Starwind
Interface Style Guide · v0.0.21 · style_guide() in the dev console
src/styles/global.css; one component .css file accompanies each .tsx. The whole interface is presented as a shipboard operating system — windows, chrome bars, and status readouts on the ship's console.
01 · Color Palette
Backgrounds
Decoration — borders, fills, dots (never text)
Text — AA-compliant on --deep
Never apply CSS opacity to text — use --text-muted / --text-disabled instead.
Text accents — brighter, interactive
Station type & specialty
02 · Typography
Three families, loaded via <link> in index.html.
Type scale
| Token | Size | LH | Weight | Used for |
|---|---|---|---|---|
--fs-display | 28px | 1.15 | 700 | Title screen, game over, arrival modal |
--fs-h1 | 20px | 1.25 | 700 | Event names, good-info name |
--fs-h2 | 16px | 1.3 | 700 | Info-card names, comms titles, panel headers |
--fs-h3 | 14px | 1.35 | 600 | Taglines, schematic names |
--fs-body | 14px | 1.55 | 400 | Body text, menu buttons, descriptions |
--fs-small | 13px | 1.5 | 400 | Secondary text, mission descriptions |
--fs-micro | 12px | 1.4 | 500 | Chrome labels, metadata, button labels |
--fs-num | 14px | 1.2 | 700 | Credits, fuel, distances |
--fs-num-sm | 13px | 1.2 | 500 | Costs, quantities, rep values |
Each token has matching --fs-*, --lh-*, --fw-* vars. Compose with font: var(--fw-x) var(--fs-x)/var(--lh-x) var(--font-x).
03 · Layout System
Viewport & root
| Element | Rule |
|---|---|
body | height: 100vh; display: flex; center; overflow: hidden; background: #000 |
#root | min(1680px…) × min(1050px…) — 16:10 canvas, letterboxed, border-radius: 8px, background: var(--void) |
.app-shell | flex: 1; display: flex; flex-direction: column; min-height: 0 |
Borders & radius
| Context | Value |
|---|---|
| Panel borders | 0.5px solid var(--panel) — never 1px |
| Accent left border | border-left: 3px solid var(--accent-cyan) (selected/active) |
| Panel radius | var(--radius) = 8px |
| Card / button radius | 4px |
| Pip / badge radius | 2–3px |
| Window composition | Title bar (.chrome-bar) + body + optional .status-bar — see §05 |
Scanlines (CRT)
One global <div class="scanlines"> in App.tsx, pointer-events: none; z-index: 9999, always on.
background: repeating-linear-gradient( to bottom, transparent 0px, transparent 3px, rgba(0,0,0,0.15) 3px, rgba(0,0,0,0.15) 4px );
Panel flex pattern
.panel-root {
flex: 1; /* fill available space */
display: flex;
flex-direction: column;
min-height: 0; /* allow scrolling children */
overflow: hidden; /* or overflow-y: auto when scrollable */
}
04 · Icons & Glyphs
Starwind uses no icon font or SVG sprite — every icon is a Unicode glyph rendered in a colored <span>. Module/system icons live as components in src/components/icons/; planet icons come from getPlanetIcon() in engine/travel.ts; the rest are inline in component JSX.
Module & system icons src/components/icons/
Default size 16px via size prop. ScannerIcon uses --cyan; ShieldIcon & RepairIcon render in currentColor (purple / cargo in context). The schematic maps these via ICON_MAP keyed on module type.
Planet-type icons getPlanetIcon()
Tinted at render with getPlanetColor() (mining = purple, agriculture = green, technology = blue).
Bars, status & checkboxes
Navigation, arrows & waypoints
Notifications & trade markers
Separators & utility
05 · Window Chrome OS Windows
Every panel and modal is drawn as a shipboard OS window — the in-fiction STARWIND OS. A window has three parts: a title bar, a body, and an optional status bar footer. Title and status bars sit one shade lighter (var(--hull)) than the body (var(--deep)) so the chrome reads as window furniture. All of it derives from the .chrome-bar family in global.css.
var(--deep); chrome bars frame it top and bottom.
Anatomy
| Part | Class | Contents |
|---|---|---|
| Title bar | .chrome-bar | Status lamps · window glyph · title · spacer · window controls |
| Body | (panel-specific) | Scrollable content on var(--deep) |
| Status bar | .status-bar | Mono readout — context (left), telemetry (right) |
| Frame | .os-window-corner | Optional HUD corner brackets (cyan, 0.5px, 55% opacity) |
Title-bar elements
| Element | Class | Spec |
|---|---|---|
| Status lamps | .chrome-bar-dots / .chrome-bar-dot | Three 7px dots — a system-state readout, not macOS traffic lights. Pattern encodes window state (below). |
| Window glyph | .chrome-bar-glyph | Leading mono icon in var(--accent-cyan) — the window class (▣ panel, ☰ log, ⚙ config) |
| Title | .chrome-bar-label | --font-display 12px/600, uppercase, 0.08em, var(--text-muted) — the *.sys / *.cfg / *.log name |
| Spacer | .chrome-bar-spacer | flex: 1 |
| Window controls | .chrome-bar-controls / .chrome-bar-ctrl | Right cluster — minimize / maximize / close (below) |
Window controls
| Control | Glyph | Hover | Behavior |
|---|---|---|---|
| Minimize | – U+2013 | border & glyph → cyan | Collapse to chrome — decorative on full-bleed panels |
| Maximize | ▢ U+25A2 | border & glyph → cyan | Restore / expand — decorative on root panels |
| Close | ✕ U+2715 | border & glyph → --negative | Functional on modals (mirrors Esc); muted & inert on root screens |
Each control is an 18×16px mono glyph in a 0.5px solid var(--panel) box. Flat, no shadow; only border & text color change on hover, instantly.
Status-lamp variants
| Pattern | Meaning | Where |
|---|---|---|
| red · amber · green | Normal operation | Title, TopBar, Station, Ship, Event, Controls, Story, Options |
| red · amber · red | Locked / warning | DeniedPanel |
| all red | Critical / breach | GameOverPanel |
Window glyph & label reference
| Screen | Glyph | Label |
|---|---|---|
| Title screen | ▣ | starwind.sys — sector command interface |
| Options modal | ⚙ | options.cfg |
| TopBar | ▣ | starwind.sys |
| StationPanel | ▣ | station.sys |
| ShipPanel | ▲ | ship.sys |
| DeniedPanel | ⚠ | station.sys — LOCKED |
| GameOverPanel | ⚠ | ship.sys — BREACH |
| EventModal | ⚠ | events.sys |
| ControlsOverlay | ⌨ | controls.sys |
| StoryPanel overlay | ☰ | missions.log |
CSS
/* global.css — window chrome */
.chrome-bar { /* title bar */
display: flex; align-items: center; gap: 8px;
padding: 10px 18px;
background: var(--hull); /* chrome shade, lighter than body */
border-bottom: 0.5px solid var(--panel);
flex-shrink: 0;
}
.chrome-bar-dots { display: flex; gap: 5px; }
.chrome-bar-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.chrome-bar-dot.red { background: var(--negative); }
.chrome-bar-dot.amber { background: var(--accent-amber); }
.chrome-bar-dot.green { background: var(--positive); }
.chrome-bar-glyph { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--accent-cyan); }
.chrome-bar-label {
font-family: var(--font-display); font-size: var(--fs-micro); font-weight: 600;
color: var(--text-muted); letter-spacing: 0.08em; text-transform: uppercase;
}
.chrome-bar-spacer { flex: 1; }
.chrome-bar-controls { display: flex; gap: 6px; }
.chrome-bar-ctrl {
font-family: var(--font-mono); font-size: var(--fs-micro); line-height: 1;
color: var(--text-muted); width: 18px; height: 16px;
display: flex; align-items: center; justify-content: center;
border: 0.5px solid var(--panel); border-radius: 3px;
}
.chrome-bar-ctrl:hover { border-color: var(--cyan); color: var(--accent-cyan); }
.chrome-bar-ctrl.close:hover { border-color: var(--alert); color: var(--negative); }
.status-bar { /* footer */
display: flex; align-items: center; justify-content: space-between;
padding: 6px 18px; background: var(--hull);
border-top: 0.5px solid var(--panel);
font-family: var(--font-mono); font-size: 11px;
color: var(--text-muted); letter-spacing: 0.04em; flex-shrink: 0;
}
.os-window { position: relative; } /* HUD corner brackets */
.os-window-corner {
position: absolute; width: 10px; height: 10px;
border: 0 solid var(--cyan); opacity: 0.55; pointer-events: none;
}
.os-window-corner.tl { top:5px; left:5px; border-top-width:.5px; border-left-width:.5px; }
.os-window-corner.tr { top:5px; right:5px; border-top-width:.5px; border-right-width:.5px; }
.os-window-corner.bl { bottom:5px; left:5px; border-bottom-width:.5px; border-left-width:.5px; }
.os-window-corner.br { bottom:5px; right:5px; border-bottom-width:.5px; border-right-width:.5px; }
06 · Buttons
Base states (global.css)
| State | CSS |
|---|---|
| Default | background: var(--hull); border: 0.5px solid var(--panel); color: var(--text-primary); padding: 8px 16px; border-radius: 4px |
| Hover | border-color: var(--cyan); background: var(--panel); color: var(--accent-cyan) |
| Active | background: var(--hull) |
| Disabled | color: var(--text-disabled); border-color: var(--hull); cursor: not-allowed |
Variants
| Variant | Pattern | Used in |
|---|---|---|
| Primary | Cyan border, accent-cyan text, cyan-tinted hover bg | Title New Game, arrival Dock |
| Danger | Alert border, negative text | Delete save, confirm delete |
| Compact | padding: 3px 12px; --fs-micro; 600; uppercase | TopBar SAVE, MENU |
| Dock / action | Cyan border, accent-cyan, uppercase micro | [M] DOCK, [M] MAP |
| Ghost | Transparent bg, panel border | Options actions, event decline |
| Tab | No bg, transparent bottom border, active = solid | Station / Ship / Story tabs |
| Info | 22×22px circle, muted → cyan on hover | Market ? info |
| Quantity | padding: 3px 8px; --fs-micro; 600, +/− pairs | Buy/sell qty |
| Jump | Flex 1, 3 states (safe / warn / danger) | Info-card jump |
| Schematic action | Small, uppercase, 0.10em tracking | Stow, sell, dismantle |
| Fire crew | Negative text, alert border, uppercase | Crew panel |
| Modal close | background: none; border: none; color: var(--text-muted); 18px | All modals |
07 · Inputs & Selects
Click a field to see the cyan focus border live.
| State | CSS |
|---|---|
| Default | background: var(--hull); border: 0.5px solid var(--panel); color: var(--text-primary); padding: 6px 10px; border-radius: 4px |
| Focus | outline: none; border-color: var(--cyan) |
Scrollbar
8px wide, --hull track, --panel thumb, 3px radius.
Cargo manifest verified: 12 units refined ore, 4 units medical supplies.
Reputation with Free Traders increased to Trusted.
New contract available in Comms: supply run to Helix Station.
Fuel reserves at 78%. Hull integrity nominal.
Scanner sweep complete — 3 adjacent systems charted.
08 · Panels & Cards
Panel backgrounds
| Context | Background | Border | Radius |
|---|---|---|---|
| Fullscreen panel | var(--deep) | None (fills #root) | — |
| Embedded panel | var(--deep) | 0.5px solid var(--panel) | 8px |
| Module / info card | var(--hull) | 0.5px solid var(--panel) | 4–6px |
| Cargo row | var(--void) | 0.5px solid var(--panel) | 4px |
| Modal panel | var(--deep) | 0.5px solid var(--panel) | 4px |
Layout classes
| Class | Where |
|---|---|
.dock-layout | Terminal-framed 2-panel dock (Station + Ship), flex row, 1px margin |
.station-panel / .ship-panel | 20–24px padded, scrollable flex column; ship has border-left |
.denied-panel / .gameover-panel | Fixed fullscreen, centered content, var(--deep) |
.starmap-root | Flex 1, relative, overflow hidden, cursor grab |
.story-panel | Flex column, gap 18px, scrollable |
.transit-screen | Flex center, void bg + radial grid |
Examples
Card classes & state variants
| Class | Spec / state |
|---|---|
.lore-entry / .story-step | var(--hull), 0.5px border, 6px radius |
.comms-mission-row | var(--deep), 0.5px border, 8px radius |
.cargo-row | var(--void), 0.5px border, 4px radius |
.outfit-mod-row / .crew-row | var(--hull), 0.5px border, 4px radius |
.module-row-vert | var(--hull), 3px left-border colored by module type |
.market-item.export-item | border-left-color: var(--cargo) |
.market-item.import-item | border-left-color: var(--amber) |
.outfit-mod-row.installed | border-color: var(--cyan), cyan-tinted bg |
.crew-row.locked | border-color: var(--hull); color: var(--text-disabled) |
.story-step.ready-handin | amber border + 3px amber left-border |
.story-step.auto-complete / .comms-mission-row.handin | border-color: var(--cargo) |
09 · Tabs
| Component | Classes | Active color |
|---|---|---|
| StationPanel | .station-tabs / .station-tab | var(--accent-cyan) |
| ShipPanel | .ship-panel-tabs / .ship-tab | var(--accent-amber) |
| StoryPanel | .story-tabs / .story-tab-btn | var(--accent-cyan) |
/* tab button */ background: none; border: none; border-bottom: 2px solid transparent; color: var(--text-muted); font-family: var(--font-display); font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; transition: none; /* snap — no smooth transitions */ /* active */ color: var(--accent-cyan); border-bottom-color: var(--cyan);
Tab badge (count): amber pill, min-width: 20px; height: 18px; border-radius: 9px, --void text, badge-pulse 2s step-end.
10 · Stat Bars
Block-character gauges using ▐ (U+2590) in spans — on = opacity 1, off = opacity 0.22.
FUEL HULL
| Bar | Segments | Color | Where |
|---|---|---|---|
| Fuel | 12–18 | var(--blue) | TopBar, ShipPanel |
| Hull | 6 | Conditional green / amber / red | TopBar |
| Progress | 18 | var(--cyan) | TransitScreen |
| Cargo | by capacity | var(--cargo) | ShipPanel |
.bar-gauge { display: flex; gap: 2px; letter-spacing: -1px; }
.bar-seg { font-size: var(--fs-micro); line-height: 1; }
.bar-seg.on { opacity: 1; }
.bar-seg.off { opacity: 0.22; }
11 · Modals
| Modal | Overlay | Panel | z-index |
|---|---|---|---|
| Controls | .controls-overlay | .controls-panel | 300 |
| Event | .event-overlay | .event-modal | 200 |
| Good Info | .goodinfo-overlay | .goodinfo-modal | 200 |
| Arrival | .arrival-overlay | .arrival-modal | 60 |
| Options (title) | .options-overlay | .options-panel | 10 |
All overlays: position: absolute; inset: 0; background: rgba(10,13,20,0.82); flex center. All panels: var(--deep), 0.5px solid var(--panel), each with a .chrome-bar header.
Drifting Freighter
A damaged hauler hails you on an open channel, hold breached and venting atmosphere.
Ceres Outpost
Refined Ore
Smelted metal stock — the backbone of station fabrication.
| Modal | Notable details |
|---|---|
| Event | Border tinted by category; category tag + icon before title; numbered choice buttons (mono prefix); effect pills using currentColor; locked decline = dashed, negative, not-allowed |
| Arrival | 4-col action grid (Dock / Scan / Trade / Leave); Dock = primary, Leave = ghost; blinking cyan tick eyebrow; 3-col facts grid; title at --fs-display |
| Good Info | Name+meta header; holdings bar (qty, avg paid, P&L) on hull; amber-left-border description; export/import/neither station lists; full-width close |
12 · Notifications
Toasts bottom-right, z-index 500, column-reverse (newest at bottom). Slide-in 0.3s steps(6). Subtitle (micro, uppercase, muted) + Title (small, bold, primary).
| Type | Icon | Left border |
|---|---|---|
| New mission | ✦ (pulses) | var(--cyan) 3px |
| Mission complete | ✓ | var(--cargo) 3px |
| Mission hand-in | ◈ | var(--amber) 3px |
| Story | ◆ | var(--text-muted) 3px |
| Generic | · | var(--text-muted) 3px |
13 · Title Screen
The game entry screen (state.screen === 'title'). Full-bleed background image (/title-screen.png) with a semi-transparent chrome bar pinned to the top, centered brand + menu, and a footer bar. Launches the Options modal (options.cfg).
Key classes
| Element | Class | Styling |
|---|---|---|
| Brand name | .title-game-name | 58px --font-display 700, accent-cyan, 0.14em, uppercase |
| Tagline | .title-tagline | --font-mono, muted, 0.22em tracking, uppercase |
| Menu button | .title-btn | 380px, --font-display, 3px left-border (cyan on hover), ▸ chevron + keycap shortcut |
| Primary | .title-btn.primary | Cyan border + accent-cyan text + cyan-tinted bg (New Game) |
| Footer | .title-footer | Lore quote (left) + version (right), --font-mono micro on translucent bar |
| Options panel | .options-panel | 380px, var(--deep), chrome options.cfg, version/save rows, Delete-Save danger action with inline confirm |
Legibility over the background image comes from opaque translucent fills (rgba(10,13,20,0.80–0.88)) on the chrome, buttons, and footer — no blur (the interface uses zero backdrop-filter). Keyboard: N new · C continue · O options · Esc closes options.
14 · TopBar (Header)
| Element | Class | Styling |
|---|---|---|
| Chrome dots | .chrome-bar-dots/-dot | Unified from global.css |
| Label | .chrome-bar-label | starwind.sys |
| Separators | .topbar-sep | │, panel color |
| Day | .topbar-val | Mono, fs-num, tabular-nums |
| Credits | .topbar-credits | Amber |
| Fuel | .topbar-fuel-bar | Blue ▐, 12 segs |
| Hull | .topbar-hull-bar | 6 segs, conditional color |
| Location | .topbar-loc-name/-type | Display cyan name + type badge |
| SAVE / MENU / DOCK | .topbar-*-btn | Compact, uppercase, micro |
| Mission dot | .topbar-story-dot | 8px amber, pulse |
15 · Star Map
Node sizes (SVG units)
| Category | Radius |
|---|---|
| Hub | 24 |
| Station | 20 |
| Anomaly | 18 |
| Outpost / Depot / Derelict | 14 |
| Beacon | 12 |
Lines & labels
| Element | Value |
|---|---|
| Base edges | 1.2px dashed var(--panel) |
| Route edges | 2.6px dashed var(--cyan), animated dash flow |
| Transit path / trail | 2.0px dashed / 3.6px solid var(--cyan) |
| Station labels | 18px --font-display uppercase (current 19px accent-cyan) |
| Edge distance labels | 17px --font-mono |
| Region watermarks | 52px --font-display, 10% opacity |
Node states & fog of war
| State | Class | Visual |
|---|---|---|
| Current | .is-current | Cyan pulse ring + brightness + larger label |
| Selected | .is-selected | Dashed cyan ring + brighter node |
| Hovered | .is-hovered | Brighter node, label → text-primary |
| On route | .is-on-route | Brightness boost |
| Hostile | .is-hostile | Red tint |
| Visited | — | Full size, name, faction color, center dot |
| Adjacent (undiscovered) | .is-discovered | 55% size, ??? label 13px, faded 0.25, dashed ring, no dot |
| Hidden | — | Not rendered |
Info card: top-right, 340px, faction-colored bullet + name, stats (type/faction/region/hazard); when routed, 3-col distance/fuel/ETA grid + color-coded jump button. HUD: corner legend top-left, zoom top-right, route/transit info bottom center.
16 · Station Panel (Docked)
7 tabs: Info · Market · Outfitting · Shipyard · Crew · Comms · Gather (Gather only when station has gatherables).
| Tab | Contents |
|---|---|
| Info | Station name (26px display, accent-cyan), planet-type icon+label, description, fields (faction/region/type/temp/gravity/atmosphere), reputation (rank + value + 6px cyan bar), services with ▸ prefixes |
| Market | Grouped Exports (◆ cargo) / Imports (● amber) / Neither; per-item name+category+?; Buy/Sell columns; held stock (amber) + P&L; green buy / red sell qty; rep-locked = LOCKED badge; sticky cargo footer |
| Outfitting | Modules grouped by type with category icon; install/buy button; installed = cyan border-left + tint; compare panel when replacing; slot badge G/E/WS; amber trade-in |
| Shipyard | Ship name (amber display) + slot pips + stats; tier + archetype badge (balanced=cyan, fast=red, heavy=amber, gunship=purple); Repair (cargo) + Refuel (blue) with Max/Fill/Clear |
| Crew | Roles grouped; skill + bonus + rep req + salary; locked = disabled/hull; hire + hired list with fire |
| Comms | Available missions (accept) + ready-to-hand-in (green border); title (display fs-h2) + reward; objectives ■/□ + counters; done = green check, strikethrough |
| Gather | Resource name (display uppercase) + yield/fuel/time; amber gather button; cooldown = muted left-border |
17 · Ship Panel (Docked)
4 tabs: Ship · Schematic · Cargo · Missions (+ Codex within Missions).
| Tab | Contents |
|---|---|
| Ship | Hull name (26px display, accent-amber) + tier/archetype badges; Performance bars (cargo, fuel, speed, mass) + Systems (scanner, crew, shield, signature); installed modules color-coded with sell; empty slots dashed; hired crew with fire |
| Schematic | See §17 |
| Cargo | Held goods (name, category badge, qty); avg paid + P&L; ? info; summary card (items, value, capacity) |
| Missions | Active steps (title, description, objectives, rewards); story chains with progress + status badges; completed = amber label |
| Codex | Discovered lore: title + body, amber discover timestamp |
18 · Schematic (Ship Build View)
Main row: ship SVG (hull fill, archetype-colored stroke, alert-red engine glow with stepped pulse) + absolute-positioned slot boxes + detail panel. Warehouse cards below; drag-and-drop slots ↔ warehouse.
Wide-band sensor sweep — charts adjacent systems two jumps out.
Slot states
| State | Visual |
|---|---|
| Empty | 45% opacity, type label (G / E / WS) |
| Filled | Colored by module type |
| Selected | Cyan border + bg |
| Drag source | 35% opacity, dashed border |
| Valid / invalid target | Cyan / red border + bg |
Slot colors by module type
| Module | Icon | Border / label |
|---|---|---|
| Cargo Hold | ▣ | --amber / accent-amber |
| Fuel Tank | ▮ | --blue / accent-blue |
| Engine | ▶ | --alert / negative |
| Crew Quarters | ☉ | --cargo / positive |
| Scanner | ◎ | --cyan / accent-cyan |
| Shielding | ◊ | --purple |
| Auto-Repair | ✚ | --cargo / positive |
19 · Transit Screen
Fullscreen, radial dot-grid over void.
| Element | Spec |
|---|---|
| Header | ▐▐ IN TRANSIT ▐▐ — fs-h1 display, accent-cyan, uppercase |
| Route | Origin → Destination, display font |
| Progress | 18 segs cyan + 34px mono accent-cyan % |
| Meta | Distance · ETA · Risk (label + mono value) |
| Ship | Amber ▶ chevron / ◄ sprite on route line |
| Particle layer | Color | Duration |
|---|---|---|
| Near | var(--cyan) | 0.3–0.8s |
| Mid | var(--blue) 30% | 0.8–1.6s |
| Far | var(--text-muted) 15% | 1.5–3.0s |
20 · Story Panel
Two tabs: Missions & Codex (opens on L).
Deliver refined ore to Helix Station before day 130.
- Active quests — steps with title, description, objectives (■/□ + counter), rewards. New missions fade in cyan (
step-highlight 3s steps(6)). Ready-to-hand-in = amber left-border; auto-complete = green border. - Story chains — row per chain: title + faction + progress + status (Dormant gray / Active amber / Complete green). Prerequisites in italic amber.
- Story flags — list with green check markers.
- Codex · Field Records — public lore entries: title (display, accent-cyan, uppercase, bordered) + body; amber discover timestamp.
- Codex · Classified — story-gated secrets: same card shape but accent-amber title + 0.5px amber border. Unrevealed = dimmed SEALED rows showing only the mono amber teaser (
▓ CLASSIFIED — …). Amber accent is the only differentiator; no shadow/gradient.
21 · Denied & Game Over
| Panel | Chrome | Center | Detail |
|---|---|---|---|
| DeniedPanel | red·amber·red · station.sys — LOCKED | Blinking ✕ 48px negative | Title ACCESS DENIED (26px display, negative); rep explanation; hint — PRESS [M] TO RETURN TO MAP — |
| GameOverPanel | all red · ship.sys — BREACH | Blinking ! 56px negative (0.8s step-end) | Title HULL BREACH (fs-display); stats card (stations, crew, ship, lore, missions, credits, top rep); RESET (alert) + CONTINUE (muted) |
22 · Animations
All animations use step-end or steps(N) — never ease, ease-in-out, linear, or cubic-bezier. Hover states snap instantly (transition: none).
Banned
/* NEVER */ transition: all 0.3s ease-in-out; box-shadow / text-shadow / filter: drop-shadow(); backdrop-filter: blur(); /* never — use opaque translucent rgba fills instead */ linear-gradient / radial-gradient /* except scanlines, star-map bg, starfield */
Global keyframes
| Name | Effect | Timing |
|---|---|---|
blink | opacity 1 ↔ 0 | 1s step-end |
pulse-step | opacity 0.6 ↔ 0.3 | 2s steps(4) |
Component keyframes
| Name | Effect | Timing | File |
|---|---|---|---|
starmap-route-flow | Dash offset | 1.2s linear | StarMap |
starmap-cell-pulse | Pulse ring | 2.4s steps(4) | StarMap |
starmap-ship-pulse | Ship glow | 1.4s steps(4) | StarMap |
info-card-in | Card slide | 0.18s steps(4) | StarMap |
arrival-modal-in | Scale + fade | 0.22s steps(4) | ArrivalModal |
arrival-tick-blink | Tick blink | 1.2s steps(2) | ArrivalModal |
event-pop | Scale pop-in | 0.3s steps(4) | EventModal |
engine-pulse | Engine glow | 2s steps(4) | ShipSchematic |
detail-in | Detail fade/slide | 0.15s steps(4) | ShipSchematic |
step-highlight | New-mission fade | 3s steps(6) | StoryPanel |
badge-pulse | Tab badge | 2s step-end | StationPanel |
confirm-pulse | Confirm flash | 0.4s step-end ×3 | StationPanel |
story-dot-pulse | TopBar mission dot | 1.5s step-end | TopBar |
particle-drift | Transit particles | 1s steps(4) | TransitScreen |
toast-in / toast-pulse | Slide / icon pulse | 0.3s steps(6) / 2s step-end | NotificationToast |
23 · Screen Reference
| state.screen | Components |
|---|---|
'title' | TitleScreen (bg image + centered menu + options modal) |
'map' | TopBar + StarMap |
'transit' | TopBar + StarMap (transit overlay) |
'docked' | TopBar + DockPanel (Station + Ship, 7 tabs) |
'denied' | TopBar + DeniedPanel |
'gameover' | TopBar + GameOverPanel |
| Overlay | Trigger |
|---|---|
| EventModal | state.activeEvent |
| StoryPanel | L key |
| ControlsOverlay | ? / / key |
| NotificationToast | Mission events |
| ArrivalModal | Transit completes on map |
| GoodInfoModal | Market / cargo ? |
#root
├── .scanlines (CRT, always on)
├── .small-viewport-warning (< 1024px)
└── .app-shell
└── GameShell (screen router)
├── TitleScreen
├── TopBar (all non-title screens)
├── StarMap / DockPanel / DeniedPanel / GameOverPanel
├── EventModal · ControlsOverlay (conditional)
└── NotificationToast
24 · CSS File Map
| File | Lines | Covers |
|---|---|---|
styles/global.css | 255 | Variables, reset, body, #root, chrome-bar, buttons, inputs, scanlines, blink/pulse |
TitleScreen.css | 270 | Title screen (bg, branding, menu, options modal) |
TopBar.css | 192 | Header (stats, fuel/hull gauges, location, actions) |
StarMap.css | 739 | Map (nodes, edges, labels, HUDs, info card, transit overlay) |
StationPanel.css | 1413 | Dock tabs (info, market, outfit, shipyard, crew, comms, gather) |
ShipPanel.css | 575 | Ship (stats, modules, cargo, missions, codex) |
ShipSchematic.css | 463 | Build view (SVG hull, slots, warehouse, drag-drop) |
StoryPanel.css | 388 | Missions + codex |
ArrivalModal.css | 253 | Arrival card (facts grid, action grid) |
TransitScreen.css | 218 | Warp (particles, progress, route) |
EventModal.css | 210 | Event popup (choices, effects, decline) |
GoodInfoModal.css | 162 | Good detail popup |
GameOverPanel.css | 113 | Game over (stats card, actions) |
ControlsOverlay.css | 105 | Keyboard shortcuts overlay |
NotificationToast.css | 92 | Toast notifications |
App.css | 80 | App shell, story overlay, action buttons |
DeniedPanel.css | 72 | Access denied |
DockPanel.css | 8 | Dock 2-panel split border frame |
Starwind Interface Style Guide · Updated 2026-05-30 · style_guide() to open