/**
 * Layout — TopBar, Sidebar, AppShell.
 * Mobile-first: sidebar je drawer pod 768px (Alpine x-show).
 */

.app-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* =====================
 * TOP BAR
 * ===================== */
.topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  height: var(--app-topbar-height);
  background: var(--surface-page);
  border-bottom: 1px solid var(--line-card);
  display: flex;
  align-items: center;
}

/* CZ: ROVINA ŘÍZENÍ JE TMAVÁ (R3). Vzor ji staví na navy (`BrAIen-Rizeni-X.dc.html:33`) a plán
       ji tak předepsal (`REDESIGN_UI_2026-09-06.md:1382`), jenže se nikdy nepostavila — token
       `--surface-dark` byl od 6. 9. 2026 definovaný a NIKDE nevykreslený. Interní rovina proto
       vypadala k nerozeznání od klientské, což byl podle majitele největší rozchod ze všech.

       ⚠️ V tmavém režimu se pozadí NEMĚNÍ (R24). `--surface-page` je tam taky navy, takže by
       lišta splynula se stránkou — odlišuje ji proto spodní linka a barva písma, ne jiná plocha.
   EN: THE MANAGEMENT PLANE IS DARK (R3). The sample builds it on navy and the plan prescribed it,
       but it was never built — `--surface-dark` sat defined and drawn NOWHERE since 6 Sep 2026.
       The internal plane was therefore indistinguishable from the client one, which the owner
       called the largest divergence of all.

       ⚠️ In dark mode the background does NOT change (R24). `--surface-page` is navy there too,
       so the bar would merge into the page — it is separated by its bottom rule and text colour
       instead of a different surface. */
.topbar--ops {
  height: var(--app-topbar-height-ops);
  background: var(--surface-dark);
  border-bottom-color: var(--line-on-dark);
}
.topbar--ops .topbar-brand,
.topbar--ops .topbar-notif:hover,
.topbar--ops .plane-nav-item:hover,
.topbar--ops .plane-nav-item.active { color: var(--text-on-dark); }
.topbar--ops .topbar-notif,
.topbar--ops .plane-nav-item,
.topbar--ops .plane-switch { color: var(--app-on-dark-muted); }
.topbar--ops .topbar-avatar {
  background: var(--line-on-dark);
  color: var(--text-on-dark);
}
/* CZ: Logo má tmavou variantu pro tmavé pozadí — v rovině řízení se použije VŽDY, ne jen
       v tmavém režimu, protože lišta je navy i ve světlém.
   EN: The logo has a dark-ground variant — in the management plane it is used ALWAYS, not only
       in dark mode, because the bar is navy in light mode too. */
.topbar--ops .topbar-logo-light { display: none; }
.topbar--ops .topbar-logo-dark { display: block; }

/* CZ: Odznak „ŘÍZENÍ" vedle loga (R3) — ve vzoru pilulka 11px verzálkami s obrysem.
   EN: The "ŘÍZENÍ" badge beside the logo (R3) — in the sample an 11px uppercase outlined pill. */
.topbar-plane-badge {
  flex: 0 0 auto;
  padding: 3px 12px;
  font-size: var(--caption-size-sm);
  font-weight: var(--caption-weight);
  letter-spacing: var(--caption-tracking);
  text-transform: uppercase;
  color: var(--app-on-dark-faint);
  border: 1px solid var(--line-on-dark);
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
/* CZ: Plná šířka — brand vlevo (nad sidebarem), akce vpravo (žádné centrování). */
/* EN: Full width — brand on the left (above the sidebar), actions on the right (no centering). */
/* CZ: STUDNA TOPBARU (R4, R17). Do 16. 9. 2026 tu stálo `width: 100%` a lišta se táhla přes
       celý viewport, zatímco `.main-content` pod ní byla vycentrovaná na 1200 px. Na širokém
       monitoru proto logo stálo stovky pixelů vlevo od místa, kde začínal obsah — to je ten
       „posunutý navbar", který majitel viděl. Studna je PER ROVINA: přístav `--well-web`,
       řízení `--well-ops`, vždy shodně s `.main-content` téže roviny.
   EN: THE TOPBAR WELL (R4, R17). Until 16 Sep 2026 this read `width: 100%` and the bar spanned
       the whole viewport while `.main-content` below was centred at 1200 px. On a wide monitor
       the logo therefore sat hundreds of pixels left of where the content began — that is the
       "shifted navbar" the owner saw. The well is PER PLANE, always matching `.main-content`. */
.topbar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  max-width: var(--well-web);
  margin: 0 auto;
  padding: 0 var(--space-4);
  gap: var(--space-2);
}
.topbar-inner--ops { max-width: var(--well-ops); }
/* CZ: min-width:0 dovolí levé i pravé skupině se zúžit (jinak by nezalomitelný obsah roztáhl
       sticky topbar přes šířku viewportu na mobilu). EN: min-width:0 lets both groups shrink
       (otherwise non-wrapping content would stretch the sticky topbar past the viewport). */
