# Návrh C „Z Jizerek“: unikátní prvky

Prvky, které tento návrh odlišují od běžného webu řemeslníka. U každého: co to je, proč, anatomie, chování, data, přístupnost, omezený pohyb, implementace v Laravelu (Blade) a kde je v ukázce.

Sdílené chování (záložky, lightbox, výběr data, formulář, mapa, otevírací doba) je v `design/_shared/assets/js/common.js` a `coverage-map.js`. Vlastní JavaScript návrhu (`assets/js/main.js`) má jen tři drobnosti: houpnutí klíče, minimum data v kalendáři a zpoždění odhalování.

---

## 1. Svazek klíčů (výběr služeb)

**Co to je:** ilustrovaný kroužek na klíče (oranžový kroužek z loga, v perspektivě jako elipsa), ze kterého visí tři klíče: od dveří, od auta a od sejfu. Každý klíč je skutečné tlačítko záložky. Vedle je panel se službami a cenami vybrané kategorie.

**Proč:** člověk v nouzi myslí na to, *co* je zamčené, ne na název služby. Klíč je okamžitě čitelný symbol, kroužek z loga propojuje značku s obsahem a výběr je zábavný bez toho, aby zdržoval. Na hlavní stránce nahrazuje „tři stejné karty služeb“.

**Anatomie:**
- `.keyring` (container query kontejner) s `svg.keyring__ring` (elipsa, tah 9 px, `--c-accent`),
- `.keyring__keys[role=tablist]` se třemi `button.key[role=tab]`: `span.key__art` s inline SVG klíče + `span.key__label`,
- `.keys__card` s `[role=tabpanel]` (nadpis, řádky ceníku `.prices`) a patička „Ceny jsou orientační… / Celý ceník“.
- Geometrie: sloupce klíčů mají středy na 1/6, 1/2 a 5/6 šířky; horní okraj klíče je posunutý o `15.6cqi` (krajní) a `20cqi` (prostřední), aby otvor v hlavě klíče ležel přesně na elipse. Krajní klíče jsou v klidu natočené o ±5° (`--rest`).

**Chování a stavy:**
- Klik nebo šipky vlevo a vpravo (Home, End) přepnou záložku (`common.js`), panel se vymění.
- Vybraný klíč: oranžová čepička (`.f-cap`), tučný popisek s oranžovou linkou; nevybrané klíče mají čepičku v mlžné barvě.
- Při výběru se klíč zhoupne kolem bodu zavěšení (tlumené kmitání 1,1 s, `main.js` přidá `.is-swinging` přes MutationObserver na `aria-selected`). Klik na už vybraný klíč ho jen zhoupne.
- Hover: popisek ztmavne. Focus: obrys 3 px kolem celého sloupce.
- **Mobil (pod 720 px):** elipsa zmizí, klíče se změní na segmentový přepínač tří velkých tlačítek (malý klíč + popisek, radius 14 px, vybraný s oranžovým okrajem a `--c-accent-soft`). Ceny bez teček.

**Data:** kategorie a služby z administrace (tabulka služeb: název, kategorie, cena od/do nebo „po posouzení“, příznak „nejhledanější“ pro tučné zobrazení, pořadí). Motiv klíče je vlastnost kategorie (`door`, `car`, `safe`).

**Přístupnost:** WAI-ARIA tabs (`aria-selected`, `aria-controls`, `tabindex` spravuje `common.js`), SVG klíčů `aria-hidden`, název záložky je text popisku, panel má `tabindex="0"` a `aria-labelledby`. Cíle dotyku 44 px a víc.

**Omezený pohyb:** houpání se nespustí (`main.js` kontroluje `prefers-reduced-motion`), přepnutí je okamžité.

**Laravel:** komponenta `<x-keyring :categories="$categories" />`, každá kategorie `<x-keyring.key :motif="$category->motif" :label="$category->name" />` a panel `<x-price-list :services="$category->services" />`. SVG klíčů jako Blade partialy (`resources/views/components/illustrations/key-door.blade.php`), aby šly přebarvit tokeny.

**Kde:** `index.html`, sekce 2 „S čím vám pomůžu“; CSS `style.css` oddíl 9, SVG `_src/partials/key-*.html`.

---

## 2. Vrstevnice (generovaný vzor)

**Co to je:** jemný vzor vrstevnic jako na turistické mapě, generovaný procedurálně, bezešvá dlaždice 1200 × 800 s 15 hladinami a zdůrazněnou každou pátou vrstevnicí.

**Proč:** dodává plochám hloubku bez fotek a bez šumu a říká „znám terén, jsem odsud“. Je to místní textura místo generických přechodů.

