:root {
  /* Typography */
  --text-xs: 0.6875rem;    /* 11px */
  --text-sm: 0.75rem;      /* 12px */
  --text-base: 0.8125rem;  /* 13px */
  --text-md: 0.875rem;     /* 14px */
  --text-lg: 1rem;         /* 16px */
  --text-xl: 1.25rem;      /* 20px */
  --text-2xl: 1.5rem;      /* 24px */

  /* Font Weights */
  --weight-normal: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* Spacing (4px base) */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;

  /* The smallest square a thumb reliably hits (WCAG 2.5.5, Apple HIG).
     Interactive elements floor their box at this on touch screens; it is a
     hit-area size, not spacing, so it has its own name (TEA-606). */
  --touch-target: 44px;

  /* Border Radius */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --radius-full: 50%;
  /* A capsule, not a circle: the floating nav pill, the tab capsule inside it,
     and the small crown buttons. --radius-full is 50% and rounds a square. */
  --radius-pill: 999px;

  /* Colors — Dark Mode (default) */
  --color-bg: #0d1117;
  --color-bg-card: #161b22;
  --color-surface: #1f2937;
  --color-border: #21262d;
  --color-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);

  /* The matte behind a photo that does not fill its square — the gutter the
     crop dialog paints when a parent zooms all the way out to contain. It is
     deliberately NOT redefined for light mode: the value is baked into the
     exported JPEG, which is then shown to other people in whichever theme
     they use, so it has to be one mid neutral that reads against both. */
  --color-photo-matte: #9aa3af;

  /* The plate a team's uploaded logo sits on (TEA-968). Logos are drawn for
     white paper -- navy wordmarks, transparent PNGs with dark ink -- so the
     plate is white in BOTH themes and deliberately not redefined for light
     mode, exactly like the photo matte above. The same value is baked into
     the JPEG fallback the crop dialog exports when a PNG is too big. */
  --color-logo-plate: #ffffff;

  --color-text: #e6edf3;
  --color-text-body: #e6edf3;
  --color-text-muted: #8b949e;

  /* --- Buttons (TEA-859) -------------------------------------------------
     The primary button is NOT the accent. Red is reserved for the active tab
     underline, the active nav indicator, prose links, status dots and badges.
     The primary is the navy in light mode and, the way Linear and Vercel do
     it, a near-white fill on the dark ground in dark mode -- the old navy
     fill was 1.21:1 against a dark page and read as a hole.
     The secondary is a soft fill, not a hollow outline: same box, same
     radius, one step quieter. Both inks clear 4.5:1 on their own fill. */
  --color-btn-primary: #e6edf3;
  --color-btn-primary-hover: #ffffff;
  --color-on-btn-primary: #0d1117;
  --color-btn-secondary: #262c35;
  --color-btn-secondary-hover: #313842;
  --color-on-btn-secondary: #e6edf3;

  --color-accent: #dc3545;
  --color-accent-hover: #e8525e;
  --color-accent-subtle: rgba(220, 53, 69, 0.1);
  /* The focus ring. Never the accent: a red border on a field you just
     clicked reads as a validation error (Matt, 2026-09-19). */
  --color-focus: #7aa7dd;
  --color-focus-subtle: rgba(122, 167, 221, 0.25);
  /* The foreground that sits ON the accent — a filled badge, a step number. */
  --color-on-accent: #ffffff;
  --color-primary: #1c2333;
  --color-primary-light: #1f2b3d;

  --color-success: #34d399;
  --color-success-subtle: #0f2922;
  --color-warning: #fbbf24;
  --color-warning-subtle: #2d2410;
  --color-error: #f87171;
  --color-error-subtle: #3b1520;
  --color-info: #a5b4fc;
  --color-info-subtle: #1e1b4b;

  /* Per-athlete identity (migration 117). Eight hues a family can tell
     apart at a glance, assigned per child and reused for a coach's own
     teams. Never semantic — these say "whose", not "how bad". The -on token
     is the foreground that sits on top of any of them. */
  --color-athlete-1: #60a5fa;
  --color-athlete-2: #34d399;
  --color-athlete-3: #fbbf24;
  --color-athlete-4: #c4b5fd;
  --color-athlete-5: #f9a8d4;
  --color-athlete-6: #5eead4;
  --color-athlete-7: #bef264;
  --color-athlete-8: #fdba74;
  --color-athlete-on: #0d1117;
  --color-athlete-1-subtle: rgba(96, 165, 250, 0.14);
  --color-athlete-2-subtle: rgba(52, 211, 153, 0.14);
  --color-athlete-3-subtle: rgba(251, 191, 36, 0.14);
  --color-athlete-4-subtle: rgba(196, 181, 253, 0.14);
  --color-athlete-5-subtle: rgba(249, 168, 212, 0.14);
  --color-athlete-6-subtle: rgba(94, 234, 212, 0.14);
  --color-athlete-7-subtle: rgba(190, 242, 100, 0.14);
  --color-athlete-8-subtle: rgba(253, 186, 116, 0.14);
  /* League colours (TEA-569, migration 146). A park gives each league a
     colour and the Park Schedule paints its games with it, so a director can
     find a league in a Sunday without reading a word. Drew named eighteen in
     the ticket and these are those eighteen: the keys are his words, and the
     -on token is the text that goes on top, chosen for 4.5:1 against the
     fill. Dark mode lightens the dark half of the palette -- a navy card on a
     near-black page is a hole, not a colour. Nothing else may use these: they
     are identity, like the athlete colours above, not status. */
  --color-league-navy: #4c6ef5;
  --color-league-navy-on: #0d1117;
  --color-league-royal: #3b82f6;
  --color-league-royal-on: #0d1117;
  --color-league-teal: #2dd4bf;
  --color-league-teal-on: #0d1117;
  --color-league-green: #34d399;
  --color-league-green-on: #0d1117;
  --color-league-yellow: #facc15;
  --color-league-yellow-on: #0d1117;
  --color-league-orange: #fb923c;
  --color-league-orange-on: #0d1117;
  --color-league-maroon: #c2565f;
  --color-league-maroon-on: #0d1117;
  --color-league-purple: #a78bfa;
  --color-league-purple-on: #0d1117;
  --color-league-pink: #f9a8d4;
  --color-league-pink-on: #0d1117;
  --color-league-slate: #94a3b8;
  --color-league-slate-on: #0d1117;
  --color-league-light-blue: #bae6fd;
  --color-league-light-blue-on: #0d1117;
  --color-league-light-green: #bbf7d0;
  --color-league-light-green-on: #0d1117;
  --color-league-light-orange: #fed7aa;
  --color-league-light-orange-on: #0d1117;
  --color-league-light-red: #fecaca;
  --color-league-light-red-on: #0d1117;
  --color-league-light-purple: #ddd6fe;
  --color-league-light-purple-on: #0d1117;
  --color-league-light-gray: #d5dbe3;
  --color-league-light-gray-on: #0d1117;
  --color-league-beige: #e3d5b7;
  --color-league-beige-on: #0d1117;
  --color-league-white: #f1f5f9;
  --color-league-white-on: #0d1117;

  /* Data Visualization */
  --color-chart-1: #34d399;  /* green — revenue, positive metrics */
  --color-chart-2: #60a5fa;  /* blue — secondary data series */
  --color-chart-3: #fbbf24;  /* amber — tertiary, comparison */
  --color-chart-muted: #374151;  /* prior year, inactive series */

  /* Lifecycle Stage */
  --color-stage-complete: #10b981;
  --color-stage-current: #6366f1;
  --color-stage-future: #21262d;

  /* Status chips — specific bg/text/border triplets that don't map to the
     generic semantic tokens. Consumed by .status-count-badge (styles.css). */
  --status-all-bg: #252540;
  --status-all-text: #9ca3af;
  --status-all-border: #3d3d5c;
  --status-pending-bg: #1a2744;
  --status-pending-text: #60a5fa;
  --status-pending-border: #2a3f66;
  --status-pending-approval-bg: #2d2410;
  --status-pending-approval-text: #fbbf24;
  --status-pending-approval-border: #4d3d1a;
  --status-completed-bg: #0f2922;
  --status-completed-text: #34d399;
  --status-completed-border: #1a4035;
  --status-waitlisted-bg: #1f1a35;
  --status-waitlisted-text: #a78bfa;
  --status-waitlisted-border: #332d55;
  --status-cancelled-bg: #1f1f2e;
  --status-cancelled-text: #6b7280;
  --status-cancelled-border: #2d2d44;
  --status-denied-bg: #2a1215;
  --status-denied-text: #f87171;
  --status-denied-border: #441a1e;

  /* Sidebar — Dark Mode */
  --sidebar-bg: var(--color-bg);
  --sidebar-text: #8b949e;
  --sidebar-text-active: #e6edf3;
  --sidebar-active-bg: rgba(220, 53, 69, 0.1);
  --sidebar-active-icon: #dc3545;
  --sidebar-hover: var(--color-surface);
  --sidebar-border: #21262d;
  --sidebar-section-label: #484f58;

  /* Sidebar dimensions */
  --sidebar-width: 220px;
  --topbar-height: 44px;
}

