/* ==================================================================
   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-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;
}
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(--ember);
}
.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:100px;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{
  background:var(--poster-crimson);color:var(--poster-cream);
  border-color:var(--poster-crimson);
  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);
  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;
  display:flex;align-items:center;gap:.5rem;
}
/* "Guide" picks up the same mustard gold accent as "every stop."
   in the hero headline so the logo and headline accent match.
   Was var(--ember) which read as muddy orange against the
   forest green bar. */
.brand span{color:var(--poster-gold);font-style:normal}
.brand-mark{display:flex;flex-shrink:0;line-height:0}
.brand-mark svg{display:block}
.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(--ember)}

/* 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:6px;
}
.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);
    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(--ember)}
}

/* ---------- 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;
  }
}

/* ---------- 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;
  display:flex;flex-direction:column;align-items:center;
  /* Top padding reduced (was 3.8rem) so the text block sits up
     in the calm sky area of the photograph, well clear of the
     heron's head and the busy water reflections below. */
  padding:1.6rem 1.2rem 2.4rem;
  /* Reduced again so the page content below comes into view
     sooner: clamp(380px, 52vh, 540px) was clamp(440px, 62vh,
     600px). Content can still push the hero taller if needed,
     since min-height does not cap growth. */
  min-height:clamp(380px,52vh,540px);
}
.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:780px;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{
  /* Bumped again to make the poster headline feel large and bold
     on both desktop and mobile. Min raised from 2.8rem to 3.75rem
     so the headline fills the width nicely on phones (about 60px
     on a 375px viewport); vw raised to 16vw for smooth growth
     through tablet sizes; max raised from 6rem to 7.5rem so the
     headline reaches ~120px on wide desktops. */
  font-size:clamp(3.75rem,16vw,7.5rem);
  letter-spacing:-.015em;line-height:.94;
  /* Breathing room between the headline and the paragraph below
     (was .8rem, too tight). */
  margin:0 0 1.5rem;
  color:var(--poster-cream);
  text-shadow:0 2px 10px rgba(0,0,0,.55), 0 1px 2px rgba(0,0,0,.5);
}
.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);
  font-size:1.04rem;line-height:1.55;font-weight:500;
  max-width:46ch;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: lives outside the hero now (so it never covers the
   image). Still a flat cream band with a thin crimson top rule
   marking the transition from image to text. */
.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);
}
.hero-stats div{
  flex:1;text-align:center;padding:1.2rem .4rem 1rem;
  border-right:1px solid rgba(140,61,34,.18);
  background:transparent;
}
.hero-stats div:last-child{border-right:none}
.hero-stats b{
  display:block;font-family:'Fraunces',serif;font-weight:900;
  font-size:2.3rem;color:var(--poster-crimson);line-height:1;
  letter-spacing:-.015em;
}
.hero-stats span{
  display:block;margin-top:.45rem;
  font-size:.7rem;letter-spacing:.22em;text-transform:uppercase;
  color:var(--poster-rail-brown);font-weight:700;
}


/* ---------- map ---------- */
.mapsection{padding:2.6rem 0 .4rem;background:var(--ivory)}
#leafmap{
  height:62vh;min-height:340px;max-height:560px;
  margin:0 .9rem;border:3px solid var(--rail);border-radius:14px;
  box-shadow:var(--shadow);overflow:hidden;
}
#leafmap.map-fallback{
  height:auto !important;max-height:none;overflow:visible;
}
.leaflet-popup-content{font-family:'Spline Sans',sans-serif;margin:.7rem .9rem}
.map-pop b{font-family:'Fraunces',serif;font-size:1rem;color:var(--rail)}
.map-pop .pop-hook{font-size:.82rem;color:var(--muted);margin:.2rem 0 .5rem}
.map-pop button{
  background:var(--ember);color:#fff;border:none;border-radius:100px;
  padding:.4rem .9rem;font-size:.8rem;font-weight:600;cursor:pointer;
  font-family:'Spline Sans',sans-serif;
}

/* ---------- map tooltip (desktop hover) ----------
   Shown on hover only. The (hover: none) media query suppresses
   tooltips on touch devices so a tap shows the preview card,
   not a transient tooltip. */