**Anatomie:** `assets/img/topo.svg` (18 kB, jen tahy) použitý jako `mask-image` na pseudo-elementu `::before` s `background-color: var(--c-topo)`. V hero a hlavičkách kombinovaný s lineárním přechodem (`mask-composite: intersect`), aby levá strana s textem zůstala čistá.

**Chování:** statický, neanimuje se. Přebarví se automaticky v tmavém režimu (17 % smrkové ve světlém, 11 % v tmavém).

**Data:** generátor `_src/tools/topo.py` (numpy): periodický bílý šum filtrovaný gaussovsky ve frekvenční oblasti (protažený ve směru západ až východ jako hřbety Jizerek), marching squares s rozlišením sedel, spojení úseček, Ramer-Douglas-Peucker, vyhlazení Catmull-Rom do Bézierových křivek, drobné uzavřené „ostrůvky“ vynechané. Jiný vzor: `python3 _src/tools/topo.py <seed>`.

**Přístupnost:** čistě dekorativní (pseudo-element, `pointer-events: none`), kontrast textu nad vzorem se měří vůči pozadí stránky, vzor ho nesnižuje pod AA.

**Omezený pohyb:** netýká se.

**Laravel:** SVG do `resources/images/topo.svg`, v CSS `mask-image: url('../images/topo.svg')` (Vite přepíše cestu). Utilita `.topo` (oddíl 6) nebo Tailwind `@utility topo { … }`. SVG musí být ze stejné domény (maska vyžaduje CORS).

**Kde:** hero (`index.html`), hlavičky podstránek (`.page-head`), hero O mně, patička; CSS oddíly 6, 7, 13, 15, 18.

---

## 3. Karta otevírací doby přes ilustraci

**Co to je:** plovoucí karta, která přesahuje levý dolní roh rámu hero ilustrace: „Pohotovost: nonstop“ (velké, oranžový text), „Neakutní služby: denně 8:00 až 17:00“, denní osa 0 až 24 h a aktuální čas.

**Proč:** dvě otázky, které člověk v nouzi řeší hned: „Zvedne to teď?“ a „Kdy dělá běžné zakázky?“. Karta odpovídá na obě na první pohled a přesahem přes ilustraci vytváří hloubku (jediný prvek se stínem na stránce).

**Anatomie:** `aside.hours-card` ve `.hero__visual`; dva řádky `hours-card__row` (popisek vlevo, hodnota vpravo), `.dayline` (celá osa = pohotovost v oranžové, zvýrazněný úsek 8 až 17 h ve smrkové, svislá značka „teď“ na pozici `--now-fraction`), popisky 8:00 a 17:00, řádek „Teď je 14:32“ (`[data-now-time]`).

**Chování:** `common.js` každých 30 s nastaví `--now-fraction` a čas (Europe/Prague) a `html[data-hours]`. Na desktopu karta visí přes roh rámu (`translate: 0 62%`), na mobilu je pod ilustrací s negativním okrajem nahoru.

**Související prvek: stavová řádka.** Nad H1 je řádek s oranžovou tečkou a textem podle stavu (`[data-hours-text]`): „Teď je pracovní doba, volejte.“ / „Mimo pracovní dobu, ale na pohotovosti jsem.“ Tečka je jediný „živý“ indikátor webu (pulzující prstenec) a označuje skutečný stav: jsem na příjmu.

**Data:** otevírací doba z nastavení (pohotovost ano/ne, běžná doba od, do), v `common.js` konstanty `OPEN_FROM`, `OPEN_TO`.

**Přístupnost:** `aside` s `aria-label="Otevírací doba"`, osa je `aria-hidden` (informace je i textem), čas v `<time>`, tabulkové číslice.

**Omezený pohyb:** karta nevyjíždí, tečka nepulzuje.

**Laravel:** `<x-hours-card :hours="$settings->hours" />`, první vykreslení času na serveru (`now('Europe/Prague')`), aby nebylo vidět „--:--“.

**Kde:** `index.html` hero; kontakt má stavovou řádku v kartě „Kdy volat“. CSS oddíl 7.

---

## 4. Milníky jako turistická trasa

**Co to je:** tři doložitelné milníky (2019 začátek, 15. 12. 2024 kvalifikace Zámkař, 17. 12. 2024 živnostenské oprávnění) rozmístěné po tečkované turistické stezce, která mírně stoupá. Každý milník označuje čtvercová značka ve stylu KČT (bílá, oranžová, bílá; oranžová je barva značky, stylizovaný odkaz na turistické značení). Trasa končí rozcestníkem ve tvaru směrovky „Dnes: pohotovost nonstop“ s malou značkou v hrotu.

**Proč:** místo suché časové osy příběh cesty, který v Jizerkách každý zná z výletů. Stoupající profil říká „pořád jdu nahoru“, rozcestník „a tady jsem teď“. Data jsou reálná, z dokumentů.

