/* 8-bit style game CSS */
/* Press Start 2P is loaded via <link> in index.html. */

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    /* A phone must not treat the game as a web page: no rubber-band, no
       pull-to-refresh, no double-tap zoom, no grey flash on tap, no "Copy |
       Look Up" callout when a finger rests on the field. */
    overscroll-behavior: none;
    -webkit-text-size-adjust: 100%;
    touch-action: manipulation;
}

body {
    font-family: 'Press Start 2P', cursive;
    background-color: #000;
    color: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
    /* dvh, with vh underneath for browsers without it: on iOS `100vh` is the
       height with the URL bar HIDDEN, so with it showing the bottom of the
       page — the tray — was off the screen. */
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    overscroll-behavior: none;
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
    /* Out from under the notch and the home indicator (viewport-fit=cover). */
    padding: env(safe-area-inset-top) max(10px, env(safe-area-inset-right))
             env(safe-area-inset-bottom) max(10px, env(safe-area-inset-left));
}

/* Hidden until assets finish loading; src/app.js reveals it. */
.game-container {
    display: none;
    flex-direction: column;
    align-items: center;
    /* AS WIDE AS THE HEIGHT ALLOWS. The field is 2000:850 and everything under
       it (--hud, measured by src/ui/device.js) has to fit too, so the width is
       whichever is smaller: the screen's, or the width whose field leaves room
       for the HUD. It used to be 100% wide with a max-height on the frame,
       which letterboxed the bitmap INSIDE its element — and clientToWorld maps
       against the element, so on a short screen every drop landed up to 240
       world px from where it was aimed. Sized this way the bitmap always fills
       its element and the mapping is exact at any size. */
    --hud: 200px;
    /* The ink bar and the drawing overlay are absolutely positioned children.
       With nothing positioned above them they anchored to the VIEWPORT, which
       only looked right while the game was pinned to the top of it. */
    position: relative;
    /* --field-w is the bitmap's width in world px: 2000 as authored, more on a
       screen wider than that shape (ui/device.js, chooseFieldWidth). */
    --field-w: 2000;
    width: min(100%, calc((100vh - var(--hud)) * var(--field-w) / 850));
    width: min(100%, calc((100dvh - var(--hud) - env(safe-area-inset-top) - env(safe-area-inset-bottom)) * var(--field-w) / 850));
    max-width: 100%;
}

.game-container.is-ready {
    display: flex;
}

/* --- Loading screen, and the briefing that follows it --- */

/* The key art, full bleed. It was an <img> at 80% on a grey page, and 837KB at
   4032px — on a phone, a blank screen while the LOADING image loaded. This copy
   is 1600px and a third of the weight. The title sits in the top third, so the
   crop is biased upward to keep it. */
#loadingScreen {
    position: fixed;
    inset: 0;
    /* Above the clock, which is fixed to the body at 9999 and showed through. */
    z-index: 10000;
    /* Pinned to the TOP: the title is the top 43% of the painting, and the
       briefing is sized (below) to start underneath it, so any cropping has to
       come off the bottom. */
    background: #16301a url('assets/images/Loader/loading-1600.jpg') center top / cover no-repeat;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: center;
    transition: opacity 0.5s ease-out;
}

/* Something for white text to sit on, without a box over the painting. */
#loadingScreen::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom, rgba(10, 20, 12, 0) 45%, rgba(10, 20, 12, 0.82) 100%);
    pointer-events: none;
}

#loadingScreen.is-hidden {
    opacity: 0;
    /* Stop the fading loader intercepting clicks before display:none lands. */
    pointer-events: none;
}

/* Portrait: a 3:2 painting under `cover` would show a third of its width and
   slice the title in half. Pin it to the top at full width instead and let the
   dark green carry the rest. */
@media (orientation: portrait) {
    #loadingScreen {
        background-size: 100% auto;
        background-position: top center;
    }
    #loadingScreen::before {
        background: linear-gradient(to bottom, rgba(22, 48, 26, 0) 30%, #16301a 46%);
    }
}

.loader-panel {
    position: relative;
    width: min(640px, 86vw);
    margin-bottom: clamp(28px, 8vh, 84px);
    text-align: center;
    transition: opacity 0.35s;
}

.loader-panel.is-done {
    opacity: 0;
}

#loadingStage {
    font-size: clamp(9px, 1.3vw, 14px);
    line-height: 1.7;
    color: #fffdf4;
    text-shadow: 2px 2px 0 #000;
    /* Room for the rabbit running along the top of the bar. */
    margin-bottom: 46px;
    min-height: 1.7em;
}

#loadingProgressContainer {
    position: relative;
    height: 24px;
    background-color: rgba(20, 12, 24, 0.88);
    border: 3px solid #fffdf4;
    box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.5);
}

#loadingProgressBar {
    height: 100%;
    width: 0%;
    background: repeating-linear-gradient(90deg, #8BC34A 0 12px, #7cb342 12px 24px);
}

/* The rabbit at the front of the bar. A CSS sprite off the game's own sheet
   (26KB, so it is there long before anything else): row 4 is the side-on hop,
   six 32px frames, shown at 1.5x. Its feet are at 0.81 of the cell, so it is
   dropped by the other 0.19 to stand ON the bar rather than hover over it. */
#loadingRunner {
    position: absolute;
    bottom: 100%;
    left: var(--progress, 0%);
    width: 48px;
    height: 48px;
    transform: translate(-50%, 9px);
    background: url('assets/images/Bunny/bunny.png') 0 -192px / 528px auto no-repeat;
    image-rendering: pixelated;
    animation: loader-hop 0.5s steps(6) infinite;
}

@keyframes loader-hop {
    to { background-position-x: -288px; }
}

#loadingText {
    margin-top: 14px;
    font-size: clamp(10px, 1.2vw, 14px);
    color: #fffdf4;
    text-shadow: 2px 2px 0 #000;
}

/* --- The briefing --- */

.briefing {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Bottom-aligned by an auto margin on the first child, NOT by
       justify-content: flex-end — with flex-end, content taller than the
       screen overflows off the TOP, where no amount of scrolling reaches it. */
    justify-content: flex-start;
    gap: clamp(8px, 1.4vh, 14px);
    padding: clamp(8px, 2vh, 22px) clamp(10px, 3vw, 40px);
    opacity: 0;
    transition: opacity 0.4s;
    overflow-y: auto;
}

.briefing.is-up {
    opacity: 1;
}

.briefing > :first-child {
    margin-top: auto;
}

.briefing-farmer {
    display: flex;
    align-items: flex-end;
    gap: 14px;
    width: min(900px, 100%);
}

.briefing-farmer canvas {
    height: clamp(90px, 15vh, 140px);
    width: auto;
    image-rendering: pixelated;
    flex: none;
}

.briefing-bubble {
    position: relative;
    margin-bottom: clamp(26px, 6vh, 56px);
    padding: 12px 14px;
    font-size: clamp(9px, 1.15vw, 14px);
    line-height: 1.8;
    color: #23170f;
    background: #fffdf4;
    border: 3px solid #23170f;
    box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.4);
}

.briefing-bubble::before {
    content: '';
    position: absolute;
    left: -10px;
    bottom: 14px;
    width: 12px;
    height: 12px;
    background: #fffdf4;
    border-left: 3px solid #23170f;
    border-bottom: 3px solid #23170f;
    transform: rotate(45deg);
}

.briefing-steps {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(8px, 1.4vw, 18px);
    width: min(900px, 100%);
}

.briefing-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: clamp(8px, 1.1vw, 14px);
    text-align: center;
    background: rgba(27, 16, 32, 0.9);
    border: 3px solid #fffdf4;
    box-shadow: 5px 5px 0 rgba(0, 0, 0, 0.45);
}

.briefing-art {
    position: relative;
    width: 100%;
    height: clamp(56px, 9vh, 84px);
    overflow: hidden;
}

.briefing-step h3 {
    font-size: clamp(10px, 1.25vw, 15px);
    font-weight: normal;
    color: #ffd166;
}

.briefing-step p {
    font-size: clamp(7px, 0.85vw, 11px);
    line-height: 1.8;
    color: #e9e2ee;
}

.briefing-play {
    font-family: 'Press Start 2P', cursive;
    font-size: clamp(14px, 1.8vw, 22px);
    padding: 13px 44px;
    color: #1b1020;
    background: #ffd166;
    border: 4px solid #fffdf4;
    box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.5);
    cursor: pointer;
    flex: none;
}

.briefing-play:hover,
.briefing-play:focus-visible {
    background: #ffe39a;
    outline: none;
}

.briefing-play:active {
    transform: translate(3px, 3px);
    box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.5);
}

/* "Add to Home Screen" is the only full screen an iPhone gives a web page, so
   on an iPhone in Safari the briefing says how. Shown by ui/titleScreen.js only
   there; hidden everywhere else, and never on a phone already running from the
   home screen. */
.briefing-install {
    display: none;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    font-size: clamp(7px, 0.9vw, 10px);
    line-height: 1.6;
    color: #1b1020;
    background: #ffd166;
    border: 2px solid #fffdf4;
    flex: none;
}

.briefing-install.is-shown { display: flex; }

.briefing-install svg { width: 14px; height: 14px; flex: none; }

.briefing-foot {
    font-size: clamp(7px, 0.8vw, 10px);
    line-height: 1.8;
    color: #fffdf4;
    text-shadow: 2px 2px 0 #000;
    text-align: center;
}

.briefing-actions {
    display: flex;
    align-items: stretch;
    justify-content: center;
    gap: 12px;
    flex: none;
}

.briefing-scores {
    font-family: 'Press Start 2P', cursive;
    font-size: clamp(9px, 1.05vw, 13px);
    padding: 0 18px;
    color: #fffdf4;
    background: rgba(27, 16, 32, 0.9);
    border: 4px solid #fffdf4;
    box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.5);
    cursor: pointer;
}

.briefing-scores:hover,
.briefing-scores:focus-visible {
    background: rgba(60, 40, 70, 0.95);
    outline: none;
}

/* --- The title screen's third button, and the page it opens --- */

/* Never played: HOW TO PLAY is the one to press, and says so by breathing. */
.briefing-how.is-new {
    color: #1b1020;
    background: #8bd450;
    animation: how-nudge 1.5s ease-in-out infinite;
}
@keyframes how-nudge { 50% { transform: translateY(-3px); box-shadow: 6px 9px 0 rgba(0, 0, 0, 0.5); } }
@media (prefers-reduced-motion: reduce) { .briefing-how.is-new { animation: none; } }

/* PLAY on a row of its own, the other two under it, one block: PLAY is as wide
   as the pair. A grid rather than a wrapped flex row, so the three can never
   settle into two-and-one the wrong way round on a narrow screen. */
.briefing-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(8px, 1.4vh, 12px) 12px;
}
.briefing-actions .briefing-play { grid-column: 1 / -1; }
/* No leaderboard configured: HOW TO PLAY is alone down there, and fills the row. */
.briefing-actions > :nth-child(2):last-child { grid-column: 1 / -1; }
.briefing-scores { padding-top: 12px; padding-bottom: 12px; white-space: nowrap; }

