/* RallyReady — design system + base styles.
   "Courtside": an athletic-editorial look. A confident grotesque display face
   (Bricolage Grotesque) over a clean humanist body (Hanken Grotesk), ink
   outlines, and a tactile HARD offset shadow (no blur) so cards and buttons read
   as physical playbook stickers — a deliberate point of view, not a default
   template. Built on a two-layer token system (brand primitives -> semantic
   tokens), tinted neutrals (no pure gray/black), an OKLCH dark-surface scale,
   accessible contrast in both themes, and hover effects only on hover devices.

   Theming: <html data-theme="light|dark"> is set before paint by a tiny inline
   script (see index.html) and kept in sync by js/app.js. Only the SEMANTIC
   layer is redefined for dark mode; brand primitives never change. */

/* ---------- Type: self-hosted variable fonts (offline-first) ----------------
   Bricolage Grotesque = a contemporary, crafted grotesque used for the display
   layer (wordmark, headings, big numbers); Hanken Grotesk = a clean humanist
   grotesque for body + UI. Both are single variable woff2 files in /fonts, so
   they're precached by the service worker and the app stays fully offline.
   font-display:swap means text paints immediately in the system fallback and
   upgrades when the face arrives — no blank text, no layout dependence. */
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("../fonts/bricolage-grotesque.var.woff2") format("woff2");
  font-weight: 200 800;
  font-stretch: 75% 100%;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Hanken Grotesk";
  src: url("../fonts/hanken-grotesk.var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ---------- Brand primitives (exact values from the brief; never themed) -- */
  --coral: #FF6B35;   /* primary actions / energy */
  --teal:  #00C2A8;   /* secondary / success */
  --sun:   #FFD23F;   /* accent / highlights */
  --navy:  #1B2A4A;   /* legacy ink (kept for fixed-hue badge text that needs AA) */
  --ink:   #16181D;   /* near-black structural line + tactile shadow colour */
  --cloud: #F2ECE1;   /* warm newsprint app background */
  --white: #FFFFFF;   /* cards */
  --slate: #5E6675;   /* muted text — navy-tinted; clears 4.5:1 on bg + both surfaces */
  --i-easy:  #00C2A8;
  --i-mid:   #FFD23F;
  --i-hard:  #FF6B35;
  --i-taper: #8C7AE6;

  /* ---------- Shape / depth / spacing / type / layout (theme-independent) ---
     "Courtside": an athletic-editorial system. Confident grotesque display type,
     ink outlines, and a tactile HARD offset shadow (no blur) so cards/buttons read
     as physical playbook stickers rather than soft generic SaaS panels. */
  --radius-card: 14px;
  --radius-input: 10px;
  --radius-pill: 999px;
  --border-w: 2px;                 /* structural outline weight (the brutalist line) */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --fs-title: 32px;   /* modular-ish scale (~1.25 steps) for clear hierarchy */
  --fs-h2: 24px;
  --fs-h3: 20px;
  --fs-body: 16px;
  --fs-sm: 14px;
  --fs-xs: 12px;
  --app-max: 480px;
  --appbar-h: 56px;
  --tabbar-h: 64px;
  --tap-min: 48px;
  /* Self-hosted variable fonts (see @font-face above) with a full system fallback,
     so the app still renders instantly and works fully offline if a face is slow. */
  --font-stack: "Hanken Grotesk", -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-display: "Bricolage Grotesque", "Hanken Grotesk", -apple-system, "Segoe UI", Roboto, sans-serif;
  --z-sticky: 200;
  --ease: cubic-bezier(0.2, 0, 0, 1);   /* smooth; deliberately no bounce */

  /* ---------- Semantic tokens — LIGHT (default) ---------------------------- */
  --bg: var(--cloud);
  --surface: var(--white);
  --surface-2: #F7F0E6;            /* warm-tinted raised fill */
  --text: var(--ink);
  --text-muted: var(--slate);      /* ≥4.7:1 on bg, white, and surface-2 — passes AA */
  --line: var(--ink);              /* structural 2px outlines on cards/inputs/buttons */
  --border: #D9CDBC;               /* warm internal hairline (row dividers, sub-cards) */
  --field-border: var(--ink);      /* form controls wear the bold outline */
  --primary: var(--coral);
  --on-primary: var(--ink);        /* near-black on coral ≈ 5.6:1 */
  --primary-tint: #FFE3D5;         /* solid light coral (avoids alpha) */
  --accent: var(--teal);
  --focus: #D24E12;                /* deepened coral, ≥ 3:1 on light bg (rings/UI) */
  --link: #B8420C;                 /* deeper coral for TEXT links: ≥ 4.5:1 on every light surface */
  --shadow-color: var(--ink);
  --shadow: 3px 3px 0 var(--shadow-color);   /* hard offset — the signature depth */
  --shadow-bar: none;
  --dot: rgba(22, 24, 29, 0.07);   /* desktop backdrop dot-grid ink */

  --appbar-bg: var(--coral);       /* solid, flat, branded band (no gradient) */
  --appbar-fg: var(--ink);
  --overlay: rgba(22, 24, 29, 0.10);   /* interactive hover wash (alpha ok) */
  --ball-fill: var(--white);
  --ball-stroke: var(--ink);

  --tab-surface: var(--white);
  --tab-inactive: var(--slate);
  --tab-active: var(--ink);        /* active icon is ink on a coral-tint pill marker */
  --tab-active-label: var(--ink);

  /* Desktop page backdrop behind the centered app column: a warm tone step down
     from --bg plus a faint ink dot-grid (see the desktop frame block), so the
     column reads as a framed "playbook" sitting on paper, not floating in a void. */
  --page-bg: #EBE3D5;
}

