/* ============================================================
   Theme Park Day — Design System (P0 redesign)
   Principles: one screen one focus · 8-pt grid · motion ≤ 400ms
   (KPI count-up 800ms is the single peak-end exception)

   Structure:
     1. Tokens     — the ONLY place raw colours/radii/shadows should live
     2. Base       — reset, typography, [hidden] guard
     3. Primitives — shared building blocks (.btn, pill buttons, form fields,
                     .icon-btn, alerts, chips, micro-labels). Reuse these
                     instead of hand-rolling a near-identical variant.
     4. Layout     — .container
     5. Sections   — banner → header → hero → setup → personalise →
                     pickers → result → modal → footer
     6. Motion     — @keyframes live next to their component
     7. Responsive
   ============================================================ */

/* ---------------- 1. Tokens ---------------- */
:root {
  --c-white: #FFFFFF;
  --c-bg: #F9FAFB;
  --c-dark: #090C15;
  --c-purple: #58207A;
  --c-purple-soft: rgba(88, 32, 122, 0.12);
  --c-ocean: #0077C8;
  --c-ocean-dark: #005FA0;
  --c-ocean-soft: rgba(0, 119, 200, 0.08);
  --c-ocean-border: rgba(0, 119, 200, 0.35);
  --c-navy: #0B1B3D;
  --c-slate: #112233;
  --c-slate-soft: #55677F;
  --c-slate-mute: #8B96A6;
  --c-border: #E5E7EB;
  --c-ok: #1A9E6C;
  --c-warn: #B45309;
  --c-err: #C0001E;
  --c-sky: #7ED0F2;

  /* hero ink — high-contrast dark gray for text over the faded castle photo */
  --c-ink: #111827;
  --c-ink-soft: #374151;

  /* unified accents — one red (errors/danger/exclude), one gold (stars) */
  --c-gold: #D4A017;
  --c-gold-glow: rgba(212, 160, 23, 0.9);
  /* hero star-dust gold — a warmer, brighter yellow than the brand --c-gold
     (fav stars) by design, so the two decorative pops stay distinct */
  --c-hero-gold: #F4B400;
  --c-hero-gold-glow: rgba(244, 180, 0, 0.9);
  --c-hero-gold-glow-soft: rgba(244, 180, 0, 0.6);
  --c-err-soft: rgba(192, 0, 30, 0.08);
  --c-err-border: rgba(192, 0, 30, 0.25);

  /* warm / caution surfaces */
  --c-warn-bg: #FFF7ED;
  --c-warn-border: #F3D9B6;
  --c-warn-soft: rgba(180, 83, 9, 0.12);

  /* skeleton shimmer */
  --c-skel: #EEF1F4;
  --c-skel-light: #F7F9FB;

  /* loader / hero decorative palette */
  --c-ferris-rim: #0B3B6E;
  --c-pink: #FF9EC4;
  --c-coral: #FFB4A2;
  --c-gold-soft: #FFD166;

  /* system stack, CJK + Thai safe, zero web-font cost */
  --font: -apple-system, "Segoe UI", "PingFang HK", "PingFang SC",
    "Microsoft JhengHei", "Microsoft YaHei", "Noto Sans TC", "Noto Sans SC",
    "Noto Sans JP", "Noto Sans KR",
    "Noto Sans Thai", "Helvetica Neue", Arial, sans-serif;

  --r-xs: 4px;
  --r-sm: 6px;
  --r-md: 8px;
  --r-lg: 12px;
  --r-pill: 9999px;

  --focus-ring: 0 0 0 4px rgba(0, 119, 200, 0.15);
  --focus-ring-soft: 0 0 0 3px rgba(0, 119, 200, 0.1);

  --shadow-soft: 0 1px 3px rgba(0, 0, 0, 0.06), 0 4px 12px rgba(0, 0, 0, 0.05);
  --shadow-cta: 0 6px 18px rgba(0, 119, 200, 0.35);
  --shadow-active: 0 2px 8px rgba(0, 119, 200, 0.3);

  --maxw: 760px;
}

/* ---------------- 2. Base ---------------- */
* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }

body {
  font-family: var(--font);
  color: var(--c-navy);
  background: var(--c-bg);
  line-height: 1.55;
  font-size: 16px;
}

img, svg { vertical-align: middle; }
button { font-family: inherit; }

/* The `hidden` attribute must always win over any `display` set on the same
   element (e.g. .modal-overlay{display:flex}). Author rules beat the UA
   [hidden]{display:none}, so this !important guard is required. */
[hidden] { display: none !important; }

/* ---------------- 3. Primitives ---------------- */

/* ---- Buttons ---- */
.btn {
  position: relative; /* anchors Fx.burst sparkles (select-all "everything's prioritised") */
  border: none; border-radius: var(--r-lg);
  padding: 12px 28px; font-size: 15px; font-weight: 600;
  cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  transition: transform 0.15s ease-out, background 0.2s, box-shadow 0.2s;
}
.btn:active { transform: translateY(1px) scale(0.98); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }

/* ---- Universal press micro-interaction ----
   Every clickable gives a fast tactile "received" cue on press (scale-down +
   settle). Icon buttons squash more than full rows/pills. These :active rules
   are the ONLY press animation; everything flashier is reserved for Fx.* wins
   below, so interaction stays snappy without feeling busy. (The matching
   transition that eases these presses is declared at the end of the Motion
   section — see "Press smoothing" — so it beats each control's own rule.) */
.preset-btn:active, .pref-preset:active, .modal-sort-btn:active,
.fb-cat:active, .pref-seg-btn:active, .picker-line:active,
.crow:active, .st-row:active,
.modal-close:active, .shared-banner-close:active {
  transform: translateY(1px) scale(0.98);
}
.icon-btn:active { transform: scale(0.92); }
.fb-star:active { transform: scale(0.95); }
.btn-ic { width: 16px; height: 16px; flex: 0 0 auto; }
.share-copy-btn .btn-ic { width: 13px; height: 13px; }
.btn-primary { background: var(--c-ocean); color: #fff; box-shadow: var(--shadow-cta); }
.btn-primary:hover { background: var(--c-ocean-dark); transform: scale(1.02); }
.btn-ghost {
  background: transparent; color: var(--c-ocean);
  border: 1px solid var(--c-ocean-border);
  padding: 8px 18px; font-size: 14px;
}
.btn-ghost:hover { background: var(--c-ocean-soft); }
.btn-hero { font-size: 17px; padding: 16px 32px; border-radius: var(--r-lg); }
/* The inline build button and the floating mobile sticky share the exact same
   size and two-line label ("Plan my day" / ★ tally on a second, smaller line).
   `.build-count` is hidden when nothing is prioritised/skipped, dropping back
   to a single line. */
.btn-build, .sticky-cta-btn {
  width: 100%; justify-content: center;
  flex-direction: column; gap: 2px;
  font-size: 17px; padding: 12px 32px; line-height: 1.2;
}
.btn-build { position: relative; }
.build-label { font-size: 17px; font-weight: 600; line-height: 1.2; }
.build-count { font-size: 12px; font-weight: 600; line-height: 1.3; opacity: 0.85; }

/* Toggle buttons — the selectable/tag toggle family. Rounded (--r-md) like
   every interactive control, so Step 1/2/3 toggles all read the same. Shared
   chrome; per-variant sizing overrides below. New toggles join this group,
   don't copy it. */
.preset-btn, .pref-preset, .modal-sort-btn, .fb-cat {
  border: 1px solid var(--c-border); background: var(--c-white);
  border-radius: var(--r-md); padding: 7px 16px;
  font-size: 13px; font-weight: 600; color: var(--c-slate);
  cursor: pointer; transition: all 0.18s ease-out;
}
.preset-btn:hover, .pref-preset:hover, .modal-sort-btn:hover,
.fb-cat:hover, .pref-seg-btn:hover {
  border-color: var(--c-ocean); color: var(--c-ocean);
}
.preset-btn.active, .pref-preset.active, .modal-sort-btn.active,
.fb-cat.is-active, .pref-seg-btn.active {
  background: var(--c-ocean); border-color: var(--c-ocean); color: #fff;
}
.preset-btn.active, .pref-preset.active, .modal-sort-btn.active,
.fb-cat.is-active { box-shadow: var(--shadow-active); }
.modal-sort-btn { padding: 4px 10px; font-size: 12px; }
.fb-cat { padding: 6px 12px; font-size: 13px; }
.fb-cat-ico { font-size: 14px; }

/* ---- Form fields — shared chrome (2px border + focus ring) so every
   control reads identically. Join this group for new inputs. ---- */
.time-select, .fb-combo-input,
.pref-maxwait input[type="number"], .sfield input[type="number"] {
  font-family: inherit; font-weight: 600; color: var(--c-navy);
  border: 2px solid var(--c-border); border-radius: var(--r-md);
  background: var(--c-white);
  transition: border-color 0.2s, box-shadow 0.2s;
}
.time-select, .fb-combo-input {
  font-size: 16px; padding: 8px 12px; width: 100%;
  appearance: none; -webkit-appearance: none;
}
.fb-combo-input { font-size: 18px; }
.time-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%230B1B3D' d='M6 8 0 0h12z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center;
}
.fb-combo-input { padding: 10px 44px 10px 14px; }
.pref-maxwait input[type="number"] { font-size: 15px; padding: 6px 10px; width: 96px; }
.sfield input[type="number"] { font-size: 16px; padding: 8px 12px; width: 100%; }
.time-select:focus, .fb-combo-input:focus,
.pref-maxwait input[type="number"]:focus, .sfield input[type="number"]:focus {
  outline: none; border-color: var(--c-ocean); box-shadow: var(--focus-ring);
}

/* Native date fields already get a calendar icon from the browser — drop the
   custom chevron so the two never overlap (see the feedback combobox, which is
   custom because <datalist> popups are unreliable on mobile). */
.time-select[type="date"] { background-image: none; cursor: pointer; }

/* ---- Icon buttons — small square/circle buttons inside picker rows.
   Behaviour modifier: --fav (bordered star, gold when active) / --excl (plain ✕,
   red-filled circle only when skipped). Inactive states are styled so both read
   as tappable buttons with matching weight. Emitted by favBtnHtml() and the
   excl buttons in app.js. ---- */
