/* Gaming Life — gaminglife.com
 *
 * The studio should look like the thing it makes: the games' own palette, flat fills, chunky
 * rounded geometry, with the ink borders doing the outlining. Depth is soft and low-key — quiet
 * ink-tinted shadows, never hard offset "sticker" shadows. No gradients.
 * Colours are the tokens from src/art/palette.js, restated in OKLCH so lightness steps are
 * perceptually even and the neutrals can be tinted toward the brand hues.
 */
/* Self-hosted variable fonts — two files, 69 KB, every weight. See fonts/README.md for why.
   `font-display: swap` so text is readable immediately and the page never blocks on a font. */
@font-face {
  font-family: 'Gabarito';
  src: url('/fonts/gabarito-var.woff2') format('woff2-variations');
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Hanken Grotesk';
  src: url('/fonts/hanken-grotesk-var.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
:root {
  --cream: oklch(97.6% 0.021 88);
  --cream-deep: oklch(93.5% 0.03 86);
  --cream-edge: oklch(88% 0.038 84);
  --ink: oklch(34% 0.038 248);
  --ink-soft: oklch(50% 0.03 248);
  --ink-faint: oklch(51% 0.025 248);
  --sun: oklch(86.5% 0.155 88);
  --amber: oklch(80% 0.155 72);
  --coral: oklch(70% 0.165 18);
  --mint: oklch(82% 0.09 178);
  --blue: oklch(66% 0.15 260);
  --shadow: 0 2px 6px oklch(34% 0.038 248 / 0.12), 0 6px 18px oklch(34% 0.038 248 / 0.08);
  --shadow-lg: 0 3px 8px oklch(34% 0.038 248 / 0.14), 0 10px 28px oklch(34% 0.038 248 / 0.1);
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 40px;
  --space-2xl: 64px;
  --space-3xl: clamp(72px, 11vw, 128px);
  --radius: 14px;
  --radius-lg: 26px;
  --measure: 68ch;
  --font-display: Gabarito, ui-rounded, 'Segoe UI', system-ui, sans-serif;
  --font-body: 'Hanken Grotesk', system-ui, -apple-system, sans-serif;
}
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.022em;
  margin: 0;
  text-wrap: balance;
}
a {
  color: inherit;
}
.wrap {
  width: min(1080px, 100% - 2 * var(--space-lg));
  margin-inline: auto;
}
/* ---------------------------------------------------------------- header */
.masthead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  padding-block: var(--space-lg);
  flex-wrap: wrap;
}
.mark {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 20px;
  letter-spacing: -0.02em;
  text-decoration: none;
}
.mark svg {
  display: block;
}
.masthead nav {
  display: flex;
  gap: var(--space-lg);
  font-size: 15px;
  font-weight: 600;
}
.masthead nav a {
  text-decoration: none;
  color: var(--ink-soft);
  padding-bottom: 2px;
  border-bottom: 2px solid transparent;
  transition: color 0.15s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.15s;
}
.masthead nav a:hover {
  color: var(--ink);
  border-bottom-color: var(--sun);
}
/* ---------------------------------------------------------------- hero */
.hero {
  padding-block: clamp(var(--space-2xl), 8vw, 100px) var(--space-3xl);
}
.hero h1 {
  font-size: clamp(2.9rem, 8.5vw, 5.5rem);
  max-width: 13ch;
}
.hero h1 .lit {
  position: relative;
  white-space: nowrap;
}
.hero h1 .lit::after {
  content: '';
  position: absolute;
  inset: 0.62em -0.06em 0.02em -0.06em;
  background: var(--sun);
  border-radius: 4px 10px 5px 8px;
  z-index: -1;
}
.hero p {
  max-width: 40ch;
  margin: var(--space-lg) 0 0;
  font-size: clamp(1.05rem, 2.1vw, 1.32rem);
  line-height: 1.5;
  color: var(--ink-soft);
}
/* ---------------------------------------------------------------- games */
.section-label {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
  margin-bottom: var(--space-xl);
}
.section-label h2 {
  font-size: 1.05rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
}
.section-label .rule {
  flex: 1;
  height: 2px;
  background: var(--cream-edge);
}
.games {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  align-items: start;
}
.game {
  display: block;
  text-decoration: none;
  background: var(--cream-deep);
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  box-shadow: var(--shadow-lg);
}
/* Two games are a composition, not a repeating unit — the first one gets the weight. */
.game--lead {
  background: var(--sun);
}
/* No hover lift while these are <article> and not <a>. A card that rises under the cursor promises
   a click, and there is nothing to click yet. Restore the lift when the games go live and these
   become links. */
/* The artwork is square (it's the same key art the store tiles use), so the frame is square too:
   no crop, the whole picture, at 1x or 2x depending on the screen (srcset in the markup). */
