/* ParkAlert: built to the iOS grouped-list idiom, since that is what the
   phone in your hand already speaks. Sizes are in rem so the layout grows with
   the reader's text size setting. */

* { margin: 0; padding: 0; box-sizing: border-box; }
/* hidden always hides, whatever display a rule gives the element. */
[hidden] { display: none !important; }

:root {
  color-scheme: light dark;
  /* ---- Color (DIRECTION.md 4; the single source is
     docs/critique/director/tools/tokens.mjs). Every blue sits at hue 205 to
     216: no purple. Accent is for what can be tapped, and nothing else. Red
     only for down, amber only for weather, green only for good news (a tag,
     a ride back), never on a wait number. No color literal outside this
     block and the band's (scripts/lint-css.js). */
  --bg: #F1F4F8;
  --surface: #FFFFFF;
  --sheet: #F7F9FC;          /* a sheet's ground, one step above the page */
  --sheet-group: #FFFFFF;    /* a card on a sheet */
  --fill: #EBEFF5;           /* chips, search, tracks */
  --fill-strong: #DCE3EC;    /* pressed, a switch's off track */
  --separator: #E1E6EE;      /* 1px rules, never 0.5px */
  --ink: #0E2340;
  --ink-2: #4C5B70;
  --ink-3: #6F7E92;          /* chevrons, placeholders, off bells: 3:1 or better */
  --accent: #0A66C2;
  --accent-soft: #E5EFFA;
  --on-accent: #FFFFFF;
  --switch-on: #0A66C2;      /* the white knob reads on it at 3:1 or better */
  --bar: #0A66C2;            /* a wait bar's fill */
  --tile: #E5EFFA;           /* the back time beside a row */
  --tile-ink: #0A66C2;
  --flip: #0F2747;
  --flip-ink: #FFFFFF;
  --flip-edge: #0F2747;
  --flip-seam: rgba(0, 0, 0, 0.45);
  --down: #B3261E; --down-soft: #FCEBEA; --down-line: #EDB9B6;
  --back: #17743F; --back-soft: #E8F6ED; --back-line: #A9DCBD;
  --storm: #8F5A00; --storm-soft: #FDF4E3; --storm-line: #EFCE93;
  --paused: #4C5B70; --paused-soft: #EEF1F5; --paused-line: #D5DDE5;
  --badge: #B3261E;          /* white numbers on it */
  --on-badge: #FFFFFF;
  /* On the band, a selected park tile and onboarding: white on deep blue. */
  --band-1: #0B3A70;
  --band-2: #2366AE;
  --on-band: #FFFFFF;
  --on-band-2: rgba(255, 255, 255, 0.9);
  --glass: rgba(255, 255, 255, 0.14);
  --glass-line: rgba(255, 255, 255, 0.16);
  --glass-strong: rgba(255, 255, 255, 0.28);
  --glass-chev: rgba(255, 255, 255, 0.24); /* the header title's chevron circle */
  --band-warn: #FFD49A;      /* "times are old", on its own dark chip */
  --band-chip: rgba(8, 20, 40, 0.42);
  --meter-off: rgba(14, 35, 64, 0.16);
  /* Materials */
  --chrome: rgba(241, 244, 248, 0.97);
  --toast: rgba(255, 255, 255, 0.96);
  --scrim: rgba(0, 0, 0, 0.45);
  --shade: rgba(0, 0, 0, 0.14);
  --press: rgba(14, 35, 64, 0.08);
  --knob: #FFFFFF;
  --shadow: 0 10px 40px rgba(10, 26, 51, 0.16);
  --shadow-card: 0 1px 2px rgba(14, 35, 64, 0.05), 0 6px 20px rgba(14, 35, 64, 0.06);
  --shadow-lift: 0 2px 4px rgba(14, 35, 64, 0.08), 0 14px 34px rgba(14, 35, 64, 0.2);
  --shadow-tile-on: 0 2px 4px rgba(14, 35, 64, 0.08), 0 14px 34px rgba(11, 58, 112, 0.2);
  --shadow-seg: 0 1px 3px rgba(0, 0, 0, 0.12);
  --shadow-knob: 0 2px 6px rgba(0, 0, 0, 0.2), 0 0 0 0.5px rgba(0, 0, 0, 0.04);
  --shadow-page: -1px 0 0 var(--separator), -12px 0 32px rgba(0, 0, 0, 0.12);
  --flip-shine: inset 0 1px 0 rgba(255, 255, 255, 0.14);

  /* ---- Type: eight styles, no others (DIRECTION.md 3). Each is a font
     shorthand plus its tracking; a rule takes both, never its own size or
     weight. Line heights are ratios, so a style capped at large text
     (a min() of the --fs-* size and a px cap) keeps its leading. The --fs-* sizes exist only
     for those caps. */
  --round: ui-rounded, 'SF Pro Rounded', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --sans: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, sans-serif;
  --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, monospace;
  --fs-display: 2.125rem; --fs-clock: 2.5rem; --fs-title: 1.375rem; --fs-number: 1.25rem;
  --fs-headline: 1.0625rem; --fs-body: 1.0625rem; --fs-subhead: 0.9375rem; --fs-caption: 0.75rem;
  --fs-park: 1.75rem;        /* the header's park title: the title style at 28 pt, capped at 28px */
  --t-display: 800 var(--fs-display)/1.176 var(--round);    /* 34/40 */
  --t-clock: 800 var(--fs-clock)/1.2 var(--round);          /* 40/48 */
  --t-title: 800 var(--fs-title)/1.273 var(--round);        /* 22/28 */
  --t-number: 800 var(--fs-number)/1.2 var(--round);        /* 20/24 */
  --t-headline: 600 var(--fs-headline)/1.294 var(--sans);   /* 17/22 */
  --t-body: 400 var(--fs-body)/1.412 var(--sans);           /* 17/24 */
  --t-subhead: 400 var(--fs-subhead)/1.333 var(--sans);     /* 15/20 */
  --t-caption: 600 var(--fs-caption)/1.333 var(--sans);     /* 12/16 */
  --tr-display: -0.02em; --tr-clock: 0; --tr-title: -0.01em; --tr-number: 0;
  --tr-headline: -0.01em; --tr-body: -0.01em; --tr-subhead: 0; --tr-caption: 0.01em;
  --tr-park: -0.5px;         /* the header's park title */
  --tr-code: 0.14em;         /* a trip code, read aloud one character at a time */

  /* ---- Space: a 4pt scale only (DIRECTION.md 5), in rem so it grows with text. */
  --sp-4: 0.25rem; --sp-8: 0.5rem; --sp-12: 0.75rem; --sp-16: 1rem; --sp-20: 1.25rem;
  --sp-24: 1.5rem; --sp-28: 1.75rem; --sp-32: 2rem; --sp-40: 2.5rem; --sp-56: 3.5rem;
  --gutter: 1rem;
  --radius: 1.125rem;        /* cards: 18 */
  --radius-sheet: 1.375rem;  /* sheets: 22 */
  --radius-btn: 0.875rem;    /* buttons: 14 */
  --tabbar-h: 3.3rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #070D19;
    --surface: #111A2A;
    --sheet: #151F31;
    --sheet-group: #1B263A;
    --fill: #1B263A;
    --fill-strong: #26344D;
    --separator: #223049;
    --ink: #F2F5FA;
    --ink-2: #A6B3C6;
    --ink-3: #7E8CA2;
    --accent: #4C9EFF;
    --accent-soft: #13294A;
    --on-accent: #04142B;
    --switch-on: #2F74C8;
    --bar: #4C9EFF;
    --tile: #13294A;
    --tile-ink: #4C9EFF;
    --flip: #1E3A66;
    --flip-edge: #4A6A9E;
    --down: #FF7A6E; --down-soft: #33171A; --down-line: #6E2E2C;
    --back: #55D98C; --back-soft: #10291D; --back-line: #245639;
    --storm: #FFBA52; --storm-soft: #2E220F; --storm-line: #5E4419;
    --paused: #A6B3C6; --paused-soft: #1B263A; --paused-line: #33425C;
    --badge: #C7362D;
    --band-1: #050B1A;
    --band-2: #163A69;
    --meter-off: rgba(255, 255, 255, 0.2);
    --chrome: rgba(7, 13, 25, 0.97);
    --toast: rgba(27, 38, 58, 0.97);
    --scrim: rgba(0, 0, 0, 0.6);
    --press: rgba(255, 255, 255, 0.08);
    --shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
    --shadow-card: 0 0 0 1px rgba(255, 255, 255, 0.035);
    --shadow-lift: 0 0 0 1px rgba(255, 255, 255, 0.05), 0 14px 34px rgba(0, 0, 0, 0.45);
    --shadow-tile-on: inset 0 0 0 1.5px var(--accent);
    --shadow-seg: 0 1px 3px rgba(0, 0, 0, 0.4);
  }
}

html {
  overscroll-behavior-y: none;
  font-family: var(--sans);
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}
body {
  font: var(--t-body); letter-spacing: var(--tr-body);
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  min-height: 100dvh;
  /* The app's own pull to refresh, not a page reload, and not stacked on
     top of iOS's rubber band: with the bounce off, only the pull moves. */
  overscroll-behavior-y: none;
}
button, input { font: inherit; color: inherit; letter-spacing: inherit; }
button { background: none; border: none; cursor: pointer; text-align: left; }
/* Numbers are always tabular, whatever style sets the type (the font
   shorthand would otherwise reset it). */
*, *::before, *::after { font-variant-numeric: tabular-nums !important; }
b, strong { font-weight: inherit; }

/* An app, not a web page: chrome can't be selected or long-pressed into a
   callout, a tap never flashes grey or waits for a double tap, and links
   are tappable words, never underlined. Selection stays where it is the
   point: the trip code, a topic to copy, and what you type. */
body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
input, textarea, .trip-code, .topic code, .selectable { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }
button, a, summary, label, [role=button], [role=switch], [role=tab] { touch-action: manipulation; }
img, svg { -webkit-user-drag: none; }
svg { width: 1.375rem; height: 1.375rem; flex: none; fill: none; stroke: currentColor;
      stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
a, a:visited { color: var(--accent); text-decoration: none; }
a:active { opacity: 0.5; }
:where(.text-btn, .btn-inline, .btn-plain, .sheet-back, summary):active { opacity: 0.5; }
.hidden { display: none !important; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

/* Type scale: tracking tightens as size grows, leading loosens as it shrinks. */
.large-title { font: var(--t-display); letter-spacing: var(--tr-display); }
.title-2 { font: var(--t-title); letter-spacing: var(--tr-title); }
.footnote { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); padding: var(--sp-8) calc(var(--gutter) + var(--sp-4)) 0; }
.section-label {
  font: var(--t-title); letter-spacing: var(--tr-title);
  color: var(--ink);
  padding: var(--sp-24) calc(var(--gutter) + var(--sp-4)) var(--sp-12);
}
.caption-label { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); }

/* Press feedback lands on touch-down, instantly, and eases back on release. */
.pressable { transition: transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1), background-color 220ms ease; }
.pressable:active { transition-duration: 0ms; }
.row.pressable:active { background: var(--press); }
.pill.pressable:active, .btn-primary.pressable:active, .tab.pressable:active,
.btn-secondary.pressable:active { transform: scale(0.96); }

/* ---- Grouped lists ---- */
.group {
  background: var(--surface); border-radius: var(--radius); overflow: hidden;
  margin: 0 var(--gutter); box-shadow: var(--shadow-card);
}
.group.spaced { margin-top: var(--sp-32); }
.row {
  width: 100%; display: flex; align-items: center; gap: var(--sp-12);
  min-height: 2.9rem; padding: var(--sp-8) var(--gutter);
  position: relative;
}
/* The one separator (.hairline): 1px, never 0.5px, which WebKit rounds away
   on some rows at 3x. Inset from the left; rows that need a deeper inset
   move only its left edge. */
.row + .row::before, .slim + .slim::before, .barrow + .barrow::before, .pick + .pick::before,
.ride-wrap + .ride-wrap::before, .hold-ride + .hold-ride::before, .hairline::before {
  content: ''; position: absolute; top: 0; right: 0; left: var(--gutter);
  height: 1px; background: var(--separator); pointer-events: none;
}
.hairline { position: relative; }
/* Rows with an icon: the line starts where the text does, as in Settings. */
.row:has(> .row-icon) + .row:has(> .row-icon)::before { left: calc(var(--gutter) + 2.125rem); }
.group.plain .row + .row::before { left: var(--gutter); }
.row-icon { width: 1.4rem; height: 1.4rem; }
.row-label { flex: 1; min-width: 0; }
.row-detail { font: var(--t-body); letter-spacing: var(--tr-body); color: var(--ink-2); white-space: nowrap; }
.row-detail.ok { color: var(--ink-2); }
.row-detail.warn { color: var(--storm); }
.chevron { width: 0.95rem; height: 0.95rem; color: var(--ink-3); stroke-width: 2.4; }
.row.danger { color: var(--down); }
.row.selected .check { color: var(--accent); }
.check { width: 1.2rem; height: 1.2rem; stroke-width: 2.4; }
.tint-accent { color: var(--accent); }
.tint-orange { color: var(--storm); }
.tint-green { color: var(--back); }
.tint-red { color: var(--down); }

/* ---- Setup ---- */
.status-line { font: var(--t-subhead); letter-spacing: var(--tr-subhead); min-height: 1.2rem; text-align: center; color: var(--ink-2); padding: 0 var(--gutter) var(--sp-12); }
.status-line.warn, .footnote.warn { color: var(--storm); }
.join { display: flex; align-items: center; padding-right: var(--sp-8); }
.join input {
  font: var(--t-body); letter-spacing: var(--tr-code);
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  outline: none;
  padding: var(--sp-12) var(--gutter);
  text-transform: uppercase;
}
.join input::placeholder { letter-spacing: var(--tr-body); text-transform: none; color: var(--ink-2); }
.btn-inline { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--accent); padding: var(--sp-8) var(--sp-12); }
.btn-inline:disabled { color: var(--ink-3); }
.btn-stack .btn-inline { align-self: center; }

/* ---- Navigation header: a translucent layer content scrolls beneath ---- */
.nav {
  position: relative;
  padding: calc(env(safe-area-inset-top) + var(--sp-16)) 0 var(--sp-12);
  background: var(--bg);
  transition: background-color 200ms ease, box-shadow 200ms ease;
}
/* The large title scrolls away with the list, and this compact bar takes
   over at the top, so the header never keeps a third of a landscape screen. */
.nav-bar {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  height: calc(env(safe-area-inset-top) + 2.75rem);
  padding: env(safe-area-inset-top) 4rem 0;
  background: var(--chrome);
  box-shadow: 0 1px 0 var(--separator);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 150ms ease;
}
.nav-bar span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.compact .nav-bar { opacity: 1; pointer-events: auto; }
.no-tabbar .nav-bar { display: none; }
.nav-inner { display: flex; align-items: flex-end; gap: var(--sp-12); padding: 0 var(--gutter); max-width: 40rem; margin: 0 auto; }
.nav-titles { flex: 1; min-width: 0; position: relative; }
.cover-btn { position: absolute; inset: 0; z-index: 1; width: 100%; border-radius: 0.5rem; cursor: pointer; }
.cover-btn:active ~ * { opacity: 0.6; }
.nav-meta { display: flex; align-items: center; gap: var(--sp-4); }
.nav .large-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav .large-title.wrap {
  white-space: normal; overflow-wrap: break-word;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
}
.nav-meta { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-top: 0; }
#park-meta.warn { color: var(--storm); }

/* The pill is drawn 33px tall but answers to a 44px finger. */
.pill::before { content: ''; position: absolute; inset: -0.4rem -0.15rem; }
.pill {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  flex: none;
  padding: var(--sp-8) var(--sp-12) var(--sp-8) var(--sp-12);
  margin-bottom: var(--sp-4);
  border-radius: 999px;
  background: var(--fill);
  color: var(--ink);
}
.pill svg { width: 1.05rem; height: 1.05rem; stroke-width: 2; }
.pill.on svg { color: var(--accent); }
.pill.closed { color: var(--ink-2); }

