/* ============================================================
   assets/site.css  -  the shared stylesheet for every page.
   Extracted from index.html so the design system lives in one
   place. build.py inlines it back into dist/index.html.
   ============================================================ */

/* ============================================================
   Avadhuta School of Yoga, Kovalam, Kerala

   Colour: cream is the ground the page lives on, orange is
   secondary, blue is the highlight, navy is ink and the footer.
   Single-theme on purpose: the page does not follow the
   visitor's OS colour scheme.

   Type is deliberately small. Cormorant Garamond carries the
   headings at modest sizes; Jost carries everything else.

   Brand inks sampled from the logo file itself:
     saffron   #F7931C   vermilion #EE5A2A
   ============================================================ */

:root {
  --cream:       #FBF7F0;
  --cream-2:     #F6EFE2;
  --cream-3:     #F1E8D8;
  --card:        #FFFFFF;
  --peach:       #FAE7D2;

  --saffron:     #F7931C;
  --vermilion:   #EE5A2A;
  --orange-text: #A8410F;   /* 5.74:1 on cream */

  --blue:        #136C99;   /* 5.41:1 on cream, 4.80:1 on peach */
  --blue-soft:   rgba(19,108,153,.08);
  --blue-line:   rgba(19,108,153,.26);

  --ink:         #14303C;   /* 12.96:1 on cream */
  --ink-soft:    #42545E;   /*  7.39:1 on cream */
  --btn-ink:     #0C1F29;   /* the ink that sits on orange */
  --line:        rgba(20,48,60,.12);
  --line-strong: rgba(20,48,60,.26);

  --deep:        #14303C;
  --deep-ink:    #FBF7F0;
  --deep-soft:   #A9B8C0;
  --deep-blue:   #7FD3EE;
  --deep-line:   rgba(251,247,240,.16);

  --display: "Cormorant Garamond", "Iowan Old Style", Georgia, serif;
  --sans:    "Jost", "Futura", "Century Gothic", system-ui, sans-serif;

  --measure: 32rem;
  --pad:   clamp(1.25rem, 4.5vw, 4rem);
  --edge:  clamp(1.25rem, 4vw, 5.5rem);  /* the full-bleed margin: nav + hero */
  --band:  clamp(3.5rem, 6.5vw, 6rem);
  --shell: 1200px;
  --r:     3px;
}

/* ---------------- base ---------------- */
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: .9375rem;
  font-weight: 300;
  line-height: 1.7;
  letter-spacing: .005em;
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; }
a { color: inherit; }

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 400;
  line-height: 1.16;
  letter-spacing: -0.005em;
  text-wrap: balance;
  margin: 0;
}
h1 { font-size: clamp(1.75rem, 3vw, 2.625rem); }
h2 { font-size: clamp(1.375rem, 2.1vw, 1.875rem); }
h3 { font-size: 1.0625rem; }
p  { margin: 0; }
em { font-style: italic; }

.eyebrow {
  font-size: .625rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .22em;
  color: var(--blue);
  display: flex;
  align-items: center;
  gap: .7rem;
}
.eyebrow.mid { justify-content: center; }

.lede { font-size: 1rem; line-height: 1.72; color: var(--ink-soft); max-width: var(--measure); }
.prose { display: flex; flex-direction: column; gap: .95rem; }
.prose p { color: var(--ink-soft); max-width: var(--measure); }

.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: var(--pad); }
.narrow { max-width: 760px; margin-inline: auto; }
section { position: relative; scroll-margin-top: 4.5rem; }
.band { padding-block: var(--band); }
.on-cream  { background: var(--cream); }
.on-cream2 { background: var(--cream-2); }
.on-white  { background: var(--card); }
.on-peach  { background: var(--peach); }
.on-dusk   { background: var(--cream-3); }

.sec-head { display: flex; flex-direction: column; gap: .95rem; }
.sec-head h2 { max-width: 26ch; }
.sec-head.center { align-items: center; text-align: center; }
.sec-head.center h2 { max-width: 28ch; }
.sec-head.center .lede { text-align: center; }

/* ---------------- buttons ---------------- */
.btn {
  font-family: var(--sans);
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: .13em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  padding: .95rem 1.5rem;
  border-radius: var(--r);
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}
.btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
/* Both brand oranges carry dark ink, never white: #0C1F29 is 7.35:1 on
   saffron and 4.93:1 on vermilion; white on vermilion is 3.43:1. */
.btn-sun { background: var(--saffron); color: var(--btn-ink); }
.btn-sun:hover { background: #FFA22F; }
.btn-line { border-color: var(--line-strong); color: var(--ink); }
.btn-line:hover { border-color: var(--blue); color: var(--blue); }
/* on the hero photograph, where the ground is dark */
.btn-ghost { border-color: rgba(251,247,240,.45); color: #FBF7F0; }
.btn-ghost:hover { border-color: #FBF7F0; background: rgba(251,247,240,.1); }

.link {
  align-self: flex-start;
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--blue);
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding-bottom: 3px;
  border-bottom: 1px solid var(--blue-line);
  transition: border-color .18s ease;
}
.link:hover { border-bottom-color: currentColor; }
.link:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
.link svg { flex: none; }

/* ---------------- header: a cream bar, fixed over the hero ----------------
   Fixed rather than sticky, so the hero photograph still measures a full
   viewport height beneath it. */
header.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 40;
  background: var(--cream);
  border-bottom: 1px solid var(--line);
}
.nav-in {
  max-width: none;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 1rem;
  padding-inline: var(--edge);
  padding-block: .45rem;
}
/* the original stacked logo, kept whole */
.nav-in .logo { height: 3.1rem; width: auto; display: block; }
.nav-links {
  display: flex;
  justify-content: center;
  gap: clamp(.7rem, 1.5vw, 1.45rem);
  font-size: .75rem;
  font-weight: 400;
  letter-spacing: .13em;
  text-transform: uppercase;
}
.nav-links a {
  text-decoration: none;
  padding: .3rem 0;
  color: var(--ink-soft);
  border-bottom: 1px solid transparent;
  transition: color .16s ease, border-color .16s ease;
  white-space: nowrap;
}
.nav-links a:hover, .nav-links a:focus-visible { color: var(--blue); border-bottom-color: var(--blue); outline: none; }
.nav-links a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--blue); }
/* the in-panel CTA belongs to the mobile menu only */
.nav-links a.btn { display: none; }

/* a smaller button, up hard against the right edge */
.nav-in > .btn { font-size: .6875rem; padding: .72rem 1.2rem; letter-spacing: .13em; }