.topbar-inner > * { min-width: 0; }
.topbar-brand { font-family: var(--font-core); font-size: var(--text-xl); font-weight: var(--weight-heading); color: var(--text-primary); text-decoration: none; display: inline-flex; align-items: center; }

/* CZ: Tři varianty loga leží v DOM naráz (viz komentář v `templates/nav/topbar.html`) a
       zobrazí se právě jedna. Výška 32 px dává při poměru lockupu 6.68:1 šířku ~214 px, tedy
       nad minimální velikostí 120 px, kterou brand manuál (§2) předepisuje pro lockup s
       wordmarkem. Pod tu hranici se sahá po samostatném symbolu, ne po zmenšeném lockupu —
       do 14. 9. 2026 tu stálo `max-width: 108px`, což lockup stlačilo POD povolené minimum.
   EN: The three logo variants sit in the DOM at once (see the comment in
       `templates/nav/topbar.html`) and exactly one is shown. A 32 px height gives ~214 px of
       width at the lockup's 6.68:1 ratio, i.e. above the 120 px minimum the brand manual (§2)
       sets for the lockup with a wordmark. Below that threshold the standalone symbol is used,
       not a shrunken lockup — until 14 Sep 2026 a `max-width: 108px` here squeezed the lockup
       BELOW the permitted minimum. */
.topbar-logo { display: block; width: auto; height: 32px; }
.topbar-logo-dark,
.topbar-logo-symbol { display: none; }
html.dark .topbar-logo-light { display: none; }
html.dark .topbar-logo-dark { display: block; }
.topbar-actions { display: flex; align-items: center; gap: var(--space-1); }
/* CZ: Uživatelské tlačítko (jméno/e-mail) se na úzké obrazovce zkrátí s „…", ať nepřetéká.
   EN: The user button (name/email) truncates with an ellipsis on narrow screens so it can't overflow. */
.topbar-user-btn { max-width: 12rem; overflow: hidden; text-overflow: ellipsis; }

/* CZ: UPOZORNĚNÍ TEXTEM (A-15) — vzor má v topbaru slovo, ne ikonu zvonku. `position:
       relative` je kotva pro odznak počtu, který nad ním plave.
   EN: ALERTS AS TEXT (A-15) — the sample carries a word in the topbar, not a bell icon.
       `position: relative` anchors the count badge floating above it. */
.topbar-notif {
  position: relative;
  font-size: var(--text-sm);
  color: var(--text-body);
  text-decoration: none;
  white-space: nowrap;
  padding: var(--space-1);
}

.topbar-notif:hover { color: var(--text-primary); text-decoration: none; }

/* CZ: Oranžová pilulka počtu — vzor ji má přesně takhle (`#F59926` s ČERNÝM číslem).
       Popředí přes `--text-on-secondary` (oranžová = sekundární akce), NIKDY přes
       `--color-text-inverse` — ten se v tmavém režimu překlápí a číslo by zmizelo (past
       popsaná v CLAUDE.md, hlídá `test_inverse_text_token_is_not_used_as_foreground`).
   EN: The orange count pill — exactly as the sample has it (`#F59926` with a BLACK number).
       Foreground via `--text-on-secondary` (orange = the secondary action), NEVER
       `--color-text-inverse` — it flips in dark mode and the number would vanish (the trap
       CLAUDE.md describes, guarded by `test_inverse_text_token_is_not_used_as_foreground`). */
