:root {
  --bg: #0b1020;
  --fg: #f2f5ff;
  --muted: #9aa3c7;
  --accent: #e94f37;
  --accent-2: #4fc3f7;
  --card: rgba(15, 22, 48, 0.88);
  --border: rgba(255, 255, 255, 0.1);
  /* Tier colors used by the 13-stop "how it works" explainer + per-row
     stripes on the TOC. Each tier-1 group (1-3, 4-6, 7-9) gets one
     color; tier-2 stops borrow their parent group's color; the finale
     (stop 13) is gold. Same swatches drive chips, stripes, and locks. */
  --tier-color-g1: #84cc16;
  --tier-color-g2: #60a5fa;
  --tier-color-g3: #c084fc;
  --tier-color-finale: #fbbf24;
}

* { box-sizing: border-box; }

a, button, [role="button"] { touch-action: manipulation; }

:focus-visible {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--fg);
  min-height: 100vh;
}

header {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

header h1 { margin: 0; font-size: 1.3rem; }

main { padding: 1.25rem; max-width: 520px; margin: 0 auto; }

.tabs {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
}
.tab {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  padding: 0.5rem 1rem;
  border-radius: 6px;
  cursor: pointer;
}
.tab.active {
  color: var(--fg);
  border-color: var(--accent);
}
.tab-panel { display: none; flex-direction: column; gap: 0.75rem; }
.tab-panel.active { display: flex; }

label {
  display: flex;
  flex-direction: column;
  font-size: 0.9rem;
  color: var(--muted);
  gap: 0.25rem;
}
input {
  padding: 0.6rem 0.75rem;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  color: var(--fg);
  font-size: 1rem;
}

button, .btn {
  padding: 0.7rem 1rem;
  border-radius: 6px;
  border: none;
  background: var(--accent);
  color: white;
  font-weight: 600;
  font-size: 1rem;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
}
button:disabled { opacity: 0.5; cursor: not-allowed; }

.error { color: #ff7070; min-height: 1.2em; margin: 0; font-size: 0.9rem; }

#hunts-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.75rem; }
.hunt-item {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem;
}
.hunt-cover {
  width: 100%;
  height: 140px;
  object-fit: cover;
  border-radius: 7px 7px 0 0;
  margin: -1rem -1rem 0.75rem;
  width: calc(100% + 2rem);
  display: block;
}
.hunt-item-title-row {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-bottom: 0.1rem;
}
.hunt-item h3 { margin: 0; }
.hunt-progress-meta {
  font-size: 0.75rem;
  color: var(--muted);
  white-space: nowrap;
}
.hunt-completed-badge { color: #a3e635; font-weight: 600; }
.hunt-item .meta { color: var(--muted); font-size: 0.85rem; margin-bottom: 0.5rem; }
.hunt-item-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.5rem;
}
.start-over-link {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 0.8rem;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
  text-decoration-style: dotted;
}
.start-over-link:hover { color: var(--fg); }
.hunt-item .progress-bar {
  height: 6px;
  background: rgba(255,255,255,0.08);
  border-radius: 3px;
  overflow: hidden;
  margin: 0.5rem 0;
}
.hunt-item .progress-bar > div {
  height: 100%;
  background: var(--accent-2);
}

/* ---------- City picker ---------- */
.city-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 1rem;
}
.city-btn {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
}
.city-btn.active {
  color: var(--fg);
  border-color: var(--accent-2);
  background: rgba(79, 195, 247, 0.1);
}

/* ---------- Site nav ---------- */
.site-nav {
  background: rgba(10, 15, 35, 0.95);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 100;
  backdrop-filter: blur(8px);
  /* When saved as a standalone PWA on iOS, the status bar (time, signal,
     battery) overlaps position:sticky content at top:0. Pad the nav so
     the hamburger menu and brand text sit below the notch / status bar. */
  padding-top: env(safe-area-inset-top, 0);
}
.site-nav-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0.6rem 1rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.site-nav-brand {
  font-weight: 700;
  color: var(--fg);
  text-decoration: none;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
}
/* Hamburger toggle in the top bar */
.site-nav-toggle {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  width: 44px;
  height: 44px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.site-nav-toggle:hover { border-color: var(--accent-2); }
.site-nav-toggle:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }
.site-nav-bars,
.site-nav-bars::before,
.site-nav-bars::after {
  display: block;
  width: 18px;
  height: 2px;
  background: var(--fg);
  border-radius: 2px;
  content: "";
  position: relative;
}
.site-nav-bars::before { position: absolute; top: -6px; left: 0; }
.site-nav-bars::after  { position: absolute; top:  6px; left: 0; }

/* Drawer — off-canvas panel + scrim. Sits above every sticky/fixed
   element on the page so the open drawer never looks like it's
   layering under the top nav or leaking page content through. */
.site-drawer {
  position: fixed;
  inset: 0;
  z-index: 1000;
}
.site-drawer[hidden] { display: none; }
.site-drawer-scrim {
  position: absolute;
  inset: 0;
  /* Fully opaque by design. The structural body.drawer-open rule below
     is the backstop that hides page content even if this alpha is ever
     lowered, so leaking content through a translucent scrim is no
     longer a regression risk — but a fully opaque scrim is still the
     intended visual: the drawer is a navigation modal, not a frosted
     overlay. Don't lower this without a deliberate UX decision. */
  background: rgba(0, 0, 0, 1);
  opacity: 0;
  transition: opacity 200ms ease;
}
/* Stop the body from scrolling while the drawer is open. Toggled by JS.
   Belt-and-suspenders: hide every top-level body child except the nav
   (which contains the drawer itself) and the toast container, so any
   fixed-position UI rendered by page scripts (camera overlays,
   completed-hunt modals, etc.) can't leak through. This is structural
   rather than per-element so a new page can't regress the overlay by
   forgetting to wrap content in <main>. */
body.drawer-open { overflow: hidden; }
body.drawer-open > *:not(#site-nav):not(.toast-container) {
  visibility: hidden;
}
body.camera-open { overflow: hidden; }
.site-drawer.open .site-drawer-scrim { opacity: 1; }
.site-drawer-panel {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: min(280px, 80vw);
  background: #0a0f23;
  border-right: 1px solid var(--border);
  padding: max(1rem, env(safe-area-inset-top, 1rem)) 1.1rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  transform: translateX(-100%);
  transition: transform 200ms ease;
}
.site-drawer.open .site-drawer-panel { transform: translateX(0); }
.site-drawer-close {
  align-self: flex-end;
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 1.5rem;
  line-height: 1;
  padding: 0.5rem 0.6rem;
  cursor: pointer;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.site-drawer-close:hover { color: var(--fg); }
.site-drawer-close:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }
/* Primary affordances: Home + Leaderboard. Two accent-tinted card
   buttons at the top of the drawer, identical visual weight, so the
   app's two main destinations are reachable in one tap. Icons sit in
   a small circular badge so the glyph reads cleanly at all sizes. */
.site-drawer-primary {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 0.25rem;
  margin-bottom: 0.4rem;
}
.site-drawer-primary-link {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.8rem 0.9rem;
  border-radius: 12px;
  background: rgba(79,195,247,0.10);
  border: 1px solid rgba(79,195,247,0.35);
  color: var(--fg);
  text-decoration: none;
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  min-height: 52px;
  transition: background 150ms ease, border-color 150ms ease, transform 100ms ease;
}
.site-drawer-primary-link:hover {
  background: rgba(79,195,247,0.18);
  border-color: var(--accent-2);
}
.site-drawer-primary-link:active { transform: scale(0.99); }
.site-drawer-primary-link.active {
  background: rgba(79,195,247,0.24);
  border-color: var(--accent-2);
}
.site-drawer-primary-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(79,195,247,0.18);
  font-size: 1.15rem;
  line-height: 1;
  flex-shrink: 0;
}
.site-drawer-primary-label { line-height: 1.1; }

/* Secondary submenu: My Account / Request a Custom Hunt / Contact Us.
   Smaller text, softer color, set apart from the primary buttons with
   a "More" label so the visual hierarchy is unambiguous. */
.site-drawer-submenu {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--border);
}
.site-drawer-submenu-label {
  color: var(--muted);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0 0.7rem 0.25rem;
}
.site-drawer-sublinks {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.site-drawer-sublink {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.85rem;
  padding: 0.55rem 0.7rem;
  border-radius: 6px;
  display: flex;
  align-items: center;
  min-height: 40px;
}
.site-drawer-sublink:hover { color: var(--fg); background: rgba(255,255,255,0.05); }
.site-drawer-sublink.active { color: var(--fg); background: rgba(79,195,247,0.12); }

.site-drawer-auth {
  margin-top: auto;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  font-size: 0.85rem;
}
.site-drawer-user { color: var(--muted); }
.site-drawer-user strong { color: var(--accent-2); font-weight: 600; }

@media (max-width: 520px) {
  .site-nav-inner { padding: 0.5rem 0.75rem; gap: 0.5rem; }
  .site-nav-brand { font-size: 0.95rem; }
}

/* ---------- State/Hunts index pages ---------- */
.state-section {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem 1.15rem;
  margin-bottom: 1rem;
}
.state-section h2 {
  margin: 0 0 0.5rem;
  font-size: 1.05rem;
}
.state-section h2 a {
  color: var(--accent-2);
  text-decoration: none;
}
.state-section h2 a:hover { text-decoration: underline; }
.state-hunt-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.state-hunt-list li a {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 0.75rem;
  border-radius: 6px;
  color: var(--fg);
  text-decoration: none;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
}
.state-hunt-list li a:hover { border-color: var(--accent-2); }
.state-hunt-list .hunt-city {
  color: var(--muted);
  font-size: 0.8rem;
}

/* ---------- Hunt detail page ---------- */
.hunt-detail-hero {
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 1rem;
}
.hunt-detail-cover {
  width: 100%;
  max-height: 220px;
  object-fit: cover;
  display: block;
}
.hunt-detail-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1rem;
  color: var(--muted);
  font-size: 0.88rem;
  margin: 0.35rem 0 0.75rem;
}
.hunt-detail-description {
  white-space: pre-wrap;
  line-height: 1.55;
  margin-bottom: 1rem;
}
#hunt-detail-map {
  height: 320px;
  border-radius: 10px;
  border: 1px solid var(--border);
  overflow: hidden;
  margin-bottom: 1rem;
}
.hunt-detail-actions {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 1rem;
}
.hunt-detail-actions .btn-secondary { background: transparent; }

/* ---------- Landing geo prompt ---------- */
.geo-prompt {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem;
  margin-bottom: 1rem;
  text-align: center;
}
.geo-prompt h3 { margin: 0 0 0.4rem; font-size: 1rem; }
.geo-prompt p { margin: 0 0 0.75rem; color: var(--muted); font-size: 0.9rem; }
.geo-prompt .button-row { justify-content: center; }

/* ---------- Hunt page ---------- */
.hunt-body { overflow: hidden; }

/* Camera is now scoped inside .camera-overlay (opt-in AR pop-out).
   The bare <video id="camera"> at body-root is gone; these rules
   apply to the overlay-embedded video. */
.camera-overlay .camera-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
}
.camera-fallback {
  /* Shown inside .camera-overlay when getUserMedia fails. Sits beneath
     the AR elements so the close button and compass remain interactive. */
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, #0b1020 0%, #1a2548 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  padding: 1.5rem;
  text-align: center;
  z-index: 1;
}
.camera-fallback[hidden] { display: none !important; }

#overlay {
  position: fixed;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  /* Only apply top safe-area padding here. The bottom safe-area is moved
     onto `.clue-card` (which is now the scroll container) so its last
     scrollable item (DNF button, issue-panel submit) can actually reach
     the visible bottom edge above the iOS home indicator. */
  padding: env(safe-area-inset-top, 0) 0 0 0;
  pointer-events: none;
}

.hunt-header {
  background: rgba(0,0,0,0.5);
  color: white;
  padding: 0.75rem 1rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  pointer-events: auto;
}
.hunt-header .back {
  color: white;
  text-decoration: none;
  font-size: 0.95rem;
  font-weight: 600;
  padding: 0.35rem 0.65rem;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.12);
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  line-height: 1;
  white-space: nowrap;
}
.hunt-header .back:hover { background: rgba(255, 255, 255, 0.22); }
.hunt-header .back span { font-size: 1.1rem; }

.clue-card {
  margin-top: auto;
  background: linear-gradient(180deg,
    rgba(15, 22, 48, 0.94) 0%,
    rgba(11, 16, 32, 0.96) 100%);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -18px 48px -16px rgba(0, 0, 0, 0.6);
  /* Bottom padding includes env(safe-area-inset-bottom) so the last
     scrollable element (DNF button, issue-panel submit) stays above the
     iOS home indicator. */
  padding: 1rem 1.25rem calc(1.25rem + env(safe-area-inset-bottom, 0));
  pointer-events: auto;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  /* Card is its own scroll region: caps height so growing content
     (multiple hints, expanded issue panel) can scroll within rather
     than push other chrome off-screen. Fallback vh for iOS <15.4;
     dvh for modern (dynamic-chrome-aware) browsers. */
  max-height: 70vh;
  max-height: min(70dvh, calc(100dvh - 120px));
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
}
.clue-card h2 { margin: 0.25rem 0 0.5rem; }

/* Hero clue text — the single most important piece of information on
   the page. Generous line-height + slightly up-weighted for readability
   in daylight on a phone. */
.clue-hero {
  margin: 0.5rem 0 0.75rem;
  font-size: 1.08rem;
  line-height: 1.55;
  color: var(--fg);
  letter-spacing: 0.005em;
}
.stop-label {
  color: var(--accent-2);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
}
.stop-label .difficulty {
  letter-spacing: 0.05em;
  color: #f5b700;
  font-size: 0.95rem;
}
.difficulty-pair {
  display: inline-flex;
  gap: 0.75rem;
  align-items: flex-start;
}
.difficulty-terrain {
  color: #a3e635;
  font-size: 0.75rem;
}
/* Labeled difficulty chip — stacks a small "Puzzle" / "Terrain" caption
   above the star/dot symbols so a first-time player can tell what the
   indicators mean at a glance (prior UI showed only the symbols + an
   invisible aria-label). */
.difficulty-chip {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1;
  gap: 0.15rem;
}
.difficulty-chip-label {
  font-size: 0.58rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
/* Accuracy-only muted line inside the clue card. (Replaces .distance-row —
   distance is now shown on the AR compass and the arrive-btn CTA, so the
   in-card duplicate was removed.) */
.accuracy-row {
  display: flex;
  justify-content: center;
  color: var(--muted);
  font-size: 0.8rem;
  margin: 0.5rem 0 0.75rem;
  letter-spacing: 0.02em;
}

/* Quiet text-link footer for secondary actions (Start over · Issue).
   Replaces a second full-width button-row that competed visually with
   the primary CTA row above it. */
.secondary-links {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.25rem;
  margin-top: 0.85rem;
  font-size: 0.82rem;
}
.secondary-links .linkish {
  background: transparent;
  border: 0;
  color: var(--muted);
  padding: 0.25rem 0.4rem;
  cursor: pointer;
  font-size: inherit;
  font-family: inherit;
  text-decoration: underline;
  text-decoration-color: rgba(255, 255, 255, 0.18);
  text-underline-offset: 3px;
}
.secondary-links .linkish:hover,
.secondary-links .linkish:focus-visible {
  color: var(--fg);
  text-decoration-color: var(--muted);
}
.secondary-links .sep {
  color: rgba(255, 255, 255, 0.25);
  user-select: none;
}

/* ---------- GPS quality banner ---------- */
.gps-quality {
  margin: 0.4rem 0 0.6rem;
  padding: 0.45rem 0.65rem;
  border-radius: 6px;
  font-size: 0.82rem;
  line-height: 1.3;
}
.gps-quality--weak {
  background: rgba(245, 183, 0, 0.12);
  border: 1px solid rgba(245, 183, 0, 0.45);
  color: #f5b700;
}
.gps-quality--bad {
  background: rgba(255, 112, 112, 0.12);
  border: 1px solid rgba(255, 112, 112, 0.5);
  color: #ff9a9a;
}

/* ---------- Album (post-hunt keepsake) ---------- */
.album-main {
  max-width: 900px;
  margin: 0 auto;
  padding: 1.5rem 1.25rem 3rem;
}
.album-hero h1 {
  margin: 0 0 0.25rem;
  font-size: 2rem;
  letter-spacing: -0.01em;
}
.album-subtitle {
  color: var(--muted);
  margin: 0 0 1rem;
}
.album-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 0.75rem;
  margin: 0.5rem 0 1rem;
  padding: 0;
}
.album-stats dt {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.album-stats dd {
  margin: 0.15rem 0 0;
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--accent-2);
}
.album-actions {
  display: flex;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}
.album-actions .btn-secondary {
  padding: 0.7rem 1rem;
  border-radius: 8px;
  text-decoration: none;
}
#album-map {
  height: 320px;
  border-radius: 10px;
  border: 1px solid var(--border);
  overflow: hidden;
  margin: 0.5rem 0 1.5rem;
}
#album-photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 1rem;
}
.album-photo {
  margin: 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.album-photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
}
.album-photo figcaption {
  padding: 0.7rem 0.85rem;
}
.album-photo strong { display: block; margin-bottom: 0.25rem; }
.album-photo p {
  margin: 0;
  font-size: 0.85rem;
  color: var(--muted);
  line-height: 1.45;
}

/* ---------- Projected board ----------
 * TV/projector first, phone-tolerant. Type and photo-tile sizes use
 * clamp() so a 55" TV at 10 feet gets ~3x the scale of a laptop at
 * arm's length without a separate breakpoint matrix. Max values are
 * tuned for a 1920×1080 projector; min values keep the page usable
 * on a host's phone while they pull up the URL.
 */
