/* ============================================================================
   nanas.css — shared stylesheet for all six pages · "THE LONG DAY" grammar
   Tokens are the v5 set, machine-verified by ../contrast-check.js:
   text pairs and non-text objects, every one at or above WCAG AA.
   Do not edit a colour here without re-running the checker.

   ── THE VISUAL IDEA ─────────────────────────────────────────────────────────
   The day is the site. Every page runs top-to-bottom through one day:
   a full-bleed dawn sky behind the hero, the field as broad daylight, a
   dusk band (t-800), night (t-900), and deep night (t-950) with the stars
   out by the footer. `data-tod` on a .blk names the hour of the section;
   .skyband seams carry the sun and moon across the joins, full width,
   edge to edge. Nana's head (nanaMorph) runs down every page as a spine.

   Rules carried over from the homepage build, all load-bearing:
     · pink is a FILL on the field, never text — it measures 1.66:1 there
     · button rings are LIGHT, not dark — a dark ring cannot reach 3:1 on a
       dark ground (rgba(3,22,28,.55) over the field is 1.94:1)
     · the bloom alphas on body::after are measured; do not raise them
     · every canvas fills a POSITIONED, FIXED-SIZE wrapper. The one selector
       that guarantees it is the ".stage canvas" rule below — any new wrapper
       class joins that selector, never gets a parallel rule.
   ============================================================================ */

:root{
  --field:#106A7C; --field-hi:#12798C; --field-lo:#0F6474;
  --t-950:#03161C; --t-900:#052730; --t-800:#073744; --t-700:#0A4757; --t-600:#0D5A6D;
  --t-400:#1EC9CF; --t-300:#5FDDE1; --t-200:#8FE8EA; --t-100:#BFF2F3;
  --p-700:#8A0F4E; --p-600:#C4176B; --p-500:#FF2E93; --p-400:#FF5CA8;
  --p-300:#FF7CBE; --p-200:#FFB3D8;
  --y-500:#FFD23F; --y-300:#FFEAA3; --b-500:#4A90FF; --b-300:#8FB6FF;
  --cream:#FBF6EA; --on-field:#EFE9DC; --on-field-2:#E2ECE9;
  --on-dark:#E8E2D8; --on-dark-2:#A8BEBC; --on-dark-3:#7FA8AD;
  --on-pink:#2B0518; --on-teal:#03272A;

  --txt-2:var(--on-field); --txt-3:var(--on-field-2); --acc:var(--y-300);
  --edge:rgba(3,22,28,.30);

  --gut:clamp(18px,4.5vw,72px);
  --ease:cubic-bezier(.16,1,.3,1);
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,Helvetica,Arial,sans-serif;
  --serif:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}

*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;color:var(--txt-2);font-family:var(--sans);background:var(--field);
  -webkit-font-smoothing:antialiased;overflow-x:hidden}

/* the lit room. ALPHAS ARE LOAD-BEARING — the yellow blooms lift the ground
   and eat contrast; at .15 they broke eleven text pairs. See contrast-check.js */
body::after{content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(ellipse 60% 42% at 78% 2%,rgba(255,46,147,.20),transparent 62%),
    radial-gradient(ellipse 52% 34% at 12% 26%,rgba(255,210,63,.06),transparent 60%),
    radial-gradient(ellipse 58% 40% at 92% 66%,rgba(255,46,147,.14),transparent 62%),
    radial-gradient(ellipse 62% 40% at 8% 92%,rgba(255,210,63,.05),transparent 62%),
    linear-gradient(180deg,rgba(3,22,28,.28),transparent 22%,transparent 78%,rgba(3,22,28,.30))}

h1,h2,h3{margin:0;font-weight:800;letter-spacing:-.035em;line-height:1.05;color:var(--cream)}
p{margin:0;line-height:1.7;color:var(--txt-2)}
a{color:inherit}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* dark contexts remap the text ramp so pink text becomes available.
   dusk (t-800), night (t-900) and deep (t-950) are all dark grounds. */
.blk[data-tod=dusk],.blk[data-tod=night],.blk[data-tod=deep],
.foot,.panel,.card,.faq,.final,.loc,.gatebox,.topbar,.sitenav{
  --txt-2:var(--on-dark); --txt-3:var(--on-dark-2); --acc:var(--p-300);
  --edge:rgba(143,232,234,.16);
}

/* ============================================================================
   THE HELD CLAIM — every unverified fact on this site renders as one of these.

   Restyled from a builder's sticky note into the site's own mark: a small
   moon and the word PENDING, set in the ledger voice. The moon is the same
   moon the sky bands carry — a held claim is simply a fact that is still
   in the dark. The FILL STAYS DARK at exactly rgba(3,22,28,.32): an amber
   tint stacks with the yellow bloom and fails on the field, and the checker
   measures the label through this exact fill. Do not make it warm, do not
   thin it.
   ============================================================================ */
.todo{display:inline-flex;align-items:center;gap:9px;vertical-align:baseline;
  padding:3px 13px 4px;border-radius:100px;border:1px solid rgba(255,234,163,.34);
  background:rgba(3,22,28,.32);color:var(--y-300);
  font-family:var(--mono);font-size:.8em;font-weight:600;letter-spacing:.015em;
  font-style:normal;text-transform:none;line-height:1.5}
.todo::before{content:"\263E PENDING";content:"\263E PENDING" / "pending";flex:none;
  font-size:.74em;font-weight:800;letter-spacing:.14em;opacity:.85}