.icon-btn {
  flex: 0 0 auto; border: none; background: none; cursor: pointer;
  line-height: 1; display: inline-flex; align-items: center; justify-content: center;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.icon-btn--fav {
  position: relative; /* the fav gold-sparkle burst anchors on the star */
  width: 32px; height: 32px; font-size: 18px;
  color: var(--c-slate-soft);
  border: 1px solid var(--c-border); background: var(--c-white);
  border-radius: var(--r-sm);
}
.icon-btn--fav:hover { color: var(--c-gold); border-color: var(--c-gold); background: var(--c-bg); }
.icon-btn--fav.active {
  color: var(--c-gold); border-color: rgba(212, 160, 23, 0.55);
  background: rgba(212, 160, 23, 0.08);
}
.icon-btn--fav-sm { width: 28px; height: 28px; font-size: 16px; padding: 0; }
.icon-btn--excl {
  width: 28px; height: 28px; border: none; background: none;
  font-size: 14px; font-weight: 700; color: var(--c-slate-mute); border-radius: 50%;
}
.icon-btn--excl:hover { color: var(--c-err); }
.crow.excluded .icon-btn--excl,
.st-row.excluded .icon-btn--excl,
.icon-btn--excl.active { color: #fff; background: var(--c-err); }
.crow.excluded .crow-name,
.st-row.excluded .st-name-text { text-decoration: line-through; opacity: 0.55; }
.st-name-line .icon-btn--excl { margin-left: auto; }

/* ---- Alerts — shared base; colour via the warn / err groups.
   New notices join one of these groups instead of copy-pasting hex values. ---- */
.stale-hint, .validation-note, .conflict-note {
  border-radius: var(--r-md); padding: 10px 14px;
  font-size: 13px; font-weight: 600; line-height: 1.55;
}
.stale-hint { color: var(--c-warn); background: var(--c-warn-bg); border: 1px solid var(--c-warn-border); margin-bottom: 14px; }
/* A stale plan (selections changed since the last build) is dimmed so it reads
   as a preview, with the "run it again" hint kept full-strength above it. */
.result.is-stale .result-body > * { opacity: 0.35; transition: opacity 0.35s ease; }
.result.is-stale .infeasible { opacity: 0.35; transition: opacity 0.35s ease; }
.result.is-stale .stale-hint,
.result.is-stale .action-bar { opacity: 1; }
.result.is-stale .stale-hint { box-shadow: 0 0 0 3px var(--c-warn-bg); }
.validation-note { color: var(--c-err); background: var(--c-err-soft); border: 1px solid var(--c-err-border); margin-top: 12px; }
.conflict-note { color: var(--c-warn); background: var(--c-warn-bg); border: 1px solid var(--c-warn-border); margin-top: 10px; }
.conflict-note b { display: block; margin: 2px 0; }

/* ---- Micro-labels — uppercase kickers/labels. Shared tracking; size/colour
   and margin per use. ---- */
.result-kicker, .scoring-table th,
.modal-sort-label, .rc-title, .pref-group-title {
  font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
}
.result-kicker { font-size: 12px; letter-spacing: 0.12em; color: var(--c-ocean); margin-bottom: 6px; }
.scoring-table th { color: var(--c-slate-soft); font-size: 11px; letter-spacing: 0.05em; }
.modal-sort-label { font-size: 11px; letter-spacing: 0.05em; color: var(--c-slate-soft); margin-right: 2px; }
.rc-title { font-size: 12px; color: var(--c-slate-soft); margin-bottom: 8px; }
.pref-group-title { font-size: 12px; color: var(--c-slate-soft); margin: 6px 0 2px; }

/* ---- Chips — small filled pills that summarise picks. ---- */
.chip, .rc-chip {
  font-size: 12px; font-weight: 600; color: var(--c-ocean-dark);
  background: var(--c-ocean-soft); border: 1px solid var(--c-ocean-border);
  border-radius: var(--r-pill); padding: 4px 10px;
}
.chip {
  position: relative; padding: 4px 10px 4px 26px;
  /* One pill per name — never wrap a long name inside its own pill. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.chip::before {
  content: "\2713"; position: absolute; left: 9px; top: 50%;
  transform: translateY(-50%); font-weight: 800; font-size: 11px; color: var(--c-ocean);
}
.chip.more {
  color: var(--c-slate-soft); border: 1px dashed var(--c-border);
  background: var(--c-bg); padding: 4px 10px;
}
.chip.more::before, .chip.empty::before { content: ""; }
.chip.empty {
  color: var(--c-slate-soft); border-style: dashed; background: transparent;
  font-weight: 500; padding: 4px 10px;
}
.rc-chip { padding: 3px 10px; }
.rc-chip.dropped {
  color: var(--c-slate-soft); background: var(--c-bg);
  border-style: dashed; text-decoration: line-through;
}
.rc-chip.skipped {
  color: var(--c-slate-soft); background: var(--c-bg);
  border-color: var(--c-border);
}

/* Legend pills (show timeline + attraction steps) */
.st-legend-chip, .pick-legend {
  display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px;
  font-size: 12px; color: var(--c-slate-soft);
  background: var(--c-bg); border: 1px solid var(--c-border);
  border-radius: var(--r-pill); padding: 5px 12px;
}

/* ---------------- 4. Layout ---------------- */
.container { max-width: var(--maxw); margin: 0 auto; padding: 0 8px 64px; }

/* ---------------- 5. Sections ---------------- */

/* ---- Slim header ---- */
.site-header {
  position: sticky; top: 0; z-index: 40;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--c-border);
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 24px; gap: 12px;
}
.brand {
  display: inline-flex; align-items: center; gap: 8px;
  font-weight: 700; font-size: 15px; letter-spacing: 0.02em;
  color: var(--c-navy); min-width: 0; white-space: nowrap;
}
.brand-mark { font-size: 20px; line-height: 1; flex: 0 0 auto; }
.brand em { font-style: normal; color: var(--c-ocean); }
.lang-wrap { display: inline-flex; align-items: center; color: var(--c-slate-soft); }
.lang-select {
  font-family: inherit; font-size: 13px; font-weight: 600; color: var(--c-slate);
  border: 2px solid var(--c-border); border-radius: var(--r-md);
  padding: 6px 30px 6px 30px; background: var(--c-white); cursor: pointer;
  appearance: none; -webkit-appearance: none;
  /* Globe icon inside the field on the left, chevron on the right. */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'%3E%3Cpath fill='%2355677F' d='M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm7.9 9h-3a15.6 15.6 0 0 0-1.2-5.6A8.03 8.03 0 0 1 17.9 11zM12 4.1c.8 1.1 1.9 3.4 2.1 6.9H9.9c.2-3.5 1.3-5.8 2.1-6.9zM4.1 13h3c.2 2.4.8 4.3 1.2 5.6A8.03 8.03 0 0 1 4.1 13zm3-2h-3a8.03 8.03 0 0 1 4.2-5.6A15.6 15.6 0 0 0 7.1 11zm4.9 8.9c-.8-1.1-1.9-3.4-2.1-6.9h4.2c-.2 3.5-1.3 5.8-2.1 6.9zm3.7-1.3c.4-1.3 1-3.2 1.2-5.6h3a8.03 8.03 0 0 1-4.2 5.6z'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%230B1B3D' d='M6 8 0 0h12z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: left 10px center, right 12px center;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.lang-select:focus {
  outline: none; border-color: var(--c-ocean);
  box-shadow: var(--focus-ring);
}
/* Header utility cluster: brand far left, language + share clustered on the
   far right (language sits directly left of share). */
.header-actions { display: flex; align-items: center; gap: 10px; }
.header-share { padding: 6px 12px; font-size: 13px; white-space: nowrap; }
.share-copy-line {
  margin: 0 auto; max-width: var(--maxw); padding: 7px 24px;
  display: flex; align-items: center; gap: 9px;
  font-size: 12px; color: var(--c-slate-soft);
  background: var(--c-ocean-soft);
  border-bottom: 1px solid var(--c-border);
  animation: share-line-in 0.3s ease-out;
}
@keyframes share-line-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
.share-copy-ic { width: 14px; height: 14px; flex: 0 0 auto; color: var(--c-ocean); }
.share-copy-line-url {
  flex: 1; word-break: break-all; font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  color: var(--c-ocean-dark);
}

/* ---- Hero ---- */
.hero {
  position: relative;
  overflow: hidden;
  color: var(--c-navy);
  min-height: calc(100vh / 3);
  display: flex; align-items: center;
}
/* Castle backdrop: the photo is zoomed to 150% width and anchored right, so
   the left third of the frame is cropped away and the castle reads toward the
   left side of the hero, clear of the centered headline. The 45% vertical
   position shifts the view down a touch from centre so the castle focal point
   sits slightly below the middle. Applies on both desktop and mobile (the
   crop reads the same on a phone as it does on a wide screen). */
.hero-bg {
  position: absolute; inset: 0;
  background: url("../hero-park.jpg") right 45% / 150% auto no-repeat;
  pointer-events: none;
}
/* Soft white wash: a radial white glow behind the text zone (centre) that
   fades out toward the edges so the castle stays clearly visible, plus a
   short fade at the very bottom easing the hero into the page background. */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(120% 130% at 50% 42%, rgba(255, 255, 255, 0.68) 0%, rgba(255, 255, 255, 0.48) 55%, rgba(255, 255, 255, 0.2) 100%),
    linear-gradient(180deg, rgba(255, 255, 255, 0) 78%, rgba(255, 255, 255, 0.92) 100%);
  pointer-events: none;
}
.hero-inner {
  width: 100%; max-width: var(--maxw); margin: 0 auto;
  padding: 48px 24px 56px;
  position: relative; z-index: 1;
  text-align: center;
}
.hero-eyebrow {
  color: var(--c-purple); text-transform: uppercase;
  letter-spacing: 0.22em; font-size: 12px; font-weight: 700;
  margin-bottom: 12px;
  /* Hidden until the real park name is known; box stays reserved (no CLS),
     then fades in via .is-shown once the forecast/fallback resolves. */
  opacity: 0; transition: opacity 0.5s ease;
}
.hero-eyebrow.is-shown { opacity: 1; }
.hero-title {
  font-size: clamp(30px, 5vw, 44px); font-weight: 800;
  letter-spacing: -0.01em; margin-bottom: 8px;
  color: var(--c-ink);
}
/* A row of gold decorative stars right under the headline. Static character
   stars (gold ★), always visible — no fade animation. */
.hero-stars-row {
  display: flex; justify-content: center; gap: 8px;
  margin: 0 0 8px;
  color: var(--c-hero-gold); font-size: 15px; line-height: 1;
}
.hero-sub {
  max-width: 560px; margin: 0 auto 18px;
  color: var(--c-slate-soft); font-size: 16px;
}
/* Hero promise: each glyph reveals with a soft rise + blur-to-sharp, staggered
   left to right (the "magical" line). Spaces stay plain text nodes so words can
   wrap. */
.hero-sub .hs-char {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.35em);
  filter: blur(5px);
  animation: hero-char-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  animation-delay: var(--hd, 0s);
}
@keyframes hero-char-in {
  0% { opacity: 0; transform: translateY(0.35em); filter: blur(5px); }
  55% { opacity: 1; }
  100% { opacity: 1; transform: translateY(0); filter: blur(0); }
}

/* ---- Hero stats: the two core count badges, one compact inline row on
   desktop (23 ATTRACTIONS · 7 SHOWS). Mobile re-stacks each pill into two
   lines (number over descriptor). ---- */
.hero-stats {
  list-style: none; margin: 0 auto 24px;
  display: flex; justify-content: center; flex-wrap: wrap; gap: 10px;
}
.hero-stat {
  display: inline-flex; flex-direction: row; align-items: baseline; gap: 8px;
  padding: 10px 18px 9px;
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid rgba(11, 27, 61, 0.08);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-soft);
  backdrop-filter: blur(4px);
}
.hs-num {
  font-size: 20px; font-weight: 800; color: var(--c-ink);
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.hs-label {
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--c-slate-soft);
  white-space: nowrap;
}

/* Hero star-dust — a clear day, a wish (dark inks on the light backdrop) */
.hero-stars { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.hs {
  position: absolute; color: rgba(11, 27, 61, 0.5); font-size: 11px; line-height: 1;
  opacity: 0; animation: twinkle 3.6s ease-in-out infinite;
}
.hs.h1 { top: 22%; left: 12%; animation-delay: 0s; }
.hs.h2 { top: 16%; left: 74%; color: var(--c-ocean); animation-delay: .9s; }
.hs.h3 { top: 34%; left: 88%; color: var(--c-hero-gold); animation-delay: 1.7s; }
.hs.h4 { top: 60%; left: 6%; color: var(--c-hero-gold); animation-delay: 2.4s; }
.hs.h5 { top: 66%; left: 92%; color: var(--c-ocean); animation-delay: .5s; }
.hs.h6 { top: 42%; left: 26%; font-size: 9px; animation-delay: 3.1s; }
@keyframes twinkle {
  0%, 100% { opacity: 0; transform: scale(.6); }
  45% { opacity: .55; transform: scale(1.05); }
}
/* one gentle golden shooting star every ~7s */
.hs-shoot {
  position: absolute; top: 16%; left: -12%;
  width: 70px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), var(--c-hero-gold-glow));
  transform: rotate(-12deg);
  opacity: 0; animation: shoot 7.2s linear infinite;
}
.hs-shoot::after {
  content: ""; position: absolute; right: 0; top: -2px;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--c-hero-gold); box-shadow: 0 0 8px 2px var(--c-hero-gold-glow-soft);
}
@keyframes shoot {
  0%, 86% { opacity: 0; transform: translate(0, 0) rotate(-12deg); }
  88% { opacity: .9; }
  96% { opacity: 0; transform: translate(340px, 72px) rotate(-12deg); }
  100% { opacity: 0; transform: translate(340px, 72px) rotate(-12deg); }
}

/* ---- Setup — individual section cards on the page background ---- */
.setup-card {
  display: flex; flex-direction: column; gap: 12px;
  position: relative; z-index: 5;
  scroll-margin-top: 64px;
}
.setup-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
}
.setup-head > div { min-width: 0; }
.setup-reset { flex: 0 0 auto; }
.setup-title { font-size: 22px; font-weight: 700; }
.setup-sub { color: var(--c-slate-soft); font-size: 14px; margin: 6px 0 0; }

.step {
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-soft);
  padding: 16px;
}
.step-title { font-size: 15px; font-weight: 700; margin-bottom: 8px; }

/* Step collapse/expand toggle — the WHOLE header row is one button, so tapping
   anywhere on the title or the chevron collapses/expands. Chevron points up
   while expanded (click to collapse) and down once collapsed (click to expand);
   collapsing hides everything below the header. */
.step-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex: 0 0 auto;
  color: var(--c-slate-soft);
  border-radius: var(--r-sm);
  transition: color 0.15s, background 0.15s;
}
.step-toggle-ico { width: 18px; height: 18px; transform: rotate(180deg); transition: transform 0.2s ease; }
.step.is-collapsed .step-toggle-ico { transform: rotate(0); }

