aboutsummaryrefslogtreecommitdiff
path: root/frontend-design/references
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-04-19 15:57:50 -0500
committerCraig Jennings <c@cjennings.net>2026-04-19 15:57:50 -0500
commita8deb6af6a14bc5e56e86289a2858a0258558388 (patch)
tree274bde1b3f7f592ad9e0462d4069863f9e287727 /frontend-design/references
parentec31be0eb39f5b86c62729a24914c2e699b42232 (diff)
downloadrulesets-a8deb6af6a14bc5e56e86289a2858a0258558388.tar.gz
rulesets-a8deb6af6a14bc5e56e86289a2858a0258558388.zip
feat: adopt frontend-design (Apache 2.0 fork) + progressive-disclosure extensions
Forked verbatim from anthropics/skills/skills/frontend-design (Apache 2.0). LICENSE.txt preserved. Upstream SKILL.md prose (aesthetic guidance, archetype list, anti-pattern callouts) kept intact. Extensions added (clearly marked, load progressively — base SKILL.md stays lean for simple cases): SKILL.md: - Description extended with explicit negative triggers: narrow maintenance (single CSS bug, dependency upgrade, a11y-only retrofit), operational contexts where stakeholder has specified "minimal, functional, no creative direction," backend / API work, non-web UIs (mobile native, desktop, terminal), and refactoring without visible design component. - New "Workflow" section at the end of SKILL.md: four phases (intake, commitment, build, review) with pointers to reference files. Simple component tweaks skip the workflow; non-trivial redesigns walk it. - New "References" section: table mapping file → load-when condition. - Attribution footer marking upstream source + what's locally added. references/workflow.md (~150 lines) Intake questions (purpose, audience, operational context, functional priority, technical constraints, brand references, success criteria). Commitment step (archetype pick, trade-offs, font pairing, palette, motion, layout as one-line decisions). Build reminders. Review pointer. Guidance on when to skip phases. references/accessibility.md (~200 lines) WCAG AA contrast thresholds + practical check guidance. Keyboard navigation + focus management. Semantic HTML + ARIA rules. Reduced- motion CSS snippet. Smoke checklist. Operational-context note for defense / ISR work. references/responsive.md (~160 lines) Mobile-first vs desktop-first decision. Named breakpoints (Tailwind- style) vs magic pixels. Container queries. Aesthetic translation table — how each archetype handles small-screen scaling. Responsive typography with clamp(). Operational-dashboard note: desktop-primary is a legitimate product decision. references/design-review.md (~170 lines) Archetype check (does the build read as what was committed to?). Anti-pattern grep for fonts, palette, layout, motion, backgrounds, components. Code-quality-match check (ornate design + lazy code = failure). Performance sanity. Convergence check (if last 3 builds all used the same archetype, break the pattern). The one-sentence test for memorability. references/rationale-template.md (~160 lines) Template for design-rationale.md alongside the build. Nine sections (purpose, archetype, locked decisions, deliberately absent, accessibility, responsive, implementation, open questions, references). Filled example using a DeepSat SOCOM demo landing page to show density and specificity. Structure matches Anthropic's own pdf / docx / webapp-testing pattern (SKILL.md entry + references/ for progressive disclosure). Makefile SKILLS extended; make install symlinks globally. Adoption caveat resolved: name kept as `frontend-design` (not renamed to ui-design) — "frontend" signals scope (web code, not mobile / desktop / terminal UIs), upstream parity preserved for attribution.
Diffstat (limited to 'frontend-design/references')
-rw-r--r--frontend-design/references/accessibility.md109
-rw-r--r--frontend-design/references/design-review.md93
-rw-r--r--frontend-design/references/rationale-template.md133
-rw-r--r--frontend-design/references/responsive.md90
-rw-r--r--frontend-design/references/workflow.md86
5 files changed, 511 insertions, 0 deletions
diff --git a/frontend-design/references/accessibility.md b/frontend-design/references/accessibility.md
new file mode 100644
index 0000000..2b0ca66
--- /dev/null
+++ b/frontend-design/references/accessibility.md
@@ -0,0 +1,109 @@
+# Accessibility
+
+Default target: WCAG 2.1 AA. For government, healthcare, finance, or other regulated contexts: AAA on specific criteria (verify with the user). Don't wait for a retrofit — apply during build.
+
+## Color Contrast
+
+**WCAG AA thresholds:**
+- Normal text (< 18pt / < 14pt bold): **4.5:1** minimum
+- Large text (≥ 18pt or ≥ 14pt bold): **3:1** minimum
+- UI components and graphics (borders, icons, focus indicators): **3:1** minimum against adjacent colors
+- Decorative or disabled elements are exempt — but a "disabled" button the user might still try to click is NOT decorative
+
+**Practical:**
+- Use a checker during palette lock-in (WebAIM Contrast Checker, or `npx check-color-contrast`)
+- Light text on saturated backgrounds (e.g., white on red-500) often fails — check, don't assume
+- Gradient backgrounds mean text contrast varies across the gradient — check against the *worst-case* point under the text
+- Ambient/atmospheric effects (dust, grain overlays, gradient meshes) can push borderline contrast below the line — verify after the effect is applied
+
+## Keyboard
+
+**Every interactive element reachable via keyboard alone.** Test by putting away the mouse and Tab / Shift-Tab / Enter / Space / arrow keys through the interface.
+
+- Focus order follows visual order (not DOM order if CSS reorders)
+- `Tab` moves between controls; `Enter` / `Space` activates buttons and links; `Esc` dismisses modals/menus; arrow keys navigate within composite widgets (menus, radio groups, sliders)
+- Custom controls (non-native buttons, non-native select): implement full keyboard behavior, not just `onClick`
+- Skip-to-content link at the top of every page — invisible until focused
+
+**Focus visibility:**
+- The default browser focus ring is ugly but functional. Don't delete it without a replacement.
+- Custom focus styles need ≥ 3:1 contrast against the adjacent background
+- `:focus-visible` (not `:focus`) for keyboard-only focus rings — lets mouse clicks stay clean without losing keyboard clarity
+
+## Semantic HTML
+
+Prefer native elements over `<div role="button" tabIndex="0" onClick={...}>`. Native buttons, links, form controls, and landmarks come with keyboard behavior, focus management, and screen reader semantics for free.
+
+**Landmarks:**
+- `<header>`, `<nav>`, `<main>`, `<aside>`, `<footer>` — at most one `<main>` per page
+- Heading hierarchy: one `<h1>`, then `<h2>`s, then `<h3>`s — don't skip levels
+- `<section>` needs an `aria-labelledby` or it's just a `<div>` to a screen reader
+
+**Forms:**
+- Every input has a visible `<label>`. Placeholder text is not a label.
+- Error messages associated via `aria-describedby`; form-level errors announced via `aria-live="polite"` (non-urgent) or `assertive` (urgent; use sparingly)
+- Required fields marked both visually (color or `*`) and programmatically (`required` attribute)
+
+## ARIA (when native isn't enough)
+
+- `aria-label` / `aria-labelledby` for elements without visible text (icon-only buttons, close ✕ buttons)
+- `aria-expanded` on disclosure controls (accordions, menus)
+- `aria-controls` to connect a control to the region it toggles
+- `aria-hidden="true"` for decorative icons
+- `role="alert"` or `aria-live` regions for dynamic announcements
+
+**Rules of ARIA (from the WAI):**
+1. If a native HTML element or attribute exists for what you need, use that first.
+2. Don't change native semantics with ARIA unless absolutely necessary.
+3. All interactive ARIA controls must be keyboard-accessible.
+4. Don't use `role="presentation"` / `aria-hidden="true"` on focusable elements.
+5. Interactive elements must have an accessible name.
+
+## Reduced Motion
+
+Respect `prefers-reduced-motion` for animations, transitions, parallax, auto-playing video, scroll-triggered reveals. The aesthetic doesn't have to disappear — just slow down or still the motion.
+
+```css
+@media (prefers-reduced-motion: reduce) {
+ *, *::before, *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+}
+```
+
+Override per-element for critical motion (a loading spinner should still spin, just perhaps slower). The blanket rule above is a baseline; tune for context.
+
+## Images, Icons, and Media
+
+- `alt=""` for decorative images; descriptive `alt` for meaningful ones
+- SVG icons that carry meaning: `role="img"` + `aria-label`; purely decorative SVGs: `aria-hidden="true"`
+- Video: captions for any spoken content; autoplay muted; controls not hidden
+- Audio-only: transcript
+
+## Smoke Checklist (for quick audits)
+
+- [ ] All text meets contrast (spot-check worst-case regions)
+- [ ] Tab order matches visual order; all interactive elements reachable
+- [ ] Visible focus ring on every focusable element
+- [ ] Semantic HTML used where a native element exists
+- [ ] Icon-only buttons have `aria-label` or visible text
+- [ ] Form fields have labels; errors are associated
+- [ ] `prefers-reduced-motion` respected
+- [ ] No keyboard trap (you can Tab *out* of every modal/menu)
+- [ ] Page heading hierarchy is sensible (one `<h1>`, no skipped levels)
+
+## Testing
+
+- **Manual keyboard:** Tab through the whole page
+- **axe-core / Lighthouse** for automated audits (both run in Chrome DevTools)
+- **Screen reader spot-check:** VoiceOver (macOS), NVDA (Windows), Orca (Linux). Hit the main flows once.
+- **zoom test:** 200% browser zoom — does layout hold?
+
+Automated tools catch ~30-40% of accessibility issues. Manual + screen reader catches most of the rest.
+
+## Operational Context Note
+
+For defense / ISR / operational dashboards — accessibility is especially not optional. Users operating complex systems under time pressure depend on clear focus, unambiguous contrast, and keyboard control. Industrial / brutalist / utilitarian aesthetics *can* be highly accessible if designed with care; they can also be less accessible if monochrome palettes push contrast near the floor.
diff --git a/frontend-design/references/design-review.md b/frontend-design/references/design-review.md
new file mode 100644
index 0000000..656b488
--- /dev/null
+++ b/frontend-design/references/design-review.md
@@ -0,0 +1,93 @@
+# Design Review
+
+Self-audit before handoff. The goal isn't "did I follow the rules" — it's "does the build match the commitment, and are any AI-slop defaults hiding in here?" Assume defaults crept in somewhere; find them.
+
+## Archetype Check
+
+Pull up the commitment from Phase 2 (or the `design-rationale.md` if you emitted one). Answer honestly:
+
+- [ ] Does the build read as the chosen archetype to a stranger?
+- [ ] Are the font pairing, palette, motion philosophy, and layout approach the ones committed to, or did they drift?
+- [ ] Is the archetype recognizable on the first five seconds of viewing, or does it require explanation?
+
+A build that "sort of" hits the archetype usually hits none cleanly. Better to overshoot than hedge.
+
+## Anti-Pattern Grep
+
+These are specific defaults that sneak back in even after you committed to something else. Check for each:
+
+**Fonts:**
+- [ ] No Inter, Roboto, Arial, Helvetica (unless deliberately justified for this archetype)
+- [ ] No "system-ui" family unless the archetype is literally "system-native"
+- [ ] Display font is distinct from body font — if both are the same (e.g., all Inter), that's a miss
+- [ ] Variable fonts with too many weights load-heavy — pick 2-3 weights max
+
+**Palette:**
+- [ ] No purple-to-pink gradient on white
+- [ ] No "evenly-distributed" palette — 6 colors all at 50% saturation reading as "gray blah"
+- [ ] Dominant colors take more space than accents; accents have real contrast
+- [ ] No "generic teal" (#14b8a6 and its cousins) unless the archetype specifically earns it
+
+**Layout:**
+- [ ] Not a cards-in-a-grid with no hierarchy
+- [ ] Not centered-column-of-text-with-a-hero-image (the default blog post)
+- [ ] Not three-equal-feature-boxes (the default SaaS landing page)
+- [ ] There's at least one layout choice the reader will remember
+
+**Motion:**
+- [ ] Hover states exist and surprise (not just `opacity: 0.8`)
+- [ ] Page load has a considered reveal (staggered, or deliberately instant — not "jump in as DOM parses")
+- [ ] `prefers-reduced-motion` respected
+- [ ] No unrequested scroll-jacking or mandatory scroll animations
+
+**Background / Atmosphere:**
+- [ ] Not plain white or plain `#0a0a0a` background (unless that's the archetype's literal point)
+- [ ] Some depth: gradient mesh, noise, dramatic shadow, decorative border, ambient texture — something
+- [ ] Whatever's chosen, it feels *designed* not *applied* (random noise texture on anything = lazy)
+
+**Components:**
+- [ ] Buttons don't look like every shadcn button ever
+- [ ] Cards aren't the generic "rounded-lg shadow-md bg-white p-6" pattern
+- [ ] Form fields have considered states (hover, focus, error, disabled, loading)
+- [ ] Custom cursor, custom selection color, custom scrollbar where fitting for the archetype
+
+## Code Quality Match
+
+The aesthetic and the code have to agree. Red flags:
+
+- [ ] Ornate maximalist design + 40 lines of CSS = mismatch (ornate needs elaborate code)
+- [ ] Claimed "minimalism" + 2000 lines of utility classes + 5 dependencies = mismatch (minimal aesthetic needs restrained code)
+- [ ] No CSS variables in a multi-page design = palette will drift across components
+- [ ] Inline styles scattered in JSX = the system hasn't been thought through
+
+Elegance in the code is part of the deliverable, not an afterthought.
+
+## Accessibility Smoke Check
+
+Run through [accessibility.md](accessibility.md)'s smoke checklist at minimum. If the build will ship, run Lighthouse + axe as well; fix CRITICAL and SERIOUS findings before handoff.
+
+## Responsive Smoke Check
+
+Resize the viewport to `sm` (~640px) and `lg` (~1024px). Does the aesthetic translate, or does the layout collapse to the AI-default "one centered column of stacked elements"? Some archetypes *should* collapse to a single column on mobile — but that's a choice, not a fallback. Verify via [responsive.md](responsive.md)'s checklist.
+
+## Performance Sanity
+
+- [ ] No 5MB hero image
+- [ ] No autoplay video that isn't essential
+- [ ] Font loading isn't blocking render (use `font-display: swap` or similar)
+- [ ] Animations don't thrash layout (use `transform` and `opacity`, not `width` / `top` / `left`)
+- [ ] Third-party scripts loaded async / deferred
+
+If the aesthetic requires heavy assets (hero videos, WebGL, etc.), that's fine — but it's a documented trade-off, not an accident.
+
+## Convergence Check
+
+If you've used this skill recently, what did the last build look like? If the last three builds all picked "brutally minimal" or all used the same font pairing — convergence. Break the pattern deliberately on the next invocation. The aesthetic space is large; defaulting to the same corner repeatedly is a failure.
+
+## Final: The One-Sentence Test
+
+Can you write one sentence describing what's memorable about this build? Not "it's clean and modern" — that applies to everything and nothing. A real answer: "The asymmetric terminal-green monospace hero with the brutalist grid and tiny rotating pixel cursor." If the sentence is vague, the design didn't commit hard enough.
+
+## Handoff
+
+Emit a `design-rationale.md` via [rationale-template.md](rationale-template.md) so the next iteration has context. Commit the rationale alongside the code — future work starts with it loaded, not with the aesthetic forgotten.
diff --git a/frontend-design/references/rationale-template.md b/frontend-design/references/rationale-template.md
new file mode 100644
index 0000000..20dd1e1
--- /dev/null
+++ b/frontend-design/references/rationale-template.md
@@ -0,0 +1,133 @@
+# Rationale Template
+
+Drop the following into a `design-rationale.md` alongside the code at handoff. Brief, specific, honest. Future iterations of the interface start by reading this.
+
+---
+
+```markdown
+# Design Rationale — <component / page / project name>
+
+**Date:** YYYY-MM-DD
+**Author:** <name or "AI-assisted via /frontend-design">
+**Invoked from:** <initial user prompt or request summary, 1-2 lines>
+
+## 1. Purpose
+
+<One paragraph. What is this for, who uses it, what problem it solves.>
+
+## 2. Archetype
+
+**Chosen:** <brutally minimal / maximalist chaos / retro-futuristic / organic / luxury / playful / editorial / brutalist / art deco / soft / industrial / custom variant>
+
+**Why:** <One sentence tying archetype to purpose + audience.>
+
+**Trading away:** <What this direction sacrifices. "Maximalism trades subtlety and scannability for memorability" / "Minimalism trades information density for focus" / etc.>
+
+## 3. Locked decisions
+
+- **Font pairing:** <display font> for headings, <body font> for text. <One-line why.>
+- **Palette:** <primary colors> with <accent colors>. <Where dominants live, where accents appear.>
+- **Motion philosophy:** <In one line — staggered page-load / aggressive hover / no motion / whatever.>
+- **Layout approach:** <Asymmetric grid / classic 12-col / brutalist stack / magazine spread / whatever.>
+
+## 4. Deliberately absent
+
+<List what's NOT in the design even though someone might expect it. "No card drop shadows — monochrome blocks define structure instead." "No hero image — typography carries the emotional weight." Explicitly naming the absences prevents the next iteration from adding them back by default.>
+
+## 5. Accessibility notes
+
+- Contrast verified at <AA / AAA> against <palette elements>
+- Keyboard navigation: <summary of focus order and any custom controls>
+- `prefers-reduced-motion`: <handled / not applicable>
+- Known concerns: <anything below threshold, noted for follow-up>
+
+## 6. Responsive notes
+
+- Primary viewport: <desktop / mobile-first / specific breakpoint>
+- Translation approach: <how the aesthetic holds at smaller sizes>
+- Unsupported viewports (if any): <below X px, behavior is Y>
+
+## 7. Implementation notes
+
+- Framework: <React / Vue / plain HTML / etc.>
+- Dependencies added: <list; keep short>
+- Integration assumptions: <what the consuming codebase must provide>
+- Known tradeoffs: <perf vs aesthetic, dep weight, etc.>
+
+## 8. Open questions / follow-ups
+
+- [ ] <item>
+- [ ] <item>
+
+## 9. References
+
+- Brand guide: <link if used>
+- Moodboard: <link if used>
+- Similar designs consulted: <list>
+```
+
+---
+
+## Filled example (abbreviated)
+
+```markdown
+# Design Rationale — SOCOM demo landing
+
+**Date:** 2026-04-19
+**Author:** AI-assisted via /frontend-design
+**Invoked from:** "Build a landing page for the SOCOM demo; feels technical
+without being sterile."
+
+## 1. Purpose
+Public-facing landing for the SOCOM ATAC demo. Audience: procurement
+officers + technical evaluators. Must feel precise, credible, and
+operationally-serious without reading as generic defense-contractor-beige.
+
+## 2. Archetype
+**Chosen:** industrial/utilitarian with restrained editorial accents.
+**Why:** Audience is operational; aesthetic distinctiveness comes from
+precision, not decoration.
+**Trading away:** Decorative delight; warmth. In exchange, seriousness and
+signal density.
+
+## 3. Locked decisions
+- **Font pairing:** IBM Plex Mono for headings; IBM Plex Sans for body.
+ (Mono carries the operational signal; sans keeps body readable.)
+- **Palette:** Near-black (#0a0e0f) dominant, cool slate (#3a4851) secondary,
+ single desaturated amber accent (#c88c3a) used only for ATAC callouts.
+- **Motion philosophy:** No motion on page load; hover states are snap-fast
+ (80ms). Stillness = precision.
+- **Layout approach:** Grid visible as 1px cool-slate rules; content sits
+ inside named cells. Hero aligns to a single numbered row, not centered.
+
+## 4. Deliberately absent
+- No hero video, no animated gradient
+- No card shadows; cells share the grid rules instead
+- No purple, no consumer-fintech palette cues
+- No "book a demo" urgency; CTA is "Contact procurement"
+
+## 5. Accessibility notes
+- AA verified on all text/button states
+- Focus rings: 2px amber outline + offset, `:focus-visible` only
+- `prefers-reduced-motion`: applies; hover transitions drop to 0ms
+
+## 6. Responsive notes
+- Primary: desktop 1440px
+- Mobile: single column, grid rules preserved; named cells stack vertically
+ in document order
+- Below 360px: layout is acceptable but not designed for
+
+## 7. Implementation notes
+- Framework: Next.js 14 (App Router) + Tailwind + IBM Plex (self-hosted)
+- No additional deps
+- Uses existing design tokens from ./lib/tokens.ts
+- Integration: expects `@/components/grid` and `@/components/cell` primitives
+
+## 8. Open questions
+- [ ] Is the amber accent readable in direct sunlight on outdoor demos?
+- [ ] Legal has approved the "ATAC" wordmark treatment
+
+## 9. References
+- Brand guide: internal/DeepSat-brand-2026-03.pdf
+- Moodboard: Monokuma.com, Field Notes, NASA technical manuals
+```
diff --git a/frontend-design/references/responsive.md b/frontend-design/references/responsive.md
new file mode 100644
index 0000000..18be11f
--- /dev/null
+++ b/frontend-design/references/responsive.md
@@ -0,0 +1,90 @@
+# Responsive
+
+Mobile is the dominant traffic profile for consumer web; desktop dominates operational and enterprise contexts. Commit to a primary viewport early — retrofitting responsive behavior into a desktop-only design is more expensive than building with breakpoints from the start.
+
+## Decision: Mobile-First or Desktop-First
+
+**Mobile-first** (build the small-screen layout first, scale up):
+- Consumer web, marketing, e-commerce, public-facing apps
+- Progressive enhancement ethos — base experience works everywhere, more features at larger sizes
+- CSS reads as `/* default (mobile) */` → `@media (min-width: X)` overrides
+- Simpler to keep working on constrained devices
+
+**Desktop-first** (design for a big screen, gracefully degrade):
+- Operational dashboards, ISR displays, pro tools, internal enterprise apps
+- Information density is the point; mobile is a fallback or unsupported
+- CSS reads as `/* default (desktop) */` → `@media (max-width: X)` overrides
+- Harder to keep working when the small screen is an afterthought
+
+Pick one deliberately. Hybrids (different viewport designs for "phone / tablet / desktop" with no progression ethos) usually produce three mediocre layouts rather than one good one.
+
+## Breakpoints
+
+Use **named, consistent** breakpoints — not magic numbers scattered across files. A design-system variable keeps them coherent.
+
+**Typical set** (Tailwind's values are reasonable defaults):
+
+| Name | Width | Use |
+|---|---|---|
+| sm | 640px | Large phones, phablets |
+| md | 768px | Tablets, small laptops |
+| lg | 1024px | Laptops |
+| xl | 1280px | Desktops |
+| 2xl | 1536px | Large desktops, wide monitors |
+
+**Don't** introduce a breakpoint at an arbitrary exact pixel. If content reflows badly at 820px, push `md` up to 840px or decide the design needs an actual rearrangement at that size — not a pixel workaround.
+
+**Container queries** (`@container`) are now broadly supported and are often a better answer than viewport breakpoints for components that live in varied contexts. A card that's 300px wide in a sidebar and 900px wide on a detail page should branch on *its* size, not the viewport's.
+
+## Aesthetic Translation by Archetype
+
+Archetypes don't all respond to screen size the same way. Match the translation strategy to the direction chosen:
+
+| Archetype | Small-screen translation |
+|---|---|
+| Maximalist chaos | Simplify, don't dilute. Fewer layered effects; preserve the rule-breaking layout feel. |
+| Brutally minimal | Scales naturally. Ensure spacing scales with viewport — "generous" at 1920px ≠ "generous" at 375px. |
+| Retro-futuristic | Stacked vertical scroll with preserved detail. Don't lose the motif elements (grids, glows, terminal text) even if resized. |
+| Organic / natural | Reflow gracefully; the aesthetic comes from shape and color, not grid. Near-free on mobile. |
+| Luxury / refined | Preserve whitespace proportions. The whitespace *is* the design. Don't cram. |
+| Playful / toy-like | Often translates well; the whimsy is in shapes/colors/animations, not layout. |
+| Editorial / magazine | Hardest. Magazine spreads assume two-page layouts. Single column on mobile, but preserve type hierarchy and whitespace choreography. |
+| Brutalist / raw | Scales naturally. Monospace and visible-grid aesthetics don't fight small screens. |
+| Art deco / geometric | Retain the geometric motifs as accents; simplify complex patterns. |
+| Soft / pastel | Reflow easily. Watch contrast on smaller screens where brightness shifts. |
+| Industrial / utilitarian | Operational dashboards often unsupported on mobile — that's a legitimate product decision. If mobile is required, prioritize scanning over interaction. |
+
+## Responsive Typography
+
+- Use `clamp(min, preferred, max)` for fluid type that never breaks the layout:
+ ```css
+ h1 { font-size: clamp(2rem, 5vw + 1rem, 4rem); }
+ ```
+- Line length: aim for 45-75 characters per line at the primary viewport. On mobile, 30-40 is fine for body text.
+- Line height scales inversely — tighter on headlines, looser on body, typically `1.2` → `1.6`.
+
+## Images and Media
+
+- `max-width: 100%` is the baseline; `object-fit: cover` for images that need to fill a container at different aspect ratios
+- Use `<picture>` for art direction (different crops per viewport), not just different sizes
+- `srcset` for resolution switching; browsers handle the choice automatically
+- Hero backgrounds at 4K don't belong on mobile — deliver appropriately sized assets
+
+## Operational Dashboard Note
+
+For DeepSat-style ISR / operational work: the primary viewport is almost always a large desktop monitor. Mobile is unsupported. Don't pretend otherwise. If mobile is a declared requirement:
+
+- Prioritize *read-only* scanning over interactive manipulation
+- Key metrics first, secondary details collapsed behind interactions
+- Assume poor bandwidth + intermittent connectivity — data-sparing matters
+- Don't split the canonical desktop layout 1:4 onto mobile tiles — design a separate layout with the same information priorities
+
+## Smoke Checklist
+
+- [ ] Primary viewport decided and documented in the rationale
+- [ ] Named breakpoints — no magic pixel values in CSS
+- [ ] Works at `sm`, `md`, `lg`, `xl` tests (at minimum)
+- [ ] Typography scales fluidly or has tuned ramps per breakpoint
+- [ ] Images use appropriate sizes per viewport
+- [ ] At 200% browser zoom, layout still holds
+- [ ] No horizontal scroll (unintentional) on any common viewport
diff --git a/frontend-design/references/workflow.md b/frontend-design/references/workflow.md
new file mode 100644
index 0000000..bd0f3a5
--- /dev/null
+++ b/frontend-design/references/workflow.md
@@ -0,0 +1,86 @@
+# Workflow
+
+Four phases for non-trivial frontend work. Cheap to skip individual phases when context warrants, but don't short-circuit the chain by default.
+
+## Phase 1 — Intake
+
+Before coding, understand what's being built and for whom. Ask these, one at a time, multiple-choice where possible. Don't batch.
+
+**Purpose**
+- What is this interface for? (landing page / dashboard / component / marketing site / internal tool / client demo / design exploration / other)
+- What problem does it solve? One sentence.
+
+**Audience**
+- Who uses this? (general public / executives / technical users / operators / customers / internal team)
+- What's their expected device / context? (desk on a big screen / mobile on the move / constrained environment)
+
+**Operational context**
+- Consumer-facing or operational? (consumer → aesthetic distinctiveness helps; operational → readability + scannability matter more)
+- Is there a design system to respect, or is this greenfield?
+- Any brand guidelines or existing visual language to match / deliberately depart from?
+
+**Functional priority**
+- Density vs scannability vs delight — which wins when they conflict?
+- Read-only, interactive, or input-heavy?
+
+**Technical constraints**
+- Framework / stack (React / Next / Vue / Svelte / vanilla HTML+CSS / static site / other)
+- Existing design system (Tailwind / shadcn / custom / none)
+- Performance budget (if any)
+- Accessibility target (WCAG AA is default; AAA for some contexts)
+- Browser support (modern-only OK, or need IE11-style fallbacks?)
+
+**References**
+- Any moodboard links, screenshots, sites you like / dislike?
+- Brand color palette, logos, fonts already in use?
+
+**Success criteria**
+- What does "good" look like for this? One-sentence test ("looks professional but not corporate" / "feels like a game" / "hides complexity behind calm surfaces" / etc.)
+- How will we know when to stop iterating?
+
+Stop asking when you can state the goal back in one sentence and the user confirms.
+
+## Phase 2 — Commitment
+
+Before writing code, lock the aesthetic direction explicitly. State all of these out loud (in output) so the user can push back before time is spent:
+
+- **Archetype chosen.** One of: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, or a named variant.
+- **Why this archetype fits** the purpose and audience from Phase 1.
+- **What's being traded away.** (Maximalism trades subtlety; minimalism trades information density; playful trades gravitas; etc.)
+- **Font pairing**, one line. Display + body, both named. Not Inter, Roboto, Arial, or system defaults unless specifically justified.
+- **Palette**, one line. 2-3 dominant colors + 1-2 sharp accents. Not "purple gradient on white."
+- **Motion philosophy**, one line. ("Staggered page-load reveal, subtle hover states, no scroll-jacking" or "no motion — stillness and typography do the work" or "aggressive hover interactions — this is supposed to feel alive.")
+- **Layout approach**, one line. (Asymmetric grid / classic 12-col / brutalist stack / magazine spreads / whatever fits the archetype.)
+
+**If the user pushes back**, revise before building. Cheaper to pivot now than after implementation.
+
+## Phase 3 — Build
+
+With the commitment locked, implement. The aesthetic guidance in `../SKILL.md` is the main reference for taste decisions.
+
+**Layout-significant work?** Load [responsive.md](responsive.md) and plan the breakpoint strategy *before* committing to a primary viewport layout.
+
+**Interactive components (forms, dialogs, menus, complex controls)?** Load [accessibility.md](accessibility.md) and apply the discipline during build, not as a retrofit.
+
+**Match implementation complexity to aesthetic vision.** Maximalism needs elaborate code (layered animations, custom cursors, grain overlays, scroll effects). Minimalism needs precision (impeccable spacing, considered typography scale, restraint in color). Don't build the wrong kind of effort.
+
+## Phase 4 — Review
+
+Before handoff, self-audit. Load [design-review.md](design-review.md) and walk the checklist:
+
+- Did the build hit the chosen archetype?
+- Any AI-slop defaults slip back in? (Inter, purple-on-white, predictable card layouts, etc.)
+- Accessibility smoke check (contrast, keyboard, focus, reduced-motion)
+- Responsive smoke check (does the aesthetic translate to mobile?)
+- Does the code quality match the aesthetic? (Lazy code under ornate design is a failure.)
+
+Emit a `design-rationale.md` using [rationale-template.md](rationale-template.md) so the next iteration or the next engineer has context for the choices made.
+
+## When to skip phases
+
+- **One-line style tweak** ("change the heading color to match the brand"): skip phases 1, 2, 4. Just apply the change.
+- **Refactoring existing code without design changes**: not this skill — use the general refactor skill.
+- **Bug fix in existing design**: skip phase 1 (context is already there) and phase 2 (don't pivot the archetype for a bug fix). Build and review.
+- **Complete rebuild / new design**: don't skip any phase.
+
+The discipline is there to prevent bad decisions at speed. Skipping for genuinely trivial work is fine; skipping because "it's faster" on non-trivial work is how AI slop wins.