diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index b1ab2c6..bb482ea 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -1,3 +1,6 @@ +{"_type":"issue","id":"islandflow-xkq","title":"Rebuild production dashboard options news around mock9 aesthetic","description":"Reconstruct the production web UI for Dashboard, Options, and News around the mock9 through mock12 dense terminal aesthetic while preserving production data subscriptions, drawers, virtualization, route helpers, redirects, and validation.","status":"closed","priority":1,"issue_type":"feature","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-13T14:07:34Z","created_by":"dirtydishes","updated_at":"2026-06-13T14:26:46Z","started_at":"2026-06-13T14:07:53Z","closed_at":"2026-06-13T14:26:46Z","close_reason":"Rebuilt Dashboard, Options, and News around the dense mock9 to mock12 production aesthetic; tests and build passed, and Browser visual inspection was documented as blocked by the unavailable in-app browser backend.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-u45","title":"Patch CVE-related dependency and Docker image findings","description":"Address Forgejo issues #15, #18, and #19 by upgrading the vulnerable tmp dependency resolution and moving Bun Docker images off the vulnerable oven/bun:1.3.11 base image with patched OpenSSL packages during image build.","status":"closed","priority":1,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-12T23:21:29Z","created_by":"dirtydishes","updated_at":"2026-06-12T23:23:27Z","started_at":"2026-06-12T23:22:16Z","closed_at":"2026-06-12T23:23:27Z","close_reason":"Patched Forgejo #15/#18 tmp CVE by resolving tmp@0.2.7, updated Bun Docker images and OpenSSL package upgrade layers for #19, and validated with bun audit, tests, web build, docker workspace check, and replacement image manifest inspection.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-hut","title":"Fix tmp path traversal audit finding","description":"bun audit reports GHSA-ph9p-34f9-6g65 through workspace:@islandflow/desktop via @electron-forge/cli. Update dependency resolution so tmp is at a non-vulnerable version and verify bun audit passes.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-12T22:50:18Z","created_by":"dirtydishes","updated_at":"2026-06-12T22:58:59Z","started_at":"2026-06-12T22:58:33Z","closed_at":"2026-06-12T22:58:59Z","close_reason":"Fixed by bumping the root tmp override to ^0.2.6, refreshing bun.lock to tmp@0.2.7, and validating with bun audit plus bun test. Forgejo issue listing was inaccessible from this environment, so the branch targets the active audit finding visible on current main.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-9ur","title":"address forgejo issue 15 tmp cve","description":"Track remediation for Forgejo issue #15: update tmp from vulnerable 0.2.5 to patched 0.2.6+ via root override and refreshed Bun lockfile, then validate with audit/tests.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-01T17:32:18Z","created_by":"dirtydishes","updated_at":"2026-06-01T17:36:01Z","started_at":"2026-06-01T17:32:23Z","closed_at":"2026-06-01T17:36:01Z","close_reason":"Resolved Forgejo issue #15 by bumping the tmp override to ^0.2.6, refreshing bun.lock to tmp@0.2.7, and validating with bun audit, bun why tmp, and bun test.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-m3d","title":"fix docs mirroring to github pages","description":"The repository docs folder is supposed to mirror to dirtydishes.github.io for GitHub Pages, but the mirroring is not working. Investigate the docs publishing workflow and repair the configuration or scripts so docs can be published reliably.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-31T22:05:48Z","created_by":"dirtydishes","updated_at":"2026-05-31T22:12:26Z","started_at":"2026-05-31T22:05:56Z","closed_at":"2026-05-31T22:12:26Z","close_reason":"Updated docs Pages workflow to publish into dirtydishes/dirtydishes.github.io under islandflow/docs, tightened docs index generation, regenerated docs index, and documented validation/limitations.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-2op","title":"[bug] Desktop app unclickable and no live data in hosted shell","description":"## Summary\\nDesktop Electron shell appears fully non-interactive (clicks do not work) and no live market data reaches the UI.\\n\\n## Why this matters\\nDesktop wrapper is currently unusable for core workflow and blocks users from validating market streams outside browser.\\n\\n## Scope\\nReproduce issue locally, identify root cause(s) in Electron shell and frontend integration, implement fix, and validate interactivity + data flow end-to-end.\\n\\n## Acceptance Criteria\\n- Desktop app responds to pointer interactions (navigation/actions clickable)\\n- Live data stream connects and updates UI in desktop mode\\n- Regression coverage or guardrails added where practical\\n- Findings and validation documented","status":"in_progress","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-24T04:23:55Z","created_by":"dirtydishes","updated_at":"2026-05-24T04:23:57Z","started_at":"2026-05-24T04:23:57Z","dependency_count":0,"dependent_count":0,"comment_count":0} @@ -27,6 +30,16 @@ {"_type":"issue","id":"islandflow-ayo","title":"Drop stale backlog events from live fanout","description":"Follow-up to live freshness rollout: /ws/live was still fanning out stale backlog events for freshness-gated channels, which kept tape panes in Live feed behind despite active synthetic ingest. Gate fanout and cache ingest by freshness for options/nbbo/equities/flow.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-04-28T21:26:39Z","created_by":"dirtydishes","updated_at":"2026-04-28T21:26:44Z","started_at":"2026-04-28T21:26:44Z","closed_at":"2026-04-28T21:26:44Z","close_reason":"Completed","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-0v6","title":"Fix tape freshness, NBBO coverage, pause controls, and filter popup","description":"Implement the tape fixes requested for synthetic options notional sizing, strict live freshness, live-mode pause/resume behavior, stronger NBBO snapshot coverage, and moving flow filters behind a popup. Includes server-side live cache changes, web terminal state/UI changes, and tests for synthetic pricing, live snapshot freshness/NBBO retention, and live pause/filter interactions.","status":"closed","priority":1,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-04-28T21:02:52Z","created_by":"dirtydishes","updated_at":"2026-04-28T21:13:38Z","started_at":"2026-04-28T21:02:57Z","closed_at":"2026-04-28T21:13:38Z","close_reason":"Completed","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-e4r","title":"Implement smart-money flow filtering and synthetic firehose modes","description":"Implement the approved multi-surface plan for named synthetic market profiles, options raw-vs-signal filtering, live/API filter contracts, Tape page client-side flow filters, firehose-readiness improvements, tests, and README updates.","status":"closed","priority":1,"issue_type":"feature","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-04-28T20:10:49Z","created_by":"dirtydishes","updated_at":"2026-04-28T20:29:29Z","started_at":"2026-04-28T20:10:53Z","closed_at":"2026-04-28T20:29:29Z","close_reason":"Implemented synthetic market profiles, options signal-path filtering, signal-aware API/replay contracts, Tape page filters, tests, and README updates. Follow-up tracked in islandflow-biq.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-9gb","title":"Rename news route to Newswire","description":"Follow-up to the mock9 production terminal rebuild: rename the /news route title from Wire Control to Newswire and keep the visual verification/docs aligned with the latest user-facing label.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-13T14:33:30Z","created_by":"dirtydishes","updated_at":"2026-06-13T14:37:01Z","started_at":"2026-06-13T14:33:42Z","closed_at":"2026-06-13T14:37:01Z","close_reason":"Renamed the /news route to Newswire, updated the design record and turn document, decoded common provider HTML entities in news text, and validated with focused web tests, production build, and Helium fitted/narrow inspection.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-iil","title":"Replace overview with dashboard command page","description":"Turn the mock9 Market Command concept into the production root dashboard, rename the visible route from Home to Dashboard, and keep the layout dense with a chart-first command surface.","acceptance_criteria":"Root page displays Dashboard instead of Home; dashboard includes command metrics, chart area, decision levels, priority board, live context, feed health, dark context, and replay context; web tests and production build pass.","notes":"Implemented from the mock9 direction while preserving the existing / URL and using the existing ChartPane until proper chart implementation lands.","status":"closed","priority":2,"issue_type":"feature","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-13T07:37:56Z","created_by":"dirtydishes","updated_at":"2026-06-13T07:43:44Z","started_at":"2026-06-13T07:38:02Z","closed_at":"2026-06-13T07:43:44Z","close_reason":"dashboard replacement implemented, validated, and documented","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-7l2","title":"Configure local web and desktop to use hosted Islandflow API","description":"Local web development and the Electron desktop shell are not connecting to the VPS-hosted API reliably after a recent endpoint change. Verify the active Delta Island API hostname, update local/default configuration so bun run dev:web and desktop development target it correctly, and validate the relevant web/desktop paths.","status":"closed","priority":2,"issue_type":"bug","owner":"dishes@dpdrm.com","created_at":"2026-06-13T07:32:28Z","created_by":"dirtydishes","updated_at":"2026-06-13T07:38:19Z","closed_at":"2026-06-13T07:38:19Z","close_reason":"Configured local web and desktop development to use https://api.flow.deltaisland.io as the hosted API origin, updated docs and local ignored env, verified the API host from the VPS, passed focused tests, public API route checks, and web build. Dev-web smoke confirmed the corrected API origin but port 3000 was already occupied.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-4j7","title":"replace activity matrix with alert lineage mock","description":"Rework the confusing Activity Matrix mock into a concrete alert lineage view that shows how a selected alert formed, including evidence chain, confirming/against context, invalidations, and audit state.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-12T00:10:18Z","created_by":"dirtydishes","updated_at":"2026-06-12T00:15:45Z","started_at":"2026-06-12T00:10:21Z","closed_at":"2026-06-12T00:15:45Z","close_reason":"Replaced the abstract Activity Matrix mock with an alert lineage view that supports all-symbol scope, selected alert evidence, invalidations, and audit context.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-5bv","title":"add four dense dashboard mock routes","description":"Add four more main dashboard page mock studies in the existing terminal style: no cards, dense at-a-glance market context, and professional copy for experienced traders.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-11T23:40:25Z","created_by":"dirtydishes","updated_at":"2026-06-11T23:48:40Z","started_at":"2026-06-11T23:40:32Z","closed_at":"2026-06-11T23:48:40Z","close_reason":"Added four dense main-dashboard mock routes and validated the web build plus desktop/mobile layout overflow.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-w2y","title":"tighten mock route terminal copy","description":"Revise mock route UI copy to read like an experienced trader terminal instead of explanatory walkthrough text. Keep the existing no-card mock route work and update the existing turn document for the minor follow-up.","status":"closed","priority":2,"issue_type":"task","owner":"dishes@dpdrm.com","created_at":"2026-06-11T23:35:21Z","created_by":"dirtydishes","updated_at":"2026-06-11T23:37:45Z","closed_at":"2026-06-11T23:37:45Z","close_reason":"Tightened mock route UI copy to professional trader-terminal language and updated the existing turn document.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-q7v","title":"add four no-card mock redesign routes","description":"Add four additional mock redesign routes to the web app without replacing the existing mock1-mock4 routes. The new routes should avoid card-style structures entirely and show varied market-activity workflows grounded in the Islandflow options flow -\u003e flow packet -\u003e smart money alert reasoning model.","status":"closed","priority":2,"issue_type":"task","owner":"dishes@dpdrm.com","created_at":"2026-06-11T22:14:44Z","created_by":"dirtydishes","updated_at":"2026-06-11T22:28:22Z","closed_at":"2026-06-11T22:28:22Z","close_reason":"Added /mock5-/mock8 no-card mock redesign routes, created required turn documentation, and validated with web build plus browser DOM checks.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-2x7","title":"Redesign mock routes from the ground up","description":"Rework the /mock1 through /mock4 frontend concepts so each route has a fresh layout, navigation treatment, and palette independent of the existing terminal chrome.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-11T09:09:12Z","created_by":"dirtydishes","updated_at":"2026-06-11T09:10:42Z","started_at":"2026-06-11T09:09:17Z","closed_at":"2026-06-11T09:10:42Z","close_reason":"Implemented fresh mock redesigns for /mock1 through /mock4, bypassed the terminal shell for mock routes, verified in the in-app browser, and passed bun web build plus focused route/terminal tests.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-3vr","title":"create ground-up frontend redesign mocks","description":"Generate a set of production-quality app mock redesigns that reuse Islandflow fundamentals in new interface models for evaluation.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-11T08:10:00Z","created_by":"dirtydishes","updated_at":"2026-06-11T08:17:51Z","started_at":"2026-06-11T08:10:09Z","closed_at":"2026-06-11T08:17:51Z","close_reason":"Created four ground-up frontend redesign mock routes and documented the work.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-9ns","title":"Refine command deck header","description":"Simplify the overview command deck header after live visual iteration, keeping live status, last tick, replay switching, and active filter controls prominent at the top of the page.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-06T11:30:15Z","created_by":"dirtydishes","updated_at":"2026-06-06T11:32:07Z","started_at":"2026-06-06T11:30:25Z","closed_at":"2026-06-06T11:32:07Z","close_reason":"accepted compact command deck header from live iteration, added active filter chips with hover clear controls, and validated web build/tests","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-xmi","title":"Resolve conflicts in PR 45","description":"Resolve the merge conflicts blocking Forgejo PR 45, validate the affected code paths, and push the reconciled branch back to Forgejo.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-06T03:33:52Z","created_by":"dirtydishes","updated_at":"2026-06-06T03:35:16Z","started_at":"2026-06-06T03:33:58Z","closed_at":"2026-06-06T03:35:16Z","close_reason":"Resolved the PR 45 merge conflict in .beads/issues.jsonl and validated the reconciled tracker file.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-8a6","title":"verify github pages token for docs mirror","description":"The docs mirror workflow now publishes islandflow/docs into dirtydishes/dirtydishes.github.io, but the GitHub Actions secret DOCS_PAGES_TOKEN must exist and have permission to push to that Pages repository. Verify the secret is configured and manually run the Publish Docs workflow after the mirror branch lands.","notes":"Direct manual publish to dirtydishes/dirtydishes.github.io succeeded on 2026-06-01 and https://dirtydishes.github.io/islandflow/docs/ returned HTTP 200. Remaining work is to verify DOCS_PAGES_TOKEN so the islandflow docs mirror workflow can publish future updates automatically.","status":"open","priority":2,"issue_type":"task","owner":"dishes@dpdrm.com","created_at":"2026-05-31T22:12:27Z","created_by":"dirtydishes","updated_at":"2026-06-01T13:45:34Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-5jt","title":"Add anatomy reference page","description":"Create a standalone docs/anatomy.html reference explaining how prints move through ingest, tape, flow packets, smart-money events, classifier hits, and alerts, including diagrams.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-31T21:20:34Z","created_by":"dirtydishes","updated_at":"2026-05-31T21:25:54Z","started_at":"2026-05-31T21:20:44Z","closed_at":"2026-05-31T21:25:54Z","close_reason":"Added the standalone anatomy reference page and linked it from the docs index.","dependency_count":0,"dependent_count":0,"comment_count":0} @@ -108,6 +121,9 @@ {"_type":"issue","id":"islandflow-zs0","title":"Migrate terminal UI to smart-money profiles","description":"Migrate apps/web terminal rendering to consume SmartMoneyEvent directly: primary profile, probability ladder, reason codes, and suppression/abstention state, while preserving legacy alert/classifier displays during the bridge.","status":"closed","priority":2,"issue_type":"task","owner":"dishes@dpdrm.com","created_at":"2026-05-04T21:35:23Z","created_by":"dirtydishes","updated_at":"2026-05-05T05:39:58Z","closed_at":"2026-05-05T05:39:58Z","close_reason":"Completed terminal smart-money profile migration","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-igk","title":"Add plan mode","description":"Implement a user-facing plan mode in the application so users can switch into planning before taking action. Scope to be clarified from existing app patterns.","status":"closed","priority":2,"issue_type":"feature","owner":"dishes@dpdrm.com","created_at":"2026-05-04T04:22:37Z","created_by":"dirtydishes","updated_at":"2026-05-04T04:26:18Z","started_at":"2026-05-04T04:22:40Z","closed_at":"2026-05-04T04:26:18Z","close_reason":"Implemented as a global pi extension toggled with Shift+P","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-biq","title":"Finish raw live options delivery and filter/backpressure observability","description":"The smart-money signal path and Tape filters are in place, but the next firehose pass should finish server-side selective raw live delivery for options subscriptions and add explicit filtered-out/backpressure observability for API/web counters. This was discovered while landing islandflow-e4r.\n","status":"in_progress","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-04-28T20:28:58Z","created_by":"dirtydishes","updated_at":"2026-04-29T03:54:12Z","started_at":"2026-04-29T03:54:12Z","dependencies":[{"issue_id":"islandflow-biq","depends_on_id":"islandflow-e4r","type":"discovered-from","created_at":"2026-04-28T16:28:58Z","created_by":"auto-import","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-q0t","title":"Publish June 11 standup git summary","description":"## Summary\nCreate the daily git-grounded standup summary for 2026-06-11 activity in docs/general.\n\n## Why this matters\nThe team needs a scannable record of yesterday's repo activity anchored to commits, Beads items, and touched files.\n\n## Scope\nInspect June 11 commits, summarize the work in HTML under docs/general, and close the task once the document is written.","status":"closed","priority":3,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-12T13:03:42Z","created_by":"dirtydishes","updated_at":"2026-06-12T13:05:40Z","started_at":"2026-06-12T13:03:45Z","closed_at":"2026-06-12T13:05:40Z","close_reason":"Created docs/general/2026-06-12-0903-standup-summary-2026-06-11.html with a commit-grounded summary of June 11 activity.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-ksr","title":"Publish June 10 standup git summary","description":"Why this issue exists and what needs to be done:\\n\\nCreate the daily standup summary for June 10, 2026 git activity in docs/general, grounded in commits and touched files, then commit and push the documentation update.","status":"closed","priority":3,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-11T13:02:18Z","created_by":"dirtydishes","updated_at":"2026-06-11T13:04:10Z","started_at":"2026-06-11T13:02:35Z","closed_at":"2026-06-11T13:04:10Z","close_reason":"Created docs/general/2026-06-11-0902-standup-summary-2026-06-10.html with a git-grounded summary of June 10 activity.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-f09","title":"Publish standup summary for 2026-06-08","description":"Why this issue exists and what needs to be done\\n\\nCreate the daily git-grounded standup summary for repository activity on 2026-06-08, save the HTML artifact in docs/general, and include only statements anchored to commits and touched files.","status":"closed","priority":3,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-09T13:02:31Z","created_by":"dirtydishes","updated_at":"2026-06-09T13:04:19Z","started_at":"2026-06-09T13:02:53Z","closed_at":"2026-06-09T13:04:19Z","close_reason":"Created docs/general/2026-06-09-0902-standup-summary-2026-06-08.html with a git-grounded summary of June 8 activity.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-5rt","title":"Summarize June 2 git activity for standup","description":"Create the daily standup summary in docs/general for 2026-06-02 activity, anchored to yesterday's commits and touched files.","status":"closed","priority":3,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-03T16:30:03Z","created_by":"dirtydishes","updated_at":"2026-06-03T16:31:33Z","started_at":"2026-06-03T16:31:26Z","closed_at":"2026-06-03T16:31:33Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-3f4","title":"Publish May 31 standup git summary","description":"## Summary\nCreate the daily standup HTML summary for 2026-05-31 git activity in docs/general and regenerate any supporting docs index entries.\n\n## Why this matters\nThe team needs a grounded, commit-anchored standup artifact for May 31 repository activity.\n\n## Scope\nInspect May 31 git history, write the summary document in docs/general, update related generated docs metadata if needed, and close out the task.","status":"closed","priority":3,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-01T13:02:21Z","created_by":"dirtydishes","updated_at":"2026-06-01T13:04:45Z","started_at":"2026-06-01T13:02:29Z","closed_at":"2026-06-01T13:04:45Z","close_reason":"Added docs/general standup summary for 2026-05-31 and verified docs index discovery.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-6ak","title":"Clarify turn doc diff rendering instructions","description":"Make AGENTS.md explicit that turn documents should render diffs with the @pierre/diffs/ssr library import instead of attempting to run @pierre/diffs through bunx.","status":"closed","priority":3,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-30T02:01:59Z","created_by":"dirtydishes","updated_at":"2026-05-30T02:02:27Z","started_at":"2026-05-30T02:02:00Z","closed_at":"2026-05-30T02:02:27Z","close_reason":"Updated AGENTS.md to require @pierre/diffs/ssr rendering, forbid bunx @pierre/diffs attempts, and include a known-good preloadPatchDiff recipe.","dependency_count":0,"dependent_count":0,"comment_count":0} @@ -127,6 +143,8 @@ {"_type":"issue","id":"islandflow-zsy","title":"Expose Forgejo SSH on a direct DNS hostname","description":"git.deltaisland.io currently resolves through Cloudflare's proxy, so SSH on port 2222 does not complete even though the Forgejo container is listening on the host. If SSH-based git/beads workflows are desired, add a DNS-only hostname (or adjust the existing record) that points directly at the server for Forgejo SSH.","status":"open","priority":3,"issue_type":"task","created_at":"2026-05-17T10:34:06Z","created_by":"delta","updated_at":"2026-05-17T10:34:06Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-38p","title":"Add native deployment unit templates and rollback helpers","description":"The deploy helper now supports --runtime native, but the repo still relies on operator-managed systemd units and manual rollback. Add checked-in native deployment templates or provisioning guidance for the expected units, and consider lightweight rollback/smoke-test helpers once the host-native path is exercised on the real VPS.","status":"open","priority":3,"issue_type":"task","owner":"dishes@dpdrm.com","created_at":"2026-05-15T23:46:42Z","created_by":"dirtydishes","updated_at":"2026-05-15T23:46:42Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-575","title":"Document smart-money event calendar env","description":"Document smart-money event-calendar environment configuration in env examples and README.\n","status":"closed","priority":3,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-05T06:57:14Z","created_by":"dirtydishes","updated_at":"2026-05-05T06:57:57Z","started_at":"2026-05-05T06:57:17Z","closed_at":"2026-05-05T06:57:57Z","close_reason":"Documented event-calendar env variables","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-iwg","title":"Summarize June 9 git activity for standup","description":"Create the daily standup summary for git activity on 2026-06-09, grounded in commits and touched files, and save the report in docs/general.","status":"closed","priority":4,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-10T13:02:19Z","created_by":"dirtydishes","updated_at":"2026-06-10T13:04:44Z","started_at":"2026-06-10T13:02:30Z","closed_at":"2026-06-10T13:04:44Z","close_reason":"Created docs/general/2026-06-10-0902-standup-summary-2026-06-09.html with a git-grounded summary of June 9 activity.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-19f","title":"Summarize June 7 git activity for standup","description":"Create the daily standup summary for yesterday's git activity, grounded in commits and changed files, and save the report in docs/general.","status":"closed","priority":4,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-08T13:01:02Z","created_by":"dirtydishes","updated_at":"2026-06-08T13:03:00Z","started_at":"2026-06-08T13:01:15Z","closed_at":"2026-06-08T13:03:00Z","close_reason":"Standup summary for 2026-06-07 created in docs/general with grounded git-history validation.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-a1m","title":"Publish June 3 standup summary","description":"Why this issue exists and what needs to be done:\\n- Produce the daily standup summary for git activity on 2026-06-03.\\n- Ground every statement in commits and touched files only.\\n- Save the HTML artifact under docs/general and complete the automation handoff workflow.","status":"closed","priority":4,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-04T13:02:04Z","created_by":"dirtydishes","updated_at":"2026-06-04T13:03:43Z","started_at":"2026-06-04T13:03:34Z","closed_at":"2026-06-04T13:03:43Z","close_reason":"Created docs/general/2026-06-04-standup-summary-2026-06-03.html with a commit-grounded summary of June 3 git activity.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-0jb","title":"Publish June 1 standup summary","description":"Why this issue exists and what needs to be done:\\n- Produce the daily standup summary for git activity on 2026-06-01.\\n- Ground every statement in commits and touched files only.\\n- Save the HTML artifact under docs/general and complete the automation handoff workflow.","status":"closed","priority":4,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-06-02T13:03:01Z","created_by":"dirtydishes","updated_at":"2026-06-02T13:05:51Z","started_at":"2026-06-02T13:03:16Z","closed_at":"2026-06-02T13:05:51Z","close_reason":"Created docs/general/2026-06-02-standup-summary-2026-06-01.html with a commit-grounded June 1 standup summary.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-1tu","title":"Publish 2026-05-24 standup summary","description":"Why this issue exists and what needs to be done\n\nCreate the daily standup summary for git activity on 2026-05-24, grounded in commits and touched files, then store the HTML report in docs/general.","status":"closed","priority":4,"issue_type":"task","owner":"dishes@dpdrm.com","created_at":"2026-05-25T13:02:56Z","created_by":"dirtydishes","updated_at":"2026-05-25T13:04:31Z","closed_at":"2026-05-25T13:04:31Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} diff --git a/DESIGN.md b/DESIGN.md index d1f2a68..2ed68d4 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -75,11 +75,11 @@ components: typography: "{typography.label}" rounded: "{rounded.md}" padding: "12px 14px" - pane-surface: + terminal-section: backgroundColor: "{colors.bg-pane}" textColor: "{colors.text-primary}" - rounded: "{rounded.xl}" - padding: "16px 18px" + rounded: "0" + padding: "8px 10px" status-chip: backgroundColor: "{colors.bg-soft}" textColor: "{colors.text-primary}" @@ -98,6 +98,8 @@ Islandflow's interface behaves like an investigation instrument, not a presentat The visual atmosphere is dark and controlled, with amber used as a directional signal rather than ambient decoration. Surfaces are compact and information-dense, but each zone is explicit about purpose so the user can move from detection to validation without losing context. +The production aesthetic is now centered on mock9 through mock12: table-first command surfaces, dense route-specific operating boards, border-block separation, minimal radius, and no dashboard-card composition as the default. Mock5 remains the workflow reference for Options only: OPRA intake, contract focus, filter controls, and packet eligibility. + This system explicitly rejects the anti-references in PRODUCT.md: no meme-stock hype aesthetics, no generic SaaS card fog, and no Bloomberg cosplay density unless density is earning its keep with decision value. **Key Characteristics:** @@ -106,6 +108,8 @@ This system explicitly rejects the anti-references in PRODUCT.md: no meme-stock - Accent color treated as scarce signal. - Monospace-assisted precision for time, numeric, and status data. - Readability preserved during bursty live updates. +- Route-specific signatures: Dashboard is Market Command, Options is OPRA Intake, News is Newswire. +- Flat terminal sections: border-block dividers and compact headers are the default; rounded cards are not. ## Colors @@ -187,13 +191,19 @@ The system is flat by default. Depth is primarily tonal (background and border d - **Style:** pill chips (`999px`) with thin border and semantic soft fill. - **State:** direction/severity/status chips map to green/red/blue semantic channels with text labels always present. -### Cards / Containers +### Sections / Containers -- **Corner Style:** medium-soft corners (`12px` or `14px`) depending on container prominence. -- **Background:** layered dark surfaces (`#111820`, `#0d141b`) with restrained top-to-bottom sheen. -- **Shadow Strategy:** no default card shadow; only overlays and floating inspectors use lift shadows. -- **Border:** subtle perimeter lines (`rgba(255,255,255,0.08)` baseline). -- **Internal Padding:** primarily `16px-18px` with tighter inner rhythm (`8px-12px`) for controls. +- **Default Shape:** square terminal sections (`0px radius`) with border-block dividers. +- **Background:** flat dark surfaces (`#111820`, `#0d141b`) with tonal contrast only. +- **Shadow Strategy:** no shadows on production route sections; only drawers, popovers, and tooltips use lift shadows. +- **Border:** top/bottom rules carry separation; perimeter boxes are reserved for true tables, overlays, and controls that need hit-area clarity. +- **Internal Padding:** primarily `8px-12px` so rows, headers, and controls stay dense. + +### Route Signatures + +- **Dashboard / Market Command:** command metrics, priority board, decision levels, chart context, source health, recent contracts, replay state, and evidence context in one dense operating board. +- **Options / OPRA Intake:** production `OptionsPane` and `FlowPane` remain the source of truth, with TanStack virtual rows, contract focus, scroll gates, and filters tuned for option decision work. +- **News / Newswire:** virtualized wire rows, source rails, symbol rails, live-only state, older-history scroll gates, and the existing news drawer. ### Inputs / Fields @@ -220,6 +230,8 @@ The system is flat by default. Depth is primarily tonal (background and border d - **Do** use amber as a sparse decision signal for active controls, focus rails, and key counters. - **Do** keep overlays visually separated with dedicated shadow roles while leaving primary panes flat. - **Do** design live updates to avoid flashing, excessive animation, and layout shifts during high-volume periods. +- **Do** prefer dense tables, rails, and flat sections for production routes. +- **Do** let each primary route have a tasteful accent and layout signature without duplicating the data model. ### Don't: @@ -228,3 +240,4 @@ The system is flat by default. Depth is primarily tonal (background and border d - **Don't** make Islandflow feel like Bloomberg-style visual density used as aesthetic cosplay instead of as a genuinely useful information structure. - **Don't** rely on red/green alone for directional meaning or severity. - **Don't** use colored side-stripe accents on rows/cards as the primary signifier; use complete semantic chips and labels instead. +- **Don't** default to card grids, decorative shadows, hero treatments, or static mock copy in production routes. diff --git a/apps/web/app/dashboard-mocks.tsx b/apps/web/app/dashboard-mocks.tsx index 1c23bb1..a0a268a 100644 --- a/apps/web/app/dashboard-mocks.tsx +++ b/apps/web/app/dashboard-mocks.tsx @@ -1,491 +1,1332 @@ import Link from "next/link"; import type { CSSProperties, ReactNode } from "react"; -type MockVariant = "mock1" | "mock2" | "mock3" | "mock4"; +type MockVariant = + | "mock1" + | "mock2" + | "mock3" + | "mock4" + | "mock5" + | "mock6" + | "mock7" + | "mock8" + | "mock9" + | "mock10" + | "mock11" + | "mock12"; type DashboardMockProps = { variant: MockVariant; }; -const variants: Record< - MockVariant, - { - title: string; - premise: string; - mode: string; - layout: string; - } -> = { +type Concept = { + title: string; + shortName: string; + routeName: string; + premise: string; + bodyClass: string; +}; + +const concepts: Record = { mock1: { - title: "Command Deck", - premise: - "Closest to the reference: left navigation, ticker ribbon, dense evidence panes, replay rail.", - mode: "Dense ops", - layout: "classic" + title: "Signal Docket", + shortName: "Docket", + routeName: "Case Tape", + premise: "Active claims, confirms, contra-flow, and invalidation marks on one symbol docket.", + bodyClass: "mock-court" }, mock2: { - title: "Investigation Stack", - premise: - "A calmer analyst layout with the selected symbol story in the center and context wrapped around it.", - mode: "Forensic", - layout: "focus" + title: "Alert Queue", + shortName: "Desk", + routeName: "Desk Queue", + premise: "Ranked live signals by urgency, source state, and tape confirmation.", + bodyClass: "mock-desk" }, mock3: { - title: "Signal Wall", - premise: - "Prioritizes alert triage and cross-symbol scanning before a user drills into price action.", - mode: "Triage", - layout: "signals" + title: "Replay Tape", + shortName: "Replay", + routeName: "Tape Review", + premise: "Frame-locked replay across prints, candles, packet state, and notes.", + bodyClass: "mock-theatre" }, mock4: { - title: "Replay Lab", + title: "Pressure Map", + shortName: "Map", + routeName: "Cross-Market", + premise: "Sector heat, linked symbols, and flow clusters before single-name drilldown.", + bodyClass: "mock-map" + }, + mock5: { + title: "OPRA Intake", + shortName: "Options", + routeName: "OPRA", + premise: "Contract tape, premium concentration, sweep shape, ask lift, and packet eligibility.", + bodyClass: "mock-options" + }, + mock6: { + title: "Packet Stack", + shortName: "Packets", + routeName: "Packets", + premise: "Flow packets scored by options burst, tape response, venue mix, and sector echo.", + bodyClass: "mock-packets" + }, + mock7: { + title: "Alert Blotter", + shortName: "Alerts", + routeName: "Alerts", + premise: "Smart-money alerts with trigger, read type, severity, and invalidation level.", + bodyClass: "mock-alerts" + }, + mock8: { + title: "Alert Lineage", + shortName: "Lineage", + routeName: "Signal Trace", premise: - "A replay-first structure with timeline, event tape, and causality context always visible.", - mode: "Replay", - layout: "replay" + "Selected alert formation from raw prints through packet, confirmation, invalidation, and replay audit.", + bodyClass: "mock-graph" + }, + mock9: { + title: "Market Command", + shortName: "Command", + routeName: "Main Board", + premise: + "Session regime, priority symbols, active packets, and invalidation levels without route switching.", + bodyClass: "mock-command" + }, + mock10: { + title: "Signal Radar", + shortName: "Radar", + routeName: "Signal Radar", + premise: + "Cross-symbol pressure ranked by confirmation, decay, source count, and nearest decision level.", + bodyClass: "mock-radar" + }, + mock11: { + title: "Risk Ledger", + shortName: "Risk", + routeName: "Risk Ledger", + premise: + "Directional exposure, live invalidations, sector crowding, and stale assumptions in one operating view.", + bodyClass: "mock-risk" + }, + mock12: { + title: "Source Control", + shortName: "Sources", + routeName: "Source Control", + premise: + "Feed quality, lag, packet eligibility, route pressure, and replay gaps for the current session.", + bodyClass: "mock-source" } }; -const tickers = [ - ["SPY", "529.18", "+0.23%", "up"], - ["QQQ", "452.47", "+0.31%", "up"], - ["AAPL", "194.88", "+1.22%", "up"], - ["NVDA", "120.19", "-0.41%", "down"], - ["TSLA", "180.72", "+0.72%", "up"], - ["AMZN", "186.31", "+0.35%", "up"], - ["IWM", "205.41", "+0.21%", "up"] +const variantOrder: MockVariant[] = [ + "mock1", + "mock2", + "mock3", + "mock4", + "mock5", + "mock6", + "mock7", + "mock8", + "mock9", + "mock10", + "mock11", + "mock12" +]; + +const symbols = [ + { + symbol: "AAPL", + price: "194.88", + move: "+1.22%", + direction: "up", + score: 94, + sector: "Mega cap tech" + }, + { + symbol: "NVDA", + price: "120.19", + move: "-0.41%", + direction: "down", + score: 81, + sector: "AI semis" + }, + { + symbol: "TSLA", + price: "180.72", + move: "+0.72%", + direction: "up", + score: 76, + sector: "EV complex" + }, + { + symbol: "AMZN", + price: "186.31", + move: "+0.35%", + direction: "up", + score: 68, + sector: "Consumer platform" + }, + { + symbol: "IWM", + price: "205.41", + move: "+0.21%", + direction: "up", + score: 59, + sector: "Small caps" + } +]; + +const anomalies = [ + { + time: "09:41:10", + symbol: "AAPL", + title: "Dark sweep aligns with call pressure", + value: "$4.32M", + confidence: "High", + direction: "Bullish", + cause: "off-exchange prints led the options burst by 72s" + }, + { + time: "09:40:58", + symbol: "NVDA", + title: "Call wall absorbed at 120", + value: "$2.01M", + confidence: "Medium", + direction: "Mixed", + cause: "quote lift faded after the second split sweep" + }, + { + time: "09:39:47", + symbol: "TSLA", + title: "Momentum classifier fired", + value: "91%", + confidence: "High", + direction: "Bullish", + cause: "volume acceleration exceeded five-session baseline" + }, + { + time: "09:39:12", + symbol: "AMZN", + title: "Large block against tape", + value: "$3.67M", + confidence: "Watch", + direction: "Bearish", + cause: "print direction diverged from sector basket" + } +]; + +const evidence = [ + ["Options", "195 C sweep", "$2.31M", "Bullish"], + ["Equity", "25,000 dark buy", "$4.87M", "Bullish"], + ["News", "AI update crossed", "09:40:21", "Info"], + ["Tape", "Momentum burst", "+1.22%", "Bullish"], + ["Venue", "Off-exchange share", "64%", "Watch"] ]; const optionRows = [ - ["2m", "AAPL", "May 17", "195 C", "5,240", "$2.31M", "Sweep", "Bullish"], - ["3m", "AAPL", "Jun 21", "200 C", "6,800", "$1.87M", "Block", "Bullish"], - ["4m", "NVDA", "May 24", "120 C", "9,150", "$2.01M", "Split", "Bullish"], - ["5m", "TSLA", "Jul 19", "205 C", "10,000", "$3.45M", "Block", "Bullish"], - ["6m", "AMZN", "May 17", "185 P", "4,500", "$1.20M", "Sweep", "Bearish"], - ["7m", "IWM", "Jun 21", "207 C", "3,100", "$712K", "Sweep", "Bullish"], - ["8m", "AAPL", "May 24", "197.5 C", "7,600", "$2.01M", "Block", "Bullish"] + ["2m", "AAPL", "May 17 195 C", "5,240", "$2.31M", "Sweep", "Bullish"], + ["3m", "AAPL", "Jun 21 200 C", "6,800", "$1.87M", "Block", "Bullish"], + ["4m", "NVDA", "May 24 120 C", "9,150", "$2.01M", "Split", "Mixed"], + ["5m", "TSLA", "Jul 19 205 C", "10,000", "$3.45M", "Block", "Bullish"], + ["6m", "AMZN", "May 17 185 P", "4,500", "$1.20M", "Sweep", "Bearish"] ]; -const signals = [ - ["09:41:10", "Dark Flow Sweep", "AAPL", "$4.32M", "Bullish"], - ["09:40:58", "Unusual Options Activity", "NVDA", "$2.01M", "Bullish"], - ["09:40:21", "News Catalyst", "AAPL", "AI update", "News"], - ["09:39:47", "Classifier Hit: Momentum", "TSLA", "91%", "Bullish"], - ["09:39:12", "Large Block Trade", "AMZN", "$3.67M", "Bearish"] +const health = [ + ["OPRA", "healthy", "120ms"], + ["CBOE", "healthy", "85ms"], + ["NYSE", "degraded", "412ms"], + ["News", "healthy", "1.2s"] ]; -const feedHealth = [ - ["OPRA Options", "Healthy", "120ms", "2,341"], - ["CBOE Quotes", "Healthy", "85ms", "1,987"], - ["Nasdaq TotalView", "Healthy", "92ms", "3,102"], - ["NYSE Pillar", "Degraded", "412ms", "932"], - ["News", "Healthy", "1.2s", "12"], - ["Dark Pool", "Healthy", "1.0s", "421"] +const timeline = [ + ["09:36", "Baseline drift", "AAPL and QQQ correlation widens"], + ["09:39", "First print", "Dark block appears before visible call lift"], + ["09:41", "Signal fired", "Sweep pressure confirms the print cluster"], + ["09:45", "Replay note", "Price accepted above prior liquidity shelf"] ]; -const darkFlow = [ - ["09:41:05", "AAPL", "Buy", "25,000", "$4.87M", "Sweep"], - ["09:40:51", "AAPL", "Buy", "18,500", "$3.60M", "Sweep"], - ["09:40:35", "AAPL", "Sell", "30,000", "$5.84M", "Block"], - ["09:39:59", "AAPL", "Buy", "12,000", "$2.34M", "Sweep"], - ["09:38:47", "AAPL", "Sell", "21,000", "$4.09M", "Block"] +const atlasGroups = [ + { + name: "Mega cap tech", + heat: 92, + flow: "+$8.4M", + symbols: ["AAPL", "MSFT", "AMZN"], + x: 16, + y: 22 + }, + { name: "AI semis", heat: 81, flow: "+$5.1M", symbols: ["NVDA", "AMD", "AVGO"], x: 64, y: 26 }, + { + name: "Beta basket", + heat: 66, + flow: "+$3.8M", + symbols: ["TSLA", "COIN", "PLTR"], + x: 34, + y: 66 + }, + { name: "Defensive", heat: 38, flow: "-$1.2M", symbols: ["XLU", "XLV", "PG"], x: 74, y: 70 } ]; -const variantOrder: MockVariant[] = ["mock1", "mock2", "mock3", "mock4"]; +const intakeRows = [ + [ + "09:41:23.420", + "AAPL", + "17MAY24 195C", + "12,480", + "$4.32M", + "sweep", + "61%", + "+3.8σ", + "candidate" + ], + [ + "09:41:18.092", + "AAPL", + "21JUN24 200C", + "8,920", + "$2.74M", + "split sweep", + "58%", + "+2.9σ", + "join" + ], + [ + "09:40:52.774", + "QQQ", + "17MAY24 458C", + "19,600", + "$5.10M", + "block lift", + "49%", + "+2.1σ", + "confirm" + ], + ["09:40:11.018", "NVDA", "24MAY24 120C", "7,340", "$2.01M", "iso sweep", "42%", "+1.7σ", "watch"], + [ + "09:39:47.660", + "TSLA", + "19JUL24 205C", + "10,000", + "$3.45M", + "block", + "38%", + "+2.4σ", + "candidate" + ], + ["09:39:12.105", "AMZN", "17MAY24 185P", "4,500", "$1.20M", "sweep", "36%", "-1.9σ", "reject"], + ["09:38:59.443", "IWM", "17MAY24 205C", "14,250", "$1.92M", "multi-leg", "31%", "+1.4σ", "watch"] +]; + +const packetSteps = [ + { + label: "options burst", + time: "09:41:23", + weight: 92, + detail: "AAPL 195C + 200C clustered inside 72s with ask-side pressure" + }, + { + label: "equity trace", + time: "09:41:48", + weight: 74, + detail: "25k dark buy and visible bid lift hold above 194.50" + }, + { + label: "venue mix", + time: "09:42:06", + weight: 68, + detail: "Off-exchange share at 64%, above session baseline by 18 points" + }, + { + label: "sector echo", + time: "09:42:31", + weight: 57, + detail: "QQQ confirms, semis neutral, no broad risk-off objection" + }, + { + label: "packet ready", + time: "09:42:44", + weight: 86, + detail: "SMP candidate: stealth accumulation into short-dated calls" + } +]; + +const packetRows = [ + ["PKT-8841", "AAPL", "ready", "5 sources", "stealth accumulation", "86"], + ["PKT-8838", "TSLA", "building", "3 sources", "momentum ignition", "71"], + ["PKT-8834", "NVDA", "held", "2 sources", "call wall absorption", "63"], + ["PKT-8827", "AMZN", "rejected", "2 sources", "put sweep divergence", "39"] +]; + +const alertRows = [ + [ + "09:42:51", + "AAPL", + "SMP Alert", + "stealth accumulation", + "options led stock by 72s; dark share elevated", + "accept above 194.50", + "high" + ], + [ + "09:41:58", + "TSLA", + "Ignition Watch", + "momentum ignition", + "block call buy plus tape acceleration", + "fails below 178.80", + "medium" + ], + [ + "09:40:34", + "NVDA", + "Absorption", + "call wall defense", + "buyers absorbed at 120 but price did not expand", + "rejects 120.40", + "watch" + ], + [ + "09:39:22", + "AMZN", + "Divergence", + "put sweep against basket", + "bearish premium while sector bid held", + "reclaims 186.20", + "low" + ] +]; + +const lineageScope = [ + ["Scope", "All symbols", "ranked formations"], + ["Focus", "AAPL SMP", "top active alert"], + ["Valid", "above 194.50", "QQQ above 458.20"], + ["Packet", "PKT-8841", "86 / 5 sources"] +]; + +const lineageQueue = [ + ["09:42:51", "AAPL", "SMP Alert", "86", "stealth accumulation", "active"], + ["09:41:58", "TSLA", "Ignition Watch", "71", "momentum ignition", "watch"], + ["09:40:34", "NVDA", "Absorption", "63", "call wall defense", "hold"], + ["09:39:22", "AMZN", "Divergence", "39", "put sweep against basket", "reject"] +]; + +const lineageEvents = [ + ["09:41:23.420", "OPRA", "17MAY 195C sweep", "$4.32M", "ask 61%", "confirming"], + ["09:41:48.018", "Equity", "dark buy cluster", "$4.87M", "off-ex 64%", "confirming"], + ["09:42:06.130", "Packet", "PKT-8841 ready", "86", "5 sources", "confirming"], + ["09:42:31.004", "Market", "QQQ confirms", "458.20 held", "semis neutral", "confirming"], + ["09:42:51.000", "Alert", "SMP fired", "high", "valid above 194.50", "active"] +]; + +const lineageChecks = [ + ["Options lead", "OPRA led stock by 72s", "confirming"], + ["Dark share", "+18 pts vs session baseline", "confirming"], + ["Market", "QQQ supportive; semis neutral", "confirming"], + ["Contra", "AMZN put sweep remains isolated", "against"], + ["Replay", "synced through alert frame", "audit"] +]; + +const lineageInvalidations = [ + ["AAPL", "194.50", "alert invalid"], + ["QQQ", "458.20", "market confirm fails"], + ["Packet", "2 source loss", "score below 70"] +]; + +const commandMetrics = [ + ["Regime", "Risk-on, narrow", "QQQ +0.82%, IWM lagging"], + ["Priority", "AAPL / TSLA / NVDA", "3 packets above 70"], + ["Decision", "194.50 AAPL", "acceptance level"], + ["Risk", "AMZN contra", "put sweep against basket"] +]; + +const commandRows = [ + ["09:42:51", "AAPL", "PKT-8841", "stealth accumulation", "86", "194.50", "confirm"], + ["09:41:58", "TSLA", "PKT-8838", "momentum ignition", "71", "178.80", "watch"], + ["09:40:34", "NVDA", "PKT-8834", "call wall absorption", "63", "120.40", "hold"], + ["09:39:22", "AMZN", "PKT-8827", "put divergence", "39", "186.20", "reject"], + ["09:38:59", "IWM", "PKT-8821", "small-cap echo", "44", "205.00", "watch"] +]; + +const commandLevels = [ + ["AAPL", "194.50", "above", "packet valid"], + ["QQQ", "458.20", "above", "market confirm"], + ["NVDA", "120.40", "below", "absorption fails"], + ["TSLA", "178.80", "above", "ignition intact"] +]; + +const radarRows = [ + ["AAPL", "92", "5", "00:29", "ask lift", "194.50", "bullish"], + ["TSLA", "78", "3", "01:14", "block call", "178.80", "bullish"], + ["NVDA", "64", "2", "02:06", "absorbed", "120.40", "watch"], + ["AMZN", "41", "2", "03:51", "put sweep", "186.20", "bearish"], + ["IWM", "38", "1", "05:08", "basket lag", "205.00", "watch"] +]; + +const radarBands = [ + { label: "Mega cap tech", score: 88, symbols: "AAPL MSFT AMZN", tone: "good" }, + { label: "AI semis", score: 63, symbols: "NVDA AMD AVGO", tone: "watch" }, + { label: "Beta", score: 74, symbols: "TSLA COIN PLTR", tone: "info" }, + { label: "Small caps", score: 38, symbols: "IWM KRE XBI", tone: "bad" } +]; + +const riskRows = [ + ["Long delta", "$12.8M", "AAPL / TSLA", "+18%", "194.50 fail"], + ["Short premium", "$3.1M", "AMZN puts", "+6%", "186.20 reclaim"], + ["Crowded calls", "$8.4M", "front-week tech", "+31%", "QQQ loses 458.20"], + ["Replay debt", "2 gaps", "09:36-09:39", "open", "audit before alert"] +]; + +const riskInvalidations = [ + ["AAPL", "194.50", "2 ticks", "live"], + ["QQQ", "458.20", "5 ticks", "live"], + ["TSLA", "178.80", "14 ticks", "watch"], + ["AMZN", "186.20", "9 ticks", "against"] +]; + +const sourceRows = [ + ["OPRA", "120ms", "99.98%", "eligible", "1,284/s"], + ["CTA", "84ms", "99.99%", "eligible", "422/s"], + ["NYSE", "412ms", "98.10%", "degraded", "91/s"], + ["News", "1.2s", "99.20%", "eligible", "8/s"], + ["Replay", "0 gaps", "synced", "eligible", "32x"] +]; + +const sourceRoutes = [ + ["OPRA -> Packets", "clear", "AAPL 195C joined"], + ["CTA -> Alerts", "clear", "price acceptance confirmed"], + ["NYSE -> Packets", "limited", "venue lag above threshold"], + ["News -> Replay", "clear", "headline aligned at 09:40:21"] +]; export function DashboardMock({ variant }: DashboardMockProps) { - const config = variants[variant]; + const concept = concepts[variant]; return ( -
- - - {variant === "mock1" ? : null} - {variant === "mock2" ? : null} - {variant === "mock3" ? : null} - {variant === "mock4" ? : null} -
+
+ + {variant === "mock1" ? : null} + {variant === "mock2" ? : null} + {variant === "mock3" ? : null} + {variant === "mock4" ? : null} + {variant === "mock5" ? : null} + {variant === "mock6" ? : null} + {variant === "mock7" ? : null} + {variant === "mock8" ? : null} + {variant === "mock9" ? : null} + {variant === "mock10" ? : null} + {variant === "mock11" ? : null} + {variant === "mock12" ? : null} +
); } -function MockHeader({ - config, - active -}: { - config: (typeof variants)[MockVariant]; - active: MockVariant; -}) { +function MockNavigation({ active, concept }: { active: MockVariant; concept: Concept }) { return ( -
-
-
-

{config.premise}

-
- Live - NATS 3ms / US-EAST-1 - 09:41:23 ET - {config.mode} -
-
{children} ); } -function OptionTape({ condensed = false }: { condensed?: boolean }) { - const rows = condensed ? optionRows.slice(0, 5) : optionRows; - +function EvidenceStack() { return ( - -
-
- Time - Symbol - Exp - Strike - Size - Prem - Type - Score -
- {rows.map((row) => ( -
- {row.map((cell, index) => ( - - {cell} - - ))} +
+ {evidence.map(([source, title, value, tone]) => ( +
+ {source} + {title} +
+ {value} + {tone}
- ))} -
- + + ))} +
); } -function ChartPanel({ compact = false }: { compact?: boolean }) { +function ChartSketch({ density, marker }: { density: number; marker: string }) { return ( - -
+
+
+ AAPL 194.88 - +2.34 (+1.22%) + +1.22%
- ); } -function SignalPanel({ hero = false }: { hero?: boolean }) { - return ( - -
- {signals.map(([time, title, symbol, value, tag]) => ( -
- -
- {title} - - {symbol} / {value} - -
- - {tag} - -
- ))} -
-
- ); -} +function FlowRows({ compact = false }: { compact?: boolean }) { + const rows = compact ? optionRows.slice(0, 4) : optionRows; -function FeedHealth() { return ( - -
- {feedHealth.map(([feed, status, lag, rate]) => ( -
- {feed} - - {status} - - {lag} - {rate}/s -
- ))} +
+
+ Age + Symbol + Contract + Size + Premium + Read
- - ); -} - -function DarkFlow() { - return ( - -
- {darkFlow.map(([time, symbol, side, size, notional, type]) => ( -
- {time} - {symbol} - - {side} - - {size} - {notional} - {type} -
- ))} -
-
- ); -} - -function EventContext() { - return ( - -
-
    - {signals.slice(0, 4).map(([time, title, symbol]) => ( -
  1. - - {title} - {symbol} evidence linked -
  2. - ))} -
-
-

Why it fired

-
-
-
Type
-
Dark Flow Sweep
-
-
-
Premium
-
$4.32M
-
-
-
Venue
-
Off-exchange
-
-
-
Tags
-
Bullish / Sweep / Call
-
-
+ {rows.map(([time, symbol, contract, size, premium, type, read]) => ( +
+ {time} + {symbol} + {contract} + {size} + {premium} + {type}
-
- + ))} +
); } -function ReplayRail({ compact = false }: { compact?: boolean }) { +function FlowLadder() { return ( - -
- - - - 32x -
-
- - -
-
- 09:00 - 09:41:23 / Live - 10:15 -
-
+
+ {["raw print", "candidate", "packet", "SMP alert"].map((item, index) => ( +
+ {index + 1} + {item} +
+ ))} +
); } -function SymbolBrief() { +function HealthRows() { return ( - -
- 194.88 - +1.22% -
-

- Dark sweep pressure aligns with short-window momentum and a fresh news catalyst. Context - confidence is high, but the largest block remains off-exchange and should be checked against - next print behavior. -

-
- Bullish - Sweep - News linked -
-
+
+ {health.map(([name, state, lag]) => ( +
+ {name} + {state} + {lag} +
+ ))} +
); } -function Sparkline({ direction }: { direction: string }) { +function FactList({ items }: { items: string[][] }) { return ( - - - +
+ {items.map(([label, value]) => ( +
+
{label}
+
{value}
+
+ ))} +
); } + +function ReplayRail() { + return ( +
+ 09:00 +
+ +
+ 09:41:23 + 10:15 +
+ ); +} + +function Meter({ value }: { value: number }) { + return ( + + + {value} + + ); +} + +function Badge({ tone, children }: { tone: string; children: ReactNode }) { + const normalized = + tone === "Bearish" + ? "bearish" + : tone === "Watch" || tone === "Mixed" + ? "watch" + : tone === "Info" + ? "info" + : "bullish"; + + return {children}; +} diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css index a670c6f..85651ad 100644 --- a/apps/web/app/globals.css +++ b/apps/web/app/globals.css @@ -18,6 +18,9 @@ --red-soft: oklch(0.68 0.16 28 / 0.12); --blue: oklch(0.72 0.13 247); --blue-soft: oklch(0.72 0.13 247 / 0.11); + --route-accent: var(--accent); + --route-accent-soft: var(--accent-soft); + --route-line: var(--border); --drawer-width: min(320px, calc(100vw - 28px)); --topbar-height: 64px; } @@ -36,9 +39,7 @@ body { min-height: 100vh; font-family: var(--font-sans), sans-serif; color: var(--text); - background: - radial-gradient(circle at top left, oklch(0.78 0.12 74 / 0.08), transparent 30%), - linear-gradient(180deg, oklch(0.15 0.012 250) 0%, oklch(0.11 0.01 250) 100%); + background: oklch(0.105 0.012 250); } a { @@ -88,7 +89,7 @@ input { .terminal-shell { position: relative; min-height: 100vh; - background: linear-gradient(180deg, oklch(0.14 0.011 250) 0%, oklch(0.11 0.01 250) 100%); + background: linear-gradient(180deg, oklch(0.125 0.012 250) 0%, oklch(0.095 0.01 250) 100%); } .terminal-nav-drawer { @@ -236,9 +237,8 @@ input { justify-content: space-between; gap: 16px; padding: 10px 20px; - background: oklch(0.15 0.012 250 / 0.96); + background: oklch(0.12 0.012 250 / 0.98); border-bottom: 1px solid var(--border); - backdrop-filter: blur(12px); } .terminal-topbar-leading { @@ -516,12 +516,30 @@ input { .terminal-content { min-width: 0; - padding: 24px clamp(16px, 2vw, 28px) 24px; + padding: 14px clamp(12px, 1.7vw, 24px) 18px; } .page-shell { display: grid; - gap: 18px; + gap: 10px; +} + +.page-shell-dashboard { + --route-accent: var(--accent); + --route-accent-soft: var(--accent-soft); + --route-line: oklch(0.78 0.12 74 / 0.2); +} + +.page-shell-options { + --route-accent: var(--green); + --route-accent-soft: var(--green-soft); + --route-line: oklch(0.74 0.13 151 / 0.22); +} + +.page-shell-news { + --route-accent: var(--blue); + --route-accent-soft: var(--blue-soft); + --route-line: oklch(0.72 0.13 247 / 0.22); } .page-header { @@ -529,6 +547,25 @@ input { align-items: center; justify-content: space-between; gap: 16px; + min-height: 44px; + padding: 2px 0 9px; + border-bottom: 1px solid var(--route-line); +} + +.page-heading { + min-width: 0; + display: flex; + align-items: baseline; + gap: 10px; + flex-wrap: wrap; +} + +.page-eyebrow { + color: var(--route-accent); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; + letter-spacing: 0.12em; + text-transform: uppercase; } .page-title, @@ -542,8 +579,10 @@ h3 { } .page-title { - font-size: clamp(1.75rem, 2.4vw, 2.3rem); - letter-spacing: 0.06em; + font-family: var(--font-mono), monospace; + font-size: 1.18rem; + line-height: 1.1; + letter-spacing: 0.04em; } .page-actions { @@ -765,6 +804,71 @@ h3 { grid-template-columns: minmax(0, 1fr); } +.opra-intake-shell, +.wire-control-shell { + display: grid; + gap: 8px; +} + +.opra-command-rail { + min-width: 0; + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)) auto; + border-top: 1px solid var(--route-line); + border-bottom: 1px solid var(--border); +} + +.opra-command-cell { + min-width: 0; + min-height: 64px; + display: grid; + align-content: center; + gap: 4px; + padding: 9px 12px; + border-right: 1px solid var(--border); +} + +.opra-command-cell span, +.opra-command-cell em { + color: var(--text-faint); + font-family: var(--font-mono), monospace; + font-size: 0.66rem; + font-style: normal; + text-transform: uppercase; +} + +.opra-command-cell strong { + min-width: 0; + overflow: hidden; + color: var(--text); + font-family: var(--font-mono), monospace; + font-size: 0.8rem; + text-overflow: ellipsis; + white-space: nowrap; +} + +.opra-command-actions { + min-width: 220px; + display: flex; + align-items: center; + justify-content: flex-end; + gap: 8px; + padding: 10px 0 10px 12px; +} + +.opra-intake-grid { + display: grid; + grid-template-columns: minmax(560px, 1.22fr) minmax(460px, 0.98fr); + gap: 8px; + align-items: stretch; + min-height: calc(100vh - var(--topbar-height) - 178px); +} + +.opra-options-pane, +.opra-flow-pane { + min-height: 620px; +} + .page-grid-home > :nth-child(3), .page-grid-home > :nth-child(4), .page-grid-options > :nth-child(1), @@ -772,9 +876,10 @@ h3 { grid-column: 1 / -1; } -.command-deck-shell { +.command-deck-shell, +.market-command-shell { display: grid; - gap: 12px; + gap: 8px; } .command-deck-header { @@ -783,10 +888,10 @@ h3 { grid-template-columns: minmax(220px, 0.8fr) minmax(260px, 1fr) auto; gap: 14px; align-items: center; - padding: 13px 14px; - border: 1px solid var(--border); - border-radius: 12px; - background: linear-gradient(180deg, oklch(0.18 0.013 250 / 0.96), oklch(0.145 0.012 250 / 0.96)); + padding: 8px 0; + border-top: 1px solid var(--route-line); + border-bottom: 1px solid var(--border); + background: transparent; } .command-deck-brand { @@ -854,6 +959,117 @@ h3 { flex-wrap: wrap; } +.compact-command-bar { + display: flex; + flex-direction: column; + align-items: stretch; + gap: 8px; + padding: 8px 0; + background: transparent; +} + +.compact-command-topline, +.compact-command-context { + min-width: 0; + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; +} + +.compact-command-title, +.compact-command-controls, +.compact-command-context { + min-width: 0; + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; +} + +.compact-command-title span, +.compact-command-context > span { + color: var(--text-faint); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; + letter-spacing: 0.12em; + text-transform: lowercase; +} + +.compact-command-title strong { + color: var(--text); + font-family: var(--font-display), sans-serif; + font-size: 1.05rem; + letter-spacing: 0.02em; + text-transform: uppercase; +} + +.compact-command-context strong { + color: var(--text); + font-family: var(--font-mono), monospace; + font-size: 0.8rem; +} + +.command-filter-tooltip { + position: relative; + min-width: 0; + max-width: min(360px, 38vw); + min-height: 32px; + display: inline-flex; + align-items: center; + gap: 7px; + padding: 5px 8px 5px 10px; + border: 1px solid var(--border-strong); + border-radius: 999px; + background: oklch(0.78 0.12 74 / 0.09); + color: var(--text); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; + text-transform: uppercase; +} + +.command-filter-tooltip span { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.command-filter-tooltip button { + width: 20px; + height: 20px; + display: inline-flex; + align-items: center; + justify-content: center; + border: 0; + border-radius: 999px; + background: oklch(0.97 0.008 250 / 0.08); + color: var(--text-dim); + cursor: pointer; + font-family: var(--font-mono), monospace; + font-size: 0.62rem; + opacity: 0; + transform: translateX(3px); + transition: + background-color 150ms ease, + color 150ms ease, + opacity 150ms ease, + transform 150ms ease; +} + +.command-filter-tooltip:hover button, +.command-filter-tooltip:focus-within button { + opacity: 1; + transform: translateX(0); +} + +.command-filter-tooltip button:hover, +.command-filter-tooltip button:focus-visible { + background: oklch(0.78 0.12 74 / 0.17); + color: var(--text); + outline: none; +} + .command-chip { min-height: 32px; display: inline-flex; @@ -884,74 +1100,353 @@ h3 { background: var(--red-soft); } +.command-metric-strip { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + border-top: 1px solid var(--route-line); + border-bottom: 1px solid var(--border); +} + +.command-metric-cell { + min-width: 0; + min-height: 72px; + display: grid; + align-content: center; + gap: 4px; + padding: 10px 12px; + border-right: 1px solid var(--border); +} + +.command-metric-cell:last-child { + border-right: 0; +} + +.command-metric-cell span, +.command-metric-cell em { + color: var(--text-faint); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; + font-style: normal; + text-transform: uppercase; +} + +.command-metric-cell strong { + min-width: 0; + overflow: hidden; + color: var(--text); + font-family: var(--font-mono), monospace; + font-size: 0.86rem; + text-overflow: ellipsis; + white-space: nowrap; +} + +.command-symbol-rail, .command-ticker-rail { min-width: 0; overflow: hidden; - border: 1px solid var(--border); - border-radius: 10px; - background: oklch(0.13 0.012 250 / 0.98); + border-top: 1px solid var(--border); + border-bottom: 1px solid var(--border); + background: oklch(0.105 0.01 250 / 0.65); } +.command-symbol-track, .command-ticker-track { display: grid; - grid-auto-columns: minmax(176px, 1fr); + grid-auto-columns: minmax(172px, 1fr); grid-auto-flow: column; - gap: 8px; + gap: 0; overflow-x: auto; - padding: 7px; + padding: 0; } +.command-symbol-row, .command-ticker-card { - min-width: 176px; - min-height: 64px; + min-width: 172px; + min-height: 54px; display: grid; grid-template-columns: 1fr auto; - gap: 4px 9px; + gap: 3px 9px; align-items: center; - border: 1px solid var(--border); - border-radius: 8px; - padding: 8px 10px; - background: oklch(0.17 0.013 250); + border: 0; + border-right: 1px solid var(--border); + border-radius: 0; + padding: 7px 10px; + background: transparent; color: inherit; text-align: left; cursor: pointer; } +.command-symbol-row:hover, +.command-symbol-row:focus-visible, .command-ticker-card:hover, .command-ticker-card:focus-visible { - border-color: var(--border-strong); + background: var(--route-accent-soft); outline: none; } +.command-symbol-name, .command-ticker-symbol { color: var(--text); + font-family: var(--font-mono), monospace; font-weight: 700; } +.command-symbol-price, +.command-symbol-meta, .command-ticker-price, .command-ticker-meta { color: var(--text-dim); + font-family: var(--font-mono), monospace; font-size: 0.72rem; } +.command-symbol-move, .command-ticker-move { justify-self: end; color: var(--text-faint); + font-family: var(--font-mono), monospace; font-size: 0.68rem; } +.command-symbol-row.is-up .command-symbol-move, .command-ticker-card.is-up .command-ticker-move { color: var(--green); } +.command-symbol-row.is-down .command-symbol-move, .command-ticker-card.is-down .command-ticker-move { color: var(--red); } +.command-symbol-meta, .command-ticker-meta { grid-column: 1 / -1; } +.market-command-grid { + display: grid; + grid-template-columns: minmax(420px, 1.14fr) minmax(420px, 1fr) minmax(300px, 0.78fr); + grid-template-areas: + "priority chart levels" + "contracts chart health" + "context replay health"; + gap: 8px; + align-items: stretch; +} + +.market-command-grid > .terminal-pane { + min-height: 0; +} + +.command-priority-pane { + grid-area: priority; + min-height: 330px; +} + +.market-command-grid > :nth-child(2) { + grid-area: chart; + min-height: 520px; +} + +.command-levels-pane { + grid-area: levels; + min-height: 236px; +} + +.command-contracts-pane { + grid-area: contracts; + min-height: 314px; +} + +.command-feed-pane { + grid-area: health; + min-height: 420px; +} + +.command-context-pane { + grid-area: context; + min-height: 230px; +} + +.command-replay-pane { + grid-area: replay; + min-height: 140px; +} + +.market-command-grid .chart-surface { + height: 430px; +} + +.command-priority-table { + min-width: 760px; + overflow-x: auto; + border-top: 1px solid var(--border); +} + +.command-priority-row { + width: 100%; + min-height: 42px; + display: grid; + grid-template-columns: 76px 58px 112px minmax(160px, 1fr) 104px 96px 78px; + gap: 8px; + align-items: center; + padding: 0 10px; + border: 0; + border-bottom: 1px solid oklch(0.72 0.012 250 / 0.09); + background: transparent; + color: var(--text-dim); + text-align: left; +} + +.command-priority-row:not(.is-head) { + cursor: pointer; +} + +.command-priority-row:not(.is-head):hover, +.command-priority-row:not(.is-head):focus-visible { + background: var(--route-accent-soft); + color: var(--text); + outline: none; +} + +.command-priority-row.is-head { + min-height: 30px; + color: var(--text-faint); + font-family: var(--font-mono), monospace; + font-size: 0.62rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.command-priority-row time, +.command-priority-row span, +.command-priority-row strong { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.command-priority-row time, +.command-priority-row span { + font-family: var(--font-mono), monospace; + font-size: 0.7rem; +} + +.command-priority-row strong { + color: var(--text); + font-family: var(--font-mono), monospace; + font-size: 0.76rem; +} + +.command-priority-row.is-reject strong, +.command-priority-row.is-reject { + color: oklch(0.78 0.12 28); +} + +.command-priority-row.is-confirm strong { + color: var(--green); +} + +.command-score-meter { + display: grid; + grid-template-columns: minmax(0, 1fr) 28px; + gap: 7px; + align-items: center; +} + +.command-score-meter i { + height: 4px; + background: + linear-gradient(90deg, var(--route-accent) var(--score), transparent 0), + oklch(0.97 0.008 250 / 0.09); +} + +.command-score-meter em { + color: var(--text-dim); + font-style: normal; + text-align: right; +} + +.command-state { + width: fit-content; + max-width: 100%; + min-height: 22px; + display: inline-flex; + align-items: center; + border: 1px solid var(--border); + padding: 2px 7px; + color: var(--text-dim); + font-size: 0.64rem; + text-transform: uppercase; +} + +.command-state-confirm { + border-color: oklch(0.74 0.13 151 / 0.34); + color: var(--green); + background: var(--green-soft); +} + +.command-state-reject { + border-color: oklch(0.68 0.16 28 / 0.34); + color: var(--red); + background: var(--red-soft); +} + +.command-state-watch, +.command-state-hold { + border-color: var(--border-strong); + color: var(--accent); + background: var(--accent-soft); +} + +.command-state-info { + border-color: oklch(0.72 0.13 247 / 0.34); + color: var(--blue); + background: var(--blue-soft); +} + +.command-level-list { + display: grid; + margin: 0; +} + +.command-level-list div { + min-height: 44px; + display: grid; + grid-template-columns: 86px minmax(0, 1fr); + gap: 8px; + align-items: center; + padding: 7px 10px; + border-bottom: 1px solid oklch(0.72 0.012 250 / 0.09); +} + +.command-level-list div:last-child { + border-bottom: 0; +} + +.command-level-list dt, +.command-level-list dd { + min-width: 0; + margin: 0; + overflow: hidden; + font-family: var(--font-mono), monospace; + text-overflow: ellipsis; + white-space: nowrap; +} + +.command-level-list dt { + color: var(--text-faint); + font-size: 0.68rem; + text-transform: uppercase; +} + +.command-level-list dd { + color: var(--text); + font-size: 0.76rem; +} + .command-deck-grid { display: grid; grid-template-columns: minmax(360px, 1.12fr) minmax(420px, 1.38fr) minmax(300px, 0.9fr); @@ -1165,9 +1660,11 @@ h3 { height: 100%; display: flex; flex-direction: column; - border: 1px solid var(--border); - border-radius: 14px; - background: var(--bg-pane); + border: 0; + border-top: 1px solid var(--route-line); + border-bottom: 1px solid var(--border); + border-radius: 0; + background: oklch(0.13 0.012 250 / 0.74); overflow: hidden; } @@ -1176,9 +1673,10 @@ h3 { align-items: center; justify-content: space-between; gap: 12px; - padding: 15px 18px; + min-height: 38px; + padding: 8px 10px; border-bottom: 1px solid var(--border); - background: oklch(0.2 0.012 250 / 0.38); + background: oklch(0.12 0.012 250 / 0.86); } .terminal-pane-title-row { @@ -1189,10 +1687,11 @@ h3 { } .terminal-pane-title { - font-family: var(--font-sans), sans-serif; - font-size: 0.94rem; + font-family: var(--font-mono), monospace; + font-size: 0.72rem; font-weight: 600; - letter-spacing: 0.08em; + letter-spacing: 0.12em; + text-transform: uppercase; } .terminal-pane-status { @@ -1215,8 +1714,8 @@ h3 { flex: 1 1 auto; min-height: 0; flex-direction: column; - gap: 14px; - padding: 16px 18px 18px; + gap: 8px; + padding: 8px 0 0; } .chart-panel { @@ -1254,9 +1753,12 @@ h3 { .chart-surface { width: 100%; height: 460px; - border-radius: 12px; - border: 1px solid var(--border); - background: var(--bg-pane-2); + border-radius: 0; + border-top: 1px solid var(--border); + border-bottom: 1px solid var(--border); + border-left: 0; + border-right: 0; + background: oklch(0.105 0.01 250); overflow: hidden; } @@ -1469,7 +1971,7 @@ h3 { overflow-y: hidden; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); - background: oklch(0.14 0.01 250 / 0.72); + background: oklch(0.105 0.01 250 / 0.92); } .data-table { @@ -1486,7 +1988,7 @@ h3 { min-height: 0; overflow-y: auto; overflow-x: hidden; - background-color: oklch(0.12 0.01 250); + background-color: oklch(0.105 0.01 250); } .data-table-body { @@ -1494,19 +1996,7 @@ h3 { min-width: 100%; --tape-row-height: 36px; --tape-row-double-height: 72px; - background: - repeating-linear-gradient( - to bottom, - oklch(0.98 0.008 250 / 0.01) 0, - oklch(0.98 0.008 250 / 0.01) calc(var(--tape-row-height) - 1px), - oklch(0.72 0.012 250 / 0.08) calc(var(--tape-row-height) - 1px), - oklch(0.72 0.012 250 / 0.08) var(--tape-row-height), - oklch(0.98 0.008 250 / 0.018) var(--tape-row-height), - oklch(0.98 0.008 250 / 0.018) calc(var(--tape-row-double-height) - 1px), - oklch(0.72 0.012 250 / 0.08) calc(var(--tape-row-double-height) - 1px), - oklch(0.72 0.012 250 / 0.08) var(--tape-row-double-height) - ), - oklch(0.12 0.01 250); + background: oklch(0.105 0.01 250); } .data-table-options { @@ -1533,6 +2023,10 @@ h3 { min-width: 820px; } +.data-table-news { + min-width: 1120px; +} + .data-table-head, .data-table-row { display: grid; @@ -1545,7 +2039,7 @@ h3 { height: 30px; padding: 0 10px; border-bottom: 1px solid oklch(0.72 0.012 250 / 0.12); - background: oklch(0.15 0.012 250 / 0.96); + background: oklch(0.125 0.012 250 / 0.98); color: var(--text-faint); font-size: 0.64rem; font-weight: 700; @@ -1558,7 +2052,7 @@ h3 { padding: 0 10px; border: 0; border-bottom: 1px solid oklch(0.72 0.012 250 / 0.08); - background: oklch(0.98 0.008 250 / 0.008); + background: transparent; color: inherit; font: inherit; text-align: left; @@ -1600,6 +2094,10 @@ h3 { height: 44px; } +.data-table-row-news { + height: 52px; +} + .data-table-flow .data-table-body, .data-table-alerts .data-table-body, .data-table-classifier .data-table-body, @@ -1608,6 +2106,11 @@ h3 { --tape-row-double-height: 88px; } +.data-table-news .data-table-body { + --tape-row-height: 52px; + --tape-row-double-height: 104px; +} + .data-table-row-classified { background: linear-gradient( @@ -1707,6 +2210,14 @@ h3 { ) minmax(74px, 0.65fr) minmax(260px, 2fr); } +.data-table-news .data-table-head, +.data-table-news .data-table-row { + grid-template-columns: minmax(86px, 0.75fr) minmax(92px, 0.75fr) minmax(118px, 0.9fr) minmax( + 80px, + 0.65fr + ) minmax(320px, 2.2fr) minmax(260px, 1.6fr); +} + .data-table-cell { min-width: 0; overflow: hidden; @@ -2279,57 +2790,188 @@ h3 { text-decoration: none; } -.news-list { - display: flex; - flex-direction: column; - gap: 10px; -} - -.news-row { - width: 100%; - display: flex; - flex-direction: column; +.wire-control-rails { + min-width: 0; + display: grid; + grid-template-columns: minmax(260px, 0.8fr) minmax(260px, 0.75fr) minmax(360px, 1fr); gap: 8px; - padding: 14px 16px; - border: 1px solid var(--border); - border-radius: 12px; - background: oklch(0.18 0.012 250 / 0.6); - color: var(--text); - text-align: left; - transition: - border-color 150ms ease, - background 150ms ease; } -.news-row:hover { - border-color: var(--accent-soft); - background: oklch(0.2 0.015 250 / 0.75); +.wire-status-rail, +.wire-source-rail, +.wire-symbol-rail { + min-width: 0; + border-top: 1px solid var(--route-line); + border-bottom: 1px solid var(--border); + background: oklch(0.105 0.01 250 / 0.45); } -.news-row-head, -.news-row-meta { +.wire-status-rail { + display: grid; +} + +.wire-rail-row { + min-width: 0; + min-height: 34px; + display: grid; + grid-template-columns: 70px minmax(0, 1fr) minmax(72px, 0.8fr); + gap: 8px; + align-items: center; + padding: 6px 10px; + border-bottom: 1px solid oklch(0.72 0.012 250 / 0.09); +} + +.wire-rail-row:last-child { + border-bottom: 0; +} + +.wire-source-rail, +.wire-symbol-rail { display: flex; align-items: center; - justify-content: space-between; - gap: 10px; - flex-wrap: wrap; + gap: 0; + overflow-x: auto; } -.news-row h3 { - margin: 0; - font-size: 0.96rem; - font-weight: 600; -} - -.news-row-time { - color: var(--text-dim); +.wire-rail-label, +.wire-empty-label, +.wire-source-pill, +.wire-symbol-rail button, +.wire-rail-row span, +.wire-rail-row strong, +.wire-rail-row em { font-family: var(--font-mono), monospace; - font-size: 0.78rem; } -.news-row-meta { +.wire-rail-label { + flex: 0 0 auto; + min-height: 100%; + display: inline-flex; + align-items: center; + padding: 0 10px; + border-right: 1px solid var(--border); + color: var(--text-faint); + font-size: 0.66rem; + text-transform: uppercase; +} + +.wire-empty-label { + padding: 0 10px; + color: var(--text-faint); + font-size: 0.7rem; +} + +.wire-source-pill, +.wire-symbol-rail button { + min-height: 38px; + display: inline-flex; + align-items: center; + gap: 7px; + padding: 0 10px; + border: 0; + border-right: 1px solid var(--border); + background: transparent; + color: var(--text-dim); + white-space: nowrap; +} + +.wire-symbol-rail button { + cursor: pointer; +} + +.wire-symbol-rail button:hover, +.wire-symbol-rail button:focus-visible { + background: var(--route-accent-soft); + color: var(--text); + outline: none; +} + +.wire-source-pill strong, +.wire-symbol-rail strong, +.wire-rail-row strong { + color: var(--text); + font-size: 0.76rem; +} + +.wire-source-pill em, +.wire-symbol-rail em, +.wire-rail-row span, +.wire-rail-row em { + color: var(--text-faint); + font-size: 0.66rem; + font-style: normal; + text-transform: uppercase; +} + +.news-pane-full { + min-height: calc(100vh - var(--topbar-height) - 190px); +} + +.news-wire-shell { + min-height: 0; +} + +.history-load-muted { + border-color: oklch(0.72 0.13 247 / 0.32); + background: oklch(0.2 0.05 247 / 0.52); + color: oklch(0.86 0.08 247); +} + +.news-headline-cell, +.news-summary-cell { + white-space: normal; + display: -webkit-box; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.news-headline-cell { + -webkit-line-clamp: 2; + color: var(--text); + font-size: 0.74rem; + line-height: 1.28; +} + +.news-summary-cell { + -webkit-line-clamp: 2; + color: var(--text-dim); + font-size: 0.7rem; + line-height: 1.28; +} + +.news-state { + width: fit-content; + max-width: 100%; + min-height: 21px; + display: inline-flex; + align-items: center; + border: 1px solid var(--border); + padding: 2px 7px; + font-family: var(--font-mono), monospace; + font-size: 0.62rem; + text-transform: uppercase; +} + +.news-state-mapped { + border-color: oklch(0.74 0.13 151 / 0.34); + color: var(--green); + background: var(--green-soft); +} + +.news-state-updated { + border-color: oklch(0.72 0.13 247 / 0.34); + color: var(--blue); + background: var(--blue-soft); +} + +.news-state-unmapped { + border-color: var(--border-strong); + color: var(--accent); + background: var(--accent-soft); +} + +.news-wire-row-unmapped { color: var(--text-dim); - font-size: 0.78rem; } .news-drawer-body a { @@ -2477,6 +3119,7 @@ h3 { .interval-button, .overlay-toggle, .drawer-close, + .command-filter-tooltip button, .status-inline-counter, .missed-count, .synthetic-control-gear { @@ -2506,6 +3149,10 @@ h3 { grid-template-columns: minmax(220px, 0.8fr) minmax(240px, 1fr); } + .compact-command-topline { + justify-content: flex-start; + } + .command-deck-controls { grid-column: 1 / -1; justify-content: flex-start; @@ -2520,6 +3167,35 @@ h3 { "dark dark" "replay replay"; } + + .market-command-grid { + grid-template-columns: minmax(0, 1fr) minmax(340px, 0.8fr); + grid-template-areas: + "priority levels" + "chart chart" + "contracts health" + "context replay"; + } + + .wire-control-rails { + grid-template-columns: minmax(0, 1fr); + } + + .opra-command-rail { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .opra-command-actions { + grid-column: 1 / -1; + justify-content: flex-start; + min-width: 0; + padding: 10px 0; + } + + .opra-intake-grid { + grid-template-columns: minmax(0, 1fr); + min-height: 0; + } } @media (max-width: 980px) { @@ -2570,6 +3246,18 @@ h3 { "dark"; } + .market-command-grid { + grid-template-columns: minmax(0, 1fr); + grid-template-areas: + "priority" + "chart" + "levels" + "contracts" + "health" + "context" + "replay"; + } + .command-deck-grid > .terminal-pane { min-height: 0; } @@ -2584,6 +3272,17 @@ h3 { min-height: 0; } + .market-command-grid > .terminal-pane, + .opra-options-pane, + .opra-flow-pane, + .news-pane-full { + min-height: 0; + } + + .command-metric-strip { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .terminal-topbar { align-items: center; justify-content: space-between; @@ -2644,7 +3343,7 @@ h3 { } .page-title { - font-size: 1.55rem; + font-size: 1.08rem; line-height: 1.06; } @@ -2674,10 +3373,62 @@ h3 { justify-content: center; } + .compact-command-bar .command-chip, + .compact-command-bar .terminal-button, + .command-filter-tooltip { + width: auto; + max-width: 100%; + justify-content: center; + } + + .compact-command-topline, + .compact-command-context { + align-items: flex-start; + flex-direction: column; + } + .command-ticker-track { grid-auto-columns: minmax(164px, 78vw); } + .command-symbol-track { + grid-auto-columns: minmax(164px, 78vw); + } + + .opra-command-rail, + .command-metric-strip { + grid-template-columns: minmax(0, 1fr); + } + + .opra-command-cell, + .command-metric-cell { + border-right: 0; + border-bottom: 1px solid var(--border); + } + + .opra-command-cell:last-of-type, + .command-metric-cell:last-child { + border-bottom: 0; + } + + .opra-command-actions { + flex-direction: column; + align-items: stretch; + } + + .opra-command-actions .flow-filter-popover, + .opra-command-actions .terminal-button { + width: 100%; + } + + .wire-rail-row { + grid-template-columns: 68px minmax(0, 1fr); + } + + .wire-rail-row em { + grid-column: 2; + } + .terminal-pane-title-row { flex-direction: column; align-items: flex-start; @@ -2688,6 +3439,8 @@ h3 { position: sticky; top: 0; z-index: 30; + flex-wrap: wrap; + align-items: stretch; padding: 12px 10px; } @@ -2755,7 +3508,7 @@ h3 { } .terminal-pane { - border-radius: 12px; + border-radius: 0; } .terminal-pane-head, @@ -2834,7 +3587,8 @@ h3 { } .data-table-options, - .data-table-flow { + .data-table-flow, + .data-table-news { min-width: 1080px; } @@ -2855,10 +3609,18 @@ h3 { height: 48px; } + .data-table-row-news { + height: 56px; + } + .command-deck-grid .chart-surface { height: 320px; } + .market-command-grid .chart-surface { + height: 320px; + } + .command-health-row { grid-template-columns: minmax(94px, 1fr) 92px; } @@ -2938,73 +3700,67 @@ h3 { } } -.mock-terminal { +.mock-redesign { min-height: calc(100vh - var(--topbar-height)); padding: 18px; color: var(--text); background: - linear-gradient(180deg, oklch(0.18 0.018 238 / 0.8), transparent 220px), - linear-gradient(135deg, oklch(0.12 0.015 230), oklch(0.1 0.012 255)); + linear-gradient(180deg, oklch(0.18 0.018 240 / 0.88), oklch(0.11 0.012 250) 280px), + oklch(0.11 0.012 250); } -.mock-header { +.mock-redesign-header { display: grid; - grid-template-columns: minmax(220px, 0.8fr) minmax(280px, 1.2fr) auto; - gap: 14px; - align-items: center; - margin-bottom: 12px; + grid-template-columns: minmax(340px, 1fr) auto; + gap: 14px 18px; + align-items: end; + margin-bottom: 14px; } -.mock-brand-lockup { +.mock-redesign-title { min-width: 0; - display: flex; - align-items: center; - gap: 11px; + display: grid; + gap: 7px; } -.mock-mark { - width: 34px; - height: 34px; - border-radius: 9px; - background: linear-gradient(135deg, oklch(0.68 0.14 246), oklch(0.68 0.12 164)), var(--blue-soft); - box-shadow: inset 0 0 0 1px oklch(0.94 0.02 240 / 0.24); -} - -.mock-brand { - display: block; - color: var(--text-dim); +.mock-redesign-product, +.mock-panel-label, +.mock-redesign-meta span, +.mock-redesign-switcher a { + color: var(--text-faint); font-family: var(--font-mono), monospace; - font-size: 0.74rem; - letter-spacing: 0.12em; - text-transform: lowercase; + font-size: 0.68rem; + letter-spacing: 0.11em; + text-transform: uppercase; } -.mock-header h1 { - margin: 2px 0 0; - font-family: var(--font-display), sans-serif; - font-size: 1.28rem; - line-height: 1.08; +.mock-redesign-title h1 { + margin: 0; + font-size: 1.54rem; + line-height: 1.12; letter-spacing: 0; + text-wrap: balance; } -.mock-header p { - max-width: 72ch; +.mock-redesign-title p { + max-width: 75ch; margin: 0; color: var(--text-dim); - font-size: 0.9rem; + font-size: 0.91rem; + line-height: 1.46; + text-wrap: pretty; } -.mock-header-tools, -.mock-switcher { +.mock-redesign-meta, +.mock-redesign-switcher { display: flex; - align-items: center; justify-content: flex-end; gap: 8px; flex-wrap: wrap; } -.mock-header-tools span, -.mock-switcher a { +.mock-redesign-meta span, +.mock-redesign-switcher a { min-height: 30px; display: inline-flex; align-items: center; @@ -3012,198 +3768,381 @@ h3 { border-radius: 8px; padding: 6px 9px; background: oklch(0.97 0.008 250 / 0.035); - color: var(--text-dim); - font-family: var(--font-mono), monospace; - font-size: 0.68rem; - letter-spacing: 0.08em; - text-transform: uppercase; } -.mock-live-dot { - color: var(--green) !important; - background: var(--green-soft) !important; +.mock-redesign-meta .is-live, +.mock-redesign-switcher a.is-active { + color: var(--accent); + border-color: var(--border-strong); + background: var(--accent-soft); } -.mock-mode, -.mock-switcher a.is-active { - color: var(--accent) !important; - border-color: var(--border-strong) !important; - background: var(--accent-soft) !important; -} - -.mock-switcher { +.mock-redesign-switcher { grid-column: 1 / -1; justify-content: flex-start; } -.mock-ticker-rail { - overflow: hidden; - margin-bottom: 10px; - border: 1px solid var(--border); - border-radius: 10px; - background: oklch(0.13 0.015 245 / 0.94); -} - -.mock-ticker-track { - display: flex; - width: max-content; - gap: 8px; - padding: 7px; - animation: mockTicker 42s linear infinite; -} - -.mock-ticker-card { - width: 176px; - min-height: 48px; - display: grid; - grid-template-columns: 1fr auto; - gap: 7px; - align-items: center; - padding: 8px 10px; - border: 1px solid var(--border); - border-radius: 8px; - background: linear-gradient(180deg, oklch(0.18 0.017 244), oklch(0.14 0.014 244)); -} - -.mock-ticker-card div { - display: grid; - gap: 2px; -} - -.mock-ticker-card strong, -.mock-table strong { - font-family: var(--font-mono), monospace; -} - -.mock-ticker-card span { - color: var(--text-dim); - font-size: 0.75rem; -} - -.mock-sparkline { - grid-column: 1 / -1; - width: 100%; - height: 22px; -} - -.mock-sparkline polyline { - stroke: var(--green); - stroke-width: 2; -} - -.mock-ticker-card:has(.is-down) .mock-sparkline polyline { - stroke: var(--red); -} - -.mock-dashboard-grid { - display: grid; - gap: 10px; -} - -.mock-grid-classic { - grid-template-columns: minmax(420px, 1.18fr) minmax(420px, 1.48fr) minmax(320px, 0.95fr); - grid-template-areas: - "tape chart signals" - "feed dark context" - "replay replay replay"; -} - -.mock-grid-focus { - grid-template-columns: minmax(280px, 0.78fr) minmax(480px, 1.45fr) minmax(360px, 0.95fr); - grid-template-areas: - "brief chart context" - "tape chart context" - "signals dark context"; -} - -.mock-grid-signals { - grid-template-columns: minmax(360px, 0.92fr) minmax(440px, 1.15fr) minmax(360px, 0.9fr); - grid-template-areas: - "signals tape chart" - "signals tape feed" - "context context context"; -} - -.mock-grid-replay { - grid-template-columns: minmax(340px, 0.95fr) minmax(460px, 1.25fr) minmax(360px, 0.9fr); - grid-template-areas: - "replay replay replay" - "tape chart context" - "signals dark context"; -} - -.mock-panel { +.mock-redesign-panel { min-width: 0; overflow: hidden; border: 1px solid var(--border); - border-radius: 10px; - background: linear-gradient(180deg, oklch(0.18 0.016 246 / 0.98), oklch(0.135 0.014 246 / 0.98)); + border-radius: 12px; + background: linear-gradient(180deg, oklch(0.19 0.015 246 / 0.98), oklch(0.135 0.012 246 / 0.98)); } -.mock-panel-head { - min-height: 40px; +.mock-panel-label { + min-height: 34px; + display: flex; + align-items: center; + padding: 9px 11px 8px; + border-bottom: 1px solid oklch(0.72 0.012 250 / 0.12); +} + +.mock-badge { + width: fit-content; + max-width: 100%; + min-height: 22px; + display: inline-flex; + align-items: center; + justify-content: center; + border: 1px solid currentColor; + border-radius: 999px; + padding: 3px 8px; + font-family: var(--font-mono), monospace; + font-size: 0.64rem; + line-height: 1; + white-space: nowrap; +} + +.mock-badge.is-bullish { + color: var(--green); + background: var(--green-soft); +} + +.mock-badge.is-bearish { + color: var(--red); + background: var(--red-soft); +} + +.mock-badge.is-watch { + color: var(--accent); + background: var(--accent-soft); +} + +.mock-badge.is-info { + color: var(--blue); + background: var(--blue-soft); +} + +.mock-score-dial { + --score-color: oklch(0.74 0.13 151); + width: 42px; + height: 42px; + flex: 0 0 auto; + display: grid; + place-items: center; + border-radius: 50%; + background: + radial-gradient(circle, oklch(0.13 0.012 250) 54%, transparent 56%), + conic-gradient(var(--score-color) calc(var(--score) * 1%), oklch(0.72 0.012 250 / 0.16) 0); + color: var(--text); + font-family: var(--font-mono), monospace; + font-size: 0.76rem; +} + +.mock-symbol-strip { + grid-area: symbols; + display: grid; + grid-template-columns: repeat(5, minmax(130px, 1fr)); + gap: 10px; +} + +.mock-symbol-tile, +.mock-evidence-card, +.mock-queue-item, +.mock-cluster-row { + min-width: 0; display: flex; align-items: center; justify-content: space-between; - gap: 12px; - padding: 10px 12px; - border-bottom: 1px solid var(--border); + gap: 10px; + border: 1px solid oklch(0.72 0.012 250 / 0.12); + border-radius: 10px; + background: oklch(0.97 0.008 250 / 0.035); } -.mock-panel-head h2 { - margin: 0; +.mock-symbol-tile { + min-height: 68px; + padding: 10px; +} + +.mock-symbol-tile div, +.mock-cluster-row div, +.mock-evidence-card, +.mock-queue-item div, +.mock-inspector-header, +.mock-check-list div { + min-width: 0; + display: grid; + gap: 4px; +} + +.mock-symbol-tile strong, +.mock-redesign-row strong, +.mock-cluster-row strong { font-family: var(--font-mono), monospace; - font-size: 0.72rem; - letter-spacing: 0.14em; - text-transform: uppercase; } -.mock-panel-head span { - color: var(--text-faint); +.mock-symbol-tile span, +.mock-evidence-card span, +.mock-queue-item span, +.mock-cluster-row span, +.mock-inspector-header p, +.mock-case-heading p, +.mock-time-spine span { + color: var(--text-dim); + font-size: 0.78rem; + line-height: 1.42; +} + +.mock-canvas-grid { + display: grid; + grid-template-columns: minmax(320px, 0.78fr) minmax(460px, 1.22fr) minmax(300px, 0.72fr); + grid-template-areas: + "symbols symbols symbols" + "brief chart context" + "tape chart context"; + gap: 10px; +} + +.mock-canvas-brief { + grid-area: brief; +} + +.mock-canvas-chart { + grid-area: chart; +} + +.mock-canvas-tape { + grid-area: tape; +} + +.mock-canvas-context { + grid-area: context; +} + +.mock-case-heading { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 10px; + align-items: start; + padding: 12px; +} + +.mock-case-heading h2, +.mock-inspector-header h2, +.mock-replay-hero h2 { + margin: 0; + font-size: 1.1rem; + line-height: 1.22; + text-wrap: balance; +} + +.mock-case-heading h2 { + font-size: 0.98rem; +} + +.mock-case-heading p, +.mock-inspector-header p { + margin: 0; +} + +.mock-case-symbol { + grid-column: 1; + display: grid; + place-items: center; + width: fit-content; + min-height: 28px; + border-radius: 10px; + padding: 5px 9px; + background: oklch(0.78 0.12 74 / 0.12); + color: var(--accent); + font-family: var(--font-mono), monospace; + font-weight: 500; +} + +.mock-confidence { + grid-column: 2; + grid-row: 1; + min-height: 28px; + display: inline-flex; + align-items: center; + border-radius: 999px; + padding: 5px 9px; + color: var(--green); + background: var(--green-soft); font-family: var(--font-mono), monospace; font-size: 0.68rem; } -.mock-option-tape { - grid-area: tape; +.mock-case-heading > div { + grid-column: 1 / -1; } -.mock-chart { - grid-area: chart; -} - -.mock-signals { - grid-area: signals; -} - -.mock-feed { - grid-area: feed; -} - -.mock-dark-flow { - grid-area: dark; -} - -.mock-context { - grid-area: context; -} - -.mock-replay { - grid-area: replay; -} - -.mock-symbol-brief { - grid-area: brief; -} - -.mock-table { +.mock-evidence-list { display: grid; - padding: 6px 10px 10px; + grid-template-columns: repeat(auto-fit, minmax(142px, 1fr)); + gap: 8px; + padding: 0 12px 12px; } -.mock-table-row { +.mock-evidence-list.is-compact { + grid-template-columns: 1fr; + padding: 10px; +} + +.mock-evidence-card { + align-items: stretch; + padding: 10px; +} + +.mock-evidence-card strong { + font-size: 0.83rem; + line-height: 1.28; +} + +.mock-evidence-card div { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} + +.mock-redesign-chart { + min-height: 332px; +} + +.mock-chart-topline, +.mock-replay-hero { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; + padding: 12px; +} + +.mock-chart-topline div, +.mock-replay-hero div:first-child { + display: grid; + gap: 4px; +} + +.mock-chart-topline span, +.mock-replay-hero span { + color: var(--text-faint); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; + text-transform: uppercase; +} + +.mock-chart-topline strong { + font-family: var(--font-mono), monospace; + font-size: 1.18rem; +} + +.mock-chart-field { + position: relative; + height: 210px; + display: flex; + align-items: end; + gap: 4px; + margin: 2px 12px 0; + padding: 14px 0; + border-top: 1px solid oklch(0.72 0.012 250 / 0.1); + border-bottom: 1px solid oklch(0.72 0.012 250 / 0.1); + background: + linear-gradient(0deg, oklch(0.72 0.012 250 / 0.07) 1px, transparent 1px) 0 0 / 100% 40px, + linear-gradient(180deg, oklch(0.14 0.015 246), oklch(0.1 0.012 246)); +} + +.mock-redesign-chart.is-compressed .mock-chart-field { + height: 150px; +} + +.mock-redesign-chart.is-replay .mock-chart-field { + height: 260px; +} + +.mock-chart-field span { + width: 6px; + height: var(--height); + min-height: 16px; + border-radius: 5px; +} + +.mock-chart-field .is-green, +.mock-volume-field .is-green { + background: var(--green); +} + +.mock-chart-field .is-red, +.mock-volume-field .is-red { + background: var(--red); +} + +.mock-chart-marker { + position: absolute; + top: 10px; + bottom: 10px; + left: 64%; + width: 2px; + border-radius: 999px; + background: var(--accent); +} + +.mock-chart-marker::after { + content: "signal"; + position: absolute; + top: 6px; + left: 8px; + border-radius: 999px; + padding: 4px 7px; + background: var(--accent-soft); + color: var(--accent); + font-family: var(--font-mono), monospace; + font-size: 0.62rem; + font-style: normal; +} + +.mock-volume-field { + height: 66px; + display: flex; + align-items: end; + gap: 5px; + padding: 9px 12px 12px; +} + +.mock-volume-field span { + width: 7px; + height: var(--height); + min-height: 8px; + opacity: 0.8; +} + +.mock-flow-tape { + min-height: 0; +} + +.mock-redesign-table { + overflow-x: auto; + padding: 8px 10px 10px; +} + +.mock-redesign-row { + min-width: 650px; min-height: 36px; display: grid; + grid-template-columns: 48px 64px minmax(170px, 1fr) 72px 82px 86px; gap: 10px; align-items: center; border-bottom: 1px solid oklch(0.72 0.012 250 / 0.09); @@ -3211,283 +4150,171 @@ h3 { font-size: 0.76rem; } -.mock-table-row:last-child { +.mock-redesign-row:last-child { border-bottom: 0; } -.mock-table-head { - min-height: 30px; +.mock-redesign-row.is-head { + min-height: 28px; color: var(--text-faint); font-family: var(--font-mono), monospace; font-size: 0.64rem; - letter-spacing: 0.1em; text-transform: uppercase; } -.mock-table-options .mock-table-row { - grid-template-columns: 42px 58px 70px 64px 68px 72px 68px 76px; +.mock-causality { + padding-bottom: 10px; } -.mock-table-feed .mock-table-row { - grid-template-columns: minmax(110px, 1fr) 86px 58px 70px; -} - -.mock-table-dark .mock-table-row { - grid-template-columns: 72px 56px 64px 74px 78px 64px; -} - -.mock-pill { - width: fit-content; - max-width: 100%; - display: inline-flex; - align-items: center; - min-height: 22px; - padding: 3px 7px; - border: 1px solid var(--border); - border-radius: 999px; - color: var(--text-dim); - font-family: var(--font-mono), monospace; - font-size: 0.64rem; - letter-spacing: 0.02em; -} - -.mock-pill.is-bullish { - color: var(--green); - background: var(--green-soft); -} - -.mock-pill.is-bearish { - color: var(--red); - background: var(--red-soft); -} - -.mock-pill.is-info, -.mock-pill.is-news { - color: var(--blue); - background: var(--blue-soft); -} - -.mock-pill.is-warning { - color: var(--accent); - background: var(--accent-soft); -} - -.mock-move { - font-family: var(--font-mono), monospace; - font-size: 0.72rem; -} - -.mock-move.is-up { - color: var(--green); -} - -.mock-move.is-down { - color: var(--red); -} - -.mock-chart { - min-height: 326px; -} - -.mock-chart.is-compact { - min-height: 240px; -} - -.mock-chart-meta { - display: flex; - align-items: baseline; - gap: 10px; - padding: 10px 12px 0; -} - -.mock-chart-meta strong, -.mock-brief-price strong { - font-family: var(--font-mono), monospace; - font-size: 1rem; -} - -.mock-candle-field { - position: relative; - height: 190px; - margin: 8px 12px 0; - display: flex; - align-items: end; - gap: 4px; - padding: 12px 0; - border-top: 1px solid oklch(0.72 0.012 250 / 0.08); - border-bottom: 1px solid oklch(0.72 0.012 250 / 0.08); - background: - repeating-linear-gradient(0deg, transparent 0 38px, oklch(0.72 0.012 250 / 0.08) 39px 40px), - linear-gradient(180deg, oklch(0.16 0.018 246), oklch(0.12 0.014 246)); -} - -.mock-chart.is-compact .mock-candle-field { - height: 126px; -} - -.mock-candle-field span { - width: 5px; - height: var(--height); - min-height: 18px; - border-radius: 4px; -} - -.mock-candle-field .is-green, -.mock-volume-field .is-green { - background: var(--green); -} - -.mock-candle-field .is-red, -.mock-volume-field .is-red { - background: var(--red); -} - -.mock-volume-field { - height: 70px; - display: flex; - align-items: end; - gap: 5px; - padding: 9px 12px 12px; -} - -.mock-chart.is-compact .mock-volume-field { - height: 54px; -} - -.mock-volume-field span { - width: 7px; - height: var(--height); - min-height: 8px; - opacity: 0.85; -} - -.mock-signal-list { - display: grid; - padding: 6px 10px 10px; -} - -.mock-signal-item { - min-height: 58px; - display: grid; - grid-template-columns: 70px minmax(0, 1fr) auto; - gap: 10px; - align-items: center; - border-bottom: 1px solid oklch(0.72 0.012 250 / 0.09); -} - -.mock-signal-item:last-child { - border-bottom: 0; -} - -.mock-signal-item time, -.mock-timeline time { - color: var(--text-faint); - font-family: var(--font-mono), monospace; - font-size: 0.72rem; -} - -.mock-signal-item div { - min-width: 0; - display: grid; - gap: 3px; -} - -.mock-signal-item strong { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-size: 0.82rem; -} - -.mock-signal-item span:not(.mock-pill) { - color: var(--text-dim); - font-size: 0.75rem; -} - -.mock-signals.is-hero .mock-signal-item { - min-height: 74px; -} - -.mock-event-layout { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(220px, 0.75fr); - gap: 10px; - padding: 10px; -} - -.mock-timeline { - display: grid; - gap: 8px; - margin: 0; - padding: 0; - list-style: none; -} - -.mock-timeline li { - display: grid; - gap: 4px; - padding: 9px; - border: 1px solid oklch(0.72 0.012 250 / 0.1); - border-radius: 8px; - background: oklch(0.97 0.008 250 / 0.028); -} - -.mock-timeline strong { - font-size: 0.8rem; -} - -.mock-timeline span, -.mock-detail dd, -.mock-symbol-brief p { - color: var(--text-dim); - font-size: 0.78rem; -} - -.mock-detail { - padding: 10px; - border: 1px solid var(--border); - border-radius: 8px; - background: oklch(0.12 0.014 246 / 0.72); -} - -.mock-detail h3 { - margin: 0 0 10px; - font-size: 0.86rem; -} - -.mock-detail dl { +.mock-causality dl { display: grid; gap: 9px; margin: 0; + padding: 10px; } -.mock-detail div { - display: flex; - justify-content: space-between; - gap: 10px; +.mock-causality div, +.mock-feed-health div { + display: grid; + grid-template-columns: minmax(100px, 0.76fr) minmax(0, 1fr); + gap: 8px; + align-items: start; } -.mock-detail dt { +.mock-causality dt { color: var(--text-faint); font-family: var(--font-mono), monospace; - font-size: 0.65rem; + font-size: 0.66rem; text-transform: uppercase; } -.mock-detail dd { +.mock-causality dd { margin: 0; - text-align: right; + color: var(--text-dim); + font-size: 0.82rem; } -.mock-replay { - min-height: 112px; +.mock-queue-grid { + display: grid; + grid-template-columns: minmax(270px, 0.72fr) minmax(440px, 1.2fr) minmax(280px, 0.72fr); + grid-template-areas: "queue inspector checks"; + gap: 10px; +} + +.mock-queue-list { + grid-area: queue; +} + +.mock-queue-inspector { + grid-area: inspector; +} + +.mock-queue-checks { + grid-area: checks; +} + +.mock-queue-list, +.mock-queue-checks { + align-self: start; +} + +.mock-queue-item { + margin: 10px 10px 0; + padding: 10px; +} + +.mock-queue-item:last-child { + margin-bottom: 10px; +} + +.mock-queue-item.is-selected { + border-color: var(--border-strong); + background: var(--accent-soft); +} + +.mock-queue-item time { + color: var(--text-faint); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; +} + +.mock-queue-item strong { + font-size: 1rem; +} + +.mock-inspector-header { + padding: 12px; +} + +.mock-inspector-header span { + color: var(--accent); + font-family: var(--font-mono), monospace; + font-size: 0.76rem; +} + +.mock-check-list, +.mock-feed-health { + display: grid; + gap: 8px; + padding: 10px; +} + +.mock-check-list div, +.mock-feed-health div { + border: 1px solid oklch(0.72 0.012 250 / 0.11); + border-radius: 10px; + padding: 9px; + background: oklch(0.97 0.008 250 / 0.03); +} + +.mock-check-list span, +.mock-feed-health span { + color: var(--text-faint); + font-family: var(--font-mono), monospace; + font-size: 0.66rem; + text-transform: uppercase; +} + +.mock-check-list strong, +.mock-feed-health strong { + font-size: 0.78rem; +} + +.mock-feed-health div { + grid-template-columns: minmax(55px, 0.6fr) auto auto; +} + +.mock-replay-grid { + display: grid; + grid-template-columns: minmax(280px, 0.64fr) minmax(500px, 1.36fr) minmax(300px, 0.8fr); + grid-template-areas: + "spine stage stage" + "spine tape notes"; + gap: 10px; +} + +.mock-replay-stage { + grid-area: stage; +} + +.mock-replay-spine { + grid-area: spine; +} + +.mock-replay-tape { + grid-area: tape; +} + +.mock-replay-notes { + grid-area: notes; } .mock-replay-controls { display: flex; align-items: center; + justify-content: flex-end; gap: 8px; - padding: 10px 12px 0; + flex-wrap: wrap; } .mock-replay-controls button { @@ -3499,147 +4326,2140 @@ h3 { cursor: pointer; } -.mock-replay-controls span { +.mock-replay-controls button:hover { + border-color: var(--border-strong); +} + +.mock-replay-track-redesign { + display: grid; + grid-template-columns: auto minmax(0, 1fr) auto auto; + gap: 10px; + align-items: center; + padding: 0 12px 12px; color: var(--text-faint); font-family: var(--font-mono), monospace; - font-size: 0.72rem; + font-size: 0.7rem; } -.mock-replay-track { +.mock-replay-track-redesign div { position: relative; - height: 26px; - margin: 12px; + height: 28px; border: 1px solid var(--border); - border-radius: 8px; - background: - repeating-linear-gradient(90deg, transparent 0 22px, oklch(0.72 0.012 250 / 0.18) 23px 24px), - oklch(0.11 0.014 246); -} - -.mock-replay-window { - position: absolute; - inset: 6px 28% 6px 42%; border-radius: 999px; - background: var(--blue); + background: linear-gradient( + 90deg, + var(--blue-soft) 0 54%, + var(--accent-soft) 54% 66%, + oklch(0.97 0.008 250 / 0.035) 66% + ); } -.mock-replay-now { +.mock-replay-track-redesign i { position: absolute; - top: 2px; - bottom: 2px; - left: 62%; + top: 3px; + bottom: 3px; + left: 64%; width: 3px; border-radius: 999px; background: var(--green); } -.mock-replay-times { - display: flex; - justify-content: space-between; - padding: 0 12px 12px; - color: var(--text-faint); +.mock-time-spine { + display: grid; + gap: 10px; + margin: 0; + padding: 10px; + list-style: none; +} + +.mock-time-spine li { + display: grid; + gap: 5px; + border: 1px solid oklch(0.72 0.012 250 / 0.11); + border-radius: 10px; + padding: 10px; + background: oklch(0.97 0.008 250 / 0.03); +} + +.mock-time-spine time { + color: var(--accent); font-family: var(--font-mono), monospace; - font-size: 0.68rem; + font-size: 0.72rem; } -.mock-replay-times strong { - color: var(--green); +.mock-atlas-grid { + display: grid; + grid-template-columns: minmax(540px, 1.35fr) minmax(320px, 0.8fr); + grid-template-areas: + "map symbols" + "map correlation"; + gap: 10px; } -.mock-symbol-brief { - padding-bottom: 12px; +.mock-atlas-map { + grid-area: map; } -.mock-brief-price, -.mock-brief-tags { - display: flex; - align-items: center; - gap: 8px; - padding: 12px 12px 0; - flex-wrap: wrap; +.mock-atlas-symbols { + grid-area: symbols; } -.mock-symbol-brief p { - margin: 12px 12px 0; +.mock-atlas-correlation { + grid-area: correlation; } -@keyframes mockTicker { - from { - transform: translateX(0); - } - - to { - transform: translateX(-50%); - } +.mock-atlas-field { + position: relative; + min-height: 570px; + margin: 10px; + border: 1px solid oklch(0.72 0.012 250 / 0.12); + border-radius: 10px; + background: + radial-gradient(circle at 30% 35%, oklch(0.78 0.12 74 / 0.14), transparent 18%), + radial-gradient(circle at 72% 62%, oklch(0.72 0.13 247 / 0.12), transparent 22%), + linear-gradient(0deg, oklch(0.72 0.012 250 / 0.07) 1px, transparent 1px) 0 0 / 100% 54px, + linear-gradient(90deg, oklch(0.72 0.012 250 / 0.07) 1px, transparent 1px) 0 0 / 64px 100%, + oklch(0.11 0.012 250); } -@media (prefers-reduced-motion: reduce) { - .mock-ticker-track { - animation: none; - } +.mock-atlas-node { + position: absolute; + left: var(--x); + top: var(--y); + width: clamp(130px, calc(var(--heat) * 1.8px), 190px); + min-height: clamp(88px, calc(var(--heat) * 1.1px), 126px); + display: grid; + align-content: center; + gap: 6px; + transform: translate(-50%, -50%); + border: 1px solid oklch(0.78 0.12 74 / 0.36); + border-radius: 12px; + padding: 14px; + background: + radial-gradient(circle at 50% 20%, oklch(0.78 0.12 74 / 0.16), transparent 62%), + oklch(0.15 0.014 246 / 0.96); +} + +.mock-atlas-node strong { + font-size: 0.9rem; +} + +.mock-atlas-node span { + color: var(--accent); + font-family: var(--font-mono), monospace; + font-size: 0.72rem; +} + +.mock-cluster-row { + margin: 10px 10px 0; + padding: 10px; +} + +.mock-cluster-row:last-child { + margin-bottom: 10px; } @media (max-width: 1180px) { - .mock-header { + .mock-redesign-header, + .mock-canvas-grid, + .mock-queue-grid, + .mock-replay-grid, + .mock-atlas-grid { grid-template-columns: 1fr; } - .mock-header-tools, - .mock-switcher { + .mock-redesign-meta, + .mock-redesign-switcher { justify-content: flex-start; } - .mock-grid-classic, - .mock-grid-focus, - .mock-grid-signals, - .mock-grid-replay { - grid-template-columns: 1fr; - grid-template-areas: - "replay" - "brief" - "signals" - "chart" - "tape" - "context" - "feed" - "dark"; + .mock-symbol-strip { + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); } - .mock-grid-classic { - grid-template-areas: - "tape" - "chart" - "signals" - "feed" - "dark" - "context" - "replay"; + .mock-canvas-grid, + .mock-queue-grid, + .mock-replay-grid, + .mock-atlas-grid { + grid-template-areas: none; + } + + .mock-canvas-grid > *, + .mock-queue-grid > *, + .mock-replay-grid > *, + .mock-atlas-grid > * { + grid-area: auto; } } @media (max-width: 720px) { - .mock-terminal { + .mock-redesign { padding: 12px; } - .mock-table { - overflow-x: auto; + .mock-redesign-title h1 { + font-size: 1.28rem; } - .mock-table-row { - width: max-content; - min-width: 100%; + .mock-case-heading, + .mock-chart-topline, + .mock-replay-hero { + grid-template-columns: 1fr; + display: grid; } - .mock-event-layout { + .mock-confidence { + width: fit-content; + } + + .mock-atlas-field { + min-height: 460px; + } + + .mock-atlas-node { + width: 128px; + min-height: 92px; + } +} + +.mock-shell { + min-height: 100vh; + background: oklch(0.11 0.018 262); +} + +.mock-skip-link { + border-color: oklch(0.82 0.11 184 / 0.58); + background: oklch(0.11 0.018 262); + color: oklch(0.9 0.08 184); +} + +.mock-redesign { + --mock-bg: oklch(0.12 0.018 262); + --mock-surface: oklch(0.18 0.02 262); + --mock-surface-2: oklch(0.145 0.018 262); + --mock-line: oklch(0.74 0.028 262 / 0.22); + --mock-line-strong: oklch(0.78 0.11 184 / 0.48); + --mock-ink: oklch(0.93 0.014 250); + --mock-muted: oklch(0.76 0.024 248); + --mock-faint: oklch(0.62 0.03 248); + --mock-accent: oklch(0.78 0.14 184); + --mock-accent-soft: oklch(0.78 0.14 184 / 0.13); + --mock-alt: oklch(0.72 0.16 328); + --mock-alt-soft: oklch(0.72 0.16 328 / 0.13); + --mock-good: oklch(0.77 0.16 158); + --mock-good-soft: oklch(0.77 0.16 158 / 0.13); + --mock-bad: oklch(0.68 0.18 24); + --mock-bad-soft: oklch(0.68 0.18 24 / 0.14); + --mock-info: oklch(0.72 0.14 236); + --mock-info-soft: oklch(0.72 0.14 236 / 0.13); + min-height: 100vh; + padding: 22px; + color: var(--mock-ink); + background: + linear-gradient(90deg, oklch(0.14 0.03 262) 0 1px, transparent 1px 100%) 0 0 / 72px 72px, + linear-gradient(180deg, var(--mock-surface-2), var(--mock-bg) 36vh), + var(--mock-bg); + font-family: var(--font-sans), system-ui, sans-serif; +} + +.mock-redesign.mock-desk { + --mock-bg: oklch(0.96 0.008 248); + --mock-surface: oklch(0.995 0.002 248); + --mock-surface-2: oklch(0.91 0.018 222); + --mock-line: oklch(0.42 0.04 236 / 0.2); + --mock-line-strong: oklch(0.54 0.14 216 / 0.5); + --mock-ink: oklch(0.19 0.03 244); + --mock-muted: oklch(0.38 0.036 244); + --mock-faint: oklch(0.5 0.035 244); + --mock-accent: oklch(0.5 0.16 218); + --mock-accent-soft: oklch(0.5 0.16 218 / 0.11); + --mock-alt: oklch(0.52 0.17 352); + --mock-alt-soft: oklch(0.52 0.17 352 / 0.1); + background: + linear-gradient(90deg, oklch(0.45 0.04 236 / 0.08) 0 1px, transparent 1px 100%) 0 0 / 72px 72px, + linear-gradient(180deg, oklch(0.9 0.022 222), var(--mock-bg) 38vh), + var(--mock-bg); +} + +.mock-redesign.mock-theatre { + --mock-bg: oklch(0.14 0.042 312); + --mock-surface: oklch(0.2 0.048 312); + --mock-surface-2: oklch(0.16 0.04 312); + --mock-line: oklch(0.78 0.05 312 / 0.22); + --mock-line-strong: oklch(0.82 0.12 82 / 0.5); + --mock-accent: oklch(0.82 0.15 82); + --mock-accent-soft: oklch(0.82 0.15 82 / 0.14); + --mock-alt: oklch(0.76 0.15 210); + --mock-alt-soft: oklch(0.76 0.15 210 / 0.14); +} + +.mock-redesign.mock-map { + --mock-bg: oklch(0.16 0.04 163); + --mock-surface: oklch(0.21 0.045 163); + --mock-surface-2: oklch(0.18 0.04 163); + --mock-line: oklch(0.78 0.05 163 / 0.22); + --mock-line-strong: oklch(0.8 0.15 137 / 0.5); + --mock-accent: oklch(0.82 0.17 137); + --mock-accent-soft: oklch(0.82 0.17 137 / 0.14); + --mock-alt: oklch(0.74 0.16 52); + --mock-alt-soft: oklch(0.74 0.16 52 / 0.14); +} + +.mock-redesign.mock-options { + --mock-bg: oklch(0.075 0.02 250); + --mock-surface: oklch(0.105 0.024 250); + --mock-surface-2: oklch(0.13 0.03 250); + --mock-line: oklch(0.76 0.048 236 / 0.26); + --mock-line-strong: oklch(0.82 0.16 82 / 0.58); + --mock-accent: oklch(0.86 0.17 84); + --mock-accent-soft: oklch(0.86 0.17 84 / 0.12); + --mock-alt: oklch(0.74 0.2 32); + --mock-alt-soft: oklch(0.74 0.2 32 / 0.13); + background: + linear-gradient(90deg, oklch(0.7 0.05 240 / 0.11) 1px, transparent 1px) 0 0 / 34px 34px, + linear-gradient(180deg, oklch(0.11 0.026 250), var(--mock-bg) 42vh), + var(--mock-bg); +} + +.mock-redesign.mock-packets { + --mock-bg: oklch(0.13 0.014 198); + --mock-surface: oklch(0.17 0.022 198); + --mock-surface-2: oklch(0.11 0.018 198); + --mock-line: oklch(0.76 0.04 198 / 0.22); + --mock-line-strong: oklch(0.78 0.15 176 / 0.54); + --mock-accent: oklch(0.78 0.15 176); + --mock-accent-soft: oklch(0.78 0.15 176 / 0.13); + --mock-alt: oklch(0.77 0.14 300); + --mock-alt-soft: oklch(0.77 0.14 300 / 0.13); +} + +.mock-redesign.mock-alerts { + --mock-bg: oklch(0.11 0.026 22); + --mock-surface: oklch(0.16 0.032 22); + --mock-surface-2: oklch(0.13 0.028 22); + --mock-line: oklch(0.8 0.04 42 / 0.23); + --mock-line-strong: oklch(0.8 0.17 58 / 0.54); + --mock-accent: oklch(0.8 0.17 58); + --mock-accent-soft: oklch(0.8 0.17 58 / 0.13); + --mock-alt: oklch(0.74 0.16 24); + --mock-alt-soft: oklch(0.74 0.16 24 / 0.14); +} + +.mock-redesign.mock-graph { + --mock-bg: oklch(0.1 0.026 274); + --mock-surface: oklch(0.155 0.034 274); + --mock-surface-2: oklch(0.125 0.03 274); + --mock-line: oklch(0.78 0.05 274 / 0.22); + --mock-line-strong: oklch(0.76 0.17 220 / 0.52); + --mock-accent: oklch(0.76 0.17 220); + --mock-accent-soft: oklch(0.76 0.17 220 / 0.13); + --mock-alt: oklch(0.78 0.16 340); + --mock-alt-soft: oklch(0.78 0.16 340 / 0.13); +} + +.mock-redesign.mock-command { + --mock-bg: oklch(0.092 0.018 238); + --mock-surface: oklch(0.132 0.022 238); + --mock-surface-2: oklch(0.112 0.02 238); + --mock-line: oklch(0.76 0.04 238 / 0.24); + --mock-line-strong: oklch(0.8 0.15 84 / 0.52); + --mock-accent: oklch(0.82 0.16 84); + --mock-accent-soft: oklch(0.82 0.16 84 / 0.13); + --mock-alt: oklch(0.74 0.16 28); + --mock-alt-soft: oklch(0.74 0.16 28 / 0.13); +} + +.mock-redesign.mock-radar { + --mock-bg: oklch(0.102 0.022 184); + --mock-surface: oklch(0.145 0.028 184); + --mock-surface-2: oklch(0.118 0.024 184); + --mock-line: oklch(0.78 0.044 184 / 0.23); + --mock-line-strong: oklch(0.78 0.16 176 / 0.52); + --mock-accent: oklch(0.78 0.16 176); + --mock-accent-soft: oklch(0.78 0.16 176 / 0.13); + --mock-alt: oklch(0.8 0.15 80); + --mock-alt-soft: oklch(0.8 0.15 80 / 0.13); +} + +.mock-redesign.mock-risk { + --mock-bg: oklch(0.105 0.026 16); + --mock-surface: oklch(0.145 0.032 16); + --mock-surface-2: oklch(0.118 0.028 16); + --mock-line: oklch(0.78 0.04 32 / 0.24); + --mock-line-strong: oklch(0.76 0.16 36 / 0.52); + --mock-accent: oklch(0.76 0.16 36); + --mock-accent-soft: oklch(0.76 0.16 36 / 0.13); + --mock-alt: oklch(0.78 0.14 326); + --mock-alt-soft: oklch(0.78 0.14 326 / 0.13); +} + +.mock-redesign.mock-source { + --mock-bg: oklch(0.095 0.018 268); + --mock-surface: oklch(0.138 0.024 268); + --mock-surface-2: oklch(0.112 0.022 268); + --mock-line: oklch(0.78 0.044 268 / 0.23); + --mock-line-strong: oklch(0.74 0.15 220 / 0.52); + --mock-accent: oklch(0.74 0.15 220); + --mock-accent-soft: oklch(0.74 0.15 220 / 0.13); + --mock-alt: oklch(0.82 0.15 86); + --mock-alt-soft: oklch(0.82 0.15 86 / 0.13); +} + +.mock-nav { + display: grid; + grid-template-columns: auto minmax(0, 1fr) auto; + grid-template-areas: + "brand tabs now" + "hero hero hero"; + gap: 14px; + align-items: start; + margin: 0 auto 18px; + max-width: 1600px; +} + +.mock-brand { + grid-area: brand; + display: inline-flex; + align-items: center; + gap: 10px; + min-height: 44px; + color: var(--mock-ink); + font-weight: 700; +} + +.mock-brand span { + display: grid; + place-items: center; + width: 38px; + height: 38px; + border-radius: 10px; + background: var(--mock-accent); + color: var(--mock-bg); + font-family: var(--font-mono), monospace; +} + +.mock-brand strong, +.mock-now, +.mock-route-tabs a span, +.mock-panel > header h2, +.mock-hero p, +.mock-flow-row.is-head, +.mock-facts dt, +.mock-desk-rail strong, +.mock-desk-rail button { + font-family: var(--font-mono), ui-monospace, monospace; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.mock-route-tabs { + grid-area: tabs; + min-width: 0; + display: flex; + gap: 8px; + overflow-x: auto; + padding-bottom: 2px; +} + +.mock-route-tabs a { + min-width: 142px; + min-height: 52px; + display: grid; + gap: 3px; + align-content: center; + border: 1px solid var(--mock-line); + border-radius: 12px; + padding: 8px 11px; + color: var(--mock-muted); + background: oklch(from var(--mock-surface) l c h / 0.72); +} + +.mock-route-tabs a:hover, +.mock-route-tabs a:focus-visible { + border-color: var(--mock-line-strong); + color: var(--mock-ink); + outline: none; +} + +.mock-route-tabs a.is-active { + border-color: var(--mock-line-strong); + background: var(--mock-accent-soft); + color: var(--mock-ink); +} + +.mock-route-tabs a span, +.mock-now span { + color: var(--mock-faint); + font-size: 0.62rem; +} + +.mock-route-tabs a strong { + font-size: 0.88rem; +} + +.mock-now { + grid-area: now; + display: grid; + gap: 4px; + justify-items: end; + border: 1px solid var(--mock-line); + border-radius: 12px; + padding: 9px 11px; + color: var(--mock-muted); + background: oklch(from var(--mock-surface) l c h / 0.72); + font-size: 0.68rem; +} + +.mock-now strong { + color: var(--mock-ink); + font-size: 0.82rem; +} + +.mock-hero { + grid-area: hero; + display: grid; + grid-template-columns: minmax(180px, 0.36fr) minmax(260px, 0.74fr) minmax(360px, 1fr); + gap: 18px; + align-items: end; + border-top: 1px solid var(--mock-line); + padding-top: 18px; +} + +.mock-hero p, +.mock-hero h1, +.mock-hero span { + margin: 0; +} + +.mock-hero p { + color: var(--mock-accent); + font-size: 0.72rem; +} + +.mock-hero h1 { + font-size: 2.05rem; + line-height: 1.02; + letter-spacing: -0.02em; + text-wrap: balance; +} + +.mock-hero span { + max-width: 72ch; + color: var(--mock-muted); + font-size: 0.94rem; + line-height: 1.5; + text-wrap: pretty; +} + +.mock-panel { + min-width: 0; + overflow: hidden; + border: 1px solid var(--mock-line); + border-radius: 12px; + background: oklch(from var(--mock-surface) l c h / 0.94); +} + +.mock-panel > header { + display: flex; + align-items: center; + min-height: 40px; + border-bottom: 1px solid var(--mock-line); + padding: 10px 12px; +} + +.mock-panel > header h2 { + margin: 0; + color: var(--mock-muted); + font-size: 0.68rem; +} + +.mock-badge { + width: fit-content; + max-width: 100%; + min-height: 24px; + display: inline-flex; + align-items: center; + justify-content: center; + border: 1px solid currentColor; + border-radius: 999px; + padding: 3px 8px; + font-family: var(--font-mono), ui-monospace, monospace; + font-size: 0.65rem; + line-height: 1; + white-space: nowrap; +} + +.mock-badge.is-bullish { + color: var(--mock-good); + background: var(--mock-good-soft); +} + +.mock-badge.is-bearish { + color: var(--mock-bad); + background: var(--mock-bad-soft); +} + +.mock-badge.is-watch { + color: var(--mock-alt); + background: var(--mock-alt-soft); +} + +.mock-badge.is-info { + color: var(--mock-info); + background: var(--mock-info-soft); +} + +.mock-court-layout, +.mock-desk-layout, +.mock-theatre-layout, +.mock-map-layout { + max-width: 1600px; + margin: 0 auto; + display: grid; + gap: 12px; +} + +.mock-court-layout { + grid-template-columns: minmax(320px, 0.9fr) minmax(440px, 1.2fr) minmax(280px, 0.72fr); + grid-template-areas: + "verdict chart objections" + "exhibits chart objections"; +} + +.mock-verdict { + grid-area: verdict; + padding-bottom: 14px; +} + +.mock-exhibits { + grid-area: exhibits; +} + +.mock-court-chart { + grid-area: chart; +} + +.mock-objections { + grid-area: objections; +} + +.mock-verdict-mark { + width: fit-content; + margin: 14px 14px 0; + border-radius: 999px; + padding: 5px 10px; + background: var(--mock-accent); + color: var(--mock-bg); + font-family: var(--font-mono), monospace; + font-weight: 700; +} + +.mock-verdict h2, +.mock-workspace-head h2, +.mock-stage-head h2 { + margin: 10px 14px 0; + font-size: 1.36rem; + line-height: 1.12; + letter-spacing: -0.01em; + text-wrap: balance; +} + +.mock-verdict p, +.mock-workspace-head p { + margin: 10px 14px 0; + color: var(--mock-muted); + line-height: 1.5; +} + +.mock-verdict-actions { + display: flex; + gap: 8px; + flex-wrap: wrap; + padding: 16px 14px 0; +} + +.mock-verdict-actions button, +.mock-stage-controls button, +.mock-desk-rail button { + min-height: 34px; + border: 1px solid var(--mock-line); + border-radius: 10px; + padding: 7px 10px; + background: var(--mock-surface-2); + color: var(--mock-ink); + cursor: pointer; +} + +.mock-verdict-actions button:hover, +.mock-verdict-actions button:focus-visible, +.mock-stage-controls button:hover, +.mock-stage-controls button:focus-visible, +.mock-desk-rail button:hover, +.mock-desk-rail button:focus-visible, +.mock-desk-rail button.is-active { + border-color: var(--mock-line-strong); + background: var(--mock-accent-soft); + outline: none; +} + +.mock-evidence-stack, +.mock-health, +.mock-facts { + display: grid; + gap: 9px; + padding: 12px; +} + +.mock-evidence, +.mock-desk-ticket, +.mock-cluster, +.mock-health div, +.mock-facts div, +.mock-script li { + min-width: 0; + border: 1px solid var(--mock-line); + border-radius: 10px; + background: oklch(from var(--mock-surface-2) l c h / 0.72); +} + +.mock-evidence { + display: grid; + gap: 7px; + padding: 10px; +} + +.mock-evidence > span, +.mock-evidence em, +.mock-desk-ticket time, +.mock-desk-ticket em, +.mock-stage-head span, +.mock-script time, +.mock-script span, +.mock-cluster span, +.mock-flow-row span { + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; + font-style: normal; +} + +.mock-evidence strong, +.mock-desk-ticket strong, +.mock-cluster strong, +.mock-flow-row strong { + color: var(--mock-ink); + font-family: var(--font-mono), monospace; +} + +.mock-evidence div { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} + +.mock-chart { + display: grid; + gap: 12px; + padding: 12px; +} + +.mock-chart-readout { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.mock-chart-readout span { + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.72rem; +} + +.mock-chart-readout strong { + margin-right: auto; + color: var(--mock-ink); + font-family: var(--font-mono), monospace; + font-size: 1.18rem; +} + +.mock-bars { + position: relative; + min-height: 340px; + display: flex; + align-items: end; + gap: 4px; + border: 1px solid var(--mock-line); + border-radius: 10px; + padding: 14px 10px; + overflow: hidden; + background: + linear-gradient(0deg, var(--mock-line) 1px, transparent 1px) 0 0 / 100% 54px, + var(--mock-surface-2); +} + +.mock-bars span, +.mock-volume span { + flex: 1 1 4px; + min-width: 3px; + height: var(--height); + border-radius: 999px 999px 2px 2px; +} + +.mock-bars .is-up, +.mock-volume .is-up { + background: var(--mock-good); +} + +.mock-bars .is-down, +.mock-volume .is-down { + background: var(--mock-bad); +} + +.mock-bars i { + position: absolute; + top: 12px; + bottom: 12px; + left: 63%; + width: 2px; + border-radius: 999px; + background: var(--mock-accent); + color: var(--mock-accent); + font-family: var(--font-mono), monospace; + font-size: 0.62rem; + font-style: normal; + white-space: nowrap; +} + +.mock-bars i::after { + content: attr(data-empty); +} + +.mock-bars i { + text-indent: 8px; +} + +.mock-volume { + height: 72px; + display: flex; + align-items: end; + gap: 5px; +} + +.mock-facts { + margin: 0; +} + +.mock-facts div { + padding: 10px; +} + +.mock-facts dt { + margin-bottom: 5px; + color: var(--mock-faint); + font-size: 0.64rem; +} + +.mock-facts dd { + margin: 0; + color: var(--mock-muted); + font-size: 0.86rem; + line-height: 1.42; +} + +.mock-desk-layout { + grid-template-columns: 146px minmax(330px, 0.88fr) minmax(420px, 1.18fr) minmax(280px, 0.72fr); + grid-template-areas: "rail queue workspace health"; +} + +.mock-desk-rail { + grid-area: rail; + display: grid; + align-content: start; + gap: 8px; + border: 1px solid var(--mock-line); + border-radius: 12px; + padding: 10px; + background: var(--mock-surface); +} + +.mock-desk-rail strong { + color: var(--mock-faint); + font-size: 0.64rem; +} + +.mock-desk-rail button { + width: 100%; + justify-content: start; + color: var(--mock-muted); + font-size: 0.64rem; + text-align: left; +} + +.mock-queue-board { + grid-area: queue; +} + +.mock-desk-workspace { + grid-area: workspace; +} + +.mock-desk-health { + grid-area: health; +} + +.mock-desk-ticket { + display: grid; + grid-template-columns: 50px minmax(0, 1fr) auto; + gap: 10px; + align-items: start; + margin: 10px 10px 0; + padding: 10px; +} + +.mock-desk-ticket:last-child { + margin-bottom: 10px; +} + +.mock-desk-ticket.is-selected { + border-color: var(--mock-line-strong); + background: var(--mock-accent-soft); +} + +.mock-desk-ticket div { + min-width: 0; + display: grid; + gap: 4px; +} + +.mock-desk-ticket span { + color: var(--mock-muted); + font-size: 0.8rem; + line-height: 1.35; +} + +.mock-workspace-head { + padding: 2px 0 8px; +} + +.mock-workspace-head span { + display: inline-flex; + margin: 14px 14px 0; + border-radius: 999px; + padding: 5px 10px; + background: var(--mock-accent-soft); + color: var(--mock-accent); + font-family: var(--font-mono), monospace; +} + +.mock-health div { + display: grid; + grid-template-columns: minmax(54px, 1fr) auto auto; + gap: 8px; + align-items: center; + padding: 9px; +} + +.mock-health span { + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; +} + +.mock-theatre-layout { + grid-template-columns: minmax(260px, 0.7fr) minmax(520px, 1.3fr) minmax(280px, 0.72fr); + grid-template-areas: + "script stage stage" + "script tape notes"; +} + +.mock-stage { + grid-area: stage; +} + +.mock-script { + grid-area: script; +} + +.mock-theatre-tape { + grid-area: tape; +} + +.mock-director-notes { + grid-area: notes; +} + +.mock-stage-head { + display: flex; + justify-content: space-between; + gap: 14px; + padding: 12px; +} + +.mock-stage-head h2 { + margin-left: 0; +} + +.mock-stage-controls { + display: flex; + align-items: flex-start; + justify-content: flex-end; + gap: 8px; + flex-wrap: wrap; +} + +.mock-stage-controls strong { + min-height: 34px; + display: inline-flex; + align-items: center; + border-radius: 10px; + padding: 7px 10px; + background: var(--mock-alt-soft); + color: var(--mock-alt); + font-family: var(--font-mono), monospace; +} + +.mock-replay-rail { + display: grid; + grid-template-columns: auto minmax(0, 1fr) auto auto; + gap: 10px; + align-items: center; + padding: 0 12px 12px; + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.7rem; +} + +.mock-replay-rail div { + position: relative; + height: 28px; + border: 1px solid var(--mock-line); + border-radius: 999px; + background: linear-gradient( + 90deg, + var(--mock-info-soft) 0 54%, + var(--mock-accent-soft) 54% 66%, + var(--mock-surface-2) 66% + ); +} + +.mock-replay-rail i { + position: absolute; + top: 3px; + bottom: 3px; + left: 64%; + width: 3px; + border-radius: 999px; + background: var(--mock-accent); +} + +.mock-script ol { + display: grid; + gap: 9px; + margin: 0; + padding: 12px; + list-style: none; +} + +.mock-script li { + display: grid; + gap: 5px; + padding: 10px; +} + +.mock-script strong { + color: var(--mock-ink); +} + +.mock-flow-table { + overflow-x: auto; + padding: 10px; +} + +.mock-flow-row { + min-width: 620px; + min-height: 36px; + display: grid; + grid-template-columns: 48px 64px minmax(160px, 1fr) 72px 82px 86px; + gap: 10px; + align-items: center; + border-bottom: 1px solid var(--mock-line); + color: var(--mock-muted); + font-size: 0.76rem; +} + +.mock-flow-row:last-child { + border-bottom: 0; +} + +.mock-flow-row.is-head { + min-height: 28px; + color: var(--mock-faint); + font-size: 0.64rem; +} + +.mock-map-layout { + grid-template-columns: minmax(520px, 1.38fr) minmax(320px, 0.82fr); + grid-template-areas: + "canvas index" + "canvas flow"; +} + +.mock-map-canvas { + grid-area: canvas; +} + +.mock-map-index { + grid-area: index; +} + +.mock-map-flow { + grid-area: flow; +} + +.mock-territory { + position: relative; + min-height: 610px; + margin: 12px; + border: 1px solid var(--mock-line); + border-radius: 12px; + overflow: hidden; + background: + linear-gradient(0deg, var(--mock-line) 1px, transparent 1px) 0 0 / 100% 58px, + linear-gradient(90deg, var(--mock-line) 1px, transparent 1px) 0 0 / 70px 100%, + var(--mock-surface-2); +} + +.mock-territory-node { + position: absolute; + left: var(--x); + top: var(--y); + width: clamp(136px, calc(var(--heat) * 1.9px), 196px); + min-height: clamp(86px, calc(var(--heat) * 1.08px), 128px); + display: grid; + align-content: center; + gap: 7px; + transform: translate(-50%, -50%); + border: 1px solid var(--mock-line-strong); + border-radius: 12px; + padding: 13px; + background: color-mix( + in oklch, + var(--mock-surface) 84%, + var(--mock-accent) calc(var(--heat) * 0.16%) + ); +} + +.mock-territory-node strong, +.mock-territory-node span { + position: relative; + z-index: 1; +} + +.mock-territory-node span { + color: var(--mock-accent); + font-family: var(--font-mono), monospace; + font-size: 0.74rem; +} + +.mock-cluster { + display: grid; + grid-template-columns: minmax(0, 1fr) 86px; + gap: 12px; + align-items: center; + margin: 10px 10px 0; + padding: 10px; +} + +.mock-cluster:last-child { + margin-bottom: 10px; +} + +.mock-cluster div { + min-width: 0; + display: grid; + gap: 4px; +} + +.mock-meter { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 8px; + align-items: center; +} + +.mock-meter i { + height: 8px; + border-radius: 999px; + background: linear-gradient( + 90deg, + var(--mock-accent) var(--value), + var(--mock-line) var(--value) + ); +} + +.mock-meter em { + color: var(--mock-muted); + font-family: var(--font-mono), monospace; + font-size: 0.72rem; + font-style: normal; +} + +.mock-options-layout, +.mock-packet-layout, +.mock-alert-layout, +.mock-graph-layout { + max-width: 1600px; + margin: 0 auto; + display: grid; + gap: 12px; +} + +.mock-options-layout { + grid-template-columns: minmax(720px, 1fr) 270px; + grid-template-areas: + "command depth" + "tape depth" + "ladder ladder"; +} + +.mock-options-command { + grid-area: command; + display: flex; + flex-wrap: wrap; + gap: 7px; + border-block: 1px solid var(--mock-line); + padding: 8px 0; +} + +.mock-options-command button { + min-height: 30px; + border: 1px solid var(--mock-line); + border-radius: 4px; + padding: 5px 9px; + background: transparent; + color: var(--mock-muted); + font-family: var(--font-mono), monospace; + font-size: 0.64rem; + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.mock-options-command button:hover, +.mock-options-command button:focus-visible, +.mock-options-command button.is-active { + border-color: var(--mock-line-strong); + color: var(--mock-accent); + outline: none; +} + +.mock-options-tape { + grid-area: tape; + overflow-x: auto; + border-block: 1px solid var(--mock-line); + background: oklch(from var(--mock-surface) l c h / 0.54); +} + +.mock-options-row { + min-width: 1060px; + min-height: 38px; + display: grid; + grid-template-columns: 116px 64px minmax(170px, 1fr) 86px 92px 110px 70px 82px 96px; + gap: 10px; + align-items: center; + border-bottom: 1px solid var(--mock-line); + padding: 0 10px; + color: var(--mock-muted); + font-family: var(--font-mono), monospace; + font-size: 0.72rem; +} + +.mock-options-row:last-child { + border-bottom: 0; +} + +.mock-options-row.is-head { + min-height: 30px; + color: var(--mock-faint); + font-size: 0.62rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.mock-options-row:not(.is-head):hover { + background: var(--mock-accent-soft); +} + +.mock-options-row.is-candidate, +.mock-options-row.is-join, +.mock-options-row.is-confirm { + color: var(--mock-ink); +} + +.mock-options-row.is-reject { + color: color-mix(in oklch, var(--mock-bad) 70%, var(--mock-muted)); +} + +.mock-options-depth { + grid-area: depth; + border-block: 1px solid var(--mock-line); + padding-block: 12px; +} + +.mock-options-depth h2, +.mock-packet-inspector h2, +.mock-alert-reason h2 { + margin: 0 0 12px; + font-size: 1rem; + letter-spacing: -0.01em; +} + +.mock-options-depth dl { + display: grid; + gap: 0; + margin: 0; +} + +.mock-options-depth div, +.mock-graph-routes div { + display: grid; + gap: 4px; + border-top: 1px solid var(--mock-line); + padding: 11px 0; +} + +.mock-options-depth div:last-child, +.mock-graph-routes div:last-child { + border-bottom: 1px solid var(--mock-line); +} + +.mock-options-depth dt, +.mock-flow-ladder span, +.mock-graph-routes span { + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.66rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.mock-options-depth dd { + margin: 0; + color: var(--mock-ink); + font-family: var(--font-mono), monospace; + font-size: 1.12rem; +} + +.mock-flow-ladder { + grid-area: ladder; + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + border-block: 1px solid var(--mock-line); +} + +.mock-flow-ladder div { + min-height: 70px; + display: grid; + align-content: center; + gap: 5px; + border-right: 1px solid var(--mock-line); + padding: 10px 12px; +} + +.mock-flow-ladder div:last-child { + border-right: 0; +} + +.mock-flow-ladder div.is-active { + background: var(--mock-accent-soft); +} + +.mock-flow-ladder strong { + font-size: 0.92rem; + text-transform: capitalize; +} + +.mock-packet-layout { + grid-template-columns: minmax(640px, 1.2fr) minmax(330px, 0.8fr); + grid-template-areas: + "chain inspector" + "ledger inspector"; +} + +.mock-packet-chain { + grid-area: chain; + display: grid; + grid-template-columns: repeat(5, minmax(0, 1fr)); + border-block: 1px solid var(--mock-line); +} + +.mock-packet-chain article { + min-width: 0; + display: grid; + gap: 8px; + border-right: 1px solid var(--mock-line); + padding: 12px; + background: + linear-gradient( + 180deg, + color-mix(in oklch, var(--mock-accent) calc(var(--weight) * 0.1%), transparent), + transparent 78% + ), + transparent; +} + +.mock-packet-chain article:last-child { + border-right: 0; +} + +.mock-packet-chain time, +.mock-alert-row time { + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.66rem; +} + +.mock-packet-chain strong { + font-family: var(--font-mono), monospace; + text-transform: uppercase; +} + +.mock-packet-chain p { + margin: 0; + color: var(--mock-muted); + font-size: 0.8rem; + line-height: 1.42; +} + +.mock-packet-chain span { + color: var(--mock-accent); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; +} + +.mock-packet-ledger { + grid-area: ledger; + overflow-x: auto; + border-block: 1px solid var(--mock-line); +} + +.mock-packet-row { + min-width: 760px; + min-height: 42px; + display: grid; + grid-template-columns: 98px 66px 92px 92px minmax(220px, 1fr) 60px; + gap: 10px; + align-items: center; + border-bottom: 1px solid var(--mock-line); + padding: 0 10px; + color: var(--mock-muted); + font-size: 0.76rem; +} + +.mock-packet-row:last-child { + border-bottom: 0; +} + +.mock-packet-row.is-head { + min-height: 30px; + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.62rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.mock-packet-inspector { + grid-area: inspector; + border-block: 1px solid var(--mock-line); + padding-block: 12px; +} + +.mock-alert-layout { + grid-template-columns: minmax(800px, 1fr) 320px; + grid-template-areas: "wall reason"; +} + +.mock-alert-wall { + grid-area: wall; + overflow-x: auto; + border-block: 1px solid var(--mock-line); +} + +.mock-alert-row { + min-width: 1080px; + min-height: 58px; + display: grid; + grid-template-columns: 78px 68px 118px 170px minmax(260px, 1fr) 170px 86px; + gap: 10px; + align-items: center; + border-bottom: 1px solid var(--mock-line); + padding: 0 10px; + color: var(--mock-muted); + font-size: 0.76rem; +} + +.mock-alert-row:last-child { + border-bottom: 0; +} + +.mock-alert-row.is-head { + min-height: 30px; + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.62rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.mock-alert-row.is-high { + background: var(--mock-accent-soft); + color: var(--mock-ink); +} + +.mock-alert-row p { + margin: 0; + line-height: 1.35; +} + +.mock-alert-reason { + grid-area: reason; + border-block: 1px solid var(--mock-line); + padding-block: 12px; +} + +.mock-alert-reason ol { + display: grid; + gap: 0; + margin: 0; + padding: 0; + list-style: none; +} + +.mock-alert-reason li { + display: grid; + gap: 5px; + border-top: 1px solid var(--mock-line); + padding: 12px 0; +} + +.mock-alert-reason li:last-child { + border-bottom: 1px solid var(--mock-line); +} + +.mock-alert-reason strong { + color: var(--mock-ink); +} + +.mock-alert-reason span { + color: var(--mock-muted); + font-size: 0.84rem; + line-height: 1.42; +} + +.mock-graph-layout { + grid-template-columns: minmax(720px, 1fr) 320px; + grid-template-areas: + "scope scope" + "chain inspector" + "queue invalid"; +} + +.mock-lineage-scope { + grid-area: scope; + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + border-block: 1px solid var(--mock-line); +} + +.mock-lineage-scope div { + min-width: 0; + min-height: 86px; + display: grid; + align-content: center; + gap: 5px; + border-right: 1px solid var(--mock-line); + padding: 12px; +} + +.mock-lineage-scope div:last-child { + border-right: 0; +} + +.mock-lineage-scope span, +.mock-lineage-scope em, +.mock-lineage-row time, +.mock-lineage-row span, +.mock-lineage-queue-row time, +.mock-lineage-queue-row span { + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; + font-style: normal; +} + +.mock-lineage-scope strong { + color: var(--mock-ink); + font-size: 1rem; + line-height: 1.12; +} + +.mock-lineage-chain, +.mock-lineage-queue { + overflow-x: auto; + border-block: 1px solid var(--mock-line); +} + +.mock-lineage-chain { + grid-area: chain; +} + +.mock-lineage-queue { + grid-area: queue; +} + +.mock-lineage-row { + min-width: 900px; + min-height: 44px; + display: grid; + grid-template-columns: 116px 86px minmax(210px, 1fr) 104px minmax(150px, 0.72fr) 106px; + gap: 10px; + align-items: center; + border-bottom: 1px solid var(--mock-line); + padding: 0 10px; + color: var(--mock-muted); + font-size: 0.76rem; +} + +.mock-lineage-queue-row { + min-width: 720px; + min-height: 42px; + display: grid; + grid-template-columns: 76px 66px 112px 58px minmax(170px, 1fr) 88px; + gap: 10px; + align-items: center; + border-bottom: 1px solid var(--mock-line); + padding: 0 10px; + color: var(--mock-muted); + font-size: 0.76rem; +} + +.mock-lineage-row:last-child, +.mock-lineage-queue-row:last-child { + border-bottom: 0; +} + +.mock-lineage-row.is-head, +.mock-lineage-queue-row.is-head { + min-height: 30px; + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.62rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.mock-lineage-row.is-active, +.mock-lineage-queue-row.is-active { + background: var(--mock-accent-soft); + color: var(--mock-ink); +} + +.mock-lineage-queue-row.is-reject { + color: color-mix(in oklch, var(--mock-bad) 72%, var(--mock-muted)); +} + +.mock-lineage-inspector, +.mock-lineage-invalid { + border-block: 1px solid var(--mock-line); + padding-block: 12px; +} + +.mock-lineage-inspector { + grid-area: inspector; +} + +.mock-lineage-invalid { + grid-area: invalid; +} + +.mock-lineage-inspector h2, +.mock-lineage-invalid h2 { + margin: 0 0 12px; + color: var(--mock-ink); + font-size: 1rem; + letter-spacing: -0.01em; +} + +.mock-command-layout, +.mock-radar-layout, +.mock-risk-layout, +.mock-source-layout { + min-width: 0; + max-width: 1600px; + margin: 0 auto; + display: grid; + gap: 12px; +} + +.mock-command-layout > *, +.mock-radar-layout > *, +.mock-risk-layout > *, +.mock-source-layout > * { + min-width: 0; +} + +.mock-command-layout { + grid-template-columns: minmax(760px, 1fr) 320px; + grid-template-areas: + "strip strip" + "board levels" + "flow levels"; +} + +.mock-command-strip { + grid-area: strip; + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + border-block: 1px solid var(--mock-line); +} + +.mock-command-strip div { + min-width: 0; + min-height: 86px; + display: grid; + align-content: center; + gap: 5px; + border-right: 1px solid var(--mock-line); + padding: 12px; +} + +.mock-command-strip div:last-child { + border-right: 0; +} + +.mock-command-strip span, +.mock-command-strip em, +.mock-command-row time, +.mock-command-row span, +.mock-radar-row span, +.mock-radar-row time, +.mock-risk-row span, +.mock-risk-level em, +.mock-source-row span, +.mock-source-routes span { + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.68rem; + font-style: normal; +} + +.mock-command-strip strong { + color: var(--mock-ink); + font-size: 1rem; + line-height: 1.12; +} + +.mock-command-board, +.mock-radar-board, +.mock-risk-board, +.mock-source-board { + overflow-x: auto; + border-block: 1px solid var(--mock-line); +} + +.mock-command-board { + grid-area: board; +} + +.mock-command-row { + min-width: 900px; + min-height: 42px; + display: grid; + grid-template-columns: 80px 70px 100px minmax(200px, 1fr) 126px 86px 90px; + gap: 10px; + align-items: center; + border-bottom: 1px solid var(--mock-line); + padding: 0 10px; + color: var(--mock-muted); + font-size: 0.76rem; +} + +.mock-command-row:last-child, +.mock-radar-row:last-child, +.mock-risk-row:last-child, +.mock-source-row:last-child { + border-bottom: 0; +} + +.mock-command-row.is-head, +.mock-radar-row.is-head, +.mock-risk-row.is-head, +.mock-source-row.is-head { + min-height: 30px; + color: var(--mock-faint); + font-family: var(--font-mono), monospace; + font-size: 0.62rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.mock-command-row.is-confirm, +.mock-command-row.is-hold, +.mock-radar-row.is-bullish, +.mock-source-row.is-eligible { + color: var(--mock-ink); +} + +.mock-command-row.is-reject, +.mock-radar-row.is-bearish { + color: color-mix(in oklch, var(--mock-bad) 72%, var(--mock-muted)); +} + +.mock-command-levels { + grid-area: levels; + border-block: 1px solid var(--mock-line); + padding-block: 12px; +} + +.mock-command-levels h2, +.mock-radar-context h2, +.mock-risk-notes h2, +.mock-source-audit h2 { + margin: 0 0 12px; + color: var(--mock-ink); + font-size: 1rem; + letter-spacing: -0.01em; +} + +.mock-command-flow { + grid-area: flow; +} + +.mock-radar-layout { + grid-template-columns: minmax(720px, 1fr) 320px; + grid-template-areas: + "sweep context" + "board context"; +} + +.mock-radar-sweep { + grid-area: sweep; + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + border-block: 1px solid var(--mock-line); +} + +.mock-radar-band { + min-height: 108px; + display: grid; + align-content: center; + gap: 8px; + border-right: 1px solid var(--mock-line); + padding: 12px; +} + +.mock-radar-band:last-child { + border-right: 0; +} + +.mock-radar-band.is-good { + background: var(--mock-good-soft); +} + +.mock-radar-band.is-watch { + background: var(--mock-alt-soft); +} + +.mock-radar-band.is-info { + background: var(--mock-info-soft); +} + +.mock-radar-band.is-bad { + background: var(--mock-bad-soft); +} + +.mock-radar-band strong, +.mock-risk-level strong, +.mock-source-routes strong { + color: var(--mock-ink); +} + +.mock-radar-band span { + color: var(--mock-muted); + font-family: var(--font-mono), monospace; + font-size: 0.7rem; +} + +.mock-radar-board { + grid-area: board; +} + +.mock-radar-row { + min-width: 860px; + min-height: 44px; + display: grid; + grid-template-columns: 70px 126px 72px 70px minmax(140px, 1fr) 92px 88px; + gap: 10px; + align-items: center; + border-bottom: 1px solid var(--mock-line); + padding: 0 10px; + color: var(--mock-muted); + font-size: 0.76rem; +} + +.mock-radar-context { + grid-area: context; + border-block: 1px solid var(--mock-line); + padding-block: 12px; +} + +.mock-risk-layout { + grid-template-columns: minmax(760px, 1fr) 330px; + grid-template-areas: + "board notes" + "map notes"; +} + +.mock-risk-board { + grid-area: board; +} + +.mock-risk-row { + min-width: 780px; + min-height: 48px; + display: grid; + grid-template-columns: minmax(140px, 1fr) 110px 180px 90px minmax(180px, 1fr); + gap: 10px; + align-items: center; + border-bottom: 1px solid var(--mock-line); + padding: 0 10px; + color: var(--mock-muted); + font-size: 0.76rem; +} + +.mock-risk-map { + grid-area: map; + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + border-block: 1px solid var(--mock-line); +} + +.mock-risk-level { + min-height: 150px; + display: grid; + align-content: center; + gap: 7px; + border-right: 1px solid var(--mock-line); + padding: 12px; + background: linear-gradient(180deg, var(--mock-accent-soft), transparent 72%), transparent; +} + +.mock-risk-level:last-child { + border-right: 0; +} + +.mock-risk-level.is-against { + background: linear-gradient(180deg, var(--mock-bad-soft), transparent 72%), transparent; +} + +.mock-risk-level span { + color: var(--mock-accent); + font-family: var(--font-mono), monospace; + font-size: 1.18rem; +} + +.mock-risk-notes { + grid-area: notes; + border-block: 1px solid var(--mock-line); + padding-block: 12px; +} + +.mock-source-layout { + grid-template-columns: minmax(520px, 0.92fr) minmax(340px, 0.78fr) 280px; + grid-template-areas: "board routes audit"; +} + +.mock-source-board { + grid-area: board; +} + +.mock-source-row { + min-width: 640px; + min-height: 44px; + display: grid; + grid-template-columns: minmax(90px, 1fr) 76px 92px 96px 80px; + gap: 10px; + align-items: center; + border-bottom: 1px solid var(--mock-line); + padding: 0 10px; + color: var(--mock-muted); + font-size: 0.76rem; +} + +.mock-source-row.is-degraded { + background: var(--mock-alt-soft); +} + +.mock-source-routes { + grid-area: routes; + display: grid; + border-block: 1px solid var(--mock-line); +} + +.mock-source-routes div { + min-height: 82px; + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 6px 10px; + align-content: center; + border-bottom: 1px solid var(--mock-line); + padding: 12px; +} + +.mock-source-routes div:last-child { + border-bottom: 0; +} + +.mock-source-routes span { + grid-column: 1 / -1; +} + +.mock-source-audit { + grid-area: audit; + border-block: 1px solid var(--mock-line); + padding-block: 12px; +} + +@media (max-width: 1180px) { + .mock-nav, + .mock-hero, + .mock-court-layout, + .mock-desk-layout, + .mock-theatre-layout, + .mock-map-layout, + .mock-options-layout, + .mock-packet-layout, + .mock-alert-layout, + .mock-graph-layout, + .mock-command-layout, + .mock-radar-layout, + .mock-risk-layout, + .mock-source-layout { + grid-template-columns: 1fr; + grid-template-areas: none; + } + + .mock-nav > *, + .mock-court-layout > *, + .mock-desk-layout > *, + .mock-theatre-layout > *, + .mock-map-layout > *, + .mock-options-layout > *, + .mock-packet-layout > *, + .mock-alert-layout > *, + .mock-graph-layout > *, + .mock-command-layout > *, + .mock-radar-layout > *, + .mock-risk-layout > *, + .mock-source-layout > * { + grid-area: auto; + } + + .mock-now { + justify-items: start; + } + + .mock-desk-rail { + display: flex; + flex-wrap: wrap; + align-items: center; + } + + .mock-desk-rail button { + width: auto; + } + + .mock-packet-chain, + .mock-flow-ladder, + .mock-lineage-scope, + .mock-command-strip, + .mock-radar-sweep, + .mock-risk-map { grid-template-columns: 1fr; } - .mock-signal-item { - grid-template-columns: 62px minmax(0, 1fr); + .mock-packet-chain article, + .mock-flow-ladder div, + .mock-lineage-scope div, + .mock-command-strip div, + .mock-radar-band, + .mock-risk-level { + border-right: 0; + border-bottom: 1px solid var(--mock-line); } - .mock-signal-item .mock-pill { - grid-column: 2; + .mock-packet-chain article:last-child, + .mock-flow-ladder div:last-child, + .mock-lineage-scope div:last-child, + .mock-command-strip div:last-child, + .mock-radar-band:last-child, + .mock-risk-level:last-child { + border-bottom: 0; + } +} + +@media (max-width: 720px) { + .mock-redesign { + padding: 14px; + } + + .mock-route-tabs { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + overflow-x: visible; + } + + .mock-route-tabs a { + min-width: 0; + } + + .mock-hero h1 { + font-size: 1.58rem; + } + + .mock-stage-head, + .mock-chart-readout, + .mock-desk-ticket, + .mock-cluster { + grid-template-columns: 1fr; + display: grid; + } + + .mock-bars { + min-height: 260px; + } + + .mock-territory { + min-height: 480px; + } + + .mock-territory-node { + width: 132px; + min-height: 94px; + } + + .mock-options-command button { + flex: 1 1 130px; + } + + .mock-command-strip strong, + .mock-risk-level span { + font-size: 1rem; + } + + .mock-lineage-scope strong { + font-size: 1rem; } } diff --git a/apps/web/app/mock10/page.tsx b/apps/web/app/mock10/page.tsx new file mode 100644 index 0000000..4b01348 --- /dev/null +++ b/apps/web/app/mock10/page.tsx @@ -0,0 +1,7 @@ +import { DashboardMock } from "../dashboard-mocks"; + +export const dynamic = "force-dynamic"; + +export default function Mock10Page() { + return ; +} diff --git a/apps/web/app/mock11/page.tsx b/apps/web/app/mock11/page.tsx new file mode 100644 index 0000000..e3d85bf --- /dev/null +++ b/apps/web/app/mock11/page.tsx @@ -0,0 +1,7 @@ +import { DashboardMock } from "../dashboard-mocks"; + +export const dynamic = "force-dynamic"; + +export default function Mock11Page() { + return ; +} diff --git a/apps/web/app/mock12/page.tsx b/apps/web/app/mock12/page.tsx new file mode 100644 index 0000000..efa0f0a --- /dev/null +++ b/apps/web/app/mock12/page.tsx @@ -0,0 +1,7 @@ +import { DashboardMock } from "../dashboard-mocks"; + +export const dynamic = "force-dynamic"; + +export default function Mock12Page() { + return ; +} diff --git a/apps/web/app/mock5/page.tsx b/apps/web/app/mock5/page.tsx new file mode 100644 index 0000000..29077e9 --- /dev/null +++ b/apps/web/app/mock5/page.tsx @@ -0,0 +1,7 @@ +import { DashboardMock } from "../dashboard-mocks"; + +export const dynamic = "force-dynamic"; + +export default function Mock5Page() { + return ; +} diff --git a/apps/web/app/mock6/page.tsx b/apps/web/app/mock6/page.tsx new file mode 100644 index 0000000..8ccc83b --- /dev/null +++ b/apps/web/app/mock6/page.tsx @@ -0,0 +1,7 @@ +import { DashboardMock } from "../dashboard-mocks"; + +export const dynamic = "force-dynamic"; + +export default function Mock6Page() { + return ; +} diff --git a/apps/web/app/mock7/page.tsx b/apps/web/app/mock7/page.tsx new file mode 100644 index 0000000..9ab0708 --- /dev/null +++ b/apps/web/app/mock7/page.tsx @@ -0,0 +1,7 @@ +import { DashboardMock } from "../dashboard-mocks"; + +export const dynamic = "force-dynamic"; + +export default function Mock7Page() { + return ; +} diff --git a/apps/web/app/mock8/page.tsx b/apps/web/app/mock8/page.tsx new file mode 100644 index 0000000..da1bc8d --- /dev/null +++ b/apps/web/app/mock8/page.tsx @@ -0,0 +1,7 @@ +import { DashboardMock } from "../dashboard-mocks"; + +export const dynamic = "force-dynamic"; + +export default function Mock8Page() { + return ; +} diff --git a/apps/web/app/mock9/page.tsx b/apps/web/app/mock9/page.tsx new file mode 100644 index 0000000..907c449 --- /dev/null +++ b/apps/web/app/mock9/page.tsx @@ -0,0 +1,7 @@ +import { DashboardMock } from "../dashboard-mocks"; + +export const dynamic = "force-dynamic"; + +export default function Mock9Page() { + return ; +} diff --git a/apps/web/app/terminal.test.ts b/apps/web/app/terminal.test.ts index d396602..f098985 100644 --- a/apps/web/app/terminal.test.ts +++ b/apps/web/app/terminal.test.ts @@ -41,6 +41,7 @@ const { composeTapeItems, deriveAlertDirection, countActiveFlowFilterGroups, + decodeNewsText, filterOptionTapeItems, findAnchorRestoreIndex, formatCompactUsd, @@ -554,6 +555,25 @@ describe("fixed tape virtualization config", () => { overscan: 24, debugLabel: "dark" }); + expect(getTapeVirtualConfig("news")).toEqual({ + rowHeight: 52, + overscan: 28, + debugLabel: "news" + }); + }); +}); + +describe("news text formatting", () => { + it("decodes common html entities in provider text", () => { + expect( + decodeNewsText( + "Palantir CEO Alex Karp Is 'Rooting For Elon' & Clients 'Screaming'" + ) + ).toBe("Palantir CEO Alex Karp Is 'Rooting For Elon' & Clients 'Screaming'"); + }); + + it("leaves unknown entities untouched", () => { + expect(decodeNewsText("Keep &market; literal")).toBe("Keep &market; literal"); }); }); @@ -574,9 +594,9 @@ describe("dark underlying route dependency helper", () => { }); describe("terminal navigation", () => { - it("exposes Home, Options, and News as top-level destinations", () => { + it("exposes Dashboard, Options, and News as top-level destinations", () => { expect(NAV_ITEMS).toEqual([ - { href: "/", label: "Home" }, + { href: "/", label: "Dashboard" }, { href: "/options", label: "Options" }, { href: "/news", label: "News" } ]); diff --git a/apps/web/app/terminal.tsx b/apps/web/app/terminal.tsx index d7afe6e..a61bd29 100644 --- a/apps/web/app/terminal.tsx +++ b/apps/web/app/terminal.tsx @@ -139,7 +139,7 @@ const LIVE_SESSION_HOT_CHANNELS = new Set([ "equity-overlay" ]); -type TapeVirtualPane = "options" | "equities" | "flow" | "alerts" | "classifier" | "dark"; +type TapeVirtualPane = "options" | "equities" | "flow" | "alerts" | "classifier" | "dark" | "news"; type TapeVirtualListConfig = { rowHeight: number; @@ -153,7 +153,8 @@ const TAPE_VIRTUAL_CONFIG: Record = { flow: { rowHeight: 44, overscan: 24, debugLabel: "flow" }, alerts: { rowHeight: 44, overscan: 24, debugLabel: "alerts" }, classifier: { rowHeight: 44, overscan: 24, debugLabel: "classifier" }, - dark: { rowHeight: 44, overscan: 24, debugLabel: "dark" } + dark: { rowHeight: 44, overscan: 24, debugLabel: "dark" }, + news: { rowHeight: 52, overscan: 28, debugLabel: "news" } }; export const getTapeVirtualConfig = (pane: TapeVirtualPane): TapeVirtualListConfig => @@ -1276,15 +1277,45 @@ export const formatNewsTimestamp = (ts: number, now = Date.now()): string => { }); }; +const NEWS_TEXT_ENTITIES: Record = { + amp: "&", + apos: "'", + gt: ">", + lt: "<", + nbsp: " ", + quot: '"' +}; + +export const decodeNewsText = (value: string): string => + value.replace(/&(#\d+|#x[\da-f]+|[a-z][\da-z]+);/gi, (match, entity: string) => { + if (entity[0] === "#") { + const radix = entity[1]?.toLowerCase() === "x" ? 16 : 10; + const rawCodePoint = radix === 16 ? entity.slice(2) : entity.slice(1); + const codePoint = Number.parseInt(rawCodePoint, radix); + if (!Number.isFinite(codePoint)) { + return match; + } + try { + return String.fromCodePoint(codePoint); + } catch { + return match; + } + } + + return NEWS_TEXT_ENTITIES[entity.toLowerCase()] ?? match; + }); + const sanitizeNewsHtml = ( value: string ): { html: string; fallbackText: string; sanitized: boolean } => { - const fallbackText = value - .replace(//gi, " ") - .replace(//gi, " ") - .replace(/<[^>]+>/g, " ") - .replace(/\s+/g, " ") - .trim(); + const fallbackText = decodeNewsText( + value + .replace(//gi, " ") + .replace(//gi, " ") + .replace(/<[^>]+>/g, " ") + .replace(/\s+/g, " ") + .trim() + ); try { const sanitized = value @@ -5016,13 +5047,15 @@ type NewsDrawerProps = { const NewsDrawer = ({ story, onClose }: NewsDrawerProps) => { const body = sanitizeNewsHtml(story.content_html); + const headline = decodeNewsText(story.headline); + const summary = decodeNewsText(story.summary); return (
+ )} +
); }); @@ -8736,47 +8871,341 @@ const buildCommandDeckTickers = (state: TerminalState): CommandDeckTicker[] => { }); }; +type CommandPriorityState = "confirm" | "watch" | "hold" | "reject" | "info"; + +type CommandPriorityRow = { + key: string; + ts: number; + symbol: string; + packet: string; + read: string; + score: number; + invalidation: string; + state: CommandPriorityState; + onOpen: () => void; +}; + +const clampCommandScore = (value: number): number => { + if (!Number.isFinite(value)) { + return 0; + } + return Math.max(0, Math.min(100, Math.round(value))); +}; + +const commandStateFromDirection = (direction: string): CommandPriorityState => { + const normalized = normalizeDirection(direction); + if (normalized === "bullish") { + return "confirm"; + } + if (normalized === "bearish") { + return "reject"; + } + return "watch"; +}; + +const inferCommandSymbolFromTrace = (traceId: string): string | null => { + const token = traceId + .toUpperCase() + .split(/[^A-Z0-9]+/) + .find((part) => /^[A-Z]{1,6}$/.test(part) && !["ALERT", "FLOW", "SMART"].includes(part)); + return token ?? null; +}; + +const buildCommandPriorityRows = (state: TerminalState): CommandPriorityRow[] => { + const rows: CommandPriorityRow[] = []; + + for (const event of state.filteredSmartMoneyEvents.slice(0, 8)) { + const primaryScore = + event.profile_scores.find((score) => score.profile_id === event.primary_profile_id) ?? + event.profile_scores[0]; + const read = + primaryScore?.reasons[0] ?? + (event.primary_profile_id + ? smartMoneyProfileLabel(event.primary_profile_id) + : event.event_kind); + rows.push({ + key: `smart-${event.event_id}-${event.seq}`, + ts: event.source_ts, + symbol: event.underlying_id.toUpperCase(), + packet: event.packet_ids[0] ?? event.event_id, + read, + score: clampCommandScore((primaryScore?.probability ?? 0) * 100), + invalidation: + event.packet_ids.length > 0 + ? `${event.packet_ids.length} packet${event.packet_ids.length === 1 ? "" : "s"}` + : `${formatFlowMetric(event.features.print_count)} prints`, + state: event.abstained ? "hold" : commandStateFromDirection(event.primary_direction), + onOpen: () => state.openFromSmartMoneyEvent(event) + }); + } + + for (const alert of state.filteredAlerts.slice(0, 8)) { + const primary = alert.hits[0]; + const direction = deriveAlertDirection(alert); + const severity = normalizeAlertSeverity(alert); + rows.push({ + key: `alert-${alert.trace_id}-${alert.seq}`, + ts: alert.source_ts, + symbol: inferCommandSymbolFromTrace(alert.trace_id) ?? "ALERT", + packet: getAlertFlowPacketRefs(alert)[0] ?? alert.trace_id, + read: primary?.explanations?.[0] ?? primary?.classifier_id ?? "Classifier alert", + score: clampCommandScore(alert.score), + invalidation: `${alert.evidence_refs.length} refs`, + state: + severity === "high" + ? commandStateFromDirection(direction) + : severity === "medium" + ? "watch" + : "hold", + onOpen: () => { + state.setSelectedNewsStory(null); + state.setSelectedDarkEvent(null); + state.setSelectedClassifierHit(null); + state.setSelectedSmartMoneyEvent(null); + state.setSelectedAlert(alert); + } + }); + } + + for (const packet of state.filteredFlow.slice(0, 6)) { + const contract = String(packet.features.option_contract_id ?? packet.id); + const symbol = extractUnderlying(contract); + const notional = parseNumber(packet.features.total_notional, 0); + rows.push({ + key: `flow-${packet.id}-${packet.seq}`, + ts: packet.source_ts, + symbol, + packet: packet.id, + read: + typeof packet.features.structure_type === "string" + ? packet.features.structure_type.replace(/_/g, " ") + : "Flow packet", + score: clampCommandScore(parseNumber(packet.join_quality.nbbo_coverage_ratio, 0) * 100), + invalidation: notional > 0 ? `$${formatCompactUsd(notional)}` : "packet fit", + state: "watch", + onOpen: () => state.setFilterInput(symbol) + }); + } + + for (const story of state.filteredNews.slice(0, 4)) { + rows.push({ + key: `news-${story.trace_id}-${story.seq}`, + ts: story.published_ts, + symbol: story.resolved_symbols[0]?.toUpperCase() ?? "WIRE", + packet: story.source, + read: decodeNewsText(story.headline), + score: story.resolved_symbols.length > 0 ? 55 : 25, + invalidation: getNewsWireStatus(story), + state: "info", + onOpen: () => openNewsStory(state, story) + }); + } + + return rows.sort((a, b) => b.ts - a.ts).slice(0, 8); +}; + +const CommandMetricsStrip = ({ state }: { state: TerminalState }) => { + const priorityCount = + state.filteredSmartMoneyEvents.length + state.filteredAlerts.length + state.filteredFlow.length; + const focus = state.activeTickers.length > 0 ? state.activeTickers.join(", ") : "All symbols"; + const decision = + state.selectedInstrument?.kind === "option-contract" + ? (state.selectedInstrumentLabel ?? "Contract focus") + : `${state.chartTicker.toUpperCase()} / ${formatIntervalLabel(state.chartIntervalMs)}`; + const risk = + state.filteredAlerts[0]?.severity ?? + (state.filteredInferredDark.length > 0 ? "dark context" : "no active alert"); + const metrics = [ + { + label: "Regime", + value: + state.mode === "live" ? statusLabel(state.liveSession.status, false, state.mode) : "Replay", + detail: state.lastSeen ? `last ${formatTime(state.lastSeen)}` : "waiting" + }, + { + label: "Priority", + value: `${formatFlowMetric(priorityCount)} events`, + detail: focus + }, + { + label: "Decision", + value: decision, + detail: state.selectedInstrument ? "focused instrument" : "chart context" + }, + { + label: "Risk", + value: risk, + detail: `${state.filteredNews.length} wire / ${state.filteredInferredDark.length} dark` + } + ]; + + return ( +
+ {metrics.map((metric) => ( +
+ {metric.label} + {metric.value} + {metric.detail} +
+ ))} +
+ ); +}; + +const CommandPriorityBoard = ({ state }: { state: TerminalState }) => { + const rows = useMemo(() => buildCommandPriorityRows(state), [state]); + + return ( + {rows.length} active rows} + > + {rows.length === 0 ? ( +
No priority events are available for this scope yet.
+ ) : ( +
+
+ {["Time", "Sym", "Packet", "Read", "Score", "Decision", "State"].map((label) => ( + + {label} + + ))} +
+ {rows.map((row) => ( + + ))} +
+ )} +
+ ); +}; + +const CommandDecisionLevels = ({ state }: { state: TerminalState }) => { + const topOption = state.filteredOptions[0]; + const topOptionLabel = topOption + ? (formatOptionContractLabel(normalizeContractId(topOption.option_contract_id))?.strike ?? + formatContractLabel(topOption.option_contract_id)) + : "--"; + const topAlert = state.filteredAlerts[0]; + const topDark = state.filteredInferredDark[0]; + const rows = [ + ["Focus", state.activeTickers.length > 0 ? state.activeTickers.join(", ") : state.chartTicker], + ["Contract", state.selectedInstrumentLabel ?? topOptionLabel], + ["Chart", `${state.chartTicker.toUpperCase()} ${formatIntervalLabel(state.chartIntervalMs)}`], + [ + "Evidence", + topAlert + ? `${normalizeAlertSeverity(topAlert)} alert at ${formatTime(topAlert.source_ts)}` + : topDark + ? `${humanizeClassifierId(topDark.type)} ${formatConfidence(topDark.confidence)}` + : "waiting" + ] + ]; + + return ( + current scope} + > +
+ {rows.map(([label, value]) => ( +
+
{label}
+
{value}
+
+ ))} +
+
+ ); +}; + const CommandDeckHeader = ({ state }: { state: TerminalState }) => { const focus = state.activeTickers.length > 0 ? state.activeTickers.join(", ") : state.chartTicker; - const selected = state.selectedInstrumentLabel ?? "No contract lock"; + const activeTickerFilter = state.filterInput.trim(); + const activeContractFilter = + state.selectedInstrument?.kind === "option-contract" ? state.selectedInstrumentLabel : null; const connectionLabel = state.mode === "live" ? statusLabel(state.liveSession.status, false, state.mode) : "Replay"; return ( -
-
-