.topbar-notif-count {
  position: absolute;
  top: 0;
  right: 0;
  background: var(--accent-attention);
  color: var(--text-on-secondary);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-subhead);
  line-height: 1;
  padding: 2px var(--space-1);
}

/* CZ: KOLEČKO S INICIÁLAMI (A-16) — 36 px podle vzoru. `flex: 0 0 auto` a pevná šířka:
       kolečko zmáčknuté do elipsy vypadá jako chyba vykreslení.
   EN: THE INITIALS CIRCLE (A-16) — 36 px per the sample. `flex: 0 0 auto` plus a fixed width:
       a circle squashed into an ellipse reads as a rendering bug. */
.topbar-avatar {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-pill);
  border: 0;
  background: var(--gray-tint);
  color: var(--text-primary);
  font-family: inherit;
  font-size: var(--text-xs);
  font-weight: var(--weight-subhead);
  cursor: pointer;
  /* CZ: Ořez profilové fotky do kolečka (23. 9. 2026) — iniciály se centrují i bez paddingu.
     EN: Clips the profile photo to the circle (23 Sep 2026) — initials centre without padding. */
  padding: 0;
  overflow: hidden;
}

.topbar-avatar:hover { background: var(--blue-tint); }

/* CZ: Nástroje v nabídce (vzhled, jazyk) — na jednom řádku, oddělené linkou od odkazů.
   EN: The menu's tools (theme, language) — on one row, separated from the links by a rule. */
.topbar-menu-tools {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-1);
  padding-top: var(--space-1);
  border-top: 1px solid var(--line-divider);
}

/* CZ: Přepínač vzhledu — tři volby (světlý · tmavý · podle systému) jako segmentová pilulka.
       Vybraná volba se pozná podle `aria-checked`, ne podle vlastní třídy, takže vzhled
       a stav pro čtečku nemůžou rozejít.
   EN: The theme switch — three choices (light · dark · system) as a segmented pill. The
       selected one is styled by `aria-checked`, not a class of its own, so the look and the
       screen-reader state cannot drift apart. */
.theme-switch {
  display: inline-flex;
  gap: var(--space-1);
  padding: var(--space-1);
  border-radius: var(--radius-pill);
  background: var(--gray-tint);
}

.theme-switch-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-1);
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-body);
  cursor: pointer;
}

.theme-switch-btn:hover { color: var(--text-primary); }

.theme-switch-btn[aria-checked="true"] {
  background: var(--surface-overlay);
  color: var(--text-primary);
}

/* CZ: Nabídka pod uživatelským tlačítkem. Vlastní třída, ne `card absolute p-2` — utility
       `.absolute` a `.card` mají STEJNOU specificitu (0,1,0), takže o pozici rozhodovalo jen
       pořadí pravidel v souboru: `.card` nastavuje `position: relative`, `.absolute` ho přebíjí
       jen proto, že leží níž. Přehození bloků nebo jakékoli specifičtější pravidlo by nabídku
       tiše vrátilo na `relative` a rozhodilo ji.
       Odhaleno 6. 9. 2026 adversariálním ověřením ve F10.

       Pozadí je `--surface-overlay` (neprůhledné) ze stejného důvodu jako u panelu a modalu:
       nabídka PŘEKRÝVÁ obsah.
   EN: The menu under the user button. Its own class rather than `card absolute p-2` — the
       `.absolute` and `.card` utilities share the SAME specificity (0,1,0), so its position was
       decided purely by rule order in the file: `.card` sets `position: relative` and `.absolute`
       only overrides it by sitting lower. Reordering the blocks, or any more specific rule, would
       silently return the menu to `relative` and break it.
       Found 6 Sep 2026 by adversarial verification in F10.

       The background is `--surface-overlay` (opaque) for the same reason as the drawer and the
       modal: the menu COVERS content. */
