/* The script face of the logo and the venue names. Served from here, not from
   Google: inside OBS a font that is late or missing falls back to "cursive",
   which on Windows is Comic Sans. SIL OFL, licence beside the file. */
@font-face {
    font-family: 'Mr Dafoe';
    src: url('../fonts/MrDafoe-Regular.woff2') format('woff2');
    font-display: swap;
}
/* The home page's menu cards (owner's pick, 2026-10-02): Monoton for the
   neon numerals, Yellowtail for the script lines. Ours too, for the same
   reason; Monoton is OFL, Yellowtail Apache 2.0, licences beside the files. */
@font-face {
    font-family: 'Monoton';
    src: url('../fonts/Monoton-Regular.woff2') format('woff2');
    font-display: swap;
}
@font-face {
    font-family: 'Yellowtail';
    src: url('../fonts/Yellowtail-Regular.woff2') format('woff2');
    font-display: swap;
}

/* Stream Racers lab - shared chrome for the work-in-progress screens.
   Same visual language as the widget: dark plates, black strokes, hot pink
   accent, Jersey 10. Sprites reuse .car-rig / .wheel from ../style.css. */

:root {
    --hot: #ff2d95;
    --ink: #170e2e;
    --ink-2: #1f1438;
    --ink-3: #2a1c4a;
    --line: #3a2a62;
    --text: #f3e9ff;
    --dim: #a99bc9;
    --stroke: #000;
    --car-scale: 3;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: #120a24;
    color: var(--text);
    font-family: 'Jersey 10', 'Trebuchet MS', system-ui, sans-serif;
    -webkit-font-smoothing: antialiased;
}

img { image-rendering: pixelated; }

a { color: inherit; text-decoration: none; }

.wrap { max-width: 1180px; margin: 0 auto; padding: 20px 22px 60px; }

/* ===== top bar ===== */

.topbar {
    display: flex;
    align-items: center;
    gap: 14px;
    /* One header, everywhere. The race screens used to shrink it in career.css
       because their deck is height-locked to the viewport - which left the lab
       pages wearing a different, taller bar. The compact size is now simply the
       size, so there is one to maintain and one to look at. */
    padding: 7px 22px;
    background: var(--ink);
    border-bottom: 3px solid var(--stroke);
}

.brand {
    font-size: 24px;
    letter-spacing: 3px;
    text-shadow: 0 2px 0 var(--hot);
}
.brand small { display: block; font-size: 12px; letter-spacing: 3px; color: var(--dim); text-shadow: none; }

