/* ============================================================
   BEARMINDFUL — PAGE LAYOUTS
   ============================================================ */

/* ============================================================
   THE COVER
   ============================================================ */

/* The three round tabs are the whole point of the front page, so the
   cover has a fixed vertical budget and the type is sized against the
   viewport HEIGHT as well as its width. A 1280x720 laptop is the tight
   case: get that right and everything taller is comfortable. */
.cover {
  position: relative;
  display: grid;
  min-height: min(calc(100svh - var(--nav-h)), 46rem);
  isolation: isolate;
  overflow: hidden;
  /* A real painted background under the artwork. If the SVG ever fails
     to load the white title still sits on dusk at 14.3:1 rather than on
     the page's white — and it makes the contrast honestly measurable. */
  background: var(--bg);
}

/* Pull the cover up so the artwork runs behind the sticky header. Without
   this, a transparent nav is transparent over the page's WHITE body, not
   over the cover, and the white wordmark disappears. */
.cover--bleed {
  margin-block-start: calc(var(--nav-h) * -1);
  padding-block-start: var(--nav-h);
  min-height: min(100svh, calc(46rem + var(--nav-h)));
}

.cover__scene {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.cover__svg {
  width: 100%;
  height: 100%;
  /* The scene is composed at 16:9 with the clearing dead centre, so a
     centre crop is right at every aspect ratio. */
  object-fit: cover;
}

/* The cover art is busy at the top where the title sits, and bright in
   the middle where the badges sit. Two soft washes, not a flat scrim. */
.cover__vignette {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(to bottom,
      oklch(0.14 0.035 215 / 0.72) 0%,
      oklch(0.14 0.035 215 / 0.30) 34%,
      oklch(0.14 0.035 215 / 0) 58%),
    linear-gradient(to top,
      oklch(0.12 0.030 215 / 0.55) 0%,
      oklch(0.12 0.030 215 / 0) 30%);
}

.cover__content {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-rows: auto 1fr auto;
  align-content: space-between;
  gap: var(--space-6);
  padding-block: clamp(2rem, 5vh, 4.5rem) clamp(2.5rem, 7vh, 5rem);
}

.cover__lockup { max-width: min(46ch, 54vw); }

.cover__series {
  font-family: var(--font-text);
  font-size: var(--step-0);
  font-style: italic;
  color: var(--ember-300);
  margin-block-end: var(--space-2);
}

.cover__title {
  /* Height-aware, not just width-aware: on a short laptop window the
     title has to give room back to the tabs. */
  font-size: clamp(2.2rem, min(7vw, 9.2vh), 4.75rem);
  color: var(--paper);
  /* One deep soft shadow so the type survives a bright patch of sky
     without needing a box behind it. */
  text-shadow: 0 2px 30px oklch(0.10 0.03 215 / 0.75),
               0 1px 3px oklch(0.10 0.03 215 / 0.5);
}

.cover__blurb {
  margin-block-start: var(--space-4);
  font-size: var(--step-1);
  color: oklch(0.94 0.02 80);
  max-width: 30ch;
  text-shadow: 0 1px 16px oklch(0.10 0.03 215 / 0.8);
}

/* The three tabs sit in a loose arc, not an even row. --lift does the
   arc; --tilt does the hand-placed rotation. */
.cover__tabs {
  grid-row: 3;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(1rem, 4vw, 3.5rem);
}

.cover__tab { display: block; }

.cover__tabs .badge {
  --size: clamp(116px, min(14.5vw, 25vh), 208px);
  transform: rotate(var(--tilt)) translateY(var(--lift, 0));
}

@media (hover: hover) and (pointer: fine) {
  .cover__tabs .badge:hover {
    transform: rotate(var(--tilt)) translateY(calc(var(--lift, 0px) - 5px));
  }
}

.cover__tabs .badge:active {
  transform: rotate(var(--tilt)) translateY(var(--lift, 0)) scale(0.97);
}

.cover__hint {
  position: absolute;
  right: var(--gutter);
  bottom: var(--space-3);
  z-index: 2;
}

.cover__hint .placeholder-note {
  background: oklch(0.10 0.03 215 / 0.5);
  color: oklch(0.88 0.02 80);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

@media (max-width: 720px) {
  .cover { min-height: auto; }
  .cover__content { padding-block: var(--space-7) var(--space-8); gap: var(--space-8); }
  .cover__tabs { gap: var(--space-5); }
  .cover__tabs .badge { --lift: 0px !important; }
  .cover__lockup { max-width: none; }
}

/* ============================================================
   BANDS
   ============================================================ */

.band-paper { background: var(--paper); }
.band-sunk  { background: var(--bg-sunk); }

.band-dusk {
  background: var(--dusk-700);
  color: var(--paper);
  --ink: var(--paper);
  --ink-muted: oklch(0.80 0.035 200);
  --rule: oklch(1 0 0 / 0.16);
  --rule-strong: oklch(1 0 0 / 0.3);
  /* Lamplight, not rosehip — the dusk band speaks the story world's
     language, and amber carries moss-900 ink. */
  --accent: var(--ember-500);
  --on-accent: var(--moss-900);
  --focus: var(--ember-300);
}

/* ============================================================
   HOMEPAGE
   ============================================================ */

.promise {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-7);
}

@media (min-width: 940px) {
  .promise {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
    gap: clamp(var(--space-7), 6vw, var(--space-10));
    align-items: start;
  }
}

.promise__intro h2 { font-size: var(--step-4); max-width: 14ch; }

/* Four promises as a hairline list. Boxing them would put four more
   containers on a page that already has three big ones below. */
.promise__list { display: grid; gap: 0; margin: 0; }

.promise__item {
  display: grid;
  gap: var(--space-1);
  padding-block: var(--space-5);
  border-top: 1px solid var(--rule);
}

.promise__item:last-child { border-bottom: 1px solid var(--rule); }

.promise__item dt {
  font-family: var(--font-display);
  font-size: var(--step-1);
  letter-spacing: var(--track-tight);
  color: var(--moss-700);
}

.promise__item dd { margin: 0; color: var(--ink-muted); max-width: 52ch; }

@media (min-width: 620px) {
  .promise__item {
    grid-template-columns: minmax(11rem, 16rem) minmax(0, 1fr);
    gap: var(--space-5);
    align-items: baseline;
  }
}

/* ---- The three tabs, as picture-and-text rows ----------------------
   Three identical cards would be the reflex, and the reflex is the tell.
   Alternating rows let each tab show what is actually behind it. */

.doors { display: grid; gap: clamp(var(--space-7), 5vw, var(--space-9)); }

.door {
  display: grid;
  gap: var(--space-6);
  align-items: center;
}

@media (min-width: 860px) {
  /* The picture keeps the same width on every row. Flipping only the
     order would hand the wider column to whichever row was flipped. */
  .door {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: clamp(var(--space-7), 5vw, var(--space-9));
  }
  .door:nth-child(even) { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
  .door:nth-child(even) .door__art { order: 2; }
}

.door__art {
  position: relative;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: color-mix(in oklab, var(--door-tint) 14%, var(--paper));
  box-shadow: inset 0 0 0 2px color-mix(in oklab, var(--door-tint) 26%, transparent);
  aspect-ratio: 4 / 3;
}

/* Absolutely positioned, not height:100%. A percentage height cannot
   resolve against a grid row whose size is still being computed, so it
   silently falls back to auto — the 600x600 sketch became 501x501 in a
   501x376 box and lost its feet. */
.door__art > * {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.door__art > img { object-fit: cover; }

.door--making     { --door-tint: var(--moss-500); }
.door--story      { --door-tint: var(--ember-500); }
.door--activities { --door-tint: var(--berry-500); }

.door--making .door__art > img { object-fit: contain; padding: var(--space-6); }

.door__body h3 { font-size: var(--step-3); margin-block-end: var(--space-4); }
.door__body h3 a { text-decoration: none; }

/* The whole row is the target, but the link stays the accessible name. */
.door__body h3 a::after { content: ''; position: absolute; inset: 0; }
.door { position: relative; }

@media (hover: hover) and (pointer: fine) {
  .door__body h3 a:hover { color: color-mix(in oklab, var(--door-tint) 74%, var(--ink)); }
  .door:hover .door__art { box-shadow: inset 0 0 0 2px color-mix(in oklab, var(--door-tint) 55%, transparent); }
}

.door__body p { color: var(--ink-muted); font-size: var(--step-0); }
.door__body strong { color: var(--berry-500); }

.door__meta {
  margin-block-start: var(--space-4);
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--bark-600) !important;
}

/* Three animal portraits overlapped, so the activities tab shows its
   contents rather than an icon standing in for them. */
.cluster-art {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  box-sizing: border-box;
}

.cluster-art img {
  width: clamp(88px, 26%, 168px);
  border-radius: var(--r-full);
  box-shadow: 0 8px 22px -10px oklch(0.22 0.03 118 / 0.5);
  transition: transform var(--dur-ui) var(--ease-out-quart);
}

.cluster-art img:nth-child(1) { transform: rotate(-8deg) translateX(14%); z-index: 1; }
.cluster-art img:nth-child(2) { width: clamp(104px, 31%, 196px); z-index: 2; }
.cluster-art img:nth-child(3) { transform: rotate(8deg) translateX(-14%); z-index: 1; }

@media (hover: hover) and (pointer: fine) {
  .door:hover .cluster-art img:nth-child(1) { transform: rotate(-11deg) translateX(4%); }
  .door:hover .cluster-art img:nth-child(3) { transform: rotate(11deg) translateX(-4%); }
}

@media (prefers-reduced-motion: reduce) {
  .cluster-art img { transition: none; }
}

/* ---- The printed book ---- */

.bookstrip {
  display: grid;
  gap: var(--space-7);
  align-items: center;
}

@media (min-width: 860px) {
  .bookstrip { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-9); }
}

.bookstrip__cover {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
}

/* ============================================================
   PAGE HEADER — used on every inner page
   ============================================================ */

.crumbs { margin-block-end: var(--space-5); }

.crumbs ol {
  list-style: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  font-size: var(--step--1);
  color: var(--ink-muted);
}

.crumbs li + li::before { content: '›'; margin-inline-end: var(--space-3); opacity: 0.55; }
.crumbs a { text-decoration: none; }

@media (hover: hover) and (pointer: fine) { .crumbs a:hover { color: var(--ink); } }

.page-head { padding-block: clamp(2rem, 5vw, 4rem) clamp(1.5rem, 3vw, 2.5rem); }
.page-head h1 { font-size: var(--step-5); max-width: 18ch; }
.page-head .lede { margin-block-start: var(--space-5); }

/* The story page gives its vertical budget to the player, not the title. */
.page-head--story { padding-block: var(--space-3) var(--space-5); }
.page-head--story h1 { font-size: var(--step-2); max-width: none; }
.page-head--story .cover__series { margin-block-end: 0; }

/* ============================================================
   TAB 1 — HOW THE CUB BEAR WAS MADE
   ============================================================ */

/* Numbered markers are used here and nowhere else on the site, because
   this section genuinely is a sequence: you cannot colour before you
   draw, or model before you colour. */
.stage {
  display: grid;
  gap: var(--space-6);
  padding-block: var(--space-section);
  border-top: 2px solid var(--rule);
}

@media (min-width: 980px) {
  .stage { grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: var(--space-8); }
  .stage--flip .stage__media { order: 2; }
}

.stage__num {
  font-family: var(--font-display);
  font-size: var(--step-4);
  line-height: 1;
  /* moss-300 on paper measures 2.11:1 — below the 3:1 large-text floor
     even at 61px. moss-500 clears it at 4.17:1. */
  color: var(--moss-500);
  display: block;
  margin-block-end: var(--space-2);
}

.stage h2 { font-size: var(--step-3); }

.stage__runtime {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-block-start: var(--space-3);
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--bark-600);
}