.topbar-menu {
  position: absolute;
  top: var(--header-height);
  right: var(--space-2);
  width: 12rem;
  padding: var(--space-1);
  background: var(--surface-overlay);
  border: var(--border-card-style);
  border-radius: var(--radius-container);
  box-shadow: var(--shadow-overlay);
  z-index: var(--z-dropdown);
}

/* CZ: Mobil (≤480px) — menší padding/mezery, uživatelské tlačítko zúžené, a místo lockupu
       samostatný SYMBOL, aby se hamburger + logo + 3 ikony + uživatel vešly bez horizontálního
       přetečení. Manuál (§2): „Min. velikost 120 px. Pod tím použít samostatný symbol."
   EN: Mobile (≤480px) — smaller padding/gaps, a narrower user button, and the standalone SYMBOL
       instead of the lockup so the hamburger + logo + 3 icons + user fit without horizontal
       overflow. The manual (§2): "Minimum size 120 px. Below that use the standalone symbol." */
@media (max-width: 480px) {
  .topbar-inner { padding: 0 var(--space-2); }
  .topbar-inner { gap: var(--space-1); }
  .topbar-actions { gap: var(--space-1); }
  .topbar-logo-light,
  .topbar-logo-dark,
  html.dark .topbar-logo-dark { display: none; }
  .topbar-logo-symbol { display: block; }
  .topbar-user-btn { max-width: 6rem; }
}

/* =============================================================================
 * PLANE NAV — vodorovná navigace roviny v topbaru (F3, 6. 9. 2026)
 * =============================================================================
 * CZ: Nahrazuje svislý sidebar. Vzor má navigaci jako řádek popisků v topbaru; aktivní
 *     položku značí ORANŽOVÝ PODTRH (3 px), ne barevná plocha.
 *
 *     ⚠️ Prvek je v DOM JEN JEDNOU. Na mobilu se z něj CSS udělá vysouvací panel — kdyby se
 *     navigace vykreslila dvakrát (jednou topbar, jednou drawer), zdvojily by se popisky,
 *     `aria` atributy i cíle pro testy, a každá změna by se musela udělat dvakrát. Přesně
 *     ta chyba, kterou odstranil refaktor shellů v srpnu.
 * EN: Replaces the vertical sidebar. The sample renders navigation as a row of labels in the
 *     topbar; the active item is marked by an ORANGE UNDERLINE (3 px), not a coloured surface.
 *
 *     ⚠️ The element appears in the DOM ONLY ONCE. On mobile, CSS turns it into a slide-out
 *     panel — rendering the nav twice (topbar + drawer) would duplicate labels, `aria`
 *     attributes and test targets, and every change would have to be made twice. Precisely the
 *     defect August's shell refactor removed.
 * ============================================================================= */
.plane-nav {
  display: flex;
  align-items: stretch;
  gap: var(--space-1);
  /* CZ: `align-self: stretch` protáhne navigaci na plnou výšku topbaru — jinak by oranžový
         podtrh aktivní položky visel uprostřed lišty místo na její spodní hraně.
         `flex: 1 1 auto` + `min-width: 0` jí dovolí se zúžit; bez toho by dlouhá navigace
         roztlačila topbar a přetekla nad něj (což se 6. 9. 2026 stalo).
     EN: `align-self: stretch` makes the nav span the topbar's full height — otherwise the active
         item's orange underline would float mid-bar instead of sitting on its bottom edge.
         `flex: 1 1 auto` + `min-width: 0` let it shrink; without them a long nav would push the
         topbar apart and overflow above it (which happened on 6 Sep 2026). */
  align-self: stretch;
  flex: 1 1 auto;
  min-width: 0;
  /* CZ: Na užším desktopu se navigace posouvá vodorovně, místo aby přetekla nebo se zalomila.
     EN: On a narrower desktop the nav scrolls horizontally instead of overflowing or wrapping. */
  overflow-x: auto;
  scrollbar-width: none;
}
.plane-nav::-webkit-scrollbar { display: none; }