[data-theme="light"] {
  --color-bg: #f8fafc;
  --color-bg-card: #ffffff;
  --color-surface: #f1f5f9;
  --color-border: #e2e8f0;
  --color-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);

  --color-text: #0f172a;
  --color-text-body: #334155;
  --color-text-muted: #64748b;

  --color-btn-primary: #1e3a5f;
  --color-btn-primary-hover: #2d4a6f;
  --color-on-btn-primary: #ffffff;
  --color-btn-secondary: #e9ecf0;
  --color-btn-secondary-hover: #dde2e8;
  --color-on-btn-secondary: #0f172a;

  --color-accent: #c22532;
  --color-accent-hover: #a91d29;
  --color-accent-subtle: rgba(194, 37, 50, 0.08);
  --color-focus: #3b6ea5;
  --color-focus-subtle: rgba(59, 110, 165, 0.18);
  --color-on-accent: #ffffff;
  --color-primary: #1e3a5f;
  --color-primary-light: #2d4a6f;

  --color-success: #047857;
  --color-success-subtle: #ecfdf5;
  --color-warning: #92400e;
  --color-warning-subtle: #fffbeb;
  --color-error: #b91c1c;
  --color-error-subtle: #fef2f2;
  --color-info: #4338ca;
  --color-info-subtle: #eef2ff;

  /* Per-athlete identity: every one of these carries white text at 4.5:1 or
     better, and none of them is the accent red. */
  --color-athlete-1: #1d4ed8;
  --color-athlete-2: #047857;
  --color-athlete-3: #b45309;
  --color-athlete-4: #6d28d9;
  --color-athlete-5: #be185d;
  --color-athlete-6: #0f766e;
  --color-athlete-7: #4d7c0f;
  --color-athlete-8: #9a3412;
  --color-athlete-on: #ffffff;
  --color-athlete-1-subtle: rgba(29, 78, 216, 0.10);
  --color-athlete-2-subtle: rgba(4, 120, 87, 0.10);
  --color-athlete-3-subtle: rgba(180, 83, 9, 0.10);
  --color-athlete-4-subtle: rgba(109, 40, 217, 0.10);
  --color-athlete-5-subtle: rgba(190, 24, 93, 0.10);
  --color-athlete-6-subtle: rgba(15, 118, 110, 0.10);
  --color-athlete-7-subtle: rgba(77, 124, 15, 0.10);
  --color-athlete-8-subtle: rgba(154, 52, 18, 0.10);
  /* League colours: the same eighteen, at light-mode weight. The strong half
     carries white text, the pale half carries ink. */
  --color-league-navy: #1e3a8a;
  --color-league-navy-on: #ffffff;
  --color-league-royal: #2563eb;
  --color-league-royal-on: #ffffff;
  --color-league-teal: #0f766e;
  --color-league-teal-on: #ffffff;
  --color-league-green: #166534;
  --color-league-green-on: #ffffff;
  --color-league-yellow: #fde047;
  --color-league-yellow-on: #0f172a;
  --color-league-orange: #ea580c;
  --color-league-orange-on: #ffffff;
  --color-league-maroon: #7f1d1d;
  --color-league-maroon-on: #ffffff;
  --color-league-purple: #6d28d9;
  --color-league-purple-on: #ffffff;
  --color-league-pink: #f9a8d4;
  --color-league-pink-on: #0f172a;
  --color-league-slate: #334155;
  --color-league-slate-on: #ffffff;
  --color-league-light-blue: #bfdbfe;
  --color-league-light-blue-on: #0f172a;
  --color-league-light-green: #bbf7d0;
  --color-league-light-green-on: #0f172a;
  --color-league-light-orange: #fed7aa;
  --color-league-light-orange-on: #0f172a;
  --color-league-light-red: #fecaca;
  --color-league-light-red-on: #0f172a;
  --color-league-light-purple: #ddd6fe;
  --color-league-light-purple-on: #0f172a;
  --color-league-light-gray: #e2e8f0;
  --color-league-light-gray-on: #0f172a;
  --color-league-beige: #e7ddc7;
  --color-league-beige-on: #0f172a;
  --color-league-white: #ffffff;
  --color-league-white-on: #0f172a;

  --color-chart-1: #047857;  /* green — darker for light bg */
  --color-chart-2: #2563eb;  /* blue */
  --color-chart-3: #d97706;  /* amber */
  --color-chart-muted: #d1d5db;  /* prior year, inactive */

  --color-stage-complete: #047857;
  --color-stage-current: #4338ca;
  --color-stage-future: #e2e8f0;

  --status-all-bg: #f3f4f6;
  --status-all-text: #4b5563;
  --status-all-border: #d1d5db;
  --status-pending-bg: #eff6ff;
  --status-pending-text: #1e40af;
  --status-pending-border: #bfdbfe;
  --status-pending-approval-bg: #fffbeb;
  --status-pending-approval-text: #92400e;
  --status-pending-approval-border: #fde68a;
  --status-completed-bg: #ecfdf5;
  --status-completed-text: #065f46;
  --status-completed-border: #a7f3d0;
  --status-waitlisted-bg: #f5f3ff;
  --status-waitlisted-text: #5b21b6;
  --status-waitlisted-border: #ddd6fe;
  --status-cancelled-bg: #f3f4f6;
  --status-cancelled-text: #6b7280;
  --status-cancelled-border: #d1d5db;
  --status-denied-bg: #fef2f2;
  --status-denied-text: #991b1b;
  --status-denied-border: #fecaca;

  --sidebar-bg: #1e3a5f;
  --sidebar-text: rgba(255, 255, 255, 0.6);
  --sidebar-text-active: #ffffff;
  --sidebar-active-bg: rgba(255, 255, 255, 0.12);
  --sidebar-active-icon: #ffffff;
  --sidebar-hover: rgba(255, 255, 255, 0.08);
  --sidebar-border: rgba(255, 255, 255, 0.1);
  --sidebar-section-label: rgba(255, 255, 255, 0.35);
}

