Kanban board tasků — filtr dle priority, labelu nebo runu.
i18n soubory měly paritní strukturu (116ř každý) i pro nepřeložené texty. Přidal jsem 28 klíčů visitPlan.* do cs.json a propsal CS placeholder do 8 dalších locales — zachovává konvenci, Sprint 005 pak přeloží jediným průchodem.
pages collection byla prázdná. Vytvořil jsem dvě content entries: plan-navstevy.md (43ř — autem/vlakem/autobusem/parkování prózní text) a kombinovane-vstupne.md (51ř — 5 cenových tier sekcí). Markdown je flexibilnější než hardcoded i18n stringy a Sveltia CMS později pohodlně edituje.
Stránka /plan-navstevy/ neexistovala, header CTA Naplánovat návštěvu vedl na 404. Postavil jsem index.astro (215ř) s 6 sekcemi: hero, getting there + adresa/GPS dl, OSM iframe mapa s odkazy, otevírací doba, doporučená délka (3 varianty), kombinované vstupné + Colosseum CTA. OSM iframe je bez API klíče a tracker-free.
Header CTA Vstupenky i homepage pillar Kalendář akcí byly v kódu wired už od Run 003/004 přes siteConfig.ticketsUrl a localizedPath. Předtím vedly na 404 protože cíle neexistovaly — teď když /kalendar/ (Run 007) a /plan-navstevy/ (Run 008) běží, všechny CTA z homepage fungují bez editu.
Hub /kalendar/ neexistoval. Server-rendered listing s dvěma sekcemi (Co se chystá + Proběhlo), getCollection sortuje upcoming asc / past desc. Past sekce defaultně viditelná v HTML, JS po hydraci skryje (no-JS gracefully shows everything).
Filtrace neexistovala. Svelte 5 runes island ($state pro hodnoty, $derived pro hasFilters, $effect pro DOM toggle .hidden přes data-attributes na cards). Tři selecty: kategorie, měsíc, pořadatel + tlačítka reset a Zobrazit archiv. Přidává @astrojs/svelte 8.1 + svelte 5.55 do projektu.
Detail neexistoval. Vzor: zazitky/[slug].astro — getStaticPaths + render Content + EventMeta + related events (upcoming-only, slice 2). Eyebrow s kategorií místo 'Návštěva'.
Events collection byla prázdná. Stáhli jsme 3 reálné akce z zamekzdar.cz/kalendar/ (Den otevřených lesů, KoresponDance, výstava Gruzie UNESCO) a doplnili 5 dalších typických (akademie, koncert, kino, dva trhy) — celkem 8 markdownů v cs/. i18n přibylo 41 events.* klíčů × 9 lokalit (cs plné, 8× CS placeholder).
Card a meta strip pro detail. EventCard kopíruje vzor ExperienceCard, ale meta = datum + místo + kategorie badge; faded styl + Proběhlo badge pro past. EventMeta = pět položek (datum, kategorie, místo, cena od, pořadatel) v gridu.
ExperienceCard (4:3 placeholder + perex + duration/price meta) sdílený mezi hubem a related listem. ExperienceMeta (info strip pro detail) dynamicky skipuje chybějící pole.
14 i18n klíčů experiences.* do 9 jazyků (CS plné texty, 8 ostatních dostalo CS placeholder per konvence z Run 003 — Sprint 005 přeloží). PLAN.md + sprint.md + done.md hotové, smoke build 0 errors.
Vznikla CS hub stránka /zazitky/ — listing tří zážitků z content collection sorted podle order fieldu, empty state pokud žádné CS entries. Per-locale hub byl smazán kvůli Astro routing konfliktu, i18n fallback to řeší.
Detail šablona /zazitky/[slug] generuje stránku pro každý CS entry. Renderuje markdown body, hero, meta strip s délkou/cenou/sezonou/audience/locací, ticket CTA a max 2 related zážitky.
Tři CS markdown soubory (Muzeum nové generace, Herna InventoriUM, Prohlídka konventu) s rich storytellingem v luxury institutional duchu. Frontmatter podle existujícího schema — perex, audience, season, duration, price_from, ticket_url, location, order, seo.
Header neměl skip-link klíč, mobile menu mělo hardcoded aria-label, Footer obsahoval inline 'Navigace' text a chyběl IČO. Přidány klíče header.skip, header.menu.open/close, lang.switcher.label, footer.navigation/contact/directions/legal.iczo plus nav.aria.primary/footer (přidáno během /review jako fix nelokalizovaného aria-label) do 9 lokalit, 8 ne-CS jako CS placeholder do Sprintu 005.
Web měl 9 jazykových mutací bez UI přepínače mezi nimi. Nový LangSwitcher používá native HTML <details>/<summary> dropdown — žádný JS framework, built-in browser state + keyboard a screen reader podpora. Aktuální locale highlightnutý bronze s aria-current, page remap přes stripLocaleFromPath + localizedPath. Dvě varianty (desktop popout vpravo, mobile inline pod nav linky).
Navbar z Run 001 byl placeholder s hardcoded CS texty bez lang switcheru, ticket CTA ani locale propagace. Refactor: locale Props, navItems array s tKey+href přes t() lokalizaci, externí ticket CTA v bronze accent vpravo s target=_blank, integrace LangSwitcheru, lokalizované aria-labels mobile menu přes data-attrs. Mobile breakpoint posunut z md na lg, protože 7 nav linků se na md nevejde.
Footer z Run 001 měl jen 2 sloupce (brand + nav) bez kontaktů, mapy, otevírací doby ani social. Refactor na 4 sloupce: (1) brand + popis + IČO + drobný ticket button, (2) Navigace lokalizovaná, (3) Kontakt s adresou, Google Maps link, tel a mailto linky, (4) Otevírací doba (sezóna + mimosezóna) + Lucide ikony Instagram/Facebook. Bottom row copyright + year.
BaseLayout volal Navbar a Footer bez locale propu, takže vnitřek nemohl lokalizovat. Přidána import createT, instance t pro skip-link (t('header.skip') místo hardcoded 'Přeskočit na obsah'), a propagace locale do Navbaru i Footeru. Skip-link tak respektuje aktuální jazyk stránky.
Obě homepage stránky (default a [locale]) ukazovaly placeholder z Run 001. Nahrazeno kompozicí Hero → IntroSection → PillarsGrid → SantiniStory přes BaseLayout. Locale prop propagován ze stránky do každé komponenty pro createT překlady.
Run 002 nechal duplicitní font-display jako Tailwind class i jako globální h1-h4 rule. Vybrán B-variant: smazána Tailwind class z SectionHeading, globální rule v global.css zůstává jako default. Plus přidány homepage překladové klíče (hero/intro/pillars/santini) do cs.json a propagovány do 8 lokalit jako CS placeholder (strojový překlad přijde Sprint 005).
Homepage měla jen centrovaný h1 z Run 001. Hero komponenta postaví 12-col asymmetric grid: vlevo eyebrow + display heading + lede + dvě CTA (primární Plán návštěvy do bronze accent, sekundární Objevit více jako outline scroll na #intro), vpravo placeholder portrait aspect-[4/5] s diagonal stripe pattern dokud nepřijde reálná foto.
Story sekce chyběly úplně. IntroSection postaví symmetrický 2-col text blok (heading vlevo, dvě těla odstavce vpravo) s ID intro pro #intro scroll z Hero. SantiniStory postaví 12-col asymmetric s textem + CTA do historie vlevo a pull-quote v Cormorant italic v figure vpravo.
Návštěvník neměl jak skočit do hlavních sekcí. PillarsGrid přidává 4 karty v 2x2 gridu (Zážitky/Ubytování/Kalendář/Vzdělávání) s placeholder image, titulkem, perexem a CTA. Karty směřují na lokalizované cesty z siteConfig.navLinks — cílové stránky přijdou v Sprint 002 a 004.
Web měl jen Inter sans z kostry, který nepasoval na luxury institutional brief. Přidán Cormorant Garamond jako druhý font přes Astro Fonts API (--font-cormorant) s preload v BaseLayout. Inter zůstává pro tělový text, Cormorant pro nadpisy.
global.css obsahoval kostra-šablonový design system — modrý primary, dark/light toggle, glass panely, glow shadows. Přepsán na single light theme s cisterciácko-barokní paletou (canvas/paper/surface ivory + ink scale + bronze accent + rule borders) a typografií displaye/sans. Connector ke všem dalším runům.
Web bude mít desítky sekcí napříč 9 lokalitami, opakovat inline mx-auto max-w-... px-... by ravioli kód. Vytvořeny dva primitivy v src/components/ui/: Container (4 max-width hodnoty), Section (3 spacing × 3 tone). Section vědomě nevkládá automaticky Container — full-bleed sekce vyžadují explicit kompozici.
Section headery se opakují napříč webem ve stejném tvaru (eyebrow + display title + lede + decentní bronze rule). Vytvořena kompoziční komponenta SectionHeading s align left/center a as h1/h2. Jednotnost přes desítky sekcí > flexibilita; pokud zatím přijde edge case (decorative ornament), doplníme slot.
Bez vizuálního benchmarku není jak ověřit, jestli paleta a typografie ladí na pozadí Versailles/Louvre briefu. Vytvořena interní /design-system stránka s noindex,nofollow — palette swatches, typografická scale, Container a Section varianty, SectionHeading 3 ukázky. Single-scroll dev artefakt.