/* ==================================================================
   THE NORTHLANDER WAYFINDER: STYLES
   Warm & rustic Northern Ontario theme. Mobile-first.
   ================================================================== */

:root{
  --ink:#241f1a;
  --paper:#f3ece0;
  --paper-2:#ece2d2;
  /* Warm ivory used for the stat strip and map section so both
     areas read as one unified warm block, with no grey undertone. */
  --ivory:#f6ecd2;
  --card:#fffaf1;
  --rail:#0e3b2c;        /* deep evergreen */
  --rail-deep:#0a2d21;   /* richer evergreen for header + footer */
  --rail-2:#16543e;
  --ember:#d96c2c;       /* warm amber (signal lamp) */
  --ember-d:#bb551c;
  --gold:#dca33c;
  --line:#d6c9b2;
  --muted:#5a4f3d;       /* stronger contrast against cream for legibility */
  --shadow:0 10px 30px rgba(20,50,38,.13);

  /* ----- WPA poster palette (Stage 1 vintage redesign) -----
     Slightly desaturated, like aged poster ink. */
  --poster-cream:#f3e6c8;
  --poster-paper:#efe1c1;
  --poster-sun:#f6e7c4;
  --poster-gold:#dca33c;
  --poster-mustard:#c89525;
  --poster-orange:#c46f2c;
  --poster-orange-d:#a85a22;
  --poster-crimson:#8e3d22;
  --poster-teal-l:#7ea29e;
  --poster-teal:#456f6c;
  --poster-teal-d:#2c5258;
  --poster-forest:#1f3d2d;
  --poster-rail-brown:#6b4528;
  --poster-ink:#241f1a;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  font-family:'Spline Sans',-apple-system,BlinkMacSystemFont,sans-serif;
  /* Bumped from default 16px to ~17px for mobile reading comfort
     without disturbing the rem-based layout. */
  font-size:1.0625rem;
  background:var(--paper);color:var(--ink);line-height:1.68;
  -webkit-font-smoothing:antialiased;
  /* subtle paper grain */
  background-image:radial-gradient(rgba(120,100,70,.05) 1px,transparent 1px);
  background-size:4px 4px;
  position:relative;
}

/* ---------- paper texture overlay ----------
   Inline SVG fractal-noise rendered as a tiled background image,
   pinned via a body::before pseudo-element so it floats above
   everything else without intercepting clicks. mix-blend-mode
   multiply lets it darken slightly into the page palette and feel
   like real ink-on-paper grain. Opacity is intentionally tiny
   (~5%) so it reads as texture, not noise. */
body::before{
  content:"";
  position:fixed;inset:0;
  pointer-events:none;
  z-index:9999;
  opacity:.05;
  mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.14 0 0 0 0 0.12 0 0 0 0 0.10 0 0 0 1 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size:240px 240px;
}
h1,h2,h3,h4{font-family:'Fraunces',Georgia,serif;line-height:1.12;font-weight:900}
img{max-width:100%;display:block}
a{color:inherit}

/* ---------- shared ---------- */
.section-head{padding:0 1.25rem;margin-bottom:1.4rem}
.section-head.center{text-align:center}
.section-head .kicker,.kicker{
  font-size:.72rem;letter-spacing:.26em;text-transform:uppercase;
  font-weight:700;color:var(--poster-crimson);
}
.section-head h2{font-size:clamp(1.9rem,7vw,2.7rem);margin-top:.35rem}
.section-head p{color:var(--muted);margin-top:.4rem;font-size:.97rem}

.btn{
  display:inline-flex;align-items:center;justify-content:center;
  padding:.85rem 1.5rem;border-radius:4px;font-weight:600;
  font-size:.95rem;text-decoration:none;border:2px solid transparent;
  transition:transform .15s,background .2s,box-shadow .2s;cursor:pointer;
}
.btn:active{transform:scale(.97)}
.btn-primary{
  /* A darker rust than poster-crimson so the button reads at the same
     depth as the stat numerals on the cream stat strip below the hero. */
  background:#6e2e17;color:var(--poster-cream);
  border-color:#6e2e17;
  box-shadow:0 4px 12px rgba(0,0,0,.35);
}
/* Hover swaps to deep forest green for clear contrast against the
   crimson rest state. Previous hover used poster-orange-d which
   was a near-identical brown and read as muddy. */
.btn-primary:hover{
  background:var(--rail);border-color:var(--rail);
  color:var(--poster-cream);
}
/* Ghost button now sits over a photographic background, so it
   gets a translucent dark fill plus cream text and border. That
   keeps it readable on the lake/foliage area without competing
   with the solid crimson primary button. */
.btn-ghost{
  background:rgba(18,28,38,.35);color:var(--poster-cream);
  border-color:var(--poster-cream);
  backdrop-filter:blur(2px);
  -webkit-backdrop-filter:blur(2px);
  box-shadow:0 4px 12px rgba(0,0,0,.35);
}
.btn-ghost:hover{
  background:var(--poster-cream);color:var(--rail);
  border-color:var(--poster-cream);
}

/* ---------- top bar ----------
   Solid deep forest green at all times. No gradients, no
   transparency, no scroll based color change. The logo and links
   are cream and read clearly on the green bar at every scroll
   position and screen size. */
.topbar{
  position:sticky;top:0;z-index:1000;
  background:var(--rail-deep);
  color:#f3ece0;
  display:flex;align-items:center;justify-content:space-between;
  padding:.65rem 1.1rem;padding-top:max(.65rem,env(safe-area-inset-top));
  box-shadow:0 2px 12px rgba(0,0,0,.18);
}
.brand{
  font-family:'Fraunces',serif;font-weight:900;font-size:1.18rem;
  text-decoration:none;color:#f3ece0;letter-spacing:-.01em;
  /* gap:0 so the flex gap does NOT push "Northlander" and "Guide"
     apart (they are separate flex items: a text node + a span).
     The icon gets its spacing from .brand-mark margin instead. */
  display:flex;align-items:center;gap:0;
}
/* "Guide" picks up the same mustard gold accent as the hero
   headline accent so the logo and headline match. It sits flush
   against "Northlander" with no separating space. */
.brand span{color:var(--poster-gold);font-style:normal}
.brand-mark{display:flex;flex-shrink:0;line-height:0;margin-right:.5rem}
.brand-mark svg{display:block}
.topnav{display:flex;align-items:baseline;column-gap:1.1rem}
.topnav a{
  color:#f3ece0;text-decoration:none;font-size:.82rem;font-weight:600;
  margin-left:1.1rem;letter-spacing:.02em;
  transition:color .15s ease;
}
.topnav a:hover{color:var(--gold)}

/* Hamburger button: hidden by default, shown only at the mobile
   breakpoint. Three stacked bars morph into an X when .open. */
.hamburger{
  display:none;
  background:transparent;border:0;cursor:pointer;
  width:40px;height:40px;padding:8px;
  flex-direction:column;justify-content:space-between;align-items:stretch;
  border-radius:4px;
}
.hamburger span{
  display:block;height:2.5px;width:100%;
  background:#f3ece0;border-radius:2px;
  transition:transform .25s ease, opacity .2s ease;
  transform-origin:center;
}
.hamburger.open span:nth-child(1){transform:translateY(9px) rotate(45deg)}
.hamburger.open span:nth-child(2){opacity:0}
.hamburger.open span:nth-child(3){transform:translateY(-9px) rotate(-45deg)}

/* Mobile menu drawer. display:none on desktop so it stays out of
   the tab order. At <768px it switches to display:flex and slides
   down from above when .open is added. The 767px breakpoint is the
   inclusive upper bound for "mobile" (matches the spec of "under
   768px"). */
.mobilemenu{display:none}
@media (max-width:767px){
  .topnav{display:none}
  .hamburger{display:flex}
  .mobilemenu{
    display:flex;flex-direction:column;
    position:fixed;top:0;left:0;right:0;z-index:998;
    background:var(--rail-deep);
    padding:calc(env(safe-area-inset-top,0) + 56px) 1.4rem 1.4rem;
    transform:translateY(-100%);
    transition:transform .3s ease;
    box-shadow:0 8px 24px rgba(0,0,0,.28);
  }
  .mobilemenu.open{transform:translateY(0)}
  .mobilemenu a{
    color:#f3ece0;text-decoration:none;
    font-family:'Fraunces',serif;font-weight:700;
    font-size:1.4rem;
    padding:1rem .25rem;
    border-bottom:1px solid rgba(243,236,224,.14);
  }
  .mobilemenu a:last-child{border-bottom:none}
  .mobilemenu a:hover,.mobilemenu a:focus{color:var(--gold)}
}

/* ---------- route progress bar ---------- */
.routebar{
  position:sticky;top:51px;z-index:999;height:3px;
  background:rgba(36,31,26,.12);
}
.routebar-fill{
  height:100%;width:0;
  background:var(--poster-crimson);
  transition:width .15s ease-out;
}

/* respect users who prefer less motion */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
}

/* ---------- Phosphor icons ----------
   Every UI icon is a Phosphor Icon (loaded from the CDN in index.html).
   Icons inherit the colour and size of their surrounding text, and
   vertical-align tucks them onto the text baseline. Size and colour
   utility classes are available for one-off overrides. */
