/* ==========================================================================
   Onepone Forest Adventure — design system
   Trailhead signage / wayfinding, not SaaS-startup styling.
   ========================================================================== */

/* --- Fonts --------------------------------------------------------------
   Two families, site-wide: Zilla Slab carries headings/titles/display text
   (a serif slab - confident and a little architectural, not decorative),
   Karla carries body copy and UI (nav, buttons, labels, route info strip).
   Loaded from Google Fonts via <link> in every page's <head> — see
   index.html etc. (weights 400/600/700 for Zilla Slab - a slab serif reads
   wrong fake-bolded from a single weight - and 400/500/700 for Karla). If
   self-hosted files are supplied later, replace the <link> tags with
   @font-face rules here instead. */

/* --- Tokens --------------------------------------------------------------- */
:root {
  /* brand palette — three colors, no substitutions */
  --sand: #fcf5e4;
  --moss: #425806;
  --white: #ffffff;

  /* surfaces (semantic aliases onto the palette above) */
  --surface-light: var(--sand);
  --surface-dark: var(--moss);
  --surface-secondary: var(--white);
  --surface-white: var(--white);
  --accent: var(--moss);

  --ink-on-light: var(--moss);
  --ink-on-dark: var(--sand);
  --ink-on-secondary: var(--moss);

  /* white reads as the "contrast" color: button fills, active-state
     accents and focus rings on dark (moss) surfaces. */
  --contrast-on-dark: var(--white);

  --rule: rgba(66, 88, 6, 0.22);
  --rule-on-dark: rgba(255, 255, 255, 0.55);

  /* type families */
  --font-heading: "Zilla Slab", Georgia, "Times New Roman", serif;
  --font-body: "Karla", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Same family as --font-heading - kept as its own token since the hero
     headline/CTA reference it separately from the general heading system,
     not because it's a different typeface anymore. */
  --font-hero: "Zilla Slab", Georgia, "Times New Roman", serif;

  /* type scale — classical proportions, not browser defaults.
     Base 1rem = 16px, roughly a major-third progression (~1.25),
     fluid above the fold so nothing rescales awkwardly on resize. */
  --text-xs: 0.75rem;    /* 12px — captions, footnotes */
  --text-sm: 0.8125rem;  /* 13px — nav, labels (mono runs wide, sized down slightly) */
  --text-base: 1rem;     /* 16px — body */
  --text-md: 1.125rem;   /* 18px — lead paragraphs */
  --text-lg: 1.375rem;   /* 22px — h4 */
  --text-xl: clamp(1.6rem, 1.35rem + 1.1vw, 2.1rem);   /* h3 */
  --text-2xl: clamp(2rem, 1.6rem + 1.8vw, 2.75rem);    /* h2 */
  --text-3xl: clamp(2.5rem, 1.9rem + 2.8vw, 3.75rem);  /* h1 */

  --leading-tight: 1.1;
  --leading-snug: 1.25;
  --leading-normal: 1.55;
  --leading-relaxed: 1.6; /* body copy - Karla is proportional, not fixed-width like the previous mono body font, so it doesn't need 1.75's extra room */

  /* measure — keeps body copy under a comfortable line length. Widened from
     66ch: with Karla (proportional) rather than the original monospace body
     font, 66ch resolved to only ~630px - narrow enough on a 1440px screen
     that a paragraph capped at it (nested inside an already-narrowed
     ~780px section) looked oddly cramped relative to its own section. */
  --measure: 75ch;
  --measure-narrow: 46ch;

  /* spacing scale — 8px grid */
  --space-3xs: 0.25rem;  /* 4px */
  --space-2xs: 0.5rem;   /* 8px */
  --space-xs: 0.75rem;   /* 12px */
  --space-sm: 1rem;      /* 16px */
  --space-md: 1.5rem;    /* 24px */
  --space-lg: 2rem;      /* 32px */
  --space-xl: 3rem;      /* 48px */
  --space-2xl: 4rem;     /* 64px */
  --space-3xl: 6rem;     /* 96px */

  /* layout */
  --content-width: 1240px;
  --content-width-prose: 780px;
  --gutter: var(--space-md);
  --header-height: 76px; /* slim, compact bar — logo is sized to fit within it, not the other way around */

  /* motion */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --duration: 180ms;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration: 0ms;
  }
}

