Backdrop Path + Cybersteel (#23)
Co-authored-by: Zachary Levy <zachary@sunforge.is> Reviewed-on: #23
This commit was merged in pull request #23.
This commit is contained in:
@@ -0,0 +1,756 @@
|
||||
// CYBERSTEEL DESIGN SYSTEM — Odin theme constants
|
||||
//
|
||||
// Retrofuturist. Technical. Direct. Gruvbox-derived palette
|
||||
// with Art Deco type system. Every visual token from the
|
||||
// Cybersteel design system, transferred 1:1 to Odin constants.
|
||||
//
|
||||
// Conventions:
|
||||
// - Colors are [4]u8 RGBA. Alpha 255 = fully opaque.
|
||||
// Translucent tints carry their alpha in the 4th channel.
|
||||
// - Times are time.Duration via core:time.
|
||||
// - Pixel sizes, weights, line-heights, letter-spacings, and
|
||||
// ratio-like values are plain (untyped) numeric literals so
|
||||
// callers can use them with whatever numeric type they need.
|
||||
// - Letter-spacing values are expressed in EMs (multiply by
|
||||
// the resolved font size to get pixels).
|
||||
// - Line-heights are unitless multipliers of the font size.
|
||||
|
||||
package cybersteel
|
||||
|
||||
import "core:time"
|
||||
|
||||
import draw ".."
|
||||
|
||||
|
||||
// ============================================================
|
||||
// BASE BACKGROUNDS — warm dark, Gruvbox-derived
|
||||
// Never pure black. The warmth is intentional: aged metal,
|
||||
// amber phosphor, old paper. Order is: deepest chrome first
|
||||
// (shell), then page, then progressively lighter surfaces.
|
||||
// ============================================================
|
||||
|
||||
// Topbar, sidebar, nav chrome, modal backdrops. Deepest base.
|
||||
BG_SHELL :: draw.Color{0x1d, 0x20, 0x21, 0xff}
|
||||
|
||||
// Default page canvas / main content area. One step up from shell.
|
||||
BG_PAGE :: draw.Color{0x31, 0x31, 0x31, 0xff}
|
||||
|
||||
// Cards, panels, drawers, input fields, code blocks, table rows.
|
||||
// Slightly lighter than the page so raised surfaces read clearly
|
||||
// without shadows.
|
||||
BG_SURFACE :: draw.Color{0x3c, 0x38, 0x36, 0xff}
|
||||
|
||||
// Selected rows, active nav items, hover states. One step lighter
|
||||
// than BG_SURFACE.
|
||||
BG_ACTIVE :: draw.Color{0x50, 0x49, 0x45, 0xff}
|
||||
|
||||
// Disabled buttons / inputs background. Pairs with FG_MUTED text
|
||||
// only — the contrast is intentionally low.
|
||||
BG_DISABLED :: draw.Color{0x66, 0x5c, 0x54, 0xff}
|
||||
|
||||
// Borders, dividers, rules, input outlines. Never use as a text
|
||||
// surface — it has no fg-pair guarantee.
|
||||
BG_BORDER :: draw.Color{0x7c, 0x6f, 0x64, 0xff}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// BASE FOREGROUNDS — warm cream / ivory, never pure white
|
||||
// Five-step ramp from brightest (heading) to most muted.
|
||||
// ============================================================
|
||||
|
||||
// Hero text, page headings, display titles. Brightest fg.
|
||||
FG_HEADING :: draw.Color{0xfb, 0xf1, 0xc7, 0xff}
|
||||
|
||||
// Primary body text, default readable content.
|
||||
FG_BODY :: draw.Color{0xf2, 0xe2, 0xba, 0xff}
|
||||
|
||||
// Labels, secondary descriptions, table data.
|
||||
FG_SECONDARY :: draw.Color{0xe0, 0xd0, 0xa8, 0xff}
|
||||
|
||||
// Captions, metadata, timestamps, placeholders.
|
||||
FG_CAPTION :: draw.Color{0xce, 0xbd, 0x9e, 0xff}
|
||||
|
||||
// Disabled text, token labels, subtle UI annotations.
|
||||
FG_MUTED :: draw.Color{0xb8, 0xa9, 0x8e, 0xff}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// ACCENT — GOLD (signature color, Art Deco)
|
||||
// The defining accent of the system. Use sparingly: borders,
|
||||
// highlights, focus rings, primary interactive states.
|
||||
// ============================================================
|
||||
|
||||
// Primary interactive, focus rings, headline interactive accent.
|
||||
GOLD_BRIGHT :: draw.Color{0xfa, 0xbd, 0x2f, 0xff}
|
||||
|
||||
// Borders, decorative rules, default Art Deco ornament color.
|
||||
GOLD_DIM :: draw.Color{0xd7, 0x99, 0x21, 0xff}
|
||||
|
||||
// Hover states, pressed accents, dimmer gold contexts.
|
||||
GOLD_MUTED :: draw.Color{0xb5, 0x76, 0x14, 0xff}
|
||||
|
||||
// Pure CRT amber. Reserved for terminal-style glow / phosphor
|
||||
// references — distinct from gold ramp.
|
||||
AMBER :: draw.Color{0xff, 0xb0, 0x00, 0xff}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// ACCENT — RED (danger, errors, critical alerts)
|
||||
// ============================================================
|
||||
|
||||
RED_BRIGHT :: draw.Color{0xfb, 0x49, 0x34, 0xff}
|
||||
RED_DIM :: draw.Color{0xcc, 0x24, 0x1d, 0xff}
|
||||
RED_MUTED :: draw.Color{0x9d, 0x00, 0x06, 0xff}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// ACCENT — GREEN (success, safe, complete)
|
||||
// ============================================================
|
||||
|
||||
GREEN_BRIGHT :: draw.Color{0xb8, 0xbb, 0x26, 0xff}
|
||||
GREEN_DIM :: draw.Color{0x98, 0x97, 0x1a, 0xff}
|
||||
GREEN_MUTED :: draw.Color{0x79, 0x74, 0x0e, 0xff}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// ACCENT — BLUE / TEAL (info, links, cool technical elements)
|
||||
// ============================================================
|
||||
|
||||
BLUE_BRIGHT :: draw.Color{0x83, 0xa5, 0x98, 0xff}
|
||||
BLUE_DIM :: draw.Color{0x45, 0x85, 0x88, 0xff}
|
||||
BLUE_MUTED :: draw.Color{0x07, 0x66, 0x78, 0xff}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// ACCENT — ORANGE (warnings, in-progress, hot paths)
|
||||
// ============================================================
|
||||
|
||||
ORANGE_BRIGHT :: draw.Color{0xfe, 0x80, 0x19, 0xff}
|
||||
ORANGE_DIM :: draw.Color{0xd6, 0x5d, 0x0e, 0xff}
|
||||
ORANGE_MUTED :: draw.Color{0xaf, 0x3a, 0x03, 0xff}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// ACCENT — AQUA (cool secondary accent, fresh/active states)
|
||||
// ============================================================
|
||||
|
||||
AQUA_BRIGHT :: draw.Color{0x8e, 0xc0, 0x7c, 0xff}
|
||||
AQUA_DIM :: draw.Color{0x68, 0x9d, 0x6a, 0xff}
|
||||
AQUA_MUTED :: draw.Color{0x42, 0x7b, 0x58, 0xff}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// ACCENT — PURPLE (rare, for categorical / data-vis variety)
|
||||
// ============================================================
|
||||
|
||||
PURPLE_BRIGHT :: draw.Color{0xd3, 0x86, 0x9b, 0xff}
|
||||
PURPLE_DIM :: draw.Color{0xb1, 0x62, 0x86, 0xff}
|
||||
PURPLE_MUTED :: draw.Color{0x8f, 0x3f, 0x71, 0xff}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// SEMANTIC COLOR ROLES
|
||||
// Aliases to accent ramps, named by intent. Prefer these in
|
||||
// product code so meaning travels with the value.
|
||||
// ============================================================
|
||||
|
||||
// Primary brand interactive — buttons, key links, focus ring.
|
||||
COLOR_PRIMARY :: GOLD_BRIGHT
|
||||
COLOR_PRIMARY_DIM :: GOLD_DIM
|
||||
|
||||
// Destructive / error / critical states.
|
||||
COLOR_DANGER :: RED_BRIGHT
|
||||
COLOR_DANGER_DIM :: RED_DIM
|
||||
|
||||
// Successful operation / safe state / completion.
|
||||
COLOR_SUCCESS :: GREEN_BRIGHT
|
||||
COLOR_SUCCESS_DIM :: GREEN_DIM
|
||||
|
||||
// Caution / in-progress / non-fatal anomaly.
|
||||
COLOR_WARNING :: ORANGE_BRIGHT
|
||||
COLOR_WARNING_DIM :: ORANGE_DIM
|
||||
|
||||
// Informational / neutral status / passive notice.
|
||||
COLOR_INFO :: BLUE_BRIGHT
|
||||
COLOR_INFO_DIM :: BLUE_DIM
|
||||
|
||||
// Hyperlinks at rest and on hover (links flip to gold on hover).
|
||||
COLOR_LINK :: BLUE_BRIGHT
|
||||
COLOR_LINK_HOVER :: GOLD_BRIGHT
|
||||
|
||||
// Keyboard / programmatic focus ring color.
|
||||
COLOR_FOCUS :: GOLD_BRIGHT
|
||||
|
||||
|
||||
// ============================================================
|
||||
// SURFACE ROLES
|
||||
// Semantic aliases for the bg ramp by usage role.
|
||||
// ============================================================
|
||||
|
||||
SURFACE_PAGE :: BG_PAGE // root canvas
|
||||
SURFACE_RAISED :: BG_SURFACE // cards, panels, inputs
|
||||
SURFACE_OVERLAY :: BG_SHELL // modals, popovers, deep chrome
|
||||
SURFACE_HOVER :: BG_ACTIVE // hovered raised surfaces
|
||||
SURFACE_ACTIVE :: BG_SURFACE // pressed/active raised surfaces
|
||||
|
||||
|
||||
// ============================================================
|
||||
// BORDER ROLES
|
||||
// Cybersteel borders are 1px solid, always crisp, always visible.
|
||||
// Color carries the meaning; weight rarely changes.
|
||||
// ============================================================
|
||||
|
||||
BORDER :: BG_BORDER // structural borders, default
|
||||
BORDER_SUBTLE :: BG_DISABLED // very faint separators
|
||||
BORDER_ACCENT :: GOLD_DIM // decorative / active edge
|
||||
BORDER_FOCUS :: GOLD_BRIGHT // focus rings
|
||||
BORDER_DANGER :: RED_DIM // destructive states
|
||||
BORDER_SUCCESS :: GREEN_DIM // success states
|
||||
|
||||
|
||||
// ============================================================
|
||||
// TRANSLUCENT ACCENT TINTS
|
||||
// Used for hover fills behind ghost buttons and for warm
|
||||
// gradient overlays. Alpha encodes the tint strength.
|
||||
// ============================================================
|
||||
|
||||
// 20% gold tint behind a hovered secondary button.
|
||||
TINT_GOLD_HOVER :: draw.Color{0xd7, 0x99, 0x21, 0x33} // ~20% alpha
|
||||
|
||||
// 20% red tint behind a hovered danger ghost button.
|
||||
TINT_DANGER_HOVER :: draw.Color{0xcc, 0x24, 0x1d, 0x33}
|
||||
|
||||
// 20% green tint behind a hovered success ghost button.
|
||||
TINT_SUCCESS_HOVER :: draw.Color{0x98, 0x97, 0x1a, 0x33}
|
||||
|
||||
// 8% gold tint — top of the diagonal "gold fade" feature
|
||||
// section overlay.
|
||||
TINT_GOLD_FADE :: draw.Color{0xfa, 0xbd, 0x2f, 0x14} // ~8% alpha
|
||||
|
||||
// 6% amber tint — top of the vertical "amber fade" overlay.
|
||||
TINT_AMBER_FADE :: draw.Color{0xff, 0xb0, 0x00, 0x0f} // ~6% alpha
|
||||
|
||||
// 4% gold tint — corner of card gradient.
|
||||
TINT_GOLD_CARD :: draw.Color{0xfa, 0xbd, 0x2f, 0x0a} // ~4% alpha
|
||||
|
||||
// 3% black tint — scanline overlay stripe color.
|
||||
TINT_SCANLINE :: draw.Color{0x00, 0x00, 0x00, 0x08} // ~3% alpha
|
||||
|
||||
|
||||
// ============================================================
|
||||
// SHADOWS
|
||||
// Cybersteel is FLAT — no drop shadows. Elevation is expressed
|
||||
// through bg + border only. The single permitted shadow use is
|
||||
// a 1px gold ring as a focus / active indicator. Constants are
|
||||
// kept here so callers don't reach for ad-hoc shadow values.
|
||||
// ============================================================
|
||||
|
||||
// 1px inset gold ring — only permitted shadow, used as focus
|
||||
// or selected-state outline. Width is 1px; color follows.
|
||||
SHADOW_GOLD_RING_WIDTH :: 1
|
||||
SHADOW_GOLD_RING_COLOR :: GOLD_DIM
|
||||
|
||||
|
||||
// ============================================================
|
||||
// SPACING SCALE (8px base grid)
|
||||
// All spacing values are multiples of 4px, with the main scale
|
||||
// in multiples of 8px. Names describe the scope of the gap, not
|
||||
// the raw size — pick by intent, not by pixel count.
|
||||
// ============================================================
|
||||
|
||||
// Badge/tag inner padding, icon-label gap, border offsets, micro nudges.
|
||||
SPACE_CHIP :: 4
|
||||
|
||||
// Inline element gaps, chip/pill padding, icon inset, tight row spacing.
|
||||
SPACE_ELEMENT :: 8
|
||||
|
||||
// Button vertical padding, input inset, list row gap, label-to-field gap.
|
||||
SPACE_COMPONENT :: 12
|
||||
|
||||
// Card inset, input horizontal padding, form field gap, default gap.
|
||||
SPACE_GROUP :: 16
|
||||
|
||||
// Grouped nav items, related form section spacing, compact panel inset.
|
||||
SPACE_CLUSTER :: 20
|
||||
|
||||
// Sidebar / panel inset, modal body padding, drawer inset, section
|
||||
// subheader gap.
|
||||
SPACE_PANEL :: 24
|
||||
|
||||
// Between distinct content blocks, card grid gutter, toolbar height.
|
||||
SPACE_BLOCK :: 32
|
||||
|
||||
// Major content group spacing, dialog padding, page sub-section gap.
|
||||
SPACE_CONTENT :: 40
|
||||
|
||||
// Page section breaks, feature group dividers, hero subheading gap.
|
||||
SPACE_SECTION :: 48
|
||||
|
||||
// Hero vertical padding, layout area spacing, large feature gaps.
|
||||
SPACE_REGION :: 64
|
||||
|
||||
// Page-scale layout spacing, full-width section vertical rhythm.
|
||||
SPACE_ZONE :: 80
|
||||
|
||||
// Page margins, full-bleed hero top padding, maximum layout gutter.
|
||||
SPACE_CANVAS :: 96
|
||||
|
||||
|
||||
// ============================================================
|
||||
// CORNER RADIUS
|
||||
// Cybersteel does not round its corners like a toy. 0–4px is the
|
||||
// preferred range; larger radii exist only for chips/pills.
|
||||
// ============================================================
|
||||
|
||||
RADIUS_NONE :: 0 // sharp corners — preferred default for chrome
|
||||
RADIUS_SM :: 4 // micro-rounding for inline code, small badges
|
||||
RADIUS_MD :: 6 // default for cards, buttons, inputs
|
||||
RADIUS_LG :: 10 // rare — used only for prominent containers
|
||||
RADIUS_PILL :: 999 // fully-rounded chips, status pills, tags
|
||||
|
||||
|
||||
// ============================================================
|
||||
// BORDER WIDTH
|
||||
// 1px solid is the standard. Heavier weights are only used for
|
||||
// the Art Deco hairline accent on pre/code blocks.
|
||||
// ============================================================
|
||||
|
||||
// Standard border weight everywhere — always crisp, always visible.
|
||||
BORDER_WIDTH_DEFAULT :: 1
|
||||
|
||||
// Accent edge on <pre> blocks (left side, gold) and similar
|
||||
// emphasized rule treatments.
|
||||
BORDER_WIDTH_ACCENT :: 2
|
||||
|
||||
|
||||
// ============================================================
|
||||
// MOTION — TRANSITION DURATIONS
|
||||
// Fast and purposeful. No bounce, no spring, no elastic. UI
|
||||
// state changes in well under a quarter-second. Animations
|
||||
// must explain causality; nothing is decorative.
|
||||
// ============================================================
|
||||
|
||||
// Entering active/pressed state. Snap-down feel — must feel
|
||||
// instant under the finger.
|
||||
TRANSITION_PRESS :: 55 * time.Millisecond
|
||||
|
||||
// Releasing from a pressed state, and slower hover-out cases.
|
||||
TRANSITION_UI :: 180 * time.Millisecond
|
||||
|
||||
// Hover enter / exit color shift on buttons, cards, links.
|
||||
TRANSITION_HOVER :: 150 * time.Millisecond
|
||||
|
||||
// Overlay / modal / popover fade-in. Slightly longer to
|
||||
// signal "a layer changed", not "a control changed".
|
||||
TRANSITION_MODAL :: 200 * time.Millisecond
|
||||
|
||||
// Cursor / immediate-feedback transitions (caret moves,
|
||||
// terminal output ticks).
|
||||
TRANSITION_CURSOR :: 80 * time.Millisecond
|
||||
|
||||
|
||||
// ============================================================
|
||||
// MOTION — COMPONENT-LEVEL TIMINGS
|
||||
// Specific named durations for known interactions. Prefer these
|
||||
// over picking a raw transition for a given component.
|
||||
// ============================================================
|
||||
|
||||
// Button press fade — primary/secondary/danger/success share this.
|
||||
BUTTON_PRESS_FADE_DUR :: 55 * time.Millisecond
|
||||
|
||||
// Button release / hover-out fade.
|
||||
BUTTON_RELEASE_FADE_DUR :: 180 * time.Millisecond
|
||||
|
||||
// Card hover (border + bg crossfade).
|
||||
CARD_HOVER_FADE_DUR :: 150 * time.Millisecond
|
||||
|
||||
// Card press (border + bg snap to active).
|
||||
CARD_PRESS_FADE_DUR :: 55 * time.Millisecond
|
||||
|
||||
// Modal / overlay enter.
|
||||
MODAL_ENTER_DUR :: 200 * time.Millisecond
|
||||
|
||||
// Modal / overlay exit (mirror of enter for symmetry).
|
||||
MODAL_EXIT_DUR :: 200 * time.Millisecond
|
||||
|
||||
// Link color crossfade on hover.
|
||||
LINK_HOVER_FADE_DUR :: 180 * time.Millisecond
|
||||
|
||||
// Terminal scanline flicker tick — single frame of the loop.
|
||||
SCANLINE_FLICKER_TICK :: 80 * time.Millisecond
|
||||
|
||||
|
||||
// ============================================================
|
||||
// TYPOGRAPHY — FONT FAMILY NAMES
|
||||
// Sans: IBM Plex Sans
|
||||
// Mono: Lilex — IBM Plex Mono with programming ligatures.
|
||||
// Drop-in Plex Mono replacement; same skeleton, same
|
||||
// proportions, plus =>, !=, >=, <=, etc. ligatures.
|
||||
// Plex Sans covers display, body, and condensed roles by
|
||||
// default. Lilex is for code, terminal output, data values,
|
||||
// and full mono-mode surfaces.
|
||||
// ============================================================
|
||||
|
||||
// Plain family names
|
||||
FONT_FAMILY_SANS :: "IBM Plex Sans"
|
||||
FONT_FAMILY_MONO :: "Lilex"
|
||||
|
||||
// IBM Plex Sans raw font data
|
||||
SANS_THIN_RAW :: #load("fonts/IBMPlexSans-Thin.ttf") // IBM Plex Sans
|
||||
SANS_THIN_ITALIC_RAW :: #load("fonts/IBMPlexSans-ThinItalic.ttf") // IBM Plex Sans
|
||||
SANS_EXTRALIGHT_RAW :: #load("fonts/IBMPlexSans-ExtraLight.ttf") // IBM Plex Sans
|
||||
SANS_EXTRALIGHT_ITALIC_RAW :: #load("fonts/IBMPlexSans-ExtraLightItalic.ttf") // IBM Plex Sans
|
||||
SANS_LIGHT_RAW :: #load("fonts/IBMPlexSans-Light.ttf") // IBM Plex Sans
|
||||
SANS_LIGHT_ITALIC_RAW :: #load("fonts/IBMPlexSans-LightItalic.ttf") // IBM Plex Sans
|
||||
SANS_REGULAR_RAW :: #load("fonts/IBMPlexSans-Regular.ttf") // IBM Plex Sans
|
||||
SANS_ITALIC_RAW :: #load("fonts/IBMPlexSans-Italic.ttf") // IBM Plex Sans
|
||||
SANS_MEDIUM_RAW :: #load("fonts/IBMPlexSans-Medium.ttf") // IBM Plex Sans
|
||||
SANS_MEDIUM_ITALIC_RAW :: #load("fonts/IBMPlexSans-MediumItalic.ttf") // IBM Plex Sans
|
||||
SANS_SEMIBOLD_RAW :: #load("fonts/IBMPlexSans-SemiBold.ttf") // IBM Plex Sans
|
||||
SANS_SEMIBOLD_ITALIC_RAW :: #load("fonts/IBMPlexSans-SemiBoldItalic.ttf") // IBM Plex Sans
|
||||
SANS_BOLD_RAW :: #load("fonts/IBMPlexSans-Bold.ttf") // IBM Plex Sans
|
||||
SANS_BOLD_ITALIC_RAW :: #load("fonts/IBMPlexSans-BoldItalic.ttf") // IBM Plex Sans
|
||||
|
||||
// Lilex raw font data
|
||||
MONO_THIN_RAW :: #load("fonts/Lilex-Thin.ttf") // Lilex
|
||||
MONO_THIN_ITALIC_RAW :: #load("fonts/Lilex-ThinItalic.ttf") // Lilex
|
||||
MONO_EXTRALIGHT_RAW :: #load("fonts/Lilex-ExtraLight.ttf") // Lilex
|
||||
MONO_EXTRALIGHT_ITALIC_RAW :: #load("fonts/Lilex-ExtraLightItalic.ttf") // Lilex
|
||||
MONO_LIGHT_RAW :: #load("fonts/Lilex-Light.ttf") // Lilex
|
||||
MONO_LIGHT_ITALIC_RAW :: #load("fonts/Lilex-LightItalic.ttf") // Lilex
|
||||
MONO_REGULAR_RAW :: #load("fonts/Lilex-Regular.ttf") // Lilex
|
||||
MONO_ITALIC_RAW :: #load("fonts/Lilex-Italic.ttf") // Lilex
|
||||
MONO_MEDIUM_RAW :: #load("fonts/Lilex-Medium.ttf") // Lilex
|
||||
MONO_MEDIUM_ITALIC_RAW :: #load("fonts/Lilex-MediumItalic.ttf") // Lilex
|
||||
MONO_SEMIBOLD_RAW :: #load("fonts/Lilex-SemiBold.ttf") // Lilex
|
||||
MONO_SEMIBOLD_ITALIC_RAW :: #load("fonts/Lilex-SemiBoldItalic.ttf") // Lilex
|
||||
MONO_BOLD_RAW :: #load("fonts/Lilex-Bold.ttf") // Lilex
|
||||
MONO_BOLD_ITALIC_RAW :: #load("fonts/Lilex-BoldItalic.ttf") // Lilex
|
||||
|
||||
|
||||
// ============================================================
|
||||
// TYPOGRAPHY — TYPE SCALE (1.25 modular ratio, base 16px)
|
||||
// Minimum body size on web is 14px; print is 12pt.
|
||||
// ============================================================
|
||||
|
||||
TEXT_XS :: 11 // status badges, fine print
|
||||
TEXT_SM :: 13 // secondary labels, captions
|
||||
TEXT_BASE :: 15 // default body text
|
||||
TEXT_MD :: 16 // slightly prominent body
|
||||
TEXT_LG :: 18 // subheadings, emphasized labels
|
||||
TEXT_XL :: 22 // H3 level
|
||||
TEXT_2XL :: 28 // H2 level
|
||||
TEXT_3XL :: 36 // H1 level
|
||||
TEXT_4XL :: 48 // display / hero
|
||||
TEXT_5XL :: 64 // hero display
|
||||
TEXT_6XL :: 96 // max scale; masthead only
|
||||
|
||||
|
||||
// ============================================================
|
||||
// TYPOGRAPHY — FONT WEIGHTS
|
||||
// Constrained to the STATIC weights that BOTH faces actually
|
||||
// ship from Google Fonts — IBM Plex Sans and Lilex share the
|
||||
// same seven static instances:
|
||||
// 100 Thin · 200 ExtraLight · 300 Light · 400 Regular ·
|
||||
// 500 Medium · 600 SemiBold · 700 Bold
|
||||
// There is no 800 ExtraBold and no 900 Black for either face.
|
||||
// Do not request a weight outside this set — Google's API
|
||||
// will fail or substitute, and the design will drift.
|
||||
// ============================================================
|
||||
|
||||
WEIGHT_THIN :: 100
|
||||
WEIGHT_EXTRALIGHT :: 200
|
||||
WEIGHT_LIGHT :: 300
|
||||
WEIGHT_REGULAR :: 400
|
||||
WEIGHT_MEDIUM :: 500
|
||||
WEIGHT_SEMIBOLD :: 600
|
||||
WEIGHT_BOLD :: 700
|
||||
|
||||
|
||||
// ============================================================
|
||||
// TYPOGRAPHY — LINE HEIGHTS (unitless multipliers)
|
||||
// Multiply by font size to derive a leading in pixels.
|
||||
// ============================================================
|
||||
|
||||
LEADING_TIGHT :: 1.15 // display headings
|
||||
LEADING_SNUG :: 1.30 // subheadings
|
||||
LEADING_NORMAL :: 1.50 // default body prose
|
||||
LEADING_LOOSE :: 1.70 // long-form reading, sparse density
|
||||
LEADING_MONO :: 1.40 // code / terminal output
|
||||
|
||||
|
||||
// ============================================================
|
||||
// TYPOGRAPHY — LETTER SPACING (in EM units)
|
||||
// Multiply by the resolved font size to get pixel spacing.
|
||||
// ============================================================
|
||||
|
||||
TRACKING_TIGHT :: -0.02 // large headings, tightened display
|
||||
TRACKING_NORMAL :: 0.00 // body default
|
||||
TRACKING_WIDE :: 0.05 // H1/H2 ALL CAPS, button labels
|
||||
TRACKING_WIDER :: 0.10 // H5 caps, section headers
|
||||
TRACKING_WIDEST :: 0.20 // .label / .label-mono — ALL CAPS chip text
|
||||
|
||||
|
||||
// ============================================================
|
||||
// HEADING ROLES — paired size + tracking + casing intent
|
||||
// Casing is documentation only; these are the numbers a
|
||||
// renderer actually consumes.
|
||||
// ============================================================
|
||||
|
||||
// H1 — page title, masthead. Title Case, ALL CAPS at display.
|
||||
H1_SIZE :: TEXT_3XL
|
||||
H1_WEIGHT :: WEIGHT_BOLD
|
||||
H1_TRACKING :: TRACKING_WIDE
|
||||
H1_LEADING :: LEADING_TIGHT
|
||||
|
||||
// H2 — major section. ALL CAPS.
|
||||
H2_SIZE :: TEXT_2XL
|
||||
H2_WEIGHT :: WEIGHT_BOLD
|
||||
H2_TRACKING :: TRACKING_WIDE
|
||||
H2_LEADING :: LEADING_TIGHT
|
||||
|
||||
// H3 — subsection. Sentence case, condensed semibold.
|
||||
H3_SIZE :: TEXT_XL
|
||||
H3_WEIGHT :: WEIGHT_SEMIBOLD
|
||||
H3_TRACKING :: TRACKING_NORMAL
|
||||
H3_LEADING :: LEADING_TIGHT
|
||||
|
||||
// H4 — minor subsection.
|
||||
H4_SIZE :: TEXT_LG
|
||||
H4_WEIGHT :: WEIGHT_SEMIBOLD
|
||||
H4_TRACKING :: TRACKING_NORMAL
|
||||
H4_LEADING :: LEADING_SNUG
|
||||
|
||||
// H5 — small caps section header (uses FG_SECONDARY).
|
||||
H5_SIZE :: TEXT_BASE
|
||||
H5_WEIGHT :: WEIGHT_SEMIBOLD
|
||||
H5_TRACKING :: TRACKING_WIDER
|
||||
H5_LEADING :: LEADING_SNUG
|
||||
|
||||
// H6 — mono caps eyebrow / overline (uses FG_CAPTION).
|
||||
H6_SIZE :: TEXT_SM
|
||||
H6_WEIGHT :: WEIGHT_REGULAR
|
||||
H6_TRACKING :: TRACKING_WIDEST
|
||||
H6_LEADING :: LEADING_SNUG
|
||||
|
||||
|
||||
// ============================================================
|
||||
// LABEL ROLES — small caps annotation chips
|
||||
// ============================================================
|
||||
|
||||
// .label — sans condensed, ALL CAPS, FG_CAPTION.
|
||||
LABEL_SIZE :: TEXT_XS
|
||||
LABEL_WEIGHT :: WEIGHT_SEMIBOLD
|
||||
LABEL_TRACKING :: TRACKING_WIDEST
|
||||
|
||||
// .label-mono — mono ALL CAPS, FG_MUTED.
|
||||
LABEL_MONO_SIZE :: TEXT_XS
|
||||
LABEL_MONO_WEIGHT :: WEIGHT_REGULAR
|
||||
LABEL_MONO_TRACKING :: TRACKING_WIDEST
|
||||
|
||||
|
||||
// ============================================================
|
||||
// FOCUS RING
|
||||
// 1px solid gold outline at 2px offset. Crisp, never blurry.
|
||||
// No glow, no box-shadow halo.
|
||||
// ============================================================
|
||||
|
||||
FOCUS_RING_WIDTH :: 1
|
||||
FOCUS_RING_OFFSET :: 2
|
||||
FOCUS_RING_COLOR :: BORDER_FOCUS // GOLD_BRIGHT
|
||||
|
||||
|
||||
// ============================================================
|
||||
// COMPONENT — BUTTONS
|
||||
// Cybersteel buttons are uppercase, semibold→bold, with wide
|
||||
// tracking. Default size is "md"; sm/lg shift padding + size.
|
||||
// ============================================================
|
||||
|
||||
// Default (md) padding: vertical / horizontal
|
||||
BUTTON_PAD_Y :: 8
|
||||
BUTTON_PAD_X :: 18
|
||||
BUTTON_FONT_SIZE :: 12
|
||||
BUTTON_FONT_WEIGHT :: WEIGHT_BOLD
|
||||
BUTTON_TRACKING :: 0.07 // EM — ALL CAPS button label
|
||||
BUTTON_RADIUS :: RADIUS_MD
|
||||
BUTTON_BORDER :: BORDER_WIDTH_DEFAULT
|
||||
|
||||
// Small button
|
||||
BUTTON_SM_PAD_Y :: 5
|
||||
BUTTON_SM_PAD_X :: 12
|
||||
BUTTON_SM_FONT_SIZE :: 10
|
||||
|
||||
// Large button
|
||||
BUTTON_LG_PAD_Y :: 11
|
||||
BUTTON_LG_PAD_X :: 24
|
||||
BUTTON_LG_FONT_SIZE :: 14
|
||||
|
||||
// Primary — solid gold fill, dark text. Hover brightens, press
|
||||
// flips to fg-heading (cream) fill.
|
||||
BUTTON_PRIMARY_BG :: GOLD_DIM
|
||||
BUTTON_PRIMARY_FG :: BG_SHELL
|
||||
BUTTON_PRIMARY_BORDER :: GOLD_DIM
|
||||
BUTTON_PRIMARY_BG_HOVER :: GOLD_BRIGHT
|
||||
BUTTON_PRIMARY_BORDER_HOVER :: GOLD_BRIGHT
|
||||
BUTTON_PRIMARY_BG_PRESS :: FG_HEADING
|
||||
BUTTON_PRIMARY_FG_PRESS :: BG_SHELL
|
||||
BUTTON_PRIMARY_BORDER_PRESS :: FG_HEADING
|
||||
|
||||
// Secondary — transparent bg, structural border, hover gains
|
||||
// gold tint + gold-dim border, press fills with gold-bright.
|
||||
BUTTON_SECONDARY_BG :: [4]u8{0, 0, 0, 0} // transparent
|
||||
BUTTON_SECONDARY_FG :: FG_SECONDARY
|
||||
BUTTON_SECONDARY_BORDER :: BG_BORDER
|
||||
BUTTON_SECONDARY_BG_HOVER :: TINT_GOLD_HOVER
|
||||
BUTTON_SECONDARY_BORDER_HOVER :: GOLD_DIM
|
||||
BUTTON_SECONDARY_FG_HOVER :: FG_BODY
|
||||
BUTTON_SECONDARY_BG_PRESS :: GOLD_BRIGHT
|
||||
BUTTON_SECONDARY_FG_PRESS :: [4]u8{0xff, 0xff, 0xff, 0xff}
|
||||
BUTTON_SECONDARY_BORDER_PRESS :: GOLD_BRIGHT
|
||||
|
||||
// Ghost — fully transparent, no border. Hover lifts to BG_ACTIVE.
|
||||
BUTTON_GHOST_BG :: [4]u8{0, 0, 0, 0}
|
||||
BUTTON_GHOST_FG :: FG_CAPTION
|
||||
BUTTON_GHOST_BORDER :: [4]u8{0, 0, 0, 0}
|
||||
BUTTON_GHOST_BG_HOVER :: BG_ACTIVE
|
||||
BUTTON_GHOST_FG_HOVER :: FG_BODY
|
||||
BUTTON_GHOST_BG_PRESS :: GOLD_DIM
|
||||
BUTTON_GHOST_FG_PRESS :: [4]u8{0xff, 0xff, 0xff, 0xff}
|
||||
|
||||
// Danger — destructive ghost button.
|
||||
BUTTON_DANGER_BG :: [4]u8{0, 0, 0, 0}
|
||||
BUTTON_DANGER_FG :: RED_BRIGHT
|
||||
BUTTON_DANGER_BORDER :: RED_DIM
|
||||
BUTTON_DANGER_BG_HOVER :: TINT_DANGER_HOVER
|
||||
BUTTON_DANGER_BORDER_HOVER :: RED_BRIGHT
|
||||
BUTTON_DANGER_FG_HOVER :: FG_BODY
|
||||
BUTTON_DANGER_BG_PRESS :: RED_BRIGHT
|
||||
BUTTON_DANGER_FG_PRESS :: [4]u8{0xff, 0xff, 0xff, 0xff}
|
||||
BUTTON_DANGER_BORDER_PRESS :: RED_BRIGHT
|
||||
|
||||
// Success — confirming ghost button.
|
||||
BUTTON_SUCCESS_BG :: [4]u8{0, 0, 0, 0}
|
||||
BUTTON_SUCCESS_FG :: GREEN_BRIGHT
|
||||
BUTTON_SUCCESS_BORDER :: GREEN_DIM
|
||||
BUTTON_SUCCESS_BG_HOVER :: TINT_SUCCESS_HOVER
|
||||
BUTTON_SUCCESS_BORDER_HOVER :: GREEN_BRIGHT
|
||||
BUTTON_SUCCESS_FG_HOVER :: FG_BODY
|
||||
BUTTON_SUCCESS_BG_PRESS :: GREEN_BRIGHT
|
||||
BUTTON_SUCCESS_FG_PRESS :: [4]u8{0xff, 0xff, 0xff, 0xff}
|
||||
BUTTON_SUCCESS_BORDER_PRESS :: GREEN_BRIGHT
|
||||
|
||||
// Disabled — flat low-contrast surface, opacity-dimmed.
|
||||
BUTTON_DISABLED_BG :: BG_ACTIVE
|
||||
BUTTON_DISABLED_FG :: FG_MUTED
|
||||
BUTTON_DISABLED_BORDER :: BG_BORDER
|
||||
BUTTON_DISABLED_OPACITY :: 0.5
|
||||
|
||||
|
||||
// ============================================================
|
||||
// COMPONENT — CARDS
|
||||
// Flat, structural, mechanical. Background sits one step above
|
||||
// page; border is structural by default and shifts to gold-dim
|
||||
// on hover/press. Corner radius is the default 6px (RADIUS_MD).
|
||||
// ============================================================
|
||||
|
||||
CARD_BG :: BG_SURFACE
|
||||
CARD_BORDER :: BG_BORDER
|
||||
CARD_BORDER_HOVER :: GOLD_DIM
|
||||
CARD_BG_PRESS :: BG_ACTIVE
|
||||
CARD_BORDER_PRESS :: GOLD_DIM
|
||||
CARD_RADIUS :: RADIUS_MD
|
||||
CARD_BORDER_WIDTH :: BORDER_WIDTH_DEFAULT
|
||||
CARD_PADDING :: SPACE_GROUP // 16px default inset
|
||||
|
||||
|
||||
// ============================================================
|
||||
// COMPONENT — INPUTS
|
||||
// Inputs sit on BG_SURFACE with structural borders. Focus
|
||||
// promotes the border to gold-bright; the focus ring follows.
|
||||
// ============================================================
|
||||
|
||||
INPUT_BG :: BG_SURFACE
|
||||
INPUT_FG :: FG_BODY
|
||||
INPUT_PLACEHOLDER :: FG_CAPTION
|
||||
INPUT_BORDER :: BG_BORDER
|
||||
INPUT_BORDER_HOVER :: GOLD_DIM
|
||||
INPUT_BORDER_FOCUS :: GOLD_BRIGHT
|
||||
INPUT_BORDER_DANGER :: RED_DIM
|
||||
INPUT_RADIUS :: RADIUS_MD
|
||||
INPUT_PAD_Y :: SPACE_COMPONENT // 12
|
||||
INPUT_PAD_X :: SPACE_GROUP // 16
|
||||
|
||||
|
||||
// ============================================================
|
||||
// COMPONENT — BADGES / STATUS PILLS
|
||||
// ============================================================
|
||||
|
||||
BADGE_FONT_SIZE :: TEXT_XS
|
||||
BADGE_WEIGHT :: WEIGHT_SEMIBOLD
|
||||
BADGE_TRACKING :: TRACKING_WIDEST
|
||||
BADGE_PAD_Y :: SPACE_CHIP // 4
|
||||
BADGE_PAD_X :: SPACE_ELEMENT // 8
|
||||
BADGE_RADIUS :: RADIUS_SM
|
||||
|
||||
|
||||
// ============================================================
|
||||
// COMPONENT — DECO RULE
|
||||
// Hairline Art Deco horizontal rule: 1px gold-dim top + 1px
|
||||
// structural drop, with panel-sized vertical margins.
|
||||
// ============================================================
|
||||
|
||||
DECO_RULE_TOP_WIDTH :: 1
|
||||
DECO_RULE_TOP_COLOR :: GOLD_DIM
|
||||
DECO_RULE_DROP_WIDTH :: 1
|
||||
DECO_RULE_DROP_COLOR :: BG_BORDER
|
||||
DECO_RULE_MARGIN_Y :: SPACE_PANEL // 24
|
||||
|
||||
|
||||
// ============================================================
|
||||
// LAYOUT — FIXED CHROME WIDTHS
|
||||
// Sidebar widths are fixed; content lives in 8 or 12 column
|
||||
// grids. No responsive collapsing for chrome — Cybersteel UIs
|
||||
// run on real workstations.
|
||||
// ============================================================
|
||||
|
||||
SIDEBAR_WIDTH_NARROW :: 240
|
||||
SIDEBAR_WIDTH_WIDE :: 280
|
||||
|
||||
GRID_COLUMNS_NARROW :: 8
|
||||
GRID_COLUMNS_WIDE :: 12
|
||||
|
||||
// Toolbar height matches SPACE_BLOCK so vertical rhythm aligns.
|
||||
TOOLBAR_HEIGHT :: SPACE_BLOCK // 32
|
||||
|
||||
|
||||
// ============================================================
|
||||
// CODE BLOCKS — <pre>
|
||||
// Mono, BG_SHELL surface with a 1px structural border and a
|
||||
// 2px gold-dim accent on the left edge.
|
||||
// ============================================================
|
||||
|
||||
CODE_INLINE_BG :: BG_SURFACE
|
||||
CODE_INLINE_FG :: GOLD_BRIGHT
|
||||
CODE_INLINE_BORDER :: BG_BORDER
|
||||
CODE_INLINE_PAD_Y :: 2
|
||||
CODE_INLINE_PAD_X :: 6
|
||||
CODE_INLINE_RADIUS :: RADIUS_SM
|
||||
|
||||
PRE_BG :: BG_SHELL
|
||||
PRE_FG :: FG_BODY
|
||||
PRE_BORDER :: BG_BORDER
|
||||
PRE_BORDER_LEFT_COLOR :: GOLD_DIM
|
||||
PRE_BORDER_LEFT_WIDTH :: BORDER_WIDTH_ACCENT // 2
|
||||
PRE_PAD_Y :: SPACE_GROUP // 16
|
||||
PRE_PAD_X :: SPACE_PANEL // 24
|
||||
|
||||
|
||||
// ============================================================
|
||||
// SCANLINE OVERLAY (opt-in, terminal surfaces only)
|
||||
// Repeating-stripe pattern at very low opacity. Stripe is 2px
|
||||
// transparent + 2px black-at-3% (TINT_SCANLINE).
|
||||
// ============================================================
|
||||
|
||||
SCANLINE_STRIPE_PX :: 2
|
||||
SCANLINE_GAP_PX :: 2
|
||||
SCANLINE_COLOR :: TINT_SCANLINE
|
||||
Reference in New Issue
Block a user