/* TITUSVILLE AGLOW — concept stylesheet
   Cold town. Warm destinations.
   Palette: winter blue-black ground, Titusville Square gold (#DFB971 family)
   for everything human and warm. Fonts follow the Square's system:
   Cormorant Garamond / Montserrat / Tangerine. */

:root {
  --night: #070b13;
  --night-2: #0c1420;
  --night-3: #122036;
  --ice: #e9f0fa;
  --ice-dim: #a9bdd6;
  --ice-faint: #6b8099;
  --gold: #dfb971;
  --gold-bright: #f6d896;
  --gold-glow: rgba(223, 185, 113, 0.35);
  --ember: #ffb84d;
  --warm-white: #fff3dd;
  --panel-bg: rgba(10, 17, 28, 0.82);
  --hairline: rgba(223, 185, 113, 0.22);
  --shadow-deep: 0 24px 70px rgba(0, 0, 0, 0.55);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --serif: 'Cormorant Garamond', Georgia, serif;
  --sans: 'Montserrat', system-ui, sans-serif;
  --script: 'Tangerine', cursive;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  height: 100%;
  overflow: hidden;
  background: var(--night);
  color: var(--ice);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}

button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- snow ---------- */
#snow {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 40;
  opacity: 0.55;
  transition: opacity 0.7s ease;
}
/* during the opening the snow falls in front of the hero (and the train) */
#snow.front { z-index: 62; }

/* ---------- intro / hero ---------- */
#intro {
  position: fixed;
  inset: 0;
  z-index: 60;
  overflow: hidden;
  text-align: center;
  background: var(--night);
  transition: opacity 1.4s var(--ease-out), visibility 1.4s;
}
#intro.gone { opacity: 0; visibility: hidden; pointer-events: none; }

/* the photo world: 2730×1536, JS scales it to cover */
.hero-fit {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
}
.hero-fit img {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}
.hero-train {
  will-change: transform;
  transform-origin: 0 0;
  opacity: 0;
  transition: opacity 0.9s ease;
  z-index: 3;
}
.hero-train.on-track { opacity: 1; }

/* foreground occlusion: overhanging branches + left tree wall, cut from the
   plate itself — the train (sprite or WebGL) passes behind them */
.hero-fg { z-index: 6; pointer-events: none; }
#train3d { z-index: 4; }

/* warm headlight bloom, rides with the locomotive nose */
.headlight {
  position: absolute;
  width: 120px;
  height: 120px;
  margin: -60px 0 0 -60px;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle, rgba(255, 214, 140, 0.55) 0%, rgba(255, 184, 77, 0.22) 40%, transparent 70%);
  mix-blend-mode: screen;
}

.hero-veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(rgba(7, 11, 19, 0.55) 0%, transparent 30%),
    linear-gradient(transparent 62%, rgba(7, 11, 19, 0.72) 100%);
}

.hero-camera {
  position: absolute;
  inset: 0;
  will-change: transform;
  transform-origin: 50% 38%;
}

/* dissolve state: photo layers + title give way to the aerial beneath */
#intro.dissolving { pointer-events: none; }
#intro.dissolving .hero-camera,
#intro.dissolving .hero-veil,
#intro.dissolving #sound-toggle,
#intro.dissolving .hero-skip {
  opacity: 0;
  transition: opacity 1.4s var(--ease-out);
}

#sound-toggle {
  position: absolute;
  top: 18px;
  right: 18px;
  padding: 8px 16px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: rgba(10, 17, 28, 0.55);
  backdrop-filter: blur(8px);
  color: var(--ice-dim);
  font-size: 0.66rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  transition: color 0.3s, background 0.3s;
}
#sound-toggle:hover { color: var(--ice); }
#sound-toggle[aria-pressed='true'] { color: var(--night); background: var(--gold); }

