/* ─── Reset ─────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
img, svg { display: block; }
a { text-decoration: none; color: inherit; }

/* ─── CSS Variables ────────────────────────────────────────────────────────
   Design tokens (dark + light) live in ONE place: p/tokens.css, which every
   page links BEFORE this file. Do not redefine tokens here — a second copy is
   what the white-label theme engine has to override twice
   (WEBSYS_MD/white-label-assessment.md §2.2). */

/* In-app browser bottom inset (2026-08-27). NOT --safe-bottom: that token is
   also used as PADDING in a dozen places (#bottom-bar's own height, modal
   scrims, page bottoms), so widening it to a real number would inflate all of
   them. This one is only ever ADDED to a floating element's `bottom` offset.
   (#bottom-bar and .ppw-back-to-top omit this token on purpose since
   2026-09-23 — they keep --safe-bottom only.)
   0 everywhere except inside an in-app browser, where the app draws its own
   controls over the page without shrinking the viewport and without
   reporting anything through env(safe-area-inset-bottom) — measured 233px of
   coverage on Android 16 / TwitterAndroid 12.19.1 at 411x852, with
   innerHeight, visualViewport and all four viewport units agreeing on 852.
   The app collapses those controls (and grows its sheet) once the page is
   scrolled, which is what `is-inapp-scrolled` tracks — set from the same
   pre-paint block that sets `is-inapp`. **The intent is that a floating
   control HUGS the top edge of that bar and follows it down as it collapses,
   taking the place the reload button vacated — not that it parks somewhere
   safe and stays there** (owner's ruling, 2026-08-27). Everything reads this
   one token, so they all move together.

   Values re-measured off the probe page's own ruler rather than estimated
   (2026-08-27, Android 16 / TwitterAndroid 12.19.1, 411x852): the full bar
   covers 194-222px, the collapsed bar covers 94-132px, and — the piece
   missed the first time — `env(safe-area-inset-bottom)` reports **15px**
   there, which every one of these offsets already adds. So a control sitting
   at `20px + safe + inapp` lands at 240px / 150px, roughly 18px above the
   bar in both states. Earlier values of 233/150 put it 46px and 33px clear,
   which read as floating rather than hugging. Anything that hides itself on scroll
   never sees the smaller value; the main site's #bottom-bar, which does not,
   is the reason the second value exists at all. */
:root { --inapp-bottom: 0px; }
:root.is-inapp { --inapp-bottom: 0px; } /* was 214px — buttons hug the edge, owner ruling 2026-10-23 */
:root.is-inapp.is-inapp-scrolled { --inapp-bottom: 0px; } /* was 117px — buttons hug the edge, owner ruling 2026-10-23 */
/* iOS is a different app build with a different, much smaller control bar —
   measured 31px of coverage against Android's 222px (2026-08-27, iPhone /
   iOS 26.6, 390x575). 30px lands a floating control ~18px above that bar —
   the same clearance the Android values give — because iOS reports
   safe-area-inset-bottom as 0 where Android reports 15px, so the control's
   own 20px offset is all that is added underneath. Two classes, so it ties with the
   `is-inapp-scrolled` rule above on specificity and wins on order — which is
   intended: iOS never gets that class, since its bar does not collapse. */
/* iOS needs NOTHING here, and that is the whole point (corrected 2026-08-27,
   second pass). On iOS the app's viewport ENDS above its own controls —
   screen.height 844 vs innerHeight 575, a 269px difference that is status bar
   plus address bar plus the tweet strip — so nothing of ours is ever covered,
   and `dvh` already reports the truth (575, against vh/svh/lvh's 631). Android
   is the opposite: innerHeight 852 against screen.height 892 is only the
   status bar, so its viewport runs to the physical bottom and the app's bar
   floats ON TOP of the page, invisible to every viewport unit — all four
   report 852. The 31px measured on an iPhone screenshot was the height of a
   bar sitting OUTSIDE the viewport; reserving for it just pushed every
   control 31px too high. Zero here is a real value, not a missing one. */
:root.is-inapp.is-inapp-ios { --inapp-bottom: 0px; }
/* And iOS reports a TOP inset that is not there. In the X app's sheet the
   WebView already starts below the notch, but env(safe-area-inset-top) still
   reports the whole screen's 44px — so `.ppw-nav` (height --navbar-h + this,
   plus a matching padding-top) rendered 100px tall instead of 56px, leaving a
   44px band above it. Confirmed by the probe page's top ruler reading 0 with
   nothing covering it. Android reports 0 here, so this line is a no-op there.
   NOTE: the same value read 0 on an earlier measurement of the same device —
   it changes with how far the sheet is dragged, so it cannot be trusted at
   all inside this browser, in either direction. */
:root.is-inapp { --safe-top: 0px; }
/* Reserved page area vs. lifted control offset — two different questions, two
   different tokens (2026-08-27). --inapp-bottom above answers "how far up must
   a FLOATING CONTROL sit to clear the bar", and it deliberately changes when
   the bar collapses. --inapp-reserve answers "how much of the page can never
   be used", and it must NOT change on scroll: driving a layout size from the
   collapsing value would resize the map every time the page is scrolled.
   It therefore takes the larger, bar-open figure and holds it. */
:root { --inapp-reserve: 0px; }
:root.is-inapp { --inapp-reserve: 0px; } /* was 229px — map keeps its browser height, owner ruling 2026-10-23 */
:root.is-inapp.is-inapp-ios { --inapp-reserve: 0px; }

/* Tell the browser this page IS dark, and follow the site's own toggle
   (2026-08-27). Without this declaration a browser has no way to know the
   page ships a dark theme of its own — Android WebView (which is what the X
   app's in-app browser is) then treats the page as light-only and runs its
   own algorithmic darkening on top of our CSS, recomputing every colour by
   heuristic. Reported as "colours look off in the X app on Android in dark
   mode". Must track data-theme, NOT prefers-color-scheme: the site's dark
   default is deliberate and independent of the OS setting (2026-08-06 ask),
   so a flat `color-scheme: dark` would leave light mode declaring the wrong
   scheme and its native controls rendering dark. Side benefit: scrollbars,
   checkboxes and date pickers pick the right built-in palette on their own —
   this does NOT replace the per-class `option { background }` rules, which
   are still required (see CLAUDE.md, native <select> theming). */
:root { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }

/* ─── Base ───────────────────────────────────────────────────────────────── */
html { scroll-behavior: smooth; }

body {
  background: var(--bg-primary);
  color: var(--text-primary);
  font-family: var(--font-thai);
  font-size: 15px;
  line-height: 1.5;
  /* vh + dvh pair (2026-08-22) — on iOS a bare 100vh is the LARGE viewport
     (address bar hidden), leaving the body ~98pt taller than what is on
     screen while the bar shows. Same convention as every /p page. */
  min-height: 100vh;
  min-height: 100dvh;
  overflow-x: hidden;
  position: relative;
}

/* ── Shared scrollbar — mirrors /p's global rule in p/tokens.css (2026-07-07)
   so the main site (index.html, 404.html, 403.html) matches every /p page
   instead of falling back to the browser default. Main site deliberately
   doesn't import p/tokens.css (see CLAUDE.md's main-site/`/p` boundary),
   so the rule is duplicated here rather than shared via import. */
* { scrollbar-width: thin; scrollbar-color: rgba(var(--surface-rgb), 0.18) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: rgba(var(--surface-rgb), 0.18); border-radius: var(--radius-pill); border: 2px solid transparent; background-clip: padding-box;
}
@media (hover: hover) { *::-webkit-scrollbar-thumb:hover { background: rgba(var(--surface-rgb), 0.32); background-clip: padding-box; } }

/* ─── Emoji / UI icons (Fluent Emoji SVG + inline line icons, replacing raw emoji characters) ─── */
/* transform: translateZ(0) (2026-07-27 ask) — see p/tokens.css's copy of this
   rule for the full explanation: works around an iOS WebKit bug where icons
   painted inside a `backdrop-filter: blur()` ancestor render pixelated. */
.emoji-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.125em;
  display: inline-block;
  transform: translateZ(0);
  opacity: 0;
  filter: blur(4px);
  transition: opacity 0.2s ease, filter 0.2s ease;
}
.emoji-icon.is-loaded { opacity: 1; filter: blur(0); }

.flag-icon {
  border-radius: var(--radius-xs);
  object-fit: cover;
  vertical-align: middle;
  flex-shrink: 0;
}

.icon-inline {
  width: 0.85em;
  height: 0.85em;
  vertical-align: -0.1em;
  fill: none;
  color: currentColor;
}

/* ─── Shooting stars ────────────────────────────────────────────────────── */
#shooting-stars { position: fixed; inset: 0; pointer-events: none; z-index: 0; overflow: hidden; }

.shooting-star {
  position: absolute;
  width: 100px;
  height: 1px;
  /* Peak alpha 0.85 -> 0.68 (2026-08-06 ask — "ลดความเข้มลง 20%"). */
  background: linear-gradient(90deg, rgba(var(--star-rgb),0) 0%, rgba(var(--star-rgb),0.68) 60%, rgba(var(--star-rgb),0) 100%);
  pointer-events: none;
  opacity: 0;
  animation: shoot var(--dur, 5s) var(--delay, 0s) infinite ease-in;
}

@keyframes shoot {
  0%   { opacity: 0; transform: translate(0, 0) rotate(var(--ang, -30deg)); }
  3%   { opacity: 0.8; }
  25%  { opacity: 0; transform: translate(var(--dx, 300px), var(--dy, 150px)) rotate(var(--ang, -30deg)); }
  100% { opacity: 0; transform: translate(var(--dx, 300px), var(--dy, 150px)) rotate(var(--ang, -30deg)); }
}

/* ─── Zone tooltip ───────────────────────────────────────────────────────── */
.zone-tooltip {
  position: fixed;
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font-thai);
  padding: 4px 10px;
  border-radius: var(--radius-xs);
  pointer-events: none;
  z-index: 200;
  opacity: 0;
  transition: opacity 0.1s;
  border: 1px solid var(--border);
  white-space: nowrap;
}
.zone-tooltip.visible { opacity: 1; }

/* ─── Starfield background ───────────────────────────────────────────────── */
#starfield { position: fixed; inset: 0; pointer-events: none; z-index: 0; overflow: hidden; }

.star {
  position: absolute;
  border-radius: var(--radius-full);
  background: rgb(var(--star-rgb));
  animation: twinkle var(--twinkle-dur, 3s) var(--twinkle-delay, 0s) infinite ease-in-out;
}

@keyframes twinkle {
  0%, 100% { opacity: var(--opacity-lo, 0.2); transform: scale(1); }
  50%       { opacity: var(--opacity-hi, 0.9); transform: scale(1.15); }
}

/* Grain overlay (2026-07-27, Feel Lab ref) — SVG feTurbulence noise at very
   low opacity to soften gradient color bands, not a decorative texture
   (kept low enough to be imperceptible at a glance). Mirrors p/tokens.css's
   identical rule for the /p subsystem. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.03;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Blurred radial gradient behind seat map (~600px, purple/navy, ~15% opacity) */
body::after {
  content: '';
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -30%);
  width: 600px;
  height: 600px;
  border-radius: var(--radius-full);
  background: radial-gradient(circle, rgba(90, 40, 160, 0.15) 0%, transparent 70%);
  filter: blur(40px);
  pointer-events: none;
  z-index: 0;
}

/* All content above pseudo-elements. (.ppw-nav, the shared Global Nav
   mounted by nav-space.js, sets its own z-index:1000 in nav.css — no longer
   needs to be listed here, 2026-07-11.) */
#page-layout, #bottom-bar { position: relative; z-index: 1; }

/* ─── Page Layout wrapper ────────────────────────────────────────────────── */
#page-layout {
  display: flex;
  flex-direction: column;
}

/* Desktop: fixed viewport — no page-level scroll, only inner columns scroll */
@media (min-width: 1024px) {
  #page-layout {
    position: fixed;
    top: var(--navbar-total-h);
    bottom: calc(var(--bottom-h) + var(--safe-bottom));
    left: 0;
    right: 0;
    overflow: hidden;
  }
}

/* ─── [B] Hero Section ───────────────────────────────────────────────────── */
#hero {
  padding: 8px 32px 0;
  /* No margin-top compensation needed (2026-07-11 — was var(--navbar-h) here,
     "push below fixed navbar"): the old #navbar was position:fixed (removed
     from flow), but .ppw-nav (nav-space.js/nav.css) is position:sticky, so
     it already occupies its own var(--navbar-h) box in normal flow (since
     2026-08-22 that box is --navbar-total-h, i.e. navbar-h plus the iOS top
     safe-area inset) — an extra margin-top here would just double that gap
     on mobile. */
  flex-shrink: 0;
}

.hero-inner {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  padding-top: 12px;
}

.hero-poster {
  width: 144px;
  height: auto;
  border-radius: var(--radius-md);
  object-fit: cover;
  flex-shrink: 0;
}

.hero-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-top: 4px;
}

.sold-out-badge {
  display: inline-block;
  align-self: flex-start;
  font-family: var(--font-latin);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 2.5px;
  color: var(--text-primary);
  background: rgba(var(--accent-gold-rgb),0.12);
  border: 1.5px solid var(--accent-gold);
  border-radius: var(--radius-4xl);
  padding: 3px 12px;
  margin-bottom: 6px;
  text-shadow: 0 0 6px rgba(var(--accent-gold-rgb), calc(0.8 * var(--glow-mult)));
  animation: soldout-pulse 2.4s ease-in-out infinite;
}

/* display:inline-block above beats the UA [hidden] rule — hide it explicitly. */
.sold-out-badge[hidden] { display: none; }

@keyframes soldout-pulse {
  0%   { box-shadow: 0 0 4px rgba(var(--accent-gold-rgb),0.5),  0 0 10px rgba(var(--accent-gold-rgb),0.2);  border-color: rgba(var(--accent-gold-rgb),0.9); }
  50%  { box-shadow: 0 0 12px rgba(var(--accent-gold-rgb),0.85), 0 0 28px rgba(var(--accent-gold-rgb),0.35); border-color: rgba(var(--accent-gold-rgb),1);   }
  100% { box-shadow: 0 0 4px rgba(var(--accent-gold-rgb),0.5),  0 0 10px rgba(var(--accent-gold-rgb),0.2);  border-color: rgba(var(--accent-gold-rgb),0.9); }
}

.hero-title {
  font-family: var(--font-latin);
  font-size: 50px;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.1;
  letter-spacing: -0.5px;
}

.hero-subtitle {
  font-size: 22px;
  font-weight: 600;
  color: var(--accent-gold-text);
  line-height: 1.3;
}

.hero-meta {
  font-size: 13px;
  font-weight: 400;
  color: var(--text-secondary);
  margin-top: 2px;
}
@media (max-width: 767px) {
  .hero-meta-location {
    display: block;
    margin-top: 2px;
  }
}

/* Price tier chips */
.price-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 8px;
}

.price-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 22px;
  border-radius: var(--radius-xs);
  font-family: var(--font-latin);
  font-size: 10px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.15s;
  border: 1px solid;
  white-space: nowrap;
  /* Background now driven by CSS from the --chip-r/g/b custom properties
     main.js sets per-chip (2026-07-10 fix) — it used to be an inline
     `chip.style.background`, which always wins over any CSS :hover rule
     regardless of specificity, so hover never visibly did anything. */
  background: rgba(var(--chip-r), var(--chip-g), var(--chip-b), 0.18);
}
/* Lower self-tint alpha in light mode (2026-08-08 fix) — the chip's text is
   the SAME color as this background tint, so any alpha here works against
   its own text's contrast. 18% was tuned for dark mode; kept there
   unchanged. Complements the tier lightColor re-tune in data.js (both were
   needed — background alpha alone couldn't reach 3.2:1 for every tier). */
:root[data-theme="light"] .price-chip { background: rgba(var(--chip-r), var(--chip-g), var(--chip-b), 0.10); }
.price-chip.chip-highlighted { background: rgba(var(--chip-r), var(--chip-g), var(--chip-b), 0.30); }
@media (hover: hover) { .price-chip:hover { background: rgba(var(--chip-r), var(--chip-g), var(--chip-b), 0.30); } }
/* Light-mode override for the states above (2026-08-08 fix) — missed in
   the original light-mode tuning pass since :hover/.chip-highlighted only
   render on interaction. 30% in light mode dropped the worst tier to
   2.61:1; 16% (same value used elsewhere for this exact self-tint-too-
   strong pattern, e.g. p/my.js/p/market.js badges) keeps every tier above
   the project's 3.2 floor (worst case 3.36:1). */
