ui/wunderfizzpanel.razor.scss
// DER WUNDERFIZZ MENU — proportions from the GMod original (sh_fizzmenu.lua).
//
// Its panel is 1024x512 and everything is placed in that space, so the same
// numbers are used here directly rather than reinvented. The original multiplies
// by (ScrW()/1920 + 1)/2; a fixed box centred by flex gets the same result with
// no scale factor to keep in step.

root
{
    position: absolute;
    width: 100%;
    height: 100%;
    align-items: center;
    justify-content: center;
}

.fizz
{
    width: 1024px;
    height: 512px;
    flex-direction: column;

    // ⛔ CENTRED BY HALF-SIZE NEGATIVE MARGINS, NOT BY THE PARENT'S FLEX. The
    // parent sets align-items and justify-content to center and it did NOT take —
    // the panel sat hard against the top-left corner. That is the THIRD time this
    // layout system has refused to centre a child through the parent (powerup
    // banner, twice), so this stops relying on it.
    //
    // 50% puts the box's TOP-LEFT at the middle of the screen; the negative
    // margins pull it back by half its own size, which lands its CENTRE there.
    // It works because the size is fixed and known — 1024x512 — and needs no
    // transform support.
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: -512px;
    margin-top: -256px;

    background-color: rgba( 10, 11, 14, 0.95 );
    border: 2px solid rgba( 235, 200, 100, 0.8 );

    font-family: Inter;
    color: rgba( 240, 240, 240, 1 );
}

// name (100, 20) 512x64
.name
{
    position: absolute;
    left: 100px;
    top: 20px;
    width: 512px;
    height: 64px;

    font-size: 40px;
    font-weight: 800;
    letter-spacing: 2px;
    color: rgba( 235, 200, 100, 1 );

    // ⛔ A HARD SHADOW, NOT A GLOW. This sits over a bright machine screen; an
    // offset black shadow keeps the letterforms readable where a soft glow does
    // not. Same reasoning as the powerup banner.
    text-shadow: 0px 3px 8px rgba( 0, 0, 0, 1 );
}

// desc (100, 72) 640x64
.desc
{
    position: absolute;
    left: 100px;
    top: 76px;
    // ⚠️ 640, NOT THE ORIGINAL'S 860 (2026-10-05): the price block under the top-right corner is three lines tall now, and a
    // long description ran under it. 640 stops 20px short of the block.
    width: 640px;
    height: 64px;

    font-size: 18px;
    color: rgba( 195, 195, 195, 1 );
}

// prices, top right where the original's cost line sat (784,36): the next perk's and the next extra slot's, each always a
// number (2026-10-05, the user: *"add the current perk price and perk slot price to the wunderfizz ui"*), and under them
// the status line that carries the refusals the cost line used to say instead of its number.
.prices
{
    position: absolute;
    left: 760px;
    top: 16px;
    width: 240px;
    flex-direction: column;
    align-items: flex-end;

    .price
    {
        height: 32px;
        flex-direction: row;
        align-items: center;
        justify-content: flex-end;
    }

    .label
    {
        font-size: 16px;
        color: rgba( 175, 175, 175, 1 );
        margin-right: 12px;
    }

    .value
    {
        font-size: 26px;
        font-weight: 700;
        color: rgba( 235, 200, 100, 1 );

        // ⚠️ RED, NOT REPLACED, when it cannot be paid for: the number is what the player needs in order to go and earn it.
        &.poor { color: rgba( 225, 110, 110, 1 ); }
    }

    // ⚠️ WORDS, NOT ONLY COLOUR, for a click that would buy nothing — owned, the machine refusing, no free slot, the
    // shortfall — so it never reads as the machine ignoring the click. Empty when the click would buy.
    .status
    {
        margin-top: 4px;
        font-size: 14px;
        text-align: right;
        color: rgba( 225, 110, 110, 1 );

        &.owned { color: rgba( 130, 220, 140, 1 ); }
    }
}