main {
  max-width: 40rem; margin: 0 auto;
  padding: var(--sp-8) 0 calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--sp-32));
}

/* ---- Down now ---- */
.cards { display: flex; flex-direction: column; gap: var(--sp-12); padding: 0 var(--gutter); }
.elapsed {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  color: var(--down);
  white-space: nowrap;
}

/* How far into a typical outage this one is: elapsed in red, the usual
   reopening window shaded ahead of it. */
.timeline {
  position: relative; height: 0.3rem; border-radius: 999px; background: var(--fill);
  margin-top: var(--sp-12); overflow: hidden;
}
.timeline .spent { position: absolute; inset: 0 auto 0 0; background: var(--down); border-radius: 999px; }
.timeline .window { position: absolute; top: 0; bottom: 0; background: var(--accent-soft); }
.timeline .window::before { content: ''; position: absolute; inset: 0; border-left: 2px solid var(--accent); opacity: 0.6; }

.hold-header {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  color: var(--storm);
  width: 100%;
  padding: var(--sp-8) var(--gutter) var(--sp-8);
}
.hold-header svg { width: 1.1rem; height: 1.1rem; }
.hold-header .chevron { color: var(--storm); opacity: 0.7; width: 0.8rem; height: 0.8rem; }
.hold-header:active { opacity: 0.6; }
.cards + .section-label { padding-top: var(--sp-24); }
.hold-card { cursor: default; }
.hold-card:active { transform: none; background: var(--surface); }
.hold-card .hold-header { padding: 0 0 var(--sp-4); }
.hold-rides { margin: var(--sp-12) calc(-1 * var(--gutter)) calc(-1 * var(--sp-16)); border-top: 1px solid var(--separator); }
.hold-ride {
  width: 100%; display: flex; align-items: center; gap: var(--sp-12); min-height: 2.75rem;
  padding: var(--sp-8) var(--gutter); position: relative;
}
.hold-ride:active { background: var(--press); }
.hold-ride.unfollowed .row-label { color: var(--ink-2); }

.empty { text-align: center; padding: var(--sp-56) var(--sp-32) var(--sp-24); }
.empty svg { width: 3.25rem; height: 3.25rem; stroke-width: 1.3; color: var(--back); margin-bottom: var(--sp-12); }
.empty .title-2 { margin-bottom: var(--sp-4); }
.empty p { color: var(--ink-2); }
.empty + .group { margin-top: var(--sp-20); }
.empty.offline svg, .empty.closed svg { color: var(--ink-2); }
.empty.loading { padding-top: 4rem; color: var(--ink-2); }
.empty .btn-secondary { margin: var(--sp-24) auto 0; max-width: 16rem; }

.row-label small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); display: block; color: var(--ink-2); margin-top: 0; }
.row-label.muted { color: var(--ink-2); }

/* ---- Rides ---- */
.search {
  display: flex; align-items: center; gap: var(--sp-8); margin: var(--sp-4) var(--gutter) var(--sp-4);
  background: var(--fill); border-radius: 0.65rem; padding: 0 var(--sp-8); color: var(--ink-2);
}
.search svg { width: 1.1rem; height: 1.1rem; stroke-width: 2; }
.search input {
  font: var(--t-body); letter-spacing: var(--tr-body);
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  outline: none;
  padding: var(--sp-8) 0;
  color: var(--ink);
}
.search input::placeholder { color: var(--ink-2); }
.search input::-webkit-search-cancel-button { filter: grayscale(1); }
.segmented {
  display: flex; gap: var(--sp-4); margin: var(--sp-8) var(--gutter) 0; padding: var(--sp-4);
  background: var(--fill); border-radius: 0.6rem;
}
.segmented button {
  font: var(--t-subhead); letter-spacing: var(--tr-subhead);
  flex: 1;
  min-height: 2.75rem;
  border-radius: 0.5rem;
  text-align: center;
  transition: background-color 180ms ease, box-shadow 180ms ease;
}
.segmented button[aria-pressed='true'], .segmented button[aria-checked='true'] { background: var(--surface); box-shadow: var(--shadow-seg); }
@media (prefers-color-scheme: dark) { .segmented button[aria-pressed='true'], .segmented button[aria-checked='true'] { background: var(--fill-strong); } }
.list-header {
  font: var(--t-caption); letter-spacing: var(--tr-caption);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-16) var(--gutter) var(--sp-8);
  color: var(--ink-2);
  text-transform: uppercase;
}
.text-btn { font: var(--t-headline); letter-spacing: var(--tr-headline); font-size: var(--fs-subhead); color: var(--accent); text-transform: none; }
/* Small text controls get a finger-sized hit area (44px) without moving:
   padding enlarges the target and a matching negative margin cancels it. */
.text-btn, .toast button, .topic button { padding: var(--sp-12) var(--sp-8); margin: calc(-1 * var(--sp-12)) calc(-1 * var(--sp-8)); }
.ride-row { cursor: default; }
.ride-row .row-label {  }
.ride-row .meta { font: var(--t-subhead); letter-spacing: var(--tr-subhead); display: flex; align-items: center; gap: var(--sp-4); color: var(--ink-2); margin-top: 0; }
.dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--ink-3); flex: none; }
.dot.OPERATING { background: var(--back); }
.dot.DOWN { background: var(--down); }
.meta.DOWN { color: var(--down); }
.group.rides .row + .row::before { left: var(--gutter); }
.ride-row { padding: 0 var(--gutter) 0 0; gap: var(--sp-8); }
.row-main {
  flex: 1; min-width: 0; align-self: stretch; display: flex; align-items: center;
  padding: var(--sp-8) var(--sp-4) var(--sp-8) var(--gutter);
}
.row-main:active { background: var(--press); }
.meta-chevron { width: 0.7rem; height: 0.7rem; stroke-width: 2.6; color: var(--ink-3); margin-left: 0; }
.tags { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-top: var(--sp-4); }
.tag { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); background: var(--fill); border-radius: 0.35rem; padding: 0 var(--sp-8); }
.segmented + .segmented { margin-top: var(--sp-8); }
.no-results { padding: var(--sp-24) var(--gutter); color: var(--ink-2); text-align: center; }

/* Switch: the familiar on/off control, one per ride. As in Settings, the
   whole trailing end of the row toggles it, not just the drawn switch. */
.switch::before { content: ''; position: absolute; top: -0.9rem; bottom: -0.9rem; left: -0.75rem; right: -1rem; }
.switch {
  position: relative; width: 3.1rem; height: 1.9rem; flex: none; border-radius: 999px;
  background: var(--fill-strong); transition: background-color 200ms ease;
}
.switch::after {
  content: ''; position: absolute; top: 0.125rem; left: 0.125rem;
  width: 1.65rem; height: 1.65rem; border-radius: 50%; background: var(--knob);
  box-shadow: var(--shadow-knob);
  transition: transform 260ms cubic-bezier(0.3, 1.3, 0.5, 1), width 160ms ease;
}
.switch { touch-action: pan-y; } /* sideways drags reach the switch, not the page */
.switch[aria-checked='true'], .switch.slide-on { background: var(--switch-on); }
.switch.slide-off { background: var(--fill-strong); }
.switch.slide-on::after { transform: translateX(1.2rem); }
.switch.slide-off::after { transform: none; }
.switch[aria-checked='true']::after { transform: translateX(1.2rem); }
.switch:active::after { width: 1.95rem; }
.switch[aria-checked='true']:active::after { transform: translateX(0.9rem); }

/* ---- Trip ---- */
.code-card { padding: var(--sp-16) var(--gutter) var(--gutter); text-align: center; }
/* Always all six characters: it is what a guest reads aloud to family. */
.trip-code {
  font: var(--t-number); letter-spacing: var(--tr-code);
  margin: var(--sp-4) 0 var(--sp-16) 0.24em;
  font-feature-settings: 'ss01';
  white-space: nowrap;
}
.btn-primary, .btn-secondary {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-8);
  width: 100%;
  min-height: 3.125rem;
  border-radius: var(--radius-btn);
  text-align: center;
}
.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary svg { width: 1.2rem; height: 1.2rem; stroke-width: 2; }
.btn-primary:disabled { opacity: 0.45; }
.btn-secondary { background: var(--fill); color: var(--accent); text-decoration: none; }
.step .btn-row .btn-secondary { flex: 1; }
.btn-secondary.danger { color: var(--down); }
/* A quieter third choice under a sheet's buttons (Delete trip for everyone). */
.btn-plain { font: var(--t-headline); letter-spacing: var(--tr-headline); display: flex; align-items: center; justify-content: center; width: 100%; min-height: 2.75rem; color: var(--accent); }
.btn-plain.danger { color: var(--down); }
.btn-stack { display: flex; flex-direction: column; gap: var(--sp-8); padding: var(--sp-20) var(--gutter) 0; }

/* ---- Tab bar: translucent, content visible beneath ---- */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  display: flex; justify-content: center;
  padding-bottom: env(safe-area-inset-bottom);
  /* Nearly opaque: its small labels must stay readable over whatever
     scrolls beneath (a green switch took them under 4.5:1). */
  background: var(--bg);
  box-shadow: 0 -1px 0 var(--separator);
}
body.paging .tabbar { background: var(--bg); -webkit-backdrop-filter: none; backdrop-filter: none; }
.tab {
  font: var(--t-caption); letter-spacing: var(--tr-caption);
  flex: 1;
  max-width: 10rem;
  height: var(--tabbar-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  color: var(--ink-2);
}
/* 28 pt glyphs with a 2 pt stroke (1.71 on their 24 grid): outline when
   idle, the filled glyph when selected. */
.tab svg { width: 1.75rem; height: 1.75rem; stroke-width: 1.71; }
.tab svg.on, .tab.active svg.off { display: none; }
.tab.active svg.on { display: block; }
.tab.active { color: var(--accent); }
.tab-icon { position: relative; display: flex; }
.badge {
  font: var(--t-caption); letter-spacing: var(--tr-caption);
  line-height: 1.1rem; letter-spacing: 0;
  position: absolute;
  top: -0.2rem;
  right: -0.55rem;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 var(--sp-4);
  border-radius: 999px;
  background: var(--badge);
  color: var(--on-band);
  text-align: center;
}

/* ---- Sheet ---- */
#app { transform-origin: 50% 0; }
.sheet-layer { position: fixed; inset: 0; z-index: 50; }
.scrim { position: absolute; inset: 0; background: var(--scrim); opacity: 0; touch-action: none; }
.sheet {
  position: absolute; left: 0; right: 0; bottom: 0; margin: 0 auto; max-width: 40rem;
  max-height: calc(100dvh - env(safe-area-inset-top) - 1.5rem);
  display: flex; flex-direction: column;
  background: var(--sheet); border-radius: var(--radius-sheet) var(--radius-sheet) 0 0; box-shadow: var(--shadow);
  padding-bottom: calc(env(safe-area-inset-bottom) + var(--sp-16));
  transform: translateY(100%); will-change: transform; outline: none;
}
.grabber-zone { flex: none; display: flex; justify-content: center; padding: var(--sp-8) 0 var(--sp-4); touch-action: none; cursor: grab; }
.grabber { width: 2.25rem; height: 0.3125rem; border-radius: 999px; background: var(--ink-3); }
.sheet-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.sheet-head { padding: var(--sp-8) var(--gutter) var(--sp-16); }
.sheet-back {
  font: var(--t-body); letter-spacing: var(--tr-body);
  display: inline-flex;
  align-items: center;
  gap: 0;
  color: var(--accent);
  min-height: 2.75rem;
  margin: calc(-1 * var(--sp-8)) 0 0 calc(-1 * var(--sp-8));
  padding: 0 var(--sp-8);
}
.sheet-back .back-chevron { width: 1.1rem; height: 1.1rem; stroke-width: 2.4; transform: scaleX(-1); }
.sheet-back:active { opacity: 0.5; }
.sheet-head p { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-top: var(--sp-4); }
.sheet .group { background: var(--sheet-group); box-shadow: none; }

/* Alert setup steps */
.steps { list-style: none; counter-reset: step; padding: 0 var(--gutter); display: flex; flex-direction: column; gap: var(--sp-20); }
.step { display: grid; grid-template-columns: 1.75rem 1fr; column-gap: var(--sp-12); counter-increment: step; }
.step::before {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  content: counter(step);
  grid-row: 1 / span 3;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-soft);
  color: var(--accent);
}
/* Done: the icon set's check, not a text glyph. */
.step.done::before {
  content: '';
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / 1.05rem no-repeat;
}
.step > * { grid-column: 2; }
.step h3 { font: var(--t-headline); letter-spacing: var(--tr-headline); line-height: 1.75rem; }
.step p { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin: 0 0 var(--sp-8); }
.step .btn-secondary, .step .btn-primary { min-height: 2.75rem; }
.step .btn-row { display: flex; gap: var(--sp-8); }
.topic {
  display: flex; align-items: center; gap: var(--sp-8); background: var(--fill); border-radius: 0.65rem;
  padding: var(--sp-8) var(--sp-8) var(--sp-8) var(--sp-12); margin-bottom: var(--sp-8);
}
/* A long-press selects the whole topic at once (the copy fallback tells
   guests to press and hold), and it wraps rather than scrolling sideways. */
.topic code { font: var(--t-subhead); letter-spacing: var(--tr-subhead); font-family: var(--mono); flex: 1; min-width: 0; overflow-wrap: anywhere; -webkit-user-select: all; user-select: all; }
.topic button { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--accent); flex: none; margin-right: calc(-1 * var(--sp-4)); }
.tip {  }
.wait-state { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-8); margin-top: var(--sp-12); }
.chip {
  font: var(--t-subhead); letter-spacing: var(--tr-subhead);
  min-height: 2.5rem;
  padding: 0 var(--sp-16);
  border-radius: 999px;
  text-align: center;
  background: var(--fill);
  color: var(--ink);
}
.chip[aria-pressed='true'] { background: var(--accent); color: var(--on-accent); }
.chip.pressable:active { transform: scale(0.96); }
/* Wait limits: one segmented row (Off, 10, 15, ...), as a picker in Settings. */
.segmented.wait-limits { margin: var(--sp-12) 0 0; }
.segmented.wait-limits .chip { flex: 1; min-height: 2.25rem; padding: 0; border-radius: 0.5rem; background: none; color: var(--ink); }
.segmented.wait-limits .chip[aria-pressed='true'] { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-seg); }
.sheet .segmented.wait-limits { background: var(--fill); }
.wait-badge { font: var(--t-headline); letter-spacing: var(--tr-headline); display: inline-flex; align-items: center; gap: 0; color: var(--accent); margin-left: var(--sp-4); }
.wait-badge svg { width: 0.9rem; height: 0.9rem; stroke-width: 2; }
.inline-icon { width: 1.1em; height: 1.1em; vertical-align: -0.2em; color: var(--accent); }

/* ---- Toast ---- */
.toast {
  font: var(--t-subhead); letter-spacing: var(--tr-subhead);
  position: fixed;
  left: 0;
  right: 0;
  margin: 0 auto;
  z-index: 60;
  width: max-content;
  bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 0.8rem);
  display: flex;
  align-items: center;
  gap: var(--sp-16);
  max-width: calc(100% - 2rem);
  padding: var(--sp-12) var(--sp-16) var(--sp-12) var(--sp-16);
  border-radius: 1rem;
  /* A heavier material than the chrome: it floats over busy content and must stay legible. */
  background: var(--toast);
  color: var(--ink);
  box-shadow: var(--shadow);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  backdrop-filter: blur(24px) saturate(180%);
  opacity: 0;
  transform: translateY(1rem) scale(0.96);
  pointer-events: none;
  transition: opacity 220ms ease, transform 320ms cubic-bezier(0.2, 0.9, 0.3, 1);
}
.toast.show { opacity: 1; transform: none; pointer-events: auto; }
.toast button { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--accent); flex: none; }
.no-tabbar .toast { bottom: calc(env(safe-area-inset-bottom) + 1.2rem); }
/* Over a sheet, a toast drops from the top instead of covering its buttons. */
.toast.top { bottom: auto; top: calc(env(safe-area-inset-top) + 0.6rem); transform: translateY(-1rem) scale(0.96); }
.toast.top.show { transform: none; }