/* --- Reset ----------------------------------------------------------------- */
*, *::before, *::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  color: var(--ink-on-light);
  background: var(--surface-light);
  /* Lets the accessibility panel (js/accessibility.js) fade the whole page
     out/in around a font or color-mode change, instead of an abrupt snap. */
  transition: opacity 220ms ease;
}
body.a11y-fading {
  opacity: 0;
}

img, svg {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
}

ul, ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

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

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- Focus ------------------------------------------------------------------
   Visible everywhere, no outline: none anywhere in this file. Moss is the
   default ring color (sand/white surfaces, ~6-8:1); white overrides on
   dark (moss) surfaces, where moss would disappear into the background —
   white-on-moss is ~8:1, clearing WCAG's 3:1 minimum for UI indicators
   with room to spare. */
:focus-visible {
  outline: 3px solid var(--moss);
  outline-offset: 3px;
}
.surface-dark :focus-visible,
.surface-secondary :focus-visible,
.site-header :focus-visible,
.site-footer :focus-visible,
.hero__overlay :focus-visible,
.intro-overlay :focus-visible,
.skip-link:focus-visible {
  outline-color: var(--contrast-on-dark);
}

/* --- Typography -------------------------------------------------------------- */
h1, h2, h3, h4 {
  margin: 0 0 var(--space-sm);
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: var(--leading-tight);
  color: inherit;
  text-wrap: balance;
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); line-height: var(--leading-snug); }
h3 { font-size: var(--text-xl); line-height: var(--leading-snug); }
h4 {
  font-size: var(--text-lg);
  font-weight: 600;
}

p {
  margin: 0 0 var(--space-sm);
  max-width: var(--measure);
  /* A capped max-width with no auto margins just left-aligns as a narrow
     block inside whatever wider container it sits in - this is the recurring
     "content stuck on the left half of the page" bug across several pages.
     Centering here is the systemic fix: any bare paragraph, anywhere, now
     centers itself as a readable column instead of needing a per-page fix. */
  margin-inline: auto;
  text-align: left;
}

/* Justified body copy on desktop/tablet; justify on a narrow mobile
   column produces uneven, ugly word-spacing, so it stays left-aligned
   below ~600px. */
@media (min-width: 600px) {
  p, dd {
    text-align: justify;
    hyphens: auto;
  }
}

p.lead {
  font-size: var(--text-md);
  line-height: var(--leading-normal);
}

small, .text-sm {
  font-size: var(--text-sm);
}

.font-hero {
  font-family: var(--font-hero);
  font-weight: 700;
}

.text-condensed {
  font-family: var(--font-body);
  font-weight: 700;
}