// icon grid from (100, 148), 64px cells, 24px gap, 72px rows
.grid
{
    position: absolute;
    left: 100px;
    top: 148px;
    width: 840px;
    height: 250px;

    flex-direction: row;
    flex-wrap: wrap;
    align-content: flex-start;
}

.slot
{
    width: 64px;
    height: 64px;
    margin-right: 24px;
    margin-bottom: 8px;

    align-items: center;
    justify-content: center;

    background-color: rgba( 255, 255, 255, 0.06 );
    border: 2px solid rgba( 255, 255, 255, 0.10 );

    &:hover { background-color: rgba( 255, 255, 255, 0.14 ); }

    // ⚠️ OWNED IS A GREEN TINT ON THE GREY, not a replacement for it — the slot
    // still reads as a slot and the icon is untouched. Declared BEFORE .on so a
    // selected owned perk still gets the gold frame; the later rule wins.
    &.owned
    {
        background-color: rgba( 80, 200, 90, 0.28 );
        border: 2px solid rgba( 90, 210, 100, 0.55 );
    }

    // ⚠️ Selection is a GOLD BORDER, matching the original's gold perk frame
    // (color_gold in sh_fizzmenu.lua) rather than a colour of my choosing.
    &.on
    {
        border: 2px solid rgba( 255, 230, 0, 1 );
        background-color: rgba( 255, 230, 0, 0.18 );
    }

    .icon
    {
        width: 56px;
        height: 56px;
    }
}

// close (108, 428) · points (860, 428)
.foot
{
    position: absolute;
    left: 100px;
    top: 428px;
    width: 840px;
    height: 40px;

    flex-direction: row;
    align-items: center;
    justify-content: space-between;

    .close
    {
        font-size: 16px;
        font-weight: 700;
        padding: 7px 22px;
        color: rgba( 18, 18, 18, 1 );
        background-color: rgba( 235, 200, 100, 1 );

        &:hover { background-color: rgba( 255, 225, 130, 1 ); }
    }

    // ⚠️ Reads as a BUTTON like CLOSE does — same padding and weight — but in the
    // machine's gold rather than CLOSE's filled block, so the paid action and the
    // exit are never mistaken for each other.
    .slotbuy
    {
        align-items: center;
        justify-content: center;

        font-size: 15px;
        font-weight: 700;
        letter-spacing: 1px;
        color: rgba( 235, 200, 100, 1 );

        padding: 7px 22px;
        border: 2px solid rgba( 235, 200, 100, 0.8 );
        background-color: rgba( 235, 200, 100, 0.12 );

        &:hover { background-color: rgba( 235, 200, 100, 0.28 ); }

        // ⚠️ Dimmed, NOT hidden, when it cannot be afforded — the price is the
        // thing the player needs to see in order to go and earn it.
        &.poor
        {
            border: 2px solid rgba( 225, 110, 110, 0.6 );
            background-color: rgba( 225, 110, 110, 0.10 );
            color: rgba( 225, 110, 110, 1 );
        }
    }

    .points
    {
        font-size: 28px;
        font-weight: 700;
        color: rgba( 235, 200, 100, 1 );
    }
}

// ═══════════════════════════════════════════════════════════════════════════
// THE AUGMENT SCREEN — proportions from the original (perks/sh_augments.lua).
//
// Its VGUI panel is 900x620 with 26px padding, a 96px header and a 54/46 column
// split. Converted to a fixed 1024x640 here so the width matches the perk grid's
// 1024 and the two modes do not jump size when you click through.
//
// ⚠️ EVERY ACCENT COLOUR IS SET INLINE FROM C#, not here. The screen is tinted with
// the perk's own colour (18 of them, straight out of sh_perks.lua) and a stylesheet
// cannot know which perk is open. What lives here is everything that does NOT change
// per perk.
// ═══════════════════════════════════════════════════════════════════════════

