/* ==========================================================================
   SALKANTAY.ORG — "The High Route" design system
   Concept: the altimeter site. Altitude is the organizing axis; the palette
   is glacial (puna night / glacier paper / Humantay-lake turquoise / ichu gold).
   Type: Archivo (variable width — signage), Fraunces (editorial italic),
   IBM Plex Mono (instrument data).
   ========================================================================== */

/* ---------- Tokens ---------- */
:root {
  /* color */
  --puna:        #0F1F17;   /* deep green-black — night camp sections, footer */
  --puna-2:      #16281E;   /* raised surface on puna */
  --glacier:     #EFF3EE;   /* cool paper white — page background */
  --glacier-2:   #E4EAE2;   /* recessed surface on glacier */
  --ink:         #10241A;   /* body text on glacier */
  --stone:       #55645B;   /* secondary text on glacier */
  --laguna:      #3FC1B6;   /* Humantay turquoise — graphics, on dark only */
  --laguna-ink:  #166F68;   /* text-safe teal — AA on BOTH --glacier (5.34:1) and --glacier-2 (4.89:1) */
  --ichu:        #C9A55C;   /* ichu-grass gold — sparing warm note */
  /* POLE tokens — deliberately NOT redefined per scheme. A dark section stays
     dark in both schemes (it becomes a raised surface, not a light one), so
     its ink is light either way. Using --glacier for this was the bug: the
     pigment name re-points, the role does not. */
  --puna-3:      #1B3025;   /* raised on puna-2 — 1.10:1, same step as puna->puna-2 */
  --stone-d:     #9DACA2;   /* secondary text on puna — 7.21:1 (--stone is 2.73 there) */
  --snow-line:   rgba(16, 36, 26, 0.14);   /* hairline on light */
  --snow-line-d: rgba(239, 243, 238, 0.16); /* hairline on dark */
  --danger:      #A8321E;   /* error on glacier — 5.96:1 */
  --danger-d:    #E8705A;   /* error on puna    — 5.61:1 (--danger is 2.56 there) */

  /* ---- ROLES ----------------------------------------------------------
     Everything above this line is a PIGMENT and never changes. Everything
     below is a ROLE and is remapped by the dark block near the end of this
     file. Rules should reference roles; a rule that names a pigment is
     asserting "this colour regardless of scheme", which is true for the
     surfaces that are dark in BOTH schemes (.hero's photo stage, .scrub,
     the footer night sky) and false everywhere else.

     Why this split exists: 33 rules used to name a pigment to mean the
     OPPOSITE pole — `color: var(--glacier)` for light ink sitting on a dark
     section. Re-pointing pigments per scheme inverted every one of them into
     invisibility (.rating-chip measured 1.10:1). Roles make that impossible
     to express by accident. */
  --surface:         var(--glacier);      /* page */
  --surface-2:       var(--glacier-2);    /* recessed panel (raised, in dark) */
  --surface-feature: var(--puna);         /* the emphasis section */
  --surface-feature-2: var(--puna-2);     /* a card RAISED inside that section.
                                             In light this is raised on --puna; in
                                             dark the section is already --puna-2,
                                             so it must step up again or the card
                                             renders identical to its own section. */
  --text:            var(--ink);
  --text-2:          var(--stone);
  --accent:          var(--laguna-ink);   /* teal as TEXT/border */
  --accent-fill:     var(--laguna-ink);   /* teal as a BACKGROUND */
  --on-accent:       var(--glacier);      /* ink on --accent-fill; flips, because
                                             the fill flips lightness */
  --on-feature:      var(--glacier);      /* ink on --surface-feature; does NOT
                                             flip — a feature section is dark in
                                             both schemes */
  --rule:            var(--snow-line);
  --invert-bg:       var(--puna);         /* "the opposite of the page" */
  --invert-text:     var(--glacier);
  --danger-text:     var(--danger);

  /* type */
  --f-display: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --f-body:    "Archivo", "Helvetica Neue", Arial, sans-serif;
  --f-serif:   "Fraunces", Georgia, serif;
  --f-mono:    "IBM Plex Mono", "SF Mono", Menlo, monospace;

  /* scale (fluid) */
  --t-hero:  clamp(2.6rem, 8.5vw, 7rem);
  --t-h1:    clamp(2.2rem, 5.5vw, 4.25rem);
  --t-h2:    clamp(1.7rem, 3.6vw, 2.75rem);
  --t-h3:    clamp(1.2rem, 2vw, 1.5rem);
  --t-lede:  clamp(1.2rem, 2.2vw, 1.65rem);
  --t-body:  1.0625rem;
  --t-small: 0.9rem;
  --t-mono:  0.8125rem;

  /* layout */
  --wrap: 1200px;
  --wrap-narrow: 760px;
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --sp-1: 0.5rem; --sp-2: 1rem; --sp-3: 1.75rem; --sp-4: 3rem;
  --sp-5: clamp(3.5rem, 8vw, 7rem);   /* section rhythm */
  --radius: 2px;

  /* motion */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---------- Reset / base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.65;
  color: var(--text);
  background: var(--surface);
  font-variation-settings: "wdth" 100;
}
img, svg, video { max-width: 100%; height: auto; display: block; }
h1, h2, h3, h4 { margin: 0 0 var(--sp-2); line-height: 1.05; font-weight: 800; letter-spacing: -0.01em; }
p { margin: 0 0 var(--sp-2); }
ul, ol { margin: 0 0 var(--sp-2); padding-left: 1.25rem; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--text); }
:focus-visible { outline: 3px solid var(--laguna-ink); outline-offset: 3px; border-radius: 1px; }
::selection { background: var(--laguna); color: var(--puna); }

.skip-link {
  position: absolute; left: -999px; top: 0; z-index: 100;
  background: var(--invert-bg); color: var(--invert-text); padding: 0.75rem 1.25rem;
  font-family: var(--f-mono); font-size: var(--t-mono);
}
.skip-link:focus { left: 0; }

/* ---------- Utility ---------- */
.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
.wrap--narrow { max-width: var(--wrap-narrow); }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* Eyebrow: mono instrument label. Encodes altitude / coordinates / day. */
.eyebrow {
  display: flex; align-items: center; gap: 0.75rem;
  font-family: var(--f-mono); font-size: var(--t-mono);
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-2); margin-bottom: var(--sp-2);
}
.eyebrow::before { content: ""; width: 2rem; height: 1px; background: var(--accent-fill); flex: none; }
.section--dark .eyebrow { color: var(--laguna); }
.section--dark .eyebrow::before { background: var(--laguna); }

/* Display headings: wide Archivo, all-caps, monumental */
.display {
  font-family: var(--f-display);
  font-variation-settings: "wdth" 118;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.005em;
  line-height: 0.98;
}
.serif-lede {
  font-family: var(--f-serif); font-style: italic; font-weight: 400;
  font-size: var(--t-lede); line-height: 1.45; letter-spacing: 0;
  color: var(--text);
}
.section--dark .serif-lede { color: var(--on-feature); }

/* Altitude figure: big mono number with unit */
.alt-figure { font-family: var(--f-mono); font-weight: 500; letter-spacing: 0.02em; }
.alt-figure sup { font-size: 0.5em; letter-spacing: 0.1em; }

/* ---------- Sections ---------- */
.section { padding-block: var(--sp-5); }
.section--dark { background: var(--surface-feature); color: var(--on-feature); }
.section--dark h1, .section--dark h2, .section--dark h3 { color: var(--on-feature); }
.section--dark a { color: var(--laguna); }
.section--dark a:hover { color: var(--on-feature); }
.section--recess { background: var(--surface-2); }
.section-head { max-width: 56rem; margin-bottom: var(--sp-4); }
.section-head h2 { font-size: var(--t-h2); }

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
}
.site-header__bar {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: 4.25rem;
}
.brand {
  font-family: var(--f-display); font-variation-settings: "wdth" 118;
  font-weight: 800; font-size: 1.15rem; letter-spacing: 0.04em;
  text-transform: uppercase; text-decoration: none; color: var(--text);
  white-space: nowrap;
}
.brand:hover { color: var(--text); }
.brand em { font-style: normal; color: var(--accent); }

/* --- brand lockup (inline SVG) ---
   Sized by HEIGHT so the 1168x470 viewBox keeps its ratio at any breakpoint;
   width:auto rather than a fixed px pair, which would distort it. The two fills
   are custom properties (see BRAND_SVG in lib.mjs) so the same asset can be
   re-themed per surface instead of shipping a second file. */
.brand { display: inline-flex; align-items: center; }
/* 2.75rem, not smaller: the lockup stacks a mountain above the wordmark, so
   only ~40% of its height is letterform. At 2rem the wordmark's cap height
   measured 13px against 14.4px nav links — the brand read as the SMALLEST
   thing in the bar. 2.75rem puts the cap at 18px and still leaves 12px of air
   in the 68px bar. */
