:root {
    --bg: #12161c;
    --panel: #1a212a;
    --panel-edge: #273140;
    --ink: #e8edf3;
    --ink-muted: #8fa0b3;
    --accent: #4a9d6f;
    --accent-ink: #ffffff;
    --danger: #e06060;
    --radius: 10px;
}

* { box-sizing: border-box; }

/* The one lever that sizes the whole app.
   Every length in this file is in rem, and rem resolves against the root
   element — so this scales text, cards, panels, gaps and tap targets together,
   in proportion, rather than leaving a big-text layout sitting in small boxes.
   A percentage rather than a pixel value on purpose: it multiplies whatever the
   reader has set as their browser font size instead of overriding it. */
html { font-size: 115%; }

body {
    margin: 0;
    padding: 2rem 1.25rem 4rem;
    background: var(--bg);
    color: var(--ink);
    font-family: "Segoe UI", system-ui, -apple-system, sans-serif;

    /* Must stay relative. A px value here would pin every inherited size back
       to 16px and only the rem-sized boxes would grow. */
    font-size: 1rem;
    line-height: 1.55;
}

h1 { font-size: 1.6rem; margin: 0 0 .35rem; font-weight: 600; }
h2 { font-size: 1rem; margin: 0 0 .9rem; font-weight: 600; color: var(--ink-muted);
     text-transform: uppercase; letter-spacing: .07em; }

.muted { color: var(--ink-muted); margin: 0 0 1rem; }
.hint  { color: var(--ink-muted); font-size: .85rem; margin: .75rem 0 0; max-width: 46ch; }
.error { color: var(--danger); margin: .6rem 0 0; font-size: .9rem; }

/* ---- lobby ---- */

.lobby { max-width: 27rem; margin: 12vh auto 0; text-align: center; }
.lobby h1 { font-size: 2.2rem; }
.tagline { color: var(--ink-muted); margin: 0 0 2.5rem; }
.lobby-actions { display: flex; flex-direction: column; gap: 2rem; }

.join-box { display: flex; flex-direction: column; gap: .5rem; }
.join-box label { color: var(--ink-muted); font-size: .9rem; }
.join-row { display: flex; flex-wrap: wrap; gap: .6rem; justify-content: center; margin-top: .4rem; }

.code-input {
    width: 7.5rem;
    text-align: center;
    font-size: 1.4rem;
    letter-spacing: .35em;
    text-indent: .35em;
    text-transform: uppercase;
}

/* ---- panels ---- */

.panel {
    max-width: 34rem;
    margin: 0 auto 1.25rem;
    padding: 1.5rem;
    background: var(--panel);
    border: 1px solid var(--panel-edge);
    border-radius: var(--radius);
}

.table-view { max-width: 34rem; margin: 0 auto; }

.table-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.table-header .muted { margin: 0; font-size: .9rem; }
.you { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: .35rem; }
.you-name { font-weight: 600; }

/* Flex rather than text-align: when the host is confirming, the footer holds a
   warning and two buttons and they have to wrap tidily on a phone. */
.table-footer {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: .6rem;
    margin-top: 1.5rem;
}

/* ---- seats ---- */

.seat-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .1rem; }

.seat {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .55rem .25rem;
    border-bottom: 1px solid var(--panel-edge);
}

.seat:last-child { border-bottom: none; }
.seat-name { font-weight: 500; }
.seat.offline { opacity: .45; }

.dot { width: .5rem; height: .5rem; border-radius: 50%; background: var(--accent); flex: none; }
.seat.offline .dot { background: var(--ink-muted); }

.tag {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-muted);
}

.badge {
    margin-left: auto;
    font-size: .72rem;
    padding: .18rem .5rem;
    border-radius: 999px;
    text-transform: uppercase;
    letter-spacing: .05em;
}

.badge-player    { background: rgba(74, 157, 111, .18); color: #7fd3a3; }
.badge-spectator { background: rgba(143, 160, 179, .15); color: var(--ink-muted); }
.you .badge { margin-left: 0; }

/* ---- controls ---- */

input[type="text"], .text-input, .code-input {
    padding: .6rem .75rem;
    background: #0e1218;
    color: var(--ink);
    border: 1px solid var(--panel-edge);
    border-radius: var(--radius);
    font: inherit;
    outline: none;
}

.text-input { width: 100%; margin-bottom: 1rem; }

input:focus { border-color: var(--accent); }

.btn {
    display: inline-block;
    padding: .6rem 1.1rem;
    background: #232d39;
    color: var(--ink);
    border: 1px solid var(--panel-edge);
    border-radius: var(--radius);
    font: inherit;
    text-decoration: none;
    cursor: pointer;
}

.btn:hover:not(:disabled) { border-color: var(--ink-muted); }
.btn:disabled { opacity: .4; cursor: not-allowed; }

.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.btn-primary:hover:not(:disabled) { filter: brightness(1.1); }

.btn-quiet { background: none; border-color: transparent; color: var(--ink-muted); }
.btn-quiet:hover { color: var(--ink); }

.toggle { display: flex; align-items: center; gap: .6rem; cursor: pointer; }
.toggle input { width: 1.05rem; height: 1.05rem; accent-color: var(--accent); cursor: pointer; }

/* ---- framework bits ---- */

#blazor-error-ui {
    display: none;
    position: fixed;
    inset: auto 0 0 0;
    z-index: 1000;
    padding: .8rem 1.25rem;
    background: #ffefc2;
    color: #3d2f00;
    box-shadow: 0 -1px 12px rgba(0, 0, 0, .3);
}

#blazor-error-ui .dismiss { float: right; cursor: pointer; }