.leaflet-tooltip.map-tip{
  background:var(--rail);color:#f3ece0;
  border:none;border-radius:6px;
  padding:.4rem .7rem;
  font-family:'Spline Sans',sans-serif;
  font-size:.85rem;font-weight:600;letter-spacing:.01em;
  box-shadow:0 3px 10px rgba(0,0,0,.28);
  white-space:nowrap;
}
.leaflet-tooltip-top.map-tip::before{border-top-color:var(--rail) !important}
.leaflet-tooltip-bottom.map-tip::before{border-bottom-color:var(--rail) !important}
.leaflet-tooltip-left.map-tip::before{border-left-color:var(--rail) !important}
.leaflet-tooltip-right.map-tip::before{border-right-color:var(--rail) !important}
@media (hover:none){
  .leaflet-tooltip.map-tip{display:none !important}
}

/* ---------- 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:18px;border-top-right-radius:18px;
  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:18px;border-top-right-radius:18px;
  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(--ember);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(--ember)}

@media (min-width:720px){
  .map-preview{
    bottom:1.5rem;
    border-radius:18px;
    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:10px;padding:.65rem .8rem;transition:border-color .15s;
}
.fallback-route li:hover{border-color:var(--ember)}
.fb-num{
  flex:0 0 28px;height:28px;border-radius:50%;
  background:var(--rail);color:#fff;border:2px solid var(--ember);
  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:100px;
  background:var(--card);color:var(--ink);
  transition:border-color 160ms ease, box-shadow 160ms ease;
}
.searchbar input:focus{
  outline:none;border-color:var(--ember);
  box-shadow:0 0 0 3px rgba(217,108,44,.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:9px}
.chip{
  flex:0 0 auto;font-family:'Spline Sans',sans-serif;font-size:.85rem;
  font-weight:600;padding:.55rem 1rem;border-radius:100px;
  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.1rem;animation:fade .22s cubic-bezier(.23,1,.32,1) both}
@keyframes fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

.stop-hero{
  position:relative;border-radius:18px;overflow:hidden;
  box-shadow:var(--shadow);margin-bottom:1.3rem;
  transition:transform .25s cubic-bezier(.2,.7,.2,1),
             box-shadow .25s ease;
}
/* Subtle hover lift on the main stop card, matching the listing
   cards. Suppressed on touch via (hover: hover). */
@media (hover:hover){
  .stop-hero:hover{
    transform:translateY(-4px);
    box-shadow:0 18px 36px rgba(20,50,38,.20);
  }
}
/* Stop card art fills a fixed-height frame at every breakpoint so
   the illustrated scenes have room to breathe instead of reading as
   a narrow strip. Mobile lands at 280px (was 240px) and desktop
   at 340px (was 320px). object-fit:cover lets the SVG slice
   gracefully if the viewport aspect differs from the source. */
.stop-hero svg,.stop-hero .stop-art svg{
  display:block;width:100%;height:280px;object-fit:cover;
}
.stop-photo{display:block;width:100%;height:280px;object-fit:cover}
@media(min-width:620px){
  .stop-hero{max-height:360px}
  .stop-hero svg,.stop-hero .stop-art svg{height:360px;object-fit:cover}
  .stop-photo{height:360px}
}
.stop-hero .label{
  position:absolute;left:0;right:0;bottom:0;
  padding:1.6rem 1.2rem 1.1rem;
  background:linear-gradient(transparent,rgba(14,59,44,.94));
  color:#f3ece0;
}
.stop-hero .ord-badge{
  position:absolute;top:.9rem;left:.9rem;z-index:2;
  background:var(--ember);color:#fff;
  width:38px;height:38px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-family:'Fraunces',serif;font-weight:900;font-size:1.05rem;
  box-shadow:0 4px 10px rgba(0,0,0,.3);
}
.stop-hero h3{font-size:1.8rem;color:#fff}
.stop-hero .region{
  font-size:.74rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gold);font-weight:700;
}
.stop-hero .hook{
  font-family:'Fraunces',serif;font-style:italic;font-weight:500;
  font-size:1.02rem;color:#e9ddc8;margin-top:.3rem;
}

.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:100px;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:100px;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:wrap;
  overflow:visible;
  padding:8px 0 .7rem;
  margin-bottom:1.1rem;
}
.catfilter button{
  flex:0 0 auto;font-family:'Spline Sans',sans-serif;font-size:.84rem;
  font-weight:600;padding:.55rem 1.05rem;border-radius:100px;cursor:pointer;
  border:2px solid var(--line);background:var(--card);color:var(--muted);
  display:flex;align-items:center;gap:.45rem;
  /* 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:100px;
  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(--ember);color:#fff;border-color:var(--ember)}
.catfilter button.active .cnt{background:rgba(255,255,255,.28);color:#fff}
.catfilter button:active{transform:scale(.97)}

/* 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:18px;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(--ember);
  }
}
/* 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;
  width:100%;aspect-ratio:16/9;overflow:hidden;background:var(--paper-2);
}
.card-img img,.card-img svg{width:100%;height:100%;object-fit:cover;display:block}
/* Fallback art always renders behind the photo. If the photo fails,
   we fade it out instead of snapping content, so the moment of
   swap is hidden. */
.card-img .img-fallback,.detail-img .img-fallback{
  position:absolute;inset:0;z-index:0;
}
.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(--rail-2);
  padding:.2rem .55rem;border-radius:5px;white-space:nowrap;
}
.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)}
.card-cta{
  display:inline-block;margin-top:.6rem;font-size:.8rem;font-weight:700;
  color:var(--ember);
}

