# Návrh A „Signál“: unikátní prvky

Prvky, které tento návrh odlišují od ostatních, s podklady pro implementaci v Laravelu (Blade + Tailwind v4). Sdílené chování (provozní doba, záložky, lightbox, formulář) je v `design/_shared/assets/js/common.js`, specifické chování návrhu v `assets/js/main.js`.

Přehled:
1. Ciferník dostupnosti
2. Týdenní mapa příplatků
3. Piktogramové ilustrace s prstencem
4. Mono číselný systém
5. Dvojitá mobilní akční lišta
6. Živý stavový řádek
7. Akutní rozcestník na Poptávce
8. Přepínač recenzí s proměnlivou výzvou
9. Pás faktů

---

## 1. Ciferník dostupnosti

**Co to je:** 24hodinový ciferník postavený z prstence loga. Plný oranžový prstenec = pohotovost nonstop, inkoustový oblouk od 8 do 17 = běžný provoz pro neakutní služby, ručička = aktuální čas v Praze. Uprostřed „nonstop“ a „běžně 8:00 až 17:00“, pod ním legenda.

**Proč:** dvě otevírací doby (nonstop pohotovost a denně 8:00 až 17:00 pro montáže) se v textu snadno pletou. Ciferník je ukáže na jeden pohled: celý kruh svítí, takže volat se dá vždy; oblouk ukazuje, kdy se dělají běžné práce; ručička říká, kde jsme teď. Zároveň je to vizuální podpis webu odvozený přímo z loga.

**Anatomie (SVG, viewBox 240 × 240, střed 120/120):**
| Vrstva | Geometrie | Styl |
|---|---|---|
| `.dial__ring` | kruh r = 108 | stroke `--c-accent`, 12 |
| `.dial__tick` | 24 rysek, r 91 až 97 (hlavní 0, 6, 12, 18: r 86 až 97) | stroke ink 1,5 (hlavní 2,5), čtvercové konce |
| `.dial__labels` | „0, 6, 12, 18“ na r = 74 | Geist Mono 12, muted |
| `.dial__hours` | oblouk r = 60 od 8/24 do 17/24 otáčky | stroke ink 8, rovné konce |
| `.dial__center` | „nonstop“ + „běžně“ + „8:00 až 17:00“ | Geist 650 23 px; Mono 10,5 px |
| `.dial__needle` | úsečka r 48 až 100 + kroužek na prstenci r = 7 | úsečka accent 3; kroužek surface s ink obrysem 3 |

Úhel: 0 h nahoře, po směru hodin, `úhel = hodina / 24 × 360°`. Bod na kružnici: `x = 120 + r·sin(úhel)`, `y = 120 − r·cos(úhel)`.

**Chování a stavy:**
- `common.js` nastaví na `<html>` proměnnou `--now-fraction` (minuty od půlnoci / 1440) a aktualizuje ji každých 30 s. CSS: `.dial__needle { transform: rotate(calc(var(--now-fraction) * 1turn)); transform-origin: 120px 120px; transform-box: view-box; }`.
- Posun ručičky má přechod 0,8 s (stavová změna).
- Bez JavaScriptu se ručička skryje (`html:not(.js) .dial__needle`), zbytek ciferníku platí vždy.
- Varianta `.dial--compact` (Kontakt, 150 až 180 px): skryje drobné texty uprostřed, legenda má 3 položky (pohotovost, neakutní služby, ručička).

**Data:** otevírací doba z administrace (`settings.hours.open_from = 8`, `open_to = 17`, `emergency = true`). Oblouk se počítá v Blade z hodin; nonstop prstenec se vykreslí jen při `emergency = true` (jinak by se prstenec vykreslil jako oblouk podle pohotovostních hodin).

**Přístupnost:** `<svg role="img" aria-labelledby="dial-title dial-desc">` s `<title>` „Ciferník dostupnosti“ a `<desc>` „Pohotovost 24 hodin denně. Neakutní služby denně od 8:00 do 17:00. Ručička ukazuje aktuální čas.“ Legenda pod ciferníkem je plnohodnotná textová alternativa. Informace není nesená jen barvou (prstenec vs. oblouk se liší tvarem i polohou).

**Reduced motion:** přechod ručičky se vypne, ručička skočí na novou pozici.