:root[data-theme="light"] .price-chip.chip-highlighted { background: rgba(var(--chip-r), var(--chip-g), var(--chip-b), 0.16); }
@media (hover: hover) { :root[data-theme="light"] .price-chip:hover { background: rgba(var(--chip-r), var(--chip-g), var(--chip-b), 0.16); } }
.price-chip.chip-highlighted {
  outline: 1.5px solid var(--accent-gold);
  outline-offset: 1px;
}

/* Section divider + label */
.hero-divider {
  height: 0;
  border-top: 1px solid var(--border);
  margin-top: 16px;
  width: 100%;
}

.section-label-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
}

.section-label {
  font-family: var(--font-thai);
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
}

.section-label-bar {
  width: 48px;
  height: 2px;
  background: var(--accent-gold);
  border-radius: 1px;
}
:root[data-theme="light"] .section-label-bar { background: var(--brand-gold); }

/* ─── [C] Seat Map + Zone Panel ──────────────────────────────────────────── */
#seat-section {
  display: flex;
  min-height: 420px;
  border-top: 1px solid var(--border);
}
@media (min-width: 1024px) {
  #seat-section { flex: 1; min-height: 0; overflow: hidden; }
}

.seat-col {
  flex: 1;
  overflow: auto;
  min-width: 0;
}

.seat-col-divider {
  width: 0;
  border-left: 1px solid var(--border);
  flex-shrink: 0;
  align-self: stretch;
}

/* Seat map wrapper — centres SVG, applies scaling */
#map-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 16px;
}

#map-col .price-chips {
  margin-top: 0;
  margin-bottom: 20px;
  justify-content: center;
}

#seat-map-wrap {
  width: 100%;
  max-width: 508px;
}

/* Seat lookup (competitor-review spec item 1) — magnifier in the map
   column's top-right corner at every width; tap expands a small input
   (Enter submits). Price chips keep 36px clear on both sides for it. */
#map-col { position: relative; }
#map-col .price-chips { padding: 0 36px; }
.seat-lookup {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 4px;
  max-width: 190px;
}
.seat-lookup__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  color: var(--text-primary);
  background: rgba(var(--surface-rgb),0.08);
  border: 1px solid rgba(var(--surface-rgb),0.18);
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.seat-lookup.is-open .seat-lookup__toggle { color: var(--gold-btn-text); background: var(--accent-gold); border-color: var(--accent-gold); }
@media (hover: hover) { .seat-lookup__toggle:hover { color: var(--gold-btn-text); background: var(--accent-gold); border-color: var(--accent-gold); } }
.seat-lookup__input {
  order: -1;
  flex: 1 1 0;
  min-width: 0;
  height: 28px;
  padding: 0 10px;
  font: 400 12px var(--font-thai);
  color: var(--text-primary);
  background: var(--bg-elevated);
  border: 1px solid var(--accent-gold);
  border-radius: var(--radius-pill);
}
.seat-lookup__input[hidden] { display: none; }
.seat-lookup__input::placeholder { color: rgba(var(--surface-rgb),0.42); }
.seat-lookup__input:focus { outline: none; }
.seat-lookup__msg {
  flex-basis: 100%;
  margin: 0;
  padding: 4px 8px;
  font-size: 11px;
  text-align: right;
  color: var(--accent-gold-text);
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
}
.seat-lookup__msg[hidden] { display: none; }

#seat-map {
  width: 100%;
  height: auto;
}

@media (min-width: 1024px) {
  #map-col { overflow: hidden; justify-content: center; }
  #seat-map-wrap { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; }
  #seat-map { width: auto; height: 100%; max-width: 100%; }
}

/* Zone interaction states — opacity sits on the BAND GROUP (scripts/build-seat-plan.py
   wraps every zone's shapes in .zone-band), never on each shape: the organiser's export
   overlaps shapes, and per-shape opacity stacked them into a darker patch (zone P). */
.zone { cursor: pointer; }
.zone-band {
  transition: opacity 0.15s, filter 0.15s;
  opacity: 0.7;
}

@media (hover: hover) { .zone:hover .zone-band { opacity: 1; } }

.zone.selected .zone-band {
  opacity: 1;
  filter: drop-shadow(0 0 4px rgba(var(--surface-rgb), 0.8));
}

.zone.dimmed .zone-band { opacity: 0.2; }

/* Multi-price zone: the clicked colour band stays lit, the zone's other bands fade */
.zone.selected .zone-band.band-dimmed { opacity: 0.25; filter: none; }
.price-row { transition: opacity 0.15s, box-shadow 0.15s; }
.price-row.price-row-muted { opacity: 0.4; }
.price-row.price-row-focus { box-shadow: inset 3px 0 0 var(--accent-gold); }
.price-row.price-row-clickable { cursor: pointer; }

/* The browser's focus ring is the <g>'s bounding RECTANGLE, not the zone's
   shape — drop it and show keyboard focus on the shape itself instead. */
.zone:focus { outline: none; }
.zone:focus-visible .zone-band {
  opacity: 1;
  filter: drop-shadow(0 0 4px rgba(var(--surface-rgb), 0.8));
}

/* Decor (stage, FOH, zone labels) fades with the zones. A zone's own label
   stays lit (main.js tags each label path with data-label-for). */
/* Stage/FOH/platform fade as ONE group — fading each overlapping shape on its own
   showed the seams between them. Labels fade per glyph so the lit zone keeps its own. */
.seat-plan-decor, [data-decor="zone_label"] > * { transition: opacity 0.15s; }
#seat-map.has-dim .seat-plan-decor:not([data-decor="zone_label"]) { opacity: 0.2; }
#seat-map.has-dim [data-decor="zone_label"] > * { opacity: 0.2; }
#seat-map.has-dim [data-decor="zone_label"] > .label-lit { opacity: 1; }

/* Zone panel container */
#panel-col {
  padding: 0;
  display: flex;
  flex-direction: column;
}

#zone-panel {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: rgba(var(--surface-rgb), 0.05);
  border: 1px solid rgba(var(--surface-rgb), 0.09);
  border-radius: var(--radius-md);
  margin: 12px;
  overflow: hidden;
}

.panel-header {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 16px 10px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.panel-header-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
}

.panel-header-sub {
  font-size: 11px;
  font-weight: 400;
  color: var(--text-secondary);
}

/* Panel states */
.panel-state {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--accent-violet-rgb), 0.4) transparent;
}
.panel-state::-webkit-scrollbar {
  width: 5px;
}
.panel-state::-webkit-scrollbar-track {
  background: transparent;
}
.panel-state::-webkit-scrollbar-thumb {
  background: rgba(var(--accent-violet-rgb), 0.4);
  border-radius: var(--radius-xs);
}

.panel-state.hidden { display: none; }

/* Panel fade transition */
.panel-state {
  animation: fadeIn 0.2s ease;
}

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Idle state — Most Liked Zones */
.panel-idle-header {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 16px;
}

.panel-idle-title {
  font-family: var(--font-latin);
  font-size: 18px;
  font-weight: 700;
  color: var(--text-primary);
}

.panel-idle-sub {
  font-size: 14px;
  color: var(--text-secondary);
}

.leaderboard {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.panel-idle-footer {
  font-size: 13px;
  color: var(--text-secondary);
  margin-top: 12px;
}

/* Podium cards */
.podium-row {
  display: flex;
  gap: 8px;
}

.podium-card {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
}

.podium-card.rank-1 {
  flex: 1 1 100%;
  background: rgba(var(--surface-rgb), 0.07);
}

.podium-card-top {
  display: flex;
  align-items: center;
  gap: 8px;
}

.zone-color-dot {
  width: 12px;
  height: 12px;
  border-radius: var(--radius-full);
  flex-shrink: 0;
}

.podium-zone-code {
  font-family: var(--font-latin);
  font-weight: 700;
  font-size: 15px;
  color: var(--text-primary);
}

.podium-rank-badge {
  font-size: 15px;
  margin-left: auto;
}

.podium-meta {
  font-size: 12px;
  color: var(--text-secondary);
}

.podium-likes {
  font-size: 13px;
  color: var(--like-red);
}

/* Ranks 4–10 compact list */
.leaderboard-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.leaderboard-row:last-child { border-bottom: none; }

.lb-rank {
  font-family: var(--font-latin);
  font-size: 13px;
  color: var(--text-secondary);
  width: 20px;
  text-align: center;
  flex-shrink: 0;
}

.lb-zone { font-weight: 700; font-size: 14px; flex: 1; }
.lb-price { font-size: 12px; color: var(--text-secondary); }
.lb-likes { font-size: 13px; color: var(--like-red); margin-left: auto; }

/* Active state — Zone Info Card (structure; detailed styles in Phase 4) */
.zone-card-band {
  height: 6px;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  margin: -16px -16px 12px;
}

.zone-card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 12px;
}

.zone-card-code {
  font-family: var(--font-latin);
  font-size: 26px;
  font-weight: 700;
  color: var(--text-primary);
}

.zone-card-meta {
  font-size: 13px;
  color: var(--text-secondary);
  margin-top: 2px;
}

.zone-card-divider {
  height: 0;
  border-top: 1px solid var(--border);
  margin: 12px 0;
}

/* Like button */
.like-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 52px;
  height: 52px;
  border-radius: var(--radius-full);
  background: var(--bg-elevated);
  border: 1.5px solid rgba(var(--surface-rgb), 0.1);
  cursor: pointer;
  color: var(--zone-color, var(--text-secondary));
  justify-content: center;
  transition: background 0.15s, border-color 0.15s;
  flex-shrink: 0;
}
@media (hover: hover) { .like-btn:hover { background: rgba(var(--surface-rgb), 0.08); } }
.like-btn:disabled { opacity: 0.6; cursor: default; }

.like-icon { display: flex; align-items: center; justify-content: center; }
.like-icon svg {
  fill: none;
  stroke: var(--zone-color, currentColor);
  transition: fill 0.15s;
}
.like-btn.liked .like-icon svg {
  fill: var(--zone-color, var(--like-red));
}

.like-btn-count {
  font-family: var(--font-thai);
  font-size: 11px;
  color: var(--zone-color, var(--like-red));
  line-height: 1;
  margin-top: -2px;
  font-weight: 600;
}

/* ─── [D] Sticky Bottom Bar ─────────────────────────────────────────────── */
#bottom-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  /* Safe-area aware (viewport-fit=cover). Fill to the physical bottom; content
     stays --bottom-h tall above the home indicator. No --inapp-bottom
     (2026-09-23) — flush in X in-app; may sit under the app bar. */
  height: calc(var(--bottom-h) + var(--safe-bottom));
  padding-bottom: var(--safe-bottom);
  padding-left: var(--safe-left);
  padding-right: var(--safe-right);
  background: var(--bottom-bg);
  border-top: 1px solid var(--border);
  z-index: 100;
}

.bottom-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 0 24px;
  gap: 0;
}

.bottom-sep {
  width: 1px;
  height: 32px;
  background: var(--border);
  flex-shrink: 0;
  margin: 0 16px;
}

/* Event summary */
.bottom-event {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex-shrink: 0;
}

.bottom-artist {
  font-family: var(--font-latin);
  font-size: 12px;
  font-weight: 700;
  color: rgba(var(--accent-teal-rgb),0.9);
  letter-spacing: 0.5px;
}

.bottom-concert-name {
  font-family: var(--font-latin);
  font-size: 8px;
  font-weight: 400;
  color: rgba(234, 240, 251, 0.38);
  letter-spacing: 0.3px;
}

.bottom-details {
  font-family: var(--font-latin);
  font-size: 7px;
  font-weight: 400;
  color: rgba(234, 240, 251, 0.25);
  letter-spacing: 0.2px;
}

/* Countdown label */
.bottom-countdown-block {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}


.bottom-countdown-label {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.bottom-countdown-label span:first-child {
  font-size: 15px;
  font-weight: 400;
  color: var(--text-primary);
}

.bottom-countdown-sub {
  font-size: 13px;
  color: var(--text-secondary);
}

/* Countdown digits */
.countdown-digits {
  display: flex;
  align-items: center;
  gap: 4px;
}

.cd-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 40px;
  background: var(--bg-elevated);
  border-radius: var(--radius-xs);
  gap: 0;
}

.cd-num {
  font-family: var(--font-latin);
  font-size: 26px;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1;
}

.cd-unit {
  font-size: 10px;
  color: var(--text-secondary);
  line-height: 1;
  margin-top: 1px;
}

.cd-colon {
  font-size: 20px;
  font-weight: 700;
  color: var(--text-secondary);
  margin-bottom: 8px;
}

/* CTA button (bottom bar — teal style, NOT gold) */
.btn-buy-bottom {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 176px;
  height: 44px;
  background: rgba(var(--accent-teal-rgb),0.12);
  border: 1px solid rgba(var(--accent-teal-rgb),0.4);
  border-radius: var(--radius-md);
  color: var(--accent-teal-text);
  font-family: var(--font-thai);
  font-size: 15px;
  font-weight: 600;
  flex-shrink: 0;
  transition: background 0.15s;
}
@media (hover: hover) { .btn-buy-bottom:hover { background: rgba(var(--accent-teal-rgb),0.20); } }

/* Sale info text */
.bottom-sale-text {
  font-size: 14px;
  color: var(--accent-gold-text);
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
/* Darker gold for this plain-text CTA (2026-08-08 fix, revised same day —
   see p/nav.css's .ppw-nav__brand-tag for the full story). First pass
   pushed to strict WCAG 4.5:1 (#814908), inconsistent with this whole
   palette's established 3.2-3.5:1 floor (LIGHT_MODE_COLOR_BIBLE.md §5) and
   read as "หม่น อึมครึม" (dull/muddy) — corrected to #9C5809, back on the
   same target as everything else (~3.5:1 here). --accent-gold alone
   measured 2.69:1 on this CTA, still an improvement over that. */
:root[data-theme="light"] .bottom-sale-text { color: var(--accent-gold-text); }
/* Phase chip (spec item 5) — plain text: two lines on desktop (main over
   sub, owner 2026-10-17), one line on phones (see the 767px block). */
.bottom-sale-text.sale-chip {
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
}
.sale-chip .sale-sub[hidden] { display: none; }
.sale-main {
  font-weight: 600;
  white-space: nowrap;
}
.sale-sub {
  font-size: 12px;
  font-weight: 400;
  white-space: nowrap;
}

/* ─── Zone Info Card ─────────────────────────────────────────────────────── */
.zone-card {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.card-price-section,
.card-benefits-section,
.card-visibility-section { margin-top: 4px; }

.card-actions { margin-top: 4px; padding-bottom: 4px; }

.card-section-label {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 8px;
}

/* Price section */
.price-main {
  font-family: var(--font-latin);
  font-size: 29px;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.2;
  margin-bottom: 8px;
}

.price-currency {
  font-size: 18px;
  font-weight: 400;
}

.fee-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 14px;
  color: var(--text-secondary);
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  background: rgba(var(--surface-rgb), 0.04);
  margin-bottom: 4px;
}

.fee-row-protect {
  background: rgba(var(--surface-rgb), 0.04);
  color: var(--text-primary);
  border: 1px solid var(--border);
}

/* Level 3 multi-price rows */
.price-rows { display: flex; flex-direction: column; gap: 4px; margin-bottom: 6px; }

.price-row {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: rgba(var(--surface-rgb), 0.04);
  border-radius: var(--radius-sm);
}

.price-row-left { display: flex; flex-direction: column; gap: 2px; }
.price-row-price { font-size: 17px; font-weight: 700; }
.price-row-label { font-size: 12px; color: var(--text-secondary); }
.price-row-fees  { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; font-size: 13px; color: var(--text-secondary); flex-shrink: 0; }
.price-row-fees-label { font-size: 11px; color: var(--text-secondary); text-align: right; }
.price-row .fee-total-val { font-size: 14px; font-weight: 700; color: var(--text-primary); }

.price-fee-note {
  font-size: 11px;
  color: var(--text-secondary);
  margin-top: 4px;
  text-align: right;
}

/* Fan Benefits */
.benefit-list { display: flex; flex-direction: column; gap: 4px; }

.benefit-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 14px;
}

.benefit-icon {
  font-size: 13px;
  width: 16px;
  text-align: center;
  flex-shrink: 0;
  margin-top: 1px;
}

.benefit-yes .benefit-icon { color: var(--success); }
.benefit-no { opacity: 0.4; }
.benefit-no  .benefit-icon { color: var(--text-secondary); }
.benefit-no  .benefit-name  { color: var(--text-secondary); }