.board-body {
  margin: 0;
  background: radial-gradient(circle at top, #14203e 0%, #070b1c 80%);
  color: var(--fg);
  min-height: 100vh;
  overflow-x: hidden;
}
.board-main {
  max-width: 1600px;
  margin: 0 auto;
  padding: clamp(1rem, 2.5vw, 2.5rem) clamp(1rem, 3vw, 3rem);
}
.board-header {
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
  margin-bottom: clamp(1rem, 2vw, 2rem);
  flex-wrap: wrap;
}
.board-header h1 {
  margin: 0;
  font-size: clamp(2rem, 6vw, 5.5rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.05;
}
.board-subtitle {
  color: var(--muted);
  font-size: clamp(0.95rem, 1.4vw, 1.4rem);
  text-transform: uppercase;
  letter-spacing: 0.12em;
}
.board-grid {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: clamp(1rem, 2.5vw, 2.5rem);
}
@media (max-width: 900px) {
  .board-grid { grid-template-columns: 1fr; }
}
.board-leaderboard-wrap h2,
.board-photos-wrap h2 {
  font-size: clamp(0.9rem, 1.2vw, 1.4rem);
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--muted);
  margin: 0 0 0.8rem;
}
.board-leaderboard {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(0.5rem, 0.9vw, 1rem);
}
.board-lb-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: clamp(0.6rem, 1.2vw, 1.5rem);
  padding: clamp(0.65rem, 1.1vw, 1.25rem) clamp(0.9rem, 1.4vw, 1.6rem);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border);
  border-radius: 12px;
  font-size: clamp(1.2rem, 2.2vw, 2.8rem);
  font-weight: 600;
}
.board-lb-row:nth-child(1) {
  background: linear-gradient(90deg, rgba(245, 183, 0, 0.22), rgba(245, 183, 0, 0.05));
  border-color: rgba(245, 183, 0, 0.55);
}
.board-lb-rank {
  font-size: clamp(1rem, 1.8vw, 2.2rem);
  color: var(--muted);
  min-width: 2ch;
}
.board-lb-row:nth-child(1) .board-lb-rank { color: #f5b700; }
.board-lb-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.board-lb-score {
  font-variant-numeric: tabular-nums;
  color: var(--accent-2);
}
.board-photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(clamp(140px, 14vw, 260px), 1fr));
  gap: clamp(0.5rem, 0.9vw, 1rem);
}
.board-photo-tile {
  margin: 0;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.board-photo-tile img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
}
.board-photo-tile figcaption {
  padding: 0.5rem 0.7rem;
  font-size: 0.78rem;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.board-photo-tile strong { color: var(--fg); }
.board-photo-tile span { color: var(--muted); }
.board-footer {
  margin-top: 1.5rem;
  text-align: right;
  color: var(--muted);
  font-size: 0.85rem;
  letter-spacing: 0.06em;
}
.board-empty {
  color: var(--muted);
  padding: 1rem;
}

/* ---------- Stop issue / DNF panel ---------- */
.stop-issue-panel {
  margin-top: 0.5rem;
  padding: 0.75rem;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.stop-issue-label {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  margin-bottom: 0.4rem;
}
.stop-issue-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.stop-issue-buttons button {
  flex: 1 1 auto;
  min-width: max-content;
}
.stop-issue-buttons button.active {
  border-color: var(--accent-2);
  color: var(--fg);
  background: rgba(79, 195, 247, 0.12);
}

/* ---------- Reveal bottom sheet ---------- */
/* The reveal slides up from the bottom so the camera stays visible above it. */
.reveal-modal {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  pointer-events: auto;
  z-index: 5;
}
.reveal-inner {
  background: rgba(11, 16, 40, 0.97);
  border-top: 1px solid var(--border);
  border-radius: 16px 16px 0 0;
  padding: 0.75rem 1.25rem env(safe-area-inset-bottom, 1.25rem);
  max-height: 72vh;
  overflow-y: auto;
  animation: slideUp 0.32s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
@keyframes slideUp {
  from { transform: translateY(100%); opacity: 0.6; }
  to   { transform: translateY(0);    opacity: 1;   }
}
.bottom-sheet-handle {
  width: 36px;
  height: 4px;
  background: rgba(255,255,255,0.18);
  border-radius: 2px;
  margin: 0 auto 0.85rem;
}
/* Frozen discovery animation inside the reveal card. Sized generously
   so kids can savor the payoff without the camera-overlay detour.
   Position relative so the absolute-positioned fallback emoji inside
   anchors to this box. */
.reveal-discovery {
  position: relative;
  width: 280px;
  height: 280px;
  max-width: 60vw;
  max-height: 60vw;
  margin: 0 auto 0.5rem;
  pointer-events: none;
}
.reveal-discovery[hidden] { display: none !important; }
.reveal-badge {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: #a3e635;
  margin-bottom: 0.2rem;
}
.reveal-inner h2 {
  margin: 0 0 0.65rem;
  color: var(--fg);
  font-size: 1.3rem;
  line-height: 1.2;
}
.reveal-image {
  width: 100%;
  max-height: 180px;
  object-fit: cover;
  border-radius: 8px;
  margin-bottom: 0.75rem;
}

/* ---------- Next clue preview (in reveal sheet) ---------- */
.next-clue-preview {
  margin-top: 1rem;
  padding: 0.75rem;
  background: rgba(79,195,247,0.07);
  border: 1px solid rgba(79,195,247,0.2);
  border-radius: 8px;
}
.next-clue-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent-2);
  margin-bottom: 0.35rem;
}
.next-clue-text {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--fg);
}

/* ---------- Completion modal (full-screen, hunt is done) ---------- */
.completed-modal {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.88);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  pointer-events: auto;
  z-index: 150;
}
/* The `display: flex` above has the same specificity as the UA `[hidden]`
   rule, so setting `hidden=true` alone doesn't hide the modal — it stays
   painted over the clue card on every /hunt.html load. Force display:none
   when the attribute is present. Mirrors the fix for .intro-screen below. */
.completed-modal[hidden] { display: none !important; }
.completed-inner {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.5rem;
  max-width: 400px;
  width: 100%;
  text-align: center;
  animation: popIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
  max-height: calc(100vh - 2.5rem);
  max-height: calc(100dvh - 2.5rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}
@keyframes popIn {
  from { opacity: 0; transform: scale(0.9); }
  to   { opacity: 1; transform: scale(1); }
}
.completed-inner h2 { margin-top: 0; color: var(--accent-2); }

/* ---------- AR compass overlay ---------- */
.ar-compass {
  position: absolute;
  top: 20%;
  left: 50%;
  transform: translateX(-50%);
  width: 160px;
  height: 160px;
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
  filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.5));
}
/* `.ar-compass { display: flex }` has equal specificity to the UA
   `[hidden] { display: none }`. Without this override the compass overlay
   is painted on every /hunt.html load before renderClue() runs.
   Same pattern as .completed-modal / .intro-screen. */
.ar-compass[hidden] { display: none !important; }
/* Suppresses the compass during close-range mode (<= 75 ft) without
   touching the `hidden` attribute, which the user pref + iOS
   permission flow owns. Toggled by hunt.js updateDistance(). */
.ar-compass.compass-close-range { display: none !important; }
.ar-arrow {
  width: 100%;
  height: 100%;
  transition: transform 120ms linear;
  transform-origin: 50% 50%;
}
.ar-compass .ar-ring {
  fill: rgba(0, 0, 0, 0.35);
  stroke: rgba(255, 255, 255, 0.5);
  stroke-width: 2;
}
.ar-compass .ar-distance {
  margin-top: 0.35rem;
  font-weight: 700;
  font-size: 1.05rem;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
}
.ar-compass.within-range .ar-ring {
  fill: rgba(40, 200, 100, 0.35);
  stroke: rgba(120, 255, 160, 0.9);
  animation: ar-pulse 1.1s ease-in-out infinite;
}
.ar-compass.within-range .ar-arrow {
  transform: rotate(0deg) scale(0.9) !important;
}
@keyframes ar-pulse {
  0%, 100% { stroke-width: 2; transform: scale(1); }
  50% { stroke-width: 5; transform: scale(1.08); }
}

/* Close-range proximity ring — replaces the compass arrow at <= 75 ft
   (see hunt.js:updateDistance). Three concentric rings shrink on a
   2.4s loop at staggered phases so there's always one visible. Color
   is driven by the existing proximity-* tier classes (warm/hot/etc)
   via the --ring-color CSS var. Medium speed per the feature request. */
.ar-proximity-ring {
  position: absolute;
  top: 20%;
  left: 50%;
  transform: translateX(-50%);
  width: 200px;
  height: 200px;
  z-index: 3;
  pointer-events: none;
  --ring-color: rgba(245, 183, 0, 0.85);
}
.ar-proximity-ring[hidden] { display: none !important; }
.ar-proximity-ring .proximity-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 4px solid var(--ring-color);
  box-shadow: 0 0 20px var(--ring-color);
  animation: proximity-ring-shrink 2.4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  opacity: 0;
}
.ar-proximity-ring .proximity-ring--1 { animation-delay: 0s; }
.ar-proximity-ring .proximity-ring--2 { animation-delay: 0.8s; }
.ar-proximity-ring .proximity-ring--3 { animation-delay: 1.6s; }
.proximity-ring-dist {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 1.4rem;
  color: #fff;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.95);
  pointer-events: none;
}
@keyframes proximity-ring-shrink {
  0%   { transform: scale(1.0);  opacity: 0.95; }
  70%  { opacity: 0.6; }
  100% { transform: scale(0.18); opacity: 0; }
}
/* Heat color tiers — piggyback on the existing proximity-* classes
   so ProximityAudio's tier output maps directly to ring color. */
.ar-proximity-ring.proximity-approaching { --ring-color: rgba(79, 195, 247, 0.8); }
.ar-proximity-ring.proximity-near        { --ring-color: rgba(160, 230, 120, 0.9); }
.ar-proximity-ring.proximity-warm        { --ring-color: rgba(255, 152, 0, 0.95); }
.ar-proximity-ring.proximity-hot         { --ring-color: rgba(233, 79, 55, 1); }

/* On-device debug panel — only shown when ?debug=1 is in the URL.
   Tiny text; sits in the top-left safe area of the camera overlay. */
.ar-debug-panel {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 72px);
  left: 8px;
  max-width: 60vw;
  padding: 0.35rem 0.5rem;
  background: rgba(0, 0, 0, 0.65);
  color: #a3e635;
  font: 500 10px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace;
  border-radius: 6px;
  z-index: 7;
  pointer-events: none;
  white-space: pre-wrap;
}
.ar-debug-panel[hidden] { display: none !important; }

/* ---------- Hint popup modal ---------- */
/* Tap Hint 1 / Hint 2 to open a simple popup with the hint text. Close
   and reopen at will — no penalty on reopen (first-reveal is cached
   client-side). The buttons stay visible regardless of state so the
   player can use them as a reminder. */
.hint-modal {
  position: fixed;
  inset: 0;
  z-index: 85;                 /* above map-reveal (80), below completion */
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  pointer-events: auto;
}
.hint-modal[hidden] { display: none !important; }
.hint-modal-inner {
  position: relative;
  background: var(--card);
  width: 100%;
  max-width: 420px;
  border-radius: 14px;
  border: 1px solid rgba(245, 183, 0, 0.4);
  padding: 1.25rem 1.25rem 1.1rem;
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.7);
  animation: hint-modal-pop 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
@keyframes hint-modal-pop {
  from { transform: scale(0.96); opacity: 0; }
  to   { transform: scale(1);    opacity: 1; }
}
.hint-modal-title {
  margin: 0 0 0.5rem;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: #f5b700;
  font-weight: 700;
}
.hint-modal-body {
  margin: 0;
  color: #f7dc7a;
  font-size: 1rem;
  line-height: 1.45;
  white-space: pre-wrap;
}
.hint-modal-close {
  position: absolute;
  top: 0.4rem;
  right: 0.55rem;
  background: transparent;
  border: none;
  color: var(--fg);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.5rem 0.6rem;
  border-radius: 6px;
  opacity: 0.75;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.hint-modal-close:hover { opacity: 1; background: rgba(255, 255, 255, 0.06); }
.hint-modal-close:focus-visible {
  outline: 2px solid #f5b700;
  outline-offset: 2px;
  opacity: 1;
}

/* Hint buttons sit in a single row so Hint 1 and Hint 2 don't each
   consume a full column line inside .help-tiers. */
.hint-row {
  display: flex;
  gap: 0.4rem;
}
.hint-row > .pill { flex: 1 1 0; }

.button-row {
  display: flex;
  gap: 0.5rem;
  align-items: stretch;
}
.button-row > * { flex: 1; }
.btn-secondary {
  background: transparent;
  color: var(--accent-2);
  border: 1px solid var(--accent-2);
  padding: 0.65rem 0.9rem;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
}
.btn-secondary:hover { background: rgba(255, 255, 255, 0.05); }

/* ---------- Hunt header progress bar ---------- */
.hunt-header-center {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.hunt-progress-bar {
  height: 4px;
  background: rgba(255,255,255,0.15);
  border-radius: 2px;
  overflow: hidden;
  width: 100%;
}
.hunt-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent-2), #a3e635);
  border-radius: 2px;
  transition: width 0.6s ease;
}

/* ---------- Mini-map overlay ---------- */
.mini-map-wrap {
  position: absolute;
  top: 70px;
  right: 12px;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid rgba(255,255,255,0.35);
  box-shadow: 0 4px 16px rgba(0,0,0,0.6);
  pointer-events: none;
  z-index: 2;
}
#mini-map {
  width: 100%;
  height: 100%;
}
/* Leaflet tile layer gets pointer-events for panning — disabled in map init */
.mini-map-wrap .leaflet-container {
  background: #1a2548;
}
.map-player-dot {
  width: 12px;
  height: 12px;
  background: #4fc3f7;
  border: 2px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 6px rgba(79,195,247,0.8);
}
.map-target-pin {
  width: 16px;
  height: 16px;
  background: var(--accent);
  border: 2px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 8px rgba(233,79,55,0.9);
}

/* ---------- Asset discovery section ---------- */
.asset-discovery-section {
  margin: 0.85rem 0 0.75rem;
  padding: 0.75rem;
  background: rgba(156,39,176,0.08);
  border: 1px solid rgba(156,39,176,0.25);
  border-radius: 8px;
}
/* First-encounter glow-up: warmer gradient + animated golden border so
   the kid SEES this is special. Animation runs once, then sits — per
   CLAUDE.md "rewards should linger, not flash". */
.asset-discovery-section.is-new-discovery {
  background: linear-gradient(135deg, rgba(255,193,7,0.18) 0%, rgba(156,39,176,0.18) 100%);
  border-color: #ffb300;
  box-shadow: 0 0 12px rgba(255,193,7,0.35);
  animation: asset-new-glow 2.5s ease-out 1;
}
@keyframes asset-new-glow {
  0%   { box-shadow: 0 0 0 rgba(255,193,7,0); transform: scale(0.96); }
  30%  { box-shadow: 0 0 24px rgba(255,193,7,0.7); transform: scale(1.02); }
  100% { box-shadow: 0 0 12px rgba(255,193,7,0.35); transform: scale(1); }
}
.asset-discovery-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}
.asset-discovery-label {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: #9c27b0;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: 1;
  min-width: 0;
}
.is-new-discovery .asset-discovery-label {
  color: #ffb300;
}
.asset-new-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.6rem;
  background: linear-gradient(90deg, #ffb300, #ff7043);
  color: #1a0f00;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  border-radius: 999px;
  text-transform: uppercase;
  box-shadow: 0 2px 8px rgba(255,179,0,0.4);
  animation: asset-new-pulse 1.4s ease-in-out infinite;
}
.asset-new-badge-spark {
  display: inline-block;
  font-size: 0.85rem;
  animation: asset-new-spark 1.4s ease-in-out infinite alternate;
}
@keyframes asset-new-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.08); }
}
@keyframes asset-new-spark {
  0%   { transform: rotate(-12deg) scale(1); }
  100% { transform: rotate(12deg) scale(1.15); }
}
.asset-encounters-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.55rem;
  background: rgba(255,255,255,0.08);
  color: var(--fg-secondary);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  border-radius: 999px;
  border: 1px solid var(--border);
}
.asset-discovery-card {
  text-align: left;
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
}
.asset-discovery-text {
  flex: 1;
  min-width: 0;
}
.asset-card-live-preview {
  flex-shrink: 0;
  width: 96px;
  height: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,0.04);
  border-radius: 10px;
  overflow: hidden;
}
.asset-card-live-fallback {
  font-size: 2.6rem;
  line-height: 1;
}
/* On legendary first-time finds, the preview gets a soft golden halo so
   the eye lands on the creature before the text. Subtle — not a pop-up. */
.is-new-discovery .asset-card-live-preview {
  background: radial-gradient(circle at center, rgba(255,193,7,0.22) 0%, rgba(255,193,7,0) 70%);
  box-shadow: 0 0 0 1px rgba(255,193,7,0.35);
}
@media (max-width: 380px) {
  .asset-discovery-card {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }
  .asset-discovery-text { width: 100%; }
}
.asset-name {
  margin: 0 0 0.35rem;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--fg);
}
.asset-description {
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
  color: var(--fg-secondary);
  line-height: 1.4;
}
.asset-attributes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.4rem;
  font-size: 0.8rem;
}
.asset-attribute {
  padding: 0.35rem 0.5rem;
  background: rgba(156,39,176,0.12);
  border-radius: 4px;
  color: var(--fg-secondary);
}
.asset-attribute-label {
  font-weight: 600;
  color: #9c27b0;
  text-transform: capitalize;
}