.hero-skip {
  position: absolute;
  bottom: 18px;
  right: 20px;
  font-size: 0.6rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(169, 189, 214, 0.55);
  opacity: 0;
  animation: introRise 1.2s var(--ease-out) 2.4s forwards;
}

/* Concept disclosure. Sits above everything and never hides: a shared preview
   link must always say what it is. Bottom-left, so it never collides with the
   skip hint (bottom-right) or the sound toggle (top-right). */
.concept-note {
  position: fixed;
  z-index: 99;
  bottom: 16px;
  left: 20px;
  max-width: min(46ch, calc(100vw - 40px));
  font-size: 0.58rem;
  line-height: 1.5;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(169, 189, 214, 0.5);
  text-shadow: 0 1px 6px rgba(4, 8, 15, 0.9);
  pointer-events: none;
}
@media (max-width: 600px) {
  .concept-note { font-size: 0.5rem; letter-spacing: 0.1em; bottom: 12px; left: 14px; }
}

/* snow-thickening flash that disguises the dissolve */
#snow.thick { opacity: 1; }

/* the traveling headlight that becomes the first event glow */
#spark {
  position: fixed;
  z-index: 66;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle at 42% 38%, var(--warm-white) 0%, var(--ember) 70%);
  box-shadow: 0 0 14px 4px rgba(255, 184, 77, 0.4);
}

/* ---------- arrival reveal ---------- */
#reveal {
  position: fixed;
  inset: 0;
  z-index: 58;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 24px;
  /* Scrim over the aerial. The map is bright and busy — white street grid on
     snow — and at 0.1 in the centre the reveal copy was competing with it and
     losing. Carries enough weight now for the text to read, while still
     letting the town show through underneath. */
  background: radial-gradient(ellipse at 50% 45%, rgba(7, 11, 19, 0.58) 0%, rgba(7, 11, 19, 0.8) 100%);
  transition: opacity 1s var(--ease-out), visibility 1s;
}
#reveal.leaving { opacity: 0; visibility: hidden; pointer-events: none; }
.reveal-stack { max-width: 640px; }
.reveal-stack > * {
  opacity: 0;
  transform: translateY(12px);
  animation: introRise 1.1s var(--ease-out) forwards;
}
.reveal-stack .intro-title  { animation-delay: 0.15s; }
.reveal-stack .intro-script { animation-delay: 0.5s; }
.reveal-stack .intro-season { animation-delay: 0.85s; }
.reveal-line {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(1.2rem, 2.5vw, 1.55rem);
  color: var(--ice);
  margin-top: 26px;
  animation-delay: 1.3s;
}
.reveal-body {
  font-size: 0.9rem;
  line-height: 1.7;
  color: var(--ice-dim);
  max-width: 460px;
  margin: 12px auto 0;
  animation-delay: 1.55s;
}
.reveal-cta {
  margin-top: 30px;
  padding: 14px 42px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font-size: 0.8rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold-bright);
  background: rgba(223, 185, 113, 0.07);
  backdrop-filter: blur(6px);
  transition: background 0.4s, box-shadow 0.4s;
  animation-delay: 2s;
}
.reveal-cta:hover {
  background: rgba(223, 185, 113, 0.16);
  box-shadow: 0 0 40px var(--gold-glow);
}

.intro-title {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(2.6rem, 7vw, 4.6rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--warm-white);
  text-shadow: 0 0 34px rgba(223, 185, 113, 0.28), 0 2px 18px rgba(0, 0, 0, 0.6);
  animation-delay: 0.35s;
}
.intro-script {
  font-family: var(--script);
  font-size: clamp(2rem, 4.5vw, 3rem);
  font-weight: 400;
  color: var(--gold);
  margin-top: 4px;
  animation-delay: 0.85s;
}
.intro-season {
  font-size: 0.78rem;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--ice-dim);
  margin-top: 18px;
  animation-delay: 1.25s;
}
@keyframes introRise {
  to { opacity: 1; transform: translateY(0); }
}