.brand svg { height: 2.75rem; width: auto; display: block; }
@media (max-width: 719px) { .brand svg { height: 2.25rem; } }

/* Light surfaces use the file's own defaults (#166F68 / #42BFB5), which are
   --laguna-ink and --laguna: the logo was drawn from this palette.

   Dark surfaces MUST override. Measured against --puna #0F1F17:
     wordmark #166F68 -> 2.85:1  FAILS WCAG 1.4.11 (needs 3:1)
     mountain #42BFB5 -> 7.61:1  passes
   so only the wordmark is repainted, to --glacier; the turquoise mountain is
   already the strongest element on dark and stays as the accent. */
.section--dark, .site-footer, .lp-final { --logo-word: var(--glacier); --logo-mark: var(--laguna); }

@media (forced-colors: active) {
  /* In forced-colors the custom properties are ignored; keep the mark visible. */
  .brand svg path { fill: CanvasText; }
}

/* the live altimeter readout — signature element */
.altimeter {
  font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.1em;
  color: var(--text-2); white-space: nowrap;
  display: none;
}
.altimeter output { color: var(--accent); font-weight: 500; }
@media (min-width: 900px) { .altimeter { display: block; } }

.site-nav { margin-left: auto; }
.site-nav ul { list-style: none; margin: 0; padding: 0; display: flex; gap: 1.75rem; align-items: center; }
/* All three rules exclude .btn — `.site-nav a` (0,1,1) outranks `.btn--primary`
   (0,1,0), so without :not() the nav would repaint the button's own label and
   drop the "Contact" text to ~3:1 against its own background. */
.site-nav a:not(.btn) {
  font-size: var(--t-small); font-weight: 600; letter-spacing: 0.02em;
  text-decoration: none; color: var(--text);
}
.site-nav a:not(.btn):hover { color: var(--accent); }
.site-nav a[aria-current="page"]:not(.btn) { color: var(--accent); }
.site-nav a.btn { text-decoration: none; }
.nav-toggle {
  margin-left: auto; display: none;
  background: none; border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 0.55rem 0.9rem; font-family: var(--f-mono); font-size: var(--t-mono);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text); cursor: pointer;
}
@media (max-width: 899px) {
  .nav-toggle { display: block; }
  .site-nav {
    display: none; position: absolute; inset: 100% 0 auto 0;
    background: var(--surface); border-bottom: 1px solid var(--rule);
    padding: var(--sp-2) var(--gutter) var(--sp-3);
  }
  .site-nav.is-open { display: block; }
  .site-nav ul { flex-direction: column; align-items: flex-start; gap: 1rem; }
  .site-nav a { font-size: 1.15rem; }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block; padding: 0.95rem 1.9rem;
  font-family: var(--f-body); font-weight: 700; font-size: var(--t-small);
  letter-spacing: 0.05em; text-transform: uppercase; text-decoration: none;
  border-radius: var(--radius); border: 1px solid transparent;
  transition: transform 0.25s var(--ease), background-color 0.25s var(--ease), color 0.25s var(--ease);
}
.btn:hover { transform: translateY(-2px); }
.btn--primary { background: var(--accent-fill); color: var(--on-accent); }
.btn--primary:hover { background: var(--invert-bg); color: var(--invert-text); }
.btn--ghost { border-color: currentColor; color: var(--text); background: transparent; }
.btn--ghost:hover { background: var(--invert-bg); color: var(--invert-text); }
.section--dark .btn--primary, .hero .btn--primary { background: var(--laguna); color: var(--puna); }
.section--dark .btn--primary:hover, .hero .btn--primary:hover { background: var(--on-feature); color: var(--puna); }
.section--dark .btn--ghost, .hero .btn--ghost { color: var(--on-feature); }
.section--dark .btn--ghost:hover, .hero .btn--ghost:hover { background: var(--on-feature); color: var(--puna); }
.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* ---------- Hero ---------- */
.hero {
  position: relative; min-height: min(92vh, 60rem);
  display: flex; align-items: flex-end;
  background: var(--puna); color: var(--on-feature); overflow: hidden;
}
.hero__media, .hero__media video, .hero__media img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.hero__media::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(15,31,23,0.25) 0%, rgba(15,31,23,0.1) 40%, rgba(15,31,23,0.82) 100%);
}
.hero__content { position: relative; z-index: 1; width: 100%; padding-block: var(--sp-4) var(--sp-4); }
.hero .eyebrow { color: var(--laguna); }
.hero .eyebrow::before { background: var(--laguna); }
.hero__title {
  font-size: var(--t-hero); margin-bottom: var(--sp-2); max-width: 16ch;
  text-wrap: balance;
}
.hero__title em { font-style: normal; color: var(--laguna); }
.hero__sub { max-width: 44ch; font-size: 1.15rem; color: rgba(239,243,238,0.88); }

/* stat strip under the hero copy */
.stat-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 1px; background: var(--snow-line-d);
  border-block: 1px solid var(--snow-line-d);
  margin-top: var(--sp-4);
}
.stat-strip > div { background: rgba(15,31,23,0.55); padding: 1.1rem 1.25rem; }
.stat-strip .alt-figure { font-size: clamp(1.4rem, 2.6vw, 2rem); color: var(--on-feature); display: block; }
.stat-strip small {
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--laguna);
}

/* ---------- Elevation profile (signature) ---------- */
.route { position: relative; }
.route__svg { width: 100%; height: auto; }
.route__svg .profile-line {
  fill: none; stroke: var(--laguna-ink); stroke-width: 2.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.route__svg .profile-fill { fill: url(#profileFade); opacity: 0.5; }
.route__svg .profile-grid { stroke: var(--rule); stroke-width: 1; }
.route__svg .profile-label { font-family: var(--f-mono); font-size: 11px; fill: var(--text-2); letter-spacing: 0.08em; }
.route__svg .profile-dot { fill: var(--surface); stroke: var(--accent); stroke-width: 2.5; }
.route__svg .profile-peak { fill: var(--ichu); stroke: none; }
.section--dark .route__svg .profile-line { stroke: var(--laguna); }
.section--dark .route__svg .profile-grid { stroke: var(--snow-line-d); }
.section--dark .route__svg .profile-label { fill: rgba(239,243,238,0.6); }
.section--dark .route__svg .profile-dot { fill: var(--surface-feature); stroke: var(--laguna); }

/* line-draw on reveal */
.js .profile-line { stroke-dasharray: 2400; stroke-dashoffset: 2400; }
.js .route.is-in .profile-line { animation: draw 2.4s var(--ease) forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }

/* day cards along the route */
.day-grid {
  display: grid; gap: var(--sp-2);
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  margin-top: var(--sp-3);
  counter-reset: day;
}
.day-card {
  border-top: 2px solid var(--accent);
  padding-top: var(--sp-2);
}
.day-card h3 { font-size: 1.05rem; letter-spacing: 0; }
.day-card .day-no {
  font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-2); display: block; margin-bottom: 0.4rem;
}
.day-card .alt-figure { color: var(--accent); font-size: 1.05rem; }
.day-card p { font-size: var(--t-small); color: var(--text-2); margin: 0.35rem 0 0; }
.section--dark .day-card { border-top-color: var(--laguna); }
.section--dark .day-card .day-no { color: rgba(239,243,238,0.6); }
.section--dark .day-card .alt-figure { color: var(--laguna); }
.section--dark .day-card p { color: rgba(239,243,238,0.72); }

/* ---------- Cards (tours / highlights / guide) ---------- */
.card-grid { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); }
.card {
  position: relative; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius);
  overflow: hidden;
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.card:hover { transform: translateY(-4px); box-shadow: 0 18px 40px -18px rgba(16,36,26,0.35); }
.card__media { aspect-ratio: 3 / 2; overflow: hidden; background: var(--surface-2); }
.card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease); }
.card:hover .card__media img { transform: scale(1.04); }
.card__body { padding: var(--sp-3); display: flex; flex-direction: column; gap: 0.6rem; flex: 1; }
.card__meta {
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--accent);
}
/* h2 as well as h3: the blog index lists posts under the page H1, so its cards
   are h2 by hierarchy (an h3 there would skip a level). Card styling is about
   the card, not the level. */
.card h2, .card h3 { font-size: var(--t-h3); margin: 0; }
.card h2 a, .card h3 a { text-decoration: none; color: inherit; }
.card h2 a::after,
.card h3 a::after { content: ""; position: absolute; inset: 0; }  /* whole-card link */
.card h2 a:hover,
.card h3 a:hover { color: var(--accent); }
/* :not(.card__meta) — the meta label is also a <p>, and without this it takes
   flex:1 too, stretching and pushing the card title down. */