/* ---------- Semantic tokens — DARK ----------------------------------------
   Impeccable: dark mode is not inverted light mode. Depth comes from a scale of
   progressively lighter surfaces (no shadows), neutrals are tinted toward the
   brand's navy hue, accents are slightly softened, and text is a near-white
   (never pure white). All values are OKLCH for perceptually even steps. */
:root[data-theme="dark"] {
  --bg: oklch(17% 0.020 264);
  --surface: oklch(22% 0.024 264);
  --surface-2: oklch(27% 0.028 264);
  --text: oklch(95% 0.008 264);
  --text-muted: oklch(75% 0.020 264);
  --line: oklch(58% 0.030 264);         /* a visible mid line carries the outline in dark */
  --border: oklch(34% 0.030 264);
  --field-border: oklch(58% 0.030 264);
  --primary: oklch(74% 0.160 42);       /* softened coral */
  --on-primary: oklch(18% 0.030 264);
  --primary-tint: oklch(32% 0.070 42);
  --accent: oklch(78% 0.120 182);
  --focus: oklch(80% 0.150 45);         /* light coral, ≥ 3:1 on dark */
  --link: oklch(80% 0.150 45);          /* same light coral: high-contrast text links on dark surfaces */
  /* Neo-brutalist depth survives in dark via a near-black hard offset (darker than
     every surface) instead of a blurred drop shadow. */
  --shadow-color: oklch(0% 0 0);
  --shadow: 3px 3px 0 var(--shadow-color);
  --shadow-bar: none;
  --dot: rgba(255, 255, 255, 0.05);

  --appbar-bg: oklch(21% 0.025 264);
  --appbar-fg: var(--text);
  --overlay: rgba(255, 255, 255, 0.10);
  --ball-fill: oklch(74% 0.160 42);     /* coral ball pops on the dark header */
  --ball-stroke: oklch(18% 0.030 264);

  --tab-surface: oklch(20% 0.022 264);
  --tab-inactive: oklch(74% 0.020 264);
  --tab-active: var(--text);
  --tab-active-label: var(--text);

  /* Darker than --bg so the app column floats above the page on desktop (in dark,
     elevation reads as the column being lighter than the backdrop behind it). */
  --page-bg: oklch(12% 0.018 264);
}