@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}
}
.backbtn{
  font-family:'Spline Sans',sans-serif;font-size:.86rem;font-weight:700;
  background:var(--card);border:2px solid var(--rail);color:var(--rail);
  border-radius:100px;padding:.55rem 1.1rem;cursor:pointer;
  margin-bottom:1.1rem;
  transition:transform 160ms ease-out,
             background-color .2s ease, color .2s ease;
  position:sticky;top:62px;z-index:60;
  box-shadow:0 4px 14px rgba(20,50,38,.16);
}
@media (hover:hover) and (pointer:fine){
  .backbtn:hover{background:var(--rail);color:#fff}
}
.backbtn:active{transform:scale(.97)}
.detail-hero{
  border-radius:16px;overflow:hidden;box-shadow:var(--shadow);
  margin-bottom:1.1rem;
}
.detail-img{
  position:relative;
  width:100%;aspect-ratio:16/9;background:var(--paper-2);
}
.detail-img img,.detail-img svg{width:100%;height:100%;object-fit:cover;display:block}
@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(--rail-2);
  padding:.25rem .6rem;border-radius:5px;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(--ember);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}
.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:18px;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:14px;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:10px;
  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);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(--ember)}
.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(--ember);color:#fff;text-decoration:none;
  display:flex;align-items:center;justify-content:center;
  font-size:1.45rem;box-shadow:0 6px 16px rgba(217,108,44,.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)}

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

/* ==================================================================
   TORONTO UNION: WPA POSTER TREATMENT
   Stage 1 redesign preview for the first stop. Activates via the
   data-stop="union" attribute on the .stop wrapper. Other 15 stops
   keep the existing styling untouched.
   ================================================================== */

/* Stop card: thick cream poster mat around the hero image, big
   chunky serif headline, gold ordinal badge in a square plaque. */
.stop[data-stop="union"] .stop-hero{
  border:8px solid var(--poster-cream);
  border-radius:18px;
  box-shadow:0 14px 32px rgba(36,31,26,.22);
  background:var(--poster-cream);
}
.stop[data-stop="union"] .stop-hero .ord-badge{
  background:var(--poster-crimson);color:var(--poster-cream);
  border-radius:6px;width:44px;height:44px;
  border:3px solid var(--poster-cream);
  box-shadow:0 3px 0 rgba(36,31,26,.25);
  font-size:1.15rem;
}
.stop[data-stop="union"] .stop-hero .label{
  background:linear-gradient(transparent,rgba(36,31,26,.92));
  padding:2.1rem 1.3rem 1.2rem;
}
.stop[data-stop="union"] .stop-hero .region{
  color:var(--poster-gold);
  letter-spacing:.28em;font-size:.8rem;font-weight:700;
}
.stop[data-stop="union"] .stop-hero h3{
  font-size:clamp(2rem,7vw,2.6rem);
  letter-spacing:-.015em;line-height:1;margin-top:.3rem;
  color:var(--poster-cream);
  text-shadow:0 2px 0 rgba(0,0,0,.4);
}
.stop[data-stop="union"] .stop-hero .hook{
  color:var(--poster-cream);font-style:italic;font-weight:500;
  font-size:1.08rem;margin-top:.45rem;
  text-shadow:0 1px 0 rgba(0,0,0,.5);
}

/* Stop meta pills, restyled like vintage destination tags. */
.stop[data-stop="union"] .stop-meta{margin-bottom:1.25rem;margin-top:1rem}
.stop[data-stop="union"] .stop-meta .pill{
  background:var(--poster-cream);
  border:2px solid var(--poster-crimson);
  border-radius:100px;padding:.4rem .9rem;font-size:.82rem;
  color:var(--poster-ink);font-weight:600;
}
.stop[data-stop="union"] .stop-meta .pill b{color:var(--poster-crimson)}