/* --- Layout helpers ------------------------------------------------------------ */
.wrap {
  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.prose {
  max-width: var(--content-width-prose);
  margin-inline: auto;
}

/* Narrows AND centers a .wrap for text-heavy sections - the same technique
   already proven by .teaser .wrap (home.css) and an inline style formerly on
   the now-deleted legal.html, just promoted to a shared, explicit modifier
   instead of every page
   reinventing it (or, more often, forgetting the margin-inline: auto half of
   it and ending up with a narrow column stuck to the left edge of the wider
   .wrap instead of centered within it). Add alongside .wrap: <div
   class="wrap wrap--prose">. Leave plain .wrap on anything that needs the
   full content width on purpose (image/tile grids, multi-column layouts,
   stat bars) - this is only for single-column reading content. */
.wrap--prose {
  max-width: var(--content-width-prose);
}

/* Page header block: an optional small kicker line + h1 + lead paragraph,
   centered as one column. Previously duplicated near-identically in
   contact.css and visit.css (both missing the centering) - consolidated
   here so every page's intro reads the same way and a future change is a
   one-line edit instead of hunting through every page's own stylesheet. */
.page-intro {
  max-width: var(--content-width-prose);
  margin-inline: auto;
}
.page-intro .text-condensed {
  display: block;
  color: var(--moss);
  margin-bottom: var(--space-3xs);
}

.surface-dark {
  background: var(--surface-dark);
  color: var(--ink-on-dark);
}
.surface-secondary {
  background: var(--surface-secondary);
  color: var(--ink-on-secondary);
}
.surface-white {
  background: var(--surface-white);
  color: var(--ink-on-light);
}

.section {
  padding-block: var(--space-3xl);
}
.section--tight {
  padding-block: var(--space-xl);
}

/* --- Buttons & links -------------------------------------------------------
   .btn is built for use on a dark (moss) surface: white fill so it reads
   as a contrast area rather than blending into the surface, inverting to
   a white outline on hover. .teaser-link is the plain-text equivalent —
   moss on light surfaces, sand-with-white-hover on dark ones. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  padding: var(--space-sm) var(--space-lg);
  background: var(--white);
  color: var(--moss);
  border: 2px solid var(--white);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background var(--duration) var(--ease), color var(--duration) var(--ease), border-color var(--duration) var(--ease);
}
.btn:hover {
  background: transparent;
  color: var(--white);
  border-color: var(--white);
}

/* .btn--outline: a secondary action alongside a primary .btn on the same
   dark surface (e.g. "Book Online" next to the existing "Book on WhatsApp"
   button) - same shape/weight as .btn, but starts in .btn's own hover state
   (transparent, outlined) so the two are clearly not the same action without
   needing a second color. Never applied to .btn itself, so existing WhatsApp
   buttons using plain .btn are completely unaffected by this rule. */
.btn--outline {
  background: transparent;
  color: var(--white);
  border-color: var(--white);
}
.btn--outline:hover {
  background: var(--white);
  color: var(--moss);
  border-color: var(--white);
}

.teaser-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--moss);
  border-bottom: 2px solid var(--rule);
  padding-bottom: 2px;
  transition: border-color var(--duration) var(--ease);
}
.teaser-link:hover {
  border-bottom-color: var(--moss);
}
.surface-dark .teaser-link {
  color: var(--sand);
  border-bottom-color: var(--rule-on-dark);
}
.surface-dark .teaser-link:hover {
  color: var(--white);
  border-bottom-color: var(--white);
}
/* Larger variant for a .teaser-link that needs to visually outweigh the
   sentence it sits inside - .teaser-link's own --text-sm is actually smaller
   than body copy by default (offset only by its bold/uppercase/underline
   treatment), so a link meant to read as a clear call-to-action mid-sentence
   (e.g. "book online" on zipline.html) needs a size bump on top of that, not
   just the existing weight/case treatment alone. Add alongside .teaser-link:
   class="teaser-link teaser-link--lg". */
.teaser-link--lg {
  font-size: var(--text-md);
}

/* ==========================================================================
   Component — hero media carousel
   Full-bleed slide stack for <hero-media>; content set via its
   data-items="[{type,src}]" attribute. See js/hero-media.js.
   ========================================================================== */
hero-media {
  display: block;
  position: absolute;
  inset: 0;
}
.hero-media__slides {
  position: absolute;
  inset: 0;
  /* Only the multi-slide carousel is draggable (drag handlers are only ever
     attached when there's more than one slide) - touch-action still needs
     to allow vertical page scroll even so, only claiming the horizontal
     gesture for the swipe itself. */
  touch-action: pan-y;
  cursor: grab;
}
.hero-media__slides:active {
  cursor: grabbing;
}
.hero-media__slide {
  position: absolute;
  inset: 0;
  transition: transform 800ms var(--ease);
}
.hero-media__el {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Dragging the track shouldn't trigger the browser's native "drag this
     image/video out" affordance or text-selection ghosting mid-swipe. */
  -webkit-user-drag: none;
  user-select: none;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .hero-media__slide {
    transition: none;
  }
}