.benefit-text { display: flex; flex-direction: column; gap: 1px; }
.benefit-name { font-size: 14px; line-height: 1.3; }
.benefit-random {
  font-size: 12px;
  color: var(--text-secondary);
  font-style: italic;
}

.benefit-tier-note {
  font-size: 12px;
  color: var(--text-secondary);
  font-weight: 400;
}

.benefit-footnote {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: 8px;
  line-height: 1.4;
  padding: 6px 8px;
  background: rgba(var(--surface-rgb), 0.03);
  border-radius: var(--radius-xs);
  border-left: 2px solid rgba(var(--surface-rgb), 0.12);
}

/* Visibility section */
.visibility-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.visibility-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: var(--radius-xl);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  flex-shrink: 0;
}

.visibility-detail {
  font-size: 14px;
  color: var(--text-secondary);
  line-height: 1.4;
}

/* Fee total value (larger + bolder) */
.fee-total-val {
  font-family: var(--font-latin);
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
}
.fee-row-protect .fee-total-val { color: var(--accent-gold-text); }   /* gold as plain text on a light panel measured 2.66:1 (2026-08-27) */

/* Action buttons */
.card-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.card-actions-row {
  display: flex;
  gap: 8px;
}
.card-actions-row > * {
  flex: 1;
}
.card-actions-social {
  display: flex;
  gap: 8px;
}
.card-actions-social > * {
  flex: 1;
}

.btn-card {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  font-family: var(--font-thai);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s;
  border: none;
  white-space: nowrap;
}
@media (hover: hover) { .btn-card:hover { opacity: 0.8; } }

.btn-view {
  background: rgba(var(--surface-rgb), 0.08);
  color: var(--text-primary);
  border: 1px solid var(--border);
  min-width: 130px;
}

.btn-save {
  background: var(--accent-gold);
  color: var(--gold-btn-text);
  min-width: 140px;
}
.btn-save:disabled { opacity: 0.6; cursor: default; }
/* Keeps dark mode's vivid gold + dark text in light mode too (2026-08-08 ask)
   — solid fill + in-box text has self-contained contrast, independent of
   the page background, so light mode's muted gold isn't needed here. */
:root[data-theme="light"] .btn-save { background: var(--brand-gold); color: var(--brand-gold-ink); }

/* Podium + leaderboard like count — use zone color via inline style */
.podium-likes {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
}
.lb-likes {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
  margin-left: auto;
}

/* Zone card stub (Phase 3 placeholder) */
.zone-card-stub {
  padding: 8px 0;
}

/* Leaderboard section label */
.lb-section-label {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin: 10px 0 6px;
}

/* Countdown concert day */
.cd-concert-day {
  font-size: 22px;
  font-weight: 700;
  color: var(--accent-teal);
}

/* Toast */
.toast {
  position: fixed;
  bottom: calc(var(--bottom-h) + 16px + var(--safe-bottom));
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--bg-elevated);
  color: var(--text-primary);
  padding: 10px 20px;
  border-radius: var(--radius-pill);
  font-size: 15px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s, transform 0.2s;
  z-index: 200;
  border: 1px solid var(--border);
  white-space: nowrap;
}

.toast.toast-show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ─── Utilities ──────────────────────────────────────────────────────────── */
.hidden { display: none !important; }

/* ─── Responsive: Tablet 768–1023px ─────────────────────────────────────── */
@media (max-width: 1023px) {
  .hero-title { font-size: 38px; }
  .hero-subtitle { font-size: 18px; }

  #seat-section {
    flex-direction: column;
  }

  .seat-col-divider { width: 100%; height: 0; border-left: none; border-top: 1px solid var(--border); }

  #map-col { padding: 12px; }

  #panel-col { min-height: 400px; }
}

/* ─── Responsive: Mobile <768px ──────────────────────────────────────────── */
@media (max-width: 767px) {
  /* Navbar mobile sizing is handled by nav.css itself (shared with every
     /p page) — no page-specific overrides needed here anymore. */

  /* Hero: poster visible on mobile but smaller */
  .hero-poster { width: 120px; height: auto; }
  .hero-title { font-size: 36px; }

  /* Price chips: wrap to next line on narrow screens */
  .price-chips {
    flex-wrap: wrap;
  }

  /* Bottom bar: floating card on mobile */
  #bottom-bar {
    height: auto;
    /* Floating card — 8px + --safe-bottom; no --inapp-bottom (2026-09-23). */
    padding-bottom: 0;
    padding-left: 0;
    padding-right: 0;
    bottom: calc(8px + var(--safe-bottom));
    left: calc(8px + var(--safe-left));
    right: calc(8px + var(--safe-right));
    width: auto;
    border-radius: var(--radius-md);
    border: 1px solid rgba(var(--surface-rgb), 0.12);
  }
  .bottom-inner {
    flex-wrap: wrap;
    height: auto;
    padding: 8px 16px;
    gap: 8px;
  }
  /* Whole countdown scales with its row width (cqi) instead of clipping on
     narrow phones; clamp() caps every size at its desktop value. */
  .bottom-countdown-block {
    flex-wrap: nowrap;
    justify-content: center;
    width: 100%;
    container-type: inline-size;
    gap: clamp(4px, 2.4cqi, 12px);
  }
  .bottom-countdown-block .bottom-countdown-label { flex-shrink: 0; }
  .bottom-countdown-label span:first-child { font-size: clamp(11px, 4.4cqi, 15px); }
  .bottom-countdown-sub { font-size: clamp(9px, 3.6cqi, 13px); }
  .bottom-countdown-block .countdown-digits { gap: clamp(2px, 1cqi, 4px); min-width: 0; }
  .bottom-countdown-block .cd-box { width: clamp(36px, 14.5cqi, 52px); height: clamp(30px, 11.5cqi, 40px); }
  .bottom-countdown-block .cd-num { font-size: clamp(17px, 7.4cqi, 26px); }
  .bottom-countdown-block .cd-unit { font-size: clamp(8px, 2.9cqi, 10px); }
  .bottom-countdown-block .cd-colon { font-size: clamp(14px, 5.6cqi, 20px); margin-bottom: clamp(5px, 2.2cqi, 8px); }
  .bottom-sep { display: none; }
  .bottom-sale-text {
    font-size: 12px;
    flex-direction: row;
    align-items: baseline;
    justify-content: center;
    gap: 4px;
    width: 100%;
  }
  /* Phone keeps the chip on one line (overrides the desktop 2-line rule). */
  .bottom-sale-text.sale-chip { flex-direction: row; align-items: baseline; gap: 6px; }

  .countdown-digits { justify-content: center; }

  /* Zone panel: stacks below map, normal flow */
  #panel-col {
    min-height: 400px;
    padding-bottom: 96px;
  }
}

/* ── Prayer Button ─────────────────────────────────────────────────── */
.btn-prayer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 11px 16px;
  background: rgba(var(--accent-teal-rgb),0.12);
  color: var(--accent-teal-text);
  border: 1px solid rgba(var(--accent-teal-rgb),0.6);
  border-radius: var(--radius-md);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s, box-shadow 0.2s;
  box-shadow: 0 0 10px rgba(var(--accent-teal-rgb),0.25);
}
@media (hover: hover) { .btn-prayer:hover { background: rgba(var(--accent-teal-rgb),0.2);
  box-shadow: 0 0 18px rgba(var(--accent-teal-rgb),0.45); } }

/* ── Prayer Modal ──────────────────────────────────────────────────── */
#prayer-modal {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  align-items: center;
  justify-content: center;
  /* Safe-area padding (2026-08-22) — the scrim is inset:0 so it now covers
     the status bar and home indicator too; padding it keeps the CARD inside
     the safe area without touching any of the card's own vh-based max-heights. */
  padding: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left);
}
#prayer-modal.is-open {
  display: flex;
  animation: prayer-fade-in 0.2s ease;
}
@keyframes prayer-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.prayer-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(var(--black-rgb), 0.88);
  backdrop-filter: blur(4px);
}

.prayer-card {
  position: relative;
  z-index: 1;
  width: 520px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - 64px);
  display: flex;
  flex-direction: column;
  background: radial-gradient(ellipse at 50% 0%, var(--bg-elevated) 0%, var(--bg-primary) 100%);
  border-radius: var(--radius-2xl);
  overflow: hidden;
  box-shadow:
    0 0 0 1.5px var(--accent-gold),
    0 0 40px rgba(var(--accent-gold-rgb),0.22),
    0 0 60px rgba(var(--accent-teal-rgb),0.12);
  animation: prayer-card-in 0.25s ease;
}
@keyframes prayer-card-in {
  from { transform: scale(0.96); opacity: 0; }
  to   { transform: scale(1);    opacity: 1; }
}

.prayer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 24px;
  background: var(--bg-secondary);
  border-bottom: 1px solid rgba(var(--accent-gold-rgb),0.25);
  flex-shrink: 0;
}
.prayer-header-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
  text-shadow: 0 0 10px rgba(var(--accent-gold-rgb), calc(0.5 * var(--glow-mult)));
}
.prayer-close {
  background: rgba(var(--surface-rgb),0.08);
  border: none;
  color: rgba(var(--surface-rgb),0.55);
  font-size: 15px;
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
@media (hover: hover) { .prayer-close:hover { background: rgba(var(--surface-rgb),0.15);
  color: var(--text-primary); } }

.prayer-body {
  padding: 20px 24px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-height: 0;
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--accent-violet-rgb), 0.4) transparent;
}
.prayer-body::-webkit-scrollbar {
  width: 5px;
}
.prayer-body::-webkit-scrollbar-track {
  background: transparent;
}
.prayer-body::-webkit-scrollbar-thumb {
  background: rgba(var(--accent-violet-rgb), 0.4);
  border-radius: var(--radius-xs);
}
.prayer-intro {
  font-size: 14px;
  color: rgba(var(--surface-rgb),0.75);
  line-height: 1.6;
  margin: 0;
}
.prayer-intro strong {
  color: var(--text-primary);
}
.prayer-direction {
  font-size: 13px;
  color: var(--text-secondary);
  margin: 0;
  line-height: 1.5;
}
.prayer-meditation {
  font-size: 13px;
  color: var(--text-secondary);
  margin: 0;
}
.prayer-closing {
  font-size: 15px;
  font-weight: 600;
  color: var(--accent-gold-text);
  text-align: center;
  margin: 4px 0 0;
}

.prayer-chant {
  margin: 0;
  padding: 14px 16px 14px 18px;
  background: rgba(var(--accent-gold-rgb),0.07);
  border-left: 3px solid var(--accent-gold);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  box-shadow: inset 0 0 12px rgba(var(--accent-gold-rgb),0.08);
}
.prayer-chant-note {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: rgba(var(--accent-gold-rgb),0.8);
  margin-bottom: 8px;
}
.prayer-chant p {
  margin: 0 0 6px;
  font-size: 14px;
  color: rgba(var(--surface-rgb),0.93);
  line-height: 1.5;
}
.prayer-chant p:last-child { margin-bottom: 0; }

.prayer-declaration {
  margin: 0;
  padding: 14px 16px 14px 18px;
  background: rgba(var(--accent-teal-rgb),0.07);
  border-left: 3px solid var(--accent-teal);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  box-shadow: inset 0 0 14px rgba(var(--accent-teal-rgb),0.08);
}
.prayer-declaration p {
  margin: 0;
  font-size: 14px;
  color: rgba(var(--surface-rgb),0.92);
  line-height: 1.5;
}
.prayer-zone-highlight {
  color: var(--accent-teal);
  font-weight: 700;
}

.prayer-footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 12px 24px;
  background: var(--bg-secondary);
  border-top: 1px solid rgba(var(--accent-gold-rgb),0.12);
  flex-shrink: 0;
}
.prayer-footer-divider {
  color: rgba(var(--accent-gold-rgb),0.6);
  font-size: 12px;
}
.prayer-footer-note {
  font-size: 12px;
  color: var(--text-secondary);
}

@media (max-width: 600px) {
  .prayer-card {
    max-height: 90vh;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    align-self: flex-end;
    width: 100%;
    max-width: 100%;
    animation: prayer-slide-up 0.3s ease;
  }
  #prayer-modal.is-open {
    align-items: flex-end;
  }
  @keyframes prayer-slide-up {
    from { transform: translateY(100%); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
  }
}

.prayer-placeholder {
  color: var(--accent-teal);
}
.prayer-slash {
  color: rgba(var(--surface-rgb),0.3);
}
.prayer-bold-white {
  color: var(--text-primary);
  font-weight: 700;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Concert Guide Modal
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── CSS variables ── */
:root {
  /* Theme tokens, not literals (2026-10-22) — follows dark/light and any re-theme. */
  --guide-modal-bg:  var(--bg-elevated);
  --guide-header-bg: var(--bg-secondary);
  --guide-divider:   rgba(var(--surface-rgb), 0.10);
}

/* ── Modal backdrop ── */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1100;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Safe-area padding (2026-08-22) — the scrim is inset:0 so it now covers
     the status bar and home indicator too; padding it keeps the CARD inside
     the safe area without touching any of the card's own vh-based max-heights. */
  padding: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left);
  background: rgba(var(--black-rgb), 0.88);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.modal-backdrop[hidden] {
  display: none;
}

/* ── Modal card ── */
.guide-modal-card {
  position: relative;
  width: 820px;
  max-width: 95vw;
  max-height: calc(100vh - 48px);
  display: flex;
  flex-direction: column;
  background: var(--guide-modal-bg);
  border-radius: var(--radius-2xl);
  overflow: hidden;
  box-shadow:
    0 0 0 1.5px rgba(var(--accent-violet-rgb), 0.55),
    0 0 48px rgba(var(--accent-violet-rgb), 0.18),
    0 8px 40px rgba(var(--black-rgb), 0.55);
  animation: guide-card-in 0.22s ease;
}
@keyframes guide-card-in {
  from { transform: scale(0.96); opacity: 0; }
  to   { transform: scale(1);    opacity: 1; }
}

/* ── Header ── */
.guide-modal-header {
  height: 56px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px 0 18px;
  background: var(--guide-header-bg);
  border-bottom: 1px solid var(--guide-divider);
}

.guide-modal-title-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.guide-teal-dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--accent-teal);
  box-shadow: 0 0 8px rgba(var(--accent-teal-rgb),0.7);
  flex-shrink: 0;
}

.guide-modal-title-text {
  font-size: 13px;
  font-weight: 700;
  color: rgba(var(--surface-rgb),0.85);
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.guide-close-btn {
  background: rgba(var(--surface-rgb),0.08);
  border: none;
  color: rgba(var(--surface-rgb),0.55);
  font-size: 14px;
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.15s, color 0.15s;
}
@media (hover: hover) { .guide-close-btn:hover { background: rgba(var(--surface-rgb),0.16);
  color: var(--text-primary); } }

/* ── Tab bar ── */
.guide-tab-bar {
  height: 68px;
  flex-shrink: 0;
  display: flex;
  align-items: stretch;
  background: var(--guide-header-bg);
  border-bottom: 1px solid var(--guide-divider);
}

.guide-tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  padding: 8px 4px;
  transition: border-color 0.15s, background 0.15s;
}
@media (hover: hover) { .guide-tab:hover { background: rgba(var(--surface-rgb),0.04); } }

.guide-tab-icon {
  font-size: 22px;
  display: block;
  text-align: center;
  line-height: 1;
}
.guide-tab-label {
  font-size: 10px;
  font-weight: 500;
  font-family: var(--font-thai);
  text-align: center;
  color: var(--text-secondary);
  white-space: nowrap;
  transition: color 0.15s;
}

.guide-tab.active {
  border-bottom-color: var(--accent-teal);
}
.guide-tab.active .guide-tab-label {
  color: var(--accent-teal);
}

/* ── Content area ── */
.guide-content {
  height: 460px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 20px 24px;
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--accent-violet-rgb), 0.4) transparent;
}
.guide-content::-webkit-scrollbar {
  width: 5px;
}
.guide-content::-webkit-scrollbar-track {
  background: transparent;
}
.guide-content::-webkit-scrollbar-thumb {
  background: rgba(var(--accent-violet-rgb), 0.4);
  border-radius: var(--radius-xs);
}

/* ── Footer ── */
.guide-modal-footer {
  height: 42px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
  background: var(--guide-header-bg);
  border-top: 1px solid var(--guide-divider);
}

.guide-footer-hint {
  font-size: 12px;
  color: rgba(var(--surface-rgb),0.3);
}

.guide-dots {
  display: flex;
  align-items: center;
  gap: 5px;
}