.augment
{
    // ⛔ CENTRED BY HALF-SIZE NEGATIVE MARGINS, exactly as .fizz is, and for the
    // documented reason: the parent's align-items/justify-content did NOT centre a
    // child here, three times. Do not "simplify" this back to flex centring.
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: -512px;
    margin-top: -320px;

    width: 1024px;
    height: 640px;
    flex-direction: column;
    padding: 26px;

    background-color: rgba( 14, 15, 20, 0.97 );
    border: 2px solid rgba( 255, 255, 255, 0.10 );

    font-family: Inter;
    color: rgba( 236, 238, 245, 1 );
}

// ── header ────────────────────────────────────────────────────────────────
.ahead
{
    width: 100%;
    height: 78px;
    flex-direction: row;
    align-items: center;

    // ⚠️ The separator is a bottom border on the HEADER rather than a spacer div,
    // so the accent underline the original draws under its header lands in the same
    // place without an extra element to keep in step.
    border-bottom: 2px solid rgba( 255, 255, 255, 0.10 );
    margin-bottom: 16px;

    .aicon
    {
        width: 58px;
        height: 58px;
        margin-right: 16px;
    }

    .atext
    {
        flex-direction: column;
        flex-grow: 1;
    }

    .atitle
    {
        font-size: 30px;
        font-weight: 700;
        letter-spacing: 1px;
        text-shadow: 0px 3px 8px rgba( 0, 0, 0, 1 );
    }

    .asub
    {
        font-size: 15px;
        color: rgba( 151, 157, 175, 1 );
    }

    .asalvage
    {
        flex-direction: column;
        align-items: flex-end;
        margin-right: 18px;

        .alabel
        {
            font-size: 12px;
            font-weight: 700;
            letter-spacing: 2px;
            color: rgba( 151, 157, 175, 1 );
        }

        // Gold, matching the salvage colour used on the survival HUD, so the number
        // reads as the same currency in both places.
        .avalue
        {
            font-size: 26px;
            font-weight: 700;
            color: rgba( 233, 197, 44, 1 );
        }
    }

    .aback
    {
        align-items: center;
        justify-content: center;

        font-size: 14px;
        font-weight: 700;
        letter-spacing: 1px;
        padding: 8px 18px;

        color: rgba( 200, 205, 220, 1 );
        background-color: rgba( 255, 255, 255, 0.06 );
        border: 2px solid rgba( 255, 255, 255, 0.14 );

        &:hover
        {
            background-color: rgba( 255, 255, 255, 0.16 );
            color: rgba( 245, 247, 255, 1 );
        }
    }
}

// ── body: rows left, detail right ─────────────────────────────────────────
.abody
{
    width: 100%;
    flex-grow: 1;
    flex-direction: row;
}

.acols
{
    width: 54%;
    flex-direction: column;
    margin-right: 18px;
}

.asect
{
    flex-direction: column;
    margin-bottom: 12px;
}

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

    .aname
    {
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 2px;
        color: rgba( 151, 157, 175, 1 );
        flex-grow: 1;
    }

    .apick
    {
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 1px;
        color: rgba( 98, 103, 120, 1 );
    }

    .apips
    {
        flex-direction: row;
        align-items: center;
        margin-right: 10px;
    }

    // ⚠️ FILLED MEANS TAKEN, hollow means available. The pips are the only thing on
    // screen that answers "can I still pick one" without reading the button, which
    // matters because the button only speaks about the row you clicked.
    .apip
    {
        width: 9px;
        height: 9px;
        border-radius: 5px;
        margin-left: 5px;
        background-color: rgba( 98, 103, 120, 1 );

        &.on { background-color: rgba( 233, 197, 44, 1 ); }
    }
}