/* ---------- top bar ---------- */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 20px;
  background: linear-gradient(rgba(7, 11, 19, 0.85), rgba(7, 11, 19, 0));
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.9s var(--ease-out) 0.5s, transform 0.9s var(--ease-out) 0.5s;
  pointer-events: none;
}
body.exploring .topbar { opacity: 1; transform: none; pointer-events: auto; }

.wordmark {
  font-family: var(--serif);
  font-size: 1.05rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--warm-white);
  white-space: nowrap;
}
.wordmark .script {
  font-family: var(--script);
  font-size: 1.5rem;
  text-transform: none;
  letter-spacing: 0;
  color: var(--gold);
  margin-left: 8px;
}

.view-toggle {
  display: flex;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  overflow: hidden;
  background: rgba(10, 17, 28, 0.6);
  backdrop-filter: blur(10px);
}
.view-toggle button {
  padding: 8px 18px;
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ice-dim);
  transition: color 0.3s, background 0.3s;
}
.view-toggle button[aria-pressed='true'] {
  color: var(--night);
  background: var(--gold);
  font-weight: 600;
}

/* ---------- map stage ---------- */
#map-view {
  position: fixed;
  inset: 0;
  /* the map resolves OUT of the white-out rather than simply being uncovered:
     it starts blown out, soft and desaturated — indistinguishable from the
     white above it — and condenses into focus as that white lifts */
  transition: filter 2600ms var(--ease-out), opacity 2000ms var(--ease-out);
}
#map-view.resolving {
  filter: blur(18px) brightness(1.9) saturate(0.3) contrast(0.78);
  opacity: 0.28;
}

.map-stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  touch-action: none;
  cursor: grab;
  background: var(--night);
}
.map-stage.dragging { cursor: grabbing; }

.map-world {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  will-change: transform;
}
.map-world img {
  display: block;
  width: 100%;
  height: 100%;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}

/* vignette over the map, under the UI */
.map-vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  background: radial-gradient(ellipse at 50% 50%, transparent 55%, rgba(7, 11, 19, 0.5) 100%);
}

/* ---------- glowing destination markers ---------- */
.glow {
  position: absolute;
  width: 44px;
  height: 44px;
  margin: -22px 0 0 -22px;
  transform: scale(calc(1 / var(--s, 1)));
  transform-origin: 50% 50%;
  border-radius: 50%;
  opacity: 0;
  transition: opacity 1s var(--ease-out), filter 0.5s;
}
body.lit .glow { opacity: 1; }
.glow .halo { display: none; }
.glow .core {
  position: absolute;
  inset: 18px;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, var(--warm-white) 0%, var(--ember) 70%);
  box-shadow: 0 0 8px 1px rgba(255, 184, 77, 0.45);
  animation: haloBreathe 3.4s ease-in-out infinite;
  animation-delay: var(--stagger, 0s);
}
.glow .chip {
  position: absolute;
  left: 50%;
  top: calc(100% + 2px);
  transform: translateX(-50%);
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  white-space: nowrap;
  color: var(--gold-bright);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.9);
  opacity: 0;
  transition: opacity 0.3s;
}
.glow:hover .chip,
.glow:focus-visible .chip,
.map-stage.zoomed .chip { opacity: 1; }

.glow:hover .core,
.glow:focus-visible .core { box-shadow: 0 0 22px 6px rgba(255, 184, 77, 0.85); }

.glow.dim { opacity: 0.14; filter: saturate(0.2); pointer-events: none; }
body.lit .glow.dim { opacity: 0.14; }
.glow.active .halo { animation-duration: 1.8s; }

@keyframes haloBreathe {
  0%, 100% { transform: scale(1); opacity: 0.8; }
  50% { transform: scale(1.25); opacity: 1; }
}

/* ---------- route glow: light travels the drive-through road ---------- */
.route-layer {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
}
/* the ember string: a faint line of tiny bulbs along the road, part of the
   calm map once the town is lit — the hint that the road itself is a
   destination. Clicking it (via the hit path) opens the event. */
