/* Gochis teaser site. Colours, type and pixel art all come from the teaser video. */

@font-face {
  font-family: 'Gochi Mono';
  src: url('../fonts/dejavu-sans-mono.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Gochi Mono';
  src: url('../fonts/dejavu-sans-mono-bold.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}

:root {
  --ink: #110F1B;        /* page, as in the teaser */
  --ink-raised: #1A1727; /* inputs and the phone */
  --ink-line: #2C2741;   /* rules and borders on ink */
  --cream: #FEF8EF;      /* the pass, and main text */
  --outline: #211D33;    /* pixel outlines, text on the pass */
  --label: #8A8291;      /* small labels on the pass */
  --muted: #A9A3BA;      /* secondary text on ink */
  --mint: #97EAC3;       /* alive */
  --mint-edge: #3E9874;
  --gold: #FFD75E;       /* the pot */
  --blush: #FE8BA9;
  --peach: #FDC594;
  --lavender: #C2A9FD;
  --blue: #95CCFE;       /* Gochi #002 */
  --hungry: #E1E0E5;     /* the pass when hungry */
  --gone: #77777F;       /* the pass when gone */
  --shadow: #06040E;     /* hard drop shadow under the pass */
  --font: 'Gochi Mono', 'DejaVu Sans Mono', Menlo, Consolas, monospace;
  /* What text, rules and fields use in the current section: night by default, .tone-light swaps them. */
  --fg: var(--cream);
  --fg-soft: var(--muted);
  --line: var(--ink-line);
  --link: var(--gold);
  --focus: var(--gold);
  --field: var(--ink-raised);
  --field-text: var(--cream);
  --field-line: var(--ink-line);
  --field-focus: var(--mint);
  --error: var(--blush);
  --ok: var(--mint);
  --bar: 56px;
  --gutter: 16px;
  --step: 75vh;          /* scroll length of one story step */
  color-scheme: dark;
}
@supports (height: 1svh) {
  :root { --step: 75svh; }
}
@media (min-width: 760px) {
  :root { --bar: 64px; --gutter: 32px; --step: 90vh; }
}

*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--bar);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--cream);
  font: 400 16px/1.6 var(--font);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; }
button { font: inherit; color: inherit; }

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
}

/* Sections in a Gochi colour carry the teaser's ink. */
.tone-light {
  --fg: var(--outline);
  --fg-soft: rgb(33 29 51 / .8);
  --line: rgb(33 29 51 / .22);
  --link: var(--outline);
  --focus: var(--outline);
  --field: var(--cream);
  --field-text: var(--outline);
  --field-line: rgb(33 29 51 / .45);
  --field-focus: var(--outline);
  --error: #A3123A;
  --ok: var(--outline);
  color: var(--fg);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The hidden attribute wins over the display a class sets, as on .btn. */
[hidden] { display: none !important; }

.skip {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: 50;
  padding: 10px 14px;
  border-radius: 10px;
  background: var(--cream);
  color: var(--outline);
  font-weight: 700;
  text-decoration: none;
}
.skip:focus { top: 12px; }

/* Pixel art: every sprite is --w × --h cells of --cell each. */
.sprite,
.icon {
  display: block;
  width: calc(var(--w) * var(--cell, 4px));
  height: calc(var(--h) * var(--cell, 4px));
  flex: none;
}
.icon { --cell: 2px; }

/* Buttons press down like toy buttons. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 18px;
  border: 0;
  border-radius: 12px;
  font: 700 16px/1 var(--font);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: transform .06s, box-shadow .06s;
}
.btn-mint {
  background: var(--mint);
  color: var(--outline);
  box-shadow: 0 4px 0 var(--mint-edge);
}
.btn-mint:active {
  transform: translateY(3px);
  box-shadow: 0 1px 0 var(--mint-edge);
}
/* On a Gochi colour the mint button gets the teaser's ink outline. */
.tone-light .btn-mint { box-shadow: 0 0 0 2px var(--outline), 0 5px 0 2px var(--outline); }
.tone-light .btn-mint:active { box-shadow: 0 0 0 2px var(--outline), 0 2px 0 2px var(--outline); }
.btn-line {
  padding: 11px 16px;
  border: 2px solid #3A3550;
  background: none;
  color: var(--cream);
  font-size: 15px;
}
.btn-line .icon { color: var(--mint); }
.btn-line:hover { border-color: var(--mint); }

/* Top bar */
.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 10px;
  height: var(--bar);
  padding: 0 max(var(--gutter), env(safe-area-inset-right)) 0 max(var(--gutter), env(safe-area-inset-left));
  background: var(--ink);
  border-bottom: 2px solid transparent;
  transition: border-color .2s;
}
.topbar.is-scrolled { border-bottom-color: var(--ink-line); }

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-right: auto;
  text-decoration: none;
}
.brand-mark { --cell: 2px; }
.brand-word {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: .02em;
}

.nav { display: none; }

.sound-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 10px;
  border: 2px solid var(--ink-line);
  border-radius: 10px;
  background: none;
  color: var(--muted);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
.sound-toggle[aria-pressed="true"] {
  border-color: var(--mint);
  color: var(--mint);
}
.sound-label { display: none; }

