/* ==========================================================================
   Cryst Cares — "Three Rooms"
   Green carries the identity. The clay accent only ever appears on something
   you can click. Type is sized for readers in their fifties and sixties on a
   phone, so nothing drops below 17px.
   ========================================================================== */

/* --- Tokens --------------------------------------------------------------- */
:root {
  --ink:        #14201A;  /* warm green-black — body text                     */
  --ink-soft:   #4A5A50;  /* secondary text on light     6.6:1 on oat         */
  --forest:     #1C3D2E;  /* primary ground — hero, bands, footer             */
  --moss:       #3E6B52;  /* mid green — rules, marks    5.6:1 on oat         */
  --sage:       #DDE4D8;  /* pale tint — cards, quiet surfaces                */
  --sage-soft:  #A9BCAE;  /* secondary text on forest    6.0:1                */
  --oat:        #F6F3EC;  /* warm paper — page ground                         */
  --ember:      #9E4A22;  /* THE accent. Actions only.   5.5:1 on oat         */
  --ember-lift: #853D1D;  /* accent hover — darker, so it passes AA as text too */

  --shell: 74rem;
  --gap: clamp(1.25rem, 3vw, 2rem);
  --band: clamp(3.5rem, 8vw, 7rem);
  --radius: 3px;

  --display: Petrona, 'Iowan Old Style', Georgia, serif;
  --body: Karla, 'Helvetica Neue', Arial, sans-serif;

  --s--1: 0.9375rem;
  --s-0:  1.1875rem;                                        /* 19px           */
  --s-1:  clamp(1.3rem,  1.13rem + 0.55vw, 1.6rem);
  --s-2:  clamp(1.6rem,  1.32rem + 1.15vw, 2.2rem);
  --s-3:  clamp(2rem,    1.52rem + 2.1vw,  3.05rem);
  --s-4:  clamp(2.4rem,  1.62rem + 3.5vw,  4.3rem);
}

/* --- Reset ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }

body {
  background: var(--oat);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--s-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

/* --- Typography ----------------------------------------------------------- */
h1, h2, h3, h4 { font-family: var(--display); font-weight: 500; line-height: 1.1; letter-spacing: -0.015em; }
h1 { font-size: var(--s-4); }
h2 { font-size: var(--s-3); }
h3 { font-size: var(--s-1); line-height: 1.2; }
p  { max-width: 62ch; }

a { color: var(--ember); text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { color: var(--ember-lift); }

.eyebrow {
  font-size: var(--s--1);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--moss);
  margin-bottom: 0.9rem;
}
.band--forest .eyebrow,
.phead .eyebrow,
.foot .eyebrow,
.on-dark .eyebrow { color: var(--sage-soft); }
.hero .eyebrow { color: var(--sage); }

.lede { font-size: var(--s-1); line-height: 1.5; color: var(--ink-soft); }
.muted { color: var(--ink-soft); }

.band--forest .lede, .phead .lede,
.band--forest .muted, .phead .muted, .foot .muted { color: var(--sage-soft); }

/* Over the hero photo the ground is lighter than flat forest, so hero text
   uses the brighter --sage. Verified against sampled pixels, not by eye. */
.hero .lede, .hero .muted { color: var(--sage); }