.route-g .route-ember {
  fill: none;
  stroke: rgba(255, 196, 110, 0.55);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 0.5 7.5;
  opacity: 0;
  transition: opacity 1.2s var(--ease-out), stroke 0.3s, stroke-width 0.3s;
  filter: drop-shadow(0 0 3px rgba(255, 184, 77, 0.5));
}
body.lit .route-g:not(.on) .route-ember {
  opacity: 0.7;
  animation: emberShimmer 4.5s ease-in-out infinite;
}
body.lit .route-g:not(.on):hover .route-ember {
  stroke: var(--gold-bright);
  stroke-width: 4.5;
}
.route-g.on .route-ember { opacity: 0; animation: none; }
@keyframes emberShimmer {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 0.95; }
}
/* invisible wide hit area: the road is clickable directly */
.route-g .route-hit {
  fill: none;
  stroke: transparent;
  stroke-width: 34;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: stroke;
  cursor: pointer;
}
/* soft warm bed under the lit road — breathes in with the route */
.route-g .route-under {
  fill: none;
  stroke: rgba(255, 184, 77, 0.16);
  stroke-width: 18;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  transition: opacity 1.6s var(--ease-out);
}
.route-g.on .route-under { opacity: 1; }
/* the road itself, revealed by the traveling light (dash animation in JS) */
.route-g .route-lit {
  fill: none;
  stroke: var(--gold-bright);
  stroke-width: 6.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  filter: drop-shadow(0 0 5px rgba(255, 214, 140, 0.9))
          drop-shadow(0 0 13px rgba(255, 184, 77, 0.55));
  transition: opacity 0.5s ease;
}
.route-g.on .route-lit { opacity: 0.95; }
/* the light doing the traveling — headlights moving through the park */
.route-g .route-comet {
  fill: var(--warm-white);
  opacity: 0;
  filter: drop-shadow(0 0 7px rgba(255, 243, 221, 1))
          drop-shadow(0 0 16px rgba(255, 184, 77, 0.85));
  transition: opacity 0.4s ease;
}
.route-g.on .route-comet { opacity: 1; }
.route-g.arrived .route-comet { opacity: 0; transition: opacity 0.8s ease; }
/* Santa at the end of the route: a warm pulse where the drive settles */
.route-g .route-santa { opacity: 0; transition: opacity 0.9s var(--ease-out); }
.route-g.arrived .route-santa { opacity: 1; }
.route-g .santa-core {
  fill: var(--warm-white);
  filter: drop-shadow(0 0 6px rgba(255, 214, 140, 1));
}
.route-g .santa-halo {
  fill: none;
  stroke: rgba(255, 184, 77, 0.75);
  stroke-width: 2;
  transform-box: fill-box;
  transform-origin: center;
  animation: santaPulse 2.2s ease-in-out infinite;
}
@keyframes santaPulse {
  0%   { transform: scale(0.55); opacity: 0.9; }
  70%  { transform: scale(1.35); opacity: 0; }
  100% { transform: scale(1.35); opacity: 0; }
}

/* hover preview card (desktop) */
#preview {
  position: fixed;
  z-index: 45;
  pointer-events: none;
  padding: 10px 16px;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: var(--panel-bg);
  backdrop-filter: blur(14px);
  box-shadow: var(--shadow-deep);
  opacity: 0;
  transform: translate(-50%, calc(-100% - 30px)) scale(0.96);
  transition: opacity 0.25s, transform 0.25s var(--ease-out);
  text-align: center;
  max-width: 240px;
}
#preview.show { opacity: 1; transform: translate(-50%, calc(-100% - 34px)) scale(1); }
#preview .p-date {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.24em;
  color: var(--gold);
}
#preview .p-title {
  font-family: var(--serif);
  font-size: 1.05rem;
  color: var(--warm-white);
  margin: 2px 0;
}
#preview .p-time { font-size: 0.68rem; color: var(--ice-dim); letter-spacing: 0.1em; }