.stage__child {
  margin-block-start: var(--space-5);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--r-md);
  background: var(--moss-100);
  font-size: var(--step-1);
  font-family: var(--font-display);
  letter-spacing: var(--track-tight);
  line-height: 1.3;
}

.stage__watch {
  margin-block-start: var(--space-4);
  color: var(--ink-muted);
  font-style: italic;
}

/* ---- Apps the illustrator used ---- */

.apps { display: grid; gap: var(--space-4); list-style: none; padding: 0; }

.app {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--space-4) var(--space-5);
  align-items: baseline;
  padding-block: var(--space-5);
  border-top: 1px solid var(--rule);
}

.app__name { font-family: var(--font-display); font-size: var(--step-1); letter-spacing: var(--track-tight); }
.app__use { color: var(--ink-muted); }

.app__price {
  justify-self: end;
  white-space: nowrap;
  font-weight: 700;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--r-full);
  background: var(--moss-100);
  color: var(--moss-700);
  font-size: var(--step--1);
}

.app__price--free { background: color-mix(in oklab, var(--moss-500) 22%, transparent); }

@media (max-width: 640px) {
  .app { grid-template-columns: minmax(0, 1fr) auto; }
  .app__use { grid-column: 1 / -1; }
}

.portrait {
  width: 100%;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
}

