/* ============================================================
   qlens — Warm Dim canvas + system UI font

   Dim canvas (#1c1c1c, three notches off true black so the
   amber accent and semantic colors stop punching). One
   accent (amber); the type is the OS system font so each
   platform keeps its native reading rhythm. Color is
   reserved for semantic state — gains, losses, market
   codes, the active rotation curve. Everything else is
   type and whitespace.

   The token *names* stay the same as the previous design
   language so per-component <style> blocks compile unchanged.
   The *values* behind those names are rewritten: glass
   surfaces collapse to flat dim, all radii stay 0, shadows
   and blurs are none, hairline rules drop to near-invisible
   so the page breathes on whitespace alone.

   `<html data-theme="oled">` is a marker, not a toggle.
   To introduce a new design language, target a new
   `[data-theme="..."]` selector on :root and override tokens
   there. The current :root tokens below ARE the warm-dim
   defaults.
   ============================================================ */

/* System UI font — no @font-face. The OS provides SF on macOS,
   Segoe UI on Windows, Roboto on Android, the platform's UI
   sans everywhere else. Numeric columns use tabular-nums. */

:root {
  color-scheme: dark;

  /* Canvas — warm dim. Three notches off true black so the amber
     accent and semantic colors stop punching; still legible as
     a dark theme. */
  --ink: #1c1c1c;
  --canvas: #1c1c1c;
  --paper: #1c1c1c;
  --paper-2: #242424;
  --paper-3: #2c2c2c;

  /* Rules — present for components that still reference them, subtle
     but visible. rule = panel frames (hairline border on cards /
     shell chrome); separator = list row dividers (must read against
     the canvas); rule-faint = inline dividers, one notch quieter than
     separator. All three stay brighter than the canvas — the previous
     `#181818` values were darker than `--canvas` and disappeared. */
  --rule: #2a2a2a;
  --rule-bold: #3a3a3a;
  --rule-faint: #242424;
  --separator: #242424;

  /* Surfaces — names preserved for component CSS. Values are
     flat dim so anything that styled against --glass-* or
     --surface inherits the no-elevation treatment. No blur,
     no shadow, no glass effect anywhere. */
  --glass-thin: #1c1c1c;
  --glass-regular: #242424;
  --glass-strong: #2c2c2c;
  --glass-edge: #2a2a2a;
  --glass-edge-soft: #181818;
  --glass-edge-strong: #3a3a3a;
  --glass-inset: none;
  --glass-shadow: none;
  --glass-filter: none;
  --glass-filter-compact: none;
  --glass-skeleton: rgba(255, 255, 255, 0.04);
  --skeleton-shimmer: rgba(255, 255, 255, 0.1);
  --surface: #1c1c1c;
  --surface-raised: #242424;
  --surface-hover: rgba(255, 255, 255, 0.03);
  --surface-pressed: rgba(255, 255, 255, 0.07);
  --surface-overlay: #1c1c1c;
  --control-flash: rgba(255, 176, 0, 0.1);

  /* Accent — single amber. The rotation curve, the splash
     bar, the active filter. Used sparingly. */
  --accent: #ffb000;
  --accent-bright: #ffd166;
  --accent-fg: #000000;
  --accent-bg: rgba(255, 176, 0, 0.1);
  --accent-edge: rgba(255, 176, 0, 0.3);
  --glow-accent: none;

  /* Semantic — vivid on black. */
  --up: #00d97e;
  --down: #ff3b5c;
  --up-fill: transparent;
  --down-fill: transparent;
  --up-edge: #00d97e;
  --down-edge: #ff3b5c;
  --mkt-us: #5eb0ff;
  --mkt-cn: #e879f9;
  --mkt-hk: #22d3ee;

  /* Text — warm-neutral, not pure white (eye fatigue on long
     sessions). Three steps of mute down to a faint baseline. */
  --text: #e6e6e2;
  --text-2: #9a9a96;
  --text-3: #5a5a56;
  --text-faint: #383834;

  /* Type scale — mobile-only, bumped one notch across the board
     from the prior trim. Body 15sp sits one notch above the 14sp
     minimum, the bottom three steps hold a tight 1px rhythm
     (14/13/12) so micro still reads as a step down from caption.
     Display + price stay paired a step apart so the detail-page
     hero price reads as the page's anchor stat without dominating
     the row. */
  --t-display: 26px;
  --t-price: 24px;
  --t-body: 15px;
  --t-sub: 14px;
  --t-caption: 13px;
  --t-micro: 12px;

  /* Tracking — three tokens cover every mono-caps role. Display
     numerals (--tracking-display) keep their own negative tracking
     because the value depends on the size being set, not the role;
     the .ql-display class and inline mono display numerals all
     pull from this one token. */
  --tracking-tight: 0.04em;
  --tracking-mid: 0.08em;
  --tracking-eyebrow: 0.16em;
  --tracking-display: -0.02em;

  /* Faces — one sans family for prose, one mono stack for numerals.
     Sans falls through the OS UI face (SF / Segoe / Roboto).
     Mono leads with JetBrains Mono from Google Fonts (loaded in
     index.html, weights 400/500/600/700, display=swap). If the
     CDN is unreachable (offline / blocked), the stack drops to
     ui-monospace then the per-platform system faces: SF Mono on
     macOS/iOS, Consolas on Windows, Liberation Mono on Fedora/RHEL,
     DejaVu Sans Mono on Debian/Ubuntu. Display + chart reuse the sans. */
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-display: var(--font);
  --font-mono:
    "JetBrains Mono", ui-monospace, "SF Mono", "SF Mono Text", Menlo, Monaco, Consolas,
    "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace;
  --font-chart: var(--font);

  /* Spacing — unchanged. */
  --pad: 16px;
  --r-2xs: 0;
  --r-xs: 0;
  --r-sm: 0;
  --r-md: 0;
  --r-lg: 0;
  --r-xl: 0;
  --r-full: 0;
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --space-2xs: 3px;
  --space-xs: 6px;
  --space-sm: 10px;
  --space-md: 14px;
  --space-lg: 18px;
  --space-xl: 26px;
  --space-2xl: 36px;

  /* Component sizing — preserved. */
  --nav-pill-h: 60px;
  --icon-btn: 40px;
  --control-shell-h: 30px;
  --control-item-h: 22px;
  --control-font: 10px;
  --control-pad-x: 8px;
  --chart-h: 220px;
  --fade-w: 28px;
  --accent-bar-h: 2px;
  --accent-eyebrow-w: 3px;

  /* Focus + selection — amber ring + amber wash. */
  --focus-offset: 2px;
  --focus-offset-inset: -2px;
  --focus-ring: 1px solid var(--accent);
  --card-shadow: none;

  /* Optical primitives. */
  --glass-inlay: none;
  --shadow-1: none;
  --shadow-2: none;

  /* Chart grid — barely-there horizontal lines, dashed y-axis. */
  --chart-grid: rgba(255, 255, 255, 0.05);
  --chart-grid-strong: rgba(255, 255, 255, 0.1);

  /* Weights — system font ships 400 / 500 / 600 / 700 on every
     supported platform; semibold = 600 so chips/eyebrows actually
     read heavier than body text (500 was visually indistinguishable
     from --w-medium). */
  --w-regular: 400;
  --w-medium: 500;
  --w-semibold: 600;
  --w-bold: 700;

  /* Motion. */
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-spring: cubic-bezier(0.22, 1.18, 0.36, 1);
  --dur-fast: 120ms;
  --dur-med: 220ms;
  --dur-slow: 380ms;
}

