/* ============================================================================
   TOM SHAW — Portal Design Tokens
   Source of truth: TOMSHAW-Brand-Guidelines-v1.1
   Do not hardcode hex values in portal code. Reference these tokens only.
   ========================================================================= */

:root {
  /* --- Core brand ------------------------------------------------------ */
  --ts-black:      #000000;
  --ts-ink:        #111111;
  --ts-white:      #FFFFFF;
  --ts-violet:     #9137FF;   /* accent — links, focus, active. Energy, not fill */
  --ts-purple:     #4F1398;   /* deep violet — primary action fill, AAA on white */
  --ts-cyan:       #00F1FF;   /* accent / info — dark surfaces only */
  --ts-ice:        #68F5FD;
  --ts-indigo:     #2221B0;
  --ts-navy:       #040461;

  /* --- Violet ramp ----------------------------------------------------- */
  --ts-violet-50:  #F5EEFF;
  --ts-violet-100: #E9DBFF;
  --ts-violet-200: #D3B7FF;
  --ts-violet-300: #B98AFF;   /* smallest safe violet text on black (8.0:1) */
  --ts-violet-400: #A35FFF;
  --ts-violet-500: #9137FF;
  --ts-violet-600: #7A22E3;
  --ts-violet-700: #6217BD;   /* primary button hover */
  --ts-violet-800: #4F1398;
  --ts-violet-900: #3A0E70;

  /* --- Neutrals / surfaces --------------------------------------------- */
  --ts-surface-1:  #111111;
  --ts-surface-2:  #131313;
  --ts-surface-3:  #202020;
  --ts-surface-4:  #353535;
  --ts-grey-light: #E5E5E5;   /* hairlines and SURFACE edges — cards, tables, dividers */
  --ts-grey-card:  #EEEEEE;
  --ts-grey-text:  #54595F;   /* secondary body text on light */
  --ts-grey-mid:   #7A7A7A;   /* placeholder / resting label */

  /**
   * Resting boundary of an INTERACTIVE control on white — 4.29:1.
   *
   * Added 15 Aug 2026, and it is an alias rather than a fifth grey (14 §2).
   * --ts-grey-light is #E5E5E5, which is 1.26:1 on white: WCAG 1.4.11 asks for
   * 3:1 on "visual information required to identify user interface components",
   * so every boxed input, filter control, pager button and SSO button in this
   * system had an edge you could not see. .ts-switch__track already used
   * --ts-grey-mid with the note "clears 1.4.11" — the rule was decided, it just
   * had not been applied to the other fourteen controls.
   *
   * SURFACES are not controls: cards, tables, dividers and section rules stay
   * on --ts-grey-light. The distinction is whether the edge tells you something
   * is operable.
   */
  --ts-border-control: var(--ts-grey-mid);   /* 4.29:1 on white */

  /* --- Status ----------------------------------------------------------- */
  --ts-success:    #1FB773;
  --ts-warning:    #E8A317;
  --ts-error:      #E0443C;
  --ts-info:       #00F1FF;
  --ts-error-ink:  #B32B24;   /* error TEXT on white — 6.4:1 AA (#E0443C is 4.2:1, fails) */

  /* --- Signature gradients ---------------------------------------------- */
  --ts-glow:        linear-gradient(135deg,#000000 0%,#200050 45%,#4F1398 78%,#9137FF 100%);
  --ts-glow-radial: radial-gradient(circle at 72% 28%,#9137FF 0%,#4F1398 28%,#200050 58%,#000000 95%);
  /* Portal panel glow — softer, corner-anchored, keeps >40% of canvas near-black */
  --ts-glow-panel:  radial-gradient(circle at 78% 22%,
                      rgba(145,55,255,.85) 0%,
                      rgba(79,19,152,.55) 26%,
                      rgba(32,0,80,.50) 55%,
                      rgba(0,0,0,0) 80%);
  /**
   * Band glow — the same bloom authored for a WIDE, SHORT canvas (.ts-hero).
   *
   * Added 15 Aug 2026. --ts-glow-panel is a circle sized for a panel: painted
   * across a 1065×360 band it only reaches transparency at 80% of a radius
   * measured from a tall box, so cropping it to a corner with a narrower
   * ::before left a visible vertical seam down the band — which is what
   * dashboard.html shipped. This one is an ellipse anchored beyond the
   * top-right corner and fully transparent by 70%, so it paints across the
   * whole surface with no edge to see and no peak under a figure.
   *
   * Decorative only: no contrast ratio applies because no text sits on it.
   * The figures sit in the near-black left and lower two thirds of the band,
   * which is what holds 01 §1's "at least 40% of the canvas staying near-black".
   */
  --ts-glow-band:   radial-gradient(115% 190% at 104% -14%,
                      rgba(145,55,255,.72) 0%,
                      rgba(79,19,152,.52) 24%,
                      rgba(32,0,80,.40) 46%,
                      rgba(0,0,0,0) 70%);

  /* --- Type ------------------------------------------------------------- */
  /* Neo Sans is licensed — self-host the webfont per portal deployment.
     Never load it from a third-party CDN. Helvetica/Arial is the approved
     system fallback; Exo 2 the approved open substitute where neither ships. */
  --ts-font: "Neo Sans","Neo Sans Std","Exo 2",Helvetica,"Helvetica Neue",Arial,sans-serif;
  --ts-mono: ui-monospace,"SF Mono","Cascadia Mono","Roboto Mono",Menlo,Consolas,monospace;

  /* Document scale — auth screens, content pages, anything read top-to-bottom.
     This is the brand type scale, unchanged. */
  --ts-fs-display: 44px;  --ts-lh-display: 1.15;
  --ts-fs-h1:      36px;  --ts-lh-h1:      1.2;
  --ts-fs-h2:      28px;  --ts-lh-h2:      1.25;
  --ts-fs-h3:      20px;  --ts-lh-h3:      1.35;
  --ts-fs-body:    18px;  --ts-lh-body:    1.6;
  --ts-fs-small:   14px;  --ts-lh-small:   1.5;
  --ts-fs-label:   12px;  /* floating field labels, meta */
  --ts-fs-btn:     16px;

  /* UI scale — app chrome, navigation, tables, dense data. A screen that is
     operated rather than read needs more rows in view than 18px allows. Use
     inside .ts-shell only; the document scale still governs content pages. */
  --ts-fs-ui:       14px;  --ts-lh-ui: 1.5;   /* nav items, table cells, form values */
  --ts-fs-ui-sm:    12px;                     /* meta, helper text, chips */
  --ts-fs-ui-label: 11px;                     /* uppercase section + column labels */
  --ts-fs-crumb:    15px;                     /* breadcrumb */
  --ts-fs-page:     20px;  --ts-lh-page: 1.3; /* in-app page title (h1) */
  --ts-fs-section:  16px;                     /* in-app section heading (h2) */
  --ts-tracking-label: .1em;

  --ts-fw-regular: 400;
  --ts-fw-bold:    700;   /* headings */
  --ts-fw-black:   800;   /* buttons, strong UI labels */

  /* --- Geometry --------------------------------------------------------- */
  --ts-space:        8px;   /* all spacing is a multiple of this */
  --ts-radius-card:  12px;
  --ts-radius-pill:  100px;
  --ts-radius-input: 0px;   /* fields are underlined, not boxed */
  --ts-radius-chip:  4px;
  --ts-radius-ui:    8px;   /* rail tiles, nav rows, UI controls */

  --ts-control-h:    54px;  /* button + tap-target height */
  --ts-field-h:      64px;  /* label + input block */

  /* --- App shell -------------------------------------------------------- */
  --ts-rail-w:       56px;  /* level 1 — product rail, always visible */
  --ts-nav-w:       240px;  /* level 2 — section nav, collapsible with [ */
  --ts-topbar-h:     60px;
  --ts-content-max: 1140px; /* content column cap; wider only for data tables */
  --ts-gutter:      calc(var(--ts-space) * 4);

  /* --- Focus (accessibility, non-negotiable) ---------------------------- */
  --ts-focus-light:  var(--ts-violet);   /* focus ring on white surfaces */
  --ts-focus-dark:   var(--ts-cyan);     /* focus ring on black surfaces */
  --ts-focus-width:  2px;
  --ts-focus-offset: 3px;

  /* --- Motion ----------------------------------------------------------- */
  --ts-ease:      cubic-bezier(.4,0,.2,1);
  --ts-dur-fast:  120ms;
  --ts-dur-base:  240ms;

  /* --- Elevation (light surfaces only; dark uses glow, not shadow) ------- */
  --ts-shadow-1: 0 1px 2px rgba(17,17,17,.06), 0 2px 8px rgba(17,17,17,.04);
  --ts-shadow-2: 0 2px 4px rgba(17,17,17,.08), 0 12px 32px rgba(17,17,17,.08);

  /* =========================================================================
     v1.2 — added per docs/00-build-contract.md §3
     ====================================================================== */

  /* --- Status inks and grounds ------------------------------------------
     These were hardcoded across four stylesheets. Text inks carry their
     contrast ratio; grounds and borders are decorative and never carry text. */
  --ts-success-ink:  #0F7F4E;   /* success TEXT on white — 5.3:1 AA */
  --ts-warning-ink:  #8A5B00;   /* warning TEXT on white — 5.9:1 AA */
  --ts-success-50:   #E9F8F1;
  --ts-success-200:  #9FDCC1;
  --ts-warning-50:   #FDF4E3;
  --ts-warning-200:  #F0D69A;
  --ts-error-50:     #FCEDEC;
  --ts-error-200:    #F3B7B3;
  /* No --ts-info-ink by design: info on a LIGHT surface is --ts-purple.
     --ts-cyan is 1.4:1 on white and is a dark-surface colour only. */

  /* --- On-dark neutrals --------------------------------------------------
     Rule 3 (tokens, never hex) applies to rgba() too. */
  --ts-on-dark-1:     rgba(255,255,255,.92);  /* primary text on black — 17.6:1 */
  --ts-on-dark-2:     rgba(255,255,255,.72);  /* secondary text on black — 10.6:1 */
  --ts-on-dark-3:     rgba(255,255,255,.50);  /* meta text on black — 5.3:1 AA, FLOOR  */
  /* .50 is the floor for TEXT and there is nothing below it. Anything dimmer
     fails AA: the nav section labels shipped at .42 (3.9:1) and .40 (3.7:1)
     until 14 Aug 2026. If a label looks too loud at .50, the answer is smaller
     or fewer labels, never a lower alpha. */
  --ts-on-dark-icon:  rgba(255,255,255,.62);  /* resting ICON on black — 7.8:1.
                                                 Icons answer to 1.4.11 (3:1), not
                                                 1.4.3, so they may sit below text. */
  --ts-hairline-dark:  rgba(255,255,255,.14); /* rules and borders on black */
  --ts-hairline-dark-2:rgba(255,255,255,.28); /* deliberate stronger divider */
  --ts-wash-dark:      rgba(255,255,255,.08); /* hover wash on black */
  --ts-wash-dark-2:    rgba(255,255,255,.16); /* active/selected wash, count badge */
  --ts-wash-violet:    rgba(145,55,255,.16);  /* active nav row on black */
  --ts-backdrop:       rgba(0,0,0,.55);       /* modal backdrop */
  --ts-shadow-dark:    0 12px 40px rgba(0,0,0,.4);  /* elevation ON black */

  /* --- Avatars — all multiples of 8; 32px is the existing topbar size ---- */
  --ts-avatar-xs:  24px;   /* table cell, list row */
  --ts-avatar-sm:  32px;   /* topbar, menu row */
  --ts-avatar-md:  40px;   /* card header, assignee picker */
  --ts-avatar-lg:  56px;   /* record header */
  --ts-avatar-xl:  96px;   /* profile page */

  /* --- Table density ----------------------------------------------------- */
  --ts-row-h-compact: 36px;
  --ts-row-h:         44px;   /* current default */
  --ts-row-h-relaxed: 56px;

  /* --- Document column ---------------------------------------------------
     An invoice or report is READ, so it uses the document scale and a
     narrower column than the 1140px operated-screen cap. */
  --ts-doc-max: 820px;

  /* --- Z-index scale -----------------------------------------------------
     Never write a bare z-index again. */
  --ts-z-sticky:   20;   /* topbar */
  --ts-z-nav:      25;   /* section nav as an overlay below 900px */
  --ts-z-rail:     30;   /* product rail */
  --ts-z-float:    40;   /* tooltips */
  --ts-z-popover:  50;   /* popovers, date pickers, tag suggestions */
  --ts-z-menu:     60;   /* dropdown menus */
  --ts-z-panel:    70;   /* assistant panel; its launcher sits one below */
  --ts-z-drawer:   90;   /* record drawer */
  --ts-z-modal:   100;   /* backdrop and modal */
  --ts-z-toast:   110;   /* toasts — above everything, never blocking */

  /* --- Chart frame -------------------------------------------------------
     Grid lines are decorative aids and are exempt from WCAG 1.4.11.
     Data marks are not: every mark clears 3:1 against its own ground. */
  --ts-chart-grid:      rgba(17,17,17,.07);
  --ts-chart-grid-dark: rgba(255,255,255,.10);
  --ts-chart-h-sm:  120px;
  --ts-chart-h:     240px;
  --ts-chart-h-lg:  360px;
  --ts-spark-h:      32px;
  --ts-track:       var(--ts-grey-card);
  --ts-track-dark:  rgba(255,255,255,.14);

  /* --- Categorical series — VALIDATED 2026-08-14 (contract §4) ------------
     Passed the dataviz validator on all five checks, across ALL pairs (a
     harder test than adjacent-only): OKLab dE x100 with Machado-Oliveira-
     Fernandes CVD simulation at severity 1.0.
       light — worst CVD dE 12.2, worst normal-vision dE 20.5
       dark  — worst CVD dE  9.7, worst normal-vision dE 16.7
     The earlier candidate set FAILED both modes; see docs/11-dataviz.md §1
     for the verbatim output and what it failed on.

     Cool axis only. Green, amber and red are reserved for meaning: a green
     series would read as "good" and a red one as "bad".

     Two sets because the usable LIGHTNESS BAND differs per ground, not
     because a colour cannot clear 3:1 on both — mid-lightness colours do.
     Picking the dark set for maximum contrast is what broke the candidate:
     four near-white pastels clear 3:1 easily and then cannot be told apart.

     Same hue sits in the same slot across both grounds. All pairs clear, so
     slot order is free — assign series by meaning, not by index.
     Four is the cap. A fifth series is a pattern in the same ink. */
  --ts-series-1: #9137FF;   /* violet (= --ts-violet) — 5.01:1 on white */
  --ts-series-2: #038F97;   /* teal                   — 3.90:1 on white */
  --ts-series-3: #064DB1;   /* blue                   — 7.77:1 on white */
  --ts-series-4: #8C0871;   /* plum                   — 8.79:1 on white */

  --ts-series-1-dark: #A35FFF;   /* violet (= --ts-violet-400) — 5.64:1 on black */
  --ts-series-2-dark: #09A8AE;   /* teal                       — 7.22:1 on black */
  --ts-series-3-dark: #0371B6;   /* blue                       — 4.04:1 on black */
  --ts-series-4-dark: #C60F95;   /* magenta                    — 3.90:1 on black */

  /* "Other" / unclassified is NOT a series slot. A neutral fails the chroma
     floor by definition — it reads as grey and does no identity work. It is
     --ts-grey-text on light, --ts-on-dark-3 on dark, always open-textured. */
}

/* ============================================================================
   v1.3 — SEMANTIC APP-SHELL TOKENS (themeable chrome)
   Added 15 Aug 2026. The shell chrome (product rail + section nav) flips with
   [data-theme] on <html>. DEFAULT IS LIGHT: a bare :root with no attribute
   resolves to the light set, so the shell is never left unthemed, and a page
   with JS disabled still renders the light default.

   Every value below is an EXISTING token — no new colours are introduced, only
   semantic names that swap per surface. Contrast ratios are for the pairing the
   token actually carries; all clear WCAG AA (text) / 1.4.11 (icons, controls).

   NOT routed through these on purpose: the topbar, the content canvas and the
   floating tooltip bubble are light in both themes (the dark theme preserves
   today's look exactly — a white topbar over a black rail), so they keep their
   existing light / on-ink tokens.
   ========================================================================= */
:root,
:root[data-theme="light"] {
  --ts-shell-bg:          var(--ts-grey-card);    /* rail — near-white, one step under content   */
  --ts-shell-bg-2:        var(--ts-white);        /* section nav — white, hairline-delineated     */
  --ts-shell-fg:          var(--ts-ink);          /* logo, nav title, hover/active-to-full        */
  --ts-shell-fg-muted:    var(--ts-grey-text);    /* resting nav rows — 7.1:1 on white            */
  --ts-shell-fg-dim:      var(--ts-grey-text);    /* group labels, foot — 7.1:1 on white          */
  --ts-shell-icon:        var(--ts-grey-text);    /* rail icons — 6.1:1 on grey-card              */
  --ts-shell-hairline:    var(--ts-grey-light);   /* rail/nav rules                               */
  --ts-shell-wash:        var(--ts-violet-50);    /* hover wash (matches table row hover)         */
  --ts-shell-wash-active: var(--ts-violet-100);   /* active nav row ground                        */
  --ts-shell-active-fg:   var(--ts-violet-700);   /* active nav text — 6.8:1 on the active wash   */
  --ts-shell-logo-accent: var(--ts-violet-700);   /* logo accent — 7.6:1 on grey-card             */
  --ts-shell-elevation:   var(--ts-shadow-2);     /* nav overlay shadow (mobile) — light elevation*/
  --ts-shell-focus:       var(--ts-focus-light);  /* violet focus ring on light chrome            */
  --ts-shell-count-bg:    var(--ts-grey-card);    /* plain count badge ground                     */
  --ts-shell-count-fg:    var(--ts-grey-text);    /* plain count badge text — 6.1:1               */
}
/**
 * Dark chrome — opt-in via data-theme="dark". Preserves the original look
 * exactly: black rail, #111 nav, cyan focus, violet-300 accents.
 *
 * Note for anyone reading rule 1 against this: LIGHT IS THE DEFAULT, by
 * decision, and that means an in-shell screen no longer reaches "Black 45%".
 * The chrome is where most of the black allocation lived (rail 3.9% + nav
 * 15.6% of a 1440px viewport). Rule 1 has been rescoped in the README rather
 * than left to contradict the code — it now governs the DARK theme and the
 * signed-out screens, which are still black-led.
 */
:root[data-theme="dark"] {
  --ts-shell-bg:          var(--ts-black);        /* rail — pure black (today's look)             */
  --ts-shell-bg-2:        var(--ts-surface-1);    /* section nav — #111, one step off the rail    */
  --ts-shell-fg:          var(--ts-white);        /* logo, nav title, hover/active-to-full        */
  --ts-shell-fg-muted:    var(--ts-on-dark-2);    /* resting nav rows — .72, 10.6:1               */
  --ts-shell-fg-dim:      var(--ts-on-dark-3);    /* group labels, foot — .50, 5.3:1 AA floor     */
  --ts-shell-icon:        var(--ts-on-dark-icon); /* rail icons — .62, 7.8:1                       */
  --ts-shell-hairline:    var(--ts-hairline-dark);/* rules on black                               */
  --ts-shell-wash:        var(--ts-wash-dark);    /* hover wash on black                          */
  --ts-shell-wash-active: var(--ts-wash-violet);  /* active nav row ground                        */
  --ts-shell-active-fg:   var(--ts-violet-300);   /* active nav text — 8.0:1 on black             */
  --ts-shell-logo-accent: var(--ts-violet-300);   /* logo accent — 8.0:1 on black                 */
  --ts-shell-elevation:   var(--ts-shadow-dark);  /* nav overlay shadow (mobile) — on black       */
  --ts-shell-focus:       var(--ts-focus-dark);   /* cyan focus ring on dark chrome               */
  --ts-shell-count-bg:    var(--ts-wash-dark-2);  /* plain count badge ground                     */
  --ts-shell-count-fg:    var(--ts-on-dark-1);    /* plain count badge text — 17.6:1              */
}

@media (prefers-reduced-motion: reduce) {
  :root { --ts-dur-fast: 0ms; --ts-dur-base: 0ms; }
}