/* ------------------------------------------------------------------ Reset -- */
*,
*::before,
*::after { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

body {
  font-family: var(--font-stack);
  color: var(--text);
  background: var(--bg);
  line-height: 1.5;
  font-size: var(--fs-body);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

button { font-family: inherit; }
a { color: inherit; }
img, svg { display: block; }

/* Keyboard focus only (Impeccable): hide for mouse/touch, show for keyboard. */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 6px;
}

/* --------------------------------------------------------------- Headings -- */
h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
}
h1 { font-size: var(--fs-title); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }

.muted { color: var(--text-muted); }
.center { text-align: center; }

/* ------------------------------------------------------- App header (top) -- */
.appbar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  width: 100%;
  max-width: var(--app-max);
  margin: 0 auto;
  min-height: var(--appbar-h);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  padding-top: calc(var(--sp-2) + env(safe-area-inset-top));
  background: var(--appbar-bg);
  border-bottom: var(--border-w) solid var(--line);
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}

.brand { display: flex; align-items: center; gap: var(--sp-2); }
.brand__ball { transform: rotate(-8deg); }   /* a touch of athletic motion */
.brand__ball .ball-face { fill: var(--ball-fill); stroke: var(--ball-stroke); stroke-width: 2.5; }
.brand__ball .ball-seam { fill: none; stroke: var(--ball-stroke); stroke-width: 2.5; stroke-linecap: round; }
.brand__name {
  font-family: var(--font-display);
  font-size: 25px;
  font-weight: 800;
  color: var(--appbar-fg);
  letter-spacing: -0.035em;
}

/* Theme toggle — sits at the far right of the header. */
.theme-toggle {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-min);
  height: var(--tap-min);
  border: none;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--appbar-fg);
  cursor: pointer;
}
.theme-toggle svg { width: 24px; height: 24px; }
.theme-toggle .icon-sun { display: none; }     /* light mode shows the moon */
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* Language flag toggle — a two-flag pill (US / RO) at the right of the header,
   just before the theme toggle. Pushes the toggle group to the right; the theme
   toggle then only needs a small gap from it. */
.lang-toggle {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.18);
}
.lang-toggle ~ .theme-toggle { margin-left: var(--sp-1); }
.lang-opt {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: none;
  cursor: pointer;
  padding: 5px 9px;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--appbar-fg);
  font-family: inherit;
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0.02em;
  opacity: 0.62;
  transition: opacity 0.15s var(--ease), background 0.15s var(--ease);
}
.lang-opt:hover { opacity: 0.85; }
.lang-opt.is-on {
  opacity: 1;
  background: rgba(255, 255, 255, 0.95);
  color: #141e33;
}
.lang-opt .flag {
  display: block;
  width: 22px;
  height: 15px;
  border-radius: 2px;
}

/* ----------------------------------------------------------- Screen area -- */
#screen {
  width: 100%;
  max-width: var(--app-max);
  margin: 0 auto;
  padding: var(--sp-5) var(--sp-4) 0;
  padding-bottom: calc(var(--tabbar-h) + max(env(safe-area-inset-bottom), var(--sp-2)) + var(--sp-5));
  min-height: calc(100vh - var(--appbar-h));
  /* The content column carries the app background so that, on desktop, the area
     OUTSIDE the column (--page-bg) frames it. On mobile this equals --bg, so it's
     a no-op there. */
  background: var(--bg);
}

.screen-head { margin-bottom: var(--sp-4); }
/* Every screen title wears a coral "spine" — a small editorial brand signature
   that ties the screens together and reads as deliberate art-direction. */
.screen-title {
  position: relative;
  font-size: var(--fs-title);
  padding-left: 16px;
}
.screen-title::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.14em;
  bottom: 0.14em;
  width: 6px;
  border-radius: var(--radius-pill);
  background: var(--primary);
}
.screen-title:focus { outline: none; }   /* programmatic focus, no visible ring */
.screen-sub { color: var(--text-muted); margin-top: var(--sp-1); }

