/* fridgle. — a daily fridge of word magnets */

* { box-sizing: border-box; }

html, body { margin: 0; }

/* phones like to auto-inflate small text ("font boosting") — that
   would undo the poem's shrink-to-fit, so turn it off */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* nothing shows until the game has built the board (game.js flips
   .ready on at the end of setup) — no flash of half-made pages */
body:not(.ready) { visibility: hidden; }

body {
  /* the surface of a fridge: off-white powder coat with a fine speckle
     (the noise is a tiny inline svg, no image files) and a soft sheen */
  background-color: #f4f3ee;
  background-image:
    linear-gradient(100deg,
      rgba(255, 255, 255, 0.5) 0%,
      rgba(255, 255, 255, 0) 45%,
      rgba(210, 206, 195, 0.18) 100%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.055'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  color: #33302a;
  font-family: Georgia, "Iowan Old Style", "Times New Roman", serif;
}

main {
  max-width: 42.5rem;
  margin: 0 auto;
  padding: 26px 18px 40px;
  /* the page fills the screen so the footer can sit at the bottom edge —
     until the tiles grow tall enough to push it further down. dvh is
     the phone-honest viewport (100vh pretends the address bar is gone,
     which shoved the footer just below the fold on android) */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* ---------- header ---------- */

header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 20px;
}

h1 {
  font-size: 1.4rem;
  font-weight: normal;
  margin: 0;
  letter-spacing: 0.02em;
}

#title { cursor: pointer; }

/* the wordmark is itself a big magnet, sitting slightly crooked */
.wordmark-tile {
  display: inline-block;
  background: #fffffe;
  border: 1px solid #c8c5b8;
  padding: 0.14em 0.5em 0.2em;
  transform: rotate(-1.3deg);
  box-shadow:
    0 1px 2px rgba(72, 60, 38, 0.18),
    0 2px 6px rgba(72, 60, 38, 0.08);
}


.corner { display: flex; align-items: baseline; gap: 0.9em; }

/* the cog: icon-only, so no dotted underline. the stroke is thinned
   so it reads as the same grey as the text beside it */
#settings-btn {
  text-decoration: none;
  align-self: center;
}
#settings-btn svg {
  width: 1.05em;
  height: 1.05em;
  display: block;
  stroke-width: 1.7;
}

#day-label { color: #8f8a7d; font-size: 0.85rem; }

/* quiet text buttons: clear, copy, edit, hard mode */
.quiet {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 0.85rem;
  color: #8f8a7d;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
}
.quiet:hover:not(:disabled) { color: #33302a; }
.quiet:disabled { opacity: 0.45; cursor: default; }

/* reset swaps its label ("are you sure?") and chrome repaints dotted
   text underlines lazily — the old width lingers or flickers. a dotted
   border redraws with the box, so reset draws its line that way */
#reset-btn {
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
  padding-bottom: 2px;
}

/* ---------- the sentence line ---------- */

#line {
  /* a single writing line: magnets sit on it, and the area grows
     upward-wrapping as the sentence gets long */
  border-bottom: 1px solid #cfccc0;
  min-height: 3.1em;
  padding: 0.3em 0.2em 0.6em;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-end;
  align-items: center;
  row-gap: 0.7em;
  position: relative;
}

#line.empty::after {
  content: "tap or drag tiles to place";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #c9c5b8;
  font-style: italic;
  pointer-events: none;
}

/* ---------- magnets ---------- */

.tile {
  display: inline-block;
  background: #fffffe;
  border: 1px solid #c8c5b8;
  padding: 0.24em 0.53em 0.3em;
  font-size: 1.06rem;
  line-height: 1.3;
  white-space: pre;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  touch-action: none;
  /* every magnet sits a little crooked, like a real fridge */
  transform: rotate(var(--rot, 0deg)) translateY(var(--dy, 0px));
  box-shadow:
    0 1px 2px rgba(72, 60, 38, 0.18),
    0 2px 6px rgba(72, 60, 38, 0.08);
}

.tile.punct, .tile.affix {
  color: #6d675a;
  min-width: 1.9em;
  text-align: center;
}

/* a linebreak sitting before the first word or after the last does
   nothing in the finished poem — it fades to say so */
.tile.brk.unused, .tile.spc.unused { opacity: 0.5; }
/* the gap magnet's face: a drawn arrow, dead-centered in the tile
   (the .txt box matches the text line-height, so tile heights agree) */
.tile.spc .txt {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 1.3em;
}
.tile.spc svg {
  width: 1.1em;
  height: 0.95em;
  display: block;
}
/* the pool's source tile wears a slightly bigger arrow so it reads */
.tile.spc-src svg { width: 1.35em; }
/* a placed gap magnet drags sideways to stretch its gap */
#line .tile.spc { cursor: ew-resize; }
/* in the finished poem a gap magnet is just its span of empty fridge */
.spc-gap {
  display: inline-block;
  visibility: hidden;
  height: 1px;
}

/* the invisible full-width sliver a linebreak magnet leaves in the
   finished poem — it makes the flex layout start a fresh line there */
.magnet-newline {
  flex-basis: 100%;
  height: 0;
}
/* two linebreaks in a row = a stanza gap: the second sliver gets real height */
.magnet-newline + .magnet-newline { height: 1.1em; }

/* the wear overlay: wiped-off patches that sit over the print */
.tile .wear {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* words with other forms are a little stack: the right edges of the
   magnets underneath stick out from beneath the top one, full height,
   flush with the tile. tapping that strip opens the menu. */
.tile { position: relative; }

/* words with other forms are a pile: whole darker tiles sit underneath
   the top one, offset a little right, so their edges show. they're drawn
   as sharp box-shadows (a fill + a 1px ring as the border each), which
   naturally paint behind the tile. two forms underneath at most. */
.tile.stacked {
  transition: box-shadow 0.15s ease;
  box-shadow:
    0 1px 2px rgba(72, 60, 38, 0.18),
    0 2px 6px rgba(72, 60, 38, 0.08),
    18px 2px 0 0 #f1eee4,
    18px 2px 0 1px #c9c6b7;
}

/* pointing at the pile pulls it out a little — it wants to be opened */
.tile.stacked:has(.stack:hover) {
  box-shadow:
    0 1px 2px rgba(72, 60, 38, 0.18),
    0 2px 6px rgba(72, 60, 38, 0.08),
    21px 2px 0 0 #f1eee4,
    21px 2px 0 1px #c9c6b7;
}

/* the menu scrolls behind a thin, fridge-toned scrollbar */
#menu, #poem, #help, #history, #settings {
  scrollbar-width: thin;
  scrollbar-color: #cfccc0 transparent;
}
#menu::-webkit-scrollbar, #poem::-webkit-scrollbar,
#help::-webkit-scrollbar, #history::-webkit-scrollbar,
#settings::-webkit-scrollbar { width: 7px; }
#menu::-webkit-scrollbar-track, #poem::-webkit-scrollbar-track,
#help::-webkit-scrollbar-track, #history::-webkit-scrollbar-track,
#settings::-webkit-scrollbar-track { background: transparent; }
#menu::-webkit-scrollbar-thumb, #poem::-webkit-scrollbar-thumb,
#help::-webkit-scrollbar-thumb, #history::-webkit-scrollbar-thumb,
#settings::-webkit-scrollbar-thumb { background: #cfccc0; }

/* strip over the protruding pile: the tap target for the menu. the V
   chevron says "there's more in here" even before you touch it */
.tile .stack {
  position: absolute;
  top: -1px;
  bottom: -1px;
  right: -2em;
  width: 2.1em; /* wider than the visible edges — easier to tap on a phone */
  cursor: pointer;
  touch-action: none;
}
.tile .stack::before {
  /* an open V chevron, drawn from two borders — sits on the pile's
     protruding edges */
  content: "";
  position: absolute;
  left: 0.45em;
  top: 50%;
  width: 0.34em;
  height: 0.34em;
  border-right: 1px solid #99947f;
  border-bottom: 1px solid #99947f;
  transform: translateY(-72%) rotate(45deg);
  pointer-events: none;
}
.tile.stacked:has(.stack:hover) .stack::before {
  border-color: #6d675a;
  transform: translateY(-56%) rotate(45deg); /* a little dip, like it's opening */
}

/* the pool and the line both leave room for the pile and its chevron */
#pool .tile.stacked, #line .tile.stacked { margin-right: 1.05em; }

