/* 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;
  /* 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);
  --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],
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; font-size:16px; padding:4px; }
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{
  position:relative; width:clamp(86px,9vw,116px); height:auto; display:block; border-radius:50%;
  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; }
.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); }

/* 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; }

/* ---- 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); }
