/* ─────────────────────────────────────────────────────────────────────────
   WMW - Wavi Market Watch: design tokens + the few rules every page shares.

   docs/DESIGN.md is the authority: every token below is listed there with its
   role and its measured WCAG contrast, and tests/test_design.py re-checks those
   ratios from THIS file, so a tweak that breaks readability fails the suite.

   Loaded by BOTH shells (templates/index.html and templates/auth_base.html).
   This is the only place a colour literal may appear: components use var(--x),
   and static/app.js reads the same tokens for Chart.js (a canvas cannot).

   Dark-only by design. There is no light theme to keep in step; `color-scheme`
   tells the browser so native scrollbars and form controls match.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  /* Surfaces: the navy family of the sibling security app. */
  --bg:          #0B1420;  /* page background */
  --panel:       #132234;  /* cards; the dashboard's inputs */
  --panel2:      #1B2E45;  /* raised: stat tiles, autocomplete, hovered rows, auth inputs */
  --line:        #24405F;  /* dividers, card borders, chart grid (decorative) */
  --line-strong: #56769A;  /* borders that identify a control: inputs, ghost buttons */

  /* Text */
  --txt:   #E6EBF0;
  --muted: #8FA3B8;

  /* Brand + interaction: the logo's teal. Accent means "you can act on this". */
  --accent:    #2FA5AF;
  --on-accent: var(--bg);  /* text on an accent fill; white on this teal is 2.9:1 */
  --accent-bg: color-mix(in srgb, var(--accent) 10%, transparent);  /* selection, current row */
  --focus:     var(--accent);

  /* Semantic finance colours. Meaning only, never decoration. */
  --pos:  #34D27B;  /* up, gain, bullish, success */
  --neg:  #FF7B7B;  /* down, loss, bearish, error */
  --neu:  #E5B53B;  /* flat, mixed, hold, demo */
  --warn: #FB8A3C;  /* caution that is not a loss */
  --info: #78AEFF;  /* informational state; NOT clickable (that is --accent) */

  /* Tints for chips, pills, alerts and banners: the colour at 12% over the surface.
     Derived, so a change to a base colour carries through. */
  --pos-bg:  color-mix(in srgb, var(--pos) 12%, transparent);
  --neg-bg:  color-mix(in srgb, var(--neg) 12%, transparent);
  --neu-bg:  color-mix(in srgb, var(--neu) 12%, transparent);
  --warn-bg: color-mix(in srgb, var(--warn) 12%, transparent);
  --info-bg: color-mix(in srgb, var(--info) 12%, transparent);
  --pos-line: color-mix(in srgb, var(--pos) 40%, transparent);
  --neg-line: color-mix(in srgb, var(--neg) 40%, transparent);
  --neu-line: color-mix(in srgb, var(--neu) 40%, transparent);

  /* Destructive fill (Delete my account). --neg is a text colour and too light to
     carry white; this is the sibling app's alert red. */
  --danger:    #D8323F;
  --on-danger: #FFFFFF;
  /* Hover DARKENS it: the brightness lift other buttons use took white-on-red to 4.14:1. */
  --danger-hover: color-mix(in srgb, var(--danger) 85%, black);

  /* Chart series: categorical, not semantic. --pos/--neg are never a series colour
     (a red line reads as "bad"); they appear in charts only as above/below-zero fills. */
  --viz-1: var(--txt);     /* the price itself */
  --viz-2: var(--accent);  /* first overlay (SMA20, GDELT tone) */
  --viz-3: #D9962F;        /* second overlay (SMA50): the sibling app's amber */
  --viz-4: #A78BFA;        /* third overlay (SMA200) */

  /* Doughnut slices (the Portfolio tab's allocation). Categorical, no green or red: those
     mean gain and loss. Validated as a RING with the data-viz palette validator on --panel
     (every neighbour, slot 8 back to slot 1 included: CVD dE >= 8.6, normal-vision dE >= 17.5,
     OKLCH L 0.58-0.67, each 3:1 or better). Named slices take 1-7 in order; --cat-8 is
     always Cash; Other and Unclassified are --muted. A ninth hue is never generated. */
  --cat-1: #3D7EDE;        /* blue */
  --cat-2: #B68F1B;        /* gold */
  --cat-3: #AC7FCC;        /* lilac */
  --cat-4: #C26300;        /* orange */
  --cat-5: #1D9999;        /* teal */
  --cat-6: #9065D0;        /* violet */
  --cat-7: #3EA1CC;        /* sky */
  --cat-8: #C34189;        /* magenta: Cash */
  /* The Big picture's size & style grid: one shade of the accent, at its strongest here;
     each cell paints it at an opacity that follows its share. --txt sits on it. */
  --grid-shade: color-mix(in srgb, var(--accent) 50%, transparent);

  /* Shape + depth. Surfaces separate by colour and a 1px line; only floating
     layers (the autocomplete) cast a shadow. */
  --r-sm: 6px;  --r-md: 8px;  --r-lg: 12px;  --r-pill: 999px;
  --shadow-lg: 0 10px 30px rgb(0 0 0 / .45);

  --font-ui: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI Variable Text",
             "Segoe UI", Roboto, Helvetica, Arial, system-ui, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  color-scheme: dark;
}

