/* ===========================================================================
   Valparai Paradise — components and page sections
   =========================================================================== */

/* --- header --------------------------------------------------------------- */
.site-head {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  color: var(--on-dark);
  transition: background-color 0.35s var(--ease), box-shadow 0.35s var(--ease),
    color 0.35s var(--ease);
}

.site-head::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgb(7 20 16 / 0.72), rgb(7 20 16 / 0));
  pointer-events: none;
  transition: opacity 0.35s var(--ease);
}

.site-head.is-stuck {
  background: color-mix(in srgb, var(--ink) 94%, transparent);
  backdrop-filter: blur(10px);
  box-shadow: 0 1px 0 var(--line-dark);
}

.site-head.is-stuck::before { opacity: 0; }

.head-inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 4.6rem;
  padding-block: 0.6rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  flex: none;
  margin-right: auto;
}

.brand-mark {
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 42%;
  background: var(--ink);
  flex: none;
}

.brand-name {
  display: grid;
  line-height: 1.05;
}

/* Sized up from 1.16rem when the display face changed. Fraunces carried the
   brand at weight 600; Libre Caslon Display has only 400, which left the brand
   reading lighter than the nav links next to it. A single-weight face gives you
   size as the only lever, so the brand takes it. */
.brand-name b {
  font-family: var(--display);
  font-size: 1.38rem;
  font-weight: 400;
  letter-spacing: -0.005em;
}

.brand-name span {
  font-size: 0.6rem;
  font-variation-settings: "wdth" 82, "wght" 550;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
}

.nav { display: flex; align-items: center; gap: clamp(1rem, 2vw, 2rem); }

.nav a {
  font-size: var(--step--1);
  font-variation-settings: "wdth" 96, "wght" 500;
  letter-spacing: 0.04em;
  text-decoration: none;
  padding-block: 0.4rem;
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease);
}

.nav a:hover,
.nav a[aria-current="page"] { border-color: var(--gold); color: var(--gold); }

/* The nav's own WhatsApp button is for the mobile drawer only — on desktop
   the header CTA already carries it. */
.nav .btn { display: none; }

.head-cta { flex: none; }

.nav-toggle {
  display: none;
  width: 2.8rem; height: 2.8rem;
  align-items: center; justify-content: center;
  background: none;
  border: 1px solid var(--line-dark);
  border-radius: 50%;
  cursor: pointer;
}

.nav-toggle span {
  position: relative;
  width: 16px; height: 1.5px;
  background: currentColor;
  transition: background-color 0.2s var(--ease);
}

.nav-toggle span::before,
.nav-toggle span::after {
  content: "";
  position: absolute;
  left: 0;
  width: 16px; height: 1.5px;
  background: currentColor;
  transition: transform 0.28s var(--ease);
}

.nav-toggle span::before { top: -5px; }
.nav-toggle span::after { top: 5px; }

.nav-toggle[aria-expanded="true"] span { background: transparent; }
.nav-toggle[aria-expanded="true"] span::before { transform: translateY(5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span::after { transform: translateY(-5px) rotate(-45deg); }

@media (max-width: 900px) {
  .nav-toggle { display: flex; }
  .head-cta { display: none; }

  .nav {
    position: fixed;
    top: 4.6rem;
    left: 0;
    right: 0;
    /* `height`, not `bottom: 0` — `.site-head.is-stuck` gets a `backdrop-filter`
       (and any header state could pick up a transform), and either one makes
       this fixed-position ancestor its own containing block, so `bottom: 0`
       would resolve against the ~70px-tall header again instead of the
       viewport. `vh`/`dvh` units are always viewport-relative regardless of
       containing block, so sizing by height sidesteps the whole problem. */
    height: calc(100dvh - 4.6rem);
    z-index: 96;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0.5rem var(--gutter) 1.6rem;
    background: color-mix(in srgb, var(--ink) 97%, transparent);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--line-dark);
    overflow-y: auto;
    transform: translateY(-120%);
    visibility: hidden;
    transition: transform 0.4s var(--ease), visibility 0.4s;
  }

  .nav.is-open { transform: none; visibility: visible; }

  .nav a {
    padding-block: 0.95rem;
    border-bottom: 1px solid var(--line-dark);
    font-size: var(--step-1);
  }

  .nav .btn { display: inline-flex; margin-top: 1.1rem; }
}

/* --- hero ----------------------------------------------------------------- */
.hero {
  position: relative;
  min-height: min(100svh, 860px);
  display: grid;
  align-items: end;
  padding-block: 9rem var(--band);
  background: var(--ink);
  color: var(--on-dark);
  isolation: isolate;
  overflow-x: clip;
}

.hero-media {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.hero-media img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 55%;
}

.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, rgb(7 20 16 / 0.94) 0%, rgb(7 20 16 / 0.5) 42%, rgb(7 20 16 / 0.34) 100%),
    linear-gradient(to right, rgb(7 20 16 / 0.6), rgb(7 20 16 / 0) 62%);
}

.hero-inner { position: relative; }

.hero h1 { max-width: 15ch; margin-bottom: 1.4rem; }

.hero h1 .is-gold { color: var(--gold); }

.hero-kicker {
  margin-bottom: 1.1rem;
  font-size: 0.7rem;
  font-variation-settings: "wdth" 86, "wght" 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
}

/* A quiet cue that there is more below, without an arrow-bounce cliche. */
.hero-scroll {
  position: absolute;
  left: 50%;
  bottom: 1.1rem;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 26px;
  height: 42px;
  border: 1px solid var(--line-dark);
  border-radius: 20px;
  transform: translateX(-50%);
  transition: border-color 0.3s var(--ease);
}

.hero-scroll span {
  width: 3px;
  height: 7px;
  border-radius: 2px;
  background: var(--gold);
  animation: scroll-hint 2.1s var(--ease) infinite;
}

.hero-scroll:hover { border-color: var(--gold); }

@keyframes scroll-hint {
  0%, 12% { transform: translateY(-6px); opacity: 0; }
  30%, 60% { opacity: 1; }
  85%, 100% { transform: translateY(7px); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-scroll span { animation: none; }
}

@media (max-width: 860px) {
  .hero-scroll { display: none; }
}

.hero-lede {
  max-width: 46ch;
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--on-dark-dim);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin-top: 2.2rem;
}

.hero-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(1.2rem, 3vw, 3rem);
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: 1.6rem;
  border-top: 1px solid var(--line-dark);
}

.hero-stat { display: grid; gap: 0.15rem; }

.hero-stat b {
  font-size: var(--step-2);
  font-family: var(--sans);
  font-variation-settings: "wdth" var(--signage-wdth), "wght" 700;
  font-variant-numeric: tabular-nums;
  color: var(--gold);
  line-height: 1;
}

/* Direct child only. The counter markup is <b><span data-count>…</span></b>,
   and a plain `.hero-stat span` also matches that inner span, overriding the
   large gold numeral with the small grey label style. */
.hero-stat > span {
  font-size: 0.72rem;
  font-variation-settings: "wdth" 88, "wght" 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--on-dark-dim);
}

/* --- trust strip ---------------------------------------------------------- */
.trust {
  background: var(--ink);
  color: var(--on-dark-dim);
  border-top: 1px solid var(--line-dark);
  padding-block: 1.1rem;
  overflow: hidden;
}

.trust-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.7rem clamp(1.2rem, 3vw, 2.6rem);
  font-size: var(--step--1);
  font-variation-settings: "wdth" 92, "wght" 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.trust-row li { display: flex; align-items: center; gap: 0.5rem; }
.trust-row svg { width: 1rem; height: 1rem; color: var(--gold); flex: none; }

/* --- section head --------------------------------------------------------- */
.sec-head {
  display: grid;
  gap: 1rem;
  max-width: var(--shell);
  margin-bottom: clamp(2.2rem, 4vw, 3.4rem);
}

.sec-head-split {
  grid-template-columns: minmax(0, 1fr) minmax(0, 26rem);
  align-items: end;
  gap: 2rem;
}

@media (max-width: 820px) {
  .sec-head-split { grid-template-columns: 1fr; align-items: start; }
}

/* ===========================================================================
   THE ASCENT — the signature section.
   Forty signposted hairpin bends from Aliyar Dam to Valparai. The road draws
   itself as you scroll and the readout climbs with it.
   =========================================================================== */
/* overflow-x: clip rather than hidden, so the sticky altimeter still sticks. */
.ascent { position: relative; overflow-x: clip; }

.ascent-grid {
  display: grid;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: start;
}

.ascent-readout {
  position: sticky;
  top: 7rem;
  display: grid;
  gap: 1.4rem;
}

.altimeter {
  display: grid;
  gap: 0.2rem;
  padding: 1.4rem 1.5rem;
  border: 1px solid var(--line-dark);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--moss) 45%, transparent);
}

.altimeter-label {
  font-size: 0.68rem;
  font-variation-settings: "wdth" 84, "wght" 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--on-dark-dim);
}

.altimeter-value {
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  font-size: clamp(2.6rem, 6vw, 3.9rem);
  font-variation-settings: "wdth" 76, "wght" 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--gold);
}

.altimeter-value small {
  font-size: 0.9rem;
  font-variation-settings: "wdth" 86, "wght" 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--on-dark-dim);
}

.altimeter-place {
  margin-top: 0.5rem;
  font-family: var(--display);
  font-size: var(--step-1);
  color: var(--on-dark);
  min-height: 1.5em;
}

.altimeter-bar {
  height: 3px;
  margin-top: 0.9rem;
  border-radius: 3px;
  background: var(--line-dark);
  overflow: hidden;
}

.altimeter-bar i {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--gold);
  transition: width 0.35s var(--ease);
}

/* the road */
.ascent-road {
  position: relative;
  display: grid;
  gap: clamp(2.5rem, 6vw, 5rem);
  padding-left: clamp(3.5rem, 9vw, 7.5rem);
}

.ascent-svg {
  position: absolute;
  inset: 0 auto 0 0;
  width: clamp(3.5rem, 9vw, 7.5rem);
  height: 100%;
  overflow: visible;
  color: var(--gold);
}

.ascent-svg .road-base {
  fill: none;
  stroke: var(--line-dark);
  stroke-width: 2.5;
  stroke-linecap: round;
}

.ascent-svg .road-draw {
  fill: none;
  stroke: currentColor;
  stroke-width: 2.5;
  stroke-linecap: round;
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--gold) 45%, transparent));
}

.bend {
  position: relative;
  display: grid;
  gap: 0.55rem;
  padding: 1.4rem 0;
  opacity: 0.42;
  transition: opacity 0.5s var(--ease);
}

.bend.is-active { opacity: 1; }

.bend-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.72rem;
  font-variation-settings: "wdth" 82, "wght" 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
}

.bend-tag i {
  font-style: normal;
  color: var(--on-dark-dim);
  font-variation-settings: "wdth" 82, "wght" 500;
  letter-spacing: 0.1em;
}

.bend h3 { font-size: var(--step-2); }

.bend p {
  max-width: 46ch;
  color: var(--on-dark-dim);
  font-size: var(--step-0);
}

@media (max-width: 900px) {
  .ascent-grid { grid-template-columns: 1fr; }
  .ascent-readout {
    position: sticky;
    top: 4.9rem;
    z-index: 5;
    background: color-mix(in srgb, var(--canopy) 96%, transparent);
    backdrop-filter: blur(8px);
    padding-block: 0.8rem;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
  }
  .altimeter { padding: 0.9rem 1.1rem; }
  .altimeter-value { font-size: 2.2rem; }
  .altimeter-place { font-size: var(--step-0); margin-top: 0.2rem; }
}

/* --- package cards -------------------------------------------------------- */
.pkg-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
  gap: clamp(1rem, 2vw, 1.6rem);
}