.card p:not(.card__meta) { font-size: var(--t-small); color: var(--text-2); margin: 0; flex: 1; }
.card__foot {
  display: flex; justify-content: space-between; align-items: baseline;
  border-top: 1px solid var(--rule); padding-top: 0.8rem; margin-top: 0.4rem;
}
.card__price { font-family: var(--f-mono); font-weight: 500; }
.card__price small { color: var(--text-2); font-family: var(--f-body); }
.card__cta { font-size: var(--t-small); font-weight: 700; color: var(--accent); }

/* dark-section variant */
.section--dark .card { background: var(--surface-feature-2); border-color: var(--snow-line-d); }
.section--dark .card h3 { color: var(--on-feature); }
.section--dark .card p { color: rgba(239,243,238,0.72); }
.section--dark .card__foot { border-top-color: var(--snow-line-d); }
.section--dark .card__meta, .section--dark .card__cta { color: var(--laguna); }
.section--dark .card__price { color: var(--on-feature); }
/* the nested <small> keeps --stone otherwise → 2.48:1 on --puna-2 */
.section--dark .card__price small { color: rgba(239,243,238,0.72); }

/* featured (2-col) card */
@media (min-width: 900px) {
  .card--wide { grid-column: span 2; flex-direction: row; }
  .card--wide .card__media { aspect-ratio: auto; flex: 1.2; }
  .card--wide .card__body { flex: 1; justify-content: center; }
}

/* ---------- Index / hub link lists (topical authority blocks) ---------- */
.index-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.index-list li { border-bottom: 1px solid var(--rule); }
.index-list a {
  display: grid; grid-template-columns: auto 1fr auto; align-items: baseline; gap: var(--sp-2);
  padding: 1.1rem 0.25rem; text-decoration: none; color: var(--text);
  transition: background-color 0.2s var(--ease), padding-left 0.25s var(--ease);
}
.index-list a:hover { background: var(--surface-2); padding-left: 0.9rem; }
.index-list .idx {
  font-family: var(--f-mono); font-size: var(--t-mono); color: var(--accent); letter-spacing: 0.1em;
}
.index-list .t { font-weight: 700; }
.index-list .d { display: block; font-size: var(--t-small); color: var(--text-2); font-weight: 400; }
.index-list .arrow { font-family: var(--f-mono); color: var(--text-2); }
.index-list a:hover .arrow { color: var(--accent); }
.section--dark .index-list { border-top-color: var(--snow-line-d); }
.section--dark .index-list li { border-bottom-color: var(--snow-line-d); }
.section--dark .index-list a { color: var(--on-feature); }
.section--dark .index-list a:hover { background: var(--surface-feature-2); }
.section--dark .index-list .d { color: rgba(239,243,238,0.72); }

/* ---------- Comparison table ---------- */
.compare-scroll { overflow-x: auto; }
.compare {
  width: 100%; border-collapse: collapse; font-size: var(--t-small); min-width: 34rem;
}
.compare caption {
  text-align: left; font-family: var(--f-mono); font-size: var(--t-mono);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-2); padding-bottom: var(--sp-2);
}
.compare th, .compare td { padding: 0.9rem 1rem; text-align: left; border-bottom: 1px solid var(--rule); vertical-align: top; }
.compare thead th {
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-2); border-bottom: 2px solid var(--text);
}
.compare tbody th { font-weight: 700; color: var(--text); }
.compare .win { color: var(--accent); font-weight: 700; }

/* ---------- Article layout (guide / highlight pages) ---------- */
.article-hero { padding-block: var(--sp-5) var(--sp-4); }
.article-hero h1 { font-size: var(--t-h1); max-width: 20ch; text-wrap: balance; }
.article-hero .serif-lede { max-width: 38ch; margin-top: var(--sp-2); }
.article-layout { display: grid; gap: var(--sp-4); }
@media (min-width: 1000px) {
  .article-layout { grid-template-columns: 15rem minmax(0, 1fr); align-items: start; }
  .article-toc { position: sticky; top: 5.5rem; }
}
.article-toc {
  border: 1px solid var(--rule); border-radius: var(--radius);
  padding: var(--sp-2) var(--sp-3); font-size: var(--t-small);
}
.article-toc strong {
  display: block; font-family: var(--f-mono); font-size: 0.72rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-2);
  margin-bottom: 0.6rem; font-weight: 500;
}
.article-toc ol { list-style: none; margin: 0; padding: 0; }
.article-toc li { margin: 0.45rem 0; }
.article-toc a { text-decoration: none; color: var(--text); }
.article-toc a:hover { color: var(--accent); }
.article-body { max-width: 44rem; }
.article-body h2 { font-size: var(--t-h2); margin-top: var(--sp-4); scroll-margin-top: 6rem; }
.article-body h3 { margin-top: var(--sp-3); scroll-margin-top: 6rem; }
.article-body figure { margin: var(--sp-3) 0; }
.article-body figcaption {
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-2); padding-top: 0.6rem;
}
.article-body img { border-radius: var(--radius); }
.article-body blockquote {
  margin: var(--sp-3) 0; padding-left: var(--sp-3);
  border-left: 2px solid var(--accent);
  font-family: var(--f-serif); font-style: italic; font-size: 1.2rem; line-height: 1.5;
}

/* key-facts panel (data sidebar block) */
.fact-panel {
  background: var(--surface-feature); color: var(--on-feature); border-radius: var(--radius);
  padding: var(--sp-3); margin: var(--sp-3) 0;
}
.fact-panel h2, .fact-panel h3 { color: var(--on-feature); font-size: 1rem; letter-spacing: 0.02em; }
.fact-panel dl { margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: var(--sp-2); }
.fact-panel dt {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--laguna);
}
.fact-panel dd { margin: 0.15rem 0 0; font-weight: 600; }

/* ---------- FAQ (accessible, CSS-only) ---------- */
.faq-list { border-top: 1px solid var(--rule); }
.faq-list details { border-bottom: 1px solid var(--rule); }
.faq-list summary {
  cursor: pointer; list-style: none; display: flex; justify-content: space-between; gap: var(--sp-2);
  padding: 1.1rem 0.25rem; font-weight: 700; font-size: 1.05rem;
}
.faq-list summary::-webkit-details-marker { display: none; }
.faq-list summary::after {
  content: "+"; font-family: var(--f-mono); color: var(--accent);
  font-size: 1.2rem; line-height: 1.4; flex: none;
  transition: transform 0.25s var(--ease);
}
.faq-list details[open] summary::after { transform: rotate(45deg); }
.faq-list .faq-a { padding: 0 0.25rem 1.25rem; max-width: 60ch; color: var(--text-2); }

/* ---------- Contact form ---------- */
.contact-form { max-width: 34rem; margin-block: var(--sp-3); }
.contact-form p { margin-bottom: var(--sp-2); }
.contact-form label {
  display: block; margin-bottom: 0.4rem;
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-2);
}
.contact-form label span { color: var(--accent); }
.contact-form input,
.contact-form select,
.contact-form textarea {
  width: 100%; padding: 0.8rem 0.9rem;
  font-family: var(--f-body); font-size: var(--t-body); color: var(--text);
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--radius); transition: border-color 0.2s var(--ease);
}
.contact-form input:focus,
.contact-form select:focus,
.contact-form textarea:focus { border-color: var(--accent); }
.contact-form textarea { resize: vertical; }
.contact-form button { cursor: pointer; }

/* --- contact form: the controls the static mockup never had --- */
/* Radio group carries `group` (Solo/Couple/Family/Group), which the handler maps
   to a pax count. It is a fieldset, so the browser default border/padding has to
   be cleared before it matches the other fields. */
.contact-form fieldset { border: 0; padding: 0; margin: 0 0 var(--sp-2); }
.contact-form legend {
  padding: 0; margin-bottom: 0.4rem;
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-2);
}
.contact-form legend span { color: var(--accent); }
.contact-form .form-group { margin-bottom: var(--sp-2); }
.contact-form .form-group--split { display: grid; gap: var(--sp-2); }
@media (min-width: 560px) {
  .contact-form .form-group--split { grid-template-columns: 1fr 1fr; }
}
.contact-form .radio-group { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.contact-form .radio-option {
  /* label is display:block + uppercase mono by default above — this is a chip */
  display: inline-flex; align-items: center; gap: 0.45rem;
  margin: 0; padding: 0.5rem 0.85rem;
  text-transform: none; letter-spacing: 0.02em; font-size: 0.8rem;
  color: var(--text); background: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--radius);
  cursor: pointer; transition: border-color 0.15s var(--ease), background-color 0.15s var(--ease);
}
.contact-form .radio-option:hover { border-color: var(--accent); }
.contact-form .radio-option input { width: auto; padding: 0; margin: 0; accent-color: var(--accent); }
.contact-form .radio-option:has(input:checked) { border-color: var(--accent); background: var(--surface-2); }
.contact-form .radio-option:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Errors: hidden until the handler sets display:block on the specific one. */
.contact-form .error-message {
  display: none; margin-top: 0.35rem;
  font-family: var(--f-mono); font-size: 0.68rem; letter-spacing: 0.02em;
  /* not --ichu/gold: this must clear AA on --glacier as small text */
  color: var(--danger-text);
}
.contact-form .error-input { border-color: var(--danger-text); }