.arow
{
    height: 40px;
    flex-direction: row;
    align-items: center;
    margin-bottom: 6px;

    background-color: rgba( 37, 41, 53, 1 );

    &:hover { background-color: rgba( 49, 54, 70, 1 ); }

    // ⚠️ EQUIPPED IS GOLD AND IS DECLARED FIRST so a selected equipped row still
    // takes the selection background from the later rule — the same ordering the
    // perk grid's .owned / .on pair depends on.
    &.owned
    {
        background-color: rgba( 50, 43, 17, 1 );

        .abadge   { color: rgba( 233, 197, 44, 1 ); }
        .arowname { color: rgba( 233, 197, 44, 1 ); }
    }

    &.on { background-color: rgba( 45, 51, 70, 1 ); }

    .astrip
    {
        width: 4px;
        height: 100%;
        margin-right: 12px;
    }

    .abadge
    {
        width: 34px;
        font-size: 15px;
        font-weight: 700;
        color: rgba( 151, 157, 175, 1 );
    }

    .arowname
    {
        font-size: 17px;
        color: rgba( 236, 238, 245, 1 );
    }
}

// ── detail pane ───────────────────────────────────────────────────────────
.adetail
{
    flex-grow: 1;
    flex-direction: column;
    padding: 18px;
    background-color: rgba( 29, 32, 42, 1 );

    .aempty
    {
        flex-grow: 1;
        flex-direction: column;
        align-items: center;
        justify-content: center;

        .e1 { font-size: 20px; color: rgba( 98, 103, 120, 1 ); }
        .e2 { font-size: 15px; color: rgba( 98, 103, 120, 1 ); margin-top: 6px; }
    }

    .dhead
    {
        flex-direction: row;
        align-items: center;
        margin-bottom: 14px;

        .dbadge
        {
            width: 48px;
            height: 26px;
            align-items: center;
            justify-content: center;
            margin-right: 12px;

            font-size: 15px;
            font-weight: 700;
            color: rgba( 236, 238, 245, 1 );
            background-color: rgba( 37, 41, 53, 1 );

            // ⚠️ A MAJOR'S BADGE IS FILLED WITH THE PERK COLOUR (set inline), so the
            // text has to go dark to stay readable on a bright fill — Banana Colada's
            // yellow and Stamin-Up's gold are both far too light for white text.
            &.major { color: rgba( 15, 15, 18, 1 ); }
        }

        .dtier
        {
            font-size: 12px;
            font-weight: 700;
            letter-spacing: 2px;
            color: rgba( 151, 157, 175, 1 );
        }
    }

    .dname
    {
        font-size: 22px;
        font-weight: 700;
        margin-bottom: 12px;
    }

    .ddesc
    {
        flex-grow: 1;
        font-size: 16px;
        line-height: 1.45;
        color: rgba( 175, 181, 198, 1 );
    }

    // ── the buy button ────────────────────────────────────────────────────
    .abuy
    {
        height: 46px;
        align-items: center;
        justify-content: center;
        margin-top: 14px;

        font-size: 18px;
        font-weight: 700;
        letter-spacing: 1px;

        color: rgba( 20, 18, 6, 1 );
        background-color: rgba( 233, 197, 44, 1 );

        &:hover { background-color: rgba( 245, 210, 60, 1 ); }

        // ⚠️ FOUR REFUSAL STATES, EACH ITS OWN COLOUR, because they need different
        // actions from the player: nothing selected (pick a row), already equipped
        // (pick another), slot full (you are done with this tier), too poor (go and
        // earn). One grey "disabled" look for all four would say only "no".
        &.none
        {
            color: rgba( 98, 103, 120, 1 );
            background-color: rgba( 37, 41, 53, 1 );
            &:hover { background-color: rgba( 37, 41, 53, 1 ); }
        }

        &.owned
        {
            color: rgba( 74, 200, 122, 1 );
            background-color: rgba( 24, 44, 30, 1 );
            &:hover { background-color: rgba( 24, 44, 30, 1 ); }
        }

        &.full
        {
            color: rgba( 214, 92, 82, 1 );
            background-color: rgba( 44, 26, 24, 1 );
            &:hover { background-color: rgba( 44, 26, 24, 1 ); }
        }

        // ⚠️ Still shows the PRICE, dimmed — the number is the thing the player needs
        // in order to know how much salvage to go and earn.
        &.poor
        {
            color: rgba( 120, 100, 40, 1 );
            background-color: rgba( 46, 41, 20, 1 );
            &:hover { background-color: rgba( 46, 41, 20, 1 ); }
        }
    }
}

