/* Staycation International
   Palette and type per Branding Guidelines.
   Two full themes, swapped via [data-theme] on :root.
   Sans is Archivo, standing in for Poppins per the grotesque swap. */

:root {
  /* ---- brand constants, identical in both themes ---- */
  --gold: #B98A44;
  --bronze: #8A6A2F;
  --champagne: #D4A55C;

  /* ---- type scale: 1.25 modular, 18px base ---- */
  --t-label: 0.75rem;      /* 12 */
  --t-caption: 0.875rem;   /* 14 */
  --t-body: 1.125rem;      /* 18 */
  --t-lede: 1.375rem;      /* 22 */
  --t-h3: 1.75rem;         /* 28 */
  --t-h2s: 2.1875rem;      /* 35 */
  --t-h2: 2.75rem;         /* 44 */
  --t-h1s: 3.4375rem;      /* 55, the rung between 44 and 69 */
  --t-h1: 4.3125rem;       /* 69 */

  --serif: "Playfair Display", Georgia, serif;
  --sans: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --gutter: clamp(1.5rem, 5vw, 5.5rem);
  --section-y: clamp(4rem, 8vw, 7rem);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

:root,
:root[data-theme="dark"] {
  --band-1: #1D1D1D;
  --band-2: #0F0F0F;
  --band-3: #080808;
  --surface: #242320;
  --text: #F5F1EA;
  --text-soft: #CFC8BD;
  /* lifted from Stone #8A8478: at 4.23:1 on --surface it failed AA.
     #948D80 clears 4.5 on every band we use it against. */
  --text-mute: #948D80;
  --rule: rgba(207, 200, 189, 0.14);
  --rule-strong: rgba(207, 200, 189, 0.30);
  /* screen, not overlay: overlay multiplies dark bases, so on #080808
     even a white texture only reaches #101010. screen adds light. */
  /* lowered from 0.16: the hero and closing now carry real material,
     so the middle sections step back and the contrast widens */
  --tex-opacity: 0.10;
  --tex-blend: screen;
  --vignette: rgba(0, 0, 0, 0.45);
  --pool: 10%;
}

/* Dark is the chosen direction. The light set is kept because switching
   back is then one attribute on <html>, not a rewrite. */
:root[data-theme="light"] {
  --band-1: #FBF9F5;
  --band-2: #EDE7DB;
  --band-3: #E2DACB;
  --surface: #FFFFFF;
  --text: #1D1D1D;
  --text-soft: #4A473F;
  --text-mute: #7C7669;
  --rule: rgba(29, 29, 29, 0.13);
  --rule-strong: rgba(29, 29, 29, 0.26);
  --tex-opacity: 0.11;
  --tex-blend: multiply;
  --vignette: rgba(76, 68, 52, 0.16);
  --pool: 14%;
}

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* tells the browser to render scrollbars and native controls dark */
  color-scheme: dark;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* the header is fixed, so anchor jumps would land the heading underneath it */
section[id] { scroll-margin-top: 100px; }

/* no double-tap zoom delay, and a tap flash in brand gold rather than
   the platform default blue */
a, button, summary, [role="button"] {
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(185, 138, 68, 0.22);
}

body {
  margin: 0;
  background: var(--band-1);
  color: var(--text-soft);
  font-family: var(--sans);
  font-weight: 300;
  font-size: var(--t-body);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.5s var(--ease), color 0.5s var(--ease);
}

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

h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 500;
  color: var(--text);
  line-height: 1.1;
  letter-spacing: -0.018em;
  margin: 0;
  text-wrap: balance;
}
/* caps at 55, the same size the desktop hero uses. Previously the clamp
   ran to 69, so tablets rendered a larger headline than desktop did. */
h1 { font-size: clamp(2.5rem, 1.55rem + 3.4vw, var(--t-h1s)); line-height: 1.06; }
h2 { font-size: clamp(1.9rem, 1.3rem + 2.6vw, var(--t-h2)); }
h3 { font-size: clamp(1.4rem, 1.2rem + 0.9vw, var(--t-h3)); letter-spacing: -0.012em; }
h1 em, h2 em { font-style: italic; color: var(--gold); }