**Laravel/Blade:**
```blade
{{-- resources/views/components/availability-dial.blade.php --}}
@props(['from' => 8, 'to' => 17, 'compact' => false])
@php
  $p = fn ($r, $h) => [120 + $r * sin($h / 24 * 2 * M_PI), 120 - $r * cos($h / 24 * 2 * M_PI)];
  [$x1, $y1] = $p(60, $from); [$x2, $y2] = $p(60, $to);
  $large = ($to - $from) > 12 ? 1 : 0;
@endphp
<div @class(['dial', 'dial--compact' => $compact])>
  <svg class="dial__svg" viewBox="0 0 240 240" role="img" aria-labelledby="dial-title dial-desc">…
    <path class="dial__hours" d="M{{ $x1 }} {{ $y1 }} A60 60 0 {{ $large }} 1 {{ $x2 }} {{ $y2 }}"/>
  </svg>
  <x-dial-legend :from="$from" :to="$to" />
</div>
```
Rysky a popisky generovat smyčkou `@for ($h = 0; $h < 24; $h++)`. ID `dial-title` / `dial-desc` doplnit o `uniqid()`, pokud by byly dva ciferníky na stránce.

**Kde v ukázce:** `index.html` (hero, 380 px na desktopu, 170 až 250 px na mobilu a tabletu s legendou vedle), `kontakt.html` (sekce Kdy pracuji, kompaktní). Zdroj: `_src/partials/dial.html`.

---

## 2. Týdenní mapa příplatků

**Co to je:** mřížka 7 dní × 24 hodin, která barevně ukazuje, kdy platí základní cena (denně 8 až 17), kdy +50 % (všední den mimo dobu) a kdy +100 % (víkend mimo dobu). Aktuální hodina svítí oranžově, nad mřížkou je věta „Teď je sobota 19:43, platí příplatek +100 % z ceny práce.“

**Proč:** příplatky jsou nejčastější zdroj nejistoty („kolik mě to bude stát teď v noci?“). Textová pravidla s „po pracovní době ve všední den“ jsou správná, ale pomalá. Mřížka odpoví okamžitě a zvýrazněná buňka „teď“ dává přímo odpověď pro aktuální situaci.

**Anatomie:**
- `.wk__now`: živá tečka + věta o aktuálním stavu (skrytá bez JS).
- `.wk__board` > `.wk__grid`: CSS grid `26px repeat(24, 1fr)` (desktop `34px`), mezera 2 až 3 px. Popisek dne (Po až Ne, víkend tučně) + 24 buněk `.wk__c` s `data-d` (0 = pondělí) a `data-h` (0 až 23). Poslední řádek `.wk__axis`: popisky 0:00, 8:00, 17:00, 24:00 na odpovídajících sloupcích.
- `.wk__side`: legenda (0 %, +50 %, +100 %, aktuální hodina) + poznámka o svátcích.

**Barvy:** základ = bg s vlasovým obrysem, +50 % = `--wk-50` (ink 28 %), +100 % = `--wk-100` (ink 72 %), teď = `--c-accent` s dvojitým prstencem (`box-shadow`). Tmavší = dražší (v tmavém režimu naopak světlejší, legenda platí vždy). Oranžová jen pro „teď“.

**Chování a výpočet (`main.js`):**
```js
surcharge(day, hour) = (hour >= 8 && hour < 17) ? 0 : (day >= 5 ? 100 : 50)
```
Den v týdnu v časové zóně Europe/Prague přes `Intl.DateTimeFormat('en-US', { timeZone: 'Europe/Prague', weekday: 'short' })`, hodina z `window.tootevruNow()` (common.js). Aktualizace na událost `tootevru:hours` (každých 30 s). Svátky se automaticky nedetekují, proto textová poznámka „Ve svátek platí příplatek +100 % z ceny práce.“ (v produkci lze doplnit seznam svátků z administrace nebo balíček `yasumi/yasumi` a větu „Dnes je státní svátek, platí +100 %.“).

**Přístupnost:** mřížka je `aria-hidden="true"` (168 buněk by čtečka četla zbytečně). Textová alternativa = legenda se slovním popisem pravidel („pondělí až pátek před 8:00 a od 17:00“) + věta o aktuálním stavu. Rozlišení úrovní jasem, ne odstínem.

**Reduced motion:** prvek se nehýbe, nic k vypnutí.