/* Four packages read better as one row of four than as three and an orphan. */
.pkg-grid-4 { grid-template-columns: repeat(auto-fill, minmax(min(100%, 16.5rem), 1fr)); }

.pkg {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--line-light);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.pkg:hover {
  border-color: color-mix(in srgb, var(--fern) 45%, transparent);
  box-shadow: 0 22px 44px -26px rgb(7 20 16 / 0.55);
}

.band-dark .pkg,
.band-ink .pkg {
  background: color-mix(in srgb, var(--moss) 42%, transparent);
  border-color: var(--line-dark);
}

.band-dark .pkg h3, .band-ink .pkg h3 { color: var(--on-dark); }
.band-dark .pkg-blurb, .band-ink .pkg-blurb { color: var(--on-dark-dim); }
.band-dark .pkg-meta, .band-ink .pkg-meta { color: var(--on-dark-dim); }
.band-dark .pkg-foot, .band-ink .pkg-foot { border-top-color: var(--line-dark); }
.band-dark .price-value, .band-ink .price-value { color: var(--on-dark); }
.band-dark .price-label, .band-ink .price-label { color: var(--on-dark-dim); }
.band-dark .pkg-go, .band-ink .pkg-go { border-color: var(--line-dark); }

.pkg-media {
  position: relative;
  aspect-ratio: 16 / 10;
  background: var(--canopy);
}

.pkg-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.pkg-kicker {
  position: absolute;
  top: 0.85rem; left: 0.85rem;
  padding: 0.35rem 0.75rem;
  border-radius: 100px;
  background: var(--gold);
  color: var(--ink);
  font-size: 0.66rem;
  font-variation-settings: "wdth" 88, "wght" 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* Flex, not grid, so the price row can be pinned to the bottom with
   margin-top:auto. Otherwise a two-line title knocks one card's price out of
   line with the rest of the row. */
.pkg-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.7rem;
  flex: 1;
  padding: 1.4rem 1.4rem 1.5rem;
}

.pkg-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.72rem;
  font-variation-settings: "wdth" 86, "wght" 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--on-light-dim);
}

.pkg-meta i { font-style: normal; opacity: 0.4; }

.pkg h3 { font-size: var(--step-2); }

.pkg h3 a { text-decoration: none; }

/* whole card clickable, keyboard focus stays on the real link */
.pkg h3 a::after { content: ""; position: absolute; inset: 0; }

.pkg-blurb {
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--on-light-dim);
}

.pkg-foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  margin-top: auto;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line-light);
}

.price { display: grid; gap: 0.1rem; }

.price-label {
  font-size: 0.64rem;
  font-variation-settings: "wdth" 86, "wght" 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--on-light-dim);
}

.price-value {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  font-size: var(--step-2);
  font-variation-settings: "wdth" 84, "wght" 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--on-light);
}

.price-value small {
  font-size: 0.7rem;
  font-variation-settings: "wdth" 88, "wght" 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--on-light-dim);
}

.pkg-go {
  display: grid;
  place-items: center;
  width: 2.5rem; height: 2.5rem;
  flex: none;
  border: 1px solid var(--line-light);
  border-radius: 50%;
  transition: background-color 0.3s var(--ease), color 0.3s var(--ease),
    border-color 0.3s var(--ease), transform 0.3s var(--ease);
}

.pkg:hover .pkg-go {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--ink);
  transform: rotate(-45deg);
}

.pkg-go svg { width: 1rem; height: 1rem; }

/* --- price ladder --------------------------------------------------------- */
.ladder {
  display: grid;
  gap: 1px;
  background: var(--line-light);
  border: 1px solid var(--line-light);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.band-dark .ladder,
.band-ink .ladder { background: var(--line-dark); border-color: var(--line-dark); }

.ladder-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 1rem;
  padding: 0.95rem 1.25rem;
  background: var(--paper);
  transition: background-color 0.25s var(--ease);
}

.band-dark .ladder-row,
.band-ink .ladder-row { background: var(--canopy); }

.ladder-row:hover { background: var(--sand); }
.band-dark .ladder-row:hover,
.band-ink .ladder-row:hover { background: var(--moss); }

.ladder-row.is-best { background: color-mix(in srgb, var(--gold) 14%, var(--paper)); }
.band-dark .ladder-row.is-best,
.band-ink .ladder-row.is-best { background: color-mix(in srgb, var(--gold) 16%, var(--canopy)); }

.ladder-label {
  font-size: var(--step--1);
  font-variation-settings: "wdth" 94, "wght" 550;
}

.ladder-price {
  font-size: var(--step-1);
  font-variation-settings: "wdth" 84, "wght" 700;
  font-variant-numeric: tabular-nums;
}

.ladder-price small {
  font-size: 0.66rem;
  font-variation-settings: "wdth" 88, "wght" 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.6;
  margin-left: 0.3rem;
}

.ladder-flag {
  display: inline-block;
  margin-left: 0.6rem;
  padding: 0.15rem 0.5rem;
  border-radius: 100px;
  background: var(--gold);
  color: var(--ink);
  font-size: 0.6rem;
  font-variation-settings: "wdth" 88, "wght" 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  vertical-align: 0.15em;
}

/* --- package fact tiles --------------------------------------------------- */
.fact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 8.5rem), 1fr));
  gap: clamp(0.6rem, 1.2vw, 1rem);
}

.fact {
  display: grid;
  align-content: start;
  gap: 0.3rem;
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--line-light);
  border-top: 3px solid var(--fern);
  border-radius: var(--radius);
  background: var(--paper);
}

.fact svg { width: 1.15rem; height: 1.15rem; color: var(--gold-deep); }

.fact strong {
  font-size: var(--step-1);
  font-variation-settings: "wdth" var(--signage-wdth), "wght" 700;
  line-height: 1.1;
}

/* --- price line in a package page header ---------------------------------- */
.hero-price {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  align-self: center;
  font-size: 0.72rem;
  font-variation-settings: "wdth" 88, "wght" 550;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--on-dark-dim);
}

.hero-price b {
  font-size: var(--step-2);
  font-variation-settings: "wdth" 82, "wght" 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  color: var(--gold);
}

/* --- "from" price block (shown instead of the ladder) --------------------- */
.from-block {
  display: grid;
  gap: 0.4rem;
  margin-bottom: 1.2rem;
  padding: 1.35rem 1.5rem;
  border: 1px solid var(--line-light);
  border-left: 3px solid var(--gold);
  border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
  background: var(--paper);
}

.band-dark .from-block,
.band-ink .from-block {
  background: color-mix(in srgb, var(--moss) 50%, transparent);
  border-color: var(--line-dark);
  border-left-color: var(--gold);
}

.from-value {
  font-size: var(--step-4);
  font-variation-settings: "wdth" 80, "wght" 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--gold-deep);
}

.band-dark .from-value,
.band-ink .from-value { color: var(--gold); }

.from-block p {
  margin-top: 0.5rem;
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--on-light-dim);
}

.band-dark .from-block p,
.band-ink .from-block p { color: var(--on-dark-dim); }

.from-extras {
  padding-top: 0.7rem;
  border-top: 1px solid var(--line-light);
}

.band-dark .from-extras,
.band-ink .from-extras { border-top-color: var(--line-dark); }

/* --- attraction grid ------------------------------------------------------ */
.att-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}

.att {
  position: relative;
  display: grid;
  align-content: end;
  gap: 0.5rem;
  min-height: 21rem;
  padding: 1.4rem;
  border-radius: var(--radius-lg);
  overflow: hidden;
  color: var(--on-dark);
  isolation: isolate;
  background: var(--canopy);
}

.att-lg { grid-column: span 2; min-height: 26rem; }

@media (max-width: 700px) { .att-lg { grid-column: span 1; min-height: 21rem; } }

.att img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.8s var(--ease);
}

.att::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to top, rgb(7 20 16 / 0.92) 8%, rgb(7 20 16 / 0.15) 62%);
}

.att:hover img { transform: scale(1.06); }

/* The category line started life inside a dark photo overlay. It now also
   appears in feature bodies on light bands, so the light case is the default
   and the dark contexts override it. */
.att-cat {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.3rem 0.55rem;
  font-size: 0.66rem;
  font-variation-settings: "wdth" 86, "wght" 650;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--gold-deep);
}

.att-cat b {
  font-variation-settings: "wdth" 86, "wght" 500;
  color: var(--on-light-dim);
  font-weight: 400;
}

.att .att-cat,
.band-dark .att-cat,
.band-ink .att-cat { color: var(--gold); }

.att .att-cat b,
.band-dark .att-cat b,
.band-ink .att-cat b { color: var(--on-dark-dim); }

.att h3 { font-size: var(--step-1); }

/* The blurb reveals on hover. `:not(.att-cat)` matters — the category line is
   also a <p> and must stay visible. */
.att > p:not(.att-cat) {
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--on-dark-dim);
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height 0.5s var(--ease), opacity 0.4s var(--ease),
    margin-top 0.5s var(--ease);
}

.att:hover > p:not(.att-cat),
.att:focus-within > p:not(.att-cat) { max-height: 16rem; opacity: 1; margin-top: 0.2rem; }

/* On touch there is no hover, so always show the copy. */
@media (hover: none) {
  .att > p:not(.att-cat) { max-height: none; opacity: 1; }
}

/* --- seasons -------------------------------------------------------------- */
.season-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}

.season {
  display: grid;
  align-content: start;
  gap: 0.7rem;
  padding: 1.6rem;
  border: 1px solid var(--line-light);
  border-top: 3px solid var(--fern);
  border-radius: var(--radius);
  background: var(--paper);
}

.season-best { border-top-color: var(--gold); }
.season-caution { border-top-color: var(--ember); }

.season-tag {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.68rem;
  font-variation-settings: "wdth" 86, "wght" 650;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--on-light-dim);
}

.season-best .season-tag b { color: var(--gold-deep); }
.season-caution .season-tag b { color: var(--ember); }

.season h3 { font-size: var(--step-1); }

.season p { font-size: var(--step--1); line-height: 1.6; color: var(--on-light-dim); }

/* Review cards: attribution pinned to the bottom so a row of them lines up
   however long the quotes are. */
.review {
  align-content: stretch;
  grid-template-rows: auto 1fr auto;
  border-top-color: var(--gold);
}

.review-stars {
  display: inline-flex;
  gap: 0.12rem;
  color: var(--gold-deep);
}

/* svg is display:block in the reset, so the row has to be laid out here or the
   stars stack vertically. Handles icons as direct children or wrapped. */
.review-stars > span { display: inline-flex; gap: 0.12rem; }
.review-stars svg { width: 0.9rem; height: 0.9rem; flex: none; }

.review p { align-self: start; }

.review-by {
  padding-top: 0.9rem;
  border-top: 1px solid var(--line-light);
  font-size: 0.68rem;
  font-variation-settings: "wdth" 88, "wght" 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--on-light-dim);
}

.band-dark .review-by,
.band-ink .review-by { border-top-color: var(--line-dark); color: var(--on-dark-dim); }

/* --- reach table ---------------------------------------------------------- */
.reach { display: grid; gap: 1px; background: var(--line-dark); }

.reach-row {
  display: grid;
  grid-template-columns: minmax(7rem, 1fr) auto auto;
  align-items: baseline;
  gap: 1rem clamp(1rem, 3vw, 2.5rem);
  padding: 1.15rem 0.2rem;
  background: var(--canopy);
}

.reach-from {
  font-family: var(--display);
  font-size: var(--step-1);
}

.reach-km,
.reach-time {
  font-variation-settings: "wdth" 84, "wght" 650;
  font-variant-numeric: tabular-nums;
  font-size: var(--step-0);
  color: var(--gold);
  white-space: nowrap;
}