/* Spinner lives inside the submit button; the handler toggles display. */
.contact-form .spinner {
  display: none; width: 0.85em; height: 0.85em; margin-left: 0.6em;
  border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
  animation: form-spin 0.6s linear infinite;
}
@keyframes form-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .contact-form .spinner { animation: none; } }
.contact-form button[disabled] { opacity: 0.6; cursor: not-allowed; }
.contact-form button[disabled]:hover { transform: none; }

/* Shown (display:block) only after a successful POST; the form is hidden then. */
.success-message {
  display: none; max-width: 34rem; margin-block: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-left: 3px solid var(--accent);
  background: var(--surface); color: var(--text);
}

/* ---------- Secondary lead capture (tour sidebar) ----------
   Deliberately QUIETER than the calendar above it: the calendar is the primary
   conversion and this must not out-shout it. Hence --btn--ghost, a hairline top
   rule instead of a filled card, and no accent background. */
.lead-capture {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--rule);
}
.lead-capture h3 {
  margin: 0 0 0.3rem;
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-2);
}
.lead-capture__pitch {
  margin: 0 0 var(--sp-2);
  font-size: 0.82rem; line-height: 1.45; color: var(--text);
}
.lead-capture input {
  width: 100%; margin-bottom: 0.45rem; padding: 0.6rem 0.7rem;
  font-family: var(--f-body); font-size: 0.85rem; color: var(--text);
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--radius); transition: border-color 0.15s var(--ease);
}
.lead-capture input:focus { border-color: var(--accent); outline: none; }
.lead-capture input::placeholder { color: var(--text-2); opacity: 1; }
.lead-capture__row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.45rem; }
.lead-capture__row input { margin-bottom: 0.45rem; }
.lead-capture .btn { width: 100%; justify-content: center; cursor: pointer; }
.lead-capture button[disabled] { opacity: 0.6; cursor: not-allowed; transform: none; }
.lead-capture__err {
  display: none; margin: 0.4rem 0 0;
  font-family: var(--f-mono); font-size: 0.68rem; color: var(--danger-text);
}
.lead-capture__fine {
  margin: 0.5rem 0 0; font-size: 0.68rem; line-height: 1.4; color: var(--text-2);
}
.lead-capture__ok {
  display: none; margin: 0;
  padding: var(--sp-2); border-left: 3px solid var(--accent);
  background: var(--surface); font-size: 0.82rem; line-height: 1.45; color: var(--text);
}

/* ---------- Breadcrumb ---------- */
.breadcrumb { padding-top: var(--sp-3); }
.breadcrumb ol {
  list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem;
  font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.05em;
}
.breadcrumb li + li::before { content: "/"; color: var(--text-2); margin-right: 0.5rem; }
.breadcrumb a { color: var(--text-2); text-decoration: none; }
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb [aria-current="page"] { color: var(--text); }

/* ---------- Testimonials ---------- */
.quote-grid { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); }
.quote {
  border-top: 2px solid var(--laguna); padding-top: var(--sp-2);
}
.quote p {
  font-family: var(--f-serif); font-style: italic; font-size: 1.15rem; line-height: 1.5;
}
.quote footer {
  font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--laguna);
}

/* rating chip */
.rating-chip {
  display: inline-flex; align-items: baseline; gap: 0.6rem;
  font-family: var(--f-mono); font-size: var(--t-small); color: var(--on-feature);
}
.rating-chip strong { font-size: 1.6rem; color: var(--laguna); }

/* ---------- Pre-footer CTA ---------- */
.cta-final { text-align: center; }
.cta-final h2 { font-size: var(--t-h1); max-width: 18ch; margin-inline: auto; text-wrap: balance; }
.cta-final p { max-width: 44ch; margin-inline: auto; }
.cta-final .btn-row { justify-content: center; margin-top: var(--sp-3); }

/* ---------- Footer ---------- */
.site-footer {
  background: var(--surface-feature); color: rgba(239,243,238,0.78);
  padding-block: var(--sp-4); font-size: var(--t-small);
  border-top: 1px solid var(--snow-line-d);
}
.site-footer a { color: rgba(239,243,238,0.9); text-decoration: none; }
.site-footer a:hover { color: var(--laguna); }
.footer-grid { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); margin-bottom: var(--sp-4); }
.footer-grid h2 {
  font-family: var(--f-mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--laguna);
  margin-bottom: var(--sp-2);
}
.footer-grid ul { list-style: none; margin: 0; padding: 0; }
.footer-grid li { margin: 0.5rem 0; }
.footer-legal {
  border-top: 1px solid var(--snow-line-d); padding-top: var(--sp-3);
  display: flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: space-between;
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: rgba(239,243,238,0.55);
}

/* ---------- Reveal animation ---------- */
.js .reveal { opacity: 0; transform: translateY(26px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.js .reveal.is-in { opacity: 1; transform: none; }
.js .reveal[data-reveal-delay="1"] { transition-delay: 0.08s; }
.js .reveal[data-reveal-delay="2"] { transition-delay: 0.16s; }
.js .reveal[data-reveal-delay="3"] { transition-delay: 0.24s; }

/* ---------- Small screens ----------
   The display face is set at wdth 118; at phone widths that pushes long words
   ("MACHU PICCHU") past the viewport. Narrow the width axis and lower the hero
   floor so headlines wrap instead of clipping. */
@media (max-width: 600px) {
  :root { --t-hero: clamp(2rem, 9.2vw, 7rem); }
  .display { font-variation-settings: "wdth" 100; }
  .hero__title { max-width: none; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .js .reveal { opacity: 1; transform: none; }
  .js .profile-line { stroke-dasharray: none; stroke-dashoffset: 0; }
}

/* ---------- Print ---------- */
@media print {
  .site-header, .site-footer, .nav-toggle, .btn, .cta-final { display: none; }
  body { background: #fff; color: #000; }
}

/* ---------- Pricing block (tour pages) ---------- */
.pricebox {
  border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--surface); padding: var(--sp-3); position: relative;
}
.pricebox__badge {
  position: absolute; top: -0.7rem; left: var(--sp-3);
  background: var(--accent-fill); color: var(--on-accent);
  font-family: var(--f-mono); font-size: 0.68rem; letter-spacing: 0.12em;
  text-transform: uppercase; padding: 0.3rem 0.7rem; border-radius: var(--radius);
}
.pricebox__year {
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-2); margin: 0 0 0.2rem;
}
.pricebox__name { font-size: var(--t-h3); margin: 0 0 var(--sp-2); }
.pricebox__display { display: flex; align-items: baseline; gap: 0.8rem; flex-wrap: wrap; }
.pricebox__old {
  font-family: var(--f-mono); font-size: 1.1rem; color: var(--text-2);
  text-decoration: line-through;
}
.pricebox__current { font-family: var(--f-mono); font-size: clamp(2.2rem, 5vw, 3rem); font-weight: 500; line-height: 1; }
.pricebox__note { font-size: var(--t-small); color: var(--text-2); margin: 0.4rem 0 var(--sp-2); }
.pricebox__list { list-style: none; margin: 0 0 var(--sp-2); padding: 0; font-size: var(--t-small); }
.pricebox__list li {
  display: flex; justify-content: space-between; gap: var(--sp-2);
  padding: 0.5rem 0; border-top: 1px solid var(--rule);
}
.pricebox__list b { font-family: var(--f-mono); font-weight: 500; }

/* ---------- Availability calendar (legacy contract) ---------- */
.availability { scroll-margin-top: 6rem; }
.availability .comboHead { display: flex; gap: var(--sp-2); margin-bottom: var(--sp-3); flex-wrap: wrap; }
.availability select {
  padding: 0.7rem 0.9rem; font-family: var(--f-body); font-size: var(--t-body);
  color: var(--text); background: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--radius);
}
.availability #months { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0 0 var(--sp-3); padding: 0; }
.availability #months li a {
  display: block; padding: 0.45rem 0.8rem; border: 1px solid var(--rule);
  border-radius: var(--radius); font-family: var(--f-mono); font-size: var(--t-mono);
  text-decoration: none; color: var(--text);
}
.availability #months li a:hover, .availability #months li a.active { background: var(--accent-fill); color: var(--on-accent); border-color: var(--accent); }
.availability table { border-collapse: collapse; }
.availability #calendario table { width: 100%; }
.availability #calendario td, .availability #calendario th { padding: 0.45rem; text-align: center; font-size: var(--t-small); }
.availability #calendario th { font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.1em; color: var(--text-2); }
.availability .legend { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-2); font-family: var(--f-mono); font-size: var(--t-mono); color: var(--text-2); }
.availability .legend span::before { content: "■ "; }
.availability .legend .is-open::before { color: var(--accent); }
.availability .legend .is-deal::before { color: var(--ichu); }
.availability .legend .is-full::before { color: var(--danger-text); }
.availability noscript p { color: var(--text-2); font-size: var(--t-small); }

