Code/Studio/TipsStudioPanel.razor.scss
// ============================================================================================
// TIPS STUDIO stylesheet. The approved Field Kits UI system (docs/design/ui-system) translated into
// the s&box panel-CSS subset: a centred 1360px modal over a dim scrim, three columns, flex and px
// only. Self-contained on purpose: s&box compiles SCSS per file at runtime, so an @import of a
// game-side theme would break wherever this kit is vendored.
//
// RETINT: change the three $fk-accent values below and nothing else moves.
//
// ============================================================================================
// TYPE. This panel ships the mockup's scale: 16 / 14 / 13 / 12 with exact px line heights
// (16/22 titles, 14/18 mono values keycaps steppers and dropdowns, 13/20 body labels buttons and
// tabs, 12/16 kickers captions and meta). Four distinct sizes, inside the engine's per-assembly
// budget, and the same pairings the other kits ship. No letter-spacing anywhere, that one really
// does corrupt glyphs.
//
// AN EARLIER NOTE HERE CLAIMED font-size RENDERS TEXT AS SOLID BLOCKS, AND STRIPPED EVERY SIZE OUT
// OF THIS PANEL. That claim was wrong and it is retracted. It was read off MCP camera captures: the
// capture path rasterizes sized text as filled grey blocks, so a screenshot of any panel that
// declares font-size looks corrupted. On the physical screen those same panels render pin sharp,
// owner-verified on engine 26.07.22 (2026-07-31) against the Sound Mixer panels, which declare all
// four sizes and are crisp.
//
// So a capture cannot verify TEXT. Geometry is judgeable in a capture (boxes, spacing, corners,
// fills); glyphs are not, and the check for text is the owner's eye on a real screen. Never delete
// a font-size on screenshot evidence again.
// ============================================================================================
//
// OTHER ENGINE RULES this file obeys, each of which has cost someone a session:
// - Borders are border-width + border-color ONLY. A `border:` shorthand or any `border-style` is a
// parse error that aborts the whole stylesheet and collapses the panel to 0x0, and SCSS compiles
// in the editor at runtime, so a headless build never sees it.
// - No box-shadow, no letter-spacing, no backdrop-filter, no inset shorthand.
// - Scroll regions are a FIXED px height under a pinned header. A percentage max-height on an
// absolutely positioned card measures against a parent the style engine has not sized yet, and
// the card collapses.
// - Wrapping rows space their children with margins, not gap, and a scrolling column never gets gap.
// - A fixed-size flex child declares BOTH width (or height) and flex-basis: flex-basis wins for the
// main axis, and an inherited 0 basis collapses the column to nothing.
// - Text nodes stay inside one line's worth of box. A run that overflows its box rasterizes as a
// solid grey block or clips to blank, so long strings are chunked before they reach the markup.
// - Text stays bright. #E8EAED is the floor for anything an author reads to operate the panel;
// key glyphs are pure white at weight 700.
// ============================================================================================
// ---- accent: the whole retint surface ----
$fk-accent: #e3c85e;
$fk-accent-hover: #edd478;
$fk-accent-ink: #1a160a;
// ---- base surfaces ----
$fk-panel-bg: rgba( 15, 17, 21, 0.94 );
$fk-scrim: rgba( 6, 8, 10, 0.55 );
$fk-well: #14171c;
$fk-toast-bg: rgba( 15, 17, 21, 0.92 );
$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-border: rgba( 255, 255, 255, 0.08 );
$fk-border-hi: rgba( 255, 255, 255, 0.12 );
$fk-border-soft: rgba( 255, 255, 255, 0.05 );
$fk-accent-edge: rgba( 227, 200, 94, 0.60 );
// ---- text ----
$fk-text-hi: #f2f4f7;
$fk-text: #e8eaed;
$fk-key-glyph: #ffffff;
$fk-danger: #ff6b6b;
$fk-danger-bg: rgba( 255, 107, 107, 0.10 );
$fk-danger-edge: rgba( 255, 107, 107, 0.35 );
// ---- pad chip (controller blue, the one non-accent hue) ----
$fk-pad-bg: rgba( 60, 70, 90, 0.60 );
$fk-pad-edge: rgba( 150, 190, 240, 0.65 );
// FONTS ARE DECLARED INLINE, never through a variable, and the UI family is the BARE name. The engine
// auto-registers fonts by family name and resolves them itself; the working precedent everywhere in the
// kits is `font-family: Poppins, sans-serif;` and `font-family: "Roboto Mono", monospace;`. A quoted
// "Poppins" behind a "Segoe UI" fallback did not resolve, and every element that should have been
// Poppins fell back to the engine default, which reads as mono. Owner caught it on a real screen; a
// capture cannot show it (font FACE resolution is not screenshot-verifiable).
// The three-column body height, and the height of one control row. Every fixed box below is derived
// from these two, so moving one keeps the columns aligned.
//
// Both are the mockup's own numbers. The control row is the mockup's 38 (9 and 9 padding, 2 border,
// over a mono line), and the body is the mockup's 593. They were 660 / 42 while this sheet had no
// font sizes and every line stood at the engine default.
//
// THE ONE NUMBER THAT IS NOT THE MOCKUP'S, and the reason the fixed boxes below are not either:
// this engine draws a text line HALF AGAIN as tall as the px line-height you declare. Measured on a
// live 1:1 capture (2026-07-31, engine 26.07.22): 16/22 renders a 33px line, 13/20 renders 30. So a
// 13px button is 9 + 9 + 2 + 30 = 50 tall, not 40, and every stack of them runs long. Keep the
// mockup's outer boxes and let the two scroll regions absorb it: measure, do not assume.
$ts-body-h: 593px;
$ts-ctrl-h: 38px;
// ============================================================================================
// Root and scrim
// ============================================================================================
// The root covers the screen and takes NO pointer events: without that it hit-tests every pixel and
// swallows the clicks meant for the game underneath. Root none, scrim and modal all.
.ts-root {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
pointer-events: none;
font-family: Poppins, sans-serif;
color: $fk-text;
}
.ts-scrim {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
flex-direction: row;
align-items: center;
justify-content: center;
background-color: $fk-scrim;
pointer-events: all;
}
.ts-modal {
width: 1360px;
flex-basis: 1360px;
flex-direction: column;
flex-shrink: 0;
background-color: $fk-panel-bg;
border-width: 1px;
border-color: $fk-border;
border-radius: 16px;
pointer-events: all;
}
// ============================================================================================
// Header
// ============================================================================================
.ts-hdr {
flex-direction: row;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
padding-top: 20px;
padding-right: 24px;
padding-bottom: 16px;
padding-left: 24px;
border-bottom-width: 1px;
border-bottom-color: $fk-border;
}
.ts-hdr-left {
flex-direction: row;
align-items: center;
}
.ts-title {
font-size: 16px;
line-height: 22px;
font-weight: 700;
text-transform: uppercase;
color: $fk-text-hi;
margin-right: 12px;
}
.ts-hdr-meta {
font-family: "Roboto Mono", monospace;
font-size: 12px;
line-height: 16px;
color: $fk-text;
flex-shrink: 0;
}
// A generous target: this is the close affordance, and a small one is a fight.
.ts-x {
font-size: 16px;
line-height: 22px;
width: 42px;
flex-basis: 42px;
height: 42px;
flex-shrink: 0;
align-items: center;
justify-content: center;
margin-top: -8px;
margin-right: -12px;
margin-bottom: -8px;
border-radius: 6px;
font-weight: 700;
color: $fk-text-hi;
cursor: pointer;
pointer-events: all;
transition: all 0.1s ease;
&:hover {
background-color: $fk-hover;
}
}
// ============================================================================================
// The three columns
// ============================================================================================
.ts-cols {
flex-direction: row;
flex-shrink: 0;
height: $ts-body-h;
flex-basis: $ts-body-h;
}
// ---- left: the merged catalog ----
.ts-left {
width: 300px;
flex-basis: 300px;
height: $ts-body-h;
flex-shrink: 0;
flex-direction: column;
padding: 16px;
border-right-width: 1px;
border-right-color: $fk-border;
}
.ts-list-hdr {
flex-direction: row;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
padding-bottom: 8px;
margin-bottom: 10px;
border-bottom-width: 1px;
border-bottom-color: $fk-border;
}
.ts-list-t {
font-size: 13px;
line-height: 20px;
font-weight: 600;
color: $fk-text-hi;
flex-shrink: 0;
}
.ts-list-m {
font-family: "Roboto Mono", monospace;
font-size: 12px;
line-height: 16px;
color: $fk-text;
flex-shrink: 0;
}
.ts-list {
// The mockup's 472 less the 20 the taller lines cost the header and the button under it, so the
// column still ends 16 above the modal's bottom edge (32 padding + 49 header + 452 + 10 + 50).
height: 452px;
flex-basis: 452px;
flex-shrink: 0;
flex-direction: column;
overflow-y: scroll;
margin-bottom: 10px;
pointer-events: all;
}
.ts-row {
flex-direction: row;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
background-color: $fk-row;
border-radius: 6px;
padding: 7px 10px;
margin-bottom: 4px;
cursor: pointer;
pointer-events: all;
transition: all 0.1s ease;
&:hover {
background-color: $fk-hover;
}
// flex-shrink 0 is load bearing. A text node squeezed narrower than its own run does not ellipsis
// or wrap here, it rasterizes as a solid filled block, which is exactly what a long id next to a
// state chip did. Better to overflow the row than to blank the id out.
.ts-row-id {
font-family: "Roboto Mono", monospace;
font-size: 14px;
line-height: 18px;
flex-shrink: 0;
color: $fk-text;
margin-right: 10px;
}
.ts-row-meta {
flex-direction: row;
align-items: center;
flex-shrink: 0;
}
.ts-row-src {
font-family: "Roboto Mono", monospace;
font-size: 12px;
line-height: 16px;
flex-shrink: 0;
color: $fk-text;
}
.ts-row-state {
font-family: "Roboto Mono", monospace;
font-size: 12px;
line-height: 16px;
flex-shrink: 0;
font-weight: 700;
color: $fk-accent-ink;
background-color: $fk-accent;
border-radius: 5px;
padding: 0px 6px;
}
// The row being edited: accent fill, ink text, exactly as the draft row reads in the mockup. The
// children name their own colour, so the override has to name them too.
&.on {
background-color: $fk-accent;
.ts-row-id {
color: $fk-accent-ink;
}
.ts-row-src {
color: $fk-accent-ink;
}
.ts-row-state {
color: $fk-accent-ink;
background-color: rgba( 26, 22, 10, 0.18 );
}
&:hover {
background-color: $fk-accent-hover;
}
}
}
.ts-left-btns {
flex-direction: row;
flex-shrink: 0;
}
// ---- middle: the draft editor ----
// flex-grow 1 over a ZERO basis, so the column is exactly the width the other two leave behind
// rather than the width its widest row would like to be.
.ts-mid {
flex-grow: 1;
flex-basis: 0px;
height: $ts-body-h;
flex-direction: column;
padding: 16px 24px;
overflow-y: scroll;
pointer-events: all;
}
// ---- right: preview and bake ----
.ts-rail {
width: 460px;
flex-basis: 460px;
height: $ts-body-h;
flex-shrink: 0;
flex-direction: column;
padding: 16px 20px;
border-left-width: 1px;
border-left-color: $fk-border;
}
// ============================================================================================
// Fields
// ============================================================================================
// A row of fields side by side.
.ts-frow {
flex-direction: row;
flex-shrink: 0;
margin-bottom: 14px;
}
.ts-field {
flex-direction: column;
margin-right: 12px;
// 200, where the mockup draws 280 for the Id and for a trigger's Input action. 280 does not fit
// either row and the type scale did not change that: the middle column is 548 wide, and the Id row
// spends 12 + 150 on Priority, which would leave the Prerequisites field 98 for a value that runs
// to 118 at 14px mono ("handbrake-turn") plus 50 of padding and chevron, and a run that overflows
// its box rasterizes as a solid block. The trigger rows are worse: they compose up to three fields
// (param, a 150 stepper, and Max show seconds, whose own stepper will not shrink below 148), which
// needs 602 of a 548 box at 280 and fits with room at 200. Measure the widest composition before
// widening this.
&.w200 { width: 200px; flex-basis: 200px; flex-shrink: 0; }
// 150px is the mockup's Priority column, and it is also the narrowest this box can honestly be:
// the stepper inside it is 28 + 6 + 80 + 6 + 28, and none of those five children shrink, so a
// 130px declaration was a box lying about its own content and stealing the difference from the
// field beside it.
&.w150 { width: 150px; flex-basis: 150px; flex-shrink: 0; }
&.w120 { width: 120px; flex-basis: 120px; flex-shrink: 0; }
&.grow { flex-grow: 1; flex-basis: 0px; }
&.last { margin-right: 0px; }
}
.ts-lab {
font-size: 13px;
line-height: 20px;
color: $fk-text-hi;
margin-bottom: 6px;
flex-shrink: 0;
}
// Label on the left, a short semantic note on the right.
.ts-lab-row {
flex-shrink: 0;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 6px;
.ts-lab {
margin-bottom: 0px;
}
.ts-cap {
font-size: 12px;
line-height: 16px;
margin-top: 0px;
}
}
// A section's title beside its one-line blurb.
.ts-sec-hd {
flex-shrink: 0;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
.ts-sec-t {
font-size: 12px;
line-height: 16px;
margin-bottom: 0px;
}
}
.ts-cap {
flex-shrink: 0;
font-family: "Roboto Mono", monospace;
color: $fk-text;
margin-top: 6px;
// Sitting in a row rather than under a control.
&.flat {
margin-top: 0px;
}
// The line under the preview well, one block-gap below the last card, as the mockup draws it.
&.well {
margin-top: 14px;
}
}
// A text box. Its height is pinned so it lines up with the steppers and dropdowns beside it.
.ts-in {
flex-shrink: 0;
font-family: "Roboto Mono", monospace;
font-size: 14px;
line-height: 18px;
height: $ts-ctrl-h;
color: $fk-text;
background-color: $fk-row;
border-width: 1px;
border-color: rgba( 255, 255, 255, 0.10 );
border-radius: 6px;
padding: 0px 12px;
pointer-events: all;
&:focus {
border-color: $fk-accent-edge;
}
}
// ---- stepper: minus, value, plus ----
.ts-step {
flex-direction: row;
align-items: center;
flex-shrink: 0;
}
.ts-stp {
width: 28px;
flex-basis: 28px;
height: $ts-ctrl-h;
flex-shrink: 0;
align-items: center;
justify-content: center;
font-family: "Roboto Mono", monospace;
font-size: 14px;
line-height: 18px;
color: $fk-text-hi;
background-color: $fk-row-2;
border-width: 1px;
border-color: rgba( 255, 255, 255, 0.10 );
border-radius: 6px;
cursor: pointer;
pointer-events: all;
transition: all 0.1s ease;
&:hover {
color: $fk-accent-ink;
background-color: $fk-accent;
}
}
.ts-val {
flex-grow: 1;
height: $ts-ctrl-h;
align-items: center;
justify-content: center;
font-family: "Roboto Mono", monospace;
font-size: 14px;
line-height: 18px;
color: $fk-text;
background-color: $fk-row;
border-width: 1px;
border-color: rgba( 255, 255, 255, 0.10 );
border-radius: 6px;
margin-left: 6px;
margin-right: 6px;
&.w80 {
width: 80px;
flex-basis: 80px;
flex-grow: 0;
flex-shrink: 0;
}
}
// ============================================================================================
// Dropdown. The engine has no native select, so this is a field that opens a flat option list
// underneath it, in flow: an absolutely positioned popup would need a z-order this style engine
// does not give siblings.
// ============================================================================================
.ts-drop {
flex-direction: column;
flex-shrink: 0;
}
.ts-drop-face {
flex-shrink: 0;
flex-direction: row;
justify-content: space-between;
align-items: center;
height: $ts-ctrl-h;
background-color: $fk-row;
border-width: 1px;
border-color: rgba( 255, 255, 255, 0.10 );
border-radius: 6px;
padding: 0px 12px;
cursor: pointer;
pointer-events: all;
transition: all 0.1s ease;
&:hover {
border-color: $fk-accent-edge;
}
// Open: an accent hairline says which field the list below belongs to.
&.open {
background-color: $fk-row-2;
border-color: $fk-accent-edge;
}
}
.ts-drop-val {
font-family: "Roboto Mono", monospace;
font-size: 14px;
line-height: 18px;
flex-shrink: 0;
color: $fk-text;
}
// The chevron. The mockup's ▾ is a Geometric Shapes glyph, which none of the shipped fonts cover, so
// it would render as tofu. This is the same mark the engine's own DropDown draws: the Material Icons
// ligature `expand_more`, which ships in addons/base/Assets/fonts and is what Add.Icon() uses.
.ts-chev {
flex-shrink: 0;
font-family: "Material Icons";
font-size: 16px;
line-height: 22px;
color: $fk-text-hi;
margin-left: 8px;
}
// A long option list gets a FIXED height and scrolls. max-height is the shape that compresses
// unpredictably here, so the markup adds `tall` once there are more options than fit.
.ts-drop-list {
flex-direction: column;
background-color: $fk-panel-bg;
border-width: 1px;
border-color: $fk-border-hi;
border-radius: 6px;
padding: 4px;
margin-top: 4px;
pointer-events: all;
&.tall {
height: 232px;
flex-basis: 232px;
flex-shrink: 0;
overflow-y: scroll;
}
}
.ts-drop-opt {
flex-shrink: 0;
font-family: "Roboto Mono", monospace;
font-size: 14px;
line-height: 18px;
color: $fk-text;
border-radius: 5px;
padding: 5px 10px;
cursor: pointer;
pointer-events: all;
transition: all 0.1s ease;
&:hover {
background-color: $fk-hover;
}
&.on {
color: $fk-accent-ink;
background-color: $fk-accent;
&:hover {
background-color: $fk-accent-hover;
}
}
}
// ============================================================================================
// Sections, chips, warnings
// ============================================================================================
.ts-sec {
flex-direction: column;
flex-shrink: 0;
border-top-width: 1px;
border-top-color: $fk-border;
padding-top: 12px;
margin-bottom: 14px;
}
.ts-sec-t {
font-family: "Roboto Mono", monospace;
font-weight: 700;
text-transform: uppercase;
color: $fk-accent;
margin-bottom: 8px;
}
// flex-shrink 0 is not optional on a child of a scrolling column. Without it the row is the one
// thing in the middle column that can be squeezed, and a squeezed wrap row collapses to no height
// and paints its chips over the block below (the prerequisite chip landed on top of the Text
// label). Every other block in this column already declares it.
.ts-chips {
flex-direction: row;
flex-wrap: wrap;
align-items: center;
flex-shrink: 0;
margin-bottom: 2px;
// Standing on its own under a field rather than inside a section.
&.block {
margin-bottom: 12px;
}
}
.ts-chip {
flex-shrink: 0;
font-weight: 500;
color: $fk-text-hi;
background-color: $fk-row;
border-radius: 6px;
padding: 4px 12px;
margin-right: 6px;
margin-bottom: 6px;
cursor: pointer;
pointer-events: all;
transition: all 0.1s ease;
&:hover {
background-color: $fk-hover;
}
&.on {
font-weight: 600;
color: $fk-accent-ink;
background-color: $fk-accent;
&:hover {
background-color: $fk-accent-hover;
}
}
&.mono {
font-family: "Roboto Mono", monospace;
font-size: 13px;
line-height: 20px;
}
&.drop {
color: $fk-danger;
}
}
// A composed child trigger, indented behind an accent edge.
.ts-child .ts-frow {
margin-bottom: 0px;
}
.ts-child {
flex-direction: column;
flex-shrink: 0;
background-color: $fk-row;
border-radius: 6px;
border-left-width: 3px;
border-left-color: $fk-accent;
padding: 10px 12px;
margin-bottom: 8px;
}
.ts-warn {
flex-direction: row;
align-items: flex-start;
flex-shrink: 0;
background-color: $fk-danger-bg;
border-width: 1px;
border-color: $fk-danger-edge;
border-radius: 6px;
padding: 9px 12px;
margin-bottom: 8px;
.ts-warn-b {
font-family: "Roboto Mono", monospace;
font-size: 12px;
line-height: 16px;
font-weight: 700;
color: $fk-danger;
margin-right: 10px;
}
.ts-warn-t {
flex-direction: column;
flex-grow: 1;
}
.ts-warn-l {
font-size: 13px;
line-height: 20px;
flex-shrink: 0;
color: $fk-text;
}
}
// The empty state: a bright line and a short instruction inside a hairline well.
.ts-empty {
flex-direction: column;
align-items: center;
flex-shrink: 0;
border-width: 1px;
border-color: $fk-border;
border-radius: 10px;
padding: 24px 16px;
.ts-empty-t {
font-size: 13px;
line-height: 20px;
flex-shrink: 0;
font-weight: 600;
color: $fk-text-hi;
margin-bottom: 6px;
}
.ts-empty-l {
font-size: 13px;
line-height: 20px;
flex-shrink: 0;
color: $fk-text;
}
}
// ============================================================================================
// Buttons
// ============================================================================================
.ts-btn-row {
flex-direction: row;
align-items: center;
flex-shrink: 0;
&.pad {
margin-top: 8px;
}
}
.ts-btn {
font-size: 13px;
line-height: 20px;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-weight: 600;
color: $fk-text-hi;
background-color: $fk-row-2;
border-width: 1px;
border-color: rgba( 255, 255, 255, 0.10 );
border-radius: 10px;
padding: 9px 18px;
cursor: pointer;
pointer-events: all;
transition: all 0.1s ease;
&:hover {
background-color: $fk-hover;
}
// Primary: accent fill, ink text. No hairline, the fill is the edge.
&.pri {
color: $fk-accent-ink;
background-color: $fk-accent;
border-width: 0px;
border-color: $fk-accent;
&:hover {
background-color: $fk-accent-hover;
}
}
&.grow {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0px;
padding-left: 0px;
padding-right: 0px;
}
&.small {
padding: 6px 14px;
}
&.gap {
margin-right: 8px;
}
}
// ============================================================================================
// The right rail: live preview and bake-out
// ============================================================================================
.ts-rail-hdr {
flex-direction: row;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
margin-bottom: 12px;
}
.ts-kicker {
font-family: "Roboto Mono", monospace;
font-size: 12px;
line-height: 16px;
font-weight: 700;
text-transform: uppercase;
color: $fk-accent;
}
// Everything between the pinned header and the pinned bake block. A FIXED height that scrolls, so a
// long tip grows the preview cards without ever pushing the bake buttons off the bottom of the card.
//
// The height is what the rail has left over, and it has to be kept in step by hand, at the line
// heights this engine actually draws (see the note at the top of the file): 593 body, less 32
// padding, less 56 for the header row and its margin, less 50 for the device picker row, less 159
// for the bake block (12 margin, 1 rule, 12 padding, a 50 button row, a 32 caption line, and an
// 8 plus 44 second button row). Under-count it and the bake block hangs below the modal.
.ts-rail-body {
height: 296px;
flex-basis: 296px;
flex-shrink: 0;
flex-direction: column;
overflow-y: scroll;
pointer-events: all;
}
.ts-well {
flex-direction: column;
flex-shrink: 0;
background-color: $fk-well;
border-width: 1px;
border-color: $fk-border-soft;
border-radius: 10px;
padding: 16px;
margin-bottom: 12px;
}
.ts-pv {
flex-direction: column;
flex-shrink: 0;
// The mockup stacks the two preview blocks 14px apart inside the well.
margin-bottom: 14px;
&.last {
margin-bottom: 0px;
}
}
.ts-pv-lab {
font-family: "Roboto Mono", monospace;
font-size: 12px;
line-height: 16px;
color: $fk-text;
margin-bottom: 6px;
flex-shrink: 0;
}
// A row of small pickers under the preview: which device the real lower-left card reads as.
.ts-pv-row {
flex-direction: row;
flex-wrap: wrap;
align-items: center;
flex-shrink: 0;
margin-bottom: 6px;
}
.ts-pv-key {
font-size: 13px;
line-height: 20px;
color: $fk-text-hi;
margin-right: 8px;
margin-bottom: 6px;
}
.ts-out {
flex-direction: column;
flex-shrink: 0;
border-top-width: 1px;
border-top-color: $fk-border;
padding-top: 12px;
margin-top: 12px;
}
.ts-out-line {
flex-shrink: 0;
font-family: "Roboto Mono", monospace;
font-size: 12px;
line-height: 16px;
color: $fk-text;
margin-top: 8px;
&.inline {
margin-top: 0px;
margin-left: 10px;
}
}
// ============================================================================================
// The toast preview cards. Same component as the shipped card (TipsDisplay), restated here because
// a stylesheet does not reach into another panel's tree; keep the two in sync when retinting.
// ============================================================================================
.tsp-card {
flex-direction: row;
align-items: stretch;
flex-shrink: 0;
background-color: $fk-toast-bg;
border-width: 1px;
border-color: $fk-border;
border-radius: 10px;
overflow: hidden;
}
// Square bar, rounded at its ends by the card's `overflow: hidden` above, exactly as the mockup
// builds it. A radius of its own is what put a notch in the corner: a radius scales down to fit its
// own box, so 9px on a 3px-wide bar comes out as a 3px curve, and that curve inside the card's 10px
// one reads as a step. Keep this in step with TipsDisplay's .stripe.
.tsp-stripe {
width: 3px;
flex-basis: 3px;
flex-shrink: 0;
background-color: $fk-accent;
}
.tsp-in {
flex-grow: 1;
flex-direction: row;
align-items: flex-start;
padding: 12px 12px 12px 14px;
}
.tsp-glyph {
font-size: 14px;
line-height: 18px;
flex-shrink: 0;
color: $fk-text;
margin-right: 8px;
}
.tsp-body {
flex-grow: 1;
flex-direction: column;
flex-shrink: 0;
}
.tsp-kicker {
font-family: "Roboto Mono", monospace;
font-size: 12px;
line-height: 16px;
font-weight: 700;
text-transform: uppercase;
color: $fk-text-hi;
margin-bottom: 3px;
flex-shrink: 0;
}
.tsp-text {
flex-direction: row;
flex-wrap: wrap;
align-items: center;
font-size: 13px;
font-weight: 500;
color: $fk-text;
// 13/20, the scale's body metric, carried by every child of the row so a wrapped second line
// clears the key chips on the line above by the same rhythm the mockup draws.
line-height: 20px;
span {
font-size: 13px;
line-height: 20px;
color: $fk-text;
// The mockup spaces every child of this row by 3px. A wrapping row cannot use gap, so each
// child carries the same right margin instead: a run against a chip gets the same air as a
// chip against a run, and the pad pill stops touching the word after it.
margin-right: 3px;
}
// A chip never splits across a wrapped line: flex + nowrap + no-shrink keeps it atomic.
.tsp-key {
display: flex;
align-items: center;
flex-shrink: 0;
white-space: nowrap;
font-family: "Roboto Mono", monospace;
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-left: 7px;
padding-right: 7px;
margin-left: 0px;
margin-right: 3px;
}
// The pad chip is the same atom rounded into a pill and tinted cooler, so a controller prompt
// reads apart from a keycap at a glance.
.tsp-pad {
display: flex;
align-items: center;
flex-shrink: 0;
white-space: nowrap;
font-family: "Roboto Mono", monospace;
font-size: 14px;
line-height: 18px;
font-weight: 700;
color: $fk-key-glyph;
background-color: $fk-pad-bg;
border-width: 1px;
border-color: $fk-pad-edge;
border-radius: 99px;
padding-left: 10px;
padding-right: 10px;
margin-left: 0px;
margin-right: 3px;
}
}
.tsp-x {
font-size: 16px;
line-height: 22px;
width: 42px;
flex-basis: 42px;
height: 42px;
flex-shrink: 0;
align-items: center;
justify-content: center;
margin-top: -8px;
margin-right: -8px;
margin-bottom: -8px;
border-radius: 6px;
color: $fk-text-hi;
}