.nav { display: flex; gap: 8px; margin-left: 18px; }
.nav a {
    font-size: 18px; letter-spacing: 2px;
    padding: 2px 12px;
    border: 2px solid var(--line);
    border-radius: 8px;
    color: #c9bce3;
}
.nav a:hover { border-color: #5e4e8c; color: #fff; }
.nav a.on { background: var(--hot); border-color: var(--hot); color: #fff; }
/* The host's screen. Set apart on purpose: everything else in this bar is the
   viewer's, and one of these is not like the others. */
.nav a.studio { margin-left: 14px; border-color: #5a4614; color: #ffd23f; }
.nav a.studio:hover { border-color: #ffd23f; color: #ffd23f; }
.nav a.studio.on { background: #ffd23f; border-color: #ffd23f; color: #170e2e; }

.credits {
    margin-left: auto;
    display: flex; align-items: center; gap: 8px;
    padding: 4px 14px;
    background: var(--ink-3);
    border: 3px solid var(--stroke);
    border-radius: 10px;
    font-size: 26px;
    letter-spacing: 1px;
}
.credits b { color: #ffd23f; font-weight: normal; }
.credits span { font-size: 15px; color: var(--dim); letter-spacing: 2px; }

/* ===== headings ===== */

.section-head {
    display: flex; align-items: center; gap: 14px;
    margin: 26px 0 14px;
}
.section-head h2 { margin: 0; font-size: 32px; letter-spacing: 3px; font-weight: normal; }
.section-head .rule { flex: 1; height: 3px; background: var(--line); border-radius: 2px; }

/* ===== filter chips ===== */

.chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
    font-family: inherit; font-size: 19px; letter-spacing: 2px;
    padding: 3px 14px;
    border: 2px solid var(--line);
    border-radius: 8px;
    background: var(--ink-2);
    color: #c9bce3;
    cursor: pointer;
    white-space: nowrap;
}
.chip:hover { border-color: #5e4e8c; color: #fff; }
.chip.on { background: var(--hot); border-color: var(--hot); color: #fff; }

/* ===== car frame (shared sprite holder) ===== */

.car-frame { position: relative; overflow: visible; }
.car-frame .car-rig {
    position: absolute;
    left: 0; top: 0;
    transform-origin: top left;
    transform: scale(var(--car-scale));
}

/* ===== shop grid ===== */

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 16px;
}

.card {
    display: flex; flex-direction: column;
    background: var(--ink-2);
    border: 3px solid var(--stroke);
    border-radius: 14px;
    overflow: hidden;
}
.card.owned { border-color: #2f6b32; }

.card-stage {
    position: relative;
    height: 132px;
    display: flex; align-items: flex-end; justify-content: center;
    padding-bottom: 8px;
    background:
        radial-gradient(120% 90% at 50% 100%, var(--tier-glow, rgba(255, 45, 149, .16)), transparent 70%),
        linear-gradient(#20202a, #17171e);
}

/* Over the car, not under it: a card whose sprite has a tall wing was drawing
   the wing across its own date. */
.tier {
    position: absolute; left: 10px; top: 10px;
    z-index: 2;
    font-size: 15px; letter-spacing: 2px;
    padding: 1px 8px 0;
    border: 2px solid var(--stroke);
    border-radius: 6px;
    color: #170e2e;
    background: var(--tier);
}

.flag {
    position: absolute; right: 10px; top: 10px;
    z-index: 2;
    font-size: 15px; letter-spacing: 2px;
    color: var(--dim);
}

.card-body { padding: 8px 14px 12px; display: flex; flex-direction: column; gap: 8px; }
.card-name { font-size: 26px; letter-spacing: 1px; line-height: 1; }

/* two by two: four stats squeezed onto one row leave each cell too narrow for
   its label, its number and a readable bar */
.spec-row { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.spec {
    flex: 1;
    background: var(--ink-3);
    border-radius: 6px;
    padding: 3px 8px 4px;
}
.spec { position: relative; }
.spec i { display: block; font-style: normal; font-size: 13px; color: var(--dim); letter-spacing: 2px; }
.spec b {
    position: absolute; right: 8px; top: 1px;
    font-size: 17px; font-weight: normal; color: #d7cbef;
}
.card-note { font-size: 15px; letter-spacing: 1px; color: var(--dim); margin-top: -2px; }
.bar { height: 6px; background: #130b26; border-radius: 3px; overflow: hidden; margin-top: 3px; }
.bar u { display: block; height: 100%; background: var(--hot); }

.card-foot { display: flex; align-items: center; gap: 10px; margin-top: 2px; }
.price { font-size: 26px; color: #ffd23f; letter-spacing: 1px; }
.price.muted { color: var(--dim); }
/* A price is a number and gets 26px; a state is a phrase and does not - at the
   price size "NOT FOR SALE" ran into whatever sat beside it. */
.price.state { font-size: 19px; letter-spacing: 2px; color: var(--dim); }
.foot-need {
    margin-left: auto;
    font-size: 18px; letter-spacing: 2px;
    color: #a99bc9;
    border: 2px solid var(--line);
    border-radius: 8px;
    padding: 3px 10px;
}

.btn {
    font-family: inherit; font-size: 21px; letter-spacing: 2px;
    padding: 3px 16px;
    border: 3px solid var(--stroke);
    border-radius: 9px;
    background: var(--hot);
    color: #fff;
    cursor: pointer;
    margin-left: auto;
}
.btn:hover:not(:disabled) { filter: brightness(1.14); }
.btn:disabled { opacity: .4; cursor: not-allowed; }
.btn.ghost { background: var(--ink-3); color: #d4c8ec; }
.btn.go { background: #8bd427; color: #170e2e; }

/* ===== garage ===== */

/* Three columns rather than two: with every panel stacked on one side the
   right-hand pile ran to three times the height of the bay, and the space under
   the car was simply left empty. Splitting the panels across two narrower
   columns puts the bay, the cosmetics and the mechanicals at roughly the same
   height, and the race buttons go in the gap under the car where they belong. */
.garage {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px 320px;
    gap: 16px;
    align-items: start;
}
.garage-col { display: flex; flex-direction: column; gap: 14px; }
.garage-col .panel + .panel { margin-top: 0; }
.bay-col { display: flex; flex-direction: column; gap: 14px; }

@media (max-width: 1120px) {
    .garage { grid-template-columns: minmax(0, 1fr) 320px; }
    .bay-col { grid-column: 1 / -1; }
}
@media (max-width: 760px) { .garage { grid-template-columns: 1fr; } }

.bay {
    position: relative;
    background:
        radial-gradient(90% 70% at 50% 92%, var(--tier-glow, rgba(255, 45, 149, .18)), transparent 70%),
        linear-gradient(#241840, #150c2a);
    border: 3px solid var(--stroke);
    border-radius: 14px;
    padding: 26px 20px 0;
    min-height: 392px;
    display: flex; flex-direction: column; align-items: center;
}

.bay-floor {
    position: absolute; left: 0; right: 0; bottom: 0;
    height: 74px;
    background: linear-gradient(transparent, rgba(0, 0, 0, .55));
    border-top: 3px solid rgba(255, 255, 255, .07);
}

/* the frame's bottom edge IS the tyre contact line, so this parks the car on
   the floor band's top edge instead of hovering above it */
.bay-car { position: relative; z-index: 1; margin-top: auto; margin-bottom: 66px; }

.bay-name {
    position: absolute; left: 20px; top: 16px;
    font-size: 30px; letter-spacing: 2px;
}
.bay-name em { display: block; font-style: normal; font-size: 16px; color: var(--dim); letter-spacing: 3px; }

.panel {
    background: var(--ink-2);
    border: 3px solid var(--stroke);
    border-radius: 14px;
    padding: 14px 16px 16px;
}
.panel + .panel { margin-top: 14px; }
.panel h3 {
    margin: 0 0 10px;
    font-size: 24px; letter-spacing: 3px; font-weight: normal;
    color: #d7cbef;
}

.swatches { display: grid; grid-template-columns: repeat(6, 1fr); gap: 7px; }
.swatch {
    height: 30px;
    border: 3px solid var(--stroke);
    border-radius: 7px;
    cursor: pointer;
    padding: 0;
}
.swatch.on { outline: 3px solid var(--hot); outline-offset: 2px; }
/* 6 border + 6 pad + 58 bay + 3 + 20 name + 7 pad */
:root { --skin-tile-h: 100px; --skin-gap: 8px; }

/* the car you race, marked in the owned list so it is findable without
   clicking through every chip */
.garage .chip.primary::after,
.chip.primary::after {
    content: '';
    display: inline-block;
    width: 7px; height: 7px; margin-left: 7px;
    border-radius: 50%;
    background: #8bd427;
    vertical-align: middle;
}

/* ===== collapsible help ===== */
/* <details> rather than a JS panel: it is keyboard-reachable, it works before
   any script runs, and there is no open/closed state to get out of step with
   the arrow. Only the remembering is scripted. */
.help {
    background: var(--ink-2);
    border: 3px solid var(--stroke);
    border-radius: 14px;
    margin-bottom: 18px;
}
.help > summary {
    list-style: none;
    cursor: pointer;
    padding: 10px 16px 11px;
    font-size: 24px; letter-spacing: 3px;
    color: var(--text);
    display: flex; align-items: center; gap: 10px;
}
.help > summary::-webkit-details-marker { display: none; }
.help > summary:hover { color: #ffd23f; }
/* the arrow is the only moving part, so it is the only thing that animates */
.help > summary i {
    margin-left: auto;
    width: 0; height: 0;
    border-left: 7px solid transparent;
    border-right: 7px solid transparent;
    border-top: 9px solid var(--dim);
    transition: transform .14s ease;
}
.help[open] > summary i { transform: rotate(180deg); }
.help[open] > summary { border-bottom: 3px solid var(--stroke); color: #ffd23f; }

.help-body {
    padding: 4px 16px 18px;
    /* Two columns that pack rather than tile. A grid of sections left a hole
       under every short one, because a grid row is as tall as its tallest cell;
       multicol has no rows, so text simply continues. It balances by height on
       its own PROVIDED it is allowed to break inside a section - pinning whole
       sections is what made it give up and stack four in one column. So the
       only things kept whole are a heading with its first line, and the table. */
    columns: 2;
    column-gap: 30px;
}
@media (max-width: 900px) { .help-body { columns: 1; } }
.help-body section { margin-top: 12px; }
.help-body h4 { break-after: avoid; }
.help-table { break-inside: avoid; }
.help-body h4 {
    margin: 0 0 5px;
    font-size: 19px; font-weight: normal; letter-spacing: 3px;
    color: #ffd23f;
}
.help-body p { margin: 0 0 6px; font-size: 19px; line-height: 1.4; color: var(--dim); }
.help-body b { color: var(--text); }
.help-body em { font-style: normal; color: #a99bc9; }
.help-body ul { margin: 0; padding-left: 18px; font-size: 19px; line-height: 1.4; color: var(--dim); }
.help-body li { margin-bottom: 3px; }

.help-table { width: 100%; border-collapse: collapse; margin: 6px 0 8px; font-size: 18px; }
.help-table th {
    text-align: left; font-weight: normal; letter-spacing: 2px;
    color: #7c6ea0; padding: 0 8px 3px 0; border-bottom: 2px solid var(--line);
}
.help-table td { padding: 3px 8px 3px 0; color: var(--dim); vertical-align: top; }
.help-table td em { display: block; font-size: 16px; }
/* the mode names carry the same tints the HUD uses, so the table reads as the
   same vocabulary rather than as a glossary of it */
.help-table .m-boost  { color: #ffd34d; }
.help-table .m-push   { color: #ff5a1f; }
.help-table .m-cruise { color: #6fd3ff; }
.help-table .m-save   { color: #8bd427; }

.panel-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; margin-bottom: 10px;
}
.panel-head h3 { margin: 0; }
.panel-head .seg { display: flex; gap: 4px; }

/* A skin is artwork, so it is chosen by looking at it. Names alone wrapped into
   a ragged block of chips and told you nothing about what you were picking. */
.skin-gallery {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--skin-gap);
    /* Exactly four tiles - two rows of two - and the rest scrolls. The tile is a
       fixed height by construction (a 58px bay over one clipped line of name),
       so this is the real measurement rather than a guess that drifts. */
    max-height: calc(var(--skin-tile-h) * 2 + var(--skin-gap));
    overflow-y: auto;
}
.skin-tile {
    height: var(--skin-tile-h);
    background: var(--ink-3);
    border: 3px solid var(--stroke);
    border-radius: 11px;
    padding: 6px 4px 7px;
    font: inherit; color: inherit;
    cursor: pointer;
    text-align: center;
    transition: border-color .12s ease;
}
.skin-tile:hover:not(:disabled) { border-color: #5e4e8c; }
.skin-tile.on { border-color: #ffd23f; background: rgba(255, 210, 63, .09); }
.skin-tile:disabled { cursor: not-allowed; }
/* Locked skins stay in the gallery: it is how a player finds out this car has
   artwork at all, and which channel to go and beat for it. */
.skin-tile.locked .skin-bay { opacity: .3; filter: grayscale(.85); }
.skin-tile.locked .skin-name { color: #5e4e8c; }
.skin-bay {
    height: 58px;
    display: flex; align-items: flex-end; justify-content: center;
    pointer-events: none;
}
.skin-name {
    font-size: 18px; letter-spacing: 1px; line-height: 1.1;
    margin-top: 3px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.skin-tile.on .skin-name { color: #ffd23f; }
.skin-note { font-size: 17px; letter-spacing: 1px; color: var(--dim); margin-top: 9px; line-height: 1.35; }

/* the panels are 320px wide now, so a row of controls has to be allowed to
   wrap instead of pushing itself out through the border */
.row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.row label { font-size: 19px; color: var(--dim); letter-spacing: 2px; white-space: nowrap; }
input[type=color] {
    width: 46px; height: 30px; padding: 0;
    background: var(--ink-3);
    border: 3px solid var(--stroke); border-radius: 7px; cursor: pointer;
}

.rims { display: flex; gap: 7px; }
/* An experimental rim is not part of the set, so it does not pretend to be:
   amber edge, and a gap before it. */
.rim.test { border-color: #5a4614; margin-left: 10px; }
.rim.test.on { border-color: #ffd23f; }

.rim {
    width: 50px; height: 50px;
    display: flex; align-items: center; justify-content: center;
    background: var(--ink-3);
    border: 3px solid var(--stroke);
    border-radius: 9px;
    cursor: pointer;
    padding: 0;
}
.rim img { width: 32px; height: 32px; }
.rim.on { outline: 3px solid var(--hot); outline-offset: 2px; }

/* ===== body kit =====
   A bought part is kept even when it is off the car, so the row has two states
   rather than one: priced while it is still in the catalogue, then a switch. */
.kit-list { display: flex; flex-wrap: wrap; gap: 10px; }
.kit-row {
    flex: 1 1 230px;
    display: flex; align-items: center; gap: 10px;
    padding: 8px 12px 9px;
    background: var(--ink-2);
    border: 3px solid var(--stroke); border-radius: 12px;
}
.kit-row.on { border-color: var(--hot); }
.kit-label { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.kit-label b { font-size: 19px; font-weight: normal; letter-spacing: 2px; }
.kit-label i { font-style: normal; font-size: 14px; color: var(--dim); letter-spacing: 1px; }
.kit-buy {
    font-family: inherit; font-size: 17px; letter-spacing: 1px;
    flex: 0 0 auto; min-width: 78px;
    padding: 3px 10px;
    border: 2px solid var(--line); border-radius: 7px;
    background: var(--ink-3); color: #ffd23f;
    cursor: pointer;
}
.kit-buy:hover:not(:disabled) { border-color: #5e4e8c; }
.kit-buy:disabled { opacity: .4; cursor: not-allowed; }
/* owned parts are a toggle, not a purchase, so they stop looking like money */
.kit-buy.owned { color: #c9bce3; }
.kit-row.on .kit-buy.owned { background: var(--hot); border-color: var(--hot); color: #fff; }
.kit-none { font-size: 16px; color: var(--dim); letter-spacing: 1px; }

.tune-row { display: flex; align-items: center; gap: 10px; margin-bottom: 9px; }
.tune-name { width: 96px; font-size: 20px; letter-spacing: 2px; }
.pips { display: flex; gap: 4px; flex: 1; }
.pip {
    flex: 1; height: 14px;
    background: #130b26;
    border: 2px solid var(--stroke);
    border-radius: 4px;
}
.pip.on { background: var(--hot); }
/* Dark with a gold price, like the kit's button above. It was a gold button,
   and the coin on it (RaceIcons.money) vanished into it and read as "©". */
.tune-buy {
    font-family: inherit; font-size: 16px; letter-spacing: 1px;
    padding: 2px 9px;
    border: 2px solid var(--line); border-radius: 7px;
    background: var(--ink-3); color: #ffd23f; cursor: pointer;
    min-width: 74px;
}
.tune-buy:hover:not(:disabled) { border-color: #5e4e8c; }
.tune-buy:disabled { opacity: .35; cursor: not-allowed; }

/* ===== career board ===== */

/* Four across, so eight cells make two clean rows instead of six-and-two. The
   value is one short thing and the unit rides beneath it - "Autobahn Hatch · 1,500 CR"
   at 26px wrapped onto two lines and made every cell in the row a different
   height. */
.career { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
@media (max-width: 860px) { .career { grid-template-columns: repeat(2, 1fr); } }
.career-cell {
    background: var(--ink-2);
    border: 3px solid var(--stroke);
    border-radius: 12px;
    padding: 8px 14px 10px;
}
.career-cell i { display: block; font-style: normal; font-size: 14px; letter-spacing: 3px; color: var(--dim); }
.career-cell b {
    display: block;
    font-size: 26px; font-weight: normal; letter-spacing: 1px; color: #fff;
    line-height: 1.05;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.career-cell s {
    display: block; text-decoration: none;
    font-size: 16px; letter-spacing: 2px; color: var(--dim);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    min-height: 18px;
}

/* ===== paint finishes ===== */

.finishes { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; margin-top: 10px; }
.finish {
    font-family: inherit;
    display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: 5px 4px 4px;
    border: 3px solid var(--stroke);
    border-radius: 8px;
    background: var(--ink-3);
    color: #d4c8ec;
    font-size: 15px; letter-spacing: 1px;
    cursor: pointer;
}
/* a strip of the chosen colour, so the four options read as four paint jobs
   rather than four words */
.finish::before {
    content: '';
    width: 100%; height: 12px;
    border: 2px solid var(--stroke); border-radius: 4px;
    background: var(--swatch, #888);
    background-size: cover;
}
.finish.on { outline: 3px solid var(--hot); outline-offset: 2px; color: #fff; }
.finish.locked { opacity: .38; cursor: not-allowed; }
.finish em { font-style: normal; font-size: 12px; color: var(--dim); letter-spacing: 1px; }

.rim.locked { opacity: .3; cursor: not-allowed; }

/* ===== performance bars ===== */

.stat-row { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; }
.stat-name { width: 62px; font-size: 19px; letter-spacing: 2px; color: #d7cbef; }
.stat-bar {
    flex: 1; display: flex;
    height: 13px;
    background: #130b26;
    border: 2px solid var(--stroke);
    border-radius: 5px;
    overflow: hidden;
}
.stat-bar u { display: block; height: 100%; background: var(--hot); }
/* the tuned part in a different colour: the money you spent is the bit that
   is not the car you bought */
.stat-bar i { display: block; height: 100%; background: #ffd23f; }
.stat-row b { width: 34px; text-align: right; font-size: 19px; font-weight: normal; color: var(--dim); }
.stat-row b.up { color: #ffd23f; }
/* its own line rather than a labelled row: the panel heading already says what
   this is, and the breakdown does not fit beside a label at this width */
.rating {
    margin-top: 10px;
    padding-top: 9px;
    border-top: 2px solid var(--ink-3);
    font-size: 19px; color: #ffd23f; letter-spacing: 2px;
}

/* ===== strategy picker ===== */

.legend { display: flex; gap: 8px; margin-bottom: 12px; }
.legend-chip {
    padding: 1px 16px 2px;
    border: 2px solid var(--stroke);
    border-radius: 7px;
    background: var(--tint);
    color: #170e2e;
    font-size: 17px; letter-spacing: 2px;
}

.tank-note { font-size: 19px; letter-spacing: 2px; color: var(--dim); white-space: nowrap; }
.tank-note b { color: #ffd23f; font-weight: normal; }

.strats { display: grid; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); gap: 10px; }

.strat {
    display: flex;
    flex-direction: column;
    gap: 4px;
    text-align: left;
    font-family: inherit;
    padding: 7px 9px 8px;
    border: 3px solid var(--stroke);
    border-radius: 10px;
    background: var(--ink-3);
    color: var(--text);
    cursor: pointer;
}
.strat:hover { border-color: #5e4e8c; }
.strat.on { outline: 3px solid var(--hot); outline-offset: 2px; }

.strat-name { font-size: 21px; letter-spacing: 2px; line-height: 1; }

/* the plan itself: segment widths are the shares, colours are the modes */
.strat-bar {
    height: 10px;
    border: 2px solid var(--stroke);
    border-radius: 5px;
    background-color: #130b26;
    background-repeat: no-repeat;
}

.strat-plan  { font-size: 14px; letter-spacing: 1px; color: #d7cbef; }
.strat-blurb { font-size: 16px; line-height: 1.2; color: var(--dim); }

/* One row, equal thirds, flush with the column above it. Two rows of full-size
   buttons put 40px of nothing under the bay and left the neighbouring columns
   ending somewhere else entirely. These are secondary actions under a picture -
   they do not need to be as big as the picture. */
.actions {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
    margin-top: 12px;
}
/* The pinned state is a confirmation, not a failure. Faded out on the hot
   background it read as a disabled error button; green with the same dot the
   owned-list uses says "this one is set" and ties the two together. */
.btn.pinned, .btn.pinned:disabled {
    background: var(--ink-3);
    border-color: #8bd427;
    color: #8bd427;
    opacity: 1;
}

.actions .btn {
    margin-left: 0;
    padding: 4px 6px;
    font-size: 18px; letter-spacing: 1px;
    text-align: center; white-space: nowrap;
}

.toast {
    position: fixed; left: 50%; bottom: 26px;
    transform: translateX(-50%) translateY(14px);
    background: var(--ink); color: #fff;
    border: 3px solid var(--stroke); border-radius: 10px;
    padding: 6px 20px 5px;
    font-size: 22px; letter-spacing: 2px;
    opacity: 0; pointer-events: none;
    transition: opacity .18s ease, transform .18s ease;
    z-index: 50;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ===== week calendar ===== */
.week-nav {
    display: flex; align-items: center; gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
.week-nav .btn { padding: 6px 12px; }
.week-label { min-width: 230px; }
.week-label b { display: block; font-size: 24px; font-weight: normal; letter-spacing: 2px; }
.week-label span { font-size: 17px; letter-spacing: 2px; color: var(--dim); }

/* One block per day, always all seven: a week with Wednesday missing reads as
   a loading bug rather than as a quiet Wednesday. */
.day-block { margin-bottom: 18px; }
.day-head {
    display: flex; align-items: center; gap: 12px;
    margin-bottom: 10px;
}
.day-head h3 {
    margin: 0; font-size: 25px; font-weight: normal; letter-spacing: 3px;
}
.day-head .rule { flex: 1; height: 2px; background: var(--line); border-radius: 1px; }
.day-head .tally { font-size: 17px; letter-spacing: 2px; color: var(--dim); }
.day-block.today .day-head h3 { color: #ffd23f; }
.day-block.past { opacity: .45; }
.day-block.quiet .day-head h3 { color: #5e4e8c; }
.day-none { font-size: 18px; letter-spacing: 2px; color: #5e4e8c; padding: 2px 0 6px; }
/* Full width, so it reads as the bottom edge of the day rather than as one more
   card in the grid. */
.day-more {
    display: block; width: 100%;
    margin-top: 10px;
    padding: 7px 12px;
    background: var(--ink-2);
    border: 3px solid var(--stroke);
    border-radius: 11px;
    font: inherit; font-size: 19px; letter-spacing: 2px;
    color: var(--dim);
    cursor: pointer;
}
.day-more:hover { border-color: #5e4e8c; color: var(--text); }

.empty {
    padding: 40px 20px;
    text-align: center;
    color: var(--dim);
    font-size: 24px; letter-spacing: 2px;
}

/* ===== engine bench ===== */

.note {
    font-size: 20px; line-height: 1.35; color: var(--dim);
    max-width: 780px; margin: 0 0 16px;
}
.note b { color: var(--text); }
.note code { color: #ffd23f; }

/* Top of the bench: what you are listening to on the left, what you are doing
   to it on the right. The model's own knobs used to share this row as a 460px
   sidebar, which left a 210px label and a slider fighting over 190px. */
.bench { display: grid; grid-template-columns: minmax(0, 1fr) 440px; gap: 18px; align-items: stretch; }
.bench-drive { display: flex; flex-direction: column; }
/* four buttons in a 440px column wrap "RUN SWEEP" onto two lines at the
   full-size type, and a two-line button in a row of one-line ones reads as
   broken rather than as emphasis */
.bench-drive .actions .btn {
    flex: 1 1 auto;
    font-size: 19px; padding: 3px 10px;
    white-space: nowrap;
}

/* The traces take whatever height the controls beside them come to, instead of
   leaving a couple of hundred pixels of nothing under a short panel. Stretching
   a scope vertically is what a gain knob does anyway. */
.bench-scope { display: flex; flex-direction: column; }
.bench-scope canvas { flex: 1 1 0; min-height: 110px; }
.bench-scope .readout { flex: 0 0 auto; }

/* The tunables run full width underneath, two across. */
.tunables { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 18px; }

/* status, not prose: green for the waveguide model, red for the fallback */
.bench-mode { font-size: 18px; letter-spacing: 1px; color: var(--dim); }

/* Buttons parked in a section head size to their labels. The stretched-equal
   rule below is for a panel footer, where the row has a width to fill; here it
   split "COPY PARAMS" over two lines. */
.section-head .actions { margin-top: 0; }
.section-head .actions .btn { flex: 0 0 auto; white-space: nowrap; }

@media (max-width: 1080px) {
    .bench { grid-template-columns: 1fr; }
    .tunables { grid-template-columns: 1fr; }
}

#scope, #spectrum {
    width: 100%; height: auto; display: block;
    border: 2px solid var(--stroke); border-radius: 8px;
    background: #130b26;
}
#spectrum { margin-top: 8px; }

.readout {
    margin-top: 8px; padding: 4px 10px;
    background: var(--ink-3); border-radius: 7px;
    font-size: 20px; letter-spacing: 1px; color: #d7cbef;
}

.drive-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.drive-row label { width: 74px; font-size: 20px; color: var(--dim); letter-spacing: 2px; }
.drive-row input[type=range] { flex: 1; accent-color: var(--hot); }
.drive-row output { width: 80px; text-align: right; font-size: 20px; color: #ffd23f; }

.gearbar { display: flex; gap: 6px; margin-top: 12px; }
.gearbar span {
    flex: 1; text-align: center;
    padding: 2px 0 1px;
    font-size: 19px;
    background: #130b26;
    border: 2px solid var(--stroke); border-radius: 6px;
    color: #5e4e8c;
}
.gearbar span.on { background: var(--hot); color: #fff; }

.knob { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.knob > label { flex: 0 0 210px; font-size: 17px; color: var(--dim); letter-spacing: 1px; }
.knob input[type=range] { flex: 1; accent-color: var(--hot); min-width: 60px; }
.knob output { flex: 0 0 54px; text-align: right; font-size: 18px; color: #ffd23f; }

/* one control per line: three cramped sliders on a row are unusable for the
   fine adjustments formants actually need */
.knob.formant {
    flex-direction: column; align-items: stretch; gap: 4px;
    padding-bottom: 8px; margin-bottom: 8px;
    border-bottom: 2px solid var(--ink-3);
}
.knob.formant > label { flex: none; color: var(--text); font-size: 19px; }
.knob.formant .sub { display: flex; align-items: center; gap: 8px; }
.knob.formant .sub i { flex: 0 0 24px; }
.knob.formant .sub i { font-style: normal; font-size: 15px; color: var(--dim); }
.knob.formant .sub output { flex: 0 0 42px; font-size: 16px; }

.dump {
    width: 100%; height: 150px; margin-top: 12px;
    background: #130b26; color: #9ad37a;
    border: 2px solid var(--stroke); border-radius: 8px;
    padding: 8px 10px;
    font-family: ui-monospace, Menlo, monospace; font-size: 12px;
    resize: vertical;
}

/* ===== hub ===== */

.hub { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; }
.hub-card {
    display: block;
    background: var(--ink-2);
    border: 3px solid var(--stroke);
    border-radius: 14px;
    padding: 18px 20px 20px;
    transition: transform .12s ease, border-color .12s ease;
}
.hub-card:hover { transform: translateY(-3px); border-color: var(--hot); }
.hub-card .kicker { font-size: 15px; letter-spacing: 3px; color: var(--hot); }
.hub-card h3 { margin: 4px 0 6px; font-size: 34px; letter-spacing: 2px; font-weight: normal; }
.hub-card p { margin: 0; font-size: 20px; line-height: 1.25; color: var(--dim); }
.hub-card.wip { opacity: .5; }
.hub-card.wip:hover { transform: none; border-color: var(--stroke); }

/* ===== clean room ===== */

.chain {
    padding: 8px 12px;
    background: #130b26;
    border: 2px solid var(--stroke); border-radius: 8px;
    font-size: 20px; letter-spacing: 1px; color: #8bd427;
    line-height: 1.4;
}
.chain.dirty { color: #ffd23f; }

.tick {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 7px 0;
    border-bottom: 2px solid var(--ink-3);
    font-size: 19px; line-height: 1.3; color: var(--dim);
    cursor: pointer;
}
.tick:last-of-type { border-bottom: 0; }
.tick input { width: 20px; height: 20px; accent-color: var(--hot); margin-top: 2px; flex: 0 0 auto; }
.tick b { color: var(--text); font-weight: normal; }
.tick code { color: #ffd23f; font-size: 16px; }

/* ===== premium redeem row ===== */
.redeem {
    display: flex; flex-direction: column; gap: 10px;
    margin-bottom: 16px;
}
.redeem-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.redeem-row .pick-name { flex: 0 1 260px; }
.redeem-row .btn { margin-left: 0; }
/* a locked livery reads as a locked livery, not as a card that failed to load */
.card .btn:disabled { opacity: .45; }

/* ===== news board =====
   A table rather than a stack of cards: the board has to hold a season of cups,
   and every row is the same five facts. Cards spent a sixth of the screen on
   one of them. */
.news-list {
    display: flex; flex-direction: column;
    margin-bottom: 8px;
    border: 3px solid var(--stroke);
    border-radius: 12px;
    background: var(--ink-2);
    overflow: hidden;
}
.cal-row {
    display: grid;
    grid-template-columns: 132px 150px minmax(0, 1fr) 250px 108px;
    align-items: center;
    gap: 12px;
    padding: 5px 14px 6px;
    border-top: 2px solid var(--ink-3);
}
.cal-row:first-child { border-top: 0; }
.cal-head {
    padding: 5px 14px 4px;
    font-size: 13px; letter-spacing: 3px; color: #7c6ea0;
    background: rgba(0, 0, 0, .30);
}
.cal-row.past { opacity: .62; }
/* the one row worth acting on right now */
.cal-row.live { background: rgba(255, 45, 149, .09); }

.cal-when { display: flex; flex-direction: column; line-height: 1.15; }
.cal-when b { font-size: 17px; font-weight: normal; letter-spacing: 1px; color: #d7cbef; }
.cal-when span { font-size: 18px; color: #ffd23f; letter-spacing: 1px; }

.cal-chan { display: flex; align-items: baseline; gap: 7px; min-width: 0; }
.cal-chan b {
    font-size: 21px; font-weight: normal; letter-spacing: 1px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-live {
    flex: 0 0 auto;
    font-style: normal; font-size: 12px; letter-spacing: 2px;
    padding: 0 6px 1px;
    background: var(--hot); color: #fff;
    border-radius: 5px;
}

.cal-race {
    font-size: 15px; color: #a99bc9; letter-spacing: 1px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The prize is shown, not described: the container is the announcement. */
.cal-prize { display: flex; align-items: center; gap: 10px; min-width: 0; }
.cal-art {
    flex: 0 0 auto; width: 84px; height: auto;
    image-rendering: auto;          /* 452px of anti-aliased art, fitted */
    border: 2px solid #000; border-radius: 5px;
}
.cal-prize-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.cal-prize-text b {
    font-size: 17px; font-weight: normal; letter-spacing: 1px; color: #f3e9ff;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-prize-text span {
    font-size: 13px; color: #7c6ea0; letter-spacing: 1px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-prize-text.won b { color: #8bd427; }
.cal-prize-text.won span { color: #6f9e4a; }

.cal-act { justify-self: end; }
.cal-watch {
    font-size: 16px; letter-spacing: 2px;
    padding: 2px 12px;
    border: 2px solid var(--hot); border-radius: 8px;
    color: #fff; background: var(--hot);
}
.cal-row:not(.live) .cal-watch { background: transparent; color: #ff6f96; }
.cal-won { font-size: 17px; color: #8bd427; letter-spacing: 1px; }

@media (max-width: 980px) {
    .cal-row { grid-template-columns: 120px minmax(0, 1fr) 96px; }
    .cal-race, .cal-prize { grid-column: 1 / -1; }
    .cal-head { display: none; }
}

/* ===== tabs ===== */
.tabs { display: flex; gap: 8px; margin: 24px 0 14px; flex-wrap: wrap; }
.tab {
    font-family: inherit; font-size: 21px; letter-spacing: 2px;
    padding: 4px 18px 5px;
    border: 3px solid var(--stroke);
    border-radius: 10px;
    background: var(--ink-2);
    color: #c9bce3;
    cursor: pointer;
}
.tab:hover { color: #fff; }
.tab.on { background: var(--hot); color: #fff; }
.hidden { display: none !important; }

/* ===== cup cards ===== */
/* Same card as a car in the dealership: the announcement is an advertisement,
   and what it advertises is a machine. */
.ev-card.live { border-color: var(--hot); }
.ev-card.past { opacity: .6; }
.ev-when { font-size: 19px; color: #ffd23f; letter-spacing: 1px; margin-top: -4px; }
.ev-race { display: flex; flex-wrap: wrap; gap: 4px; }
.ev-race span {
    font-size: 14px; letter-spacing: 1px; color: #c9bce3;
    padding: 1px 7px 2px;
    background: var(--ink-3); border-radius: 6px;
}
.ev-prize { font-size: 15px; color: var(--dim); letter-spacing: 1px; }
.ev-prize.won { color: #8bd427; }
.ev-card .card-foot .btn { font-size: 18px; padding: 2px 14px; }

/* ===== filter bar ===== */
.filter-bar {
    display: flex; flex-direction: column; gap: 8px;
    padding: 10px 14px 12px;
    margin-bottom: 16px;
    background: var(--ink-2);
    border: 3px solid var(--stroke);
    border-radius: 12px;
}
.filter-row { display: flex; align-items: center; gap: 10px; }
.filter-label {
    flex: 0 0 78px;
    font-size: 14px; letter-spacing: 3px; color: var(--dim);
}
.filter-row .chip { font-size: 17px; padding: 2px 11px; }
.filter-row .chip:disabled { opacity: .32; cursor: not-allowed; }
@media (max-width: 760px) {
    .filter-row { flex-direction: column; align-items: flex-start; gap: 4px; }
}

/* the bay's own display switch, parked over the floor in the far corner so it
   never lands on the car whatever is standing there */
.bay-view {
    position: absolute;
    right: 12px; top: 12px;
    z-index: 2;
    gap: 5px;
}
.bay-view .opt-btn { font-size: 15px; padding: 1px 8px; }

/* ===== wallet =====
   Two currencies now, so the corner of the bar is a row rather than one plate.
   The credit plate kept its own margin-left:auto for years; it moves out here so
   the two sit together instead of fighting over the same push. */
.wallet { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.wallet .credits { margin-left: 0; }

.shards {
    display: flex; align-items: center; gap: 8px;
    padding: 4px 14px;
    background: var(--ink-3);
    border: 3px solid var(--stroke);
    border-radius: 10px;
    font-size: 26px;
    letter-spacing: 1px;
}
.shards b { color: #6fd3ff; font-weight: normal; }
.shards.inline { padding: 0; background: none; border: 0; display: inline-flex; vertical-align: middle; }

/* The shard and the coin are the guide's pixel icons (icons.js), drawn on a
   16px grid: 24px in the top bar's plates, 18px beside a price. The facet
   shape below is only the fallback for a page without icons.js. */
.shard-icon { width: 18px; height: 18px; flex: 0 0 18px; display: inline-block; }
.shard-icon.px, .coin-icon { display: inline-flex; }
.shard-icon.px svg, .coin-icon svg { display: block; width: 100%; height: 100%; }
.coin-icon { width: 24px; height: 24px; flex: 0 0 24px; }
/* the coin's art sits a grid pixel high in its 16px cell (one empty row above
   it, three below); one grid pixel down centres it on the number beside it */
.coin-icon svg { transform: translateY(6.25%); }
.topbar .shards .shard-icon { width: 24px; height: 24px; flex-basis: 24px; }
.credits .coin-icon, .topbar .shards .shard-icon { filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .45)); }
/* a price: the coin, then the number (RaceIcons.money) */
.money { display: inline-flex; align-items: center; gap: .2em; vertical-align: middle; white-space: nowrap; }
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.shard-icon.shape {
    background: linear-gradient(150deg, #bff0ff 0%, #6fd3ff 46%, #2e7dff 100%);
    clip-path: polygon(52% 0%, 100% 34%, 74% 100%, 18% 84%, 0% 40%);
}

/* ===== containers =====
   A shelf, so it reads as one: three cards on a row, art and a count and a
   button. The drop table used to live on the card and made each one 230px tall,
   which pushed the gallery and everything else off the bottom of the screen. It
   is one click away now, in .crate-detail below. */

.crates { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }

.crate {
    display: flex; flex-direction: column; gap: 7px;
    padding: 10px;
    background: var(--ink-2);
    border: 3px solid var(--stroke);
    border-top: 5px solid var(--tint, var(--line));
    border-radius: 14px;
    cursor: pointer;
}
/* Holding one is the difference between a shelf and a prize, so it is worth a
   glow rather than only a number. */
.crate.has { box-shadow: 0 8px 30px -16px var(--tint); }
.crate.on { box-shadow: 0 0 0 2px var(--tint); }

.crate-art {
    position: relative;
    background: #0c0c10;
    border: 3px solid var(--stroke);
    border-radius: 10px;
    overflow: hidden;
}
/* The one place in the project that does NOT want nearest-neighbour: this is
   452px of anti-aliased artwork being fitted to a card, and pixelated at a
   fractional scale turns its texture into noise. */
.crate-art img { width: 100%; height: auto; image-rendering: auto; display: block; }
.crate:not(.has) .crate-art img { filter: grayscale(.7) brightness(.62); }

.crate-count {
    position: absolute; top: 6px; right: 8px;
    padding: 0 9px;
    font-size: 22px; letter-spacing: 2px;
    background: var(--tint, var(--line));
    color: #170e2e;
    border: 3px solid var(--stroke);
    border-radius: 8px;
}
.crate-count.none { background: var(--ink-3); color: var(--dim); }

.crate-head { display: flex; align-items: baseline; gap: 8px; }
.crate-head b { font-size: 27px; font-weight: normal; letter-spacing: 2px; }
.crate-head span {
    margin-left: auto;
    font-size: 15px; letter-spacing: 2px; color: var(--tint, var(--dim));
    white-space: nowrap;
}
.crate-sub { font-size: 16px; letter-spacing: 1px; color: var(--dim); }

.crate-foot { margin-top: 2px; display: flex; align-items: center; gap: 8px; }
.crate-foot .btn { margin-left: 0; font-size: 19px; padding: 2px 12px; }
.crate-foot .btn.ghost {
    display: inline-flex; align-items: center; gap: 6px;
    color: #6fd3ff;
}
.crate-foot .btn.go { margin-left: auto; }

/* Three across holds down to a tablet; one column only on a phone, and then
   no wider than a phone - at 900px one crate across the whole page was a
   billboard. */
@media (max-width: 700px) {
    .crates { grid-template-columns: 1fr; max-width: 440px; margin: 0 auto; }
}

/* ===== what is in the box =====
   Opened by clicking a crate. Cars rather than a list of names: six pictures
   say what the container is in a way six lines of text never did, and this is
   the only advertisement a crate gets. */
.crate-detail {
    margin-top: 14px;
    padding: 12px 14px 14px;
    background: var(--ink-2);
    border: 3px solid var(--stroke);
    border-left: 6px solid var(--tint, var(--line));
    border-radius: 14px;
}
.detail-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 10px; }
.detail-head b { font-size: 26px; font-weight: normal; letter-spacing: 2px; color: var(--tint); }
.detail-head span { font-size: 17px; letter-spacing: 1px; color: var(--dim); }
.detail-head .btn { margin-left: auto; font-size: 17px; padding: 1px 12px; }

.crate-skins {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
    gap: 10px;
}
.crate-skin {
    position: relative;
    padding: 6px 6px 8px;
    text-align: center;
    background: rgba(0, 0, 0, .24);
    border: 2px solid var(--line);
    border-top: 3px solid var(--quality);
    border-radius: 10px;
}
/* Already pulled: still listed, because it is still what is in the box and
   still what you are rolling against - but faded back, so the tiles that stand
   out are the ones you are actually playing for. */
.crate-skin.mine { border-color: #2f6b32; border-top-color: var(--quality); opacity: .42; }
.crate-skin.mine:hover { opacity: .85; }
.crate-skin.mine::after {
    content: '✓';
    position: absolute; top: 4px; left: 8px;
    font-size: 20px; color: #8bd427;
}

/* Rarity is a look, not only a word. The bay is lit in the quality's own
   colour, harder the rarer it is, so the good one in a row of six is the one
   your eye lands on before you have read anything.

   TWO overlapping ellipses rather than one: a single radial-gradient at this
   size bands into visible rings, and the pair cross-fade into a falloff with no
   edge in it. A legendary gets a slow diagonal sheen on top - a highlight
   travelling across the tile, not the whole thing pulsing brighter, which is
   what it used to do and what made it look like a blinking div. */
.cs-bay {
    position: relative;
    height: 74px;
    display: flex; align-items: flex-end; justify-content: center;
    border-radius: 8px;
    overflow: hidden;
}
.q-common .cs-bay {
    background:
        radial-gradient(52% 42% at 50% 94%, color-mix(in srgb, var(--quality) 26%, transparent), transparent 100%),
        radial-gradient(104% 74% at 50% 100%, color-mix(in srgb, var(--quality) 10%, transparent), transparent 100%);
}
.q-rare .cs-bay {
    background:
        radial-gradient(50% 40% at 50% 94%, color-mix(in srgb, var(--quality) 72%, transparent), transparent 100%),
        radial-gradient(108% 78% at 50% 100%, color-mix(in srgb, var(--quality) 26%, transparent), transparent 100%);
}
.q-legendary .cs-bay,
.q-unique .cs-bay {
    background:
        radial-gradient(46% 38% at 50% 94%, color-mix(in srgb, var(--quality) 95%, transparent), transparent 100%),
        radial-gradient(76% 58% at 50% 98%, color-mix(in srgb, var(--quality) 48%, transparent), transparent 100%),
        radial-gradient(122% 88% at 50% 100%, color-mix(in srgb, var(--quality) 18%, transparent), transparent 100%);
}
.q-legendary .cs-bay::after,
.q-unique .cs-bay::after {
    content: '';
    position: absolute; inset: -30% -60%;
    pointer-events: none;
    background: linear-gradient(72deg,
        transparent 38%,
        color-mix(in srgb, var(--quality) 55%, #fff) 50%,
        transparent 62%);
    opacity: .22;
    mix-blend-mode: screen;
    animation: sheen 4.2s ease-in-out infinite;
}
@keyframes sheen {
    0%, 100% { transform: translateX(-46%); }
    50%      { transform: translateX(46%); }
}

/* And the tile itself, so the rarity is readable from across the row rather
   than only under the car. */
.crate-skin.q-rare { box-shadow: 0 0 16px -6px var(--quality); }
.crate-skin.q-legendary,
.crate-skin.q-unique {
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--quality) 55%, transparent),
                0 0 26px -6px var(--quality);
}
@media (prefers-reduced-motion: reduce) {
    .q-legendary .cs-bay::after, .q-unique .cs-bay::after { animation: none; opacity: .12; }
}
.crate-skin u {
    display: block; text-decoration: none;
    font-size: 19px; letter-spacing: 1px; color: var(--quality);
    text-align: right;
}
.crate-skin b { display: block; font-size: 21px; font-weight: normal; letter-spacing: 1px; }
.crate-skin i { display: block; font-style: normal; font-size: 16px; color: var(--dim); }

/* ===== the opening =====
   A reel that decelerates past a mark, which is the shape this whole genre
   settled on and for a good reason: it is the only version with a NEAR MISS in
   it. A box that rattles and then states an answer cannot show you that the
   legendary went by one tile early.

   The light is a <canvas> (reveal-fx.js), not gradients: additive, grainy, with
   things moving in it. The CSS version this replaced was two flat radial smears
   crossfading, and it read as coloured plastic. */

.reveal {
    position: fixed; inset: 0; z-index: 50;
    display: flex; align-items: center; justify-content: center;
    padding: 20px;
    background: rgba(6, 6, 9, .90);
    backdrop-filter: blur(2px);
}
.reveal[hidden] { display: none; }

.reveal-box {
    position: relative; overflow: hidden;
    width: min(720px, 100%);
    padding: 16px 18px 18px;
    background: linear-gradient(180deg, #1b1b23 0%, #150c2a 100%);
    border: 3px solid var(--stroke);
    border-radius: 16px;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--quality, #ffd23f) 40%, transparent),
                0 40px 110px -40px var(--quality, #000);
    text-align: center;
    transition: box-shadow .6s ease-out;
}
.reveal.landed .reveal-box {
    box-shadow: 0 0 0 2px var(--quality), 0 40px 120px -30px var(--quality);
}

/* the light, behind everything the box holds */
.fx-canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.reveal-box > *:not(.fx-canvas) { position: relative; }

/* ---- header: which crate this is ---- */
.reveal-head {
    display: flex; align-items: center; justify-content: center; gap: 12px;
    margin-bottom: 12px;
}
.reveal-head img {
    width: 108px; height: auto; image-rendering: auto;
    border: 2px solid #000; border-radius: 6px;
}
.reveal-head b {
    font-size: 25px; font-weight: normal; letter-spacing: 3px;
    color: var(--tint, #fff);
}
.reveal.done .reveal-head { display: none; }

/* ---- the reel ---- */
.reel {
    position: relative;
    height: 136px;
    overflow: hidden;
    background: #07040f;
    border: 3px solid #000;
    border-radius: 12px;
    box-shadow: inset 0 0 40px -10px #000;
}
.reveal.done .reel { display: none; }

.reel-track {
    position: absolute; left: 0; top: 0; bottom: 0;
    display: flex; gap: 8px; padding: 8px;
    will-change: transform;
}

.reel-item {
    position: relative;
    flex: 0 0 176px; width: 176px;   /* see ITEM_W in collection.js */
    display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
    padding-bottom: 4px;
    border-radius: 8px;
    background:
        linear-gradient(180deg, transparent 34%,
            color-mix(in srgb, var(--quality) 30%, transparent) 100%),
        #14141a;
    border-bottom: 3px solid var(--quality);
}
.reel-item.q-legendary, .reel-item.q-unique {
    background:
        linear-gradient(180deg, transparent 22%,
            color-mix(in srgb, var(--quality) 55%, transparent) 100%),
        #191119;
}
.ri-bay { flex: 1; display: flex; align-items: flex-end; justify-content: center; }
.reel-item b {
    font-size: 16px; font-weight: normal; letter-spacing: 1px;
    color: #d8d8e4;
    max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The one that stopped under the mark. */
.reel-item.win { animation: reel-win .5s cubic-bezier(.2, 1.4, .4, 1) both; z-index: 2; }
@keyframes reel-win {
    0%   { transform: scale(1); filter: brightness(1); }
    38%  { transform: scale(1.10); filter: brightness(2.1); }
    100% { transform: scale(1.05); filter: brightness(1.25); }
}

/* Edges fade out so the strip runs off into the dark instead of being cut. */
.reel-veil {
    position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(90deg, #07040f 0%, transparent 16%,
                                        transparent 84%, #07040f 100%);
}
/* The mark. Thin, bright, and the only pure white in the box. */
.reel-mark {
    position: absolute; left: 50%; top: -2px; bottom: -2px; width: 2px;
    transform: translateX(-50%);
    background: linear-gradient(180deg, transparent, #fff 12%, #fff 88%, transparent);
    box-shadow: 0 0 10px 1px color-mix(in srgb, var(--quality) 80%, #fff);
    pointer-events: none;
}
.reel-mark::before, .reel-mark::after {
    content: ''; position: absolute; left: 50%; width: 0; height: 0;
    transform: translateX(-50%);
    border-left: 7px solid transparent; border-right: 7px solid transparent;
}
.reel-mark::before { top: 0; border-top: 9px solid #fff; }
.reel-mark::after { bottom: 0; border-bottom: 9px solid #fff; }

/* ---- the card ---- */
.reveal-out { display: none; }
.reveal.done .reveal-out { display: block; animation: reveal-in .5s cubic-bezier(.16, .9, .3, 1) both; }
@keyframes reveal-in {
    from { opacity: 0; transform: scale(.92) translateY(14px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}

.reveal-quality {
    font-size: 20px; letter-spacing: 6px;
    color: var(--quality, #ffd23f);
    text-shadow: 0 0 18px color-mix(in srgb, var(--quality) 70%, transparent);
}
/* A slow sheen across the letters, so the name is not just white text. */
.reveal-name {
    font-size: 48px; letter-spacing: 2px; line-height: 1; margin: 2px 0 4px;
    background: linear-gradient(100deg,
        #fff 0%, #fff 38%,
        color-mix(in srgb, var(--quality) 85%, #fff) 50%,
        #fff 62%, #fff 100%);
    background-size: 260% 100%;
    -webkit-background-clip: text; background-clip: text;
    color: transparent;
    animation: name-sheen 3.4s ease-in-out infinite;
}
@keyframes name-sheen {
    0%, 100% { background-position: 130% 0; }
    50%      { background-position: -30% 0; }
}
.reveal-car { font-size: 20px; letter-spacing: 2px; color: var(--dim); }

.reveal-bay {
    display: flex; align-items: flex-end; justify-content: center;
    min-height: 210px;
    margin: 6px 0 10px;
}

.reveal-verdict {
    margin-top: 12px;
    font-size: 24px; letter-spacing: 3px;
    display: flex; align-items: center; justify-content: center; gap: 6px;
}
.reveal-verdict.fresh { color: #8bd427; }
.reveal-verdict.dupe { color: var(--dim); }

/* .btn carries margin-left:auto so it pushes right inside a card foot; here the
   pair wants to be centred, so it is cancelled rather than fought with. */
.reveal-foot { display: flex; justify-content: center; gap: 10px; margin-top: 16px; }
.reveal-foot .btn { margin-left: 0; }
.reveal-foot .btn[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
    .reveal-name, .reel-item.win, .reveal-out { animation: none !important; }
    .reveal-name { color: #fff; -webkit-text-fill-color: #fff; }
}
/* ===== collection groups ===== */

.section-head.sub { margin-top: 20px; }
.section-head.sub h2 { font-size: 22px; color: var(--dim); letter-spacing: 3px; }

/* A skin tile carries what it is worth as a strip along its top, so the gallery
   reads as a set with tiers rather than a wall of cars. */
.skin-tile { position: relative; }
.skin-tile[style*="--quality"]::before {
    content: '';
    position: absolute; left: 8px; right: 8px; top: 3px;
    height: 3px; border-radius: 2px;
    background: var(--quality);
    opacity: .85;
}
.skin-tile.locked[style*="--quality"]::before { opacity: .3; }

/* A gallery card carries its rarity the same way a crate tile does: the stage is
   lit in the quality colour (set in skinCard), and a legendary has a highlight
   travelling across it so it is findable in a grid without reading a label. */
.card.q-legendary .card-stage,
.card.q-unique .card-stage { overflow: hidden; }
.card.q-legendary .card-stage::after,
.card.q-unique .card-stage::after {
    content: '';
    position: absolute; inset: -40% -60%;
    pointer-events: none;
    background: linear-gradient(72deg,
        transparent 40%,
        color-mix(in srgb, var(--quality) 45%, #fff) 50%,
        transparent 60%);
    opacity: .16;
    mix-blend-mode: screen;
    animation: sheen 5.6s ease-in-out infinite;
}
.card.q-legendary .tier { box-shadow: 0 0 14px -2px var(--quality); }
@media (prefers-reduced-motion: reduce) {
    .card.q-legendary .card-stage::after, .card.q-unique .card-stage::after { animation: none; }
}

/* ===== the crate sheet =====
   What is in a container, over the page. Used wherever a screen has no room to
   hold the strip open - the studio's cup settings, today. Built once by
   crateSheet() in crates.js and reused for every crate. */
.sheet {
    position: fixed; inset: 0; z-index: 60;
    display: flex; align-items: center; justify-content: center;
    padding: 20px;
    background: rgba(6, 6, 9, .84);
    backdrop-filter: blur(2px);
}
.sheet[hidden] { display: none; }
.sheet-box {
    width: min(1100px, 100%);
    max-height: 90vh; overflow: auto;
    padding: 14px 16px 16px;
    background: var(--ink-2);
    border: 3px solid var(--stroke);
    border-left: 6px solid var(--tint, var(--line));
    border-radius: 14px;
}
.sheet-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.sheet-head img {
    width: 128px; height: auto; image-rendering: auto;
    border: 2px solid #000; border-radius: 6px;
}
.sheet-head b {
    font-size: 26px; font-weight: normal; letter-spacing: 2px; color: var(--tint);
}
.sheet-head span { font-size: 17px; letter-spacing: 1px; color: var(--dim); }
.sheet-head .btn { margin-left: auto; font-size: 17px; padding: 1px 12px; }

/* ===== the sign-in chip =====
   Sits with the wallet because it belongs to the same idea: what you have, and
   who it belongs to. Sized down from .credits on purpose — signing in matters,
   but not more than the balance it protects. */
.account { display: flex; align-items: center; gap: 8px; }
.account .signin,
.account .link-out {
    font-family: inherit;
    padding: 5px 14px;
    background: var(--ink-3);
    border: 3px solid var(--stroke);
    border-radius: 10px;
    color: var(--dim);
    font-size: 15px;
    letter-spacing: 2px;
    cursor: pointer;
}
.account .signin { color: #c9a6ff; }
.account .signin:hover { border-color: #9146ff; color: #e5d4ff; }
.account .signin:disabled { opacity: .55; cursor: default; border-color: var(--stroke); }
.account .who {
    padding: 4px 12px;
    background: var(--ink-3);
    border: 3px solid var(--stroke);
    border-radius: 10px;
    font-size: 18px;
    letter-spacing: 1px;
    max-width: 18ch;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.account .link-out:hover { color: #ff8b8b; border-color: #6b3a3a; }

/* The wordmark is the way home (nav.js wraps it). */
.brand-link { color: inherit; }
.brand-link:hover .brand { text-shadow: 0 2px 0 #ffd23f; }

/* ===== the top bar on a narrow screen =====
   The logo, six sections, a wallet and a sign-in chip need about 1100px. Below
   that the bar used to push the whole page sideways (761-1080px, found in the
   identity review, 2026-10-01). So the sections drop to a row of their own
   that scrolls sideways, and the page does not. */
@media (max-width: 1100px) {
    .topbar { flex-wrap: wrap; row-gap: 8px; }
    .topbar .nav {
        order: 3; flex: 1 0 100%;
        margin-left: 0;
        overflow-x: auto; scrollbar-width: none;
        padding-bottom: 2px;
    }
    .topbar .nav::-webkit-scrollbar { display: none; }
    .nav a { flex: 0 0 auto; }
    .nav a.studio { margin-left: 4px; }
}
@media (max-width: 760px) {
    .topbar { padding: 7px 16px; }
    .brand { font-size: 20px; }
    .credits, .shards { font-size: 20px; padding: 2px 10px; }
    .wrap { padding-left: 16px; padding-right: 16px; }
}


/* =============================================================================
   Vice '91 - the identity (owner, 2026-10-01; designed on preview/vapor/).
   Neon Night: violet ink, hot pink, cyan, gold. STREAM in brushed-metal
   pixels, Racers in pale neon script. The palette itself is the tokens and
   hex values above; what is here is the treatment.
   ========================================================================== */
body {
    background:
        radial-gradient(120% 60% at 50% -12%, #2a1452 0%, transparent 62%),
        #120a24;
    background-attachment: fixed;
}

/* the logo, small, in the top bar (nav.js builds the markup) */
.brand { position: relative; text-shadow: none; line-height: 1; padding: 2px 30px 10px 2px; }
.brand .bl-a {
    display: block;
    font-size: 30px; letter-spacing: 2px;
    /* At this size a text-stroke eats the pixel letters from inside, so the
       outline is a shadow instead, and the metal band is lighter than on the
       big logo. */
    background: linear-gradient(180deg, #ffffff 0%, #eef0ff 44%, #9a9cc8 50%, #e6f8ff 58%, #ffffff 100%);
    -webkit-background-clip: text; background-clip: text; color: transparent;
    filter: drop-shadow(1px 0 0 #1a0b2e) drop-shadow(-1px 0 0 #1a0b2e) drop-shadow(0 2px 0 #000);
}
.brand .bl-b {
    position: absolute; left: 52px; top: 15px;
    font-family: 'Mr Dafoe', 'Segoe Script', cursive; font-size: 27px; letter-spacing: 0;
    color: #ffe2f3; transform: rotate(-7deg);
    text-shadow: 0 0 1px #000, 2px 2px 0 #000, 0 0 8px #ff2d95, 0 0 16px #ff2d95;
}
.brand small { display: none; }
.brand-link:hover .bl-b { text-shadow: 0 0 1px #000, 2px 2px 0 #000, 0 0 10px #ff2d95, 0 0 22px #ff2d95; }

/* section heads in chrome */
.section-head h2 {
    background: linear-gradient(180deg, #ffffff 0%, #ffd6f5 45%, #ff7ac8 52%, #8be9ff 100%);
    -webkit-background-clip: text; background-clip: text; color: transparent;
    filter: drop-shadow(0 2px 0 #000);
}

/* the call to action: hot pink, dark enough under white text to read */
.btn { background: linear-gradient(180deg, #ff4fa6, #d61a7a 55%, #a3106a); }
.btn:not(.ghost):not(.go):not(:disabled) { box-shadow: 0 0 12px rgba(255, 45, 149, .35); }
.btn.ghost { background: var(--ink-3); }
.btn.go { background: #22e4ff; color: #10101a; }

/* tabs and chips: the "where am I" colour is cyan, so pink stays the action */
.tab.on { background: #22e4ff; color: #10101a; }
.chip.on { background: #22e4ff; border-color: #22e4ff; color: #10101a; }
.nav a.on { background: var(--hot); border-color: var(--hot); box-shadow: 0 0 10px rgba(255, 45, 149, .4); }

/* =============================================================================
   The way back to the LoKyo Arcade (nav.js): the maker's mark ahead of the
   game's wordmark, and the footer on every page that is not on stream.
   ========================================================================== */
.lokyo-mark {
    display: flex; align-items: center;
    height: 34px; padding-right: 14px; margin-right: -2px;
    border-right: 2px solid var(--line);
}
/* the arcade's own wordmark, black in the file, white here */
.lokyo-mark img { height: 22px; width: auto; image-rendering: auto; filter: brightness(0) invert(1); opacity: .85; }
.lokyo-mark:hover img, .lokyo-mark:focus-visible img {
    opacity: 1;
    filter: brightness(0) invert(1) drop-shadow(0 0 6px rgba(255, 45, 149, .7));
}
.lokyo-mark:focus-visible { outline: 3px solid #ffd23f; outline-offset: 3px; border-radius: 4px; }

.site-foot {
    position: relative;
    margin-top: 48px;
    border-top: 3px solid #000;
    background: linear-gradient(#150c2a, #0c071c);
}
/* the neon horizon along its top edge */
.site-foot::before {
    content: ''; position: absolute; left: 0; right: 0; top: 0; height: 2px;
    background: linear-gradient(90deg, transparent, #ff2d95 22%, #22e4ff 78%, transparent);
    opacity: .7;
}
.sf-in {
    max-width: 1180px; margin: 0 auto;
    padding: 28px 22px 18px;
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr));
    gap: 24px;
}
.sf-lockup { position: relative; display: inline-block; height: 46px; padding-right: 40px; }
.sf-lockup .bl-a {
    display: block;
    font-size: 32px; letter-spacing: 2px; line-height: 1;
    background: linear-gradient(180deg, #ffffff 0%, #eef0ff 44%, #9a9cc8 50%, #e6f8ff 58%, #ffffff 100%);
    -webkit-background-clip: text; background-clip: text; color: transparent;
    filter: drop-shadow(1px 0 0 #1a0b2e) drop-shadow(-1px 0 0 #1a0b2e) drop-shadow(0 2px 0 #000);
}
.sf-lockup .bl-b {
    position: absolute; left: 56px; top: 16px;
    font-family: 'Mr Dafoe', 'Segoe Script', cursive; font-size: 30px; line-height: 1;
    color: #ffe2f3; transform: rotate(-7deg);
    text-shadow: 0 0 1px #000, 2px 2px 0 #000, 0 0 8px #ff2d95, 0 0 16px #ff2d95;
}
.sf-about p { margin: 10px 0 14px; max-width: 360px; font-size: 18px; line-height: 1.3; color: var(--dim); }
.sf-arcade {
    display: inline-flex; align-items: center; gap: 10px;
    padding: 6px 12px 7px;
    border: 2px solid var(--line); border-radius: 9px;
    font-size: 16px; letter-spacing: 1px; color: #c9bce3;
}
.sf-arcade img { height: 18px; width: auto; image-rendering: auto; filter: brightness(0) invert(1); }
.sf-arcade:hover { border-color: var(--hot); color: #fff; }

.sf-col { display: flex; flex-direction: column; gap: 6px; }
.sf-col b { font-weight: normal; font-size: 14px; letter-spacing: 3px; color: #22e4ff; margin-bottom: 4px; }
/* the streamer's column in the streamer's gold, as the Studio is everywhere */
.sf-col[aria-label="STREAMERS"] b { color: #ffd23f; }
.sf-col a { width: max-content; max-width: 100%; font-size: 18px; letter-spacing: 1px; color: #c9bce3; }
.sf-col a:hover { color: #fff; }
.site-foot a:focus-visible { outline: 3px solid #ffd23f; outline-offset: 2px; border-radius: 4px; }

.sf-bar {
    max-width: 1180px; margin: 0 auto;
    padding: 12px 22px 22px;
    display: flex; justify-content: space-between; gap: 12px;
    border-top: 2px dashed var(--line);
    font-size: 15px; letter-spacing: 2px; color: var(--dim);
}

@media (max-width: 760px) {
    .lokyo-mark { height: 28px; padding-right: 10px; }
    .lokyo-mark img { height: 17px; }
    .sf-in { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px 16px; padding: 22px 16px 14px; }
    .sf-about { grid-column: 1 / -1; }
    .sf-bar { padding: 12px 16px 20px; flex-direction: column; gap: 4px; }
}
