/* ===================================================================== Cyclone — design system --------------------------------------------------------------------- A precision instrument for one operator on one machine. The visual language borrows from Bloomberg terminals and Linear-grade engineering tools: dark, hairline-strict, mono-heavy, with one editorial serif accent for the moments that deserve weight. --------------------------------------------------------------------- Type stack: - Geist Sans · UI, body, controls - Geist Mono · every number, every id, every code-like datum - Instrument Serif · editorial display (hero numbers, headlines) ===================================================================== */ @tailwind base; @tailwind components; @tailwind utilities; @layer base { :root { /* ---- Core surfaces ---- A graphite canvas with a whisper of blue. Slightly warm at the midtones (--card) to keep the chrome from feeling sterile. */ --background: 222 18% 5%; /* #0b0c10 — near-black, cool */ --foreground: 220 14% 96%; /* #f4f5f7 — paper white */ --card: 222 16% 8%; /* #11131a */ --card-foreground: 220 14% 96%; --popover: 222 18% 9%; /* #13151c */ --popover-foreground: 220 14% 96%; --muted: 222 12% 13%; /* #1f2229 */ --muted-foreground: 220 8% 64%; /* #9b9ea6 */ --secondary: 222 12% 13%; --secondary-foreground: 220 14% 96%; /* ---- Accents ---- Electric blue (primary) for actions and emphasis. Amber (signal) is reserved for "needs attention" states and the Inbox terminal accents — never decorative. */ --accent: 212 100% 60%; /* #2e8aff — electric, modern */ --accent-foreground: 0 0% 100%; --signal: 36 92% 56%; /* #f3a531 — warm amber */ --primary: 212 100% 60%; --primary-foreground: 0 0% 100%; --destructive: 358 82% 60%; /* #ec4458 */ --destructive-foreground: 0 0% 100%; --success: 152 64% 46%; /* #2cbd76 */ --success-foreground: 152 70% 8%; --warning: 36 92% 56%; /* #f3a531 */ --warning-foreground: 26 80% 12%; --border: 222 10% 16%; /* #262932 */ --input: 222 10% 16%; --ring: 212 100% 60%; /* ---- Sidebar ---- */ --sidebar: 222 20% 4%; /* darker than the page */ --sidebar-foreground: 220 14% 96%; --sidebar-accent: 212 100% 60%; --sidebar-border: 222 12% 12%; /* ---- Document surface (drawer detail panels) ---- A faint warm paper. Keeps detail views distinct from the chrome without going full light. Pairs with editorial serif headlines. */ --surface: 36 18% 96%; /* #f6f3ec */ --surface-ink: 30 12% 9%; /* #181614 */ --surface-ink-2: 30 6% 32%; /* #4f4b46 */ --surface-ink-3: 30 4% 52%; /* #85807a */ --surface-line: 30 14% 14%; /* #24221f */ --surface-line-soft: 30 14% 14% / 0.12; /* ---- Ticker-tape terminal (Inbox) ---- Bloomberg-coded: three accent rails on near-black, with the paper-tone ink for legibility. */ --tt-bg: 220 22% 5%; /* #0a0d12 */ --tt-bg-elev: 220 18% 9%; /* #13171f */ --tt-ink: 36 18% 88%; /* #e2ddd0 */ --tt-ink-dim: 220 6% 58%; /* #8e9098 */ --tt-amber: 36 88% 56%; /* #efa836 */ --tt-oxblood: 354 50% 40%; /* #8a2d35 */ --tt-ink-blue: 212 38% 36%; /* #2e4d77 */ --tt-muted: 220 4% 38%; /* #5b5d62 */ /* ---- Legacy aliases (--m-*) Kept as thin shims so any older component still using the "warm paper" surface family resolves to the same hue family. New components should prefer --surface-* / --destructive / etc. */ --m-surface: hsl(var(--surface)); --m-ink-primary: hsl(var(--surface-ink)); --m-ink-secondary: hsl(var(--surface-ink-2)); --m-ink-tertiary: hsl(var(--surface-ink-3)); --m-border-heavy: hsl(var(--surface-line)); --m-font-mono: var(--font-mono); --m-error: hsl(var(--destructive)); --m-error-bg: hsl(var(--destructive) / 0.08); --m-success: hsl(var(--success)); --m-warning: hsl(var(--warning)); --m-accent: hsl(var(--accent)); --radius: 0.625rem; /* 10px — slightly tighter */ /* ---- Type stack ---- */ --font-sans: "Geist", ui-sans-serif, -apple-system, BlinkMacSystemFont, system-ui, sans-serif; --font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace; --font-display: "Instrument Serif", "Iowan Old Style", "Apple Garamond", "Baskerville", "Times New Roman", serif; } * { @apply border-border; } html, body, #root { height: 100%; } body { @apply bg-background text-foreground; font-family: var(--font-sans); font-feature-settings: "ss01", "cv11", "calt"; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; /* Subtle "lit from above" wash — gives every page a slightly lighter zone in the upper third without lifting the base color. A vertical gradient + a soft top-center halo, both very low opacity. The composition is additive: a soft glow behind the page header, fading to nothing well before the fold. Pointer-events unaffected (it's a background). */ background-image: radial-gradient(ellipse 90% 38% at 50% -6%, hsla(220, 28%, 26%, 0.22), transparent 62%), linear-gradient(180deg, hsla(220, 22%, 14%, 0.30) 0%, hsla(220, 22%, 8%, 0.10) 22%, transparent 42%); background-attachment: fixed; } /* A precise top-right accent + a complementary soft top-center softbox. Two light sources, both very subtle — the result reads as "the chrome is being lit from above" rather than "there's a gradient in the background". The softbox adds the small lift the cards sit in; the accent preserves the instrument character. */ body::before { content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0; background: radial-gradient(ellipse 70% 38% at 50% 0%, hsla(220, 32%, 28%, 0.16), transparent 65%), radial-gradient(55rem 35rem at 100% -15%, hsla(212, 100%, 60%, 0.09), transparent 62%); } /* Hairline grid — the substrate of a precision instrument. Sits behind everything, gives the dark surfaces a sense of scale and the work a sense of "field". Slightly more present than before so the texture actually reads against the softer top wash. */ body::after { content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0; opacity: 0.6; background-image: linear-gradient(to right, hsl(222 10% 18% / 0.20) 1px, transparent 1px), linear-gradient(to bottom, hsl(222 10% 18% / 0.20) 1px, transparent 1px); background-size: 64px 64px; mask-image: radial-gradient(ellipse 80% 60% at 50% 30%, black 30%, transparent 80%); -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 30%, black 30%, transparent 80%); } /* Custom scrollbar — minimal, hairline, Apple-style */ ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: hsl(var(--border)); border-radius: 999px; border: 2px solid transparent; background-clip: content-box; } ::-webkit-scrollbar-thumb:hover { background: hsl(var(--muted-foreground) / 0.4); background-clip: content-box; } /* Focus ring — accent, 2px, with offset. Components override this with Tailwind focus-visible:ring-* utilities for a ring+offset combo that matches the rest of the design system. */ :focus-visible { outline: 2px solid hsl(var(--ring)); outline-offset: 2px; border-radius: 6px; } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; } } } @layer components { /* Tabular numerals everywhere a number is shown */ .num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum", "ss01"; } /* Display face — Instrument Serif. Used for the moments that need editorial weight: hero numbers, page titles in document surfaces, and the brand mark. */ .display { font-family: var(--font-display); font-weight: 400; letter-spacing: -0.015em; font-feature-settings: "ss01"; } /* Data mono — Geist Mono with tabular-nums. The voice of every id, code, dollar amount, and timestamp in the app. */ .mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; } /* Soft card surface — a 1px hairline + a 1px inner highlight to give the surface a sense of depth without a heavy shadow. The vertical gradient (lighter at top, darker at bottom) plus a slightly more present inner highlight makes the card read as a subtle "lit from above" panel — each card becomes its own small lighter area without lifting the base card color. */ .surface { background: linear-gradient( 180deg, hsl(222 16% 10.5%) 0%, hsl(222 16% 8.5%) 55%, hsl(222 16% 7.5%) 100% ); border: 1px solid hsl(var(--border)); box-shadow: inset 0 1px 0 0 hsl(0 0% 100% / 0.06), 0 1px 2px 0 hsl(0 0% 0% / 0.4); } /* Subtle elevated surface — used for cards that should lift a little more than the default. Same "lit from above" treatment as .surface, with a touch more lift in the gradient stops and a more visible inner highlight. The card body becomes a slightly more present lighter area than the surrounding chrome. */ .surface-2 { background: linear-gradient( 180deg, hsl(222 16% 11%) 0%, hsl(222 16% 9%) 55%, hsl(222 16% 7.5%) 100% ); border: 1px solid hsl(var(--border)); box-shadow: inset 0 1px 0 0 hsl(0 0% 100% / 0.08), 0 1px 3px 0 hsl(0 0% 0% / 0.5); } /* Hairline — a 1px separator that reads as a divider, not a border */ .hairline { border-color: hsl(var(--border) / 0.6); } /* Active nav indicator — a thin left-aligned accent line with a subtle glow that matches the instrument aesthetic. */ .nav-active { background-color: hsl(var(--muted) / 0.6); color: hsl(var(--foreground)); } .nav-active::before { content: ""; position: absolute; left: -0.75rem; top: 0.5rem; bottom: 0.5rem; width: 2px; border-radius: 2px; background-color: hsl(var(--accent)); box-shadow: 0 0 12px hsl(var(--accent) / 0.5); } /* Skip link — invisible until focused. */ .skip-link { position: fixed; top: 0.75rem; left: 0.75rem; z-index: 100; display: inline-flex; align-items: center; height: 2.25rem; padding: 0 0.875rem; border-radius: 0.625rem; background-color: hsl(var(--card)); color: hsl(var(--foreground)); border: 1px solid hsl(var(--border)); box-shadow: inset 0 1px 0 0 hsl(0 0% 100% / 0.04), 0 8px 24px hsl(0 0% 0% / 0.45); font-size: 12.5px; font-weight: 600; letter-spacing: 0.01em; transform: translateY(-200%); transition: transform 150ms ease-out; } .skip-link:focus-visible { transform: translateY(0); outline: none; box-shadow: inset 0 1px 0 0 hsl(0 0% 100% / 0.04), 0 0 0 2px hsl(var(--background)), 0 0 0 4px hsl(var(--ring)), 0 8px 24px hsl(0 0% 0% / 0.45); } @media (prefers-reduced-motion: reduce) { .skip-link { transition: none; } } /* Keyboard hint chip */ .kbd { display: inline-flex; align-items: center; gap: 0.15rem; height: 1.375rem; min-width: 1.375rem; padding: 0 0.4rem; border-radius: 0.375rem; border: 1px solid hsl(var(--border)); background: hsl(var(--muted) / 0.5); color: hsl(var(--muted-foreground)); font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: 0.04em; line-height: 1; } /* Section label — the all-caps eyebrow used everywhere */ .eyebrow { font-size: 10.5px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: hsl(var(--muted-foreground)); } /* Editorial serif headline — for hero numbers and document surfaces. A single line height that breathes. */ .editorial { font-family: var(--font-display); font-weight: 400; letter-spacing: -0.02em; line-height: 1.05; } /* Row hover state — slightly more refined than the default table hover. A subtle tint + a left accent strip. */ .row-hover { transition: background-color 150ms ease; } .row-hover:hover { background-color: hsl(var(--muted) / 0.4); } } @layer utilities { .text-balance { text-wrap: balance; } .text-pretty { text-wrap: pretty; } .ring-inset-hairline { box-shadow: inset 0 0 0 1px hsl(var(--border) / 0.6); } } /* ---------------------------------------------------------------------- Print styles — a clean paper-record rendering of detail drawers. ---------------------------------------------------------------------- */ @media print { aside, header, [data-print="hide"], button[aria-label^="Close"] { display: none !important; } :root { --background: #ffffff; --foreground: #000000; --card: #ffffff; --card-foreground: #000000; --muted: #f5f5f5; --muted-foreground: #444444; --border: #cccccc; --accent: #1a1a1a; } body { background: #ffffff !important; color: #000000 !important; } [role="dialog"] { position: static !important; inset: auto !important; width: 100% !important; max-width: 100% !important; height: auto !important; transform: none !important; background: #ffffff !important; box-shadow: none !important; border: none !important; } [data-state="open"][data-radix-dialog-overlay], .animate-fade-in, .animate-shimmer, .animate-scan { animation: none !important; transition: none !important; } [role="dialog"] * { overflow: visible !important; } table { page-break-inside: avoid; } section, h1, h2, h3 { page-break-after: avoid; } *, *::before, *::after { animation-duration: 0s !important; } } /* Universal drill-down affordance — applied by DrillableCell. */ .drillable { cursor: pointer; transition: background-color 120ms ease; } .drillable:hover { background-color: hsl(var(--accent) / 0.08); } .drillable:hover::after { content: "›"; margin-left: 6px; color: hsl(var(--accent)); font-weight: 600; }