@media (min-width: 520px) {
  .sound-label { display: inline; }
}
@media (max-width: 360px) {
  :root { --gutter: 12px; }
  .topbar,
  .brand { gap: 8px; }
  .brand-word { font-size: 17px; }
}
@media (min-width: 960px) {
  .nav {
    display: flex;
    gap: 26px;
    margin-right: 14px;
  }
  .nav a {
    color: var(--muted);
    font-size: 14px;
    font-weight: 700;
    text-decoration: none;
  }
  .nav a:hover { color: var(--cream); }
}

/* Hero: the teaser's forms in a row, egg to adult, and the ghost a forgotten one becomes. */
.hero {
  display: grid;
  justify-items: center;
  gap: 12px;
  max-width: 1240px;
  margin: 0 auto;
  padding: 26px max(var(--gutter), env(safe-area-inset-right)) 64px max(var(--gutter), env(safe-area-inset-left));
  text-align: center;
  container-type: inline-size;
}
.hero-kicker {
  margin: 0;
  color: var(--mint);
  font-size: 15px;
  font-weight: 700;
}
.hero-title {
  max-width: 20ch;
  margin: 0;
  font-size: clamp(26px, 7.2vw, 54px);
  line-height: 1.12;
  text-wrap: balance;
}
.hero-wallets {
  margin: 0;
  color: var(--muted);
  font-weight: 700;
}
.pill {
  max-width: 100%;
  margin: 0;
  padding: 6px 12px;
  border: 2px solid var(--gold);
  border-radius: 18px;
  color: var(--gold);
  font-size: clamp(11px, 3.1vw, 14px);
  font-weight: 700;
}
/* On narrow phones the pill breaks between its two halves, never inside one. */
.pill span { white-space: nowrap; }
.soon {
  margin: 0;
  color: var(--mint);
  font-size: 18px;
  font-weight: 700;
}

/* Phones: the four forms in a row and the ghost on a line of its own. Wider screens: one row. */
.forms {
  --arrow-w: 20px;
  --card: min(84px, calc((100vw - 2 * var(--gutter) - 3 * var(--arrow-w)) / 4));
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  row-gap: 16px;
  margin: 20px 0 18px;
  padding: 0;
  list-style: none;
}
/* The hero's own width, so a desktop scrollbar never pushes the fourth card onto a new line. */
@supports (width: 1cqi) {
  .forms { --card: min(84px, (100cqi - 3 * var(--arrow-w)) / 4); }
}
.forms li {
  display: flex;
  align-items: center;
}
.form-arrow {
  display: grid;
  place-items: center;
  width: var(--arrow-w);
  color: var(--mint);
}
.form-fate {
  flex-basis: 100%;
  justify-content: center;
}
.fate-label {
  margin-right: 4px;
  color: var(--muted);
  font-size: 14px;
  font-weight: 700;
}
.form-fate .form-arrow { color: var(--muted); }

/* Cream like the pass. The sprites stand on one floor, so the growing shows. */
.form-card {
  --cell: calc(var(--card) / 22);
  display: grid;
  grid-template-rows: calc(var(--card) * .84) auto;
  justify-items: center;
  align-items: end;
  width: var(--card);
  padding: calc(var(--card) * .06) 0 calc(var(--card) * .09);
  border: 0;
  border-radius: calc(var(--card) * .12);
  background: var(--cream);
  color: var(--outline);
  box-shadow: calc(var(--card) * .05) calc(var(--card) * .05) 0 var(--shadow);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform .08s, box-shadow .08s;
  animation: card-in .42s steps(3) backwards;
  animation-delay: calc(var(--i) * .14s);
}
@media (hover: hover) {
  .form-card:hover { transform: translateY(-2px); }
}
.form-card:active {
  transform: translateY(2px);
  box-shadow: calc(var(--card) * .02) calc(var(--card) * .02) 0 var(--shadow);
}
/* A shade darker than the gone pass, so the cream label stays readable. */
.form-card.is-gone {
  background: #6F6F78;
  color: var(--cream);
}
.form-art { display: block; }
.is-gone .form-art { margin-bottom: calc(var(--cell) * 2); }
.form-name {
  margin-top: calc(var(--card) * .05);
  font-size: clamp(11px, calc(var(--card) * .13), 18px);
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
}

/* The forms take turns: each hops twice, then the arrow passes it on. A tap makes one hop now. */
.form-art .sprite {
  animation: turn 4s infinite;
  animation-delay: calc(1.2s + var(--i) * .8s);
}
.is-gone .form-art .sprite { animation-name: turn-ghost; }
.form-arrow .icon {
  animation: arrow-turn 4s infinite;
  animation-delay: calc(.95s + var(--i) * .8s);
}
.form-card.is-tapped .form-art { animation: tap-hop .5s; }
.form-card.is-gone.is-tapped .form-art { animation-name: tap-shake; }

@keyframes card-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes turn {
  0%, 4.9%, 10%, 14.9% { transform: translateY(calc(var(--cell) * -2)); }
  5%, 9.9%, 15%, 100% { transform: translateY(0); }
}
@keyframes turn-ghost {
  0%, 6.5%, 13.3%, 19.9% { transform: translateY(calc(var(--cell) * -1)); }
  6.6%, 13.2% { transform: translateY(calc(var(--cell) * -2)); }
  20%, 100% { transform: translateY(0); }
}
@keyframes arrow-turn {
  0%, 9.9% { transform: translateX(var(--cell)); }
  10%, 100% { transform: translateX(0); }
}
@keyframes tap-hop {
  0%, 24.9% { transform: translateY(calc(var(--cell) * -3)); }
  25%, 49.9% { transform: translateY(0); }
  50%, 74.9% { transform: translateY(calc(var(--cell) * -2)); }
  75%, 100% { transform: translateY(0); }
}
@keyframes tap-shake {
  0%, 19.9%, 40%, 59.9% { transform: translateX(calc(var(--cell) * -1)); }
  20%, 39.9%, 60%, 79.9% { transform: translateX(var(--cell)); }
  80%, 100% { transform: translateX(0); }
}