.reach-time { color: var(--on-dark-dim); }

.reach-note {
  grid-column: 1 / -1;
  font-size: var(--step--1);
  color: var(--on-dark-dim);
  max-width: 60ch;
}

@media (max-width: 620px) {
  .reach-row { grid-template-columns: 1fr auto; }
  .reach-time { grid-column: 2; }
}

/* --- itinerary timeline --------------------------------------------------- */
.days { display: grid; gap: clamp(1.6rem, 3vw, 2.6rem); }

.day {
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 2.5rem);
  padding-top: 1.8rem;
  border-top: 1px solid var(--line-light);
}

.band-dark .day { border-top-color: var(--line-dark); }

@media (max-width: 780px) { .day { grid-template-columns: 1fr; gap: 1rem; } }

.day-no {
  font-size: 0.68rem;
  font-variation-settings: "wdth" 84, "wght" 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold-deep);
  margin-bottom: 0.5rem;
}

.band-dark .day-no { color: var(--gold); }

.day h3 { font-size: var(--step-2); margin-bottom: 0.6rem; }

.day-summary { font-size: var(--step--1); color: var(--on-light-dim); }
.band-dark .day-summary { color: var(--on-dark-dim); }

.stops { display: grid; gap: 0.1rem; }

.stop {
  display: grid;
  grid-template-columns: 4.5rem 1fr;
  gap: 0.9rem;
  align-items: baseline;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--line-light);
}

.band-dark .stop { border-bottom-color: var(--line-dark); }

.stop:last-child { border-bottom: none; }

.stop-time {
  font-size: 0.72rem;
  font-variation-settings: "wdth" 84, "wght" 650;
  letter-spacing: 0.06em;
  color: var(--gold-deep);
  font-variant-numeric: tabular-nums;
}

.band-dark .stop-time { color: var(--gold); }

.stop-text { font-size: var(--step-0); }

/* --- list with ticks / crosses -------------------------------------------- */
.checks { display: grid; gap: 0.7rem; }

.checks li {
  display: grid;
  grid-template-columns: 1.15rem 1fr;
  gap: 0.75rem;
  align-items: start;
  font-size: var(--step--1);
  line-height: 1.55;
}

.checks svg { width: 1.15rem; height: 1.15rem; margin-top: 0.18em; flex: none; }

.checks-yes svg { color: var(--gold); }
.checks-no svg { color: var(--on-light-dim); opacity: 0.55; }
.band-dark .checks-no svg { color: var(--on-dark-dim); }

/* --- FAQ ------------------------------------------------------------------ */
.faq { display: grid; gap: 0; max-width: 52rem; }

.faq details {
  border-bottom: 1px solid var(--line-light);
}

.band-dark .faq details { border-bottom-color: var(--line-dark); }

.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.25rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--display);
  font-size: var(--step-1);
  line-height: 1.25;
  transition: color 0.25s var(--ease);
}

.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--gold-deep); }
.band-dark .faq summary:hover { color: var(--gold); }

.faq-sign {
  position: relative;
  width: 1.05rem; height: 1.05rem;
  flex: none;
  color: var(--gold-deep);
}

.band-dark .faq-sign { color: var(--gold); }

.faq-sign::before,
.faq-sign::after {
  content: "";
  position: absolute;
  top: 50%; left: 0;
  width: 100%; height: 1.5px;
  background: currentColor;
  transition: transform 0.3s var(--ease);
}

.faq-sign::after { transform: rotate(90deg); }
.faq details[open] .faq-sign::after { transform: rotate(0deg); }

.faq-answer {
  padding-bottom: 1.4rem;
  max-width: 58ch;
  font-size: var(--step-0);
  color: var(--on-light-dim);
}

.band-dark .faq-answer { color: var(--on-dark-dim); }

/* --- enquiry form --------------------------------------------------------- */
.enquiry {
  display: grid;
  gap: 1rem;
  padding: clamp(1.4rem, 3vw, 2.2rem);
  background: var(--paper);
  border: 1px solid var(--line-light);
  border-radius: var(--radius-lg);
}

.band-dark .enquiry,
.band-ink .enquiry {
  background: color-mix(in srgb, var(--moss) 50%, transparent);
  border-color: var(--line-dark);
}

.field { display: grid; gap: 0.4rem; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }

@media (max-width: 560px) { .field-row { grid-template-columns: 1fr; } }

.field label {
  font-size: 0.7rem;
  font-variation-settings: "wdth" 88, "wght" 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--on-light-dim);
}

.band-dark .field label,
.band-ink .field label { color: var(--on-dark-dim); }

.field input,
.field select,
.field textarea {
  padding: 0.8rem 0.95rem;
  background: var(--mist);
  border: 1px solid var(--line-light);
  border-radius: var(--radius);
  font-size: var(--step-0);
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease);
}

.band-dark .field input,
.band-dark .field select,
.band-dark .field textarea,
.band-ink .field input,
.band-ink .field select,
.band-ink .field textarea {
  background: color-mix(in srgb, var(--ink) 45%, transparent);
  border-color: var(--line-dark);
  color: var(--on-dark);
}

.field input:focus,
.field select:focus,
.field textarea:focus { outline: none; border-color: var(--gold); }

.field textarea { resize: vertical; min-height: 5.5rem; }

.form-note {
  font-size: var(--step--1);
  color: var(--on-light-dim);
}

.band-dark .form-note, .band-ink .form-note { color: var(--on-dark-dim); }

/* --- quote preview --------------------------------------------------------
   `display: flex` beats the `hidden` attribute's UA `display: none`, so the
   empty quote box rendered as a blank strip in the form until a price existed
   to put in it. It never showed before only because the one form that had a
   quote box was on a page where a quote was always computable. */
.quote[hidden] { display: none; }

.quote {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.6rem 1rem;
  padding: 0.95rem 1.15rem;
  border: 1px dashed var(--line-light);
  border-radius: var(--radius);
  font-size: var(--step--1);
}

.band-dark .quote, .band-ink .quote { border-color: var(--line-dark); }

.quote b {
  font-size: var(--step-1);
  font-variation-settings: "wdth" 84, "wght" 700;
  font-variant-numeric: tabular-nums;
  color: var(--gold-deep);
}

.band-dark .quote b, .band-ink .quote b { color: var(--gold); }

/* --- footer --------------------------------------------------------------- */
.site-foot {
  background: var(--ink);
  color: var(--on-dark-dim);
  padding-block: clamp(3rem, 6vw, 5rem) 2rem;
}

.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: clamp(1.8rem, 4vw, 3rem);
}

@media (max-width: 900px) { .foot-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .foot-grid { grid-template-columns: 1fr; } }

/* h2, because <footer> is a top-level landmark and these are its sections.
   h3 left the 404 page — which has an h1 and no h2 at all — skipping a level.
   line-height is pinned here because h1/h2 and h3/h4 carry different defaults
   and the level should not decide how this looks. */
.foot-col h2 {
  line-height: 1.18;
  margin-bottom: 1rem;
  font-family: var(--sans);
  font-size: 0.68rem;
  font-variation-settings: "wdth" 86, "wght" 650;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
}

.foot-col li { margin-bottom: 0.6rem; font-size: var(--step--1); }
.foot-col a { text-decoration: none; transition: color 0.25s var(--ease); }
.foot-col a:hover { color: var(--gold); }

.foot-brand { max-width: 34ch; }
.foot-brand img { width: 8.5rem; margin-bottom: 1rem; }
.foot-brand p { font-size: var(--step--1); line-height: 1.6; }
/* The tagline sits under the description as a quieter, smaller line — it is a
   flourish, not a second paragraph competing with the one above it. */
.foot-tagline {
  margin-top: .6rem;
  font-style: italic;
  letter-spacing: .01em;
  opacity: .72;
}

.foot-social { display: flex; gap: 0.6rem; margin-top: 1.2rem; }

.foot-social a {
  display: grid;
  place-items: center;
  width: 2.4rem; height: 2.4rem;
  border: 1px solid var(--line-dark);
  border-radius: 50%;
  transition: background-color 0.25s var(--ease), color 0.25s var(--ease),
    border-color 0.25s var(--ease);
}

.foot-social a:hover { background: var(--gold); border-color: var(--gold); color: var(--ink); }
.foot-social svg { width: 1.05rem; height: 1.05rem; }

.foot-base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.8rem 1.5rem;
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--line-dark);
  font-size: 0.76rem;
}

.foot-base a { text-decoration: none; }
.foot-base a:hover { color: var(--gold); }

.foot-links { display: flex; flex-wrap: wrap; gap: 0.6rem 1.4rem; }

/* --- floating WhatsApp ---------------------------------------------------- */
.wa-float {
  position: fixed;
  right: clamp(0.9rem, 2vw, 1.6rem);
  bottom: clamp(0.9rem, 2vw, 1.6rem);
  z-index: 90;
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.85rem 1.25rem;
  border-radius: 100px;
  background: #158741;
  color: #fff;
  font-size: var(--step--1);
  font-variation-settings: "wdth" 94, "wght" 650;
  letter-spacing: 0.03em;
  text-decoration: none;
  box-shadow: 0 10px 28px -10px rgb(0 0 0 / 0.55);
  transition: transform 0.3s var(--ease), background-color 0.3s var(--ease);
}

.wa-float:hover { transform: translateY(-3px); background: #10763a; }
.wa-float svg { width: 1.3rem; height: 1.3rem; flex: none; }

@media (max-width: 560px) {
  .wa-float span { display: none; }
  .wa-float { padding: 1rem; }
}

/* --- misc ----------------------------------------------------------------- */
.page-head {
  padding-block: clamp(7rem, 12vw, 10rem) clamp(2.5rem, 5vw, 4rem);
  background: var(--ink);
  color: var(--on-dark);
}

.crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.2rem;
  font-size: 0.7rem;
  font-variation-settings: "wdth" 88, "wght" 550;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--on-dark-dim);
}

.crumbs a { text-decoration: none; }
.crumbs a:hover { color: var(--gold); }
.crumbs i { font-style: normal; opacity: 0.45; }

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(1.6rem, 4vw, 4rem);
  align-items: start;
}

@media (max-width: 880px) { .split { grid-template-columns: 1fr; } }

.sticky-side { position: sticky; top: 6.5rem; }

@media (max-width: 880px) { .sticky-side { position: static; } }

.note-strip {
  display: grid;
  gap: 0.5rem;
  padding: 1.15rem 1.35rem;
  border-left: 3px solid var(--gold);
  background: var(--sand);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: var(--step--1);
  line-height: 1.6;
}

.band-dark .note-strip, .band-ink .note-strip {
  background: color-mix(in srgb, var(--moss) 50%, transparent);
  color: var(--on-dark-dim);
}

.tag-row { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.tag {
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--line-light);
  border-radius: 100px;
  font-size: 0.7rem;
  font-variation-settings: "wdth" 90, "wght" 550;
  letter-spacing: 0.06em;
  color: var(--on-light-dim);
}

.band-dark .tag, .band-ink .tag { border-color: var(--line-dark); color: var(--on-dark-dim); }

/* --- header hides on scroll-down, returns on scroll-up --------------------
   `transform: none` at rest, not `translateY(0)` — a non-"none" transform on
   an ancestor creates a containing block for `position: fixed` descendants,
   which was capturing the mobile `.nav` drawer (also `position: fixed`) and
   sizing it against the ~70px-tall header instead of the viewport, collapsing
   the open drawer to a sliver under the header. `none` still animates cleanly
   to `translateY(-100%)` on `.is-away` — browsers treat `none` as the identity
   matrix for transitions — so the scroll-hide effect is unchanged. */
