Skip to main content

max / balanced_breakfast

css: F5 phase A — install utility layer + GO-shared invariant scales BB had the compose-first charter but defined none of the utilities/layout primitives it names, and had no spacing/type scale (raw rem literals). Install them so F5 row migrations (phase B) and future GO-pattern ports drop in. - Utilities (BAND FOUNDATIONS, new §2b): .flex-1, .stack + .stack-{2,3,4}, .row-flex + .row-flex-{2,3,4}, .mb-1/.mb-2, .text-sm/.text-sm-secondary. `.row` is deliberately NOT a utility — it is BB's renderRow component base; raw flex rows use .row-flex. - :root invariant scales, values mirrored from GO for cross-app portability: --space-1..6, --font-size-xxs..4xl, --line-height-*, --transition-*, plus the missing --radius-xs/--radius-full. radius-md stays absent (dropped dup). - lint: theme-token-coverage extractor was digit-blind (--[a-z-]+), collapsing --space-2 to --space-; widened to --[a-z0-9-]+ so numbered tokens resolve. All utilities currently unused, so purely additive (no visual change). CSS parses clean; 55 JS tests pass. Lint unchanged at 28 pre-existing theme-token-coverage failures (color tokens vs themes.js drift — separate F5 themes.js cleanup, not touched here). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-12 17:26 UTC
Commit: 2f0339ba813f750b63c67024b4bc63b30cbbb2b1
Parent: 141cb64
2 files changed, +63 insertions, -6 deletions
@@ -78,7 +78,7 @@ report "no-native-dialogs" "window.confirm/prompt/alert are banned — use BB.ui
78 78 # /* composition */ annotation on the same line. Catches dangling
79 79 # tokens that silently fall back to the hardcoded :root value.
80 80 root_tokens=$(awk '/^:root \{/{flag=1; next} /^\}/{flag=0} flag' "$SRC_CSS" \
81 - | grep -oE -- '--[a-z-]+' | sort -u || true)
81 + | grep -oE -- '--[a-z0-9-]+' | sort -u || true)
82 82 unmapped=""
83 83 for tok in $root_tokens; do
84 84 # Allow tokens marked invariant or composition on the declaration line.
@@ -4,11 +4,12 @@
4 4 Build new UI by COMPOSING the existing vocabulary, in this order of preference:
5 5
6 6 1. Use a UTILITY class for one-off adjustments (.hidden, .sr-only,
7 - .mb-1, .flex-1 — most
8 - still to be added)
9 - 2. Use a LAYOUT PRIMITIVE to position content (.row-flex, .row,
10 - .stack-{2,3,4} —
11 - to be added in F1/F2)
7 + .mb-1, .mb-2, .flex-1,
8 + .text-sm,
9 + .text-sm-secondary)
10 + 2. Use a LAYOUT PRIMITIVE to position content (.row-flex +
11 + .row-flex-{2,3,4},
12 + .stack + .stack-{2,3,4})
12 13 3. Use a COMPONENT PRIMITIVE for a UI element (.btn, .card, .modal,
13 14 .form-input,
14 15 .form-select, .badge,
@@ -48,6 +49,8 @@
48 49 BAND: FOUNDATIONS
49 50 1. Design System Variables — tokens (:root)
50 51 2. CSS Reset & Base
52 + 2b. Utility Classes — layout primitives,
53 + margin, text
51 54 3. Keyframes & Animation
52 55
53 56 BAND: APP SHELL & CHROME
@@ -157,11 +160,40 @@
157 160 --accent-yellow-light: color-mix(in oklch, var(--category-four) 82%, white);
158 161 --shadow-color: color-mix(in oklch, var(--content-muted) 88%, black);
159 162 --border-width: 2px; /* invariant */
163 + --radius-xs: 3px; /* invariant — scrollbars, tiny elements */
160 164 --radius-sm: 5px; /* invariant */
161 165 --radius-lg: 10px; /* invariant */
162 166 --radius-xl: 20px; /* invariant */
167 + --radius-full: 50%; /* invariant — circles */
163 168 --shadow-offset: 3px; /* invariant — BB neobrute signature */
164 169 --shadow-brutal: var(--shadow-offset) var(--shadow-offset) 0 var(--shadow-color); /* invariant composition */
170 +
171 + /* Invariant scales (values shared with GO for cross-app portability;
172 + never themed). Per-line `invariant` markers satisfy the lint
173 + theme-token-coverage rule. radius-md intentionally absent (dropped as
174 + a dup of radius-sm). */
175 + --space-1: 0.25rem; /* invariant */
176 + --space-2: 0.5rem; /* invariant */
177 + --space-3: 0.75rem; /* invariant */
178 + --space-4: 1rem; /* invariant */
179 + --space-5: 1.25rem; /* invariant */
180 + --space-6: 1.5rem; /* invariant */
181 + --font-size-xxs: 0.65rem; /* invariant — tiny badges, indicators */
182 + --font-size-xs: 0.7rem; /* invariant — small badges, counts */
183 + --font-size-sm: 0.75rem; /* invariant — meta text, timestamps */
184 + --font-size-md: 0.8rem; /* invariant — table headers, compact UI */
185 + --font-size-base: 0.875rem; /* invariant — body text default */
186 + --font-size-lg: 1rem; /* invariant — emphasized body text */
187 + --font-size-xl: 1.1rem; /* invariant — subheadings */
188 + --font-size-2xl: 1.25rem; /* invariant — section titles */
189 + --font-size-3xl: 1.5rem; /* invariant — page titles */
190 + --font-size-4xl: 1.75rem; /* invariant — main headings */
191 + --line-height-tight: 1.25; /* invariant */
192 + --line-height-normal: 1.5; /* invariant */
193 + --line-height-relaxed: 1.75; /* invariant */
194 + --transition-fast: 0.1s; /* invariant */
195 + --transition-normal: 0.15s; /* invariant */
196 + --transition-slow: 0.3s; /* invariant */
165 197 }
166 198 /* F5 cleanup (2026-06-02): dropped --bg-surface (themed but never consumed),
167 199 --radius-md (duplicate of --radius-sm), --shadow / --shadow-hover (derived
@@ -171,6 +203,31 @@
171 203 /* === 2. CSS Reset & Base ================================================ */
172 204 * { margin: 0; padding: 0; box-sizing: border-box; }
173 205
206 + /* === 2b. Utility Classes ================================================
207 + Compose-first layer (see header). Ported from GO's utility set; all consume
208 + the shared --space-* / intent tokens. NOTE: `.row` is NOT a utility here —
209 + BB uses `.row` as the renderRow COMPONENT base (see § Component Primitives).
210 + For a raw centered flex row use `.row-flex`; for a column use `.stack`.
211 + ========================================================================== */
212 + /* Layout primitives */
213 + .flex-1 { flex: 1; }
214 + .stack { display: flex; flex-direction: column; }
215 + .stack-2 { gap: var(--space-2); }
216 + .stack-3 { gap: var(--space-3); }
217 + .stack-4 { gap: var(--space-4); }
218 + .row-flex { display: flex; align-items: center; }
219 + .row-flex-2 { gap: var(--space-2); }
220 + .row-flex-3 { gap: var(--space-3); }
221 + .row-flex-4 { gap: var(--space-4); }
222 +
223 + /* Margin (values mirror GO exactly for drop-in ports) */
224 + .mb-1 { margin-bottom: var(--space-4); }
225 + .mb-2 { margin-bottom: var(--space-2); }
226 +
227 + /* Text */
228 + .text-sm { font-size: var(--font-size-sm); }
229 + .text-sm-secondary { font-size: var(--font-size-sm); color: var(--content-secondary); }
230 +
174 231 /* === 4. Layout shell — body & #app ==================================== */
175 232 body {
176 233 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;