/* Prodigy Montessori — the live single-page site, restyled.
   Structure, photographs and copy are the incumbent's; everything visual is
   DESIGN.md. Tokens mirror that document exactly — no colour is invented here.

   breakpoints: sm 375, md 768, lg 1280 */

/* ─────────────────────────────────────────────────────────────── tokens */

:root {
  /* olive — the spine, and the colour of the logo */
  --olive-wash: #e6e6dc;
  --olive-mist: #d0d0c0;
  --olive-pale: #b3b39c;
  --olive-soft: #949478;
  --olive-mid:  #7a7a5f;
  --olive:      #63634b;
  --olive-deep: #4f4f3c;
  --olive-dark: #3f3f30;
  --olive-ink:  #2f2f24;

  /* sand — the warm ground */
  --sand-light: #f5f0ec;
  --sand:       #ebe3dd;
  --sand-mid:   #e2d9d1;
  --sand-deep:  #d9cec5;

  /* neutrals.
     --ink-subtle is NOT a text colour: 3.13:1 on sand fails AA at every size
     this system uses. It survives as a non-text tint only. All quiet TEXT is
     --ink-muted, which clears 4.5:1 on sand, sand-light and paper. */
  --paper:      #ffffff;
  --ink:        #23211c;
  --ink-muted:  #5b574e;
  --ink-subtle: #857f74;

  /* the one warm thing — clay is the primary action and nothing else */
  --clay:       #b0532b;
  --clay-deep:  #94441f;

  /* two border weights per ground: one separates, one bounds a control */
  --hairline: rgba(35, 33, 28, 0.12);
  --hairline-strong: rgba(35, 33, 28, 0.22);
  --hairline-inverse: rgba(255, 255, 255, 0.22);
  --hairline-inverse-strong: rgba(255, 255, 255, 0.4);

  /* type. EB Garamond sets small; every serif step below already carries the
     ~14% it needs beside Public Sans. These are shipping sizes. */
  --serif: "EB Garamond", Garamond, Georgia, "Times New Roman", serif;
  --sans: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
  --display-track: -0.005em;

  --t-display: clamp(2.5rem, 5.9vw, 4.75rem);
  --t-headline: clamp(2.25rem, 4.5vw, 3.5rem);
  --t-title: clamp(1.5rem, 2.5vw, 1.875rem);
  --t-title-sm: 1.4375rem;
  --t-quote: clamp(1.4375rem, 2.7vw, 2rem);
  --t-body: clamp(1rem, 1.1vw, 1.125rem);
  --t-caption: 0.875rem;
  --t-label: 0.8125rem;

  /* space — 4/8/16/24/40/64/96, and the band */
  --s-xs: 4px;
  --s-sm: 8px;
  --s-md: 16px;
  --s-lg: 24px;
  --s-xl: 40px;
  --s-2xl: 64px;
  --s-3xl: 96px;
  --band: clamp(64px, 9vw, 128px);

  --gutter: 20px;
  --container: 1200px;
  --header-h: 68px;
  --tap: 44px;
  --bar-h: 72px;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 120ms;
  --dur: 180ms;
  --dur-slow: 320ms;
}

@media (min-width: 768px) { :root { --gutter: 32px; --header-h: 76px; } }
@media (min-width: 1280px) { :root { --gutter: 48px; } }

body.density-regular { --band: clamp(48px, 6vw, 88px); }

/* ─────────────────────────────────────── reset + browser surfaces */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: calc(var(--header-h) + 16px); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--sand);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, p, figure, blockquote, table { margin: 0; }
/* height:auto matters: an intrinsic height attribute counts as a specified
   height, and a specified height stops aspect-ratio from computing one — which
   turns every square tile into a full-column strip. Components that set their
   own height override this by specificity. */
img { display: block; max-width: 100%; height: auto; }
button, input, textarea, select { font: inherit; color: inherit; }

/* The parts nobody draws still carry the design. */
::selection { background: var(--olive); color: var(--paper); }
:root { caret-color: var(--clay); accent-color: var(--olive); }
* { scrollbar-color: var(--olive-mid) var(--sand-mid); scrollbar-width: thin; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--sand-mid); }
::-webkit-scrollbar-thumb { background: var(--olive-mid); border: 3px solid var(--sand-mid); }
::-webkit-scrollbar-thumb:hover { background: var(--olive); }

:focus-visible { outline: 2px solid var(--clay); outline-offset: 3px; }
.on-olive :focus-visible, .on-olive:focus-visible { outline-color: var(--paper); }

/* A paper panel inside an olive band inherits the band's paper text unless it
   resets. That is how a white heading lands on a white ground. */
.on-olive .card, .on-olive .panel { color: var(--ink); }

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

.skip-link {
  position: absolute; left: var(--s-md); top: -100px; z-index: 100;
  background: var(--clay); color: var(--paper);
  padding: var(--s-md) var(--s-lg);
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.09em;
  text-transform: uppercase; text-decoration: none;
  transition: top var(--dur) var(--ease);
}
.skip-link:focus { top: var(--s-md); }

/* ─────────────────────────────────────────────────────── type roles */