.site-head { transform: none; }
.site-head.is-away { transform: translateY(-100%); }

@media (prefers-reduced-motion: reduce) {
  .site-head.is-away { transform: none; }
}

/* --- review grid ----------------------------------------------------------
   Reviews are quotes, not products: a looser three-up that lets a long one
   breathe instead of forcing every card to package-card proportions. */
.review-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}

/* ===========================================================================
   SECTION ARCHETYPES
   The site had one composition — eyebrow, big headline left, lede right, grid
   — repeated for every section on every page. These are the alternatives, so
   the page changes shape as you move down it.
   =========================================================================== */

/* --- Archetype B: alternating feature rows -------------------------------- */
.features { display: grid; gap: clamp(2.5rem, 5vw, 5rem); }

.feature {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(1.5rem, 4vw, 4rem);
}

.feature:nth-child(even) .feature-media { order: 2; }

/* The frame clips (parallax and zoom need it); the wrapper does not, so the
   index numeral can hang off the corner without being cut in half. */
.feature-media { position: relative; }

.feature-frame {
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-lg);
}

.feature-frame > img { border-radius: inherit; }

/* An oversized index number, set half off the image edge. Real sequence:
   these are ordered by how often guests ask about them. */
.feature-index {
  position: absolute;
  top: -0.32em;
  left: -0.1em;
  z-index: 2;
  font-family: var(--sans);
  font-size: clamp(3.5rem, 7vw, 6.5rem);
  font-variation-settings: "wdth" 76, "wght" 700;
  line-height: 1;
  color: var(--gold);
  opacity: 0.9;
  pointer-events: none;
}

.feature:nth-child(even) .feature-index { left: auto; right: -0.12em; }

.feature-body { display: grid; gap: 1rem; align-content: center; }

/* Two levels, one look. On the homepage these cards sit under a section h2, so
   h3 is the right level. On /stay/ they are the page's top-level sections and
   sit directly under the h1, so there they are h2. They are card headings
   either way, so the h3 treatment is carried across both and the level stays a
   purely semantic choice. */
.feature-body h2,
.feature-body h3 {
  font-size: var(--step-3);
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.18;
}

.feature-body p {
  max-width: 46ch;
  color: var(--on-light-dim);
  font-size: var(--step-0);
  line-height: 1.62;
}

.band-dark .feature-body p,
.band-ink .feature-body p { color: var(--on-dark-dim); }

@media (max-width: 860px) {
  .feature { grid-template-columns: 1fr; gap: 1.25rem; }
  .feature:nth-child(even) .feature-media { order: 0; }
  .feature-media { aspect-ratio: 16 / 10; }
  .feature-index { font-size: clamp(2.8rem, 12vw, 4rem); top: -0.25em; left: -0.04em; }
  .feature:nth-child(even) .feature-index { left: -0.04em; right: auto; }
}

/* --- a compact ruled list, for the long tail ------------------------------ */
.ruled { display: grid; }

.ruled-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 1rem;
  padding: 1.05rem 0;
  border-top: 1px solid var(--line-light);
  transition: padding-left 0.4s var(--ease-out);
}

.band-dark .ruled-row,
.band-ink .ruled-row { border-top-color: var(--line-dark); }

.ruled-row:last-child { border-bottom: 1px solid var(--line-light); }
.band-dark .ruled-row:last-child,
.band-ink .ruled-row:last-child { border-bottom-color: var(--line-dark); }

.ruled-row:hover { padding-left: 0.7rem; }

.ruled-name {
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 400;
  letter-spacing: -0.015em;
}

.ruled-meta {
  font-size: 0.7rem;
  font-variation-settings: "wdth" 86, "wght" 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--on-light-dim);
  white-space: nowrap;
}

.band-dark .ruled-meta,
.band-ink .ruled-meta { color: var(--on-dark-dim); }

.ruled-meta b { color: var(--gold-deep); font-weight: inherit; }
.band-dark .ruled-meta b, .band-ink .ruled-meta b { color: var(--gold); }

/* --- Archetype C: the statement ------------------------------------------- */
.statement {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  max-width: 22ch;
}

.statement-wide { max-width: 30ch; }

.statement-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 2rem;
  max-width: none;
}

/* --- Archetype D: the season strip ---------------------------------------- */
.strip {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--line-light);
}

.band-dark .strip, .band-ink .strip { border-top-color: var(--line-dark); }

.strip-col {
  display: grid;
  align-content: start;
  gap: 0.7rem;
  padding: clamp(1.4rem, 3vw, 2.2rem) clamp(1rem, 2vw, 1.8rem);
  border-left: 1px solid var(--line-light);
  position: relative;
}

.band-dark .strip-col, .band-ink .strip-col { border-left-color: var(--line-dark); }

.strip-col:first-child { border-left: none; padding-left: 0; }

/* the marker bar that says how good this window is */
.strip-col::before {
  content: "";
  position: absolute;
  top: -1px; left: 0; right: 0;
  height: 3px;
  background: var(--fern);
}

.strip-col:first-child::before { left: 0; }
.strip-best::before { background: var(--gold); }
.strip-caution::before { background: var(--ember); }

.strip-tag {
  font-size: 0.68rem;
  font-variation-settings: "wdth" 86, "wght" 650;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--on-light-dim);
}

.band-dark .strip-tag, .band-ink .strip-tag { color: var(--on-dark-dim); }
.strip-best .strip-tag { color: var(--gold-deep); }
.band-dark .strip-best .strip-tag { color: var(--gold); }
.strip-caution .strip-tag { color: var(--ember); }

.strip-col h3 { font-size: var(--step-2); }

.strip-temp {
  font-variation-settings: "wdth" 84, "wght" 650;
  font-size: var(--step--1);
  letter-spacing: 0.03em;
  color: var(--gold-deep);
}

.band-dark .strip-temp, .band-ink .strip-temp { color: var(--gold); }

.strip-col p {
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--on-light-dim);
}

.band-dark .strip-col p, .band-ink .strip-col p { color: var(--on-dark-dim); }

@media (max-width: 780px) {
  .strip { grid-template-columns: 1fr; }
  .strip-col {
    border-left: none;
    border-top: 1px solid var(--line-dark);
    padding-left: 0;
    padding-right: 0;
  }
  .strip-col:first-child { border-top: none; }
  .strip-col::before { width: 3rem; right: auto; }
}

/* --- Archetype E: the lead quote ------------------------------------------ */
.quote-lead {
  display: grid;
  gap: 1.5rem;
  align-content: start;
}

.quote-lead blockquote {
  margin: 0;
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 400;
  line-height: 1.3;
  letter-spacing: -0.018em;
  color: var(--on-dark);
  max-width: 24ch;
}

.quote-lead blockquote::before {
  content: "\201C";
  display: block;
  font-size: 2.4em;
  line-height: 0.6;
  color: var(--gold);
  margin-bottom: 0.1em;
}

.quote-by {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem 0.7rem;
  font-size: 0.7rem;
  font-variation-settings: "wdth" 88, "wght" 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--on-dark-dim);
}

.quote-by .review-stars { color: var(--gold); }

@media (max-width: 900px) {
  .quote-lead { max-width: none; }
}

.ruled-quote {
  font-size: var(--step--1);
  line-height: 1.62;
  color: var(--on-dark-dim);
}

/* ===========================================================================
   MOBILE
   Not a shrunk desktop layout. The grids change shape, the cards change
   density, and a persistent action bar sits at the thumb.
   =========================================================================== */

/* --- sticky action bar ----------------------------------------------------
   The single highest-value mobile element on a site whose entire conversion
   path is WhatsApp. It sits above the home indicator and never covers content
   because body gets matching bottom padding. */
.action-bar {
  position: fixed;
  inset: auto 0 0;
  z-index: 95;
  display: none;
  gap: 0.55rem;
  padding: 0.6rem var(--gutter) calc(0.6rem + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--ink) 96%, transparent);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--line-dark);
}

.action-bar .btn {
  flex: 1;
  min-height: 3rem;
  padding-inline: 0.9rem;
  font-size: 0.78rem;
}

.action-bar .btn-ghost { color: var(--on-dark); flex: 0 0 3.4rem; padding-inline: 0; }
.action-bar .btn svg { width: 1.15em; height: 1.15em; }

@media (max-width: 860px) {
  .action-bar { display: flex; }
  body { padding-bottom: 4.6rem; }
  /* the floating bubble would sit on top of the bar */
  .wa-float { display: none; }
}

/* --- hero ----------------------------------------------------------------- */
@media (max-width: 860px) {
  .hero {
    min-height: min(92svh, 720px);
    padding-block: 7rem clamp(1.5rem, 5vw, 2.5rem);
  }

  .hero h1 { max-width: 13ch; }
  .hero-lede { font-size: var(--step-0); max-width: none; }
  .hero-actions { margin-top: 1.6rem; gap: 0.65rem; }
  .hero-actions .btn { flex: 1 1 100%; }
  .hero-foot {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem 1.5rem;
    margin-top: 2rem;
    padding-top: 1.2rem;
  }
  .hero-kicker { font-size: 0.62rem; letter-spacing: 0.18em; }
}

/* --- compact package tiles ------------------------------------------------
   Two up rather than one, because four full-width cards is 2,300px of scroll
   for four links. The blurb goes; the title, the tag and the price are what
   a browsing decision actually needs. */
@media (max-width: 620px) {
  .pkg-grid,
  .pkg-grid-4 {
    grid-template-columns: 1fr 1fr;
    gap: 0.7rem;
  }

  .pkg-media { aspect-ratio: 1 / 1; }
  .pkg-body { padding: 0.85rem 0.85rem 0.95rem; gap: 0.4rem; }
  .pkg-blurb { display: none; }
  .pkg h3 { font-size: var(--step-0); letter-spacing: -0.01em; }
  .pkg-meta { font-size: 0.58rem; letter-spacing: 0.1em; gap: 0.3rem; }
  .pkg-foot { padding-top: 0.7rem; }
  .pkg-go { display: none; }
  .price-label { font-size: 0.55rem; letter-spacing: 0.1em; }
  .price-value { font-size: var(--step-1); }
  .price-value small { display: none; }
  .pkg-kicker {
    top: 0.5rem; left: 0.5rem;
    padding: 0.22rem 0.5rem;
    font-size: 0.53rem;
    letter-spacing: 0.08em;
  }
}

/* --- section rhythm ------------------------------------------------------- */
@media (max-width: 700px) {
  .sec-head { margin-bottom: 1.6rem; gap: 0.7rem; }
  .sec-head .lede { font-size: var(--step-0); }
  .features { gap: 2.25rem; }
  .split { gap: 2rem; }
  .contour { height: 30px; }
}

/* --- the ascent on a phone ------------------------------------------------
   The readout was semi-transparent, so bend text scrolled visibly through it.
   It is opaque now, and sits directly under the header. */
@media (max-width: 900px) {
  .ascent-readout {
    background: var(--canopy);
    box-shadow: 0 10px 20px -14px rgb(0 0 0 / 0.8);
    border-bottom: 1px solid var(--line-dark);
  }

  .ascent-road { padding-left: 2.75rem; }
  .ascent-svg { width: 2.75rem; }
  .bend { padding: 1rem 0; }
  .bend h3 { font-size: var(--step-1); }
  .bend p { font-size: var(--step--1); }
}

/* --- tap targets ----------------------------------------------------------
   Anything a thumb has to hit gets at least 44px of height. */
@media (max-width: 860px) {
  .ruled-row { padding-block: 0.95rem; min-height: 3rem; }
  .faq summary { padding-block: 1.1rem; min-height: 3.25rem; }
  .foot-col li { margin-bottom: 0.15rem; }
  .foot-col li a { display: inline-block; padding-block: 0.55rem; }
  .foot-social a { width: 2.9rem; height: 2.9rem; }
  .crumbs a { padding-block: 0.35rem; }
}