.hero-media__selector {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--space-md);
  z-index: 3;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--space-xs);
}
/* Small round dots, not the earlier numbered squares - the active one fades
   to a brighter, larger state rather than snapping to a different color. */
.hero-media__dot {
  position: relative;
  width: 10px;
  height: 10px;
  padding: 0;
  border-radius: 50%;
  border: 1.5px solid var(--white);
  background: var(--white);
  opacity: 0.5;
  transform: scale(1);
  transition: opacity var(--duration) var(--ease), transform var(--duration) var(--ease);
}
/* Visual dot stays small; the tappable area doesn't - a 10px target fails
   any touch-target guideline. */
.hero-media__dot::before {
  content: "";
  position: absolute;
  inset: -12px;
}
.hero-media__dot:hover {
  opacity: 0.8;
}
.hero-media__dot.is-active {
  opacity: 1;
  transform: scale(1.35);
}

/* Standard clip-based hidden-but-announced text - e.g. a dot's "Slide N"
   label, present for screen readers without showing visually. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: var(--space-sm);
  top: -48px;
  background: var(--moss);
  color: var(--sand);
  padding: var(--space-2xs) var(--space-sm);
  z-index: 200;
  transition: top var(--duration) var(--ease);
}
.skip-link:focus {
  top: var(--space-sm);
}

/* ==========================================================================
   Site header — trailhead signage
   ========================================================================== */
site-header {
  display: block;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  min-height: var(--header-height);
  background: var(--moss);
  color: var(--sand);
}

/* Announcement ticker - lives inside .site-header (above the bar) so it
   scrolls with the sticky nav as one unit instead of needing its own sticky
   offset math. Brand yellow on moss, same accent already used for the
   Book Now nav item's hover state, so it reads as "pay attention" without
   introducing a new color to the palette. Content/messages configured in
   js/components.js (TICKER_MESSAGES) - not hardcoded here. */
.site-ticker {
  overflow: hidden;
  background: #ffd400;
  white-space: nowrap;
  border-bottom: 1px solid rgba(0, 0, 0, 0.15);
}
.site-ticker__track {
  display: flex;
  width: max-content;
  animation: site-ticker-scroll 22s linear infinite;
}
.site-ticker__item {
  display: inline-flex;
  align-items: center;
  padding-block: var(--space-2xs);
  padding-inline: var(--space-lg);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--moss);
}
@keyframes site-ticker-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .site-ticker__track {
    animation: none;
  }
}

.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  min-height: var(--header-height);
}

.site-header__mark {
  display: flex;
  align-items: center;
  min-width: 0;
}
.site-header__mark img {
  height: 52px;
  width: auto;
}
.site-header--large .site-header__mark img {
  height: 60px;
}

.site-header__nav-toggle {
  display: none;
  align-items: center;
  gap: var(--space-2xs);
  padding: var(--space-2xs) var(--space-xs);
  border: 2px solid var(--rule-on-dark);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.site-header__nav-toggle-icon {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--sand);
  position: relative;
}
.site-header__nav-toggle-icon::before,
.site-header__nav-toggle-icon::after {
  content: "";
  position: absolute;
  left: 0;
  width: 22px;
  height: 2px;
  background: var(--sand);
  transition: transform var(--duration) var(--ease);
}
.site-header__nav-toggle-icon::before { top: -7px; }
.site-header__nav-toggle-icon::after { top: 7px; }
.site-header[data-nav-open="true"] .site-header__nav-toggle-icon {
  background: transparent;
}
.site-header[data-nav-open="true"] .site-header__nav-toggle-icon::before {
  transform: translateY(7px) rotate(45deg);
}
.site-header[data-nav-open="true"] .site-header__nav-toggle-icon::after {
  transform: translateY(-7px) rotate(-45deg);
}