.guide-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: rgba(var(--surface-rgb),0.2);
  transition: background 0.2s, transform 0.2s;
}
.guide-dot.active {
  background: var(--accent-teal);
  transform: scale(1.25);
}
:root[data-theme="light"] .guide-dot.active { background: var(--brand-teal); }

/* ── Guide content shared ── */
.guide-section-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--accent-teal);
  letter-spacing: 0.04em;
  margin-bottom: 16px;
}
.guide-subsection-title {
  font-size: 12px;
  font-weight: 700;
  color: rgba(var(--surface-rgb),0.45);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 20px 0 10px;
}
.guide-placeholder {
  font-size: 14px;
  color: rgba(var(--surface-rgb),0.35);
  padding: 12px 0;
}

/* ── Timeline (Tab 1: schedule) ── */
.guide-timeline {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.guide-tl-item {
  display: grid;
  grid-template-columns: 14px 2px 1fr;
  column-gap: 12px;
  position: relative;
  padding-bottom: 18px;
}
.guide-tl-item:last-child { padding-bottom: 0; }

.guide-tl-dot {
  width: 10px;
  height: 10px;
  border-radius: var(--radius-full);
  background: rgba(var(--surface-rgb),0.2);
  border: 2px solid rgba(var(--surface-rgb),0.25);
  margin-top: 3px;
  grid-column: 1;
  align-self: start;
  justify-self: center;
}
.guide-tl-highlight .guide-tl-dot {
  background: var(--accent-teal);
  border-color: var(--accent-teal);
  box-shadow: 0 0 8px rgba(var(--accent-teal-rgb),0.6);
}
:root[data-theme="light"] .guide-tl-highlight .guide-tl-dot { background: var(--brand-teal); border-color: var(--brand-teal); }

.guide-tl-line {
  grid-column: 2;
  grid-row: 1 / span 2;
  width: 2px;
  background: rgba(var(--surface-rgb),0.08);
  justify-self: center;
  margin-top: 14px;
}

.guide-tl-body {
  grid-column: 3;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.guide-tl-date {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent-gold-text);
  letter-spacing: 0.03em;
}
.date-update-chip {
  display: inline-block;
  margin-left: 6px;
  padding: 1.5px 6px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--accent-gold-text);
  border: 1px solid rgba(var(--accent-gold-rgb),0.5);
  border-radius: var(--radius-pill);
  vertical-align: middle;
}
.guide-tl-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.4;
}
.guide-tl-highlight .guide-tl-label {
  color: var(--accent-teal);
}
.guide-tl-sub {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.4;
}
.guide-tl-dday-label {
  color: var(--accent-gold-text) !important;
  font-size: 15.3px;
}
.guide-tl-dday-item .guide-tl-date {
  color: var(--accent-teal) !important;
}
.guide-tl-dday-item .guide-tl-dot {
  background: var(--accent-gold);
  border-color: var(--accent-gold);
  box-shadow: 0 0 8px rgba(var(--accent-gold-rgb),0.7);
}
:root[data-theme="light"] .guide-tl-dday-item .guide-tl-dot { background: var(--brand-gold); border-color: var(--brand-gold); }
.guide-tl-past {
  opacity: 0.4;
}

/* ── Rule list (Tab 2 & 3) ── */
.guide-rule-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 4px;
}
.guide-rule-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 14px;
  background: rgba(var(--surface-rgb),0.04);
  border-radius: var(--radius-md);
  border: 1px solid var(--guide-divider);
}
.guide-rule-item.guide-rule-important {
  border-color: rgba(var(--accent-gold-rgb),0.3);
  background: rgba(var(--accent-gold-rgb),0.06);
}
.guide-rule-item.guide-rule-teal {
  border-color: rgba(var(--accent-teal-rgb),0.3);
  background: rgba(var(--accent-teal-rgb),0.06);
}
.guide-rule-icon {
  font-size: 16px;
  flex-shrink: 0;
  margin-top: 1px;
}
.guide-rule-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.45;
}
.guide-rule-sub {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.5;
  margin-top: 2px;
}

/* ── Live date highlight grid ── */
.live-date-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 16px; }
.live-date-card { padding: 13px 14px; border: 1px solid var(--guide-divider); border-radius: var(--radius-lg); display: flex; flex-direction: column; gap: 3px; }
.live-date-card.live-date-teal { border-color: rgba(var(--accent-teal-rgb),0.35); background: rgba(var(--accent-teal-rgb),0.07); }
.live-date-card.live-date-gold { border-color: rgba(var(--accent-gold-rgb),0.35); background: rgba(var(--accent-gold-rgb),0.07); }
.live-date-icon { font-size: 18px; margin-bottom: 4px; }
.live-date-label { font-size: 11px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.05em; }
.live-date-value { font-size: 14px; font-weight: 700; color: var(--text-primary); }
.live-date-sub { font-size: 11.5px; color: var(--text-secondary); margin-top: 2px; line-height: 1.4; }

/* ── Channel cards (Tab 2) ── */
.guide-channel-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 4px;
}
.guide-channel-card {
  padding: 12px 14px;
  background: rgba(var(--surface-rgb),0.04);
  border: 1px solid var(--guide-divider);
  border-radius: var(--radius-md);
}
.guide-channel-card.guide-channel-highlight {
  border-color: rgba(var(--accent-violet-rgb),0.4);
  background: rgba(var(--accent-violet-rgb),0.07);
}
.guide-channel-badge {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--accent-gold-text);
  margin-bottom: 4px;
  text-transform: uppercase;
}
.guide-channel-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 3px;
}
.guide-channel-name-note {
  font-size: 13px;
  font-weight: 400;
}
.guide-channel-sub {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.4;
}

/* ── Fee note & price table (Tab 2) ── */
.guide-fee-note {
  font-size: 12px;
  color: var(--text-secondary);
  margin-bottom: 10px;
  line-height: 1.5;
}
.guide-table-wrap {
  overflow-x: auto;
  border-radius: var(--radius-md);
  border: 1px solid var(--guide-divider);
}
.guide-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}
.guide-table th {
  padding: 8px 10px;
  background: rgba(var(--surface-rgb),0.06);
  color: rgba(var(--surface-rgb),0.5);
  font-weight: 600;
  text-align: left;
  white-space: nowrap;
  border-bottom: 1px solid var(--guide-divider);
}
.guide-table td {
  padding: 7px 10px;
  color: rgba(var(--surface-rgb),0.85);
  border-bottom: 1px solid rgba(var(--surface-rgb),0.04);
  vertical-align: middle;
}
.guide-table tr:last-child td { border-bottom: none; }
@media (hover: hover) { .guide-table tr:hover td { background: rgba(var(--surface-rgb),0.03); } }
.guide-price-cell {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.guide-tier-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  margin-right: 6px;
  vertical-align: middle;
  flex-shrink: 0;
}

/* ── Info box (Tab 3) ── */
.guide-info-box {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-top: 16px;
  padding: 12px 14px;
  background: rgba(var(--accent-teal-rgb),0.07);
  border: 1px solid rgba(var(--accent-teal-rgb),0.2);
  border-radius: var(--radius-md);
  font-size: 13px;
  color: rgba(var(--surface-rgb),0.8);
  line-height: 1.55;
}
.guide-info-icon {
  font-size: 16px;
  flex-shrink: 0;
}

/* Text-link button in the schedule timeline (opens the pickup helper). */
.guide-tl-link {
  align-self: flex-start;
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  cursor: pointer;
}
.guide-rule-link {
  display: inline-block;
  margin-top: 5px;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent-teal);
  text-decoration: none;
  transition: opacity 0.15s;
}
@media (hover: hover) { .guide-rule-link:hover { opacity: 0.75;
  text-decoration: underline; } }

/* ── Ticket rules grid (Tab 2) ── */
.ticket-rules-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 16px;
}
.ticket-rule-card {
  padding: 12px 13px;
  background: rgba(var(--surface-rgb),0.04);
  border: 1px solid var(--guide-divider);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ticket-rule-card.trcard-warn {
  border-color: rgba(var(--accent-gold-rgb),0.3);
  background: rgba(var(--accent-gold-rgb),0.06);
}
.ticket-rule-card.trcard-danger {
  border-color: rgba(255,80,80,0.25);
  background: rgba(255,80,80,0.05);
  flex-direction: row;
  align-items: center;
  gap: 8px;
}
.ticket-rule-card.trcard-full {
  grid-column: 1 / -1;
}
.trcard-icon {
  font-size: 18px;
  line-height: 1;
  margin-bottom: 2px;
  flex-shrink: 0;
}
.trcard-label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.4;
}
.trcard-sub {
  font-size: 11.5px;
  color: var(--text-secondary);
  line-height: 1.45;
}
.trcard-bullets {
  margin: 3px 0 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.trcard-bullets li {
  font-size: 11.5px;
  color: var(--text-secondary);
  line-height: 1.45;
  padding-left: 12px;
  position: relative;
}
.trcard-bullets li::before {
  content: '·';
  position: absolute;
  left: 0;
  color: var(--text-secondary);
  font-weight: 700;
}

/* ── Payment chips (Tab 2) ── */
.payment-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-bottom: 10px;
}
.payment-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px;
  background: rgba(var(--surface-rgb),0.05);
  border: 1px solid var(--guide-divider);
  border-radius: var(--radius-4xl);
  font-size: 12px;
  color: rgba(var(--surface-rgb),0.8);
  white-space: nowrap;
}
.payment-chip.payment-chip-highlight {
  border-color: rgba(var(--accent-gold-rgb),0.35);
  background: rgba(var(--accent-gold-rgb),0.08);
  color: var(--accent-gold-text);
}

/* ── Payment warning grid ── */
.payment-warn-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 4px; }
.payment-warn-card { padding: 12px 13px; background: rgba(var(--surface-rgb),0.04); border: 1px solid var(--guide-divider); border-radius: var(--radius-md); display: flex; flex-direction: column; gap: 7px; }
.payment-warn-card.payment-warn-teal { border-color: rgba(var(--accent-teal-rgb),0.3); background: rgba(var(--accent-teal-rgb),0.06); }
.payment-warn-card.payment-warn-danger { border-color: rgba(239,68,68,0.4); background: rgba(239,68,68,0.07); }
.payment-warn-card.payment-warn-full { grid-column: 1 / -1; }
.payment-warn-top { display: flex; align-items: center; gap: 7px; }
.payment-warn-icon { font-size: 16px; flex-shrink: 0; }
.payment-warn-label { font-size: 12.5px; font-weight: 700; color: var(--text-primary); line-height: 1.35; }

/* ── Queue tips (Tab 2) ── */
.queue-tips-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 4px; }
.queue-tip-card { padding: 12px 13px; background: rgba(var(--surface-rgb),0.04); border: 1px solid var(--guide-divider); border-radius: var(--radius-md); display: flex; flex-direction: column; gap: 6px; }
.queue-tip-card.queue-tip-card-warn { border-color: rgba(var(--accent-gold-rgb),0.3); background: rgba(var(--accent-gold-rgb),0.06); }
.queue-tip-icon { font-size: 18px; }
.queue-tip-label { font-size: 12.5px; font-weight: 700; color: var(--text-primary); line-height: 1.35; }

/* ── Login grid (Tab 2) ── */
.login-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 4px;
}
.login-card {
  padding: 14px 13px;
  border-radius: var(--radius-md);
  border: 1px solid var(--guide-divider);
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.login-card-tip {
  border-color: rgba(var(--accent-gold-rgb),0.35);
  background: rgba(var(--accent-gold-rgb),0.07);
}
.login-card-fix {
  background: rgba(var(--surface-rgb),0.04);
}
.login-card-icon {
  font-size: 20px;
  line-height: 1;
}
.login-card-label {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.35;
}
.login-card-sub {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.6;
}
.login-fix-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-teal-rgb),0.2);
  color: var(--accent-teal-text);
  font-size: 10px;
  font-weight: 700;
  flex-shrink: 0;
  vertical-align: middle;
  margin-right: 2px;
}

/* ── Collect pick options (Tab 3) ── */
.collect-pick-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 14px;
}
.collect-pick-card {
  padding: 14px 14px;
  background: rgba(var(--surface-rgb),0.04);
  border: 1px solid var(--guide-divider);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.collect-pick-card.collect-pick-recommended {
  border-color: rgba(var(--accent-violet-rgb),0.4);
  background: rgba(var(--accent-violet-rgb),0.07);
}
.collect-pick-badge {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-teal-text);
  margin-bottom: 2px;
}
.collect-pick-badge.collect-pick-badge-neutral {
  color: var(--text-secondary);
}
.collect-pick-icon {
  font-size: 24px;
  line-height: 1;
  margin-bottom: 2px;
}
.collect-pick-title {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.35;
}
.collect-pick-date {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--accent-teal);
  margin-bottom: 2px;
}
.collect-pick-sub {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.55;
}

/* ── Ticket steps (Tab 2) ── */
.ticket-steps {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  margin-bottom: 10px;
}
.ticket-step {
  padding: 13px 12px;
  background: rgba(var(--surface-rgb),0.04);
  border: 1px solid var(--guide-divider);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  gap: 4px;
  position: relative;
}
.tstep-num {
  position: absolute;
  top: 10px;
  right: 11px;
  font-size: 12px;
  font-weight: 700;
  color: var(--accent-teal);
  opacity: 0.7;
}
.tstep-icon {
  font-size: 22px;
  line-height: 1;
  margin-bottom: 4px;
}
.tstep-label {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.35;
}
.tstep-sub {
  font-size: 11.5px;
  color: var(--text-secondary);
  line-height: 1.5;
}

/* ── Benefit table (Tab 4) ── */
.guide-ben-legend {
  display: flex;
  gap: 16px;
  font-size: 12px;
  color: var(--text-secondary);
  margin-bottom: 10px;
}
.guide-ben-table {
  font-size: 12px;
  min-width: 560px;
}
.guide-ben-tier-header,
.guide-ben-header {
  text-align: center;
  white-space: nowrap;
  padding: 8px 6px;
  font-size: 11px;
}
.guide-ben-tier-header { text-align: left; min-width: 90px; }
.guide-ben-tier-cell {
  white-space: nowrap;
  padding: 7px 10px;
  font-size: 12px;
  color: rgba(var(--surface-rgb),0.85);
}
.guide-ben-cell {
  text-align: center;
  padding: 7px 4px;
  font-size: 13px;
}
.guide-ben-yes  { color: var(--accent-teal); }
.guide-ben-no   { color: rgba(var(--surface-rgb),0.2); font-size: 14px; }
.guide-ben-rand { font-size: 12px; }
.guide-ben-n {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  color: var(--accent-gold-text);
  vertical-align: super;
  margin-left: 1px;
}
.guide-ben-sup {
  color: var(--accent-gold-text);
  font-size: 10px;
  margin-left: 1px;
}
.guide-ben-footnotes {
  margin-top: 10px;
}
.guide-ben-footnote-text {
  font-size: 12px;
  color: rgba(var(--surface-rgb),0.45);
  line-height: 1.5;
  margin-bottom: 4px;
}

/* ── Live perk badge (Tab 5) ── */
.guide-live-perk {
  margin-top: 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent-teal);
}

/* ── Responsive < 900px ── */
@media (max-width: 900px) {
  .guide-modal-card {
    width: 95vw;
  }
  .guide-modal-title-text {
    font-size: 11px;
  }
}

/* ── Responsive < 600px ── */
@media (max-width: 600px) {
  .guide-modal-card {
    max-height: 90vh;
    border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
    align-self: flex-end;
    width: 100%;
    max-width: 100%;
    animation: guide-slide-up 0.28s ease;
  }
  .modal-backdrop {
    align-items: flex-end;
  }
  @keyframes guide-slide-up {
    from { transform: translateY(100%); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
  }
  .guide-tab-label {
    font-size: 8px;
  }
  .guide-tab-icon {
    font-size: 18px;
  }
}

/* ─── Zone Seat Count + Seat View Button ─────────────────────────────────── */
.zone-seat-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  align-items: center;
  margin-bottom: 14px;
}