/* Grid and flex children default to min-width:auto, which is min-content — a
   single unshrinkable row (a star rating next to a date, say) can then force
   the whole track wider than the viewport. This is the standard guard. */
.pkg,
.att,
.season,
.review,
.strip-col,
.feature,
.feature-body,
.ruled-row,
.day,
.reach-row,
.fact { min-width: 0; }

.season-tag { flex-wrap: wrap; }

/* --- inner-page hero ------------------------------------------------------
   Shorter than the homepage hero, same grammar. Replaces the flat dark
   rectangle every inner page used to open on. */
.page-hero {
  position: relative;
  display: grid;
  align-items: end;
  min-height: min(64svh, 560px);
  padding-block: 8.5rem clamp(2rem, 4vw, 3.25rem);
  background: var(--ink);
  color: var(--on-dark);
  isolation: isolate;
  overflow-x: clip;
}

.page-hero-media { position: absolute; inset: 0; z-index: -2; }

.page-hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, rgb(7 20 16 / 0.95) 0%, rgb(7 20 16 / 0.62) 46%, rgb(7 20 16 / 0.4) 100%),
    linear-gradient(to right, rgb(7 20 16 / 0.55), rgb(7 20 16 / 0) 68%);
}

.page-hero-inner { position: relative; display: grid; gap: 1rem; justify-items: start; }
.page-hero-inner h1 { max-width: 20ch; }
.page-hero-inner .lede { max-width: 52ch; color: var(--on-dark-dim); }
.page-hero-inner .crumbs { margin-bottom: 0.2rem; }
.page-hero-inner .hero-kicker { margin-bottom: 0; }
.page-hero .hero-actions { margin-top: 0.9rem; }

@media (max-width: 860px) {
  .page-hero {
    min-height: min(56svh, 460px);
    padding-block: 6.75rem clamp(1.5rem, 4vw, 2.25rem);
  }
  .page-hero-inner .lede { font-size: var(--step-0); }
  .page-hero .hero-actions .btn { flex: 1 1 100%; }
}

/* --- wildlife tiles: image on top, text below, not overlaid ---------------
   The overlay treatment works when the photo is a place. For an animal the
   subject is the point, so the frame stays clean and the text sits under it. */
.att-grid-4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }

.att-grid-4 .att {
  min-height: 0;
  align-content: start;
  padding: 0;
  gap: 0.55rem;
  background: none;
  border-radius: 0;
}

.att-grid-4 .att::after { display: none; }

.att-frame {
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-lg);
  margin-bottom: 0.35rem;
}

.att-grid-4 .att img {
  position: static;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.att-grid-4 .att > p:not(.att-cat) { max-height: none; opacity: 1; }

@media (max-width: 620px) {
  .att-grid-4 { grid-template-columns: 1fr 1fr; gap: 0.9rem; }
  .att-grid-4 .att h3 { font-size: var(--step-0); }
  .att-grid-4 .att > p:not(.att-cat) { font-size: 0.78rem; }
}

/* In a feature body the qualifier is a subtitle, not a second label — losing
   the uppercase stops it competing with the heading underneath it. */
.feature-body .att-cat b {
  text-transform: none;
  letter-spacing: 0.02em;
  font-size: 0.78rem;
}

/* --- Trust badge ---------------------------------------------------------
   Google score + star row + review count, as a link to the real profile.
   Lives in heroes, which are always photographic and therefore always dark
   text-on-image — so this is styled for the dark side first and only lightened
   inside a light band. Sized off the type scale so it holds up next to an
   h1 without competing with it. */
.trust-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  margin-top: 1.5rem;
  padding: 0.5rem 0.9rem 0.5rem 0.75rem;
  border: 1px solid color-mix(in srgb, var(--on-dark) 26%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, #000 26%, transparent);
  backdrop-filter: blur(6px);
  color: var(--on-dark);
  text-decoration: none;
  font-size: var(--step--1);
  line-height: 1;
  transition: border-color 0.25s ease, background 0.25s ease, transform 0.25s ease;
}

.trust-badge:hover,
.trust-badge:focus-visible {
  border-color: var(--gold);
  background: color-mix(in srgb, #000 42%, transparent);
  transform: translateY(-1px);
}

.trust-badge .ts-score {
  font-family: var(--display);
  font-weight: 400; /* Libre Caslon Display has one weight — see README */
  font-size: var(--step-1);
  color: var(--gold);
  letter-spacing: 0.01em;
}

.trust-badge .ts-stars {
  display: inline-flex;
  gap: 0.1rem;
}

.trust-badge .ts-star svg {
  width: 0.95em;
  height: 0.95em;
  display: block;
}

.trust-badge .ts-on { color: var(--gold); }
.trust-badge .ts-half { color: var(--gold); opacity: 0.55; }
.trust-badge .ts-off { color: var(--on-dark); opacity: 0.28; }

.trust-badge .ts-count {
  color: var(--on-dark-dim);
  letter-spacing: 0.02em;
}

.trust-compact { margin-top: 1.2rem; }

/* Inside a light band the glass treatment has nothing to sit on. */
.band .trust-badge,
.sticky-side .trust-badge {
  border-color: var(--line-light);
  background: var(--sand);
  color: var(--ink);
  backdrop-filter: none;
}

.band .trust-badge .ts-count,
.sticky-side .trust-badge .ts-count { color: var(--on-light-dim); }

.band .trust-badge .ts-off,
.sticky-side .trust-badge .ts-off { color: var(--ink); opacity: 0.22; }

@media (max-width: 32rem) {
  .trust-badge {
    gap: 0.45rem;
    padding: 0.45rem 0.75rem;
    font-size: var(--step--2);
  }
}

/* --- Stay cards ----------------------------------------------------------
   The six properties, sold the way the packages are. Shares the .pkg card so
   Stay and Packages read as one site. What differs is the empty state: a
   property with no photo yet gets a lettered tile with an honest offer on it,
   not a stock hill photograph under a real property's name. */
.stay-card .pkg-media { background: var(--sand); }

.stay-blank {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 0.55rem;
  background: var(--sand);
}

.stay-blank b {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.6rem, 7vw, 3.6rem);
  line-height: 1;
  color: var(--gold-deep);
}

.stay-blank i {
  font-style: normal;
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-variation-settings: "wdth" 86, "wght" 600;
  color: var(--on-light-dim);
}

.stay-points {
  list-style: none;
  display: grid;
  gap: 0.45rem;
  margin: 0;
  padding: 0;
  font-size: var(--step--1);
  color: var(--on-light-dim);
}

.stay-points li { display: flex; align-items: center; gap: 0.55rem; }

.stay-points svg {
  width: 1.05em;
  height: 1.05em;
  flex: none;
  color: var(--gold-deep);
}

.stay-card .pkg-foot { align-items: center; }

/* The whole card is already a link to this same WhatsApp thread, through the
   title's stretched ::after. This is that link made visible, sized down so it
   sits beside the price rather than dominating the card. It stays clickable in
   its own right because it is positioned and comes later in the DOM. */
.stay-cta { min-height: 2.6rem; padding: 0.6rem 1.05rem; font-size: 0.78rem; }

@media (max-width: 30rem) {
  .stay-card .pkg-foot { flex-wrap: wrap; }
  .stay-cta { width: 100%; }
}

/* --- Property rows -------------------------------------------------------
   The Stay page's property list, with the property's own photo where one has
   been uploaded to the admin panel. Coverage is partial and will stay partial
   for a while, so the empty state is a deliberate lettered tile rather than a
   stand-in photograph — a generic hill photo under a real property's name is a
   promise the guest checks on arrival. The tile keeps the rows aligned. */
.prop-row {
  grid-template-columns: 3.5rem 1fr;
  align-items: center;
  column-gap: 1.1rem;
}

.prop-thumb {
  grid-row: span 2;
  width: 3.5rem;
  aspect-ratio: 1;
  border-radius: calc(var(--radius) * 0.6);
  overflow: hidden;
  background: var(--sand);
  display: grid;
  place-items: center;
}

.prop-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* the real photos are portrait phone shots */
  display: block;
}

.prop-thumb-blank {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--step-1);
  color: var(--gold-deep);
  border: 1px solid var(--line-light);
}

.band-dark .prop-thumb,
.band-ink .prop-thumb { background: color-mix(in srgb, var(--moss) 50%, transparent); }

.band-dark .prop-thumb-blank,
.band-ink .prop-thumb-blank { color: var(--gold); border-color: var(--line-dark); }

@media (max-width: 40rem) {
  .prop-row { grid-template-columns: 2.75rem 1fr; column-gap: 0.85rem; }
  .prop-thumb { width: 2.75rem; }
}

/* --- Attraction cards that link out --------------------------------------
   A card becomes an <a> only when that attraction has a page of its own, so
   the affordance has to be carried by the card rather than assumed. */
a.att-link {
  text-decoration: none;
  color: inherit;
  display: block;
  transition: transform 0.3s ease;
}

a.att-link:hover,
a.att-link:focus-visible { transform: translateY(-3px); }

.att-more {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.7rem;
  color: var(--gold-deep);
  font-size: var(--step--1);
  letter-spacing: 0.02em;
}

.att-more svg { width: 1em; height: 1em; transition: transform 0.3s ease; }
a.att-link:hover .att-more svg { transform: translateX(3px); }

.band-dark .att-more, .band-ink .att-more { color: var(--gold); }

/* ===========================================================================
   HOMEPAGE REWORK — September 2026
   Hero + form, assurances, the Google wall, and the reel strip.
   =========================================================================== */

/* --- hero: centred copy, booking bar underneath -------------------------
   The first version put the copy left and the form right. It worked, but it
   split the visitor's attention across two columns before they had read what
   the business even sells. Centred, the headline and the price are read first
   and the bar underneath is the single obvious next move — the arrangement a
   hotel or flight search page has settled on for the same reason. */
.hero-centred {
  align-items: center;
  padding-block: clamp(6rem, 10vw, 8rem) clamp(2rem, 4vw, 3.5rem);
  min-height: min(100svh, 940px);
}

/* One full-width column, with the copy centred INSIDE it rather than the grid
   centring its items. `justify-items: center` sizes each item to its content,
   which quietly capped the booking card at its max-content width — about 86%
   of the shell — and left it looking inset for no reason. */
.hero-stack {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.8rem, 3.5vw, 2.8rem);
}

.hero-centred .hero-inner { margin-inline: auto; }

.hero-centred .hero-inner {
  display: grid;
  justify-items: center;
  text-align: center;
  max-width: 54rem;
}

/* --step-6 was drawn for a headline running the full shell. Centred over a
   54rem measure it needs a slightly shorter ramp or the second line breaks. */
.hero-centred h1 {
  font-size: clamp(2.4rem, 1.2rem + 4vw, 4.2rem);
  max-width: 20ch;
  margin-bottom: 1.1rem;
}

.hero-centred .hero-kicker { margin-bottom: 0.9rem; }

.hero-centred .hero-lede {
  max-width: 52ch;
  font-size: var(--step-1);
  color: var(--on-dark-dim);
}

/* --- the three proof chips ----------------------------------------------
   A badge and a short phrase, three across, centred under the lede. The first
   opens the real Google profile: a rating nobody can check is worth nothing,
   and one that is clearly a link makes a reader treat the other two as
   checkable too. */
.hero-proof {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.7rem clamp(1rem, 2.6vw, 2.2rem);
  margin-top: clamp(1.3rem, 2.5vw, 1.9rem);
}

