/* SellerTally design tokens — v1.0
   Adopted verbatim from docs/for-claude-code/design/tokens.css (Claude Design output + two Cowork
   edits: the three *-on-chrome gap tokens, and the prefers-color-scheme resolution below) per
   0-DESIGN (2026-08-04) -- BLAZOR-REBUILD-SPEC.md's "DESIGN SYSTEM -- BINDING" section. That file is
   the source of truth; this is the deployed copy. Do not edit the two out of sync -- if a value
   needs to change, change it there first.

   Derived from the production CSS; semantic names only.
   Components may reference ONLY these tokens, never a literal colour.
   Elevation order: surface-app < surface < surface-alt < surface-overlay.
   Chrome (top bar + left nav) is dark in BOTH themes -- that is the product's
   signature, not a dark-mode artefact, so it has its own surface + ink tokens. */

:root {
  color-scheme: light;   /* native controls/scrollbars follow the resolved theme, not the OS */

  /* surfaces */
  --st-surface-app:        #eef1f4;
  --st-surface:            #ffffff;
  --st-surface-alt:        #f5f7f9;
  --st-surface-overlay:    #ffffff;
  /* SPRINT-QA 2026-08-14 #10 -- Mazhar: "Light mode: menu + top bar stay dark." The chrome was
     deliberately dark in BOTH themes (production values carried over verbatim from NavMenu.css /
     TopBar.css), which is why the theme toggle read as half-broken: everything changed except the
     two surfaces he looks at most. In light mode the chrome now follows the theme.

     Values are taken from the existing light palette rather than invented -- chrome = --st-surface-alt
     (#f5f7f9), ink = the normal light text ramp, hover/active = the same alphas the rest of light mode
     uses, border = --st-border. So this introduces no new colour into the product.

     HONEST CONSEQUENCE, stated rather than buried: the old alphas were contrast-measured against a
     DARK chrome (COMPONENT-SPECS.md §10 -- the 3px active-nav indicator's 3.03:1 is measured against
     --st-surface-active-on-chrome). Those measurements described the dark chrome and still hold in
     dark mode, where these tokens are unchanged; the light-mode figures have NOT been re-measured,
     because measuring them is a contrast-report pass, not a QA fix. Reverting is this one block.

     The dark theme's own block further down does not override these, so dark mode is untouched. */
  --st-surface-chrome:     #f5f7f9;
  --st-surface-hover-on-chrome:  rgba(15, 26, 38, 0.05);
  --st-surface-active-on-chrome: rgba(15, 26, 38, 0.09);
  --st-border-on-chrome:         #dde2e7;
  --st-surface-hover:      rgba(15, 26, 38, 0.05);
  --st-surface-active:     rgba(15, 26, 38, 0.09);
  --st-surface-selected:   rgba(31, 111, 212, 0.10);
  --st-scrim:              rgba(0, 0, 0, 0.50);

  /* borders */
  --st-border:             #dde2e7;
  --st-border-subtle:      #e9edf1;
  --st-border-strong:      #c2cad2;
  --st-border-input:       #7e8b97;   /* ≥3:1 -- form controls, see contrast report */

  /* text */
  --st-text-primary:       #1c2126;
  --st-text-secondary:     #4b5560;
  --st-text-muted:         #636c76;
  --st-text-on-fill:       #ffffff;
  /* SPRINT-QA 2026-08-14 #10: dark ink now that the light-mode chrome is a light surface. White
     text on #f5f7f9 would have made the whole menu invisible -- these two move together with
     --st-surface-chrome above, always. */
  --st-text-on-chrome:     #1c2126;
  --st-text-on-chrome-muted: rgba(28, 33, 38, 0.72);

  /* accent */
  --st-accent:             #1f6fd4;
  --st-accent-fill:        #1f6fd4;
  --st-accent-fill-hover:  #195cb0;
  --st-accent-fill-active: #16509b;
  --st-accent-subtle:      #e8f1fd;
  --st-accent-on-subtle:   #1a5cb0;
  /* DASHBOARD-SPEC.md §6.2: the active dashboard tab's underline. Diagnostic exact value, not a
     free choice — same in both themes (the spec quotes one hex with no light/dark variant). */
  --st-dashboard-tab-active: #00ACAC;

  /* status */
  --st-success:            #198754;
  --st-success-fill:       #198754;
  --st-success-subtle:     #e3f2ea;
  --st-success-on-subtle:  #146c43;
  --st-warning:            #8f6400;
  --st-warning-fill:       #8f6400;
  --st-warning-subtle:     #fdf3d9;
  --st-warning-on-subtle:  #7a5500;
  --st-danger:             #dc3545;
  --st-danger-fill:        #dc3545;
  --st-danger-fill-hover:  #bb2d3b;
  --st-danger-subtle:      #fce8ea;
  --st-danger-on-subtle:   #b02a37;

  /* focus */
  --st-focus-ring:            #1f6fd4;
  /* LOGIN-SPEC §9.2 (approved by Cowork 08-04): --st-accent-on-chrome is the honest name for the
     production blue used as a GRAPHIC on the chrome (nav active indicator, login accent rule);
     the focus ring on chrome is a focus ring that happens to share it. One value, three uses. */
  --st-accent-on-chrome:      #4f9cf7;

  /* SPRINT-QA 2026-08-14 #10, second-order consequence caught before it shipped. The login/verify
     brand panel (Auth.css's .lg-brand, "the dark-chrome signature") was built on the *-on-chrome
     tokens back when the chrome was dark in BOTH themes. #10 makes the chrome light in light mode --
     which would have flipped the login page's dark signature panel to light as a side effect, i.e.
     redesigned the one screen Mazhar's own sprint order says not to touch (#7 is his, excluded).
     These tokens hold the ORIGINAL dark chrome values and never vary by theme, so the auth panel is
     now independent of the app chrome -- which is also the honest model: it is a brand surface, not
     application chrome that happens to look the same. Same values in both themes, so no override in
     the dark block below. */
  --st-brand-panel-surface:     #262d33;
  --st-brand-panel-text:        #ffffff;
  --st-brand-panel-text-muted:  rgba(255, 255, 255, 0.72);
  --st-brand-panel-border:      rgba(255, 255, 255, 0.30);
  --st-brand-panel-accent:      #4f9cf7;
  /* W544 (2026-08-17): this pointed at --st-accent-on-chrome (#4f9cf7), a light blue chosen when the
     chrome was DARK in both themes. SPRINT-QA #10 made light mode's chrome #f5f7f9, which took this
     pairing to a MEASURED 2.63:1 against the 3:1 UI-boundary minimum -- the suite caught it, so it is
     a defect and not a stale test. It now points at --st-focus-ring (#1f6fd4 in light = 4.55:1 on the
     light chrome). Deliberately NOT overridden in the dark block: var() resolves at the use site, so
     under [data-theme="dark"] --st-focus-ring is #4f9cf7 and this token keeps its original dark value
     (4.92:1 on #262d33) with no second declaration to keep in step.
     STILL UNMEASURED, named rather than silently inherited: --st-accent-on-chrome is also the nav
     ACTIVE INDICATOR on the same light chrome, so that graphic has the same 2.63:1 problem. Left alone
     here because it is a visible design colour, not a focus ring -- see W544's ledger row. */
  --st-focus-ring-on-chrome:  var(--st-focus-ring);
  --st-focus-ring-offset:     #ffffff;

  /* accounting semantics (aliases -- do not diverge) */
  --st-debit:  var(--st-accent);
  --st-credit: var(--st-danger);

  /* categorical, charts only -- never for meaning */
  --st-chart-1: #1f6fd4;  --st-chart-2: #198754;
  --st-chart-3: #8f6400;  --st-chart-4: #6f42c1;
  --st-chart-5: #b02a37;  --st-chart-6: #0d7f92;

  /* space -- 4px base */
  --st-space-1: 4px;   --st-space-2: 8px;   --st-space-3: 12px;
  --st-space-4: 16px;  --st-space-5: 24px;  --st-space-6: 32px;

  /* radius */
  --st-radius-sm: 4px;   /* controls */
  --st-radius-md: 8px;   /* cards, tables, modals */
  --st-radius-pill: 999px;

  /* type */
  --st-font-ui:   "Work Sans", system-ui, sans-serif;      /* labels, buttons, headings */
  --st-font-text: "Source Sans 3", system-ui, sans-serif;  /* body, prose */
  --st-font-num:  "Consolas", ui-monospace, monospace;     /* amounts, totals */
  --st-text-xs:   12px;  --st-leading-xs: 1.6;
  --st-text-sm:   14px;  --st-leading-sm: 1.5;
  --st-text-base: 16px;  --st-leading-base: 1.5;
  --st-text-lg:   20px;  --st-leading-lg: 1.3;
  --st-text-xl:   24px;  --st-leading-xl: 1.2;

  /* metrics */
  --st-control-h:         36px;  /* inputs, selects, buttons */
  --st-control-h-sm:      32px;  /* in-grid controls, pager */
  --st-icon-btn:          32px;
  /* 0-ROW-SPACING (2026-08-05) bumped this 40px -> 44px for breathing room around row text (kept:
     the real vertical padding on .data-grid td, DataGrid.razor.css). 0-REVIEW-9 #2 (2026-08-06,
     Mazhar's live review) supplied the PRECISE rule that first pass was missing: a data row must be
     slightly SHORTER than --st-grid-header-h (40px) and match the height class of the date inputs
     (--st-control-h, 36px) -- not "taller for breathing room" but "the same control-height anchor
     every other field already uses." 44px -> 36px, same value as --st-control-h. */
  --st-row-h:             36px;  /* editable / clickable grid row -- matches --st-control-h */
  /* W148: was 28px, which is 0.70 of the 40px header -- the "not half, slightly shorter" rule broken
     in advance. Nothing uses this token today, so it renders nowhere and this change is invisible; the
     point is that the FIRST report grid to reach for it (the comment invites exactly that) would have
     shipped the same defect W145 just found in the old app's reports grid. 34px = 0.85 of the header,
     the same bound --st-row-h already satisfies, while staying visibly denser than an editable row. */
  --st-row-h-compact:     34px;  /* read-only report grid */
  --st-grid-header-h:     40px;
  --st-topbar-h:          48px;
  --st-nav-w:             210px;
  --st-nav-w-collapsed:   70px;
  --st-nav-item-h:        36px;
  /* A181 (Mazhar, 2026-08-20 night, EXPLICIT OVERRIDE of the --st-tap-min pin below): "Main menu rows
     (the ones with icons) still have the OLD height -- apply the same reduction so main + sub are
     uniform." OldApp flagged this as a real conflict first, not guessed through: --st-nav-item-h had
     been pinned to --st-tap-min (44px) across THREE separate rulings (B17 2026-08-17, A102 2026-08-20,
     and A179 2026-08-20 itself -- A179's own comment above draws this exact line on purpose, "this has
     no accessibility floor to respect the way --st-nav-item-h does"). Mazhar's answer, given the
     conflict, was explicit: 36px, matching --st-control-h/--st-row-h, overriding the tap-min floor for
     this control. Per mazhar-rules.md §4 ("a change of mind is a ruling, not an inconsistency... the
     latest ruling wins, silently") this is recorded, not re-litigated. --st-tap-min itself is UNCHANGED
     (44px) and still governs the topbar menu and any other control that cites it directly -- only this
     one token's pin to it is removed. */
  /* R4 B17 (Mazhar, 2026-08-17, his SECOND report of the same thing): "Setup submenu rows are
     congested in height vs every other menu -- make all menus uniform." Sub-items were 4px shorter
     than top-level rows, and the topbar menu's own rows are --st-tap-min (44px), so the app had
     THREE menu row heights. One number then, matching 44px --st-tap-min.
     A102 (Mazhar 2026-08-20, first time this reached prod, BUG/REGRESSION): "the real menu's row
     height INCREASED instead of decreasing" -- a change of mind on B17 once he actually saw the
     44px unification live, not an inconsistency (mazhar-rules.md §4: the latest ruling wins,
     silently). Reverted to 40px, the exact pre-B17 value -- restoring the prior height rather than
     guessing a new one, since A102 only says "must not grow", not what it should become. B17's
     actual congestion fix (flex-shrink:0 on the sub-item, 500px -> 1600px group cap, viewport-bound
     flyout) is untouched -- that fixed a real squashing bug independent of this token's value, and
     30 rows * 40px = 1200px still comfortably fits the 1600px cap. Kept as its own token, same
     reasoning as before: a future spec can split item/subitem height again deliberately. */
  /* A179 (Mazhar 2026-08-20 evening): A102's 40px revert reached prod and read as "decreased a
     little... still lot of gap" -- same lever again, another 20% off (40px * 0.8 = 32px, rounds
     exact). Sub-item rows aren't held to --st-tap-min (see that token's own "phone: never smaller"
     scope, which A102/B17's history already treats as top-level-only), so this has no accessibility
     floor to respect the way --st-nav-item-h does. */
  --st-nav-subitem-h:     32px;
  --st-tap-min:           44px;  /* phone: never smaller */

  /* elevation */
  --st-shadow-sm: 0 1px 2px rgba(15, 26, 38, 0.08);
  --st-shadow-md: 0 8px 24px rgba(0, 0, 0, 0.20);

  /* motion */
  --st-duration-fast: 150ms;
  --st-duration-slow: 300ms;
  --st-ease: cubic-bezier(0.4, 0, 0.2, 1);

  /* states */
  --st-disabled-opacity: 0.45;
  --st-inactive-opacity: 0.65;
}