/* BLOCK VARIANT MUST NOT BE FLEX. The inline chip is inline-flex so the badge
   and a short label sit on one line, but a block hold contains real prose with
   <b> and <em> in it — under flex those become sibling flex ITEMS and the
   paragraph renders as two ragged columns. display:block keeps ::before inline
   in the text flow, which is what a badge in front of a paragraph wants. */
.todo.blk{display:block;padding:15px 18px 15px 20px;border-radius:14px;
  border:1px solid rgba(255,234,163,.26);border-left:3px solid var(--y-500);
  font-size:13px;line-height:1.7;margin:20px 0;max-width:62em}
.todo.blk::before{content:"\263E HELD — PENDING THE LICENCE";
  content:"\263E HELD — PENDING THE LICENCE" / "held, pending the licence";
  display:block;margin-bottom:7px;font-size:.72em}
.todo.blk b{color:#FFF3C4}   /* one step brighter than the chip body */

/* ============================================================================
   THE OPEN-NOW PILL — the other side of the same coin.

   Written 2026-08-24, when the hours gate opened. The colours are NOT a new
   decision: contrast-check.js has carried this exact pair since the pill was
   first designed ('.pill label' = t-200 on t-900, edge = rgba(30,201,207,.5))
   — there was simply no rule for it to attach to while the claim was held, so
   the header showed a .todo chip instead.

   Geometry deliberately mirrors .todo down to the padding and the radius: the
   header keeps ONE shape whether the fact is live or pending, and the only
   thing that changes is amber-and-a-moon becoming teal-and-a-lit-dot. Sitting
   on --t-950 rather than the t-900 the checker measures against, so every
   measured pair here can only gain.
   ============================================================================ */
.pill{display:inline-flex;align-items:center;gap:9px;vertical-align:baseline;
  padding:3px 13px 4px;border-radius:100px;
  border:1px solid rgba(30,201,207,.5);background:rgba(3,22,28,.32);
  color:var(--t-200);font-family:var(--mono);font-size:.8em;font-weight:700;
  letter-spacing:.015em;font-style:normal;text-transform:none;line-height:1.5}
/* the dot is the only thing that reports state, and it is not colour alone —
   an open pill is filled, a closed one is hollow, which survives both
   greyscale and the roughly one man in twelve who cannot separate the hues */
.pill::before{content:"\25CB";flex:none;font-size:.78em;opacity:.9}
.pill.on::before{content:"\25CF";color:var(--t-400)}

/* the standing banner every page carries while the site is embargoed —
   the ledger, set like the rest of the furniture rather than shouting */
.gatebox{position:relative;z-index:3;margin:0 var(--gut);background:var(--t-800);
  border:1px solid rgba(255,234,163,.22);border-left:3px solid var(--y-500);
  border-radius:0 16px 16px 0;padding:20px 24px 22px;overflow:hidden}
.gatebox::after{content:"\263E";position:absolute;right:14px;top:2px;
  font-size:64px;line-height:1;color:rgba(255,234,163,.08);pointer-events:none}
.gatebox h2{font-size:13px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--y-300);margin-bottom:9px;font-family:var(--mono)}
.gatebox p{font-size:13px;line-height:1.65;color:var(--on-dark)}
.gatebox p+p{margin-top:9px}
.gatebox code{font-family:var(--mono);font-size:12.5px;color:var(--t-200)}
.gatebox ul{margin:10px 0 0;padding-left:20px;font-size:13px;line-height:1.75;
  color:var(--on-dark);columns:2;column-gap:34px}
.gatebox li{break-inside:avoid}
.gatebox b{color:var(--y-300)}

/* ── status rows ─────────────────────────────────────────────────────────────
   The block used to be four undifferentiated paragraphs, which made a settled
   item and an outstanding one look identical. Each line now states which it is
   and shows it twice over: the word, and a filled vs hollow dot. Never colour
   alone — greyscale and the roughly one man in twelve who cannot separate hue
   both have to survive it. */
.gatebox .grow{display:grid;grid-template-columns:15px 1fr;gap:4px 11px;
  align-items:baseline;padding:11px 0 0;margin-top:11px;
  border-top:1px solid rgba(143,232,234,.13)}
.gatebox .grow::before{grid-row:1/3;font-size:12px;line-height:1.5}
.gatebox .grow.clear::before{content:"\25CF";color:var(--t-400)}
.gatebox .grow.open::before{content:"\25CB";color:var(--y-300)}
/* DIRECT CHILD, every one of them. The row title is a <b>, but so is half the
   emphasis inside the row's prose — a plain descendant selector put the mono
   uppercase treatment on "Glendale" and "85302" and appended "· outstanding"
   after each of them, mid-sentence. */
.gatebox .grow>b{font-size:12px;letter-spacing:.05em;font-family:var(--mono);
  text-transform:uppercase}
.gatebox .grow.clear>b{color:var(--t-200)}
.gatebox .grow.clear>b::after{content:" \00B7 settled";
  opacity:.62;font-weight:400;text-transform:none;letter-spacing:0}
.gatebox .grow.open>b::after{content:" \00B7 outstanding";
  opacity:.62;font-weight:400;text-transform:none;letter-spacing:0}
.gatebox .grow span{grid-column:2;font-size:13px;line-height:1.65;color:var(--on-dark)}
@media(max-width:760px){.gatebox ul{columns:1}}