.skills { list-style: none; padding: 0; display: grid; gap: var(--space-4); }

.skills li {
  padding-block-start: var(--space-4);
  border-top: 1px solid var(--rule);
  font-size: var(--step-0);
  color: var(--ink-muted);
  max-width: var(--measure);
}

.skills strong { color: var(--ink); }

/* ============================================================
   TAB 2 — THE STORY PLAYER
   ============================================================ */

.player {
  display: grid;
  gap: clamp(var(--space-3), 2vw, var(--space-5));
  justify-items: center;
}

/* Sized from the viewport HEIGHT, not its width. The giant play button
   has to be on screen at the same time as the picture — on a 1280x720
   laptop a width-driven 16:9 stage pushes the transport below the fold,
   which defeats the entire design. */
.player__stage {
  position: relative;
  height: min(42svh, 540px);
  aspect-ratio: 16 / 9;
  width: auto;
  max-width: 100%;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--dusk-900);
  box-shadow: var(--shadow-2);
  isolation: isolate;
}

@media (max-width: 720px) {
  .player__stage { height: auto; width: 100%; }
}

/* Short-and-wide windows — the 1280x720 laptop, and any 16:9 screen in
   a browser with chrome — need the play button above the fold more than
   they need a big picture. Give the height back to the transport. */
