@font-face { font-family: Inter; src: url('../assets/fonts/inter-variable.woff2') format('woff2'); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: 'Grenze Gotisch'; src: url('../assets/fonts/grenze-gotisch-variable.woff2') format('woff2'); font-weight: 100 900; font-style: normal; font-display: swap; }
/* The room frames its latest change through these values, and the drawer lowers through --drawer-drop; registering them lets them move smoothly. */
@property --fx { syntax: '<number>'; inherits: true; initial-value: .5; }
@property --fy { syntax: '<number>'; inherits: true; initial-value: .3; }
@property --drawer-drop { syntax: '<length>'; inherits: true; initial-value: 0px; }
/* Dark mode is the default: the bistro by lamplight, walnut and plum surfaces warmed by candles, not cool grey. */
:root {
  color-scheme: dark;
  --page: #1c1614; --panel: #2a201e; --surface: #33272a; --inset: #382b29; --chosen: #56423a;
  --ink: #f5e9d8; --muted: #cdb7a6; --line: #544039; --accent: #ecc1a2;
  --action: #e8b58e; --on-action: #2a2028; --gold: #e8bd83; --focus: #8fd0ca;
  --tile-a: #47362f; --tile-b: #3b2c27; --selected: #e8b58e; --ready: #9ecea1;
  --control-line: #8c7064; --coin-face: #e8bd83; --coin-rim: #8f5f2e; --cat-glow: drop-shadow(0 0 1px #e8b58e80) drop-shadow(0 3px 10px #e8b58e30); --tile-lift: 0 1px 2px #2a1a1040;
  --shadow: 0 9px 26px #0a060433; --radius: 14px; --control-radius: 9px; --tile-radius: 6px; --card-radius: 12px; --dialog-radius: 18px;
  font-family: Inter, system-ui, sans-serif; color: var(--ink); background: var(--page);
  font-optical-sizing: auto; font-synthesis: none;
}
/* Light mode: cream and parchment with plum and dark brown ink. The System choice takes it on a light device. */
:root[data-theme='light'] {
  color-scheme: light;
  --page: #eee7dc; --panel: #f8f2e8; --surface: #fffbf3; --inset: #e9dfd0; --chosen: #fffbf3;
  --ink: #33292a; --muted: #6d5853; --line: #d6c6b9; --accent: #6e3d50;
  --action: #6e3d50; --on-action: #fff6ea; --gold: #835121; --focus: #276d6c;
  --tile-a: #f2e7d5; --tile-b: #e7d8c2; --selected: #9b6644; --ready: #3e6848;
  --control-line: #8f7a70; --coin-face: #d39a5c; --coin-rim: #835121; --cat-glow: none;
  --shadow: 0 9px 26px #42282412;
}
@media (prefers-color-scheme: light) {
  :root[data-theme='system'] {
    color-scheme: light;
    --page: #eee7dc; --panel: #f8f2e8; --surface: #fffbf3; --inset: #e9dfd0; --chosen: #fffbf3;
    --ink: #33292a; --muted: #6d5853; --line: #d6c6b9; --accent: #6e3d50;
    --action: #6e3d50; --on-action: #fff6ea; --gold: #835121; --focus: #276d6c;
    --tile-a: #f2e7d5; --tile-b: #e7d8c2; --selected: #9b6644; --ready: #3e6848;
    --control-line: #8f7a70; --coin-face: #d39a5c; --coin-rim: #835121; --cat-glow: none;
    --shadow: 0 9px 26px #42282412;
  }
}
* { box-sizing: border-box; scrollbar-color: var(--line) var(--page); scrollbar-width: thin; }
body { margin: 0; min-width: 320px; background: var(--page); }
button, input { font: inherit; color: inherit; }
button { cursor: pointer; touch-action: manipulation; transition: transform .15s; }
button:disabled { cursor: default; }
button:not(:disabled):active { transform: translateY(1px); }
button:focus-visible, a:focus-visible, input:focus-visible, summary:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
a { color: var(--accent); text-underline-offset: 4px; }
::selection { background: var(--action); color: var(--on-action); }
h1,h2,h3,p { margin: 0; }
h1,h2,h3 { font-family: Inter, system-ui, sans-serif; font-weight: 600; text-wrap: balance; letter-spacing: -.025em; }
h1,h2 { font-size: 21px; line-height: 1.3; }
h3 { font-size: 19px; line-height: 1.4; }
img { max-width: 100%; object-fit: contain; }
svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.skip-link { position: absolute; left: 16px; top: -100px; z-index: 100; background: var(--surface); padding: 12px; }
.skip-link:focus { top: 10px; }
.visually-hidden,.room-caption,.game-layout:is([data-offer],[data-selected]) .mara-line { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* The coin figures share the wordmark baseline. */
.masthead { display: flex; gap: 20px; align-items: baseline; }
.brand { display: flex; align-items: baseline; gap: 24px; min-width: 0; }
/* The cat is an empty box, so its bottom edge sits on the wordmark baseline. */
.wordmark { display: flex; align-items: baseline; gap: 8px; font: 600 48px/1 'Grenze Gotisch', serif; letter-spacing: 0; color: var(--ink); white-space: nowrap; }
/* Cropped to the sitting cat's alpha bounds (252,119)–(638,753) in the 1536px mascot atlas. */
.wordmark .mascot { height: 1.2em; aspect-ratio: 386/634; flex-shrink: 0; background-size: 397.93% 242.27%; background-position: 21.913% 13.193%; filter: var(--cat-glow); }
.tagline { color: var(--muted); font-size: 13px; white-space: nowrap; }
.header-controls { margin-left: auto; flex-shrink: 0; display: flex; align-items: center; gap: 16px; }
.coin-count { position: relative; display: flex; align-items: baseline; gap: 8px; padding-right: 16px; border-right: 1px solid var(--line); color: var(--gold); font-variant-numeric: tabular-nums; white-space: nowrap; }
.coin { align-self: center; width: 22px; height: 22px; flex-shrink: 0; }
.coin-face { fill: var(--coin-face); stroke: var(--coin-rim); stroke-width: 1.5; }
.coin-moon { fill: var(--coin-rim); stroke: none; }
#coins { font: 600 24px/1 Inter,sans-serif; }
.coin-label { font-size: 13px; }
.coin-delta { position: absolute; left: 28px; bottom: 100%; font: 600 13px/1 Inter,sans-serif; color: var(--gold); opacity: 0; pointer-events: none; animation: coin-rise .9s cubic-bezier(.16,1,.3,1); }
.coin-count.gained .coin { animation: coin-flip .7s cubic-bezier(.16,1,.3,1); }
@keyframes coin-rise { 0% { opacity: 0; transform: translateY(14px); } 25% { opacity: 1; } 100% { opacity: 0; transform: translateY(-4px); } }
@keyframes coin-flip { to { transform: rotateY(360deg); } }
.options-button { display: inline-flex; align-items: center; gap: 9px; min-height: 44px; padding: 0 16px 0 12px; border: 1px solid var(--control-line); border-radius: var(--control-radius); background: var(--surface); font-size: 14px; font-weight: 600; white-space: nowrap; }
.icon-button { width: 44px; height: 44px; border: 1px solid var(--control-line); border-radius: var(--control-radius); display: grid; place-items: center; padding: 9px; background: var(--surface); }
/* An accent-tinted fill plus border keeps hover visible on both themes. */
@media (hover: hover) { .options-button:hover,.icon-button:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--surface)); } }