/* ---------- Photo challenge section ---------- */
.photo-challenge-section {
  margin: 0.85rem 0 0.75rem;
  padding: 0.75rem;
  background: rgba(79,195,247,0.08);
  border: 1px solid rgba(79,195,247,0.25);
  border-radius: 8px;
  text-align: left;
}
.photo-challenge-label {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--accent-2);
  margin-bottom: 0.3rem;
}
.photo-challenge-prompt {
  margin: 0 0 0.6rem;
  font-size: 0.9rem;
  color: var(--fg);
  line-height: 1.4;
}
.photo-preview-wrap {
  margin-bottom: 0.6rem;
}
.photo-preview {
  width: 100%;
  max-height: 160px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--border);
  display: block;
  margin-bottom: 0.35rem;
}
.photo-status {
  font-size: 0.8rem;
  color: var(--muted);
}
.photo-status-ok { color: #a3e635; }
.photo-status-error { color: #ff7070; }

/* ---------- Confetti canvas ---------- */
.confetti-canvas {
  position: fixed;
  inset: 0;
  /* Inside #overlay stacking context. Above .camera-overlay (60),
     .map-reveal-modal (80), .hint-modal (85) so confetti rains over
     the AR view + reveal sheet — but below .completed-modal (150)
     so the trophy still wins on hunt completion. */
  z-index: 140;
  pointer-events: none;
}

/* ---------- Completion summary stats ---------- */
.summary-stats {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 1rem;
  margin: 1rem 0 1.25rem;
  text-align: left;
  font-size: 0.95rem;
}
.summary-stats dt {
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 0.75rem;
  padding-top: 0.2rem;
}
.summary-stats dd {
  margin: 0;
  color: var(--accent-2);
  font-weight: 600;
}

/* ---------- Standalone pages (leaderboard) ---------- */
.page-body { padding-bottom: 3rem; }
.page-header {
  padding: max(1rem, env(safe-area-inset-top, 1rem)) 1.25rem 1rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 1rem;
}
.page-header h1 { margin: 0; font-size: 1.25rem; }
.page-header .back {
  color: var(--accent-2);
  text-decoration: none;
  font-weight: 600;
}
/* Right-aligned nav cluster + user-id span rendered by renderPageHeader().
   Inline margin-left is set per-element by the helper (auto on the first,
   then .75rem) so the cluster pushes to the right edge and the items
   stack tightly. Color/size live here so future tweaks don't require
   touching the JS. */
.page-header-link {
  font-size: 0.85rem;
  color: var(--accent, #4a9eff);
  text-decoration: none;
}
.page-header-user {
  font-size: 0.85rem;
}
.page-main {
  padding: 1.25rem;
  max-width: 720px;
  margin: 0 auto;
}
.muted { color: var(--muted); }

.leaderboard {
  width: 100%;
  border-collapse: collapse;
  margin-top: 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.leaderboard th,
.leaderboard td {
  padding: 0.6rem 0.85rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.leaderboard th {
  background: rgba(255, 255, 255, 0.04);
  color: var(--muted);
  text-transform: uppercase;
  font-size: 0.75rem;
  letter-spacing: 0.06em;
}
.leaderboard tr:last-child td { border-bottom: none; }
.leaderboard tr:nth-child(1) td:first-child { color: #f5b700; font-weight: 700; }

.table-scroll-wrap {
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--card);
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  margin-top: 1rem;
}
.table-scroll-wrap > .leaderboard {
  border: none;
  border-radius: 0;
  overflow: visible;
  margin-top: 0;
  background: transparent;
}

/* ---------- Leaderboard index (hunt picker) ---------- */
.lb-hunt-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.lb-hunt-item a {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.75rem 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--fg);
  text-decoration: none;
  transition: border-color 0.15s;
}
.lb-hunt-item a:hover,
.lb-hunt-item a:focus-visible {
  border-color: var(--accent-2);
}
.lb-hunt-item .muted {
  font-size: 0.85rem;
}

/* ---------- Community stats dashboard (leaderboard redesign) ---------- */
.lb-community-stats {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 0.75rem;
  margin: 0.25rem 0 1.5rem;
}

.lb-stat-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.85rem 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  text-align: center;
}

.lb-stat-number {
  font-size: clamp(1.5rem, 4vw, 2.25rem);
  font-weight: 700;
  color: var(--accent-2);
  line-height: 1;
}

.lb-stat-label {
  font-size: 0.72rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.lb-records {
  margin: 0 0 1.5rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

.lb-records-heading {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  margin: 0.75rem 1rem 0.5rem;
}

.lb-record-row {
  display: grid;
  grid-template-columns: 2rem 1fr auto;
  align-items: center;
  gap: 0.6rem;
  padding: 0.65rem 1rem;
  border-top: 1px solid var(--border);
  font-size: 0.9rem;
}

.lb-record-icon {
  font-size: 1.3rem;
  text-align: center;
}

.lb-record-label {
  color: var(--muted);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.lb-record-value {
  font-weight: 600;
  color: var(--fg);
  text-align: right;
  font-size: 0.88rem;
}

.lb-section-heading {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  margin: 0 0 0.5rem;
}

/* Neutralise the gold rank-#1 highlight — player table has no rank column. */
.lb-players tr:nth-child(1) td:first-child {
  color: inherit;
  font-weight: inherit;
}

/* ---------- Profile page ---------- */
.profile-card {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.25rem;
  margin-bottom: 1.25rem;
}
.avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--accent);
  color: white;
  font-size: 1.5rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.profile-info { flex: 1; min-width: 0; }
.profile-info h2 { margin: 0 0 0.2rem; font-size: 1.2rem; }
.profile-info p { margin: 0.15rem 0; font-size: 0.88rem; }
.profile-logout-btn { flex-shrink: 0; align-self: center; }

.stats-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}
.stat-box {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.85rem 0.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
}
.stat-value {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--accent-2);
}
.stat-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

/* ---------- Achievements strip ---------- */
.achievements-section {
  margin-bottom: 1.75rem;
}
.achievements-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.65rem;
}
.achievements-header .section-heading { margin: 0; }
.achievements-count {
  font-size: 0.78rem;
  font-weight: 700;
  color: #ffb300;
}
.achievements-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 0.55rem;
}
.achievement-badge {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.65rem 0.7rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.achievement-badge.is-earned {
  border-color: rgba(255,193,7,0.55);
  background: linear-gradient(180deg, var(--card) 0%, rgba(255,193,7,0.06) 100%);
}
.achievement-badge.is-earned:hover { transform: translateY(-1px); }
.achievement-badge.is-locked {
  filter: grayscale(0.6);
  opacity: 0.65;
}
.achievement-icon {
  font-size: 1.7rem;
  line-height: 1;
  flex-shrink: 0;
  filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
}
.achievement-body {
  flex: 1;
  min-width: 0;
}
.achievement-title {
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--fg);
}
.is-earned .achievement-title { color: #ffb300; }
.achievement-desc {
  font-size: 0.7rem;
  color: var(--muted);
  line-height: 1.3;
  margin-top: 0.1rem;
}
.achievement-progress {
  margin-top: 0.4rem;
  height: 4px;
  background: rgba(255,255,255,0.06);
  border-radius: 999px;
  overflow: hidden;
}
.achievement-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #9c27b0, #ffb300);
  transition: width 0.4s ease;
}

/* ---------- Collection section ---------- */
.collection-section {
  margin-bottom: 2rem;
}
.collection-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.75rem;
}
.collection-header .section-heading {
  margin: 0;
}
.uniqueness-badge {
  background: linear-gradient(135deg, rgba(156,39,176,0.2) 0%, rgba(233,79,55,0.1) 100%);
  border: 1px solid rgba(156,39,176,0.3);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
}
.uniqueness-score {
  font-size: 1.3rem;
  font-weight: 700;
  color: #9c27b0;
}
.uniqueness-label {
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.collection-description {
  margin: 0 0 1rem;
  font-size: 0.9rem;
  color: var(--fg-secondary);
}
.collection-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 0.75rem;
}
.asset-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.75rem;
  text-align: center;
  cursor: pointer;
  transition: all 0.2s ease;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
}
.asset-card:hover {
  border-color: #9c27b0;
  background: rgba(156,39,176,0.08);
  transform: translateY(-2px);
}
.asset-card-preview {
  width: 64px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.asset-card-preview-fallback {
  font-size: 2.25rem;
  line-height: 1;
}
.asset-card-name {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--fg);
}
.asset-card-rarity {
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 700;
}
/* Tier accents — mirror the rarity_tier values returned by /api/assets/* */
.asset-card-common { border-color: rgba(150,150,150,0.35); }
.asset-card-common .asset-card-rarity { color: var(--muted); }
.asset-card-uncommon { border-color: rgba(76,175,80,0.45); }
.asset-card-uncommon .asset-card-rarity { color: #4caf50; }
.asset-card-rare { border-color: rgba(33,150,243,0.5); }
.asset-card-rare .asset-card-rarity { color: #2196f3; }
.asset-card-legendary {
  border-color: rgba(255,193,7,0.6);
  background: linear-gradient(180deg, var(--card) 0%, rgba(255,193,7,0.06) 100%);
}
.asset-card-legendary .asset-card-rarity { color: #ffb300; }

/* ---------- Share-collection button row ---------- */
.collection-share-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-bottom: 0.85rem;
}
.share-collection-feedback {
  font-size: 0.82rem;
  color: var(--accent-2);
  font-weight: 500;
  min-width: 0;
  word-break: break-all;
}
.share-collection-feedback a {
  color: var(--accent-2);
  text-decoration: underline;
}

/* ---------- Shared collection viewer (/c/{token}) ---------- */
.shared-uniqueness {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: linear-gradient(135deg, rgba(156,39,176,0.2) 0%, rgba(255,179,0,0.12) 100%);
  border: 1px solid rgba(156,39,176,0.3);
  border-radius: 8px;
  padding: 0.4rem 0.8rem;
  margin-top: 0.5rem;
  align-self: center;
}
.shared-cta {
  margin: 2.5rem auto 1rem;
  text-align: center;
  padding: 1.25rem 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  max-width: 460px;
}
.shared-cta p {
  margin: 0 0 0.65rem;
  font-weight: 600;
  color: var(--fg);
}

/* ---------- Catalog page ---------- */
.catalog-summary {
  margin-bottom: 1rem;
}
.catalog-progress-row {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.85rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.catalog-progress-label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.catalog-progress-count {
  font-size: 1.4rem;
  font-weight: 700;
  color: #9c27b0;
}
.catalog-progress-tag {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
}
.catalog-progress-bar {
  width: 100%;
  height: 8px;
  background: rgba(156,39,176,0.12);
  border-radius: 999px;
  overflow: hidden;
}
.catalog-progress-fill {
  height: 100%;
  width: 0%;
  /* Wide gradient + slow background-position scroll keeps the bar
     feeling alive. The `width` transition still drives the discovery
     count growth — independent axes, no fight. */
  background: linear-gradient(90deg, #9c27b0, #ffb300, #9c27b0);
  background-size: 200% 100%;
  transition: width 0.4s ease;
  animation: progress-shimmer 4s linear infinite;
}
@keyframes progress-shimmer {
  0%   { background-position: 0% 50%; }
  100% { background-position: 200% 50%; }
}
.catalog-anon-note {
  margin: 0.6rem 0 0;
  text-align: center;
  font-size: 0.88rem;
}

/* Intro "definition" card — frames Curiositter as a dictionary entry
   so first-time visitors learn the word AND the loop in one glance.
   Subtle purple-tinted gradient + a drifting sparkle in the corner
   carry the whimsy without crowding the prose. */
.bestiary-intro {
  position: relative;
  background: linear-gradient(135deg, var(--card) 0%, rgba(156, 39, 176, 0.08) 100%);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1rem 1.1rem 0.9rem;
  margin-bottom: 1rem;
  overflow: hidden;
}
.bestiary-intro-glyph {
  position: absolute;
  top: 0.5rem;
  right: 0.7rem;
  font-size: 1.4rem;
  line-height: 1;
  pointer-events: none;
  animation: sparkle-drift 6s ease-in-out infinite;
  filter: drop-shadow(0 0 6px rgba(255, 213, 79, 0.45));
}
.bestiary-intro-term {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 800;
  color: #ce93d8;
  letter-spacing: 0.01em;
  text-shadow: 0 0 18px rgba(206, 147, 216, 0.35);
}
.bestiary-intro-pos {
  font-size: 0.7rem;
  font-weight: 600;
  font-style: italic;
  color: var(--muted);
  letter-spacing: 0.06em;
  text-transform: lowercase;
  margin-left: 0.3rem;
  text-shadow: none;
}
.bestiary-intro-pron {
  margin: 0.05rem 0 0.55rem;
  font-size: 0.78rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--muted);
  letter-spacing: 0.02em;
}
.bestiary-intro-def {
  margin: 0 0 0.6rem;
  font-size: 0.94rem;
  line-height: 1.5;
  color: var(--fg);
}
.bestiary-intro-hint {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--fg-secondary);
  display: flex;
  gap: 0.35rem;
  align-items: baseline;
}
.bestiary-intro-hint span {
  flex: 0 0 auto;
}

@keyframes sparkle-drift {
  0%, 100% { transform: translateY(0) rotate(0deg); opacity: 0.85; }
  50%      { transform: translateY(-3px) rotate(8deg); opacity: 1; }
}

/* Centered, rounded "rail" framing the rarity filters so they read as
   one deliberate control rather than a free-floating row of pills. */
.catalog-controls {
  display: flex;
  justify-content: center;
  margin-bottom: 1rem;
}
/* Same specificity as `[hidden] { display: none }`, so the rule above
   wins and the chip rail leaks out before JS unhides it. Pin the
   `hidden` attribute back. Matches the pattern used by .ar-compass,
   .completed-modal, .reveal-discovery, etc. */
.catalog-controls[hidden] { display: none !important; }
.catalog-filters {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.35rem;
  padding: 0.35rem 0.55rem;
  background: rgba(156, 39, 176, 0.06);
  border: 1px solid rgba(156, 39, 176, 0.28);
  border-radius: 999px;
  box-shadow: 0 0 16px rgba(156, 39, 176, 0.12);
  max-width: 100%;
}
.catalog-chip {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.35rem 0.85rem;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  color: var(--fg);
  transition: background-color 0.18s ease, border-color 0.18s ease,
              color 0.18s ease, transform 0.18s ease,
              box-shadow 0.18s ease;
}
.catalog-chip:hover { border-color: rgba(255,255,255,0.35); }
.catalog-chip.is-active {
  background: rgba(156,39,176,0.18);
  border-color: rgba(156,39,176,0.6);
  color: #ce93d8;
  transform: scale(1.04);
  box-shadow: 0 0 12px rgba(156, 39, 176, 0.4);
}
/* Rarity-tinted accents on the per-tier chips so the filter palette
   matches the card border palette below. The active state for each
   chip uses the same color family so it reads as "I'm filtering to
   THIS rarity." Each tier gets a soft glow in its own color. */
.catalog-chip-common.is-active {
  background: rgba(150,150,150,0.18);
  border-color: rgba(200,200,200,0.6);
  color: #e0e0e0;
  box-shadow: 0 0 12px rgba(200, 200, 200, 0.3);
}
.catalog-chip-uncommon.is-active {
  background: rgba(76,175,80,0.18);
  border-color: rgba(76,175,80,0.6);
  color: #81c784;
  box-shadow: 0 0 12px rgba(76, 175, 80, 0.4);
}
.catalog-chip-rare.is-active {
  background: rgba(33,150,243,0.18);
  border-color: rgba(33,150,243,0.6);
  color: #64b5f6;
  box-shadow: 0 0 12px rgba(33, 150, 243, 0.4);
}
.catalog-chip-legendary.is-active {
  background: rgba(255,193,7,0.22);
  border-color: rgba(255,193,7,0.6);
  color: #ffb300;
  box-shadow: 0 0 14px rgba(255, 193, 7, 0.5);
}

.catalog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 0.85rem;
}

/* Honor the OS-level "reduce motion" preference — kids on managed
   school devices, anyone with vestibular sensitivity. Layout, color,
   and the active-chip scale stay (those are essential affordances);
   only the ambient keyframe animations freeze. */
@media (prefers-reduced-motion: reduce) {
  .bestiary-intro-glyph,
  .catalog-progress-fill,
  .catalog-entry.is-locked .catalog-entry-preview,
  .catalog-entry-locked-mark {
    animation: none !important;
  }
}

.catalog-entry {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.9rem 0.7rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
  transition: transform 0.15s ease, border-color 0.15s ease;
}
.catalog-entry.is-collected:hover {
  transform: translateY(-2px);
  border-color: #9c27b0;
}
.catalog-entry.is-locked {
  background: linear-gradient(180deg, #f7f8fb 0%, #e9ecf3 100%);
  border-color: rgba(0,0,0,0.12);
}
.catalog-entry.is-locked:hover {
  transform: translateY(-2px);
  border-color: rgba(0,0,0,0.35);
}
.catalog-entry-preview {
  position: relative;
  width: 72px;
  height: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.catalog-entry-preview-fallback {
  font-size: 2.4rem;
  line-height: 1;
}
/* Locked preview: white "moon" disc with the discovery animation
   flattened to a black silhouette so kids can see the shape of what
   they're chasing without spoiling color/lore. The gentle float
   keyframe drifts each disc by ±2px on Y + 0.5° rotation; the
   :nth-child delays below stagger them so the grid breathes
   asynchronously rather than as one block. */
.catalog-entry.is-locked .catalog-entry-preview {
  background: radial-gradient(circle at 50% 42%, #ffffff 0%, #ecedf3 78%);
  border-radius: 50%;
  box-shadow: inset 0 -3px 8px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.05);
  animation: silhouette-float 4s ease-in-out infinite;
}
@keyframes silhouette-float {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-2px) rotate(0.5deg); }
}
/* Stagger so a row of locked cards doesn't bob in unison — every
   sixth card resets, so within any visible row each position has its
   own phase. */
.catalog-entry.is-locked:nth-child(6n+1) .catalog-entry-preview { animation-delay: 0s; }
.catalog-entry.is-locked:nth-child(6n+2) .catalog-entry-preview { animation-delay: -0.7s; }
.catalog-entry.is-locked:nth-child(6n+3) .catalog-entry-preview { animation-delay: -1.4s; }
.catalog-entry.is-locked:nth-child(6n+4) .catalog-entry-preview { animation-delay: -2.1s; }
.catalog-entry.is-locked:nth-child(6n+5) .catalog-entry-preview { animation-delay: -2.8s; }
.catalog-entry.is-locked:nth-child(6n)   .catalog-entry-preview { animation-delay: -3.5s; }
.catalog-entry.is-locked .catalog-entry-preview svg {
  filter: brightness(0) saturate(100%);
  opacity: 0.85;
}
.catalog-entry.is-locked .catalog-entry-preview-fallback {
  color: #1a1d24;
  font-weight: 800;
}
/* Purple "?" badge floats over the silhouette to telegraph "unknown
   trophy." Sits above the SVG in z-order; disappears once collected
   because the badge element is only rendered for locked cards.
   z-index is required because Lottie appends its SVG as a later
   sibling — without it the silhouette paints on top of the mark and
   the "?" only shows through the SVG's transparent pixels. */
.catalog-entry-locked-mark {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.9rem;
  font-weight: 900;
  color: #9c27b0;
  text-shadow: 0 1px 0 #fff, 0 0 6px rgba(156, 39, 176, 0.45);
  pointer-events: none;
  animation: mark-bobble 2.5s ease-in-out infinite;
}
@keyframes mark-bobble {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-1.5px); }
}
.catalog-entry-name {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--fg);
}
.catalog-entry.is-locked .catalog-entry-name {
  color: #1a1d24;
}
.catalog-entry-meta {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  align-items: center;
}
.catalog-entry-rarity {
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.catalog-entry.is-locked .catalog-entry-rarity {
  color: #555a66;
}
.catalog-entry-encounters {
  font-size: 0.7rem;
  color: var(--muted);
}
.catalog-entry-desc {
  margin: 0.25rem 0 0;
  font-size: 0.78rem;
  color: var(--fg-secondary);
  line-height: 1.35;
}
/* Tier color accents reuse the .asset-card-* palette so the catalog
   entries match the profile collection cards. */
.catalog-entry-common { border-color: rgba(150,150,150,0.35); }
.catalog-entry-common .catalog-entry-rarity { color: var(--muted); }
.catalog-entry-uncommon { border-color: rgba(76,175,80,0.45); }
.catalog-entry-uncommon .catalog-entry-rarity { color: #4caf50; }
.catalog-entry-rare { border-color: rgba(33,150,243,0.5); }
.catalog-entry-rare .catalog-entry-rarity { color: #2196f3; }
.catalog-entry-legendary {
  border-color: rgba(255,193,7,0.6);
  background: linear-gradient(180deg, var(--card) 0%, rgba(255,193,7,0.06) 100%);
}
.catalog-entry-legendary .catalog-entry-rarity { color: #ffb300; }

/* ---------- Asset detail modal (shared by profile + catalog) ---------- */
.asset-modal {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  animation: asset-modal-in 0.2s ease-out;
}
/* The `display: flex` above has the same specificity as the UA `[hidden]`
   rule, so without this override the modal stays visible even after
   closeAssetModal() sets the hidden attribute — the X / backdrop / Esc
   look broken when in fact only the paint is wrong. */
.asset-modal[hidden] { display: none !important; }
@keyframes asset-modal-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.asset-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 15, 35, 0.78);
  backdrop-filter: blur(4px);
}
.asset-modal-card {
  position: relative;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  max-width: 460px;
  width: 100%;
  padding: 1.4rem 1.2rem 1.2rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: 0 12px 48px rgba(0, 0, 0, 0.5);
  animation: asset-modal-card-in 0.25s cubic-bezier(0.2, 0.9, 0.4, 1.2);
}
@keyframes asset-modal-card-in {
  from { transform: translateY(12px) scale(0.96); opacity: 0; }
  to   { transform: translateY(0) scale(1); opacity: 1; }
}
.asset-modal-close {
  position: absolute;
  top: 0.5rem;
  right: 0.7rem;
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.25rem 0.5rem;
  border-radius: 6px;
}
.asset-modal-close:hover { color: var(--fg); background: rgba(255,255,255,0.05); }
.asset-modal-preview {
  position: relative;
  width: 160px;
  height: 160px;
  margin: 0.25rem auto 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,0.04);
  border-radius: 14px;
  overflow: hidden;
}
.asset-modal-fallback { font-size: 4rem; line-height: 1; }
/* Purple "?" badge over the locked silhouette in the detail modal —
   matches the catalog card overlay so the visual language stays
   consistent. Only rendered for locked entries; vanishes once owned.
   z-index keeps it above the Lottie SVG (Lottie is appended after the
   mark, so without this the silhouette would paint over the "?"). */
.asset-modal-locked-mark {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 4.2rem;
  font-weight: 900;
  color: #9c27b0;
  text-shadow: 0 2px 0 #fff, 0 0 14px rgba(156, 39, 176, 0.55);
  pointer-events: none;
}
.asset-modal-tier {
  display: inline-block;
  align-self: center;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
}
.asset-modal-name {
  margin: 0;
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--fg);
}
.asset-modal-desc {
  margin: 0;
  font-size: 0.95rem;
  color: var(--fg-secondary);
  line-height: 1.45;
  padding: 0 0.4rem;
}
.asset-modal-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  justify-content: center;
  margin: -0.2rem 0 0.1rem;
}
.asset-modal-badges:empty { display: none; }
.asset-modal-badge {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  color: var(--fg);
  text-transform: capitalize;
}
.asset-modal-badge-rarity {
  background: rgba(156,39,176,0.18);
  border-color: rgba(156,39,176,0.35);
  color: #ce93d8;
  text-transform: none;
}
.asset-modal-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  justify-content: center;
}
.asset-modal-meta-pill {
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: rgba(156,39,176,0.15);
  border: 1px solid rgba(156,39,176,0.3);
  color: #ce93d8;
}
.asset-modal-attributes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.4rem;
  margin-top: 0.4rem;
}
.asset-modal-attribute {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: rgba(255,255,255,0.04);
  border-radius: 8px;
  padding: 0.5rem 0.4rem;
}
.asset-modal-attribute-label {
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  font-weight: 700;
}
.asset-modal-attribute-value {
  font-size: 0.85rem;
  color: var(--fg);
  font-weight: 500;
  margin-top: 0.15rem;
  text-transform: capitalize;
}
/* Tier accents on the modal mirror the card palette. */
.asset-modal-common .asset-modal-tier { background: rgba(150,150,150,0.18); color: var(--muted); }
.asset-modal-uncommon .asset-modal-tier { background: rgba(76,175,80,0.18); color: #81c784; }
.asset-modal-rare .asset-modal-tier { background: rgba(33,150,243,0.18); color: #64b5f6; }
.asset-modal-legendary .asset-modal-tier { background: rgba(255,193,7,0.22); color: #ffb300; }
.asset-modal-legendary .asset-modal-card {
  border-color: rgba(255,193,7,0.5);
  box-shadow: 0 0 32px rgba(255,193,7,0.2), 0 12px 48px rgba(0,0,0,0.5);
}
.asset-modal.is-locked .asset-modal-preview {
  background: radial-gradient(circle at 50% 42%, #ffffff 0%, #ecedf3 78%);
  border-radius: 50%;
  box-shadow: inset 0 -4px 12px rgba(0,0,0,0.06);
}
.asset-modal.is-locked .asset-modal-preview svg {
  filter: brightness(0) saturate(100%);
  opacity: 0.85;
}
.asset-modal.is-locked .asset-modal-fallback { color: #1a1d24; font-weight: 800; }
body.asset-modal-open { overflow: hidden; }
body.reveal-open { overflow: hidden; }

/* Make collection cards feel tappable on hover */
.asset-card { cursor: pointer; }
.catalog-entry.is-collected { cursor: pointer; }
.catalog-entry.is-locked { cursor: pointer; }

.section-heading {
  margin: 0 0 0.75rem;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
}

.hunt-rows { list-style: none; padding: 0; margin: 0 0 1.5rem; display: flex; flex-direction: column; gap: 0.6rem; }
.hunt-row {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.9rem 1rem;
  display: flex;
  align-items: center;
  gap: 1rem;
}
.hunt-row-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: 0.9rem;
  min-width: 0;
}
.btn-sm {
  padding: 0.45rem 0.85rem;
  font-size: 0.85rem;
  white-space: nowrap;
}

@media (max-width: 480px) {
  .stats-strip { grid-template-columns: repeat(2, 1fr); }
  .profile-card { flex-direction: column; text-align: center; }
  .profile-logout-btn { align-self: stretch; }
}

/* ---------- Admin UI ---------- */
.admin-layout {
  max-width: 1100px;
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: 1.5rem;
  align-items: start;
}
/* stack on narrow screens */
@media (max-width: 720px) {
  .admin-layout { grid-template-columns: 1fr; }
}

.admin-sidebar {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.sidebar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
  background: rgba(255,255,255,0.03);
}
.sidebar-header h3 { margin: 0; font-size: 0.9rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }

.admin-hunt-list { list-style: none; padding: 0; margin: 0; }
.admin-hunt-item {
  padding: 0.7rem 1rem;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  transition: background 120ms;
}
.admin-hunt-item:last-child { border-bottom: none; }
.admin-hunt-item:hover { background: rgba(255,255,255,0.04); }
.admin-hunt-item.active { background: rgba(79,195,247,0.1); border-left: 3px solid var(--accent-2); }
.hunt-item-title { display: block; font-weight: 600; font-size: 0.9rem; }
.hunt-item-meta { display: block; font-size: 0.78rem; color: var(--muted); margin-top: 0.1rem; }

.admin-detail {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem;
  min-height: 200px;
}

/* Admin forms */
.admin-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.admin-form h3, .admin-form h4 { margin: 0 0 0.25rem; }
.admin-form textarea {
  padding: 0.6rem 0.75rem;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: rgba(255,255,255,0.04);
  color: var(--fg);
  font-size: 0.95rem;
  font-family: inherit;
  resize: vertical;
}
.form-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.25rem; }

.btn-primary { background: var(--accent); color: white; border: none; padding: .55rem 1rem; border-radius: 6px; font-weight: 600; cursor: pointer; font-size: .9rem; }
.btn-ghost { background: transparent; color: var(--muted); border: 1px solid var(--border); padding: .5rem 0.9rem; border-radius: 6px; cursor: pointer; font-size: .9rem; }
.btn-ghost:hover { background: rgba(255,255,255,0.05); }
.btn-danger { background: transparent; color: #ff7070; border: 1px solid #ff7070; padding: .5rem 0.9rem; border-radius: 6px; cursor: pointer; font-size: .9rem; }
.btn-danger:hover { background: rgba(255,80,80,0.1); }
.btn-xs { padding: .5rem .75rem; font-size: .8rem; border-radius: 5px; min-height: 2.75rem; }

/* Stops section */
.stops-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 1.5rem 0 0.75rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
}
.stops-header h3 { margin: 0; font-size: 0.9rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }

/* Author dashboard for player-filed stop-issue reports. Same shape as
 * .stops-header so it nests under the stops list as a sibling section,
 * not visually a child of any one stop. */
.reports-section { margin-top: 1.5rem; padding-top: 1.25rem; border-top: 1px solid var(--border); }
.reports-header { display: flex; justify-content: space-between; align-items: center; margin: 0 0 0.75rem; }
.reports-header h3 { margin: 0; font-size: 0.9rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.reports-total-badge {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 600;
  background: rgba(220, 53, 69, 0.18);
  color: #ff6b6b;
  border: 1px solid rgba(220, 53, 69, 0.4);
  text-transform: none;
  letter-spacing: 0;
}
.reports-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.reports-item {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.6rem 0.85rem;
  font-size: 0.85rem;
}
.reports-item-head { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.reports-item-stop { font-weight: 600; }
.reports-item-reason {
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: rgba(245, 183, 0, 0.18);
  color: #f5b700;
  border: 1px solid rgba(245, 183, 0, 0.4);
}
.reports-item-note { margin: 0.4rem 0; color: var(--fg); white-space: pre-wrap; }
.reports-item-foot { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; margin-top: 0.4rem; font-size: 0.78rem; flex-wrap: wrap; }

#stops-map {
  height: 260px;
  border-radius: 8px;
  margin-bottom: 1rem;
  border: 1px solid var(--border);
  overflow: hidden;
}

.stops-list { list-style: none; padding: 0; margin: 0 0 1rem; display: flex; flex-direction: column; gap: .5rem; }
.stop-item {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: .7rem .85rem;
}
.stop-item-num {
  width: 24px; height: 24px; flex-shrink: 0;
  background: var(--accent-2);
  color: #0b1020;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: .75rem; font-weight: 700;
}
.stop-item-body { flex: 1; font-size: .88rem; min-width: 0; }
.stop-item-body .muted { font-size: .78rem; display: block; margin: .15rem 0; }
.stop-clue-preview { margin: .25rem 0 0; color: var(--muted); font-size: .82rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stop-item-actions { display: flex; gap: .35rem; align-items: flex-start; }

.stop-form {
  margin-top: 1rem;
  padding: 1rem;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.stop-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .6rem;
  margin-bottom: .6rem;
}
@media (max-width: 560px) { .stop-form-grid { grid-template-columns: 1fr; } }

/* ══════════════════════════════════════════════════════════════════════
   HUNT CARD GRID  (hunts index page)
   ══════════════════════════════════════════════════════════════════════ */
.hunt-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1rem;
  margin-top: 0.75rem;
}
.hunt-card {
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  text-decoration: none;
  color: var(--fg);
  transition: border-color 150ms, transform 150ms;
}
.hunt-card:hover {
  border-color: rgba(79, 195, 247, 0.5);
  transform: translateY(-2px);
}
.hunt-card-img-wrap {
  position: relative;
  height: 160px;
  background: #121830;
  flex-shrink: 0;
}
.hunt-card-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hunt-card-img-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 40%, rgba(8, 13, 35, 0.75) 100%);
}
.hunt-card-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.hunt-card-badge--done {
  background: rgba(16, 40, 16, 0.88);
  color: #a3e635;
  border: 1px solid rgba(163, 230, 53, 0.35);
}
.hunt-card-badge--progress {
  background: rgba(10, 30, 55, 0.88);
  color: var(--accent-2);
  border: 1px solid rgba(79, 195, 247, 0.35);
}
.hunt-card-body {
  padding: 0.85rem 1rem 1rem;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.hunt-card-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.25;
  color: var(--fg);
}
.hunt-card-meta {
  display: flex;
  gap: 0.75rem;
  color: var(--muted);
  font-size: 0.8rem;
}
.hunt-card-desc {
  margin: 0;
  font-size: 0.85rem;
  color: var(--muted);
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.hunt-card-progress {
  height: 3px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 2px;
  overflow: hidden;
  margin-top: auto;
}
.hunt-card-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent-2), #a3e635);
  border-radius: 2px;
}

/* ══════════════════════════════════════════════════════════════════════
   AMBIENT BACKGROUND  (hunt page — behind camera)
   ══════════════════════════════════════════════════════════════════════ */
.ambient-bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  background-size: cover;
  background-position: center;
  transition: opacity 0.8s ease;
}