.claim-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  width: 100%;
  max-width: 480px;
  margin-top: 6px;
}
.claim-form input {
  min-width: 0;
  padding: 13px 14px;
  border: 2px solid var(--field-line);
  border-radius: 12px;
  background: var(--field);
  color: var(--field-text);
  font: 400 16px/1.2 var(--font);
}
.claim-form input::placeholder { color: #6E6883; }
.claim-form input:focus {
  outline: none;
  border-color: var(--field-focus);
}
.claim-form input[aria-invalid="true"] { border-color: var(--error); }
.form-msg {
  grid-column: 1 / -1;
  min-height: 1.5em;
  margin: 0;
  color: var(--fg-soft);
  font-size: 14px;
  line-height: 1.5;
}
.form-msg.is-error { color: var(--error); }
.form-msg.is-ok { color: var(--ok); }
.form-fine {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--fg-soft);
  font-size: 13px;
  line-height: 1.5;
}
@media (max-width: 420px) {
  .claim-form { grid-template-columns: minmax(0, 1fr); }
}

@media (min-width: 720px) {
  .forms {
    --card: clamp(92px, 10.5vw, 150px);
    --arrow-w: calc(var(--card) * .28);
    flex-wrap: nowrap;
    margin: 30px 0 22px;
  }
  .form-arrow .icon { --cell: calc(var(--card) / 50); }
  .form-fate {
    flex-basis: auto;
    margin-left: calc(var(--card) * .2);
  }
  .fate-label { font-size: 15px; }
}
@media (min-width: 960px) {
  .hero {
    align-content: center;
    min-height: calc(100vh - var(--bar));
    min-height: calc(100svh - var(--bar));
    padding-top: 32px;
  }
}

/* The teaser window */
.teaser-box {
  width: min(100% - 2 * var(--gutter), 640px, 100svh - 150px);
  max-width: none;
  max-height: none;
  margin: auto;
  padding: 0;
  overflow: visible;
  border: 0;
  background: none;
  color: var(--cream);
}
.teaser-box::backdrop { background: rgb(6 4 14 / .88); }
html:has(.teaser-box[open]) { overflow: hidden; }
.teaser-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.teaser-title {
  margin: 0;
  font-size: 16px;
}
.teaser-close {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 0;
  border-radius: 999px;
  background: var(--cream);
  color: var(--outline);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 3px 0 var(--shadow);
}
.teaser-video {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  border: 2px solid var(--ink-line);
  border-radius: 22px;
  background: var(--ink);
  box-shadow: 10px 10px 0 var(--shadow);
}

/* Living sprites hop in place, two frames, like a toy screen. */
@keyframes hop {
  0%, 49.9% { transform: translateY(0); }
  50%, 100% { transform: translateY(calc(var(--cell) * -1)); }
}
@keyframes wobble {
  0%, 24.9% { transform: translateX(0); }
  25%, 49.9% { transform: translateX(calc(var(--cell) * -1)); }
  50%, 74.9% { transform: translateX(0); }
  75%, 100% { transform: translateX(var(--cell)); }
}
@keyframes nudge {
  0%, 5.9% { transform: translateX(0); }
  6%, 11.9% { transform: translateX(calc(var(--cell) * -1)); }
  12%, 17.9% { transform: translateX(var(--cell)); }
  18%, 23.9% { transform: translateX(calc(var(--cell) * -1)); }
  24%, 100% { transform: translateX(0); }
}
@keyframes drift {
  0%, 32.9% { transform: translateY(0); }
  33%, 65.9% { transform: translateY(calc(var(--cell) * -1)); }
  66%, 100% { transform: translateY(calc(var(--cell) * -2)); }
}
@keyframes float-up {
  0% { transform: translateY(0); opacity: 1; }
  70% { opacity: 1; }
  100% { transform: translateY(calc(var(--cell) * var(--rise, 9) * -1)); opacity: 0; }
}
@keyframes flash {
  0% { opacity: 0; }
  35% { opacity: 1; }
  100% { opacity: 0; }
}

.footer-trio > span { animation: hop 1.1s infinite; }
.footer-trio > span:nth-child(2) { animation-delay: -.37s; }
.footer-trio > span:nth-child(3) { animation-delay: -.74s; }
.footer-trio > span:nth-child(4) { animation-delay: -.2s; }

/* The pass: the teaser's card, 600 × 670 units, scaled by --pass-w. */
.pass {
  --pass-w: min(78vw, calc((100vh - var(--bar)) * .46), 360px);
  --cell: calc(var(--pass-w) * .03667);
  position: relative;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  width: var(--pass-w);
  aspect-ratio: 600 / 670;
  padding: calc(var(--pass-w) * .055) calc(var(--pass-w) * .067) calc(var(--pass-w) * .05);
  overflow: hidden;
  border-radius: calc(var(--pass-w) * .067);
  background: var(--cream);
  color: var(--outline);
  box-shadow: calc(var(--pass-w) * .017) calc(var(--pass-w) * .017) 0 var(--shadow);
  transition: background-color .45s steps(3);
}
@supports (height: 1svh) {
  .pass { --pass-w: min(78vw, calc((100svh - var(--bar)) * .46), 360px); }
}
.pass[data-card="hungry"] { background: var(--hungry); }
.pass[data-card="gone"] { background: var(--gone); }

