/* Game surfaces: dice, dice-count stepper, spinner, coin, score cards. */
/* ============ Dice ============ */
.dice-tray {
    display: flex; justify-content: center; align-items: center;
    gap: clamp(10px, 2vw, 24px);
    flex-wrap: wrap; margin: 8px 0 clamp(12px, calc(2.4 * var(--vh)), 30px);
    min-height: 0;
}
.die {
    appearance: none; font-family: inherit;
    position: relative;
    /* Height matters as much as width here: five dice sized only against the
       viewport width are far too tall on a short laptop screen. */
    width: clamp(56px, min(13vw, calc(19 * var(--vh))), 132px);
    aspect-ratio: 1;
    border-radius: 22px;
    background: var(--die-face);
    border: 3px solid var(--dice);
    color: var(--die-pip);
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    display: grid; place-items: center;
    transition: transform .3s cubic-bezier(.34,1.56,.64,1), box-shadow .3s ease, background .25s ease, border-color .25s ease, color .25s ease;
}
.die.interactive:hover { transform: translateY(-6px); box-shadow: var(--shadow-lg); }
.die.static { cursor: default; }
.die .pips {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);
    width: 66%; height: 66%;
    gap: 8%;
}
.die .pips i {
    border-radius: 50%;
    background: currentColor;
    width: 100%; aspect-ratio: 1;
    align-self: center; justify-self: center;
    visibility: hidden;
    box-shadow: inset 0 -2px 3px rgba(0,0,0,0.14);
}
.die .pips i.on { visibility: visible; }
.die.held {
    background: linear-gradient(140deg, var(--hold), #63c193);
    border-color: transparent; color: #ffffff;
    transform: translateY(-4px) scale(1.03);
    box-shadow: 0 18px 40px rgba(70, 168, 118, 0.42);
}
.die.held .pips i { box-shadow: inset 0 -2px 3px rgba(0,0,0,0.22); }
.die .lock {
    position: absolute; top: -14px; right: -14px;
    width: 44px; height: 44px; border-radius: 50%;
    background: var(--die-face); color: var(--hold);
    display: none; place-items: center;
    border: 3px solid var(--hold); box-shadow: var(--shadow-sm);
}
.die.held .lock { display: grid; }
.die .lock .ico { width: 22px; height: 22px; }
/* Pig's losing face: the one roll the game is about. */
.die.bust {
    border-color: var(--coral); color: var(--coral);
    animation: bustShake .5s ease;
}
@keyframes bustShake {
    0%, 100% { transform: translateX(0); }
    20% { transform: translateX(-9px) rotate(-4deg); }
    45% { transform: translateX(8px) rotate(3deg); }
    70% { transform: translateX(-5px) rotate(-2deg); }
}
.die.rolling { animation: roll .55s cubic-bezier(.34,1.56,.64,1); }
/* The moment it stops: a squash and a settle. A die that simply ceases to
   spin has no weight — this is what makes it read as having hit the table. */
.die.landed { animation: dieLand .26s cubic-bezier(.3,1.6,.5,1); }
@keyframes dieLand {
    0% { transform: scale(1.16) rotate(-4deg); }
    45% { transform: scale(.93, 1.07); }
    100% { transform: scale(1) rotate(0); }
}
@keyframes roll {
    0%,100% { transform: rotate(0) scale(1); }
    30% { transform: rotate(120deg) scale(1.14); }
    60% { transform: rotate(250deg) scale(1.16); }
}

/* Dice count stepper */
.count-row {
    display: flex; align-items: center; justify-content: center; gap: 10px;
    flex-wrap: wrap; margin: 4px 0 clamp(6px, calc(1.6 * var(--vh)), 28px);
    flex-shrink: 0;
}
.count-label { font-weight: 800; color: var(--ink-dim); font-size: 15px; margin-right: 6px; }
.count-btn {
    appearance: none; font-family: 'Fredoka', sans-serif;
    width: clamp(44px, calc(7.5 * var(--vh)), 60px); height: clamp(44px, calc(7.5 * var(--vh)), 60px); border-radius: 18px;
    border: 1.5px solid var(--line-strong); background: var(--surface-2);
    color: var(--ink); font-size: clamp(20px, calc(3.4 * var(--vh)), 26px); font-weight: 600; cursor: pointer;
    transition: transform .2s ease, border-color .2s ease, background .2s ease, color .2s ease, box-shadow .2s ease;
}
.count-btn:hover { transform: translateY(-2px); border-color: var(--primary-ink); }
.count-btn[aria-pressed="true"] {
    background: linear-gradient(135deg, var(--primary), var(--primary-strong));
    color: #fff; border-color: transparent;
}

/* ============ Spinner ============ */
.spinner-stage {
    display: flex; flex-direction: column; align-items: center;
    gap: clamp(8px, calc(1.8 * var(--vh)), 24px);
    margin: 6px 0 clamp(10px, calc(2 * var(--vh)), 28px);
    min-height: 0; overflow: hidden;
    container-type: size;
}
/* The wheel is capped as a fraction of the stage, not of the viewport, so the
   result box and the legend below it always keep their rows. */
.spinner-wrap {
    position: relative; flex-shrink: 1; min-height: 0;
    width: min(420px, 78vw, 46cqh); aspect-ratio: 1;
    display: grid; place-items: center;
    container-type: size;
}
.spinner-result { flex-shrink: 0; }
.spinner-pointer {
    position: absolute; top: -6px; left: 50%; transform: translateX(-50%);
    width: 0; height: 0; z-index: 3;
    border-left: 20px solid transparent; border-right: 20px solid transparent;
    border-top: 40px solid var(--accent);
    filter: drop-shadow(0 8px 10px rgba(21,44,61,.3));
}
.spinner-wheel {
    width: 100%; height: 100%; border-radius: 50%;
    border: 8px solid var(--surface);
    box-shadow: var(--shadow-md), 0 0 0 1px var(--line-strong);
    position: relative; overflow: hidden;
    background: conic-gradient(var(--primary), var(--accent));
}
.spinner-wheel::after {
    content: ''; position: absolute; inset: 30%; border-radius: 50%;
    background: radial-gradient(circle at 32% 30%, color-mix(in srgb, var(--surface-2) 60%, #fff), var(--surface-2) 72%);
    border: 5px solid var(--surface);
    box-shadow: var(--shadow-sm);
}
.spinner-center {
    position: absolute; z-index: 2; text-align: center; width: 40%;
    font-family: 'Fredoka', sans-serif; font-weight: 700;
    font-size: min(18px, 9cqh); overflow: hidden;
    color: var(--ink); line-height: 1.1;
}
.spinner-labels { position: absolute; inset: 0; border-radius: 50%; }
.spinner-label {
    position: absolute; left: 50%; top: 50%;
    width: clamp(64px, 22%, 110px); text-align: center;
    font-weight: 800; font-size: min(16px, 8cqh); color: #fff;
    text-shadow: 0 2px 6px rgba(0,0,0,.55);
    pointer-events: none; line-height: 1.1;
}
.spinner-result {
    background: var(--surface-2); border: 2px solid var(--result-color, var(--line-strong));
    border-radius: 16px; padding: min(16px, 4cqh) 26px; min-width: min(360px, 100%);
    flex-shrink: 0; text-align: center; box-shadow: var(--shadow-sm);
    transition: border-color .3s ease;
}
.spinner-result-label { display: block; color: var(--ink-dim); font-size: 14px; }
@container (max-height: 260px) { .spinner-result-label { display: none; } }
.spinner-result-label { font-size: 14px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; margin-bottom: 6px; }
.spinner-result-value { font-family: 'Fredoka', sans-serif; font-size: min(clamp(20px, 5vw, 40px), 13cqh); font-weight: 700; line-height: 1.05; }
.spinner-legend {
    display: flex; flex-wrap: wrap; justify-content: center; align-content: start;
    gap: 10px; width: 100%;
}
/* The wheel yields before the legend does: a legend clipped to nothing leaves
   crowded spinners with no way to read their slices. One chip row is the floor
   here, not the taller default a paged region gets — the legend is a reference
   strip, not the main event. */
.screen.active .spinner-legend[data-fit-pages] { min-height: 46px; }
body.is-tight .spinner-stage { gap: 6px; margin-bottom: 6px; }
body.is-tight .spinner-wrap { width: min(420px, 78vw, 40cqh); }
body.is-tight .screen.active .spinner-legend[data-fit-pages] { min-height: 40px; }
body.is-tight .legend-item { padding: 4px 10px; }
body.is-tight .spinner-result { padding: 6px 16px; }
body.is-tighter .spinner-wrap { width: min(420px, 78vw, 34cqh); }
body.is-tighter .spinner-stage { gap: 4px; margin: 2px 0 4px; }
body.is-tighter .count-btn { width: 44px; height: 44px; font-size: 19px; }
body.is-tighter .die { width: clamp(44px, min(13vw, calc(13 * var(--vh))), 96px); }
body.is-tighter .sk-card { padding: 6px 10px; }
/* Past ~10 slices the labels overlap into noise; the legend names them instead. */
.spinner-labels.is-crowded { display: none; }
.legend-item {
    display: inline-flex; align-items: center; gap: 8px;
    background: var(--surface-2); border: 1px solid var(--line);
    border-radius: var(--radius-pill); padding: 8px 14px;
}
.legend-swatch { width: 18px; height: 18px; border-radius: 50%; border: 2px solid rgba(255,255,255,.7); flex-shrink: 0; box-shadow: var(--shadow-sm); }
.legend-text { font-weight: 800; font-size: 15px; color: var(--ink); }

/* Coin flip */
.coin-stage {
    display: grid; place-items: center; min-height: 0;
    margin: 6px 0 clamp(8px, calc(2 * var(--vh)), 24px); perspective: 900px;
    /* The coin's back face is rotated 180deg in 3D, which projects outside the
       stage and would otherwise register as overflow. */
    overflow: hidden;
    container-type: size;
}
.coin {
    position: relative; width: min(clamp(96px, 30vw, 230px), 92cqh); aspect-ratio: 1;
    transform-style: preserve-3d;
    /* Its own container so the face text scales with the coin. Text that keeps
       its viewport-derived size while the coin shrinks overflows the face — and
       an absolutely-positioned face passes that overflow up to the stage. */
    container-type: size;
}
.coin-face {
    position: absolute; inset: 0; border-radius: 50%;
    display: grid; place-items: center; padding: min(16px, 8cqh); text-align: center;
    backface-visibility: hidden; -webkit-backface-visibility: hidden;
    font-family: 'Fredoka', sans-serif; font-weight: 700;
    font-size: min(clamp(15px, 4.2vw, 34px), 17cqh); line-height: 1.1;
    border: 6px solid rgba(0, 0, 0, 0.18); box-shadow: var(--shadow-md);
    overflow: hidden; overflow-wrap: anywhere;
}
.coin-face.front { background: linear-gradient(135deg, var(--accent), #f7c667); color: #4a3200; }
.coin-face.back { background: linear-gradient(135deg, var(--primary), var(--primary-strong)); color: #fff; transform: rotateY(180deg); }
.coin-result-wrap { display: grid; justify-items: center; margin-bottom: 24px; }
/* Themed rather than literal, so the result stays readable on the dark and
   high-contrast palettes as well as the light ones. */
.spinner-result-value.is-side-1 { color: var(--accent); }
.spinner-result-value.is-side-2 { color: var(--primary-ink); }

/* Score keeper.
   The grid is a size container so the cards scale against the space they were
   actually given, not against the viewport. Sizing to the viewport is what made
   a card taller than its own box — at which point paging cannot help, because
   even one card per page does not fit. */
.sk-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    grid-auto-rows: min-content; align-content: start;
    gap: 14px; margin: 6px 0 clamp(10px, calc(2 * var(--vh)), 26px);
    container-type: size;
}
.sk-card {
    background: var(--surface-2); border: 1px solid var(--line);
    border-top: 5px solid var(--sk-color, var(--primary));
    border-radius: 16px; padding: clamp(8px, 4cqh, 18px) 16px;
    display: flex; flex-direction: column; align-items: center; gap: clamp(4px, 3cqh, 10px);
    min-height: 0;
}
.sk-name { font-weight: 800; font-size: 16.5px; color: var(--ink); }
.sk-score {
    font-family: 'Fredoka', sans-serif; font-weight: 700; line-height: 1;
    font-size: clamp(26px, min(7vw, 32cqh), 68px); color: var(--sk-color, var(--primary));
}
.sk-btns { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }

/* Short box: lay the card out along the row instead of down the column. The
   +/- buttons have a hard 44px floor (they are the touch target), so stacking
   them under a score numeral is what pushed the card past its own container. */
@container (max-height: 220px) {
    .sk-card {
        flex-direction: row; flex-wrap: wrap;
        justify-content: center; align-items: center;
        gap: 10px 14px;
    }
    .sk-score { font-size: clamp(24px, 46cqh, 44px); }
}
.sk-plus {
    appearance: none; font-family: 'Fredoka', sans-serif;
    background: var(--sk-color, var(--primary)); color: #fff;
    border: none; border-radius: 14px; padding: clamp(6px, 3cqh, 14px) clamp(18px, 6cqw, 30px);
    font-size: clamp(20px, 14cqh, 26px); font-weight: 600; cursor: pointer; min-height: clamp(44px, 22cqh, 60px);
    box-shadow: var(--shadow-sm);
    transition: transform .2s ease, filter .2s ease;
}
.sk-plus:hover { transform: translateY(-2px); filter: brightness(1.06); }
.sk-minus {
    appearance: none; font-family: 'Nunito', sans-serif;
    width: clamp(44px, 22cqh, 50px); height: clamp(44px, 22cqh, 50px); border-radius: 12px;
    flex-shrink: 0;
    border: 1.5px solid var(--line-strong); background: var(--surface);
    font-size: 19px; font-weight: 800; cursor: pointer; color: var(--ink-dim);
}
.sk-minus:hover { border-color: var(--primary-ink); color: var(--ink); }
.sk-card.is-leader { border-color: var(--sk-color, var(--primary)); }
/* A word, not a crown emoji: it says the same thing at a legible size, in the
   theme's own colours, on every platform. */
.sk-card.is-leader .sk-name::after {
    content: 'Leading';
    margin-left: 8px; padding: 2px 9px; border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--accent) 20%, transparent);
    color: var(--accent); font-size: 11px; font-weight: 800;
    letter-spacing: .07em; text-transform: uppercase;
}
.sk-plus:disabled { opacity: .4; cursor: not-allowed; transform: none; }
.sk-card.winner { border-color: var(--sk-color, var(--primary)); animation: winnerPulse 0.9s ease-in-out 3; }
@keyframes winnerPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } }
body.big-targets .sk-plus { padding: min(20px, 6cqh) 40px; font-size: min(30px, 18cqh); }
body.big-targets .sk-minus { width: min(64px, 30cqh); height: min(64px, 30cqh); }
body.big-targets.is-tighter .sk-plus { padding: 6px 20px; font-size: 20px; min-height: 44px; }
body.big-targets.is-tighter .sk-minus { width: 44px; height: 44px; }

/* ============ Yahtzee scorecard ============ */
.yz-totals {
    display: flex; flex-wrap: wrap; gap: 8px;
    justify-content: center; margin-bottom: 18px;
}
.yz-chooser {
    margin: 4px 0 clamp(8px, calc(1.6 * var(--vh)), 22px);
    display: flex; flex-direction: column; gap: 8px;
}
.yz-chooser[hidden] { display: none !important; }
.yz-chooser-help {
    text-align: center; color: var(--ink-dim);
    font-weight: 700; font-size: 15px; margin-bottom: clamp(4px, calc(1 * var(--vh)), 14px);
    flex-shrink: 0;
}
.score-picks {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    grid-auto-rows: min-content;
    gap: 10px; align-content: start;
}
.score-pick {
    appearance: none; font-family: 'Nunito', sans-serif;
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    border: 1.5px solid var(--line-strong); background: var(--surface-2);
    color: var(--ink); border-radius: 14px;
    padding: 16px 20px; min-height: 64px; cursor: pointer;
    transition: transform .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.score-pick:hover { transform: translateY(-2px); border-color: var(--primary-ink); background: color-mix(in srgb, var(--primary) 12%, var(--surface-2)); }
.score-pick-name { font-weight: 800; font-size: 16px; text-align: left; }
.score-pick-pts {
    font-family: 'Fredoka', sans-serif; font-weight: 600; font-size: 26px;
    color: var(--primary-ink); min-width: 46px; text-align: right;
}
.score-pick.is-zero { opacity: 0.72; }
.score-pick.is-zero .score-pick-pts { color: var(--ink-dim); }
/* The highest-scoring open box, flagged rather than sorted-and-hoped-for. */
.score-pick.is-best {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 34%, transparent);
}
.score-pick-name { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.score-pick-flag {
    background: var(--accent); color: #4a3200;
    border-radius: var(--radius-pill); padding: 2px 10px;
    font-size: 14px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
}

.yz-card-wrap { margin-top: 8px; }
.yz-card-toggle {
    appearance: none; cursor: pointer; user-select: none;
    display: inline-flex; align-items: center; gap: 8px;
    font-family: 'Fredoka', sans-serif; font-weight: 600; font-size: 17px;
    color: var(--primary-ink);
    border: 1.5px solid var(--line-strong); border-radius: var(--radius-pill);
    padding: 10px 20px; min-height: 48px; background: var(--surface-2);
}
.yz-card-toggle:hover { border-color: var(--primary-ink); }
.yz-card-toggle::after { content: '\25BE'; transition: transform .18s ease; }
.yz-card-toggle[aria-expanded="false"]::after { transform: rotate(-90deg); }
.yz-card-scroll { overflow-x: auto; margin-top: 14px; }
.yz-card { width: 100%; border-collapse: collapse; font-size: 15px; }
.yz-card th, .yz-card td {
    border: 1px solid var(--line); padding: 8px 12px; text-align: center;
}
.yz-card th[scope="row"] { text-align: left; font-weight: 700; color: var(--ink-dim); white-space: nowrap; }
.yz-card thead th { font-weight: 800; background: var(--surface-2); }
.yz-card .is-turn { background: color-mix(in srgb, var(--primary) 12%, transparent); }
.yz-card .is-open { color: var(--ink-dim); }
.yz-card .yz-subtotal td, .yz-card .yz-subtotal th { background: var(--surface-2); font-weight: 800; }
.yz-card .yz-grand td, .yz-card .yz-grand th {
    background: color-mix(in srgb, var(--primary) 14%, transparent);
    font-family: 'Fredoka', sans-serif; font-weight: 600; font-size: 18px;
}
.yz-bonus { color: var(--mint); font-weight: 800; font-size: 14px; }

/* ============ Pig ============ */
.pig-turn-total { font-weight: 800; font-size: 14.5px; color: var(--ink-dim); }
.sk-card.is-turn { border-color: var(--sk-color, var(--primary)); box-shadow: var(--shadow-md); }

/* ============ Cause & effect: Fireworks ============ */
.ce-stage {
    position: relative; display: grid; place-items: center;
    min-height: 0; min-width: 0;
    margin: 6px 0 clamp(10px, calc(2 * var(--vh)), 24px); overflow: hidden;
    container-type: size;
}
.ce-button {
    appearance: none; font-family: 'Fredoka', sans-serif;
    position: relative; z-index: 2;
    width: min(460px, 88%); height: min(300px, 96cqh); min-height: 88px;
    border: none; border-radius: 34px;
    background: linear-gradient(140deg, var(--primary), var(--accent));
    color: #fff; cursor: pointer;
    display: grid; place-items: center; gap: 6px;
    box-shadow: var(--shadow-lg);
    transition: transform .16s cubic-bezier(.34,1.56,.64,1), filter .16s ease;
}
.ce-button:hover { transform: translateY(-4px); filter: saturate(1.08); }
.ce-button:active { transform: scale(.97); }
.ce-button.scan-current { border-radius: 34px; }
.ce-button-emoji { display: block; font-size: clamp(28px, min(12vw, 34cqh), 92px); line-height: 1; }
.ce-button-emoji .ico { width: 1.2em; height: 1.2em; }
.ce-button-text { font-size: clamp(18px, min(5vw, 15cqh), 40px); font-weight: 600; text-shadow: 0 3px 10px rgba(0,0,0,.28); }

#ce-count.is-milestone { animation: winnerPulse .5s ease-in-out 2; }
/* The glyph particles that used to live here are gone: Fireworks draws real
   rockets on the shared canvas now (js/core/fx.js). The calm ring stays — for
   a player learning cause and effect the feedback IS the activity, so it is
   never removed, only made still. */
.ce-calm {
    position: absolute; left: 50%; top: 50%; z-index: 3;
    width: 62%; aspect-ratio: 1; transform: translate(-50%, -50%);
    border: 10px solid var(--accent); border-radius: 50%;
    pointer-events: none; opacity: .8;
}
.count-btn.wide { width: 76px; }

/* ============ This or That ============ */
.choice-grid {
    display: grid; gap: clamp(18px, 4vw, 40px);
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: 1fr; min-height: 0;
    margin: 10px 0 clamp(8px, calc(1.8 * var(--vh)), 22px);
    container-type: size;
}
.choice-grid[data-count="3"] { grid-template-columns: repeat(3, 1fr); }
.choice-grid[data-count="4"] { grid-template-columns: repeat(2, 1fr); }
.choice-card {
    appearance: none; font-family: 'Fredoka', sans-serif;
    min-height: 0;
    border: 5px solid transparent; border-radius: 26px;
    background: var(--choice-color, var(--primary));
    color: #fff; cursor: pointer;
    display: grid; place-items: center; padding: 20px;
    box-shadow: var(--shadow-lg);
    transition: transform .22s cubic-bezier(.34,1.56,.64,1), filter .2s ease;
}
.choice-card:hover { transform: translateY(-6px); filter: saturate(1.08); }
.choice-card.scan-current { border-radius: 26px; }
.choice-card-text {
    font-size: clamp(20px, min(5.5vw, 22cqh), 46px); font-weight: 600;
    text-align: center; overflow-wrap: anywhere;
    text-shadow: 0 3px 12px rgba(0,0,0,.32);
}
.choice-card.is-picked { transform: scale(1.04); border-color: var(--ink); }
.tc-result { margin: 0 auto 22px; max-width: min(520px, 100%); }
.tc-help { text-align: center; color: var(--ink-dim); font-weight: 600; font-size: 14px; }

@media (max-width: 640px) {
    .choice-grid, .choice-grid[data-count="3"], .choice-grid[data-count="4"] { grid-template-columns: 1fr; }
}