.how-to-play {
    position: fixed;
    inset: 0;
    z-index: 10002;                 /* with the scoreboard: over the briefing and the game */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(8px, 1.6vh, 16px);
    padding: calc(clamp(10px, 2vh, 22px) + env(safe-area-inset-top))
             calc(clamp(12px, 3vw, 40px) + env(safe-area-inset-right))
             calc(clamp(10px, 2vh, 22px) + env(safe-area-inset-bottom))
             calc(clamp(12px, 3vw, 40px) + env(safe-area-inset-left));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    font-family: 'Press Start 2P', cursive;
    color: #fffdf4;
    background: rgba(18, 28, 20, 0.97);
    opacity: 0;
    transition: opacity 0.25s;
}
.how-to-play.is-up { opacity: 1; }
.how-to-play > * { width: min(980px, 100%); flex: none; }

.how-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.how-title { font-size: clamp(13px, 1.8vw, 22px); font-weight: normal; color: #ffd166; text-shadow: 3px 3px 0 #000; }
.how-back, .how-clear {
    font-family: inherit;
    font-size: clamp(9px, 1.05vw, 13px);
    padding: 10px 16px;
    color: #fffdf4;
    background: rgba(27, 16, 32, 0.9);
    border: 3px solid #fffdf4;
    box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.5);
    cursor: pointer;
}
.how-back:hover, .how-clear:hover, .how-back:focus-visible, .how-clear:focus-visible { background: rgba(60, 40, 70, 0.95); outline: none; }

.how-try {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    gap: clamp(10px, 1.6vw, 20px);
    align-items: stretch;
}
.how-pad { position: relative; display: flex; }
.how-pad-canvas {
    width: 100%;
    aspect-ratio: 560 / 340;
    background: #1d2b22
        repeating-linear-gradient(0deg, transparent 0 33px, rgba(255, 253, 244, 0.05) 33px 34px);
    border: 3px solid #fffdf4;
    box-shadow: 5px 5px 0 rgba(0, 0, 0, 0.45);
    cursor: crosshair;
    touch-action: none;             /* a finger draws here; it does not scroll the page */
}
.how-pad-label {
    position: absolute; left: 12px; top: 10px;
    font-size: clamp(9px, 1vw, 12px); color: #ffd166; pointer-events: none;
    transition: opacity 0.2s;
}
.how-pad-canvas.has-ink ~ .how-clear { opacity: 1; }
.how-pad:has(.has-ink) .how-pad-label { opacity: 0.25; }
.how-clear { position: absolute; right: 10px; bottom: 12px; padding: 8px 12px; opacity: 0.55; }