.site-header__nav {
  display: flex;
}
.site-header__links {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  flex-wrap: wrap;
  justify-content: center;
}

/* Desktop convention: logo far left, links centered, icon cluster (the
   mobile-only toggle occupies this slot too) far right. The 1fr/auto/1fr
   split - not flex space-between - is what actually centers the middle
   column on the page: both outer tracks get an equal share of the leftover
   width by definition, regardless of how wide the logo happens to be, so
   the nav doesn't drift off-center when the logo's width changes. Scoped to
   min-width so the mobile accordion layout below is untouched. */
@media (min-width: 861px) {
  .site-header__bar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
  }
  .site-header__mark {
    grid-column: 1;
    justify-self: start;
  }
  .site-header__nav {
    grid-column: 2;
  }
  .site-header__nav-toggle {
    grid-column: 3;
    justify-self: end;
  }
}
.site-header__links a {
  display: inline-block;
  padding: var(--space-2xs) 0;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--sand);
  border-bottom: 2px solid transparent;
}
.site-header__links a:hover {
  border-bottom-color: var(--white);
}
.site-header__links a[aria-current="page"] {
  color: var(--white);
  border-bottom-color: var(--white);
}
.site-header__links a.is-cta {
  color: var(--sand);
  font-weight: 700;
}
.site-header__links a.is-cta:hover {
  border-bottom-color: var(--white);
}
.site-header__links a.is-cta[aria-current="page"] {
  color: var(--white);
}

/* Book Now nav item — outlined, not filled: a white border by default,
   turning the brand yellow (#ffd400, ~5.6:1 against moss — comfortably
   clears the 3:1 UI-component minimum) on hover/active. */
.site-header__links a.is-book-now {
  font-weight: 700;
  border: 2px solid var(--white);
  padding: var(--space-2xs) var(--space-md);
}
.site-header__links a.is-book-now:hover {
  border-color: #ffd400;
}
.site-header__links a.is-book-now[aria-current="page"] {
  border-color: #ffd400;
  color: var(--white);
}

/* "More" dropdown — flies out below the toggle on desktop, folds inline
   into the accordion nav on mobile (see the max-width: 860px block below). */
.site-header__dropdown {
  position: relative;
}
.site-header__dropdown-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  padding: var(--space-2xs) 0;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--sand);
  border-bottom: 2px solid transparent;
}
.site-header__dropdown-toggle::after {
  content: "";
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform var(--duration) var(--ease);
}
.site-header__dropdown-toggle:hover {
  border-bottom-color: var(--white);
}
.site-header__dropdown.is-open .site-header__dropdown-toggle::after {
  transform: rotate(180deg);
}
.site-header__submenu {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 10;
  min-width: 180px;
  margin-top: var(--space-xs);
  background: var(--moss);
  border: 1px solid var(--rule-on-dark);
  padding-block: var(--space-2xs);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity var(--duration) var(--ease), transform var(--duration) var(--ease), visibility var(--duration) var(--ease);
}
.site-header__dropdown.is-open .site-header__submenu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.site-header__submenu a {
  display: block;
  padding: var(--space-xs) var(--space-md);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--sand);
}
.site-header__submenu a:hover,
.site-header__submenu a[aria-current="page"] {
  color: var(--white);
  background: rgba(255, 255, 255, 0.08);
}