// ── footer ────────────────────────────────────────────────────────────────
.afoot
{
    width: 100%;
    height: 40px;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    margin-top: 16px;

    .close
    {
        font-size: 16px;
        font-weight: 700;
        padding: 7px 22px;
        color: rgba( 18, 18, 18, 1 );
        background-color: rgba( 235, 200, 100, 1 );

        &:hover { background-color: rgba( 255, 225, 130, 1 ); }
    }

    // Deliberately quiet — it is a standing disclaimer, not a warning to act on.
    .anote
    {
        font-size: 13px;
        font-style: italic;
        color: rgba( 98, 103, 120, 1 );
    }
}

// ═══ BASALT (`HudTheme`) — the map's face, Cinzel on every word of the machine ═══
//
// *"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. `.adetail .ddesc` keeps its own 1.45.
// ⛔ 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.
.theme-basalt,
.theme-basalt .fizz,
.theme-basalt .augment
{
    font-family: Cinzel;
    line-height: 0.898;
}

// ═══ BASALT (`HudTheme`) — the Wunderfizz in the HUD's stone, bone and ember ════════════════════════════════════════════════════
//
// *"Stone-dark panels, bone text, ember accents on selected and affordable items, and one white light strip"* — the user's pick
// (2026-09-27). ⛔ COLOURS ONLY: no border added or removed, no size or spacing touched, so nothing here can move. Every rule
// names the theme and the box, a class deeper than the rule it recolours, and each state and hover is restated, so none
// depends on where it sits in the file. The meanings stay: ember is what you can buy or have picked, jade is owned (and
// salvage, as on the HUD), rust is what you cannot afford.
$stone: rgba( 46, 42, 37, 0.9 );
$stone-hi: rgba( 92, 83, 72, 1 );
$stone-lo: rgba( 17, 14, 11, 1 );
$groove: rgba( 15, 12, 9, 0.95 );
$bone: rgba( 228, 217, 195, 1 );
$bone-dim: rgba( 160, 148, 130, 1 );
$ember: rgba( 222, 108, 46, 1 );
$ember-hot: rgba( 248, 150, 72, 1 );
$lite: rgba( 234, 246, 255, 1 );
$gold: rgba( 226, 204, 158, 1 );
$jade: rgba( 96, 170, 120, 1 );
$rust: rgba( 196, 86, 60, 1 );

// ── the perk grid ──
.theme-basalt .fizz
{
    background-color: rgba( 20, 17, 14, 0.96 );
    border-color: $stone-hi;
    border-right-color: $stone-lo;
    border-bottom-color: $lite;          // the light strip along its foot, as the HUD's
    color: $bone;

    .name { color: $ember-hot; }
    .desc { color: rgba( 200, 190, 172, 1 ); }
    .prices .label { color: $bone-dim; }
    .prices .value { color: $gold; }
    .prices .value.poor { color: $rust; }
    .prices .status { color: $rust; }
    .prices .status.owned { color: $jade; }

    .slot
    {
        background-color: rgba( 15, 12, 9, 0.6 );
        border-color: rgba( 92, 83, 72, 0.7 );
    }
    .slot:hover { background-color: rgba( 92, 83, 72, 0.35 ); }
    .slot.owned
    {
        background-color: rgba( 96, 170, 120, 0.22 );
        border-color: rgba( 96, 170, 120, 0.6 );
    }
    .slot.on
    {
        border-color: $ember-hot;
        background-color: rgba( 222, 108, 46, 0.2 );
    }

    .foot .close
    {
        color: $stone-lo;
        background-color: $ember;
    }
    .foot .close:hover { background-color: $ember-hot; }

    .foot .slotbuy
    {
        color: $ember-hot;
        border-color: rgba( 222, 108, 46, 0.8 );
        background-color: rgba( 222, 108, 46, 0.12 );
    }
    .foot .slotbuy:hover { background-color: rgba( 222, 108, 46, 0.28 ); }
    .foot .slotbuy.poor
    {
        border-color: rgba( 196, 86, 60, 0.55 );
        background-color: rgba( 196, 86, 60, 0.1 );
        color: $rust;
    }

    .foot .points { color: $gold; }
}