**Laravel/Blade:** komponenta `<x-surcharge-map :rules="$surcharges" />`. Data z administrace:
```php
// config nebo tabulka settings
'hours' => ['from' => 8, 'to' => 17],
'surcharges' => ['weekday_off' => 50, 'weekend_off' => 100, 'holiday' => 100],
```
Buňky generovat `@foreach (range(0, 6) as $d) @foreach (range(0, 23) as $h)`, třídu určí stejná funkce jako v JS (sdílet jako PHP helper `surcharge($d, $h)`). Buňku „teď“ lze označit i serverem (`now('Europe/Prague')`), JS ji jen udržuje aktuální.

**Kde v ukázce:** `cenik.html`, sekce „Příplatky podle dne a hodiny“. Zdroj mřížky: `_src/partials/surcharge-grid.html`.

---

## 3. Piktogramové ilustrace s prstencem

**Co to je:** sada pěti liniových piktogramů ve stylu dopravního značení (dveře, auto, zlomený klíč, trezor, cylindrická vložka). Každý obsahuje jediný oranžový prstenec převzatý z loga: hlavu klíče, číselník trezoru, rotor vložky.

**Proč:** klient chtěl ilustrace. Fotky konkrétních situací (zamčené dveře, zlomený klíč) zatím nejsou a stock fotky by působily nedůvěryhodně. Piktogramy jsou okamžitě rozpoznatelné i ve stresu (jako cedule na letišti) a prstenec je váže k logu.

**Anatomie a pravidla:** mřížka 96 × 96, linka 2 px (`stroke-linecap: square`, `stroke-linejoin: miter`), bez výplní, max. 8 tahů, jeden `<circle class="picto__ring">`. Detailní katalog a použití v `BRAND.md`, kapitola 8.

**Chování:** statické. Tloušťka se přizpůsobí velikosti zobrazení přes CSS proměnné `--picto-stroke` a `--picto-ring` (např. v panelu ceníku 56 px: `--picto-stroke: 3.4`), aby vykreslená linka byla vždy cca 2 px.

**Přístupnost:** dekorativní, `aria-hidden="true" focusable="false"`; význam nese nadpis vedle. Samostatné SVG soubory mají `role="img"` a `aria-label` pro případné jiné použití.

**Tmavý režim:** linky `currentColor`, prstenec `var(--c-accent)`, bez úprav souborů.

**Laravel/Blade:** anonymní komponenty `resources/views/components/picto/{dvere,auto,klic,trezor,montaz}.blade.php` s obsahem partialu; použití `<x-picto.dvere class="size-14" />`. V administraci služeb pole „piktogram“ (select z této sady), aby šlo služby přeřadit bez vývojáře.

**Kde v ukázce:** `index.html` (dlaždice služeb), `cenik.html` (hlavičky panelů), `poptavka.html` (boční panel). Zdroje: `_src/partials/picto-*.html`, `assets/img/illustrations/picto-*.svg`.

---

## 4. Mono číselný systém

**Co to je:** všechna čísla, podle kterých se člověk rozhoduje, jsou v Geist Mono s tabulkovými číslicemi: telefon (v tlačítkách, horní liště, patičce, obří na Kontaktu), ceny, časy, data milníků, hodnocení, IČ, popisky ciferníku a mapy příplatků, dny ve výběru termínu.

**Proč:** „dispečerský“ pocit (odjezdová tabule, digitální hodiny) a hlavně rychlé čtení. Monospace číslice mají stejnou šířku, ceny v ceníku se zarovnají, telefon se čte po trojicích a neslévá se s okolním textem.

**Anatomie:** utilita `.num` = `font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; white-space: nowrap`. Velká čísla stahují prostrkání až na -0,05em. V rozsazích se mono sází jen samotné časy, spojka „až“ zůstává v Geistu.

**Pravidla:**
- Telefon vždy s nezlomitelnými mezerami po trojicích: `730&nbsp;915&nbsp;828`.
- Cena: `1&nbsp;300&nbsp;Kč`, „od“ může být mono (v řádku ceníku) nebo Geist menším řezem (v dlaždici).
- Neuvádí se nic, co není číslo (slova v mono jen v legendách a mikro popiscích).

