Sudoku Fighting — visual design reference & component inventory
Primary action color. Used on primary buttons, shadows on white text, character card shadows, toggle on-state, KO block fill, overlay text. Never used as background behind white text unless a contrasting shadow offsets it.
All P1 UI: grid border, selected cells, name shadow, HUD score/combo shadow. Never used on P2 elements.
Mirrors P1 semantics exactly, shifted to magenta. Grid border, selected cells, name shadow. Never mixed with P1 colors on the same element.
Error states, conflicts, and low-HP. The track of the health bar is always the danger red, revealed as health drops. Also used for the timer at <10s, wrong-move cell backgrounds, and the Leave/Surrender button.
Orange is the VS AI / single-player signal color. It also appears on the HP bar at ~50% health, and in the heavy-hit screen flash. Yellow is the HP bar fill at full health, and the overlay subtitle text (always on dark or colored backgrounds).
Used for backgrounds, surfaces, borders, and body text. All neutral values have equal R/G/B channels — no color cast.
Aa Bb Cc 0–9
Weights used: 400 (normal), 500 (medium), 700 (bold), 800 (heavy), 900 (black).
Used for all body text, buttons, HUD labels, number input, settings, lobby UI.
FIGHT!
Weight 900 only. Reserved exclusively for impactful game moments: FIGHT!, KO, VICTORY/DEFEAT, VS, lobby titles, section labels, match-end screen, start-screen mode headers.
Hard pixel text shadows (offset, no blur) are used throughout. Shadow offset grows with type size so it remains proportionally punchy at every scale. Shadows pair with the background context — purple shadows over white UI, colored shadows over dark/arena backgrounds.
| Token | Size | Shadow offset rule | Common shadow pairings |
|---|---|---|---|
--text-xs | 10px | 1px 1px 0 | — |
--text-sm | 12px | 1px 1px 0 | White text → accent; Settings labels |
--text-base | 14px | 1px 2px 0 | White text → accent; Body copy |
--text-md | 18px | 2px 2px 0 | P1 white name → p1-mid-dark; P2 white name → p2-mid-dark; Generic white → accent |
--text-lg | 22px | 1px 2px 0 | Yellow overlay sub-text → accent |
--text-xl | 26px | 2px 3px 0 | White timer → accent; Share code white → accent |
--text-2xl | 28px | 2px 3px 0 | White VS / lobby title → accent; Player label → white |
--text-3xl | 66px | 3px 4px 0 | Match-end title accent → semi-white; danger defeat variant |
--text-4xl | 96px | 4px 5px 0 | Main overlay (accent text) → white |
--text-xl 26px → 18px--text-3xl 66px → 44px--text-4xl 96px → 56px
All buttons use Roboto Mono, 700 weight. Press interaction: translate +2px/+2px with shadow shrink. Release: translate -1px/-2px with shadow grow. Shadow is a hard pixel offset (no blur) — the direction and color are the meaningful signals.
.btnaccent #8B49FF4px 4px 0 #ffffff5px 6px 0 #ffffff
.btn.btn-sm2px 2px 0 #ffffff
.btn-secondary or .btn.btn-secondaryaccent #8B49FF4px 4px 0 accent (purple).btn.btn-sm, a specificity override ensures purple shadow wins over the default white.
.btn.btn-alt.btn (purple) on the same page. Currently: VS AI on the start screen, START! in the SP lobby. Not tied to any specific screen — use any time you have two primary CTAs and need visual separation.--orange #FF8B164px 4px 0 #ffffff
.btn.btn-danger--danger-color #F000134px 4px 0 #ffffff
.btn-utilityrgba(0,0,0,0.35).btn-sm composes orthogonally with any intent modifier. e.g. .btn.btn-sm.btn-danger = small destructive button.
| Class(es) | Preview | Background | Shadow | Semantic role |
|---|---|---|---|---|
.btn |
accent #8B49FF | 4px 4px white | Primary CTA — default intent. | |
.btn.btn-alt |
orange #FF8B16 | 4px 4px white | Alternate primary — contrast with .btn on same page. | |
.btn.btn-danger |
danger #F00013 | 4px 4px white | Destructive / irreversible action. | |
.btn-secondary |
white #FFFFFF | 4px 4px accent | Secondary weight — alternative action. | |
.btn.btn-sm |
accent #8B49FF | 2px 2px white | Small primary. radius-xs (5px). | |
.btn.btn-sm.btn-secondary |
white #FFFFFF | 2px 2px accent | Small secondary. opacity 0.55 when inactive. | |
.btn-utility |
rgba(0,0,0,0.35) | none | Minimal weight — icons & low-priority actions. |
The grid renders over an arena background. Cell backgrounds use white at varying opacity so the arena art shows through on ghosted cells. Own grid uses 88% opacity white for clarity. Opponent empty cells use 25% — visibly ghosted to signal "not yours". Opponent filled cells match own-grid opacity (90%) to show progress legibly.
#888888 — spectator/neutralp1-color — replaces neutralp2-color — replaces neutral| State | Class(es) | Background | Text color / weight | Notes |
|---|---|---|---|---|
| Empty (own) | .is-me .cell | rgba(255,255,255,0.88) | — | Active puzzle cells |
| Empty (opponent) | .cell (not is-me) | rgba(255,255,255,0.25) | — | Ghosted — not interactive |
| Given number | .cell.given | inherits | text-secondary #333, w700 | Pre-filled clue cells. Still clickable. |
| Correctly filled | .cell.correct | rgba(255,255,255,0.88) | p1-dark/p2-dark, w600 | Color keyed to grid owner |
| Highlighted row/col | .cell.highlight | p1/p2-bg-light | — | Same row/col as cursor |
| Same number | .cell.same-number | p1/p2-bg-mid | — | All cells matching entered digit |
| Selected cursor | .cell.selected | p1/p2-bg-light | — | Inset box-shadow: 2px solid p1/p2-color |
| Invalid entry | .cell.danger | danger-bg-light #FFEBEC | danger-dark #A8000F, w600 | Red diagonal X overlay via ::before/::after |
| Opponent cursor | .cell.opponent-cursor | p1/p2-bg-light | — | 3px inset outline in p1/p2 color |
| Opponent filled | .cell.opponent-filled | rgba(255,255,255,0.9) | p1/p2-dark, w600 | Matches own-grid opacity to show legibly |
Thin cell lines: 1px #D5D5D5. Thick 3×3 box dividers: 2px #888888. The outer border uses CSS custom properties (--_grid-outline-color, --_grid-outline-width) so that .is-me overrides both color and width on the same single border declaration — it fully replaces the neutral border rather than layering on top of it. Default: 2px grid-box-border. Own grid: 3px in the player's identity color. Right and bottom borders of cells adjacent to box lines are suppressed to prevent double-border artifacts.
The bar track is always danger red — the red is the "low HP" signal already baked in. The fill bar covers it: yellow at full, orange at ~50%, then pulsing yellow at low HP.
yellow #FFCA00orange #FF8B16yellow pulsing (opacity blink)danger-color fully visibledanger-color, shadow to orange, blinks. KO block: Barlow Condensed 28px, accent purple fill, white text.accent purple + white shadow. Defeat: danger-color red. Sub-text: Roboto Mono 22px w700, yellow + purple shadow (never white — legible on any arena bg).Appears near the cell where a correct number is entered. 13px, w800, accent purple. Floats up 36px and fades out over 0.75s.
Full-screen inset box-shadow flashes on hit, keyed to attack type:
• Punch: rgba(240,0,19,0.22) — subtle red, 0.25s
• Heavy: rgba(255,139,22,0.32) → red — orange then red, 0.35s
• Self-hit: rgba(240,0,19,0.20) — 0.2s
.join-comboInput and action button fused into a single bordered unit. Currently appears once on the start screen for room code entry. White outer border, purple box-shadow. The inner button acts as a secondary action (white bg, accent text) with no border-radius.
Proposed for future forms (player name entry, search, etc.). Not currently used standalone in the game. Focus ring uses accent-light at 3px spread — soft glow rather than hard pixel, since this is a white-bg form context not an arena overlay.
Inline feedback text beneath form elements. Rendered in-place using visibility: hidden / visibility: visible — never display: none — so layout does not shift when they appear.
Room not found. Check the code and try again.
Copied to clipboard!
visibility not display to toggle.
.lobby-shareSemi-transparent frosted panel used for the private room invite code. Sits over the arena background. Used sparingly — only when content needs grouping against a complex background.
rgba(255,255,255,0.12)rgba(255,255,255,0.25)Quick Play share row. The feedback text ("Copied to clipboard") always occupies its line height via visibility: hidden/visible — this prevents the button from jumping down when feedback appears.
Copied to clipboard
Copied to clipboard
visibility not display..track-carouselUsed for track selection in settings and arena selection in lobbies. Chevron buttons are utility style with 44×44px minimum touch target. Title is center-fixed width with overflow ellipsis.
.btn-utility style, min 44×44px touch target.sp-diff-btnRow of small secondary buttons where inactive options are dimmed to 55% opacity. The selected button restores to full opacity — no other visual indicator needed.
.btn.btn-sm.btn-secondary at opacity 0.55Used for "Waiting for opponent…" and similar transient states. Pulse draws attention without urgency.
Waiting for opponent...
fade-pulse 1.4s ease-in-out infinite (opacity 1.0 → 0.4)
Lives in the HUD sub-row alongside the score. Reserves its line height even when empty so the score doesn't shift when a combo appears.
min-height: 1em — always reserves space so score doesn't jumpp1-mid-dark — P2: shadow p2-mid-dark
accent color, 3px 4px 0 #ffffff shadowdanger-color color, same shadowpop-in scale 0.55→12px 3px 0 #ffffffrgba(255,255,255,0.25)The game renders UI over complex, colorful arena backgrounds. All readable text therefore uses white or high-chroma colors with hard pixel shadows that ensure contrast regardless of what's behind.
| Context | Text color | Shadow color | Offset | Reason |
|---|---|---|---|---|
| Generic white text over arena | #ffffff | accent #8B49FF | 2px 2px 0 | Purple provides contrast on any bg |
| P1 player name (HUD) | #ffffff | p1-mid-dark #0A8FBB | 2px 2px 0 | Cyan shadow reinforces P1 identity |
| P2 player name (HUD) | #ffffff | p2-mid-dark #BC0074 | 2px 2px 0 | Magenta shadow reinforces P2 identity |
| P1 player label (lobby, selected) | p1-color #17B9EF | #ffffff | 3px 3px 0 | Player-color on dark bg; white grounds it |
| P2 player label (lobby, selected) | p2-color #F31299 | #ffffff | 3px 3px 0 | Same logic, magenta |
| Round timer (normal) | #ffffff | accent #8B49FF | 3px 3px 0 | Large text, offset scales up |
| Round timer (urgent ≤10s) | danger-color #F00013 | orange #FF8B16 | 2px 3px 0 | Red with warm orange shadow — high alarm |
| Main overlay (FIGHT! / VICTORY) | accent #8B49FF | #ffffff | 4px 5px 0 | Biggest text; needs widest shadow |
| Main overlay (DEFEAT) | danger-color #F00013 | #ffffff | 4px 5px 0 | Red as danger signal |
| Overlay sub-text | yellow #FFCA00 | accent #8B49FF | 1px 2px 0 | Yellow is legible on both light and dark arenas |
| Primary btn text | #ffffff | n/a (box-shadow on element) | — | Button surface carries the shadow |
| Secondary btn text | accent #8B49FF | n/a | — | White surface, no text shadow needed |
When white text appears with a player-color shadow, use the mid-dark variant (p1-mid-dark, p2-mid-dark), not the primary color. The primary cyan and magenta are too bright for a shadow — they'd feel garish. The mid-dark is dark enough to read as a grounding shadow while still being clearly player-colored.
These components do not yet exist in the game but are consistent with the design language and likely needed as the game adds features. Specs are proposals — refine before shipping.
Small pill labels for surfacing state, novelty, or counts. Uses --radius-pill. Variants keyed to semantic meaning, not visual preference.
.badge-new — accent purple: new feature/content.badge-beta — orange: experimental/unreleased.badge-count — danger red: notification count.badge-p1/p2 — player identity colors.badge-neutral — grey: inactive/offline stateEphemeral feedback that appears over gameplay or between screens. Bottom-anchored, auto-dismisses. Uses a left accent border rather than full background color to keep it readable over any arena. Would need a JS show/hide with a slide-up + fade animation.
accent borderdanger-color bordergrid-box-border (#888) border--shadow-mdBlocks interaction for destructive confirmations (e.g., "Surrender — are you sure?"). Backdrop at 65% black. Panel on white surface. Actions use the existing button system — confirm uses .btn-danger, cancel uses .btn-secondary.
rgba(0,0,0,0.65). Panel: white surface, radius-md, heavy box-shadow.Contextual info on hover. Useful for explaining game mechanics (e.g., what "combo" means, difficulty differences). Uses the same dark panel as the settings menu, with a hard pixel shadow in accent to stay on-brand.
#1a1a2e near-black, white text, 10px bold2px 2px 0 accent — keeps it on-brand:hover on parent, or JS for touch
Styled <select> for settings that have more than 2–3 options (e.g., language, region, control scheme). Uses custom chevron SVG via background-image to replace the native arrow.
background-image SVGappearance: none removes native chromeFor async waits: character portrait loading, matchmaking, network reconnect. Skeleton uses a shimmer gradient. Spinner uses accent color on top of grey track.
--border / --bg--border grey. Active arc: --accent purple