/* The separator between chips is a dot drawn by the list, not a character in
   the markup — so it never ends up read aloud or stranded on a wrapped line. */
.hproof { display: flex; align-items: center; gap: clamp(1rem, 2.6vw, 2.2rem); }

.hproof + .hproof::before {
  content: "";
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.4;
}

/* --- the booking card, straddling hero and the band below -----------------
   Sits outside <section class="hero">, right after it in the markup, then
   pulls itself up with a negative margin so roughly half the card sits on
   the hero photo and half sits on the section below — the layout almost
   every travel-agency homepage converges on. `.hero` only clips its X axis
   (overflow-x: clip, for the parallax media), so the card is free to sit
   above the hero's own lower edge without being cut off.
   The section right after it (`.band-hero-follow`) adds extra top padding
   so its own heading always clears the card, whatever the card's exact
   height ends up being at a given width — safer than trying to match the
   pull-up amount to the card height exactly. */
.hero-form-float {
  position: relative;
  z-index: 5;
  /* Roughly half the card's own height (~15rem at the 4-columns-across
     width this applies at) — see the 979px hero breakpoint below, which is
     where the card also switches to 2 columns and gets noticeably taller. */
  margin-top: -7.4rem;
}

@media (max-width: 61.1875rem) {
  /* Below 979px the hero itself drops its fixed height (min-height: 0, see
     .hero-centred below) and becomes an auto-height stack — there's no
     longer a predictable stretch of photo for the card to sit half on, so
     it just follows in normal flow instead of guessing at an overlap. */
  .hero-form-float { margin-top: 1.6rem; }
}

.band-hero-follow { padding-top: calc(var(--band) + 5.5rem); }

@media (max-width: 61.1875rem) {
  .band-hero-follow { padding-top: var(--band); }
}

.hproof > a,
.hproof > span {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--on-dark);
  text-decoration: none;
  font-size: var(--step--1);
  line-height: 1.2;
}

.hproof > a { transition: color 0.25s var(--ease); }
.hproof > a:hover { color: var(--gold); }

.hproof-badge {
  display: grid;
  place-items: center;
  width: 1.85rem;
  height: 1.85rem;
  flex: none;
  border-radius: 50%;
  background: var(--gold);
  color: var(--ink);
}

.hproof-badge svg { width: 0.95rem; height: 0.95rem; }

.hproof-text b {
  font-variation-settings: "wdth" 92, "wght" 700;
  font-variant-numeric: tabular-nums;
}

/* Stacked on a phone, and the separator dots go with the row they separated —
   wrapped, they dangled at the start of each line instead of between chips. */
@media (max-width: 620px) {
  .hero-proof { flex-direction: column; align-items: center; gap: 0.6rem; }
  .hproof { gap: 0; }
  .hproof + .hproof::before { display: none; }
}

/* ===========================================================================
   THE BOOKING CARD
   Four questions across, one full-width action underneath. A raised warm-white
   card is the only pale object in the hero, so "start here" needs no arrow
   pointing at it.
   =========================================================================== */
.bookcard {
  display: grid;
  gap: 0.9rem;
  width: 100%;
  padding: clamp(1.15rem, 2.2vw, 1.75rem);
  /* Near-white, with just enough warmth not to read as a browser dialog
     dropped on the photograph. The first version sat at #f7f5f0 and looked
     grey against the hero. */
  background: #fdfcfa;
  border-radius: clamp(14px, 1.6vw, 24px);
  /* Two shadows: a tight one that seats the card on the image, and a wide soft
     one that lifts it off. One shadow doing both jobs always looks like a
     sticker. */
  box-shadow:
    0 2px 6px -2px rgb(7 20 16 / 0.35),
    0 40px 90px -36px rgb(7 20 16 / 0.85);
  color: var(--on-light);
  text-align: left;
}

.bookcard-title {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--step-1);
  line-height: 1.15;
  text-align: center;
}

.bookcard-lede {
  margin-top: -0.5rem;
  font-size: var(--step--1);
  color: var(--on-light-dim);
  text-align: center;
}

.bookcard-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.2vw, 1rem);
}

.bf { display: grid; gap: 0.4rem; min-width: 0; align-content: start; }

/* `:first-child`, not `> span`. The field's box is also a direct span child, so
   the bare selector put `text-transform: uppercase` on the whole control — and
   it inherited straight into the enhanced dropdown, which came out shouting
   VALPARAI DELUXE — 1N / 2D — FROM ₹2,999. */
.bf > span:first-child,
.bf-label {
  font-size: 0.63rem;
  font-variation-settings: "wdth" 88, "wght" 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--on-light-dim);
}

/* Three of the four fields are required, so the asterisks mark the majority —
   fewer marks than tagging the one optional field, and the field without one
   reads as genuinely optional. */
.bf-req { color: var(--ember); font-style: normal; }

/* The bordered box, so the input inside can be a bare field with no chrome of
   its own and the focus ring can sit on something. */
.bf-box {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  padding: 0 0.85rem;
  height: 3.1rem;
  background: var(--paper);
  border: 1px solid color-mix(in srgb, var(--on-light) 14%, transparent);
  border-radius: 10px;
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.bf-box:focus-within {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 22%, transparent);
}

/* Replaces the browser's own validation bubble — see initForms() in site.js. */
.bf-box.is-invalid { border-color: var(--ember); }

.bf-error {
  display: block;
  min-height: 0;
  font-size: 0.68rem;
  color: var(--ember);
}

.bf-error:empty { display: none; }

.bf-box input,
.bf-box select {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: none;
  background: transparent;
  font-size: var(--step-0);
  font-variation-settings: "wdth" 100, "wght" 500;
  color: var(--on-light);
}

.bf-box input:focus,
.bf-box select:focus { outline: none; }

.bf-box input::placeholder { color: color-mix(in srgb, var(--on-light) 42%, transparent); }

/* `appearance: none` strips the native caret along with the native chrome, and
   a select with no caret reads as a text field nobody thinks to click. */
.bf-box select {
  appearance: none;
  cursor: pointer;
  padding-right: 1.2rem;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 0.4rem center, right 0.15rem center;
  background-size: 0.32rem 0.32rem, 0.32rem 0.32rem;
  background-repeat: no-repeat;
}

.bf-lead { width: 1.05rem; height: 1.05rem; flex: none; color: var(--gold-deep); }

/* The native date field puts its picker button on the right and shows nothing
   useful until it has a value. The button is stretched over the whole cell
   instead, so a tap anywhere opens the calendar, and our own glyph leads on
   the left where the mock puts it. */
.bf-date .bf-box { position: relative; }

.bf-date input[type="date"] { position: relative; z-index: 1; }

.bf-date input[type="date"]::-webkit-calendar-picker-indicator {
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
}

/* --- the guest stepper ---------------------------------------------------- */
.bf-step { justify-content: space-between; padding-inline: 0.4rem; gap: 0.3rem; }

.bf-step input {
  text-align: center;
  font-variation-settings: "wdth" 100, "wght" 600;
  /* Spinners next to a pair of stepper buttons is two controls doing one job. */
  appearance: textfield;
  -moz-appearance: textfield;
}

.bf-step input::-webkit-outer-spin-button,
.bf-step input::-webkit-inner-spin-button { appearance: none; margin: 0; }

.bf-stepper {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  flex: none;
  border: none;
  border-radius: 50%;
  background: color-mix(in srgb, var(--on-light) 8%, transparent);
  color: var(--on-light);
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

.bf-stepper svg { width: 0.85rem; height: 0.85rem; }
.bf-stepper:hover { background: var(--gold); color: var(--ink); }
.bf-stepper:disabled { opacity: 0.35; cursor: not-allowed; }
.bf-stepper:disabled:hover { background: color-mix(in srgb, var(--on-light) 8%, transparent); color: var(--on-light); }

/* The honeypot. Off-screen, never announced, never focusable. */
.bf-hp { position: absolute; left: -9999px; top: auto; }

.bookcard-go {
  width: 100%;
  min-height: 3.5rem;
  font-size: var(--step-0);
}

.bookcard .quote {
  border: none;
  border-radius: 10px;
  background: color-mix(in srgb, var(--gold) 18%, var(--paper));
  padding: 0.85rem 1.15rem;
}

.bookcard .quote b { color: var(--gold-deep); }

.bookcard .quote-line {
  flex-basis: 100%;
  font-size: var(--step--2);
  line-height: 1.5;
  color: var(--on-light-dim);
}

.bookcard-assure {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.35rem clamp(0.9rem, 2.2vw, 1.8rem);
  font-size: var(--step--2);
  color: var(--on-light-dim);
}

.bookcard-assure li { display: flex; align-items: center; gap: 0.4rem; }

.bookcard-assure li + li::before {
  content: "";
  width: 3px;
  height: 3px;
  margin-right: clamp(0.5rem, 1.2vw, 1rem);
  border-radius: 50%;
  background: currentColor;
  opacity: 0.45;
}

.bookcard-assure svg { width: 0.9rem; height: 0.9rem; color: #158741; flex: none; }

/* Two across, then one. Nothing is dropped at any width. */
@media (max-width: 860px) {
  .bookcard-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 460px) {
  .bookcard-row { grid-template-columns: minmax(0, 1fr); }
  .bookcard-assure { justify-content: flex-start; }
  .bookcard-assure li + li::before { display: none; }
}

@media (max-width: 979px) {
  .hero-centred { padding-block: 5.5rem var(--band-sm); min-height: 0; }
}

/* --- how booking works ---------------------------------------------------- */
.how-grid {
  display: grid;
  gap: clamp(1.8rem, 4vw, 3.5rem);
  align-items: start;
}

@media (min-width: 900px) {
  .how-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); }
}

/* ===========================================================================
   GOOGLE REVIEWS
   The claim is only worth the space if it can be checked, so the score, the
   full star spread and the link into the profile travel together.
   =========================================================================== */
.google-grid {
  display: grid;
  gap: clamp(1.8rem, 3.5vw, 3rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}

@media (min-width: 1000px) {
  .google-grid { grid-template-columns: 19.5rem minmax(0, 1fr); align-items: start; }
  .gsc-topics { grid-column: 1 / -1; }
}

/* --- the score panel ------------------------------------------------------ */
.gsc {
  display: grid;
  gap: 0.85rem;
  justify-items: start;
  padding: clamp(1.3rem, 2.5vw, 1.8rem);
  background: color-mix(in srgb, var(--ink-lift) 80%, transparent);
  border: 1px solid var(--line-dark);
  border-radius: var(--radius-lg);
}

.gsc-brand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.72rem;
  font-variation-settings: "wdth" 88, "wght" 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--on-dark-dim);
}

.gsc-g { width: 1.05rem; height: 1.05rem; flex: none; }

.gsc-score { display: flex; align-items: center; gap: 0.7rem; }

.gsc-score b {
  font-family: var(--sans);
  font-size: clamp(2.6rem, 6vw, 3.4rem);
  font-variation-settings: "wdth" 88, "wght" 700;
  font-variant-numeric: tabular-nums;
  line-height: 0.9;
  color: var(--on-dark);
}

.gsc-stars { color: var(--gold); }
.gsc-stars svg { width: 1rem; height: 1rem; }

.gsc-count { font-size: var(--step--1); color: var(--on-dark-dim); }
.gsc-count b { color: var(--on-dark); font-weight: inherit; }

/* --- the star spread ------------------------------------------------------
   All five rows, one-stars included and at the same weight as the rest. A
   ratings panel that hides its bad rows is the first thing a sceptical reader
   looks for, and finding it is what stops them believing the page. */
.gsc-bars { display: grid; gap: 0.3rem; width: 100%; margin-top: 0.2rem; }

