/*
Theme Name: The Wonder
Theme URI: https://thewonder.fun
Author: The Wonder
Description: Custom block theme for The Wonder — an indoor family play club with
locations in Battery Park NY, Westport CT and the Upper West Side. Black-and-white
architecture; the 2px rule is the structural system.
Requires at least: 6.7
Tested up to: 7.1
Requires PHP: 8.1
Version: 0.1.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: wonder
Tags: full-site-editing, block-patterns, editor-style
*/

/*
   Almost everything lives in theme.json. Put CSS here only when a token or a
   block style genuinely cannot express it. Every rule added here is a rule
   somebody has to find later.
*/

/* ─── Rule zero ──────────────────────────────────────────────────────────
   Black on white on every device, whatever the system theme says. This is
   the identity, not a contrast preference: inverted, the 2px architecture
   stops reading as architecture and it becomes a different company. Two
   mocks shipped inverted before this was caught.
   Do not add prefers-color-scheme. Do not add a toggle.                   */
:root { color-scheme: light; }
html, body { background: #fff; color: #000; }

/* ─── Typography, declared HERE and not in theme.json ────────────────────
   WORDPRESS.COM REPLACES `settings.typography.fontFamilies` WHOLESALE.
   Proved on staging 24 Sep: the global styles came back carrying
   --wp--preset--font-family--alegreya, --arvo, --cabin, --chivo,
   --commissioner — WordPress.com's own curated list — and OUR display, body
   and hand were not overridden but absent. The `fontFace` declarations went
   with them, so there was no @font-face on the page and not one request for
   a woff2. Every heading and every line of body copy fell back to Times, and
   with the wrong faces at the wrong metrics all the spacing drifted too.

   Font SIZES and colours survived untouched — it is only the families.

   So the faces and the stacks live in this stylesheet, which no host
   rewrites. theme.json still names the same three families, with literal
   stacks rather than var() references, so the editor and the front end agree
   and neither depends on a preset that may not be there. Self-hosting the
   fonts to avoid a third party, and then relying on a third party to declare
   them, was never going to hold.

   Studio could not have shown this. Studio is plain WordPress. */
@font-face { font-family: 'Playfair Display'; font-style: normal; font-weight: 700; font-display: swap;
	src: url('assets/fonts/playfair-display-latin-700-normal.woff2') format('woff2'); }
@font-face { font-family: 'Playfair Display'; font-style: italic; font-weight: 700; font-display: swap;
	src: url('assets/fonts/playfair-display-latin-700-italic.woff2') format('woff2'); }
@font-face { font-family: 'Playfair Display'; font-style: normal; font-weight: 900; font-display: swap;
	src: url('assets/fonts/playfair-display-latin-900-normal.woff2') format('woff2'); }
@font-face { font-family: 'Playfair Display'; font-style: italic; font-weight: 900; font-display: swap;
	src: url('assets/fonts/playfair-display-latin-900-italic.woff2') format('woff2'); }
@font-face { font-family: 'Caveat'; font-style: normal; font-weight: 400; font-display: swap;
	src: url('assets/fonts/caveat-latin-400-normal.woff2') format('woff2'); }
@font-face { font-family: 'Caveat'; font-style: normal; font-weight: 600; font-display: swap;
	src: url('assets/fonts/caveat-latin-600-normal.woff2') format('woff2'); }
@font-face { font-family: 'Caveat'; font-style: normal; font-weight: 700; font-display: swap;
	src: url('assets/fonts/caveat-latin-700-normal.woff2') format('woff2'); }

:root {
	--wonder-display: 'Playfair Display', Georgia, 'Times New Roman', serif;
	--wonder-body: 'Helvetica Neue', Helvetica, Arial, sans-serif;
	--wonder-hand: Caveat, 'Bradley Hand', cursive;
}

/* Belt and braces: theme.json sets these too, but if its typography is ever
   stripped the way its families were, the site still reads correctly. */
body { font-family: var(--wonder-body); }
h1, h2, h3, h4, h5, h6 { font-family: var(--wonder-body); }

/* ─── Topbar ─────────────────────────────────────────────────────────────
   Left-anchored: the nav sits beside the logo and the right-hand group is
   pushed out with margin-left:auto. With space-between the nav floats into
   the middle of a wide screen and stops reading as one group with the logo. */
/* THE TOPBAR IS FULL-BLEED AND IT STICKS. Joey, 23 Sep, and the mock all
   along: `position:sticky; top:0; padding:14px 32px`, edge to edge.

   Ours was a `constrained` group, so the whole bar lived inside the 1200px
   content width and floated in the middle of a wide window with the mark
   nowhere near the left edge. The layout now comes from here rather than from
   block attributes, which is the only way to get the mock's exact numbers.

   z-index 50 so the bar passes over the hero video and the checkout drawer's
   scrim still covers it — the drawer sits at 100. */
/* STICKY BELONGS ON THE TEMPLATE PART, NOT ON THE BAR INSIDE IT.
   `position: sticky` travels only within its containing block, and WordPress
   wraps a template part in its own `<header class="wp-block-template-part">`
   — which is exactly as tall as the bar and holds nothing else. So the bar was
   sticky inside a 70px box with nowhere to go, and scrolled away with it. The
   declaration was right and structurally inert for weeks, which is why nobody
   caught it by reading the CSS.

   Joey, 25 Sep, after launch: "I want the nav bar at the top to be a static
   bar that is always visible even as you scroll." The mock says the same —
   its own deck script pushes itself below "the site header, sticky at top:0". */
.wp-site-blocks > header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: 50;
}

.wonder-topbar {
	border-bottom: 2px solid var(--k);
	/* theme.json's root padding lands on every top-level block, which put
	   35.6px down each side of the bar before its own padding started — so
	   the mark sat 68px in rather than 32. The gutters belong to the row. */
	padding: 0;
}
.wonder-topbar-inner {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 18px 34px;
	padding: 14px 32px;
}
.wonder-topbar .wp-block-navigation { flex: 0 1 auto; }
/* `margin-left:auto` is what throws the picker and the portal button to the
   right edge. It was an inline style on the block; here it survives an editor
   touching that group.

   Two class names deep on purpose. WordPress ships
   `.is-layout-flex > :is(*, div) { margin: 0 }`, and `:is()` takes the
   specificity of its heaviest argument — so that rule scores (0,1,1) and beat
   a single `.wonder-topbar-right` at (0,1,0). The button sat mid-bar with the
   auto margin silently overruled. */
.wonder-topbar .wonder-topbar-right { margin-left: auto; }
.wonder-topbar .wp-block-site-logo img { height: 40px; width: auto; }
.wonder-topbar .wonder-nav { font-size: 12px; }
.wonder-topbar .wonder-nav a { text-decoration: none; }
.wonder-topbar .wonder-nav a:hover,
.wonder-topbar .wonder-nav a[aria-current] { text-decoration: underline; text-underline-offset: 4px; }

/* NOTHING BETWEEN THE BAR AND THE HERO. theme.json sets a global blockGap,
   which WordPress turns into `margin-block-start` on every child of
   `.wp-site-blocks` — so the header and the page it sits on were 16px apart
   and the video started below a white stripe. The bands are meant to touch. */
.wp-site-blocks > * { margin-block-start: 0; }

@media (max-width: 900px) {
	.wonder-topbar-inner { padding: 12px 18px; gap: 14px 20px; }
}

/* The Member Portal button is INERT until the portal is live (decided
   21 Sep — it will not be ready for launch). It is a paragraph, not a link,
   so there is nothing to click and nothing to 404. When the portal ships,
   this becomes an anchor to https://portal.thewonder.fun in the SAME tab —
   a new tab is what makes it feel like leaving the site.

   IT SAYS "MEMBER PORTAL" AND NOTHING ELSE UNTIL YOU HOVER IT. Joey, 23 Sep.
   The button used to carry a permanent " · soon", which made the label read
   as a caveat in every screenshot of every page. Now the veil does that job
   only when someone reaches for it.

   ::after rather than a second element, because the button is stamped into
   the header of every page on the site and none of them should need editing
   to carry this.

   The label goes transparent underneath. Without that, MEMBER PORTAL shows
   through the half-opaque veil and collides with SOON — both are centred, so
   they land on top of each other. The ::after sets its own colour, so it is
   unaffected; and this is why the rule is not `opacity: .75` on the button,
   which would fade the veil's own text along with everything else. */
.wonder-portal-soon {
	position: relative;
	overflow: hidden;
	border: 2px solid #000;
	/* The mock's metrics. At 11px/18px the button was 44px tall and made the
	   whole bar 112 instead of 70. */
	padding: 8px 16px;
	font-size: 10.5px;
	line-height: 1.2;
	font-weight: 900;
	letter-spacing: .08em;
	text-transform: uppercase;
	cursor: default;
	white-space: nowrap;
}
.wonder-portal-soon::after {
	content: "Soon";
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(0, 0, 0, .5);
	color: var(--w);
	opacity: 0;
	transition: opacity .16s ease;
}
.wonder-portal-soon:hover { color: transparent; }
.wonder-portal-soon:hover::after { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
	.wonder-portal-soon::after { transition: none; }
}
/* TOUCH GETS THE WORDS BACK. Joey, 23 Sep.

   A phone has no hover, so there is nothing to reveal — which would leave a
   button that looks live and does nothing. The mock accepted that; we do not.
   Here the same ::after stops being a veil and becomes the inline " · Soon"
   the button used to carry all the time, so the caveat is visible exactly
   where it cannot be discovered any other way.

   `:hover` is reset too, because a touch browser can still fire it on tap and
   would otherwise turn the label transparent with no veil to replace it —
   leaving an empty box. */
@media (hover: none) {
	.wonder-portal-soon::after {
		content: " · Soon";
		position: static;
		display: inline;
		background: none;
		color: inherit;
		font-weight: 700;
		opacity: .45;
	}
	.wonder-portal-soon:hover { color: inherit; }
	.wonder-portal-soon:hover::after { opacity: .45; }
}

/* ─── Footer ─────────────────────────────────────────────────────────── */
/* ─── The sign-off, and the footer under it ──────────────────────────────
   THE WORDMARK INTERRUPTS THE RULE — it does not sit above one. The mock's
   `.logo-tick` is a flex row whose ::before and ::after ARE the two rules,
   each taking half the leftover space, so the line stops at the mark and
   starts again after it. We had built the logo and the rule as two separate
   things: a centred mark, then an unbroken 2px border below it. Close
   enough to look deliberate, and not the drawing. (Joey, 24 Sep.)

   1.5px, not 2px — this one rule is deliberately lighter than the site's
   structural 2px, because it is a sign-off rather than architecture. */
.wonder-logo-tick {
	display: flex;
	align-items: center;
	gap: 24px;
	/* 10px, not the mock's 18. Joey, 25 Sep: "the whole footer row with the
	   links and icons can be higher up (not so much space below the wonder
	   logo footer)." The other two thirds of that gap were the footer's own
	   top padding and a margin nobody wrote — see below. */
	padding: 44px 32px 10px;
}

.wonder-logo-tick::before,
.wonder-logo-tick::after {
	content: '';
	flex: 1;
	border-top: 1.5px solid var(--k);
}

.wonder-logo-tick .wp-block-site-logo { margin: 0; }
.wonder-logo-tick .wp-block-site-logo img { height: 46px; width: auto; display: block; }

/* THE LINKS ARE CENTRED. Joey, 24 Sep — and the mock agrees: three columns,
   `1fr auto 1fr`, with the copyright left, the nav in the middle and the
   social icons hard right. Ours was a flex row set to space-between, which
   put the links on the left and bundled the copyright in with the icons. */
.wonder-footer .wonder-fgrid {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 14px 24px;
}

.wonder-footer .wonder-fcopy { grid-column: 1; justify-self: start; }
/* `margin: 0` because WordPress's navigation block brings its own 16px and
   nothing in the mock or this file ever asked for it. Same species as the
   weekly schedule's h2: a default that arrives quietly and is only visible as
   "too much space". It pushed the whole centred row down, because the grid
   centres its items against the tallest one. */
.wonder-footer .wonder-fnav  { grid-column: 2; justify-self: center; margin: 0; }
.wonder-footer .wonder-fright { grid-column: 3; justify-self: end; }

.wonder-footer .wp-block-navigation__container { row-gap: 10px; justify-content: center; }

/* The mock's icons are bordered squares that fill with Signal on hover, not
   bare glyphs. */
.wonder-footer .wp-block-social-link { margin: 0; }
.wonder-footer .wp-block-social-link a {
	border: 2px solid var(--k);
	padding: 6px;
	line-height: 0;
}
/* THE FILL IS THE HOVER STATE. THE SIZE IS NOT.
   Core ships `transition: transform .1s` on `.wp-block-social-link` and scales
   it on hover, so our bordered square grew about 10% under the pointer and the
   bottom of its 2px border was clipped by the row. Joey, 25 Sep: "I don't want
   to lose the bottom of that black border." Both properties are turned off
   rather than just the hover, so nothing animates on the way out either. */
/* THE HOVER RULE HAS TO RESTATE THE BORDER, and the reason is worth keeping.
   Core ships one grouped rule:

     .wp-block-social-links .wp-social-link a,
     .wp-block-social-links .wp-social-link a:hover { border-bottom: 0; }

   Two selectors of DIFFERENT weight in one rule. At rest theirs is (0,2,1),
   which ties our `.wonder-footer .wp-block-social-link a` and loses on order,
   so the square keeps all four sides. On hover theirs becomes (0,3,1) and
   there is no hover declaration of ours for it to tie with — our border lives
   in the rest-state rule, which theirs now outranks. So the bottom edge, and
   only the bottom edge, vanished under the pointer.

   A hover rule can lose a property it never mentions. Stating the border here
   gives it a (0,3,1) declaration to win with. */
.wonder-footer .wp-block-social-link a:hover {
	background: var(--signal);
	border: 2px solid var(--k);
}
.wonder-footer .wp-block-social-link,
.wonder-footer .wp-block-social-link:hover,
.wonder-footer .wp-block-social-link a,
.wonder-footer .wp-block-social-link a:hover {
	transform: none;
	transition: none;
}

/* One column on a phone, everything centred, and the copyright LAST —
   a legal line is the least of what somebody scrolled down here for. */
@media (max-width: 760px) {
	.wonder-logo-tick { padding: 34px 18px 14px; gap: 16px; }

	.wonder-footer .wonder-fgrid {
		grid-template-columns: 1fr;
		justify-items: center;
		text-align: center;
	}

	.wonder-footer .wonder-fcopy,
	.wonder-footer .wonder-fnav,
	.wonder-footer .wonder-fright {
		grid-column: 1;
		justify-self: center;
	}

	.wonder-footer .wonder-fcopy { order: 3; }
}

/* ─── Display face ───────────────────────────────────────────────────────
   Headings are SANS everywhere (decided 9 Sep). Playfair belongs to Our
   Story alone, so it is opt-in per heading rather than a default — the
   scaffold had it as the default and would have put it on all 23 pages. */
.is-style-wonder-display {
	font-family: var(--wonder-display);
	line-height: .92;
}

/* ── Location picker ──────────────────────────────────────────────────────
   One component, two faces. .is-gate is the bordered band on a hub page;
   .is-bar is the compact switcher in the topbar. WHERE it sits is an
   attribute on the block, not something derived from whether a location is
   chosen — those are different questions, and conflating them put the full
   gate, heading and all, inside the topbar. .is-chosen is the separate
   state, set from the URL. */

.wonder-picker__list {
	display: flex;
	flex-wrap: wrap;
	gap: 0;
	list-style: none;
	margin: 0;
	padding: 0;
}

.wonder-picker__heading {
	margin: 0 0 12px;
	font-weight: 900;
	letter-spacing: -0.01em;
}

.wonder-picker__link {
	display: block;
	padding: 10px 18px;
	border: 2px solid var(--wp--preset--color--ink);
	font-weight: 900;
	text-decoration: none;
	color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--paper);
}

/* The 2px rule is the structural device, so adjacent buttons share one edge
   rather than sitting 4px apart pretending to be a single control. */
.wonder-picker__item + .wonder-picker__item .wonder-picker__link {
	border-left-width: 0;
}

.wonder-picker__link:hover,
.wonder-picker__link:focus-visible {
	background: var(--wp--preset--color--signal);
}

/* YOUR LOCATION LOOKS THE SAME WHEREVER IT IS SAID. Joey, 24 Sep: "I want
   them to match... I'd rather it match the other page where it's Black
   background."

   These were two treatments on purpose — black for "you are on this
   location's page", a yellow underbar for "this is only your remembered
   preference" — and the distinction did not survive contact with anybody
   using the site. The same row, in the same menu, changed appearance
   depending on which page you opened it from, which reads as a bug however
   carefully it was reasoned. One marker now. */
.wonder-picker__link[aria-current="true"],
.wonder-picker__link[data-preferred="true"] {
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
}

.wonder-picker__note {
	display: block;
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
}

.wonder-picker.is-gate {
	border: 2px solid var(--wp--preset--color--ink);
	padding: 28px;
	text-align: center;
}

/* Once a location is chosen the band is a switcher, not a question, so it
   loses its heading and tightens up. The inverted button carries the answer. */
.wonder-picker.is-gate.is-chosen {
	padding: 18px;
}

.wonder-picker.is-gate .wonder-picker__list {
	justify-content: center;
}

.wonder-picker.is-gate .wonder-picker__heading {
	font-size: clamp(20px, 2.6vw, 30px);
}

/* The topbar face. No heading — the three buttons are the question, and a
   second "Which Wonder are you visiting?" above the page's own gate asks it
   twice. Small enough to sit beside the Member Portal button. */
