/* JJW v2 design system — tokens, header, footer, section primitives.
   One source for every page; page-specific layout stays in each page.

   Type + shape language is shared with jevikajoy.shop (the Shopify theme):
   Baloo 2 800 display headings (also the logo wordmark's face), Big
   Shoulders Display 700 for condensed caps/labels/buttons, Nunito body —
   all Google Fonts, properly licensed. This REPLACED the Fontspring
   Sofia Pro Soft demo build, whose broken glyph table shipped "DEMO"
   badges in place of apostrophes on the live site. Don't reintroduce it. */

@import url("https://fonts.googleapis.com/css2?family=Baloo+2:wght@700;800&family=Big+Shoulders+Display:wght@700&family=Nunito:wght@400;600;700;800&display=swap");


:root {
  --ink:          #1A2F5E;
  --ink-soft:     color-mix(in oklch, #1A2F5E 70%, white);
  --ink-mute:     color-mix(in oklch, #1A2F5E 45%, white);
  --pink:         #FF4F8B;
  --pink-deep:    color-mix(in oklch, #FF4F8B 80%, black);
  --pink-soft:    color-mix(in oklch, #FF4F8B 15%, white);
  --blue:         #0F7DAF;
  --blue-soft:    color-mix(in oklch, #0F7DAF 15%, white);
  --saffron:      #F6A313;
  --saffron-soft: color-mix(in oklch, #F6A313 15%, white);
  --warm-white:   #F8F8F6;
  --radius:       16px;     /* one corner radius site-wide — the shop's 1.6rem */
  --ink-deep:     #10244A;  /* night navy — every offset shadow, from the shop */
  --cream:        #FFF7E8;  /* the shop's canvas — bright fields sit on this */
  --mint:         #73D78D;  /* Mint Green — Minku's fill; also bright-field glow */
  --lavender:     #A88BFF;  /* Lavender — Pinki's fill; also bright-field glow */
  --candy:        #FF5FA2;  /* Candy Pink — Jevika's fill (shop character pair) */
  --sky:          #59C8F6;  /* Sky Blue — Joy's fill; the kids section's drenched field */
  --star:         #FFD94C;  /* Star Yellow — Brutus's fill; headline highlight on sky */
  --serif: "Baloo 2", "Nunito", system-ui, sans-serif;          /* display headings */
  --sans:  "Nunito", "Inter", system-ui, sans-serif;             /* body copy */
  --mono:  "Big Shoulders Display", "Arial Narrow", sans-serif;  /* caps labels, nav, buttons —
     overrides styles.css's Geist Mono; every eyebrow/button/label reads this token */

  /* Height of the fixed .site-header, derived from the same values that build
     it: its own vertical padding, twice, plus the tallest thing in the row
     (the 32px logo). Every page currently hard-codes a top offset to clear the
     header; point them at this instead so the two can't drift apart. */
  --header-h: calc(clamp(20px, 3.2vh, 32px) * 2 + 32px);

  /* Height of the About band, and the ceiling for the founder photo inside it
     (photo = this minus the band's top padding, so it still bleeds to the
     bottom edge). Every section is a full screen now — set this to 80svh to
     make About the short one again; nothing else needs touching, since the
     overlap margins that used to depend on it are gone. */
  --about-h: 100svh;
}
/* on touch widths the nav links grow to a 44px tap target and become the
   tallest thing in the row, so the header grows with them */
@media (max-width: 1024px) {
  :root { --header-h: calc(clamp(20px, 3.2vh, 32px) * 2 + 44px); }
}

/* persistent header — dot + small logo + nav, fixed above every section.
   The logo is static: it sits in the header at its natural size from load.
   (It used to FLIP-scrub up onto the hero wordmark and back; that, and every
   other scroll-driven effect on this site, has been removed.) */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: clamp(20px, 3.2vh, 32px) clamp(24px, 4vw, 56px);
  color: var(--warm-white);
  text-shadow: 0 1px 3px rgba(0,0,0,.35);
  transition: background 0.3s var(--ease-out), backdrop-filter 0.3s var(--ease-out);
}
.site-header.is-scrolled {
  background: color-mix(in oklch, var(--ink) 55%, transparent);
  backdrop-filter: blur(10px);
}
.site-header .hv-dot { position: static; flex-shrink: 0; }
.site-header .hv-nav { position: static; }
.site-logo {
  margin-right: auto;
  display: block;
  height: 32px;
  width: auto;
}

/* Reduced-motion fallback for the hero field. styles.css hides .hero-video-bg
   outright when motion is reduced, which left .hero.hero-video with no
   background at all — so the near-white body background showed through behind
   warm-white overlay text, i.e. the eyebrow, the copy and the scroll hint were
   invisible. Fall back to the video's own poster frame under the same navy
   scrim #mission uses over its photo, so the register and the contrast both
   survive. */
@media (prefers-reduced-motion: reduce) {
  /* hero-poster.jpg no longer exists — a plain navy gradient keeps the
     register and the overlay text readable with the video hidden */
  .hero.hero-video {
    background: linear-gradient(160deg,
      color-mix(in oklch, var(--ink) 94%, black) 0%, var(--ink) 55%,
      color-mix(in oklch, var(--ink) 80%, var(--blue)) 100%);
  }
}

/* text-logo hero overlay — big wordmark + brand copy over the full-bleed video */
.hv-overlay {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  color: var(--warm-white);
  text-shadow: 0 1px 3px rgba(0,0,0,.35);
}
.hv-overlay a { color: inherit; }

.hv-dot {
  position: absolute;
  top: clamp(28px, 4vh, 44px);
  left: clamp(24px, 4vw, 56px);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--saffron);
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--saffron) 30%, transparent);
}

.hv-nav {
  position: absolute;
  top: clamp(24px, 4vh, 40px);
  right: clamp(24px, 4vw, 56px);
  display: flex;
  gap: clamp(18px, 2.4vw, 40px);
  pointer-events: auto;
}
.hv-nav a {
  text-decoration: none;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding-bottom: 6px;
  border-bottom: 1px dotted transparent;
  opacity: 0.75;
  transition: opacity 0.2s var(--ease-out);
}
.hv-nav a:hover { opacity: 1; }
.hv-nav a.active { opacity: 1; border-bottom-color: currentColor; }

.hv-eyebrow {
  position: absolute;
  top: clamp(56px, 9vh, 84px);
  left: clamp(24px, 6vw, 90px);
  margin: 0;
  font-family: var(--mono);
  font-size: clamp(11px, 1vw, 14px);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0.9;
}

/* The hero has no logo of its own — the header's #siteLogo is the single
   logo on the page. (.hv-wordmark and its slot were removed with the FLIP.) */

/* brand marquee — the shop's 24s loop verbatim: track is two identical
   groups, so translating -50% loops seamlessly. Sits between hero and About
   on the homepage only. Ink-deep on Sunshine Gold: 5.9:1. */
.jj-marquee {
  overflow: hidden;
  background: var(--saffron);
  color: var(--ink-deep);
  border-block: 4px solid var(--ink-deep);
  padding: 13px 0;
  position: relative;
  z-index: 3;
}
.jj-marquee__track { display: flex; width: max-content; animation: jj-marquee 24s linear infinite; }
.jj-marquee__group { display: flex; align-items: center; gap: 32px; padding-right: 32px; }
.jj-marquee__group span {
  font-family: var(--mono);
  font-weight: 700;
  font-size: clamp(17px, 1.8vw, 24px);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}
@keyframes jj-marquee { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .jj-marquee__track { animation: none; } }

.hv-desc {
  position: absolute;
  top: 50%;
  right: clamp(24px, 6vw, 80px);
  transform: translateY(-50%);
  max-width: 420px;
  margin: 0;
  font-family: var(--sans);
  font-size: clamp(17px, 1.6vw, 24px);
  line-height: 1.45;
  text-align: right;
}
.hv-desc em { font-family: var(--serif); font-style: normal; color: var(--saffron); }

.hv-card {
  position: absolute;
  left: clamp(20px, 3.5vw, 48px);
  bottom: clamp(70px, 9vh, 110px);
  width: min(340px, 30vw);
  padding: clamp(20px, 2.2vw, 28px);
  border-radius: var(--radius);
  background: color-mix(in oklch, var(--ink) 45%, transparent);
  backdrop-filter: blur(6px);
  box-shadow: 6px 6px 0 color-mix(in oklch, var(--ink-deep) 75%, transparent);
}
.hv-card-title {
  margin: 0 0 clamp(18px, 2vh, 26px);
  font-family: var(--sans);
  font-weight: 600;
  font-size: clamp(15px, 1.3vw, 19px);
  line-height: 1.35;
  text-transform: uppercase;
}
.hv-card-divider {
  display: block;
  height: 0;
  border-top: 1px dashed color-mix(in oklch, var(--warm-white) 40%, transparent);
  margin-bottom: clamp(18px, 2vh, 26px);
}
.hv-card-sub {
  margin: 0;
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.6;
  opacity: 0.85;
}

.hv-side-tab {
  position: absolute;
  top: clamp(120px, 16vh, 190px);
  right: 0;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  background: var(--warm-white);
  color: var(--ink);
  text-shadow: none;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 18px 10px;
  border-radius: var(--radius) 0 0 var(--radius);
}

.hv-scroll {
  position: absolute;
  bottom: clamp(24px, 4vh, 44px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.85;
}
.hv-scroll .chev { font-size: 14px; animation: hv-bob 1.6s ease-in-out infinite; }
@keyframes hv-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(4px); }
}
@media (prefers-reduced-motion: reduce) {
  .hv-scroll .chev { animation: none; }
}

.hv-sound {
  position: absolute;
  right: clamp(24px, 4vw, 56px);
  bottom: clamp(24px, 4vh, 44px);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border: none;
  border-radius: var(--radius);
  background: color-mix(in oklch, var(--ink) 45%, transparent);
  backdrop-filter: blur(6px);
  color: inherit;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  pointer-events: auto;
  transition: background 0.2s var(--ease-out);
}
.hv-sound:hover { background: color-mix(in oklch, var(--ink) 60%, transparent); }
.hv-sound svg { width: 16px; height: 16px; }
.hv-sound .ic-unmuted { display: none; }
.hv-sound.is-unmuted .ic-muted { display: none; }
.hv-sound.is-unmuted .ic-unmuted { display: block; }

/* Mobile/tablet hero. The desktop composition hangs all six overlay pieces off
   absolute clamp()ed offsets, which only stay clear of each other at desktop
   proportions — narrow viewports collided the scroll hint into the sound
   button, and the old fix here (a clamp(220px, 42vh, 320px) top margin on
   .hv-desc to clear the wordmark) made the whole stack depend on viewport
   HEIGHT, so it re-broke on short/landscape phones.
   Below 900px the overlay is a plain flex column in DOM order instead: the
   pieces cannot overlap at any viewport size because they are in flow. Only
   the two bottom-corner controls stay absolute. 900px — not the old 880 —
   matches the .about-stage/.kids-stage collapse and the JS split-and-pop
   fallback, so a single breakpoint governs the whole page. */
@media (max-width: 900px) {
  .hv-overlay {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: clamp(12px, 2vh, 20px);
    /* top clears the fixed header, bottom reserves the scroll/sound row */
    padding: calc(var(--header-h) + clamp(16px, 3vh, 40px)) 24px clamp(76px, 11vh, 104px);
  }
  .hv-eyebrow,
  .hv-desc,
  .hv-card { position: static; transform: none; margin: 0; }

  /* Reading order top→bottom: eyebrow and wordmark hard against the left
     gutter, then right-aligned copy, then the glass card parked bottom-left
     with the free space banked above it. */
  .hv-eyebrow { text-align: left; align-self: flex-start; font-size: 12px; }
  .hv-desc {
    max-width: 30ch;
    text-align: right;
    align-self: flex-end;
    font-size: clamp(17px, 4.8vw, 22px);
  }
  /* auto margin banks the free space here, so the card sits low-left and the
     wordmark block stays up top — the desktop composition, minus the offsets. */
  .hv-card {
    width: min(78%, 340px);
    align-self: flex-start;
    margin-top: auto;
  }
  .hv-card-title { font-size: 16px; }
  .hv-card-sub { font-size: 15px; }
  .hv-side-tab { display: none; }
}
/* shared section shell — both the dark "liquid" sections and the bright
   "kids" sections sit in the same viewport-height flex-center frame */
.jj-section {
  position: relative;
  z-index: 2;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: var(--s-8) 28px;
}

/* liquid glide — next section rises over the pinned hero, opening through an
   elliptical clip-path that reads as a surface of liquid rather than a card edge.
   Overlap (negative margin) only applies once JS confirms the pin/scrub is active —
   without it, sections must stack normally or the hero is permanently hidden. */

/* no more shared background video — brand-color field instead. Two soft
   radial glows over the navy base gradient (rule: dark fields get 1-2 glows,
   not a flat fill — DESIGN-v2.md §2), drawn from the navy+gold+blue register
   reflective sections keep to. */
.liquid-next,
.dark-field {
  background:
    radial-gradient(ellipse 60% 55% at 14% 8%, color-mix(in oklch, var(--blue) 38%, transparent), transparent 70%),
    radial-gradient(ellipse 55% 50% at 92% 88%, color-mix(in oklch, var(--saffron) 20%, transparent), transparent 70%),
    linear-gradient(160deg, color-mix(in oklch, var(--ink) 94%, black) 0%, var(--ink) 45%, color-mix(in oklch, var(--ink) 80%, var(--blue)) 100%);
  color: var(--warm-white);
}
/* .liquid-next is now purely the dark-field background + grain for #about —
   nothing transforms or clips it any more, so no will-change layer either. */
/* About / founder band — cutout founder photo bleeding off the bottom edge,
   headline + copy + CTA stacked in the right column. Field is inherited from
   .liquid-next (navy base + blue/saffron glows) rather than overridden: that
   IS the brand's reflective register per §5, and it measures cream 12.25:1 /
   saffron 6.31:1, so the standard §2 rule 1 accents work unmodified. A flat
   saturated pink was tried and dropped — --pink is 2.9:1 against cream. */
.founder-band {
  min-height: var(--about-h);   /* deliberately shorter than a full screen */
  align-items: flex-end;
  padding-bottom: 0;
}
.about-stage {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1280px;
  display: grid;
  grid-template-columns: 0.92fr 1.08fr;
  grid-template-areas:
    "media heading"
    "media copy";
  align-items: end;
  column-gap: clamp(24px, 4vw, 72px);
  row-gap: clamp(12px, 2vh, 20px);
}
.about-heading {
  grid-area: heading;
  align-self: end;
  margin: 0;
  padding-bottom: clamp(6px, 1.5vh, 14px);
}
.about-copy {
  grid-area: copy;
  align-self: start;
  padding-bottom: clamp(40px, 7vh, 88px);
}
.about-copy .ln-sub { max-width: 420px; opacity: 0.92; }
.founder-band .ln-title { font-size: min(8vw, clamp(34px, 4.6vw, 68px)); }

/* transparent cutout — deliberately no card frame, radius or ring: it sits
   directly on the field and bleeds off the band's bottom edge */
.about-media {
  grid-area: media;
  align-self: end;
  position: relative;
  margin: 0;
  width: 100%;
}
.about-media img {
  display: block;
  width: 100%;
  height: auto;
  /* the band minus its top padding — the tallest the photo can be and still
     bleed to the bottom edge without pushing the band past --about-h */
  max-height: calc(var(--about-h) - var(--s-8));
  object-fit: contain;
  object-position: 50% 100%;
  filter: drop-shadow(0 24px 48px rgba(0,0,0,.28));
}

/* handwritten-style name tags pinned to each subject */
.fb-tag {
  position: absolute;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 10px 16px;
  background: var(--saffron);
  color: var(--ink-deep);
  border-radius: 12px;
  border: 3px solid var(--warm-white);
  box-shadow: 4px 4px 0 var(--ink-deep);
}
.fb-tag-name {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(14px, 1.4vw, 19px);
  line-height: 1;
}
.fb-tag-role {
  font-family: var(--mono);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1;
  opacity: 0.75;
}
.fb-tag-founder { top: 56%; left: -4%; transform: rotate(-6deg); }
.fb-tag-brutus  { top: 41%; right: -6%; transform: rotate(5deg); }

/* same button family as .cta-btn — saffron fill against the navy field */
.fb-btn {
  display: inline-block;
  margin-top: clamp(20px, 3vh, 30px);
  padding: 15px 30px;
  background: var(--saffron);
  color: var(--ink-deep);
  border-radius: var(--radius);
  font-family: var(--mono);
  font-size: clamp(15px, 1.4vw, 18px);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: 5px 5px 0 var(--ink-deep);
  transition: transform 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
.fb-btn:hover { transform: translate(3px, 3px); box-shadow: 2px 2px 0 var(--ink-deep); }

@media (max-width: 900px) {
  .founder-band { align-items: center; }
  .about-stage {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "heading"
      "copy"
      "media";
    text-align: center;
    row-gap: clamp(18px, 3vh, 28px);
  }
  /* NOT justify-items:center — that shrink-to-fits every row to its own
     max-content, which sized .about-heading to 225px inside a 319px column
     and made the headline wrap far earlier than it needed to. Rows stretch;
     the two elements that actually need centring get margin-inline:auto. */
  .about-heading, .about-copy { align-self: auto; padding-bottom: 0; }
  .about-copy .ln-sub { margin-inline: auto; }
  .about-media { max-width: 400px; margin-inline: auto; }
  .about-media img { max-height: 52svh; }
  .fb-tag-founder { left: 0; }
  .fb-tag-brutus { right: 0; }
}
/* fine grain so the dark field doesn't band — reads as printed, not rendered */
.liquid-next::after,
.dark-field::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.05;
  z-index: 1;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* No section overlaps another any more. The .is-glide / .is-split negative
   margins that used to pull #about over the hero's pin spacer and #kids over
   #about's lived here — both are gone along with the pinned timelines that
   needed them. Sections are plain document flow now, stacked in order. */

/* mission keeps the dark register but swaps the flat navy base for the city
   aerial — same two glows on top, plus a navy scrim heavy enough that plain
   warm-white text (no card here) still clears contrast over a busy image. */
#mission {
  background:
    radial-gradient(ellipse 60% 55% at 14% 8%, color-mix(in oklch, var(--blue) 38%, transparent), transparent 70%),
    radial-gradient(ellipse 55% 50% at 92% 88%, color-mix(in oklch, var(--saffron) 20%, transparent), transparent 70%),
    linear-gradient(160deg,
      color-mix(in oklch, var(--ink) 90%, transparent) 0%,
      color-mix(in oklch, var(--ink) 78%, transparent) 50%,
      color-mix(in oklch, var(--ink) 90%, transparent) 100%),
    url("assets/backgrounds/city-aerial.jpg") center / cover no-repeat;
}

/* bright field — cream canvas with the two kid-facing accent glows.
   (The old AI sky/clouds photo is gone: it competed with every image put on
   top of it and read as generated, not designed.) */
.bright-next {
  background:
    radial-gradient(ellipse 55% 50% at 10% 6%, color-mix(in oklch, var(--mint) 26%, transparent), transparent 70%),
    radial-gradient(ellipse 55% 50% at 94% 92%, color-mix(in oklch, var(--lavender) 20%, transparent), transparent 70%),
    var(--cream);
  color: var(--ink);
}
/* same glass-card recipe as .hv-card (hero) — ink @ 45% + blur(6px) — not a
   lighter variant for the bright register. Text inside flips to light to
   read against the now-dark card. (About no longer uses a card at all —
   its copy sits plain on the dark field, see .about-copy.) */
.bright-next .ln-text {
  background: color-mix(in oklch, var(--ink) 45%, transparent);
  backdrop-filter: blur(6px);
  border-radius: var(--radius);
  box-shadow: 6px 6px 0 color-mix(in oklch, var(--ink-deep) 75%, transparent);
  padding: clamp(28px, 4vw, 48px);
  color: var(--warm-white);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.14),
    inset 0 0 0 1px rgba(255,255,255,.07),
    0 24px 48px rgba(0,0,0,.28);
}
.bright-next .ln-eyebrow,
.bright-next .ln-sub,
.bright-next .ln-link { opacity: 1; }
.bright-next .ln-eyebrow { opacity: 0.9; }
.bright-next .ln-sub { opacity: 0.78; color: inherit; }
.bright-next .ln-title em { color: var(--saffron); }
.bright-next .ln-link { border-bottom-color: color-mix(in oklch, var(--warm-white) 40%, transparent); }
.bright-next .ln-link:hover { border-bottom-color: var(--warm-white); }
/* mission — a plain centred statement on the dark field, no card and no
   image: the rhythm break after three image-led sections, and the one place
   the brand says what it's for out loud. */
