/* Self-hosted fonts (SIL Open Font License, see public/fonts/OFL-*.txt). Latin subset. */
@font-face {
  font-family: 'Patrick Hand';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/patrick-hand-400-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Gaegu';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/gaegu-700-latin.woff2') format('woff2');
}

/* Layout: one narrow notebook column; on the play screen the keyboard is the anchor. */
:root {
  --paper: #f5f4ef;
  --paper-key: #fbfaf7;
  --ink: #1e1d1b;
  --ink-soft: #6e6b63;
  --rule: #e2dfd6;
  --burn: #e04a2a;
  --key-side: #e6e2d7;
  --timer: #f28c28;

  --font-hand: 'Patrick Hand', 'Comic Sans MS', 'Segoe Print', cursive;
  --font-letter: 'Gaegu', 'Patrick Hand', 'Comic Sans MS', cursive;

  --col: 34rem;
  --stroke: 2px;
  color-scheme: light;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  background-color: var(--paper);
  /* Faint notebook ruling */
  background-image: repeating-linear-gradient(to bottom, transparent 0 31px, var(--rule) 31px 32px);
  color: var(--ink);
  font-family: var(--font-hand);
  font-size: 1.125rem;
  line-height: 1.35;
  -webkit-tap-highlight-color: transparent;
}

#app {
  max-width: var(--col);
  margin: 0 auto;
  padding-inline: 16px;
  padding-block: max(12px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-bottom));
  min-height: 100%;
}

.screen { display: flex; flex-direction: column; gap: 14px; }

/* Start overlay: translucent paper over the idle game, so the keyboard shows
   through. Fades in and out (class "leaving" = transparent). */
.start {
  position: fixed; inset: 0; z-index: 20; overflow-y: auto;
  padding-inline: 16px;
  padding-block: max(12px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--paper) 86%, transparent);
  backdrop-filter: blur(2.5px);
  -webkit-backdrop-filter: blur(2.5px);
  transition: opacity 0.25s ease-out;
}
/* One centred column, the same width as the game underneath. */
.start-col {
  max-width: calc(var(--col) - 32px); margin-inline: auto;
  display: flex; flex-direction: column; gap: 14px;
}
.start.leaving { opacity: 0; pointer-events: none; }
/* Views below the masthead: the old one fades out fast, then the new one in. */
.view { display: flex; flex-direction: column; gap: 14px; transition: opacity 0.12s ease-out; }
.view.dim { opacity: 0; }
.view-back { align-self: center; }

/* FAQ & privacy */
.faq-link { align-self: center; font-size: 1rem; padding-block: 2px; min-height: 36px; }
.card.faq { padding-right: 10px; }
/* Only the inside scrolls, so the sketched outline stays put. */
.faq-scroll { max-height: 58vh; overflow-y: auto; overflow-x: hidden; padding-right: 10px; }
.faq-list { margin: 0; display: grid; gap: 4px; }
.faq-list dt { font-size: 1.15rem; margin-top: 10px; }
.faq-list dt:first-child { margin-top: 0; }
.faq-list dd { margin: 0; color: var(--ink-soft); }
.card-head.privacy-head { margin-top: 30px; }
.privacy p { margin: 0 0 10px; color: var(--ink-soft); font-size: 1rem; }
.privacy b { color: var(--ink); font-weight: normal; }
.privacy-date { font-size: 0.9rem; }

.arch-note { text-align: left; margin-bottom: 8px; }
.archive-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; max-height: 60vh; overflow-y: auto; }
.arch-item {
  width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
  padding: 8px 4px; font-size: 1.2rem; border-bottom: 1.5px dashed var(--rule);
}
.arch-item b { color: var(--burn); font-weight: normal; margin-right: 6px; }
@media (hover: hover) { .arch-item:hover { background: var(--paper-key); } }
.card .unlock-perks { margin: 6px 0 24px; }
#btn-buy { width: 100%; transition: background-color 0.15s ease-out; }
/* The buy button turns orange on hover instead of the usual pencil wobble. */
@media (hover: hover) {
  #btn-buy:hover { animation: none; background: var(--burn); }
  #btn-buy:hover svg.sk path { stroke: var(--burn); }
}
#unlock-msg { margin-top: 8px; min-height: 1.4em; }

button { font: inherit; color: inherit; }

:focus-visible { outline: 2px dashed var(--burn); outline-offset: 3px; }

