/* ============================================================================
 * ARGUS DESIGN SYSTEM — TOKENS
 * Sprint: dashboard-tokens, 2026-08-03
 *
 * THE single source of colours, type sizes, spacing, radii and durations.
 * Loaded FIRST in the cascade, before reset.css.
 *
 * Derived from /root/argus-landing-hero.html :root, merged with the values the
 * dashboard genuinely needs (a marketing hero has no up/down pair, no 10-14px
 * type band, no status families).
 *
 * ── SCOPE OF THIS SPRINT ────────────────────────────────────────────────────
 * This file is the source of the SYSTEM. Retrofitting consumers is deliberately
 * deferred: base.css is rewritten to alias these tokens, but the literals in
 * components.css (73KB), app.css and login.css are NOT rewritten. Changing the
 * colour system and rewriting 227 font-sizes in the same sprint would make any
 * regression impossible to attribute.
 *
 * Existing variable names (--green-dark, --charcoal, ...) are NOT renamed.
 * base.css aliases them onto these tokens, so the rename can happen later
 * without a big-bang.
 *
 * ── DOCROOT: THIS FILE REACHES TWO SURFACES, NOT THREE ──────────────────────
 * Added 2026-08-28, sprint dashboard-typo. Read this before editing anything
 * here, and before writing any sentence in this file about "the landing".
 *
 * REACHES:        dashboard.argus.cfd/app  (app.html)
 *                 dashboard.argus.cfd/     (index.html, the login page)
 *                 — they share tokens.css, reset.css, base.css, components.css
 *                   and differ only in app.css vs login.css.
 * DOES NOT REACH: argus.cfd, ANY of its 11 pages.
 *
 * argus.cfd is a different nginx root (/var/www/html vs /var/www/dashboard).
 * There is a SECOND FILE also called tokens.css over there, plus a THIRD token
 * block inline in that site's index.html under a `--h-*` prefix. Three
 * definitions of one design system; a root-relative /css/tokens.css resolves to
 * a different file depending on the host; no path written here can reach either
 * of the others.
 *
 * THE PRACTICAL RULES:
 *   1. A change here does NOT propagate to argus.cfd. If the change should
 *      apply there, it is a second, manual edit in /var/www/html/css/.
 *      Sprint landing-unify (2026-08-27) forgot exactly this and left the
 *      dashboard on a serif for a day.
 *   2. DO NOT WRITE CLAIMS HERE ABOUT WHAT THE LANDING LOADS. This file has
 *      carried three successive wrong versions of that one sentence, each true
 *      when written. Nothing makes such a claim falsifiable from inside this
 *      file, so it rots silently. Describe what THIS file does.
 *   3. Token NAMES differ across the three, for identical values:
 *          here            landing site.css     landing index.html
 *          --t-display     --fs-display         --h-fs-* (own scale)
 *          --r-md          --radius-control     --h-radius-*
 *          --c-accent      --green-dark         --h-color-accent
 *      A name borrowed from the wrong surface renders off its fallback, or off
 *      inheritance, and looks correct. Grep the name before using it.
 *
 * Filed as a HIGH backlog item with both candidate fix shapes (one served token
 * file, or a build step) — see argus-brain/backlog.md. Not fixed in the sprint
 * that wrote this note, on purpose: it is a serving change, and folding it into
 * a typography pass would make any regression unattributable.
 * ========================================================================= */