.wonder-picker.is-bar .wonder-picker__link {
	padding: 8px 12px;
	font-size: 10.5px;
	line-height: 1.2;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

.wonder-picker.is-bar .wonder-picker__note {
	display: none;
}

@media (max-width: 600px) {
	.wonder-picker.is-gate .wonder-picker__list { flex-direction: column; }
	.wonder-picker.is-gate .wonder-picker__item + .wonder-picker__item .wonder-picker__link {
		border-left-width: 2px;
		border-top-width: 0;
	}
	.wonder-picker.is-bar .wonder-picker__list { flex-wrap: wrap; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   THE RESET THE MOCKS OPEN WITH

   Every mock begins `*{margin:0;padding:0;box-sizing:border-box}` and this was
   never ported, which turned out not to be cosmetic: without border-box a
   `width: 100%` box carrying 16px of padding measures 100% PLUS 32px, so it is
   wider than the thing containing it. On the home page that made every card's
   photo frame overhang its own card by exactly its padding.

   MARGIN AND PADDING GO TO ZERO TOO, and leaving them out was a mistake that
   took until 23 Sep to find.

   The note that used to sit here said a blanket zero "would silently flatten
   anything relying on the browser's defaults". Nothing relies on them: every
   rule in this file was ported from a mock that opens with
   `*{margin:0;padding:0;box-sizing:border-box}`, so each one was written
   against a zeroed baseline and each one sets the spacing it wants.

   What actually happened was the opposite. `.eyebrow` sets `margin-bottom:14px`
   and the mock puts 14px between it and the headline. On our Home page that
   gap was 37px, because the `<h2>` underneath still carried the browser's own
   `margin: 0.83em 0` — 36.5px at 44px type — and the larger of the two won.
   The same 36.5px then appeared again below the headline, where the mock has
   none at all. Every heading, paragraph, list and figure on every page we
   built was carrying a margin nobody asked for, and the symptom reads as
   "the padding is off everywhere", which is exactly how Joey described it.

   Scoped to the blocks. WordPress's own markup — the header, the footer, the
   editor — is not ours to reset.
   ═══════════════════════════════════════════════════════════════════════════ */

.wonder-catalogue, .wonder-catalogue *,
.wonder-camps, .wonder-camps *,
.wonder-birthdays, .wonder-birthdays *,
.wonder-theme, .wonder-theme *,
.wonder-membership, .wonder-membership *,
.wonder-faqs, .wonder-faqs *,
.wonder-home, .wonder-home *,
.wonder-locpanel, .wonder-locpanel *,
.wonder-schedule, .wonder-schedule *,
.wonder-gifts, .wonder-gifts *,
.wonder-story, .wonder-story *,
.wonder-careers, .wonder-careers *,
.wonder-legal, .wonder-legal * {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}

/* `hidden` has to actually hide. The browser's own `[hidden]{display:none}`
   is the weakest rule there is, so any `display` declaration beats it — which
   is how a nav item hidden because its location has no camps went on sitting
   in the bar. normalize.css has carried this exact line for a decade. */
[hidden] { display: none !important; }

/* The mocks' other one-liner. Without it an `<img>` is inline, sits on the
   text baseline, and leaves a few pixels of descender space under every
   picture — which is invisible until a photo is supposed to sit flush against
   a 2px rule and does not. */
/* WRAPPED IN :where() ON PURPOSE — THIS IS A RESET AND MUST LOSE EVERY FIGHT.
   Written first as `.wonder-membership img`, which is (0,2,0) and therefore
   beat `.m-logo { display: none }` at (0,1,0): the membership masthead kept a
   340px wordmark on a phone and the page scrolled sideways at all three
   locations. A UA default loses to any author rule whatever its weight, so a
   reset needs no specificity at all to do its job — and having none is what
   stops it silently outranking a deliberate rule somewhere else. Same lesson
   as `.is-layout-flex > :is(*, div)`: `:is()` takes its heaviest argument,
   `:where()` takes nothing. */
:where(.wonder-catalogue, .wonder-camps, .wonder-birthdays, .wonder-membership,
       .wonder-faqs, .wonder-home, .wonder-locpanel, .wonder-schedule,
       .wonder-gifts, .wonder-story, .wonder-careers, .wonder-legal,
       .wonder-theme)
	:where(img, video) { display: block; }

/* h3 AND DOWN INHERIT THE BODY LINE-HEIGHT, because the mocks only ever set
   one on h1 and h2.

   theme.json puts `lineHeight: 1.04` on `elements.heading`, which WordPress
   applies to every level — so an `<h3>` that the mock renders at 18px/1.6,
   29px tall, came out 19px tall here and every card lost ten pixels. The
   headings that want something tighter say so themselves, a few dozen times
   in this file, and those rules still win on specificity. */
.wonder-catalogue h3, .wonder-catalogue h4, .wonder-catalogue h5, .wonder-catalogue h6,
.wonder-camps h3, .wonder-camps h4, .wonder-camps h5, .wonder-camps h6,
.wonder-birthdays h3, .wonder-birthdays h4, .wonder-birthdays h5, .wonder-birthdays h6,
.wonder-theme h3, .wonder-theme h4, .wonder-theme h5, .wonder-theme h6,
.wonder-membership h3, .wonder-membership h4, .wonder-membership h5, .wonder-membership h6,
.wonder-faqs h3, .wonder-faqs h4, .wonder-faqs h5, .wonder-faqs h6,
.wonder-home h3, .wonder-home h4, .wonder-home h5, .wonder-home h6,
.wonder-locpanel h3, .wonder-locpanel h4, .wonder-locpanel h5, .wonder-locpanel h6,
.wonder-schedule h3, .wonder-schedule h4, .wonder-schedule h5, .wonder-schedule h6,
.wonder-gifts h3, .wonder-gifts h4, .wonder-gifts h5, .wonder-gifts h6,
.wonder-story h3, .wonder-story h4, .wonder-story h5, .wonder-story h6,
.wonder-careers h3, .wonder-careers h4, .wonder-careers h5, .wonder-careers h6,
.wonder-legal h3, .wonder-legal h4, .wonder-legal h5, .wonder-legal h6 { line-height: 1.6; }

/* ═══════════════════════════════════════════════════════════════════════════
   LOCATIONS — ported from 02-locations.html.
   The mock is the decision. Where this disagrees with a row in the docs, the
   mock wins: the docs describe the mocks, sometimes from before a change.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The mock's own names, mapped to the theme's presets once here rather than
   rewritten through every rule — which keeps a ported rule diffable against
   the file it came from. */
:root {
	--k: var(--wp--preset--color--ink);
	--w: var(--wp--preset--color--paper);
	--signal: var(--wp--preset--color--signal);
	--body: #222;
	--muted: #555;
	--faint: #888;

	/* Two faces, both opt-in. Playfair belongs to Our Story and to nothing
	   else (9 Sep); Caveat is the hand that signs off a page. Named here so a
	   ported rule keeps the mock's spelling instead of repeating the stack. */
	--display: var(--wonder-display);
	--hand: var(--wonder-hand);

	/* THE SPACE ABOVE A PAGE'S HEADLINE, in one place.
	   Joey, 25 Sep: "there is a LOT of padding and empty space below the nav
	   bar and the start of any individual page's content ... the header
	   section of each page can be a bit tighter/closer to the nav bar." His
	   instruction, so it overrides the mocks' 44px and 52px.

	   It was 44px on six mastheads and 52px on two, each written out
	   separately, on top of the 48px `page.html` puts on <main> — which is how
	   the gap reached 129px on most pages and 214px on Birthday Parties. Half
	   of it now, and a token rather than eight numbers, because eight copies
	   of one decision is how the next trim gets applied to seven of them.

	   The two plainest pages — Careers and the policy — keep their extra 4px
	   over the rest, as `calc()` off this, which was the 52-against-44
	   relationship the mocks set. Home and Our Story are untouched: they use
	   templates that put no padding on <main> at all, which is exactly why
	   those two already read right.

	   NOT every 44px in this file is a masthead: the gift-card `.uses` band and
	   the FAQ `.sect` rhythm are also 44px and are deliberately left alone. */
	--mast-top: 20px;
}

.eyebrow {
	font-size: 11px;
	font-weight: 900;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--k);
	/* The mock's 14px, and it had been missing since the port. It never showed
	   because the headline underneath carried the browser's own 36.5px margin,
	   which is larger and therefore won — so the gap looked roughly right and
	   was wrong for the wrong reason. Zeroing that margin left nothing here. */
	margin-bottom: 14px;
}

.wonder-locpanel .mast h1 {
	font-size: clamp(40px, 6vw, 74px);
	font-weight: 900;
	letter-spacing: -0.02em;
	line-height: 0.98;
	color: var(--k);
	margin-top: 12px;
}

.panel {
	display: grid;
	grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
	gap: 32px;
	margin: 24px 0 0;
	align-items: start;
}

.panel .plate {
	border: 2px solid var(--k);
	overflow: hidden;
	aspect-ratio: 554 / 340;
}

.panel .plate img { width: 100%; height: 100%; object-fit: cover; object-position: center; }

/* Cap the reading column so the hours label and its time sit close together
   rather than being flung to opposite edges of a very wide column. The 8px is
   on the RIGHT — the top padding belongs to the stacked layout only. */
.details { display: flex; flex-direction: column; gap: 0; max-width: 540px; padding: 0 8px 0 0; }

.addr {
	font-size: 14px;
	line-height: 1.5;
	font-weight: 800;
	color: var(--k);
	margin: 0 0 2px;
	max-width: 430px;
}

.chip {
	display: inline-block;
	background: var(--k);
	color: var(--w);
	font-size: 10px;
	font-weight: 900;
	letter-spacing: 0.1em;
	padding: 4px 10px;
	margin-bottom: 8px;
	text-transform: uppercase;
}

.lede { font-size: 13px; line-height: 1.6; color: #333; margin: 8px 0 2px; max-width: 460px; }

.hourslabel {
	font-size: 10px;
	font-weight: 900;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--faint);
	margin-top: 16px;
}

.hourstable { width: 100%; max-width: 430px; border-collapse: collapse; font-size: 12px; margin: 10px 0 12px; }
.hourstable td { padding: 5px 0; }
.hourstable tr { border-bottom: 1px solid #ddd; }
.hourstable tr:last-child { border-bottom: none; }
.hourstable td:first-child { font-weight: 800; letter-spacing: 0.06em; color: var(--k); }
.hourstable td:last-child { text-align: right; font-variant-numeric: tabular-nums; color: var(--body); }

/* ── Inside the club ──────────────────────────────────────────────────────
   The photo band between the panel and the weekly schedule. Ported from
   `02-locations.html`, which notes it "can become a single WordPress block
   later" — it now is.

   4:5 rather than the square these started as (Joey, 18 Sep: "a little
   taller"), 340px tall at full width against 272. It is also the ratio most
   of these photographs were shot at, 1080x1350, so most show whole with no
   crop at all.

   The crop is anchored to the TOP of the frame, because in almost all of
   these the faces are in the upper half and a centred crop beheads them. */
/* TWO HOMES FOR ONE BAND, as of 25 Sep. It was the Locations panel's alone;
   the home page's "Wonder IRL" strip now shows the same carousel once a club
   is chosen (Joey's ask), so every rule below answers to either page.

   `:is()` rather than writing each selector twice. The usual warning about it
   — that it takes its HEAVIEST argument — does not bite here, because both
   arguments are single class selectors of identical weight, so the specificity
   is exactly what `.wonder-locpanel .lshot` was. */
:is(.wonder-locpanel, .wonder-home, .wonder-camps) .locshots { margin: 34px 0 0; }

/* On home the band sits under a heading rather than under the panel, and it
   replaces `.tour`, whose own padding it has to stand in for. */
.wonder-home .tourshots .locshots { margin: 26px 0 0; }
.wonder-home .tourshots { padding-bottom: 56px; }
:is(.wonder-locpanel, .wonder-home, .wonder-camps) .lnav { display: flex; gap: 8px; justify-content: flex-end; margin-bottom: 10px; }
:is(.wonder-locpanel, .wonder-home, .wonder-camps) .lnav button {
	width: 36px;
	height: 36px;
	border: 2px solid var(--k);
	background: var(--w);
	color: var(--k);
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
	font-family: inherit;
}
:is(.wonder-locpanel, .wonder-home, .wonder-camps) .lnav button:hover:not(:disabled) { background: var(--signal); }
:is(.wonder-locpanel, .wonder-home, .wonder-camps) .lnav button:disabled { opacity: 0.3; cursor: default; }

:is(.wonder-locpanel, .wonder-home, .wonder-camps) .ltrack {
	display: flex;
	gap: 16px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	scrollbar-width: none;
	-ms-overflow-style: none;
}
:is(.wonder-locpanel, .wonder-home, .wonder-camps) .ltrack::-webkit-scrollbar { display: none; }

:is(.wonder-locpanel, .wonder-home, .wonder-camps) .lshot {
	scroll-snap-align: start;
	flex: 0 0 calc((100% - 48px) / 4);
	border: 2px solid var(--k);
	overflow: hidden;
	aspect-ratio: 4 / 5;
}
:is(.wonder-locpanel, .wonder-home, .wonder-camps) .lshot img { width: 100%; height: 100%; object-fit: cover; object-position: top; display: block; }

/* Four across on a phone is 80px a side. Two keeps a face readable, and the
   band still scrolls to reach the rest. */
@media (max-width: 640px) {
	:is(.wonder-locpanel, .wonder-home, .wonder-camps) .lshot { flex: 0 0 calc((100% - 16px) / 2); }
}

@media (prefers-reduced-motion: reduce) {
	:is(.wonder-locpanel, .wonder-home, .wonder-camps) .ltrack { scroll-behavior: auto; }
}

.hourstable td.vary { color: var(--muted); }

/* Special hours: derived, never typed. Renders only when a day departs from
   the location's standard week, and disappears on its own when the week goes
   back to normal. Same yellow the schedule grid flags a day with.

   THE BASE RULE WAS MISSING until 25 Sep, so the box had no border, no
   measure and no gap beneath it: the yellow header ran the full 642px of the
   details column instead of sitting at the hours table's 430px, and the list
   below it floated free of anything. */
.special { border: 2px solid var(--k); margin: 0 0 12px; max-width: 430px; }

.special .hd {
	background: var(--signal);
	color: var(--k);
	padding: 5px 10px;
	font-size: 9.5px;
	font-weight: 900;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.special ul { list-style: none; margin: 0; padding: 6px 10px 7px; display: grid; grid-template-columns: 1fr; gap: 0 18px; }
.special ul.two { grid-template-columns: 1fr 1fr; }
.special li { display: flex; justify-content: space-between; gap: 12px; font-size: 11.5px; padding: 2px 0; font-variant-numeric: tabular-nums; }
.special li b { font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--k); }
.special li span { color: var(--body); }

.acts { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: 0; }

.btn {
	border: 2px solid var(--k);
	background: var(--k);
	color: var(--w);
	font-family: inherit;
	font-size: 11px;
	font-weight: 900;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	padding: 11px 20px;
	cursor: pointer;
	text-decoration: none;
	display: inline-block;
}

.btn:hover { opacity: 0.75; }
.btn-o { background: var(--w); color: var(--k); }
.btn-o:hover { opacity: 1; background: var(--signal); }

/* ── This week ──────────────────────────────────────────────────────────── */

.week { padding: 48px 0 0; }
.week h2 { font-size: clamp(26px, 4vw, 44px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.04; color: var(--k); }
.week .dek { font-size: 14px; color: var(--muted); max-width: 600px; margin-top: 12px; }

.days { display: grid; gap: 0; border: 2px solid var(--k); margin-top: 26px; grid-template-columns: repeat(7, 1fr); }

.day { border-right: 2px solid var(--k); display: flex; flex-direction: column; min-width: 0; }
.day:last-child { border-right: none; }

.day .hd { background: var(--k); color: var(--w); border-bottom: 2px solid var(--k); padding: 13px 12px 12px; }
.day .hd .wd { font-size: 12px; font-weight: 900; letter-spacing: 0.12em; text-transform: uppercase; color: var(--w); }
.day .hd .wd .dt { font-weight: 800; letter-spacing: 0.04em; color: rgba(255,255,255,0.62); font-variant-numeric: tabular-nums; }

.day .list { padding: 10px 12px 14px; display: flex; flex-direction: column; gap: 11px; flex: 1; }

.slot .t { font-size: 11px; font-weight: 900; color: var(--k); font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
.slot .n { font-size: 12.5px; font-weight: 800; line-height: 1.25; color: var(--k); margin-top: 2px; }
.slot .s { font-size: 11px; line-height: 1.3; color: var(--muted); margin-top: 2px; }
.slot .out { font-size: 9px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--w); background: var(--k); padding: 2px 6px; display: inline-block; margin-top: 4px; }

/* Open Play is a session the day happens inside, not a label on the day, so
   it is the first row in the white column with a rule under it. */
.slot.op .n { font-size: 13px; font-weight: 900; }
.slot.op { border-bottom: 2px solid var(--k); padding-bottom: 11px; }

.day .ft { border-top: 2px solid var(--k); padding: 9px 12px; font-size: 10px; font-weight: 900; letter-spacing: 0.06em; text-transform: uppercase; color: var(--body); margin-top: auto; }
.day .ft.flag { background: var(--signal); color: var(--k); }
.day.closed .list { color: var(--muted); font-size: 12px; padding-top: 16px; }

@media (max-width: 980px) {
	.days { grid-template-columns: repeat(2, 1fr); }
	.day { border-right: 2px solid var(--k); border-bottom: 2px solid var(--k); }
	.day:nth-child(2n) { border-right: none; }
}

@media (max-width: 880px) {
	.panel { grid-template-columns: 1fr; }
	.details { padding-top: 8px; max-width: none; }
	.special ul.two { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
	.days { grid-template-columns: 1fr; }
	.day { border-right: none; }
}

/* ── Topbar picker, collapsed ───────────────────────────────────────────────
   Restored after a careless edit deleted it: a script that cut "from this
   comment to the next section header" found no next header and cut to the end
   of the file. Rules appended without a section header of their own were
   invisible to it — which is the argument for every block having one. */

details.wonder-picker.is-bar { position: relative; }

.wonder-picker__summary {
	display: inline-block;
	/* The mock's `.locbtn` metrics, minus its 172px min-width: that was there
	   to stop the bar reflowing when the chosen location changes length, and
	   it bought that by leaving a hand's width of empty box beside the word.
	   Joey, 23 Sep. A button that fits its label is worth a few pixels of
	   movement on the rare occasion somebody switches. */
	padding: 8px 12px;
	border: 2px solid var(--wp--preset--color--ink);
	font-size: 10.5px;
	line-height: 1.2;
	font-weight: 900;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	cursor: pointer;
	list-style: none;
	white-space: nowrap;
}

/* Chrome draws the disclosure triangle with ::marker now, and list-style:none
   alone no longer removes it — the topbar was reading "▶ Battery Park". */
.wonder-picker__summary::marker { content: ""; }
.wonder-picker__summary::-webkit-details-marker { display: none; }

.wonder-picker__summary::after { content: " ▾"; font-size: 10px; }
details[open] .wonder-picker__summary::after { content: " ▴"; }

.wonder-picker__summary:hover,
.wonder-picker__summary:focus-visible { background: var(--wp--preset--color--signal); }

/* Chrome draws a blue rounded ring by default, which is the one colour this
   site does not contain. Keyboard focus is worth showing — it is just worth
   showing in the site's own terms. */
.wonder-picker__summary:focus-visible,
.wonder-picker__link:focus-visible {
	outline: 2px solid var(--k);
	outline-offset: 2px;
}

/* The open list sits over the page rather than pushing it, so opening the
   picker never moves the content underneath. */
details.wonder-picker.is-bar .wonder-picker__list {
	position: absolute;
	top: calc(100% + 2px);
	right: 0;
	z-index: 20;
	flex-direction: column;
	min-width: 100%;
	background: var(--wp--preset--color--paper);
	border: 2px solid var(--wp--preset--color--ink);
}

details.wonder-picker.is-bar .wonder-picker__link {
	border: 0;
	border-top: 2px solid var(--wp--preset--color--ink);
	white-space: nowrap;
}

details.wonder-picker.is-bar .wonder-picker__item:first-child .wonder-picker__link { border-top: 0; }
details.wonder-picker.is-bar .wonder-picker__note { display: block; }

/* ═══════════════════════════════════════════════════════════════════════════
   CLASSES — ported from 01-classes.html.
   ═══════════════════════════════════════════════════════════════════════════ */

.wonder-catalogue .mast h1 {
	font-size: clamp(40px, 6vw, 74px);
	font-weight: 900;
	letter-spacing: -0.02em;
	line-height: 0.98;
	color: var(--k);
	margin-top: 12px;
}

.wonder-catalogue .mast .dek { font-size: 15px; line-height: 1.65; color: #222; max-width: 620px; margin-top: 18px; }

.banner {
	border: 2px solid var(--k);
	background: var(--wp--preset--color--field);
	padding: 16px 18px;
	margin-top: 22px;
	font-size: 14.5px;
	font-weight: 800;
	color: var(--k);
}

/* Age bands and subjects are different questions — "how old is my child" and
   "what is it" — so a rule separates them. One run of nine chips reads as one
   question with nine answers. */
.filter { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; padding: 20px 0; border-bottom: 2px solid var(--k); }
.filter button {
	border: 2px solid var(--k);
	background: var(--w);
	color: var(--k);
	font-family: inherit;
	font-size: 10.5px;
	font-weight: 800;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	padding: 6px 12px;
	cursor: pointer;
}
.filter button:hover { background: var(--signal); color: var(--k); }
.filter button[aria-pressed="true"] { background: var(--k); color: var(--w); }
.filter button[aria-pressed="true"]:hover { background: var(--k); color: var(--signal); }
.filter .sep { width: 2px; align-self: stretch; background: var(--k); margin: 0 8px; }

/* A subject that needs explaining explains itself here, once, instead of on
   every card that carries it. Only Wonderbox has one today. */
.tagnote { max-width: 80ch; padding: 18px 0 0; font-size: 15px; line-height: 1.6; color: var(--body); }
.tagnote b { font-weight: 900; color: var(--k); }

.cgrid { display: grid; gap: 34px 24px; padding: 38px 0 10px; grid-template-columns: repeat(auto-fill, minmax(226px, 1fr)); }

.card { display: flex; flex-direction: column; gap: 11px; min-width: 0; }

/* `display: flex` outranks the browser's own `[hidden] { display: none }`, so
   without this a filtered-out card keeps its grid cell and draws as an empty
   bordered box. Say it again, louder. */
.card[hidden] { display: none; }

/* SCOPED TO ITS TWO PAGES, AND IT HAD TO BE.
   `.flip` was global, and Our Story's `.char-card.flip` — a mirrored column
   order, nothing to do with a 3D card — inherited `aspect-ratio: 1191/1685`
   from it. Every flipped professor became a 1100x1556 empty A4 box with the
   portrait and the bio pushed to the bottom of it. Three pages, one word,
   two entirely different components: the same failure as `.faq`, `.gate`,
   `.ph`, `.badge`, `.soon` and `.fineprint` before it.

   The card is two pictures. The front is the poster, the back is the
   description — both artwork — so the card prints no age line and no blurb:
   the blurb is the BACK'S ALT TEXT. That is how the description reaches a
   screen reader and a search engine while the sighted reader gets the
   drawing, instead of the page saying everything twice. */
.wonder-catalogue .flip, .wonder-birthdays .flip, .wonder-theme .flip {
	position: relative;
	aspect-ratio: 1191 / 1685;
	border: 2px solid var(--k);
	background: var(--wp--preset--color--field);
	perspective: 1400px;
	cursor: pointer;
	padding: 0;
	width: 100%;
	display: block;
	font: inherit;
	color: inherit;
	text-align: left;
}

.wonder-catalogue .inner, .wonder-birthdays .inner, .wonder-theme .inner { position: absolute; inset: 0; transform-style: preserve-3d; transition: transform 0.55s cubic-bezier(0.2, 0.7, 0.3, 1); }
/* HOVER IS BEHIND A HOVER QUERY, and it had to be. iOS leaves `:hover` stuck
   on the last thing a finger touched, so a card tapped once stayed flipped
   however many times it was tapped again: `.open` came off, `:hover` did not.
   Joey, 25 Sep: "tapping it again is not returning it back to the front side."
   A device with no pointer now gets `.open` and nothing else. */
.wonder-catalogue .flip.open .inner, .wonder-birthdays .flip.open .inner, .wonder-theme .flip.open .inner { transform: rotateY(180deg); }
@media (hover: hover) {
	.wonder-catalogue .flip:hover .inner, .wonder-birthdays .flip:hover .inner, .wonder-theme .flip:hover .inner { transform: rotateY(180deg); }
}
.wonder-catalogue .side, .wonder-birthdays .side, .wonder-theme .side { position: absolute; inset: 0; backface-visibility: hidden; overflow: hidden; }
.wonder-catalogue .side.back, .wonder-birthdays .side.back, .wonder-theme .side.back { transform: rotateY(180deg); }
.wonder-catalogue .side img, .wonder-birthdays .side img, .wonder-theme .side img { width: 100%; height: 100%; object-fit: cover; }

.wonder-catalogue .ph,
.wonder-theme .acard .ph,
.wonder-birthdays .acard .ph { width: 100%; height: 100%; background: var(--wp--preset--color--field); display: flex; flex-direction: column; justify-content: space-between; padding: 16px; }
.wonder-catalogue .ph .nm,
.wonder-theme .acard .ph .nm,
.wonder-birthdays .acard .ph .nm { font-size: 19px; font-weight: 900; line-height: 1.06; letter-spacing: -0.01em; color: var(--k); }
.wonder-catalogue .ph .lbl,
.wonder-theme .acard .ph .lbl,
.wonder-birthdays .acard .ph .lbl { font-size: 9px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }
.wonder-catalogue .ph.b,
.wonder-theme .acard .ph.b,
.wonder-birthdays .acard .ph.b { background: var(--w); }
.wonder-catalogue .ph.b .cp,
.wonder-theme .acard .ph.b .cp,
.wonder-birthdays .acard .ph.b .cp { font-size: 11.5px; line-height: 1.45; color: var(--body); overflow: hidden; }

.meta { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.meta h3 { font-size: 19px; font-weight: 900; line-height: 1.1; letter-spacing: -0.01em; color: var(--k); }
.meta a.sched { font-size: 10px; font-weight: 900; letter-spacing: 0.08em; text-transform: uppercase; color: var(--k); white-space: nowrap; text-decoration: none; border-bottom: 2px solid var(--k); flex: none; }
.meta a.sched:hover { background: var(--signal); }
.meta .resting { font-size: 10px; font-weight: 900; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); white-space: nowrap; flex: none; }

.empty { padding: 52px 0; font-size: 24px; font-weight: 900; color: var(--muted); }

/* The hint only exists where hover cannot flip the card. */
.wonder-catalogue .tap, .wonder-birthdays .tap, .wonder-theme .tap { display: none; }

@media (hover: none) {
	.wonder-catalogue .tap, .wonder-birthdays .tap, .wonder-theme .tap {
		display: block;
		position: absolute;
		right: 0;
		bottom: 0;
		z-index: 2;
		background: var(--k);
		color: var(--w);
		font-size: 9px;
		font-weight: 900;
		letter-spacing: 0.14em;
		text-transform: uppercase;
		padding: 5px 9px;
	}
	.wonder-catalogue .flip.open .tap, .wonder-birthdays .flip.open .tap, .wonder-theme .flip.open .tap { display: none; }
}

@media (max-width: 640px) { .filter .sep { display: none; } }
@media (prefers-reduced-motion: reduce) { .wonder-catalogue .inner, .wonder-birthdays .inner, .wonder-theme .inner { transition: none; } }

/* ============================================================================
   CAMPS
   Ported from `08-camps.html`. Its companion `08b-camps-with-portal.html` is
   the swap for the day the Member Portal is live, not the build — Joey, 21 Sep.
   ========================================================================= */

.wonder-camps .mast { border-bottom: 2px solid var(--k); padding: var(--mast-top) 0 26px; }
.wonder-camps .mast h1 {
	font-size: clamp(40px, 6vw, 74px);
	font-weight: 900;
	letter-spacing: -0.02em;
	line-height: 0.98;
	color: var(--k);
	margin-top: 12px;
}
.wonder-camps .mast .dek { font-size: 15px; line-height: 1.65; color: var(--body); max-width: 600px; margin-top: 16px; }

/* The badge sits BESIDE the headline, not above it: it is a mark, not a
   picture, and stacking it would push the dates below the fold. No border and
   no box either — it is a circle with its own edge, and a 2px square around a
   round badge fights it.

   The 240px ceiling is measured, not taste: the row is 1136px from 1200 up,
   the headline's long line measures 836 and the gap is 36, so anything over
   264 would push "No problem. We got you." onto a third line. */
/* SCOPED: `.mast-row` and `.mast-copy` are also the membership masthead's
   class names, and the row-reverse below was reversing that one too — which is
   how a 340px wordmark ended up at x = -25 on a phone. Collision number eight,
   caught before it shipped. */
.wonder-camps .mast-row { display: flex; align-items: center; gap: 36px; }
.wonder-camps .mast-copy { flex: 1; min-width: 0; }
.wonder-camps .camp-badge { flex: none; width: clamp(104px, 17vw, 240px); height: auto; display: block; }
@media (min-width: 1200px) { .wonder-camps .camp-badge { width: 240px; } }
@media (max-width: 720px) {
	.wonder-camps .mast-row { flex-direction: row-reverse; align-items: flex-start; gap: 18px; }
	.wonder-camps .camp-badge { width: 84px; margin-top: 4px; }
}

/* Equinox green, not the site's black and yellow: this panel says "not here,
   not yet", and that is the Upper West Side's colour wherever it appears. */
.soon {
	border: 2px solid var(--wp--preset--color--equinox);
	background: var(--wp--preset--color--equinox-tint);
	padding: 22px 24px;
	margin: 26px 0 0;
}
.soon .tag {
	display: inline-block;
	background: var(--wp--preset--color--equinox);
	color: var(--w);
	font-size: 9.5px;
	font-weight: 900;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	padding: 4px 10px;
	margin-bottom: 10px;
}
.soon p { font-size: 13.5px; line-height: 1.6; color: #123; }

.intro { display: grid; grid-template-columns: 1.7fr 1fr; gap: 26px; padding: 40px 0 8px; align-items: start; }
@media (max-width: 900px) { .intro { grid-template-columns: 1fr; } }
.intro .lead { font-size: 16px; line-height: 1.6; color: var(--body); }
.intro .lead b { color: var(--k); }

/* A run of chips rather than a bulleted list: it is a sampler, not a sequence,
   and "try a little of a lot" should look like it. */
.wonder-camps .chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 20px; }
.wonder-camps .chips span {
	font-size: 10.5px;
	font-weight: 900;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	border: 2px solid var(--k);
	padding: 6px 11px;
	color: var(--k);
}

.wonder-camps .facts { display: flex; flex-wrap: wrap; gap: 0 26px; margin-top: 24px; border-top: 2px solid var(--k); padding-top: 14px; }
.wonder-camps .facts div { min-width: 104px; }
.wonder-camps .facts .k { font-size: 9.5px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }
.wonder-camps .facts .v { font-size: 17px; font-weight: 900; color: var(--k); line-height: 1.2; margin-top: 2px; }

/* COLLISION NUMBER NINE, and it reached a page nobody was looking at.
   `.pricebox` is the CAMPS price table's box. The membership page uses the
   same word for the billing figure inside its `.base` card, where the mock
   asks for `text-align:right` and nothing else — so the UWS presale card was
   drawing a 2px box with 26px of padding inside its own 4px box. Joey, 24
   Sep: "an additional box... adding a lot of unnecessary padding."

   Scoped, not renamed, because the camps markup is right and it was only
   ever this stylesheet claiming the name globally.

   `.prices` next door is NOT the same case and is deliberately left alone:
   camps and birthdays share that component on purpose, which is why
   `.wonder-birthdays .prices` exists to adjust it rather than replace it. */
.wonder-camps .pricebox { border: 2px solid var(--k); padding: 26px; background: var(--w); }
.wonder-camps .pricebox h3 { font-size: 12px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--k); }
.prices { margin-top: 16px; border-top: 2px solid var(--k); }
.prices .row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 10px 0; border-bottom: 1px solid #e5e5e5; }
.prices .row:last-child { border-bottom: none; }
.prices .who { font-size: 11px; font-weight: 900; letter-spacing: 0.08em; text-transform: uppercase; color: var(--k); }
.prices .amt { font-size: 26px; font-weight: 900; color: var(--k); font-variant-numeric: tabular-nums; }
.prices .amt small { font-size: 11px; font-weight: 800; color: var(--muted); letter-spacing: 0.04em; }
.redeem { font-size: 11.5px; line-height: 1.5; color: var(--muted); margin-top: 14px; }
.redeem b { color: var(--k); }

/* Square and four across, Joey's call on 18 Sep: it keeps 80% of each
   photograph where 4:3 kept 60% and read as "too cropped". The sources are
   portrait phone pictures whose subjects all sit in the UPPER half, so the
   crop is anchored to the top of the frame — worth knowing before anyone
   drops a fifth photograph in here with its subject low.

   Two-by-two below 600, because four across on a phone is 77px a side and a
   photograph that small says nothing. */
/* The camp photographs are the site's photograph band now, not a grid of
   their own — Joey, 25 Sep: "Images should be carousel like everything else."
   Square rather than 4:5 is the only thing that differs, and it is one line:
   the sources are portrait phone pictures whose subjects sit in the upper
   half, which is why the crop stays anchored to the top. */
.campshots { margin: 30px 0 0; }
.wonder-camps .lshot { aspect-ratio: 1 / 1; }

.season { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; border-bottom: 2px solid var(--k); padding-bottom: 8px; margin: 44px 0 0; }
.season h2 { font-size: clamp(24px, 3.6vw, 38px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.04; color: var(--k); }
.season .count { font-size: 10px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); white-space: nowrap; flex: none; padding-bottom: 4px; }
.nodates { padding: 30px 0; font-size: 15px; color: var(--muted); }

/* One row per bookable date. The row highlight bleeds 12px past the column on
   both sides so the band reads as full-width without the grid being so. */
.drow { display: grid; grid-template-columns: 76px 1fr auto 150px; gap: 0 22px; align-items: center; border-bottom: 2px solid var(--k); padding: 16px 0; }
.drow:hover { background: var(--signal); box-shadow: -12px 0 0 var(--signal), 12px 0 0 var(--signal); }
.dnum { font-size: 30px; font-weight: 900; line-height: 0.9; color: var(--k); font-variant-numeric: tabular-nums; }
.dmon { font-size: 9.5px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); margin-top: 4px; }
.dday { font-size: 18px; font-weight: 900; letter-spacing: -0.01em; color: var(--k); line-height: 1.15; }
.dmeta { font-size: 12px; color: var(--muted); margin-top: 2px; }
.dstate { font-size: 10px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--k); white-space: nowrap; }
.drow .btn { padding: 13px 18px; font-size: 11px; width: 100%; text-align: center; }
@media (max-width: 760px) {
	.drow { grid-template-columns: 62px 1fr; gap: 4px 16px; }
	.dstate { grid-column: 2; }
	/* The grid item is the button's wrapper, not the button. */
	.drow > div:last-child { grid-column: 1 / -1; margin-top: 10px; }
}

.know { border: 2px solid var(--k); padding: 28px 30px; margin-top: 44px; }
.know h2 { font-size: 12px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--k); margin-bottom: 14px; }
.know ul { list-style: none; display: grid; grid-template-columns: 1fr 1fr; gap: 0 32px; margin: 0; padding: 0; }
@media (max-width: 760px) { .know ul { grid-template-columns: 1fr; } }
.know li { font-size: 13.5px; line-height: 1.55; padding: 9px 0 9px 18px; position: relative; border-bottom: 1px solid #e9e9e9; color: #333; }
.know li:before { content: ''; position: absolute; left: 0; top: 17px; width: 8px; height: 2px; background: var(--k); }
.know li b { color: var(--k); }
@media (min-width: 761px) { .know li:nth-last-child(-n+2) { border-bottom: none; } }
@media (max-width: 760px) { .know li:last-child { border-bottom: none; } }

/* ── the ROLLER checkout drawer ──────────────────────────────────────────
   Scoped to `.wonder-checkout`, a class the CAMPS and GIFT CARDS blocks both
   carry, because it is one component on two pages. Scoping it to `.wonder-camps`
   meant Gift Cards got the markup and none of the styling.

   ROLLER's checkout is built to be framed — their own overlay script does
   exactly that — so this puts it in OUR frame instead of accepting theirs. The
   drawer is ours: our rule, our close, our ground. Inside it is their page,
   untouched. */
.wonder-checkout .scrim { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.42); z-index: 80; opacity: 0; transition: opacity 0.28s; }
.wonder-checkout .scrim[hidden] { display: none; }
.wonder-checkout .scrim.on { opacity: 1; }
.wonder-checkout .drawer {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	width: min(520px, 100%);
	background: var(--w);
	border-left: 2px solid var(--k);
	z-index: 81;
	display: flex;
	flex-direction: column;
	transform: translateX(100%);
	transition: transform 0.32s cubic-bezier(0.2, 0.7, 0.3, 1);
}
.wonder-checkout .drawer[hidden] { display: none; }

/* WIDER ON MEMBERSHIP. Joey, 24 Sep: "is it possible it appears in a similar
   way the camp checkout appears? (But wider?)". A camp checkout is one date;
   this one carries four tiers and two billing terms, and at 520px a family
   would be scrolling sideways to compare the very thing they opened it to
   compare. 860px read as too wide, so: 45% of the window, Joey's number.

   Written from the inside out rather than as a clamp(), because clamp() lets
   its floor beat its ceiling: clamp(520px, 45%, 100%) is 520px on a 390px
   phone, i.e. wider than the phone. min(100%, max(...)) cannot do that — the
   window always wins last. So: 45%, never narrower than the camp drawer it is
   modelled on, never wider than the window. 1440 -> 648px. 1024 -> 520px.
   390 -> 390px, full width, the same as every other drawer on a phone. */
.wonder-membership.wonder-checkout .drawer { width: min(100%, max(520px, 45%)); }
.wonder-checkout .drawer.on { transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
	.wonder-checkout .drawer, .wonder-checkout .scrim { transition: none; }
}
.dhd { display: flex; align-items: center; justify-content: space-between; gap: 16px; border-bottom: 2px solid var(--k); padding: 16px 20px; flex: none; }
.dhd .lbl { font-size: 9.5px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }
.dhd h2 { font-size: 18px; font-weight: 900; letter-spacing: -0.01em; color: var(--k); line-height: 1.15; }
.dclose { border: 2px solid var(--k); background: var(--w); width: 34px; height: 34px; flex: none; cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; }
.dclose:hover { background: var(--signal); }
.dclose svg { width: 13px; height: 13px; stroke: var(--k); stroke-width: 2.4; stroke-linecap: round; fill: none; }
.dbody { position: relative; flex: 1; min-height: 0; background: var(--w); }
.dbody iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
.dfall { position: absolute; inset: 0; z-index: 2; background: var(--wp--preset--color--field); display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 36px 26px; gap: 14px; }
.dfall[hidden] { display: none; }
.dfall .lbl { font-size: 10px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }
.dfall h3 { font-size: 21px; font-weight: 900; letter-spacing: -0.01em; line-height: 1.15; color: var(--k); max-width: 22ch; }
.dfall p { font-size: 13px; line-height: 1.6; color: var(--muted); max-width: 40ch; }

/* ============================================================================
   BIRTHDAY PARTIES
   Ported from `05-birthday-parties.html`.

   Several pieces here are deliberately the SAME components as other pages —
   the flip card is the Classes card, the quote band is the home page's, the
   green "coming soon" panel is the Camps one. Where a rule already exists
   above it is not repeated; only the differences are written down.
   ========================================================================= */

/* The masthead is copy left, photograph right, and the picture sits beside the
   WHOLE copy block rather than beside the headline — its height is absorbed by
   four stacked elements so no gap opens between the headline and the
   standfirst. */
.wonder-birthdays .mast {
	display: grid;
	grid-template-columns: 1.15fr 0.85fr;
	gap: 36px;
	align-items: center;
	border-bottom: 2px solid var(--k);
	padding: var(--mast-top) 0 26px;
}
.wonder-birthdays .mcopy { min-width: 0; }
.wonder-birthdays .mast-cta { margin-top: 22px; }

/* The headline is ARTWORK rather than type — Joey, 18 Sep. "Let's party!"
   moved up into the eyebrow and the Wonder Birthdays script takes the h1's
   place.

   It stays an <h1> with an <img> inside rather than becoming a bare picture:
   the page still needs a heading, and alt="Wonder Birthdays" IS that heading.
   A <div> with a photograph in it would have left the page with no h1 at all.

   The width is capped in em so it tracks the h1's own clamped font-size —
   9.4em of a 74px headline is ~695px, and the artwork is 824 wide, so it never
   renders above its natural size and never goes soft. line-height:0 kills the
   inline-image gap that would otherwise open under it. */
.wonder-birthdays .mast h1 {
	font-size: clamp(40px, 6vw, 74px);
	font-weight: 900;
	letter-spacing: -0.02em;
	line-height: 0.98;
	color: var(--k);
}
.wonder-birthdays .mast h1.wordmark { line-height: 0; margin-top: 14px; }
.wonder-birthdays .mast h1.wordmark img { width: min(100%, 9.4em); height: auto; display: block; }
.wonder-birthdays .mast .dek { font-size: 15px; line-height: 1.65; color: var(--body); max-width: none; margin-top: 16px; }

/* 4:5 — the photograph's own shape, uncropped. It was 1170×1005 while the art
   was a landscape picture; the balloons shot that replaced it on 18 Sep is
   portrait, and Joey's call is that it shows WHOLE rather than being cut to
   fit a landscape hole. So the frame follows the picture, and `object-fit:
   cover` on a box of the same ratio has nothing left to trim.

   The cost, so nobody mistakes it for an accident: the art column is taller
   than the copy beside it — about 500px against 290px — so the masthead is
   deeper than it was and the copy sits centred against the picture rather than
   filling it. That is the trade for an uncropped photograph.

   The cap is on the BOX, not on the grid column: narrowing the column would
   have widened the copy to ~830px and set the standfirst at a measure nobody
   can read. `margin-left:auto` keeps the frame hard against the right-hand
   rule, where every other band on the site ends. */
.wonder-birthdays .mastart {
	border: 2px solid var(--k);
	background: var(--wp--preset--color--field);
	aspect-ratio: 4 / 5;
	align-self: center;
	overflow: hidden;
	width: min(100%, 400px);
	margin-left: auto;
}
.wonder-birthdays .mastart img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 760px) {
	.wonder-birthdays .mast { grid-template-columns: 1fr; gap: 24px; }
	/* Stacked, the frame would otherwise run the full width — at the 760px end
	   of this range that is an 870px-tall photograph before the reader has met
	   a single word. */
	.wonder-birthdays .mastart { order: 2; width: min(100%, 340px); margin: 0 auto; }
}

/* ── the quote band ──────────────────────────────────────────────────────
   The same component as the home page, deliberately down to the class names:
   one pattern used twice, rather than two things that merely look alike.

   One difference, and it is why the type is smaller here. The home page runs
   eight one-liners; these are letters from parents, and the band is as tall as
   its LONGEST quote — the slides are stacked in one grid cell so it never
   jumps as it turns. At the home page's 32px the long one ran seven lines and
   left the two short ones floating in a tall empty box. */
.quotes { padding: 40px 20px 34px; border-bottom: 2px solid var(--k); text-align: center; }
.qrow { display: flex; align-items: center; justify-content: center; gap: 26px; max-width: 1040px; margin: 0 auto; }
.qtrack { display: grid; flex: 1; min-width: 0; max-width: 900px; margin: 0 auto; }
.qtrack figure { grid-area: 1 / 1; opacity: 0; transition: opacity 0.22s ease; pointer-events: none; display: flex; flex-direction: column; justify-content: center; }
.qtrack figure.on { opacity: 1; pointer-events: auto; transition: opacity 0.34s ease 0.1s; }
.qtrack blockquote { font-size: clamp(15px, 1.75vw, 21px); font-weight: 900; line-height: 1.4; color: var(--k); letter-spacing: -0.01em; }
.qtrack figcaption { margin-top: 16px; font-size: 12px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.qtrack figcaption .where { color: var(--faint); }
.qnav { flex: none; width: 48px; height: 48px; padding: 0; border: 2px solid var(--k); background: var(--w); color: var(--k); cursor: pointer; display: flex; align-items: center; justify-content: center; }
.qnav:hover { background: var(--signal); }
.qnav:active { background: var(--k); color: var(--w); }
.qnav svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: square; stroke-linejoin: miter; }
@media (max-width: 640px) { .qrow { gap: 8px; } .qnav { width: 36px; height: 36px; } }
@media (prefers-reduced-motion: reduce) { .qtrack figure { transition: none; } }

/* ── the package ─────────────────────────────────────────────────────────
   Three boxes: price and what-you-get side by side, the add-on menu full width
   underneath. The two top boxes stretch to the taller of the pair, so the CTA
   is pinned to the bottom of the price box rather than floating. */
.pkg { display: grid; grid-template-columns: 1fr 1.15fr; gap: 22px; padding: 40px 0 8px; align-items: stretch; }
.pkg .addons { grid-column: 1 / -1; }
@media (max-width: 900px) { .pkg { grid-template-columns: 1fr; } }

.tier { border: 2px solid var(--k); padding: 30px; position: relative; background: var(--w); }
.tier-hero { border-width: 4px; }
.tier h3 { font-size: 13px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--k); }
.tier-price { display: flex; flex-direction: column; }
.tier-price .prices { flex: none; }
.tier-price .btn-full { margin-top: auto; }
.ribbon {
	position: absolute;
	top: -14px;
	left: 50%;
	transform: translateX(-50%);
	background: var(--k);
	color: var(--w);
	font-size: 10px;
	font-weight: 900;
	letter-spacing: 0.12em;
	padding: 6px 16px;
	white-space: nowrap;
}