.loading { text-align: center; margin-top: 30vh; color: var(--ink-soft); font-size: 1.4rem; }
.dots::after { content: '...'; animation: dots 1s steps(4) infinite; display: inline-block; width: 1.2em; text-align: left; overflow: hidden; vertical-align: bottom; }
@keyframes dots { from { width: 0; } to { width: 1.2em; } }

/* ---------- Sketched outlines ---------- */
[data-sketch] { position: relative; }
svg.sk {
  position: absolute; inset: 0; pointer-events: none; overflow: visible;
}
svg.sk path { fill: none; stroke: var(--ink); stroke-width: var(--stroke); stroke-linecap: round; stroke-linejoin: round; }

/* ---------- Buttons ---------- */
.btn {
  background: var(--paper-key);
  border: 0;
  min-height: 52px;
  padding: 8px 22px;
  font-size: 1.35rem;
  cursor: pointer;
  border-radius: 6px;
}
.btn.primary { background: var(--ink); color: var(--paper); }
.btn.primary svg.sk path { stroke: var(--ink); }

@media (hover: hover) {
  .btn:hover, .link-btn:hover { animation: wobble 0.35s steps(3) infinite; }
}
@keyframes wobble {
  0%   { transform: rotate(0deg) translate(0, 0); }
  33%  { transform: rotate(-1.2deg) translate(0.5px, -0.5px); }
  66%  { transform: rotate(0.9deg) translate(-0.5px, 0.5px); }
  100% { transform: rotate(0deg) translate(0, 0); }
}

.link-btn {
  background: none; border: 0; padding: 10px 6px; cursor: pointer;
  font-size: 1.1rem; color: var(--ink-soft);
  text-decoration: underline wavy var(--ink-soft) 1px; text-underline-offset: 4px;
  min-height: 44px;
}

.actions { display: flex; gap: 12px; flex-wrap: wrap; }
.actions .btn { flex: 1 1 8rem; }

.note { margin: 0; color: var(--ink-soft); text-align: center; text-wrap: balance; }

.meta { margin: 0; color: var(--ink-soft); font-size: 1.05rem; letter-spacing: 0.02em; }

