/* Page visibility for the single-document site.
 *
 * All 23 pages live in one DOM as <main class="page">, and the engine in
 * scripts.js adds `.active` to the one whose path is showing. The rule that
 * hides the rest used to live in site.css, which the redesign replaced -- the
 * design's own stylesheets know nothing about this architecture, because in
 * the ZIP each page was its own file.
 *
 * Kept in a separate sheet rather than patched into the design's CSS so the
 * design files stay byte-identical to the handoff and can be re-imported when
 * a new version arrives.
 */
.page { display: none; }
.page.active { display: block; animation: pageIn .45s cubic-bezier(.2, .8, .2, 1) both; }

/* The homepage intro measures fixed and absolute elements against the live
 * viewport. A translated page wrapper makes position:fixed descendants use
 * that wrapper as their coordinate space, so the first frame used to put the
 * travelling headline at the page's top-left before measurement caught up.
 * Keep the homepage wrapper still, and do not start its cinematic pieces until
 * home.js has installed real pixel coordinates for both landings. */
#page-home.active { animation-name: homePageIn; }
#page-home #heroBlobStage,
#page-home #heroRideText,
#page-home #heroWordFly,
#page-home #heroLockup,
#page-home #heroLockup > span,
#page-home #siteWordmark,
#page-home #heroH1,
#page-home #heroH1 > span:first-child {
  animation-play-state: paused !important;
}
html[data-hero-ready] #page-home #heroBlobStage,
html[data-hero-ready] #page-home #heroRideText,
html[data-hero-ready] #page-home #heroWordFly,
html[data-hero-ready] #page-home #heroLockup,
html[data-hero-ready] #page-home #heroLockup > span,
html[data-hero-ready] #page-home #siteWordmark,
html[data-hero-ready] #page-home #heroH1,
html[data-hero-ready] #page-home #heroH1 > span:first-child {
  animation-play-state: running !important;
}

@keyframes pageIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

@keyframes homePageIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .page.active { animation: none; }
}

/* The public site's only door to /admin: a 6px dot in the footer legal row.
 * Findable if you know it is there, invisible if you don't.
 *
 * Lives here rather than in a design stylesheet for the same reason the page
 * rules do: the design files stay byte-identical to the handoff so a new ZIP
 * can be re-imported wholesale. The original rule was scoped `.site-footer
 * .admin-inline-dot`; the redesign's footer has no such class, so it is scoped
 * to the footer element instead.
 */
footer .admin-inline-dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: rgba(250, 247, 239, .28); opacity: .55;
  transition: opacity .2s, background .2s;
  text-indent: -9999px; overflow: hidden; flex: 0 0 auto;
}
footer .admin-inline-dot:hover { opacity: 1; background: var(--sun); }

/* The Google review badge used a capital G set in the display serif, coloured
 * Google blue. That is a letter, not the mark -- it reads as a placeholder and
 * misuses the brand. Replaced in the markup with the real four-colour glyph;
 * this only sizes it inside the existing 32px circle.
 */
.grating__g svg { width: 18px; height: 18px; display: block; }

/* Footer hours wrapped onto two lines because the value column is `1fr` of a
 * narrow footer column, so "7:00 am – 6:00 pm" broke mid-range and each day
 * took two lines. Size the column to its content and stop it breaking.
 */
footer .hours { grid-template-columns: auto max-content; column-gap: .9rem; }
footer .hours dd { white-space: nowrap; }

/* ── Room-finder cue, directly under the hero ────────────────────────────────
   The expert review's point was that the fit finder is the strongest
   converting element on the homepage and it sat eighth: a parent read a
   promise, an argument and six practices before anything told them whether the
   school even takes their child's age. This is the ten-second qualifier that
   the review asked for, as one line rather than a second copy of the widget —
   a duplicated finder would mean duplicated ids and a second script instance,
   which is the exact trap this single-document site keeps falling into. */