p { margin: 0 0 1.15rem; max-width: 64ch; }
p:last-child { margin-bottom: 0; }
a { color: inherit; text-decoration: none; }

/* ---------- primitives ---------- */

.wrap { max-width: 1240px; margin: 0 auto; padding-inline: var(--gutter); position: relative; }
.section { padding-block: var(--section-y); position: relative; }

.band-1 { background: var(--band-1); }
.band-2 { background: var(--band-2); }
.band-3 { background: var(--band-3); }

.eyebrow {
  font-family: var(--sans);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 1.35rem;
}
.eyebrow.muted { color: var(--text-mute); }

.rule { width: 52px; height: 1px; background: var(--gold); border: 0; margin: 1.75rem 0; }

/* scales with the headline. Held flat at 22px it sat too close to a
   40px mobile h1, while reading correctly against 55px on desktop. */
.lede {
  font-size: clamp(1.1875rem, 1.06rem + 0.55vw, var(--t-lede));
  line-height: 1.55;
  color: var(--text-soft);
  max-width: 52ch;
}
.section-head { max-width: 60ch; margin-bottom: clamp(2.5rem, 4.5vw, 3.5rem); }

/* On wide screens a left-aligned head leaves the right half dead.
   Where there is a lede, it moves alongside and fills the measure. */
@media (min-width: 1040px) {
  .section-head:has(.lede) {
    max-width: none;
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.8fr);
    column-gap: clamp(2.5rem, 5vw, 5.5rem);
  }
  .section-head:has(.lede) > .eyebrow { grid-column: 1; grid-row: 1; }
  .section-head:has(.lede) > h2      { grid-column: 1; grid-row: 2; }
  .section-head:has(.lede) > .rule   { grid-column: 1; grid-row: 3; margin-bottom: 0; }
  .section-head:has(.lede) > .lede   {
    grid-column: 2; grid-row: 2 / 4;
    align-self: end;
    max-width: 44ch;
    margin-bottom: 0.4rem;
  }
}
.caption { font-size: var(--t-caption); color: var(--text-mute); }

/* ---------- depth: texture, vignette, light pools ----------
   Three cheap layers so no band is a flat fill. */

.tex {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  opacity: var(--tex-opacity);
  mix-blend-mode: var(--tex-blend);
  pointer-events: none;
}
.tex--soft { opacity: calc(var(--tex-opacity) * 0.55); }

/* Photographic material, hero and closing only. Each gets its own opacity
   because the two source images differ a lot in brightness, so a shared
   value would make one shout and the other vanish.
   Drift is `alternate`, so it eases out and back with no loop seam. */