/* ---------- buttons · LIGHT rings, see the header note ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;
  background:var(--p-500);color:var(--on-pink);font-weight:800;padding:14px 26px;
  border-radius:100px;text-decoration:none;font-size:15px;border:0;cursor:pointer;
  white-space:nowrap;box-shadow:0 0 0 2px rgba(255,179,216,.95),0 6px 18px rgba(3,22,28,.3);
  transition:transform .25s var(--ease),box-shadow .25s,background .25s}
.btn:hover{background:var(--p-400);transform:translateY(-2px)}
.btn:focus-visible{outline:3px solid var(--cream);outline-offset:3px}
.btn.ghost{background:var(--t-800);color:var(--cream);
  box-shadow:0 0 0 2px rgba(143,232,234,.88),0 6px 18px rgba(3,22,28,.28)}
.btn.ghost:hover{background:var(--t-700)}
.btn.tealb{background:var(--t-400);color:var(--on-teal);
  box-shadow:0 0 0 2px rgba(3,39,42,.5),0 6px 18px rgba(3,22,28,.28)}

/* ---------- top bar + nav ---------- */
.topbar{position:relative;z-index:5;display:flex;align-items:center;gap:14px;
  justify-content:space-between;padding:14px var(--gut);flex-wrap:wrap;
  background:var(--t-950)}
.wordmark{display:inline-flex;align-items:center;gap:11px;font-weight:800;font-size:16.5px;
  letter-spacing:-.02em;text-decoration:none;line-height:1.15;color:var(--cream)}
.wordmark em{font-style:normal;color:var(--p-300)}   /* pink text is safe on t-950 */
.topcall{display:inline-flex;align-items:center;gap:8px;font-weight:800;font-size:16px;
  text-decoration:none;font-variant-numeric:tabular-nums;color:var(--cream)}
.topcall:hover{color:var(--t-200)}
.sitenav{position:relative;z-index:5;display:flex;gap:4px;flex-wrap:wrap;
  padding:0 var(--gut) 12px;background:var(--t-950)}
.sitenav a{text-decoration:none;font-size:13.5px;font-weight:700;letter-spacing:.02em;
  padding:8px 14px;border-radius:100px;color:var(--on-dark-2);transition:background .25s}
.sitenav a:hover{background:var(--t-800);color:var(--cream)}
.sitenav a[aria-current=page]{background:var(--t-800);color:var(--cream);
  box-shadow:inset 0 0 0 1px rgba(143,232,234,.25)}
.sitenav a.draft{color:var(--y-300);border:1px dashed rgba(255,234,163,.45)}

/* ============================================================================
   SECTION GRAMMAR — the day arc.
   A .blk with no data-tod sits on the open field: daylight. dusk / night /
   deep step the ground down through the evening. The seams between them are
   .skyband elements, full-bleed, carrying the sun or the moon.
   ============================================================================ */
.blk{position:relative;z-index:2;padding:clamp(58px,9vh,110px) 0;overflow:hidden}
/* ── a film behind a whole section ───────────────────────────────────────────
   .68 is derived, not chosen. Worst case is a white frame: (1-.68) leaves 32%
   of the video through, which holds --on-field at 5.2:1 and cream at 5.9:1 —
   floors that no footage can undercut, because nothing is brighter than white.
   contrast-check.js measures this exact stack; thin it there and here or the
   check fails. The clip itself never goes near white (it is trimmed to a mean
   luma around 74), so this is headroom on top of headroom.
   Everything inside .blk already sits at z-index 2 or above; the two layers
   below are the only unpositioned children, hence the explicit z-index 0. */
.hasvid>.blkvid,.hasvid>.blkveil{position:absolute;inset:0;z-index:0;pointer-events:none}
.hasvid>.blkvid{overflow:hidden}
/* CONTAIN, not cover. A 16:9 frame inside a full-bleed band is roughly 5:1, so
   cover throws away the top and bottom of every frame — which is where this
   clip keeps its star and its horizon. contain shows the whole frame; the band
   is then given enough height for that frame to be worth looking at, and the
   left and right edges are faded out so the letterboxing reads as a vignette
   rather than as two black bars. */
.hasvid>.blkvid video{width:100%;height:100%;object-fit:contain;display:block;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 14%,#000 86%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 14%,#000 86%,transparent)}
.final.hasvid{min-height:min(46vw,540px);display:flex;flex-direction:column;
  justify-content:center}
.hasvid>.blkveil{background:rgba(3,22,28,.68)}
.hasvid>*:not(.blkvid):not(.blkveil){position:relative;z-index:1}
@media (prefers-reduced-motion:reduce){.hasvid>.blkvid{display:none}
  .hasvid>.blkveil{background:rgba(3,22,28,.30)}}
.blk[data-tod=dusk]{background:var(--t-800);color:var(--on-dark)}
.blk[data-tod=night]{background:var(--t-900);color:var(--on-dark)}
.blk[data-tod=deep]{background:var(--t-950);color:var(--on-dark)}
/* dusk keeps the last of the pink on its horizon — alpha at .09, well under
   the measured .20 bloom the checker already composites over dark grounds */
.blk[data-tod=dusk]::after{content:"";position:absolute;left:0;right:0;top:0;height:38%;
  pointer-events:none;z-index:0;
  background:radial-gradient(ellipse 90% 100% at 50% 0%,rgba(255,46,147,.09),transparent 70%)}
/* night and deep get the stars in the ground itself — pure gradients, cheap,
   there before a single canvas mounts. Decorative, alpha ≤ .30. */
.blk[data-tod=night]::after,.blk[data-tod=deep]::after,.final::after,.foot::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
  background-image:
    radial-gradient(1.3px 1.3px at 31px 42px,rgba(251,246,234,.26) 50%,transparent 51%),
    radial-gradient(1px 1px at 118px 156px,rgba(143,232,234,.22) 50%,transparent 51%),
    radial-gradient(1.5px 1.5px at 201px 74px,rgba(251,246,234,.17) 50%,transparent 51%),
    radial-gradient(1px 1px at 66px 214px,rgba(255,234,163,.15) 50%,transparent 51%),
    radial-gradient(1px 1px at 173px 251px,rgba(251,246,234,.13) 50%,transparent 51%);
  background-size:260px 280px}