.game figure {
  margin: 0 0 var(--space-lg);
  aspect-ratio: 1;
  background: var(--cream);
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  overflow: hidden;
}
.game figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.game h3 {
  font-size: 1.65rem;
}
.game p {
  margin: var(--space-sm) 0 var(--space-md);
  color: var(--ink-soft);
  font-size: 0.97rem;
  line-height: 1.5;
}
.game--lead p {
  color: oklch(40% 0.05 78);
}
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.tags span,
.tags a {
  border: 2px solid var(--ink);
  border-radius: 999px;
  padding: 3px 11px;
  background: var(--cream);
}
/* The next game. Deliberately not a card — it's a gap, and it should read as one. */
.next {
  border: 2px dashed var(--cream-edge);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  display: grid;
  place-content: center;
  text-align: center;
  min-height: 190px;
  color: var(--ink-faint);
}
.next strong {
  display: block;
  font-family: var(--font-display);
  font-size: 1.35rem;
  color: var(--ink-soft);
  margin-bottom: var(--space-xs);
}
/* ---------------------------------------------------------------- how */
.how {
  padding-block: var(--space-3xl);
}
.how-grid {
  display: grid;
  gap: var(--space-xl) var(--space-2xl);
  grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
}
.how-grid h3 {
  font-size: 1.28rem;
  margin-bottom: var(--space-sm);
}
.how-grid p {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.97rem;
}
.how-grid .n {
  font-family: var(--font-display);
  font-size: 0.82rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  color: var(--coral);
  display: block;
  margin-bottom: var(--space-sm);
}
/* ---------------------------------------------------------------- about */
.about {
  padding: var(--space-xl);
  background: var(--ink);
  color: var(--cream);
  border-radius: var(--radius-lg);
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  align-items: start;
}
.about h2 {
  font-size: clamp(1.6rem, 3.4vw, 2.3rem);
  margin-bottom: var(--space-md);
}
.about p {
  margin: 0 0 var(--space-md);
  color: oklch(88% 0.02 240);
  max-width: 46ch;
}
.about p:last-child {
  margin-bottom: 0;
}
.about a {
  color: var(--sun);
  text-underline-offset: 3px;
}
.contact {
  background: oklch(40% 0.035 248);
  border-radius: var(--radius);
  padding: var(--space-lg);
  font-size: 0.93rem;
}
.contact dt {
  font-weight: 700;
  color: var(--sun);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 2px;
}
.contact dd {
  margin: 0 0 var(--space-md);
  color: oklch(90% 0.015 240);
}
.contact dd:last-child {
  margin-bottom: 0;
}
/* ---------------------------------------------------------------- footer */
.foot {
  margin-top: var(--space-3xl);
  padding-block: var(--space-xl);
  border-top: 2px solid var(--cream-edge);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md) var(--space-lg);
  justify-content: space-between;
  align-items: center;
  font-size: 0.87rem;
  color: var(--ink-faint);
}
.foot nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm) var(--space-lg);
  min-width: 0;
}
.foot a {
  color: var(--ink-soft);
  text-decoration: none;
  border-bottom: 1px solid var(--cream-edge);
}
.foot a:hover {
  border-bottom-color: var(--ink-soft);
}
/* ---------------------------------------------------------------- legal pages */
.legal {
  padding-block: var(--space-2xl) var(--space-xl);
  max-width: var(--measure);
}
.legal h1 {
  font-size: clamp(2.2rem, 6vw, 3.4rem);
  margin-bottom: var(--space-md);
}
.legal .updated {
  color: var(--ink-faint);
  font-size: 0.87rem;
  margin: 0 0 var(--space-xl);
}
.legal h2 {
  font-size: 1.45rem;
  margin: var(--space-2xl) 0 var(--space-md);
}
.legal h3 {
  font-size: 1.08rem;
  margin: var(--space-xl) 0 var(--space-sm);
}
.legal p,
.legal li {
  color: var(--ink-soft);
}
.legal p {
  margin: 0 0 var(--space-md);
}
.legal ul {
  margin: 0 0 var(--space-md);
  padding-left: 1.15em;
}
.legal li {
  margin-bottom: var(--space-sm);
}
.legal a {
  color: var(--ink);
  text-underline-offset: 3px;
}
.legal strong {
  color: var(--ink);
}
/* The plain-language summary that opens each legal page — the part parents actually read. */
.gist {
  background: var(--sun);
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  margin-bottom: var(--space-2xl);
  box-shadow: var(--shadow);
}
.gist h2 {
  margin: 0 0 var(--space-sm);
  font-size: 1.2rem;
}
.gist p,
.gist li {
  color: oklch(36% 0.05 78);
}
.gist p:last-child,
.gist ul:last-child {
  margin-bottom: 0;
}
table.plain {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 var(--space-lg);
  font-size: 0.93rem;
}
table.plain th,
table.plain td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid var(--cream-edge);
  vertical-align: top;
  color: var(--ink-soft);
}
table.plain th {
  font-weight: 700;
  color: var(--ink);
  border-bottom: 2px solid var(--ink);
}
/* ---------------------------------------------------------------- responsive */
@media (max-width: 720px) {
  .about {
    grid-template-columns: 1fr;
  }
  .hero {
    max-width: none;
  }
}
/* ---------------------------------------------------------------- motion
 *
 * Two layers, and no more: one orchestrated page-load reveal, and one slow idle loop per game card.
 * The idle loops are not decoration — each one animates the thing its game actually does, so the
 * card shows the verb before you've read a word. Transform and opacity only; nothing here can
 * trigger layout.
 */
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
}
/* The signature moment: the sun highlight wipes in under the word after the headline lands. */
@keyframes wipe {
  from {
    transform: scaleX(0);
  }
}
.masthead,
.hero h1,
.hero p,
#games .section-label,
.games > *,
.how,
.about {
  animation: rise 0.62s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.hero h1 {
  animation-delay: 60ms;
}
.hero p {
  animation-delay: 140ms;
}
#games .section-label {
  animation-delay: 220ms;
}
.games > *:nth-child(1) {
  animation-delay: 280ms;
}
.games > *:nth-child(2) {
  animation-delay: 340ms;
}
.games > *:nth-child(3) {
  animation-delay: 400ms;
}
.how {
  animation-delay: 460ms;
}
.about {
  animation-delay: 520ms;
}
.hero h1 .lit::after {
  transform-origin: left center;
  animation: wipe 0.5s cubic-bezier(0.22, 1, 0.36, 1) 520ms both;
}
/* ---------------------------------------------------------------- focus */
a:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
  border-radius: 4px;
}
.cta:focus-visible,
.mark:focus-visible {
  outline-offset: 5px;
}
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}
/* Jip, the portal. Sits on style.css (tokens, fonts, .wrap, .foot). Same vocabulary as the games:
 * cream ground, ink outlines, flat fills, chunky radii, soft ink-tinted shadows. Touch targets are
 * big because the primary device is an iPad in a nine-year-old's hands. */
body {
  min-height: 100vh;
}
/* The play overlay and the loader set display: grid/flex, which would beat the `hidden`
   attribute's UA display: none. This keeps `hidden` meaning hidden everywhere on the portal. */
[hidden] {
  display: none !important;
}
.wrap {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
#view {
  flex: 1;
}
.boot {
  min-height: 40vh;
}
.noscript {
  padding: var(--space-lg);
  text-align: center;
}
.muted {
  color: var(--ink-faint);
}
hr {
  border: 0;
  border-top: 2px solid var(--cream-edge);
  margin: var(--space-lg) 0;
}
/* ---------------------------------------------------------------- top bar */
/* icons.js SVG comes in through a span (React's dangerouslySetInnerHTML); keep it on the baseline */
.svg {
  display: inline-flex;
  line-height: 0;
}
.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding-block: var(--space-md) var(--space-lg);
}
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 26px;
  letter-spacing: -0.02em;
  text-decoration: none;
}
.top nav {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}
.chip,
.parents-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 4px 14px 4px 6px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--cream-deep);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 15px;
  text-decoration: none;
  color: var(--ink);
}
.parents-link {
  padding-left: 12px;
  background: var(--cream);
  color: var(--ink-soft);
}
.parents-link .glyph {
  width: 20px;
  height: 20px;
}
.chip .glyph {
  width: 18px;
  height: 18px;
  color: var(--ink-faint);
}
.chip.time {
  padding-left: 8px;
  font-size: 14px;
}
.chip.time .ring {
  --p: 1;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  background: conic-gradient(var(--sun) calc(var(--p) * 100%), var(--cream) 0);
}
.chip.time.low {
  background: var(--amber);
}
.foot select.lang {
  font: inherit;
  font-size: 0.87rem;
  padding: 4px 8px;
  border: 2px solid var(--cream-edge);
  border-radius: 999px;
  background: var(--cream);
  color: var(--ink-soft);
}
/* A kid's request from another device, and "no games today" in the header (spec 4). */
.banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm) var(--space-md);
  margin: 0 0 var(--space-md);
  padding: var(--space-sm) var(--space-md);
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--sun);
  font-weight: 600;
}
.banner .row {
  display: flex;
  gap: var(--space-xs);
  flex-wrap: wrap;
  margin: 0;
}
.panel-head .row {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex-wrap: wrap;
  justify-content: flex-end;
  margin: 0;
}
.off-note {
  font-weight: 700;
  color: var(--ink-soft);
}
.kid .tag {
  margin-left: var(--space-xs);
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--cream-edge);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
}
.rule-today .btn + .btn {
  margin-left: var(--space-xs);
}
/* The minutes left as a picture: a ring in the kid's colour that empties, the avatar in it, the
   number big. For a six-year-old the ring is the message; the sentence next to it is for the rest. */