/* Step bodies collapse/expand with a quick 180 ms height animation — the CSS
   grid 0fr→1fr rows trick. `.step-body` animates the single row, `.step-body-in`
   is the grid item that clips the content (min-height:0 + overflow:hidden), so
   the collapse is a real slide, not an instant display toggle. Collapsed content
   stays in the DOM (inputs keep their values) but is hidden from the a11y tree
   via visibility only after the slide-out finishes. */
.step-body {
  display: grid; grid-template-rows: 1fr;
  transition: grid-template-rows 0.18s ease, visibility 0s;
}
.step-body > .step-body-in { min-height: 0; overflow: hidden; }
.step.is-collapsed .step-body {
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows 0.18s ease, visibility 0s linear 0.18s;
}

/* Shared fast expand/collapse primitive for the inline toggles (More
   preferences, Advanced settings, dev panels). Same 0fr→1fr grid rows trick:
   `.acc` = animator, `.acc > .acc-in` = its single clipping child. Toggle the
   `.open` class to expand. Everything visual must live INSIDE `.acc-in` so no
   border/padding/margin peeks out while the row is 0. */
.acc {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows 0.18s ease, visibility 0s,
    margin-top 0.18s ease, margin-bottom 0.18s ease,
    padding-top 0.18s ease, padding-bottom 0.18s ease;
}
.acc > .acc-in { min-height: 0; overflow: hidden; }
.acc.open { grid-template-rows: 1fr; }
/* Collapsed: clip the content away from the a11y tree once the slide-out ends
   and drop the body's own vertical margin/padding so nothing peeks above the
   0-height row. */
.acc:not(.open) {
  visibility: hidden;
  margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0;
  transition: grid-template-rows 0.18s ease, visibility 0s linear 0.18s,
    margin-top 0.18s ease, margin-bottom 0.18s ease,
    padding-top 0.18s ease, padding-bottom 0.18s ease;
}
@media (prefers-reduced-motion: reduce) {
  .step-body, .acc { transition: none; }
}

.field { display: block; }
.field-label { display: block; font-weight: 600; font-size: 14px; margin-bottom: 6px; }
.field-hint { display: block; font-size: 12px; color: var(--c-slate-soft); margin-top: 6px; }

/* Step 1 — responsive field grid. Each field stacks its label (small hint
   inline to the right of the title) above its control:
   - >=768px: two columns — Visit date and Meals span the full row,
     Entry time & Leaving time sit side-by-side.
   - <768px: single column, everything stacked. */
.plan-rows { display: grid; grid-template-columns: 1fr; gap: 12px; }
.plan-field { display: grid; gap: 4px; min-width: 0; align-content: start; }
.plan-field-label {
  display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-weight: 600; font-size: 13.5px; color: var(--c-slate); line-height: 1.3;
}
.plan-field .time-select { width: 100%; }
.plan-field-hint { font-size: 11px; font-weight: 500; color: var(--c-slate-soft); line-height: 1.35; white-space: nowrap; }

@media (min-width: 768px) {
  .plan-rows { grid-template-columns: 1fr 1fr; gap: 14px; }
  .plan-field--date, .plan-field--meals { grid-column: 1 / -1; }
}

/* The 2-column layout (date full-width, entry + leaving side-by-side)
   applies at every width >= 768px - no 3-column centred row. */

/* Tiny info tooltip icon (long helper copy lives in title/aria-label). */
.hint-tip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border: none; background: none;
  color: var(--c-slate-soft); border-radius: 50%; cursor: help;
  padding: 0; flex: 0 0 auto; position: relative;
}
.hint-tip:hover { color: var(--c-ocean); }
.hint-tip-ico { width: 14px; height: 14px; }
/* Tap/hover popover for the info icon - works on desktop (hover) and on
   mobile (tap opens it). */
.hint-pop {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 40;
  width: max-content;
  max-width: min(260px, 82vw);
  background: var(--c-navy); color: #fff;
  border-radius: var(--r-sm); padding: 9px 12px;
  font-size: 12px; font-weight: 500; line-height: 1.5;
  box-shadow: var(--shadow-soft);
  text-align: left; white-space: normal;
}
.hint-pop::before {
  content: ""; position: absolute; bottom: 100%; left: 16px;
  border: 6px solid transparent; border-bottom-color: var(--c-navy);
}

/* Meal toggle pills — always visible, no edit step. Compact 2-line chips that
   sit side-by-side on one row. */
.meal-checks { display: flex; gap: 8px; flex-wrap: wrap; }
.meal-check {
  display: inline-flex; align-items: center; gap: 7px;
  border: 2px solid var(--c-border); border-radius: var(--r-md);
  background: var(--c-white); padding: 4px 12px;
  font-size: 13px; font-weight: 600; color: var(--c-navy); cursor: pointer;
}
.meal-check:hover { border-color: var(--c-ocean); }
.meal-check:has(input:checked) {
  border-color: var(--c-ocean); background: var(--c-ocean-soft);
  box-shadow: var(--shadow-active);
}
.meal-check-body { display: flex; flex-direction: column; line-height: 1.2; }
.meal-check input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--c-ocean); cursor: pointer; }
.meal-check small { font-weight: 400; color: var(--c-slate-soft); font-size: 11px; }
.meal-check:has(input:disabled) { opacity: 0.55; cursor: not-allowed; }

/* Step 1 footer — slim planned-window summary badge. */
.time-summary {
  margin-top: 12px;
  background: var(--c-bg); border: 1px solid var(--c-border);
  border-radius: var(--r-md); padding: 8px 16px;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; color: var(--c-slate);
}
.time-summary b { color: var(--c-navy); }

/* ---- Presets + picker lines ---- */
.preset-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.preset-hint { font-size: 13px; color: var(--c-slate-soft); margin-right: 2px; }

.picker-line {
  display: flex; align-items: center; gap: 10px; width: 100%;
  text-align: left; background: var(--c-bg);
  border: 1px solid var(--c-border); border-radius: var(--r-md);
  padding: 8px 10px; cursor: pointer;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.picker-line:hover { border-color: var(--c-ocean); box-shadow: var(--focus-ring-soft); }
.chip-tray {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-wrap: wrap; gap: 6px;
}
.picker-meta { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; }
.picker-count { font-size: 12px; color: var(--c-slate-soft); white-space: normal; line-height: 1.5; }
.picker-edit { font-size: 13px; font-weight: 700; color: var(--c-ocean); white-space: nowrap; }

/* ---- Step 3: header row + legend banner + card grid ---- */
.step-head {
  display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
  /* The whole header is the expand/collapse toggle — reset button chrome. */
  width: 100%; padding: 0; border: none; background: none;
  text-align: left; font: inherit; cursor: pointer;
  border-radius: var(--r-sm);
  transition: background 0.15s;
}
.step-head:hover .step-title, .step-head:hover .step-toggle { color: var(--c-ocean); }
.step-head:hover .step-toggle { background: var(--c-bg); }
.step-head:focus-visible { outline: 2px solid var(--c-ocean); outline-offset: 1px; }
.step-head .step-title { margin-bottom: 0; flex: 0 1 auto; transition: color 0.15s; }
.step-head-spacer { flex: 1 1 auto; }
.picker-edit-btn { flex: 0 0 auto; padding: 5px 12px; font-size: 12.5px; }
.picker-edit-btn .btn-ic { width: 14px; height: 14px; }

.legend-banner {
  display: flex; align-items: center; justify-content: flex-start; flex-wrap: wrap; gap: 6px;
  width: 100%; margin-bottom: 14px;
  background: var(--c-bg); border: 1px solid var(--c-border);
  border-radius: var(--r-md); padding: 8px 14px;
}

/* Preset quick-set chips — theme colour per preset, icon before the label. */
.preset-btn { display: inline-flex; align-items: center; gap: 6px; }
.preset-btn-ico { font-size: 15px; line-height: 1; }
.preset-btn--first:hover { border-color: var(--c-ok); color: var(--c-ok); }
.preset-btn--first.active { background: var(--c-ok); border-color: var(--c-ok); }
.preset-btn--thrill:hover { border-color: var(--c-warn); color: var(--c-warn); }
.preset-btn--thrill.active { background: var(--c-warn); border-color: var(--c-warn); }
.preset-btn--family:hover { border-color: var(--c-purple); color: var(--c-purple); }
.preset-btn--family.active { background: var(--c-purple); border-color: var(--c-purple); }
.preset-btn.active .preset-btn-ico { filter: drop-shadow(0 0 4px rgba(255,255,255,0.45)); }
.preset-btn--first.active:hover,
.preset-btn--thrill.active:hover,
.preset-btn--family.active:hover {
  color: #fff;
}

.attr-grid-hint {
  display: flex; align-items: center; gap: 6px;
  margin: 0 0 10px; font-size: 12.5px; color: var(--c-slate-soft);
}
.attr-grid-hint .lg-star { font-size: 13px; }

.attr-grid-wrap {
  position: relative; overflow: hidden;
  max-height: 158px;
}
.attr-grid-wrap.no-clip { max-height: none; overflow: visible; }
.attr-grid-wrap.no-clip::after { display: none; }
/* Bottom fade — a compact "peek" that hints at the full list behind the modal
   without occupying much vertical space. */
.attr-grid-wrap::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 46px;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1));
  pointer-events: none;
}

.attr-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px;
}
/* Inside the flex-column modal list, the grid must never flex-shrink — let the
   modal scroll at natural card heights instead of squashing the cards. */
.attr-grid--modal { flex: 0 0 auto; }

.attr-card {
  display: flex; align-items: stretch; padding: 0;
  position: relative; overflow: hidden; height: 88px;
  background: var(--c-white); border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  transition: border-color 0.2s, box-shadow 0.2s, opacity 0.2s;
}
.attr-card:hover { border-color: var(--c-gold); box-shadow: 0 0 0 1px rgba(212, 160, 23, 0.3); }
.attr-card.is-fav { border-color: var(--c-gold); box-shadow: 0 0 0 1px rgba(212, 160, 23, 0.35); }
.attr-card.excluded { opacity: 0.55; }
/* A skipped/greyed card reads as "off" — hovering it should NOT glow gold (that
   colour means prioritised), so it cues blue like every other interactive edge. */
.attr-card.excluded:hover { border-color: var(--c-ocean); box-shadow: 0 0 0 1px rgba(0, 119, 200, 0.3); }
.attr-card.excluded .attr-thumb { filter: grayscale(0.85); }
.attr-card.excluded .attr-name, .attr-card.excluded .attr-name .name-en { text-decoration: line-through; }
.attr-card.is-hidden { opacity: 0.45; }
/* Live search: a quiet divider sits between the ranked matches (top) and the
   rest of the list (below, still at full weight) — the search never hides or
   dims anything, it just reorders with a clean separation. */
.attr-search-divider {
  display: flex; align-items: center; gap: 10px;
  margin: 14px 2px 12px; color: var(--c-slate-soft);
  font-size: 11px; letter-spacing: 0.05em;
}
.attr-search-divider::before,
.attr-search-divider::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--c-border);
}

/* Full-bleed thumbnail: flush against the card's top/bottom/left edges and
   clipped to the rounded corners by the parent's overflow:hidden. */