/* spacing between magnets on the line: normal word gap by default,
   snug when something glues (punctuation, suffixes, dashes) */
#line .tile { margin-left: 0.55em; }
#line .tile.first { margin-left: 0; }
#line .tile.tight { margin-left: 2px; }

/* the one being dragged: the original stays as a faint ghost */
.tile.ghost { opacity: 0.25; cursor: grabbing; }

/* the copy that follows your finger */
.tile.clone {
  position: fixed;
  z-index: 40;
  margin: 0;
  pointer-events: none;
  transform: rotate(var(--rot, 0deg)) scale(1.07);
  box-shadow:
    0 5px 12px rgba(72, 60, 38, 0.28),
    0 12px 28px rgba(72, 60, 38, 0.14);
}
/* a dragged pile brings its under-tile along: the clone's lifted
   shadows and the pile's edge shadows share one box-shadow list */
.tile.clone.stacked {
  box-shadow:
    0 5px 12px rgba(72, 60, 38, 0.28),
    0 12px 28px rgba(72, 60, 38, 0.14),
    18px 2px 0 0 #f1eee4,
    18px 2px 0 1px #c9c6b7;
}

/* thin marker showing where the magnet will land */
.caret {
  width: 2px;
  height: 1.7em;
  border-radius: 1px;
  background: #b5ae9d;
  margin-left: 3px;
  align-self: center;
}

/* the magnets themselves, seated in the card under the print:
   centered rows, wrapping like the line, piles left behind */
#poem-tiles {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start; /* a poem reads from the left */
  align-items: center;
  row-gap: 0.3em;
  margin-top: 0.6em;
  cursor: default;
  font-size: 1.33rem; /* scales the row spacing along with the tiles */
}
/* the poem's magnets show a bit bigger (the base .tile size is in
   rem, so it has to be overridden here, not inherited) */
/* tiles follow their container's size (in em, not rem) so a long-lined
   poem can shrink as a whole to keep its line breaks */
#poem-tiles .tile { font-size: 1em; }

/* one strip of flush magnets, tilted as a unit — strips flow side by
   side and only wrap when they run out of room */
.magnet-row { display: inline-flex; align-items: center; }
#poem-tiles, .history-tiles { column-gap: 0.55em; }

/* history shows each day's actual magnets, small */
.history-tiles {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start; /* left-aligned lines, centered block */
  align-items: center;
  row-gap: 0.25em;
  margin-top: 0.55em;
  cursor: default;
  font-size: 1.06rem; /* the tiles inherit this, scalable like the poem's */
}
.history-tiles .tile { font-size: 1em; }
#poem-tiles .tile { cursor: default; }

/* the morning deal: magnets drop onto the fridge one after another
   (the world fridge's poems and credit lines arrive the same way —
   .waiting hides them until their card scrolls into view) */
.tile.arrive,
.wall-credit.arrive,
.help-intro.arrive,
.help-row.arrive,
.help-start-row.arrive {
  animation: arrive 0.26s cubic-bezier(0.2, 0.8, 0.3, 1) backwards;
}
.wall-tiles .tile.waiting,
.wall-credit.waiting { opacity: 0; }
@keyframes arrive {
  0% { opacity: 0; translate: 0 -16px; scale: 1.1; }
  70% { opacity: 1; translate: 0 1px; }
  100% { opacity: 1; translate: 0 0; scale: 1; }
}

/* small "no" shake, e.g. tapping a magnet that has no other forms */
.tile.wiggle { animation: wiggle 0.22s ease-in-out; }
@keyframes wiggle {
  25% { transform: rotate(calc(var(--rot, 0deg) - 2.5deg)) translateY(var(--dy, 0px)); }
  75% { transform: rotate(calc(var(--rot, 0deg) + 2.5deg)) translateY(var(--dy, 0px)); }
}

/* ---------- under the line: hard mode info + buttons ---------- */

#meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 12px;
  min-height: 2em;
}

/* the endless ↔ and ↲ magnets, first thing in the row */
#sources { display: flex; align-items: center; gap: 0.5em; margin-right: 1em; }
body.done #sources .tile { opacity: 0.45; }
/* hard mode's counter: small grey text tucked above the writing
   line's right end. zero height, so it never pushes the board around */
#hard-info {
  color: #8f8a7d;
  font-size: 0.85rem;
  height: 0;
  text-align: right;
  position: relative;
  top: -1.3em;
  pointer-events: none;
}
#hard-info.over { color: #a8574a; }
/* hard mode counter: reddish until the word count is exactly right */
#hard-info.bad { color: #a8574a; }
#hard-info.good { color: #6f8a55; }

#actions { margin-left: auto; display: flex; align-items: center; gap: 1.2em; }

/* proper buttons, but nothing like the magnets: plain rectangles a
   shade darker than the fridge, no border */
.btn {
  font: inherit;
  font-size: 0.95rem;
  color: #4a453a;
  background: #e7e4d8;
  border: 1px solid #c8c5b8; /* bordered like the tiles */
  white-space: nowrap; /* a button label never breaks into a tower */
  padding: 0.4em 1.15em 0.45em;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(72, 60, 38, 0.14);
}
.btn:hover:not(:disabled) { background: #dedacb; }
.btn:disabled { opacity: 0.45; cursor: default; }

/* ---------- the poem card (after finalize) ---------- */

#poem {
  position: fixed;
  z-index: 70;
  left: 50%;
  top: 12%;
  transform: translateX(-50%);
  width: min(37rem, 92vw);
  /* tall poems scroll inside the card instead of running off-screen.
     the gutter is reserved up front so the scrollbar appearing can't
     shrink the width after the lines were measured */
  max-height: 76vh;
  overflow-y: auto;
  scrollbar-gutter: stable;
  background: #fefdf9;
  border: 1px solid #c8c5b8;
  padding: 1.6em 1.6em 1.4em;
  text-align: center;
  box-shadow:
    0 8px 20px rgba(72, 60, 38, 0.18),
    0 24px 60px rgba(72, 60, 38, 0.14);
  animation: poem-in 0.35s ease-out;
}

@keyframes poem-in {
  from {
    opacity: 0;
    transform: translateX(-50%) translateY(10px);
  }
}

@media (prefers-reduced-motion: reduce) {
  #poem { animation: none; }
}

/* the card's header: small wordmark magnet and day number, centered */
#poem-label {
  font-size: 0.9rem;
  color: #33302a;
  letter-spacing: 0.02em;
  margin-bottom: 0.7em;
}
#poem-label .wordmark-tile { transform: rotate(1.1deg); }
.poem-meta { margin-left: 0.75em; color: #a09a8b; font-size: 0.85rem; }
/* on secret days, just the day number wears the void's color —
   corner label, poem card, and history rows alike */
body.void-day #day-label,
.void-num {
  color: #7a6cae;
}


.poem-row {
  margin-top: 1.4em;
  display: flex;
  flex-wrap: wrap; /* narrow screens wrap the row, never the labels */
  align-items: baseline;
  justify-content: center;
  row-gap: 0.6em;
  gap: 1.2em;
}



/* the note floats beside the share button without nudging it */
.poem-row { position: relative; }
/* "visit the world fridge": its own quiet row under share/history,
   wearing the masthead's fridge icon */
#poem-fridge-row { margin-top: 1.9em; } /* leaves room for "copied!" under share */
#poem-fridge-row[hidden] { display: none; } /* beats .poem-row's flex */
#poem-fridge-btn {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
}
#poem-fridge-btn svg { width: 0.95em; height: 1.15em; flex: none; }
/* the "— name · date" line under the poem: all of it the same quiet
   grey, the name just carries the dotted "you can edit me" underline */
#poem-credit {
  color: #8f8a7d;
  font-size: 0.9rem;
  font-style: italic;
  margin-top: 0.9em;
}
.credit-name {
  font-style: italic;
  font-size: 0.9rem;
  color: inherit;
}
#poem-credit .quiet:hover:not(:disabled) { color: #6d675a; }
#credit-input {
  font: inherit;
  font-style: italic;
  color: #4a453a;
  background: none;
  border: none;
  border-bottom: 1px dotted #99947f;
  outline: none;
  width: 9em;
  text-align: center;
}

/* the small print on old secret-day poems: which tile set dealt them */
#poem-era-note {
  color: #9d94b8;
  font-size: 0.82rem;
  font-style: italic;
  margin-top: 0.5em;
}