.roomcue{padding-block:clamp(18px,2.4vw,30px)}
.roomcue__bar{
  display:flex;align-items:center;gap:1rem;flex-wrap:wrap;
  padding:1rem 1.4rem;border:1px solid var(--line);border-radius:999px;
  text-decoration:none;color:inherit;background:transparent;
  transition:border-color .18s,background .18s,transform .18s;
}
.roomcue__bar:hover{border-color:var(--sun);background:rgba(223,175,62,.07);transform:translateY(-1px)}
.roomcue__q{font-family:var(--display);font-size:clamp(1.15rem,2vw,1.5rem);line-height:1.2}
.roomcue__hint{
  font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;
  opacity:.62;margin-inline-start:auto;
}
.roomcue__go{
  flex:0 0 auto;width:2rem;height:2rem;border-radius:50%;
  display:grid;place-items:center;background:var(--sun);color:#221A08;font-weight:700;
}
@media (max-width:560px){
  .roomcue__hint{margin-inline-start:0;flex-basis:100%}
  .roomcue__go{margin-inline-start:auto}
}

/* ── CAPE step object ────────────────────────────────────────────────────────
   The sculpted object for the visible CAPE step — fallen tomato plants for
   Challenge, the plant tied to a ruler for Analyze, the cage for Produce, the
   rock for Evaluate. The elements are white objects on transparency, so they
   sit on the dark ground without a plate behind them.

   The <img> ships `hidden` and curiosity-v2.js only reveals it on a successful
   load, so a missing file is invisible rather than a broken icon. */