**Přístupnost:** čísla zůstávají textem, žádné obrázky číslic. `white-space: nowrap` zabraňuje zalomení uprostřed čísla.

**Laravel/Blade:** Tailwind utilita `@utility num { … }` (viz `BRAND.md`), helper pro formát ceny `Number::format($price, locale: 'cs')` + `&nbsp;Kč`, pro telefon `phone_display('+420730915828')` vracející `730&nbsp;915&nbsp;828`.

**Kde v ukázce:** všude; nejvýrazněji `kontakt.html` (telefon 92 px), `index.html` (fakta „2019“, „69-038-H“, „+0 Kč DPH“) a `cenik.html`.

---

## 5. Dvojitá mobilní akční lišta

**Co to je:** lišta přilepená ke spodní hraně displeje pod 768 px. Dvě třetiny šířky oranžové tlačítko s telefonem „730 915 828“, třetina „SMS“. Přes celou šířku, bez zaoblení, výška 60 px + bezpečná zóna iPhonu.

**Proč:** web se používá hlavně v krizi a na telefonu. Tlačítko Volat musí být pod palcem na každé stránce a v každém místě stránky. SMS je druhý kanál pro situace, kdy člověk nemůže mluvit (noc, děti spí, hluk) nebo chce poslat adresu písemně.

**Anatomie:** `.callbar` (grid `2fr 1fr`, surface, horní linka) > `a.callbar__call` (accent, ikona telefonu Fill, číslo mono 21 px) + `a.callbar__sms` (ink, ikona `chat-text`, levá linka).

**Chování a stavy:** fixní pozice, `body` má spodní padding `61px + env(safe-area-inset-bottom)`, aby lišta nezakrývala patičku. Stisk: tmavší oranžová / pozadí bg. Fokus: obrys uvnitř tlačítka (`outline-offset: -4px`). Na mobilu hlavička záměrně není sticky, aby nebyly dvě pevné lišty. Cookie lišta se na mobilu vykreslí nad akční lištou (`#cc-main .cm--box.cm--bottom { bottom: 72px }`), takže volat jde i před rozhodnutím o cookies.

**Přístupnost:** `role="region" aria-label="Rychlý kontakt"`, přístupné názvy „Zavolat na 730 915 828“ a „Poslat SMS na 730 915 828“ (obsahují viditelný text). Cíle 60 px vysoké.

**Reduced motion:** lišta se nepohybuje.

**Laravel/Blade:** součást layoutu `layouts/app.blade.php` (`<x-callbar />`), telefon z `config('tootevru.phone')`. Volitelně skrýt na stránce Poptávka po odeslání formuláře? Nedoporučuji, lišta má být konstanta.

**Kde v ukázce:** všechny stránky pod 768 px (`_src/layout.html`).

---

## 6. Živý stavový řádek

**Co to je:** malý řádek nad H1 na úvodu (a v sekci Kdy pracuji na Kontaktu): oranžová tečka, aktuální čas v Praze (mono) a stav: „Otevřeno do 17:00, pohotovost nonstop“ nebo „Pohotovost nonstop, běžný provoz od 8:00“.

**Proč:** první otázka v krizi zní „bere to teď někdo?“. Řádek odpoví dřív, než člověk dočte nadpis, a vysvětlí rozdíl mezi pohotovostí a běžným provozem v konkrétní chvíli.

**Anatomie:** `.status` > `.live-dot` (8 px kruh, oranžová se světlým lemem) + `<time data-now-time>` + `<span data-hours-text data-open-text="…" data-closed-text="…">`.

**Chování:** texty přepíná `common.js` podle času v Praze (`html[data-hours]`), aktualizace co 30 s. Bez JS se zobrazí „Pohotovost nonstop, 24 hodin denně“ a čas se skryje (`time:empty`). Tečka je statická (žádné pulzování), je to skutečný stav, ne dekorace.

**Přístupnost:** tečka `aria-hidden`, stav je text. Záměrně bez `aria-live`, aby čtečka nehlásila změnu každých 30 s.

**Laravel/Blade:** `<x-live-status />`, výchozí text renderuje server podle `now('Europe/Prague')`, JS ho jen udržuje.

**Kde v ukázce:** `index.html` (hero), `kontakt.html`.

---

## 7. Akutní rozcestník na Poptávce

