:root {
    --bg1: #1c5c30;
    --bg2: #17492a;
    --card: #ffffff;
    --ink: #1f3a24;
    --accent: #4e7cff;
    --accent-dark: #2c56d8;
    --good: #58b043;
    --pill: rgba(255, 255, 255, 0.16);
}
* {
    box-sizing: border-box;
    -webkit-tap-highlight-color: transparent;
}
html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
}
body {
    height: 100vh;
    height: 100dvh;
    display: flex;
    flex-direction: column;
    font-family: ui-rounded, "SF Pro Rounded", "Segoe UI", system-ui, sans-serif;
    background: radial-gradient(120% 120% at 50% 0%, var(--bg1), var(--bg2));
    color: #fff;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    touch-action: manipulation;
}
#hdr {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px 6px;
    padding-top: calc(10px + env(safe-area-inset-top));
    padding-left: calc(14px + env(safe-area-inset-left));
    padding-right: calc(14px + env(safe-area-inset-right));
}
.pill {
    background: var(--pill);
    border-radius: 999px;
    padding: 8px 14px;
    font-size: 17px;
    font-weight: 700;
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 72px;
    justify-content: center;
}
/* Four 46px buttons and the padding take 240px of a 320px phone, so the run
   pills are what give way — never a button (measure the bar before you add). */
/* R-C19: a number the player WATCHES CHANGE gets tabular figures. Measured on
   word-search: the clock pill swings between 51.3px and 66.3px as it counts,
   and the pill beside it slides 8px sideways — every second, and again at
   0:09 -> 0:10. Crossword found this, fixed its own clock, and wrote the
   reason into its own stylesheet, where the other four games could not read
   it. Fourth time a lesson has been recorded only where it was learned. */
#runInfo { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px;
           overflow: hidden; font-variant-numeric: tabular-nums; }

/* ...except "give way" turned out to mean "get sliced in half". Measured on a
   375px viewport: three pills are 232px of content in 185px of space, and the
   pause button takes another 46 the moment a run starts. The third pill was
   simply cut off by the overflow:hidden above — invisible rather than
   compressed, and invisible in RUMBLE too, since v2.0.
   Coil's kill count is that third pill, so the old answer stopped being one.
   Nothing shrinks: below 480px the pills take a row of their own, which is the
   only arrangement where three of them and four 44px targets both survive. */