.stop[data-stop="union"] .stop-blurb{
  font-size:1.1rem;line-height:1.7;color:var(--poster-ink);
  padding:0 .2rem;margin-bottom:1.5rem;
}

/* Share row buttons in poster tones. Pill border-radius matches
   the regular .share-row button, the stop chips and the catfilter
   buttons so every pressable on the page is fully rounded. */
.stop[data-stop="union"] .share-row button{
  border:2px solid var(--poster-crimson);
  color:var(--poster-crimson);background:var(--poster-cream);
  border-radius:100px;font-weight:700;
}
.stop[data-stop="union"] .share-row button:hover{
  background:var(--poster-crimson);color:var(--poster-cream);
}

/* Category filter as a row of poster-style chunky buttons.
   Pill border-radius matches the regular variant and the stop
   chips, so every catfilter button on the site reads as the same
   shape. */
.stop[data-stop="union"] .catfilter button{
  border:2px solid var(--poster-rail-brown);
  background:var(--poster-cream);color:var(--poster-rail-brown);
  border-radius:100px;font-weight:700;letter-spacing:.02em;
}
.stop[data-stop="union"] .catfilter button.active{
  background:var(--poster-crimson);border-color:var(--poster-crimson);
  color:var(--poster-cream);
}
@media (hover:hover){
  .stop[data-stop="union"] .catfilter button:hover{
    color:var(--poster-crimson);border-color:var(--poster-crimson);
  }
  .stop[data-stop="union"] .catfilter button.active:hover{
    color:var(--poster-cream);
  }
}
.stop[data-stop="union"] .catfilter button .cnt{
  background:var(--poster-orange);color:var(--poster-cream);
}
.stop[data-stop="union"] .catfilter button.active .cnt{
  background:rgba(243,230,200,.3);
}

/* Listing cards as small poster cards. */
.stop[data-stop="union"] .card{
  border:2px solid var(--poster-rail-brown);
  border-radius:18px;background:var(--poster-cream);
  box-shadow:0 6px 18px rgba(36,31,26,.12);
}
.stop[data-stop="union"] .card:hover{
  border-color:var(--poster-crimson);
  box-shadow:0 14px 28px rgba(36,31,26,.20);
}
.stop[data-stop="union"] .card .tag{
  background:var(--poster-crimson);border-radius:3px;
}
.stop[data-stop="union"] .card .rating{color:var(--poster-mustard)}
.stop[data-stop="union"] .card h4{
  font-size:1.22rem;color:var(--poster-ink);font-weight:700;
}
.stop[data-stop="union"] .card .desc{
  color:var(--poster-rail-brown);font-size:.94rem;line-height:1.55;
}
.stop[data-stop="union"] .card-cta{color:var(--poster-crimson);font-weight:800}

/* Detail view: poster framing for the back button, the headline,
   and the listing image block. */
.stop.detail[data-stop="union"] .backbtn{
  border:2px solid var(--poster-crimson);
  background:var(--poster-cream);color:var(--poster-crimson);
  border-radius:100px;font-weight:800;
  box-shadow:0 4px 12px rgba(36,31,26,.16);
}
.stop.detail[data-stop="union"] .backbtn:hover{
  background:var(--poster-crimson);color:var(--poster-cream);
}
.stop.detail[data-stop="union"] .detail-hero{
  border:8px solid var(--poster-cream);border-radius:18px;
  background:var(--poster-cream);
  box-shadow:0 14px 32px rgba(36,31,26,.20);
}
.stop.detail[data-stop="union"] .detail-body .tag{
  background:var(--poster-crimson);border-radius:3px;
}
.stop.detail[data-stop="union"] .detail-body h3{
  font-size:clamp(1.8rem,6vw,2.3rem);
  color:var(--poster-ink);letter-spacing:-.015em;line-height:1.05;
  margin-bottom:.4rem;
}
.stop.detail[data-stop="union"] .detail-body .rating{color:var(--poster-mustard)}
.stop.detail[data-stop="union"] .detail-loc{
  color:var(--poster-crimson);font-weight:700;font-size:.9rem;
  letter-spacing:.04em;
}
.stop.detail[data-stop="union"] .detail-desc{
  color:var(--poster-ink);font-size:1.08rem;line-height:1.7;
}
.stop.detail[data-stop="union"] .more{
  border-top:3px double var(--poster-crimson);padding-top:1.6rem;
}
.stop.detail[data-stop="union"] .more-head{
  color:var(--poster-crimson);font-size:1.25rem;letter-spacing:-.005em;
}

/* ---------- 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:100px;
  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)}
