ui/scoreboard.razor.scss
// SCOREBOARD — held on TAB.
//
// ⚠️ COOL GREY ON BLACK, not the blood red of DownedHud. That panel is an emergency and shouts;
// this is a glance at a table mid-round and must not read as damage.

// ⛔ TWO COLUMNS (the user's layout, 2026-09-29: *"score on the left, map on the right, zombies left on the top, and current
// Easter egg step bellow the score"*): the score with the Easter egg's own panel under it, and the map beside them. On a map
// without a TAB map the right column is not drawn and the left one centres, as the board always did. The zombies left are
// RoundBarHud's, above it all.
.scoreboard {
    position: absolute;
    width: 100%;
    height: 100%;
    pointer-events: none;
    flex-direction: row;
    align-items: flex-start;
    justify-content: center;
    padding: 90px 40px 0px 40px;
    font-family: Inter;

    // ⛔ NOT `display: none`. A hidden panel with zero opacity keeps its layout, so the table does
    // not reflow on the frame TAB goes down — which showed as a visible snap on the first press.
    &.hidden {
        opacity: 0;
    }
}

// The left column: the score, then the Easter egg's panel
.side {
    flex-direction: column;
    flex-shrink: 0;
}

.board {
    flex-direction: column;
    background-color: rgba(8, 10, 12, 0.88);
    border: 1px solid rgba(255, 255, 255, 0.09);
    border-radius: 4px;
    padding: 18px 22px 20px;
}

// ── title ───────────────────────────────────────────────────────────────────

.head {
    flex-direction: row;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 14px;
    padding-bottom: 10px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);

    .title {
        font-size: 22px;
        font-weight: 700;
        letter-spacing: 3px;
        color: rgba(235, 240, 245, 1);
    }

    .round {
        font-size: 14px;
        letter-spacing: 2px;
        color: rgba(150, 160, 172, 1);
    }
}

// ── rows ────────────────────────────────────────────────────────────────────

.row {
    flex-direction: row;
    align-items: center;
    height: 32px;

    // ⚠️ The local player is marked, not moved to the top. The order is the standing — pinning
    // yourself first would hide whether you are actually winning.
    &.me {
        background-color: rgba(90, 140, 190, 0.14);
    }

    &.hdr {
        height: 26px;
        color: rgba(140, 150, 162, 1);
        font-size: 11.5px;
        letter-spacing: 0.8px;
        text-transform: uppercase;

        // ⛔ ON THE CELLS, NOT ONLY THE ROW (2026-10-05): *"The score columns are overlapping a bit in their names"*. `.c` sets
        // its own 16 px and near-white, and a rule on the element itself beats a value inherited from the row, so the headers
        // were drawn at 16 px. There "HEADSHOTS" and "POINTS EARNED" are wider than their columns and ran into the one beside
        // them (measured with the real fonts: HEADSHOTS 105 px in Inter and 113 px in basalt's Cinzel, in a 96 px column). At the
        // 11.5 px meant here every header fits, with 12 px or more to spare in both faces.
        .c {
            font-size: 11.5px;
            color: rgba(140, 150, 162, 1);
        }
    }
}

.c {
    font-size: 16px;
    color: rgba(224, 230, 236, 1);
    padding: 0 10px;
    white-space: nowrap;

    // ⚠️ Digits line up column to column. Without tabular figures the numbers jitter sideways as
    // they tick, which on a table this dense reads as the whole panel shifting.
    font-variant-numeric: tabular-nums;
}

// ⚠️ NARROWED FOR THE MAP BESIDE IT (2026-09-29): 240 / 128 / 172 were 1,052 wide; 190 / 96 / 136 are 806, and "Headshots" and
// "Points earned" still fit their headers in basalt's wider Cinzel (measured at 11.5 px).
.name {
    width: 190px;
    justify-content: flex-start;
    text-align: left;
}