[data-theme="dark"] {
  color-scheme: dark;

  --st-surface-app:        #11161a;
  --st-surface:            #1a2026;
  --st-surface-alt:        #212930;
  --st-surface-overlay:    #262d33;
  --st-surface-chrome:     #262d33;
  /* SPRINT-QA 2026-08-14 #10: these six were previously declared ONLY in :root, because the chrome
     was dark in both themes and one declaration served both. Now that light mode has a light chrome,
     dark mode must declare its own or it would inherit light mode's dark ink onto a dark chrome --
     an invisible menu. These are the ORIGINAL :root values, moved here unchanged, so dark mode looks
     exactly as it did and COMPONENT-SPECS.md §10's measured contrast still describes it. */
  --st-surface-hover-on-chrome:  rgba(255, 255, 255, 0.08);
  --st-surface-active-on-chrome: rgba(255, 255, 255, 0.15);
  --st-border-on-chrome:         rgba(255, 255, 255, 0.30);
  --st-text-on-chrome:           #ffffff;
  --st-text-on-chrome-muted:     rgba(255, 255, 255, 0.72);
  --st-surface-hover:      rgba(255, 255, 255, 0.06);
  --st-surface-active:     rgba(255, 255, 255, 0.10);
  --st-surface-selected:   rgba(79, 156, 247, 0.16);

  --st-border:             #333c44;
  --st-border-subtle:      #272f36;
  --st-border-strong:      #48535d;
  --st-border-input:       #6c7a86;

  --st-text-primary:       #eef1f4;
  --st-text-secondary:     #b3bcc5;
  --st-text-muted:         #939ca5;

  --st-accent:             #4f9cf7;   /* text, icons, links, active indicator */
  --st-accent-fill:        #1f6fd4;   /* UNCHANGED from light -- keeps the ink white */
  --st-accent-fill-hover:  #2f7ee0;
  --st-accent-fill-active: #1a5cb0;
  --st-accent-subtle:      #14304f;
  --st-accent-on-subtle:   #8ec1fb;
  --st-dashboard-tab-active: #00ACAC;

  --st-success:            #3ecf8e;
  --st-success-subtle:     #10352a;
  --st-success-on-subtle:  #5cd9a0;
  --st-warning:            #e0a139;
  --st-warning-subtle:     #3a2a0c;
  --st-warning-on-subtle:  #e9b661;
  --st-danger:             #f2707c;
  --st-danger-subtle:      #3d1418;
  --st-danger-on-subtle:   #f79aa3;
  /* *-fill tokens intentionally NOT overridden -- see contrast report */

  --st-focus-ring:         #4f9cf7;
  --st-focus-ring-offset:  #1a2026;

  --st-chart-1: #4f9cf7;  --st-chart-2: #3ecf8e;
  --st-chart-3: #e0a139;  --st-chart-4: #a78bfa;
  --st-chart-5: #f2707c;  --st-chart-6: #4fc3d4;

  --st-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.40);
  --st-shadow-md: 0 8px 24px rgba(0, 0, 0, 0.55);
}

