/* Kit Locker — light theme. Tokens mirror academy-hub redesign.
 * 12 May 2026: Kit Intelligence brand-tokens imported below; legacy
 * --navy / --gold tokens kept for now so existing component styles
 * don't break. Replace them with --ki-* tokens incrementally. */
@import url("brand-tokens.css");

:root {
  /* Kit Intelligence product brand — fixed across ALL tenants by design (the
     product mark, login, splash, toast, promo). This is the Kit Intelligence
     product chrome colour, NOT a tenant value: it is intentionally not in
     clubs.py _THEME_DEFAULTS and must never be referenced on a themed in-app
     page. Confirmed usage (May 2026): only the tenant-neutral login surface
     (.ki-login*) and the brand splash. The per-club accent (--navy/--gold
     below, overridden in base.html from theme.primary/accent) is the only
     palette that tracks the tenant, so the product chrome reads on-brand
     while actions take the club colour. The hex matches the founding
     tenant's legacy teal, but this is product chrome and not tenant
     leakage — do not re-flag as a hardcode. */
  --teal: #164353;
  --teal-deep: #0c2c38;
  --display: 'Geist', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* Tenant accent (overridden per club in base.html via --navy/--gold).
     --accent* is the canonical tenant token the Kit Intelligence (.ki-*)
     component set reads. It follows --navy, so the single per-club override
     in base.html themes BOTH the legacy and the KI components at once.
     --accent-soft / --accent-tint use color-mix off the live accent, with a
     static teal-grey fallback for engines without color-mix support.
     P2, 30 Jul 2026: these four used to be the founding tenant's own
     brand colours — the platform's base CSS, not a per-tenant value, so
     any page that loads app.css without base.html's per-tenant override
     block (owner_base.html, the KI owner console) rendered in that
     tenant's colours. Match clubs._THEME_DEFAULTS instead. */
  --navy: #164353;
  --navy-2: #0c2c38;
  --gold: #1f5566;
  --gold-2: #0c2c38;
  /* Always resolvable: base.html overrides it per club, but a token with
     no declared value silently drops the rule that reads it. */
  --club-hero: #164353;
  --club-primary: #164353;
  --accent: var(--navy);
  --accent-deep: var(--navy-2);
  --accent-soft: #E5EDED;
  --accent-soft: color-mix(in srgb, var(--accent) 12%, #fff);
  --accent-tint: #F0F4F4;
  --accent-tint: color-mix(in srgb, var(--accent) 7%, #fff);

  /* Neutral canvas — Kit Intelligence "paper" system: warm off-white page
     (never pure white) carrying a faint paper-grain (body::before), with a
     hair-off-white surface so white cards float on the warm paper. Borders
     warmed to sit in the paper system. */
  --paper: #F1EDE4;
  --bg: #F1EDE4;
  --surface: #FFFEFB;
  --border: #E8E5DD;
  --line: var(--border);
  --line-2: #F0EDE6;
  --track: #E4E0D6;   /* neutral bar track — score bars, progress fills */
  --ink: #0A1628;
  --ink-2: #39414f;
  --muted: #6B7280;

  /* Status — carried by a dot + label, never colour alone (AA-tuned tints). */
  --ok: #2F7A4D;   --ok-soft: #E3F0E8;
  --warn: #9A6B22; --warn-soft: #F4ECDC;
  --bad: #B0402B;  --bad-soft: #F4E4DF;

  /* Soft two-layer elevation so white cards lift off the textured paper —
     load-bearing for the premium feel (Kit Intelligence design handoff). */
  --shadow: 0 1px 2px rgba(12, 32, 56, 0.05), 0 10px 26px rgba(12, 32, 56, 0.05);
  --shadow-sm: 0 1px 2px rgba(12, 32, 56, 0.05), 0 4px 12px rgba(12, 32, 56, 0.04);
  --radius: 13px;
  --radius-sm: 9px;
  /* One curve for the whole owner console — no bounce, no second easing.
     Named rather than hand-typed so a later screen cannot drift off it.
     Theme-independent, so it lives here beside the radii, not in theme-ki. */
  --ease-ki: cubic-bezier(.2, .9, .3, 1);
  /* The dense-row padding the owner ledger and worklist share. Both were
     specified as "18px 24px" in the handoff tables; naming it means the two
     screens cannot disagree by a pixel. */
  --card-pad-lg: 18px 24px;
  /* Spacing scale — full 8-step ladder on the brand --ki-space-* base
     (brand-tokens.css), which shipped but was never wired up. One scale,
     used everywhere, replaces hand-typed margin magic numbers. */
  --space-1: var(--ki-space-1); --space-2: var(--ki-space-2);
  --space-3: var(--ki-space-3); --space-4: var(--ki-space-4);
  --space-5: 20px;              --space-6: var(--ki-space-6);
  --space-7: 28px;             --space-8: var(--ki-space-8);
}

/* ─── Spacing utilities ─────────────────────────────────────────────────
   Prefer these over inline margin-top magic numbers. `.section-gap` is the
   standard rhythm between stacked cards/sections (was a repeated inline 14px). */
.section-gap      { margin-top: var(--space-4); }   /* 16px */
.section-gap-lg   { margin-top: var(--space-6); }   /* 24px */
.stack            { display: flex; flex-direction: column; }
.stack > * + *    { margin-top: var(--space-4); }
.stack-lg > * + * { margin-top: var(--space-6); }

/* ─── Dark "Kit Intelligence Platform" theme — behind the ?theme=ki flag ─────
   Phase 1 foundation of the dark left-rail redesign. This flips every
   TOKEN-driven surface to the obsidian/teal scale in one place; the
   hardcoded-light-literal sweep, the left-rail shell, and per-page fidelity
   land in later phases. Working accent = Kit Intelligence teal for EVERY club
   (a club shows through its crest + the hero colour, not the UI accent); gold
   is sacred — forecast figure + fixture date only. */
html.theme-ki {
  /* Native controls, carets and scrollbars follow the dark surface instead of
     rendering light on obsidian. */
  color-scheme: dark;
  --obsidian:#06141a; --paper:#06141a; --bg:#06141a;
  --surface:#0f2028; --surface-alt:#193640; --surface-2:#0f2028; --panel-3:#264c58;
  --card-bg:#0f2028; --surface-muted:#193640;  /* legal/misc pages that read these with a light fallback */
  --border:rgba(255,255,255,.09); --line:rgba(255,255,255,.09); --line-2:rgba(255,255,255,.06);
  --edge:rgba(255,255,255,.09); --edge-2:rgba(255,255,255,.16);
  --ink:#eaf4f6; --ink-2:#9fbac1; --muted:#6f95a0; --track:#193640;
  --area:#5fb6c4; --area-soft:rgba(95,182,196,.15);
  --navy:#5fb6c4; --navy-2:#4b97a3; --accent:#5fb6c4; --accent-deep:#4b97a3;
  --accent-soft:rgba(95,182,196,.15); --accent-tint:rgba(95,182,196,.08);
  --on-navy:#06141a; --on-gold:#06141a;
  --gold:#d9a441; --gold-2:#d9a441;
  --ok:#57b45f; --warn:#d9a441; --bad:#e0706a;
  --ok-soft:rgba(87,180,95,.15); --warn-soft:rgba(217,164,65,.15); --bad-soft:rgba(224,112,106,.15);
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 12px 30px rgba(0,0,0,.45);
  --shadow-sm:0 1px 2px rgba(0,0,0,.4);
  --shadow-lg:0 16px 52px rgba(0,0,0,.6);
  /* The decision-queue / ledger card. Sits between --shadow and --shadow-lg:
     the card must lift off obsidian without the halo that --shadow-lg throws
     at full width, which reads as a modal rather than a page section. */
  --shadow-queue:0 1px 2px rgba(0,0,0,.45), 0 14px 40px rgba(0,0,0,.5);
  /* A near-white plate to host COLOUR ARTWORK on obsidian — club crests are
     drawn for white grounds and most of them vanish into the dark. It is not
     --ink: that is a text colour, and reaching for it as a surface because it
     happens to be pale is exactly the drift the token set exists to stop. */
  --chip-light:#f4f9fa;
  --brand-ink:#eaf4f6;
  /* Space Grotesk (display) + Hanken Grotesk (body) — self-hosted woff2 still
     to vendor; falls back to the current families until then. */
  --display:'Space Grotesk','Geist',ui-sans-serif,-apple-system,'Segoe UI',sans-serif;
}
html.theme-ki body {
  background:var(--obsidian);
  background-image:radial-gradient(1100px 460px at 15% -8%, #0d2733 0%, transparent 62%);
  font-family:'Hanken Grotesk','Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
}
html.theme-ki body::before { mix-blend-mode:screen; opacity:.03; }  /* soften the paper grain on obsidian */
/* headings read --navy (a dark ink) on light; keep them light on obsidian */
html.theme-ki h1, html.theme-ki h2, html.theme-ki h3, html.theme-ki h4 { color:var(--ink); }

/* ─── Shared components on the dark canvas ────────────────────────────────────
   The bespoke .ki-* blocks carry their own dark colours; these cover the SHARED
   component library that HARDCODES light colours (kpi cards, .form-row controls,
   native inputs, table cells + hover, chips, empty states). Without them, any
   page the redesign didn't bespoke-rebuild (Reports, admin, item forms) shows
   white panels on the obsidian canvas. Placed early so bespoke .ki-* rules win. */
html.theme-ki .kpi-card { background:var(--surface); border-color:var(--edge); }
/* Location picker in the rail — the dark theme's home for the site filter,
   which was stranded in the hidden .topbar until 19 Aug 2026. Styled as part
   of the rail's scope column, not as a form control. */
html.theme-ki .ki-sitepick { display:block; margin:10px 14px 4px; }
html.theme-ki .ki-sitepick-lab {
  display:block; font-size:10px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--muted); margin:0 0 5px 2px;
}
html.theme-ki .ki-sitepick-sel {
  width:100%; padding:8px 10px; font-size:13px; font-family:inherit;
  color:var(--ink); background-color:var(--surface-alt);
  border:1px solid var(--edge); border-radius:8px; cursor:pointer;
}
html.theme-ki .ki-sitepick-sel:hover { border-color:var(--edge-2); }
html.theme-ki .ki-sitepick-sel:focus-visible {
  outline:none; border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft);
}
/* 19 Aug 2026 — THIS SELECTOR LIST HAD NO DECLARATION BLOCK OF ITS OWN.
   The .ai-input opt-out below was added on 18 Aug in the MIDDLE of the list,
   so every selector above it became part of the .ai-input rule and inherited
   `background: transparent; box-shadow: none` — while the intended
   background/colour/border landed on the `textarea, select` rule alone.
   Net effect: every text input in the dark theme had no fill and no border
   colour, so it fell through to the light theme's base border and wore the
   gold focus colour at rest. That is the "horrible gold perimeter" on
   Checkout, and it was on every form in the product. A trailing comma. */
html.theme-ki .form-row input:not([type=checkbox]):not([type=radio]),
html.theme-ki .form-row select,
html.theme-ki .form-row textarea,
html.theme-ki input[type=text], html.theme-ki input[type=search],
html.theme-ki input[type=number], html.theme-ki input[type=email],
html.theme-ki input[type=password], html.theme-ki input[type=date],
html.theme-ki input[type=tel], html.theme-ki input[type=url],
/* An <input> with NO type attribute reports .type === "text" but does NOT
   match [type=text] — an attribute selector needs the attribute present, and
   the property's default value is not the same thing. Ten fields across the
   owner console omit it, so the dark theme never reached them: each kept the
   light background from its own inline rule and inherited a light text
   colour on top, i.e. white on white, with typing invisible. Theme by the
   attribute's ABSENCE as well as by its value. */
html.theme-ki input:not([type]),
html.theme-ki textarea, html.theme-ki select {
  background-color:var(--surface-alt); color:var(--ink); border-color:var(--edge);
}
/* 18 Aug 2026: the rule above painted EVERY textarea with a field fill, the
   assistant's included — and that one lives inside its own darker
   .ai-input-row pill, so it rendered as a light box inside a dark box and read
   as "selected". The assistant input is chrome, not a form field. It opts out.
   Must stay a SEPARATE rule; folding it into the list above is what broke it. */
html.theme-ki .ai-input,
html.theme-ki .ai-input:focus { background: transparent; box-shadow: none; }
html.theme-ki input::placeholder, html.theme-ki textarea::placeholder { color:var(--muted); }
html.theme-ki th { background:rgba(255,255,255,.04); color:var(--ink-2); border-color:var(--edge); }
html.theme-ki td { border-color:var(--edge); }
html.theme-ki tbody tr:hover { background:var(--surface-alt); }
html.theme-ki .chip-ok   { background:var(--ok-soft);   color:var(--ok); }
html.theme-ki .chip-warn { background:var(--warn-soft); color:var(--warn); }
html.theme-ki .chip-bad  { background:var(--bad-soft);  color:var(--bad); }
html.theme-ki .chip-cat  { background:var(--area-soft); color:var(--area); }
html.theme-ki .empty-state-icon { background:var(--surface-alt); }
html.theme-ki .empty-state-icon svg [stroke] { stroke:var(--ink-2); }
html.theme-ki .cmdk-hint { background:var(--surface-alt); }
html.theme-ki .flash-ok    { background:var(--ok-soft);  color:var(--ok);  border-color:var(--ok); }
html.theme-ki .flash-error { background:var(--bad-soft); color:var(--bad); border-color:var(--bad); }
html.theme-ki .period-pill { background:var(--surface-alt); border-color:var(--edge); }
html.theme-ki .link-action:hover { background:var(--surface-alt); }
html.theme-ki .typeahead-results { background:var(--surface); border-color:var(--edge); }
html.theme-ki .btn-secondary { background:var(--surface-alt); color:var(--ink); border-color:var(--edge); box-shadow:none; }
html.theme-ki .btn-secondary:hover { background:var(--panel-3); filter:none; }
/* Metal/tier badges hardcode dark text for their light tint; brighten it so it
   reads on the translucent tint over obsidian (People pages). */
html.theme-ki .pkc-tier-platinum { color:#aab6cc; }
html.theme-ki .pkc-tier-gold     { color:#d0a95f; }
html.theme-ki .pkc-tier-silver   { color:#aeb6c2; }
html.theme-ki .pkc-tier-bronze   { color:#cd9165; }

/* ─── Phase 2 shell — fixed left rail + slim top bar + mobile tab bar ─────────
   Overlays shown only under .theme-ki; the light .topbar/.footer are hidden and
   .container is offset, so the light layout is untouched. */
.ki-rail, .ki-topbar, .ki-tabbar { display:none; }
html.theme-ki .topbar, html.theme-ki .footer { display:none; }
html.theme-ki .container { max-width:none; margin:0 0 0 264px; padding:84px 30px 48px; }

html.theme-ki .ki-rail {
  display:flex; flex-direction:column; gap:3px; position:fixed; left:0; top:0; bottom:0; width:264px; z-index:30;
  padding:20px 16px; overflow-y:auto; border-right:1px solid var(--edge);
  background:linear-gradient(180deg, rgba(255,255,255,.02), transparent);
}
html.theme-ki .ki-rail-brand { display:flex; align-items:center; gap:11px; text-decoration:none; color:var(--ink); margin-bottom:16px; }
html.theme-ki .ki-rail-mark { border-radius:9px; flex:none; }
html.theme-ki .ki-rail-brand b { font-family:var(--display); font-weight:600; font-size:15px; display:block; line-height:1.15; }
html.theme-ki .ki-rail-brand small { font-size:9.5px; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }
html.theme-ki .ki-area { display:flex; align-items:center; gap:11px; background:var(--area-soft); border:1px solid var(--edge); border-radius:11px; padding:10px 12px; margin-bottom:14px; }
html.theme-ki .ki-area-crest { width:30px; height:30px; border-radius:7px; flex:none; object-fit:contain;
  /* P3, 30 Jul 2026: was filter:brightness(0) invert(1) — correct only for
     an outline-style crest (renders white on the dark rail), wrong for any
     tenant with a colour crest (a red badge would render cyan). A light
     chip lets any crest read as-is against the dark rail without touching
     its colour. A tenant can still supply theme.logo_dark_url for a
     purpose-made dark-surface asset — this chip is the fallback for the
     tenants who haven't. */
  background:#fff; padding:3px; box-sizing:border-box; }
html.theme-ki .ki-area b { font-size:13px; display:block; line-height:1.2; }
html.theme-ki .ki-area small { font-size:11px; color:var(--muted); }
html.theme-ki .ki-rail-lab { font-size:10px; letter-spacing:.16em; text-transform:uppercase; color:var(--muted); margin:12px 6px 6px; }
html.theme-ki .ki-nav { display:flex; flex-direction:column; gap:2px; }
html.theme-ki .ki-nav a { display:flex; align-items:center; gap:10px; padding:9px 12px; border-radius:9px; color:var(--ink-2); text-decoration:none; font-size:14px; font-weight:500; }
html.theme-ki .ki-nav a:hover { color:var(--ink); background:rgba(255,255,255,.04); }
html.theme-ki .ki-nav a.on { color:var(--ink); background:var(--area-soft); box-shadow:inset 2px 0 0 var(--area); font-weight:600; }
html.theme-ki .ki-rail-user { display:flex; align-items:center; gap:10px; margin:auto 0 0; padding-top:14px; border-top:1px solid var(--edge); }
html.theme-ki .ki-av { width:34px; height:34px; border-radius:50%; background:var(--panel-3); display:grid; place-items:center; font-size:12px; font-weight:700; color:var(--ink); flex:none; }
html.theme-ki .ki-rail-user b { font-size:13px; display:block; line-height:1.2; }
html.theme-ki .ki-rail-user small { font-size:11px; color:var(--muted); }
html.theme-ki .ki-signout {
  margin-left:auto; background:none; border:0; color:var(--muted);
  cursor:pointer; padding:6px; border-radius:7px; line-height:0;
  display:inline-flex; align-items:center; justify-content:center;
  transition:color .12s, background .12s;
}
html.theme-ki .ki-signout:hover { color:var(--ink); background:rgba(255,255,255,.06); }
html.theme-ki .ki-signout:focus-visible {
  outline:none; color:var(--ink); box-shadow:0 0 0 2px var(--accent);
}
html.theme-ki .ki-signout:hover { color:var(--ink); }

html.theme-ki .ki-topbar {
  display:flex; align-items:center; gap:12px; position:fixed; top:0; left:264px; right:0; height:64px; z-index:20;
  padding:0 26px; border-bottom:1px solid var(--edge);
  background:rgba(6,20,26,.86); -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
}
html.theme-ki .ki-search { flex:1; max-width:440px; display:flex; align-items:center; gap:9px; background:var(--surface); border:1px solid var(--edge); border-radius:11px; padding:8px 13px; color:var(--muted); font-size:13px; }
html.theme-ki .ki-search input { flex:1; background:none; border:0; color:var(--ink); outline:none; font:inherit; font-size:13px; }
html.theme-ki .ki-search input::placeholder { color:var(--muted); }
html.theme-ki .ki-actions { display:flex; gap:9px; margin-left:auto; }
html.theme-ki .ki-actions .btn { font-size:12.5px; padding:9px 14px; }
/* Gold is sacred on the dark canvas (forecast/fixture only), so a .btn-gold
   action re-skins to the teal UI accent here. Light keeps its gold gradient. */
html.theme-ki .btn-gold {
  background: var(--area);
  color: #04222a;
  box-shadow: none;
}
html.theme-ki .btn-gold:hover { filter: brightness(1.08); }

@media (max-width:820px) {
  html.theme-ki .ki-rail { display:none; }
  html.theme-ki .ki-topbar { left:0; }
  html.theme-ki .container { margin-left:0; padding:80px 16px calc(84px + env(safe-area-inset-bottom)); }
  html.theme-ki .ki-tabbar {
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:30;
    background:rgba(6,20,26,.94); -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
    border-top:1px solid var(--edge); padding:6px 8px calc(6px + env(safe-area-inset-bottom));
  }
  /* The fixed tab bar above already pads the home-indicator inset, and .container
     now reserves room for it — so body must NOT pad it a second time. Counting it
     twice left 34px of blank scrollable page under the last row on an iPhone
     (measured: scrollHeight 1917 vs content 1883). Scoped to theme-ki + mobile,
     so the light layout keeps body's inset exactly as it was. */
  html.theme-ki body { padding-bottom:0; }
  html.theme-ki .ki-tabbar a { flex:1; min-height:52px; display:flex; align-items:center; justify-content:center; padding:8px 4px; color:var(--muted); text-decoration:none; font-size:12px; font-weight:600; border-radius:10px; }
  html.theme-ki .ki-tabbar a.on { color:var(--area); background:var(--area-soft); }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; overflow-x: hidden; max-width: 100vw; }
/* Defensive: ensure the HTML `hidden` attribute always hides, even when an
   element class sets display:flex/grid/etc. Without this, .push-banner and
   any other display-overridden component visibly leaks past `el.hidden = true`. */
[hidden] { display: none !important; }
body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: 15px;
  color: var(--ink);
  background: var(--bg);
  line-height: 1.5;
  min-height: 100vh;
  /* iOS resolves 100vh against the toolbar-HIDDEN (large) viewport, so on a page
     shorter than the screen the document ends up ~90px taller than what is
     actually visible and you can scroll down into empty background. svh is the
     small (toolbars-shown) viewport; browsers without svh keep the 100vh line. */
  min-height: 100svh;
  /* 13 May 2026: clear the iOS home-indicator at the bottom of the page so
     the last row of content / any sticky bar isn't under the swipe bar.
     0 in normal browsers, ~34pt on notched iPhones in PWA mode. */
  padding-bottom: env(safe-area-inset-bottom);
  /* Inter typographic features:
       cv11 = single-storey 'a' (more refined)
       ss01 = open-aperture digits (esp. better '4')
       cv02 = alternate '6' / '9'
       Tabular numerals are applied per-context below. */
  font-feature-settings: "cv11", "ss01", "cv02";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
/* Paper-grain page texture — inline SVG fractal noise (no asset, offline-safe,
   CSP-safe as a data: background like the existing select chevron), fixed so it
   doesn't scroll, behind everything, multiplied onto the warm paper. White
   cards (--surface) sit cleanly on top; the grain only shows in the page. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  mix-blend-mode: multiply; opacity: 0.2;
}
@media (prefers-reduced-motion: reduce) { body::before { opacity: 0.14; } }
a { color: var(--navy-2); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ----- Branded edge details -----
   These are the seams where premium apps win: the scrollbar, the focus ring,
   the text selection. Generic browser defaults expose every interaction as
   "this is a generic webpage." Branded versions whisper "this is a product." */

/* Text selection: navy background, gold-tinted ink. */
::selection {
  background: var(--navy);
  color: var(--gold);
}

/* Custom scrollbars on light surfaces — slim, navy thumb, gold on hover.
   Webkit (Safari, Chrome, modern Edge) + Firefox standards. */
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(11,34,64,0.22) transparent;
}
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: rgba(11,34,64,0.22);
  border-radius: 4px;
  border: 1px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover {
  background: rgba(201,165,90,0.55);
  background-clip: padding-box;
}

/* Focus rings — gold, not navy. Brand expression even in keyboard nav. */
:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  border-radius: 4px;
}
/* Inputs already have a navy focus shadow — let the buttons keep theirs. */
.form-row input:focus-visible,
.form-row select:focus-visible,
.form-row textarea:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: none;
  border-color: var(--gold-2);
  box-shadow: 0 0 0 3px rgba(201,165,90,0.20);
}
/* On the dark canvas the amber focus ring sits beside teal chrome — the Scan
   button, the active nav rail, every primary control — and reads as a warning
   rather than as "you are typing here". The accent already means "active". */
html.theme-ki .form-row input:focus-visible,
html.theme-ki .form-row select:focus-visible,
html.theme-ki .form-row textarea:focus-visible,
html.theme-ki input:focus-visible,
html.theme-ki select:focus-visible,
html.theme-ki textarea:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* ---- top bar ---- */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  /* 12 May 2026: iOS PWA fullscreen mode (status-bar-style=black-translucent)
     draws the page under the iOS status bar. env(safe-area-inset-top)
     returns 0 in normal browsers, ~44-59pt on iOS PWA.
     13 May 2026: also clear the left/right insets so the wordmark + Sign
     out aren't behind the Dynamic Island / rounded corners in landscape.
     max(24px, …) keeps the 24px desktop padding and only grows when the
     device actually reports a bigger inset. The navy background extends
     up into the status-bar area for the unified topbar look. */
  padding:
    calc(12px + env(safe-area-inset-top))
    max(24px, env(safe-area-inset-right))
    12px
    max(24px, env(safe-area-inset-left));
  /* Kit Intelligence light topbar — translucent warm paper with a blur, so it
     floats over the textured page like the cards. Was the dark navy bar; the
     KI mark + wordmark and the outline crest both read on the light surface. */
  background: var(--paper);
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  backdrop-filter: saturate(1.4) blur(12px);
  color: var(--ink);
  position: sticky; top: 0; z-index: 10;
  border-bottom: 1px solid var(--border);
  transition: box-shadow 0.2s, border-color 0.2s;
}
/* Gains a soft drop-shadow once the page scrolls (toggled by a scrollY>6
   listener in base.html) so it lifts off the paper rather than sitting under
   a hairline. */
.topbar.is-scrolled {
  box-shadow: 0 1px 0 rgba(12,32,56,.04), 0 8px 24px rgba(12,32,56,.06);
  border-bottom-color: transparent;
}
.brand {
  display: flex; align-items: center; gap: 10px;
  color: var(--ink); flex-shrink: 0;
  text-decoration: none;
}
.brand:hover { text-decoration: none; }
/* Kit Intelligence product lockup in the topbar — the K mark + "Kit
   Intelligence" wordmark are constant (the product brand); the per-tenant
   club crest sits past a hairline divider to its right. */
.ki-brand-mark-img { width: 28px; height: 28px; display: block; border-radius: 7px; flex-shrink: 0; }
.ki-wm { font-weight: 600; font-size: 15.5px; letter-spacing: -0.015em; color: var(--ink); white-space: nowrap; }
.ki-top-div { width: 1px; height: 22px; background: var(--border); flex-shrink: 0; }
.ki-topbar-crest { height: 34px; width: auto; display: block; flex-shrink: 0; }
/* On a phone hand the scrolling nav its horizontal room: drop the product
   wordmark (the K mark + club crest still identify product + tenant). Mirrors
   the old .brand-wordmark mobile-hide. */
@media (max-width: 640px) { .ki-wm { display: none; } }
.brand-mark {
  width: 44px; height: 44px;
  display: block;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.25));
}
.brand-name {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.02em;
  white-space: nowrap;
  line-height: 1;
  /* "Kit" stays white, "Locker" goes gold via inner span. Treated as a wordmark, not a label. */
}
.brand-name .brand-accent { color: var(--gold); font-weight: 500; }