@media (max-width: 860px) {
  .site-header__bar {
    flex-wrap: wrap;
    padding-block: var(--space-xs);
  }
  .site-header__mark img {
    height: 42px;
  }
  .site-header--large .site-header__mark img {
    height: 48px;
  }
  .site-header__nav-toggle {
    display: inline-flex;
  }
  .site-header__nav {
    order: 3;
    width: 100%;
    max-height: 0;
    overflow: hidden;
    transition: max-height var(--duration) var(--ease);
  }
  .site-header[data-nav-open="true"] .site-header__nav {
    max-height: 640px;
  }
  .site-header__links {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding-top: var(--space-sm);
    border-top: 1px solid var(--rule-on-dark);
  }
  .site-header__links li {
    border-bottom: 1px solid var(--rule-on-dark);
  }
  .site-header__links a {
    display: block;
    padding: var(--space-sm) var(--space-3xs);
    width: 100%;
  }
  .site-header__links a.is-cta {
    margin-top: var(--space-xs);
    text-align: center;
  }
  .site-header__dropdown-toggle {
    display: flex;
    justify-content: space-between;
    width: 100%;
    padding: var(--space-sm) var(--space-3xs);
  }
  .site-header__submenu {
    position: static;
    z-index: auto;
    min-width: 0;
    margin-top: 0;
    border: 0;
    background: rgba(0, 0, 0, 0.15);
    padding-block: 0;
    max-height: 0;
    overflow: hidden;
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: max-height var(--duration) var(--ease);
  }
  .site-header__dropdown.is-open .site-header__submenu {
    max-height: 200px;
    padding-block: var(--space-2xs);
  }
  .site-header__submenu a {
    padding: var(--space-sm) var(--space-md);
  }
}

/* ==========================================================================
   Site footer
   ========================================================================== */
site-footer {
  display: block;
}

.site-footer {
  background: var(--moss);
  color: var(--sand);
  border-top: 4px solid var(--white);
  padding-block: var(--space-xl) var(--space-lg);
}

.site-footer__grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr;
  gap: var(--space-lg);
  padding-bottom: var(--space-lg);
  border-bottom: 1px solid var(--rule-on-dark);
}

.site-footer__brand img {
  height: 64px;
  width: auto;
  margin-bottom: var(--space-sm);
  opacity: 0.92;
}

.site-footer__heading {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--white);
  margin-bottom: var(--space-sm);
}

.site-footer__contact li {
  margin-bottom: var(--space-2xs);
}
.site-footer__contact a {
  text-decoration: none;
}
.site-footer__contact a:hover {
  color: var(--white);
}

.site-footer__social {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}
.site-footer__social a {
  display: inline-flex;
  opacity: 0.85;
  transition: opacity var(--duration) var(--ease), transform var(--duration) var(--ease);
}
.site-footer__social a img {
  width: 28px;
  height: 28px;
}
.site-footer__social a:hover,
.site-footer__social a:focus-visible {
  opacity: 1;
  transform: translateY(-2px);
}

.site-footer__bottom {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-xs);
  padding-top: var(--space-md);
  border-top: 1px solid var(--rule-on-dark);
  font-size: var(--text-xs);
  color: var(--sand);
}
.site-footer__bottom a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--rule-on-dark);
}
.site-footer__bottom a:hover {
  color: var(--white);
  border-bottom-color: var(--white);
}

@media (max-width: 760px) {
  .site-footer__grid {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
  }
}

/* ==========================================================================
   Component — conservation status tag
   A blaze mark, not a SaaS pill: flat rectangle, sharp corners, a single
   bold swatch of color from the brand palette per status. No red. Severity
   reads through fill weight: solid moss (most severe) down to white
   (mildest), all on the same three-color palette.
   ========================================================================== */
.tag {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  gap: var(--space-3xs);
  padding: var(--space-3xs) var(--space-xs);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  border-radius: 2px;
  white-space: nowrap;
}
.tag::before {
  content: "";
  width: 8px;
  height: 8px;
  background: currentColor;
  flex-shrink: 0;
}