.how-side { display: flex; flex-direction: column; gap: clamp(8px, 1.2vw, 14px); min-width: 0; }
.pad-guess {
    display: flex; flex-direction: column; gap: 8px;
    padding: clamp(8px, 1.1vw, 14px);
    min-height: clamp(84px, 13vh, 120px);
    background: rgba(27, 16, 32, 0.9);
    border: 3px solid #fffdf4;
    box-shadow: 5px 5px 0 rgba(0, 0, 0, 0.45);
}
.pad-guess-head { display: flex; align-items: center; gap: 12px; }
.pad-guess-art { width: clamp(40px, 5vw, 64px); height: clamp(40px, 5vw, 64px); object-fit: contain; image-rendering: pixelated; flex: none; }
.pad-guess-name { font-size: clamp(10px, 1.3vw, 16px); line-height: 1.5; color: #ffd166; }
.pad-guess-job { margin-top: 5px; font-size: clamp(7px, 0.85vw, 10px); color: #b9aec2; }
.pad-guess-note { font-size: clamp(7px, 0.9vw, 11px); line-height: 1.7; color: #e9e2ee; }
.pad-guess-note.is-warning { color: #ff7961; }
.pad-guess-also { font-size: clamp(6px, 0.75vw, 9px); line-height: 1.6; color: #8f8599; }

/* The farmer, heckling. Same man and same bubble as everywhere else. */
.how-farmer { width: 100%; margin-top: auto; }
.how-farmer canvas { height: clamp(70px, 12vh, 118px); }
.how-farmer .briefing-bubble { margin-bottom: clamp(16px, 4vh, 40px); flex: 1 1 auto; min-height: 3.6em; }

/* A phone on its side: the cards are the first thing to go small, the pad the last. */
@media (max-height: 560px) {
    /* THE PAD FIRST. On a phone the page is two screens tall, and the thing worth
       opening it for should not be the one under the fold. */
    .how-head { order: 0; }
    .how-try { order: 1; }
    .how-to-play .briefing-steps { order: 2; }
    .how-to-play .briefing-art { height: 44px; }
    .how-to-play .briefing-step { gap: 4px; padding: 6px; }
    .how-try { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); }
}

/* Nothing in the game is a native drag: a chip's <img> is draggable by default,
   and a precise pointer (an Apple Pencil, an iPad's trackpad) starts that drag at
   once, cancelling the pointer sequence our own drag is built on. See guardPen. */
.game-container img, .drag-ghost img, .how-to-play img { -webkit-user-drag: none; user-drag: none; }

/* --- The farmer's job for the day, under the ink bar it pays out in (mechanics/jobs.js) --- */
.job-line {
    position: absolute;
    left: 50%;
    top: 100%;
    transform: translateX(-50%);
    margin-top: 5px;
    padding: 3px 8px;
    font-family: 'Press Start 2P', cursive;
    font-size: clamp(7px, 0.8vw, 10px);
    line-height: 1.4;
    white-space: nowrap;
    color: #ffd166;
    background: rgba(0, 0, 0, 0.6);
    border-radius: 4px;
    pointer-events: none;
}
.job-line:empty { display: none; }
.job-line.is-done { color: #1b1020; background: #ffd166; }
/* The reward: the pen is free until dawn, and the bar is gold while it is. */
.ink-container.is-free { box-shadow: 0 0 0 2px #ffd166, 0 0 14px rgba(255, 209, 102, 0.6); }
.ink-container.is-free .ink-level,
.ink-container.is-free .ink-bar > div { background: linear-gradient(90deg, #ffd166, #fff1b8, #ffd166) !important; background-size: 200% 100% !important; animation: free-ink 1.4s linear infinite; }
.ink-container.is-free > div:first-child { color: #ffd166 !important; }
@keyframes free-ink { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .ink-container.is-free .ink-level, .ink-container.is-free .ink-bar > div { animation: none; } }

/* --- PAUSED, and what it offers (ui/pauseMenu.js) --- */
.pause-menu {
    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    z-index: 90;                    /* over the drawing overlay (50) and the HUD; under the books */
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: clamp(6px, 1.4vh, 12px);
    min-width: min(300px, 70%);
    padding: clamp(10px, 2.4vh, 22px) clamp(14px, 2.4vw, 28px);
    font-family: 'Press Start 2P', cursive;
    text-align: center;
    background: rgba(27, 16, 32, 0.95);
    border: 4px solid #fffdf4;
    box-shadow: 8px 8px 0 rgba(0, 0, 0, 0.5);
}
.pause-menu.is-open { display: flex; }
.pause-menu.is-behind { visibility: hidden; }
.pause-title { font-size: clamp(14px, 2.2vw, 26px); color: #fffdf4; text-shadow: 3px 3px 0 #000; margin-bottom: 4px; }
.pause-button {
    font-family: inherit;
    font-size: clamp(9px, 1.15vw, 14px);
    padding: clamp(9px, 1.8vh, 14px) 16px;
    color: #fffdf4;
    background: rgba(60, 40, 70, 0.95);
    border: 3px solid #fffdf4;
    box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.5);
    cursor: pointer;
    white-space: nowrap;
}
.pause-button:hover, .pause-button:focus-visible { background: rgba(90, 62, 104, 0.98); outline: none; }
.pause-button:active { transform: translate(2px, 2px); box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.5); }
.pause-button.is-primary { color: #1b1020; background: #ffd166; }
.pause-button.is-primary:hover, .pause-button.is-primary:focus-visible { background: #ffe39a; }
.pause-button.is-quit { color: #ffb4a8; }
.pause-button.is-quit.is-armed { color: #fffdf4; background: #c0392b; }

/* The pictures in the three steps. */

.doodle path {
    fill: none;
    stroke: #fffdf4;
    stroke-width: 4;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 640;
    stroke-dashoffset: 640;
    animation: doodle-draw 3.2s ease-in-out infinite;
}

@keyframes doodle-draw {
    0% { stroke-dashoffset: 640; }
    55%, 88% { stroke-dashoffset: 0; }
    100% { stroke-dashoffset: 640; }
}

.doodle-guess {
    position: absolute;
    right: 4%;
    bottom: 6%;
    padding: 4px 6px;
    font-size: clamp(6px, 0.75vw, 9px);
    color: #9be28f;
    background: rgba(0, 0, 0, 0.7);
    opacity: 0;
    animation: doodle-guess 3.2s ease-in-out infinite;
}

@keyframes doodle-guess {
    0%, 55% { opacity: 0; }
    62%, 90% { opacity: 1; }
    100% { opacity: 0; }
}

.drop-item {
    position: absolute;
    left: 50%;
    bottom: 12%;
    height: 58%;
    transform: translateX(-50%);
    image-rendering: pixelated;
    animation: drop-fall 2.4s cubic-bezier(.5, 0, 1, .6) infinite;
}

@keyframes drop-fall {
    0% { transform: translate(-50%, -190%) rotate(-25deg); }
    38%, 100% { transform: translate(-50%, 0) rotate(0deg); }
}

.drop-rabbit {
    position: absolute;
    bottom: 0;
    width: 40px;
    height: 40px;
    background: url('assets/images/Bunny/bunny.png') 0 -960px / 440px auto no-repeat;
    image-rendering: pixelated;
    animation: drop-squash 2.4s linear infinite;
}

@keyframes drop-squash {
    0%, 36% { opacity: 1; transform: none; }
    40%, 92% { opacity: 0; transform: scaleY(0.1); }
    100% { opacity: 1; transform: none; }
}

.gauge {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 10px;
    height: 100%;
}

.gauge-bar {
    height: 16px;
    border: 3px solid #fffdf4;
    background: rgba(0, 0, 0, 0.5);
}

.gauge-fill {
    height: 100%;
    width: 8%;
    background: #8BC34A;
    animation: gauge-rise 5s ease-in infinite;
}

@keyframes gauge-rise {
    0% { width: 8%; background: #8BC34A; }
    60% { background: #ffa500; }
    92%, 100% { width: 100%; background: #ff3b3b; }
}

.gauge-label {
    font-size: clamp(7px, 0.85vw, 11px);
    color: #fffdf4;
}

/* NARROW (a phone held upright, a slim window): the steps stack, picture beside
   words. */
@media (max-width: 700px) and (min-height: 521px) {
    .briefing-steps { grid-template-columns: 1fr; }
    .briefing-step {
        flex-direction: row;
        flex-wrap: wrap;
        text-align: left;
        align-items: center;
        gap: 6px 12px;
    }
    .briefing-art { width: 34%; height: 56px; flex: none; }
    .briefing-step h3, .briefing-step p { width: 60%; flex: 1 1 58%; }
    .briefing-bubble { margin-bottom: 22px; }
}

/* SHORT (a phone on its side, any width — an iPhone SE is only 667 across):
   room for three across and no height for anything else. This used to share
   the rule above, which stacked the cards off the bottom of the screen and
   took PLAY with them; and then split from it on WIDTH, which still caught the
   SE. The question is height, so the test is height. Everything
   shrinks until PLAY is on screen without scrolling at 340px tall. */
@media (max-height: 520px) {
    .briefing { gap: 6px; padding: 6px max(14px, env(safe-area-inset-right)) 8px max(14px, env(safe-area-inset-left)); }
    .briefing-farmer { gap: 10px; align-items: center; }
    .briefing-farmer canvas { height: 58px; }
    .briefing-bubble { margin-bottom: 0; padding: 7px 10px; font-size: 8px; line-height: 1.6; }
    .briefing-step { gap: 4px; padding: 6px 8px; }
    .briefing-art { height: 40px; }
    .briefing-step h3 { font-size: 9px; }
    .briefing-step p { font-size: 7px; line-height: 1.55; }
    .briefing-play { font-size: 13px; padding: 9px 34px; border-width: 3px; }
    .briefing-foot { display: none; }
    .drop-rabbit { width: 28px; height: 28px; background-size: 308px auto; background-position: 0 -672px; }
}

@media (prefers-reduced-motion: reduce) {
    #loadingRunner, .doodle path, .doodle-guess, .drop-item, .drop-rabbit, .gauge-fill { animation: none; }
    .doodle path { stroke-dashoffset: 0; }
    .doodle-guess { opacity: 1; }
    .gauge-fill { width: 70%; background: #ffa500; }
}

.canvas-container {
    position: relative;
    width: 100%;
    /* A shadow, not a border. With border-box sizing a 4px border comes OUT of
       the box that carries the aspect ratio, so the canvas inside was 8px short
       each way and no longer 2000:850 — it letterboxed by ~5px a side under
       object-fit, and clientToWorld (which maps against the element) was out by
       up to 16 world px at the edges. A spread shadow draws the same white
       frame and takes up no layout at all. */
    box-shadow: 0 0 0 4px #fff;
    overflow: hidden;
    /* No max-height: see .game-container. A cap here is what letterboxed the
       bitmap inside its own element. */
    /* Exactly the canvas bitmap: 2000 x 850. Written as the division so it
       cannot drift from the real thing. It was 2.35/1, which is close but not
       equal to 2000/850 (2.3529…); with object-fit: contain that mismatch
       letterboxed the bitmap and let the canvas's own background show through
       as vertical bars down both sides. */
    aspect-ratio: var(--field-w, 2000) / 850;
}

#gameCanvas {
    display: block;
    /* Deliberately transparent, NOT the old opaque #5c94fc. The canvas paints
       its own sky every frame, so this colour was only ever visible in the
       letterbox gap — which is exactly what the blue bars were. Transparent
       means any residual sub-pixel rounding shows the frame's own dark
       backdrop instead of a bright blue stripe. */
    background-color: transparent;
    width: 100%; /* Make canvas responsive */
    height: 100%; /* Changed from auto to 100% */
    object-fit: contain; /* Preserve aspect ratio */
}

@media (max-width: 768px) {
    .game-ui {
        flex-direction: column;
        gap: 10px;
        padding: 5px;
    }
    
    .stats {
        flex-wrap: wrap;
        justify-content: center;
        gap: 8px;
        font-size: 8px;
    }
    
    .controls {
        flex-wrap: wrap;
        justify-content: center;
    }
    
    .control-item {
        min-width: 40px;
        padding: 5px;
        font-size: 10px;
    }
    
    #timeElapsed, #day, #rabbitsKilled, #score, #rabbitCount {
        padding: 2px 4px;
    }
}

.scroll-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 40px;
    height: 40px;
    background-color: rgba(0, 0, 0, 0.5);
    color: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 24px;
    cursor: pointer;
    /* Must sit above #drawingOverlay (z-index 50), which covers the canvas with
       pointer-events:auto — otherwise clicks start a drawing instead of scrolling. */
    z-index: 60;
    user-select: none;
}

.scroll-arrow.disabled {
    opacity: 0.3;
    cursor: default;
    background-color: rgba(0, 0, 0, 0.3);
}

.left-arrow {
    left: 10px;
}

.right-arrow {
    right: 10px;
}

/* The bin with nothing to bin. Inline styles give it `cursor: pointer`, hence
   the !important. See DrawingInterface.syncClearButton. */
#clearDrawing.is-idle {
    opacity: 0.32;
    filter: grayscale(0.7);
    cursor: default !important;
}

/* --- The field map: a scrollbar that shows where the rabbits are --- */

.field-map {
    position: relative;
    width: 100%;
    height: 26px;
    margin-top: 6px;
    background: #0b0f0c;
    border: 3px solid #fff;
    cursor: pointer;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    flex: none;
    /* #drawingOverlay is a full-WINDOW canvas at z-index 50, not just the
       field — without this the map is underneath it and a finger on the map
       draws a line across it instead of scrolling. */
    z-index: 60;
}

.field-map-dots {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    image-rendering: pixelated;
}

/* What the frame is showing. Lighter than its surroundings rather than framed
   in a heavy box, so the dots underneath stay readable. */
.field-map-thumb {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 50%;
    background: rgba(139, 195, 74, 0.28);
    border-left: 3px solid #8BC34A;
    border-right: 3px solid #8BC34A;
    cursor: grab;
}

.field-map.is-dragging,
.field-map.is-dragging .field-map-thumb {
    cursor: grabbing;
}

.field-map.is-dragging .field-map-thumb {
    background: rgba(139, 195, 74, 0.42);
}

/* A finger needs more to hold on to than a mouse does. */
@media (pointer: coarse) {
    .field-map { height: 32px; }
}

.game-ui {
    width: 100%;
    padding: 10px;
    display: flex;
    justify-content: space-between;
    margin-top: 10px;
    border: 4px solid #fff;
}

.stats {
    display: flex;
    gap: 15px;
    align-items: center;
    font-size: 10px;
    font-family: 'Press Start 2P', cursive;
}

#timeElapsed, #day, #rabbitsKilled, #score, #rabbitCount {
    white-space: nowrap;
    padding: 4px 8px;
    text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
    background-color: rgba(0, 0, 0, 0.4);
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 4px;
}

/* The counter's label is a rabbit (src/ui/hudRabbit.js). It sits IN the pill and
   sticks out of the top of it: negative margins, so a 30px animal does not make
   a 20px pill 30px tall and shove the whole HUD row about. */
#rabbitCount.has-hud-rabbit {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding-left: 5px;
}
.hud-rabbit {
    width: 35px;               /* 23x24 source, at a whole 1.5x */
    height: 36px;
    margin: -22px 0 -4px -2px;
    image-rendering: pixelated;
    pointer-events: none;
    flex: none;
}

#score {
    color: #8BC34A; /* Light green */
    font-weight: bold;
    border-color: rgba(139, 195, 74, 0.5);
}

#rabbitsKilled {
    color: #FF5252; /* Red */
    border-color: rgba(255, 82, 82, 0.5);
}

.controls {
    display: flex;
    gap: 10px;
}

.control-item {
    padding: 10px;
    background-color: #e7471d; /* Mario red */
    cursor: pointer;
    text-align: center;
    min-width: 60px;
}

.control-item.cooldown {
    background-color: #666;
    cursor: not-allowed;
}

/* --- Ingredient tray ---
   Holds drawn items. Drag a slot onto the canvas to deploy it, or onto another
   slot to combine them into a recipe. */

.ingredient-tray {
    /* Sits in normal flow directly under .game-ui so it stays attached to the
       game rather than floating at the bottom of the viewport. */
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 8px;
    width: 100%;
    margin-top: 10px;
    padding: 10px 12px;
    background-color: rgba(0, 0, 0, 0.75);
    border: 4px solid #444;
    border-radius: 5px;
    box-sizing: border-box;
    /* Above #drawingOverlay (50) so drags start on the slot, not the canvas. */
    z-index: 60;
}

.ingredient-tray-label {
    font-size: 10px;
    color: #8BC34A;
    letter-spacing: 1px;
    margin-right: 4px;
}

.ingredient-slot {
    position: relative;
    width: 74px;
    height: 66px;
    background-color: #111;
    border: 3px dashed #555;
    box-sizing: border-box;
    cursor: grab;
    flex: 0 0 auto;
}

.ingredient-slot[data-item] {
    border-style: solid;
    cursor: grab;
}

.ingredient-slot.is-drop-target {
    border-color: #8BC34A;
    background-color: #1d2a12;
}

/* A chip being dropped ON: bigger, and GREEN if the two make something, RED if
   not (§69). Obvious from arm's length — a border colour alone was not. */
.ingredient-slot.is-drop-target.is-match,
.ingredient-slot.is-drop-target.is-nomatch {
    transform: scale(1.14);
    transition: transform 0.08s ease-out;
    z-index: 2;
}
.ingredient-slot.is-drop-target.is-match {
    border-color: #8BC34A !important;
    background-color: #1f3a12 !important;
    box-shadow: 0 0 0 3px #8BC34A, 0 0 18px 4px rgba(139, 195, 74, 0.85);
}
.ingredient-slot.is-drop-target.is-nomatch {
    border-color: #ff5555 !important;
    background-color: #3a1212 !important;
    box-shadow: 0 0 0 3px #ff5555, 0 0 18px 4px rgba(255, 85, 85, 0.75);
}
/* ...and the picture's own frame with it, which carries an inline green: a red
   chip with a green frame inside it reads as neither. */
.ingredient-slot.is-drop-target.is-match .item { border-color: #8BC34A !important; }
.ingredient-slot.is-drop-target.is-nomatch .item { border-color: #ff5555 !important; }
.ingredient-slot.is-rejected { animation: chip-no 0.36s ease-in-out; }
@keyframes chip-no {
    0%, 100% { transform: translateX(0); }
    20% { transform: translateX(-6px); }
    40% { transform: translateX(6px); }
    60% { transform: translateX(-4px); }
    80% { transform: translateX(4px); }
}
@media (prefers-reduced-motion: reduce) {
    .ingredient-slot.is-rejected { animation: none; }
}

.ingredient-slot.is-crafted .item {
    animation: crafted-flash 0.5s ease-out;
}

@keyframes crafted-flash {
    from { background-color: #8BC34A; }
    to   { background-color: #000; }
}

.ingredient-slot .item {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 2px;
    background-color: #000;
    border: 3px solid #555;
    box-sizing: border-box;
    text-align: center;
    padding: 2px;
    overflow: hidden; /* long crafted names must not spill out of the slot */
    pointer-events: none; /* let drags originate from the slot */
}

/* The player's doodle, used as the item's art. */
.ingredient-slot .item-sprite {
    width: 26px;
    height: 26px;
    object-fit: contain;
    flex: 0 0 auto;
    image-rendering: pixelated;
    /* No invert: doodles are drawn in the item's own colour now. */
}

.recipe-chip .item-sprite {
    width: 22px;
    height: 22px;
    object-fit: contain;
}

.ingredient-slot .item-name {
    font-size: 6px;
    color: #fff;
    line-height: 1.2;
    word-break: break-word;
    max-height: 16px;
    overflow: hidden;
}

.ingredient-slot .item-conf {
    font-size: 8px;
    flex: 0 0 auto;
}
.item-conf:empty { display: none; }

/* How big it was drawn, when that is not the usual size. mechanics/drawnSize.js */
.item-size {
    color: #ffe08a;
    letter-spacing: 0;
}

.ingredient-remove {
    position: absolute;
    top: -8px;
    right: -8px;
    width: 20px;
    height: 20px;
    padding: 0;
    background-color: #e7471d;
    color: #fff;
    border: 2px solid #000;
    border-radius: 50%;
    font-family: inherit;
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    display: none;
    z-index: 2;
}

.ingredient-slot[data-item] .ingredient-remove {
    display: block;
}

.tray-message {
    position: absolute;
    bottom: -22px;
    left: 0;
    width: 100%;
    text-align: center;
    font-size: 9px;
    color: #FFA500;
}

/* --- Something crafted ---
   The chip arrives with a pop every time; the first time a recipe is made it
   also gets a card over the field. DrawingInterface.showDiscovery. */

.ingredient-slot.is-fresh { animation: crafted-pop 0.62s cubic-bezier(.3, 1.6, .5, 1); }
.ingredient-slot.is-crafted .item-sprite { filter: drop-shadow(0 0 5px rgba(255, 209, 102, 0.9)); }

@keyframes crafted-pop {
    0%   { transform: scale(0.4) rotate(-14deg); box-shadow: 0 0 0 0 rgba(255, 209, 102, 0.9); }
    55%  { transform: scale(1.22) rotate(5deg);  box-shadow: 0 0 0 14px rgba(255, 209, 102, 0); }
    100% { transform: scale(1) rotate(0); box-shadow: 0 0 0 0 rgba(255, 209, 102, 0); }
}

.discovery-card {
    position: absolute;
    left: 50%;
    top: 44%;
    z-index: 68;                       /* over the overlay (50) and the HUD, under the ending card */
    width: min(430px, 72%);
    padding: 18px 22px 20px;
    text-align: center;
    font-family: 'Press Start 2P', cursive;
    color: #fffdf4;
    background: rgba(27, 16, 32, 0.95);
    border: 4px solid #ffd166;
    box-shadow: 8px 8px 0 rgba(0, 0, 0, 0.45);
    overflow: hidden;
    cursor: pointer;
    transform: translate(-50%, -50%);
    animation: discovery-in 0.42s cubic-bezier(.3, 1.5, .5, 1);
}
.discovery-card.is-leaving { opacity: 0; transform: translate(-50%, -58%) scale(0.94); transition: opacity 0.25s, transform 0.25s; }

@keyframes discovery-in {
    from { opacity: 0; transform: translate(-50%, -40%) scale(0.6) rotate(-3deg); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0); }
}

/* Turning rays behind the picture: a conic gradient, so it costs nothing. */
.discovery-rays {
    position: absolute;
    left: 50%;
    top: 46%;
    width: 560px;
    height: 560px;
    margin: -280px 0 0 -280px;
    background: repeating-conic-gradient(rgba(255, 209, 102, 0.16) 0 12deg, transparent 12deg 24deg);
    animation: discovery-turn 14s linear infinite;
    pointer-events: none;
}
@keyframes discovery-turn { to { transform: rotate(360deg); } }

.discovery-label { position: relative; font-size: clamp(8px, 0.9vw, 11px); color: #ffd166; letter-spacing: 2px; margin-bottom: 10px; }
.discovery-art {
    position: relative;
    display: block;
    width: clamp(84px, 11vw, 150px);
    height: clamp(84px, 11vw, 150px);
    margin: 0 auto 10px;
    object-fit: contain;
    image-rendering: pixelated;
    filter: drop-shadow(0 0 12px rgba(255, 209, 102, 0.85));
    animation: discovery-bob 1.6s ease-in-out infinite;
}
@keyframes discovery-bob { 50% { transform: translateY(-6px) rotate(3deg); } }
.discovery-name { position: relative; font-size: clamp(12px, 1.6vw, 20px); line-height: 1.5; margin-bottom: 8px; }
.discovery-joke { position: relative; font-size: clamp(7px, 0.85vw, 10px); line-height: 1.7; color: #cfc6d6; }

@media (prefers-reduced-motion: reduce) {
    .ingredient-slot.is-fresh, .discovery-card, .discovery-rays, .discovery-art { animation: none; }
}

/* --- Recipe box ---
   One slot that accumulates ingredients. CRAFT either produces the result or
   rejects the mix and hands the ingredients back. */

.recipe-box {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: 6px;
    padding-left: 12px;
    border-left: 3px solid #444;
}

/* BIGGER. It worked; it was just a postage stamp — a 60x44 chip with its name in
   6px type, in the corner of the tray. (A full-screen crafting page was tried and
   was, in Mat's words, massive overkill: §45.) Same box, same behaviour, more of
   it, and the ingredients have their pictures now. */
.recipe-slot {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 300px;
    min-height: 92px;          /* a chip's height, so filling it does not change the tray's */
    padding: 7px;
    background-color: #111;
    border: 3px dashed #555;
    box-sizing: border-box;
}

.recipe-slot.is-empty {
    justify-content: center;
    font-size: 8px;
    color: #666;
}

.recipe-slot.is-drop-target {
    border-color: #8BC34A;
    background-color: #1d2a12;
}

.recipe-chip {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 2px;
    width: 92px;
    height: 70px;
    padding: 3px;
    background-color: #000;
    border: 3px solid #555;
    box-sizing: border-box;
    text-align: center;
    overflow: hidden;
    cursor: pointer;
    flex: 0 0 auto;
}

.recipe-chip .item-sprite { width: 34px; height: 34px; object-fit: contain; image-rendering: pixelated; }
.recipe-chip .item-name {
    font-size: 7px;
    color: #fff;
    line-height: 1.25;
    word-break: break-word;
    max-height: 24px;
    overflow: hidden;
}

.recipe-chip .item-conf { font-size: 7px; }

.recipe-result {
    min-width: 130px;
    font-size: 10px;
    color: #888;
    text-align: center;
    line-height: 1.4;
}

.recipe-result.is-match { color: #8BC34A; }
.recipe-result.is-nomatch { color: #FF5555; }

.craft-button {
    padding: 16px 18px;
    background-color: #8BC34A;
    color: #000;
    border: none;
    font-family: inherit;
    font-size: 13px;
    cursor: pointer;
}

/* HINT gives a clue, never a recipe (DrawingInterface.showHint). */
.hint-button {
    padding: 16px 12px;
    font-family: inherit;
    font-size: 10px;
    color: #ffd166;
    background: #15150f;
    border: 2px solid #5a4a1c;
    cursor: pointer;
}
.hint-line {
    /* Beside the buttons on a desktop, where the tray is one wide row and a line
       of its own pushed the whole tray off the bottom of the window. The touch
       pop-up has room to grow upwards, and gives it a row (see the phone block). */
    flex: 0 1 320px;
    min-height: 1.6em;
    font-size: 9px;
    line-height: 1.6;
    color: #cfc6a0;
}
.hint-line:empty { display: none; }
.hint-line b { color: #ffd166; font-weight: normal; }


.craft-button:disabled {
    background-color: #555;
    color: #888;
    cursor: not-allowed;
}

/* Highlight the play area while dragging an item over it. */
.canvas-container.is-drop-target {
    outline: 4px solid #8BC34A;
    outline-offset: -4px;
}

/* Copy of the dragged slot that follows the pointer. */
.drag-ghost {
    position: fixed;
    transform: translate(-50%, -50%);
    opacity: 0.85;
    pointer-events: none;
    z-index: 9998;
} 
/* --- Recipe book (press R) ---
   Undiscovered recipes show only a hint and their shape. The book is a record
   of what you worked out, not a menu to follow. */

.recipe-book {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    background-color: #12120d;
    z-index: 9000;
    /* Inside the notch and the home bar; the page itself still fills the glass. */
    padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

.recipe-book-backdrop { display: none !important; }

.recipe-book-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 16px;
    padding: 12px 18px;
    border-bottom: 3px solid #2c2c22;
    background: #181811;
}

.recipe-book-title { font-size: clamp(11px, 1.5vw, 18px); color: #8BC34A; letter-spacing: 1px; }

.recipe-book-progress { display: flex; align-items: center; gap: 10px; flex: 1 1 160px; min-width: 120px; font-size: clamp(8px, 1vw, 11px); color: #cfc6a0; }
.recipe-book-bar { flex: 1 1 auto; height: 10px; background: #0b0b08; border: 2px solid #3a3a2c; }
.recipe-book-bar i { display: block; height: 100%; width: 0; background: #8BC34A; transition: width 0.4s; }
.recipe-book-progress b { font-weight: normal; white-space: nowrap; }

.recipe-book-tabs { display: flex; gap: 6px; }
.recipe-book-tabs button,
.recipe-book-close {
    font-family: inherit;
    font-size: clamp(7px, 0.85vw, 10px);
    padding: 9px 10px;
    color: #cfc6a0;
    background: #0b0b08;
    border: 2px solid #3a3a2c;
    cursor: pointer;
}
.recipe-book-tabs button.is-on { color: #12120d; background: #8BC34A; border-color: #8BC34A; }
.recipe-book-close { color: #12120d; background: #ffd166; border-color: #ffd166; }

.recipe-book-list {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 14px 18px 24px;
}

/* How crafting works, in three lines. */
.recipe-book-how > summary { grid-column: 1 / -1; cursor: pointer; color: #ffd166; font-size: clamp(7px, 0.85vw, 10px); letter-spacing: 1px; list-style: none; }
.recipe-book-how > summary::before { content: '+ '; }
.recipe-book-how[open] > summary::before { content: '- '; }
.recipe-book-how > summary::-webkit-details-marker { display: none; }
.recipe-book-how {
    display: block;
    margin-bottom: 14px;
    font-size: clamp(7px, 0.8vw, 9px);
    line-height: 1.8;
    color: #9a9a86;
}
/* The grid goes on a row INSIDE the fold, never on the `details` itself. */
.recipe-book-how-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 8px;
    margin-top: 8px;
}
.recipe-book-how-row > div { padding: 9px 11px; background: #0b0b08; border-left: 4px solid #ffd166; }
.recipe-book-how b { display: block; margin-bottom: 3px; color: #ffd166; font-weight: normal; }

.recipe-book-none { padding: 30px 10px; font-size: 10px; color: #777; }


/* Two columns where there is room for them; one on a phone. */
.recipe-book-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 8px;
}

.recipe-entry {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    padding: 9px 10px;
    border-left: 4px solid #333;
    background-color: #0b0b08;
    min-width: 0;
}

.recipe-entry.is-found { border-left-color: #8BC34A; }

.recipe-entry-art {
    flex: 0 0 auto;
    width: 56px;
    height: 56px;
    object-fit: contain;
    image-rendering: pixelated;
}
.recipe-entry-art.is-blank { background: #15150f; }

/* Not yet made: the shape of it and nothing else. */
.recipe-entry.is-hidden .recipe-entry-art { filter: brightness(0) invert(0.22); }

.recipe-entry-text { min-width: 0; flex: 1 1 auto; }

.recipe-entry-name {
    font-size: 10px;
    color: #fff;
    margin-bottom: 4px;
    line-height: 1.5;
}
.recipe-entry.is-hidden .recipe-entry-name { color: #555; }

.recipe-entry-kind {
    font-size: 7px;
    color: #6f8f4a;
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.recipe-entry-kind:empty { display: none; }

.recipe-entry-inputs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    font-size: 8px;
    color: #FFA500;
    margin-bottom: 6px;
}

.recipe-ingredient {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 5px 2px 2px;
    background: #1b1a12;
    border: 1px solid #3a3420;
}
.recipe-ingredient-art { width: 20px; height: 20px; object-fit: contain; image-rendering: pixelated; }
.recipe-ingredient.is-unknown { padding: 5px 8px; color: #555; border-color: #2a2a22; }
/* A KIND of thing rather than a thing: "anything electric". */
.recipe-ingredient.is-kind { padding: 5px 8px; color: #8fd3ff; border-color: #24465e; font-style: italic; }
.recipe-plus { color: #6a5a2a; }

.recipe-entry-joke {
    font-size: 8px;
    color: #999;
    line-height: 1.6;
}

.recipe-entry.is-hidden .recipe-entry-joke { color: #777; font-style: italic; }

/* --- Tuning panel (press ` ) ---
   Editing an archetype retunes every item using it, live, against the rabbits
   currently on screen. Export downloads the file; nothing is written for you. */

.tuning-panel {
    position: fixed;
    top: 16px;
    right: 16px;
    width: min(400px, 92vw);
    max-height: 88vh;
    flex-direction: column;
    background-color: #0d0f14;
    border: 4px solid #3498db;
    border-radius: 5px;
    z-index: 9500;
    box-shadow: 0 0 0 4px #000;
}

/* Popped out into its own window: fill it rather than float over a page.
   The panel element is MOVED into the popup, not copied, so it keeps all its
   listeners and stays wired to the running game. See TuningPanel.popOut(). */
.tuning-panel.tuning-popped {
    position: static;
    width: 100%;
    max-width: none;
    max-height: 100vh;
    height: 100vh;
    border: none;
    border-radius: 0;
    box-shadow: none;
}

.tuning-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 12px;
    font-size: 11px;
    color: #3498db;
    letter-spacing: 1px;
    border-bottom: 3px solid #222;
}

.tuning-close {
    background: none;
    border: none;
    color: #FF5252;
    font-family: inherit;
    font-size: 15px;
    cursor: pointer;
    line-height: 1;
}

.tuning-body { overflow-y: auto; padding: 10px 12px 14px; }

.tuning-live {
    font-size: 8px;
    color: #8BC34A;
    padding: 7px 8px;
    margin-bottom: 10px;
    background-color: #05070a;
    border-left: 3px solid #8BC34A;
    line-height: 1.6;
}

.tuning-row { margin-bottom: 12px; }

.tuning-row label {
    display: block;
    font-size: 8px;
    color: #888;
    margin-bottom: 5px;
}

.tuning-row select,
.tuning-text {
    width: 100%;
    padding: 6px;
    margin-bottom: 6px;
    background-color: #05070a;
    color: #fff;
    border: 2px solid #333;
    font-family: inherit;
    font-size: 9px;
}

.tuning-note {
    font-size: 7px;
    color: #666;
    line-height: 1.6;
    margin-top: 4px;
}

.tuning-sliders { margin-bottom: 12px; }

/* label | slider | typed value | derived readout. The number field is editable:
   some values you know rather than feel, and typing also escapes the slider's
   range, which is a guess at sensible values rather than a limit. */
.tuning-slider {
    display: grid;
    grid-template-columns: 88px 1fr 62px 54px;
    align-items: center;
    gap: 8px;
    margin-bottom: 7px;
}

.tuning-slider label { font-size: 7px; color: #888; margin: 0; }
.tuning-slider input[type="range"] { width: 100%; accent-color: #3498db; }
.tuning-value { font-size: 7px; color: #8BC34A; text-align: right; }

.tuning-toggle {
    width: 16px;
    height: 16px;
    accent-color: #3498db;
    cursor: pointer;
    justify-self: start;
}

.tuning-number {
    width: 100%;
    min-width: 0;
    padding: 3px 4px;
    font-family: inherit;
    font-size: 7px;
    color: #8BC34A;
    background-color: #05070a;
    border: 1px solid #2c3e50;
    border-radius: 3px;
    text-align: right;
}

.tuning-number:focus {
    outline: none;
    border-color: #3498db;
    color: #fff;
}

.tuning-button {
    padding: 7px 10px;
    margin-right: 6px;
    background-color: #3498db;
    color: #000;
    border: none;
    font-family: inherit;
    font-size: 8px;
    cursor: pointer;
}

.tuning-button:hover { background-color: #5dade2; }

/* Armed, and one more click throws away unsaved tuning. Red because the cost of
   the next click is not recoverable, unlike every other button in the panel. */
.tuning-button-danger { background-color: #e74c3c; color: #fff; }
.tuning-button-danger:hover { background-color: #ec7063; }

.tuning-empty { font-size: 9px; color: #666; padding: 10px; }

/* Scope heading — makes it obvious whether a slider affects one item or 114. */
.tuning-scope {
    font-size: 8px;
    letter-spacing: .1em;
    color: #8BC34A;
    margin-bottom: 8px;
    padding-bottom: 5px;
    border-bottom: 1px solid #2a2e1d;
}

/* Per-parameter explanation under each slider. */
.tuning-hint {
    grid-column: 1 / -1;
    font-size: 7px;
    color: #6a705c;
    line-height: 1.6;
    margin: -3px 0 8px;
}

/* ---------------------------------------------------------------------------
   The review pass (tuning panel).

   Curating 346 items is a job you come back to over several evenings, so the
   panel has to answer "where am I" before it answers anything else. Colour is
   the only fast channel for that at this size: green done, amber wants art,
   grey skipped, and the bar is the whole vocabulary at a glance.
   See src/ui/reviewList.js.
   --------------------------------------------------------------------------- */

.tuning-review {
    margin-bottom: 14px;
    padding-bottom: 12px;
    border-bottom: 1px solid #1d2430;
}

.tuning-review-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 8px;
    color: #8a93a6;
    margin-bottom: 6px;
}

.tuning-review-head b { color: #8BC34A; font-size: 11px; }

.tuning-review-save { font-size: 7px; color: #4a5160; }
.tuning-review-save.tuning-review-warn { color: #FF7043; }

/* Segments, not one fill: the split between done and needs-art is the useful
   number, and a single bar would hide it. */
.tuning-review-bar {
    display: flex;
    height: 6px;
    background-color: #171c26;
    border-radius: 3px;
    overflow: hidden;
}

.tuning-review-fill { height: 100%; }
.tuning-review-fill.is-done { background-color: #8BC34A; }
.tuning-review-fill.is-art { background-color: #FFB300; }
.tuning-review-fill.is-skip { background-color: #4a5160; }

.tuning-review-legend {
    font-size: 7px;
    color: #6a705c;
    margin: 5px 0 10px;
}

.tuning-review-title {
    font-size: 10px;
    color: #e8eaf0;
    margin-bottom: 8px;
}

.tuning-review-title span { font-size: 7px; color: #5c6474; }

/* The sprite at both sizes it has to survive — in the field, and as a tray
   chip. Bottom-aligned to match how the world renderer seats ground art. */
.tuning-art {
    display: flex;
    align-items: flex-end;
    gap: 14px;
    padding: 10px;
    margin-bottom: 10px;
    background-color: #12161e;
    border: 1px solid #1d2430;
    border-radius: 3px;
}

.tuning-art-cell { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.tuning-art-cell span { font-size: 6px; color: #5c6474; }
.tuning-art-cell img { display: block; }
.tuning-art-tier { margin-left: auto; font-size: 6px; color: #5c6474; }
.tuning-art-none { font-size: 7px; color: #6a705c; padding: 8px 0; }

.tuning-review-states { display: flex; gap: 6px; margin-bottom: 8px; }

.tuning-state {
    flex: 1;
    margin-right: 0;
    background-color: #232935;
    color: #8a93a6;
}

.tuning-state:hover { background-color: #2c3442; }
.tuning-state.is-current.is-done { background-color: #8BC34A; color: #000; }
.tuning-state.is-current.is-art { background-color: #FFB300; color: #000; }
.tuning-state.is-current.is-skip { background-color: #6a7382; color: #000; }

.tuning-review-note { margin-bottom: 8px; }
.tuning-review-nav { display: flex; gap: 6px; margin-bottom: 8px; }
.tuning-review-nav .tuning-button { flex: 1; margin-right: 0; }
.tuning-review-message { font-size: 7px; color: #FFB300; min-height: 10px; margin-bottom: 4px; }

.tuning-review-filters { display: flex; gap: 4px; margin: 10px 0 8px; }

.tuning-filter {
    flex: 1;
    margin-right: 0;
    padding: 5px 4px;
    font-size: 6px;
    background-color: #232935;
    color: #8a93a6;
}

.tuning-filter.is-current { background-color: #3498db; color: #000; }

/* 346 rows, so they have to be dense and scannable rather than pretty. */
.tuning-checklist {
    max-height: 320px;
    overflow-y: auto;
    border: 1px solid #1d2430;
    border-radius: 3px;
    background-color: #0a0d12;
}

.tuning-checklist-group {
    position: sticky;
    top: 0;
    padding: 5px 8px;
    background-color: #171c26;
    font-size: 7px;
    letter-spacing: .1em;
    color: #8BC34A;
}

.tuning-checklist-row {
    display: flex;
    align-items: center;
    gap: 7px;
    width: 100%;
    padding: 4px 8px;
    background: none;
    border: none;
    font-family: inherit;
    font-size: 7px;
    color: #8a93a6;
    text-align: left;
    cursor: pointer;
}

.tuning-checklist-row:hover { background-color: #171c26; }
.tuning-checklist-row.is-current { background-color: #1d2b3a; color: #e8eaf0; }
.tuning-checklist-row.is-done { color: #5c6474; }
.tuning-checklist-note { margin-left: auto; color: #FFB300; }

.tuning-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex-shrink: 0;
    background-color: #2c3442;
}

.tuning-dot.is-done { background-color: #8BC34A; }
.tuning-dot.is-art { background-color: #FFB300; }
.tuning-dot.is-skip { background-color: #6a7382; }

.tuning-art-queue {
    margin-top: 10px;
    padding: 8px;
    background-color: #1a1509;
    border: 1px solid #3d3110;
    border-radius: 3px;
}

/* ---------------------------------------------------------------------------
   Grouped controls.

   Twenty-odd knobs with an explanation under each is a scroll rather than a
   panel. Sections are collapsible, remember what you had open, and are hidden
   entirely when nothing in them applies to the item in front of you.
   --------------------------------------------------------------------------- */

.tuning-group { margin-bottom: 4px; }

.tuning-group-head {
    display: flex;
    align-items: center;
    gap: 7px;
    width: 100%;
    padding: 7px 8px;
    background-color: #171c26;
    border: none;
    border-left: 2px solid #2c3442;
    font-family: inherit;
    font-size: 8px;
    letter-spacing: .08em;
    color: #8a93a6;
    text-align: left;
    cursor: pointer;
}

.tuning-group-head:hover { background-color: #1d2430; color: #c8cedb; }
.tuning-group-head.is-open { color: #8BC34A; border-left-color: #8BC34A; }
.tuning-group-caret { font-size: 7px; width: 8px; }

/* How many knobs are inside, so a shut section still says whether it is worth
   opening for this particular item. */
.tuning-group-count {
    margin-left: auto;
    padding: 1px 5px;
    background-color: #0d0f14;
    border-radius: 8px;
    font-size: 6px;
    color: #5c6474;
}

.tuning-group-body {
    padding: 10px 8px 4px;
    border-left: 2px solid #2c3442;
}

/* One switch for every explanation in the panel — they are what make it
   readable by someone who did not write it, and also most of its height. The
   text stays on `title`, so it is one hover away rather than gone. */
.tuning-hints-off .tuning-hint { display: none; }
.tuning-hints-button.is-off { opacity: .4; }


/* --- Small and short screens: iPhone in landscape, iPad split view --- */

/* The ink bar is given 580px inline by DrawingInterface, which is wider than a
   phone. !important because an inline style outranks everything else. */
.ink-container {
    width: min(580px, 58%) !important;
    max-width: calc(100% - 170px);
}

#drawingOverlay {
    touch-action: none;
}

/* PHONES (short screens): THE FIELD IS THE SCREEN.
 *
 * A phone on its side has 340-390px of height. A 2000:850 field with a stats
 * bar and a tray under it left the field 250px tall and the rabbits eleven
 * pixels high — the thing you draw on was the smallest thing there. So nothing
 * permanent sits under the field but one slim strip, and everything else is
 * either in the picture's corners or pops up over it when it has something to
 * show:
 *
 *   under the field   the map, and four small buttons beside it
 *   top-left          the clock, the day, the count that loses the run
 *   bottom-right      the ITEMS you are holding, as chips — and only those. An
 *                     empty slot is not drawn, so an empty tray is nothing at
 *                     all. Drag a chip onto the field as ever: one gesture.
 *   MIX               opens the recipe box as a pop-up above the chips
 *
 * The scroll arrows go: the map and a two-finger pan do their job, and they
 * were sitting on the two edges of the one thing that matters.
 */
.craft-toggle { display: none; }

/* EVERY SCREEN. This was the touch layout — the field, a strip under it, chips
   that pop up over the picture — against a desktop layout of a stats bar and two
   permanent trays below the field. Mat, looking at the two side by side: "we
   should mimic the desktop layout to the phone one... or iPad more like." So
   there is one layout now, and `(min-height: 561px)` after this block is what
   makes a desktop an iPad rather than a phone: the same arrangement at the sizes
   meant for an arm's length. §64.

   (It asked `(max-height: 560px), (pointer: coarse)` — short OR touch — and the
   mirrored-iPhone bug of §51 was this query answering "no" on a phone-sized
   screen with a mouse. That cannot happen to a query that is always true.) */
@media all {
    /* HOW FAR THE HUD STAYS FROM THE GLASS, on top of the safe area. It was 4px,
       which on a real phone — rounded corners, a Dynamic Island, a thumb — read
       as things jammed into the corners. Everything in the picture's corners and
       the strip under it is set from this one number. */
    .game-container { --pad: 14px; }

    .game-container.is-ready {
        display: grid;
        grid-template-columns: 1fr auto;
        column-gap: 4px;
        align-items: stretch;
    }

    .canvas-container {
        grid-column: 1 / -1;
        box-shadow: 0 0 0 2px #fff;
    }

    .scroll-arrow { display: none; }

    /* --- the strip: the map, and the two sound switches --- */
    .field-map {
        grid-column: 1;
        /* `auto`, not the 100% it has elsewhere: with a left margin to clear
           the notch, 100% + margin overflowed its cell by exactly the margin
           and ran under the buttons beside it. A grid item stretches anyway. */
        width: auto;
        min-width: 0;
        height: 30px;
        margin-top: 6px;
        margin-bottom: 6px;
        border-width: 2px;
    }

    .game-ui {
        grid-column: 2;
        margin-top: 6px;
        margin-bottom: 6px;
        padding: 0;
        border: 0;
        width: auto;
        align-items: stretch;
    }

    /* --- top right: the bin and pause, where a thumb already is ---
       The two you reach for mid-run, out of a strip at the bottom edge where
       they sat under the hand that was drawing. Absolutely placed against
       .game-container (nothing between them and it is positioned); their own
       inline `position: static` is why these need !important. */
    #clearDrawing,
    #pauseGame {
        position: absolute !important;
        top: var(--pad);
        width: 36px !important;
        height: 32px;
        z-index: 61 !important;
        box-shadow: 0 0 0 2px rgba(255, 253, 244, 0.85);
        border-radius: 9px !important;   /* a thumb's buttons, not a toolbar's */
    }
    #pauseGame { right: calc(var(--pad) + env(safe-area-inset-right)); }
    #clearDrawing { right: calc(var(--pad) + 44px + env(safe-area-inset-right)); }

    .controls { gap: 3px; flex-wrap: nowrap; align-items: stretch; }

    /* ICONS, not words. "Clear Drawing  Pause  MUSIC  FX" was 330px of a strip
       whose other occupant is the map; as four squares it is 140, and the map
       gets the rest. The word is still there for a screen reader (font-size 0
       hides it, aria-label names it); the picture comes from data-icon. */
    .controls button[data-icon] {
        width: 32px;
        min-width: 32px !important;
        padding: 0 !important;
        margin: 0 !important;
        font-size: 0 !important;
        background-repeat: no-repeat;
        background-position: center;
        background-size: 17px 17px;
    }

    .controls button[data-icon="clear"] {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23fff' d='M6 1h4v1h4v2H2V2h4zM3 5h10l-1 10H4zm3 2v6h1V7zm3 0v6h1V7z'/%3E%3C/svg%3E");
    }
    .controls button[data-icon="pause"] {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23fff' d='M3 2h4v12H3zm6 0h4v12H9z'/%3E%3C/svg%3E");
    }
    .controls button[data-icon="pause"][data-state="paused"] {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23fff' d='M4 2l10 6-10 6z'/%3E%3C/svg%3E");
    }
    .controls button[data-icon="book"] {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%238BC34A' d='M1 3c2.5-1 4.5-1 6.5.4v10C5.500 12 3.500 12 1 13zm14 0c-2.500-1-4.500-1-6.500.4v10c2-1.400 4-1.400 6.500-.4z'/%3E%3C/svg%3E");
    }
    .controls button[data-icon="music"] {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23fff' d='M6 2h7v3H8v7.5a2.5 2.5 0 1 1-2-2.45z'/%3E%3C/svg%3E");
    }
    .controls button[data-icon="fx"] {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23fff' d='M2 6h3l4-3v10l-4-3H2z'/%3E%3Cpath fill='none' stroke='%23fff' stroke-width='1.5' d='M11 5.5a3.5 3.5 0 0 1 0 5M12.5 3.5a6 6 0 0 1 0 9'/%3E%3C/svg%3E");
    }

    /* --- in the picture --- */
    .stats {
        position: absolute;
        top: calc(var(--pad) + 3px);
        left: 46px;
        z-index: 60;
        gap: 4px;
        font-size: 8px;
        flex-wrap: nowrap;
        pointer-events: none;
        /* STACKED, day over count, beside the dial. Side by side they were
           290px of the top edge, which pushed the ink bar off to the right of
           centre; stacked they are 100, and the bar can sit in the middle. */
        flex-direction: column;
        /* STRETCH: the two bands are one block, the same length as each other
           (the longer one's — "600/600" and a rabbit will not go in "Day: 1")
           and, below, the same thickness: the Day band's. */
        align-items: stretch;
    }
    #day { text-align: center; }
    /* Room for the fullest count from the start, so the pair does not grow a
       character wider the day the field passes a hundred. 1em is one glyph. */
    .hud-rabbit-count { min-width: 7em; text-align: center; }
    #timeElapsed, #rabbitsKilled, #score { display: none; }
    #day, #rabbitCount { padding: 3px 5px; background-color: rgba(0, 0, 0, 0.6); }
    /* In the picture the pill is 7px from the top of the screen: a smaller
       rabbit, and one that mostly sticks out of the BOTTOM of it. */
    #rabbitCount.has-hud-rabbit { gap: 3px; padding-left: 3px; }
    /* ...and under the Day pill now, so it sticks out of the bottom only. The
       margins sum to the rabbit's height less one line of text, which is what
       makes this band exactly as thick as the Day band above it. */
    .hud-rabbit { width: 23px; height: 24px; margin: -3px 0 -13px -1px; }

    /* --- the items, popping up over the bottom-right of the field --- */
    /* A COLUMN along the bottom edge, stacked upward in the order things are
       built: the chips' container at the bottom, the guess above it, an item's
       caption above that (§62). `column-reverse` is what puts the first child
       lowest, so nothing has to be given an order. The tray itself takes no
       pointer events; its children take their own back. */
    .ingredient-tray {
        position: absolute;
        left: 8px;                   /* spans the bottom edge, so "centred" is the screen's centre */
        right: 8px;
        bottom: 44px;                /* clear of the strip */
        z-index: 61;
        width: auto;
        margin: 0;
        padding: 0;
        gap: 4px;
        flex-wrap: nowrap;
        flex-direction: column-reverse;
        justify-content: flex-start;
        align-items: center;
        background: none;
        border: 0;
        pointer-events: none;        /* the gaps between the rows belong to the field */
    }

    /* What you are holding, as one shelf: the chips, and MIX at the RIGHT end
       of them (Mat). Empty slots are not drawn, so it hugs what is in it. */
    .chip-row {
        display: flex;
        align-items: center;
        gap: 5px;
        padding: 5px;
        background: rgba(27, 16, 32, 0.82);
        border: 2px solid #fffdf4;
        box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.4);
        pointer-events: auto;
    }
    /* Nothing held and nothing being mixed: no shelf. Nor while a guess is up —
       it takes the shelf's place rather than standing on it (§67), unless you
       are mixing, where the shelf is how you close the mix. */
    .ingredient-tray:not(.is-crafting):not(:has(.ingredient-slot[data-item])) .chip-row,
    .ingredient-tray.is-guessing:not(.is-crafting) .chip-row { display: none; }

    .ingredient-tray > * { pointer-events: auto; }
    .ingredient-tray-label { display: none; }

    /* The toast ("anvil deployed", "Tray full") hangs 22px under the tray on a
       desktop. Here the tray is a row of chips in a corner with nothing under
       it but the edge of the phone, so the message was two clipped letters.
       It goes to the top of the field, where there is room to read it. */
    .tray-message {
        position: fixed;
        top: calc(var(--pad) + 44px);
        bottom: auto;
        left: 50%;
        width: auto;
        max-width: 70vw;
        transform: translateX(-50%);
        padding: 4px 8px;
        background: rgba(0, 0, 0, 0.72);
        white-space: nowrap;
        pointer-events: none !important;
        z-index: 62;
    }
    .tray-message:empty { display: none; }

    /* An item's line, on the compact layout, is the tray's TOP line: above the
       guess, above the chips (TextOverlayEffect.caption puts it there, §62). At
       7% up the field it was on the prompt; at 52px, once the chips were centred,
       it was between the guess and the chips. Lines are packed upward from the
       chips, so it moves nothing under it, faded out or not. Its inline styles
       are the desktop's, hence the !importants. */
    .ingredient-tray > .item-caption {
        position: static !important;
        transform: none !important;
        max-width: 90% !important;
        pointer-events: none !important;
    }

    /* The recipe book on a phone: the header is one tight row, and the how-to
       is a single scrolling line rather than a third of a 340px page. */
    .recipe-book-header { padding: 6px 12px; gap: 6px 10px; }
    .recipe-book-tabs button, .recipe-book-close { padding: 7px 8px; }
    .recipe-book-list { padding: 8px 12px 16px; }
    .recipe-book-how { margin-bottom: 8px; }

    /* A recipe made for the first time: smaller, and in the middle of the
       screen, where the mix it was made in just was. (It stood right of centre,
       beside the farmer rather than on him; Mat wanted it in the middle, §62.) */
    .discovery-card { top: 50%; left: 50%; width: min(360px, 56%); padding: 10px 14px 12px; border-width: 3px; }
    .discovery-art { width: 74px; height: 74px; margin-bottom: 6px; }
    .discovery-label { margin-bottom: 6px; }
    .discovery-name { margin-bottom: 5px; }

    .ingredient-slot { width: 52px; height: 48px; border-width: 2px; background-color: rgba(10, 10, 10, 0.82); }
    .ingredient-slot:not([data-item]) { display: none; }
    /* A 52x48 chip holds a picture and one short line. That line used to be the
       percentage, and the name was squeezed to nothing behind it; with the
       percentage gone (§53) the name came back as a 4px sliver of clipped text.
       The picture IS the name here, so it gets the room; the only words are how
       big it was drawn, when that is not the usual size. */
    .ingredient-slot .item-name { display: none; }
    .ingredient-slot .item-sprite { width: 32px; height: 32px; }
    .ingredient-slot:has(.item-size) .item-sprite { width: 26px; height: 26px; }

    .craft-toggle {
        display: block;
        height: 48px;
        padding: 0 8px;
        font-family: 'Press Start 2P', cursive;
        font-size: 8px;
        color: #fffdf4;
        background: rgba(27, 16, 32, 0.9);
        border: 2px solid #fffdf4;
        cursor: pointer;
    }

    /* Nothing to mix, nothing to show. Where :has() is missing the rule is
       dropped whole and the button simply stays — harmless. */
    .ingredient-tray:not(.is-crafting):not(:has(.ingredient-slot[data-item])) .craft-toggle { display: none; }

    /* --- crafting, as a pop-up in the middle of the field --- */
    .recipe-box { display: none; }

    /* Open, the tray grows to cover the field (top: 0) so the box can be centred
       in it: in the middle of the screen, and bigger, where it had been hung off
       the chips in the corner at 560px (§62). Centred in the part ABOVE the chip
       row (--chip-row), so CLOSE and the chips are never under it, and never
       taller than that part. The chips do not move — the lines are still packed
       at the bottom — and the tray itself takes no pointer events, so the field
       stays drawable around the box. And the mix is what the player is doing:
       over the farmer and his bubble (the tray's z-index), and over the guess,
       which has an inline z-index of 100 (the box's). */
    .ingredient-tray { --chip-row: 62px; }   /* a chip, plus the shelf's padding and border */
    .ingredient-tray.is-crafting { top: 0; z-index: 67; }

    .ingredient-tray.is-crafting .recipe-box {
        display: flex;
        flex-wrap: wrap;
        position: absolute;
        z-index: 101;
        left: 50%;
        top: calc((100% - var(--chip-row)) / 2);
        transform: translate(-50%, -50%);
        max-height: calc(100% - var(--chip-row) - 6px);
        overflow-y: auto;
        box-sizing: border-box;
        width: min(840px, 96%);
        margin: 0;
        gap: 8px 10px;
        padding: 10px;
        align-items: center;
        /* All but opaque: at 0.94 the farmer's bubble read through it. */
        background: rgba(27, 16, 32, 0.985);
        border: 2px solid #fffdf4;
        box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.45);
    }

    /* The ingredients get a ROW OF THEIR OWN, however many there are. Sharing
       one with the verdict and CRAFT, a fourth ingredient squeezed "Not a
       recipe" into a three-line sliver under the CRAFT button (Mat). */
    .recipe-slot { min-width: 0; min-height: 120px; flex: 1 1 100%; padding: 6px; gap: 10px; flex-wrap: nowrap; justify-content: center; }
    .recipe-slot.is-empty { font-size: 10px; }
    /* FOUR ACROSS, ALWAYS — four is the mix's limit, the longest recipe there
       is. They share the row and shrink to fit rather than wrapping onto a
       second line, which is what made the box taller than the screen on a
       667px phone. */
    .recipe-chip { flex: 1 1 0; min-width: 0; width: auto; max-width: 124px; height: 104px; }
    .recipe-chip .item-sprite { width: 54px; height: 54px; }
    .recipe-chip .item-name { font-size: 9px; max-height: 26px; }
    /* It wraps before CRAFT does: on a small phone CRAFT was pushed onto the
       hint's row, and the box grew taller than the room above the chips. */
    .recipe-result { min-width: 0; flex: 1 1 0; font-size: 13px; line-height: 1.5; text-align: left; }
    .recipe-result:not(.is-match):not(.is-nomatch) { display: none; }
    .craft-button { padding: 30px 24px; font-size: 17px; flex: none; }
    /* On the second row with its clue, so only as tall as a button needs to be:
       at CRAFT's height the two rows did not fit a phone with Safari's bars up. */
    .hint-button { padding: 13px 14px; font-size: 12px; }
    /* The clue is a row of its own, under the buttons. */
    .hint-line { flex: 1 1 100%; align-self: center; font-size: 10px; }

    /* Between the two corners: the dial, the day and the count are top-left,
       the bin and pause top-right. Hung off the RIGHT corner and given whatever
       is left, now that the day/night pill has gone into the dial and is no
       longer standing in the middle of it. 290px is the counts at their widest
       ("Rabbits: 600/600"); 100px is the two buttons. */
    /* CENTRED ON THE SCREEN, not in whatever was left between the corners —
       that was always right of centre, because the left corner is the wider.
       As wide as leaves the wider corner (dial + stacked counts, 150px) clear
       on BOTH sides, so it is symmetrical on a phone with a notch at one end. */
    .ink-container {
        top: var(--pad) !important;
        left: 50% !important;
        right: auto !important;
        transform: translateX(-50%) !important;
        width: calc(100% - 2 * (150px + var(--pad)
            + max(env(safe-area-inset-left), env(safe-area-inset-right)))) !important;
        max-width: none;
        height: 20px !important;
        padding: 2px 5px !important;
    }
    .ink-container > div:first-child { font-size: 9px !important; width: 34px !important; }
    .ink-bar { height: 10px !important; }

    #gameClock {
        transform: scale(0.55);
        transform-origin: top left;
        /* Centred on the two bands beside it, which are its height together. */
        top: calc(var(--pad) + 2px) !important;
        left: calc(var(--pad) + env(safe-area-inset-left)) !important;
    }

    /* EDGE TO EDGE. The picture runs under the notch and the rounded corners,
       as a game's should; only the things you read or touch stay inside the
       safe area. The body's side padding was keeping the whole game inside it,
       which on an iPhone is 59px of black down each side. */
    body { padding-left: 0; padding-right: 0; }
    .stats { left: calc(var(--pad) + 42px + env(safe-area-inset-left)); }
    .ingredient-tray {
        left: calc(var(--pad) + env(safe-area-inset-left));
        right: calc(var(--pad) + env(safe-area-inset-right));
        bottom: 54px;
    }
    .field-map { margin-left: calc(var(--pad) + env(safe-area-inset-left)); }
    .game-ui { margin-right: calc(var(--pad) + env(safe-area-inset-right)); }
    .farmer, .farmer-bubble { margin-left: calc(var(--pad) - 6px + env(safe-area-inset-left)); }

    /* The ending card, clear of the farmer: centred, it sat on the right half
       of what he was saying. Its sizes are inline, hence the !important. */
    .finale-card {
        left: 63% !important;
        top: 50% !important;
        min-width: 0 !important;
        max-width: 56% !important;
        padding: 12px 18px 14px !important;
    }
    .finale-card > div { margin-bottom: 8px !important; }

    /* ALWAYS ALONG THE BOTTOM. The guess is a member of the tray here
       (DrawingInterface.mountGuess), on the line above the chips: at the bottom
       edge with nothing held, one chip's height up with chips, and never higher.
       It used to keep out from under the chips by stepping UP 96px, and 180 over
       the farmer's bubble, which on a 330px field is the middle of the picture,
       where the hand was trying to draw (§62). Its inline styles are the
       desktop's — absolute, 14px up, centred on the frame — hence the
       !importants. */
    .ingredient-tray > .prediction-display {
        position: static !important;
        transform: none !important;
        margin: 0 !important;
        flex: 0 0 auto;
        max-width: none;
        line-height: 1.6;
        white-space: nowrap;
    }
    /* The name sits 10px over the buttons inline; 3 keeps the box a chip and a
       half tall rather than two. */
    .prediction-display > div:first-child { margin-bottom: 3px !important; }
}

/* A PHONE ON ITS SIDE, where the field is 270-330px tall and the mix has to fit
   between the top edge and the shelf of chips. Everything in it is the smallest
   that still reads: at the sizes a tablet gets, the box was half a screen taller
   than the screen and scrolled. Nothing here is rearranged; only the numbers. */
@media (max-height: 420px) {
    .ingredient-tray.is-crafting .recipe-box { padding: 8px; gap: 6px; }
    .recipe-slot { min-height: 92px; padding: 5px; gap: 6px; }
    .recipe-chip { max-width: 108px; height: 78px; }
    .recipe-chip .item-sprite { width: 40px; height: 40px; }
    .recipe-chip .item-name { font-size: 7px; max-height: 20px; }
    .craft-button { padding: 14px 16px; font-size: 13px; }
    .hint-button { padding: 11px 12px; font-size: 11px; }
    .recipe-result { font-size: 11px; }
    .hint-line { font-size: 9px; }
}

/* PORTRAIT ON A PHONE: the field would be 390px wide and 166 tall, and a rabbit
   six pixels high. There is no layout that fixes that, so it says so. An iPad
   in portrait is fine and is left alone. */
.rotate-prompt {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 10001;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 22px;
    padding: 30px;
    text-align: center;
    font-size: 12px;
    line-height: 2;
    color: #fffdf4;
    background: #16301a;
}

.rotate-prompt-phone {
    width: 46px;
    height: 80px;
    border: 4px solid #fffdf4;
    border-radius: 8px;
    animation: rotate-phone 2.4s ease-in-out infinite;
}

@keyframes rotate-phone {
    0%, 25% { transform: rotate(0deg); }
    55%, 100% { transform: rotate(-90deg); }
}

@media (orientation: portrait) and (max-width: 600px), (orientation: portrait) and (pointer: coarse) {
    .rotate-prompt { display: flex; }
}

/* A BIG SCREEN — a tablet, or a desktop window. The same layout as a phone — the
   field, a strip, chips that pop up — at sizes meant for an arm's length rather
   than a palm. Every number here overrides one in the block above; nothing is
   rearranged. It asked for a coarse pointer as well until §64 gave the desktop
   this layout; a tall window is the question now. */
@media (min-height: 561px) {
    .game-container { --pad: 20px; }
    #gameClock { transform: scale(0.95); top: calc(var(--pad) + 13px) !important; }
    .stats { top: calc(var(--pad) + 14px); left: calc(var(--pad) + 78px + env(safe-area-inset-left)); gap: 8px; font-size: 12px; }
    #day, #rabbitCount { padding: 6px 9px; }
    .hud-rabbit { width: 35px; height: 36px; margin: -4px 0 -20px -3px; }
    .stats { top: calc(var(--pad) + 16px) !important; gap: 6px; }
    #clearDrawing, #pauseGame { border-radius: 12px !important; }
    .ink-container {
        height: 30px !important;
        top: calc(var(--pad) + 8px) !important;
        width: calc(100% - 2 * (270px + var(--pad))) !important;
    }
    .ink-container > div:first-child { font-size: 13px !important; width: 52px !important; }
    .ink-bar { height: 16px !important; }
    #clearDrawing, #pauseGame { width: 56px !important; height: 56px !important; background-size: 26px 26px !important; }
    #clearDrawing { right: calc(var(--pad) + 66px + env(safe-area-inset-right)) !important; }
    .controls button[data-icon] { width: 48px; min-width: 48px !important; height: 44px; background-size: 24px 24px; }
    .ingredient-slot { width: 84px; height: 78px; }
    .ingredient-tray { bottom: 74px; gap: 4px 8px; }
    .craft-toggle { height: 78px; padding: 0 14px; font-size: 12px; }
    .ingredient-tray.is-crafting .recipe-box { width: min(1040px, 90%); padding: 22px; gap: 16px; }
    .recipe-chip { max-width: 164px; height: 138px; }
    .recipe-chip .item-sprite { width: 76px; height: 76px; }
    .recipe-chip .item-name { font-size: 12px; max-height: 34px; }
    .recipe-slot { min-height: 164px; gap: 14px; }
    .craft-button { padding: 40px 32px; font-size: 22px; }
    .hint-button { padding: 20px 20px; font-size: 15px; }
    .hint-line { font-size: 14px; }
    .ingredient-tray { --chip-row: 100px; }
    .recipe-result, .recipe-slot.is-empty { font-size: 16px; }
    /* Along the bottom with the chips, as on a phone; the type is a tablet's. */
    .prediction-display { font-size: 14px !important; }
    .farmer { margin-bottom: 3px; }
    .tray-message { top: calc(var(--pad) + 70px); font-size: 12px; padding: 7px 12px; }
    .discovery-card { top: 46%; left: 50%; width: min(460px, 60%); padding: 18px 22px 20px; border-width: 4px; }
    .discovery-art { width: 130px; height: 130px; margin-bottom: 10px; }
}

@media (prefers-reduced-motion: reduce) {
    .rotate-prompt-phone { animation: none; transform: rotate(-90deg); }
}


/* The prompt under the field is given 14px inline, which on a phone is a banner
   across a third of it. */
.prediction-display {
    font-size: clamp(8px, 1.25vw, 14px) !important;
    padding: clamp(5px, 0.8vw, 10px) !important;
    max-width: 62%;
}

/* ONE LINE, ALWAYS. The buttons carry an inline 14px and a min-width, and the
   box had a max-width: on a phone the three did not fit, so "Tap to / add" and
   "Guess / Again" each broke in two and the box doubled in height. The type
   scales with the screen instead and nothing in here may wrap; the padding is
   what keeps a one-line button a thumb's height. */
.prediction-display button {
    font-size: clamp(9px, 1.7vw, 14px) !important;
    min-width: 0 !important;
    white-space: nowrap;
    padding: clamp(10px, 1.5vw, 12px) clamp(10px, 1.6vw, 14px) !important;
}

/* Its text is a span with its own inline 14px, so sizing the parent alone
   changed nothing. */
.prediction-display span,
.prediction-display div {
    font-size: inherit !important;
}

/* NARROW BUT TALL: an iPad held upright, or a small window. Five numbers and
   four buttons do not fit 800px, and the buttons were the ones pushed off the
   edge. Time is already on the clock and the score is not the record (the
   ending card is), so those two go, and the bar may wrap. */
@media (max-width: 1000px) and (min-height: 561px) {
    #timeElapsed, #score { display: none; }
    .game-ui { flex-wrap: wrap; gap: 8px; align-items: center; }
    .controls { flex-wrap: wrap; }
    .controls button { font-size: 10px !important; padding: 8px !important; }
}


/* --- The books: leaderboard and sign-in --- */

.scoreboard {
    position: fixed;
    inset: 0;
    z-index: 10002;               /* over the briefing (10000) and the rotate prompt's neighbours */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: max(12px, env(safe-area-inset-top)) max(12px, env(safe-area-inset-right))
             max(12px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left));
    background: rgba(8, 6, 10, 0.72);
}

.scoreboard-panel {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: min(620px, 100%);
    max-height: 100%;
    padding: clamp(12px, 2.4vh, 24px) clamp(12px, 2vw, 26px);
    color: #fffdf4;
    background: rgba(27, 16, 32, 0.97);
    border: 4px solid #fffdf4;
    box-shadow: 8px 8px 0 rgba(0, 0, 0, 0.5);
}

.scoreboard-title {
    font-size: clamp(13px, 1.7vw, 20px);
    font-weight: normal;
    color: #ffd166;
    text-align: center;
}

.scoreboard-where,
.scoreboard-hint,
.scoreboard-note {
    font-size: clamp(7px, 0.85vw, 10px);
    line-height: 1.8;
    color: #cfc6d6;
    text-align: center;
}

.scoreboard-note { color: #9be28f; }
.scoreboard-note.is-bad { color: #ff8a8a; }

.scoreboard-list {
    list-style: none;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    flex: 1 1 auto;
    min-height: 60px;
    border-top: 2px solid rgba(255, 253, 244, 0.25);
    border-bottom: 2px solid rgba(255, 253, 244, 0.25);
}

.scoreboard-row {
    display: grid;
    grid-template-columns: 3.2em 1fr auto 5.5em;
    gap: 8px;
    align-items: center;
    padding: 7px 4px;
    font-size: clamp(8px, 0.95vw, 12px);
}

.scoreboard-row:nth-child(odd) { background: rgba(255, 253, 244, 0.05); }
.scoreboard-row.is-mine { color: #1b1020; background: #ffd166; }
.scoreboard-rank { color: inherit; opacity: 0.7; }
.scoreboard-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* SCORE / DAY: the score is the headline, the day is what it was earned over. */
.scoreboard-score { text-align: right; font-size: 1.25em; }
.scoreboard-when { text-align: right; opacity: 0.75; }
.scoreboard-empty { padding: 18px 6px; font-size: clamp(8px, 0.95vw, 12px); text-align: center; color: #cfc6d6; }

.scoreboard-account { display: flex; flex-direction: column; gap: 8px; align-items: center; }
.scoreboard-signin { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.scoreboard-email { display: flex; gap: 6px; }

.scoreboard-email input {
    font-family: 'Press Start 2P', cursive;
    font-size: clamp(8px, 0.9vw, 11px);
    width: min(230px, 52vw);
    padding: 9px;
    color: #fffdf4;
    background: #0b0f0c;
    border: 3px solid #fffdf4;
    -webkit-user-select: text;
    user-select: text;
}

.scoreboard-button,
.scoreboard-close {
    font-family: 'Press Start 2P', cursive;
    font-size: clamp(8px, 0.9vw, 11px);
    padding: 9px 12px;
    color: #fffdf4;
    background: transparent;
    border: 3px solid #fffdf4;
    cursor: pointer;
}

.scoreboard-button:disabled { opacity: 0.5; }

.scoreboard-close {
    align-self: center;
    color: #1b1020;
    background: #ffd166;
    padding: 11px 26px;
    font-size: clamp(10px, 1.1vw, 14px);
}

/* A phone in Safari is 340px tall and the logo is part of the painting: two rows
   of buttons must not climb up over it any further than one did. */
@media (max-height: 400px) {
    .briefing { gap: 5px; padding-bottom: 6px; }
    .briefing-actions { gap: 6px 10px; }
    .briefing-play { padding: 6px 34px !important; }
    .briefing-scores { padding: 6px 12px !important; }
    .briefing-install { padding: 3px 8px; }
}

@media (max-height: 520px) {
    /* Its own row now, so it needs its own height: beside PLAY it was stretched
       to PLAY's, and `padding: 0` was fine. */
    .briefing-scores { border-width: 3px; font-size: 9px; padding: 9px 12px; }
    .scoreboard-panel { gap: 6px; padding: 8px 12px; }
    .scoreboard-row { padding: 4px; }
    .scoreboard-close { padding: 8px 20px; }
}