/* ---------- Start ---------- */
.masthead { text-align: center; padding-block: 18px 4px; }
/* Clear the tipped-over "p" so it never touches the date line. */
.masthead .meta { margin-top: 0.7rem; }
.title {
  font-family: var(--font-letter); font-weight: 700;
  font-size: clamp(3.6rem, 18vw, 5.4rem); line-height: 0.9; margin: 0;
  filter: url(#ink); letter-spacing: 0.01em;
}
.title span { display: inline-block; }
.title span:nth-child(odd) { transform: rotate(-3deg); }
.title span:nth-child(even) { transform: rotate(2deg) translateY(2px); }
/* The last letter has popped off like a destroyed keycap */
.title span.t-fall { transform: rotate(18deg) translate(2px, 0.16em); }
/* "Key" in ink, "slop" in the accent, ".io" in soft grey */
.title span.t-slop { color: var(--burn); }
.title span.t-tld { font-size: 0.36em; transform: none; color: var(--ink-soft); margin-left: 0.1em; }

.card { padding: 16px 20px 18px; }
.card-head { margin: 0 0 6px; font-family: var(--font-letter); font-weight: 700; font-size: 1.5rem; }

.rules { margin: 0; padding-left: 1.2em; display: grid; gap: 10px; color: var(--ink); }
.rules li { list-style: '– '; }

/* ---------- Play ---------- */
.play { gap: 10px; }
.play-top { display: flex; justify-content: space-between; align-items: baseline; color: var(--ink-soft); font-size: 1.05rem; }
.burn-count b { color: var(--burn); font-weight: normal; font-size: 1.25rem; }
.tag { border: 1.5px solid currentColor; border-radius: 4px; padding: 0 6px; margin-left: 6px; font-size: 0.9rem; }

.progress { height: 34px; }

/* Run clock (RULES.timeLimitMs), drawn like the progress bar: a wobbly pen outline (sketched
   by doodle.js) around orange crayon hatching. It drains by clipping, so the
   hatching never squashes. Fixed height, always present. */
.timer { position: relative; height: 22px; padding: 6px 7px; margin-top: -4px; }
.timer svg.sk path { stroke-width: 2; }
.timer-fill {
  height: 100%; border-radius: 2px;
  background:
    repeating-linear-gradient(-62deg, transparent 0 3px, rgba(150, 60, 0, 0.28) 3px 4.5px),
    var(--timer);
  filter: url(#ink);
  clip-path: inset(0 0 0 0);
}
.timer.low .timer-fill { animation: timerPulse 0.6s ease-in-out infinite alternate; }
@keyframes timerPulse { to { background-color: var(--burn); } }
.progress svg { display: block; overflow: visible; }
.pb-frame, .pb-div, .pb-hatch { fill: none; stroke: var(--ink); stroke-linecap: round; }
.pb-frame { stroke-width: 2.2; }
.pb-div { stroke-width: 1.6; }
.pb-hatch { stroke-width: 1.2; opacity: 0.45; }
.pb-block { fill: var(--ink); stroke: var(--ink); stroke-width: 1; stroke-linejoin: round; }
.pb-block.fresh { animation: inkIn 0.45s cubic-bezier(.3,1.6,.6,1) both; transform-box: fill-box; transform-origin: center; }
@keyframes inkIn { from { transform: scale(0.2) rotate(-8deg); opacity: 0; } to { transform: none; opacity: 1; } }

.prompt-wrap { text-align: center; }
.round-label { margin: 0; color: var(--ink-soft); font-size: 1rem; letter-spacing: 0.04em; }
/* A fixed two-line box, so a long prompt never moves the keyboard. If a prompt
   would need a third line, main.js shrinks its text to fit (fitPrompt). */
.prompt {
  --prompt-size: clamp(1.9rem, 8.5vw, 3rem);
  margin: 0; font-family: var(--font-letter); font-weight: 700;
  font-size: var(--prompt-size); line-height: 1.05; text-wrap: balance; filter: url(#ink);
  height: calc(var(--prompt-size) * 2.1); overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.prompt { transition: opacity 0.16s ease-out; }
.prompt.out { opacity: 0; }
.prompt .pt-text { text-align: center; }
/* Letters hold their final position; typing only reveals them. */
.prompt .pt-ch { position: relative; opacity: 0; }
.prompt .pt-ch.on { opacity: 1; animation: keyIn 0.09s ease-out; }
@keyframes keyIn { from { opacity: 0.15; } }
/* The cursor hangs off the newest letter and takes up no space. */
.prompt .pt-ch.cur::after {
  content: ''; position: absolute; left: 100%; top: 0.08em; bottom: 0.02em;
  width: 0.07em; margin-left: 0.03em; background: var(--burn); border-radius: 1px;
}
@keyframes dropIn { from { opacity: 0; transform: translateY(-8px) rotate(-2deg); } to { opacity: 1; transform: none; } }

.rounds { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; font-size: 1.05rem; }
/* Fixed one-line rows: long labels or answers are cut with an ellipsis
   instead of wrapping, so the list never changes height. */
.rounds li {
  display: grid; grid-template-columns: 1.4em minmax(0, 8.5em) minmax(0, 1fr); align-items: baseline; gap: 6px;
  height: 26px; color: var(--ink-soft);
}
.rounds li > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rounds .n { text-align: right; }
.rounds .ans { color: var(--ink); font-size: 1.2rem; min-width: 0; }
.rounds li.current { color: var(--ink); }
.rounds li.current .ans { color: var(--ink-soft); }
.rounds li.current .n::before { content: '→'; margin-right: 2px; color: var(--burn); }
.rounds li.current .n span { display: none; }
.rounds li.future { color: var(--ink-soft); opacity: 0.6; }
.rounds .hidden-q { font-family: var(--font-letter); font-weight: 700; letter-spacing: 0.3em; }
.rounds li.skipped .lbl { text-decoration: line-through; }
.rounds li.skipped .ans { color: var(--ink-soft); font-size: 1rem; }
/* Results: your answer next to today's most common one */
.res-rounds li:has(.pop) { grid-template-columns: 1.4em minmax(0, 7em) minmax(0, 1fr) minmax(0, 1fr); }
.res-rounds .rows-head { height: 22px; font-size: 0.9rem; letter-spacing: 0.04em; color: var(--ink-soft); }
.res-rounds .rows-head .pop { font-size: 0.9rem; }
.res-rounds .pop { color: var(--ink-soft); font-size: 1.1rem; }
.res-rounds .pop i { font-style: normal; font-size: 0.85rem; }
.res-rounds li.same .ans { color: var(--burn); }
.pb-skip { fill: none; stroke: var(--ink-soft); stroke-width: 2.4; stroke-linecap: round; }

/* Keyboard: a sketched case holding 3D keycaps. Keys tile edge to edge so the
   whole cell is a tap target; each cap is drawn inset inside its cell. */
.kb-case { margin-inline: -12px; padding: 8px 6px 18px; }
.keyboard { position: relative; display: flex; flex-direction: column; user-select: none; }
.kb-row { display: flex; justify-content: center; }
.kb-spacer { flex: 0.5; }
.case-fill { fill: var(--paper-key); }
.case-line { fill: none; stroke: var(--ink); stroke-width: 2.2; stroke-linecap: round; }
.case-hatch { fill: none; stroke: var(--ink); stroke-width: 1; opacity: 0.5; stroke-linecap: round; }

.key {
  --depth: 7px;
  position: relative;
  flex: 1 1 0; min-width: 0; height: 58px; padding: 0;
  background: none; border: 0; cursor: pointer;
  font-size: 1.5rem; text-transform: uppercase;
  display: grid; place-items: center;
  touch-action: manipulation;
}
.key svg.cap { position: absolute; inset: 0; pointer-events: none; overflow: visible; }
.key .k { position: relative; transform: translateY(calc(var(--depth) / -2)); transition: color 0.15s; }
.key.wide { flex: 1.5 1 0; font-size: 1.15rem; text-transform: none; }
.key.space { flex: 5 1 0; font-size: 1.05rem; text-transform: none; color: var(--ink-soft); }

.cap-skirt { fill: var(--key-side); }
.cap-face { fill: var(--paper-key); }
.cap-line { fill: none; stroke: var(--ink); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.cap-hatch { fill: none; stroke: var(--ink); stroke-width: 0.9; opacity: 0.6; }
.captop { transition: transform 0.06s; }
.key.pressed .captop { transform: translateY(2px); }
.key.pressed .k { transform: translateY(calc(var(--depth) / -2 + 2px)); }

@media (hover: hover) {
  .key:not([data-lives="0"]):hover { animation: wobble 0.35s steps(3) infinite; }
}

/* Cracks: c1 is the first crack, c2 the second that splits the cap. */
.crack { display: none; fill: none; stroke: var(--ink); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.key[data-lives="1"] .c1 { display: inline; }

/* Live preview while typing: what accepting this answer would do. */
.key.pv-crack .c1 { display: inline; stroke: var(--burn); stroke-dasharray: 0.07 0.05; animation: march 0.8s linear infinite; }
.key.pv-crack .k, .key.pv-break .k { color: var(--burn); }
@keyframes march { to { stroke-dashoffset: -0.24; } }

/* Typing a key's last use pops its cap off right away. The bare switch's
   stem is dashed while it's only a preview. Backspace clicks the cap back on. */
.key.pv-break .socket { display: inline; }
.key.pv-break .sock-stem { stroke-dasharray: 2.5 2; }
.key.pv-break .c1, .key.pv-break .c2 { display: inline; }
.key.pv-break .capbody { animation: popOff 0.45s ease-in forwards; transform-box: fill-box; transform-origin: 50% 50%; }
.key.pv-break .k { animation: popOffK 0.45s ease-in forwards; }

.key.reclick .capbody { animation: clickIn 0.24s cubic-bezier(.3, 1.5, .6, 1) both; transform-box: fill-box; transform-origin: 50% 50%; }
.key.reclick .k { animation: clickInK 0.24s cubic-bezier(.3, 1.5, .6, 1) both; }
@keyframes clickIn {
  from { transform: translateY(-16px) rotate(-8deg); opacity: 0; }
  70% { transform: translateY(2px); opacity: 1; }
  to { transform: none; opacity: 1; }
}
@keyframes clickInK {
  from { transform: translateY(calc(var(--depth) / -2 - 16px)) rotate(-8deg); opacity: 0; }
  70% { transform: translateY(calc(var(--depth) / -2 + 2px)); opacity: 1; }
  to { transform: translateY(calc(var(--depth) / -2)); opacity: 1; }
}

/* Accepted: crack draws in */
.key.cracking .c1 { stroke-dasharray: 1; stroke-dashoffset: 1; animation: draw 0.35s ease-out forwards; }
.key.cracking { animation: bump 0.35s ease-out; }
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes bump { 30% { transform: scale(1.08) rotate(-2deg); } 100% { transform: none; } }

/* Destroyed: cap pops off, bare switch remains */
.socket { display: none; }
.sock-well { fill: none; stroke: var(--ink-soft); stroke-width: 1.2; stroke-dasharray: 3 3; }
.sock-housing { fill: var(--key-side); stroke: var(--ink); stroke-width: 1.4; }
.sock-stem { fill: none; stroke: var(--burn); stroke-width: 2.6; stroke-linecap: round; }
.sock-crumbs { fill: var(--ink-soft); }
.key[data-lives="0"] { cursor: not-allowed; }
.key[data-lives="0"] .capbody, .key[data-lives="0"] .k { display: none; }
.key[data-lives="0"] .socket, .key.popping .socket { display: inline; }
.key.popping .c1, .key.popping .c2 { display: inline; }
.key.popping .capbody { animation: popOff 0.52s ease-in forwards; transform-box: fill-box; transform-origin: 50% 50%; }
.key.popping .k { animation: popOffK 0.52s ease-in forwards; }
@keyframes popOff {
  0% { transform: none; opacity: 1; }
  30% { transform: translateY(-12px) rotate(-10deg); opacity: 1; }
  100% { transform: translate(16px, 34px) rotate(50deg); opacity: 0; }
}
@keyframes popOffK {
  0% { transform: translateY(calc(var(--depth) / -2)); opacity: 1; }
  30% { transform: translateY(-16px) rotate(-10deg); opacity: 1; }
  100% { transform: translate(16px, 30px) rotate(50deg); opacity: 0; }
}
.key.denied { animation: shake 0.3s; }

.answer-row { display: flex; gap: 10px; align-items: stretch; }
.answer {
  flex: 1; min-width: 0; min-height: 56px; padding: 8px 14px;
  display: flex; align-items: center; background: var(--paper-key); border-radius: 6px;
  font-size: 1.6rem; overflow: hidden; white-space: pre;
}
.answer-text:empty::before { content: 'type your answer'; color: var(--ink-soft); font-size: 1.25rem; }
.caret { width: 2px; height: 1.1em; background: var(--ink); margin-left: 1px; animation: blink 1s steps(1) infinite; }
.answer-text:empty + .caret { order: -1; margin: 0 4px 0 0; }
@keyframes blink { 50% { opacity: 0; } }
.answer.shake { animation: shake 0.35s; }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px) rotate(-0.6deg); }
  40% { transform: translateX(6px) rotate(0.5deg); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(3px); }
}

.enter { flex: 0 0 auto; padding-inline: 18px; min-width: 92px; display: grid; place-items: center; }
.enter .spinner { display: none; width: 30px; height: 30px; fill: var(--paper); animation: spin 0.9s steps(8) infinite; }
.enter.checking .enter-label { display: none; }
.enter.checking .spinner { display: block; }
@keyframes spin { to { transform: rotate(360deg); } }

.play-foot { display: flex; flex-direction: column; gap: 2px; }
.msg { margin: 0; min-height: 1.4em; font-size: 1.1rem; min-width: 0; }
.foot-btns { display: flex; justify-content: space-between; align-items: center; gap: 10px; }

/* Small wordmark between the footer buttons. Always takes its space (no layout
   shift); it just fades in once a run has started. */
.foot-logo {
  /* No ink filter here: at this size its wobble made the "o" read like an "a". */
  font-family: var(--font-letter); font-weight: 700; font-size: clamp(1.5rem, 7.2vw, 2rem); line-height: 1;
  letter-spacing: 0.02em; white-space: nowrap; user-select: none;
  opacity: 0; transition: opacity 0.4s ease-out 0.15s;
}
.foot-logo.shown { opacity: 1; }
.foot-logo .t-slop { color: var(--burn); }
.foot-logo .t-tld { font-size: 0.6em; color: var(--ink-soft); margin-left: 0.05em; }
.res-logo { align-self: center; margin-top: 4px; }
.btn.small { min-height: 44px; padding: 6px 13px; font-size: 1.1rem; white-space: nowrap; flex-shrink: 0; }

/* "Did you mean" box under the answer bar */
.suggest {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px;
  width: 100%; text-align: left; padding: 10px 14px; border: 0; border-radius: 6px;
  background: var(--paper-key); cursor: pointer; font-size: 1.2rem;
  animation: dropIn 0.25s ease-out;
}
.suggest b { color: var(--burn); font-weight: normal; font-size: 1.35rem; }
.suggest .suggest-hint { color: var(--ink-soft); font-size: 1rem; margin-left: auto; }
.suggest svg.sk path { stroke: var(--burn); stroke-dasharray: 6 4; }
.msg.bad { color: var(--burn); }

/* ---------- Results ---------- */
.res-head { text-align: center; padding-top: 10px; }
.res-title { margin: 0; font-family: var(--font-letter); font-weight: 700; font-size: clamp(2.4rem, 11vw, 3.4rem); line-height: 1; filter: url(#ink); text-wrap: balance; }
.score-line { display: flex; flex-direction: column; align-items: center; gap: 0; }
.score-big { font-family: var(--font-letter); font-weight: 700; font-size: 5rem; line-height: 1; color: var(--burn); font-variant-numeric: tabular-nums; }
.score-break { color: var(--ink-soft); text-align: center; }

.mini-kb { position: relative; display: flex; flex-direction: column; gap: 4px; align-items: center; }

/* Results tally */
.score-big.tick { animation: tick 0.18s ease-out; }
@keyframes tick { 40% { transform: scale(1.12) rotate(-2deg); } }
.float-pts {
  position: absolute; transform: translate(-50%, -4px); pointer-events: none; z-index: 2;
  font-family: var(--font-letter); font-weight: 700; font-size: 1.2rem; color: var(--burn);
  animation: floatUp 0.85s ease-out forwards;
}
@keyframes floatUp { to { transform: translate(-50%, -34px) rotate(-6deg); opacity: 0; } }
.res-bonus {
  font-family: var(--font-letter); font-weight: 700; font-size: 1.4rem; color: var(--burn);
  border: 2px solid var(--burn); border-radius: 6px; padding: 0 10px; transform: rotate(-4deg);
}
.res-bonus.stamp { animation: stamp 0.4s cubic-bezier(.3, 1.6, .6, 1); }
@keyframes stamp { from { transform: scale(2.4) rotate(-14deg); opacity: 0; } to { transform: rotate(-4deg); opacity: 1; } }

/* Where you landed */
.curve-wrap { padding: 12px 14px 10px; }
.curve-head { margin: 0; font-family: var(--font-letter); font-weight: 700; font-size: 1.5rem; text-align: center; }
.curve { height: 150px; }
.curve svg { display: block; overflow: visible; }
.curve-note { margin: 2px 0 0; color: var(--ink-soft); text-align: center; text-wrap: balance; }
.crv-area { fill: var(--rule); opacity: 0.7; }
.crv-line { fill: none; stroke: var(--ink); stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.crv-line.draw { stroke-dasharray: 1; stroke-dashoffset: 1; animation: draw 0.9s ease-out forwards; }
.crv-base { fill: none; stroke: var(--ink); stroke-width: 1.8; stroke-linecap: round; }
.crv-tick, .crv-avg-label { fill: var(--ink-soft); font-family: var(--font-hand); font-size: 13px; }
.crv-avg { stroke: var(--ink-soft); stroke-width: 1.5; stroke-dasharray: 4 4; }
.crv-you-line { fill: none; stroke: var(--burn); stroke-width: 2.4; stroke-linecap: round; }
.crv-you-dot { fill: var(--burn); stroke: var(--ink); stroke-width: 1.5; }
.crv-you-label { fill: var(--burn); font-family: var(--font-letter); font-weight: 700; font-size: 17px; }
.crv-you.drop { animation: youDrop 0.45s 0.85s cubic-bezier(.3, 1.6, .6, 1) both; }
@keyframes youDrop { from { transform: translateY(-24px); opacity: 0; } to { transform: none; opacity: 1; } }
.mini-kb .kb-row { gap: 4px; }
.mini-kb .key { flex: 0 0 auto; width: 31px; height: 40px; font-size: 1.05rem; cursor: default; }


.copy-fallback { width: 100%; min-height: 7em; font: inherit; background: var(--paper-key); color: var(--ink); border: 1.5px dashed var(--ink-soft); padding: 8px; }

/* Dev tools: deliberately not in the doodle style so it never passes as game UI */
.dev-reset {
  position: fixed; right: 8px; bottom: calc(8px + env(safe-area-inset-bottom, 0px)); z-index: 50;
  font: 600 12px/1 ui-monospace, Consolas, monospace; letter-spacing: 0.04em;
  color: #fff; background: #c2185b; border: 2px dashed #fff; outline: 2px solid #c2185b;
  padding: 7px 10px; border-radius: 3px; cursor: pointer; opacity: 0.85;
}
.dev-reset:hover { opacity: 1; }
.dev-reset.second { bottom: calc(46px + env(safe-area-inset-bottom, 0px)); }

@media (max-height: 700px) {
  .key { height: 50px; }
  .mini-kb .key { height: 40px; }
  .prompt { font-size: 2.1rem; }
  .rounds li { min-height: 22px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; }
}