/* ---------------------------------------------------------------- Cards --- */
.card {
  background: var(--surface);
  border: var(--border-w) solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
  padding: var(--sp-5);
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.card + .card { margin-top: var(--sp-4); }
.card > h2, .card > h3 { margin-bottom: var(--sp-2); }

.empty { text-align: center; }
.empty h2 { margin-bottom: var(--sp-2); }
.empty p { margin: 0 auto; max-width: 32ch; }

/* ---- Collapsible disclosure card (shared; RR.ui.disclosure) --------------- */
.disclosure { padding: 0; overflow: hidden; }
.disclosure__toggle {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  width: 100%; min-height: var(--tap-min); padding: var(--sp-4) var(--sp-5);
  background: transparent; border: none; cursor: pointer; text-align: left; color: var(--text);
}
.disclosure__title { font-size: var(--fs-h3); font-weight: 800; letter-spacing: -0.015em; }
.disclosure__chev { flex: none; color: var(--text-muted); transition: transform 0.18s var(--ease); }
.disclosure__chev.is-open { transform: rotate(180deg); }
.disclosure__panel { padding: 0 var(--sp-5) var(--sp-5); }
@media (hover: hover) { .disclosure__toggle:hover { background: var(--surface-2); } }
/* Bare variant: a plain divider + toggle, for use inside another card. */
.disclosure--bare { border-top: 1px solid var(--border); margin-top: var(--sp-2); }
.disclosure--bare .disclosure__toggle { padding: var(--sp-3) 0; }
.disclosure--bare .disclosure__title { font-size: var(--fs-body); color: var(--text-muted); text-transform: none; }
.disclosure--bare .disclosure__panel { padding: 0 0 var(--sp-2); }

/* -------------------------------------------------------------- Buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--tap-min);
  padding: 0 var(--sp-5);
  border: var(--border-w) solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: var(--fs-body);
  font-weight: 700;
  letter-spacing: -0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.08s var(--ease), box-shadow 0.08s var(--ease), filter 0.15s var(--ease), background 0.15s var(--ease);
}
.btn:active { transform: translateY(1px); }

/* Primary + ghost are the tactile pair: an ink outline and a hard offset shadow
   that COLLAPSES on press (the button physically pushes into the page). */
.btn-primary {
  background: var(--primary);
  color: var(--on-primary);
  border-color: var(--line);
  box-shadow: var(--shadow);
}
.btn-ghost {
  background: var(--surface);
  color: var(--text);
  border-color: var(--line);
  box-shadow: var(--shadow);
}
.btn-primary:active,
.btn-ghost:active {
  transform: translate(3px, 3px);
  box-shadow: 0 0 0 var(--shadow-color);
}
.btn-block { width: 100%; }

/* ----------------------------------------------------------- Pills/badges - */
.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-1) var(--sp-3);
  border: 2px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--primary-tint);
  color: var(--text);
  font-size: var(--fs-sm);
  font-weight: 700;
}

.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border: 1.5px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--fs-sm);
  font-weight: 700;
  line-height: 1.4;
}
/* Intensity badges keep their fixed brand hues in both themes (with navy text,
   which clears AA on each), so a given intensity always reads the same color.
   The ink hairline gives them a crisp "sticker" edge on any surface. */