.zone-seat-count {
  display: flex;
  align-items: center;
  gap: 8px;
  background: rgba(var(--surface-rgb),0.04);
  border: 1px solid rgba(var(--surface-rgb),0.08);
  border-radius: var(--radius-md);
  padding: 8px 10px;
}
.seat-count-icon { font-size: 16px; flex-shrink: 0; }
.seat-count-body {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.seat-count-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.seat-count-num {
  font-family: var(--font-latin);
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1;
}

.btn-seat-view {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  height: 52px;
  padding: 0 12px;
  flex-shrink: 0;
  background: color-mix(in srgb, var(--zone-btn-color, var(--accent-teal)) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--zone-btn-color, var(--accent-teal)) 35%, transparent);
  border-radius: var(--radius-md);
  /* Two variables on purpose: the 10% wash and 35% border above are IDENTITY
     (theme-invariant tierColor), the label below is TEXT on this card's neutral
     surface and needs tierTextColor's light-mode variant — one variable driving
     both measured 1.14:1 in light mode. main.js sets both; the fallback chain
     keeps a caller that only sets --zone-btn-color working. */
  color: var(--zone-btn-text-color, var(--accent-teal));
  font-family: var(--font-thai);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s, border-color 0.15s;
}
@media (hover: hover) { .btn-seat-view:hover { background: color-mix(in srgb, var(--zone-btn-color, var(--accent-teal)) 20%, transparent);
  border-color: color-mix(in srgb, var(--zone-btn-color, var(--accent-teal)) 60%, transparent); } }

/* ─── Seat Summary Stats (above Most Liked Zones) ───────────────────────── */
.seat-summary-title {
  font-family: var(--font-latin);
  font-size: 18px;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 10px;
}
.seat-summary-hint {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
  margin: 0 0 14px;
}
.seat-summary-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 16px;
}
.seat-summary-card {
  display: flex;
  align-items: center;
  gap: 10px;
  background: rgba(var(--surface-rgb),0.04);
  border: 1px solid rgba(var(--surface-rgb),0.08);
  border-radius: var(--radius-lg);
  padding: 10px 12px;
}
.seat-summary-icon { font-size: 20px; flex-shrink: 0; }
.seat-summary-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.seat-summary-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.seat-summary-num {
  font-family: var(--font-latin);
  font-size: 17px;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1;
}

/* ─── Seat count in leaderboard rows ────────────────────────────────────── */
.lb-seat-count {
  font-size: 12px;
  color: var(--text-secondary);
  margin-left: auto;
  margin-right: 4px;
  white-space: nowrap;
}
.podium-seat-count {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: 2px;
}

/* Seat View Lightbox base + zone-view photos: zone-view.css (shared with /p/find, 2026-10-26). */
#lightbox-label {
  font-size: 15px;
  color: var(--text-secondary);
  margin: 0;
}
/* --- Zone Card Divider --- */
.zone-card-divider {
  height: 0;
  border-top: 1px solid rgba(var(--surface-rgb),0.08);
  margin: 14px 0;
}

/* --- Seat Rows Collapsible --- */
.seat-rows-detail {
  margin-top: 10px;
}
.seat-rows-summary {
  font-size: 13px;
  font-weight: 600;
  color: inherit;
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 0;
  user-select: none;
}
.seat-rows-summary::-webkit-details-marker { display: none; }
.seat-rows-summary::before {
  content: '▶';
  font-size: 10px;
  transition: transform 0.2s;
}
.seat-rows-detail[open] > .seat-rows-summary::before {
  transform: rotate(90deg);
}
.seat-rows-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px 0;
  margin-top: 8px;
  padding: 10px 4px;
  background: rgba(var(--surface-rgb),0.04);
  border-radius: var(--radius-md);
}
.seat-rows-grid .seat-row-item {
  padding: 3px 10px;
}
.seat-rows-grid .seat-row-item:nth-child(3n+2),
.seat-rows-grid .seat-row-item:nth-child(3n) {
  border-left: 1px solid rgba(var(--surface-rgb),0.1);
}
.seat-row-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 3px 0;
}
.seat-row-name {
  font-size: 12px;
  color: var(--text-secondary);
}
.seat-row-num {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-primary);
}
.seat-row-unit {
  font-size: 10px;
  font-weight: 400;
  color: var(--text-secondary);
}

/* --- Seat Summary total card highlight --- */
.seat-summary-card--total {
  background: linear-gradient(135deg, rgba(var(--accent-gold-rgb),0.12) 0%, rgba(var(--accent-gold-rgb),0.04) 100%);
  border-color: rgba(var(--accent-gold-rgb),0.4);
  position: relative;
  overflow: hidden;
}
.seat-summary-card--total::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(135deg, rgba(var(--accent-gold-rgb),0.08), transparent 60%);
  pointer-events: none;
}
.seat-summary-card--total .seat-summary-label {
  color: var(--accent-gold-text);
}
.seat-summary-card--total .seat-summary-num {
  color: var(--accent-gold-text);
}
/* 2026-08-08 fix — same accent-gold-as-plain-text issue as .ppw-nav__brand-tag/
   .bottom-sale-text (measured 2.89:1), same established value, not a new
   derivation. */
:root[data-theme="light"] .seat-summary-card--total .seat-summary-label,
:root[data-theme="light"] .seat-summary-card--total .seat-summary-num { color: var(--accent-gold-text); }

/* ═══════════════════════════════════════════════════════════════════════════
   Seat Map Lightbox Modal  (Phase 3)
   ═══════════════════════════════════════════════════════════════════════════ */

/* Override lightbox-content layout when showing seat map */
.lightbox-content:has(.sm-header) {
  align-items: stretch;
  width: min(828px, 95vw);
  max-height: 92vh;
  background: var(--bg-primary);
  border-radius: var(--radius-xl);
  border: 1px solid rgba(var(--surface-rgb),0.16);
  overflow: hidden;
  gap: 0;
  display: flex;
  flex-direction: column;
}

/* Close button positioned inside sm-header (not absolutely positioned) */
.sm-close-btn {
  position: static !important;
  top: auto !important;
  right: auto !important;
}

/* ── Header ── */
.sm-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  height: 48px;
  flex-shrink: 0;
}
.sm-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
}

/* ── Dividers ── */
.sm-divider {
  height: 0;
  border-top: 1px solid rgba(var(--surface-rgb),0.10);
  flex-shrink: 0;
}
.sm-divider-subtle {
  border-top-color: rgba(var(--surface-rgb),0.06);
}

/* ── Stage bar ── */
.sm-stage {
  position: relative;
  height: 52px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  flex-shrink: 0;
  padding-bottom: 7px;
}
.sm-stage svg {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  width: 100%;
  height: 36px;
}
.sm-stage-label {
  position: relative;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.28em;
  color: rgba(var(--like-red-rgb),0.85);
  z-index: 1;
}

/* ── Seat grid outer (gradient overlays) ── */
.seat-grid-outer {
  position: relative;
  overflow: hidden;
}

/* ── Zone seat-map filter bar (search / row / price) ── */
.sm-filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  flex-shrink: 0;
}
.sm-filter-search {
  flex: 1 1 140px;
  min-width: 120px;
}
.sm-search-input {
  width: 100%;
  height: 30px;
  padding: 0 10px;
  font-size: 13px;
  font-family: 'Noto Sans Thai', sans-serif;
  color: var(--text-primary);
  background: rgba(var(--surface-rgb),0.06);
  border: 1px solid rgba(var(--surface-rgb),0.14);
  border-radius: var(--radius-md);
}
.sm-search-input::placeholder { color: rgba(var(--surface-rgb),0.42); }
.sm-search-input--miss { border-color: var(--danger-text); }
/* "Seat not found" line under the filter row (main.js setMiss) — its own
   block, not inside the bar: the bar is nowrap on phones and the open search
   input is absolutely centered in it */
.sm-search-miss {
  flex-shrink: 0;
  margin: -4px 16px 6px;
  font-size: 12px;
  color: var(--danger-text);
}
/* Magnifier fallback when the row is too full (main.js adds
   .sm-search-collapsed) — same look as the homepage .seat-lookup__toggle */
.sm-search-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  color: var(--text-primary);
  background: rgba(var(--surface-rgb),0.08);
  border: 1px solid rgba(var(--surface-rgb),0.18);
  border-radius: var(--radius-pill);
  cursor: pointer;
  flex-shrink: 0;
}
@media (hover: hover) { .sm-search-toggle:hover { color: var(--gold-btn-text); background: var(--accent-gold); border-color: var(--accent-gold); } }
.sm-filter-bar { position: relative; }
.sm-filter-bar.sm-search-collapsed .sm-filter-search { flex: 0 0 auto; min-width: 0; }
.sm-filter-bar.sm-search-collapsed .sm-search-toggle { display: inline-flex; }
.sm-filter-bar.sm-search-collapsed .sm-search-input { display: none; }
/* Open: input spans the whole row over select + chips, toggle stays at its end */
.sm-filter-bar.sm-search-open .sm-search-toggle { position: relative; z-index: 2; color: var(--gold-btn-text); background: var(--accent-gold); border-color: var(--accent-gold); }
.sm-filter-bar.sm-search-open .sm-search-input {
  display: block;
  position: absolute;
  z-index: 1;
  top: 50%;
  transform: translateY(-50%);
  left: 12px;
  right: 12px;
  width: auto;
  padding-right: 40px;
  background: var(--bg-elevated);
  border-color: var(--accent-gold);
}
.sm-filter-bar.sm-search-open .sm-filter-search { order: 99; margin-left: auto; }
.sm-search-input:focus {
  outline: none;
  border-color: var(--like-red);
}
.sm-row-select {
  height: 30px;
  padding: 0 8px;
  font-size: 13px;
  font-family: 'Noto Sans Thai', sans-serif;
  color: var(--text-primary);
  background: rgba(var(--surface-rgb),0.06);
  border: 1px solid rgba(var(--surface-rgb),0.14);
  border-radius: var(--radius-md);
  flex-shrink: 0;
}
/* The closed box above is themed via --surface-rgb/--text-primary, but the
   OPEN option list is native/OS-rendered and ignores that — left unstyled it
   falls back to the browser default white background, which combined with
   the inherited white --text-primary (dark mode) makes the open list
   unreadable white-on-white. Same bug/fix as p/admin.css's `select option`
   rule (2026-07 admin fix) — this is the main site's own <select>. */
.sm-row-select option {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.sm-price-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  flex-shrink: 0;
}
.sm-price-chip {
  height: 26px;
  padding: 0 10px;
  font-size: 12px;
  font-weight: 600;
  font-family: 'Noto Sans Thai', sans-serif;
  border-radius: var(--radius-pill);
  cursor: pointer;
  background: rgba(var(--chip-r),var(--chip-g),var(--chip-b),0.16);
  border: 1px solid rgba(var(--chip-r),var(--chip-g),var(--chip-b),0.5);
  transition: background 0.15s, border-color 0.15s;
}
@media (hover: hover) { .sm-price-chip:hover { background: rgba(var(--chip-r),var(--chip-g),var(--chip-b),0.28); } }
.sm-price-chip.active {
  background: rgba(var(--chip-r),var(--chip-g),var(--chip-b),0.85);
  border-color: rgba(var(--chip-r),var(--chip-g),var(--chip-b),1);
}

/* Row/price filter: dim non-matching rows rather than hiding them (keeps the
   whole zone shape visible while drawing the eye to the matched rows) */
.seat-row.sm-row-dimmed {
  opacity: 0.22;
  transition: opacity 0.15s;
}

/* Search: highlight matched seat */
.seat-cell.sm-seat-highlight {
  box-shadow: 0 0 0 2px var(--bg-primary), 0 0 0 4px rgba(var(--like-red-rgb),0.9);
}

/* ── Zoom controls (overlaid on stage) ── */
.sm-zoom-controls {
  position: absolute;
  right: 12px;
  bottom: 6px;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 7px;
  /* Deliberately always dark (not theme-tokened) — this pill floats over the
     stage graphic itself, not the page background, so it needs the same
     fixed dark chrome + white icons in both themes for legibility (like a
     video player's control bar), not a swap that could leave dark text on
     this same dark pill in light mode. */
  background: rgba(var(--black-rgb),0.65);
  border: 1px solid rgba(var(--white-rgb),0.12);
  border-radius: var(--radius-4xl);
  backdrop-filter: blur(6px);
}
.sm-zoom-btn {
  width: 22px;
  height: 22px;
  border-radius: var(--radius-full);
  border: none;
  background: rgba(var(--white-rgb),0.1);
  color: var(--white);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s;
}
@media (hover: hover) { .sm-zoom-btn:hover { background: rgba(var(--white-rgb),0.22); } }
.sm-zoom-label {
  font-size: 12px;
  color: rgba(var(--white-rgb),0.65);
  min-width: 34px;
  text-align: center;
}

/* ── Seat grid viewport — pan/zoom by pan-zoom.js (transform), never native
   scroll: iOS Safari froze panning after a CSS zoom change (bible §5.11) ── */
.seat-grid-wrap {
  position: relative;
  height: 414px;
  overflow: hidden;
  touch-action: none; /* every gesture goes to pan-zoom.js, none to the page */
  flex-shrink: 0;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
}
.seat-grid-wrap.is-panning { cursor: grabbing; }

/* Bottom fade — pinned to the viewport's bottom edge */
.sm-fade-bottom {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 36px;
  background: linear-gradient(to top, var(--bg-primary), transparent);
  pointer-events: none;
  z-index: 25;
  align-self: stretch;
}

/* Right fade — hidden */
.sm-fade-right { display: none; }

/* ── Seat grid ── */
.seat-grid {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 5px 5px 44px 5px;
  width: fit-content;
  position: absolute;   /* placed by pan-zoom.js's transform */
  top: 0;
  left: 0;
  transform-origin: 0 0;
}

/* ── Seat row ── */
.seat-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.seat-row-label {
  font-size: 12px;
  color: rgba(var(--surface-rgb),0.55);
  width: 28px;
  min-width: 28px;
  text-align: center;
  padding: 0 6.5px;
  flex-shrink: 0;
  font-family: 'Noto Sans Thai', sans-serif;
  position: relative; /* was sticky — moves with the grid now (pan-zoom.js) */
  z-index: 20;
}
.seat-row-cells {
  display: grid;
  gap: 3px;
}
.seat-row-label-right {
  font-size: 12px;
  color: rgba(var(--surface-rgb),0.55);
  width: 28px;
  min-width: 28px;
  text-align: center;
  padding: 0 6.5px;
  flex-shrink: 0;
  font-family: 'Noto Sans Thai', sans-serif;
  position: relative; /* was sticky — moves with the grid now (pan-zoom.js) */
  z-index: 20;
}

/* ── Seat cell (circle) ── */
.seat-cell {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-full);
  background: var(--seat-color, #888);
  /* Was a fixed #0a0a1a — collided with some tier colors in both themes
     (2026-08-08 fix). --seat-text-color is computed per-cell by main.js
     via contrastTextColor(), same technique as p/panel.js's zone chip. */
  color: var(--seat-text-color, var(--fixed-bg-3));
  font-size: 11px;
  font-family: 'Noto Sans Thai', sans-serif;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: default;
  user-select: none;
  opacity: 0.90;
}

/* ── Scroll hints ── */
.sm-scroll-hints {
  display: flex;
  justify-content: space-between;
  padding: 4px 16px;
  font-size: 10.9px;
  color: rgba(var(--surface-rgb),0.38);
  flex-shrink: 0;
}

/* ── Legend ── */
.seat-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  padding: 8px 16px;
  flex-shrink: 0;
}
.seat-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
}
.seat-legend-dot {
  width: 12px;
  height: 12px;
  border-radius: var(--radius-full);
  flex-shrink: 0;
}
.seat-legend-price {
  font-size: 11px;
  color: rgba(var(--surface-rgb),0.75);
  font-family: 'Noto Sans Thai', sans-serif;
}

/* ── Action buttons ── */
.sm-buttons {
  display: flex;
  gap: 20px;
  padding: 7px 20px;
  flex-shrink: 0;
}
.sm-btn {
  flex: 1;
  height: 38px;
  border-radius: var(--radius-md);
  font-size: 14px;
  font-family: 'Noto Sans Thai', sans-serif;
  font-weight: 600;
  cursor: pointer;
  border: none;
  transition: opacity 0.15s;
}
@media (hover: hover) { .sm-btn:hover { opacity: 0.82; } }
.sm-btn-primary {
  background: var(--accent-gold);
  color: var(--gold-btn-text);
}
/* Keeps dark mode's vivid gold + dark text in light mode too (2026-08-08 ask)
   — solid fill + in-box text has self-contained contrast, independent of
   the page background, so light mode's muted gold isn't needed here. */
:root[data-theme="light"] .sm-btn-primary { background: var(--brand-gold); color: var(--brand-gold-ink); }
.sm-btn-secondary {
  background: rgba(var(--accent-teal-rgb),0.08);
  border: 1px solid rgba(var(--accent-teal-rgb),0.70);
  color: var(--accent-teal-text);
}