html.light {
  color-scheme: light;

  --ink: #1a1a18;
  --canvas: #f4f2eb;
  --paper: #f4f2eb;
  --paper-2: #ebe8e0;
  --paper-3: #ddd9cd;

  --rule: #d4d0c2;
  --rule-bold: #aea99a;
  --rule-faint: #ebe8e0;
  --separator: #ebe8e0;

  --glass-thin: #f4f2eb;
  --glass-regular: #ebe8e0;
  --glass-strong: #ddd9cd;
  --glass-edge: #d4d0c2;
  --glass-edge-soft: #ebe8e0;
  --glass-edge-strong: #aea99a;
  --glass-inset: none;
  --glass-shadow: none;
  --glass-filter: none;
  --glass-filter-compact: none;
  --glass-skeleton: rgba(0, 0, 0, 0.06);
  --skeleton-shimmer: rgba(0, 0, 0, 0.1);
  --surface: #f4f2eb;
  --surface-raised: #ebe8e0;
  --surface-hover: rgba(0, 0, 0, 0.04);
  --surface-pressed: rgba(0, 0, 0, 0.08);
  --surface-overlay: #f4f2eb;
  --control-flash: rgba(168, 112, 0, 0.14);

  --accent: #a87000;
  --accent-bright: #c9971a;
  --accent-fg: #f4f2eb;
  --accent-bg: rgba(168, 112, 0, 0.1);
  --accent-edge: rgba(168, 112, 0, 0.3);

  --up: #00875a;
  --down: #c42b48;
  --up-fill: transparent;
  --down-fill: transparent;
  --mkt-us: #2563a8;
  --mkt-cn: #9d2eb8;
  --mkt-hk: #1a7a72;

  --text: #1a1a18;
  --text-2: #5a5a55;
  --text-3: #8a8a82;
  --text-faint: #aeae9e;

  --glass-inlay: none;
  --shadow-1: none;
  --shadow-2: none;
  --card-shadow: none;
  --chart-grid: rgba(0, 0, 0, 0.08);
  --chart-grid-strong: rgba(0, 0, 0, 0.16);
}

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html {
  min-height: 100%;
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background: var(--canvas);
}
body {
  min-width: 320px;
  min-height: 100vh;
  min-height: 100dvh;
  overflow-x: hidden;
  background: var(--canvas);
  color: var(--text);
  font-size: var(--t-body);
  line-height: 1.45;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  padding-top: env(safe-area-inset-top, 0px);
  transition: color var(--dur-med) var(--ease-out);
}

/* Shared base for full-width tap-target rows (stock list, rotation
   holdings/ranks, signals). Per-view classes add layout-specific
   properties (flex, padding, gap). */