.mission-stage {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 900px;
  text-align: center;
}
/* 6.9vw, not the 7vw the shared .ln-title uses: mission carries the longest
   authored line on the site ("It's time they had their own."), and each
   .ln-line has to survive on ONE line — it is a masked line-rise reveal, so a
   line that wraps shows a half-clipped second row instead of overflowing. */
.mission-stage .ln-title { font-size: min(6.9vw, clamp(32px, 4.4vw, 64px)); }
.mission-stage .ln-sub { max-width: 660px; margin-inline: auto; }

/* kids stage — the cast group render sits dead centre with the heading card
   on its left and the copy card on its right (same centred-subject idea as
   the hero and About rows). */
.kids-stage {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1240px;
  display: grid;
  grid-template-columns: 1fr 0.82fr 1fr;
  grid-template-areas: "heading media copy";
  gap: clamp(24px, 3vw, 44px);
  align-items: center;
}
.kids-heading { grid-area: heading; }
.kids-copy    { grid-area: copy; }
.kids-media {
  grid-area: media;
  margin: 0;
  border-radius: var(--radius);
  overflow: hidden;
  border: 5px solid var(--warm-white);
  box-shadow: 8px 8px 0 var(--ink-deep);
}
.kids-media img { display: block; width: 100%; height: auto; }