.badge--easy  { background: var(--i-easy);  color: var(--navy); border-color: var(--ink); }
.badge--mid   { background: var(--i-mid);   color: var(--navy); border-color: var(--ink); }
.badge--hard  { background: var(--i-hard);  color: var(--navy); border-color: var(--ink); }
.badge--taper { background: #9D8DEA; color: var(--navy); border-color: var(--ink); } /* lightened from --i-taper so navy text clears 4.5:1 */

/* --------------------------------------------------------------- List rows */
.list {
  background: var(--surface);
  border: var(--border-w) solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  width: 100%;
  min-height: 56px;
  padding: var(--sp-3) var(--sp-4);
  border: none;
  background: transparent;
  text-align: left;
  font-size: var(--fs-body);
  color: var(--text);
  border-bottom: 1px solid var(--border);
}
.row:last-child { border-bottom: none; }
a.row, button.row { cursor: pointer; }
.row__label { font-weight: 600; }
.row__value { color: var(--text-muted); display: flex; align-items: center; gap: var(--sp-2); }
.chev { color: var(--text-muted); flex: none; }

/* ------------------------------------------------------------- Form inputs */
.field { margin-bottom: var(--sp-4); }
.field > label {
  display: block;
  font-weight: 700;
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-2);
}
.input,
input.input,
select.input,
textarea.input {
  width: 100%;
  min-height: var(--tap-min);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-body);   /* 16px avoids mobile zoom-on-focus */
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  border: 2px solid var(--field-border);
  border-radius: var(--radius-input);
  appearance: none;
  transition: border-color 0.15s var(--ease);
}
.input::placeholder { color: var(--text-muted); }   /* still meets 4.5:1 */
.input:focus { outline: none; border-color: var(--primary); }
.input:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

/* Empty native date fields render as a blank box (no placeholder), which reads as
   "nothing to do here". When empty we prompt with the field's data-placeholder and
   tint the border so it clearly invites a choice; once a date is set it's normal. */
.datefield.is-empty {
  border-color: var(--focus);
  color: var(--text-muted);
}
.datefield.is-empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
  font-weight: 600;
}
.datefield.is-empty::-webkit-datetime-edit { color: transparent; }   /* hide "mm/dd/yyyy" */
.datefield:not(.is-empty)::before { content: none; }

/* A native date field packs the date text AND a calendar-picker icon into the box.
   With the form's roomy input padding there isn't room for both on narrower phones,
   so the year (the last digits of mm/dd/yyyy) gets clipped. Tighten the horizontal
   padding and trim the icon's gap so the whole date always fits; the field still
   drops to its own row when its column gets too narrow (see .field-row). */
/* .input.datefield (0,2,0) intentionally outweighs the base input.input (0,1,1)
   padding rule above — a plain .datefield would lose to it and never tighten. */
.input.datefield { padding-left: var(--sp-2); padding-right: var(--sp-2); }
.datefield::-webkit-datetime-edit { padding: 0; }
.datefield::-webkit-datetime-edit-fields-wrapper { padding: 0; }
.datefield::-webkit-calendar-picker-indicator { margin-inline-start: var(--sp-1); padding: 0; }

/* ---------------------------------------------------- Bottom tab bar (nav) */
.tabbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0 auto;
  width: 100%;
  max-width: var(--app-max);
  /* Reserve at least a little bottom inset even when the device reports no
     safe-area (most Android phones): it lifts the icon+label cluster off the very
     bottom edge so the labels stay visible as Chrome's URL bar shows/hides and
     nudges the fixed bar — keeping the nice movement without clipping the text. */
  height: calc(var(--tabbar-h) + max(env(safe-area-inset-bottom), var(--sp-2)));
  padding-bottom: max(env(safe-area-inset-bottom), var(--sp-2));
  display: flex;
  background: var(--tab-surface);
  border-top: var(--border-w) solid var(--line);
  box-shadow: var(--shadow-bar);
  z-index: var(--z-sticky);
}
.tabbar a {
  position: relative;
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: var(--tap-min);
  text-decoration: none;
  color: var(--tab-inactive);
  font-size: var(--fs-xs);
  font-weight: 600;
  transition: color 0.18s var(--ease);   /* smooth fade between active/inactive */
}
/* The icon sits inside a rounded "key" that fills with a coral-tint, ink-outlined
   pill only when the tab is active — a clear, tactile bottom-nav selection. */
.tabbar a svg {
  width: 24px;
  height: 24px;
  padding: 5px 14px;
  border: 2px solid transparent;
  border-radius: var(--radius-pill);
  box-sizing: content-box;
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease);
}
.tab-label { line-height: 1; }