/* ---- Detail sheets ---- */
.group.padded { padding: var(--sp-16) var(--gutter) var(--sp-16); }
.group.spaced-sm { margin-top: var(--sp-16); }
.sheet-head p.tint-red { color: var(--down); }
.kind-tag { font: var(--t-caption); letter-spacing: var(--tr-caption); display: inline-flex; align-items: center; gap: var(--sp-4); color: var(--ink-2); margin-bottom: var(--sp-4); }
.kind-tag.hold { color: var(--storm); }
.kind-tag svg { width: 0.95rem; height: 0.95rem; }
.big-outlook { font: var(--t-title); letter-spacing: var(--tr-title); }
.clock { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-top: var(--sp-4); }
.explain { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-top: var(--sp-12); }
/* Stat cells as the strip has them: the number over its caption, centered,
   1px between (review round 2, p3). */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); text-align: center; }
.stats > div { display: flex; flex-direction: column-reverse; align-items: center; justify-content: flex-end; gap: var(--sp-4); min-width: 0; padding: 0 var(--sp-4); }
.stats > div + div { border-left: 1px solid var(--separator); }
.stat-label { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); }
.stat-value { font: var(--t-number); letter-spacing: var(--tr-number); margin-top: 0; }
.stats + [data-chart] { margin-top: var(--sp-16); }

/* ---- Charts: one accent hue, hairline axes, text in text colors ---- */
/* A finger on a chart scrubs it and the page holds still, as in Stocks:
   scroll by touching anywhere else. */
.chart { display: block; width: 100%; height: auto; touch-action: manipulation; overflow: visible; outline: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.chart.scrub { touch-action: pan-y pinch-zoom; }
:root.zoomed .chart.scrub, :root.zoomed .switch { touch-action: auto; } /* up and down still scroll; sideways scrubs (app.js) */
.chart:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.chart .grid { stroke: var(--separator); stroke-width: 1; }
.chart .axis { stroke: var(--separator); stroke-width: 1; }
.chart text { stroke: none; }
.chart .line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.chart .area { fill: var(--accent); opacity: 0.1; stroke: none; }
.chart .line.down { stroke: var(--down); }
.chart .down-area { fill: var(--down-soft); stroke: none; }
.chart .crosshair { stroke: var(--ink-2); stroke-width: 1; }
.chart .fresh-dot { fill: var(--down); stroke: var(--surface); stroke-width: 2; }
.chart .dot-mark { fill: var(--accent); stroke: var(--surface); stroke-width: 2; }
.sheet .chart .dot-mark { stroke: var(--sheet-group); }
.chart .bar { fill: var(--accent); stroke: none; transition: opacity 150ms ease; }
.chart .bar.empty { fill: var(--fill-strong); }
.chart .bar.dim { opacity: 0.3; }
.chart .bar.picked { opacity: 1; }
.chart .hit { fill: transparent; stroke: none; cursor: pointer; outline: none; }
.chart .hit:focus-visible { fill: var(--fill); }
.chart-readout { font: var(--t-headline); letter-spacing: var(--tr-headline); margin-bottom: var(--sp-8); min-height: 1.3em; }
.chart-x { font: var(--t-caption); letter-spacing: var(--tr-caption); position: relative; display: flex; justify-content: space-between; color: var(--ink-2); margin-top: var(--sp-4); }
.chart-x .mid { position: absolute; transform: translateX(-50%); }
.chart-plot { position: relative; margin-top: var(--sp-16); }
.chart-y { font: var(--t-caption); letter-spacing: var(--tr-caption); position: absolute; inset: 0; pointer-events: none; color: var(--ink-2); }
.chart-y span { position: absolute; left: 0; }
.chart-y span:first-child { top: -1.1rem; right: 0; left: auto; }
.chart-y span:last-child { bottom: 0.15rem; left: 0.2rem; }
.chart .grid.faint { opacity: 0.5; stroke-dasharray: 2 3; }
.chart-days { font: var(--t-caption); letter-spacing: var(--tr-caption); display: grid; text-align: center; color: var(--ink-2); margin-top: var(--sp-4); }

/* An activity indicator in a row's trailing slot. */
.spinner {
  width: 1.1rem; height: 1.1rem; flex: none; border-radius: 50%;
  border: 2px solid var(--fill-strong); border-top-color: var(--ink-2);
  animation: spin 800ms linear infinite;
}
#setup-parks.busy .row:not(:has(.spinner)) { opacity: 0.5; pointer-events: none; }

/* ---- Pull to refresh ---- */
main { position: relative; transition: none; }
#setup { position: relative; }
#setup-ptr { top: calc(env(safe-area-inset-top) + 0.5rem); }
.retry { padding-bottom: var(--sp-8); }
.retry .btn-secondary { margin: var(--sp-8) var(--gutter) 0; width: auto; }
.ptr {
  position: absolute; left: 50%; top: 0; margin-left: calc(-1 * var(--sp-16)); width: 1.8rem; height: 1.8rem;
  opacity: 0; pointer-events: none; color: var(--ink-2);
}
.ptr svg { width: 100%; height: 100%; stroke-width: 2.2; stroke-dasharray: 40 14; }
.ptr.armed { color: var(--accent); }
.ptr.spinning svg { animation: spin 700ms linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- Accessibility preferences ---- */
@media (prefers-reduced-motion: reduce) {
  .pressable, .pressable:active { transform: none !important; }
  .switch::after, .toast { transition-duration: 1ms; }
  .ptr.spinning svg { animation-duration: 2.4s; }
}
@media (prefers-reduced-transparency: reduce) {
  .nav-bar, .tabbar, .toast { background: var(--bg); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-contrast: more) {
  :root { --ink-2: var(--ink); --separator: var(--ink-3); }
  .group { box-shadow: 0 0 0 1px var(--separator); }
}

@media (min-width: 44rem) {
  :root { --gutter: 1.25rem; }
}

/* ---- Accessibility text sizes (html.ax-type, 150% and up) ----
   Stack instead of squeeze: the title and the alerts pill each get the full
   width, list headers wrap, and a row's switch moves under its label. The
   tab bar stays one size, as iOS keeps it. */
.ax-type .nav-inner { flex-wrap: wrap; align-items: flex-start; }
.ax-type .nav-titles { flex-basis: 100%; }
.ax-type .nav .large-title.wrap { -webkit-line-clamp: 3; }
.ax-type .nav .large-title.ax { overflow-wrap: normal; display: block; overflow: visible; }
/* The header scrolls away rather than covering half the screen. */
.ax-type .nav { position: relative; }
.ax-type .pill { margin: var(--sp-8) 0 0; }
.ax-type .list-header { flex-wrap: wrap; gap: var(--sp-4) var(--sp-16); }
.ax-type .ride-row { flex-wrap: wrap; padding-bottom: var(--sp-12); }
.ax-type .ride-row .row-main { flex-basis: 100%; }
.ax-type .ride-row .switch { margin-left: var(--gutter); }
.ax-type .row:has(> .switch) { flex-wrap: wrap; }
.ax-type .row:has(> .switch) .row-label { flex-basis: calc(100% - 3rem); }
.ax-type .stats { grid-template-columns: 1fr; text-align: left; }
.ax-type .stats > div { align-items: flex-start; padding: var(--sp-8) 0; }
.ax-type .stats > div + div { border-left: 0; border-top: 1px solid var(--separator); }
.ax-type .segmented { flex-wrap: wrap; }
.ax-type .segmented button { flex-basis: 45%; }
.ax-type { --tabbar-h: 56px; }
/* Margins stay phone-sized, as iOS keeps them, so the text gets the width. */
.ax-type { --gutter: 16px; }
.ax-type .search-row { flex-wrap: wrap; }
.ax-type .search-row .search { flex-basis: 100%; }
.ax-type .trip-code { margin-left: 0.12em; }
/* A button whose label wraps keeps its icon above the words, not stranded
   beside the first line. */
.ax-type .btn-primary { flex-direction: column; gap: var(--sp-4); padding: var(--sp-8) var(--gutter); }
.ax-type .tab { font-size: min(var(--fs-caption), 12px); }
.ax-type .tab svg { width: 26px; height: 26px; }
.ax-type .badge { font-size: min(var(--fs-caption), 12px); line-height: 18px; min-width: 18px; height: 18px; }
.ax-type .ride-row .meta { align-items: flex-start; }
.ax-type .ride-row .meta .dot { margin-top: 0.4em; }
@media (prefers-color-scheme: dark) { .segmented.wait-limits .chip[aria-pressed='true'] { background: var(--fill-strong); } }

/* ---- Pages: detail screens that push in from the right ---- */
/* Pages stop above the tab bar, which stays in reach as on iOS. */
.pages { position: fixed; inset: 0 0 calc(var(--tabbar-h) + env(safe-area-inset-bottom)) 0; z-index: 40; }
.no-tabbar .pages { bottom: 0; }
.page-shade { position: absolute; inset: 0; background: var(--shade); opacity: 0; pointer-events: none; }
.page {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  background: var(--bg); will-change: transform;
  box-shadow: var(--shadow-page);
}
/* Three columns, as iOS lays out its bar: Back in the first, the title
   centered in the middle, the third as wide as the first so the title stays
   centered. Neither can be drawn over the other (review round 3, M5). The
   title takes its room only once it shows; until then Back has the bar. */
.page-nav {
  flex: none; position: relative; display: grid; align-items: center; min-height: 2.75rem;
  grid-template-columns: minmax(2.75rem, 1fr) minmax(0, auto) minmax(2.75rem, 1fr);
  padding: calc(env(safe-area-inset-top) + var(--sp-4)) var(--sp-8) var(--sp-4);
  background: var(--bg); transition: background-color 200ms ease, box-shadow 200ms ease;
}
.page:not(.titled) .page-nav { grid-template-columns: minmax(0, 1fr) 0 0; }
.page.titled .page-nav {
  background: var(--chrome); box-shadow: 0 1px 0 var(--separator);
  -webkit-backdrop-filter: blur(20px) saturate(180%); backdrop-filter: blur(20px) saturate(180%);
}
.page-back {
  font: var(--t-body); letter-spacing: var(--tr-body);
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 0;
  min-height: 2.75rem;
  grid-column: 1;
  justify-self: start;
  max-width: 100%;
  min-width: 0;
  padding: 0 var(--sp-8) 0 0;
  color: var(--accent);
}
.page-back span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.page-back .back-chevron { width: 1.5rem; height: 1.5rem; stroke-width: 2.2; transform: scaleX(-1); flex: none; }
.page-back:active { opacity: 0.4; transition: none; }
.page-nav-title {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  grid-column: 2;
  min-width: 0;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transition: opacity 150ms ease;
  pointer-events: none;
}
.page.titled .page-nav-title { opacity: 1; }
/* Accessibility sizes: no centered title, as iOS drops it there; Back keeps
   the whole bar. */
.ax-type .page-nav-title { display: none; }
.ax-type .page .page-nav { grid-template-columns: minmax(0, 1fr); }
.page-body {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  padding-bottom: var(--sp-40);
}
.page-body > * { max-width: 40rem; margin-left: auto; margin-right: auto; }
.page-body > .group { margin-left: max(var(--gutter), calc((100% - 40rem) / 2 + var(--gutter))); margin-right: max(var(--gutter), calc((100% - 40rem) / 2 + var(--gutter))); }
.page-title { padding: 0 var(--gutter) 0; }
.page-sub { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); padding: var(--sp-4) var(--gutter) var(--sp-16); }
.page-sub.tint-red { color: var(--down); }

/* ---- Skeletons: the shape of what's coming, not a word ---- */
.sk { display: block; border-radius: 0.35rem; background: var(--fill); animation: sk-pulse 1.4s ease-in-out infinite; }
.sk-line { height: 0.8rem; margin: var(--sp-4) 0; }
.sk-line.w60 { width: 60%; } .sk-line.w50 { width: 50%; } .sk-line.w35 { width: 35%; }
.sk-bar { height: 0.3rem; width: 100%; margin: var(--sp-12) 0 var(--sp-8); border-radius: 999px; }
.sk-num { display: inline-block; width: 2.2rem; height: 1.1rem; vertical-align: middle; }
.sk-big { width: 5.5rem; height: 2.4rem; margin: var(--sp-8) 0 var(--sp-4); }
.barrow .sk-bar { margin: var(--sp-8) 0 0; }
@keyframes sk-pulse { 50% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) { .sk { animation: none; } }

/* Search with its sort toggle beside it. */
.search-row { display: flex; align-items: center; gap: var(--sp-8); margin: var(--sp-4) var(--gutter) 0; }
/* min-width 0: a text field's intrinsic width (about 20 characters) must
   never set the row's, or at large text the page pans sideways. */
.search-row .search { flex: 1; margin: 0; min-width: 0; }
.search input { width: 100%; }
.sort-btn {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: 2.25rem;
  padding: 0 var(--sp-12);
  border-radius: 0.65rem;
  background: var(--fill);
  color: var(--accent);
}
.sort-btn svg { width: 1.05rem; height: 1.05rem; stroke-width: 2; }
.sort-btn:active { opacity: 0.6; transition: none; }

/* "Or use the ntfy app instead": the fallback, folded away under the main path. */
.more { margin: var(--sp-24) var(--gutter) 0; }
.more summary {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  list-style: none;
  cursor: pointer;
  color: var(--accent);
  padding: var(--sp-8) 0;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
}
.more summary::-webkit-details-marker { display: none; }
.more summary::after { content: ''; width: 0.45rem; height: 0.45rem; border: solid currentColor; border-width: 0 2px 2px 0; transform: rotate(45deg); margin-top: calc(-1 * var(--sp-4)); transition: transform 200ms ease; }
.more[open] summary::after { transform: rotate(225deg); margin-top: var(--sp-4); }
.more .steps { padding: var(--sp-8) 0 0; }
.footnote.center { text-align: center; }

/* Wait trend beside a ride's wait: rising in the warning color, falling in green. */
.trend { display: inline-flex; margin-left: var(--sp-4); }
.trend svg { width: 0.95rem; height: 0.95rem; stroke-width: 2.2; }
.trend.up { color: var(--storm); }
.trend.down { color: var(--back); }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Full label colour on the grey track: the secondary one fell short of 4.5:1. */
.segmented .count { color: var(--ink); margin-left: var(--sp-4); }
.page .ptr { top: calc(env(safe-area-inset-top) + 2.9rem); z-index: 2; }

/* ---- Crowd level: one quiet row, a ten-step meter ---- */
.crowd-group { margin-bottom: var(--sp-16); }
.crowd-row .row-label small { margin-top: var(--sp-4); }
.crowd-word { font: var(--t-headline); letter-spacing: var(--tr-headline); }
.crowd-row.stale .crowd-word { color: var(--ink-2); }

/* ---- Wait or go: the verdict, and the chance it's back soon ---- */
.chance {
  position: relative; height: 0.4rem; border-radius: 999px; background: var(--fill);
  margin-top: var(--sp-8); overflow: hidden;
}
.chance span { position: absolute; inset: 0 auto 0 0; } /* square steps; the track rounds the ends */
/* One hue in three steps, darkest for soonest, with a 2px surface gap between steps. */
.chance .c60 { background: var(--accent); opacity: 0.25; }
.chance .c30 { background: var(--accent); opacity: 0.55; box-shadow: 2px 0 0 var(--surface); }
.chance .c15 { background: var(--accent); box-shadow: 2px 0 0 var(--surface); }
.chance-key { font: var(--t-caption); letter-spacing: var(--tr-caption); display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-12); margin-top: var(--sp-8); color: var(--ink-2); }
.chance-key span { display: inline-flex; align-items: center; gap: var(--sp-4); }
.chance-key i { width: 0.55rem; height: 0.55rem; border-radius: 2px; background: var(--accent); display: inline-block; }
.chance-key .k30 { opacity: 0.55; }
.chance-key .k60 { opacity: 0.25; }
.chance-key .chance-label {  }
.outlook-block .chance { margin-top: var(--sp-12); }

/* ---- Best time to ride, and the crowd chart ---- */
.best-line { font: var(--t-subhead); letter-spacing: var(--tr-subhead); margin-bottom: var(--sp-12); }
.chart .bar.soft { opacity: 0.45; }
.chart .line.usual { stroke: var(--ink-2); stroke-width: 2; stroke-dasharray: 4 3; } /* 3:1 or better, and told apart by more than color */
.chart-legend { font: var(--t-caption); letter-spacing: var(--tr-caption); display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-16); margin-top: var(--sp-8); color: var(--ink-2); }
.chart-legend span { display: inline-flex; align-items: center; gap: var(--sp-4); }
.chart-legend i { width: 0.9rem; height: 2px; border-radius: 1px; display: inline-block; }
.lg-today { background: var(--accent); }
.lg-usual { background: repeating-linear-gradient(90deg, var(--ink-2) 0 4px, transparent 4px 7px); }
.lg-max { margin-left: auto; }