/* ============================================================
   MADE FOR KIDS (homepage #kids) — redesigned. Drenched field:
   the surface IS Sky Blue (Joy's fill, the same solid as the
   shop's nav pills), flat + grain, no photo, no glass anywhere.
   Ink type sits directly on the field (6.8:1). The .kids-*
   classes above are untouched — story.html still uses them.
   ============================================================ */
.sky-field {
  position: relative;
  background: var(--sky);
  color: var(--ink);
}
/* same print-grain the dark fields carry, so flat reads as ink on paper */
.sky-field::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.05;
  z-index: 1;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

.mk-stage {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1280px;
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  align-items: center;
  gap: clamp(32px, 5vw, 80px);
}

/* headline emphasis on the sky field: neither saffron (dark-field rule) nor
   pink clears contrast against mid-luminance sky, so <em> becomes an ink-on-
   Star-Yellow highlight sweep instead (9.4:1) — marker on a sticker */
.mk-copy .ln-title em {
  color: var(--ink);
  background: var(--star);
  padding: 0.02em 0.14em;
  border-radius: 8px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
.mk-copy .ln-sub { color: var(--ink); opacity: 0.9; max-width: 46ch; }

/* trust checklist — answers "will this rot their brain less?" inline */
.mk-trust {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  margin: clamp(16px, 2.4vh, 24px) 0 0;
  padding: 0;
  list-style: none;
}
.mk-trust li {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--mono);
  font-weight: 700;
  font-size: clamp(13px, 1.2vw, 15px);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.mk-trust li::before {
  content: "✓";
  flex: none;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--sky);
  font-size: 12px;
  font-weight: 800;
}