.t-display, .t-headline, .t-title, .t-quote {
  font-family: var(--serif); font-weight: 400;
}
.t-display { font-size: var(--t-display); line-height: 1.05; letter-spacing: var(--display-track); text-wrap: balance; }
.t-headline { font-size: var(--t-headline); line-height: 1.15; letter-spacing: var(--display-track); text-wrap: balance; }
.t-title { font-size: var(--t-title); line-height: 1.3; text-wrap: balance; }
.t-quote { font-size: var(--t-quote); line-height: 1.45; }

.t-label {
  font-family: var(--sans); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase; line-height: 1.2;
}
.t-body { max-width: 68ch; }
.t-body + .t-body { margin-top: 1.1em; }
/* Markdown fields emit their own paragraphs inside the wrapper. */
.t-body > p + p { margin-top: 1.1em; }
.muted { color: var(--ink-muted); }
.on-olive .muted { color: var(--olive-wash); }


/* ────────────────────────────────────────────── bands + container */

.band { padding-block: var(--band); }
.band--sand { background: var(--sand); color: var(--ink); }
.band--olive { background: var(--olive); color: var(--paper); }

.wrap {
  width: min(var(--container), 100% - (var(--gutter) * 2));
  margin-inline: auto;
}

/* A band heading owns its own line and a measure of air beneath it. There are
   no eyebrows in this system — the heading says what the section is. */
.band__head { margin-bottom: var(--s-2xl); }
.band__head .t-body { margin-top: var(--s-lg); }

/* ────────────────────────────────────────────────────────── buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-sm);
  min-height: var(--tap);
  font-family: var(--sans); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase; text-decoration: none;
  padding: 18px 40px;
  border: none; border-radius: 999px;   /* the only round thing */
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.btn--primary { background: var(--clay); color: var(--paper); }
.btn--primary:hover { background: var(--clay-deep); }

/* Clay is never used on an olive band: the contrast is poor and the band is
   already carrying the emphasis. */
.btn--on-olive { background: var(--paper); color: var(--olive-dark); }
.btn--on-olive:hover { background: var(--olive-wash); }

.btn--sm { padding: 13px 26px; }

/* Busy, not disabled: an olive ground carries paper text at 5.7:1, so the state
   a visitor is waiting on is actually readable. The captcha's own re-submit
   needs the button enabled, so the busy state is carried by aria-busy — which
   is also what tells a screen reader something is in flight. */
.btn[disabled], .btn[aria-busy="true"] { background: var(--olive); color: var(--paper); cursor: progress; }
.btn[disabled]:hover, .btn[aria-busy="true"]:hover { background: var(--olive); }
.btn--on-olive[disabled], .btn--on-olive[aria-busy="true"] { background: var(--olive-deep); color: var(--paper); }
.btn__spin {
  width: 13px; height: 13px; flex: none;
  border: 2px solid var(--hairline-inverse-strong); border-top-color: var(--paper);
  border-radius: 999px;
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .btn__spin { animation-duration: 2.4s; } }

/* A phone number is a tap target, not a run of text. The live site's is neither. */
.tel {
  display: inline-flex; align-items: center;
  min-height: var(--tap);
  text-underline-offset: 4px; text-decoration-thickness: 1px;
}

/* ─────────────────────────────────────────────────────────── header */

.header {
  position: sticky; top: 0; z-index: 40;
  background: var(--sand);
  border-bottom: 1px solid var(--hairline);
}
.header__inner {
  width: min(var(--container), 100% - (var(--gutter) * 2));
  margin-inline: auto;
  display: grid; grid-template-columns: auto 1fr auto;
  align-items: center; gap: var(--s-md);
  min-height: var(--header-h);
}
.header__mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap); margin-left: -10px;
}
.header__mark img { width: 30px; height: 30px; }
.header__name {
  font-family: var(--serif); font-weight: 400;
  font-size: var(--t-body); letter-spacing: 0.01em;
  white-space: nowrap; justify-self: start;
}
.header .btn { padding: 12px 16px; white-space: nowrap; letter-spacing: 0.07em; }
/* Narrow phones: the wordmark and the full button no longer fit side by side, so
   the button tightens first and, below 480px, the mark stands alone — the name
   is one tap away in the aria-label and the page's own headline. */
@media (max-width: 419px) {
  .header__inner { gap: 12px; }
  .header .btn { padding: 12px 14px; letter-spacing: 0.05em; }
}
@media (max-width: 479px) { .header__name { display: none; } }

@media (min-width: 768px) {
  .header__mark img { width: 34px; height: 34px; }
  .header__name { font-size: var(--t-title-sm); justify-self: center; }
  .header .btn { padding: 13px 26px; }
}

/* ───────────────────────────────────────────────────────────── hero */

/* Shared by both treatments. */
.hero { position: relative; }
.hero__media { overflow: hidden; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: 58% 50%; }
@media (min-width: 900px) { .hero__media img { object-position: 50% 50%; } }
.hero__inner {
  position: relative;
  display: flex; align-items: flex-end;
  padding-block: var(--s-xl) var(--s-2xl);
}
.hero__text { width: min(60ch, 100%); }
.hero h1 { color: var(--paper); }
.hero__sub {
  margin-top: var(--s-lg);
  max-width: 46ch;
  color: var(--olive-wash);
  font-size: var(--t-body);
}