// ── the augment screen ──
.theme-basalt .augment
{
    background-color: rgba( 20, 17, 14, 0.97 );
    border-color: $stone-hi;
    border-right-color: $stone-lo;
    border-bottom-color: $lite;
    color: $bone;

    .ahead { border-bottom-color: rgba( 234, 246, 255, 0.55 ); }    // the light strip under its header
    .ahead .asub { color: $bone-dim; }
    .ahead .asalvage .alabel { color: $bone-dim; }
    .ahead .asalvage .avalue { color: $jade; }

    .ahead .aback
    {
        color: $bone;
        background-color: rgba( 92, 83, 72, 0.25 );
        border-color: rgba( 92, 83, 72, 0.8 );
    }
    .ahead .aback:hover
    {
        background-color: rgba( 92, 83, 72, 0.45 );
        color: rgba( 245, 238, 225, 1 );
    }

    .alabelrow .aname { color: $bone-dim; }
    .alabelrow .apick { color: rgba( 120, 110, 95, 1 ); }
    .alabelrow .apip { background-color: $stone-hi; }
    .alabelrow .apip.on { background-color: $ember; }

    .arow { background-color: rgba( 38, 33, 28, 1 ); }
    .arow:hover { background-color: rgba( 52, 46, 39, 1 ); }
    .arow.owned { background-color: rgba( 58, 36, 20, 1 ); }
    .arow.owned .abadge, .arow.owned .arowname { color: $ember-hot; }
    .arow.on { background-color: rgba( 64, 54, 44, 1 ); }
    .arow .abadge { color: $bone-dim; }
    .arow .arowname { color: $bone; }

    .adetail { background-color: rgba( 28, 24, 20, 1 ); }
    .adetail .dhead .dbadge
    {
        color: $bone;
        background-color: rgba( 38, 33, 28, 1 );
    }
    .adetail .dhead .dbadge.major { color: rgba( 15, 15, 18, 1 ); }    // ⚠️ its fill is the perk's colour, set inline
    .adetail .dhead .dtier { color: $bone-dim; }
    .adetail .ddesc { color: rgba( 200, 190, 172, 1 ); }

    .adetail .abuy
    {
        color: $stone-lo;
        background-color: $ember;
    }
    .adetail .abuy:hover { background-color: $ember-hot; }
    .adetail .abuy.none, .adetail .abuy.none:hover
    {
        color: rgba( 120, 110, 95, 1 );
        background-color: rgba( 38, 33, 28, 1 );
    }
    .adetail .abuy.owned, .adetail .abuy.owned:hover
    {
        color: $jade;
        background-color: rgba( 24, 36, 28, 1 );
    }
    .adetail .abuy.full, .adetail .abuy.full:hover
    {
        color: $rust;
        background-color: rgba( 44, 26, 20, 1 );
    }
    .adetail .abuy.poor, .adetail .abuy.poor:hover
    {
        color: rgba( 150, 105, 60, 1 );
        background-color: rgba( 46, 34, 22, 1 );
    }

    .afoot .close
    {
        color: $stone-lo;
        background-color: $ember;
    }
    .afoot .close:hover { background-color: $ember-hot; }
    .afoot .anote { color: rgba( 120, 110, 95, 1 ); }
}