/* the five heroes, NAMED — the founder-band tag language, one tag per
   character in its own shop fill. Ink text on every fill (never tint-on-tint):
   candy 4.55 · sky 6.77 · star 9.39 · mint 7.27 · lavender 4.79. Joy's tag is
   sky-on-sky by necessity; the white sticker border does the separating. */
.mk-cast {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 14px;
  margin: clamp(22px, 3.2vh, 34px) 0 0;
  padding: 0;
  list-style: none;
}
.mk-cast li {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 7px 16px 7px 8px;
  border-radius: 999px;
  border: 3px solid var(--warm-white);
  box-shadow: 4px 4px 0 var(--ink-deep);
  color: var(--ink-deep);
}
.mk-cast li img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--warm-white);
}
.mk-cast .mk-name {
  display: block;
  font-family: var(--serif);
  font-weight: 800;
  font-size: 15px;
  line-height: 1.05;
}
.mk-cast .mk-role {
  display: block;
  font-family: var(--mono);
  font-weight: 700;
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.72;
}
.mk-cast .is-jevika { background: var(--candy); }
.mk-cast .is-joy    { background: var(--sky); }
.mk-cast .is-pinki  { background: var(--lavender); }
.mk-cast .is-minku  { background: var(--mint); }
.mk-cast .is-brutus { background: var(--star); }