.menu-btn {
  display: none;
  width: 2.4rem; height: 2.4rem;
  border-radius: var(--r);
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  place-items: center;
  justify-self: end;
}
.menu-btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.menu-btn .bars { display: block; width: 15px; height: 8px; position: relative; }
.menu-btn .bars::before, .menu-btn .bars::after {
  content: ""; position: absolute; left: 0; right: 0; height: 1px;
  background: currentColor; transition: transform .2s ease;
}
.menu-btn .bars::before { top: 0; }
.menu-btn .bars::after { bottom: 0; }
.menu-btn[aria-expanded="true"] .bars::before { transform: translateY(3.5px) rotate(45deg); }
.menu-btn[aria-expanded="true"] .bars::after { transform: translateY(-3.5px) rotate(-45deg); }

@media (max-width: 1060px) {
  .nav-in { grid-template-columns: auto 1fr; }
  .menu-btn { display: grid; }
  .nav-in > .btn { display: none; }
  .nav-links {
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; justify-content: flex-start; gap: 0;
    padding: .5rem var(--edge) 1.5rem;
    background: var(--cream);
    border-bottom: 1px solid var(--line);
    display: none;
  }
  .nav-links[data-open="true"] { display: flex; }
  .nav-links a { padding: .85rem 0; border-bottom: 1px solid var(--line); font-size: .8125rem; }
  .nav-links a[aria-current="page"] { color: var(--blue); border-bottom-color: var(--line); }
  /* `.nav-links a` (0,1,1) outranks `.btn-sun` (0,1,0), so restate the colour */
  .nav-links a.btn {
    display: inline-flex; margin-top: 1.15rem; align-self: flex-start;
    color: var(--btn-ink); border-bottom: 0; padding: .9rem 1.4rem;
  }
}

/* ---------------- 1 · hero: photograph as the ground ---------------- */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--deep);
  color: #FBF7F0;
}
/* the slides sit stacked; only the one carrying .on is visible */
.hero-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 48%;
  opacity: 0;
  transition: opacity 1.4s ease;
}
.hero-img.on { opacity: 1; }
/* the first slide is marked .on in the markup, so there is a photograph in
   place before the script runs and nothing flashes on load */
@media (prefers-reduced-motion: reduce) {
  .hero-img { transition: none; }
}
/* the photograph is bright grass, so the type needs a real scrim to sit on */
.hero::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(100deg, rgba(10,25,32,.88) 0%, rgba(10,25,32,.62) 42%, rgba(10,25,32,.18) 72%, rgba(10,25,32,.32) 100%),
    linear-gradient(to top, rgba(10,25,32,.55) 0%, transparent 45%);
}
.hero .shell {
  position: relative; z-index: 2;
  max-width: none;
  padding-inline: var(--edge);
  padding-block: clamp(3rem, 7vw, 5rem);
}
.hero .eyebrow { color: var(--saffron); }
.hero h1 { margin-top: 1.15rem; max-width: 22ch; }
.hero h1 em { font-style: italic; color: var(--saffron); }
.hero .lede { margin-top: 1.15rem; color: rgba(251,247,240,.82); max-width: 34rem; }
.hero .cta { display: flex; flex-wrap: wrap; gap: .65rem; margin-top: 1.9rem; }

/* the two Google listings and the credentials, as a quiet row on the photo */
.hero-facts {
  display: flex; flex-wrap: wrap;
  gap: .5rem clamp(1.25rem, 3.5vw, 2.75rem);
  margin-top: clamp(2.25rem, 5vw, 3.25rem);
  padding-top: 1.25rem;
  border-top: 1px solid rgba(251,247,240,.2);
}
.hero-facts div { display: flex; align-items: baseline; gap: .45rem; }
.hero-facts b {
  font-family: var(--sans);
  font-size: 1.125rem; font-weight: 400;
  color: var(--saffron);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.hero-facts span {
  font-size: .625rem; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(251,247,240,.7);
}
.stars { color: var(--saffron); letter-spacing: .08em; }

/* one photograph, centred and contained, for a page that announces a single
   thing. A full-bleed hero was tried first and was too loud for a page whose
   whole content is a title and a form. */
.page-shot { margin: 0 auto; max-width: 52rem; }
.page-shot img {
  width: 100%; height: auto;
  aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--r);
  background: var(--cream-3);
}

/* ---------------- 2 · about: the film, large ---------------- */
/* the film is centred with the copy beneath it, both to the same measure */
.about-body { --film: 900px; margin-top: clamp(2rem, 4vw, 3rem); }
.about-body .film { max-width: var(--film); margin-inline: auto; }
.about-text {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
  gap: clamp(1.5rem, 3.5vw, 3rem);
  max-width: var(--film);
  margin: clamp(2rem, 4vw, 2.75rem) auto 0;
}

.film {
  display: block; position: relative;
  border-radius: var(--r);
  overflow: hidden;
  text-decoration: none;
  background: var(--deep);
}
.film img { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; transition: transform .9s cubic-bezier(.2,.6,.3,1); }
.film:hover img { transform: scale(1.02); }
.film .play {
  position: absolute; top: 50%; left: 50%;
  translate: -50% -50%;
  width: clamp(3.25rem, 5vw, 4.75rem); height: clamp(3.25rem, 5vw, 4.75rem);
  border-radius: 999px;
  background: var(--saffron);
  color: var(--btn-ink);
  display: grid; place-items: center;
  z-index: 2;
  transition: transform .25s ease, background-color .2s ease;
}
.film:hover .play { transform: scale(1.07); background: #FFA22F; }
.film:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
.film .cap {
  position: absolute; inset: auto 0 0 0; z-index: 2;
  padding: 1.35rem clamp(1.1rem, 2vw, 1.6rem);
  background: linear-gradient(to top, rgba(10,25,32,.8), transparent);
  color: #FBF7F0;
}
.film .cap b { display: block; font-family: var(--display); font-size: 1.25rem; font-weight: 400; }
.film .cap span {
  display: block; margin-top: .2rem;
  font-size: .625rem; letter-spacing: .16em; text-transform: uppercase;
  color: rgba(251,247,240,.72);
}

.about-text p { color: var(--ink-soft); }
.lineage {
  display: flex; flex-wrap: wrap;
  gap: .4rem 1.5rem;
  margin: 1.1rem 0 0;
  font-size: .625rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--blue);
}

/* ---------------- 2b · retreats ----------------
   Same card language as the films below: a picture does the work of saying
   what a retreat is, and the caption only has to say which one and when.
   Six on the home page; the rest live on retreats.html. */