.ql-row {
  width: 100%;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.ql-row:active {
  background: var(--surface-pressed);
}
.ql-row:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset-inset);
}
@media (hover: hover) and (pointer: fine) {
  .ql-row:hover:not(:active):not(:disabled) {
    background: var(--surface-hover);
  }
}

/* Shared utilities. */

/* Up/down chip — replaces the 3 earlier recipes (sig-badge, strat-chip,
   rank-trend / win-trend / rank-win). Use variant="text" for the bare
   coloured glyphs on the rotation rank rows. */
.ql-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-mono);
  font-size: var(--t-micro);
  font-weight: var(--w-semibold);
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: var(--tracking-tight);
  white-space: nowrap;
  flex-shrink: 0;
  background: transparent;
  color: var(--text-2);
  border: 0;
}
.ql-chip--fill {
  background: transparent;
  border-color: transparent;
}
.ql-chip--fill.up {
  color: var(--up);
}
.ql-chip--fill.down {
  color: var(--down);
}
.ql-chip--edge {
  border-color: transparent;
}
.ql-chip--edge.up {
  color: var(--up);
}
.ql-chip--edge.down {
  color: var(--down);
}
.ql-chip--edge.accent {
  color: var(--accent);
}
.ql-chip--text {
  background: none;
  border: 0;
  padding: 0;
}
.ql-chip--text.up {
  color: var(--up);
}
.ql-chip--text.down {
  color: var(--down);
}

/* Pulsing status dot — RotationView pending, EmptyState.pending. */
.ql-pulse-dot {
  width: 6px;
  height: 6px;
  border-radius: 0;
  background: var(--accent);
  animation: ql-pulse 1.6s var(--ease-out) infinite;
}
@keyframes ql-pulse {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0.3;
  }
  100% {
    opacity: 1;
  }
}

/* Scroll fade masks — replaces 6 duplicated mask-image blocks across
   scrollers. Apply `ql-fade` + a `data-fade` value to opt in. */
.ql-fade[data-fade="end"] {
  mask-image: linear-gradient(to right, #000 calc(100% - var(--fade-w)), transparent);
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--fade-w)), transparent);
}
.ql-fade[data-fade="start"] {
  mask-image: linear-gradient(to right, transparent, #000 var(--fade-w));
  -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--fade-w));
}
.ql-fade[data-fade="both"] {
  mask-image: linear-gradient(
    to right,
    transparent,
    #000 var(--fade-w),
    #000 calc(100% - var(--fade-w)),
    transparent
  );
  -webkit-mask-image: linear-gradient(
    to right,
    transparent,
    #000 var(--fade-w),
    #000 calc(100% - var(--fade-w)),
    transparent
  );
}

/* Tabular numerals — every numeric cell. */
.ql-num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* Display numerals — hero return values, the eye lands on these.
   Mono on OLED still benefits from slight negative tracking; the
   tracking value is shared via --tracking-display. */
.ql-display {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-display);
}

/* Eyebrow — uppercase, tracked, used for section headers and
   tape-style metadata strips. Pulls from --font-mono by default. */
.ql-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--t-micro);
  font-weight: var(--w-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow);
  color: var(--text-2);
}

/* Hairline rule. Replaces the old Divider component for inline use.
   On OLED the rule sits just above the canvas — present but quiet. */
.ql-rule {
  height: 0;
  border: 0;
  border-top: 1px solid var(--rule);
}

/* Disabled control — `:disabled` and `[aria-disabled="true"]` both
   get the dimmed hairline treatment and `not-allowed` cursor so a
   data-missing row reads as a dead end at a glance. The hover guard
   in `.ql-row` already filters `:disabled`; this rule covers the
   button-level visuals so seg-btn / nav-item / top-bar-btn / quiet
   buttons all share the same disabled appearance. */
button:disabled,
[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.45;
}
button:disabled:focus-visible,
[aria-disabled="true"]:focus-visible {
  outline-color: var(--text-3);
}

@media (prefers-reduced-transparency: reduce) {
  :root {
    --glass-thin: #1c1c1c;
    --glass-regular: #1c1c1c;
    --glass-strong: #1c1c1c;
    --surface: #1c1c1c;
    --surface-overlay: #1c1c1c;
    --chart-grid: rgba(255, 255, 255, 0.06);
    --chart-grid-strong: rgba(255, 255, 255, 0.12);
  }
  html.light {
    --glass-thin: #f4f2eb;
    --glass-regular: #ebe8e0;
    --surface: #f4f2eb;
    --surface-overlay: #f4f2eb;
    --chart-grid: rgba(0, 0, 0, 0.1);
    --chart-grid-strong: rgba(0, 0, 0, 0.2);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

@media (prefers-contrast: more) {
  :root {
    --rule: #2a2a2a;
    --rule-bold: #3a3a3a;
    --separator: #2a2a2a;
    --text-2: #bdbdb8;
    --text-3: #8a8a86;
  }
  html.light {
    --rule: #aea99a;
    --rule-bold: #5c5c52;
    --separator: #aea99a;
    --text-2: #1a1a18;
    --text-3: #3a3a35;
  }
}