/* ---------- filters ---------- */
.filters {
  position: fixed;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 48;
  display: flex;
  gap: 6px;
  max-width: calc(100vw - 32px);
  overflow-x: auto;
  scrollbar-width: none;
  padding: 6px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: rgba(10, 17, 28, 0.72);
  backdrop-filter: blur(14px);
  opacity: 0;
  transition: opacity 0.9s var(--ease-out) 0.9s;
  pointer-events: none;
}
.filters::-webkit-scrollbar { display: none; }
body.exploring .filters { opacity: 1; pointer-events: auto; }
.filters button {
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ice-dim);
  white-space: nowrap;
  transition: color 0.3s, background 0.3s;
}
.filters button:hover { color: var(--ice); }
.filters button[aria-pressed='true'] {
  color: var(--night);
  background: var(--gold);
  font-weight: 600;
}

/* ---------- journey rail ---------- */
#journey {
  position: fixed;
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 47;
  display: flex;
  flex-direction: column;
  gap: 2px;
  opacity: 0;
  transition: opacity 0.9s var(--ease-out) 1.2s;
  pointer-events: none;
}
body.exploring #journey { opacity: 1; pointer-events: auto; }
.journey-label {
  font-size: 0.6rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ice-faint);
  margin-bottom: 8px;
}
.chapter {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 7px 10px;
  border-radius: 8px;
  text-align: left;
  transition: background 0.3s;
}
.chapter:hover { background: rgba(223, 185, 113, 0.08); }
.chapter .num {
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  color: var(--ice-faint);
  font-variant-numeric: tabular-nums;
}
.chapter .name {
  font-family: var(--serif);
  font-size: 1.05rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ice-dim);
  transition: color 0.3s;
}
.chapter:hover .name { color: var(--ice); }
.chapter[aria-pressed='true'] .name { color: var(--gold-bright); }
.chapter[aria-pressed='true'] .num { color: var(--gold); }
.chapter-tagline {
  min-height: 34px;
  max-width: 220px;
  margin-top: 10px;
  font-size: 0.72rem;
  font-style: italic;
  line-height: 1.5;
  color: var(--ice-dim);
  font-family: var(--serif);
  opacity: 0;
  transition: opacity 0.4s;
}
.chapter-tagline.show { opacity: 1; }

/* ---------- detail panel (desktop) ---------- */
#panel {
  position: fixed;
  top: 76px;
  right: 24px;
  bottom: 84px;
  z-index: 52;
  width: min(400px, calc(100vw - 48px));
  display: flex;
  flex-direction: column;
  border: 1px solid var(--hairline);
  border-radius: 16px;
  background: var(--panel-bg);
  backdrop-filter: blur(20px);
  box-shadow: var(--shadow-deep);
  overflow: hidden;
  opacity: 0;
  transform: translateX(28px);
  visibility: hidden;
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out), visibility 0.5s;
}
#panel.open { opacity: 1; transform: none; visibility: visible; }

.panel-media {
  flex: 0 0 auto;
  height: 128px;
  position: relative;
  background:
    radial-gradient(ellipse at 30% 100%, rgba(255, 184, 77, 0.35), transparent 60%),
    radial-gradient(ellipse at 75% 20%, rgba(223, 185, 113, 0.18), transparent 55%),
    linear-gradient(160deg, var(--night-3), var(--night-2));
}
.panel-media::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(255, 243, 221, 0.5) 1px, transparent 1.5px);
  background-size: 90px 70px;
  opacity: 0.35;
}
.panel-close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  background: rgba(7, 11, 19, 0.6);
  color: var(--ice);
  font-size: 1rem;
  line-height: 1;
  display: grid;
  place-items: center;
  transition: background 0.3s;
}
.panel-close:hover { background: rgba(223, 185, 113, 0.25); }