/* Treatment one — the words sit on the photograph. The scrim is the olive band
   bleeding across it, so the hero keeps the rhythm of everything below. */
.hero--overlay { background: var(--olive-ink); }
.hero--overlay .hero__media { position: absolute; inset: 0; }
.hero--overlay .hero__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, rgba(47, 47, 36, 0.94) 0%, rgba(47, 47, 36, 0.88) 55%, rgba(47, 47, 36, 0.74) 80%, rgba(47, 47, 36, 0.5) 100%);
}
.hero--overlay .hero__inner { min-height: clamp(480px, 76vh, 720px); }

@media (min-width: 900px) {
  .hero--overlay .hero__scrim {
    background:
      linear-gradient(100deg, rgba(47, 47, 36, 0.9) 0%, rgba(47, 47, 36, 0.82) 36%, rgba(47, 47, 36, 0.5) 58%, rgba(47, 47, 36, 0.14) 80%, rgba(47, 47, 36, 0) 93%),
      linear-gradient(to top, rgba(47, 47, 36, 0.46) 0%, rgba(47, 47, 36, 0) 44%);
  }
  .hero--overlay .hero__text { width: min(54ch, 62%); }
}

/* Treatment two — the photograph keeps its own frame and the words sit on their
   own olive field beside it. No scrim; the field carries the contrast. */
.hero--split { background: var(--olive); }
.hero--split .hero__media { aspect-ratio: 3 / 2; }
.hero--split .hero__scrim { display: none; }
.hero--split .hero__inner { background: var(--olive); }

@media (min-width: 1024px) {
  .hero--split { display: grid; grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr); align-items: stretch; }
  .hero--split .hero__media { aspect-ratio: auto; order: 2; min-height: clamp(480px, 70vh, 680px); }
  .hero--split .hero__inner {
    order: 1; align-items: center;
    width: 100%; max-width: none; margin: 0;
    padding: var(--s-3xl) var(--s-2xl) var(--s-3xl) var(--gutter);
  }
  .hero--split .hero__text {
    width: 100%; max-width: 34rem;
    margin-left: auto; padding-right: var(--s-xl);
  }
  .hero--split h1 { font-size: var(--t-headline); line-height: 1.1; }
}
@media (min-width: 1392px) {
  .hero--split .hero__inner { padding-left: calc((100vw - var(--container)) / 2 + var(--gutter)); }
}

/* ───────────────────────────────────────────────────────── programs */

.cards {
  display: grid; gap: var(--s-lg);
  grid-template-columns: 1fr;
}
@media (min-width: 620px) { .cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .cards { grid-template-columns: repeat(4, 1fr); } }

/* One media ratio across the row, so four headings share one baseline. On the
   live site four differently-shaped photographs push them 250px apart. */
.card { background: var(--paper); display: flex; flex-direction: column; }
.card__media { aspect-ratio: 4 / 3; overflow: hidden; }
.card__media img { width: 100%; height: 100%; object-fit: cover; }
.card__body { padding: clamp(20px, 2.2vw, 28px); }
.card__body h3 { margin-bottom: var(--s-sm); }
.card__body p { color: var(--ink-muted); font-size: 1rem; line-height: 1.6; }

/* ──────────────────────────────────────────────────────────── about */

.about { display: grid; gap: var(--s-2xl); }
@media (min-width: 900px) {
  .about { grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.7fr); gap: var(--s-3xl); align-items: start; }
}
.about__body { margin-top: var(--s-xl); max-width: 36ch; text-wrap: pretty; }
.about__sign {
  margin-top: var(--s-xl);
  padding-top: var(--s-lg);
  border-top: 1px solid var(--hairline);
  max-width: 32ch;
  color: var(--ink-muted);
}
.on-olive .about__sign { border-top-color: var(--hairline-inverse); }
.about__portrait { aspect-ratio: 3 / 4; overflow: hidden; }
.about__portrait img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 40%; }

/* ─────────────────────────────────────────────────────── classrooms */

.rooms {
  display: grid; gap: var(--s-md);
  grid-template-columns: repeat(2, 1fr);
  margin-top: var(--s-2xl);
}
@media (min-width: 900px) { .rooms { grid-template-columns: repeat(4, 1fr); gap: var(--s-lg); } }
.rooms img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }

/* ─────────────────────────────────────────────────── testimonials

   Three parent letters, not three cards. The name sits in the rail to the
   left, level with the quote's first line, so a visitor knows whose words
   these are before reading them instead of five lines later — the serif alone
   cannot tell the school's voice from a parent's, and every heading on this
   page is the same face.

   Rows also settle the conflict a three-column grid could not: DESIGN.md asks
   the Testimonial component for both a 45-55 character measure and all three
   at once, and inside a 1200px container three columns are ~368px, which buys
   the grid only by shrinking the type below the body copy in the band above.
   A row gives each quote the full Quote step at ~53 characters, and all three
   are still on screen without a control to operate. */