.blazor-error-boundary { padding: 1rem; background: #b32121; color: #fff; border-radius: var(--radius); }
.blazor-error-boundary::after { content: "An error has occurred."; }

/* ---- table code + copy ---- */

.code-block { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.code-label { color: var(--ink-muted); font-size: .8rem; text-transform: uppercase; letter-spacing: .07em; }

.code-chip {
    font: inherit;
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: .22em;
    text-indent: .22em;
    padding: .25rem .7rem;
    color: var(--ink);
    background: #0e1218;
    border: 1px dashed var(--panel-edge);
    border-radius: var(--radius);
    cursor: pointer;
}

.code-chip:hover { border-color: var(--accent); border-style: solid; }

.btn-sm { padding: .3rem .65rem; font-size: .85rem; }

.copy-note {
    font-size: .85rem;
    color: var(--accent);
    opacity: 0;
    transition: opacity .15s ease;
}

.copy-note.shown { opacity: 1; }

/* ---- cards ---- */

.card {
    position: relative;
    width: 4.5rem;
    height: 6.6rem;
    border-radius: .55rem;
    border: 2px solid rgba(255, 255, 255, .85);
    box-shadow: 0 2px 6px rgba(0, 0, 0, .45);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    user-select: none;
    flex: none;

    /* The buttons wrapping a card zero out line-height to kill the inline gap
       underneath it. Reset it here so the corner number keeps a real line box —
       inheriting 0 collapses it to zero height and clips the glyph. */
    line-height: 1;
}

.card-sm { width: 2.6rem; height: 3.8rem; border-width: 1.5px; border-radius: .35rem; }

.card-face {
    position: relative;
    font-size: 2rem;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 2px 3px rgba(0, 0, 0, .45);
    line-height: 1;
}

.card-sm .card-face { font-size: 1.05rem; }

.card-corner {
    position: absolute;
    top: .2rem;
    left: .35rem;
    font-size: .8rem;
    font-weight: 700;
    color: rgba(255, 255, 255, .9);
}

.card-sm .card-corner { display: none; }

/* Art sits over the colour, so a custom design keeps its card's identity. */
.card-art {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
}

.card-red    { background: #d33a2c; }
.card-yellow { background: #d9a520; }
.card-green  { background: #3f9d48; }
.card-blue   { background: #2f6fc4; }

.card-wild {
    background:
        conic-gradient(#d33a2c 0deg 90deg, #d9a520 90deg 180deg,
                       #3f9d48 180deg 270deg, #2f6fc4 270deg 360deg);
}

.card-back {
    background: repeating-linear-gradient(45deg, #1d2530 0 6px, #232d3a 6px 12px);
    border-color: rgba(255, 255, 255, .35);
}

.card-back-mark {
    width: 60%;
    height: 34%;
    border-radius: 50%;
    background: rgba(255, 255, 255, .1);
    border: 1.5px solid rgba(255, 255, 255, .22);
}

.card-button {
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
    transition: transform .1s ease;
    line-height: 0;
}

.card-button:hover { transform: translateY(-.5rem); }

/* ---- play area ---- */

.piles { display: flex; gap: 2rem; justify-content: center; margin-bottom: 1.75rem; }
.pile { display: flex; flex-direction: column; align-items: center; gap: .5rem; }
.pile-label { font-size: .78rem; color: var(--ink-muted); }

.pile-button { padding: 0; background: none; border: none; cursor: pointer; line-height: 0; }
.pile-button:disabled { cursor: default; }
.pile-button:hover:not(:disabled) .card { border-color: var(--accent); }

.opponents { display: flex; flex-direction: column; gap: 1.1rem; }
.opponent.offline { opacity: .45; }
.opponent-head { display: flex; align-items: center; gap: .5rem; margin-bottom: .4rem; }
.count { margin-left: auto; font-size: .8rem; color: var(--ink-muted); }

/* Overlapping backs, so a big hand still fits on one row. */
.fan { display: flex; }
.fan > * { margin-right: -1.35rem; }
.fan > *:last-child { margin-right: 0; }

.hand { display: flex; flex-wrap: wrap; gap: .5rem; padding-top: .5rem; }

.join-row.left { justify-content: flex-start; margin: 0 0 1.25rem; }

/* ---- turn state ---- */

.panel-active { border-color: var(--accent); box-shadow: 0 0 0 1px rgba(74, 157, 111, .25); }
.turn-you { color: var(--accent) !important; }

.turn-facts { display: flex; gap: .5rem; flex-wrap: wrap; }

.chip {
    font-size: .78rem;
    padding: .25rem .6rem;
    border-radius: 999px;
    background: #232d39;
    border: 1px solid var(--panel-edge);
    color: var(--ink-muted);
}

.chip-red    { background: rgba(211, 58, 44, .22);  border-color: #d33a2c; color: #f0a49c; }
.chip-yellow { background: rgba(217, 165, 32, .22); border-color: #d9a520; color: #f0d492; }
.chip-green  { background: rgba(63, 157, 72, .22);  border-color: #3f9d48; color: #9fd8a5; }
.chip-blue   { background: rgba(47, 111, 196, .22); border-color: #2f6fc4; color: #a3c2ef; }

.turn-actions { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.1rem; }

/* Side by side in a narrow column these split their labels mid-phrase.
   fit-content keeps each on one line down to the point where the line genuinely
   does not fit, and then lets it wrap rather than run off the screen. */
.turn-actions .btn,
.join-row .btn { min-width: fit-content; }

.notice { margin: .9rem 0 0; color: #f0c274; font-size: .9rem; }

.banner-win { border-color: var(--accent); text-align: center; }
.banner-win h1 { margin-bottom: 1rem; }

.opponent.their-turn .seat-name { color: var(--accent); }
.opponent.their-turn .dot { box-shadow: 0 0 0 3px rgba(74, 157, 111, .3); }

.uno-flag {
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .08em;
    padding: .12rem .4rem;
    border-radius: 4px;
    background: #d9a520;
    color: #2a2000;
}

/* ---- playability ---- */

.card-button.blocked { cursor: not-allowed; }
.card-button.blocked .card { opacity: .35; filter: grayscale(.6); }
.card-button.blocked:hover { transform: none; }
.card-button.playable .card { box-shadow: 0 0 0 2px var(--accent), 0 2px 6px rgba(0, 0, 0, .45); }

/* ---- wild colour picker ---- */

.color-picker { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; margin-bottom: 1.1rem; }

.color-swatch {
    font: inherit;
    font-size: .85rem;
    padding: .45rem .9rem;
    border-radius: var(--radius);
    cursor: pointer;
    color: var(--ink);
}

.color-swatch:hover { filter: brightness(1.35); }

/* ---- action log ---- */

.log { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .35rem; }
.log li { font-size: .88rem; color: var(--ink-muted); }
.log li strong { color: var(--ink); font-weight: 600; }
.log li:first-child { color: var(--ink); }

/* ---- final standings ---- */

.standings { margin: 0 0 1.25rem; padding-left: 1.4rem; text-align: left; display: inline-block; }
.standings li { padding: .2rem 0; }
.standings li::marker { color: var(--ink-muted); }
.standings li:first-child { font-weight: 700; color: var(--accent); }
.standings li.last { color: var(--ink-muted); list-style: none; margin-left: -1.4rem; padding-top: .5rem; }

/* ---- game picker ---- */

.game-list { display: flex; flex-direction: column; gap: .6rem; }

.game-option {
    display: flex;
    flex-direction: column;
    gap: .2rem;
    width: 100%;
    padding: .85rem 1rem;
    text-align: left;
    font: inherit;
    color: var(--ink);
    background: #1f2732;
    border: 1px solid var(--panel-edge);
    border-radius: var(--radius);
    cursor: pointer;
}

.game-option:hover:not(:disabled) { border-color: var(--ink-muted); }
.game-option:disabled { cursor: default; }

.game-option.picked {
    border-color: var(--accent);
    background: rgba(74, 157, 111, .12);
}

/* Your own vote. Distinct from .picked, which is what the table has settled on —
   they are usually the same button, and it matters when they are not. */
.game-option.voted { border-color: var(--ink-muted); }
.game-option.voted.picked { border-color: var(--accent); }

/* Not built yet: readable, clearly not choosable. */
.game-option.soon { opacity: .5; }

.vote-count {
    min-width: 1.5rem;
    padding: .05rem .35rem;
    background: var(--accent);
    color: var(--accent-ink);
    border-radius: 999px;
    font-size: .75rem;
    font-weight: 700;
    text-align: center;
}

.vote-row { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; margin-top: .9rem; }

.vote-tally { font-size: .85rem; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.vote-tally.live { color: var(--danger); font-weight: 600; }

/* The host's leave button asks first, because it ends everyone's evening. */
.leave-warn { font-size: .85rem; color: #f0a0a0; align-self: center; }

.game-name { display: flex; align-items: center; gap: .5rem; font-weight: 600; }
.game-tagline { font-size: .88rem; color: var(--ink-muted); }
.game-players { font-size: .78rem; color: var(--ink-muted); }

.soon-flag {
    font-size: .65rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    padding: .12rem .4rem;
    border-radius: 4px;
    background: #2f3947;
    color: var(--ink-muted);
}

/* ---- No Mercy ---- */

/* "+10", "⊘ ALL" and friends need to fit where a single digit used to. */
.card-face.long { font-size: 1.15rem; letter-spacing: -.02em; }
.card-sm .card-face.long { font-size: .7rem; }

.chip-danger {
    background: rgba(224, 96, 96, .2);
    border-color: var(--danger);
    color: #f0a0a0;
    font-weight: 700;
}

.btn-danger { background: #7d2b2b; border-color: #a33c3c; color: #fff; }
.btn-danger:hover:not(:disabled) { filter: brightness(1.15); }

.verdict { margin: .35rem 0; color: var(--ink-muted); }
.verdict strong { color: var(--ink); }
.verdict.lost strong { color: #f0a0a0; }

/* ---- Exploding Kittens ---- */

.kcard {
    position: relative;
    width: 4.6rem;
    height: 6.6rem;
    border-radius: .55rem;
    border: 2px solid rgba(255, 255, 255, .8);
    box-shadow: 0 2px 6px rgba(0, 0, 0, .45);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .25rem;
    padding: .3rem .18rem;
    overflow: hidden;
    user-select: none;
    line-height: 1;
    flex: none;
    background: #384252;
}

.kcard-sm { width: 2.7rem; height: 3.9rem; border-width: 1.5px; border-radius: .35rem; }

.kcard-symbol { font-size: 1.75rem; }
.kcard-sm .kcard-symbol { font-size: 1rem; }

/* Sized so the longest name on a card — CATTERMELON — still fits inside it
   rather than being sliced off at the border. */
.kcard-name {
    font-size: .53rem;
    font-weight: 600;
    text-align: center;
    color: rgba(255, 255, 255, .92);
    text-transform: uppercase;
    letter-spacing: 0;
}

.kcard-sm .kcard-name { display: none; }

.kcard-art { position: absolute; inset: 0; background-size: cover; background-position: center; }

.kcard.selected { outline: 3px solid var(--accent); outline-offset: 1px; }

.kc-boom    { background: #8c2020; }
.kc-defuse  { background: #2f7d55; }
.kc-nope    { background: #6d2f6d; }
.kc-attack  { background: #a34a1e; }
.kc-skip    { background: #2f5f9e; }
.kc-favor   { background: #7a5c1e; }
.kc-shuffle { background: #3a5a6e; }
.kc-future  { background: #4a3a8c; }
.kc-cat     { background: #46525f; }

.kcard-back {
    background: repeating-linear-gradient(-45deg, #1d2530 0 6px, #232d3a 6px 12px);
    border-color: rgba(255, 255, 255, .3);
}

.kcard-mark {
    width: 55%;
    height: 30%;
    border-radius: 40%;
    background: rgba(255, 255, 255, .09);
    border: 1.5px solid rgba(255, 255, 255, .2);
}

.peek {
    margin: 0 0 1.1rem;
    padding: .75rem;
    border: 1px dashed var(--panel-edge);
    border-radius: var(--radius);
    background: rgba(74, 58, 140, .12);
}

.peek-label {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--ink-muted);
}

.kcard-empty {
    background: none;
    border-style: dashed;
    border-color: var(--panel-edge);
    box-shadow: none;
}

/* ---- rules panel ---- */

.rules-toggle {
    display: flex;
    align-items: center;
    gap: .55rem;
    width: 100%;
    padding: 0;
    font: inherit;
    font-weight: 600;
    color: var(--ink);
    background: none;
    border: none;
    cursor: pointer;
    text-align: left;
}

.rules-toggle:hover { color: var(--accent); }
.rules-caret { color: var(--ink-muted); font-size: .8rem; }
.rules-hint { margin-left: auto; font-size: .78rem; font-weight: 400; color: var(--ink-muted); }

.rules { margin-top: 1.25rem; }

.rules h3 {
    font-size: .78rem;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--ink-muted);
    margin: 1.5rem 0 .6rem;
}

.rules-goal {
    margin: 0;
    padding: .7rem .9rem;
    border-left: 3px solid var(--accent);
    background: rgba(74, 157, 111, .1);
    border-radius: 0 var(--radius) var(--radius) 0;
}

.rules-steps { margin: 0; padding-left: 1.3rem; display: flex; flex-direction: column; gap: .4rem; }
.rules-steps li { color: var(--ink); }
.rules-steps li::marker { color: var(--ink-muted); }

.rules-cards { margin: 0; display: flex; flex-direction: column; gap: .55rem; }

.rules-card {
    display: grid;
    grid-template-columns: 5.5rem 1fr;
    gap: .2rem .8rem;
    align-items: baseline;
    padding-bottom: .55rem;
    border-bottom: 1px solid var(--panel-edge);
}

.rules-card:last-child { border-bottom: none; padding-bottom: 0; }

.rules-card dt { display: flex; flex-direction: column; gap: .1rem; }
.rules-card dd { margin: 0; color: var(--ink-muted); font-size: .9rem; }

.rules-label {
    font-weight: 700;
    font-size: .95rem;
    color: var(--ink);
    word-break: break-word;
}

.rules-name { font-size: .72rem; color: var(--ink-muted); }

.rules-house { margin: 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: .4rem; }
.rules-house li { color: var(--ink-muted); font-size: .9rem; }
.rules-house li::marker { color: #f0c274; }

@media (max-width: 30rem) {
    .rules-card { grid-template-columns: 1fr; }
}

/* ---- Skyjo ---- */

.sjcard {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.9rem;
    height: 4rem;
    border-radius: .4rem;
    border: 2px solid rgba(255, 255, 255, .8);
    box-shadow: 0 2px 5px rgba(0, 0, 0, .4);
    font-size: 1.25rem;
    font-weight: 700;
    color: #fff;
    line-height: 1;
    user-select: none;
}

.sj-negative { background: #2f7d55; }
.sj-zero     { background: #3f6b8c; }
.sj-low      { background: #4a6fae; }
.sj-mid      { background: #b07d1e; }
.sj-high     { background: #a83c3c; }

.sj-back {
    background: repeating-linear-gradient(45deg, #1d2530 0 5px, #232d3a 5px 10px);
    border-color: rgba(255, 255, 255, .3);
}

.sj-mark {
    width: 55%;
    height: 30%;
    border-radius: 40%;
    background: rgba(255, 255, 255, .08);
    border: 1.5px solid rgba(255, 255, 255, .18);
}

.sj-empty {
    background: none;
    border-style: dashed;
    border-color: var(--panel-edge);
    box-shadow: none;
}

.sjcard.held { box-shadow: 0 0 0 3px var(--accent), 0 2px 5px rgba(0, 0, 0, .4); }

.sj-grid {
    display: grid;
    grid-template-columns: repeat(4, max-content);
    gap: .35rem;
}

.sj-slot { padding: 0; background: none; border: none; line-height: 0; cursor: default; }
.sj-slot.clickable { cursor: pointer; }
.sj-slot.clickable:hover .sjcard { outline: 2px solid var(--accent); outline-offset: 1px; }

.sj-others { display: flex; flex-wrap: wrap; gap: 1.4rem; }
.sj-other { display: flex; flex-direction: column; gap: .45rem; }
.sj-other.their-turn .seat-name { color: var(--accent); }
.sj-other .opponent-head { margin: 0; }
.sj-other .count { margin-left: .6rem; }

/* ---- scoreboard ---- */

.scoreboard { width: 100%; border-collapse: collapse; margin: 1rem 0; text-align: left; }
.scoreboard th {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--ink-muted);
    font-weight: 600;
    padding: .3rem .5rem;
    border-bottom: 1px solid var(--panel-edge);
}
.scoreboard td { padding: .4rem .5rem; border-bottom: 1px solid var(--panel-edge); }
.scoreboard tr:last-child td { border-bottom: none; }
.scoreboard tr.best td { color: var(--accent); font-weight: 700; }

/* ---- Flip 7 ---- */

.f7card {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.4rem;
    height: 3.2rem;
    padding: 0 .35rem;
    border-radius: .4rem;
    border: 2px solid rgba(255, 255, 255, .8);
    box-shadow: 0 2px 5px rgba(0, 0, 0, .4);
    font-size: 1.1rem;
    font-weight: 700;
    color: #fff;
    line-height: 1;
    user-select: none;
}

.f7-zero   { background: #3f6b8c; }
.f7-low    { background: #4a6fae; }
.f7-mid    { background: #b07d1e; }
.f7-high   { background: #a83c3c; }
.f7-bonus  { background: #2f7d55; }
.f7-action { background: #5b3f8c; }

.f7-row { display: flex; flex-wrap: wrap; gap: .35rem; align-items: center; min-height: 3.2rem; }
.f7-row.busted .f7card { opacity: .35; filter: grayscale(.7); }

.f7-others { display: flex; flex-direction: column; gap: 1.1rem; }
.f7-other.done { opacity: .6; }
.f7-other.their-turn .seat-name { color: var(--accent); }
.f7-other .opponent-head { margin-bottom: .4rem; }
.f7-other .count { margin-left: auto; }

/* ---- Phase 10 ---- */

.p10card {
    position: relative;
    width: 3.4rem;
    height: 4.9rem;
    border-radius: .5rem;
    border: 2px solid rgba(255, 255, 255, .82);
    box-shadow: 0 2px 5px rgba(0, 0, 0, .4);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-weight: 700;
    font-size: 1.5rem;
    text-shadow: 0 2px 3px rgba(0, 0, 0, .45);
    user-select: none;
    flex: none;
    line-height: 1;
}

.p10-small { width: 2.3rem; height: 3.3rem; font-size: 1rem; border-width: 1.5px; border-radius: .35rem; }

.p10-red    { background: #d33a2c; }
.p10-blue   { background: #2f6fc4; }
.p10-green  { background: #3f9d48; }
.p10-yellow { background: #d9a520; }
.p10-wild   { background: linear-gradient(135deg, #7d4bbf 0%, #b0479b 100%); }
.p10-skip   { background: #4a4f57; }

.p10-back {
    background: repeating-linear-gradient(45deg, #2b3a4a 0 6px, #35485c 6px 12px);
    border-color: rgba(255, 255, 255, .35);
}

.p10-mark {
    width: 55%;
    height: 55%;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, .3);
}

.p10-empty {
    background: none;
    border-style: dashed;
    border-color: var(--panel-edge);
}

.p10-corner {
    position: absolute;
    top: .15rem;
    left: .3rem;
    font-size: .72rem;
    font-weight: 700;
    color: rgba(255, 255, 255, .9);
    text-shadow: none;
}

.p10-face { font-size: inherit; }

/* ---- your hand ---- */

.p10-cardbutton {
    padding: 0;
    background: none;
    border: none;
    line-height: 0;
    cursor: pointer;
    border-radius: .5rem;
    transition: transform .09s ease;
}

.p10-cardbutton:disabled { cursor: default; }
.p10-cardbutton:not(:disabled):hover { transform: translateY(-3px); }

.p10-cardbutton.picked { transform: translateY(-8px); }
.p10-cardbutton.picked .p10card { box-shadow: 0 0 0 3px var(--accent), 0 4px 8px rgba(0, 0, 0, .5); }

.p10-hand { gap: .4rem; padding-top: .9rem; align-items: flex-end; min-height: 6rem; }

/* ---- what is on the table ---- */

.p10-melds { display: flex; flex-direction: column; gap: 1.1rem; }
.p10-meldgroup { display: flex; flex-direction: column; gap: .5rem; }

.p10-meld {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    padding: .45rem .6rem;
    border: 1px solid var(--panel-edge);
    border-radius: .5rem;
}

.p10-meldlabel {
    font-size: .78rem;
    color: var(--ink-muted);
    min-width: 8.5rem;
}

.p10-row { display: flex; gap: .25rem; flex-wrap: wrap; }

.p10-hit { min-width: 2rem; font-weight: 700; }

/* ---- your phase, and the ladder ---- */

.p10-goal { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin: .6rem 0 0; }

.chip-phase { background: rgba(125, 75, 191, .25); border-color: #7d4bbf; color: #cbaef0; }
.chip-done  { background: rgba(63, 157, 72, .2); border-color: #3f9d48; color: #9fd8a5; }

.p10-ready { color: var(--accent); }

.p10-ladder summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--ink-muted);
}

.p10-phases { margin: .9rem 0 0; padding-left: 1.6rem; display: flex; flex-direction: column; gap: .3rem; }
.p10-phases li { color: var(--ink-muted); font-size: .9rem; }
.p10-phases li.current { color: var(--accent); font-weight: 700; }

/* ---- Selfish ---- */

.sfcard {
    position: relative;
    width: 3.4rem;
    height: 4.9rem;
    border-radius: .5rem;
    border: 2px solid rgba(255, 255, 255, .8);
    box-shadow: 0 2px 5px rgba(0, 0, 0, .45);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-weight: 700;
    font-size: 1.45rem;
    user-select: none;
    flex: none;
    line-height: 1;
}

.sf-oxy    { background: linear-gradient(160deg, #1f7a8c 0%, #2aa5bd 100%); }
.sf-oxy2   { background: linear-gradient(160deg, #12626f 0%, #2fc2dd 100%); }
.sf-attack { background: linear-gradient(160deg, #7a2436 0%, #b2374f 100%); }
.sf-guard  { background: linear-gradient(160deg, #3d5a8c 0%, #5a83c4 100%); }
.sf-boost  { background: linear-gradient(160deg, #6d4899 0%, #9a6bd1 100%); }

.sf-corner {
    position: absolute;
    top: .18rem;
    left: .3rem;
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: .04em;
    color: rgba(255, 255, 255, .85);
}

.sf-face { font-size: inherit; }

.sf-cardbutton {
    padding: 0;
    background: none;
    border: none;
    line-height: 0;
    cursor: pointer;
    border-radius: .5rem;
    transition: transform .09s ease;
}

.sf-cardbutton:disabled { cursor: default; opacity: .55; }
.sf-cardbutton:not(:disabled):hover { transform: translateY(-3px); }
.sf-cardbutton.picked { transform: translateY(-8px); }
.sf-cardbutton.picked .sfcard { box-shadow: 0 0 0 3px var(--accent), 0 4px 8px rgba(0, 0, 0, .5); }
.sf-cardbutton.aiming .sfcard { box-shadow: 0 0 0 3px #e2603f, 0 4px 8px rgba(0, 0, 0, .5); }

.sf-hand { gap: .4rem; padding-top: .9rem; align-items: flex-end; min-height: 6rem; }

/* ---- the run ---- */

.sf-tracks { display: flex; flex-direction: column; gap: 1rem; }
.sf-lane { display: flex; flex-direction: column; gap: .4rem; }
.sf-lane.yours .seat-name { color: var(--accent); }
.sf-lane.their-turn .dot { background: var(--accent); }

.sf-who { display: flex; align-items: center; gap: .5rem; font-size: .85rem; }
.sf-who .count { margin-left: auto; color: var(--ink-muted); font-size: .78rem; }

.sf-track { display: flex; gap: .3rem; overflow-x: auto; padding-bottom: .2rem; }

.sf-cell {
    position: relative;
    width: 3rem;
    height: 3rem;
    flex: none;
    border: 1px dashed var(--panel-edge);
    border-radius: .45rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.sf-cell.here { border-style: solid; border-color: var(--accent); background: rgba(255, 255, 255, .04); }
.sf-ship { border-style: solid; font-size: 1.4rem; }

.sf-astro { position: relative; font-size: 1.3rem; z-index: 1; }

.sf-litter {
    position: absolute;
    inset: .2rem;
    border-radius: .3rem;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .95rem;
    opacity: .8;
}

.sp-empty { background: rgba(255, 255, 255, .06); }
.sp-good  { background: rgba(63, 157, 72, .3); }
.sp-bad   { background: rgba(168, 60, 60, .35); }
.sp-odd   { background: rgba(125, 75, 191, .32); }

.chip-air { background: rgba(42, 165, 189, .22); border-color: #2aa5bd; color: #9fdce8; }

.sf-lost { margin-top: .9rem; font-size: .85rem; }
.sf-warn { color: #f0c274; }

.sf-ref summary { cursor: pointer; font-weight: 600; color: var(--ink-muted); }
.sf-reflist { list-style: none; margin: .9rem 0 0; padding: 0; display: flex; flex-direction: column; gap: .45rem; }
.sf-reflist li { display: flex; align-items: center; gap: .6rem; font-size: .85rem; color: var(--ink-muted); }
.sf-reflist .sf-litter { position: static; inset: auto; width: 1.7rem; height: 1.7rem; flex: none; }

/* ---- Taco vs Burrito ---- */

.tvbcard {
    position: relative;
    width: 3.6rem;
    height: 5rem;
    border-radius: .5rem;
    border: 2px solid rgba(255, 255, 255, .8);
    box-shadow: 0 2px 5px rgba(0, 0, 0, .45);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .15rem;
    color: #fff;
    font-weight: 700;
    user-select: none;
    flex: none;
    line-height: 1;
    padding: .2rem;
    text-align: center;
}

.tvb-face { font-size: 1.35rem; }

.tvb-name {
    font-size: .5rem;
    font-weight: 600;
    letter-spacing: .01em;
    opacity: .9;
    line-height: 1.15;
    overflow: hidden;
}

.tvb-small { width: 2.4rem; height: 3.3rem; }
.tvb-small .tvb-face, .tvb-small { font-size: 1rem; }
.tvb-small .tvb-name { display: none; }

.tvb-food      { background: linear-gradient(160deg, #2f7d3f 0%, #46a95a 100%); }
.tvb-yuck      { background: linear-gradient(160deg, #6b4a1f 0%, #9a7130 100%); }
.tvb-sauce     { background: linear-gradient(160deg, #a8231f 0%, #e2603f 100%); }
.tvb-block     { background: linear-gradient(160deg, #3d5a8c 0%, #5a83c4 100%); }
.tvb-inspector { background: linear-gradient(160deg, #4a4f57 0%, #6d747f 100%); }
.tvb-action    { background: linear-gradient(160deg, #6d4899 0%, #9a6bd1 100%); }

.tvb-cardbutton {
    padding: 0;
    background: none;
    border: none;
    line-height: 0;
    cursor: pointer;
    border-radius: .5rem;
    transition: transform .09s ease;
}

.tvb-cardbutton:disabled { cursor: default; opacity: .5; }
.tvb-cardbutton:not(:disabled):hover { transform: translateY(-3px); }
.tvb-cardbutton.picked { transform: translateY(-8px); }
.tvb-cardbutton.picked .tvbcard { box-shadow: 0 0 0 3px var(--accent), 0 4px 8px rgba(0, 0, 0, .5); }
.tvb-cardbutton.aiming .tvbcard { box-shadow: 0 0 0 3px #e2603f, 0 4px 8px rgba(0, 0, 0, .5); }

.tvb-hand { gap: .45rem; padding-top: .9rem; align-items: flex-end; min-height: 6rem; }

/* ---- the meals ---- */

.tvb-meals { display: flex; flex-direction: column; gap: 1.1rem; }
.tvb-meal { display: flex; flex-direction: column; gap: .5rem; align-items: flex-start; }
.tvb-meal.yours .seat-name { color: var(--accent); }
.tvb-meal.their-turn .dot { background: var(--accent); }
.tvb-meal .opponent-head { margin: 0; width: 100%; }
.tvb-meal .count { margin-left: auto; }

.tvb-shell {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-muted);
    border: 1px solid var(--panel-edge);
    border-radius: .6rem;
    padding: .05rem .4rem;
}

.tvb-plate {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    align-items: center;
    min-height: 3.5rem;
    width: 100%;
}

.tvb-item { padding: 0; background: none; border: none; line-height: 0; cursor: default; border-radius: .35rem; }
.tvb-item.grabbable { cursor: pointer; }
.tvb-item.grabbable:hover .tvbcard { outline: 2px solid var(--accent); outline-offset: 1px; }

.tvb-good { color: #7fd08c; }
.tvb-bad  { color: #f0a49c; }

.chip-meal { background: rgba(70, 169, 90, .2); border-color: #46a95a; color: #a4dcae; }

.tvb-bin summary { cursor: pointer; font-weight: 600; color: var(--ink-muted); }

/* ---------------------------------------------------------------------------
   Skip-Bo. Four building piles in the middle, and everybody's stock and
   discard piles around them. Cards are small and numerous, so the whole thing
   leans on one compact card chip rather than the big CardView.
   --------------------------------------------------------------------------- */

.sb-builds {
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem;
}

.sb-build {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding: 0.6rem;
    border: 1px solid var(--panel-edge);
    border-radius: 0.6rem;
    min-width: 5.5rem;
}

.sb-build-open {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent);
}

.sb-needs {
    font-size: 0.8rem;
    color: var(--ink-muted);
}

.sb-card {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 3.1rem;
    height: 4.3rem;
    border-radius: 0.5rem;
    border: 1px solid var(--panel-edge);
    background: var(--panel);
    font-weight: 700;
    font-size: 1.4rem;
    line-height: 1;
    padding: 0;
}

.sb-card.sb-small {
    width: 2.2rem;
    height: 3rem;
    font-size: 1rem;
}

.sb-wild {
    background: linear-gradient(145deg, #6d28d9, #2563eb);
    border-color: #7c3aed;
    color: #fff;
}

.sb-empty {
    background: transparent;
    border-style: dashed;
    color: var(--ink-muted);
    font-weight: 400;
}

.sb-asterisk {
    font-size: 0.55rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    opacity: 0.85;
    margin-top: 0.15rem;
}

.sb-pick { cursor: pointer; }
.sb-pick:disabled { cursor: default; opacity: 0.75; }
.sb-pick:not(:disabled):hover { border-color: var(--accent); }

.sb-on {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent);
    transform: translateY(-3px);
}

.sb-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.sb-yours {
    display: flex;
    flex-wrap: wrap;
    gap: 2rem;
    margin-bottom: 1rem;
}

.sb-slot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
}

.sb-divider {
    width: 1px;
    align-self: stretch;
    background: var(--panel-edge);
    margin: 0 0.4rem;
}

.sb-people {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}

.sb-person {
    padding: 0.7rem 0.9rem;
    border: 1px solid var(--panel-edge);
    border-radius: 0.6rem;
}

.sb-person-on { border-color: var(--accent); }

.sb-person-head {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    margin-bottom: 0.5rem;
}

.sb-peek { margin-top: 0.5rem; opacity: 0.85; }

/* ---- Cards Against Humanity ---- */

.cah-black {
    background: #0b0d10;
    color: #f4f6f8;
    border: 1px solid #000;
    border-radius: 0.7rem;
    padding: 1.1rem 1.2rem 0.9rem;
    max-width: 34rem;
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
}

.cah-black-text {
    margin: 0;
    font-size: 1.15rem;
    line-height: 1.45;
    font-weight: 600;
}

.cah-pick {
    align-self: flex-end;
    font-size: 0.72rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #9aa6b4;
}

.cah-pack { margin: 0.5rem 0 0; font-size: 0.8rem; }

.cah-hand {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
}

.cah-white {
    position: relative;
    width: 11rem;
    min-height: 6.5rem;
    text-align: left;
    padding: 0.7rem 0.75rem;
    background: #f2f4f6;
    color: #14181d;
    border: 1px solid #cdd4db;
    border-radius: 0.6rem;
    font: inherit;
    font-size: 0.9rem;
    line-height: 1.35;
    cursor: pointer;
}

.cah-white:hover { filter: brightness(1.04); }

.cah-on {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px rgba(74, 157, 111, 0.55);
    transform: translateY(-2px);
}

.cah-white-text { display: block; }

.cah-order {
    position: absolute;
    top: 0.4rem;
    right: 0.5rem;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 50%;
    background: var(--accent);
    color: var(--accent-ink);
    font-size: 0.75rem;
    line-height: 1.25rem;
    text-align: center;
}

.cah-actions {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-top: 1rem;
    flex-wrap: wrap;
}

.cah-locked {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    flex-wrap: wrap;
}

.cah-answers {
    display: flex;
    flex-wrap: wrap;
    gap: 0.8rem;
}

.cah-answer {
    flex: 1 1 18rem;
    max-width: 26rem;
    padding: 0.9rem 1rem;
    border: 1px solid var(--panel-edge);
    border-radius: 0.6rem;
    background: rgba(255, 255, 255, 0.02);
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
}

.cah-answer-win {
    border-color: var(--accent);
    box-shadow: 0 0 0 1px rgba(74, 157, 111, 0.35);
}

.cah-filled {
    line-height: 1.5;
    flex: 1;
}

/* The bit that came off a white card, so you can see the joint. */
.cah-fill {
    font-weight: 600;
    color: #fff;
    border-bottom: 2px solid var(--accent);
}

.cah-answer-foot {
    display: flex;
    justify-content: flex-end;
    min-height: 1.8rem;
    align-items: center;
}

.cah-owner { font-size: 0.85rem; color: var(--ink-muted); }

.cah-answer-win .cah-owner { color: var(--ink); }

.cah-people {
    display: flex;
    flex-wrap: wrap;
    gap: 0.8rem;
}

.cah-person {
    padding: 0.65rem 0.85rem;
    border: 1px solid var(--panel-edge);
    border-radius: 0.6rem;
    min-width: 9rem;
}

.cah-person-judge { border-color: var(--accent); }

.cah-person-head {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    margin-bottom: 0.35rem;
}

.cah-state {
    font-size: 0.8rem;
    color: var(--ink-muted);
}

.cah-state-in { color: var(--accent); }

/* Ran the clock out: out of this hand, still in the game. */
.cah-state-out { color: var(--danger); font-weight: 600; }

/* The answering clock. Tabular figures so the number does not jitter as it counts
   down and the chip does not change width every second. */
.cah-clock { font-variant-numeric: tabular-nums; }

.cah-clock.urgent {
    background: rgba(224, 96, 96, .2);
    border-color: var(--danger);
    color: #f0a0a0;
    font-weight: 700;
}

/* Swap mode: the hand is being thrown away, not played, so it should not look
   like the normal pick-a-card state. */
.cah-hand.cah-swapping .cah-white { border-color: var(--danger); }
.cah-hand.cah-swapping .cah-white:hover { filter: none; background: rgba(224, 96, 96, .18); }

.cah-swap-hint { color: #f0a0a0; }
.cah-swap-used { font-size: .85rem; align-self: center; }

.cah-peek {
    margin-top: 0.5rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    opacity: 0.85;
}

.cah-mini {
    font-size: 0.72rem;
    padding: 0.15rem 0.4rem;
    border: 1px solid var(--panel-edge);
    border-radius: 0.35rem;
    color: var(--ink-muted);
}

/* ---------------------------------------------------------------------------
   Suited cards — Mau-Mau, Crazy Eights. A normal deck rather than a coloured
   one, so the cards are pale with a printed index: rank over pip in the corner,
   the way a real card fans.
   --------------------------------------------------------------------------- */

.scard {
    position: relative;
    width: 3.6rem;
    height: 5.2rem;
    border-radius: .45rem;
    border: 1px solid #b9bfc7;
    background: #f4f2ec;
    box-shadow: 0 2px 5px rgba(0, 0, 0, .45);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .1rem;
    overflow: hidden;
    user-select: none;
    flex: none;
    line-height: 1;
}

/* On the card face the suits print their real colours. */
.scard.suit-red   { color: #c1272d; }
.scard.suit-black { color: #16181c; }

.scard-rank { font-size: 1.45rem; font-weight: 700; }
.scard-pip  { font-size: 1.1rem; }

/* The index. A fanned hand overlaps down to this corner and nothing else, which
   is exactly what it is for. */
.scard-corner {
    position: absolute;
    top: .2rem;
    left: .3rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .02rem;
    font-size: .62rem;
    font-weight: 700;
    line-height: 1;
}

.scard-corner-pip { font-size: .6rem; font-weight: 400; }

.scard-art { position: absolute; inset: 0; background-size: cover; background-position: center; }

/* Small cards are what a fan is made of, so they keep the index and drop the
   middle — the opposite of the UNO cards, which fan by their big glyph. */
.scard-sm {
    width: 2.5rem;
    height: 3.6rem;
    border-radius: .3rem;
}

.scard-sm .scard-rank,
.scard-sm .scard-pip { display: none; }

.scard-sm .scard-corner { font-size: .68rem; top: .22rem; left: .28rem; }
.scard-sm .scard-corner-pip { font-size: .66rem; }

.scard-back {
    background:
        repeating-linear-gradient(45deg, #6d2028 0 4px, #86282f 4px 8px),
        #6d2028;
    border-color: #a8545a;
}

.scard-mark {
    width: 58%;
    height: 32%;
    border-radius: 40%;
    background: rgba(255, 255, 255, .1);
    border: 1.5px solid rgba(255, 255, 255, .3);
}

.suit-cardbutton {
    padding: 0;
    background: none;
    border: none;
    line-height: 0;
    cursor: pointer;
    border-radius: .45rem;
    transition: transform .1s ease;
}

.suit-cardbutton:disabled { cursor: not-allowed; }
.suit-cardbutton:not(:disabled):hover { transform: translateY(-.5rem); }
.suit-cardbutton.playable .scard { box-shadow: 0 0 0 2px var(--accent), 0 2px 6px rgba(0, 0, 0, .45); }
.suit-cardbutton.blocked .scard { opacity: .38; filter: grayscale(.5); }
.suit-cardbutton.blocked:hover { transform: none; }
.suit-cardbutton.picked { transform: translateY(-.5rem); }
.suit-cardbutton.picked .scard { box-shadow: 0 0 0 3px var(--accent), 0 4px 8px rgba(0, 0, 0, .5); }

/* Against the dark panel a black pip would vanish, so the two suit colours
   become light and red rather than black and red. */
.chip.suit-red,
.suit-called.suit-red { color: #f0a49c; }

.chip.suit-black,
.suit-called.suit-black { color: var(--ink); }

.chip.suit-red { background: rgba(193, 39, 45, .2); border-color: #a8383c; }
.chip.suit-black { background: rgba(232, 237, 243, .12); border-color: var(--ink-muted); }

.suit-called {
    margin: 0 0 1.25rem;
    font-size: .9rem;
}

.suit-swatch {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font: inherit;
    font-size: .85rem;
    padding: .45rem .9rem;
    border-radius: var(--radius);
    background: #232d39;
    border: 1px solid var(--panel-edge);
    cursor: pointer;
}

.suit-swatch:hover { border-color: var(--accent); }
.suit-swatch.suit-red { color: #f0a49c; }
.suit-swatch.suit-black { color: var(--ink); }
.suit-swatch-pip { font-size: 1.1rem; }

/* ---------------------------------------------------------------------------
   Table chat. Text for anyone without a mic, emotes for anyone who has one but
   is holding a phone — tapping is a lot faster than typing on your turn.
   --------------------------------------------------------------------------- */

.chat-log {
    display: flex;
    flex-direction: column;
    gap: .3rem;
    max-height: 14rem;
    overflow-y: auto;
    margin-bottom: .75rem;
    padding-right: .25rem;
}

.chat-empty { margin: 0; font-size: .88rem; }

.chat-line {
    font-size: .9rem;
    line-height: 1.35;
    /* Long words and pasted URLs wrap instead of widening the whole column. */
    overflow-wrap: anywhere;
}

/* The gap is a real space in the markup, not a margin, so a copied line reads
   "Bob: nice one" rather than running the name into the message. */
.chat-who {
    color: var(--ink-muted);
    font-weight: 600;
}

.chat-line.mine .chat-who { color: var(--accent); }

.chat-text { color: var(--ink); }

/* An emote is the message, so it gets to be legible from across the room. */
.chat-emote { font-size: 1.5rem; vertical-align: middle; line-height: 1; }

.chat-emotes {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    margin-bottom: .6rem;
}

.chat-emote-button {
    padding: .25rem .45rem;
    background: #232d39;
    border: 1px solid var(--panel-edge);
    border-radius: var(--radius);
    font-size: 1.15rem;
    line-height: 1.1;
    cursor: pointer;
}

.chat-emote-button:hover { border-color: var(--accent); }

.chat-compose { display: flex; gap: .5rem; align-items: flex-start; }

/* .text-input carries a bottom margin for the join form; the row supplies its own. */
.chat-input { margin-bottom: 0; }

.chat-compose .btn { flex: 0 0 auto; }

/* ---------------------------------------------------------------------------
   Custom card designs.

   A design fills the card and takes the drawn face with it — the big glyph is
   the app's drawing of the card, and yours replaces it. The corner index is kept
   on purpose: a fanned hand overlaps down to that corner and it is the only part
   still visible, so losing it would make your own cards unplayable in a fan.
   --------------------------------------------------------------------------- */

.card.has-art,
.kcard.has-art,
.scard.has-art { background-size: cover; background-position: center; }

/* The drawn face steps aside for the artwork. */
.card.has-art .card-face,
.kcard.has-art .kcard-symbol,
.kcard.has-art .kcard-name,
.scard.has-art .scard-rank,
.scard.has-art .scard-pip { display: none; }

/* ...and the back's placeholder mark goes with it. */
.card-back.has-art .card-back-mark,
.kcard-back.has-art .kcard-mark,
.scard-back.has-art .scard-mark { display: none; }

/* Kept legible over whatever the art happens to be underneath. */
.card.has-art .card-corner,
.scard.has-art .scard-corner {
    background: rgba(255, 255, 255, .82);
    color: #16181c;
    border-radius: .3rem;
    padding: .05rem .22rem;
    line-height: 1.05;
}

/* Decks whose cards are read one at a time rather than from a fanned corner: the
   design replaces the whole face. Only the UNO, suited and Kittens decks overlap
   into a fan, which is why those keep their corner index and these do not.

   Two rules because a face can be bare text (Skyjo's number is the div's own text
   content, with no element to hide) or a child span. */
.sjcard.has-art,
.f7card.has-art,
.p10card.has-art,
.sb-card.has-art,
.tvbcard.has-art,
.sfcard.has-art,
.sf-litter.has-art {
    background-size: cover;
    background-position: center;
    color: transparent;
}

.sjcard.has-art > *,
.f7card.has-art > *,
.p10card.has-art > *,
.sb-card.has-art > *,
.tvbcard.has-art > *,
.sfcard.has-art > * { visibility: hidden; }

/* Cards Against Humanity gets a background rather than card art: the words are
   the card, so they stay on top of whatever you put behind them. */
.cah-black.has-art,
.cah-white.has-art {
    background-size: cover;
    background-position: center;
}

/* ---------------------------------------------------------------------------
   The /designs reference sheet.
   --------------------------------------------------------------------------- */

.deck-head {
    display: flex;
    align-items: center;
    gap: .6rem;
    width: 100%;
    padding: 0;
    background: none;
    border: 0;
    color: var(--ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.deck-caret { color: var(--ink-muted); width: .9rem; }
.deck-name { font-weight: 600; flex: 1 1 auto; }

.deck-count {
    color: var(--ink-muted);
    font-size: .85rem;
    font-variant-numeric: tabular-nums;
}

.deck-count.some { color: var(--accent); font-weight: 600; }

.art-grid {
    margin-top: .9rem;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: .5rem;
}

.art-slot {
    position: relative;
    display: flex;
    align-items: center;
    border: 1px solid var(--panel-edge);
    border-radius: var(--radius);
    font-size: .82rem;
}

/* The whole tile is the upload button, so the target is as big as the tile. */
.art-pick {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex: 1 1 auto;
    min-width: 0;
    padding: .35rem .5rem;
    background: none;
    border: 0;
    border-radius: var(--radius);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.art-pick:disabled { cursor: default; }
.art-pick:not(:disabled):hover { background: rgba(255, 255, 255, .05); }

.art-slot.busy { opacity: .5; }

.art-remove {
    flex: 0 0 auto;
    align-self: stretch;
    padding: 0 .5rem;
    background: none;
    border: 0;
    border-left: 1px solid var(--panel-edge);
    color: var(--ink-muted);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}

.art-remove:hover { color: var(--danger); }

/* Off-screen rather than display:none — a hidden input cannot be clicked open. */
.visually-gone {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
}

.art-slot.found { border-color: var(--accent); }

.art-swatch {
    flex: 0 0 auto;
    width: 2rem;
    height: 2.9rem;
    border-radius: .25rem;
    background-color: #232d39;
    background-size: cover;
    background-position: center;
    border: 1px solid var(--panel-edge);
}

.art-name { overflow-wrap: anywhere; font-family: ui-monospace, Consolas, monospace; }

/* The name and, for a moment, the sentence saying when you would hear it. */
.art-text {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    min-width: 0;
}

.art-note { color: var(--ink-muted); font-size: .75rem; line-height: 1.3; }

/* Pictures or sounds. Same decks, one list at a time. */
.mode-row { display: flex; gap: .5rem; margin: 0 0 1rem; }

/* A sound has nothing to show, so its swatch is a mark rather than a card. */
.art-grid-wide { grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); }

.sound-swatch {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.1rem;
    height: 2.1rem;
    font-size: 1.15rem;
    line-height: 1;
    color: var(--ink-muted);
}

.art-slot.found .sound-swatch { color: var(--accent); }

.art-play {
    flex: 0 0 auto;
    align-self: stretch;
    padding: 0 .5rem;
    background: none;
    border: 0;
    border-left: 1px solid var(--panel-edge);
    color: var(--ink-muted);
    font-size: .8rem;
    line-height: 1;
    cursor: pointer;
}

.art-play:hover { color: var(--accent); }

/* The language switch: quiet, and out of the way of the name box. */
.lang-picker { display: flex; gap: .4rem; margin: .75rem 0; }

/* The vote buttons on a seat. They sit on their own line so a long name and two
   counters never squeeze the badge off the row on a phone. */
.seat-votes {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    flex-basis: 100%;
    margin-top: .3rem;
}

.seat-votes .btn { font-variant-numeric: tabular-nums; }

.seat { flex-wrap: wrap; }

/* ---------------------------------------------------------------------------
   Volume, in the table header.

   Per browser, not per table: everyone is sitting in a different room, and the
   one thing this must never do is play into somebody's headphones at a level
   they did not choose.
   --------------------------------------------------------------------------- */

.sound-box { display: flex; align-items: center; gap: .4rem; }

.sound-icon {
    padding: 0;
    background: none;
    border: 0;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
}

.sound-slider {
    width: 6.5rem;
    accent-color: var(--accent);
    cursor: pointer;
}

/* The reference sheet is a wide read, not a narrow one like the lobby. */
.lobby-wide { max-width: 62rem; margin: 0 auto; }
.lobby-wide h1 { margin-bottom: .35rem; }
.lobby-note {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .5rem;
    margin-top: 2.5rem;
}

.lobby-note-count { margin: 0; }
.art-slot:not(.found) .art-name { color: var(--ink-muted); }

/* ===========================================================================
   Responsive layout

   The table used to be one 34rem column at every width, which meant a phone
   scrolled past three panels of preamble to reach its own hand, and a desktop
   monitor left two thirds of itself empty. Two rules fix most of it: the play
   area comes first in the document, and on a wide screen the reference
   material (game blurb, rules, log, seats, host controls) moves beside it
   rather than under it.
   =========================================================================== */

.table-view {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0 1.5rem;
    max-width: 34rem;
    margin: 0 auto;
}

.table-header,
.table-footer { grid-column: 1 / -1; }

/* Panels size to their column here; the 34rem cap is for the pages that are
   still a single centred card, like joining a table. */
.table-main .panel,
.table-side .panel { max-width: none; margin-left: 0; margin-right: 0; }

/* ---- tablets and small laptops: one wider column ---- */

@media (min-width: 46rem) {
    .table-view { max-width: 42rem; }

    /* Ten games stacked one to a row is a long scroll on a screen with the
       room for two. */
    .game-list {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
        gap: .6rem;
    }

    /* Room for a full table of people without a scroll each. */
    .opponents,
    .f7-others {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
        gap: 1.1rem 1.5rem;
    }
}

/* ---- desktop: two columns ---- */

@media (min-width: 62rem) {
    .table-view {
        max-width: 62rem;
        grid-template-columns: minmax(0, 1fr) 21rem;
        align-items: start;
    }

    /* A long game leaves a long log. Let it scroll in place instead of
       stretching the sidebar past the play area. */
    .table-side .log { max-height: 18rem; overflow-y: auto; }

    /* 21rem is phone-width, so the rules read the way they do on a phone. */
    .table-side .rules-card { grid-template-columns: 1fr; }
}

/* ---- big screens: let the wide games breathe ---- */

@media (min-width: 82rem) {
    .table-view { max-width: 78rem; }
}

/* ---- phones ---- */

@media (max-width: 40rem) {
    body { padding: 1rem .85rem 3rem; }

    h1 { font-size: 1.35rem; }
    .lobby { margin-top: 7vh; }
    .lobby h1 { font-size: 1.9rem; }
    .lobby-actions { gap: 1.5rem; }

    .panel { padding: 1.1rem; margin-bottom: .85rem; }

    .table-header {
        flex-wrap: wrap;
        gap: .5rem .75rem;
        margin-bottom: 1rem;
    }

    /* Once it wraps onto its own line there is nothing left to be right of. */
    .you {
        flex-direction: row;
        align-items: center;
        text-align: left;
        gap: .55rem;
    }

    .code-chip { font-size: 1.25rem; }
    .table-footer { margin-top: 1rem; }

    .piles { gap: 1.25rem; margin-bottom: 1.25rem; }
    .opponents { gap: .8rem; }

    /* Ten choices at full size is a lot of thumb. */
    .game-option { padding: .7rem .85rem; }
    .game-tagline { font-size: .84rem; }

    /* Two white cards to a row beats ten rows of one. */
    .cah-hand { gap: .45rem; }
    .cah-white { width: calc(50% - .25rem); min-height: 5.25rem; font-size: .84rem; padding: .55rem .6rem; }
    .cah-black { padding: .9rem 1rem .75rem; }
    .cah-black-text { font-size: 1.05rem; }
    .cah-answer { flex-basis: 100%; }
    .cah-person { min-width: 0; flex: 1 1 8rem; }

    .sb-builds { gap: .7rem; }
    .sb-yours { gap: 1rem; }
    .sb-people { gap: .7rem; }

    .scard { width: 3.2rem; height: 4.6rem; }
    .scard-rank { font-size: 1.25rem; }
    .scard-pip { font-size: .95rem; }

    .sj-others { gap: 1rem; }
    .tvb-meals { gap: .8rem; }
    .p10-melds { gap: .8rem; }
    .p10-meldlabel { min-width: 0; }
}

/* ---- touch ---- */

@media (pointer: coarse) {
    /* Emote buttons are the fast path on a phone, so make them a real target. */
    .chat-emote-button { min-width: 2.75rem; min-height: 2.75rem; font-size: 1.3rem; }

    /* inline-flex so the label stays centred once the minimum height kicks in. */
    .btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-height: 2.75rem;
    }

    .btn-sm { min-height: 2.25rem; }
    .toggle input { width: 1.25rem; height: 1.25rem; }
}

/* A finger has no hover, so a tap leaves the lifted card stuck up in the air
   until you touch something else. */
@media (hover: none) {
    .card-button:hover,
    .suit-cardbutton:not(:disabled):hover,
    .p10-cardbutton:not(:disabled):hover,
    .sf-cardbutton:not(:disabled):hover,
    .tvb-cardbutton:not(:disabled):hover { transform: none; }

    .cah-white:hover { filter: none; }
}