@media (min-width: 900px) and (max-height: 800px) {
  .page-head--story { padding-block: var(--space-2) var(--space-3); }
  .player__stage { height: min(38svh, 460px); }
  .player .chapter { min-height: 50px; }
  .player .chapter__mode { font-size: 0.85rem; }
}

.player__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.player__part { position: absolute; inset: 0; }
.player__part[hidden] { display: none; }

/* ---- The listening state.
     Audio-only is the hard part of this screen. The picture has to stay
     alive without pulling attention away from the voice reading aloud,
     so: one very slow breath, and a light that drifts. Nothing cuts. ---- */

.listening { position: absolute; inset: 0; }

.listening__art {
  width: 100%;
  height: 100%;
  object-fit: cover;
  animation: breathe 9s var(--ease-in-out) infinite alternate;
  transform-origin: 50% 58%;
}

@keyframes breathe {
  from { transform: scale(1); }
  to   { transform: scale(1.016); }
}

.listening__glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(38% 46% at 50% 62%,
    oklch(0.84 0.10 65 / 0.22), transparent 70%);
  animation: drift-glow 13s var(--ease-in-out) infinite alternate;
}

@keyframes drift-glow {
  from { transform: translate3d(-2%, 0, 0); opacity: 0.7; }
  to   { transform: translate3d(2%, -1.5%, 0); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .listening__art, .listening__glow { animation: none; }
}

/* ---- The read-aloud line.
     It sits ON the picture, not under it. It is a caption for what is on
     screen, it keeps the words and the image in one glance, and it buys
     back the ~90px of vertical space the transport needs on a laptop. ---- */

.player__line {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 3;
  margin: 0;
  padding: clamp(2.5rem, 8%, 4rem) clamp(1rem, 5%, 3rem) clamp(0.9rem, 4%, 1.6rem);
  max-width: none;
  text-align: center;
  font-size: clamp(1rem, 1.9cqw + 0.5rem, 1.5rem);
  line-height: 1.4;
  color: var(--paper);
  text-wrap: balance;
  text-shadow: 0 1px 14px oklch(0.08 0.02 210 / 0.9);
  background: linear-gradient(to top,
    oklch(0.08 0.02 210 / 0.82) 0%,
    oklch(0.08 0.02 210 / 0.45) 45%,
    oklch(0.08 0.02 210 / 0) 100%);
  pointer-events: none;
}

.player[data-mode='listen'] .player__line { font-style: italic; }

.player__transport { padding-block-start: var(--space-2); }

.player__transport { display: grid; gap: var(--space-5); justify-items: center; width: 100%; }

.player .chapters { width: 100%; max-width: 820px; }
.player .chapter { min-height: 56px; padding-block: var(--space-2); }

/* ---- Lights down. Rare, deliberate, and the point of the page. ---- */

body.is-lights-down { background: var(--dusk-900); }

body.is-lights-down .nav,
body.is-lights-down .footer,
body.is-lights-down .story-notes,
body.is-lights-down .crumbs,
body.is-lights-down .page-head {
  opacity: 0.12;
  transition: opacity var(--dur-scene) var(--ease-out-quart);
}

body.is-lights-down .nav:focus-within,
body.is-lights-down .footer:focus-within { opacity: 1; }

body.is-lights-down .player__stage { box-shadow: 0 0 90px -20px oklch(0.70 0.165 55 / 0.28); }

.player__vignette {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(118% 88% at 50% 46%,
    transparent 40%, oklch(0.08 0.02 210 / 0.62) 100%);
  transition: opacity var(--dur-scene) var(--ease-out-quart);
}

body.is-lights-down .player__vignette { opacity: 1; }

/* ---- Carry on from where we stopped ---- */

.resume {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--r-full);
  background: color-mix(in oklab, var(--ember-500) 18%, var(--dusk-700));
  box-shadow: inset 0 0 0 2px color-mix(in oklab, var(--ember-500) 45%, transparent);
}