:root {

  /* ── SURFACES ───────────────────────────────────────────────────────────
   * From the landing. Note the panel LIFT improves: #FAFAF9 on #EEEFEA is
   * 1.11 contrast, against 1.05 for the old #FAFAF8 on #F5F4F2. Panels read
   * as more distinct than before with no border change.
   */
  --c-page:       #EEEFEA;
  --c-panel:      #FAFAF9;
  --c-page-rgb:   238 239 234;
  --c-panel-rgb:  250 250 249;

  /* Border. Landing offers #dcdfe4 (cool); we keep the dashboard's warm
   * #E2E0DC — see the NEUTRAL TEMPERATURE note at the foot of this file.
   * Visibility is low either way (1.14 on page, 1.26 on panel); it was 1.20
   * on the old page, so borders get marginally fainter. Tracked as debt. */
  --c-border:     #E2E0DC;

  /* ── INK ────────────────────────────────────────────────────────────────
   * Warm family retained. -rgb triplets exist only where alpha variants are
   * actually needed (per the components.css:2798 problem: the author knew
   * --warm-white == rgb(250,250,248) but had no mechanism to say so).
   */
  --c-ink:        #1A1A18;
  --c-ink-rgb:    26 26 24;
  --c-ink-2:      #4A4A46;

  /* MUTED — CHANGED THIS SPRINT, deliberately.
   * Was #8A8A84: 3.32 contrast on the old panel, degrading to 3.00 on the new
   * lighter page. That FAILS WCAG AA (4.5) at 108 consumers, most of them
   * 10px letterspaced uppercase mono — the worst case for legibility.
   * Leaving it would have shipped a measurable regression, not "no change".
   * #6B6B66 clears AA on both surfaces (5.13 panel / 4.64 page) and stays in
   * the warm family (b* +2.8). */
  --c-ink-muted:  #6B6B66;

  /* ── ACCENT ─────────────────────────────────────────────────────────────
   * Landing --color-accent is IDENTICAL to the dashboard's --green-dark, so
   * the 109 consumers do not shift. The tints below are dashboard-only.
   */
  --c-accent:            #2D5A3D;
  --c-accent-rgb:        45 90 61;
  --c-accent-mid:        #3D7A53;
  --c-accent-light:      #6BA583;
  --c-accent-light-rgb:  107 165 131;
  --c-accent-pale:       #C8DDD0;
  --c-accent-pale-rgb:   200 221 208;

  /* ── UP / DOWN — SEMANTIC ───────────────────────────────────────────────
   * These are SEMANTIC tokens, deliberately distinct from the palette entries
   * --c-accent and --c-danger-ink. That distinction is the point: before this
   * sprint the same role resolved four different ways —
   *   .stat-delta.negative      -> #C44        (hardcoded)
   *   .data-table td.negative   -> #C44        (hardcoded)
   *   .chart-card-chg.negative  -> #C44        (hardcoded)
   *   .detail-meta-list dd.negative -> --red-dark #6E2F2F
   *   .am-flow-term-val.positive    -> --green-mid #3D7A53
   * A data table's .negative and a detail list's .negative were different reds.
   *
   * --c-up keeps #2D5A3D, so every positive number is visually UNCHANGED.
   *
   * --c-down is #A82F2F, the one deliberate colour change in this sprint:
   *   #CC4444 (the old #C44) fails AA on BOTH old and new surfaces (4.49/4.06)
   *           — a pre-existing failure, not one the new palette introduced.
   *   #C03A3A clears AA by only 0.15 on the page — no headroom at 13px.
   *   #6E2F2F (--red-dark) is maroon; it reads as body text, not as alert.
   *   #A82F2F gives 6.46 panel / 5.84 page, landing ~0.9 below --c-up. That
   *           gap is intentional: red at equal WCAG luminance appears
   *           perceptually heavier than green, so a slightly lighter red
   *           gives visual parity down a table column.
   */
  --c-up:        #2D5A3D;
  --c-up-rgb:    45 90 61;
  --c-down:      #A82F2F;
  --c-down-rgb:  168 47 47;

  /* ── STATUS ─────────────────────────────────────────────────────────────
   * The danger-* family is the verdict/banner role, semantically separate
   * from --c-down: a number going down is not an error.
   * warn-* and hy-bg each retire a hardcoded literal; none is invented.
   */
  --c-danger-ink:     #6E2F2F;
  --c-danger-bg:      #F8EFEF;
  --c-danger-border:  #B86A6A;
  --c-warn-bg:        #F5E8C8;   /* components.css:1435 .badge-watchlist   */
  --c-warn-ink:       #8A6A1A;   /* components.css:1435 .badge-watchlist   */
  --c-hy-bg:          #E7C9A0;   /* components.css:2335 credit HY zone     */

  /* ── ON-ACCENT & SCRIMS ─────────────────────────────────────────────── */
  --c-on-accent:  #FFFFFF;                    /* retires 5x #fff / #ffffff */
  --c-scrim:      rgb(0 0 0 / 0.40);          /* app.css:657 modal scrim   */
  --c-shadow-sm:  0 2px 12px rgb(0 0 0 / 0.04);

  /* ── TYPE — FAMILIES ────────────────────────────────────────────────────
   * Sprint dashboard-typo, 2026-08-28. Inter + JetBrains Mono, self-hosted
   * from /css/fonts.css. No serif, no italic, on either surface this docroot
   * serves. Google Fonts is gone from app.html and index.html.
   *
   * ── THE COMMENT THIS REPLACES WAS WRONG, AND SO WAS THE ONE BEFORE IT ───
   * It read "ALREADY UNIFIED WITH THE LANDING ... Playfair Display + DM Sans +
   * DM Mono, identical to app.html:10", and it was itself the 2026-08-03
   * correction of an EARLIER claim that said the opposite ("the landing is
   * Inter + JetBrains Mono with NO serif"). Both were true when written and
   * both went stale, because nothing on this box makes a statement about the
   * landing's fonts falsifiable from inside this file.
   *
   * That is the third wrong version of one sentence. The cause is structural,
   * not carelessness: see the DOCROOT note at the head of this file. Do not
   * write another claim here about what the landing loads. State what THIS
   * file does; let the landing's own tokens.css state what it does.
   *
   * ── WHAT REPLACED PLAYFAIR, SLOT BY SLOT ────────────────────────────────
   * --font-serif is DELETED, not redefined, and --serif is deleted with it in
   * base.css. This is the landing's reasoning at its own tokens.css:122 and it
   * applies here with one difference that mattered: left defined-and-unused a
   * serif token is a loaded gun, because a future `font-family: var(--serif)`
   * resolves to the Georgia fallback — a serif nobody chose — and reads as a
   * decision rather than a mistake. Undefined, the same rule falls back to the
   * inherited sans and is a visible no-op in review.
   *
   * On the LANDING that gun was unloaded (samples.html referenced var(--serif)
   * zero times). HERE IT WAS LOADED AND POINTED: components.css:2019 was
   * `font-family: var(--serif, Georgia, serif)` on .flow-report-body — the Flow
   * analyst's running prose, the one serif consumer on this box that set body
   * copy rather than a heading, and the only one carrying its own hardcoded
   * fallback. Deleting the token alone would have moved that block to Georgia
   * silently. It is rewritten to var(--sans) in the same commit.
   *
   * The 16 former --serif consumers (this file's old comment said 19; it was
   * 16) are now var(--sans) at weight 600, except two that changed CATEGORY
   * rather than family:
   *   .topbar-brand-name  the wordmark  -> Inter 600 13px / 0.28em uppercase
   *   .nav-num            I. II. III.   -> mono, the landing's eyebrow idiom
   * Both are recorded at their own sites in app.css.
   */
  --font-sans:  'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono:  'JetBrains Mono', 'SFMono-Regular', Consolas, monospace;

  /* ── TYPE — SCALE ───────────────────────────────────────────────────────
   * Frozen on what the dashboard MEASURABLY uses (235 declarations counted
   * 2026-08-03), not on the landing's 4-step marketing scale. 76% of all type
   * sits in the 10-14px band, which a hero has no reason to define.
   *
   * Orphans folded to nearest neighbour: 13.5px -> --t-table,
   * 10.5px (x2) -> --t-meta, 16px -> --t-body.
   *
   * ASPIRATIONAL beyond base.css: only the 8 declarations in base.css are
   * retrofitted this sprint. The other 227 remain literals. See SCOPE above.
   */
  --t-micro:         9px;   /*  10 uses */
  --t-meta:         10px;   /*  62 uses — mono uppercase label, most common  */
  --t-caption:      11px;   /*  34 uses */
  --t-small:        12px;   /*  36 uses */
  --t-table:        13px;   /*  31 uses */
  --t-table-lg:     14px;   /*  17 uses */
  --t-body:         15px;   /*   9 uses — body default                      */
  --t-subhead:      17px;   /*   4 uses — h3                                */
  --t-title:        18px;   /*   8 uses */
  --t-ticker:       20px;   /*   2 uses */
  --t-section:      22px;   /*   6 uses — h2 / .panel h2 / .stat-value      */
  --t-lead:         26px;   /*   3 uses */
  --t-metric:       32px;   /*   2 uses — .composite-value                  */
  /* ── --t-display 36 -> 28 — sprint dashboard-typo, 2026-08-28 ───────────
   * The 8 view titles ("Dashboard", "Argus AM", "Equity Scanner", ...) and the
   * global h1, which on this surface are the same elements.
   *
   * Operator decision, and the argument is DENSITY, not the ramp: 40px over a
   * landing hero has room; 40px over a data table does not. The landing's own
   * number was never a candidate here.
   *
   *     was   Playfair 700 36px   ratio 2.40x against the 15px body
   *     now   Inter    600 28px   ratio 1.87x
   *
   * NOTE THE DENOMINATOR. The brief cited 1.75x, which is 28/16. Body on this
   * surface is --t-body = 15px, not 16 — `html { font-size: 16px }`
   * (base.css:57) is the rem root, not the body size, and .view-sub, the
   * heading's actual neighbour, is --t-body too. So the delivered ratio is
   * 1.87x. It clears the 1.5x level-change threshold by more than the target
   * did, so the decision stands unchanged; only the number is corrected. This
   * is the same denominator trap the landing hit from the other side, where
   * the real neighbour was a 17px lede and not the 16px body.
   *
   * CONSEQUENCE, deliberate: 28px is exactly --t-display-sm, so the mobile
   * step-down at app.css:216 is now a no-op. It is REMOVED there rather than
   * left as a rule that looks live and does nothing. --t-display-sm itself is
   * kept and documented below — it is the pair partner of a token that may
   * move again, and deleting it would make the next retune re-derive it. */
  --t-display:      28px;   /*   2 uses — h1 / .view-header h1   was 36px   */
  --t-display-xl:   40px;   /*   2 uses */
  --t-hero:         48px;   /*   1 use  — .login-aside-title                */
  /* ── @media STEP-DOWNS ──────────────────────────────────────────────────
   * Added 2026-08-03, sprint dashboard-type stage 5. A mobile step-down is a
   * PAIR, not an independent size: .perf-body .composite-value at 26px is "the
   * small --t-metric", and it happens to equal --t-lead. Writing var(--t-lead)
   * there would hard-code that coincidence, and the next person who retunes
   * --t-lead would silently move a portfolio metric on mobile.
   *
   * A companion exists only where the base token carries a ROLE (metric,
   * ticker, hero, section, lead, display). Where an element simply moves down
   * into the 9-15px band on mobile, it uses the plain band token — no
   * companion, because there is no role to keep in sync.
   */
  /* --t-display-sm now EQUALS --t-display (both 28px), so it has no consumer:
   * app.css:216 was its only one and that rule is removed. Kept, not deleted,
   * because it is the pair partner described above — if --t-display is ever
   * raised again this is the value the mobile step returns to, and the pairing
   * rule is what stops someone writing var(--t-lead) there by coincidence. */
  --t-display-sm:      28px;   /* step-down of --t-display    28 -> 28, unused */
  --t-display-xl-sm:   30px;   /* step-down of --t-display-xl 40 -> 30 */
  --t-hero-sm:         32px;   /* step-down of --t-hero       48 -> 32 */
  --t-metric-sm:       26px;   /* step-down of --t-metric     32 -> 26 */
  --t-lead-sm:         22px;   /* step-down of --t-lead       26 -> 22 */
  --t-section-sm:      18px;   /* step-down of --t-section    22 -> 18 */
  --t-ticker-sm:       17px;   /* step-down of --t-ticker     20 -> 17 */

  /* ── SPACING ────────────────────────────────────────────────────────────
   * DERIVED FROM A CENSUS, 2026-08-03, sprint dashboard-type stage 6.
   * Replaces the previous 4px scale, which was ASSERTED (carried over from the
   * landing's --grid-unit: 8px) and fitted only 56% of the 478 spacing values
   * on the box. This one is measured, the way the type scale above was.
   *
   * ── The two populations ───────────────────────────────────────────────
   * Splitting spacing by role is what makes the coverage figure honest:
   *
   *   LAYOUT (gap, margin, container padding)      428 values — 97% on 2px
   *   INLINE CONTROL padding (badge/pill/btn/…)     50 values — 34% ODD
   *
   * Inline control padding is NOT in this scale, on purpose. Vertical padding
   * on a badge is set against its LINE-HEIGHT, not against a layout grid —
   * that is why `.credit-verdict` is `3px 9px` and `.flow-anchor-badge` is
   * `1px 5px`. Forcing them onto 2px steps would be a visual redesign of every
   * badge, and folding them into the coverage number would let this scale claim
   * a reach it does not have. Same category as `html { font-size: 16px }`:
   * real, deliberate, and not a scale member.
   *
   * ── The shape, and why it changes at 24 ───────────────────────────────
   * Grid fit of LAYOUT spacing, by band:
   *
   *      1- 8px   n=159   on 4px  53%   on 2px  92%
   *      9-16px   n=171   on 4px  58%   on 2px  99%
   *     17-24px   n= 74   on 4px  69%   on 2px 100%
   *     25px+     n= 24   on 4px 100%   on 2px 100%
   *
   * Below 24 the dashboard is on a 2px grid; at 25+ it is ALREADY perfectly on
   * 4px, 24 of 24 values. The boundary is exact, not a preference.
   *
   * ── Naming: BY PX VALUE ───────────────────────────────────────────────
   * --space-12 is 12px. A mixed 2px/4px scale cannot be indexed sanely (would
   * --space-3 be 6px or 12px?), and --space-1-5 for 6px is a name that produces
   * mistakes for years. Naming by value is self-verifying and makes the
   * substitution proof trivial.
   *
   * THIS REUSES OLD NAMES WITH NEW VALUES (--space-4 was 16px, is now 4px).
   * Safe only because the box had exactly ONE consumer, components.css:5
   * `gap: var(--space-2)` (8px), rewritten to var(--space-8) in this same
   * commit. Verified: no JS reads --space-*, and the landing's --space usages
   * are its own inline :root, which never loads this file.
   *
   * Counts below are LAYOUT uses measured at derivation time.
   */
  --space-2:   2px;   /*  15 */
  --space-4:   4px;   /*  37 */
  --space-6:   6px;   /*  47 */
  --space-8:   8px;   /*  48 */
  --space-10: 10px;   /*  36 */
  --space-12: 12px;   /*  54 — most used */
  --space-14: 14px;   /*  34 */
  --space-16: 16px;   /*  46 */
  --space-18: 18px;   /*  17 */
  --space-20: 20px;   /*  28 */
  --space-22: 22px;   /*   6 — credit/equity panel padding, a real role */
  --space-24: 24px;   /*  23 — last 2px step */
  --space-28: 28px;   /*   4 */
  --space-32: 32px;   /*  10 */
  --space-40: 40px;   /*   4 */
  --space-48: 48px;   /*   2 */
  --space-56: 56px;   /*   3 */

  /* NOT tokens, deliberately — 13 odd-valued LAYOUT declarations (3px x5,
   * 1px x3, 5px x3, 7px x1, 9px x1) stay literal as optical adjustments, and
   * 36px x1 is folded in stage 6b. Every site is listed in that commit so a
   * future reader sees they were considered and kept, not missed. */

  /* ── RADII ──────────────────────────────────────────────────────────────
   * Dashboard values retained. Landing --radius-card is 12px; dashboard cards
   * are 6px and 10px, and adopting 12px would restyle every panel. Deferred.
   */
  --r-xs:    2px;
  --r-sm:    3px;
  --r-md:    4px;   /* == landing --radius-control */
  --r-lg:    6px;
  --r-xl:   10px;
  --r-pill:  50%;

  /* ── MOTION ─────────────────────────────────────────────────────────────
   * Drift found: 120ms (20 sites) and 0.12s (3 sites) are the SAME duration
   * spelled two ways; likewise 0.15s/150ms and 0.8s/800ms.
   *
   * --dur-fast is 120ms (23 dashboard consumers) over the landing's 0.15s
   * (2 sites); a 30ms delta is imperceptible and consumer count decides.
   *
   * --ease-standard adopts the LANDING's curve. The dashboard's
   * cubic-bezier(0.2,0.6,0.3,1) survives as a literal at components.css:1235
   * and :1241 only; both are entrance animations, migration deferred.
   */
  --dur-instant:  100ms;
  --dur-fast:     120ms;
  --dur-mid:      160ms;
  --dur-slow:     240ms;
  --dur-slower:   800ms;
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-default:  ease;                      /* 24 sites, unchanged */
}