/* A row that opens in place: its chevron turns down when open. */
.chevron.turn { transition: transform 200ms ease; }
.chevron.turn.open { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .chevron.turn { transition: none; } }
.recent-row.sub { padding-left: calc(var(--gutter) + var(--sp-16)); }

/* A second paragraph under a sheet's heading, for a caveat. */
.sheet-note { font: var(--t-subhead); letter-spacing: var(--tr-subhead); padding: 0 var(--gutter) var(--sp-8); color: var(--ink-2); overflow-wrap: anywhere; }

/* iPad and wider: Down now's cards in two columns across a wider page,
   instead of one phone-width column with empty sides. Rides and Trip stay
   a comfortable reading width. */
@media (min-width: 48rem) {
  main, .nav-inner { max-width: 56rem; }
  #view-down .cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
  #view-down .cards[data-key=hold] { grid-template-columns: minmax(0, 1fr); }
  #view-rides, #view-more { max-width: 40rem; margin: 0 auto; }
}

.tip-box { margin-top: var(--sp-16); }
.tip-box p { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-bottom: var(--sp-12); }

/* ---- Ride page: one card first, then actions, then one section at a time ---- */
.hero { margin-top: var(--sp-4); }
.hero-kicker { font: var(--t-headline); letter-spacing: var(--tr-headline); display: flex; align-items: center; gap: var(--sp-4); }
.hero-kicker .inline-icon { width: 1rem; height: 1rem; }
.hero-title { font: var(--t-title); letter-spacing: var(--tr-title); margin-top: var(--sp-4); display: flex; align-items: center; gap: var(--sp-8); }
.hero-title .trend svg { width: 1.3rem; height: 1.3rem; }
.hero-sub { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-top: var(--sp-4); }
.hero-tags { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-top: var(--sp-8); }
.hero .chance { margin-top: var(--sp-12); }
.how { margin-top: var(--sp-12); border-top: 1px solid var(--separator); padding-top: var(--sp-8); }
.how summary { font: var(--t-headline); letter-spacing: var(--tr-headline); cursor: pointer; color: var(--accent); list-style: none; }
.how summary::-webkit-details-marker { display: none; }
.how p { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-top: var(--sp-8); }
.actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-8); margin: var(--sp-12) var(--gutter) 0; }
.page-body > .actions { margin-left: max(var(--gutter), calc((100% - 40rem) / 2 + var(--gutter))); margin-right: max(var(--gutter), calc((100% - 40rem) / 2 + var(--gutter))); }
.action {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-8);
  min-height: 2.9rem;
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
}
.action svg { width: 1.15rem; height: 1.15rem; stroke-width: 2; color: var(--ink-2); }
.action.on { color: var(--accent); }
.action.on svg { color: var(--accent); }
.action:active { transform: scale(0.97); }
.page-tabs { margin: var(--sp-24) var(--gutter) var(--sp-12); }
.page-body > .page-tabs { margin-left: max(var(--gutter), calc((100% - 40rem) / 2 + var(--gutter))); margin-right: max(var(--gutter), calc((100% - 40rem) / 2 + var(--gutter))); }

/* Focus moved by the app (a page or sheet opening), not by a keyboard: no ring. */
.quiet-focus:focus, .quiet-focus:focus-visible { outline: none; box-shadow: none; }
.hold-ride.hold-all .row-label { color: var(--accent); }

/* =====================================================================
   Redesign: one calm board under a band of color, and plain words.
   ===================================================================== */

/* ---- Home's header: the band (art in the swappable block at the end), the
   park's name on it as the title, and the lifted card with the headline ---- */
.nav.home-head { margin: 0; padding: 0; background: transparent; }
.home-head .band { height: calc(env(safe-area-inset-top) + 230px); min-height: fit-content; padding-top: calc(env(safe-area-inset-top) + var(--sp-16)); }
.home-head .nav-inner { position: relative; display: block; }
/* The park's name is the title (identity round 8, top-left option 1): the
   heavy rounded face at 28 pt for every park, following Dynamic Type below
   that (the root follows -apple-system-body) but never above it. A long name
   wraps onto a second line, never shrinks. The row ends before x 325 of the
   art box (min(303px, 50vw + 108px)), on a 375 pt phone too. The chevron sits
   in a soft circle on the last line's baseline, 8 pt from the name; that gap
   is capped like the type, so large text never pushes "California Adventure"
   onto a second line on a 393 pt phone. One 44 pt button. */
.park-title { display: inline-flex; align-items: flex-end; min-height: 44px; max-width: min(303px, calc(50vw + 108px)); margin: 0; padding: 0; color: var(--on-band); text-align: left; border-radius: 10px; }
.park-title:active { opacity: 0.6; }
.park-title:focus-visible { outline: 2px solid var(--on-band); outline-offset: 4px; border-radius: 10px; }
.park-title-name { font: var(--t-title); letter-spacing: var(--tr-park); font-size: min(var(--fs-park), 28px); line-height: 1.12; min-width: 0; overflow-wrap: break-word; }
.park-title-end { white-space: nowrap; }
.park-title-chev { display: inline-grid; place-items: center; vertical-align: bottom; width: 26px; height: 26px; border-radius: 13px; margin: 0 0 3px min(var(--sp-8), 8px); background: var(--glass-chev); }
.park-title-chev svg { width: 14px; height: 14px; fill: none; stroke: var(--on-band); stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; }
/* The app tile: on the first-run band and in onboarding (no longer on Home's header). */
.app-tile { width: 46px; height: 46px; border-radius: 11px; flex: none; display: block; box-shadow: 0 0 0 1.5px var(--glass-strong); }
/* The headline and the line under it open the lifted card; the board's
   first card joins under them as one card. */
.today-head {
  position: relative; z-index: 2;
  max-width: calc(40rem - 2 * var(--gutter));
  margin: calc(-1 * var(--sp-56)) var(--gutter) 0;
  padding: var(--sp-16) var(--gutter) var(--sp-12);
  background: var(--surface); color: var(--ink);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
}
@media (min-width: 42rem) { .today-head { margin-left: auto; margin-right: auto; } }
.status-title { font: var(--t-display); letter-spacing: var(--tr-display); font-size: min(var(--fs-display), 30px); text-wrap: balance; }
.today-head .nav-meta { font: var(--t-subhead); letter-spacing: var(--tr-subhead); font-size: min(var(--fs-subhead), 20px); color: var(--ink-2); margin-top: var(--sp-4); }
.today-head #park-meta.warn { color: var(--storm); }
#app:has(#down-list > .lift:first-child) .today-head { border-bottom-left-radius: 0; border-bottom-right-radius: 0; padding-bottom: var(--sp-8); box-shadow: none; }
#down-list > .lift:first-child { margin-top: calc(-1 * var(--sp-8)); border-top-left-radius: 0; border-top-right-radius: 0; box-shadow: var(--shadow-lift), inset 0 1px 0 var(--separator); }
#down-list .lift:not(:first-child) { margin-top: 0; }

/* Rides and More have plain titles; the band is Home's alone. */
.view-title { padding: calc(env(safe-area-inset-top) + var(--sp-16)) calc(var(--gutter) + var(--sp-4)) var(--sp-8); }
body:not(.view-down) #nav { display: none; }
.view-title-wrap { max-width: 40rem; margin: 0 auto; }

/* ---- The board: your rides that are down, one line each ---- */
.lift { position: relative; margin-top: calc(-1 * var(--sp-56)); box-shadow: var(--shadow-lift); }
#view-down { position: relative; z-index: 1; }
.slim { width: 100%; display: flex; align-items: center; gap: var(--sp-8); min-height: 3.2rem; padding: var(--sp-8) var(--sp-12) var(--sp-8) var(--gutter); position: relative; }
.slim:active { background: var(--press); }
.slim .mk { width: 0.75rem; flex: none; display: flex; justify-content: center; align-self: flex-start; margin-top: var(--sp-8); }
.status-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--down); flex: none; }
.status-dot.theirs { background: var(--ink-3); }
.bolt-mark { width: 0.75rem; height: 0.8rem; fill: var(--storm); stroke: none; }
.bolt-mark.theirs { fill: var(--ink-3); }
.slim .rl { font: var(--t-headline); letter-spacing: var(--tr-headline); flex: 1; min-width: 0; }
.slim .rl .nm { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
.slim .rl small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); display: block; color: var(--ink-2); margin-top: 0; }
.slim.quiet .rl { font: var(--t-body); letter-spacing: var(--tr-body); color: var(--ink-2); }
.slim.theirs { min-height: 2.9rem; padding-left: calc(var(--gutter) + var(--sp-8)); }
.slim.theirs .rl { font: var(--t-subhead); letter-spacing: var(--tr-subhead); }
.slim .chevron { margin-left: 0; }
.tile {
  font: var(--t-number); letter-spacing: var(--tr-number);
  white-space: nowrap;
  background: var(--tile);
  color: var(--tile-ink);
  border-radius: 0.5rem;
  padding: var(--sp-4) var(--sp-8);
  flex: none;
}
.tile.quiet { background: var(--fill); color: var(--ink-2); }
.slim.theirs .tile {  }
.more-below { display: none; }

/* ---- Wait bars: one scale for every ride, the usual wait as a tick ---- */
.barrow { width: 100%; display: flex; flex-direction: column; gap: var(--sp-8); padding: var(--sp-12) var(--sp-12) var(--sp-12) var(--gutter); position: relative; }
.barrow:active { background: var(--press); }
.barrow .top2 { display: flex; align-items: baseline; gap: var(--sp-8); }
.barrow .rl { font: var(--t-headline); letter-spacing: var(--tr-headline); flex: 1; min-width: 0; }
.barrow .rl small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); display: block; color: var(--ink-2); margin-top: 0; }
.wait-num { font: var(--t-number); letter-spacing: var(--tr-number); white-space: nowrap; }
.wait-num small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-left: var(--sp-4); }
.wait-word { font: var(--t-headline); letter-spacing: var(--tr-headline); white-space: nowrap; color: var(--ink-2); }
.wait-word.down { color: var(--down); }
.wait-word.weather { color: var(--storm); }
/* --at (0 to 1, set by waitBar()) places the fill's end and the tick on the
   same scale. The fill is never thinner than its round cap, so a 0 wait is a
   dot flush left; the tick runs from flush left to flush right. */
.wbar { --cap: 0.375rem; --tick: 3px; position: relative; height: var(--cap); border-radius: 999px; background: var(--fill); margin-right: var(--sp-4); }
.wbar.out { height: 0; background: none; border-top: 2px dashed var(--down-line); margin-top: var(--sp-4); }
.wbar.out.weather { border-top-color: var(--storm-line); }
.wbar i { --at: 0; position: absolute; left: 0; top: 0; bottom: 0; width: calc(var(--cap) + (100% - var(--cap)) * var(--at)); border-radius: 999px; background: var(--bar); }
.wbar b { --at: 0; position: absolute; top: -0.25rem; left: calc((100% - var(--tick)) * var(--at)); width: var(--tick); height: 0.875rem; margin-left: 0; border-radius: 2px; background: var(--ink); box-shadow: 0 0 0 1.5px var(--surface); }
.sheet .wbar b { box-shadow: 0 0 0 1.5px var(--sheet-group); }
.barrow .ride-tags { display: flex; flex-wrap: wrap; gap: var(--sp-4); }

/* ---- Flip tiles: the return time on a ride page, like a posted-wait sign ---- */
.flip { display: flex; align-items: center; gap: var(--sp-4); margin: var(--sp-4) 0 var(--sp-4); flex-wrap: wrap; }
.flip span {
  font: var(--t-clock); letter-spacing: var(--tr-clock);
  font-size: min(var(--fs-clock), 48px);
  min-width: 1.1em;
  height: 1.45em;
  padding: 0 0.05em;
  border-radius: 0.45rem;
  display: grid;
  place-items: center;
  background: var(--flip);
  color: var(--on-band);
  position: relative;
  box-shadow: var(--flip-shine), 0 0 0 1px var(--flip-edge);
}
.flip span::after { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 1px; background: var(--flip-seam); }
.flip em { font: var(--t-clock); letter-spacing: var(--tr-clock); font-size: min(var(--fs-clock), 48px); font-style: normal; padding: 0 0.05em; }
.flip .suffix { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--ink-2); margin-left: var(--sp-4); align-self: flex-end; margin-bottom: var(--sp-4); }
.flip-pair { display: flex; align-items: center; gap: var(--sp-8); flex-wrap: wrap; }
.flip-pair .flip { margin: var(--sp-4) 0 var(--sp-4); flex-wrap: nowrap; }
.flip-pair { gap: var(--sp-8); }
.flip-pair .flip { gap: var(--sp-4); }
.flip-pair .flip span { font: var(--t-number); letter-spacing: var(--tr-number); }
.flip-pair .flip em { font: var(--t-number); letter-spacing: var(--tr-number); }
.flip-pair .flip .suffix { margin-left: var(--sp-4); }
.flip-to { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
.flip .suffix.weather { color: var(--storm); }
.flabel { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-top: var(--sp-8); }
.big-wait { font: var(--t-clock); letter-spacing: var(--tr-clock); font-size: min(var(--fs-clock), 48px); margin-top: var(--sp-4); }
/* A sentence in the big-number slot ("Not running right now"). */
.big-wait.words { font: var(--t-title); letter-spacing: var(--tr-title); }
.big-wait small { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--ink-2); }
.hero .kicker { font: var(--t-headline); letter-spacing: var(--tr-headline); display: flex; align-items: flex-start; gap: var(--sp-4); }
.hero .kicker svg { width: 1rem; height: 1rem; flex: none; margin-top: 0.1em; }
.kicker.down { color: var(--down); }
.kicker.open { color: var(--back); }
.kicker.weather { color: var(--storm); }
.kicker.closed { color: var(--ink-2); }
.hero .range { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-top: var(--sp-4); }
.hero .wbar { margin-top: var(--sp-12); }
.how-row {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  margin-top: var(--sp-12);
  padding-top: var(--sp-12);
  border-top: 1px solid var(--separator);
  color: var(--accent);
}
.how-row .row-label small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
.how-body { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); margin-top: var(--sp-8); }
.how-body p + p { margin-top: var(--sp-8); }
.note { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); padding: var(--sp-8) calc(var(--gutter) + var(--sp-4)) 0; }
.note.center { text-align: center; }
.page-body > .note { max-width: 40rem; }

.day-head { font: var(--t-subhead); letter-spacing: var(--tr-subhead); display: flex; justify-content: space-between; align-items: baseline; }
.day-head b { font: var(--t-headline); letter-spacing: var(--tr-headline); }
.day-head span { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); }