/* SYSTEM THEME -- resolved via an inline script in index.html <head>, above the stylesheet link,
   before Blazor boots (prevents a light-theme flash on a dark-mode machine during the WASM load).
   [data-theme="dark"] above is the ONLY dark block that exists -- no @media (prefers-color-scheme)
   block, by design (see index.html's inline script comment and ThemeService for the full mechanism
   -- persists the PREFERENCE ('system'/'light'/'dark'), never the resolved value, and follows an OS
   flip mid-session via matchMedia's change event). */

/* Deprecated aliases -- keep until every component is migrated, then delete. */
:root {
  --surface:        var(--st-surface);
  --surface-raised: var(--st-surface-alt);
  --surface-sunken: var(--st-surface-app);
  --border:         var(--st-border);
  --border-strong:  var(--st-border-strong);
  --text-primary:   var(--st-text-primary);
  --text-secondary: var(--st-text-secondary);
  --text-muted:     var(--st-text-muted);
  --text-on-accent: var(--st-text-on-fill);
  --accent:         var(--st-accent);
  --accent-hover:   var(--st-accent-fill-hover);
  --accent-muted:   var(--st-accent-subtle);
  --success:        var(--st-success);
  --warning:        var(--st-warning);
  --danger:         var(--st-danger);
  --info:           var(--st-accent);   /* merged */
  --focus-ring:     var(--st-focus-ring);
  /* This app's own legacy names with no equivalent above -- mapped to their closest new-system
     counterpart so nothing silently falls back to an unset custom property (which resolves to
     the initial value, i.e. invisible/transparent, not an error). */
  --warning-muted:  var(--st-warning-subtle);
  --danger-muted:   var(--st-danger-subtle);
  --debit:          var(--st-debit);
  --credit:         var(--st-credit);
  --chart-1: var(--st-chart-1);  --chart-2: var(--st-chart-2);
  --chart-3: var(--st-chart-3);  --chart-4: var(--st-chart-4);
  --chart-5: var(--st-chart-5);  --chart-6: var(--st-chart-6);
  --space-1: var(--st-space-1);  --space-2: var(--st-space-2);  --space-3: var(--st-space-3);
  --space-4: var(--st-space-4);  --space-6: var(--st-space-6);  --space-8: var(--st-space-6);
  --radius-sm: var(--st-radius-sm);  --radius-md: var(--st-radius-md);  --radius-lg: var(--st-radius-md);
  --font-sans: var(--st-font-ui);
  --text-xs: var(--st-text-xs);  --text-sm: var(--st-text-sm);  --text-base: var(--st-text-base);
  --text-lg: var(--st-text-lg);  --text-xl: var(--st-text-xl);
  --shadow-sm: var(--st-shadow-sm);  --shadow-md: var(--st-shadow-md);
}