/* a button quietly working: label hidden, a little circle turning */
.btn.busy,
.quiet.busy {
  color: transparent;
  pointer-events: none;
  position: relative;
}
.btn.busy::after,
.quiet.busy::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1em;
  height: 1em;
  margin: -0.5em 0 0 -0.5em;
  border: 2px solid #8f8a7d;
  border-top-color: transparent;
  border-radius: 50%;
  animation: btn-spin 0.7s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

/* the gentle "are you sure?" that sits beside the yes button */
#confirm-note {
  color: #8f8a7d;
  font-size: 0.95rem;
  font-style: italic;
}


#copy-note {
  color: #8f8a7d;
  font-size: 0.85rem;
  font-style: italic;
  position: absolute;
  left: 50%;
  top: calc(100% + 0.2em);
  transform: translateX(-50%);
  white-space: nowrap;
}

/* ---------- the pool of unused magnets ---------- */

#pool {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7em 0.5em;
  margin-top: 28px;
  padding: 2px;
}

/* once finalized, the fridge is done for today */
body.done .tile { cursor: default; }
body.done #pool .tile { opacity: 0.45; }

/* while the poem card is up, everything behind it fades right back —
   except the footer credit, which stays */
main > * { transition: opacity 0.35s ease; }
body.poem-open main > :not(footer):not(#poem):not(#history):not(#calendar):not(#settings):not(#help),
body.history-open main > :not(footer):not(#poem):not(#history):not(#calendar):not(#settings):not(#help),
body.calendar-open main > :not(footer):not(#poem):not(#history):not(#calendar):not(#settings):not(#help),
body.settings-open main > :not(footer):not(#poem):not(#history):not(#calendar):not(#settings):not(#help),
body.help-open main > :not(footer):not(#poem):not(#history):not(#calendar):not(#settings):not(#help) {
  opacity: 0.12;
  /* faded things are out of reach — a tap out there only dismisses */
  pointer-events: none;
}

/* ---------- footer ---------- */

footer {
  margin-top: auto; /* pushed to the bottom of screen or content */
  padding-top: 4em;
  text-align: center;
}

/* ---------- history panel: your finalized prose ---------- */

/* the reveal's stage curtain: swallows every tap while it plays */
#shield { position: fixed; inset: 0; z-index: 200; }

/* the calendar dissolving at the end of the reveal */
#calendar.cal-fading { opacity: 0; transition: opacity 0.45s ease; }

/* the calendar: a little white pad, one month at a time */
#calendar {
  overflow: hidden; /* the wave ring stays inside the pad */
  position: fixed;
  z-index: 60;
  left: 50%;
  top: 12%; /* every popup opens at the same height */
  transform: translateX(-50%);
  width: min(19rem, 88vw);
  /* same skin as the poem card — every pad in the game matches */
  background: #fefdf9;
  border: 1px solid #c8c5b8;
  padding: 14px 16px 16px;
  box-shadow:
    0 8px 20px rgba(72, 60, 38, 0.18),
    0 24px 60px rgba(72, 60, 38, 0.14);
}
.cal-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 10px;
}
.cal-head .quiet { text-decoration: none; font-size: 1.1rem; padding: 0 0.4em; }
.cal-title { font-style: italic; color: #4a453a; }
/* the year dropdown, dressed as plain text */
.cal-year {
  font: inherit;
  font-style: italic;
  color: #4a453a;
  background: none;
  border: none;
  cursor: pointer;
}
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  text-align: center;
}
.cal-wd { color: #b3af9f; font-size: 0.75rem; }
/* every reachable day is a tiny magnet, each sitting a hair crooked */
.cal-day {
  font: inherit;
  font-size: 0.85rem;
  color: #8f8a7d;
  background: #fffffe;
  border: 1px solid #d8d5c9;
  padding: 0.28em 0;
  cursor: pointer;
  transform: rotate(var(--rot, 0deg));
  box-shadow: 0 1px 1.5px rgba(72, 60, 38, 0.12);
}
.cal-day:hover:not(:disabled) { background: #fffef4; color: #33302a; }
.cal-day:disabled {
  background: none;
  border-color: transparent;
  box-shadow: none;
  color: #d5d2c6;
  cursor: default;
  transform: none;
  /* only future days are truly disabled — they lean forward, unwritten.
     (the locked void days sit upright... for those who notice.) */
  font-style: italic;
}
/* a finished day: aged plastic, full ink */
.cal-day.done {
  color: #33302a;
  background: #fcf8ee;
  border-color: #c8c5b8;
  box-shadow: 0 1px 2px rgba(72, 60, 38, 0.18);
}
.cal-day.today { border-color: #99947f; }
/* a day beaten on hard mode wears the counter's green */
.cal-day.done.hard { color: #6f8a55; }
.cal-day.shown {
  font-weight: bold;
  text-decoration: underline;
  text-underline-offset: 2px;
}
/* the void days (before day 1): dressed exactly like disabled days,
   but they're listening. hammer one and it wakes up. */
.cal-day.void.locked {
  background: none;
  border-color: transparent;
  box-shadow: none;
  color: #d5d2c6;
  cursor: default;
  transform: none;
}
/* the base tremble: once you've rattled it awake, a locked void day
   keeps quivering — harder the closer the rupture gets, calming when
   you leave it alone (--shk rises and falls with your persistence) */
.cal-day.shaking { animation: cal-rumble 0.28s linear infinite; }
@keyframes cal-rumble {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(calc(var(--shk, 1) * 0.5px),
           calc(var(--shk, 1) * -0.4px)); }
  50%  { transform: translate(calc(var(--shk, 1) * -0.4px),
           calc(var(--shk, 1) * 0.5px)); }
  75%  { transform: translate(calc(var(--shk, 1) * 0.4px),
           calc(var(--shk, 1) * 0.3px)); }
  100% { transform: translate(0, 0); }
}

/* the jolt: every tap on a locked void day answers INSTANTLY at full
   strength, then rings down fast — one sharp shake per tap, harder the
   longer you keep at it (--shk grows with persistence) */
.cal-day.jolting {
  animation: cal-jolt 0.45s cubic-bezier(0.2, 0.8, 0.4, 1) 1;
}
@keyframes cal-jolt {
  0%   { transform: translate(calc(var(--shk, 1) * -2.4px),
           calc(var(--shk, 1) * 1.4px)) rotate(calc(var(--shk, 1) * -1.6deg)); }
  18%  { transform: translate(calc(var(--shk, 1) * 2.1px),
           calc(var(--shk, 1) * -1.2px)) rotate(calc(var(--shk, 1) * 1.3deg)); }
  38%  { transform: translate(calc(var(--shk, 1) * -1.2px),
           calc(var(--shk, 1) * -0.7px)) rotate(calc(var(--shk, 1) * 0.8deg)); }
  62%  { transform: translate(calc(var(--shk, 1) * 0.6px),
           calc(var(--shk, 1) * 0.4px)) rotate(calc(var(--shk, 1) * -0.4deg)); }
  85%  { transform: translate(calc(var(--shk, 1) * -0.2px), 0) rotate(0deg); }
  100% { transform: translate(0, 0) rotate(0deg); }
}
/* the one wave: a single indigo ring that sweeps the pad outward from
   the broken cell — the cue that causes everything below */
.cal-wave {
  position: absolute;
  width: var(--reach);
  height: var(--reach);
  margin-left: calc(var(--reach) / -2);
  margin-top: calc(var(--reach) / -2);
  border-radius: 50%;
  border: 2px solid rgba(75, 58, 140, 0.5);
  box-shadow:
    0 0 20px 5px rgba(75, 58, 140, 0.2),
    inset 0 0 16px 4px rgba(75, 58, 140, 0.12);
  pointer-events: none;
  animation: cal-wave 1.35s linear forwards;
}
@keyframes cal-wave {
  0%   { transform: scale(0.02); opacity: 0.95; }
  81%  { transform: scale(1); opacity: 0.5; }
  100% { transform: scale(1.04); opacity: 0; }
}

/* the transformation: the instant the wavefront touches a dead day it
   snaps dark — white-hot number, immediate — and leaps straight up,
   lands, settles with one small after-bounce, then cools into an
   ordinary living magnet. */
.cal-day.freeing {
  animation: cal-become 1.0s cubic-bezier(0.3, 0, 0.3, 1) forwards;
  z-index: 2;
}
@keyframes cal-become {
  0%   { transform: translateY(0);
         color: #b9b5a6; background: rgba(255, 255, 254, 0);
         border-color: rgba(216, 213, 201, 0); box-shadow: none; }
  5%   { transform: translateY(-2px) rotate(var(--rot, 0deg));
         color: #fdfcff; background: #2b2145; border-color: #241a3d;
         box-shadow: 0 3px 8px rgba(36, 26, 61, 0.35); }
  30%  { transform: translateY(-11px) rotate(var(--rot, 0deg));
         color: #fdfcff; background: #2b2145; border-color: #241a3d;
         box-shadow: 0 12px 18px rgba(36, 26, 61, 0.3); }
  54%  { transform: translateY(0) rotate(var(--rot, 0deg));
         color: #fdfcff; background: #2b2145; border-color: #241a3d;
         box-shadow: 0 1px 3px rgba(36, 26, 61, 0.4); }
  66%  { transform: translateY(-3.5px) rotate(var(--rot, 0deg));
         color: #f4f1ff; background: #34285a; border-color: #2b2145;
         box-shadow: 0 5px 9px rgba(36, 26, 61, 0.28); }
  78%  { transform: translateY(0) rotate(var(--rot, 0deg));
         color: #8a76d6; background: #efecff; border-color: #b9aee6;
         box-shadow: 0 1px 2px rgba(75, 58, 140, 0.2); }
  100% { transform: translateY(0) rotate(var(--rot, 0deg));
         color: #7a6cae; background: #f8f6fe; border-color: #dcd6ee;
         box-shadow: 0 1px 1.5px rgba(72, 60, 38, 0.12); }
}

/* freed void days: a whisper of periwinkle while unwritten, deepening
   to full otherworldly plastic once a poem lives there */
.cal-day.void.unlocked:not(.done) {
  color: #7a6cae;
  background: #f8f6fe;
  border-color: #dcd6ee;
}
.cal-day.void.unlocked:not(.done):hover {
  background: #f1edfc;
  color: #4b3a8c;
}
.cal-day.void.unlocked.done {
  color: #4b3a8c;
  background: #eae5fb;
  border-color: #c9c0ea;
  box-shadow: 0 1px 2px rgba(75, 58, 140, 0.22);
}

/* retroactive poems wear a little star, perched on the tile's corner */
.cal-day { position: relative; }
.cal-day.retro::after {
  content: "*";
  position: absolute;
  top: -0.05em;
  right: 0.12em;
  color: #b3af9f;
  font-size: 1.1em;
}

#help {
  overflow-x: hidden;
  /* the looping demos shuffle layout every few seconds — without
     this, mobile scroll-anchoring chases them and the card twitches */
  overflow-anchor: none;
}
#history,
#settings,
#help {
  position: fixed;
  z-index: 60;
  left: 50%;
  top: 12%;
  transform: translateX(-50%);
  width: min(28rem, 88vw);
  max-height: 62vh;
  overflow-y: auto;
  /* same skin as the poem card — every pad in the game matches */
  background: #fefdf9;
  border: 1px solid #c8c5b8;
  padding: 16px 20px 18px;
  box-shadow:
    0 8px 20px rgba(72, 60, 38, 0.18),
    0 24px 60px rgba(72, 60, 38, 0.14);
}

/* one settings entry: name + cycling button, small print, example */
.setting-row {
  display: flex;
  flex-wrap: wrap; /* narrow screens drop the switch under the name */
  align-items: center;
  justify-content: space-between;
  gap: 0.4em 1em;
  margin-top: 14px;
}
.setting-name { color: #3a362e; }
/* each setting flips with a switch; the current value is written
   just left of the pill. dark mode's pill has three stops — its
   middle one is "adaptive". sized generously for thumbs. */
.sw {
  font: inherit;
  font-size: 0.95rem;
  background: none;
  border: none;
  padding: 0.4em 0;
  color: #8f8a7d;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
}
@media (pointer: coarse) {
  .sw { font-size: 1.1rem; }
}
.sw .sw-label { color: #6d675a; }
.sw .sw-track {
  width: 2.6em;
  height: 1.25em;
  border: 1px solid #c8c5b8;
  border-radius: 999px;
  background: #fffffe;
  position: relative;
  display: inline-block;
  box-shadow: inset 0 1px 2px rgba(72, 60, 38, 0.1);
  transition: background 0.15s, border-color 0.15s;
}
.sw .sw-knob {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: 3px;
  width: 0.95em;
  height: 0.95em;
  border-radius: 50%;
  background: #99947f;
  box-shadow: 0 1px 1.5px rgba(72, 60, 38, 0.25);
  transition: left 0.15s, background 0.15s;
}
.sw.mid .sw-knob { left: calc(50% - 0.475em); }
.sw.on .sw-knob { left: calc(100% - 0.95em - 3px); }
/* hard mode flipped on wears the game's red */
#hard-switch.on .sw-label { color: #a8574a; }
#hard-switch.on .sw-track { background: #f5e9e2; border-color: #c9a196; }
#hard-switch.on .sw-knob { background: #a8574a; }
/* the share flavor's emblem rides beside the word */
.sw-label svg {
  width: 0.95em;
  height: 0.8em;
  display: inline-block;
  vertical-align: -0.06em;
}
.sw-label .ico-lead { margin-right: 0.25em; }
.sw-label .ico-tail { margin-left: 0.4em; }
.setting-desc {
  margin: 8px 0 0;
  color: #8f8a7d;
  font-size: 0.85rem;
  font-style: italic;
}
.setting-example {
  margin: 10px 0 0;
  padding: 10px 12px;
  background: #f4f3ee;
  border: 1px solid #dcdad1;
  font: inherit;
  font-size: 0.85rem;
  color: #3a362e;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

#history h2,
#settings h2,
#help h2 {
  margin: 0 0 4px;
  font-size: 1rem;
  font-weight: normal;
  font-style: italic;
  color: #6d675a;
}

.history-entry { margin-top: 14px; }
.history-share { margin-left: 0.9em; }
.history-day { color: #8f8a7d; font-size: 0.8rem; }
.history-sentence { margin-top: 2px; color: #3a362e; }
.history-empty { color: #8f8a7d; font-style: italic; margin: 12px 0 4px; }

/* ---------- tap-a-word menu of other forms ---------- */

/* the menu is just more magnets, on a clean patch of fridge so the
   pool behind can't bleed through */
#menu {
  position: fixed;
  z-index: 50;
  padding: 9px;
  max-height: 46vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  background: #f4f3ee;
  border: 1px solid #d5d2c5;
  box-shadow:
    0 6px 16px rgba(72, 60, 38, 0.14),
    0 14px 34px rgba(72, 60, 38, 0.1);
}

.menu-item {
  display: inline-block;
  text-align: left;
  background: #fffffe;
  border: 1px solid #c8c5b8;
  font: inherit;
  font-size: 1.06rem;
  color: #33302a;
  padding: 0.24em 0.53em 0.3em;
  cursor: pointer;
  box-shadow:
    0 1px 2px rgba(72, 60, 38, 0.18),
    0 2px 6px rgba(72, 60, 38, 0.08);
}
.menu-item:nth-child(odd) { transform: rotate(-1.2deg); }
.menu-item:nth-child(even) { transform: rotate(1.1deg); }
.menu-item:hover {
  transform: rotate(0deg);
  border-color: #b5ae9d;
  box-shadow:
    0 2px 4px rgba(72, 60, 38, 0.22),
    0 4px 10px rgba(72, 60, 38, 0.1);
}

/* the form you're already using sits pressed into the fridge */
.menu-item.now {
  background: #f3efe2;
  box-shadow: inset 0 1px 2px rgba(72, 60, 38, 0.18);
}

@media (max-width: 480px) {
  main { padding-top: 18px; }
  .tile { font-size: 1rem; }
}

/* ---------- dark mode: the fridge at night ---------- */
/* the magnets stay white plastic — only the fridge itself, its pads,
   and the writing around them go dim. same speckle, less light. */
body.dark {
  /* the powder coat at night: same speckle, no sheen — a gradient
     over a dark coat just looked like a stain */
  background-color: #0e0e0e;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.055'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  color: #d3d3d0;
  /* white-on-black blooms; antialiasing keeps the serifs slim */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
body.dark .quiet { color: #949390; }
body.dark .quiet:hover:not(:disabled) { color: #e5e5e2; }
body.dark #day-label { color: #949390; }
body.dark #line { border-bottom-color: #333332; }
body.dark #line.empty::after { color: #4a4a47; }
body.dark .btn {
  color: #d3d3d0;
  background: #232324;
  border-color: #3a3a38;
}
body.dark .btn:hover:not(:disabled) { background: #2c2c2d; }
body.dark #poem,
body.dark #history,
body.dark #settings,
body.dark #help,
body.dark #calendar {
  background: #1a1a1b;
  border-color: #333332;
}
body.dark #history h2,
body.dark #settings h2 { color: #b1b0ab; }
body.dark .history-sentence { color: #d3d3d0; }
body.dark .history-day,
body.dark .poem-meta,
body.dark #poem-credit,
body.dark .credit-name,
body.dark #confirm-note,
body.dark #copy-note,
body.dark .setting-desc { color: #949390; }
body.dark #poem-credit .quiet:hover:not(:disabled) { color: #d3d3d0; }
body.dark #credit-input { color: #d3d3d0; }
body.dark .setting-name { color: #d3d3d0; }
body.dark .setting-example {
  background: #161617;
  border-color: #333332;
  color: #cfcfcc;
}
body.dark #menu {
  background: #0e0e0e;
  border-color: #333332;
}
body.dark #menu::-webkit-scrollbar-thumb,
body.dark #poem::-webkit-scrollbar-thumb,
body.dark #help::-webkit-scrollbar-thumb,
body.dark #history::-webkit-scrollbar-thumb,
body.dark #settings::-webkit-scrollbar-thumb { background: #3a3a38; }
body.dark .cal-title,
body.dark .cal-year { color: #d3d3d0; }
/* unwritten future days recede into the dark door (the locked secret
   days dress like them, and stay camouflaged) */
body.dark .cal-day:disabled { color: #4a4a47; }

/* dark magnets: deep warm plastic, pale ink. the inks and plastic
   tints are painted inline by the game (theme-aware there); these are
   the frames, piles, and cells around them. */
body.dark .wordmark-tile,
body.dark .tile {
  background: #161617;
  border-color: #3a3a38;
  color: #f0f0ee;
}
body.dark .tile.punct,
body.dark .tile.affix { color: #bcbbb6; }
body.dark .tile.stacked {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.3),
    0 2px 6px rgba(0, 0, 0, 0.16),
    18px 2px 0 0 #111112,
    18px 2px 0 1px #383836;
}
body.dark .tile.stacked:has(.stack:hover) {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.3),
    0 2px 6px rgba(0, 0, 0, 0.16),
    21px 2px 0 0 #111112,
    21px 2px 0 1px #383836;
}
body.dark .tile.clone {
  box-shadow:
    0 5px 12px rgba(0, 0, 0, 0.45),
    0 12px 28px rgba(0, 0, 0, 0.25);
}
body.dark .tile.clone.stacked {
  box-shadow:
    0 5px 12px rgba(0, 0, 0, 0.45),
    0 12px 28px rgba(0, 0, 0, 0.25),
    18px 2px 0 0 #111112,
    18px 2px 0 1px #383836;
}
body.dark .menu-item {
  background: #161617;
  border-color: #3a3a38;
  color: #f0f0ee;
}
body.dark .menu-item:hover { border-color: #605e56; }
body.dark .menu-item.now {
  background: #101010;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.4);
}
body.dark .cal-day {
  background: #161617;
  border-color: #333332;
  color: #aeada8;
  box-shadow: 0 1px 1.5px rgba(0, 0, 0, 0.3);
}
body.dark .cal-day:hover:not(:disabled) {
  background: #222221;
  color: #f0f0ee;
}
body.dark .cal-day.done {
  background: #1d1c1b;
  border-color: #3a3a38;
  color: #f0f0ee;
}
body.dark .cal-day:disabled {
  background: none;
  border-color: transparent;
  box-shadow: none;
}
body.dark .cal-wd { color: #5f5e5a; }
body.dark .sw .sw-track { background: #161617; border-color: #3a3a38; }
body.dark .sw .sw-label { color: #b1b0ab; }
body.dark #hard-switch.on .sw-track {
  background: #45302a;
  border-color: #6a453c;
}
body.dark #hard-switch.on .sw-label { color: #c97f6f; }

/* shadows stay shadows after dark: the daytime ones are warm brown,
   which a dark fridge simply swallows — so everything casts black */
body.dark .tile,
body.dark .wordmark-tile {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.35),
    0 2px 6px rgba(0, 0, 0, 0.18);
}
body.dark .btn { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); }
body.dark .menu-item {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.35),
    0 2px 6px rgba(0, 0, 0, 0.18);
}
body.dark #poem,
body.dark #history,
body.dark #settings,
body.dark #help,
body.dark #calendar {
  box-shadow:
    0 8px 20px rgba(0, 0, 0, 0.45),
    0 24px 60px rgba(0, 0, 0, 0.35);
}
body.dark #menu {
  box-shadow:
    0 6px 16px rgba(0, 0, 0, 0.45),
    0 14px 34px rgba(0, 0, 0, 0.35);
}
body.dark .sw .sw-knob { box-shadow: 0 1px 1.5px rgba(0, 0, 0, 0.4); }
body.dark .cal-day.done { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); }

/* the void after dark: locked secret days keep their camouflage
   (dressed exactly like the dimmed unwritten days), freed ones go
   deep periwinkle-on-indigo */
body.dark .cal-day.void.locked {
  color: #4a4a47;
  background: none;
  border-color: transparent;
  box-shadow: none;
}
body.dark .cal-day.void.unlocked:not(.done) {
  color: #9c8fc7;
  background: #2b2839;
  border-color: #443d5c;
}
body.dark .cal-day.void.unlocked:not(.done):hover {
  background: #343050;
  color: #b6a9ea;
}
body.dark .cal-day.void.unlocked.done {
  color: #b3a4e6;
  background: #332e4a;
  border-color: #4f4670;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
body.dark .void-num,
body.dark.void-day #day-label { color: #9c8fc7; }

/* the rupture, at night: same leap, but it must land exactly on the
   dark freed look (a mismatched last frame snaps visibly) */
body.dark .cal-day.freeing { animation-name: cal-become-dark; }
@keyframes cal-become-dark {
  0%   { transform: translateY(0);
         color: #4a4a47; background: rgba(32, 32, 33, 0);
         border-color: rgba(69, 68, 63, 0); box-shadow: none; }
  5%   { transform: translateY(-2px) rotate(var(--rot, 0deg));
         color: #fdfcff; background: #2b2145; border-color: #241a3d;
         box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4); }
  30%  { transform: translateY(-11px) rotate(var(--rot, 0deg));
         color: #fdfcff; background: #2b2145; border-color: #241a3d;
         box-shadow: 0 12px 18px rgba(0, 0, 0, 0.35); }
  54%  { transform: translateY(0) rotate(var(--rot, 0deg));
         color: #fdfcff; background: #2b2145; border-color: #241a3d;
         box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); }
  66%  { transform: translateY(-3.5px) rotate(var(--rot, 0deg));
         color: #f4f1ff; background: #34285a; border-color: #2b2145;
         box-shadow: 0 5px 9px rgba(0, 0, 0, 0.33); }
  78%  { transform: translateY(0) rotate(var(--rot, 0deg));
         color: #a99ad9; background: #3a3357; border-color: #4f4670;
         box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); }
  100% { transform: translateY(0) rotate(var(--rot, 0deg));
         color: #9c8fc7; background: #2b2839; border-color: #443d5c;
         box-shadow: 0 1px 1.5px rgba(0, 0, 0, 0.3); }
}

/* the empty spot a placed magnet leaves behind in the pool — it
   holds the tile's place, unseen, until the magnet comes home */
.tile.gap {
  visibility: hidden;
  pointer-events: none;
}

/* the six-dot grip at a line's end — drag it to move the whole line */
.line-grab {
  display: inline-flex;
  align-items: center;
  align-self: center;
  margin-right: 0.5em;
  padding: 0 0.45em;
  color: #b9b5a6;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.line-grab svg { width: 0.52em; height: 0.9em; display: block; }
.line-grab:hover { color: #6d675a; }
body.line-dragging, body.line-dragging .line-grab { cursor: grabbing; }
/* the line in hand floats a little lighter while it moves */
.tile.lifting { opacity: 0.6; }
body.dark .line-grab { color: #5f5e5a; }
body.dark .line-grab:hover { color: #b1b0ab; }

/* the share-text box in settings: a finished poem shows its real
   share text here, with a copy button perched in the corner */
.setting-example-wrap { position: relative; margin-top: 10px; }
.setting-example-wrap .setting-example { margin-top: 0; }
#share-copy {
  position: absolute;
  top: 2px;
  right: 2px;
  background: none;
  border: none;
  padding: 0.25em;
  color: #8f8a7d;
  cursor: pointer;
}
#share-copy:hover { color: #33302a; }
#share-copy svg { width: 1em; height: 1em; display: block; }
#share-copy .when-copied { display: none; }
#share-copy.copied .when-copy { display: none; }
#share-copy.copied .when-copied { display: block; color: #6f8a55; }
body.dark #share-copy { color: #949390; }
body.dark #share-copy:hover { color: #e5e5e2; }

/* ---------- the big fridge: everyone's shared poems ---------- */
body.wall-mode #line,
body.wall-mode #meta,
body.wall-mode #hard-info,
body.wall-mode #pool { display: none; }
#wall-day {
  color: #8f8a7d;
  font-style: italic;
  font-size: 0.9rem;
  margin: 2px 0 18px;
  text-align: center; /* sits over the centered poem blocks */
}
#wall-cards {
  display: grid;
  grid-template-columns: 1fr; /* one poem per row, like a feed */
  gap: 400px; /* each poem gets air — they're poems, not a list */
  margin-top: 110px; /* a little less air up top, then the big gaps */
  align-items: start;
}
#wall-cards.wall-empty {
  display: block;
  color: #8f8a7d;
  font-style: italic;
  text-align: center;
}
/* poems sit straight on the fridge, no boxes — just air between */
.wall-card {
  display: block;
  text-decoration: none;
  color: inherit;
  padding: 6px 0;
}
.wall-card:hover .wall-credit { color: #6d675a; }
/* each card lays its magnets exactly like the poem card, just small */
.wall-tiles {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: center;
  row-gap: 0.3em;
  column-gap: 0.55em;
  font-size: 0.82rem;
  cursor: pointer;
}
.wall-tiles .tile { font-size: 1em; }
.wall-credit {
  margin-top: 10px;
  color: #8f8a7d;
  font-size: 0.8rem;
  font-style: italic;
  text-align: center;
}
body.dark .wall-card:hover .wall-credit { color: #b1b0ab; }
/* the little loading circle under the wall — it doubles as the
   scroll sentinel that asks for the next helping of poems */
.wall-loading {
  width: 20px;
  height: 20px;
  margin: 28px auto;
  border: 2px solid #c8c5b8;
  border-top-color: #6d675a;
  border-radius: 50%;
  animation: wall-spin 0.8s linear infinite;
}
@keyframes wall-spin { to { transform: rotate(360deg); } }
body.dark .wall-loading {
  border-color: #454543;
  border-top-color: #b1b0ab;
}


/* the wordmark and its little fridge, side by side */
.masthead { display: flex; align-items: center; gap: 0.7em; }
#fridge-link {
  color: #8f8a7d;
  display: inline-flex;
}
#fridge-link:hover { color: #33302a; }
#fridge-link svg { width: 1.15em; height: 1.35em; display: block; }
body.wall-mode #fridge-link { display: none; } /* already here */
/* the wall's longer wordmark never wraps — it shrinks to fit instead */
body.wall-mode h1 { font-size: clamp(0.92rem, 3.9vw, 1.4rem); }
body.wall-mode .wordmark-tile { white-space: nowrap; }
body.dark #fridge-link { color: #949390; }
body.dark #fridge-link:hover { color: #e5e5e2; }

/* the whole wall card is one link — every magnet shows the hand,
   even when today's board is finalized (body.done dulls tiles) */
.wall-card,
.wall-card .tile { cursor: pointer; }
/* wall magnets aren't draggable, so a touch that starts on one must
   still scroll the page (the board's tiles set touch-action: none) */
.wall-tiles .tile { touch-action: auto; }

/* ---------- the how-to-play card ---------- */
.help-row {
  display: flex;
  align-items: center;
  gap: 1em;
  margin-top: 13px;
}
.help-row p,
.help-intro {
  margin: 0;
  font-size: 0.92rem;
  color: #45412f;
}
.help-intro { margin-top: 10px; }
.help-intro.sub { margin-top: 6px; }
.help-mark {
  font-size: 1.12rem;
  padding: 0.02em 0.4em 0.1em;
  margin-right: 0.1em;
}
body.dark .help-row p,
body.dark .help-intro { color: #d6d5d0; }

/* the big friendly door out */
.help-start-row { margin-top: 20px; text-align: center; }
#help-start {
  font-size: 1.05rem;
  padding: 0.45em 2.8em;
}

/* each little stage replays its move on its own clock, then blinks
   dark at the loop seam and starts over — end states hold, exactly
   like the real fridge (an indent stays indented). moves happen in
   short fast windows to match the game's quick magnet glide. */
.help-demo {
  position: relative;
  flex-shrink: 0;
  width: 5.6em;
  height: 2.9em;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35em;
  /* a mid-animation magnet never leaks out and jiggles the card */
  overflow: hidden;
}
.help-demo.wide { width: 9.6em; }
.help-demo.lefty {
  justify-content: flex-start;
  padding-left: 2px;
}
.help-demo.tall { width: 9.6em; height: 5.2em; }
.help-demo .tile {
  cursor: default;
  touch-action: auto;
  font-size: 0.92rem;
}
.help-demo .help-arrow {
  width: 1.1em;
  height: 0.95em;
  display: block;
  margin: 0.18em 0;
}
.help-grip {
  color: #b9b5a6;
  display: inline-flex;
  flex-shrink: 0;
}
.help-grip svg { width: 8px; height: 14px; }
body.dark .help-demo .tile {
  background: #161617;
  border-color: #333332;
  color: rgba(236, 236, 233, 0.85);
}

/* the visitor's finger (or mouse): a soft touch-dot */
.help-finger {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 17px;
  height: 17px;
  margin: -8.5px;
  border-radius: 50%;
  background: rgba(72, 60, 38, 0.3);
  --fhalo: rgba(72, 60, 38, 0.1);
  --fring: rgba(72, 60, 38, 0.26);
  --fnone: rgba(72, 60, 38, 0);
  box-shadow: 0 0 0 4px var(--fhalo);
  opacity: 0;
  pointer-events: none;
  z-index: 2;
}
body.dark .help-finger {
  background: rgba(236, 236, 233, 0.32);
  --fhalo: rgba(236, 236, 233, 0.1);
  --fring: rgba(236, 236, 233, 0.28);
  --fnone: rgba(236, 236, 233, 0);
}
@keyframes help-blink {
  0%, 0.5% { opacity: 0; }
  2.5% { opacity: 1; }
  95% { opacity: 1; }
  98%, 100% { opacity: 0; }
}
.blinky { animation: help-blink 3s linear infinite; }

/* 1 — tap to place (shared beat): press, and the magnet hops to the
   line the instant the finger lands */
.d1-stage, .d9-stage {
  position: absolute;
  inset: 0;
  animation: help-blink 3s linear infinite;
}
.d1-stage .help-finger, .d9-stage .help-finger {
  left: 0;
  top: 0;
  margin: 0;
}
.d1-line {
  position: absolute;
  left: 2px;
  right: 2px;
  top: 0;
  height: 38px;
  border-bottom: 1px solid #cfccc0;
}
body.dark .d1-line { border-bottom-color: #3a3a38; }
.d1-dog {
  position: absolute;
  left: 8px;
  top: 48px;
  animation: help-d1-dog 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.d1-big { position: absolute; left: 56px; top: 48px; }
.f1 { animation: help-d1-f 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
@keyframes help-d1-dog {
  0%, 18% { translate: 0 0; }
  22%, 100% { translate: 0 -44px; }
}
@keyframes help-d1-f {
  0%, 10% { opacity: 0; transform: translate(17px, 54px); }
  14% { opacity: 1; transform: translate(17px, 54px); box-shadow: 0 0 0 4px var(--fhalo); }
  18% { transform: translate(17px, 54px) scale(0.68);
    box-shadow: 0 0 0 2px var(--fring); }
  24% { transform: translate(17px, 54px) scale(1);
    box-shadow: 0 0 0 14px var(--fnone); }
  32%, 100% { opacity: 0; transform: translate(17px, 54px);
    box-shadow: 0 0 0 14px var(--fnone); }
}

/* 1b — drag to rearrange (shared beat): carry "big" in front of
   "dog"; dog scoots aside mid-drag */
.d9-dog {
  position: absolute;
  left: 8px;
  top: 8px;
  animation: help-d9-dog 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.d9-big {
  position: absolute;
  left: 56px;
  top: 8px;
  animation: help-d9-big 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.f9 { animation: help-d9-f 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
@keyframes help-d9-dog {
  0%, 26% { translate: 0 0; }
  30%, 100% { translate: 38px 0; }
}
@keyframes help-d9-big {
  0%, 22% { translate: 0 0; }
  34%, 100% { translate: -48px 0; }
}
@keyframes help-d9-f {
  0%, 10% { opacity: 0; transform: translate(62px, 13px); }
  14% { opacity: 1; transform: translate(62px, 13px); box-shadow: 0 0 0 4px var(--fhalo); }
  18%, 22% { transform: translate(62px, 13px) scale(0.72); box-shadow: 0 0 0 3px var(--fring); }
  34% { transform: translate(15px, 13px) scale(0.72); opacity: 1; box-shadow: 0 0 0 3px var(--fring); }
  38% { transform: translate(15px, 13px) scale(1); box-shadow: 0 0 0 4px var(--fhalo); }
  46%, 100% { opacity: 0; transform: translate(15px, 13px); }
}

/* 2 — the pile (3s): press the little arrow, the pile pulls out, the
   word changes form — and stays changed */
.d2-wrap { animation: help-blink 3s linear infinite; }
.d2-tile {
  position: relative;
  /* both forms share one grid cell, so the magnet is always wide
     enough for the longer word */
  display: inline-grid;
}
.d2-tile .d2a,
.d2-tile .d2b {
  grid-area: 1 / 1;
  /* each word keeps its own width so the card can measure them */
  justify-self: start;
  width: max-content;
}
.d2-tile .d2a { animation: help-d2a 3s linear infinite; }
.d2-tile .d2b {
  opacity: 0;
  animation: help-d2b 3s linear infinite;
}
.d2-chev {
  position: absolute;
  right: -14px;
  top: 50%;
  width: 8px;
  height: 6px;
  margin-top: -3px;
  color: #99947f;
  animation: help-d2c 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.d2-tile {
  animation:
    help-d2t 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite,
    help-d2w 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
/* the magnet grows to fit its new, longer word — just like the board */
@keyframes help-d2w {
  0%, 23% { width: var(--d2-narrow, 3.7em); }
  26%, 100% { width: var(--d2-wide, 4.75em); }
}
.f2 { animation: help-f2 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
@keyframes help-f2 {
  0%, 10% { opacity: 0; transform: translate(-2px, 0px); }
  14% { opacity: 1; transform: translate(-2px, 0px); box-shadow: 0 0 0 4px var(--fhalo); }
  18% { transform: translate(-2px, 0px) scale(0.68);
    box-shadow: 0 0 0 2px var(--fring); }
  24% { transform: translate(-2px, 0px) scale(1);
    box-shadow: 0 0 0 14px var(--fnone); }
  34%, 100% { opacity: 0; transform: translate(-2px, 0px);
    box-shadow: 0 0 0 14px var(--fnone); }
}
.d2-tile {
  --d2rest:
    0 1px 2px rgba(72, 60, 38, 0.18), 0 2px 6px rgba(72, 60, 38, 0.08),
    18px 2px 0 0 #f1eee4, 18px 2px 0 1px #c9c6b7;
  --d2out:
    0 1px 2px rgba(72, 60, 38, 0.18), 0 2px 6px rgba(72, 60, 38, 0.08),
    21px 2px 0 0 #f1eee4, 21px 2px 0 1px #c9c6b7;
}
/* the dark fridge's pile is black plastic with lighter rings, and its
   shadows cast black (warm shadows vanish on a dark ground) */
body.dark .d2-tile {
  --d2rest:
    0 1px 2px rgba(0, 0, 0, 0.5), 0 2px 6px rgba(0, 0, 0, 0.3),
    18px 2px 0 0 #222221, 18px 2px 0 1px #454543;
  --d2out:
    0 1px 2px rgba(0, 0, 0, 0.5), 0 2px 6px rgba(0, 0, 0, 0.3),
    21px 2px 0 0 #222221, 21px 2px 0 1px #454543;
}
@keyframes help-d2t {
  0%, 18% { box-shadow: var(--d2rest); }
  21%, 32% { box-shadow: var(--d2out); }
  38%, 100% { box-shadow: var(--d2rest); }
}
@keyframes help-d2c {
  0%, 18% { translate: 0 0; }
  21%, 32% { translate: 0 2px; }
  38%, 100% { translate: 0 0; }
}
@keyframes help-d2a {
  0%, 23% { opacity: 1; }
  26%, 100% { opacity: 0; }
}
@keyframes help-d2b {
  0%, 23% { opacity: 0; }
  26%, 100% { opacity: 1; }
}

/* 3 — the linebreak (3s): drag a fresh ↲ onto the line; the rest of
   the line drops to a new one, quick as a reflow */
.d7-stage {
  position: absolute;
  inset: 0;
  animation: help-blink 3s linear infinite;
}
.d7-stage .help-finger { left: 0; top: 0; margin: 0; }
.d7-so {
  position: absolute;
  left: 2px;
  top: 4px;
  animation: help-d7-so 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.d7-cold {
  position: absolute;
  left: 42px;
  top: 4px;
  animation: help-d7-cold 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.d7-brk {
  position: absolute;
  left: 72px;
  top: 44px;
  animation: help-d7-brk 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
/* the moment a second line exists, its drag dots grow in */
.d7-g1, .d7-g2 {
  position: absolute;
  left: 2px;
  opacity: 0;
  animation: help-d7-g 3s linear infinite;
}
.d7-g1 { top: 10px; }
.d7-g2 { top: 44px; }
@keyframes help-d7-g {
  0%, 29% { opacity: 0; }
  32%, 100% { opacity: 1; } /* the instant "cold" starts to move */
}
.f7 { animation: help-d7-f 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
@keyframes help-d7-so {
  0%, 29% { translate: 0 0; }
  32%, 100% { translate: 12px 0; }
}
@keyframes help-d7-brk {
  0%, 22% { translate: 0 0; }
  32%, 100% { translate: -20px -40px; }
}
@keyframes help-d7-cold {
  0%, 29% { translate: 0 0; }
  32%, 100% { translate: -28px 34px; }
}
@keyframes help-d7-f {
  0%, 10% { opacity: 0; transform: translate(74px, 49px); }
  14% { opacity: 1; transform: translate(74px, 49px); box-shadow: 0 0 0 4px var(--fhalo); }
  18%, 22% { transform: translate(74px, 49px) scale(0.72); box-shadow: 0 0 0 3px var(--fring); }
  34% { transform: translate(43px, 9px) scale(0.72); opacity: 1; box-shadow: 0 0 0 3px var(--fring); }
  38% { transform: translate(43px, 9px) scale(1); box-shadow: 0 0 0 4px var(--fhalo); }
  46%, 100% { opacity: 0; transform: translate(43px, 9px); }
}

/* 4 — rearranging lines (3s): carry the top line below its
   neighbour; the neighbour hops up the instant they cross */
.d5-stage {
  position: absolute;
  inset: 0;
  animation: help-blink 3s linear infinite;
}
.d5-stage .help-finger { left: 0; top: 0; margin: 0; }
.d5-l1, .d5-l2 {
  position: absolute;
  left: 2px;
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
}
.d5-l1 { top: 4px; animation: help-d5-l1 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
.d5-l2 { top: 40px; animation: help-d5-l2 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
.f5 { animation: help-d5-f 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
@keyframes help-d5-l1 {
  0%, 22% { translate: 0 0; }
  34%, 100% { translate: 0 36px; }
}
@keyframes help-d5-l2 {
  0%, 26% { translate: 0 0; }
  29%, 100% { translate: 0 -36px; }
}
@keyframes help-d5-f {
  0%, 10% { opacity: 0; transform: translate(1px, 9px); }
  14% { opacity: 1; transform: translate(1px, 9px); box-shadow: 0 0 0 4px var(--fhalo); }
  18%, 22% { transform: translate(1px, 9px) scale(0.7); box-shadow: 0 0 0 3px var(--fring); }
  34% { transform: translate(1px, 45px) scale(0.7); opacity: 1; box-shadow: 0 0 0 3px var(--fring); }
  38% { transform: translate(1px, 45px) scale(1); box-shadow: 0 0 0 4px var(--fhalo); }
  46%, 100% { opacity: 0; transform: translate(1px, 45px); }
}

/* 5 — the indent (3s): grab the second line, slide it right; it
   stays slid until the stage blinks and replays. lines share the
   rearrange demo's left edge. */
.d4-stage {
  position: absolute;
  inset: 0;
  animation: help-blink 3s linear infinite;
}
.d4-stage .help-finger { left: 0; top: 0; margin: 0; }
.d4-l1, .d4-l2 {
  position: absolute;
  left: 2px;
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
}
.d4-l1 { top: 4px; }
.d4-l2 { top: 40px; animation: help-d4 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
.f4 { animation: help-f4 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
@keyframes help-d4 {
  0%, 22% { translate: 0 0; }
  34%, 100% { translate: 20px 0; }
}
@keyframes help-f4 {
  0%, 10% { opacity: 0; transform: translate(1px, 45px); }
  14% { opacity: 1; transform: translate(1px, 45px); box-shadow: 0 0 0 4px var(--fhalo); }
  18%, 22% { transform: translate(1px, 45px) scale(0.7); box-shadow: 0 0 0 3px var(--fring); }
  34% { transform: translate(21px, 45px) scale(0.7); box-shadow: 0 0 0 3px var(--fring); }
  38% { transform: translate(21px, 45px) scale(1); box-shadow: 0 0 0 4px var(--fhalo); }
  46%, 100% { opacity: 0; transform: translate(21px, 45px); }
}

/* 6 — placing a gap magnet (3s): dragged from the pool to sit
   between two words; "ice" scoots aside for the caret */
.d8-stage {
  position: absolute;
  inset: 0;
  animation: help-blink 3s linear infinite;
}
.d8-stage .help-finger { left: 0; top: 0; margin: 0; }
.d8-hot { position: absolute; left: 2px; top: 4px; }
.d8-ice {
  position: absolute;
  left: 40px;
  top: 4px;
  animation: help-d8-ice 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.d8-spc {
  position: absolute;
  left: 64px;
  top: 44px;
  animation: help-d8-spc 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.f8 { animation: help-d8-f 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
@keyframes help-d8-ice {
  0%, 28% { translate: 0 0; }
  32%, 100% { translate: 32px 0; }
}
@keyframes help-d8-spc {
  0%, 22% { translate: 0 0; }
  34%, 100% { translate: -24px -40px; }
}
@keyframes help-d8-f {
  0%, 10% { opacity: 0; transform: translate(70px, 48px); }
  14% { opacity: 1; transform: translate(70px, 48px); box-shadow: 0 0 0 4px var(--fhalo); }
  18%, 22% { transform: translate(70px, 48px) scale(0.72); box-shadow: 0 0 0 3px var(--fring); }
  34% { transform: translate(46px, 9px) scale(0.72); opacity: 1; box-shadow: 0 0 0 3px var(--fring); }
  38% { transform: translate(46px, 9px) scale(1); box-shadow: 0 0 0 4px var(--fhalo); }
  46%, 100% { opacity: 0; transform: translate(46px, 9px); }
}

/* 7 — the gap magnet dragged wider: same resting layout as the
   placement row above, then ↔ and everything after it slide right */
.d3-stage {
  position: absolute;
  inset: 0;
  animation: help-blink 3s linear infinite;
}
.d3-stage .help-finger { left: 0; top: 0; margin: 0; }
.d3-hot { position: absolute; left: 2px; top: 8px; }
.d3-spc {
  position: absolute;
  left: 40px;
  top: 8px;
  animation: help-d3 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.d3-ice {
  position: absolute;
  left: 72px;
  top: 8px;
  animation: help-d3 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.f3 { animation: help-f3 3s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; }
@keyframes help-d3 {
  0%, 22% { translate: 0 0; }
  34%, 100% { translate: 18px 0; }
}
@keyframes help-f3 {
  0%, 10% { opacity: 0; transform: translate(46px, 12px); }
  14% { opacity: 1; transform: translate(46px, 12px); box-shadow: 0 0 0 4px var(--fhalo); }
  18%, 22% { transform: translate(46px, 12px) scale(0.72); box-shadow: 0 0 0 3px var(--fring); }
  34% { transform: translate(64px, 12px) scale(0.72); opacity: 1; box-shadow: 0 0 0 3px var(--fring); }
  38% { transform: translate(64px, 12px) scale(1); box-shadow: 0 0 0 4px var(--fhalo); }
  46%, 100% { opacity: 0; transform: translate(64px, 12px); }
}

/* stillness for those who asked for it */
@media (prefers-reduced-motion: reduce) {
  .help-demo *, .help-finger, .blinky { animation: none !important; }
  .help-finger { display: none; }
  .d1-dog { translate: 0 -44px; }
  .d9-dog { translate: 38px 0; }
  .d9-big { translate: -48px 0; }
  .d7-so { translate: 12px 0; }
  .d8-ice { translate: 32px 0; }
  .d3-spc, .d3-ice { translate: 18px 0; }
  .d8-spc { translate: -24px -40px; }
  .d7-brk { translate: -20px -40px; }
  .d7-cold { translate: -28px 34px; }
  .d7-g1, .d7-g2 { opacity: 1; }
  .d5-l1 { translate: 0 36px; }
  .d5-l2 { translate: 0 -36px; }
}

/* the glyphs in the captions are tiny magnets themselves */
.help-glyph {
  display: inline-block;
  background: #fffffe;
  border: 1px solid #c8c5b8;
  padding: 0 0.3em 0.05em;
  font-size: 0.88em;
  line-height: 1.25;
  white-space: pre;
  box-shadow: 0 1px 2px rgba(72, 60, 38, 0.15);
  transform: rotate(-1deg);
  margin: 0 0.1em;
}
.help-glyph .help-cap-arrow {
  width: 0.95em;
  height: 0.8em;
  display: inline-block;
  vertical-align: -0.08em;
}
body.dark .help-glyph {
  background: #161617;
  border-color: #333332;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

/* the how-to card stretches taller when the screen allows — less
   scrolling through the demos */
#help {
  top: 6%;
  max-height: 86vh;
}

/* the card's scrollbar earns a bit more presence on desktop */
#help {
  scrollbar-width: auto;
  scrollbar-color: #b5b1a2 transparent;
}
#help::-webkit-scrollbar { width: 11px; }
#help::-webkit-scrollbar-thumb {
  background: #b5b1a2;
  border-radius: 6px;
  border: 2px solid #fefdf9;
}
body.dark #help { scrollbar-color: #55554f transparent; }
body.dark #help::-webkit-scrollbar-thumb {
  background: #55554f;
  border-color: #1a1a1b;
}

/* a shared poem link opens its card plainly — no entrance animation */
body.visiting #poem { animation: none; }

/* clicking the poem clears the room: card chrome, buttons, credit,
   and the whole page behind it fade away — just magnets on the
   fridge. clicking again brings everything back. */
#poem {
  transition: background 0.3s ease, border-color 0.3s ease,
    box-shadow 0.3s ease;
}
#poem > * { transition: opacity 0.3s ease; }
body.poem-focus #poem {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  scrollbar-color: transparent transparent;
}
body.poem-focus #poem::-webkit-scrollbar-thumb { background: transparent; }
body.poem-focus #poem > :not(#poem-tiles):not(#poem-credit) {
  opacity: 0;
  pointer-events: none;
}
/* the attribution stays — centered, dateless, untouchable */
.credit-line { display: inline-block; }
#poem-credit .credit-when { transition: opacity 0.3s ease; }
body.poem-focus #poem-credit { pointer-events: none; }
body.poem-focus #poem-credit .credit-when { opacity: 0; }
body.poem-focus main > :not(#poem) { opacity: 0 !important; }