.resume p { margin: 0; }

.story-notes { padding-block: var(--space-section); }

/* ============================================================
   TAB 3 — ACTIVITIES
   ============================================================ */

.hub {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 4vw, 3rem);
  justify-content: center;
}

.hub .badge { --badge-fill: var(--paper); }

.creatures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-6);
  list-style: none;
  padding: 0;
}

.creature {
  display: grid;
  justify-items: center;
  gap: var(--space-3);
  text-align: center;
}

.creature[hidden] { display: none; }

.creature__link { text-decoration: none; display: grid; justify-items: center; gap: var(--space-3); }

.creature__art {
  width: 100%;
  max-width: 220px;
  border-radius: var(--r-full);
  transition: transform var(--dur-ui) var(--ease-out-quart),
              box-shadow var(--dur-ui) var(--ease-out-quart);
}

@media (hover: hover) and (pointer: fine) {
  .creature__link:hover .creature__art {
    transform: translateY(-4px);
    box-shadow: var(--shadow-2);
  }
}

.creature__link:active .creature__art { transform: scale(0.97); }

.creature__name { font-size: var(--step-1); }

.creature__young { font-size: var(--step-0); color: var(--ink-muted); max-width: 24ch; }
.creature__young strong { color: var(--berry-500); }

.filters { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-block-end: var(--space-7); }

/* ---- Species page ---- */

.species {
  display: grid;
  gap: var(--space-7);
  align-items: start;
}

@media (min-width: 900px) {
  .species { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: var(--space-9); }
}

.species__art { width: 100%; border-radius: var(--r-full); box-shadow: var(--shadow-2); }

.species__young {
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: 1.2;
  color: var(--moss-700);
  margin-block: var(--space-4);
}

.species__young strong { color: var(--berry-500); }

.facts { list-style: none; padding: 0; display: grid; gap: var(--space-4); counter-reset: fact; }

.facts__item {
  position: relative;
  padding-inline-start: calc(var(--space-6) + var(--space-3));
  font-size: var(--step-1);
  line-height: 1.5;
  counter-increment: fact;
}

.facts__item::before {
  content: counter(fact);
  position: absolute;
  left: 0;
  top: 0.1em;
  display: grid;
  place-items: center;
  width: var(--space-6);
  height: var(--space-6);
  border-radius: var(--r-full);
  background: var(--moss-100);
  color: var(--moss-700);
  font-family: var(--font-display);
  font-size: var(--step-0);
}

