:root{
  --paper:#fbfbf9; --sheet:#fbfbf9; --ink:#171613; --gray:#a39d90; --rule:#dcd5c6; --muted:#6f6a5f; --err:#a3261c;
  --sans:'Inconsolata',ui-monospace,monospace; --mono:'Inconsolata',ui-monospace,monospace;
}
*{box-sizing:border-box}
html,body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans)}
body{min-height:100vh;display:flex;justify-content:center;padding:56px 20px 80px}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}

.sheet{width:min(920px,100%);background:var(--sheet);border:1px solid transparent;padding:48px clamp(20px,6vw,72px) 40px;position:relative}

.masthead{border-bottom:1px solid var(--ink);padding-bottom:20px;margin-bottom:44px}
.masthead h1{margin:0;font:600 15px/1 var(--sans);letter-spacing:.32em}
.sub{margin:10px 0 22px;font:400 22px/1.3 var(--sans);color:var(--ink)}
.form{display:flex;flex-wrap:wrap;gap:0;margin:0}
.form div{border:1px solid var(--rule);border-right:0;padding:6px 14px 7px;min-width:130px}
.form div:last-child{border-right:1px solid var(--rule)}
.form dt{font:500 11px var(--sans);color:var(--muted);letter-spacing:.06em}
.form dd{margin:2px 0 0;font:400 15px var(--mono)}

.instruction{margin:0 0 26px;font:400 16px var(--sans);color:var(--muted)}

/* the passage: monospace so a reversed or recapitalised word never changes width and never reflows the page */
.passage{font:400 clamp(20px,2.6vw,26px)/2.3 var(--mono);color:var(--ink);word-spacing:.08em;cursor:text;position:relative;
  /* four lines visible, the current one kept second from the top; generous side margin so runaway words aren't cut off */
  height:calc(2.3em * 4);clip-path:inset(-.5em -140px -.5em -140px)}
.lines{position:relative;transition:transform .22s ease}
.word{display:inline-block;position:relative;white-space:nowrap}
.word>.mv,.mv>.a1,.a1>.a2,.a2>.fx{display:inline-block}
.fx>.l{display:inline-block;position:relative}
.word.done{color:var(--gray)}
.word.current .fx{text-decoration:none}
.l.ok{color:var(--gray)}
.l.bad{color:var(--err);text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:4px}
.l.extra{color:var(--err);text-decoration:line-through}
.l.caret::before{content:'';position:absolute;left:-1px;top:.32em;bottom:.32em;width:2px;background:var(--ink);animation:blink 1.05s steps(1) infinite}
.l.caret-after::after{content:'';position:absolute;right:-2px;top:.32em;bottom:.32em;width:2px;background:var(--ink);animation:blink 1.05s steps(1) infinite}
@keyframes blink{50%{opacity:0}}
.word.nudge{animation:nudge .18s}
@keyframes nudge{30%{translate:-3px 0}70%{translate:3px 0}}

/* ── mutations ──────────────────────────────────────────────────────────── */
/* motion layer (a1): one travelling motion at a time */
.a1.float{animation:float var(--dur,2.6s) ease-in-out infinite alternate}
@keyframes float{from{translate:0 calc(var(--amp,.35em)*-1)}to{translate:0 var(--amp,.35em)}}
.a1.drift{animation:drift var(--dur,3.2s) ease-in-out infinite alternate}
@keyframes drift{from{translate:calc(var(--amp,.6em)*-1) 0}to{translate:var(--amp,.6em) 0}}
.a1.runaway{animation:runaway var(--dur,7s) ease-in forwards}
@keyframes runaway{to{translate:var(--far,3em) var(--rise,-.4em)}}
/* shake layer (a2): jitter moves, pulse scales; separate properties so both can run */
.a2.jitter{animation:jitter .11s steps(2) infinite}
@keyframes jitter{0%{translate:.04em -.03em}50%{translate:-.05em .04em}100%{translate:.03em .05em}}
.a2.pulse{animation:pulse var(--pdur,1.4s) ease-in-out infinite alternate}
@keyframes pulse{from{scale:.86}to{scale:1.22}}
.a2.jitter.pulse{animation:jitter .11s steps(2) infinite,pulse var(--pdur,1.4s) ease-in-out infinite alternate}
/* static layer (fx) gets an inline transform, blur and fade */
.fx.fade{opacity:.13}
.fx.blur{filter:blur(1.6px)}
/* letters that wander on their own */
.fx.letters>.l{animation:wander var(--ldur,1.8s) ease-in-out infinite alternate;animation-delay:var(--ld,0s)}
@keyframes wander{from{translate:0 -.18em}to{translate:0 .2em}}