/* ── Disclaimer ── */
.sm-disclaimer {
  font-size: 12px;
  color: rgba(var(--surface-rgb),0.28);
  text-align: center;
  padding: 10px 16px 14px;
  font-family: 'Noto Sans Thai', sans-serif;
  flex-shrink: 0;
}

/* ── Responsive: narrow screens ── */
@media (max-width: 480px) {
  .sm-buttons { gap: 10px; padding: 7px 12px; }
  /* Buttons, price legend and disclaimer -10% on phones (owner 2026-10-17) */
  .sm-btn { font-size: 12px; height: 34px; }
  .seat-legend { gap: 7px 18px; }
  .seat-legend-dot { width: 11px; height: 11px; }
  .seat-legend-price { font-size: 10px; }
  .sm-disclaimer { font-size: 11px; }
  /* Stage + zoom pill -10% on phones (owner 2026-10-17) */
  .sm-stage { height: 47px; padding-bottom: 6px; }
  .sm-stage svg { height: 32px; }
  .sm-stage-label { font-size: 11px; }
  .sm-zoom-controls { right: 11px; bottom: 5px; gap: 4px; padding: 3px 6px; }
  .sm-zoom-btn { width: 20px; height: 20px; font-size: 14px; }
  .sm-zoom-label { font-size: 11px; min-width: 31px; }
  /* Search + row + price chips on ONE row like desktop (owner 2026-10-17);
     chips scroll sideways if a zone has more than fit */
  .sm-filter-bar { flex-wrap: nowrap; gap: 6px; padding: 10px 12px; }
  .sm-filter-search { flex: 1 1 0; min-width: 0; }
  .sm-search-input { padding: 0 8px; }
  .sm-row-select { padding: 0 4px; }
  .sm-price-filter { flex-wrap: nowrap; flex-shrink: 1; min-width: 0; overflow-x: auto; scrollbar-width: none; }
  .sm-price-filter::-webkit-scrollbar { display: none; }
  .sm-price-chip { flex-shrink: 0; padding: 0 8px; }
  .sm-scroll-hints { font-size: 9.8px; padding: 4px 12px; } /* -10% (owner 2026-10-17) */
  .seat-grid { padding-left: 8px; }
}

/* ── Panel legal footer (2026-07-12 ask) ─────────────────────────────────
   "ข้อกำหนดการใช้งาน · นโยบายความเป็นส่วนตัว" row at the end of the idle
   panel content (Most Liked Zones) — idle state only, so it's hidden along
   with the rest of #panel-idle once a zone is selected and #panel-active
   takes over. */
.panel-legal-footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin-top: 16px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-secondary);
  font-family: var(--font-thai);
}
.panel-legal-footer a { color: var(--text-secondary); text-decoration: none; }
@media (hover: hover) { .panel-legal-footer a:hover { color: var(--text-primary); } }

/* ── Mobile "scroll for details" hint (2026-07-12 ask) ───────────────────
   Mirrors /p/find's .find-scroll-hint: mobile only, floats above the
   floating bottom bar, scrolls #panel-col into view, fades out once the
   panel's top edge is visible (toggled in main.js via IntersectionObserver).
   Hidden entirely outside the mobile query — desktop has nothing below the
   fold to scroll to (#page-layout is a fixed viewport there). */
.scroll-hint { display: none; }
@media (max-width: 767px) {
  .scroll-hint {
    display: flex;
    align-items: center;
    gap: 6px;
    position: fixed;
    left: 50%;
    /* Sits 12px above the floating #bottom-bar card: 8px bar offset + its
       measured height (--bottom-bar-h, set by main.js initScrollHint). */
    bottom: calc(8px + var(--bottom-bar-h, 96px) + 12px + var(--safe-bottom));
    transform: translateX(-50%);
    padding: 5px 12px;
    border: 1px solid rgba(var(--surface-rgb), 0.3);
    border-radius: var(--radius-pill);
    background: rgba(var(--surface-rgb), 0.14);
    backdrop-filter: blur(16px) saturate(1.4);
    -webkit-backdrop-filter: blur(16px) saturate(1.4);
    box-shadow: 0 6px 18px rgba(var(--shadow-rgb), calc(0.35 * var(--shadow-mult)));
    color: var(--text-primary);
    font: 600 12px var(--font-thai);
    cursor: pointer;
    z-index: 150;
    opacity: 1;
    transition: opacity 0.3s ease;
  }
  .scroll-hint.is-hidden { opacity: 0; pointer-events: none; }
  .scroll-hint__arrow { display: inline-block; animation: scroll-hint-bounce 1.4s ease-in-out infinite; }
}
@keyframes scroll-hint-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(3px); }
}

/* ── Shared loading spinner (2026-07-12 ask) ─────────────────────────────
   Same class names/markup as every /p page's .ppw-loading (p/tokens.css) —
   recreated here with the main site's own token names instead of importing
   tokens.css, to avoid pulling in the rest of that stylesheet. Use
   `.ppw-loading` (spinner + text row) for a section's data-fetch state. */
@keyframes ppw-spin { to { transform: rotate(360deg); } }
.ppw-spinner {
  display: inline-block;
  width: 16px; height: 16px;
  border: 2px solid rgba(var(--surface-rgb), 0.2);
  border-top-color: var(--accent-gold);
  border-radius: var(--radius-full);
  animation: ppw-spin 0.7s linear infinite;
  flex-shrink: 0;
}
.ppw-spinner--lg { width: 34px; height: 34px; border-width: 3px; }
.ppw-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: var(--text-secondary);
  font-size: 15px;
  padding: 40px 0;
}
.ppw-loading-text { opacity: 0.8; }

/* Stuck-loading recovery state (2026-07-15, see p/boot-timeout.js) — same
   rules as /p's tokens.css copy, recreated here for the same reason as the
   spinner block above (avoid importing tokens.css just for this). */
.ppw-loading--stuck { flex-direction: column; gap: 14px; }
.ppw-retry-btn {
  background: var(--accent-gold);
  /* Was var(--bg-primary) — happened to work in dark mode (near-black) but
     landed light lavender text on light mode's darker gold (3.19:1, fails)
     (2026-08-08 fix, same class of bug as .auth-btn--primary). */
  color: var(--gold-btn-text);
  border: none;
  border-radius: var(--radius-md);
  padding: 10px 24px;
  font-family: var(--font-thai, inherit);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
@media (hover: hover) { .ppw-retry-btn:hover { opacity: 0.9; } }
/* Keeps dark mode's vivid gold + dark text in light mode too (2026-08-08 ask)
   — solid fill + in-box text has self-contained contrast, independent of
   the page background, so light mode's muted gold isn't needed here. */
:root[data-theme="light"] .ppw-retry-btn { background: var(--brand-gold); color: var(--brand-gold-ink); }

/* Leaderboard skeleton (2026-07-21) — grey shape of the podium/rows that
   are about to land there, shown while renderLeaderboard() waits on
   Supabase. Shimmer sweep is what reads as "working"; static grey would
   read as frozen for the same wait. */
@keyframes lb-skel-shimmer {
  0%   { background-position: -120% 0; }
  100% { background-position: 120% 0; }
}
.lb-skel {
  border-radius: var(--radius-md);
  background: linear-gradient(90deg, rgba(var(--surface-rgb), 0.05) 25%, rgba(var(--surface-rgb), 0.12) 50%, rgba(var(--surface-rgb), 0.05) 75%);
  background-size: 200% 100%;
  animation: lb-skel-shimmer 1.4s ease-in-out infinite;
}
.lb-skel-podium { height: 84px; flex: 1; }
.lb-skel-row { height: 30px; margin: 6px 0; }

/* ── Page boot loader ─────────────────────────────────────────────────────
   Covers navbar/hero/map/panel until window `load` fires (initPageLoader()
   in main.js) — mirrors /p's "spinner before reveal" logic at the whole-page
   level. z-index above nav.css's navbar (1000, per its own comment above). */
#page-loader {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  background: var(--bg-primary);
  transition: opacity 0.3s ease;
}
#page-loader.is-hidden { opacity: 0; pointer-events: none; }

/* ── Toast notifications (toast.js) ──────────────────────────────────────
   Shared with every /p page (duplicated into p/tokens.css, same convention
   as this file's own copy of /p's scrollbar rule — see TROUBLESHOOTING_BIBLE
   §6.11) — replaces alert() sitewide (2026-07-25 ask) with a non-blocking,
   auto-dismissing notice. z-index 9999 is deliberately above every other
   documented z-index in the codebase (highest prior was this file's own
   #page-loader at 2000) so a toast is never hidden behind a modal. */
.ppw-toast-host {
  position: fixed;
  left: 50%;
  bottom: calc(24px + var(--safe-bottom) + var(--inapp-bottom));
  transform: translateX(-50%);
  z-index: 9999;
  display: flex;
  flex-direction: column-reverse;
  gap: 8px;
  align-items: center;
  pointer-events: none;
  max-width: calc(100vw - 32px);
}
.ppw-toast {
  pointer-events: auto;
  cursor: pointer;
  padding: 16px 22px;
  border-radius: var(--radius-xl);
  /* A light frosted-glass tint (2026-07-26 fix) — the previous dark navy
     fill (rgba(28,30,53,...)) was too close to the page's own near-black
     background/space-gradient, so the toast barely stood out despite the
     blur. Lighter than the page reads as a distinct floating card instead.
     Fixed white glass (not rgba(var(--surface-rgb),X), unlike every other
     "raised surface" tint sitewide) — reverted 2026-08-13 back to this
     original subtle-glow-glass look after a same-day attempt at an opaque
     white-card-with-dark-text variant read as flatter/lost the frosted
     quality against the site's dark space theme. Fixed background (not a
     theme-reactive token) so this glass look stays put across the light/dark
     toggle instead of swapping. Text color BELOW stays var(--text-primary)
     though (not also fixed white) — fixed white text on this same white
     glass went unreadable in light mode (2026-08-13 follow-up fix); the
     glass tint is subtle enough that dark text in light mode still reads
     fine against it. Kept in sync with the /p subsystem's duplicate copy in
     p/tokens.css. */
  background: rgba(var(--white-rgb), 0.10);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(var(--white-rgb), 0.18);
  border-left: 5px solid var(--text-secondary);
  color: var(--text-primary);
  font-family: var(--font-thai);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.5;
  box-shadow: 0 14px 36px rgba(var(--shadow-rgb), calc(0.45 * var(--shadow-mult)));
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  max-width: 420px;
}
.ppw-toast.is-in { opacity: 1; transform: translateY(0); }
/* Type glow (2026-07-26 ask: "more prominent") — a soft colored glow on top
   of the base drop shadow, tinted per type, on every toast sitewide. */
.ppw-toast--error { border-left-color: var(--like-red); box-shadow: 0 14px 36px rgba(var(--shadow-rgb), calc(0.45 * var(--shadow-mult))), 0 0 28px rgba(var(--like-red-rgb), 0.28); }
.ppw-toast--success { border-left-color: var(--success-text); box-shadow: 0 14px 36px rgba(var(--shadow-rgb), calc(0.45 * var(--shadow-mult))), 0 0 28px rgba(var(--status-green-rgb), 0.28); }
.ppw-toast--info { border-left-color: var(--accent-teal); box-shadow: 0 14px 36px rgba(var(--shadow-rgb), calc(0.45 * var(--shadow-mult))), 0 0 28px rgba(var(--accent-teal-rgb),0.28); }
/* Sticky error toast (2026-10-23): close button + code/time/path meta line
   for screenshots. Kept in sync with the duplicate copy in the other file. */
.ppw-toast--sticky { position: relative; padding-right: 40px; }
.ppw-toast__close { position: absolute; top: 6px; right: 8px; background: none; border: 0; color: var(--text-secondary); font-size: 20px; line-height: 1; cursor: pointer; padding: 4px; }
.ppw-toast__meta { margin-top: 6px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; font-weight: 500; color: var(--text-secondary); word-break: break-word; user-select: text; }

/* ─── Theme variants: poster-band hero, flat zone panel, red-fog motif ─────
   Added 2026-10-12 for events/jasper-temptation-2026 (handoffs/jasper-temptation-redesign.md).
   Every rule is keyed to a theme-boot.js attribute that the default project
   never sets (hero "poster-band", motif pattern "red-fog"), so PPW renders
   pixel-identical. Layout, order, labels and click flow are unchanged — only
   the hero backdrop, the panel's outer box and the title face differ. */

/* Hero (owner 2026-10-12): two layers behind the title.
   ::before — the cover, full-bleed and blurred (fills the whole hero). Uses
              JASPER_temptation-cover-blur.webp (480px, 18 KB, 2026-10-22):
              at blur(24px) it looks the same as the 572 KB full cover.
   ::after  — JASPER_temptation-cover_new (all four faces), sharp, same pixels
              as the file (no resize): right side at full hero height on
              desktop, full width at the top on phones; its edge fades into
              the blur through a mask, so there is no hard seam.
   No dark band over the art — the title gets a soft text-shadow instead. */
html[data-variant-hero="poster-band"] #hero {
  position: relative; isolation: isolate; overflow: hidden;
  background: var(--bg-primary);
}
html[data-variant-hero="poster-band"] #hero::before,
html[data-variant-hero="poster-band"] #hero::after {
  content: ""; position: absolute; pointer-events: none;
}
html[data-variant-hero="poster-band"] #hero::before {
  inset: -48px; z-index: -2;
  background: var(--hero-band-img, url('/JASPER_temptation-cover-blur.webp')) center 30% / cover no-repeat,
              var(--hero-thumb-cover, none) center 30% / cover no-repeat; /* blur-up layer, blur-up.js */
  filter: blur(24px) brightness(0.8);
}
html[data-variant-hero="poster-band"] #hero::after {
  z-index: -1; top: 0; left: 0; width: 100%; aspect-ratio: 1642 / 850;
  background: url('/JASPER_temptation-cover_new.webp') center / cover no-repeat,
              var(--hero-thumb-cover-new, none) center / cover no-repeat; /* blur-up layer, blur-up.js */
  -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
}
html[data-variant-hero="poster-band"] .hero-info { text-shadow: 0 2px 14px rgba(var(--black-rgb), 0.75); }
/* The hero is always dark art (blurred cover + photo), so in light mode its
   text keeps the DARK palette (owner 2026-10-12). Values = theme.json "dark". */
html[data-theme="light"][data-variant-hero="poster-band"] #hero {
  color-scheme: dark;
  --text-primary: #F2ECEA;
  --text-secondary: #B9AFAD;
  --accent-gold-text: #FF5A52;
  --accent-teal: #D4A85A;
}
html[data-variant-hero="poster-band"] .hero-poster { display: none; }
/* One rule under the hero: keep .hero-divider (and its 16px breathing room
   above it) and drop #seat-section's border-top, which sat 1px below it and
   read as a double line (owner 2026-10-12). */
html[data-variant-hero="poster-band"] #seat-section { border-top: 0; }
@media (max-width: 1023px) {
  html[data-variant-hero="poster-band"] #hero { padding-top: 0; }
  /* Title sits under the faces: reserve the image height minus a small overlap. */
  html[data-variant-hero="poster-band"] .hero-inner { min-height: 20vh; align-items: flex-end; padding-top: calc(100vw * 850 / 1642 - 64px); }
}
@media (min-width: 1024px) {
  html[data-variant-hero="poster-band"] #hero::after {
    left: auto; right: 0; bottom: 0; width: auto; height: 100%;
    /* Art 10% larger inside the same hero (owner 2026-10-12); the hero's
       overflow:hidden trims the overflow evenly top and bottom. */
    transform: scale(1.1); transform-origin: 100% 50%;
    -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 28%);
            mask-image: linear-gradient(90deg, transparent 0%, #000 28%);
  }
  html[data-variant-hero="poster-band"] .hero-inner { min-height: 150px; align-items: flex-end; padding-bottom: var(--space-8); }
}
@media (min-width: 1024px) and (min-height: 860px) {
  html[data-variant-hero="poster-band"] .hero-inner { min-height: 200px; }
}

/* Zone panel: one surface, not a box inside a box. The column divider
   already separates it from the map, so the outer frame goes; inner cards
   become flat tiles. */
html[data-variant-hero="poster-band"] #zone-panel { background: rgba(var(--black-rgb), 0.4); border: 0; border-radius: 0; margin: 0; }
/* Faint dark ground behind the info column so text reads clearly over the
   red haze (owner 2026-10-12); light mode gets the equivalent pale veil. */