/* ---- Detail pages: a strip of the same band, the title on it ---- */
.page-strip { position: relative; color: var(--on-band); overflow: hidden; margin: 0 0 var(--sp-16); padding: calc(env(safe-area-inset-top) + var(--sp-56)) var(--gutter) var(--sp-56); }
.page-body > .page-strip { max-width: none; }
/* Nothing truncates: the title is the short name and may wrap; the full
   name, when it differs, goes once under it (review round 2, M7). */
.page-strip .page-title { font: var(--t-display); letter-spacing: var(--tr-display); font-size: min(var(--fs-display), 40px); position: relative; padding: 0; text-wrap: balance; }
.page-sub { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); padding: var(--sp-4) var(--gutter) 0; }
.page-strip .page-sub { position: relative; padding: var(--sp-4) 0 0; color: var(--on-band-2); }
.page-strip .strip-action { position: absolute; right: var(--gutter); top: calc(env(safe-area-inset-top) + 0.35rem); z-index: 2; }
.page.has-strip .page-nav { position: absolute; top: 0; left: 0; right: 0; z-index: 3; background: transparent; }
.page.has-strip:not(.titled) .page-back { color: var(--on-band); }
.page.has-strip.titled .page-nav {
  background: var(--chrome); box-shadow: 0 1px 0 var(--separator);
  -webkit-backdrop-filter: blur(20px) saturate(180%); backdrop-filter: blur(20px) saturate(180%);
}
.page.has-strip .page-body { padding-top: 0; }
.page.has-strip .ptr { top: calc(env(safe-area-inset-top) + 3.3rem); }

/* ---- Rides: filters as chips, grouped by land ---- */
/* How the Rides list is shown: four segments that fit 343 pt and never
   scroll, so the selected one is always in sight (review round 2, M4). At
   large text they wrap into a 2 by 2 grid (.ax-type .segmented). */
.segmented.ride-views { margin-top: var(--sp-12); }
.ride-views button { min-width: 0; padding: 0 var(--sp-4); white-space: nowrap; }
.ax-type .ride-views button { white-space: normal; }
.alerts-line { font: var(--t-subhead); letter-spacing: var(--tr-subhead); display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-16); padding: var(--sp-16) calc(var(--gutter) + var(--sp-4)) 0; color: var(--ink-2); }
.bell-mark { width: 0.85rem; height: 0.85rem; color: var(--accent); vertical-align: -0.1em; margin-left: var(--sp-4); stroke-width: 2; }

/* ---- Choose rides: the picker for alerts ---- */
.pick { width: 100%; display: flex; align-items: center; gap: var(--sp-12); min-height: 3rem; padding: var(--sp-8) var(--gutter); position: relative; }
.pick + .pick::before { left: calc(var(--gutter) + 2.25rem); }
.pick:active { background: var(--press); }
.pick .ring { width: 1.5rem; height: 1.5rem; border-radius: 50%; border: 1.5px solid var(--ink-2); flex: none; display: grid; place-items: center; }
.pick[aria-checked='true'] .ring { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.pick .ring svg { width: 0.9rem; height: 0.9rem; stroke-width: 2.8; opacity: 0; }
.pick[aria-checked='true'] .ring svg { opacity: 1; }
.pick .row-label small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); }

/* ---- Sheets ---- */
.sheet-title { font: var(--t-title); letter-spacing: var(--tr-title); }
.say { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--ink); text-align: center; padding: var(--sp-16) var(--gutter) 0; }
.sheet .note.strong, .note.strong { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink); }
.btn-ghost { font: var(--t-headline); letter-spacing: var(--tr-headline); display: flex; align-items: center; justify-content: center; width: 100%; min-height: 3rem; border-radius: 0.85rem; color: var(--accent); text-align: center; }
.btn-ghost:active { background: var(--press); }
.bigcheck { width: 3.5rem; height: 3.5rem; border-radius: 50%; background: var(--accent); color: var(--on-accent); display: grid; place-items: center; margin: var(--sp-8) auto var(--sp-12); }
.bigcheck svg { width: 1.75rem; height: 1.75rem; stroke-width: 2.6; }
.center-head { text-align: center; }
.center-head h2 { font: var(--t-title); letter-spacing: var(--tr-title); }
.center-head p { color: var(--ink); margin-top: var(--sp-8); }
.wait-nums { display: grid; grid-template-columns: repeat(auto-fit, minmax(3rem, 4.5rem)); justify-content: center; gap: var(--sp-8); padding: 0 var(--gutter); }
.wait-nums button { font: var(--t-number); letter-spacing: var(--tr-number); min-height: 3rem; border-radius: 0.75rem; background: var(--sheet-group); text-align: center; }
.wait-nums button[aria-checked='true'] { background: var(--sheet-group); color: var(--accent); box-shadow: inset 0 0 0 2.5px var(--accent); }
.wait-nums + .note { text-align: center; }
.scope { margin: 0 var(--gutter) var(--sp-8); }

/* ---- First open: the band, then the one lifted card with the two ways
   in, then the parks and the code (DIRECTION.md 6: band, lifted card) ---- */
.band.setup-band {
  padding: calc(env(safe-area-inset-top) + var(--sp-16)) max(var(--sp-20), calc((100% - 34rem) / 2 + var(--sp-20))) calc(var(--sp-56) + var(--sp-40));
  background: linear-gradient(165deg, var(--band-1), var(--band-2)); color: var(--on-band);
}
.setup-top { display: flex; align-items: center; gap: var(--sp-12); min-height: 2.75rem; }
.setup-app { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--on-band); }
.setup-title { font: var(--t-display); letter-spacing: var(--tr-display); color: var(--on-band); margin-top: var(--sp-24); text-wrap: balance; }
.setup-lede { font: var(--t-body); letter-spacing: var(--tr-body); color: var(--on-band-2); margin-top: var(--sp-8); max-width: 26rem; }
.setup { max-width: 34rem; margin: 0 auto; padding: 0 0 calc(env(safe-area-inset-bottom) + var(--sp-56)); }
.setup-card {
  position: relative; z-index: 1; display: flex; flex-direction: column; gap: var(--sp-12);
  margin: calc(-1 * var(--sp-56)) var(--gutter) 0; padding: var(--sp-16);
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-lift);
}
.setup-card .status-line { padding: 0; min-height: 0; }
.setup-card .status-line:empty { display: none; }
.setup-card .btn-stack { padding: 0; }
/* The trip code, inside the first card (review round 2, m20). */
.setup-card .join-card { padding-right: var(--sp-4); border-radius: 0.75rem; box-shadow: inset 0 0 0 1.5px var(--separator); }
.setup-card .join-card input { padding: var(--sp-12); }
.join-note { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); text-wrap: pretty; }
.join-note.warn { color: var(--storm); }
/* A resort's name over its parks: a caption, not a second heading. */
.group-caption { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--ink-2); padding: var(--sp-16) calc(var(--gutter) + var(--sp-4)) var(--sp-8); }
.btn-outline { background: var(--surface); color: var(--accent); box-shadow: inset 0 0 0 1.5px var(--accent); }
.unofficial { font: var(--t-subhead); letter-spacing: var(--tr-subhead); text-align: center; color: var(--ink-2); padding: var(--sp-20) var(--gutter) 0; }
.unofficial.credit { padding-top: var(--sp-8); }
.unofficial a { color: var(--accent); }

/* ---- Large text: rows grow, titles stop at 1.3 times ---- */
.ax-type .slim, .ax-type .barrow .top2 { flex-wrap: wrap; }
.ax-type .slim .rl { flex-basis: calc(100% - 2rem); }
.ax-type .slim .rl .nm, .ax-type .slim .rl small { white-space: normal; }
.ax-type .slim .chevron { display: none; }
.ax-type .flip { gap: var(--sp-4); }

.sheet .note { padding-left: var(--gutter); padding-right: var(--gutter); }
.state-text { color: var(--ink); }
.section-label.in-card { padding: var(--sp-12) var(--gutter) 0; }
.up-mark { width: 1rem; height: 1rem; color: var(--back); }
.trend-mark { width: 1rem; height: 1rem; color: var(--accent); }
.moon-mark { width: 1rem; height: 1rem; color: var(--ink-2); }
.help-list { margin: var(--sp-8) 0 0 var(--sp-20); color: var(--ink-2); font: var(--t-subhead); letter-spacing: var(--tr-subhead); }
.how-wrap summary { list-style: none; cursor: pointer; }
.how-wrap summary::-webkit-details-marker { display: none; }
.how-wrap .chevron { transition: transform 200ms ease; }
.how-wrap[open] .chevron { transform: rotate(90deg); }
.page-body > .spaced-sm { margin-top: var(--sp-16); }

.more-below { display: none; }
.ax-type .slim .rl .nm { -webkit-line-clamp: unset; display: block; }
.ax-type .more-below {
  font: var(--t-headline); letter-spacing: var(--tr-headline);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  width: 100%;
  padding: var(--sp-12) 0 0;
  color: var(--accent);
}
.ax-type .more-below svg { width: 1rem; height: 1rem; transform: rotate(90deg); stroke-width: 2.4; }

/* Large text: the band keeps a 24 pt foot under the card's overlap, so the
   headline, the strip and the first down ride stay above the fold (review
   round 2, M15). */
.ax-type .home-head .band { height: auto; padding-bottom: calc(var(--sp-56) + var(--sp-24)); }

/* No word left alone on a last line. Ignored where unsupported. */
.footnote, .note, .sheet-note, .sheet-head p, .row-label small, .slim .rl small, .hero .range, .state-text, .range { text-wrap: pretty; }
.today-head .nav-meta { text-wrap: balance; }

/* ---- Rides tab: a bell beside each ride turns its alerts on or off ---- */
.ride-wrap { display: flex; align-items: stretch; position: relative; }
.ride-wrap > .barrow { flex: 1; min-width: 0; padding-right: var(--sp-4); }
.ride-wrap + .ride-wrap::before { z-index: 1; }
.follow-btn { flex: none; width: 2.9rem; display: grid; place-items: center; color: var(--ink-3); }
.follow-btn svg { width: 1.25rem; height: 1.25rem; }
.follow-btn[aria-pressed='true'] { color: var(--accent); }
.follow-btn[aria-pressed='true'] svg { fill: currentColor; }
.alerts-acts { display: flex; gap: var(--sp-4); }
.alerts-acts .text-btn { min-height: 2.75rem; padding: 0 var(--sp-8); margin: calc(-1 * var(--sp-8)) 0; }
.alerts-acts .text-btn:disabled { color: var(--ink-3); }

/* ---- Wait alert: a slider in fives ---- */
.wait-slider { display: flex; flex-direction: column; gap: var(--sp-8); padding: var(--sp-8) var(--gutter) var(--sp-4); }
.wait-ask { font: var(--t-body); letter-spacing: var(--tr-body); color: var(--ink-2); }
.wait-ask b { font: var(--t-clock); letter-spacing: var(--tr-clock); display: block; color: var(--ink); }
/* DIRECTION.md 6: a 28 pt thumb on a 6 pt track, a tick every 5 min under
   it (review round 3, m3). The track fills with accent up to the thumb
   (--fill-to, set as it moves). The ticks sit on the thumb's travel, inset
   by half a thumb at each end. */
.wait-range { position: relative; display: block; }
.wait-slider input[type=range] {
  -webkit-appearance: none; appearance: none; display: block;
  --fill-to: 50%;
  width: 100%; height: 2.75rem; margin: 0; background: transparent;
}
.wait-slider input[type=range]::-webkit-slider-runnable-track {
  height: 0.375rem; border-radius: 999px;
  background: linear-gradient(to right, var(--accent) var(--fill-to), var(--fill-strong) var(--fill-to));
}
.wait-slider input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 1.75rem; height: 1.75rem; margin-top: -0.6875rem; border-radius: 50%;
  background: var(--knob); box-shadow: var(--shadow-knob);
}
.wait-slider input[type=range]::-moz-range-track { height: 0.375rem; border-radius: 999px; background: var(--fill-strong); }
.wait-slider input[type=range]::-moz-range-progress { height: 0.375rem; border-radius: 999px; background: var(--accent); }
.wait-slider input[type=range]::-moz-range-thumb { width: 1.75rem; height: 1.75rem; border: 0; border-radius: 50%; background: var(--knob); box-shadow: var(--shadow-knob); }
.wait-slider input[type=range]:focus-visible { outline: none; }
.wait-slider input[type=range]:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--accent); outline-offset: 2px; }
.wait-ticks { position: absolute; left: 0.875rem; right: 0.875rem; top: calc(50% + 1rem); height: 0.375rem; pointer-events: none; }
.wait-ticks i { position: absolute; top: 0; width: 2px; height: 100%; margin-left: -1px; border-radius: 1px; background: var(--ink-3); }
.wait-ends { font: var(--t-caption); letter-spacing: var(--tr-caption); display: flex; justify-content: space-between; color: var(--ink-2); margin-top: 0; }

/* ---- More: grouped sections in order of use, an invite card first while alone ---- */
.invite-card { margin-top: var(--sp-8); margin-bottom: var(--sp-8); padding: var(--sp-16); box-shadow: var(--shadow-lift); }
.ic-head { display: flex; align-items: flex-start; gap: var(--sp-12); margin-bottom: var(--sp-16); }
.ic-icon { width: 2.25rem; height: 2.25rem; flex: none; padding: var(--sp-8); border-radius: 0.6rem; background: var(--accent-soft); color: var(--accent); stroke-width: 1.8; }
.ic-text { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); display: flex; flex-direction: column; gap: var(--sp-4); }
.ic-text b { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--ink); }
/* The trip code, said once on More: here while the card leads (review round 3, M7). */
.ic-code { display: flex; align-items: baseline; flex-wrap: wrap; column-gap: var(--sp-8); }
.ic-code small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
.ic-code .trip-code { margin: 0; color: var(--ink); }
/* A hold row's names: under its title, the row's full width, two names at
   most, so never past two lines (review round 3, m5). */
.downrow > .nm .hold-names { display: block; margin-top: var(--sp-4); font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
#view-more [id^='sec-'] { scroll-margin-top: calc(env(safe-area-inset-top) + 3.5rem); }

.code-row { align-items: center; }
.code-row .row-label small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); display: block; color: var(--ink-2); margin: 0 0 0; }
.code-row .trip-code { margin: 0; display: block; }
.btn-pill { font: var(--t-headline); letter-spacing: var(--tr-headline); display: inline-flex; align-items: center; gap: var(--sp-4); min-height: 2.5rem; padding: 0 var(--sp-16); border-radius: 999px; background: var(--accent); color: var(--on-accent); flex: none; }
.btn-pill svg { width: 1.05rem; height: 1.05rem; stroke-width: 2; }

/* ---- Busy meter: four steps beside the hours ---- */
.crowd-meter { display: inline-flex; align-items: center; gap: var(--sp-4); margin-left: var(--sp-8); vertical-align: 0.05em; white-space: nowrap; }
.crowd-meter i { width: 0.8rem; height: 0.45rem; border-radius: 2px; background: var(--meter-off); }
.crowd-meter i.on { background: var(--accent); }
.crowd-meter b { font-weight: inherit; margin-left: var(--sp-4); }

.today-head .nav-meta { flex-wrap: wrap; row-gap: var(--sp-4); }
.today-head #park-meta { flex: 0 1 auto; }
.crowd-meter { flex: none; }

/* ---- Onboarding: full screen, the trip's band behind the top, each card's
   picture lifted over its foot, swiped sideways or stepped with Next ---- */