.panel-body { flex: 1; overflow-y: auto; padding: 22px 24px 26px; }
.panel-date {
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.26em;
  color: var(--gold);
}
.panel-title {
  font-family: var(--serif);
  font-size: 1.7rem;
  font-weight: 500;
  line-height: 1.15;
  color: var(--warm-white);
  margin: 6px 0 4px;
}
.panel-when { font-size: 0.76rem; color: var(--ice-dim); letter-spacing: 0.06em; }

.panel-meta { margin: 16px 0; display: grid; gap: 9px; }
.panel-meta .row { display: flex; gap: 10px; font-size: 0.78rem; line-height: 1.45; }
.panel-meta .k {
  flex: 0 0 84px;
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ice-faint);
  padding-top: 2px;
}
.panel-meta .v { color: var(--ice); }

.panel-desc { font-size: 0.82rem; line-height: 1.65; color: var(--ice-dim); margin: 14px 0; }

.badges { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0; }
.badge {
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid var(--hairline);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-bright);
}
.badge.free { border-color: rgba(138, 194, 136, 0.4); color: #a9d8a7; }

.panel-links { display: flex; gap: 8px; margin: 16px 0 4px; flex-wrap: wrap; }
.panel-links a, .panel-links .link-dead {
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
}
.panel-links a {
  color: var(--night);
  background: var(--gold);
  font-weight: 600;
}
.panel-links .link-dead {
  color: var(--ice-faint);
  border: 1px solid rgba(107, 128, 153, 0.3);
  cursor: not-allowed;
}

.related-label {
  font-size: 0.6rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ice-faint);
  margin: 18px 0 8px;
}
.related-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid transparent;
  transition: border-color 0.3s, background 0.3s;
}
.related-item:hover { border-color: var(--hairline); background: rgba(223, 185, 113, 0.06); }
.related-item .r-date { font-size: 0.6rem; letter-spacing: 0.2em; color: var(--gold); font-weight: 700; }
.related-item .r-title { font-family: var(--serif); font-size: 1rem; color: var(--ice); }

.demo-note {
  margin-top: 20px;
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px dashed rgba(107, 128, 153, 0.4);
  font-size: 0.64rem;
  line-height: 1.5;
  color: var(--ice-faint);
}

/* ---------- the frosted window pane (route events) ----------
   Looking at the park through a frosted window on a winter night:
   milky glass, a gold window frame, frost creeping in from the corners,
   and the media header as a live window onto the route itself. */
#panel.frost {
  background: linear-gradient(155deg,
    rgba(176, 199, 226, 0.16) 0%,
    rgba(21, 32, 50, 0.68) 36%,
    rgba(10, 17, 28, 0.86) 100%);
  backdrop-filter: blur(26px) saturate(1.25);
  border-color: rgba(246, 216, 150, 0.35);
  box-shadow: var(--shadow-deep),
    inset 0 0 0 1px rgba(233, 240, 250, 0.07),
    inset 0 14px 60px rgba(233, 240, 250, 0.05);
}
#panel.frost .panel-media {
  height: 168px;
  box-shadow: inset 0 0 0 1px rgba(246, 216, 150, 0.28),
    inset 0 0 34px rgba(7, 11, 19, 0.55);
}
#panel.frost .panel-title { text-shadow: 0 0 24px rgba(223, 185, 113, 0.35); }
.pane-map {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
}
.pane-route {
  fill: none;
  stroke: var(--gold-bright);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.9;
  filter: drop-shadow(0 0 3px rgba(255, 214, 140, 0.9))
          drop-shadow(0 0 8px rgba(255, 184, 77, 0.5));
}
.pane-comet {
  fill: var(--warm-white);
  filter: drop-shadow(0 0 4px rgba(255, 243, 221, 1))
          drop-shadow(0 0 10px rgba(255, 184, 77, 0.9));
}
.pane-frost {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background:
    radial-gradient(150px 115px at 0% 0%, rgba(233, 240, 250, 0.17), transparent 70%),
    radial-gradient(170px 125px at 100% 0%, rgba(233, 240, 250, 0.12), transparent 70%),
    radial-gradient(150px 120px at 0% 100%, rgba(233, 240, 250, 0.09), transparent 70%),
    radial-gradient(180px 135px at 100% 100%, rgba(233, 240, 250, 0.14), transparent 70%);
}
@media (max-width: 767px) {
  #panel.frost .panel-media { height: 112px; }
}