.retreats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 270px), 1fr));
  gap: clamp(1rem, 1.6vw, 1.35rem) clamp(1rem, 1.6vw, 1.35rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
@media (min-width: 900px) { .retreats { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1000px) {
  #retreats > .shell {
    max-width: calc(var(--shell) + clamp(0px,
      calc((100vw - var(--shell)) / 2 + var(--pad) - 2rem), 150px) * 2);
  }
}
.retreat { display: block; }
.retreat .shot {
  display: block;
  position: relative;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--deep);
}
.retreat .shot img {
  width: 100%; height: auto;
  aspect-ratio: 8 / 5; object-fit: cover;
  transition: transform .8s cubic-bezier(.2,.6,.3,1);
}
.retreat h3 { margin-top: 1.05rem; font-size: clamp(1.1875rem, 1.6vw, 1.375rem); }
.retreat .sub { margin-top: .25rem; font-size: .8125rem; color: var(--ink-soft); }
.retreats-foot {
  display: flex; justify-content: center;
  margin-top: clamp(2.25rem, 4.5vw, 3.25rem);
}

/* ---------------- 3 · daily practice ----------------
   Not a card grid. The school's own thesis is that body and mind are one
   piece of work ("working on both simultaneously is the only way"), so the
   six benefits run down a spine, split by which of the two they serve. The
   division is the information; there are no numbers, because these are not a
   sequence. The right-hand strand is offset half a step so the two interleave.

   The spine is drawn as an absolutely positioned rule at 50%, not as a 1px
   grid track: a 1px track rounds away to nothing at some zoom levels. */
.strands {
  --spine-gap: clamp(1.75rem, 5vw, 4.5rem);
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: var(--spine-gap);
  margin-top: clamp(2.25rem, 4.5vw, 3.5rem);
}
.strands::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 1.75rem;
  bottom: 5.5rem;
  width: 1px;
  transform: translateX(-50%);
  background: linear-gradient(to bottom,
    transparent 0, var(--blue-line) 4%, var(--blue-line) 90%, transparent 100%);
}
.col { display: flex; flex-direction: column; gap: clamp(1.75rem, 3vw, 2.5rem); }
.col-l { text-align: right; align-items: flex-end; }
/* half a step down, so the strands read as interleaved rather than paired */
.col-r { margin-top: clamp(3rem, 7vw, 6rem); }

.strand-heads {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: var(--spine-gap);
  margin-bottom: clamp(1rem, 2vw, 1.5rem);
}
.strand-label {
  font-size: .625rem; font-weight: 500;
  letter-spacing: .24em; text-transform: uppercase;
  color: var(--blue);
}
.strand-heads .strand-label:first-child { text-align: right; }
.strand { position: relative; display: flex; flex-direction: column; gap: .45rem; }
/* the marker sits on the spine itself, half the column gap away */
.strand::after {
  content: "";
  position: absolute;
  top: .5rem;
  width: 7px; height: 7px;
  border-radius: 999px;
  background: var(--saffron);
  box-shadow: 0 0 0 5px var(--peach);
}
.col-l .strand::after { right: calc(var(--spine-gap) / -2 - 3.5px); }
.col-r .strand::after { left: calc(var(--spine-gap) / -2 - 3.5px); }
.strand h3 { font-size: clamp(1.125rem, 1.6vw, 1.375rem); max-width: 22ch; }
.strand p { color: var(--ink-soft); font-size: .875rem; line-height: 1.7; max-width: 33ch; }
.strand .side { display: none; }

/* where the two strands resolve */
.strands-foot {
  grid-column: 1 / -1;
  display: flex; flex-direction: column; align-items: center;
  gap: .9rem;
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  text-align: center;
}
.strands-foot img { width: 2.5rem; height: auto; }
.strands-foot p {
  font-family: var(--display);
  font-size: clamp(1.0625rem, 1.7vw, 1.3125rem);
  font-style: italic;
  line-height: 1.45;
  color: var(--ink);
  max-width: 32ch;
}

@media (max-width: 820px) {
  /* one strand, spine on the left, and the side becomes a tag on each item */
  .strands { grid-template-columns: 1fr; --spine-gap: 1.5rem; }
  .strands::before { left: 3.5px; transform: none; top: .5rem; bottom: 4.5rem; }
  .col { padding-left: 1.75rem; gap: 1.9rem; }
  .col-l { text-align: left; align-items: flex-start; }
  .col-r { margin-top: 1.9rem; }
  .strand-heads { display: none; }
  .col-l .strand::after, .col-r .strand::after { left: -1.75rem; right: auto; }
  .strand .side {
    display: block;
    font-family: var(--sans);
    font-size: .5625rem; font-weight: 500;
    letter-spacing: .2em; text-transform: uppercase;
    color: var(--blue);
  }
  .strands-foot { align-items: flex-start; text-align: left; padding-left: 1.75rem; }
}

