Code/Demo/DemoTuningPanel.razor.scss
// ================================================================================================
// FIELD KIT UI SYSTEM · Vehicle Physics Kit · demo tuning lab
//
// SOURCE OF TRUTH: docs/design/ui-system/tokens.dc.html
// (+ components.dc.html for the parts, vehicle-physics.dc.html screen 03.A for
// this panel. 03.B/03.C/03.D on that page are the GAME's overlays, not this kit's.)
//
// DRIFT NOTE. s&box cannot express a library-to-library dependency, so a kit must never @import
// another kit's stylesheet. Every kit carries its OWN copy of the token values below. Nothing syncs
// them: if a value moves on the tokens page, hand-update it here and in every other kit.
//
// ENGINE-LEGAL SUBSET. The mockups are browser HTML and carry CSS this engine cannot parse. What
// changed on the way in, all applied below:
// · never `border: 1px solid x` -> border-width + border-color only. border-style is a parse
// error that aborts the WHOLE stylesheet and collapses the panel to 0x0.
// · never box-shadow (the previous version of this sheet had two; the alpha surfaces carry the
// depth instead).
// · never the `inset` shorthand -> top/left/width/height, expanded.
// · never letter-spacing, never a percent max-height on an absolute card, no glyphs outside the
// shipped font.
// · explicit px line-heights and explicit px font sizes, only from {12, 13, 14, 16}. The previous
// version declared NO font size at all and rode the engine default, so the panel had no type
// hierarchy; that is what the sizes below fix.
//
// CONTRAST LAW (overrides the mockups wherever they are dimmer): nothing a player reads to operate
// a control is dimmer than #E8EAED, key badges are pure #FFFFFF at weight 700. The expanded card
// carries a 42px close x, which is the only close affordance; no ESC badge anywhere.
//
// SLIDER MECHANIC, unchanged and load-bearing: .track is position:relative with pointer-events:all,
// .fill is position:absolute with pointer-events:none, so the fill grows without resizing the row
// and the drag stays measured against the track.
// ================================================================================================
// ---- base tokens (shared across kits, copied per kit) ----
$fk-panel-bg: rgba( 15, 17, 21, 0.92 );
$fk-border: rgba( 255, 255, 255, 0.08 );
$fk-border-hi: rgba( 255, 255, 255, 0.12 );
$fk-row: rgba( 255, 255, 255, 0.05 );
$fk-row-2: rgba( 255, 255, 255, 0.06 );
$fk-hover: rgba( 255, 255, 255, 0.10 );
$fk-track: rgba( 255, 255, 255, 0.12 );
$fk-track-hover: rgba( 255, 255, 255, 0.16 );
$fk-text-hi: #F2F4F7;
$fk-text: #E8EAED;
$fk-key-glyph: #FFFFFF;
// ---- kit accent (Vehicle Physics Kit · base hue 210) ----
$fk-accent: #4AD9F2;
$fk-accent-hover: #58E1F7;
$fk-accent-ink: #0A161A;
$fk-ui-font: Poppins, sans-serif;
$fk-mono-font: "Roboto Mono", monospace;
DemoTuningPanel {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
pointer-events: none;
font-family: $fk-ui-font;
.mono { font-family: $fk-mono-font; }
// Shared key chip: pure white bold on a gray plate, never tinted.
.kbd {
font-size: 14px;
line-height: 18px;
font-weight: 700;
color: $fk-key-glyph;
background-color: $fk-row;
border-width: 1px;
border-color: $fk-border-hi;
border-radius: 5px;
padding: 3px 8px;
}
// Top-right key legend (car switching). A persistent hint, not a panel, so it carries no close
// affordance: the mockup shows the same.
.legend {
position: absolute;
right: 40px;
top: 40px;
flex-direction: row;
align-items: center;
gap: 8px;
padding: 10px 14px;
background-color: $fk-panel-bg;
border-width: 1px;
border-color: $fk-border;
border-radius: 16px;
.title {
font-size: 13px;
line-height: 18px;
font-weight: 600;
color: $fk-text-hi;
}
}
.panel {
position: absolute;
left: 40px;
top: 40px;
width: 380px;
flex-direction: column;
gap: 12px;
padding: 20px;
background-color: $fk-panel-bg;
border-width: 1px;
border-color: $fk-border;
border-radius: 16px;
pointer-events: all;
.head {
flex-direction: row;
justify-content: space-between;
align-items: center;
.title {
font-size: 16px;
line-height: 22px;
font-weight: 700;
color: $fk-text-hi;
}
}
// Key chip + close x, kept together at the right end of the header.
.hr {
flex-direction: row;
align-items: center;
gap: 4px;
}
// 42px hit target on a 16px glyph. The negative margins pull the box back into the card's
// 20px padding so the header row stays compact.
.x {
font-size: 16px;
line-height: 22px;
color: $fk-text-hi;
width: 42px;
height: 42px;
margin: -8px -12px -8px 0px;
justify-content: center;
align-items: center;
border-radius: 6px;
cursor: pointer;
pointer-events: all;
transition: all 0.12s ease;
&:hover { background-color: $fk-hover; }
}
.hint {
font-size: 13px;
line-height: 20px;
color: $fk-text;
}
// Collapsed legend chip: same anchor as the expanded card (left/top 40px via .panel), sized
// to its content so it reads as the card's top-left corner waiting to grow. No close x: it
// IS the closed state.
&.chip {
width: auto;
padding: 10px 14px;
gap: 0px;
cursor: pointer;
.head {
gap: 8px;
justify-content: flex-start;
.title {
font-size: 13px;
line-height: 18px;
font-weight: 600;
color: $fk-text-hi;
}
}
}
.dials {
flex-direction: column;
gap: 12px;
.dial {
flex-direction: column;
gap: 6px;
}
.drow {
flex-direction: row;
justify-content: space-between;
align-items: center;
.dname {
font-size: 13px;
line-height: 20px;
color: $fk-text-hi;
}
.dval {
font-size: 14px;
line-height: 18px;
color: $fk-text;
}
}
.dctl {
flex-direction: row;
align-items: center;
gap: 10px;
.step {
font-size: 14px;
line-height: 18px;
width: 28px;
height: 28px;
flex-shrink: 0;
justify-content: center;
align-items: center;
color: $fk-text-hi;
background-color: $fk-row-2;
border-width: 1px;
border-color: $fk-hover;
border-radius: 6px;
cursor: pointer;
transition: all 0.12s ease;
&:hover {
color: $fk-accent-ink;
background-color: $fk-accent;
}
}
.track {
// Click-to-jump + drag-to-scrub hit box. Events must land on the track (not the
// fill) so the mouse local position stays track-relative: pointer-events all
// here, none on the fill.
position: relative;
flex-grow: 1;
height: 14px;
border-radius: 99px;
background-color: $fk-track;
pointer-events: all;
cursor: pointer;
&:hover { background-color: $fk-track-hover; }
.fill {
position: absolute;
left: 0px;
top: 0px;
height: 100%;
// min-width keeps the pill from collapsing below its own radius at the bottom
// of a dial's range: a dial at its minimum still reads as a slider.
min-width: 14px;
border-radius: 99px;
background-color: $fk-accent;
pointer-events: none;
}
}
}
// Cycling value chip (Assists, Tires): accent fill, ink text, mono label.
.cycle {
font-size: 14px;
line-height: 18px;
font-weight: 600;
justify-content: center;
align-items: center;
color: $fk-accent-ink;
background-color: $fk-accent;
border-radius: 6px;
padding: 4px 14px;
cursor: pointer;
transition: all 0.12s ease;
&:hover { background-color: $fk-accent-hover; }
}
}
.foot {
flex-direction: column;
gap: 8px;
.btn {
font-size: 13px;
line-height: 18px;
font-weight: 600;
justify-content: center;
align-items: center;
color: $fk-text-hi;
background-color: $fk-row-2;
border-width: 1px;
border-color: $fk-hover;
border-radius: 10px;
padding: 11px 0px;
cursor: pointer;
transition: all 0.12s ease;
&:hover { background-color: $fk-hover; }
}
}
}
}