/* ===========================================================================
   Kidsee — style-extended.css
   Full visual system. Tokens harvested from the source Webflow site
   (see ../../DESIGN-TOKENS.md). Mobile-first. Phase 1 base — Phase 2 adds
   the landing section styles.
   =========================================================================== */

:root {
	/* Brand — periwinkle.
	   NOTE: #7c83fd is the colour the source actually paints every CTA with.
	   #6157f8 exists as a `--primary-button` token in the source CSS but is only
	   ever used for text/link accents, never for button fills. Don't swap them. */
	--kidsee-primary:      #7c83fd;
	--kidsee-primary-hover:#5e65e2;
	--kidsee-primary-down: #43464d;
	--kidsee-primary-deep: #6157f8;
	--kidsee-primary-600:  #7c83fd;
	--kidsee-primary-800:  #472def;
	--kidsee-primary-200:  #9e97ff;
	--kidsee-primary-100:  #c9c6ff;   /* lavender panel behind the About role portraits */
	--kidsee-primary-050:  #f0ecfd;

	/* Accent — warm coral */
	--kidsee-accent-600:   #e6724c;
	--kidsee-accent-400:   #ff8963;
	--kidsee-accent-300:   #ffad92;
	--kidsee-accent-100:   #fff3ef;

	/* Secondary / status */
	--kidsee-secondary:    #00a1c1;
	--kidsee-warning:      #f8b34b;

	/* Text */
	--kidsee-text:         #2b3a55;
	--kidsee-text-strong:  #19213d;
	--kidsee-text-muted:   #5f6570;
	--kidsee-text-faint:   #626a85;   /* darkened from the source's #6d758f: 16px quote text now clears 4.5:1 */

	/* Backgrounds & surfaces.
	   The source page is white overall, with warm #fff8f2 washes at the hero,
	   the feature-tabs band and the usage band — not a peach page background. */
	--kidsee-bg:           #ffffff;
	--kidsee-warm:         #fff8f2;
	--kidsee-hero-bg:      #ffeee1;
	--kidsee-surface:      #ffffff;
	--kidsee-surface-alt:  #efeef7;
	--kidsee-border:       #e1e4ed;
	--kidsee-grey-050:     #f2f3f7;
	--kidsee-footer-bg:    #2b3a55;
	--kidsee-store-tile:   #e4eeff;
	/* Footer "small" store badge tile — width/height/gap as variables so the
	   footer grid (.foot-cols, below) can size its download column from the
	   same numbers instead of a duplicated literal. */
	--kidsee-store-badge-size: 56px;
	--kidsee-store-badge-gap:  12px;

	/* Type */
	--kidsee-font: "Mulish", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

	/* Radii */
	--kidsee-r-card:   28px;
	--kidsee-r-tile:   32px;
	--kidsee-r-btn:    20px;
	--kidsee-r-cta:    38px;
	--kidsee-r-sm:     8px;
	--kidsee-r-md:     16px;
	--kidsee-r-lg:     24px;
	--kidsee-r-pill:   100px;

	/* Layout */
	--kidsee-container: 1140px;
	--kidsee-gutter:    24px;
	--kidsee-header-h:  92px;   /* .top-inner's rendered height (min-height, border-box) — keep in sync if that changes */

	/* Elevation — source uses one soft blue-grey shadow everywhere */
	--kidsee-shadow-card: 0 4px 20px rgba(111, 121, 141, .18);
	--kidsee-shadow-tab:  0 4px 15px rgba(111, 121, 141, .18);
	--kidsee-shadow-btn:  0 1px 5px rgba(75, 75, 75, .08);
	--kidsee-shadow-btn-h: 0 10px 24px rgba(124, 131, 253, .35);
	/* Promo island / modal (inc/promo-island.php) — deep-indigo-tinted, one
	   size up from --kidsee-shadow-btn-h, since the floating pill and the
	   modal card both sit on top of page content rather than inside it. */
	--kidsee-shadow-promo:       0 10px 26px rgba(71, 45, 239, .30);
	--kidsee-shadow-promo-h:     0 14px 32px rgba(71, 45, 239, .40);
	--kidsee-shadow-promo-modal: 0 30px 70px rgba(25, 33, 61, .45);

	/* Motion.
	   Unhurried on purpose: state changes settle over ~a third of a second and
	   entrances take a full second, all on the same exponential ease-out. Keep
	   related properties on ONE duration — mixed speeds on a single element are
	   what made the earlier hover read as twitchy rather than calm. */
	--kidsee-ease:      cubic-bezier(.22, .61, .36, 1);
	--kidsee-out:       cubic-bezier(.16, 1, .3, 1); /* exponential ease-out */
	--kidsee-t-fast:    .24s;
	--kidsee-t-base:    .34s;
	--kidsee-t-slow:    .55s;
	--kidsee-t-enter:   1s;   /* first-appearance reveals only */

	/* Misc accents */
	--kidsee-star:        #ffb800;
	--kidsee-badge-bg:    #e4dcff;
	--kidsee-btn-2-hover: #e6e4f3;
	--kidsee-on-dark-dim: rgba(255, 255, 255, .66);
	--kidsee-on-dark-hov: #dad9e8;
}

/* Reduced motion: remove travel and looping animation, but keep colour and
   shadow response so hover, focus and open/closed states still read. */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .001ms !important;
		animation-iteration-count: 1 !important;
		scroll-behavior: auto !important;
		transition-property: color, background-color, border-color, box-shadow, opacity, outline-color !important;
	}
	.btn:hover, .cta-pill:hover, .btn-primary:hover,
	.usage-card:hover, .testimonial-card:hover, .price-card:hover,
	.blog-card:hover, .tab-switcher__tab:hover,
	.store-buttons--small .store-btn:hover {
		transform: none !important;
	}
}

/* --- Base ---------------------------------------------------------------- */

/* Smooth in-page anchor jumps (article table of contents). The reduced-motion
   block above already forces this back to `auto` — nothing extra needed there. */
html { scroll-behavior: smooth; }

/* Sticky footer. Body's DOM order is already header → #main-content → footer
   (header.php / footer.php), so this is a flex column on the existing three
   siblings — no markup change. `#main-content` is the only side that grows;
   header and footer keep their natural height and the footer lands on the
   viewport's bottom edge on short pages (e.g. a blog index with no posts in
   the current language) instead of floating above bare background.
   Height: `100vh` first as a fallback, then `100svh` (small viewport height)
   overrides it — a browser that doesn't understand `svh` just ignores that
   line and keeps `vh`. Plain `vh` on mobile is pinned to the LARGEST
   viewport (browser chrome hidden), so a page sized with it sits taller than
   the chrome-visible viewport and the footer visibly jumps as the address
   bar collapses/expands on scroll. `svh` is pinned to the viewport with
   chrome always shown, so the fill height never jumps.
   WordPress' admin bar (`#wpadminbar`, shown here because Playground
   auto-logs in) is `position: fixed` — a fixed-position child of a flex
   container is taken out of flex layout entirely (CSS Flexbox §4: it's
   sized/placed like any other out-of-flow absolute box), so it never
   becomes a flex item, never gets a track of its own, and adds no gap. */
body {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	min-height: 100svh;
	font-family: var(--kidsee-font);
	color: var(--kidsee-text);
	background: var(--kidsee-bg);
	line-height: 1.6;
}
#main-content { flex: 1 0 auto; }

/* Type scale — mirrors the source: one weight (800) for display headings,
   a tight 1.1–1.2 leading, and 18px body copy in the same ink as the headings. */
h1, h2, h3, h4, h5 {
	color: var(--kidsee-text);
	font-weight: 800;
	line-height: 1.15;
	margin: 0 0 .5em;
	text-wrap: balance;
}

h1 { font-size: clamp(32px, 6.2vw, 48px); line-height: 1.2; letter-spacing: -.015em; }
h2 { font-size: clamp(28px, 4.6vw, 36px); line-height: 1.15; letter-spacing: -.01em; }
h3 { font-size: clamp(20px, 3vw, 24px); }
h4 { font-size: 18px; }
h5 { font-size: 15px; }

p {
	margin: 0 0 1em;
	color: var(--kidsee-text);
	font-size: 18px;
	line-height: 1.55;
}

a { color: inherit; }

:where(a, button, summary, [tabindex]):focus-visible {
	outline: 3px solid var(--kidsee-primary);
	outline-offset: 3px;
	border-radius: var(--kidsee-r-sm);
}

/* --- Text roles ----------------------------------------------------------
   Six roles, and nothing outside them. Elements keep their semantics (an h2 is
   still an h2); these classes name the *role* so a heading that must not be an
   h2, or body copy inside a card, still lands on the same scale. Never set a
   raw font-size in a component — reach for one of these first.
   ------------------------------------------------------------------------- */

.t-display {            /* page-opening statement — one per page */
	font-size: clamp(32px, 6.2vw, 48px);
	line-height: 1.2;
	font-weight: 800;
	letter-spacing: -.015em;
	color: var(--kidsee-text);
}
.t-title {              /* section heading */
	font-size: clamp(28px, 4.6vw, 36px);
	line-height: 1.15;
	font-weight: 800;
	letter-spacing: -.01em;
	color: var(--kidsee-text);
}
.t-subtitle {           /* card / block heading */
	font-size: clamp(20px, 3vw, 24px);
	line-height: 1.25;
	font-weight: 700;
	color: var(--kidsee-text);
}
.t-lead {               /* supporting line under a heading */
	font-size: 18px;
	line-height: 28px;
	color: var(--kidsee-text);
}
.t-body {               /* running copy */
	font-size: 18px;
	line-height: 1.55;
	color: var(--kidsee-text);
}
.t-meta {               /* dates, roles, fine print */
	font-size: 14px;
	line-height: 20px;
	color: var(--kidsee-text-faint);
}
.t-label {              /* the small label above a group */
	font-size: 15px;
	line-height: 1.4;
	color: var(--kidsee-text-faint);
}