.mk-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 26px;
  margin-top: clamp(24px, 3.6vh, 38px);
}
/* quiet secondary next to the saffron button */
.mk-faq {
  font-family: var(--mono);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 2px solid color-mix(in oklch, var(--ink) 45%, transparent);
  padding-bottom: 3px;
}
.mk-faq:hover { border-color: var(--ink); }

/* the proof — the five of them together, in the sticker frame */
.mk-media { margin: 0; }
.mk-media img {
  display: block;
  width: 100%;
  max-width: 460px;
  margin-inline: auto;
  height: auto;
  border-radius: var(--radius);
  border: 5px solid var(--warm-white);
  box-shadow: 10px 10px 0 var(--ink-deep);
  transform: rotate(1.5deg);
}

@media (max-width: 900px) {
  .mk-stage {
    grid-template-columns: minmax(0, 1fr);
    text-align: left;   /* deliberate: checklist + tags read as a list, not centred poetry */
  }
  .mk-media { order: 2; margin-top: clamp(26px, 4vh, 40px); }
  .mk-media img { max-width: 380px; box-shadow: 7px 7px 0 var(--ink-deep); }
}
@media (max-width: 560px) {
  .mk-cast li { padding: 6px 13px 6px 7px; }
  .mk-cast li img { width: 34px; height: 34px; }
}
.ln-text { text-align: left; }
.ln-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.7;
}
.ln-eyebrow .dot {
  width: 28px;
  height: 1px;
  border-radius: 0;
  background: var(--saffron);
}
/* Sized to the width of a ~550-600px single text column (About's title box,
   Kids' .ln-text grid column) — NOT the full viewport. The old 92px max was
   tuned against the viewport, not the column it actually renders in, so at
   ordinary desktop widths every authored line ("A father's belief.", "Made
   for kids first.") ran wider than its box and wrapped mid-word. Any new
   section reusing .ln-title should fit its longest authored line in a column
   this size — if the column is narrower, scope a smaller override rather
   than widening this shared value back out.
   The outer min() is the PHONE guard: the 30px floor was tuned for that
   ~550px column, but the same headline lands in a ~264px column at 320px
   (and ~208px inside a .bright-next glass card), where 30px forces the
   authored .ln-line spans to wrap mid-headline. 7vw only undercuts the
   clamp below ~428px, so it is inert at every width the clamp was tuned
   for and needs no media query. */