.cape__img{
  display:block;width:clamp(120px,17vw,190px);height:auto;
  margin:1.4rem 0 .4rem;
  filter:drop-shadow(0 14px 26px rgba(0,0,0,.30));
  animation:capeObjIn .45s cubic-bezier(.2,.7,.3,1) both;
}
@keyframes capeObjIn{from{opacity:0;transform:translateY(10px) scale(.97)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.cape__img{animation:none}}

/* ── Age-band strip on the programme pages ───────────────────────────────────
   The expert review's second structural fix. A parent who lands on Toddlers
   from a Google search has no way to see the rest of the ladder — the six age
   pages are not in the top nav, so their only route is back to the hub. This
   strip puts the whole ladder on every programme page with the current one
   marked, so they can step sideways.

   It sits directly under the topbar and above the page hero, which is dark
   (.phero), so it is styled as a dark band that reads as part of the header
   rather than as a bar floating on the hero. data-no-edit: it is navigation,
   and the nav is not click-to-edit territory. */
.ageband{background:var(--foot);border-bottom:1px solid var(--line-lt)}
.ageband__row{
  display:flex;gap:.4rem;align-items:stretch;
  overflow-x:auto;scrollbar-width:none;
  padding-block:.55rem;
}
.ageband__row::-webkit-scrollbar{display:none}
/* var(--r), not 999px: these labels vary from "Twos" to "Pre-K & VPK", and a
   999px radius on the short ones renders a circle while the long ones stay
   pills — the current item looked like a different component depending on
   which page you were on. A fixed radius reads the same at every width.
   min-width keeps the row on a rhythm instead of bunching. */
.ageband__pill{
  flex:0 0 auto;display:flex;flex-direction:column;gap:.1rem;
  min-width:7.5rem;padding:.45rem .9rem;border-radius:var(--r);text-decoration:none;
  color:rgba(250,247,239,.72);border:1px solid transparent;
  transition:background .18s,color .18s,border-color .18s;
}
.ageband__pill b{font-family:var(--body);font-weight:600;font-size:.85rem;line-height:1.2}
.ageband__pill small{
  font-family:var(--mono);font-size:.62rem;letter-spacing:.08em;opacity:.7;line-height:1.2;
}
.ageband__pill:hover{color:var(--paper);background:rgba(250,247,239,.08)}
.ageband__pill.is-current{
  color:#221A08;background:var(--sun);border-color:var(--sun);
}
.ageband__pill.is-current small{opacity:.75}

/* The room-cue bar sits on the evergreen ground directly under the hero (the
   cream gap between them read as a broken seam), so its border and hint have
   to come from the light side of the palette rather than --line, which is a
   dark alpha and disappears on green. */
.roomcue.on-ink .roomcue__bar{border-color:var(--line-lt)}
.roomcue.on-ink .roomcue__bar:hover{border-color:var(--sun);background:rgba(223,175,62,.12)}

/* ── Visit section on the dark ground ────────────────────────────────────────
   The fact list, the resource cards and the map were all styled for the light
   grounds and go nearly invisible on the evergreen band: --muted labels, a
   --line divider that is a dark alpha, and a sun-coloured icon on cream.
   Scoped to .on-ink so the same components keep their light-ground styling
   everywhere else. */
.on-ink .facts li{border-bottom-color:rgba(250,247,239,.22)}
.on-ink .facts b{color:rgba(250,247,239,.72)}
.on-ink .facts span,.on-ink .facts a{color:var(--paper)}
.on-ink .facts a:hover{color:var(--sun-lt)}

/* Resource cards: dark ink on cream, with a warm ring so the card itself reads
   as a target rather than a flat panel. */
.on-ink .resource{
  background:var(--paper);color:#221A08;
  border-color:rgba(223,175,62,.55);
  box-shadow:0 0 0 1px rgba(223,175,62,.28),0 14px 30px -18px rgba(0,0,0,.6);
}
.on-ink .resource b{color:#221A08}
.on-ink .resource small{color:#5C5445}
.on-ink .resource i{background:#221A08;color:var(--sun);font-size:1.05rem}
.on-ink .resource:hover{
  border-color:var(--sun);color:#221A08;
  box-shadow:0 0 0 3px rgba(223,175,62,.35),0 18px 34px -16px rgba(0,0,0,.6);
}

/* The map read as a small grey tile. Give it the wider column, real height and
   the map's own colour back. */
@media (min-width:900px){.visit-split{grid-template-columns:.92fr 1.08fr}}
.map--wide{min-height:460px;position:relative;border-color:rgba(250,247,239,.28)}
.map--wide iframe{min-height:460px;filter:none}
.map__cap{
  position:absolute;left:0;right:0;bottom:0;margin:0;padding:.6rem 1rem;
  background:rgba(34,26,8,.72);color:var(--paper);
  font-family:var(--mono);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;
}

/* ── Wordmark, 1.5× ──────────────────────────────────────────────────────────
   The schoolhouse mark was set at 38px in the header and 52px in the footer,
   which reads as a favicon beside the wordmark rather than as the brand. */
.mark__mark{height:69px}
footer .mark__mark{height:87px}
@media (max-width:640px){.mark__mark{height:57px}footer .mark__mark{height:70px}}
/* The header bar was a fixed 72px, so the 1.5× mark cropped at the baseline. */
.topbar__inner{height:auto;min-height:88px;padding-block:.35rem}
.on-ink .resource{gap:.85rem;padding:1rem 1.1rem}
.on-ink .resource b{font-size:1.05rem;line-height:1.15}

/* Homepage gallery band — its own colour so it doesn't read as the same
   surface as the sections above and below it. */
#a-week-in-pictures{background:#DFE6D2}
#a-week-in-pictures .eyebrow{color:#4E5A42}
#a-week-in-pictures figcaption{background:var(--paper)}

/* ── First-paint guard ───────────────────────────────────────────────────────
   Every page is display:none until the engine marks one `.active`, so a slow
   boot painted a document made only of the header and the footer — the footer
   sat directly under the header at the top of the window, then jumped once the
   hero appeared. LegacySite marks <html data-page-ready> on mount (before the
   scripts load); until then the footer stays out of the flow so there is no
   half-page to see. */
html:not([data-page-ready]) footer { display: none; }

/* ── The site's ground colour, restored ──────────────────────────────────
   `design.css` is assembled by concatenating every pack page's helmet, and
   each page's helmet carries its own `body { … }`. Two pages are designed on
   a dark ground — the Letter on AI and the tour page — so their
   `body{background:#22301E;color:#FAF6EC}` is in there too, and the tour
   page's copy is the LAST body rule in the file. Equal specificity, last one
   wins: **the whole site inherited a dark ground and cream text.**

   Almost everything sets its own colours, so it hid — except where text
   inherits. The homepage headline has no colour of its own, so "Curiosity
   leads the way." painted cream-on-cream until contrast-guard.js noticed at
   runtime and repaired it to ink. That is the white-then-green flash on every
   first load of the homepage, and the reason the contrast guard had so much
   to repair in the first place.

   Fixing it here rather than in the converter: one rule, after design.css,
   survives every future conversion, and cannot be undone by a pack page
   adding another body rule. */
body {
  background: #FAF6EC;
  color: #22301E;
}

/* The two pages that really are dark now say so themselves, instead of
   leaning on a leak. `min-height:100vh` so a short page still fills the
   screen with its own ground, which is what the body rule used to do. */
#page-letter-on-ai,
#page-admissions-schedule-a-tour {
  background: #22301E;
  color: #FAF6EC;
  min-height: 100vh;
}