.plane-nav-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 12px;
  height: 100%;
  background: none;
  border: 0;
  /* CZ: Podtrh je průhledný i v klidu — jinak by se položka při aktivaci posunula o 3 px.
     EN: The underline is transparent at rest too — otherwise the item would jump 3 px when it
         becomes active. */
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  font-family: var(--font-core);
  font-size: var(--text-sm);
  font-weight: var(--weight-body);
  color: var(--text-body);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: color var(--transition-normal), border-color var(--transition-normal);
}
.plane-nav-item:hover { color: var(--text-primary); text-decoration: none; }
.plane-nav-item.active {
  color: var(--text-primary);
  font-weight: var(--weight-subhead);
  border-bottom-color: var(--accent-attention);
}

/* CZ: Skupina = položka s rozbalovací nabídkou. Vzor skupiny nemá (má 8 cílů, aplikace 25),
       takže je to PŘÍDAVEK — bez něj by se na 17 destinací nedalo dostat z navigace.
   EN: A group = an item with a dropdown. The sample has no groups (8 destinations vs the app's
       25), so this is an ADDITION — without it 17 destinations would be unreachable from the nav. */
.plane-nav-group { position: relative; display: inline-flex; align-items: stretch; }
.plane-nav-caret { transition: transform var(--transition-fast); }
.plane-nav-group[data-open="true"] .plane-nav-caret { transform: rotate(180deg); }

/* CZ: ⚠️ `position: fixed`, NE `absolute` (9. 9. 2026). `.plane-nav` má `overflow-x: auto`,
       čímž prohlížeč podle specifikace doplní i `overflow-y: auto` — a ten by absolutně
       pozicovanou nabídku, která vyskakuje POD nízkou lištou, oříznul. Fixní prvek `overflow`
       předků neořezává, takže se z klipu dostane bez zásahu do DOM.

       Souřadnice dodává `planeDropdown` (`static/js/nav_dropdown.js`) přes proměnné
       `--menu-top` / `--menu-left`, které váže na SKUPINU. Nejsou v `style` nabídky schválně:
       tam si píše `x-transition` a vzájemně by se přepisovaly (nabídka pak zůstala na
       `opacity: 0` — otevřená, správně umístěná a neviditelná).

       Fallback `100% / 0` platí, než se nabídka poprvé otevře; do té doby je stejně skrytá.
   EN: ⚠️ `position: fixed`, NOT `absolute` (9 Sep 2026). `.plane-nav` has `overflow-x: auto`, so
       per spec the browser adds `overflow-y: auto` too — which would clip the absolutely
       positioned menu popping out BELOW the short bar. A fixed element is not clipped by
       ancestors' `overflow`, so it escapes with no DOM surgery.

       The coordinates come from `planeDropdown` (`static/js/nav_dropdown.js`) via the
       `--menu-top` / `--menu-left` variables it binds on the GROUP. They are deliberately not in
       the menu's `style`: `x-transition` writes there and the two would overwrite each other
       (leaving the menu at `opacity: 0` — open, correctly placed and invisible).

       The `100% / 0` fallback applies until the menu is first opened; it is hidden until then. */