/* ---------------- 4 · classes ---------------- */
.classes {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(.9rem, 1.4vw, 1.15rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
@media (min-width: 640px)  { .classes { grid-template-columns: repeat(2, 1fr); } }
/* eight cards, two rows of four, but only once the band is wide enough that
   four columns are not cramped */
@media (min-width: 1280px) { .classes { grid-template-columns: repeat(4, 1fr); } }
/* taller, quieter cards: a rule, a title, the copy, and one meta line */
.klass {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: clamp(1.5rem, 2.1vw, 1.9rem);
  min-height: 17.5rem;
  display: flex; flex-direction: column;
  text-decoration: none;
  transition: border-color .2s ease, box-shadow .3s ease;
}
.klass:hover { border-color: var(--blue-line); box-shadow: 0 1px 24px -12px rgba(20,48,60,.35); }
.klass .no {
  font-size: .625rem; font-weight: 500; letter-spacing: .2em;
  color: var(--blue); font-variant-numeric: tabular-nums;
}
.klass h3 {
  font-size: clamp(1.1875rem, 1.5vw, 1.375rem);
  margin-top: .8rem;
  max-width: 19ch;
}
.klass .rule { width: 2rem; height: 1px; background: var(--blue); opacity: .55; margin: 1.15rem 0; }
.klass p { color: var(--ink-soft); font-size: .875rem; line-height: 1.72; }
.klass .meta {
  margin-top: auto; padding-top: 1.35rem;
  display: flex; flex-wrap: wrap; gap: .35rem .85rem;
  font-size: .625rem; letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-soft);
}
.klass .meta span { display: flex; align-items: center; gap: .5rem; }
.klass .meta span + span::before {
  content: ""; width: 3px; height: 3px; border-radius: 999px;
  background: var(--blue); opacity: .6;
}
.klass-ask { background: var(--blue-soft); border-color: var(--blue-line); }
.klass-ask p { margin-top: 0; }

/* ---------------- 5 · gallery ----------------
   Two rows that both finish on the same line. Getting a flush bottom and
   uncropped figures at the same time is only possible if the pictures already
   match their slots, so the crops are baked into the files: four at 3:2 for
   the top row, three at 3:4 for the bottom, each framed around its subject.
   CSS then never has to trim anything. Every item in a row shares a width and
   a ratio, so the row heights are equal by construction. */
.gallery {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(.5rem, 1vw, .85rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
.gallery figure {
  margin: 0;
  overflow: hidden;
  border-radius: var(--r);
  background: var(--cream-3);
}
.gallery img {
  width: 100%;
  height: auto;
  display: block;
  transition: transform .9s cubic-bezier(.2,.6,.3,1);
}
.gallery figure:hover img { transform: scale(1.04); }
/* every row is four across the twelve, so the columns line up between rows
   and each row's items share a width and a ratio */
.g-wide, .g-tall { grid-column: span 3; }
@media (max-width: 900px)  { .g-wide, .g-tall { grid-column: span 6; } }
@media (max-width: 560px)  { .g-wide { grid-column: span 12; } .g-tall { grid-column: span 6; } }

/* ---------------- 6 · reviews: two rows, drifting apart ---------------- */
.listings {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: .6rem 1rem;
  margin-top: 1.5rem;
}
.listing {
  display: flex; align-items: center; gap: .7rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .55rem 1.1rem .55rem .85rem;
}
.listing b {
  font-family: var(--display); font-size: 1.25rem; font-weight: 400;
  color: var(--vermilion); font-variant-numeric: tabular-nums; line-height: 1;
}
.listing span { font-size: .625rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft); }

.rail { margin-top: clamp(2.25rem, 4.5vw, 3.25rem); display: flex; flex-direction: column; gap: clamp(1rem, 1.9vw, 1.6rem); }
.marquee {
  overflow: hidden;
  /* fade the ends so cards enter and leave rather than being chopped */
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.track {
  display: flex;
  gap: clamp(1rem, 1.9vw, 1.6rem);
  width: max-content;
  /* a fallback pace; the script recalculates it from the track width so the
     drift runs at a constant speed whatever the viewport */
  animation: drift 130s linear infinite;
}
.track.back { animation-direction: reverse; }
.marquee:hover .track, .marquee:focus-within .track { animation-play-state: paused; }
@keyframes drift { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  /* no drift; the rows become plain horizontal scrollers */
  .marquee { overflow-x: auto; mask-image: none; -webkit-mask-image: none; }
  .track { animation: none; }
}

.review {
  width: clamp(268px, 24vw, 470px);
  flex: none;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 1.55rem 1.65rem 1.35rem;
  display: flex; flex-direction: column; gap: .8rem;
}
.review .stars { font-size: .6875rem; }
.review blockquote {
  margin: 0; flex: 1;
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
  color: var(--ink);
}
.review footer {
  display: flex; align-items: center; gap: .65rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.review .who {
  width: 1.85rem; height: 1.85rem;
  border-radius: 999px;
  background: var(--blue-soft);
  color: var(--blue);
  display: grid; place-items: center;
  font-size: .6875rem; font-weight: 500;
  flex: none;
}
.review .name { font-size: .78125rem; color: var(--ink); line-height: 1.3; display: block; }
.review .when { font-size: .5625rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft); }

/* ---------------- 6b · yoga at your place ----------------
   The one course the school teaches that does not happen at the school, so a
   ninth card in the class grid would have buried it. It sits after the
   reviews and before the films, where the page has finished proving itself
   and has not yet started talking about anything else.

   Peach is a second helping of the middle of the page, and deliberate: it
   carries the warmest ground on the site, which is what a band whose whole
   argument is domestic wants. Cream above it, dusk below.

   The picture column is capped at 32rem, which is 512px against a 640px
   original: a half-band picture on a 1200px shell was visibly softer than
   everything above it, and held under its own native width it is sharp.
   The cap is also what closes the gutter — the copy is capped at 30rem, so
   a wider picture column is what keeps the two blocks talking to each
   other rather than drifting apart. The copy is deliberately short — one line of prose, then the
   three questions people actually ask, answered in a word or a phrase each.
   The picture follows the text in the source, so the heading still leads
   when the two stack. */
.athome {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  align-items: center;
}
@media (min-width: 900px) {
  .athome { grid-template-columns: minmax(0, 1fr) minmax(0, 32rem); }
}
.athome-text {
  display: flex; flex-direction: column;
  align-items: flex-start;
  gap: 1.05rem;
}
.athome-text h2 { max-width: 22ch; }
.athome-text .lede { max-width: 30rem; }
/* label and answer on one line each, ruled top and bottom: three facts that
   can be read at a glance without becoming a card */
.athome-list {
  margin: .5rem 0 0;
  width: 100%; max-width: 30rem;
  display: grid;
}
.athome-list div {
  display: grid;
  grid-template-columns: 4.75rem minmax(0, 1fr);
  gap: .75rem;
  align-items: baseline;
  padding: .8rem 0;
  border-top: 1px solid var(--line-strong);
}
.athome-list div:last-child { border-bottom: 1px solid var(--line-strong); }
.athome-list dt {
  font-size: .625rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--blue);
}
.athome-list dd {
  margin: 0;
  color: var(--ink-soft); font-size: .875rem; line-height: 1.6;
}
.athome-cta {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: .85rem 1.5rem;
  margin-top: .5rem;
}
/* on a phone the 4.75rem label column leaves too little for the answer, so
   the label sits on its own line and the answer gets the full width */
@media (max-width: 560px) {
  .athome-list div { grid-template-columns: 1fr; gap: .25rem; }
}
.athome-shot { margin: 0; }
.athome-shot img {
  width: 100%; height: auto;
  aspect-ratio: 3 / 2; object-fit: cover;
  border-radius: var(--r);
  background: var(--cream-3);
}

/* ---------------- 7 · videos ---------------- */
.videos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 270px), 1fr));
  gap: clamp(1rem, 1.6vw, 1.35rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
/* the media band runs wider than the text column, so the films get some size
   without shifting the heading off the page's left edge. Only above 900px,
   where there is room outside the shell to give back. */
/* Classes and videos run wider than the rest of the page. This widens the
   whole section container rather than pulling just the grid out with negative
   margins: offsetting the grid alone left each section heading stranded
   inboard of its own cards. Heading, cards and trailing link now share one
   left edge. The extra width is the space between the shell's content edge
   and the viewport edge, less a 2rem margin, so it tapers to nothing around
   1200px where there is nothing spare to give back. */
@media (min-width: 1000px) {
  #classes > .shell, #videos > .shell {
    max-width: calc(var(--shell) + clamp(0px,
      calc((100vw - var(--shell)) / 2 + var(--pad) - 2rem), 150px) * 2);
  }
}
.vid { display: block; text-decoration: none; }
.vid .shot {
  display: block;
  position: relative;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--deep);
}
.vid .shot img { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; transition: transform .8s cubic-bezier(.2,.6,.3,1); }
.vid:hover .shot img { transform: scale(1.03); }
.vid .play {
  position: absolute; top: 50%; left: 50%;
  translate: -50% -50%;
  width: clamp(3rem, 4vw, 3.75rem); height: clamp(3rem, 4vw, 3.75rem);
  border-radius: 999px;
  background: var(--saffron);
  color: var(--btn-ink);
  display: grid; place-items: center;
  transition: transform .22s ease, background-color .2s ease;
}
.vid:hover .play { transform: scale(1.08); background: #FFA22F; }
.vid:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
.vid h3 { margin-top: 1.05rem; font-size: clamp(1.1875rem, 1.6vw, 1.375rem); }
.vid .sub { margin-top: .25rem; font-size: .8125rem; color: var(--ink-soft); }


/* ---------------- contact: enquiry form + map ----------------
   The school runs everything through WhatsApp, so the form composes a message
   and hands it to wa.me rather than posting to a backend that does not exist.
   Nothing is stored, and nothing leaves the page on its own. */
.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 4.5vw, 3.5rem);
  align-items: start;
  margin-top: clamp(2.25rem, 4.5vw, 3.25rem);
  text-align: left;
}
@media (max-width: 900px) { .contact-grid { grid-template-columns: 1fr; } }