@media (max-width: 480px) {
    #hdr { flex-wrap: wrap; row-gap: 6px; }
    #runInfo {
        order: 2;                 /* after every button, so it wraps as a unit */
        flex: 1 1 100%;
        justify-content: center;
        overflow: visible;
    }
    /* On one row #runInfo was the spacer holding these apart. On two it is
       gone from between them, and without this they bunch up on the left. */
    #hdrMute { margin-left: auto; }
}
.howBody { text-align: left; font-size: 15px; line-height: 1.5; }
.howBody p { margin: 0 0 9px; }
.iconBtn {
    background: var(--pill);
    border: none;
    color: #fff;
    border-radius: 999px;
    /* flex: none, or four buttons and three pills shrink each other below the
       44px floor at 320px — the buttons were measuring 43px wide. */
    flex: 0 0 auto;
    width: 46px;
    height: 46px;
    font-size: 20px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.08s;
}
.iconBtn:active { transform: scale(0.9); }
#stage {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-bottom: env(safe-area-inset-bottom);
    touch-action: none;
}
#game {
    border-radius: 14px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.35);
}
.overlay {
    position: absolute;
    inset: 0;
    display: flex;
    /* NOT align-items: center. A centred flex item taller than its container
       overflows at BOTH ends, so the top of the card goes up out of reach and
       no amount of scrolling brings it back — the failure the catalog's status
       overlay shipped, in a different game.
       Measured at 375x620 with Coil selected: a 715px card in a 465px stage,
       top at -14, and the Play button entirely off screen. The menu was the
       one screen you could not get past.
       flex-start plus a scroll region: short cards still look centred, because
       margin:auto only centres what fits. */
    align-items: flex-start;
    justify-content: center;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* Contained here, so reaching the end of a long card does not chain out to
       the document behind it (R-C15). */
    overscroll-behavior: contain;
    background: rgba(10, 30, 16, 0.55);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    z-index: 5;
    padding: 16px;
}
.overlay.hidden { display: none; }
.card {
    background: var(--card);
    color: var(--ink);
    border-radius: 24px;
    padding: 26px 26px 22px;
    width: min(340px, 92%);
    /* Centres the card when it fits and pins it to the top when it does not —
       which is the half `align-items: center` gets right and the half it gets
       catastrophically wrong.
       `align-items: safe center` was tried in v2.5 as a more direct way to say
       this, on the strength of a measurement showing 128px of dead space above
       the card. The measurement was wrong: `.card` runs a `pop` animation that
       starts at scale(0.85), and getBoundingClientRect returns the TRANSFORMED
       box, so every height read during those 250 ms came back 15% short and
       the missing 15% looked like padding. There was no dead space, and the
       card is 852px rather than the 724 the rect claimed. */
    margin: auto;
    flex: 0 0 auto;
    text-align: center;
    box-shadow: 0 16px 50px rgba(0, 0, 0, 0.35);
    animation: pop 0.25s ease-out;
}
@keyframes pop {
    from { transform: scale(0.85); opacity: 0; }
    to { transform: scale(1); opacity: 1; }
}
.card .big { font-size: 56px; line-height: 1; }
.card h1 {
    margin: 8px 0 4px;
    font-size: 30px;
    font-weight: 800;
}
.card .hint {
    margin: 4px 0 16px;
    font-size: 15px;
    color: #5a7561;
    font-weight: 600;
}
/* The mode switch. A segmented control rather than two chips, because the two
   modes are not two settings of one thing -- picking one changes what the rest
   of the card is even asking. */
.seg {
    display: flex;
    background: #eef2ee;
    border-radius: 16px;
    padding: 4px;
    gap: 4px;
    margin: 6px 0 10px;
}
.segBtn {
    /* flex-basis 0 with min-width 0, so three unequal labels get three EQUAL
       thirds. On `flex: 1` alone the basis is auto and "Classic" claims more
       room than "Coil" — fine for two, visibly lopsided for three. */
    flex: 1 1 0;
    min-width: 0;
    border: none;
    background: transparent;
    color: #5a7561;
    border-radius: 12px;
    /* 44px is the floor a thumb needs, and it is a floor rather than a
       coincidence of the font size — the icon moved onto its own line when the
       third mode landed, and padding alone would have been read as decorative
       and tuned away. */
    min-height: 44px;
    padding: 7px 2px;
    font-size: 14px;
    line-height: 1.25;
    font-weight: 800;
    font-family: inherit;
    cursor: pointer;
    transition: transform 0.08s;
}
.segBtn:active { transform: scale(0.96); }
.segBtn.selected {
    background: var(--good);
    color: #fff;
    box-shadow: 0 2px 8px rgba(88, 176, 67, 0.4);
}
/* A one-rule switch (R29). Deliberately NOT `.chips` — the mode, tier and
   format rows are three-way picks between peers, and a two-state setting
   wearing their clothes reads as a fourth choice of the same weight. It is
   also 47px shorter than the chip row it replaced, on the tallest card in the
   game. Full width and 48px tall, so the target is bigger than a chip's
   despite the row being smaller. */
