ui/arsenalpanel.razor.scss
// THE ARSENAL — the four-tab shell.
//
// ⛔ SIZED IN PERCENTAGES AND CENTRED BY ITS OWN INSETS. It was a fixed 1100x620
// box relying on the parent's `align-items: center`, and it sat hard against the
// top-left — the FOURTH time this layout system has refused to centre a child
// through its parent. WunderfizzPanel.scss records the first three (itself, and the
// powerup banner twice) and works around it with half-size negative margins.
//
// ⚠️ THE NEGATIVE-MARGIN TRICK IS NOT USED HERE, deliberately: it needs a KNOWN
// fixed size, and a percentage `margin-top` resolves against the parent's WIDTH, not
// its height — so it cannot centre a percentage-sized box vertically without being
// silently wrong on any non-square screen.
//
// The insets centre it arithmetically instead: left 5% + width 90% leaves 5% either
// side, top 7% + height 86% leaves 7% above and below. No flex centring, no negative
// margins, no transform support needed — and it cannot overflow, which was the
// actual cause of the pinning: 620px was TALLER than the 613px viewport it was being
// asked to centre inside.
root
{
position: absolute;
width: 100%;
height: 100%;
}
.arsenal
{
position: absolute;
left: 5%;
top: 7%;
width: 90%;
height: 86%;
flex-direction: column;
align-items: center;
background-color: rgba( 8, 9, 12, 0.94 );
border: 2px solid rgba( 255, 255, 255, 0.14 );
border-radius: 4px;
font-family: Inter, system-ui, sans-serif;
color: rgba( 235, 235, 235, 0.95 );
}
.title
{
margin-top: 26px;
font-size: 52px;
font-weight: 700;
letter-spacing: 8px;
color: rgba( 255, 190, 70, 0.95 );
text-shadow: 0px 2px 8px rgba( 0, 0, 0, 0.9 );
}
// ── tabs ────────────────────────────────────────────────────────────────────
.tabs
{
flex-direction: row;
width: 94%;
margin-top: 26px;
gap: 18px;
}
// ⚠️ flex-grow, NOT a fixed width. Four 250px tabs plus gaps need 1060px, which
// overflowed the box on a narrow window — part of what pushed the panel off-centre.
// Growing into whatever is available cannot overflow at any size.
.tab
{
flex-grow: 1;
height: 54px;
align-items: center;
justify-content: center;
font-size: 22px;
font-weight: 600;
letter-spacing: 1px;
background-color: rgba( 255, 255, 255, 0.05 );
border: 2px solid rgba( 255, 255, 255, 0.12 );
color: rgba( 235, 235, 235, 0.7 );
&:hover
{
background-color: rgba( 255, 255, 255, 0.10 );
color: rgba( 255, 255, 255, 0.95 );
}
}
// The open tab. Gold, matching the title.
.tab.on
{
background-color: rgba( 255, 190, 70, 0.16 );
border-color: rgba( 255, 190, 70, 0.75 );
color: rgba( 255, 215, 130, 1 );
}
// ⚠️ DIMMED, NOT DISABLED. An unbuilt tab still opens and still says why it is
// empty — a tab that refuses to click reads as broken, and the point of showing all
// four is that the shape of the finished machine is visible while it fills in.
//
// ⛔ `border-style: dashed` WAS HERE AND NEVER WORKED. s&box logs
// "dashed is not valid with border-style" and drops the declaration, so the dashed
// edge these two rules were written for has never once been drawn — the tabs were
// only ever dimmed. It went unnoticed because dim alone looks deliberate, and because
// the warning only surfaces when the stylesheet is recompiled.
//
// Replaced with a FAINTER BORDER, which is supported and carries the same meaning.
// A silently-dropped property is worse than a plainer one that works.
.tab.todo
{
color: rgba( 235, 235, 235, 0.42 );
border-color: rgba( 255, 255, 255, 0.06 );
}
.tab.todo.on
{
color: rgba( 255, 215, 130, 0.85 );
border-color: rgba( 255, 190, 70, 0.35 );
}
// ── page body ───────────────────────────────────────────────────────────────
// ⛔ `flex-direction: column` IS LOAD-BEARING AND WAS MISSING. Without it this
// container laid its children out as a ROW, so on any page with more than one child the
// second sat BESIDE the first instead of under it — the weapon name ended up stranded in
// a narrow column down the left edge with the node list squeezed beside it, and the
// squeeze is what made the tier bands overflow into each other.
//
// ⚠️ Every other flex container in this stylesheet states its direction explicitly.
// This one relied on a default, and the default is not the one CSS uses.
.content
{
width: 94%;
flex-grow: 1;
margin-top: 26px;
flex-direction: column;
align-items: center;
justify-content: center;
}
// ── armor cards ───────────────────────────────────────────────
.cards
{
flex-direction: row;
justify-content: center;
align-items: center;
gap: 40px;
}
// ⚠️ A FIXED CARD, unlike the tabs. The original's are 260x340 and their tall
// portrait shape is what makes them read as cards rather than buttons — letting them
// flex-grow would stretch three of them into wide panels on a big screen. Three at
// 260 plus gaps is 900, which fits inside the 90%-wide box at any sane resolution.
.card
{
width: 260px;
height: 340px;
flex-direction: column;
align-items: center;
background-color: rgba( 255, 255, 255, 0.04 );
border: 2px solid rgba( 255, 255, 255, 0.12 );
border-radius: 3px;
}
.kind
{
margin-top: 26px;
font-size: 16px;
font-weight: 600;
letter-spacing: 2px;
color: rgba( 235, 235, 235, 0.55 );
}
.tier
{
margin-top: 14px;
font-size: 46px;
font-weight: 700;
letter-spacing: 2px;
color: rgba( 255, 225, 170, 0.95 );
}
.hp
{
margin-top: 12px;
font-size: 22px;
font-weight: 600;
color: rgba( 235, 235, 235, 0.6 );
}
// ⛔ PUSHED DOWN BY margin-top:auto, NOT POSITIONED ABSOLUTELY. It was
// `position: absolute; bottom: 26px` and it escaped the card completely — all three
// costs rendered in a row along the bottom of the PANEL, beside the CLOSE button.
//
// The reason: in this layout system an absolutely-positioned child anchors to the
// nearest ancestor that is ITSELF positioned, and `.card` was not — so they resolved
// against `.arsenal`. WunderfizzPanel's absolute children work only because `.fizz`
// is `position: absolute` itself.
//
// Auto margin in a flex column does the same job with nothing to anchor to, so it
// cannot come loose. This layout system has already refused to centre a child through
// its parent four times; giving it fewer chances is the cheaper fix.
.cost
{
margin-top: auto;
margin-bottom: 24px;
flex-direction: row;
align-items: center;
gap: 9px;
// A green diamond, the same shape and colour as the salvage pickup's outline and
// the HUD counter — so the currency is recognisable without the word.
.coin
{
width: 13px;
height: 13px;
background-color: rgba( 60, 210, 90, 0.95 );
transform: rotate( 45deg );
}
.amount
{
font-size: 26px;
font-weight: 700;
color: rgba( 255, 255, 255, 0.95 );
}
}
// ⚠️ ONLY THE BUYABLE CARD REACTS TO THE CURSOR. A hover on a locked or owned
// card would say "click me" about something that refuses, which is the same lie the
// overlay exists to prevent.
.card.buyable
{
border-color: rgba( 255, 190, 70, 0.55 );
&:hover
{
background-color: rgba( 255, 190, 70, 0.13 );
border-color: rgba( 255, 190, 70, 0.9 );
}
}
// ⛔ A FLOW LABEL, NOT A COVERING BOX. The original draws its status as an overlay
// across the whole card; an absolutely-positioned one here broke loose exactly as the
// cost did, leaving stray "LOCKED" text across the tier name and one card shaded
// differently from its neighbour in the same state.
//
// So the status sits in the card's own column, and the DIMMING moves onto the card
// itself — which reads the same and cannot be mispositioned.
.status
{
margin-top: 10px;
font-size: 22px;
font-weight: 700;
letter-spacing: 3px;
}
// Colours from the original: owned green, locked grey, unaffordable red.
.card.owned .status { color: rgba( 120, 220, 140, 1 ); }
.card.locked .status { color: rgba( 140, 140, 140, 1 ); }
.card.poor .status { color: rgba( 215, 120, 120, 1 ); }
// The dimming the overlay used to provide, applied to the card so every card in the
// same state looks the same.
.card.owned,
.card.locked,
.card.poor
{
background-color: rgba( 255, 255, 255, 0.02 );
.kind, .tier, .hp { opacity: 0.42; }
.cost { opacity: 0.42; }
}
// Owned is a success, not a refusal — it keeps a green edge rather than reading as
// another thing you cannot have.
.card.owned
{
border-color: rgba( 120, 220, 140, 0.45 );
}
// ── ammo type page ────────────────────────────────────────────────────────────
//
// ⛔ SEVEN CARDS, NOT FIVE, AND THAT IS WHAT SETS THE SIZE. The rarity page's own
// note records the trap: five 260px cards overflowed the 90%-wide panel and pinned it to
// the top-left. Seven is worse — six mods plus RANDOM. At 168 wide with an 18px gap
// that is 7x168 + 6x18 = 1284, which still fits; at rarity's 196 it would be 1480 and
// would not.
//
// ⚠️ THE CARDS ARE ALSO TALLER, because each carries a badge and a sentence of
// description that neither of the other pages has. 316 tall with that content clipped the
// blurb.
.cards.ammo
{
gap: 18px;
.card
{
width: 168px;
height: 352px;
}
// ⚠️ SMALL, because "RADIOACTIVE DECAY" is seventeen characters in a 168px
// card. The rarity page dropped to 26px for nine; this needs less again, and the
// names WRAP rather than being truncated — a clipped mod name is unreadable
// and there is vertical room for two lines.
.tier
{
margin-top: 10px;
font-size: 15px;
letter-spacing: 1px;
text-align: center;
width: 90%;
}
// The chance/cooldown line.
.hp
{
margin-top: 8px;
font-size: 16px;
}
// ⚠️ THE `kind` LABEL IS SHRUNK AND ITS TOP MARGIN CUT. At 26px of margin
// (the shared value) plus a badge plus a wrapped name plus a blurb, the foot ran off
// the bottom of the card.
.kind
{
margin-top: 12px;
font-size: 12px;
letter-spacing: 1px;
}
}
// The upstream badge, the same image the HUD shows beside the weapon name.
//
// ⚠️ NOT `Additive` OR TINTED HERE, unlike the HUD's copy: on the HUD the badge
// dims to show a cooldown, but on a shop card the only question is which mod this is, and
// a dimmed icon there would read as the card being disabled.
.cards.ammo .badge
{
width: 62px;
height: 62px;
margin-top: 10px;
}
// The one-sentence description. The only wrapped prose on any Arsenal card.
.cards.ammo .blurb
{
margin-top: 10px;
width: 86%;
font-size: 13px;
text-align: center;
color: rgba( 225, 225, 225, 0.6 );
}
// ⛔ THE UNWIRED WARNING, AND IT IS DELIBERATELY LOUD. Four of the six mods roll,
// show their badge on the HUD and do nothing at all. A card that looked identical to a
// working one would be selling 500 salvage of nothing, so this says so before the click
// rather than after — the same argument the unbuilt TABS make about themselves.
.cards.ammo .nofx
{
margin-top: 8px;
font-size: 11px;
font-weight: 700;
letter-spacing: 1px;
color: rgba( 235, 170, 90, 0.95 );
}
// ⚠️ THE SAME `.foot` WRAPPER TREATMENT AS THE RARITY CARD, and for the identical
// reason its note gives: a fitted card shows no price, so the auto margin has to live on
// the wrapper. Declaring it on both `.cost` and `.status` SPLITS the slack rather than
// falling back.
.cards.ammo .card .foot
{
margin-top: auto;
margin-bottom: 16px;
flex-direction: column;
align-items: center;
gap: 6px;
.cost
{
margin-top: 0px;
}
}
// FITTED is this page's "you are here", the same role EQUIPPED plays on the rarity
// ladder — so it borrows that styling rather than inventing a second colour for the
// same idea.
.card.fitted
{
border-color: rgba( 255, 190, 70, 0.75 );
background-color: rgba( 255, 190, 70, 0.07 );
.status { color: rgba( 255, 215, 130, 1 ); }
}
// The RANDOM card — no badge, no blurb, so it needs to read as deliberate rather
// than as a card that failed to load. A dashed border does that; it is the one card that
// is not a specific product.
//
// ⛔ `justify-content: center` WAS HERE AND COULD NEVER HAVE WORKED. The shared
// `.cards.ammo .card .foot` rule puts `margin-top: auto` on the foot, and an auto margin
// absorbs ALL the free space — so there is none left for the container to centre
// with, and the rest of the card stays pinned to the top. It rendered top-aligned while
// the stylesheet claimed otherwise. Removed rather than fought: top-aligned content with
// the price at the bottom is what every other card on the page does, so matching them is
// both simpler and more consistent than making this one card special.
//
// ⚠️ THE PADDING REPLACES IT, pushing the three lines down to roughly where the
// other cards' badges sit, so the row of names lines up across all seven.
.card.ammo-random
{
border-style: dashed;
.kind { margin-top: 44px; }
.tier { font-size: 22px; }
.hp { opacity: 0.7; }
}
// ── ammo type page: the grid and the detail panel (2026-10-04) ─────────────────────────────────────────
//
// ⛔ THE USER'S LAYOUT: "all the ammo mods in 5 rows of 4 on the left, jsut the icons and name / and when i click one the
// right side shows me the mod and what it does including cooldown and chance, and a button to buy". RANDOM plus 19 mods is
// 20 tiles, so the grid is exactly full. The `.cards.ammo` rules above drew the old row of cards and no longer match
// anything.
//
// ⚠️ SIZED TO FILL THE PAGE (2026-10-04, the user: "we can make everyhing a bit bigger to fill the scree mor"): five 92-tall
// rows with four 10px gaps are 500 (520 if the borders count), which with the weapon's name above it leaves about 30px
// before CLOSE on the user's 16:9-ish window. The tiles wrap inside a fixed-width box, since this layout system has no
// grid, and the panel stretches to the grid's height.
.ammopage
{
flex-direction: row;
align-items: stretch;
gap: 30px;
}
// ⛔ NEVER AN EXACT FIT. 424 (4 x 100 + 3 x 8) wrapped at three a row on the user's screen: the UI scale's rounding, or
// the 2px borders if they count toward a tile's width, pushed the fourth tile down. 580 holds four 128s either way
// (4 x 132 + 30 = 558) and can't hold five (680). `justify-content: center` splits the spare width on both sides of a row.
.ammogrid
{
width: 580px;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
gap: 10px;
}
.atile
{
width: 128px;
height: 92px;
flex-direction: column;
align-items: center;
background-color: rgba( 255, 255, 255, 0.04 );
border: 2px solid rgba( 255, 255, 255, 0.12 );
border-radius: 3px;
.aicon
{
width: 54px;
height: 54px;
margin-top: 7px;
}
// ⚠️ SMALL, AND IT WRAPS: "RADIOACTIVE DECAY" takes two lines in a 128px tile.
//
// ⛔ `justify-content: center` AS WELL AS `text-align`. The text is a child box sized to itself and sitting at the start
// of this one, so `text-align` alone centred the lines on each other and left the block hard against the tile's left
// edge (2026-10-04, the user's screenshot).
.aname
{
margin-top: 4px;
width: 94%;
justify-content: center;
font-size: 12px;
font-weight: 700;
letter-spacing: 1px;
text-align: center;
color: rgba( 255, 225, 170, 0.9 );
}
&:hover
{
background-color: rgba( 255, 190, 70, 0.1 );
border-color: rgba( 255, 190, 70, 0.6 );
}
}
// The one on the gun: green, like owned things elsewhere.
.atile.fitted
{
border-color: rgba( 96, 200, 120, 0.85 );
}
// The one being looked at. After `.fitted`, so a selected tile always shows as selected.
.atile.on
{
background-color: rgba( 255, 190, 70, 0.14 );
border-color: rgba( 255, 190, 70, 0.95 );
}
// Designed, not built: dimmed, but still clickable to read about.
.atile.soon
{
opacity: 0.45;
}
// RANDOM's mark, until it has an icon of its own.
.ricon
{
width: 54px;
height: 54px;
margin-top: 7px;
align-items: center;
justify-content: center;
font-size: 38px;
font-weight: 700;
color: rgba( 255, 190, 70, 0.9 );
border: 2px solid rgba( 255, 190, 70, 0.5 );
border-radius: 6px;
}
// ⚠️ NO HEIGHT OF ITS OWN: `.ammopage` stretches it to the grid's, so the two always end level.
//
// ⚠️ PADDING 16, NOT 22, SINCE 2026-10-06: five upgrade rows in the height three had (the ladder's note, below).
.ammodetail
{
width: 600px;
flex-direction: column;
align-items: center;
padding: 16px 26px;
background-color: rgba( 255, 255, 255, 0.04 );
border: 2px solid rgba( 255, 255, 255, 0.12 );
border-radius: 3px;
.dicon
{
width: 140px;
height: 140px;
}
.ricon.big
{
width: 140px;
height: 140px;
margin-top: 0px;
font-size: 90px;
}
.dname
{
margin-top: 12px;
font-size: 32px;
font-weight: 700;
letter-spacing: 3px;
color: rgba( 255, 225, 170, 0.95 );
}
.drows
{
margin-top: 16px;
width: 100%;
flex-direction: column;
gap: 7px;
}
.drow
{
flex-direction: row;
justify-content: space-between;
.k
{
font-size: 15px;
font-weight: 700;
letter-spacing: 2px;
color: rgba( 235, 235, 235, 0.45 );
}
.v
{
font-size: 18px;
font-weight: 600;
color: rgba( 235, 235, 235, 0.92 );
}
}
.ddesc
{
margin-top: 16px;
width: 100%;
font-size: 18px;
text-align: center;
color: rgba( 225, 225, 225, 0.75 );
}
.dsoon
{
margin-top: 10px;
font-size: 14px;
font-weight: 700;
letter-spacing: 2px;
color: rgba( 235, 170, 90, 0.95 );
}
// ⚠️ THE PRICE AND THE BUTTON SIT AT THE FOOT (`margin-top: auto`), where every Arsenal card keeps its price. The
// shared `.cost` carries its own auto margin and a bottom margin; both are taken off here, inside the row.
//
// ⚠️ A SIZE DOWN SINCE 2026-10-06 (30 → 26, the button 22 → 20 and 10 → 8 of padding), for the five upgrade rows above it.
.dbuy
{
margin-top: auto;
flex-direction: row;
align-items: center;
gap: 24px;
.cost
{
margin-top: 0px;
margin-bottom: 0px;
.coin
{
width: 15px;
height: 15px;
}
.amount
{
font-size: 26px;
}
}
}
.buy
{
padding: 8px 30px;
font-size: 20px;
font-weight: 700;
letter-spacing: 3px;
border: 2px solid rgba( 255, 255, 255, 0.2 );
border-radius: 3px;
color: rgba( 235, 235, 235, 0.5 );
}
.buy.buyable
{
border-color: rgba( 255, 190, 70, 0.8 );
color: rgba( 255, 210, 120, 1 );
&:hover
{
background-color: rgba( 255, 190, 70, 0.18 );
border-color: rgba( 255, 190, 70, 1 );
}
}
.buy.fitted
{
border-color: rgba( 96, 200, 120, 0.7 );
color: rgba( 130, 220, 150, 1 );
}
.buy.poor
{
color: rgba( 220, 110, 90, 0.95 );
}
}
// ── the ammo page's mod header and upgrades (2026-10-05) ──────────────────────────────────────────────
//
// ⛔ THE ICON MOVED BESIDE THE NAME, AND THE PANEL GREW 40px (THE GAP GAVE 10 OF IT), FOR THE UPGRADES. Stacked, the 140px icon,
// the name, three rows and the blurb already took about 450 of the panel's 500, the grid's height, which the panel must not
// pass: `.ammopage` would grow and push CLOSE off the screen. Side by side they take about 100, and the three upgrade rows
// about 160. 580 + 30 + 600 still fits a 4:3 screen, as 580 + 40 + 560 did.
//
// ⚠️ EVERY EFFECT LINE IS WRITTEN SHORT (`AmmoModUpgrades.All`) so a row stays one line in Inter. Cinzel, basalt's face, is wider
// and wraps a few to two; the panel has room for that, not for three-line rows.
//
// ⛔ FIVE ROWS SINCE 2026-10-06 (IV and V), IN THE SAME 500. At the sizes above they came to about 550, past the grid, so every
// part of the panel gave a little: its padding (22 → 16), the header's name and rows, the blurb, the ladder's gaps, each row's
// padding (5 → 3) and type, the buy button. Worked from Inter's line box, 1.211 of the size, which basalt pins Cinzel to: padding
// and border 36, header 89, blurb 44 (two lines), ladder 257 (its head and five rows of 42), button 44 — about 470, which leaves
// room for an effect line or two wrapping in Cinzel (16 each). ⚠️ COMPUTED, NOT SEEN: open a mod at IV or V in both faces and look.
.ammodetail
{
.dhead
{
width: 100%;
flex-direction: row;
align-items: center;
gap: 18px;
.dicon
{
width: 84px;
height: 84px;
flex-shrink: 0;
}
.dname
{
margin-top: 0px;
font-size: 26px;
}
.drows
{
margin-top: 4px;
gap: 1px;
}
.drow .k { font-size: 12px; }
.drow .v { font-size: 14px; }
}
.dtitle
{
flex-grow: 1;
flex-shrink: 1;
flex-direction: column;
}
.ddesc.tight
{
margin-top: 8px;
font-size: 15px;
}
// The ladder. Owned is green, the next level gold and clickable, the later ones dim: the armor cards' meanings, in rows.
.dups
{
margin-top: 8px;
margin-bottom: 6px;
width: 100%;
flex-direction: column;
gap: 4px;
}
.uhead
{
flex-direction: row;
justify-content: space-between;
align-items: center;
.ulabel
{
font-size: 13px;
font-weight: 700;
letter-spacing: 3px;
color: rgba( 235, 235, 235, 0.45 );
}
.unote
{
font-size: 12px;
letter-spacing: 1px;
color: rgba( 235, 235, 235, 0.35 );
}
}
// ⚠️ 3px OF PADDING AND A POINT OFF THE TYPE SINCE 2026-10-06 (the note above): a row is 42 tall, its effect line kept at 13.
.uprow
{
flex-direction: row;
align-items: center;
gap: 10px;
padding: 3px 8px;
background-color: rgba( 255, 255, 255, 0.03 );
border: 2px solid rgba( 255, 255, 255, 0.1 );
border-radius: 3px;
.unum
{
width: 34px;
flex-shrink: 0;
justify-content: center;
font-size: 18px;
font-weight: 700;
color: rgba( 255, 225, 170, 0.55 );
}
.ubody
{
flex-grow: 1;
flex-shrink: 1;
flex-direction: column;
}
.uname
{
flex-direction: row;
align-items: center;
gap: 8px;
}
.un
{
font-size: 13px;
font-weight: 700;
letter-spacing: 1px;
color: rgba( 255, 225, 170, 0.92 );
}
.usoon
{
font-size: 10px;
font-weight: 700;
letter-spacing: 1px;
color: rgba( 235, 170, 90, 0.9 );
}
.ueff
{
font-size: 13px;
color: rgba( 225, 225, 225, 0.72 );
}
// ⚠️ THE SHARED `.cost` CARRIES AN AUTO MARGIN AND A BOTTOM MARGIN, as `.dbuy` notes; both are taken off here.
.uside
{
width: 88px;
flex-shrink: 0;
flex-direction: column;
align-items: flex-end;
.cost
{
margin-top: 0px;
margin-bottom: 0px;
.coin
{
width: 11px;
height: 11px;
}
// ⚠️ 15, NOT 17 (2026-10-06): the row's height, and V's "10,000" is a figure wider than III's "3,000".
.amount
{
font-size: 15px;
}
}
}
.ustate
{
font-size: 10px;
font-weight: 700;
letter-spacing: 1px;
color: rgba( 235, 235, 235, 0.45 );
}
}
.uprow.owned
{
border-color: rgba( 96, 200, 120, 0.55 );
.unum, .ustate { color: rgba( 130, 220, 150, 1 ); }
}
.uprow.buyable
{
border-color: rgba( 255, 190, 70, 0.75 );
background-color: rgba( 255, 190, 70, 0.07 );
.unum, .ustate { color: rgba( 255, 210, 120, 1 ); }
&:hover
{
background-color: rgba( 255, 190, 70, 0.18 );
border-color: rgba( 255, 190, 70, 1 );
}
}
.uprow.poor .ustate { color: rgba( 220, 110, 90, 0.95 ); }
// A level that needs the one before it first: dim, as a designed mod's tile is.
.uprow.locked { opacity: 0.5; }
}
// A mod's upgrade level on its grid tile: a pip a level in the top corner, once it has a level.
//
// ⛔ THE TILE IS POSITIONED SO THE PIPS ANCHOR TO IT. In this layout an absolute child anchors to the nearest ancestor that is
// ITSELF positioned (`.cost`'s note): without this rule all nineteen tiles' pips would stack in a corner of `.arsenal`.
// Scoreboard's `.pip` and the HUD's `.boot` anchor their pieces the same way.
//
// ⚠️ FIVE PIPS SINCE 2026-10-06 (IV and V), 7px with 2px between where three were 8px with 3: a row 43 wide, where five of the
// old ones would be 52 and reach well over the 54px icon, which starts 37 from the tile's edge. These still touch its corner.
.atile
{
position: relative;
}
.atile .apips
{
position: absolute;
top: 5px;
right: 6px;
flex-direction: row;
gap: 2px;
.pip
{
width: 7px;
height: 7px;
border-radius: 4px;
background-color: rgba( 255, 255, 255, 0.12 );
border: 1px solid rgba( 255, 190, 70, 0.5 );
}
.pip.on
{
background-color: rgba( 255, 200, 90, 1 );
}
}
// ── weapon rarity page ───────────────────────────────────────
// The gun this page is about, above the ladder.
//
// ⚠️ `.content` is `justify-content: center`, so this and the card row share the
// vertical middle rather than this sitting at the top. That is deliberate: the subject
// and its ladder read as one block.
.subject
{
flex-direction: column;
align-items: center;
margin-bottom: 22px;
.wep
{
font-size: 30px;
font-weight: 700;
letter-spacing: 3px;
color: rgba( 255, 190, 70, 0.9 );
}
// The current tier. Colour comes INLINE from Rarity.HexFor — no colour here.
.cur
{
margin-top: 6px;
font-size: 21px;
font-weight: 700;
letter-spacing: 3px;
}
}
// ⛔ FIVE CARDS, NARROWER THAN ARMOR'S THREE. The armor row is 3x260 + 2x40 gaps =
// 860. Five at that size would be 1460 and would overflow the 90%-wide panel on any
// normal window — the exact overflow that pinned this panel to the top-left the first
// time (see the header note). 5x196 + 4x24 = 1076, which fits.
//
// ⚠️ STILL FIXED, NOT flex-grow, for the same reason armor's are: the tall portrait
// shape is what makes them read as cards rather than buttons.
.cards.rarity
{
gap: 24px;
.card
{
width: 196px;
height: 316px;
}
// Smaller than armor's 46px — "LEGENDARY" is nine characters in a 196px card.
.tier
{
margin-top: 12px;
font-size: 26px;
letter-spacing: 1px;
}
.hp
{
margin-top: 10px;
font-size: 19px;
}
}
// ⚠️ SIX CARDS ONCE BASALT'S EASTER EGG IS COMPLETE — Godly's too. At five's size six would be
// 6x196 + 5x24 = 1296 and overflow a narrow window; narrower cards and gaps keep the row to
// 6x172 + 5x16 = 1112, about what five took.
.cards.rarity.six
{
gap: 16px;
.card
{
width: 172px;
}
.tier
{
font-size: 23px;
}
}
// The solid colour bar from the original — what makes the ladder readable without
// reading five words. Colour is inline.
.band
{
width: 78%;
height: 8px;
margin-top: 16px;
border-radius: 2px;
}
// ⛔ THE ONLY margin-top:auto ON THE RARITY CARD. See the razor note: the armor card
// can put it on `.cost` because a cost is always drawn, but a rarity card at or below
// the current tier has no price, and declaring it on both `.cost` and `.status` would
// SPLIT the free space instead of falling back.
.cards.rarity .card .foot
{
margin-top: auto;
margin-bottom: 18px;
flex-direction: column;
align-items: center;
gap: 8px;
// Overrides the shared `.cost` rule, whose own auto margin would otherwise fight
// the wrapper's for the same slack.
.cost
{
margin-top: 0px;
margin-bottom: 0px;
}
.status
{
margin-top: 0px;
font-size: 18px;
letter-spacing: 2px;
}
}
// EQUIPPED is the state armor has no equivalent of — it is not a purchase, it is where
// the weapon currently sits. Bordered in the tier's own colour would need inline style
// on the card; a warm neutral says "you are here" without a second colour source.
.card.equipped
{
border-color: rgba( 255, 190, 70, 0.75 );
background-color: rgba( 255, 190, 70, 0.07 );
.status { color: rgba( 255, 215, 130, 1 ); }
}
// ⚠️ NOT DIMMED, unlike owned/locked/poor. The equipped card is the one true
// statement on the page about the gun in your hands; dimming it would bury it among
// the tiers you cannot have.
// ── weapon tech page ─────────────────────────────────────────
// ⛔ ONE TIER AT A TIME, WHICH IS WHY NOTHING HERE SCROLLS ANY MORE. Two earlier
// attempts failed for the same underlying reason and both are worth recording:
//
// 1. A WRAPPING GRID of 41 small cards. `flex-wrap` did not grow its container, so
// tier 4's second row of cards drew straight over the tier 5 header.
// 2. FULL-WIDTH ROWS for all 41 at once. Flex children SHRINK below their stated
// height when the container cannot fit them, so `height: 44px` became about 10px
// and all seven rows of tier 1 drew on top of each other. `overflow-y: scroll` did
// not save it — the content had already been compressed to fit rather than
// overflowing.
//
// The lesson is the same both times: this layout engine solves an over-full container by
// squashing children, not by overflowing them. So the fix is to stop over-filling it —
// 11 rows is the most any tier holds, and that fits at a readable size.
// ⚠️ `flex-shrink: 0` ON THE ROWS AND THE BAND regardless, so if a tier ever grows past
// the space the rows keep their height and the band overflows visibly instead of silently
// collapsing into an unreadable stack. A layout that breaks loudly is debuggable.
.subject
{
// stays a column: weapon name, then the tier selector under it
flex-shrink: 0;
}
// Tier selector — five small buttons.
.tierpick
{
flex-direction: row;
justify-content: center;
margin-top: 8px;
gap: 8px;
.tbtn
{
width: 56px;
height: 40px;
align-items: center;
justify-content: center;
font-size: 22px;
font-weight: 700;
background-color: rgba( 255, 255, 255, 0.05 );
border: 2px solid rgba( 255, 255, 255, 0.12 );
color: rgba( 235, 235, 235, 0.7 );
&:hover
{
background-color: rgba( 255, 255, 255, 0.12 );
color: rgba( 255, 255, 255, 0.95 );
}
}
// The tier being viewed.
.tbtn.on
{
background-color: rgba( 255, 190, 70, 0.18 );
border-color: rgba( 255, 190, 70, 0.8 );
color: rgba( 255, 215, 130, 1 );
}
}
// ⚠️ `flex-grow: 1` SO THE BAND OWNS WHATEVER HEIGHT IS LEFT under the subject, and
// `align-self: stretch` because `.content` centres its children — without it a tall tier
// would be centred and clipped at BOTH ends, with the top unreachable.
//
// ⚠️ `.content` keeps `justify-content: center`, which is right for the armor page's
// three cards. This page does not depend on it: a flex-grow child absorbs the free space
// either way, so the two pages can disagree about vertical alignment without fighting.
.tierband
{
width: 100%;
flex-grow: 1;
align-self: stretch;
flex-direction: column;
margin-top: 14px;
padding: 12px 14px;
background-color: rgba( 255, 255, 255, 0.02 );
border-left: 4px solid rgba( 255, 190, 70, 0.55 );
}
// ⛔ THE ROWS SCROLL, THE HEADER DOES NOT. Tiers 1-3 hold 5-7 rows and never scroll;
// tiers 4 and 5 hold 11 and scroll a little. Scrolling the whole band would take the
// PICK count — the one number that explains why a row says TIER FULL — off screen
// exactly when a player is scrolling to find something to buy.
//
// ⚠️ This only works because the rows carry `flex-shrink: 0`. Without it the engine
// solves an over-full container by COMPRESSING children rather than overflowing them, so
// eleven 42px rows silently became eleven 10px rows drawn on top of each other and the
// scrollbar never appeared. That failure is what this whole page was rebuilt to escape.
.technodes
{
width: 100%;
flex-direction: column;
flex-grow: 1;
overflow-y: scroll;
}
.tierhead
{
flex-direction: row;
align-items: baseline;
flex-shrink: 0;
margin-bottom: 12px;
.tnum
{
margin-right: 12px;
font-size: 34px;
font-weight: 700;
letter-spacing: 2px;
color: rgba( 255, 190, 70, 0.95 );
}
.tname
{
font-size: 34px;
font-weight: 700;
letter-spacing: 2px;
color: rgba( 255, 235, 200, 0.85 );
}
// ⚠️ `margin-left: auto` ON THE FIRST OF THE TRAILING PAIR ONLY. Two auto margins
// split the slack between them and strand the pick count mid-header — the failure
// WeaponStatsPanel's `.wclass` note records from a three-child header.
.tpick
{
margin-left: auto;
margin-right: 20px;
font-size: 27px;
font-weight: 700;
color: rgba( 120, 220, 140, 0.95 );
}
.tcost
{
font-size: 23px;
color: rgba( 235, 235, 235, 0.5 );
}
}
// One row per node.
// ⚠️ SCALED 1.5x FROM 42px, which is what lets the type be this size — the row height
// was the constraint, not the font. Every dimension moved together so the proportions
// hold: 42->63 tall, 20->30 name, 18->27 effect, 17->25 state.
//
// ⚠️ 63px x 11 ROWS IS 693px, SO TIERS 4 AND 5 NOW ALWAYS SCROLL. That is the trade
// this size buys and it is fine — the scroll works properly now that the rows carry
// `flex-shrink: 0`. Tiers 1-3 at 5-7 rows still fit without scrolling.
.technode
{
width: 100%;
flex-direction: row;
align-items: center;
flex-shrink: 0;
height: 63px;
padding: 0px 21px;
margin-bottom: 9px;
background-color: rgba( 255, 255, 255, 0.04 );
border: 2px solid rgba( 255, 255, 255, 0.10 );
border-radius: 3px;
// Fixed, so every name starts on the same column and the list scans vertically.
.nname
{
width: 340px;
flex-shrink: 0;
font-size: 30px;
font-weight: 700;
letter-spacing: 1px;
color: rgba( 255, 235, 200, 0.95 );
}
// ⚠️ ALLOWED TO WRAP TO A SECOND LINE. At 27px the longest effect strings —
// Railgun's and Chimera's are both ~86 characters — need more width than the row
// has left after a 340px name and a 180px state column. Two lines of 27px is 54px,
// which still fits inside 63px, so a wrap costs nothing; forcing one line would clip
// exactly the nodes whose text matters most.
.neffect
{
flex-grow: 1;
font-size: 27px;
color: rgba( 235, 235, 235, 0.75 );
}
// ⚠️ FIXED WIDTH AND ALWAYS RENDERED, even when empty. A label that only exists
// sometimes lets the effect text reflow between rows, so buyable rows end up a
// different length from owned ones and the column wanders down the list.
.nstate
{
width: 180px;
flex-shrink: 0;
text-align: right;
font-size: 25px;
font-weight: 700;
letter-spacing: 2px;
}
}
// ⚠️ ONLY A BUYABLE ROW REACTS TO THE CURSOR — a hover on something that refuses is
// the same lie the state label exists to prevent.
.technode.buyable
{
border-color: rgba( 255, 190, 70, 0.55 );
&:hover
{
background-color: rgba( 255, 190, 70, 0.13 );
border-color: rgba( 255, 190, 70, 0.9 );
}
}
.technode.owned
{
border-color: rgba( 120, 220, 140, 0.45 );
.nstate { color: rgba( 120, 220, 140, 1 ); }
}
.technode.poor .nstate { color: rgba( 215, 120, 120, 1 ); }
.technode.full .nstate { color: rgba( 235, 190, 110, 1 ); }
.technode.locked .nstate { color: rgba( 140, 140, 140, 1 ); }
// ⛔ THE NON-CLASS AUGMENTS EACH HAVE A COLOUR (the user, 2026-10-04): fire mode (action) blue, clip
// size (magazine) purple, shell load (one round at a time) orange. A thick left edge and a tinted name,
// so the card's state border (buyable, owned) still reads. Restated in the basalt block, whose
// `.technode .nname` would otherwise win on specificity.
.technode.set-action { border-left: 6px solid rgba( 90, 160, 255, 0.95 ); }
.technode.set-action .nname { color: rgba( 150, 200, 255, 1 ); }
.technode.set-mag { border-left: 6px solid rgba( 175, 110, 255, 0.95 ); }
.technode.set-mag .nname { color: rgba( 210, 170, 255, 1 ); }
.technode.set-reload { border-left: 6px solid rgba( 255, 150, 50, 0.95 ); }
.technode.set-reload .nname { color: rgba( 255, 190, 120, 1 ); }
// Dimmed for every state you cannot act on. Owned is excluded — it is a success, not a
// refusal.
.technode.locked,
.technode.full,
.technode.poor
{
background-color: rgba( 255, 255, 255, 0.015 );
.nname, .neffect { opacity: 0.45; }
}
.placeholder
{
flex-direction: column;
align-items: center;
gap: 12px;
.head
{
font-size: 38px;
font-weight: 700;
letter-spacing: 3px;
color: rgba( 235, 235, 235, 0.55 );
}
.line
{
font-size: 22px;
color: rgba( 235, 235, 235, 0.75 );
text-align: center;
}
// The explanation of WHY it is empty — quieter than the statement that it is.
.line.dim
{
max-width: 860px;
font-size: 17px;
color: rgba( 235, 235, 235, 0.45 );
}
}
// The one tab with a system behind it reads warmer, so "not built yet" and
// "blocked on a missing system" are visibly different states.
.placeholder.ready .head
{
color: rgba( 255, 190, 70, 0.7 );
}
// ── footer ──────────────────────────────────────────────────────────────────
.foot
{
width: 94%;
height: 70px;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.close
{
width: 180px;
height: 44px;
align-items: center;
justify-content: center;
font-size: 19px;
font-weight: 600;
letter-spacing: 2px;
background-color: rgba( 255, 255, 255, 0.06 );
border: 2px solid rgba( 255, 255, 255, 0.16 );
color: rgba( 235, 235, 235, 0.85 );
&:hover
{
background-color: rgba( 220, 60, 50, 0.20 );
border-color: rgba( 220, 60, 50, 0.8 );
color: rgba( 255, 255, 255, 1 );
}
}
// Green, matching the salvage counter on the HUD and the outline on the pickup, so
// the currency reads as one thing across all three places it appears.
.salvage
{
flex-direction: row;
align-items: baseline;
gap: 8px;
.amount
{
font-size: 30px;
font-weight: 700;
color: rgba( 60, 210, 90, 0.95 );
}
.label
{
font-size: 15px;
font-weight: 600;
letter-spacing: 2px;
color: rgba( 235, 235, 235, 0.45 );
}
}
// The tech page's "right-click to take it off" line (ArsenalMenu.TechNote). Quiet, like the
// Wunderfizz's `.anote`: it is a standing instruction, not a warning to act on. It may shrink
// and wrap, so CLOSE and the salvage counter on either side keep their size.
.fnote
{
flex-shrink: 1;
padding: 0px 24px;
text-align: center;
font-size: 14px;
font-style: italic;
color: rgba( 235, 235, 235, 0.45 );
}
// ═══ 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.
// ⛔ 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 .arsenal
{
font-family: Cinzel;
line-height: 0.898;
}
// ═══ BASALT (`HudTheme`) — the Arsenal 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 );
.theme-basalt .arsenal
{
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;
.title { color: $ember-hot; }
// ── the tabs ──
.tab
{
background-color: rgba( 92, 83, 72, 0.18 );
border-color: rgba( 92, 83, 72, 0.8 );
color: $bone-dim;
}
.tab:hover
{
background-color: rgba( 92, 83, 72, 0.35 );
color: $bone;
}
.tab.on
{
background-color: rgba( 222, 108, 46, 0.18 );
border-color: rgba( 222, 108, 46, 0.8 );
color: $ember-hot;
}
.tab.todo
{
color: rgba( 160, 148, 130, 0.5 );
border-color: rgba( 92, 83, 72, 0.35 );
}
.tab.todo.on
{
color: rgba( 248, 150, 72, 0.8 );
border-color: rgba( 222, 108, 46, 0.4 );
}
// ── the cards: armor, rarity, ammo ──
.card
{
background-color: rgba( 15, 12, 9, 0.5 );
border-color: rgba( 92, 83, 72, 0.7 );
}
.kind { color: $bone-dim; }
.tier { color: $gold; }
.hp { color: $bone-dim; }
.cost .coin { background-color: $jade; }
.cost .amount { color: $bone; }
.card.buyable { border-color: rgba( 222, 108, 46, 0.6 ); }
.card.buyable:hover
{
background-color: rgba( 222, 108, 46, 0.14 );
border-color: rgba( 248, 150, 72, 0.95 );
}
.card.owned .status { color: rgba( 110, 190, 140, 1 ); }
.card.locked .status { color: rgba( 120, 110, 95, 1 ); }
.card.poor .status { color: $rust; }
.card.owned, .card.locked, .card.poor { background-color: rgba( 15, 12, 9, 0.35 ); }
.card.owned { border-color: rgba( 96, 170, 120, 0.5 ); }
.cards.ammo .blurb { color: rgba( 200, 190, 172, 0.75 ); }
.cards.ammo .nofx { color: $ember-hot; }
.card.fitted, .card.equipped
{
border-color: rgba( 222, 108, 46, 0.8 );
background-color: rgba( 222, 108, 46, 0.08 );
}
.card.fitted .status, .card.equipped .status { color: $ember-hot; }
.subject .wep { color: $ember-hot; }
// ── the ammo page's grid and detail panel (2026-10-04) ──
.atile { background-color: rgba( 15, 12, 9, 0.5 ); border-color: rgba( 92, 83, 72, 0.7 ); }
.atile:hover { background-color: rgba( 222, 108, 46, 0.12 ); border-color: rgba( 248, 150, 72, 0.8 ); }
.atile .aname { color: $gold; }
.atile.fitted { border-color: rgba( 96, 170, 120, 0.85 ); }
.atile.on { background-color: rgba( 222, 108, 46, 0.16 ); border-color: rgba( 248, 150, 72, 0.95 ); }
.ricon { color: $ember-hot; border-color: rgba( 222, 108, 46, 0.6 ); }
.ammodetail { background-color: rgba( 15, 12, 9, 0.5 ); border-color: rgba( 92, 83, 72, 0.7 ); }
.ammodetail .dname { color: $gold; }
.ammodetail .drow .k { color: $bone-dim; }
.ammodetail .drow .v { color: $bone; }
.ammodetail .ddesc { color: rgba( 200, 190, 172, 0.8 ); }
.ammodetail .dsoon { color: $ember-hot; }
.ammodetail .buy { border-color: rgba( 92, 83, 72, 0.8 ); color: $bone-dim; }
.ammodetail .buy.buyable { border-color: rgba( 222, 108, 46, 0.8 ); color: $ember-hot; }
.ammodetail .buy.buyable:hover { background-color: rgba( 222, 108, 46, 0.18 ); border-color: $ember-hot; }
.ammodetail .buy.fitted { border-color: rgba( 96, 170, 120, 0.7 ); color: $jade; }
.ammodetail .buy.poor { color: $rust; }
// ── the ammo page's upgrades (2026-10-05) ──
.atile .apips .pip { background-color: rgba( 15, 12, 9, 0.8 ); border-color: rgba( 222, 108, 46, 0.55 ); }
.atile .apips .pip.on { background-color: $ember-hot; }
.ammodetail .uhead .ulabel { color: $bone-dim; }
.ammodetail .uhead .unote { color: $bone-dim; }
.ammodetail .uprow { background-color: rgba( 15, 12, 9, 0.35 ); border-color: rgba( 92, 83, 72, 0.7 ); }
.ammodetail .uprow .unum { color: $bone-dim; }
.ammodetail .uprow .un { color: $gold; }
.ammodetail .uprow .ueff { color: rgba( 200, 190, 172, 0.8 ); }
.ammodetail .uprow .usoon { color: $ember-hot; }
.ammodetail .uprow .ustate { color: $bone-dim; }
.ammodetail .uprow.owned { border-color: rgba( 96, 170, 120, 0.6 ); }
.ammodetail .uprow.owned .unum, .ammodetail .uprow.owned .ustate { color: $jade; }
.ammodetail .uprow.buyable { background-color: rgba( 222, 108, 46, 0.08 ); border-color: rgba( 222, 108, 46, 0.8 ); }
.ammodetail .uprow.buyable .unum, .ammodetail .uprow.buyable .ustate { color: $ember-hot; }
.ammodetail .uprow.buyable:hover { background-color: rgba( 222, 108, 46, 0.18 ); border-color: $ember-hot; }
.ammodetail .uprow.poor .ustate { color: $rust; }
// ── the tech tree ──
.tierpick .tbtn
{
background-color: rgba( 92, 83, 72, 0.18 );
border-color: rgba( 92, 83, 72, 0.8 );
color: $bone-dim;
}
.tierpick .tbtn:hover
{
background-color: rgba( 92, 83, 72, 0.35 );
color: $bone;
}
.tierpick .tbtn.on
{
background-color: rgba( 222, 108, 46, 0.2 );
border-color: rgba( 222, 108, 46, 0.85 );
color: $ember-hot;
}
.tierband
{
background-color: rgba( 15, 12, 9, 0.35 );
border-left-color: rgba( 222, 108, 46, 0.6 );
}
.tierhead .tnum { color: $ember-hot; }
.tierhead .tname { color: $bone; }
.tierhead .tpick { color: $jade; }
.tierhead .tcost { color: $bone-dim; }
.technode
{
background-color: rgba( 15, 12, 9, 0.5 );
border-color: rgba( 92, 83, 72, 0.6 );
}
.technode .nname { color: $bone; }
.technode .neffect { color: rgba( 200, 190, 172, 0.85 ); }
.technode.buyable { border-color: rgba( 222, 108, 46, 0.6 ); }
.technode.buyable:hover
{
background-color: rgba( 222, 108, 46, 0.14 );
border-color: rgba( 248, 150, 72, 0.95 );
}
.technode.owned { border-color: rgba( 96, 170, 120, 0.5 ); }
.technode.owned .nstate { color: $jade; }
.technode.poor .nstate { color: $rust; }
.technode.full .nstate { color: $gold; }
.technode.locked .nstate { color: rgba( 120, 110, 95, 1 ); }
.technode.locked, .technode.full, .technode.poor { background-color: rgba( 15, 12, 9, 0.3 ); }
// the set colours, restated for basalt (see the default section)
.technode.set-action { border-left: 6px solid rgba( 90, 160, 255, 0.95 ); }
.technode.set-action .nname { color: rgba( 150, 200, 255, 1 ); }
.technode.set-mag { border-left: 6px solid rgba( 175, 110, 255, 0.95 ); }
.technode.set-mag .nname { color: rgba( 210, 170, 255, 1 ); }
.technode.set-reload { border-left: 6px solid rgba( 255, 150, 50, 0.95 ); }
.technode.set-reload .nname { color: rgba( 255, 190, 120, 1 ); }
// ── the empty pages, the close, the wallet ──
.placeholder .head { color: $bone-dim; }
.placeholder .line { color: rgba( 200, 190, 172, 0.85 ); }
.placeholder .line.dim { color: rgba( 160, 148, 130, 0.6 ); }
.placeholder.ready .head { color: rgba( 248, 150, 72, 0.8 ); }
.close
{
background-color: rgba( 92, 83, 72, 0.2 );
border-color: rgba( 92, 83, 72, 0.8 );
color: $bone;
}
.close:hover
{
background-color: rgba( 222, 108, 46, 0.22 );
border-color: rgba( 248, 150, 72, 0.9 );
color: rgba( 255, 240, 225, 1 );
}
.salvage .amount { color: $jade; }
.salvage .label { color: $bone-dim; }
.fnote { color: $bone-dim; }
}