.hello.with-time {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  flex-wrap: wrap;
}
.time-visual {
  --p: 1;
  display: flex;
  align-items: center;
  gap: var(--space-md);
}
.tv-ring {
  width: 112px;
  height: 112px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: conic-gradient(var(--sun) calc(var(--p) * 100%), var(--cream-edge) 0);
  border: 3px solid var(--ink);
  box-shadow: var(--shadow);
}
.tv-ring .avatar {
  width: 76px;
  height: 76px;
}
.time-visual.low .tv-ring {
  background: conic-gradient(var(--amber) calc(var(--p) * 100%), var(--cream-edge) 0);
}
.time-visual.out .tv-ring {
  background: var(--cream-edge);
}
.tv-num {
  display: flex;
  flex-direction: column;
  line-height: 1;
  font-family: var(--font-display);
}
.tv-num strong {
  font-size: clamp(2.6rem, 7vw, 3.6rem);
  font-weight: 900;
  letter-spacing: -0.03em;
}
.tv-num span {
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink-faint);
  margin-top: 4px;
}
.cats {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 var(--space-lg);
}
.cats button {
  appearance: none;
  min-height: 40px;
  padding: 6px 16px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 15px;
  cursor: pointer;
}
.cats button.on {
  background: var(--ink);
  color: var(--cream);
}
/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 10px 22px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--sun);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 17px;
  text-decoration: none;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: transform 0.15s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.15s;
}
.btn:hover {
  transform: translateY(-1px);
}
.btn:active {
  transform: translateY(1px) scale(0.98);
  box-shadow: none;
}
.btn[disabled] {
  opacity: 0.45;
  cursor: default;
  transform: none;
}
.btn.big {
  min-height: 56px;
  font-size: 19px;
  padding-inline: 28px;
}
.btn.small {
  min-height: 38px;
  font-size: 14px;
  padding: 6px 14px;
}
.btn.ghost {
  background: var(--cream);
  box-shadow: none;
}
.btn.danger {
  color: oklch(50% 0.17 25);
  border-color: currentColor;
}
.btn .glyph {
  width: 18px;
  height: 18px;
}
.row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-md);
  align-items: center;
  margin-top: var(--space-lg);
}
.row.end {
  justify-content: flex-end;
}
/* ---------------------------------------------------------------- launch bar + why */
.launch {
  margin: 0 0 var(--space-xl);
  background: var(--ink);
  color: var(--cream);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.launch-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-md) var(--space-lg);
  flex-wrap: wrap;
}
.launch-bar p {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.05rem, 2.2vw, 1.3rem);
  letter-spacing: -0.01em;
}
.launch-actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}
.launch-x {
  appearance: none;
  width: 36px;
  height: 36px;
  border: 2px solid oklch(60% 0.03 248);
  border-radius: 50%;
  background: none;
  color: var(--cream);
  cursor: pointer;
  display: grid;
  place-items: center;
}
.launch-x .glyph {
  width: 18px;
  height: 18px;
}
.launch-body {
  padding: 0 var(--space-lg) var(--space-lg);
  border-top: 2px solid oklch(44% 0.035 248);
}
.launch-more {
  margin: var(--space-md) 0 0;
}
.launch-more a:not(.btn),
.why-grid a {
  color: var(--sun);
}
.why-grid {
  display: grid;
  gap: var(--space-lg) var(--space-xl);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  padding-top: var(--space-lg);
}
.why-grid .n {
  display: block;
  font-family: var(--font-display);
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  color: var(--sun);
  margin-bottom: 6px;
}
.why-grid h3 {
  font-size: 1.2rem;
  margin-bottom: var(--space-sm);
}
.why-grid p {
  margin: 0;
  font-size: 0.97rem;
  line-height: 1.5;
  color: oklch(88% 0.02 240);
}
.panel.why h1 {
  max-width: 22ch;
}
.panel.why .why-grid {
  background: var(--ink);
  color: var(--cream);
  border-radius: var(--radius-lg);
  padding: var(--space-xl);
  margin-top: var(--space-lg);
}
/* ---------------------------------------------------------------- home */
.hello {
  padding-block: var(--space-md) var(--space-xl);
}
/* The band: a bright field behind the top bar and the greeting, stamped with the studio's shapes,
   the way mailbook paints its band; the tiles start over its lower edge. Not on the play screen. */