.photo { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.photo::before {
  content: "";
  position: absolute;
  inset: -8%;
  background-size: cover;
  background-position: center;
  opacity: var(--photo-op);
  animation: photodrift var(--photo-dur) ease-in-out infinite alternate;
  will-change: transform;
}
/* 0.80 and 0.30 are the ceilings. Above them the gold italic in each
   heading falls below 3:1 against the brightest part of the image. */
.photo--hero {
  --photo-op: 0.80;
  --photo-dur: 60s;
}
.photo--hero::before { background-image: url("../img/hero-stone.jpg"); }
.photo--closing {
  --photo-op: 0.30;
  --photo-dur: 75s;
}
.photo--closing::before {
  background-image: url("../img/closing-wall.jpg");
  animation-direction: alternate-reverse;
}

/* Middle sections: the same stone, quiet and static. Each section takes a
   different crop via --pos so it reads as material rather than a repeat.
   No animation here; six drifting layers is a lot to composite for
   something nobody is meant to notice. */
.photo--sub {
  --photo-op: 0.13;
}
.photo--sub::before {
  inset: 0;
  background-image: url("../img/hero-stone.jpg");
  background-position: var(--pos, center);
  animation: none;
  will-change: auto;
}
@keyframes photodrift {
  from { transform: scale(1) translate3d(0, 0, 0); }
  to   { transform: scale(1.11) translate3d(-1.6%, -1.1%, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .photo::before { animation: none; }
}

/* edges fall away, so the band has a centre */
.section::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(135% 100% at 50% 30%, transparent 42%, var(--vignette) 100%);
}

/* an off-centre warm pool, so light appears to come from somewhere */
.glow::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(48% 60% at var(--gx, 18%) var(--gy, 22%),
    color-mix(in srgb, var(--gold) var(--pool), transparent), transparent 72%);
}
.glow--right { --gx: 84%; --gy: 70%; }
.glow--low { --gx: 50%; --gy: 108%; }

.section > .wrap { z-index: 2; }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--sans);
  font-size: var(--t-caption);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 1rem 1.9rem;
  border-radius: 999px;
  border: 1px solid var(--gold);
  color: var(--gold);
  background: transparent;
  cursor: pointer;
  transition: background-color 0.4s var(--ease), color 0.4s var(--ease), border-color 0.4s var(--ease);
}
.btn:hover { background: var(--gold); color: #0F0F0F; }
.btn--solid { background: var(--gold); color: #0F0F0F; }
.btn--solid:hover { background: var(--champagne); border-color: var(--champagne); }
.btn--quiet { border-color: var(--rule-strong); color: var(--text-soft); }
.btn--quiet:hover { background: transparent; border-color: var(--text); color: var(--text); }

:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* ---------- header ---------- */

.header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 90;
  padding-block: 1.3rem;
  transition: padding 0.45s var(--ease);
}

/* The blurred bar is drawn by this pseudo-element, not by .header itself.
   backdrop-filter makes an element the containing block for its fixed
   descendants. While it sat on .header, the moment .is-stuck landed the
   fixed mobile nav stopped resolving against the viewport and resolved
   against the header strip instead: the menu opened correctly at the top
   of the page and collapsed into the bar once scrolled. Isolating the
   filter here keeps .nav anchored to the viewport at every scroll
   position. Do not move backdrop-filter back onto .header. */
.header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-bottom: 1px solid transparent;
  transition: background-color 0.45s var(--ease), border-color 0.45s var(--ease);
}
.header.is-stuck::before, .header--solid::before {
  background: color-mix(in srgb, var(--band-2) 92%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom-color: var(--rule);
}
.header.is-stuck, .header--solid { padding-block: 0.8rem; }
.header .wrap { display: flex; align-items: center; justify-content: space-between; gap: 2rem; }
.brand img { width: 152px; height: auto; }

.nav { display: flex; align-items: center; gap: clamp(1.25rem, 2.4vw, 2.25rem); }
/* :not(.btn) so the nav colour rule cannot outrank .btn--solid,
   which is a lower-specificity selector. */
.nav a:not(.btn) {
  font-size: var(--t-label);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text-soft);
  transition: color 0.3s var(--ease);
}
.nav a:not(.btn):hover { color: var(--gold); }
.nav .btn { padding: 0.7rem 1.35rem; }

.nav-toggle {
  display: none;
  background: none; border: 0; color: var(--text); cursor: pointer;
  width: 44px; height: 44px;
  align-items: center; justify-content: center;
  padding: 0;
  /* must sit above the open overlay, or it becomes unreachable */
  position: relative;
  z-index: 100;
}
.nav-toggle svg { width: 24px; height: 24px; }
.nav-toggle .i-close { display: none; }
.nav-toggle[aria-expanded="true"] .i-menu { display: none; }
.nav-toggle[aria-expanded="true"] .i-close { display: block; }

@media (max-width: 980px) {
  .nav-toggle { display: inline-flex; }
  .nav {
    position: fixed; inset: 0;
    z-index: 95;
    flex-direction: column; justify-content: center; gap: 1.75rem;
    background: var(--band-2);
    overscroll-behavior: contain;
    padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
    opacity: 0; visibility: hidden;
    transition: opacity 0.4s var(--ease), visibility 0.4s;
  }
  .nav.is-open { opacity: 1; visibility: visible; }
  .nav a:not(.btn) { font-size: 1rem; }
}

