| name | design-token-css |
| description | Styling for the server-rendered / no-build stacks (php, vanilla-flask): a token-driven CSS sheet themed per-run by editing one `:root` variable block. Invoke on these stacks to give each lab a distinctive, coherent, believable look — different every run — without a build step.
|
design-token-css skill
Applies to php and vanilla-flask — no build step, so styling is one shared
CSS sheet driven by CSS variables.
Goal: each lab should look like a real product with a genuinely different
look every run — not the same default blue, not generic AI slop.
Commit to ONE bold direction first (before coding)
Pick one aesthetic direction and execute it with intentionality. Refined
minimalism and bold maximalism both win — what matters is a clear
point-of-view. Options (full hex token/font/texture recipes in
references/aesthetic-directions.md):
refined/luxury · brutally minimal · brutalist/raw · retro-futuristic ·
organic/natural · editorial/magazine · playful/toy · industrial/utilitarian ·
soft/pastel · art-deco/geometric · glassmorphism · claymorphism ·
dark academia · memphis/80s-pop · signal (deep-navy & gold)
Decide up front: light or dark, the dominant brand color + one sharp
accent, the radius scale, and a font pairing (display + body). Then
encode those decisions in the token block. Never converge on the same
choices run to run.
Where the styling lives (already in the template — don't re-create)
- php:
public/app.css, linked from the single shared layout
render_page() in src/auth.php. Every page uses it.
- vanilla-flask:
static_assets/style.css, linked from index.html.
Both ship a canonical sheet whose component rules (nav, .card, .btn,
input, table, .alert) consume an AGENT THEME TOKENS :root block.
Theme per-run via tokens (the only thing you edit to re-skin)
Edit only the :root { … } token block. The component rules stay fixed.
Tokens are hex/value based (not HSL):
--font-sans
--radius
--bg --surface --text --muted --border
--brand --brand-hover
--on-brand --on-brand-muted
Set the product brand name: the $brand arg to render_page() (php) or the
.brand text in index.html (vanilla) — invent a domain-fitting name, not the
spec's lab id.
Allowed creative edits, beyond the colors: a single web-font @import at the
top of the CSS file (+ optional --font-display token used by a global heading
rule); a few extra tokens added to :root (e.g. --accent, --shadow,
--app-bg) referenced from global rules; and atmosphere (gradient-mesh
--app-bg, grain overlay) instead of a flat background — all in
references/aesthetic-directions.md and references/component-snippets.md.
Vary the composition, not just the color
Same data, different shape. references/component-snippets.md is a copy-paste
library of token-only building blocks — hero/header treatments, stat tiles, card
variations, list rows (vs tables), badges/pills, empty states, split auth
screens, and a one-shot staggered page-load reveal. Mix a different selection
each run so two labs with the same data don't look the same.
Icons & imagery
These stacks can't npm install an icon pack, but real photos make a lab feel
like a product — use both:
- Icons → inline SVG. Paste small
<svg> glyphs (a 20–24px viewBox,
fill="none" stroke="currentColor") directly into the markup; currentColor
tints them with the surrounding token color automatically. Use them in nav
items, buttons, and stat tiles.
- Content-matched photos → invoke the
arena-spawner:stock-images skill.
For imagery that should depict its subject (product catalogs, article covers,
profile/team faces, venue shots), that skill builds keyword-matched, browser-
loaded image URLs seeded by row id — so a coffee catalog actually shows coffee.
(Plain picsum.photos/i.pravatar.cc seeds are fine only for subject-agnostic
filler or avatars.) Always give every <img> a real alt and fixed
width/height (or aspect-ratio) so layout doesn't jump while it loads.
- Atmosphere → CSS/SVG. Gradient meshes, a subtle pattern, or a data-URI SVG
backdrop — token-colored (
var(--brand), var(--accent)) so it re-skins with
the theme. Layer these behind/around the photos rather than replacing them.
Pick imagery that fits the domain (a product grid shows products, profiles show
faces) — not decorative noise.
A nudge, not a cage — combine with a direction above:
- ecommerce / social / blog / creative / media → bolder brand color, larger
radius, display/serif headline.
- banking / fintech / insurance / legal / gov → muted navy/green/ink, small
radius, clean sans — refined and trustworthy.
- healthcare / wellness / education → soft/pastel or calm organic.
- devops / developer tools / analytics / infra → dense industrial, often
dark, mono for figures.
- hospitality / food / travel / events → warm, editorial or playful.
- Never ship the default palette unchanged.
Anti-"AI slop" checklist (every run)
Pitfalls / guardrails
- Theme through the token block + brand + font ONLY. No per-page
<style>
blocks; no inline hex. Inline style="…" is acceptable only when every
value references a token (var(--brand), var(--border)), never a literal
color. New reusable classes go in the shared sheet, never per page.
- php: never bypass
render_page() — every page renders through it.
- Keep the one shared layout/nav; consistency across pages is the point.
- Decorative shapes must never block clicks. Any purely-decorative
absolutely-positioned element (squiggles, blobs, dots, zigzags, confetti,
gradient orbs) MUST set
pointer-events: none (and aria-hidden). An absolute
shape with a negative offset overflows its box and silently covers the nav or
buttons beneath it, swallowing their clicks — a real, hard-to-spot bug. Keep
decorations behind content (low/negative z-index) and non-interactive.