:root {
  --band-h: 300px;
  --band: #2fc95f;
}
@supports (color: oklch(0.7 0.2 140)) {
  :root {
    --band: oklch(0.73 0.27 142.93);
  }
}
@media (max-width: 640px) {
  :root {
    --band-h: 232px;
  }
}
body {
  /* Logged out on a phone the launch card stands between the top bar and the greeting, so the band
     stopped under it with the heading, the chips and the tiles all left on the cream below. It
     reaches past the top of the first row here instead, which is the crossing a wide screen gets. */
}
body:not(.playing) {
  position: relative;
}
body:not(.playing)::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 172px;
  /* behind the top bar, and the content holder's top edge sits over it */
  --band-fill: var(--sun);
  background-color: var(--band-fill);
  background-image: url('/artwork/stamps-big.svg');
  background-size: 1600px 1600px;
  background-position: var(--stamp-x, -300px) var(--stamp-y, -200px);
  /* App sets a random crop per load */
  z-index: -1;
}
body.band-green::before {
  background-color: var(--band);
  background-image: url('/artwork/stamps.svg');
  background-size: 260px 260px;
}
body[data-route='home']::before,
body[data-route='who']::before {
  height: calc(var(--band-h) + 64px);
  /* the first row of tiles starts on the band and crosses its edge */
}
@media (max-width: 600px) {
  body[data-route='home']:has(.launch)::before {
    height: calc(var(--band-h) + 384px);
  }
}
.hello h1 {
  font-size: clamp(2.2rem, 6.5vw, 3.6rem);
}
.hello p {
  margin: var(--space-sm) 0 0;
  color: var(--ink-soft);
  font-size: clamp(1.05rem, 2vw, 1.25rem);
  max-width: 52ch;
}
.grid {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
}
.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  cursor: pointer;
  color: var(--ink);
  background: var(--cream-deep);
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
  box-shadow: var(--shadow-lg);
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.2s;
}
.tile:hover,
.tile:focus-visible {
  transform: translateY(-4px);
}
.tile.coral {
  background: oklch(93% 0.05 18);
}
.tile.mint {
  background: oklch(94% 0.05 178);
}
.tile.blue {
  background: oklch(93% 0.04 260);
}
.tile figure {
  position: relative;
  margin: 0 0 var(--space-md);
  aspect-ratio: 1;
  background: var(--cream);
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  overflow: hidden;
  isolation: isolate;
}
.tile img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.tile video.preview {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  z-index: 1;
  transition: opacity 0.18s;
  pointer-events: none;
}
.tile video.preview.on {
  opacity: 1;
  transition: opacity 0.5s ease;
}
.tile video.preview.front {
  z-index: 2;
}
.tile h3 {
  font-size: 1.55rem;
}
.tile h3 a {
  text-decoration: none;
  color: inherit;
}
.tile h3 a:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
  border-radius: 4px;
}
.tile p {
  margin: 6px 0 var(--space-md);
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.45;
}
.ctrls {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  align-items: flex-end;
}
.tile .ctrls {
  margin: -4px 0 var(--space-md);
}
.ctrls .bind {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}
.ctrls .keys {
  display: inline-flex;
  gap: 3px;
  align-items: center;
}
.ctrls .does {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.78rem;
  color: var(--ink-faint);
  text-transform: lowercase;
}
.ctrls.big .kc {
  transform: scale(1.35);
  transform-origin: bottom center;
  margin: 0 6px;
}
.ctrls.big .gs {
  width: 64px;
  height: 64px;
}
.ctrls.big .does {
  font-size: 0.95rem;
  margin-top: 8px;
}
.tile .tags .plays {
  background: var(--sun);
}
.loader .ctrls {
  justify-content: center;
  gap: 10px 32px;
  margin-top: var(--space-sm);
}
.tile .tags .by {
  background: var(--sun);
  text-decoration: none;
  color: var(--ink);
}
.tile .tags .by:hover {
  background: var(--amber);
}
.play-btn {
  position: absolute;
  right: var(--space-md);
  top: var(--space-md);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 8px 14px 8px 10px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--sun);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 15px;
  box-shadow: var(--shadow);
}
.play-btn .glyph {
  width: 18px;
  height: 18px;
}
.for-parents {
  margin-top: var(--space-2xl);
  padding: var(--space-xl);
  background: var(--ink);
  color: var(--cream);
  border-radius: var(--radius-lg);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-lg);
  align-items: center;
  justify-content: space-between;
}
.for-parents h2 {
  font-size: 1.6rem;
  margin-bottom: var(--space-sm);
}
.for-parents p {
  margin: 0;
  max-width: 52ch;
  color: oklch(88% 0.02 240);
}
/* ---------------------------------------------------------------- who's playing */
.who {
  text-align: center;
  padding-block: var(--space-xl);
}
.who h1 {
  font-size: clamp(2.2rem, 6.5vw, 3.6rem);
  margin-bottom: var(--space-xl);
}
.who-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-lg);
  margin-bottom: var(--space-xl);
}
.who-tile {
  appearance: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  width: 168px;
  padding: var(--space-lg) var(--space-md);
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  background: var(--cream-deep);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.3rem;
  cursor: pointer;
  box-shadow: var(--shadow-lg);
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.who-tile:hover,
.who-tile:focus-visible {
  transform: translateY(-4px) scale(1.02);
}
/* ---------------------------------------------------------------- panels (parents) */
/* The content holder is a card that sits over the band's lower edge (mailbook's modal does the
   same over its band): cream, ink border, a soft shadow. */
.panel {
  position: relative;
  margin-top: var(--space-sm);
  padding: var(--space-lg) var(--space-xl) var(--space-xl);
  background: var(--cream);
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
@media (max-width: 640px) {
  .panel {
    padding: var(--space-md) var(--space-md) var(--space-lg);
  }
}
.panel-legacy-padding {
  padding-block: var(--space-md) var(--space-xl);
}
.panel.narrow {
  max-width: 440px;
  margin-inline: auto;
}
.panel h1 {
  font-size: clamp(1.9rem, 5vw, 2.8rem);
  margin-bottom: var(--space-sm);
}
.panel .lead {
  color: var(--ink-soft);
  max-width: 60ch;
  margin: 0 0 var(--space-lg);
}
.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
}
.ticks {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-lg);
  display: grid;
  gap: var(--space-sm);
}
.ticks li {
  display: flex;
  align-items: center;
  gap: 10px;
}
.ticks .glyph {
  color: oklch(55% 0.14 160);
  flex: none;
}
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: var(--space-md) 0 var(--space-lg);
  border-bottom: 2px solid var(--cream-edge);
  padding-bottom: var(--space-sm);
}
.tabs a {
  padding: 8px 14px;
  border-radius: 999px;
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--ink-soft);
}
.tabs a.on {
  background: var(--ink);
  color: var(--cream);
}
.form {
  display: grid;
  gap: var(--space-md);
}
.form label {
  display: grid;
  gap: 6px;
  font-weight: 600;
  font-size: 0.95rem;
}
.form input,
.form select,
.rule select {
  font: inherit;
  font-size: 17px;
  padding: 11px 14px;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--cream);
  color: var(--ink);
  min-height: 48px;
}
.form input:focus-visible,
.form select:focus-visible,
.rule select:focus-visible {
  outline: 3px solid var(--sun);
  outline-offset: 2px;
}
.err {
  color: oklch(50% 0.17 25);
  font-weight: 600;
  margin: 0;
}
.kid-list {
  display: grid;
  gap: var(--space-sm);
  margin-bottom: var(--space-lg);
}
.kid {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--cream-deep);
}
.kid-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.2rem;
  flex: 1;
}
.kid-actions {
  display: flex;
  gap: 6px;
}
.kid-form {
  padding: var(--space-lg);
  border: 2px dashed var(--cream-edge);
  border-radius: var(--radius-lg);
}
.kid-preview {
  justify-self: center;
}
.pick {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.pick button {
  appearance: none;
  border: 2px solid transparent;
  background: none;
  padding: 2px;
  border-radius: 999px;
  cursor: pointer;
  line-height: 0;
}
.pick button[aria-checked='true'] {
  border-color: var(--ink);
  background: var(--cream-deep);
}
.pick.kind button {
  padding: 8px 16px;
  line-height: 1.1;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--ink);
  border-color: var(--cream-edge);
  background: var(--cream);
}
.pick.kind button[aria-checked='true'] {
  border-color: var(--ink);
  background: var(--cream-deep);
}
.kid-form .hint {
  margin: -6px 0 0;
  font-size: 0.9rem;
}
.pick.colors button {
  width: 40px;
  height: 40px;
  background: var(--c);
  border: 3px solid var(--cream);
  box-shadow: 0 0 0 2px var(--cream-edge);
}
.pick.colors button[aria-checked='true'] {
  box-shadow: 0 0 0 3px var(--ink);
}
.rule,
.screen {
  display: grid;
  gap: var(--space-md);
  padding: var(--space-md);
  margin-bottom: var(--space-md);
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  background: var(--cream-deep);
}
.rule {
  grid-template-columns: 1fr;
}
@media (min-width: 640px) {
  .rule {
    grid-template-columns: 1.2fr 1fr 1fr;
    align-items: start;
  }
  .rule .rule-today {
    grid-column: 1 / -1;
  }
}
.rule > label {
  display: grid;
  gap: 6px;
  font-weight: 600;
  font-size: 0.9rem;
}
.seg-row {
  display: flex;
  justify-content: flex-start;
  margin-bottom: var(--space-md);
}
.rule-who .stack {
  display: inline-flex;
}
.rule-who .stack .svg + .svg {
  margin-left: -14px;
}
.today-rows {
  display: grid;
  gap: var(--space-sm);
  margin-top: var(--space-md);
}
.today-rows .rule-today {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: var(--space-sm) var(--space-md);
  border: 2px solid var(--cream-edge);
  border-radius: var(--radius);
}
.today-rows .rule-today strong {
  font-family: var(--font-display);
}
.today-rows .rule-today .muted {
  flex: 1;
}
.rule-who {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  font-family: var(--font-display);
  font-size: 1.15rem;
  flex-wrap: wrap;
}
.rule-who .muted {
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 500;
}
.rule .win {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  font-size: 0.92rem;
}
.rule .win .win-label {
  font-weight: 700;
  min-width: 7.5em;
}
.rule .win select {
  min-height: 40px;
  padding: 6px 10px;
  font-size: 15px;
}
.rule.free {
  grid-template-columns: 1fr;
  background: var(--cream);
}
.rule.free p {
  margin: 4px 0 0;
  font-size: 0.92rem;
}
.rule.free input[type='date'] {
  font: inherit;
  padding: 6px 10px;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--cream);
}
.rule-today {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  font-size: 0.92rem;
}
.checks {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}
.check {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 6px 8px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--cream);
  font-weight: 600;
  cursor: pointer;
}
.check.setting {
  margin-bottom: var(--space-md);
}
.check img {
  border-radius: 50%;
  border: 2px solid var(--ink);
}
.check input {
  width: 22px;
  height: 22px;
  accent-color: var(--ink);
}
.bars {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
  height: 140px;
  align-items: end;
}
.bar-col {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  display: grid;
  grid-template-rows: auto 1fr auto;
  height: 100%;
  text-align: center;
  font-size: 0.78rem;
  color: var(--ink-faint);
}
.bar-v {
  font-weight: 700;
  color: var(--ink-soft);
}
.bar-fill {
  align-self: end;
  height: var(--h);
  min-height: 3px;
  background: var(--ink-soft);
  border-radius: 6px 6px 3px 3px;
}
.bar-col.today .bar-fill {
  background: var(--sun);
  border: 2px solid var(--ink);
}
.bar-col.on .bar-l {
  color: var(--ink);
  font-weight: 800;
}
.bar-col.on .bar-fill {
  outline: 3px solid var(--ink);
  outline-offset: 1px;
}
.sessions {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-md);
  display: grid;
  gap: 2px;
}
.sessions li {
  display: grid;
  grid-template-columns: 4.5em 1fr auto auto;
  gap: 4px 12px;
  padding: 6px 0;
  border-top: 1px solid var(--cream-edge);
  font-size: 0.95rem;
  align-items: baseline;
}
.sessions .when {
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
}
.sessions .note {
  grid-column: 2 / -1;
  font-size: 0.85rem;
  color: var(--ink-faint);
}
.screen h4 {
  font-size: 1rem;
  margin: var(--space-md) 0 var(--space-xs);
}
.device-names {
  grid-template-columns: 1fr;
}
.device-names input {
  font: inherit;
  font-size: 17px;
  padding: 11px 14px;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--cream);
  max-width: 280px;
}
.bygame {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 4px;
}
.bygame li {
  display: flex;
  justify-content: space-between;
  padding: 6px 0;
  border-top: 1px solid var(--cream-edge);
  font-size: 0.95rem;
}
.scan {
  display: grid;
  justify-items: start;
  gap: var(--space-sm);
  margin: var(--space-lg) 0;
}
.scan .qr {
  display: block;
}
.code {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.8rem, 6vw, 2.8rem);
  letter-spacing: 0.02em;
  padding: var(--space-md) var(--space-lg);
  border: 3px dashed var(--ink);
  border-radius: var(--radius-lg);
  background: var(--sun);
  display: inline-block;
  user-select: all;
}
/* ---------------------------------------------------------------- pin pad */
.pinpad {
  text-align: center;
  outline: none;
}
.pin-title {
  font-size: 1.7rem;
}
.pin-hint {
  color: var(--ink-soft);
  min-height: 1.5em;
  margin: 6px 0 var(--space-md);
}
.pin-dots {
  display: flex;
  justify-content: center;
  gap: 14px;
  margin-bottom: var(--space-lg);
}
.pin-dots span {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  background: var(--cream);
  transition: background 0.12s;
}
.pin-dots span.on {
  background: var(--ink);
}
.pin-keys {
  display: grid;
  grid-template-columns: repeat(3, 76px);
  gap: 10px;
  justify-content: center;
}
.pin-keys button {
  appearance: none;
  height: 64px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--cream-deep);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 26px;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: transform 0.1s;
}
.pin-keys button:active {
  transform: scale(0.94);
  box-shadow: none;
}
.pin-keys .pin-cancel,
.pin-keys .pin-del {
  background: none;
  border-color: transparent;
  box-shadow: none;
  font-size: 15px;
  color: var(--ink-soft);
}
.pin-keys .pin-del .glyph {
  width: 26px;
  height: 26px;
}
.pinpad.shake {
  animation: shake 0.4s;
}
@keyframes shake {
  20%,
  60% {
    transform: translateX(-8px);
  }
  40%,
  80% {
    transform: translateX(8px);
  }
}
/* ---------------------------------------------------------------- modal + toast */
.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: var(--space-lg);
  background: oklch(34% 0.038 248 / 0.5);
}
.card {
  width: min(460px, 100%);
  background: var(--cream);
  border: 3px solid var(--ink);
  border-radius: var(--radius-lg);
  padding: var(--space-xl) var(--space-lg);
  box-shadow: var(--shadow-lg);
  text-align: center;
}
.card h2 {
  font-size: 1.6rem;
}
.card p {
  color: var(--ink-soft);
  margin: var(--space-sm) 0 0;
}
.card .row {
  justify-content: center;
}
#toast {
  position: fixed;
  left: 50%;
  bottom: max(24px, env(safe-area-inset-bottom));
  transform: translate(-50%, 20px);
  z-index: 120;
  padding: 12px 20px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--sun);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 16px;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s, transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}
#toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}
/* ---------------------------------------------------------------- play screen */
body.playing {
  overflow: hidden;
}
#stage {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--ink);
}
.play {
  display: flex;
  flex-direction: column;
  height: 100%;
  height: 100dvh;
  background: var(--ink);
}
.bar {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  height: 44px;
  padding: 0 8px;
  padding-top: env(safe-area-inset-top);
  box-sizing: content-box;
  background: var(--cream);
  border-bottom: 2px solid var(--ink);
  color: var(--ink);
}
.bar-btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 36px;
  padding: 0 10px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--cream-deep);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 15px;
  cursor: pointer;
}
.bar-btn .glyph {
  width: 20px;
  height: 20px;
}
.bar-title {
  flex: 1;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 16px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bar-time {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 12px 0 6px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--cream-deep);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 14px;
  white-space: nowrap;
}
.bar-time .ring {
  --p: 1;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  background: conic-gradient(var(--sun) calc(var(--p) * 100%), var(--cream) 0);
}
.bar-time:not(.limited) .ring {
  background: var(--sun);
}
.bar-time.low {
  background: var(--amber);
}
.bar-time .ring.pulse {
  animation: ring-pulse 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes ring-pulse {
  50% {
    transform: scale(1.15);
  }
}
/* while a game is open the warnings sit under the play bar, never over the game's bottom HUD */
body.playing #toast {
  top: calc(44px + env(safe-area-inset-top) + 12px);
  bottom: auto;
  transform: translate(-50%, -20px);
}
body.playing #toast.show {
  transform: translate(-50%, 0);
}
.frame {
  position: relative;
  flex: 1;
  min-height: 0;
  background: var(--ink);
}
.game-frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--ink);
}
.loader {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  background: var(--cream);
  color: var(--ink-soft);
  font-family: var(--font-display);
  font-weight: 700;
  transition: opacity 0.4s;
}
.loader.hide {
  opacity: 0;
  pointer-events: none;
}
.loader .bob {
  animation: bob 1.1s ease-in-out infinite;
}
@keyframes bob {
  50% {
    transform: translateY(-8px);
  }
}
.overlay {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: grid;
  place-items: center;
  padding: var(--space-lg);
  background: oklch(34% 0.038 248 / 0.72);
  overflow: auto;
}
.overlay .card.timeup h2 {
  margin-top: var(--space-sm);
  font-size: clamp(1.6rem, 5vw, 2.2rem);
}
.overlay .card.pin {
  padding: var(--space-lg) var(--space-md);
}
@media (max-width: 480px) {
  .bar-btn.back span,
  .bar-title {
    display: none;
  }
  .bar-time {
    margin-left: auto;
  }
  .tile h3 {
    font-size: 1.35rem;
  }
  .pin-keys {
    grid-template-columns: repeat(3, 68px);
  }
}
@media (prefers-reduced-motion: reduce) {
  .tile,
  .who-tile,
  .btn,
  .loader .bob,
  .pinpad.shake {
    transition: none;
    animation: none;
  }
}
.chip.time .nudge,
.bar-time .nudge {
  display: none;
  width: 18px;
  height: 18px;
}
.chip.time.low .nudge,
.bar-time.low .nudge {
  display: inline-flex;
  animation: wrap-nudge 1.2s ease-in-out infinite;
}
.chip.time .nudge svg,
.bar-time .nudge svg {
  width: 18px;
  height: 18px;
}
.tv-wrap {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 3px solid var(--ink);
  background: var(--amber);
  box-shadow: var(--shadow);
  animation: wrap-nudge 1.2s ease-in-out infinite;
}
.tv-wrap svg {
  width: 26px;
  height: 26px;
}
@keyframes wrap-nudge {
  0%,
  100% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(4px);
  }
}
@media (prefers-reduced-motion: reduce) {
  .chip.time.low .nudge,
  .bar-time.low .nudge,
  .tv-wrap {
    animation: none;
  }
}
.chip.time:has(> .ring:only-child) {
  padding: 5px;
  border-radius: 50%;
  gap: 0;
}
/* ---------------------------------------------------------------- brand, ux, ui (docs/specs/brand-ux-ui.md) */
/* 1. Jip in the wordmark: his pupils move (jipeyes.js), the mood changes with the day */
.wordmark .pupil {
  transition: transform 0.15s ease-out;
}
/* 2. a kid's tile: art, name, this device's controls; the rest is in the sheet */
.tile.kid .tile-body {
  padding-bottom: var(--space-sm);
}
.tile.kid h3 {
  margin-bottom: 4px;
}
.tile.kid .plays {
  display: inline-block;
  margin-top: 2px;
  font-size: 0.85rem;
  color: var(--ink-faint);
}
.card.sheet {
  text-align: center;
  max-width: 420px;
}
.card.sheet img {
  display: block;
  width: 120px;
  height: 120px;
  margin: 0 auto var(--space-sm);
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  object-fit: cover;
}
.card.sheet p {
  color: var(--ink-soft);
  margin: 6px 0;
}
.card.sheet .sheet-ctrls {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 28px;
  margin: var(--space-md) 0 var(--space-sm);
}
.card.sheet .row {
  justify-content: center;
}
.card.sheet .btn .glyph {
  width: 18px;
  height: 18px;
}
/* 3. the Who screen: tiles in the kid's colour, a bigger animal, a wobble, a ghost tile to add one */
.who-line {
  margin: -8px 0 var(--space-lg);
  color: var(--ink-faint);
  font-weight: 600;
}
.who-tile {
  --c: var(--sun);
  width: 200px;
  background: color-mix(in oklab, var(--c) 18%, var(--cream));
}
.who-tile .avatar {
  width: 160px;
  height: 160px;
}
.who-tile:hover,
.who-tile:focus-visible {
  animation: wobble 0.35s ease-in-out;
}
.who-tile.add {
  background: transparent;
  border-style: dashed;
  border-color: var(--cream-edge);
  color: var(--ink-faint);
  box-shadow: none;
  font-size: 1rem;
  justify-content: center;
  text-decoration: none;
}
.who-tile.add .glyph {
  width: 56px;
  height: 56px;
}
.who-tile.add:hover,
.who-tile.add:focus-visible {
  border-color: var(--ink);
  color: var(--ink);
  animation: none;
}
@keyframes wobble {
  0%,
  100% {
    rotate: 0deg;
  }
  30% {
    rotate: 2deg;
  }
  70% {
    rotate: -2deg;
  }
}
/* 4. category chips carry a picture; under 480px the picture is the chip */
.cats button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.cats button .glyph {
  width: 18px;
  height: 18px;
}
/* On a phone the chips wrapped, and six of them came out as five and then a lonely sixth on a line
   of its own, which reads as a mistake rather than a row. One row that scrolls sideways instead,
   bled out to the edges of the SCREEN rather than the edges of the column, so the chip at the rim
   is cut by the glass and says there is more without needing an arrow to say it. The swipe is kept
   inside the strip so it cannot turn into the browser's back gesture. */