*, *::before, *::after { box-sizing: border-box; }

/* W550 NINTH PASS (2026-08-19, OldApp, bug 65 continuation): the topbar cluster's own controls are
   all correctly sized now (verified in the sha=62d3d86 E2E run -- .shell-signout-btn/.shell-icon-btn
   measured exactly 32px, matching the CSS), yet .shell-topbar's own scrollWidth still differs PER
   PAGE (400 ReportPicker, 411 ChangePasswordPage, 424 NewTransactionPage, 428 CoaTree, 465
   SecAccountListPage) even though the shell markup is identical on all five. .shell-topbar is a
   normal-flow flex child of `.shell` (height: 100vh, no width containment), not position:fixed, so
   its width tracks its ancestor's content-box width -- and nothing in this stylesheet ever capped
   html/body at the viewport. Any page with content wider than 375px (a grid, a wide row) was
   silently growing html/body's own scrollWidth, and the topbar -- a 100%-width child of that same
   ancestor chain -- grew with it. This is the "second, per-screen contributor" every pass since the
   fifth has been chasing without a browser to confirm it live; overflow-x: hidden here is the
   standard containment fix and doesn't affect any element that already manages its own horizontal
   scroll (e.g. a DataGrid with its own overflow-x: auto keeps scrolling internally, it just can no
   longer drag the whole document along with it). */
html, body {
  margin: 0; height: 100%; min-width: 320px;
  overflow-x: hidden;
  font-family: var(--st-font-text);
  font-size: var(--st-text-sm);
  line-height: var(--st-leading-sm);
  background: var(--st-surface-app);
  color: var(--st-text-primary);
}

a { color: var(--st-accent); }
a:hover { color: var(--st-accent-on-subtle); }

:focus-visible {
  outline: 2px solid var(--st-focus-ring);
  outline-offset: 2px;
}
.st-on-chrome :focus-visible {
  outline-color: var(--st-focus-ring-on-chrome);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 1ms !important; animation: none !important; }
}
