@stylecrib/cli 0.0.0-stage → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +163 -2
- package/agents/MANIFEST.yml +136 -0
- package/agents/README.md +75 -0
- package/agents/art-director.md +168 -0
- package/agents/audacity-director.md +109 -0
- package/agents/brand-identity.md +179 -0
- package/agents/brand-precedent.md +119 -0
- package/agents/brief-enforcer.md +136 -0
- package/agents/component-qa.md +167 -0
- package/agents/cto.md +49 -0
- package/agents/design-director.md +184 -0
- package/agents/design-systems-engineer.md +162 -0
- package/agents/direction-curator.md +133 -0
- package/agents/homogeneity-detector.md +104 -0
- package/agents/logo-designer.md +240 -0
- package/agents/marketing-designer.md +156 -0
- package/agents/media-curator.md +165 -0
- package/agents/motion-engineer.md +270 -0
- package/agents/qa-conductor.md +143 -0
- package/agents/render-qa.md +133 -0
- package/agents/upgrade-simulator.md +123 -0
- package/agents/vp-architecture.md +49 -0
- package/agents/vp-engineering.md +49 -0
- package/dist/index.js +7182 -0
- package/package.json +69 -4
- package/themes/README.md +70 -0
- package/themes/acrylic-soft/THEME.md +142 -0
- package/themes/acrylic-soft/tokens.ts +180 -0
- package/themes/agency-creative/THEME.md +91 -0
- package/themes/agency-creative/tokens.ts +202 -0
- package/themes/agency-portfolio/THEME.md +109 -0
- package/themes/agency-portfolio/tokens.ts +159 -0
- package/themes/ai-startup/THEME.md +95 -0
- package/themes/ai-startup/tokens.ts +162 -0
- package/themes/airline-modern/THEME.md +104 -0
- package/themes/airline-modern/tokens.ts +179 -0
- package/themes/arc-stack/.anchor-render.png +0 -0
- package/themes/arc-stack/THEME.md +125 -0
- package/themes/arc-stack/audit.log.jsonl +6 -0
- package/themes/arc-stack/dismissals.jsonl +3 -0
- package/themes/arc-stack/tailwind.snippet.ts +17 -0
- package/themes/arc-stack/theme.yml +153 -0
- package/themes/arc-stack/tokens.ts +29 -0
- package/themes/architectural/THEME.md +102 -0
- package/themes/architectural/tokens.ts +159 -0
- package/themes/atelier-radiance/THEME.md +93 -0
- package/themes/atelier-radiance/audit.log.jsonl +1 -0
- package/themes/atelier-radiance/tailwind.snippet.ts +15 -0
- package/themes/atelier-radiance/theme.yml +130 -0
- package/themes/atelier-radiance/tokens.ts +29 -0
- package/themes/automotive-ev/THEME.md +87 -0
- package/themes/automotive-ev/tokens.ts +183 -0
- package/themes/automotive-luxury/THEME.md +88 -0
- package/themes/automotive-luxury/tokens.ts +175 -0
- package/themes/baby-modern/THEME.md +79 -0
- package/themes/baby-modern/tokens.ts +184 -0
- package/themes/banking-gravity/THEME.md +171 -0
- package/themes/banking-gravity/tokens.ts +169 -0
- package/themes/beauty-clean/THEME.md +92 -0
- package/themes/beauty-clean/tokens.ts +176 -0
- package/themes/beauty-luxury/THEME.md +96 -0
- package/themes/beauty-luxury/tokens.ts +178 -0
- package/themes/bento-modular/.anchor-render.png +0 -0
- package/themes/bento-modular/BUILD_BRIEF.md +171 -0
- package/themes/bento-modular/THEME.md +80 -0
- package/themes/bento-modular/audit.log.jsonl +3 -0
- package/themes/bento-modular/dismissals.jsonl +1 -0
- package/themes/bento-modular/tailwind.snippet.ts +17 -0
- package/themes/bento-modular/theme.yml +83 -0
- package/themes/bento-modular/tokens.ts +27 -0
- package/themes/bookstore-indie/THEME.md +78 -0
- package/themes/bookstore-indie/tokens.ts +147 -0
- package/themes/brutalist/THEME.md +96 -0
- package/themes/brutalist/tokens.ts +151 -0
- package/themes/business-tiles/THEME.md +141 -0
- package/themes/business-tiles/tokens.ts +178 -0
- package/themes/cabana-poster/THEME.md +158 -0
- package/themes/cabana-poster/audit.log.jsonl +1 -0
- package/themes/cabana-poster/tailwind.snippet.ts +16 -0
- package/themes/cabana-poster/theme.yml +221 -0
- package/themes/cabana-poster/tokens.ts +34 -0
- package/themes/case-panel/THEME.md +126 -0
- package/themes/case-panel/audit.log.jsonl +2 -0
- package/themes/case-panel/tailwind.snippet.ts +15 -0
- package/themes/case-panel/theme.yml +153 -0
- package/themes/case-panel/tokens.ts +28 -0
- package/themes/cinematic-dark/THEME.md +97 -0
- package/themes/cinematic-dark/tokens.ts +195 -0
- package/themes/classic-car/THEME.md +86 -0
- package/themes/classic-car/tokens.ts +173 -0
- package/themes/cloud-friendly/THEME.md +152 -0
- package/themes/cloud-friendly/tokens.ts +181 -0
- package/themes/community-niche/THEME.md +102 -0
- package/themes/community-niche/tokens.ts +177 -0
- package/themes/corporate-grid/THEME.md +154 -0
- package/themes/corporate-grid/tokens.ts +182 -0
- package/themes/couture-luxury/THEME.md +85 -0
- package/themes/couture-luxury/tokens.ts +146 -0
- package/themes/creator-social/THEME.md +131 -0
- package/themes/creator-social/tokens.ts +249 -0
- package/themes/crypto-onchain/THEME.md +100 -0
- package/themes/crypto-onchain/tokens.ts +207 -0
- package/themes/cycling-brand/THEME.md +78 -0
- package/themes/cycling-brand/tokens.ts +185 -0
- package/themes/dating-friendly/THEME.md +102 -0
- package/themes/dating-friendly/tokens.ts +178 -0
- package/themes/dense-utility/THEME.md +85 -0
- package/themes/dense-utility/tokens.ts +155 -0
- package/themes/devtool-cli/THEME.md +100 -0
- package/themes/devtool-cli/tokens.ts +195 -0
- package/themes/devtool-docs/THEME.md +105 -0
- package/themes/devtool-docs/tokens.ts +177 -0
- package/themes/editorial/THEME.md +129 -0
- package/themes/editorial/audit.log.jsonl +2 -0
- package/themes/editorial/tailwind.snippet.ts +15 -0
- package/themes/editorial/theme.yml +173 -0
- package/themes/editorial/tokens.ts +29 -0
- package/themes/education-formal/THEME.md +154 -0
- package/themes/education-formal/audit.log.jsonl +1 -0
- package/themes/education-formal/tailwind.snippet.ts +15 -0
- package/themes/education-formal/theme.yml +186 -0
- package/themes/education-formal/tokens.ts +29 -0
- package/themes/education-warm/THEME.md +91 -0
- package/themes/education-warm/tokens.ts +185 -0
- package/themes/ember-poster/README.md +79 -0
- package/themes/ember-poster/THEME.md +101 -0
- package/themes/ember-poster/audit.log.jsonl +17 -0
- package/themes/ember-poster/package.json +34 -0
- package/themes/ember-poster/tailwind.snippet.ts +17 -0
- package/themes/ember-poster/theme.yml +109 -0
- package/themes/ember-poster/tokens.ts +27 -0
- package/themes/enterprise-cloud/THEME.md +139 -0
- package/themes/enterprise-cloud/tokens.ts +179 -0
- package/themes/enterprise-tech/.anchor-render.png +0 -0
- package/themes/enterprise-tech/THEME.md +167 -0
- package/themes/enterprise-tech/audit.log.jsonl +1 -0
- package/themes/enterprise-tech/tailwind.snippet.ts +15 -0
- package/themes/enterprise-tech/theme.yml +202 -0
- package/themes/enterprise-tech/tokens.ts +29 -0
- package/themes/ev-charging/THEME.md +94 -0
- package/themes/ev-charging/tokens.ts +185 -0
- package/themes/farm-direct/THEME.md +92 -0
- package/themes/farm-direct/tokens.ts +180 -0
- package/themes/fintech-card/THEME.md +96 -0
- package/themes/fintech-card/tokens.ts +191 -0
- package/themes/fintech-trust/THEME.md +94 -0
- package/themes/fintech-trust/tokens.ts +192 -0
- package/themes/food-blog/THEME.md +98 -0
- package/themes/food-blog/tokens.ts +183 -0
- package/themes/forum-classic/THEME.md +100 -0
- package/themes/forum-classic/tokens.ts +168 -0
- package/themes/fresh-plate/.anchor-render.png +0 -0
- package/themes/fresh-plate/THEME.md +144 -0
- package/themes/fresh-plate/audit.log.jsonl +2 -0
- package/themes/fresh-plate/dismissals.jsonl +3 -0
- package/themes/fresh-plate/tailwind.snippet.ts +16 -0
- package/themes/fresh-plate/theme.yml +189 -0
- package/themes/fresh-plate/tokens.ts +30 -0
- package/themes/furniture-modern/THEME.md +94 -0
- package/themes/furniture-modern/tokens.ts +176 -0
- package/themes/gaming-esports/THEME.md +146 -0
- package/themes/gaming-esports/tokens.ts +199 -0
- package/themes/gaming-streamer/THEME.md +139 -0
- package/themes/gaming-streamer/tokens.ts +201 -0
- package/themes/glassmorphic-modern/THEME.md +119 -0
- package/themes/glassmorphic-modern/tokens.ts +174 -0
- package/themes/government-civic/THEME.md +138 -0
- package/themes/government-civic/tokens.ts +164 -0
- package/themes/gym-chain/THEME.md +79 -0
- package/themes/gym-chain/tokens.ts +196 -0
- package/themes/healthcare-bright/THEME.md +95 -0
- package/themes/healthcare-bright/tokens.ts +184 -0
- package/themes/home-decor/THEME.md +94 -0
- package/themes/home-decor/tokens.ts +177 -0
- package/themes/hotel-boutique/THEME.md +110 -0
- package/themes/hotel-boutique/tokens.ts +179 -0
- package/themes/hyperminimal-mono/THEME.md +91 -0
- package/themes/hyperminimal-mono/tokens.ts +150 -0
- package/themes/indie-art-game/THEME.md +107 -0
- package/themes/indie-art-game/tokens.ts +216 -0
- package/themes/insurance-legacy/THEME.md +101 -0
- package/themes/insurance-legacy/tokens.ts +182 -0
- package/themes/insurance-modern/THEME.md +103 -0
- package/themes/insurance-modern/tokens.ts +192 -0
- package/themes/kaiju-reveal/THEME.md +97 -0
- package/themes/kaiju-reveal/tokens.ts +185 -0
- package/themes/kinetic-data/THEME.md +172 -0
- package/themes/kinetic-data/audit.log.jsonl +1 -0
- package/themes/kinetic-data/tailwind.snippet.ts +16 -0
- package/themes/kinetic-data/theme.yml +207 -0
- package/themes/kinetic-data/tokens.ts +30 -0
- package/themes/kinetic-headline/.anchor-render.png +0 -0
- package/themes/kinetic-headline/BUILD_BRIEF.md +156 -0
- package/themes/kinetic-headline/THEME.md +78 -0
- package/themes/kinetic-headline/audit.log.jsonl +4 -0
- package/themes/kinetic-headline/dismissals.jsonl +1 -0
- package/themes/kinetic-headline/tailwind.snippet.ts +16 -0
- package/themes/kinetic-headline/theme.yml +81 -0
- package/themes/kinetic-headline/tokens.ts +26 -0
- package/themes/law-firm/THEME.md +108 -0
- package/themes/law-firm/tokens.ts +158 -0
- package/themes/lawtech-modern/THEME.md +107 -0
- package/themes/lawtech-modern/tokens.ts +192 -0
- package/themes/linkedin-pro/THEME.md +102 -0
- package/themes/linkedin-pro/tokens.ts +174 -0
- package/themes/logistics-modern/THEME.md +94 -0
- package/themes/logistics-modern/tokens.ts +187 -0
- package/themes/magazine-glossy/THEME.md +74 -0
- package/themes/magazine-glossy/tokens.ts +158 -0
- package/themes/marker-mag/THEME.md +128 -0
- package/themes/marker-mag/audit.log.jsonl +1 -0
- package/themes/marker-mag/tailwind.snippet.ts +15 -0
- package/themes/marker-mag/theme.yml +159 -0
- package/themes/marker-mag/tokens.ts +27 -0
- package/themes/marketplace-modern/THEME.md +135 -0
- package/themes/marketplace-modern/tokens.ts +186 -0
- package/themes/marketplace-vintage/THEME.md +110 -0
- package/themes/marketplace-vintage/tokens.ts +185 -0
- package/themes/maximalist/THEME.md +96 -0
- package/themes/maximalist/tokens.ts +168 -0
- package/themes/mid-century/THEME.md +109 -0
- package/themes/mid-century/tokens.ts +162 -0
- package/themes/motorcycle-brand/THEME.md +86 -0
- package/themes/motorcycle-brand/tokens.ts +174 -0
- package/themes/museum/THEME.md +83 -0
- package/themes/museum/tokens.ts +147 -0
- package/themes/music-streaming/THEME.md +101 -0
- package/themes/music-streaming/tokens.ts +187 -0
- package/themes/music-vinyl/THEME.md +98 -0
- package/themes/music-vinyl/tokens.ts +167 -0
- package/themes/nature-distilled/.anchor-render.png +0 -0
- package/themes/nature-distilled/BUILD_BRIEF.md +158 -0
- package/themes/nature-distilled/THEME.md +81 -0
- package/themes/nature-distilled/audit.log.jsonl +2 -0
- package/themes/nature-distilled/tailwind.snippet.ts +16 -0
- package/themes/nature-distilled/theme.yml +91 -0
- package/themes/nature-distilled/tokens.ts +26 -0
- package/themes/news-tabloid/THEME.md +72 -0
- package/themes/news-tabloid/tokens.ts +158 -0
- package/themes/news-tech/THEME.md +75 -0
- package/themes/news-tech/tokens.ts +149 -0
- package/themes/newsletter/THEME.md +82 -0
- package/themes/newsletter/tokens.ts +138 -0
- package/themes/newspaper-classic/THEME.md +74 -0
- package/themes/newspaper-classic/tokens.ts +159 -0
- package/themes/nonprofit-arts/THEME.md +78 -0
- package/themes/nonprofit-arts/tokens.ts +157 -0
- package/themes/nonprofit-warm/THEME.md +105 -0
- package/themes/nonprofit-warm/tokens.ts +188 -0
- package/themes/outdoor-adventure/THEME.md +113 -0
- package/themes/outdoor-adventure/tokens.ts +181 -0
- package/themes/overland-broadside/THEME.md +119 -0
- package/themes/overland-broadside/audit.log.jsonl +1 -0
- package/themes/overland-broadside/tailwind.snippet.ts +17 -0
- package/themes/overland-broadside/theme.yml +138 -0
- package/themes/overland-broadside/tokens.ts +27 -0
- package/themes/performance-engineered/THEME.md +162 -0
- package/themes/performance-engineered/audit.log.jsonl +1 -0
- package/themes/performance-engineered/tailwind.snippet.ts +15 -0
- package/themes/performance-engineered/theme.yml +193 -0
- package/themes/performance-engineered/tokens.ts +29 -0
- package/themes/pet-food/THEME.md +78 -0
- package/themes/pet-food/tokens.ts +185 -0
- package/themes/pharma-clinical/THEME.md +164 -0
- package/themes/pharma-clinical/audit.log.jsonl +1 -0
- package/themes/pharma-clinical/tailwind.snippet.ts +15 -0
- package/themes/pharma-clinical/theme.yml +201 -0
- package/themes/pharma-clinical/tokens.ts +29 -0
- package/themes/pill-editorial/THEME.md +125 -0
- package/themes/pill-editorial/audit.log.jsonl +1 -0
- package/themes/pill-editorial/tailwind.snippet.ts +15 -0
- package/themes/pill-editorial/theme.yml +168 -0
- package/themes/pill-editorial/tokens.ts +31 -0
- package/themes/podcast-warm/THEME.md +103 -0
- package/themes/podcast-warm/tokens.ts +192 -0
- package/themes/publisher-indie/THEME.md +78 -0
- package/themes/publisher-indie/tokens.ts +148 -0
- package/themes/raw-concrete/BUILD_BRIEF.md +157 -0
- package/themes/raw-concrete/THEME.md +76 -0
- package/themes/raw-concrete/audit.log.jsonl +10 -0
- package/themes/raw-concrete/tailwind.snippet.ts +16 -0
- package/themes/raw-concrete/theme.yml +88 -0
- package/themes/raw-concrete/tokens.ts +27 -0
- package/themes/realestate-luxury/THEME.md +94 -0
- package/themes/realestate-luxury/tokens.ts +169 -0
- package/themes/realestate-marketplace/THEME.md +106 -0
- package/themes/realestate-marketplace/tokens.ts +183 -0
- package/themes/restaurant-modern/THEME.md +109 -0
- package/themes/restaurant-modern/tokens.ts +172 -0
- package/themes/runway-fashion/THEME.md +99 -0
- package/themes/runway-fashion/tokens.ts +167 -0
- package/themes/saturday-morning/THEME.md +117 -0
- package/themes/saturday-morning/tokens.ts +281 -0
- package/themes/schema.ts +235 -0
- package/themes/signal-dark/BUILD_BRIEF.md +168 -0
- package/themes/signal-dark/THEME.md +107 -0
- package/themes/signal-dark/tokens.ts +181 -0
- package/themes/soft-modern/THEME.md +91 -0
- package/themes/soft-modern/tokens.ts +166 -0
- package/themes/solar-residential/THEME.md +92 -0
- package/themes/solar-residential/tokens.ts +176 -0
- package/themes/sports-league/THEME.md +180 -0
- package/themes/sports-league/audit.log.jsonl +1 -0
- package/themes/sports-league/tailwind.snippet.ts +15 -0
- package/themes/sports-league/theme.yml +213 -0
- package/themes/sports-league/tokens.ts +32 -0
- package/themes/stadium-sport/THEME.md +114 -0
- package/themes/stadium-sport/tokens.ts +187 -0
- package/themes/streetwear-hype/THEME.md +100 -0
- package/themes/streetwear-hype/tokens.ts +174 -0
- package/themes/studio-architect/THEME.md +108 -0
- package/themes/studio-architect/tokens.ts +162 -0
- package/themes/studio-photographer/THEME.md +88 -0
- package/themes/studio-photographer/tokens.ts +164 -0
- package/themes/team-kanban/.anchor-render.png +0 -0
- package/themes/team-kanban/THEME.md +167 -0
- package/themes/team-kanban/audit.log.jsonl +2 -0
- package/themes/team-kanban/dismissals.jsonl +1 -0
- package/themes/team-kanban/tailwind.snippet.ts +15 -0
- package/themes/team-kanban/theme.yml +209 -0
- package/themes/team-kanban/tokens.ts +35 -0
- package/themes/telehealth-modern/THEME.md +95 -0
- package/themes/telehealth-modern/tokens.ts +197 -0
- package/themes/tourism-board/THEME.md +111 -0
- package/themes/tourism-board/tokens.ts +173 -0
- package/themes/toys-modern/THEME.md +79 -0
- package/themes/toys-modern/tokens.ts +200 -0
- package/themes/travel-luxury/THEME.md +95 -0
- package/themes/travel-luxury/tokens.ts +162 -0
- package/themes/vacation-rental/THEME.md +105 -0
- package/themes/vacation-rental/tokens.ts +174 -0
- package/themes/vault-reel/THEME.md +134 -0
- package/themes/vault-reel/audit.log.jsonl +3 -0
- package/themes/vault-reel/tailwind.snippet.ts +16 -0
- package/themes/vault-reel/theme.yml +167 -0
- package/themes/vault-reel/tokens.ts +30 -0
- package/themes/vet-modern/THEME.md +79 -0
- package/themes/vet-modern/tokens.ts +194 -0
- package/themes/web3-restraint/THEME.md +87 -0
- package/themes/web3-restraint/tokens.ts +154 -0
- package/themes/wellness-active/THEME.md +102 -0
- package/themes/wellness-active/tokens.ts +203 -0
- package/themes/wellness-spa/THEME.md +93 -0
- package/themes/wellness-spa/tokens.ts +173 -0
- package/themes/y2k-chrome/THEME.md +118 -0
- package/themes/y2k-chrome/tokens.ts +249 -0
- package/themes/yoga-studio/THEME.md +76 -0
- package/themes/yoga-studio/tokens.ts +163 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Design Direction — Government-Civic
|
|
2
|
+
|
|
3
|
+
## Ethos
|
|
4
|
+
US Web Design System (USWDS) · 21st Century IDEA Act accessibility · USDS public-service restraint · 18F democratic clarity · .gov heritage
|
|
5
|
+
|
|
6
|
+
## Feel
|
|
7
|
+
Public-service formal. White or deep-navy backgrounds, federal-blue with USWDS-red secondary, Public Sans typography. Strict accessibility (WCAG AAA target where possible; AA minimum), high information density, no decoration. Reads as "a citizen must be able to use this regardless of device, bandwidth, vision, or English literacy."
|
|
8
|
+
|
|
9
|
+
## Reference brands
|
|
10
|
+
- **USWDS (US Web Design System)** → the federal government's design system. This direction IS USWDS — not "inspired by." Token names, ratios, and patterns trace to it directly.
|
|
11
|
+
- **USDS (US Digital Service)** → public-service restraint. The work is for the citizen, not the agency.
|
|
12
|
+
- **18F (GSA)** → democratic clarity. Plain language, sixth-grade reading level, no insider jargon.
|
|
13
|
+
- **login.gov** → accessibility-first authentication. AA contrast minimum, AAA target.
|
|
14
|
+
- **va.gov** → the VA's digital modernization. Service forms that work for older, lower-bandwidth, lower-literacy users.
|
|
15
|
+
- **irs.gov (post-2021 redesign)** → tax forms rendered as digital services without losing legal precision.
|
|
16
|
+
- **Code for America** → civic-tech ergonomics; the human side of services.
|
|
17
|
+
- **GOV.UK** → international cousin. Different style guide, same religion (service-pattern discipline, plain language, accessibility).
|
|
18
|
+
|
|
19
|
+
## Brand-book customization
|
|
20
|
+
USWDS is **the** brand book for federal sites. Agencies layer their identity (Treasury seal, DOJ seal, agency wordmark) **on top of** USWDS, but cannot override the underlying token system without losing USWDS compliance and the Section 508 / IDEA Act safety net that comes with it.
|
|
21
|
+
|
|
22
|
+
**Allowed customization:**
|
|
23
|
+
- `--primary` may shift to an agency brand color when an agency uses a non-USWDS-blue corporate color (DOD navy `220 40% 18%`, Coast Guard cobalt `212 95% 38%`, USPS blue `217 78% 30%`). The replacement still needs to clear **4.5:1 against white** and **3:1 against `--ring` (gold-vivid)** — verify before swapping.
|
|
24
|
+
- Agency logo + wordmark in the header. Always paired with the "An official website of the United States government" banner ribbon at the top — that ribbon is non-removable on federal `.gov` sites.
|
|
25
|
+
- A single agency-seal favicon and one accent surface (e.g., a hero band tinted with the agency color at 8% opacity).
|
|
26
|
+
|
|
27
|
+
**NOT allowed (compliance-breaking):**
|
|
28
|
+
- Changing the accessibility contrast ratios. WCAG AA is the floor; AAA is the target.
|
|
29
|
+
- Removing or restyling focus rings. The 4px gold-vivid ring stays.
|
|
30
|
+
- Reducing line-height below 1.5 or body font-size below 17px (the IDEA Act readability floor).
|
|
31
|
+
- Removing the language-toggle in the header. Federal sites serving the public must offer translation (Spanish minimum; many add Chinese, Vietnamese, Tagalog, Korean, Arabic).
|
|
32
|
+
- Adding decorative shadows, gradients, glassmorphism, or animation that violates `prefers-reduced-motion`.
|
|
33
|
+
|
|
34
|
+
**State + local government variants:** USWDS is the **federal** standard, but states and cities frequently inherit it and override `--primary` with their state seal color (California navy `220 60% 22%`, Texas state-flag blue `218 100% 32%`, NYC blue `217 87% 35%`). The override pattern is the same as agency-level: swap `--primary`, leave every other token alone, re-verify the contrast matrix. Some states (e.g., Massachusetts `mass.gov`, Georgia `georgia.gov`) ship lightly-forked USWDS variants — treat those as `government-civic` with a `--primary` override, not as separate directions.
|
|
35
|
+
|
|
36
|
+
## Tokens
|
|
37
|
+
All tokens live in `src/index.css` as HSL triples. Every token's `from:` comment names its USWDS provenance (`base-darkest`, `gray-cool-5`, `primary`, `secondary-vivid`, `gold-vivid`, `green-cool`). Do not introduce numbered or generic tokens — if a new color is needed, it must trace to a USWDS palette entry.
|
|
38
|
+
|
|
39
|
+
Surface stack is **white** (background, card, popover) → `gray-cool-5` (secondary, muted) → `gray-cool-10` (accent, hover only). Depth comes from **1px borders and outlines**, never from shadow or fill drama.
|
|
40
|
+
|
|
41
|
+
Brand tokens: `--secondary-red` (emphasis, error), `--gold-vivid` (warning + focus ring), `--green-cool` (success), `--gray-cool-5` (surface alias), `--gray-cool-90` (foreground alias), `--base-dark` (mid-tier text), `--base-light` (borders), `--navy-dark` (optional dark-mode bg).
|
|
42
|
+
|
|
43
|
+
## Typography
|
|
44
|
+
- **Display:** Public Sans, weights 500/600/700. USWDS canonical face. Tracking `-0.005em` — barely tightened.
|
|
45
|
+
- **Body:** Public Sans, **17px floor (1.0625rem)** with **line-height 1.6 minimum**. This is the IDEA Act readability ceiling, not a suggestion. Tracking `0`.
|
|
46
|
+
- **Mono:** Roboto Mono — case numbers, form IDs, codes, EINs. Never used decoratively.
|
|
47
|
+
|
|
48
|
+
Font features: `"tnum", "ss01"` — tabular numerics so dollar columns and SSNs align. H1 uses `clamp(1.75rem, 4vw, 2.75rem)` — restrained; civic pages are services, not marketing.
|
|
49
|
+
|
|
50
|
+
## Spacing
|
|
51
|
+
- **Container:** `max-w-6xl px-4 lg:px-8` — 1152px. Service-form width; wider columns lose accessibility for low-vision users using browser zoom.
|
|
52
|
+
- **Section padding tiers:**
|
|
53
|
+
- Hero: `pt-12 pb-10 lg:pt-16 lg:pb-12` (restrained — civic, not promotional)
|
|
54
|
+
- Default: `py-10 lg:py-16`
|
|
55
|
+
- Tight: `py-6 lg:py-8`
|
|
56
|
+
- **Allowed scale values:** 2 4 6 8 12 16 20 24 32 40 48 64 80. Mapped to USWDS spacing units; no arbitrary values.
|
|
57
|
+
|
|
58
|
+
## Color
|
|
59
|
+
No hex anywhere in component files. All color via tokens. Every token has a **measured contrast ratio** noted in its `from:` comment when AA-relevant. Pure black is forbidden — `--foreground` is `218 30% 16%` (base-darkest with a faint navy bias). White (`0 0% 100%`) is permitted because it's the USWDS page surface.
|
|
60
|
+
|
|
61
|
+
**Color is never the only signal.** Error states pair red with an icon and "Error:" prefix; success pairs green with a check icon; warning pairs gold with an alert icon. Colorblind users (8% of men, including many veterans the VA serves) must be able to use every form without color.
|
|
62
|
+
|
|
63
|
+
## Radius
|
|
64
|
+
`--radius: 2px`. **Subtle, formal, slight.** Pills are disallowed (`pillsAllowed: false`) — USWDS uses rectangular Alert and Tag patterns, not pills. Pills read consumer/marketing; the federal aesthetic is the rectangle.
|
|
65
|
+
|
|
66
|
+
## Shadows
|
|
67
|
+
**Minimal.** Two utilities:
|
|
68
|
+
- `.border-strong` — `inset 0 0 0 1px var(--border)`. Border-as-shadow for elevated surfaces.
|
|
69
|
+
- `.focus-ring` — `0 0 0 2px var(--background), 0 0 0 4px var(--ring)`. Double-layer 4px gold ring with a 2px white inner gap so the ring is visible against any surface color.
|
|
70
|
+
|
|
71
|
+
USWDS uses thin border lines and outlines rather than drop shadows. Reason: accessibility — focus rings must read crisply, and drop shadows reduce focus-ring contrast.
|
|
72
|
+
|
|
73
|
+
## Motion
|
|
74
|
+
Single keyframe: `fade-in` (200ms, opacity only). **Translate-based reveals are forbidden** — vestibular sensitivity is common in the population federal services serve (veterans with TBI, elderly users, users with inner-ear conditions).
|
|
75
|
+
|
|
76
|
+
USWDS motion-policy: "use motion sparingly because vestibular sensitivity is common in the population we serve." Reveal duration 200ms maximum. No ambient motion. No infinite loops except a spinner for inline loading (and even that gets paused under `prefers-reduced-motion`).
|
|
77
|
+
|
|
78
|
+
`prefers-reduced-motion: reduce` is honored in every motion utility — non-negotiable. When set, all animations collapse to `animation-duration: 0.01ms` (functionally instant, but still triggers `animationend` listeners).
|
|
79
|
+
|
|
80
|
+
## Component patterns
|
|
81
|
+
- **Buttons:** Primary = solid USWDS blue (`hsl(213 92% 32%)`), white text, **2px** radius, **h-10 px-5**. Secondary = ghost with 2px USWDS-blue border, blue text. Danger = secondary-red solid. **Every button has a visible 4px gold-vivid focus ring on `:focus-visible`** (4.5:1 ring contrast). Minimum tap target **44x44px** (Section 508).
|
|
82
|
+
- **Cards:** Sharp 2px corners, 1px `base-light` border, white bg. Padding `p-6 lg:p-8`. No shadow. Title in Public Sans 600. Cards sit; they do not float.
|
|
83
|
+
- **Inputs:** Full box, **h-10**, 1px base border, 2px radius, white bg. **Label always sits above the input — placeholder-only labels are forbidden (Section 508).** Error state = 2px secondary-red left-border + inline message in red with `aria-describedby` linking message to input. Focus ring is gold (not blue) — maximizes contrast against the blue primary actions adjacent to it.
|
|
84
|
+
- **CTAs:** Primary action = solid blue button. In-text CTAs = underlined links in primary blue. Marketing-style hero CTAs do not exist; services have "Start application," "Continue to next step," "Submit." **All link text must make sense out of context** (Section 508 — no "click here," no "learn more" without antecedent).
|
|
85
|
+
- **Alerts (USWDS Alert):** Rectangular bar with 8px-thick left border in semantic color, icon, bold heading, body copy. Variants: `info` (blue), `success` (green-cool), `warning` (gold-vivid), `error` (secondary-red). Never auto-dismiss.
|
|
86
|
+
|
|
87
|
+
## Accessibility — first-class constraint
|
|
88
|
+
This is not a section; it's the whole direction. The non-negotiables:
|
|
89
|
+
- WCAG **2.2 AA** is the floor; **AAA** is the target. Run axe-core in CI.
|
|
90
|
+
- Body font-size **17px (1.0625rem) minimum**. Body line-height **1.6 minimum**.
|
|
91
|
+
- Form labels **never** placeholder-only. Always `<label for>` with visible text above the input.
|
|
92
|
+
- Focus ring **always visible**, **never removed**, **4.5:1 contrast** against the surface behind it.
|
|
93
|
+
- Color **never** the sole signal — pair with icon + text.
|
|
94
|
+
- Every interactive control is keyboard-reachable in document order. Skip-links land at `<main>`.
|
|
95
|
+
- Language toggle in the header (Spanish minimum). `<html lang>` updates correctly.
|
|
96
|
+
- Heading hierarchy is strict — exactly one h1, no skipped levels.
|
|
97
|
+
- Form errors summarize at the top of the form **and** mark each invalid input with `aria-invalid` + `aria-describedby`.
|
|
98
|
+
- "An official website of the United States government" banner ribbon at the top of every federal page.
|
|
99
|
+
|
|
100
|
+
## Recommended rich media
|
|
101
|
+
Documentary photography only — **citizens being served** (a person at a service window, a veteran reading paperwork, a family at a passport office), federal facilities (real buildings, real signage), public-service workers in their environment. **Stock photography is forbidden** — too polished, breaks trust, often unrepresentative.
|
|
102
|
+
|
|
103
|
+
Diagrams and flowcharts are the **dominant** rich media: eligibility-decision trees, service-step indicators (USWDS Step Indicator pattern), application-progress flows. These should be **drawn in the USWDS icon style** (single-stroke, two-tone, geometric) — never decorative.
|
|
104
|
+
|
|
105
|
+
Iconography is the **USWDS icon set** (the canonical federal icon library, ~250 icons covering services, document types, accessibility, transportation, weather). Lucide / Phosphor are acceptable fallbacks if USWDS lacks the glyph, but house style is USWDS-icon-set first.
|
|
106
|
+
|
|
107
|
+
**AI tool recommendations: AVOID generative AI imagery in federal contexts.** Disclosure rules under EO 14110 and ongoing federal AI-transparency policy make AI imagery a trust liability — a constituent who recognizes an AI-generated photograph on a `.gov` site has reasonable grounds to distrust everything else on the page. Use **real attributed photography** only: Unsplash for-government accounts, agency public-domain archives (NARA, DOD imagery, NASA), or commissioned documentary work. Always credit: *"Photo: U.S. Department of Veterans Affairs."* If AI is used for a diagram or illustration, **disclose it inline** ("Illustration generated with AI assistance and reviewed by [name]").
|
|
108
|
+
|
|
109
|
+
**Aspect ratios:** 3:2 (documentary standard) or 4:3 for portrait subjects. Never 16:9 cinematic widescreen — that reads marketing/promotional. Diagrams use whatever serves the content; never decorative crops.
|
|
110
|
+
|
|
111
|
+
**Video:** rare. When used: short (≤2 min), captioned (open captions burned in OR `<track>` with SRT — both is best), audio-described track for any video conveying non-textual information, transcript available below the video. Never autoplay. Never background-video heroes. ≤8 MB; H.264 or AV1; poster image required.
|
|
112
|
+
|
|
113
|
+
**Performance:** federal services target users on **3G connections and low-end Android**. Hero image ≤120 KB AVIF at 1600w. LCP **under 2.5s on Slow 4G**. Total page weight under 500 KB for service pages. JavaScript is progressive enhancement — every form must work without it.
|
|
114
|
+
|
|
115
|
+
**Avoid:** AI-generated photography (trust + disclosure issue), stock imagery, gradient backgrounds, glassmorphism, decorative SVG ornament, drop shadows, marketing-style hero video, autoplay anything, parallax, mouse-tracking effects, animated GIFs, lens flare, 3D renders, illustration styles that read corporate-friendly (Dropbox/Notion era flat-people illustrations), emoji as iconography.
|
|
116
|
+
|
|
117
|
+
**Accessibility for media:** long-form alt-text for photography, mandatory. Diagrams need both `aria-label` AND an adjacent text description ("Flowchart: Eligibility for Pell Grant. Step 1: …"). Charts must have a data-table alternative directly below them. Video needs captions + transcript + audio description.
|
|
118
|
+
|
|
119
|
+
## Component families
|
|
120
|
+
USWDS ships ~40 components; this direction inherits all of them by reference. Highest-traffic families:
|
|
121
|
+
- **Banner** (official-government ribbon — always at top, never removed).
|
|
122
|
+
- **Header** (agency wordmark, primary nav, language toggle, search).
|
|
123
|
+
- **Step Indicator** (multi-step service forms — Section 508 mandatory landmark).
|
|
124
|
+
- **Form patterns** (USWDS Form, Fieldset, Date Picker, Combo Box, File Input — all have specific accessibility behavior baked in; do not re-implement).
|
|
125
|
+
- **Alert** (info / success / warning / error — rectangular bar with thick left border).
|
|
126
|
+
- **Summary Box** (callout for service-specific eligibility, fees, deadlines).
|
|
127
|
+
- **Process List** (numbered vertical steps for how-to-apply content).
|
|
128
|
+
|
|
129
|
+
## Details
|
|
130
|
+
- **Selection:** `hsl(var(--primary) / 0.25)` background, foreground text.
|
|
131
|
+
- **Focus ring:** `4px solid hsl(var(--ring))` (gold-vivid). Double-layer with white inner gap via `.focus-ring` utility. **Never thinner. Never removed.**
|
|
132
|
+
- **Scrollbar:** `auto` (OS-native — accessibility-tool users rely on native scrollbar behavior; custom thin scrollbars break for AT).
|
|
133
|
+
|
|
134
|
+
## Exceptions
|
|
135
|
+
None yet. Any exception must be reviewed against Section 508 and the 21st Century IDEA Act before landing, and documented here with the WCAG criterion it touches and the mitigation.
|
|
136
|
+
|
|
137
|
+
## Revisions
|
|
138
|
+
- Initial direction, generated at install time. Sourced from USWDS v3.x token system.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import type { Direction } from "../schema";
|
|
2
|
+
|
|
3
|
+
export const governmentCivic: Direction = {
|
|
4
|
+
name: "government-civic",
|
|
5
|
+
ethos:
|
|
6
|
+
"US Web Design System (USWDS) · 21st Century IDEA Act accessibility · " +
|
|
7
|
+
"USDS public-service restraint · 18F democratic clarity · .gov heritage",
|
|
8
|
+
references: [
|
|
9
|
+
{ brand: "USWDS", trait: "the federal government's design system — the brand book itself" },
|
|
10
|
+
{ brand: "USDS", trait: "public-service restraint, citizen-first" },
|
|
11
|
+
{ brand: "18F", trait: "democratic clarity, plain-language UI" },
|
|
12
|
+
{ brand: "login.gov", trait: "accessibility-first authentication, AA minimum" },
|
|
13
|
+
{ brand: "va.gov", trait: "VA's digital-modernized service" },
|
|
14
|
+
{ brand: "GOV.UK", trait: "international cousin — service-pattern discipline" },
|
|
15
|
+
],
|
|
16
|
+
feel:
|
|
17
|
+
"Public-service formal. White or deep-navy surfaces, federal-blue with USWDS-red " +
|
|
18
|
+
"secondary, Public Sans typography. Strict accessibility (WCAG AAA target, AA floor), " +
|
|
19
|
+
"high information density, no decoration. Reads as 'a citizen must be able to use this " +
|
|
20
|
+
"regardless of device, bandwidth, vision, or English literacy.'",
|
|
21
|
+
|
|
22
|
+
fonts: {
|
|
23
|
+
display: {
|
|
24
|
+
family: "Public Sans",
|
|
25
|
+
fallback: ["system-ui", "-apple-system", "BlinkMacSystemFont", "Helvetica Neue", "Arial", "sans-serif"],
|
|
26
|
+
from: "USWDS canonical face — the federal sans, free + open",
|
|
27
|
+
googleFont: "Public+Sans",
|
|
28
|
+
weights: [400, 500, 600, 700],
|
|
29
|
+
},
|
|
30
|
+
body: {
|
|
31
|
+
family: "Public Sans",
|
|
32
|
+
fallback: ["system-ui", "-apple-system", "BlinkMacSystemFont", "Helvetica Neue", "Arial", "sans-serif"],
|
|
33
|
+
from: "USWDS canonical face — body and display share the family",
|
|
34
|
+
googleFont: "Public+Sans",
|
|
35
|
+
weights: [400, 500, 600, 700],
|
|
36
|
+
},
|
|
37
|
+
mono: {
|
|
38
|
+
family: "Roboto Mono",
|
|
39
|
+
fallback: ["ui-monospace", "SFMono-Regular", "Menlo", "Consolas", "monospace"],
|
|
40
|
+
from: "USWDS canonical mono — case numbers, form IDs, codes",
|
|
41
|
+
googleFont: "Roboto+Mono",
|
|
42
|
+
weights: [400, 500],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
typography: {
|
|
47
|
+
headingTracking: "-0.005em",
|
|
48
|
+
bodyTracking: "0",
|
|
49
|
+
fontFeatureSettings: '"tnum", "ss01"',
|
|
50
|
+
h1ScaleClamp: "clamp(1.75rem, 4vw, 2.75rem)", // restrained — civic, not marketing
|
|
51
|
+
bodyBaseSize: "1.0625rem", // 17px FLOOR — never smaller, accessibility-mandated
|
|
52
|
+
bodyLineHeight: "1.6", // 1.5 minimum per WCAG; we go 1.6
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
colors: {
|
|
56
|
+
background: { hsl: "0 0% 100%", from: "federal white — the .gov page surface" },
|
|
57
|
+
foreground: { hsl: "218 30% 16%", from: "USWDS base-darkest — near-black navy ink" },
|
|
58
|
+
card: { hsl: "0 0% 100%", from: "card surface = page surface; depth from borders" },
|
|
59
|
+
popover: { hsl: "0 0% 100%", from: "popovers stay white; bordered, not shadowed" },
|
|
60
|
+
primary: { hsl: "213 92% 32%", from: "USWDS primary blue #005EA2 — federal interactive blue" },
|
|
61
|
+
primaryForeground: { hsl: "0 0% 100%", from: "white on federal blue, AAA contrast" },
|
|
62
|
+
secondary: { hsl: "210 20% 96%", from: "USWDS gray-cool-5 — secondary surface tier" },
|
|
63
|
+
secondaryForeground: { hsl: "218 30% 16%", from: "base-darkest on gray-cool-5" },
|
|
64
|
+
muted: { hsl: "210 20% 96%", from: "same as secondary — gray-cool-5" },
|
|
65
|
+
mutedForeground: { hsl: "218 18% 38%", from: "USWDS base — secondary text, still AA against white" },
|
|
66
|
+
accent: { hsl: "210 24% 92%", from: "gray-cool-10 — hover/active surfaces only" },
|
|
67
|
+
accentForeground: { hsl: "218 30% 16%", from: "ink on gray-cool-10" },
|
|
68
|
+
border: { hsl: "214 20% 78%", from: "USWDS base-light — visible 1px rules, structural" },
|
|
69
|
+
input: { hsl: "214 20% 60%", from: "USWDS base — inputs need higher-contrast borders" },
|
|
70
|
+
ring: { hsl: "44 91% 50%", from: "USWDS gold-vivid focus ring — 4.5:1 against any surface" },
|
|
71
|
+
destructive: { hsl: "354 71% 45%", from: "USWDS secondary red — errors, alerts" },
|
|
72
|
+
destructiveForeground: { hsl: "0 0% 100%", from: "white on secondary red, AAA" },
|
|
73
|
+
brand: {
|
|
74
|
+
"secondary-red": { hsl: "354 71% 45%", from: "USWDS secondary red — emphasis + error" },
|
|
75
|
+
"gold-vivid": { hsl: "44 91% 50%", from: "USWDS warning gold — also the focus ring" },
|
|
76
|
+
"green-cool": { hsl: "158 64% 35%", from: "USWDS success — green-cool, AA compliant" },
|
|
77
|
+
"gray-cool-5": { hsl: "210 20% 96%", from: "surface tier — alias of secondary" },
|
|
78
|
+
"gray-cool-90": { hsl: "218 30% 16%", from: "alias of foreground — base-darkest" },
|
|
79
|
+
"base-dark": { hsl: "218 18% 38%", from: "USWDS base — mid-tier text" },
|
|
80
|
+
"base-light": { hsl: "214 20% 78%", from: "USWDS base-light — borders, dividers" },
|
|
81
|
+
"navy-dark": { hsl: "218 40% 12%", from: "alternate dark-mode background, deep navy" },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
spacing: {
|
|
86
|
+
base: 4,
|
|
87
|
+
scale: [2, 4, 6, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80], // USWDS spacing units mapped
|
|
88
|
+
containerMax: "max-w-6xl", // 1152px — service-form width
|
|
89
|
+
containerPadding: "px-4 lg:px-8",
|
|
90
|
+
sectionPadding: {
|
|
91
|
+
hero: "pt-12 pb-10 lg:pt-16 lg:pb-12", // restrained — civic hero, not marketing
|
|
92
|
+
default: "py-10 lg:py-16",
|
|
93
|
+
tight: "py-6 lg:py-8",
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
radius: {
|
|
98
|
+
base: "2px", // USWDS subtle — formal, slight, never pill-soft
|
|
99
|
+
pillsAllowed: false, // status indicators use rectangular USWDS Alert/Tag patterns
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
shadows: {
|
|
103
|
+
style: "minimal",
|
|
104
|
+
utilities: {
|
|
105
|
+
// USWDS uses borders + outlines rather than shadows — better focus visibility
|
|
106
|
+
"border-strong":
|
|
107
|
+
"inset 0 0 0 1px hsl(var(--border))",
|
|
108
|
+
"focus-ring":
|
|
109
|
+
"0 0 0 2px hsl(var(--background)), 0 0 0 4px hsl(var(--ring))", // 4px gold ring, double-layer
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
motion: {
|
|
114
|
+
easing: "cubic-bezier(0.22, 1, 0.36, 1)",
|
|
115
|
+
durations: {
|
|
116
|
+
reveal: 200, // USWDS motion-policy: 200ms reveals only
|
|
117
|
+
loop: 0, // no loops
|
|
118
|
+
ambient: 0, // no ambient — vestibular sensitivity in citizen population
|
|
119
|
+
},
|
|
120
|
+
keyframes: {
|
|
121
|
+
"fade-in": {
|
|
122
|
+
css:
|
|
123
|
+
"from { opacity: 0; }\n" +
|
|
124
|
+
"to { opacity: 1; }",
|
|
125
|
+
defaultDuration: 200,
|
|
126
|
+
iteration: "once",
|
|
127
|
+
purpose:
|
|
128
|
+
"the only entrance — opacity only, no transform. Alerts, accordions, " +
|
|
129
|
+
"validation messages. Translate-based motion is forbidden (vestibular).",
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
respectsReducedMotion: true,
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
density: "high",
|
|
136
|
+
|
|
137
|
+
patterns: {
|
|
138
|
+
button:
|
|
139
|
+
"Primary = solid USWDS blue (#005EA2), white text, 2px radius, h-10 px-5. " +
|
|
140
|
+
"Secondary = ghost with 2px USWDS-blue border, blue text. " +
|
|
141
|
+
"Danger = USWDS secondary-red solid. " +
|
|
142
|
+
"ALL buttons MUST show a visible 4px gold-vivid focus ring (4.5:1 contrast) on :focus-visible. " +
|
|
143
|
+
"Minimum tap target 44x44px (Section 508).",
|
|
144
|
+
card:
|
|
145
|
+
"Sharp (2px) corners, 1px USWDS base-light border, white bg. Padding p-6 lg:p-8. " +
|
|
146
|
+
"No shadows. Headers use h2/h3 in Public Sans 600. Cards never float — they sit.",
|
|
147
|
+
input:
|
|
148
|
+
"Full box, h-10, 1px base border (#71767A-equivalent), 2px radius, white bg. " +
|
|
149
|
+
"Label ALWAYS sits above the input — placeholder is never the label (Section 508). " +
|
|
150
|
+
"Error state = 2px secondary-red left border + inline message in red with icon. " +
|
|
151
|
+
"Focus = 4px gold-vivid ring (not blue — blue is button color; gold maximizes contrast).",
|
|
152
|
+
cta:
|
|
153
|
+
"Primary action is a solid blue button. In-text CTAs are underlined links in primary blue. " +
|
|
154
|
+
"Marketing-style hero CTAs do not exist — services have 'Start application' or 'Continue'. " +
|
|
155
|
+
"All link text must make sense out of context (Section 508 — no 'click here').",
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
details: {
|
|
159
|
+
selectionBg: "hsl(var(--primary) / 0.25)",
|
|
160
|
+
selectionFg: "hsl(var(--foreground))",
|
|
161
|
+
focusRing: "4px solid hsl(var(--ring))", // 4px gold — non-negotiable, never removed
|
|
162
|
+
scrollbarStyle: "auto", // OS-native — accessible to AT users
|
|
163
|
+
},
|
|
164
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Design Direction — Gym-Chain
|
|
2
|
+
|
|
3
|
+
## Ethos
|
|
4
|
+
Equinox matte-black luxury · Barry's red-room theatre · Rumble boxing-poster bravado · SoulCycle ritual atmosphere · F45 functional grid
|
|
5
|
+
|
|
6
|
+
## Feel
|
|
7
|
+
Matte black with one signal red. Full-bleed athlete photography mid-motion — sweat, lens flare, theatrical spotlight. Condensed display at billboard scale. The page is a venue, not a website. Booking a class feels like buying a ticket.
|
|
8
|
+
|
|
9
|
+
## Reference brands
|
|
10
|
+
- **Equinox** → matte black, full-bleed campaign photography, restrained gold reserved for member badges.
|
|
11
|
+
- **Barry's Bootcamp** → signal red room, oversized condensed display, boxing-poster confidence.
|
|
12
|
+
- **Rumble Boxing** → neon-red ring lighting, boxing-card typography, hype-build campaigns.
|
|
13
|
+
- **SoulCycle** → ritual studio darkness, candle-and-spot lighting, manifesto copy.
|
|
14
|
+
- **F45 Training** → functional schedule grid, intensity badges, color-coded class types.
|
|
15
|
+
|
|
16
|
+
## Tokens
|
|
17
|
+
Surface stack is **matte black** (background) → **+8% black** (card) → **+13% black** (secondary / muted / accent). Depth via hairline borders + the `card-deep` shadow. Brand tokens: `--signal-red`, `--red-deep`, `--black`, `--white`, `--gray-stage`, `--gold`. Primary is `--signal-red`. Gold is a *single-purpose* member-only badge color — never a CTA, never decoration.
|
|
18
|
+
|
|
19
|
+
## Typography
|
|
20
|
+
- **Display:** Bebas Neue 400 — condensed all-caps headline weight. Headlines set UPPERCASE with tracking 0.03em. Billboard scale: `clamp(3.5rem, 11vw, 9rem)`.
|
|
21
|
+
- **Body:** Inter 400/500/600/700. Neutral under heavy display. 16px base, line-height 1.55 (tighter than editorial — this is event copy).
|
|
22
|
+
- **Mono:** JetBrains Mono. Schedule times, intensity tiers, club codes.
|
|
23
|
+
|
|
24
|
+
Font features: `"tnum", "ss01", "cv11"`. Numbers are always tabular.
|
|
25
|
+
|
|
26
|
+
## Spacing
|
|
27
|
+
- **Container:** `max-w-7xl px-6 lg:px-10` — wide, full-bleed photography needs it.
|
|
28
|
+
- **Section padding tiers:**
|
|
29
|
+
- Hero: `pt-24 pb-16 lg:pt-36 lg:pb-24`
|
|
30
|
+
- Default: `py-20 lg:py-32`
|
|
31
|
+
- Tight: `py-12 lg:py-16`
|
|
32
|
+
- **Allowed scale values:** 4 8 12 16 20 24 32 40 48 64 80 96 128 160 200. The big numbers exist on purpose — venue scale.
|
|
33
|
+
|
|
34
|
+
## Color
|
|
35
|
+
No hex anywhere — tokens only. There is one red, and it is the brand. `--destructive` IS `--signal-red` — error states use the same hue because the brand IS the alarm color. Gold appears only on member badges. No greens, no blues, no warm wood-tones — this is a black box.
|
|
36
|
+
|
|
37
|
+
## Radius
|
|
38
|
+
`--radius: 0.25rem`. Boxing-card chamfer. Pills are allowed (`pillsAllowed: true`) but reserved for intensity badges and schedule chips, never for primary buttons (those are 0.25rem rectangles, stamp-like).
|
|
39
|
+
|
|
40
|
+
## Shadows
|
|
41
|
+
**Glow.** Utilities: `.glow-red` (1px red ring + 24px + 100px red glow), `.spotlight` (red upward halo + deep black drop), `.card-deep` (1px hairline + 30px×80px black drop). The default card uses `.card-deep`. Featured class cards use `.glow-red`. Hero photography frames use `.spotlight`.
|
|
42
|
+
|
|
43
|
+
## Motion
|
|
44
|
+
Five keyframes: `kinetic-rise` (800ms, opacity + 28px translate — fast and kinetic), `intensity-pulse` (2200ms loop for live-class dots), `spotlight-sweep` (6000ms horizontal light-sweep on featured cards), `ken-burns-athlete` (22000ms slow camera push over hero photography), `pulse-red` (2400ms heartbeat ring — exactly one book-now CTA per page).
|
|
45
|
+
|
|
46
|
+
Easing `cubic-bezier(0.22, 1, 0.36, 1)`. `prefers-reduced-motion` is honored — ambient ken-burns and spotlight-sweep stop, but the page still loads in place.
|
|
47
|
+
|
|
48
|
+
## Component patterns
|
|
49
|
+
- **Buttons:** primary is signal-red filled rectangle, white text, 0.25rem, uppercase tracking 0.1em in display face. Secondary is transparent with 1px border. Tertiary is uppercase red text-link.
|
|
50
|
+
- **Cards:** 0.25rem radius, hairline border, `bg-card`. Padding `p-6 lg:p-8`. Class cards get `card-deep`, featured cards get `glow-red`.
|
|
51
|
+
- **Class schedule grid:** today's classes as a row of compact dark cards — time in display, name in body bold, intensity as a pill badge (red 1-tier / amber 2-tier / white 3-tier), instructor in mono.
|
|
52
|
+
- **Club locations row:** four cards across, city in display all-caps, address in mono, "OPEN 5AM – 11PM" line in mono uppercase, hero photo background tinted black.
|
|
53
|
+
- **Performance metric callout strip:** four oversized tabular numbers in display, label in mono uppercase below. The numbers ARE the layout.
|
|
54
|
+
- **Inputs:** full box, 1px border, `bg-card`, 0.25rem. Label above in mono uppercase tracking 0.1em. Focus is signal-red 2px.
|
|
55
|
+
|
|
56
|
+
## Recommended rich media
|
|
57
|
+
Full-bleed athlete photography is the lead medium — mid-motion, theatrical key lighting from one side, deep shadow on the other, grain visible. Boxing-glove close-ups, rower mid-pull, sprint silhouettes against a red-lit wall. Aspect ratios 21:9 cinematic for hero, 4:5 portrait for athlete features. Never high-key wellness stock. Never people smiling at the camera holding a water bottle.
|
|
58
|
+
|
|
59
|
+
**AI tool recommendations:** Midjourney with *"Equinox campaign photography, low-key red room lighting, athletic body in motion, sweat, film grain, Magnum Photos"*. Avoid the default Midjourney glossy fitness style.
|
|
60
|
+
|
|
61
|
+
**Video:** hero looped 6-second athlete clip is on-brand — silent, autoplay, ≤4 MB. Stops on `prefers-reduced-motion`.
|
|
62
|
+
|
|
63
|
+
**Performance:** hero photo ≤200 KB AVIF at 1920w. Spotlight is a CSS gradient, not an image.
|
|
64
|
+
|
|
65
|
+
**Avoid:** bright cheerful gym stock, white-background product shots, smiling group classes, soft gradients, blue accents, "Three reasons to switch", any "transformation" before/after layout — that's MLM-tier, not Equinox-tier.
|
|
66
|
+
|
|
67
|
+
## Component families
|
|
68
|
+
None at install time.
|
|
69
|
+
|
|
70
|
+
## Details
|
|
71
|
+
- **Selection:** `hsl(var(--signal-red) / 0.4)` — red highlight on the matte-black canvas.
|
|
72
|
+
- **Focus ring:** 2px solid signal-red.
|
|
73
|
+
- **Scrollbar:** thin.
|
|
74
|
+
|
|
75
|
+
## Exceptions
|
|
76
|
+
None yet.
|
|
77
|
+
|
|
78
|
+
## Revisions
|
|
79
|
+
- Initial direction, generated at install time.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import type { Direction } from "../schema";
|
|
2
|
+
|
|
3
|
+
// gym-chain — Equinox / Barry's / Rumble atmosphere. Matte black, full-bleed
|
|
4
|
+
// mid-motion athlete photography, signal red accent. The room is dark, the
|
|
5
|
+
// lighting is theatrical, the bass is hitting. Marketing reads as event flyer,
|
|
6
|
+
// not service brochure.
|
|
7
|
+
export const gymChain: Direction = {
|
|
8
|
+
name: "gym-chain" as Direction["name"],
|
|
9
|
+
ethos:
|
|
10
|
+
"Equinox matte-black luxury · Barry's red-room theatre · Rumble boxing-poster bravado · " +
|
|
11
|
+
"SoulCycle ritual atmosphere · F45 functional grid",
|
|
12
|
+
references: [
|
|
13
|
+
{ brand: "Equinox", trait: "matte black, full-bleed campaign photography, restrained gold accent" },
|
|
14
|
+
{ brand: "Barry's Bootcamp", trait: "signal red room, oversized condensed display, boxing-poster confidence" },
|
|
15
|
+
{ brand: "Rumble Boxing", trait: "neon-red ring lighting, boxing-card typography, hype-build campaigns" },
|
|
16
|
+
{ brand: "SoulCycle", trait: "ritual studio darkness, candle-and-spot lighting, manifesto copy" },
|
|
17
|
+
{ brand: "F45 Training", trait: "functional-grid schedule, intensity badges, color-coded class types" },
|
|
18
|
+
],
|
|
19
|
+
feel:
|
|
20
|
+
"Matte black with one signal red. Full-bleed athlete photography mid-motion — sweat, " +
|
|
21
|
+
"lens flare, theatrical spotlight. Condensed display type at billboard scale. The page " +
|
|
22
|
+
"is a venue, not a website. Booking a class feels like buying a ticket.",
|
|
23
|
+
|
|
24
|
+
fonts: {
|
|
25
|
+
display: {
|
|
26
|
+
family: "Bebas Neue",
|
|
27
|
+
fallback: ["Anton", "Oswald", "Impact", "Arial Narrow Bold", "sans-serif"],
|
|
28
|
+
from: "Barry's/Rumble condensed all-caps headline — boxing-card poster weight, billboard-scale presence",
|
|
29
|
+
googleFont: "Bebas+Neue",
|
|
30
|
+
weights: [400],
|
|
31
|
+
},
|
|
32
|
+
body: {
|
|
33
|
+
family: "Inter",
|
|
34
|
+
fallback: ["system-ui", "-apple-system", "Helvetica Neue", "sans-serif"],
|
|
35
|
+
from: "Equinox clean modern sans — neutral under heavy display, never decorative under campaign photography",
|
|
36
|
+
googleFont: "Inter",
|
|
37
|
+
weights: [400, 500, 600, 700, 800],
|
|
38
|
+
},
|
|
39
|
+
mono: {
|
|
40
|
+
family: "JetBrains Mono",
|
|
41
|
+
fallback: ["ui-monospace", "SFMono-Regular", "Menlo", "monospace"],
|
|
42
|
+
from: "F45 tabular schedule numerics — class times, intensity tiers, location codes",
|
|
43
|
+
googleFont: "JetBrains+Mono",
|
|
44
|
+
weights: [400, 500, 700],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
typography: {
|
|
49
|
+
headingTracking: "0.03em", // condensed display needs positive tracking for billboard clarity
|
|
50
|
+
bodyTracking: "0.005em",
|
|
51
|
+
fontFeatureSettings: '"tnum", "ss01", "cv11"',
|
|
52
|
+
h1ScaleClamp: "clamp(3.5rem, 11vw, 9rem)", // billboard / event-poster scale
|
|
53
|
+
bodyBaseSize: "1rem", // 16px — comfortable on near-black
|
|
54
|
+
bodyLineHeight: "1.55", // tighter than editorial, this is event copy not prose
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
colors: {
|
|
58
|
+
background: { hsl: "0 0% 5%", from: "Equinox matte-black studio wall — graphite, never blue-tinted" },
|
|
59
|
+
foreground: { hsl: "0 0% 96%", from: "white-hot lighting bounce — venue-spotlight white" },
|
|
60
|
+
card: { hsl: "0 0% 8%", from: "elevated surface — one stop up, intensity-badge tier" },
|
|
61
|
+
popover: { hsl: "0 0% 11%", from: "menu/popover surface, two stops up" },
|
|
62
|
+
primary: { hsl: "356 78% 50%", from: "Barry's signal red — the canonical red-room mark, used on CTAs and intensity peaks" },
|
|
63
|
+
primaryForeground: { hsl: "0 0% 96%", from: "white on signal red" },
|
|
64
|
+
secondary: { hsl: "0 0% 13%", from: "Equinox shadow-tier — secondary surface, deeper grain" },
|
|
65
|
+
secondaryForeground: { hsl: "0 0% 96%", from: "white on shadow" },
|
|
66
|
+
muted: { hsl: "0 0% 15%", from: "muted surface — same family as secondary, fractionally lighter" },
|
|
67
|
+
mutedForeground: { hsl: "0 0% 62%", from: "stage-light gray — bystander text, instructor bio in low light" },
|
|
68
|
+
accent: { hsl: "0 0% 18%", from: "hover surface — brushed-steel highlight" },
|
|
69
|
+
accentForeground: { hsl: "0 0% 96%", from: "white on accent" },
|
|
70
|
+
border: { hsl: "0 0% 22%", from: "concrete-floor hairline — visible only on inspection" },
|
|
71
|
+
input: { hsl: "0 0% 22%", from: "same as border — single hairline language" },
|
|
72
|
+
ring: { hsl: "356 78% 50%", from: "signal red — focus is the brand color, never neutral" },
|
|
73
|
+
destructive: { hsl: "356 78% 50%", from: "same as primary — there is one red, and it is the brand" },
|
|
74
|
+
destructiveForeground: { hsl: "0 0% 96%", from: "white on red" },
|
|
75
|
+
brand: {
|
|
76
|
+
"signal-red": { hsl: "356 78% 50%", from: "Barry's red-room 356 — the venue's color, also primary" },
|
|
77
|
+
"red-deep": { hsl: "356 80% 38%", from: "deeper red — used only for gradient-bottom on hero spotlights" },
|
|
78
|
+
black: { hsl: "0 0% 5%", from: "Equinox matte — the canvas, also background" },
|
|
79
|
+
white: { hsl: "0 0% 96%", from: "spotlight bounce — the body color, also foreground" },
|
|
80
|
+
"gray-stage": { hsl: "0 0% 62%", from: "stage-light gray — secondary text" },
|
|
81
|
+
gold: { hsl: "41 56% 56%", from: "Equinox premium-tier gold — used only on member-only badges, never as primary" },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
spacing: {
|
|
86
|
+
base: 4,
|
|
87
|
+
scale: [4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96, 128, 160, 200], // dramatic — venue scale
|
|
88
|
+
containerMax: "max-w-7xl", // wide — full-bleed photography needs it
|
|
89
|
+
containerPadding: "px-6 lg:px-10",
|
|
90
|
+
sectionPadding: {
|
|
91
|
+
hero: "pt-24 pb-16 lg:pt-36 lg:pb-24",
|
|
92
|
+
default: "py-20 lg:py-32",
|
|
93
|
+
tight: "py-12 lg:py-16",
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
radius: {
|
|
98
|
+
base: "0.25rem", // tight — boxing-card chamfer, never pillow
|
|
99
|
+
pillsAllowed: true, // intensity badges read as pills, schedule chips too
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
shadows: {
|
|
103
|
+
style: "glow",
|
|
104
|
+
utilities: {
|
|
105
|
+
"glow-red":
|
|
106
|
+
"0 0 0 1px hsl(var(--signal-red) / 0.4), " +
|
|
107
|
+
"0 8px 24px hsl(var(--signal-red) / 0.25), " +
|
|
108
|
+
"0 40px 100px hsl(var(--signal-red) / 0.3)",
|
|
109
|
+
"spotlight":
|
|
110
|
+
"0 -20px 80px hsl(var(--signal-red) / 0.18), " +
|
|
111
|
+
"0 60px 120px hsl(0 0% 0% / 0.6)",
|
|
112
|
+
"card-deep":
|
|
113
|
+
"0 1px 0 0 hsl(var(--border)), " +
|
|
114
|
+
"0 30px 80px hsl(0 0% 0% / 0.5)",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
motion: {
|
|
119
|
+
easing: "cubic-bezier(0.22, 1, 0.36, 1)",
|
|
120
|
+
durations: {
|
|
121
|
+
reveal: 800, // entrance — fast enough to feel kinetic
|
|
122
|
+
loop: 2200, // pulse rings, intensity bars
|
|
123
|
+
ambient: 22000, // ken-burns over hero athlete photography
|
|
124
|
+
},
|
|
125
|
+
keyframes: {
|
|
126
|
+
"kinetic-rise": {
|
|
127
|
+
css:
|
|
128
|
+
"from { opacity: 0; transform: translateY(28px); }\n" +
|
|
129
|
+
"to { opacity: 1; transform: translateY(0); }",
|
|
130
|
+
defaultDuration: 800,
|
|
131
|
+
iteration: "once",
|
|
132
|
+
purpose: "section/headline entrance — kinetic, with momentum",
|
|
133
|
+
},
|
|
134
|
+
"intensity-pulse": {
|
|
135
|
+
css:
|
|
136
|
+
"0%, 100% { opacity: 1; transform: scale(1); }\n" +
|
|
137
|
+
"50% { opacity: 0.65; transform: scale(0.96); }",
|
|
138
|
+
defaultDuration: 2200,
|
|
139
|
+
iteration: "infinite",
|
|
140
|
+
purpose: "live class indicator — intensity dot pulses in tempo with red-room beat",
|
|
141
|
+
},
|
|
142
|
+
"spotlight-sweep": {
|
|
143
|
+
css:
|
|
144
|
+
"0% { background-position: -100% 0; }\n" +
|
|
145
|
+
"100% { background-position: 200% 0; }",
|
|
146
|
+
defaultDuration: 6000,
|
|
147
|
+
iteration: "infinite",
|
|
148
|
+
purpose: "subtle horizontal light-sweep on featured class card — venue spotlight",
|
|
149
|
+
},
|
|
150
|
+
"ken-burns-athlete": {
|
|
151
|
+
css:
|
|
152
|
+
"0% { transform: scale(1.08) translate(0, 0); }\n" +
|
|
153
|
+
"100% { transform: scale(1.2) translate(-3%, -1.5%); }",
|
|
154
|
+
defaultDuration: 22000,
|
|
155
|
+
iteration: "infinite",
|
|
156
|
+
purpose: "hero athlete photography drift — slow camera push, broadcast feel",
|
|
157
|
+
},
|
|
158
|
+
"pulse-red": {
|
|
159
|
+
css:
|
|
160
|
+
"0%, 100% { box-shadow: 0 0 0 0 hsl(var(--signal-red) / 0.6); }\n" +
|
|
161
|
+
"50% { box-shadow: 0 0 0 16px hsl(var(--signal-red) / 0); }",
|
|
162
|
+
defaultDuration: 2400,
|
|
163
|
+
iteration: "infinite",
|
|
164
|
+
purpose: "single book-now CTA heartbeat ring — one per page, never more",
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
respectsReducedMotion: true,
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
density: "medium",
|
|
171
|
+
|
|
172
|
+
patterns: {
|
|
173
|
+
button:
|
|
174
|
+
"Primary action = signal-red filled rectangle, white text, 0.25rem radius, uppercase tracking 0.1em label, condensed display face. " +
|
|
175
|
+
"Secondary = transparent with 1px border in --border, white text, hover lifts to --accent. " +
|
|
176
|
+
"Tertiary = text-link in signal-red, uppercase, underline-on-hover. " +
|
|
177
|
+
"Never softened, never pilled-out — the button is a boxing-card stamp.",
|
|
178
|
+
card:
|
|
179
|
+
"0.25rem radius, hairline border (--border), bg-card. Padding p-6 lg:p-8. " +
|
|
180
|
+
"Class cards use card-deep shadow; live/featured cards use glow-red; hero photography uses spotlight. " +
|
|
181
|
+
"Headline in condensed display uppercase, label in mono uppercase tracking 0.1em.",
|
|
182
|
+
input:
|
|
183
|
+
"Full box, 1px --border, bg-card, 0.25rem radius. Label sits above in mono uppercase tracking 0.1em. " +
|
|
184
|
+
"Focus ring is signal-red, 2px.",
|
|
185
|
+
cta:
|
|
186
|
+
"The single book-now CTA per page uses pulse-red ring. Inline CTAs are text-links in signal-red, uppercase tracking 0.08em. " +
|
|
187
|
+
"Never a soft pastel, never a gradient softer than red → red-deep.",
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
details: {
|
|
191
|
+
selectionBg: "hsl(var(--signal-red) / 0.4)",
|
|
192
|
+
selectionFg: "hsl(var(--foreground))",
|
|
193
|
+
focusRing: "2px solid hsl(var(--ring))",
|
|
194
|
+
scrollbarStyle: "thin",
|
|
195
|
+
},
|
|
196
|
+
};
|