/* Rules above each entry and one below the last: three letters read as a set
   that is closed, rather than a list that stopped. */
.quotes { display: grid; border-bottom: 1px solid var(--hairline); }
.quote {
  display: grid; gap: var(--s-sm);
  border-top: 1px solid var(--hairline);
  padding-block: var(--s-lg) var(--s-xl);
}
.on-olive .quotes, .on-olive .quote { border-color: var(--hairline-inverse); }
.on-olive .quote blockquote { color: var(--paper); }
.quote blockquote {
  font-family: var(--serif); font-weight: 400;
  font-size: var(--t-quote); line-height: 1.45;
  color: var(--ink);
  max-width: 42ch;   /* ~53 rendered characters; EB Garamond's ch is 0.48em */
  text-wrap: pretty;
}
.on-olive .quote blockquote { color: var(--paper); }
.quote figcaption { color: var(--ink-muted); }
.on-olive .quote figcaption { color: var(--olive-mist); }

@media (min-width: 768px) {
  .quote {
    grid-template-columns: minmax(0, 0.22fr) minmax(0, 0.78fr);
    gap: var(--s-xl);
    align-items: baseline;
  }
}

/* ─────────────────────────────────────────────────── contact + footer */

.footer { background: var(--olive-dark); color: var(--paper); padding-block: var(--band) var(--s-2xl); }
.footer :focus-visible { outline-color: var(--paper); }
.footer .t-label { color: var(--olive-mist); }
.footer .muted { color: var(--olive-wash); }
/* Not .btn: a button link carries its own text colour, and this rule is more
   specific than the variant — it once painted paper text on the paper pill. */
.footer a:not(.btn) { color: var(--paper); text-underline-offset: 4px; }

.contact { display: grid; gap: var(--s-2xl); }
@media (min-width: 900px) {
  .contact { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: var(--s-3xl); align-items: start; }
}
.contact__head { margin-bottom: var(--s-xl); }
.contact__head .t-body { margin-top: var(--s-md); }

.details { display: grid; gap: var(--s-xl); }
.details__block { border-top: 1px solid var(--hairline-inverse); padding-top: var(--s-md); }
.details__block .t-label { display: block; margin-bottom: var(--s-sm); }
.details address { font-style: normal; display: grid; gap: 2px; }
/* Brand marks, not an icon set. The system's ban on icons stands everywhere
   else on the page; a destination's own mark is how that destination writes
   its name, and a row of two is read faster than two words are.

   Bounded like the map, and for the same reason: a control should look like
   one. A bare 20px glyph floating on the band reads as decoration. */
.details__links { display: flex; flex-wrap: wrap; gap: var(--s-sm); }
.details__links a {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap);
  border: 1px solid var(--hairline-inverse);
  text-decoration: none;
  transition: border-color var(--dur) var(--ease);
}
.details__links a:hover { border-color: var(--hairline-inverse-strong); }
.social__mark { display: block; width: 20px; height: 20px; }
/* Optical size, not measured size. Instagram's mark is drawn as an outline;
   Facebook's, LinkedIn's and YouTube's are solid silhouettes that fill their
   box. Set to the same 20px the solid ones read a size larger, and the row
   stops looking like a row. These sit down to match. */
.social__mark[data-mark="facebook"],
.social__mark[data-mark="linkedin"],
.social__mark[data-mark="youtube"] { width: 18px; height: 18px; }

/* The map is a control, not a divider, so it takes the bounding weight. */
.map {
  display: block; margin-top: var(--s-xl);
  border: 1px solid var(--hairline-inverse-strong);
  text-decoration: none;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.map img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.map__cue {
  display: block;
  padding: var(--s-md);
  border-top: 1px solid var(--hairline-inverse);
  color: var(--olive-mist);
  transition: color var(--dur) var(--ease);
}
.map:hover { border-color: var(--paper); }
.map:hover .map__cue { color: var(--paper); }

.footer__legal {
  margin-top: var(--s-3xl); padding-top: var(--s-md);
  border-top: 1px solid var(--hairline-inverse);
  display: flex; flex-wrap: wrap; gap: var(--s-sm) var(--s-lg); align-items: center;
  color: var(--olive-mist); font-size: var(--t-caption);
}
.footer__legal img { width: 26px; height: 26px; }
.footer__link { display: inline-flex; align-items: center; min-height: var(--tap); color: var(--olive-mist); text-underline-offset: 4px; }
.footer__link:hover { color: var(--paper); }
@media (min-width: 620px) { .footer__link { margin-left: auto; } }

/* ───────────────────────────────────────────────────────────── form */

/* The form is one grid. Fields span it; a field marked --half takes a single
   column once there is room for two, which is how Name and Phone Number sit
   side by side without a wrapper element the CMS would have to invent. */
.form { display: grid; gap: var(--s-lg); }
@media (min-width: 620px) {
  .form { grid-template-columns: 1fr 1fr; }
  .form > * { grid-column: 1 / -1; }
  .form > .field--half { grid-column: auto; }
}

.field { display: flex; flex-direction: column; gap: 6px; }
.field > label { color: var(--olive-mist); }
.field > label .req { color: var(--sand); margin-left: 2px; }
.field input, .field textarea {
  /* width:100% because the CMS wraps a textarea in a div of its own, and a
     textarea without it falls back to its cols attribute. */
  width: 100%;
  background: transparent;
  border: none; border-bottom: 1px solid var(--hairline-inverse); border-radius: 0;
  padding: 12px 0;
  min-height: var(--tap);
  color: var(--paper);
  transition: border-color var(--dur-fast) var(--ease);
}
.field textarea { resize: vertical; min-height: 108px; }
.field input::placeholder, .field textarea::placeholder { color: var(--olive-pale); }
.field input:focus, .field textarea:focus {
  border-bottom-color: var(--sand); border-bottom-width: 2px; padding-bottom: 11px;
}
.field--error input, .field--error textarea {
  border-bottom-color: var(--sand); border-bottom-width: 2px;
}
.field__err { color: var(--sand); font-size: var(--t-caption); }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* The summary sits with the submit control, because that is where the thumb
   already is. A message a screen above the tapped button reads as nothing
   happening at all. */
.form__summary {
  border: 1px solid var(--sand);
  background: var(--olive-deep);
  padding: var(--s-md) var(--s-lg);
  color: var(--paper);
}
.form__summary b { display: block; margin-bottom: 4px; }
.form__summary ul { margin: 0; padding-left: 1.1em; font-size: var(--t-caption); }
.form__summary a { color: var(--sand); }

.form__foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-md); margin-top: var(--s-sm); }
.form__foot .muted { font-size: var(--t-caption); max-width: 36ch; }

