# DESIGN.md — tokeny projektu · Akademia Claude CFS / Moduł M3

> Kontrakt wykonania dla kontra-build. Brief = CO i DLACZEGO (`brief.md`). To = ILE.
> Paleta ŹRÓDŁOWA zablokowana przez usera (2026-07-14) na markę CFS — wartości niżej to PRZELICZENIE
> na OKLCH + korekty tam, gdzie oryginalny hex nie przechodził WCAG AA w typowym parowaniu. Kotwica
> `--green-500` MUSI pozostać pikselowo identyczna z `#35BA81`.
>
> **v2 — PIVOT 2026-07-14.** Brief v1 (motyw szlabanu) odrzucony przez usera. Kolor i typografia
> ZOSTAJĄ bez zmian (nie były przedmiotem odrzucenia). Zmiany w tym pliku: usunięta specyfikacja
> ruchu belki szlabanu (§5, zastąpiona opisem demo replikującego realny UI zgody), dodane tokeny
> szerokości/marginaliów pod poszerzony layout (§3), zaktualizowana lista zakazów (§6).

---

## Meta
- Projekt: CFS / Akademia Claude — moduł M3
- Wersja DESIGN: v2 (pivot layoutu i ruchu; kolor/typografia = v1)
- Źródło palety: marka klienta (carflowsystem.pl), zablokowana przez usera — NIE z bazy ui-ux-pro-max.
  Źródło typografii: `uiux-data/scripts/search.py --domain typography` (patrz brief §7, weryfikacja
  ponowna w v2 przeciw alternatywom — Space Grotesk + Source Sans 3 potwierdzone jako najlepszy wybór).

## 1. Kolor — prymitywy OKLCH (L zmienna, C i H stałe per rodzina)

### Zielony (marka, kotwica na 500)
`C = 0.142, H = 160.3`

| Token | OKLCH | Hex (referencja) | Użycie |
|---|---|---|---|
| `--green-50` | `oklch(97.5% 0.020 160.3)` | ~#E4F7EE | tło wyróżnień, tint |
| `--green-100` | `oklch(93.5% 0.045 160.3)` | ~#C6EDDA | hover na tle jasnym |
| `--green-200` | `oklch(87% 0.075 160.3)` | ~#98DDBB | obwódki aktywne |
| `--green-300` | `oklch(80% 0.105 160.3)` | ~#66CC9C | — |
| `--green-400` | `oklch(75% 0.128 160.3)` | ~#45C28A | — |
| **`--green-500`** | **`oklch(70.4% 0.142 160.3)`** | **`#35BA81`** | **KOTWICA — marka, dokładny hex** |
| `--green-600` | `oklch(60.1% 0.120 160.5)` | `#2A9668` | hover/naciśnięcie CTA |
| `--green-700` | `oklch(54% 0.107 160.2)` | ~#237E58 | tekst-na-jasnym wysoki kontrast |
| `--green-800` | `oklch(48.1% 0.095 160.0)` | `#1F6E4B` | tło z BIAŁYM tekstem (6.19:1 AA) |
| `--green-900` | `oklch(38% 0.075 159.8)` | ~#175339 | inwersja / dark mode (jeśli potrzebne) |

### Neutralne (ink/graphite/silver — achromatyczne lub prawie)
| Token | OKLCH | Hex | Użycie |
|---|---|---|---|
| `--ink` | `oklch(23.1% 0.019 172.0)` | `#14201C` | `--text-primary`, 16.76:1 na bg |
| `--graphite` | `oklch(26.8% 0.012 178.5)` | `#202826` | `--surface-inverse` (sekcje ciemne) |
| `--muted` | `oklch(56.6% 0.019 173.6)` | `#6B7A75` | `--text-muted` — 4.50:1 na białym, GRANICA AA: używaj ≥16px regular lub 14px/600+ |
| `--aluminium` | `oklch(72.2% 0.000 89.9)` | `#A5A5A5` | linie/ramki/materiał — NIGDY tekst na jasnym tle |
| `--line` | `oklch(92.6% 0.008 164.9)` | `#E2E8E5` | `--border-subtle` |
| `--bg-soft` | `oklch(97.7% 0.002 165.1)` | `#F6F8F7` | `--surface-canvas` |
| `--bg` | `oklch(99% 0 0)` | `#FEFEFE` | `--surface-page` — off-white, NIGDY #FFFFFF czysty |