/* ============================================================================
 * NOTES ON WHAT IS DELIBERATELY *NOT* HERE
 *
 * TELEGRAM BRAND BLUE (#2aabee / #1f9ad6, login.css:114-124) is NOT a token.
 *   It is a third-party brand constant. Tokenising it would invite a future
 *   "harmonise the palette" pass, and harmonising someone else's brand blue
 *   would be wrong. It stays a literal, on purpose.
 *
 * LANDING GRAPHIC COLOURS (--color-universe #16181d, --color-universe-active
 *   #2a2e37, --color-flow-line #a8adb5, --dur-flow 2.4s, --dur-connector 1.6s)
 *   are not text neutrals; they serve the landing's animated network visual.
 *   They stay in the landing and never enter the dashboard.
 *
 * LANDING TOKENS WITH ZERO DASHBOARD CONSUMERS are omitted rather than
 *   imported speculatively: --color-accent-hover #234a30 (the dashboard
 *   expresses hover as --green-mid, i.e. it LIGHTENS where the landing
 *   darkens), --color-accent-tint #F5F8F6, --color-surface #ffffff as a
 *   surface, --space-section 80px, --fw-*, --lh-*, --ls-*.
 *
 * ── NEUTRAL TEMPERATURE — the conflict, and why warm won ───────────────────
 * The landing and dashboard shipped different blacks and greys:
 *     ink    landing #16181d (b* -3.8, cool)  vs  dashboard #1A1A18 (b* +1.4)
 *     ink-2  landing #545964 (b* -7.0, cool)  vs  dashboard #4A4A46 (b* +2.4)
 *     line   landing #dcdfe4 (b* -2.8, cool)  vs  dashboard #E2E0DC (b* +2.2)
 *
 * The dashboard's WARM family was chosen because:
 *   1. The new page #EEEFEA is b* +2.3 — WARMER than the old page #F5F4F2
 *      (+1.1). The landing made the page warmer, not cooler.
 *   2. The shared accent #2D5A3D is b* +12.1, strongly warm, and is confirmed
 *      identical across both systems.
 *   3. Cool ink would put every glyph in temperature opposition to both the
 *      surface beneath it and the accent beside it — tolerable on a hero at
 *      49.6px, not in 10-13px dense tables.
 *   4. Contrast gives no tiebreak: 15.08 vs 15.37 on page, both AA.
 *   5. Warm costs zero visual change across 190 existing consumers.
 *
 * Caveat recorded: landing --color-sub is L* 37.8 against the dashboard
 * slate's L* 31.3 — LIGHTER, not merely cooler. The darker dashboard value
 * was kept (30 consumers, and 7.70 vs 6.08 contrast).
 *
 * CONSEQUENCE — REWRITTEN 2026-08-03, sprint dashboard-type. The comparison
 * above is against a landing that does not exist (decisions.md ERRATUM). The
 * SERVED landing at /var/www/html/index.html:22-30 is neither the cool family
 * nor this warm one:
 *     page #FCFBF7 · panel #FFFFFF · ink #2A2A24 · muted #9C9788 · line #E7E3D9
 * Against those, this file did not reduce colour drift — it increased it. The
 * WCAG decisions here still stand (they were measured on the dashboard's own
 * surfaces and are independent of the landing), but the reconciliation claim
 * does not. The landing-tokens sprint must be scoped against /var/www/html AS
 * SERVED, never against a transcribed value list. Top open item in backlog.md.
 * ========================================================================= */