@media (prefers-reduced-motion:reduce){
  .a1.float,.a1.drift,.a2.jitter,.a2.pulse,.fx.letters>.l{animation:none}
  .a1.runaway{animation-duration:.01s}
}

/* hidden but focusable: it catches typing (and brings up phone keyboards) */
.typer{position:absolute;opacity:0;pointer-events:none;left:0;top:0;width:1px;height:1px}
.hint{margin:28px 0 0;font:400 14px var(--sans);color:var(--muted);min-height:1.4em}

.status{margin-top:48px;border-top:1px solid var(--rule);padding-top:18px}
.status-line{display:flex;gap:14px;align-items:baseline;font:400 16px var(--sans);margin-bottom:16px}
.label{display:block;font:500 11px var(--sans);color:var(--muted);letter-spacing:.06em}
.status-line .label{display:inline;min-width:auto}
#status{transition:opacity .4s}
#status.swap{opacity:0}
.readouts{display:grid;grid-template-columns:repeat(3,auto);justify-content:start;gap:8px 42px;font:400 14px var(--sans);color:var(--muted)}
.readouts b{font:500 22px var(--mono);color:var(--ink);margin-right:3px;font-variant-numeric:tabular-nums}
.progress{height:2px;background:var(--rule);margin:20px 0 14px}
.progress i{display:block;height:100%;width:0;background:var(--ink);transition:width .25s}
button{font:inherit;cursor:pointer}
.link{background:none;border:0;padding:0;font:400 14px var(--sans);color:var(--muted);text-decoration:underline;text-underline-offset:3px}
.link:hover{color:var(--ink)}
button:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