.onboard-screen { position: fixed; inset: 0; z-index: 60; display: flex; flex-direction: column; color: var(--ink); background: var(--bg); animation: ob-in 320ms ease both; }
.onboard-screen.leaving { animation: ob-out 260ms ease both; }
@keyframes ob-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes ob-out { to { opacity: 0; } }
.onboard-screen .ob-band { position: absolute; inset: 0 0 auto; height: calc(env(safe-area-inset-top) + 12.5rem); }
.ob-top { position: relative; z-index: 2; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-12); padding: calc(env(safe-area-inset-top) + var(--sp-8)) var(--gutter) 0; }
.ob-lockup { display: inline-flex; align-items: center; gap: var(--sp-12); min-width: 0; }
.ob-app { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--on-band); }
.ob-skip { font: var(--t-headline); letter-spacing: var(--tr-headline); color: var(--on-band); min-height: 2.75rem; min-width: 2.75rem; padding: 0 var(--sp-8); text-align: center; }
.ob-skip:active { opacity: 0.6; }
.ob-track { position: relative; z-index: 1; flex: 1; min-height: 0; display: flex; overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; scrollbar-width: none; overscroll-behavior: contain; }
.ob-track::-webkit-scrollbar { display: none; }
/* A card taller than the screen (large text) scrolls on its own. */
.ob-slide { flex: 0 0 100%; scroll-snap-align: center; overflow-y: auto; overscroll-behavior: contain; padding: var(--sp-24) var(--gutter) var(--sp-16); }
.ob-slide > * { max-width: 30rem; margin-left: auto; margin-right: auto; }
/* More of the card below the fold: its foot fades (set while the card can
   still scroll down, app.js openOnboarding). */
.ob-slide.ob-fade {
  -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 2.5rem), transparent);
  mask-image: linear-gradient(to bottom, black calc(100% - 2.5rem), transparent);
}
.ob-art { display: flex; align-items: center; justify-content: center; min-height: 9.5rem; margin-bottom: var(--sp-24); }
/* A short screen (iPhone SE at 320 x 568): the cards keep their words above
   the dots; the space around the picture gives way. */
@media (max-height: 600px) {
  .ob-slide { padding-top: var(--sp-16); }
  .ob-art { margin-bottom: var(--sp-16); }
}
.ob-title { font: var(--t-display); letter-spacing: var(--tr-display); font-size: min(var(--fs-display), 40px); text-wrap: balance; padding: 0 var(--sp-4); }
.ob-text { font: var(--t-body); letter-spacing: var(--tr-body); color: var(--ink-2); margin-top: var(--sp-8); padding: 0 var(--sp-4); }
.ob-foot { position: relative; z-index: 1; width: 100%; max-width: 32rem; margin: 0 auto; padding: var(--sp-8) var(--gutter) calc(env(safe-area-inset-bottom) + var(--sp-12)); display: flex; flex-direction: column; gap: var(--sp-4); }
.ob-later { font: var(--t-headline); letter-spacing: var(--tr-headline); align-self: center; min-height: 2.75rem; padding: 0 var(--sp-16); color: var(--accent); text-align: center; }
.ob-dots { display: flex; justify-content: center; gap: var(--sp-8); margin-bottom: var(--sp-8); }
.ob-dots i { width: 0.5rem; height: 0.5rem; border-radius: 999px; background: var(--fill-strong); transition: width 200ms ease; }
.ob-dots i.on { width: 1.4rem; background: var(--accent); }
/* The cards' pictures: the app's own pieces on a lifted card. */
.ob-card, .ob-tiles {
  width: 100%; max-width: 22rem; display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-8);
  padding: var(--sp-16); border-radius: var(--radius); background: var(--surface); color: var(--ink); box-shadow: var(--shadow-lift);
}
.ob-ride { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-8); width: 100%; }
.ob-ride b { font: var(--t-headline); letter-spacing: var(--tr-headline); }
.ob-cap, .ob-tiles .flabel { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); margin-top: var(--sp-4); }
.ob-trip { align-items: center; text-align: center; }
.ob-code { font: var(--t-number); letter-spacing: var(--tr-code); padding: var(--sp-8) var(--sp-16) var(--sp-8) calc(var(--sp-16) + 0.14em); border-radius: 0.75rem; box-shadow: inset 0 0 0 1.5px var(--accent); }
.ob-park { font: var(--t-subhead); letter-spacing: var(--tr-subhead); display: inline-flex; align-items: center; gap: var(--sp-4); color: var(--ink-2); }
.ob-park svg { width: 1rem; height: 1rem; color: var(--accent); }
.ob-lines { padding: var(--sp-4) 0; }
.ob-lines .barrow { width: 100%; }
.ob-pushes { width: 100%; max-width: 22rem; display: flex; flex-direction: column; gap: var(--sp-8); }
.ob-push { display: flex; align-items: flex-start; gap: var(--sp-12); padding: var(--sp-12) var(--sp-16); border-radius: var(--radius); background: var(--surface); color: var(--ink); box-shadow: var(--shadow-lift); }
.ob-push img { flex: none; width: 2.375rem; height: 2.375rem; border-radius: 0.5625rem; }
.ob-push-body { font: var(--t-subhead); letter-spacing: var(--tr-subhead); flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ob-push-body b { font: var(--t-headline); letter-spacing: var(--tr-headline); font-size: var(--fs-subhead); }
.ob-push-body span { color: var(--ink-2); }
.ob-push-now { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); }
.ob-mark, .ob-bell { width: 6rem; height: 6rem; margin: var(--sp-16) 0; border-radius: 50%; display: grid; place-items: center; background: var(--surface); color: var(--accent); box-shadow: var(--shadow-lift); animation: ok-pop 500ms cubic-bezier(0.2, 1.4, 0.4, 1) both; }
@keyframes ok-pop { from { transform: scale(0.6); opacity: 0; } to { transform: none; opacity: 1; } }
.ob-mark svg, .ob-bell svg { width: 2.75rem; height: 2.75rem; stroke-width: 2; }
@media (prefers-reduced-motion: reduce) { .onboard-screen, .onboard-screen.leaving, .ob-mark, .ob-bell { animation: none; } .ob-dots i { transition: none; } }

/* ---- The board (build package 3): the back time is the hero ----
   A down row puts the name on its own line, the land and the status pill
   under it on the left, and the key box on the right. Every key box has
   the same minimum width, so the times line up as a departure board. */
.slim.downrow {
  display: grid; grid-template-columns: minmax(7.5rem, 1fr) auto; grid-template-areas: 'nm nm' 'meta key';
  column-gap: var(--sp-12); row-gap: var(--sp-4); align-items: center;
  padding: var(--sp-12) var(--gutter); text-align: left;
}
.downrow > .nm { grid-area: nm; font: var(--t-headline); letter-spacing: var(--tr-headline); }
.downrow .dr-meta { grid-area: meta; display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-4); min-width: 0; }
.downrow .dr-meta small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
.downrow > .keybox, .downrow > .dr-side { grid-area: key; justify-self: end; }
/* One width down the column, so the times line up. The land and the pill
   keep a floor of their own (the column above): the box gives way, never
   lies over them (review round 2, B1). */
.downrow > .keybox { min-width: 10rem; max-width: 62vw; }
.downrow > .keybox.words .kv { white-space: nowrap; }
.downrow.theirs > .keybox { width: 9rem; min-height: 3rem; }
.downrow .dr-meta > * { max-width: 100%; }
/* iPhone SE (375 pt) and other screens up to 390 pt: a narrower box whose words and
   windows wrap inside it ("Longer than / usual", "2:30 to / 3:00 PM"). */
@media (max-width: 390px) {
  .downrow > .keybox { min-width: 8.5rem; max-width: 100%; }
  .downrow > .keybox .kv, .downrow > .keybox.words .kv { white-space: normal; }
}
/* 320 pt (iPhone SE first generation, Display Zoom): a tighter box, so the
   meta column keeps its 7 rem. */
@media (max-width: 359px) {
  .slim.downrow { grid-template-columns: minmax(7rem, 1fr) auto; column-gap: var(--sp-8); }
  .downrow > .keybox, .downrow.theirs > .keybox { width: auto; min-width: 7.25rem; padding-left: var(--sp-8); padding-right: var(--sp-8); }
}
/* Narrower than that, the box goes under the pill, as at large text. */
@media (max-width: 299px) {
  .slim.downrow { grid-template-columns: minmax(0, 1fr); grid-template-areas: 'nm' 'meta' 'key'; }
  .downrow > .keybox, .downrow > .dr-side { justify-self: start; }
  .downrow > .keybox { min-width: 0; }
}
.dr-side { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); text-align: right; }
.slim.downrow.theirs { padding-left: calc(var(--gutter) + var(--sp-8)); }
.downrow.theirs > .nm { font: var(--t-subhead); letter-spacing: var(--tr-subhead); }

/* The key box: solid accent for a time or a window, dashed grey for no
   time yet, dashed amber for the weather (DIRECTION.md 6). */
.keybox {
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center; flex: none;
  min-width: 6.75rem; min-height: 3.375rem; padding: var(--sp-4) var(--sp-12);
  border-radius: 0.75rem; border: 1.5px solid var(--accent); color: var(--ink); text-align: center;
}
.keybox .kv { font: var(--t-number); letter-spacing: var(--tr-number); white-space: nowrap; }
.keybox .kv small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
.keybox .kn { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); }
.keybox.words .kv { font: var(--t-headline); letter-spacing: var(--tr-headline); white-space: normal; }
.keybox.dashed { border-style: dashed; border-color: var(--ink-3); }
.keybox.storm { border-style: dashed; border-color: var(--storm); color: var(--storm); }
.keybox.storm .kn { color: var(--storm); }
.keybox.lock { flex-direction: row; gap: var(--sp-4); border-style: dashed; border-color: var(--ink-3); color: var(--ink-2); }
.keybox.lock .kv { font: var(--t-headline); letter-spacing: var(--tr-headline); }
/* On a ride's page, a window: one large box, never six tiles. */
.keybox.large { align-items: flex-start; margin: var(--sp-4) 0; padding: var(--sp-12) var(--sp-16); }
.keybox.large .kv { font: var(--t-title); letter-spacing: var(--tr-title); }

/* Status pills: soft, never loud. A dot, or a glyph, and the words. */
.spill {
  font: var(--t-caption); letter-spacing: var(--tr-caption);
  display: inline-flex; align-items: center; gap: var(--sp-4); min-height: 1.375rem; padding: 0 var(--sp-8);
  border-radius: 999px; white-space: nowrap; max-width: 100%;
  color: var(--paused); background: var(--paused-soft); box-shadow: inset 0 0 0 1px var(--paused-line);
}
.spill.wrap { white-space: normal; border-radius: 0.6875rem; padding-top: 0.125rem; padding-bottom: 0.125rem; }
.spill i { width: 0.375rem; height: 0.375rem; border-radius: 50%; background: currentColor; flex: none; }
.spill svg { width: 0.75rem; height: 0.75rem; flex: none; stroke-width: 2.4; }
.spill.down { color: var(--down); background: var(--down-soft); box-shadow: inset 0 0 0 1px var(--down-line); }
.spill.storm { color: var(--storm); background: var(--storm-soft); box-shadow: inset 0 0 0 1px var(--storm-line); }
.spill.back, .spill.good { color: var(--back); background: var(--back-soft); box-shadow: inset 0 0 0 1px var(--back-line); }

/* The lifted strip: three numbers over their labels, 1px between. */
.strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); padding: var(--sp-16) var(--sp-8); text-align: center; }
.strip > div { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-4); min-width: 0; padding: 0 var(--sp-4); }
.strip > div + div { border-left: 1px solid var(--separator); }
.strip .sv { font: var(--t-number); letter-spacing: var(--tr-number); white-space: nowrap; }
.strip .sv small { font: var(--t-number); letter-spacing: var(--tr-number); }
.strip .sv small.unit { font: var(--t-headline); letter-spacing: var(--tr-headline); }
.strip .sv.accent { color: var(--accent); }
.strip .sv.down { color: var(--down); }
.strip span { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); white-space: nowrap; }

/* A section heading with a quiet note, or an action, on its right. */
/* The heading never breaks inside its words for the note: when the two
   don't fit on one line, the note wraps to its own line under it (review
   round 2, M5). */
.section-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; padding-right: calc(var(--gutter) + var(--sp-4)); }
.section-head .section-label { flex: 0 1 auto; min-width: 0; }
.section-aside { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); flex: 0 1 auto; min-width: 0; }
/* Wrapped under the heading, the note lines up with it. */
.section-aside, .sec-head .sec-hint { padding: 0 0 var(--sp-12) calc(var(--gutter) + var(--sp-4)); }
.section-head .section-act { margin-left: auto; }
.section-act { font: var(--t-headline); letter-spacing: var(--tr-headline); font-size: var(--fs-subhead); color: var(--accent); min-height: 2.75rem; white-space: nowrap; }

/* A ride's page: the pill, and since when, over the answer. */
.kick-row { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--sp-8); }
.kick-row > span:not(.spill) { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
.barrow .rl .row-sub { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4) var(--sp-8); }

/* Large text: a down row stacks, the key box under the pill. */
html.ax-type .slim.downrow { grid-template-columns: minmax(0, 1fr); grid-template-areas: 'nm' 'meta' 'key'; }
html.ax-type .downrow > .keybox, html.ax-type .downrow > .dr-side { justify-self: start; }
html.ax-type .downrow > .keybox { min-width: 0; max-width: 100%; }
html.ax-type .downrow > .keybox.words .kv { white-space: normal; }
/* The land and the pill share a line when both fit, and the row's padding
   stays phone-sized, so the first ride clears the tab bar (M4). */
html.ax-type .slim.downrow { row-gap: 4px; padding-top: 8px; padding-bottom: 8px; }
/* A hold row's names, as the meta line and the strip above: capped at
   20 pt, and the key box no taller than its words. */
html.ax-type .downrow > .nm .hold-names { font-size: min(var(--fs-subhead), 20px); }
html.ax-type .downrow > .keybox { min-height: 0; }
html.ax-type .downrow .dr-meta { flex-direction: row; flex-wrap: wrap; align-items: center; column-gap: var(--sp-8); }

/* ---- Waits today: one chart opening to close, three zooms, the best times left (DIRECTION.md 6) ---- */
.chart .now-mark { stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 2 3; }
.chart.wait .line { stroke-width: 2.4; }
.chart.wait .area { opacity: 0.08; }
.chart.wait .line.usual { stroke-width: 1.6; }
.chart.wait .line.down { stroke-width: 2; }
.chart .pick-band { fill: var(--accent); opacity: 0.14; stroke: none; }
.chart-readout b { font-weight: inherit; }
.chart-readout b.down { color: var(--down); }
.chart-readout span { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
.chart-plot.wc { margin-top: var(--sp-8); }
.wc-labels { font: var(--t-caption); letter-spacing: var(--tr-caption); position: absolute; inset: 0; pointer-events: none; color: var(--ink-2); }
.wc-y { position: absolute; left: 0; transform: translateY(-50%); }
.wc-tag { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; }
.wc-tag.end { transform: translateX(-100%); }
.wc-tag.start { transform: none; }
.wc-tag.usual { right: 0; transform: none; }
.wc-tag.down { color: var(--down); }
.chart-x.wc-x { min-height: 1.333em; }
.wc-x .mid.start { transform: none; }
.wc-x .mid.end { transform: translateX(-100%); }
/* The zooms: three small chips under the axis, at its right, 28 pt drawn
   with a 44 pt hit area (review round 3, M3). The chosen one is the
   selected tint; the others are quiet. At large text, a menu as small. */
.chart-range { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--sp-8); margin-top: var(--sp-12); }
.chart-range button {
  font: var(--t-caption); letter-spacing: var(--tr-caption);
  position: relative; min-height: 1.75rem; min-width: 2.75rem; padding: 0 var(--sp-12); border-radius: 999px;
  background: var(--fill); color: var(--ink-2); transition: background-color 180ms ease, color 180ms ease;
}
.chart-range button::before { content: ''; position: absolute; inset: -0.5rem 0; }
.chart-range button[aria-checked='true'] { background: var(--accent-soft); color: var(--accent); }
.range-pop { display: none; }
.ax-type .chart-range { display: none; }
.ax-type .range-pop {
  font: var(--t-subhead); letter-spacing: var(--tr-subhead);
  display: flex; position: relative; align-items: center; justify-content: center;
  width: max-content; max-width: 100%; min-height: 2.75rem; margin: var(--sp-12) 0 0 auto; padding: 0 var(--sp-16);
  border-radius: 999px; background: var(--fill); color: var(--accent);
}
.range-pop-face { display: inline-flex; align-items: center; gap: var(--sp-4); }
.range-pop-face svg { width: 1.1rem; height: 1.1rem; stroke-width: 2.2; }
.range-pop select { font: var(--t-body); position: absolute; inset: 0; width: 100%; opacity: 0; }
.best-head { font: var(--t-headline); letter-spacing: var(--tr-headline); margin-top: var(--sp-20); }
.best-list { margin: var(--sp-4) calc(-1 * var(--gutter)) calc(-1 * var(--sp-16)); }
.best-row {
  display: grid; grid-template-columns: minmax(4.5rem, auto) minmax(2rem, 1fr) auto; align-items: center; gap: var(--sp-16);
  position: relative; width: 100%; min-height: 3.25rem; padding: var(--sp-4) var(--gutter); text-align: left; color: var(--ink);
  transition: background-color 180ms ease;
}
.best-row + .best-row::before { content: ''; position: absolute; top: 0; left: var(--gutter); right: var(--gutter); border-top: 1px solid var(--separator); }
.best-row[aria-pressed='true'] { background: var(--accent-soft); }
/* 375 to 400 pt: a window ("11 AM to 1:20 PM") takes the line; the bar
   sits under it, never under the words. */