/* --- Section heading component ------------------------------------------- */

.section-heading {
	display: flex;
	flex-direction: column;
	gap: 16px;
	margin-bottom: 40px;
}
.section-heading--center { align-items: center; text-align: center; }
.section-heading--start  { align-items: flex-start; text-align: left; }
/* `level: 'h1'` (page-pricing.php's page header) renders an <h1> instead of
   the default <h2> — same selectors cover both so the tag never picks up an
   extra browser-default margin or misses the on-dark ink swap. */
.section-heading > h1,
.section-heading > h2 { margin: 0; }
.section-heading__lead { margin: 0; max-width: 620px; }
.section-heading--on-dark > h1,
.section-heading--on-dark > h2,
.section-heading--on-dark .section-heading__lead { color: #fff; }

/* Per-section spacing lives here, in one place, rather than as a stray
   `h2 { margin-bottom }` inside each section's block. */
.usage-section .section-heading        { margin-bottom: 0; }
.pricing-section .section-heading      { margin-bottom: 56px; }
.testimonials-section .section-heading { gap: 32px; max-width: 530px; margin-inline: auto; margin-bottom: 56px; }
.faq-section .section-heading          { margin-bottom: 32px; }
.pricing-page-header .section-heading  { margin-bottom: 0; }
.blog-section .section-heading         { margin-bottom: 28px; }

.wrap {
	width: 100%;
	max-width: var(--kidsee-container);
	margin-inline: auto;
	padding-inline: var(--kidsee-gutter);
}

.section { padding-block: 56px; }
@media (min-width: 768px) { .section { padding-block: 88px; } }

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	background: var(--kidsee-primary);
	color: #fff;
	padding: 10px 16px;
	border-radius: 0 0 var(--kidsee-r-sm) 0;
	z-index: 1000;
}
.skip-link:focus { left: 0; }

/* --- Buttons ------------------------------------------------------------- */

/* Two sizes only, matching the source:
   .btn        — inline CTA inside a section (48px tall, radius 24)
   .btn--lg    — the page's hero/section CTAs (70px tall, pill)
   .cta-pill   — the compact header button (radius 20) */
.btn,
.cta-pill,
.btn-primary {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	font-family: var(--kidsee-font);
	font-weight: 700;
	font-size: 19px;
	line-height: 1.2;
	padding: 15px 26px;
	border: 1px solid var(--kidsee-primary);
	border-radius: var(--kidsee-r-lg);
	background: var(--kidsee-primary);
	color: #fff;
	cursor: pointer;
	text-decoration: none;
	box-shadow: var(--kidsee-shadow-btn);
	transition:
		background-color var(--kidsee-t-base) var(--kidsee-out),
		transform var(--kidsee-t-base) var(--kidsee-out),
		box-shadow var(--kidsee-t-base) var(--kidsee-out);
}
.btn:hover,
.cta-pill:hover,
.btn-primary:hover {
	background: var(--kidsee-primary-hover);
	border-color: var(--kidsee-primary-hover);
	box-shadow: var(--kidsee-shadow-btn-h);
	transform: translateY(-2px);
}
.btn:active,
.cta-pill:active,
.btn-primary:active {
	background: var(--kidsee-primary-down);
	border-color: var(--kidsee-primary-down);
	transform: translateY(0);
	box-shadow: var(--kidsee-shadow-btn);
}

/* Large CTA — the 70px pill the source uses for every headline call to action. */
.btn--lg {
	min-height: 70px;
	padding: 20px 40px;
	border-radius: var(--kidsee-r-cta);
	font-size: 19px;
}

.cta-pill {
	padding: 12px 24px;
	font-size: 17px;
	font-weight: 700;
	border-radius: var(--kidsee-r-btn);
}

.btn-secondary {
	background: var(--kidsee-surface-alt);
	color: var(--kidsee-text-strong);
	border: 1px solid var(--kidsee-border);
}
.btn-secondary:hover {
	background: var(--kidsee-btn-2-hover);
	border-color: var(--kidsee-border);
	color: var(--kidsee-text-strong);
	box-shadow: var(--kidsee-shadow-card);
}

/* --- Icons ---------------------------------------------------------------
   Lucide geometry (24×24, 2px round caps) inlined by kidsee_icon(). Each icon
   carries its own state change, driven by the open/expanded state of whatever
   contains it — so a toggle never has to swap one icon for another.
   ------------------------------------------------------------------------- */

.icon {
	display: block;
	flex: none;
	width: 20px;
	height: 20px;
	overflow: visible;
}
.icon .icon__bar,
.icon path {
	transition:
		transform var(--kidsee-t-base) var(--kidsee-out),
		opacity var(--kidsee-t-fast) var(--kidsee-ease);
	transform-box: view-box;
	transform-origin: 12px 12px;
}

/* menu → close. The outer bars slide onto the centre line and cross; the middle
   one collapses into them. Reads as one continuous fold rather than a swap. */
.menu-toggle[open] .icon--menu .icon__bar--top { transform: rotate(45deg) translateY(6px); }
.menu-toggle[open] .icon--menu .icon__bar--bot { transform: rotate(-45deg) translateY(-6px); }
.menu-toggle[open] .icon--menu .icon__bar--mid { opacity: 0; transform: scaleX(.4); }

/* chevron — flips when its menu opens, wherever that menu lives. */
.nav-dropdown.is-open .icon--chevron-down,
.menu-links__submenu[open] .icon--chevron-down { transform: rotate(180deg); }
.icon--chevron-down {
	transition: transform var(--kidsee-t-base) var(--kidsee-out);
	transform-origin: center;
}

/* plus → minus. The upright stroke spins a quarter turn onto the horizontal
   one and fades as it lands, so open and closed share the same silhouette. */
.qa[open] .icon--plus .icon__bar--v { transform: rotate(90deg); opacity: 0; }
.qa[open] .icon--plus { transform: rotate(180deg); }
.icon--plus {
	transition: transform var(--kidsee-t-slow) var(--kidsee-out);
	transform-origin: center;
}

/* arrow-right — "Read more" affordance on the featured post and blog cards.
   The head slides forward from the shaft on hover. `<line>`/`<polyline>`
   aren't covered by the generic `.icon__bar, .icon path` transition above,
   so they get their own. */
.icon--arrow-right .icon__shaft,
.icon--arrow-right .icon__head {
	transition: transform var(--kidsee-t-base) var(--kidsee-out);
	transform-box: view-box;
	transform-origin: 12px 12px;
}
.blog-card:hover .icon--arrow-right .icon__head,
.blog-featured:hover .icon--arrow-right .icon__head {
	transform: translateX(3px);
}

/* --- Header / top bar ---------------------------------------------------- */

.top-bar {
	position: sticky;
	top: 0;
	z-index: 100;
	background: var(--kidsee-surface);
	transition: box-shadow var(--kidsee-t-base) var(--kidsee-ease);
}
/* Source has a flat white bar; the shadow only appears once the page scrolls
   under it, so the header stays legible without adding a permanent border. */
.top-bar.is-scrolled { box-shadow: 0 2px 16px rgba(43, 58, 85, .10); }

.top-inner {
	display: flex;
	align-items: center;
	gap: 20px;
	min-height: 92px;
	max-width: var(--kidsee-container);
	margin-inline: auto;
	padding: 10px var(--kidsee-gutter);
}
.logo { display: inline-flex; align-items: center; }
.logo-img { height: 35px; width: auto; }

/* Nav sits hard right and carries the language switcher + CTA as its last items. */
.top-nav {
	display: none;
	align-items: center;
	gap: 4px;
	margin-left: auto;
}
/* Nav-link styling must not reach the CTA — it is a button, not a nav link, and
   inherits the shared .btn treatment instead (see .cta-pill). */
.top-nav > a:not(.cta-pill),
.top-nav .nav-dropdown__toggle {
	font-weight: 500;
	font-size: 18px;
	line-height: 20px;
	padding: 10px 16px;
	color: var(--kidsee-text);
	white-space: nowrap;
	transition: color var(--kidsee-t-base) var(--kidsee-ease);
}
.top-nav > a:not(.cta-pill):hover,
.top-nav .nav-dropdown__toggle:hover { color: var(--kidsee-primary-deep); }
.top-nav .cta-pill { margin-left: 12px; white-space: nowrap; }

.top-right {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-left: auto;
}

@media (min-width: 992px) {
	.top-nav { display: flex; }
	.top-right { margin-left: 0; }
}

/* --- Nav dropdown (shared: language switcher + Features menu) ------------ */

/* Both header dropdowns (Features, language) are plain nav items in the source —
   no pill, no border — with a floating white card below. */