/* ══════════════════════════════════════════════════════════════════════
   HUNT INTRO SCREEN
   ══════════════════════════════════════════════════════════════════════ */
.intro-screen {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: flex-end;
}
/* The `display: flex` above has the same specificity as the UA `[hidden]`
   rule, so setting `hidden=true` alone doesn't guarantee the screen hides.
   Force display:none whenever the attribute is present. */
.intro-screen[hidden] { display: none !important; }
.intro-inner {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.intro-cover-wrap {
  position: relative;
  flex: 1;
  min-height: 0;
}
.intro-cover {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.intro-cover-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.1) 0%,
    rgba(8, 13, 35, 0.5) 60%,
    rgba(8, 13, 35, 0.95) 100%
  );
}
.intro-body {
  position: relative;
  z-index: 1;
  background: rgba(8, 13, 35, 0.97);
  padding: 1.25rem 1.5rem env(safe-area-inset-bottom, 1.5rem);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.intro-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent-2);
}
.intro-title {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1.15;
  color: var(--fg);
}
.intro-desc {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--muted);
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.intro-stats {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  margin: 0.15rem 0;
}
.intro-stat {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.intro-stat-label {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
}
.intro-stat-value {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--fg);
}
.intro-begin-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.9rem 1rem;
  margin-top: 0.35rem;
  background: var(--accent);
  color: white;
  border: none;
  border-radius: 12px;
  font-size: 1.05rem;
  font-weight: 700;
  cursor: pointer;
  letter-spacing: 0.01em;
}
.intro-begin-btn:hover { background: #d94430; }

/* ══════════════════════════════════════════════════════════════════════
   AR ICON OVERLAYS  (lock / unlock / sparkle)
   ══════════════════════════════════════════════════════════════════════ */
.ar-icons {
  position: absolute;
  top: 30%;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
  z-index: 3;
}
.ar-icon-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}
/* Ensure the `hidden` attribute actually hides #ar-lock / #ar-unlock.
   Without this override, both icons are painted on page load — so a
   player who is 5 km away still sees the green "YOU'RE HERE!" unlock
   label stacked over the compass. Same specificity fix as .ar-compass. */
.ar-icon-wrap[hidden] { display: none !important; }
.ar-icon-img {
  width: 64px;
  height: 64px;
  filter: drop-shadow(0 4px 14px rgba(0, 0, 0, 0.65));
}
.ar-icon-label {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.8);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
}

/* Lock — de-emphasized, pinned bottom-right of the camera overlay so it
   doesn't compete with the compass arrow, Lottie discovery, or arrive
   CTA in the middle of the frame. Small, low-opacity, red drop-shadow
   to signal "not yet arrived" without dominating the view.

   `position: absolute` resolves against the nearest positioned ancestor
   (.camera-overlay, which is `position: fixed`). #ar-lock is a direct
   child of .camera-overlay — NOT nested inside #ar-icons — because
   #ar-icons has a `transform` that would create a new containing block
   for any `position: fixed` descendants and hijack the offsets. */
.ar-lock {
  position: absolute;
  bottom: calc(1rem + env(safe-area-inset-bottom, 0));
  right: calc(1rem + env(safe-area-inset-right, 0));
  top: auto;
  left: auto;
  transform: none;
  flex-direction: row;
  align-items: center;
  gap: 0.35rem;
  opacity: 0.55;
  z-index: 5;
  pointer-events: none;
}
.ar-lock .ar-icon-img {
  width: 24px;
  height: 24px;
  filter: drop-shadow(0 2px 6px rgba(233, 79, 55, 0.55));
}
.ar-lock .ar-icon-label {
  font-size: 0.65rem;
  letter-spacing: 0.08em;
}

/* Unlock — green, pulses in */
.ar-unlock .ar-icon-img {
  filter: drop-shadow(0 4px 18px rgba(80, 220, 130, 0.7));
}
.ar-unlock-label {
  color: #a3e635;
  font-size: 0.95rem;
}
@keyframes ar-icon-pop {
  0%   { opacity: 0; transform: scale(0.5); }
  60%  { opacity: 1; transform: scale(1.15); }
  100% { opacity: 1; transform: scale(1); }
}
.ar-icon-pulse {
  animation: ar-icon-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

/* Sparkle ring overlay */
.ar-sparkle-ring {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 200px;
  height: 200px;
  pointer-events: none;
}
.ar-sparkle-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.ar-sparkle-outer {
  animation: sparkle-spin 1.2s linear forwards;
  opacity: 0;
}
.ar-sparkle-inner {
  animation: sparkle-pop 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
  opacity: 0;
}
@keyframes sparkle-spin {
  0%   { opacity: 0; transform: rotate(-30deg) scale(0.6); }
  15%  { opacity: 1; }
  80%  { opacity: 1; transform: rotate(20deg) scale(1.05); }
  100% { opacity: 0; transform: rotate(30deg) scale(1.1); }
}
@keyframes sparkle-pop {
  0%   { opacity: 0; transform: scale(0.4); }
  40%  { opacity: 1; transform: scale(1.2); }
  70%  { transform: scale(0.9); }
  85%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1); }
}

/* Individual star particles — offset staggered */
.ar-sparkle-star {
  width: 32px;
  height: 32px;
  inset: unset;
  animation: star-fly 0.9s ease-out forwards;
  opacity: 0;
}
.ar-sparkle-star1 { top: 10%;  left: 20%;  animation-delay: 0.05s; }
.ar-sparkle-star2 { top: 15%;  right: 18%; animation-delay: 0.12s; }
.ar-sparkle-star3 { bottom: 12%; left: 50%; margin-left: -16px; animation-delay: 0.18s; }
@keyframes star-fly {
  0%   { opacity: 0; transform: scale(0) rotate(0deg); }
  25%  { opacity: 1; }
  100% { opacity: 0; transform: scale(1.4) rotate(45deg) translateY(-20px); }
}

/* ══════════════════════════════════════════════════════════════════════
   REVEAL SHEET ENHANCEMENTS
   ══════════════════════════════════════════════════════════════════════ */
.reveal-photo-wrap {
  margin-bottom: 0.75rem;
}
/* .reveal-image already styled above — just inherits from that rule */

.next-clue-deco {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.35rem;
}
.next-clue-deco-icon {
  opacity: 0.6;
  flex-shrink: 0;
}
.photo-challenge-label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

/* ══════════════════════════════════════════════════════════════════════
   COMPLETION SCREEN ENHANCEMENTS
   ══════════════════════════════════════════════════════════════════════ */
.completed-trophy {
  position: relative;
  width: 96px;
  height: 96px;
  margin: 0 auto 0.75rem;
}
.completed-trophy-icon {
  position: relative;
  z-index: 1;
  width: 56px;
  height: 56px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 4px 12px rgba(245, 183, 0, 0.6));
  animation: trophy-drop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
@keyframes trophy-drop {
  0%   { opacity: 0; transform: translate(-50%, -60%) scale(0.6); }
  100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
.completed-trophy-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  animation: ring-spin 2.5s linear infinite;
  opacity: 0.7;
}
@keyframes ring-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Photo collage */
.photo-collage {
  margin: 0.75rem 0;
  text-align: left;
}
.photo-collage-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-bottom: 0.45rem;
}
.photo-collage-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
}
.collage-photo {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid var(--border);
  display: block;
}