.plane-nav-menu {
  position: fixed;
  top: var(--menu-top, 100%);
  left: var(--menu-left, 0);
  min-width: 13rem;
  padding: var(--space-1);
  background: var(--surface-overlay);
  border: var(--border-card-style);
  border-radius: var(--radius-container);
  /* CZ: Jediné místo, kde stín zůstává — plovoucí vrstva. Vzor: „modals / floating menus only".
     EN: The one place a shadow remains — a floating layer. The sample: "modals / floating menus only". */
  box-shadow: var(--shadow-overlay);
  z-index: var(--z-dropdown);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.plane-nav-menu a {
  padding: var(--space-1) 12px;
  border-radius: var(--radius-chip);
  font-size: var(--text-sm);
  color: var(--text-body);
  text-decoration: none;
  white-space: nowrap;
}
.plane-nav-menu a:hover { background: var(--surface-panel); color: var(--text-primary); text-decoration: none; }
.plane-nav-menu a.active { color: var(--text-primary); font-weight: var(--weight-subhead); }

/* CZ: Odkaz na druhou rovinu — tichý, drobný, vpravo. Vzor ho má jako prostý text, ne tlačítko:
       přepnutí roviny není akce, kterou dělá klient.
   EN: The link to the other plane — quiet, small, on the right. The sample renders it as plain
       text, not a button: switching planes is not something a client does. */
/* CZ: ODZNAK ROVINY (C-05) — tichý štítek „Interní pohled" pro interní role v přístavu.
       Šedý, ne barevný: je to orientace, ne varování. Klient ho nikdy nevidí (podmínka
       `user_is_ops` v šabloně), takže se s ničím u klienta neperе.

       `margin-left: auto` ho odsune doprava k přepínači rovin; `.plane-switch` za ním už
       auto-margin nepotřebuje, ale nechává se — kdyby odznak zmizel, přepínač zůstane vpravo.
   EN: THE PLANE BADGE (C-05) — a quiet "Internal view" label for internal roles in the harbour.
       Grey, not coloured: it is orientation, not a warning. A client never sees it (the
       `user_is_ops` condition in the template), so it competes with nothing on their screen.

       `margin-left: auto` pushes it right towards the plane switch; `.plane-switch` after it no
       longer needs its own auto margin, but keeps it — should the badge go, the switch stays right. */
.plane-badge {
  margin-left: auto;
  flex: none;
  align-self: center;
  padding: 2px var(--space-1);
  border-radius: var(--radius-pill);
  background: var(--gray-tint);
  color: var(--text-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-subhead);
  white-space: nowrap;
}

.plane-switch {
  /* CZ: `margin-left: auto` ho odsune na pravý konec navigace — ve vzoru sedí mezi navigací
         a ikonami vpravo. `flex: none`, aby se při scrollování navigace nesmrskl.
     EN: `margin-left: auto` pushes it to the navigation's right end — in the sample it sits
         between the nav and the icons on the right. `flex: none` so it does not shrink when the
         nav scrolls. */
  margin-left: auto;
  flex: none;
  align-self: center;
  padding-inline: 12px;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  text-decoration: none;
  white-space: nowrap;
}
.plane-switch:hover { color: var(--text-primary); text-decoration: none; }
@media (max-width: 768px) {
  /* CZ: Ve svislém panelu nemá „odsunutí doprava" smysl — přepínač je poslední položka seznamu.
     EN: In the vertical panel "push right" is meaningless — the switch is the list's last item. */
  .plane-switch { margin-left: 0; align-self: stretch; padding: 10px 12px; }
}

/* =====================
 * APP BODY (main)
 * ===================== */
.app-body { display: flex; flex: 1; min-height: calc(100vh - var(--header-height)); }

.sidebar {
  width: var(--sidebar-width);
  background: var(--surface-page);
  border-right: 1px solid var(--line-card);
  padding: var(--space-2);
  flex-shrink: 0;
  height: calc(100vh - var(--header-height));
  position: sticky;
  top: var(--header-height);
  overflow-y: auto;
}

.sidebar-section { margin-bottom: var(--space-2); }
.sidebar-section-label { padding: var(--space-1) var(--space-2); font-size: var(--text-xs); font-weight: var(--weight-subhead); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-secondary); }

.sidebar-link {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-chip);
  font-size: var(--text-sm);
  font-weight: var(--weight-eyebrow);
  color: var(--text-body);
  text-decoration: none;
  transition: background-color var(--transition-fast), color var(--transition-fast);
}
.sidebar-link:hover { background: var(--gray-tint); color: var(--text-primary); text-decoration: none; }
/* CZ: Aktivní odkaz — „strong" accent jako text na accent-soft tintu (brand #FF6B35 by na
       světlém tintu neprošel kontrastem). EN: Active link — "strong" accent as text on the
       accent-soft tint (brand #FF6B35 would fail contrast on the light tint). */
.sidebar-link.active { background: var(--orange-pale); color: var(--text-link); }
.sidebar-link-icon { width: 18px; height: 18px; flex-shrink: 0; }

/* CZ: Obsahová studna — vzor drží obsah v 1200 px (přístav) a centruje ho, protože bez levého
       sloupce by se řádky na širokém monitoru roztáhly přes celou šířku a přestaly se číst.
       Rovinu řízení pouští šířeji (`--well-ops`, 1280 px) přes `.main-content--ops`.
   EN: The content well — the sample keeps content within 1200 px (the portal) and centres it,
       because without a left column the lines would stretch across a wide monitor and stop being
       readable. The management plane runs wider (`--well-ops`, 1280 px) via `.main-content--ops`. */