.ph, .ph-light, .ph-fill {
  font-size: inherit;
  color: inherit;
  vertical-align: -0.125em;
  line-height: 1;
}
.icon-sm { font-size: 16px; }
.icon-md { font-size: 20px; }
.icon-lg { font-size: 24px; }
.icon-xl { font-size: 32px; }
.icon-brown { color: #7d3a1e; }
.icon-green { color: #0a2d21; }
.icon-ivory { color: #f5f0e8; }
.icon-gold { color: #c4860f; }
.catfilter button .ic{display:inline-flex;align-items:center;line-height:1}
.catfilter button .ic .ph-light{font-size:1.15em;vertical-align:0}
.rating .ph-light{font-size:.95em;margin-right:.18em}
.detail-loc .ph-light,.evcard .where .ph-light{margin-right:.05em}
/* Buttons that combine an icon + text get a small gap and flex
   centering so the icon never collides with the label. */
.share-row button{display:inline-flex;align-items:center;gap:.45rem}
.backbtn{display:inline-flex;align-items:center;gap:.45rem}
.card-cta{display:inline-flex;align-items:center;gap:.25rem}

/* ---------- reveal-on-scroll ----------
   .reveal wrappers (and the few elements that get .reveal directly,
   like .section-head) start invisible and gently lifted. JS adds
   .is-visible via IntersectionObserver as the element enters the
   viewport. The wrapper pattern keeps the rise transform off the
   inner card itself so the card's hover lift stays snappy at its
   own duration.
   prefers-reduced-motion is already handled by the global block
   above (transitions collapse to ~0ms, so reveals snap in). */
.reveal{
  opacity:0;
  transform:translateY(18px);
  transition:opacity .55s cubic-bezier(.23,1,.32,1),
             transform .55s cubic-bezier(.23,1,.32,1);
  will-change:opacity, transform;
}
.reveal.is-visible{
  opacity:1;
  transform:none;
}
/* Cascade siblings: when a row of listing cards or event cards all
   enter the viewport at once, stagger their reveals so the group
   reads as a cascade instead of a single thunk. */
.cards > .reveal:nth-child(2){transition-delay:.06s}
.cards > .reveal:nth-child(3){transition-delay:.12s}
.cards > .reveal:nth-child(4){transition-delay:.18s}
.cards > .reveal:nth-child(5){transition-delay:.24s}
.cards > .reveal:nth-child(6){transition-delay:.30s}
.cards > .reveal:nth-child(n+7){transition-delay:.36s}
.evlist > .reveal:nth-child(2){transition-delay:.06s}
.evlist > .reveal:nth-child(3){transition-delay:.12s}
.evlist > .reveal:nth-child(4){transition-delay:.18s}
.evlist > .reveal:nth-child(n+5){transition-delay:.24s}

/* ---------- hero (Stage 5: real illustrated background) ----------
   The hand-built SVG landscape from earlier stages was replaced
   with an illustrated photograph of the actual route scenery (a
   heron at a calm Northern Ontario lake in autumn). The image is
   absolutely positioned to cover the hero area; a soft top-down
   dark gradient sits between the image and the text so the light
   headline stays legible without washing out the heron and lake
   below. */
.hero{
  position:relative;overflow:hidden;color:var(--poster-cream);
  isolation:isolate;
  /* Content sits in the upper band over the sky/treeline so the
     painted train reads as a clear scene below the headline. Top
     padding kept tight so the train shows through cleanly. */
  display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  padding:clamp(0.5rem,2vh,1.4rem) 1.2rem 2.4rem;
  min-height:clamp(460px,60vh,640px);
}
.hero-img{
  position:absolute;inset:0;z-index:-2;
  width:100%;height:100%;
  object-fit:cover;object-position:center;
  display:block;
}
/* Soft dark gradient over the text region only. Slightly stronger
   than the previous pass so the subtitle paragraph stays crisp,
   but still fades to fully transparent in the lower portion so
   the heron, lake, and trees read clearly. */
.hero::before{
  content:"";
  position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,
    rgba(18,28,38,.78) 0%,
    rgba(18,28,38,.60) 32%,
    rgba(18,28,38,.28) 60%,
    rgba(18,28,38,0)   88%);
  pointer-events:none;
}

.hero-inner{
  position:relative;width:100%;max-width:1080px;margin:0 auto;
  text-align:center;
  animation:heroRise .7s cubic-bezier(.2,.7,.2,1) both;
}
@keyframes heroRise{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}

.hero .kicker{
  color:var(--poster-cream);display:block;
  margin-bottom:1.4rem;
  letter-spacing:.32em;font-size:.78rem;font-weight:700;
  text-shadow:0 1px 4px rgba(0,0,0,.55);
}
.hero h1{
  /* "Every stop has a story" is a five-word headline, so the
     clamp max is tuned to keep it on one line on desktop within
     the 960px hero-inner while still feeling large. On mobile the
     smaller end of the clamp lets it wrap naturally to two lines
     rather than forcing a <br>. text-wrap:balance keeps the wrap
     points even. */
  font-size:clamp(3.25rem,8vw,6rem);
  letter-spacing:-.02em;line-height:1.02;
  text-wrap:balance;
  /* Generous space below the headline so the painted train shows
     through cleanly between the title and the tagline on desktop.
     Scales down on shorter viewports so mobile stays compact. */
  margin:0 0 clamp(2.2rem,9vh,6rem);
  color:var(--poster-cream);
  text-shadow:0 2px 10px rgba(0,0,0,.55), 0 1px 2px rgba(0,0,0,.5);
}
@media(min-width:768px){
  /* Desktop: keep it on a single line. */
  .hero h1{white-space:nowrap}
  /* Desktop: drop the tagline and CTA group lower on the banner so
     the composition feels balanced against the painted train. Pushes
     the gap between the headline and the subtitle wider without
     touching mobile, where space is tight. */
  .hero h1{margin-bottom:clamp(4.5rem,16vh,10rem)}
}
.hero h1 em{
  font-style:italic;color:var(--poster-gold);
  text-shadow:0 2px 10px rgba(0,0,0,.55), 0 1px 2px rgba(0,0,0,.5);
}
.hero-sub{
  position:relative;
  isolation:isolate;
  color:var(--poster-cream);
  /* Tagline: ~18px, lighter weight (400) than before. */
  font-size:1.125rem;line-height:1.55;font-weight:400;
  max-width:54ch;margin:0 auto 1.2rem;
  /* Multi-layered soft text shadow gives every letter a quiet
     halo that fades to nothing. No box, no edges. */
  text-shadow:
    0 0 14px rgba(0,0,0,.7),
    0 0 6px rgba(0,0,0,.8),
    0 1px 3px rgba(0,0,0,.7);
}
/* Very soft blurred dark glow sitting just behind the paragraph
   text. Radial fade plus a blur filter means there are no visible
   rectangle edges, just a quiet ambient darkening that helps the
   text read over the busy water reflections. */
.hero-sub::before{
  content:"";
  position:absolute;
  inset:-18px -28px;
  background:radial-gradient(ellipse at center,
    rgba(8,14,20,.42) 0%,
    rgba(8,14,20,.18) 55%,
    rgba(8,14,20,0)   100%);
  filter:blur(12px);
  z-index:-1;
  pointer-events:none;
}
.hero-cta{
  display:flex;gap:.8rem;justify-content:center;flex-wrap:wrap;
  margin-top:1rem;
}

/* Hero stats: dramatic editorial scale shift. The numbers are the
   loudest thing on the page (huge Fraunces, tightly tracked); the
   labels below collapse to whisper-tiny small-caps. The contrast
   between the giant number and the tiny label *is* the design. */
.hero-stats{
  position:relative;display:flex;justify-content:center;gap:0;
  background:var(--ivory);
  color:var(--poster-ink);
  border-top:4px solid var(--poster-crimson);
  padding:2rem 0 1.6rem;
}
.hero-stats div{
  flex:1;text-align:center;
  padding:0 .4rem;
  border-right:1px solid rgba(140,61,34,.22);
  background:transparent;
  position:relative;
}
.hero-stats div:last-child{border-right:none}
.hero-stats b{
  display:block;
  position:relative;
  font-family:'Fraunces',serif;
  font-weight:900;
  font-size:clamp(4rem,14vw,9rem);
  color:var(--poster-crimson);
  line-height:.85;
  letter-spacing:-.04em;
  /* A barely-there warm shadow gives the numerals a touch of
     ink-on-paper depth. */
  text-shadow:0 1px 0 rgba(36,31,26,.04);
}
.hero-stats span{
  /* inline-block + a negative margin-right equal to the
     letter-spacing cancels the trailing gap that letter-spacing
     adds after the last character. The parent column centres the
     inline-block by its (now corrected) box, so the visible label
     sits truly centred under the number. Cleaner and more reliable
     than text-indent, which over-compensated. */
  display:inline-block;
  margin-top:.9rem;
  margin-right:-.34em;
  font-size:.6rem;
  letter-spacing:.34em;
  text-transform:uppercase;
  color:var(--poster-rail-brown);
  font-weight:700;
}
/* The "~" on "~11": taken OUT of flow and positioned just to the
   upper-left of the centred "11". Because it no longer occupies
   layout space, the "11" centres in its column on its own, so the
   HOURS label (also centred) sits exactly under the "11" rather
   than under the wider "~11" group. The .44em offset is half the
   width of "11" in this face, nudging the mark to the digit's
   left edge. */
.hero-stats .approx{
  position:absolute;
  top:.06em;
  right:calc(50% + .44em);
  font-size:.5em;
  line-height:1;
  font-weight:900;
  opacity:.5;
  letter-spacing:0;
}
@media(min-width:720px){
  .hero-stats{padding:3rem 0 2.4rem}
  .hero-stats span{font-size:.65rem;letter-spacing:.38em;margin-right:-.38em;margin-top:1.1rem}
}


/* ---------- stopnav (rail + slab) ----------
   Replaces the old map section and the old directory chips. A
   vertical rail of 16 station circles on the left; a content slab
   on the right that shows the selected stop. Same metaphor on
   every screen size; mobile uses an off-canvas slide so the slab
   takes over the screen when a stop is open.
   ------------------------------------------------------------------ */
.stopnav{
  background:var(--ivory);
  padding:2rem 0;
  position:relative;
  /* So scrollIntoView() (on card tap / back) lands below the
     sticky topbar instead of tucking the top under it. */
  scroll-margin-top:56px;
}
@media (min-width:768px){
  .stopnav{
    display:grid;
    grid-template-columns:280px 1fr;
    gap:2.5rem;
    max-width:1280px;
    margin:0 auto;
    padding:3rem 1.5rem 4rem;
    align-items:start;
  }
}

/* RAIL: vertical list of station circles + names + regions */
.rail{
  position:relative;
  padding:0 1.25rem;
}
@media (min-width:768px){
  .rail{
    padding:0;
    position:sticky;
    top:80px;
    align-self:start;
    max-height:calc(100vh - 100px);
    overflow-y:auto;
  }
}
.rail-head{
  margin:0 0 1rem 3rem;
}
.rail-head .kicker{display:block;margin-bottom:.2rem}
.rail-head h2{
  font-family:'Fraunces',serif;
  font-size:1.4rem;font-weight:900;line-height:1;
  color:var(--ink);
}
.rail-stops{
  list-style:none;
  margin:0;padding:0;
  position:relative;
}
/* The actual rail line: a thin vertical brown rule that runs down
   the middle of all the station circles. Sits behind the circles
   via z-index so they read as ink dots on a printed rail. */
.rail-stops::before{
  content:"";
  position:absolute;
  left:21px;
  top:18px;
  bottom:18px;
  width:2.5px;
  background:var(--poster-rail-brown);
  opacity:.28;
  z-index:0;
}
.rail-stops li{margin:0}
.rail-stop{
  display:flex;align-items:center;
  gap:.85rem;
  padding:.55rem .5rem;
  background:transparent;border:none;
  width:100%;text-align:left;cursor:pointer;
  font-family:'Spline Sans',sans-serif;
  color:var(--ink);
  position:relative;
  z-index:1;
  border-radius:4px;
  transition:background .15s ease;
}
/* Desktop: more breathing room between stops in the route rail. */
@media (min-width:768px){
  .rail-stops li{margin-bottom:.45rem}
  .rail-stops li:last-child{margin-bottom:0}
  .rail-stop{padding:.7rem .55rem}
}
/* Mobile first-time hint: pulse the first stop and label it so a new
   visitor knows to tap. Both effects stop once .rail-stops gains the
   .tapped class, which JS adds on first tap and persists via
   localStorage. */
@media (max-width:767px){
  .rail-stops li:first-child .rail-circle{
    animation:railPulse 1.8s ease-in-out infinite;
  }
  .rail-stops li:first-child .rail-stop::after{
    content:"Tap to start";
    position:absolute;right:14px;top:50%;
    transform:translateY(-50%);
    font-family:'Spline Sans',sans-serif;
    font-size:11px;letter-spacing:.16em;text-transform:uppercase;
    color:var(--poster-crimson);font-weight:700;
    animation:railHintFade 1.8s ease-in-out infinite;
    pointer-events:none;
  }
  .rail-stops.tapped li:first-child .rail-circle{animation:none}
  .rail-stops.tapped li:first-child .rail-stop::after{display:none}
}
@keyframes railPulse{
  0%,100%{box-shadow:0 0 0 0 rgba(142,61,34,.45);transform:scale(1)}
  50%{box-shadow:0 0 0 12px rgba(142,61,34,0);transform:scale(1.06)}
}
@keyframes railHintFade{
  0%,100%{opacity:.55}
  50%{opacity:1}
}
.rail-circle{
  flex:0 0 38px;height:38px;
  border-radius:50%;
  background:var(--card);
  border:2.5px solid var(--poster-rail-brown);
  display:flex;align-items:center;justify-content:center;
  font-family:'Fraunces',serif;font-weight:900;
  font-size:.86rem;
  color:var(--poster-rail-brown);
  transition:background .18s ease, border-color .18s ease,
             color .18s ease, transform .18s ease,
             box-shadow .18s ease;
}
.rail-text{
  display:flex;flex-direction:column;
  gap:.1rem;
  min-width:0;flex:1;
}
.rail-name{
  font-weight:700;
  font-size:.95rem;line-height:1.15;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.rail-region{
  font-size:.7rem;
  color:var(--muted);
  letter-spacing:.06em;text-transform:uppercase;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
@media (hover:hover) and (pointer:fine){
  .rail-stop:hover{background:rgba(140,61,34,.06)}
  .rail-stop:hover .rail-circle{
    border-color:var(--poster-crimson);
    color:var(--poster-crimson);
    transform:scale(1.06);
  }
}
.rail-stop:active{transform:scale(.985)}
.rail-stop[aria-selected="true"] .rail-circle{
  background:var(--poster-crimson);
  border-color:var(--poster-crimson);
  color:var(--poster-cream);
  box-shadow:0 4px 10px rgba(142,61,34,.25);
}
.rail-stop[aria-selected="true"] .rail-name{
  color:var(--poster-crimson);
}
.rail-stop:focus-visible{
  outline:2px solid var(--poster-crimson);
  outline-offset:2px;
}

/* SLAB: the detail panel that holds the selected stop's content */
.slab{
  background:var(--card);
  border:1px solid rgba(140,61,34,.18);
  border-radius:4px;
  min-height:60vh;
  overflow:hidden;
  position:relative;
  box-shadow:0 10px 28px rgba(20,50,38,.08);
}
.slab-back{display:none}

/* MOBILE: the rail is the full-screen first view. Tapping a circle
   hides the rail and shows the slab (with a short slide-in
   entrance). Rail and slab toggle via display rather than absolute
   positioning, so the page scrolls naturally, tall slab content is
   never clipped, and the sticky back bars work against the page
   scroll. */
@media (max-width:767px){
  .stopnav{
    display:block;
    padding:1.4rem 0 2rem;
  }
  /* Default view: rail shown, slab hidden. */
  .slab{
    display:none;
    overflow:visible;
    min-height:0;
    margin:0;
    border:none;border-radius:0;
    box-shadow:none;
  }
  .stopnav.detail-open .rail{display:none}
  .stopnav.detail-open .slab{
    display:block;
    animation:slabIn .32s cubic-bezier(.2,.7,.2,1) both;
  }
  /* "Back to route" bar: full-width solid sticky header. Hidden
     while a single listing detail is open, where the detail's own
     "Back to <stop>" bar takes over. */
  .slab-back{
    display:flex;align-items:center;gap:.4rem;
    position:sticky;top:52px;z-index:55;
    background:var(--card);
    margin:0;
    padding:.8rem 1rem;
    border:none;
    border-bottom:1px solid rgba(140,61,34,.15);
    color:var(--poster-crimson);
    font-family:'Spline Sans',sans-serif;
    font-size:.88rem;font-weight:700;
    width:100%;text-align:left;cursor:pointer;
  }
  .slab.detail-listing .slab-back{display:none}
  .slab-back-arrow{
    font-size:1.6rem;line-height:1;
    margin-top:-3px;
  }
  .slab-back:active{background:rgba(142,61,34,.05)}
}
@keyframes slabIn{
  from{opacity:0;transform:translateX(24px)}
  to{opacity:1;transform:none}
}

/* ---------- map preview card (tap/click) ----------
   Bottom-sheet on mobile (slides up from the bottom of the
   viewport, full width). On wider screens it floats with rounded
   corners and a small bottom offset, capped at 440px wide. */
.map-preview{
  position:fixed;bottom:0;left:50%;
  transform:translateX(-50%) translateY(110%);
  visibility:hidden;
  width:100%;max-width:480px;
  background:var(--card);
  border-top-left-radius:4px;border-top-right-radius:4px;
  box-shadow:0 -14px 36px rgba(20,50,38,.24);
  z-index:2000;
  /* Closing transition: snappy ease-in so dismissal feels fast.
     The .open rule below overrides this with a slower ease-out
     curve for entry so the user sees the card decide to appear. */
  transition:transform .18s cubic-bezier(.4,0,1,1), visibility .18s;
  padding-bottom:env(safe-area-inset-bottom,0);
  font-family:'Spline Sans',sans-serif;
}
.map-preview.open{
  transform:translateX(-50%) translateY(0);
  visibility:visible;
  transition:transform .32s cubic-bezier(.2,.7,.2,1), visibility .32s;
}
.map-preview-img{
  position:relative;width:100%;
  aspect-ratio:16/9;background:var(--paper-2);
  border-top-left-radius:4px;border-top-right-radius:4px;
  overflow:hidden;
}
.map-preview-img img,.map-preview-img svg{
  width:100%;height:100%;object-fit:cover;display:block;
}
.map-preview-body{
  position:relative;
  padding:1.5rem 1.2rem 1.3rem;
}
.map-preview-num{
  position:absolute;top:-22px;left:1.1rem;
  width:44px;height:44px;border-radius:50%;
  background:var(--poster-crimson);color:#fff;
  display:flex;align-items:center;justify-content:center;
  font-family:'Fraunces',serif;font-weight:900;font-size:1.1rem;
  border:3px solid var(--card);
  box-shadow:0 4px 10px rgba(0,0,0,.28);
}
.map-preview-body h3{
  font-family:'Fraunces',serif;font-weight:900;
  font-size:1.4rem;color:var(--rail);
  margin:0 0 .4rem;line-height:1.15;
}
.map-preview-body p{
  font-size:.95rem;line-height:1.5;color:var(--muted);
  margin:0 0 1.1rem;
}
.map-preview-open{
  width:100%;font-size:.95rem;
}
.map-preview-close{
  position:absolute;top:.55rem;right:.55rem;z-index:3;
  background:rgba(255,250,241,.92);color:var(--rail);
  border:none;border-radius:50%;
  width:34px;height:34px;
  font-size:1.45rem;font-weight:700;line-height:1;
  cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 2px 8px rgba(0,0,0,.25);
  font-family:'Spline Sans',sans-serif;
  transition:background .15s, color .15s;
}
.map-preview-close:hover{background:#fff;color:var(--poster-crimson)}

@media (min-width:720px){
  .map-preview{
    bottom:1.5rem;
    border-radius:4px;
    max-width:420px;
  }
}

/* map fallback (shown only if Leaflet can't load) */
.map-fallback{
  background:var(--card);padding:1rem;
}
.fallback-note{
  text-align:center;color:var(--muted);font-size:.84rem;
  font-style:italic;margin-bottom:.8rem;
}
.fallback-route{list-style:none;display:grid;gap:.5rem}
.fallback-route li{
  display:flex;gap:.8rem;align-items:center;cursor:pointer;
  background:var(--paper);border:1.5px solid var(--line);
  border-radius:4px;padding:.65rem .8rem;transition:border-color .15s;
}
.fallback-route li:hover{border-color:var(--poster-crimson)}
.fb-num{
  flex:0 0 28px;height:28px;border-radius:50%;
  background:var(--rail);color:#fff;border:2px solid var(--poster-crimson);
  display:flex;align-items:center;justify-content:center;
  font-weight:700;font-size:.8rem;
}
.fb-body{display:flex;flex-direction:column;line-height:1.3}
.fb-body b{font-family:'Fraunces',serif;font-size:1rem;color:var(--rail)}
.fb-body em{font-size:.8rem;color:var(--muted);font-style:italic}

/* ---------- explore ---------- */
.explore{padding:1.4rem 0 1.5rem;max-width:1080px;margin:0 auto}
.searchbar{padding:0 1.25rem;margin-bottom:1.1rem}
.searchbar input{
  width:100%;font-family:'Spline Sans',sans-serif;font-size:1rem;
  padding:.95rem 1.1rem;border:2px solid var(--line);border-radius:4px;
  background:var(--card);color:var(--ink);
  transition:border-color 160ms ease, box-shadow 160ms ease;
}
.searchbar input:focus{
  outline:none;border-color:var(--poster-crimson);
  box-shadow:0 0 0 3px rgba(142,61,34,.18);
}

/* stop chips: horizontal scroll on mobile.
   Tight bottom padding keeps the scrollbar nestled close to the
   chip row (so it reads as "the chip slider"). A generous
   margin-bottom then opens clear breathing room between the
   slider and the stop card directly below. */
.stopchips{
  display:flex;gap:.5rem;overflow-x:auto;
  padding:.3rem 1.25rem .5rem;margin-bottom:2rem;
  -webkit-overflow-scrolling:touch;scrollbar-width:thin;
  /* Firefox uses scrollbar-color (thumb track). Matches the
     poster-crimson rusty brown used for the route progress bar. */
  scrollbar-color:var(--poster-crimson) transparent;
}
.stopchips::-webkit-scrollbar{height:7px}
.stopchips::-webkit-scrollbar-thumb{background:var(--poster-crimson);border-radius:4px}
.chip{
  flex:0 0 auto;font-family:'Spline Sans',sans-serif;font-size:.85rem;
  font-weight:600;padding:.55rem 1rem;border-radius:4px;
  border:2px solid var(--line);background:var(--card);color:var(--ink);
  cursor:pointer;white-space:nowrap;
  transition:transform 160ms ease-out,
             background-color .15s ease, color .15s ease,
             border-color .15s ease;
}
@media (hover:hover) and (pointer:fine){
  .chip:hover{border-color:var(--rail)}
}
.chip:active{transform:scale(.97)}
.chip.active{background:var(--rail);color:#fff;border-color:var(--rail)}
.chip .ord{opacity:.5;margin-right:.35rem;font-variant-numeric:tabular-nums}

/* ---------- stop panel ---------- */
.stop{padding:0 1.25rem 1.5rem;animation:fade .22s cubic-bezier(.23,1,.32,1) both}
/* The hero is the first child of .stop and needs to fill the slab
   edge-to-edge, so it escapes .stop's horizontal padding via a
   matching negative margin. Everything else inside .stop stays
   padded normally. */
.stop > .reveal:first-child{
  margin:0 -1.25rem 1.5rem;
}
@keyframes fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* ---------- full-bleed stop poster ----------
   The illustrated stop poster is the strongest visual asset on the
   site, so it earns the headline treatment: it breaks out of the
   .explore max-width AND the .stop horizontal padding to span the
   full viewport, and it sits at 55-75vh tall so it actually
   dominates the fold. The label band at the bottom keeps the same
   content but the type gets dramatic. */
.stop-hero{
  position:relative;
  /* Fills the slab end-to-end. The slab is its own container so the
     hero does not need to escape to the viewport edges any more;
     it just sits flush inside. */
  width:100%;
  margin:0 0 0;
  overflow:hidden;
  /* Warm placeholder tone behind the poster so it fades up from cream
     instead of flashing white before the photo paints. */
  background:#e8e4dc;
}
.stop-hero svg,.stop-hero .stop-art svg{
  display:block;width:100%;
  height:clamp(320px, 50vh, 520px);
  object-fit:cover;
}
.stop-photo{
  display:block;width:100%;
  height:clamp(320px, 50vh, 520px);
  object-fit:cover;
}
/* Desktop poster: ~60vh, still the loudest thing in the slab. */
@media(min-width:768px){
  .stop-hero svg,.stop-hero .stop-art svg{
    height:clamp(440px, 60vh, 720px);
  }
  .stop-photo{height:clamp(440px, 60vh, 720px)}
}
/* Label band: bigger, more breathable, with stronger gradient
   support so the type sits on a real darkness instead of fighting
   the photo. */
.stop-hero .label{
  position:absolute;left:0;right:0;bottom:0;
  /* Taller gradient with a smoother multi-stop fade, so the dark
     area reads as a gentle wash up the image rather than a hard
     band. Spans the full width of the poster (no max-width cap)
     so there is no visible edge where the gradient stops. */
  padding:5.5rem 1.6rem 1.8rem;
  background:linear-gradient(
    transparent 0%,
    rgba(14,30,22,.18) 28%,
    rgba(14,30,22,.55) 62%,
    rgba(14,30,22,.95) 100%);
  color:#f3ece0;
}
@media(min-width:720px){
  .stop-hero .label{padding:9rem 3rem 3rem}
}
/* Ord badge: bigger and squarer, like a poster's plate number. */
.stop-hero .ord-badge{
  position:absolute;top:1.2rem;left:1.2rem;z-index:2;
  background:var(--poster-crimson);color:#f3e6c8;
  width:54px;height:54px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-family:'Fraunces',serif;font-weight:900;font-size:1.35rem;
  box-shadow:0 4px 12px rgba(0,0,0,.35);
  border:2px solid rgba(243,230,200,.4);
}
@media(min-width:720px){
  .stop-hero .ord-badge{
    top:2rem;left:2rem;
    width:72px;height:72px;font-size:1.8rem;
  }
}
/* The big-deal headline: dramatic Fraunces, tight letter-spacing,
   responsive scale that lets it really sing on desktop. */
.stop-hero h3{
  font-family:'Fraunces',serif;font-weight:900;
  font-size:clamp(2.2rem, 7vw, 5rem);
  line-height:.95;
  letter-spacing:-.025em;
  color:#fff;
  text-shadow:0 2px 14px rgba(0,0,0,.4);
  margin:.4rem 0 .5rem;
}
.stop-hero .region{
  font-size:.72rem;letter-spacing:.32em;text-transform:uppercase;
  color:var(--poster-gold);font-weight:700;
}
@media(min-width:720px){
  .stop-hero .region{font-size:.82rem;letter-spacing:.38em}
}
.stop-hero .hook{
  font-family:'Fraunces',serif;font-style:italic;font-weight:500;
  font-size:clamp(1.05rem, 2vw, 1.4rem);
  line-height:1.4;
  color:#e9ddc8;margin-top:.5rem;
  max-width:42ch;
}

.stop-meta{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}
.stop-meta .pill{
  background:var(--card);border:1.5px solid var(--line);
  border-radius:4px;padding:.3rem .8rem;font-size:.78rem;
}
.stop-meta .pill b{color:var(--rail)}
.stop-blurb{color:#52493c;margin-bottom:1.3rem;padding:0 .15rem}

.share-row{display:flex;gap:.5rem;margin-bottom:1.5rem;flex-wrap:wrap}
.share-row button{
  font-family:'Spline Sans',sans-serif;font-size:.82rem;font-weight:600;
  padding:.5rem .95rem;border-radius:4px;cursor:pointer;
  border:2px solid var(--rail);background:transparent;color:var(--rail);
  transition:transform 160ms ease-out,
             background-color .15s ease, color .15s ease;
}
@media (hover:hover) and (pointer:fine){
  .share-row button:hover{background:var(--rail);color:#fff}
}
.share-row button:active{transform:scale(.97)}

/* category filter.
   Parent of the four category buttons. Was overflow-x:auto so it
   could scroll horizontally on narrow screens, but that also
   clipped the top of any button while it lifted on hover.
   Switched to overflow:visible (no clipping) and flex-wrap:wrap
   (buttons wrap to a second row on narrow screens instead of
   overflowing). Added padding-top:8px so the hover lift has room
   above the row without nudging the row down. */
.catfilter{
  display:flex;gap:.4rem;flex-wrap:nowrap;
  overflow-x:auto;overflow-y:visible;
  padding:8px 0 .7rem;
  margin-bottom:1.1rem;
  scrollbar-width:thin;
  -webkit-overflow-scrolling:touch;
}
.catfilter::-webkit-scrollbar{height:4px}
.catfilter::-webkit-scrollbar-thumb{background:rgba(142,61,34,.3);border-radius:4px}
.catfilter button{
  flex:0 0 auto;font-family:'Spline Sans',sans-serif;font-size:.84rem;
  font-weight:600;padding:.55rem 1.05rem;border-radius:4px;cursor:pointer;
  border:2px solid var(--line);background:var(--card);color:var(--muted);
  display:flex;align-items:center;gap:.45rem;
  white-space:nowrap;
  /* No browser-default focus outline: the default outline can
     visually detach from the button when transform is applied on
     hover. The element's own border (transformed with the button)
     handles all state indication. Keyboard focus picks up
     :focus-visible below for accessibility. */
  outline:none;
  /* Match transform timing with border-color so the lift and the
     border colour change land together. */
  transition:transform .22s cubic-bezier(.2,.7,.2,1),
             box-shadow .22s ease, color .22s ease,
             background .22s ease, border-color .22s ease;
}
.catfilter button:focus-visible{
  border-color:var(--rail);
  box-shadow:0 0 0 3px rgba(14,59,44,.18);
}
.catfilter button .ic{font-size:1rem;line-height:1}
.catfilter button .cnt{
  background:var(--line);color:var(--ink);border-radius:4px;
  font-size:.68rem;padding:.05rem .4rem;min-width:18px;text-align:center;
  transition:background .2s ease, color .15s ease;
}
/* Subtle lift on desktop hover, matching the listing card hover. */
@media (hover:hover){
  .catfilter button:hover{
    color:var(--rail);
    transform:translateY(-2px);
    box-shadow:0 8px 18px rgba(36,31,26,.14);
    border-color:var(--rail);
  }
  .catfilter button.active:hover{color:#fff}
}
.catfilter button.active{background:var(--poster-crimson);color:#fff;border-color:var(--poster-crimson)}
.catfilter button.active .cnt{background:rgba(255,255,255,.28);color:#fff}
.catfilter button:active{transform:scale(.97)}

/* ===== Sort + filter bar under the category tabs =====
   Three mutually exclusive sort pills (Featured / Closest / Top Rated)
   plus a stackable Local Deals filter. Smaller and lighter than the
   category tabs so the hierarchy reads clearly. */
.sort-bar{
  display:flex;align-items:center;gap:.4rem;flex-wrap:nowrap;
  overflow-x:auto;overflow-y:visible;
  padding:6px 0 12px;margin:0 0 .8rem;
  scrollbar-width:thin;-webkit-overflow-scrolling:touch;
}
.sort-bar::-webkit-scrollbar{height:4px}
.sort-bar::-webkit-scrollbar-thumb{background:rgba(142,61,34,.3);border-radius:4px}
.sort-bar .sort-label{
  flex:0 0 auto;font-family:'Spline Sans',sans-serif;
  font-size:.72rem;text-transform:uppercase;letter-spacing:.16em;
  font-weight:700;color:var(--muted);padding-right:.3rem;white-space:nowrap;
}
.sort-bar .sort-pill,
.sort-bar .deals-pill{
  flex:0 0 auto;display:inline-flex;align-items:center;gap:.35rem;
  font-family:'Spline Sans',sans-serif;font-size:.78rem;font-weight:600;
  color:var(--muted);background:transparent;
  border:1.5px solid var(--line);border-radius:999px;
  padding:.32rem .75rem;cursor:pointer;white-space:nowrap;
  transition:color .15s,border-color .15s,background .15s,transform .15s;
}
.sort-bar .sort-pill i,
.sort-bar .deals-pill i{font-size:1.05em;color:var(--poster-crimson)}
.sort-bar .sort-pill:hover,
.sort-bar .deals-pill:hover{color:var(--ink);border-color:var(--poster-crimson);transform:translateY(-1px)}
.sort-bar .sort-pill.active{
  color:#fff;background:var(--poster-crimson);border-color:var(--poster-crimson);
}
.sort-bar .sort-pill.active i{color:#fff}
.sort-bar .deals-pill.active{
  color:#fff;background:var(--gold);border-color:var(--gold);
}
.sort-bar .deals-pill.active i{color:#fff}
.sort-bar .sort-divider{
  flex:0 0 auto;width:1px;height:1.1em;background:var(--line);margin:0 .25rem;
}

/* Category header image: a full-width illustrated banner above the
   listing cards, swapped per selected category. 180px on mobile,
   220px on wider screens. The category name sits bottom-left in
   Fraunces over a soft dark gradient so it reads on any photo. */
.cat-header{
  position:relative;
  width:100%;height:180px;
  margin:0 0 1.1rem;
  border-radius:4px;overflow:hidden;
  background:#e8e4dc;
}
@media(min-width:768px){
  .cat-header{height:220px}
}
.cat-header img{
  width:100%;height:100%;
  object-fit:cover;object-position:center;
  display:block;
}
.cat-header.img-failed img{display:none}
.cat-header-label{
  position:absolute;left:0;right:0;bottom:0;
  padding:1.3rem 1.2rem 1rem;
  font-family:'Fraunces',serif;font-weight:600;
  font-size:1.9rem;line-height:1;
  color:var(--poster-cream);
  background:linear-gradient(0deg,
    rgba(18,28,38,.72) 0%,
    rgba(18,28,38,.34) 55%,
    rgba(18,28,38,0)   100%);
  text-shadow:0 2px 8px rgba(0,0,0,.5);
}
@media(min-width:768px){
  .cat-header-label{font-size:2.3rem}
}

/* Listing cards (with image area). Entrance animation is handled
   by the reveal-on-scroll system above: each card sits inside a
   .reveal wrapper that fades and rises as it enters the viewport,
   staggered via .cards > .reveal:nth-child rules. */
.cards{display:grid;grid-template-columns:1fr;gap:.9rem}
.card{
  background:var(--card);border:1.5px solid var(--line);
  border-radius:4px;overflow:hidden;cursor:pointer;
  text-align:left;font-family:inherit;padding:0;width:100%;
  display:flex;flex-direction:column;
  box-shadow:0 4px 14px rgba(36,31,26,.08);
  transition:transform .22s cubic-bezier(.2,.7,.2,1),
             box-shadow .22s ease, border-color .15s ease;
}
/* Gentle lift on desktop hover. Touch devices fall back to the
   :active scale below, since (hover: none) suppresses :hover. */
@media (hover:hover){
  .card:hover{
    transform:translateY(-4px);
    box-shadow:0 14px 28px rgba(36,31,26,.18);
    border-color:var(--poster-crimson);
  }
}
/* Combined press microstate: keep the lift, add a small scale.
   Without combining, the card snaps back to baseline on click
   which reads as a glitch. */
.card:active{transform:translateY(-2px) scale(.99)}
.card-img{
  position:relative;
  /* Fixed height (not aspect-ratio) so the image area never
     collapses to zero on mobile inside the flex card column.
     200px tall, full width, object-fit cover. */
  width:100%;height:200px;overflow:hidden;
  /* Loading state: a clean neutral grey instead of the warm
     amber + icon. The icon-bearing fallback only shows when the
     image genuinely cannot load (see .show-fallback below). */
  background:#e8e4dc;
}
.card-img img,.card-img svg{width:100%;height:100%;object-fit:cover;display:block}
/* Illustrated fallback sits behind the photo, but hidden by
   default so the loading state stays a neutral grey. Revealed via
   the .show-fallback class on the parent, which is set either at
   render time (listing has no image) or by the img's onerror
   handler (image failed to load). */
.card-img .img-fallback,.detail-img .img-fallback{
  position:absolute;inset:0;z-index:0;
  opacity:0;
  transition:opacity .22s ease;
}
.card-img.show-fallback .img-fallback,
.detail-img.show-fallback .img-fallback{opacity:1}
.card-img > img,.detail-img > img{
  position:relative;z-index:1;
  transition:opacity 220ms ease;
}
.card-img > img.img-failed,.detail-img > img.img-failed{opacity:0}
.card-body{padding:.9rem 1rem 1rem}
.card .toprow{display:flex;justify-content:space-between;align-items:flex-start;gap:.6rem}
.card .tag{
  font-size:.64rem;letter-spacing:.1em;text-transform:uppercase;
  font-weight:700;color:#fff;background:var(--poster-crimson);
  padding:.2rem .55rem;border-radius:2px;white-space:nowrap;
}
/* Featured tag: warm gold instead of crimson, dark ink text so the
   "Featured" label is unmistakable. Used on both .card .tag and
   .detail-body .tag when the listing has featured:true. */
.tag.tag-featured,
.detail-body .tag.tag-featured{
  background:var(--poster-gold);
  color:var(--poster-ink);
}
.card-featured{
  /* Subtle gold accent on the card frame so featured items read as
     elevated without screaming. */
  border-color:var(--poster-gold);
  box-shadow:0 4px 14px rgba(220,163,60,.18);
}
.card .rating{color:var(--gold);font-weight:700;font-size:.86rem;white-space:nowrap}
.card h4{font-size:1.16rem;font-weight:600;margin:.45rem 0 .25rem}
.card .desc{font-size:.88rem;color:var(--muted)}
/* Walking-time line below the listing name. Small, muted, and
   prefixed by the pin icon. Reused on the detail view too. The
   .hours-line shares this styling so the two micro-utility lines
   (walk + open-today) read as a related pair. */
.walk-line,
.hours-line{
  display:inline-flex;align-items:center;gap:.3rem;
  font-size:.78rem;color:var(--poster-rail-brown);
  font-weight:600;margin:.05rem 0 .4rem;
  letter-spacing:.01em;
}
.detail-body .walk-line,
.detail-body .hours-line{
  font-size:.86rem;margin:.3rem 0 .8rem;
}

/* Editorial description on the listing card. Two-line clamp with
   ellipsis so cards stay uniform regardless of summary length. The
   detail view uses .detail-desc for the same field with full text,
   so this class only applies inside .card-body. */
.card-body .description{
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
  overflow:hidden;
  font-size:.92rem;line-height:1.45;
  color:var(--ink);
  margin:.35rem 0 .4rem;
}

/* Discount badge on a listing card plus the discount detail line in the
   detail view. Both use the rusty brown poster-crimson accent so a
   member discount reads as a small, warm callout. */
.discount-badge{
  display:inline-flex;align-items:center;gap:.3rem;
  font-size:.68rem;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:#fff;
  background:var(--poster-crimson);
  padding:.22rem .5rem;border-radius:3px;
  margin:.1rem 0 .45rem;
}
.discount-badge .ph-light{font-size:.9em}
.detail-body .discount-line{
  display:inline-flex;align-items:center;gap:.4rem;
  font-size:.88rem;font-weight:600;
  color:var(--poster-crimson);
  margin:.2rem 0 .8rem;
}
.detail-body .discount-line .ph-light{flex:none}

/* Action row on the detail view: globe + phone buttons under the
   hours line. Vertical icon-over-label layout, comfortable tap
   targets (min 44px each), rusty crimson on hover-able tint. */
.action-row{
  display:flex;gap:.65rem;flex-wrap:wrap;
  margin:.2rem 0 1rem;
}
.action-btn{
  display:inline-flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.25rem;
  /* flex:1 makes Website / Call / Map share the row in equal widths. */
  flex:1 1 0;
  min-width:64px;min-height:44px;
  padding:.5rem .75rem;
  border:2px solid var(--poster-crimson);
  border-radius:4px;
  background:var(--card);
  color:var(--poster-crimson);
  text-decoration:none;
  font-family:'Spline Sans',sans-serif;
  font-size:.7rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  transition:transform 160ms ease-out,
             background-color .15s ease, color .15s ease;
}
.action-btn .ph-light{font-size:1.35em}
.action-btn .action-label{line-height:1}
@media (hover:hover) and (pointer:fine){
  .action-btn:hover{background:var(--poster-crimson);color:var(--poster-cream)}
}
.action-btn:active{transform:scale(.96)}
.card-cta{
  display:inline-block;margin-top:.6rem;font-size:.8rem;font-weight:700;
  color:var(--poster-crimson);
}

@media(min-width:620px){
  .cards{grid-template-columns:1fr 1fr}
}

/* ---------- detail view ---------- */
.stop.detail{animation:detailIn .24s cubic-bezier(.2,.7,.2,1) both}
@keyframes detailIn{
  from{opacity:0;transform:translateY(14px)}
  to{opacity:1;transform:none}
}
/* Back button: a full-width solid bar that sits ABOVE the image
   in its own row, never over it. Escapes the .stop horizontal
   padding so it spans the slab. On mobile it becomes sticky (with
   its solid background) so it stays reachable while scrolling
   without obscuring the photo. */
.backbtn{
  display:flex;align-items:center;gap:.45rem;
  margin:0 -1.25rem 1.2rem;
  padding:.85rem 1.25rem;
  background:var(--card);
  border:none;border-bottom:1px solid rgba(140,61,34,.16);
  color:var(--poster-crimson);
  font-family:'Spline Sans',sans-serif;font-size:.9rem;font-weight:700;
  cursor:pointer;text-align:left;width:auto;
  transition:color .15s ease, background-color .15s ease;
}
@media (hover:hover) and (pointer:fine){
  .backbtn:hover{color:var(--rail);background:rgba(142,61,34,.05)}
}
.backbtn:active{background:rgba(142,61,34,.07)}
@media (max-width:767px){
  .backbtn{
    position:sticky;top:52px;z-index:54;
  }
}
.detail-hero{
  /* Full-bleed in the slab (escapes the .stop side padding) so the
     photo lines up edge-to-edge with the full-width back bar above
     it, matching the stop poster treatment. */
  margin:0 -1.25rem 1.2rem;
  overflow:hidden;
}
.detail-img{
  position:relative;
  width:100%;aspect-ratio:16/9;
  background:#e8e4dc;
}
.detail-img img,.detail-img svg{width:100%;height:100%;object-fit:cover;display:block}

/* ---------- swipeable photo gallery (detail view) ----------
   Lives inside .detail-img when a listing has more than one photo.
   .gallery-track is a flex row of full-width slides; we move
   between slides by translating the track. Touch swipe is handled
   in app.js; prev/next buttons are visible on desktop (hover:hover)
   and hidden on touch so swipes are the only input. */
.gallery .gallery-track{
  display:flex;width:100%;height:100%;
  transition:transform .35s cubic-bezier(.23,1,.32,1);
  will-change:transform;
}
.gallery .gallery-slide{
  flex:0 0 100%;width:100%;height:100%;
  object-fit:cover;display:block;
  position:relative;z-index:1;
}
.gallery .gallery-slide.img-failed{opacity:0;transition:opacity .22s ease}
.gallery .gallery-prev,
.gallery .gallery-next{
  position:absolute;top:50%;transform:translateY(-50%);
  width:40px;height:40px;border-radius:50%;
  background:rgba(36,31,26,.55);color:#f3ece0;
  border:none;cursor:pointer;z-index:3;
  display:flex;align-items:center;justify-content:center;
  transition:background .15s ease, transform .15s ease;
}
.gallery .gallery-prev{left:.7rem}
.gallery .gallery-next{right:.7rem}
.gallery .gallery-prev:hover,
.gallery .gallery-next:hover{background:rgba(36,31,26,.8)}
.gallery .gallery-prev:active,
.gallery .gallery-next:active{transform:translateY(-50%) scale(.92)}
/* Hide arrows on touch devices: swipe is the primary input there. */
@media (hover:none){
  .gallery .gallery-prev,
  .gallery .gallery-next{display:none}
}
.gallery .gallery-dots{
  position:absolute;bottom:.65rem;left:50%;
  transform:translateX(-50%);
  display:flex;gap:.35rem;z-index:3;
  padding:.35rem .55rem;border-radius:4px;
  background:rgba(36,31,26,.4);
}
.gallery .gallery-dot{
  width:8px;height:8px;border-radius:50%;
  border:none;background:rgba(243,236,224,.55);
  padding:0;cursor:pointer;
  transition:background .2s ease, width .25s ease;
}
.gallery .gallery-dot.active{
  background:#f3ece0;
  width:22px;border-radius:4px;
}

@media(min-width:620px){
  .detail-img{aspect-ratio:21/9}
}
.detail-body{margin-bottom:1.6rem}
.detail-body .toprow{
  display:flex;gap:.6rem;align-items:center;margin-bottom:.5rem;
}
.detail-body .tag{
  font-size:.64rem;letter-spacing:.1em;text-transform:uppercase;
  font-weight:700;color:#fff;background:var(--poster-crimson);
  padding:.25rem .6rem;border-radius:2px;white-space:nowrap;
}
.detail-body .rating{color:var(--gold);font-weight:700;font-size:.9rem}
.detail-body h3{font-size:1.7rem;margin-bottom:.25rem}
.detail-loc{font-size:.84rem;color:var(--poster-crimson);font-weight:600;margin-bottom:.8rem}
.detail-desc{color:#52493c;margin-bottom:1.1rem}
.more{
  border-top:2px dashed var(--line);padding-top:1.4rem;
}
.more-head{
  font-size:1.15rem;color:var(--rail);margin-bottom:.9rem;
}

/* ---------- events ---------- */
.eventsection{padding:2.4rem 0 2.8rem;max-width:1080px;margin:0 auto}

/* ---------- homepage events grid (route-wide, grouped by month) ---------- */
#eventPanel{padding:0 1.1rem}

/* Filter card above the grid. Two-tier layout: a top "When" section
   spans the full width with month chips (the dimension visitors use
   most), then a three-column grid for What / Price / Walk time. Each
   section has an icon next to a friendly question word ("When",
   "What", "Price", "Walk time") so the bar feels conversational
   instead of form-like. Collapses to a single column on phones. */
.hev-filters{background:var(--card);border:1.5px solid var(--line);border-radius:10px;
  padding:1.1rem 1.2rem 1.2rem;margin:0 0 1.8rem;box-shadow:0 4px 14px rgba(36,31,26,.06)}
.hev-filters-head{display:flex;justify-content:space-between;align-items:center;
  margin:0 0 .9rem;padding-bottom:.7rem;border-bottom:1px solid var(--line)}
.hev-filters-title{font-family:'Fraunces',Georgia,serif;font-size:1.15rem;font-weight:600;color:var(--poster-ink);margin:0;line-height:1}
.hev-reset{background:transparent;border:0;color:var(--poster-crimson);font-size:.82rem;font-weight:700;
  cursor:pointer;padding:.25rem .5rem;display:inline-flex;align-items:center;gap:.25rem;
  border-radius:4px;font-family:inherit;transition:background .15s ease}
.hev-reset .ph-light{font-size:.95rem}
.hev-reset:hover{background:rgba(142,61,34,.08)}
.hev-filter-section{display:flex;flex-direction:column;gap:.45rem;margin:.7rem 0 0}
.hev-filter-section--full{margin-top:0}
.hev-filter-section-label{display:inline-flex;align-items:center;gap:.4rem;
  font-size:.78rem;letter-spacing:.05em;text-transform:uppercase;font-weight:700;color:var(--poster-mute)}
.hev-filter-section-label .ph-light{font-size:1rem;color:var(--poster-crimson)}
/* Three filter sections sit on one row with equal gaps between them.
   Each section is content-sized (no forced 1fr), so Price does not
   pad out into empty space and Walk time keeps all four chips on a
   single line on desktop. Stacks vertically below 720px. */
.hev-filter-grid{display:flex;justify-content:space-between;align-items:flex-start;
  flex-wrap:wrap;gap:1rem 1.5rem;margin-top:.4rem}
.hev-filter-section{flex:0 1 auto;min-width:0}
.hev-chip-row{display:flex;flex-wrap:wrap;gap:.4rem}
.hev-chip{background:transparent;border:1.5px solid var(--line);border-radius:999px;
  padding:.38rem .9rem;font-size:.84rem;font-weight:600;color:var(--poster-ink);cursor:pointer;
  font-family:inherit;line-height:1.2;
  transition:background .15s ease,color .15s ease,border-color .15s ease,transform .15s ease}
.hev-chip:hover{border-color:var(--poster-crimson);color:var(--poster-crimson)}
.hev-chip.is-active{background:var(--poster-crimson);border-color:var(--poster-crimson);color:var(--poster-ivory,#f6efe2);
  box-shadow:0 2px 8px rgba(142,61,34,.25)}
.hev-select{background:var(--poster-ivory,#f6efe2);border:1.5px solid var(--line);border-radius:6px;
  padding:.5rem .75rem;font-size:.9rem;font-family:'Spline Sans',sans-serif;color:var(--poster-ink);
  width:100%;max-width:280px;cursor:pointer;
  appearance:none;-webkit-appearance:none;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23766f5d'><path d='M4 6 L8 10 L12 6 Z'/></svg>");
  background-repeat:no-repeat;background-position:right .65rem center;background-size:14px;padding-right:2rem}
.hev-select:focus{outline:none;border-color:var(--poster-crimson)}
@media (max-width:720px){
  .hev-filter-grid{grid-template-columns:1fr;gap:.7rem}
}
@media (max-width:480px){
  .hev-filters{padding:1rem 1rem 1.1rem}
  .hev-filters-title{font-size:1.05rem}
}

.hev-month{margin:0 0 2.4rem}
.hev-month-label{font-family:'Fraunces',Georgia,serif;font-size:1.35rem;font-weight:600;color:var(--poster-ink);
  margin:0 0 1rem;padding:0 0 .5rem;border-bottom:1.5px solid var(--line);letter-spacing:.01em}
.hev-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:1.1rem}
.hev-card{background:var(--card);border:1.5px solid var(--line);border-radius:4px;
  display:flex;flex-direction:column;text-decoration:none;color:inherit;overflow:hidden;
  transition:transform .22s cubic-bezier(.2,.7,.2,1),box-shadow .22s ease,border-color .15s ease}
@media (hover:hover){
  a.hev-card:hover{transform:translateY(-3px);box-shadow:0 14px 28px rgba(36,31,26,.16);
    border-color:var(--poster-crimson)}
}
.hev-img{width:100%;aspect-ratio:16/9;background:#e8e0cd center/cover no-repeat}
.hev-img--blank{display:flex;align-items:center;justify-content:center;color:var(--poster-crimson)}
.hev-img--blank .ph-light,.hev-img--blank .ph{font-size:48px}
.hev-body{padding:1rem 1.1rem 1.1rem;display:flex;flex-direction:column;flex:1;gap:.35rem}
.hev-when{font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;font-weight:700;color:var(--poster-crimson)}
.hev-name{font-family:'Fraunces',Georgia,serif;font-size:1.15rem;font-weight:600;margin:.1rem 0 0;color:var(--poster-ink);line-height:1.25}
.hev-stop{font-size:.82rem;color:var(--poster-mute)}
.hev-desc{font-size:.88rem;line-height:1.45;color:var(--poster-ink);opacity:.82;margin:.4rem 0 0;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.hev-meta{display:flex;flex-wrap:wrap;gap:.3rem .8rem;margin-top:.5rem}
.hev-walk{display:inline-flex;align-items:center;gap:.3rem;font-size:.78rem;font-weight:700;
  color:var(--poster-crimson);letter-spacing:.02em}
.hev-walk .ph-light{font-size:.95rem}
.hev-family{display:inline-flex;align-items:center;gap:.3rem;font-size:.72rem;font-weight:700;
  color:#3f6e44;letter-spacing:.02em;
  background:rgba(63,110,68,.1);padding:.15rem .55rem;border-radius:999px;line-height:1.4}
.hev-family .ph-light{font-size:.95rem}
.hev-foot{display:flex;justify-content:space-between;align-items:center;gap:.6rem;margin-top:auto;padding-top:.8rem}
.hev-price{font-size:.78rem;font-weight:700;color:var(--poster-ink);letter-spacing:.02em}
.hev-cta{font-size:.78rem;font-weight:700;color:var(--poster-crimson);display:inline-flex;align-items:center;gap:.2rem}
.hev-cta .ph-light{font-size:.95rem}
/* Pagination below the homepage event grid. Centred row of buttons
   with a clear active state. Prev / Next gain a subtle caret. */
.hev-pagination{display:flex;justify-content:center;align-items:center;flex-wrap:wrap;
  gap:.4rem;margin:1.6rem 0 .8rem}
.hev-pagebtn{background:transparent;border:1.5px solid var(--line);border-radius:4px;
  min-width:36px;height:36px;padding:0 .65rem;font-size:.9rem;font-weight:700;font-family:inherit;
  color:var(--poster-ink);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:.25rem;
  transition:background .15s ease,color .15s ease,border-color .15s ease}
.hev-pagebtn:hover:not([disabled]){border-color:var(--poster-crimson);color:var(--poster-crimson)}
.hev-pagebtn.is-active{background:var(--poster-crimson);border-color:var(--poster-crimson);color:var(--poster-ivory,#f6efe2)}
.hev-pagebtn[disabled]{opacity:.4;cursor:not-allowed}
.hev-pagenav{padding:0 .9rem}
.hev-pageellipsis{padding:0 .35rem;color:var(--poster-mute);font-weight:700}

.hev-empty{padding:3rem 1.5rem;text-align:left;background:var(--card);border:1.5px dashed var(--line);border-radius:4px;max-width:640px;margin:0 auto}
.hev-empty .ph-light,.hev-empty .ph{font-size:2.8rem;color:var(--poster-crimson);display:block;margin-bottom:.7rem}
.hev-empty p{font-family:'Fraunces',Georgia,serif;font-size:1.1rem;color:var(--poster-ink);margin:0 0 .8rem;max-width:540px}
.hev-empty a{color:var(--poster-crimson);font-weight:600}

/* ---------- event CTA card (replaces the inline form) ---------- */
.event-cta{margin:3rem 1.1rem 0;padding:2.2rem 1.5rem;background:var(--card);
  border:1.5px solid var(--line);border-radius:6px;text-align:center}
.event-cta-body h3{font-family:'Fraunces',Georgia,serif;font-size:1.55rem;font-weight:600;margin:0 0 .55rem;color:var(--poster-ink)}
.event-cta-body p{max-width:560px;margin:0 auto 1.2rem;color:var(--poster-mute);font-size:.96rem;line-height:1.55}
.event-cta-body .btn{display:inline-flex;align-items:center;gap:.4rem}

/* ---------- event submission modal ---------- */
.ev-modal{padding:0;border:0;background:transparent;
  /* Center the card in the viewport. */
  max-width:760px;width:calc(100vw - 2rem);max-height:calc(100vh - 2rem);
  margin:auto;overflow:visible}
.ev-modal::backdrop{background:rgba(20,28,30,.72);backdrop-filter:blur(4px)}
.ev-modal-card{position:relative;background:var(--card);border:1.5px solid var(--line);border-radius:6px;
  max-height:calc(100vh - 2rem);overflow-y:auto;padding:2rem 1.6rem 1.8rem;box-shadow:0 24px 60px rgba(0,0,0,.35)}
.ev-modal-close{position:absolute;top:.6rem;right:.6rem;background:transparent;border:0;cursor:pointer;
  width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center;color:var(--poster-mute);
  border-radius:50%;transition:background .15s ease,color .15s ease}
.ev-modal-close:hover{background:rgba(0,0,0,.06);color:var(--poster-crimson)}
.ev-modal-close .ph-light{font-size:22px}
.ev-modal-head{max-width:560px;margin:0 auto 1.4rem;text-align:center;padding-right:2rem;padding-left:2rem}
.ev-modal-head h2{font-family:'Fraunces',Georgia,serif;font-size:1.6rem;font-weight:600;margin:0 0 .5rem;color:var(--poster-ink)}
.ev-modal-head p{margin:0;color:var(--poster-mute);font-size:.94rem;line-height:1.5}
@media (max-width:480px){
  .ev-modal-head{padding-left:0;padding-right:0}
  .ev-modal-card{padding:1.4rem 1.1rem}
}

/* ---------- /submit-event/ standalone page ---------- */
.submit-event-page{background:var(--poster-ivory,#f6efe2);min-height:100vh;display:flex;flex-direction:column}
.submit-event-page .topbar{position:sticky;top:0;background:var(--poster-forest,#0e3b2c);color:#f3ece0;
  padding:.7rem 1.1rem;display:flex;justify-content:space-between;align-items:center;z-index:5}
.submit-event-page .topbar .brand{color:#f3ece0;display:inline-flex;align-items:center;gap:.55rem;text-decoration:none;font-weight:700}
.submit-event-page .topbar .brand span{color:var(--poster-gold,#d9a648)}
.topbar-back{color:#f3ece0;text-decoration:none;font-size:.92rem;display:inline-flex;align-items:center;gap:.3rem}
.topbar-back:hover{color:var(--poster-gold,#d9a648)}
.submit-event-main{flex:1;max-width:760px;width:100%;margin:0 auto;padding:2.4rem 1.2rem 3rem}
.submit-event-hero{text-align:center;margin:0 0 2rem}
.submit-event-hero .kicker{color:var(--poster-crimson);font-size:.78rem;letter-spacing:.32em;text-transform:uppercase;font-weight:700;margin:0 0 .8rem}
.submit-event-hero h1{font-family:'Fraunces',Georgia,serif;font-size:2.2rem;font-weight:600;color:var(--poster-ink);margin:0 0 .8rem;line-height:1.15}
.submit-event-hero p{color:var(--poster-mute);max-width:560px;margin:0 auto;font-size:1rem;line-height:1.55}
.event-form--page{background:var(--card);border:1.5px solid var(--line);border-radius:6px;padding:1.6rem 1.4rem 1.8rem}
.submit-event-footer{padding:1.4rem 1.2rem;text-align:center;color:var(--poster-mute);font-size:.85rem;border-top:1px solid var(--line);background:var(--card)}
.submit-event-footer p{margin:.2rem 0}
.submit-event-footer a{color:var(--poster-crimson)}

/* ---------- event submission form ---------- */
.event-submit{margin:3rem 1.1rem 0;padding:2rem 1.5rem 2.2rem;
  background:var(--card);border:1.5px solid var(--line);border-radius:6px}
.event-submit-head{max-width:640px;margin:0 auto 1.6rem;text-align:center}
.event-submit-head h3{font-family:'Fraunces',Georgia,serif;font-size:1.6rem;font-weight:600;margin:0 0 .5rem;color:var(--poster-ink)}
.event-submit-head p{color:var(--poster-mute);font-size:.96rem;line-height:1.55;margin:0}
.event-form{max-width:760px;margin:0 auto}
.event-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:.9rem 1rem}
@media (max-width:640px){.event-form-grid{grid-template-columns:1fr}}
.ef-field{display:flex;flex-direction:column;gap:.35rem}
.ef-field.ef-span-2{grid-column:span 2}
@media (max-width:640px){.ef-field.ef-span-2{grid-column:span 1}}
.ef-label{font-size:.78rem;letter-spacing:.06em;text-transform:uppercase;font-weight:700;color:var(--poster-mute)}
.ef-req{color:var(--poster-crimson)}
.event-form input[type="text"],
.event-form input[type="email"],
.event-form input[type="url"],
.event-form input[type="date"],
.event-form select,
.event-form textarea{
  width:100%;font-family:'Spline Sans',sans-serif;font-size:.95rem;
  background:var(--poster-ivory,#f6efe2);border:1.5px solid var(--line);
  border-radius:4px;padding:.6rem .7rem;color:var(--poster-ink);
  transition:border-color .15s ease}
.event-form input:focus,.event-form select:focus,.event-form textarea:focus{
  outline:none;border-color:var(--poster-crimson)}
.event-form textarea{resize:vertical;min-height:96px;font-family:inherit}
.ef-checkbox-inline{flex-direction:row;align-items:center;gap:.5rem;padding-top:1.4rem}
.ef-checkbox-inline input{width:18px;height:18px;accent-color:var(--poster-crimson)}
.ef-checkbox-inline span{font-size:.92rem;color:var(--poster-ink)}
.ef-honey{position:absolute;left:-9999px;opacity:0;pointer-events:none}
.ef-confirms{margin:1.2rem 0 1rem;display:flex;flex-direction:column;gap:.6rem}
.ef-check{display:flex;align-items:flex-start;gap:.55rem;font-size:.92rem;color:var(--poster-ink);cursor:pointer}
.ef-check input{margin-top:3px;width:16px;height:16px;accent-color:var(--poster-crimson);flex:none}
/* Image picker: upload OR url, on a single horizontal row that
   wraps. Preview sits below the row at small size. */
.ef-image-block{display:flex;flex-direction:column;gap:.4rem}
.ef-image-hint{margin:0 0 .2rem;font-size:.84rem;color:var(--poster-mute);line-height:1.5}
.ef-image-hint em{font-style:normal;color:var(--poster-ink);font-weight:600}
.ef-image-pickers{display:flex;gap:.6rem;flex-wrap:wrap;align-items:center}
.ef-image-upload{
  display:inline-flex;align-items:center;gap:.4rem;
  padding:.55rem .9rem;background:var(--poster-ivory,#f6efe2);
  border:1.5px solid var(--line);border-radius:4px;cursor:pointer;
  font-size:.92rem;font-weight:600;color:var(--poster-ink);
  transition:background .15s ease,color .15s ease,border-color .15s ease;
  white-space:nowrap}
.ef-image-upload:hover{background:var(--poster-crimson);color:var(--poster-ivory,#f6efe2);border-color:var(--poster-crimson)}
.ef-image-upload .ph-light{font-size:1.05rem}
.ef-image-clear{
  background:transparent;border:0;cursor:pointer;font-size:.85rem;
  color:var(--poster-mute);text-decoration:underline;padding:.4rem .2rem}
.ef-image-clear:hover{color:var(--poster-crimson)}
.ef-image-url{flex:1 1 200px;min-width:0}
.ef-image-preview{display:block;max-width:240px;max-height:160px;
  object-fit:cover;border:1px solid var(--line);border-radius:4px;margin-top:.4rem}

.event-form button[type="submit"]{margin-top:.4rem}
.event-form button[type="submit"][disabled]{opacity:.5;cursor:not-allowed}
.ef-msg{font-size:.92rem;margin:.8rem 0 0;color:var(--poster-crimson);min-height:1.2em}
.ef-msg.ok{color:var(--poster-gold)}
.evlist{padding:0 1.1rem;display:grid;gap:.9rem}
.evcard{
  display:flex;gap:1.1rem;background:var(--card);
  border:1.5px solid var(--line);
  border-radius:4px;padding:1rem 1.15rem;align-items:stretch;
  box-shadow:0 4px 14px rgba(36,31,26,.08);
  transition:transform .22s cubic-bezier(.2,.7,.2,1),
             box-shadow .22s ease, border-color .15s ease;
}
@media (hover:hover){
  .evcard:hover{
    transform:translateY(-3px);
    box-shadow:0 14px 28px rgba(36,31,26,.16);
    border-color:var(--poster-crimson);
  }
}
/* Bold date block: poster-crimson plate, cream day numeral and gold
   month label. The big serif day reads first, the small spaced month
   below it. Matches the site's palette and rounded-corner language. */
.evcard .date{
  flex:0 0 78px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;background:var(--poster-crimson);
  border-radius:4px;padding:.65rem .35rem .55rem;
  box-shadow:0 4px 10px rgba(140,61,34,.25);
}
.evcard .date .d{
  font-family:'Fraunces',serif;font-size:2.4rem;font-weight:900;
  line-height:1;letter-spacing:-.02em;
  color:var(--poster-cream);
}
.evcard .date .m{
  margin-top:.4rem;
  font-size:.7rem;letter-spacing:.22em;text-transform:uppercase;
  font-weight:700;color:var(--poster-gold);
}
.evcard > div:last-child{
  flex:1;display:flex;flex-direction:column;justify-content:center;
}
.evcard h4{
  font-family:'Fraunces',serif;font-size:1.15rem;font-weight:700;
  color:var(--ink);line-height:1.2;
}
.evcard .where{
  font-size:.82rem;color:var(--poster-crimson);
  font-weight:700;margin:.25rem 0 .3rem;letter-spacing:.01em;
}
.evcard .edesc{font-size:.9rem;color:var(--muted);line-height:1.5}

/* ---------- ad slots ---------- */
.adslot{
  background:repeating-linear-gradient(45deg,#e8ddc8 0 11px,#e3d7bf 11px 22px);
  border:1.5px dashed var(--line);border-radius:4px;
  display:flex;align-items:center;justify-content:center;
  color:#a99c80;font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;
  font-weight:600;
}
.adslot.inline{margin:1.8rem 1.25rem 0;min-height:110px}

/* ---------- footer ---------- */
footer{background:var(--rail-deep);color:#cad7cf;padding:2.6rem 1.4rem 1.6rem}
.fwrap{max-width:1080px;margin:0 auto;display:grid;gap:1.8rem}
.fcol h4{font-family:'Fraunces',serif;color:#f3ece0;font-size:1.05rem;margin-bottom:.5rem}
.fcol a{color:#cad7cf;text-decoration:none;display:block;padding:.2rem 0;font-size:.9rem}
.fcol a:hover{color:var(--gold)}
.fbrand .brand{font-size:1.15rem;margin-bottom:.5rem;display:inline-block}
.fbrand p{font-size:.87rem;color:#9fb0a6;max-width:40ch}
.disc{
  max-width:1080px;margin:1.9rem auto 0;padding-top:1.3rem;
  border-top:1px solid var(--rail-2);font-size:.74rem;color:#7e948a;
}
@media(min-width:680px){
  .fwrap{grid-template-columns:2fr 1fr 1fr}
}

/* ---------- back to top ----------
   Appears once the user has scrolled >600px (see app.js scroll
   listener). Sits in the bottom-right with a comfortable mobile
   tap target (52px, above the 44px WCAG minimum). Includes
   env(safe-area-inset-bottom) so it never slips under the iOS
   home indicator. */
.totop{
  position:fixed;
  right:1.1rem;
  bottom:calc(1.1rem + env(safe-area-inset-bottom,0));
  z-index:900;
  width:52px;height:52px;border-radius:50%;
  background:var(--poster-crimson);color:#fff;text-decoration:none;
  display:flex;align-items:center;justify-content:center;
  font-size:1.45rem;box-shadow:0 6px 16px rgba(142,61,34,.4);
  opacity:0;pointer-events:none;
  transition:opacity .25s ease, transform .22s ease-out;
}
.totop.show{opacity:1;pointer-events:auto}
.totop:active{transform:scale(.94)}

/* Floating back-to-all-stops button, mirror of .totop top-left. Shows
   after a short scroll so it does not crowd the hero on first view. */
.toback{
  position:fixed;
  left:1.1rem;
  top:calc(70px + env(safe-area-inset-top,0));
  z-index:900;
  width:46px;height:46px;border-radius:50%;
  background:var(--rail-deep);color:#f3ece0;text-decoration:none;
  display:flex;align-items:center;justify-content:center;
  font-size:1.35rem;
  border:1px solid #1d4d3a;
  box-shadow:0 6px 16px rgba(10,45,33,.35);
  opacity:0;pointer-events:none;
  transition:opacity .25s ease, transform .22s ease-out, color .15s;
}
.toback.show{opacity:1;pointer-events:auto}
.toback:hover{color:var(--gold)}
.toback:active{transform:scale(.94)}

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

/* ---------- toast ---------- */
.toast{
  position:fixed;left:50%;bottom:1.4rem;transform:translateX(-50%) translateY(20px);
  background:var(--rail);color:#f3ece0;padding:.7rem 1.2rem;border-radius:4px;
  font-size:.86rem;font-weight:600;box-shadow:var(--shadow);
  opacity:0;transition:all .3s;z-index:1100;pointer-events:none;
}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}

/* ===== Stop-page link on listing cards ===== */
.stop-page-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: 'Spline Sans', sans-serif;
  font-size: 12px;
  letter-spacing: 0.06em;
  color: #7d3a1e;
  text-decoration: none;
  margin-top: 8px;
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s;
}
.stop-page-link:hover { border-bottom-color: #7d3a1e; }

/* ===== Lantern "Explore Stops" button (header) =====
   Matches .topnav a so the button sits inline with the other links. */
.stop-explorer-btn {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  background: none;
  border: 0;
  cursor: pointer;
  color: #f3ece0;
  font-family: 'Spline Sans', sans-serif;
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .02em;
  padding: 0;
  line-height: 1;
  transition: color .15s ease;
}
.stop-explorer-btn:hover { color: var(--gold); }
.stop-explorer-btn i {
  color: #f0b541;
  font-size: 1.3em;
  animation: lanternGlow 2.4s ease-in-out infinite;
}
@keyframes lanternGlow {
  0%, 100% {
    filter: drop-shadow(0 0 4px rgba(240,181,65,0.7)) drop-shadow(0 0 10px rgba(240,181,65,0.35));
    transform: scale(1);
    opacity: 0.95;
  }
  50% {
    filter: drop-shadow(0 0 12px rgba(255,200,90,1)) drop-shadow(0 0 22px rgba(255,200,90,0.55));
    transform: scale(1.08);
    opacity: 1;
  }
}

/* ===== Header "More" dropdown menu =====
   Categorised list of additional pages. Categories are placeholders -
   add new <a> tags under each .nav-section to populate. */
.nav-dropdown { position: relative; display: inline-block; }
.nav-dropdown-toggle {
  background: none; border: 0; cursor: pointer;
  color: #f3ece0;
  font-family: 'Spline Sans', sans-serif;
  font-size: .82rem; font-weight: 600; letter-spacing: .02em;
  padding: 0; line-height: 1;
  display: inline-flex; align-items: baseline; gap: 5px;
  transition: color .15s ease;
}
.nav-dropdown-toggle:hover, .nav-dropdown.open .nav-dropdown-toggle { color: var(--gold); }
.nav-dropdown-toggle i { font-size: 1.15em; transition: transform .2s; }
.nav-dropdown.open .nav-dropdown-toggle i { transform: rotate(180deg); }
.nav-dropdown-panel {
  position: absolute; top: 100%; right: 0;
  background: var(--rail-deep);
  border: 1px solid #1d4d3a;
  min-width: 240px; padding: 18px 22px 20px;
  margin-top: 14px; z-index: 1500;
  opacity: 0; visibility: hidden;
  transform: translateY(-6px);
  transition: opacity .15s, transform .15s, visibility .15s;
  box-shadow: 0 8px 24px rgba(0,0,0,.25);
}
.nav-dropdown.open .nav-dropdown-panel { opacity: 1; visibility: visible; transform: translateY(0); }
.nav-section + .nav-section { margin-top: 16px; padding-top: 16px; border-top: 1px solid #1d4d3a; }
.nav-section-label {
  text-transform: uppercase; letter-spacing: .2em;
  font-size: 10px; color: var(--gold);
  font-family: 'Spline Sans', sans-serif;
  font-weight: 700; margin: 0 0 10px;
}
.nav-section a {
  display: block; color: #f3ece0;
  font-size: 13px; font-weight: 500;
  padding: 5px 0;
  text-decoration: none;
  letter-spacing: .01em;
  transition: color .15s;
}
.nav-section a:hover { color: var(--gold); }
@media (max-width: 900px) { .nav-dropdown { display: none; } }

/* ===== Stop explorer overlay ===== */
.stop-explorer {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(10,45,33,0.97);
  display: none; overflow-y: auto;
}
.stop-explorer.open { display: block; }
.stop-explorer .se-panel { max-width: 1100px; margin: 0 auto; padding: 70px 24px 60px; position: relative; }
.stop-explorer .se-close {
  position: absolute; top: 22px; right: 22px;
  background: none; border: 2px solid #f5f0e8; color: #f5f0e8;
  width: 42px; height: 42px; font-size: 24px; line-height: 1; cursor: pointer;
}
.stop-explorer .se-close:hover { background: #f5f0e8; color: #0a2d21; }
.stop-explorer .se-kicker { text-transform: uppercase; letter-spacing: .2em; font-size: 11px; font-weight: 600; color: #c4860f; }
.stop-explorer .se-head h2 { font-family: 'Fraunces', serif; color: #f5f0e8; font-size: clamp(2rem,5vw,3.4rem); margin: 10px 0 4px; font-weight: 700; }
.stop-explorer .se-head p { color: #b9c9bf; font-size: 14px; margin: 0 0 32px; }
.stop-explorer .se-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
.stop-explorer .se-card { text-decoration: none; background: #ede0cc; border: 1px solid #d3c4a6;
  display: flex; flex-direction: column; transition: border-color .15s, transform .15s; }
.stop-explorer .se-card:hover { border-color: #c4860f; transform: translateY(-2px); }
.stop-explorer .se-card-img { height: 120px; overflow: hidden; background: #ede0cc; }
.stop-explorer .se-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.stop-explorer .se-card-body { padding: 14px 16px 16px; position: relative; }
.stop-explorer .se-num { position: absolute; top: -16px; left: 14px; width: 30px; height: 30px; border-radius: 50%;
  background: #c4860f; color: #0a2d21; font-family: 'Fraunces', serif; font-weight: 700; font-size: 15px;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 1px 3px rgba(10,45,33,.4); }
.stop-explorer .se-card h3 { font-family: 'Fraunces', serif; color: #0a2d21; font-size: 20px; margin: 10px 0 4px; font-weight: 600; }
.stop-explorer .se-time { display: block; color: #7d3a1e; font-size: 12px; letter-spacing: .03em; font-weight: 600; }
.stop-explorer .se-explore { display: inline-block; margin-top: 10px; color: #7d3a1e; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; font-weight: 600; }
@media (max-width: 900px) { .stop-explorer .se-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .stop-explorer .se-grid { grid-template-columns: 1fr; } }

/* ===== "Plan a Trip" nav pill (shared across all pages) =====
   Sits inline with other .topnav items. Text stays ivory in both
   states; only the background flips to rusty brown on hover. The
   selectors use `a.topnav-plan` so they out-specify the
   `.topnav a:hover{color:var(--gold)}` rule above and the text
   doesn't pick up the gold link-hover. */
a.topnav-plan{
  font-family:'Spline Sans',sans-serif;
  font-size:.82rem;font-weight:600;letter-spacing:.02em;
  color:#f3ece0;text-decoration:none;
  padding:.35rem .8rem;border-radius:3px;
  border:1px dashed var(--poster-gold);
  transition:background .15s, color .15s, border-color .15s;
}
a.topnav-plan:hover{
  /* Matches the .btn-primary rust (#6e2e17) so the pill reads as
     part of the site's CTA palette, not a lighter shade of crimson. */
  background:#6e2e17;color:#f3ece0;border-color:#6e2e17;
}

/* ===== Stop-page "Plan Your Trip" CTA =====
   Rendered by stop-page.js between the "Continue Your Journey" and
   "Before You Board" sections. Mirrors the /plan boarding-pass
   aesthetic: forest stub with a vertical wordmark on the left, warm
   cream paper body with a rust kicker, Fraunces headline and rust
   CTA on the right. Reads as a real ticket the visitor is being
   handed at the end of the stop guide. */
.sp-plan-trip-cta{
  margin:1.8rem auto;
  max-width:820px;
  background:#fbf6ea;
  color:#241f1a;
  display:grid;grid-template-columns:60px 1fr;
  box-shadow:0 10px 26px rgba(40,30,20,.14);
  position:relative;
}
.sp-plan-trip-cta-stub{
  background:#0a2d21;
  color:#f3ece0;
  display:flex;flex-direction:column;align-items:center;justify-content:space-between;
  padding:18px 8px;
  border-right:2px dashed rgba(245,240,232,.45);
  text-align:center;
}
.sp-plan-trip-cta-stub i{
  font-size:24px;color:#c4860f;line-height:1;
}
.sp-plan-trip-cta-stub-line{
  writing-mode:vertical-rl;transform:rotate(180deg);
  font-family:'Fraunces',Georgia,serif;
  font-weight:900;font-size:13px;letter-spacing:.18em;
  text-transform:uppercase;line-height:1;
  color:#c4860f;
}
.sp-plan-trip-cta-body{
  padding:24px 28px 22px;
  display:flex;flex-direction:column;gap:8px;
}
.sp-plan-trip-cta-kicker{
  font-family:'Spline Sans',sans-serif;
  text-transform:uppercase;letter-spacing:.22em;
  font-size:11px;font-weight:700;color:#7d3a1e;
}
.sp-plan-trip-cta-body h3{
  font-family:'Fraunces',Georgia,serif;
  font-weight:700;font-size:1.5rem;color:#0a2d21;
  margin:0;line-height:1.1;letter-spacing:-.005em;
}
.sp-plan-trip-cta-body p{
  font-family:'Fraunces',Georgia,serif;
  font-style:italic;font-size:1rem;line-height:1.5;
  color:#3a2f22;opacity:.85;margin:0 0 8px;
}
.sp-plan-trip-cta-btn{
  align-self:flex-start;
  display:inline-flex;align-items:center;gap:6px;
  background:#7d3a1e;color:#f5f0e8;
  font-family:'Spline Sans',sans-serif;
  font-weight:600;font-size:.92rem;letter-spacing:.04em;
  padding:.75rem 1.3rem;border-radius:0;
  text-decoration:none;
  border:2px solid #7d3a1e;
  transition:background .15s, border-color .15s, transform .15s;
}
.sp-plan-trip-cta-btn:hover{
  background:#0a2d21;border-color:#0a2d21;color:#f5f0e8;
  transform:translateY(-1px);
}
.sp-plan-trip-cta-btn i{font-size:1.1em;line-height:1}
@media(max-width:560px){
  .sp-plan-trip-cta{grid-template-columns:1fr}
  .sp-plan-trip-cta-stub{
    flex-direction:row;justify-content:center;gap:14px;
    padding:12px 16px;
    border-right:0;border-bottom:2px dashed rgba(245,240,232,.45);
  }
  .sp-plan-trip-cta-stub-line{
    writing-mode:horizontal-tb;transform:none;
  }
  .sp-plan-trip-cta-body{padding:22px 20px}
  .sp-plan-trip-cta-body h3{font-size:1.3rem}
  .sp-plan-trip-cta-btn{width:100%;justify-content:center}
}