@media (max-width: 640px) {
  .cats {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    margin-inline: calc(-1 * var(--space-lg));
    padding-inline: var(--space-lg);
    scrollbar-width: none;
  }
  .cats::-webkit-scrollbar {
    display: none;
  }
  .cats button {
    flex: none;
    scroll-snap-align: start;
  }
}
@media (max-width: 480px) {
  .cats button .name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }
  .cats button .glyph {
    width: 22px;
    height: 22px;
  }
}
/* 5. minutes as segmented buttons, not a select */
.seg {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  vertical-align: middle;
}
.seg button {
  appearance: none;
  min-height: 34px;
  padding: 4px 12px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--cream);
  color: var(--ink);
  font: inherit;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
}
.seg button.on {
  background: var(--ink);
  color: var(--cream);
}
.rule label:has(.seg) {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}
/* 7. empty states with Jip, the crew on the pages without JavaScript */
.empty {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-xl) 0;
  text-align: center;
}
.legal .crew {
  display: block;
  width: min(100%, 560px);
  height: auto;
  margin: 0 0 var(--space-lg);
}
/* 8. the launch bar on phones is one line with a link (Home.jsx folds the panel) */
@media (max-width: 600px) {
  /* Even on all four sides: the wide-screen bar is one line, so its 16/24 reads as a bar, while
     the folded card is a block of text with a button under it and 8px top and bottom pinched it. */
  .launch-bar {
    padding: var(--space-md);
  }
  .launch-body {
    display: none;
  }
}
/* 9. every interactive thing shows its focus */
.btn:focus-visible,
.chip:focus-visible,
.parents-link:focus-visible,
.cats button:focus-visible,
.seg button:focus-visible,
.pinpad button:focus-visible,
.tabs a:focus-visible,
.who-tile:focus-visible,
.foot select.lang:focus-visible,
.check input:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 2px;
}
/* 10. the kid line on the loader */
.loader .kid-line {
  margin: -4px 0 var(--space-sm);
  color: var(--ink-faint);
  font-weight: 600;
}
/* ---------------------------------------------------------------- the grid is art, the game's page has the words */
.grid {
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--space-md);
}
@media (min-width: 900px) {
  .grid {
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  }
}
@media (min-width: 360px) {
  .grid .tile.big {
    grid-column: span 2;
    grid-row: span 2;
  }
  .grid .tile.big .name {
    font-size: 1.25rem;
    padding: 14px 16px;
  }
}
@media (min-width: 360px) and (max-width: 599px) {
  .grid .tile.big {
    grid-column: 1 / span 2;
    grid-row: 2 / span 2;
  }
}
a.tile {
  display: block;
  padding: 0;
  overflow: hidden;
  /* the art is the tile: clipped by the tile's own rounded corners */
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}
a.tile figure {
  margin: 0;
  border: 0;
  border-radius: 0;
}
a.tile .name {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 10px 12px;
  background: linear-gradient(transparent, oklch(34% 0.038 248 / 0.75));
  color: var(--cream);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1rem;
  opacity: 0;
  transition: opacity 0.2s;
}
a.tile:hover .name,
a.tile:focus-visible .name {
  opacity: 1;
}
a.tile .plays {
  position: absolute;
  bottom: 10px;
  right: 10px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--cream);
  border: 2px solid var(--ink);
  font-size: 0.75rem;
  font-weight: 700;
  transition: opacity 0.2s;
}
a.tile:hover .plays,
a.tile:focus-visible .plays {
  opacity: 0;
}
a.tile .play-btn {
  bottom: auto;
  top: 8px;
  right: 8px;
}
.play-page h1 {
  margin: var(--space-md) 0 4px;
}
.play-area {
  position: relative;
  aspect-ratio: 16 / 9;
  max-height: 70vh;
  display: grid;
  place-items: center;
  border: 3px solid var(--ink);
  border-radius: var(--radius-lg);
  background: var(--ink) var(--art) center / cover no-repeat;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  /* A phone holds a game upright, and 16/9 left the holder a 192px letterbox with the cover art
     cropped to a strip and the Play button sitting in it like a caption. */
}
@media (max-width: 640px) {
  .play-area {
    aspect-ratio: 3 / 4;
    max-height: 62vh;
  }
}
.play-area::before {
  content: '';
  position: absolute;
  inset: 0;
  background: oklch(34% 0.038 248 / 0.35);
}
.play-big {
  position: relative;
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 76px;
  padding: 0 40px 0 32px;
  border: 3px solid var(--ink);
  border-radius: 999px;
  background: var(--sun);
  color: var(--ink);
  font: inherit;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 28px;
  cursor: pointer;
  box-shadow: var(--shadow-lg);
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.play-big .glyph {
  width: 34px;
  height: 34px;
}
.play-big:hover,
.play-big:focus-visible {
  transform: scale(1.05);
}
.play-area .card.switch {
  position: relative;
  text-align: center;
  max-width: 460px;
  margin: var(--space-md);
}
.switch-games {
  display: flex;
  justify-content: center;
  gap: var(--space-md);
  margin-top: var(--space-md);
}
.switch-game {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-decoration: none;
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 800;
}
.switch-game img {
  width: 96px;
  height: 96px;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  object-fit: cover;
}
.game-info .blurb {
  font-size: 1.1rem;
  color: var(--ink-soft);
  max-width: 62ch;
}
.game-info h2 {
  font-size: 1.1rem;
  margin: var(--space-lg) 0 var(--space-sm);
}
.game-info .tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: var(--space-sm);
}
.game-info .tags span,
.game-info .tags .by {
  padding: 3px 10px;
  border-radius: 999px;
  border: 2px solid var(--cream-edge);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--ink-soft);
  text-decoration: none;
}
.game-ctrls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md) var(--space-xl);
  margin-top: var(--space-md);
}
.game-ctrls .other {
  opacity: 0.45;
}
.play-page h2.more {
  margin: var(--space-xl) 0 var(--space-md);
}
/* One question under a game: what should it get next. Before the tap it is three big targets, after
   it three bars, because a kid who votes wants to see where the votes went. The bar is a background
   layer under the words rather than a sibling, so a long answer wrapping to two lines cannot push
   its own percentage out of line. */