.form { display: flex; flex-direction: column; gap: 1.35rem; }
.field { display: flex; flex-direction: column; gap: .4rem; }
.field label {
  font-size: .5625rem; font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--blue);
}
.field input, .field select, .field textarea {
  font-family: var(--sans);
  font-size: .9375rem;
  font-weight: 300;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line-strong);
  border-radius: 0;
  padding: .5rem 0;
  width: 100%;
  transition: border-color .18s ease;
}
.field textarea { resize: vertical; min-height: 3.4rem; line-height: 1.6; }
.field select {
  appearance: none;
  cursor: pointer;
  padding-right: 1.5rem;
  background-image: linear-gradient(45deg, transparent 50%, var(--blue) 50%),
                    linear-gradient(135deg, var(--blue) 50%, transparent 50%);
  background-position: right 6px center, right 1px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-bottom-color: var(--blue);
}
.field input::placeholder, .field textarea::placeholder { color: var(--ink-soft); opacity: .6; }
.form-actions { display: flex; flex-wrap: wrap; gap: .65rem; margin-top: .35rem; }
/* A styled dropdown. The browser draws a <select>'s option list itself, in
   its own colours, and no rule here reaches it, so site.js swaps the select
   for a button and a listbox of the same options and keeps the select in
   sync behind them. Without the script the native select is still there and
   still submits. */
.sel { position: relative; }
.sel select {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none;
}
.sel-btn {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  width: 100%;
  font-family: var(--sans); font-size: .9375rem; font-weight: 300;
  color: var(--ink); text-align: left;
  background: transparent;
  border: 0; border-bottom: 1px solid var(--line-strong); border-radius: 0;
  padding: .5rem 0;
  cursor: pointer;
  transition: border-color .18s ease;
}
/* the same caret the fields used, drawn rather than imported */
.sel-btn::after {
  content: ""; flex: none;
  width: 6px; height: 6px;
  margin-bottom: 3px;
  border-right: 1px solid var(--blue); border-bottom: 1px solid var(--blue);
  transform: rotate(45deg);
  transition: transform .18s ease;
}
.sel-btn:hover, .sel[data-open="true"] .sel-btn { border-bottom-color: var(--blue); }
.sel-btn:focus-visible { outline: none; border-bottom-color: var(--blue); box-shadow: 0 1px 0 var(--blue); }
.sel[data-open="true"] .sel-btn::after { transform: rotate(225deg); margin-bottom: -3px; }
.sel-list {
  position: absolute; z-index: 30;
  top: calc(100% + .45rem); left: 0; right: 0;
  margin: 0; padding: .3rem;
  list-style: none;
  background: var(--card);
  border: 1px solid var(--line-strong); border-radius: var(--r);
  box-shadow: 0 20px 44px -26px rgba(20,48,60,.55);
  display: none;
}
.sel[data-open="true"] .sel-list { display: block; }
.sel-list li {
  padding: .6rem .7rem;
  font-size: .875rem; color: var(--ink-soft);
  border-radius: 2px;
  cursor: pointer;
}
.sel-list li:hover, .sel-list li.is-active { background: var(--blue-soft); color: var(--ink); }
.sel-list li[aria-selected="true"] { color: var(--ink); }
.sel-list li[aria-selected="true"]::after {
  content: ""; float: right;
  width: 9px; height: 5px; margin-top: .45rem;
  border-left: 1px solid var(--blue); border-bottom: 1px solid var(--blue);
  transform: rotate(-45deg);
}
@media (prefers-reduced-motion: reduce) {
  .sel-btn, .sel-btn::after { transition: none; }
}
/* a finger needs more than a pointer does: the control and each option clear
   44px on a phone */
@media (max-width: 700px) {
  .sel-btn { padding-block: .72rem; }
  .sel-list { padding: .35rem; }
  .sel-list li { padding: .78rem .7rem; }
}

.form-note { font-size: .75rem; line-height: 1.6; color: var(--ink-soft); }

.where { display: flex; flex-direction: column; gap: 1.25rem; align-items: flex-start; }
.map {
  width: 100%;
  border-radius: var(--r);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--cream-2);
  aspect-ratio: 4 / 3;
}
.map iframe { display: block; width: 100%; height: 100%; border: 0; }
/* the artifact build swaps the embed for this panel: that sandbox blocks
   third-party frames, so a live map would render as a blank rectangle */
.map-fallback {
  height: 100%;
  display: flex; flex-direction: column; justify-content: center; gap: .7rem;
  padding: clamp(1.5rem, 3vw, 2.25rem);
  text-align: center;
}
.map-fallback img { width: 2.5rem; height: auto; margin-inline: auto; }
.map-fallback b { font-family: var(--display); font-size: 1.125rem; font-weight: 400; color: var(--ink); }
.map-fallback span { font-size: .75rem; line-height: 1.6; color: var(--ink-soft); }
.where address { font-style: normal; font-size: .875rem; line-height: 1.75; color: var(--ink-soft); }
.where address b { display: block; color: var(--ink); font-weight: 400; }
.where .hours-line {
  width: 100%;
  font-size: .8125rem; color: var(--ink-soft);
  padding-top: 1rem; border-top: 1px solid var(--line);
}
.where .hours-line b { color: var(--ink); font-weight: 400; }
.wa-inline {
  display: inline-flex; align-items: center; gap: .5rem;
  font-size: 1rem; text-decoration: none;
  color: var(--orange-text);   /* 5.74:1 on cream */
}
.wa-inline:hover { color: var(--vermilion); }