### Statusy (semantyka §2.1 spec zachowana, hex korygowane pod AA)
| Token | OKLCH | Hex | Kontrast tekst | Użycie |
|---|---|---|---|---|
| `--status-success` | = `--green-500`/`600` | `#35BA81`/`#2A9668` | ink 6.78:1 na 500 | „ukończony" moduł |
| `--status-warning` | `oklch(75.5% 0.157 78.3)` | `#E5A100` | ink 7.52:1 | „w trakcie" / moduł obowiązkowy |
| `--status-info` | `oklch(60.9% 0.182 257.3)` | `#2F80ED` | **żaden tekst nie zdaje 4.5:1** (biały 3.87, ink 4.33) | TYLKO obrys/ikona/lewy pasek — nie wypełnienie z tekstem |
| `--status-info-fill` | `oklch(50% 0.170 257.3)` | ~#1E63C4 *(przybliżenie, zweryfikuj w buildzie)* | biały tekst, cel ≥4.5:1 | wariant do użycia gdy potrzebne wypełnione tło z tekstem |
| `--status-danger` | `oklch(59.7% 0.182 24.5)` | `#D64545` | biały 4.38:1 (borderline, fail przy drobnym) | ikona/obrys/duży tekst |
| `--status-danger-text` | `oklch(51.8% 0.161 24.7)` | `#B23636` | biały 6.05:1 AA | badge wypełniony z tekstem |

Gradient: **NIE**. Zero gradientów dekoracyjnych — materiał to linia kierunkowa (SVG, opacity 4–8%,
`--aluminium` na `--bg-soft`), nie gradient.

## 2. Typografia

- **Display/Label:** `Space Grotesk` — waga 500 (H2/H3), 600–700 (kickery, liczby, H1 lekcji),
  tracking `-0.01em` na dużym display, `+0.04em` na kickerach uppercase, line-height 1.1–1.2.
- **Body:** `Source Sans 3` — waga 400 (tekst), 450/600 (wyróżnienia w tekście), line-height 1.6–1.75,
  miara 65–72ch.
- Skala (desktop), ratio ~1.25, baza 18px (podniesiona z 16 — czytelność dla zróżnicowanej kadry):
  - Kicker/label: `13px` / uppercase / tracking +0.04em (Space Grotesk 600)
  - Small/meta: `14px` / 1.5 (Source Sans 3 450)
  - Body: `18px` / 1.7 (Source Sans 3 400)
  - H3: `23px` / 1.3 (Space Grotesk 500)
  - H2: `29px` / 1.2 (Space Grotesk 500)
  - H1 (nagłówek lekcji): `clamp(28px, 3vw, 42px)` / 1.15 (Space Grotesk 600)
  - Display (rzadko, np. licznik na starcie): `clamp(42px, 5vw, 64px)` / 1.05 (Space Grotesk 700,
    `font-variant-numeric: tabular-nums`)
- Mobile: skaluj w dół ~85% wg zasady ze spec; NIGDY nie ukrywaj treści (memory
  `tekst-dopasowany-do-viewport`).
- Licencja: oba kroje open-source (SIL OFL), Google Fonts — zero ryzyka.

## 3. Przestrzeń