/* --- Layout --------------------------------------------------------------- */
.shell { width: min(100% - 2.5rem, var(--shell)); margin-inline: auto; }
.shell--narrow { width: min(100% - 2.5rem, 52rem); margin-inline: auto; }
.band { padding-block: var(--band); }
.band--forest { background: var(--forest); color: var(--sage); }
.band--forest h1, .band--forest h2, .band--forest h3 { color: #fff; }
.band--sage { background: var(--sage); }

.skip {
  position: absolute; left: -9999px;
  background: var(--forest); color: #fff; padding: .8rem 1.2rem; z-index: 99;
}
.skip:focus { left: 1rem; top: 1rem; }

:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 3px solid var(--ember);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --- Masthead ------------------------------------------------------------- */
.masthead {
  background: var(--forest);
  color: var(--sage);
  position: sticky; top: 0; z-index: 40;
  border-bottom: 1px solid rgba(255,255,255,.1);
}
.masthead__in { display: flex; align-items: center; gap: 1rem; min-height: 78px; }

.brand { display: flex; align-items: center; gap: .7rem; color: #fff; text-decoration: none; margin-right: auto; }
.brand__mark { color: var(--sage-soft); flex: none; }
.brand__name { font-family: var(--display); font-size: 1.35rem; font-weight: 600; display: block; line-height: 1.1; }
.brand__sub { display: block; max-height: 2rem; overflow: hidden; font-size: .78rem; letter-spacing: .12em; text-transform: uppercase; color: var(--sage-soft); }

.nav { display: flex; align-items: center; gap: clamp(1rem, 2.2vw, 1.9rem); }
.nav__list { display: flex; gap: clamp(1rem, 2.2vw, 1.9rem); list-style: none; padding: 0; }
.nav__list a {
  color: var(--sage); text-decoration: none; font-weight: 500; font-size: 1.05rem;
  padding: .55rem 0; display: block; border-bottom: 2px solid transparent;
}
.nav__list a:hover { color: #fff; border-bottom-color: var(--sage-soft); }
.nav__list a[aria-current="page"] { color: #fff; border-bottom-color: var(--ember); }

.burger { display: none; background: none; border: 0; padding: .75rem; cursor: pointer; }
.burger span { display: block; width: 26px; height: 2px; background: var(--sage); margin: 5px 0; transition: transform .25s, opacity .2s; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 61rem) {
  .burger { display: block; }
  .nav {
    position: fixed; inset: 78px 0 auto 0;
    background: var(--forest); flex-direction: column; align-items: stretch;
    gap: 0; padding: 1rem 1.25rem 2rem;
    border-bottom: 1px solid rgba(255,255,255,.12);
    display: none;
  }
  .nav.is-open { display: flex; }
  .nav__list { flex-direction: column; gap: 0; }
  .nav__list a { padding: .95rem 0; border-bottom: 1px solid rgba(255,255,255,.09); }
  .nav__cta { margin-top: 1.25rem; text-align: center; }
}

/* --- Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 50px; padding: .8rem 1.5rem;
  font-family: var(--body); font-weight: 700; font-size: 1.05rem;
  border: 2px solid transparent; border-radius: var(--radius);
  text-decoration: none; cursor: pointer;
  transition: background-color .18s, border-color .18s, color .18s;
}
.btn--accent { background: var(--ember); color: #fff; }
.btn--accent:hover { background: var(--ember-lift); color: #fff; }
.btn--ghost { border-color: currentColor; color: inherit; background: none; }
.band--forest .btn--ghost:hover { background: rgba(255,255,255,.1); color: #fff; }
.btn--ghost:hover { background: rgba(28,61,46,.07); }
.btn--lg { min-height: 58px; padding: 1rem 2rem; font-size: 1.1rem; }

/* --- Hero ----------------------------------------------------------------- */
/* The photo sits behind a forest scrim that is near-solid on the left, where
   the headline lives, and opens up to the right so the room reads through.
   background-color stays as the fallback if the image ever fails to load. */
/* The photo lives on the zone, not the hero, so it continues underneath the
   room board. `to right` rather than an angle: the zone is much taller than the
   hero was, and an angled scrim would skew across that height.

   The hero photo is MIRRORED on purpose. Unflipped, both faces sit on the left,
   directly under the headline — measured, the h1 came out at 2.38:1. Mirrored,
   the resident's face lands on the open right side where the scrim thins to 22%
   and reads clearly, while the text keeps the heavy left end it needs. A
   vertical scrim cannot serve both: faces and text share the same band.

   Re-measure after ANY change here — resources/tools/hero-contrast.py samples
   the real composited pixels under every glyph. Do not eyeball it. */
.hero-zone {
  background-color: var(--forest);
  background-image:
    linear-gradient(to right,
      rgba(28,61,46,.950) 0%,
      rgba(28,61,46,.915) 35%,
      rgba(28,61,46,.870) 50%,
      rgba(28,61,46,.790) 57%,
      rgba(28,61,46,.620) 64%,
      rgba(28,61,46,.440) 74%,
      rgba(28,61,46,.220) 100%),
    url('/img/hero-care.jpg');
  background-image:
    linear-gradient(to right,
      rgba(28,61,46,.950) 0%,
      rgba(28,61,46,.915) 35%,
      rgba(28,61,46,.870) 50%,
      rgba(28,61,46,.790) 57%,
      rgba(28,61,46,.620) 64%,
      rgba(28,61,46,.440) 74%,
      rgba(28,61,46,.220) 100%),
    image-set(url('/img/hero-care.webp') type('image/webp'),
              url('/img/hero-care.jpg')  type('image/jpeg'));
  background-size: cover;
  background-position: center right;
  background-repeat: no-repeat;
}

.hero {
  color: var(--sage);
  padding-block: clamp(3.5rem, 8vw, 6.5rem) clamp(2.5rem, 5vw, 3.75rem);
}

/* Below the two-column breakpoint the text runs the full width, so a horizontal
   scrim has nothing to hide behind and the whole frame has to carry the text.
   The mobile source is therefore a purpose-made portrait crop, and the scrim is
   vertical: a light band across the top where the extra hero padding leaves the
   caregiver's face clear of any text, then heavy from ~13% down. Measured with
   resources/tools/hero-contrast.py at 390x844. */
@media (max-width: 62rem) {
  .hero-zone {
    background-image:
      linear-gradient(to bottom,
        rgba(28,61,46,.360) 0%,
        rgba(28,61,46,.510) 7%,
        rgba(28,61,46,.820) 13%,
        rgba(28,61,46,.855) 24%,
        rgba(28,61,46,.900) 45%,
        rgba(28,61,46,.950) 100%),
      url('/img/hero-care-sm.jpg');
    background-image:
      linear-gradient(to bottom,
        rgba(28,61,46,.360) 0%,
        rgba(28,61,46,.510) 7%,
        rgba(28,61,46,.820) 13%,
        rgba(28,61,46,.855) 24%,
        rgba(28,61,46,.900) 45%,
        rgba(28,61,46,.950) 100%),
      image-set(url('/img/hero-care-sm.webp') type('image/webp'),
                url('/img/hero-care-sm.jpg')  type('image/jpeg'));
    background-position: center top;
  }
  /* Buys a band of clear photo above the headline. Without it the eyebrow starts
     56px into the zone and the hero is text from top to bottom. */
  .hero { padding-block: 8rem clamp(2.5rem, 5vw, 3.75rem); }
}
/* One column since the facts widget came out. The headline and lede carry
   their own max-widths, so the photo keeps the right side of the frame. */
.hero__grid { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: end; }

.hero h1 { color: #fff; max-width: 17ch; }
/* Each half of the headline is its own block so `balance` applies to both.
   A single <br> inside one block balances only the first half and leaves the
   second orphaning its last word. */
.hero h1 .hl, .hero h1 em { display: block; text-wrap: balance; }
.hero h1 em { font-style: normal; color: var(--sage-soft); }
.hero__p { margin-top: 1.5rem; max-width: 46ch; }
.hero__acts { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 2.25rem; }

/* Sits astride the hero's bottom edge — the hero ends, the board overlaps it. */
.board-wrap { background: linear-gradient(transparent 50%, var(--oat) 50%); padding-top: clamp(3rem, 7vw, 5rem); }
.board {
  background: var(--oat);
  border: 1px solid var(--sage);
  border-top: 4px solid var(--ember);
  padding: clamp(1.5rem, 4vw, 2.5rem);
  box-shadow: 0 18px 40px -28px rgba(20,32,26,.55);
}
.board__head {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline;
  gap: .75rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--sage);
}
.board__head .eyebrow { margin-bottom: 0; }
.board__count { font-family: var(--display); font-size: var(--s-1); color: var(--ink); }
.board__count b { color: var(--ember); font-weight: 600; }

.board__rooms { list-style: none; padding: 0; display: grid; gap: 1px; background: var(--sage); margin-top: 1px; }
@media (min-width: 48rem) { .board__rooms { grid-template-columns: repeat(3, 1fr); } }
.room { background: var(--oat); padding: 1.4rem 1.25rem 1.5rem; }
.room__status {
  display: inline-flex; align-items: center; gap: .5rem;
  font-size: var(--s--1); font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
}
.room__status::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: currentColor; }
.room--open   .room__status { color: var(--ember); }
.room--taken  .room__status { color: var(--ink-soft); }
.room__name { font-family: var(--display); font-size: var(--s-1); margin: .5rem 0 .35rem; }
.room--taken .room__name { color: var(--ink-soft); }
.room__note { font-size: 1rem; color: var(--ink-soft); }
.board__foot { padding-top: 1.4rem; display: flex; flex-wrap: wrap; gap: 1rem 1.5rem; align-items: center; justify-content: space-between; }
.board__foot p { font-size: 1rem; color: var(--ink-soft); max-width: 48ch; }

/* --- The walk-through ----------------------------------------------------- */
/* Sections are labelled by where you are in the house, not 01/02/03 — the
   labels trace a real tour path, so they carry information. */
.stop { display: grid; gap: clamp(1.75rem, 4vw, 3.5rem); align-items: center; }
.stop + .stop { margin-top: clamp(3rem, 7vw, 5.5rem); }
@media (min-width: 54rem) {
  .stop { grid-template-columns: 1fr 1fr; }
  .stop--flip .stop__media { order: -1; }
}
.stop__body h2 { margin-bottom: 1rem; }
.stop__body p + p { margin-top: 1rem; }

/* --- Photo slots ---------------------------------------------------------- */
/* Art-directed placeholders. Each names the exact shot still needed from
   Yvette, so the mockup reads as intentional rather than unfinished. */
.shot {
  position: relative;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--moss);
  background:
    radial-gradient(120% 90% at 18% 12%, rgba(255,255,255,.14), transparent 60%),
    linear-gradient(155deg, var(--moss) 0%, var(--forest) 68%);
  display: grid; place-content: center; gap: .75rem; padding: 1.5rem; text-align: center;
  overflow: hidden;
}
.shot::after {
  content: ""; position: absolute; inset: 10px; border: 1px solid rgba(255,255,255,.16); pointer-events: none;
}
/* A filled slot: same box, real photo. Keeps the hairline so photos and
   placeholders sit in the same frame. */
.shot--img { background: none; padding: 0; border-color: var(--moss); display: block; }
.shot--img::after { display: none; }
.shot--img picture { display: block; width: 100%; height: 100%; }
.shot--img img { width: 100%; height: 100%; object-fit: cover; display: block; }

.shot--tall { aspect-ratio: 3 / 4; }
.shot--wide { aspect-ratio: 16 / 9; }
.shot__icon { color: var(--sage-soft); margin-inline: auto; }
.shot figcaption { display: grid; gap: .5rem; }
.shot__label, .shot__desc { display: block; }
.shot__label {
  font-size: var(--s--1); letter-spacing: .12em; text-transform: uppercase;
  color: var(--sage-soft); font-weight: 700;
}
.shot__desc { font-family: var(--display); color: #fff; font-size: 1.15rem; line-height: 1.3; max-width: 26ch; margin-inline: auto; }

/* --- Cards / grids -------------------------------------------------------- */
.grid { display: grid; gap: 1.25rem; }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }

.card { background: var(--oat); border: 1px solid var(--sage); padding: 1.6rem 1.5rem; }
.band--sage .card { background: #fff; border-color: #fff; }
.band--forest .card { background: rgba(255,255,255,.05); border-color: rgba(255,255,255,.14); }
.card h3 { margin-bottom: .5rem; }
.card p { font-size: 1.05rem; color: var(--ink-soft); }
.band--forest .card p { color: var(--sage-soft); }

/* The nurse block — the strongest trust signal on the site, so it gets its
   own treatment rather than being one card among many. */
.nurse { display: grid; gap: clamp(1.75rem, 4vw, 3rem); align-items: center; }
@media (min-width: 54rem) { .nurse { grid-template-columns: .8fr 1.2fr; } }
.nurse__creds { list-style: none; padding: 0; margin-top: 1.75rem; display: grid; gap: .7rem; }
.nurse__creds li { display: flex; gap: .75rem; align-items: flex-start; font-size: 1.05rem; }
.nurse__creds li::before {
  content: ""; flex: none; width: 8px; height: 8px; margin-top: .58rem;
  background: var(--ember); transform: rotate(45deg);
}

/* --- Included list -------------------------------------------------------- */
.included { list-style: none; padding: 0; display: grid; gap: 0; }
@media (min-width: 44rem) { .included { grid-template-columns: 1fr 1fr; column-gap: 2.5rem; } }
.included li {
  padding: .85rem 0 .85rem 2rem; border-bottom: 1px solid var(--sage);
  position: relative; font-size: 1.05rem;
}
.band--forest .included li { border-bottom-color: rgba(255,255,255,.14); }
.included li::before {
  content: ""; position: absolute; left: 0; top: 1.4rem;
  width: 12px; height: 6px; border-left: 2px solid var(--ember); border-bottom: 2px solid var(--ember);
  transform: rotate(-45deg);
}

/* --- Quotes --------------------------------------------------------------- */
.quote { border-left: 3px solid var(--ember); padding-left: 1.5rem; }
.quote p { font-family: var(--display); font-size: var(--s-1); line-height: 1.4; }
.quote cite { display: block; margin-top: .9rem; font-style: normal; font-size: 1rem; color: var(--ink-soft); }
.band--forest .quote cite { color: var(--sage-soft); }

/* --- FAQ ------------------------------------------------------------------ */
.faq { border-top: 1px solid var(--sage); }
.faq details { border-bottom: 1px solid var(--sage); }
.faq summary {
  cursor: pointer; list-style: none; padding: 1.35rem 2.5rem 1.35rem 0;
  font-family: var(--display); font-size: var(--s-1); position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: .4rem; top: 2.05rem;
  width: 11px; height: 11px; border-right: 2px solid var(--ember); border-bottom: 2px solid var(--ember);
  transform: rotate(45deg); transition: transform .2s;
}
.faq details[open] summary::after { transform: rotate(-135deg); }
.faq__a { padding: 0 0 1.5rem; }
.faq__a p + p { margin-top: .85rem; }

/* --- Form ----------------------------------------------------------------- */
.form { display: grid; gap: 2rem; }
.fset { border: 0; padding: 0; margin: 0; }
.fset__legend {
  font-family: var(--display); font-size: var(--s-1); padding: 0 0 .35rem;
  border-bottom: 2px solid var(--forest); width: 100%; margin-bottom: 1.1rem;
}
.fset__hint { font-size: 1rem; color: var(--ink-soft); margin: -.5rem 0 1.1rem; }

.frow { display: grid; gap: 1.1rem; }
@media (min-width: 42rem) { .frow--2 { grid-template-columns: 1fr 1fr; } }

.field { display: grid; gap: .4rem; }
.field > label { font-weight: 700; font-size: 1.02rem; }
.field .req { color: var(--ember); }
.field input[type="text"], .field input[type="tel"], .field input[type="email"],
.field select, .field textarea {
  width: 100%; padding: .8rem .9rem; min-height: 50px;
  background: #fff; border: 1px solid var(--moss); border-radius: var(--radius);
  font-size: 1.05rem;
}
.field textarea { min-height: 120px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--ember); }

.checks { display: grid; gap: .1rem; }
.check {
  display: flex; gap: .8rem; align-items: flex-start;
  padding: .75rem .85rem; min-height: 50px;
  border: 1px solid transparent; border-radius: var(--radius); cursor: pointer;
}
.check:hover { background: var(--sage); }
.check input { flex: none; width: 22px; height: 22px; margin-top: .18rem; accent-color: var(--ember); }
.check span { font-size: 1.03rem; }
.check--consent { align-items: flex-start; background: var(--sage); padding: 1.1rem; }
.check--consent span { font-size: .98rem; line-height: 1.55; }

.stop-note {
  background: var(--sage); border-left: 3px solid var(--moss);
  padding: 1.1rem 1.25rem; font-size: 1.02rem; margin-top: 1rem;
}
.form__submit { display: grid; gap: 1rem; justify-items: start; }
.form__fine { font-size: .95rem; color: var(--ink-soft); }

/* Shown by JS when a hard-stop condition is ticked. */
.disqualify { display: none; border: 1px solid var(--moss); background: var(--sage); padding: 1.4rem 1.5rem; }
.disqualify.is-shown { display: block; }
.disqualify h3 { margin-bottom: .5rem; }
.disqualify p { font-size: 1.03rem; }

/* --- Blog ----------------------------------------------------------------- */
.posts { list-style: none; padding: 0; display: grid; gap: 0; border-top: 1px solid var(--sage); }
.posts li { border-bottom: 1px solid var(--sage); }
.posts a { display: grid; gap: .4rem; padding: 1.75rem 0; text-decoration: none; color: var(--ink); }
@media (min-width: 46rem) { .posts a { grid-template-columns: 9rem 1fr; gap: 2rem; align-items: baseline; } }
.posts a:hover .post__t { color: var(--ember); }
.post__d { font-size: var(--s--1); letter-spacing: .1em; text-transform: uppercase; color: var(--moss); font-weight: 700; }
.post__t { font-family: var(--display); font-size: var(--s-1); line-height: 1.25; }
.post__x { font-size: 1.05rem; color: var(--ink-soft); margin-top: .35rem; }

/* --- Page head ------------------------------------------------------------ */
.phead { background: var(--forest); color: var(--sage); padding-block: clamp(2.75rem, 6vw, 4.5rem); }
.phead h1 { color: #fff; max-width: 20ch; font-size: var(--s-3); }
.phead p { margin-top: 1.1rem; max-width: 54ch; color: var(--sage-soft); font-size: var(--s-1); line-height: 1.5; }

/* --- Footer --------------------------------------------------------------- */
.foot { background: var(--forest); color: var(--sage); padding-block: var(--band) 2.5rem; margin-top: var(--band); }
.foot__top { display: grid; gap: clamp(2rem, 5vw, 3.5rem); }
@media (min-width: 56rem) { .foot__top { grid-template-columns: 1.4fr .8fr .8fr; } }
.foot__h { color: #fff; font-size: var(--s-2); max-width: 16ch; }
.foot__p { margin: 1rem 0 2rem; color: var(--sage-soft); max-width: 44ch; }
.foot a { color: var(--sage); }
.foot a:hover { color: #fff; }
.foot .btn--accent { color: #fff; }
.foot address { font-style: normal; margin-bottom: .9rem; }
.foot__nap p { margin-bottom: .9rem; }
.foot__hours { font-size: 1rem; color: var(--sage-soft); }
.foot__links ul { list-style: none; padding: 0; display: grid; gap: .55rem; }
.foot__links a { text-decoration: none; }
.foot__links a:hover { text-decoration: underline; }
.foot__legal {
  margin-top: clamp(2.5rem, 6vw, 4rem); padding-top: 1.75rem;
  border-top: 1px solid rgba(255,255,255,.14);
  display: grid; gap: .9rem; font-size: .95rem; color: var(--sage-soft);
}
.foot__disclosure { max-width: 78ch; }

/* --- Utilities ------------------------------------------------------------ */
.stack > * + * { margin-top: 1rem; }
.mt-lg { margin-top: clamp(2rem, 5vw, 3.25rem); }
.mt-md { margin-top: 1.75rem; }
.center { text-align: center; margin-inline: auto; }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ==========================================================================
   Motion
   Slow and calm on purpose. The audience is reading on a phone, often for the
   first time, often about a parent — nothing here may delay that or move under
   a finger. Every hidden state is scoped to `.js`, set in the <head> before
   first paint, so a visitor without JavaScript sees the finished page.
   ========================================================================== */

/* --- Scroll reveals ------------------------------------------------------- */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .55s cubic-bezier(.2,.6,.3,1), transform .55s cubic-bezier(.2,.6,.3,1);
  transition-delay: calc(var(--i, 0) * 90ms);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

/* Photos settle out of a slight zoom as they arrive. The scale lives on the
   image so the figure's box never changes size. */
.js .shot[data-reveal] { overflow: hidden; }
.js .shot[data-reveal] img {
  transform: scale(1.04);
  transition: transform 1.1s cubic-bezier(.2,.6,.3,1);
  transition-delay: calc(var(--i, 0) * 90ms);
}
.js .shot[data-reveal].is-in img { transform: none; }

/* The hero moves but never fades. Its headline is the LCP element, and starting
   it at opacity 0 would delay the measurement by the length of the animation. */
.js .hero__grid > * {
  animation: hero-settle .8s cubic-bezier(.2,.6,.3,1) both;
}
@keyframes hero-settle {
  from { transform: translateY(14px); }
  to   { transform: none; }
}

/* --- Typewriter ----------------------------------------------------------- */
/* Characters are laid out immediately and revealed by opacity, so the text
   never reflows and the page never jumps while it writes. */
/* Hidden until it is this element's turn. Without this the raw text sits there
   fully legible until split() runs on it, so a queued block shows its whole
   contents and then restarts as typing — which looks like a fault.
   `visibility` rather than `display`, so the element still occupies its final
   space and nothing below it moves when the writing starts. */
.js [data-type] { visibility: hidden; }
.js [data-type] .w { white-space: nowrap; }
.js [data-type] .ch {
  opacity: 0;
  transition: opacity .12s linear;
}
.js [data-type] .ch.is-on { visibility: visible; opacity: 1; }

/* Completion, and every fallback path — reduced motion, no observer, a script
   that threw. Whatever happens, the words end up on the screen. */
.js [data-type].is-typed,
.js [data-type].is-typed .ch { visibility: visible; opacity: 1; }

/* The caret rides the character being written. Absolutely positioned, so it
   takes up no space and pushes nothing along. */
.js [data-type] .ch.is-cursor { position: relative; }
.js [data-type] .ch.is-cursor::after {
  content: "";
  position: absolute;
  right: -0.07em; top: .08em; bottom: .08em;
  width: 2px;
  background: var(--ember);
  animation: caret 1s steps(2, start) infinite;
}
.band--forest .js [data-type] .ch.is-cursor::after,
.js .band--forest [data-type] .ch.is-cursor::after { background: var(--sage-soft); }
@keyframes caret { 50% { opacity: 0; } }

/* The element the nav observer watches. It MUST have real dimensions — a
   zero-area target makes isIntersecting unreliable across engines, which shows
   up as the nav randomly failing to shrink. The negative margin cancels the 1px
   so it costs no layout. */
.mast-sentinel { display: block; height: 1px; margin-bottom: -1px; }

/* --- Floating masthead ---------------------------------------------------- */
/* DESKTOP ONLY, and that is load-bearing. The mobile nav panel below 61rem is
   positioned with a hardcoded `inset: 78px`, matching the masthead's height. As
   long as the masthead never changes height at those widths, that offset stays
   correct. If this shrink is ever extended to mobile, that 78px has to become a
   measured value at the same moment. */
@media (min-width: 61.01rem) {
  .masthead {
    transition: background-color .3s ease, border-color .3s ease, padding .3s ease;
  }
  .masthead__in {
    transition: min-height .3s ease, max-width .3s ease,
                background-color .3s ease, border-radius .3s ease,
                box-shadow .3s ease, padding .3s ease;
  }

  .masthead.is-stuck {
    background: transparent;
    border-bottom-color: transparent;
    padding-block: .55rem;
  }
  .masthead.is-stuck .masthead__in {
    min-height: 58px;
    max-width: 58rem;
    background: var(--forest);
    border-radius: 14px;
    padding-inline: 1.15rem;
    gap: .85rem;
    box-shadow: 0 14px 34px -18px rgba(10,20,15,.75);
  }

  /* Everything inside the panel scales down with it. At full size the CTA is
     50px tall in a 58px bar, which reads as a button wearing the nav rather
     than sitting in it — and a 3px-cornered button inside a 14px-cornered panel
     looks like two unrelated shapes. */
  .masthead .brand__name,
  .masthead .nav,
  .masthead .nav__list,
  .masthead .nav__list a {
    transition: font-size .3s ease, gap .3s ease, padding .3s ease;
  }
  /* Higher specificity than .btn, whose own transition is declared later. */
  .masthead .nav__cta {
    transition: min-height .3s ease, padding .3s ease, font-size .3s ease,
                border-radius .3s ease, background-color .18s, border-color .18s,
                color .18s, transform .2s ease, box-shadow .2s ease;
  }

  /* opacity alone leaves the subtitle's line box in place, which pushes the
     brand name off centre inside the panel. Zeroing font-size does not help
     either — that line box is sized by the PARENT's strut, not the child's. The
     box itself has to collapse. */
  .masthead.is-stuck .brand__sub { opacity: 0; max-height: 0; }
  .masthead.is-stuck .brand__mark { transform: scale(.86); }
  .masthead.is-stuck .brand__name { font-size: 1.15rem; }
  .masthead.is-stuck .brand { gap: .55rem; }

  .masthead.is-stuck .nav,
  .masthead.is-stuck .nav__list { gap: clamp(.85rem, 1.7vw, 1.45rem); }
  .masthead.is-stuck .nav__list a { font-size: 1rem; padding: .3rem 0; }

  .masthead.is-stuck .nav__cta {
    min-height: 38px;
    padding: .35rem 1.05rem;
    font-size: .97rem;
    /* 10px against the panel's 14px: the inner curve of the same shape, not a
       second unrelated one. */
    border-radius: 10px;
  }

  .brand__sub { transition: opacity .25s ease, max-height .3s ease; }
  .brand__mark { transition: transform .3s ease; }
}

/* --- FAQ answers ---------------------------------------------------------- */
/* The chevron already rotated smoothly while the panel snapped open, which read
   as unfinished. 0fr -> 1fr animates an unknown height without measuring it.
   The state is a CLASS, not [open]: a browser does not render details content
   while it is closed, so there would be nothing to transition. motion.js holds
   `open` on until the collapse finishes. Scoped to .js — without it, details
   behaves natively and this whole block is inert. */
.js .faq .faq__a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .34s cubic-bezier(.3,.7,.4,1);
}
.js .faq details.is-open .faq__a { grid-template-rows: 1fr; }
.js .faq .faq__a > * { overflow: hidden; min-height: 0; }

/* --- Hover lift ----------------------------------------------------------- */
/* hover:hover only — on a touch screen these stick after a tap. */
@media (hover: hover) {
  .card, .btn { transition: transform .2s ease, box-shadow .2s ease,
                            background-color .18s, border-color .18s, color .18s; }
  .card:hover { transform: translateY(-2px); box-shadow: 0 12px 26px -18px rgba(20,32,26,.5); }
  .btn:hover  { transform: translateY(-2px); }
  .room { transition: transform .2s ease; }
  .room:hover { transform: translateY(-2px); }
}

/* --- Reduced motion ------------------------------------------------------- */
/* The global rule near the top of this file zeroes durations, but that does not
   rescue something sitting at opacity 0 waiting on an observer. Show it all. */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal],
  .js [data-reveal].is-in { opacity: 1; transform: none; }
  .js .shot[data-reveal] img { transform: none; }
  .js [data-type] .ch { opacity: 1; }
  .js [data-type] .ch.is-cursor::after { display: none; }
  .js .hero__grid > * { animation: none; }
  .js .faq .faq__a { transition: none; }
}