/* ---------- hero ---------- */

.hero {
  position: relative;
  min-height: 88svh;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: var(--band-3);
  padding-block: clamp(7rem, 14vw, 10rem) clamp(4rem, 8vw, 6rem);
}
.hero__media { position: absolute; inset: 0; z-index: 0; }
.hero__media video { width: 100%; height: 100%; object-fit: cover; opacity: 0.45; }

.hero__light {
  position: absolute; inset: -25%; z-index: 0;
  background:
    radial-gradient(38% 46% at 24% 30%, color-mix(in srgb, var(--gold) 30%, transparent), transparent 68%),
    radial-gradient(44% 40% at 76% 64%, color-mix(in srgb, var(--bronze) 26%, transparent), transparent 70%);
  filter: blur(30px);
  animation: drift 40s var(--ease) infinite alternate;
}
@keyframes drift {
  from { transform: translate3d(-3%, -2%, 0) scale(1); }
  to   { transform: translate3d(4%, 3%, 0) scale(1.12); }
}

.hero__scrim {
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(to top,
    color-mix(in srgb, var(--band-3) 92%, transparent) 0%,
    color-mix(in srgb, var(--band-3) 45%, transparent) 50%,
    color-mix(in srgb, var(--band-3) 70%, transparent) 100%);
}
.hero .wrap { z-index: 3; width: 100%; }
.hero h1 { max-width: 15ch; }
.hero .lede { margin-top: 1.75rem; }
.actions { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 2.5rem; }

/* Headline left, supporting copy and buttons set against its baseline,
   so the right half of the hero carries weight instead of sitting empty. */
@media (min-width: 1040px) {
  .hero .wrap {
    display: grid;
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.82fr);
    column-gap: clamp(3rem, 6vw, 6rem);
    align-items: end;
  }
  .hero .eyebrow { grid-column: 1 / -1; grid-row: 1; }
  /* one rung down and a wider measure: fewer lines, so the headline mass
     sits closer to the block beside it */
  .hero h1       { grid-column: 1; grid-row: 2; max-width: 16ch; }
  .hero .rule    { grid-column: 1; grid-row: 3; margin-bottom: 0; }
  /* one block, centred against the headline. Splitting it top and bottom
     just moved the gap into the middle. */
  .hero__aside {
    grid-column: 2; grid-row: 2 / 4;
    align-self: center;
  }
  .hero__aside .lede { margin-top: 0; max-width: 38ch; }
  .hero__aside .actions { margin-top: 2.25rem; }
}

/* ---------- service grid ---------- */

.grid { display: grid; gap: 1px; background: var(--rule); border-block: 1px solid var(--rule); }
@media (min-width: 760px) { .grid { grid-template-columns: 1fr 1fr; } }
.cell { background: var(--band-1); padding: clamp(1.75rem, 3.2vw, 2.75rem); }
.cell__num {
  font-family: var(--serif); font-style: italic;
  font-size: var(--t-lede); color: var(--bronze);
  display: block; margin-bottom: 0.9rem;
}
.cell h3 { margin-bottom: 0.75rem; }
.cell p { color: var(--text-mute); font-size: var(--t-body); }

/* ---------- packages ---------- */

/* `align-items: start` was sizing each card to its own content, so the
   three finished at three different heights and stepped down like a
   ladder. Stretch is the default and gives every card the height of the
   tallest, which is Essential. In the stacked layout each row is its own
   height, so this only applies once they sit side by side. */
