/* Self-hosted replacements for the Google Fonts CDN request this site used to
   make on every page load. Same two families, same axes the site actually
   uses (Fraunces variable — wght/opsz/SOFT/WONK, used via
   font-variation-settings throughout site.css; Archivo static 400–700), same
   licence (SIL Open Font License 1.1 — see fonts/LICENSE-*.txt), fetched from
   the npm registry's @fontsource mirrors of the same files Google serves,
   sub­setted to Latin (covers the site's English/Irish-placename content —
   the same subset a browser would actually download from Google Fonts when
   rendering this page, since Google splits the same font into per-script
   files too). Hosting them ourselves means no request to a third-party
   domain, no render-blocking cross-origin connection, and — because these
   are now on this site's own asset path — a cache lifetime this site
   controls instead of Google's. */
@font-face{
  font-family:"Fraunces";
  font-style:normal;
  font-display:swap;
  font-weight:100 900;
  src:url(fonts/fraunces-var.woff2) format("woff2-variations");
}
@font-face{
  font-family:"Fraunces";
  font-style:italic;
  font-display:swap;
  font-weight:100 900;
  src:url(fonts/fraunces-var-italic.woff2) format("woff2-variations");
}
@font-face{
  font-family:"Archivo";
  font-style:normal;
  font-display:swap;
  font-weight:400;
  src:url(fonts/archivo-400.woff2) format("woff2");
}
@font-face{
  font-family:"Archivo";
  font-style:normal;
  font-display:swap;
  font-weight:500;
  src:url(fonts/archivo-500.woff2) format("woff2");
}
@font-face{
  font-family:"Archivo";
  font-style:normal;
  font-display:swap;
  font-weight:600;
  src:url(fonts/archivo-600.woff2) format("woff2");
}
@font-face{
  font-family:"Archivo";
  font-style:normal;
  font-display:swap;
  font-weight:700;
  src:url(fonts/archivo-700.woff2) format("woff2");
}
/* ============================================================
   HUTT BACKPACKERS — shared styles
   Granite ground · Atlantic green · peat · fire amber · oat paper
   Display: Fraunces · Body: Archivo
   ============================================================ */
:root{
  --ink:#14181A; --granite:#242A2C; --slate:#59635F; --stone:#98A09A;
  --sea-deep:#0C332F; --sea:#1B5C51; --moss:#41654A; --peat:#5A3E2B;
  --amber:#E07A2B; --amber-soft:#F0A94E; --sand:#D9C6A3;
  --paper:#EFE9DB; --paper-2:#E3DACA;
  --measure:min(1240px,92vw);
  --sec-pad:clamp(3.5rem,8vw,7rem);
  --f-display:"Fraunces","Iowan Old Style",Georgia,serif;
  --f-body:"Archivo","Helvetica Neue",Arial,sans-serif;
  /* Micro-label floor. A dozen styles used to sit between 9.3px and 10.2px —
     uppercase and heavily letter-spaced, which makes small text harder again.
     One token holds them all at 11.2px and up. */
  --label:clamp(.7rem,.67rem + .14vw,.78rem);
  --step--1:clamp(.78rem,.76rem + .12vw,.86rem);
  --step-0:clamp(1rem,.97rem + .18vw,1.06rem);
  --step-1:clamp(1.14rem,1.08rem + .4vw,1.34rem);
  --step-2:clamp(1.45rem,1.3rem + .9vw,2rem);
  --step-3:clamp(1.9rem,1.55rem + 1.8vw,2.9rem);
  --step-4:clamp(2.5rem,1.8rem + 3.2vw,4.4rem);
  --step-5:clamp(3.2rem,2rem + 6vw,7rem);
  --edge:1px solid color-mix(in srgb,var(--stone) 32%,transparent);
}
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--ink);color:var(--paper);font-family:var(--f-body);
  font-size:var(--step-0);line-height:1.6;overflow-x:hidden;font-synthesis-weight:none}
body::after{content:"";position:fixed;inset:0;pointer-events:none;z-index:60;opacity:.055;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>")}
img{max-width:100%;display:block}
a{color:inherit}
h1,h2,h3,h4{font-family:var(--f-display);font-weight:600;line-height:1.03;margin:0;
  font-variation-settings:"SOFT" 22,"WONK" 1,"opsz" 100}
p{margin:0 0 1em}
::selection{background:var(--amber);color:var(--ink)}
/* Focus ring. Amber-soft is only ~1.5:1 on oat paper, so the outline colour
   follows the ground it lands on: peat (8:1 on paper) wherever the surface is
   light, amber wherever the surface stays dark in both modes. */
:focus-visible{outline:3px solid var(--amber-soft);outline-offset:3px;border-radius:2px}
.sec--paper :focus-visible,.card-index :focus-visible,.listview :focus-visible{outline-color:var(--peat)}
html[data-theme="day"] :focus-visible{outline-color:var(--peat)}
html[data-theme="day"] .hero :focus-visible,
html[data-theme="day"] .phead :focus-visible,
html[data-theme="day"] .sec--sea :focus-visible,
html[data-theme="day"] .board :focus-visible,
html[data-theme="day"] .menu :focus-visible,
html[data-theme="day"] .nav:not(.is-stuck) :focus-visible{outline-color:var(--amber-soft)}

/* Section headings that keep the document outline honest without adding
   visible chrome — see the h1→h3 skips fixed in the page bodies. */
.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}

.wrap{width:var(--measure);margin-inline:auto}
.eyebrow{font-size:var(--step--1);font-weight:600;letter-spacing:.22em;text-transform:uppercase;
  color:var(--amber-soft);display:flex;align-items:center;gap:.7em;margin:0 0 1rem}
.eyebrow::before{content:"";width:clamp(18px,4vw,48px);height:1px;background:currentColor;opacity:.65;flex:none}
.lede{font-size:var(--step-1);color:color-mix(in srgb,var(--paper) 80%,transparent);max-width:50ch}
.small{font-size:var(--step--1);color:var(--stone)}
.skip{position:absolute;left:-9999px;top:0;z-index:100;background:var(--amber);color:var(--ink);padding:.8rem 1.2rem;font-weight:700}
.skip:focus{left:1rem;top:1rem}

/* buttons */
.btn{--bg:var(--amber);--fg:var(--ink);display:inline-flex;align-items:center;gap:.6em;justify-content:center;
  background:var(--bg);color:var(--fg);text-decoration:none;font-weight:700;font-size:var(--step--1);
  letter-spacing:.13em;text-transform:uppercase;padding:1em 1.6em;border:0;cursor:pointer;border-radius:2px;
  font-family:var(--f-body);transition:transform .22s cubic-bezier(.2,.7,.3,1),background .22s,color .22s}
.btn:hover{transform:translateY(-2px);--bg:var(--amber-soft)}
.btn--ghost{--bg:transparent;--fg:var(--paper);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--paper) 45%,transparent)}
.btn--ghost:hover{--bg:color-mix(in srgb,var(--paper) 12%,transparent);--fg:var(--paper)}
.btn--sm{padding:.7em 1.05em;letter-spacing:.1em}
.btn:disabled{cursor:not-allowed;opacity:.55}
.btn:disabled:hover{transform:none;--bg:var(--amber)}

/* photo placeholders */
.photo{position:relative;margin:0;overflow:hidden;border-radius:3px;isolation:isolate;background:var(--granite);min-height:150px}
/* A real photo dropped into a .photo figure: fills the box exactly like the
   placeholder gradient it replaces. The generated ::before/::after below
   still paint (texture behind, highlight screen-blend on top) regardless of
   where this sits in the markup, so a real photo gets the same subtle sheen
   a placeholder does — see PROJECT-BRIEF.md §9 entry 51 for why that's free. */
.photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.photo::before{content:"";position:absolute;inset:0;
  background:repeating-linear-gradient(115deg,rgba(255,255,255,.045) 0 2px,transparent 2px 9px),var(--ph,linear-gradient(160deg,#20323a,#0f1a1e))}
.photo::after{content:"";position:absolute;inset:0;background:radial-gradient(120% 90% at 20% 10%,rgba(255,255,255,.16),transparent 60%);mix-blend-mode:screen}
.photo__tag{position:absolute;left:0;bottom:0;z-index:2;max-width:min(100%,40ch);
  font-size:clamp(.7rem,1.5vw,.78rem);font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--paper);background:color-mix(in srgb,var(--ink) 74%,transparent);backdrop-filter:blur(4px);padding:.5em .85em;line-height:1.35}
.ph-sea{--ph:linear-gradient(170deg,#8fb3bb,#3f6b74 38%,#1b3a41 78%,#101d21)}
.ph-gold{--ph:linear-gradient(165deg,#f0b767,#c67a35 32%,#5c4a34 70%,#1c1f1d)}
.ph-mountain{--ph:linear-gradient(170deg,#7d8f86,#41564c 40%,#1e2c28 80%,#101614)}
.ph-forest{--ph:linear-gradient(165deg,#5c7a52,#2f4a34 45%,#16241b)}
.ph-fire{--ph:linear-gradient(170deg,#e08a3a,#8a4a22 40%,#2a1c14 85%)}
.ph-wood{--ph:linear-gradient(160deg,#b08a5c,#6b4a2f 45%,#241a12)}
.ph-dune{--ph:linear-gradient(165deg,#e0cfa6,#a89468 40%,#4c4a34 80%,#1d1f19)}
.ph-town{--ph:linear-gradient(170deg,#9aa7ad,#4f5c63 40%,#20272b 85%)}
.ph-granite{--ph:linear-gradient(165deg,#98a09a,#4a534f 45%,#1a1f1d)}
.ph-mural{--ph:linear-gradient(160deg,#e8c168,#5a9270 40%,#1e4a3c 78%,#101f1a)}

/* nav */
.nav{position:fixed;inset:0 0 auto 0;z-index:50;display:flex;align-items:center;gap:1.2rem;
  padding:clamp(.6rem,1.5vw,1rem) clamp(1rem,4vw,2.4rem);transition:background .4s,backdrop-filter .4s,box-shadow .4s;
  /* A real background-colour, not just the dark hero/phead photo showing
     through: the nav's own contrast has to hold regardless of what image or
     gradient happens to be underneath (a short viewport, a future page with
     no photo band), not just in the cases that were eyeballed. Same idea as
     .phead::after's scrim below, applied directly to the element the text
     actually sits on so it's guaranteed rather than incidental. */
  background:color-mix(in srgb,var(--ink) 90%,transparent)}
.nav.is-stuck{background:color-mix(in srgb,var(--ink) 90%,transparent);backdrop-filter:blur(10px) saturate(1.2);
  box-shadow:0 1px 0 color-mix(in srgb,var(--stone) 25%,transparent)}
/* Pinned, not inherited: the nav sits over the hero and page-header photo
   bands, which stay dark in day view. Everything else in the bar already
   pins its own colour; the wordmark used to inherit from body and went
   ink-on-dark the moment day view was switched on. */
.brand{display:flex;align-items:center;gap:.7rem;text-decoration:none;margin-right:auto;color:var(--paper)}
.brand__mark{width:32px;height:32px;flex:none;color:var(--amber)}
.brand__name{font-family:var(--f-display);font-weight:700;font-size:1.1rem;line-height:1}
.brand__sub{display:block;font-family:var(--f-body);font-size:var(--label);letter-spacing:.24em;text-transform:uppercase;color:var(--stone);margin-top:.25em}
.nav__links{display:flex;align-items:center;gap:clamp(.9rem,2vw,1.8rem);list-style:none;margin:0;padding:0}
.nav__links a{text-decoration:none;font-size:var(--step--1);font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;padding:.4em 0;position:relative;color:color-mix(in srgb,var(--paper) 88%,transparent)}
.nav__links a::after{content:"";position:absolute;left:0;right:100%;bottom:0;height:1px;background:var(--amber);transition:right .3s}
.nav__links a:hover::after,.nav__links a[aria-current="page"]::after{right:0}
.nav__links a[aria-current="page"]{color:var(--amber-soft)}
.nav .btn{padding:.8em 1.2em}

/* preference toggles (day/night, animation on/off) — icon-only, no text label */
.prefs{display:flex;align-items:center;gap:.3rem}
.prefs__btn{display:inline-flex;align-items:center;justify-content:center;width:2.3rem;height:2.3rem;flex:none;
  background:none;border:0;border-radius:50%;color:var(--paper);cursor:pointer;padding:0;transition:background .2s,color .2s}
.prefs__btn:hover{background:color-mix(in srgb,var(--paper) 12%,transparent)}
.prefs__btn svg{width:19px;height:19px;flex:none}
.prefs__btn .i-moon,.prefs__btn .i-play{display:none}
html[data-theme="day"] #themeToggle .i-sun{display:none}
html[data-theme="day"] #themeToggle .i-moon{display:block}
html[data-motion="off"] #motionToggle .i-pause{display:none}
html[data-motion="off"] #motionToggle .i-play{display:block}
.nav__toggle{display:none}
@media(max-width:940px){
  .nav__links,.nav>.btn{display:none}
  .nav__toggle{display:inline-flex;align-items:center;gap:.55em;background:none;border:0;color:var(--paper);
    font-family:var(--f-body);font-size:var(--step--1);font-weight:700;letter-spacing:.16em;text-transform:uppercase;cursor:pointer;padding:.5em .2em}
  .nav__toggle span{display:block;width:22px;height:9px;border-top:2px solid currentColor;border-bottom:2px solid currentColor}
  .menu{position:fixed;inset:0;z-index:55;background:var(--sea-deep);display:grid;align-content:center;gap:.3rem;
    padding:2rem;transform:translateY(-100%);transition:transform .45s cubic-bezier(.65,0,.2,1)}
  .menu.is-open{transform:none}
  .menu a{font-family:var(--f-display);font-size:var(--step-3);text-decoration:none;color:var(--paper);
    border-bottom:1px solid color-mix(in srgb,var(--stone) 30%,transparent);padding:.3em 0}
  .menu .btn{margin-top:1.2rem;justify-self:start}
  .menu__close{position:absolute;top:1.2rem;right:1.2rem;background:none;border:0;color:var(--paper);font-size:2rem;cursor:pointer;line-height:1}
}
@media(min-width:941px){.menu{display:none}}
.menu[hidden]{display:none}

/* reveal */
.reveal{opacity:0;transform:translateY(22px);transition:opacity .8s cubic-bezier(.2,.7,.3,1),transform .8s cubic-bezier(.2,.7,.3,1)}
.reveal.is-in{opacity:1;transform:none}

/* page header (inner pages) */
.phead{position:relative;padding:clamp(7rem,16vh,11rem) 0 clamp(2.5rem,6vw,4.5rem);overflow:hidden;color:var(--paper)}
/* A real photo dropped into a .phead: fills the band exactly like the
   placeholder gradient it replaces. ::before/::after still paint (gradient
   backdrop behind, darkening legibility overlay in front) regardless of
   where this sits in the markup — same free bracketing behaviour as the
   hero/.photo real-image treatments, see PROJECT-BRIEF.md §9 entry 51. */
.phead__photo{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.phead::before{content:"";position:absolute;inset:0;background:var(--ph,linear-gradient(150deg,#22322f,#101614));opacity:.9}
.phead::after{content:"";position:absolute;inset:0;background:linear-gradient(to top,var(--ink),color-mix(in srgb,var(--ink) 55%,transparent) 55%,transparent)}
.phead .wrap{position:relative;z-index:2}
.phead h1{font-size:var(--step-4);letter-spacing:-.02em;max-width:16ch;text-wrap:balance;
  font-variation-settings:"SOFT" 30,"WONK" 1,"opsz" 144}
.phead p{margin-top:1rem;max-width:46ch;font-size:var(--step-1);color:color-mix(in srgb,var(--paper) 84%,transparent)}
/* Clear of the fixed header and inset from the edge — at right:0 these ran
   under the "Check availability" button and off the right of the viewport. */
.phead .photo__tag{top:clamp(5.4rem,11vh,7.2rem);bottom:auto;left:auto;
  right:clamp(.6rem,2.5vw,1.4rem);text-align:right;max-width:min(calc(100vw - 2rem),34ch)}
/* Every phead's caption sits above the ridge band (z-index:2) at its foot —
   was a one-off inline style repeated identically on every phead page. */
.phead > .photo__tag{z-index:3}

/* hero */
.hero{position:relative;min-height:100svh;display:flex;flex-direction:column;justify-content:flex-end;overflow:hidden;color:var(--paper)}
.hero__stage{position:absolute;inset:0;z-index:0}
/* The slow zoom lives on the image layer, not on the plate itself. When the
   plate was the thing being scaled, everything positioned inside it was scaled
   and offset too — which dragged the caption up under the fixed header and out
   past the right edge of the viewport. The frame, the vignette and the caption
   now stay put while the photograph drifts behind them. */
.hero__plate{position:absolute;inset:0;opacity:0;transition:opacity 1.6s ease}
.hero__plate.is-live{opacity:1}
.hero__plate::before{content:"";position:absolute;inset:0;background:var(--ph);
  transform:scale(1.06);transition:transform 8s linear}
.hero__plate.is-live::before{transform:scale(1.13)}
.hero__plate::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,var(--ink) 2%,color-mix(in srgb,var(--ink) 62%,transparent) 38%,transparent 72%),
  linear-gradient(to right,color-mix(in srgb,var(--ink) 72%,transparent),transparent 55%)}
.hero__plate .photo__tag{top:clamp(5.4rem,11vh,7.2rem);bottom:auto;left:auto;
  right:clamp(.6rem,2.5vw,1.4rem);text-align:right;max-width:min(calc(100vw - 2rem),34ch)}
/* A real photo plate: same slow-zoom treatment as the ::before gradient
   layer above (same duration/curve so a rotation between a real photo and a
   still-placeholder plate doesn't visibly change pace), sitting between the
   generated ::before (behind) and ::after (the legibility gradient, still on
   top) in paint order for free, since ::before/::after bracket real children
   regardless of where they sit in the markup. */
.hero__plate .hero__photo{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transform:scale(1.06);transition:transform 8s linear}
.hero__plate.is-live .hero__photo{transform:scale(1.13)}
.hero__grid{position:absolute;inset:0;z-index:1;pointer-events:none;
  background-image:linear-gradient(to right,color-mix(in srgb,var(--paper) 8%,transparent) 1px,transparent 1px);background-size:calc(100% / 6) 100%}
.hero__inner{position:relative;z-index:2;width:var(--measure);margin-inline:auto;padding:clamp(6rem,14vh,10rem) 0 clamp(1.4rem,4vh,2.6rem)}
.hero h1{font-size:var(--step-5);letter-spacing:-.022em;max-width:15ch;text-wrap:balance;
  font-variation-settings:"SOFT" 30,"WONK" 1,"opsz" 144}
.hero h1 em{font-style:italic;color:var(--amber-soft);font-variation-settings:"SOFT" 60,"WONK" 1,"opsz" 144}
.hero__sub{max-width:34ch;margin-top:1.2rem;font-size:var(--step-1);color:color-mix(in srgb,var(--paper) 88%,transparent)}
.hero__cta{display:flex;flex-wrap:wrap;gap:.7rem;margin-top:1.8rem;opacity:0;transform:translateY(14px);transition:opacity .8s .5s,transform .8s .5s}
.hero.is-ready .hero__cta{opacity:1;transform:none}
.hero__foot{position:relative;z-index:2;width:var(--measure);margin:0 auto;display:flex;flex-wrap:wrap;
  gap:1rem 2rem;align-items:center;justify-content:space-between;border-top:var(--edge);padding:.9rem 0 1.2rem}
.chips{display:flex;flex-wrap:wrap;gap:.8rem}
.chip{display:inline-flex;align-items:center;gap:.7rem;border:1px dashed color-mix(in srgb,var(--sand) 55%,transparent);
  padding:.55rem .85rem;border-radius:2px;background:color-mix(in srgb,var(--ink) 45%,transparent);font-size:var(--step--1);line-height:1.3}
.chip b{font-family:var(--f-display);font-size:1.1rem;display:block;font-weight:600}
.chip__label{color:var(--stone);letter-spacing:.16em;text-transform:uppercase;font-size:var(--label);font-weight:600}
/* A verdict is a sentence, not a stat — same chip shell, lighter type so it
   doesn't try to display-font its way across the hero at 1.1rem. */
.chip--verdict{max-width:23rem}
.chip--verdict b{font-family:inherit;font-size:var(--step--1);font-weight:500;line-height:1.4}
.hero__scroll{display:flex;align-items:center;gap:.7rem;color:var(--stone);font-size:var(--label);letter-spacing:.24em;text-transform:uppercase;font-weight:600;margin:0}
.hero__scroll i{display:block;width:1px;height:30px;background:linear-gradient(var(--amber),transparent);animation:drip 2.4s infinite}
@keyframes drip{0%{transform:scaleY(.2);transform-origin:top}50%{transform:scaleY(1);transform-origin:top}51%{transform-origin:bottom}100%{transform:scaleY(.2);transform-origin:bottom}}
@media(max-width:700px){.hero__grid{background-size:calc(100% / 3) 100%}}

/* ticker */
.strip{background:var(--amber);color:var(--ink);overflow:hidden;border-block:1px solid rgba(0,0,0,.2)}
.strip__row{display:flex;width:max-content;animation:slide 46s linear infinite}
.strip:hover .strip__row{animation-play-state:paused}
.strip span{padding:.7rem 1.5rem;font-size:var(--step--1);font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;white-space:nowrap;display:flex;align-items:center;gap:1.5rem}
.strip span::after{content:"";width:5px;height:5px;background:currentColor;transform:rotate(45deg)}
@keyframes slide{to{transform:translateX(-50%)}}

/* sections */
/* Sections that set a fixed dark ground must also pin a fixed text colour.
   Day view flips body's colour to ink, and anything relying on inheritance
   goes dark-on-dark — the same trap .hero and .phead already had to escape. */
.sec{padding-block:var(--sec-pad);position:relative}
.sec--sea{background:var(--sea-deep);color:var(--paper)}
.sec--granite{background:var(--granite);color:var(--paper)}
.sec--paper{background:var(--paper);color:var(--ink)}
.sec--paper .lede{color:color-mix(in srgb,var(--ink) 74%,transparent)}
.sec--paper .eyebrow{color:var(--peat)}
.sec--paper .small{color:var(--slate)}
.sec__head{display:grid;gap:1rem;margin-bottom:clamp(1.6rem,4vw,3rem)}
.sec__head h2{font-size:var(--step-3);letter-spacing:-.02em;max-width:18ch;text-wrap:balance}
@media(min-width:900px){.sec__head{grid-template-columns:1.1fr .9fr;align-items:end;gap:2.5rem}}
section[id],form[id]{scroll-margin-top:5.5rem}

/* cards / grids */
.grid{display:grid;gap:clamp(.7rem,1.8vw,1.2rem);grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr))}
.tile{background:color-mix(in srgb,var(--paper) 6%,transparent);border:var(--edge);padding:clamp(1rem,2.2vw,1.4rem);
  border-radius:3px;display:flex;flex-direction:column;gap:.5rem}
.sec--paper .tile{background:color-mix(in srgb,#fff 45%,transparent);border-color:color-mix(in srgb,var(--slate) 28%,transparent)}
.tile h3{font-size:var(--step-1)}
.tile p{margin:0;font-size:var(--step--1);color:color-mix(in srgb,currentColor 78%,transparent)}
.tile__num{font-size:var(--label);letter-spacing:.18em;text-transform:uppercase;font-weight:700;color:var(--amber-soft)}
.sec--paper .tile__num{color:var(--peat)}

/* Testimonials (basecamp.html, PROJECT-BRIEF §9 entry 44) — real guest
   reviews, reproduced as given, not paraphrased. Built on .tile (its
   background/border are already correct in both themes) rather than a new
   card type — the amber/stone/currentColor choices below deliberately
   mirror .tile__num and .small, including their day-theme swaps further
   down this file, so no new theme logic was needed to get this right. */
.quote{margin:0}
.quote__mark{font-family:var(--f-display);font-size:clamp(2.2rem,5vw,3rem);line-height:.5;
  color:var(--amber-soft);margin:0}
.quote blockquote{margin:0}
.quote blockquote p{font-family:var(--f-display);font-weight:500;font-size:var(--step-0);
  line-height:1.5;color:currentColor;margin:0}
.quote figcaption{font-size:var(--step--1);font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--stone)}
.quote__stay{font-weight:400;letter-spacing:0;text-transform:none;
  color:color-mix(in srgb,currentColor 65%,transparent)}
/* A desk-typed closure notice sitting inside an otherwise self-writing tile,
   marked off so it reads as someone's word rather than the machine's. Only
   ever used inside .sec--sea, which day view deliberately leaves dark, so this
   needs no light-theme counterpart — see the fixed-dark rule in the brief. */
.desknote{margin:0;padding-left:.7rem;border-left:2px solid var(--amber);font-size:var(--step--1)}
.linkcard{text-decoration:none;position:relative;overflow:hidden;border-radius:3px;min-height:clamp(280px,40vw,360px);
  display:flex;flex-direction:column;justify-content:flex-end;padding:clamp(1rem,2.4vw,1.6rem);color:var(--paper)}
.linkcard .photo{position:absolute;inset:0;border-radius:0}
.linkcard .photo__tag{top:0;bottom:auto}
.linkcard::after{content:"";position:absolute;inset:0;z-index:2;background:linear-gradient(to top,rgba(10,14,13,.94),rgba(10,14,13,.2) 62%,transparent)}
.linkcard>div{position:relative;z-index:3}
.linkcard h3{font-size:var(--step-2);margin-bottom:.4rem}
.linkcard p{margin:0;font-size:var(--step--1);color:color-mix(in srgb,var(--paper) 86%,transparent)}
.linkcard .go{display:inline-block;margin-top:.8rem;font-size:var(--label);font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--amber-soft)}
.linkcard:hover .go{color:var(--paper)}

/* condensed day timeline */
.beats{display:grid;gap:0;border-top:var(--edge)}
.beat{display:grid;gap:.3rem 1.6rem;grid-template-columns:auto 1fr;padding:1rem 0;border-bottom:var(--edge);align-items:baseline}
.beat time{font-family:var(--f-display);font-size:var(--step-2);color:var(--amber);line-height:1;
  font-variation-settings:"WONK" 1,"SOFT" 40,"opsz" 144;min-width:4.5rem}
.beat h3{font-size:var(--step-1);margin-bottom:.2rem}
.beat p{margin:0;font-size:var(--step--1);color:color-mix(in srgb,var(--paper) 76%,transparent);max-width:56ch}
.sec--paper .beat p{color:color-mix(in srgb,var(--ink) 74%,transparent)}
.sec--paper .beat time{color:var(--peat)}   /* amber is 2.5:1 on paper; peat is the paper-section accent */

/* facts row */
.facts{display:grid;gap:1px;background:color-mix(in srgb,var(--stone) 25%,transparent);border:var(--edge);border-radius:3px;overflow:hidden;
  grid-template-columns:repeat(2,1fr)}
@media(min-width:800px){.facts{grid-template-columns:repeat(4,1fr)}}
.fact{background:var(--ink);padding:clamp(1rem,2.4vw,1.5rem)}
.sec--paper .fact{background:var(--paper)}
.fact b{display:block;font-family:var(--f-display);font-size:var(--step-2);line-height:1;font-variation-settings:"WONK" 1,"SOFT" 30,"opsz" 144}
.fact span{font-size:var(--label);letter-spacing:.16em;text-transform:uppercase;color:var(--stone);display:block;margin-top:.45rem}
.sec--paper .fact span{color:var(--slate)}

/* forms */
.form{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(min(100%,230px),1fr))}
.field{display:flex;flex-direction:column;gap:.4rem}
.field--full{grid-column:1/-1}
label{font-size:var(--label);font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--stone)}
input,select,textarea{font-family:var(--f-body);font-size:var(--step-0);color:var(--paper);
  background:color-mix(in srgb,var(--paper) 8%,transparent);border:1px solid color-mix(in srgb,var(--stone) 40%,transparent);
  border-radius:2px;padding:.8em .9em;width:100%}
input:hover,select:hover,textarea:hover{border-color:color-mix(in srgb,var(--sand) 60%,transparent)}
textarea{min-height:120px;resize:vertical}
select option{background:var(--granite);color:var(--paper)}
input[type="date"]::-webkit-calendar-picker-indicator{filter:invert(1);opacity:.6;cursor:pointer}
.form__note{grid-column:1/-1;font-size:var(--step--1);color:var(--stone)}
.form__status{grid-column:1/-1;background:color-mix(in srgb,var(--amber) 14%,transparent);border-left:3px solid var(--amber);padding:1rem;font-size:var(--step--1)}
.form__status a{text-decoration:underline;text-decoration-color:var(--amber);text-underline-offset:3px}
.form__status--ok{background:color-mix(in srgb,var(--sea) 18%,transparent);border-left-color:var(--sea)}
html[data-theme="day"] .form__status--ok{background:color-mix(in srgb,var(--sea) 12%,transparent)}
/* spam trap — off-screen, not display:none, so bots still find and fill it */
.hp{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden}
input[aria-invalid="true"],select[aria-invalid="true"],textarea[aria-invalid="true"]{border-color:var(--amber);border-width:2px}
.form__status[hidden]{display:none}

/* footer */
.footer{background:var(--ink);padding-block:clamp(2.5rem,6vw,4.5rem) 1.6rem;border-top:1px solid color-mix(in srgb,var(--stone) 25%,transparent)}
.footer__grid{display:grid;gap:2rem;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr))}
.footer h2{font-size:var(--label);letter-spacing:.18em;text-transform:uppercase;color:var(--amber-soft);font-family:var(--f-body);font-weight:700;margin-bottom:.8rem}
.footer ul{list-style:none;margin:0;padding:0;font-size:var(--step--1)}
.footer li{margin-bottom:.45rem}
.footer a{text-decoration:none;color:color-mix(in srgb,var(--paper) 80%,transparent)}
.footer a:hover{color:var(--amber-soft)}
/* legal pages don't exist yet — these are labels, not links, so they aren't
   focusable and don't promise a destination they can't reach */
.footer__pending{color:color-mix(in srgb,var(--paper) 55%,transparent)}
.footer__social{display:flex;gap:.55rem;margin-top:1rem}
.footer__social li{margin-bottom:0}
.footer__social a{display:inline-flex;align-items:center;justify-content:center;width:2.15rem;height:2.15rem;
  border:1px solid color-mix(in srgb,currentColor 35%,transparent);border-radius:999px;transition:border-color .2s,background-color .2s}
.footer__social a:hover{background:color-mix(in srgb,currentColor 14%,transparent);border-color:currentColor}
.footer__social svg{width:16px;height:16px;flex:none}
/* --stone, not --slate: this sits on --ink by default (night is the
   default theme, no data-theme attribute set), where slate only reaches
   2.87:1 — a real WCAG AA failure caught by check-a11y.js. --slate comes
   back for day view below, where it already had 5.1:1 and stone would
   drop to 2.2:1 the same way. */
.footer__bar{display:flex;flex-wrap:wrap;gap:.6rem 1.6rem;justify-content:space-between;margin-top:clamp(1.6rem,4vw,2.6rem);
  padding-top:1.1rem;border-top:var(--edge);font-size:var(--label);letter-spacing:.1em;color:var(--stone)}
.footer__word{font-family:var(--f-display);font-size:clamp(2.2rem,13vw,9rem);line-height:.85;letter-spacing:-.03em;
  color:color-mix(in srgb,var(--paper) 9%,transparent);margin-top:1.6rem;user-select:none}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;scroll-behavior:auto !important}
  .reveal{opacity:1;transform:none}
  .hero__plate::before{transform:none}
  .hero__cta{opacity:1;transform:none}
}
/* same reset, driven by the manual "animation on/off" toggle rather than the OS setting */
html[data-motion="off"] *,html[data-motion="off"] *::before,html[data-motion="off"] *::after{
  animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;scroll-behavior:auto !important}
html[data-motion="off"] .reveal{opacity:1;transform:none}
html[data-motion="off"] .hero__plate::before{transform:none}
html[data-motion="off"] .hero__cta{opacity:1;transform:none}

/* ===== Day view =====
   Flips page chrome and plain content sections to a light ground.
   The hero/phead photo bands, the basecamp map board and the mobile
   fullscreen menu keep their fixed dark, image-legible treatment in
   both modes — they're art-directed like photography, not flat page
   chrome, and the map is explicitly a "noticeboard", not page background. */
html[data-theme="day"] body{background:var(--paper);color:var(--ink)}
/* Fully opaque, not 92%: at 92% whatever's scrolled directly underneath
   bleeds through just enough, on some pages, to pull .brand__sub's slate
   text below 4.5:1 — the same "guarantee it, don't rely on what happens to
   be behind it" fix as the unstuck nav's background above. */
html[data-theme="day"] .nav.is-stuck{background:var(--paper)}
html[data-theme="day"] .nav.is-stuck .brand__sub{color:var(--slate)}
html[data-theme="day"] .nav.is-stuck .nav__links a{color:color-mix(in srgb,var(--ink) 82%,transparent)}
html[data-theme="day"] .nav.is-stuck .nav__links a[aria-current="page"]{color:var(--peat)}
html[data-theme="day"] .nav.is-stuck .nav__toggle{color:var(--ink)}
html[data-theme="day"] .nav.is-stuck .prefs__btn{color:var(--ink)}
html[data-theme="day"] .nav.is-stuck .prefs__btn:hover{background:color-mix(in srgb,var(--ink) 10%,transparent)}
html[data-theme="day"] .footer{background:var(--paper);border-top-color:color-mix(in srgb,var(--slate) 30%,transparent)}
html[data-theme="day"] .footer a{color:color-mix(in srgb,var(--ink) 78%,transparent)}
html[data-theme="day"] .footer__bar{color:var(--slate)}
html[data-theme="day"] .footer__word{color:color-mix(in srgb,var(--ink) 8%,transparent)}
html[data-theme="day"] .footer__pending{color:var(--slate)}
/* Amber-soft is 1.65:1 and amber 2.5:1 against oat paper. Wherever day view
   turns the ground to paper, the accent switches to peat — the same swap
   .sec--paper already makes in both modes. */
html[data-theme="day"] .footer h2,
html[data-theme="day"] .footer a:hover,
html[data-theme="day"] .nav.is-stuck .brand__mark,
html[data-theme="day"] .sec:not(.sec--paper):not(.sec--sea) .eyebrow,
html[data-theme="day"] .sec:not(.sec--paper):not(.sec--sea) .tile__num,
html[data-theme="day"] .sec:not(.sec--paper):not(.sec--sea) .beat time,
html[data-theme="day"] .sec:not(.sec--paper):not(.sec--sea) .quote__mark{color:var(--peat)}
html[data-theme="day"] .nav.is-stuck .brand{color:var(--ink)}
html[data-theme="day"] .sec:not(.sec--paper):not(.sec--sea) .tile{
  background:color-mix(in srgb,var(--ink) 6%,transparent);border-color:color-mix(in srgb,var(--slate) 30%,transparent)}
html[data-theme="day"] .sec:not(.sec--paper):not(.sec--sea) .fact{background:var(--paper)}
html[data-theme="day"] .sec:not(.sec--paper):not(.sec--sea) .fact span{color:var(--slate)}
html[data-theme="day"] .sec:not(.sec--paper):not(.sec--sea) .small,
html[data-theme="day"] .sec:not(.sec--paper):not(.sec--sea) .quote figcaption{color:var(--slate)}
html[data-theme="day"] .facts{background:color-mix(in srgb,var(--slate) 20%,transparent)}
html[data-theme="day"] label,html[data-theme="day"] .form__note,html[data-theme="day"] .detail dt{color:var(--slate)}
html[data-theme="day"] input,html[data-theme="day"] select,html[data-theme="day"] textarea{
  color:var(--ink);background:color-mix(in srgb,var(--ink) 6%,transparent)}
html[data-theme="day"] select option{background:var(--paper);color:var(--ink)}
html[data-theme="day"] input[type="date"]::-webkit-calendar-picker-indicator{filter:none}

/* ===== legal / long-form prose =====
   The site had no running-text style — everything was cards, tiles and short
   blocks. These pages are the first that need to be read straight through. */
.prose{max-width:68ch}
.prose h2{font-size:var(--step-2);letter-spacing:-.015em;margin:clamp(2rem,4vw,2.8rem) 0 .8rem;max-width:26ch}
.prose h3{font-size:var(--step-1);margin:1.6rem 0 .5rem}
.prose p,.prose li{color:color-mix(in srgb,var(--paper) 84%,transparent)}
.sec--paper .prose p,.sec--paper .prose li,
html[data-theme="day"] .sec:not(.sec--sea) .prose p,
html[data-theme="day"] .sec:not(.sec--sea) .prose li{color:color-mix(in srgb,var(--ink) 82%,transparent)}
.prose ul,.prose ol{padding-left:1.2em;margin:0 0 1em}
.prose li{margin-bottom:.45em}
.prose a{text-decoration:underline;text-decoration-color:var(--amber);text-underline-offset:3px}
.prose dl{margin:0 0 1.4rem}
.prose__updated{font-size:var(--label);letter-spacing:.14em;text-transform:uppercase;color:var(--stone);
  font-weight:700;margin-bottom:1.6rem}
/* Marks text the hostel still has to supply. Same convention as the photo
   placeholders: never let unfinished content look finished. */
.todo{background:color-mix(in srgb,var(--amber) 22%,transparent);
  box-shadow:0 0 0 1px color-mix(in srgb,var(--amber) 55%,transparent);
  padding:.1em .4em;border-radius:2px;font-weight:600;color:var(--paper)}
html[data-theme="day"] .todo,.sec--paper .todo{color:var(--ink)}
.draft{border:1px solid color-mix(in srgb,var(--amber) 55%,transparent);
  border-left:3px solid var(--amber);background:color-mix(in srgb,var(--amber) 12%,transparent);
  padding:1rem 1.2rem;margin-bottom:1.8rem;max-width:68ch}
.draft b{color:var(--amber-soft)}
html[data-theme="day"] .draft b,.sec--paper .draft b{color:var(--peat)}

/* contact */
.contact-grid{display:grid;gap:clamp(1.6rem,4vw,3rem)}
.contact-grid dl{margin:0}
@media(min-width:960px){.contact-grid{grid-template-columns:1.1fr .9fr}}
.detail{border-top:var(--edge);padding:.9rem 0;display:grid;grid-template-columns:auto 1fr;gap:1.2rem;align-items:baseline}
.detail dt{font-size:var(--label);letter-spacing:.16em;text-transform:uppercase;color:var(--stone);font-weight:700}
.detail dd{margin:0;font-size:var(--step--1)}
.detail a{text-decoration-color:var(--amber);text-underline-offset:4px}

/* ===== The Donard Line ===== */
.ridge-band{position:relative;width:100%;line-height:0;pointer-events:none}
.ridge-band svg{display:block;width:100%;height:auto}
/* Plain HTML, not SVG text — positioned by percentage over the ridge-band
   box in ridge.js (which sizes exactly to the svg — see .ridge-band above),
   so font-size here is a real, constant CSS size at every viewport width
   rather than something that shrinks with the graphic on a narrow phone. */
/* User-reported 2026-08-24: "the sun and moon must layer behind the text
   that shows on the ridge on the index page." The DOM/paint order was
   already label-over-marker (confirmed by forcing an exact pixel overlap
   and letting every opacity transition fully settle before checking, not
   trusting a screenshot taken mid-fade) — the label's translucent colour
   (70% paper, so it deliberately reads as soft against the dark ridge) is
   what actually broke down: blended with the sun/moon's own solid, fully
   saturated fill passing directly behind a letter, the result reads as a
   muddy smear rather than a legible letter sitting "in front" of anything,
   which is exactly what a plain reading of "layer behind the text" would
   flag. A text-shadow — a soft dark halo matching the ridge's own --ink,
   not a colour or opacity change — fixes the legibility without touching
   the deliberately soft look against the plain ridge background: the
   shadow is inert wherever the label already sits on dark ridge, and only
   does real work at the moment something bright passes underneath. */
.ridge-label{position:absolute;transform:translate(-50%,-100%);white-space:nowrap;
  font-family:var(--f-body);font-size:var(--label);letter-spacing:2.4px;text-transform:uppercase;
  color:color-mix(in srgb,var(--paper) 70%,transparent);opacity:0;transition:opacity 1s;
  -webkit-text-stroke:1.5px var(--ink);paint-order:stroke fill;text-shadow:0 0 6px var(--ink)}
.ridge-label.on{opacity:1}
.ridge-sun{opacity:0;transition:opacity 1.6s}
.ridge-sun.on{opacity:1}
.ridge-moon{opacity:0;transition:opacity 1.6s}
.ridge-moon.on{opacity:1}
.hero__ridge{margin-bottom:-.4rem;opacity:.92}
.phead__ridge{position:absolute;left:0;right:0;bottom:-1px;z-index:2;opacity:.4}
.sec__ridge{opacity:.5;margin-bottom:-1px}
/* Labels sit close together at this width (Donard/Saddle/Commedagh trace a
   short, steep stretch of line) — 10% smaller here only, not a change to
   --label itself, which is shared by chip labels, footer headings and more
   elsewhere on the site. calc() off the token rather than a flat px value so
   it stays in step with whatever --label's own fluid clamp resolves to. */
@media(max-width:700px){.hero__ridge{opacity:.8}.phead__ridge{opacity:.3}.ridge-label{font-size:calc(var(--label) * .9)}}

/* ===== The Ebb Line — footer tideline ===== */
.tide-band{position:relative;width:100%;line-height:0;pointer-events:none;margin-bottom:-1px}
.tide-band svg{display:block;width:100%;height:clamp(46px,7vw,84px)}
.footer__tide{opacity:.92}
@media(max-width:700px){.footer__tide{opacity:.8}}

/* ===== shared modifiers (replaces one-off inline styles that repeated
   identically across pages, or were plainly reusable, with named classes
   here; page-unique spacing tweaks stay as small utilities below rather
   than inline, so nothing in the page markup carries a style attr) ===== */
.sec--tight-top{padding-top:clamp(1.5rem,4vw,2.5rem)}
.sec--snug{padding-block:clamp(2.5rem,5vw,4rem)}
.sec--flush-top{padding-top:0}
.btnrow{display:flex;flex-wrap:wrap;gap:.7rem;margin-top:clamp(1.4rem,3vw,2.2rem)}
.btnrow--lg{margin-top:clamp(1.6rem,4vw,2.6rem)}
.btn--ghost-paper{--fg:var(--ink);box-shadow:inset 0 0 0 1px rgba(20,24,26,.35)}
.linkcard--static{cursor:default}
.tile--photo{padding:0;overflow:hidden}
.tile__body{padding:clamp(1rem,2.2vw,1.4rem);display:flex;flex-direction:column;gap:.5rem}
.credit-card__thumb{display:block;width:100%;aspect-ratio:4/3;object-fit:cover;background:var(--granite)}
.credits-empty{color:var(--stone)}
html[data-theme="day"] .sec:not(.sec--paper):not(.sec--sea) .credits-empty{color:var(--slate)}
.photo--flush{aspect-ratio:16/10;border-radius:0}
.photo--tour{aspect-ratio:4/3}
.tour-frame{position:relative}
.field--narrow{max-width:15rem}
.link--peat{color:var(--peat)}
.link--amber{color:var(--amber-soft)}
.mt-1{margin-top:.3rem}
.mt-2{margin-top:.7rem}
.mt-3{margin-top:1rem}
.mt-4{margin-top:1.2rem}
.mt-5{margin-top:clamp(1.4rem,3vw,2.2rem)}
.cta-banner{text-align:center}
.cta-banner h2{font-size:var(--step-3);max-width:20ch;margin:0 auto 1.2rem;text-wrap:balance}
/* ===== BASECAMP NOTICEBOARD MAP ===== */
/* The board is art-directed dark in both modes, so it pins its own text
   colour rather than inheriting body's — which day view flips to ink. */
.board{background:repeating-linear-gradient(180deg,rgba(0,0,0,.12) 0 1px,transparent 1px 46px),linear-gradient(150deg,#3c2c1e,#241a12);
  color:var(--paper);
  padding:clamp(.7rem,2vw,1.4rem);border-radius:4px;box-shadow:0 30px 60px -30px rgba(0,0,0,.8),inset 0 0 0 1px rgba(255,255,255,.06)}

/* toolbar */
.tools{display:flex;flex-wrap:wrap;gap:.5rem 1.2rem;align-items:center;margin-bottom:.9rem}
.tools__group{display:flex;flex-wrap:wrap;gap:.35rem;align-items:center}
.tools__label{font-size:var(--label);font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--sand);opacity:.75;margin-right:.2rem}
.tog{background:color-mix(in srgb,#0b1412 55%,transparent);border:1px solid color-mix(in srgb,var(--sand) 35%,transparent);
  color:var(--paper);font-family:var(--f-body);font-size:var(--label);font-weight:600;letter-spacing:.08em;
  padding:.45em .75em;border-radius:99px;cursor:pointer;transition:.18s;line-height:1.3;display:inline-flex;align-items:center;gap:.4em}
.tog:hover{border-color:var(--amber-soft)}
.tog[aria-pressed="true"]{background:var(--amber);border-color:var(--amber);color:var(--ink)}
.tog--layer[aria-pressed="true"]{background:var(--sea);border-color:var(--sea);color:var(--paper)}
.tools__spacer{margin-left:auto}
/* sits outside .tools (a flex row) so it doesn't disturb the spacer's push */
#filterEmpty{margin-bottom:.9rem}
/* the map-vs-paper-map note under the board, and the resource links below
   it — split into a short lead-in plus a real list (was one dense run-on
   paragraph) so the three links scan as items, not clauses. */
.mapnote{margin:1.4rem 0 0;max-width:62ch}
.mapnote__list{margin-top:.5rem;list-style:none;padding:0;display:flex;flex-direction:column;gap:.4rem}

/* map + list panes */
.board__inner{display:grid;gap:clamp(.7rem,1.8vw,1.1rem);grid-template-columns:minmax(0,1fr)}
@media(min-width:1000px){.board__inner{grid-template-columns:1.5fr 1fr}}
.mapfig{position:relative;aspect-ratio:10/7;background:#0f1c1a;border-radius:3px;overflow:hidden;box-shadow:inset 0 0 0 1px rgba(255,255,255,.08)}
.mapfig svg{position:absolute;inset:0;width:100%;height:100%}
[data-pane]{display:none}
[data-pane].is-shown{display:block}

/* layers */
#layer-contours,#layer-rings,#layer-routes,#layer-labels{transition:opacity .35s}
[data-layer-off="contours"] #layer-contours,
[data-layer-off="rings"] #layer-rings,
[data-layer-off="routes"] #layer-routes,
[data-layer-off="labels"] #layer-labels{opacity:0;pointer-events:none}
.route{fill:none;stroke:#c9b183;stroke-width:2.4;stroke-dasharray:6 8;opacity:.45;transition:opacity .3s,stroke .3s,stroke-width .3s}
.route.is-live{stroke:var(--amber);opacity:1;stroke-width:3.4;stroke-dasharray:8 6}

/* pins — the dot stays 14px, but the button carries a transparent hit area
   so the touch target clears the 24px WCAG 2.2 minimum */
.pin{position:absolute;transform:translate(-50%,-50%);z-index:3;background:none;border:0;cursor:pointer;
  padding:6px;min-width:26px;min-height:26px;
  color:var(--paper);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.28rem;font-family:var(--f-body);
  transition:opacity .3s,filter .3s}
.pin__dot{width:14px;height:14px;border-radius:50%;background:var(--paper);box-shadow:0 0 0 2px #0b1412,0 0 0 3px var(--paper);transition:transform .25s,background .25s}
.pin__label{font-size:var(--label);font-weight:700;letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;
  background:color-mix(in srgb,#0b1412 82%,transparent);padding:.22em .45em;border-radius:2px;color:color-mix(in srgb,var(--paper) 90%,transparent)}
/* Pins near the edge of the board hang their label inboard instead of centring
   it, so a long name like "Castlewellan Forest Park" isn't clipped off. The
   translate is half the label's own width, so it works whatever the name. */
.pin--w .pin__label{transform:translateX(calc(50% - 13px))}
.pin--e .pin__label{transform:translateX(calc(-50% + 13px))}
.pin:hover .pin__dot,.pin:focus-visible .pin__dot{transform:scale(1.35)}
.pin.is-active .pin__dot{background:var(--amber);box-shadow:0 0 0 2px #0b1412,0 0 0 3px var(--amber),0 0 20px 4px color-mix(in srgb,var(--amber) 55%,transparent)}
.pin.is-active .pin__label{color:var(--amber-soft)}
.pin.is-dimmed{opacity:.22;filter:grayscale(1)}
.pin--home .pin__dot{background:var(--amber);width:18px;height:18px;box-shadow:0 0 0 3px #0b1412,0 0 0 4px var(--amber);animation:pulse 3.4s infinite}
@keyframes pulse{0%,100%{box-shadow:0 0 0 3px #0b1412,0 0 0 4px var(--amber),0 0 0 0 color-mix(in srgb,var(--amber) 45%,transparent)}
50%{box-shadow:0 0 0 3px #0b1412,0 0 0 4px var(--amber),0 0 0 14px transparent}}
@media(max-width:620px){
  .pin__label{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .pin--home .pin__label{position:static;width:auto;height:auto;clip-path:none;padding:.22em .45em}
}
/* Used to float over the bottom-right corner of the map, which on narrow
   viewports sat on top of live pins (Bloody Bridge, Donard) and swallowed
   their taps. Now a plain line below the map/list column instead — still
   only shown for the map pane, via the same [data-pane] toggle as mapfig
   and listview, so switching to List view hides it correctly. */
.maphint{margin-top:.6rem;font-size:var(--label);letter-spacing:.14em;text-transform:uppercase;
  color:color-mix(in srgb,var(--paper) 60%,transparent);text-align:right}

/* index card */
.card-index{background:var(--paper);color:var(--ink);border-radius:3px;padding:clamp(1rem,2.4vw,1.5rem);
  box-shadow:0 18px 30px -22px rgba(0,0,0,.9);display:flex;flex-direction:column;gap:.8rem;min-height:100%;
  background-image:linear-gradient(color-mix(in srgb,var(--sea) 11%,transparent) 1px,transparent 1px);
  background-size:100% 30px;background-position:0 12px}
.card-index h3{font-size:var(--step-2);line-height:1.05}
.card-index__meta{display:flex;flex-wrap:wrap;gap:.35rem}
.tag{font-size:var(--label);font-weight:700;letter-spacing:.14em;text-transform:uppercase;padding:.38em .6em;border-radius:2px;background:var(--sea);color:var(--paper)}
.tag--amber{background:var(--amber);color:var(--ink)}
.tag--peat{background:var(--peat);color:var(--paper)}
.card-index dl{margin:0;display:grid;gap:.7rem}
.card-index dt{font-size:var(--label);font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--peat);margin-bottom:.15rem}
.card-index dd{margin:0;font-size:var(--step--1);line-height:1.5;color:color-mix(in srgb,var(--ink) 84%,transparent)}
.elev-spark{display:block;margin-top:.4rem;color:var(--peat);width:96px;height:26px}
.dots{display:inline-flex;gap:3px;vertical-align:middle;margin-left:.4rem}
.dots i{width:8px;height:8px;border-radius:50%;background:color-mix(in srgb,var(--slate) 35%,transparent);display:block}
.dots i.on{background:var(--amber)}
/* difficulty word in the card footer — same label treatment as .card-index dt,
   minus its bottom margin (this one sits inline, not stacked over a value) */
.diffword{font-size:var(--label);font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--peat)}
.card-index__foot{margin-top:auto;border-top:1px dashed color-mix(in srgb,var(--slate) 45%,transparent);padding-top:.8rem;
  display:flex;flex-wrap:wrap;gap:.5rem;align-items:center}
.card-index__foot .btn{--bg:var(--sea);--fg:var(--paper)}
.card-index__foot .btn:hover{--bg:var(--moss)}
.card-index__foot .btn.is-added{--bg:var(--peat)}

/* list view */
.listview{background:var(--paper);color:var(--ink);border-radius:3px;overflow:hidden}
.listview__row{display:grid;grid-template-columns:1fr auto;gap:.3rem 1rem;align-items:center;width:100%;text-align:left;
  background:none;border:0;border-bottom:1px solid color-mix(in srgb,var(--slate) 25%,transparent);
  padding:.85rem clamp(.9rem,2vw,1.3rem);cursor:pointer;font-family:var(--f-body);color:inherit}
.listview__row:hover{background:color-mix(in srgb,var(--sand) 35%,transparent)}
.listview__row b{font-family:var(--f-display);font-size:var(--step-1);font-weight:600;display:block}
.listview__row small{font-size:var(--step--1);color:var(--slate);grid-column:1;display:block}
.listview__row .mins{font-size:var(--label);font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--peat);grid-row:1/3;text-align:right;white-space:nowrap}

/* shortlist tray */
.tray{margin-top:clamp(.7rem,1.8vw,1.1rem);background:color-mix(in srgb,#0b1412 60%,transparent);
  border:1px dashed color-mix(in srgb,var(--sand) 45%,transparent);border-radius:3px;padding:clamp(.9rem,2.2vw,1.3rem)}
.tray__head{display:flex;flex-wrap:wrap;gap:.6rem;align-items:baseline;justify-content:space-between}
.tray__head h3{font-size:var(--step-1)}
/* "Turn into a day" / "Empty" button pair, next to the tray heading */
.tray__actions{display:flex;gap:.5rem;flex-wrap:wrap}
#trayNote{margin:.2rem 0 0}
.tray__items{display:flex;flex-wrap:wrap;gap:.4rem;margin:.8rem 0 0;padding:0;list-style:none}
.tray__items li{display:inline-flex;align-items:center;gap:.5em;background:color-mix(in srgb,var(--sand) 20%,transparent);
  border:1px solid color-mix(in srgb,var(--sand) 40%,transparent);border-radius:99px;padding:.35em .5em .35em .8em;font-size:.72rem}
/* the "Nothing added yet." placeholder — plain text, none of the pill chrome
   real tray items get, so it can't be mistaken for a removable item */
.tray__items .tray__empty{background:none;border:0;padding-left:0;color:var(--stone)}
.tray__items button{background:none;border:0;color:var(--amber-soft);cursor:pointer;font-size:1rem;line-height:1;padding:0 .2em}
.tray__out{margin-top:1rem;display:none}
.tray__out.is-shown{display:block}
.plan-lines{list-style:none;margin:.6rem 0 0;padding:0;counter-reset:step}
.plan-lines li{display:grid;grid-template-columns:auto 1fr;gap:.9rem;padding:.55rem 0;border-top:1px dashed color-mix(in srgb,var(--sand) 30%,transparent);font-size:var(--step--1)}
.plan-lines time{font-family:var(--f-display);color:var(--amber-soft);font-weight:600}
.plan-title{margin:.2rem 0 .4rem}
.plan-warn{margin-top:.7rem}
.plan-warn--short{color:var(--amber-soft)}
.plan-footnote{margin-top:.9rem}
.plan-actions{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1rem}
.plan-actions .btn{--bg:transparent;--fg:var(--paper);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--paper) 45%,transparent)}
.plan-actions .btn:hover{--bg:color-mix(in srgb,var(--paper) 12%,transparent);--fg:var(--paper)}
.plan-actions .btn:disabled{transform:none}

/* today card */
.today{margin-top:clamp(.7rem,1.8vw,1.1rem);display:grid;gap:.9rem;
  background:color-mix(in srgb,#0b1412 55%,transparent);border:1px dashed color-mix(in srgb,var(--sand) 45%,transparent);
  padding:clamp(.9rem,2.2vw,1.4rem);border-radius:3px}
@media(min-width:820px){
  .today{grid-template-columns:auto 1fr auto;align-items:center;gap:1.4rem}
  /* Only hold the button on one line once there's room for it. Below this,
     nowrap forced a ~373px minimum that widened the whole document and made
     the page scroll sideways on every phone. */
  .today .btn{white-space:nowrap}
}
.today h3{font-size:var(--step-2)}
.today .btn{text-align:center}
.today .eyebrow{margin-bottom:.4rem}
.today__col{margin:0}
#pickBody{margin:0}
#pickNote,#pickWhy{margin:.35rem 0 0}
/* shown only when the weather bumped the pick to something else */
.pick__why{color:var(--amber-soft)}
#pickMap{margin-top:.5rem}

/* pouring routes (study 03) */
.route.is-live{stroke:var(--amber);opacity:1;stroke-width:3.2;stroke-linecap:round;stroke-dasharray:none}
.route.is-hint{opacity:.85;stroke:var(--sand);stroke-width:2.8}
#layer-rings circle{transform-box:view-box;transform-origin:430px 330px}
#layer-rings.ripple circle{animation:ringpop .85s cubic-bezier(.2,.7,.3,1) both}
#layer-rings.ripple circle:nth-child(2){animation-delay:.1s}
#layer-rings.ripple circle:nth-child(3){animation-delay:.2s}
@keyframes ringpop{from{transform:scale(.5);opacity:0}to{transform:scale(1);opacity:.85}}
@media (prefers-reduced-motion: reduce){#layer-rings.ripple circle{animation:none}}
html[data-motion="off"] #layer-rings.ripple circle{animation:none}

/* ===== PRINT: the built "My day" plan, and nothing else -----------------
   Allow-list, not a deny-list: everything under <body> is hidden, then the
   plan itself (and only the plan) is switched back on and repainted for
   paper. The "Print this plan" button only exists once a plan has been
   built, so there's always something here to print by the time this runs. */
@media print{
  body{background:#fff!important}
  header.nav, footer.footer, .tide-band, .skip{display:none!important}
  #main>*{display:none!important}
  #main>#map{display:block!important}
  #map>.wrap>*{display:none!important}
  #map>.wrap>.board{display:contents!important}
  .board>*{display:none!important}
  .board>.tray{display:block!important}
  .tray{background:#fff!important;border:0!important;padding:0!important;margin:0!important}
  .tray>*{display:none!important}
  .tray>.tray__out{display:block!important}
  .tray__out{color:#111!important}
  .tray__out::before{content:"Hutt Backpackers — My Day";display:block;
    font-family:var(--f-display);font-size:1.4rem;font-weight:600;margin-bottom:.6rem;color:#111}
  .tray__out .eyebrow{color:#555!important}
  .tray__out .small{color:#333!important}
  .plan-lines li{border-top:1px solid #999!important;color:#111}
  .plan-lines time{color:#111!important}
  .plan-actions{display:none!important}
  .tray__out a{color:#111!important;text-decoration:underline}
}
/* ---------------------------------------------------------------------
   What's On — event cards, filters, sections. Extends the existing tile/
   grid/chip vocabulary (site.css) rather than inventing a parallel one —
   see PROJECT-BRIEF.md's own component list before adding new class names
   here. Concatenated into site.css by build.py, same as map.css.
   --------------------------------------------------------------------- */

.evt-jump{display:flex;gap:.5rem;flex-wrap:wrap;margin:0 0 1.5rem}
.evt-jump a{font-size:var(--label);letter-spacing:.14em;text-transform:uppercase;font-weight:700;
  color:var(--paper);text-decoration:none;padding:.5em .9em;border-radius:999px;
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--paper) 35%,transparent)}
.evt-jump a:hover{background:color-mix(in srgb,var(--paper) 10%,transparent)}
html[data-theme="day"] .sec:not(.sec--sea) .evt-jump a{color:var(--ink);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ink) 25%,transparent)}
html[data-theme="day"] .sec:not(.sec--sea) .evt-jump a:hover{background:color-mix(in srgb,var(--ink) 10%,transparent)}

/* Filter row — horizontally scrollable on narrow screens so it never wraps
   into a tall stack that pushes "Tonight" below the fold. */
.evt-filters{display:flex;gap:.6rem;overflow-x:auto;padding-bottom:.3rem;margin:0 0 2rem;
  -webkit-overflow-scrolling:touch;scrollbar-width:thin}
.evt-filters::-webkit-scrollbar{height:5px}
.evtchip{flex:none;font-size:var(--step--1);font-weight:600;padding:.55em 1.1em;border-radius:999px;
  background:transparent;color:var(--paper);cursor:pointer;
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--paper) 38%,transparent);
  transition:background .15s ease,color .15s ease,box-shadow .15s ease}
.evtchip:hover{background:color-mix(in srgb,var(--paper) 10%,transparent)}
.evtchip.is-active{background:var(--amber);color:var(--ink);box-shadow:none}
html[data-theme="day"] .sec:not(.sec--sea) .evtchip{color:var(--ink);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ink) 25%,transparent)}
html[data-theme="day"] .sec:not(.sec--sea) .evtchip.is-active{background:var(--peat);color:var(--paper)}

.evt-grid{display:grid;gap:clamp(.8rem,1.8vw,1.3rem);grid-template-columns:repeat(auto-fill,minmax(min(100%,280px),1fr))}
.evt-grid--compact{grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr))}

.evt-card{display:flex;flex-direction:column;text-decoration:none;color:inherit;padding:0;overflow:hidden;position:relative}
.evt-card__media{position:relative;aspect-ratio:16/10;overflow:hidden;background:linear-gradient(155deg,var(--sea-deep),var(--sea))}
.evt-card__media img{width:100%;height:100%;object-fit:cover;display:block}
.evt-card__glyph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;opacity:.5}
.evt-card__glyph svg{width:38%;height:38%;max-width:64px;max-height:64px}
.evt-card__badge{position:absolute;top:.6rem;left:.6rem;z-index:2;font-size:var(--label);font-weight:700;
  letter-spacing:.06em;padding:.35em .7em;border-radius:999px;background:rgba(10,14,13,.72);color:var(--paper);
  backdrop-filter:blur(2px)}
.evt-card__badge--free{background:var(--amber);color:var(--ink)}
.evt-card__featured{position:absolute;top:.6rem;right:.6rem;z-index:2;font-size:var(--label);font-weight:700;
  letter-spacing:.06em;padding:.35em .7em;border-radius:999px;background:var(--amber-soft);color:var(--ink)}

.evt-card__body{padding:clamp(.9rem,2vw,1.2rem);display:flex;flex-direction:column;gap:.5rem;flex:1}
.evt-card__when{font-size:var(--label);letter-spacing:.1em;text-transform:uppercase;font-weight:700;color:var(--amber-soft)}
html[data-theme="day"] .sec:not(.sec--sea) .evt-card__when{color:var(--peat)}
.evt-card__title{font-family:var(--f-display);font-size:var(--step-1);font-weight:600;line-height:1.15;margin:0}
.evt-card__meta{font-size:var(--step--1);color:color-mix(in srgb,currentColor 72%,transparent);display:flex;flex-wrap:wrap;gap:.4em 1em;margin:0}
.evt-card__meta span{white-space:nowrap}
.evt-card__desc{font-size:var(--step--1);margin:0;color:color-mix(in srgb,currentColor 82%,transparent)}
.evt-card__tags{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:.15rem}
.evt-tag{font-size:.7rem;letter-spacing:.03em;padding:.28em .6em;border-radius:999px;
  background:color-mix(in srgb,var(--paper) 10%,transparent);color:color-mix(in srgb,var(--paper) 88%,transparent)}
html[data-theme="day"] .sec:not(.sec--sea) .evt-tag{background:color-mix(in srgb,var(--ink) 8%,transparent);color:var(--ink)}
.evt-card__go{margin-top:auto;padding-top:.5rem;font-size:var(--label);font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--amber-soft)}
html[data-theme="day"] .sec:not(.sec--sea) .evt-card__go{color:var(--peat)}
.evt-card:hover .evt-card__go{color:var(--paper)}
html[data-theme="day"] .sec:not(.sec--sea) .evt-card:hover .evt-card__go{color:var(--granite)}

.evt-empty{font-size:var(--step-0);color:var(--stone);padding:1.5rem 0}
.evt-skeleton .evt-grid{opacity:.5}
.evt-skel-card{height:220px;border-radius:3px;background:color-mix(in srgb,var(--paper) 6%,transparent);border:var(--edge)}

/* Homepage compact widget — three-ish cards, no filters, its own CTA. */
.evt-home .evt-grid{margin-bottom:1.5rem}

@media(max-width:600px){
  .evt-card__title{font-size:var(--step-1)}
}