/* ---------- calendar view ---------- */
#calendar-view {
  position: fixed;
  inset: 0;
  z-index: 46;
  overflow-y: auto;
  background: linear-gradient(var(--night), var(--night-2));
  padding: 96px 24px 120px;
}
#calendar-view[hidden] { display: none; }
.cal-inner { max-width: 760px; margin: 0 auto; }
.cal-heading {
  font-family: var(--serif);
  font-size: clamp(1.8rem, 4vw, 2.6rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--warm-white);
  margin-bottom: 6px;
}
.cal-sub { font-size: 0.8rem; color: var(--ice-dim); margin-bottom: 36px; }
.cal-day { margin-bottom: 34px; }
.cal-date {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--hairline);
  margin-bottom: 10px;
}
.cal-date .d-num {
  font-family: var(--serif);
  font-size: 2rem;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.cal-date .d-name {
  font-size: 0.68rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ice-dim);
}
.cal-event {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  text-align: left;
  padding: 14px 12px;
  border-radius: 12px;
  transition: background 0.3s;
}
.cal-event:hover { background: rgba(223, 185, 113, 0.07); }
.cal-event .e-time {
  flex: 0 0 88px;
  font-size: 0.72rem;
  color: var(--gold-bright);
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}
.cal-event .e-main { flex: 1; min-width: 0; }
.cal-event .e-title { font-family: var(--serif); font-size: 1.15rem; color: var(--ice); }
.cal-event .e-venue { font-size: 0.7rem; color: var(--ice-faint); margin-top: 2px; }
.cal-event .e-map {
  flex: 0 0 auto;
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
  opacity: 0;
  transition: opacity 0.3s;
}
.cal-event:hover .e-map, .cal-event:focus-visible .e-map { opacity: 1; }
.cal-empty { font-size: 0.8rem; color: var(--ice-faint); font-style: italic; padding: 8px 12px; }

/* ---------- mobile ---------- */
@media (max-width: 767px) {
  .wordmark { font-size: 0.85rem; letter-spacing: 0.16em; }
  .wordmark .script { display: none; }
  .view-toggle button { padding: 8px 12px; font-size: 0.62rem; }

  /* journey becomes a horizontal strip above the filters */
  #journey {
    left: 0;
    right: 0;
    top: auto;
    bottom: 74px;
    transform: none;
    flex-direction: row;
    gap: 4px;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 0 16px;
  }
  #journey::-webkit-scrollbar { display: none; }
  .journey-label { display: none; }
  .chapter-tagline { display: none; }
  .chapter {
    flex: 0 0 auto;
    border: 1px solid var(--hairline);
    border-radius: 999px;
    background: rgba(10, 17, 28, 0.72);
    backdrop-filter: blur(10px);
    padding: 7px 14px;
  }
  .chapter .name { font-size: 0.85rem; }

  .filters { bottom: 14px; border-radius: 14px; }

  /* detail panel becomes a bottom sheet */
  #panel {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-height: 72vh;
    border-radius: 20px 20px 0 0;
    border-left: none;
    border-right: none;
    border-bottom: none;
    transform: translateY(100%);
  }
  #panel.open { transform: none; }
  #panel::before {
    content: '';
    position: absolute;
    top: 8px;
    left: 50%;
    transform: translateX(-50%);
    width: 44px;
    height: 4px;
    border-radius: 2px;
    background: rgba(233, 240, 250, 0.25);
    z-index: 3;
  }
  .panel-media { height: 84px; }
  #preview { display: none; }

  #calendar-view { padding: 84px 16px 100px; }
  .cal-event .e-time { flex-basis: 64px; font-size: 0.66rem; }
  .cal-event { gap: 10px; }
}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001s !important;
    animation-delay: 0s !important;
    transition-duration: 0.001s !important;
  }
  #snow { display: none; }
}