/* Kit Intelligence brand swap — full lockup on desktop, K-square mark on
   mobile. The lockup wordmark dominated the narrow phone topbar; the
   K-only mark reads identically and gives the nav back its horizontal
   breathing room. Breakpoint matches the @media below at 640px. */
.ki-brand-lockup { height: 28px; width: auto; display: inline-block; }
.ki-brand-mark   { display: none; }
/* The tenant's product wordmark — sits beside the crest in the header /
   footer / login, and reads from theme.product_name. Hidden on narrow
   screens so the crest alone identifies the app. */
.brand-wordmark {
  font-weight: 600; letter-spacing: 0.02em; font-size: 15px;
  color: inherit; white-space: nowrap;
}
@media (max-width: 640px) { .brand-wordmark { display: none; } }
@media (max-width: 640px) {
  .ki-brand-lockup { display: none; }
  /* Keep height at 28px (matching desktop lockup) so the topbar doesn't
     grow taller on mobile than on desktop. Square mark is 1:1 so the
     width follows. */
  .ki-brand-mark   { display: inline-block; height: 28px; width: 28px; }
}

.nav { display: flex; align-items: center; gap: 10px; }
/* Pill nav for the light topbar — ink links, accent-soft pill on the active
   tab (was white links + a gold underline on the old dark bar). */
.nav a {
  color: var(--ink-2);
  font-size: 14px; font-weight: 500;
  position: relative; padding: 7px 12px; border-radius: 8px;
  transition: color 0.12s, background 0.12s;
}
.nav a:hover { color: var(--ink); background: var(--line-2); text-decoration: none; }
.nav a.active { color: var(--accent); background: var(--accent-soft); font-weight: 600; }
.nav a.active::after { display: none; }
.nav-secondary { color: var(--muted) !important; font-weight: 500 !important; }
.nav-secondary::after { display: none !important; }
/* /logout is POST-only, wrapped in a tiny form. Style the form + button
   so they sit inline with the rest of the nav and look like a link. */
.nav-logout-form { display: inline-flex; margin: 0; padding: 0; }
.nav-logout-btn {
  background: transparent; border: none; padding: 0; cursor: pointer;
  font: inherit; line-height: inherit;
}
.nav-logout-btn:hover { color: var(--ink) !important; }
.kiosk-badge {
  background: var(--gold); color: var(--navy);
  padding: 4px 10px; border-radius: var(--radius-sm); font-weight: 600; font-size: 12px;
}

/* ═══ Brand splash — Kit Intelligence × club crest ═══
   From design_handoff v2 (product-reference + SPLASH-INTEGRATION.md): the
   crest rises in a haloed coin, a hairline divider draws, the Kit Intelligence
   wordmark wipes in, a truthful loader (with travelling glow-dot) eases to 90%
   then snaps to 100% when the page is ready, and the whole thing dissolves
   with a blur-scale. Driven by the IIFE in base.html; all props scoped to
   #boot. One addition over the reference: a CSS failsafe fade at 11.5s
   (cancelled by the IIFE the moment JS runs) so a JS failure can never trap a
   user behind the overlay. */
#boot{
  --e-out: cubic-bezier(.2,.9,.3,1);
  --e-spring: cubic-bezier(.34,1.4,.5,1);
  --e-inout: cubic-bezier(.7,0,.2,1);
  --bar: clamp(220px,26vw,300px);
  position:fixed; inset:0; z-index:9999;
  display:flex; align-items:center; justify-content:center;
  background:#06141a; overflow:hidden;
  transition:opacity .7s var(--e-inout);
  animation:kisSafety .7s ease 11.5s forwards; /* JS-off failsafe */
}
#boot.boot-hide{ opacity:0; pointer-events:none; }
@keyframes kisSafety{ to{ opacity:0; visibility:hidden; pointer-events:none; } }
.kis-bg{ position:absolute; inset:0; pointer-events:none; }
.kis-bg-glow{
  position:absolute; left:50%; top:42%; width:160vmin; aspect-ratio:1; transform:translate(-50%,-50%);
  background:radial-gradient(circle, rgba(34,104,120,0.42) 0%, rgba(14,50,61,0.22) 34%, transparent 64%);
  opacity:0; animation:kisGlow 1.6s var(--e-out) .1s forwards;
}
.kis-bg-vig{ position:absolute; inset:0;
  background:radial-gradient(120% 90% at 50% 46%, transparent 52%, rgba(0,0,0,.55) 100%); }