.attr-thumb {
  flex: 0 0 104px; width: 104px; min-height: 76px;
  align-self: stretch; position: relative; overflow: hidden;
  display: block;
  background: linear-gradient(135deg, #E8ECF2, #D6DDE8);
}
.attr-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.attr-thumb--none { display: flex; align-items: center; justify-content: center; }
.attr-thumb-fallback { font-size: 26px; line-height: 1; opacity: 0.75; }
.attr-seq {
  position: absolute; top: 6px; left: 6px; z-index: 1;
  min-width: 18px; height: 18px; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(11, 27, 61, 0.78); color: #fff;
  font-size: 11px; font-weight: 700; border-radius: var(--r-pill);
}

.attr-body {
  flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column;
  gap: 4px; justify-content: center; padding: 10px 0 10px 12px;
}
.attr-name {
  font-size: 13px; font-weight: 700; color: var(--c-navy); line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.attr-name .name-en { display: block; font-size: 11px; font-weight: 500; color: var(--c-slate-soft); margin-top: 1px; }
.attr-meta-line { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.attr-meta-line .crow-meta { margin-left: 0; }
/* Est-wait — muted grey pill (matches the meta badges; no blue pop). */
.attr-wait {
  display: inline-flex; align-items: center; white-space: nowrap;
  border-radius: var(--r-pill); padding: 2px 9px;
  font-size: 10px; font-weight: 800; letter-spacing: 0.04em; line-height: 1.45;
  color: var(--c-slate-soft);
  background: var(--c-bg);
  border: 1px solid var(--c-border);
}
.attr-wait small { font-size: 9px; font-weight: 700; margin-left: 1px; opacity: 0.9; }
.attr-meta-line .crow-pref { margin-left: 2px; }
/* Full-day wait trend — hidden on the 2-column grid, shown on mobile where the
   cards are full-width. */
.attr-content {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center;
  position: relative; z-index: 1;
}
/* Wait-time sparkline as a faint background watermark on the card's right
   section, scaled to at most the lower half of the card — content (z-index 1)
   stays readable above it. */
.attr-spark-bg {
  position: absolute; right: 0; top: 50%; height: 50%; width: 40%;
  z-index: 0; pointer-events: none; overflow: hidden;
}
.attr-spark-bg .spark { width: 100%; height: 100%; }
.attr-spark-bg .spark .line { stroke-width: 1; stroke: var(--c-sky); }
.attr-spark-bg .spark .area { fill: rgba(126, 208, 242, 0.08); }

.attr-actions {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px;
  justify-content: center; padding: 10px 12px 10px 10px;
}
.attr-actions .icon-btn--fav { width: 30px; height: 30px; font-size: 17px; }
.attr-actions .icon-btn--excl { width: 28px; height: 28px; font-size: 12px; }
.icon-btn--excl.active { color: #fff; background: var(--c-err); border-color: var(--c-err); }

.attr-show-all {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; margin-top: 10px; text-align: center;
  border: 1px dashed var(--c-border); background: var(--c-white);
  border-radius: var(--r-md); padding: 10px 14px;
  font-size: 13px; font-weight: 700; color: var(--c-ocean); cursor: pointer;
  transition: border-color 0.18s, box-shadow 0.18s, color 0.18s;
}
.attr-show-all:hover { border-color: var(--c-ocean); color: var(--c-ocean-dark); box-shadow: var(--focus-ring-soft); }
.attr-show-all-arrow { display: inline-flex; align-items: center; }
.attr-show-all-arrow svg { width: 14px; height: 14px; }
.attr-show-all[hidden] { display: none; }

/* ---- Personalise (preferences) ---- */
/* Preset profile selection cards — 5-column icon-over-text grid on desktop,
   wrapped 2-3 column grid on phones (see Responsive). */
.pref-presets {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px;
  margin-bottom: 10px;
}

.pref-preset {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; padding: 10px 8px;
  border: 1px solid var(--c-border); background: var(--c-white);
  border-radius: var(--r-md); box-shadow: var(--shadow-soft);
  text-align: center; cursor: pointer;
}
.pref-preset:hover { border-color: var(--c-ocean); box-shadow: var(--shadow-active); }
.pref-preset-ico {
  width: 40px; height: 40px;
  border-radius: 50%;
  background: #fff;
  box-shadow: inset 0 0 0 1px rgba(11, 27, 61, 0.08);
  overflow: hidden;
}
.pref-preset-ico img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pref-preset-name { font-size: 12px; font-weight: 700; color: var(--c-slate); line-height: 1.3; }
.pref-preset.active {
  border-color: var(--c-ocean); background: var(--c-ocean-soft);
  box-shadow: var(--shadow-active);
}
.pref-preset.active .pref-preset-name { color: var(--c-ocean-dark); }

.pref-control {
  display: flex; flex-direction: column; gap: 2px;
  background: var(--c-bg); border: 1px solid var(--c-border);
  border-radius: var(--r-md); padding: 8px 12px;
}
.pref-label { font-size: 13px; font-weight: 600; color: var(--c-navy); }
.pref-control input[type="range"] {
  width: 100%; accent-color: var(--c-ocean); cursor: pointer; margin: 2px 0;
}
.pref-scale {
  font-size: 10px; letter-spacing: 0.04em;
  color: var(--c-slate-soft); text-transform: uppercase; font-weight: 600;
  display: flex; justify-content: space-between;
}
.pref-check { flex-direction: row; align-items: center; gap: 8px; }
.pref-check input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--c-ocean); cursor: pointer; }
.pref-maxwait { flex-direction: row; align-items: center; justify-content: space-between; gap: 10px; }
.pref-more-toggle {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  margin: 8px auto 0;
  border: none; background: none; padding: 6px 10px;
  font-size: 13px; font-weight: 700; letter-spacing: 0.02em;
  color: var(--c-ocean); cursor: pointer;
  transition: color 0.18s ease-out;
}
.pref-more-toggle:hover { color: var(--c-ocean-dark); }
.pref-more-arrow { display: inline-flex; align-items: center; transition: transform 0.18s ease-out; }
.pref-more-arrow svg { width: 14px; height: 14px; }
.pref-more-toggle[aria-expanded="true"] .pref-more-arrow { transform: rotate(180deg); }
.pref-controls {
  display: grid; grid-template-columns: 1fr;
}
/* The bordered box lives INSIDE the collapsing row (a child of .acc-in) so no
   border/padding peeks out while "More preferences" is collapsed. */
.pref-controls .acc-in > .pref-controls-in {
  display: grid; gap: 10px;
  margin-top: 8px;
  border: 1px solid var(--c-ocean-border); border-radius: var(--r-md);
  background: rgba(0, 119, 200, 0.03); padding: 10px;
}
.pref-group { display: grid; gap: 8px; }
.pref-seg-row { display: flex; gap: 4px; }
.pref-seg-btn {
  flex: 1; border: 1px solid var(--c-border); background: var(--c-white);
  border-radius: var(--r-md); padding: 6px 4px;
  font-size: 12px; font-weight: 600; color: var(--c-slate);
  cursor: pointer; transition: all 0.15s ease-out;
}
.pref-summary {
  margin-top: 10px;
  background: var(--c-ocean-soft); border: 1px solid var(--c-ocean-border);
  border-radius: var(--r-md); padding: 8px 12px;
  font-size: 13px; color: var(--c-slate);
}
/* The "Prioritising: …" line re-triggers a soft fade-up whenever the chosen
   preferences change the summary text (preset switch, segment/toggle tweak). */
.pref-summary-pop { animation: pref-summary-pop .45s cubic-bezier(.16, 1, .3, 1); }
@keyframes pref-summary-pop {
  0% { opacity: 0; transform: translateY(4px); }
  100% { opacity: 1; transform: translateY(0); }
}

/* ---- Shared tag component (picker badges + timeline badges) ---- */
.crow-meta { flex: 0 0 auto; display: inline-flex; gap: 4px; margin-left: 6px; }
.tag {
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 9px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  border-radius: var(--r-pill); padding: 2px 6px; white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.tag--indoor { background: var(--c-ocean-soft); color: var(--c-ocean-dark); }
.tag--thrill { background: var(--c-err-soft); color: var(--c-err); }
.tag--exclusive { background: var(--c-warn-soft); color: var(--c-warn); }
.tag--meet { background: var(--c-purple-soft); color: var(--c-purple); }
.tag--show { background: var(--c-purple-soft); color: var(--c-purple); }
.tag--meal { background: var(--c-warn-soft); color: var(--c-warn); }
.tag--gentle, .tag--ride { background: var(--c-ocean-soft); color: var(--c-ocean-dark); }

/* ---- Preference pill (shows how prefs change each pick) ---- */
.crow-pref {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-left: 6px; vertical-align: middle; flex: 0 0 auto;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.6) inset;
}
.crow-pref.pos { background: var(--c-ok); }
.crow-pref.pos.s1 { opacity: 0.4; }
.crow-pref.pos.s2 { opacity: 0.7; }
.crow-pref.pos.s3 { opacity: 1; }
.crow-pref.neg { background: var(--c-warn); }
.crow-pref.neg.s1 { opacity: 0.4; }
.crow-pref.neg.s2 { opacity: 0.7; }
.crow-pref.neg.s3 { opacity: 1; }
.picker-pref-hint {
  margin: 0 2px 6px; padding: 6px 10px; font-size: 12px; font-weight: 600;
  color: var(--c-slate-soft); background: var(--c-bg);
  border: 1px solid var(--c-border); border-radius: var(--r-md);
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
}
.picker-pref-hint .crow-pref { margin-left: 0; }
.picker-pref-hint .lg-star { font-size: 13px; }

/* ---- Modal sort chips ---- */
.modal-sort { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; padding: 8px 16px 4px; }

/* ---- Result recap ---- */
.result-recap {
  background: var(--c-white); border: 1px solid var(--c-border);
  border-radius: var(--r-md); box-shadow: var(--shadow-soft); padding: 14px 16px;
  margin-bottom: 20px; font-size: 13px; color: var(--c-slate);
}
.rr-line { margin-bottom: 6px; }
.rr-line b { color: var(--c-navy); }
.rr-drop { font-size: 12px; color: var(--c-slate-soft); padding-left: 12px; border-left: 2px solid var(--c-border); }
.rc-chips { display: flex; flex-wrap: wrap; gap: 6px; }

/* Favourite star in day timeline */
.dt-star { color: var(--c-gold); margin-right: 5px; }

/* Dev: active prefs summary */
.scoring-prefs {
  margin: -8px 0 14px; font-size: 12px; font-weight: 600; color: var(--c-slate-soft);
}

/* ---- Show timeline (inline, one row per show) ---- */
.toolbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; gap: 10px; flex-wrap: wrap; }
.toolbar-btns { display: flex; gap: 8px; }
.toolbar .btn-ghost { padding: 5px 12px; font-size: 12px; }

.show-timeline {
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  background: var(--c-white);
  /* Clip scroll content to the card's rounded corners instead of letting it
     poke past the radius at the top-left/right edges. */
  overflow: hidden;
}
/* Inner scrollport for the timeline. The right padding keeps the last column
   ("21:00" tick and edge showtime pills) from being clipped against the card
   edge: it is part of the scrollable area, so the last column stays reachable
   and the tick label never sits flush against the border. */
.st-scroll {
  overflow-x: auto;
  padding-right: 24px;
}
.st-header {
  display: flex; align-items: stretch;
  width: 100%;
  background: var(--c-bg);
  border-bottom: 1px solid var(--c-border);
  font-size: 11px; color: var(--c-slate-soft); font-weight: 600;
  min-width: 560px;
}
.st-header .st-name-col { background: var(--c-bg); }
.st-name-col { flex: 0 0 244px; min-width: 0; overflow: hidden; padding: 4px 10px; position: sticky; left: 0; z-index: 2; }
.st-row .st-name-col { background: var(--c-white); }
/* Left thumbnail for a show row — photo or category-tinted letter tile. */
.st-thumb {
  flex: 0 0 40px; width: 40px; height: 40px; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 700; overflow: hidden;
  background: var(--c-ocean-soft); color: var(--c-ocean-dark);
}
.st-thumb--img { overflow: hidden; background: var(--c-skel); }
.st-thumb-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.st-thumb--thrill { background: var(--c-err-soft); color: var(--c-err); }
.st-thumb--meet { background: var(--c-purple-soft); color: var(--c-purple); }
.st-thumb--exclusive { background: var(--c-warn-soft); color: var(--c-warn); }
.st-thumb--ride { background: var(--c-bg); color: var(--c-slate); }
.st-track-col { flex: 1 1 auto; position: relative; min-width: 0; border-left: 1px solid var(--c-border); }
.st-tick { position: absolute; top: 0; bottom: 0; width: 0; font-size: 10px; color: var(--c-slate-soft); }
.st-tick::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 1px; background: var(--c-border); }
/* Hour label sits just right of its tick mark; the last (park-close) tick flips
   its label left of the mark so it never overflows the track's right edge. */