/* Horizontal scroll fallback — the injected 7-column grid has no responsive
   collapse of its own, same pattern as .compare-scroll. */
.calendar-scroll { overflow-x: auto; }

/* Day cells — classes are generated by calendar-trek.js/calendar-tour.js
   (renderCell), reused unmodified from the live site; these rules style
   what that module actually outputs, not a redesign of it. */
.availability .availBox {
  cursor: pointer; border-radius: var(--radius);
  transition: background-color 0.2s var(--ease);
}
.availability .availBox:hover { background: var(--surface-2); }
.availability .availBox.soldOut { cursor: default; color: var(--text-2); }
.availability .availBox.soldOut:hover { background: none; }
.availability .resNum { font-family: var(--f-mono); font-weight: 500; display: block; }
.availability .resText { display: block; font-size: 0.68rem; color: var(--text-2); }
.availability .resIns {
  display: block; font-size: 0.62rem; color: var(--accent);
  font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
}
.availability .status-dot {
  display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%;
  margin: 0.25rem auto; background: var(--text-2);
}
/* same three colors as .legend above — open/deal/full */
.availability .dot-available { background: var(--accent-fill); }
.availability .dot-discount { background: var(--ichu); }
.availability .dot-unavailable { background: var(--danger-text); }

/* calendario2 (detailed view) is not wired into the current booking section
   but renderCell() emits it from the same module — styled for parity. */
.availability .price-old { font-family: var(--f-mono); font-size: 0.75rem; color: var(--text-2); text-decoration: line-through; }
.availability .price-sale { font-family: var(--f-mono); font-weight: 500; }
.availability .price-sale.xsale { color: var(--ichu); }
.availability .goto-book { margin-top: 0.4rem; }
.availability .goto-book button {
  font: inherit; font-weight: 700; font-size: var(--t-small); cursor: pointer;
  background: var(--accent-fill); color: var(--on-accent); border: none;
  border-radius: var(--radius); padding: 0.5rem 0.9rem;
  transition: background-color 0.25s var(--ease);
}
.availability .goto-book button:hover { background: var(--invert-bg); }

/* Fetch-failure fallback — module's own markup (showError), styled here only */
.calendar-error {
  text-align: center; padding: var(--sp-4) var(--sp-3);
  border: 1px dashed var(--rule); border-radius: var(--radius);
}
.calendar-error p { color: var(--text-2); margin: 0 0 var(--sp-2); }
.calendar-error button {
  font: inherit; font-weight: 700; font-size: var(--t-small); cursor: pointer;
  padding: 0.75rem 1.5rem;
  background: var(--accent-fill); color: var(--on-accent); border: none;
  border-radius: var(--radius);
  transition: background-color 0.25s var(--ease);
}
.calendar-error button:hover { background: var(--invert-bg); }

/* ---------- Embedded scroll-scrub ---------- */
.scrub { position: relative; height: 260vh; background: var(--puna); }
.scrub__stage { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; }
.scrub__canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.scrub__stage::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(15,31,23,.55) 0%, rgba(15,31,23,.15) 45%, rgba(15,31,23,.85) 100%);
}
.scrub__hud {
  position: absolute; top: clamp(1.5rem, 4vw, 2.5rem); left: clamp(1.5rem, 4vw, 3rem); z-index: 2;
  font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.14em;
  text-transform: uppercase; color: rgba(239,243,238,.75);
}
.scrub__hud b { display: block; font-size: clamp(1.8rem, 4vw, 2.6rem); font-weight: 500; color: var(--laguna); letter-spacing: 0.02em; }
.scrub__cap {
  position: absolute; z-index: 2; left: clamp(1.5rem, 4vw, 3rem); bottom: clamp(3rem, 10vh, 6rem);
  max-width: min(30rem, 78vw); margin: 0; color: var(--on-feature);
  opacity: 0; transform: translateY(18px);
  transition: opacity .5s var(--ease), transform .5s var(--ease);
}
.scrub__cap .m {
  font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--laguna); display: block; margin-bottom: 0.5rem;
}
.scrub__cap h3 { font-size: var(--t-h2); margin: 0 0 0.4rem; }
.scrub__cap p { font-size: 1.05rem; color: rgba(239,243,238,.85); margin: 0; }
/* ---- Static fallback: reduced motion, and the manifest-fetch failure ----
   The three captions SHARE ONE absolutely-positioned slot and are cross-faded
   by render() as you scroll. Two bugs lived here:

   1. The old reduced-motion rule was
        .scrub__cap { opacity: 1 !important; transform: none !important; }
      which forced every caption visible WITHOUT taking it out of the shared
      slot — so all three painted on top of each other. Reported on the 5-day
      tour page 2026-08-27 and reproduced at every viewport width; it is only
      visible with "Reduce motion" enabled, which is why it survived review.
   2. `.scrub--failed` left the captions at opacity 0, so the fetch-failure
      mode showed a blank panel with no text at all.

   Both states now collapse the section into ordinary flow: one poster frame,
   then the captions stacked as readable blocks. No motion in either. */
.scrub--failed,
.scrub--static { height: auto; }
.scrub--failed .scrub__stage,
.scrub--static .scrub__stage { position: static; height: auto; min-height: 0; overflow: visible; }
.scrub--failed .scrub__canvas,
.scrub--static .scrub__canvas { position: relative; height: clamp(220px, 45vh, 460px); }
.scrub--failed .scrub__stage::after,
.scrub--static .scrub__stage::after { display: none; }
.scrub--failed .scrub__hud,
.scrub--static .scrub__hud { position: static; padding: clamp(1.5rem, 4vw, 2.5rem) clamp(1.5rem, 4vw, 3rem) 0; }
.scrub--failed .scrub__cap,
.scrub--static .scrub__cap {
  position: static; opacity: 1; transform: none; transition: none;
  max-width: 44rem; margin: 1.75rem clamp(1.5rem, 4vw, 3rem) 0;
}
.scrub--failed .scrub__cap:last-of-type,
.scrub--static .scrub__cap:last-of-type { margin-bottom: clamp(2rem, 6vw, 3.5rem); }

/* ==========================================================================
   Footer night sky
   Ported from the legacy salkantay footer (_footermain.scss) but rebuilt for
   cost. Three deliberate departures from the original:

   1. TRANSFORM-ONLY shooting stars. The legacy keyframes animated `width`
      (tail 0->100px->0, shining 0->30px->0) on an infinite loop — a layout
      pass every frame, forever. Here one keyframe animates translate3d+scaleX,
      which stays on the compositor. The glow is baked into the gradient rather
      than a live drop-shadow() filter, which would repaint per frame.
   2. content-visibility on the sky. The tour pages run to ~18,000px, so the
      footer is off-screen ~97% of the time; without this the animation burns
      main thread for an audience of nobody. contain-intrinsic-size keeps the
      collapsed box from causing scrollbar jump.
   3. Retinted to --laguna. The original glow (#5f91ff) was picked for a navy
      #10354b footer; on --puna green-black it reads as a foreign accent.
      --laguna is already the footer's heading colour, and it matches the
      turquoise of the lake in the ridge illustration.
   ========================================================================== */

.site-footer { position: relative; overflow: hidden; isolation: isolate; }
.site-footer > .wrap { position: relative; z-index: 2; }

.footer-sky { display: none; }