@media (max-width: 400px) {
  html:not(.ax-type) .best-row { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: 'time wait' 'bar wait'; row-gap: var(--sp-4); padding-top: var(--sp-8); padding-bottom: var(--sp-8); }
  html:not(.ax-type) .best-row .bt-time { grid-area: time; }
  html:not(.ax-type) .best-row .bt-bar { grid-area: bar; }
  html:not(.ax-type) .best-row .bt-wait { grid-area: wait; }
}
.best-row:last-child { border-bottom-left-radius: var(--radius); border-bottom-right-radius: var(--radius); }
.bt-time { font: var(--t-number); letter-spacing: var(--tr-number); white-space: nowrap; }
.bt-bar { height: 6px; border-radius: 3px; background: var(--fill); overflow: hidden; }
.bt-bar i { display: block; height: 100%; border-radius: 3px; background: var(--ink-3); }
.best-row.top .bt-bar i { background: var(--ink); }
.bt-wait { font: var(--t-headline); letter-spacing: var(--tr-headline); display: flex; flex-direction: column; align-items: flex-end; white-space: nowrap; }
.bt-wait small { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); }
.best-now { font: var(--t-subhead); letter-spacing: var(--tr-subhead); margin-top: var(--sp-16); color: var(--ink-2); }
/* Large text: the time on one line, "usually 25 min" under it, no bar. */
.ax-type .best-row { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); padding-top: var(--sp-8); padding-bottom: var(--sp-8); }
.ax-type .bt-bar { display: none; }
.ax-type .bt-wait { flex-direction: row-reverse; justify-content: flex-end; align-items: baseline; gap: 0.3em; white-space: normal; }
.ax-type .bt-wait small { font: var(--t-headline); letter-spacing: var(--tr-headline); }

/* ---- Ride page: stats strip, best-time chips, action row ---- */
.stat-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); padding: var(--sp-16) var(--sp-8); margin-top: var(--sp-12); text-align: center; }
.stat-strip div { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }
.stat-strip div + div { border-left: 1px solid var(--separator); }
.stat-strip b { font: var(--t-number); letter-spacing: var(--tr-number); }
.stat-strip span { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); }
.act-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }
.act { display: flex; flex-direction: column; align-items: center; gap: var(--sp-4); padding: var(--sp-12) var(--sp-4); min-height: 5.2rem; text-align: center; color: var(--accent); }
.act + .act { border-left: 1px solid var(--separator); }
.act svg { width: 1.5rem; height: 1.5rem; }
.act span { font: var(--t-headline); letter-spacing: var(--tr-headline); font-size: var(--fs-subhead); color: var(--ink); }
.act small { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); }
.act:active { background: var(--press); }

/* ---- Trend arrow under a ride's wait ---- */
.wait-col { display: flex; flex-direction: column; align-items: flex-end; gap: 0; flex: none; }
.trend { font: var(--t-caption); letter-spacing: var(--tr-caption); }
.trend.down { color: var(--back); }
.trend.up { color: var(--storm); }

.repeat-row { margin: var(--sp-8) 0 0; padding: var(--sp-4) var(--gutter); background: none; box-sizing: border-box; width: 100%; }

/* ---- Billing: the paywall, the free-day card and locked back times (billing.js) ---- */
.pw-lock { width: 0.8rem; height: 0.8rem; stroke-width: 2.2; flex: none; }
.pw-lock.inline { margin-left: var(--sp-4); vertical-align: -0.05em; color: var(--ink-2); }
.tile.when-lock { display: inline-flex; align-items: center; gap: var(--sp-4); }
.when-lock .pw-lock { color: inherit; }
/* The return time on a ride's page, before there is a pass: the tiles dimmed, no digits. */
.flip.locked span { background: var(--fill-strong); color: var(--ink-3); box-shadow: none; }
.flip.locked span::after { background: var(--separator); }
.flip.locked em { color: var(--ink-3); }
.pw-see { font: var(--t-headline); letter-spacing: var(--tr-headline); display: block; margin-top: var(--sp-4); }
#row-pass.static { cursor: default; }
/* A free day ready: the accent, never amber (amber is the weather's alone). */
#row-pass .row-detail.accent { color: var(--accent); }
#lbl-crowd small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); display: block; color: var(--ink-2); margin-top: 0; }

.pw-features { list-style: none; padding: 0 var(--gutter); display: flex; flex-direction: column; gap: var(--sp-8); margin-bottom: var(--sp-16); }
.pw-features li { font: var(--t-headline); letter-spacing: var(--tr-headline); display: flex; align-items: center; gap: var(--sp-12); }
.pw-features svg { width: 1.4rem; height: 1.4rem; color: var(--accent); }
.pw-status { font: var(--t-headline); letter-spacing: var(--tr-headline); margin: 0 var(--gutter) var(--sp-16); padding: var(--sp-8) var(--sp-12); border-radius: 0.7rem; background: var(--accent-soft); color: var(--accent); }
.pw-options { display: flex; flex-direction: column; gap: var(--sp-8); padding: 0 var(--gutter); }
.pw-opt { display: flex; align-items: center; gap: var(--sp-12); width: 100%; min-height: 3.4rem; padding: var(--sp-8) var(--sp-16); border-radius: 0.9rem; background: var(--fill); }
.pw-opt[aria-checked='true'] { background: var(--accent-soft); box-shadow: inset 0 0 0 1.5px var(--accent); }
.pw-opt:disabled { opacity: 0.6; }
.pw-radio { flex: none; width: 1.35rem; height: 1.35rem; border-radius: 50%; box-shadow: inset 0 0 0 2px var(--ink-3); }
.pw-opt[aria-checked='true'] .pw-radio { background: var(--accent); box-shadow: inset 0 0 0 2px var(--accent), inset 0 0 0 5px var(--accent-soft), inset 0 0 0 9px var(--accent); }
.pw-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-4); }
.pw-name { font: var(--t-headline); letter-spacing: var(--tr-headline); white-space: nowrap; }
/* On its own line above the name, so "Trip Pass" never wraps around it on an iPhone SE. */
.pw-best { font: var(--t-caption); letter-spacing: var(--tr-caption); align-self: flex-start; padding: 0 var(--sp-8); border-radius: 999px; background: var(--accent); color: var(--on-accent); white-space: nowrap; }
.pw-body small { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
/* What is billed is the biggest number on the screen. */
.pw-price { font: var(--t-number); letter-spacing: var(--tr-number); flex: none; display: flex; flex-direction: column; align-items: flex-end; white-space: nowrap; }
.pw-price small { font: var(--t-caption); letter-spacing: var(--tr-caption); color: var(--ink-2); }
.pw-dash { display: block; width: 3rem; height: 1.2rem; border-radius: 0.4rem; background: var(--fill-strong); }
.pw-note { font: var(--t-subhead); letter-spacing: var(--tr-subhead); padding: var(--sp-12) var(--gutter) 0; color: var(--ink-2); }
.pw-note.warn { color: var(--storm); }
.pw-note .text-btn { font: inherit; display: inline; margin: 0; padding: 0; }
.pw-fine { font: var(--t-subhead); letter-spacing: var(--tr-subhead); padding: var(--sp-16) var(--gutter) 0; color: var(--ink-2); }
.pw-links { font: var(--t-subhead); letter-spacing: var(--tr-subhead); display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: var(--sp-4) var(--sp-8); padding: var(--sp-12) var(--gutter) var(--sp-16); color: var(--ink-2); }
.pw-links .text-btn { font: inherit; margin: 0; padding: var(--sp-4) 0; }
.pw-links a { padding: var(--sp-4) 0; }

/* The free-day card in the intro: the first card's sample ride, down, with
   the free day's pill as a tab over its top edge (review round 3, m4). The
   accent, as the free day is everywhere; never amber. */
.fd-hero { position: relative; }
.fd-pill { font: var(--t-caption); letter-spacing: var(--tr-caption); position: absolute; top: 0; left: var(--sp-16); transform: translateY(-50%); padding: var(--sp-4) var(--sp-8); border-radius: 999px; background: var(--accent); color: var(--on-accent); box-shadow: 0 0 0 2px var(--surface); white-space: nowrap; }
.fd-hero .ob-ride { margin-top: var(--sp-4); }
.ob-note { font: var(--t-subhead); letter-spacing: var(--tr-subhead); margin-top: var(--sp-8); color: var(--ink-2); }
/* The free day, used when the family chooses: its button and when it would end. */
.fd-action { display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-8); margin-top: var(--sp-16); }
.fd-when, .fd-ask { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
.pw-free { margin: 0 var(--gutter) var(--sp-16); padding: var(--sp-12); border-radius: 0.9rem; background: var(--accent-soft); display: flex; flex-direction: column; gap: var(--sp-4); }
.pw-free p { font: var(--t-subhead); letter-spacing: var(--tr-subhead); }
.pw-free .fd-when { color: var(--ink-2); }
.pw-free .btn-plain { align-self: flex-start; margin: 0; padding-left: 0; padding-right: 0; color: var(--accent); }
/* The free-day card is the one card with its own button: while it shows,
   "Use free day" is the only blue button, and "Next" steps back to plain. */
#onboard:has(.ob-slide[aria-hidden='false'] [data-freeday]) .ob-foot [data-act=next] { background: none; color: var(--accent); min-height: 2.75rem; }
/* On a short screen (iPhone SE, 667 pt) the card's button and its
   disclosure stay above the dots: the sample gives way, not the words. The
   ride and its pill on one line, "Likely back" beside smaller tiles. */
@media (max-height: 740px) {
  .ob-slide:has(.fd-action) .ob-art { min-height: 0; margin-bottom: var(--sp-56); }
  .ob-slide:has(.fd-action) .fd-hero { flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--sp-4) var(--sp-8); padding: var(--sp-16) var(--sp-12) var(--sp-8); }
  .ob-slide:has(.fd-action) .fd-hero .ob-ride { width: 100%; margin-top: 0; }
  .ob-slide:has(.fd-action) .fd-hero .ob-cap { margin-top: 0; }
  .ob-slide:has(.fd-action) .fd-hero .flip { margin: 0; }
  .ob-slide:has(.fd-action) .fd-hero .flip span, .ob-slide:has(.fd-action) .fd-hero .flip em { font-size: min(var(--fs-display), 28px); }
  .ob-slide:has(.fd-action) .fd-action { margin-top: var(--sp-12); }
}
/* The smallest iPhones (320 by 568 pt): even the short layout above hides
   "Use free day" under the dots (review round 3, m2). On this card the band
   steps back to the lockup and the sample, and the title fits one line, so
   the button, the disclosure and until when all show without scrolling. */
@media (max-height: 600px) {
  #onboard:has(.fd-action) .ob-band { transition: height 240ms ease; }
  #onboard:has(.ob-slide[aria-hidden='false'] .fd-action) .ob-band { height: calc(env(safe-area-inset-top) + 9.5rem); }
  .ob-slide:has(.fd-action) { padding-top: var(--sp-12); padding-bottom: var(--sp-4); }
  .ob-slide:has(.fd-action) .ob-art { margin-bottom: var(--sp-16); }
  .ob-slide:has(.fd-action) .fd-action { margin-top: var(--sp-8); gap: var(--sp-4); }
  .ob-slide:has(.fd-action) .ob-title { font-size: min(var(--fs-display), 28px); }
  .ob-slide:has(.fd-action) .fd-hero .flip span, .ob-slide:has(.fd-action) .fd-hero .flip em { font-size: min(var(--fs-display), 24px); }
}
@media (max-height: 600px) and (prefers-reduced-motion: reduce) {
  #onboard:has(.fd-action) .ob-band { transition: none; }
}
[data-sheet=paywall] .btn-stack { padding-top: var(--sp-16); gap: var(--sp-4); }

/* =====================================================================
   The band (DIRECTION.md 4.2; identity round 10, docs/critique/identity-10
   and docs/critique/bands-build): a CSS gradient in the park's colors for
   its state (day, rain, storm, show, night) and appearance, with the park's
   light drawn on it by public/band.js: static SVG layers (no filters), at
   most 6 moving elements (transform and opacity only) and a static grain
   layer on top that dithers the gradients and glows so they never band into
   rings. Which option each park shows is the server's BAND_PICKS setting.
   app.js (bandState, syncBand) sets the gradient and mounts the art, which
   adds .play; this block is how the art sits and moves.
   One-shot effects (fireworks, the glint, the lightning flash) play once
   when the state changes, then rest. Ambient motion loops gently. Only the
   layers that move for good are promoted. Everything pauses while the page
   is hidden, scrolling or on another tab (html.band-paused) and stands
   still under Reduce Motion, where the motion-only glint and wave are left
   out of the still frame.
   A swappable layer: the band's own colors live here and in band.js.
   ===================================================================== */