.st-tick-label { position: absolute; left: 5px; top: 50%; transform: translateY(-50%); white-space: nowrap; font-variant-numeric: tabular-nums; }
.st-tick--last .st-tick-label { left: auto; right: 5px; }
.st-row {
  display: flex; align-items: stretch; border-bottom: 1px solid var(--c-border);
  user-select: none; width: 100%; min-width: 560px; transition: background 0.15s; cursor: pointer;
}
.st-row:last-child { border-bottom: none; }
.st-row:hover { background: var(--c-bg); box-shadow: inset 3px 0 0 var(--c-gold); }
.st-row:hover .st-name-col { background: var(--c-bg); }
.st-row .st-name-col { display: flex; flex-direction: column; align-items: stretch; gap: 2px; font-size: 13px; font-weight: 500; color: var(--c-navy); }
.st-name-line { display: flex; align-items: center; gap: 6px; min-width: 0; }
.st-name-line .crow-pref { margin-left: 0; }
.st-name-text {
  flex: 1 1 auto; min-width: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.3;
}
.st-row.selected .st-name-col { color: var(--c-ocean-dark); font-weight: 600; }
/* Showtime pill: the clock time lives INSIDE the pill, centred. */
.st-marker {
  position: absolute; top: 50%; transform: translateY(-50%);
  height: 17px; min-width: 38px; padding: 0 5px;
  border-radius: var(--r-pill);
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(85, 103, 127, 0.10);
  border: 1px solid rgba(85, 103, 127, 0.22);
  color: var(--c-slate-soft);
  transition: all 0.15s;
}
.st-marker-label {
  font-size: 10px; font-weight: 700; line-height: 1;
  white-space: nowrap; color: inherit; font-variant-numeric: tabular-nums;
}
.st-marker-label em { font-style: normal; font-weight: 700; color: var(--c-warn); }
.st-row.selected .st-marker { background: var(--c-purple); border-color: var(--c-purple); color: #fff; }
.st-marker-chosen { background: var(--c-ok); border-color: var(--c-ok); color: #fff; }
.st-row.selected .st-marker.st-marker-chosen { background: var(--c-ok); border-color: var(--c-ok); }
.st-row.in-itin .st-name-col { color: var(--c-ok); font-weight: 700; }
.st-row.in-itin .st-name-col .name-en { color: var(--c-ok); }

/* Consolidated legend strip (shows step): icon key + dots + green in-plan */
.st-legend-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin-top: 8px; margin-bottom: 8px;
}
.st-legend-chip .crow-pref { margin-left: 0; }
.st-legend-dot {
  flex: 0 0 auto; width: 12px; height: 12px; border-radius: 50%;
  background: var(--c-ok);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.6) inset;
}

/* Icon legend under step titles (attractions step): gold ★ must-do · red ✖ skip */
.lg-ico { font-size: 13px; line-height: 1; }
.lg-star { color: var(--c-gold); }
.lg-x { color: var(--c-err); font-weight: 700; }
.lg-sep { color: var(--c-slate-soft); }
.lg-dash { margin: 0 1px; }

/* ---- Advanced / dev toggles ---- */
.adv-toggle {
  background: none; border: none; cursor: pointer;
  font-size: 13px; font-weight: 600; color: var(--c-slate-soft);
  padding: 8px 0; display: inline-flex; align-items: center; gap: 6px;
  transition: color 0.2s;
}
.adv-toggle:hover { color: var(--c-ocean); }
.adv-arrow { display: inline-flex; align-items: center; transition: transform 0.2s; }
.adv-arrow svg { width: 14px; height: 14px; }
.adv-toggle.open .adv-arrow { transform: rotate(180deg); }
.adv-body { padding-top: 8px; }

/* ---- Result ---- */
.result { margin-top: 40px; scroll-margin-top: 56px; }
.result-title { font-size: 26px; font-weight: 700; margin-bottom: 20px; }

.kpi-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 20px; }
.kpi-card {
  background: var(--c-white); border: 1px solid var(--c-border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-soft);
  padding: 16px; display: flex; flex-direction: column; gap: 2px;
}
.kpi-top { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 4px; }
.kpi-value { font-size: 26px; font-weight: 700; color: var(--c-navy); font-variant-numeric: tabular-nums; }
.kpi-unit, .kpi-label { font-size: 14px; font-weight: 600; color: var(--c-slate-soft); }
.kpi-label { text-transform: lowercase; }
.kpi-sub { font-size: 12px; color: var(--c-slate-soft); }
.kpi-saved, .kpi-saved-value { color: var(--c-ok); }
.kpi-saved { font-weight: 700; }

/* Plan map — always-visible Leaflet block under the day timeline */
.plan-map-wrap { margin-bottom: 20px; }
.plan-map-wrap > .plan-map + .plan-map-legs, .plan-map-wrap > .plan-map-legs { margin-top: 8px; }
/* isolation: isolate contains Leaflet's internal z-indexes (panes up to 700) so
   they can never sit above modals or the sticky CTA. */
.plan-map {
  width: 100%; height: 320px; border-radius: var(--r-md); overflow: hidden;
  border: 1px solid var(--c-border); background: #E8ECEF;
  position: relative; isolation: isolate; z-index: 0;
}
.plan-map-foot { font-size: 12px; color: var(--c-slate-mute); line-height: 1.5; margin-top: 2px; }
/* Numbered pins (divIcon, no Leaflet chrome) + entry pin. Pin fill follows the
   day-timeline tag palette: meet/show purple, thrill red, indoor/gentle/ride
   ocean, meal amber — the same tones as the timeline badges. */
.plan-pin-wrap { background: none; border: none; }
.plan-pin {
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--c-ocean); color: var(--c-white);
  font-size: 13px; font-weight: 700; line-height: 1; font-family: inherit;
  border: 2px solid var(--c-white);
  box-shadow: 0 2px 6px rgba(11, 27, 61, 0.35);
}
.plan-pin--entry {
  width: 34px; height: 34px; font-size: 15px;
  background: var(--c-purple);
  border-radius: 50% 50% 50% 6px;
}
.plan-pin--meet, .plan-pin--show { background: var(--c-purple); }
.plan-pin--thrill { background: var(--c-err); }
.plan-pin--indoor, .plan-pin--gentle, .plan-pin--ride { background: var(--c-ocean); }
.plan-pin--meal { background: var(--c-warn); }

.plan-pop-name { display: block; font-weight: 600; color: var(--c-navy); }
.plan-pop-name .name-local, .plan-pop-name .name-en { display: block; }
.plan-pop-time { display: block; font-size: 12px; color: var(--c-slate-soft); margin-top: 2px; font-variant-numeric: tabular-nums; }

/* Walk legs legend — one row per leg so it reads left→right with actual names
   (number chips match the pins/tag colors). Scrolls when the day is long. */
.plan-map-legs {
  max-height: 220px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 4px;
  padding: 4px; font-variant-numeric: tabular-nums;
}
.pm-leg {
  display: flex; align-items: center; gap: 6px; min-width: 0;
  font-size: 12.5px; color: var(--c-slate); line-height: 1.35;
}
.pm-chip {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; width: 18px; height: 18px; border-radius: 50%;
  background: var(--c-ocean); color: var(--c-white);
  font-size: 10.5px; font-weight: 700; line-height: 1;
  border: 1px solid var(--c-white); box-shadow: 0 1px 3px rgba(11, 27, 61, 0.3);
}
.pm-chip--entry { background: var(--c-purple); }
.pm-chip--meet, .pm-chip--show { background: var(--c-purple); }
.pm-chip--thrill { background: var(--c-err); }
.pm-chip--indoor, .pm-chip--gentle, .pm-chip--ride { background: var(--c-ocean); }
.pm-chip--meal { background: var(--c-warn); }
.pm-leg-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pm-leg-name:first-of-type { flex: 1 0 0; text-align: right; }
.pm-leg-name:last-of-type { flex: 1 0 0; }
.pm-leg-arrow { flex: none; color: var(--c-slate-mute); }
.pm-leg-walk {
  flex: none; font-size: 11px; font-weight: 600; color: var(--c-slate-soft);
}

.explain {
  background: var(--c-ocean-soft);
  border-radius: var(--r-md);
  padding: 14px 16px; font-size: 14px; color: var(--c-slate);
  margin-bottom: 20px;
}

/* Day timeline — vertical blocks, ≥56px touch targets */
.day-timeline {
  --tl-times-w: 64px; --tl-node-w: 16px; --tl-tag-w: 88px; --tl-gap: 12px;
  display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px; position: relative;
}
/* Gutter connector: a thin spine running down the MIDDLE of the node column
   (its centre = times col + gap + half the node col), linking every time block
   so the day reads as one continuous timeline. */
.day-timeline::before {
  content: ""; position: absolute; top: 6px; bottom: 6px;
  left: calc(var(--tl-times-w) + var(--tl-gap) + var(--tl-node-w) / 2 - 1px); width: 2px;
  background: var(--c-border); border-radius: 1px; z-index: 0;
}
.dt-item {
  display: flex; align-items: stretch; gap: var(--tl-gap); min-height: 56px;
  opacity: 0; transform: translateY(12px);
  animation: dt-in 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
  position: relative; z-index: 1;
}
@keyframes dt-in { to { opacity: 1; transform: translateY(0); } }
/* Times column — fixed width, OUTSIDE the card, left of the spine. Text never
   touches the node column. */
.dt-times {
  flex: 0 0 var(--tl-times-w);
  display: flex; flex-direction: column; justify-content: center;
  text-align: right; font-variant-numeric: tabular-nums;
}
.dt-time-start {
  font-size: 14px; font-weight: 700; color: var(--c-navy); line-height: 1.3;
}
.dt-time-end {
  font-size: 12px; font-weight: 500; color: var(--c-slate-soft); line-height: 1.3;
}
/* Node column — its own fixed-width container, distinct from the time text.
   The spine runs down its middle; the node circle is centred on it. */
.dt-node-col {
  flex: 0 0 var(--tl-node-w); position: relative;
  display: flex; align-items: center; justify-content: center;
}
.dt-node {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--c-white); border: 2px solid var(--c-ocean);
  box-shadow: 0 0 0 2px var(--c-white); z-index: 1;
}
/* Entry / leave bookends: the spine runs up to the entry node at the top of
   the day and down to the leave node at the bottom, framing the plan with the
   visit window. Simple time + node + small label — no card on the right. */
.dt-edge {
  display: flex; gap: var(--tl-gap); align-items: center; min-height: 24px;
  opacity: 0; transform: translateY(12px);
  animation: dt-in 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
  position: relative; z-index: 1;
}
.dt-node--edge {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--c-border); border: none;
  box-shadow: 0 0 0 2px var(--c-white);
}
.dt-edge-label {
  font-size: 12px; font-weight: 600; color: var(--c-slate-soft);
  letter-spacing: 0.04em;
}
/* The card clips (overflow:hidden) so a full-bleed thumbnail can sit flush
   against the top/bottom/left borders and follow the card's corner radius.
   Right-side padding only — spaces the ✕ button from the card edge. */
.dt-block {
  flex: 1 1 auto; min-width: 0;
  background: var(--c-white); border: 1px solid var(--c-border);
  border-radius: var(--r-md); box-shadow: var(--shadow-soft);
  padding: 0 10px 0 0; overflow: hidden;
  display: flex; align-items: center; gap: 10px;
}
.dt-block.meal { background: rgba(180, 83, 9, 0.04); }
/* Compact full-bleed thumbnail — stretched to the card's full height and
   flush to its top/bottom/left edges. The card's overflow:hidden clips it to
   the card's rounded corners, so the tile itself carries no radius. */
.dt-thumb {
  flex: 0 0 44px; width: 44px; align-self: stretch;
  padding: 0; margin: 0; overflow: hidden; border-radius: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 700;
  background: var(--c-ocean-soft); color: var(--c-ocean-dark);
}
.dt-thumb--img { background: var(--c-skel); }
.dt-thumb-img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  margin: 0; padding: 0; border: 0; border-radius: 0;
}
.dt-thumb--meal { background: var(--c-warn-soft); color: var(--c-warn); }
.dt-thumb--thrill { background: var(--c-err-soft); color: var(--c-err); }
.dt-thumb--meet { background: var(--c-purple-soft); color: var(--c-purple); }
.dt-thumb--indoor { background: var(--c-ocean-soft); color: var(--c-ocean-dark); }
.dt-thumb--ride { background: var(--c-bg); color: var(--c-slate); }
/* Fixed-width tag container so every title starts on the same vertical line
   regardless of tag width. */
.dt-badge-row { flex: 0 0 var(--tl-tag-w); flex-shrink: 0; }
.dt-badge-row .tag {
  width: 100%; padding: 3px 4px;
  font-size: 10px; letter-spacing: 0.02em; line-height: 1.2;
}
.dt-main { flex: 1 1 auto; min-width: 0; }
.dt-name {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; font-size: 14px; font-weight: 600; color: var(--c-navy);
}
.dt-meta { display: block; font-size: 12px; color: var(--c-slate-soft); }
.dt-idle {
  display: flex; gap: var(--tl-gap); align-items: center; min-height: 24px;
  opacity: 0; animation: dt-in 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
  position: relative; z-index: 1;
}
.dt-idle-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--c-border);
}
.dt-idle-text { font-size: 11px; color: var(--c-slate-soft); letter-spacing: 0.04em; }

.confidence {
  font-size: 12px; color: var(--c-slate-soft);
  border-top: 1px dashed var(--c-border); padding-top: 14px;
  margin-bottom: 18px;
}