.blk>*{position:relative;z-index:1}
.blk::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;z-index:1;
  background:linear-gradient(90deg,transparent,var(--acc) 30%,var(--acc) 70%,transparent);
  opacity:.5}
.bhead{padding:0 var(--gut);margin-bottom:clamp(28px,4.5vh,52px)}
.btag{font-size:11px;font-weight:800;letter-spacing:.3em;text-transform:uppercase;
  color:var(--txt-3)}
.btag b{color:var(--acc);margin-right:1em;font-variant-numeric:tabular-nums}
.bhead h2{font-size:clamp(28px,4.4vw,56px);margin-top:14px;max-width:18em}
.bhead .lede{margin-top:18px;font-size:clamp(15px,1.35vw,17.5px);max-width:40em}
.lede em,.sub em{font-family:var(--serif);font-style:italic;color:var(--acc)}
.wrapc{padding:0 var(--gut);max-width:74em}
.wrapc p+p{margin-top:16px}
.wrapc p{font-size:clamp(15px,1.35vw,17px)}

/* the hour numeral of a section — huge, outlined, half off the edge.
   Pure ornament: aria-hidden in markup, stroke at .09 alpha. */
.unum{position:absolute;top:4px;z-index:0;font-weight:800;pointer-events:none;
  user-select:none;font-size:clamp(120px,17vw,240px);line-height:.9;
  letter-spacing:-.05em;color:transparent;
  -webkit-text-stroke:1.5px rgba(251,246,234,.09)}
.unum.r{right:-10px}.unum.l{left:-10px}
@media(max-width:760px){.unum{font-size:96px;top:auto;bottom:0;opacity:.8}}

/* the spine — Nana's head becoming the hour's object, bled off the edge
   behind a section head. Decorative morph mounts only (data-quiet).

   THE MASK IS WHAT MAKES THE OPACITY SAFE. The spine box overlaps the first
   ~140px of the text column at desktop widths, so raising its opacity would
   put dots behind glyphs and quietly eat the measured text pairs (a cream
   dot at .18 effective over the field drops 15px body copy to ~3.6:1). The
   mask fades each spine to nothing before it reaches the copy, so the part
   a reader sees is the part hanging in the gutter — which is also where it
   looks best. Raise the opacity here freely; do NOT remove the mask. */
.spine{position:absolute;z-index:0;pointer-events:none;opacity:.30;
  top:clamp(8px,4vh,44px);
  width:clamp(240px,28vw,400px);height:clamp(240px,28vw,400px)}