.listen-row {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5);
  border-radius: var(--r-lg);
  background: var(--bg-sunk);
}

.more {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--space-5);
}

.more__item { display: grid; justify-items: center; gap: var(--space-2); text-decoration: none; text-align: center; }
.more__item img { width: 100%; max-width: 130px; border-radius: var(--r-full); }
.more__item span { font-family: var(--font-display); font-size: var(--step-0); }

/* ---- The Listening Wall ---- */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-6);
}

.tile {
  display: grid;
  justify-items: center;
  gap: var(--space-3);
  cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--step-0);
  letter-spacing: var(--track-tight);
  color: var(--ink);
  transition: transform var(--dur-press) var(--ease-out-quart);
}

.tile__disc { position: relative; display: block; width: 100%; max-width: 190px; }
.tile__disc img { width: 100%; border-radius: var(--r-full); }

.tile__ring { position: absolute; inset: -6px; width: calc(100% + 12px); height: calc(100% + 12px); }

.tile__ring circle {
  fill: none;
  stroke: var(--ember-500);
  stroke-width: 4;
  stroke-linecap: round;
  transform: rotate(-90deg);
  transform-origin: 50% 50%;
  stroke-dasharray: 289;
  stroke-dashoffset: 289;
}

.tile.is-playing .tile__ring circle { animation: ring-fill var(--dur, 2s) linear forwards; }

@media (prefers-reduced-motion: reduce) {
  .tile.is-playing .tile__ring circle { animation: none; stroke-dashoffset: 0; }
}

.tile:active { transform: scale(0.97); }

.tile.is-wrong { animation: shake 400ms var(--ease-out-quart); }

@keyframes shake {
  0%, 100% { transform: none; }
  25% { transform: translateX(-6px); }
  75% { transform: translateX(6px); }
}

@media (prefers-reduced-motion: reduce) { .tile.is-wrong { animation: none; opacity: 0.5; } }

.guess {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-6);
  border-radius: var(--r-lg);
  background: var(--bg-sunk);
  margin-block-end: var(--space-7);
}

.guess__status { font-family: var(--font-display); font-size: var(--step-1); letter-spacing: var(--track-tight); }

/* ---- Screensavers ---- */

.savers { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--space-7); }

.saver { display: grid; gap: var(--space-4); }

.saver__preview {
  width: 100%;
  border-radius: var(--r-md);
  box-shadow: var(--shadow-2);
  background: var(--dusk-900);
  object-fit: cover;
}

.saver__meta { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; justify-content: space-between; }
.saver__size { font-size: var(--step--1); color: var(--ink-muted); font-weight: 600; }

/* ---- Newsletter ---- */

.gate { max-width: 40rem; }

.gate__lock {
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  border-radius: var(--r-full);
  background: var(--moss-100);
  color: var(--moss-700);
  margin-block-end: var(--space-5);
}

.gate__lock svg { width: 44px; height: 44px; }

.signup { max-width: 40rem; display: grid; gap: var(--space-6); }
.signup[hidden] { display: none; }

.consents { display: grid; gap: var(--space-4); }

.success {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-7);
  border-radius: var(--r-lg);
  background: color-mix(in oklab, var(--moss-500) 12%, var(--paper));
  box-shadow: inset 0 0 0 2px color-mix(in oklab, var(--moss-500) 32%, transparent);
}

.success[hidden] { display: none; }

/* ============================================================
   DESIGN SYSTEM PAGE
   ============================================================ */

.swatches { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--space-4); }

.swatch { display: grid; gap: var(--space-2); }

.swatch__chip {
  height: 88px;
  border-radius: var(--r-md);
  box-shadow: inset 0 0 0 1px oklch(0 0 0 / 0.12);
}

.swatch__name { font-weight: 700; font-size: var(--step-0); }
.swatch__val { font-size: var(--step--1); color: var(--ink-muted); font-variant-numeric: tabular-nums; }

.ratios { width: 100%; border-collapse: collapse; font-size: var(--step-0); }
.ratios th, .ratios td { text-align: left; padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--rule); }
.ratios th { font-weight: 700; }
.ratios td:last-child, .ratios th:last-child { text-align: right; }
.ratios .pass { color: var(--moss-700); font-weight: 700; }
.ratios .large { color: var(--bark-600); font-weight: 700; }
.ratios .fail { color: var(--berry-500); font-weight: 700; }