.main-content {
  flex: 1;
  min-width: 0;
  width: 100%;
  max-width: var(--well-web);
  margin: 0 auto;
  padding: var(--space-4) var(--space-2);
}
.main-content--ops { max-width: var(--well-ops); }
@media (min-width: 768px) {
  .main-content { padding: var(--space-6) var(--space-4); }
}

/* =====================
 * PAGE HEADER (uvnitř main content)
 * =====================
 * CZ: TYPOGRAFIE NADPISU STRÁNKY ŽIJE V `components.css`, NE TADY (9. 9. 2026).
 *     Do 9. 9. existovaly TŘI kopie téhož přepisu — `.page-header h1` (77 šablon),
 *     `.dash-head-title` a `.progress-head-title`. Dvě z nich měly `letter-spacing:
 *     var(--tracking-tight)`, třetí ne, takže dědila `--h1-tracking` (−1.5 px) z `base.css`:
 *     stejně velký nadpis se v aplikaci sázel dvěma různými prostrky podle toho, na které
 *     obrazovce stál. Sloučeno do jediného pravidla — viz „NADPIS STRÁNKY" v `components.css`.
 *     Tady zůstává jen ROZVRŽENÍ hlavičky (flex, mezery), které je opravdu její.
 * EN: THE PAGE-TITLE TYPOGRAPHY LIVES IN `components.css`, NOT HERE (9 Sep 2026).
 *     Until 9 Sep there were THREE copies of the same override — `.page-header h1`
 *     (77 templates), `.dash-head-title` and `.progress-head-title`. Two of them set
 *     `letter-spacing: var(--tracking-tight)`, the third did not and therefore inherited
 *     `--h1-tracking` (−1.5px) from `base.css`: an identically sized heading was set with two
 *     different trackings depending on which screen it stood on. Merged into a single rule —
 *     see "PAGE TITLE" in `components.css`. What stays here is the header's LAYOUT (flex,
 *     spacing), which genuinely belongs to it.
 */