.tag--critically-endangered {
  background: var(--moss);
  color: var(--white);
}
.tag--endangered {
  background: var(--sand);
  color: var(--moss);
  border: 1px solid var(--moss);
}
.tag--vulnerable {
  background: var(--white);
  color: var(--moss);
  border: 1px solid var(--moss);
}

/* ==========================================================================
   Component — route info strip
   Reads left to right like a trail signpost: plank-bordered strip,
   fields separated by rules, not icon-in-a-card.
   ========================================================================== */
.route-strip {
  display: flex;
  flex-wrap: wrap;
  border-top: 3px solid var(--moss);
  border-bottom: 3px solid var(--moss);
}
.route-strip__item {
  flex: 1 1 auto;
  padding: var(--space-sm) var(--space-md);
  border-right: 1px solid var(--rule);
}
.route-strip__item:last-child {
  border-right: 0;
}
.route-strip__label {
  display: block;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--moss);
  margin-bottom: var(--space-3xs);
}
.route-strip__value {
  display: block;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-lg);
  color: var(--moss);
  line-height: var(--leading-tight);
}
.route-strip__item--price {
  background: var(--moss);
}
.route-strip__item--price .route-strip__label {
  color: var(--sand);
}
.route-strip__item--price .route-strip__value {
  color: var(--white);
}

.route-strip.on-dark {
  border-top-color: var(--sand);
  border-bottom-color: var(--sand);
}
.route-strip.on-dark .route-strip__item {
  border-right-color: var(--rule-on-dark);
}
.route-strip.on-dark .route-strip__label {
  color: var(--sand);
  opacity: 0.85;
}
.route-strip.on-dark .route-strip__value {
  color: var(--sand);
}

@media (max-width: 640px) {
  .route-strip {
    flex-direction: column;
  }
  .route-strip__item {
    border-right: 0;
    border-bottom: 1px solid var(--rule);
  }
  .route-strip__item:last-child {
    border-bottom: 0;
  }
}

/* ==========================================================================
   Component — placeholder chip / block
   Marks real missing content so it can't be mistaken for a finished field.
   Never use these to hold invented copy — dashed border, muted color,
   explicit "add real copy here" label, nothing that could pass as real.
   ========================================================================== */
.placeholder-chip {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  gap: var(--space-3xs);
  padding: var(--space-3xs) var(--space-xs);
  border: 2px dashed var(--moss);
  background: transparent;
  color: var(--moss);
  font-family: var(--font-body);
  font-weight: 500;
  font-style: italic;
  font-size: var(--text-xs);
  letter-spacing: 0.01em;
  text-transform: none;
  white-space: nowrap;
}

.placeholder-block {
  border: 2px dashed var(--moss);
  padding: var(--space-md);
  color: var(--moss);
}
.placeholder-block__label {
  display: block;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: var(--space-3xs);
}
.placeholder-block__note {
  display: block;
  font-style: italic;
  font-size: var(--text-sm);
}

.placeholder-photo {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  aspect-ratio: 1 / 1;
  border: 2px dashed var(--moss);
  color: var(--moss);
  background: transparent;
  padding: var(--space-sm);
  font-style: italic;
  font-weight: 500;
  font-size: var(--text-xs);
  letter-spacing: 0.01em;
}

/* ==========================================================================
   Accessibility panel — js/accessibility.js (mounted on every landing page)
   Font-style and color-mode presets, applied via data-attributes on <html>
   and read back by js/a11y-early.js on the next page load.
   ========================================================================== */

/* Color-mode presets: overriding the same tokens every component already
   reads (--moss/--sand/--ink-on-*) re-themes the whole site without needing
   per-component overrides. */
:root[data-a11y-theme="high-contrast"] {
  --moss: #000000;
  --sand: #ffffff;
  --ink-on-light: #000000;
  --ink-on-dark: #ffffff;
  --surface-light: #ffffff;
  --rule: rgba(0, 0, 0, 0.7);
  --rule-on-dark: rgba(255, 255, 255, 0.85);
}
:root[data-a11y-theme="muted"] {
  --moss: #5b6355;
  --sand: #f2efe9;
  --rule: rgba(91, 99, 85, 0.22);
}