.spine.l{left:clamp(-200px,-12vw,-80px);
  -webkit-mask-image:linear-gradient(to right,#000 0%,#000 34%,transparent 78%);
  mask-image:linear-gradient(to right,#000 0%,#000 34%,transparent 78%)}
.spine.r{right:clamp(-200px,-12vw,-80px);
  -webkit-mask-image:linear-gradient(to left,#000 0%,#000 34%,transparent 78%);
  mask-image:linear-gradient(to left,#000 0%,#000 34%,transparent 78%)}
@media(max-width:920px){.spine{display:none}}
@media(prefers-reduced-motion:reduce){.spine{display:none}}

/* ---------- the sky seams — full-bleed horizon bands ---------- */
.skyband{position:relative;z-index:2;overflow:hidden;
  height:clamp(160px,22vw,300px)}
.skyband.thin{height:clamp(120px,15vw,200px)}
/* a seam blends the ground it leaves into the ground it enters */
.skyband[data-sky=noon]{background:linear-gradient(180deg,var(--field-hi),var(--field))}
.skyband[data-sky=day]{background:var(--field)}
.skyband[data-sky=dusk]{background:linear-gradient(180deg,var(--field),var(--field-lo) 40%,var(--t-800))}
.skyband[data-sky=night]{background:linear-gradient(180deg,var(--t-800),var(--t-900))}
.skyband[data-sky=deep]{background:linear-gradient(180deg,var(--t-900),var(--t-950))}
.skyband[data-sky=dawn]{background:linear-gradient(180deg,var(--t-950),var(--t-800) 55%,var(--field))}
.skyband .bnote{position:absolute;left:var(--gut);bottom:12px;z-index:2;
  font-family:var(--mono);font-size:10.5px;font-weight:700;letter-spacing:.2em;
  text-transform:uppercase;color:var(--on-dark-2);
  background:rgba(3,22,28,.66);padding:6px 11px;border-radius:6px}
.skyband .bnote b{color:var(--y-300);font-weight:800}

/* ---------- reveal ---------- */
.rv{opacity:0;transform:translateY(22px);
  transition:opacity .8s var(--ease),transform .8s var(--ease)}
.rv.in{opacity:1;transform:none}

/* ============================================================================
   HERO — full-bleed sky. The skyline canvas covers the whole header; a veil
   only DARKENS the ground under the copy (light text over a darker ground
   can only gain contrast against the measured field pairs); the dial or the
   page's instrument floats in the right column inside its own dark stage.
   ============================================================================ */
.hero{position:relative;z-index:2;overflow:hidden;min-height:min(86svh,900px);
  padding:clamp(36px,6vh,72px) var(--gut) clamp(48px,8vh,88px);
  display:grid;grid-template-columns:minmax(0,6fr) minmax(320px,5fr);
  gap:clamp(26px,4vw,56px);align-items:center}
.hero.solo{grid-template-columns:1fr;min-height:min(66svh,720px)}
/* cap the COPY column only — .herosky and .veil are div children too, and
   capping them cut the solo heroes' sky off at 56em. Invisible while the
   sky was dots on a CSS band; glaring once the canvas paints its own wash. */
/* :not(.herovid) is load-bearing: the solo hero's 56em cap exists to keep TEXT
   columns readable, but the video layer was added after this rule and got
   caught by it — clamping the full-bleed film to a 896px box on wide screens.
   Every full-bleed layer must be excluded here, not just the first two. */
.hero.solo>div:not(.herosky):not(.veil):not(.herovid){max-width:56em}
.herosky{position:absolute;inset:0;z-index:0;pointer-events:none}
.hero .veil{position:absolute;inset:0;z-index:0;pointer-events:none;
  background:linear-gradient(104deg,rgba(3,22,28,.40) 0%,rgba(3,22,28,.16) 46%,transparent 70%),
             linear-gradient(180deg,transparent 60%,rgba(3,22,28,.22) 100%)}
.hero>*{position:relative;z-index:1}
.hero>.herosky,.hero>.veil{position:absolute;inset:0;z-index:0}

/* ============================================================================
   VIDEO HERO — index only, and the only moving image in the build.

   Three things are load-bearing here:

   1. .hasvideo .herosky goes to opacity 0 rather than display:none. The canvas
      must keep its BOX, because the page clock reads waypoint positions off
      laid-out elements; display:none would collapse it and bend the day arc.
   2. The veil is roughly doubled over the copy column. Every contrast pair in
      contrast-check.js assumes text on a dark, KNOWN ground; video brightness
      is not knowable, so the veil has to do the work the field used to.
   3. Under prefers-reduced-motion the video is removed outright and the
      skyline comes back — a looping video is exactly what that setting is for.
   ============================================================================ */
.hero.hasvideo>.herovid{position:absolute;inset:0;z-index:0;overflow:hidden}
.hero.hasvideo>.herovid video{width:100%;height:100%;object-fit:cover;display:block}
.hero.hasvideo>.herosky{opacity:0}
/* The veil now only sets MOOD, and deliberately does not thin out to the right.
   The first draft of it did — a 104deg wash going .82 → .28 — which reads well
   in a screenshot and is unsound: at narrow widths the body copy runs past the
   78% stop and lands on the thin end, where a bright video frame washes it out.
   A viewport-percentage gradient cannot protect text whose line length it does
   not know. So the veil got flat and the protection moved onto .heroL, which
   IS the text. */
.hero.hasvideo .veil{
  background:linear-gradient(180deg,rgba(3,22,28,.34) 0%,rgba(3,22,28,.30) 40%,rgba(3,22,28,.52) 100%)}

/* THE COPY SCRIM. Sits behind the hero column and nowhere else, so the video
   stays bright and open on the right where nothing is written.

   .52 is not a taste value, it is the answer to an inequality. Worst case is a
   pure-white video frame under the veil at its thinnest (.30): transmittance
   works out at (1-.52)x(1-.30) = .336, which puts cream at 5.9:1, --on-field at
   5.3:1 and y-300 at 5.3:1. White is the brightest frame that can exist, so
   those are floors for ANY footage, including footage nobody has shot yet.
   contrast-check.js measures this exact stack — change .52 there and here or
   the check fails, which is the point.

   The box bleeds 50vw left so it meets the screen edge no matter the gutter,
   and feathers out only in the 150px of overhang past the column, i.e. never
   under a glyph. inset's -46px top/bottom keeps ascenders and the focus ring
   inside the protected area. */
.hero.hasvideo .heroL::before{content:"";position:absolute;
  top:-46px;bottom:-46px;left:-50vw;right:-150px;z-index:0;pointer-events:none;
  background:linear-gradient(90deg,rgba(3,22,28,.52) 0%,
             rgba(3,22,28,.52) calc(100% - 150px),rgba(3,22,28,0) 100%)}
@media (prefers-reduced-motion:reduce){
  .hero.hasvideo>.herovid{display:none}
  .hero.hasvideo>.herosky{opacity:1}
  /* skyline is back, so the original measured veil comes back with it and the
     copy scrim goes away — over a known canvas it was never needed. */
  .hero.hasvideo .veil{
    background:linear-gradient(104deg,rgba(3,22,28,.40) 0%,rgba(3,22,28,.16) 46%,transparent 70%),
               linear-gradient(180deg,transparent 60%,rgba(3,22,28,.22) 100%)}
  .hero.hasvideo .heroL::before{display:none}
}
.eyebrow{display:flex;align-items:center;gap:12px;flex-wrap:wrap;font-size:11.5px;
  font-weight:700;letter-spacing:.22em;text-transform:uppercase;color:var(--on-field-2)}
h1{margin-top:22px}
.giant{display:block;font-size:clamp(40px,7vw,100px);line-height:.93;letter-spacing:-.045em}
/* no pink in this gradient — pink fails even large-text contrast on the field.
   The teal stop is t-100, not t-200: t-200 measures 4.07:1 here. */
.h1b{display:block;font-family:var(--serif);font-style:italic;font-weight:500;
  font-size:clamp(22px,3vw,40px);line-height:1.18;margin-top:.34em;letter-spacing:-.015em;
  background:linear-gradient(94deg,var(--cream) 0%,var(--y-300) 52%,var(--t-100) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.hero .sub{margin-top:22px;font-size:clamp(15px,1.4vw,18px);max-width:34em}
.cta{display:flex;gap:12px;margin-top:28px;flex-wrap:wrap}
@media(max-width:920px){.hero{grid-template-columns:1fr;min-height:0}}

/* ---------- hero: the quiet morph, bled off the left edge ----------
   A WRAPPER + canvas, not a bare canvas: an inline canvas takes its layout
   size from its own backing store, so the engine's ResizeObserver grows it
   every pass until the backing store fails and it paints white. The wrapper
   carries a fixed box and the canvas fills it absolutely — same contract as
   every other surface on the site (the .stage canvas rule below). */
.heroL{position:relative}
.heroL>*:not(.herofw){position:relative;z-index:1}
/* masked on the same principle as .spine — it fades out before the H1's
   left edge, so the visible part lives in the gutter and no hero text pair
   is measured through a dot */
.herofw{position:absolute;z-index:0;pointer-events:none;
  left:clamp(-200px,-13vw,-84px);top:52%;transform:translateY(-50%);
  width:clamp(230px,29vw,400px);height:clamp(230px,29vw,400px);
  opacity:.30;
  -webkit-mask-image:linear-gradient(to right,#000 0%,#000 36%,transparent 80%);
  mask-image:linear-gradient(to right,#000 0%,#000 36%,transparent 80%)}
/* Under 920px the grid collapses to one column and the burst would sit
   directly under the H1, so it goes rather than dimming further. Also
   hidden for reduced motion — the engine would still draw its one still
   frame, and a decorative layer has no business being that frame. */
@media(max-width:920px){.herofw{display:none}}
@media(prefers-reduced-motion:reduce){.herofw{display:none}}

/* ---------- canvas stages ---------- */
.stage{position:relative;border-radius:26px;overflow:hidden;
  border:1px solid rgba(143,232,234,.10);
  background:linear-gradient(180deg,var(--t-950),var(--t-900),#063039);
  box-shadow:0 24px 64px rgba(3,22,28,.40)}
/* a stage cut loose from the centre column: full-bleed, no chrome */
.stage.bleed{margin:0!important;border-radius:0;border-left:0;border-right:0;
  box-shadow:none}
/* the canvas fills its box ABSOLUTELY. This must cover every wrapper class —
   .stagebox, .herofw, .herosky, .spine, .skyband — an inline canvas
   re-measured by the engine's ResizeObserver would otherwise grow itself
   each pass until its backing store fails and it paints white. ONE selector,
   no parallel rules. */
.stage canvas,.stagebox canvas,.herofw canvas,.herosky canvas,.spine canvas,
.skyband canvas{display:block;width:100%;height:100%;position:absolute;inset:0}
.stagebox{position:relative;height:clamp(300px,34vw,420px)}
.stagebox.short{height:clamp(230px,26vw,300px)}
.stagebox.tall{height:clamp(340px,42vw,520px)}
/* the parade strip — wide and low, so a row of heads reads as a row */
.stagebox.strip{height:clamp(180px,21vw,270px)}
.stagefoot{position:relative;padding:12px 18px 16px;
  border-top:1px solid rgba(143,232,234,.12)}
.slider{display:block;padding:4px 4px 2px}
.slider input[type=range]{width:100%;height:30px;margin:0;accent-color:#FF2E93;cursor:pointer}
.slider input:focus-visible{outline:3px solid var(--t-300);outline-offset:3px;border-radius:100px}
.ticks{display:flex;justify-content:space-between;margin-top:2px;font-size:10.5px;
  font-weight:700;letter-spacing:.12em;color:var(--on-dark-2);text-transform:uppercase}
.legend{display:flex;justify-content:center;gap:20px;flex-wrap:wrap;margin-top:10px}
.legend span{display:inline-flex;align-items:center;gap:8px;font-size:12px;color:var(--on-dark-2)}
.legend i{width:9px;height:9px;border-radius:50%;flex:none}
.legend .lg-night{background:var(--t-300)}
.legend .lg-day{background:var(--y-500)}
.legend .lg-pend{background:transparent;border:1px dashed var(--y-300)}

/* ---------- generic panels + cards ---------- */
.panel{background:var(--t-800);border:1px solid rgba(3,22,28,.4);border-radius:22px;
  color:var(--on-dark);padding:clamp(22px,3vw,34px)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:0 var(--gut)}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;padding:0 var(--gut)}
@media(max-width:900px){.grid3{grid-template-columns:1fr 1fr}}
@media(max-width:820px){.grid2{grid-template-columns:1fr}}
@media(max-width:560px){.grid3{grid-template-columns:1fr}}

.card{background:var(--t-800);border:1px solid rgba(3,22,28,.4);border-radius:20px;
  padding:24px 22px 26px;border-top:3px solid var(--pc,var(--t-400));
  color:var(--on-dark);box-shadow:0 10px 30px rgba(3,22,28,.25)}
/* --pc is the FILL (3:1 as a rule); --pct is the same accent as 11px TEXT
   (4.5:1). #FF2E93 is 3.70:1 and #4A90FF is 4.10:1 as labels — hence the split. */
.card.c-y{--pc:var(--y-500);--pct:var(--y-500)}
.card.c-t{--pc:var(--t-400);--pct:var(--t-400)}
.card.c-p{--pc:var(--p-500);--pct:var(--p-300)}
.card.c-b{--pc:var(--b-500);--pct:var(--b-300)}
/* ============================================================================
   PHOTOGRAPHS. Real frames of the real buildings, full frame, signage and all.
   The wall signs — 24/7, OVERNIGHT CHILD CARE, SAT. SUN. DROP IN — are the
   centre's own and they say what the centre does; they are the point of the
   photograph, not noise in it.
   Sized with width/height so the grid does not jump while they load.
   ============================================================================ */
.shot{margin:16px 0 0;border-radius:14px;overflow:hidden;position:relative;
  border:1px solid var(--edge);background:var(--t-950)}
/* height:auto is load-bearing. The <img> carries width/height ATTRIBUTES so the
   grid reserves space before the file lands; those attributes map to a used
   height, and aspect-ratio only applies when height computes to auto. Without
   this the photo renders at its full natural height — a 1067px image in a
   326px column. */
.shot img{display:block;width:100%;height:auto;aspect-ratio:3/2;object-fit:cover;
  object-position:50% 30%}
.shot.vid video{display:block;width:100%;height:auto;aspect-ratio:16/9;background:#000}
.shot figcaption{padding:9px 13px 11px;font-size:12px;line-height:1.5;
  color:var(--txt-3);background:var(--t-950)}
/* ── illustrations ───────────────────────────────────────────────────────────
   Drawn artwork, not photographs of the buildings. Kept visually distinct from
   .shot on purpose — flatter frame, no hard border — so a reader never has to
   wonder whether they are looking at a picture of the actual room. Anything
   that IS the actual building uses .shot and says where it was taken. */
/* Accents, not billboards. The first pass let these run the full column width,
   which put a whole viewport of illustration between a heading and its content
   — nothing on a childcare page earns that. Capped tight; inside a .panel the
   panel's own width already constrains them. */
.art{margin:18px 0 0;border-radius:14px;overflow:hidden;position:relative;
  background:var(--t-950);max-width:400px}
.panel .art{max-width:none}
.art img{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover}
.art.tall img{aspect-ratio:3/2}
.art figcaption{padding:9px 2px 0;font-size:12px;line-height:1.5;color:var(--txt-3)}

/* ── folds ───────────────────────────────────────────────────────────────────
   The old site's page copy, carried over verbatim-ish and tucked behind a
   disclosure so it keeps its search value without burying the page. Native
   <details> — indexed by crawlers, zero JS, cannot trap focus. */
.fold{margin:16px 0 0;border:1px solid var(--edge);border-radius:14px;
  background:rgba(3,22,28,.24);overflow:hidden}
.fold summary{cursor:pointer;padding:13px 16px;font-weight:700;font-size:14px;
  color:var(--t-200);list-style:none;display:flex;align-items:center;gap:10px}
.fold summary::before{content:"\25B8";font-size:11px;transition:transform .25s var(--ease)}
.fold[open] summary::before{transform:rotate(90deg)}
.fold summary::-webkit-details-marker{display:none}
.fold>p{padding:0 18px;font-size:13.5px;line-height:1.7}
.fold>p:last-child{padding-bottom:16px}
.fold+.fold{margin-top:10px}

/* ── two small photos inside a text panel — the dead-space killer ─────────── */
.panelpics{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:16px}
.panelpics img{display:block;width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;
  object-position:50% 25%;
  border-radius:12px;border:1px solid var(--edge);
  transition:transform .45s var(--ease)}
.panelpics img:hover{transform:scale(1.03)}

/* ── a 16:9 video embed that cannot break the column ─────────────────────── */
.ytv{position:relative;aspect-ratio:16/9;border-radius:14px;overflow:hidden;
  background:var(--t-950);margin-top:14px}
.ytv iframe{position:absolute;inset:0;width:100%;height:100%;border:0}

/* ── the film strip ──────────────────────────────────────────────────────────
   One row of real photographs, scrolled sideways. Height-capped so it costs a
   card of vertical space, not a viewport; snap so a flick lands on a photo. */
.pstrip{display:flex;gap:12px;overflow-x:auto;padding:6px var(--gut) 16px;
  scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;
  scrollbar-width:thin;scrollbar-color:var(--t-600) transparent}
.pstrip img{height:200px;width:auto;flex:none;border-radius:14px;
  scroll-snap-align:start;border:1px solid var(--edge);
  transition:transform .35s var(--ease)}
.pstrip img:hover{transform:translateY(-4px)}
@media(max-width:560px){.pstrip img{height:150px}}

/* a small lift on hover, everywhere a photograph sits */
.shot img,.gcell img{transition:transform .45s var(--ease)}
.shot:hover img,.gcell:hover img{transform:scale(1.03)}
.shot,.gcell{isolation:isolate}

/* ── gallery grid ────────────────────────────────────────────────────────────
   Reuses .shot's frame so a photograph looks the same wherever it appears.
   auto-fit + minmax means the column count follows the viewport instead of
   breakpoints, and every cell keeps 3:2 so the rows stay level regardless of
   what the originals were shot at. */
.gal{display:grid;grid-template-columns:repeat(auto-fit,minmax(268px,1fr));
  gap:14px;padding:0 var(--gut)}
.gcell{margin:0;border-radius:16px;overflow:hidden;position:relative;
  border:1px solid var(--edge);background:var(--t-950)}
/* object-position biases the crop toward the top third: these are photos of
   children, and when a portrait frame is cropped to a landscape cell the
   default centre-crop takes the face off. Faces live in the upper part of
   nearly every shot, so the crop follows them. */
.gcell img{display:block;width:100%;height:auto;aspect-ratio:3/2;object-fit:cover;
  object-position:50% 25%}
.gcell figcaption{padding:10px 14px 12px;font-size:12.5px;line-height:1.55;
  color:var(--txt-3);background:var(--t-950)}
.card .kicker{font-size:11px;font-weight:800;letter-spacing:.2em;text-transform:uppercase;
  color:var(--pct,var(--t-400))}
.card h3{font-size:19px;margin:12px 0 8px}
.card p{font-size:13.5px;line-height:1.65;color:var(--on-dark)}
.card .stagebox,.panel .stagebox{position:relative;margin-top:16px;border-radius:16px;
  overflow:hidden;background:linear-gradient(180deg,var(--t-900),#04212A)}

/* ---------- locations ---------- */
.loc{background:var(--t-800);border:1px solid rgba(3,22,28,.4);border-radius:22px;
  padding:clamp(22px,3vw,34px);border-top:3px solid var(--lc,var(--p-500));
  color:var(--on-dark)}
.loc.a{--lc:var(--p-500);--lct:var(--p-300)}
.loc.b{--lc:var(--t-400);--lct:var(--t-400)}
.loc .locname{font-size:11px;font-weight:800;letter-spacing:.24em;text-transform:uppercase;
  color:var(--lct,var(--p-300))}
.loc h3{font-size:clamp(19px,2.2vw,25px);margin-top:10px}
.loc .addr{margin-top:12px;font-size:15px;line-height:1.65;color:var(--on-dark);
  font-style:normal}
.loc .lic{margin-top:12px;font-size:12px;color:var(--on-dark-2);letter-spacing:.03em}
.locrow{display:flex;gap:10px;margin-top:18px;flex-wrap:wrap}

/* ---------- the rate calculator window — the lit window at noon ---------- */
.calcwrap{position:relative;z-index:2;max-width:980px;margin:30px auto 0;
  padding:clamp(18px,3vw,36px);background:var(--cream);color:#14232B;border-radius:24px;
  box-shadow:0 0 0 1px rgba(255,46,147,.45),0 0 60px rgba(255,210,63,.18),
    0 26px 70px rgba(3,22,28,.45)}
.calcwrap a{color:#B21463}
.calcwrap h3{color:#14232B;font-size:17px;margin:0 0 4px}
.calcwrap .fine{font-size:11.5px;color:#5C6B72;margin:6px 0 0}
.calcrow{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px}
.calcwrap select{font-family:inherit;font-size:14px;font-weight:600;padding:10px 12px;
  border-radius:9px;border:1px solid #C9D3D6;background:#fff;color:#14232B;cursor:pointer}
.calcwrap select:focus-visible{outline:3px solid #B21463;outline-offset:2px}
#npc-weekly-total{margin-top:16px;padding-top:14px;border-top:1px solid #DDE4E6;
  display:flex;justify-content:space-between;align-items:baseline;font-size:14.5px}
#npc-weekly-total strong{font-size:21px;letter-spacing:-.02em}
@media(max-width:720px){.calcwrap{margin-left:10px;margin-right:10px;border-radius:16px}}

/* ---------- faq ---------- */
.faq{background:var(--t-800);border:1px solid rgba(3,22,28,.4);border-radius:22px;
  margin:0 var(--gut);overflow:hidden;color:var(--on-dark)}
.q{border-bottom:1px solid rgba(143,232,234,.14)}
.q:last-child{border-bottom:0}
.q button{width:100%;background:none;border:0;color:var(--cream);font-family:inherit;
  font-size:clamp(15.5px,1.5vw,18px);font-weight:700;letter-spacing:-.015em;text-align:left;
  padding:22px 58px 22px 26px;cursor:pointer;position:relative}
.q button:hover{background:var(--t-700)}
.q button:focus-visible{outline:3px solid var(--t-300);outline-offset:-3px;border-radius:6px}
.q button::after{content:"";position:absolute;right:24px;top:50%;width:11px;height:11px;
  border-right:2px solid var(--on-dark-2);border-bottom:2px solid var(--on-dark-2);
  transform:translateY(-70%) rotate(45deg);transition:transform .3s var(--ease)}
.q.open button::after{transform:translateY(-30%) rotate(-135deg);border-color:var(--p-300)}
.q .a{max-height:0;overflow:hidden;transition:max-height .45s var(--ease)}
.q .a p{padding:0 26px 24px;font-size:14.5px;max-width:58em;color:var(--on-dark)}

/* ---------- final + footer — deep night, stars out ---------- */
.final{position:relative;text-align:center;padding:clamp(80px,12vh,140px) var(--gut);
  background:var(--t-950);color:var(--on-dark);overflow:hidden}
.final>*{position:relative;z-index:1}
.final::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;z-index:1;
  background:linear-gradient(90deg,transparent,var(--t-400) 30%,var(--p-500) 70%,transparent)}
.final h2{font-size:clamp(30px,4.2vw,54px)}
.final p{margin:18px auto 28px;max-width:36em;font-size:clamp(15px,1.4vw,17px)}
.final .cta{justify-content:center}
.foot{padding:40px var(--gut) 90px;position:relative;z-index:2;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:26px;
  background:var(--t-950);color:var(--on-dark-2);overflow:hidden}
.foot>*{position:relative;z-index:1}
.foot div{font-size:13px;color:var(--on-dark-2);line-height:1.85;font-style:normal}
.foot b{color:var(--cream);display:block;margin-bottom:4px}
.foot a{text-decoration:none}
.foot a:hover{color:var(--t-200)}

@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *{animation:none!important;transition:none!important}
  .rv{opacity:1;transform:none}
}