html[data-theme="light"][data-variant-hero="poster-band"] #zone-panel { background: rgba(var(--white-rgb), 0.55); }
html[data-variant-hero="poster-band"] .panel-header { padding-left: var(--space-10); padding-right: var(--space-10); }
html[data-variant-hero="poster-band"] .seat-summary-card { border: 0; border-radius: 0; background: var(--bg-elevated); }
html[data-variant-hero="poster-band"] .seat-summary-card--total { border-left: 2px solid var(--accent-gold); }

/* Motif red-fog: one static haze (Calm Motion — never animated) and the
   chrome display title. */
/* body::before is the grain layer; body::after is the glow behind the map
   (hardcoded purple for PPW) — recoloured from the theme accent here. */
html[data-motif-pattern="red-fog"] body::after {
  background: radial-gradient(circle, rgba(var(--accent-gold-rgb), 0.18) 0%, transparent 70%);
}
html[data-motif-pattern="red-fog"] .hero-title {
  font-family: var(--font-display); letter-spacing: .04em;
  background: linear-gradient(180deg, var(--text-primary) 0%, var(--text-secondary) 45%, var(--accent-teal) 55%, var(--text-primary) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
html[data-motif-pattern="red-fog"] .hero-subtitle { font-family: var(--font-display); letter-spacing: .12em; }

/* Guide popup follows the theme (2026-10-12) — only for a red-fog-motif theme
   (events/jasper-temptation-2026); the literals above stay PPW's default.
   [data-project] lifts specificity above the :root[data-theme] branches. */
:root[data-motif-pattern="red-fog"][data-project] {
  --guide-modal-bg:  var(--modal-bg);
  --guide-header-bg: var(--navbar-bg);
  --guide-btn:       var(--accent-gold);
  --guide-divider:   rgba(var(--surface-rgb), 0.10);
}

/* Red-fog theme: these labels used the FILL accent as ink (3.1–3.3:1 on the
   jasper ground). Use the -text variant (≥ 4.5:1) — UIUX §5.3 "no fill as ink". */
:root[data-motif-pattern="red-fog"][data-project] .seat-summary-card--total .seat-summary-label,
:root[data-motif-pattern="red-fog"][data-project] .seat-summary-card--total .seat-summary-num,
:root[data-motif-pattern="red-fog"][data-project] .sale-main,
:root[data-motif-pattern="red-fog"][data-project] .sale-sub { color: var(--accent-gold-text); }

/* Red-fog theme: PPW's navy-black scrims and the zoom pill were literals
   (rgba 2,3,16 / 7,7,26) and left a blue cast behind popups. Neutral black here. */
:root[data-motif-pattern="red-fog"][data-project] .prayer-backdrop,
:root[data-motif-pattern="red-fog"][data-project] .modal-backdrop { background: rgba(var(--black-rgb), 0.88); }
:root[data-motif-pattern="red-fog"][data-project] .sm-zoom-controls { background: rgba(var(--black-rgb), 0.65); }
/* Keyboard focus on a zone glows in the theme's focus colour (shape-following, not a box). */
:root[data-motif-pattern="red-fog"][data-project] .zone:focus-visible .zone-band { filter: drop-shadow(0 0 4px var(--focus-ring)) drop-shadow(0 0 2px var(--focus-ring)); }

/* ─── Panel toolbar + Ticket planner (ticket-planner.js, 2026-10-13) ────── */
/* "เมนูเพิ่มเติม" in the idle panel — same pattern as /p/find's submenu
   (muted label + full-width tinted button), neutral rather than red. */
.panel-submenu { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.panel-submenu-label { font-size: 11px; font-weight: 600; color: var(--text-secondary); }
/* Three buttons per row; each stacks icon over label. */
.panel-submenu-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.panel-entry-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 100%;
  min-height: 64px;
  padding: 8px 6px;
  font: 600 12px var(--font-thai);
  line-height: 1.25;
  text-align: center;
  color: var(--text-primary);
  background: rgba(var(--surface-rgb), 0.06);
  border: 1px solid rgba(var(--surface-rgb), 0.18);
  border-radius: var(--radius-lg);
  cursor: pointer;
}
@media (hover: hover) { .panel-entry-btn:hover { background: rgba(var(--surface-rgb), 0.12); } }
.panel-entry-btn .emoji-icon { width: 20px; height: 20px; }

/* Zone card: fee hint + the one planner button share a row. */
.price-plan-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 8px; }
.price-plan-row--end { justify-content: flex-end; }
.price-plan-row .price-fee-note { flex: 1; min-width: 0; margin: 0; }
.btn-plan {
  flex-shrink: 0;
  height: 30px;
  padding: 0 12px;
  font: 600 12px var(--font-thai);
  color: var(--text-primary);
  background: rgba(var(--surface-rgb), 0.06);
  border: 1px solid rgba(var(--surface-rgb), 0.2);
  border-radius: var(--radius-pill);
  cursor: pointer;
  white-space: nowrap;
}
@media (hover: hover) { .btn-plan:hover { background: rgba(var(--surface-rgb), 0.12); } }

.tp-modal {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  align-items: center;
  justify-content: center;
  padding: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left);
}
.tp-modal.is-open { display: flex; animation: prayer-fade-in 0.2s ease; }
.tp-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.82); backdrop-filter: blur(4px); }
.tp-card {
  position: relative;
  z-index: 1;
  width: 480px;
  max-width: calc(100vw - 24px);
  max-height: calc(100dvh - 48px);
  display: flex;
  flex-direction: column;
  background: var(--bg-primary);
  border-radius: var(--radius-2xl);
  overflow: hidden;
  box-shadow: 0 0 0 1.5px var(--accent-gold), 0 0 40px rgba(var(--accent-gold-rgb), 0.22);
}
.tp-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background: var(--bg-secondary);
  border-bottom: 1px solid rgba(var(--accent-gold-rgb), 0.25);
}
.tp-title { font-size: 15px; font-weight: 700; color: var(--text-primary); }
.tp-close, .tp-x {
  background: rgba(var(--surface-rgb), 0.08);
  border: none;
  color: var(--text-secondary);
  font-size: 13px;
  padding: 4px 9px;
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.tp-body { padding: 14px 16px 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
.tp-step-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.tp-step-head .tp-step { flex: 1; min-width: 0; }
.tp-step-head .tp-dots { flex-shrink: 0; }
.tp-step { margin: 0; display: flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 700; color: var(--text-primary); }
.tp-step-num {
  flex-shrink: 0;
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--accent-gold-text);
  border-radius: 50%;
  font-size: 12px; font-weight: 700; line-height: 1;
  color: var(--accent-gold-text);
}
.tp-dots { display: flex; align-items: center; gap: 5px; }
.tp-dot { width: 6px; height: 6px; border-radius: var(--radius-pill); background: rgba(var(--surface-rgb), 0.18); transition: width 0.2s, background 0.2s; }
.tp-dot.is-done { background: rgba(var(--accent-gold-rgb), 0.55); }
.tp-dot.is-current { width: 20px; background: var(--accent-gold-text); }
.tp-btn--back { display: inline-flex; align-items: center; justify-content: center; gap: 4px; }
.tp-btn--back svg { flex-shrink: 0; }
.tp-q { margin: 4px 0 0; font-size: 13px; font-weight: 600; color: var(--text-primary); }
.tp-muted { font-size: 12px; color: var(--text-secondary); margin: 0; }
.tp-center { text-align: center; }
.tp-fine { margin: 0; font-size: 11px; color: var(--text-secondary); }
.tp-field { display: flex; flex-direction: column; gap: 4px; }
.tp-select {
  height: 38px;
  padding: 0 10px;
  font: 400 14px var(--font-thai);
  color: var(--text-primary);
  background: var(--bg-elevated);
  border: 1px solid rgba(var(--surface-rgb), 0.18);
  border-radius: var(--radius-md);
}
.tp-select:focus { outline: none; border-color: var(--accent-gold); }
.tp-select option { color: var(--text-primary); background: var(--bg-elevated); }
.tp-price-fixed { font: 700 18px var(--font-latin); }
.tp-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.tp-chip {
  min-height: 30px;
  padding: 0 12px;
  font: 500 13px var(--font-thai);
  color: var(--text-primary);
  background: rgba(var(--surface-rgb), 0.06);
  border: 1px solid rgba(var(--surface-rgb), 0.16);
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.tp-chip--price { font-family: var(--font-latin); font-weight: 700; }
.tp-chip--zone { min-width: 40px; padding: 0 8px; font-family: var(--font-latin); font-weight: 700; }
.tp-chip.is-on { color: var(--gold-btn-text); background: var(--accent-gold); border-color: var(--accent-gold); }
.tp-chip:disabled { opacity: 0.35; cursor: not-allowed; }
.tp-tier { display: flex; align-items: flex-start; gap: 10px; }
.tp-tier-price { flex: 0 0 64px; padding-top: 6px; font: 700 13px var(--font-latin); }
.tp-link { align-self: flex-start; background: none; border: none; padding: 0; font-size: 12px; color: var(--accent-gold-text); text-decoration: underline; cursor: pointer; }
.tp-stepper { display: flex; align-items: center; justify-content: center; gap: 18px; margin-top: 6px; }
.tp-step-btn {
  width: 40px; height: 40px;
  font-size: 22px; line-height: 1;
  color: var(--text-primary);
  background: rgba(var(--surface-rgb), 0.08);
  border: 1px solid rgba(var(--surface-rgb), 0.2);
  border-radius: 50%;
  cursor: pointer;
}
.tp-step-btn:disabled { opacity: 0.3; cursor: not-allowed; }
.tp-qty { min-width: 64px; text-align: center; font: 700 22px var(--font-thai); color: var(--text-primary); }
.tp-totals { display: flex; flex-direction: column; gap: 4px; padding: 10px 12px; background: var(--bg-secondary); border-radius: var(--radius-md); }
.tp-total-row { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; color: var(--text-primary); }
.tp-total-row--protect strong { color: var(--accent-gold-text); }
.tp-items, .tp-saved { display: flex; flex-direction: column; gap: 6px; }
.tp-item, .tp-saved-row {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px;
  background: var(--bg-secondary);
  border-radius: var(--radius-md);
}
.tp-item-info, .tp-saved-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: 13px; color: var(--text-primary); }
.tp-bene { display: flex; gap: 10px; padding: 8px 10px; background: var(--bg-secondary); border-radius: var(--radius-md); }
.tp-bene-list { margin: 0; padding-left: 16px; font-size: 12px; color: var(--text-primary); display: flex; flex-direction: column; gap: 2px; }
.tp-input {
  height: 34px; padding: 0 12px;
  font: 400 14px var(--font-thai);
  color: var(--text-primary);
  background: rgba(var(--surface-rgb), 0.06);
  border: 1px solid rgba(var(--surface-rgb), 0.16);
  border-radius: var(--radius-md);
}
.tp-input:focus { outline: none; border-color: var(--accent-gold); }
.tp-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.tp-actions--stack { flex-direction: column; }
.tp-btn {
  height: 36px; padding: 0 18px;
  font: 600 14px var(--font-thai);
  color: var(--gold-btn-text);
  background: var(--accent-gold);
  border: 1px solid var(--accent-gold);
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.tp-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.tp-btn--ghost { color: var(--text-primary); background: transparent; border-color: rgba(var(--surface-rgb), 0.3); }
.tp-btn--danger { color: var(--accent-gold-text); }
.tp-saved-row .tp-btn { height: 30px; padding: 0 12px; font-size: 12px; }

/* Divider between "เมนูเพิ่มเติม" and Seat Summary (owner 2026-10-13). */
.panel-submenu { padding-bottom: 16px; border-bottom: 1px solid var(--border); }

/* Countdown bar — red-to-dark gradient from the theme's own accent instead of
   one flat grey (owner 2026-10-13). Tokens only; follows light/dark. */
#bottom-bar {
  background:
    radial-gradient(110% 120% at 0% 0%, rgba(var(--accent-gold-rgb), 0.34) 0%, transparent 55%),
    radial-gradient(90% 120% at 100% 0%, rgba(var(--accent-gold-rgb), 0.22) 0%, transparent 60%),
    linear-gradient(100deg, var(--bg-elevated) 0%, var(--bottom-bg) 50%, var(--bg-elevated) 100%);
  border-top-color: rgba(var(--accent-gold-rgb), 0.55);
}
#bottom-bar .cd-box {
  background: linear-gradient(180deg, rgba(var(--accent-gold-rgb), 0.32) 0%, rgba(var(--accent-gold-rgb), 0.08) 100%);
}
/* Breathing room inside each countdown tile so digits/units don't touch its edge. */
#bottom-bar .cd-box { box-sizing: border-box; height: auto; padding: 5px 8px; }
@media (max-width: 767px) {
  #bottom-bar .bottom-countdown-block .cd-box {
    height: auto;
    padding: clamp(3px, 1.2cqi, 5px) clamp(4px, 1.6cqi, 8px);
  }
}

/* Pickup helper (pickup-helper.js) — reuses .tp-* modal; sits above the
   Concert Guide (.modal-backdrop z 1100) since it opens from inside it. */
.ph-modal { z-index: 1200; }
.ph-answers { display: flex; flex-direction: column; gap: 10px; }
.ph-answer {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  width: 100%;
  padding: 16px 18px;
  text-align: left;
  font-family: var(--font-thai);
  color: var(--text-primary);
  background: rgba(var(--surface-rgb), 0.05);
  border: 1.5px solid rgba(var(--surface-rgb), 0.18);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.ph-answer:focus-visible { outline: none; border-color: var(--accent-gold); background: rgba(var(--accent-gold-rgb), 0.10); }
/* Hover only on real pointers: tapping an answer re-renders the next step,
   and on touch the new button under the finger keeps a stuck :hover. */
@media (hover: hover) { .ph-answer:hover { border-color: var(--accent-gold); background: rgba(var(--accent-gold-rgb), 0.10); } }
.ph-answer-title { font-size: 16px; font-weight: 700; }
.ph-answer-sub { font-size: 12px; color: var(--text-secondary); }
.ph-recap { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; margin: 0; padding: 10px 12px; font-size: 13px; background: var(--bg-secondary); border-radius: var(--radius-md); }
.ph-recap dt { color: var(--text-secondary); }
.ph-recap dd { margin: 0; color: var(--text-primary); font-weight: 600; }
.ph-group { padding: 10px 12px; background: var(--bg-secondary); border-radius: var(--radius-md); display: flex; flex-direction: column; gap: 6px; }
.ph-group-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 13px; color: var(--text-primary); }
.ph-tag { padding: 1px 8px; font-size: 11px; font-weight: 600; color: var(--accent-gold-text); border: 1px solid rgba(var(--accent-gold-rgb), 0.5); border-radius: var(--radius-pill); }
.ph-note {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 12px;
  font-size: 13px; color: var(--text-primary);
  background: rgba(var(--accent-gold-rgb), 0.10);
  border-left: 3px solid var(--accent-gold);
  border-radius: var(--radius-md);
}
.ph-note strong { color: var(--accent-gold-text); }
.ph-list { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--text-primary); }
.btn-pickup-helper {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; margin-top: 12px; padding: 10px;
  font: 600 13px var(--font-thai);
  color: var(--text-primary);
  background: rgba(var(--surface-rgb), 0.06);
  border: 1px solid rgba(var(--surface-rgb), 0.18);
  border-radius: var(--radius-lg);
  cursor: pointer;
}
@media (hover: hover) { .btn-pickup-helper:hover { background: rgba(var(--surface-rgb), 0.12); } }
.ph-hint { margin: -4px 0 2px; font-size: 12px; color: var(--accent-gold-text); }
.ph-must { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; font-size: 13px; color: var(--text-primary); border: 1.5px solid var(--accent-gold); border-radius: var(--radius-md); }
.ph-must strong { color: var(--accent-gold-text); }

/* First-timer journey (first-timer.js) — route of 4 chapters, progress ring,
   "ตอนนี้" chapter from EVENT dates, stamp on a finished chapter. Tokens only. */