.ln-title {
  margin: clamp(20px, 3vh, 32px) 0 clamp(22px, 3vh, 34px);
  font-family: var(--serif);
  font-style: normal;
  font-weight: 800;
  font-size: min(7vw, clamp(30px, 3.6vw, 54px));
  line-height: 1.06;
  letter-spacing: 0.01em;   /* Baloo 2 is round — negative tracking crowds it */
  text-wrap: balance;
}
.ln-title em {
  color: var(--saffron);
  font-style: normal;
}
/* line-mask reveal: each line clips its inner span, which slides up from below */
.ln-line { display: block; overflow: hidden; padding-block: 0.06em; margin-block: -0.06em; }
.ln-line-inner { display: inline-block; will-change: transform; }
.ln-sub {
  margin: 0;
  max-width: 440px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: clamp(16px, 1.5vw, 19px);
  line-height: 1.7;
  opacity: 0.85;
}
.ln-sub strong { font-weight: 500; color: var(--saffron); }
.ln-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: clamp(22px, 3vh, 32px);
  color: inherit;
  text-decoration: none;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding-bottom: 4px;
  border-bottom: 1px solid color-mix(in oklch, var(--warm-white) 40%, transparent);
  transition: border-color 0.2s var(--ease-out), gap 0.2s var(--ease-out);
}
.ln-link:hover { border-color: currentColor; gap: 11px; }

/* reveal targets — visible by default; JS hides + animates in only when motion is safe */
.reveal { opacity: 1; }

@media (max-width: 900px) {
  .kids-stage {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "media"
      "heading"
      "copy";
  }
  /* stretch rather than justify-items:center, same reason as .about-stage */
  .kids-media { max-width: 420px; margin-inline: auto; }
}


/* closing CTA — bright register between the dark mission and the dark
   footer. Warm-white field with the same two kid-facing glows as #kids,
   but no photo: this section is the one place the page asks for something,
   so nothing competes with the headline and the two buttons. */
.cta-field {
  background:
    radial-gradient(ellipse 55% 60% at 12% 10%, color-mix(in oklch, var(--mint) 26%, transparent), transparent 70%),
    radial-gradient(ellipse 55% 60% at 90% 90%, color-mix(in oklch, var(--lavender) 22%, transparent), transparent 70%),
    var(--cream);
  color: var(--ink);
  min-height: auto;
  padding-block: clamp(72px, 14vh, 160px);
}
.cta-stage {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 900px;
  text-align: center;
}
.cta-stage .ln-title { font-size: min(7.4vw, clamp(30px, 4.2vw, 60px)); margin-bottom: clamp(28px, 4vh, 42px); }
.cta-stage .ln-title em { color: var(--pink); }

.cta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(10px, 1.4vw, 16px);
}
/* the shop's signature button, one-element edition: solid fill, hard
   night-navy offset shadow that presses flat on hover. The shop builds this
   from two layers on a blob clip-path; a rounded rect + box-shadow reads the
   same and needs no extra markup. Labels are ink-deep on BOTH fills — Sky is
   6.8:1, Heart Pink 4.91:1 (cream labels on pink fail at 2.9:1). */
.cta-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;  /* floor keeps the touch target on short phones */
  padding: clamp(13px, 1.6vh, 17px) clamp(24px, 2.6vw, 34px);
  border-radius: var(--radius);
  border: 0;
  background: color-mix(in oklch, var(--blue) 30%, var(--warm-white));
  color: var(--ink-deep);
  text-decoration: none;
  font-family: var(--mono);
  font-size: clamp(15px, 1.4vw, 18px);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  box-shadow: 5px 5px 0 var(--ink-deep);
  transition: transform 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
.cta-btn:hover { transform: translate(3px, 3px); box-shadow: 2px 2px 0 var(--ink-deep); }
.cta-btn.is-primary { background: var(--pink); }

/* ============================================================
   FOOTER — logo block pinned to a 30% column, oversized link
   list filling the rest. Hovering a link swaps the character
   face parked on the right (the same faces the scroll companion
   uses), so the footer stays playful without extra chrome.
   ============================================================ */