/* ── Base ─────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--txt);
  font: 15px/1.5 var(--font-ui);
  /* Every number in the app lines up in columns, prose included: cheaper than
     remembering a class on each of the hundreds of places a number is printed. */
  font-variant-numeric: tabular-nums;
}
/* Keyboard focus is always visible and always the same ring. Mouse clicks do not
   show it (:focus-visible), so there is no reason ever to remove it. */
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* ── The logo mark ─────────────────────────────────────────────────────── */
/* The PNG's own transparent margin IS the clear space: never crop it, never
   overlap it. Fixed square box, no stretching. */
.brand-mark { display: block; flex: none; aspect-ratio: 1; object-fit: contain; }

/* ── Buttons ───────────────────────────────────────────────────────────── */
/* Primary: one per form. A 1px transparent border keeps it the same height as a
   ghost button beside it. */
.btn {
  display: inline-block; padding: 12px 20px; border: 1px solid transparent;
  border-radius: var(--r-md); background: var(--accent); color: var(--on-accent);
  font: 600 15px/1.2 var(--font-ui); text-align: center; text-decoration: none;
  cursor: pointer;
}
.btn:hover { filter: brightness(1.08); }
.btn:disabled { opacity: .5; cursor: default; filter: none; }
.btn.ghost  { background: transparent; border-color: var(--line-strong); color: var(--txt); }
.btn.danger { background: var(--danger); color: var(--on-danger); }
.btn.danger:hover { filter: none; background: var(--danger-hover); }

/* Mini: row-level actions (sign out a device, revoke, remove from watchlist). */
.mini {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 32px; min-width: 32px; padding: 6px 11px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--panel2); color: var(--txt);
  font: 600 12px/1.2 var(--font-ui); white-space: nowrap; cursor: pointer;
}
.mini:hover { filter: brightness(1.15); }
.mini.go   { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.mini.warn { background: transparent; border-color: var(--neg-line); color: var(--neg); }
/* Disabled, as .btn: half strength, the default cursor, no hover lift. A page's own rule for a
   particular bar (.wl-bar .mini:disabled) still wins where it is more specific. */
.mini:disabled { opacity: .5; cursor: default; filter: none; }
/* Touch screens get 40px targets; a mouse keeps the denser 32px. */
@media (pointer: coarse) { .mini { min-height: 40px; min-width: 40px; } }

/* ── Motion ────────────────────────────────────────────────────────────── */
/* Nothing in the app animates for decoration; this keeps it that way for anyone
   who asked their OS for less motion. app.js applies the same preference to
   scrollIntoView and to Chart.js. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}