/* Medal row */
.medal-row {
  display: flex;
  justify-content: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin: 0.5rem 0 1rem;
}
.medal-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
}
.medal-item img {
  filter: drop-shadow(0 2px 6px rgba(245, 183, 0, 0.4));
  animation: medal-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
@keyframes medal-pop {
  0%   { opacity: 0; transform: scale(0.5) rotate(-15deg); }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}
.medal-item span {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
}

/* ---------- PWA install banner ---------- */
.pwa-install-banner {
  position: fixed;
  left: 0.75rem;
  right: 0.75rem;
  bottom: calc(0.75rem + env(safe-area-inset-bottom, 0));
  max-width: 480px;
  margin: 0 auto;
  background: rgba(10, 15, 35, 0.98);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0.85rem 0.9rem;
  display: flex;
  align-items: center;
  gap: 0.8rem;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
  z-index: 150;
}
.pwa-install-banner[hidden] { display: none; }
.pwa-install-icon { width: 40px; height: 40px; border-radius: 8px; flex-shrink: 0; }
.pwa-install-text { flex: 1; font-size: 0.85rem; line-height: 1.35; }
.pwa-install-text strong { color: var(--fg); display: block; margin-bottom: 0.15rem; }
.pwa-install-text p { color: var(--muted); margin: 0; font-size: 0.8rem; }
.pwa-install-actions { display: flex; align-items: center; gap: 0.35rem; flex-shrink: 0; }
#pwa-install-btn { padding: 0.45rem 0.85rem; border-radius: 6px; font-size: 0.85rem; }
.pwa-install-dismiss {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 1.3rem;
  line-height: 1;
  padding: 0.2rem 0.5rem;
  cursor: pointer;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
}
.pwa-install-dismiss:focus-visible {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
}

/* ---------- Camera gate (shared between landing setup + hunt intro) ----------
   Injected by camera-gate.js via renderCameraGate(). The module controls
   which child elements show for each state (checking / prompt / denied /
   unavailable / granted) via .camera-gate[data-state="..."].
   On "granted" the container self-hides — the caller then reveals the
   downstream UI (hunts list, Begin hunt button). */
.camera-gate {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.5rem;
  padding: 1rem 1rem 0.75rem;
  background: rgba(245, 183, 0, 0.06);
  border: 1px solid rgba(245, 183, 0, 0.25);
  border-radius: 10px;
  margin: 0.5rem 0;
}
.camera-gate[data-state="granted"] {
  /* Successful path — module sets body/heading empty; suppress padding so
     the granted "✓" line reads as a quiet confirmation, not a panel. */
  background: transparent;
  border-color: transparent;
  padding: 0.25rem 0;
}
.camera-gate-icon {
  font-size: 2rem;
  line-height: 1;
}
.camera-gate-heading {
  font-weight: 600;
  font-size: 1rem;
  color: var(--fg);
}
.camera-gate-body {
  color: var(--muted);
  font-size: 0.9rem;
  margin: 0;
  line-height: 1.4;
}
.camera-gate-action {
  min-width: 160px;
}
.camera-gate-ready {
  color: var(--accent-2, #5ec8ff);
  font-size: 0.85rem;
  font-weight: 600;
}

/* Intro-screen gate variant: sits inside .intro-body, tightened margins
   so the Begin-hunt button stays in a natural reading flow. */
.intro-camera-gate:empty { display: none; }
.intro-camera-gate .camera-gate { margin: 0.75rem 0 0.5rem; }

/* Small-screen tightening for the hunt page. The AR compass, mini-map, and
   AR icon overlays are all absolutely positioned with percentage-from-top
   offsets tuned for tall viewports. On short iPhones (SE, older Pros in
   landscape-mode-close-to-portrait) they pile into the narrow band above
   the capped clue card. These breakpoints compress that band so the
   compass + mini-map stay visible without overlapping the clue card top. */
@media (max-height: 720px) {
  .ar-compass { top: 14%; }
  #ar-icons { top: 22%; }
  #mini-map-wrap {
    width: 90px;
    height: 90px;
    top: 60px;
    right: 10px;
  }
}
@media (max-width: 400px) {
  /* Very narrow: stack the CLUE label above the difficulty chip pair so
     neither crushes the other. */
  .stop-label {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.3rem;
  }
  .difficulty-pair { align-self: flex-end; }
}
.pwa-install-dismiss:hover { color: var(--fg); }

/* ══════════════════════════════════════════════════════════════════════
   HINT PAGE REDESIGN — v1 (applies to all hunts, HR is the beta test)

   - Hero clue card is the page (see .clue-card + .clue-hero above).
   - Camera + AR moved into an opt-in .camera-overlay pop-out.
   - Map reveal is now an in-app .map-reveal-modal (Leaflet), replacing
     the old external Google Maps hyperlink.
   - Hint + map actions rendered as .pill buttons instead of a cramped
     tri-column button row.
   - Arrive CTA pinned to the bottom of the card as .arrive-bar for
     thumb reach; stays visible while hints scroll.
   ══════════════════════════════════════════════════════════════════════ */

/* ---------- Signal chip (replaces .accuracy-row) ---------- */
.signal-row {
  display: flex;
  justify-content: center;
  margin: 0.35rem 0 0.6rem;
}
.signal-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.28rem 0.7rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: var(--muted);
  font-size: 0.78rem;
  letter-spacing: 0.02em;
}
.signal-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #9aa3c7;
  box-shadow: 0 0 0 0 rgba(154, 163, 199, 0.45);
}
.signal-chip--ok   .signal-dot { background: #a3e635; box-shadow: 0 0 0 3px rgba(163, 230, 53, 0.18); }
.signal-chip--weak .signal-dot { background: #f5b700; box-shadow: 0 0 0 3px rgba(245, 183, 0, 0.2); }
.signal-chip--bad  .signal-dot { background: #ff7070; box-shadow: 0 0 0 3px rgba(255, 112, 112, 0.22); }

/* ---------- Help tiers (tiered hint progression) ---------- */
.help-tiers {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0.5rem 0 0.75rem;
}
.help-tiers-header {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 0.15rem;
}
.pill[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Backwards compat: legacy .action-pills name */
.action-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.25rem 0 0.75rem;
}
.pill {
  flex: 1 1 auto;
  min-height: 44px;              /* iOS 44pt tap target */
  padding: 0.6rem 0.9rem;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.04);
  color: var(--fg);
  font-size: 0.88rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  cursor: pointer;
  transition: background 120ms ease, transform 80ms ease, border-color 120ms ease;
  white-space: nowrap;
}
.pill:hover { background: rgba(255, 255, 255, 0.08); }
.pill:active { transform: scale(0.97); }
.pill img { opacity: 0.9; }
.pill[hidden] { display: none !important; }

.pill-camera {
  background: linear-gradient(135deg, rgba(79, 195, 247, 0.16), rgba(79, 195, 247, 0.04));
  border-color: rgba(79, 195, 247, 0.45);
  color: #dff4ff;
}
.pill-camera:hover { background: linear-gradient(135deg, rgba(79, 195, 247, 0.28), rgba(79, 195, 247, 0.08)); }

.pill-hint {
  background: linear-gradient(135deg, rgba(245, 183, 0, 0.18), rgba(245, 183, 0, 0.04));
  border-color: rgba(245, 183, 0, 0.5);
  color: #ffe9a1;
}
.pill-hint:hover { background: linear-gradient(135deg, rgba(245, 183, 0, 0.3), rgba(245, 183, 0, 0.08)); }

.pill-map {
  background: linear-gradient(135deg, rgba(233, 79, 55, 0.16), rgba(233, 79, 55, 0.04));
  border-color: rgba(233, 79, 55, 0.5);
  color: #ffd4cb;
}
.pill-map:hover { background: linear-gradient(135deg, rgba(233, 79, 55, 0.28), rgba(233, 79, 55, 0.08)); }

/* ---------- Arrive bar (sticky bottom CTA inside .clue-card) ---------- */
.arrive-bar {
  position: sticky;
  bottom: 0;
  margin: 0.75rem -1.25rem -0.25rem;     /* bleed into card padding */
  padding: 0.65rem 1.25rem 0.35rem;
  background: linear-gradient(180deg,
    rgba(15, 22, 48, 0) 0%,
    rgba(11, 16, 32, 0.92) 40%,
    rgba(11, 16, 32, 0.98) 100%);
  z-index: 2;
}
.arrive-btn {
  width: 100%;
  min-height: 52px;
  padding: 0.85rem 1rem;
  border-radius: 14px;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  background: linear-gradient(135deg, var(--accent) 0%, #ff8a5c 100%);
  color: white;
  border: 0;
  cursor: pointer;
  box-shadow: 0 8px 24px -8px rgba(233, 79, 55, 0.65);
  transition: transform 80ms ease, box-shadow 160ms ease, filter 160ms ease;
}
.arrive-btn:hover:not(:disabled) { filter: brightness(1.06); }
.arrive-btn:active:not(:disabled) { transform: scale(0.99); }
.arrive-btn:disabled {
  background: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.55);
  box-shadow: none;
  cursor: not-allowed;
}

/* ---------- Camera pop-out overlay ---------- */
.camera-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;                 /* above #overlay (z:1) and below reveal modals (z:~80) */
  background: #000;
  pointer-events: auto;
}
/* Same specificity fix as .completed-modal / .ar-compass: an element
   with an explicit display rule ties UA [hidden] and wins the cascade. */
.camera-overlay[hidden] { display: none !important; }

.camera-close {
  position: absolute;
  top: calc(0.75rem + env(safe-area-inset-top, 0));
  right: 0.75rem;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(0, 0, 0, 0.55);
  color: white;
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(6px);
}
.camera-close:hover { background: rgba(0, 0, 0, 0.8); }

/* Sound toggle button inside the camera overlay — mutes/unmutes the
   proximity beeping. Mirrors the camera-close style but on the left. */
.sound-toggle {
  position: absolute;
  top: calc(0.75rem + env(safe-area-inset-top, 0));
  left: 0.75rem;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(0, 0, 0, 0.55);
  color: white;
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(6px);
}
.sound-toggle:hover { background: rgba(0, 0, 0, 0.8); }

/* Compass show/hide toggle inside the camera overlay. Shares the
   pill/blur style of #sound-toggle but sits next to it on the left
   so the compass arrow (mid-screen) is within thumb reach. */
.compass-toggle {
  position: absolute;
  top: calc(0.75rem + env(safe-area-inset-top, 0));
  left: calc(0.75rem + 44px + 0.5rem);
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(0, 0, 0, 0.55);
  color: white;
  cursor: pointer;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(6px);
  transition: background 0.15s ease, border-color 0.15s ease;
}
.compass-toggle:hover { background: rgba(0, 0, 0, 0.8); }
.compass-toggle img {
  opacity: 0.65;
  transition: opacity 0.15s ease;
}
.compass-toggle--on {
  background: rgba(245, 183, 0, 0.4);
  border-color: rgba(245, 183, 0, 0.8);
}
.compass-toggle--on img { opacity: 1; }

/* Proximity color escalation on the AR compass ring. The ring pulses
   with increasingly urgent colors as the player approaches the stop. */
.proximity-approaching .ar-ring { stroke: rgba(79, 195, 247, 0.5); }
.proximity-near .ar-ring { stroke: rgba(245, 183, 0, 0.6); }
.proximity-warm .ar-ring { stroke: rgba(255, 152, 0, 0.8); }
.proximity-hot .ar-ring { stroke: rgba(233, 79, 55, 1); stroke-width: 3; }

/* Proximity message: shown alongside the close-range ring (<= 100 ft).
   Sits below the rings so it doesn't crowd the distance readout in the
   center. Pulses gently to draw the eye without competing with the
   ring animation. */
.ar-search-msg {
  position: absolute;
  left: 50%;
  top: 100%;
  transform: translateX(-50%);
  margin-top: 0.5rem;
  width: max-content;
  max-width: 80vw;
  color: #f5b700;
  font-size: 0.9rem;
  font-weight: 600;
  text-align: center;
  letter-spacing: 0.02em;
  line-height: 1.3;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.95);
  animation: search-pulse 1.5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes search-pulse {
  0%, 100% { opacity: 0.75; }
  50% { opacity: 1; }
}
.ar-search-msg[hidden] { display: none !important; }

/* Lottie discovery animation — themed icon that appears when the player
   gets within 50 ft and stays pinned (frozen) after arrival. Anchored
   to the same top edge as .ar-proximity-ring (top: 20%): the ring is
   200×200, while this .lottie-discovery container is intentionally
   larger at 240×240 so the Lottie / emoji sits directly over the
   heat-ring as one visual group — the payoff lands where the eye is
   already tracking the solved circle. */
.lottie-discovery {
  position: absolute;
  left: 50%;
  top: 20%;
  /* CSS-default position is centered (kept for reduce-motion / no-
     compass fallback). When real-AR anchoring is active, JS adds
     `.ar-anchored` and writes the three custom properties below;
     they shift + scale the container around its CSS anchor without
     needing JS to also recompute the centering offset. */
  --ar-anchor-x: 0vw;
  --ar-anchor-y: 0%;
  --ar-anchor-scale: 1;
  transform: translateX(-50%);
  width: 240px;
  height: 240px;
  max-width: 60vw;
  max-height: 40vh;
  z-index: 4;
  pointer-events: none;
  will-change: transform;
  transition: transform 80ms linear;
  /* Fallback emoji renders via `.discovery-fallback`. When Lottie
     injects an <svg> inside, JS adds `.lottie-loaded` which hides the
     emoji — otherwise the emoji stays visible so a kid always sees a
     bunny. */
}
.lottie-discovery.ar-anchored {
  top: var(--ar-anchor-y);
  transform: translate(calc(-50% + var(--ar-anchor-x)), 0) scale(var(--ar-anchor-scale));
  /* Smaller transition window so anchored panning feels responsive. */
  transition: transform 50ms linear, top 120ms linear;
}
.lottie-discovery[hidden] { display: none !important; }

/* Stage-2 reveal asset (the bunny / fox / gem). World-anchored to the
   same bearing as the chest so they pan together. Sits slightly above
   and to the right of the chest at default; the JS-driven anchor
   transform applies to both. Pop-in scale animation when first shown
   gives a satisfying "hops out of the box" beat. */
.lottie-reveal-asset {
  position: absolute;
  left: calc(50% + 60px);
  top: 12%;
  --ar-anchor-x: 0vw;
  --ar-anchor-y: 0%;
  --ar-anchor-scale: 1;
  transform: translateX(-50%);
  width: 180px;
  height: 180px;
  max-width: 45vw;
  max-height: 35vh;
  z-index: 5;
  pointer-events: none;
  will-change: transform;
  transition: transform 80ms linear;
}
.lottie-reveal-asset.ar-anchored {
  /* Offset 6vw right of the chest so the bunny sits next to it, not
     on top of it. The chest's --ar-anchor-x is shared so they pan in
     lockstep; the reveal asset adds the lateral offset on top. */
  top: calc(var(--ar-anchor-y) - 8%);
  transform: translate(calc(-50% + var(--ar-anchor-x) + 6vw), 0)
             scale(calc(var(--ar-anchor-scale) * 0.85));
  transition: transform 50ms linear, top 120ms linear;
}
.lottie-reveal-asset[hidden] { display: none !important; }
/* One-shot pop when first appearing — kids need a clear "look at me"
   beat for the bunny so it doesn't blend into the chest. */
.lottie-reveal-asset.reveal-asset-popin {
  animation: reveal-asset-popin 600ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes reveal-asset-popin {
  0%   { opacity: 0; transform: translate(calc(-50% + var(--ar-anchor-x) + 6vw), 30px) scale(0.2); }
  60%  { opacity: 1; transform: translate(calc(-50% + var(--ar-anchor-x) + 6vw), -8px) scale(1.1); }
  100% { opacity: 1; transform: translate(calc(-50% + var(--ar-anchor-x) + 6vw), 0) scale(calc(var(--ar-anchor-scale) * 0.85)); }
}

/* Off-screen anchor arrow: shown when the world-locked chest is
   behind the player or beyond the camera FOV. JS toggles `.left` /
   `.right` so the arrow faces the right way. */
.ar-anchor-arrow {
  position: absolute;
  top: 45%;
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  border: 2px solid rgba(255, 255, 255, 0.85);
  border-radius: 50%;
  color: #fff;
  font-size: 2rem;
  font-weight: 800;
  z-index: 6;
  pointer-events: none;
  animation: anchor-arrow-pulse 1.4s ease-in-out infinite;
}
.ar-anchor-arrow.left  { left: 0.8rem;  }
.ar-anchor-arrow.right { right: 0.8rem; }
.ar-anchor-arrow.left .ar-anchor-arrow-glyph  { transform: rotate(180deg); }
.ar-anchor-arrow.right .ar-anchor-arrow-glyph { transform: none; }
.ar-anchor-arrow[hidden] { display: none !important; }
@keyframes anchor-arrow-pulse {
  0%, 100% { transform: scale(1);    opacity: 0.85; }
  50%      { transform: scale(1.12); opacity: 1; }
}
/* Lottie injects its SVG into .lottie-host so the fallback emoji
   (a sibling) is never clobbered by the renderer. */
.lottie-discovery .lottie-host,
.reveal-discovery .lottie-host {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

/* Shared static emoji fallback inside #lottie-discovery and
   #reveal-discovery. Absolute-centered so it sits behind any Lottie
   SVG that loads. Wiggle animation so it feels alive. */
.discovery-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(80px, 42vw, 240px);
  line-height: 1;
  pointer-events: none;
  filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.5));
  animation: discovery-wiggle 1.6s ease-in-out infinite;
}
.lottie-discovery.lottie-loaded .discovery-fallback,
.lottie-reveal-asset.lottie-loaded .discovery-fallback,
.reveal-discovery.lottie-loaded .discovery-fallback {
  display: none;
}
@keyframes discovery-wiggle {
  0%, 100% { transform: translateY(0) rotate(-4deg); }
  50%      { transform: translateY(-6px) rotate(4deg); }
}

/* Compass permission prompt inside the camera overlay. Shown when device
   orientation hasn't been granted yet. The button inside provides the fresh
   user gesture iOS needs for DeviceOrientationEvent.requestPermission(). */
.camera-compass-prompt {
  position: absolute;
  left: 50%;
  bottom: calc(1.5rem + env(safe-area-inset-bottom, 0));
  transform: translateX(-50%);
  text-align: center;
  padding: 1.25rem 1.5rem;
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  z-index: 5;
  max-width: 280px;
  backdrop-filter: blur(6px);
}
.camera-compass-prompt p { margin: 0; }
.camera-compass-prompt .btn {
  min-width: 180px;
}
.camera-compass-prompt[hidden] { display: none !important; }

.camera-hint {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  transition: opacity 0.5s ease;
  padding: 0.5rem 0.9rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 0.82rem;
  letter-spacing: 0.02em;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  z-index: 4;
  backdrop-filter: blur(6px);
}

/* AR compass + icons were historically siblings of .clue-card (absolute
   positioning relative to #overlay). They now live inside .camera-overlay
   — same positioned-ancestor contract, so their `top: 20%` / `top: 30%`
   offsets still compose correctly. Bump z-index so they paint above the
   video but below the close button. */
.camera-overlay .ar-compass { z-index: 3; }
.camera-overlay .ar-icons { z-index: 2; }

/* ---------- Map reveal modal (in-app Leaflet bottom sheet) ---------- */
.map-reveal-modal {
  position: fixed;
  inset: 0;
  z-index: 80;                 /* above camera overlay, below completion */
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  pointer-events: auto;
}
.map-reveal-modal[hidden] { display: none !important; }
.map-reveal-inner {
  background: var(--card);
  width: 100%;
  max-width: 520px;
  border-radius: 20px 20px 0 0;
  padding: 0.75rem 1.25rem calc(1.25rem + env(safe-area-inset-bottom, 0));
  box-shadow: 0 -24px 60px -20px rgba(0, 0, 0, 0.7);
  animation: map-reveal-slide-up 280ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
@keyframes map-reveal-slide-up {
  from { transform: translateY(30%); opacity: 0.4; }
  to   { transform: translateY(0);   opacity: 1; }
}
.map-reveal-inner h2 {
  margin: 0.25rem 0 0.65rem;
  font-size: 1.15rem;
  color: var(--fg);
}
.map-reveal-map {
  width: 100%;
  height: 260px;
  border-radius: 12px;
  border: 1px solid var(--border);
  overflow: hidden;
  background: #0a0f23;
}
.map-reveal-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.85rem;
}
.map-target-pin--lg {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: radial-gradient(circle, #ff8a5c 0%, var(--accent) 70%);
  border: 3px solid #fff;
  box-shadow: 0 0 0 3px rgba(233, 79, 55, 0.35), 0 4px 10px rgba(0, 0, 0, 0.45);
}

/* ══════════════════════════════════════════════════════════════════════
   SHARED 401 / SESSION-EXPIRED FLOW (PR F)
   ══════════════════════════════════════════════════════════════════════ */

/* Toast — fixed bottom-right notification used by common.js showToast().
   Auto-dismissed after ~3s. Stacks if multiple fire. */
.toast-container {
  position: fixed;
  bottom: calc(1rem + env(safe-area-inset-bottom, 0));
  right: 1rem;
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  pointer-events: none;
  max-width: calc(100vw - 2rem);
}
.toast {
  background: rgba(15, 22, 48, 0.95);
  color: var(--fg);
  border: 1px solid rgba(79, 195, 247, 0.35);
  border-radius: 10px;
  padding: 0.7rem 1rem;
  font-size: 0.9rem;
  line-height: 1.35;
  box-shadow: 0 10px 28px -10px rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(6px);
  pointer-events: auto;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 200ms ease, transform 200ms ease;
}
.toast--visible {
  opacity: 1;
  transform: translateY(0);
}
.toast--error {
  border-color: rgba(233, 79, 55, 0.55);
  color: #ffd4cb;
}

/* Banner inside #auth-panel, shown by app.js when the user arrived via
   a ?return= session-expired redirect. Tells them why they're on the
   login form and what they'll get back to. */
.return-banner {
  background: rgba(245, 183, 0, 0.12);
  border: 1px solid rgba(245, 183, 0, 0.45);
  color: #f5b700;
  padding: 0.6rem 0.85rem;
  border-radius: 8px;
  font-size: 0.88rem;
  margin-bottom: 1rem;
  line-height: 1.35;
}

/* ---------- Landing page (marketing home for authenticated users) ---------- */
.landing-hero {
  position: relative;
  margin: -1.25rem -1.25rem 1.5rem;
  border-radius: 0 0 16px 16px;
  overflow: hidden;
  min-height: 280px;
}
.landing-hero-img {
  width: 100%;
  height: 320px;
  object-fit: cover;
  display: block;
}
.landing-hero-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(10,15,35,0.25) 0%, rgba(10,15,35,0.92) 75%);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 1.5rem 1.25rem;
}
.landing-headline {
  margin: 0 0 0.5rem;
  font-size: 1.6rem;
  line-height: 1.2;
  color: #fff;
  font-weight: 700;
}
.landing-tagline {
  margin: 0 0 1rem;
  color: rgba(255, 255, 255, 0.8);
  font-size: 0.95rem;
  line-height: 1.4;
}
.landing-cta {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  font-size: 1rem;
  font-weight: 600;
  border-radius: 8px;
  text-align: center;
  text-decoration: none;
  width: 100%;
}