@media (min-width: 768px) {
  /* Full-height night panel. Scoped to the same breakpoint as the sky: below 768px
     the sky is display:none, and a 100vh footer with nothing in it is just dead
     scroll. svh (not vh) so mobile browser chrome can't overshoot the viewport. */
  .site-footer {
    min-height: 100svh;
    display: flex; flex-direction: column; justify-content: center;
    padding-block: var(--sp-5);
  }
  /* .wrap centres itself with margin-inline:auto. As a flex item those auto margins
     beat align-items:stretch, so it collapsed to fit-content (926px vs the header's
     1200px) and auto-fit dropped the grid from 4 columns to 3 + an orphan.
     width:100% restores the stretch the rest of the site's .wrap relies on. */
  .site-footer > .wrap { width: 100%; }

  .footer-sky {
    display: block;
    position: absolute; inset: 0; z-index: 0;
    pointer-events: none;
    /* NO content-visibility here. It was added to stop the animation burning main
       thread while the footer sat off-screen — but the transform-only rewrite already
       made that cost zero (measured: 0 layouts, 0 style recalcs over 8s), so it was
       guarding against a cost that no longer exists. In exchange it produced a
       reported freeze: scroll away and back and the streaks show a stale frame,
       because skipped content stops painting while the animation timeline keeps
       running. Not reproducible headlessly, but it is the only viewport-dependent
       thing here and the perf it bought is already banked elsewhere. */
  }

  /* --- star field: parent-opacity twinkle, staggered so layers never blink together --- */
  .footer-sky .stars {
    position: absolute; inset: 0;
    fill: #fff;
    /* base < 1 so no star is pure white: at full opacity a handful of 1px specks
       landed in the link band and measured under 4.5 against the text. 24 isolated
       pixels is not a real legibility fault, but it costs nothing to remove. */
    opacity: 0.75;
    animation: sky-twinkle 4s ease-in-out infinite;
  }
  .footer-sky .stars:nth-child(2) { animation-delay: -1.32s; }
  .footer-sky .stars:nth-child(3) { animation-delay: -2.64s; }
  .footer-sky .stars circle:nth-child(3n)  { opacity: 0.8; }
  .footer-sky .stars circle:nth-child(7n)  { opacity: 0.6; }
  .footer-sky .stars circle:nth-child(13n) { opacity: 0.4; }
  .footer-sky .stars circle:nth-child(19n) { opacity: 0.25; }

  @keyframes sky-twinkle { 25% { opacity: 0; } }

  /* --- shooting stars --- */
  .footer-sky .shooting {
    position: absolute; top: 0; left: 0;
    width: 70%; height: 60%;
    transform: rotate(140deg);
    transform-origin: 50% 50%;
  }
  .footer-sky .shooting i {
    position: absolute;
    width: 100px; height: 2px;
    transform-origin: 100% 50%;
    will-change: transform;
    /* glow baked into the gradient — a live drop-shadow() would repaint every frame */
    background: linear-gradient(-45deg, var(--laguna), rgba(63,193,182,0.35) 40%, rgba(63,193,182,0));
    border-radius: 2px;
    /* linear, NOT ease-in-out. CSS applies a timing function between EVERY pair of
       keyframes, not once across the animation — with stops at 0/30/60/100 an
       ease-in-out made the streak decelerate to a near-stop twice mid-flight
       (measured: 0.41 and 0.24 px/step against a 7.11 peak) and lurch across the
       sky in three bursts. Linear + proportionally-spaced translate stops gives one
       constant-velocity flight, which is what a meteor actually looks like. */
    animation: sky-shoot 4s linear infinite;
  }
  .footer-sky .shooting i:nth-child(1) { top: 18%; left: 12%; animation-delay: 2s; }
  .footer-sky .shooting i:nth-child(2) { top: 62%; left: 34%; animation-delay: 3.6s; }
  .footer-sky .shooting i:nth-child(3) { top: 40%; left: 8%;  animation-delay: 1.1s; }
  .footer-sky .shooting i:nth-child(4) { top: 76%; left: 26%; animation-delay: 2.9s; }

  /* Every translate stop is exactly 320px x its own percentage, so linear timing
     yields dead-constant velocity. The tail (scaleX) and fade ride along on the
     same keyframes without perturbing the travel. */
  @keyframes sky-shoot {
    0%   { transform: translate3d(0, 0, 0)       scaleX(0);   opacity: 0; }
    8%   { transform: translate3d(25.6px, 0, 0)  scaleX(0.7); opacity: 1; }
    20%  { transform: translate3d(64px, 0, 0)    scaleX(1);   opacity: 1; }
    62%  { transform: translate3d(198.4px, 0, 0) scaleX(1);   opacity: 0.85; }
    100% { transform: translate3d(320px, 0, 0)   scaleX(0);   opacity: 0; }
  }

  /* --- ridge illustration: a horizon UNDER the content, not a backdrop behind it.
     Measured first: at full height/0.55 opacity a link crossing the pale rock scored
     3.14:1 against --glacier text, under the 4.5 AA floor. Two fixes, both needed —
     cap the height so only the ridgeline shows, and lay a scrim over it so text
     contrast no longer depends on which part of the illustration it lands on. --- */
  .footer-sky .footer-ridge {
    position: absolute; bottom: 0; left: 0;
    width: 100%; height: 38vh;
    object-fit: cover; object-position: 50% 12%;
    opacity: 0.85;
    /* The legibility problem is specifically the SNOW (#FFF / #E5E2DF): even at low
       opacity it composites to ~rgb(136,144,140) and drops link contrast to 2.9:1.
       Uniform fading kills the whole illustration to fix one tonal band, so crush
       the highlights instead — brightness() keeps the ridgeline shape readable
       while taking the snow down to something text can sit on. */
    filter: brightness(0.30) saturate(0.55);
  }

  /* The legal strip sits lowest, where the ridge is brightest. Measured: over the
     lightest backdrop it actually lands on (rgb 60,64,63) the base 0.55 alpha gives
     4.07 — just under AA. 0.75 gives 6.08 with headroom, and is scoped to the
     desktop breakpoint where the ridge exists at all. */
  .site-footer .footer-legal { color: rgba(239,243,238,0.75); }

  .footer-sky::after {
    content: ""; position: absolute; inset: 0; z-index: 1;
    background: linear-gradient(to bottom,
      rgba(15,31,23,0.35) 0%,
      rgba(15,31,23,0.20) 60%,
      rgba(15,31,23,0.10) 100%);
  }
}

/* The award CSS already gates motion elsewhere; the sky is decoration, so it
   goes fully static rather than merely slower. */
@media (prefers-reduced-motion: reduce) {
  .footer-sky .stars,
  .footer-sky .shooting i { animation: none; }
  .footer-sky .shooting i { transform: scaleX(1); opacity: 0.5; }
}

/* ---------- Availability as a sticky sidebar ----------
   Content left, live calendar right, pinned while the itinerary scrolls. The
   calendar keeps every id the production module resolves by getElementById —
   this is purely a layout change around unchanged nodes. */
.booking-layout { display: grid; gap: var(--sp-4); }
@media (min-width: 1024px) {
  /* align-items MUST stay stretch here. Copied from .article-layout it was `start`,
     which collapses the <aside> to its content height — so sticky's containing block
     was 446px tall around a 446px box, giving it zero travel and making
     position:sticky completely inert (measured: inner top tracked the scroll 1:1 at
     -300/-700/-1200px instead of clamping at 88px). Stretching the aside to the row
     height (8417px of article) is what gives the calendar something to stick within. */
  .booking-layout { grid-template-columns: minmax(0, 1fr) 25rem; align-items: stretch; }
  .booking-side__inner { position: sticky; top: 5.5rem; }
}
.booking-side__inner {
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--sp-3);
}
.booking-side .eyebrow { margin-bottom: 0.35rem; }
.booking-side h2 {
  font-family: var(--f-mono); font-size: 0.82rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent);
  margin: 0 0 var(--sp-2);
}
/* ---- month rail (state 1: the chooser) ----
   The module shows this rail, then hides it and reveals the grid on pick. At
   sidebar width the inherited full-width flex-wrap left a ragged 15-card block
   315px tall with uneven widths; an even 3-col grid reads as a picker. */
.booking-side #months {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.3rem;
  list-style: none; margin: 0; padding: 0;
}
.booking-side #months li { margin: 0; }
.booking-side #months a {
  display: block; text-align: center;
  font-family: var(--f-mono); font-size: 0.66rem; line-height: 1.25; letter-spacing: 0.02em;
  padding: 0.42rem 0.2rem;
  border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--surface); color: var(--text); text-decoration: none;
  transition: background-color 0.15s var(--ease), border-color 0.15s var(--ease), color 0.15s var(--ease);
}
.booking-side #months a:hover,
.booking-side #months a:focus-visible {
  background: var(--accent-fill); border-color: var(--accent); color: var(--on-accent);
}

/* ---- month/year selects (state 2: the controls) ----
   These were native appearance:auto — OS chrome in the middle of an otherwise
   token-driven panel. Restyled with the award's own border/radius/mono and a
   drawn chevron; month takes the room, year takes what it needs. */
.booking-side .comboHead { display: grid; grid-template-columns: 1fr auto; gap: 0.4rem; margin-bottom: var(--sp-2); }
.booking-side select {
  appearance: none; -webkit-appearance: none;
  width: 100%; padding: 0.5rem 1.8rem 0.5rem 0.6rem;
  font-family: var(--f-mono); font-size: 0.74rem; letter-spacing: 0.03em;
  color: var(--text); background-color: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--radius);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23166F68' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.6rem center; background-size: 0.6rem;
  cursor: pointer;
}
.booking-side select:hover { border-color: var(--accent); }
.booking-side select:focus-visible { outline: 2px solid var(--laguna-ink); outline-offset: 1px; }

/* ---- calendar grid ----
   Cell borders were a flat 1px #55645B on every edge — a heavy utility grid in a
   panel where every other line is a hairline token. */