/* Cap runs invisible by default; this is the labelled slot for mode: checkbox,
   so nothing moves if the school ever turns the widget on. */
/* Cap runs invisible by default: the field draws nothing a person can see, so
   its wrapper goes with it. Switch the plugin to checkbox mode and the same
   field becomes the labelled slot the widget renders into — the space was
   always accounted for, so nothing around it moves. */
body:not(.captcha-checkbox) .field--captcha { display: none; }
body.captcha-checkbox .field--captcha {
  border: 1px solid var(--hairline-inverse-strong); padding: var(--s-md);
  color: var(--olive-wash);
}

.sent { border: 1px solid var(--hairline-inverse); padding: var(--s-xl); }
.sent:focus-visible { outline-offset: 6px; }

/* The one state change worth animating: the form leaving and the answer
   arriving in its place. The form dims while the request is in flight, then
   the panel materialises — rising a little and drawing its own edge — rather
   than appearing as a hard swap. Short, once, and in the same exponential
   ease-out the hero uses; the page has no other motion vocabulary to learn. */
.form[data-busy="1"] {
  opacity: 0.5;
  transition: opacity var(--dur) var(--ease);
}

@media (prefers-reduced-motion: no-preference) {
  .sent { animation: sent-in 420ms var(--ease) both; }
}

@keyframes sent-in {
  from { opacity: 0; transform: translateY(10px); border-color: transparent; }
  to   { opacity: 1; transform: none; }
}
.sent h3 { font-family: var(--serif); font-weight: 400; font-size: var(--t-title); margin-bottom: var(--s-sm); }

/* ──────────────────────────────────────────────────────────── facts
   An unconfirmed value still renders as real content — the blueprint field
   behind it will hold real content, and a page of holes cannot be reviewed.
   ?annotate=1 tints each one and prints its content/CONTENT-GAPS.md section.
   Review affordance only; it never ships. */

body.annotate .fact--pending {
  background: rgba(176, 83, 43, 0.1);
  box-shadow: -3px 0 0 0 var(--clay);
  padding-left: var(--s-sm);
}
body.annotate .fact--pending::after {
  content: attr(data-gap);
  display: inline-block; margin-left: var(--s-sm);
  font-family: var(--sans); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--clay-deep); vertical-align: 2px;
}
body.annotate .on-olive .fact--pending::after,
body.annotate .footer .fact--pending::after { color: var(--sand); }

.annotate-note {
  position: fixed; inset: auto var(--s-md) var(--s-md) auto; z-index: 60;
  max-width: 30ch; background: var(--olive-ink); color: var(--paper);
  padding: var(--s-md) var(--s-lg);
  font-size: var(--t-caption); line-height: 1.5;
}
.annotate-note b { display: block; font-size: var(--t-label); letter-spacing: 0.09em; text-transform: uppercase; margin-bottom: 4px; }

/* ────────────────────────────────────── motion: one authored moment
   The hero settles once, on load. Everything below it is visible from the
   first frame — no scroll-triggered entrances, nothing that can strand
   content behind a stalled observer. */

/* Gated on body.is-ready, which app.jsx adds after mount. Visible is the
   default: if the script never runs, or a paint lands before it does, the hero
   renders finished rather than showing an empty olive field where the headline
   should be. The wipe clips the headline to nothing at its start, so an
   ungated animation is a headline that can be absent. */
@media (prefers-reduced-motion: no-preference) {
  body.is-ready .hero__scrim { animation: scrim 1100ms var(--ease) both; }
  body.is-ready .hero h1 { animation: wipe 950ms var(--ease) 80ms both; }
  body.is-ready .hero__sub { animation: rise 900ms var(--ease) 320ms both; }
  body.is-ready .hero__media img { animation: settle 1600ms var(--ease) both; }
}