/* Font override: needs to beat a page-specific font pass (e.g. home.css's
   body.home, an equal-specificity same-element rule) regardless of file load
   order, so this targets body through an extra ancestor step - html[attr]
   body - which is more specific than body.home instead of relying on
   whichever stylesheet happens to load last. */
html[data-a11y-font="dyslexia"] body {
  --font-heading: "Atkinson Hyperlegible", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: "Atkinson Hyperlegible", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}
/* System/web-safe serif, not a Google Fonts load - "Times New Roman" itself
   where the OS has it, falling back to the generic "Times" alias and then
   any serif for devices (some mobile/Linux systems) that have neither. */
html[data-a11y-font="times"] body {
  --font-heading: "Times New Roman", Times, serif;
  --font-body: "Times New Roman", Times, serif;
}

/* Font-size slider (js/accessibility.js sets documentElement.style.fontSize
   as a percentage) - every text-size rule site-wide reads var(--text-*),
   and every one of those tokens is rem-based, so retuning what 1rem
   resolves to here rescales the entire site's text proportionally with no
   other CSS changes needed. The transition is what makes dragging the
   slider feel smooth rather than jumping between values - lives on html
   since that's the element whose font-size actually changes. */
html {
  transition: font-size 120ms ease;
}
@media (prefers-reduced-motion: reduce) {
  html {
    transition: none;
  }
}

.a11y-toggle-wrap {
  position: fixed;
  left: var(--space-md);
  bottom: var(--space-md);
  z-index: 500;
}

.a11y-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 2px solid var(--white);
  background: var(--moss);
  color: var(--white);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-md);
  box-shadow: 0 2px 10px rgba(20, 25, 0, 0.3);
  transition: transform var(--duration) var(--ease);
}
.a11y-toggle:hover {
  transform: scale(1.06);
}

.a11y-panel {
  position: absolute;
  left: 0;
  bottom: calc(100% + var(--space-sm));
  width: min(280px, calc(100vw - 2 * var(--space-md)));
  background: var(--surface-light);
  color: var(--ink-on-light);
  border: 1px solid var(--rule);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(20, 25, 0, 0.25);
  padding: var(--space-md);
}

.a11y-panel__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-sm);
}
.a11y-panel__header h2 {
  margin: 0;
  font-size: var(--text-lg);
}
.a11y-panel__close {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-size: var(--text-lg);
  line-height: 1;
  color: var(--moss);
}
.a11y-panel__close:hover {
  background: var(--rule);
}

.a11y-panel__section + .a11y-panel__section {
  margin-top: var(--space-md);
  padding-top: var(--space-md);
  border-top: 1px solid var(--rule);
}

.a11y-panel__label {
  margin: 0 0 var(--space-xs);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--moss);
}

.a11y-panel__label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
  margin-bottom: var(--space-xs);
}
.a11y-panel__label-row .a11y-panel__label {
  margin-bottom: 0;
}
.a11y-panel__value {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-sm);
  color: var(--moss);
  font-variant-numeric: tabular-nums;
}

/* Native range input, restyled just enough to read as an intentional part
   of the panel rather than an unstyled browser default - accent-color alone
   covers the filled-track/thumb color in every evergreen browser without
   needing the old multi-vendor-prefix ::-webkit-slider-thumb/::-moz-range-
   thumb song and dance. */
.a11y-font-scale-input {
  width: 100%;
  accent-color: var(--moss);
  cursor: pointer;
}

.a11y-panel__options {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}
.a11y-panel__options label {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--text-sm);
  cursor: pointer;
}

@media (max-width: 480px) {
  .a11y-toggle-wrap {
    left: var(--space-sm);
    bottom: var(--space-sm);
  }
}