.toggle {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    min-height: 48px;
    padding: 6px 12px;
    margin: 0 0 12px;
    border: 3px solid #dbe7dd;
    background: #f4f8f5;
    color: var(--ink);
    border-radius: 16px;
    font: 800 15px/1.2 inherit;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: transform 0.08s;
}
.toggle .tgText { flex: 1 1 auto; min-width: 0; }
.toggle .tgState {
    flex: 0 0 auto;
    border-radius: 999px;
    padding: 5px 13px;
    background: #dbe7dd;
    color: #5a7561;
    font-size: 13px;
    font-weight: 800;
}
.toggle:active { transform: scale(0.97); }
.toggle.on { border-color: var(--good); background: #e9f7e4; }
.toggle.on .tgState { background: var(--good); color: #fff; }

.blurb {
    margin: 0 0 14px;
    font-size: 13px;
    line-height: 1.4;
    color: #5a7561;
    font-weight: 600;
    min-height: 1em;
}
.blurb:empty { margin: 0; min-height: 0; }
.chips {
    display: flex;
    gap: 8px;
    justify-content: center;
    margin-bottom: 18px;
}
.chip {
    flex: 1;
    border: 3px solid #dbe7dd;
    background: #f4f8f5;
    color: var(--ink);
    border-radius: 16px;
    padding: 10px 4px;
    font-size: 15px;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    transition: transform 0.08s;
}
.chip:active { transform: scale(0.94); }
.chip.selected {
    border-color: var(--good);
    background: #e9f7e4;
}
.btn {
    display: block;
    width: 100%;
    border: none;
    border-radius: 18px;
    padding: 15px;
    margin-top: 10px;
    font-size: 19px;
    font-weight: 800;
    font-family: inherit;
    cursor: pointer;
    background: #eef2ee;
    color: var(--ink);
    transition: transform 0.08s;
}
.btn:active { transform: scale(0.96); }
.btn.primary {
    background: linear-gradient(180deg, #6ec258, var(--good));
    color: #fff;
    box-shadow: 0 5px 0 #3d8a2c;
}
.btn.primary:active {
    box-shadow: 0 2px 0 #3d8a2c;
    transform: translateY(3px) scale(0.98);
}
.banner {
    background: linear-gradient(90deg, #ffd166, #ffb703);
    color: #6b4b00;
    font-weight: 800;
    border-radius: 12px;
    padding: 8px;
    margin-bottom: 10px;
    font-size: 17px;
    animation: wiggle 0.6s ease-in-out infinite alternate;
}
@keyframes wiggle {
    from { transform: rotate(-1.5deg) scale(1); }
    to { transform: rotate(1.5deg) scale(1.04); }
}
.banner.hidden { display: none; }
/* Rumble's over-screen carries three figures rather than two, so the gap has
   to survive the third without wrapping on a 320px-wide phone. */
.stats {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 8px 18px;
    font-size: 21px;
    margin: 10px 0 14px;
}
/* Boost (R12a). It shares the footer with the version chip rather than
   floating over the board, because the whole stage is the swipe surface and a
   button on top of it is a rectangle where steering stops working.

   It costs the board NOTHING in height. version.js already gives #footer a
   44px chip (R-C11's hit-area floor) and a 44px ::before counterweight, so the
   row is 44px tall whether or not this button is in it — which is what makes
   the ::before double as this button's left margin and leaves it centred.

   flex: 0 1 auto with a max-width, so on a 320px phone it gives way before it
   pushes the chip off the end; min-height is the floor and does not. */
#btnBoost {
    -webkit-appearance: none;
    appearance: none;
    flex: 0 1 auto;
    max-width: 60%;
    min-height: 44px;
    padding: 0 22px;
    border: none;
    border-radius: 999px;
    font: 800 16px/1 inherit;
    font-family: inherit;
    color: #6b4b00;
    background: linear-gradient(180deg, #ffd166, #ffb703);
    box-shadow: 0 3px 0 #b8860b;
    cursor: pointer;
    white-space: nowrap;
    /* A HELD control. Without this, a press-and-hold on the button is a
       long-press gesture to the OS: text selection, a callout menu, and on
       iOS a pointercancel that leaves the snake boosting with nothing held. */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    transition: transform 0.06s, box-shadow 0.06s;
}
/* `.on` is set from world.boosting(), not from the pointer — so at the floor
   (R30f) the button visibly stops firing rather than looking held and doing
   nothing. That is the difference between "I have run out" and "it is
   broken". */
#btnBoost.on {
    background: linear-gradient(180deg, #ff9f1c, #ff7b00);
    color: #fff;
    box-shadow: 0 1px 0 #b8860b;
    transform: translateY(2px);
}

.hidden { display: none !important; }