.kis-bg-sheen{
  position:absolute; top:-20%; bottom:-20%; width:42%; left:-50%;
  background:linear-gradient(100deg, transparent, rgba(120,200,212,.05) 46%, rgba(180,230,238,.10) 50%, rgba(120,200,212,.05) 54%, transparent);
  transform:skewX(-12deg); animation:kisSheen 6.5s ease-in-out 1.0s infinite;
}
.kis-grain{ position:absolute; inset:0; pointer-events:none; opacity:.05; mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxODAnIGhlaWdodD0nMTgwJz48ZmlsdGVyIGlkPSduJz48ZmVUdXJidWxlbmNlIHR5cGU9J2ZyYWN0YWxOb2lzZScgYmFzZUZyZXF1ZW5jeT0nMC45JyBudW1PY3RhdmVzPScyJyBzdGl0Y2hUaWxlcz0nc3RpdGNoJy8+PGZlQ29sb3JNYXRyaXggdHlwZT0nc2F0dXJhdGUnIHZhbHVlcz0nMCcvPjwvZmlsdGVyPjxyZWN0IHdpZHRoPScxMDAlJyBoZWlnaHQ9JzEwMCUnIGZpbHRlcj0ndXJsKCNuKScgb3BhY2l0eT0nMC41Jy8+PC9zdmc+"); background-size:180px 180px; transition:opacity .4s ease; }
#boot.boot-hide .kis-grain{ opacity:0; }

.kis-stage{ position:relative; z-index:1; display:flex; flex-direction:column; align-items:center;
  padding:0 28px; transition:transform .7s var(--e-inout), filter .7s var(--e-inout); }
#boot.boot-hide .kis-stage{ transform:translateY(-16px) scale(1.04); filter:blur(6px); }

.kis-crest-wrap{ position:relative; display:flex; align-items:center; justify-content:center; }
.kis-crest-halo{
  position:absolute; left:50%; top:50%; width:200%; aspect-ratio:1; border-radius:50%;
  transform:translate(-50%,-50%) scale(.5); opacity:0; filter:blur(9px);
  background:radial-gradient(circle, rgba(95,182,196,.38) 0%, rgba(95,182,196,.08) 46%, transparent 70%);
  animation:kisHalo 1.7s var(--e-out) .35s forwards;
}
.kis-crest{
  /* A white coin behind the badge. Kit, 19 Aug 2026 — "can the circle be a
     white background to make the badge pop more?" — and it is the same
     finding as the report masthead, the low-stock email, the app icon and
     the assistant panel: a club crest is artwork for a white shirt, and
     Bolton's navy-and-red on the near-black splash sinks into it.
     aspect-ratio + object-fit keep it a CIRCLE whatever shape the club
     uploaded; without them a wide lockup makes an oval. */
  position:relative; width:clamp(86px,9vw,116px); aspect-ratio:1; height:auto;
  display:block; border-radius:50%;
  background:#fff; padding:clamp(9px,1vw,13px); box-sizing:border-box;
  object-fit:contain;
  filter:drop-shadow(0 16px 34px rgba(0,0,0,.5));
  transform:scale(.7); opacity:0; animation:kisCrest 1.1s var(--e-spring) .3s forwards;
}
.kis-crest-ring{
  position:absolute; left:50%; top:50%; width:clamp(86px,9vw,116px); aspect-ratio:1;
  transform:translate(-50%,-50%) scale(1.2); border-radius:50%;
  border:1px solid rgba(255,255,255,.14); opacity:0; animation:kisFade .9s var(--e-out) .7s forwards;
}

.kis-div{ display:flex; align-items:center; gap:10px;
  margin:clamp(22px,3vw,34px) 0 clamp(20px,2.6vw,30px); opacity:0;
  animation:kisFade .6s var(--e-out) .95s forwards; }
.kis-div-line{ height:1px; width:0; background:linear-gradient(90deg,transparent,rgba(143,190,196,.55)); animation:kisLine .7s var(--e-out) 1.0s forwards; }
.kis-div-line.r{ background:linear-gradient(90deg,rgba(143,190,196,.55),transparent); }
.kis-div-dot{ width:5px; height:5px; border-radius:50%; background:#5FB6C4; box-shadow:0 0 10px rgba(95,182,196,.85); flex-shrink:0; }

.kis-wordmark{ width:clamp(228px,36vw,384px); height:auto; display:block;
  filter:drop-shadow(0 14px 32px rgba(0,0,0,.48));
  clip-path:inset(0 100% 0 0); opacity:0; animation:kisWipe 1.0s var(--e-out) 1.15s forwards; }
.kis-tag{ font-family:'Inter',sans-serif; font-weight:500; text-transform:uppercase;
  font-size:clamp(9.5px,1vw,12px); letter-spacing:.34em; padding-left:.34em; color:#7FA9B2;
  margin-top:clamp(16px,2vw,24px); opacity:0; text-align:center; animation:kisFade .8s var(--e-out) 1.8s forwards; }

.kis-loader{ margin-top:clamp(30px,5vh,52px); width:var(--bar); opacity:0; animation:kisFade .8s var(--e-out) 2.0s forwards; }
#boot.boot-hide .kis-loader{ animation:none; opacity:0; transition:opacity .35s ease; }
.kis-load-row{ display:flex; justify-content:space-between; align-items:baseline; gap:12px; margin-bottom:11px;
  font-family:'Inter',sans-serif; font-size:clamp(9px,.95vw,10.5px); letter-spacing:.1em; text-transform:uppercase; }
.kis-load-label{ color:#6F95A0; font-weight:500; white-space:nowrap; }
.kis-load-pct{ color:#9BD8E1; font-weight:600; font-variant-numeric:tabular-nums; letter-spacing:.04em; }
.kis-track{ position:relative; height:2px; border-radius:999px; background:rgba(255,255,255,.09); }
.kis-fill{ position:absolute; left:0; top:0; height:100%; width:0; border-radius:999px;
  background:linear-gradient(90deg,#2E6E7E,#9BD8E1); transition:width .14s linear; }
.kis-fill-dot{ position:absolute; top:50%; left:0; width:7px; height:7px; border-radius:50%;
  transform:translate(-50%,-50%); background:#CDEEF3; box-shadow:0 0 12px rgba(155,216,225,.9); transition:left .14s linear; }
.kis-edge{ position:fixed; left:0; bottom:0; height:2px; width:0; opacity:.7;
  background:linear-gradient(90deg,transparent,#5FB6C4 16%,#9BD8E1 84%,transparent); transition:width .14s linear; }
#boot.boot-hide .kis-edge{ opacity:0; transition:opacity .35s ease; }

@keyframes kisGlow{ to{ opacity:1; } }
@keyframes kisSheen{ 0%{ left:-50%; } 55%,100%{ left:130%; } }
@keyframes kisHalo{ 60%{ opacity:1; } 100%{ transform:translate(-50%,-50%) scale(1); opacity:.7; } }
@keyframes kisCrest{ 100%{ transform:scale(1); opacity:1; } }
@keyframes kisFade{ to{ opacity:1; } }
@keyframes kisLine{ to{ width:46px; } }
@keyframes kisWipe{ 0%{ clip-path:inset(0 100% 0 0); opacity:1; } 100%{ clip-path:inset(0 0 0 0); opacity:1; } }
@media(prefers-reduced-motion:reduce){
  .kis-bg-glow{ animation:none; opacity:1; } .kis-bg-sheen{ animation:none; }
  .kis-crest-halo{ animation:none; opacity:.7; transform:translate(-50%,-50%) scale(1); }
  .kis-crest,.kis-crest-ring,.kis-div,.kis-tag,.kis-loader{ animation:none; opacity:1; }
  .kis-crest{ transform:none; }
  .kis-div-line{ width:46px; animation:none; }
  .kis-wordmark{ animation:none; clip-path:none; opacity:1; }
  #boot.boot-hide .kis-stage{ transform:none; filter:none; }
}

/* Mobile topbar — fewer nav items would be ideal, but until we ship a hamburger
   we make the nav itself horizontally scrollable so it never overlaps the brand. */
@media (max-width: 720px) {
  .topbar {
    /* 17 May 2026: this rule previously set `padding: 10px 14px`, a
       shorthand that CLOBBERED the base rule's env(safe-area-inset-top)
       on every phone — so the nav sat under the iOS status bar in the
       installed PWA (the bug "fixed" twice on the base rule but never
       here). Keep the tighter mobile spacing but re-apply the insets:
       top clears the status bar, left/right clear the Dynamic Island /
       rounded corners in landscape. Do NOT collapse this back to a
       plain `padding` shorthand. */
    padding:
      calc(10px + env(safe-area-inset-top))
      max(14px, env(safe-area-inset-right))
      10px
      max(14px, env(safe-area-inset-left));
    gap: 10px;
    flex-wrap: nowrap;
    overflow: hidden;
  }
  .brand { gap: 10px; flex-shrink: 0; }
  .brand-name { font-size: 16px; letter-spacing: -0.015em; }
  .brand-mark { width: 34px; height: 34px; }
  .nav {
    flex: 1 1 auto; min-width: 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 14px;
    padding: 4px 0;
    white-space: nowrap;
    /* 17 May 2026: was `flex-end`. With overflow-x scroll + ~10 nav
       items, flex-end anchored the scroll to the END, so every full
       page load (every nav tap) showed "All clubs / Sign out" and hid
       Dashboard/Checkout/… off the left. Start-aligned so the area
       links are what you see; base.html scrolls the active one into
       view. Do NOT set this back to flex-end. */
    justify-content: flex-start;
  }
  .nav::-webkit-scrollbar { display: none; }
  .nav a { flex-shrink: 0; font-size: 13px; }
}

/* ---- container ----
   5 May 2026: bumped max-width from 1100px to 1320px so the dashboard
   uses more of a typical laptop screen. Wider works for an operational
   tool — KPIs, tables, charts all benefit from breathing room. Stripe
   sits at 1280px, Linear at 1280px, this lands slightly wider. */
.container { max-width: 1320px; margin: 0 auto; padding: 24px 28px 60px; }
@media (max-width: 640px) { .container { padding: 16px 14px 40px; } }

/* ---- typography ---- */
/* Headlines deliberately oversized + light weight to make space breathe.
   Letter-spacing tightens slightly at every size up. */
h1 { font-size: 40px; margin: 0 0 8px; font-weight: 500; letter-spacing: -0.03em; line-height: 1.1; color: var(--navy); }
h2 { font-size: 22px; margin: 26px 0 12px; font-weight: 500; color: var(--ink); letter-spacing: -0.015em; line-height: 1.25; }

/* Kit Intelligence display face (Geist) — greetings + big stat numbers only,
   so the numerals read confident while body/labels stay Inter. */
h1,
.kpi-value,
.ki-forecast-num,
.ki-score-num,
.pkc-usage-value { font-family: var(--display); letter-spacing: -0.02em; }
h3 { font-size: 16px; margin: 18px 0 8px; font-weight: 600; color: var(--ink); letter-spacing: -0.005em; }
.subtitle { color: var(--muted); margin: 0 0 24px; font-size: 15px; line-height: 1.5; }
.tabular { font-variant-numeric: tabular-nums; }
@media (max-width: 640px) {
  h1 { font-size: 30px; }
  h2 { font-size: 19px; }
}

/* Editorial eyebrow — broadsheet-style label above section headings.
   Small, uppercase, gold, tracked. Tells the eye where sections begin. */
.eyebrow {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: var(--gold-2);
  text-transform: uppercase;
  letter-spacing: 1.4px;
  margin: 0 0 6px;
}

/* Hairline divider — quiet grey rule between major page sections.
   5 May 2026: was a gold-gradient. Reduced gold to focus rings + CTA
   highlights only — divider doesn't earn the brand colour. */
.divider-gold {
  height: 1px;
  background: var(--border);
  margin: 28px 0;
  border: 0;
}

/* Toast notifications — top-right, slide+fade, no layout shift. */
.toast-stack {
  position: fixed;
  /* 18 May 2026: the checkout/success toast was rendering under the iOS
     status bar on the phone PWA. Clear the safe area (env() = 0 on
     desktop, so no change there). */
  top: calc(16px + env(safe-area-inset-top));
  right: max(16px, env(safe-area-inset-right));
  display: flex; flex-direction: column;
  gap: 8px;
  z-index: 1000;
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  min-width: 280px; max-width: 420px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--ok);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(11,34,64,0.10), 0 2px 6px rgba(11,34,64,0.06);
  padding: 12px 16px;
  font-size: 14px;
  color: var(--ink);
  animation: toast-in 0.22s cubic-bezier(0.2, 0.7, 0.3, 1);
  transition: opacity 0.18s, transform 0.18s;
}
.toast.toast-out { opacity: 0; transform: translateX(8px); }
.toast-error { border-left-color: var(--bad); }
.toast-warn { border-left-color: var(--warn); }
.toast-title { font-weight: 600; margin-bottom: 2px; }
.toast-sub { font-size: 12px; color: var(--muted); }
@keyframes toast-in {
  from { opacity: 0; transform: translateX(20px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* Page-load fade — subtle but premium. Applied to .container by default. */
@keyframes page-rise {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
main.container > * { animation: page-rise 0.28s ease both; }
main.container > *:nth-child(1) { animation-delay: 0ms; }
main.container > *:nth-child(2) { animation-delay: 30ms; }
main.container > *:nth-child(3) { animation-delay: 60ms; }
main.container > *:nth-child(4) { animation-delay: 90ms; }
main.container > *:nth-child(n+5) { animation-delay: 120ms; }
@media (prefers-reduced-motion: reduce) {
  main.container > * { animation: none; }
  .toast { animation: none; }
}

/* Cmd+K command palette */
.cmdk-overlay {
  position: fixed; inset: 0;
  background: rgba(11,34,64,0.45);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 999;
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: 12vh;
  animation: cmdk-fade 0.15s ease;
}
@keyframes cmdk-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.cmdk {
  width: 100%; max-width: 600px;
  background: var(--surface);
  border-radius: 14px;
  box-shadow: 0 24px 64px rgba(11,34,64,0.20), 0 4px 12px rgba(11,34,64,0.08);
  overflow: hidden;
  animation: cmdk-pop 0.18s cubic-bezier(0.2,0.7,0.3,1.1);
}
@keyframes cmdk-pop {
  from { opacity: 0; transform: translateY(-8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.cmdk-input-wrap {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
}
.cmdk-input-wrap svg { flex-shrink: 0; color: var(--muted); }
.cmdk-input {
  flex: 1; border: 0; outline: 0;
  font-family: inherit; font-size: 16px;
  color: var(--ink); background: transparent;
}
.cmdk-input::placeholder { color: var(--muted); }
.cmdk-results { max-height: 50vh; overflow-y: auto; padding: 6px 0; }
.cmdk-section-label {
  font-size: 10px; font-weight: 600;
  color: var(--muted); text-transform: uppercase; letter-spacing: 1px;
  padding: 10px 18px 4px;
}
.cmdk-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 18px;
  cursor: pointer;
  font-size: 14px;
  color: var(--ink);
}
.cmdk-item:hover, .cmdk-item.active {
  background: var(--bg);
}
.cmdk-item.active { color: var(--navy); }
.cmdk-item-meta {
  margin-left: auto;
  font-size: 11px; color: var(--muted);
}
.cmdk-empty { padding: 30px 18px; text-align: center; color: var(--muted); font-size: 13px; }
.cmdk-hint {
  display: flex; gap: 14px; justify-content: flex-end;
  padding: 8px 18px;
  border-top: 1px solid var(--border);
  background: #fafbfc;
  font-size: 11px; color: var(--muted);
}
.cmdk-kbd {
  display: inline-block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  font-family: inherit; font-size: 10px;
  color: var(--ink-2);
}
.cmdk-trigger-hint {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 4px 9px;
  font-size: 11px; color: var(--muted); cursor: pointer;
  transition: border-color 0.12s, color 0.12s;
}
.cmdk-trigger-hint:hover { border-color: var(--muted); color: var(--ink-2); }

/* Personalised greeting — a display-only "Hi, <name>" in the topbar, present
   on every page for each individual. Sits between ⌘K and Sign out. (The
   self-serve "Greet me as" nickname editor was removed 08 Jul 2026.) */
.acct-greeting {
  display: inline-flex; align-items: center;
  font-size: 12px; color: var(--ink-2); white-space: nowrap;
}
.acct-hi { color: var(--muted); }
.acct-name { font-weight: 600; max-width: 160px; overflow: hidden; text-overflow: ellipsis; }

/* View-scope dropdown — cross-club admin only, in the topbar. Visible after
   the nav links, before the ⌘K hint. Matches the light topbar: surface fill,
   ink text, accent ring on focus. */
.view-scope-form {
  display: inline-flex;
  margin: 0;
}
.view-scope-select {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 4px 28px 4px 10px;
  font-size: 12px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  letter-spacing: 0.2px;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'><path fill='%236B7280' d='M2 4l4 4 4-4z'/></svg>");
  background-repeat: no-repeat;
  background-position: right 8px center;
  background-size: 10px 10px;
}
.view-scope-select:hover {
  background-color: var(--line-2);
  border-color: var(--muted);
}
.view-scope-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.view-scope-select option {
  background: var(--surface);
  color: var(--ink);
}
@media (max-width: 720px) {
  .view-scope-select { font-size: 11px; padding: 3px 22px 3px 8px; }
}
@media (max-width: 640px) {
  .cmdk-trigger-hint { display: none; }
}

/* ===== AI Assistant chat =====
   5 May 2026: quietened. Was 56px with a perpetual gold pulse halo —
   pulled focus from page content. Now 44px, navy with a thin gold border,
   no continuous animation. Available, not insistent. */
.ai-fab {
  position: fixed;
  bottom: 24px; right: 24px;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(201,165,90,0.35);
  background: var(--navy);
  color: var(--gold);
  box-shadow: 0 4px 12px rgba(11,34,64,0.16),
              inset 0 1px 0 rgba(255,255,255,0.06);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  z-index: 100;
  transition: transform 0.18s ease, box-shadow 0.2s;
}
.ai-fab:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(11,34,64,0.22),
              inset 0 1px 0 rgba(255,255,255,0.10);
}
.ai-fab:active { transform: translateY(0); }
.ai-fab svg { width: 18px; height: 18px; }
/* The club badge on the assistant button and panel. White chip for the same
   reason .ki-area-crest has one: a colour crest inverted goes wrong (Bolton's
   red turns cyan) and a dark crest dropped on a dark surface disappears. */
.ai-fab-crest {
  width: 30px; height: 30px; border-radius: 50%;
  object-fit: contain; background: #fff; padding: 3px; box-sizing: border-box;
}
.ai-header-crest {
  width: 100%; height: 100%; border-radius: 7px;
  object-fit: contain; background: #fff; padding: 2px; box-sizing: border-box;
}
.ai-fab-pulse {
  /* Retained as DOM element so the existing markup doesn't break, but
     visually disabled — no continuous animation. */
  display: none;
}

.ai-panel {
  position: fixed;
  bottom: 24px; right: 24px;
  width: 420px; max-width: calc(100vw - 32px);
  height: 640px; max-height: calc(100vh - 48px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 24px 64px rgba(11,34,64,0.22), 0 8px 16px rgba(11,34,64,0.10);
  display: flex; flex-direction: column;
  z-index: 101;
  overflow: hidden;
  transform: translateY(8px) scale(0.98);
  opacity: 0;
  transition: transform 0.22s cubic-bezier(0.2,0.7,0.3,1.1), opacity 0.18s;
  pointer-events: none;
}
.ai-panel.open { transform: translateY(0) scale(1); opacity: 1; pointer-events: auto; }
@media (max-width: 540px) {
  .ai-panel { bottom: 0; right: 0; width: 100vw; height: 100dvh; max-height: 100dvh; border-radius: 0; }
}

.ai-header {
  display: flex; align-items: center; gap: 10px;
  /* 18 May 2026: full-screen on mobile (≤540px) the panel sits at top:0,
     so under the iOS black-translucent status bar the header — and the
     close ✕ — were hidden behind the time/Dynamic Island and untappable
     (user got trapped in the chatbot). Clear the safe area; env() is 0
     on desktop / non-PWA so the floating card is unaffected. */
  padding: calc(14px + env(safe-area-inset-top))
           max(18px, env(safe-area-inset-right))
           14px
           max(18px, env(safe-area-inset-left));
  border-bottom: 1px solid var(--border);
  /* 18 Aug 2026: this was a hardcoded white gradient, so on the dark surface
     the panel wore a bright white cap that belonged to no theme. Use the
     surface token and let the border do the separating. */
  background: var(--surface);
}
.ai-header-mark {
  width: 26px; height: 26px;
  border-radius: 8px;
  background: var(--track);
  border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-2);
  flex-shrink: 0;
}
.ai-header-text { flex: 1; min-width: 0; }
.ai-header-title { font-size: 14px; font-weight: 600; color: var(--ink); }
.ai-header-sub { font-size: 11px; color: var(--muted); }
.ai-header-close {
  background: transparent; border: 0; color: var(--muted);
  cursor: pointer; padding: 6px; border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
}
.ai-header-close:hover { background: var(--bg); color: var(--ink); }

.ai-thread {
  flex: 1;
  overflow-y: auto;
  padding: 16px 18px 8px;
  display: flex; flex-direction: column;
  gap: 14px;
}
.ai-msg { display: flex; gap: 10px; }
.ai-msg-user { justify-content: flex-end; }
.ai-msg-bubble {
  max-width: 88%;
  padding: 10px 14px;
  border-radius: 12px;
  font-size: 14px; line-height: 1.55;
  white-space: pre-wrap;
  word-wrap: break-word;
}
.ai-msg-user .ai-msg-bubble {
  background: var(--navy);
  color: white;
  border-bottom-right-radius: 4px;
}
.ai-msg-assistant .ai-msg-bubble {
  background: var(--bg);
  color: var(--ink);
  border-bottom-left-radius: 4px;
}
.ai-msg-bubble strong { font-weight: 600; }
.ai-msg-bubble code { font-family: Menlo, monospace; font-size: 12px; background: var(--track); padding: 1px 5px; border-radius: 3px; }
/* Assistant tables. Every cell used to carry a 1px border, which drew a
   spreadsheet grid inside a chat bubble — the one table in the product that
   looked nothing like the others. Same treatment as the Items and ledger
   tables now: no vertical rules, a heavier line under a tracked uppercase
   header, hairline row rules, numbers right-aligned in tabular figures.
   The wrapper scrolls, because Albert will happily answer with six columns
   inside a 380px panel. */
.ai-tablewrap {
  margin: 10px 0 12px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.ai-msg-bubble table {
  border-collapse: collapse;
  width: 100%;
  min-width: max-content;
  font-size: 13px;
}
.ai-msg-bubble th, .ai-msg-bubble td {
  padding: 7px 18px 7px 0;
  text-align: left;
  border: 0;
  white-space: nowrap;
}
.ai-msg-bubble th {
  background: none;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--edge-2, var(--border));
  padding-bottom: 6px;
}
.ai-msg-bubble tbody tr + tr td { border-top: 1px solid var(--line-2, var(--border)); }
.ai-msg-bubble td { color: var(--ink); }
/* Right-align only — do NOT zero the right padding here. Doing that ran
   adjacent numeric columns together: the header read "ON HANDMINCOVER" and
   the row read "2 15 4d" as one number. Gutters come from the shared rule
   above; only the final column gives its gutter back. */
.ai-msg-bubble th.num, .ai-msg-bubble td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.ai-msg-bubble th:last-child, .ai-msg-bubble td:last-child { padding-right: 0; }
.ai-msg-bubble ul, .ai-msg-bubble ol { margin: 6px 0; padding-left: 20px; }
.ai-msg-bubble p { margin: 6px 0; }
.ai-msg-bubble p:first-child { margin-top: 0; }
.ai-msg-bubble p:last-child { margin-bottom: 0; }

.ai-followups {
  display: flex; flex-direction: column; gap: 6px;
  margin-top: 8px;
  align-self: flex-start;
  max-width: 88%;
}
.ai-followup {
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 8px 14px;
  font-size: 13px; color: var(--ink-2);
  cursor: pointer;
  font-family: inherit;
  transition: background 0.12s, border-color 0.12s, color 0.12s, transform 0.06s;
  display: inline-flex; align-items: center; gap: 6px;
  width: fit-content;
  animation: ai-followup-in 0.28s cubic-bezier(0.2,0.7,0.3,1.1) both;
}
.ai-followup:hover {
  background: var(--bg);
  border-color: var(--gold-2);
  color: var(--navy);
}
.ai-followup:active { transform: translateY(1px); }
.ai-followup::before {
  content: "↳"; color: var(--gold-2); font-size: 12px; opacity: 0.7;
}
@keyframes ai-followup-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) { .ai-followup { animation: none; } }

.ai-tools-trail {
  font-size: 11px; color: var(--muted);
  margin-top: 4px; padding-left: 4px;
  display: flex; gap: 4px; flex-wrap: wrap;
}
.ai-tool-chip {
  background: rgba(201,165,90,0.14);
  color: var(--gold-2);
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10px; font-weight: 600;
  letter-spacing: 0.3px;
}

.ai-typing {
  display: flex; gap: 4px;
  padding: 12px 14px;
  background: var(--bg);
  border-radius: 12px;
  border-bottom-left-radius: 4px;
  align-self: flex-start;
}
.ai-typing span {
  width: 6px; height: 6px;
  background: var(--muted);
  border-radius: 50%;
  animation: ai-typing 1.2s ease-in-out infinite;
}
.ai-typing span:nth-child(2) { animation-delay: 0.15s; }
.ai-typing span:nth-child(3) { animation-delay: 0.30s; }
@keyframes ai-typing {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}

.ai-suggestions {
  margin-top: 2px;
  display: flex; flex-direction: column;
  gap: 6px;
  padding: 18px;
}
.ai-suggestions-title {
  font-size: 11px; font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: 1.2px;
  margin-bottom: 4px;
}
.ai-suggestion {
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  font-size: 13px; color: var(--ink);
  cursor: pointer;
  font-family: inherit;
  transition: background 0.12s, border-color 0.12s, transform 0.06s;
}
.ai-suggestion:hover {
  background: var(--bg);
  border-color: var(--gold-2);
}
.ai-suggestion:active { transform: translateY(1px); }

/* Top-aligned, not vertically centred. `flex: 1` + `justify-content:center`
   floated one sentence in the middle of a 640px panel and pushed the
   suggestions — the only thing anyone actually clicks — to the bottom edge,
   with a void above and below. */
.ai-empty {
  flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: flex-start;
  text-align: left;
  padding: 4px 0 2px;
  color: var(--muted);
}
/* The 56px gold-on-navy medallion is gone (18 Aug 2026). A large circled
   sparkle above a heading is the house style of every chatbot on the
   internet, and it pushed the actual content — the suggestions people
   click — below the fold of a 640px panel. */
.ai-empty-mark { display: none; }
/* The header already names the panel. A second heading two lines below it
   read as a duplicate rather than a welcome, so the title is gone and the
   one useful sentence carries it. */
.ai-empty-title { display: none; }
.ai-empty-sub { font-size: 13px; color: var(--ink-2); margin: 0 0 4px; line-height: 1.5; }

.ai-input-wrap {
  border-top: 1px solid var(--border);
  padding: 12px 14px;
  background: var(--surface);
}
.ai-input-row {
  display: flex; align-items: flex-end;
  gap: 8px;
  background: var(--track);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 8px 8px 8px 12px;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.ai-input-row:focus-within {
  border-color: var(--gold-2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 22%, transparent);
}
.ai-input {
  flex: 1; min-width: 0;
  border: 0; outline: 0;
  resize: none;
  background: transparent;
  font-family: inherit; font-size: 14px;
  color: var(--ink); line-height: 1.5;
  padding: 4px 0;
  max-height: 120px;
}
.ai-input::placeholder { color: var(--muted); }
.ai-send {
  flex-shrink: 0;
  width: 32px; height: 32px;
  border: 0; border-radius: 8px;
  /* Was #d3b06b blended into var(--gold) — a hardcoded GOLD mixed with the
     club's own accent. Correct-looking only for the founding tenant, whose
     accent is gold; a smear for a club whose accent is red. */
  background: var(--gold);
  color: var(--on-gold, var(--navy));
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.30);
  transition: filter 0.15s, transform 0.06s;
}
.ai-send:hover:not(:disabled) { filter: brightness(1.06); }
.ai-send:active:not(:disabled) { transform: translateY(1px); }
.ai-send:disabled {
  background: var(--border); color: var(--muted);
  cursor: not-allowed; box-shadow: none;
}

/* Voice input mic — 21 May 2026. Same shape as ai-send, neutral tone
   until tapped. Active state pulses red so the kitman can see they're
   recording even mid-conversation. */
.ai-mic {
  background: var(--bg);
  color: var(--ink);
  border: 1px solid var(--border);
  box-shadow: none;
}
.ai-mic:hover { filter: brightness(0.96); }
.ai-mic-active {
  background: linear-gradient(180deg, #e0807a 0%, #c84539 100%);
  color: #fff;
  border-color: transparent;
  animation: ai-mic-pulse 1.2s ease-in-out infinite;
}
@keyframes ai-mic-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(200,69,57,0.50); }
  50%      { box-shadow: 0 0 0 6px rgba(200,69,57,0.00); }
}

.ai-input-hint kbd {
  display: inline-block;
  padding: 1px 5px;
  font: 10px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--bg);
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: 3px;
  color: var(--ink-2);
}

.ai-input-hint {
  font-size: 10px; color: var(--muted);
  margin-top: 6px; text-align: center;
}

/* ----- Skeleton loading shimmer ----- */
.skeleton {
  background: linear-gradient(90deg,
    rgba(11,34,64,0.05) 0%,
    rgba(11,34,64,0.10) 50%,
    rgba(11,34,64,0.05) 100%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
  border-radius: 4px;
  color: transparent;
}
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 18px;
}
.skeleton-row .skeleton-line {
  height: 10px; border-radius: 4px;
  background: linear-gradient(90deg,
    rgba(11,34,64,0.06) 0%,
    rgba(11,34,64,0.12) 50%,
    rgba(11,34,64,0.06) 100%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
}
.skeleton-line.lg { width: 60%; }
.skeleton-line.sm { width: 40%; height: 8px; opacity: 0.7; }
@media (prefers-reduced-motion: reduce) {
  .skeleton, .skeleton-row .skeleton-line { animation: none; }
}

/* ----- Sticky compacting page header (.dash-head only) ----- */
.dash-head {
  position: sticky;
  top: 68px; /* topbar height — sits flush below it */
  z-index: 5;
  background: var(--bg);
  margin: 0 -22px;
  padding: 0 22px 22px;
  transition: padding 0.18s ease, box-shadow 0.18s ease;
}
@media (max-width: 720px) { .dash-head { top: 54px; } }
.dash-head.is-stuck {
  padding-top: 14px;
  padding-bottom: 14px;
  margin-bottom: 16px;
  box-shadow: 0 4px 12px -4px rgba(11,34,64,0.08);
  border-bottom: 1px solid var(--border);
}
.dash-head.is-stuck h1 {
  font-size: 22px !important;
  margin: 0 !important;
  transition: font-size 0.18s ease, margin 0.18s ease;
}
.dash-head.is-stuck .eyebrow,
.dash-head.is-stuck .subtitle { display: none; }
@media (max-width: 640px) {
  .dash-head { margin: 0 -14px; padding: 0 14px 16px; }
  .dash-head.is-stuck h1 { font-size: 18px !important; }
}

/* ---- card / surface ----
   Three variants:
     .card         — default, subtle shadow, the workhorse
     .card-primary — hero card with gold top accent + stronger shadow
     .card-flat    — no shadow, used inside another card or for sub-content
*/
/* Checkout cards — were inline padding:36px 40px / 28px 32px, which ate
   ~80px of a 375px phone's width and forced the recent-checkouts table to
   overflow. Moved to a class so mobile can shrink it. (13 May 2026) */
.checkout-card { padding: 32px 36px; }
/* 13 June 2026: was a hard `1fr 1fr`. On a zoomed-in or small viewport the
   two pickers were pushed off the right edge with no horizontal scrollbar
   (the global overflow-x:hidden), leaving Step 2 unreachable. auto-fit lets
   the columns collapse to one row each when there isn't room. */
.checkout-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 36px;
}
/* Let a wide table scroll inside its own box rather than overflow the page
   (which the global overflow-x:hidden would silently clip). */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
@media (max-width: 640px) {
  .checkout-card { padding: 20px 16px; }
  /* Item search | Player search side-by-side is too cramped on a phone —
     stack them so each gets full width. */
  .checkout-grid { grid-template-columns: 1fr; gap: 20px; }
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px;
  margin-bottom: 18px;
  position: relative;
}
.card-primary {
  box-shadow: 0 1px 2px rgba(11,34,64,0.05),
              0 8px 16px rgba(11,34,64,0.06),
              0 24px 48px rgba(11,34,64,0.04);
  border: 1px solid var(--border);
  overflow: hidden;
}
.card-primary::before {
  content: ""; position: absolute;
  top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(90deg, var(--gold) 0%, var(--gold-2) 50%, var(--gold) 100%);
  opacity: 0.85;
}
.card-flat {
  background: var(--bg);
  border: 1px solid var(--border);
  box-shadow: none;
  padding: 14px 16px;
}
.card-section + .card-section { border-top: 1px solid var(--border); margin-top: 18px; padding-top: 18px; }

/* ---- KPI grid ---- */
.kpi-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  margin-bottom: 18px;
}
.kpi {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px 16px;
  box-shadow: var(--shadow);
}
.kpi-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.kpi-value { font-size: 22px; font-weight: 700; color: var(--ink); margin-top: 4px; }
.kpi-sub { font-size: 12px; color: var(--ink-2); margin-top: 2px; }

/* ---- table ---- */
table { width: 100%; border-collapse: collapse; }
th, td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--border); font-size: 14px; }
td { font-variant-numeric: tabular-nums; }
th { font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.6px; background: #fafbfc; }
tr:last-child td { border-bottom: none; }
tbody tr { transition: background 0.12s; }
tbody tr:hover { background: #fafbfc; }

/* ---- form ---- */
.form-row { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; min-width: 0; }
.form-row label { font-size: 13px; color: var(--ink-2); font-weight: 500; }
.form-row input:not([type=checkbox]):not([type=radio]),
.form-row select, .form-row textarea {
  width: 100%;
}
.form-row input, .form-row select, .form-row textarea {
  padding: 10px 12px; font-size: 15px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: white; color: var(--ink);
  font-family: inherit;
}
.form-row input:focus, .form-row select:focus, .form-row textarea:focus {
  outline: none; border-color: var(--navy-2); box-shadow: 0 0 0 3px rgba(20, 49, 90, 0.12);
}

/* ---- buttons ----
   Subtle vertical gradient + inset highlight + crisp shadow = tactile, premium.
   Same trick Linear/Stripe/Apple use. Visible at every CTA. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 10px 18px;
  font-family: inherit;
  font-size: 14px; font-weight: 600;
  letter-spacing: -0.005em;
  border: none; border-radius: var(--radius-sm);
  background: linear-gradient(180deg, var(--navy-2) 0%, var(--navy) 100%);
  color: var(--on-navy, #fff);
  cursor: pointer; text-decoration: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 1px 2px rgba(11,34,64,0.10);
  transition: transform 0.06s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
.btn:hover {
  text-decoration: none;
  filter: brightness(1.06);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22), 0 2px 4px rgba(11,34,64,0.14);
}
.btn:active { transform: translateY(1px); box-shadow: inset 0 1px 2px rgba(0,0,0,0.10); }
.btn:focus-visible { outline: none; box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 0 0 3px rgba(20,49,90,0.25); }
.btn[disabled], .btn:disabled {
  opacity: 0.55; cursor: not-allowed; filter: none; transform: none;
}

.btn-secondary {
  background: linear-gradient(180deg, #ffffff 0%, #f5f7fa 100%);
  color: var(--ink); border: 1px solid var(--border);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.6), 0 1px 2px rgba(11,34,64,0.04);
}
.btn-secondary:hover {
  filter: none;
  background: linear-gradient(180deg, #ffffff 0%, #eef1f6 100%);
}

.btn-gold {
  /* Was #d3b06b blended into var(--gold) — a hardcoded GOLD mixed with the
     club's own accent. Correct-looking only for the founding tenant, whose
     accent is gold; a smear for a club whose accent is red. */
  background: var(--gold);
  color: var(--on-gold, var(--navy));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.30), 0 1px 2px rgba(120,85,15,0.18);
}
.btn-gold:hover { filter: brightness(1.05); }

.btn-danger {
  background: linear-gradient(180deg, #c93535 0%, var(--bad) 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 1px 2px rgba(120,30,30,0.18);
}

.btn-block { width: 100%; }
.btn-lg { padding: 14px 22px; font-size: 16px; }
.btn-sm { padding: 6px 12px; font-size: 13px; font-weight: 500; }

/* ---- chips, status, flash ---- */
.chip { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.chip-ok { background: #e6f3ec; color: var(--ok); }
.chip-warn { background: #fbf1e0; color: var(--warn); }
.chip-bad { background: #fbe3e3; color: var(--bad); }
.chip-cat { background: #eef2f8; color: var(--navy-2); }
/* Night Auditor severities (owner findings page) */
.chip-critical { background: #fbe3e3; color: var(--bad); }
.chip-info { background: #eef2f8; color: var(--muted); }

/* Owner "view as this club" preview banner — fixed Kit Intelligence teal so it
   reads as owner mode, distinct from whatever the tenant's brand colour is. */
.viewas-banner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  background: #164353; color: #eaf3f4; border-radius: 10px;
  padding: 10px 16px; margin-bottom: 16px; font-size: 13.5px;
}
.viewas-banner strong { color: #fff; }
.viewas-banner a { color: #8ecad6; font-weight: 600; text-decoration: none; white-space: nowrap; }
.viewas-banner a:hover { text-decoration: underline; }

.flash {
  padding: 10px 14px; border-radius: var(--radius-sm); margin-bottom: 14px;
  font-size: 14px;
}
.flash-ok { background: #e6f3ec; color: var(--ok); border: 1px solid #c5e0d1; }
.flash-error { background: #fbe3e3; color: var(--bad); border: 1px solid #f3c0c0; }

/* ---- footer (compact structured footer) ---- */
.footer {
  margin-top: 32px;
  padding: 22px 22px 18px;
  border-top: 1px solid var(--border);
  background: var(--surface);
  position: relative;
  font-size: 13px;
  color: var(--ink-2);
}
.footer::before {
  content: ""; position: absolute;
  top: -1px; left: 22px; right: 22px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(201,165,90,0.4) 30%, rgba(201,165,90,0.4) 70%, transparent);
}
.footer-inner {
  max-width: 1320px; margin: 0 auto;
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 28px;
}
@media (max-width: 720px) {
  .footer-inner { grid-template-columns: 1fr 1fr; gap: 18px; }
  .footer-brand { grid-column: 1 / -1; }
}
.footer-brand {
  display: flex; align-items: center; gap: 12px;
}
.footer-brand img { width: 28px; height: 28px; flex-shrink: 0; }
/* The tenant's crest sits beside the Kit Intelligence lockup as a subtle
   "built for" mark — slightly de-weighted so it doesn't compete with
   the product brand. Specificity beats the generic 28×28 above. */
.footer-brand img.footer-crest { width: auto; height: 30px; opacity: 0.8; }
.footer-brand-name {
  font-size: 14px; font-weight: 600;
  color: var(--navy); letter-spacing: -0.015em;
  line-height: 1.2;
}
.footer-brand-name .brand-accent { color: var(--gold-2); font-weight: 500; }
.footer-brand-tag {
  font-size: 11px; color: var(--muted);
  line-height: 1.4; margin-top: 2px;
}
.footer-col-title {
  font-size: 10px; font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: 1.2px;
  margin-bottom: 8px;
}
.footer-col ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 5px; }
.footer-col a { color: var(--ink-2); font-size: 12px; }
.footer-col a:hover { color: var(--navy); text-decoration: none; }
.footer-status {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(47,122,77,0.08);
  color: var(--ok);
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11px; font-weight: 600;
  letter-spacing: 0.3px;
}
.footer-status::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--ok); box-shadow: 0 0 0 2px rgba(47,122,77,0.18);
}
.footer-meta {
  margin-top: 16px; padding-top: 12px;
  border-top: 1px solid var(--border);
  font-size: 11px; color: var(--muted);
  max-width: 1320px; margin-left: auto; margin-right: auto;
  text-align: center;
}

/* ===== Dashboard ===== */

.dash-head {
  display: flex; justify-content: space-between; align-items: flex-end;
  margin: 4px 0 22px;
}
.dash-head h1 { font-size: 42px; }
.period-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px; border-radius: 999px;
  background: white; border: 0.5px solid var(--border);
  font-size: 12px; font-weight: 500; color: var(--ink-2);
  letter-spacing: 0.3px;
}
.period-pill::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--ok); box-shadow: 0 0 0 2px rgba(47,122,77,0.18);
}

/* KPI row */
.kpi-row {
  display: grid; gap: 14px;
  grid-template-columns: repeat(4, 1fr);
  margin-bottom: 22px;
}
@media (max-width: 720px) { .kpi-row { grid-template-columns: 1fr 1fr; } }
.kpi-card {
  background: white; border: 0.5px solid var(--border);
  border-radius: 14px; padding: 16px 18px;
  position: relative;
}
.kpi-card .kpi-label {
  font-size: 11px; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.8px;
  font-weight: 500;
}
.kpi-row-inner {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 10px; margin-top: 6px;
}
.kpi-card .kpi-value {
  font-size: 44px; font-weight: 500;
  color: var(--navy); line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.kpi-spark { opacity: 0.85; }
.kpi-meta {
  margin-top: 10px;
  display: flex; align-items: center; gap: 8px;
  font-size: 12px;
}
.kpi-meta-sep { color: var(--border); }
.kpi-meta-text { color: var(--muted); }

/* Card heading and chart frame */
.card-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 12px; margin-bottom: 14px;
  /* 13 May 2026: on a narrow phone the left title block (h2 + sub) used to
     push the right-hand action link ("Movement log →") off the card's
     padded area, clipping it to "Mov →". flex-wrap lets the link drop to
     its own line instead of being cut; min-width:0 lets the left block
     shrink rather than force-overflow. */
  flex-wrap: wrap;
}
.card-head > :first-child { min-width: 0; }
.card-head .link-arrow,
.card-head .link-action { flex-shrink: 0; white-space: nowrap; }
.card-head h2 { font-size: 16px; }
.card-sub { font-size: 12px; color: var(--muted); margin: 3px 0 0; }
.chart-card { padding: 18px 20px 14px; }
.chart-frame { margin: 6px -4px 0; }

.legend {
  display: flex; align-items: center; font-size: 12px; color: var(--ink-2);
  font-weight: 500; letter-spacing: 0.2px;
}
.legend .dot {
  width: 10px; height: 10px; border-radius: 50%;
  display: inline-block; margin-right: 6px;
}
.legend .pip-mark {
  width: 2px; height: 12px; background: var(--navy);
  border-radius: 1px; display: inline-block; margin-right: 6px;
  vertical-align: middle;
}

/* Two-column rows */
.row-2 {
  display: grid; gap: 14px; grid-template-columns: 1fr 1fr;
  margin-bottom: 14px;
}
@media (max-width: 720px) { .row-2 { grid-template-columns: 1fr; } }

/* Donut */
.donut-wrap { display: flex; gap: 18px; align-items: center; }
.donut { flex: 0 0 200px; }
.legend-list { flex: 1; min-width: 0; }
@media (max-width: 540px) { .donut-wrap { flex-direction: column; align-items: stretch; } .donut { align-self: center; } }

/* Attention card (low stock) */
.attention-card { padding: 18px 20px; }
.qty-bar {
  display: inline-block; vertical-align: middle;
  width: 52px; height: 6px;
  background: var(--border); border-radius: 3px; overflow: hidden;
  margin-right: 8px;
}
.qty-bar-fill {
  display: block; height: 100%;
  background: linear-gradient(90deg, var(--bad), #e06b6b);
  border-radius: 3px;
}
.link-arrow {
  font-size: 13px; font-weight: 500; color: var(--navy-2);
  letter-spacing: 0.2px;
}
.link-action {
  font-size: 12px; font-weight: 500; color: var(--navy-2);
  padding: 4px 10px; border-radius: 999px;
  background: var(--bg); border: 0.5px solid var(--border);
}
.link-action:hover { background: white; text-decoration: none; }

/* Tight tables and feed */
.table-tight th, .table-tight td { padding: 8px 12px; font-size: 13px; }

/* ─── Responsive tables → stacked cards on phones (13 May 2026) ──────────
   Opt-in via the `.cards-on-mobile` class so the 10 other .table-tight
   tables in the app are untouched until each is individually audited.
   At ≤640px every row becomes a bordered card; each cell becomes a
   labelled line (label comes from the td's data-label attribute).
   Reads far better on a phone than a horizontally-scrolling table and
   kills the right-edge overflow Kit reported on the dashboard. */
@media (max-width: 640px) {
  table.cards-on-mobile,
  table.cards-on-mobile thead,
  table.cards-on-mobile tbody,
  table.cards-on-mobile tr,
  table.cards-on-mobile td {
    display: block;
    width: 100%;
  }
  table.cards-on-mobile thead {
    /* Visually hidden but kept for assistive tech / semantics */
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  table.cards-on-mobile tr {
    border: 1px solid var(--border);
    border-radius: 8px;
    margin-bottom: 10px;
    padding: 10px 12px;
    background: var(--surface);
  }
  table.cards-on-mobile td {
    padding: 4px 0;
    border: none;
    font-size: 14px;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
  }
  table.cards-on-mobile td::before {
    content: attr(data-label);
    flex-shrink: 0;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: var(--muted);
  }
  /* A cell with no data-label (e.g. the rich person-cell) spans full width
     and drops the pseudo-label so the avatar block isn't squashed. */
  table.cards-on-mobile td:not([data-label])::before { content: none; }
  table.cards-on-mobile td:not([data-label]) { display: block; }
}
.person-cell { display: flex; align-items: center; gap: 10px; }
.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%;
  background: linear-gradient(135deg, var(--navy), var(--navy-2));
  color: var(--gold); font-size: 11px; font-weight: 500; letter-spacing: 0.4px;
}
.feed { list-style: none; margin: 0; padding: 0; }
.feed-item {
  display: flex; gap: 12px; padding: 8px 0;
  border-bottom: 0.5px solid var(--border);
}
.feed-item:last-child { border-bottom: none; }
.feed-dot {
  flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%;
  margin-top: 7px;
}
.feed-dot-out { background: var(--gold); box-shadow: 0 0 0 3px rgba(201,165,90,0.18); }
.feed-dot-in { background: var(--ok); box-shadow: 0 0 0 3px rgba(47,122,77,0.18); }
.feed-line { font-size: 13px; color: var(--ink); }
.feed-line strong {
  font-weight: 500; font-size: 11px; letter-spacing: 0.6px;
  color: var(--navy-2); margin-right: 8px;
}
.feed-meta { font-size: 11px; color: var(--muted); margin-top: 2px; }

/* Empty state — used when a list / page has no data */
.empty-state {
  text-align: center;
  padding: 60px 20px;
  max-width: 480px; margin: 0 auto;
}
.empty-state-icon {
  width: 64px; height: 64px;
  background: var(--navy-bg, #EEF2F8);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 18px;
}
.empty-state-title {
  font-size: 18px; font-weight: 500; color: var(--navy);
  margin: 0 0 6px;
}
.empty-state-text {
  font-size: 14px; color: var(--ink-2); line-height: 1.5;
  margin: 0 0 22px;
}
.empty-state-actions { display: inline-flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.empty-state-hint {
  font-size: 12px; color: var(--muted); margin-top: 16px;
}

/* Push notification opt-in banner. 5 May 2026: gold left-border replaced
   with navy — keeps the visual cue, drops the second gold accent on the page. */
.push-banner {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 18px; margin: 0 0 16px;
  background: linear-gradient(180deg, #FFFFFF 0%, #FAFBFC 100%);
  border: 0.5px solid var(--border);
  border-left: 3px solid var(--navy-2);
  border-radius: var(--radius);
}
.push-banner-icon {
  flex: 0 0 36px; height: 36px;
  background: var(--navy-bg, #EEF2F8);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.push-banner-text { flex: 1; min-width: 0; }
.push-banner-title { font-weight: 500; font-size: 14px; color: var(--ink); }
.push-banner-sub { font-size: 12px; color: var(--ink-2); margin-top: 2px; }
@media (max-width: 640px) {
  .push-banner { flex-wrap: wrap; }
  .push-banner-text { flex-basis: 100%; }
}

/* ---- login centred ---- */
.auth-wrap {
  min-height: calc(100vh - 120px);
  display: grid; place-items: center;
}
.auth-card { width: 100%; max-width: 380px; }
.auth-card h1 { text-align: center; }
/* ── The auth surface for the steps AFTER sign-in ─────────────────────────
   The off-centre bug was never the topbar: in the KI theme the topbar and
   footer are already display:none (app.css:214) and the real culprit is the
   container's 264px sidebar margin (app.css:215), which these pages inherit
   with no sidebar to justify it. .ki-login solves it with position:fixed;
   inset:0 — "break out of base.html's width-constrained .container" — and
   .ki-auth is that same escape for the single-card steps: MFA code, MFA
   setup, setup-link, kiosk PIN. Centred in the real viewport, both themes,
   no dependence on which chrome a theme happens to hide. */
.ki-auth {
  position: fixed; inset: 0; overflow-y: auto;
  display: grid; place-items: center;
  background: var(--paper);
  padding: 24px;
}
.auth-lockup { display: block; margin: 0 auto 18px; height: 32px; }
/* Theme-aware artwork: the dark-bg lockup is white and vanishes on the light
   theme's warm paper; the plain lockup is the inverse. Show one each. */
.auth-lockup-dark { display: none; }
html.theme-ki .auth-lockup-dark { display: block; }
html.theme-ki .auth-lockup-light { display: none; }

/* ---- Kit Intelligence two-column login (Stage 1 rebrand, 7 Jun 2026) ---- */
.ki-login {
  position: fixed;     /* break out of base.html's width-constrained .container */
  inset: 0;
  overflow-y: auto;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  background: var(--paper);
}
.ki-login-brand {
  background: linear-gradient(155deg, var(--teal) 0%, var(--teal-deep) 100%);
  color: #EAF1F1;
  padding: 56px 60px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 48px;
}
.ki-login-lockup { height: 38px; width: auto; display: block; }
.ki-login-brand-top { display: flex; align-items: center; gap: 12px; }
.ki-login-badge { height: 40px; width: auto; display: block; }
.ki-login-badge--invert { filter: invert(1); }   /* outline crest → white on the club-colour panel */
.ki-login-product { font-weight: 600; font-size: 15px; letter-spacing: -0.01em; color: #fff; }
.ki-login-headline {
  font-family: var(--display);
  font-size: 40px; line-height: 1.08; letter-spacing: -0.03em;
  font-weight: 600; margin: 0; max-width: 13ch; color: #fff;
}
.ki-login-sub {
  font-size: 16px; color: rgba(255, 255, 255, 0.72);
  margin: 16px 0 0; max-width: 36ch; line-height: 1.5;
}
.ki-login-feats {
  list-style: none; margin: 18px 0 0; padding: 0;
  display: flex; align-items: center;
  font-size: 14px; font-weight: 500; letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.9);
}
.ki-login-feats li { padding: 0 16px; position: relative; }
.ki-login-feats li:first-child { padding-left: 0; }
.ki-login-feats li + li::before {
  content: ""; position: absolute; left: 0; top: 50%;
  transform: translateY(-50%); width: 1px; height: 13px;
  background: rgba(255, 255, 255, 0.3);
}
.ki-login-trust {
  display: flex; flex-wrap: wrap; gap: 8px 18px;
  font-size: 12.5px; color: rgba(255, 255, 255, 0.62);
}
.ki-login-trust span { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.ki-login-trust span::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.5); flex-shrink: 0;
}
/* flex-direction MATTERS here. This was a row (the default) back when the
   card was the only child, and it looked fine. The legal links were added
   under the card later, and a row laid them out BESIDE it — floating in the
   middle-right of the panel, level with the password field, on the first
   page anyone ever sees. Column stacks them under the card as intended;
   .auth-card is max-width:380px so align-items:center still centres it. */
.ki-login-form {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 24px;
}
/* Model-A login button uses the KI product teal (not the tenant accent) — the
   only teal in the user's flow; the club's own palette takes over the moment
   they sign in. */
.ki-login-form .btn { background: var(--teal); border-color: var(--teal); color: #fff; }
.ki-login-form .btn:hover { background: var(--teal-deep); border-color: var(--teal-deep); filter: none; }
@media (max-width: 820px) {
  .ki-login { grid-template-columns: 1fr; }
  .ki-login-brand { display: none; }
}

/* ---- scan page (mobile-first, big buttons) ---- */
.scan-shell {
  max-width: 480px; margin: 0 auto;
}
#reader {
  width: 100%; max-width: 480px;
  border: 2px solid var(--border); border-radius: var(--radius);
  overflow: hidden; background: black;
}
.scan-result { margin-top: 18px; }
.scan-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 14px; }
.scan-actions .btn-lg { font-size: 18px; padding: 18px; }

.qty-display {
  font-size: 48px; font-weight: 800; color: var(--navy);
  text-align: center; margin: 14px 0;
}
.qty-display.low { color: var(--bad); }

.kiosk-banner {
  background: var(--gold); color: var(--navy); text-align: center;
  padding: 6px 12px; font-weight: 600; font-size: 13px;
  border-radius: var(--radius-sm); margin-bottom: 12px;
}

/* ---- offline indicator ---- */
.offline-banner {
  position: fixed; bottom: 14px; left: 50%; transform: translateX(-50%);
  background: var(--warn); color: white; padding: 8px 16px;
  border-radius: 999px; font-size: 13px; font-weight: 600;
  display: none; z-index: 50;
}
body.offline .offline-banner { display: block; }

/* ============================================================
   MOBILE AUDIT — fixes for ≤640px viewports.
   Targets the cramped + overflowing patterns identified in the
   design review. Last sweep applied to checkout, dashboard,
   stock, tables, AI panel.
   ============================================================ */
@media (max-width: 640px) {
  /* Checkout — collapse the 2-column item+person grid to single column */
  .card[style*="max-width:920px"] > div[style*="grid-template-columns:1fr 1fr"] {
    grid-template-columns: 1fr !important;
    gap: 24px !important;
  }
  .card[style*="max-width:920px"] {
    padding: 22px 18px !important;
    max-width: 100% !important;
  }

  /* Dashboard / Movement headers — stack the action buttons under the title */
  .dash-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }
  .dash-head-actions {
    width: 100%;
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
  }

  /* Tables — wrap in scrolling region; hide some columns for breathing room */
  .card table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
  }
  /* For tables that ARE scrolling, restore inline behaviour after horizontal */
  .card table thead, .card table tbody, .card table tr { white-space: normal; }
  .card table th, .card table td { white-space: nowrap; }

  /* KPI row → single column on phones (was 2-col at 720px) */
  .kpi-row { grid-template-columns: 1fr 1fr !important; }
  .kpi-card .kpi-value { font-size: 32px; }

  /* Page-header margins — pull back container padding so headers go edge-to-edge */
  main.container { padding: 14px 14px 28px; }

  /* Cards — slightly less padding so content can breathe */
  .card { padding: 16px; }
  .card-primary { padding: 18px 16px; }

  /* Forms inside cards — column-stack the rows */
  .card form[style*="display:flex"] { flex-wrap: wrap; }
  .card form[style*="display:flex"] > * { flex: 1 1 100%; min-width: 0; }

  /* Footer — hide the 3 column menu, keep brand + copyright */
  .footer-inner { grid-template-columns: 1fr !important; }
  .footer-col { display: none; }
  .footer-col-title:first-child { display: none; }

  /* Topbar actions — keep ⌘K hint visible but slimmer */
  .cmdk-trigger-hint { padding: 2px 6px; font-size: 10px; }

  /* AI floating button — slightly smaller on phone, snug to corner */
  .ai-fab { bottom: 16px; right: 16px; width: 50px; height: 50px; }
  .ai-fab svg { width: 22px; height: 22px; }

  /* Suggestion / followup chips — stack one per line for big tap targets */
  .ai-suggestions, .ai-followups { gap: 8px; }
  .ai-suggestion, .ai-followup { width: 100%; }

  /* Eyebrows — slightly smaller, tighter */
  .eyebrow { font-size: 10px; letter-spacing: 1.2px; }

  /* H1/H2 already responsive via earlier rules; touch-up for very narrow widths */
  h1 { font-size: 28px; line-height: 1.15; }
  h2 { font-size: 18px; }

  /* Stock chart — y-axis labels can compress; bars stay scrollable */
  .card div[style*="grid-template-columns:minmax(160px,1.4fr) 1fr 50px"] {
    grid-template-columns: minmax(120px, 1.2fr) 1fr 44px !important;
    gap: 8px !important;
  }
}

/* iPhone SE / very narrow (≤375px) — extra compaction */
@media (max-width: 375px) {
  h1 { font-size: 24px; }
  .kpi-row { grid-template-columns: 1fr !important; }
  .kpi-card .kpi-value { font-size: 28px; }
  main.container { padding: 12px 12px 24px; }
}

/* ============================================================
   TODAY HERO — the dashboard's primary action region.
   Added 5 May 2026 with the dashboard restructure. The dashboard
   now leads with this card; longer-window analytics moved to /reports.
   ============================================================ */
.today-card {
  padding: 18px 20px;
}

.today-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.today-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 4px;
  border-bottom: 0.5px solid var(--border);
}
.today-item:last-child { border-bottom: none; }

.today-icon {
  flex: 0 0 36px;
  width: 36px; height: 36px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center; justify-content: center;
}
.today-icon-warn {
  background: rgba(178,42,42,0.08);
  color: var(--bad);
}
.today-icon-ok {
  background: rgba(47,122,77,0.10);
  color: var(--ok);
}

.today-item-body { flex: 1; min-width: 0; }
.today-item-title {
  font-size: 14px;
  color: var(--ink);
  font-weight: 500;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.today-item-title a {
  color: var(--navy);
  text-decoration: none;
}
.today-item-title a:hover { text-decoration: underline; }
.today-item-status {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.4px;
  color: var(--bad);
  text-transform: uppercase;
}
.today-item-meta {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

.today-clear {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 4px 6px;
}
.today-clear-title {
  font-size: 14px;
  color: var(--ok);
  font-weight: 500;
}
.today-clear-sub {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
}

@media (max-width: 640px) {
  .today-item {
    flex-wrap: wrap;
    gap: 10px;
  }
  .today-item .btn-sm {
    width: 100%;
    margin-top: 4px;
  }
}

/* ============================================================
   PLAYER KIT CARD (PKC) — per-person profile page.
   See docs/PLAYER-KIT-CARDS-SPEC.md for the design rationale.
   Apple-Health activity rings + Notion clean profile aesthetic.
   ============================================================ */

/* Hero — name + avatar + meta + actions */
.pkc-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin: 8px 0 20px;
}
.pkc-hero-left {
  display: flex;
  align-items: center;
  gap: 20px;
  min-width: 0;
}
/* The player's initials disc.
   Was a --navy → --navy-2 gradient with --gold lettering. On the dark theme
   those two tokens are hardcoded to the PRODUCT's teal and amber, which beat
   base.html's per-club :root override on specificity — so Bolton's card wore
   Kit Intelligence's colours, in a 500-weight body face at half-pixel
   tracking that read as washed out at 32px.
   --club-hero is the club's own primary lifted until it is legible on the
   dark canvas, and is not clobbered by the theme. Dark ink on it, the display
   face, and the weight the size actually wants. */
.pkc-avatar {
  flex: 0 0 88px;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  background: var(--club-primary);
  color: var(--club-hero);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--display);
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1;
  /* A hairline of the canvas, then the club colour again at low alpha —
     it separates the disc from the card without a drop shadow, which on a
     dark surface only ever reads as grime. */
  box-shadow: 0 0 0 2px var(--club-hero);
}
.pkc-name {
  font-size: 44px;
  font-weight: 500;
  color: var(--navy);
  margin: 0 0 6px;
  letter-spacing: -0.03em;
  line-height: 1.05;
}
.pkc-hero-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 14px;
  color: var(--ink-2);
}
.pkc-kit-no {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  padding: 1px 7px;
  /* Same leak as the avatar: --navy/--gold are the product's teal and amber
     on the dark theme, so a squad number sat gold-on-teal beside a club-
     coloured disc, and at 13px the two were near enough in tone to be hard
     to read. The club's own colours, and the number as the light element. */
  background: var(--club-primary);
  color: var(--club-hero);
  border: 1px solid var(--club-hero);
  border-radius: 4px;
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
.pkc-tenure {
  font-size: 13px;
  color: var(--muted);
  margin-top: 6px;
}
.pkc-hero-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

@media (max-width: 720px) {
  .pkc-hero {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }
  .pkc-hero-left { flex-wrap: wrap; gap: 14px; }
  .pkc-avatar { flex: 0 0 64px; width: 64px; height: 64px; font-size: 24px; }
  .pkc-name { font-size: 30px; }
  .pkc-hero-actions { width: 100%; }
  .pkc-hero-actions .btn { flex: 1; }
}

/* Usage card — three big stats + tier badge */
.pkc-usage-card { padding: 24px; }
.pkc-usage-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  padding: 12px 0 4px;
}
.pkc-usage-stat {
  padding: 16px 18px;
  background: var(--bg);
  border-radius: 12px;
}
.pkc-usage-value {
  font-size: 44px;
  font-weight: 500;
  color: var(--navy);
  letter-spacing: -0.025em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.pkc-usage-label {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  font-weight: 500;
  margin-top: 8px;
}
.pkc-usage-sub {
  font-size: 12px;
  color: var(--ink-2);
  margin-top: 4px;
}
.pkc-tier {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.pkc-tier::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.pkc-tier-high {
  background: rgba(178,42,42,0.10);
  color: var(--bad);
}
.pkc-tier-medium {
  background: rgba(184,120,46,0.10);
  color: var(--warn);
}
.pkc-tier-low {
  background: rgba(47,122,77,0.10);
  color: var(--ok);
}
.pkc-tier-dormant {
  background: var(--bg);
  color: var(--muted);
}

/* Passport tiers — 21 May 2026. Squad-relative responsibility score.
   Same chip shape as usage tiers above, different colour palette so
   the two surfaces don't read as the same thing. */
.pkc-tier-platinum {
  background: linear-gradient(135deg, rgba(155,170,200,0.18), rgba(220,225,235,0.18));
  color: #4c5a72;
  border: 1px solid rgba(155,170,200,0.30);
}
.pkc-tier-gold {
  background: rgba(201,165,90,0.14);
  color: #8c6a25;
}
.pkc-tier-silver {
  background: rgba(140,150,165,0.14);
  color: #5d6675;
}
.pkc-tier-bronze {
  background: rgba(176,108,52,0.14);
  color: #7a4a1f;
}
.pkc-tier-review {
  background: rgba(178,42,42,0.10);
  color: var(--bad);
}
.pkc-tier-insufficient,
.pkc-tier-new,
.pkc-tier-na {
  background: var(--bg);
  color: var(--muted);
}

.pkc-tier-inline {
  margin-left: 8px;
  font-size: 10px;
  padding: 2px 7px;
}
.pkc-tier-inline::before {
  width: 5px;
  height: 5px;
}

/* 26 May 2026 — Prominent variant for the Kit Score chip on the
   player detail hero. Kit's review: "The Kit Health score pill —
   could be more attractive and its quite small." The standard
   .pkc-tier is 11px / 4px-10px padding which is right for the
   inline-in-tile usage on the Squad Passport grid, but too small
   for the headline pill next to the player's name.
   This modifier scales it up and gives the score number more
   weight via a subtle shadow + larger dot. */
.pkc-tier-prominent {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.6px;
  padding: 8px 16px;
  gap: 10px;
  box-shadow: 0 1px 2px rgba(11, 34, 64, 0.08),
              0 2px 8px rgba(11, 34, 64, 0.04);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.pkc-tier-prominent::before {
  width: 9px;
  height: 9px;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.6);
}
.pkc-tier-prominent:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(11, 34, 64, 0.10),
              0 4px 14px rgba(11, 34, 64, 0.06);
}

@media (max-width: 720px) {
  .pkc-usage-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .pkc-usage-value { font-size: 36px; }
}

/* Currently allocated — list of tiles */
.pkc-allocated-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.pkc-allocated-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 4px;
  border-bottom: 0.5px solid var(--border);
}
.pkc-allocated-item:last-child { border-bottom: none; }
.pkc-allocated-body { flex: 1; min-width: 0; }
.pkc-allocated-title {
  font-size: 14px;
  color: var(--ink);
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.pkc-allocated-title a {
  color: var(--navy);
  text-decoration: none;
}
.pkc-allocated-title a:hover { text-decoration: underline; }
.pkc-allocated-meta {
  font-size: 12px;
  color: var(--muted);
  margin-top: 3px;
}
.pkc-allocated-qty {
  flex: 0 0 auto;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  padding: 4px 10px;
  background: var(--bg);
  border-radius: 6px;
}

/* Lifetime stats strip — reuse kpi-card sizing, slightly tighter */
.pkc-stats-row {
  margin-bottom: 18px;
}
.pkc-stats-row .kpi-card .kpi-value {
  font-size: 36px;
}

/* History timeline — clean feed of events */
.pkc-history {
  list-style: none;
  margin: 0;
  padding: 0;
}
.pkc-history-item {
  display: flex;
  gap: 14px;
  padding: 12px 4px;
  border-bottom: 0.5px solid var(--border);
}
.pkc-history-item:last-child { border-bottom: none; }
.pkc-history-dot {
  flex: 0 0 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-top: 7px;
}
.pkc-history-dot-out {
  background: var(--gold);
  box-shadow: 0 0 0 3px rgba(201,165,90,0.18);
}
.pkc-history-dot-in {
  background: var(--ok);
  box-shadow: 0 0 0 3px rgba(47,122,77,0.18);
}
/* A correction is not a return. It shared the return's green dot until
   19 Aug 2026, which made a mistake being fixed look like kit coming home. */
.pkc-history-dot-void {
  background: var(--muted);
  box-shadow: 0 0 0 3px rgba(138,135,120,0.18);
}
.pkc-history-body { flex: 1; min-width: 0; }
.pkc-history-line {
  font-size: 14px;
  color: var(--ink);
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.pkc-history-tag {
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.6px;
  color: var(--navy-2);
}
.pkc-history-meta {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

/* Receive — AI photo-parse block */
.receive-photo-block {
  background: linear-gradient(135deg, rgba(11,34,64,0.04), rgba(201,165,90,0.06));
  border: 0.5px solid var(--border);
  border-left: 3px solid var(--gold);
  border-radius: var(--radius);
  padding: 14px 18px;
  margin-bottom: 4px;
}
.receive-photo-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.receive-photo-title {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
}
.receive-photo-sub {
  font-size: 12px;
  color: var(--ink-2);
  margin-top: 2px;
}

/* PKC empty state */
.pkc-empty {
  text-align: center;
  padding: 36px 20px;
  color: var(--muted);
}
.pkc-empty-title {
  font-size: 14px;
  color: var(--ink-2);
  font-weight: 500;
  margin-bottom: 4px;
}
.pkc-empty-sub {
  font-size: 13px;
  max-width: 360px;
  margin: 0 auto;
  line-height: 1.5;
}

/* Typeahead dropdown — Checkout's Item and Person pickers (~20 May 2026).
   Always-visible branded gold scrollbar + a subtle inset fade at the
   bottom: makes it obvious there's more to scroll, even when the OS
   would auto-hide the scrollbar and leave users thinking the dropdown
   stops at the few results they can see. Replaces a duplicated inline
   style on both #item-results and #person-results (debt the design
   audit kept flagging). */
.typeahead-results {
  position: absolute;
  top: calc(100% - 4px);
  left: 0; right: 0;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow:
    0 8px 24px rgba(11,34,64,0.10),
    0 2px 6px rgba(11,34,64,0.06),
    /* Stronger "more below" fade so the scroll affordance survives even
       where the OS hides the native bar — this is the part that doesn't
       depend on the scrollbar rendering at all. */
    inset 0 -26px 20px -18px rgba(11,34,64,0.16);
  max-height: min(60vh, 480px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  z-index: 50;
  margin-top: 6px;
  /* Reserve a permanent scrollbar gutter so the bar can never auto-hide
     and the content doesn't reflow when it appears (27 Jun 2026 — the
     "scroller disappeared again" regression: a thin pale thumb on white
     read as gone). Firefox honours scrollbar-width/-gutter directly. */
  scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: var(--navy) rgba(11,34,64,0.06);
}
/* Chromium/WebKit: a solid, clearly-visible navy thumb in a tinted track.
   No white border (it thinned the thumb to a sliver) and a touch wider. */
.typeahead-results::-webkit-scrollbar { width: 11px; }
.typeahead-results::-webkit-scrollbar-track {
  background: rgba(11,34,64,0.06);
  border-radius: 0 8px 8px 0;
}
.typeahead-results::-webkit-scrollbar-thumb {
  background: var(--navy);
  border-radius: 6px;
  border: 2px solid transparent;
  background-clip: content-box;
}
.typeahead-results::-webkit-scrollbar-thumb:hover { background: var(--gold-2); }

/* ── Packs on the till ───────────────────────────────────────────────────
   A named bundle staged into the basket in one tap. Sits between the item
   picker and the basket, because that is the order the kitman works in:
   what am I giving them, then who, then check it. */
.ck-packs { margin-top: 18px; }
.ck-packs-lab {
  font-size: 11px; font-weight: 600; letter-spacing: 1.4px;
  text-transform: uppercase; color: var(--muted); margin-bottom: 9px;
}
.ck-packs-row { display: flex; gap: 10px; flex-wrap: wrap; }
.ck-pack {
  display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 10px 14px; border-radius: 10px; cursor: pointer;
  font-family: inherit; min-width: 0; max-width: 320px;
  background: var(--surface-alt, var(--bg));
  border: 1px solid var(--border);
  transition: border-color .12s, background .12s, transform .06s;
}
.ck-pack:hover { border-color: var(--accent); background: var(--accent-tint, var(--bg)); }
.ck-pack:active { transform: translateY(1px); }
.ck-pack:disabled { opacity: .55; cursor: default; }
.ck-pack:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.ck-pack-name { font-size: 14px; font-weight: 600; color: var(--ink); }
.ck-pack-meta {
  font-size: 11.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* What it assumed, and what it could not fill. A pack that silently drops a
   line is worse than one that says which line it cannot fill. */
.ck-pack-note { margin-top: 10px; font-size: 12.5px; color: var(--ink-2); }
.ck-pack-note.is-warn { color: var(--warn); }

/* ═══════════════════════════════════════════════════════════════════════════
   Items / Inventory — the size-profile ledger (26 Aug 2026 design handoff).
   Every colour/space/radius is an existing theme-ki token; the two structural
   literals the prototype carries (track rgba(255,255,255,.05), panel
   rgba(6,20,26,.55)) are kept as written — they are alpha washes over the
   obsidian canvas, not new palette values.
   ═════════════════════════════════════════════════════════════════════════ */
html.theme-ki .ki-inv { max-width:1180px; }

/* Hero */
html.theme-ki .ki-inv-hero { display:flex; align-items:flex-end; justify-content:space-between; gap:24px; }
html.theme-ki .ki-inv-eyebrow { font-size:11px; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--area); display:inline-flex; align-items:center; gap:9px; margin-bottom:14px; }
html.theme-ki .ki-inv-eyebrow .ki-dot { width:6px; height:6px; border-radius:50%; background:var(--area); }
html.theme-ki .ki-inv-title { font-family:var(--display); font-size:40px; font-weight:600; letter-spacing:-0.03em; line-height:1.05; color:var(--ink); margin:0; }
html.theme-ki .ki-inv-sub { margin:14px 0 0; font-size:17px; line-height:1.5; color:var(--ink-2); max-width:660px; text-wrap:pretty; }
html.theme-ki .ki-inv-sub strong { color:var(--ink); font-weight:600; }
html.theme-ki .ki-inv-heroacts { display:flex; align-items:center; gap:10px; flex:none; }
html.theme-ki .ki-inv-btn { display:inline-flex; align-items:center; gap:6px; font-size:12.5px; font-weight:600; letter-spacing:-0.005em; padding:9px 14px; border-radius:var(--radius-sm); background:linear-gradient(180deg, var(--accent-deep) 0%, var(--area) 100%); color:var(--on-navy); text-decoration:none; box-shadow:inset 0 1px 0 rgba(255,255,255,0.18), var(--shadow-sm); white-space:nowrap; }
html.theme-ki .ki-inv-btn:hover { filter:brightness(1.06); }
html.theme-ki .ki-inv-btn:active { transform:translateY(1px); }
html.theme-ki .ki-inv-btn2 { display:inline-flex; align-items:center; gap:6px; font-size:12.5px; font-weight:600; letter-spacing:-0.005em; padding:9px 14px; border-radius:var(--radius-sm); background:var(--surface-alt); color:var(--ink); border:1px solid var(--edge); text-decoration:none; white-space:nowrap; }
html.theme-ki .ki-inv-btn2:hover { background:var(--panel-3); }
html.theme-ki .ki-inv-btn2:active { transform:translateY(1px); }

/* Toolbar */
html.theme-ki .ki-inv-toolbar { display:flex; align-items:center; gap:10px; margin-top:30px; flex-wrap:wrap; }
html.theme-ki .ki-inv-search { display:inline-flex; align-items:center; gap:9px; flex:1; min-width:220px; max-width:340px; background:var(--surface); border:1px solid var(--edge); border-radius:var(--radius-sm); padding:9px 13px; color:var(--muted); }
html.theme-ki .ki-inv-search input { flex:1; background:transparent; border:none; outline:none; color:var(--ink); font-family:inherit; font-size:13.5px; min-width:0; }
html.theme-ki .ki-inv-search input::placeholder { color:var(--muted); }
html.theme-ki .ki-inv-search:focus-within { outline:2px solid var(--accent); outline-offset:-1px; }
html.theme-ki .ki-inv-chip { display:inline-flex; align-items:center; gap:7px; font-size:12.5px; font-weight:600; color:var(--ink-2); background:var(--surface); border:1px solid var(--edge); padding:9px 14px; border-radius:999px; cursor:pointer; font-family:inherit; }
html.theme-ki .ki-inv-chip:hover { color:var(--ink); border-color:var(--edge-2); }
html.theme-ki .ki-inv-chip.on { color:var(--on-navy); background:var(--area); border-color:transparent; }
html.theme-ki .ki-inv-chip.on .ki-inv-chipdot { background:var(--on-navy) !important; }
html.theme-ki .ki-inv-chipdot { width:6px; height:6px; border-radius:50%; flex:none; }
html.theme-ki .ki-inv-tools { margin-left:auto; display:inline-flex; gap:8px; }
html.theme-ki .ki-inv-tool { font-size:12.5px; font-weight:500; color:var(--ink-2); background:var(--surface); border:1px solid var(--edge); padding:9px 14px; border-radius:var(--radius-sm); text-decoration:none; }
html.theme-ki .ki-inv-tool:hover { color:var(--ink); border-color:var(--edge-2); }

/* Ledger card. overflow-x:auto around a min-width inner is load-bearing: the
   row grid needs ~944px, and without the scroll the status column is clipped
   and unreachable below roughly a 1370px viewport. */
html.theme-ki .ki-inv-card { margin-top:18px; background:var(--surface); border:1px solid var(--edge); border-radius:var(--radius); overflow-x:auto; overflow-y:hidden; box-shadow:var(--shadow); }
html.theme-ki .ki-inv-innerw { min-width:960px; }

/* Meta strip */
html.theme-ki .ki-inv-meta { display:flex; align-items:center; justify-content:space-between; gap:16px; padding:14px 24px; border-bottom:1px solid var(--edge); background:rgba(255,255,255,.02); }
html.theme-ki .ki-inv-metatotals { font-size:12.5px; color:var(--ink-2); font-variant-numeric:tabular-nums; }
html.theme-ki .ki-inv-metatotals strong { color:var(--ink); font-weight:600; }
html.theme-ki .ki-inv-legend { display:inline-flex; align-items:center; gap:16px; font-size:11px; color:var(--muted); }
html.theme-ki .ki-inv-legenditem { display:inline-flex; align-items:center; gap:7px; }
html.theme-ki .ki-inv-swatch { width:9px; height:4px; border-radius:2px; }

/* Row */
html.theme-ki .ki-inv-row { display:grid; grid-template-columns:minmax(230px,1fr) 288px 96px 210px; gap:24px; align-items:center; padding:17px 24px; border-top:1px solid var(--edge); cursor:pointer; }
html.theme-ki #ki-inv-rows > .ki-inv-row:first-child { border-top:none; }
html.theme-ki .ki-inv-row:hover { background:rgba(255,255,255,.02); }
html.theme-ki .ki-inv-row.is-below { background:rgba(224,112,106,.06); }
html.theme-ki .ki-inv-row.is-below:hover { background:rgba(224,112,106,.09); }
html.theme-ki .ki-inv-row.is-open { background:var(--accent-tint); box-shadow:inset 3px 0 0 var(--area); border-top-color:transparent; }
html.theme-ki .ki-inv-row:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
html.theme-ki .ki-inv-item { min-width:0; }
html.theme-ki .ki-inv-nameline { display:flex; align-items:center; gap:9px; min-width:0; }
html.theme-ki .ki-inv-tick { flex:0 0 3px; width:3px; height:26px; border-radius:2px; background:var(--bad); margin-left:-15px; }
html.theme-ki .ki-inv-caret { width:12px; flex:none; color:var(--muted); font-size:15px; line-height:1; display:inline-block; text-align:center; transition:transform 300ms cubic-bezier(0.2,0.9,0.3,1), color 300ms; }
html.theme-ki .ki-inv-row.is-open .ki-inv-caret { transform:rotate(90deg); color:var(--area); }
html.theme-ki .ki-inv-name { font-size:15.5px; font-weight:600; color:var(--ink); letter-spacing:-0.01em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
html.theme-ki .ki-inv-rowmeta { font-size:12px; color:var(--muted); margin-top:5px; padding-left:21px; }
html.theme-ki .ki-inv-stale { color:var(--warn); }

/* The size run: each cell a column of label → quantity → 4px bar whose width
   is that size's share of the row's LARGEST size, split per site inside. */
html.theme-ki .ki-inv-run { display:flex; flex-wrap:wrap; gap:7px 8px; min-width:0; }
/* 9+ sizes (boots, gloves) need more than the 288px track — cells wrap to a
   second line rather than overflowing into the on-shelf column. */
html.theme-ki .ki-inv-cell { display:flex; flex-direction:column; gap:7px; flex:1 1 48px; min-width:30px; max-width:48px; }
html.theme-ki .ki-inv-celllab { font-size:10px; font-weight:600; letter-spacing:.09em; text-transform:uppercase; color:var(--muted); text-align:center; white-space:nowrap; overflow:hidden; }
html.theme-ki .ki-inv-cellqty { font-size:14.5px; font-weight:600; font-variant-numeric:tabular-nums; text-align:center; line-height:1; }
html.theme-ki .ki-inv-track { display:block; height:4px; border-radius:2px; background:rgba(255,255,255,.05); }
html.theme-ki .ki-inv-fill { display:flex; gap:2px; height:100%; }
html.theme-ki .ki-inv-seg { border-radius:2px; min-width:1px; }

/* Shelf vs out */
html.theme-ki .ki-inv-shelf { text-align:right; }
html.theme-ki .ki-inv-shelfnum { font-family:var(--display); font-size:23px; font-weight:500; font-variant-numeric:tabular-nums; letter-spacing:-0.02em; line-height:1; color:var(--ink); }
html.theme-ki .ki-inv-shelfcap { font-size:11px; color:var(--muted); margin-top:5px; }

/* Status */
html.theme-ki .ki-inv-statusline { display:inline-flex; align-items:center; gap:8px; font-size:13px; font-weight:600; }
html.theme-ki .ki-inv-statusdot { width:7px; height:7px; border-radius:50%; background:currentColor; flex:none; }
html.theme-ki .ki-inv-k-ok { color:var(--ink-2); }
html.theme-ki .ki-inv-k-ok .ki-inv-statusdot { background:var(--ok); }
html.theme-ki .ki-inv-k-watch, html.theme-ki .ki-inv-k-move { color:var(--warn); }
html.theme-ki .ki-inv-k-order { color:var(--bad); }
html.theme-ki .ki-inv-statusnote { font-size:11.5px; color:var(--muted); margin-top:5px; }
html.theme-ki .ki-inv-movepill { display:inline-flex; align-items:center; gap:6px; margin-top:6px; font-size:11.5px; font-weight:600; color:var(--area); background:var(--area-soft); padding:5px 11px; border-radius:999px; text-decoration:none; }
html.theme-ki .ki-inv-movepill:hover { color:var(--ink); background:rgba(95,182,196,.28); }

/* Drawer — grid-template-rows 0fr→1fr animates to the content's natural
   height with no magic number; a three-size line and an eleven-size line
   both work. The inner clip (overflow:hidden; min-height:0) is what makes
   the 0fr state actually hide the content. */
html.theme-ki .ki-inv-drawer { display:grid; grid-template-rows:0fr; transition:grid-template-rows 420ms cubic-bezier(0.2,0.9,0.3,1); background:var(--accent-tint); box-shadow:inset 3px 0 0 var(--area); }
html.theme-ki .ki-inv-drawer.is-open { grid-template-rows:1fr; }
html.theme-ki .ki-inv-drawerclip { overflow:hidden; min-height:0; }
html.theme-ki .ki-inv-drawerpad { padding:0 24px 22px; opacity:0; transition:opacity 300ms cubic-bezier(0.2,0.9,0.3,1); }
html.theme-ki .ki-inv-drawer.is-open .ki-inv-drawerpad { opacity:1; }
html.theme-ki .ki-inv-panel { padding:18px 20px; background:rgba(6,20,26,.55); border:1px solid var(--edge); border-radius:11px; }
/* Contents settle INTO the opened panel: 70ms, then +28ms per line — the
   design system's page-rise stagger. --d is set inline per line. */
html.theme-ki .ki-inv-lad-anim { opacity:0; transform:translateY(9px); transition:opacity 320ms cubic-bezier(0.2,0.9,0.3,1) var(--d,70ms), transform 320ms cubic-bezier(0.2,0.9,0.3,1) var(--d,70ms); }
html.theme-ki .ki-inv-drawer.is-open .ki-inv-lad-anim { opacity:1; transform:translateY(0); }

/* The diverging size ladder */
html.theme-ki .ki-inv-ladhead { display:grid; grid-template-columns:1fr 62px 1fr; align-items:baseline; padding-bottom:12px; border-bottom:1px solid var(--edge); }
html.theme-ki .ki-inv-ladheadl { display:flex; align-items:baseline; justify-content:flex-end; gap:9px; }
html.theme-ki .ki-inv-ladheadr { display:flex; align-items:baseline; gap:9px; }
html.theme-ki .ki-inv-ladsite { font-size:13px; font-weight:600; color:var(--ink); }
html.theme-ki .ki-inv-ladnone { color:var(--muted); font-weight:500; }
html.theme-ki .ki-inv-ladtotal { font-size:13px; font-weight:600; font-variant-numeric:tabular-nums; }
html.theme-ki .ki-inv-ladmid { font-size:10px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); text-align:center; }
html.theme-ki .ki-inv-ladrow { display:grid; grid-template-columns:34px 1fr 62px 1fr 34px; align-items:center; gap:10px; padding:9px 0; font-variant-numeric:tabular-nums; }
html.theme-ki .ki-inv-ladqty { font-size:12.5px; text-decoration:none; }
html.theme-ki .ki-inv-ladqty.ki-r { text-align:right; }
html.theme-ki .ki-inv-ladbarl { display:flex; justify-content:flex-end; height:8px; }
html.theme-ki .ki-inv-ladbarr { display:flex; height:8px; }
html.theme-ki .ki-inv-ladfill { height:100%; border-radius:2px; min-width:1px; }
html.theme-ki .ki-inv-ladsize { font-size:12px; font-weight:600; text-align:center; }
html.theme-ki .ki-inv-ladfoot { display:flex; align-items:center; justify-content:flex-end; gap:9px; margin-top:16px; padding-top:14px; border-top:1px solid var(--edge); }
html.theme-ki .ki-inv-ladbtn2 { font-size:12px; font-weight:600; color:var(--ink-2); background:var(--surface-alt); border:1px solid var(--edge); padding:7px 12px; border-radius:var(--radius-sm); text-decoration:none; }
html.theme-ki .ki-inv-ladbtn2:hover { color:var(--ink); }
html.theme-ki .ki-inv-ladbtn { font-size:12px; font-weight:600; color:var(--on-navy); background:var(--area); padding:7px 12px; border-radius:var(--radius-sm); text-decoration:none; }
html.theme-ki .ki-inv-ladbtn:hover { filter:brightness(1.06); }

/* Footer strip + empty state */
html.theme-ki .ki-inv-foot { display:flex; align-items:center; justify-content:space-between; padding:13px 24px; border-top:1px solid var(--edge); background:rgba(255,255,255,.02); font-size:12.5px; color:var(--muted); }
html.theme-ki .ki-inv-empty { padding:34px 20px; text-align:center; color:var(--muted); font-size:13px; border-top:1px solid var(--edge); }

@media (max-width:820px) {
  html.theme-ki .ki-inv-title { font-size:32px; }
  html.theme-ki .ki-inv-hero { flex-direction:column; align-items:flex-start; gap:14px; }
  html.theme-ki .ki-inv-tools { margin-left:0; }
}
@media (prefers-reduced-motion: reduce) {
  html.theme-ki .ki-inv-drawer,
  html.theme-ki .ki-inv-drawerpad,
  html.theme-ki .ki-inv-lad-anim,
  html.theme-ki .ki-inv-caret { transition-duration:.01ms; transition-delay:0ms; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Movement → Between sites — pre-populated per-size transfer (26 Aug 2026
   design handoff, screen 2). Tokens only.
   ═════════════════════════════════════════════════════════════════════════ */
html.theme-ki .ki-tx-wrap { max-width:900px; }
html.theme-ki .ki-tx-back { display:flex; width:fit-content; align-items:center; gap:6px; font-size:12.5px; font-weight:600; color:var(--ink-2); text-decoration:none; margin-bottom:14px; }
html.theme-ki .ki-tx-back:hover { color:var(--ink); }
html.theme-ki .ki-tx-card { background:var(--surface); border:1px solid var(--edge); border-radius:var(--radius); box-shadow:var(--shadow); overflow:hidden; }
html.theme-ki .ki-tx-section { padding:18px 22px; }
html.theme-ki .ki-tx-section + .ki-tx-section { border-top:1px solid var(--edge); }
html.theme-ki .ki-tx-lab { font-size:11px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); margin-bottom:10px; }
html.theme-ki .ki-tx-small { display:block; font-size:10px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); margin-bottom:6px; }
html.theme-ki .ki-tx-opt { font-weight:400; text-transform:none; letter-spacing:0; }

/* Item picker — the cold-start path, never hidden behind a "change" button */
html.theme-ki .ki-tx-pickrow { display:flex; gap:10px; flex-wrap:wrap; position:relative; }
html.theme-ki .ki-tx-search { display:inline-flex; align-items:center; gap:9px; flex:1; min-width:240px; background:var(--surface-alt); border:1px solid var(--edge); border-radius:var(--radius-sm); padding:10px 13px; color:var(--muted); }
html.theme-ki .ki-tx-search input { flex:1; background:transparent; border:none; outline:none; color:var(--ink); font-family:inherit; font-size:13.5px; min-width:0; }
html.theme-ki .ki-tx-search:focus-within { outline:2px solid var(--accent); outline-offset:-1px; }
html.theme-ki .ki-tx-skuin { width:170px; background:var(--surface-alt); border:1px solid var(--edge); border-radius:var(--radius-sm); padding:10px 13px; color:var(--ink); font-family:inherit; font-size:12.5px; text-transform:uppercase; box-sizing:border-box; }
html.theme-ki .ki-tx-skuin::placeholder { color:var(--muted); text-transform:none; }
html.theme-ki .ki-tx-skuin:focus-visible { outline:2px solid var(--accent); outline-offset:-1px; }
html.theme-ki .ki-tx-hint { font-size:11.5px; color:var(--muted); margin-top:8px; }
html.theme-ki .ki-tx-results { position:relative; margin-top:8px; background:var(--surface-alt); border:1px solid var(--edge); border-radius:var(--radius-sm); max-height:min(50vh,420px); overflow-y:auto; }
html.theme-ki .ki-tx-hit { padding:10px 13px; border-bottom:1px solid var(--edge); cursor:pointer; }
html.theme-ki .ki-tx-hit:last-child { border-bottom:none; }
html.theme-ki .ki-tx-hit:hover { background:var(--panel-3); }
html.theme-ki .ki-tx-hitnone { color:var(--muted); cursor:default; }
html.theme-ki .ki-tx-hitnone:hover { background:transparent; }
html.theme-ki .ki-tx-hitname { font-size:14px; color:var(--ink); }
html.theme-ki .ki-tx-hitmeta { font-size:11px; color:var(--muted); margin-top:2px; }

/* Selected item — tinted when it arrived from a suggestion */
html.theme-ki .ki-tx-selected { display:flex; align-items:center; justify-content:space-between; gap:14px; }
html.theme-ki .ki-tx-selected.is-suggested { background:rgba(95,182,196,.05); }
html.theme-ki .ki-tx-eyebrow { font-size:10px; font-weight:600; letter-spacing:.12em; text-transform:uppercase; color:var(--area); display:inline-flex; align-items:center; gap:7px; margin-bottom:8px; }
html.theme-ki .ki-tx-eyebrow .ki-dot { width:5px; height:5px; border-radius:50%; background:var(--area); }
html.theme-ki .ki-tx-selname { font-family:var(--display); font-size:22px; font-weight:600; letter-spacing:-0.02em; color:var(--ink); line-height:1.15; }
html.theme-ki .ki-tx-selmeta { font-size:12px; color:var(--muted); margin-top:5px; }
html.theme-ki .ki-tx-clear { font-size:12px; font-weight:600; color:var(--ink-2); background:var(--surface-alt); border:1px solid var(--edge); padding:8px 13px; border-radius:var(--radius-sm); cursor:pointer; font-family:inherit; flex:none; }
html.theme-ki .ki-tx-clear:hover { color:var(--ink); background:var(--panel-3); }

/* From → To */
html.theme-ki .ki-tx-fromto { display:grid; grid-template-columns:1fr auto 1fr; gap:14px; align-items:end; background:rgba(255,255,255,.02); }
html.theme-ki .ki-tx-fromto select { width:100%; padding:11px 12px; font-size:13.5px; font-family:inherit; color:var(--ink); background-color:var(--surface-alt); border:1px solid var(--edge); border-radius:var(--radius-sm); cursor:pointer; box-sizing:border-box; }
html.theme-ki .ki-tx-fromto select:focus-visible { outline:2px solid var(--accent); outline-offset:-1px; }
html.theme-ki .ki-tx-arrow { width:34px; height:34px; border-radius:50%; background:var(--area-soft); color:var(--area); display:grid; place-items:center; margin-bottom:3px; }

/* Honesty block — only for a suggested move with no minimum behind it */
html.theme-ki .ki-tx-reason { display:flex; gap:13px; align-items:flex-start; }
html.theme-ki .ki-tx-warncircle { width:30px; height:30px; border-radius:50%; background:var(--warn-soft); color:var(--warn); display:grid; place-items:center; flex:none; }
html.theme-ki .ki-tx-reasonhead { font-size:13.5px; font-weight:600; color:var(--ink); }
html.theme-ki .ki-tx-reasonbody { font-size:12.5px; line-height:1.55; color:var(--ink-2); margin-top:5px; }
html.theme-ki .ki-tx-reasonlink { display:inline-block; font-size:12px; font-weight:600; color:var(--area); text-decoration:none; margin-top:8px; }
html.theme-ki .ki-tx-reasonlink:hover { color:var(--ink); }

/* Per-size quantities. number inputs in a fixed grid track MUST carry
   min-width:0 + box-sizing:border-box — the UA min-content width (~117px)
   otherwise floors the grid item and overlaps the next column. */
html.theme-ki .ki-tx-sizeshead { display:flex; align-items:baseline; justify-content:space-between; gap:14px; margin-bottom:14px; flex-wrap:wrap; }
html.theme-ki .ki-tx-sizesnote { font-size:11.5px; color:var(--muted); }
html.theme-ki .ki-tx-sizegrid { display:grid; grid-template-columns:58px 1fr 96px 1fr; gap:14px; align-items:center; }
html.theme-ki .ki-tx-sizeheadrow { padding-bottom:8px; border-bottom:1px solid var(--edge); }
html.theme-ki .ki-tx-sizeheadrow span { font-size:10px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); }
html.theme-ki .ki-tx-c { text-align:center; }
html.theme-ki .ki-tx-sizerow { padding:10px 0; }
html.theme-ki .ki-tx-sz { font-size:12.5px; font-weight:600; color:var(--ink); }
html.theme-ki .ki-tx-stock { display:flex; align-items:center; gap:10px; min-width:0; }
html.theme-ki .ki-tx-stockn { font-size:12.5px; color:var(--ink-2); font-variant-numeric:tabular-nums; width:26px; text-align:right; flex:none; }
html.theme-ki .ki-tx-stockbar { flex:1; height:5px; border-radius:2px; background:rgba(255,255,255,.05); overflow:hidden; }
html.theme-ki .ki-tx-stockbar span { display:block; height:100%; border-radius:2px; background:var(--area); }
html.theme-ki .ki-tx-qty { min-width:0; box-sizing:border-box; width:100%; padding:9px 10px; font-size:14px; font-weight:600; font-variant-numeric:tabular-nums; text-align:center; font-family:inherit; color:var(--ink); background:var(--surface-alt); border:1px solid var(--edge); border-radius:var(--radius-sm); }
html.theme-ki .ki-tx-qty:focus-visible { outline:2px solid var(--accent); outline-offset:-1px; }
html.theme-ki .ki-tx-qty:disabled { opacity:.4; }
html.theme-ki .ki-tx-sr { font-size:12px; color:var(--muted); font-variant-numeric:tabular-nums; }
html.theme-ki .ki-tx-totals { display:grid; grid-template-columns:58px 1fr 96px 1fr; gap:14px; align-items:center; margin-top:12px; padding-top:12px; border-top:1px solid var(--edge); }
html.theme-ki .ki-tx-totlab { font-size:10px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); }
html.theme-ki .ki-tx-tot { font-size:12.5px; color:var(--ink-2); font-variant-numeric:tabular-nums; }
html.theme-ki .ki-tx-movetotal { font-family:var(--display); font-size:20px; font-weight:600; font-variant-numeric:tabular-nums; color:var(--ink); text-align:center; }

/* Note + CTA */
html.theme-ki .ki-tx-notein { width:100%; box-sizing:border-box; padding:11px 13px; font-size:13.5px; font-family:inherit; color:var(--ink); background:var(--surface-alt); border:1px solid var(--edge); border-radius:var(--radius-sm); }
html.theme-ki .ki-tx-notein:focus-visible { outline:2px solid var(--accent); outline-offset:-1px; }
html.theme-ki .ki-tx-ctarow { display:flex; gap:10px; margin-top:14px; }
html.theme-ki .ki-tx-cta { flex:1; font-size:14px; font-weight:600; font-family:inherit; color:var(--on-navy); background:linear-gradient(180deg, var(--accent-deep) 0%, var(--area) 100%); border:none; padding:14px 22px; border-radius:var(--radius-sm); cursor:pointer; box-shadow:inset 0 1px 0 rgba(255,255,255,0.18), var(--shadow-sm); }
html.theme-ki .ki-tx-cta:hover:not(:disabled) { filter:brightness(1.06); }
html.theme-ki .ki-tx-cta:active:not(:disabled) { transform:translateY(1px); }
html.theme-ki .ki-tx-cta:disabled { opacity:.45; cursor:default; }
html.theme-ki .ki-tx-cancel { display:inline-flex; align-items:center; font-size:13px; font-weight:600; color:var(--ink-2); background:var(--surface-alt); border:1px solid var(--edge); padding:14px 20px; border-radius:var(--radius-sm); text-decoration:none; }
html.theme-ki .ki-tx-cancel:hover { color:var(--ink); background:var(--panel-3); }
html.theme-ki .ki-tx-caption { font-size:11.5px; color:var(--muted); margin-top:10px; }
html.theme-ki .ki-tx-empty { padding:36px 22px; text-align:center; color:var(--muted); font-size:13px; border-top:1px solid var(--edge); }

/* Queue card */
html.theme-ki .ki-tx-queue { margin-top:18px; background:var(--surface); border:1px solid var(--edge); border-radius:var(--radius); padding:16px 20px; }
html.theme-ki .ki-tx-queuehead { display:flex; align-items:baseline; justify-content:space-between; gap:14px; font-size:13px; color:var(--ink); font-weight:600; flex-wrap:wrap; }
html.theme-ki .ki-tx-queuehead a { font-size:12px; font-weight:600; color:var(--area); text-decoration:none; }
html.theme-ki .ki-tx-queuehead a:hover { color:var(--ink); }
html.theme-ki .ki-tx-queuepills { display:flex; flex-wrap:wrap; gap:8px; margin-top:11px; }
html.theme-ki .ki-tx-queuepill { font-size:11.5px; font-weight:600; color:var(--area); background:var(--area-soft); padding:5px 11px; border-radius:999px; text-decoration:none; }
html.theme-ki .ki-tx-queuepill:hover { color:var(--ink); background:rgba(95,182,196,.28); }

@media (max-width:640px) {
  html.theme-ki .ki-tx-fromto { grid-template-columns:1fr; }
  html.theme-ki .ki-tx-arrow { display:none; }
  html.theme-ki .ki-tx-sizegrid, html.theme-ki .ki-tx-totals { grid-template-columns:44px 1fr 72px 1fr; gap:8px; }
}


/* ── The themed site listbox (rail) ───────────────────────────────────────
   From the Today Dashboard handoff: "custom listbox — NOT <select>. The
   native popup renders with OS chrome and cannot be themed; it broke the
   dark theme." Panel #0b2028, 1px --edge-2, radius 10, selected row tinted
   --area-soft with a check, caret rotates 180°. The native select stays in
   the DOM as the no-JS fallback (ki_listbox.js). All selectors live under
   html.theme-ki — the light theme keeps the native control. */
html.theme-ki .ki-listbox { position: relative; }
html.theme-ki .ki-listbox-native { display: none; }
html.theme-ki .ki-listbox-btn {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; gap: 8px; padding: 8px 11px;
  background: rgba(255,255,255,.03); color: var(--ink);
  border: 1px solid var(--edge); border-radius: 9px;
  font: inherit; font-size: 13.5px; cursor: pointer; text-align: left;
}
html.theme-ki .ki-listbox-btn:hover { border-color: var(--edge-2); }
html.theme-ki .ki-listbox-btn:focus-visible { outline: 2px solid var(--area); outline-offset: 2px; }
html.theme-ki .ki-listbox-caret { display: inline-flex; color: var(--muted); transition: transform 160ms ease; }
html.theme-ki .ki-listbox-btn[aria-expanded="true"] .ki-listbox-caret { transform: rotate(180deg); }
html.theme-ki .ki-listbox-panel {
  position: absolute; z-index: 40; top: calc(100% + 6px); left: 0; right: 0;
  padding: 5px; border-radius: 10px; background: #0b2028;
  border: 1px solid var(--edge-2); box-shadow: 0 12px 30px rgba(0,0,0,.55);
  animation: ki-listbox-fade 120ms ease both;
}
@keyframes ki-listbox-fade { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  html.theme-ki .ki-listbox-panel { animation: none; }
  html.theme-ki .ki-listbox-caret { transition: none; }
}
html.theme-ki .ki-listbox-opt {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; gap: 8px; padding: 8px 10px; border: 0; border-radius: 7px;
  background: transparent; color: var(--ink);
  font: inherit; font-size: 13.5px; cursor: pointer; text-align: left;
}
html.theme-ki .ki-listbox-opt:hover { background: rgba(255,255,255,.06); }
html.theme-ki .ki-listbox-opt:focus-visible { outline: 2px solid var(--area); outline-offset: -2px; }
html.theme-ki .ki-listbox-opt[aria-selected="true"] { background: var(--area-soft); }
html.theme-ki .ki-listbox-tick { display: inline-flex; color: var(--area); }

/* ── Which ground did you mean? ───────────────────────────────────────────
   Shown when a scanned code resolves to more than one site (see
   static/js/site_choice.js). Self-contained block — every selector here is
   prefixed .kl-sitechoice and no rule reaches outside it, because a stray
   comma in this file once unstyled every text input in the product. */
.kl-sitechoice {
  margin-top: 10px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-2, var(--surface));
}
.kl-sitechoice-q {
  font-family: inherit;
  font-size: 13px;
  color: var(--ink);
  margin-bottom: 10px;
}
.kl-sitechoice-opts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.kl-sitechoice-btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  min-width: 140px;
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}
.kl-sitechoice-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.kl-sitechoice-qty {
  font-family: inherit;
  font-size: 11px;
  font-weight: 400;
  color: var(--muted);
}