.tabbar a.is-active { color: var(--tab-active); }
.tabbar a.is-active svg { background: var(--primary-tint); border-color: var(--line); }
.tabbar a.is-active .tab-label { color: var(--tab-active-label); font-weight: 800; }
.tabbar a.is-active::before {
  content: "";
  position: absolute;
  top: -2px;
  width: 36px;
  height: 4px;
  border-radius: 0 0 var(--radius-pill) var(--radius-pill);
  background: var(--primary);
}

/* ------------------------------------------------- Hover (pointer devices) -
   Only attach hover effects where a real hover pointer exists, so touch
   devices don't get stuck in a hover state (Impeccable responsive guidance). */
@media (hover: hover) {
  .btn-primary:hover { filter: brightness(1.04); }
  .btn-ghost:hover { background: var(--surface-2); }
  a.row:hover, button.row:hover { background: var(--surface-2); }
  .theme-toggle:hover { background: var(--overlay); }
}

/* ----------------------------------------------------------------- Motion - */
@media (prefers-reduced-motion: no-preference) {
  /* Subtle rise-in as each screen renders; replays on every route change. */
  #screen > * { animation: rr-rise 0.28s var(--ease) both; }
  @keyframes rr-rise {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
  }
}
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ============================================================ Season / Camp ==
   The plan overview (intensity curve / camp-day strip + "Today" marker) and the
   per-phase cards. Phase hues are the FIXED --i-* intensity colors so a phase
   always reads the same; everything else is semantic so both themes pass AA. */

/* Status line under the title — full --text on --bg (muted would miss AA there). */
.season-status { margin: calc(-1 * var(--sp-2)) 0 var(--sp-4); color: var(--text); font-weight: 600; }

/* ---- Overview card --------------------------------------------------------- */
.plan-overview__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-3);
}
.plan-overview__head h2 { margin-bottom: 0; font-size: var(--fs-h3); }

/* The chart scales to the container width at a fixed aspect ratio, so the HTML
   overlays (Today marker, phase labels) line up with the SVG by percentage. */
.chart { position: relative; margin: var(--sp-1) 0 var(--sp-3); }
.chart__svg { display: block; width: 100%; height: auto; overflow: visible; }

.chart__baseline { stroke: var(--border); stroke-width: 2; }

/* Phase / day columns — fixed intensity hues, with a faint edge so light bars
   (e.g. the yellow mid hue) stay defined on the card surface in both themes. */
.chart__bar { stroke: var(--text); stroke-opacity: 0.16; stroke-width: 2; }
.chart__bar--easy  { fill: var(--i-easy); }
.chart__bar--mid   { fill: var(--i-mid); }
.chart__bar--hard  { fill: var(--i-hard); }
.chart__bar--taper { fill: var(--i-taper); }

/* The intensity profile drawn over the columns: high-contrast so the rise/ease
   reads clearly regardless of the bar colours beneath it. */
.chart__curve { stroke: var(--text); stroke-opacity: 0.7; stroke-width: 6; stroke-linejoin: round; stroke-linecap: round; }
.chart__node { fill: var(--surface); stroke: var(--text); stroke-width: 4; }

/* "Today" marker: a --text line with a --surface halo so it's visible over any
   coloured column, in both themes; the flag uses the bg/fg pair (max contrast). */
.chart__today {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--text);
  box-shadow: 0 0 0 1.5px var(--surface);
  border-radius: var(--radius-pill);
}
.chart__today-flag {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: var(--text);
  color: var(--bg);
  font-size: var(--fs-xs);
  font-weight: 800;
  white-space: nowrap;
  box-shadow: none;
}

/* Phase labels beneath the chart — also the colour legend. Widths are set inline
   to match each phase's share of the timeline; names truncate when space is tight. */