/* ---------------- footer ---------------- */
.site-foot {
  background: var(--deep);
  color: var(--deep-ink);
  /* The bottom pad clears the floating WhatsApp button: it parks over this
     band once the page is scrolled to the end, and at 1.6rem it sat on the
     Privacy / Terms line with 7px to spare. */
  padding-block: clamp(3rem, 5.5vw, 4.5rem) 6rem;
}
.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(auto-fit, minmax(140px, 1fr));
  gap: 2.5rem clamp(1.5rem, 4vw, 3rem);
}
.foot-grid h2, .foot-grid h4 {
  font-family: var(--sans);
  font-size: .5625rem; font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--deep-soft);
  margin: 0 0 1rem;
}
.foot-grid ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .6rem; }
.foot-grid a {
  text-decoration: none;
  font-size: .8125rem; font-weight: 300;
  color: var(--deep-soft);
  transition: color .16s ease;
}
.foot-grid a:hover { color: var(--deep-blue); }
.foot-brand .logo { height: 4.25rem; width: auto; }
.foot-brand address {
  font-style: normal;
  color: var(--deep-soft);
  font-size: .875rem;
  margin-top: 1.15rem;
  max-width: 28ch;
  line-height: 1.75;
}
.wa {
  display: inline-flex; align-items: center; gap: .55rem;
  margin-top: 1.2rem;
  font-size: 1rem; font-weight: 400;
  text-decoration: none;
  color: var(--saffron);   /* 6.03:1 on the footer ink */
}
.hours {
  margin-top: 1.35rem; padding-top: 1.15rem;
  border-top: 1px solid var(--deep-line);
  font-size: .8125rem;
  color: var(--deep-soft);
  max-width: 24ch;
}
.hours b { display: block; font-family: var(--display); font-size: 1rem; font-weight: 400; color: var(--deep-ink); }
.socials { display: flex; gap: .5rem; margin-top: 1.35rem; }
.socials a {
  width: 2.1rem; height: 2.1rem;
  border-radius: 999px;
  border: 1px solid var(--deep-line);
  display: grid; place-items: center;
  color: var(--deep-soft);
  transition: color .16s ease, border-color .16s ease;
}
.socials a:hover { color: var(--deep-blue); border-color: var(--deep-blue); }
.foot-rule {
  margin-top: clamp(2.5rem, 4.5vw, 3.5rem);
  padding-top: 1.3rem;
  border-top: 1px solid var(--deep-line);
  display: flex; flex-wrap: wrap; gap: .6rem 1.5rem; justify-content: space-between;
  font-size: .6875rem; font-weight: 300;
  color: var(--deep-soft);
}
.foot-rule a { text-decoration: none; }
.foot-rule a:hover { color: var(--deep-blue); }

/* ---------------- floating WhatsApp ----------------
   The school runs on WhatsApp, so the chat is reachable from anywhere on the
   page and not only from the contact section. WhatsApp's own #25D366 with a
   white mark, as asked: the one place on this page where a colour comes from
   outside the palette, which is defensible because it is a product mark rather
   than a brand surface. Note white on #25D366 is 2.0:1: fine for a glyph this
   size and this well known, short of the 4.5:1 the label would want. Swap the
   ground for #128C7E (4.1:1 white) if that matters more than the exact green.
   Below the header's z-index so the open mobile menu still covers it. The
   label unfurls on hover and focus; the collapsed state keeps its accessible
   name, so it is never a mystery button. */
.wa-float {
  position: fixed;
  right: clamp(1rem, 2.5vw, 1.75rem);
  bottom: clamp(1rem, 2.5vw, 1.75rem);
  z-index: 30;
  display: inline-flex; align-items: center;
  height: 3.375rem; padding: 0 1.0625rem;
  border-radius: 999px;
  background: #25D366; color: #FFFFFF;
  text-decoration: none;
  box-shadow: 0 6px 20px rgba(20,48,60,.22);
  transition: background-color .45s ease, box-shadow .45s ease;
}
.wa-float svg { flex: none; }
.wa-float span {
  font-family: var(--sans);
  font-size: .6875rem; font-weight: 500;
  letter-spacing: .13em; text-transform: uppercase;
  white-space: nowrap;
  max-width: 0; padding-left: 0; opacity: 0; overflow: hidden;
  transition: max-width .6s cubic-bezier(.22,.61,.36,1), padding-left .6s cubic-bezier(.22,.61,.36,1), opacity .45s ease;
}
.wa-float:focus-visible { background: #1EBE5A; box-shadow: 0 10px 26px rgba(20,48,60,.28); }
.wa-float:focus-visible span { max-width: 12rem; padding-left: .6rem; opacity: 1; }
/* Hover only where there is a real pointer: on a touch screen a tap leaves
   :hover stuck on, and the label would never fold back. */
@media (hover: hover) {
  .wa-float:hover { background: #1EBE5A; box-shadow: 0 10px 26px rgba(20,48,60,.28); }
  .wa-float:hover span { max-width: 12rem; padding-left: .6rem; opacity: 1; }
}
.wa-float:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }

/* ---------------- consent ----------------
   A bar, not a modal: the question is small and the page behind it is not
   withheld pending an answer. It sits bottom-left so it does not land on the
   floating WhatsApp button, and it is built by assets/analytics.js. */
.consent {
  position: fixed;
  z-index: 60;
  left: clamp(.75rem, 2vw, 1.5rem);
  bottom: clamp(.75rem, 2vw, 1.5rem);
  width: min(26rem, calc(100vw - 1.5rem));
  display: flex; flex-direction: column; gap: 1rem;
  padding: clamp(1.1rem, 2vw, 1.4rem);
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  box-shadow: 0 24px 50px -28px rgba(20,48,60,.6);
}
.consent p {
  font-size: .8125rem; line-height: 1.65;
  color: var(--ink-soft);
}
.consent a { color: var(--blue); }
.consent a:hover { border-bottom: 1px solid currentColor; }
.consent-actions { display: flex; flex-wrap: wrap; gap: .55rem; }
.consent-actions .btn { font-size: .625rem; padding: .7rem 1.15rem; }
/* on a phone the bar spans the width and clears the WhatsApp button above it */
@media (max-width: 560px) {
  .consent { left: .75rem; right: .75rem; width: auto; bottom: 5.25rem; }
}

/* ---------------- motion ---------------- */
.rise {
  opacity: 0; transform: translateY(12px);
  transition: opacity .7s cubic-bezier(.22,.61,.36,1), transform .7s cubic-bezier(.22,.61,.36,1);
}
.rise.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .rise { opacity: 1; transform: none; transition: none; }
  .wa-float span { transition: none; }
  .film:hover img, .film:hover .play, .vid:hover .shot img, .vid:hover .play,
  .gallery figure:hover img { transform: none; }
}