**Anatomie:** `.trail-wrap` > `svg.trail__path` (výškový profil `.trail__ground` + tečkovaná stezka `.trail__line`, `preserveAspectRatio="none"`, `vector-effect: non-scaling-stroke`) + `ol.trail` se čtyřmi `li.trail__stop` (`span.kct`, `time.trail__date`, `p.trail__text`), poslední `li.trail__stop--now` s `.signpost` (`.signpost__board` > `.signpost__inner` s názvem, podtitulem a `.signpost__mark`, `.signpost__post`).
- Desktop (od 900 px): čtyři sloupce bez mezer, značky posunuté svisle podle proměnné `--y` (90, 74, 60, 44 px) tak, aby seděly na křivce; křivka prochází body x = 0, 250, 500, 750 (z 1000) a je posunutá o polovinu šířky značky.
- Mobil: svislá čárkovaná čára vlevo, značky na ní, rozcestník bez sloupku.

**Chování:** zastávky se odhalují postupně při scrollu (`[data-reveal-group]`, zpoždění po 90 ms).

**Data:** milníky z administrace (datum, přesnost „rok / den“, text, zvýrazněná část, volitelně odkaz na dokument v galerii), poslední „Dnes“ je text z nastavení.

**Přístupnost:** sémantický `<ol>`, data v `<time datetime>`, značky a křivka `aria-hidden`, rozcestník je běžný text.

**Omezený pohyb:** zastávky jsou vidět hned.

**Laravel:** `<x-trail :milestones="$milestones" :today="$settings->todayLabel" />`; výšky `--y` generovat z pořadí (lineárně stoupající) a stejnými body vykreslit cestu SVG.

**Kde:** `o-me.html`, sekce „Moje cesta k zámkům“; CSS oddíl 18.

---

## 5. Panorama Jizerek s Ještědem v patičce

**Co to je:** celošířková linková ilustrace hřebene nad patičkou: vlevo Ještěd s vysílačem, uprostřed hřeben Jizerských hor s rozhlednou, vpravo Krkonoše v dálce, smrky na popředí, malé oranžové slunce. Popředí má barvu patičky, takže hory z patičky „vyrůstají“.

**Proč:** každá stránka končí stejným místním obrazem: podpis regionu, bez textu. Uzavírá stránku klidně a zapamatovatelně.

**Anatomie:** `.footer__panorama` > `svg.panorama` (`viewBox 0 0 1440 220`, `preserveAspectRatio="xMidYMax slice"`, výška `clamp(96px, 13vw, 210px)`), vrstvy: noční hvězdy, slunce / srpek, vzdálené hory (`.sl .f-far`), hřeben (`.s .f-hill`), Ještěd a rozhledna, popředí (`.f-foot` = `--c-footer`), smrky. Pod ním `.footer__body` s vrstevnicemi.

**Chování:** statické. Na úzkém displeji se ořízne do stran (Ještěd zůstává vidět), v tmavém režimu přejde do noci (hvězdy, srpek měsíce).

**Data:** žádná, jedna ilustrace pro celý web.

**Přístupnost:** `aria-hidden="true"`, dekorativní.

**Omezený pohyb:** netýká se.

**Laravel:** `resources/views/components/illustrations/panorama.blade.php` vložený v `layouts/app.blade.php` nad patičkou.

**Kde:** všechny stránky, `_src/partials/ill-panorama.html`, CSS oddíl 13.

---

## 6. Mobilní lišta s fotkou

**Co to je:** plovoucí oranžová lišta u spodního okraje na mobilu: kulatá fotka Ondřeje (44 px), „Zavolat 730 915 828“ a pod tím „Ondřej Balý, pohotovost nonstop“, vpravo ikona telefonu. Celá lišta je jeden odkaz `tel:`.

**Proč:** volání je vždy na dosah palce, a díky fotce člověk ví, komu volá. Osobní dotek snižuje ostych zavolat cizímu člověku v noci.

**Anatomie:** `a.callbar` (fixed, `left/right max(10px, (100% - 520px) / 2)`, radius 18 px, `--shadow-bar`) > `.callbar__photo` (kruh s výřezem obličeje), `.callbar__text` (strong + small), `.callbar__icon`.

**Chování:** vyjede zespodu po načtení; skryje se při otevřeném mobilním menu (menu má vlastní tlačítko volání); od 1024 px zmizí (volání je v hlavičce). Stránka má dole rezervu 84 px + `env(safe-area-inset-bottom)`.

**Data:** fotka a telefon z nastavení (fotka ideálně samostatný čtvercový výřez obličeje 160 × 160 px).

**Přístupnost:** jeden odkaz s `aria-label="Zavolat 730 915 828, Ondřej Balý, pohotovost nonstop"`, fotka `alt=""` (informace je v textu), kontrast 5,0 : 1, výška 60 px.