.tiers { display: grid; gap: clamp(1rem, 2vw, 1.5rem); }
@media (min-width: 1040px) { .tiers { grid-template-columns: repeat(3, 1fr); } }
.tier {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-top: 2px solid var(--gold);
  padding: clamp(1.6rem, 2.8vw, 2.25rem);
  /* the card fills the stretched track rather than the content floating
     in a taller box */
  display: flex;
  flex-direction: column;
}
.tier h3 { font-size: clamp(1.6rem, 1.3rem + 1.1vw, var(--t-h2s)); color: var(--gold); margin-bottom: 0.7rem; }
.tier__desc {
  color: var(--text-mute); font-size: var(--t-caption); line-height: 1.6;
  margin-bottom: 1.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--rule);
}
.tier ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; }
.tier li {
  position: relative; padding-left: 1.3rem;
  font-size: var(--t-caption); line-height: 1.6; color: var(--text-soft);
}
.tier li::before {
  content: "\203A"; position: absolute; left: 0; top: -0.15rem;
  color: var(--gold); font-size: var(--t-body);
}

/* ---------- process: scrubbed progress sequence ---------- */

.process { --progress: 0; --marker-op: 0; }
.process__track { position: relative; margin-top: clamp(2rem, 4vw, 3rem); }

/* Spans first dot centre to last dot centre, so it stops where the
   sequence stops. Horizontal only; the stacked mobile layout drops it. */
.process__line { display: none; }
@media (min-width: 1040px) {
  .process__line {
    display: block;
    position: absolute;
    left: 27px;
    right: calc(25% - 27px);
    top: 27px;
    height: 1px;
    background: var(--rule-strong);
    z-index: 0;
  }
}

/* Stacked layout gets the same idea turned on its side: a rule from the
   first dot's centre to the last dot's centre, filling as you scroll.
   --v-top and --v-len are measured in site.js, because the gap between
   the first and last dot depends on how the step copy wraps and is not
   knowable in CSS. The dots have an opaque fill and sit above this, so
   the rule passes behind them rather than through them. */
.process__vline { display: none; }
@media (max-width: 1039px) {
  /* The stacked step layout that clears a path for this rule lives with
     the other .step rules further down, so that it lands after them in
     source order and actually wins. */
  .process__vline {
    display: block;
    position: absolute;
    /* the dot's own centre, measured in site.js, so this cannot drift out
       of step with the dot size the way a hard-coded value would */
    left: var(--v-left, 22px);
    top: var(--v-top, 22px);
    height: var(--v-len, 0px);
    width: 1px;
    background: var(--rule-strong);
    z-index: 0;
  }
  .process__vline::after {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: calc(var(--progress) * 100%);
    background: var(--gold);
  }
}

/* Travelling head of the progress line. Fades out as it arrives at each
   dot, so it reads as merging into the number rather than passing over it. */
.process__marker {
  position: absolute;
  top: 50%;
  left: calc(var(--progress) * 100%);
  width: 13px;
  height: 13px;
  margin: -6.5px 0 0 -6.5px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--gold) 20%, transparent);
  opacity: var(--marker-op);
  transition: opacity 0.28s var(--ease);
  pointer-events: none;
}
.process__line::after {
  content: "";
  position: absolute; inset: 0 auto 0 0;
  width: calc(var(--progress) * 100%);
  background: var(--gold);
}

.steps { display: grid; gap: 2.25rem; position: relative; z-index: 1; }
/* four across needs real width; below this they stack rather than squeeze */
@media (min-width: 1040px) { .steps { grid-template-columns: repeat(4, 1fr); gap: 1.5rem; } }

.step { padding-right: 1.25rem; }
.step__dot {
  position: relative;
  z-index: 2;
  width: 54px; height: 54px;
  border-radius: 50%;
  border: 1px solid var(--rule-strong);
  background: var(--band-1);
  display: grid; place-items: center;
  font-family: var(--serif); font-style: italic;
  font-size: var(--t-lede);
  color: var(--text-mute);
  margin-bottom: 1.4rem;
  transition: color 0.45s var(--ease), border-color 0.45s var(--ease),
              background-color 0.45s var(--ease), box-shadow 0.45s var(--ease),
              transform 0.45s var(--ease);
}
.step.is-lit .step__dot {
  background: var(--gold);
  border-color: var(--gold);
  color: #0F0F0F;
  box-shadow: 0 0 0 7px color-mix(in srgb, var(--gold) 15%, transparent);
  transform: scale(1.07);
}
.step h3 { font-size: clamp(1.2rem, 1.1rem + 0.5vw, 1.5rem); margin-bottom: 0.6rem; }
.step p { color: var(--text-mute); font-size: var(--t-body); margin: 0; max-width: 34ch; }