.chart__phases { display: flex; gap: 2px; margin-top: var(--sp-2); }
.chart__phase {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 2px;
  font-size: var(--fs-xs);
  color: var(--text);
}
.chart__phase-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; }
.chart__swatch { width: 12px; height: 12px; border-radius: 4px; flex: none; border: 1px solid var(--field-border); }
.chart__swatch--easy  { background: var(--i-easy); }
.chart__swatch--mid   { background: var(--i-mid); }
.chart__swatch--hard  { background: var(--i-hard); }
.chart__swatch--taper { background: var(--i-taper); }

.chart__axis { display: flex; justify-content: space-between; gap: var(--sp-3); margin-top: 6px; font-size: var(--fs-xs); color: var(--text-muted); }

/* ---- Phase cards (siblings — never nested inside the overview card) -------- */
.phase-card__head { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-2); }
.phase-card__head h3 { margin: 0; }
.phase-dot { width: 14px; height: 14px; border-radius: 50%; flex: none; border: 1px solid var(--field-border); }
.phase-dot--easy  { background: var(--i-easy); }
.phase-dot--mid   { background: var(--i-mid); }
.phase-dot--hard  { background: var(--i-hard); }
.phase-dot--taper { background: var(--i-taper); }
.phase-now { margin-left: auto; }

.phase-card__range { margin: 0 0 var(--sp-2); color: var(--text-muted); font-size: var(--fs-sm); font-weight: 600; }
.phase-card__focus { margin: 0 0 var(--sp-3); color: var(--text); }

.phase-card__intensity { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.phase-card__intensity-label { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; color: var(--text-muted); }
.phase-card__intensity-num { font-weight: 800; color: var(--text); }

/* Intensity dots: the "N / 10" text carries the meaning (dots are aria-hidden),
   and filled dots get a --text hairline so their boundary passes AA either way. */
.dots { display: inline-flex; gap: 4px; }
.dot { width: 11px; height: 11px; border-radius: 50%; }
.dot--off { border: 1.5px solid var(--field-border); }
.dot--on { border: 1.5px solid var(--text); }
.dot--easy  { background: var(--i-easy); }
.dot--mid   { background: var(--i-mid); }
.dot--hard  { background: var(--i-hard); }
.dot--taper { background: var(--i-taper); }

.eyebrow { display: block; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; color: var(--text-muted); margin-bottom: 2px; }
.phase-card__why p { margin: 0; color: var(--text); font-size: var(--fs-sm); }

/* Current phase — a full ring + "Now" pill (no left-border "side tab" tell). The
   ring uses --focus (clears 3:1 on the card in both themes); --shadow is none in dark. */
.phase-card.is-current { border-color: var(--focus); box-shadow: 0 0 0 1px var(--focus), var(--shadow); }

/* ====================================================== Desktop app frame ===
   Mobile-first 480px column, but on wider screens present it as a centered,
   framed "app rail" on a distinct page backdrop — so it reads as an intentional
   product instead of a left-stranded mobile page. Only semantic tokens differ;
   depth comes from a tone step (--page-bg) plus hairline borders, with no heavy
   shadows, so it stays correct and dark-safe in both themes. The header (sticky)
   and tab bar (fixed) already share the same max-width + centering, so the whole
   column lines up. */
@media (min-width: 600px) {
  /* Paper backdrop + a faint ink dot-grid: the column now sits ON something
     (a coach's grid pad) instead of floating in an empty void. */
  body {
    background-color: var(--page-bg);
    background-image: radial-gradient(var(--dot) 1.6px, transparent 1.6px);
    background-size: 24px 24px;
    background-position: 12px 12px;
  }
  .appbar,
  #screen,
  .tabbar {
    border-left: var(--border-w) solid var(--line);
    border-right: var(--border-w) solid var(--line);
  }
  .appbar {
    border-top-left-radius: var(--radius-card);
    border-top-right-radius: var(--radius-card);
  }
  .tabbar {
    border-bottom-left-radius: var(--radius-card);
    border-bottom-right-radius: var(--radius-card);
  }
}