.page-header { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
/* CZ: flex-wrap — víc tlačítek (např. finance: Nahrát/Záznamy/Cashflow/Power of One) se na
       úzké obrazovce zalomí místo přetečení. EN: flex-wrap — multiple buttons wrap on a narrow
       screen instead of overflowing. */
.page-header-actions { display: flex; flex-wrap: wrap; gap: var(--space-1); }

/* =====================
 * FOOTER (public layout)
 * ===================== */
.footer {
  border-top: 1px solid var(--line-card);
  padding: var(--space-3) 0;
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

/* =====================
 * MOBILE — sidebar drawer
 * ===================== */
.sidebar-toggle { display: none; }
.sidebar-backdrop { display: none; position: fixed; inset: 0; background: rgba(26, 35, 50, 0.5); z-index: calc(var(--z-modal-backdrop) - 1); }

@media (max-width: 768px) {
  .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: var(--z-modal-backdrop);
    transform: translateX(-100%);
    transition: transform var(--transition-normal);
    height: 100vh;
  }
  .sidebar[data-open="true"] { transform: translateX(0); box-shadow: var(--shadow-overlay); }
  .sidebar-backdrop[data-open="true"] { display: block; }
  .sidebar-toggle { display: inline-flex; }

  /* CZ: Na mobilu se z TÉŽE navigace stane vysouvací panel. Vzor mobil neřeší vůbec (nemá
         jedinou media query) — tohle je proto dopočítané podle `FE_RESPONSIVE.md`, ne podle
         vzoru, a je to prozatímní stav do F7, kde se mobil dodělá pořádně.
         Panel se otevírá stejným hamburgerem a stejným stavem `sidebarOpen` jako dřív sidebar,
         takže se chování uživatele nemění.
     EN: On mobile the SAME nav becomes a slide-out panel. The sample does not cover mobile at all
         (not a single media query) — this is derived from `FE_RESPONSIVE.md`, not from the sample,
         and is an interim state until F7 finishes mobile properly.
         The panel opens with the same hamburger and the same `sidebarOpen` state the sidebar used,
         so the user's behaviour does not change. */
  .plane-nav {
    position: fixed;
    top: var(--header-height);
    bottom: 0;
    left: 0;
    width: min(18rem, 82vw);
    height: auto;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: var(--space-2);
    /* CZ: NEPRŮHLEDNÁ plocha — panel obsah PŘEKRÝVÁ. `--surface-card` je v tmavém režimu
           `rgba(255,255,255,.08)`, takže přes panel prosvítal text stránky a nečitelné byly
           obě vrstvy. Odhaleno 6. 9. 2026 (F7); `visual_snapshot.py` to nenafotil, protože
           panel se otevírá až klikem — proto vznikl `scratchpad/drawer_shot.py`.
       EN: An OPAQUE surface — the drawer COVERS content. `--surface-card` is
           `rgba(255,255,255,.08)` in dark mode, so the page's text showed through the drawer and
           both layers became unreadable. Found 6 Sep 2026 (F7); `visual_snapshot.py` never caught
           it because the drawer only opens on a click — hence `scratchpad/drawer_shot.py`. */
    background: var(--surface-overlay);
    border-right: var(--border-card-style);
    overflow-y: auto;
    z-index: var(--z-modal-backdrop);
    transform: translateX(-100%);
    /* CZ: `visibility: hidden` u zavřeného panelu (F8, 6. 9. 2026) — bez toho zůstávají odkazy
           uvnitř V POŘADÍ TABULÁTORU. Uživatel, který ovládá aplikaci klávesnicí, se pak
           tabuluje do menu, které NENÍ vidět: fokus zmizí za levý okraj obrazovky a není
           poznat, kde je. Samotný `transform` prvek z přístupnostního stromu neodstraní.

           `visibility` se přechází spolu s `transform`, aby panel při zavírání nezmizel
           skokem uprostřed animace — proto je v `transition` a ne jen přepnutá.
       EN: `visibility: hidden` on the closed drawer (F8, 6 Sep 2026) — without it the links
           inside stay IN THE TAB ORDER. A keyboard user then tabs into a menu that is NOT
           visible: focus disappears past the left edge of the screen with no way to tell where
           it is. `transform` alone does not remove an element from the accessibility tree.

           `visibility` is transitioned alongside `transform` so the drawer does not vanish
           abruptly mid-animation while closing — hence it is in `transition`, not just toggled. */
    visibility: hidden;
    transition: transform var(--transition-normal), visibility var(--transition-normal);
  }
  .plane-nav[data-open="true"] {
    transform: translateX(0);
    visibility: visible;
    box-shadow: var(--shadow-overlay);
  }

  /* CZ: Ve svislém panelu nedává podtrh smysl — aktivní položka se značí levým pruhem.
     EN: In a vertical panel an underline makes no sense — the active item gets a left bar. */
  .plane-nav-item {
    height: auto;
    padding: 10px 12px;
    border-bottom: 0;
    border-left: 3px solid transparent;
    margin-bottom: 0;
    border-radius: var(--radius-chip);
    justify-content: flex-start;
  }
  .plane-nav-item.active { border-left-color: var(--accent-attention); background: var(--surface-panel); }

  .plane-nav-group { flex-direction: column; align-items: stretch; }
  /* CZ: Podnabídka se ve svislém panelu nevznáší, ale rozbalí pod položkou — plovoucí menu
         v drawer nemá kam. EN: In the vertical panel the submenu does not float but expands
         beneath the item — a floating menu has nowhere to go inside a drawer. */
  .plane-nav-menu {
    position: static;
    box-shadow: none;
    border: 0;
    padding-left: var(--space-2);
    min-width: 0;
  }
}

/* =====================
 * PUBLIC LAYOUT (auth pages)
 * ===================== */
.public-layout { min-height: 100vh; display: flex; flex-direction: column; background: var(--gray-pale); }
.public-main { flex: 1; padding: var(--space-6) var(--space-2); }