/* Stacked, each step's copy sits directly beneath its own dot, so the rule
   joining the dots has nowhere to run but straight down through the text.
   The horizontal layout avoids this for free by putting the line above the
   row rather than through it. Here the dot lifts out of the flow into a
   rail of its own and the copy is indented clear of it, which also buys
   back the right-hand padding the wide layout needs and this one does not.
   These must stay after the base .step rules to outrank them. */
@media (max-width: 1039px) {
  .step {
    position: relative;
    padding-left: 60px;
    padding-right: 0;
  }
  .step__dot {
    position: absolute;
    left: 0;
    top: 0;
    width: 44px;
    height: 44px;
    font-size: var(--t-body);
    margin-bottom: 0;
  }
  /* sets the heading's first line against the middle of the dot rather
     than against its top edge */
  .step h3 { padding-top: 0.5rem; }
}

/* ---------- response panel ---------- */

.split { display: grid; gap: clamp(2rem, 4vw, 4rem); }
@media (min-width: 920px) { .split { grid-template-columns: 1fr 1fr; align-items: center; } }

.panel { border: 1px solid color-mix(in srgb, var(--gold) 34%, transparent); padding: clamp(1.75rem, 4vw, 3rem); }
.panel__hours {
  font-family: var(--serif);
  font-size: clamp(1.5rem, 1.1rem + 1.9vw, var(--t-h2s));
  color: var(--text); line-height: 1.25; margin: 0 0 1.15rem; max-width: 22ch;
}
.panel__hours span { color: var(--gold); font-style: italic; }
.panel p:last-child { color: var(--text-mute); font-size: var(--t-caption); }

/* ---------- faq ---------- */

.faq { max-width: 880px; }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  cursor: pointer; list-style: none;
  padding-block: 1.35rem;
  font-family: var(--serif);
  font-size: clamp(1.15rem, 1.05rem + 0.5vw, 1.45rem);
  color: var(--text);
  display: flex; justify-content: space-between; align-items: center; gap: 2rem;
  transition: color 0.3s var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--gold); }
.faq summary::after {
  content: ""; flex: none; width: 10px; height: 10px;
  border-right: 1px solid var(--gold); border-bottom: 1px solid var(--gold);
  transform: rotate(45deg) translate(-3px, -3px);
  transition: transform 0.35s var(--ease);
}
.faq details[open] summary::after { transform: rotate(225deg) translate(-3px, -3px); }
.faq details p { color: var(--text-mute); padding-bottom: 1.5rem; font-size: var(--t-body); }

/* ---------- closing cta ---------- */

.cta { text-align: center; }
.cta h2 { margin-inline: auto; max-width: 17ch; }
.cta .lede { margin: 1.5rem auto 0; }
.cta .rule { margin-inline: auto; }
.cta .actions { justify-content: center; }

/* ---------- footer ---------- */

.footer { background: var(--band-3); padding-block: clamp(3rem, 5vw, 4.5rem) 2rem; border-top: 1px solid var(--rule); }
.footer__top { display: grid; gap: 2.5rem; margin-bottom: 3rem; }
@media (min-width: 840px) { .footer__top { grid-template-columns: 1.4fr 1fr 1.2fr; } }
.footer .footer-h {
  font-family: var(--sans); font-size: var(--t-label); font-weight: 500;
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--text-mute); margin: 0 0 1.1rem;
}
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.35rem; }
/* 24px minimum touch height, WCAG 2.5.8 */
.footer li > a {
  display: inline-flex; align-items: center;
  min-height: 26px;
}
.footer a { color: var(--text-soft); font-size: var(--t-caption); transition: color 0.3s var(--ease); }
.footer a:hover { color: var(--gold); }
.footer__brand img { width: 178px; height: auto; margin-bottom: 1.5rem; }

