| name | design-system |
| description | Dual-theme design system (French Brutalism dark + Japanese Minimalism light) for public-facing pages. Reference this when building new pages/components to ensure consistency. Admin pages may vary. |
Design System
Dual-theme system: French Brutalism (Dark) + Japanese Minimalism (Light)
Quick Reference
Framework: Tailwind CSS v4 (@tailwindcss/forms, @tailwindcss/typography)
Fonts: System stack | Noto Sans JP (100-400) | Cormorant Garamond (300-400)
Font Weights: Dark: 400-700 | Light: 100-300
Breakpoint: 768px (mobile) | 1200px (desktop compact)
Transitions: 0.2s-0.3s ease | Cards: 0.4s cubic-bezier(0.4, 0, 0.2, 1)
Text Style: Uppercase + letter-spacing: 0.1em (all UI elements)
Opacity: Default: 0.7 | Hover: 1.0 | Labels: 0.8 | Placeholders: 0.3
Color System
/* Dark Mode - French Brutalism */
--bg-primary: #000000
--text-primary: #ffffff
--text-secondary: #cccccc
--text-tertiary: #808080
--border-subtle: rgba(255, 255, 255, 0.15)
--border-active: rgba(255, 255, 255, 0.4)
/* Light Mode - Japanese Minimalism */
[data-theme='light']
--bg-primary: #ffffff
--text-primary: #000000
--text-secondary: #666666
--text-tertiary: #999999
--border-subtle: rgba(0, 0, 0, 0.08)
--border-active: rgba(0, 0, 0, 0.2)
Accent Colors (Charts/Data Viz):
Blue rgba(59, 130, 246, 0.9) | Purple rgba(168, 85, 247, 0.9) | Green rgba(34, 197, 94, 0.9) | Yellow rgba(234, 179, 8, 0.9) | Red rgba(239, 68, 68, 0.9) | Pink rgba(236, 72, 153, 0.9)
Typography
| Element | Size | Letter Spacing |
|---|---|---|
| Hero names | clamp(2.5rem, 6vw, 5rem) |
0.15em (dark) / 0.2em (light) |
| Page headers | clamp(1.5rem, 4vw, 2.5rem) |
0.1em |
| Body text | 1rem | 0.05em |
| Inputs/buttons | 0.875rem | 0.1em |
| Nav/labels | 0.75rem | 0.1em |
| Badges | 0.625rem | 0.05em |
| Chart text | 9-11px | - |
Font Weights (Critical):
/* Dark mode: bolder for contrast */
:global([data-theme='dark']) .element { font-weight: 400-700; }
/* Light mode: lighter for elegance */
:global([data-theme='light']) .element { font-weight: 100-300; }
Text Transform: Uppercase for all headings, buttons, nav, table headers
Spacing Scale
| Type | Value | Usage |
|---|---|---|
| Page Padding | ||
| Large pages | 6rem 2rem 4rem 2rem |
Top breathing room |
| Landing | 4rem 2rem 2rem |
Standard pages |
| Mobile | 3.5rem 1rem 2rem |
Small screens |
| Component Gaps | ||
| Sections | 3.5rem | Large spacing |
| Grids | 3rem | Card layouts |
| Nav/controls | 2rem | Medium spacing |
| Compact | 1rem | Tight elements |
| Toasts | 0.75rem | Stacked items |
| Element Padding | ||
| Table cells | 1rem | Standard |
| Inputs | 0.75rem 1rem |
Form fields |
| Buttons | 0.5rem 2rem |
CTAs |
| Toasts | 0.875rem 1.25rem |
Notifications |
Container Widths: 1200px (main) | 400px (inputs/mobile cards) | 320px (desktop cards) | 240px (compact cards)
Component Patterns
Buttons
Primary CTA (Outlined):
- Transparent background, uppercase,
letter-spacing: 0.1em - Dark:
border: 1px solid #fff, hover inverts to white bg/black text - Light:
border: 0.5px solid #000, font-weight: 200, hover inverts padding: 0.75rem 2rem; transition: all 0.3s ease;
Text Button/Link:
- No background/border,
opacity: 0.7, hover to1.0 font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.1em;
Cards
Feature Card:
height: 420px; padding: 3rem 2rem; background: var(--bg-primary);- Dark:
border: 1px solid rgba(255,255,255,0.3), hover0.4 + shadow - Light:
border: 1px solid rgba(0,0,0,0.15), hover0.2 + shadow - Hover:
transform: translateY(-4px); transition: all 0.4s cubic-bezier(0.4,0,0.2,1);
Forms
Text Input:
background: transparent; border: 1px solid var(--border-subtle);- Focus:
border-color: var(--border-active); - Placeholder:
opacity: 0.3;
Select:
- Same as input +
text-transform: uppercase; letter-spacing: 0.05em; - Dark options:
background: #1a1a1a;
Tables
Leaderboard:
- Wrapper:
border: 1px solid var(--border-subtle); overflow-x: auto; - Headers:
font-size: 0.75rem; text-transform: uppercase; opacity: 0.8; - Rows:
border-bottom: 1px solid var(--border-subtle); - Hover:
opacity: 0.8; transition: opacity 0.15s;
Toasts
- Fixed
bottom: 2rem; left: 2rem; z-index: 9999; padding: 0.875rem 1.25rem; border: 1px solid;- Dark:
border-color: rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); - Light:
border-color: rgba(0,0,0,0.2); background: rgba(0,0,0,0.05); font-weight: 200; - Animation:
slideIn 0.3s ease-out(translateX from -100%)
Dropdowns
position: absolute; background: var(--bg-primary); border: 1px solid var(--border-subtle);- Items:
padding: 0.75rem 1rem; opacity: 0.8;, hoveropacity: 1 + background: var(--border-subtle);
Layout Patterns
Grid (Feature Cards):
display: grid;
grid-template-columns: repeat(3, 320px); /* 240px @ <1200px */
gap: 3rem; /* 2rem @ <1200px */
Flex (Page Header):
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 3rem;
padding-bottom: 1rem;
border-bottom: 1px solid rgba(255,255,255,0.1);
Centered Content:
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
Breakpoints:
@media (max-width: 768px): Stack vertically, reduce padding (1rem), hide non-critical table columns@media (max-width: 1200px): Compact grid (240px cards, 2rem gap)
Animations
Standard Pattern:
@keyframes fadeInCard {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* Usage */
animation: fadeInCard 0.4s ease-out forwards;
animation-delay: 0.5s; /* Optional */
Common Animations:
fadeIn: opacity 0→1 (hero: 2s, links: 1s with 0.5s delay)fadeInCard: opacity + translateY for cards (0.4s)slideIn: translateX(-100%) for toasts (0.3s)
Always include:
@media (prefers-reduced-motion: reduce) {
.element { animation: none; opacity: 1; transform: none; }
}
Theme Implementation
HTML attribute: <html data-theme="dark"> or "light"
Persistence (app.html):
(function() {
const theme = localStorage.getItem('theme') || 'dark';
document.documentElement.setAttribute('data-theme', theme);
})();
Styling pattern:
:global([data-theme='dark']) .element { /* dark styles */ }
:global([data-theme='light']) .element { /* light styles */ }
Design Philosophy
French Brutalism (Dark Mode)
Pure black (#000) backgrounds, white text, heavy weights (400-700), stark borders (0.3-0.4 opacity), system fonts, geometric precision
Japanese Minimalism (Light Mode)
Pure white (#fff) backgrounds, black text, light weights (100-300), subtle borders (0.08-0.2 opacity), Noto Sans JP influence, generous negative space
Shared Principles
Uppercase typography with generous letter-spacing, smooth transitions (0.2-0.4s), mobile-first responsive, reduced motion support, transparent backgrounds with borders
Critical Patterns
- Theme-specific font weights - Dark: 400-700 | Light: 100-300
- Always use CSS variables -
var(--bg-primary),var(--text-primary), etc. - Uppercase UI text -
text-transform: uppercase; letter-spacing: 0.1em; - Theme-specific borders - Use
:global([data-theme='...'])pattern - Rem-based spacing - Multiples of 0.5rem or defined patterns above
- Mobile breakpoint: 768px - Stack layouts, reduce padding, adjust fonts
- Interactive opacity - Default: 0.7 | Hover: 1.0
- Standard transitions -
0.2s easeor0.3s ease(cards:0.4s cubic-bezier) - Reduced motion support - Always include
@media (prefers-reduced-motion: reduce) - Transparent backgrounds - Most components use
background: transparentwith borders
See reference.md for full component code examples.