**Co to je:** výrazný panel s tónovaným pozadím hned pod nadpisem Poptávky: „Zabouchli jste se, nebo nejde odemknout? Formulář nevyplňujte a zavolejte. Pohotovost je nonstop.“ + velké tlačítko Volat.

**Proč:** část lidí v krizi skončí na formuláři omylem (hledá „kontakt“, „objednat“). Vyplňování formuláře by je zdrželo o minuty a Ondřej by se o problému dozvěděl pozdě. Panel je odkloní na telefon dřív, než začnou psát.

**Anatomie:** `.acute` (accent-soft, rádius 8 px) > ikona `warning` + H2 + věta; tlačítko `.btn--call.btn--xl` vpravo (na mobilu pod textem přes celou šířku).

**Přístupnost:** skutečný nadpis H2 (najde se v navigaci po nadpisech), tlačítko s plným přístupným názvem.

**Laravel/Blade:** `<x-acute-banner />`, text z administrace (pole „Akutní upozornění“), stejné tlačítko jako v layoutu.

**Kde v ukázce:** `poptavka.html`.

---

## 8. Přepínač recenzí s proměnlivou výzvou

**Co to je:** segmentový přepínač Google | Seznam. S přepnutím se mění souhrnné hodnocení (5,0 a 27 recenzí na Google / 5,0 a 6 hodnocení na Firmy.cz), pás karet i výzva „Ohodnotit na Google“ / „Ohodnotit na Seznamu“ a odkaz na všechny recenze.

**Proč:** Ondřej má hodnocení na dvou místech a každý zákazník používá jiný ekosystém. Výzva k hodnocení se mění s kontextem, takže vede přesně tam, kde se člověk právě dívá.

**Anatomie:** `[data-tabs]` > `.segmented[role=tablist]` > 2 × `button[role=tab]`; 2 × `[role=tabpanel][data-track]` se souhrnem, šipkami a pásem `.reviews__track` (scroll-snap, karty max. 3 řádky); patička s prvky `[data-tab-show="google|seznam"]`.

**Chování:** přepínání řeší `common.js` (šipky na klávesnici, Home/End, `aria-selected`, `hidden`). Šipky pásu (`main.js`) posouvají o šířku karty a vypínají se na začátku a konci pomocí IntersectionObserveru (bez scroll listeneru). Na mobilu se šipky skryjí, pás se posouvá prstem.

**Přístupnost:** WAI-ARIA tabs, pás je `role="region"` s popiskem a `tabindex="0"` (lze posouvat klávesnicí), hvězdy mají `role="img" aria-label="Hodnocení 5 z 5"`.

**Reduced motion:** posun pásu bez plynulé animace (`behavior: 'auto'`), přepnutí panelu bez prolínání.

**Laravel/Blade:** recenze z tabulky `reviews` (zdroj, jméno, text, hodnocení, datum), souhrn z `review_sources` (hodnota, počet, URL profilu, URL pro hodnocení). Google Place ID a URL profilů v nastavení. Do JSON-LD se `aggregateRating` nevkládá (viz `content.md`).

**Kde v ukázce:** `index.html`, sekce „Hodnocení zákazníků“ (texty recenzí jsou mock, souhrn Firmy.cz je reálný).

---

## 9. Pás faktů

**Co to je:** místo tří stejných karet „proč si nás vybrat“ jeden pás mezi dvěma linkami: velký fakt (fotka Ondřeje + „2019“) a dva menší pod sebou („69-038-H“ Profesní kvalifikace Zámkař, „+0 Kč DPH“ Konečné ceny).

**Proč:** důvěra se buduje ověřitelnými fakty, ne přídavnými jmény. Rok, kód kvalifikace a DPH status jsou čísla, která si člověk může ověřit (dokumenty na O mně).

**Anatomie:** `.facts` (horní a dolní linka) > `.facts__grid` 7:5 > `.fact--lg` (foto 4:5 + `.fact__fig` 56 až 104 px mono + text + odkaz „O mně a dokumenty“) a `.facts__side` se dvěma `.fact` oddělenými linkou.

**Přístupnost:** čísla jsou text, fotka má popisný alt.

**Laravel/Blade:** `<x-facts />`, fakta jako opakovatelné pole v administraci (číslo, popisek, odkaz).

**Kde v ukázce:** `index.html`, sekce „Kdo k vám přijede“.