.gsc-bar {
  display: grid;
  grid-template-columns: 2.3rem 1fr 2.1rem;
  align-items: center;
  gap: 0.55rem;
  font-size: var(--step--2);
  font-variant-numeric: tabular-nums;
  color: var(--on-dark-dim);
}

.gsc-bar-n { display: inline-flex; align-items: center; gap: 0.2rem; }
.gsc-bar-n svg { width: 0.72rem; height: 0.72rem; color: var(--gold); opacity: 0.8; }

.gsc-bar-track {
  height: 6px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--on-dark) 12%, transparent);
  overflow: hidden;
}

.gsc-bar-track i {
  display: block;
  height: 100%;
  min-width: 2px;
  border-radius: 3px;
  background: var(--gold);
}

.gsc-bar-c { text-align: right; }

.gsc-actions {
  display: grid;
  gap: 0.7rem;
  justify-items: start;
  width: 100%;
  margin-top: 0.5rem;
}

.gsc-actions .btn { width: 100%; }

.gsc-note { font-size: var(--step--2); line-height: 1.5; }

/* --- the wall ------------------------------------------------------------
   Two lanes drifting in opposite directions. A wall of people reads as a
   business with 229 reviews; four static cards reads as four reviews. */
.grev-wall {
  display: grid;
  gap: 1rem;
  overflow: hidden;
  /* Fade the lanes into the band at both ends rather than cutting them, so the
     motion reads as a continuing wall and not a clipped box. */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 13%, #000 87%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 13%, #000 87%, transparent);
}

.grev-lane { display: flex; width: max-content; gap: 1rem; }
.grev-run { display: flex; gap: 1rem; }

/* Each lane holds the same run twice, so translating by half its width plus
   half the gap lands exactly where it started. */
.grev-lane-a { animation: grev-drift 78s linear infinite; }
.grev-lane-b { animation: grev-drift 96s linear infinite reverse; }

@keyframes grev-drift {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(calc(-50% - 0.5rem), 0, 0); }
}

/* Reading a moving card is impossible, so pointing at the wall stops it. */
.grev-wall:hover .grev-lane,
.grev-wall:focus-within .grev-lane { animation-play-state: paused; }

.grev {
  display: grid;
  gap: 0.6rem;
  align-content: start;
  width: 20rem;
  padding: 1.15rem 1.25rem;
  background: color-mix(in srgb, var(--ink-lift) 70%, transparent);
  border: 1px solid var(--line-dark);
  border-radius: var(--radius-lg);
}

.grev-head { display: flex; align-items: center; gap: 0.65rem; }

.grev-avatar {
  display: grid;
  place-items: center;
  width: 2.15rem;
  height: 2.15rem;
  flex: none;
  border-radius: 50%;
  background: var(--tile, var(--fern));
  color: #fff;
  font-size: 0.95rem;
  font-variation-settings: "wdth" 100, "wght" 600;
  line-height: 1;
}

.grev-who { display: grid; gap: 0.05rem; min-width: 0; flex: 1; }

.grev-who b {
  font-size: var(--step--1);
  font-variation-settings: "wdth" 100, "wght" 600;
  color: var(--on-dark);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.grev-who i {
  font-style: normal;
  font-size: var(--step--2);
  color: var(--on-dark-dim);
}

.grev-g { width: 1.05rem; height: 1.05rem; flex: none; }

.grev-stars { color: var(--gold); }
.grev-stars svg { width: 0.85rem; height: 0.85rem; }

.grev-text {
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--on-dark-dim);
  /* Long reviews are clamped in the layout, never cut in the data — the whole
     text stays in the HTML for anyone reading it another way. */
  display: -webkit-box;
  -webkit-line-clamp: 7;
  line-clamp: 7;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* On a phone the marquee is more nuisance than spectacle, and a swipeable row
   is the gesture people already have. */
/* The wall keeps drifting on a phone rather than becoming a swipe row. A
   static pair of cards reads as two reviews; a moving wall reads as 229, which
   is the only reason the section is this size. Touch pauses it — see
   .is-held, set by site.js. */
@media (max-width: 760px) {
  .grev { width: min(19rem, 78vw); }
  .grev-lane-a { animation-duration: 52s; }
  .grev-lane-b { animation-duration: 64s; }
  .grev-wall.is-held .grev-lane { animation-play-state: paused; }
}

@media (prefers-reduced-motion: reduce) {
  .grev-lane { animation: none; }
  .grev-wall {
    overflow-x: auto;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .grev-lane .grev-run + .grev-run { display: none; }
}

/* --- Google's own topic chips --------------------------------------------- */
.gsc-topics {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.4rem;
}

.gsc-topics li {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--line-dark);
  border-radius: 100px;
  font-size: var(--step--2);
  color: var(--on-dark-dim);
}

.gsc-topics b {
  font-variation-settings: "wdth" 88, "wght" 700;
  font-variant-numeric: tabular-nums;
  color: var(--gold);
}

.gsc-topics .is-neg b { color: var(--ember); }

/* ===========================================================================
   INSTAGRAM REELS
   Links with a still, not Instagram's embed script. On a phone these open the
   app, where a reel is worth far more than it is in a 300px iframe.
   =========================================================================== */
.reel-strip {
  display: grid;
  gap: clamp(1.6rem, 3vw, 2.6rem);
  margin-top: clamp(2rem, 4vw, 3rem);
  align-items: start;
}

/* One reel under a full-width heading reads as a section waiting for content.
   While there are fewer than four, the row is paired with the guest quote that
   explains why the section exists — see reelStrip() in src/components.mjs. */
@media (min-width: 860px) {
  .reel-strip-paired { grid-template-columns: auto minmax(0, 1fr); }
}

/* Desktop: one run of tiles that wraps. The duplicate run is removed from the
   layout entirely — it exists only for the phone marquee below. */
.reel-row { display: block; }

.reel-run {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.8rem, 1.6vw, 1.2rem);
}

.reel-run-dup { display: none; }

/* `margin: 0` is load-bearing. The tile is a <figure>, and the UA stylesheet
   gives that `margin: 1em 40px` — which showed up as an 80px gutter between
   tiles and pushed the fifth reel onto its own row. */
.reel {
  display: grid;
  gap: 0.55rem;
  align-content: start;
  width: 13rem;
  margin: 0;
  text-decoration: none;
  color: inherit;
}

/* --- the guest quote beside the reels ------------------------------------- */
.reel-proof {
  display: grid;
  gap: 1rem;
  justify-items: start;
  align-content: center;
  max-width: 40rem;
  padding-left: clamp(1rem, 2vw, 1.8rem);
  border-left: 1px solid var(--line-dark);
}

@media (max-width: 859px) {
  .reel-proof { padding-left: 0; border-left: none; }
}

.reel-proof blockquote {
  margin: 0;
  font-family: var(--display);
  font-size: var(--step-2);
  line-height: 1.28;
  letter-spacing: -0.012em;
  color: var(--on-dark);
}

.reel-proof-by {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--step--1);
  color: var(--on-dark-dim);
}

.reel-proof-by .review-stars { color: var(--gold); }
.reel-proof-by .review-stars svg { width: 0.85rem; height: 0.85rem; }

/* --- the like count -------------------------------------------------------
   A snapshot, and safe to leave stale: a like count only climbs, so an old
   number understates. See data/reels.mjs. */
.reel-stat {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--step--2);
  color: var(--on-dark-dim);
}

.reel-stat svg { width: 0.85rem; height: 0.85rem; color: var(--gold); flex: none; }
.reel-stat b { color: var(--on-dark); font-variation-settings: "wdth" 92, "wght" 700; }

/* --- phone and tablet: the row drifts on its own -------------------------
   Wrapping five portrait tiles onto a narrow screen makes a tall stack that
   pushes everything below it off the page. A drifting row keeps the section
   one screen high and shows there is more than one reel without asking anyone
   to scroll sideways to find out.

   Touching it stops it — a moving tap target is not a tap target. */
@media (max-width: 860px) {
  .reel-row {
    display: flex;
    width: max-content;
    gap: 0.75rem;
    animation: reel-drift 34s linear infinite;
  }

  .reel-run { flex-wrap: nowrap; gap: 0.75rem; }
  .reel-run-dup { display: flex; }

  .reel { width: 10.5rem; }

  .reel-strip {
    /* `width: max-content` on the row would otherwise size this grid's only
       column to the whole marquee, dragging anything else in the strip — the
       guest quote, when there are fewer than four reels — out with it. */
    grid-template-columns: minmax(0, 1fr);
    overflow: hidden;
    /* Fade both ends so the row reads as continuing rather than clipped. */
    -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
    mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
  }

  .reel-strip:hover .reel-row,
  .reel-strip:focus-within .reel-row,
  .reel-strip.is-held .reel-row { animation-play-state: paused; }

  /* The quote is not part of the moving row, so it must not be masked with it. */
  .reel-proof {
    -webkit-mask-image: none;
    mask-image: none;
  }
}

/* Half the total width plus half the gap: the two runs are identical, so this
   lands exactly where it started. */
@keyframes reel-drift {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(calc(-50% - 0.375rem), 0, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .reel-row { animation: none; width: auto; display: block; }
  .reel-run { flex-wrap: wrap; }
  .reel-run-dup { display: none; }
  .reel-strip { -webkit-mask-image: none; mask-image: none; overflow: visible; }
}

/* ===========================================================================
   HOMEPAGE PASS 2 — September 2026
   Centred FAQ, the inline reel player, and the closing CTA.
   =========================================================================== */

/* --- a centred section head ----------------------------------------------
   `.sec-head-split` puts the lede in a second column. The FAQ has no lede and
   no image, so left-aligning it left two thirds of the band empty. */
.sec-head-centre {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 0.4rem;
  margin-bottom: clamp(1.8rem, 3.5vw, 2.6rem);
}

.sec-head-centre .eyebrow { margin: 0; }

.faq-band .faq {
  margin-inline: auto;
  max-width: 46rem;
}

/* ===========================================================================
   THE CLOSING CTA
   Centred, and short enough to read in one look. The version this replaced was
   a left-aligned stack on a 1240px band with nothing on the right.
   =========================================================================== */
.cta-close-inner {
  display: grid;
  gap: 1.1rem;
  justify-items: center;
  text-align: center;
  max-width: 44rem;
}

.cta-close-inner .lede { max-width: 42ch; }

.cta-close-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.8rem;
  margin-top: 0.5rem;
}

/* Not flex. A flex container turns the bare " · " text node into its own item,
   so the row gap landed on both sides of it and the separator floated. */
.cta-close-note {
  font-size: var(--step--1);
  color: var(--on-dark-dim);
}

.cta-close-note [data-hours] { white-space: nowrap; }

/* The open/closed dot. It is the detail that makes someone message at 11pm,
   so it gets to be the one spot of colour in the block. */
.cta-close-note [data-hours]::before {
  content: "";
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  margin-right: 0.45rem;
  border-radius: 50%;
  background: var(--ember);
  vertical-align: 0.02em;
}

.cta-close-note [data-hours][data-state="open"]::before {
  background: #2ecc71;
  box-shadow: 0 0 0 3px color-mix(in srgb, #2ecc71 25%, transparent);
}

/* ===========================================================================
   REELS — the inline player
   The frame is a link to Instagram until site.js upgrades it; the Instagram
   button below is the separate, smaller action for someone who wants the
   account rather than the clip.
   =========================================================================== */
.reel { position: relative; }

.reel-media {
  position: relative;
  display: block;
  aspect-ratio: 9 / 16;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--ink-lift);
  border: 1px solid var(--line-dark);
  cursor: pointer;
}

.reel-media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.25s var(--ease);
  pointer-events: none;
}