- Skala bazowa: wielokrotności 4px: `4 8 12 16 24 32 48 64 96 128`.
- Padding sekcji (pion) zmienny per akt: hub-start sekcje kafli `py-64`, widok lekcji bloki treści
  `py-32`/`py-48` między blokami tematycznymi, demo M3 w ramce własnej `py-48` (izolacja — „chwila
  skupienia" z rytmu w brief §2).
- Makro (między sekcjami) ≫ mikro (w grupie): makro `64–96px`, mikro `8–16px`.
- Kontener hub-start: `max-width: 1200px`.

### 3a. Layout widoku lekcji — marginalia (v2, NOWE — zastępuje wąski wycentrowany kontener z v1)

> v1 miał `min(68ch, 100% - 48px)` wyśrodkowane na pustym tle — user odrzucił jako „absurdalnie wąską
> kolumnę". Kolumna czytania ZOSTAJE ~70ch (to fizyczna granica czytelności tekstu, nie estetyka) —
> zmienia się WYŁĄCZNIE to, co dzieje się dookoła niej: margines staje się pracującym aparatem, nie
> pustką.

| Token | Wartość | Użycie |
|---|---|---|
| `--frame-max` | `min(1440px, 100% - 96px)` | ramka strony widoku lekcji, wyśrodkowana |
| `--reading-col` | `min(70ch, 100%)` | kolumna akapitów treści — TYLKO akapity, nie nagłówki |
| `--margin-col` | `260px` | prawa kolumna aparatu (numer-znak-wodny, status, „na tej stronie", nawigacja modułów) |
| `--frame-gap` | `64px`–`80px` (`clamp(64px, 6vw, 80px)`) | odstęp kolumna czytania ↔ margines-aparat |
| `--breakpoint-margin-stack` | `1100px` | poniżej tej szerokości margines-aparat spada POD treść jako pozioma belka meta (numer + status + kotwice w linii) — NIGDY nie znika |

- **Nagłówki i kickery MOGĄ przekraczać `--reading-col`** i rozciągać się w stronę marginesu (do
  `--frame-max`) — to jest miejsce oddechu typografii na pełnym viewporcie; akapity trzymają się
  ściśle `--reading-col`.
- Grid: `grid-template-columns: minmax(0, var(--reading-col)) var(--margin-col); gap: var(--frame-gap);`
  wewnątrz `--frame-max`.
- Znak-wodny numeru modułu (memorable element, brief §9): `clamp(120px, 14vw, 220px)`, Space Grotesk
  700, `font-variant-numeric: tabular-nums`, `color: var(--ink)`, `opacity: .06–.08`, pozycja: góra
  kolumny marginesu, `line-height: 0.9`, `user-select: none`, `aria-hidden="true"` (dekoracyjny wobec
  treści — informacja o numerze modułu istnieje już w tekście nagłówka, żywa dla czytnika ekranu).

## 4. Głębia

| Klasa | Radius | Cień/border |
|---|---|---|
| Kafel modułu (tabliczka) | `4px` | 1px `--aluminium` przy 40% opacity + delikatny górny highlight (`inset 0 1px 0 rgba(255,255,255,.4)`) — NIE `shadow-md` domyślny |
| Karta demo (ramka „przepływ zgody") | `8px` | 1px `--line` + tło `--bg-soft`, brak cienia (płasko, jak tabliczka techniczna) |
| Przycisk primary | `4px` | brak cienia, solid `--green-500` bg + `--ink` tekst (6.78:1) |
| Pole „Spróbuj sam" | `2px` | dashed 1px `--aluminium` — neutralna ramka pola do kopiowania promptu, zero ozdobnej ikonografii |
| Foto/media (jeśli pojawi się później) | `0` | świadomie ostre krawędzie — pasuje do dokumentacji technicznej |

## 5. Ruch

- **Główny moment (v2 — PRZEPROJEKTOWANY, bez belki szlabanu):** demo „przepływ zgody" (brief §9a) —
  panel repliki UI zgody: `opacity` + `transform: translateY(4px)→0`, duration `220ms`, easing
  `ease-out`, WYŁĄCZNIE sterowany klikiem usera (4-stanowa state machine:
  `czeka → prosi → zezwolono` / `prosi → odmówiono`). Log zdarzeń pod panelem: nowy wiersz wjeżdża
  `translateY(-4px)→0` + `opacity`, `160ms`.
- **Mikro-interakcje:** hover na kaflu modułu = `translateY(-2px)` + zmiana koloru obwódki na
  `--green-500`, `160ms ease-out`. Focus states: obrys `2px --green-600` offset 2px (widoczny,
  klawiaturowy — WCAG).
- **Zakaz:** `transition: all`, autoplay demo, animacja przy ładowaniu strony poza font-ready gate,
  JAKAKOLWIEK rotacja/opadanie elementu udającego mechanizm fizyczny (belka, klapka, zasuwka) — to
  jest trwały zakaz po odrzuceniu v1 (brief §12 pkt 3), nie tylko techniczny detal.
- **`prefers-reduced-motion`:** demo zgody przechodzi między stanami natychmiastowo (bez fade/translate),
  hover-lift wyłączony, wszystkie `transition` → `none`.

## 6. Zakazy (avoid-list dla tego projektu)

- **Jakikolwiek wymyślony mechanizm-metafora (szlaban, bramka, klucz, zamek, brama, filtr) jako motyw
  wizualny — ZAKAZ TRWAŁY po odrzuceniu v1** (brief §12 pkt 3). Nie tylko usunięcie belki szlabanu —
  zakaz obejmuje KAŻDY nowy zamiennik tego typu. Charakter wyłącznie przez typografię/marginalia/
  materiał.
- Wycentrowana, samotna kolumna `min(68ch)` na pustym tle bez zaprojektowanego marginesu — ZAKAZ
  (brief §5, §12 pkt 5) — layout MUSI używać systemu marginaliów `--margin-col`/`--frame-max` (§3a).
- Space Grotesk w rejestrze „kinetic brutalism" (uppercase hero 80px+, tracking mocno ujemny na
  ogromnym display) — ZAKAZ, patrz brief §7/§12 pkt 4. Display trzymany mały i spokojny.
- Centered hero / SaaS funnel — układ to Archival index (H10), nie wycentrowany hero.
- Grid identycznych kart z ikoną w kółku — kafle modułów różnicowane statusem (kolor + etykieta), nie
  identyczne.
- Ikony kłódki/tarczy/checkmark-w-kółeczku jako symbol bezpieczeństwa — ZAKAZ; demo zgody to replika
  realnego UI (brief §9a), nie ikonografia.
- Confetti / emoji / „AI-powered" sparkle — ZAKAZ.
- Gradient wieloprzystankowy na CTA — ZAKAZ, solid `--green-500` + ink tekst.
- Czyste `#000000`/`#FFFFFF` — użyj `--ink`/`--graphite` i `--bg` (off-white `#FEFEFE`).
- `--status-info` (`#2F80ED`) jako wypełnienie plakietki z drobnym tekstem — użyj `--status-info-fill`
  albo samego obrysu/ikony.
- Anonimizowane placeholdery treści („Klient A", „kwota XXX") — ZAKAZ, brief v2 wymaga realnych danych
  biura CFS jako materiału dowodowego (brief §2, doktryna zgoda+zakres+operacje na polecenie).

## 7. Kotwica do briefu (v2 — po pivocie 2026-07-14)

- Parasol (1 zdanie): to nie metafora, to rejestr — Akademia czyta się jak precyzyjnie złożony
  wewnętrzny podręcznik techniczny firmy inżynierskiej; charakter bierze się z rygoru typografii,
  hierarchii i marginaliów, nie z wymyślonego mechanizmu.
- Akcent koloru skąd z treści: `--green-500` to dokładnie kolor marki/produktu CFS — nie dobrany
  dekoracyjnie, tożsamy z realną tożsamością wizualną klienta (bez odwołania do fabuły „bramki").
- 1 świadome odstępstwo od znanego wzorca: system marginaliów z dużym numerem-znakiem-wodnym modułu
  (§3a) zamiast wycentrowanej wąskiej kolumny — czytelność tekstu zachowana (70ch), reszta viewportu
  pracuje jako aparat redakcyjny, nie pustka.