.ico {
  display: inline-flex; align-items: center; gap: 0.65rem;
}
.ico svg { width: 17px; height: 17px; flex: none; fill: var(--gold); transition: fill 0.3s var(--ease); }
.footer a:hover .ico svg, .ico:hover svg { fill: var(--champagne); }

.footer__legal {
  border-top: 1px solid var(--rule); padding-top: 1.75rem;
  display: flex; flex-wrap: wrap; gap: 0.75rem 2rem; justify-content: space-between;
  font-size: var(--t-caption); color: var(--text-mute);
}

/* ---------- legal and error pages ---------- */

/* Prose reads best in a single centred column, not stranded in the
   left half of a 1240px container. */
.doc { padding-top: clamp(7rem, 12vw, 9.5rem); }
.doc .wrap { max-width: 860px; }
.doc .section-head { max-width: none; }
.doc__body { max-width: none; }
.doc__body h3 {
  font-size: clamp(1.25rem, 1.1rem + 0.6vw, 1.6rem);
  margin: 2.75rem 0 0.85rem;
}
.doc__body h3:first-child { margin-top: 0; }
.doc__body p, .doc__body li { color: var(--text-soft); }
.doc__body ul { padding-left: 1.1rem; margin: 0 0 1.15rem; }
.doc__body li { margin-bottom: 0.5rem; }
.doc__body a { color: var(--gold); }
.doc__body a:hover { text-decoration: underline; }
.doc__updated {
  font-size: var(--t-caption);
  color: var(--text-mute);
  padding-bottom: 1.75rem;
  margin-bottom: 2.5rem;
  border-bottom: 1px solid var(--rule);
}

.oops { min-height: 72svh; display: grid; place-items: center; text-align: center; }
.oops .rule { margin-inline: auto; }
.oops .actions { justify-content: center; }

/* ---------- booking page ---------- */

.booking { padding-top: clamp(7rem, 12vw, 9.5rem); }
/* A floor while the iframe is still coming up, so the page does not jump
   when Cal.com reports its real height. Above that the box hugs the embed. */
.booking__embed {
  margin-top: clamp(2rem, 4vw, 3rem);
  min-height: 340px;
  border: 1px solid var(--rule);
  background: var(--band-2);
  overflow: hidden;
}
/* Its own panel now rather than a child of the embed, because it stands in
   for the embed when the calendar fails rather than sitting inside it. */
.booking__fallback {
  margin-top: clamp(2rem, 4vw, 3rem);
  border: 1px solid var(--rule);
  background: var(--band-2);
  padding: clamp(2rem, 4vw, 3.5rem);
  text-align: center;
  color: var(--text-soft);
}
.booking__fallback p { margin-inline: auto; }
.booking__fallback .actions { justify-content: center; }

/* ---------- motion ----------
   Scroll-driven where supported, so reveals scrub with the scroll
   in both directions. IntersectionObserver fallback lives in site.js. */

.reveal { opacity: 0; transform: translateY(14px); }
.reveal.is-in { opacity: 1; transform: none; transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); }

@supports (animation-timeline: view()) {
  .reveal {
    animation: revealIn linear both;
    animation-timeline: view();
    animation-range: entry 8% cover 32%;
    transition: none;
  }
  @keyframes revealIn { to { opacity: 1; transform: none; } }
}

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; animation: none; transition: none; }
  .hero__light { animation: none; }
  .process__line::after { width: 100%; }
  .process__vline::after { height: 100%; }
  .step .step__dot { color: var(--gold); border-color: var(--gold); }
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
/* the skip link has to be reachable, so it surfaces on keyboard focus */
a.sr-only:focus {
  position: fixed; top: 1rem; left: 1rem;
  width: auto; height: auto; margin: 0; overflow: visible; clip: auto;
  z-index: 200;
  padding: 0.85rem 1.4rem;
  background: var(--gold); color: #0F0F0F;
  font-size: var(--t-caption); font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase;
  border-radius: 999px;
}
