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 ); }
}