/* How it works: 3-step row */
.landing-how { margin: 2rem 0; }
.landing-how h2 { margin: 0 0 1rem; font-size: 1.2rem; }
.landing-steps {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.landing-step {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem;
}
.landing-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-weight: 700;
  font-size: 0.85rem;
  margin-bottom: 0.5rem;
}
.landing-step h3 { margin: 0 0 0.3rem; font-size: 1rem; }
.landing-step p { margin: 0; color: var(--muted); font-size: 0.9rem; line-height: 1.4; }

/* Active hunts / state chips */
.landing-locations { margin: 2rem 0; }
.landing-locations h2 { margin: 0 0 0.5rem; font-size: 1.2rem; }
.landing-state-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.75rem 0;
}
.landing-state-chip {
  background: rgba(79, 195, 247, 0.1);
  border: 1px solid rgba(79, 195, 247, 0.35);
  color: var(--accent-2);
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
}
.landing-state-chip:hover {
  background: rgba(79, 195, 247, 0.2);
  color: #fff;
}
.landing-browse {
  display: inline-block;
  margin-top: 0.75rem;
  padding: 0.65rem 1rem;
  border-radius: 8px;
  text-align: center;
  text-decoration: none;
  font-size: 0.9rem;
}

@media (min-width: 600px) {
  .landing-steps { flex-direction: row; }
  .landing-step { flex: 1; }
  .landing-steps-4 { flex-wrap: wrap; }
  .landing-steps-4 .landing-step { flex: 1 1 calc(50% - 0.5rem); }
}

/* Step icon — replaces the numbered circle for the 4-step explainer.
   Just an emoji in a soft square so it stays visual without needing
   extra image assets. */
.landing-step-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: rgba(79, 195, 247, 0.12);
  font-size: 1.25rem;
  margin-bottom: 0.5rem;
}

/* Intro paragraph under the hero. */
.landing-intro {
  margin: 1.5rem 0;
}
.landing-intro p {
  margin: 0;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.55;
}

/* Section lead — the muted intro paragraph that sits under each h2. */
.landing-section-lead {
  margin: 0.25rem 0 1rem;
  font-size: 0.92rem;
  line-height: 1.45;
}

/* ---------- "What's the AR part?" explainer ---------- */
.landing-ar { margin: 2.5rem 0; }
.landing-ar h2 { margin: 0 0 0.25rem; font-size: 1.2rem; }
.landing-ar .landing-section-lead { margin: 0 0 1rem; }
.landing-ar-grid {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.landing-ar-figure {
  position: relative;
  width: 100%;
  max-width: 380px;
  margin: 0 auto;
  aspect-ratio: 16 / 9;
  border-radius: 12px;
  overflow: hidden;
  background: #000;
  border: 1px solid var(--border);
}
.landing-ar-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.landing-ar-scrim {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at center 65%, rgba(10, 15, 35, 0.55) 0%, rgba(10, 15, 35, 0.15) 55%, rgba(10, 15, 35, 0) 80%),
    linear-gradient(180deg, rgba(10, 15, 35, 0.05) 0%, rgba(10, 15, 35, 0.45) 100%);
  pointer-events: none;
}
.landing-ar-arrow {
  position: absolute;
  left: 50%;
  top: 26%;
  width: 14%;
  max-width: 64px;
  transform: translateX(-50%);
  filter: drop-shadow(0 0 8px rgba(255, 200, 80, 0.85)) drop-shadow(0 2px 4px rgba(0, 0, 0, 0.4));
  pointer-events: none;
}
.landing-ar-compass {
  position: absolute;
  left: 50%;
  top: 55%;
  width: 24%;
  max-width: 110px;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 0 12px rgba(79, 195, 247, 0.55)) drop-shadow(0 4px 8px rgba(0, 0, 0, 0.5));
  opacity: 0.95;
  pointer-events: none;
}
.landing-ar-distance {
  position: absolute;
  left: 50%;
  bottom: 10%;
  transform: translateX(-50%);
  text-align: center;
  color: #fff;
  background: rgba(10, 15, 35, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 999px;
  padding: 0.35rem 0.85rem;
  font-size: 0.85rem;
  line-height: 1.1;
  pointer-events: none;
}
.landing-ar-distance strong {
  display: block;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.landing-ar-distance span {
  display: block;
  font-size: 0.7rem;
  color: rgba(255, 255, 255, 0.75);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-top: 0.1rem;
}
.landing-ar-badge {
  position: absolute;
  top: 0.6rem;
  left: 0.6rem;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #fff;
  background: rgba(220, 50, 50, 0.85);
  border-radius: 4px;
  padding: 0.18rem 0.5rem;
}
.landing-ar-badge::before {
  content: "● ";
  color: #fff;
}
.landing-ar-copy p { margin: 0 0 0.75rem; font-size: 0.95rem; line-height: 1.5; }
.landing-ar-copy p:last-child { margin-bottom: 0; }
@media (min-width: 720px) {
  .landing-ar-grid {
    flex-direction: row;
    align-items: stretch;
    gap: 1.5rem;
  }
  .landing-ar-figure { flex: 1 1 55%; max-width: none; margin: 0; }
  .landing-ar-copy { flex: 1 1 45%; align-self: center; }
}

/* ---------- Hunt format cards ---------- */
.landing-formats { margin: 2.5rem 0; }
.landing-formats h2 { margin: 0 0 0.25rem; font-size: 1.2rem; }
.landing-format-cards {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.landing-format-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.landing-format-img {
  width: 100%;
  height: 160px;
  object-fit: cover;
  display: block;
}
.landing-format-body {
  padding: 1rem;
}
.landing-format-tag {
  display: inline-block;
  background: rgba(233, 79, 55, 0.15);
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  margin-bottom: 0.5rem;
}
.landing-format-card h3 {
  margin: 0 0 0.4rem;
  font-size: 1.05rem;
}
.landing-format-card p {
  margin: 0;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.45;
}

@media (min-width: 720px) {
  .landing-format-cards { flex-direction: row; }
  .landing-format-card { flex: 1; }
}

/* ---------- Hint progression list ---------- */
.landing-hints { margin: 2.5rem 0; }
.landing-hints h2 { margin: 0 0 0.25rem; font-size: 1.2rem; }
.landing-hint-list {
  list-style: none;
  padding: 0;
  margin: 1rem 0 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}
.landing-hint-row {
  display: grid;
  grid-template-columns: minmax(80px, auto) auto 1fr;
  gap: 0.65rem;
  align-items: baseline;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.9rem;
  line-height: 1.4;
}
.landing-hint-row:last-child { border-bottom: none; }
.landing-hint-tier {
  font-weight: 600;
  color: var(--accent-2);
  white-space: nowrap;
}
.landing-hint-cost {
  font-size: 0.78rem;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.04);
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  white-space: nowrap;
  justify-self: start;
}
.landing-hint-text { color: var(--fg); }

/* ---------- City image grid ---------- */
.landing-city-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.6rem;
  margin: 1rem 0 0.75rem;
}
.landing-city-card {
  position: relative;
  display: block;
  border-radius: 10px;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  text-decoration: none;
}
.landing-city-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 200ms ease;
}
.landing-city-card:hover img { transform: scale(1.04); }
.landing-city-label {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 0.5rem 0.7rem;
  background: linear-gradient(180deg, transparent, rgba(10, 15, 35, 0.85));
  color: #fff;
  font-weight: 600;
  font-size: 0.95rem;
}

@media (min-width: 720px) {
  .landing-city-grid { grid-template-columns: repeat(4, 1fr); }
}

/* ---------- Final CTA block ---------- */
.landing-final-cta {
  margin: 2.5rem 0 1rem;
  padding: 1.5rem 1.25rem;
  background: linear-gradient(135deg, rgba(79, 195, 247, 0.12), rgba(233, 79, 55, 0.10));
  border: 1px solid var(--border);
  border-radius: 12px;
  text-align: center;
}
.landing-final-cta h2 { margin: 0 0 0.5rem; font-size: 1.3rem; }
.landing-final-cta p { margin: 0 0 1rem; color: var(--muted); font-size: 0.95rem; }
.landing-final-cta .landing-cta { width: auto; padding: 0.75rem 1.75rem; }

/* ---------- Auth panel heading (when shown below marketing content) ---------- */
.auth-panel-heading {
  margin: 2.5rem 0 0.25rem;
  font-size: 1.2rem;
}
.auth-panel-lead {
  margin: 0 0 1rem;
  font-size: 0.92rem;
  line-height: 1.45;
}

/* ---------- Hunts filter bar + state chips ---------- */
.hunts-filter-bar { margin-bottom: 1rem; }
.state-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-bottom: 0.75rem;
}
.state-chip {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
}
.state-chip.active {
  color: var(--fg);
  border-color: var(--accent-2);
  background: rgba(79, 195, 247, 0.1);
}
.state-chip:hover { border-color: var(--accent-2); color: var(--fg); }
/* Home-state chip — pinned at the head of the short list per
   docs/BROWSE_AND_DISCOVERY.md. Subtle accent so the user can find it. */
.state-chip--home {
  border-color: var(--accent-2);
  background: rgba(79, 195, 247, 0.06);
}
.state-chip--more {
  font-style: italic;
  color: var(--muted);
}

/* ---------- Browse-page location chip + first-visit nudge ----------
   See docs/BROWSE_AND_DISCOVERY.md. Kid-safe defaults: silent, no
   modal, fail open. */