.jj-footer {
  /* styles.css has a bare `footer {}` rule that injects margin-top, a
     border-top and its own padding — that margin showed as a strip of body
     background above the footer. Reset all three here, once, for every page. */
  margin-top: 0;
  border-top: 0;
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 30% 1fr auto;
  grid-template-areas:
    "brand links peek"
    "fine  fine  fine";
  align-items: center;
  gap: clamp(32px, 5vw, 72px);
  padding: clamp(64px, 10vh, 120px) clamp(24px, 5vw, 72px) clamp(28px, 4vh, 44px);
  background: color-mix(in oklch, var(--ink) 94%, black);
  color: var(--warm-white);
}
.jf-brand { grid-area: brand; }
/* logo lockup — the mark (which carries the universe planet) plus the
   punchline directly beneath, set in the logo's own face (Baloo 2) and
   centred to the mark's width so the two read as ONE logo. */
.jf-logo { display: block; width: min(220px, 100%); height: auto; }
.jf-tagline {
  margin: 10px 0 0;
  width: min(220px, 100%);
  text-align: center;
  font-family: var(--serif);
  font-weight: 700;
  font-size: 15px;
  line-height: 1.35;
  letter-spacing: 0.02em;
  color: var(--saffron);
}

/* full-width link rows separated by hairlines — the label sits left, an
   arrow parks right and slides in on hover, and the row tints behind it. */
.jf-links {
  grid-area: links;
  display: flex;
  flex-direction: column;
  border-top: 1px solid color-mix(in oklch, var(--warm-white) 14%, transparent);
}
.jf-links a {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: clamp(14px, 2vh, 22px) clamp(12px, 1.4vw, 20px);
  border-bottom: 1px solid color-mix(in oklch, var(--warm-white) 14%, transparent);
  color: inherit;
  text-decoration: none;
  font-family: var(--sans);
  font-weight: 700;
  font-size: clamp(15px, 1.3vw, 19px);
  line-height: 1.2;
  opacity: 0.7;
  transition: opacity 0.25s var(--ease-out), background 0.25s var(--ease-out),
              padding-left 0.25s var(--ease-out);
}
.jf-links a .idx {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--saffron);
  opacity: 0.75;
}
.jf-links a .arw {
  margin-left: auto;
  font-size: 0.62em;
  opacity: 0;
  transform: translateX(-10px);
  transition: opacity 0.25s var(--ease-out), transform 0.25s var(--ease-out);
}
.jf-links a:hover,
.jf-links a:focus-visible {
  opacity: 1;
  background: color-mix(in oklch, var(--warm-white) 6%, transparent);
  padding-left: clamp(20px, 2.2vw, 32px);
}
.jf-links a:hover .arw,
.jf-links a:focus-visible .arw { opacity: 0.8; transform: translateX(0); }

/* the peeking face — parked right, only visible while a link is hovered */
.jf-peek {
  grid-area: peek;
  width: clamp(120px, 14vw, 190px);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: color-mix(in oklch, var(--warm-white) 12%, transparent);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.12);
  opacity: 0;
  transform: scale(0.86) translateY(10px);
  transition: opacity 0.3s var(--ease-out), transform 0.4s var(--ease-out);
}
.jj-footer.is-peeking .jf-peek { opacity: 1; transform: scale(1) translateY(0); }
.jf-peek-img { width: 100%; height: 100%; object-fit: cover; display: block; }

.jf-fine {
  grid-area: fine;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px;
  margin: clamp(40px, 6vh, 72px) 0 0;
  padding-top: clamp(18px, 2.5vh, 26px);
  border-top: 1px solid color-mix(in oklch, var(--warm-white) 14%, transparent);
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.5;
}
.jf-fine a { color: inherit; text-decoration: none; border-bottom: 1px solid currentColor; }