.band {
  position: relative; isolation: isolate; overflow: hidden; color: #fff;
  background: linear-gradient(165deg, #0A2456, #0A5566);
}
@media (prefers-color-scheme: dark) { .band { background: linear-gradient(165deg, #050B1A, #094657); } }
/* The art box: the design's 390 x 280 frame, centered, its bottom on the band's. */
.band-art { position: absolute; left: 50%; bottom: 0; width: 390px; height: 280px; margin-left: -195px; z-index: -1; pointer-events: none; }
/* On Home it hangs from the title instead, so the title always sits at y 66
   of the frame, in the zone nothing is drawn in: at default text that is the
   same place, and at large text (a taller title, a band sized to it) the
   motifs stay clear of the words and the card covers more of them. */
.home-head .band-art { bottom: auto; top: calc(env(safe-area-inset-top) + var(--sp-16) - 66px); }
/* Onboarding's band hangs its art from the top too, so it holds still when
   the free-day card shortens the band on a short screen. Its top row (the
   app tile and name on the left, Skip on the right, where the art's star,
   balloons and ball are) sits on the band's colors alone: the art starts
   just below it, fading in. The art here is a still frame. */
.onboard-screen .ob-band .band-art {
  bottom: auto; top: calc(env(safe-area-inset-top) + var(--sp-8));
  -webkit-mask-image: linear-gradient(to bottom, transparent 3rem, #000 4.25rem); mask-image: linear-gradient(to bottom, transparent 3rem, #000 4.25rem);
}
/* The app's svg defaults (an icon's size and stroke) don't apply to art. */
.band-art svg { width: auto; height: auto; stroke: none; }
.band-art > .lay { position: absolute; inset: 0; }
.band-art .anim { position: absolute; pointer-events: none; }
.band-art .grain { position: absolute; inset: 0; pointer-events: none; opacity: 0.25; background: url("data:image/png;base64,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") 0 0 / 64px 64px; }
/* Rain starts below the park's own title zone (band.js sets the top); no
   mask, since a mask over endlessly moving children repaints every frame. */
.band-art .rainbox { position: absolute; left: 0; right: 0; top: 124px; bottom: 0; overflow: hidden; }
.band-art .rain { left: 0; top: 0; width: 390px; }
.band-art .rain.ra { height: 220px; top: -64px; background: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2764%27 height=%2764%27%3E%3Cg stroke=%27%23E6F4FF%27 stroke-linecap=%27round%27 stroke-width=%271.1%27 opacity=%27.42%27%3E%3Cpath d=%27M12 2l-3 13M44 18l-3 13M28 40l-3 13M58 50l-3 13%27/%3E%3C/g%3E%3C/svg%3E") 0 0 / 64px 64px; }
.band-art .rain.rb { height: 252px; top: -96px; background: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2796%27 height=%2796%27%3E%3Cg stroke=%27%23E6F4FF%27 stroke-linecap=%27round%27 stroke-width=%271.4%27 opacity=%27.28%27%3E%3Cpath d=%27M20 6l-4 18M70 34l-4 18M44 66l-4 18%27/%3E%3C/g%3E%3Ccircle cx=%2766%27 cy=%2754%27 r=%271.1%27 fill=%27%23fff%27 opacity=%27.8%27/%3E%3Ccircle cx=%2716%27 cy=%2726%27 r=%271%27 fill=%27%23fff%27 opacity=%27.7%27/%3E%3C/svg%3E") 0 0 / 96px 96px; opacity: 0.8; }
/* Kept to the top-right corner, clear of the title. */
.band-art .flash { left: 330px; top: -90px; width: 150px; height: 150px; opacity: 0.3; background: radial-gradient(closest-side, rgba(207, 230, 255, 0.5), rgba(207, 230, 255, 0)); }
.band-art .tw { width: 16px; height: 16px; }
/* EPCOT: a sun glint by day, a slow wave of light at night. Hollywood Studios: a warm glint over the sunburst. */
.band-art .shimmer { left: 0; top: 128px; width: 90px; height: 180px; transform: translateX(250px) skewX(-22deg); background: radial-gradient(closest-side, rgba(191, 246, 255, 0.18), rgba(191, 246, 255, 0)); }
.band-art .shimmer.deco { top: 120px; background: radial-gradient(closest-side, rgba(255, 231, 184, 0.16), rgba(255, 231, 184, 0)); }
.band-art .wave { left: 0; top: 128px; width: 140px; height: 180px; transform: translateX(200px); background: radial-gradient(closest-side, rgba(159, 243, 255, 0.16), rgba(159, 243, 255, 0)); }
/* Magic Kingdom: the evening star breathes. */
.band-art .wish { width: 60px; height: 60px; }
/* Hollywood Studios: the searchlights sway from their bases; at show time the mist glows. */
.band-art .sweep { transform-origin: 50% 212px; }
.band-art .mistpulse { left: 138px; top: 126px; width: 248px; height: 88px; background: radial-gradient(closest-side, rgba(207, 233, 255, 0.35), rgba(207, 233, 255, 0)); }
/* Disneyland: the balloon bunch bobs from the hand below the card. */
.band-art .bob { transform-origin: 60px 168px; }
/* California Adventure: the water show's second set of jets fades in and out, under a moving color wash. */
.band-art .shift { opacity: 0; }
.band-art .wash { left: 40px; top: 150px; width: 240px; height: 80px; background: radial-gradient(closest-side, rgba(255, 79, 168, 0.32), rgba(63, 230, 240, 0.14) 60%, rgba(63, 230, 240, 0)); }
.band-art .rain, .band-art .tw, .band-art .wave, .band-art .wish, .band-art .dustfall, .band-art .glitter, .band-art .sweep, .band-art .flick, .band-art .mistpulse,
.band-art .flock, .band-art .fly, .band-art .drift, .band-art .pulse, .band-art .bob, .band-art .chase, .band-art .shift, .band-art .wash { will-change: transform, opacity; }
@media (prefers-reduced-motion: no-preference) {
  /* One-shot effects are hidden while the band plays; their animation shows
     them once, and ParkBand.settle then rests them. */
  .band-art.play .fw, .band-art.play .shimmer { opacity: 0; }
  .band-art.play .fw { animation: band-fw 3s ease-out 1 both; }
  .band-art.play .fw.f2 { animation-delay: 2.6s; }
  .band-art.play .fw.f3 { animation-delay: 1.3s; }
  /* Disneyland's own beat: the shells cascade left to right, each a little slower to fade. */
  .band-art.play .fw.dl { animation: band-fw-dl 3.6s ease-out 0.5s 1 both; }
  .band-art.play .fw.dl.f2 { animation-delay: 1.5s; }
  .band-art.play .fw.dl.f3 { animation-delay: 2.7s; }
  .band-art.play .shimmer { animation: band-shimmer 3s ease-in-out 1 both; }
  .band-art.play .flash { animation: band-flash 1.4s ease-out 1 both; }
  .band-art.play .wave { animation: band-wave 9s ease-in-out infinite alternate; }
  .band-art.play .tw { animation: band-tw 3.6s ease-in-out infinite; }
  .band-art.play .rain.ra { animation: band-rain64 0.7s linear infinite; }
  .band-art.play .rain.rb { animation: band-rain96 1.4s linear infinite; }
  .band-art.play .wish { animation: band-wish 4.8s ease-in-out infinite; }
  .band-art.play .dustfall { animation: band-dustfall 7s linear infinite; }
  .band-art.play .glitter { animation: band-tw 4s ease-in-out infinite; }
  .band-art.play .sweep { animation: band-sweep 10s ease-in-out infinite alternate; }
  .band-art.play .flick { animation: band-flick 3s ease-in-out infinite; }
  .band-art.play .mistpulse { animation: band-tw 5s ease-in-out infinite; }
  .band-art.play .flock { animation: band-flock 16s ease-in-out infinite alternate; }
  .band-art.play .fly { animation: band-flap 0.9s ease-in-out infinite alternate; }
  .band-art.play .fly.f2 { animation-duration: 1.15s; animation-delay: -0.4s; }
  .band-art.play .drift { animation: band-drift 14s ease-in-out infinite alternate; }
  .band-art.play .pulse { animation: band-tw 6s ease-in-out infinite; }
  .band-art.play .bob { animation: band-bob 5s ease-in-out infinite alternate; }
  /* Three groups of bulbs, each lit a third of the cycle: a real chase. Lazy by day. */
  .band-art.play .chase { animation: band-chase 2.4s linear infinite; }
  .band-art.play .chase.c1 { animation-delay: -0.8s; }
  .band-art.play .chase.c2 { animation-delay: -1.6s; }
  .band-art.play .chase.lazy { animation-duration: 7.2s; }
  .band-art.play .chase.lazy.c1 { animation-delay: -2.4s; }
  .band-art.play .chase.lazy.c2 { animation-delay: -4.8s; }
  .band-art.play .shift { animation: band-cycle 10s ease-in-out infinite alternate; }
  .band-art.play .wash { animation: band-wash 9s ease-in-out infinite alternate; }
  .band-paused .band-art .anim { animation-play-state: paused !important; }
}
@media (prefers-reduced-motion: reduce) { .band-art .shimmer, .band-art .wave { display: none; } }
@keyframes band-fw { 0% { transform: scale(0.35); opacity: 0; } 15% { opacity: 1; } 70% { transform: scale(1) translateY(4px); opacity: 0.95; } 100% { transform: scale(1.04) translateY(10px); opacity: 0; } }
@keyframes band-fw-dl { 0% { transform: scale(0.3); opacity: 0; } 12% { opacity: 1; } 60% { transform: scale(1) translateY(3px); opacity: 1; } 100% { transform: scale(1.05) translateY(12px); opacity: 0; } }
@keyframes band-shimmer { 0% { transform: translateX(-120px) skewX(-22deg); opacity: 1; } 100% { transform: translateX(480px) skewX(-22deg); opacity: 1; } }
@keyframes band-flash { 0% { opacity: 0.2; } 12% { opacity: 0.9; } 24% { opacity: 0.35; } 36% { opacity: 0.75; } 100% { opacity: 0.3; } }
@keyframes band-wave { 0% { transform: translateX(-60px); } 100% { transform: translateX(400px); } }
@keyframes band-tw { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
@keyframes band-rain64 { from { transform: translateY(0); } to { transform: translateY(64px); } }
@keyframes band-rain96 { from { transform: translateY(0); } to { transform: translateY(96px); } }
@keyframes band-wish { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(0.86); opacity: 0.8; } }
@keyframes band-dustfall { 0% { transform: translateY(-6px); opacity: 0; } 15% { opacity: 1; } 85% { opacity: 0.8; } 100% { transform: translateY(14px); opacity: 0; } }
@keyframes band-sweep { from { transform: skewX(-2.5deg); } to { transform: skewX(2.5deg); } }
@keyframes band-flick { 0% { opacity: 1; } 25% { opacity: 0.75; } 50% { opacity: 0.95; } 75% { opacity: 0.8; } }
@keyframes band-flock { from { transform: translateX(-30px); } to { transform: translateX(40px); } }
@keyframes band-flap { from { transform: scaleX(1); } to { transform: scaleX(0.35); } }
@keyframes band-drift { from { transform: translate(-10px, 4px); } to { transform: translate(12px, -6px); } }
@keyframes band-bob { from { transform: rotate(-2.2deg); } to { transform: rotate(2.2deg); } }
@keyframes band-chase { 0%, 30% { opacity: 1; } 36%, 94% { opacity: 0.25; } 100% { opacity: 1; } }
@keyframes band-cycle { 0%, 30% { opacity: 0; } 70%, 100% { opacity: 1; } }
@keyframes band-wash { from { transform: translateX(-60px); } to { transform: translateX(60px); } }
/* The band block ends here (scripts/lint-css.js). */

/* ---- Park tiles: the park sheet and the Trip tab (DIRECTION.md 9) ---- */
.sec-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; max-width: 40rem; margin: 0 auto; padding-right: calc(var(--gutter) + var(--sp-4)); }
.sec-head .section-label { flex: 0 1 auto; min-width: 0; }
.sec-head .sec-hint { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); flex: 0 1 auto; min-width: 0; }
.park-picker { max-width: 40rem; margin: 0 auto var(--sp-12); padding: 0 var(--gutter); }
.park-picker.in-sheet { padding: 0 var(--gutter); }
.resort-switch { margin: 0 0 var(--sp-12); }
.resort-switch button { min-height: 2.25rem; position: relative; }
.resort-switch button::before { content: ''; position: absolute; inset: -0.25rem 0; }
.park-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-12); }
.park-tile {
  position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-4);
  min-height: 5.5rem; padding: var(--sp-12) var(--sp-12) var(--sp-12) var(--sp-16); border-radius: 1rem; text-align: left;
  background: var(--surface); color: var(--ink); box-shadow: var(--shadow-card);
}
.sheet .park-tile { background: var(--sheet-group); }
.park-tile .tile-name { font: var(--t-headline); letter-spacing: var(--tr-headline); padding-right: var(--sp-56); }
.park-tile .tile-sub { font: var(--t-subhead); letter-spacing: var(--tr-subhead); color: var(--ink-2); }
.park-tile .tile-pill { margin-top: auto; padding-top: var(--sp-8); }
.park-tile.on { color: var(--on-band); background: linear-gradient(180deg, var(--band-1), var(--band-2)); box-shadow: var(--shadow-tile-on); }
.park-tile.on .tile-sub { color: var(--on-band-2); }
.park-tile .here { font: var(--t-caption); letter-spacing: var(--tr-caption); position: absolute; top: 0.75rem; right: 0.75rem; display: inline-flex; align-items: center; gap: var(--sp-4); }
.park-tile .here svg { width: 0.9rem; height: 0.9rem; }
.park-tile:active { transform: scale(0.97); }
.tpill { font: var(--t-caption); letter-spacing: var(--tr-caption); display: inline-flex; align-items: center; gap: var(--sp-4); min-height: 1.375rem; padding: 0 var(--sp-8); border-radius: 999px; white-space: nowrap; }
.tpill svg { width: 0.75rem; height: 0.75rem; fill: currentColor; stroke: none; }
.tpill.down { color: var(--down); background: var(--down-soft); }
.tpill.back { color: var(--back); background: var(--back-soft); }
.tpill.storm { color: var(--storm); background: var(--storm-soft); }
.tpill.neutral { color: var(--ink-2); background: var(--fill); }
.park-tile.on .tpill { color: var(--on-band); background: var(--glass-line); box-shadow: inset 0 0 0 1px var(--glass-strong); }
.ax-type .park-tiles { grid-template-columns: minmax(0, 1fr); }

/* ---- Accessibility pass (build 5) ----
   Tap targets: 44 x 44 pt everywhere, drawn smaller where the design says
   so (a 36 pt chip or pill gets a 44 pt hit area). Accessibility text
   sizes: nothing truncates, rows stack with the value under its label,
   and controls that sat side by side wrap. */
.search input { min-height: 2.75rem; }
.alerts-acts .text-btn { min-width: 2.75rem; text-align: center; }
.btn-pill { position: relative; }
.btn-pill::before { content: ''; position: absolute; inset: -0.25rem 0; }
.btn-inline, .more summary, .how-row { min-height: 2.75rem; }
.credit a { display: inline-block; padding: var(--sp-12) 0; margin: calc(-1 * var(--sp-12)) 0; }
.ax-type .stat-strip { grid-template-columns: minmax(0, 1fr); padding: var(--sp-4) var(--sp-16); text-align: left; }
.ax-type .stat-strip div { flex-direction: column-reverse; align-items: flex-start; padding: var(--sp-8) 0; }
.ax-type .stat-strip div + div { border-left: 0; border-top: 1px solid var(--separator); }
/* Large text on Home: the first down ride above the fold (review round 3,
   M4). The crowd meter goes (the park page has it), the "Down now" heading
   is left to VoiceOver (the headline already says it), and the strip runs
   as one sentence ("Next back 1:28 · Longest down 5 hr · Running 22"). */
.ax-type #crowd-meter { display: none; }
.ax-type #down-list [data-key=board-label] { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* At the size of the meta line above it (capped at 20 pt, as that line is),
   so the sentence takes two lines at most, not three. */
.ax-type .strip { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-4) 1rem; padding: var(--sp-8) var(--gutter); text-align: left; }
.ax-type .strip > div { flex-direction: row-reverse; align-items: baseline; gap: 0.3em; padding: 0; }
.ax-type .strip > div + div { border-left: 0; }
.ax-type .strip .sv, .ax-type .strip .sv small { font: var(--t-headline); letter-spacing: var(--tr-headline); font-size: min(var(--fs-headline), 20px); }
.ax-type .strip span { font: var(--t-subhead); letter-spacing: var(--tr-subhead); font-size: min(var(--fs-subhead), 20px); }
.ax-type .page-strip { padding-top: calc(env(safe-area-inset-top) + 3.75rem); }
.ax-type .page-strip .strip-action { position: relative; top: auto; right: auto; margin-top: var(--sp-12); }
.ax-type .onboard-screen .ob-band { height: calc(env(safe-area-inset-top) + 9rem); }
.ax-type .ob-slide { padding-top: var(--sp-16); }
.ax-type .ob-art { min-height: 0; }

/* Space above, on the 4 pt scale, for the few elements that need their own
   (review round 3, p2: no inline margins in app.js). :root lifts them over
   a component's own margin, as the inline style did. */
:root .mt-8 { margin-top: var(--sp-8); }
:root .mt-12 { margin-top: var(--sp-12); }
:root .mt-16 { margin-top: var(--sp-16); }
:root .mt-20 { margin-top: var(--sp-20); }
