@stylecrib/cli 0.3.1 → 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 +94 -9
- 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 +1577 -463
- package/package.json +11 -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,147 @@
|
|
|
1
|
+
import type { Direction } from "../schema";
|
|
2
|
+
|
|
3
|
+
export const bookstoreIndie: Direction = {
|
|
4
|
+
name: "bookstore-indie" as Direction["name"],
|
|
5
|
+
ethos:
|
|
6
|
+
"Strand 18 miles of books · Powell's stacked-card warmth · City Lights beat-poet pedigree · Three Lives neighborhood serif · Greenlight handwritten staff blurbs",
|
|
7
|
+
references: [
|
|
8
|
+
{ brand: "Strand Bookstore", trait: "warm cream, dense shelves, no marketing varnish" },
|
|
9
|
+
{ brand: "Powell's City of Books", trait: "color-coded room signage, handwritten staff blurbs" },
|
|
10
|
+
{ brand: "City Lights", trait: "literary-magazine serif, beat-poet austerity" },
|
|
11
|
+
{ brand: "Three Lives & Co", trait: "neighborhood-bookstore serif, single-window display" },
|
|
12
|
+
{ brand: "Greenlight Bookstore", trait: "Lora-feel body serif, staff-pick shelf as homepage" },
|
|
13
|
+
],
|
|
14
|
+
feel:
|
|
15
|
+
"Walking into a small bookstore on a side street. Warm cream paper, generous body serif, " +
|
|
16
|
+
"handwritten-feel staff blurbs in italic. The page should feel like the staff actually read these. " +
|
|
17
|
+
"Color is sparing — a single brick-red accent for new arrivals and the staff stamp.",
|
|
18
|
+
|
|
19
|
+
fonts: {
|
|
20
|
+
display: {
|
|
21
|
+
family: "Lora",
|
|
22
|
+
fallback: ["Georgia", "Iowan Old Style", "Times New Roman", "serif"],
|
|
23
|
+
from: "Greenlight / Three Lives book-cover serif feel — readable at every size",
|
|
24
|
+
googleFont: "Lora",
|
|
25
|
+
weights: [400, 500, 600, 700],
|
|
26
|
+
},
|
|
27
|
+
body: {
|
|
28
|
+
family: "Lora",
|
|
29
|
+
fallback: ["Georgia", "Iowan Old Style", "Times New Roman", "serif"],
|
|
30
|
+
from: "single-family discipline — body in the same serif as display, smaller and lighter",
|
|
31
|
+
googleFont: "Lora",
|
|
32
|
+
weights: [400, 500],
|
|
33
|
+
},
|
|
34
|
+
mono: {
|
|
35
|
+
family: "JetBrains Mono",
|
|
36
|
+
fallback: ["ui-monospace", "SFMono-Regular", "Consolas", "monospace"],
|
|
37
|
+
from: "ISBN, event times, shelf tags — receipt-tape mono",
|
|
38
|
+
googleFont: "JetBrains+Mono",
|
|
39
|
+
weights: [400, 500],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
typography: {
|
|
44
|
+
headingTracking: "-0.01em",
|
|
45
|
+
bodyTracking: "0",
|
|
46
|
+
fontFeatureSettings: '"tnum", "calt"',
|
|
47
|
+
h1ScaleClamp: "clamp(2.25rem, 5vw, 4rem)",
|
|
48
|
+
bodyBaseSize: "1.0625rem",
|
|
49
|
+
bodyLineHeight: "1.7",
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
colors: {
|
|
53
|
+
background: { hsl: "38 35% 93%", from: "warm cream paperback stock — Strand / Greenlight" },
|
|
54
|
+
foreground: { hsl: "24 18% 16%", from: "warm deep ink, espresso brown — not black" },
|
|
55
|
+
card: { hsl: "38 38% 96%", from: "shelf-tag cream, one stop up from background" },
|
|
56
|
+
popover: { hsl: "38 38% 96%", from: "matches card" },
|
|
57
|
+
primary: { hsl: "8 55% 38%", from: "brick red — staff-pick stamp, new-arrivals shelf marker" },
|
|
58
|
+
primaryForeground: { hsl: "38 35% 93%", from: "cream on brick" },
|
|
59
|
+
secondary: { hsl: "38 28% 88%", from: "deeper cream — section dividers, shelf labels" },
|
|
60
|
+
secondaryForeground: { hsl: "24 18% 16%", from: "ink on shelf cream" },
|
|
61
|
+
muted: { hsl: "38 28% 88%", from: "same as secondary — single muted family" },
|
|
62
|
+
mutedForeground: { hsl: "28 10% 42%", from: "receipt-tape gray — ISBNs, event times" },
|
|
63
|
+
accent: { hsl: "38 25% 85%", from: "hover surface — cream deeper still" },
|
|
64
|
+
accentForeground: { hsl: "24 18% 16%", from: "ink on hover" },
|
|
65
|
+
border: { hsl: "30 15% 78%", from: "shelf-edge wood-tone hairline" },
|
|
66
|
+
input: { hsl: "30 15% 78%", from: "same as border" },
|
|
67
|
+
ring: { hsl: "8 55% 38%", from: "brick red — focus" },
|
|
68
|
+
destructive: { hsl: "0 60% 42%", from: "out-of-stock indicator" },
|
|
69
|
+
destructiveForeground: { hsl: "38 35% 93%", from: "cream on destructive" },
|
|
70
|
+
brand: {
|
|
71
|
+
ink: { hsl: "24 18% 16%", from: "espresso ink — semantic foreground" },
|
|
72
|
+
cream: { hsl: "38 35% 93%", from: "paperback cream — semantic background" },
|
|
73
|
+
brick: { hsl: "8 55% 38%", from: "staff-pick brick — also semantic primary" },
|
|
74
|
+
sage: { hsl: "100 18% 42%", from: "event-listing sage green — readings, signings" },
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
spacing: {
|
|
79
|
+
base: 4,
|
|
80
|
+
scale: [4, 6, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96],
|
|
81
|
+
containerMax: "max-w-5xl",
|
|
82
|
+
containerPadding: "px-6 lg:px-10",
|
|
83
|
+
sectionPadding: {
|
|
84
|
+
hero: "pt-24 pb-14 lg:pt-36 lg:pb-20",
|
|
85
|
+
default: "py-16 lg:py-24",
|
|
86
|
+
tight: "py-10 lg:py-16",
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
radius: {
|
|
91
|
+
base: "0.125rem",
|
|
92
|
+
pillsAllowed: false,
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
shadows: {
|
|
96
|
+
style: "minimal",
|
|
97
|
+
utilities: {
|
|
98
|
+
"hairline-bottom":
|
|
99
|
+
"0 1px 0 0 hsl(var(--border))",
|
|
100
|
+
"shelf-tag":
|
|
101
|
+
"0 1px 0 0 hsl(var(--border)), inset 0 0 0 1px hsl(var(--border))",
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
motion: {
|
|
106
|
+
easing: "cubic-bezier(0.22, 1, 0.36, 1)",
|
|
107
|
+
durations: {
|
|
108
|
+
reveal: 1000,
|
|
109
|
+
loop: 4000,
|
|
110
|
+
ambient: 30000,
|
|
111
|
+
},
|
|
112
|
+
keyframes: {
|
|
113
|
+
"fade-rise": {
|
|
114
|
+
css:
|
|
115
|
+
"from { opacity: 0; transform: translateY(16px); }\n" +
|
|
116
|
+
"to { opacity: 1; transform: translateY(0); }",
|
|
117
|
+
defaultDuration: 1000,
|
|
118
|
+
iteration: "once",
|
|
119
|
+
purpose: "shelf entrance — quiet, page-turn feel",
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
respectsReducedMotion: true,
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
density: "medium",
|
|
126
|
+
|
|
127
|
+
patterns: {
|
|
128
|
+
button:
|
|
129
|
+
"Text-link CTAs with brick-red on hover; 'Buy from us' is the single solid-fill — brick bg + cream text. " +
|
|
130
|
+
"Pills disallowed — shelf tags are rectangular.",
|
|
131
|
+
card:
|
|
132
|
+
"Hairline border, slight cream-tier shift from background. Padding p-6 lg:p-8. " +
|
|
133
|
+
"Title in display serif italic; author in display serif roman; staff blurb in body serif italic.",
|
|
134
|
+
input:
|
|
135
|
+
"Border-bottom only (1px ink). Label above in mono uppercase, small.",
|
|
136
|
+
cta:
|
|
137
|
+
"Text-link with ink, hover transitions to brick. Never a chip, never a gradient. " +
|
|
138
|
+
"'Buy local' is the single exception — solid brick rectangle with cream text.",
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
details: {
|
|
142
|
+
selectionBg: "hsl(var(--primary) / 0.2)",
|
|
143
|
+
selectionFg: "hsl(var(--foreground))",
|
|
144
|
+
focusRing: "1px solid hsl(var(--ring))",
|
|
145
|
+
scrollbarStyle: "thin",
|
|
146
|
+
},
|
|
147
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Design Direction — Brutalist
|
|
2
|
+
|
|
3
|
+
## Ethos
|
|
4
|
+
System defaults · monospace prominence · Hacker News pedigree · IA Writer restraint · Bear blog purity · Berkeley Mono dignity
|
|
5
|
+
|
|
6
|
+
## Feel
|
|
7
|
+
Raw HTML feel taken seriously. System default fonts, no off-whites, no soft shadows, no rounded corners, no animations. Dense information with monospace prominence for technical content. The opposite of "polished" — but composed and intentional, not just bare.
|
|
8
|
+
|
|
9
|
+
## Reference brands
|
|
10
|
+
- **Hacker News** → raw-web orange, system fonts, no chrome. The page is the data.
|
|
11
|
+
- **IA Writer** → monospace dignity, prose discipline. The cursor matters more than the canvas.
|
|
12
|
+
- **Berkeley Mono showcase** → monospace as a first-class display face, not a code-block ghetto.
|
|
13
|
+
- **Bear blog** → default-stylesheet purity. The browser already shipped a stylesheet; respect it.
|
|
14
|
+
- **Wikipedia** → browser-default link colors, unstyled hierarchy. Blue means link. Purple means visited.
|
|
15
|
+
- **Unix man pages** → tabular density, no decoration. Information is the design.
|
|
16
|
+
|
|
17
|
+
## Tokens
|
|
18
|
+
HSL triples in `src/index.css`. Every token's `from:` traces to a brand·trait — Hacker News, IA Writer, Wikipedia, Bear blog, or Unix heritage. Brand tokens: `--link-blue` (browser-default unstyled `<a>` color), `--visited-purple` (browser-default visited color), `--hn-orange` (= primary), `--meta-gray` (Hacker News meta-text gray).
|
|
19
|
+
|
|
20
|
+
Surface stack is **almost nonexistent**: `bg` and `card` and `popover` are all the same pure white. `secondary`, `muted`, and `accent` collapse into a single near-white (`0 0% 96%`). Depth never comes from fill differentiation; it comes from **1px black borders**. Brutalist refuses to invent intermediate grays.
|
|
21
|
+
|
|
22
|
+
## Typography
|
|
23
|
+
- **Display:** the system UI stack (`-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui`). There is no custom display face — size is the only hierarchy tool, and it's used sparingly. H1 clamps at `clamp(1.25rem, 2.5vw, 1.75rem)` — barely larger than body.
|
|
24
|
+
- **Body:** Georgia (the IA Writer / Bear blog move). The browser already shipped a body serif on every OS; brutalist uses it instead of pulling 80kb of webfont over the wire. **16px**, line-height **1.5**.
|
|
25
|
+
- **Mono:** Berkeley Mono (with JetBrains Mono, SF Mono, ui-monospace as fallback). **Prominent throughout** — IDs, timestamps, file paths, code, metrics, tables. Mono is not a special case in this language; it's a co-equal voice.
|
|
26
|
+
|
|
27
|
+
Font features: `"tnum", "zero"` — tabular figures + slashed zero, Unix man-page heritage. Heading tracking is `0` — system fonts ship with correct tracking and we don't override it.
|
|
28
|
+
|
|
29
|
+
## Spacing
|
|
30
|
+
- **Container:** `max-w-4xl px-3 lg:px-4` — Hacker News column width is roughly 85ch; brutalist sits there. Not full-bleed (utility), not narrow (editorial).
|
|
31
|
+
- **Section padding tiers:**
|
|
32
|
+
- Hero: `pt-6 pb-4 lg:pt-8 lg:pb-6` — **there is no hero**. The first paragraph is the hero.
|
|
33
|
+
- Default: `py-6 lg:py-8`
|
|
34
|
+
- Tight: `py-3 lg:py-4`
|
|
35
|
+
- **Allowed scale values:** 2 4 6 8 12 16 20 24. **Tight and finite.** No 32, no 48, no 64 — brutalist refuses to luxuriate. The `2` step is for inline icon-to-text gaps; nothing else uses it.
|
|
36
|
+
|
|
37
|
+
## Color
|
|
38
|
+
No hex anywhere. **Pure white (`0 0% 100%`) and pure black (`0 0% 0%`) are the foundation** — the opposite stance from editorial and dense-utility, which both forbid them. Off-whites, slates, and warm papers are out of language. Primary is **Hacker News orange** (`24 100% 50%`) — the canonical "raw web" accent, used only for the topbar mark, the focus ring, and the selection highlight.
|
|
39
|
+
|
|
40
|
+
`--link-blue` and `--visited-purple` are intentional. Browser-default link colors are the most honest UI affordance the web has, and brutalist will not paint over them.
|
|
41
|
+
|
|
42
|
+
## Radius
|
|
43
|
+
`--radius: 0`. **Sharp corners only.** Pills are disallowed (`pillsAllowed: false`) — status badges, rounded inputs, and capsule buttons all read web-app, not brutalist. If you need to differentiate, use a border or change the text.
|
|
44
|
+
|
|
45
|
+
## Shadows
|
|
46
|
+
**None.** Single utility: `.border-1px` (`inset 0 0 0 1px var(--border)`) — the literal 1px default table rule, expressed as a shadow because some shadcn primitives expect a shadow class. Drop shadows, glows, and soft elevations do not exist in this language.
|
|
47
|
+
|
|
48
|
+
## Motion
|
|
49
|
+
**None.** The `keyframes` map is intentionally empty. Reveal, loop, and ambient durations are all `0 ms`. Brutalist rejects ambient motion entirely — no entrance fades, no hover transitions, no spinners (use the text "loading..." instead), no parallax, no scroll-triggered anything.
|
|
50
|
+
|
|
51
|
+
`respectsReducedMotion: true` — honored as a matter of principle, though in practice there is nothing to reduce. Easing stays in the schema for parity but has no callers.
|
|
52
|
+
|
|
53
|
+
## Component patterns
|
|
54
|
+
- **Buttons:** underlined text links only. Primary, secondary, and CTA all render as `<a>` with underline. Solid filled buttons are antithetical. The one permitted exception: form submits MAY render as the default browser `<input type=submit>` — the `[submit]` look — because honoring the browser default is on-direction.
|
|
55
|
+
- **Cards:** 1px solid black border, no fill differentiation from background, no shadow, no radius. Padding `p-3 lg:p-4`. Titles are bold body weight; no display face, no size jump beyond ~1.125x.
|
|
56
|
+
- **Inputs:** full 1px black box (border, not bottom-only), no radius, system font, 16px. Label is a plain `<label>` above the field — no placeholder-as-label. Focus uses the browser default ring.
|
|
57
|
+
- **CTAs:** underlined text link in `--link-blue` (or `--primary` for the loud one). **Never a chip, never a rect, never a gradient.** Visited links use `--visited-purple` — intentional, not a bug.
|
|
58
|
+
|
|
59
|
+
## Component families
|
|
60
|
+
None at install time. If component families emerge (e.g. comment threads, news listings), they will mirror Hacker News conventions: indented `<ul>` for threads, rank-number prefix for listings, mono `--meta-gray` for bylines and timestamps.
|
|
61
|
+
|
|
62
|
+
## Recommended rich media
|
|
63
|
+
Brutalist rejects most rich media. The on-direction options are narrow and intentional:
|
|
64
|
+
|
|
65
|
+
- **ASCII art** — diagrams, dividers, banner text. The most on-direction visual element this language has.
|
|
66
|
+
- **System emoji as captioned figures** — a single emoji glyph with a `<figcaption>` underneath, framed like a tiny museum label. Used sparingly.
|
|
67
|
+
- **Low-res screenshots presented frankly** — no shadow, no border-radius, no padding. The pixels are the content. PNG or GIF, not WebP fanciness.
|
|
68
|
+
- **Text-as-image only if necessary** — e.g. poster art, scanned document, a screenshot of a terminal session.
|
|
69
|
+
|
|
70
|
+
**AI tool recommendations: rarely needed.** When AI generation is used, pick tools that don't add gloss: ASCII-art generators, dithered-image converters (e.g. `dither-me-this`), 1-bit pixel art tools. Avoid anything that markets "photorealism," "cinematic," or "4K."
|
|
71
|
+
|
|
72
|
+
**Aspect ratios:** respect the natural aspect of the source image. No cropping to a system, no 16:9 conformity, no square-format Instagram grids. If a screenshot is 1438×612, ship it at 1438×612.
|
|
73
|
+
|
|
74
|
+
**What to AVOID:**
|
|
75
|
+
- Stock photography of any kind.
|
|
76
|
+
- AI-glossy hero images (Midjourney "epic cinematic" output).
|
|
77
|
+
- Video backgrounds and looping reels.
|
|
78
|
+
- Decorative SVG (blobs, swooshes, abstract gradients).
|
|
79
|
+
- Glassmorphic anything.
|
|
80
|
+
- Lens flare, bokeh, depth-of-field tricks.
|
|
81
|
+
- Gradients of any kind — linear, radial, mesh.
|
|
82
|
+
|
|
83
|
+
**Honest constraint:** a brutalist site that uses **zero AI-generated rich media** is more on-direction than one that uses any. If you can ship the page without an image, ship it without an image.
|
|
84
|
+
|
|
85
|
+
**Accessibility:** alt-text is the design constraint. If you can't describe an image in one plain sentence, you don't need the image. Brutalist's commitment to "the text is the page" means every figure must survive alt-text-only consumption.
|
|
86
|
+
|
|
87
|
+
## Details
|
|
88
|
+
- **Selection:** `hsl(var(--primary) / 0.3)` background, foreground text. HN-orange highlight — the only place orange touches body text.
|
|
89
|
+
- **Focus ring:** `2px solid hsl(var(--ring))` — close to the browser default. Brutalist does not minimize the focus ring; accessibility is on-direction.
|
|
90
|
+
- **Scrollbar:** **auto** (browser default). Brutalist does not restyle the scrollbar — that's a soft-modern affordance.
|
|
91
|
+
|
|
92
|
+
## Exceptions
|
|
93
|
+
None yet. When an intentional one-of-one violation lands, add it here with the reason.
|
|
94
|
+
|
|
95
|
+
## Revisions
|
|
96
|
+
- Initial direction, generated at install time.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import type { Direction } from "../schema";
|
|
2
|
+
|
|
3
|
+
export const brutalist: Direction = {
|
|
4
|
+
name: "brutalist",
|
|
5
|
+
ethos:
|
|
6
|
+
"System defaults · monospace prominence · Hacker News pedigree · IA Writer restraint · Bear blog purity · Berkeley Mono dignity",
|
|
7
|
+
references: [
|
|
8
|
+
{ brand: "Hacker News", trait: "raw-web orange, system fonts, no chrome" },
|
|
9
|
+
{ brand: "IA Writer", trait: "monospace dignity, prose discipline" },
|
|
10
|
+
{ brand: "Berkeley Mono showcase", trait: "monospace as a first-class display face" },
|
|
11
|
+
{ brand: "Bear blog", trait: "default-stylesheet purity" },
|
|
12
|
+
{ brand: "Wikipedia", trait: "browser-default link colors, unstyled hierarchy" },
|
|
13
|
+
{ brand: "Unix man pages", trait: "tabular density, no decoration" },
|
|
14
|
+
],
|
|
15
|
+
feel:
|
|
16
|
+
"Raw HTML feel taken seriously. System default fonts, no off-whites, no soft " +
|
|
17
|
+
"shadows, no rounded corners, no animations. Dense information with monospace " +
|
|
18
|
+
"prominence for technical content. The opposite of polished — but composed and " +
|
|
19
|
+
"intentional, not just bare.",
|
|
20
|
+
|
|
21
|
+
fonts: {
|
|
22
|
+
display: {
|
|
23
|
+
family: "-apple-system",
|
|
24
|
+
fallback: ["BlinkMacSystemFont", "Segoe UI", "system-ui", "sans-serif"],
|
|
25
|
+
from: "no custom display face — Hacker News stance: system UI stack, size is the only hierarchy",
|
|
26
|
+
weights: [400, 700],
|
|
27
|
+
},
|
|
28
|
+
body: {
|
|
29
|
+
family: "Georgia",
|
|
30
|
+
fallback: ["Iowan Old Style", "Times New Roman", "serif"],
|
|
31
|
+
from: "IA Writer / Bear blog default-serif body — the browser already shipped a body face",
|
|
32
|
+
weights: [400, 700],
|
|
33
|
+
},
|
|
34
|
+
mono: {
|
|
35
|
+
family: "Berkeley Mono",
|
|
36
|
+
fallback: ["JetBrains Mono", "SF Mono", "ui-monospace", "SFMono-Regular", "Menlo", "monospace"],
|
|
37
|
+
from: "Berkeley Mono showcase — monospace as a first-class face, not a code-block ghetto",
|
|
38
|
+
googleFont: "JetBrains+Mono",
|
|
39
|
+
weights: [400, 700],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
typography: {
|
|
44
|
+
headingTracking: "0", // system fonts ship with correct tracking; do not adjust
|
|
45
|
+
bodyTracking: "0",
|
|
46
|
+
fontFeatureSettings: '"tnum", "zero"', // tabular figures + slashed zero — terminal/man-page heritage
|
|
47
|
+
h1ScaleClamp: "clamp(1.25rem, 2.5vw, 1.75rem)", // small — Hacker News H1 is barely larger than body
|
|
48
|
+
bodyBaseSize: "1rem", // 16px — the browser default, not a designer's 17px or 14px
|
|
49
|
+
bodyLineHeight: "1.5",
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
colors: {
|
|
53
|
+
background: { hsl: "0 0% 100%", from: "pure white — no warm bias, no cream paper trick (Hacker News, Bear blog)" },
|
|
54
|
+
foreground: { hsl: "0 0% 0%", from: "pure black — no slate, no ink, no softening (Wikipedia body color)" },
|
|
55
|
+
card: { hsl: "0 0% 100%", from: "same as background — surfaces don't differentiate by fill in brutalist" },
|
|
56
|
+
popover: { hsl: "0 0% 100%", from: "same as background — depth via 1px border, never fill" },
|
|
57
|
+
primary: { hsl: "24 100% 50%", from: "Hacker News orange — the canonical raw-web accent" },
|
|
58
|
+
primaryForeground: { hsl: "0 0% 100%", from: "white on HN orange — the original bar at the top of news.ycombinator.com" },
|
|
59
|
+
secondary: { hsl: "0 0% 96%", from: "Hacker News pale background bar (#f6f6ef-equivalent), used only for the thinnest secondary surface" },
|
|
60
|
+
secondaryForeground: { hsl: "0 0% 0%", from: "pure black on the HN bar" },
|
|
61
|
+
muted: { hsl: "0 0% 96%", from: "same as secondary — brutalist refuses to invent extra grays" },
|
|
62
|
+
mutedForeground: { hsl: "0 0% 33%", from: "Hacker News meta-text gray (#828282-equivalent) — author lines, timestamps" },
|
|
63
|
+
accent: { hsl: "0 0% 96%", from: "same as secondary — hover state, no new color" },
|
|
64
|
+
accentForeground: { hsl: "0 0% 0%", from: "pure black on hover" },
|
|
65
|
+
border: { hsl: "0 0% 0%", from: "pure black 1px border — the literal default browser table rule" },
|
|
66
|
+
input: { hsl: "0 0% 0%", from: "same as border — inputs are 1px black boxes, like a 1995 form" },
|
|
67
|
+
ring: { hsl: "24 100% 50%", from: "HN orange — focus only, matches primary" },
|
|
68
|
+
destructive: { hsl: "0 100% 40%", from: "browser-default error red — the unstyled <strong> warning color" },
|
|
69
|
+
destructiveForeground: { hsl: "0 0% 100%", from: "white on red" },
|
|
70
|
+
brand: {
|
|
71
|
+
"link-blue": {
|
|
72
|
+
hsl: "240 100% 40%",
|
|
73
|
+
from: "browser-default unstyled <a> blue — Wikipedia, Bear blog, every honest hyperlink since 1993",
|
|
74
|
+
},
|
|
75
|
+
"visited-purple": {
|
|
76
|
+
hsl: "280 60% 40%",
|
|
77
|
+
from: "browser-default visited-link purple — intentional, not a bug",
|
|
78
|
+
},
|
|
79
|
+
"hn-orange": {
|
|
80
|
+
hsl: "24 100% 50%",
|
|
81
|
+
from: "Hacker News orange — also semantic primary; named here for component-level clarity",
|
|
82
|
+
},
|
|
83
|
+
"meta-gray": {
|
|
84
|
+
hsl: "0 0% 33%",
|
|
85
|
+
from: "Hacker News meta text — bylines, scores, comment counts",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
spacing: {
|
|
91
|
+
base: 4,
|
|
92
|
+
scale: [2, 4, 6, 8, 12, 16, 20, 24], // tight, finite — brutalist refuses to luxuriate
|
|
93
|
+
containerMax: "max-w-4xl", // ~896px — Hacker News column width is ~85ch; not full-bleed, not narrow
|
|
94
|
+
containerPadding: "px-3 lg:px-4",
|
|
95
|
+
sectionPadding: {
|
|
96
|
+
hero: "pt-6 pb-4 lg:pt-8 lg:pb-6", // there is no hero — first paragraph is the hero
|
|
97
|
+
default: "py-6 lg:py-8",
|
|
98
|
+
tight: "py-3 lg:py-4",
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
radius: {
|
|
103
|
+
base: "0", // sharp corners only — pills disallowed
|
|
104
|
+
pillsAllowed: false,
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
shadows: {
|
|
108
|
+
style: "none",
|
|
109
|
+
utilities: {
|
|
110
|
+
"border-1px":
|
|
111
|
+
"inset 0 0 0 1px hsl(var(--border))", // the only utility — literally a 1px border, the default table rule
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
motion: {
|
|
116
|
+
easing: "cubic-bezier(0.22, 1, 0.36, 1)", // unused in practice; kept for schema parity
|
|
117
|
+
durations: {
|
|
118
|
+
reveal: 0, // no entrance animations
|
|
119
|
+
loop: 0, // no loops
|
|
120
|
+
ambient: 0, // no ambient motion
|
|
121
|
+
},
|
|
122
|
+
keyframes: {}, // intentionally empty — brutalist rejects ambient motion entirely
|
|
123
|
+
respectsReducedMotion: true, // honored, but there is nothing to reduce
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
density: "high",
|
|
127
|
+
|
|
128
|
+
patterns: {
|
|
129
|
+
button:
|
|
130
|
+
"Underlined text links only — primary, secondary, and CTA all render as <a> with underline. " +
|
|
131
|
+
"Solid filled buttons are antithetical to brutalist. The one exception: form submits MAY render as the " +
|
|
132
|
+
"default browser button (<input type=submit>) — that is, [submit] — because honoring the browser default " +
|
|
133
|
+
"is on-direction.",
|
|
134
|
+
card:
|
|
135
|
+
"1px solid black border, no fill differentiation from background, no shadow, no radius. " +
|
|
136
|
+
"Internal padding is tight (p-3 lg:p-4). Title is bold body weight — no display face, no size jump beyond ~1.125x.",
|
|
137
|
+
input:
|
|
138
|
+
"Full 1px black box (border, not bottom-only), no radius, system font, 16px. " +
|
|
139
|
+
"Label is a plain <label> above the field. No placeholder-as-label. Focus is the browser default ring.",
|
|
140
|
+
cta:
|
|
141
|
+
"Underlined text link in `--link-blue` (or `--primary` for the loud one). Never a chip, never a rect, never a gradient. " +
|
|
142
|
+
"Visited links use `--visited-purple` — intentional.",
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
details: {
|
|
146
|
+
selectionBg: "hsl(var(--primary) / 0.3)", // HN-orange highlight on selection — the only place orange touches body text
|
|
147
|
+
selectionFg: "hsl(var(--foreground))",
|
|
148
|
+
focusRing: "2px solid hsl(var(--ring))", // 2px solid — close to the browser default, not minimized away
|
|
149
|
+
scrollbarStyle: "auto", // browser default — brutalist does not restyle the scrollbar
|
|
150
|
+
},
|
|
151
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Design Direction — Business-Tiles
|
|
2
|
+
|
|
3
|
+
## Ethos
|
|
4
|
+
SAP Fiori 3 principles · Fiori tile dashboards · S/4HANA enterprise utility · 72-typeface humanism · process-friendly enterprise
|
|
5
|
+
|
|
6
|
+
## Feel
|
|
7
|
+
Enterprise productivity that doesn't feel hostile. SAP's iconic Fiori tile dashboard pattern. Soft cool-gray backgrounds, SAP-blue signal color, friendly rounded utility. Reads as "ERP that's actually been used by humans recently." The opposite of stuffy enterprise — process-aware but approachable.
|
|
8
|
+
|
|
9
|
+
## Reference brands
|
|
10
|
+
- **SAP Fiori 3** → the tile-dashboard design language. Cool-gray canvas, SAP blue accent, white tiles, hairline borders.
|
|
11
|
+
- **S/4HANA** → SAP's flagship ERP — the marketing register for enterprise utility made approachable.
|
|
12
|
+
- **SAP Ariba** → procurement screens. Tables, line items, approval workflows.
|
|
13
|
+
- **SAP Concur** → expense surfaces. Forms over rigid workflow, made friendlier than spreadsheet-era enterprise.
|
|
14
|
+
- **SAP Build Apps** → low-code tooling. Tile-first information architecture, process-aware composition.
|
|
15
|
+
|
|
16
|
+
## Brand-book customization
|
|
17
|
+
Fiori is one of the most opinionated enterprise systems in the world; this direction ships as a faithful open-source approximation, with explicit hooks for licensed SAP customers to swap in their own brand assets.
|
|
18
|
+
|
|
19
|
+
### SAP72 typeface licensing
|
|
20
|
+
SAP's proprietary type family is **72** (sometimes referenced as **SAP72**). It is **not free**: it ships with SAP products under SAP's own license terms and is not available on Google Fonts or in commercial font-licensing marketplaces under that name. This direction ships with **Inter** as the open-source fallback — Inter is the closest widely-available humanist sans and matches 72's rhythm closely enough that screens read on-brand to non-SAP users.
|
|
21
|
+
|
|
22
|
+
**For SAP customers:** if your organization has a 72 license (typically bundled with SAP UI5 / Fiori Launchpad entitlements), swap 72 into the font stack ahead of Inter in `tokens.ts` and `src/index.css`. The fallback chain (`"72", "SAP72", ...`) is already wired so installing the licensed face locally activates it without code changes. Do **not** redistribute 72 in a public web build for non-SAP customers — host it on an authenticated origin or behind a customer-only CDN.
|
|
23
|
+
|
|
24
|
+
### Override hooks
|
|
25
|
+
- **Corporate brand color** → override `--primary` as an HSL triple. SAP blue (`218 100% 35%`) is the default; SAP partners (Magenta Telekom, Allianz, Mercedes) typically substitute their own corporate signal here. The focus ring, selection background, and emphasized CTA gradient all derive from `--primary`, so a single token swap re-themes the whole surface.
|
|
26
|
+
- **Tile chrome** → `--tile-bg` (default `0 0% 100%`) and `--tile-border` (default `213 14% 86%`) control every dashboard tile. To dial in a darker dashboard register (Fiori Quartz Dark equivalent), drop tile-bg lightness and lift tile-border accordingly.
|
|
27
|
+
- **SAP product modules** — each SAP suite product carries a Fiori variant accent color, documented in SAP's design specs. Map them to brand tokens or scope-local overrides as needed:
|
|
28
|
+
- **Ariba** → procurement orange. Map to `--accent-orange` or override `--accent` on Ariba-scoped screens.
|
|
29
|
+
- **Concur** → travel/expense teal. Override `--accent` on Concur-scoped screens; `--info-blue` is the next-closest default.
|
|
30
|
+
- **SuccessFactors** → HR violet. Add a `--sf-violet` brand token and route it through the accent surface on HR-scoped screens.
|
|
31
|
+
- **Fieldglass** → contingent-workforce magenta. Add as `--fg-magenta` brand token, treat like SuccessFactors.
|
|
32
|
+
- **Customer Experience (CX)** → SAP blue, unchanged.
|
|
33
|
+
The default direction stays in SAP-blue-canonical territory; product-specific accents are opt-in via scoped CSS variables, not by re-theming the whole token set.
|
|
34
|
+
|
|
35
|
+
## Tokens
|
|
36
|
+
HSL triples in `src/index.css`. Surface stack: `--background` (`213 14% 95%`, Fiori cool-gray canvas) sits *below* `--card` / `--tile-bg` (`0 0% 100%`, white tile) — the inversion-from-dark-themes is intentional and is the visual signature of Fiori. Depth comes from the canvas-to-tile lightness gap plus a 1px `--tile-border` and the `.shadow-tile` utility.
|
|
37
|
+
|
|
38
|
+
Brand tokens:
|
|
39
|
+
- `--tile-bg` — Fiori tile surface (white).
|
|
40
|
+
- `--tile-border` — Fiori tile hairline border, structural at dashboard density.
|
|
41
|
+
- `--info-blue` (`200 100% 42%`) — Fiori info blue, links, informational chips.
|
|
42
|
+
- `--accent-orange` (`28 100% 50%`) — Fiori warning orange, in-progress workflow states.
|
|
43
|
+
- `--success-green` (`140 50% 40%`) — Fiori success green, positive semantic state.
|
|
44
|
+
- `--sap-blue` — alias for `--primary`, used in marketing surfaces where the brand name is invoked literally.
|
|
45
|
+
|
|
46
|
+
Semantic discipline:
|
|
47
|
+
- **SAP blue** — primary, links, active state, focus.
|
|
48
|
+
- **Success green** — successful posting, approved, completed.
|
|
49
|
+
- **Accent orange** — warning, in-progress, awaiting approval.
|
|
50
|
+
- **Destructive red** — error, rejected, destructive actions.
|
|
51
|
+
- **Info blue** — informational, neutral notification.
|
|
52
|
+
|
|
53
|
+
## Typography
|
|
54
|
+
- **Display:** Inter, weights 400/500/600/700. Stand-in for SAP 72. H1 uses `clamp(1.5rem, 3vw, 2.25rem)` — restrained, because ERP body is the work.
|
|
55
|
+
- **Body:** Inter, 14px (`0.875rem`), line-height 1.5, tracking `0`. Fiori is high-density and body-first.
|
|
56
|
+
- **Mono:** JetBrains Mono, weights 400/500. Used for document numbers, GL accounts, posting keys, purchase order IDs.
|
|
57
|
+
|
|
58
|
+
Font features: `"tnum", "ss01"` — tabular figures for financial tables, Inter stylistic set 01 for the closer-to-72 letterforms.
|
|
59
|
+
|
|
60
|
+
## Spacing
|
|
61
|
+
- **Container:** `max-w-screen-2xl px-4 lg:px-6` — wide; Fiori dashboards claim the screen.
|
|
62
|
+
- **Section padding tiers:**
|
|
63
|
+
- Hero (rare on ERP surfaces): `pt-10 pb-8 lg:pt-14 lg:pb-10`
|
|
64
|
+
- Default: `py-8 lg:py-12`
|
|
65
|
+
- Tight: `py-4 lg:py-6`
|
|
66
|
+
- **Allowed scale:** **2** 4 6 8 10 12 16 20 24 32 40 48 64. The `2` step exists for icon-to-label gaps inside tiles and table cells.
|
|
67
|
+
|
|
68
|
+
High density. The reference is the Fiori Launchpad tile grid and S/4HANA work-list screens, not a marketing page.
|
|
69
|
+
|
|
70
|
+
## Color
|
|
71
|
+
No hex anywhere. Pure black is forbidden (`--foreground` is `220 35% 22%`, a deep slate). Pure white *is* used for `--tile-bg` — this is Fiori canon: white tiles on a cool-gray canvas, not card-on-card-on-card. The blue bias in the gray (`213 14% 95%`) reads as enterprise / data / process, not as warm-luxury or cold-medical.
|
|
72
|
+
|
|
73
|
+
## Radius
|
|
74
|
+
`--radius: 0.25rem` (4px). **Fiori tile radius — modest, productivity-grade.** Pills are allowed (`pillsAllowed: true`) for status chips, severity badges, and document-type tags — SAP convention. Avoid larger radii: anything above 6px reads as consumer/marketing, not ERP.
|
|
75
|
+
|
|
76
|
+
## Shadows
|
|
77
|
+
Style is **"soft"**. Three utilities:
|
|
78
|
+
- `.shadow-tile` — `0 1px 2px hsl(220 35% 22% / 0.06), 0 1px 1px hsl(220 35% 22% / 0.04)`. The default tile drop on the cool-gray canvas.
|
|
79
|
+
- `.shadow-tile-hover` — lifts on hover; the canonical Fiori tile interaction. `0 4px 8px ..., 0 2px 4px ...`.
|
|
80
|
+
- `.shadow-tile-focus` — `0 0 0 2px hsl(var(--primary) / 0.4)`. Focus ring as shadow for the keyboard-driven tile grid.
|
|
81
|
+
|
|
82
|
+
Soft, restrained, productivity-grade. No marketing elevation stacks; no glow.
|
|
83
|
+
|
|
84
|
+
## Motion
|
|
85
|
+
- **Easing:** `cubic-bezier(0.22, 1, 0.36, 1)`
|
|
86
|
+
- **Duration tiers:** reveal **200ms** (entry), exit **150ms**, ambient 0 (no ambient motion). Business-paced — not theatrical, not snappy.
|
|
87
|
+
- **Keyframes:**
|
|
88
|
+
- `fade-in` (200ms) — entry fade for tiles, popovers, menus, dialog content.
|
|
89
|
+
- `tile-lift` (200ms) — small Y-translate + opacity on tile hover/load. The signature Fiori gesture.
|
|
90
|
+
- `fade-out` (150ms) — exit fade for popovers, menus, dismissed dialogs.
|
|
91
|
+
|
|
92
|
+
**Deliberate, business-paced.** No bounce, no spring, no parallax, no ambient drift. `prefers-reduced-motion` honored throughout.
|
|
93
|
+
|
|
94
|
+
## Component patterns
|
|
95
|
+
- **Buttons:** primary = solid SAP blue, white text, 4px radius, weight 600. Secondary = ghost with input border. **Emphasized** = filled SAP blue with subtle top-to-bottom gradient — reserved for the single most important action on a process screen (Submit, Post, Approve, Release). Sizes: small (`h-7 px-2.5 text-xs`) and default (`h-8 px-3 text-sm`).
|
|
96
|
+
- **Cards (Fiori tiles):** `rounded-sm` (4px), `bg-tile-bg` (white), 1px `tile-border`, `.shadow-tile` drop. Tight padding (`p-4 lg:p-5`). Tile header uses a bottom hairline. Hover lifts to `.shadow-tile-hover`; focus uses `.shadow-tile-focus`.
|
|
97
|
+
- **Inputs:** compact (`h-8 text-sm`), 1px input border, `bg-tile-bg`, `rounded-sm`. Focus uses a 2px SAP-blue ring (Fiori expects a visible keyboard ring; this is the only direction in the library that doesn't go 1px). Inline validation in destructive red; warning orange for in-progress process state.
|
|
98
|
+
- **CTAs:** primary = SAP-blue button. Secondary = ghost. Emphasized = gradient SAP-blue, one per process screen. Marketing-style double-CTAs do not exist in this language — ERP screens have one verb.
|
|
99
|
+
|
|
100
|
+
## Component families
|
|
101
|
+
**Fiori tiles** (`*Tile`, `*KPITile`, `*LaunchpadTile`): the signature pattern. White rectangle, 4px radius, hairline border, soft drop, hover lift. KPI tiles render a label, a large numeric value (tabular figures), and a small trend indicator or icon. Launchpad tiles render an icon + label + count badge.
|
|
102
|
+
|
|
103
|
+
**Process pills** (`*StatusPill`, `*WorkflowBadge`): rounded-full, text-xs, semantic bg + fg. Green for completed, accent-orange for in-progress, destructive for rejected, info-blue for informational, muted for draft.
|
|
104
|
+
|
|
105
|
+
**Data tables** (`*Table`, `*WorkList`): tabular figures, mono numeric columns, `border-collapse`, 1px row borders matching `--tile-border`. Header row uses muted-foreground; selected row uses a faint primary tint (`hsl(var(--primary) / 0.08)`).
|
|
106
|
+
|
|
107
|
+
## Recommended rich media
|
|
108
|
+
SAP-Fiori is **dashboard-heavy and process-diagram-heavy**, with **conservative business photography** when humans appear at all. The aesthetic is "the screen at 11am on Tuesday at a Fortune 500 finance department" — not lifestyle, not marketing.
|
|
109
|
+
|
|
110
|
+
**Hero media:**
|
|
111
|
+
- **Dashboard tile screenshots** — real Fiori Launchpad captures or close approximations. White tiles on cool-gray canvas, clear KPI hierarchy. Present frankly: no decorative crop, no shadow stack.
|
|
112
|
+
- **KPI cards** rendered inline — large tabular numeric, trend indicator, label, period. Use the brand semantic palette (success green up, destructive red down, accent orange flat-but-attention).
|
|
113
|
+
- **Process-flow diagrams** — SAP's "happy path" workflow visualization: numbered steps, swimlanes for roles (Requester → Approver → Buyer → Finance), arrow connectors. Two-to-three color: SAP blue for steps, accent orange for in-progress, success green for completion.
|
|
114
|
+
- **Conservative business photography** — people in offices, at meetings, at desks. **Not** lifestyle, not airy startup photography, not laptops-in-coffee-shops. The register is "annual report photo," not "Series-B landing page." Neutral office interiors, business-formal or smart-casual attire, real conference-room lighting.
|
|
115
|
+
|
|
116
|
+
**AI tool recommendations:**
|
|
117
|
+
- **Recraft** — primary recommendation for **tile illustrations** ("flat illustration of a procurement workflow, two-color SAP blue and accent orange, white background, simple line icons, no shadows"). Recraft's flat-illustration capability matches Fiori's icon-illustration register exactly.
|
|
118
|
+
- **Excalidraw** — process-flow diagrams when a hand-drawn-but-precise feel works.
|
|
119
|
+
- **Mermaid** — declarative process flow and BPMN-lite diagrams that update with the code.
|
|
120
|
+
- **Carbon (carbon.now.sh)** — only if rendering code snippets (rare in Fiori surfaces; ERP screens don't usually show code).
|
|
121
|
+
|
|
122
|
+
**Avoid heavy photography.** Fiori surfaces are dashboards first; photography appears only on marketing landing pages and customer-story sections. When photography does appear, it should be conservative business documentary, not lifestyle. **No** stock-photo handshakes, **no** abstract glass-tower architecture shots, **no** smiling-headset call-center photos.
|
|
123
|
+
|
|
124
|
+
**Aspect ratios:** 16:9 for dashboard captures and process diagrams; 4:3 for documentation screenshots; 3:2 for business photography (matches editorial-photo conventions); natural aspect for KPI inline media.
|
|
125
|
+
|
|
126
|
+
**Performance:** SVG diagrams inline (≤8 KB each); screenshots ≤120 KB AVIF at 1.5x device pixel ratio; photography ≤200 KB AVIF. LCP target <1.5s — Fiori users run these surfaces on locked-down corporate networks and Citrix sessions.
|
|
127
|
+
|
|
128
|
+
**Avoid:** lifestyle photography, gradient meshes, glassmorphic anything, autoplay video, 3D product renders, purple/pink gradients, decorative SVG ornament, lens flare, dark-mode marketing aesthetic, AI-generated photorealistic humans, anything that signals consumer/startup/AI-fad rather than ERP/process/Fortune-500.
|
|
129
|
+
|
|
130
|
+
**Accessibility:** WCAG AA on `213 14% 95%` background requires foreground at `220 35% 22%` (well above AA). SAP blue on tile white passes AA at all sizes. Color-coding (green/orange/red/blue) needs a non-color signal (icon, text label) — colorblind users matter especially in process screens where status conveys workflow position.
|
|
131
|
+
|
|
132
|
+
## Details
|
|
133
|
+
- **Selection:** `hsl(var(--primary) / 0.2)` background, foreground text — SAP blue tint, subtle.
|
|
134
|
+
- **Focus ring:** `2px solid hsl(var(--ring))` — Fiori is keyboard-friendly and the ring should be visible; this is the only direction in the library that goes 2px instead of 1px.
|
|
135
|
+
- **Scrollbar:** auto — Fiori respects the OS scrollbar convention (Windows enterprise machines expect the system scrollbar).
|
|
136
|
+
|
|
137
|
+
## Exceptions
|
|
138
|
+
None yet. Add intentional violations here (e.g., a darker Fiori Quartz Dark variant for night-shift operations centers, or a customer-branded theme that swaps `--primary` to a corporate signal color).
|
|
139
|
+
|
|
140
|
+
## Revisions
|
|
141
|
+
- Initial direction, generated at install time. Authored as the ERP-suite counterpart to the dense-utility (developer-tools) and enterprise-tech (semiconductor/infrastructure) directions — Fiori covers the process-aware, dashboard-tile, ERP register that those don't.
|