.location-bar {
  margin: 0 0 1rem;
}
.location-chip-host {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}
.location-chip {
  background: var(--card);
  color: var(--fg);
  border: 1px solid var(--accent-2);
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
.location-chip:hover {
  background: rgba(79, 195, 247, 0.12);
}
.location-chip--secondary {
  border-color: var(--border);
  color: var(--muted);
  background: transparent;
}
.location-chip--set {
  background: rgba(79, 195, 247, 0.1);
}
.location-zip-form {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.location-zip-input {
  width: 5rem;
  padding: 0.4rem 0.6rem;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--fg);
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
}
.location-zip-error {
  color: var(--accent-warn, #ffb86b);
  font-size: 0.8rem;
}
.location-nudge {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.6rem;
  padding: 0.5rem 0.75rem;
  background: rgba(79, 195, 247, 0.06);
  border: 1px dashed var(--accent-2);
  border-radius: 10px;
  color: var(--muted);
  font-size: 0.85rem;
}
.location-nudge-dismiss {
  background: transparent;
  border: 0;
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.3rem;
}
.location-nudge-dismiss:hover { color: var(--fg); }

/* ---------- "Your area" pill on a state-section header ---------- */
.state-section-home-pill {
  display: inline-block;
  margin-left: 0.6rem;
  padding: 0.1rem 0.55rem;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent-2);
  background: rgba(79, 195, 247, 0.1);
  border: 1px solid var(--accent-2);
  border-radius: 999px;
  vertical-align: middle;
}

/* ---------- City-tinted placeholder for hunts without a cover_image.
   The inline `style` from cityGradientStyle() seeds the hue; a
   region-neutral image (compass / map / parchment) sits behind the
   gradient at reduced opacity so every card carries a visual without
   risking a wrong-region stock photo. See docs/BROWSE_AND_DISCOVERY.md. */
.hunt-card-img-themed {
  position: relative;
  aspect-ratio: 16 / 9;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.hunt-card-themed-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.55;
  mix-blend-mode: luminosity;
}
.hunt-card-themed-icon {
  width: 38%;
  max-width: 96px;
  opacity: 0.18;
  filter: brightness(2);
  position: absolute;
  inset: auto auto 8% 10%;
  z-index: 1;
}
.hunt-card-themed-title {
  position: relative;
  z-index: 1;
  color: rgba(255, 255, 255, 0.96);
  font-weight: 600;
  font-size: 1.05rem;
  text-align: center;
  padding: 0 1rem;
  line-height: 1.25;
  text-shadow: 0 2px 6px rgba(0, 0, 0, 0.6);
}

/* ---------- Setup page (camera + location prereqs) ----------
   Two-card layout shown before the hunts list when either camera
   permission or location is missing. See docs/BROWSE_AND_DISCOVERY.md. */
.setup-page {
  max-width: 760px;
  margin: 0 auto;
}
.setup-header {
  display: block;
  margin: 1rem 0 1.5rem;
}
.setup-header h1 {
  margin: 0 0 0.5rem;
  font-size: 1.5rem;
  line-height: 1.15;
}
.setup-header p {
  margin: 0;
}
.setup-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.setup-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.setup-card[data-state="granted"],
.setup-card[data-state="set"] {
  border-color: rgba(80, 200, 120, 0.5);
  background: linear-gradient(180deg, rgba(80, 200, 120, 0.06), var(--card));
}
.setup-card[data-state="denied"],
.setup-card[data-state="unavailable"] {
  border-color: rgba(255, 184, 107, 0.45);
}
.setup-card-icon {
  font-size: 1.6rem;
  line-height: 1;
}
.setup-card-title {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 600;
}
.setup-card-status {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  width: fit-content;
}
.setup-card-status--ok {
  color: #50c878;
  background: rgba(80, 200, 120, 0.12);
  border: 1px solid rgba(80, 200, 120, 0.4);
}
.setup-card-status--pending {
  color: var(--accent-2);
  background: rgba(79, 195, 247, 0.1);
  border: 1px solid var(--accent-2);
}
.setup-card-status--blocked {
  color: var(--accent-warn, #ffb86b);
  background: rgba(255, 184, 107, 0.1);
  border: 1px solid rgba(255, 184, 107, 0.45);
}
.setup-card-status--neutral {
  color: var(--muted);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--border);
}
.setup-card-status--cta {
  cursor: pointer;
  padding: 0.45rem 0.95rem;
  font-size: 0.8rem;
  user-select: none;
  transition: background 120ms ease, transform 120ms ease;
}
.setup-card-status--cta:hover {
  background: rgba(79, 195, 247, 0.18);
}
.setup-card-status--cta:active {
  transform: scale(0.97);
}
.setup-card-status--cta:focus-visible {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
}
.setup-card-body {
  margin: 0;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.4;
}
.setup-card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.4rem;
}
.setup-card-btn {
  font-size: 0.9rem;
}
.setup-card-btn-skip {
  background: transparent;
  border: 0;
  color: var(--muted);
  text-decoration: underline;
  cursor: pointer;
  padding: 0.3rem 0.5rem;
  font-size: 0.85rem;
}
.setup-card-btn-skip:hover { color: var(--fg); }
.setup-zip-form {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.setup-zip-input {
  width: 5rem;
  padding: 0.4rem 0.6rem;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--fg);
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
}
.setup-zip-error {
  color: var(--accent-warn, #ffb86b);
  font-size: 0.8rem;
}
.setup-footer {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  align-items: center;
  margin-top: 1rem;
  text-align: center;
}
.setup-footer .btn {
  min-width: 12rem;
}
.setup-footer-hint {
  margin: 0;
  font-size: 0.85rem;
}

/* ---------- Stops table of contents (hunt-detail.html) ---------- */
.stops-toc { margin: 1.5rem 0; }
.stops-toc-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.stops-toc-item {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.stops-toc-item--completed { border-left: 3px solid #a3e635; }
.stops-toc-item--open { border-left: 3px solid var(--accent-2); }
.stops-toc-item--locked { border-left: 3px solid rgba(255,255,255,0.1); opacity: 0.55; }

.stops-toc-item summary,
.stops-toc-link,
.stops-toc-locked {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 0.85rem;
  font-size: 0.95rem;
  min-height: 44px;
  cursor: pointer;
  text-decoration: none;
  color: var(--fg);
}
.stops-toc-link:hover { background: rgba(255,255,255,0.04); }
.stops-toc-locked {
  cursor: pointer;
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  font: inherit;
}
.stops-toc-locked:hover { background: rgba(255,255,255,0.04); }
.stops-toc-item summary { list-style: none; }
.stops-toc-item summary::-webkit-details-marker { display: none; }
.stops-toc-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(255,255,255,0.08);
  font-size: 0.8rem;
  font-weight: 600;
  flex-shrink: 0;
}
.stops-toc-item--completed .stops-toc-num { background: rgba(163,230,53,0.15); color: #a3e635; }
.stops-toc-item--open .stops-toc-num { background: rgba(79,195,247,0.15); color: var(--accent-2); }
.stops-toc-icon { font-size: 0.85rem; flex-shrink: 0; }
.stops-toc-title { flex: 1; font-weight: 500; }
.stops-toc-reveal {
  padding: 0 0.85rem 0.75rem 3.5rem;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.4;
}
.stops-toc-clue {
  margin: 0;
  padding: 0 0.85rem 0.65rem 3.5rem;
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.4;
  font-style: italic;
}

/* Inline paywall card — sits inside the stops-toc list at the boundary
   where the player's access ends. The boxed treatment + accent border
   make the breakpoint obvious without interrupting the stops rhythm. */
.stops-toc-paywall {
  background: rgba(79, 195, 247, 0.06);
  border: 1px solid var(--accent-2);
  border-radius: 12px;
  padding: 1rem;
  margin: 0.75rem 0;
}
@keyframes paywall-flash {
  0%, 100% { background: rgba(79, 195, 247, 0.06); }
  30% { background: rgba(79, 195, 247, 0.22); }
}
.stops-toc-paywall--flash {
  animation: paywall-flash 0.7s ease;
}
.stops-toc-paywall-heading {
  margin: 0 0 0.25rem;
  font-size: 1rem;
  color: var(--accent-2);
}
.stops-toc-paywall-sub {
  margin: 0 0 0.85rem;
  font-size: 0.88rem;
  color: var(--muted);
  line-height: 1.4;
}
.stops-toc-paywall-ctas {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.stops-toc-paywall .anytown-tiers {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}
.stops-toc-paywall .anytown-sub-banner {
  margin-top: 0.5rem;
}

/* "Free" pill rendered next to the first N stops on non-owners' TOC,
   making the free-vs-paid split visible without reading the paywall
   card. Lime green keeps it consistent with the tier-1 group color. */
.stop-free-badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  margin-left: 0.4rem;
  color: #1f2937;
  background: var(--tier-color-g1);
  white-space: nowrap;
}

/* Locked stops on a paywall hunt show "Buy to unlock" + a brighter
   left border so they read as actionable, not as dim placeholders. */
.stops-toc-locked-cta {
  margin-left: auto;
  font-size: 0.78rem;
  color: var(--accent-2);
  font-weight: 600;
  white-space: nowrap;
}
.stops-toc-item.stops-toc-item--paywall {
  opacity: 1;
  border-left-color: var(--accent-2);
}
.stops-toc-locked--cta {
  text-decoration: none;
  color: var(--fg);
}
.stops-toc-locked--cta:hover {
  background: rgba(79, 195, 247, 0.06);
}

/* Quiet pill button beneath the stops list — only rendered after
   purchase on canonical 13-stop hunts. Tapping opens the unlock-modal
   that explains how the tier-2/tier-3 stops gate. */
.unlock-info-btn {
  display: block;
  margin: 1rem auto 0;
  padding: 0.55rem 1.1rem;
  font-size: 0.9rem;
  background: transparent;
  color: var(--accent-2);
  border: 1px solid var(--accent-2);
  border-radius: 999px;
  cursor: pointer;
}
.unlock-info-btn:hover { background: rgba(79, 195, 247, 0.08); }
.unlock-info-btn:focus-visible {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
}

/* Modal overlay — shape mirrors .hint-modal so the two feel like one
   pattern. Higher z-index than the AR compass overlay (60) but below
   the completion modal (150) so a finale celebration still wins. */
.unlock-modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.unlock-modal[hidden] { display: none !important; }
.unlock-modal-inner {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.25rem 1.25rem 1.5rem;
  max-width: 420px;
  width: 100%;
  max-height: calc(100dvh - 2rem);
  overflow-y: auto;
  position: relative;
  animation: hint-modal-pop 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.unlock-modal-title {
  margin: 0 0 0.6rem;
  font-size: 1.05rem;
  color: var(--fg);
}
.unlock-modal-list {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--muted);
}
.unlock-modal-list li + li { margin-top: 0.35rem; }
.unlock-modal-close {
  position: absolute;
  top: 0.4rem;
  right: 0.5rem;
  background: transparent;
  border: none;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 0.5rem 0.6rem;
  border-radius: 6px;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.unlock-modal-close:hover { color: var(--fg); background: rgba(255, 255, 255, 0.06); }
.unlock-modal-close:focus-visible {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
}

/* Inline color pills used inside the unlock modal copy and beside
   locked stop rows. Border + tinted background so they read on dark
   cards. */
.tier-chip {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  border: 1px solid currentColor;
  background: rgba(255, 255, 255, 0.04);
  white-space: nowrap;
}
.tier-chip--g1 { color: var(--tier-color-g1); }
.tier-chip--g2 { color: var(--tier-color-g2); }
.tier-chip--g3 { color: var(--tier-color-g3); }
.tier-chip--finale { color: var(--tier-color-finale); }

/* Per-row tier stripes on the TOC list. Override the default
   .stops-toc-item--{status} left-border so the tier color always wins
   on 13-stop tiered hunts. The status colors still drive the number
   pill background, so completion/open state stays readable. */
.stops-toc-item.toc-row--g1 { border-left: 3px solid var(--tier-color-g1); }
.stops-toc-item.toc-row--g2 { border-left: 3px solid var(--tier-color-g2); }
.stops-toc-item.toc-row--g3 { border-left: 3px solid var(--tier-color-g3); }
.stops-toc-item.toc-row--finale { border-left: 3px solid var(--tier-color-finale); }
/* Tier-2 rows: thicker but dashed accent to signal "depends on the
   matching tier-1 group". The colored stripe + the matching chip in
   the explainer copy carry the relationship; we don't try to tint the
   ✅/📍/🔒 emoji in the row body since the glyphs are full-color on
   most platforms and ignore CSS `color`. */
.stops-toc-item.toc-row--t2 { border-left-style: dashed; border-left-width: 4px; }

/* Inline paywall offer cards — Buy hunt, All Access, Bundle. Same shape
   so the three options read as parallel choices; differentiated by
   tinted background + heading color so the eye can still tell them
   apart. Whole card is a click target (role=button); the inner CTA
   button stops propagation so we don't double-fire checkout. */
.paywall-option-card {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.85rem 1rem;
  border-radius: 0.5rem;
  background: rgba(20, 25, 50, 0.55);
  border: 1px solid var(--border);
  cursor: pointer;
  transition: background-color 0.15s ease, transform 0.05s ease;
}
.paywall-option-card:hover {
  background: rgba(255, 255, 255, 0.05);
}
.paywall-option-card:active {
  transform: scale(0.995);
}
/* The inner <button> owns the tab stop; light up the whole card when
   keyboard focus lands inside so the focused area still reads as a
   single offer, not just a button. */
.paywall-option-card:focus-within {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
}
.paywall-option-heading {
  margin: 0;
  font-size: 1rem;
  color: var(--fg);
}
.paywall-option-price {
  font-size: 1.05rem;
  font-weight: 700;
}
.paywall-option-sub {
  font-size: 0.88rem;
  color: var(--muted);
  line-height: 1.4;
}
.paywall-option-cta {
  width: 100%;
  margin-top: 0.35rem;
}

/* Variant: Buy this hunt — warm red to match the primary checkout CTA. */
.paywall-option-card--hunt {
  background: rgba(229, 62, 62, 0.10);
  border-color: rgba(229, 62, 62, 0.45);
}
.paywall-option-card--hunt:hover {
  background: rgba(229, 62, 62, 0.16);
}
.paywall-option-card--hunt .paywall-option-heading {
  color: #f87171;
}

/* Variant: All Access — gold gradient (subscription tier). */
.paywall-option-card--all-access {
  background: linear-gradient(135deg, rgba(194, 124, 10, 0.22), rgba(246, 173, 85, 0.16));
  border-color: rgba(246, 173, 85, 0.45);
}
.paywall-option-card--all-access:hover {
  background: linear-gradient(135deg, rgba(194, 124, 10, 0.30), rgba(246, 173, 85, 0.24));
}
.paywall-option-card--all-access .paywall-option-heading {
  color: #f6ad55;
}

/* Variant: Bundle — accent-blue tint, paired with the existing
   .paywall-bundle-* classes that style the inner hunt-titles list. */
.paywall-option-card--bundle {
  background: rgba(79, 195, 247, 0.10);
  border-color: var(--accent-2);
}
.paywall-option-card--bundle:hover {
  background: rgba(79, 195, 247, 0.16);
}
.paywall-bundle-heading {
  color: var(--accent-2);
}
.paywall-bundle-savings {
  display: inline-block;
  margin-left: 0.35rem;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: rgba(72, 187, 120, 0.22);
  border: 1px solid rgba(72, 187, 120, 0.5);
  color: #9ae6b4;
  font-size: 0.78rem;
  font-weight: 600;
  vertical-align: middle;
}
.paywall-bundle-hunts {
  margin: 0.15rem 0 0.25rem;
  padding-left: 1.1rem;
  font-size: 0.88rem;
  color: var(--muted);
  line-height: 1.4;
}
.paywall-bundle-hunts li {
  margin: 0.1rem 0;
}
.paywall-bundle-more {
  list-style: none;
  margin-left: -1.1rem;
  font-style: italic;
  opacity: 0.85;
}
/* Quiet "see all pricing options" link below the three offer cards. */
.paywall-pricing-link {
  display: block;
  text-align: center;
  margin-top: 0.85rem;
  font-size: 0.85rem;
  color: var(--accent-2);
  text-decoration: none;
}
.paywall-pricing-link:hover {
  text-decoration: underline;
}
.paywall-pricing-link:focus-visible {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Site-wide footer injected by common.js renderSiteFooter(). Mirrors
   main's 520px constraint so it lines up beneath the content column. */
.site-footer {
  margin: 3rem auto 1rem;
  padding: 1.5rem 1.25rem 0;
  max-width: 520px;
  border-top: 1px solid var(--border);
  text-align: center;
  font-size: 0.85rem;
  color: var(--muted);
}
.site-footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  justify-content: center;
  margin-bottom: 0.6rem;
}
.site-footer-links a {
  color: var(--muted);
  text-decoration: none;
}
.site-footer-links a:hover,
.site-footer-links a:focus {
  color: var(--fg);
  text-decoration: underline;
}
.site-footer-copy {
  font-size: 0.8rem;
  opacity: 0.7;
}

/* ══════════════════════════════════════════════════════════════════════
   CUSTOM QUOTE FORM  (contact page)
   ══════════════════════════════════════════════════════════════════════ */
.quote-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.1rem;
  margin: 1rem 0 1.5rem;
}
.quote-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
}
@media (max-width: 520px) {
  .quote-row { grid-template-columns: 1fr; }
}
.quote-form label { gap: 0.35rem; }
.quote-form textarea {
  padding: 0.6rem 0.75rem;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  color: var(--fg);
  font-family: inherit;
  font-size: 1rem;
  resize: vertical;
}
.quote-form input[type="range"] {
  padding: 0;
  background: transparent;
  border: none;
}
.quote-range-value {
  color: var(--fg);
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
}
.quote-required { color: var(--accent); }
.quote-optional { color: var(--muted); font-weight: normal; font-size: 0.8rem; }

.quote-packages {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.6rem 0.9rem 0.8rem;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.quote-packages legend {
  color: var(--muted);
  font-size: 0.85rem;
  padding: 0 0.35rem;
}
.quote-pkg {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 0.6rem;
  padding: 0.55rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  color: var(--fg);
  font-size: 0.95rem;
}
.quote-pkg:hover { border-color: rgba(79, 195, 247, 0.5); }
.quote-pkg input[type="radio"] { margin: 0; }
.quote-pkg:has(input[type="radio"]:checked) {
  border-color: var(--accent-2);
  background: rgba(79, 195, 247, 0.08);
}
.quote-pkg-title { font-weight: 600; }
.quote-pkg-meta { color: var(--muted); font-size: 0.85rem; }
.quote-pkg-price { font-variant-numeric: tabular-nums; color: var(--fg); font-weight: 600; }

.quote-extras {
  flex-direction: row !important;
  align-items: flex-start;
  gap: 0.6rem !important;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  color: var(--fg);
  font-size: 0.92rem;
}
.quote-extras input[type="checkbox"] { margin-top: 0.2rem; }
.quote-extras-price {
  color: var(--muted);
  margin-left: 0.4rem;
  font-variant-numeric: tabular-nums;
}

.quote-total {
  font-size: 1rem;
  color: var(--muted);
  padding-top: 0.4rem;
  border-top: 1px solid var(--border);
}
.quote-total strong {
  color: var(--fg);
  font-size: 1.15rem;
  font-variant-numeric: tabular-nums;
  margin-left: 0.35rem;
}

.quote-success {
  margin: 0;
  color: #a3e635;
  font-size: 0.95rem;
}

.quote-map-block {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.quote-map-panel {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.6rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
}
.quote-map-help {
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
}
.quote-map {
  height: 320px;
  width: 100%;
  border-radius: 6px;
  overflow: hidden;
  background: #121830;
}
.quote-map-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.quote-map-stats {
  font-size: 0.85rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.quote-map-error { margin: 0; min-height: 1.1em; }

/* ══════════════════════════════════════════════════════════════════════
   ADMIN · QUOTES PAGE
   ══════════════════════════════════════════════════════════════════════ */
.admin-quotes-main {
  max-width: 960px;
  margin: 0 auto;
  padding: 1.25rem;
}
.quote-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 1rem;
}
.quote-filter {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
}
.quote-filter.active {
  color: var(--fg);
  border-color: var(--accent-2);
  background: rgba(79, 195, 247, 0.1);
}
.quote-filter-count {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.quote-filter.active .quote-filter-count { color: var(--fg); }

.quote-filter-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}
.quote-filter-group .quote-filters { margin-bottom: 0; }
.quote-filter-label {
  color: var(--muted);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  flex-shrink: 0;
}
.quote-card-lifecycle {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--muted);
  flex-shrink: 0;
}
.quote-card-lifecycle[data-lifecycle="requested"] {
  background: rgba(79, 195, 247, 0.15); color: #a5dcff;
}
.quote-card-lifecycle[data-lifecycle="awaiting_feedback"] {
  background: rgba(255, 215, 0, 0.15); color: #ffe486;
}
.quote-card-lifecycle[data-lifecycle="paid"] {
  background: rgba(163, 230, 53, 0.18); color: #c6f086;
}
.quote-card-lifecycle[data-lifecycle="in_progress"] {
  background: rgba(186, 104, 200, 0.18); color: #e1b6f0;
}
.quote-card-lifecycle[data-lifecycle="shipped"] {
  background: rgba(79, 195, 247, 0.22); color: #c8e9ff;
}
.quote-card-lifecycle[data-lifecycle="live"] {
  background: rgba(76, 175, 80, 0.22); color: #b8efb6;
}
.quote-card-lifecycle[data-lifecycle="deprecated"] {
  background: rgba(255, 255, 255, 0.05); color: var(--muted);
}

.quote-empty {
  color: var(--muted);
  padding: 2rem 0;
  text-align: center;
  font-style: italic;
}

.quote-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}
.quote-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.quote-card-summary {
  width: 100%;
  display: block;
  text-align: left;
  background: transparent;
  color: var(--fg);
  border: none;
  padding: 0.85rem 1rem;
  cursor: pointer;
  font: inherit;
}
.quote-card-summary:hover { background: rgba(255, 255, 255, 0.03); }
.quote-card-summary.open { background: rgba(79, 195, 247, 0.06); }
.quote-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.25rem;
}
.quote-card-email {
  font-weight: 600;
  font-size: 0.95rem;
  word-break: break-all;
}
.quote-card-status {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--muted);
  flex-shrink: 0;
}
.quote-card-status[data-status="new"] {
  background: rgba(233, 79, 55, 0.15); color: #ffb4a8;
}
.quote-card-status[data-status="contacted"] {
  background: rgba(79, 195, 247, 0.15); color: #a5dcff;
}
.quote-card-status[data-status="quoted"] {
  background: rgba(255, 215, 0, 0.15); color: #ffe486;
}
.quote-card-status[data-status="won"] {
  background: rgba(163, 230, 53, 0.15); color: #c6f086;
}
.quote-card-status[data-status="lost"],
.quote-card-status[data-status="archived"] {
  background: rgba(255, 255, 255, 0.05); color: var(--muted);
}
.quote-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  color: var(--muted);
  font-size: 0.82rem;
}
.quote-card-body {
  padding: 0 1rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  border-top: 1px solid var(--border);
  padding-top: 0.85rem;
  margin-top: 0;
}
.quote-details {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 0.5rem 1rem;
  margin: 0;
  font-size: 0.88rem;
}
.quote-details > div { display: flex; flex-direction: column; gap: 0.1rem; }
.quote-details dt {
  color: var(--muted);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.quote-details dd { margin: 0; color: var(--fg); }
.quote-details-notes { gap: 0.35rem; }
.quote-notes-readonly {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.6rem 0.75rem;
  color: var(--fg);
  font-size: 0.9rem;
  white-space: pre-wrap;
  min-height: 2.4em;
}
.quote-card-body select,
.quote-card-body textarea {
  padding: 0.55rem 0.7rem;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  color: var(--fg);
  font-family: inherit;
  font-size: 0.95rem;
}
.quote-card-body textarea { resize: vertical; }
.quote-save-status {
  font-size: 0.85rem;
  color: #a3e635;
  align-self: center;
}
.quote-save-status.error { color: #ff7070; }

.quote-details-geofence {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.6rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(79, 195, 247, 0.04);
}
.quote-geofence-stats {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  flex-wrap: wrap;
  font-size: 0.85rem;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}
.quote-geofence-label {
  color: var(--muted);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.quote-admin-map {
  height: 220px;
  width: 100%;
  border-radius: 6px;
  overflow: hidden;
  background: #121830;
}

/* ── AI draft panel ── */
.quote-ai-panel {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 0.7rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(163, 230, 53, 0.04);
}
.quote-ai-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.6rem;
}
.quote-ai-label {
  color: var(--muted);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.quote-ai-rating {
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  padding: 0.12rem 0.55rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--fg);
}
.quote-ai-rating[data-tier="good"] { background: rgba(163, 230, 53, 0.2); color: #c6f086; }
.quote-ai-rating[data-tier="marginal"] { background: rgba(255, 215, 0, 0.2); color: #ffe486; }
.quote-ai-rating[data-tier="poor"] { background: rgba(233, 79, 55, 0.2); color: #ffb4a8; }

.quote-ai-empty,
.quote-ai-drafting {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.quote-ai-empty p,
.quote-ai-drafting p { margin: 0; }

.quote-ai-draft {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.quote-ai-rubric summary,
.quote-ai-yaml summary {
  cursor: pointer;
  color: var(--muted);
  font-size: 0.85rem;
  padding: 0.25rem 0;
}
.quote-ai-rubric dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.25rem 0.75rem;
  margin: 0.35rem 0;
  font-size: 0.88rem;
}
.quote-ai-rubric dt {
  color: var(--muted);
  text-transform: capitalize;
}
.quote-ai-rubric dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.quote-ai-yaml pre {
  max-height: 320px;
  overflow: auto;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.65rem;
  font-size: 0.8rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  white-space: pre-wrap;
  color: var(--fg);
}
.quote-ai-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.quote-ai-override {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.82rem;
  color: var(--muted);
  cursor: pointer;
}
.quote-ai-reject-panel {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.55rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: rgba(255, 112, 112, 0.04);
}
.quote-ai-reject-panel textarea {
  padding: 0.5rem 0.65rem;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  color: var(--fg);
  font-family: inherit;
  font-size: 0.9rem;
  resize: vertical;
}
.quote-ai-linked {
  margin: 0;
  font-size: 0.85rem;
  color: #a3e635;
}
.quote-ai-error { margin: 0; min-height: 1.1em; }

/* =============================================================================
   PAYMENTS — hunt-card price chip, hunt-detail buy CTAs, /purchases page
   ============================================================================= */

/* Anytown hunt-detail purchase panel: three tier cards side-by-side
   with a subscription banner above. Mirrors the existing .btn family so
   visual weight matches the standard-hunt price chip. */
.anytown-purchase-panel {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 1rem;
  border-radius: 0.75rem;
  background: rgba(14, 18, 42, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.08);
  margin: 1rem 0;
}
.anytown-sub-banner {
  padding: 0.75rem 1rem;
  border-radius: 0.5rem;
  background: linear-gradient(135deg, rgba(194, 124, 10, 0.25), rgba(246, 173, 85, 0.18));
  border: 1px solid rgba(246, 173, 85, 0.45);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.anytown-tiers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.75rem;
}
.anytown-tier {
  padding: 0.75rem;
  border-radius: 0.5rem;
  background: rgba(20, 25, 50, 0.7);
  border: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.anytown-tier h4 { margin: 0; font-size: 1rem; }
.anytown-tier .price { font-size: 1.1rem; font-weight: 700; }
.anytown-tier .range { font-size: 0.85rem; opacity: 0.8; }
.anytown-tier--owned {
  opacity: 0.6;
  background: rgba(49, 130, 206, 0.25);
}

/* Per-stop lock badges on the TOC / stops overview. The ?? icon sits
   inline so a kid can tell which stops are still to unlock at a glance. */
.stop-lock-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.1rem 0.45rem;
  margin-left: 0.4rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  background: rgba(194, 124, 10, 0.35);
  color: #f6ad55;
  border: 1px solid rgba(246, 173, 85, 0.4);
}

/* Local Legend badge on stops-toc rows (Strava-style — most visits in
 * the rolling 90 day window). Inline with the stop title; gold to read
 * as "trophy" without competing with the green "completed" border or
 * the blue accent. Same shape and weight as .stop-lock-badge — both
 * are inline metadata pills, distinguished only by color (gold here,
 * orange there). */
.toc-legend-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  padding: 0.08rem 0.45rem;
  margin-left: 0.4rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  background: rgba(245, 183, 0, 0.18);
  color: #f5b700;
  border: 1px solid rgba(245, 183, 0, 0.45);
  white-space: nowrap;
}

/* Subscription card on /profile.html — shows status + "Manage" CTA
   that opens Stripe's hosted Customer Portal. */
.subscription-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem;
  border-radius: 0.75rem;
  background: rgba(20, 25, 50, 0.7);
  border: 1px solid rgba(255, 255, 255, 0.08);
  flex-wrap: wrap;
}
.subscription-status {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  background: rgba(160, 160, 160, 0.25);
}
.subscription-status--active {
  background: rgba(56, 161, 105, 0.3);
  color: #9ae6b4;
}
.subscription-status--warn {
  background: rgba(214, 158, 46, 0.3);
  color: #faf089;
}
.subscription-status--off {
  background: rgba(120, 120, 120, 0.25);
  color: #cbd5e0;
}

/* Inline badges used in the admin Anytown overlay list. Three subtle
   variants so source/state distinctions read at a glance. */
.badge {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  margin-left: 0.3rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: rgba(160, 160, 160, 0.25);
  color: #cbd5e0;
}
.badge--info { background: rgba(49, 130, 206, 0.3); color: #90cdf4; }
.badge--accent { background: rgba(56, 161, 105, 0.3); color: #9ae6b4; }
.badge--warn { background: rgba(214, 158, 46, 0.3); color: #faf089; }

.archetype-list {
  list-style: disc;
  padding-left: 1.25rem;
  margin: 0;
}

/* Buy CTA buttons on hunt-detail piggy-back on the existing .btn /
   .btn-secondary styles — no new selectors needed. The post-purchase
   "Finalizing…" status uses .muted; only need a subtle progress hint. */
#post-paid-status::after {
  content: "";
  display: inline-block;
  width: 0.6em;
  margin-left: 0.4em;
  animation: post-paid-dots 1.2s steps(4, end) infinite;
}
@keyframes post-paid-dots {
  0%   { content: ""; }
  25%  { content: "."; }
  50%  { content: ".."; }
  75%  { content: "..."; }
  100% { content: ""; }
}

/* Owned hunts + receipts list on /profile.html (My Account). */
.owned-hunts {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.owned-hunts li {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  padding: 0.5rem 0.85rem;
}
.owned-hunts a { color: inherit; text-decoration: none; }
.owned-hunts a:hover { text-decoration: underline; }

.purchases-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 0.75rem;
}
.purchases-table th,
.purchases-table td {
  text-align: left;
  padding: 0.5rem 0.7rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 0.9rem;
}
.purchases-table th {
  color: #9aa3c7;
  font-weight: 600;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.purchases-table code {
  font-size: 0.82rem;
  background: rgba(255, 255, 255, 0.06);
  padding: 0.05rem 0.35rem;
  border-radius: 4px;
}

/* =============================================================================
   ADMIN CONSOLE — asset index + asset preview pages
   ============================================================================= */
.asset-index-page,
.asset-preview-page {
  max-width: 1080px;
  margin: 0 auto;
  padding: 1.5rem 1rem 4rem;
}

.asset-index-header,
.asset-preview-header {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.25rem;
  justify-content: flex-start;
}

.asset-index-header h1,
.asset-preview-header h1 {
  margin: 0 0 0.5rem;
  font-size: 1.6rem;
}

.asset-index-header p,
.asset-preview-header p {
  margin: 0;
}

.asset-index-controls {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  flex-wrap: wrap;
  margin: 1rem 0 0.75rem;
}

.asset-index-search {
  flex: 1 1 320px;
  min-width: 220px;
  padding: 0.55rem 0.75rem;
  font-size: 1rem;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.04);
  color: inherit;
}

.asset-index-search:focus {
  outline: 2px solid var(--accent, #4a9eff);
  outline-offset: 2px;
}

.asset-index-tree {
  margin-top: 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.asset-index-state {
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.02);
  overflow: hidden;
}

.asset-index-state[open] {
  background: rgba(255, 255, 255, 0.04);
}

.asset-index-state-summary {
  cursor: pointer;
  padding: 0.7rem 0.9rem;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  font-weight: 600;
  list-style: none;
}

.asset-index-state-summary::-webkit-details-marker { display: none; }

.asset-index-state-summary::before {
  content: "▶";
  font-size: 0.7em;
  color: var(--accent, #4a9eff);
  transition: transform 0.15s ease;
  display: inline-block;
}

.asset-index-state[open] > .asset-index-state-summary::before {
  transform: rotate(90deg);
}

.state-summary-code {
  font-size: 1.05rem;
  letter-spacing: 0.05em;
}

.state-summary-count {
  font-size: 0.85rem;
}

.asset-index-state-body {
  padding: 0.25rem 0.9rem 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.asset-index-hunt {
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.18);
}

.asset-index-hunt-summary {
  cursor: pointer;
  padding: 0.55rem 0.75rem;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
  list-style: none;
}

.asset-index-hunt-summary::-webkit-details-marker { display: none; }

.asset-index-hunt-summary::before {
  content: "▸";
  color: var(--accent, #4a9eff);
  margin-right: 0.15rem;
  display: inline-block;
  transition: transform 0.15s ease;
}

.asset-index-hunt[open] > .asset-index-hunt-summary::before {
  transform: rotate(90deg);
}

.hunt-summary-title {
  font-weight: 600;
}

.hunt-summary-slug {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.85rem;
}

.hunt-summary-count {
  font-size: 0.85rem;
}

.asset-index-hunt-body {
  padding: 0 0.75rem 0.75rem;
}

.stop-card {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 0.7rem 0.8rem;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 0.5rem;
  background: rgba(255, 255, 255, 0.02);
}

.stop-card + .stop-card {
  margin-top: 0.5rem;
}

.stop-card-head {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.stop-order {
  font-variant-numeric: tabular-nums;
  color: var(--muted, #a8b0c0);
  font-size: 0.85rem;
}

.stop-card-title {
  font-weight: 600;
  font-size: 0.95rem;
  overflow-wrap: anywhere;
}

.stop-card-assets {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 0.6rem;
}

.asset-panel {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.55rem 0.65rem;
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 0.4rem;
  background: var(--card);
  min-width: 0;
}

.asset-panel-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}

.asset-panel-empty {
  background: rgba(255, 255, 255, 0.02);
  border-style: dashed;
}

.asset-panel-missing {
  font-size: 0.85rem;
  font-style: italic;
}

.asset-slug-link {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.85rem;
  color: var(--accent, #4a9eff);
  text-decoration: none;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.asset-slug-link:hover,
.asset-slug-link:focus {
  text-decoration: underline;
}

.asset-slug-empty {
  color: rgba(255, 255, 255, 0.3);
}

.asset-desc {
  font-size: 0.78rem;
  color: var(--muted, #a8b0c0);
  line-height: 1.35;
  overflow-wrap: anywhere;
}

.asset-index-empty {
  margin: 0.4rem 0;
  font-size: 0.9rem;
}

/* Asset group card (slug-first view) */
.asset-group-card {
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
  padding: 1rem 1.1rem 0.9rem;
}

.asset-group-head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin-bottom: 0.35rem;
}

.asset-group-head .asset-slug-link {
  font-size: 1rem;
  font-weight: 600;
}

.asset-use-count {
  font-size: 0.82rem;
}

.asset-group-card .asset-desc {
  margin: 0 0 0.75rem;
  font-size: 0.82rem;
  color: var(--muted, #a8b0c0);
  line-height: 1.4;
}

.asset-usage-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.asset-usage-table th {
  text-align: left;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted, #a8b0c0);
  padding: 0.3rem 0.5rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  font-weight: 600;
}

.asset-usage-table td {
  padding: 0.35rem 0.5rem;
  vertical-align: top;
}

.asset-usage-table tbody tr + tr td {
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}

.ait-num,
.ait-asset {
  color: var(--muted, #a8b0c0);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  width: 2rem;
  text-align: center;
}

/* Asset preview page */
.asset-preview-header .back {
  display: inline-block;
  margin-bottom: 0.4rem;
  color: var(--accent, #4a9eff);
  text-decoration: none;
  font-size: 0.9rem;
}

.asset-preview-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1rem;
  margin: 1rem 0;
}

.asset-preview-card {
  border-radius: 12px;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.asset-preview-card-light {
  background: #f4f1ec;
  color: #222;
}

.asset-preview-card-dark {
  background: #0d1424;
  color: #eee;
}

.asset-preview-label {
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.7;
}

.asset-preview-host {
  width: 280px;
  height: 280px;
  max-width: 80vw;
  display: flex;
  align-items: center;
  justify-content: center;
}

.asset-preview-host > svg {
  max-width: 100%;
  max-height: 100%;
}

.asset-preview-meta {
  margin-top: 1.5rem;
}

.asset-preview-meta h2 {
  font-size: 1.05rem;
  margin: 0 0 0.5rem;
}

.asset-preview-meta-list {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.4rem 1rem;
}

.asset-preview-meta-list .meta-row {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.08);
  padding-bottom: 0.25rem;
}

.asset-preview-meta-list dt {
  color: var(--muted, #a8b0c0);
  font-size: 0.8rem;
  min-width: 6rem;
}

.asset-preview-meta-list dd {
  margin: 0;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.85rem;
}

/* =============================================================================
   REDUCED MOTION — respects OS-level "reduce motion" preference (WCAG 2.1)
   ============================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01s !important;
    scroll-behavior: auto !important;
  }
}

/* ─── Admin asset index — pool catalog view (20260502a) ──────────────── */

.asset-tier-section {
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.02);
  overflow: hidden;
  margin-bottom: 0.5rem;
}
.asset-tier-section[open] { background: rgba(255, 255, 255, 0.04); }
.asset-tier-summary {
  cursor: pointer;
  padding: 0.7rem 0.9rem;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  list-style: none;
}
.asset-tier-summary::-webkit-details-marker { display: none; }
.asset-tier-summary::before {
  content: "▶";
  font-size: 0.7em;
  color: var(--accent, #4a9eff);
  transition: transform 0.15s ease;
  display: inline-block;
}
.asset-tier-section[open] > .asset-tier-summary::before { transform: rotate(90deg); }
.asset-tier-label { font-weight: 700; font-size: 1rem; }
.asset-tier-count { font-size: 0.82rem; color: var(--muted); }
.asset-tier-legendary .asset-tier-label { color: #ffb300; }
.asset-tier-rare      .asset-tier-label { color: #2196f3; }
.asset-tier-uncommon  .asset-tier-label { color: #4caf50; }
.asset-tier-common    .asset-tier-label { color: var(--muted); }

.asset-pool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 0.75rem;
  padding: 0.25rem 0.9rem 0.9rem;
}

.asset-type-badge {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.15rem 0.4rem;
  border-radius: 4px;
  font-weight: 600;
}
.asset-type-animal   { background: rgba(76, 175, 80, 0.15); color: #81c784; }
.asset-type-mythical { background: rgba(255, 193, 7, 0.15); color: #ffb300; }

.asset-style-badge {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.15rem 0.4rem;
  border-radius: 4px;
  font-weight: 600;
}
.asset-style-kawaii       { background: rgba(255, 182, 193, 0.18); color: #f7a8b8; }
.asset-style-chibi-fierce { background: rgba(244, 81, 30, 0.18);  color: #ff8a65; }
.asset-style-heraldic     { background: rgba(255, 215, 0, 0.18);  color: #ffd54f; }
.asset-style-mythic-grand { background: rgba(186, 104, 200, 0.18); color: #ce93d8; }
.asset-style-cosmic       { background: rgba(100, 181, 246, 0.18); color: #90caf9; }
.asset-style-cryptid      { background: rgba(141, 110, 99, 0.18); color: #bcaaa4; }

.asset-backup-emoji {
  font-size: 1em;
  margin-right: 0.15rem;
  filter: saturate(1.05);
}

.asset-filter-pills { display: flex; gap: 0.4rem; }
.asset-filter-pill {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.35rem 0.85rem;
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
  color: var(--fg);
  transition: all 0.15s ease;
}
.asset-filter-pill:hover { border-color: #9c27b0; }
.asset-filter-pill.active {
  background: rgba(156, 39, 176, 0.15);
  border-color: #9c27b0;
  color: #ce93d8;
  font-weight: 600;
}

.scene-assets-section {
  margin-top: 2.5rem;
  border-top: 1px solid var(--border, rgba(255, 255, 255, 0.1));
  padding-top: 1.25rem;
}
.scene-assets-section h2 {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin: 0 0 0.75rem;
}
.scene-assets-row {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.35rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.scene-assets-row:last-child { border-bottom: none; }

/* ── Curiositters landing section ──────────────────────────────────────────── */
.landing-curiositters { margin: 2.5rem 0; }

.landing-curiositters-chest {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.landing-chest-slot {
  width: 140px;
  height: 140px;
  margin: 0 auto 0.75rem;
  flex-shrink: 0;
}

.landing-curiositter-reel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.5rem;
}

.landing-curiositter-slot {
  width: 160px;
  height: 160px;
  background: radial-gradient(circle at 50% 42%, #ffffff 0%, #ecedf3 78%);
  border-radius: 50%;
  box-shadow: inset 0 -3px 8px rgba(0,0,0,.06), 0 1px 3px rgba(0,0,0,.08);
  overflow: hidden;
  position: relative;
}

.landing-curiositter-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2.5rem;
  pointer-events: none;
}

.landing-curiositter-dots {
  display: flex;
  gap: 0.4rem;
}

.landing-curiositter-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-muted, #bbb);
  transition: background 0.3s;
}

.landing-curiositter-dot.is-active {
  background: var(--color-accent, #7c3aed);
}

@media (min-width: 720px) {
  .landing-curiositters-chest { text-align: left; align-items: flex-start; }
}

/* ── Admin Hunts Console ─────────────────────────────────────────────── */
.admin-hunts-main { padding: 1rem 1.25rem 3rem; max-width: 1200px; margin: 0 auto; }
.admin-hunts-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: end;
  justify-content: space-between;
  padding: 0.75rem 0 1rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  margin-bottom: 1rem;
}
.admin-hunts-filters { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.admin-hunts-filters label { display: flex; flex-direction: column; font-size: 0.8rem; gap: 0.25rem; }
.admin-hunts-filters select,
.admin-hunts-filters input[type="search"] {
  min-width: 9rem;
  padding: 0.4rem 0.55rem;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.04);
  color: inherit;
  font-size: 0.9rem;
}
.admin-hunts-toggles { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; font-size: 0.85rem; }
.admin-hunts-toggles label { display: inline-flex; gap: 0.35rem; align-items: center; }

.admin-hunts-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.admin-hunts-table th,
.admin-hunts-table td {
  text-align: left;
  padding: 0.55rem 0.6rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  vertical-align: top;
}
.admin-hunts-table th {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-muted, #999);
  font-weight: 600;
}
.admin-hunts-table tbody tr { cursor: pointer; }
.admin-hunts-table tbody tr:hover { background: rgba(255, 255, 255, 0.04); }
.admin-hunts-table a { color: #4fc3f7; text-decoration: none; font-weight: 600; }
.admin-hunts-table a:hover { text-decoration: underline; }
.admin-hunts-table code { font-size: 0.8rem; color: #a0a0a0; }

.hunt-tag-chip,
.hunt-flag {
  display: inline-block;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  font-size: 0.7rem;
  margin-right: 0.25rem;
  font-weight: 600;
  white-space: nowrap;
}
.hunt-tag-chip { background: rgba(124, 58, 237, 0.18); color: #c4b5fd; }
.hunt-flag { letter-spacing: 0.04em; }
.flag-test { background: rgba(255, 159, 67, 0.2); color: #ffb86c; }
.flag-hidden { background: rgba(150, 150, 150, 0.2); color: #cfcfcf; }
.flag-featured { background: rgba(255, 213, 0, 0.18); color: #ffe066; }
.flag-anytown { background: rgba(79, 195, 247, 0.18); color: #4fc3f7; }
.flag-free { background: rgba(72, 187, 120, 0.2); color: #6ee7a3; }

@media (max-width: 600px) {
  .admin-hunts-main { padding: 0.75rem 0.75rem 2rem; }
  .admin-hunts-filters { width: 100%; }
  .admin-hunts-filters label { flex: 1 1 calc(50% - 0.4rem); min-width: 0; }
  .admin-hunts-filters select,
  .admin-hunts-filters input[type="search"] { min-width: 0; width: 100%; }
  .admin-hunts-toggles { width: 100%; }
  /* Hide Slug (col 2) and Tags (col 6) at narrow widths. Title still
     links through to /admin-hunt.html?slug=…, so the slug column isn't
     load-bearing for navigation. */
  .admin-hunts-table th:nth-child(2),
  .admin-hunts-table td:nth-child(2),
  .admin-hunts-table th:nth-child(6),
  .admin-hunts-table td:nth-child(6) { display: none; }
  .admin-hunts-table { font-size: 0.82rem; }
  .admin-hunts-table th,
  .admin-hunts-table td { padding: 0.45rem 0.4rem; }
}

/* ── Admin Hunt detail page ──────────────────────────────────────────── */
.admin-hunt-detail-main { padding: 1rem 1.25rem 3rem; max-width: 760px; margin: 0 auto; }
.admin-hunt-form { display: flex; flex-direction: column; gap: 1.25rem; }
.admin-section {
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  padding: 0.75rem 1rem 1rem;
  background: rgba(255, 255, 255, 0.02);
}
.admin-section legend {
  padding: 0 0.4rem;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-muted, #aaa);
}
.admin-section label {
  display: block;
  margin-top: 0.6rem;
  font-size: 0.85rem;
}
.admin-section input[type="text"],
.admin-section input[type="number"],
.admin-section input[type="search"],
.admin-section input:not([type]),
.admin-section textarea,
.admin-section select {
  width: 100%;
  padding: 0.45rem 0.6rem;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.04);
  color: inherit;
  font: inherit;
  margin-top: 0.2rem;
}
.admin-section input[readonly] { opacity: 0.65; cursor: not-allowed; }
.admin-section .checkbox-label {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  margin-top: 0.5rem;
}
.admin-section .checkbox-label input[type="checkbox"] {
  margin-top: 0.2rem;
}

.admin-section.read-only { background: rgba(255, 255, 255, 0.01); }
.readonly-grid {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.25rem 0.75rem;
  font-size: 0.85rem;
  margin: 0.5rem 0 0.75rem;
}
.readonly-grid dt { color: var(--color-muted, #999); }
.readonly-grid dd { margin: 0; }

.tag-input-wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  padding: 0.45rem 0.55rem;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.04);
  margin-top: 0.4rem;
}
.tag-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: rgba(124, 58, 237, 0.25);
  color: #ddd6fe;
  font-size: 0.78rem;
  font-weight: 600;
}
.tag-chip-x {
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  font-size: 1rem;
  padding: 0;
  line-height: 1;
}
#tag-input {
  flex: 1;
  min-width: 8rem;
  border: none;
  background: transparent;
  color: inherit;
  font: inherit;
  outline: none;
  padding: 0.15rem 0;
}