/* ---- Shared-day banner (opened via a shared link) ---- */
.shared-banner {
  background: linear-gradient(135deg, var(--c-ocean), var(--c-ocean-dark));
  color: #fff; border-radius: var(--r-lg);
  padding: 12px 16px;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
}
.shared-banner-text { display: flex; flex-direction: column; gap: 2px; }
.shared-banner-title { font-size: 15px; font-weight: 700; letter-spacing: 0.01em; }
.shared-banner-body { font-size: 13px; opacity: 0.92; }
.shared-banner-count {
  align-self: flex-start; margin-top: 4px;
  background: rgba(255, 255, 255, 0.18); border-radius: var(--r-pill);
  padding: 2px 10px; font-size: 12px; font-weight: 600;
}
.shared-banner-close {
  background: rgba(255, 255, 255, 0.16); border: 1px solid rgba(255, 255, 255, 0.35);
  color: #fff; width: 26px; height: 26px; border-radius: 50%;
  line-height: 1; cursor: pointer; flex: 0 0 auto; font-size: 12px;
  transition: background 0.2s;
}
.shared-banner-close:hover { background: rgba(255, 255, 255, 0.3); }

/* Attention pulse on the Build CTA when a shared day is loaded */
.shared-highlight { animation: shared-pulse 1.8s ease-in-out 2; }
@keyframes shared-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(0, 119, 200, 0.45); }
  50% { box-shadow: 0 0 0 10px rgba(0, 119, 200, 0); }
}
.action-bar { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 20px; }
/* Result actions share the compact .btn-ghost spacing so Re-optimize (primary),
   Copy/Share/Adjust (ghost) and "Reset everything" all sit at the same size. */
.action-bar .btn { padding: 8px 18px; font-size: 14px; }

/* ---- Skeleton loading ---- */
.result-loading { padding: 8px 0 4px; }
.loading-steps {
  list-style: none; margin: 0 auto 18px; padding: 0;
  max-width: 340px;
  display: flex; flex-direction: column; gap: 10px;
}
.loading-step {
  display: flex; align-items: center; gap: 11px;
  font-size: 15px; font-weight: 600;
  color: var(--c-slate-soft);
  opacity: 0.55;
  transition: opacity 0.3s ease, color 0.3s ease;
}
.loading-step[data-state="active"] { opacity: 1; color: var(--c-ocean); }
.loading-step[data-state="done"] { opacity: 1; color: var(--c-slate); }

.ls-icon {
  position: relative; flex: 0 0 20px; width: 20px; height: 20px;
  border-radius: 50%;
  border: 2px solid var(--c-border);
  background: transparent;
  transition: background 0.2s ease, border-color 0.2s ease;
}
.loading-step[data-state="active"] .ls-icon {
  border-color: var(--c-ocean);
  background: rgba(0, 119, 200, 0.08);
  animation: ls-pulse 1.1s ease-in-out infinite;
}
.loading-step[data-state="done"] .ls-icon {
  background: var(--c-ok); border-color: var(--c-ok);
}
.ls-check { display: none; position: absolute; inset: 0; margin: auto; width: 13px; height: 13px; }
.ls-check path {
  fill: none; stroke: #fff; stroke-width: 3;
  stroke-linecap: round; stroke-linejoin: round;
}
.loading-step[data-state="done"] .ls-check { display: block; animation: ls-fade 0.15s ease-out; }
@keyframes ls-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}
@keyframes ls-fade { from { opacity: 0; } to { opacity: 1; } }

/* ---- Magic loader: ferris wheel orbit ---- */
.ferris-wrap {
  position: relative;
  width: 84px; height: 84px;
  margin: 0 auto 10px;
}
.ferris { width: 100%; height: 100%; overflow: visible; }
.wheel { animation: spin 2.4s linear infinite; transform-origin: 32px 29px; }
.cabin {
  animation: glow 1.6s ease-in-out infinite;
  transform-origin: 32px 29px;
}
.cabin.c-pink  { fill: var(--c-pink); color: var(--c-pink); animation-delay: 0s; }
.cabin.c-gold  { fill: var(--c-gold-soft); color: var(--c-gold-soft); animation-delay: .4s; }
.cabin.c-sky   { fill: var(--c-sky); color: var(--c-sky); animation-delay: .8s; }
.cabin.c-coral { fill: var(--c-coral); color: var(--c-coral); animation-delay: 1.2s; }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes glow {
  0%, 100% { opacity: .35; filter: drop-shadow(0 0 0 rgba(0, 0, 0, 0)); }
  50% { opacity: 1; filter: drop-shadow(0 0 3px currentColor); }
}
.sparkle-field { position: absolute; inset: 0; }
.spk {
  position: absolute; font-size: 13px; line-height: 1;
  opacity: 0; pointer-events: none;
  animation: drift 1.7s ease-out infinite;
}
.spk.s1 { color: var(--c-sky);  top: 8%;  left: 6%;  animation-delay: 0s;    --dx: 6px; }
.spk.s2 { color: var(--c-pink); top: 2%;  left: 38%; animation-delay: .25s;  --dx: -5px; }
.spk.s3 { color: var(--c-gold-soft); top: 20%; left: 82%; animation-delay: .5s; --dx: 5px; }
.spk.s4 { color: var(--c-purple); top: 0%;  left: 64%; animation-delay: .75s; --dx: -6px; }
.spk.s5 { color: var(--c-sky);  top: 70%; left: 90%; animation-delay: 1s;    --dx: 4px; }
.spk.s6 { color: var(--c-coral); top: 78%; left: 2%;  animation-delay: 1.25s; --dx: -4px; }
.spk.s7 { color: var(--c-gold-soft); top: 62%; left: -2%; animation-delay: .1s; --dx: 7px; }
.spk.s8 { color: var(--c-ocean); top: 44%; left: 94%; animation-delay: .6s;  --dx: -7px; }
@keyframes drift {
  0%   { transform: translate(0, 0) scale(.4) rotate(0deg); opacity: 0; }
  25%  { opacity: 1; }
  100% { transform: translate(var(--dx, 4px), -34px) scale(1) rotate(90deg); opacity: 0; }
}

/* ---- Cast burst: build CTA ---- */
.btn-build.cast { animation: cast-squash .18s ease-out; }
@keyframes cast-squash {
  0% { transform: scale(1); }
  40% { transform: scale(1.03, .97); }
  100% { transform: scale(1); }
}
.magic-burst { position: absolute; inset: 0; pointer-events: none; z-index: 5; }
.spk-burst {
  position: absolute; left: 50%; top: 50%;
  width: 7px; height: 7px; margin: -3px 0 0 -3px; border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff 0 35%, var(--c-gold-soft) 100%);
  box-shadow: 0 0 6px rgba(255, 209, 102, .85);
  opacity: 0;
  animation: sparkle-fly .6s cubic-bezier(.16, 1, .3, 1) var(--delay, 0s) forwards;
}
@keyframes sparkle-fly {
  0% { opacity: 0; transform: translate(0, 0) scale(.4); }
  20% { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx, 0), var(--dy, -26px)) scale(1) rotate(var(--rot, 0deg)); }
}

/* ---- Result reveal (ta-da) ---- */
.result-body .result-kicker { animation: pop-in .42s cubic-bezier(.34, 1.56, .64, 1) both; }
.result-body .result-title { animation: fade-up .42s ease-out .08s both; }
.result-body .action-bar { animation: fade-up .42s ease-out .14s both; }
.result-body .kpi-card { animation: fade-up .42s cubic-bezier(.34, 1.56, .64, 1) both; }
.result-body .kpi-card:nth-child(1) { animation-delay: .22s; }
.result-body .kpi-card:nth-child(2) { animation-delay: .28s; }
.result-body .kpi-card:nth-child(3) { animation-delay: .34s; }
.result-body .explain { animation: fade-up .42s ease-out .38s both; }
.result-body .result-recap { animation: fade-up .42s ease-out .12s both; }
.result-body .action-bar--repeat { animation: fade-up .42s ease-out .38s both; }
#confidenceText { animation: fade-up .42s ease-out .38s both; }
@keyframes pop-in {
  0% { opacity: 0; transform: translateY(8px) scale(.96); }
  60% { opacity: 1; transform: translateY(-1px) scale(1.015); }
  100% { opacity: 1; transform: none; }
}
@keyframes fade-up {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* ---- Favourite star micro-pop ---- */
.icon-btn--fav.star-pop { animation: star-pop .28s cubic-bezier(.34, 1.56, .64, 1); }
@keyframes star-pop {
  0% { transform: scale(.6); }
  55% { transform: scale(1.3); filter: drop-shadow(0 0 4px var(--c-gold-glow)); }
  100% { transform: scale(1); filter: none; }
}

/* ---- Interaction feedback toolkit (Fx.* in app.js) ----
   Restraint rule: these are the ONLY non-press animations. Sparkles fire only
   on intentional wins (preset apply / build); pops confirm a selection flip;
   the toast is the single confirmation channel for bulk/irreversible changes. */
.fx-pop { animation: fx-pop .18s ease-out; }
@keyframes fx-pop {
  from { opacity: .55; transform: scale(.985); }
  to { opacity: 1; transform: scale(1); }
}

/* Row-level toggle confirmation: a soft background wash at the point of change
   (ocean when re-including, red when excluding) that just fades out — no ring,
   no bounce. */
.toggle-pop { animation: toggle-pop .4s ease-out; }
@keyframes toggle-pop {
  from { background: var(--c-ocean-soft); }
  to { background: transparent; }
}
.toggle-pop.excl-flash { animation-name: toggle-pop-excl; }
@keyframes toggle-pop-excl {
  from { background: var(--c-err-soft); }
  to { background: transparent; }
}

/* Automatic value-change feedback (Fx.flash in app.js) — a field that was just
   rewritten FOR the user (date switch re-picks entry/leave, forecast park hours
   move the window, meal eligibility drops a meal, reset restores defaults) gets
   a soft ocean wash + border pulse so the change reads as "done" instead of
   silently applying. Same palette as .toggle-pop; heavier ring because these are
   system changes the user didn't click on. */
.fx-flash { animation: fx-flash .6s ease-out; }
@keyframes fx-flash {
  0% {
    background-color: var(--c-ocean-soft);
    border-color: var(--c-ocean);
    box-shadow: var(--focus-ring);
  }
  100% {
    background-color: transparent;
    border-color: var(--c-border);
    box-shadow: none;
  }
}

/* Toast — a quiet confirmation pill, top-centre under the sticky header.
   Fades in with a tiny settle (ease-out only), auto-dismisses, tap to dismiss,
   never modal. */
.toast-root {
  position: fixed; top: 72px; left: 0; right: 0; z-index: 120;
  display: flex; justify-content: center; pointer-events: none;
  padding: 0 16px;
}
.toast {
  pointer-events: auto; cursor: pointer;
  background: var(--c-navy); color: #fff;
  border-radius: var(--r-pill); padding: 9px 16px;
  font-size: 13px; font-weight: 600;
  box-shadow: 0 4px 16px rgba(9, 12, 21, 0.18);
  display: inline-flex; align-items: center; gap: 8px;
  animation: toast-in .22s ease-out both;
  max-width: 100%;
}
.toast b { color: var(--c-gold-soft); font-weight: 700; }
.toast.is-leaving { animation: toast-out .16s ease-in both; }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes toast-out {
  to { opacity: 0; transform: translateY(-4px); }
}

@media (prefers-reduced-motion: reduce) {
  .wheel, .cabin, .spk { animation: none; }
  .cabin { opacity: 1; }
  .spk { opacity: 0; }
  .hs, .hs-shoot { animation: none; opacity: .25; }
  .btn-build.cast, .spk-burst { animation: none; }
  .result-body .result-kicker,
  .result-body .result-title,
  .result-body .action-bar,
  .result-body .kpi-card,
  .result-body .explain,
  .result-body .result-recap,
  #confidenceText { animation: none; }
  .icon-btn--fav.star-pop { animation: none; }
  .pref-summary-pop { animation: none; }
  .fx-pop, .toggle-pop, .toast, .toast.is-leaving, .fx-flash { animation: none; }
  .ls-icon { animation: none !important; }
  .ls-check { animation: none; }
  .hero-eyebrow { transition: none; }
  .hero-sub .hs-char { animation: none; opacity: 1; transform: none; filter: none; }
}

/* ---- Infeasible ---- */
.infeasible {
  background: var(--c-warn-bg); border: 1px solid var(--c-warn-border);
  border-radius: var(--r-lg); padding: 24px;
}
.infeasible h3 { font-size: 18px; color: var(--c-warn); margin-bottom: 8px; }
.infeasible-reason { font-size: 13px; color: var(--c-slate); margin-bottom: 12px; }
.infeasible-hint { font-size: 14px; font-weight: 600; margin-bottom: 10px; }
.fix-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }

/* ---- Modal ---- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(9, 12, 21, 0.5);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  animation: fade-in 0.2s ease-out;
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
.modal {
  background: var(--c-white); border-radius: var(--r-lg);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
  width: 100%; max-width: 640px; max-height: 84vh;
  display: flex; flex-direction: column;
  animation: modal-in 0.2s ease-out;
}
@keyframes modal-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
.modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px 12px;
}
.modal-head h3 { font-size: 17px; font-weight: 700; }
.modal-close {
  background: none; border: none; font-size: 24px; line-height: 1;
  color: var(--c-slate-soft); cursor: pointer; padding: 2px 8px;
  border-radius: var(--r-sm); transition: background 0.15s;
}
.modal-close:hover { background: var(--c-bg); color: var(--c-navy); }
.modal-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 20px 12px; border-bottom: 1px solid var(--c-border);
}
.modal-toolbar-btns { display: flex; gap: 8px; }
.modal-toolbar .btn-ghost { padding: 5px 12px; font-size: 12px; }
/* Attraction search */
.modal-search { padding: 10px 20px 2px; }
.modal-search-box {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--c-border); border-radius: var(--r-lg);
  padding: 0 10px; background: var(--c-bg);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.modal-search-box:focus-within { border-color: var(--c-ocean); box-shadow: 0 0 0 3px rgba(0, 119, 200, 0.15); }
.modal-search-ic { width: 16px; height: 16px; color: var(--c-slate-soft); flex: 0 0 auto; }
.modal-search-box input {
  flex: 1 1 auto; min-width: 0; border: none; outline: none; background: none;
  color: var(--c-navy); font-family: inherit; font-size: 14px; line-height: 1.3;
  padding: 9px 0;
}
.modal-search-box input::placeholder { color: var(--c-slate-soft); }
/* Hide the native clear "x" (WebKit/Edge) — we render our own. */
.modal-search-box input::-webkit-search-cancel-button,
.modal-search-box input::-webkit-search-decoration { -webkit-appearance: none; }
.modal-search-clear {
  flex: 0 0 auto; border: none; background: none; cursor: pointer;
  color: var(--c-slate-soft); font-size: 18px; line-height: 1;
  width: 24px; height: 24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s, color 0.15s;
}
.modal-search-clear:hover { background: var(--c-border); color: var(--c-navy); }
.attr-search-empty {
  text-align: center; padding: 42px 16px; color: var(--c-slate-soft);
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.attr-search-empty p { margin: 0; font-size: 14px; line-height: 1.5; }
.modal-list { overflow-y: auto; padding: 8px 12px; flex: 1 1 auto; }
.modal-foot { padding: 14px 20px; border-top: 1px solid var(--c-border); text-align: right; }

/* Feedback modal */
.modal-body { overflow-y: auto; padding: 4px 20px 8px; flex: 1 1 auto; }
.feedback-form { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.feedback-sub { font-size: 13px; color: var(--c-slate-soft); margin: 0 0 14px; line-height: 1.5; }
.feedback-cats { display: flex; gap: 8px; flex-wrap: wrap; }
.feedback-message {
  width: 100%; border: 2px solid var(--c-border); border-radius: var(--r-md);
  padding: 10px 12px; font-size: 14px; font-family: inherit; line-height: 1.5;
  resize: vertical; background: var(--c-bg); color: var(--c-navy);
}
.feedback-message:focus { outline: none; border-color: var(--c-ocean); }
.feedback-count { display: block; font-size: 11px; color: var(--c-slate-soft); text-align: right; margin-top: 4px; }

/* Feedback "which ride or show" combobox — a single custom chevron + a real
   dropdown list so it works on mobile (native <datalist> hides its popup on
   iOS Safari and doubles the caret on focus). Free text is always allowed. */
.fb-combo { position: relative; }
.fb-combo-box { position: relative; }
.fb-combo-btn {
  position: absolute; top: 2px; right: 2px; bottom: 2px; width: 42px;
  border: none; background: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.fb-combo-btn::after {
  content: ""; display: block;
  width: 0; height: 0;
  border-left: 6px solid transparent; border-right: 6px solid transparent;
  border-top: 7px solid var(--c-navy);
  transition: transform 0.15s;
}
.fb-combo.is-open .fb-combo-btn::after { transform: rotate(180deg); }
.fb-combo-list {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px);
  background: var(--c-white); border: 1px solid var(--c-border); border-radius: var(--r-md);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.18);
  max-height: 240px; overflow-y: auto; -webkit-overflow-scrolling: touch; z-index: 30;
  list-style: none; margin: 0; padding: 6px;
}
.fb-combo-list li {
  padding: 9px 12px; border-radius: var(--r-sm); cursor: pointer;
  font-size: 15px; line-height: 1.35;
}
.fb-combo-list li.is-active,
.fb-combo-list li:hover { background: var(--c-bg); }
.fb-combo-other {
  display: flex; align-items: center; gap: 8px;
  font-weight: 600; color: var(--c-ocean);
}
.fb-combo-empty { color: var(--c-slate-soft); font-size: 13px; cursor: default; }
.feedback-stars { display: flex; gap: 4px; }
.fb-star {
  background: none; border: none; cursor: pointer; font-size: 26px; line-height: 1;
  color: var(--c-border); padding: 2px 3px; transition: transform 0.12s, color 0.12s;
}
.fb-star:hover { transform: scale(1.15); }
.fb-star.is-on { color: var(--c-gold); }
.feedback-hp { position: absolute; left: -9999px; top: -9999px; opacity: 0; height: 0; overflow: hidden; }
.feedback-err {
  margin: 10px 0 0; font-size: 13px; font-weight: 600; color: var(--c-err);
  background: var(--c-err-soft); border: 1px solid var(--c-err-border);
  border-radius: var(--r-md); padding: 8px 12px;
}
.feedback-thanks { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.feedback-thanks-body { text-align: center; padding: 24px 20px 18px; }
.feedback-thanks-emoji { font-size: 40px; margin: 0 0 10px; }
.feedback-thanks h3 { font-size: 17px; font-weight: 700; margin: 0 0 8px; }
.feedback-thanks p { font-size: 14px; color: var(--c-slate-soft); line-height: 1.55; margin: 0; }
.footer-feedback {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 22px; font-size: 14px; font-weight: 600;
  color: #fff; background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.4); border-radius: var(--r-lg);
  text-decoration: none; cursor: pointer;
  transition: background 0.15s, border-color 0.2s, color 0.15s, transform 0.12s ease-out;
}
.footer-feedback:hover { background: rgba(255, 255, 255, 0.16); border-color: #fff; color: #fff; }
.footer-feedback:active { transform: scale(0.97); }
.footer-feedback .btn-ic { width: 15px; height: 15px; }

/* Compact attraction rows (modal) */
.compact-list { display: flex; flex-direction: column; }
/* Modal rows must never flex-shrink — otherwise the tall thumbnail overflows
   the squashed row when many attractions exceed the modal's height. Keep every
   row at its natural height and let the list scroll instead. */
.compact-list .crow { flex: 0 0 auto; }
.crow {
  display: flex; align-items: center; gap: 10px;
  padding: 3px 8px; cursor: pointer;
  border-radius: var(--r-md);
  transition: background 0.15s;
  user-select: none;
  min-height: 44px;
}
.crow:hover { background: var(--c-bg); }
.crow.selected { background: var(--c-ocean-soft); }
.crow-hidden { opacity: 0.4; }
.crow-hidden .crow-toggle { opacity: 0.5; }
.modal-filter-hint {
  margin: 0 2px 6px; padding: 6px 10px;
  font-size: 12px; font-weight: 600; color: var(--c-warn);
  background: var(--c-warn-bg); border: 1px solid var(--c-warn-border); border-radius: var(--r-md);
}
.crow-toggle {
  flex: 0 0 auto; width: 18px; height: 18px;
  border-radius: var(--r-sm); border: 2px solid var(--c-border);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; color: transparent;
  background: var(--c-white); transition: all 0.15s;
}
.crow.selected .crow-toggle { background: var(--c-ocean); border-color: var(--c-ocean); color: #fff; }

/* Large thumbnail — matches the inline card size so the modal list and the
   collapsed preview read consistently. Letter-tile fallback when no photo. */
.crow-thumb {
  flex: 0 0 104px; width: 104px; height: 76px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm); font-size: 24px; font-weight: 700;
  overflow: hidden;
  background: var(--c-ocean-soft); color: var(--c-ocean-dark);
}
.crow-thumb-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.crow-thumb--thrill { background: var(--c-err-soft); color: var(--c-err); }
.crow-thumb--meet { background: var(--c-purple-soft); color: var(--c-purple); }
.crow-thumb--exclusive { background: var(--c-warn-soft); color: var(--c-warn); }
.crow-thumb--ride { background: var(--c-bg); color: var(--c-slate); }

/* Single-line row body: name + badges inline, English secondary moves to the
   row's title tooltip so the compact list stays 44px tall. */
.crow-main { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px; }
.crow-name {
  flex: 0 1 auto; min-width: 0; font-size: 13px; font-weight: 500; color: var(--c-navy);
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.3;
}
.crow .name-en { display: none; }
.crow-meta-line { display: inline-flex; flex-wrap: nowrap; gap: 4px; align-items: center; }
.crow-meta-line .crow-pref { margin-left: 0; }

/* Localized attraction/show names: local primary + official English secondary.
   English-only falls back to .name-main (unchanged layout). The long English
   secondary (e.g. "Meet LinaBell at Duffy and Friends Play House") is clamped to
   one ellipsized line so rows never balloon to 5 lines on mobile. */
.name-local { display: inline; }
.name-en {
  display: block; font-size: 11px; font-weight: 500;
  color: var(--c-slate-soft); line-height: 1.25; margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.crow-spark { flex: 0 0 110px; }
.crow-spark .spark { height: 24px; }
.crow-avg { flex: 0 0 46px; text-align: right; font-size: 14px; font-weight: 600; color: var(--c-ocean-dark); font-variant-numeric: tabular-nums; }
.crow-avg small { display: block; font-size: 10px; font-weight: 500; color: var(--c-slate-soft); }

/* Sparkline */
.spark { display: block; width: 100%; height: 40px; }
.spark .line { fill: none; stroke: var(--c-ocean); stroke-width: 2; }
.spark .area { fill: rgba(0, 119, 200, 0.12); }

/* ---- Dev panels (legacy styles kept) ---- */
.dev { max-width: var(--maxw); margin: 48px auto 0; border-top: 1px dashed var(--c-border); padding: 20px 8px 0; }
.dev-hint { font-size: 12px; color: var(--c-slate-soft); margin: 4px 0 12px; }
.dev-body { margin-top: 8px; }

.vpanel {
  background: var(--c-white); border: 1px solid var(--c-border);
  border-radius: var(--r-lg); padding: 20px; margin-bottom: 14px;
}
.vpanel h3 {
  font-size: 13px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--c-navy); margin-bottom: 12px;
}
.scoring-body { margin-top: 16px; }
.scoring-inputs { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 12px; }
.sfield { margin-bottom: 0; flex: 0 0 130px; }
.scoring-note {
  background: var(--c-bg); border: 1px solid var(--c-border);
  border-radius: var(--r-md); padding: 12px 16px;
  font-size: 13px; color: var(--c-slate); margin-bottom: 16px;
}
.scoring-note b { color: var(--c-navy); }
.scoring-layout { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.scoring-table-wrap { overflow-x: auto; }
.scoring-table-wrap h3 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 8px; }
.scoring-table-wrap h3 small { text-transform: none; letter-spacing: 0; color: var(--c-slate-soft); font-weight: 400; }
.score-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.score-table th, .score-table td {
  text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--c-border); white-space: nowrap;
}
.score-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.score-table td.strong { font-weight: 700; color: var(--c-ocean-dark); }
.score-table td.times { white-space: normal; min-width: 200px; color: var(--c-slate-soft); font-size: 12px; }
.score-table tbody tr:hover { background: var(--c-bg); }

.validation-layout { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 14px; }
.checklist { list-style: none; }
.checklist li {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 6px 0; font-size: 13px; color: var(--c-slate);
  border-bottom: 1px dashed var(--c-border);
}
.checklist li:last-child { border-bottom: none; }
.checklist .icn { font-weight: 700; flex: 0 0 auto; font-size: 14px; line-height: 1.3; }
.chk-ok .icn { color: var(--c-ok); }
.chk-warn .icn { color: var(--c-warn); }
.chk-err .icn { color: var(--c-err); }

.timeline-panel { overflow: hidden; }
.timeline { position: relative; height: 96px; margin: 6px 4px 0; }
.tl-base { position: absolute; left: 0; right: 0; top: 69px; height: 2px; background: var(--c-border); }
/* Rides-open area chart: a faint green band whose top edge traces how many
   selected attractions are operating at each minute of the day. */
.tl-band { position: absolute; left: 0; right: 0; top: 0; height: 54px; }
.tl-band polygon {
  fill: rgba(26, 158, 108, 0.14);
  stroke: rgba(26, 158, 108, 0.55);
  stroke-width: 1.2;
  vector-effect: non-scaling-stroke;
}
/* Showtime tick: carries its duration instead of a bare dot. */
.tl-show { position: absolute; height: 8px; top: 14px; background: var(--c-purple); border-radius: 2px; }
/* Optimized plan blocks — the real day schedule. */
.tl-plan {
  position: absolute; top: 34px; height: 20px;
  border-radius: 3px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 10px; font-weight: 700; white-space: nowrap;
}
.tl-plan--attr { background: var(--c-ocean); }
.tl-plan--show { background: var(--c-purple); }
.tl-plan--meal { background: var(--c-warn); }
.tl-wait { position: absolute; left: 0; top: 0; bottom: 0; background: rgba(0, 0, 0, 0.28); }
.tl-plan-label { position: relative; z-index: 1; max-width: 100%; overflow: hidden; text-overflow: ellipsis; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45); }
.tl-window {
  position: absolute; top: 58px; height: 22px;
  background: linear-gradient(90deg, var(--c-ocean), var(--c-purple));
  border-radius: var(--r-sm); color: #fff; font-size: 11px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  white-space: nowrap; overflow: hidden;
}
.tl-tick { position: absolute; top: 69px; transform: translateY(-50%); font-size: 10px; color: var(--c-slate-soft); }
.timeline-legend { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 10px; font-size: 12px; color: var(--c-slate-soft); }
.timeline-legend .lg { display: inline-block; width: 14px; height: 10px; border-radius: 3px; margin-right: 6px; vertical-align: middle; }
.lg-window { background: linear-gradient(90deg, var(--c-ocean), var(--c-purple)); }
.lg-band { background: rgba(26, 158, 108, 0.35); border: 1px solid rgba(26, 158, 108, 0.6); }
.lg-plan-attr { background: var(--c-ocean); }
.lg-plan-show { background: var(--c-purple); }
.lg-plan-meal { background: var(--c-warn); }
.lg-show { background: var(--c-purple); width: 10px; height: 8px; border-radius: 2px; }

.raw-panel pre {
  font-family: Consolas, "Courier New", monospace; font-size: 12px; color: var(--c-slate);
  white-space: pre-wrap; word-break: break-all; line-height: 1.5;
}

.opt-status {
  display: flex; flex-wrap: wrap; gap: 6px 20px;
  background: var(--c-bg); border: 1px solid var(--c-border);
  border-radius: var(--r-md); padding: 10px 14px; margin-top: 12px;
  font-size: 12px; color: var(--c-slate);
}
.op-status-item b { color: var(--c-ocean-dark); }
.op-status-item small { color: var(--c-slate-soft); }

/* ---- Footer ---- */
.footer { background: var(--c-dark); color: rgba(255, 255, 255, 0.7); margin-top: 64px; }
.footer-inner {
  max-width: var(--maxw); margin: 0 auto; padding: 16px 24px;
  display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
  font-size: 12px; flex-wrap: wrap;
}
.footer-info { display: flex; flex-direction: column; gap: 4px; max-width: 560px; line-height: 1.6; }
.footer-note { margin: 0; color: rgba(255, 255, 255, 0.85); }
.footer-data { margin: 0; }
.footer-meta summary {
  display: inline-flex; align-items: center; gap: 6px;
  cursor: pointer; list-style: none;
  font-size: 13px; font-weight: 600; color: rgba(255, 255, 255, 0.85);
  transition: color 0.2s;
}
.footer-meta summary::-webkit-details-marker { display: none; }
.footer-meta summary:hover { color: #fff; }
.footer-meta[open] summary .adv-arrow { transform: rotate(180deg); }
.footer-meta[open] p { animation: footer-meta-in 0.18s ease-out; }
@keyframes footer-meta-in { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: translateY(0); } }
.footer-meta p { margin: 6px 0 0; line-height: 1.55; opacity: 0.85; }

/* ---------------- About + FAQ (AEO content) ---------------- */
.about-faq {
  max-width: var(--maxw); margin: 0 auto; padding: 8px 8px 0;
}
.about { margin: 40px 0 48px; text-align: center; }
.about h2 { font-size: 26px; font-weight: 800; color: var(--c-navy); margin: 0 0 12px; }
.about p { color: var(--c-slate-soft); line-height: 1.7; margin: 0; font-size: 15px; }
.faq { border-top: 1px solid var(--c-border); padding: 28px 0 16px; }
.faq-title {
  font-size: 15px; font-weight: 700; letter-spacing: 0.02em;
  color: var(--c-ocean-dark); text-transform: uppercase; margin: 0 0 20px;
}
.faq-item { padding: 16px 0; border-bottom: 1px solid var(--c-border); }
.faq-item h3 { font-size: 16px; font-weight: 700; color: var(--c-ink); margin: 0 0 6px; }
.faq-item p { margin: 0; font-size: 14px; line-height: 1.65; color: var(--c-slate-soft); }

/* Park pulse — build-time crawlable facts (hours, waits, showtimes) so search
   and AI engines can answer "what are the hours/waits/showtimes" from static
   HTML. Regenerated from js/data.js by scripts/build-seo.js. */
.park-pulse {
  margin: 0 0 44px; padding: 16px 20px;
  background: var(--c-ocean-soft); border: 1px solid var(--c-ocean-border);
  border-radius: var(--r-md);
}
.pulse-title { margin: 0 0 10px; font-size: 15px; font-weight: 800; color: var(--c-navy); }
.pulse-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.pulse-list li { line-height: 1.5; }
.pulse-label {
  font-size: 12px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--c-slate-mute);
}
.pulse-val { font-size: 14px; color: var(--c-ink); }