.booking-side #calendarSalidas { width: 100%; table-layout: fixed; border-collapse: collapse; }
.booking-side #calendarSalidas th,
.booking-side #calendarSalidas td { border: 1px solid var(--rule); }
.booking-side #calendarSalidas th { font-size: 0; padding: 0.3rem 0; background: var(--surface); }
.booking-side #calendarSalidas th::after { font-family: var(--f-mono); font-size: 0.6rem; letter-spacing: 0.06em; color: var(--text-2); }
.booking-side #calendarSalidas th:nth-child(1)::after { content: "S"; }
.booking-side #calendarSalidas th:nth-child(2)::after { content: "M"; }
.booking-side #calendarSalidas th:nth-child(3)::after { content: "T"; }
.booking-side #calendarSalidas th:nth-child(4)::after { content: "W"; }
.booking-side #calendarSalidas th:nth-child(5)::after { content: "T"; }
.booking-side #calendarSalidas th:nth-child(6)::after { content: "F"; }
.booking-side #calendarSalidas th:nth-child(7)::after { content: "S"; }
.booking-side #calendarSalidas td { padding: 0.35rem 0.1rem; font-size: 0.78rem; text-align: center; }
.booking-side #calendarSalidas td.availBox {
  background: var(--surface); cursor: pointer;
  transition: background-color 0.15s var(--ease);
}
.booking-side #calendarSalidas td.availBox:hover { background: var(--accent-fill); }
.booking-side #calendarSalidas td.availBox:hover .resNum,
.booking-side #calendarSalidas td.availBox:hover .resText { color: var(--on-feature); }
/* Hierarchy: the day number was --ink at weight 600 — the loudest thing in the
   grid, while carrying the least decision value (every cell has one). What you
   actually scan for is "which dates can I book", which was the quietest layer.
   So the number steps back to --stone, and the state dot steps forward. */
.booking-side #calendarSalidas .resNum {
  font-weight: 500; display: block; line-height: 1.2; color: var(--text-2);
}
.booking-side #calendarSalidas td.availBox .resNum { color: var(--text-2); }
.booking-side #calendarSalidas .status-dot { width: 7px; height: 7px; margin: 0.2rem auto; }
/* "Available" repeated in ~20 cells. Setting it as an uppercase badge made it WIDER
   and MORE prominent — the opposite of the goal in a 48px cell. So it becomes
   screen-reader-only, and the state is carried visually by dot SHAPE as well as
   colour, which is what WCAG 1.4.1 actually asks for (colour must not be the sole
   cue) — not by repeating a word in every cell. The legend below maps the shapes. */
.booking-side #calendarSalidas .resText {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.booking-side #calendarSalidas .status-dot { border-radius: 50%; }
.booking-side #calendarSalidas .dot-discount { border-radius: 1px; transform: rotate(45deg); }
.booking-side #calendarSalidas .dot-unavailable { border-radius: 1px; height: 2px; width: 9px; }
/* legend swatches mirror the cell shapes, so the mapping is learnable */
.booking-side .legend span { display: inline-flex; align-items: center; gap: 0.3rem; }
.booking-side .legend span::before { content: ""; width: 7px; height: 7px; display: inline-block; }
.booking-side .legend .is-open::before { border-radius: 50%; background: var(--accent-fill); }
.booking-side .legend .is-deal::before { border-radius: 1px; transform: rotate(45deg); background: var(--ichu); }
.booking-side .legend .is-full::before { border-radius: 1px; height: 2px; width: 9px; background: var(--danger-text); }
.booking-side #calendarSalidas .resIns,
.booking-side #calendarSalidas .goto-book,
.booking-side #calendarSalidas .rango-fecha { display: none; }
/* Past-date cells carry a day number plus five <br> spacers the legacy renderer
   emits to pad them to booked-cell height — 786px of table in a 400px column. */
/* Trailing/leading blanks stretch to the row's tallest booked cell, so a bordered
   empty box hung off the last week. They are not days — drop their rule. */
.booking-side #calendarSalidas td:empty { padding: 0; height: 1.4rem; border-color: transparent; }
.booking-side #calendarSalidas td:not(.availBox) br { display: none; }
.booking-side #calendarSalidas td:not(.availBox) {
  height: 1.9rem; padding: 0.2rem 0; font-size: 0.72rem; color: var(--text-2); opacity: 0.5;
}
.booking-side .legend { font-size: 0.62rem; margin-top: var(--sp-2); display: flex; flex-wrap: wrap; gap: 0.6rem; }

/* ==========================================================================
   Landing page (/salkantay-trek/) — standalone conversion surface.
   Uses the same tokens as the rest of the award site so the body can be
   dropped into lib.mjs's page() shell later without restyling.
   ========================================================================== */

/* --- minimal bar: no nav, so no exits --- */
.lp-bar { border-bottom: 1px solid var(--rule); background: var(--surface); }
.lp-bar__in { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); padding-block: 0.9rem; }
.lp-bar__brand {
  font-family: var(--f-display); font-weight: 700; letter-spacing: 0.02em;
  font-size: 1.05rem; color: var(--text); text-decoration: none;
}
.lp-bar__brand span { color: var(--accent); }
/* the LP bar is shorter than the site header, so the lockup runs a size down */
.lp-bar__brand svg { height: 2.4rem; }
@media (max-width: 480px) { .lp-bar__brand svg { height: 2rem; } }
.lp-bar__contact { margin: 0; display: flex; gap: var(--sp-2); font-family: var(--f-mono); font-size: 0.74rem; }
.lp-bar__contact a { white-space: nowrap; }
/* At 390px the brand + a full US number + "WhatsApp" do not fit on one line and
   the number wraps mid-digits. Shrink the bar type rather than dropping a
   contact route — both ARE conversions for someone who would rather talk. */
@media (max-width: 480px) {
  .lp-bar__in { gap: 0.5rem; }
  .lp-bar__brand { font-size: 0.9rem; }
  .lp-bar__contact { gap: 0.6rem; font-size: 0.62rem; }
}
.lp-bar__contact a { color: var(--text-2); text-decoration: none; }
.lp-bar__contact a:hover { color: var(--accent); }

/* --- hero: promise, proof, one primary action --- */
.lp-hero { padding-block: var(--sp-5); background: var(--surface-2); }
.lp-hero h1 { margin: 0.2rem 0 var(--sp-2); }
.lp-hero .serif-lede { max-width: 46ch; }
.lp-cta-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: var(--sp-3) 0 0; }

/* Trust strip. Numbers only — every one is sourced from published site content. */
.lp-trust {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-2);
  list-style: none; margin: var(--sp-4) 0 0; padding: var(--sp-3) 0 0;
  border-top: 1px solid var(--rule);
}
@media (min-width: 720px) { .lp-trust { grid-template-columns: repeat(4, 1fr); } }
.lp-trust strong { display: block; font-family: var(--f-display); font-size: 1.5rem; line-height: 1.1; color: var(--text); }
.lp-trust span { font-family: var(--f-mono); font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-2); }

.lp-section { padding-block: var(--sp-5); }
.lp-section--tint { background: var(--surface-2); }
.lp-section h2 { margin-top: 0; }
.lp-sub { max-width: 56ch; color: var(--text-2); margin-bottom: var(--sp-3); }

.lp-points { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.lp-points h3 {
  margin: 0 0 0.35rem; font-family: var(--f-mono); font-size: 0.72rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent);
}
.lp-points p { margin: 0; font-size: var(--t-small); line-height: 1.55; }

/* Calendar wrapper: the sidebar rules are scoped to .booking-side, which the
   markup keeps, so the calendar renders identically here. Centred and capped
   because on a landing page it is the CENTREPIECE, not a rail. */
.lp-cal { max-width: 27rem; margin-inline: auto; }
.lp-cal .booking-side__inner { position: static; }

.lp-reviews { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }
.lp-review { margin: 0; border-top: 2px solid var(--laguna); padding-top: var(--sp-2); }
.lp-review blockquote { margin: 0; }
.lp-review p { font-family: var(--f-serif); font-style: italic; font-size: 1.05rem; line-height: 1.5; margin: 0; }
.lp-review figcaption {
  margin-top: 0.6rem; font-family: var(--f-mono); font-size: 0.68rem;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-2);
}

.lp-capture { max-width: 26rem; margin-inline: auto; border-top: 0; padding-top: 0; }
.lp-capture h3 { text-align: center; }
.lp-capture .lead-capture__pitch { text-align: center; }

.lp-faq { border-bottom: 1px solid var(--rule); }
.lp-faq summary {
  cursor: pointer; padding: var(--sp-2) 0; font-weight: 600; line-height: 1.4;
  list-style: none;
}
.lp-faq summary::-webkit-details-marker { display: none; }
.lp-faq summary::after { content: "+"; float: right; color: var(--accent); font-family: var(--f-mono); }
.lp-faq[open] summary::after { content: "\2212"; }
.lp-faq div { padding-bottom: var(--sp-2); }
.lp-faq p { margin: 0; max-width: 68ch; color: var(--text-2); font-size: var(--t-small); line-height: 1.6; }