@media (max-width: 900px) {
  .jj-footer {
    grid-template-columns: 1fr;
    grid-template-areas: "brand" "links" "fine";
    gap: clamp(28px, 5vh, 48px);
  }
  .jf-peek { display: none; }
  .jf-links a:hover { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .jf-links a, .jf-peek { transition: none; }
}

/* ============================================================
   RESPONSIVE — cross-cutting rules that belong to no single
   component. Component-specific breakpoints stay next to their
   component above. The whole file uses four widths and no others:

     <= 1024px  touch sizing + the tablet band below
     <= 900px   3-col stages stack, hero overlay goes to flow,
                footer stacks (JS keys its split-and-pop fallback
                to this same 900px — do not move it)
     <= 768px   (inherited from the two above; no rules of its own)
     <= 560px   small phone — trim the gutters the layout is
                paying for twice over at that width
   ============================================================ */

/* Touch sizing. Everything here already met 44px except these three:
   .hv-nav a measured 25x36, .ln-link 23px, .hv-sound 37px.
   .cta-btn (53px) and .jf-links a (59px) already pass and are untouched. */
@media (max-width: 1024px) {
  /* blockified by the flex parent, so min-width/padding-block both apply.
     Padding rather than min-height keeps the active-state underline riding
     under the text instead of dropping to the bottom of a 44px box. */
  .hv-nav a {
    min-width: 44px;
    padding-block: 13px 12px;
    text-align: center;
  }
  /* grows UPWARD only — flex-end keeps the underline welded to the text, and
     the reclaimed margin keeps the gap above the link visually unchanged. */
  .ln-link {
    min-height: 44px;
    align-items: flex-end;
    margin-top: clamp(2px, 1vh, 12px);
  }
  .hv-sound { min-height: 44px; }
}

/* Tablet landscape. The 3-col stages survive here (they only stack at 900px,
   which the split-and-pop script depends on), but at this width the fixed
   card padding was eating the columns: .kids-copy's paragraph measured 212px
   and .kids-heading's headline box 239px. Narrow the media column, tighten
   the gutters, and give the padding back to the text. */
@media (min-width: 901px) and (max-width: 1024px) {
  .jj-section { padding-inline: 24px; }
  .kids-stage { grid-template-columns: 1fr 0.62fr 1fr; gap: 24px; }
  .about-stage { gap: 28px 32px; }
  .bright-next .ln-text { padding: 22px; }
  /* .kids-heading is the narrowest headline column on the page — a third of
     the row, minus card padding — so the shared .ln-title size (tuned for a
     ~550px column) overshoots it here and breaks the authored line structure:
     .ln-line is a one-line mask, and a line that no longer fits just wraps
     inside it. Scoped down rather than widening the shared value, per the
     note on .ln-title. */
  .kids-heading .ln-title { font-size: min(3.25vw, 34px); }
}

/* Desktop. Same narrow-column problem as the tablet block above, but here the
   fix is width rather than type size: at 1440 the heading column is 409px and
   the card's 48px inline padding left only 313px, while the longest authored
   line ("Made for kids") needs 314px — so it wrapped inside its one-line mask.
   Give both kid cards their inline padding back instead of shrinking a
   headline that sits beside 52px siblings. ~31px of headroom at 1440, which
   also absorbs the metric shift when the licensed font replaces the demo cut. */
@media (min-width: 1025px) {
  .bright-next .kids-heading,
  .bright-next .kids-copy { padding-inline: 32px; }
}

@media (max-width: 560px) {
  .jj-section { padding-inline: 20px; }
  /* the header row fits at 320px with ~29px to spare, which one more nav link
     or a longer label would eat. Buy back ~24px of slack from the gutters
     rather than shrinking the type. */
  .site-header { gap: 10px; padding-inline: 16px; }
  .hv-nav { gap: 14px; }
  /* 28px of card padding on a 264px card is 21% of the line length */
  .bright-next .ln-text { padding: 22px 20px; }
  /* centred, the scroll hint's right edge crosses the sound button's left
     edge below ~406px. Park it in the opposite corner instead. */
  .hv-scroll { left: 24px; transform: none; }
}

/* ============================================================
   MOBILE NAV DRAWER — below 900px the inline .hv-nav is replaced
   by a dot pill that slides a full-height panel in from the right
   (links, then general-enquiries block pinned to the bottom).
   Radius stays var(--radius): the reference used a rounded pill,
   but this site's one-radius rule wins — flip these three values
   to 999px if the pill silhouette is wanted back.
   ============================================================ */
.nav-toggle {
  display: none;              /* desktop uses the inline .hv-nav */
  align-items: center;
  gap: 9px;
  margin-left: auto;
  min-height: 44px;
  padding: 11px 18px;
  border: 1px solid color-mix(in oklch, var(--warm-white) 42%, transparent);
  border-radius: var(--radius);
  background: color-mix(in oklch, var(--ink) 45%, transparent);
  backdrop-filter: blur(6px);
  color: var(--warm-white);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
}
.nt-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--saffron);
  flex-shrink: 0;
}

.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 190;
  background: color-mix(in oklch, var(--ink) 72%, black);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease-out), visibility 0.4s var(--ease-out);
}
.nav-drawer {
  position: fixed;
  inset: 0 0 0 auto;
  z-index: 200;
  width: min(78vw, 420px);
  display: flex;
  flex-direction: column;
  padding: clamp(18px, 3vh, 28px) clamp(22px, 6vw, 40px) clamp(28px, 5vh, 44px);
  background: color-mix(in oklch, var(--ink) 96%, black);
  color: var(--warm-white);
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateX(100%);
  visibility: hidden;
  transition: transform 0.45s var(--ease-out), visibility 0.45s var(--ease-out);
}
html.nav-open .nav-drawer { transform: none; visibility: visible; }
html.nav-open .nav-scrim  { opacity: 0.78; visibility: visible; }
html.nav-open, html.nav-open body { overflow: hidden; }

.nav-toggle.is-close { display: flex; align-self: flex-end; margin-left: 0; }

.nd-links {
  display: flex;
  flex-direction: column;
  margin-top: clamp(28px, 6vh, 56px);
}
.nd-links a {
  padding: clamp(8px, 1.5vh, 14px) 0;
  min-height: 44px;
  display: flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
  font-family: var(--sans);
  font-weight: 700;
  font-size: min(9vw, clamp(26px, 4.6vh, 38px));
  line-height: 1.1;
  letter-spacing: -0.02em;
  border-bottom: 1px dotted transparent;
  opacity: 0.92;
}
.nd-links a:hover,
.nd-links a:focus-visible { opacity: 1; }
.nd-links a[aria-current="page"] {
  border-bottom-color: color-mix(in oklch, var(--warm-white) 55%, transparent);
  align-self: flex-start;
}

.nd-contact {
  margin: auto 0 0;
  padding-top: clamp(28px, 5vh, 48px);
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.nd-contact span { opacity: 0.55; }
.nd-contact a {
  color: inherit;
  text-decoration: none;
  font-size: 14px;
  border-bottom: 1px solid color-mix(in oklch, var(--warm-white) 40%, transparent);
  align-self: flex-start;
  padding-bottom: 3px;
}

@media (max-width: 900px) {
  .site-header .hv-nav { display: none; }
  .nav-toggle { display: flex; }
}
@media (prefers-reduced-motion: reduce) {
  .nav-scrim, .nav-drawer { transition: none; }
}