.reel.is-playing .reel-media video { opacity: 1; pointer-events: auto; }
.reel.is-playing .reel-media img { opacity: 0; }
.reel.is-playing .reel-play,
.reel.is-playing .reel-tag { opacity: 0; pointer-events: none; }

.reel-media img { transition: transform 0.6s var(--ease-out), opacity 0.25s var(--ease); }

.reel-play,
.reel-tag { transition: opacity 0.25s var(--ease), transform 0.35s var(--ease-out), background-color 0.3s var(--ease); }

.reel-body { display: grid; gap: 0.45rem; margin: 0; }

.reel-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
}

/* Its own control, not part of the frame's click target. Small, because
   leaving the site is the secondary action here. */
.reel-ig {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--line-dark);
  border-radius: 100px;
  font-size: 0.66rem;
  font-variation-settings: "wdth" 90, "wght" 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--on-dark-dim);
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease);
}

.reel-ig svg { width: 0.8rem; height: 0.8rem; }
.reel-ig:hover { color: var(--gold); border-color: var(--gold); }

.reel-stat b { color: var(--on-dark); font-variation-settings: "wdth" 92, "wght" 700; }

/* ===========================================================================
   Fixes from the first review pass
   =========================================================================== */

/* "Read all 229 on Google" wrapped onto two lines inside a pill whose arrow
   then sat beside the second line, which read as a misaligned button. The
   label is short enough to hold one line at every width the panel has. */
.gsc-actions .btn {
  width: 100%;
  justify-content: space-between;
  gap: 0.8rem;
  padding-inline: 1.25rem;
  text-align: left;
  white-space: nowrap;
}

.gsc-actions .btn svg { flex: none; }

/* ===========================================================================
   HERO POLISH — 3 September 2026
   =========================================================================== */

/* The overlay was one flat dark gradient, which flattened a photograph that
   has real depth in it. Three layers now: a warm lift where the light falls,
   a deeper floor under the card so the white edge has something to sit on,
   and a top band so the header is always legible. The ember at 7% is what
   stops the whole thing reading as a green filter.

   Scoped to .hero-centred so every inner-page hero is untouched. */
.hero-centred .hero-media::after {
  background:
    radial-gradient(80% 55% at 62% 34%, rgb(224 179 65 / 0.16) 0%, transparent 62%),
    radial-gradient(90% 60% at 50% 100%, rgb(7 20 16 / 0.92) 0%, transparent 70%),
    linear-gradient(to bottom, rgb(7 20 16 / 0.78) 0%, rgb(7 20 16 / 0.34) 26%, rgb(7 20 16 / 0.46) 62%, rgb(7 20 16 / 0.88) 100%),
    linear-gradient(to right, rgb(192 85 46 / 0.07), rgb(192 85 46 / 0) 55%);
}

/* Caslon is a high-contrast face; at hero size a hairline shadow is what keeps
   the thin strokes from disappearing into a bright patch of the photograph. */
.hero-centred h1 {
  letter-spacing: -0.022em;
  text-shadow: 0 2px 26px rgb(7 20 16 / 0.5);
}

.hero-centred .hero-lede {
  color: color-mix(in srgb, var(--on-dark) 82%, transparent);
  text-shadow: 0 1px 14px rgb(7 20 16 / 0.55);
}

.hero-centred .hero-kicker {
  font-size: 0.72rem;
  letter-spacing: 0.26em;
}

/* Slightly larger badges, and a ring so a gold disc on a gold-lit photograph
   still reads as an object. */
.hproof-badge {
  width: 2rem;
  height: 2rem;
  box-shadow: 0 0 0 1px rgb(7 20 16 / 0.16), 0 6px 16px -8px rgb(7 20 16 / 0.9);
}

.hproof > a,
.hproof > span { text-shadow: 0 1px 12px rgb(7 20 16 / 0.5); }

/* The one field that is a real decision gets a touch more room than the three
   that are a date, a number and a name. */
@media (min-width: 861px) {
  .bookcard-row { grid-template-columns: 1.35fr 1fr 0.95fr 1.1fr; }
}

.bookcard-go {
  letter-spacing: 0.02em;
  box-shadow: 0 12px 30px -14px rgb(21 135 65 / 0.9);
}

/* ===========================================================================
   FANCY SELECT AND DATE PICKER
   Both follow the same contract: the native control stays in the DOM and stays
   the value, and these sit on top of it. With JavaScript off neither exists and
   the native controls are visible and usable, which is why they are hidden
   here rather than in the markup.
   =========================================================================== */
.bf-box-fancy { position: relative; }

/* Hidden only once the enhanced control is actually in place. `.js` alone is
   not enough — the class goes on <html> before this script runs. */
.bf-box-fancy > select,
.bf-box-fancy > input[type="date"] {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  pointer-events: none;
}

.fs-trigger,
.dp-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  min-width: 0;
  padding: 0;
  border: none;
  background: none;
  font-size: var(--step-0);
  font-variation-settings: "wdth" 100, "wght" 500;
  color: var(--on-light);
  text-align: left;
  cursor: pointer;
}

.fs-trigger:focus-visible,
.dp-trigger:focus-visible { outline: none; }

.fs-value,
.dp-value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fs-trigger.is-empty .fs-value,
.dp-value.is-empty { color: color-mix(in srgb, var(--on-light) 42%, transparent); }

/* The caret is drawn here rather than on the button, so it never scrolls out
   with a long trip name. */
.fs-trigger::after {
  content: "";
  flex: none;
  width: 0.42rem;
  height: 0.42rem;
  margin-right: 0.1rem;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: translateY(-0.14em) rotate(45deg);
  opacity: 0.55;
  transition: transform 0.25s var(--ease-out);
}

.bf-box-fancy.is-open .fs-trigger::after {
  transform: translateY(0.06em) rotate(-135deg);
}

/* --- the popovers --------------------------------------------------------- */
.fs-list,
.dp {
  position: absolute;
  top: calc(100% + 0.45rem);
  left: 0;
  z-index: 40;
  min-width: 100%;
  padding: 0.35rem;
  background: var(--paper);
  border: 1px solid color-mix(in srgb, var(--on-light) 12%, transparent);
  border-radius: 14px;
  box-shadow:
    0 2px 8px -3px rgb(7 20 16 / 0.22),
    0 24px 48px -20px rgb(7 20 16 / 0.5);
  animation: pop-in 0.18s var(--ease-out) both;
}

@keyframes pop-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.985); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .fs-list, .dp { animation: none; }
}

/* --- the trip list -------------------------------------------------------- */
/* Wider than the field it hangs off. The trip column is the narrowest place a
   package name ever has to fit, and inside it "Valparai Explorer" wrapped onto
   two lines with the price stranded beside the first. A popover is allowed to
   be wider than its trigger; a wrapped list of names is not. */
.fs-list {
  width: max(100%, 23rem);
  /* …but never wider than the screen. On a 390px phone the 23rem floor put the
     right edge 17px past the viewport, which is a horizontal scrollbar on the
     whole page. The gutter either side of the card is the budget. */
  max-width: calc(100vw - 2.5rem);
  max-height: 19rem;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.fs-name { white-space: nowrap; }

.fs-opt {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.9rem;
  padding: 0.6rem 0.7rem;
  border-radius: 9px;
  cursor: pointer;
  /* No transition: the highlight follows the cursor, and a 150ms fade on a
     list you are running down turns into a smear. */
}

.fs-opt.is-active { background: color-mix(in srgb, var(--gold) 16%, transparent); }
.fs-opt[aria-selected="true"] { background: color-mix(in srgb, var(--gold) 26%, transparent); }

.fs-name {
  font-size: var(--step--1);
  font-variation-settings: "wdth" 100, "wght" 600;
  color: var(--on-light);
}

.fs-meta {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex: none;
  font-size: var(--step--2);
  color: var(--on-light-dim);
  white-space: nowrap;
}

.fs-meta b {
  font-variation-settings: "wdth" 92, "wght" 700;
  font-variant-numeric: tabular-nums;
  color: var(--gold-deep);
}

/* --- the calendar --------------------------------------------------------- */
.dp { width: 19.5rem; padding: 0.8rem; }

.dp-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.55rem;
}

.dp-title {
  font-size: var(--step--1);
  color: var(--on-light-dim);
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.dp-title b {
  font-variation-settings: "wdth" 100, "wght" 700;
  color: var(--on-light);
}

.dp-nav {
  display: grid;
  place-items: center;
  width: 1.9rem;
  height: 1.9rem;
  flex: none;
  border: none;
  border-radius: 50%;
  background: color-mix(in srgb, var(--on-light) 7%, transparent);
  color: var(--on-light);
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

.dp-nav:hover:not(:disabled) { background: var(--gold); color: var(--ink); }
.dp-nav:disabled { opacity: 0.3; cursor: not-allowed; }

.dp-dow,
.dp-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}

.dp-dow {
  margin-bottom: 0.25rem;
  font-size: 0.6rem;
  font-variation-settings: "wdth" 88, "wght" 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--on-light-dim);
  text-align: center;
}

.dp-day {
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 8px;
  background: none;
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  color: var(--on-light);
  cursor: pointer;
  transition: background-color 0.15s var(--ease), color 0.15s var(--ease);
}

.dp-day:hover:not(:disabled) { background: color-mix(in srgb, var(--gold) 22%, transparent); }
.dp-day.is-past { opacity: 0.28; cursor: not-allowed; }

/* Today is a ring, the choice is a fill — so the two never read as the same
   thing at a glance. */
.dp-day.is-today { box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--on-light) 30%, transparent); }

.dp-day.is-chosen {
  background: var(--canopy);
  color: var(--on-dark);
  box-shadow: none;
}

.dp-day.is-chosen:hover { background: var(--canopy); }

.dp-pad { aspect-ratio: 1; }

/* --- the season markers --------------------------------------------------
   Straight out of the season copy on /valparai/ — see monthTone in
   data/valparai.mjs, which is derived from the same list the page prints. */
.dp-tone {
  display: inline-block;
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  flex: none;
}

.dp-tone-best { background: var(--gold); }
.dp-tone-caution { background: var(--ember); }
.dp-tone-good { background: color-mix(in srgb, var(--on-light) 22%, transparent); }

.dp-note {
  margin-top: 0.6rem;
  padding: 0.55rem 0.65rem;
  border-radius: 9px;
  background: color-mix(in srgb, var(--ember) 12%, transparent);
  font-size: var(--step--2);
  line-height: 1.45;
  color: var(--on-light);
}

.dp-legend {
  display: flex;
  gap: 0.9rem;
  margin-top: 0.6rem;
  padding-top: 0.55rem;
  border-top: 1px solid color-mix(in srgb, var(--on-light) 10%, transparent);
  font-size: 0.62rem;
  color: var(--on-light-dim);
}

.dp-legend span { display: inline-flex; align-items: center; gap: 0.35rem; }

/* The last field in the row would push its popover off the right edge. */
.bookcard-row > .bf:last-of-type .fs-list,
.bookcard-row > .bf:last-of-type .dp { left: auto; right: 0; }

@media (max-width: 460px) {
  .dp { width: min(19.5rem, calc(100vw - 3rem)); }
}

/* Opened upwards when there is not room below — set by placePopover() in
   site.js after the panel is visible and can be measured. */
.bf-box-fancy.is-up .fs-list,
.bf-box-fancy.is-up .dp {
  top: auto;
  bottom: calc(100% + 0.45rem);
}

.bf-box-fancy.is-up .fs-list,
.bf-box-fancy.is-up .dp { animation-name: pop-in-up; }

@keyframes pop-in-up {
  from { opacity: 0; transform: translateY(6px) scale(0.985); }
  to { opacity: 1; transform: none; }
}