/* --- The installed app's crown and floating nav (TEA-637) ----------------
   The shell is light-only, so these sit outside the theme blocks and resolve
   once. --app-crown-color is the ONE value a park can change; the server
   overrides it with the park's hex and everything else is derived from it.
   No --color-* token is redefined here: the park owns the chrome, the app
   owns the meaning, so a park choosing red never touches --color-accent. */
.app-shell-root {
  /* Team Captain navy. --color-primary IS the navy, and a ground is exactly
     what it is for -- nothing navy below becomes text, an icon or a border. */
  --app-crown-color: var(--color-primary);

  /* Both ink pairs live here; crownInk() on the server decides which the
     crown wears, by stamping data-crown-ink on <html>. */
  --app-ink-on-dark: #ffffff;
  --app-ink-on-dark-muted: rgba(255, 255, 255, 0.68);
  --app-ink-on-dark-fill: rgba(255, 255, 255, 0.16);
  --app-ink-on-dark-hairline: rgba(255, 255, 255, 0.18);
  /* Home's rule under the ask bar: the crown's ink at 20% (2026-09-29). */
  --app-ink-on-dark-rule: rgba(255, 255, 255, 0.2);
  /* A cancellation's reason on the crown's own ground (Next up, 2026-09-29):
     a red that reads on navy, and the ordinary error red on a pale crown. */
  --app-ink-on-dark-alert: #ffb3b8;
  --app-ink-on-light: #0f172a;
  --app-ink-on-light-muted: rgba(15, 23, 42, 0.62);
  --app-ink-on-light-fill: rgba(15, 23, 42, 0.08);
  --app-ink-on-light-hairline: rgba(15, 23, 42, 0.12);
  --app-ink-on-light-rule: rgba(15, 23, 42, 0.2);
  --app-ink-on-light-alert: var(--color-error);

  --app-nav-shadow: 0 8px 28px rgba(15, 23, 42, 0.20);
  /* 12px, not 16: the bar's side inset is the width every tab slot pays
     for, and five tabs at 360px need it (Josh, 2026-09-28). */
  --app-nav-inset: var(--space-3);
  --app-nav-height: 56px;
  /* The active tab's corner (Josh, 2026-09-28). Not a capsule: a tab slot is
     ~60px wide at 360px with five tabs, and a capsule's round ends cut into
     "Messages" -- the label spilled past the red. 16px keeps the corner
     inside the bar's own curve (58px tall, 4px padding) and clears a label
     that sits 6px off the bottom edge. */
  --app-tab-radius: 16px;
  /* The crown's own height, without the status-bar inset. One value rather
     than whatever the tallest child happens to be, so anything that has to
     sit BELOW the crown -- a sticky sub-tab strip, a scroll anchor -- has a
     number to offset by (TEA-637). It also stops the crown changing height
     between a page with a back chevron (44px) and one with a logo (28px). */
  --app-crown-height: 56px;
  /* The gutter TC's mark sits in on the right of the pill (TEA-665). One
     number, so the reserved padding and the mark can never disagree. */
  --app-tc-size: 48px;

  /* The browser preview of the app view (TEA-771). 560px is a phone-shaped
     column on purpose: every app screen -- the hero, the list rows, the
     floating tab pill -- is laid out for a phone, and stretching them to a
     900px page would be designing a new surface instead of previewing the
     one we have. The strip's height is a token because the sticky crown
     offsets by it. */
  --app-preview-width: 560px;
  --app-preview-strip-height: 44px;
}