**Omezený pohyb:** lišta je rovnou na místě.

**Laravel:** `<x-call-bar :phone="$settings->phone" :photo="$settings->avatar" />` v layoutu, `@unless(request()->routeIs('admin.*'))`.

**Kde:** všechny stránky pod 1024 px; CSS oddíl 14.

---

## 7. Sada ilustrací (s noční variantou)

**Co to je:** vlastní linkové ilustrace: hero (dveře se svazkem klíčů, Jizerky, Ještěd, smrky, pěšina, rozcestník se značkou), tři klíče, tři drobné motivy ceníku (dveře, auto, sejf), kroužek se dvěma klíči v CTA pásu, panorama v patičce.

**Proč:** klient výslovně chtěl ilustrace. Dávají webu tvář bez stockových fotek a drží jednotný místní jazyk. Oranžový kroužek se opakuje jako leitmotiv.

**Anatomie a pravidla:** inline SVG s třídami (`.s` obrys, `.sl` vzdálená linka, `.f-*` výplně, `.ring` oranžový kroužek, `.ill-night`, `.ill-moon-cut`), barvy výhradně z tokenů `--ill-*`, tah 2,25 px s `non-scaling-stroke`. Podrobnosti v `BRAND.md`, kapitola 11.

**Chování:** svazek klíčů v hero se po načtení jednou zhoupne kolem zámku (2,6 s). V tmavém režimu se objeví hvězdy a ze slunce se výřezem stane srpek měsíce (pohotovost nonstop beze slov).

**Data:** statické soubory; samostatné exporty se světlými výchozími barvami v `assets/img/illustrations/*.svg` (skript `_src/tools/export-illustrations.py`) pro Figmu a tisk.

**Přístupnost:** hero `role="img"` s `<title>`, ostatní `aria-hidden="true"`.

**Omezený pohyb:** svazek se nehoupe.

**Laravel:** Blade komponenty v `resources/views/components/illustrations/`, např. `<x-illustrations.hero />`; exportované SVG jen tam, kde není potřeba přebarvení (OG obrázek, tisk).

**Kde:** `_src/partials/ill-*.html`, `key-*.html`, `spot-*.html`, `cta-band.html`.

---

## 8. Recenze: přepínač zdroje, výzva podle záložky, pás na mobilu

**Co to je:** přepínač Google / Seznam (kapsle, jen text), souhrn hodnocení (velké číslo, hvězdy, počet), výzva „Pomohl jsem i vám? Budu rád za pár slov.“ s tlačítkem, které se mění se záložkou („Ohodnotit na Google“ / „Ohodnotit na Seznamu“), karty recenzí v masonry (první zvýrazněná `--c-accent-soft`, větší písmo). Na mobilu karty v pásu se snapem.

**Proč:** lidé věří tomu zdroji, který sami používají; výzva k hodnocení je u toho správného profilu, a na mobilu recenze nezaberou pět obrazovek.

**Anatomie:** `.reviews__grid[data-tabs]` > `.reviews__side` (nadpis, `.seg[role=tablist]`, `.rating[data-tab-show]`, `.reviews__cta[data-tab-show]`) + `.reviews__main` (`[role=tabpanel]` s `.masonry` a `figure.review`). Na mobilu `.reviews__side { display: contents }` a pořadí přes `order`: nadpis, přepínač, souhrn, recenze, výzva.

**Data:** Google souhrn a recenze zatím ukázkové (`<!-- MOCK -->`), Seznam souhrn podle skutečného profilu Firmy.cz (5,0 ze 6 hodnocení), karty z `content.md`. V produkci ze správy (ručně schválené recenze: jméno, zdroj, datum, text, hvězdy) nebo z Google Business Profile.

**Přístupnost:** tabs, hvězdy `aria-hidden` s textem „hodnocení 5 z 5“ pro čtečky, citace v `blockquote`, podpis ve `figcaption`.

**Omezený pohyb:** netýká se (jen přepnutí).

**Laravel:** `<x-reviews :sources="['google' => $google, 'seznam' => $seznam]" />`, odkaz na hodnocení `https://search.google.com/local/writereview?placeid={{ config('services.google.place_id') }}`.

**Kde:** `index.html`, sekce „Co říkají zákazníci“; CSS oddíl 11.

---

## Poznámka ke sdíleným souborům

Během práce byly ve sdílených souborech opravené dvě chyby mapy (pád Leafletu při přidávání popisků před nastavením pohledu a dlaždice CARTO vyžadující API klíč). Tento návrh už žádné lokální obejití nemá: mapa používá sdílený `coverage-map.js` a vzhled podkladu nastavuje jen tokenem `--map-tile-filter` (světlý režim do smrkového tónu, tmavý invertovaný).