.pass-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  padding-bottom: calc(var(--pass-w) * .03);
  border-bottom: calc(var(--pass-w) * .004 + 1px) solid #D9D3CA;
  font-weight: 700;
  line-height: 1.2;
}
.pass-name { font-size: calc(var(--pass-w) * .053); }
.pass-std {
  color: var(--label);
  font-size: calc(var(--pass-w) * .04);
}
.pass-art { position: relative; }
.pass-foot {
  display: grid;
  line-height: 1.2;
  font-weight: 700;
}
.pass-label {
  color: var(--label);
  font-size: calc(var(--pass-w) * .034);
  letter-spacing: .03em;
}
.pass-status { font-size: calc(var(--pass-w) * .056); }
.pass[data-card="gone"] .pass-head { border-color: #8E8E97; }
.pass[data-card="gone"] .pass-std,
.pass[data-card="gone"] .pass-label { color: #5D5D67; }

.pass-flash {
  position: absolute;
  inset: 0;
  background: #fff;
  opacity: 0;
  pointer-events: none;
}
.pass.is-flashing .pass-flash { animation: flash .36s steps(4); }

/* Centred like the teaser, so growing up spreads both ways. */
.pass-art > .sprite {
  position: absolute;
  left: 50%;
  top: 50%;
  display: none;
  translate: -50% -50%;
}
.pass-art > .sprite.is-on { display: block; }
.pass-art > .pass-heart {
  --cell: calc(var(--pass-w) * .0133);
  --rise: 6;
  left: auto;
  right: 6%;
  top: 13%;
  translate: none;
}
.pass-art > .pass-poop {
  --cell: calc(var(--pass-w) * .0167);
  left: auto;
  right: 8%;
  top: auto;
  bottom: calc(50% - var(--pass-w) * .2167);
  translate: none;
}
.pass-clean {
  position: absolute;
  left: 50%;
  top: calc(50% + var(--cell) * 6.6);
  display: none;
  translate: -50% 0;
  color: var(--label);
  font-size: calc(var(--pass-w) * .032);
  font-weight: 700;
  white-space: nowrap;
}
.pass-clean.is-on { display: block; }

.pass[data-motion="hop"] .pass-body.is-on { animation: hop 1s infinite; }
.pass[data-motion="wobble"] .pass-body.is-on { animation: wobble .9s infinite; }
.pass[data-motion="shake"] .pass-body.is-on { animation: wobble .36s infinite; }
.pass[data-motion="drift"] .pass-body.is-on { animation: drift 2.4s infinite alternate; }
.pass-heart.is-on { animation: float-up 1.5s steps(6) infinite; }

/* The life story: scrolling plays the teaser's card, and the page takes the colour of the moment.
   It fades to grey when the Gochi goes hungry and goes dark when it is gone. */
.life {
  position: relative;
  height: calc(100vh - var(--bar) + 6 * var(--step));
  background-color: var(--mint);
  transition: background-color .45s steps(3);
}
@supports (height: 1svh) {
  .life { height: calc(100svh - var(--bar) + 6 * var(--step)); }
}
.life[data-mood="feed"] { background-color: var(--blush); }
.life[data-mood="clean"] { background-color: var(--peach); }
.life[data-mood="grow"] { background-color: var(--lavender); }
/* A shade under the hungry pass, so the pass stays visible. */
.life[data-mood="hungry"] { background-color: #CFCDD8; }
.life[data-mood="gone"] {
  --fg: var(--cream);
  --fg-soft: var(--muted);
  --line: #55526A;
  --link: var(--gold);
  --focus: var(--gold);
  background-color: #3A3846;
}
/* On colour the pass gets the ink outline every sprite in the teaser has. */
.life .pass {
  box-shadow: 0 0 0 calc(var(--pass-w) * .008 + 1px) var(--outline),
    calc(var(--pass-w) * .026) calc(var(--pass-w) * .026) 0 var(--outline);
}
.life-stage {
  position: sticky;
  top: var(--bar);
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 22px;
  height: calc(100vh - var(--bar));
  padding: 12px var(--gutter) 18px;
}
@supports (height: 1svh) {
  .life-stage { height: calc(100svh - var(--bar)); }
}

.life-copy {
  display: grid;
  justify-items: center;
  gap: 14px;
  width: 100%;
  max-width: 520px;
  text-align: center;
}
@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
.life-text.is-new { animation: fade-in .24s steps(4); }
.life-line {
  min-height: 2.3em;
  margin: 0;
  font-size: clamp(24px, 7vw, 30px);
  font-weight: 700;
  line-height: 1.15;
  text-wrap: balance;
  display: grid;
  align-items: end;
}
.life-note {
  min-height: 4.5em;
  margin: 8px 0 0;
  color: var(--fg-soft);
  font-size: 15px;
  line-height: 1.5;
  text-wrap: balance;
}

/* On phones the steps are a segmented progress bar; on wide screens a list. */
.life-steps {
  display: flex;
  gap: 6px;
  width: min(78vw, 360px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.life-steps li { flex: 1; }
.life-steps button {
  position: relative;
  display: block;
  width: 100%;
  height: 24px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.life-steps button::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 9px;
  height: 6px;
  background: var(--line);
}
.life-steps .is-done button::before,
.life-steps button[aria-current="step"]::before { background: var(--fg); }
.life-steps .step-name {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

.life-skip {
  color: var(--fg-soft);
  font-size: 13px;
}

@media (min-width: 960px) {
  .life-stage {
    grid-template-columns: auto minmax(0, 480px);
    align-items: center;
    justify-content: center;
    gap: clamp(48px, 7vw, 110px);
  }
  .pass { --pass-w: min(34vw, calc((100vh - var(--bar)) * .66), 460px); }
  @supports (height: 1svh) {
    .pass { --pass-w: min(34vw, calc((100svh - var(--bar)) * .66), 460px); }
  }
  .life-copy {
    justify-items: start;
    gap: 28px;
    text-align: left;
  }
  .life-line {
    min-height: 2.2em;
    font-size: clamp(34px, 3.6vw, 52px);
  }
  .life-note {
    min-height: 3.2em;
    font-size: 17px;
    max-width: 40ch;
  }
  .life-steps {
    flex-direction: column;
    gap: 2px;
    width: auto;
  }
  .life-steps button {
    display: flex;
    align-items: center;
    gap: 12px;
    width: auto;
    height: auto;
    padding: 5px 0;
    color: var(--fg-soft);
    font-size: 15px;
    font-weight: 700;
  }
  .life-steps button::before {
    position: static;
    width: 12px;
    height: 12px;
    border: 2px solid currentColor;
    background: none;
  }
  .life-steps .is-done button::before { background: currentColor; }
  .life-steps button[aria-current="step"] { color: var(--fg); }
  .life-steps button[aria-current="step"]::before { background: currentColor; }
  .life-steps .step-name {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip: auto;
  }
}

/* Survivors: scrolling thins the field down to one Gochi. */
.survivors {
  position: relative;
  height: calc(100vh - var(--bar) + 220vh);
}
.surv-stage {
  position: sticky;
  top: var(--bar);
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 16px;
  height: calc(100vh - var(--bar));
  padding: 0 var(--gutter);
  overflow: hidden;
  text-align: center;
}
@supports (height: 1svh) {
  .surv-stage { height: calc(100svh - var(--bar)); }
}
.surv-title {
  margin: 0 0 6px;
  font-size: clamp(26px, 7vw, 56px);
  line-height: 1.12;
  text-wrap: balance;
}
.field {
  --cols: 6;
  --slot: min(13.5vw, 7.2vh, 60px);
  display: grid;
  grid-template-columns: repeat(var(--cols), var(--slot));
  gap: 6px;
  justify-content: center;
}
.slot {
  --cell: calc(var(--slot) / 19);
  position: relative;
  display: grid;
  place-items: end center;
  height: var(--slot);
}
.slot .sprite {
  grid-area: 1 / 1;
  animation: hop 1s infinite;
  animation-delay: var(--delay, 0s);
}
.slot .slot-ghost { display: none; }
.slot.is-dead .slot-live { display: none; }
.slot.is-dead .slot-ghost {
  display: block;
  opacity: .42;
  animation: none;
  transform: translateY(calc(var(--cell) * -2));
}
.surv-stage.is-won .slot.is-dead .slot-ghost { opacity: .2; }
.surv-stage.is-won .slot.is-winner .slot-live {
  animation-duration: .5s;
  scale: 1.35;
  transform-origin: 50% 100%;
}
.surv-stage.is-won .slot.is-winner::after {
  content: '';
  position: absolute;
  inset: -8px -6px -4px;
  border: 3px solid var(--gold);
  border-radius: 10px;
  /* Stepped rings instead of a blur, so the glow stays pixel-like. */
  box-shadow: 0 0 0 5px rgb(255 215 94 / .24), 0 0 0 10px rgb(255 215 94 / .1);
}

.surv-count {
  margin: 6px 0 0;
  color: var(--mint);
  font-size: clamp(18px, 4.6vw, 24px);
  font-weight: 700;
}
.surv-pot {
  margin: 0;
  color: var(--gold);
  font-size: clamp(17px, 4.6vw, 28px);
  font-weight: 700;
  line-height: 1.3;
  opacity: .55;
  transition: opacity .3s;
  text-wrap: balance;
}
.surv-stage.is-won .surv-count { color: var(--gold); }
.surv-stage.is-won .surv-pot { opacity: 1; }
.surv-fine {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
}

@media (min-width: 960px) {
  .field {
    --cols: 12;
    --slot: min(6vw, 9vh, 72px);
    gap: 8px;
  }
}

/* Wallet: blue like Gochi #002 on the phone. The colour runs edge to edge, the content stays 1160px wide. */
.wallet {
  display: grid;
  align-items: center;
  gap: 48px;
  padding: 96px max(var(--gutter), (100% - 1160px) / 2 + var(--gutter));
  background: var(--blue);
}
.wallet h2,
.claim h2,
.faq h2 {
  margin: 0 0 24px;
  font-size: clamp(28px, 7.4vw, 52px);
  line-height: 1.1;
  text-wrap: balance;
}
.facts {
  display: grid;
  gap: 22px;
  margin: 0;
}
.facts dt {
  font-size: 18px;
  font-weight: 700;
}
.facts dd {
  max-width: 46ch;
  margin: 4px 0 0;
  color: var(--fg-soft);
}
.facts a,
.faq a { color: var(--link); }

/* An iPhone in dark mode, open on Apple Wallet. Everything is measured in iOS points (--pt): the screen is
   393 × 852 pt like an iPhone 15 or 16, inside a 15 pt bezel whose outer 5 pt is the titanium band. */
.phone {
  --pw: min(300px, 78vw);
  --pt: calc(var(--pw) / 423);
  position: relative;
  justify-self: center;
  width: var(--pw);
  aspect-ratio: 423 / 882;
  border-radius: calc(var(--pt) * 70);
  /* Black titanium, catching the light at two corners. */
  background: linear-gradient(135deg, #8A898E, #3B3A3F 18%, #1E1D22 45%, #333237 70%, #85848A);
  box-shadow:
    inset 0 0 0 calc(var(--pt) * .8) rgb(255 255 255 / .35),
    0 calc(var(--pt) * 40) calc(var(--pt) * 70) rgb(17 15 27 / .3),
    0 calc(var(--pt) * 12) calc(var(--pt) * 22) rgb(17 15 27 / .22);
}
/* The black bezel inside the band */
.phone::before {
  content: '';
  position: absolute;
  inset: calc(var(--pt) * 5);
  border-radius: calc(var(--pt) * 65);
  background: #000;
  box-shadow: 0 0 0 calc(var(--pt) * .8) rgb(0 0 0 / .6);
}
/* Action button and volume on the left, side button on the right */
.phone-key {
  position: absolute;
  left: calc(var(--pt) * -2.5);
  width: calc(var(--pt) * 3);
  border-radius: calc(var(--pt) * 2) 0 0 calc(var(--pt) * 2);
  background: linear-gradient(90deg, #5E5D62, #2A292E);
}
.phone-key.is-action { top: calc(var(--pt) * 158); height: calc(var(--pt) * 32); }
.phone-key.is-up { top: calc(var(--pt) * 222); height: calc(var(--pt) * 62); }
.phone-key.is-down { top: calc(var(--pt) * 298); height: calc(var(--pt) * 62); }
.phone-key.is-side {
  left: auto;
  right: calc(var(--pt) * -2.5);
  top: calc(var(--pt) * 250);
  height: calc(var(--pt) * 100);
  border-radius: 0 calc(var(--pt) * 2) calc(var(--pt) * 2) 0;
  background: linear-gradient(270deg, #5E5D62, #2A292E);
}
.phone-screen {
  position: absolute;
  inset: calc(var(--pt) * 15);
  overflow: hidden;
  border-radius: calc(var(--pt) * 55);
  background: #000;
  color: #fff;
  font: 400 calc(var(--pt) * 15) / 1.3 -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
  -webkit-font-smoothing: antialiased;
}
/* Light glancing off the glass */
.phone-screen::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 4;
  background: linear-gradient(115deg, rgb(255 255 255 / .1), rgb(255 255 255 / 0) 32%);
  pointer-events: none;
}
/* Status bar: the time and the icons sit centred either side of the Dynamic Island. */
.phone-status {
  display: grid;
  grid-template-columns: 1fr calc(var(--pt) * 126) 1fr;
  align-items: center;
  justify-items: center;
  height: calc(var(--pt) * 37);
  margin: calc(var(--pt) * 11) 0 calc(var(--pt) * 6);
  font-size: calc(var(--pt) * 17);
  font-weight: 600;
}
.phone-time { padding-left: calc(var(--pt) * 8); }
.phone-island {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: calc(var(--pt) * 19);
  background: #000;
  box-shadow: inset 0 0 0 calc(var(--pt) * .6) rgb(255 255 255 / .06);
}
/* The front camera */
.phone-island::after {
  content: '';
  position: absolute;
  right: calc(var(--pt) * 12);
  top: 50%;
  width: calc(var(--pt) * 11);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #34446A, #0B0E18 62%);
  translate: 0 -50%;
}
.phone-icons {
  display: flex;
  align-items: center;
  gap: calc(var(--pt) * 5);
  padding-right: calc(var(--pt) * 6);
}
.phone-icons svg {
  display: block;
  width: auto;
  height: calc(var(--pt) * 12);
  fill: currentColor;
}
.phone-icons svg:last-child { height: calc(var(--pt) * 13); }

/* Wallet's own header: the large title and the add button */
.wallet-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(var(--pt) * 4) calc(var(--pt) * 16) calc(var(--pt) * 12) calc(var(--pt) * 20);
}
.wallet-title {
  font-size: calc(var(--pt) * 34);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: .01em;
}
.wallet-add {
  width: calc(var(--pt) * 30);
  height: calc(var(--pt) * 30);
  border-radius: 50%;
  background:
    linear-gradient(#fff 0 0) center / calc(var(--pt) * 13) calc(var(--pt) * 2) no-repeat,
    linear-gradient(#fff 0 0) center / calc(var(--pt) * 2) calc(var(--pt) * 13) no-repeat,
    #2C2C2E;
}

/* Gochi passes: each in a deep shade of its Gochi's colour, with labels in the colour itself. */
.wpass {
  --tint: var(--blue);
  --pass-bg: #172B4A;
  position: relative;
  margin: 0 calc(var(--pt) * 16);
  border-radius: calc(var(--pt) * 12);
  background: var(--pass-bg);
  box-shadow:
    0 calc(var(--pt) * -2) calc(var(--pt) * 8) rgb(0 0 0 / .55),
    inset 0 calc(var(--pt) * .7) 0 rgb(255 255 255 / .1);
}
.wpass.is-lavender { --tint: var(--lavender); --pass-bg: #2C2452; }
.wpass.is-mint { --tint: var(--mint); --pass-bg: #163B30; }
/* Passes further back show only their top, tucked under the next one. */
.wpass.is-tucked {
  height: calc(var(--pt) * 58);
  margin-bottom: calc(var(--pt) * -10);
}
.wpass-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: calc(var(--pt) * 48);
  padding: 0 calc(var(--pt) * 14);
}
.wpass-logo {
  display: flex;
  align-items: center;
  gap: calc(var(--pt) * 7);
  font: 700 calc(var(--pt) * 15) / 1 var(--font);
  letter-spacing: .06em;
}
.wpass-logo .sprite { --cell: calc(var(--pt) * 1.8); }
.wpass small {
  display: block;
  color: var(--tint);
  font-size: calc(var(--pt) * 10);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: .03em;
}
.wpass-tag {
  font-size: calc(var(--pt) * 17);
  line-height: 1.1;
  text-align: right;
}
/* The strip: the Gochi in its meadow, which goes to dusk when it gets hungry. Cells match the meadow's. */
.wpass-strip {
  --cell: calc(var(--pt) * 361 / 64);
  position: relative;
  height: calc(var(--cell) * 21);
  overflow: hidden;
}
.wpass-strip .scene {
  position: absolute;
  top: 0;
  left: 0;
}
.wpass-strip .scene-dusk {
  opacity: 0;
  transition: opacity 1.2s;
}
.strip-pet,
.strip-bowl {
  position: absolute;
  bottom: var(--cell);
}
.strip-pet { left: calc(var(--cell) * 40); }
.strip-bowl { left: calc(var(--cell) * 52); }
.strip-pet.is-happy .sprite { animation: hop 1s infinite; }
.wpass-strip .is-hungry,
.phone.is-pinged .wpass-strip .is-happy { display: none; }
.phone.is-pinged .wpass-strip .is-hungry { display: block; }
.phone.is-pinged .scene-dusk { opacity: 1; }
.wpass-primary {
  position: absolute;
  left: calc(var(--pt) * 14);
  top: calc(var(--pt) * 8);
  font-size: calc(var(--pt) * 24);
  line-height: 1.2;
  text-shadow: 0 calc(var(--pt) * 1) calc(var(--pt) * 3) rgb(17 15 27 / .4);
}
.wpass-fields {
  display: grid;
  gap: calc(var(--pt) * 12);
  padding: calc(var(--pt) * 12) calc(var(--pt) * 14) calc(var(--pt) * 150);
}
.wpass-row {
  display: flex;
  justify-content: space-between;
  gap: calc(var(--pt) * 12);
}
.wpass-field { margin: 0; }
.wpass-field.is-end { text-align: right; }
.phone.is-pinged [data-wpass-until] { color: var(--blush); }

/* The notification banner, frosted the way iOS draws it, drops in below the island. */
.phone-note {
  position: absolute;
  top: calc(var(--pt) * 54);
  left: calc(var(--pt) * 9);
  right: calc(var(--pt) * 9);
  z-index: 3;
  display: flex;
  align-items: center;
  gap: calc(var(--pt) * 10);
  padding: calc(var(--pt) * 12) calc(var(--pt) * 14);
  border-radius: calc(var(--pt) * 24);
  background: rgb(52 52 58 / .82);
  -webkit-backdrop-filter: blur(calc(var(--pt) * 18)) saturate(1.6);
  backdrop-filter: blur(calc(var(--pt) * 18)) saturate(1.6);
  box-shadow: 0 calc(var(--pt) * 10) calc(var(--pt) * 30) rgb(0 0 0 / .5);
  translate: 0 calc(-100% - var(--pt) * 60);
  transition: translate .55s cubic-bezier(.2, .9, .3, 1.15);
}
.phone.is-pinged .phone-note { translate: 0 0; }
.note-icon {
  --cell: calc(var(--pt) * 2.3);
  display: grid;
  place-items: center;
  width: calc(var(--pt) * 38);
  height: calc(var(--pt) * 38);
  flex: none;
  border-radius: calc(var(--pt) * 9);
  background: #172B4A;
}
.note-body {
  display: grid;
  flex: 1;
  min-width: 0;
  line-height: 1.3;
}
.note-app {
  display: flex;
  justify-content: space-between;
  font-weight: 600;
}
.note-app span {
  color: rgb(235 235 245 / .6);
  font-size: calc(var(--pt) * 13);
  font-weight: 400;
}
/* Home indicator */
.phone-home {
  position: absolute;
  left: 50%;
  bottom: calc(var(--pt) * 8);
  width: calc(var(--pt) * 134);
  height: calc(var(--pt) * 5);
  border-radius: calc(var(--pt) * 3);
  background: #fff;
  translate: -50% 0;
}

@media (min-width: 960px) {
  .wallet {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 96px;
    padding-top: 140px;
    padding-bottom: 140px;
  }
  .phone { --pw: 320px; }
}

/* Claim: gold, the colour of the prize. */
.claim {
  display: grid;
  justify-items: center;
  gap: 10px;
  padding: 72px var(--gutter) 96px;
  background: var(--gold);
  text-align: center;
}
.claim h2 { margin-bottom: 4px; }
.claim-sub {
  max-width: 38ch;
  margin: 0;
  color: var(--fg-soft);
}
.egg {
  --cell: clamp(8px, 2.6vw, 11px);
  position: relative;
  display: grid;
  place-items: end center;
  width: calc(var(--cell) * 22);
  height: calc(var(--cell) * 20);
  margin-top: 18px;
  padding: 0;
  border: 0;
  border-radius: 24px;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.egg .sprite {
  grid-area: 1 / 1;
  display: none;
  margin-bottom: calc(var(--cell) * 2);
}
.egg .sprite.is-on { display: block; }
.egg[data-motion="nudge"] .sprite.is-on { animation: nudge 2.6s infinite; }
.egg[data-motion="shake"] .sprite.is-on { animation: wobble .3s infinite; }
.egg[data-motion="hop"] .sprite.is-on { animation: hop .8s infinite; }
.egg .egg-heart {
  --cell: clamp(3px, 1vw, 4px);
  position: absolute;
  right: 6%;
  top: 4%;
  display: none;
}
.egg .egg-heart.is-on {
  display: block;
  animation: float-up 1.2s steps(9) forwards;
}
.egg-hint {
  min-height: 1.6em;
  margin: 0;
  font-weight: 700;
  text-wrap: balance;
}
.egg-again {
  padding: 4px 8px;
  border: 0;
  background: none;
  color: var(--fg-soft);
  font-size: 14px;
  text-decoration: underline;
  cursor: pointer;
}
.claim-open { margin-top: 8px; }

/* The sign-up window: a cream card that pops up over the page once the egg hatches. */
.claim-box {
  width: min(100% - 2 * var(--gutter), 460px);
  max-width: none;
  max-height: none;
  margin: auto;
  padding: 0;
  overflow: visible;
  border: 0;
  background: none;
}
.claim-box::backdrop { background: rgb(6 4 14 / .72); }
.claim-box[open]::backdrop { animation: fade-in .3s; }
html:has(.claim-box[open]) { overflow: hidden; }
.claim-card {
  --field: #FFFFFF;
  display: grid;
  justify-items: center;
  gap: 12px;
  max-height: calc(100vh - 24px);
  max-height: calc(100svh - 24px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 16px 20px 22px;
  border: 2px solid var(--outline);
  border-radius: 22px;
  background: var(--cream);
  box-shadow: 8px 8px 0 var(--shadow);
  text-align: center;
}
.claim-box[open] .claim-card { animation: card-pop .32s cubic-bezier(.25, 1.4, .5, 1); }
@keyframes card-pop {
  from { transform: translateY(16px) scale(.9); opacity: 0; }
}
.claim-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  width: 100%;
}
.claim-number {
  font-size: 14px;
  font-weight: 700;
}
.claim-close {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 2px solid var(--outline);
  border-radius: 999px;
  background: none;
  color: var(--outline);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
/* The Gochi that hatched, hopping on the claim section's gold. */
.claim-gochi {
  --cell: clamp(6px, 2vw, 8px);
  display: grid;
  place-items: end center;
  width: 100%;
  height: calc(var(--cell) * 20);
  border: 2px solid var(--outline);
  border-radius: 16px;
  background: var(--gold);
}
/* A gold Gochi would vanish on gold. */
.claim-gochi[data-colour="g"] { background: var(--lavender); }
.claim-gochi .sprite {
  margin-bottom: calc(var(--cell) * 2);
  animation: hop .8s infinite;
}
.claim-box-title {
  margin: 4px 0 0;
  font-size: clamp(26px, 7vw, 34px);
  line-height: 1.1;
}
.claim-box-text {
  max-width: 34ch;
  margin: 0;
  color: var(--fg-soft);
}
.claim-card .claim-form { margin-top: 4px; }

/* Pixels that fly off when the egg hatches */
.burst {
  position: absolute;
  left: 50%;
  top: 55%;
  width: var(--cell);
  height: var(--cell);
  pointer-events: none;
  animation: burst .7s steps(7) forwards;
}
@keyframes burst {
  from { transform: translate(-50%, -50%); opacity: 1; }
  to { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))); opacity: 0; }
}

/* FAQ: cream like the pass, for calm reading. The colour runs edge to edge, the text stays 760px wide. */
.faq {
  padding: 48px max(var(--gutter), (100% - 760px) / 2 + var(--gutter)) 96px;
  background: var(--cream);
}
.faq details { border-top: 2px solid var(--line); }
.faq details:last-of-type { border-bottom: 2px solid var(--line); }
.faq summary {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 0;
  font-size: 17px;
  font-weight: 700;
  list-style: none;
  cursor: pointer;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: '+'; }
.faq details[open] summary::after { content: '–'; }
.faq details p {
  max-width: 60ch;
  margin: 0 0 20px;
  color: var(--fg-soft);
}

/* Footer */
.footer {
  display: grid;
  justify-items: center;
  gap: 14px;
  padding: 48px var(--gutter) calc(56px + env(safe-area-inset-bottom));
  color: var(--muted);
  font-size: 13px;
  text-align: center;
}
.footer-trio {
  --cell: 4px;
  display: flex;
  align-items: flex-end;
  gap: 16px;
}
.footer-word {
  margin: 0;
  color: var(--cream);
  font-size: 28px;
  font-weight: 700;
}
.footer-links {
  display: flex;
  gap: 22px;
}
.footer-links a {
  color: var(--cream);
  font-size: 15px;
  font-weight: 700;
  text-decoration: none;
}
.footer-fine {
  max-width: 62ch;
  margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
}