/* The room and the drawer. The room is one 3:4 painting of an area, filling the room behind everything. --view-h is the height of
   room that shows above the drawer; the frame places the latest change (--fx, --fy) in the middle of it, and never shows past the painting's edges. */
.room { overflow: hidden; }
.room-stage { position: absolute; inset: 0; margin: 0; overflow: hidden; background: #2b2228; container-type: size; }
.room-frame {
  --h: calc(var(--frame-w) * 4 / 3);
  position: absolute; width: var(--frame-w); height: var(--h); container-type: size;
  left: clamp(calc(100cqw - var(--frame-w)), calc(50cqw - var(--frame-w) * var(--fx)), 0px);
  top: clamp(min(0px, calc(var(--view-h) - var(--h))), calc(var(--view-h) / 2 - var(--h) * var(--fy) + var(--pin-pan, 0px)), 0px);
}
.room-frame.settled { transition: --fx .9s cubic-bezier(.16,1,.3,1), --fy .9s cubic-bezier(.16,1,.3,1); }
/* The paintings are scenery: a long press or a drag on them never picks up the image. */
.room-paintings,.room-painting { position: absolute; inset: 0; pointer-events: none; }
.room-painting img { display: block; width: 100%; height: 100%; max-width: none; }
.room-painting.entering { opacity: 0; }
.room-decorations,.decoration-layer { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/* A finish that a quest unlocked switches where it stands in the room. The badge marks it; hover and focus outline its place. */
.room-finishes { position: absolute; inset: 0; pointer-events: none; }
.room-finish { position: absolute; z-index: 2; min-width: 44px; min-height: 44px; padding: 0; border: 0; border-radius: 8px; background: transparent; pointer-events: auto; cursor: pointer; }
.room-finish:hover,.room-finish:focus { outline: 2px dashed var(--coin-face); outline-offset: 2px; }
.swap-mark { position: absolute; top: -10px; right: -10px; width: 26px; height: 26px; }
.swap-mark circle { fill: var(--surface); stroke: var(--coin-rim); stroke-width: 1.5; }.swap-mark path { stroke: var(--ink); stroke-width: 1.8; }
.room-finish[inert] { visibility: hidden; }
.room-stage[data-failed] :is(.room-decorations,.room-finishes) { display: none; }
/* Miez sits on the left end of the front room's windowsill (its top 47.2% down the painting); the sitting cat's paws are 95.5% down its sprite cell. */
.sill-cat { position: absolute; left: 62.65%; bottom: 52.4%; width: 11.73%; aspect-ratio: 1; min-width: 44px; }
.miez { padding: 0; border: 0; border-radius: var(--control-radius); background: transparent; }
.sill-cat>.mascot { width: 100%; height: 100%; }
/* In the room ready for the supper, a second black cat sleeps on the counter's free left end, its body on the counter top 83.5% down. */
.counter-cat { position: absolute; left: 1.05%; bottom: 15.6%; width: 11.73%; aspect-ratio: 1; pointer-events: none; }
.room-frame .mascot { filter: var(--cat-glow); }
/* The dusk beyond the mended window's glass, where a bat sometimes crosses: a rectangle measured on the window of states 01 on. */
.window-sky { position: absolute; left: 71%; top: 24.5%; width: 19.4%; height: 21%; overflow: hidden; pointer-events: none; }
.window-sky .bat { position: absolute; left: 0; top: 0; width: 34%; aspect-ratio: 1; animation: flap .16s ease-in-out infinite alternate; }
@keyframes flap { to { scale: 1 .62; } }
.room-frame:not([data-area='front-room']) :is(.sill-cat,.window-sky,.counter-cat),
.room-frame[data-painting='front-room-00'] .window-sky,
.room-frame:not([data-current='front-room-24']) .counter-cat { display: none; }
/* The New pin: a small copper-glow marker whose point touches the latest change. Near the top of the painting it hangs below the change instead. */
/* The pin sits above the edge of the change; --shift slides it inside the room while its tail stays on the mark. */
.room-pin { --shift: 0px; position: absolute; z-index: 3; translate: calc(-50% + var(--shift)) calc(-100% - 9px); display: inline-flex; align-items: center; gap: 6px; min-height: 28px; padding: 4px 11px 4px 8px; border: 0; border-radius: 14px; background: var(--panel); color: var(--ink); font-size: 12px; font-weight: 600; line-height: 1; white-space: nowrap; box-shadow: 0 6px 16px #1009122e; }
.room-pin::before { content: ''; position: absolute; inset: -8px -4px; }
.room-pin::after { content: ''; position: absolute; left: calc(50% - var(--shift)); top: 100%; width: 10px; height: 10px; translate: -50% -50%; rotate: 45deg; background: var(--panel); border-radius: 2px; }
.room-pin[data-below] { translate: calc(-50% + var(--shift)) 9px; }
.room-pin[data-bare] .pin-label { display: none; }
.pin-label { font-weight: 400; }
.room-pin[data-below]::after { top: 0; }
.room-pin[hidden] { display: none; }
.pin-dot { position: relative; width: 9px; height: 9px; border-radius: 50%; background: var(--coin-face); box-shadow: 0 0 0 2px var(--panel), 0 0 8px 3px #e8b58eb3; }
/* The area switch sits in the room's lower corner, on the side away from the change. A locked area has the dashed "not yet" edge. */
.area-switch { position: absolute; z-index: 4; top: calc(var(--view-h) - 64px); display: flex; gap: 2px; padding: 3px; background: var(--panel); border: 1px solid var(--control-line); border-radius: var(--control-radius); box-shadow: 0 6px 16px #1009122e; }
.area-switch[data-side='left'] { left: 12px; }
.area-switch:not([data-side='left']) { right: 12px; }
.area-switch:empty { display: none; }
.area-choice { min-width: 44px; min-height: 44px; padding: 0 12px; border: 0; border-radius: var(--tile-radius); background: transparent; color: var(--muted); font-size: 13px; white-space: nowrap; }
.area-choice[aria-pressed='true'] { background: var(--chosen); color: var(--ink); font-weight: 600; box-shadow: inset 0 0 0 2px var(--accent), 0 1px 3px #2a1d2024; }
.area-choice[aria-disabled='true'] { cursor: not-allowed; outline: 1px dashed var(--control-line); outline-offset: -4px; }
.area-choice:focus-visible { outline-offset: -3px; }
@media (hover: hover) { .area-choice:not([aria-pressed='true'],[aria-disabled='true']):hover { color: var(--ink); } }
/* A painting that cannot load leaves the room in words. */
.room-stage[data-failed] .room-caption { position: absolute; inset: 16px 16px auto; width: auto; height: auto; max-height: calc(var(--view-h) - 96px); margin: 0; overflow: auto; clip-path: none; white-space: normal; padding: 14px 16px; background: var(--panel); border: 1px dashed var(--control-line); border-radius: var(--control-radius); color: var(--ink); font-size: 14px; line-height: 1.6; }
.room-stage:not([data-failed]) .room-missing { display: none; }
.room-missing { margin-bottom: 8px; }
.room-name { font-weight: 600; }
.room-changes { margin: 6px 0 0; padding-left: 18px; color: var(--muted); }
.room-changes li::marker { color: var(--accent); }

/* The drawer: the quests on paper tickets, the board on timber between cross-stitch runners, and Mara's line or the selected item's actions. */
.drawer { background: var(--panel); }
.drawer-handle { display: none; }
.tickets { position: relative; }
/* Three quest tickets, and a fourth for the recovery quest while it is open. */
.ticket-row { display: grid; grid-template-columns: repeat(var(--tickets, 3), minmax(0, 1fr)); }
.ticket { position: relative; min-width: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--control-radius); box-shadow: 0 1px 2px #2a1a1029; }
.ticket .portrait { width: 36px; height: 36px; }
/* The face of a ticket is one target that opens the quest. Its title is the reading cue, in the accent of things that the player can press. */
.ticket-face { min-width: 0; min-height: 44px; padding: 0; border: 0; border-radius: var(--tile-radius); background: transparent; color: inherit; text-align: left; }
.ticket-words { display: grid; min-width: 0; }
.ticket-name,.ticket-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ticket-name { font-size: 13px; font-weight: 600; line-height: 1.3; }
.ticket-title { color: var(--accent); font-size: 12px; line-height: 1.4; text-underline-offset: 3px; }
@media (hover: hover) { .ticket-face:hover .ticket-title { text-decoration: underline; } }
.ticket-items { display: flex; justify-content: center; align-items: center; gap: 2px; }
.ticket-item { position: relative; display: grid; place-items: center; width: 44px; height: 44px; border-radius: var(--tile-radius); }
.ticket-item .food { width: 38px; height: 38px; }
.ticket-item.ready::after { content: ''; position: absolute; right: 1px; bottom: 3px; width: 9px; height: 9px; background: var(--ready); border: 2px solid var(--surface); border-radius: 50%; }
/* A dish that a quest needs more than once shows how many the board holds, out of how many. */
.ticket-count { position: absolute; left: 0; bottom: 0; padding: 0 3px; border-radius: 6px; background: var(--surface); color: var(--ink); font-size: 10px; font-weight: 600; line-height: 14px; font-variant-numeric: tabular-nums; box-shadow: 0 0 0 1px var(--line); }
.ticket-items.many .ticket-item { width: 34px; }.ticket-items.many .food { width: 30px; height: 30px; }
/* The recovery quest is an offer, not a campaign quest: its ticket has a dashed edge. */
.recovery-ticket { grid-column: -2; border-style: dashed; }
.ticket-more { color: var(--muted); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
.tickets-empty { grid-column: 1 / -1; margin: 0; padding: 12px; color: var(--muted); font-size: 13px; text-align: center; }
.ticket-row:has(.recovery-ticket) .tickets-empty { grid-column: 1 / -2; }
.deliver-button { display: flex; align-items: center; justify-content: center; gap: 5px; min-height: 44px; padding: 6px; font-size: 13px; white-space: nowrap; }
.deliver-button .coin { width: 16px; height: 16px; }
.deliver-button.guide-target { outline: 2px dotted color-mix(in srgb, var(--muted) 50%, transparent); outline-offset: -4px; }
.deliver-button.guide-target:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
.ticket.arriving { animation: ticket-in .45s cubic-bezier(.16,1,.3,1) var(--rise-delay) both; }
@keyframes ticket-in { from { opacity: 0; visibility: hidden; translate: 0 10px; } }
.deliver-flight { position: fixed; z-index: 100; pointer-events: none; filter: drop-shadow(0 7px 5px #17101a65); }
/* Each opaque painting offers AVIF first and WebP for browsers without it; phones load the smaller timber. */
.table { overflow: hidden; background: url('../assets/variants/timber-tabletop-1536x1536.webp') center / cover; background-image: image-set(url('../assets/variants/timber-tabletop-1536x1536.avif') type('image/avif'), url('../assets/variants/timber-tabletop-1536x1536.webp') type('image/webp')); }
.runner { display: block; width: 100%; height: var(--runner-h); stroke: none; }
.runner-source { position: absolute; width: 0; height: 0; overflow: hidden; }
.board { display: grid; grid-template-columns: repeat(6,var(--cell)); grid-template-rows: repeat(7,var(--cell)); gap: var(--gap); justify-content: center; }
.cell { min-width: 0; min-height: 0; position: relative; background: var(--tile-a); border: 0; border-radius: var(--tile-radius); padding: 5px; display: grid; place-items: center; touch-action: none; box-shadow: var(--tile-lift); }
.cell:nth-child(12n+2),.cell:nth-child(12n+4),.cell:nth-child(12n+6),.cell:nth-child(12n+7),.cell:nth-child(12n+9),.cell:nth-child(12n+11) { background: var(--tile-b); }
.cell .food { width: 100%; height: 100%; pointer-events: none; }
.cell.obstacle { box-shadow: inset 0 0 0 2px var(--control-line), var(--tile-lift); }
.cell.obstacle::before { content: ''; position: absolute; inset: 0; border-radius: inherit; background: rgb(184 38 44 / 20%); z-index: 3; pointer-events: none; }
.cell.obstacle.clutter { background: var(--tile-b); }
.cell.obstacle .food { width: 70%; height: 70%; }
.blocker-mark { position: absolute; right: 2px; bottom: 2px; width: 16px; height: 16px; z-index: 4; pointer-events: none; }
.blocker-mark circle { fill: var(--panel); stroke: var(--control-line); stroke-width: 1.7; }
.blocker-mark path { stroke: var(--ink); }
.clutter-art,.preparation-art { position: absolute; inset: 2px; display: block; pointer-events: none; background-repeat: no-repeat; }
.clutter-art { background-image: url('../assets/variants/board-clutter-1536x1024.webp'); }
.clutter-object { z-index: 1; }
.clutter-overlay { z-index: 2; }
.preparation-art { background-image: url('../assets/variants/preparation-clutter-1448x1086.webp'); }
.cell.empty::after { content: ''; width: 4px; height: 4px; background: var(--muted); opacity: .3; border-radius: 50%; }
.cell.selected { box-shadow: inset 0 0 0 3px var(--selected), var(--tile-lift); }
.cell:focus-visible { outline-offset: -3px; }
.cell:not(.selected):hover { box-shadow: inset 0 0 0 2px var(--selected), var(--tile-lift); }
.cell:is(.blocker-target,.merge-target,.guide-target) { outline: 2px dotted color-mix(in srgb, var(--muted) 50%, transparent); outline-offset: -4px; }
.cell:is(.blocker-target,.merge-target,.guide-target):focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
.source-mark { position: absolute; right: 3px; bottom: 3px; width: 17px; height: 17px; pointer-events: none; }
.source-mark circle { fill: var(--action); stroke: var(--tile-a); stroke-width: 1.5; }.source-mark path { stroke: var(--on-action); stroke-width: 2.6; }
/* A paid source shows the coins of one take. The Herb basket is free and shows none. */
.take-cost { position: absolute; left: 3px; bottom: 3px; display: flex; align-items: center; gap: 1px; padding: 0 5px 0 1px; border-radius: 9px; background: var(--panel); color: var(--ink); font-size: 11px; font-weight: 600; line-height: 16px; font-variant-numeric: tabular-nums; pointer-events: none; box-shadow: 0 0 0 1px var(--control-line); }
.take-cost .coin { width: 14px; height: 14px; }
.cell.hint { animation: hint-pulse .75s ease-in-out 3; }
/* A merged or new item settles onto its tile; the first of each dish arrives with a small flourish. */
.cell.settle .food { animation: settle .18s cubic-bezier(.16,1,.3,1); }
.cell.first .food { animation: first-taste .7s cubic-bezier(.16,1,.3,1); }
@keyframes settle { from { transform: scale(.82); } }
@keyframes first-taste { 0% { transform: scale(.55) rotate(-8deg); } 60% { transform: scale(1.12) rotate(2deg); } }
@keyframes hint-pulse { 50% { box-shadow: inset 0 0 0 4px var(--focus), var(--tile-lift); } }
/* Mara's line and the selected item's actions share one place under the board: the actions replace the line while an item is selected. */
.mara-line { display: flex; align-items: center; gap: 10px; width: 100%; }
.mara-line .portrait { width: 38px; height: 38px; flex-shrink: 0; }
.mara-line p { flex: 1; min-width: 0; font-size: 14px; line-height: 1.45; text-wrap: pretty; }
.mara-line .text-button { flex-shrink: 0; padding: 0; font-size: 13px; }
/* While the next preparation is affordable and no tile is selected, Mara offers it by name with Pay; a selected tile still wins the place. */
.game-layout:not([data-offer]) .offer,.game-layout[data-selected] .offer { display: none; }
body:has(#modal[open] .pay-button) #offer { visibility: hidden; }
.offer { display: flex; align-items: center; gap: 10px; width: 100%; }
.offer .portrait { width: 38px; height: 38px; flex-shrink: 0; }
.offer p { flex: 1; min-width: 0; font-size: 13px; line-height: 1.35; }
.offer strong { display: block; font-size: 14px; font-weight: 600; }
.offer span { color: var(--muted); }
.offer .pay-button { flex-shrink: 0; padding: 10px 14px; font-size: 13px; }
/* Keep status announcements available, but remove the hidden action from keyboard navigation. */
.game-layout[data-offer] #hint-button,.game-layout[data-selected] #hint-button { display: none; }
.game-layout:not([data-selected]) #item-detail { display: none; }
#item-detail { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; width: 100%; }
#item-detail.blocker-help { flex-wrap: nowrap; }
.blocker-copy { flex: 1; min-width: 0; }
.blocker-title { display: block; font-size: 13px; line-height: 1.3; }
.blocker-rule { font-size: 12px; line-height: 1.4; color: var(--ink); }
.blocker-help>.clear-selection { flex-shrink: 0; padding: 9px; }
.detail-head { display: flex; flex: 1 1 170px; align-items: center; gap: 10px; min-width: 0; }
.detail-head .food { width: 44px; height: 44px; flex-shrink: 0; }
.detail-words { min-width: 0; }
.detail-words h3 { font-size: 15px; line-height: 1.25; }
.detail-next,.detail-description { font-size: 12px; color: var(--muted); line-height: 1.4; }
.item-actions { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.item-actions button { font-size: 13px; padding: 10px 12px; }
.item-actions .clear-selection { padding: 9px; }
.guide-stop { min-width: 44px; font-weight: 600; }
.completion-message { margin-top: 16px; font-size: 13px; line-height: 1.5; }
/* The supper: the painting of the neighbours at the courtyard tables, the ending, and the way on. */
.supper-view { text-align: center; }
.supper-painting img { display: block; width: auto; max-width: 100%; height: auto; max-height: min(62dvh, 680px); margin: 0 auto; border-radius: var(--card-radius); }
.supper-view .completion-message { margin: 14px 0 16px; }
.pay-button,.quest-deliver { display: flex; align-items: center; justify-content: center; gap: 6px; }
.pay-button .coin,.quest-deliver .coin { width: 16px; height: 16px; }
.chapter-name { font-size: 13px; color: var(--accent); margin-top: 5px; }
.chapter-title { font-size: 19px; line-height: 1.25; color: var(--accent); text-wrap: balance; }
.chapter-objective { font-size: 12px; color: var(--muted); line-height: 1.45; margin-top: 1px; }
/* The chapter's preparations: a filled pip for each done, a ringed pip for the current one, and a dashed pip for each still to come. */
.chapter-steps { display: flex; align-items: center; gap: 10px; margin-top: 4px; font-size: 12px; color: var(--muted); }
.chapter-steps ol { display: flex; gap: 5px; list-style: none; margin: 0; padding: 0; }
.chapter-steps li { width: 18px; height: 6px; border-radius: 3px; border: 1px dashed var(--control-line); }
.chapter-steps li[data-step='done'] { background: var(--accent); border: 1px solid var(--accent); }
.chapter-steps li[data-step='now'] { border: 1px solid var(--accent); }
/* The 44px target of Read now reaches into the space above and below the row, so the row adds only one line to the story. */
.story-waiting { display: flex; align-items: center; flex-wrap: wrap; column-gap: 12px; margin-top: 4px; font-size: 13px; line-height: 1.5; }
.story-waiting .text-button { margin-block: -12px; }
.scene-unsaved { margin: 16px 0 0; }
.task-content { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.task-content h3 { margin-bottom: 5px; }
.task-content p { font-size: 13px; color: var(--muted); line-height: 1.55; margin-bottom: 10px; }
.task-payment { display: flex; align-items: center; gap: 10px; }
.task-payment .primary-button { flex: 1; min-width: 0; padding-inline: 8px; }
.task-payment .text-button { flex-shrink: 0; }
.task-requirements { list-style: none; padding: 0; margin: 8px 0; font-size: 13px; line-height: 1.55; font-variant-numeric: tabular-nums; }
.task-requirements li { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0 10px; }
.task-content .task-ready { margin: 8px 0; color: var(--ink); font-weight: 600; }
.cost-toggle { display: inline-flex; align-items: center; gap: 4px; }
.cost-toggle svg { width: 14px; height: 14px; }
.cost-toggle[aria-expanded='true'] svg { rotate: 180deg; }
.task-cost { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.cost-requirements-title { margin: 20px 0 4px; font-size: 14px; font-weight: 600; }
.story-links { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 20px; margin-top: 2px; }
.story-foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px 10px; padding-top: 10px; border-top: 1px solid var(--line); font-size: 12px; color: var(--muted); line-height: 1.5; }
/* The Story sheet keeps Miez's card; the story card leaves the cat on the windowsill. */
.story-panel .miez-card { display: none; }
.primary-button,.secondary-button { padding: 11px 15px; border: 0; border-radius: var(--control-radius); min-height: 44px; font-weight: 600; font-size: 14px; }
.primary-button { background: var(--action); color: var(--on-action); }
.secondary-button { background: var(--inset); color: var(--ink); border: 1px solid var(--control-line); }
@media (hover: hover) { .primary-button:hover:not(:disabled),.secondary-button:hover:not(:disabled) { filter: brightness(1.07); } }
.primary-button:disabled,.secondary-button:disabled { background: transparent; color: var(--muted); border: 1px dashed var(--control-line); }
.text-button { padding: 10px 0; min-height: 44px; border: 0; background: transparent; color: var(--accent); font-size: 13px; text-decoration: underline; text-underline-offset: 4px; }
.miez-card { display: flex; align-items: center; width: 100%; gap: 9px; margin: 6px 0 12px; padding: 12px 14px; border: 0; border-radius: var(--control-radius); background: var(--inset); text-align: left; }
.miez-card .mascot { width: 64px; height: 64px; flex-shrink: 0; }
.miez-card strong,.recipe-book strong { font: 600 15px/1.4 Inter,sans-serif; display: block; }
.miez-card small,.recipe-book small { display: block; font-size: 12px; line-height: 1.5; color: var(--muted); margin-top: 4px; }
.small-copy { font-size: 13px; color: var(--muted); line-height: 1.65; margin: 8px 0 13px; }
/* If the kitchen cannot open, the buttons that open its sheets and books are dimmed. */
.options-button:disabled,.recipe-book:disabled,.phone-bar button:disabled { opacity: .5; }
.recipe-book { display: flex; gap: 4px; align-items: center; padding: 0; border: 0; background: none; text-align: left; }
.recipe-book .mascot { width: 52px; height: 52px; flex-shrink: 0; }
.chain { margin: 0; padding: 0; list-style: none; }
.chain li { display: grid; justify-items: center; align-content: start; border-radius: var(--tile-radius); }
.chain .current { background-color: var(--inset); outline: 1px solid var(--line); }
/* In the item dialog the chain names each stage: three to a row, read left to right. */
.chain.named { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 6px; margin-top: 16px; }
.chain.named li { gap: 4px; padding: 8px 4px; }
.chain.named .food { width: 44px; height: 44px; }
.chain.named span { font-size: 12px; line-height: 1.35; color: var(--muted); text-align: center; }
.chain.named .current span { color: var(--ink); font-weight: 600; }
.item-detail>.food { width: 100px; height: 100px; margin: 0 auto 12px; }
#modal-body .item-detail { text-align: center; }
#modal-body .item-detail p { margin: 0 0 4px; color: var(--muted); font-size: 13px; line-height: 1.6; }
#modal-body .item-detail .item-how { color: var(--ink); font-size: 14px; }
#modal-body .item-detail .secondary-button { margin-top: 18px; }
/* A dish shows only its own atlas cell. */
.food { display: block; overflow: hidden; stroke: none; fill: none; }
.portrait { display: block; background-image: url('../assets/variants/portraits-640x640.webp'); background-size: 200% 200%; background-repeat: no-repeat; border-radius: 50%; background-color: var(--inset); }
.visitor-portrait { background-image: url('../assets/variants/visitor-portraits-640x640.webp'); }
.guest-portrait { background-image: url('../assets/variants/guests-640x640.webp'); }
.regulars-1-portrait { background-image: url('../assets/variants/regulars-1-640x640.webp'); }
.regulars-2-portrait { background-image: url('../assets/variants/regulars-2-640x640.webp'); }
.regulars-3-portrait { background-image: url('../assets/variants/regulars-3-640x640.webp'); }
.mascot { display: block; background-image: url('../assets/variants/mascots-640x640.webp'); background-size: 200% 200%; background-repeat: no-repeat; }
.cat-sitting { background-position: 0 0; }.cat-sleeping { background-position: 100% 0; }.bat { background-position: 0 100%; }
.phone-bar { display: none; }
dialog { width: 560px; max-width: calc(100vw - 32px); max-height: calc(100dvh - 40px); padding: 26px; background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: var(--dialog-radius); box-shadow: 0 24px 70px #100b173f; }
dialog::backdrop { background: #17101ac4; }
/* Quest pages keep the same paper and brown ink in either theme. */
dialog:has(.quest-page-content) {
  color-scheme: light;
  --panel: #f3dfb3; --surface: #fffbf3; --inset: #e9dfd0; --ink: #3b2a1e; --muted: #58402e;
  --line: #95754d; --control-line: #806345; --accent: #6e3d50; --gold: #624020;
  --action: #6e3d50; --on-action: #fff6ea; --focus: #27605b; --coin-face: #d39a5c; --coin-rim: #624020;
  background: var(--panel) url('../assets/variants/parchment-page-1254x1254.webp') repeat 0 0 / 512px 512px;
  color: var(--ink);
}
.quest-reading { display: flow-root; }
.quest-sketch { display: block; float: right; width: 42%; max-width: 210px; height: auto; margin: 0 0 12px 16px; }
.quest-page-content .quest-lines { display: block; line-height: 1.75; }
.quest-page-content .quest-line + .quest-line { margin-top: 12px; }
@media (max-width: 540px) {
  .quest-sketch { float: none; width: 170px; margin: 0 auto 14px; }
}
.quest-sketch.quest-scene-sketch { float: none; width: 100%; max-width: 460px; margin: 0 auto 16px; }
@media (forced-colors: active) {
  dialog:has(.quest-page-content) { background: Canvas; color: CanvasText; --ink: CanvasText; --muted: CanvasText; --gold: CanvasText; }
}
.modal-heading { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 19px; }
.modal-copy { font-size: 14px; line-height: 1.7; margin-bottom: 18px; color: var(--muted); }
.settings-actions { display: flex; flex-wrap: wrap; gap: 9px; }
/* The dialog title takes focus when an open dialog changes; it is read, not operated, so it shows no ring. */
#modal-title:focus { outline: none; }
.settings-section { margin-top: 24px; padding-top: 22px; border-top: 1px solid var(--line); }
.settings-section p { font-size: 13px; line-height: 1.7; color: var(--muted); margin: 9px 0 14px; }
.app-version { margin: 24px 0 0; font-size: 12px; color: var(--muted); text-align: center; font-variant-numeric: tabular-nums; }
.choice-fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
.choice-fieldset legend { padding: 0; font-size: 19px; font-weight: 600; line-height: 1.4; letter-spacing: -.025em; }
.choice-group { display: inline-flex; padding: 3px; border: 1px solid var(--control-line); border-radius: var(--control-radius); background: var(--inset); }
.choice { position: relative; display: grid; place-items: center; min-width: 84px; min-height: 44px; padding: 0 14px; border-radius: var(--tile-radius); font-size: 14px; color: var(--muted); cursor: pointer; }
.choice input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.choice:hover { color: var(--ink); }
.choice:has(input:checked) { background: var(--chosen); color: var(--ink); font-weight: 600; box-shadow: inset 0 0 0 2px var(--accent), 0 1px 3px #2a1d2024; }
.choice:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }
.danger-button { padding: 11px 15px; border-radius: var(--control-radius); border: 1px solid var(--accent); background: transparent; color: var(--accent); min-height: 44px; font-size: 14px; font-weight: 600; }
.save-error { border: 1px solid var(--accent); border-radius: var(--control-radius); padding: 12px; font-size: 13px; line-height: 1.6; margin-bottom: 15px; }
.story-controls { display: flex; justify-content: flex-end; margin-top: 24px; }
.story-turn { display: flow-root; }
.story-turn + .story-turn { margin-top: 18px; }
.story-turn .portrait { float: left; width: 44px; height: 44px; margin-right: 12px; }
.turn-words { margin-left: 56px; }
.story-turn :is(h3,h4) { font-size: 13px; font-weight: 600; line-height: 1.4; margin: 0 0 4px; }
.story-turn p { font-size: 16px; line-height: 1.75; }
.conversation-part>h3 { font-size: 16px; margin-bottom: 12px; }
.conversation-part + .conversation-part { margin-top: 24px; padding-top: 18px; border-top: 1px solid var(--line); }
@media (max-width: 720px) {
  .story-turn p { font-size: 14px; }
}
.journal-list { display: flex; flex-direction: column; gap: 8px; }
.journal-entry { display: flex; justify-content: space-between; align-items: center; gap: 12px; text-align: left; border: 1px solid var(--control-line); background: var(--surface); padding: 13px; border-radius: var(--control-radius); min-height: 44px; }
.journal-entry>span { font-size: 12px; color: var(--muted); }
.neighbour-introduction { display: grid; grid-template-columns: 44px minmax(0, 1fr) minmax(0, 1fr); }
.neighbour-introduction>strong,.neighbour-introduction>span { min-width: 0; overflow-wrap: anywhere; }
.neighbour-introduction>span { text-align: right; }
.neighbour-entry { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; width: 100%; }
.neighbour-words { display: grid; gap: 2px; min-width: 0; overflow-wrap: anywhere; }
.neighbour-words>span { font-size: 12px; color: var(--muted); }
.neighbour-entry.not-yet { border-style: dashed; background: transparent; color: var(--muted); }
.portrait-outline { width: 44px; height: 44px; border-radius: 50%; border: 1px dashed var(--control-line); }
.quest-heading { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.quest-heading .portrait,.journal-entry .portrait { flex-shrink: 0; width: 44px; height: 44px; }
.quest-person,.quest-note,.quest-count { color: var(--muted); font-size: 13px; line-height: 1.6; }
.quest-person { margin: 2px 0 0; }
.quest-note { margin: 8px 0 14px; }
.quest-lines { display: grid; gap: 12px; margin-bottom: 14px; }
.quest-line { margin: 0; }
/* In an exchange, each turn starts with its speaker's name on its own line. */
.quest-speaker { display: block; font-size: 13px; font-weight: 600; line-height: 1.4; }
.quest-requirements { list-style: none; margin: 0; padding: 0; }
.quest-requirements li { display: flex; align-items: center; gap: 8px; }
.quest-item { display: flex; flex: 1; align-items: center; gap: 10px; min-width: 0; min-height: 52px; padding: 6px 0; text-align: left; border: 0; background: transparent; }
.quest-item .food { width: 40px; height: 40px; flex-shrink: 0; }
.quest-item>span:not(.quest-count) { flex: 1; min-width: 0; font-size: 14px; }
.quest-find { flex: none; min-width: 44px; min-height: 44px; padding-inline: 2px; }
.quest-count { text-align: right; font-variant-numeric: tabular-nums; }
.quest-reward { margin: 12px 0 8px; color: var(--gold); font-weight: 600; font-size: 14px; }
.quest-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.quest-actions>button { flex: 1 1 auto; }
.quest-journal { padding: 14px 0; border-top: 1px solid var(--line); }
.quest-journal .journal-entry { width: 100%; }
.chapter-journal { display: flex; flex-direction: column; gap: 8px; padding: 14px 0; border-top: 1px solid var(--line); }
.chapter-journal>p:not(.small-copy) { font-size: 14px; line-height: 1.65; }
.chapter-journal .small-copy { margin: 0; }
.journal-steps { margin: 0; padding-left: 20px; font-size: 13px; line-height: 1.7; color: var(--muted); }
.journal-unread { display: flex; flex-direction: column; gap: 8px; }
.journal-unread .small-copy { margin: 0; }
.journal-unread .journal-entry>span { flex-shrink: 0; }
.journal-group { border-top: 1px solid var(--line); }
.journal-group>summary { padding: 14px 0; min-height: 44px; cursor: pointer; font-size: 16px; font-weight: 600; }
.journal-group[open]>summary { margin-bottom: 8px; }
.journal-group .neighbour-entry,.journal-group .neighbour-introduction { margin-bottom: 8px; }
.journal-group .neighbour-introduction { width: 100%; }
.journal-group .quest-journal:first-of-type,.journal-group .chapter-journal:first-of-type { border-top: 0; }
.recipe-chain { border-top: 1px solid var(--line); padding: 16px 0; }
.recipe-chain h3 { margin-bottom: 12px; }
/* A complete chain: a check and the word, so the mark does not depend on color. */
.chain-complete { display: inline-flex; align-items: center; gap: 4px; margin-left: 10px; vertical-align: 2px; font-size: 12px; line-height: 1.5; font-weight: 600; letter-spacing: 0; color: var(--ready); }
.chain-complete svg { width: 14px; height: 14px; stroke-width: 2; }
.recipe-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: 10px; }
.recipe-item { padding: 8px; background: var(--surface); border: 1px solid var(--control-line); border-radius: var(--control-radius); min-width: 0; }
.recipe-item .food { width: 68px; height: 68px; margin: auto; }
.recipe-item span:last-child { display: block; font-size: 12px; text-align: center; line-height: 1.4; margin-top: 7px; }
/* A dish nobody has made yet waits under a dashed cover, using the dashed "not yet" style. */
.recipe-item.not-yet { background: transparent; border-style: dashed; border-color: var(--control-line); color: var(--muted); }
.covered-dish { display: block; color: var(--muted); }
.covered-dish-dome { stroke-dasharray: 3 3.4; }
.recipe-item .covered-dish { width: 68px; height: 68px; margin: auto; }
.chain.named .covered-dish { width: 44px; height: 44px; }
/* New dishes since the recipe book was last opened: the recipe book card says how many; the bar's Recipes button carries a candle dot. */
#recipes-button,#story-button { position: relative; }
#story-button[data-ready]::after { content: ''; position: absolute; top: 6px; left: calc(50% + 7px); width: 8px; height: 8px; border-radius: 50%; background: var(--coin-face); box-shadow: 0 0 0 2px var(--panel); }
#recipes-button[data-fresh]::after { content: ''; position: absolute; top: 6px; left: calc(50% + 7px); width: 8px; height: 8px; border-radius: 50%; background: var(--coin-face); box-shadow: 0 0 0 2px var(--panel), 0 0 8px 2px #e8b58e99; }
.drag-ghost { position: fixed; width: 74px; height: 74px; pointer-events: none; z-index: 100; filter: drop-shadow(0 7px 5px #17101a65); }
.hidden { display: none!important; }

/* Wider screens: the room fills the left half at full height and nothing covers it. The drawer is one parchment panel docked on the right:
   the masthead, the paper tickets, then the board with Mara's line beside the story and the recipe book as sections of the same surface.
   The cell follows the panel's width and the screen's full height, so the panel fills the first screen from 1280 to 1920 wide. */
@media (min-width: 1024px) {
  :root { --panel-w: max(50vw, 620px); }
  :root,body { background: var(--panel); }
  body { padding-left: calc(100vw - var(--panel-w)); }
  /* The panel's edge toward the room is shaded on the panel itself, warm and offset downward, so no shadow falls on the painting. */
  body::before { content: ''; position: fixed; z-index: 1; inset: 0 auto 0 calc(100vw - var(--panel-w)); width: 24px; pointer-events: none; box-shadow: inset 10px 6px 14px -10px #42282440; }
  .masthead { padding: 18px 24px 12px; }
  .wordmark { font-size: clamp(43px, 3.2vw, 48px); }
  .game-layout {
    --view-h: 100dvh; --frame-w: max(100cqw, 75cqh); --gap: 4px; --runner-h: 14px;
    --side-w: clamp(240px, calc(var(--panel-w) * .36), 300px);
    --cell: clamp(44px, min(calc((var(--panel-w) - var(--side-w) - 116px) / 6), calc((100dvh - 432px) / 7)), 96px);
    padding: 0 24px 16px;
  }
  .room { position: fixed; z-index: 0; inset: 0 auto 0 0; width: calc(100vw - var(--panel-w)); }
  .drawer { display: flex; flex-direction: column; gap: 14px; background: none; }
  .ticket-row { gap: 12px; }
  .ticket { display: flex; flex-direction: column; gap: 6px; padding: 8px; border-radius: var(--card-radius); }
  .ticket-face { display: grid; grid-template-columns: 36px minmax(0,1fr); grid-template-areas: 'face words' 'dishes dishes'; align-items: center; gap: 4px 8px; }
  .ticket-face .portrait { grid-area: face; }.ticket-words { grid-area: words; }.ticket-items { grid-area: dishes; justify-content: flex-start; }
  .ticket .ticket-item { width: 40px; height: 36px; }.ticket .ticket-item .food { width: 32px; height: 32px; }
  .ticket .ticket-items.many .ticket-item { width: 34px; }.ticket .ticket-items.many .food { width: 30px; height: 30px; }
  .drawer-body { display: grid; grid-template-columns: auto minmax(0,1fr); align-items: start; gap: 20px; }
  .kitchen { width: calc(var(--cell) * 6 + var(--gap) * 5 + 28px); display: flex; flex-direction: column; gap: 12px; }
  .table { border-radius: var(--radius); box-shadow: 0 2px 4px #2a1a1029, var(--shadow); }
  .board { padding: 14px; }
  .line-slot>* { min-height: 62px; padding: 6px 2px; }
  /* The story and the recipe book are sections of the panel, between hairlines, not cards. */
  .side { align-self: stretch; display: flex; flex-direction: column; min-width: 0; padding-left: 20px; border-left: 1px solid var(--line); }
  .drawer .side>*+* { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
  .side>.recipe-book { padding-top: 10px; }
  .recipe-book strong { color: var(--accent); text-decoration: underline; text-underline-offset: 4px; }
}
@media (min-width: 1024px) and (max-width: 1599px) { .tagline { display: none; } }
@media (min-width: 1024px) and (max-width: 1365px) {
  .options-button { padding: 0 12px; }.header-controls { gap: 12px; }.coin-count { padding-right: 12px; }
  .detail-description { display: none; }
  /* Narrower panels use tighter sections. */
  .drawer .side>*+* { margin-top: 10px; padding-top: 10px; }.side>.recipe-book { padding-top: 6px; }
  .task-content p { margin-bottom: 8px; }
  .task-content { margin-top: 8px; padding-top: 8px; }.game-layout { padding-bottom: 4px; }
  /* The longest chapter title keeps to one line. */
  .chapter-title { font-size: 16px; }
}

/* Phones and tablets: the room fills the screen behind a parchment drawer that sits half open. Its handle row carries the tickets
   just under the visible room; then the board on timber, then Mara's line, then the bar. --cell and the room share one height budget. */
@media (max-width: 1023px) {
  :root { --head-h: 48px; --bar-h: 56px; --safe: env(safe-area-inset-bottom, 0px); }
  .masthead { position: relative; z-index: 12; height: var(--head-h); align-items: center; padding: 0 14px; gap: 12px; background: var(--page); }
  .wordmark { font-size: clamp(28px, 9.4vw, 38px); gap: 5px; }
  .tagline,.masthead .options-button,.recipe-book { display: none; }
  .coin-count { gap: 5px; padding-right: 0; border-right: 0; }.coin { width: 20px; height: 20px; }#coins { font-size: 21px; }.coin-label { font-size: 12px; }
  .game-layout {
    --gap: 3px; --runner-h: 8px; --drawer-chrome: 152px; --frame-w: 100cqw;
    --cell: clamp(44px, min(calc((100vw - 40px) / 6), calc((100dvh - var(--head-h) - var(--bar-h) - var(--safe) - var(--drawer-chrome) - 18px - 29.5dvh) / 7)), 60px);
    --drawer-h: calc(var(--cell) * 7 + 18px + var(--drawer-chrome));
    --view-base: calc(100dvh - var(--head-h) - var(--bar-h) - var(--safe) - var(--drawer-h));
    /* Lowered, the drawer shows the whole painting and keeps its tickets in view. */
    --drop-full: max(0px, calc(min(100vw * 4 / 3, 100dvh - var(--head-h) - var(--bar-h) - var(--safe) - 68px) - var(--view-base)));
    --view-h: calc(var(--view-base) + var(--drawer-drop));
    transition: --drawer-drop .6s cubic-bezier(.65,0,.35,1);
  }
  .game-layout:is(.lowered,.revealing) { --drawer-drop: var(--drop-full); }
  .room { position: fixed; z-index: 0; inset: var(--head-h) 0 0; }
  .drawer { position: fixed; z-index: 10; inset: auto 0 calc(var(--bar-h) + var(--safe)); height: var(--drawer-h); translate: 0 var(--drawer-drop); display: flex; flex-direction: column; border-radius: var(--dialog-radius) var(--dialog-radius) 0 0; box-shadow: 0 -8px 12px -6px #1a0f0a73; }
  .drawer>:not(.drawer-handle),.drawer-body>* { width: min(100%, 560px); margin-inline: auto; }
  /* The handle's target reaches up over the room's edge, so it stays 44px tall without pushing the tickets down. */
  .drawer-handle { position: absolute; z-index: 1; top: -24px; left: 50%; display: block; width: 96px; height: 44px; translate: -50% 0; padding: 0; border: 0; border-radius: var(--control-radius); background: none; }
  .drawer-handle span { position: absolute; left: 50%; bottom: 10px; width: 40px; height: 4px; translate: -50% 0; border-radius: 2px; background: var(--control-line); }
  .drawer-handle:focus-visible { outline-offset: -3px; }
  .tickets { flex: none; padding: 14px 8px 4px; }
  .ticket-row { gap: 6px; }
  .ticket { display: flex; align-items: center; gap: 2px; height: 50px; padding: 2px 3px; }
  /* The neighbour's portrait sits on the ticket's corner, inside the face target; the face and Deliver name the quest to screen readers. */
  .ticket-face { display: flex; align-items: center; flex: 0 1 auto; min-width: 44px; }
  .ticket-words { display: none; }
  .ticket .portrait { position: absolute; left: -4px; top: -9px; z-index: 1; width: 22px; height: 22px; box-shadow: 0 0 0 2px var(--surface); }
  .ticket-items { flex: none; gap: 0; }
  /* A phone ticket is too small for counts; the quest dialog gives them. */
  .ticket-count { display: none; }
  .ticket-items:has(>:only-child) .ticket-item { width: 44px; }
  /* Two dishes on one target are pictures, so they draw smaller and leave Deliver its 44px. */
  .ticket-items .ticket-item { width: 26px; }.ticket-items .food { width: 26px; height: 26px; }
  /* Three or four dishes overlap like a fanned stack, so Deliver keeps its 44px. */
  .ticket-items.many { flex: 0 1 auto; min-width: 0; }
  .ticket-items.many .ticket-item { flex: 0 1 26px; min-width: 6px; justify-items: start; }.ticket-items.many .ticket-item:last-child { flex-shrink: 0; }
  .ticket-items.many .food { width: 26px; height: 26px; }
  .ticket-item.ready::after { right: -1px; bottom: 6px; width: 8px; height: 8px; }
  .deliver-button { flex: 1; min-width: 44px; padding: 0 3px; gap: 3px; font-size: 12px; }
  .deliver-dot,.deliver-button .coin { display: none; }
  .deliver-button:disabled .deliver-word,.deliver-button:enabled .deliver-reward { display: none; }
  /* Serve has no reward, so it keeps its word in the not-yet style. The count of the other plates keeps its own width. */
  .deliver-button:disabled .deliver-word:only-child { display: inline; }
  .ticket-items.many .ticket-more { flex: none; width: auto; min-width: 24px; padding-left: 4px; justify-items: center; }
  /* A ready Deliver keeps its whole word; the fanned dishes give way. */
  .deliver-button:enabled { flex: 1 0 auto; }
  .deliver-button:disabled .coin { display: block; width: 14px; height: 14px; }
  /* Four tickets do not fit two 44px targets each, so the recovery ticket shows its face alone. Its dialog delivers. */
  .ticket-row:has(.recovery-ticket) { grid-template-columns: repeat(3, minmax(0, 1fr)) auto; }
  .recovery-ticket .deliver-button { display: none; }
  .recovery-ticket .ticket-face:has(~ .guide-target) { outline: 2px dotted color-mix(in srgb, var(--muted) 50%, transparent); outline-offset: -4px; }
  .recovery-ticket .ticket-face:has(~ .guide-target):focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
  /* The line is as tall as a ticket, so the board stays still when a ticket replaces it. */
  .tickets-empty { display: grid; place-items: center; min-height: 50px; padding: 0 12px; }
  /* The source mark holds the lower corner of a small tile, so the cost of a take sits in the upper corner. */
  .take-cost { top: 2px; bottom: auto; left: 2px; }
  .drawer-body { flex: 1; display: flex; flex-direction: column; min-height: 0; }
  .kitchen { flex: 1; display: flex; flex-direction: column; min-height: 0; }
  .table { flex: none; margin-top: 4px; border-radius: var(--card-radius); background-image: url('../assets/variants/timber-tabletop-1024x1024.webp'); background-image: image-set(url('../assets/variants/timber-tabletop-1024x1024.avif') type('image/avif'), url('../assets/variants/timber-tabletop-1024x1024.webp') type('image/webp')); }
  .board { padding: 6px 0; }.cell { padding: 3px; }
  .line-slot { flex: 1; display: flex; align-items: center; min-height: 0; padding: 0 10px; }
  .mara-line,.offer { gap: 8px; }.mara-line .portrait,.offer .portrait { width: 28px; height: 28px; }.offer strong { font-size: 13px; }.mara-line p { font-size: 13px; line-height: 1.35; }
  .detail-head { flex: 1 1 0; gap: 8px; }.detail-head .food { width: 40px; height: 40px; }
  .detail-words h3 { line-height: 1.2; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
  .detail-next { line-height: 1.3; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
  /* The strip holds three lines: a name on two lines leaves no room for what it makes, so that line steps aside rather than show a fragment. */
  .long-name .detail-next,.detail-description { display: none; }
  #item-detail { flex-wrap: nowrap; }
  .item-actions { flex-shrink: 0; gap: 6px; }.item-actions button { padding: 9px 11px; }
  .side { display: none; }
  .phone-bar { display: flex; position: fixed; z-index: 16; inset: auto 0 0; gap: 4px; height: calc(var(--bar-h) + var(--safe)); padding: 4px max(8px, env(safe-area-inset-right)) env(safe-area-inset-bottom) max(8px, env(safe-area-inset-left)); background: var(--panel); border-top: 1px solid var(--line); }
  .phone-bar button { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 2px; border: 0; border-radius: var(--control-radius); background: transparent; color: var(--ink); font-size: 13px; line-height: 1.2; white-space: nowrap; }
  .phone-bar svg { width: 24px; height: 24px; }
  .phone-bar button:focus-visible { outline-offset: -3px; }
}
@media (max-width: 720px) {
  /* Sheets rise from the bottom edge, within thumb reach. */
  dialog { width: 100%; max-width: 100%; margin: auto 0 0; max-height: 88dvh; padding: 20px 20px calc(20px + env(safe-area-inset-bottom)); border-width: 1px 0 0; border-radius: var(--dialog-radius) var(--dialog-radius) 0 0; }
  .story-controls .primary-button { padding: 10px 14px; }.recipe-item .food { width: 58px; height: 58px; }
  .item-detail>.food { width: 120px; height: 120px; }
}
/* Narrow phones drop the word once the figure grows; the coin mark carries the unit and screen readers hear the exact total. */
@media (max-width: 410px) { .masthead { padding-inline: 12px; gap: 8px; }.coin-count.long .coin-label { display: none; } }
@media (max-width: 410px) { .tickets:has(.recovery-ticket) { padding-inline: 4px; }.ticket-row:has(.recovery-ticket) { gap: 4px; } }
/* Narrow phones give the strip's words the room: a smaller dish, and below 361px no dish at all. */
@media (max-width: 410px) { .detail-head .food { width: 34px; height: 34px; } }
@media (max-width: 360px) { .detail-head .food,.detail-next { display: none; }.item-actions button { padding-inline: 9px; } }
.guided .detail-next { display: block; }
.source-detail .detail-description { display: block; }
/* The narrowest tickets give Deliver every spare pixel, so each target on a ticket stays 44px wide. */
@media (max-width: 360px) { .ticket { padding-inline: 2px; }.deliver-button { padding-inline: 1px; }.ticket-items .ticket-item,.ticket-items .food { width: 22px; }.ticket-items .food { height: 22px; } }
/* Landscape phones and 200% zoom leave too little height for a fixed drawer over the room, so the room, the drawer and the bar return to the page flow. */
@media (max-width: 1023px) and (max-height: 600px) {
  .game-layout { --view-h: 240px; --drawer-drop: 0px; transition: none; }
  .room { position: relative; inset: auto; height: 240px; }
  .drawer { position: static; height: auto; translate: none; box-shadow: none; }
  .drawer-handle { display: none; }
  .line-slot { min-height: 56px; }
  .phone-bar { position: static; }
}
/* A quest's completion notice: it reports itself and clears on its own, so delivering a quest never stops play for a tap. */
.toast-stack { position: fixed; z-index: 100; display: flex; flex-direction: column; gap: 8px; pointer-events: none; }
.toast { pointer-events: none; max-width: 340px; padding: 10px 14px; background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: var(--card-radius); box-shadow: var(--shadow); font-size: 14px; line-height: 1.4; text-wrap: pretty; }
.toast-text { margin: 0; }
/* A notice that offers a reply takes the pointer, so it can wait while the player reaches for Read. */
.toast:has(.toast-reply) { pointer-events: auto; }
.toast-reply { display: block; margin: -2px 0 -10px; }
.toast.entering { animation: toast-in .3s cubic-bezier(.16,1,.3,1); }
.toast.leaving { animation: toast-out .3s ease forwards; }
@keyframes toast-in { from { opacity: 0; scale: .92; } }
@keyframes toast-out { to { opacity: 0; } }
@media (min-width: 1024px) { .toast-stack { right: 20px; bottom: 20px; align-items: flex-end; } }
@media (max-width: 1023px) {
  .toast-stack { top: calc(var(--head-h) + 10px); left: 50%; translate: -50% 0; align-items: center; width: min(92vw, 360px); }
  .toast { max-width: none; width: 100%; text-align: center; }
  .toast-reply { margin-inline: auto; }
}
/* Forced colours drop the tile fills and the inset rings: spaces, buttons and the selection keep system-colour edges. */
@media (forced-colors: active) {
  .cell,.primary-button,.secondary-button,.ticket-item,.ticket,.area-choice,.room-pin { border: 1px solid ButtonBorder; }
  .cell.obstacle { border: 2px dashed ButtonText; }
  .cell.selected,.cell:hover { outline: 3px solid Highlight; outline-offset: -3px; }
  .cell:is(.blocker-target,.merge-target,.guide-target),.deliver-button.guide-target { outline: 3px dotted Highlight; outline-offset: -3px; }
  .cell:is(.blocker-target,.merge-target,.guide-target):focus-visible,.deliver-button.guide-target:focus-visible { outline: 3px solid Highlight; }
  .ticket-item.ready::after,#recipes-button[data-fresh]::after,#story-button[data-ready]::after,.pin-dot { forced-color-adjust: none; background: Highlight; }
  .choice:has(input:checked),.area-choice[aria-pressed='true'] { outline: 2px solid Highlight; outline-offset: -2px; }
}
/* The Motion choice in Options: Reduced always stills the page; System stills it when the device asks; Full never does. */
:root[data-motion='reduced'] *,:root[data-motion='reduced'] *::before,:root[data-motion='reduced'] *::after { animation: none!important; transition: none!important; scroll-behavior: auto!important; }
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion='full']) *,:root:not([data-motion='full']) *::before,:root:not([data-motion='full']) *::after { animation: none!important; transition: none!important; scroll-behavior: auto!important; }
}