.ft-top { display: flex; align-items: center; gap: 14px; }
.ft-ring { position: relative; flex: 0 0 76px; width: 76px; height: 76px; }
.ft-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.ft-ring circle { fill: none; stroke-width: 3.2; }
.ft-ring-track { stroke: rgba(var(--surface-rgb), 0.12); }
.ft-ring-fill { stroke: var(--accent-gold); stroke-linecap: round; transition: stroke-dasharray 0.4s ease; filter: drop-shadow(0 0 4px rgba(var(--accent-gold-rgb), 0.6)); }
.ft-ring-label { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1.1; }
.ft-ring-label strong { font: 700 17px var(--font-latin); color: var(--text-primary); }
.ft-ring-label span { font-size: 10px; color: var(--text-secondary); }
.ft-intro { display: flex; flex-direction: column; gap: 2px; font-size: 12px; color: var(--text-secondary); }
.ft-intro strong { font-size: 16px; color: var(--accent-gold-text); letter-spacing: 0.3px; }
.ft-route { list-style: none; margin: 4px 0 0; padding: 0 0 0 14px; position: relative; display: flex; flex-direction: column; gap: 10px; }
.ft-route::before { content: ""; position: absolute; left: 14px; top: 18px; bottom: 18px; width: 2px; background: linear-gradient(180deg, var(--accent-gold), rgba(var(--accent-gold-rgb), 0.12)); }
.ft-chapter { position: relative; margin-left: 0; padding-left: 26px; }
.ft-chapter-head {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 10px 12px; text-align: left;
  font: 600 14px var(--font-thai); color: var(--text-primary);
  background: var(--bg-secondary);
  border: 1px solid rgba(var(--surface-rgb), 0.12);
  border-radius: var(--radius-lg);
  cursor: pointer;
}
.ft-chapter.is-now .ft-chapter-head { border-color: var(--accent-gold); box-shadow: 0 0 14px rgba(var(--accent-gold-rgb), 0.25); }
.ft-node {
  position: absolute; left: -14px; top: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--bg-elevated); border: 2px solid rgba(var(--accent-gold-rgb), 0.5);
}
.ft-node .emoji-icon { width: 16px; height: 16px; }
.ft-chapter.is-now .ft-node, .ft-chapter.is-done .ft-node { border-color: var(--accent-gold); background: rgba(var(--accent-gold-rgb), 0.18); }
.ft-chapter-title { flex: 1; min-width: 0; }
.ft-now { padding: 1px 8px; font-size: 11px; font-weight: 700; color: var(--gold-btn-text); background: var(--accent-gold); border-radius: var(--radius-pill); }
.ft-count { font: 600 12px var(--font-latin); color: var(--text-secondary); }
.ft-stamp {
  position: absolute; right: 96px; top: -9px;
  padding: 1px 8px; font-size: 11px; font-weight: 800; letter-spacing: 1px;
  color: var(--accent-gold-text); border: 2px solid var(--accent-gold); border-radius: var(--radius-xs);
  transform: rotate(-6deg); background: var(--bg-primary);
}
.ft-items { display: flex; flex-direction: column; gap: 4px; padding: 8px 4px 2px; }
.ft-item { display: flex; align-items: flex-start; gap: 10px; padding: 6px 4px; font-size: 13px; color: var(--text-primary); cursor: pointer; }
.ft-item input { position: absolute; opacity: 0; pointer-events: none; }
.ft-check {
  flex: 0 0 18px; height: 18px; margin-top: 1px;
  border: 2px solid rgba(var(--surface-rgb), 0.35); border-radius: 50%;
  transition: background 0.15s, border-color 0.15s;
}
.ft-item.is-checked .ft-check { background: var(--accent-gold); border-color: var(--accent-gold); box-shadow: inset 0 0 0 3px var(--bg-primary); }
.ft-item.is-checked .ft-text { color: var(--text-secondary); text-decoration: line-through; text-decoration-color: rgba(var(--accent-gold-rgb), 0.7); }
.ft-item input:focus-visible + .ft-check { outline: 2px solid var(--accent-gold); outline-offset: 2px; }
.ft-link { align-self: flex-start; margin: -2px 0 4px 32px; padding: 0; background: none; border: none; font-size: 12px; font-weight: 600; color: var(--accent-gold-text); cursor: pointer; }
.ft-foot { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 6px; }

/* Buttons/inputs inside the popups don't inherit the page font by default
   (browser UA → Arial). Pin every control in them to the theme font. */
.tp-modal button, .tp-modal input, .tp-modal select, .tp-modal textarea,
.seat-lookup button, .seat-lookup input { font-family: var(--font-thai); }

/* Zone finder / compare (zone-finder.js) — reuses .tp-* + .ph-answer. */
.plan-btns { display: inline-flex; gap: 6px; flex-shrink: 0; }
.zf-card { width: 560px; }
.zf-results { display: flex; flex-direction: column; gap: 6px; }
.zf-result {
  display: flex; flex-direction: column; gap: 2px; width: 100%;
  padding: 10px 12px; text-align: left;
  color: var(--text-primary); background: var(--bg-secondary);
  border: 1.5px solid rgba(var(--surface-rgb), 0.12); border-radius: var(--radius-md); cursor: pointer;
}
.zf-result.is-on { border-color: var(--accent-gold); background: rgba(var(--accent-gold-rgb), 0.10); }
.zf-result-head { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.zf-rank { flex: 0 0 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; color: var(--gold-btn-text); background: var(--accent-gold); border-radius: 50%; }
.zf-price { margin-left: auto; font-weight: 700; font-size: 13px; }
.zf-why { padding-left: 30px; font-size: 12px; color: var(--text-secondary); }
/* Finder result card (owner 2026-10-13): name + reasons left, price(s)
   right. One price → whole card toggles; several → one pill each. */
.zf-result { flex-direction: row; align-items: center; gap: 12px; position: relative; transition: border-color 0.15s, background 0.15s; }
.zf-result--multi { cursor: default; }
/* Hover only on real pointers — on touch :hover sticks to the last-tapped card. */
@media (hover: hover) { .zf-result:not(.zf-result--multi):hover:not(:disabled) { border-color: rgba(var(--accent-gold-rgb), 0.6); } }
.zf-result:disabled { opacity: 0.45; cursor: not-allowed; }
.zf-result-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.zf-result-name { display: flex; align-items: center; gap: 8px; font-size: 15px; }
.zf-result-info .zf-why { padding-left: 30px; }
.zf-result-prices { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 6px; max-width: 62%; }
.zf-price-item { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; text-align: right; }
.zf-price-item .zf-price { margin-left: 0; font-size: 16px; font-family: var(--font-latin); }
.zf-price-pill {
  min-width: 78px; padding: 5px 12px; cursor: pointer; align-items: center; text-align: center;
  color: var(--text-primary); background: rgba(var(--surface-rgb), 0.04);
  border: 1.5px solid rgba(var(--surface-rgb), 0.16); border-radius: var(--radius-pill);
  transition: border-color 0.15s, background 0.15s;
}
.zf-price-pill .zf-price { font-size: 14px; }
@media (hover: hover) { .zf-price-pill:hover:not(:disabled) { border-color: rgba(var(--accent-gold-rgb), 0.6); } }
.zf-price-pill.is-on { border-color: var(--accent-gold); background: rgba(var(--accent-gold-rgb), 0.14); }
.zf-price-pill:disabled { opacity: 0.4; cursor: not-allowed; }
/* Narrow screens: a multi-price zone stacks its price pills under the
   details so the details line keeps the full card width (owner 2026-10-14). */
@media (max-width: 480px) {
  .zf-result--multi { flex-direction: column; align-items: stretch; gap: 8px; }
  .zf-result--multi .zf-result-prices { max-width: none; justify-content: flex-start; padding-left: 30px; }
}
.zf-result-info .zf-perks { padding-left: 30px; font-size: 12px; color: var(--text-secondary); }
.zf-icon-line { display: flex; align-items: baseline; gap: 6px; }
.zf-match { text-underline-offset: 3px; text-decoration-thickness: 1.5px; color: var(--text-primary); }
.zf-icon { flex: 0 0 auto; display: inline-flex; font-size: 11px; opacity: 0.85; transform: translateY(1px); }
.zf-check:empty { display: none; }
.zf-check {
  position: absolute; top: -7px; right: -7px; width: 20px; height: 20px;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; border-radius: 50%;
  color: var(--gold-btn-text); background: var(--accent-gold);
}
.zf-results { gap: 8px; }
/* Multi-price zone: one-row segmented control (owner 2026-10-14). */
.zf-col-prices {
  display: flex; width: max-content; margin-top: 6px; overflow: hidden;
  border: 1px solid rgba(var(--surface-rgb), 0.2); border-radius: var(--radius-pill);
}
.zf-col-price {
  padding: 3px 8px; font-size: 11px; font-weight: 600; cursor: pointer;
  color: var(--text-secondary); background: transparent; border: 0;
}
.zf-col-price + .zf-col-price { border-left: 1px solid rgba(var(--surface-rgb), 0.2); }
.zf-col-price.is-on { color: var(--gold-btn-text); background: var(--accent-gold); }
.zf-col-price:disabled { opacity: 0.35; cursor: not-allowed; }
/* Scrolls on both axes so the sticky header row sticks to THIS box (owner 2026-10-14). */
.zf-scroll { overflow: auto; max-height: 60vh; margin: 0 -4px; }
.zf-table { width: 100%; border-collapse: collapse; font-size: 12px; color: var(--text-primary); }
.zf-table th, .zf-table td { padding: 7px 8px; text-align: left; vertical-align: top; border-bottom: 1px solid rgba(var(--surface-rgb), 0.08); }
.zf-table tbody th { width: 34%; font-weight: 600; color: var(--text-secondary); }
.zf-table thead th {
  white-space: nowrap; position: sticky; top: 0; z-index: 1;
  background: var(--bg-primary); box-shadow: inset 0 -1px 0 rgba(var(--surface-rgb), 0.2);
}
.zf-table thead th strong { margin-right: 6px; font-size: 14px; }
.zf-table tr.is-diff td, .zf-table tr.is-diff th { background: rgba(var(--accent-gold-rgb), 0.10); }
.zf-table tr.zf-row-price th, .zf-table tr.zf-row-price td { font-weight: 700; }
.zf-table td.is-best { font-weight: 700; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1.5px; }
.zf-views { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
.zf-view .zone-view-figure { margin-top: 0; }
.zf-view-cap { margin: 6px 0 0; font-size: 13px; font-weight: 700; text-align: center; }
.zf-view-credit { margin-top: 2px; text-align: center; font-size: 11px; }
.zf-table tr.zf-notes td { font-size: 11px; color: var(--text-secondary); }

/* Panel header back button (shown while a zone is selected). */
.panel-header { position: relative; }
.panel-back {
  position: absolute; top: 10px; right: 12px;
  height: 28px; padding: 0 12px;
  font: 600 12px var(--font-thai); color: var(--text-primary);
  background: rgba(var(--surface-rgb), 0.06);
  border: 1px solid rgba(var(--surface-rgb), 0.2);
  border-radius: var(--radius-pill); cursor: pointer;
}
@media (hover: hover) { .panel-back:hover { background: rgba(var(--surface-rgb), 0.12); } }
.panel-back.hidden { display: none; }

/* Finder answers that would leave no zone — dimmed, not pressable, say why. */
.ph-answer.is-blocked, .ph-answer:disabled { opacity: 0.45; cursor: not-allowed; }
@media (hover: hover) { .ph-answer:disabled:hover { border-color: rgba(var(--surface-rgb), 0.18); background: rgba(var(--surface-rgb), 0.05); } }
.zf-why-not { color: var(--accent-gold-text); }
/* Two buttons now share the fee-note row — let the note take its own line
   when the row gets narrow instead of squeezing to a sliver. */
.price-plan-row { flex-wrap: wrap; }
.price-plan-row .price-fee-note { flex: 1 1 220px; }
.price-plan-row .plan-btns { margin-left: auto; }

/* Add to calendar popup (calendar.js, owner 2026-10-14). */
.cal-seg { display: flex; padding: 3px; gap: 3px; background: rgba(var(--surface-rgb), 0.06); border-radius: var(--radius-pill); }
.cal-seg-btn {
  flex: 1; height: 32px; font: 600 13px var(--font-thai); cursor: pointer;
  color: var(--text-secondary); background: transparent; border: 0; border-radius: var(--radius-pill);
}
.cal-seg-btn.is-on { color: var(--gold-btn-text); background: var(--accent-gold); }
.cal-list { display: flex; flex-direction: column; gap: 8px; }
.cal-row {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 10px 12px;
  text-align: left; font: inherit; color: var(--text-primary);
  background: var(--bg-secondary); border: 1px solid transparent; border-radius: var(--radius-md);
}
button.cal-row { cursor: pointer; }
.cal-row.is-on { border-color: var(--accent-gold); }
.cal-date {
  flex: 0 0 48px; display: flex; flex-direction: column; align-items: center; line-height: 1.1;
  padding: 6px 0; border-right: 1px solid rgba(var(--surface-rgb), 0.12);
}
.cal-date strong { font: 700 20px var(--font-latin); }
.cal-date span { font-size: 11px; color: var(--text-secondary); }
.cal-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cal-name { font-size: 14px; font-weight: 600; }
.cal-time { font-size: 12px; color: var(--text-secondary); }
.cal-check {
  flex: 0 0 22px; height: 22px; display: grid; place-items: center;
  font-size: 13px; font-weight: 700; color: var(--gold-btn-text);
  border: 1.5px solid rgba(var(--surface-rgb), 0.3); border-radius: 50%;
}
.cal-row.is-on .cal-check { background: var(--accent-gold); border-color: var(--accent-gold); }
.cal-add {
  flex: 0 0 auto; padding: 6px 14px; font-size: 13px; font-weight: 600; text-decoration: none;
  color: var(--accent-gold-text); border: 1px solid var(--accent-gold); border-radius: var(--radius-pill);
}
.cal-save { width: 100%; height: 42px; }
.cal-note { text-align: center; }

/* Flat icons on the main page (2026-10-14, owner ask) — "More Menu" buttons
   reuse the nav's per-card shades (--nav-ic-*) so the two menus read as one
   set; section headings use the theme red. */
.flat-ico { display: inline-flex; flex-shrink: 0; vertical-align: -0.15em; }
.panel-entry-btn .flat-ico {
  width: 30px; height: 30px; border-radius: 8px; align-items: center; justify-content: center; font-size: 16px;
  color: var(--btn-ic, var(--accent-teal-text));
  background: color-mix(in srgb, var(--btn-ic, var(--accent-teal-text)) 16%, transparent);
}
#btn-panel-my       { --btn-ic: var(--nav-ic-my); }
#btn-panel-find     { --btn-ic: var(--nav-ic-find); }
#btn-panel-guide    { --btn-ic: var(--nav-ic-guide); }
#btn-ticket-planner { --btn-ic: var(--nav-ic-ttm); }
#btn-pickup-helper  { --btn-ic: var(--nav-ic-md); }
#btn-first-timer    { --btn-ic: var(--nav-ic-fanbene); }
#btn-zone-compare   { --btn-ic: var(--nav-ic-homesafe); }
#btn-zone-finder    { --btn-ic: var(--nav-ic-gohome); }
#btn-calendar       { --btn-ic: var(--nav-ic-vote); }
.flat-ico--head { color: var(--accent-gold-text); }
.panel-header-title .flat-ico { font-size: 18px; vertical-align: -0.2em; }
.seat-summary-icon.flat-ico { color: var(--accent-teal-text); }
.seat-summary-card--total .seat-summary-icon.flat-ico { color: var(--accent-gold-text); }

/* account-sync.js "sync with your account?" popup — stacks above .tp-modal */
.sync-ask { z-index: 1001; }
.sync-ask .tp-card { max-width: 360px; }
a.tp-btn { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }

/* 3D seat view entry links (impact-3d-link.js): dimmed until the phase opens. */
.impact3d-locked { opacity: 0.45; pointer-events: none; }
#btn-panel-3d { --btn-ic: var(--accent-gold-text); grid-column: 1 / -1; text-decoration: none; }
.btn-3d { gap: 6px; text-decoration: none; }
.sm-btn-3d { display: inline-flex; align-items: center; justify-content: center; gap: 6px; text-decoration: none; }

/* Flat Concert Guide tab icons, one shade per tab (2026-11-01) — keep in step with p/guide-modal.css. */
.guide-tab-icon svg { display: block; margin: 0 auto; }
.guide-tab[data-tab="schedule"] .guide-tab-icon { color: var(--nav-ic-guide); }
.guide-tab[data-tab="ticket"] .guide-tab-icon { color: var(--nav-ic-ttm); }
.guide-tab[data-tab="collect"] .guide-tab-icon { color: var(--nav-ic-my); }
.guide-tab[data-tab="benefit"] .guide-tab-icon { color: var(--nav-ic-fanbene); }
.guide-tab[data-tab="live"] .guide-tab-icon { color: var(--nav-ic-home); }
.guide-tab[data-tab="rules"] .guide-tab-icon { color: var(--nav-ic-md); }