// ⛔ `justify-content`, NOT `text-align` ALONE. These cells are flex boxes holding a label, so the
// label is a CHILD — text-align sets how the glyphs sit inside the label, which is already exactly
// its own width, and the label itself stayed pinned left. On screen every number read as
// left-aligned despite the rule being there.
.num {
    width: 96px;
    justify-content: flex-end;
    text-align: right;
}

// ⚠️ Widened because "Points earned" and "Headshots" WRAPPED at the old width — the header came out
// as "HEADSHO / TS". `white-space: nowrap` above stops the wrap; this makes room for it.
.wide {
    width: 136px;
}

.empty {
    padding: 18px 4px;
    color: rgba(140, 150, 162, 1);
    font-size: 14px;
}

// ── the Easter egg, its own panel under the score ───────────────────────────
//
// ⛔ THE MAIN STEP, THEN ITS LITTLE STEPS (the user, 2026-09-29: *"I want the steps to be divided in main step, and the little
// steps to complete it"*): the step's name in ember; each little step with its mark — ticked when done, a lit diamond on the one
// on now, a ring on the rest — and its count where it keeps one; nine hexes for the nine main steps. A panel like the score's, so
// its head is `.head`; basalt's Cinzel reaches it from the root.

.egg-card {
    margin-top: 24px;

    .egg-name {
        font-size: 21px;
        letter-spacing: 1.5px;
        color: rgba(248, 150, 72, 1);
        text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.9);
        margin-bottom: 8px;
        white-space: nowrap;
    }

    .little {
        flex-direction: row;
        align-items: center;
        height: 30px;
        padding: 0px 12px 0px 6px;

        .mark {
            width: 22px;
            height: 22px;
            margin-right: 12px;
            align-items: center;
            justify-content: center;
        }

        // a ring, for a step still to come
        .glyph {
            width: 10px;
            height: 10px;
            border: 2px solid rgba(96, 103, 112, 1);
            border-radius: 5px;
        }

        .text {
            font-size: 16px;
            letter-spacing: 0.6px;
            color: rgba(96, 103, 112, 1);
            white-space: nowrap;
        }

        .count {
            margin-left: auto;
            padding-left: 16px;
            font-size: 16px;
            letter-spacing: 1px;
            color: rgba(248, 150, 72, 1);
            white-space: nowrap;
        }

        // done: a tick (two sides of a box, turned), in Color Smash's green
        &.done {
            .glyph {
                width: 7px;
                height: 13px;
                margin-top: -4px;
                border-width: 0px;
                border-radius: 0px;
                border-right-width: 3px;
                border-bottom-width: 3px;
                border-right-color: rgba(126, 196, 122, 1);
                border-bottom-color: rgba(126, 196, 122, 1);
                transform: rotate(45deg);
            }

            .text {
                color: rgba(140, 150, 162, 1);
            }
        }

        // the one on now: a lit diamond, and the row warmed
        &.now {
            background-color: rgba(248, 150, 72, 0.09);

            .glyph {
                border-width: 0px;
                border-radius: 0px;
                background-color: rgba(248, 150, 72, 1);
                transform: rotate(45deg);
            }

            .text {
                color: rgba(235, 240, 245, 1);
            }
        }
    }

    // the nine main steps, a hex each — ⚠️ THREE BARS TURNED 0, 60 AND -60 DEGREES MAKE ONE: a panel has no hexagon of its own
    .pips {
        flex-direction: row;
        margin-top: 14px;
        padding-left: 6px;
    }

    .pip {
        position: relative;
        width: 16px;
        height: 16px;
        margin-right: 8px;

        .h {
            position: absolute;
            left: 1px;
            top: 4px;
            width: 14px;
            height: 8px;
            background-color: rgba(70, 75, 82, 1);
        }

        .b {
            transform: rotate(60deg);
        }

        .c {
            transform: rotate(-60deg);
        }

        &.done .h {
            background-color: rgba(228, 217, 195, 1);
        }

        &.now .h {
            background-color: rgba(248, 150, 72, 1);
        }
    }
}