/* #reveal sets display:grid, which overrides the hidden ATTRIBUTE — the UA
   rule for [hidden] is weaker than an id rule — so the reveal was on screen
   from page load, merely hidden behind #intro, and appeared the moment the
   hero faded rather than on its own beat. */
#reveal[hidden] { display: none; }

/* The opening title. Sits high in the frame, clear of the bridge, so the
   train crosses beneath it. Type matches the reveal so the two read as one
   voice. Opacity is driven from JS, tied to the crossing. */
#hero-title {
  position: absolute;
  top: 13%;
  left: 0;
  right: 0;
  z-index: 30;
  text-align: center;
  padding: 0 24px;
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
}
.hero-title-main {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.7rem, 4.4vw, 3.1rem);
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--warm-white);
  text-shadow: 0 0 34px rgba(223, 185, 113, 0.3), 0 2px 20px rgba(0, 0, 0, 0.75);
}
.hero-title-sub {
  margin-top: 10px;
  font-family: var(--script);
  font-size: clamp(1.5rem, 3.2vw, 2.3rem);
  color: var(--gold);
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.7);
}
@media (max-width: 640px) { #hero-title { top: 9%; } }

/* The December strip under the journey. Five across so the month reads as a
   block the eye can scan, and narrow enough to stay inside the left rail. */
.day-label { margin-top: 18px; }
.day-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 2px;
  max-width: 176px;
}
.day {
  font-family: var(--serif);
  font-size: 0.86rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  color: var(--ice-dim);
  padding: 5px 0;
  border-radius: 6px;
  text-align: center;
  transition: background 0.25s, color 0.25s;
}
.day:hover:not(:disabled) { background: rgba(223, 185, 113, 0.1); color: var(--ice); }
.day[aria-pressed="true"] {
  color: var(--night);
  background: var(--gold-bright);
}
/* nothing on that day: still shown, so the shape of the month reads, but inert */
.day.empty { color: rgba(226, 236, 248, 0.16); cursor: default; }
@media (max-width: 900px) { .day-label, .day-grid { display: none; } }

/* The way back to the whole map. Top centre: the wordmark holds the left and
   the view switcher the right, and the filters own the bottom, so this is the
   one piece of clear air — and it is where the eye goes when something has
   changed. Hidden whenever the view already IS the full map, so it never
   becomes furniture. */
#reset-view {
  position: fixed;
  top: 18px;
  left: 50%;
  transform: translateX(-50%) translateY(-6px);
  z-index: 52;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 20px;
  border-radius: 999px;
  border: 1px solid rgba(223, 185, 113, 0.42);
  background: rgba(9, 14, 24, 0.82);
  backdrop-filter: blur(7px);
  font-family: var(--sans);
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-bright);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.35s var(--ease-out), transform 0.35s var(--ease-out), background 0.25s;
}
#reset-view.show { opacity: 1; transform: translateX(-50%) translateY(0); }
#reset-view:hover { background: rgba(223, 185, 113, 0.16); }
#reset-view[hidden] { display: none; }
.reset-arrow { font-size: 0.9rem; line-height: 1; }
@media (max-width: 640px) {
  #reset-view { top: auto; bottom: 74px; font-size: 0.62rem; padding: 8px 16px; }
}

/* Invisible tap catcher for the gap between the hero fading and the reveal.
   Below #reveal (58) so the Begin button always wins, above the map so a tap
   in that window reaches this instead of panning the town. */
#skip-catch { position: fixed; inset: 0; z-index: 57; cursor: pointer; }
#skip-catch[hidden] { display: none; }