.poll {
  margin-top: var(--space-xl);
  /* what the votes already turned into: a datapoint, not a headline */
}
.poll h2 {
  font-size: 1.1rem;
  margin-bottom: var(--space-md);
}
.poll ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
  max-width: 62ch;
}
.poll .poll-answers button {
  width: 100%;
  min-height: 52px;
  padding: 10px 16px;
  text-align: left;
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  background: var(--cream);
  border: 2px solid var(--cream-edge);
  border-radius: var(--radius);
  cursor: pointer;
}
.poll .poll-answers button:hover:not(:disabled) {
  border-color: var(--sun);
}
.poll .poll-answers button:disabled {
  cursor: default;
}
.poll .poll-result li {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 52px;
  padding: 10px 16px;
  border: 2px solid var(--cream-edge);
  border-radius: var(--radius);
  overflow: hidden;
  /* the one this kid picked, so the answer stays theirs among the others */
}
.poll .poll-result li .bar {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--pct);
  background: var(--cream-edge);
  opacity: 0.55;
}
.poll .poll-result li .what,
.poll .poll-result li .pct {
  position: relative;
}
.poll .poll-result li .what {
  flex: 1;
}
.poll .poll-result li .pct {
  font-weight: 700;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.poll .poll-result li.mine {
  border-color: var(--sun);
}
.poll .poll-result li.mine .bar {
  background: var(--sun);
}
.poll .poll-result li.mine .what {
  font-weight: 700;
}
.poll .poll-thanks {
  margin-top: var(--space-sm);
  color: var(--ink-soft);
}
.poll .poll-shipped {
  margin-top: var(--space-md);
}
.poll .poll-shipped li {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--ink-soft);
  font-size: 0.95rem;
}
.poll .poll-shipped .tick {
  width: 16px;
  height: 16px;
  flex: none;
  border-radius: 50%;
  background: var(--mint);
}
/* the kid's chip carries the day's ring around their animal; the pill next to it only carries words */
.chip.kid,
.chip.time {
  min-height: 44px;
  padding-top: 3px;
  padding-bottom: 3px;
}
.chip.kid {
  padding-left: 4px;
}
.chip.time .face svg {
  width: 24px;
  height: 24px;
}
.chip .day-ring {
  --p: 0;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: conic-gradient(var(--sun) calc(var(--p) * 100%), var(--cream-edge) 0);
}
.chip .day-ring .avatar {
  width: 26px;
  height: 26px;
}
.chip .day-ring.low {
  background: conic-gradient(var(--amber) calc(var(--p) * 100%), var(--cream-edge) 0);
}
.chip .day-ring.out {
  background: var(--cream-edge);
}
.chip .day-ring.none {
  border-color: transparent;
  background: transparent;
}
.chip.kid.low {
  background: var(--amber);
}
/* on a phone the header is pictures only: the animal in its ring, Jip's face or the arrow, the gear */
@media (max-width: 600px) {
  .top {
    gap: var(--space-sm);
    min-width: 0;
  }
  .top nav {
    gap: 6px;
    flex-shrink: 0;
  }
  .wordmark {
    min-width: 0;
  }
  .chip.kid > span:not(.day-ring) {
    display: none;
  }
  .chip.kid {
    padding-right: 4px;
  }
  .chip.time .t {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }
  .chip.time {
    padding-right: 8px;
  }
  .parents-link > span:not(.svg) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }
  .parents-link {
    padding: 4px 10px;
  }
}
/* ---------------------------------------------------------------- the developer dashboard: the funnel and the playtest */
.funnels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space-md) var(--space-xl);
  margin: var(--space-md) 0;
}
.funnel h4 {
  margin: 0 0 6px;
}
.frow {
  display: grid;
  grid-template-columns: 11em 1fr 5.5em;
  align-items: center;
  gap: 8px;
  font-size: 0.9rem;
  margin: 3px 0;
}
.frow .fb {
  height: 12px;
  border-radius: 999px;
  background: var(--cream-deep);
  border: 1px solid var(--cream-edge);
  overflow: hidden;
}
.frow .fbar {
  display: block;
  height: 100%;
  background: var(--sun);
}
.frow .fn {
  font-weight: 700;
  white-space: nowrap;
}
.playtest {
  margin: var(--space-sm) 0;
  padding: var(--space-sm) var(--space-md);
  border: 2px solid var(--cream-edge);
  border-radius: var(--radius);
  background: var(--cream);
}
.playtest.changes {
  border-color: var(--coral);
}
.playtest.ok {
  border-color: var(--mint);
}
.playtest summary {
  cursor: pointer;
  font-weight: 700;
}
.playtest .ptchecks {
  list-style: none;
  padding: 0;
  margin: var(--space-sm) 0;
  font-size: 0.9rem;
}
.playtest .ptcheck {
  display: grid;
  grid-template-columns: 3em 6em 1fr;
  gap: 8px;
  padding: 2px 0;
}
.playtest .ptcheck .k {
  font-family: var(--font-display);
  font-weight: 800;
}
.playtest .ptcheck.ok .k {
  color: oklch(50% 0.12 160);
}
.playtest .ptcheck.no .k {
  color: oklch(50% 0.17 25);
}
.playtest .ptcheck.note .k {
  color: var(--ink-faint);
}
.playtest .ptcheck .cid {
  color: var(--ink-faint);
}
.playtest .shots {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin: var(--space-sm) 0;
}
.playtest .shots a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-size: 0.75rem;
  color: var(--ink-faint);
  text-decoration: none;
}
.playtest .shots img {
  width: 56px;
  height: auto;
  border: 2px solid var(--ink);
  border-radius: 8px;
  background: var(--cream-deep);
}
.playtest .sound {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
  margin: var(--space-sm) 0;
  font-size: 0.85rem;
}
.playtest .sound audio {
  height: 36px;
  max-width: 100%;
}
.playtest .sound .spark {
  width: 160px;
  height: 24px;
  fill: var(--ink);
  background: var(--cream-deep);
  border-radius: 4px;
}
.playtest .claude {
  margin-top: var(--space-sm);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--cream-edge);
  font-size: 0.92rem;
}
.playtest .claude h4 {
  margin: 0 0 4px;
}
.playtest .claude .challenges {
  padding-left: 1.2em;
  margin: 6px 0;
}
.playtest .claude .note {
  padding: 8px 12px;
  border-left: 3px solid var(--sun);
  background: var(--cream-deep);
  border-radius: 0 8px 8px 0;
}
/* /why: where this goes, a vertical timeline. The rail runs behind the markers; the first step is
   where we are (a filled marker and a card with an ink edge), the rest are the targets ahead. */
.why .goals {
  margin: var(--space-lg) 0 var(--space-md);
}
.why .goals ol {
  list-style: none;
  margin: var(--space-md) 0 0;
  padding: 0 0 0 46px;
  position: relative;
}
.why .goals ol::before {
  content: '';
  position: absolute;
  left: 17px;
  top: 14px;
  bottom: 22px;
  width: 4px;
  border-radius: 2px;
  background: var(--cream-edge);
}
.why .goals li {
  position: relative;
  padding-bottom: var(--space-md);
}
.why .goals li:last-child {
  padding-bottom: 0;
}
.why .goals li .dot {
  position: absolute;
  left: -46px;
  top: 6px;
  width: 22px;
  height: 22px;
  margin-left: 4px;
  border-radius: 999px;
  border: 4px solid var(--ink);
  background: var(--cream);
}
.why .goals li.now .dot {
  background: var(--sun);
  box-shadow: 0 0 0 6px var(--cream);
}
.why .goals li .step {
  padding: var(--space-sm) var(--space-md);
  border: 2px solid var(--cream-edge);
  border-radius: var(--radius-lg);
  background: var(--cream);
}
.why .goals li.now .step {
  border-color: var(--ink);
  background: var(--cream-deep);
}
.why .goals li .metric {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 3px 10px;
  border-radius: 999px;
  border: 2px solid var(--ink);
  background: var(--cream);
  color: var(--ink);
}
.why .goals li.now .metric {
  background: var(--ink);
  color: var(--cream);
}
.why .goals h3 {
  margin: 8px 0 4px;
}
.why .goals p {
  margin: 0;
}
@media (max-width: 520px) {
  .why .goals ol {
    padding-left: 34px;
  }
  .why .goals ol::before {
    left: 11px;
  }
  .why .goals li .dot {
    left: -34px;
    top: 8px;
    width: 16px;
    height: 16px;
    border-width: 3px;
  }
}
/* Band variants for the review: sun (the brand's own yellow, chunky cream stamps with ink outlines),
   mint (the palette's soft green), none (cream, a faint texture). The class sits on body. */