.nav-dropdown { position: relative; }
.nav-dropdown__toggle {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	background: none;
	border: none;
	padding: 10px 16px;
	font-family: inherit;
	font-weight: 500;
	font-size: 18px;
	line-height: 20px;
	color: var(--kidsee-text);
	cursor: pointer;
}
.nav-dropdown__arrow { width: 18px; height: 18px; }
.nav-dropdown__list {
	position: absolute;
	right: 0;
	top: calc(100% + 4px);
	min-width: 180px;
	list-style: none;
	margin: 0;
	padding: 6px;
	background: var(--kidsee-surface);
	border-radius: var(--kidsee-r-md);
	box-shadow: 0 4px 20px rgba(111, 121, 141, .28);
	display: none;
	z-index: 200;
}
.nav-dropdown.is-open .nav-dropdown__list {
	display: block;
	animation: kidsee-dropdown-in var(--kidsee-t-slow) var(--kidsee-out);
}
@keyframes kidsee-dropdown-in {
	from { opacity: 0; transform: translateY(-6px); }
	to   { opacity: 1; transform: none; }
}
.nav-dropdown__list li { margin: 0; }
.nav-dropdown__list a {
	display: block;
	padding: 10px 14px;
	border-radius: var(--kidsee-r-sm);
	font-size: 16px;
	line-height: 18px;
	font-weight: 500;
	white-space: nowrap;
	transition: background-color var(--kidsee-t-fast) var(--kidsee-ease), color var(--kidsee-t-fast) var(--kidsee-ease);
}
.nav-dropdown__list a:hover { background: var(--kidsee-primary-050); color: var(--kidsee-primary-deep); }
.nav-dropdown__list li[aria-selected="true"] a { color: var(--kidsee-primary-deep); font-weight: 700; }

.features-dropdown .nav-dropdown__list { left: 0; right: auto; min-width: 200px; }

/* --- Mobile menu (details/summary) --------------------------------------- */

.menu-toggle { position: relative; }
.menu-toggle summary {
	list-style: none;
	cursor: pointer;
	width: 44px;
	height: 44px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: var(--kidsee-r-sm);
}
.menu-toggle summary::-webkit-details-marker { display: none; }
.menu-icon { width: 26px; height: 26px; color: var(--kidsee-text); }