@keyframes scrim { from { opacity: 0; } to { opacity: 1; } }
@keyframes settle { from { transform: scale(1.035); } to { transform: none; } }
@keyframes wipe {
  from { opacity: 0; clip-path: inset(0 0 100% 0); transform: translateY(0.14em); }
  to   { opacity: 1; clip-path: inset(0 0 -0.25em 0); transform: none; }
}
@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}


/* ═══════════════════════════════════════════ conversion + trust refresh */

/* ── secondary button ─────────────────────────────────────────────────────
   Outline on the hero's dark ground: the call is an equal option, never the
   louder one. A real border, not a shadow — the system has none. Padding is
   one pixel short each way so it stands the same height as the primary. */
.btn--ghost {
  background: transparent; color: var(--paper);
  border: 1px solid var(--hairline-inverse-strong); padding: 17px 39px;
}
.btn--ghost:hover { background: rgba(255, 255, 255, 0.12); border-color: var(--paper); }
/* The hero sits on a dark scrim but is not an .on-olive band. */
.hero :focus-visible { outline-color: var(--paper); }

/* ── hero additions ───────────────────────────────────────────────────── */

.hero__eyebrow { color: var(--olive-mist); margin-bottom: var(--s-md); letter-spacing: 0.14em; text-wrap: balance; }
.hero__actions { display: flex; flex-direction: column; gap: var(--s-sm); margin-top: var(--s-lg); }
.hero__actions .btn { width: 100%; }
.hero__trust {
  margin-top: var(--s-lg); max-width: 46ch;
  color: var(--olive-mist); font-size: var(--t-caption); line-height: 1.6;
}
/* The strip below says the same four things; on a phone it is one scroll away,
   so the hero's own line steps aside until there is room for both. */
.hero__trust { display: none; }
@media (min-width: 900px) { .hero__trust { display: block; } }
@media (min-width: 620px) {
  .hero__actions { flex-direction: row; flex-wrap: wrap; gap: var(--s-md); }
  .hero__actions .btn { width: auto; }
}
@media (min-width: 900px) { .hero--overlay .hero__text { width: min(56ch, 64%); } }
@media (prefers-reduced-motion: no-preference) {
  body.is-ready .hero__eyebrow { animation: rise 900ms var(--ease) both; }
  body.is-ready .hero__actions,
  body.is-ready .hero__trust { animation: rise 900ms var(--ease) 480ms both; }
}

/* ── trust strip ──────────────────────────────────────────────────────── */

.strip { background: var(--sand-light); border-bottom: 1px solid var(--hairline); }
.strip__list {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr;
}
.strip__list li {
  padding: var(--s-lg) var(--s-md); text-align: center; color: var(--olive-dark);
  border-top: 1px solid var(--hairline); line-height: 1.4;
  display: flex; align-items: center; justify-content: center;
}
.strip__list li:nth-child(-n+2) { border-top: none; }
.strip__list li:nth-child(even) { border-left: 1px solid var(--hairline); }
@media (min-width: 900px) {
  .strip__list { grid-template-columns: repeat(4, 1fr); }
  .strip__list li { border-top: none; border-left: 1px solid var(--hairline); padding: var(--s-lg); }
  .strip__list li:first-child { border-left: none; }
}

/* ── call to action after the program cards ───────────────────────────── */

.cta-row {
  display: grid; gap: var(--s-lg); align-items: center; justify-items: start;
  margin-top: var(--s-2xl); padding-top: var(--s-xl);
  border-top: 1px solid var(--hairline-inverse);
}
.pull { display: grid; gap: var(--s-sm); max-width: 46ch; }
.pull blockquote {
  font-family: var(--serif); font-size: var(--t-title-sm); line-height: 1.45; text-wrap: pretty;
}
.pull figcaption { color: var(--olive-mist); }
@media (min-width: 900px) {
  .cta-row { grid-template-columns: minmax(0, 1fr) auto; gap: var(--s-3xl); }
}

/* ── why families choose ──────────────────────────────────────────────── */

.why { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-xl); }
.why__item { border-top: 1px solid var(--hairline-strong); padding-top: var(--s-lg); }
.why__item h3 { margin-bottom: var(--s-sm); }
.why__item p { max-width: 34ch; }
@media (min-width: 620px) { .why { grid-template-columns: repeat(2, 1fr); gap: var(--s-xl) var(--s-xl); } }
@media (min-width: 1024px) { .why { grid-template-columns: repeat(4, 1fr); gap: var(--s-xl) var(--s-lg); } }

/* ── faq ──────────────────────────────────────────────────────────────── */

