/* Fonts are served from sunblot.io and preloaded by every page, so they're ready before the first paint and text never
   jumps when they arrive. Latin subsets (Google Fonts, OFL licence). Space Grotesk is one variable file for 300-700. */
@font-face { font-family: 'Space Grotesk'; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url("fonts/space-grotesk-var-latin.woff2") format("woff2"); }
/* Fraunces italic is the only Fraunces face we ship, registered as the display family's normal style, so every heading
   is italic without synthesising one. Axes: weight, optical size, SOFT (rounded terminals) and WONK (the leaning n/m/h). */
@font-face { font-family: 'Sunblot Display'; font-style: normal; font-weight: 300 500; font-display: swap;
  src: url("fonts/fraunces-italic-print.woff2") format("woff2"); } /* SOFT 100, WONK 1 and weights 300-500 only (design/tools/subset-fonts.py) */

/* Sunblot: night sky, gold light. Flat panels, hairline borders, small letter-spaced labels. */
:root {
  --bg: #0E1020;
  --panel: #11142A;      /* page-level panels (menu, cards) */
  --card: #141730;       /* inputs, tiles */
  --raise: #1A1E3C;      /* hover */
  --text: #ECE8DF;
  --muted: #A3A8C3;
  --faint: #6E7496;
  --line: #232744;
  --line-strong: #353A5C;
  --gold: #FF8552;
  --gold-ink: #0E1020;
  --radius: 6px;
  --serif: 'Sunblot Display', Georgia, serif;
  --mono: 'Martian Mono', ui-monospace, monospace;
  --sans: 'Space Grotesk', system-ui, sans-serif;
  /* Side gutters respect phone notches / rounded corners (viewport-fit=cover). */
  --gutter-l: max(16px, env(safe-area-inset-left));
  --gutter-r: max(16px, env(safe-area-inset-right));
  /* Vertical space the game needs around the board (header, ladder, title, answer box).
     The board takes whatever is left, so the whole level fits on screen without scrolling. */
  --chrome: 300px;
}
/* Settings > High contrast */
:root[data-contrast="high"] { --muted: #D2D5E6; --faint: #A9AECB; --line: #3E4468; --line-strong: #5A6190; --text: #FFFFFF; }

* { box-sizing: border-box; }
html { color-scheme: dark; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; overflow-x: hidden; }
@supports (overflow-x: clip) { html { overflow-x: clip; } } /* clip, unlike hidden, doesn't create a scroll container (keeps fixed layers and momentum scrolling smooth) */
html, body { overscroll-behavior-y: none; } /* no rubber-band scrolling past the top or bottom of the page into empty space */
/* The page colour lives on <html> (set inline too, so there is never a white flash); body stays transparent so the fixed sky layer (z-index -1) shows through. */
html { background: var(--bg); }
body { margin: 0; min-height: 100vh; min-height: 100dvh; background: transparent; color: var(--text);
  font: clamp(15px, 0.85rem + 0.25vw, 17px)/1.5 var(--sans); -webkit-font-smoothing: antialiased; }
img, svg, video { max-width: 100%; }
body { display: flex; flex-direction: column; }
body > main { flex: 1 0 auto; } /* short pages keep the footer at the bottom of the screen */
button, input { font: inherit; color: inherit; }
[hidden] { display: none !important; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
a { color: var(--gold); text-underline-offset: 3px; text-decoration-thickness: 1px; }
::selection { background: var(--gold); color: var(--gold-ink); }

.wrap { width: 100%; max-width: 640px; margin: 0 auto; padding: 14px var(--gutter-r) max(48px, env(safe-area-inset-bottom)) var(--gutter-l); }
.muted { color: var(--muted); }
.small { font-size: .85rem; }

/* Small letter-spaced labels: the main type device of the site. */
.eyebrow { font: 600 .8rem/1.3 var(--sans); color: var(--gold); margin: 0; } /* plain, readable labels: no tiny spaced-out caps */
.eyebrow.muted { color: var(--muted); }
/* A section label followed by a dashed rule that runs to the edge. */
.rule { display: flex; align-items: center; gap: 14px; font: 600 .82rem/1.3 var(--sans); color: var(--muted); margin: 32px 0 14px; }
.rule::after { content: ''; flex: 1; border-top: 1px solid var(--line); }
.page-title { font: 400 clamp(2.4rem, 1.6rem + 3vw, 3.4rem)/1 var(--serif); margin: 8px 0 10px; letter-spacing: -.01em; }
.lede { color: var(--muted); margin: 0 0 8px; font-size: 1.05rem; }

/* ---------------------------------------------------------------- Header */

.top { display: flex; align-items: center; justify-content: space-between; gap: 12px; position: relative; padding-top: env(safe-area-inset-top); }
.brand { min-width: 0; }
.wordmark { font: 400 clamp(1.8rem, 1.4rem + 1.6vw, 2.4rem)/1 var(--serif); margin: 0; letter-spacing: .005em; }
.wordmark a { color: inherit; text-decoration: none; }
.dateline { margin: 0 0 4px; min-height: 1.2em; } /* reserved before the script fills it, so the logo doesn't jump */

/* Reserved at the size of its two 44px buttons, which a script adds: the header never grows after the page appears. */
#site-nav { display: flex; align-items: center; gap: 8px; min-width: 96px; min-height: 44px; justify-content: flex-end; }
.icon-btn { width: 44px; height: 44px; min-height: 44px; padding: 0; display: grid; place-items: center; border-radius: var(--radius);
  background: var(--panel); border: 1px solid var(--line-strong); color: var(--text); box-shadow: none; }
.icon-btn:hover { background: var(--raise); }
.icon-btn svg { width: 20px; height: 20px; }
.icon-btn[aria-pressed="false"] { color: var(--faint); }

/* ---------------------------------------------------------------- Menu + settings (a modal panel) */

.sheet { width: min(460px, calc(100vw - 24px)); max-height: min(760px, calc(100dvh - 24px)); margin: auto; padding: 0;
  background: var(--panel); color: var(--text); border: 1px solid var(--line-strong); border-radius: 10px;
  box-shadow: 0 30px 80px -20px #000000cc, 0 0 0 1px #00000040; overflow: auto; overscroll-behavior: contain; }
.sheet::backdrop { background: #05060Ecc; backdrop-filter: blur(3px); }
.sheet[open] { animation: sheet-in .18s ease-out; }
@keyframes sheet-in { from { opacity: 0; transform: translateY(8px); } }
@media (prefers-reduced-motion: reduce) { .sheet[open] { animation: none; } }
.sheet-body { padding: 26px 24px 22px; }
.sheet-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 6px; }
.sheet-head h2 { font: 400 2.2rem/1 var(--serif); margin: 8px 0 0; }
.sheet .rule { margin: 22px 0 12px; }

.tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0; padding: 0; list-style: none; }
.tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 96px; padding: 14px 8px;
  border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--card); color: var(--text); text-decoration: none;
  font: 600 .65rem/1.2 var(--mono); letter-spacing: .08em; text-transform: uppercase; text-align: center; box-shadow: inset 0 -2px 0 #00000040; }
.tile svg { width: 22px; height: 22px; color: var(--muted); }
.tile:hover { background: var(--raise); }
.tile:hover svg { color: var(--text); }
.tile[aria-current="page"] { border-color: var(--gold); color: var(--gold); }
.tile[aria-current="page"] svg { color: var(--gold); }

.link-row { display: flex; align-items: center; gap: 14px; padding: 14px 16px; margin-top: 8px; border: 1px solid var(--line-strong); border-radius: var(--radius);
  color: var(--text); text-decoration: none; background: transparent; }
.link-row:hover { background: var(--raise); }
.link-row svg { width: 20px; height: 20px; color: var(--muted); flex: none; }
.link-row .lr-text { flex: 1; min-width: 0; }
.link-row strong { display: block; font-weight: 600; font-size: .95rem; }
.link-row span span { color: var(--muted); font-size: .82rem; }
.link-row .arrow { color: var(--gold); }
.sheet-foot { margin: 22px 0 0; padding-top: 14px; border-top: 1px dashed var(--line-strong); color: var(--faint); font-size: .8rem; }

.back-link { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0; border: 0; background: none; box-shadow: none; color: var(--gold);
  font: 600 .63rem/1 var(--mono); letter-spacing: .09em; text-transform: uppercase; }
.back-link:hover { background: none; text-decoration: underline; text-underline-offset: 4px; }

.setting { display: flex; justify-content: space-between; align-items: center; gap: 18px; padding: 16px 0; border-top: 1px solid var(--line); }
.setting:first-of-type { border-top: 0; }
.setting h3 { font: 600 .8rem/1.2 var(--sans); margin: 0 0 5px; }
.setting p { margin: 0; color: var(--muted); font-size: .85rem; line-height: 1.45; }
/* On/off switch: a sliding block that says what it is. */
.switch { position: relative; flex: none; width: 76px; height: 36px; min-height: 36px; padding: 0; border-radius: 4px; background: #0A0C18; border: 1px solid var(--line-strong); box-shadow: inset 0 2px 4px #00000060; }
.switch::before { content: 'OFF'; position: absolute; top: 4px; left: 4px; width: 36px; height: 26px; display: grid; place-items: center; border-radius: 3px;
  background: var(--line-strong); color: var(--muted); font: 700 .62rem/1 var(--sans); letter-spacing: .12em; transition: transform .15s ease, background .15s; }
.switch[aria-checked="true"] { border-color: var(--gold); }
.switch[aria-checked="true"]::before { content: 'ON'; transform: translateX(32px); background: var(--gold); color: var(--gold-ink); }
@media (prefers-reduced-motion: reduce) { .switch::before { transition: none; } }

/* ---------------------------------------------------------------- Buttons, inputs, cards */

button { cursor: pointer; border-radius: var(--radius); border: 1px solid var(--line-strong); background: var(--card); padding: 12px 18px; min-height: 44px;
  font: 600 .78rem/1.2 var(--sans); letter-spacing: .14em; text-transform: uppercase; box-shadow: inset 0 -2px 0 #00000040; }
button:hover { background: var(--raise); }
/* Buttons and links that look like buttons answer a press: a quick dip, with colour changes eased instead of snapping. */
button, a.button { transition: background-color .15s ease, border-color .15s ease, color .15s ease, transform .1s ease, opacity .15s ease; }
button:not(:disabled):active, a.button:active { transform: scale(.97); }
/* Main buttons are sunlit: warm gold with a light top edge, sentence case, and a tiny eclipse at the start (a gold sun
   with the dark moon just touching it). Hover or press and the moon slides across to totality. */
button.primary, a.button.primary, .row button { display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  background: linear-gradient(180deg, #F5CF78 0%, #FF8552 55%, #D99A35 100%); color: #1C1407; border: 1px solid #F8DB96;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 -1px 0 rgba(120, 70, 10, .35), 0 8px 20px -10px rgba(255, 133, 82, .75);
  text-transform: none; letter-spacing: .02em; font: 600 .95rem/1.2 var(--sans); }
button.primary, a.button.primary { border-radius: 999px; padding: 12px 22px; }
button.primary:hover, a.button.primary:hover, .row button:hover { background: linear-gradient(180deg, #F8D88A 0%, #EDB955 55%, #DFA23E 100%); }
button.primary::before, a.button.primary::before, .row button::before { content: ''; flex: none; width: .95em; height: .95em; border-radius: 50%;
  background: radial-gradient(circle at 38% 36%, #FFF8E4, #FFD27A 55%, #F2994A); box-shadow: inset -.34em .08em 0 0 #1C1407, 0 0 0 1px rgba(28, 20, 7, .35);
  transition: box-shadow .45s cubic-bezier(.4, 0, .2, 1); }
button.primary:hover::before, button.primary:focus-visible::before, a.button.primary:hover::before, .row button:hover::before, .row button:focus-visible::before {
  box-shadow: inset -.95em 0 0 0 #1C1407, 0 0 0 1px rgba(28, 20, 7, .35), 0 0 6px 1px rgba(255, 248, 228, .8); }
button.primary:disabled::before, .row button:disabled::before { box-shadow: inset -.34em .08em 0 0 #1C1407, 0 0 0 1px rgba(28, 20, 7, .35); }
/* Secondary buttons are night glass: translucent, a hairline edge that warms to gold on hover. */
button.ghost, a.button:not(.primary), .actions-row > button:not(.primary), #sign-out, #copy-code, #email-create, #restart {
  border-radius: 999px; background: rgba(201, 212, 242, .06); border: 1px solid rgba(201, 212, 242, .2); color: var(--text); box-shadow: none;
  text-transform: none; letter-spacing: .02em; font: 600 .9rem/1.2 var(--sans); padding: 11px 20px; }
button.ghost:hover, a.button:not(.primary):hover, .actions-row > button:not(.primary):hover, #sign-out:hover, #copy-code:hover, #email-create:hover, #restart:hover {
  background: rgba(255, 133, 82, .08); border-color: var(--gold); color: var(--gold); }
@media (prefers-reduced-motion: reduce) { button.primary::before, a.button.primary::before, .row button::before { transition: none; } }
button:disabled { opacity: .6; cursor: progress; }
button.ghost { background: transparent; box-shadow: none; }
button.danger { border-color: #8A4B55; color: #F0B4B4; background: transparent; }
button.danger:hover { background: #2A1420; }
button.wide { width: 100%; }
a.button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 44px; text-decoration: none; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: var(--card); color: var(--text); padding: 10px 18px; box-shadow: inset 0 -2px 0 #00000040;
  font: 600 .78rem/1.2 var(--sans); letter-spacing: .14em; text-transform: uppercase; }
a.button:hover { background: var(--raise); }
.status { min-height: 1.4em; color: var(--muted); }
.status:not(:empty) { animation: fade-in .2s ease-out; }
.suggest { display: flex; flex-wrap: wrap; gap: 8px; }
.suggest:empty { display: none; }
.suggestion { font: inherit; color: var(--text); background: var(--raise); border: 1px solid var(--line-strong); border-radius: var(--radius); padding: 6px 12px; cursor: pointer; text-transform: none; letter-spacing: normal; }
.suggestion:hover, .suggestion:focus-visible { border-color: var(--text); }
.card { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 20px; margin-top: 12px; }
.card > .eyebrow:first-child, .card > .rule:first-child { margin-top: 0; }

/* ---------------------------------------------------------------- The game */

/* Level ladder: five segments; each fills with its moon once played. */
.ladder { list-style: none; display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; padding: 0; margin: 14px 0 4px; }
.ladder li { position: relative; display: flex; align-items: center; justify-content: center; gap: 6px; height: 30px; border: 1px solid var(--line); border-radius: 4px;
  font: 600 .72rem/1 var(--sans); letter-spacing: .14em; color: var(--faint); font-variant-numeric: tabular-nums; background: #0E102099; }
.ladder li.current { border-color: var(--gold); color: var(--gold); background: #FF855214; }
.ladder li.done { border-color: var(--line-strong); color: var(--text); background: var(--panel); font-size: .95rem; letter-spacing: 0; }
.puzzle-title { font: 600 .8rem/1.2 var(--sans); color: var(--muted); margin: 10px 0 0; text-align: center; }

/* Phones (one column): the game fills the screen; the board centres in the free space and the
   answer box sits low, where thumbs reach. Wider layouts below switch to two columns. */
.wrap.game { display: flex; flex-direction: column; min-height: 100svh; padding-bottom: max(14px, env(safe-area-inset-bottom)); }
.play { display: flex; flex-direction: column; flex: 1; gap: 4px; }
.stage { display: flex; flex-direction: column; align-items: center; justify-content: center; flex: 1; min-width: 0; }
.panel { min-width: 0; }
/* As wide as the column allows, but never taller than the screen minus the rest of the game. */
.board-wrap { position: relative; padding-top: 1.1em; /* room for top labels that wrap at small sizes */ width: min(100%, max(var(--board-min, 230px), calc((100svh - var(--chrome)) * 400 / 350))); transition: width .35s ease; }
/* One column, after answering: the board makes room so the whole result card fits on screen too. */
.play.answered { --board-min: 240px; } /* app.js sets --chrome to the measured height of everything else */
@media (prefers-reduced-motion: reduce) { .board-wrap { transition: none; } }

.board { position: relative; width: 100%; aspect-ratio: 400 / 350; container-type: inline-size; }
.board svg { display: block; width: 100%; height: 100%; overflow: visible; }
.board .moon { fill: url(#moonTex); stroke: #4A5070; stroke-width: .8; transition: fill .25s, stroke .25s; }
.board .stars { opacity: calc(1 - var(--day, 0)); transition: opacity var(--day-ms, 1.4s) ease-in-out var(--day-delay, .3s); } /* the board's own stars come out with the sky's */
.board .moon.miss { fill: transparent; stroke: #7A80A3; stroke-dasharray: 5 5; }
.board .blackout, .board .diamond { opacity: 0; transition: opacity .15s; }
.board .corona { opacity: 0; transform: scale(.55); transform-box: fill-box; transform-origin: center; transition: opacity .3s ease-out, transform .3s ease-out; }
.board .halo { transition: opacity .3s; }
/* The board sits still while you think: nothing animates until you answer, so phones aren't redrawing the board
   every frame while you type. (The moons' slide and the totality flourish below are the only motion.) */
.board .sun, .board .moon { transform-box: fill-box; transform-origin: center; }
.board svg.total .blackout { opacity: 1; }
.board svg.total .corona { opacity: 1; transform: scale(1); }
.board svg.total .halo { opacity: .1; }
.board svg.total .diamond { animation: ring .3s ease-out forwards; }
@keyframes ring { 0% { opacity: 0; } 40% { opacity: 1; } 100% { opacity: .75; } }
@media (prefers-reduced-motion: reduce) { .board * { transition: none !important; animation-duration: 1ms !important; animation-iteration-count: 1 !important; } .board .sun, .board .halo, .board .moon { animation: none !important; } }

.board-labels { position: absolute; inset: 0; pointer-events: none; }
/* Labels scale with the board itself (container units), so they stay readable and never crowd at any size. */
.board-label { position: absolute; max-width: 32%; text-align: center; font-size: .85rem; font-size: clamp(11px, 3.4cqi, 17px);
  line-height: 1.25; font-weight: 500; translate: -50% 0; text-wrap: balance; }
/* Centred with the translate property, so the ease-in animation (which uses transform) can't knock it off centre. */
.board-label.above { translate: -50% -100%; }
.board-label.right { translate: 0 -50%; text-align: left; }
.board-label.left { translate: -100% -50%; text-align: right; }
.board-label.miss { color: var(--muted); }

.guess { margin-top: 6px; }
.guess label { display: block; margin-bottom: 8px; }
.guess p { margin: 8px 0 0; }
#submit:disabled { cursor: not-allowed; }
/* Answer box and its button read as one control. */
.row { display: flex; gap: 0; border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--card); padding: 4px; }
.row:focus-within { border-color: var(--gold); }
.row input { flex: 1; min-width: 0; min-height: 46px; background: transparent; border: 0; padding: 10px 12px; font-size: max(16px, 1.05rem); /* 16px+ stops iOS zooming in */ }
.row input:focus-visible { outline: none; }
.row input::placeholder { color: var(--faint); }
.row button { min-height: 46px; border-radius: 4px; }

.result-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.result-head p { margin: 0; }
.answer { font-size: 1.3rem; font-weight: 600; overflow-wrap: anywhere; margin-top: 6px !important; }
.points { text-align: right; }
.points span:first-child { display: block; font: 400 2.4rem/1 var(--serif); color: var(--gold); font-variant-numeric: tabular-nums; }
.points span:last-child { font: 600 .56rem/1 var(--mono); letter-spacing: .10em; text-transform: uppercase; }
.tier-name { font: 400 2rem/1.1 var(--serif); margin: 12px 0 4px; }
#r-explain { color: var(--muted); margin: 0; }
/* Tier scale: one connected strip, the earned tier lit. */
.pills { list-style: none; display: flex; padding: 0; margin: 14px 0; border: 1px solid var(--line-strong); border-radius: var(--radius); overflow: hidden; }
.pills li { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 7px 2px; border-left: 1px solid var(--line);
  font-size: .72rem; line-height: 1.2; color: var(--muted); }
.pills li:first-child { border-left: 0; }
.pills .pe { font-size: 1rem; line-height: 1.1; }
/* Names wrap onto two lines ("Total / Eclipse") instead of being cut off, so every tier reads in full on any phone. */
.pills .pn { max-width: 100%; white-space: normal; text-align: center; overflow-wrap: normal; word-break: keep-all; hyphens: none; letter-spacing: .02em; line-height: 1.15; }
.pills .pp { font-weight: 700; font-variant-numeric: tabular-nums; }
@media (max-width: 480px) {
  .pills li { padding: 7px 1px; }
  .pills.many li { font-size: .66rem; }
}
.pills li.on { background: var(--gold); color: var(--gold-ink); font-weight: 700; }
.checklist { list-style: none; padding: 0; margin: 0 0 16px; }
.checklist li { display: grid; grid-template-columns: 22px 1fr auto; gap: 10px; align-items: center; padding: 9px 0; border-top: 1px solid var(--line); }
.checklist svg { width: 20px; height: 20px; }
.checklist .verdict { font: 600 .58rem/1 var(--mono); letter-spacing: .09em; text-transform: uppercase; }
.checklist .fits .verdict { color: var(--gold); }
.checklist .misses .verdict { color: var(--faint); }
#next, #report { width: 100%; }
.share-row { display: flex; gap: 10px; }
.share-row > button { flex: 1 1 0; min-width: 0; }

/* End of the day. Phones: one column in reading order (your day, the answers, worldwide, friends, then the rating).
   Wide screens: two columns; your day and the rating stay in view on the left while you browse the right. */
.summary { display: flex; flex-direction: column; gap: 14px; margin-top: 12px; }
.sum-main, .sum-side { display: contents; }
.sum-day { order: 1; } .sum-more { order: 2; } .sum-answers { order: 3; } .sum-world { order: 4; } .sum-friends { order: 5; } .sum-rate { order: 6; }
.summary .card { margin: 0; }
.big-score { font: 400 3.4rem/1 var(--serif); margin: 10px 0 0; font-variant-numeric: tabular-nums; }
.big-score .muted { font-size: 1.6rem; }
.summary-list { list-style: none; padding: 0; margin: 16px 0; counter-reset: lvl; }
.summary-list li { display: grid; grid-template-columns: 2.2em 1.6em 1fr auto; align-items: center; gap: 6px; padding: 9px 0; border-top: 1px solid var(--line); overflow-wrap: break-word; counter-increment: lvl; }
.summary-list li::before { content: '0' counter(lvl); font: 600 .68rem/1 var(--sans); letter-spacing: .14em; color: var(--faint); }
.summary-list .sl-tier { color: var(--muted); font-size: .85rem; white-space: nowrap; }
/* Narrow phones: the tier goes on its own line under the answer, so neither gets squeezed or split mid-word. */
@media (max-width: 400px) {
  .summary-list li { grid-template-columns: 2.2em 1.6em 1fr; row-gap: 2px; }
  .summary-list .sl-tier { grid-column: 3; font-size: .8rem; }
}
.share { font: 1.4rem/1.4 var(--sans); background: #0A0C18; border: 1px dashed var(--line-strong); border-radius: var(--radius); padding: 14px; white-space: pre-wrap; margin: 0 0 10px; }
/* Record: one connected grid of numbers. */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); margin: 0; border: 1px solid var(--line-strong); border-radius: var(--radius); overflow: hidden; }
.stats div { display: flex; flex-direction: column; justify-content: space-between; gap: 8px; padding: 14px 12px 12px; border-left: 1px solid var(--line-strong); min-width: 0; } /* labels may wrap; numbers line up at the bottom */
.stats div:first-child { border-left: 0; }
.stats dt { font-size: .74rem; color: var(--muted); line-height: 1.25; min-height: 2.5em; }
.stats dd { margin: 0; font: 600 1.8rem/1 var(--sans); letter-spacing: -.02em; color: var(--gold); font-variant-numeric: tabular-nums; }
@media (max-width: 420px) {
  .stats { grid-template-columns: 1fr 1fr; }
  .stats div:nth-child(3) { border-left: 0; }
  .stats div:nth-child(n+3) { border-top: 1px solid var(--line-strong); }
}

/* Wide screens (laptops, desktops, tablets in landscape): board on the left, answer and result on the right.
   The board sizes from the screen height, so a whole level is visible at once. */
@media (min-width: 860px) {
  .wrap.game { max-width: 1180px; padding-top: 22px; }
  .game .play { display: grid; flex: none; grid-template-columns: minmax(0, 1fr) minmax(320px, 400px); gap: 32px; align-items: start; }
  .game .stage { justify-content: flex-start; }
  .game .panel { padding-top: 40px; }
  .game .board-wrap { width: min(100%, max(320px, calc((100svh - 190px) * 400 / 350))); }
  .game .summary { display: grid; grid-template-columns: minmax(320px, 400px) minmax(0, 1fr); gap: 20px; align-items: start; }
  .game .sum-main, .game .sum-side { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
}
/* Phones and small tablets held sideways: same two columns, header squeezed so the board gets the height. */
@media (orientation: landscape) and (max-height: 560px) and (min-width: 560px) {
  .wrap.game { max-width: none; padding-top: 6px; padding-bottom: 12px; }
  .game .wordmark { font-size: 1.6rem; }
  .game .dateline, .game .puzzle-title { display: none; }
  .game .ladder { margin: 6px 0 2px; }
  .game .ladder li { height: 24px; }
  .game .play { display: grid; flex: none; grid-template-columns: minmax(0, 1fr) minmax(260px, 46%); gap: 16px; align-items: start; }
  .game .stage { justify-content: flex-start; }
  .game .board-wrap { width: min(100%, max(200px, calc((100svh - 96px) * 400 / 350))); }
  .game .summary { display: grid; grid-template-columns: minmax(280px, 42%) minmax(0, 1fr); gap: 14px; align-items: start; }
  .game .sum-main, .game .sum-side { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
}
/* Shorter screens: a more compact result card (the checklist already says what the explanation line says). */
@media (max-height: 720px) {
  .game .card { padding: 14px 16px; margin-top: 8px; }
  .game #r-explain { display: none; }
  .game .tier-name { font-size: 1.5rem; margin: 6px 0 0; }
  .game .pills { margin: 8px 0; }
  .game .checklist li { padding: 6px 0; }
  .game .points span:first-child { font-size: 1.9rem; }
}
/* Short screens (small phones, browser bars showing): drop the hint line, keep everything on one screen. */
@media (max-height: 640px) {
  :root { --chrome: 290px; }
  .game .guess p, .game .dateline { display: none; }
  .game .ladder { margin-top: 8px; }
}
/* Very small phones (e.g. 320px wide): tighter chrome so the board stays big. */
@media (max-width: 360px) {
  :root { --chrome: 280px; }
  .pills li { font-size: .68rem; }
  .stats dt { font-size: .68rem; }
  .sheet-body { padding: 22px 16px 18px; }
}
/* Big monitors and TVs: a little larger overall. */
@media (min-width: 1600px) and (min-height: 900px) {
  body { font-size: 18px; }
  .wrap.game { max-width: 1400px; }
}

/* ---------------------------------------------------------------- Content pages */

.prose { max-width: 640px; margin-top: 28px; }
.prose > h1.tier-name { font: 400 clamp(2.4rem, 1.6rem + 3vw, 3.4rem)/1 var(--serif); margin: 8px 0 12px; }
.prose h2 { font: 600 1.05rem/1.3 var(--sans); color: var(--text); margin: 36px 0 12px; }

.prose p, .prose li { color: #D8D6E2; line-height: 1.7; }
.prose li { margin: 6px 0; }
.prose li::marker { color: var(--faint); }
.prose strong { color: var(--text); font-weight: 600; }
.prose .muted { color: var(--muted); }
.field { margin: 16px 0; }
.field label { display: block; font-weight: 500; margin-bottom: 8px; }
.field input { width: 100%; min-height: 48px; background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--radius); padding: 12px; font-size: max(16px, 1rem); }
.field input:focus-visible { outline: none; border-color: var(--gold); }
.hint { font-size: .85rem; color: var(--muted); margin: 6px 0 0; }
fieldset.plain { border: 0; padding: 0; margin: 0; }
.field-legend { font: 400 1.5rem var(--serif); padding: 0; }

/* FAQ: questions as labelled sections. */
.faq-tiers { list-style: none; padding: 0; margin: 14px 0; border: 1px solid var(--line-strong); border-radius: var(--radius); overflow: hidden; }
.faq-tiers li { display: grid; grid-template-columns: 1.8em 1fr auto; gap: 10px; align-items: center; margin: 0; padding: 10px 14px; border-top: 1px solid var(--line); }
.faq-tiers li:first-child { border-top: 0; }
.faq-tiers b { color: var(--gold); font-variant-numeric: tabular-nums; }
.faq-tiers span.muted { font-size: .85rem; }

/* Account (logbook) */
.acct-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.acct-row > div { min-width: 0; }
.acct-email { margin: 0; overflow-wrap: anywhere; }
.synced { margin: 12px 0 0; color: var(--gold); font-weight: 500; font-size: .9rem; }
.danger-zone { margin-top: 40px; padding-top: 18px; border-top: 1px dashed var(--line-strong); }
.danger-zone h2 { margin-top: 0 !important; }
.or { text-align: center; margin: 12px 0; }
.actions-row { display: flex; gap: 8px; flex-wrap: wrap; margin: 16px 0 0; }
.friend-code { font: 400 2.2rem/1.1 var(--serif); letter-spacing: .08em; color: var(--gold); margin: 6px 0; overflow-wrap: anywhere; }
.tabs { display: flex; gap: 6px; margin: 8px 0 4px; flex-wrap: wrap; }
.tabs button { flex: 1 1 auto; }
.tabs button[aria-pressed="true"] { background: var(--gold); border-color: var(--gold); color: var(--gold-ink); }
.table-scroll { overflow-x: auto; }
.board-table { width: 100%; border-collapse: collapse; }
.board-table th, .board-table td { text-align: left; padding: 10px 6px; border-top: 1px solid var(--line); }
.board-table th { font: 600 .59rem/1.2 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.board-table tr.you td { color: var(--gold); font-weight: 700; }
.board-table td:nth-child(3) { white-space: nowrap; }
.people { list-style: none; padding: 0; margin: 0; }
.people li { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-top: 1px solid var(--line); flex-wrap: wrap; }
.people li span { flex: 1; min-width: 8em; }
.people button { padding: 6px 12px; }

.site-foot { margin-top: 48px; padding-top: 16px; border-top: 1px dashed var(--line-strong); display: flex; gap: 18px; flex-wrap: wrap; font-size: .82rem; color: var(--faint); }
.site-foot a { color: var(--muted); }

/* ---------------------------------------------------------------- Background sky (sky.js) */

/* Sized to the LARGE viewport (lvh) so it never resizes when a phone's address bar slides in and out while scrolling,
   and promoted to its own compositor layer: the browser just slides the page over it instead of repainting the image. */
#sky { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; height: 100lvh; z-index: -1; pointer-events: none; overflow: hidden;
  transform: translate3d(0, 0, 0); backface-visibility: hidden; will-change: transform; contain: strict;
  background:
    radial-gradient(1px 1px at 12% 18%, #ECE8DF88, transparent 60%), radial-gradient(1px 1px at 78% 12%, #ECE8DF66, transparent 60%),
    radial-gradient(1.5px 1.5px at 35% 72%, #ECE8DF55, transparent 60%), radial-gradient(1px 1px at 88% 64%, #ECE8DF77, transparent 60%),
    radial-gradient(1px 1px at 6% 88%, #ECE8DF55, transparent 60%), radial-gradient(1.5px 1.5px at 55% 36%, #ECE8DF44, transparent 60%),
    radial-gradient(1px 1px at 22% 46%, #ECE8DF66, transparent 60%), radial-gradient(1px 1px at 67% 90%, #ECE8DF55, transparent 60%),
    linear-gradient(180deg, #121530 0%, var(--bg) 55%, #0A0B17 100%); }
/* Painted sky (npm run art): wide image on landscape screens, tall one on portrait phones. */
/* Under the picture, a gradient in the same colours (night sky fading to the orange horizon glow) shows for the
   instant before it arrives, so the page never sits on a flat background. */
#sky.painted { background: url("art/sky-wide.webp") center bottom / cover no-repeat,
  linear-gradient(180deg, #0B0D1C 0%, #10132A 55%, #1A1A33 80%, #3A2A2E 90%, #0C0D18 100%); }
@media (orientation: portrait) { #sky.painted { background-image: url("art/sky-tall.webp"), linear-gradient(180deg, #0B0D1C 0%, #10132A 55%, #1A1A33 80%, #3A2A2E 90%, #0C0D18 100%); } }
/* Daylight over the night sky (sky.js setDaylight): a deep day blue that lifts as the moons cover the sun.
   Kept dark enough for the cream text; it thins out at the very bottom so the hills and horizon glow still show. */
#sky .daylight { position: absolute; inset: 0; opacity: var(--day, 0); transition: opacity var(--day-ms, 1.4s) ease-in-out var(--day-delay, .3s);
  background: linear-gradient(180deg, #173057 0%, #203E6B 50%, #28466F 80%, rgba(40, 70, 111, .55) 90%, rgba(40, 70, 111, 0) 97%); }
@media (prefers-reduced-motion: reduce) { #sky .daylight, .board .stars { transition: none; } }
.flyer { position: absolute; left: 0; top: 0; will-change: transform; }
.flyer svg { display: block; overflow: visible; max-width: none; }
.flyer.birds path { fill: #121A2C; }
.flyer .beat .up, .flyer .beat .down { animation: var(--beat, .5s) steps(1) var(--d, 0s) infinite; }
.flyer .beat .up { animation-name: wing-up; }
.flyer .beat .down { animation-name: wing-down; opacity: 0; }
@keyframes wing-up { 50% { opacity: 0; } }
@keyframes wing-down { 0% { opacity: 0; } 50% { opacity: 1; } }
.flyer .strobe { opacity: 0; animation: strobe 1.6s infinite; }
@keyframes strobe { 0%, 4%, 10%, 14% { opacity: 0; } 2%, 12% { opacity: 1; } }
.flyer .glint { animation: glint 9s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
@keyframes glint { 0%, 40%, 60%, 100% { opacity: .35; transform: scale(.8); } 50% { opacity: 1; transform: scale(1.4); } }
@media (prefers-reduced-motion: reduce) { .flyer { display: none; } }

/* Today, worldwide (stats.js) */

/* Today, worldwide (stats.js): big score, a moonlight bell curve with your score as a gold line, the ranking line,
   then a level log of stems where lower = a rarer answer. */
.w-top { display: flex; align-items: baseline; gap: 12px; margin: 8px 0 2px; }
.w-score { font: 400 3rem/1 var(--serif); letter-spacing: -.01em; }
.w-rank { margin: 10px 0 2px; font: 600 .9rem/1.3 var(--sans); color: var(--gold); }
.c-tip { position: absolute; top: 6px; padding: 5px 9px; border: 1px solid var(--line-strong); border-radius: 6px; background: var(--card); color: var(--text);
  font-size: .78rem; white-space: nowrap; pointer-events: none; box-shadow: 0 6px 18px -8px #000a; z-index: 2; }
.c-tip b { margin-right: 6px; font-variant-numeric: tabular-nums; }
.c-tip-you { color: var(--gold); font-weight: 600; }

.world-levels { list-style: none; padding: 0; margin: 12px 0 0; }
.world-levels li { border-top: 1px solid var(--line); padding: 12px 0; }
.world-levels p { margin: 3px 0; }
.wl-level { color: var(--faint); font: 600 .8rem/1 var(--sans); margin-right: 6px; }
.wl-answer { overflow-wrap: anywhere; }
.wl-tier { color: var(--muted); font-size: .85rem; }
.chip { display: inline-block; border: 1px solid var(--line-strong); border-radius: 4px; padding: 2px 8px; margin: 4px 2px 0 0; }
.chip.you { border-color: var(--gold); color: var(--gold); }
.google-btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px; background: #fff; color: #1F1F1F; border-color: #fff;
  text-transform: none; letter-spacing: 0; font-size: .95rem; font-weight: 500; }
.google-btn:hover { background: #F1F1F1; }

/* Rating (stats.js) */
.rate-row { display: flex; align-items: center; gap: 14px; margin: 10px 0 4px; min-height: 44px; }
.stars { display: inline-flex; gap: 6px; padding: 4px; margin: -4px; border-radius: 10px; cursor: pointer; touch-action: pan-y; outline: none; }
.stars:focus-visible { box-shadow: 0 0 0 2px var(--gold); }
/* Each star: an outline, and a gold copy on top clipped to --fill (0%, 50% or 100%). */
.star { position: relative; display: block; width: 34px; height: 34px; }
.star svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.star polygon { stroke-linejoin: round; stroke-width: 1.4; }
.s-base polygon { fill: rgba(122, 128, 163, .12); stroke: #7A80A3; /* 3:1+ on the card */ }
.s-fill { clip-path: inset(0 calc(100% - var(--fill, 0%)) 0 0); transition: clip-path .12s ease-out; filter: drop-shadow(0 0 6px rgba(255, 133, 82, .35)); }
.s-fill polygon { fill: var(--gold); stroke: var(--gold); }
.stars.previewing .s-fill polygon { fill: #F2C978; stroke: #F2C978; }
.stars.pop .star { animation: star-pop .38s cubic-bezier(.3, 1.6, .5, 1) both; }
.stars.pop .star:nth-child(2) { animation-delay: .03s; } .stars.pop .star:nth-child(3) { animation-delay: .06s; }
.stars.pop .star:nth-child(4) { animation-delay: .09s; } .stars.pop .star:nth-child(5) { animation-delay: .12s; }
@keyframes star-pop { 40% { transform: scale(1.18); } }
.rate-hint { font: 500 .9rem/1 var(--sans); color: var(--gold); font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (prefers-reduced-motion: reduce) { .s-fill { transition: none; } .stars.pop .star { animation: none; } }
.card-title { margin-top: 0 !important; }
.card-end { margin-bottom: 0 !important; }
.prose .tier-name { line-height: 1.15; }

/* Site footer (every page) and the 404 page */
.site-footer { text-align: center; padding: 28px var(--gutter-r) max(28px, env(safe-area-inset-bottom)) var(--gutter-l); color: var(--faint); font-size: .8rem; }
.site-footer p { margin: 0; }
.site-footer a { color: var(--muted); text-decoration: none; }
.site-footer a:hover, .site-footer a:focus-visible { color: var(--text); text-decoration: underline; }
.not-found { padding-top: 6vh; }
.not-found .actions-row { margin-top: 24px; }

/* Game loading and load-error states (app.js) */
.loading { display: flex; align-items: center; justify-content: center; gap: 12px; flex: 1; min-height: 40vh; color: var(--muted); font-size: .95rem; }
.spinner { width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--line-strong); border-top-color: var(--gold); animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.4s; } }
.load-error { max-width: 460px; margin: 10vh auto 0; text-align: center; }
.load-error p { margin: 0 0 16px; }

/* Archive (archive.html) and the past-day banner on the game */
.archive-list { list-style: none; padding: 0; margin: 12px 0 24px; border-top: 1px solid var(--line); }
.archive-list li { border-bottom: 1px solid var(--line); margin: 0; }
.archive-list a { display: grid; grid-template-columns: 1fr auto; grid-template-areas: "date go" "status go"; gap: 2px 12px; align-items: center; padding: 14px 6px; color: var(--text); text-decoration: none; border-radius: 6px; }
.archive-list a:hover, .archive-list a:focus-visible { background: var(--raise); }
.ad-date { grid-area: date; font-weight: 600; }
.ad-status { grid-area: status; font-size: .9rem; letter-spacing: .02em; }
.ad-status b { color: var(--gold); margin-left: 6px; }
.ad-go { grid-area: go; color: var(--gold); font-size: .85rem; white-space: nowrap; }
.archive-bar { margin: 0 0 10px; padding: 8px 12px; border: 1px solid var(--line-strong); border-radius: var(--radius); background: rgba(14, 16, 32, .7); font-size: .85rem; color: var(--muted); }


/* Phones (one-column game, and short landscape): the game is exactly one screen tall, so no footer below it to scroll
   to. That extra height let the page scroll past the game into empty space while the keyboard was open. Privacy and
   Contact are in the menu. */
@media (max-width: 859px), (orientation: landscape) and (max-height: 560px) {
  body:has(> main.game) > .site-footer { display: none; }
}

/* Sign-in: "or use email" between the Google button and the email form */
.or-divider { display: flex; align-items: center; gap: 12px; margin: 18px 0 6px; color: var(--faint); font-size: .8rem; letter-spacing: .06em; }
.or-divider::before, .or-divider::after { content: ''; flex: 1; border-top: 1px solid var(--line); }

/* ---------------------------------------------------------------- Motion: short, purposeful, and off for reduced motion */
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes shake { 0%, 100% { transform: none; } 20% { transform: translateX(-6px); } 40% { transform: translateX(5px); } 60% { transform: translateX(-3px); } 80% { transform: translateX(2px); } }
/* A new level: the board and its labels ease in. */
.board.enter .board-labels { animation: fade-in .35s ease-out both; }
.board.enter .board-label { animation: label-in .45s cubic-bezier(.2, .7, .2, 1) both; } /* delay per moon, set in board.js */
@keyframes label-in { from { opacity: 0; transform: translateY(4px); filter: blur(2px); } to { opacity: 1; transform: none; filter: none; } }
/* The result card and the day's summary slide up into place. */
#result:not([hidden]) { animation: rise .3s ease-out both; }
.summary:not([hidden]) .card { animation: rise .35s ease-out both; }
.summary:not([hidden]) .sum-answers, .summary:not([hidden]) .sum-rate { animation-delay: .06s; }
.summary:not([hidden]) .sum-world { animation-delay: .12s; }
.summary:not([hidden]) .sum-friends { animation-delay: .18s; }
/* A word that doesn't count (not a word, or a strike): the answer box gives a small shake. */
.row.shake { animation: shake .35s ease-in-out; }
/* Level ladder: steps change colour smoothly as you go. */
.ladder li { transition: background-color .3s ease, border-color .3s ease, color .3s ease; }
@media (prefers-reduced-motion: reduce) {
  .board.enter svg, .board.enter .board-labels, .board.enter .board-label, #result:not([hidden]), .summary:not([hidden]) .card,
  .row.shake, .status:not(:empty) { animation: none; }
  button, a.button, .ladder li { transition: none; }
  button:not(:disabled):active, a.button:active { transform: none; }
}

/* ---------------------------------------------------------------- Start screen (index.html #home) */
.home { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 4px; padding: 24px 8px 32px; max-width: 520px; margin: 0 auto; }
/* A small eclipse from the game's own sun and moon art. */
.home-eclipse { position: relative; width: 132px; height: 132px; margin-bottom: 18px; }
.home-eclipse span { position: absolute; border-radius: 50%; background-size: cover; }
/* The eclipse plays out on a slow loop: the moon drifts over the sun to totality (a pale corona blooms, a diamond-ring
   flash as it closes), then drifts back off. Sizes in % so the small-screen version scales with it. */
.home-eclipse { --pass: 22s; } /* slow, so the eclipse feels like an event */
.he-sun { inset: 14%; background-image: url("art/sun.webp"), radial-gradient(#FFF8E4, #FFD27A 55%, #F2994A); box-shadow: 0 0 40px 10px rgba(255, 190, 90, .32); }
.he-moon { inset: 12.5%; background-image: url("art/moon.webp"), radial-gradient(circle at 40% 35%, #1E2236, #05060B 75%); box-shadow: inset 0 0 0 1px #4A507066;
  transform: translate(30%, -14%); animation: moon-pass var(--pass) cubic-bezier(.45, 0, .55, 1) infinite; will-change: transform; }
.home-eclipse::before { content: ''; position: absolute; inset: 2%; border-radius: 50%; opacity: 0; pointer-events: none;
  background: radial-gradient(circle, transparent 50%, rgba(255, 248, 228, .6) 54.5%, rgba(255, 133, 82, .28) 61%, rgba(255, 133, 82, .08) 68%, transparent 74%);
  animation: corona var(--pass) ease-in-out infinite; }
.home-eclipse::after { content: ''; position: absolute; top: 22%; right: 22%; width: 7px; height: 7px; border-radius: 50%; background: #FFFFFF; opacity: 0; pointer-events: none;
  box-shadow: 0 0 10px 4px rgba(255, 248, 228, .9), 0 0 0 1px rgba(255, 255, 255, .6); animation: diamond var(--pass) ease-out infinite; }
@keyframes moon-pass { 0%, 100% { transform: translate(30%, -14%); } 46%, 56% { transform: translate(0, 0); } }
@keyframes corona { 0%, 38%, 64%, 100% { opacity: 0; transform: scale(.88); } 48%, 54% { opacity: 1; transform: scale(1); } }
@keyframes diamond { 0%, 41%, 47.5%, 100% { opacity: 0; transform: scale(.3); } 44% { opacity: 1; transform: scale(1); } }
.home-title { font: 400 clamp(1.9rem, 1.4rem + 2.4vw, 2.7rem)/1.1 var(--serif); margin: 10px 0 8px; text-wrap: balance; }
.home-lede { max-width: 420px; text-wrap: balance; }
.home-status { min-height: 2.8em; margin: 14px 0 4px; /* two lines reserved: the script fills it after the word list loads, and a phone wraps it, so the centred start screen would jump */ color: var(--gold); font-size: .95rem; }
.home-start { min-width: 220px; min-height: 52px; margin-top: 6px; font-size: 1rem; letter-spacing: .14em; display: inline-flex; align-items: center; justify-content: center; gap: 10px; }
.home-start .spinner { display: none; width: 16px; height: 16px; border-width: 2px; border-color: #0E102055; border-top-color: var(--gold-ink); }
.home-start.loading .spinner { display: inline-block; }
.home-start.loading { letter-spacing: .04em; text-transform: none; }
.home-links { margin: 18px 0 0; font-size: .9rem; color: var(--faint); }
@media (prefers-reduced-motion: reduce) { .home:not([hidden]) { animation: none; } }
/* On the start screen the date is shown in the hero; no need to repeat it in the header. */
.game:has(#home:not([hidden])) .dateline { visibility: hidden; }
@media (max-height: 700px) { .home { padding: 8px 8px 16px; } .home-eclipse { width: 96px; height: 96px; margin-bottom: 10px; } .home-status { margin-top: 8px; } }
/* The archive list is filled in by a script; reserve room so the footer doesn't jump down when it appears. */
.archive-list:empty { min-height: 60vh; }
.home-start { white-space: nowrap; height: 52px; } /* same size while loading and after, so the start screen never reflows */
/* Pages that load their content after a sign-in check: hold the space while loading so the footer starts below the screen. */
#loading:not([hidden]) { min-height: 75vh; }

/* End-of-day answers card (app.js answersCard) */
.ans-legend { margin: 6px 0 2px; }
.ans-level { border-top: 1px solid var(--line); padding: 14px 0 6px; }
.ans-level:first-of-type { border-top: 0; }
.ans-head { margin: 0 0 4px; font-size: .9rem; line-height: 1.4; }
.ans-head b { color: var(--gold); margin-right: 6px; font-weight: 600; }
.ans-you { margin: 0 0 8px; }
.ans-sub { margin: 0 0 6px; font: 600 .8rem/1.2 var(--sans); color: var(--muted); }
.ans-chips { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; padding: 0; margin: 0 0 6px; }
.ans-chip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border: 1px solid var(--line-strong); border-radius: 999px; font-size: .9rem; background: rgba(14, 16, 32, .5); }
.ans-chip .ans-n { font-size: .75rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.ans-chip.you { border-color: var(--gold); color: var(--gold); }
.ans-chip.you .ans-n { color: var(--gold); }
.ans-chip.none { border-style: dashed; color: var(--muted); }
.ans-more { min-height: 0; padding: 5px 12px; border-radius: 999px; font-size: .8rem; letter-spacing: .04em; text-transform: none; }
.ans-pop { margin: 4px 0 0; }

.r-answers { margin: 8px 0 0; }
.summary-list.tally li { grid-template-columns: 1.6em 1fr auto; }
.summary-list.tally li::before { content: none; }

/* ---------------------------------------------------------------- End-of-day answers (app.js answersCard) */
.ar-rule { margin-top: 0 !important; }
.ar-title { color: var(--gold); }
.ar-hint { letter-spacing: .14em; }
.ar-levels { list-style: none; padding: 0; margin: 0; }
.ar { border-top: 1px solid var(--line); }
.ar:first-child { border-top: 0; }
.ar-row { display: grid; grid-template-columns: 1.4em 1.6em 1fr auto 1.2em; align-items: center; gap: 8px; width: 100%; padding: 12px 2px;
  background: transparent; border: 0; box-shadow: none; border-radius: 6px; text-align: left; text-transform: none; letter-spacing: 0; font: inherit; min-height: 0; }
.ar-row:hover { background: var(--raise); }
.ar-n { color: var(--faint); font-size: .8rem; font-variant-numeric: tabular-nums; text-align: center; }
.ar-moon { font-size: 1rem; line-height: 1; }
.ar-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ar-labels { font: 500 .8rem/1.35 var(--sans); color: var(--muted); }
.ar-ans { font-weight: 600; font-size: 1.02rem; overflow-wrap: anywhere; }
.ar-count { font-size: .78rem; color: var(--muted); }
.ar-count b { color: var(--gold); font-weight: 600; }
.ar-pts { font-weight: 700; font-variant-numeric: tabular-nums; color: var(--muted); }
.ar-pts.totalipse { color: var(--gold); }
.ar-chev::before { content: '+'; color: var(--faint); font-size: 1.1rem; }
.ar-row[aria-expanded="true"] .ar-chev::before { content: '−'; }
.ar-panel { padding: 2px 0 14px; }
.ar-panel:not([hidden]) { animation: fade-in .2s ease-out; }
.ar-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 10px; }
.ar-tab { min-height: 0; padding: 6px 10px; font-size: .74rem; letter-spacing: .02em; text-transform: none; border-radius: 6px; background: rgba(14, 16, 32, .5); }
.ar-tab[aria-selected="true"] { border-color: var(--gold); color: var(--gold); }
.ar-tab-n { color: var(--faint); margin-left: 2px; font-variant-numeric: tabular-nums; }
.ar-tab[aria-selected="true"] .ar-tab-n { color: var(--gold); }
.ar-search { width: 100%; min-height: 40px; margin: 0 0 8px; padding: 8px 12px; background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--radius); font-size: max(16px, .95rem); }
.ar-search:focus-visible { outline: none; border-color: var(--gold); }
.ar-list { list-style: none; padding: 0 4px 0 0; margin: 0; max-height: 340px; overflow-y: auto; overscroll-behavior: contain; border: 1px solid var(--line); border-radius: var(--radius); }
.ar-item { display: grid; grid-template-columns: 1.6em 1fr auto 4.2em; align-items: center; gap: 8px; padding: 8px 10px; border-top: 1px solid var(--line); font-size: .92rem; }
.ar-item:first-child { border-top: 0; }
.ar-item.you { background: #FF855214; }
.ar-word { overflow-wrap: anywhere; }
.ar-word em { font-style: normal; font: 600 .54rem/1 var(--mono); letter-spacing: .07em; text-transform: uppercase; color: var(--gold); margin-left: 6px; }
.ar-dots { display: inline-flex; gap: 3px; }
.ar-dots i { width: 6px; height: 6px; border-radius: 50%; border: 1px solid var(--line-strong); }
.ar-dots i.on { background: var(--gold); border-color: var(--gold); }
.ar-plays { text-align: right; font-size: .75rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.ar-foot { display: flex; justify-content: space-between; margin: 6px 2px 0; }
.ar-pop { margin: 6px 2px 0; }
@media (max-width: 420px) { .ar-item { grid-template-columns: 1.4em 1fr auto 3.4em; gap: 6px; padding: 8px; } .ar-row { gap: 6px; } }

/* ---------------------------------------------------------------- A new day: the transition into each level */
/* A line of first light lifts off the horizon and thins out as it climbs; the glow behind the hills blooms and settles. */
#sky .dawn { position: absolute; inset: 0; opacity: 0; pointer-events: none;
  background: radial-gradient(130% 55% at 50% 108%, rgba(255, 196, 120, .55), rgba(255, 150, 96, .22) 38%, transparent 66%); }
#sky .dawn::after { content: ''; position: absolute; left: -10%; right: -10%; bottom: 9%; height: 2px; opacity: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 232, 186, .95) 30%, rgba(255, 246, 222, 1) 50%, rgba(255, 232, 186, .95) 70%, transparent);
  box-shadow: 0 0 22px 6px rgba(255, 196, 120, .35); }
#sky .dawn.go { animation: dawn-glow 2.8s cubic-bezier(.25, .6, .3, 1) both; }
@keyframes dawn-glow { 0% { opacity: 0; transform: translateY(10%); } 30% { opacity: 1; } 100% { opacity: 0; transform: none; } }
@keyframes dawn-line { 0% { opacity: 0; transform: translateY(0) scaleX(.6); } 18% { opacity: 1; } 100% { opacity: 0; transform: translateY(-62vh) scaleX(1); } }
/* The sun comes up into place; the level title settles in. (The moons fan out from behind it in board.js.) */
.puzzle-title.enter { animation: title-in .5s ease-out both; }
@keyframes title-in { from { opacity: 0; letter-spacing: .32em; } to { opacity: 1; letter-spacing: .2em; } }
@media (prefers-reduced-motion: reduce) { #sky .dawn { display: none; } .puzzle-title.enter { animation: none; } }

/* ---------------------------------------------------------------- Start screen: tiles for the other ways to play */
.home-modes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; width: 100%; max-width: 480px; margin-top: 22px; }
.mode-tile { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding: 12px 12px 11px; text-align: left; text-decoration: none; color: var(--text);
  background: rgba(14, 16, 32, .55); border: 1px solid var(--line-strong); border-radius: 10px; backdrop-filter: blur(2px);
  transition: border-color .2s ease, background-color .2s ease, transform .15s ease; }
.mode-tile svg { width: 20px; height: 20px; color: var(--gold); flex: none; }
.mode-tile b { display: block; font: 600 .8rem/1.2 var(--sans); letter-spacing: .06em; }
.mode-tile small { display: block; margin-top: 2px; font-size: .72rem; line-height: 1.3; color: var(--muted); }
.mode-tile:hover, .mode-tile:focus-visible { border-color: var(--gold); background: rgba(26, 30, 60, .7); }
.mode-tile:active { transform: scale(.98); }
.home-modes:has(> :nth-child(2):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 340px; }
@media (max-width: 420px) {
  .home-modes { grid-template-columns: 1fr; max-width: 300px; gap: 6px; }
  .home-modes:has(> :nth-child(2):last-child) { grid-template-columns: 1fr; }
  .mode-tile { flex-direction: row; align-items: center; gap: 12px; padding: 10px 12px; }
}
@media (prefers-reduced-motion: reduce) { .mode-tile { transition: none; } .mode-tile:active { transform: none; } }
@media (max-width: 520px) { .ar-rule { flex-wrap: wrap; gap: 4px 10px; } .ar-rule::after { display: none; } .ar-hint { flex-basis: 100%; letter-spacing: .1em; } }

/* Start screen entrance: everything floats up into place, one after another. */
.home:not([hidden]) > * { animation: home-in .7s cubic-bezier(.2, .7, .2, 1) both; }
.home:not([hidden]) > :nth-child(2) { animation-delay: .08s; }
.home:not([hidden]) > :nth-child(3) { animation-delay: .16s; }
.home:not([hidden]) > :nth-child(4) { animation-delay: .24s; }
.home:not([hidden]) > :nth-child(5) { animation-delay: .3s; }
.home:not([hidden]) > :nth-child(6) { animation-delay: .36s; }
.home:not([hidden]) > :nth-child(7) { animation-delay: .44s; }
@keyframes home-in { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
/* Play: now and then a soft band of light sweeps across the button. */
.home-start { position: relative; overflow: hidden; }
.home-start:not(.loading)::after { content: ''; position: absolute; inset: 0; pointer-events: none; transform: translateX(-120%);
  background: linear-gradient(105deg, transparent 35%, rgba(255, 255, 255, .42) 50%, transparent 65%); animation: sweep 6s ease-in-out 1.4s infinite; }
@keyframes sweep { 0%, 72% { transform: translateX(-120%); } 100% { transform: translateX(120%); } }
/* Mode tiles: a small lift on hover, the icon nudges. */
.mode-tile svg { transition: transform .25s cubic-bezier(.3, 1.5, .5, 1); }
.mode-tile:hover { transform: translateY(-2px); }
.mode-tile:hover svg { transform: translateY(-1px) scale(1.12); }
@media (prefers-reduced-motion: reduce) {
  .he-moon, .home-eclipse::before, .home-eclipse::after, .home:not([hidden]) > *, .home-start::after { animation: none; }
  .he-moon { transform: translate(30%, -14%); }
  .mode-tile:hover, .mode-tile:hover svg { transform: none; }
}

/* ---------------------------------------------------------------- The logo: an eclipse inside the name */
/* Both O's are moons drawn in CSS so they sit on the serif's x-height: a waxing crescent (a thin edge of gold light),
   then a total eclipse (the dark moon inside a faint corona). */
.logo { display: inline-flex; align-items: baseline; color: inherit; text-decoration: none; letter-spacing: .005em; }
.lo { display: inline-block; width: .5em; height: .5em; margin: 0 .035em; border-radius: 50%; position: relative; top: .01em; flex: none; }
.lo-cres { background: #11142A; box-shadow: inset .13em -.03em 0 0 #FF8552, 0 0 0 1px rgba(255, 133, 82, .35); }
.lo-total { background: radial-gradient(circle at 40% 36%, #1E2236, #05060B 78%); box-shadow: 0 0 0 1.5px rgba(255, 248, 228, .85), 0 0 8px 2px rgba(255, 133, 82, .45); }
.logo:hover .lo-cres { box-shadow: inset .5em 0 0 0 #FF8552, 0 0 0 1px rgba(255, 133, 82, .5); transition: box-shadow .6s cubic-bezier(.4, 0, .2, 1); }
.lo-cres { transition: box-shadow .6s cubic-bezier(.4, 0, .2, 1); }
@media (prefers-reduced-motion: reduce) { .lo-cres { transition: none; } }

/* End of the day: the other ways to play, as the start screen's tiles */
.more-modes { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px; margin-top: 10px; }

/* ---------------------------------------------------------------- Start screen: the other ways to play, as a moon-phase rail */
/* No boxes: one hairline rail, three stops. Each stop has a small moon at its own phase (crescent, half, gibbous);
   hover or focus and that moon fills to full while the name warms to gold and a hairline draws in beneath. */
.home-modes { display: flex; gap: 0; max-width: 600px; margin-top: 26px; padding: 0; border-block: 1px solid rgba(201, 212, 242, .14); }
.home-modes .mode-tile { flex: 1 1 0; position: relative; display: flex; flex-direction: row; align-items: center; gap: 11px; padding: 14px 16px;
  background: none; border: 0; border-radius: 0; backdrop-filter: none; transform: none; }
.home-modes .mode-tile + .mode-tile { border-left: 1px solid rgba(201, 212, 242, .12); }
.home-modes .mode-tile svg { display: none; }
.home-modes .mode-tile::before { content: ''; flex: none; width: 14px; height: 14px; border-radius: 50%; background: #10132A;
  box-shadow: inset -4px 0 0 0 var(--gold), 0 0 0 1px rgba(255, 133, 82, .35); transition: box-shadow .5s cubic-bezier(.4, 0, .2, 1); }
.home-modes .mode-tile:nth-child(2)::before { box-shadow: inset -7px 0 0 0 var(--gold), 0 0 0 1px rgba(255, 133, 82, .35); }
.home-modes .mode-tile:nth-child(3)::before { box-shadow: inset -10px 0 0 0 var(--gold), 0 0 0 1px rgba(255, 133, 82, .35); }
.home-modes .mode-tile::after { content: ''; position: absolute; left: 16px; right: 16px; bottom: -1px; height: 1px; background: var(--gold);
  transform: scaleX(0); transition: transform .35s cubic-bezier(.4, 0, .2, 1); }
.home-modes .mode-tile b { font: 400 1.18rem/1.1 var(--serif); letter-spacing: .005em; white-space: nowrap; transition: color .2s ease; }
.home-modes .mode-tile small { margin-top: 3px; white-space: nowrap; font: 500 .7rem/1.25 var(--sans); color: var(--muted); }
.home-modes .mode-tile:hover, .home-modes .mode-tile:focus-visible { background: none; transform: none; outline: none; }
.home-modes .mode-tile:hover::before, .home-modes .mode-tile:focus-visible::before { box-shadow: inset -14px 0 0 0 var(--gold), 0 0 0 1px rgba(255, 133, 82, .5), 0 0 10px 1px rgba(255, 133, 82, .45); }
.home-modes .mode-tile:hover::after, .home-modes .mode-tile:focus-visible::after { transform: scaleX(1); }
.home-modes .mode-tile:hover b, .home-modes .mode-tile:focus-visible b { color: var(--gold); }
.home-modes .mode-tile:active { transform: none; opacity: .8; }
@media (max-width: 520px) {
  /* Phones: the rail turns vertical, one stop per line, the caption on the right. */
  .home-modes { flex-direction: column; max-width: 340px; }
  .home-modes .mode-tile { padding: 13px 4px; }
  .home-modes .mode-tile + .mode-tile { border-left: 0; border-top: 1px solid rgba(201, 212, 242, .1); }
  .home-modes .mode-tile > span { display: flex; flex: 1; align-items: baseline; justify-content: space-between; gap: 12px; }
  .home-modes .mode-tile small { margin: 0; text-align: right; }
  .home-modes .mode-tile::after { left: 4px; right: 4px; }
}
@media (prefers-reduced-motion: reduce) { .home-modes .mode-tile::before, .home-modes .mode-tile::after { transition: none; } }


/* ================================================================ The almanac: type and plates */
/* Fraunces everywhere it appears: rounded terminals and the leaning letters on; optical size follows the font size. */
:root { font-variation-settings: "SOFT" 100, "WONK" 1; }
.page-title, .home-title, .tier-name, .sheet-head h2, .prose > h1.tier-name { font-weight: 360; letter-spacing: -.015em; }
.home-title { font-size: clamp(2.1rem, 1.5rem + 2.8vw, 3.1rem); line-height: 1.02; }
.wordmark { font-weight: 420; letter-spacing: -.01em; }
.big-score, .w-score, .points span:first-child, .friend-code { font-weight: 300; font-variant-numeric: lining-nums tabular-nums; letter-spacing: -.02em; }
.big-score .muted { font-weight: 300; }

/* Labels read like instrument readouts: mono, a short lead line in front of section labels. */
.puzzle-title { font-stretch: 87.5%; font-weight: 500; }

#home-date, .home-date { font: 600 .82rem/1.3 var(--sans); }
.ladder li, .c-tick { font-family: var(--mono); font-stretch: 87.5%; }
.stats dd { font-family: var(--serif); font-weight: 300; font-size: 2.1rem; font-variant-numeric: lining-nums tabular-nums; }
.stats dt { font-size: .58rem; letter-spacing: .06em; text-transform: uppercase; }
.site-footer { font: 400 .62rem/1.6 var(--mono); font-stretch: 87.5%; letter-spacing: .04em; }

/* Cards are plates from a star atlas: square-ish, a hairline frame, gold registration ticks in the corners and a faint
   inner glow along the top edge. */
.card { border-radius: 3px; border-color: rgba(201, 212, 242, .11);
  --tick: rgba(255, 133, 82, .55);
  background:
    linear-gradient(var(--tick), var(--tick)) top left / 9px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) top left / 1px 9px no-repeat,
    linear-gradient(var(--tick), var(--tick)) top right / 9px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) top right / 1px 9px no-repeat,
    linear-gradient(var(--tick), var(--tick)) bottom left / 9px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) bottom left / 1px 9px no-repeat,
    linear-gradient(var(--tick), var(--tick)) bottom right / 9px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) bottom right / 1px 9px no-repeat,
    linear-gradient(180deg, rgba(201, 212, 242, .045), transparent 38%),
    var(--panel); }

/* The answer box: a field on the plate, with the cursor in gold. */
#answer { caret-color: var(--gold); }
#answer::placeholder { font-family: var(--serif); font-size: 1.08em; color: var(--faint); letter-spacing: 0; }

/* Circle names on the board: a little more presence. */
.board-label { font-weight: 500; letter-spacing: .01em; }

/* The share card prints like a readout. */
.share { font: 500 1.05rem/1.5 var(--mono); font-stretch: 87.5%; letter-spacing: .02em; }

/* End of the day: "Keep playing" uses the start screen's moon-phase rail, stacked (the card is narrow). */
.more-modes { display: flex; flex-direction: column; gap: 0; margin-top: 8px; border-block: 1px solid rgba(201, 212, 242, .14); }
.more-modes .mode-tile { position: relative; display: flex; flex-direction: row; align-items: center; gap: 11px; padding: 13px 4px;
  background: none; border: 0; border-radius: 0; backdrop-filter: none; transform: none; }
.more-modes .mode-tile + .mode-tile { border-top: 1px solid rgba(201, 212, 242, .1); }
.more-modes .mode-tile svg { display: none; }
.more-modes .mode-tile::before { content: ''; flex: none; width: 14px; height: 14px; border-radius: 50%; background: #10132A;
  box-shadow: inset -4px 0 0 0 var(--gold), 0 0 0 1px rgba(255, 133, 82, .35); transition: box-shadow .5s cubic-bezier(.4, 0, .2, 1); }
.more-modes .mode-tile:nth-child(2)::before { box-shadow: inset -7px 0 0 0 var(--gold), 0 0 0 1px rgba(255, 133, 82, .35); }
.more-modes .mode-tile > span { display: flex; flex: 1; align-items: baseline; justify-content: space-between; gap: 12px; }
.more-modes .mode-tile b { font: 400 1.18rem/1.1 var(--serif); transition: color .2s ease; }
.more-modes .mode-tile small { margin: 0; white-space: nowrap; text-align: right; font: 500 .74rem/1.25 var(--sans); color: var(--muted); }
.more-modes .mode-tile:hover, .more-modes .mode-tile:focus-visible { background: none; transform: none; outline: none; }
.more-modes .mode-tile:hover::before, .more-modes .mode-tile:focus-visible::before { box-shadow: inset -14px 0 0 0 var(--gold), 0 0 0 1px rgba(255, 133, 82, .5), 0 0 10px 1px rgba(255, 133, 82, .45); }
.more-modes .mode-tile:hover b, .more-modes .mode-tile:focus-visible b { color: var(--gold); }
@media (prefers-reduced-motion: reduce) { .more-modes .mode-tile::before { transition: none; } }

/* ---------------------------------------------------------------- Sunrise behind the hills (sky.js sunrise) */
#sky .hills, #sky .hills-tint { position: absolute; inset: 0; pointer-events: none; }
#sky .hills { background: url("art/hills-wide.webp") center bottom / cover no-repeat; }
/* the hills' share of the daylight tint: the same gradient as .daylight, masked to the hills */
#sky .hills-tint { opacity: var(--day, 0); transition: opacity var(--day-ms, 1.4s) ease-in-out var(--day-delay, .3s);
  background: linear-gradient(180deg, #173057 0%, #203E6B 50%, #28466F 80%, rgba(40, 70, 111, .55) 90%, rgba(40, 70, 111, 0) 97%);
  -webkit-mask: url("art/hills-wide.webp") center bottom / cover no-repeat; mask: url("art/hills-wide.webp") center bottom / cover no-repeat; }
@media (orientation: portrait) {
  #sky .hills { background-image: url("art/hills-tall.webp"); }
  #sky .hills-tint { -webkit-mask-image: url("art/hills-tall.webp"); mask-image: url("art/hills-tall.webp"); }
}
#sky .sky-sun { position: absolute; left: 0; top: 0; width: 72px; height: 72px; border-radius: 50%; opacity: 0; will-change: transform, filter;
  background: url("art/sun.webp") center / cover, radial-gradient(circle, #FFF8E4, #FFD27A 55%, #F2994A);
  box-shadow: 0 0 34px 10px rgba(255, 210, 122, .45), 0 0 110px 36px rgba(255, 168, 88, .22); }
@media (prefers-reduced-motion: reduce) { #sky .sky-sun { display: none; } }

/* ---- Answer reveal: slow, shaky, rewarding ---- */
/* The result card and end-of-day cards let the sky show through. */
#result.card, .summary .card { background: rgba(17, 20, 42, .55); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
/* The checklist goes through the circles one by one, each line appearing as its moon lands (--d set in app.js). */
.checklist li { opacity: 0; animation: ck-in .55s cubic-bezier(.2, .7, .2, 1) var(--d, 0ms) forwards; }
.checklist .fits svg { animation: ck-pop .5s cubic-bezier(.3, 1.6, .5, 1) var(--d, 0ms) both; }
@keyframes ck-in { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: none; } }
@keyframes ck-pop { 0% { transform: scale(.4); } 70% { transform: scale(1.25); } 100% { transform: scale(1); } }
/* Each moon that lands gives the board a small bump; the last one on a Total Eclipse shakes it. */
.board svg.bump { animation: board-bump .35s ease-out; }
.board svg.quake { animation: board-quake .9s cubic-bezier(.36, .07, .19, .97); }
@keyframes board-bump { 0%, 100% { translate: 0 0; } 30% { translate: 2px -1px; } 60% { translate: -2px 1px; } }
@keyframes board-quake { 0%, 100% { translate: 0 0; rotate: 0deg; } 10% { translate: -4px 2px; rotate: -.6deg; } 25% { translate: 5px -3px; rotate: .7deg; }
  40% { translate: -4px 3px; rotate: -.5deg; } 55% { translate: 3px -2px; rotate: .4deg; } 70% { translate: -2px 1px; rotate: -.2deg; } 85% { translate: 1px 0; } }
/* Totality blooms slowly: the corona grows and pulses, the diamond ring flashes longer. */
.board .corona { transition: opacity 1.4s ease-out, transform 1.8s cubic-bezier(.2, .8, .2, 1); }
.board .blackout { transition: opacity .9s ease-in; }
.board svg.total .corona { animation: corona-pulse 3.2s ease-in-out 1.8s infinite; }
.board svg.total .diamond { animation: ring 1.4s ease-out .5s both; }
@keyframes corona-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .72; } }
/* The looping start-screen eclipse wobbles a little as it passes. */
.he-moon { animation: moon-pass var(--pass) cubic-bezier(.45, 0, .55, 1) infinite, moon-jitter 1.1s ease-in-out infinite; }
@keyframes moon-jitter { 0%, 100% { translate: 0 0; } 25% { translate: 1px -1px; } 50% { translate: -1px 1px; } 75% { translate: 1px 1px; } }
@media (prefers-reduced-motion: reduce) {
  .checklist li { opacity: 1; animation: none; } .checklist .fits svg { animation: none; }
  .board svg.bump, .board svg.quake, .board svg.total .corona { animation: none; } .he-moon { animation: none; }
}

/* ---- Drifting clouds (built in sky.js), behind the hills ---- */
#sky .clouds { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
#sky .cloud { position: absolute; left: -35%; top: var(--y); width: var(--w); height: calc(var(--w) * .34);
  opacity: calc(var(--o) * (.55 + var(--day, 0) * .9)); filter: blur(7px); animation: cloud-drift var(--t) linear var(--d) infinite; will-change: transform; }
#sky .cloud span { position: absolute; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(196, 206, 236, .34), rgba(150, 165, 205, .16) 60%, transparent); }
@keyframes cloud-drift { from { transform: translateX(0); } to { transform: translateX(calc(100vw + 70%)); } }
@media (prefers-reduced-motion: reduce) { #sky .cloud { animation: none; left: calc(var(--y) * 2); } }

/* ================================================================ Theme v2: ink and ember ====
   A screen-printed look: flat colour, solid edges and hard offset shadows instead of gradients, glass and glow.
   The sky, hills, stars, sun and moons are all drawn in code (no photos). Everything below overrides the rules above. */
:root {
  --bg: #090D20;
  --panel: #10153A;
  --card: #151B45;
  --raise: #1D2558;
  --text: #F4EDE0;
  --muted: #AEB4D2;
  --faint: #7A82AC;
  --line: #262E60;
  --line-strong: #3C4688;
  --gold: #FF8552;        /* the accent, ember (the variable keeps its old name) */
  --gold-ink: #1A0D06;
  --ice: #8FE3CF;         /* a moonlit mint for things that fit */
  --shadow: #04061A;
  --radius: 12px;
}
:root[data-contrast="high"] { --muted: #D8DCEF; --faint: #B4BAD8; --line: #454E90; --line-strong: #6570BC; --text: #FFFFFF; }
::selection { background: var(--gold); color: var(--gold-ink); }
:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* ---- Sky: banded dusk, drawn stars, orbit lines, print grain ---- */
#sky, #sky.painted { background:
  linear-gradient(180deg, #060918 0 22%, #080D25 23% 40%, #0C1434 41% 55%, #131A47 56% 66%, #221E5A 67% 74%, #452769 75% 80%, #86396A 81% 85%, #D36046 86% 89%, #F4A75B 90% 100%); }
@media (orientation: portrait) { #sky.painted { background-image: linear-gradient(180deg, #060918 0 26%, #080D25 27% 46%, #0C1434 47% 61%, #131A47 62% 71%, #221E5A 72% 79%, #452769 80% 84%, #86396A 85% 87.5%, #D36046 88.5% 91%, #F4A75B 92% 100%); } }
#sky::before { content: ''; position: absolute; inset: 0; pointer-events: none; opacity: calc(1 - var(--day, 0) * .6);
  background: repeating-radial-gradient(circle at 50% 40%, transparent 0 139px, rgba(244, 237, 224, .05) 139px 140px); }
#sky::after { content: ''; position: absolute; inset: 0; pointer-events: none; opacity: .5; mix-blend-mode: overlay;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .55 -.12'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"); }
#sky .daylight, #sky .hills-tint { background: linear-gradient(180deg, #0F2F60 0%, #19498A 50%, #2A6EA6 80%, rgba(42, 110, 166, .55) 90%, rgba(42, 110, 166, 0) 97%); }
#sky .starfield { position: absolute; inset: 0 0 22% 0; opacity: calc(1 - var(--day, 0)); transition: opacity var(--day-ms, 1.4s) ease-in-out var(--day-delay, .3s); }
#sky .starfield svg { display: block; width: 100%; height: 100%; }
#sky .starfield .tw { animation: twinkle var(--t, 4s) ease-in-out var(--d, 0s) infinite; }
@keyframes twinkle { 0%, 100% { opacity: 1; } 50% { opacity: .15; } }
#sky .hills { background: url("art/hills.svg") center bottom / max(100%, 1100px) auto no-repeat; }
#sky .hills-tint { -webkit-mask: url("art/hills.svg") center bottom / max(100%, 1100px) auto no-repeat; mask: url("art/hills.svg") center bottom / max(100%, 1100px) auto no-repeat; }
@media (orientation: portrait) {
  #sky .hills { background-image: url("art/hills.svg"); }
  #sky .hills-tint { -webkit-mask-image: url("art/hills.svg"); mask-image: url("art/hills.svg"); }
}
#sky .sky-sun { background: radial-gradient(circle, #FFF0C2 0, #FFC15C 52%, #FF7F45 100%); box-shadow: 0 0 0 8px rgba(255, 133, 82, .16), 0 0 0 20px rgba(255, 133, 82, .07); }
/* Clouds: flat stacked bars, like cut paper, drifting at their own speeds. */
#sky .cloud { position: absolute; left: -30%; top: var(--y); width: var(--w); height: auto; filter: none; opacity: calc(var(--o) * (.5 + var(--day, 0) * .8));
  display: flex; flex-direction: column; gap: 5px; animation: cloud-drift var(--t) linear var(--d) infinite; will-change: transform; }
#sky .cloud span { position: static; display: block; height: 9px; border-radius: 99px; background: #C9D0F0; }
@media (prefers-reduced-motion: reduce) { #sky .starfield .tw { animation: none; } }

/* ---- Surfaces: solid ink plates with a hard shadow ---- */
.card { border-radius: 16px; border: 1.5px solid var(--line-strong); background: var(--panel); }
#result.card, .summary .card { background: rgba(16, 21, 58, .58); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
.sheet { border-radius: 18px; border: 1.5px solid var(--line-strong); box-shadow: none; }
.row { border: 1.5px solid var(--line-strong); border-radius: 14px; background: var(--card); transition: border-color .15s; }
.icon-btn { border-radius: 12px; border: 1.5px solid var(--line-strong); background: var(--panel); box-shadow: 3px 3px 0 var(--shadow); transition: transform .08s, box-shadow .08s, border-color .15s; }
.icon-btn:hover { border-color: var(--gold); }
.icon-btn:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--shadow); }
.ladder li { border-radius: 8px; border-width: 1.5px; }
.ladder li.current { background: rgba(255, 133, 82, .1); }

/* ---- Buttons: flat ember, pressed down like a key ---- */
button.primary, a.button.primary, .row button {
  background: var(--gold); color: var(--gold-ink); border: 1.5px solid #FFB08A; border-radius: 14px;
  box-shadow: 0 5px 0 #B24A1F; font: 700 .97rem/1.2 var(--sans); letter-spacing: .01em;
  transition: transform .08s ease-out, box-shadow .08s ease-out, background .15s; }
button.primary, a.button.primary { border-radius: 14px; padding: 13px 24px; }
.row button { border-radius: 10px; box-shadow: 0 3px 0 #B24A1F; }
button.primary:hover, a.button.primary:hover, .row button:hover { background: #FF9668; }
button.primary:active, a.button.primary:active { transform: translateY(4px); box-shadow: 0 1px 0 #B24A1F; }
.row button:active { transform: translateY(2px); box-shadow: 0 1px 0 #B24A1F; }
button.primary::before, a.button.primary::before, .row button::before { background: #FFE9B8; box-shadow: inset -.34em .08em 0 0 var(--gold-ink), 0 0 0 1.5px var(--gold-ink); }
button.primary:hover::before, button.primary:focus-visible::before, a.button.primary:hover::before, .row button:hover::before, .row button:focus-visible::before {
  box-shadow: inset -.95em 0 0 0 var(--gold-ink), 0 0 0 1.5px var(--gold-ink); }
button.primary:disabled::before, .row button:disabled::before { box-shadow: inset -.34em .08em 0 0 var(--gold-ink), 0 0 0 1.5px var(--gold-ink); }
button.ghost, a.button:not(.primary), .actions-row > button:not(.primary), #sign-out, #copy-code, #email-create, #restart {
  border-radius: 14px; background: var(--panel); border: 1.5px solid var(--line-strong); box-shadow: 0 4px 0 var(--shadow);
  transition: transform .08s ease-out, box-shadow .08s ease-out, border-color .15s, color .15s; }
button.ghost:hover, a.button:not(.primary):hover, .actions-row > button:not(.primary):hover, #sign-out:hover, #copy-code:hover, #email-create:hover, #restart:hover {
  background: var(--panel); border-color: var(--gold); color: var(--gold); }
button.ghost:active, a.button:not(.primary):active, .actions-row > button:not(.primary):active, #sign-out:active, #copy-code:active, #email-create:active, #restart:active {
  transform: translateY(3px); box-shadow: 0 1px 0 var(--shadow); }
.home-start { box-shadow: 0 6px 0 #B24A1F; }

/* ---- Board: drawn sun and moons, rays on totality ---- */
.board .moon { stroke: #7C87D8; stroke-width: 1.1; }
.board .moon.miss { stroke: #6E78B8; }
.board .halo { fill: #FF8552; }
.board .rays { opacity: 0; transform-box: fill-box; transform-origin: center; transition: opacity .6s ease-out; }
.board .rays line { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 1.7s cubic-bezier(.2, .8, .2, 1) .45s; }
.board svg.total .rays { opacity: .9; animation: rays-turn 120s linear infinite; }
.board svg.total .rays line { stroke-dashoffset: 0; }
@keyframes rays-turn { to { transform: rotate(360deg); } }
.checklist .fits .verdict { color: var(--ice); }
.checklist .fits svg { color: var(--ice); }
@media (prefers-reduced-motion: reduce) { .board svg.total .rays { animation: none; } .board .rays line { transition: none; } }

/* ---- Start screen eclipse and logo, drawn flat ---- */
.he-sun { background-image: radial-gradient(circle, #FFF0C2 0, #FFC15C 52%, #FF7F45 100%); box-shadow: 0 0 0 7px rgba(255, 133, 82, .16), 0 0 0 17px rgba(255, 133, 82, .07); }
.he-moon { background-image: radial-gradient(circle at 34% 36%, #0A0F2C 0 11%, transparent 12%), radial-gradient(circle at 62% 60%, #0A0F2C 0 14%, transparent 15%), radial-gradient(circle at 60% 26%, #0A0F2C 0 6%, transparent 7%), linear-gradient(#131A45, #131A45);
  box-shadow: inset 0 0 0 1.5px rgba(124, 135, 216, .7); }
.lo-cres { background: var(--panel); box-shadow: inset .13em -.03em 0 0 var(--gold), 0 0 0 1px rgba(255, 133, 82, .4); }
.lo-total { background: #0A0F2C; box-shadow: 0 0 0 1.5px #FFE9B8; }
.home-title { text-wrap: balance; }
button.primary:focus-visible, a.button.primary:focus-visible, .row button:focus-visible { outline-color: #FFE9B8; }
/* Phones: fewer, smaller clouds so they don't crowd the text. */
#sky .cloud { opacity: calc(var(--o) * (.38 + var(--day, 0) * .9)); }
@media (max-width: 640px) { #sky .cloud { width: calc(var(--w) * .55); } #sky .cloud span { height: 7px; } #sky .cloud:nth-child(n+4) { display: none; } }
/* Reading pages scroll text over the bright horizon, so they get a dark wash along the bottom of the screen. */
body:not(:has(main.game))::after { content: ''; position: fixed; left: 0; right: 0; bottom: 0; height: 40vh; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(9, 13, 32, 0), rgba(9, 13, 32, .86) 60%); }
/* The start screen's links sit low, over the horizon: an ink plate keeps them readable. */
.home-modes { background: rgba(9, 13, 32, .62); border: 1.5px solid var(--line); border-radius: 14px; backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }

/* ---- Hits: each moon that lands sends out rings, squeezes the sun and pops its circle's name ---- */
.board .shock { fill: none; stroke: #FFE9B8; stroke-width: 2.2; pointer-events: none; transform-box: fill-box; transform-origin: center; animation: shock .65s cubic-bezier(.1, .7, .3, 1) forwards; }
.board .shock.late { stroke: #FF8552; animation-duration: .9s; animation-delay: .08s; opacity: 0; }
@keyframes shock { 0% { transform: scale(.9); opacity: .95; } 100% { transform: scale(2.1); opacity: 0; stroke-width: .2; } }
.board .sun.hit { animation: sun-hit .4s cubic-bezier(.3, 1.5, .5, 1); }
@keyframes sun-hit { 0% { transform: scale(1); } 30% { transform: scale(.9); } 100% { transform: scale(1); } }
.board-label.hit { animation: tag-hit .55s cubic-bezier(.3, 1.6, .5, 1); color: var(--ice); }
@keyframes tag-hit { 0% { scale: 1; } 40% { scale: 1.18; } 100% { scale: 1; } }
/* The checklist tick lands harder too. */
@keyframes ck-pop { 0% { transform: scale(.2) rotate(-25deg); } 60% { transform: scale(1.35) rotate(6deg); } 100% { transform: scale(1) rotate(0); } }

/* ---- Results: drawn eclipses for tiers, the day at a glance, and a chart made of stars ---- */
.phase { --c: 0; display: inline-block; width: 1em; height: 1em; border-radius: 50%; vertical-align: -.14em; flex: none;
  background: radial-gradient(circle, #FFF0C2 0, #FFC15C 55%, #FF7F45 100%); box-shadow: inset calc(var(--c) * -1em) 0 0 0 #0A0F2C, 0 0 0 1px rgba(255, 133, 82, .55); }
.phase.penumbra { --c: .24; } .phase.gibbous { --c: .44; } .phase.antumbra { --c: .62; } .phase.umbra { --c: .82; }
.phase.totalipse { background: #0A0F2C; box-shadow: 0 0 0 1.5px #FFE9B8, 0 0 0 4px rgba(255, 233, 184, .16); }
.day-strip { display: flex; justify-content: space-around; gap: 6px; margin: 14px 0 4px; padding: 16px 10px 12px; border: 1.5px solid var(--line); border-radius: 14px; background: rgba(9, 13, 32, .45); }
.day-strip:empty { display: none; }
.day-strip span { display: grid; justify-items: center; gap: 8px; animation: rise .5s cubic-bezier(.2, .7, .2, 1) var(--d, 0ms) both; }
.day-strip .phase { font-size: 2.2rem; }
.day-strip b { font: 600 .8rem/1 var(--sans); color: var(--muted); font-variant-numeric: tabular-nums; }
.summary-list .phase, .ar-moon .phase { font-size: 1.15rem; }
.big-score #s-score { color: var(--text); }
.starchart { margin: 12px 0 0; padding: 14px 10px 10px; border: 1.5px solid var(--line); border-radius: 14px; background: rgba(9, 13, 32, .45); }
.starchart svg { display: block; width: 100%; height: auto; overflow: visible; }
.starchart figcaption { margin-top: 4px; text-align: center; }
.sc-ground { stroke: var(--line-strong); stroke-width: 1.5; stroke-linecap: round; fill: none; }
.sc-tick { fill: var(--faint); font: 500 8px/1 var(--sans); font-variant-numeric: tabular-nums; }
.sc-star { fill: var(--text); opacity: 0; animation: sc-in .5s ease-out var(--d, 0ms) forwards; }
@keyframes sc-in { to { opacity: .9; } }
.sc-you-sun { fill: var(--gold); stroke: #FFE9B8; stroke-width: 1; }
.sc-you-ring { fill: none; stroke: var(--gold); stroke-width: 1; opacity: .55; transform-box: fill-box; transform-origin: center; animation: sc-pulse 2.6s ease-in-out infinite; }
@keyframes sc-pulse { 50% { transform: scale(1.4); opacity: .12; } }
.sc-you-label { fill: var(--gold); font: 700 9px/1 var(--sans); }
@media (prefers-reduced-motion: reduce) { .sc-star { opacity: .9; animation: none; } .sc-you-ring { animation: none; } .day-strip span { animation: none; } }
.phase.totalipse { background: radial-gradient(circle at 35% 35%, #1B2358, #0A0F2C 70%); box-shadow: 0 0 0 2px #FFE9B8, 0 0 0 5px rgba(255, 133, 82, .5); }
.wl-tier .phase { margin: 0 .3em 0 .2em; }
.day-strip .phase { margin: 4px; }

/* ---- Eclipse light: every tier has a clearly different sky. The daylight steps down in even amounts (app.js LIGHT)
   and this layer adds each tier's colour of light: a grey haze, then gold, copper, deep violet with a sunset glow
   all round the horizon (as in a real eclipse), and a faint ring of glow on the horizon at totality. ---- */
#sky .eclipse-light { position: absolute; inset: 0; z-index: 20; pointer-events: none; opacity: 0;
  transition: opacity 1.6s ease-in-out .3s, background 1.6s ease-in-out .3s; }
html[data-light="penumbra"] #sky .eclipse-light { opacity: 1; background:
  radial-gradient(ellipse at 50% 45%, transparent 40%, rgba(14, 18, 52, .38) 100%), linear-gradient(rgba(60, 70, 110, .22), rgba(60, 70, 110, .22)); }
html[data-light="gibbous"] #sky .eclipse-light { opacity: 1; background:
  radial-gradient(ellipse at 50% 45%, transparent 30%, rgba(30, 16, 40, .45) 100%), linear-gradient(180deg, rgba(70, 45, 60, .22), rgba(255, 180, 60, .55) 90%); }
html[data-light="antumbra"] #sky .eclipse-light { opacity: 1; background:
  radial-gradient(ellipse at 50% 45%, transparent 22%, rgba(12, 8, 40, .62) 100%), linear-gradient(180deg, rgba(30, 16, 70, .42), rgba(255, 115, 60, .46) 88%); }
html[data-light="umbra"] #sky .eclipse-light { opacity: 1; background:
  radial-gradient(ellipse at 50% 45%, transparent 15%, rgba(8, 4, 30, .72) 100%), linear-gradient(180deg, rgba(20, 8, 56, .55) 40%, rgba(255, 95, 60, .6) 92%); }
html[data-light="totalipse"] #sky .eclipse-light { opacity: 1; background:
  radial-gradient(ellipse at 50% 45%, transparent 20%, rgba(2, 2, 14, .55) 100%), linear-gradient(180deg, transparent 70%, rgba(255, 120, 60, .42) 96%); }
@media (prefers-reduced-motion: reduce) { #sky .eclipse-light { transition: none; } }

/* ---- Phones: while a level is on screen the page is locked (no scrolling, no bounce) and fitted to what's visible
   above the keyboard: header, board in all the space that's left, then the answer box or the result card.
   The result card scrolls inside itself if it's long, with Next always in reach. ---- */
@media (max-width: 859px) and (orientation: portrait) {
  html:has(#play:not([hidden])), html:has(#play:not([hidden])) body { overflow: hidden; overscroll-behavior: none; }
  html:has(#play:not([hidden])) body { position: fixed; inset: 0; width: 100%; height: 100%; touch-action: manipulation; }
  /* flex: none matters: body is a flex column and main would otherwise grow back to full height under the keyboard */
  main.game:has(#play:not([hidden])) { display: flex; flex-direction: column; flex: none; height: var(--vvh, 100dvh); max-height: var(--vvh, 100dvh); min-height: 0; overflow: hidden;
    transform: translateY(var(--vvtop, 0px)); padding-top: max(8px, env(safe-area-inset-top)); padding-bottom: max(10px, env(safe-area-inset-bottom)); }
  main.game:has(#play:not([hidden])) > :not(#play) { flex: none; }
  main.game:has(#play:not([hidden])) .top { margin-bottom: 2px; }
  main.game:has(#play:not([hidden])) .ladder { margin: 6px 0 2px; }
  .game #play:not([hidden]) { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; gap: 6px; }
  .game #play .stage { flex: 1 1 0; min-height: 110px; container-type: size; justify-content: center; }
  .game #play .board-wrap { width: min(100cqw, calc((100cqh - 3.4em) * 400 / 350)); }
  .game #play .panel { flex: none; max-height: 64%; min-height: 0; display: flex; flex-direction: column; }
  .game #play .guess > .small { display: none; } /* the how-to line is in the FAQ; on a phone the screen is for the board */
  .game #play .guess > label { margin-bottom: 4px; }
  .game #play #result:not([hidden]) { overflow-y: auto; overscroll-behavior: contain; min-height: 0; padding-bottom: 0; }
  .game #play #result #next { position: sticky; bottom: 0; margin-bottom: 14px; z-index: 1; }
  .game #play #status:empty, .game #play #suggest:empty { display: none; }
  /* Keyboard open: only the level, the board and the answer box, so it all fits in the space above the keyboard. */
  html.kb main.game:has(#play:not([hidden])) > :not(#play) { display: none; }
  html.kb main.game:has(#play:not([hidden])) { padding-top: 6px; padding-bottom: 6px; }
  html.kb .game #play .guess > label { display: none; }
  html.kb .game #play .stage { min-height: 0; }
}

/* ---- Circle names on the board: balanced lines, long names a touch smaller, examples on their own quiet line ---- */
.board-label { line-height: 1.18; text-wrap: balance; }
.board-label.long { font-size: clamp(10px, 3cqi, 15px); }
.board-label .ex { display: block; margin-top: 2px; font-size: max(10px, .86em); font-weight: 400; font-style: italic; letter-spacing: 0; color: var(--muted); }
.board-label.hit .ex { color: inherit; opacity: .8; }
/* The start-screen link plate: room for two links as well as three, and padding so nothing touches its edge. */
.home-modes, .home-modes:has(> :nth-child(2):last-child) { max-width: 600px; width: auto; padding: 0 8px; }
.home-modes:has(> :nth-child(2):last-child) { max-width: 500px; }
@media (max-width: 420px) {
  .home-modes, .home-modes:has(> :nth-child(2):last-child) { width: 100%; max-width: 340px; padding: 0 10px; }
  .home-modes .mode-tile { padding: 13px 6px; }
}

/* ================================================================ Theme v3: the relief print ====
   The same view from Earth, printed from hand-cut blocks. Every picture is an alpha mask of a proof (art/print/*.webp,
   generated art, see DESIGN_NOTES.md) and gets its colour here from an ink variable, so the whole scene can be re-inked
   as the light changes. sky.js sets the inks (its INKS table); the values below are the pre-dawn set, so the page is
   already inked before any script runs. Everything below overrides the rules above. */
:root {
  --bg: #0A1322;
  --panel: #0F1B2A;
  --card: #14243A;
  --raise: #1C3048;
  --text: #F4EDE0;
  --muted: #AEBAC8;
  --faint: #8494A6;
  --line: #22364B;
  --line-strong: #3A536C;
  --shadow: #04080F;
  --mono: var(--sans); /* two faces only: Fraunces italic for names and numbers, Space Grotesk for everything read */
  --sky-top: #0A1322; --sky-mid: #101E33; --sky-low: #1B2E44; --sky-hz: #4F6170; --cloud: #22344A;
  --far: #162536; --far-cut: #2D4258; --mid: #0F1B28; --mid-cut: #263A4E; --near: #080F18; --near-cut: #172636;
  --sun: #F2A24A; --sun-core: #FFD98A; --sun-rim: #E8552A; --moon: #0A1220; --moon-cut: #33475F; --glow-ink: #C8743A;
  --stars: .75; --bright: .9; --glow: 0; --lamp: 1;
  --on-sky: #D6DEE7; /* quieter words that sit straight on the sky: light enough for every ink the sky is rolled in */
  --paper: #F1EBDD; /* the unprinted sheet: stars, comets and the corona are cut out to it */
  --sun-inks: radial-gradient(closest-side, var(--sun-core) 0, var(--sun) 30%, var(--sun) 39%, var(--sun-rim) 46%, var(--sun) 47.5%, var(--sun) 100%);
}
:root[data-contrast="high"] { --muted: #D5DDE6; --faint: #B3C0CE; --line: #3A536C; --line-strong: #5C7A96; --text: #FFFFFF; }
html { background: var(--bg); }

/* One rule cuts every plate: the proof is the mask, the ink is the background. */
.sk-land i, .sk-hatch, .sk-stars i, .cloud, .sky-sun, .fl-art, .rook b, .bd-sun, .bd-corona i, .bd-diamond, .bd-blackout, .bd-moon i,
.he-sun::before, .he-moon, .he-moon::after, .home-eclipse::before, .home-eclipse::after {
  -webkit-mask: var(--art) var(--art-pos, center) / var(--art-size, 100% 100%) no-repeat; mask: var(--art) var(--art-pos, center) / var(--art-size, 100% 100%) no-repeat; }
/* No CSS masks (very old browsers): the blocks print as they were proofed, in black, without their second inks. */
@supports not ((-webkit-mask-image: none) or (mask-image: none)) {
  .sk-land .key, .cloud, .sky-sun, .fl-art, .rook b, .bd-sun, .bd-moon .key, .he-sun::before, .he-moon::after { background: var(--art) var(--art-pos, center) / var(--art-size, 100% 100%) no-repeat !important; }
  .sk-land .sil, .sk-hatch, .sk-stars, .sk-lamp, .bd-corona, .bd-diamond, .bd-blackout, .bd-moon .sil, .home-eclipse::before, .home-eclipse::after { display: none !important; }
  .he-moon { background: none !important; }
}

/* ---- The scene, back to front: sky roll, cleared-sky chatter, stars, horizon glow, rising sun, clouds, three land plates, paper tooth ---- */
#sky, #sky.painted { --W: max(100vw, 1100px); /* the land's width: never narrower than this, so a phone sees the middle of it */
  background: var(--sky-mid); }
#sky::before, #sky::after { content: none; }
#sky .daylight { display: none; }
#sky > * { position: absolute; pointer-events: none; }
/* A blended roll: two blues from the top, opening to the horizon ink just above the hills. */
.sk-roll { inset: 0; background: linear-gradient(to top, var(--sky-hz) calc(var(--W) * .1), var(--sky-low) calc(var(--W) * .178), var(--sky-mid) 62%, var(--sky-top) 97%); }
.sk-hatch { left: 0; right: 0; bottom: calc(var(--W) * .105); height: calc(var(--W) * .2); --art: url("art/print/sky-hatch.webp"); --art-size: max(100%, 1000px) 100%; background: var(--sky-mid); opacity: .5; }
.sk-stars { inset: 0 0 calc(var(--W) * .1) 0; }
.sk-stars.faint { opacity: var(--stars); } .sk-stars.bright { opacity: var(--bright); }
.sk-stars i { position: absolute; inset: 0; --art-size: max(1000px, 72vw) auto; --art-pos: 50% 0; -webkit-mask-repeat: repeat; mask-repeat: repeat; background: var(--paper); animation: print-twinkle 5.5s ease-in-out infinite alternate; }
.sk-stars.faint i { --art: url("art/print/stars-faint.webp"); }
.sk-stars.bright i { --art: url("art/print/stars-bright.webp"); animation-duration: 3.7s; }
@keyframes print-twinkle { from { opacity: 1; } to { opacity: .62; } }
#sky.starless .sk-stars { visibility: hidden; }
#sky.starless .sk-stars i { animation: none; }
/* The glow that stands all round the horizon in the dark of an eclipse. */
.sk-glow { left: 0; right: 0; bottom: 0; height: calc(var(--W) * .215); opacity: var(--glow); background: linear-gradient(to top, var(--glow-ink) 47%, transparent 100%); }
#sky .sky-sun { left: 0; top: 0; width: 160px; height: 160px; opacity: 0; will-change: transform; border-radius: 0; box-shadow: none; --art: url("art/print/sun.webp"); background: var(--sun-inks); }

.sk-clouds { inset: 0; overflow: hidden; }
#sky .cloud { position: absolute; left: 0; top: var(--y); --cw: calc(clamp(150px, 21vw, 340px) * var(--k, 1)); width: var(--cw); height: calc(var(--cw) * .35); display: block; filter: none; opacity: 1;
  background: var(--cloud); animation: print-drift var(--t, 200s) linear var(--d, 0s) infinite; will-change: transform; }
#sky .cloud.c1 { --art: url("art/print/cloud-1.webp"); height: calc(var(--cw) * .352); }
#sky .cloud.c2 { --art: url("art/print/cloud-2.webp"); height: calc(var(--cw) * .343); }
#sky .cloud.c3 { --art: url("art/print/cloud-3.webp"); height: calc(var(--cw) * .145); }
#sky .cloud.c4 { --art: url("art/print/cloud-4.webp"); height: calc(var(--cw) * .236); }
#sky .cloud.c5 { --art: url("art/print/cloud-5.webp"); --cw: calc(clamp(80px, 9vw, 150px) * var(--k, 1)); height: calc(var(--cw) * .505); }
@keyframes print-drift { from { transform: translateX(-110%); } to { transform: translateX(100vw); } }
/* One long streak of cloud lying on the horizon, in the horizon's own ink, half hidden by the far hills. */
#sky .cloud.low { top: auto; left: 8%; bottom: calc(var(--W) * .128); --cw: calc(var(--W) * .3); --art: url("art/print/cloud-3.webp"); height: calc(var(--cw) * .145);
  background: var(--sky-hz); opacity: .8; animation: print-low 260s ease-in-out infinite alternate; }
@keyframes print-low { from { transform: translateX(-6%); } to { transform: translateX(22%); } }

/* Land: each plate is two pulls of the same block. First its whole shape in the lighter ink (what shows in the cuts),
   then the cut block itself in the darker ink on top. */
.sk-land { left: 50%; width: var(--W); margin-left: calc(var(--W) / -2); }
.sk-land i { position: absolute; inset: 0; }
.sk-land.far { height: calc(var(--W) / 10.0174); bottom: calc(var(--W) * .068); }
.sk-land.mid { height: calc(var(--W) / 7.8102); bottom: calc(var(--W) * .006); }
.sk-land.near { height: calc(var(--W) / 4.3472); bottom: calc(var(--W) * -.05); }
.sk-land.far .sil { --art: url("art/print/land-far-sil.webp"); background: var(--far-cut); }
.sk-land.far .key { --art: url("art/print/land-far-key.webp"); background: var(--far); }
.sk-land.mid .sil { --art: url("art/print/land-mid-sil.webp"); background: var(--mid-cut); }
.sk-land.mid .key { --art: url("art/print/land-mid-key.webp"); background: var(--mid); }
/* the bank's own ground ink under the whole plate, so its cuts never open onto the bright horizon behind */
.sk-land.near::before { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 52%; background: var(--near-cut); }
.sk-land.near .sil { --art: url("art/print/land-near-sil.webp"); background: var(--near-cut); }
.sk-land.near .key { --art: url("art/print/land-near-key.webp"); background: var(--near); }
/* Lamplight in the house by the observatory: a spot of warm ink under the block, showing through its window cuts. */
.sk-land .sk-lamp { inset: auto; left: 64.1%; width: 2.5%; top: 24%; height: 8.5%; -webkit-mask: none; mask: none; background: #F4B860; opacity: calc(var(--lamp) * .9); }
/* Phones: the middle 46% of each plate, as its own smaller file. */
@media (max-width: 640px) {
  .sk-land { width: calc(var(--W) * .46); margin-left: calc(var(--W) * -.23); }
  .sk-land.far .sil { --art: url("art/print/land-far-sil-phone.webp"); } .sk-land.far .key { --art: url("art/print/land-far-key-phone.webp"); }
  .sk-land.mid .sil { --art: url("art/print/land-mid-sil-phone.webp"); } .sk-land.mid .key { --art: url("art/print/land-mid-key-phone.webp"); }
  /* the bank's own ground ink under the whole plate, so its cuts never open onto the bright horizon behind */
.sk-land.near::before { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 52%; background: var(--near-cut); }
.sk-land.near .sil { --art: url("art/print/land-near-sil-phone.webp"); } .sk-land.near .key { --art: url("art/print/land-near-key-phone.webp"); }
  .sk-land .sk-lamp { left: 80.7%; width: 5.4%; }
  #sky .sk-clouds .cloud:nth-child(n+4) { display: none; }
}
/* Paper tooth: specks of bare paper over the whole print, where the ink did not take. */
.sk-tooth { inset: 0; background: url("art/print/tooth.webp") 0 0 / 256px 256px; opacity: .26; }

/* ---- Life in the sky (sky.js): every sprite is a small block, inked to suit the light ---- */
.flyer { position: absolute; left: 0; top: 0; will-change: transform; }
.fl-art { display: block; background: var(--near); }
.flyer.flock, .flyer.roost { width: 300px; height: 160px; }
.rook { position: absolute; width: 48px; height: 59px; overflow: hidden; animation: print-bob var(--bob, 3s) ease-in-out var(--d, 0s) infinite alternate; }
.rook b { display: block; width: 288px; height: 59px; --art: url("art/print/rook-strip.webp"); background: var(--near); animation: print-flap var(--beat, .6s) steps(6) var(--d, 0s) infinite; }
.rook.glide b { animation: print-flap-glide calc(var(--beat, .6s) * 3.4) step-end var(--d, 0s) infinite; }
@keyframes print-bob { from { transform: translateY(-4px) scale(var(--s, .7)); } to { transform: translateY(5px) scale(var(--s, .7)); } }
@keyframes print-flap { to { transform: translateX(-100%); } }
/* two wingbeats, then a long glide on level wings */
@keyframes print-flap-glide { 0%, 36% { transform: none; } 6%, 42% { transform: translateX(-16.667%); } 12%, 48% { transform: translateX(-33.333%); } 18% { transform: translateX(-50%); } 24% { transform: translateX(-66.667%); } 30% { transform: translateX(-83.333%); } }
.flyer.balloon .fl-art { background: var(--sun-rim); }
.flyer.plane { width: 30px; height: 25px; }
.flyer.plane .jet { position: absolute; right: 0; top: 0; background: var(--sky-hz); }
.flyer.plane .trail { position: absolute; right: 27px; top: 5px; width: 520px; height: 29px; overflow: hidden; animation: print-trail-window 16s linear both; }
.flyer.plane .trail .fl-art { width: 520px; height: 29px; background: var(--sky-hz); opacity: .85; animation: print-trail 16s linear both; }
@keyframes print-trail-window { from { transform: translateX(100%); } to { transform: none; } }
@keyframes print-trail { from { transform: translateX(-100%); } to { transform: none; } }
.flyer .nav { position: absolute; width: 3px; height: 3px; border-radius: 50%; opacity: 0; }
.flyer.lit .nav { opacity: 1; }
.flyer .nav.port { right: 20px; top: 0; background: #F2553F; } .flyer .nav.star { right: 19px; top: 22px; background: #5FD68A; }
.flyer.lit .nav.strobe { right: 12px; top: 11px; background: #FFFFFF; opacity: 0; animation: strobe 1.6s infinite; }
.flyer.satellite .fl-art, .flyer.meteor .fl-art, .flyer.comet .fl-art { background: var(--paper); }
.flyer.satellite .fl-art { animation: print-glint 7s ease-in-out infinite; }
@keyframes print-glint { 0%, 44%, 56%, 100% { opacity: .55; } 50% { opacity: 1; } }
.flyer.meteor { transform-origin: 0 50%; } .flyer.meteor .fl-art { transform: translate(-100%, -50%); }
.flyer.comet .fl-art { transform: translate(-100%, -50%); }
/* A hidden tab, or Settings > Calm sky: the print holds still. */
#sky.asleep *, #sky.calm .cloud, #sky.calm .sk-stars i { animation-play-state: paused !important; }
#sky.calm .flyer { display: none; }
@media (prefers-reduced-motion: reduce) {
  .flyer { display: none; }
  #sky .cloud, .sk-stars i { animation: none; }
  #sky .sk-clouds .cloud { transform: translateX(calc(var(--y) * 14)); }
}

/* ---- The board: a printed sun, six different moons, the corona and the diamond ring ---- */
.board .bd-art, .board .bd-fx, .board .bd-sun-g, .board .bd-moons { position: absolute; inset: 0; }
.board svg.bd-fx { width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.bd-art > div, .bd-sun-g > div, .bd-moons > div { position: absolute; }
.bd-halo, .bd-sun, .bd-corona, .bd-blackout { height: 0; } /* squares: board.js gives each a width and the same bottom padding */
.bd-halo { border-radius: 50%; background: radial-gradient(closest-side, var(--sun-rim) 0, transparent 100%); opacity: .3; transition: opacity .8s; }
.bd-sun { --art: url("art/print/sun.webp"); background: var(--sun-inks); }
.bd-sun.hit { animation: sun-hit .4s cubic-bezier(.3, 1.5, .5, 1); }
.bd-blackout { --art: url("art/print/moons-sil.webp"); --art-size: 300% 200%; --art-pos: 0 0; background: var(--moon); opacity: 0; transition: opacity .9s ease-in; }
.bd-moon { left: 0; top: 0; height: 0; will-change: transform; }
.bd-moon i { position: absolute; inset: 0; --art-size: 300% 200%; --art-pos: 0 0; transition: opacity .6s ease; }
.bd-moon .sil { --art: url("art/print/moons-sil.webp"); background: var(--moon-cut); }
.bd-moon .key { --art: url("art/print/moons-key.webp"); background: var(--moon); }
.bd-moon.face1 i { --art-pos: 50% 0; } .bd-moon.face2 i { --art-pos: 100% 0; }
.bd-moon.face3 i { --art-pos: 0 100%; } .bd-moon.face4 i { --art-pos: 50% 100%; } .bd-moon.face5 i { --art-pos: 100% 100%; }
/* A circle the answer missed stays at home as a ghost proof: the block's cuts, barely inked. */
.bd-moon.miss .sil { opacity: 0; }
.bd-moon.miss .key { background: var(--paper); opacity: .2; }
/* Totality: the sun goes dark behind the moons, the corona opens out from a tighter, turned start, and the diamond flashes. */
.board.total .bd-blackout { opacity: 1; }
.board.total .bd-halo { opacity: 0; }
.bd-corona { opacity: 0; transform: scale(.7) rotate(-9deg); transition: opacity .3s ease-out, transform .3s ease-out; }
.board.warm .bd-corona { opacity: .012; }
.board.total .bd-corona { opacity: 1; transform: none; transition: opacity 1.5s ease-out .2s, transform 2.4s cubic-bezier(.2, .8, .2, 1) .2s; }
.bd-corona i { position: absolute; inset: 0; --art: url("art/print/corona.webp"); background: radial-gradient(closest-side, #FFFDF4 0 27%, #EFE6CF 50%, rgba(239, 230, 207, 0) 96%); }
.bd-corona i + i { transform: rotate(180deg) scale(1.07); opacity: .4; } /* a second, fainter pull of the same block, turned round */
.board.total .bd-corona i { animation: print-corona 5.2s ease-in-out 2.4s infinite alternate; }
.board.total .bd-corona i + i { animation: print-corona-2 6.6s ease-in-out 2.4s infinite alternate; }
@keyframes print-corona { to { opacity: .74; } }
@keyframes print-corona-2 { to { opacity: .72; } }
.bd-diamond { width: 12.5%; height: 0; padding-bottom: 9.8%; transform: translate(-50%, -50%) scale(.2); opacity: 0; --art: url("art/print/diamond.webp"); background: #FFFEF6; }
.board.total .bd-diamond { animation: print-diamond 1.5s cubic-bezier(.2, .8, .2, 1) .6s both, print-diamond-glint 3.4s ease-in-out 2.2s infinite alternate; }
@keyframes print-diamond { 0% { opacity: 0; transform: translate(-50%, -50%) scale(.2) rotate(-20deg); } 35% { opacity: 1; transform: translate(-50%, -50%) scale(1.18); } 100% { opacity: 1; transform: translate(-50%, -50%) scale(.82); } }
@keyframes print-diamond-glint { from { transform: translate(-50%, -50%) scale(.82); } to { transform: translate(-50%, -50%) scale(.94) rotate(5deg); } }
.board.bump .bd-art { animation: board-bump .35s ease-out; }
.board.quake .bd-art { animation: board-quake .9s cubic-bezier(.36, .07, .19, .97); }
.board .shock { stroke: var(--paper); stroke-width: 1.6; }
.board .shock.late { stroke: var(--sun-rim); }
/* Circle names sit on the sky, so each carries a halo of the sky's own darkest ink: they read over clouds, the
   corona and the hills alike. A hit stays lit; a miss goes quiet. */
.board-label { text-shadow: 0 0 2px var(--sky-top), 0 0 5px var(--sky-top), 0 1px 1px var(--sky-top); }
.board-label.hit { color: var(--ice); }
.board-label.miss, .board-label .ex { color: var(--on-sky); }
.board-label.miss { font-weight: 400; }
.board-label.hit .ex { color: inherit; }
@media (prefers-reduced-motion: reduce) {
  .board.bump .bd-art, .board.quake .bd-art { animation: none; }
  .board.total .bd-corona i { animation: none; }
  .board.total .bd-diamond { animation: none; opacity: 1; transform: translate(-50%, -50%) scale(.82); }
}

/* ---- Start screen: the same sun and the first moon, looping; logo and tier marks in the print's inks ---- */
.home-eclipse span { background: none; box-shadow: none; border-radius: 0; }
.he-sun { background: none; box-shadow: none; }
.he-sun::before { content: ''; position: absolute; inset: -58.7%; --art: url("art/print/sun.webp"); background: var(--sun-inks); }
.he-moon { --art: url("art/print/moons-sil.webp"); --art-size: 300% 200%; --art-pos: 0 0; background: var(--moon-cut); box-shadow: none; }
.he-moon::after { content: ''; position: absolute; inset: 0; --art: url("art/print/moons-key.webp"); --art-size: 300% 200%; --art-pos: 0 0; background: var(--moon); }
.home-eclipse::before { inset: -105%; border-radius: 0; box-shadow: none; --art: url("art/print/corona.webp"); background: radial-gradient(closest-side, #FFFDF4 0 30%, rgba(239, 230, 207, 0) 54%); }
.home-eclipse::after { top: 6%; right: 2%; width: 34%; height: 27%; border-radius: 0; box-shadow: none; --art: url("art/print/diamond.webp"); background: #FFFEF6; }
.lo-cres { background: var(--panel); }
.lo-total, .phase.totalipse { background: #05090F; }
.phase { box-shadow: inset calc(var(--c) * -1em) 0 0 0 #0A1422, 0 0 0 1px rgba(255, 133, 82, .55); }

/* ---- Surfaces: solid ink plates, no glass ---- */
#result.card, .summary .card { background: var(--panel); backdrop-filter: none; -webkit-backdrop-filter: none; }
.home-modes { background: var(--panel); backdrop-filter: none; -webkit-backdrop-filter: none; }
.mode-tile { backdrop-filter: none; }
.share, .day-strip, .starchart { background: #0A1420; }
body:not(:has(main.game))::after { background: linear-gradient(180deg, rgba(10, 19, 34, 0), rgba(10, 19, 34, .9) 60%); }
.checklist .verdict, .points span:last-child { font-size: .64rem; letter-spacing: .07em; }
/* Words that sit straight on the sky get the same halo as the circle names. */
.puzzle-title, .guess label, .game .dateline, #status, .home-title, .home-lede, #home-date, .home-status { text-shadow: 0 0 3px var(--bg), 0 0 8px var(--bg); }
.puzzle-title { color: var(--text); }
.guess label.muted, .guess > .small, .home-lede, .game > .archive-bar { color: var(--on-sky); }
/* Links on the sky are cream and underlined; the ember ink is kept for links on panels, where it has the contrast. */
.guess > .small a, .game > .archive-bar a, .site-footer a { color: var(--text); }
.site-footer { color: var(--on-sky); }
.ladder li.current { color: #FFA880; }
.game .dateline, #home-date { color: #FFA880; }

/* ---- Laptops and desktops: the board stops short of the hills, so the circles' names stay on open sky ---- */
@media (min-width: 860px) {
  .game .board-wrap { width: min(100%, max(320px, calc((100svh - 190px - max(100vw, 1100px) * .125) * 400 / 350))); }
}

/* ---- Phones, after answering: the board keeps its size, the result card takes what is left and scrolls inside
   itself; Next sits below the scrolling part, never on top of the tier strip or the fits/misses list. ---- */
.result-body { min-width: 0; }
@media (max-width: 859px) and (orientation: portrait) {
  .game #play .stage { min-height: min(43%, 98vw); }
  .game #play .panel { max-height: none; flex: 0 1 auto; }
  .game #play #result:not([hidden]) { display: flex; flex-direction: column; overflow: hidden; padding: 12px 14px 0; margin-top: 4px; }
  .game #play .result-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
  /* when the list runs on below, its last visible line fades out, so it is plain there is more to scroll to */
  .game #play .result-body::after { content: ''; display: block; position: sticky; bottom: 0; height: 18px; margin-top: -4px; pointer-events: none; background: linear-gradient(rgba(15, 27, 42, 0), var(--panel)); }
  .game #play #result #next { position: static; flex: none; margin: 10px 0 12px; }
  .game #play .tier-name { font-size: 1.55rem; margin: 6px 0 2px; }
  .game #play #r-explain { font-size: .88rem; line-height: 1.35; }
  .game #play .pills { margin: 8px 0 4px; }
  .game #play .pills li { padding: 5px 1px; }
  .game #play .checklist { margin-bottom: 6px; }
  .game #play .checklist li { padding: 5px 0; gap: 8px; font-size: .92rem; line-height: 1.25; }
  .game #play .answer { font-size: 1.15rem; margin-top: 2px !important; }
  .game #play .points span:first-child { font-size: 1.9rem; }
  .game #play #report { min-height: 0; padding: 8px 12px; font-size: .85rem; }
}

#status:not(:empty) { background: var(--panel); border: 1.5px solid var(--line); border-radius: 12px; padding: 8px 12px; margin: 8px 0 0; text-shadow: none; }

/* ---- Review round 1 ---- */
/* The level line: plainly set, no wide tracking. */
.puzzle-title { letter-spacing: .03em; font-stretch: 100%; }
.puzzle-title.enter { animation-name: print-title-in; }
@keyframes print-title-in { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }
/* The UI's plates are printed too: the same paper tooth as the scene, at a third of the strength. */
.card, .sheet, .home-modes, #status:not(:empty) { background-image: url("art/print/tooth-soft.webp"); background-size: 256px 256px; }
@media (max-width: 859px) and (orientation: portrait) {
  /* 5-circle results: every line that can go, goes, so more of the fits/misses list shows without scrolling */
  .game #play .result-head .eyebrow { display: none; }
  .game #play .answer { margin-top: 0 !important; }
  .game #play .points { display: flex; align-items: baseline; gap: 4px; }
  .game #play .tier-name { margin-top: 0; }
  .game #play .pills .pe { font-size: .9rem; }
  .game #play .pills li { padding: 4px 1px; gap: 1px; }
}
/* Reading pages put long text over the sky: the star plates print much fainter there. */
body:not(:has(main.game)) .sk-stars.faint { opacity: calc(var(--stars) * .4); }
body:not(:has(main.game)) .sk-stars.bright { opacity: calc(var(--bright) * .3); }
/* Laptop-height screens: a 5-circle result card with its report button ran to the very bottom edge. */
@media (min-width: 860px) and (max-height: 940px) { .game .panel { padding-top: 14px; } .game .checklist li { padding: 7px 0; } .game .checklist { margin-bottom: 10px; } }
/* In totality the printed sun under the moons is let go to a trace: its rays read as the last warm prominences. */
.bd-sun { transition: opacity 1.4s ease; }
.board.total .bd-sun { opacity: .5; }
/* A missed circle name over the pale end of the day sky measured 4.35:1 in the quiet colour: it stays cream, and is told apart by weight and by the hits turning mint. */
.board-label.miss { color: var(--text); }
/* the start-screen moon keeps its own lighter ink in its cuts (the reset above for .home-eclipse span outranks .he-moon) */
.home-eclipse .he-moon { background: var(--moon-cut); }

/* ---- The board sits wholly in the sky ----
   app.js measures the room between the level line and the top of the land (--sky-room). The board is sized to fit in
   it and centred in it, so no moon or circle name lies over the hills at any screen size or circle count.
   --bw is the board's width; its box is 0.875 as tall. The 3.3em taken off the room is the 1.1em kept above the board
   for names that wrap upward, and 2.2em below it for names under the bottom moons that run to a third line. */
@media (min-width: 860px), (orientation: landscape) and (max-height: 560px) and (min-width: 560px) {
  .game .stage { justify-content: flex-start; }
  .game .board-wrap { --bw: min(100%, max(200px, calc((var(--sky-room, 60svh) - 3.3em) * 400 / 350)));
    width: var(--bw); margin-top: max(0px, calc((var(--sky-room, 60svh) - var(--bw) * .875 - 3.3em) / 2)); }
}
@media (max-width: 859px) and (orientation: portrait) {
  html:not(.kb) .game #play:not(.answered) .stage { justify-content: flex-start; }
  html:not(.kb) .game #play:not(.answered) .board-wrap { --bw: min(100cqw, calc((var(--sky-room, 100cqh) - 3.3em) * 400 / 350));
    width: var(--bw); margin-top: max(0px, calc((var(--sky-room, 100cqh) - var(--bw) * .875 - 3.3em) / 2)); }
}

/* ---- Wide screens, centre stage ----
   While you are guessing, the board has the middle of the sky to itself and the answer box is docked on the land below. Once an answer is in, the board steps aside and the
   result card takes the right-hand column. Short, wide screens (a phone on its side) keep the two columns throughout. */
@media (min-width: 860px) and (min-height: 600px) {
  /* a little more kept above the board than on a phone, so a name over the top moon never touches the level line */
  .game .board-wrap { --bw: min(100%, max(200px, calc((var(--sky-room, 60svh) - 4.5em) * 400 / 350)));
    width: var(--bw); margin-top: max(1.2em, calc((var(--sky-room, 60svh) - var(--bw) * .875 - 3.3em) / 2)); }
  .game #play:not(.answered) { grid-template-columns: minmax(0, 1fr); justify-items: center; gap: 0; }
  .game #play:not(.answered) .stage { width: 100%; }
  /* The answer box is docked low on the land, clear of the board, and stays there: it is out of the page's flow, so
     nothing moves it. Messages stack above it. The footer waits for the start screen and the results. */
  .game #play:not(.answered) .panel { position: fixed; z-index: 2; left: 0; right: 0; bottom: clamp(20px, 5.5vh, 60px); width: min(100% - 48px, 560px); margin: 0 auto; padding: 0;
    display: flex; flex-direction: column; gap: 8px; }
  .game #play:not(.answered) .guess { order: 1; }
  body:has(#play:not([hidden]):not(.answered)) > .site-footer { display: none; }
  .game #play:not(.answered) #status:not(:empty), .game #play:not(.answered) #suggest:not(:empty) { margin: 0; padding: 8px 12px; border-radius: 12px; background: var(--panel); text-shadow: none; }
  .game #play.answered .stage { animation: stage-aside .7s cubic-bezier(.2, .7, .2, 1) both; }
  .game #play.answered .panel { animation: card-in .5s ease-out .15s both; }
}
@keyframes stage-aside { from { transform: translateX(216px); } } /* half the card column and its gap: where the centred board stood */
@keyframes card-in { from { opacity: 0; transform: translateX(24px); } }
@media (prefers-reduced-motion: reduce) { .game #play.answered .stage, .game #play.answered .panel { animation: none; } }
/* The level strip moves up beside the wordmark on wide screens: the row it used to take goes to the sky, so the board is bigger. */
@media (min-width: 1000px) and (min-height: 600px) {
  /* not while the past-day notice sits under the header, and not for Endless's long strip */
  .game:has(#play:not([hidden])):not(:has(#archive-bar:not([hidden]))) .ladder:not(:has(> :nth-child(7))) { margin: -42px 140px 12px 190px; position: relative; z-index: 1; }
}

/* ================================================================ Buttons: one block of ink ====
   Every button is printed from the same hand-cut block (art/print/block-*.webp: generated, see
   design/tools/process-buttons.py). The block's own cut outline is laid out as a nine-slice, so its corners keep their
   shape at any size. Nothing else: no shadow, no bevel, no pattern. Hovering lifts the ink a shade; pressing sets it
   down a pixel. Under the block is a plain fill, inset so it never shows, for when the block can't be loaded. */
button.primary, a.button.primary, .row button, button.ghost, a.button:not(.primary), .actions-row > button:not(.primary), #sign-out, #copy-code, #email-create, #restart {
  border: 2px solid transparent; border-radius: 9px; box-shadow: none; color: var(--text);
  background: #23405C padding-box; border-image: url("art/print/block-ink.webp") 44 fill / 22px;
  transition: filter .15s ease, transform .08s ease-out; }
button.primary, a.button.primary, .row button { color: #1B0D05; background: #EE6A35 padding-box; border-image-source: url("art/print/block-ember.webp"); }
button.primary:hover, a.button.primary:hover, .row button:hover, button.ghost:hover, a.button:not(.primary):hover, .actions-row > button:not(.primary):hover, #sign-out:hover, #copy-code:hover, #email-create:hover, #restart:hover { color: var(--text); background: #23405C padding-box; filter: brightness(1.22); }
button.primary:hover, a.button.primary:hover, .row button:hover { color: #1B0D05; background: #EE6A35 padding-box; filter: brightness(1.09); }
button.primary:not(:disabled):active, a.button.primary:not(:disabled):active, .row button:not(:disabled):active, button.ghost:not(:disabled):active, a.button:not(.primary):not(:disabled):active, .actions-row > button:not(.primary):not(:disabled):active, #sign-out:not(:disabled):active, #copy-code:not(:disabled):active, #email-create:not(:disabled):active, #restart:not(:disabled):active { transform: translateY(1px); box-shadow: none; filter: brightness(.92); }
/* not ready yet (nothing typed, still loading): the quiet block */
button.primary:disabled, .row button:disabled { color: var(--muted); background: #23405C padding-box; border-image-source: url("art/print/block-ink.webp"); filter: none; opacity: 1; }
.row button:disabled { cursor: default; }
.icon-btn { border-radius: 50%; border: 1.5px solid var(--line-strong); background: var(--panel); box-shadow: none; transition: border-color .15s, background-color .15s, transform .08s ease-out; }
.icon-btn:hover { border-color: var(--paper); background: var(--card); }
.icon-btn:active { transform: translateY(1px); box-shadow: none; }
@media (prefers-reduced-motion: reduce) { button.primary, a.button.primary, .row button, button.ghost, a.button:not(.primary), .actions-row > button:not(.primary), #sign-out, #copy-code, #email-create, #restart, .icon-btn { transition: none; } }
/* links whose href is handled by nav.js (no browser address bubble on hover) still act and look like links: this stands in
   for the browser's own link underline, at zero weight so every rule above still decides how a given link looks */
:where(a[data-href]) { cursor: pointer; text-decoration: underline; }

/* ---- No selecting or copying the site's words ----
   Text can't be highlighted anywhere except where a player types (the answer box, sign-in fields) and the share
   card's text, which is the fallback for copying your own result by hand when the Share button can't reach the
   clipboard. nav.js also cancels copy and cut outside those places. */
html, body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
input, textarea, select, [contenteditable="true"], #s-share { -webkit-user-select: text; user-select: text; }

/* ================================================================ Today's scores (results page graph) ====
   One curve, drawn straight on the card in the paper's cream: higher where more players scored. The scores below yours
   are inked in ember; your own is a thin ember line up to the curve, ending in a small sun with a bite out of it. */
.w-rank { margin: 10px 0 0; font: 400 1rem/1.25 var(--sans); color: var(--text); }
.w-rank b { margin: 0 .1em; font: italic 300 2.5rem/1 var(--serif); font-variant-numeric: lining-nums; letter-spacing: -.02em; color: #FFA880; }
/* Behind it, the Milky Way (art/print/chart-sky-milkyway.webp, generated): fading into the card on every
   side, and showing only above the curve, which stands in front of it like a hill. The sky is the setting, not the subject. */
.curve { position: relative; isolation: isolate; margin: 12px -8px 0; padding: 14px 8px 0; }
.curve::before { content: ''; position: absolute; inset: 0 0 18px; z-index: -1; opacity: .72; background: url("art/print/chart-sky-milkyway.webp") 50% 40% / cover;
  -webkit-mask: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent), linear-gradient(transparent, #000 22%, #000 70%, transparent); -webkit-mask-composite: source-in; mask: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent), linear-gradient(transparent, #000 22%, #000 70%, transparent); mask-composite: intersect; }
.curve .c-ground { fill: var(--panel); }
.curve .c-fill { opacity: .8; } .curve .c-fill-you { opacity: .88; }
.curve svg { display: block; width: 100%; height: auto; overflow: visible; }
.curve .c-base, .curve .c-tickmark { stroke: var(--line-strong); stroke-width: 1; }
.curve .c-tick { fill: var(--muted); font: italic 500 8.5px/1 var(--serif); font-variant-numeric: lining-nums; }
.curve .c-line { fill: none; stroke: var(--paper); stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round; stroke-dasharray: 1; animation: curve-draw 1.1s cubic-bezier(.3, .7, .2, 1) .1s both; }
.curve .c-area { animation: curve-fade .8s ease-out .5s both; }
.curve .c-mark { animation: curve-fade .5s ease-out 1s both; }
.curve .c-you { stroke: var(--gold); stroke-width: 1.2; }
.curve .c-you-sun { fill: #FFD98A; stroke: var(--gold); stroke-width: 1.4; }
.curve .c-you-moon { fill: #0A1220; }
.curve .c-you-axis { fill: #FFA880; font: italic 600 9px/1 var(--serif); }
@keyframes curve-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes curve-fade { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .curve .c-line, .curve .c-area, .curve .c-mark { animation: none; } }
/* results page order: the day's graph first, then the answers, then the level-by-level figures */
.sum-world { order: 3; } .sum-answers { order: 4; } .sum-world-levels { order: 5; } .sum-friends { order: 6; } .sum-rate { order: 7; }
/* Phones, after answering: with larger moons the names under the bottom moons need a little more room above the result
   card. The level line goes (the strip above already says which level) and that room is kept under the board. */
@media (max-width: 859px) and (orientation: portrait) {
  .game #play.answered .puzzle-title { display: none; }
  html:not(.kb) .game #play.answered .board-wrap { width: min(100cqw, calc((100cqh - 3.1em) * 400 / 350)); margin-top: .4em; margin-bottom: auto; }
}

/* ---- Phones: the board fits the room that is really left ----
   board.js now lets a circle's name run out past a small board (fitLabels), so names keep to one or two lines and
   can be set a little larger at the small end. */
.board-label { font-size: clamp(12px, 3.4cqi, 17px); width: max-content; } /* its own width, not what is left of the board to its right */
.board-label.long { font-size: clamp(11.5px, 3cqi, 15px); }
@media (max-width: 859px) and (orientation: portrait) {
  /* never more than the stage itself holds: a message under the answer box takes room the sky measure can't see.
     .4em is always kept between the level line and a name over the top moon. */
  html:not(.kb) .game #play:not(.answered) .board-wrap { --room: min(var(--sky-room, 100cqh), 100cqh - 1.7em);
    --bw: min(100cqw, calc((var(--room) - 3.7em) * 400 / 350)); margin-top: max(.4em, calc((var(--room) - var(--bw) * .875 - 3.3em) / 2)); }
  /* keyboard up: the level line goes as well, and its row goes to the board; names are one or two lines now, so less is kept for them */
  html.kb .game #play .puzzle-title { display: none; }
  html.kb .game #play .board-wrap { width: min(100cqw, calc((100cqh - 2.6em) * 400 / 350)); }
  /* after answering: the more circles, the more the board gives way to the card, so the fits/misses lines show
     without scrolling. Five circles stop at 34%: any smaller and the names round the board run into each other,
     so on a short phone the fifth line is a short scroll away. */
  .game #play.answered:has(#r-checks li:nth-child(4)) .stage { min-height: min(36%, 98vw); }
  .game #play.answered:has(#r-checks li:nth-child(5)) .stage { min-height: min(34%, 98vw); }
  .game #play.answered .checklist li { padding: 4px 0; }
}

/* ================================================================ The answer box: one plate ====
   A single ink plate at every size: the prompt, the words you type under it, and Eclipse at its right-hand end. No box
   inside a box. The plate itself takes the focus colour, and shakes when an answer doesn't count. */
.game #play .guess { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 10px; margin: 0; padding: 9px 9px 9px 16px;
  border: 1.5px solid var(--line-strong); border-radius: 14px; background: var(--panel) url("art/print/tooth-soft.webp") 0 0 / 256px 256px; transition: border-color .15s; }
.game #play .guess:focus-within { border-color: var(--gold); }
.game #play .guess > label { grid-column: 1; margin: 0; text-shadow: none; }
.game #play .guess > .small { display: none; } /* the how-to line is in the FAQ and on the start screen */
.game #play .guess .row { display: contents; }
.game #play .guess .row input { grid-column: 1; grid-row: 2; min-height: 34px; padding: 2px 0; }
.game #play .guess .row button { grid-column: 2; grid-row: 1 / span 2; min-height: 48px; }
.game #play .guess:has(.row.shake) { animation: shake .35s ease-in-out; }

/* ================================================================ PC and laptop: a taller sky, a bigger board ====
   On a wide screen the land is as wide as the window, so it stood a quarter to a third of the way up a short one and
   the board, which keeps to the sky, came out small. Here the whole scene is hung lower: the sky layer is made taller
   than the window by --drop, so everything in it that is measured from its foot (the land, the horizon's colours, the
   glow) moves down together and the hilltops stand a fifth of the way up. sky.js landCrest() reads the layer's own
   foot, so the board is sized and centred in the taller sky without being told. Names and the level line grow with it. */
@media (min-width: 860px) {
  #sky, #sky.painted { --drop: max(0px, calc(max(100vw, 1100px) * .164 - 20vh)); height: calc(100vh + var(--drop)); height: calc(100lvh + var(--drop)); }
  .board-label { font-size: clamp(13px, 3.4cqi, 22px); }
  .board-label.long { font-size: clamp(12px, 3cqi, 19px); }
  .game .puzzle-title { font-size: .95rem; }
}
/* The room kept for names used to be a fixed 4.5em whatever the board's size and however its moons sat, which cost a
   small board on a laptop far more than a large one. Names are set in proportion to the board, so the room for them is
   too, as shares of the board's width: --above for two lines over the top of its box, --below for a second line under
   the foot of it. Three circles have a moon at the very top and room to spare below; four sit on the diagonals, clear
   of the top; five need a little of both. The board takes all the sky that is left. */
@media (min-width: 860px) and (min-height: 600px) {
  .game .board-wrap { --above: .075; --below: .07;
    --bw: min(100%, max(200px, calc(var(--sky-room, 60svh) / (.875 + var(--above) + var(--below))))); width: var(--bw); margin-top: calc(var(--bw) * var(--above)); }
  .game .board-wrap:has(.board[data-n="3"]) { --above: .1; --below: 0; }
  .game .board-wrap:has(.board[data-n="4"]) { --above: .01; --below: .065; }
  .game .board-wrap:has(.board[data-n="6"]) { --above: .065; --below: .095; }
}