.menu-panel {
	position: absolute;
	right: 0;
	top: calc(100% + 10px);
	width: min(88vw, 320px);
	background: var(--kidsee-surface);
	border: 1px solid var(--kidsee-border);
	border-radius: var(--kidsee-r-md);
	box-shadow: var(--kidsee-shadow-card);
	padding: 16px;
	display: flex;
	flex-direction: column;
	gap: 12px;
}
.menu-links { display: flex; flex-direction: column; gap: 2px; }
/* Every row in the phone menu is a full 44px touch target. */
.menu-links a,
.menu-links__submenu summary {
	display: flex;
	align-items: center;
	min-height: 44px;
	padding: 8px 6px;
	font-weight: 600;
	font-size: 17px;
	border-radius: var(--kidsee-r-sm);
}
.menu-links a:hover,
.menu-links__submenu summary:hover { background: var(--kidsee-primary-050); }
.menu-links__submenu summary { cursor: pointer; list-style: none; justify-content: space-between; }
.menu-links__submenu summary::-webkit-details-marker { display: none; }
.menu-links__chevron { width: 18px; height: 18px; color: var(--kidsee-text-faint); }
.menu-links__submenu a { padding-left: 22px; font-weight: 500; font-size: 16px; }
.menu-meta { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--kidsee-text-faint); }
.menu-lang { display: flex; flex-wrap: wrap; gap: 6px; }
.menu-lang__btn {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 8px 14px;
	border: 1px solid var(--kidsee-border);
	border-radius: var(--kidsee-r-pill);
	font-size: 14px;
	font-weight: 600;
}
.menu-lang__btn.is-active { background: var(--kidsee-primary); color: #fff; border-color: var(--kidsee-primary); }

@media (min-width: 992px) {
	.menu-toggle { display: none; }
}

/* --- Store badges -------------------------------------------------------- */

.store-buttons { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.store-btn img { height: 44px; width: auto; display: block; }

/* Footer treatment: icon on a tinted tile, per the source. */
.store-buttons--small { gap: var(--kidsee-store-badge-gap); }
.store-buttons--small .store-btn {
	display: grid;
	place-items: center;
	width: var(--kidsee-store-badge-size);
	height: var(--kidsee-store-badge-size);
	background: var(--kidsee-store-tile);
	border-radius: var(--kidsee-r-lg);
	transition: background-color var(--kidsee-t-base) var(--kidsee-ease), transform var(--kidsee-t-base) var(--kidsee-ease);
}
.store-buttons--small .store-btn:hover { background: #fff; transform: translateY(-2px); }
.store-buttons--small .store-btn img { height: 26px; width: auto; }

/* --- Footer -------------------------------------------------------------- */

.site-footer {
	background: var(--kidsee-footer-bg);
	color: #fff;
	padding-block: 72px;
}
.foot-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 40px;
	justify-items: center;
	text-align: center;
}
.foot-brand { display: grid; gap: 28px; justify-items: center; max-width: 320px; }
.foot-brand .logo-img { height: 35px; }
.foot-copy { color: rgba(255, 255, 255, .6); font-size: 13px; line-height: 24px; margin: 0; }

.foot-cols {
	display: grid;
	grid-template-columns: 1fr;
	gap: 40px;
	width: 100%;
	justify-items: center;
}
/* Tablet folds the footer to two columns instead of jumping 1 → 3 at 992. */
@media (min-width: 600px) and (max-width: 991px) {
	.foot-cols {
		grid-template-columns: repeat(2, auto);
		justify-content: center;
		justify-items: start;
		gap: 40px 64px;
		text-align: left;
	}
	.foot-contact { grid-column: 1 / -1; }
	.foot-support, .foot-download { align-items: flex-start; }
}
.foot-col { display: flex; flex-direction: column; gap: 12px; }
/* The footer is an inverted surface: it carries its own on-dark text roles
   rather than the light-surface .t-* utilities. */
.foot-col__label { color: var(--kidsee-on-dark-dim); font-size: 15px; line-height: 1.6; }
.foot-col a {
	color: #fff;
	font-size: 16px;
	line-height: 24px;
	transition: color var(--kidsee-t-slow) var(--kidsee-ease);
}
.foot-col a:hover { color: var(--kidsee-on-dark-hov); }
.foot-contact { gap: 24px; }
.foot-support, .foot-download { display: flex; flex-direction: column; gap: 12px; align-items: center; }
/* Measured on the live source 2026-08-18: 17px, weight 400, line-height 24px
   — not the 24px/700 this rule used to declare. That declaration never
   applied anyway: `.foot-col a` (class + type) outranks a lone `.foot-email`
   class, so the size silently lost while the weight won. Selector raised to
   actually take effect, values matched to the source, and the 30px desktop
   override below removed as dead. */
.foot-col a.foot-email { font-size: 17px; font-weight: 400; line-height: 24px; }

@media (min-width: 992px) {
	.foot-grid {
		grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
		gap: 80px;
		justify-items: start;
		text-align: left;
	}
	.foot-brand { justify-items: start; }
	.foot-cols {
		/* Column-gap matches the tablet breakpoint's 64px above, not the wider
		   80px this used to carry: at this grid's actual rendered width (the
		   `.wrap` max-width caps it well before most desktop viewports), three
		   `auto` columns already outgrow the space, so `auto auto auto` here
		   compresses every column below its content's natural width — the
		   16px this reclaims goes back into that shrunk content instead of
		   idle gutter. (The badge-column floor that stops the 4th badge from
		   wrapping lives in the next breakpoint down — see the comment there
		   for why it can't live here.) */
		grid-template-columns: auto auto auto;
		justify-content: space-between;
		justify-items: start;
		gap: 40px 64px;
		padding-top: 16px;
	}
	.foot-support, .foot-download { align-items: flex-start; }
}

/* 992-1187px: the same defect, solved the other way round. A floor on the
   badge column alone overflows here (see the 1188px comment below), but only
   because the two nav columns are plain `auto` tracks: an `auto` track refuses
   to shrink below its max-content width, so the floor has nowhere to take
   space from except the grid's own width. Switching them to `minmax(0, auto)`
   lets them shrink and wrap their links instead — then the floor is
   satisfiable inside the container. Tile drops to 44px with an 8px gap, which
   is exactly the 44px touch-target minimum and puts the floor at 200px:
   measured, `.foot-cols` is 637px at a 1100px viewport and ~529px at 992px,
   both of which clear 200px + 2 × 40px gaps with the nav columns wrapping. */
@media (min-width: 992px) and (max-width: 1187.98px) {
	.foot-cols {
		--kidsee-store-badge-size: 44px;
		--kidsee-store-badge-gap: 8px;
		grid-template-columns:
			minmax(0, auto)
			minmax(0, auto)
			minmax(calc(4 * var(--kidsee-store-badge-size) + 3 * var(--kidsee-store-badge-gap)), auto);
		column-gap: 40px;
	}
}

/* 1188px = --kidsee-container (1140px) + 2 × --kidsee-gutter (24px): the
   width at which `.wrap` hits its max-width and stops growing, so `.foot-cols`
   itself stops getting wider too. Below this, `.foot-cols` is still shrinking
   with the viewport and is often narrower than the 992px breakpoint's whole
   demand — a hard-px floor on the badge column there would win its space back
   from the two nav columns right up to the point of *outgrowing the grid
   itself* (a `minmax()` lower bound is a genuine floor: unlike a plain `auto`
   track it will not yield, so it forces the grid wider than its container
   once there isn't enough room for everyone, producing horizontal overflow).
   From 1188px up, `.foot-cols` width is constant, so the floor's effect on
   the two nav columns is knowable and was checked (uk/ru, the longest-label
   locales): it does not add any new wrapped nav link over what those columns
   already wrap without it. Below 1188px the badges fall back to wrapping to
   a second row, same as before this fix — not the target of this defect. */
@media (min-width: 1188px) {
	.foot-cols {
		/* Shrinking the tile from 56px to 48px here (still clear of the 44px
		   touch-target floor — see .store-btn) lowers what the floor below
		   needs to claim back from the two nav columns, from 260px to 228px. */
		--kidsee-store-badge-size: 48px;
		grid-template-columns: auto auto minmax(calc(4 * var(--kidsee-store-badge-size) + 3 * var(--kidsee-store-badge-gap)), auto);
	}
}


/* --- Card ----------------------------------------------------------------
   One surface treatment for the whole card family. Modifiers change only what
   genuinely differs; nothing re-declares the radius, fill or shadow.
     .card--tile   the wide soft tiles (usage, stat bar)
     .card--quote  testimonial
     .card--price  pricing plan
     .card--flat   no lift on hover (the FAQ row)
   ------------------------------------------------------------------------- */

.card {
	background: var(--kidsee-surface);
	border-radius: var(--kidsee-r-card);
	box-shadow: var(--kidsee-shadow-card);
}
.card--tile { border-radius: var(--kidsee-r-tile); }
.card--lift {
	transition:
		transform var(--kidsee-t-base) var(--kidsee-out),
		box-shadow var(--kidsee-t-base) var(--kidsee-out);
}
.card--lift:hover {
	transform: translateY(-4px);
	box-shadow: 0 14px 34px rgba(43, 58, 85, .16);
}

/* --- Blog stub list ------------------------------------------------------ */

.blog-list { list-style: none; padding: 0; }
.blog-list li { padding: 12px 0; border-bottom: 1px solid var(--kidsee-border); }
.blog-list a { font-weight: 700; font-size: 18px; }
.article-wrap { max-width: 728px; }

/* ===========================================================================
   Landing sections (Phase 2)
   =========================================================================== */

.center { text-align: center; }
.wrap--narrow { max-width: 760px; }
.eyebrow {
	display: inline-block;
	font-weight: 700;
	font-size: 14px;
	color: var(--kidsee-primary);
	background: var(--kidsee-primary-050);
	padding: 6px 14px;
	border-radius: var(--kidsee-r-pill);
	margin-bottom: 18px;
}
.subtitle { font-size: 17px; }

/* Stars */
.stars { display: inline-flex; gap: 2px; line-height: 0; }
.stars--warm { color: var(--kidsee-warning); }

/* --- Hero ---------------------------------------------------------------- */
.hero {
	background: linear-gradient(var(--kidsee-warm), var(--kidsee-warm) 71%, #fff);
	padding-top: 42px;
	padding-bottom: 50px;
	overflow: hidden;
}
.hero-inner {
	display: grid;
	grid-template-columns: 1fr;
	gap: 24px;
	align-items: center;
	text-align: center;
	justify-items: center;
}
.hero-copy { max-width: 445px; }
.hero-copy h1 { margin-bottom: 16px; }
.hero-sub {
	font-size: 18px;
	line-height: 24px;
	color: var(--kidsee-text);
	margin-bottom: 0;
}
.hero-cta { margin-top: 28px; }
/* rating: value stacked over its label, stars alongside — as on the source */
.hero-rating {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	margin-top: 28px;
}
.hero-rating__score { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 92px; }
.hero-rating strong { font-size: 26px; font-weight: 600; line-height: 31px; color: var(--kidsee-text); }
.hero-rating__label { color: var(--kidsee-text); font-size: 15px; line-height: 20px; }
.hero-media { width: 100%; }
.hero-media img { width: 100%; height: auto; }

/* No gap above: the hero art is cropped to its bottom edge, so the stat card
   reads as the base the composition sits on rather than a floating slab. */
.stat-bar {
	display: grid;
	grid-template-columns: 1fr;
	gap: 24px;
	padding: 32px 24px;
	margin-top: 0;
}
.stat { text-align: center; display: grid; gap: 12px; }
.stat__v { font-size: 40px; font-weight: 700; line-height: 1; color: var(--kidsee-text); }
.stat__l { font-size: 18px; font-weight: 600; line-height: 24px; color: rgba(43, 58, 85, .8); }

@media (min-width: 768px) {
	.hero { padding-top: 56px; }
	.stat-bar {
		grid-template-columns: repeat(3, 1fr);
		gap: 40px;
		border-radius: 48px;
		padding: 40px 48px;
	}
	.stat__v { font-size: 48px; }
}

@media (min-width: 992px) {
	.hero-inner {
		grid-template-columns: minmax(0, 445px) minmax(0, 1fr);
		gap: 40px;
		text-align: left;
		justify-items: stretch;
		align-items: center;
	}
	.hero-copy { max-width: 445px; }
	.hero-rating { margin-top: 28px; }
	.stat-bar { padding: 40px 90px; }
}

/* --- Split sections ------------------------------------------------------ */
.split-inner {
	display: grid;
	grid-template-columns: 1fr;
	gap: 28px;
	align-items: center;
	text-align: center;
	justify-items: center;
}
.split-media { width: 100%; }
.split-media img { width: 100%; height: auto; }
.split-copy h2 { margin-bottom: 16px; }
.split-copy p { line-height: 28px; }
.split-copy .btn { margin-top: 24px; }
/* DOM is always copy-then-media (see split.php) — this single, unconditional
   `order` flip is what makes '--media-left' visual-left both at the mobile
   single column (top) and the desktop two-column grid (left) below, with no
   markup duplication. Confirmed per-section against source-mirror: whichever
   side is visually left on desktop stays on top on mobile too — it is NOT a
   blanket "image always first on mobile" rule. */
.split--media-left .split-media { order: -1; }

/* Tinted band variant (source: .main-section.grey, background #f1f2ff →
   closest existing token --kidsee-surface-alt #efeef7, which is in fact the
   exact value the live site already uses for the same lavender bands
   elsewhere — see webflow.css). Full-bleed for free: .section has no
   max-width of its own, only .wrap inside is constrained, so a background
   here already runs edge to edge. Source keeps a constant 64px top+bottom
   padding on this band at every breakpoint (unlike the plain .section
   56/88 split), so this overrides padding-block outright rather than
   layering on top of it. */
.split--tint {
	background: var(--kidsee-surface-alt);
	padding-block: 64px;
}

@media (min-width: 992px) {
	.split-inner {
		grid-template-columns: 1fr 1fr;
		gap: 80px;
		text-align: left;
		justify-items: stretch;
	}
}

/* --- Tab switcher --------------------------------------------------------
   Source layout: a vertical stack of tab cards beside a single image panel.
   Below 992px the two stack, menu first. */
.tab-switcher {
	display: grid;
	grid-template-columns: 1fr;
	gap: 40px;
	align-items: center;
	justify-items: center;
}
.tab-switcher__menu {
	display: flex;
	flex-direction: column;
	gap: 16px;
	width: 100%;
	max-width: 370px;
}
.tab-switcher__tab {
	display: flex;
	align-items: center;
	gap: 18px;
	width: 100%;
	min-height: 84px;
	background: var(--kidsee-surface);
	border: 3px solid var(--kidsee-surface);
	border-radius: var(--kidsee-r-lg);
	padding: 16px 20px;
	text-align: left;
	font-family: inherit;
	font-size: 20px;
	font-weight: 500;
	line-height: 1.2;
	color: var(--kidsee-text);
	cursor: pointer;
	box-shadow: var(--kidsee-shadow-tab);
	transition:
		border-color var(--kidsee-t-base) var(--kidsee-out),
		box-shadow var(--kidsee-t-base) var(--kidsee-out),
		transform var(--kidsee-t-base) var(--kidsee-out);
}
.tab-switcher__tab:hover { transform: translateY(-2px); }
.tab-switcher__tab.is-active { border-color: var(--kidsee-primary); }
.tab-switcher__icon {
	flex: 0 0 auto;
	width: 28px;
	height: 28px;
	display: grid;
	place-items: center;
	color: var(--kidsee-primary);
}
.tab-switcher__icon svg,
.tab-switcher__icon img { width: 100%; height: 100%; object-fit: contain; }
.tab-switcher__panels { width: 100%; max-width: 550px; }
.tab-switcher__panel { display: none; }
.tab-switcher__panel.is-active { display: block; animation: kidsee-panel-in var(--kidsee-t-enter) var(--kidsee-out); }
@keyframes kidsee-panel-in {
	from { opacity: 0; transform: translateY(8px); }
	to   { opacity: 1; transform: none; }
}
.tab-switcher__panel img { width: 100%; height: auto; display: block; }
.feature-cta { text-align: center; margin-top: 40px; }

.feature-section {
	background: linear-gradient(#fff, var(--kidsee-warm));
}

@media (min-width: 992px) {
	.tab-switcher {
		grid-template-columns: minmax(0, 370px) minmax(0, 550px);
		gap: 120px;
		justify-content: center;
		justify-items: stretch;
	}
	.tab-switcher__tab { font-size: 20px; padding: 16px 24px; }
}

/* --- Usage --------------------------------------------------------------- */
.usage-section { background: var(--kidsee-warm); }
.usage-section .usage-media { margin: 16px 0 0; }
.usage-media img { width: 100%; height: auto; }
.usage-cards {
	display: grid;
	grid-template-columns: 1fr;
	gap: 22px;
}
.usage-card {
	padding: 40px 24px;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	text-align: center;
	font-size: 22px;
	font-weight: 500;
	line-height: 28px;
	color: var(--kidsee-text-strong);
}
.usage-card__title,
.usage-card__sub { font: inherit; color: inherit; }
@media (min-width: 768px) { .usage-cards { grid-template-columns: repeat(3, 1fr); } }

/* --- Pricing ------------------------------------------------------------- */
.pricing-section {
	background: var(--kidsee-primary);
	padding-block: 72px;
}
.on-primary { color: #fff; }
.pricing-cards {
	display: grid;
	grid-template-columns: 1fr;
	gap: 22px;
	max-width: 820px;
	margin-inline: auto;
}
.price-card {
	display: flex;
	flex-direction: column;
	gap: 24px;
	border: 1px solid rgba(43, 58, 85, .15);
	padding: 32px 24px;
	box-shadow: 0 3px 25px rgba(43, 58, 85, .15);
	transition: transform var(--kidsee-t-base) var(--kidsee-out), box-shadow var(--kidsee-t-base) var(--kidsee-out);
}
.price-card:hover { transform: translateY(-6px); box-shadow: 0 18px 40px rgba(25, 33, 61, .28); }
.price-card--featured { border: 3px solid var(--kidsee-text-strong); padding: 30px 22px; }
.price-card__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.price-card__plan { display: flex; align-items: center; gap: 10px; }
.price-card__icon { width: 38px; height: 38px; }
.price-card__name { font-size: 20px; font-weight: 700; color: var(--kidsee-text-strong); }
.price-badge {
	background: var(--kidsee-badge-bg);
	border: 1px solid var(--kidsee-border);
	color: var(--kidsee-text-strong);
	font-weight: 700;
	font-size: 14px;
	padding: 6px 14px;
	border-radius: 18px;
}
.price-card__amount { display: flex; align-items: baseline; gap: 6px; margin: -12px 0 -12px; }
.price-card__value { font-size: 40px; font-weight: 800; line-height: 1.1; color: var(--kidsee-text-strong); }
.price-card__period { color: var(--kidsee-text-faint); font-weight: 600; font-size: 16px; }
.price-card__note { color: var(--kidsee-text); font-size: 15px; line-height: 22px; }
.price-card__sub { color: var(--kidsee-text-faint); font-size: 14px; margin-top: -18px; }
.price-card__cta { width: 100%; margin-top: auto; }
@media (min-width: 768px) { .pricing-cards { grid-template-columns: 1fr 1fr; } }
@media (min-width: 992px) { .pricing-section { padding-block: 96px; } }

/* --- Testimonials --------------------------------------------------------
   Photo-backed band; card reads author → rating → quote, as on the source. */
.testimonials-section {
	background-image: linear-gradient(rgba(255, 248, 242, .35), rgba(255, 248, 242, .35)), url("assets/images/testimonials-bg.webp");
	background-position: 50%;
	background-size: cover;
	background-repeat: no-repeat;
	padding-block: 80px;
}
.testimonial-cards {
	display: grid;
	grid-template-columns: 1fr;
	gap: 22px;
	max-width: 1000px;
	margin-inline: auto;
}
.testimonial-card {
	display: flex;
	flex-direction: column;
	gap: 24px;
	margin: 0;
	padding: 24px 24px 27px;
}
.testimonial-card__author { display: flex; align-items: center; gap: 12px; padding-block: 4px; }
.testimonial-card__avatar { width: 48px; height: 48px; border-radius: 50%; flex: none; }
.testimonial-card__who { display: flex; flex-direction: column; }
.testimonial-card__who strong { font-size: 14px; font-weight: 600; line-height: 20px; color: var(--kidsee-text); }
.testimonial-card__who span { font-size: 14px; line-height: 20px; color: var(--kidsee-text-faint); }
.testimonial-card__quote {
	margin: 0;
	font-size: 16px;
	line-height: 22px;
	color: var(--kidsee-text-faint);
}
/* Below 992 a 3-up row squeezes each quote to ~22ch, so the cards stay
   single-column and centred instead of merely narrower. */
.testimonial-cards { max-width: 620px; }
@media (min-width: 992px) {
	.testimonial-cards { max-width: 1000px; grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 992px) { .testimonials-section { padding-block: 96px; } }

/* --- Blog strip ---------------------------------------------------------- */
.blog-cards {
	display: grid;
	grid-template-columns: 1fr;
	gap: 22px;
}
.blog-card {
	border-radius: var(--kidsee-r-md);
	overflow: hidden;
	display: block;
	transition: transform var(--kidsee-t-base) var(--kidsee-out), box-shadow var(--kidsee-t-base) var(--kidsee-out);
}
.blog-card:hover { transform: translateY(-3px); box-shadow: 0 14px 40px rgba(43,58,85,.14); }
.blog-card__media img { width: 100%; height: 180px; object-fit: cover; }
.blog-card__body { padding: 18px 20px 22px; }
.blog-card__date { font-size: 13px; color: var(--kidsee-text-faint); }
.blog-card__title { font-size: 18px; line-height: 1.3; font-weight: 700; margin: 8px 0 12px; }
/* Excerpt — grid cards only (the featured card has its own, unclamped
   .blog-featured__excerpt). Clamped to 4 lines per source spec. */
.blog-card__excerpt {
	color: var(--kidsee-text-muted);
	font-size: 14px;
	line-height: 1.5;
	margin: 0 0 14px;
	display: -webkit-box;
	-webkit-line-clamp: 4;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.blog-card__more {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	color: var(--kidsee-primary);
	font-weight: 700;
	font-size: 14px;
}
.blog-card__more-icon { width: 14px; height: 14px; flex: none; }
/* Grid breakpoints mirror the source `.collection-list-4`: 1 column up to
   767px, 2 columns 768–991px, 4 columns from 992px. Also governs the related-
   posts grid below (see its own comment further down) — same breakpoints
   apply evenly there. */
@media (min-width: 768px) { .blog-cards { grid-template-columns: 1fr 1fr; } }
@media (min-width: 992px) { .blog-cards { grid-template-columns: repeat(4, 1fr); } }

/* --- FAQ ----------------------------------------------------------------- */
.faq-section { background: var(--kidsee-surface-alt); padding-block: 64px; }
.faq-list { display: flex; flex-direction: column; gap: 12px; }
.qa {
	border-radius: var(--kidsee-r-md);
	overflow: hidden;
}
.qa summary {
	list-style: none;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 20px 22px;
	font-size: 18px;
	line-height: 1.4;
	font-weight: 700;
	color: var(--kidsee-text-strong);
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary:hover { color: var(--kidsee-primary-deep); }
.qa__q { flex: 1; }
.qa__icon { width: 22px; height: 22px; color: var(--kidsee-primary); }
.qa__answer { padding: 0 22px 20px; }
.qa__answer p { margin: 0; }

/* Open/close animates the panel's track height rather than its own height, so
   there is nothing to measure in JS and the text never reflows mid-transition.
   theme.js keeps the `open` attribute on long enough for the closing run.

   The grid item (.qa__clip) must carry NO padding or border. `overflow: hidden`
   clips content but not padding, so a 0fr track still resolves to the padding's
   height — which left a 20px sliver of the closing answer hanging on screen
   until the `open` attribute came off. Spacing belongs to .qa__answer inside. */
.qa__wrap {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows var(--kidsee-t-slow) var(--kidsee-out);
}
.qa__clip {
	overflow: hidden;
	min-height: 0;
	padding: 0;
	border: 0;
}
.qa.is-open .qa__wrap { grid-template-rows: 1fr; }
/* No-JS fallback: native <details> has no is-open class, so key off [open]. */
.qa[open]:not(.is-animatable) .qa__wrap { grid-template-rows: 1fr; }

/* The list reserves the height of its tallest answer (set by theme.js as a
   custom property), so opening a question never grows the section and nothing
   below it — footer included — moves. One panel is open at a time, which is
   what keeps that reservation to a single answer instead of all five. */
.faq-list { min-height: var(--kidsee-faq-min, auto); }

/* --- Blog index + single (Phase 3) --------------------------------------- */
.blog-index__title { margin-bottom: 28px; }
.blog-index__subhead { margin: 0; font-size: 22px; }

/* Featured post + promo banner, side by side — source `.container-14`
   (webflow.css:5696): flex row, gap 22px, column at <=991px. */
.blog-featured-row {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 22px;
}
@media (min-width: 992px) {
	/* stretch, not flex-start: the featured card and the promo banner beside
	   it must end at the same baseline. With flex-start the shorter of the two
	   kept its content height and the row looked ragged. */
	.blog-featured-row { flex-direction: row; align-items: stretch; }
	.blog-featured-row .blog-featured { flex: 1 1 auto; min-width: 0; }
}

.blog-featured {
	display: grid;
	grid-template-columns: 1fr;
	gap: 0;
	background: var(--kidsee-surface);
	border-radius: var(--kidsee-r-card);
	box-shadow: var(--kidsee-shadow-card);
	overflow: hidden;
	transition: transform var(--kidsee-t-base) var(--kidsee-out), box-shadow var(--kidsee-t-base) var(--kidsee-out);
}
.blog-featured:hover { transform: translateY(-3px); box-shadow: 0 16px 44px rgba(43,58,85,.16); }
.blog-featured__media img { width: 100%; height: 100%; object-fit: cover; max-height: 340px; }
.blog-featured__body { padding: 26px 28px 30px; }
.blog-featured__title { font-size: 26px; margin: 8px 0 12px; }
.blog-featured__excerpt { color: var(--kidsee-text-muted); }
@media (min-width: 768px) {
	.blog-featured { grid-template-columns: 1.2fr 1fr; }
	.blog-featured__body { align-self: center; }
	/* The card's height is set by the text column (and at >=992px by the
	   promo banner beside it), so the image must fill whatever height that
	   comes out to. The media cell already stretches as a grid item; the
	   image is taken out of flow inside it so it can cover the full cell
	   instead of keeping its intrinsic ratio and leaving white space below. */
	.blog-featured__media { position: relative; overflow: hidden; }
	.blog-featured__media img { position: absolute; inset: 0; max-height: none; }
}

/* "Latest articles" heading + decorative "All Articles" badge (source
   `.latest-articles` / `.actions-4` — a dead `href="#"` link on the source,
   rendered here as a non-interactive label; see home.php comment). */
.blog-index__latest-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin: 44px 0 22px;
}
.blog-index__all-badge {
	flex: none;
	background: var(--kidsee-surface-alt);
	border-radius: var(--kidsee-r-btn);
	padding: 10px 16px;
	font-size: 14px;
	font-weight: 700;
	color: var(--kidsee-text);
}

/* Promo banner — "Download Kidsee App For Free". Shared markup for both
   placements (blog index beside the featured post, article page in the
   rail); source `.card-3` (index) / `.card-7` (article) — see
   template-parts/promo-banner.php and the article-rail block further down. */
.promo-banner {
	display: flex;
	flex-direction: column;
	background: var(--kidsee-primary-600);
	border-radius: var(--kidsee-r-card);
	overflow: hidden;
	text-decoration: none;
	box-shadow: var(--kidsee-shadow-card);
	transition: transform var(--kidsee-t-base) var(--kidsee-out), box-shadow var(--kidsee-t-base) var(--kidsee-out);
}
.promo-banner:hover { transform: translateY(-3px); box-shadow: 0 16px 44px rgba(43,58,85,.16); }
.promo-banner__media { padding: 24px 24px 0; }
.promo-banner__media img { width: 100%; height: auto; display: block; }
.promo-banner__body { padding: 20px 24px 28px; display: flex; flex-direction: column; gap: 16px; }
.promo-banner__heading { margin: 0; color: #fff; font-size: 22px; font-weight: 800; line-height: 1.3; white-space: pre-line; }
.promo-banner__button {
	align-self: flex-start;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: #fff;
	color: var(--kidsee-text);
	font-weight: 700;
	font-size: 15px;
	border-radius: var(--kidsee-r-btn);
	padding: 12px 22px;
}

/* Index placement — bottom-anchored in a tall card, matches the featured
   post's height at desktop. */
.promo-banner--index { min-height: 414px; justify-content: flex-end; }
@media (min-width: 992px) {
	.promo-banner--index { flex: 0 0 320px; max-width: 320px; }
}

/* Single article */
.single-article__back { display: inline-block; color: var(--kidsee-primary); font-weight: 700; font-size: 14px; margin-bottom: 18px; }
.single-article__title { font-size: 32px; margin: 8px 0 22px; }
.single-article__hero img { width: 100%; border-radius: var(--kidsee-r-card); margin-bottom: 28px; }
@media (min-width: 768px) { .single-article__title { font-size: 40px; } }

/* Article column + promo-banner rail — source `.container-19`
   (webflow.css:6474): flex row, gap 40px, max-width 1106px; `.column-14`
   caps the article at max-width 716px. Mobile-first translation of the
   source's three breakpoints (webflow.css:17193 / 18225+18229 / 18999+19022):
     <480px  — rail below the article, banner itself stacked vertical/full-width
     480–767 — rail below the article, banner is a horizontal strip
     768–991 — rail beside the article (row), banner narrows to 280px
     >=992   — rail beside the article (row), banner at its full 348px width */
.single-article-layout {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 40px;
	max-width: 1106px;
	margin-inline: auto;
}
.single-article-layout__main { max-width: 716px; width: 100%; }
@media (min-width: 768px) {
	.single-article-layout { flex-direction: row; align-items: flex-start; }
}

/* Promo banner, article-rail variant (source `.card-7`). */
.promo-banner--article {
	width: 100%;
	max-width: none;
	flex-direction: column;
	/* Source webflow.css:6699 sets `position: sticky; top: 96px` on .card-7 —
	   the designer wants the banner static on desktop so it does not follow
	   the scroll. Change `static` back to `sticky` (and restore `top: 96px`)
	   to revert to the source behaviour. */
	position: static;
}
@media (min-width: 480px) {
	.promo-banner--article { flex-direction: row; align-items: center; }
}
@media (min-width: 768px) {
	.promo-banner--article { flex-direction: column; align-items: stretch; flex: 0 0 280px; max-width: 280px; }
}
@media (min-width: 992px) {
	.promo-banner--article { flex: 0 0 348px; max-width: 348px; }
}

.article-body { font-size: 17px; color: var(--kidsee-text); overflow-wrap: break-word; }
.article-body h2 { font-size: 26px; margin: 34px 0 14px; }
.article-body h3 { font-size: 21px; margin: 26px 0 12px; }
.article-body p { margin: 0 0 18px; color: var(--kidsee-text); }
.article-body ul, .article-body ol { margin: 0 0 18px; padding-left: 22px; }
.article-body li { margin-bottom: 8px; }
.article-body a { color: var(--kidsee-primary); font-weight: 600; text-decoration: underline; }
.article-body img { border-radius: var(--kidsee-r-md); margin: 20px 0; }
.article-body table {
	width: 100%; border-collapse: collapse; margin: 22px 0; font-size: 15px;
	display: block; overflow-x: auto;
}
.article-body th, .article-body td { border: 1px solid var(--kidsee-border); padding: 10px 12px; text-align: left; vertical-align: top; }
.article-body th { background: var(--kidsee-surface-alt); font-weight: 800; color: var(--kidsee-text-strong); }
.article-body blockquote {
	margin: 22px 0; padding: 14px 20px; border-left: 4px solid var(--kidsee-primary);
	background: var(--kidsee-primary-050); border-radius: 0 var(--kidsee-r-sm) var(--kidsee-r-sm) 0;
}

/* Article table of contents — source markup is `.table-of-contents` (a
   background-tinted rounded box, webflow.css) with an `<h6>Table of
   content</h6>` label and a plain <ul> of anchor links built at runtime by
   the source's own inline script; see kidsee_inject_article_toc() for our
   server-side equivalent. Colour/radius are literal source values (#f9fafa
   has no matching token; #7c83fd and 24px do — reused as tokens below).
   Lives inside .article-body, so link colour/weight need re-declaring —
   .article-body a otherwise wins the tie on specificity. */
.article-toc {
	background-color: #f9fafa;
	border-radius: var(--kidsee-r-lg);
	padding: 24px;
	margin: 0 0 16px;
}
.article-toc__heading {
	margin: 0 0 12px;
	font-size: 22px;
	font-weight: 500;
	line-height: 1.3;
	color: var(--kidsee-text-strong);
}
.article-toc__list { margin: 0; padding-left: 0; list-style: none; }
.article-toc__item { margin-bottom: 8px; }
.article-toc__item:last-child { margin-bottom: 0; }
.article-toc a {
	color: var(--kidsee-primary);
	font-size: 16px;
	font-weight: 400;
	text-decoration: none;
	word-break: break-word;
	overflow-wrap: anywhere;
}
.article-toc a:hover, .article-toc a:focus-visible { text-decoration: underline; }

/* Anchor targets for the ToC above — offset so the sticky header (92px,
   --kidsee-header-h) never covers the heading it jumps to. */
.article-body h2[id] { scroll-margin-top: calc(var(--kidsee-header-h) + 24px); }

.related-posts { margin-top: 56px; }
.related-posts h2 { margin-bottom: 24px; }

/* --- Feature cards (new; template-parts/feature-cards.php) ---------------
   Image + title + body, N-up. No homepage equivalent — built for the 4
   feature pages. 1-up on phones, 2-up from 768px; for exactly 4 items that
   same 2-up continues at desktop as a 2x2 grid rather than a single 4-up
   row — each card carries a real body paragraph, and 4 columns at the
   1140px container leave too little room for image + title + paragraph to
   read comfortably.
   2026-08-18: no card surface — source sits the image + text directly on
   the section background, so this no longer borrows .card/--tile/--lift
   (removed from the markup itself; nothing to override here). Gap widened
   from 24px to the source's own `.feature-row` rhythm for this section —
   40px base, 120px from 992px (same pair `.tab-switcher` already reuses
   for its desktop gap) — so each card reads as its own element instead of
   one continuous grid. */
.feature-cards {
	display: grid;
	grid-template-columns: 1fr;
	gap: 40px;
}
.feature-cards__card {
	display: flex;
	flex-direction: column;
	gap: 16px;
	text-align: left;
}
/* Fixed aspect-ratio box: source art ships at two close but different crops
   (545x338 and 545x344 — ours: 1012x628 and 1012x640), which misaligned
   grid rows by ~6px. Box uses the midpoint of the two source ratios so both
   crop by an equal, small amount under `cover`; no image file touched. The
   images' own rounded corners are baked into each webp's alpha channel
   (confirmed on the shipped assets), so this radius is additive safety for
   the container, not a second surface. */
.feature-cards__media {
	aspect-ratio: 545 / 341;
	border-radius: var(--kidsee-r-md);
	overflow: hidden;
}
.feature-cards__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.feature-cards__title,
.feature-cards__body { margin: 0; }
@media (min-width: 768px) {
	.feature-cards { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 992px) {
	.feature-cards { gap: 120px; }
}

/* --- CTA band (new; template-parts/cta-band.php) --------------------------
   Full-width band, heading + optional body + one CTA via section-heading.
   Two tones only, matching the pricing band's own treatment rather than
   introducing a third band style. */
.cta-band { text-align: center; }
.cta-band--default { background: var(--kidsee-warm); }
.cta-band--accent {
	background: var(--kidsee-primary);
	padding-block: 72px;
}
.cta-band .section-heading { margin-bottom: 0; }
/* On the accent band the CTA sits directly on periwinkle — a periwinkle-fill
   button there would be nearly invisible, so it inverts to a white fill with
   periwinkle text (the same on-dark hover tint the footer links already use)
   rather than introducing a new button variant. */
.cta-band--accent .btn-primary {
	background: #fff;
	border-color: #fff;
	color: var(--kidsee-primary);
}
.cta-band--accent .btn-primary:hover {
	background: var(--kidsee-on-dark-hov);
	border-color: var(--kidsee-on-dark-hov);
	color: var(--kidsee-primary-hover);
}
.cta-band--accent .btn-primary:active {
	background: var(--kidsee-primary-200);
	border-color: var(--kidsee-primary-200);
	color: var(--kidsee-primary-down);
}
@media (min-width: 992px) {
	.cta-band--accent { padding-block: 96px; }
}

/* --- Pricing bullets (optional; template-parts/pricing.php $args['bullets'])
   The homepage never passes this — only the pricing PAGE does. A simple
   token-consistent list; not a speculative layout, see the component's own
   doc comment for why. */
.pricing-bullets {
	list-style: none;
	margin: 40px 0 0;
	padding: 0;
	display: grid;
	gap: 12px;
	max-width: 620px;
	margin-inline: auto;
	text-align: center;
}
.pricing-bullets__item { color: #fff; }

/* Pricing page ---------------------------------------------------------------
   Everything new for page-pricing.php: the standalone <h1> header band, the
   icon+text bullet list (template-parts/pricing-bullets.php) and the
   `.pricing-section--page` variant of the shared pricing cards (see
   template-parts/pricing.php's docblock). See DESIGN-SYSTEM.md "Pricing
   bullets" and NOTES.md for why the bullets are their own template part
   rather than a redesign of the .pricing-bullets placeholder above (that
   placeholder is left exactly as-is — still reachable via
   template-parts/pricing.php's own `bullets` arg, just unused by this page).

   2026-08-21 fidelity pass (measured against the live source /pricing):
   the H1, the bullets and the two price cards sit on ONE continuous
   --kidsee-hero-bg panel there — not three separate blocks — and each
   bullet is a plain icon+text row with NO card/shadow (28px icon, 16px gap
   to the text, rows ~44-48px apart), not the boxed .card/.card--lift rows
   this used to carry. Bullet icon left edge lines up with the H1's own left
   edge (measured identical x on the source), which .wrap--narrow already
   gives us for free once the card padding stops pushing it inward. */

.pricing-page-header,
.pricing-bullets-section,
.pricing-section--page {
	background: var(--kidsee-hero-bg);
}
.pricing-page-header { padding-block: 48px 8px; }
@media (min-width: 768px) { .pricing-page-header { padding-block: 64px 8px; } }

.pricing-bullets-section { padding-block: 8px 40px; }

.pricing-bullet-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 16px;
}
.pricing-bullet-list__item {
	display: flex;
	align-items: center;
	gap: 16px;
}
.pricing-bullet-list__icon {
	flex: 0 0 auto;
	width: 28px;
	height: 28px;
	object-fit: contain;
}
.pricing-bullet-list__text { margin: 0; }

/* The shared pricing-cards markup (template-parts/pricing.php) is correct
   as-is for the homepage's own indigo band — this variant only fires on
   the dedicated page, where the source drops the indigo section background
   entirely (the cards float on the cream panel above) and fills the
   featured/Annual card itself with solid indigo instead of outlining it. */
.pricing-section--page { padding-block: 0 72px; }
@media (min-width: 992px) { .pricing-section--page { padding-block: 0 96px; } }
.pricing-section--page .price-card--featured {
	background: var(--kidsee-primary-deep);
	border: none;
	color: var(--kidsee-warm);
}
.pricing-section--page .price-card--featured .price-card__name,
.pricing-section--page .price-card--featured .price-card__note { color: var(--kidsee-warm); }
.pricing-section--page .price-card--featured .price-card__value,
.pricing-section--page .price-card--featured .price-card__period { color: #fff; }
.pricing-section--page .price-card--featured .price-card__sub { color: rgba(255, 248, 242, .75); }
.pricing-section--page .price-card--featured .price-badge {
	background: var(--kidsee-accent-300);
	color: var(--kidsee-text-strong);
	border-color: transparent;
}
.pricing-section--page .price-card--featured .price-card__cta {
	background: var(--kidsee-warm);
	color: var(--kidsee-text);
}

/* --- Remaining pages (Phase 4) ------------------------------------------- */

/* System pages (page.php): contact / support / legal */
.prose-shell { max-width: 760px; margin-inline: auto; padding-inline: var(--kidsee-gutter); }
.entry-card { background: var(--kidsee-surface); border-radius: var(--kidsee-r-card); box-shadow: var(--kidsee-shadow-card); padding: 32px 28px; }
.entry-title { font-size: 30px; margin-bottom: 20px; }
.entry-content { color: var(--kidsee-text); }
.entry-content p { color: var(--kidsee-text); }
.entry-content a { color: var(--kidsee-primary); font-weight: 600; }
@media (min-width: 768px) { .entry-title { font-size: 38px; } .entry-card { padding: 44px 48px; } }

.support-cancel-notice p { margin-bottom: 16px; }
.support-links { list-style: none; padding: 0; margin-top: 12px; }
.support-links li { padding: 4px 0; }

/* Legal */
.legal-updated { color: var(--kidsee-text-faint); font-size: 14px; margin-bottom: 24px; }
.legal-body h2 { font-size: 21px; margin: 28px 0 12px; }

/* Feature pages (2026-08-13 rebuild) --------------------------------------
   page-feature.php now composes its full section set (hero / stat-bar /
   feature-cards / split / teaser tab-switcher / pricing / testimonials /
   FAQ) entirely from the shared template parts above — see
   DESIGN-SYSTEM.md. Every one of those components already carries its own
   CSS; the only page-specific rule left is the hero band tint. The old
   `.feature-sections` / `.feature-block` placeholder rules (for the
   previous 2-paragraph body) are removed — nothing renders that markup
   anymore. */
.feature-hero { background: var(--kidsee-hero-bg); }

/* --- Download page (store-dispatch landing) ------------------------------
   Rebuilt against the Webflow source: source-mirror/en/download.html +
   webflow.css base rules at :4990-5115 and :15754 (`.store-link` pill).
   Breakpoints reproduced (source is max-width/desktop-first; this file
   stays mobile-first per the rest of the theme, so the same three
   thresholds appear here as min-width tiers):
     - base (<480px)   ← source's `max-width:479px` (webflow.css:18850)
     - ≥480px          ← source's unprefixed/default rules
     - ≥768px          ← source's `max-width:767px` (webflow.css:18212) — padding only
     - ≥992px          ← source's `max-width:991px` inverse (webflow.css:17131) —
                          the two columns are stacked+centered below this, side-by-side
                          above it.
   Verified live (kidsee.app/download-parental-control-app) at 1440/991/767/390:
   the badge row stays a 343px-capped 2×2 grid down to 480px, then — because
   the source's OWN `.store-link` rule sets `width:80%` at max-width:479
   (webflow.css:19842) — collapses to a single column below that. That single-
   column mobile behaviour is intentional fidelity to the source, not a bug. */
.download-hero { padding: 40px 15px; }
.download-row {
	display: grid;
	grid-template-columns: 1fr;
	row-gap: 40px;
	align-items: center;
	justify-items: center;
	text-align: center;
}
.download-copy {
	display: flex;
	flex-direction: column;
	align-items: center;
	row-gap: 40px;
	width: 100%;
}
.download-copy h1 {
	width: 100%;
	margin: 0;
	color: var(--kidsee-text-strong);
	font-size: 36px;
	line-height: 46px;
	white-space: pre-line; /* renders the \n from kidsee_localize_ui() as a line break — same convention as .promo-banner__heading */
}
.download-assets {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 40px;
	width: 100%;
}
.download-qr-link {
	display: inline-flex;
	border-radius: var(--kidsee-r-sm);
	transition: opacity var(--kidsee-t-base) var(--kidsee-ease);
}
.download-qr-link:hover, .download-qr-link:focus-visible { opacity: .85; }
.download-qr { width: 110px; height: 110px; border-radius: var(--kidsee-r-sm); }
.download-badges {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: flex-start;
	gap: 8px;
	max-width: 343px;
}
/* The dark pill the source wraps every badge in (webflow.css:15754,
   `.store-link { background-color: var(--dark-blue) }`) — --dark-blue is
   #2b3a55, which the theme already tokenizes as --kidsee-footer-bg (same
   navy the source itself reuses for its footer, webflow.css:4802). */
.download-badge {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 80%;
	height: 54px;
	padding-top: 2px;
	border-radius: var(--kidsee-r-pill);
	background-color: var(--kidsee-footer-bg);
	transition: background-color var(--kidsee-t-base) var(--kidsee-ease), transform var(--kidsee-t-base) var(--kidsee-ease);
}
.download-badge:hover {
	/* Source: var(--dark-blue-hover) = #24334d (webflow.css:2080). No token in
	   theme.json/style-extended.css covers this darker shade — hardcoded
	   verbatim rather than inventing a new custom property for one use. */
	background-color: #24334d;
	transform: translateY(-4px);
}
.download-badge img { height: 27px; width: auto; }
.download-visual { display: flex; justify-content: center; width: 100%; }
.download-visual__img { width: 100%; max-width: none; height: auto; border-radius: var(--kidsee-r-sm); }

@media (min-width: 480px) {
	.download-hero { padding: 60px 15px; }
	.download-copy h1 { font-size: 48px; line-height: 58px; }
	.download-qr { width: 151px; height: 151px; }
	.download-badges { gap: 12px; }
	.download-badge { width: 164px; height: 64px; }
	.download-visual__img { max-width: 482px; }
}

@media (min-width: 768px) {
	.download-hero { padding: 80px 24px 100px; }
}

@media (min-width: 992px) {
	.download-row {
		grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
		column-gap: 80px;
		justify-items: stretch;
		text-align: left;
	}
	.download-copy { align-items: flex-start; width: auto; }
	.download-assets { flex-direction: row; align-items: flex-start; width: auto; }
}

/* --- 404 (Phase 7) ------------------------------------------------------- */
.section--404 { padding-block: 90px; }
.error-404-code {
	font-size: 72px;
	font-weight: 800;
	color: var(--kidsee-primary);
	line-height: 1;
	margin: 0 0 8px;
}
.section--404 h1 { margin-bottom: 12px; }
.section--404 .btn { margin-top: 20px; }

/* ===========================================================================
   Motion & micro-interaction

   One grammar for the whole page: things arrive by rising 22px out of
   transparency on an exponential ease-out. The hero plays it as a staged
   entrance on load; card rows stagger their items; everything else moves once.
   JS only applies the pending state when motion is allowed, so no-JS and
   reduced-motion visitors get the finished layout with no transition at all.
   =========================================================================== */

/* The entrance is a keyframe animation, not a transition, on purpose: a
   transition here would occupy the element's `transition` property and silently
   cancel the hover/active transitions of anything that reveals (the hero CTA
   lost its state animation that way). `backwards` fill holds the hidden state
   through the stagger delay; nothing is held afterwards, so hover is free. */
.is-reveal-pending,
.kidsee-anim .js-hero-step { opacity: 0; }

.is-reveal-pending.is-revealed,
.kidsee-anim .js-hero-step.is-revealed {
	opacity: 1;
	animation: kidsee-rise var(--kidsee-t-enter) var(--kidsee-out) backwards;
}
@keyframes kidsee-rise {
	from { opacity: 0; transform: translateY(28px); }
	to   { opacity: 1; transform: translateY(0); }
}

/* Nav links grow an underline from the centre on hover. The CTA is excluded —
   it is a filled button and an underline crawling under it read as a glitch. */
.top-nav > a:not(.cta-pill) { position: relative; }
.top-nav > a:not(.cta-pill)::after {
	content: "";
	position: absolute;
	left: 16px;
	right: 16px;
	bottom: 4px;
	height: 2px;
	border-radius: 2px;
	background: currentColor;
	transform: scaleX(0);
	transition: transform var(--kidsee-t-slow) var(--kidsee-out);
}
.top-nav > a:not(.cta-pill):hover::after { transform: scaleX(1); }

/* Stars: hero rating uses the source's larger 25px mark. */
.hero-rating .star { width: 25px; height: 25px; }
.stars--warm { color: var(--kidsee-star); }

img { max-width: 100%; }

/* ===========================================================================
   Blog (2026-08-13 gap-closing pass: CTA banner between featured post + grid,
   author byline on article pages, related-posts count 3→4). All blog-only
   CSS lives in this one block — nothing above this point was touched. */

/* CTA band's optional 'image' variant (cta-band.php $args['image']) — the
   live blog index's "Download Kidsee App For Free" banner. Two-column on
   desktop (image beside the heading), stacked image-above-copy on phones.
   Additive: a cta-band call with no 'image' arg never gets this class, so
   every existing centred/image-less usage is byte-identical to before. */
.cta-band--media .cta-band__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 28px;
}
.cta-band--media .cta-band__media { width: 100%; max-width: 320px; }
.cta-band--media .cta-band__media img {
	width: 100%;
	height: auto;
	display: block;
}
.cta-band--media .section-heading { width: 100%; margin-bottom: 0; }
@media (min-width: 768px) {
	.cta-band--media .cta-band__inner { flex-direction: row; text-align: left; }
	.cta-band--media .cta-band__media { max-width: 360px; flex: 0 0 auto; }
	.cta-band--media .section-heading { flex: 1; }
}

/* The live CTA banner's heading is a literal two-line string ("Download
   Kidsee App" / "For Free") — a real line break, not a wrapped sentence.
   section-heading.php escapes the title with esc_html(), which preserves
   the \n byte but browsers collapse it to a space by default; pre-line
   keeps that break without needing to smuggle a <br> through esc_html().
   Scoped to .cta-band so it can't affect any other section-heading caller
   (none of which pass a multi-line title today). */
.cta-band .t-title { white-space: pre-line; }

/* Author byline — single.php, between the date and the H1. Per-article
   author comes from post meta (_kidsee_author_name), seeded from
   blog-seed.json; an article with no author on the source renders no
   byline (see NOTES.md), so this class only ever appears when there is a
   real name to show. */
.single-article__byline {
	display: block;
	font-size: 14px;
	font-weight: 700;
	color: var(--kidsee-text-muted);
	margin-top: 4px;
}

/* Related posts: 3 → 4 items. .blog-cards' own "Blog strip" block above
   already goes to a 4-column grid at >=992px, so the 4th card slots into
   the same row for free; no grid change needed there. Below 992px the
   existing 1-col / 2-col breakpoints still apply evenly to 4 items. */

/* --- About page (page-about.php) ------------------------------------------
   Hero / pull-quote / mission / values / product-maturity / team / closing
   CTA. Reuses .hero/.hero-inner/.hero-copy/.hero-media, the .card family,
   .t-* type roles, and the section-heading / feature-cards / cta-band parts
   for every section that fits one. Only three shapes have no existing
   equivalent, so only these are new: the two-CTA hero action row, the
   standalone pull-quote, and the icon-fronted value cards. See CLAUDE.md /
   DESIGN-SYSTEM.md for what was reused where. */

.about-hero-actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 16px;
	margin-top: 28px;
}
@media (min-width: 992px) {
	.about-hero-actions { justify-content: flex-start; }
}

/* Pull quote — a single centred statement. The closest existing thing,
   .article-body blockquote, is scoped to blog post bodies and reads far too
   small for a page-level statement, so this is its own small rule rather
   than a repurposed one. */
.about-quote { text-align: center; }
.about-quote__text {
	margin: 0;
	font-size: clamp(24px, 3.4vw, 32px);
	font-weight: 800;
	line-height: 1.3;
	letter-spacing: -.01em;
	color: var(--kidsee-primary-800);
}

/* Mission — section-heading (eyebrow + h2) above a plain narrow prose block;
   no image, so split.php (which requires one) doesn't apply here. */
.about-mission__body {
	display: grid;
	gap: 16px;
	max-width: 680px;
	margin-inline: auto;
}
.about-mission__body p { margin: 0; }

/* Values — icon-fronted cards. Same surface family as every other card on
   the site (.card/.card--tile/.card--lift — no new radius or shadow); the
   one new visual is the icon roundel, built from the same primary-050/
   primary pair the eyebrow pill already uses, sized close to the
   tab-switcher's own 28px icon. feature-cards.php was considered first but
   doesn't fit: it has no icon slot, only an optional raster <img>, and these
   three items need a Lucide icon each, not a screenshot. */
.about-values-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 24px;
}
.about-value {
	display: flex;
	flex-direction: column;
	gap: 16px;
	padding: 32px 28px;
	text-align: left;
}
.about-value__icon {
	display: grid;
	place-items: center;
	width: 56px;
	height: 56px;
	border-radius: var(--kidsee-r-pill);
	background: var(--kidsee-primary-050);
	color: var(--kidsee-primary);
	flex: 0 0 auto;
}
.about-value__icon .icon { width: 26px; height: 26px; }
.about-value h3,
.about-value p { margin: 0; }
@media (min-width: 768px) {
	.about-values-grid { grid-template-columns: repeat(3, 1fr); }
}

/* Product maturity + Team sections reuse template-parts/feature-cards.php
   with no per-item 'image' (an explicitly supported shape, see that part's
   own contract) — pure title+body cards, no new CSS needed for either. */

/* --- About: role cards ----------------------------------------------------
   Two overrides, both scoped to this one section.

   1. The feature-card grid's media box is a 545/341 landscape crop, sized for
      app screenshots. The About page's role art is square (1024x1024, subject
      cut out over its own lavender panel), so a landscape crop would slice
      the head off.

   2. feature-cards.php deliberately holds exactly-4-items at 2-up on desktop,
      because a feature card carries a 2-5 sentence paragraph and 4 columns
      would leave each one ~245px. A role card carries a single line, so that
      reasoning inverts: 2-up gave four 462px portraits and a 1825px-tall
      section for four short labels. 4-up with a tighter gap sizes the art to
      the text it belongs to. */
.about-team .feature-cards__media {
	aspect-ratio: 1 / 1;
}

/* The lavender panel behind each portrait is drawn HERE, not baked into the
   image. Four separate generations placed their panel at four different
   heights and sizes, so the row read ragged; as a pseudo-element every card
   aligns by construction, the colour comes from a token, and the art files
   get smaller. The portraits are normalised to a single scale and sit on the
   box's bottom edge, so the head rises above the panel the way it does in the
   feature-page art. */
.about-team .feature-cards__media {
	position: relative;
	overflow: visible;
	border-radius: 0;
}
.about-team .feature-cards__media::before {
	content: "";
	position: absolute;
	inset: auto 0 0 0;
	height: 72%;
	background: var(--kidsee-primary-100);
	border-radius: var(--kidsee-r-md);
}
.about-team .feature-cards__media img {
	position: relative;
	object-fit: contain;
	object-position: bottom center;
}

@media (min-width: 992px) {
	.about-team .feature-cards {
		grid-template-columns: repeat(4, 1fr);
		gap: 32px;
	}
}
