    body {
        font-family: 'Arial', sans-serif;
        background-color: #333;
        margin: 0;
        padding: 0;
        color: #eee;
    }
    a { color: #7cb8ff; }
    .page {
        max-width: 900px;
        margin: 0 auto;
        padding: 20px;
        padding-bottom: 70px; /* room for the mobile hand tabs, harmless on desktop */
    }
    .site-nav {
        position: relative;
        display: flex;
        align-items: center;
        gap: 10px;
        flex-wrap: wrap;
        background: #262626;
        padding: 10px 20px;
    }
    .site-nav .brand {
        font-weight: bold;
        font-size: 1.2em;
        text-decoration: none;
        display: inline-flex;
        align-items: center;
        gap: 8px;
    }
    .site-nav .brand-logo {
        height: 1.9em;
        width: auto;
    }
    .hamburger {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: none;
        border: none;
        padding: 6px 8px;
        color: #eee;
        cursor: pointer;
    }
    .hamburger:hover { background: #3a3a3a; }
    .hamburger-icon {
        width: 22px;
        height: 22px;
        fill: none;
        stroke: currentColor;
        stroke-width: 2;
        stroke-linecap: round;
    }
    .nav-menu {
        display: none;
        flex-direction: column;
        gap: 2px;
        position: absolute;
        top: 100%;
        right: 10px;
        background: #2e2e2e;
        border: 1px solid #555;
        border-radius: 0 0 8px 8px;
        padding: 6px;
        min-width: 180px;
        z-index: 600;
    }
    .nav-menu.open { display: flex; }
    .nav-menu a, .nav-menu button {
        display: block;
        text-align: left;
        background: none;
        border: none;
        padding: 8px 10px;
        border-radius: 4px;
        font-size: 1em;
        color: #eee;
        text-decoration: none;
        cursor: pointer;
    }
    .nav-menu a:hover, .nav-menu button:hover { background: #454545; }
    .nav-version {
        display: block;
        padding: 8px 10px;
        font-size: 0.8em;
        color: #888;
        border-top: 1px solid #444;
        margin-top: 4px;
    }
    .site-nav .nav-extra {
        display: flex;
        gap: 16px;
        align-items: center;
        margin-left: auto;
    }
    .room-code {
        font-family: monospace;
        font-size: 1.3em;
        letter-spacing: 0.2em;
        background: #1a1a1a;
        color: #fff;
        padding: 4px 10px;
        border-radius: 6px;
    }
    .flash {
        background: #fce8b2;
        border: 1px solid #d4a017;
        color: #3a2e00;
        padding: 8px 12px;
        border-radius: 6px;
        margin-bottom: 15px;
    }
    .role-badge {
        display: inline-block;
        background: #262626;
        color: #bbb;
        font-size: 0.85em;
        padding: 4px 12px;
        border-radius: 999px;
        margin-bottom: 12px;
    }
    button, .button {
        font-size: 1em;
        padding: 8px 16px;
        border-radius: 6px;
        border: 1px solid #666;
        background: #4a4a4a;
        color: #eee;
        cursor: pointer;
        white-space: nowrap;
    }
    a.button {
        display: inline-block;
        text-decoration: none;
    }
    .play-from {
        margin: 12px 0;
    }
    button:hover, .button:hover {
        background: #5a5a5a;
    }
    button.small {
        font-size: 0.8em;
        padding: 3px 10px;
    }
    input[type=text] {
        font-size: 1em;
        padding: 8px;
        border-radius: 6px;
        border: 1px solid #666;
        background: #4a4a4a;
        color: #eee;
    }
    input[type=text]::placeholder {
        color: #aaa;
    }
    input.room-code-input {
        text-transform: uppercase;
        letter-spacing: 0.15em;
    }

    /* Name / settings modal, reused for the forced "pick a name" prompt
       and for the always-available settings button, and the game-over
       result modal. */
    .modal-backdrop {
        display: none;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.6);
        align-items: center;
        justify-content: center;
        z-index: 1000;
    }
    .modal-backdrop.open { display: flex; }
    .modal {
        position: relative;
        background: #444;
        border: 1px solid #666;
        padding: 20px 28px;
        border-radius: 8px;
        min-width: 260px;
        text-align: center;
    }
    .modal h3 { margin-top: 0; }
    .modal h2 { margin-top: 0; font-size: 1.8em; }
    .modal .modal-score { font-size: 1.2em; margin-bottom: 4px; }
    .modal .modal-close {
        position: absolute;
        top: 6px;
        right: 10px;
        background: none;
        border: none;
        font-size: 1.4em;
        line-height: 1;
        padding: 4px 8px;
        color: #ccc;
    }
    .modal .modal-close:hover { background: none; color: #fff; }
    .modal-actions {
        margin-top: 12px;
        display: flex;
        gap: 8px;
        justify-content: center;
        flex-wrap: wrap;
    }

    .history-stepper {
        display: flex;
        justify-content: center;
        align-items: center;
        gap: 10px;
        margin: 10px 0;
        width: 650px;
        max-width: 100%;
    }
    .history-count {
        display: inline-block;
        min-width: 4.5em;
        text-align: center;
        white-space: nowrap;
    }
    .move-analysis {
        width: 650px;
        max-width: 100%;
        margin: 10px 0;
        background: #2b2b2b;
        border: 1px solid #4a4a4a;
        border-radius: 8px;
        padding: 10px 14px;
    }
    .move-analysis h3 {
        margin: 4px 0 6px;
        font-size: 1.05em;
    }
    .analysis-sub {
        color: #aaa;
        font-weight: normal;
        font-size: 0.85em;
        margin-left: 6px;
    }
    .analysis-note {
        color: #bbb;
        font-size: 0.85em;
        margin: 4px 0 8px;
    }
    .analysis-table-wrap {
        overflow-x: auto;
    }
    .analysis-table {
        border-collapse: collapse;
        width: 100%;
        font-size: 0.9em;
    }
    .analysis-table th, .analysis-table td {
        text-align: left;
        padding: 4px 10px 4px 0;
        border-bottom: 1px solid #3d3d3d;
        white-space: nowrap;
    }
    .analysis-table th {
        color: #999;
        font-weight: normal;
        cursor: default;
    }
    .analysis-table tr:last-child td { border-bottom: none; }
    .analysis-table td.num {
        font-variant-numeric: tabular-nums;
        text-align: right;
    }
    .analysis-table th:nth-child(n+2) { text-align: right; }
    .analysis-table .badges { text-align: right; }
    .analysis-played td { background: rgba(124, 184, 255, 0.08); }
    .cardtext { font-weight: bold; }
    .cardtext.red { color: #ff7a7a; }
    .badge {
        display: inline-block;
        font-size: 0.75em;
        padding: 1px 8px;
        border-radius: 999px;
        margin-left: 4px;
    }
    .badge-best { background: #2e5c34; color: #b8f0c0; }
    .badge-played { background: #2e4a6b; color: #bcd9ff; }
    .badge-out { background: #4a4a4a; color: #aaa; }
    .badge-calculating { background: #4a4326; color: #f0dfa8; }
    .badge-stopped { background: #4a2e2e; color: #f0b8b8; }
    .analysis-out td { opacity: 0.55; }
    .analysis-unsolved td { color: #888; }
    .analysis-unsolved .num { color: #666; }
    .outcome-heatmap {
        margin: 10px 0 14px;
    }
    .outcome-heatmap-header {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 10px;
        margin-bottom: 6px;
        font-size: 0.85em;
    }
    .outcome-heatmap-title { color: #aaa; }
    .outcome-heatmap-mode { font-weight: bold; white-space: nowrap; }
    .outcome-heatmap-row {
        display: grid;
        gap: 2px;
        height: 34px;
    }
    .outcome-heatmap-cell {
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 3px;
        font-size: 0.72em;
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
    }
    .outcome-heatmap-cell-zero {
        box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.55);
    }
    .outcome-heatmap-ticks {
        display: grid;
        gap: 2px;
        margin-top: 4px;
        font-size: 0.72em;
        color: #999;
        text-align: center;
    }
    .outcome-heatmap-names {
        display: flex;
        justify-content: space-between;
        margin-top: 2px;
        font-size: 0.8em;
        color: #bbb;
    }
    .rematch-controls {
        display: flex;
        align-items: center;
        gap: 8px;
        flex-wrap: wrap;
        margin: 10px 0;
    }
    /* Two copies of the same controls (see _game_state.html.jinja2) so they
       can sit in different spots on desktop vs. mobile without JS - only
       one is ever visible at a time. */
    .rematch-controls-mobile { display: none; }

    .game-container {
        display: flex;
        align-items: flex-start;
        gap: 40px;
        margin: 15px 0;
        /* No wrapping in desktop mode - the mobile breakpoint (900px) is
           already the intentional cutoff for "not enough room for board +
           hands side by side", so anything at or above it should reliably
           stay side by side. Wrapping here was what let long rematch-status
           text (e.g. "Waiting for X to respond...") drop the hands below
           the board even on a full desktop width, since flex-wrap decides
           per-line fit before shrinking is applied. */
        flex-wrap: nowrap;
    }
    .hands {
        display: flex;
        flex-direction: column;
        gap: 30px;
        /* The fanned cards inside are absolutely positioned, so they don't
           contribute to this column's own width - but normal-flow content
           like .rematch-controls-desktop's rematch-request text does, and
           without a cap that text can grow the column wide enough to push
           .game-container's flex-wrap into dropping the hands below the
           board (see history around the 700px->900px breakpoint fix). Cap
           it to the fan's own rough footprint so long text wraps in place
           instead of stretching the layout. */
        max-width: 260px;
    }
    .seat-header {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 10px;
        margin-bottom: 4px;
    }
    .board {
        display: grid;
        grid-template-columns: repeat(6, 100px);
        grid-template-rows: repeat(6, 150px);
        gap: 10px;
        position: relative;
    }
    .board::before {
        content: "";
        position: absolute;
        top: 74px;
        left: 49px;
        width: 552px;
        height: 802px;
        background-image: linear-gradient(to right, #777 2px, transparent 2px),
                          linear-gradient(to bottom, #777 2px, transparent 2px);
        background-size: 110px 160px;
    }
    .cell-button {
        all: unset;
        cursor: pointer;
    }
    .cell-button .card {
        outline: 3px solid transparent;
        transition: outline-color 0.1s ease-in-out;
    }
    .cell-button:hover .card,
    .cell-button:focus .card {
        outline-color: #d4a017;
    }
    .card {
        width: 100px;
        height: 150px;
        border: 1px solid #000;
        border-radius: 10px;
        background-color: white;
        position: relative;
        font-size: 1.5em;
        box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
        box-sizing: border-box;
    }
    .marker::after {
        content: '';
        position: absolute;
        display: block;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        width: 50%;
        aspect-ratio: 1 / 1;
        background-color: blue;
        border-radius: 50%;
        box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
    }
    .turnmarker::after {
        content: '';
        position: relative;
        display: inline-block;
        width: 0.5em;
        height: 0.5em;
        background-color: blue;
        border-radius: 50%;
        box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.2);
        margin-left: 0.2em;
        vertical-align: middle;
    }
    .trophy {
        margin-left: 0.3em;
    }
    .card.taken {
        border-color: transparent;
        background: transparent;
        box-shadow: none;
    }
    .card.just-taken {
        outline: 3px solid #ffd43b;
        box-shadow: 0 0 12px 2px rgba(255, 212, 59, 0.8);
    }
    /* Marker placement phase: outline the central cells the marker can
       start on. */
    .cell-button.place-target .card { outline: 3px solid #4aa3df; }
    .cell-button.place-target:hover .card,
    .cell-button.place-target:focus .card { outline-color: #7cc4f0; }
    .placement-banner {
        margin: 0 auto 12px;
        padding: 8px 12px;
        background: #3a3a3a;
        border-left: 3px solid #4aa3df;
        border-radius: 4px;
        max-width: 640px;
    }
    .card.hearts, .card.diamonds { color: red; }
    .card.clubs, .card.spades { color: black; }
    .card .corner {
        position: absolute;
        line-height: 0.8;
    }
    .card .top-left { top: 5px; left: 5px; }
    .card .bottom-right { bottom: 5px; right: 5px; transform: rotate(180deg); }
    .card .suit {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: 50px;
    }
    .card.facedown {
        background: radial-gradient(circle, #3c3, #363);
        color: transparent;
    }
    .hand-label { font-size: 1em; color: #bbb; }
    .score {
        font-size: 2.2em;
        font-weight: 500;
    }
    .handarray {
        display: flex;
        position: relative;
        flex-direction: column;
        height: 285px;
    }
    .hand {
        display: flex;
        position: relative;
        flex-direction: row;
    }
    .handarray > .hand {
        position: absolute;
        height: 150px;
    }
    .hand > .card {
        position: absolute;
        height: 150px;
    }
    .hand:nth-child(1) { top: 0; }
    .hand:nth-child(2) { top: 45px; }
    .hand:nth-child(3) { top: 90px; }
    .hand:nth-child(4) { top: 135px; }
    .hand > .card:nth-child(1) { left: 0; }
    .hand > .card:nth-child(2) { left: 20px; }
    .hand > .card:nth-child(3) { left: 40px; }
    .hand > .card:nth-child(4) { left: 60px; }
    .hand > .card:nth-child(5) { left: 80px; }
    .hand > .card:nth-child(6) { left: 100px; }
    .hand > .card:nth-child(7) { left: 120px; }
    .hand > .card:nth-child(8) { left: 140px; }
    .hand > .card:nth-child(9) { left: 160px; }

    /* Room list */
    table.room-list {
        border-collapse: collapse;
        width: 100%;
    }
    table.room-list th, table.room-list td {
        text-align: left;
        padding: 8px 10px;
        border-bottom: 1px solid #555;
    }

    /* Mobile hand tabs, hidden on desktop */
    .mobile-hand-tabs { display: none; }

    /* ---- inText-style compact cards for small screens ----
       Adapted from https://github.com/selfthinker/CSS-Playing-Cards
       "inText" mode: shrink the cards right down and drop the decorative
       corner/center-suit layout entirely in favour of a single centered
       rank+suit label (rank stacked above the suit icon, as in the
       original) - the full card face is too small to read legibly at
       this size. */
    /* Matches .page's own max-width: the desktop layout needs a fixed
       ~650px board plus room for the hand fans beside it, which stops
       fitting well before a narrower viewport would visually justify
       staying in "desktop" mode - so switch to the compact mobile layout
       at the same point the page itself starts shrinking, rather than
       leaving a gap where flex-wrap silently drops the (still full-size)
       hands below the board. */
    @media (max-width: 900px) {
        /* The hand panel is now permanently shown (see applyActiveHand()),
           not a drawer you tap open, so it costs board space the whole
           time you're playing - claw some of that back from the page's
           top padding rather than shrinking the board itself, and reserve
           room at the bottom so it doesn't sit on top of the board. */
        .page { padding-top: 8px; padding-bottom: 246px; }
        .game-container { justify-content: center; margin-top: 4px; }
        .hands { display: contents; }
        .board {
            grid-template-columns: repeat(6, 40px);
            grid-template-rows: repeat(6, 56px);
            gap: 4px;
        }
        .board::before {
            /* Same centering/truncation math as the desktop rule above,
               just recomputed for the 40x56 mobile card size and 4px gap
               (pitch 44x60): offset = (card size - 2px line) / 2, and
               extent = (6 - 1) * pitch + 2px so the grid lines land
               exactly on each row/column center and stop past the last
               one instead of overshooting or falling short. */
            top: 27px;
            left: 19px;
            width: 222px;
            height: 302px;
            background-size: 44px 60px;
        }
        .history-stepper {
            width: 260px;
            margin: 10px auto;
            gap: 4px;
        }
        .history-stepper button {
            padding: 6px 8px;
        }
        .history-count {
            min-width: 3.5em;
            font-size: 0.85em;
        }
        .move-analysis {
            width: 100%;
            margin: 10px auto;
            padding: 8px 10px;
            font-size: 0.95em;
        }
        .outcome-heatmap-cell {
            font-size: 0.6em;
        }
        .outcome-heatmap-ticks {
            font-size: 0.6em;
        }
        .rematch-controls-desktop { display: none; }
        .rematch-controls-mobile {
            display: flex;
            justify-content: center;
            width: 260px;
            margin: 10px auto;
        }
        .card {
            width: 40px;
            height: 56px;
            border-radius: 4px;
            font-size: 0.6em;
            box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.4);
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .card .corner, .card > .suit { display: none; }
        .card .simple-label {
            display: flex !important;
            flex-direction: column;
            align-items: center;
            line-height: 1.1;
        }
        .card .simple-label span:first-child { font-size: 19px; font-weight: bold; }
        .card .simple-label span:last-child { font-size: 18px; }

        /* The desktop hand uses absolute positioning to fan cards out with
           an overlap, relying on the corner rank+suit still being readable
           where a card is partly covered. That doesn't work with the
           mobile simple-label (centered, so any overlap hides it) - lay
           cards out as a plain wrapping grid instead. */
        .handarray {
            height: auto;
            gap: 4px;
            align-items: center;
        }
        .handarray > .hand {
            position: static;
            height: auto;
            flex-wrap: wrap;
            justify-content: center;
            gap: 3px;
        }
        .hand > .card, .hand > .card-slot {
            position: static;
            width: 40px;
            height: 56px;
        }
        /* The board needs full-size cards so the layout/icons stay
           readable, but a hand is already sorted into a predictable
           order - it doesn't need to be nearly as large to read, so
           shrink it further to reclaim vertical space in the
           permanently-visible mobile hand panel. */
        .hand-slot .card, .hand-slot .card-slot {
            width: 26px;
            height: 36px;
        }
        .hand-slot .simple-label span:first-child { font-size: 12px; }
        .hand-slot .simple-label span:last-child { font-size: 11px; }

        .mobile-hand-tabs {
            display: flex;
            position: fixed;
            left: 0;
            right: 0;
            bottom: 0;
            z-index: 500;
        }
        .mobile-hand-tabs button {
            flex: 1;
            border-radius: 0;
            border: none;
            border-top: 1px solid #666;
            padding: 12px 6px;
        }
        .mobile-hand-tabs button.active {
            background: #5a5a5a;
            border-top: 2px solid #7cb8ff;
        }
        /* Fixed-width slot, always rendered whether or not this player
           currently has a turn/trophy indicator - keeps the name from
           shifting sideways in the tab as the turn changes hands. */
        .mobile-hand-tabs .turn-slot {
            display: inline-block;
            width: 1.1em;
            text-align: center;
        }
        .mobile-hand-tabs .turnmarker::after {
            margin: 0;
        }
        .mobile-hand-tabs .trophy {
            margin: 0;
        }
        /* The tabs already carry the name, score and turn/trophy indicator
           for each player - the drawer they open is just for the cards. */
        .hand-slot .hand-label, .hand-slot .score {
            display: none;
        }
        .hand-slot {
            position: fixed;
            left: 0;
            right: 0;
            bottom: 46px;
            background: #3a3a3a;
            border-top: 1px solid #666;
            padding: 8px 12px 10px;
            transform: translateY(110%);
            transition: transform 0.25s ease-out;
            max-height: 200px;
            overflow-y: auto;
            z-index: 400;
        }
        .hand-slot.open { transform: translateY(0); }
    }

    /* --- How to play page --- */
    /* Diagrams reuse the game's card markup but force the compact
       simplified card style at every width (the game only shows it below
       900px), so the rules read the same on desktop and mobile. */
    .how-to-play { max-width: 720px; }
    .how-to-play h2 { margin-top: 1.7em; }
    .how-to-play p { line-height: 1.6; }
    .how-to-play button { margin: 4px 6px 4px 0; }
    .htp-diagram { margin: 18px 0; overflow-x: auto; }
    .htp-diagram figcaption {
        margin: 8px auto 0;
        font-size: 0.9em;
        color: #bbb;
        max-width: 400px;
        text-align: center;
    }
    /* Centre the board so the outline on the left-edge cards has room and
       isn't clipped by the figure's overflow. auto margins collapse to 0
       when it can't fit (narrow screens), leaving it scrollable. */
    .htp-diagram .diagram-board {
        display: grid;
        grid-template-columns: repeat(6, 40px);
        grid-auto-rows: 56px;
        gap: 4px;
        width: max-content;
        margin: 0 auto;
    }
    .htp-diagram .diagram-cell { position: relative; width: 40px; height: 56px; }
    .htp-diagram .diagram-cell.legal .card { outline: 3px solid #d4a017; }
    .htp-diagram .diagram-cell.pick .card { outline: 3px solid #4aa3df; }
    .htp-diagram .diagram-cell.dim .card { opacity: 0.22; }
    .htp-diagram .diagram-hand { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; justify-content: center; }
    /* Runs and sets side by side, stacking on narrow screens. */
    .how-to-play .htp-columns { display: flex; gap: 24px; flex-wrap: wrap; }
    .how-to-play .htp-columns > div { flex: 1 1 240px; }
    .htp-diagram .card {
        width: 40px;
        height: 56px;
        border-radius: 4px;
        box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.4);
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .htp-diagram .card .corner, .htp-diagram .card > .suit { display: none; }
    .htp-diagram .card .simple-label {
        display: flex !important;
        flex-direction: column;
        align-items: center;
        line-height: 1.1;
    }
    .htp-diagram .card .simple-label span:first-child { font-size: 19px; font-weight: bold; }
    .htp-diagram .card .simple-label span:last-child { font-size: 18px; }
    .htp-legend {
        display: flex;
        gap: 20px;
        flex-wrap: wrap;
        font-size: 0.9em;
        color: #bbb;
        margin: 10px 0;
    }
    .htp-legend .swatch {
        display: inline-block;
        width: 0.9em;
        height: 0.9em;
        vertical-align: middle;
        margin-right: 0.4em;
        box-sizing: border-box;
    }
    .htp-swatch-marker { background: blue; border-radius: 50%; }
    .htp-swatch-legal { outline: 3px solid #d4a017; background: white; }
    .htp-details { margin: 12px 0; }
    .htp-details summary { cursor: pointer; color: #7cb8ff; width: fit-content; }
    .htp-details summary:hover { text-decoration: underline; }
    .htp-details .table-scroll { margin-top: 10px; }
    .table-scroll { overflow-x: auto; }
    .score-table { border-collapse: collapse; margin: 10px 0; }
    .score-table th, .score-table td {
        border: 1px solid #555;
        padding: 4px 14px;
        text-align: center;
    }