.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;
}


/* ============================================================
   SUB-PAGES
   Everything below belongs to the individual pages rather than
   the home page. It spends the tokens defined at the top of this
   file and invents no new colour.
   ============================================================ */

:root {
  /* The fixed header measures logo 3.1rem + .9rem padding + a 1px rule.
     It has to be a token because sub-pages open flush against it and need
     to pad past it. Without this, calc(var(--nav-h) + ...) is an invalid
     value, the whole declaration is dropped, and the page title renders
     underneath the bar. That is exactly what happened on retreats.html. */
  --nav-h: 4.0625rem;
}

/* ---------------- page head ----------------
   A sub-page opens on a plain title block, not on the home page's
   photographic hero. On a class page the copy is the point, and a second
   full-height photograph would only delay it. */
.page-head { padding-top: calc(var(--nav-h) + clamp(2.5rem, 6vw, 4.5rem)); }
.page-head .lede { margin-top: 1rem; }
.sec-head h1 { max-width: 24ch; }
.sec-head.center h1 { max-width: 26ch; }

/* ---------------- breadcrumbs ----------------
   An ordered list inside a labelled nav, mirrored in BreadcrumbList
   JSON-LD on every page that carries one. */
.crumbs { margin-bottom: 1.35rem; }
.crumbs ol {
  margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: .55rem;
  font-size: .625rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-soft);
}
.crumbs.mid ol { justify-content: center; }
.crumbs li { list-style: none; display: flex; align-items: center; gap: .55rem; }
.crumbs li + li::before {
  content: ""; width: 3px; height: 3px; border-radius: 999px;
  background: var(--blue); opacity: .6; flex: none;
}
.crumbs a { color: var(--blue); text-decoration: none; border-bottom: 1px solid transparent; }
.crumbs a:hover { border-bottom-color: currentColor; }
.crumbs [aria-current="page"] { color: var(--ink-soft); }

/* ---------------- a wider band ----------------
   The class-level version of the widening the home page performs on
   #classes and #videos, so card grids on sub-pages can run past the text
   column. Same arithmetic: the space between the shell's content edge and
   the viewport edge, less a 2rem margin, so it tapers to nothing near
   1200px where there is nothing spare to give back. */
@media (min-width: 1000px) {
  .wide > .shell {
    max-width: calc(var(--shell) + clamp(0px,
      calc((100vw - var(--shell)) / 2 + var(--pad) - 2rem), 150px) * 2);
  }
}

/* ---------------- article: the long-form column ----------------
   Held to a reading measure rather than to the shell width. Running text
   stays Jost at the body size; only headings are allowed Cormorant. */
.split {
  display: grid; grid-template-columns: 1fr;
  gap: clamp(2rem, 4vw, 3.5rem);
  margin-top: clamp(2rem, 4vw, 3rem);
  align-items: start;
}
@media (min-width: 980px) { .split { grid-template-columns: minmax(0, 1fr) 20.5rem; } }

.article-body { display: flex; flex-direction: column; gap: 1.1rem; max-width: 40rem; }
.article-body > * { max-width: 100%; }
.article-body p, .article-body li { color: var(--ink-soft); line-height: 1.78; }
.article-body h2 {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  font-size: clamp(1.25rem, 1.9vw, 1.625rem);
  max-width: 30ch;
}
.article-body > h2:first-child { margin-top: 0; }   /* a page that opens on a heading sits level with its aside */
.article-body h3 { margin-top: .85rem; font-size: 1.0625rem; }
.article-body ul, .article-body ol { margin: 0; padding-left: 1.15rem; display: grid; gap: .5rem; }
.article-body li::marker { color: var(--blue); }
.article-body blockquote {
  margin: .5rem 0; padding-left: 1.2rem;
  border-left: 1px solid var(--blue-line);
  font-family: var(--display); font-size: 1.25rem; line-height: 1.45;
  color: var(--ink);
}
.article-body strong { font-weight: 500; color: var(--ink); }
.article-body a:not(.btn):not(.link):not(.chip) {
  color: var(--blue); text-decoration: none;
  border-bottom: 1px solid var(--blue-line);
}
.article-body a:not(.btn):not(.link):not(.chip):hover { border-bottom-color: currentColor; }
.article-body figure { margin: .75rem 0; }
.article-body figure img { width: 100%; height: auto; border-radius: var(--r); }
.article-body figcaption { margin-top: .6rem; font-size: .75rem; color: var(--ink-soft); }

/* ---------------- the aside card ---------------- */
.aside-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: clamp(1.5rem, 2.2vw, 1.9rem);
  display: flex; flex-direction: column; gap: 1.15rem;
}
@media (min-width: 980px) { .aside-card { position: sticky; top: calc(var(--nav-h) + 1.25rem); } }
.aside-card h2, .aside-card h3 { font-size: 1.1875rem; }
.aside-card p { color: var(--ink-soft); font-size: .875rem; line-height: 1.72; }
.aside-card .btn { justify-content: center; }

.spec { margin: 0; display: grid; gap: 0; }
.spec div {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding: .7rem 0; border-bottom: 1px solid var(--line);
}
.spec div:last-child { border-bottom: 0; padding-bottom: 0; }
.spec dt { font-size: .625rem; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); }
.spec dd { margin: 0; font-size: .875rem; color: var(--ink); text-align: right; }