/* Planning tips — evergreen SEO/AEO content; reuses .faq item styling. The
   section follows the FAQ, so drop the second divider and pull its top padding
   in to keep the rhythm from doubling. */
.plan-tips { max-width: var(--maxw); margin: 0 auto; padding: 0 8px; }
.plan-tips .faq { border-top: 0; padding-top: 8px; }

.sticky-cta { display: none; }

/* Press smoothing — declared here (last, after every control's own transition
   rule) so it wins and guarantees the press scale-down/up actually eases; CSS
   order decides equal-specificity ties. */
.preset-btn, .pref-preset, .modal-sort-btn, .fb-cat, .pref-seg-btn,
.icon-btn, .picker-line, .crow, .st-row,
.modal-close, .shared-banner-close {
  transition: transform 0.12s ease-out, background 0.15s, border-color 0.2s, box-shadow 0.2s, color 0.15s;
}

/* ---------------- 7. Responsive ---------------- */
@media (max-width: 640px) {
  .footer-inner { flex-direction: column; align-items: flex-start; }
  .footer-feedback { align-self: flex-start; }
  body { padding-bottom: 64px; }
  /* Attraction cards stack to a single column with a smaller thumbnail so the
     tap targets stay comfortable on phones; the preview clip stays compact. */
  .attr-grid { grid-template-columns: 1fr; }
  .attr-card { height: 84px; }
  .attr-thumb { flex: 0 0 88px; width: 88px; min-height: 66px; }
  .attr-body { padding: 8px 0 8px 10px; }
  .attr-actions { padding: 8px 10px 8px 8px; }
  .attr-grid-wrap { max-height: 168px; }
  /* Preset quick-set buttons: the hint takes a full row so the buttons always
     start on a fresh line below it — no "First timer" jammed right after the
     hint text when all three buttons can't fit on the same line. */
  .preset-hint { flex-basis: 100%; }
  /* Keep the sticky header from overflowing: share collapses to an icon-only
     button (text stays accessible via visually-hidden clip) so the language
     picker fits next to the brand. */
  .site-header { padding: 10px 12px; gap: 6px; position: static; }
  .header-actions { gap: 6px; }
  .header-share { padding: 7px; }
  .header-share > span {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  /* Mobile hero: ~⅓–½ viewport, tighter padding; each stat badge re-stacks
     into a 2-line layout (number on top, descriptor beneath) so nothing wraps
     or clutters. The setup card sits clearly BELOW the hero image. */
  .hero { min-height: 42vh; }
  .hero-inner { padding: 30px 20px 46px; }
  .hero-title { font-size: clamp(24px, 6.4vw, 30px); }
  .hero-stars-row { gap: 6px; font-size: 13px; margin-bottom: 6px; }
  .hero-sub { font-size: 14px; }
  .hero-stat { flex-direction: column; align-items: center; gap: 1px; padding: 10px 14px; }
  .hs-num { font-size: 22px; }
  /* Floating "Plan my day": no bar, no chrome — just the button, the exact same
     size/width as the inline build button it hands off to. The transparent strip
     is pointer-events:none so taps beside the button pass through to the page. */
  .sticky-cta {
    display: block; position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    padding: 10px 8px;
    pointer-events: none;
  }
  .sticky-cta-btn { pointer-events: auto; }
  .kpi-row { grid-template-columns: 1fr; gap: 8px; }
  .kpi-card { flex-direction: row; align-items: baseline; gap: 8px; flex-wrap: wrap; }
  .kpi-value { font-size: 22px; }
  /* Day timeline on phones: keep the same single-row layout as desktop — fixed
     time column + node column left of the card, title/meta in the flexing main
     column — just tighter widths so nothing wraps. */
  .day-timeline { --tl-times-w: 48px; --tl-node-w: 14px; --tl-tag-w: 56px; --tl-gap: 8px; }
  .dt-time-start { font-size: 13px; }
  .dt-time-end { font-size: 11px; }
  .dt-block { gap: 6px; padding: 0 8px 0 0; }
  .dt-thumb { flex-basis: 40px; width: 40px; font-size: 14px; }
  .dt-badge-row .tag { padding: 3px 3px; }
  .dt-name { font-size: 13px; }
  .dt-meta { font-size: 11px; }
  .plan-map { height: 280px; }
  .scoring-layout, .validation-layout { grid-template-columns: 1fr; }
  .pref-controls { grid-template-columns: 1fr; }
  /* Preference preset cards wrap into a 3-column grid (2 below 340px) so each
     stays a tap-friendly icon-over-text target on phones. */
  .pref-presets { grid-template-columns: repeat(3, 1fr); gap: 8px; }
  @media (max-width: 340px) { .pref-presets { grid-template-columns: repeat(2, 1fr); } }
  /* Attraction rows: drop the sparkline + slim buttons so long names keep a
     healthy width instead of collapsing to one word per line. The wait avg
     stays; users can still scan busyness via the sort chips. */
  .crow { gap: 4px 8px; padding: 3px 6px; }
  .crow-spark { display: none; }
  .crow .icon-btn--fav { width: 28px; height: 28px; font-size: 16px; }
  .crow .icon-btn--excl { width: 26px; height: 26px; font-size: 13px; }
  .crow-avg { flex-basis: 36px; font-size: 13px; }
  .crow-name { font-size: 13px; -webkit-line-clamp: 1; }
  /* Attraction picker: stack the count + Edit above the chips so the selected
     names get the full row width and each pill sits on its own line. */
  .picker-line { flex-direction: column; align-items: stretch; gap: 10px; }
  .picker-meta { width: 100%; justify-content: space-between; }
  .chip-tray { width: 100%; }
  /* Show timeline: widen the sticky name column and slim the star/skip chrome
     so names like "Ant-Man and The Wasp: Nano Battle!" wrap into at most two
     full lines on phones. */
  .st-name-col { flex-basis: 200px; }
  .st-name-line { gap: 4px; }
  .st-name-text { -webkit-line-clamp: 3; }
  .st-name-line .icon-btn--fav,
  .st-name-line .icon-btn--fav-sm { width: 24px; height: 24px; font-size: 14px; }
  .st-name-line .icon-btn--excl { width: 24px; height: 24px; font-size: 12px; }
  .st-header, .st-row { min-width: 620px; }
  .modal-overlay { padding: 0; align-items: flex-end; }
  .modal { max-width: none; max-height: 92vh; border-radius: var(--r-lg) var(--r-lg) 0 0; }
  /* Attraction picker: full-screen, edge to edge — top to bottom, no gaps —
     and float the Done button over the image grid instead of a solid footer
     bar (images extend behind the footer area). */
  #attrModal.modal-overlay { padding: 0; align-items: stretch; }
  #attrModal .modal {
    max-width: none; width: 100%; height: 100vh; height: 100dvh;
    max-height: none; border-radius: 0; position: relative;
  }
  #attrModal .modal-foot {
    position: absolute; right: 12px; bottom: 12px; z-index: 10;
    border: none; background: none; padding: 0;
  }
  #attrModal .modal-foot .btn-primary {
    box-shadow: 0 6px 18px rgba(11, 27, 61, 0.35);
  }
  #attrModal .modal-list { padding-bottom: 64px; }
}