.scroll-x { overflow-x: auto; min-width: 0; max-width: 100%; }

.specimen { display: grid; gap: var(--space-2); padding-block: var(--space-5); border-bottom: 1px solid var(--rule); }
.specimen__meta { font-size: var(--step--1); color: var(--ink-muted); font-variant-numeric: tabular-nums; }

.worlds { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-5); }

.world-card { padding: var(--space-6); border-radius: var(--r-lg); display: grid; gap: var(--space-3); }
.world-card h3 { font-size: var(--step-1); }
.world-card p { font-size: var(--step--1); }
.world-card--studio { background: var(--paper); color: var(--moss-900); box-shadow: inset 0 0 0 2px var(--rule); }
.world-card--forest { background: var(--moss-100); color: var(--moss-900); }
.world-card--dusk   { background: var(--dusk-700); color: var(--paper); }
.world-card--night  { background: var(--dusk-900); color: var(--paper); }

/* ============================================================
   CONTENT SWAP DEMO
   ============================================================ */

.swap { display: grid; gap: var(--space-7); }

@media (min-width: 1000px) {
  .swap { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: var(--space-8); align-items: start; }
}

/* Grid children default to min-width:auto, which refuses to shrink below
   their content and pushes the page sideways. */
.swap { min-width: 0; }
.swap > * { min-width: 0; }
.swap__previews { display: grid; gap: var(--space-5); min-width: 0; }

.swap__frame {
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-2);
  background: var(--dusk-900);
}

.swap__frame img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; }

.swap__caption {
  padding: var(--space-4) var(--space-5);
  background: var(--paper);
  display: grid;
  gap: var(--space-1);
}

.swap__caption strong { font-family: var(--font-display); font-size: var(--step-1); letter-spacing: var(--track-tight); }
.swap__caption span { font-size: var(--step--1); color: var(--ink-muted); }

.swap__thumbs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3); }
.swap__thumbs img { width: 100%; border-radius: var(--r-md); aspect-ratio: 1; object-fit: cover; }

.swap__code {
  margin: 0;
  padding: var(--space-5);
  border-radius: var(--r-md);
  background: var(--dusk-900);
  color: oklch(0.90 0.02 200);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.86rem;
  line-height: 1.65;
  overflow-x: auto;
  tab-size: 2;
}

.swap__code b { color: var(--ember-300); font-weight: 400; }
.swap__code i { color: oklch(0.62 0.03 200); font-style: normal; }

/* ============================================================
   SMALL-SCREEN NOTE
   The brief is explicit that this is not a phone product. Saying so
   once, politely, beats pretending otherwise.
   ============================================================ */

.screen-note {
  display: none;
  position: fixed;
  left: var(--space-4);
  right: var(--space-4);
  bottom: var(--space-4);
  z-index: var(--z-toast);
  gap: var(--space-3);
  justify-items: start;
  padding: var(--space-5);
  border-radius: var(--r-lg);
  background: var(--moss-900);
  color: var(--paper);
  box-shadow: var(--shadow-2);
}

@media (max-width: 699px) {
  .screen-note:not([data-dismissed]) { display: grid; }
}
.screen-note p { font-size: var(--step--1); margin: 0; }
.screen-note .btn { color: var(--ember-300); }

/* ============================================================
   FOOTER BITS
   ============================================================ */

.footer__brand { font-family: var(--font-display); font-size: var(--step-2); letter-spacing: var(--track-tight); }
.footer__note { font-size: var(--step--1); color: var(--ink-muted); max-width: 30ch; }
.footer__head { font-family: var(--font-text); font-size: var(--step-0); font-weight: 700; margin-block-end: var(--space-4); }
.footer__ext { margin-inline-start: 0.35em; font-size: 0.8em; }

/* ============================================================
   404
   ============================================================ */

.lost { display: grid; justify-items: center; text-align: center; gap: var(--space-5); padding-block: var(--space-10); }
.lost img { width: min(320px, 70vw); }

/* ============================================================
   SCREENSAVERS
   ============================================================ */