.faq { border-bottom: 1px solid var(--hairline); max-width: 820px; }
.faq__item { border-top: 1px solid var(--hairline); }
.faq__item summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-lg);
  min-height: var(--tap); padding-block: var(--s-lg);
  font-size: var(--t-title-sm); list-style: none; cursor: pointer;
}
.faq__item summary::-webkit-details-marker { display: none; }
/* A typographic plus, not an icon: it becomes a minus when the row opens. */
.faq__item summary::after {
  content: "+"; flex: none; font-family: var(--sans); font-size: 1.5rem; line-height: 1;
  color: var(--olive);
}
.faq__item[open] summary::after { content: "\2212"; }
.faq__item summary:hover { color: var(--olive-deep); }
.faq__a { padding-bottom: var(--s-lg); max-width: 62ch; }
.faq__a a { color: var(--ink); text-underline-offset: 4px; }

/* ── tour form: added fields ──────────────────────────────────────────── */

.field .opt { color: var(--olive-pale); font-weight: 400; letter-spacing: 0.04em; text-transform: none; margin-left: 4px; }
.field select, .field input[type="date"] { color-scheme: dark; }
.field select {
  width: 100%; min-height: var(--tap); padding: 12px 0;
  background: transparent; border: none; border-bottom: 1px solid var(--hairline-inverse);
  border-radius: 0; color: var(--paper); cursor: pointer;
}
.field select:has(option[value=""]:checked) { color: var(--olive-pale); }
.field select option { color: var(--ink); background: var(--paper); }
.field select:focus { border-bottom-color: var(--sand); border-bottom-width: 2px; padding-bottom: 11px; }
.field--error select { border-bottom-color: var(--sand); border-bottom-width: 2px; }
.form__note { font-size: var(--t-caption); }
.details__note { font-size: var(--t-caption); margin-top: var(--s-sm); max-width: 32ch; }

/* ── mobile conversion bar ────────────────────────────────────────────────
   Phones only. DESIGN.md → Mobile Action Bar says below 1024px; at tablet width
   the header's own tour button, the hero's and this bar's made three of the same
   action in one viewport, so the bar stops at 767px. It reserves its own height on <body> so it never sits over
   the footer, respects the bottom safe area, and slides away while the form
   is on screen so it cannot cover a field. */

.bar { display: none; }
@media (max-width: 767px) {
  body.has-bar { padding-bottom: calc(var(--bar-h) + env(safe-area-inset-bottom, 0px)); }
  body.has-bar .bar {
    position: fixed; inset: auto 0 0 0; z-index: 50;
    display: flex; align-items: center; gap: var(--s-sm);
    padding: var(--s-sm) var(--gutter) calc(var(--s-sm) + env(safe-area-inset-bottom, 0px));
    background: var(--sand); border-top: 1px solid var(--hairline-strong);
    transition: transform var(--dur-slow) var(--ease);
  }
  body.has-bar.bar-hidden .bar { transform: translateY(100%); visibility: hidden; transition: transform var(--dur-slow) var(--ease), visibility 0s var(--dur-slow); }
  .bar .btn { flex: 1; min-height: 52px; padding-inline: var(--s-md); }
  .bar__call {
    flex: none; width: 52px; height: 52px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--olive-dark); text-decoration: none;
    border: 1px solid var(--hairline-strong);   /* square: the pill is the primary button's alone */
    transition: background var(--dur) var(--ease);
  }
  .bar__call:hover { background: var(--sand-mid); }
  .phone__mark { width: 22px; height: 22px; }
}
@media (prefers-reduced-motion: reduce) {
  body.has-bar .bar, body.has-bar.bar-hidden .bar { transition: none; }
}


/* ═══════════════════════════════════════════════════ privacy policy page */


/* ── title band ───────────────────────────────────────────────────────── */

.phero { background: var(--olive); color: var(--paper); padding-block: clamp(56px, 8vw, 112px) clamp(48px, 6vw, 88px); }
.phero__lede { margin-top: var(--s-lg); max-width: 52ch; text-wrap: pretty; color: var(--olive-wash); font-size: var(--t-body); }
.phero__meta {
  margin-top: var(--s-xl); padding-top: var(--s-md);
  border-top: 1px solid var(--hairline-inverse);
  display: flex; flex-wrap: wrap; gap: var(--s-xs) var(--s-xl);
  color: var(--olive-mist); font-size: var(--t-caption);
}
@media (prefers-reduced-motion: no-preference) {
  body.is-ready .phero h1 { animation: wipe 950ms var(--ease) 80ms both; }
  body.is-ready .phero__lede, body.is-ready .phero__meta { animation: rise 900ms var(--ease) 300ms both; }
}

/* ── reading layout ───────────────────────────────────────────────────── */

.policy__grid { display: grid; gap: var(--s-2xl); }
@media (min-width: 1024px) {
  .policy__grid { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: var(--s-3xl); align-items: start; }
  .policy__grid--solo { grid-template-columns: minmax(0, 1fr); }
}
.policy__main { max-width: 46rem; }

/* Contents: a reference list, so it sits still beside the text on wide screens
   and folds into a two-column list above it on a phone. */