// ── the map of the whole place (`TabMap`), the right column ────────────────
//
// ⚠️ A PANEL LIKE THE SCORE'S, taking the width the left column leaves (`flex-grow`). `TabMap.Fit` sizes the picture's frame in it
// from code: as wide as the panel, and shorter if the screen runs out. The picture is the walkable ground (`basalt_map.py
// --game`); the room names and the players are panels on it, placed from code in percent of the picture.

.map-card {
    margin-left: 24px;
    flex-grow: 1;
}

.tabmap {
    flex-direction: column;
    align-items: center;

    &.none {
        display: none;
    }

    .frame {
        position: relative;
        background-size: contain;
        background-repeat: no-repeat;
        border: 1px solid rgba(255, 255, 255, 0.09);
        border-radius: 3px;
        overflow: hidden;
    }

    // A room's name, centred on its place, in the picture's own ember
    .room {
        position: absolute;
        transform: translateX(-50%) translateY(-50%);
        font-size: 13px;
        font-weight: 700;
        letter-spacing: 1.5px;
        white-space: nowrap;
        color: rgba(248, 150, 72, 0.95);
        text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.95);
    }

    // ⛔ A PLAYER, POINTING THE WAY THEY LOOK (*"all players can be seen on the map directionally"*): a dot and a nose, centred on
    // where they stand by the margins; the turn is set from code (`TabMap.Face`). Teammates in the tags' blue. YOU BIGGER AND
    // WHITE (*"the player sees themselves as bigger on the map"*).
    .marker {
        position: absolute;
        width: 18px;
        height: 18px;
        margin-left: -9px;
        margin-top: -9px;
        align-items: center;
        justify-content: center;

        .dot {
            width: 10px;
            height: 10px;
            border-radius: 5px;
            background-color: rgba(150, 215, 255, 1);
            border: 1.5px solid rgba(0, 0, 0, 0.85);
        }

        // ⚠️ A SQUARE TURNED 45°, NOT A GLYPH (`PlayerTagsHud`'s reason): the nose, along +x until turned, under the dot
        .nose {
            position: absolute;
            left: 12px;
            top: 5.5px;
            width: 7px;
            height: 7px;
            background-color: rgba(150, 215, 255, 1);
            border: 1px solid rgba(0, 0, 0, 0.8);
            transform: rotate(45deg);
        }

        .name {
            position: absolute;
            left: 21px;
            top: 0px;
            font-size: 12px;
            font-weight: 700;
            white-space: nowrap;
            color: rgba(150, 215, 255, 0.97);
            text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.9);
        }

        // You: over half as big again, white, and no name
        &.me {
            width: 28px;
            height: 28px;
            margin-left: -14px;
            margin-top: -14px;

            .dot {
                width: 16px;
                height: 16px;
                border-radius: 8px;
                border-width: 2px;
                background-color: rgba(255, 255, 255, 1);
            }

            .nose {
                left: 19px;
                top: 8.5px;
                width: 11px;
                height: 11px;
                background-color: rgba(255, 255, 255, 1);
            }

            .name {
                display: none;
            }
        }

        // Down: red, the revive badge's own
        &.down {
            .dot {
                background-color: rgba(255, 112, 100, 0.98);
            }

            .nose {
                background-color: rgba(255, 112, 100, 0.98);
            }

            .name {
                color: rgba(255, 112, 100, 0.98);
            }
        }
    }
}

// ═══ BASALT (`HudTheme`) — the map's face, Cinzel on the scoreboard ═══
//
// *"i want the font for this map to affect … all hud messages that appear on screen"* (2026-09-27). The root wears the theme's class; the rules name it and each box
// here that sets Inter itself.
// ⛔ ON INTER'S LINE BOX, so no row grows taller: 0.898 of Cinzel's own line, which is Inter's 1.211 of the size. See
// `.round` in SurvivalHud.razor.scss for why it is not 1.211. It is wider on mixed-case text, which it sets in small capitals. Cinzel-Bold is the one face shipped,
// so every weight draws bold.
.scoreboard.theme-basalt
{
    font-family: Cinzel;
    line-height: 0.898;
}