body.band-sun::before,
body.band-mint::before,
body.band-none::before {
  background-image: url('/artwork/stamps-big.svg');
  background-size: 1600px 1600px;
}
body.band-sun::before {
  background-color: var(--sun);
  background-blend-mode: normal;
}
body.band-mint::before {
  background-color: var(--mint);
}
body.band-none::before {
  background-color: var(--cream);
}
body.band-sun::before,
body.band-mint::before {
  --stamp: 0.16;
}
body.band-none::before {
  --stamp: 0.08;
}
body.band-mint::before {
  --band-fill: var(--mint);
}
body.band-none::before {
  --band-fill: var(--cream);
}
body.band-none .hello p {
  color: var(--ink-soft);
}
body[data-route='home'] .hello p,
body[data-route='who'] .who .muted {
  color: var(--ink);
}
pre {
  background: var(--ink);
  color: var(--cream);
  padding: var(--space-md) var(--space-lg);
  border-radius: var(--radius);
  overflow-x: auto;
  font-size: 0.88rem;
  line-height: 1.5;
}
code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.92em;
}
.legal code {
  background: var(--cream-deep);
  padding: 1px 6px;
  border-radius: 6px;
}
.legal pre code {
  background: none;
  padding: 0;
  color: inherit;
}
.apply {
  margin-top: var(--space-xl);
  padding: var(--space-xl);
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  background: var(--cream-deep);
}
.apply .form label span {
  color: var(--ink-faint);
  font-weight: 500;
}
.apply textarea {
  font: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 14px;
  line-height: 1.5;
  padding: 11px 14px;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--cream);
  min-height: 320px;
}
.apply .check {
  border-radius: var(--radius);
  padding: 10px 14px;
  width: 100%;
  justify-content: flex-start;
}
.apply .hp {
  position: absolute;
  left: -9999px;
}
.legal code {
  background: var(--cream-deep);
  padding: 1px 6px;
  border-radius: 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.92em;
}
textarea {
  font: 14px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  padding: 11px 14px;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--cream);
  min-height: 260px;
}
input[type='file'] {
  font: inherit;
}
.sub {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-sm) var(--space-md);
  align-items: center;
  padding: var(--space-md);
  margin-bottom: var(--space-sm);
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--cream-deep);
}
.sub h3 {
  font-size: 1.15rem;
}
.sub .meta {
  color: var(--ink-faint);
  font-size: 0.9rem;
}
.status {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 999px;
  border: 2px solid var(--ink);
  background: var(--cream);
}
.status.live {
  background: var(--mint);
}
.status.submitted {
  background: var(--sun);
}
.status.changes {
  background: var(--amber);
}
.status.rejected,
.status.replaced {
  background: var(--cream-edge);
}
.sub {
  /* What changed, as the list it is: a paragraph of six changes is one nobody finishes. */
  /* The build's digest in the meta line: a number to compare, so it reads as one. */
}
.sub .reason {
  grid-column: 1 / -1;
  margin: 0;
  padding: var(--space-sm) var(--space-md);
  background: var(--cream);
  border-radius: var(--radius);
  font-size: 0.95rem;
}
.sub .changed {
  margin: 6px 0 0;
  padding-left: 1.2em;
}
.sub .changed li {
  margin: 2px 0;
}
.sub .build {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.92em;
}
.sub details {
  grid-column: 1 / -1;
}
.dev-tabs {
  margin: var(--space-md) 0 var(--space-lg);
}
.dev-tabs .count {
  display: inline-block;
  min-width: 1.4em;
  padding: 0 6px;
  margin-left: 4px;
  border-radius: 999px;
  background: var(--sun);
  color: var(--ink);
  font-size: 0.8rem;
  text-align: center;
}
.sub {
  /* What the players asked for, under the play stats. Sorted by votes, so the answer a developer
     came for is the first line; the bar is relative to the winner, not to the total, because the
     question is which one won and by how far. */
}
.sub .wants {
  grid-column: 1 / -1;
  padding: var(--space-sm) var(--space-md) var(--space-md);
  background: var(--cream);
  border-radius: var(--radius);
  font-size: 0.95rem;
}
.sub .wants h4 {
  margin: var(--space-sm) 0 6px;
  font-size: 0.95rem;
}
.sub .wants .muted {
  color: var(--ink-faint);
  font-weight: 400;
}
.sub .wants .votes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 4px;
}
.sub .wants .votes li {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-radius: 8px;
  overflow: hidden;
}
.sub .wants .votes .bar {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--cream-edge);
  opacity: 0.7;
}
.sub .wants .votes .what,
.sub .wants .votes .n {
  position: relative;
}
.sub .wants .votes .what {
  flex: 1;
}
.sub .wants .votes .n {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.sub .wants .votes li:first-child .bar {
  background: var(--sun);
}
.sub .stats {
  grid-column: 1 / -1;
  padding: var(--space-sm) var(--space-md) var(--space-md);
  background: var(--cream);
  border-radius: var(--radius);
  font-size: 0.95rem;
}
.sub .stats h4 {
  margin: var(--space-sm) 0 4px;
  font-size: 0.95rem;
}
.sub .stats .muted {
  margin: 4px 0 0;
  color: var(--ink-faint);
  font-size: 0.88rem;
}
.sub .stats .days,
.sub .stats .ends {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 4px;
  align-items: end;
}
.sub .stats .bar-col {
  height: 64px;
  display: flex;
  align-items: flex-end;
  border-bottom: 2px solid var(--cream-edge);
}
.sub .stats .bar {
  width: 100%;
  min-height: 2px;
  background: var(--sun);
  border: 2px solid var(--ink);
  border-bottom: 0;
  border-radius: 6px 6px 0 0;
}
.sub .stats .ends .bar {
  background: var(--mint);
}
.sub .stats .n {
  text-align: center;
  font-weight: 700;
  font-size: 0.8rem;
  min-height: 1.1em;
}
.sub .stats .l {
  text-align: center;
  color: var(--ink-faint);
  font-size: 0.72rem;
  line-height: 1.1;
}
.sub pre {
  white-space: pre-wrap;
  font-size: 0.85rem;
  background: var(--cream);
  padding: var(--space-md);
  border-radius: var(--radius);
  max-height: 320px;
  overflow: auto;
}
.review {
  grid-column: 1 / -1;
  display: grid;
  gap: var(--space-sm);
}
.review textarea {
  min-height: 80px;
}
.panel + .panel {
  border-top: 2px solid var(--cream-edge);
}
/* The one legal-shaped page that is not a column of prose: it has a card beside it, so it gets
   the width of the page rather than a reading measure. Not called `contact`: base.less already
   has a `.contact` (a dark dl card), and a page-level modifier by that name inherits its background
   and paints the whole page dark grey on dark grey. */
.legal.legal-wide {
  max-width: none;
}
/* ---------------------------------------------------------------- contact
   Prose on the left, the ways to reach a person on the right, the way the other Ymedia pages do
   it. The card is the answer for someone who came to find one thing, so it repeats what the prose
   says rather than adding to it: nobody should have to read a page to find an email address. */
.contact-page {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: var(--space-xl);
  align-items: start;
  margin-top: var(--space-lg);
}
.contact-page h2:first-child {
  margin-top: 0;
}
.contact-card {
  position: sticky;
  top: var(--space-lg);
  padding: var(--space-lg);
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  background: var(--cream-deep);
  box-shadow: var(--shadow);
}
.contact-card .contact-label {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.contact-card .contact-title {
  margin: 2px 0 var(--space-md);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.25rem;
}
.contact-rows {
  margin: 0;
}
.contact-rows > div {
  padding: 10px 0;
  border-top: 1px solid rgba(20, 26, 30, 0.14);
}
.contact-rows dt {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.contact-rows dd {
  margin: 3px 0 0;
  font-size: 0.95rem;
  line-height: 1.4;
}
@media (max-width: 760px) {
  .contact-page {
    grid-template-columns: minmax(0, 1fr);
  }
  .contact-card {
    position: static;
    order: -1;
    /* the address first on a phone: it is what the page is for */
  }
}