.wonder-birthdays .prices { margin: 18px 0 4px; border-top: 2px solid var(--k); }
.wonder-birthdays .prices .row { padding: 9px 0; }
.wonder-birthdays .prices .amt { font-size: 20px; }
.wonder-birthdays .prices .row.lead .amt { font-size: 34px; line-height: 1; }
/* The headline number is a MEMBER price. Its label is the only thing stopping
   a non-member anchoring on a figure they cannot pay, so it is not allowed to
   be the quiet grey the other rows use. */
.wonder-birthdays .prices .row.lead .who { font-size: 12px; }

/* No standfirst here. The heading is followed by the same 2px rule the price
   ladder uses, so the two boxes open identically — Joey's call, 14 Sep, and it
   is the better one: a sentence explaining that a list of inclusions is a list
   of inclusions was doing no work. */
.tier ul { list-style: none; margin: 18px 0 22px; padding: 0; }
.included ul { margin: 18px 0 0; border-top: 2px solid var(--k); }
.tier li { font-size: 13px; line-height: 1.5; padding: 7px 0; border-bottom: 1px solid #e5e5e5; color: #333; }
.tier li:last-child { border-bottom: none; }
.tier li b { color: var(--k); font-weight: 800; }
.btn-full { width: 100%; text-align: center; }

.addons h3 { margin-bottom: 4px; }
.addons .lede { font-size: 12px; color: var(--muted); margin: 8px 0 16px; }
.addcols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
@media (max-width: 760px) { .addcols { grid-template-columns: 1fr; } }
.addcol .hd { font-size: 10px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; border-bottom: 2px solid var(--k); padding-bottom: 6px; margin-bottom: 8px; color: var(--k); }
.addcol ul { list-style: none; margin: 0; padding: 0; }
.addcol li { font-size: 12.5px; line-height: 1.45; padding: 5px 0; border-bottom: 1px solid #eee; color: #333; }
.addcol li:last-child { border-bottom: none; }
.addcol li .nb { color: var(--muted); }
.addcol li .chip { display: inline-block; font-size: 8px; font-weight: 900; letter-spacing: 0.08em; text-transform: uppercase; background: var(--k); color: var(--w); padding: 2px 6px; margin-left: 5px; vertical-align: 1px; }

/* ── the card grid and the theme carousel ───────────────────────────────── */
.tl { padding: 34px 0 10px; }
.tl h2 { font-size: clamp(26px, 4vw, 44px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.04; color: var(--k); }
.poster-note { font-size: 12.5px; color: var(--muted); max-width: 680px; line-height: 1.6; margin-top: 10px; }

/* The standfirst is measured against its own HEADLINE rather than against a
   number. A one-column grid sized to max-content takes its width from the
   widest thing in it — the h2 — so the paragraph wraps at the headline's right
   edge and keeps doing so if the headline is reworded or the type scale moves.

   `width: 0` removes the paragraph from that measurement, or the column would
   size to the UNWRAPPED sentence, which is wider than the headline and the
   opposite of the point. `min-width: 100%` then stretches it back out to
   whatever the headline settled on. Joey, 16 Sep. */
.tl-intro { display: grid; grid-template-columns: minmax(0, max-content); justify-content: start; }
.tl-intro h2 { max-width: 100%; }
.tl-intro .poster-note { width: 0; min-width: 100%; max-width: none; }

.tl-sub { font-size: 10px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--k); border-bottom: 2px solid var(--k); padding-bottom: 7px; margin: 38px 0 6px; }

/* The same flip card the Classes page uses — .flip, .inner, .side, .ph and
   .tap are all defined in the CLASSES section above and are not repeated. Only
   the type sizes differ, because these cards sit five across rather than four
   and their names are longer. */
.agrid { display: grid; gap: 28px 18px; padding: 16px 0 4px; grid-template-columns: repeat(5, 1fr); }
@media (max-width: 1040px) { .agrid { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 840px) { .agrid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 620px) { .agrid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 380px) { .agrid { grid-template-columns: 1fr; } }
.acard { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.acard[hidden] { display: none; }
.acard .ph { padding: 13px; }
.acard .ph .nm { font-size: 16px; }
.acard .ph.b .cp { font-size: 10.5px; }
.ameta { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.ameta h3 { font-size: 14.5px; font-weight: 900; line-height: 1.1; letter-spacing: -0.01em; color: var(--k); }
.ameta .pr { font-size: 10px; font-weight: 900; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); white-space: nowrap; flex: none; }

/* A carousel, not a grid. Seven posters in two rows leaves a ragged second row
   and pushes the form off the screen; one row that scrolls keeps the section
   one band tall however many themes we add. Native overflow scrolling does the
   work and the arrows only nudge it, so a trackpad swipe, a touch drag and the
   keyboard all keep working. */
.carhd { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; border-bottom: 2px solid var(--k); padding-bottom: 7px; margin: 38px 0 6px; }
.carhd .tl-sub { border-bottom: none; padding-bottom: 0; margin: 0; }
.arrows { display: flex; gap: 6px; flex: none; }
.arrows button { width: 30px; height: 26px; border: 2px solid var(--k); background: var(--w); cursor: pointer; padding: 0; display: flex; align-items: center; justify-content: center; }
.arrows button:hover:not(:disabled) { background: var(--signal); }
.arrows button:disabled { opacity: 0.28; cursor: default; }
.arrows svg { width: 11px; height: 11px; stroke: var(--k); stroke-width: 2.4; fill: none; stroke-linecap: round; stroke-linejoin: round; }
/* The arrows used to go below 640px, from when the phone got a peeking card
   instead. Joey, 25 Sep: "Needs arrows like all other carousels" and "Themes
   are also getting cut off … needs arrows to navigate." A row a thumb cannot
   reach the end of is worse than two small buttons.

   Except above the add-on strip, which is a GRID over 600px with nothing to
   scroll — there the buttons would be permanently dead. */
@media (min-width: 601px) { .addhd .arrows { display: none; } }

.carousel { position: relative; padding: 16px 0 4px; }
.carousel .track { display: flex; gap: 18px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; scrollbar-width: none; -ms-overflow-style: none; padding-bottom: 4px; }
.carousel .track::-webkit-scrollbar { display: none; }
.carousel .track > * { scroll-snap-align: start; flex: 0 0 calc((100% - 54px) / 4); }
@media (max-width: 1040px) { .carousel .track > * { flex-basis: calc((100% - 36px) / 3); } }
/* Below the third card the next one PEEKS rather than sitting flush: on a
   phone the arrows are gone and the peek is the only thing that says there is
   more to the right. */
@media (max-width: 840px) { .carousel .track > * { flex-basis: calc((100% - 18px) / 2.4); } }
@media (max-width: 520px) { .carousel .track > * { flex-basis: 72%; } }
@media (prefers-reduced-motion: reduce) { .carousel .track { scroll-behavior: auto; } }

/* Theme posters carry their own title, so the card is the artwork and nothing
   is set on top of it. The name lives underneath, where a caption belongs. */
.tcard { display: flex; flex-direction: column; gap: 10px; min-width: 0; text-decoration: none; color: inherit; }
.tposter { display: block; position: relative; aspect-ratio: 700 / 990; border: 2px solid var(--k); background: var(--wp--preset--color--field); overflow: hidden; transition: transform 0.15s; }
.tposter img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tcard:hover .tposter { transform: translateY(-4px); }
.tmeta { display: block; }
.tmeta h3 { font-size: 15px; font-weight: 900; line-height: 1.12; letter-spacing: -0.01em; color: var(--k); }
.tmeta .go { display: inline-block; font-size: 9.5px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--k); border-bottom: 2px solid var(--k); margin-top: 6px; }
.tcard:hover .tmeta .go { background: var(--signal); }
.tmeta .go.pending { border-bottom-color: #bbb; color: var(--faint); }
.tcard:hover .tmeta .go.pending { background: none; }

/* A theme with no landing page yet.
   NOTE the class is .tsoon, not .soon: this page already uses .soon for the
   UWS pre-opening band, and reusing it gave every coming-soon poster that
   band's green Equinox border.
   A half-opacity veil over the poster on hover, and none of the affordances
   that say "this goes somewhere": no lift, no yellow. Joey's call, 15 Sep. */
.tcard.tsoon { cursor: default; }
.tcard.tsoon:hover .tposter { transform: none; }
.soonveil { position: absolute; inset: 0; background: rgba(255, 255, 255, 0.5); display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.18s ease; }
.tcard.tsoon:hover .soonveil,
.tcard.tsoon:focus-within .soonveil { opacity: 1; }
.soonlbl { background: var(--k); color: var(--w); font-size: 11px; font-weight: 900; letter-spacing: 0.16em; text-transform: uppercase; padding: 9px 16px; white-space: nowrap; }
/* Touch has no hover, so there the veil is simply always on. */
@media (hover: none) { .soonveil { opacity: 1; } }

/* ── the questions ──────────────────────────────────────────────────────
   A <details> accordion rather than a wall of text: twenty-six answers is a
   lot to scroll past on the way to the enquiry form, and a parent is looking
   for exactly one of them. Native <details> opens without JavaScript, the
   browser's own find-in-page reaches inside it, and it is keyboard accessible
   with nothing from us. */
.wonder-birthdays .faq { padding: 46px 0 0; }
.wonder-birthdays .faq > h2 { font-size: clamp(24px, 3.4vw, 36px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.08; color: var(--k); }
.wonder-birthdays .faq .lede { font-size: 13px; line-height: 1.6; color: #333; margin: 8px 0 0; max-width: 520px; }
.wonder-birthdays .faqgrp { margin-top: 30px; }
.wonder-birthdays .faqgrp > h3 { font-size: 10px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--k); border-bottom: 2px solid var(--k); padding-bottom: 7px; margin: 0 0 2px; }
.wonder-birthdays .faq details { border-bottom: 1px solid #e0e0e0; }
.wonder-birthdays .faq details:last-child { border-bottom: none; }
.wonder-birthdays .faq summary { list-style: none; cursor: pointer; padding: 13px 34px 13px 0; position: relative; font-size: 14px; font-weight: 800; color: var(--k); line-height: 1.35; }
.wonder-birthdays .faq summary::-webkit-details-marker { display: none; }
/* A plus that becomes a minus, drawn with two rules rather than a glyph so it
   lines up with the 2px the rest of the page is built from. */
.wonder-birthdays .faq summary::before, .wonder-birthdays .faq summary::after { content: ""; position: absolute; right: 6px; background: var(--k); transition: transform 0.16s ease, opacity 0.16s ease; }
.wonder-birthdays .faq summary::before { top: 50%; width: 13px; height: 2px; margin-top: -1px; }
.wonder-birthdays .faq summary::after { top: 50%; right: 11px; width: 2px; height: 13px; margin-top: -6.5px; }
.wonder-birthdays .faq details[open] summary::after { transform: rotate(90deg); opacity: 0; }
.wonder-birthdays .faq .a { font-size: 13.5px; line-height: 1.65; color: #333; padding: 0 34px 16px 0; max-width: 660px; }
@media (prefers-reduced-motion: reduce) { .faq summary::before, .wonder-birthdays .faq summary::after { transition: none; } }

/* ── the enquiry form ───────────────────────────────────────────────────
   Wider than a hand-built form would need: Typeform wants room, and below
   about 640px its one-question-at-a-time layout starts to feel cramped. */
.form { max-width: 880px; margin: 44px auto 0; border: 2px solid var(--k); padding: 36px; }
.form h2 { font-size: 26px; font-weight: 900; letter-spacing: -0.01em; color: var(--k); line-height: 1.1; }
.form .lede { font-size: 13px; color: var(--muted); margin-top: 8px; }
@media (max-width: 640px) { .form { padding: 24px; } }

/* The form is Typeform's; the 2px frame is ours. The slot owns a DEFINITE
   height so the embed has something to measure itself against — a container
   with no height, or display:none, makes Typeform render into nothing.

   White ground, because the embed runs at opacity 0 and this is the colour the
   form actually sits on. No border of its own: it already sits inside the
   section's 2px frame, and Typeform draws a progress rule at its own top edge.
   Two lines a few pixels apart read as a mistake. */
.tf-slot { margin-top: 22px; position: relative; height: 400px; background: var(--w); }
/* The phone's way in, hidden wherever the embed works. See the phone section
   at the end of this file. */
.tf-phone { display: none; }
.tf-widget { position: absolute; inset: 0; }

/* The WRAPPER has to be stretched, not just the iframe.
   Typeform inserts `div.tf-v1-widget` around its iframe and gives it a 150px
   default height, so `height: 100%` on the iframe alone resolves against 150px
   and the form renders as a 150px letterbox inside a 400px frame. The mock has
   this same rule and the same bug; it never showed there because the embed is
   blocked in a file:// preview, so the form never loaded to be too short.
   `> *` rather than the class name, because that class is Typeform's to
   rename. */
.tf-widget > * { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }
.tf-widget iframe { width: 100% !important; height: 100% !important; border: 0; display: block; }
@media (max-width: 640px) { .tf-slot { height: 380px; } }

/* Opaque, so it covers rather than sits behind. */
.tf-fallback { position: absolute; inset: 0; z-index: 2; background: var(--wp--preset--color--field); display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 40px 28px; gap: 14px; }
.tf-fallback[hidden] { display: none; }
.tf-fallback .lbl { font-size: 10px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }
.tf-fallback h3 { font-size: 22px; font-weight: 900; letter-spacing: -0.01em; line-height: 1.15; color: var(--k); max-width: 22ch; }
.tf-fallback p { font-size: 13px; line-height: 1.6; color: var(--muted); max-width: 44ch; }

/* ============================================================================
   MEMBERSHIP
   Ported from `09-membership.html`.

   Scoped to `.wonder-membership` more tightly than the other sections, because
   this page's FAQ and the Birthdays page's FAQ are different components that
   happen to share a class name — one uses ± drawn from two rules, the other a
   plus glyph on a 2px rule — and unscoped they overwrite each other.
   ========================================================================= */

.wonder-membership .mast { padding: var(--mast-top) 0 26px; }

/* The badge sits beside the headline, on the right. It is already drawn at a
   tilt in the artwork, so nothing is rotated here — a CSS rotation on top of
   that would read as a mistake.

   340px is a ceiling, not a preference. The longest of the three headlines is
   "Upper West Side, NYC" at 754px, the band is 1136, and the gap is 28:
   754 + 28 + 340 = 1122, leaving 14px. 350 puts that headline onto a second
   line. Measured in a browser with no Helvetica Neue, where the fallback sets
   WIDER than the real font — so the true slack on a Mac is bigger, which is
   the direction the uncertainty needs to run for 14px to be acceptable. */
.wonder-membership .mast-row { display: flex; align-items: center; gap: 28px; }
.wonder-membership .mast-copy { flex: 1; min-width: 0; }
.wonder-membership .m-logo { flex: none; width: 340px; height: auto; display: block; }

/* THE LOCATION MARK IS SIZED BY HEIGHT, AND THE WORDMARK BY WIDTH.
   Joey, 25 Sep: the Statue of Liberty for Battery Park, the sailboat for
   Westport. They are not the same shape as the thing they replace — the
   wordmark is landscape at 700x472, the statue is a tall cut-out at 410x1496.
   Through `.m-logo`'s `width: 340px` that statue renders **1,240 pixels tall**
   and takes the masthead with it. Capping the height instead lets two very
   different silhouettes stand beside the headline at the same visual weight,
   and `max-width` catches any future mark that is wide rather than tall. */
.wonder-membership .m-mark {
	flex: none;
	/* A FIXED BOX, and the artwork centred inside it. The statue is 71px wide
	   and the sailboat 200; left to size themselves they would sit at two
	   different places on the page. A common box plus `object-fit: contain`
	   gives both the same centre line whatever their silhouette. */
	width: 300px;
	height: 260px;
	object-fit: contain;
	display: block;

	/* CENTRED OVER THE BLACK KEY CARD, not hard right. Joey, 25 Sep: "directly
	   above the No Initiation Fee bar". That bar is centred on the second of
	   two equal cards, so its centre sits half a card width in from the right
	   edge — `(100% - gap) / 4` — and the box's own half-width comes off that.
	   Written against the grid rather than as a measured 145px so it holds as
	   the column narrows, instead of drifting apart from the thing it is
	   supposed to line up with. */
	margin-right: calc((100% - 20px) / 4 - 150px);
}
@media (max-width: 820px) { .wonder-membership .m-mark { display: none; } }
/* Below 820 there is no room beside a headline, and stacking a landscape
   wordmark above the eyebrow reads as a second page header. It goes — the same
   mark is in the top bar on every page, so nothing is lost. */
@media (max-width: 820px) { .wonder-membership .m-logo { display: none; } }

/* `text-wrap: balance` is for the chooser's headline, the only one here that
   runs to two lines. Without it the break falls wherever the column ends,
   leaving "An absurdly playful space for" over "families." — a full line and a
   stub. The three location headlines are single lines and are unaffected. */
.wonder-membership .mast h1 {
	font-size: clamp(40px, 6vw, 74px);
	font-weight: 900;
	letter-spacing: -0.02em;
	line-height: 0.98;
	color: var(--k);
	margin-top: 12px;
	text-wrap: balance;
}
.wonder-membership .mast .dek { font-size: 15px; line-height: 1.65; color: var(--body); max-width: 620px; margin-top: 16px; }

/* ── "Which Wonder?" — the choose-a-location gate ────────────────────────────
   ONE COMPONENT, SEVEN PAGES. It was the Membership page's alone until 25 Sep
   2026, when Joey asked for it on every nav page that varies by location: "when
   I go to locations page there is NOTHING if i haven't selected a location yet,
   and if I go to birthdays, it seems to default to UWS details." The markup is
   rendered by `inc/location-gate.php` in the plugin.

   THE NAME IS PREFIXED, AND THAT IS THE WHOLE POINT. `.gate` already meant two
   different things — these cards and the HOME page's horizontal band under the
   hero — and the comment that used to live here recorded what that cost:
   unscoped, this rule's `display: grid` collapsed Home's gate to its border and
   floated its buttons over the hero. A third component sharing the name would
   have been collision number eleven, so the shared version is `.wonder-gate`
   and its children carry names of their own rather than the old generic ones.

   One rule was STILL unscoped right up to the rename — a max-width 760px
   override on the bare name — and it reached Home's gate as well. It did
   nothing only because Home's gate is a flex container, so a grid property had
   nothing to apply to. Luck, not design, and now gone.

   ── the location question ──────────────────────────────────────────────
   v6 opened with a three-way gate. The header picker replaces it as a control
   but NOT as a question: on Membership the two tier families sell genuinely
   different products, so a wrong default is worse than no default. That was the
   argument for making this page the exception. It turned out to be the argument
   for making it the rule. Links rather than buttons, so each choice is a real
   URL.

   AUTO-FIT, NOT `repeat(3, 1fr)`. Camps runs at two clubs, not three, and a
   fixed three-column grid left it a hole. With three cards the computed result
   is identical, which is why the Membership page is unchanged to the pixel. */
.wonder-gate { border: 2px solid var(--k); padding: 34px; margin-top: 34px; }
/* A bottom margin only when something follows. On Membership, Camps and Gift
   Cards the gate is the last thing in the block and must not add height; on
   Classes, FAQs and Birthdays there is a page below it to clear. */
.wonder-gate:not(:last-child) { margin-bottom: 30px; }
.wonder-gate .eyebrow { color: var(--faint); }
.wonder-gate h2 { font-size: clamp(22px, 3vw, 32px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.06; color: var(--k); margin-top: 10px; }
/* No measure cap here: this paragraph sits inside a full-width box and a 56ch
   limit stopped it a third of the way along. Joey, 15 Sep. */
.wonder-gate p { font-size: 15px; line-height: 1.6; color: var(--muted); margin-top: 12px; max-width: none; }
.wonder-gate .gopts { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; margin-top: 24px; }
@media (max-width: 760px) { .wonder-gate .gopts { grid-template-columns: 1fr; } }
.wonder-gate .gopts a { border: 2px solid var(--k); background: var(--w); padding: 18px 18px 16px; text-align: left; cursor: pointer; font-family: inherit; display: block; text-decoration: none; }
.wonder-gate .gopts a:hover { background: var(--signal); }
.wonder-gate .gname { display: block; font-size: 15px; font-weight: 900; letter-spacing: -0.01em; color: var(--k); }
.wonder-gate .gnote { display: block; font-size: 10px; font-weight: 900; letter-spacing: 0.12em; text-transform: uppercase; color: var(--faint); margin-top: 6px; }
.wonder-gate .gopts a.equinox { border-color: var(--wp--preset--color--equinox); }
.wonder-gate .gopts a.equinox .gnote { color: var(--wp--preset--color--equinox); }

/* ── the Key ladder ─────────────────────────────────────────────────── */
.plans { display: grid; gap: 20px; padding: 30px 0 4px; }
.plans.two { grid-template-columns: 1fr 1fr; }
@media (max-width: 720px) { .plans.two { grid-template-columns: 1fr; } }
.plan { border: 2px solid var(--k); padding: 28px; display: flex; flex-direction: column; position: relative; background: var(--w); }
.plan.lead { border-width: 4px; }
/* THE KEY MARK, in the room the price row was already leaving empty.
   Joey, 24 Sep: "neatly fill that space but not make the container any
   bigger." So the head is a row rather than a new band, and the mark is
   sized to come in UNDER the natural height of the name-price-note stack
   beside it — the card ends up exactly as tall as it was.

   It goes away between 721 and 860px, the one band where the cards are
   still side by side but narrow enough that the mark would squeeze the
   price note onto an extra line. Below 721 they stack full-width and there
   is room again. */
.plan-head { display: flex; align-items: center; gap: 18px; }
.plan-headtext { flex: 1 1 auto; min-width: 0; }
.plan-key { flex: 0 0 auto; width: clamp(88px, 25%, 128px); height: auto; }
@media (max-width: 860px) and (min-width: 721px) { .plan-key { display: none; } }
.plan-name { font-size: 13px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--k); }
.price { font-size: 40px; font-weight: 900; line-height: 1; color: var(--k); margin-top: 14px; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.price small { font-size: 14px; font-weight: 800; letter-spacing: 0; }
.price-note { font-size: 11.5px; line-height: 1.5; color: var(--muted); margin-top: 8px; }
.plan ul { list-style: none; margin: 20px 0 22px; padding: 0; border-top: 2px solid var(--k); }
.plan li { font-size: 13px; line-height: 1.5; padding: 8px 0; border-bottom: 1px solid #e8e8e8; color: #333; }
.plan li:last-child { border-bottom: none; }
.plan li b { color: var(--k); font-weight: 800; }
.plan .cta { margin-top: auto; }
.plan .btn { width: 100%; text-align: center; }
.fineprint { font-size: 12px; line-height: 1.6; color: var(--muted); margin-top: 18px; max-width: 70ch; }
.fineprint b { color: var(--k); }

/* ── shared card furniture ──────────────────────────────────────────── */
.was { color: var(--faint); text-decoration: line-through; text-decoration-thickness: 2px; font-weight: 800; }
.save { display: inline-block; background: var(--signal); color: var(--k); font-size: 10px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; padding: 3px 9px; }

/* ── the presale: base + add-ons ────────────────────────────────────── */
.uwsplans { margin-top: 4px; }
.base { border: 4px solid var(--k); padding: 30px 32px; margin-top: 30px; display: grid; grid-template-columns: 1.5fr 1fr; gap: 24px 36px; align-items: center; }
@media (max-width: 820px) { .base { grid-template-columns: 1fr; } }
.base .nm { font-size: 13px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--k); }
.base h3 { font-size: clamp(22px, 3vw, 30px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.1; color: var(--k); margin-top: 8px; }
.base .desc { font-size: 13.5px; line-height: 1.6; color: var(--muted); margin-top: 10px; max-width: 48ch; }
.base .pricebox { text-align: right; }
@media (max-width: 820px) { .base .pricebox { text-align: left; } }
.base .big { font-size: clamp(40px, 6vw, 62px); font-weight: 900; line-height: 1; color: var(--k); letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.base .big .was { font-size: 0.42em; margin-right: 12px; letter-spacing: -0.01em; }
.base .big small { font-size: 0.28em; font-weight: 800; letter-spacing: 0; }
.base .init { font-size: 12.5px; color: var(--muted); margin-top: 10px; }
.base .init b { color: var(--k); }
/* The membership on its own is buyable — you do not have to add drop-off to
   join. Outlined rather than solid, because the emphasis still belongs on the
   add-on cards. Joey, 15 Sep. */
.base .basecta { margin-top: 18px; }
.base .basecta .btn { display: inline-block; }
@media (max-width: 820px) { .base .basecta .btn { width: 100%; text-align: center; } }

/* Reversed out and bigger than a caption, 17 Sep. At 11px grey-on-white it
   read as a label on the rule rather than the hinge of the whole page, which
   is what it is: everything above is the membership, everything below is what
   you add to it. */
.plusrow { display: flex; align-items: center; gap: 16px; margin: 30px 0 26px; }
.plusrow .line { flex: 1; border-top: 2px solid var(--k); }
.plusrow .word { font-size: 15px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--w); background: var(--k); padding: 9px 18px; white-space: nowrap; }
@media (max-width: 520px) {
	.plusrow { gap: 10px; }
	.plusrow .word { font-size: 12px; padding: 7px 12px; letter-spacing: 0.08em; }
}

.dropintro { font-size: clamp(20px, 2.7vw, 28px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.2; color: var(--k); margin: 4px auto 30px; text-align: center; text-wrap: balance; }
.addgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
@media (max-width: 820px) { .addgrid { grid-template-columns: 1fr; } }
.add { border: 2px solid var(--k); padding: 26px; display: flex; flex-direction: column; position: relative; }
.add.lead { border-width: 4px; }
/* An icon, not hero art. Joey, 24 Sep: "they should feel like icons above,
   not huge", then "right orientation but NEXT to the x drop-offs a month".
   So the drop-off line and its cadence become a column and the mark takes
   the end of that row — the same arrangement as the Key ladder's cards, so
   the two kinds of membership page read as one family.

   `align-self` is doing real work on `.add-key`: `.add` is a COLUMN flex
   container, and before this row existed a child with no cross-axis
   alignment stretched to the card's full width — a stretched replaced
   element ignores its own aspect ratio and renders 332px wide instead of
   57px. Inside `.add-head` the axis is horizontal, so `flex: 0 0 auto` is
   what holds the shape, and `center` is vertical alignment against the two
   lines of text. */
.add-head { display: flex; align-items: center; gap: 14px; }
.add-headtext { flex: 1 1 auto; min-width: 0; }
.add-key { flex: 0 0 auto; align-self: center; width: auto; height: 44px; }
/* BESIDE THE LABEL NEEDS ABOUT 1100px, and below that the mark takes the
   room "12 drop-offs a month" needs to stay on one line — measured, not
   guessed: with the mark hidden the label is one line at 900px and two
   with it. Joey, 24 Sep: "can the icon be above? so it doesn't scrunch
   the text?" So below 1100 the row becomes a stack and the mark crowns
   the card, centred, which is where it started. The label gets the whole
   width back at every size where it was losing it. */
@media (max-width: 1100px) {
	/* `column-reverse`, not `column`, and not `display: block`: the mark comes
	   AFTER the text in the markup, because that is what puts it on the right
	   in the row. Stacking it the obvious way would therefore put it under the
	   label rather than over it. Reversing the column lifts it back on top
	   without touching the markup, and `align-self: center` above is already
	   the horizontal centring once the axis turns. */
	.add-head { flex-direction: column-reverse; }
	.add-key { margin-bottom: 14px; }
}
.add .sessions { font-size: 13px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--k); }
.add .per { font-size: 11.5px; color: var(--muted); margin-top: 4px; }
/* The ADD-ON price is the hero: a family is buying three drop-offs for fifty
   dollars, not a $249 membership. The total is the small number. */
.add .plus { font-size: 52px; font-weight: 900; line-height: 1; color: var(--k); margin-top: 18px; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.add .plus span { font-size: 0.42em; vertical-align: 0.32em; }
.add .permo { font-size: 11px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--faint); margin-top: 8px; }
.add .total { font-size: 12.5px; color: var(--muted); margin-top: 14px; padding-top: 12px; border-top: 2px solid var(--k); }
.add .total b { font-size: 17px; font-weight: 900; color: var(--k); }
/* The tier name sits in the total line at the size of the money rather than
   the caption around it, so it reads as part of what you are buying. */
.add .total .tiername { font-size: 13.5px; letter-spacing: 0.02em; }
.add .total .was { font-size: 12px; }
.add .total .save { margin-top: 8px; }
.add .cta { margin-top: auto; padding-top: 20px; }
.add .btn { width: 100%; text-align: center; }

/* The badge belongs to both card kinds, and to the Birthdays ribbon's sibling
   on this page only — the Birthdays page uses `.ribbon` for its own. */
.wonder-membership .badge {
	position: absolute;
	top: -14px;
	left: 50%;
	transform: translateX(-50%);
	background: var(--k);
	color: var(--w);
	font-size: 9.5px;
	font-weight: 900;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	padding: 5px 14px;
	white-space: nowrap;
}

/* ── the billing switch ─────────────────────────────────────────────────
   It renders TWICE — once above the base card, once between the base card and
   the drop-off tiers — so a family comparing add-ons can switch cadence
   without scrolling back up. Both read the same state, so there is no such
   thing as one being out of step with the other. */
.billsw { display: flex; justify-content: center; margin: 30px 0 0; }
.billsw .seg { display: inline-flex; border: 3px solid var(--k); }
.billsw button { border: none; background: var(--w); color: var(--k); font-family: inherit; font-size: 13px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; padding: 13px 30px; cursor: pointer; border-right: 3px solid var(--k); }
.billsw button:last-child { border-right: none; }
.billsw button:hover { background: var(--signal); }
.billsw button[aria-pressed="true"] { background: var(--k); color: var(--w); }
.billsw button[aria-pressed="true"]:hover { background: var(--k); color: var(--signal); }
@media (max-width: 520px) { .billsw button { padding: 12px 18px; font-size: 12px; } }
/* The second instance takes the plus rule's old job: separating the
   membership from the things you add to it. */
.billsw.mid { margin: 4px 0 22px; }

/* ── the scarcity band ──────────────────────────────────────────────── */
/* `auto` on the second track, so with the counter gone the copy takes the
   whole band instead of sitting in a half-width column beside nothing. The
   counter is off by decision — see wonder_uws_spots() — and these rules stay
   for the day a real number can feed it. */
.scarce { border: 2px solid var(--k); background: var(--k); color: var(--w); padding: 26px 28px; margin-top: 34px; display: grid; grid-template-columns: 1fr auto; gap: 18px 30px; align-items: center; }
@media (max-width: 820px) { .scarce { grid-template-columns: 1fr; } }
.scarce .kicker { font-size: 10px; font-weight: 900; letter-spacing: 0.16em; text-transform: uppercase; color: var(--signal); }
.scarce h2 { font-size: clamp(22px, 3.2vw, 34px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.04; margin-top: 9px; }
.scarce p { font-size: 13.5px; line-height: 1.6; color: #ddd; margin-top: 10px; max-width: 60ch; }
.scarce p b { color: var(--w); }
/* The tiger stands where the counter would, and only when there is no counter
   — see `wonder_membership_scarcity()`. Landscape at 1030x398, so it is capped
   by width; the pale outline it is drawn with is what keeps it off the black
   rather than any treatment here. */
.scarce .tiger { width: 320px; max-width: 100%; height: auto; display: block; }
@media (max-width: 820px) { .scarce .tiger { width: 240px; margin: 0 auto; } }

.counter { border: 2px solid var(--signal); padding: 14px 18px; text-align: center; flex: none; }
.counter .n { font-size: 34px; font-weight: 900; line-height: 1; color: var(--signal); font-variant-numeric: tabular-nums; }
.counter .t { font-size: 9px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: #ccc; margin-top: 7px; }

/* ── the honest math ────────────────────────────────────────────────── */
.math { border: 2px solid var(--k); padding: 34px; margin-top: 46px; }
.math-head { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; align-items: end; }
@media (max-width: 900px) { .math-head { grid-template-columns: 1fr; align-items: start; } }
.math-head h2 { font-size: clamp(22px, 3vw, 34px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.06; color: var(--k); margin-top: 8px; }
.math-head p { font-size: 13.5px; line-height: 1.6; color: var(--muted); }
.figure { margin-top: 28px; }
.fig-cap { font-size: 10px; font-weight: 900; letter-spacing: 0.12em; text-transform: uppercase; color: var(--faint); margin-bottom: 12px; }
.plot { position: relative; height: 230px; display: grid; grid-template-columns: repeat(12, 1fr); gap: 6px; align-items: end; border-bottom: 2px solid var(--k); }
/* The line a year of Black Key draws across the chart; everything above it is
   money a Gold family has spent past the annual price. Its height comes from
   the same arithmetic as the bars, through a custom property, so a price
   change moves the line and the bars together. */
.thresh { position: absolute; left: 0; right: 0; bottom: var(--thresh, 52.79%); border-top: 2px dashed var(--k); pointer-events: none; }
.thresh span { position: absolute; right: 0; top: -20px; font-size: 9.5px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; background: var(--w); padding: 2px 6px; color: var(--k); }
.thresh span.short { display: none; }
@media (max-width: 640px) {
	.thresh span.long { display: none; }
	.thresh span.short { display: inline; }
}
.wonder-membership .bar { position: relative; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; }
.seg-base { background: var(--k); }
.seg-over { background: var(--signal); border: 2px solid var(--k); border-bottom: none; }
.wonder-membership .bar .tip { position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); margin-bottom: 8px; background: var(--k); color: var(--w); font-size: 11px; padding: 6px 10px; white-space: nowrap; opacity: 0; transition: opacity 0.12s; pointer-events: none; z-index: 3; }
.wonder-membership .bar:hover .tip { opacity: 1; }
/* A nowrap tooltip on the rightmost bar measures 185px and is centred on a
   segment near the edge, so it reaches 392 in a 390 viewport: two pixels of
   sideways scroll on a page nobody can even trigger the tooltip on, because
   there is no hover on a phone. It goes there rather than being clamped —
   clamping would leave an invisible element still deciding the page width. */
@media (hover: none) { .wonder-membership .bar .tip { display: none; } }
.axis { display: grid; grid-template-columns: repeat(12, 1fr); gap: 6px; margin-top: 8px; }
.axis span { font-size: 9.5px; font-weight: 800; color: var(--faint); text-align: center; }
.axis span.mark { color: var(--k); }
.callouts { display: grid; grid-template-columns: 1fr 1fr; margin-top: 28px; border: 2px solid var(--k); }
@media (max-width: 640px) { .callouts { grid-template-columns: 1fr; } }
.callout { padding: 20px 22px; border-right: 2px solid var(--k); }
.callout:last-child { border-right: none; }
@media (max-width: 640px) {
	.callout { border-right: none; border-bottom: 2px solid var(--k); }
	.callout:last-child { border-bottom: none; }
}
.callout dt { font-size: 10px; font-weight: 900; letter-spacing: 0.12em; text-transform: uppercase; color: var(--faint); }
.callout dd { font-size: 13px; line-height: 1.5; color: #333; margin: 8px 0 0; }
.callout dd b { font-size: 26px; font-weight: 900; color: var(--k); display: block; margin-bottom: 4px; font-variant-numeric: tabular-nums; }
.numbers { margin-top: 22px; }
.numbers summary { font-size: 10.5px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; cursor: pointer; color: var(--k); border-bottom: 2px solid var(--k); padding-bottom: 7px; }
.numbers table { width: 100%; border-collapse: collapse; margin-top: 14px; }
.numbers th { font-size: 9.5px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; text-align: left; color: var(--faint); padding: 8px 10px 8px 0; border-bottom: 2px solid var(--k); }
.numbers td { font-size: 13px; padding: 7px 10px 7px 0; border-bottom: 1px solid #eee; font-variant-numeric: tabular-nums; color: #333; }
.numbers tr.cross td { font-weight: 900; color: var(--k); background: var(--signal); }
.verdict { font-family: var(--wonder-display); font-size: 22px; line-height: 1.3; color: var(--k); margin-top: 26px; }

/* ── the drop-off explainer ─────────────────────────────────────────── */
.howmuch { display: grid; grid-template-columns: repeat(3, 1fr); border: 2px solid var(--k); margin-top: 34px; }
@media (max-width: 860px) { .howmuch { grid-template-columns: 1fr; } }
.howmuch > div { padding: 22px 24px; border-right: 2px solid var(--k); }
.howmuch > div:last-child { border-right: none; }
@media (max-width: 860px) {
	.howmuch > div { border-right: none; border-bottom: 2px solid var(--k); }
	.howmuch > div:last-child { border-bottom: none; }
}
.howmuch dt { font-size: 10px; font-weight: 900; letter-spacing: 0.12em; text-transform: uppercase; color: var(--k); }
.howmuch dd { font-size: 13px; line-height: 1.55; color: #333; margin: 9px 0 0; }

/* ── the waitlist band ──────────────────────────────────────────────── */
.join { border: 2px solid var(--k); background: var(--k); color: var(--w); padding: 38px; margin-top: 46px; display: flex; align-items: center; justify-content: space-between; gap: 22px; flex-wrap: wrap; }
.join h2 { font-size: clamp(22px, 3vw, 32px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.06; }
.join p { font-size: 13.5px; line-height: 1.6; color: #ddd; max-width: 46ch; margin-top: 10px; }
.join .btn { background: var(--signal); color: var(--k); border-color: var(--signal); flex: none; }
.join .btn:hover { opacity: 1; background: var(--w); border-color: var(--w); }

/* ── the FAQ ────────────────────────────────────────────────────────────
   A different component from the Birthdays FAQ despite the class name: heavier
   rules, a glyph rather than two drawn bars, and the first answer open. Both
   are scoped so neither can reach the other. */
.wonder-membership .faq { margin-top: 46px; }
.wonder-membership .faq > h2 { font-size: clamp(22px, 3vw, 34px); font-weight: 900; letter-spacing: -0.01em; color: var(--k); border-bottom: 2px solid var(--k); padding-bottom: 14px; }
.wonder-membership .faq details { border-bottom: 2px solid var(--k); }
.wonder-membership .faq summary { list-style: none; cursor: pointer; padding: 16px 0; font-size: 15.5px; font-weight: 800; color: var(--k); display: flex; justify-content: space-between; gap: 16px; align-items: baseline; }
.wonder-membership .faq summary::-webkit-details-marker { display: none; }
.wonder-membership .faq summary::after { content: '+'; font-weight: 900; font-size: 19px; line-height: 1; flex: none; }
.wonder-membership .faq details[open] summary::after { content: '\2013'; }
.wonder-membership .faq p { font-size: 13.5px; line-height: 1.65; color: var(--body); padding: 0 0 18px; max-width: 66ch; }
.wonder-membership .faq p + p { padding-top: 0; }

/* ============================================================================
   HOME
   Ported from `04-home.html`.

   This page reuses the quote band from Birthdays and the awning from Camps.
   Only its differences are written down; the shared rules live above.
   ========================================================================= */

/* The page is the block, so it spans the viewport and re-constrains its own
   bands. The hero, the gate, the press band, the wayfinding strip, the
   announcement and the awning are full-bleed by design; everything else sits
   inside `.wrap`. */
.wonder-home { max-width: none; width: 100%; }
.wonder-home .wrap { max-width: 1200px; margin: 0 auto; padding: 0 32px; }
@media (max-width: 640px) { .wonder-home .wrap { padding: 0 18px; } }

/* ── the hero ───────────────────────────────────────────────────────────
   Autoplaying motion that runs past five seconds needs a way to stop it
   (WCAG 2.2.2), which is what `.vidctl` is for. */
.wonder-home .hero {
	position: relative;
	border-bottom: 2px solid var(--k);
	background: var(--wp--preset--color--field);
	height: min(600px, 78vh);
	overflow: hidden;
}
.wonder-home .hero video,
.wonder-home .hero .still { width: 100%; height: 100%; object-fit: cover; display: block; }
.wonder-home .hero .still { display: none; }
.wonder-home .hero .still.only { display: block; }
.hero-overlay {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 44px 32px;
	background: linear-gradient(transparent, rgba(0, 0, 0, 0.55));
	display: flex;
	justify-content: space-between;
	align-items: flex-end;
	gap: 20px;
	flex-wrap: wrap;
}
.hero-overlay h1 {
	font-size: clamp(40px, 6vw, 74px);
	font-weight: 900;
	letter-spacing: -0.02em;
	line-height: 0.98;
	color: var(--w);
	text-shadow: 0 2px 20px rgba(0, 0, 0, 0.3);
}
.hero-ctas { display: flex; gap: 14px; flex-wrap: wrap; }
@media (max-width: 640px) { .hero-overlay { padding: 24px 18px; } }

.vidctl {
	position: absolute;
	top: 18px;
	right: 18px;
	z-index: 3;
	border: 2px solid var(--w);
	background: rgba(0, 0, 0, 0.45);
	color: var(--w);
	font-family: inherit;
	font-size: 10px;
	font-weight: 900;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	padding: 8px 14px;
	cursor: pointer;
}
.vidctl:hover { background: var(--w); color: var(--k); }

/* Reduced motion stops both clips and keeps their poster frames. Hiding the
   <video> hides its `poster` attribute with it, which is why the Wonderbox
   frame carries the same still as a background-image INLINE — an inline style
   beats this shorthand, and a var() inside a shorthand would not work at all:
   a substitution that makes the shorthand invalid discards the whole
   declaration, black included. */
@media (prefers-reduced-motion: reduce) {
	.wonder-home .hero video { display: none; }
	.wonder-home .hero .still { display: block; }
	.wonder-home .vidctl { display: none; }
	.wonderbox video { display: none; }
	.wonderbox .ph { background: var(--k) center / cover no-repeat; }
}

/* ── the gate ───────────────────────────────────────────────────────────
   Not a modal. An interstitial before anyone has seen anything is a bounce
   risk and counts against mobile ranking. Once answered it stops being a
   question and becomes a quiet line. */
.wonder-home .gate { border-bottom: 2px solid var(--k); background: var(--wp--preset--color--field); }
.wonder-home .gate .inner {
	max-width: 1200px;
	margin: 0 auto;
	padding: 24px 32px;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 18px;
	flex-wrap: wrap;
}
.wonder-home .gate .q { font-size: 15px; font-weight: 900; letter-spacing: -0.01em; color: var(--k); }
.wonder-home .gate .opts { display: flex; gap: 10px; flex-wrap: wrap; }
.wonder-home .gate .opts button {
	border: 2px solid var(--k);
	background: var(--w);
	color: var(--k);
	font-family: inherit;
	font-size: 11px;
	font-weight: 900;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	padding: 11px 20px;
	cursor: pointer;
}
.wonder-home .gate .opts button:hover { background: var(--signal); }
.wonder-home .gate .opts button small {
	display: block;
	font-size: 8.5px;
	font-weight: 700;
	letter-spacing: 0.06em;
	color: var(--muted);
	margin-top: 2px;
	text-transform: none;
}
.wonder-home .gate.chosen { background: var(--w); }
.wonder-home .gate.chosen .inner { padding: 11px 32px; justify-content: flex-start; gap: 10px; }
.wonder-home .gate.chosen .q { font-size: 11px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }
.wonder-home .gate.chosen .opts button { padding: 6px 12px; font-size: 9.5px; }

/* ── the press band ─────────────────────────────────────────────────────
   ONE band, not two. An earlier version gave the claim its own bordered band
   and the page gained a third horizontal rule inside forty pixels. The rules
   flanking it are v6's logo-tick device — it says "statement" without costing
   another band, and lets the type come down to 30px from 38. */
.press { padding: 42px 20px 28px; border-bottom: 2px solid var(--k); text-align: center; }
.press-tick { display: flex; align-items: center; justify-content: center; gap: 24px; max-width: 900px; margin: 0 auto 30px; }
/* `0 1 72px` rather than a fixed width: on a phone 144px of rule plus 48px of
   gap would leave the line about 220px to live in, so the rules give way first
   and the words keep the room. */
.press-tick .r { flex: 0 1 72px; min-width: 18px; height: 2px; background: var(--k); }
.press-claim { margin: 0; font-size: clamp(19px, 2.4vw, 30px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.04; color: var(--k); text-wrap: balance; }
.press-marks { display: flex; gap: 44px; justify-content: center; align-items: center; flex-wrap: wrap; }
.press .lbl { font-size: 10px; font-weight: 700; letter-spacing: 0.16em; color: var(--faint); text-transform: uppercase; }
/* Heights are set PER MARK, not shared. Domino is a lowercase wordmark at 5:1
   while Forbes and Bazaar are 4:1 with caps, so a single height makes one of
   them shout and another vanish. Matched by eye on cap height, which is what
   the eye actually reads. */
.press img { width: auto; display: block; opacity: 0.92; height: auto; }
.press img.harpers { height: 30px; }
.press img.domino { height: 20px; }
.press img.forbes { height: 23px; }
@media (max-width: 640px) {
	.press { padding: 32px 18px 24px; }
	.press-tick { gap: 14px; margin-bottom: 24px; }
	.press-marks { gap: 26px; }
}

/* ── the three cards ────────────────────────────────────────────────────
   EVERY grid on this page uses minmax(0, 1fr), not 1fr. `1fr` is
   `minmax(auto, 1fr)` and the auto minimum is the IMAGE's intrinsic width, so
   three 1024px photographs demanded a 3072px row and pushed the page 600px
   past the viewport. The mock documents the same trap for .wonderbox.wide;
   it applies to all of them.

   7:6 rather than a landscape band. Two of the three photographs are portrait
   and a wide frame was throwing most of them away; this keeps about 70% of the
   original height instead of half, without going full portrait and pushing the
   copy off the screen. */
.cards3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; padding: 56px 0; }
.vcard { border: 2px solid var(--k); background: var(--w); }
.vcard .ph { aspect-ratio: 7 / 6; border-bottom: 2px solid var(--k); }
.vcard-body { padding: 20px; }
.vcard-body h3 { font-size: 18px; font-weight: 900; margin-bottom: 8px; color: var(--k); }
.vcard-body p { font-size: 13px; line-height: 1.6; color: #333; }

.wonder-home .ph { position: relative; overflow: hidden; background: var(--wp--preset--color--field); display: flex; align-items: center; justify-content: center; }
.wonder-home .ph img, .wonder-home .ph video { width: 100%; height: 100%; object-fit: cover; display: block; }

.wayband { border-top: 2px solid var(--k); border-bottom: 2px solid var(--k); background: var(--k); display: flex; justify-content: center; gap: 52px; padding: 13px 20px; flex-wrap: wrap; }
.wayband a { color: var(--w); font-size: 11px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; text-decoration: none; }
.wayband a:hover { color: var(--signal); }

/* ── membership and birthdays ───────────────────────────────────────────
   This one photograph keeps its own proportions: the box takes its height from
   the picture rather than cropping the picture to a fixed band, so the rule
   that makes every other .ph crop to fill is overridden here. */
.pitch { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 40px; align-items: center; padding: 56px 0; }
.pitch .ph { height: auto; border: 2px solid var(--k); align-self: center; }
.pitch .ph img { width: 100%; height: auto; object-fit: fill; }
.wonder-home .sub { font-size: 15px; line-height: 1.65; color: var(--body); max-width: 560px; margin: 18px 0 26px; }
.wonder-home .sub.small { font-size: 14px; }

/* The odd-looking 1.2915 is not a guess. The membership band puts a 40px gap
   between its columns and this one is a flush frame, so the same 1.2 split
   would leave this photograph 21px wider — this ratio cancels that out and the
   two pictures render at the same size, 494×282 each. Joey, 16 Sep. */
.bday-band { border: 2px solid var(--k); margin: 24px 0 56px; display: grid; grid-template-columns: minmax(0, 1.2915fr) minmax(0, 1fr); }
/* Vertical padding trimmed so the COPY no longer sets the band's height — the
   photograph does, at its own ratio, which is the only way it fills the frame
   with nothing cropped and no white strip underneath. */
.bday-left { padding: 16px 44px; border-right: 2px solid var(--k); display: flex; flex-direction: column; justify-content: center; }
/* `align-self: stretch` matters: the ratio sets the height, but if a narrow
   viewport rewraps the headline and makes the copy taller, the photograph
   grows to meet it and crops a little rather than leaving a white strip under
   itself. A gap reads as broken; a 2% crop reads as nothing. */
.bday-band .ph { min-height: 0; aspect-ratio: 1000 / 571; align-self: stretch; }
.bday-band .ph img { object-position: center; }

/* ── the Wonderbox band ─────────────────────────────────────────────────
   The vertical cut is 4:5, about seven-tenths of the phone frame, because
   everything that matters sits inside that band: the wordmark on the doors,
   the compass, the end card. A wide frame cut all three. */
.wonderbox { border: 2px solid var(--k); margin: 0 0 56px; display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); align-items: stretch; }
.wonderbox-copy { padding: 44px; display: flex; flex-direction: column; justify-content: center; }
.wonderbox .ph { aspect-ratio: 4 / 5; max-height: 640px; border-left: 2px solid var(--k); background: var(--k); }
.wonderbox .ph video { position: absolute; inset: 0; }
.wonderbox .vidctl { top: 14px; right: 14px; padding: 6px 11px; font-size: 9px; }

/* Battery Park's cut is 16:9, so its frame matches the membership and birthday
   bands. Exactly 16:9 — not the 880/496 of the encode, which is a rounding
   artefact of scaling 1080×608 to an even height. The frame states the ratio
   Joey can export to rather than one only ffmpeg would arrive at. */
.wonderbox.wide .ph { aspect-ratio: 16 / 9; max-height: none; max-width: 100%; }
.wonderbox.wide { grid-template-columns: 1.2915fr 1fr; }
/* The padding is the real fix for the right edge. A stretched grid item with
   an aspect ratio takes its width from the ROW height, and the row was 316px
   tall because the copy's 44px of vertical padding made it so — 316 × 1.774 =
   560px of frame in a 494px column, hanging 64px past the end of the band. At
   24px the frame's own ratio sets the height and it resolves to 494 × 278,
   flush with the other two bands. max-width is the guarantee: if the copy
   renders taller than measured, the frame clamps to its column and the video
   crops instead of sticking out. */
.wonderbox.wide .wonderbox-copy { padding: 24px 44px; }
/* Between about 900 and 1200px the 16:9 frame demanded 656px inside a 363px
   column and pushed the page past the viewport. min-width:0, min-height:0 and
   minmax(0,1fr) all leave it at 656 — the used width comes from the ratio, not
   from any minimum. So below 1200 the wide band stacks, which is what it
   already does on a phone. The vertical cut keeps two columns down to 900px,
   where its 640px ceiling stops the same thing happening to it. */
@media (max-width: 1199px) {
	.wonderbox.wide { grid-template-columns: 1fr; }
	.wonderbox.wide .ph { border-left: none; border-top: 2px solid var(--k); }
}

/* 4:5, taller than the square it replaced, because the frames were cutting
   people off at the knees. Not full portrait: at 2:3 the row would dominate
   the page. A centre crop of the three square sources leaves every subject
   intact. Joey, 16 Sep. */
/* `.tour` — the four-across grid the generic frames used to be — is gone.
   They are `.lshot` frames in the shared photograph band now, so they behave
   exactly as a club's own band does: four across on a desk, two and a pair of
   arrows on a phone. Joey, 25 Sep. */

@media (max-width: 900px) {
	.cards3 { grid-template-columns: 1fr; }
	/* `.wonderbox.wide` is two classes, so it outranks a single-class rule
	   whatever the order — without naming it here, Battery Park's band kept
	   two columns on a phone and pushed the page 400px wide. */
	.pitch, .bday-band, .wonderbox, .wonderbox.wide { grid-template-columns: 1fr; }
	.bday-left { border-right: none; border-bottom: 2px solid var(--k); padding: 28px; }
	.wonderbox-copy { padding: 28px; }
	.wonderbox .ph { border-left: none; border-top: 2px solid var(--k); }
}

.announce { border-top: 2px solid var(--k); border-bottom: 2px solid var(--k); text-align: center; padding: 26px 20px; background: var(--wp--preset--color--equinox); }
.announce a { color: var(--w); text-decoration: none; font-size: 15px; font-weight: 900; letter-spacing: 0.12em; text-transform: uppercase; }
.announce a u { text-underline-offset: 4px; }
.announce a:hover u { color: var(--signal); }

/* The quote band is the Birthdays component — same markup, same class names,
   same pausing rules. Only the type scale differs: these are one-liners rather
   than letters from parents, so they carry at 32px where the other band had to
   come down to 21. */
.wonder-home .quotes { padding: 60px 20px 52px; border-bottom: none; }
.wonder-home .qtrack { max-width: 860px; }
.wonder-home .qtrack blockquote { font-size: clamp(22px, 3vw, 32px); line-height: 1.28; }
/* A masthead is not a person: the two are attributed differently. */
.qtrack figcaption.masthead { font-weight: 900; color: var(--k); }

.wonder-home .awning { line-height: 0; margin-top: 0; }
.wonder-home .awning svg { width: 100%; height: 90px; display: block; }

.home-locs { padding-top: 50px; }
.locs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; padding: 26px 0 56px; }
.loc { border: 2px solid var(--k); padding: 26px; display: flex; flex-direction: column; }
.loc h3 { font-size: 21px; font-weight: 900; color: var(--k); }
.loc .addr { font-size: 13px; color: #444; margin: 10px 0 14px; line-height: 1.55; }
.loc .hrs { display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; font-size: 12px; margin: 0 0 20px; flex: 1; align-content: start; font-variant-numeric: tabular-nums; }
.loc .hrs dt { font-weight: 800; letter-spacing: 0.05em; color: var(--k); }
.loc .hrs dd { margin: 0; color: #444; }
.loc .hrs dd.vary { color: var(--muted); }
.loc .btn { align-self: flex-start; }
.loc.eq { border-color: var(--wp--preset--color--equinox); border-width: 3px; background: var(--wp--preset--color--equinox-tint); }
.loc.eq h3 { color: #004D38; }
.wonder-home .chip { display: inline-block; align-self: flex-start; background: var(--k); color: var(--w); font-size: 10px; font-weight: 900; letter-spacing: 0.1em; padding: 4px 10px; margin-bottom: 12px; text-transform: uppercase; }
@media (max-width: 900px) { .locs { grid-template-columns: 1fr; } }

.btn-sm { font-size: 11px; padding: 12px 22px; }

/* ============================================================================
   FAQS
   Ported from `06-faqs.html`.

   A THIRD accordion, and a third set of rules, scoped like the other two. This
   one is the magazine treatment: a hairline section rule with a number, a
   signal-yellow hover that bleeds past the column, and a drawn plus rather
   than a glyph. Membership's is heavier and opens its first answer; Birthdays'
   is lighter and starts shut. Three components, one word.
   ========================================================================= */

.wonder-faqs .mast { border-bottom: 2px solid var(--k); padding: var(--mast-top) 0 26px; }
.wonder-faqs .mast h1 { font-size: clamp(40px, 6vw, 74px); font-weight: 900; letter-spacing: -0.02em; line-height: 0.98; color: var(--k); margin-top: 12px; }
.wonder-faqs .mast .dek { font-size: 15px; line-height: 1.65; color: var(--body); max-width: 600px; margin-top: 16px; }

/* The column is capped for reading but flush LEFT under the masthead —
   centring it would read as a mistake against a left-aligned h1. */
.faqwrap { max-width: 1200px; margin: 0 auto; padding: 0 32px; }
.faqwrap > * { max-width: 820px; }
@media (max-width: 640px) { .faqwrap { padding: 0 18px; } }

.wonder-faqs .sect { padding: 44px 0 0; }
/* The section rule is the whole device: a hairline, a number, a name. */
.secthd { display: flex; align-items: baseline; gap: 14px; border-bottom: 2px solid var(--k); padding-bottom: 9px; margin-bottom: 4px; }
.secthd .no { font-size: 10px; font-weight: 900; letter-spacing: 0.16em; color: var(--faint); font-variant-numeric: tabular-nums; flex: none; }
.secthd h2 { font-size: clamp(20px, 2.6vw, 28px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.1; color: var(--k); }

.wonder-faqs details { border-bottom: 2px solid var(--k); }
.wonder-faqs summary { list-style: none; cursor: pointer; padding: 18px 34px 18px 0; position: relative; font-size: 16px; font-weight: 800; line-height: 1.35; color: var(--k); }
.wonder-faqs summary::-webkit-details-marker { display: none; }
/* The hover bleeds 10px past the column on both sides, so the highlight reads
   as a full-width band rather than a box around the words. */
.wonder-faqs summary:hover { background: var(--signal); box-shadow: -10px 0 0 var(--signal), 10px 0 0 var(--signal); }
/* A hairline plus and minus, drawn rather than typed, so they match the rules
   the rest of the page is built from. */
.wonder-faqs summary::before, .wonder-faqs summary::after { content: ''; position: absolute; right: 6px; background: var(--k); transition: opacity 0.15s; }
.wonder-faqs summary::before { top: calc(50% - 1px); width: 14px; height: 2px; }
.wonder-faqs summary::after { top: calc(50% - 7px); right: 12px; width: 2px; height: 14px; }
.wonder-faqs details[open] summary::after { opacity: 0; }
.wonder-faqs details[open] summary { padding-bottom: 4px; }
@media (prefers-reduced-motion: reduce) {
	.wonder-faqs summary::before, .wonder-faqs summary::after { transition: none; }
}

.wonder-faqs .a { font-size: 15px; line-height: 1.7; color: #333; padding: 0 34px 22px 0; max-width: 64ch; }
.wonder-faqs .a p + p { margin-top: 12px; }
.wonder-faqs .a ul { list-style: none; margin: 10px 0 0; padding: 0; }
.wonder-faqs .a li { padding: 6px 0 6px 18px; position: relative; border-bottom: 1px solid #eee; }
.wonder-faqs .a li:last-child { border-bottom: none; }
.wonder-faqs .a li::before { content: ''; position: absolute; left: 0; top: 15px; width: 8px; height: 2px; background: var(--k); }
.wonder-faqs .a a { color: var(--k); text-decoration: none; border-bottom: 2px solid var(--k); }
.wonder-faqs .a a:hover { background: var(--signal); }

.ask { border: 2px solid var(--k); padding: 34px; margin: 52px 0 0; text-align: center; }
.ask h2 { font-size: clamp(22px, 3vw, 32px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.15; color: var(--k); }
.ask p { font-size: 14px; line-height: 1.65; color: var(--muted); margin: 12px auto 20px; max-width: 46ch; }
.ask .hand { font-size: 21px; color: var(--muted); margin-top: 14px; }

/* ============================================================================
   GIFT CARDS
   Ported from `14-gift-cards.html`. The checkout drawer is the shared one.
   ========================================================================= */

.wonder-gifts .gift-hero { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: 40px; align-items: center; padding: var(--mast-top) 0 8px; }
@media (max-width: 900px) { .wonder-gifts .gift-hero { grid-template-columns: 1fr; gap: 26px; } }
.wonder-gifts .gift-hero h1 { font-size: clamp(38px, 5.6vw, 68px); font-weight: 900; letter-spacing: -0.02em; line-height: 0.98; color: var(--k); margin-top: 12px; }
.wonder-gifts .gift-hero .dek { font-size: 16px; line-height: 1.6; color: var(--body); max-width: 46ch; margin-top: 16px; }

/* The tiger is a cut-out illustration, so it gets NO frame. A 2px box round a
   transparent drawing fights it — the whole point of a cut-out is that it sits
   on the page rather than in a slot. */
.wonder-gifts .gart { line-height: 0; }
.wonder-gifts .gart img { width: 100%; height: auto; display: block; }
@media (max-width: 900px) { .wonder-gifts .gart { max-width: 420px; margin: 0 auto; } }

.wonder-gifts .buyrow { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 24px; }
.wonder-gifts .buyrow .note { font-size: 12px; color: var(--muted); }

.wonder-gifts .uses { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; padding: 44px 0 8px; }
@media (max-width: 860px) { .wonder-gifts .uses { grid-template-columns: 1fr; } }
.wonder-gifts .use { border: 2px solid var(--k); padding: 26px; background: var(--w); }
.wonder-gifts .use .no { font-size: 10px; font-weight: 900; letter-spacing: 0.16em; color: var(--faint); }
.wonder-gifts .use h3 { font-size: 19px; font-weight: 900; letter-spacing: -0.01em; color: var(--k); margin: 8px 0; }
.wonder-gifts .use p { font-size: 13.5px; line-height: 1.6; color: #333; }

.wonder-gifts .steps { border-top: 2px solid var(--k); border-bottom: 2px solid var(--k); display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 44px 0 0; }
@media (max-width: 760px) { .wonder-gifts .steps { grid-template-columns: 1fr; } }
.wonder-gifts .step { padding: 28px; border-right: 2px solid var(--k); }
.wonder-gifts .step:last-child { border-right: none; }
@media (max-width: 760px) {
	.wonder-gifts .step { border-right: none; border-bottom: 2px solid var(--k); }
	.wonder-gifts .step:last-child { border-bottom: none; }
}
.wonder-gifts .step .n { font-size: 10px; font-weight: 900; letter-spacing: 0.16em; text-transform: uppercase; color: var(--faint); }
.wonder-gifts .step h3 { font-size: 16px; font-weight: 900; color: var(--k); margin: 6px 0; }
.wonder-gifts .step p { font-size: 13px; line-height: 1.6; color: #333; }

/* `.fineprint` is also the Membership page's class for a single paragraph.
   Scoped here because this one is a definition list. */
.wonder-gifts .fineprint { padding: 44px 0 56px; font-size: inherit; color: inherit; max-width: none; margin-top: 0; }
.wonder-gifts .fineprint h2 { font-size: 22px; font-weight: 900; letter-spacing: -0.01em; color: var(--k); }
.wonder-gifts .fineprint dl { margin-top: 16px; border-top: 2px solid var(--k); }
.wonder-gifts .fineprint div { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 0 24px; padding: 14px 0; border-bottom: 1px solid #e5e5e5; }
@media (max-width: 640px) { .wonder-gifts .fineprint div { grid-template-columns: 1fr; gap: 4px 0; } }
.wonder-gifts .fineprint dt { font-size: 11px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--k); }
.wonder-gifts .fineprint dd { margin: 0; font-size: 13.5px; line-height: 1.6; color: #333; }
.wonder-gifts .fineprint dd b { color: var(--k); }
.wonder-gifts .fineprint dd a { color: var(--k); }

/* A heavier, centred version of the green panel the other pages use — this one
   replaces the whole page rather than sitting beside it, so it carries more
   weight. Scoped, because `.soon` is the slimmer band elsewhere. */
.wonder-gifts .soon { border: 3px solid var(--wp--preset--color--equinox); background: var(--wp--preset--color--equinox-tint); padding: 36px; text-align: center; margin: 44px 0; }
.wonder-gifts .soon .tag { display: inline-block; background: var(--wp--preset--color--equinox); color: var(--w); font-size: 10px; font-weight: 900; letter-spacing: 0.12em; text-transform: uppercase; padding: 5px 12px; margin-bottom: 0; }
.wonder-gifts .soon h2 { font-size: clamp(22px, 3vw, 30px); font-weight: 900; letter-spacing: -0.01em; color: #00543e; margin: 14px 0 10px; }
.wonder-gifts .soon p { font-size: 14px; line-height: 1.65; color: #2c4a41; max-width: 52ch; margin: 0 auto; }

/* `.pick` was here — a dashed box holding one sentence that told the reader to
   "pick one above". Gone 25 Sep with the shared gate, which offers the choice
   instead of describing where to find it. */
/* These three are reset with every other block, at the top of this file. */

/* ============================================================================
   OUR STORY
   Ported from `13-our-story.html`.

   THIS PAGE BREAKS THE SYSTEM ON PURPOSE. Every other page is black on white,
   Helvetica Neue 900, 2px rules and no curves. This one is a scrapbook: taped
   snapshots, a handwritten hand, and Playfair — the only page Playfair belongs
   to, which is why the theme makes it opt-in per heading rather than a default.

   Scoped throughout, so none of it can leak into a page that is meant to look
   like the rest of the site. If it ever stops looking out of place, something
   has gone wrong.
   ========================================================================= */

/* ── Our Story ────────────────────────────────────────────
   THE ONE PAGE THAT BREAKS THE SYSTEM, ON PURPOSE.

   Everywhere else is black on white, Helvetica Neue 900, 2px rules, no
   curves. This is ruled notebook paper, a red margin line, Playfair for the
   names and Caveat for everything a person actually wrote. That is v6's
   call and it is the right one: the page is an origin story told in a
   child's exercise book, and setting it in the same furniture as a pricing
   table would kill it.

   It stays contained. The header and footer above and below are the
   system's, unchanged, so the page reads as a room inside the building
   rather than a different building. */
.wonder-story .paper {background:#f4f6fb;position:relative;
  background-image:repeating-linear-gradient(transparent 0px,transparent 31px,
    #c8d4e8 31px,#c8d4e8 32px);
  background-size:100% 32px;background-position:0 24px;}
/* the margin rule, drawn where a school exercise book puts it */
.wonder-story .paper::before {content:'';position:absolute;top:0;bottom:0;left:88px;width:2px;
  background:#e8a0a0;z-index:1;opacity:.55;}
.wonder-story .paper-content {padding:44px 52px 56px 120px;position:relative;z-index:3;max-width:1000px;}
.wonder-story .paper h1 {font-family:var(--display);color:#1a2340;font-weight:900;
  font-size:clamp(38px,6vw,72px);line-height:1.02;letter-spacing:-.01em;}
.wonder-story .paper h1 em {color:var(--wp--preset--color--equinox);font-style:italic;}

.wonder-story .chapter {display:flex;align-items:baseline;gap:16px;margin:46px 0 10px;}
.wonder-story .chapter-num {font-family:var(--hand);font-size:15px;color:#e8a0a0;font-weight:600;
  flex:none;}
.wonder-story .chapter-title {font-family:var(--hand);font-size:clamp(28px,3.5vw,42px);font-weight:700;
  color:#1a2340;line-height:1;}

.wonder-story .handwritten {font-family:var(--hand);font-size:clamp(17px,1.8vw,21px);line-height:1.88;
  color:#2a3a5c;max-width:760px;}
.wonder-story .handwritten p {margin-bottom:30px;}
.wonder-story .handwritten p:last-child {margin-bottom:0;}
.wonder-story .handwritten strong {font-weight:700;color:#1a2340;}
.wonder-story .handwritten em {font-style:italic;color:var(--wp--preset--color--equinox);}
/* highlighter, not a fill: it sits in the bottom 40% the way a pen does */
.wonder-story .hl {background:linear-gradient(transparent 60%, rgba(249,224,0,.6) 60%);}

/* ── snapshots in the margin ──────────────────────────── */
/* Two photographs dropped at angles in the empty paper to the right of the
   essay. Joey, 18 Sep. The page already speaks this language — lined paper,
   a handwritten hand, a taped quote sitting at -1.2deg — so a polaroid here
   is joining in rather than importing a new idea. This is also the ONE part
   of the site where tilting something is right: everywhere else is built on
   a hard 2px grid, and a snapshot on a scrapbook page is the exception that
   proves it.

   Absolutely positioned against .paper rather than placed in the flow,
   because the flow is a single column of text and these belong in the
   margin beside it, not between two paragraphs.

   The bottom mat is deeper than the other three sides — 44px against 12px.
   That asymmetry IS the polaroid; without it a white border is just a white
   border. */
/* Anchored to the TEXT COLUMN, not the right edge of the window. The essay
   is a fixed 760px measure starting 120px in, so it always ends at 880;
   pinning these to the viewport instead sent them drifting 680px away from
   it on a wide screen, where they read as two photographs stranded in the
   corner rather than snapshots dropped beside the writing. */
.wonder-story .snaps {position:absolute;top:96px;left:920px;width:300px;
  z-index:4;}
.wonder-story .snap {background:#fff;padding:12px 12px 44px;width:260px;
  box-shadow:0 10px 26px rgba(20,32,64,.22),0 2px 6px rgba(20,32,64,.14);}
.wonder-story .snap img {width:100%;height:auto;aspect-ratio:1/1;object-fit:cover;display:block;
  background:#e9edf6;}
/* Joey's order, 18 Sep: founder, yeti, then the dinosaurs — all three inside
   the opening section, before the faculty. They are NOT a pile: they run
   down the margin, staggered sideways so the three do not line up as a
   column, and leaning alternately so none of them looks placed by a grid.

   The gaps were 210px when there were two and are 78px now that there are
   three — Joey asked for them closer together, and three at the old spacing
   would have run past the end of the section anyway. */
/* SCOPED TO `.snaps`, because there is a second set of these in the flow now
   (see `.snapflow`) and `nth-child` counts siblings — one of the inline copies
   would otherwise have picked up the margin set's 78px offset from whatever
   position it happened to hold among the chapters. */
.wonder-story .snaps .snap:nth-child(1) {transform:rotate(3.2deg);}
.wonder-story .snaps .snap:nth-child(2) {transform:rotate(-4.5deg);margin:78px 0 0 34px;}
.wonder-story .snaps .snap:nth-child(3) {transform:rotate(2.6deg);margin:78px 0 0 -8px;}

/* Below 1280 there is no margin left to drop anything into: the snaps need
   920+300=1220px plus air, and at 1200 they were clipping the last word of
   every line. Rather than shrink them into the text, they go. A snapshot in
   a margin needs a margin. */
@media (max-width:1279px){ .wonder-story .snaps{display:none;} }

/* THE SAME THREE PHOTOGRAPHS, IN THE FLOW, WHERE THERE IS NO MARGIN TO PUT
   THEM IN. Joey, 25 Sep: "Can we have them be above 01, above 02, and above
   03, all centered (but on the same angle they are on the regular page)."

   Same angles as the margin set, centred rather than staggered — a stagger
   needs room on both sides and there is none. Exactly one set is displayed at
   any width, so nothing is ever shown or announced twice. */
.wonder-story .snapflow {display:none;}
@media (max-width:1279px){
  .wonder-story .snapflow {display:block;margin:38px auto 4px;}
  .wonder-story .snapflow.s1 {transform:rotate(3.2deg);}
  .wonder-story .snapflow.s2 {transform:rotate(-4.5deg);}
  .wonder-story .snapflow.s3 {transform:rotate(2.6deg);}
}
@media (max-width:420px){ .wonder-story .snapflow {width:min(100%, 230px);padding:9px 9px 34px;} }

.wonder-story .tape {display:inline-block;background:rgba(249,224,0,.35);
  border:1px dashed rgba(0,0,0,.2);padding:8px 18px;font-family:var(--hand);
  font-size:17px;color:#1a2340;transform:rotate(-1.2deg);margin-top:14px;}

.wonder-story .char-card {border-top:1.5px solid rgba(0,0,0,.1);padding:52px 52px 52px 120px;
  position:relative;z-index:3;display:grid;grid-template-columns:1fr 300px;
  gap:48px;align-items:center;max-width:1100px;}
.wonder-story .char-card.flip {grid-template-columns:300px 1fr;}
.wonder-story .char-card.flip .char-img {order:-1;}
.wonder-story .char-role {font-size:10px;font-weight:900;letter-spacing:.16em;text-transform:uppercase;
  color:var(--wp--preset--color--equinox);margin-bottom:8px;}
.wonder-story .char-name {font-family:var(--display);font-size:clamp(24px,3vw,36px);
  font-weight:900;color:#1a2340;line-height:1.08;}
.wonder-story .char-name span {display:block;font-family:var(--hand);font-size:17px;font-weight:600;
  color:#e8a0a0;margin-top:2px;}
.wonder-story .char-bio {font-family:var(--hand);font-size:clamp(16px,1.7vw,20px);line-height:1.88;
  color:#2a3a5c;margin-top:14px;}
.wonder-story .char-bio em {font-style:italic;color:var(--wp--preset--color--equinox);}
.wonder-story .char-bio strong {font-weight:700;color:#1a2340;}
.wonder-story .char-img img {width:100%;height:auto;display:block;
  filter:drop-shadow(0 8px 18px rgba(0,0,0,.12));}

.wonder-story .story-close {text-align:center;padding:60px 20px;border-bottom:2px solid var(--k);}
.wonder-story .story-close h2 {font-size:clamp(24px,3.4vw,38px);font-weight:900;letter-spacing:-.01em;
  color:var(--k);margin-bottom:20px;}

@media (max-width:820px){
  /* The margin rule and the 120px indent are a desk-sized joke. On a phone
     they are just lost space, so the paper keeps its lines and drops both. */
  .wonder-story .paper::before {display:none;}
  .wonder-story .paper-content, .wonder-story .char-card {padding:36px 20px 40px;}
  .wonder-story .char-card, .wonder-story .char-card.flip {grid-template-columns:1fr;gap:26px;}
  .wonder-story .char-card.flip .char-img {order:0;}
  .wonder-story .char-img {max-width:260px;margin:0 auto;}
}


/* ============================================================================
   CAREERS
   Ported from `16-careers.html`.
   ========================================================================= */

/* ── careers ──────────────────────────────────────────────
   The plainest kind of page after the policy: a masthead, a paragraph or
   two, and a list of openings. Nothing here needs a photograph to do its
   job, and the 2px rule does all the structure. */
.wonder-careers .cmast {padding:calc(var(--mast-top) + 4px) 0 0;}
.wonder-careers .cmast h1 {font-size:clamp(40px,6.4vw,80px);}
/* The headline asks whether you like dinosaur flash mobs; this is the
   answer, so it stays next to the copy that explains the job rather than
   being parked further down.

   Copy left, picture right — the same way the birthday and membership
   bands are built. No frame on the picture: the masthead rule sits just
   above and a 2px border here would put two lines a few pixels apart.

   The picture is FIRST in the markup so that when the columns stack it
   lands straight under the headline, which is where the joke pays off;
   the grid puts it back on the right on a wider screen. */
.wonder-careers .cbody {display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.92fr);
  gap:46px;align-items:start;margin:28px 0 0;}
.wonder-careers .cbody .cintro {grid-column:1;grid-row:1;}
.wonder-careers .cbody .dinoband {grid-column:2;grid-row:1;}
.wonder-careers .dinoband {margin:0;}
/* No photograph on file: one column, rather than a two-column grid with a
   hole where the picture should be. */
.wonder-careers .cbody.solo {grid-template-columns:minmax(0,1fr);}
.wonder-careers .dinoband img {width:100%;height:auto;display:block;aspect-ratio:3/2;
  object-fit:cover;background:var(--wp--preset--color--field);}
.wonder-careers .dinoband figcaption {font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted);margin-top:10px;}
@media (max-width:860px){
  .wonder-careers .cbody {grid-template-columns:1fr;gap:24px;margin-top:22px;}
  .wonder-careers .cbody .cintro, .wonder-careers .cbody .dinoband {grid-column:1;grid-row:auto;}
  .wonder-careers .dinoband img {aspect-ratio:3/2;}
}

.wonder-careers .cintro {max-width:60ch;padding:0;}
.wonder-careers .cintro p {font-size:15.5px;line-height:1.72;color:#222;margin-bottom:16px;}
.wonder-careers .cintro p.kicker {font-size:19px;line-height:1.5;font-weight:700;color:var(--k);}

.wonder-careers .ohead {border-top:2px solid var(--k);margin-top:44px;padding-top:14px;
  display:flex;justify-content:space-between;align-items:baseline;gap:16px;flex-wrap:wrap;}
.wonder-careers .ohead h2 {font-size:clamp(22px,2.8vw,30px);font-weight:900;letter-spacing:-.01em;color:var(--k);}
.wonder-careers .ohead .ct {font-size:10px;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
  color:var(--faint);}

.wonder-careers .jobs {border-top:2px solid var(--k);margin-top:16px;}
.wonder-careers .job {display:grid;grid-template-columns:1fr auto;gap:10px 24px;align-items:center;
  padding:22px 0;border-bottom:2px solid var(--k);text-decoration:none;color:inherit;}
@media (max-width:620px){ .wonder-careers .job{grid-template-columns:1fr;align-items:start;} }
.wonder-careers .job h3 {font-size:clamp(19px,2.4vw,26px);font-weight:900;letter-spacing:-.01em;color:var(--k);
  line-height:1.08;}
.wonder-careers .job .where {font-size:11px;font-weight:900;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);margin-top:6px;display:block;}
.wonder-careers .job .go {font-size:11px;font-weight:900;letter-spacing:.1em;text-transform:uppercase;
  color:var(--k);white-space:nowrap;}
.wonder-careers a.job:hover {background:#FFFDF0;}
.wonder-careers a.job:hover .go {background:var(--signal);padding:4px 8px;}
.wonder-careers .job.inert .go {color:var(--faint);}

.wonder-careers .cend {border-top:2px solid var(--k);margin-top:44px;padding:28px 0 8px;
  display:flex;flex-wrap:wrap;gap:12px 32px;align-items:baseline;}
.wonder-careers .cend p {font-size:14px;line-height:1.6;color:#333;max-width:52ch;}
.wonder-careers .cend .hand {font-family:var(--hand);font-size:19px;color:var(--k);}

/* ── one role ─────────────────────────────────────────── */
.wonder-careers .role {display:grid;grid-template-columns:1.35fr .65fr;gap:44px;padding:8px 0 20px;
  align-items:start;}
@media (max-width:900px){ .wonder-careers .role{grid-template-columns:1fr;gap:28px;} }
.wonder-careers .role .body h2 {font-size:13px;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
  color:var(--k);border-top:2px solid var(--k);padding-top:14px;margin:36px 0 12px;}
.wonder-careers .role .body p {font-size:15.5px;line-height:1.72;color:#222;margin-bottom:16px;}
.wonder-careers .role .body ul {list-style:none;}
.wonder-careers .role .body li {font-size:14.5px;line-height:1.6;color:#333;padding:11px 0;
  border-bottom:1px solid #e5e5e5;}
.wonder-careers .role .body li:last-child {border-bottom:none;}
.wonder-careers .role .body li b {color:var(--k);font-weight:900;}

/* The apply panel sticks, because the list of qualifications is long and the
   button should never be something you have to scroll back up for. */
.wonder-careers .applybox {border:4px solid var(--k);padding:26px;background:var(--w);position:sticky;top:120px;}
@media (max-width:900px){ .wonder-careers .applybox{position:static;} }
.wonder-careers .applybox h3 {font-size:12px;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
  color:var(--k);}
.wonder-careers .applybox p {font-size:13.5px;line-height:1.6;color:#333;margin:10px 0 0;}
.wonder-careers .applybox ol {margin:14px 0 0;padding-left:0;list-style:none;counter-reset:s;}
.wonder-careers .applybox ol li {counter-increment:s;font-size:13.5px;line-height:1.55;color:#333;
  padding:9px 0;border-bottom:1px solid #e5e5e5;}
.wonder-careers .applybox ol li:last-child {border-bottom:none;}
.wonder-careers .applybox ol li::before {content:counter(s);font-weight:900;font-size:10px;color:var(--faint);
  margin-right:9px;}
.wonder-careers .applybox .btn {width:100%;text-align:center;margin-top:18px;}
.wonder-careers .applybox .addr {font-size:11px;font-weight:900;letter-spacing:.06em;color:var(--muted);
  margin-top:12px;word-break:break-all;}
.wonder-careers .backlink {font-size:10px;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
  color:var(--faint);text-decoration:none;display:inline-block;margin-top:34px;}
.wonder-careers .backlink:hover {color:var(--k);}


/* ============================================================================
   PRIVACY POLICY
   Ported from `15-privacy-policy.html`. The words are the live site's,
   verbatim; this is only the frame around them.
   ========================================================================= */

/* ── privacy policy ───────────────────────────────────────
   One column, one measure, no columns-within-columns. The only
   structural device is the 2px rule, same as everywhere else. */
.wonder-legal .legal {max-width:none;}
.wonder-legal .legal .mast {padding:calc(var(--mast-top) + 4px) 0 0;}
.wonder-legal .legal .mast h1 {font-size:clamp(40px,6vw,74px);}
.wonder-legal .stamp {font-size:11px;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
  color:var(--faint);margin-top:18px;border-top:2px solid var(--k);padding-top:12px;
  display:inline-block;}
.wonder-legal .stamp b {color:var(--k);}

.wonder-legal .toc {border-top:2px solid var(--k);border-bottom:2px solid var(--k);margin:34px 0 0;
  padding:20px 0;}
.wonder-legal .toc .lbl {font-size:10px;font-weight:900;letter-spacing:.16em;text-transform:uppercase;
  color:var(--faint);display:block;margin-bottom:12px;}
.wonder-legal .toc ol {list-style:none;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:6px 40px;counter-reset:t;}
@media (max-width:760px){ .wonder-legal .toc ol{grid-template-columns:1fr;} }
.wonder-legal .toc li {counter-increment:t;font-size:13.5px;line-height:1.5;}
.wonder-legal .toc li::before {content:counter(t,decimal-leading-zero);font-weight:900;font-size:10px;
  letter-spacing:.1em;color:var(--faint);margin-right:10px;}
.wonder-legal .toc a {color:var(--k);text-decoration:none;border-bottom:1px solid rgba(0,0,0,.25);}
.wonder-legal .toc a:hover {border-bottom:2px solid var(--k);}

.wonder-legal .doc {max-width:74ch;padding:10px 0 20px;}
.wonder-legal .doc section {padding-top:44px;}
.wonder-legal .doc h2 {font-size:clamp(20px,2.4vw,26px);font-weight:900;letter-spacing:-.01em;
  color:var(--k);border-top:2px solid var(--k);padding-top:14px;margin-bottom:14px;
  scroll-margin-top:120px;}
.wonder-legal .doc h3 {font-size:14px;font-weight:900;letter-spacing:.02em;color:var(--k);
  margin:26px 0 8px;}
.wonder-legal .doc p {font-size:15px;line-height:1.72;color:#222;margin-bottom:16px;}
.wonder-legal .doc p b.lead {font-weight:900;color:var(--k);}
.wonder-legal .doc a {color:var(--k);text-decoration:none;border-bottom:2px solid var(--signal);
  padding-bottom:1px;}
.wonder-legal .doc a:hover {background:var(--signal);}
.wonder-legal .doc .top {font-size:10px;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
  color:var(--faint);border-bottom:none;}
.wonder-legal .doc .top:hover {background:none;color:var(--k);}

.wonder-legal .legal-end {border-top:2px solid var(--k);margin-top:48px;padding:28px 0 8px;
  display:flex;flex-wrap:wrap;gap:14px 32px;align-items:baseline;}
.wonder-legal .legal-end p {font-size:13.5px;line-height:1.6;color:#333;max-width:52ch;}
.wonder-legal .legal-end .hand {font-family:var(--hand);font-size:19px;color:var(--k);}

/* ── the birthday theme landing pages ────────────────────────────────────
   Seven pages, one block, and almost none of their furniture is new: the
   flip card, the carousel, the poster, the Typeform slot and the button are
   the Birthday Parties page's own, extended above rather than reimplemented.
   What is below is only the arrangement the theme mocks ask for.

   EVERY SELECTOR HERE IS SCOPED. `.dbox`, `.prow`, `.pwho`, `.pamt`,
   `.dlede`, `.esub`, `.actgrid` and `.tmast` are all generic enough to be
   claimed by something else one day, and this stylesheet has had nine
   collisions already — the last of them, `.pricebox`, reached a live page.
   A bare class selector is the thing to refuse in review. */
.wonder-theme .tmast {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 18px;
	align-items: center;
	border-bottom: 2px solid var(--k);
	padding: var(--mast-top) 0 26px;
}
/* The icon sits beside the WHOLE copy block, not just the headline — the
   mock's note, 16 Sep. Beside the headline alone, a square icon set the
   height of that one row and opened a canyon between the headline and the
   standfirst. Four columns, so it lands over the fourth card below it. */
.wonder-theme .tmcopy { grid-column: 1 / 4; min-width: 0; }
.wonder-theme .tmast h1 {
	font-size: clamp(40px, 6vw, 74px);
	font-weight: 900;
	letter-spacing: -0.02em;
	line-height: 0.98;
	color: var(--k);
	margin-top: 12px;
	text-wrap: balance;
}
/* TWO LINES, WHATEVER THE HEADLINE. Joey, 25 Sep: Winter's was running to
   three while Fairy's and Space's sat on two, and the page reads as a
   different design when it does.

   The headline lengths run from 22 characters ("For The Dinosaur Lover") to
   46 ("For The Winter Ice Princess Yeti Snowman Lover"), so one fixed size
   cannot serve both. CSS cannot count characters; the block counts them into
   `--h1ch` and this works the size out from it.

   `1cqw` is one per cent of the copy column, so two lines hold roughly
   `2 × 100cqw ÷ (k × size)` characters, and solving for the size gives the
   rule below. **k = 0.56 was measured, not guessed**: at 896px, Winter needs
   70px to fit two lines and Fairy fits at 74px, which pins k between 0.550
   and 0.556 — 0.56 clears both with a little to spare. The 74px cap still
   wins for every headline short enough not to need the help, so Dinosaur,
   Halloween and Teddy Bear are untouched.

   Only above 900px, where the copy column is three grid columns wide. Below
   that the masthead is a single stack, three or four lines is the right
   answer, and forcing two would leave the type too small to read. */
@media (min-width: 901px) {
	.wonder-theme .tmcopy { container-type: inline-size; }
	.wonder-theme .tmast h1 { font-size: min(74px, calc(200cqw / (0.56 * var(--h1ch, 24)))); }
}
.wonder-theme .tmast .dek { font-size: 15px; line-height: 1.65; color: #222; max-width: 600px; margin-top: 16px; }
.wonder-theme .tmcta { margin-top: 22px; }
/* Square and CONTAINED, so a tall narrow wand and a round pumpkin take the
   same footprint on every one of the seven.

   `height: auto` IS LOAD-BEARING, and leaving it out broke all five pages.
   wp_get_attachment_image() writes width and height ATTRIBUTES — 513 and 513
   for the picnic basket — and those are presentational hints, so with no
   author rule for height the basket kept its own 513px while width was
   squeezed to the column's 287. `aspect-ratio` does nothing once both
   dimensions are set, so the masthead grew to 585px instead of 359px. Every
   theme had it; Teddy Bear Picnic's square icon just made it obvious, where
   Space's 560x374 only looked like slightly generous padding. */
.wonder-theme .themeicon { grid-column: 4; align-self: center; width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: contain; object-position: center; }
@media (max-width: 900px) {
	.wonder-theme .tmast { grid-template-columns: repeat(3, 1fr); gap: 14px; }
	.wonder-theme .tmcopy { grid-column: 1 / 3; }
	.wonder-theme .themeicon { grid-column: 3; }
}
@media (max-width: 620px) {
	.wonder-theme .tmast { grid-template-columns: 1fr; }
	.wonder-theme .tmcopy, .wonder-theme .themeicon { grid-column: 1; }
	.wonder-theme .themeicon { width: min(100%, 220px); order: 2; }
}

/* Four across, which is the mock. It has to survive a page with four cards
   and a page with twelve — Teddy Bear Picnic arrived on 24 Sep with twelve —
   so it is a fixed count that steps down, not an auto-fill that would leave
   the Dinosaur page's four cards stranded at a third of their width. */
/* `.tacts`, not `.acts` — see the block. `.acts` is the Locations page's
   action-button row and it is `display: flex`, so a section of ours wearing
   that name became a flex container and the grid inside sized to content:
   675px of a 1200px page. Renamed rather than fought, because the Locations
   page had the name first and its markup is right. */
.wonder-theme .tacts { padding: 26px 0 8px; }
.wonder-theme .actgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 28px 18px; }
@media (max-width: 1040px) { .wonder-theme .actgrid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 720px) { .wonder-theme .actgrid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 380px) { .wonder-theme .actgrid { grid-template-columns: 1fr; } }

/* Prices and what's included, side by side and the same height. */
.wonder-theme .detail { display: grid; grid-template-columns: 1fr 1.15fr; gap: 22px; padding: 8px 0 48px; align-items: stretch; }
@media (max-width: 820px) { .wonder-theme .detail { grid-template-columns: 1fr; } }
.wonder-theme .dbox { border: 2px solid var(--k); padding: 28px; background: var(--w); }
.wonder-theme .dbox.lead { border-width: 4px; display: flex; flex-direction: column; }
.wonder-theme .dbox h3 { font-size: 13px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--k); }
.wonder-theme .dbox .btn { width: 100%; text-align: center; margin-top: auto; }
.wonder-theme .dlede { font-size: 12px; color: var(--muted); margin: 8px 0 2px; }
.wonder-theme .dbox .included { border: none; padding: 0; }
.wonder-theme .dbox .included h3 { display: none; }
.wonder-theme .dbox ul { list-style: none; margin: 14px 0 0; padding: 0; }
.wonder-theme .dbox li { font-size: 13px; line-height: 1.5; padding: 7px 0; border-bottom: 1px solid #e5e5e5; color: #333; }
.wonder-theme .dbox li:last-child { border-bottom: none; }
.wonder-theme .dbox li[hidden] { display: none; }
.wonder-theme .dbox li b { color: var(--k); font-weight: 800; }
.wonder-theme .prices { margin-top: 16px; border-top: 2px solid var(--k); }
.wonder-theme .prow { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 9px 0; border-bottom: 1px solid #e5e5e5; }
.wonder-theme .prow:last-child { border-bottom: none; }
.wonder-theme .pwho { font-size: 11px; font-weight: 900; letter-spacing: 0.08em; text-transform: uppercase; color: var(--k); }
.wonder-theme .pamt { font-size: 20px; font-weight: 900; color: var(--k); font-variant-numeric: tabular-nums; }
.wonder-theme .prow.lead .pamt { font-size: 34px; line-height: 1; }

/* The theme you are on stays in the row rather than dropping out of it, so
   the row never changes length as you walk the seven. It is marked, not
   removed — and it is a <span>, so there is nothing to click back to. */
.wonder-theme .tcard.here { outline: 4px solid var(--k); outline-offset: 4px; cursor: default; }
.wonder-theme .tcard.here:hover .tposter { transform: none; }
.wonder-theme .tmeta .go.here { border-bottom-color: transparent; color: var(--faint); }

/* The index at /birthday-parties/themes/ is a grid, not a carousel: there is
   no theme being compared against one you are already reading, so there is no
   row to stay in. */
.wonder-theme .tgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 28px 18px; padding: 26px 0 48px; }
@media (max-width: 1040px) { .wonder-theme .tgrid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 720px) { .wonder-theme .tgrid { grid-template-columns: repeat(2, 1fr); } }

.wonder-theme .themes { padding-top: 8px; }
.wonder-theme .carhd h2 { font-size: clamp(22px, 3vw, 32px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.06; color: var(--k); margin-top: 6px; }
.wonder-theme .carhd .eyebrow { font-size: 10px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }

.wonder-theme .enquire { padding: 52px 0 64px; }
.wonder-theme .enquire .eyebrow { font-size: 10px; font-weight: 900; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }
.wonder-theme .enquire h2 { font-size: clamp(24px, 3.4vw, 36px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.08; color: var(--k); margin-top: 8px; }
.wonder-theme .esub { font-size: 14.5px; line-height: 1.65; color: #333; max-width: 60ch; margin: 12px 0 22px; }

/* ═══════════════════════════════════════════════════════════════════════════
   THE PHONE.

   Every page above was built and checked at desk width, and the phone was
   taking whatever fell out of it. Joey, 25 Sep, with twelve screenshots:
   "the optimization for mobile is all wrong … I would like to go through and
   fix all of that asap."

   ONE BREAKPOINT, AT 600px, AND IT IS NOT AN INVENTED NUMBER. 600 is where
   WordPress's navigation block swaps the six links for the hamburger, so it
   is already the width at which this site becomes a phone. The stylesheet
   above carries twelve different breakpoints with no system behind them;
   everything that follows uses this one, and lives together at the end of the
   file so that it always wins on order rather than on specificity tricks.

   Nothing here gets BIGGER than the rule it overrides — every declaration
   either shrinks something or re-flows it. At exactly 600px the page renders
   as it did before.
   ═══════════════════════════════════════════════════════════════════════════ */

/* THE DAY STEPPER.
   Hidden everywhere except the phone, where the week is one frame wide. It is
   printed by the block rather than drawn by script so that it is in the HTML
   a search engine and a reader without JavaScript both get — with no script
   the buttons do nothing, but the track still scrolls by hand, which is the
   honest fallback. */
.daynav { display: none; align-items: center; justify-content: space-between; gap: 12px; margin-top: 24px; }
.daynav button {
	border: 2px solid var(--k);
	background: var(--w);
	color: var(--k);
	font-family: inherit;
	font-size: 15px;
	font-weight: 900;
	line-height: 1;
	width: 40px;
	height: 36px;
	flex: none;
	cursor: pointer;
}
.daynav button:disabled { opacity: 0.3; cursor: default; }
.daynav button:not(:disabled):hover { background: var(--signal); }
.daynav .cur { font-size: 11px; font-weight: 900; letter-spacing: 0.12em; text-transform: uppercase; color: var(--k); text-align: center; flex: 1; font-variant-numeric: tabular-nums; }

/* THE PLAN SWITCH and THE CARD SHEET.
   Both are phone-only behaviours whose furniture is declared here, out of the
   media query, so the query holds only the decision to use them. */

/* Hidden until the script says a browser can work it — see the day stepper
   above for the same reasoning, and `.switched` for its other half. */
.plansw { display: none; gap: 0; margin: 26px 0 0; border: 2px solid var(--k); }
.plansw button {
	flex: 1 1 0;
	border: 0;
	background: var(--w);
	color: var(--k);
	font-family: inherit;
	font-size: 11.5px;
	font-weight: 900;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	padding: 13px 8px;
	cursor: pointer;
}
.plansw button + button { border-left: 2px solid var(--k); }
.plansw button[aria-pressed="true"] { background: var(--k); color: var(--w); }

/* The sheet a class card opens into on a phone. The back of a card is a
   DRAWING of the description, so the only thing that makes it readable is
   size: the frame takes the width of the screen and keeps the card's ratio. */
.cardsheet {
	position: fixed;
	inset: 0;
	z-index: 200;
	background: rgba(0, 0, 0, 0.82);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 20px;
}
.cardsheet[hidden] { display: none; }
.cardsheet { overflow: auto; }
.cardsheet .cs-in { position: relative; width: min(100%, 460px); }
/* A CLONE OF THE WHOLE BACK, not of its photograph. Most card backs are a
   drawing, but a card with no artwork renders a `.ph` panel of real type
   instead, and that one has no `<img>` to copy. The frame keeps the card's
   ratio and whatever is inside fills it. */
.cardsheet .cs-body { aspect-ratio: 1191 / 1685; border: 2px solid var(--k); background: var(--w); overflow: hidden; }
.cardsheet .cs-body > * { width: 100%; height: 100%; display: block; }
.cardsheet img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* A PHOTOGRAPH KEEPS ITS OWN SHAPE. The card frame is 1191:1685 because every
   card back is drawn to it; the pictures in the photograph bands are whatever
   shape they were taken in, and cropping one to a card would be the opposite
   of "expands the image so you can see it larger". Joey, 25 Sep. */
.cardsheet.photo .cs-body { aspect-ratio: auto; max-height: calc(100vh - 120px); }
.cardsheet.photo img { height: auto; max-height: calc(100vh - 124px); object-fit: contain; }
.cardsheet .cs-x {
	position: absolute;
	top: -46px;
	right: 0;
	width: 38px;
	height: 38px;
	border: 2px solid var(--w);
	background: transparent;
	color: var(--w);
	font-family: inherit;
	font-size: 20px;
	font-weight: 900;
	line-height: 1;
	cursor: pointer;
}
.cardsheet .cs-x:hover { background: var(--signal); color: var(--k); border-color: var(--signal); }

@media (max-width: 600px) {

	/* ── the bar ─────────────────────────────────────────────────────────
	   "On Mobile I want the Logo and the hamburger center, location select
	   and member portal also center underneath."

	   The row already wrapped to two lines; both were left-aligned, which is
	   what made the bar read as a desktop layout that had run out of room.
	   `margin-left: auto` is what threw the picker to the right edge, so it
	   goes; `flex: 0 0 100%` is what guarantees the second line rather than
	   hoping the widths add up to a wrap. */
	.wonder-topbar-inner { justify-content: center; gap: 10px 18px; padding: 10px 18px; }
	.wonder-topbar .wonder-topbar-right { margin-left: 0; flex: 0 0 100%; justify-content: center; }

	/* ── "as seen in" ────────────────────────────────────────────────────
	   Three logos and the label measured 389px of content in a 354px band, so
	   Forbes wrapped alone onto a second line. The marks are sized in PERCENT
	   here rather than in pixels: the band has to hold at 320px as well as at
	   390, and a fixed height cannot do that. Heights stay in proportion to
	   each other — 30/20/23 becomes 22/15/17 — so the cap-height match the
	   desktop rule was set up by eye survives the shrink. */
	.press-marks { flex-wrap: nowrap; gap: 10px; }
	.press .lbl { flex: none; font-size: 9px; letter-spacing: 0.1em; }
	.press img.harpers { height: auto; width: 26%; }
	.press img.domino { height: auto; width: 21%; }
	.press img.forbes { height: auto; width: 19%; }

	/* ── the black band ──────────────────────────────────────────────────
	   "Black bar should be one line or two lines max and way closer
	   together." It was three lines 70px apart, because `gap: 52px` sets the
	   ROW gap as well as the column gap and nobody had ever seen it wrap. */
	.wayband { gap: 9px 16px; padding: 12px 16px; }
	.wayband a { font-size: 10px; letter-spacing: 0.1em; }

	/* ── the camp announcement ───────────────────────────────────────────
	   "Camp banner shouldn't extend to 3 lines." Four, in fact: 15px of
	   uppercase at 0.12em tracking is 900px of type in a 350px band. */
	.announce { padding: 16px; }
	.announce a { font-size: 12px; letter-spacing: 0.05em; }

	/* ── mastheads ───────────────────────────────────────────────────────
	   "the names of locations shouldn't extend to multiple lines."

	   The floor of every masthead clamp is 40px, which was chosen for a
	   1200px column. "Upper West Side, NY." sets 385px wide at 40px in a
	   326px column, so it broke in two. 8.2vw resolves to 32px at 390 (308px
	   of type) and keeps shrinking on narrower phones, which is the only way
	   the longest name fits on an iPhone SE as well. The 40px ceiling means
	   this rule can only ever make a masthead smaller. */
	.wonder-locpanel .mast h1,
	.wonder-catalogue .mast h1,
	.wonder-camps .mast h1,
	.wonder-birthdays .mast h1,
	.wonder-membership .mast h1,
	.wonder-faqs .mast h1,
	.wonder-careers .cmast h1,
	.wonder-legal .legal .mast h1 { font-size: clamp(26px, 8.2vw, 40px); }
	/* Birthdays' masthead is a drawn wordmark, not type, and its width is
	   quoted in `em` — so shrinking the h1 would have shrunk the picture with
	   it. It keeps the full column. */
	.wonder-birthdays .mast h1.wordmark img { width: 100%; }

	/* ── classes ─────────────────────────────────────────────────────────
	   "it's only showing one card, way too much scrolling, sorter of buttons
	   is all a mess."

	   Nineteen cards one-up at 496px each is 10,076px of catalogue. Two-up
	   takes it to about 2,800 — the same nineteen classes, a third of the
	   thumb. The poster keeps its ratio; only the type around it comes down.

	   The rule between the age chips and the subject chips COMES BACK. It was
	   hidden below 640px, which left nine chips in one ragged run and no sign
	   that they answer two different questions. A vertical rule cannot
	   survive a wrapped row, so it becomes a horizontal one: `flex-basis:
	   100%` forces a break either side of it. */
	.cgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px 12px; padding: 26px 0 10px; }
	.card { gap: 8px; }
	.meta { flex-direction: column; align-items: flex-start; gap: 3px; }
	.meta h3 { font-size: 15px; }
	.wonder-catalogue .ph { padding: 10px; }
	.wonder-catalogue .ph .nm { font-size: 14px; }
	.filter { gap: 6px; padding: 14px 0; }
	.filter button { font-size: 9.5px; padding: 5px 9px; letter-spacing: 0.04em; }
	.filter .sep { display: block; flex: 0 0 100%; width: auto; height: 2px; align-self: auto; margin: 2px 0; }

	/* ── the honest math ─────────────────────────────────────────────────
	   "Membership page graph is all messed up." The threshold label is
	   anchored to the RIGHT end of its dashed line, which on a desk sits in
	   clear air. On a phone the line crosses the chart at 53% and the
	   right-hand bars are all taller than that, so the label was printed
	   across four of them. It moves to the left end, where the early months
	   are still short and the space is genuinely empty. */
	.thresh span { right: auto; left: 0; z-index: 2; font-size: 9px; }
	/* The bar tooltips are already hidden by `@media (hover: none)`, which is
	   the honest test — but it is a test of the POINTER, not of the width,
	   and a tablet with a trackpad passes it. A nowrap tooltip centred on the
	   last bar measures 185px and reaches 407 in a 390 viewport, so on
	   anything this narrow it goes whether or not the device claims a hover.
	   There is nothing to lose: a tooltip that needs hovering cannot be read
	   on a phone in the first place. */
	.wonder-membership .bar .tip { display: none; }

	/* ── the birthday add-ons ────────────────────────────────────────────
	   "Birthday pages add on menu is just one big long scroll." Thirteen
	   activities two-up is seven rows and 1,963px. It becomes a swipe strip —
	   the same gesture as the photo band further up the page — and the 58%
	   width is deliberate: the next card is always half in frame, which is
	   what tells a thumb there is more to the right. */
	.agrid {
		display: flex;
		gap: 12px;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		padding-bottom: 8px;
	}
	/* EXACTLY TWO, and a whole gap. 58% put one and two thirds in frame, which
	   is what Joey photographed: "they are still getting cut off … I would
	   like 2 per view." The peek was the only thing telling a thumb there was
	   more to the right; the arrows do that now, so it can go. */
	.agrid > * { flex: 0 0 calc((100% - 12px) / 2); scroll-snap-align: start; }

	/* ── the week ────────────────────────────────────────────────────────
	   "I don't HATE that it only shows one day but if that's the case it
	   cannot be an endless scroll to see the 7 days it needs to be a button
	   to navigate to the next day carousel style."

	   Seven stacked days measured 3,833px. One day at a time, swiped or
	   stepped with the two buttons above it. The buttons are in the markup
	   already and hidden by default — see .daynav below — so this is the only
	   place that decides a phone gets them. */
	.days {
		display: flex;
		grid-template-columns: none;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		margin-top: 0;
	}
	.days::-webkit-scrollbar { display: none; }
	.day { flex: 0 0 100%; scroll-snap-align: start; border-right: none; }
	/* `:not([hidden])` is the whole no-JavaScript story: the nav is printed
	   hidden and the script is what unhides it, so a reader without scripts
	   never sees two buttons that cannot do anything.

	   THE STEPPER IS THE DAY'S HEADER HERE. Printed as its own light bar it
	   read "WEDNESDAY 9/30" thirty pixels above a black band saying
	   "WEDNESDAY 9/30" — the same string twice. So the band gives up its
	   header and the stepper takes on its black: one strong line that names
	   the day and moves between days, with the card flush underneath it. */
	.daynav:not([hidden]) {
		display: flex;
		gap: 0;
		margin-top: 26px;
		background: var(--k);
		border: 2px solid var(--k);
	}
	.daynav .cur { color: var(--w); }
	.daynav button { background: var(--k); color: var(--w); border: 0; width: 44px; height: 42px; }
	.daynav button:disabled { opacity: 0.35; }
	.daynav button:not(:disabled):hover { background: var(--signal); color: var(--k); }
	.days .day .hd { display: none; }
	.days { border-top: 0; }

	/* ── the home gate ───────────────────────────────────────────────────
	   "those three buttons need to all exist on the same line next to each
	   other." They were one per line, 150px apart, which turned the first
	   question the site asks into three screens of scrolling. Equal thirds of
	   the row rather than three widths that happen to add up: the names are
	   very different lengths and a flex row would have given "Upper West Side"
	   half the bar. A name that will not fit on one line wraps INSIDE its
	   button, which keeps the three buttons level. */
	.wonder-home .gate .inner { padding: 16px 18px; gap: 12px; }
	.wonder-home .gate .q { font-size: 13px; flex: 0 0 100%; text-align: center; }
	.wonder-home .gate .opts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; width: 100%; }
	.wonder-home .gate .opts button { padding: 9px 4px; font-size: 9px; letter-spacing: 0.04em; line-height: 1.15; }
	.wonder-home .gate .opts button small { font-size: 7.5px; letter-spacing: 0.02em; margin-top: 3px; }
	.wonder-home .gate.chosen .inner { padding: 10px 18px; justify-content: center; }
	.wonder-home .gate.chosen .opts { grid-template-columns: repeat(3, 1fr); }

	/* ── the Key ladder ──────────────────────────────────────────────────
	   One card at a time, named by how you pay for it. `.switched` is added by
	   the script, so with no JavaScript both cards stay and nothing is lost
	   behind a switch that cannot move. */
	.plansw:not([hidden]) { display: flex; }
	.plans.two.switched .plan:not(.is-on) { display: none; }
	.plans { padding-top: 16px; }

	/* ── birthdays ───────────────────────────────────────────────────────
	   The longest quote sets the height of every slide, because they are
	   stacked in one grid cell. Dropping it here takes about 300px off the
	   band and costs a phone reader one testimonial out of five. */
	.wonder-birthdays .qtrack figure[data-long] { display: none; }
	/* "Add more space (not a ton) above the green awning." */
	.wonder-birthdays .awning { margin-top: 22px; }
	/* Arrows big enough for a thumb, and a header that does not crowd them. */
	.arrows button { width: 34px; height: 30px; }
	.carhd { margin-top: 28px; gap: 10px; }
	/* Typeform draws INTO the box it is given, and 380px was not enough at
	   this width: the heading clipped at the top and the button sat alone
	   under a field of white, which reads exactly like a form that failed to
	   load. More height, and less padding around it so the widget gets the
	   width too. */
	/* THE FORM IS A BUTTON HERE. `?wdiag=1` on Joey's iPhone reported the
	   widget built and sized — `iframe: 302x560` — and rendering nothing
	   inside it; Typeform cannot lay itself out in a column that narrow, and
	   302px is what a 402px phone has left after the gutters, the rule and
	   the padding. The link opens the form on Typeform's own page, full
	   screen, where it works. */
	.form { padding: 20px; }
	.tf-slot { height: auto; background: none; }
	.tf-widget { display: none; }
	.tf-phone { display: block; text-align: center; }

	/* ── camps ───────────────────────────────────────────────────────────
	   "Logo can be at the very top, center aligned, before everything else."
	   It also gives the headline the whole column back — beside an 84px badge
	   it had 224px and "No school? No problem. We got you." ran to three
	   lines. The copy stays left-aligned; only the badge is centred. */
	.wonder-camps .mast-row { flex-direction: column; align-items: stretch; gap: 14px; }
	.wonder-camps .camp-badge { order: -1; width: 132px; margin: 0 auto; }

	/* ── the Key cards ───────────────────────────────────────────────────
	   Joey, 25 Sep: "when you toggle back and forth between gold and black,
	   the key logo and placement moves slightly since the black border around
	   Black Key is thicker." It does — 4px against 2px is 4px of width, so
	   everything inside shifts 2px on every switch. Side by side the heavier
	   border is what says which card the page is arguing for; one at a time it
	   says nothing, because there is nothing beside it to be heavier THAN.
	   The "no initiation fee" badge still does that job. */
	.plans.two.switched .plan.lead { border-width: 2px; }

	/* ── the menu ────────────────────────────────────────────────────────
	   "Any chance when you click the hamburger rather than a full screen
	   appearing with the nav links that it instead was just … smaller? Like
	   only extended to the bottom of the links?"

	   WordPress's overlay is `position: fixed; inset: 0` — a modal, covering
	   a page the reader was in the middle of. Anchored to the bar instead it
	   is a drop-down as tall as its own contents. The 46px margin and 56px
	   padding inside it are there to clear a full-screen close button; the x
	   sits in the corner of the panel now, so they go and 22px of clearance
	   replaces them. */
	.wonder-topbar { position: relative; }
	/* The panel's `left: 0; right: 0` resolve against its nearest POSITIONED
	   ancestor, and core makes the `<nav>` relative — so the drop-down came
	   out 36px wide, the width of the hamburger. Standing the nav down hands
	   the job to the bar, which is the full width of the screen. */
	.wonder-topbar .wp-block-navigation { position: static; }
	.wonder-topbar .wp-block-navigation__responsive-container.is-menu-open {
		position: absolute;
		top: 100%;
		left: 0;
		right: 0;
		bottom: auto;
		padding: 12px 18px 8px;
		border-bottom: 2px solid var(--k);
	}
	/* Core writes both of these from `.is-menu-open`, which is two classes
	   deep — so naming the bar alone lost, and the panel kept 46px of margin
	   and 56px of padding meant to clear a full-screen close button. Both
	   selectors are matched here and outrun by one. */
	.wonder-topbar .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog { margin-top: 0; }
	.wonder-topbar .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content { padding-top: 20px; gap: 0; }
	.wonder-topbar .wp-block-navigation__responsive-container-close { top: -4px; right: 0; }
	.wonder-topbar .wp-block-navigation__container { gap: 0; }
	.wonder-topbar .wp-block-navigation-item { border-bottom: 2px solid rgba(0, 0, 0, 0.1); }
	.wonder-topbar .wp-block-navigation-item:last-child { border-bottom: 0; }
	/* A 23px row is a line of type, not a target — two links 23px apart on a
	   phone is a mis-tap waiting to happen. 10px either side makes each row
	   about 43px, which is the size a thumb expects. Written from
	   `.is-menu-open` because core's own padding rule is that deep. */
	.wonder-topbar .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content { display: block; width: 100%; padding: 10px 0; }

	/* The theme posters, for the same reason as the add-ons above. */
	.carousel .track > * { flex-basis: calc((100% - 18px) / 2); }
}