.saver__row { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
.saver__select { max-width: 20rem; flex: 1 1 12rem; }

/* ============================================================
   BOOK PAGE
   ============================================================ */

.specs { display: grid; gap: 0; }

.specs > div {
  display: grid;
  grid-template-columns: minmax(8rem, 12rem) 1fr;
  gap: var(--space-4);
  padding-block: var(--space-3);
  border-top: 1px solid var(--rule);
}

.specs dt { font-weight: 700; color: var(--ink-muted); }
.specs dd { margin: 0; }

/* ============================================================
   CONTENT SWAP
   ============================================================ */

.seasons { display: grid; gap: var(--space-3); }

.season {
  display: grid;
  gap: var(--space-1);
  justify-items: start;
  text-align: left;
  padding: var(--space-4) var(--space-5);
  border-radius: var(--r-md);
  cursor: pointer;
  background: transparent;
  box-shadow: inset 0 0 0 2.5px var(--rule-strong);
  transition: box-shadow var(--dur-ui) var(--ease-out-quart),
              background-color var(--dur-ui) var(--ease-out-quart),
              transform var(--dur-press) var(--ease-out-quart);
}

.season__badge {
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: var(--track-label);
  color: var(--ink-muted);
}

.season__name {
  font-family: var(--font-display);
  font-size: var(--step-1);
  letter-spacing: var(--track-tight);
  line-height: 1.15;
}

.season__when { font-size: var(--step--1); color: var(--ink-muted); }

@media (hover: hover) and (pointer: fine) {
  .season:hover { box-shadow: inset 0 0 0 2.5px var(--accent); }
}

.season:active { transform: scale(0.99); }

.season[aria-pressed='true'] {
  background: color-mix(in oklab, var(--accent) 12%, transparent);
  box-shadow: inset 0 0 0 2.5px var(--accent);
}

.season[aria-pressed='true'] .season__badge { color: var(--accent); }

/* A hairline in the season's own accent, so flipping the switch visibly
   retints the preview and not just its picture. */
.swap__frame {
  box-shadow: var(--shadow-2), inset 0 0 0 3px var(--swap-accent, transparent);
}

.swap__frame img { transition: opacity var(--dur-panel) var(--ease-out-quart); }

/* ============================================================
   DESIGN SYSTEM EXTRAS
   ============================================================ */

.ruler { display: flex; gap: 6px; align-items: flex-end; margin-block-start: var(--space-4); }
.ruler span { height: 26px; background: var(--moss-300); border-radius: 3px; }

.radii { display: flex; gap: var(--space-3); margin-block-start: var(--space-4); flex-wrap: wrap; }
.radii span { width: 48px; height: 48px; background: var(--moss-300); display: block; }

.curves { display: grid; gap: var(--space-3); margin-block-start: var(--space-4); }

.curves span {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-4);
  font-size: var(--step--1);
  color: var(--ink-muted);
}

.curves i {
  display: block;
  height: 10px;
  border-radius: var(--r-full);
  background: var(--moss-100);
  position: relative;
}

.curves i::after {
  content: '';
  position: absolute;
  top: -3px; left: 0;
  width: 16px; height: 16px;
  border-radius: var(--r-full);
  background: var(--ember-500);
  transform: translateX(0);
}

.curves.is-running i::after {
  animation: slide 1s var(--e) both;
}

/* The dot travels the whole track. Animating `left` on an absolutely
   positioned pseudo-element costs nothing here and is the only way to
   express "the full width of my parent" — a percentage translate would
   be a percentage of the dot itself. */
@keyframes slide { to { left: 100%; transform: translateX(-100%); } }

@media (prefers-reduced-motion: reduce) { .curves.is-running i::after { animation: none; } }

/* ============================================================
   LEGAL PAGES
   ============================================================ */

.legal h2 { font-size: var(--step-2); margin-block-end: var(--space-3); }
.legal p + p { margin-block-start: var(--space-3); }
.legal section { padding-block-start: var(--space-5); border-top: 1px solid var(--rule); }

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.88em;
  padding: 0.1em 0.36em;
  border-radius: 5px;
  background: color-mix(in oklab, var(--ink) 8%, transparent);
}