.result{position:absolute;inset:0;background:var(--sheet);padding:48px clamp(20px,6vw,72px);display:flex;flex-direction:column;justify-content:center}
.result[hidden]{display:none}
.result h2{margin:0 0 30px;font:600 15px var(--sans);letter-spacing:.32em;border-bottom:1px solid var(--ink);padding-bottom:20px}
.scores{display:grid;grid-template-columns:repeat(4,1fr);margin:0 0 36px;border:1px solid var(--rule)}
.scores div{padding:16px 18px;border-right:1px solid var(--rule)}
.scores div:last-child{border-right:0}
.scores dt{font:500 11px var(--sans);color:var(--muted);letter-spacing:.06em}
.scores dd{margin:6px 0 0;font:400 15px var(--sans);color:var(--muted)}
.scores b{font:500 36px var(--mono);color:var(--ink);font-variant-numeric:tabular-nums}
.verdict{font:400 22px/1.4 var(--sans);margin:0 0 10px;max-width:34ch}
.fine{font:400 14px var(--sans);color:var(--muted);margin:0 0 34px}
.primary{align-self:flex-start;background:var(--ink);color:var(--sheet);border:0;padding:14px 24px;font:500 15px var(--sans)}
.primary:hover{background:#000}

@media (max-width:640px){
  body{padding:16px 12px 40px}
  .readouts{grid-template-columns:repeat(2,auto)}
  .scores{grid-template-columns:repeat(2,1fr)}
  .scores div:nth-child(2){border-right:0}
  .scores div:nth-child(-n+2){border-bottom:1px solid var(--rule)}
}

/* ── deeper mutations ───────────────────────────────────────────────────── */
.a1{perspective:320px}                                   /* gives coin spins real depth */
.a2.coin{animation:coin var(--cdur,2.2s) linear infinite}
.a2.coin.jitter{animation:coin var(--cdur,2.2s) linear infinite,jitter .11s steps(2) infinite}
.a2.coin.pulse{animation:coin var(--cdur,2.2s) linear infinite,pulse var(--pdur,1.4s) ease-in-out infinite alternate}
.a2.coin.jitter.pulse{animation:coin var(--cdur,2.2s) linear infinite,jitter .11s steps(2) infinite,pulse var(--pdur,1.4s) ease-in-out infinite alternate}
@keyframes coin{to{rotate:y 360deg}}
/* liquid letters: they sag, stretch down and snap back */
.fx.drip>.l{animation:drip var(--ldur,2s) cubic-bezier(.6,0,.4,1) infinite;animation-delay:var(--ld,0s);transform-origin:50% 0}
@keyframes drip{0%,100%{translate:0 0;scale:1 1}45%{translate:0 .25em;scale:.82 1.75}55%{translate:0 .5em;scale:1.15 .55}70%{translate:0 0;scale:1 1.08}}
.word.current{z-index:6}
/* you are here: the current word sits on a patch of paper above everything else, wherever it has wandered */
.word.current .fx{background:var(--sheet);box-shadow:0 0 0 .16em var(--sheet),0 0 0 calc(.16em + 1px) var(--ink),0 4px 14px rgba(0,0,0,.12)}
.word.selected .fx{background:#b4d3ff;box-shadow:0 0 0 2px #b4d3ff}
@media (prefers-reduced-motion:reduce){.a2.coin,.fx.drip>.l{animation:none}}

/* the last word, out of the page and loose in the window */
.escape{position:fixed;inset:0;pointer-events:none;z-index:40;font:400 clamp(20px,2.6vw,26px)/2.3 var(--mono);color:var(--ink)}
.escape .mv.escaped{position:absolute;white-space:nowrap;pointer-events:auto;cursor:text}
.escape .mv.current-mv .fx{background:var(--sheet);box-shadow:0 0 0 .16em var(--sheet),0 0 0 calc(.16em + 1px) var(--ink),0 6px 24px rgba(0,0,0,.18)}

/* ── the page misbehaves ────────────────────────────────────────────────── */
#stage{transform-style:preserve-3d;perspective:1400px;width:100%;display:flex;justify-content:center}
body.sway #stage{animation:sway 7s ease-in-out infinite alternate}
@keyframes sway{0%{translate:-10px 0;rotate:-.6deg}50%{translate:8px 6px;rotate:.4deg}100%{translate:-4px -4px;rotate:.8deg}}
body.tilt .sheet{animation:lift 9s ease-in-out infinite alternate;transform-origin:50% 100%}
@keyframes lift{0%{transform:rotateX(0) rotateZ(0)}50%{transform:rotateX(9deg) rotateZ(-.8deg)}100%{transform:rotateX(4deg) rotateY(-5deg) rotateZ(.6deg)}}
html.inverted{filter:invert(1) hue-rotate(180deg);transition:filter .25s}
html{transition:filter .6s}
/* ghost cursors of other candidates */
#ghosts{position:fixed;inset:0;pointer-events:none;z-index:45;overflow:hidden}
.ghost{position:absolute;left:0;top:0;will-change:transform}
.ghost svg{display:block;filter:drop-shadow(0 1px 1px rgba(0,0,0,.3))}
.ghost span{position:absolute;left:14px;top:18px;font:500 10px var(--sans);background:var(--ghost,#3b6fd8);color:#fff;padding:1px 5px;white-space:nowrap}
@media (prefers-reduced-motion:reduce){body.sway #stage,body.tilt .sheet{animation:none}}

.links{display:flex;gap:22px}
.readouts b.odd{font-family:var(--sans)}

/* ── finale ─────────────────────────────────────────────────────────────── */
#finale{position:fixed;inset:0;width:100vw;height:100vh;pointer-events:none;z-index:60;display:none}
#finale.on{display:block}
.sheet.hiding{visibility:hidden}

/* ── print: a calm certificate, whatever the screen was doing ───────────── */
#certificate{display:none}
@media print{
  body>*:not(#certificate){display:none!important}
  html,body{background:#fff;filter:none!important}
  #certificate{display:block;font:400 14pt/1.6 var(--sans);color:#000;padding:2cm;border:2px solid #000;margin:1cm}
  #certificate .c-head{font:600 11pt var(--sans);letter-spacing:.32em}
  #certificate h2{font:400 26pt var(--sans);margin:.2em 0 1em}
}

/* ── the last stretch ───────────────────────────────────────────────────── */
/* a word swallowed by its neighbour keeps its space but isn't drawn */
.word.consumed{display:none}
/* letters a ghost candidate has "typed" */
.l.ghosted{color:var(--gray)}
.assist{margin:6px 0 0;font:400 14px var(--sans);color:var(--ink);min-height:1.4em}
.shift-note{margin:4px 0 0;font:500 12px var(--sans);letter-spacing:.06em;color:var(--err)}
.shift-note[hidden]{display:none}
.legend{margin-top:14px;font:400 13px var(--mono)}
.legend[hidden]{display:none}
.legend div{display:flex;gap:4px;margin-top:4px}
.legend div:nth-child(3){padding-left:14px}.legend div:nth-child(4){padding-left:30px}
.legend kbd{display:flex;flex-direction:column;align-items:center;min-width:30px;padding:3px 0;border:1px solid var(--rule);background:var(--paper);font:500 15px var(--mono)}
.legend kbd small{font:500 9px var(--sans);color:var(--muted)}
/* the whole sheet turns over, then is mirrored */
#stage{transition:transform 5s cubic-bezier(.6,0,.3,1)}
body.flipped #stage{transform:rotate(180deg)}
body.flipped.mirrored #stage{transform:rotate(180deg) scaleX(-1)}
body.mirrored:not(.flipped) #stage{transform:scaleX(-1)}
@media (prefers-reduced-motion:reduce){#stage{transition:none}}
.interlude{z-index:20}
.interlude[hidden]{display:none}
.press{font:500 15px var(--sans);margin:0;animation:blink 1.6s steps(1) infinite}

/* ── WordArt ─────────────────────────────────────────────────────────────── */
/* untyped letters get the fill; typed ones go back to plain feedback colours */
.fx.wa{font-family:Impact,"Arial Black","Haettenschweiler",sans-serif;font-weight:900;letter-spacing:.02em;
  filter:drop-shadow(.04em .04em 0 var(--wa-x,#3a3a52)) drop-shadow(.04em .04em 0 var(--wa-x,#3a3a52)) drop-shadow(.04em .04em 0 var(--wa-x,#3a3a52)) drop-shadow(.06em .08em .04em rgba(0,0,0,.35))}
.fx.wa>.l:not(.ok):not(.bad):not(.extra){-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;-webkit-text-stroke:.022em var(--wa-s,#1b1b6b);
  background-image:var(--wa-g);background-size:calc(var(--n) * 100%) 100%;background-position:calc(var(--i) / max(1, var(--n) - 1) * 100%) 0}
.fx.wa-rainbow{--wa-g:linear-gradient(90deg,#e8102b,#ff8a00 18%,#ffe600 36%,#19c43c 54%,#1f6bff 72%,#8a2be2 90%);--wa-s:#16165c;--wa-x:#5d5d78}
.fx.wa-gold{--wa-g:linear-gradient(180deg,#fff8c4,#f6cf3c 45%,#b27b00 55%,#ffdf6b);background-size:100% 100%;--wa-s:#5a3a00;--wa-x:#7a5400}
.fx.wa-chrome{--wa-g:linear-gradient(180deg,#ffffff,#c9ced8 40%,#5b6372 52%,#e9edf3 70%,#8b93a3);--wa-s:#2a2f3a;--wa-x:#4a5060}
.fx.wa-fire{--wa-g:linear-gradient(0deg,#b30000,#ff4d00 35%,#ffb300 65%,#fff27a);--wa-s:#4a0000;--wa-x:#6b1a00}
.fx.wa-sky{--wa-g:linear-gradient(180deg,#e6f6ff,#7cc8ff 45%,#1c5fd1 55%,#9fdcff);--wa-s:#0b2a6b;--wa-x:#203a70}
/* vertical gradients sit the same on every letter */
.fx.wa-gold>.l,.fx.wa-chrome>.l,.fx.wa-fire>.l,.fx.wa-sky>.l{background-size:100% 100%!important;background-position:0 0!important}
.interlude .wa-title{font-size:clamp(56px,9vw,104px);line-height:1.2;margin:10px 0 26px;white-space:nowrap}
.interlude h2{margin-bottom:0}
/* the current word reads upright whatever the sheet is doing. Each counter-transform is the exact inverse of the
   sheet's, and while the sheet is turning the word turns back on the same curve, so it never reads inverted. */
body.flipped .word.current{transform:rotate(-180deg)}
body.flipped.mirrored .word.current{transform:scaleX(-1) rotate(-180deg)}
body.mirrored:not(.flipped) .word.current{transform:scaleX(-1)}
body.turning .word.current{transition:transform 5s cubic-bezier(.6,0,.3,1)}


/* ════════════════════════════════════════════════════════════════════════════
   The page's design, era by era (deco.js toggles cumulative classes d1…d5).
   Era 0: a blank page and a passage in Inconsolata. Nothing else.
   ════════════════════════════════════════════════════════════════════════════ */
.masthead{border:0;padding:0;margin:0 0 30px;min-height:0}
.masthead .sub,.masthead .sub-wa{display:none;margin:0}
.status{border-top:0;margin-top:30px}
.readouts{font-size:13px;gap:6px 30px;color:var(--gray)}
.readouts b{font-size:18px;color:var(--gray)}
.label{color:var(--gray);font-weight:400;letter-spacing:0}
.progress{background:transparent;height:1px}
.progress i{background:var(--rule)}
.link{color:var(--gray);text-decoration:none}
#deco{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
#deco>div{position:absolute;inset:0;opacity:0;transition:opacity 1.2s}
#stage{position:relative;z-index:1}
.sheet{transition:background-color 1s,border-color 1s,border-radius 1s,box-shadow 1s}
body{transition:background-color 1.2s}
.deco-marquee,.deco-new,.deco-tape,.deco-counter{display:none}

/* ── era 1, corporate memo: the page yellows, a rule and a watermark appear ── */
body.d1{background:#f4f0e4}
body.d1 .sheet{background-color:#f8f5ec;border-color:#e3dccb;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='260'%3E%3Ctext x='20' y='160' transform='rotate(-18 210 130)' font-family='Inconsolata,monospace' font-weight='700' font-size='58' letter-spacing='14' fill='%23000' fill-opacity='.035'%3EOFFICIAL%3C/text%3E%3C/svg%3E")}
body.d1 .readouts b{color:var(--ink)}
body.d1 .progress{height:2px;background:#e3dccb}
body.d1 .progress i{background:#2d5bd7}

/* ── era 2, Office 2003: striped desktop, rounded panel, Comic Sans, marquee, stickers ── */
body.d2{background:repeating-linear-gradient(135deg,#dfeaff 0 22px,#eef4ff 22px 44px)}
body.d2 .sheet{background:#fffef8;background-image:none;border:2px solid #9bb7ef;border-radius:14px;box-shadow:0 10px 0 #b8cdf5,0 18px 40px rgba(40,70,140,.25)}
body.d2 .masthead .sub{display:block;font:700 34px "Comic Neue","Comic Sans MS",cursive;color:#2a4fbf;text-shadow:2px 2px 0 #ffd84a}
body.d2 .readouts>div{background:#fff3b0;border:2px solid #f2c94c;border-radius:10px;padding:6px 12px}
body.d2 .readouts>div:nth-child(2){background:#d6f5d6;border-color:#7ccf7c}
body.d2 .readouts>div:nth-child(3){background:#ffd6e7;border-color:#f28bb5}
body.d2 .label,body.d2 .link{color:#2a4fbf}
body.d2 .deco-marquee{display:block;position:absolute;left:0;right:0;top:12px;overflow:hidden;font:700 15px "Comic Neue","Comic Sans MS",cursive;color:#c2185b;white-space:nowrap}
.deco-marquee>div{display:inline-block;padding-left:100%;animation:marq 22s linear infinite}
@keyframes marq{to{transform:translateX(-100%)}}
body.d2 #deco .deco-stickers{opacity:1}
.deco-stickers span{position:absolute;rotate:var(--r);animation:bob var(--d) ease-in-out var(--dl) infinite alternate;filter:drop-shadow(2px 3px 0 rgba(0,0,0,.15))}
@keyframes bob{to{translate:0 -14px;rotate:calc(var(--r) * -1)}}

/* ── era 3, GeoCities: starfield, rainbow frame, WordArt title, counter, tape, NEW!, sparkles, neon ── */
body.d3{background:#05051a}
body.d3 #deco .deco-sky{opacity:1;background:radial-gradient(1.5px 1.5px at 20px 30px,#fff,transparent),radial-gradient(1px 1px at 90px 120px,#ffe,transparent),radial-gradient(2px 2px at 160px 60px,#bdf,transparent),radial-gradient(1px 1px at 230px 180px,#fff,transparent),radial-gradient(1.5px 1.5px at 60px 210px,#fdf,transparent);background-size:260px 240px;animation:stars 40s linear infinite}
@keyframes stars{to{background-position:-520px 480px}}
body.d3 .sheet{border:0;border-radius:0;animation:rainbowframe 3s linear infinite}
@keyframes rainbowframe{
  0%{box-shadow:0 0 0 5px #ff2a2a,0 0 0 10px #ff9a00,0 0 0 15px #ffe600,0 0 0 20px #2ad13c,0 0 0 25px #2a7bff,0 0 0 30px #9b30ff}
  33%{box-shadow:0 0 0 5px #2a7bff,0 0 0 10px #9b30ff,0 0 0 15px #ff2a2a,0 0 0 20px #ff9a00,0 0 0 25px #ffe600,0 0 0 30px #2ad13c}
  66%{box-shadow:0 0 0 5px #ffe600,0 0 0 10px #2ad13c,0 0 0 15px #2a7bff,0 0 0 20px #9b30ff,0 0 0 25px #ff2a2a,0 0 0 30px #ff9a00}
  100%{box-shadow:0 0 0 5px #ff2a2a,0 0 0 10px #ff9a00,0 0 0 15px #ffe600,0 0 0 20px #2ad13c,0 0 0 25px #2a7bff,0 0 0 30px #9b30ff}}
body.d3 .masthead .sub{display:none}
body.d3 .masthead .sub-wa{display:block;font-size:52px;line-height:1.3;margin-top:14px}
body.d3 .readouts>div{background:#000;border-color:#0ff;box-shadow:0 0 12px #0ff}
body.d3 .readouts b{color:#39ff14;text-shadow:0 0 8px #39ff14}
body.d3 .readouts>div:nth-child(2){border-color:#f0f;box-shadow:0 0 12px #f0f}
body.d3 .readouts>div:nth-child(3){border-color:#ff0;box-shadow:0 0 12px #ff0}
body.d3 .label{color:#fff}
body.d3 .deco-new{display:block;position:absolute;right:28px;top:40px;background:#ff1744;color:#ffeb3b;font:900 18px Impact,"Arial Black",sans-serif;padding:4px 10px;transform:rotate(12deg);animation:blink 1s steps(1) infinite;box-shadow:3px 3px 0 #000}
body.d3 .deco-tape{display:block;position:absolute;left:-30px;right:-30px;bottom:14px;height:30px;overflow:hidden;background:repeating-linear-gradient(45deg,#ffd000 0 22px,#111 22px 44px);transform:rotate(-1.5deg);box-shadow:0 4px 10px rgba(0,0,0,.35)}
.deco-tape span{display:block;text-align:center;font:900 15px/30px Impact,"Arial Black",sans-serif;color:#fff;letter-spacing:.12em;text-shadow:0 0 3px #000,1px 1px 0 #000}
body.d3 .deco-counter{display:block;position:absolute;right:30px;bottom:56px;font:700 12px var(--sans);color:#333}
.deco-counter b{display:inline-flex;gap:2px;margin-left:6px}
.deco-counter i{font:700 16px var(--mono);font-style:normal;background:#000;color:#39ff14;padding:1px 4px;border:1px solid #555}
.deco-spark{position:fixed;z-index:70;pointer-events:none;font-size:18px;translate:-50% -50%;animation:spark .9s ease-out forwards}
@keyframes spark{to{opacity:0;translate:calc(-50% + var(--dx)) 20px;scale:.4}}

/* ── era 4, vaporwave meltdown: sunset grid, orbiting emoji, marching ants, confetti, rainbow readouts ── */
body.d4{background:linear-gradient(#1a0033 0%,#7a1fa2 38%,#ff5ea8 62%,#ffb86b 100%)}
body.d4 #deco .deco-sky{opacity:.6}
body.d4 #deco .deco-grid{opacity:1;top:55%;background:repeating-linear-gradient(90deg,rgba(0,255,255,.55) 0 2px,transparent 2px 80px),repeating-linear-gradient(0deg,rgba(255,0,255,.55) 0 2px,transparent 2px 60px);transform:perspective(320px) rotateX(62deg);transform-origin:50% 0;animation:gridrun 1.6s linear infinite;inset:55% -60% -40% -60%}
@keyframes gridrun{to{background-position:0 0,0 60px}}
body.d4 .sheet{animation:rainbowframe 1.2s linear infinite;outline:3px dashed #fff;outline-offset:38px}
body.d4 #deco .deco-orbit{opacity:1;animation:spin 26s linear infinite}
.deco-orbit span{position:absolute;left:50%;top:50%;transform:rotate(var(--a)) translateX(var(--rad)) rotate(calc(var(--a) * -1));translate:-50% -50%;filter:drop-shadow(4px 6px 0 rgba(0,0,0,.25))}
@keyframes spin{to{rotate:360deg}}
body.d4 .readouts b{background:linear-gradient(90deg,#ff2a2a,#ff9a00,#ffe600,#2ad13c,#2a7bff,#9b30ff,#ff2a2a);background-size:200% 100%;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;text-shadow:none;animation:slide 1.5s linear infinite}
@keyframes slide{to{background-position:200% 0}}
body.d4 .readouts>div:nth-child(1){rotate:-4deg}body.d4 .readouts>div:nth-child(2){rotate:3deg}body.d4 .readouts>div:nth-child(3){rotate:-2deg}
body.d4 .deco-marquee{color:#ff00d4;font-size:18px}
body.d4 .deco-marquee>div{animation-duration:9s}
.deco-confetti{position:fixed;z-index:70;pointer-events:none;font-size:22px;translate:-50% -50%;animation:pop 1.1s cubic-bezier(.2,.7,.4,1) forwards}
@keyframes pop{to{translate:calc(-50% + var(--x)) calc(-50% + var(--y) + 60px);rotate:var(--r);opacity:0}}

/* ── era 5, overtime: all of it, faster, and the colours won't sit still ── */
body.d5 #deco{animation:hue 6s linear infinite}
@keyframes hue{to{filter:hue-rotate(360deg)}}
body.d5 .sheet{animation-duration:.6s}
body.d5 .deco-marquee>div{animation-duration:5s}
body.d5 #deco .deco-orbit{animation-duration:9s}

@media (prefers-reduced-motion:reduce){
  .deco-marquee>div,.deco-stickers span,body.d3 #deco .deco-sky,body.d4 #deco .deco-grid,body.d4 #deco .deco-orbit,body.d3 .sheet,body.d4 .sheet,body.d5 #deco,body.d4 .readouts b,body.d3 .deco-new{animation:none}
}

/* desktop: the page is one fixed screen, no scrolling into empty space below the sheet */
@media (min-width:641px) and (min-height:620px){
  html,body{height:100%;overflow:hidden}
  body{min-height:0;box-sizing:border-box;align-items:center;padding:24px 20px}
}
body.d3 .sheet{padding-bottom:84px}