/* ---------------- numbered steps ---------------- */
.steps {
  display: grid; grid-template-columns: 1fr;
  gap: clamp(.9rem, 1.4vw, 1.15rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
@media (min-width: 700px)  { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .steps { grid-template-columns: repeat(4, 1fr); } }
.step {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: clamp(1.4rem, 2vw, 1.75rem);
  display: flex; flex-direction: column; gap: .7rem;
}
.step .no {
  font-size: .625rem; font-weight: 500; letter-spacing: .2em;
  color: var(--blue); font-variant-numeric: tabular-nums;
}
.step h3 { font-size: 1.0625rem; }
.step p { color: var(--ink-soft); font-size: .875rem; line-height: 1.72; }

/* ---------------- FAQ ----------------
   Native details/summary, so it works with no script and every answer is in
   the markup for a crawler to read whether or not it is open. Mirrored in
   FAQPage JSON-LD. */
.faq { margin-top: clamp(1.75rem, 3.5vw, 2.5rem); border-top: 1px solid var(--line); max-width: 46rem; }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; list-style: none; position: relative;
  padding: 1.1rem 2.25rem 1.1rem 0;
  font-family: var(--display); font-size: 1.0625rem; color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: .4rem; top: 1.4rem;
  width: 8px; height: 8px;
  border-right: 1px solid var(--blue); border-bottom: 1px solid var(--blue);
  transform: rotate(45deg);
  transition: transform .2s ease, top .2s ease;
}
.faq details[open] summary::after { transform: rotate(-135deg); top: 1.6rem; }
.faq summary:hover { color: var(--blue); }
.faq summary:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.faq .answer { padding: 0 2.25rem 1.4rem 0; display: flex; flex-direction: column; gap: .8rem; }
.faq .answer p, .faq .answer li { color: var(--ink-soft); font-size: .875rem; line-height: 1.75; }
.faq .answer ul { margin: 0; padding-left: 1.1rem; display: grid; gap: .4rem; }
.faq .answer li::marker { color: var(--blue); }

/* ---------------- blog cards ---------------- */
.posts {
  display: grid; grid-template-columns: 1fr;
  gap: clamp(.9rem, 1.4vw, 1.15rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
@media (min-width: 700px)  { .posts { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .posts { grid-template-columns: repeat(3, 1fr); } }
.post {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  overflow: hidden; text-decoration: none;
  display: flex; flex-direction: column;
  transition: border-color .2s ease, box-shadow .3s ease;
}
.post:hover { border-color: var(--blue-line); box-shadow: 0 1px 24px -12px rgba(20,48,60,.35); }
.post .shot { display: block; overflow: hidden; background: var(--cream-3); }
/* setting width alone would leave the height attribute in force and make
   aspect-ratio inert, which is the trap the README documents */
.post .shot img {
  width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover;
  transition: transform .9s cubic-bezier(.2,.6,.3,1);
}
.post:hover .shot img { transform: scale(1.04); }
.post .body {
  padding: clamp(1.25rem, 1.9vw, 1.6rem);
  display: flex; flex-direction: column; gap: .65rem; flex: 1;
}
.post .kicker { font-size: .625rem; font-weight: 500; letter-spacing: .16em; text-transform: uppercase; color: var(--blue); }
.post h2, .post h3 { font-size: 1.125rem; max-width: 24ch; }
.post p { color: var(--ink-soft); font-size: .875rem; line-height: 1.7; }
.post .when {
  margin-top: auto; padding-top: 1rem;
  font-size: .5625rem; letter-spacing: .13em; text-transform: uppercase; color: var(--ink-soft);
  display: flex; flex-wrap: wrap; gap: .35rem .8rem;
}
.post .when span { display: flex; align-items: center; gap: .5rem; }
.post .when span + span::before {
  content: ""; width: 3px; height: 3px; border-radius: 999px;
  background: var(--blue); opacity: .6;
}

/* the lead post on the blog index runs the full width and shows more copy */
@media (min-width: 700px) {
  .post-lead { grid-column: 1 / -1; flex-direction: row; align-items: stretch; }
  .post-lead .shot { flex: 1 1 52%; min-width: 0; }
  .post-lead .shot img { height: 100%; aspect-ratio: auto; min-height: 17rem; }
  .post-lead .body { flex: 1 1 48%; justify-content: center; padding: clamp(1.75rem, 3vw, 2.75rem); }
  .post-lead h2 { font-size: clamp(1.375rem, 2.1vw, 1.875rem); }
}

/* ---------------- blog post meta ---------------- */
.post-meta {
  display: flex; flex-wrap: wrap; gap: .4rem .85rem; align-items: center;
  font-size: .625rem; letter-spacing: .13em; text-transform: uppercase; color: var(--ink-soft);
}
.post-meta > span { display: flex; align-items: center; gap: .85rem; }
.post-meta > span + span::before {
  content: ""; width: 3px; height: 3px; border-radius: 999px;
  background: var(--blue); opacity: .6;
}
.post-hero { margin-top: clamp(2rem, 4vw, 3rem); border-radius: var(--r); overflow: hidden; background: var(--cream-3); }
.post-hero img { width: 100%; height: auto; }
/* a 3:4 studio photograph would be 850px tall across the reading column,
   so portrait heroes are held to a narrower measure instead of cropped */
.post-hero.portrait { max-width: 26rem; margin-inline: auto; }

/* ---------------- related cards ---------------- */
.related {
  display: grid; grid-template-columns: 1fr;
  gap: clamp(.9rem, 1.4vw, 1.15rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
@media (min-width: 760px) { .related { grid-template-columns: repeat(3, 1fr); } }
.rel {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: clamp(1.25rem, 1.9vw, 1.6rem);
  text-decoration: none;
  display: flex; flex-direction: column; gap: .5rem;
  transition: border-color .2s ease;
}
.rel:hover { border-color: var(--blue-line); }
.rel .kicker { font-size: .625rem; font-weight: 500; letter-spacing: .16em; text-transform: uppercase; color: var(--blue); }
.rel h3 { font-size: 1.0625rem; }
.rel p { color: var(--ink-soft); font-size: .8125rem; line-height: 1.65; }

/* ---------------- chips ---------------- */
.chips { display: flex; flex-wrap: wrap; gap: .45rem; }
.chip {
  font-size: .625rem; letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-soft); text-decoration: none;
  border: 1px solid var(--line); border-radius: 999px;
  padding: .38rem .8rem;
}
a.chip:hover { border-color: var(--blue-line); color: var(--blue); }

/* ---------------- figures ---------------- */
.stats {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(1.25rem, 2.5vw, 2rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
@media (min-width: 860px) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat { display: flex; flex-direction: column; gap: .3rem; padding-top: 1.05rem; border-top: 1px solid var(--line-strong); }
.stat b { font-family: var(--display); font-size: clamp(1.5rem, 2.4vw, 2rem); font-weight: 400; line-height: 1.1; }
.stat span { font-size: .625rem; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); }

/* ---------------- a static wall of reviews ----------------
   The home page drifts its reviews past; a page devoted to them should let
   the visitor read at their own pace, so the marquee width is released. */
.review-wall {
  display: grid; grid-template-columns: 1fr;
  gap: clamp(.9rem, 1.4vw, 1.15rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
@media (min-width: 700px)  { .review-wall { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .review-wall { grid-template-columns: repeat(3, 1fr); } }
.review-wall .review { width: auto; }

/* ---------------- closing call to action ---------------- */
.cta-band .shell { display: flex; flex-direction: column; align-items: center; gap: 1.35rem; text-align: center; }
.cta-band h2 { max-width: 22ch; }
.cta-band .lede { text-align: center; }
.cta-row { display: flex; flex-wrap: wrap; gap: .75rem; justify-content: center; margin-top: .35rem; }