.toc { border-top: 1px solid var(--hairline-strong); padding-top: var(--s-md); }
.toc h2 { color: var(--ink-muted); margin-bottom: var(--s-sm); }
.toc ol { list-style: none; margin: 0; padding: 0; display: grid; }
.toc a {
  display: flex; align-items: center; min-height: var(--tap);
  color: var(--ink-muted); text-decoration: none; font-size: var(--t-caption); line-height: 1.35;
  padding-block: 6px; transition: color var(--dur) var(--ease);
}
.toc a:hover, .toc a[aria-current="true"] { color: var(--olive-deep); }
.toc a[aria-current="true"] { font-weight: 600; text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 6px; }
@media (min-width: 620px) and (max-width: 1023px) { .toc ol { grid-template-columns: 1fr 1fr; column-gap: var(--s-xl); } }
@media (min-width: 1024px) { .toc { position: sticky; top: calc(var(--header-h) + var(--s-lg)); } }

/* ── in short ─────────────────────────────────────────────────────────── */

.short { padding-bottom: var(--s-2xl); }
.short h2 { margin-bottom: var(--s-lg); }
.short__list { list-style: none; margin: 0; padding: 0; border-bottom: 1px solid var(--hairline-strong); }
.short__list li {
  padding-block: var(--s-lg); border-top: 1px solid var(--hairline-strong);
  font-size: clamp(1.25rem, 2.2vw, 1.5rem); line-height: 1.45; text-wrap: pretty;
}

/* ── sections + prose ─────────────────────────────────────────────────── */

.psec { padding-block: var(--s-xl) var(--s-lg); border-top: 1px solid var(--hairline); }
.psec + .psec { margin-top: var(--s-lg); }
.short + .psec { border-top: none; margin-top: 0; padding-top: 0; }
.psec > h2 { margin-bottom: var(--s-lg); max-width: 26ch; }
.psec:target > h2 { text-decoration: underline; text-decoration-color: var(--clay); text-decoration-thickness: 2px; text-underline-offset: 8px; }

.prose { max-width: 68ch; }
.prose > * + * { margin-top: 1.1em; }
.prose p, .prose li { font-size: var(--t-body); line-height: 1.7; }
.prose ul { padding-left: 1.2em; }
.prose li { padding-left: 0.3em; }
.prose li + li { margin-top: 0.55em; }
.prose li::marker { color: var(--olive-mid); }
.prose a { color: var(--olive-deep); text-underline-offset: 4px; text-decoration-thickness: 1px; }
.prose a:hover { color: var(--clay-deep); }
.prose b { font-weight: 600; }
.prose code {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; font-size: 0.86em;
  background: var(--sand-mid); padding: 1px 6px;
}
.prose .sub { margin-top: 2.2em; margin-bottom: -0.2em; color: var(--ink-muted); }
.prose .tag { color: var(--ink-muted); font-size: var(--t-caption); margin-left: 6px; }

/* The one sentence a reader must not miss: set on a lighter ground, no side
   stripe, no box shadow. */
.prose .note { background: var(--sand-light); border: 1px solid var(--hairline); padding: var(--s-lg); }

/* Services table. A grid of rows on wide screens; each row becomes a labelled
   stack on a phone rather than a table that scrolls sideways. */
.table { border-top: 1px solid var(--hairline-strong); }
.table__row { display: grid; gap: 2px; padding-block: var(--s-md); border-bottom: 1px solid var(--hairline); }
.table__row--head { display: none; }
.table__row [data-label]::before {
  content: attr(data-label); display: block; margin-bottom: 2px;
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--ink-muted);
}
@media (min-width: 620px) {
  .table__row { grid-template-columns: 1.1fr 1.6fr 1.1fr; gap: var(--s-lg); align-items: baseline; }
  .table__row--head { display: grid; color: var(--ink-muted); padding-block: var(--s-sm); }
  .table__row [data-label]::before { display: none; }
}

/* ── footer ───────────────────────────────────────────────────────────── */

.pfoot { display: grid; gap: var(--s-2xl); }
.pfoot .t-body { margin-top: var(--s-md); }
@media (min-width: 900px) { .pfoot { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: var(--s-3xl); align-items: start; } }

/* ── print: a policy gets printed ─────────────────────────────────────── */

@media print {
  .header, .toc, .footer .btn, .skip-link { display: none !important; }
  body { background: #fff; }
  .phero, .footer { background: #fff; color: #000; padding-block: 16px; }
  .phero__lede, .phero__meta, .footer .muted { color: #333; }
  .psec { break-inside: avoid; }
}

/* Markdown in the policy text: sub-headings read as the small tracked label the
   mockup sets them in, and a Markdown table takes the mockup's ruled rows. */
.prose h3 { margin-top: 2.2em; margin-bottom: -0.2em; color: var(--ink-muted);
  font-family: var(--sans); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase; line-height: 1.2; }
.prose table { width: 100%; border-collapse: collapse; border-top: 1px solid var(--hairline-strong); }
.prose th { text-align: left; padding-block: var(--s-sm); color: var(--ink-muted);
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; }
.prose td { padding-block: var(--s-md); vertical-align: baseline; padding-right: var(--s-md); }
.prose tr + tr, .prose thead tr { border-bottom: 1px solid var(--hairline); }
.prose tbody tr { border-bottom: 1px solid var(--hairline); }
@media (max-width: 619px) {
  .prose thead { display: none; }
  .prose tr, .prose td { display: block; }
  .prose td { padding-block: 2px; }
  .prose tr { padding-block: var(--s-md); }
}