.lp-final { padding-block: var(--sp-5); background: var(--surface-feature); color: var(--on-feature); text-align: center; }
.lp-final h2 { color: var(--on-feature); max-width: 22ch; margin-inline: auto; }
.lp-final p { color: rgba(239,243,238,0.85); }
.lp-final .lp-cta-row { justify-content: center; }
.lp-final .btn--ghost { color: var(--on-feature); border-color: currentColor; }
.lp-final .btn--ghost:hover { background: var(--on-feature); color: var(--puna); }

.lp-foot { padding-block: var(--sp-3); background: var(--surface); border-top: 1px solid var(--rule); }
.lp-foot p { margin: 0.2rem 0; font-family: var(--f-mono); font-size: 0.68rem; color: var(--text-2); }
.lp-foot a { color: var(--text-2); }

/* Sticky mobile CTA: on a phone the hero button scrolls away long before the
   calendar arrives, so the primary action follows the visitor. Desktop keeps
   the in-flow CTAs and hides this. */
.lp-sticky { display: none; }
@media (max-width: 719px) {
  .lp-sticky {
    display: block; position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    padding: 0.6rem var(--gutter) calc(0.6rem + env(safe-area-inset-bottom));
    background: rgba(239,243,238,0.94); backdrop-filter: blur(6px);
    border-top: 1px solid var(--rule);
  }
  .lp-sticky .btn { width: 100%; justify-content: center; }
  /* keep the sticky bar from covering the final CTA */
  .lp-foot { padding-bottom: 4.5rem; }
}
@media (prefers-reduced-motion: reduce) { .lp-sticky { backdrop-filter: none; } }

/* ==========================================================================
   DARK MODE
   Implemented by REMAPPING ROLES, not by re-pointing pigments. Every pigment
   above keeps its value in both schemes; only the role -> pigment mapping
   changes here. That is what makes the rest of the stylesheet scheme-agnostic:
   a rule says --text or --surface-feature and is correct either way.
   ========================================================================== */
@media (prefers-color-scheme: dark) {
  :root {
    --surface:         var(--puna);
    --surface-2:       var(--puna-2);

    /* The emphasis section separates today by dropping to --puna against light
       paper (15.24:1). In dark the page IS --puna, so the same value would put
       it at 1.00:1 — invisible. It becomes a RAISED surface: 1.10:1, the same
       margin the light theme already trusts between --glacier and --glacier-2
       (1.09:1). Once the page is at the floor, lighter is the only direction
       emphasis can go. */
    --surface-feature: var(--puna-2);
    --surface-feature-2: var(--puna-3);

    --text:            var(--glacier);
    --text-2:          var(--stone-d);

    /* --laguna-ink is text-safe on glacier (5.34) and fails on puna (2.85);
       --laguna is the reverse (1.97 / 7.74). The palette documented --laguna as
       "on dark only" from the start. */
    --accent:          var(--laguna);
    --accent-fill:     var(--laguna);

    /* --accent-fill flips from a DARK teal to a LIGHT one, so the ink on it has
       to flip too. This is why --on-accent exists separately from --on-feature:
       a feature surface is dark in both schemes and its ink never flips. */
    --on-accent:       var(--puna);

    --rule:            var(--snow-line-d);
    --invert-bg:       var(--glacier);
    --invert-text:     var(--puna);
    --danger-text:     var(--danger-d);

    /* The page itself is now a dark surface, so the brand needs the same
       repaint the dark SECTIONS already get (see the --logo-word note above).
       Without this the wordmark keeps its light-surface teal and renders at
       2.85:1 against --puna — measured from the rendered header, not computed:
       it fails WCAG 1.4.11 (3:1) on every page in dark mode. */
    --logo-word:       var(--glacier);
    --logo-mark:       var(--laguna);

    color-scheme: dark;
  }

  /* The one rule dark mode needs beyond the remap. The raised fill separates at
     1.10:1, which is real but reads far quieter than the light theme's drop to
     night; an explicit edge states the boundary the fill can only imply. Drawn
     with --rule, so it is the same hairline the design uses everywhere else and
     it tracks the scheme by itself.

     No `.section--dark + .section--dark` collapse rule: checked the live DOM
     across 7 pages and there is not one adjacent pair, so it would guard a case
     that does not exist. If two ever become siblings their hairlines will stack
     into a 2px seam — add it then. */
  .section--dark,
  .lp-final { border-block: 1px solid var(--rule); }
  /* .lp-foot draws its own border-top; a bottom edge here would make a 2px seam. */
  .lp-final { border-bottom: 0; }

  /* Photographs carry their own light. A slight knock-down stops them glaring
     out of a dark page — taste, and the first thing to revert if it reads muddy. */
  .card img, .article-body img, .quote-grid img { filter: brightness(0.92); }
}

/* ---------- Byline (authorship + review date) ----------
   Rendered on Article pages from the same data the Article schema carries, so
   the two can never disagree. Deliberately quiet: it is a trust signal, not a
   headline — it sits under the lede at small mono caps, the way the rest of the
   instrument furniture on this site does. */
.byline {
  margin-top: var(--sp-2);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.35rem 0.9rem;
  font-family: var(--f-mono);
  font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-2);
}
.byline a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.byline a:hover { color: var(--accent); }
/* The credential line is the least urgent of the three and drops out where
   there is no room for it — the author and the date are what carry the signal.
   It is NOT dimmed to say so: --text-2 is 5.57:1 on glacier and an 0.85 opacity
   composited that to 4.06:1. Being third in a small mono row is enough. */
@media (max-width: 520px) {
  .byline { gap: 0.25rem 0.7rem; font-size: 0.68rem; }
  .byline__cred { display: none; }
}
/* No .article-hero override here on purpose. That hero is TRANSPARENT — it sits
   on the page surface (glacier in light, puna in dark), so --text-2 already
   resolves correctly for both. An earlier version pinned it to --stone-d on the
   assumption the hero was a dark plate in both schemes; measured, that put the
   byline at 2.11:1 on the light page. */

/* ---------- Blog sidebar rail (TOC + promo) ----------
   Only the blog uses this. The /guide/ articles share .article-layout and have
   no promo, so the rail is a modifier rather than a change to the base class. */
.article-rail { display: flex; flex-direction: column; gap: var(--sp-3); }
@media (min-width: 1000px) {
  /* Sticky moves from the TOC to the rail so the promo travels with it. The
     inner sticky is released, or the two would fight for the same offset. */
  .article-layout--rail .article-toc { position: static; }
  .article-layout--rail .article-rail { position: sticky; top: 5.5rem; }

  /* Wider than the guide articles. The rail carries a promo as well as a TOC,
     so 15rem squeezed it (the fact rows wrapped), and the body column needs to
     hold a full-width 800-unit infographic without letterboxing it. Scoped to
     --rail so the /guide/ articles keep their reading measure. */
  .article-layout--rail { grid-template-columns: 18rem minmax(0, 1fr); }
  .article-layout--rail .article-body { max-width: 52rem; }
}
@media (min-width: 1240px) {
  /* Past this width the wrap itself is the constraint, not the columns. */
  .article-layout--rail { max-width: 1340px; }
}

.promo {
  border: 1px solid var(--rule); border-radius: var(--radius);
  padding: var(--sp-3);
  background: var(--surface-2);
}
.promo__meta {
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--accent); margin: 0 0 0.4rem;
}
.promo__title { font-size: var(--t-h3); margin: 0 0 0.5rem; }
.promo__body { font-size: var(--t-small); color: var(--text-2); margin: 0 0 var(--sp-2); }
.promo__facts { list-style: none; margin: 0 0 var(--sp-2); padding: 0; font-size: var(--t-small); }
/* Stacked, not space-between. The rail is 15rem, and two columns forced
   "deposit per / person" and "No / permit" onto two lines each. The value reads
   first and the label runs on after it. */
.promo__facts li {
  padding: 0.45rem 0; border-top: 1px solid var(--rule); color: var(--text-2);
}
.promo__facts strong { margin-right: 0.35rem; }
.promo__facts strong { color: var(--text); font-family: var(--f-mono); font-weight: 500; }
.promo__cta { letter-spacing: 0.04em; }
/* .btn ships 2rem of side padding, which at the 15rem rail left ~176px for
   "SEE THE TREKS" and wrapped it. The label is right; the padding was. */
.promo__cta { width: 100%; justify-content: center; padding-left: 1rem; padding-right: 1rem; }
/* No opacity here: hierarchy comes from size, and dimming --text-2 has taken
   this file below AA three times already. */
.promo__fine { margin: 0.7rem 0 0; font-size: 0.68rem; line-height: 1.4; color: var(--text-2); }

/* Featured image at the head of a blog article. */
.article-lead { margin: 0 0 var(--sp-3); }
.article-lead img { width: 100%; height: auto; display: block; border-radius: var(--radius); }
/* Inline SVG infographics sit as block figures with the article's own rhythm. */
.article-body > svg { display: block; width: 100%; height: auto; margin: var(--sp-4) 0; }
