/* Metview — layout appky. Kostra vznikla podle makety
   `docs/design/maketa-oblasti.html` (#46); navigaci přepsalo #72 podle
   `docs/design/maketa-navigace.html`: mapa dostává celou plochu a všechno
   ostatní jsou překryvy nad ní — vlevo nahoře popisek produktu, vpravo
   svislý pruh legendy, dole JEDEN skleněný panel s členy, rodinami a
   časovou osou. Zasouvací svislé panely (legenda vlevo, členové vpravo)
   ani rodiny v záhlaví už nejsou.

   Tokeny (bg/panel/line/text/muted/accent/gold/lock/glass/btn/btn-on) jsou
   beze změny — obě makety je navrhly se stejnými hodnotami, viz CLAUDE.md
   „Dvě kvality…". */

:root {
  --bg: #0b1220;
  --panel: #131c2e;
  --line: #24304a;
  --text: #e8edf6;
  --muted: #94a3b8;
  --accent: #4ea1ff;
  --gold: #e6b84a;
  --lock: #7c8798;
  --glass: rgba(11, 18, 32, .74);
  --btn: #0f1728;
  --btn-on: #12253d;
  /* Podklad legendy — palety jsou návrhem průhledné, bílá dává nejvyšší
     kontrast pro barevná pásma (CLAUDE.md „Podklad mapy je bílý"). */
  --map-bg: #ffffff;

  /* Velikost podle ovládání (issue #46, bod 1): prst = základ, myš menší.
     Uživatelský krok malé/střední/velké (`html.fs-*`, viz níž) násobí navrch
     přes `@media (pointer:)` blok — kombinace dá přesně šest kroků z
     makety (`.app[data-pointer][data-size]`), beze změny JS. Střední =
     tenhle základ beze třídy (dřívější „normal"/nejmenší, #51). */
  --fs: 19px;
  --tap: 44px;
  --hdr: 52px;
}

@media (pointer: fine) {
  :root { --fs: 15px; --tap: 34px; --hdr: 44px; }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-size: var(--fs);
  line-height: 1.4;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior: none;
}

/* Uživatelský krok malé/střední/velké (hamburger menu, #51) — násobí `--fs`
   NAVRCH ovládací základny, ne místo ní (viz `:root`/`@media(pointer:fine)`
   výš). Střední nemá vlastní třídu (= tenhle základ). Hodnoty přesně
   z makety: 17/19/23 px na prstu, 13/15/19 px na myši. */
html.fs-small { --fs: 17px; }
html.fs-large { --fs: 23px; }
@media (pointer: fine) {
  html.fs-small { --fs: 13px; }
  html.fs-large { --fs: 19px; }
}

button { font: inherit; color: inherit; cursor: pointer; }
button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

svg.ic {
  width: 1.15em;
  height: 1.15em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: 0 0 auto;
}

#app {
  position: relative;
  display: grid;
  grid-template-rows: var(--hdr) 1fr;
  /* `--app-h` = skutečně viditelná výška z JS (`syncAppHeight()`, #69): po
     reloadu na telefonu `100dvh` občas přesáhne obrazovku a usekne spodní
     pruh rodin. `100dvh` zůstává jen jako výchozí hodnota před prvním během JS. */
  height: var(--app-h, 100dvh);
  /* `clip`, ne `hidden`: `hidden` dělá z `#app` posouvací kontejner, který
     jde posunout programově (`scrollIntoView`, fokus) — celá appka pak
     „cukla" do strany (2026-09-23). `clip` ořízne stejně, ale posunout nejde. */
  overflow: hidden;
  overflow: clip;
  /* Bez spodního odsazení (2026-10-23): mapa sahá až ke spodní hraně
     i pod pruh gesta domů na iPhonu, jinak tam v appce z plochy zůstal
     tmavý pruh. Bezpečný okraj si bere jen ovládání (`.bottom-ov`,
     `placeOverlays()`). */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           0 env(safe-area-inset-left);
}

/* --- záhlaví: hamburger, oblast, rodiny (jen na širokém), tarif, běh --- */
.hdr {
  /* Lišta leží NAD mapou (2026-09-23): `.stage` zabírá oba řádky mřížky.
     Díky tomu se lišta v režimu celé mapy jen odsune nahoru a mapa nemění
     velikost — dřív se zvětšila, obraz poskočil a dorovnávání polohy
     nesedělo (mapa sjela k severu). */
  grid-row: 1;
  grid-column: 1;
  position: relative;
  z-index: 6;
  transition: transform .34s cubic-bezier(.2, .8, .2, 1);
  display: flex;
  align-items: center;
  gap: .35rem;
  padding: 0 .4rem;
  min-width: 0;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

.icon-btn {
  flex: 0 0 auto;
  width: var(--tap);
  height: var(--tap);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: .5rem;
  background: var(--btn);
  color: var(--text);
}
.icon-btn:active { background: #16203a; }

.hamburger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 18px;
}
.hamburger span { display: block; height: 2px; border-radius: 1px; background: var(--text); }

.region-btn {
  flex: 0 0 auto;
  height: var(--tap);
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: 0 .6rem;
  border: 1px solid var(--line);
  border-radius: .5rem;
  background: var(--btn);
  font-weight: 600;
  font-size: .9rem;
  color: var(--text);
}
.region-btn .caret { color: var(--muted); font-size: .8em; }

.grow { flex: 1 1 auto; min-width: 0; }

.tier {
  flex: 0 0 auto;
  height: calc(var(--tap) - 8px);
  display: flex;
  align-items: center;
  gap: .3rem;
  padding: 0 .55rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
  font-size: .72rem;
  white-space: nowrap;
}
.tier b { color: var(--gold); }

/* Údaj o běhu = přepínač běhů (#81). Tlačítko, ne jen text: rámeček
   a caret jako u `.region-btn`, ať je poznat, že se na něj dá klepnout. */
.runinfo {
  flex: 0 0 auto;
  min-height: var(--tap);
  display: flex;
  align-items: center;
  gap: .35rem;
  padding: 0 .5rem;
  border: 1px solid var(--line);
  border-radius: .5rem;
  background: var(--btn);
  font-size: .66rem;
  line-height: 1.15;
  color: var(--muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.runinfo:hover { color: var(--text); }
.runinfo .caret { font-size: .9rem; }
.runinfo[data-source="chmi"] .runinfo__text { color: var(--text); }

/* --- pruh rodin a řádek členů (spodní skleněný blok, #72) ---------------
   Obojí je vodorovný scroller: prstem se posouvá nativně (`touch-action`),
   myší a perem vlastním tažením se setrvačností (`dragScroll()` v app.js).
   Tam, kde řádek pokračuje za okraj, je okraj zeslabený do průhledna —
   jediné, co uživateli řekne „posuň mě", bez šipek a bez scrollbaru. */
.hscroll {
  touch-action: pan-x;
  user-select: none;
  -webkit-user-select: none;
  cursor: grab;
}
.hscroll.dragging { cursor: grabbing; }
/* Během tažení nesmí pod prstem/myší nic reagovat — jinak by se tažení
   skončilo klepnutím na čip, přes který se zrovna přejíždělo. */
.hscroll.dragging * { pointer-events: none; }
.hscroll.fade-l { mask-image: linear-gradient(90deg, transparent, #000 22px); -webkit-mask-image: linear-gradient(90deg, transparent, #000 22px); }
.hscroll.fade-r { mask-image: linear-gradient(90deg, #000 calc(100% - 22px), transparent); -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 22px), transparent); }
.hscroll.fade-l.fade-r { mask-image: linear-gradient(90deg, transparent, #000 22px, #000 calc(100% - 22px), transparent); -webkit-mask-image: linear-gradient(90deg, transparent, #000 22px, #000 calc(100% - 22px), transparent); }

/* Šipka na okraji řádku (2026-09-18). Zeslabení obsahu do průhledna samo
   o sobě nestačí: když ořez padne do mezery mezi čipy, není co zeslabovat
   a řádek vypadá, že končí. Šipka je proti tomu jednoznačná a stojí navíc
   za to, že je zároveň ovládací prvek pro myš. Je vidět jen na té straně,
   kam se dá posunout (třídu `show` řídí `dragScroll()` v app.js).

   `tabindex="-1"`: klávesnice si řádek posune sama, když se Tabem dostane
   na čip za okrajem — šipka by v pořadí fokusu jen překážela. */
.hscroll-wrap { position: relative; min-width: 0; }
.hscroll-arrow {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 26px;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  z-index: 2;
  color: #dbe4f2;
  font-size: 1.1rem;
  line-height: 1;
  text-shadow: 0 0 4px rgba(8, 13, 24, .9);
}
.hscroll-arrow.show { display: flex; }
.hscroll-arrow--left {
  left: 0;
  background: linear-gradient(90deg, rgba(13, 21, 38, .92), rgba(13, 21, 38, 0));
}
.hscroll-arrow--right {
  right: 0;
  background: linear-gradient(270deg, rgba(13, 21, 38, .92), rgba(13, 21, 38, 0));
}

.fams {
  position: relative;
  display: flex;
  gap: .1rem;
  overflow-x: auto;
  scrollbar-width: none;
  min-width: 0;
  /* Dole bez odsazení: záložka musí dosednout na panel členů. Po stranách
     aspoň šířka zaobleného přechodu záložky (TAB_FILLET_PX v app.js). */
  padding: .1rem 12px 0;
}
/* Vycentrování, které se nerozbije při přetečení: pseudo-položky s auto
   okraji spolknou volné místo, a když žádné není, mají nulu — `justify-
   content: center` by u posuvného řádku uřízl začátek. */
.fams::before, .fams::after { content: ""; margin: auto; }
.fams::-webkit-scrollbar { display: none; }

/* `button { font: inherit }` (výš) má vyšší specificitu než holá třída —
   velikost písma čipů proto se selektorem `#app .chip`, ne `.chip`
   (past z makety, CLAUDE.md „Navigace Kde · Co · Kdy"). */
#app .chip {
  flex: 0 0 auto;
  height: calc(var(--tap) - 6px);
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: 0 .65rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-weight: 600;
  font-size: .92rem;
  white-space: nowrap;
  position: relative;
  z-index: 1;
  transition: color .2s;
}
/* Nevybrané položky nejsou „potlačené", jen nevybrané — `--muted` (#94a3b8)
   se na průsvitném pruhu nad světlou mapou četlo špatně. */
#app .chip { color: #aebbcd; }
.chip[aria-selected="true"] { color: #ffffff; }
.chip[disabled] { opacity: .4; }
.chip .caret { font-size: .7em; color: var(--muted); margin-left: -.1rem; }
/* Rodina bez aktivního člena, zobrazená jen díky přehledu (#48) — kliknutí
   jen informuje (toast), nikam neodkazuje. */
.chip.inactive { color: var(--lock); cursor: default; }

/* Záložka aktivní rodiny (#78): stejná barva jako panel členů pod ní
   (`--tab-bg`) a dosedá na něj, takže záložka a dlaždice pod ní čtou jako
   jeden celek — „tyhle produkty patří k téhle rodině". Při přepnutí
   rodiny KLOUŽE pod nový čip (přechod na `left`/`width`). */
.fam-tab {
  position: absolute;
  top: .1rem;
  bottom: 0;
  left: 0;
  width: 0;
  border-radius: .7rem .7rem 0 0;
  background: var(--tab-bg);
  /* Sklo (zpětná vazba 2026-09-23: „trošku víc skleněné"): lesk na horní
     hraně a světlejší horní polovina. Spodní část MUSÍ zůstat přesně
     `--tab-bg`, jinak by byl vidět šev se zaoblenými přechody a panelem. */
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .12), rgba(255, 255, 255, 0) 70%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .38), inset 1px 0 0 rgba(255, 255, 255, .1), inset -1px 0 0 rgba(255, 255, 255, .1);
  backdrop-filter: blur(10px) saturate(1.5);
  -webkit-backdrop-filter: blur(10px) saturate(1.5);
  z-index: 0;
  pointer-events: none;
  transition: left .38s cubic-bezier(.3, 1.2, .4, 1), width .38s cubic-bezier(.3, 1.2, .4, 1);
}
/* Zaoblené přechody záložky do panelu (jako záložky prohlížeče) — bez
   nich by záložka stála na panelu ostrými rohy. */
.fam-tab::before, .fam-tab::after {
  content: "";
  position: absolute;
  bottom: 0;
  width: 10px;
  height: 10px;
}
.fam-tab::before { left: -10px; background: radial-gradient(circle at 0 0, transparent 9.5px, var(--tab-bg) 10px); }
.fam-tab::after { right: -10px; background: radial-gradient(circle at 100% 0, transparent 9.5px, var(--tab-bg) 10px); }
/* Přechod, který se k panelu nevejde (záložka u okraje), zmizí a roh panelu
   pod ní je rovný — viz `placeMemberPanel()` v app.js. */
.fam-tab.nf-l::before, .fam-tab.nf-r::after { display: none; }
.member-panel.sq-l { border-top-left-radius: 0; }
.member-panel.sq-r { border-top-right-radius: 0; }
.fam-tab.blink { animation: tab-blink .6s ease; }
@keyframes tab-blink { 35% { background: rgba(78, 161, 255, .32); } }

/* Panel členů = obsah aktivní záložky. Široký jako obsah, vodorovně ho
   pod záložku posadí `placeMemberPanel()` v app.js. */
.member-panel {
  align-self: flex-start;
  width: max-content;
  max-width: 100%;
  border-radius: .75rem;
  background: var(--tab-bg);
  /* Sklo navazující na záložku: bez horního lemu (ten by přeškrtl styk se
     záložkou), lesk jen po stranách a dole a jemný stín pod panelem. */
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, .14), inset 1px 0 0 rgba(255, 255, 255, .08), inset -1px 0 0 rgba(255, 255, 255, .08), 0 6px 14px rgba(0, 0, 0, .22);
  backdrop-filter: blur(10px) saturate(1.5);
  -webkit-backdrop-filter: blur(10px) saturate(1.5);
  transition: margin-left .38s cubic-bezier(.3, 1.2, .4, 1);
}
.member-panel.blink { animation: tab-blink .6s ease; }
/* Mřížka se sloupci 1fr v řádku o šířce obsahu: všechny sloupce dostanou
   šířku nejdelšího popisku, dlaždice jsou tedy stejně široké (2026-09-23).
   `safe center`: u přetékajícího řádku by prosté `center` uřízlo začátek;
   prohlížeč bez `safe` si nechá `start`. */
.members {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  justify-content: start;
  justify-content: safe center;
  gap: .3rem;
  overflow-x: auto;
  scrollbar-width: none;
  min-width: 0;
  padding: .2rem .25rem .15rem;
  align-items: flex-start;
}
.members::-webkit-scrollbar { display: none; }

/* Dlaždice člena (#78): náhled toho, jak produkt vypadá, a krátký popisek.
   Úzká a stejně široká pro všechny — dřívější textové čipy byly „moc široké"
   a málo nápadné. Náhled je buňka spritu `icons/member-thumbs.webp`
   (96×64 px, zobrazený na polovinu kvůli displejům s dpr 2). */
/* Od 2026-09-23 je náhled jen nízký PROUŽEK nad popiskem (zpětná vazba:
   poměr 3:2 blok natahoval do výšky a nutil k titěrnému písmu). Popisek je
   na jeden řádek a o polovinu větší; dlaždice je široká jako popisek, proužek
   se roztáhne na její šířku a svisle se ořízne ze středu buňky spritu —
   poměr stran obrázku se tím nekřiví. */
#app .mtile {
  flex: 0 0 auto;
  min-width: 4.2rem;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 3px;
  padding: 4px 5px 3px;
  border: 0;
  border-radius: .55rem;
  background: transparent;
  color: #c3cedd;
  font-size: .72rem;
  font-weight: 600;
  line-height: 1.15;
  transition: color .2s, background .2s;
}
.mthumb {
  display: block;
  flex: 0 0 auto;
  height: 12px;
  border-radius: 4px;
  background-image: var(--member-thumbs);
  background-repeat: no-repeat;
  /* Buňka spritu = šířka dlaždice, výška podle poměru buňky. Procentní
     pozice: buňka i leží na i/(n−1) šířky spritu. */
  background-size: calc(var(--cells) * 100%) auto;
  background-position: calc(var(--cell) / (var(--cells) - 1) * 100%) 50%;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .16);
  transition: box-shadow .2s, transform .2s;
}
.mthumb--icon { display: flex; align-items: center; justify-content: center; background: rgba(255, 255, 255, .06); }
.mthumb--icon svg.ic { width: 10px; height: 10px; }
.mlabel {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: center;
  max-width: 100%;
}
.mtile[aria-selected="true"] { color: #ffffff; background: rgba(255, 255, 255, .1); }
/* Vybraný náhled: silný rámeček v barvě akcentu — nese to tvar i světlost,
   ne jen odstín (barvocit). */
.mtile[aria-selected="true"] .mthumb { box-shadow: 0 0 0 2px var(--accent), 0 0 0 4px rgba(78, 161, 255, .25); }
.mtile:not([aria-selected="true"]):hover .mthumb { transform: translateY(-1px); }
.mtile[disabled] { opacity: .4; }
/* „Mrknutí" po přepnutí rodiny: dlaždice naběhnou zleva postupně.
   `prefers-reduced-motion` appka vypíná globálně. */
.member-panel.blink .mtile { animation: chip-in .34s both; animation-delay: calc(var(--i) * 38ms); }
@keyframes chip-in {
  from { opacity: 0; transform: translateY(6px) scale(.94); }
  to { opacity: 1; transform: none; }
}

/* --- plátno: mapa dostane celou plochu, vše ostatní jsou překryvy --- */
.stage {
  grid-row: 1 / -1;
  grid-column: 1;
  position: relative;
  min-height: 0;
  background: var(--bg);
}
.map { position: absolute; inset: 0; width: 100%; height: 100%; }

.ov {
  position: absolute;
  background: var(--glass);
  border-radius: .45rem;
  padding: .25rem .55rem;
  font-size: .8rem;
  color: #fff;
  pointer-events: none;
}
/* Popisek produktu + atribuce Mapy.cz pod ním, jeden svislý sloupec v levém
   horním rohu (přesunuto z `#sideLeft` u panelu sytosti, #59 — tam se
   atribuce posouvala s `placeLayers()` podle otevřeného/zavřeného panelu a
   při otevření `#layers` se s ním vizuálně překrývala, viz git historie
   screenshotu v ticketu). Tady je pozice napevno, nezávislá na jakémkoli
   panelu — nemůže kolidovat s ničím, co se zasouvá/vysouvá. */
.ov-topleft {
  position: absolute;
  left: .5rem;
  top: calc(var(--hdr) + .5rem);
  z-index: 3; /* nad `.layers` (z-index 2) — tlačítko/nudge zůstanou klikatelné, i když panel sytosti sjede přes stejnou oblast */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  /* Vpravo nahoře je logo (2026-09-23, ikona nad nápisem) — karta k němu
     nesmí dojet. Nápis „SimplyMeteo" je ~4,5 rem široký, s odsazením od
     okraje a mezerou ke kartě to dá 6,2 rem (dlouhý název produktu jinak
     přejel první písmeno). */
  max-width: calc(100% - 6.2rem);
}
.ov-label {
  position: static;
  max-width: 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 .4rem;
  font-size: .95rem;
  font-weight: 600;
  pointer-events: auto;
}
/* Karta vlevo nahoře: název, čas, model (2026-09-23). Šířka podle obsahu,
   ale nejvýš tolik, aby se řádek s modelem raději zalomil, než aby kartu
   roztáhl — dřív ji roztáhl skoro přes celý telefon a vpravo se překryla
   s časem a logem. */
.ov-label {
  max-width: min(100%, 19rem);
  /* Mřížka, ne zalamovaný flex: (i) musí zůstat na řádku s názvem a raději
     se zalomí dlouhý název (na dva řádky) — ve flexu (i) odpadlo na vlastní
     řádek. Čas a model jdou přes oba sloupce. */
  display: grid;
  grid-template-columns: minmax(0, max-content) auto;
  justify-content: start;
}
.ov-when { grid-column: 1 / -1; }
.ov-when {
  flex: 1 0 100%;
  font-size: 1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.3;
}
.ov-when:empty { display: none; }
/* Popisek produktu je tlačítko do přehledu „Co zobrazit" (#72) — vypadá
   jako text, chová se jako nabídka (šipka dolů za popiskem). */
.ov-label .prod {
  display: flex;
  align-items: center;
  gap: .35rem;
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  font-weight: 600;
  text-align: left;
}
.ov-label .prod .caret { flex: 0 0 auto; color: var(--muted); font-size: .7em; }
/* Plný název se na úzkém displeji raději zalomí, než aby se useknul. */
.ov-label .prod span { overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.ov-label small { font-weight: 400; color: var(--muted); }
.ov-label .info {
  flex: 0 0 auto;
  width: 1.5em;
  height: 1.5em;
  border-radius: 50%;
  border: 1px solid var(--muted);
  background: transparent;
  color: var(--muted);
  font-size: .8em;
  display: grid;
  place-items: center;
  padding: 0;
}

/* --- legenda: svislý pruh u pravého okraje mapy (#72) -------------------
   Nahrazuje zasouvací panel vlevo s úchytem („pěst na oko", zpětná vazba).
   Pruh je dost úzký, aby mohl být vidět pořád — legenda je pro čtení mapy
   podstatná a schovávat ji znamenalo, že ji uživatel neměl, když ji
   potřeboval. Hodnoty stojí VLEVO od pruhu, bílé s tmavým halem, takže
   nepotřebují vlastní podklad a nekřižují mapu víc, než musí. */
.legend-strip {
  position: absolute;
  right: .5rem;
  /* Pod logem vpravo nahoře (ikona nad nápisem). */
  top: calc(var(--hdr) + 4rem);
  /* Sloupce sekcí (2026-09-23): první sloupec u okraje, další vlevo od něj. */
  display: flex;
  flex-direction: row-reverse;
  align-items: stretch;
  gap: 8px;
  z-index: 1;
  pointer-events: none;
}
.legend-col { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.legend-sec { display: flex; flex-direction: column; align-items: flex-end; flex: 1 1 0; min-height: 0; }
/* `display:flex` na třídě přebije UA `[hidden]` (stejná specificita, autor
   vyhrává) — bez tohohle by se schovaná legenda pořád kreslila (#55). */
.legend-strip[hidden] { display: none; }
.legend-strip__unit {
  font-size: .6rem;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 0 3px rgba(0, 0, 0, .9), 0 0 6px rgba(0, 0, 0, .7);
  margin-bottom: 3px;
  padding-right: 2px;
  white-space: nowrap;
}
.legend-strip__body { position: relative; flex: 1 1 auto; min-height: 0; display: flex; gap: 5px; align-items: stretch; }
.legend-strip__labels {
  position: relative;
  width: 44px;
  /* Stejný důvod jako u pruhu: čísla přes šrafu nešla přečíst. */
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  border-radius: 6px;
}
.legend-strip__labels span {
  position: absolute;
  right: 0;
  transform: translateY(-50%);
  font-size: .62rem;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 0 3px rgba(0, 0, 0, .95), 0 0 6px rgba(0, 0, 0, .7);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  line-height: 1;
}
.legend-strip__labels span.cat { font-weight: 600; }
/* Canvas ABSOLUTNĚ přes pruh s pevnou šířkou: uvnitř flex položky si jinak
   vynutí svou vnitřní šířku (násobek dpr) a `width:100%` se vyřeší
   cyklicky na 0 — pruh vyjde prázdný (past z makety, CLAUDE.md). */
.legend-strip__bar {
  position: relative;
  flex: 0 0 20px;
  width: 20px;
  min-width: 0;
  border-radius: 7px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .4);
  /* ŽÁDNÝ vlastní podklad (2026-09-18): pruh je průsvitný stejně jako data,
     takže pod ním prosvítá mapa a pásmo v legendě vypadá přesně tak, jak
     vypadá na mapě. Dřív se pásma míchala na bílou, což u palet nesoucích
     hodnotu krytím (dohlednost) ukazovalo něco jiného, než co uživatel
     doopravdy vidí. */
  background: transparent;
  /* Rozmazání pod pruhem (2026-09-27): šrafa utlumení termiky prosvítala
     skrz průsvitný pruh a legenda byla nečitelná. Rozmazání čáry šrafy
     slije, barva mapy pod pruhem zůstane. */
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
}
.legend-strip canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.legend-strip__bar i { position: absolute; left: 0; right: 0; height: 1px; background: rgba(0, 0, 0, .28); }

/* Telefon (dotyk na úzkém displeji): užší pruh, menší písmo, popisek jen na
   každé druhé hranici a jen spodní část výšky mapy — v plné výšce jí bylo
   „opravdu moc" (zpětná vazba, šesté kolo makety). Tablet a počítač mají
   plnou verzi. Výšku a spodní okraj dopočítává `placeOverlays()` v app.js
   podle výšky spodního bloku. */
@media (pointer: coarse) and (max-width: 699px) {
  .legend-strip { right: .35rem; }
  .legend-strip__bar { flex-basis: 12px; width: 12px; border-radius: 5px; }
  .legend-strip__labels { width: 34px; }
  .legend-strip__labels span, .legend-strip__unit { font-size: .55rem; }
  .legend-strip__body { gap: 3px; }
}

/* --- hodnota v bodě (#29, fáze 2) ---------------------------------------
   Tlačítko nad tlačítkem polohy (svislou pozici počítá `placeOverlays()`),
   na dotyku i na počítači (od 2026-09-23 — myš má navíc hodnotu u kurzoru,
   ale připnutý bod je potřeba ke sledování hodnoty v čase). Křížek sedí
   přesně ve středu mapy, bublina nad ním — prst ji při posouvání mapy
   nezakrývá. */
.probe-btn {
  position: absolute;
  left: .5rem;
  z-index: 2;
  background: var(--glass);
}
.probe-btn[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); }
/* OGN Live (#238): nad tlačítkem hodnoty v bodě, pozici počítá
   `placeProbeBtn()`. Pod ikonou drobný nápis, ať je jasné, co dělá. */
.ogn-live-btn {
  position: absolute;
  left: .5rem;
  z-index: 2;
  background: var(--glass);
  flex-direction: column;
  gap: 0;
  line-height: 1;
}
.ogn-live-btn[hidden] { display: none; }
.ogn-live-btn svg { margin-top: -2px; }
.ogn-live-btn__txt { font-size: .5rem; font-weight: 800; letter-spacing: .06em; margin-top: -3px; }
.ogn-live-btn[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); }
.ogn-live-btn[aria-pressed="true"] .ogn-live-btn__txt { animation: ogn-live-pulse 1.6s ease-in-out infinite; }
@keyframes ogn-live-pulse { 50% { opacity: .35; } }
/* Záznam letu (#238): tmavá karta jako spodní blok, barogram přes celou
   šířku. `touch-action: none` — tažení prstem po barogramu nesmí posouvat
   stránku ani mapu. */
.ogn-panel {
  position: absolute;
  z-index: 3;
  padding: .4rem .55rem .45rem;
  border-radius: .7rem;
  background: rgba(11, 18, 32, .9);
  border: 1px solid rgba(255, 255, 255, .18);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .4);
  color: #fff;
  font-size: .78rem;
  line-height: 1.3;
}
.ogn-panel[hidden] { display: none; }
/* Hvězdička: obrys = není oblíbené, plná zlatá = oblíbené. */
.ogn-panel__fav {
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  margin: -.2rem 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: .5rem;
  background: transparent;
  color: #c3cedd;
}
.ogn-panel__fav[hidden] { display: none; }
.ogn-panel__fav svg.ic, .ogn-fav-filter-btn svg.ic { width: 1.25rem; height: 1.25rem; }
.ogn-panel__fav[aria-pressed="true"], .ogn-fav-filter-btn[aria-pressed="true"] { color: #ffd23f; }
.ogn-panel__fav[aria-pressed="true"] svg.ic, .ogn-fav-filter-btn[aria-pressed="true"] svg.ic { fill: currentColor; }
/* Filtr oblíbených nad OGN Live ve sloupci tlačítek (`placeProbeBtn()`);
   vedle by ho zakryl panel záznamu letu. */
.ogn-fav-filter-btn {
  position: absolute;
  left: .5rem;
  z-index: 2;
  background: var(--glass);
}
.ogn-fav-filter-btn[hidden] { display: none; }
.ogn-fav-filter-btn[aria-pressed="true"] { border-color: #ffd23f; }
.ogn-panel__head { display: flex; align-items: flex-start; gap: .4rem; }
.ogn-panel__id { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.ogn-panel__title { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ogn-panel__stats { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ogn-panel__close {
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  margin: -.2rem -.25rem 0 0;
  border: 0;
  border-radius: .5rem;
  background: transparent;
  font-size: 1.3rem;
  line-height: 1;
  color: #c3cedd;
}
.ogn-panel__baro {
  display: block;
  width: 100%;
  height: 84px;
  margin-top: .3rem;
  touch-action: none;
  cursor: crosshair;
}
.ogn-panel__cursor { margin-top: .15rem; color: #c3cedd; font-size: .72rem; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Bod: kroužek na zeměpisném místě, čárkovaná vodicí čára a karta stranou
   (zadání 2026-09-23: karta přímo nad bodem zakrývala místo zájmu).
   Prvek je nulový, obsah přetéká — polohu drží MapLibre `Marker`. */
.probe-pin { position: relative; width: 0; height: 0; pointer-events: none; }
.probe-pin[hidden] { display: none; }
.probe-ring {
  position: absolute;
  left: -9px;
  top: -9px;
  width: 18px;
  height: 18px;
  border: 2.5px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 0 1.5px rgba(0, 0, 0, .6), inset 0 0 0 1.5px rgba(0, 0, 0, .35);
}
.probe-ring::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 3px;
  height: 3px;
  margin: -1.5px 0 0 -1.5px;
  border-radius: 50%;
  background: #fff;
}
.probe-lead { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; }
.probe-lead line {
  stroke: #fff;
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
  filter: drop-shadow(0 0 1px rgba(0, 0, 0, .9));
}
.probe-card {
  position: absolute;
  white-space: nowrap;
  padding: .3rem .6rem;
  border-radius: .6rem;
  background: rgba(11, 18, 32, .88);
  border: 1px solid rgba(255, 255, 255, .22);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
  color: #fff;
  font-size: .8rem;
  line-height: 1.35;
  font-variant-numeric: tabular-nums;
  /* Klepnutí kartu zavře (2026-10-26), proto přijímá události. */
  pointer-events: auto;
  cursor: pointer;
}
.probe-card:empty { display: none; }
/* Křížek přesahuje roh karty: nezvětšuje ji a je vidět na první pohled. */
.probe-close {
  position: absolute;
  top: -.55rem;
  right: -.55rem;
  width: 1.3rem;
  height: 1.3rem;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .35);
  background: rgba(11, 18, 32, .95);
  color: #fff;
  font: 700 .9rem/1 system-ui, sans-serif;
  cursor: pointer;
}
/* Dotyk: větší cíl bez většího kolečka. */
@media (pointer: coarse) {
  .probe-close::after { content: ""; position: absolute; inset: -.5rem; }
}
.probe-row { display: flex; justify-content: space-between; align-items: baseline; gap: .8rem; }
.probe-label { color: #c3cedd; }
/* Rozpětí dne pod hodnotou (vlna a svah): doplněk k řádku nad sebou. */
.probe-row--range { font-size: .88em; }
.probe-row--range .probe-label { padding-left: .7em; }
.probe-row--range .probe-value { font-weight: 600; color: #dbe4f0; }
.probe-value { display: inline-flex; align-items: baseline; font-weight: 700; }
/* Číslo v poli pevné šířky zarovnané doprava, jednotka za ním — šířky dává
   `channelNumWidth()` v app.js podle tabulky produktu. */
.probe-num { display: inline-block; text-align: right; }
.probe-unit { display: inline-block; margin-left: .25em; text-align: left; font-weight: 600; }
.probe-sep { margin: 0 .35em; color: #93a3ba; }
.probe-unit--tight { margin-left: 0; }
/* Denní přehled (2026-09-23): „max …" nad úrovní hodnoty, „min …" pod ní,
   malým písmem vpravo — sloupec je vyšší než hodnota, ta stojí uprostřed.
   Poloha nese význam (barvocit), barva jen pomáhá. Šířka vyhrazená
   dopředu, viz `dailyRangeEl()`. */
.probe-row:has(.probe-daily) { align-items: center; }
/* Řádky přehledu přesahují nad a pod hodnotu — karta jim dá místo. */
.probe-card:has(.probe-daily) { padding-top: .6rem; padding-bottom: .6rem; }
.probe-daily {
  display: inline-flex;
  flex-direction: column;
  justify-content: space-between;
  align-self: stretch;
  gap: 1.1em;
  margin-left: .6em;
  font-size: .62rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}
.probe-daily__top { color: #ffc2b0; min-height: 1em; margin-top: -.55em; }
.probe-daily__bottom { color: #a9d6ff; min-height: 1em; margin-bottom: -.55em; }
.probe-card--single .probe-value { font-size: 1.05rem; }
.probe-card--muted { font-size: .75rem; color: #c3cedd; }
.probe-card--stale { opacity: .45; transition: opacity .15s; }
/* Znak Premium vedle textu: zlatý, velikost podle písma. */
.premium-ico { width: 1.15em; height: 1.15em; margin-right: .3em; vertical-align: -.2em; color: var(--gold); }
/* Verze Zdarma (#118): karta místo hodnot nabízí ukázku. */
.probe-card--locked { pointer-events: auto; max-width: 13rem; white-space: normal; }
.probe-locked { font-size: .75rem; color: #c3cedd; }
#app .probe-demo, #app .package-demo {
  margin-top: .35rem; padding: .3rem .55rem; border: 1px solid var(--gold);
  border-radius: .45rem; background: transparent; color: var(--gold);
  font-size: .72rem; font-weight: 600; text-align: left;
}
.row.package .ttl .package-lock { color: var(--gold); font-weight: 600; }
.row.package .ttl .package-lock--plain { color: var(--muted); font-weight: 400; }
/* Odznak ceny: číslo, slovo a řada mincí (jedna za metcoin). */
.row.package .ttl .package-cost {
  display: inline-flex; align-items: center; gap: .35em; width: max-content; max-width: 100%;
  margin-top: .35rem; padding: .18rem .6rem; border-radius: 999px;
  border: 1px solid var(--gold); background: rgba(255, 200, 80, .12); color: var(--gold);
}
.row.package .ttl .package-cost span { display: inline-flex; margin: 0; color: inherit; }
.row.package .ttl .package-cost__n { font-size: 1.35em; font-weight: 700; line-height: 1; }
.row.package .ttl .package-cost__u { font-size: .85em; }
.row.package .ttl .package-cost__pips { gap: .16em; margin-left: .15em; }
.package-cost__pips i { width: .5em; height: .5em; border-radius: 50%; background: var(--gold); }
.row.package.off .package-cost { opacity: .85; }
.tiers button small { font-size: .82em; opacity: .8; }
.package-img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: .4rem; margin-bottom: .45rem; }
.tiers button .premium-ico { margin-right: .2em; }
/* Karta u kurzoru: vpravo nahoře od hrotu, ať ho nezakrývá. */
.probe-hover { z-index: 3; transform: translate(14px, calc(-100% - 10px)); }
.probe-hover[hidden] { display: none; }
/* Hláška „bez hodnoty" krátce nad spodním menu, ne uprostřed mapy. */
.probe-hint {
  position: absolute;
  left: 50%;
  z-index: 4;
  transform: translate(-50%, 6px);
  padding: .25rem .7rem;
  border-radius: .5rem;
  background: rgba(11, 18, 32, .88);
  border: 1px solid var(--line);
  color: #c3cedd;
  font-size: .72rem;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s, transform .2s;
}
.probe-hint.show { opacity: 1; transform: translate(-50%, 0); }

/* Poloha uživatele — vlastní tlačítko vlevo dole (#72, pravý okraj patří
   legendě). Svislou pozici počítá `placeOverlays()` nad spodním blokem. */
.locate-btn {
  position: absolute;
  left: .5rem;
  bottom: .5rem;
  z-index: 2;
  background: var(--glass);
}
/* Mezistav „získávám polohu" (#53) — okamžitá zpětná vazba na klik, ne až
   na výsledek geolokace. */
/* Ikona polohy (#82): obrys = poloha neznámá, plný střed v barvě akcentu =
   appka polohu sleduje (`watchPosition`). */
.locate-ic__dot { fill: currentColor; stroke: none; }
#locateBtn:not([data-tracking]) .locate-ic__dot { fill: none; stroke: currentColor; stroke-width: 2; }
#locateBtn[data-tracking] { color: var(--accent); }
#locateBtn[aria-busy="true"] { opacity: .55; pointer-events: none; animation: locate-pulse 1.1s ease-in-out infinite; }
@keyframes locate-pulse { 50% { opacity: .95; } }

/* --- menu zobrazení produktu: ikona v `.ov-topleft` (#51/#55, přesunuto
   #62 — zpětná vazba: tlačítko pod legendou nikdo nenacházel). Normální
   flow, žádný vlastní `top`/`z-index` — `.ov-topleft` ho řídí sama, stejně
   jako popisek produktu a atribuci Mapy.cz. Panel `.layers` sám JE
   `position:absolute` a svůj `top` čte z rendered pozice tohohle tlačítka
   (`placeLayers()` v app.js), ať sedí vizuálně pod ním. */
.layers-btn { background: var(--glass); }
.layers-btn.hidden { visibility: hidden; }
/* Atribuce Mapy.cz — licence dlaždic vyžaduje viditelnou značku NA MAPĚ (ne
   v zasunovacím panelu), proto trvalý kompaktní odkaz, dřív pod ikonou
   vrstev (#55), od #59 pod popiskem produktu vlevo nahoře (`.ov-topleft`) —
   místo, které se nikdy nezasouvá ani nehýbe s jiným panelem. Text „Seznam.cz
   a.s. and others“ (v `title`) i odkaz ověřené 2026-09-11 proti
   developer.mapy.com/rest-api-mapy-cz/atribution/. */
/* `.attrib-row` drží Mapy.cz a (jen na CHMI produktech) ČHMÚ VEDLE SEBE,
   ne pod sebou — `.ov-topleft` je sloupcový flex, takže dva přímé potomky
   by se naskládaly svisle. `flex-wrap` pro případ, že by se na úzkém
   telefonu obě naráz nevešly vedle sebe. */
.attrib-row { display: flex; flex-wrap: wrap; gap: 4px; }
.map-attrib {
  display: block;
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: .4rem;
  padding: 1px 6px;
  font-size: .6rem;
  line-height: 1.6;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}
.map-attrib:hover, .map-attrib:focus-visible { color: var(--text); }
/* `[hidden]` samo o sobě NESTAČÍ — `.map-attrib { display: block }` výš má
   stejnou specificitu jako UA pravidlo `[hidden]{display:none}` a autorské
   CSS UA styl vždy přebije, takže `#chmiAttrib.hidden` zůstávalo viditelné
   na všech produktech, ne jen CHMI (nahlášeno 2026-09-14). Tenhle selektor
   má vyšší specificitu (třída + atribut) a `hidden` tím pádem skutečně
   skryje. */
.map-attrib[hidden] { display: none; }
/* Nabídka druhého podrobného modelu ve ztmavené ploše mapy (2026-10-02).
   Nekřiklavé: sklo jako ostatní překryvy, žádná barva navíc. `#app` kvůli
   specificitě `#app button { font: inherit }` (past z makety navigace). */
#app .alt-model {
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .35rem .8rem;
  min-height: var(--tap);
  font-size: .8rem;
  color: var(--text);
  white-space: nowrap;
  cursor: pointer;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
#app .alt-model:hover, #app .alt-model:focus-visible { border-color: var(--muted); }
#app.immersive .alt-model { display: none; }
/* Levý okraj panelu SLEDUJE `#layersBtn` (`placeLayers()` v app.js), ne
   pevný `--edge` odstup (#67, zpětná vazba: na mobilu "uskočené víc
   doleva" než na počítači a "odtržené od tlačítka" — `--edge` byl 32px na
   dotyku / 8px na myši, nezávisle na tom, kde tlačítko doopravdy sedí,
   takže se zarovnání rozešlo). `left: .5rem` tady je jen výchozí hodnota
   pro okamžik PŘED prvním voláním `placeLayers()`, přepíše se hned. */
.layers {
  position: absolute;
  left: .5rem;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 2px;
  transform: translateX(calc(-100% - 10px));
  transition: transform .2s ease;
}
.layers.open { transform: none; }
/* Šířky v `rem`, ne v px (#68): obsah (písmo, odsazení) roste s `--fs`, takže
   pevných 186px/90px přeteklo doprava na dotyku (19 px) a u většího písma —
   na iPadu to vypadalo jako chyba vykreslování WebKitu, nebyla. */
.layers .body {
  /* Šířka sloupce s ovládacím prvkem — jedno číslo pro posuvníky i tlačítko
     polohy, ať se nerozjedou nezávisle na sobě. */
  --layers-control: 5.6rem;
  /* Výška řádku: `max()` proto, že ji jednou určuje dvouřádkový popisek
     (roste s `--fs`) a jindy tlačítko polohy (roste s `--tap`) — u myši je
     `--tap` větší než dva řádky drobného písma, na dotyku s velkým písmem
     naopak. Bez `max()` by při jedné z těch kombinací vyšel jeden řádek
     vyšší než ostatní. */
  --layers-row: max(1.95rem, calc(var(--tap) - 6px));
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: .5rem;
  padding: .45rem .6rem;
  width: 12.4rem;
  max-width: calc(100vw - 1rem);
  display: grid;
  gap: .3rem;
}
/* Řádky panelu jsou GRID se dvěma sloupci (popisek | ovládací prvek), ne
   `flex` + `space-between` (zpětná vazba 2026-09-15: „slidery mají každý
   jinou šířku"). U flexu byl posuvník `flex: 0 1 auto`, takže se u delšího
   popisku smrskl — každý řádek pak měl jinak široký posuvník a jinde
   začínal. Pevný druhý sloupec to dělá za nás: všechny posuvníky mají
   TOTOŽNOU šířku i levý okraj, popisek dostane zbytek (`minmax(0,1fr)`,
   ne `1fr` — bez toho se sloupec nesmrskne pod `min-content` a dlouhé
   slovo by řádek rozšířilo).

   `min-height` + `line-height` řeší druhou půlku téže zpětné vazby
   („zalamování řádků popisu přidává mezeru"): dvouřádkový popisek se vejde
   do stejné výšky jako jednořádkový, takže mezery mezi řádky zůstávají
   stejné bez ohledu na to, který popisek se zalomí. Výška i písmo jsou
   v `rem`, tedy v `--fs` (viz `html` výš), takže poměr platí ve všech
   krocích velikosti písma — kdyby popisek někdy potřeboval tři řádky,
   tohle je místo, kde se výška zvedne, ne kde se zmenší písmo. */
.layers .body label {
  font-size: .68rem;
  color: var(--muted);
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--layers-control);
  align-items: center;
  gap: .5rem;
  min-height: var(--layers-row);
  line-height: 1.15;
}
.layers .body input { width: 100%; min-width: 0; margin: 0; accent-color: var(--accent); }
/* Malý nadpis panelu (#73) — jen ať je jasné, co panel je, žádný
   `.sheet__head`/velké písmo. */
.layers .body .layers-title {
  font-size: .68rem;
  font-weight: 600;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: .04em;
}
/* Ladicí pole (#73, nahrazuje číselné boxy z #71 — "zobrazuje se to téměř
   nepoužitelně"). Čtyři hodnoty čárkou oddělené, čte se z něj i do něj
   zapisuje (`syncDebugField()`/`applyDebugField()` v app.js) — schované,
   dokud appka neběží v "Režimu ladění" (`#layers.debug`, viz níž). */
.layers .body input.debug-field {
  width: 100%;
  box-sizing: border-box;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: .25rem;
  font-size: .68rem;
  padding: .3rem .4rem;
  margin: 0;
}
/* Řádek „Moje poloha" (#55, dřív plovoucí `.locate` tlačítko na mapě) —
   stejné rozvržení jako `.layers .body label` výš (popisek vlevo, ovládací
   prvek vpravo), jen bez `<label>`, protože nejde o formulářový prvek. */
.layers .body .layers-row {
  font-size: .68rem;
  color: var(--muted);
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--layers-control);
  align-items: center;
  gap: .5rem;
  min-height: var(--layers-row);
  line-height: 1.15;
}
/* Tlačítko doprava ve svém sloupci — ten je stejně široký jako u posuvníků,
   takže ikona lícuje s jejich pravým okrajem. */
.layers .body .layers-row .icon-btn {
  width: calc(var(--tap) - 6px);
  height: calc(var(--tap) - 6px);
  justify-self: end;
}
/* Odstín/průhlednost symbolů (#70) — vlastní grid uvnitř `.body`, aby dva
   vnořené `<label>` dostaly stejnou mezeru mezi sebou jako `.body` sama dává
   svým přímým dětem (ta se na vnořené prvky nevztahuje). */
.layers .body .layers-symbols { display: grid; gap: .3rem; }
/* `[hidden]` samo o sobě NESTAČÍ — `display:grid` výš má stejnou/vyšší
   specificitu než UA pravidlo `[hidden]{display:none}` a autorské CSS
   vyhrává bez ohledu na pořadí (stejná past jako `.map-attrib[hidden]`,
   viz CLAUDE.md „#69"). Bez tohohle zůstal řádek vidět i na produktech bez
   overlaye, přestože `productHasSymbolOverlay()` v app.js `hidden` nastavil
   správně. */
.layers .body .layers-symbols[hidden] { display: none; }
/* Odstín symbolů se schovává i samostatně: v režimu částic (#74) na
   produktu, kde jsou symboly JEN šipky, by ten posuvník neovládal nic
   viditelného (částice mají barvu pevnou). `label` má `display:grid` výš,
   takže i tady platí, že `[hidden]` samo nestačí. */
.layers .body .layers-symbols label[hidden] { display: none; }
/* Přepínač praporky/částice (#74) — dvě ikony ve stejném sloupci, ve kterém
   jinde sedí posuvník nebo tlačítko polohy, takže pravý okraj lícuje se
   zbytkem panelu. Rozměr dědí z `.layers-row .icon-btn` výš; ve sloupci
   5.6rem se dvojice vejde na dotyku i u myši ve všech třech krocích písma. */
.layers .body .layers-row.layers-wind[hidden] { display: none; }
.wind-style-group { display: flex; gap: .3rem; justify-self: end; }
/* Vibrace u záblesku výboje (2026-09-15) — stejný tvar řádku jako přepínač
   větru, včetně toho, proč `[hidden]` potřebuje vlastní pravidlo (viz
   `.layers-symbols[hidden]` výš). Řádek se zobrazuje jen na produktu
   s blesky a jen tam, kde `navigator.vibrate()` existuje. */
.layers .body .layers-row.layers-lightning[hidden] { display: none; }
#layersHapticsBtn[aria-pressed="true"], #ognBtn[aria-pressed="true"], .tp-row .icon-btn[aria-pressed="true"] { border-color: var(--accent); background: var(--btn-on); color: var(--text); }
.wind-style-opt[aria-pressed="true"] { border-color: var(--accent); background: var(--btn-on); color: var(--text); }
/* Návrat na výchozí zobrazení produktu (2026-09-15) — ikona „šipka zpět"
   v nadpisovém řádku panelu, ne tlačítko přes celou šířku: text navíc pod
   posuvníky panel opticky roztahoval, kdežto nadpisový řádek už existuje a
   ikona v něm nestojí ani řádek navíc. Menší než `.layers-row .icon-btn`
   (poloha) — je to opravný krok, ne hlavní akce panelu. */
.layers .body .layers-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .4rem;
}
.layers .body .layers-title > span { white-space: nowrap; }
.layers .body .layers-reset {
  /* `max()` drží rozumný cíl i u myši (`--tap` 34 → 16 px je zbytečně málo),
     zároveň nesmí vyrůst tak, aby nadpis na jednom řádku (`nowrap` výš)
     přetekl panel — na dotyku vychází 26 px, u myši 20 px. */
  width: max(20px, calc(var(--tap) - 18px));
  height: max(20px, calc(var(--tap) - 18px));
  color: var(--muted);
  flex: 0 0 auto;
}
.layers .body .layers-reset:hover { color: var(--text); }
/* --- spodní blok: jeden skleněný panel (členy / rodiny / osa), #72 ------
   Na telefonu přes celou šířku. Na širokém displeji (od 2026-09-23) úzký
   a VPRAVO dole, hned vlevo od legendy — dřív byl vycentrovaný přes střed
   mapy a na nízkém notebooku kryl nejdůležitější část obrazu (zpětná
   vazba). Vpravo je i legenda a čas, takže se oko nemusí přesouvat.
   Legenda si tím nechává plnou výšku mapy (stojí vedle bloku, ne nad ním).
   `right` dopočítává `placeOverlays()` podle skutečné šířky legendy. */
.bottom-ov {
  position: absolute;
  left: .5rem;
  right: .5rem;
  bottom: calc(.5rem + env(safe-area-inset-bottom));
  z-index: 1;
}
/* Měřítko spodního bezpečného okraje pro `placeOverlays()` — `env()`
   z vlastní proměnné JS přečíst nejde. */
.safe-bottom-probe {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 0;
  height: env(safe-area-inset-bottom);
  visibility: hidden;
  pointer-events: none;
}
@media (min-width: 700px) {
  .bottom-ov {
    left: auto;
    width: min(540px, calc(100% - 7rem));
  }
}

/* Sklo (iOS liquid glass): panel je matná deska nad mapou, bublina lesklý
   zaoblený prvek na ní. Průsvitnost je tady funkční, ne ozdoba — pod
   panelem zůstává vidět mapa, takže blok nekrade plochu, jen ji sdílí. */
/* Podklad je záměrně skoro stejně tmavý jako záhlaví (`--panel`), ne
   poloprůsvitné sklo jako v maketě (zpětná vazba 2026-09-18): na světlých
   produktech — radar, oblačnost — měly čipy proti prosvítající mapě malý
   kontrast a blok navíc působil rušivě jinak než záhlaví nad ním. Rozostření
   zůstává, takže mapa pod blokem je pořád znát, jen nekonkuruje textu. */
/* Jedna skleněná karta (třetí kolo zpětné vazby 2026-09-22): samostatné
   průsvitné pruhy působily neuspořádaně, dřívější plná tmavá deska
   (.88) zase „strašně tučně". Tohle je střed — průsvitnější sklo s
   rozostřením a světlým lemem, obsah řádků vycentrovaný. Světlejší
   `--tab-bg` nese vybranou záložku a panel jejích členů. */
.glass-panel {
  --tab-bg: rgba(255, 255, 255, .13);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: .25rem .25rem 0;
  background: linear-gradient(180deg, rgba(20, 30, 50, .66), rgba(11, 18, 32, .74));
  backdrop-filter: blur(16px) saturate(1.4);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 1.1rem;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .35), inset 0 1px 0 rgba(255, 255, 255, .14);
}
.glass {
  background: linear-gradient(180deg, rgba(255, 255, 255, .24), rgba(255, 255, 255, .09));
  border: 1px solid rgba(255, 255, 255, .42);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 -1px 0 rgba(255, 255, 255, .06), 0 4px 14px rgba(0, 0, 0, .3);
  backdrop-filter: blur(5px) saturate(1.2);
  -webkit-backdrop-filter: blur(5px) saturate(1.2);
}

/* Osa je JEDEN řádek (#72): model drobně vlevo, dráha vpravo. Dřívější
   druhý řádek s hodinami a popisky pod dráhou je pryč — spodní blok byl
   „vertikálně brutálně mohutný" (zpětná vazba). */
.ov-time-axis {
  display: flex;
  align-items: stretch;
  margin-top: 2px;
  /* Dole místo pro popisky hodin pod dráhou — dřív se dotýkaly spodní hrany
     karty, nebo ji přesahovaly (zpětná vazba 2026-09-23). */
  padding: 0 .15rem 7px;
}
/* Aktuálně | Předpověď (+ vysunuté modely). Segmentový přepínač uprostřed
   nahoře; vybraná hodnota má světlý podklad s tmavým písmem — liší se
   světlostí, ne jen odstínem (barvocit). Při víc modelech, než se vejde,
   se dá posunout. */
.horizons {
  align-self: center;
  max-width: 100%;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  overflow-x: auto;
  scrollbar-width: none;
  border-radius: 999px;
  background: rgba(255, 255, 255, .08);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
}
.horizons::-webkit-scrollbar { display: none; }
.horizons:empty { display: none; }
#app .hz {
  flex: 0 0 auto;
  height: 24px;
  padding: 0 .7rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: #c3cedd;
  font-size: .72rem;
  font-weight: 700;
  white-space: nowrap;
  transition: background .2s, color .2s;
}
.hz--now::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin: 0 4px 1px 0;
  border-radius: 50%;
  background: #62c9a3;
  vertical-align: middle;
}
/* Experimentální model: čárkovaný obrys, ať je znát, že nepatří k běžné nabídce. */
#app .hz--exp { box-shadow: inset 0 0 0 1px rgba(230, 184, 74, .7); }
#app .hz[aria-pressed="true"] {
  background: linear-gradient(180deg, #ffffff, #dfe6f0);
  color: #0b1220;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .3);
}
/* Modely vysunuté vedle Předpovědi: druhá úroveň, proto vybraný model jen
   skleněně zvýrazněný, ne bílý jako hlavní volba. */
.hz-models {
  display: flex;
  gap: 2px;
  margin-left: 2px;
  padding-left: 4px;
  border-left: 1px solid rgba(255, 255, 255, .18);
  animation: hz-models-in .28s ease both;
}
@keyframes hz-models-in {
  from { opacity: 0; transform: translateX(-8px); }
  to { opacity: 1; transform: none; }
}
#app .hz--model { padding: 0 .55rem; font-weight: 600; }
/* Délka předpovědi pod slovem (Podrobně 48 h, Výhled 5 dní). */
#app .hz small { margin-left: .35em; font-size: .78em; font-weight: 500; opacity: .75; }
#app .hz--model[aria-pressed="true"] {
  background: rgba(255, 255, 255, .22);
  color: #ffffff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35);
}

.track-wrap { position: relative; flex: 1 1 auto; min-width: 0; height: 44px; --thumb: 30px; }
/* Dny NAD dráhou, tenká linka půlnoci přes celou výšku — kalendářní
   orientace bez druhého řádku textu. */
/* Dny sedí TĚSNĚ nad čarou dráhy (zpětná vazba 2026-09-18) — horní řádek
   se tím uvolnil pro bublinu s časem. Linka půlnoci vede od popisku dolů
   až do dráhy, takže je vidět, ke které části dne popisek patří. */
.axis-days {
  position: absolute;
  left: calc(var(--thumb) / 2);
  right: calc(var(--thumb) / 2);
  top: 14px;
  height: 13px;
  font-size: .55rem;
  line-height: 13px;
  color: #d7dfec;
  font-weight: 600;
}
.axis-days span { position: absolute; padding-left: 3px; white-space: nowrap; }
.axis-days i { position: absolute; top: 2px; width: 1px; height: 31px; background: var(--text); opacity: .3; }
/* Mezihodnoty pod dráhou — drobné dílky a řídké popisky hodin. Vejdou se
   do zbytku výšky řádku (dráha končí na 33 px, řádek má 44), takže spodní
   blok kvůli nim neroste. */
.axis-ticks {
  position: absolute;
  left: calc(var(--thumb) / 2);
  right: calc(var(--thumb) / 2);
  top: 34px;
  height: 10px;
  font-size: .5rem;
  line-height: 1;
  color: #93a3ba;
  font-variant-numeric: tabular-nums;
}
.axis-ticks i { position: absolute; top: 0; width: 1px; height: 3px; background: currentColor; opacity: .75; }
.axis-ticks span { position: absolute; top: 4px; transform: translateX(-50%); white-space: nowrap; }

.track {
  position: absolute;
  left: calc(var(--thumb) / 2);
  right: calc(var(--thumb) / 2);
  top: 27px;
  height: 6px;
  border-radius: 3px;
  overflow: hidden;
  background: rgba(255, 255, 255, .08);
}
/* Úsek dráhy podle zdroje dat: předpověď plná, pozorování (ČHMÚ) zelené.
   Šrafovaný hrubší model přibude s #70 (jedna osa přes oba modely). */
.track .seg { position: absolute; top: 0; bottom: 0; }
.track .seg-fine { background: var(--text); }
.track .seg-obs { background: #62c9a3; }
/* Nativní palec je průhledný a nese jen úchop přes celou výšku řádku —
   vidět je skleněná bublina pod ním (`.thumb`), skrz kterou prosvítá den
   i dráha. */
.track-wrap input[type="range"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 44px;
  margin: 0;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  cursor: grab;
  z-index: 2;
}
.track-wrap input[type="range"]:active { cursor: grabbing; }
.track-wrap input[type="range"]::-webkit-slider-runnable-track { height: 44px; background: transparent; }
.track-wrap input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: var(--thumb); height: 44px; background: transparent; border: 0; }
.track-wrap input[type="range"]::-moz-range-track { height: 44px; background: transparent; }
.track-wrap input[type="range"]::-moz-range-thumb { width: var(--thumb); height: 44px; background: transparent; border: 0; border-radius: 0; }
/* Palec je od 2026-09-18 jen úchop — čas se přestěhoval nad dráhu. Dvě
   krátké rysky uvnitř říkají „tohle se chytá a táhne", což samotná prázdná
   skleněná ploška neřekne. */
.thumb {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--thumb);
  height: 44px;
  border-radius: 11px;
  z-index: 1;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
}
.thumb::before, .thumb::after {
  content: "";
  width: 1px;
  height: 14px;
  border-radius: 1px;
  background: rgba(255, 255, 255, .7);
}

/* Čas kroku nad dráhou: větší písmo než cokoli jiného na ose, protože je to
   ta jediná hodnota, kterou uživatel při tažení čte. `left` (střed bubliny)
   počítá `syncThumb()` podle palce a u krajů ho zarazí, aby text nevyjel
   z panelu. */
.axis-time {
  position: absolute;
  /* Nad řádkem dnů, tedy lehce přes pruh rodin — uživatel to schválil
     („nevadilo by, že bublinka v čase pohybu překrývá menu nad tím"). */
  top: -10px;
  left: 0;
  transform: translateX(-50%);
  z-index: 3;
  padding: 1px .45rem 2px;
  border-radius: .55rem;
  font-size: .8rem;
  font-weight: 700;
  line-height: 1.25;
  color: #ffffff;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
  white-space: nowrap;
  pointer-events: none;
}
.axis-time:empty { display: none; }

.ov-time-axis { position: relative; }

/* --- gesto zpět na Androidu: co se táhne, nesmí začínat u hrany ---------
   Tažení, které začne blíž než ~20 dp od levé/pravé hrany displeje, spolkne
   systém jako gesto zpět a stránka se o něm vůbec nedozví — `touch-action`
   ani nic jiného v CSS to nepřebije, je to systémové gesto, ne scroll
   prohlížeče. Palec časové osy v krajní poloze seděl 18 px od hrany, tedy
   přesně v té zóně (nahlášeno 2026-09-18; #67 tuhle past předpovídalo
   u posuvníků sytosti a určilo i způsob opravy).

   Odsazuje se DRÁHA, ne celý blok: první verze posunula celý panel o 24 px
   od obou hran a sebrala tím 29 px šířky pruhu rodin i řádku členů, což
   uživatel zamítl. Zbývající riziko je vědomé — flick pruhu rodin začatý
   přesně u hrany systém pořád sebere, ale chytit se dá kdekoli jinde,
   zatímco palec v krajní poloze jiné místo nemá.

   Hodnota je v PIXELECH, ne v rem — je to fyzická zóna zařízení, ne
   typografie, takže nesmí růst s velikostí písma. Platí jen na dotyku a na
   úzkém displeji: u myši žádné takové gesto není a na tabletu je blok
   vycentrovaný, tedy od hran daleko. */
@media (pointer: coarse) and (max-width: 699px) {
  /* Zúžený je CHOD POSUVNÍKU, ne celý blok (zpětná vazba 2026-09-18:
     „to zúžení vzalo místo pro chip menu a menu rodin a to nebylo cílem").
     Pruh rodin i řádek členů potřebují každý pixel šířky, palec ne — a
     volné místo na konci dráhy se nejspíš bude hodit #70 (značka hranice
     modelů u osy). */
  /* Od 2026-09-23 i zleva a stejně (zpětná vazba ze screenshotu z
     telefonu): vnitřní odsazení karty, které mělo levou stranu chránit,
     nestačilo a jezdec v krajní poloze dojel skoro k hraně. */
  .ov-time-axis { padding-left: 24px; padding-right: 24px; }
}
/* Posuvníky sytosti (#67 je čekalo jako druhé místo téhož problému) odsazení
   NEPOTŘEBUJÍ: panel je od #59 dvousloupcový grid a levý sloupec s popiskem
   je od hrany odstrčí — změřeno 139 px od levé hrany na 375px telefonu.
   Kdo by je odsazoval „pro jistotu", jen zúží popisky. */

/* --- toast --- */
.toast {
  position: absolute;
  left: 50%;
  /* Pod řádkem názvu produktu a času — lišta od 2026-09-23 leží nad mapou,
     takže `--hdr` je od horní hrany plátna, ne od jeho začátku. */
  top: calc(var(--hdr) + 4rem);
  transform: translateX(-50%);
  z-index: 4;
  padding: .3rem .7rem;
  border-radius: .45rem;
  background: #1b2a44;
  border: 1px solid var(--line);
  font-size: .78rem;
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
  transition: opacity .2s;
}
.toast.show { opacity: 1; }

/* --- dotaz Ano/Ne (#51, nahrazuje `window.confirm()`) ---
   `position: fixed`, ne `absolute` — stejný grid-past jako u `.sheet` (viz
   níž): `#confirm` je přímý potomek `#app` (CSS grid) bez `grid-row`, takže
   `absolute` by se počítalo vůči implicitní gridové buňce, ne vůči appce. */
.confirm {
  position: fixed;
  left: 50%;
  top: 40%;
  transform: translate(-50%, -50%);
  z-index: 25;
  display: none;
  flex-direction: column;
  gap: .6rem;
  min-width: 240px;
  max-width: min(90vw, 320px);
  padding: .8rem 1rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: .7rem;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .4);
  color: var(--text);
}
.confirm.open { display: flex; }
.confirm .btns { display: flex; gap: .4rem; justify-content: flex-end; }
.confirm .btns button {
  height: calc(var(--tap) - 6px);
  padding: 0 .8rem;
  border: 1px solid var(--line);
  border-radius: .45rem;
  background: var(--btn);
  color: var(--text);
  font-size: .8rem;
}
.confirm .btns button.ok { border-color: var(--accent); background: var(--btn-on); }

/* --- nabídka „Přidat na plochu" (#59, přepsáno po zpětné vazbě) ---
   PRVNÍ verze byla fixní banner dole — přes celou šířku, nad sliderem i
   pruhem rodin, i po zúžení na sloupec (text/tlačítka) pořád nápadný a
   rušil ovládání appky. Teď je to třetí, nejmenší řádek v `.ov-topleft`
   (pod popiskem produktu a atribucí Mapy.cz, viz index.html) — normální
   flow, žádné `position:fixed`/`z-index`/vlastní šířka, roste odshora dolů
   a nikdy nezasáhne do spodní časové osy. Drobné písmo (`.68rem`) záměrně
   — má tam BÝT, ne řvát. Zavření lze znovu otevřít z hamburgeru
   (`#menuInstallBtn`, `showInstallNudge(kind, {force:true})` v app.js). */
/* Stav pozorování (#79) — výrazný, ale malý pruh pod popiskem produktu. */
.chmi-stale {
  display: flex;
  align-items: center;
  gap: .4rem;
  min-height: 2rem;
  padding: .25rem .6rem;
  background: var(--glass);
  border: 1px solid var(--gold);
  border-radius: .5rem;
  color: var(--text);
  font-size: .72rem;
  pointer-events: auto;
}
.chmi-stale[hidden] { display: none; }
.chmi-stale b { color: var(--gold); }
.chmi-stale span { white-space: nowrap; }
.chmi-stale .ic { width: 1rem; height: 1rem; }
.chmi-stale[aria-busy="true"] .ic { animation: chmi-spin 1s linear infinite; }
@keyframes chmi-spin { to { transform: rotate(360deg); } }
/* Pruh „starší předpověď": jantarový, ať je vidět na první pohled, a v téže
   koloně jako popisek produktu, takže nic nepřekrývá a zůstává i v režimu
   celé mapy. */
.old-run {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .3rem;
  max-width: 17rem;
  padding: .45rem .6rem;
  border-radius: .45rem;
  background: rgba(245, 180, 40, .94);
  color: #1a1405;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .35);
  pointer-events: auto;
}
.old-run[hidden] { display: none; }
.old-run__text { font-size: .74rem; font-weight: 600; line-height: 1.3; }
#app .old-run__back {
  padding: .3rem .6rem;
  border: 0;
  border-radius: .4rem;
  background: #1a1405;
  color: #ffd98a;
  font-size: .74rem;
  font-weight: 700;
}

.install-nudge {
  display: none;
  flex-direction: column;
  gap: .3rem;
  max-width: 100%;
  padding: .4rem .55rem;
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: .4rem;
  color: var(--muted);
}
.install-nudge.open { display: flex; }
.install-nudge__text { font-size: .68rem; line-height: 1.3; }
.install-nudge__btns { display: flex; align-items: center; justify-content: flex-end; gap: .3rem; }
.install-nudge__btns button {
  height: 20px;
  padding: 0 .5rem;
  border: 1px solid var(--line);
  border-radius: .35rem;
  background: var(--btn);
  color: var(--text);
  font-size: .64rem;
  white-space: nowrap;
}
.install-nudge__btns button.ok { border-color: var(--accent); background: var(--btn-on); }
#installNudgeDismiss { padding: 0 .4rem; color: var(--muted); }

/* --- sheety: zespodu na telefonu, panel 480px zprava na širokém ---
   `.open` řídí transform/opacity, ne `hidden` atribut — jinak by se nedal
   animovat přechod (issue #46, bod 7). */
/* `position: fixed`, NE `absolute` — `#app` je grid a `.sheet` je jeho přímý
   potomek bez `grid-row`/`grid-column`; Chromium ho pak auto-umístí do
   implicitního gridového řádku a `inset:0` se spočítá vůči TÉ buňce, ne
   vůči `#app` (zažito: sheet vyjde o desítky px posunutý nahoru/dolů).
   `fixed` se řídí viewportem a gridová past ho vůbec nepotká. */
.sheet { position: fixed; inset: 0; z-index: 20; pointer-events: none; }
.sheet.open { pointer-events: auto; }
.sheet__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .55);
  opacity: 0;
  transition: opacity .22s;
}
.sheet.open .sheet__backdrop { opacity: 1; }
.sheet__panel {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  max-height: 80dvh;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border-top: 1px solid var(--line);
  border-top-left-radius: 1rem;
  border-top-right-radius: 1rem;
  transform: translateY(100%);
  transition: transform .22s ease;
}
.sheet.open .sheet__panel { transform: translateY(0); }
/* Ukotvené záhlaví (#49): `.sheet__pinned` nescrolluje (titulek, podtitulek,
   u sheetu Předplatné navíc tarify/rozpočet/filtr), scrolluje jen
   `.sheet__scroll` pod ním — 1:1 tvar `.head`/`.scroll` z
   docs/design/maketa-oblasti.html, teď společný pro všechny sheety. */
.sheet__pinned { flex: 0 0 auto; padding: .5rem .75rem .35rem; border-bottom: 1px solid var(--line); }
.sheet__head { display: flex; align-items: center; justify-content: space-between; }
.sheet__title { font-weight: 600; }
/* Obnovit appku (#51) sedí v záhlaví hamburgeru vlevo od křížku — obě ikony
   spolu, `.sheet__head` je `justify-content:space-between` mezi titulkem
   a tímhle prvkem (ne mezi třemi položkami zvlášť). */
.sheet__head-actions { display: flex; align-items: center; gap: .3rem; flex: 0 0 auto; }
/* (i) sheet title nese jméno produktu + rodinu (`#infoTitle`, viz `openInfo()`
   v app.js) — rodina jako drobný odsazený štítek, ne slitá s názvem. */
.sheet__title span { margin-left: .4rem; font-size: .7rem; font-weight: 400; color: var(--muted); }
.sheet__scroll {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: .4rem .75rem calc(1rem + env(safe-area-inset-bottom));
  /* Scrollbar jako součást appky, ne systémový — 1:1
     `.sheet .scroll` z docs/design/maketa-oblasti.html. */
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.sheet__scroll::-webkit-scrollbar { width: 8px; }
.sheet__scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; border: 2px solid var(--panel); }
.sheet__scroll::-webkit-scrollbar-track { background: transparent; }

@media (min-width: 700px) {
  .sheet__panel {
    left: auto;
    top: 0;
    bottom: 0;
    width: min(480px, 100%);
    max-height: none;
    border-radius: 0;
    border-top: none;
    border-left: 1px solid var(--line);
    transform: translateX(100%);
  }
  .sheet.open .sheet__panel { transform: translateX(0); }
}

/* Hamburger (#51): na telefonu je zespodu JAKO OSTATNÍ sheety (beze
   změny — žádné `.sheet--left` pravidlo na malé šířce), na širokém vyjíždí
   ZLEVA místo zprava (na rozdíl od ostatních sheetů, které tam jedou
   zprava — viz `@media(min-width:700px) .sheet__panel` výš). Dřív vjíždělo
   zleva vždy, i na telefonu, což maketa (šesté kolo) změnila. */
@media (min-width: 700px) {
  .sheet--left .sheet__panel {
    left: 0; right: auto; top: 0; bottom: 0;
    width: min(480px, 100%);
    max-height: none;
    border-radius: 0;
    border-top: none;
    border-left: none;
    border-right: 1px solid var(--line);
    transform: translateX(-100%);
  }
  .sheet--left.open .sheet__panel { transform: translateX(0); }
}

.drawer__section { margin: 1rem 0; }
/* Účet (#177) */
.account__hint { margin: 0 0 .5rem; font-size: .85rem; color: var(--muted); }
.account__hint[hidden] { display: none; }
.account__google { min-height: 44px; margin-bottom: .4rem; }
.account__google[hidden] { display: none; }
.account__who { display: flex; align-items: center; gap: .6rem; margin-bottom: .5rem; }
.account__who img { border-radius: 50%; }
.account__who img[hidden] { display: none; }
.account__email { font-size: .8rem; color: var(--muted); }
/* Přihlášení e-mailem s kódem (#186). */
.account__form[hidden], .account__form [hidden] { display: none; }
.account__form label { display: block; }
.account__row { display: flex; gap: .4rem; margin-bottom: .4rem; }
.account__row input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: var(--tap);
  padding: .5rem .7rem;
  border: 1px solid var(--line);
  border-radius: .6rem;
  background: var(--btn);
  color: var(--text);
  font: inherit;
}
.account__row input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
#codeInput { font-variant-numeric: tabular-nums; letter-spacing: .2em; }
.account__btn {
  flex: 0 0 auto;
  min-height: var(--tap);
  padding: .5rem .8rem;
  border: 1px solid var(--accent);
  border-radius: .6rem;
  background: var(--btn-on);
  color: var(--text);
}
.account__btn[disabled] { opacity: .5; }
.account__links { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: .4rem; }
.account__link {
  padding: .3rem 0;
  border: 0;
  background: none;
  color: var(--accent);
  font-size: .85rem;
  text-decoration: underline;
}
.account__link[disabled] { color: var(--muted); text-decoration: none; }
/* Přihlásit se | Vytvořit účet (#209). */
.account__intent { display: flex; gap: .3rem; margin-bottom: .5rem; }
.account__tab {
  flex: 1 1 0;
  min-height: var(--tap);
  padding: .4rem .5rem;
  border: 1px solid var(--line);
  border-radius: .6rem;
  background: var(--btn);
  color: var(--muted);
}
.account__tab[aria-selected="true"] { border-color: var(--accent); background: var(--btn-on); color: var(--text); }
#authMethods[hidden], .account__signup[hidden] { display: none; }
.account__signup p { margin: 0 0 .6rem; }
.account__check { display: flex; gap: .5rem; align-items: flex-start; margin-bottom: .6rem; font-size: .9rem; }
.account__check a { color: var(--accent); }
.account__check input { width: 1.2rem; height: 1.2rem; margin-top: .1rem; flex: 0 0 auto; }
.account__btn--plain { border-color: var(--line); background: var(--btn); }
.drawer__label {
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
  margin-bottom: .35rem;
}
.drawer__item {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: .6rem .75rem;
  margin-bottom: .4rem;
  border: 1px solid var(--line);
  border-radius: .6rem;
  background: var(--btn);
  color: var(--text);
  text-align: left;
}
.drawer__item[disabled] { opacity: .45; }
/* "Režim ladění" (#73) — stejný vzor jako `.toggle[aria-pressed="true"]`
   u předplatného, jen na `.drawer__item` (appka mění i text tlačítka
   samotného, barva není jediný nosič stavu). */
.drawer__item[aria-pressed="true"] { border-color: var(--accent); background: var(--btn-on); }

.drawer__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  min-height: var(--tap);
  margin-bottom: .5rem;
}
.drawer__row-label { color: var(--text); display: flex; align-items: center; gap: .4rem; }
.drawer__row[hidden] { display: none; }
/* Oblast — první položka menu (2026-10-26): vlevo akce, vpravo aktuální oblast. */
.drawer__area { display: flex; align-items: center; justify-content: space-between; gap: .6rem; font-weight: 600; }
.drawer__area-now { color: var(--accent); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.drawer__area-now::after { content: " ›"; color: var(--muted); }
#areaList .row { cursor: pointer; }
/* Průvodce s avatarem průvodkyně — první položka menu (2026-09-25). */
.drawer__tour { display: flex; align-items: center; gap: .7rem; font-weight: 600; }
.drawer__tour img {
  width: 40px; height: 40px;
  border-radius: 50%;
  background: #e8eef7;
  flex: 0 0 auto;
}
/* Sbalovací části menu (#80): klávesové zkratky a „Pro vývojáře". */
.drawer__details > summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; }
.drawer__details > summary::-webkit-details-marker { display: none; }
.drawer__details > summary::after { content: "▾"; color: var(--muted); transition: transform .2s; }
.drawer__details[open] > summary::after { transform: rotate(180deg); }
.drawer__details .keys { margin: .3rem 0 .6rem; }
.drawer__summary { margin-bottom: .35rem; }
/* Zkratky jen tam, kde je klávesnice — na dotyku k ničemu. */
@media (pointer: coarse) { .drawer__keys { display: none; } }
.drawer__privacy { display: block; margin: .8rem 0 .2rem; font-size: .85rem; color: var(--accent); }
.drawer__version {
  margin: 1.4rem 0 .4rem;
  font-size: .7rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  line-height: 1.5;
}
/* Panel zobrazení u mapy jen v režimu ladění (2026-09-25). */
.layers-btn[hidden] { display: none; }
.drawer__row input[type="range"] { flex: 1 1 auto; max-width: 160px; accent-color: var(--accent); }

/* Nápověda kláves (#52) — dvousloupcový seznam kbd/popisek, stejný vzor jako
   `docs/design/maketa-oblasti.html` (`.keys`/`kbd`). Obsah generuje
   `buildKeysHelp()` v app.js ze `keyHintRows()`. */
.keys {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .3rem .8rem;
  align-items: center;
  font-size: .85rem;
}
.keys span { color: var(--muted); }
kbd {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: .8em;
  padding: .05rem .35rem;
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: .3rem;
  background: var(--btn);
  color: var(--text);
  justify-self: start;
}

/* Tři písmena A v rostoucí velikosti (#51) — vizuálně napovídá, co tlačítko
   dělá, na rozdíl od dřívějšího stejně velkého textu. */
.font-size-group { display: flex; gap: .3rem; }
.font-size-opt { font-weight: 700; }
.font-size-opt[data-size="small"] { font-size: var(--fs); }
.font-size-opt[data-size="medium"] { font-size: calc(var(--fs) + 2px); }
.font-size-opt[data-size="large"] { font-size: calc(var(--fs) + 4px); }
.font-size-opt[aria-pressed="true"] { border-color: var(--accent); background: var(--btn-on); }

.run-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  min-height: var(--tap);
  padding: .6rem .75rem;
  margin-bottom: .35rem;
  border: 1px solid var(--line);
  border-radius: .6rem;
  background: var(--btn);
  color: var(--text);
  text-align: left;
}
.run-row[aria-current="true"] { border-color: var(--accent); background: var(--btn-on); }
.run-row__meta { font-size: .75rem; color: var(--muted); }

/* --- oblast (mapka pokrytí + seznam) a pořadí rodin (issue #47) ---
   `.row`/`.grp`/`.ttl` jsou 1:1 z docs/design/maketa-oblasti.html — sdílené
   mezi sheetem oblastí (výsledky klepnutí do mapky, seznam všech oblastí)
   a sheetem pořadí rodin (jeden řádek na rodinu). */
.sheet__subtitle { font-size: .7rem; color: var(--muted); margin: .3rem 0 0; }

.grp {
  font-size: .66rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: .8rem 0 .3rem;
}

.row {
  display: flex;
  align-items: center;
  gap: .5rem;
  min-height: calc(var(--tap) + 4px);
  padding: .3rem .4rem;
  margin-bottom: .3rem;
  border-radius: .5rem;
  border: 1px solid transparent;
  background: var(--btn);
}
.row.sel { border-color: var(--accent); background: var(--btn-on); }
.row.off { background: transparent; }
/* Karta balíčku (2026-09-30): delší popis a seznam rodin se zalamují,
   přepínač stojí vpravo nahoře; „vždy zapnuté" má přepínač zašedlý. */
.row.package { align-items: center; flex-wrap: wrap; padding: .45rem .5rem; border-color: var(--gold); }
.row.package.off { border-color: var(--line); }
.row.package .ttl { flex: 1 1 0; min-width: 0; cursor: pointer; }
.row.package .package-thumb {
  width: 3.6rem; height: 3.6rem; flex: none; object-fit: cover; border-radius: .45rem; cursor: pointer;
}
/* Vypnutý balíček: náhled bez barev a ztmavený, ať je stav vidět na první pohled. */
.row.package.off .package-thumb { filter: grayscale(1) brightness(.55); }
.row.package.off .package-cost { filter: grayscale(1); opacity: .7; }
#app .package-more {
  display: block; margin-top: .25rem; padding: 0; border: 0; background: none; min-width: 0; height: auto;
  color: var(--accent); font-size: .72rem; text-decoration: underline;
}
.package-detail, .package-notice { flex: 1 1 100%; display: flex; flex-direction: column; align-items: flex-start; gap: .3rem; font-size: .76rem; color: #c3cedd; }
.package-detail .package-img { margin: .2rem 0 .2rem; }
.package-detail .package-lock--plain { color: var(--muted); }
.package-notice { padding: .5rem .6rem; border-radius: .45rem; border: 1px solid var(--gold); background: rgba(230, 184, 74, .12); color: var(--text); }
.budget b { font-size: 1.15em; }
.budget__note { grid-column: 1 / -1; font-size: .72rem; color: var(--muted); }
.budget__note.package-notice { color: var(--text); font-size: .76rem; }
.row.package .ttl span { white-space: normal; overflow: visible; text-overflow: clip; display: block; margin-top: .2rem; }
.row.package .ttl b { font-size: .95em; }
.row.package .sw:disabled { opacity: .55; cursor: default; }
/* Volitelný produkt balíčku (2026-10-01): odsazený řádek pod kartou. */
.row.package-extra { margin-left: 1rem; }
.row.package-extra .ttl span { display: block; }
/* Experimentální modely (2026-10-05): jen v režimu ladění, pod balíčky. */
.package-exp-head { margin: .9rem 0 .2rem; padding-top: .6rem; border-top: 1px dashed var(--muted); }
.package-exp-head b { display: block; font-size: .85rem; }
.package-exp-head span { display: block; font-size: .72rem; color: var(--muted); }
.row.package-exp { margin-left: 0; }
.row.package-exp .ttl span { white-space: normal; margin-top: .2rem; }
.row.off .ttl b { color: var(--lock); }
.row[tabindex] { cursor: pointer; }
.ttl { flex: 1 1 auto; min-width: 0; }
.ttl b { display: flex; align-items: center; gap: .35rem; font-size: .88rem; font-weight: 600; }
.ttl span { display: block; font-size: .68rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.regmap {
  width: 100%;
  height: 15rem;
  display: block;
  border: 1px solid var(--line);
  border-radius: .5rem;
  overflow: hidden; /* zaoblení platí i pro dlaždice uvnitř */
  background: #0f1728;
  cursor: crosshair;
  margin-bottom: .3rem;
}
/* Atribuce Mapy.cz musí být vidět i v mapce (licence dlaždic). */
.regmap .maplibregl-ctrl-attrib { font-size: .6rem; }

/* Pořadí rodin: úchyt tažení — `touch-action:none`, jinak prst posouvá
   stránku místo řádku (funguje prstem i myší, viz `startOrderDrag`). */
.row .grip {
  flex: 0 0 auto;
  width: 22px;
  align-self: stretch;
  display: grid;
  place-items: center;
  color: var(--muted);
  cursor: grab;
  touch-action: none;
  font-size: 1.1em;
  user-select: none;
}
.row.dragging { opacity: .55; border-color: var(--accent); }
.order-actions { display: flex; justify-content: flex-end; margin-top: .5rem; }

/* --- Předplatné (#48): tarify, rozpočet, řádek produktu, (i) --- */
.row button, .toggle {
  min-width: var(--tap);
  height: calc(var(--tap) - 6px);
  padding: 0 .55rem;
  border: 1px solid var(--line);
  border-radius: .45rem;
  background: var(--btn);
  color: var(--text);
  font-size: .76rem;
}
.row button[aria-pressed="true"], .toggle[aria-pressed="true"] { border-color: var(--accent); background: var(--btn-on); }
.row button:disabled { opacity: .35; cursor: default; }
/* (i) na řádku produktu — kolečko, stejný vzor jako `.ov-label .info`. */
.row button.i { min-width: calc(var(--tap) - 6px); height: calc(var(--tap) - 6px); padding: 0; border-radius: 50%; }
/* Přepínač řádku produktu (2026-09-26, nahradil zaškrtávátko `.cb` z #49).
   Zpětná vazba uživatelů: nezaškrtnuté pole (tmavé na tmavém panelu) nebylo
   vůbec poznat. Přepínač nese stav třemi kanály zároveň — poloha jezdce,
   výplň dráhy a SVĚTLOST (zlatá proti šedomodré), ne jen odstínem (barvocit).
   Vypnutý stav má schválně světlou dráhu i jezdec, aby byl vidět na panelu.
   `.row .sw`, ne `.sw` — jinak by vyhrálo obecné `.row button` výš. */
.row .sw {
  position: relative;
  flex: 0 0 auto;
  width: calc(var(--tap) + 2px);
  min-width: 0;
  height: calc(var(--tap) * .58);
  margin: 0;
  padding: 0;
  border: 1.5px solid #6b7894;
  border-radius: 999px;
  background: #3a4560;
  transition: background-color .18s ease, border-color .18s ease;
}
.row .sw::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 3px;
  width: calc(var(--tap) * .58 - 9px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: #d5dce8;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .45);
  transform: translateY(-50%);
  transition: left .18s ease, background-color .18s ease;
}
.row .sw[aria-checked="true"] { background: var(--gold); border-color: var(--gold); }
.row .sw[aria-checked="true"]::after { left: calc(100% - (var(--tap) * .58 - 9px) - 3px); background: #0b1220; }
.row .sw:disabled { opacity: .35; cursor: default; }
.row .sw:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.menu-row { display: flex; align-items: center; gap: .6rem; min-height: var(--tap); font-size: .82rem; flex-wrap: wrap; }

.coin { font-size: .66rem; padding: .1rem .4rem; border-radius: .4rem; border: 1px solid var(--line); color: var(--muted); white-space: nowrap; }
.coin.paid { color: var(--gold); border-color: #6b5a24; }
.coin.free { color: #9fe0b8; border-color: #2d6b4a; }

.tiers { display: grid; grid-template-columns: repeat(4, 1fr); gap: .3rem; margin: .3rem 0 .6rem; }
.tiers button { height: calc(var(--tap) + 8px); border: 1px solid var(--line); border-radius: .45rem; background: var(--btn); color: var(--text); font-size: .78rem; line-height: 1.15; }
.tiers button[aria-pressed="true"] { border-color: var(--gold); color: var(--gold); background: #1c1a12; }

.budget { display: grid; grid-template-columns: 1fr auto; gap: .2rem .6rem; font-size: .78rem; margin: .4rem 0 .6rem; }
.budget .barx { grid-column: 1 / -1; height: 8px; border-radius: 4px; background: var(--btn); overflow: hidden; border: 1px solid var(--line); }
.budget .barx i { display: block; height: 100%; background: var(--gold); }

/* Hlavička sbalitelné oblasti v seznamu produktů (aktivní oblast otevřená,
   ostatní sbalené — `tierOpenRegions` v app.js). */
.reg-head { display: flex; align-items: center; gap: .5rem; min-height: var(--tap); cursor: pointer; border-radius: .45rem; padding: 0 .3rem; }
.reg-head:hover { background: var(--btn); }
.reg-head b { flex: 1 1 auto; font-size: .85rem; }
.reg-head span { font-size: .68rem; color: var(--muted); }
.reg-head .car { color: var(--muted); font-size: .8em; width: 1em; text-align: center; }
.reg-body[hidden] { display: none; }

/* (i) o produktu: náhled 96×72 ze skutečných dat, viz `setInfoThumbnail()`.
   Světlý podklad (ne `--bg`) — náhled je tmavý produktový snímek na
   průhledném pozadí, potřebuje kontrast nezávislý na tmavém tématu appky. */
.info-card { display: grid; grid-template-columns: 96px 1fr; gap: .6rem; align-items: start; margin: .4rem 0 .8rem; }
.info-thumb {
  width: 96px;
  height: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: .4rem;
  background: #e6e8dc;
  color: #55605a;
  font-size: .6rem;
  text-align: center;
  padding: .2rem;
}
.info-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.info-card p { margin: 0 0 .3rem; font-size: .78rem; }
.info-card p.meta { color: var(--muted); font-size: .68rem; }

/* Čipy v režimu "ikona + drobný popisek" — ikona nahoře, malý text pod ní,
   místo ikony + textu vedle sebe (výchozí, viz `.chip` výš). `.chip--icons`
   je stejný vzhled jako samotný izolovaný modifikátor (#51, „Nabídka
   produktů" — živá ukázka obou variant musí vypadat správně bez ohledu na
   to, co appka zrovna má nastavené v `#app[data-chips]`). */
#app[data-chips="icons"] .chip:not(.chip--text),
.chip--icons {
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  padding: 0 .4rem;
  min-width: var(--tap);
  height: calc(var(--tap) - 8px);
}
/* Šipka „▾" u aktivního čipu by v režimu ikon přidala třetí řádek —
   přehled „Co zobrazit" se otevře klepnutím na aktivní čip i bez ní. */
#app[data-chips="icons"] .chip .caret { display: none; }
#app[data-chips="icons"] .chip:not(.chip--text) svg.ic,
.chip--icons svg.ic { width: 1.2em; height: 1.2em; }
#app[data-chips="icons"] .chip:not(.chip--text) .lb,
.chip--icons .lb { font-size: .56rem; font-weight: 500; }
/* Ikona rodiny je v obou podobách stejně velká (#80: ukázky v menu měly
   každá jinou) — v textové podobě dřív 1,15em, v ikonové 1,2em. */
#app .chip svg.ic { width: 1.2em; height: 1.2em; }

/* "Nabídka produktů" (#51, dřív textový přepínač): dva živé čipy Oblačnost
   (ikona+text / ikona+popisek), klepnutí přepne volbu — `buildChipSample()`
   v app.js, `aria-selected` zvýrazní aktivní stejně jako u čipů rodin. */
.chip-sample { display: flex; gap: .4rem; }
/* V pruhu rodin stačí aktivnímu čipu barva (vybraný je pod skleněnou
   bublinou), v ukázce v hamburgeru ale žádná bublina není — tam potřebuje
   vlastní rámeček, jinak není poznat, která varianta je zvolená. */
/* `#app` v selektoru: `#app .chip { border: 0 }` má jinak vyšší specificitu
   a rámeček vybrané ukázky se nikdy neukázal (#80). */
#app .chip-sample .chip[aria-selected="true"] {
  border: 1px solid var(--accent);
  background: var(--btn-on);
}

/* --- start appky: co se schová, než jsou data (2026-09-15) ----------------
   Zpětná vazba: první ~3 s byla vidět rozdělaná appka — prázdný čip oblasti,
   prázdné kolečko tarifu, osamocený úchyt legendy se šipkami uprostřed
   okraje, prázdný slider a chybějící pruh rodin. Horší než prázdná
   obrazovka: vypadá to jako appka, které něco chybí.

   Schovává se JEN ovládání, které ještě nemá obsah. Mapa zůstává —
   je hotová dřív než data a je to nejhezčí část startu. S ní musí zůstat
   i atribuce Mapy.cz (`.attrib-row`), protože licence dlaždic ji vyžaduje
   vždy, když jsou dlaždice na obrazovce (CLAUDE.md „#55") — proto se
   schovává `.ov-label` a `#layersBtn` jednotlivě, ne celá `.ov-topleft`.

   Selektory jsou dost specifické (`#app.booting` = ID + třída), aby
   přebily `display` z vlastních pravidel těch prvků — stejná past jako
   u `[hidden]` jinde v tomhle souboru. */
#app.booting .legend-strip,
#app.booting .locate-btn,
#app.booting .probe-btn,
#app.booting .ogn-live-btn,
#app.booting .ogn-fav-filter-btn,
#app.booting .map-side-btn,
#app.booting .bottom-ov,
#app.booting .ov-label,
#app.booting #layersBtn,
#app.booting #tierBtn,
#app.booting .runinfo,
#app.booting .region-btn { display: none; }

.boot-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none; /* mapa pod tím zůstává ovladatelná */
  z-index: 4;
}
/* Řídí se atributem `hidden`, ne třídou `.booting` — po NEÚSPĚŠNÉM startu
   zůstává viset s chybovou hláškou, zatímco `.booting` už je pryč (ovládání
   se musí vrátit, i když data nedorazila). `[hidden]` samo nestačí:
   `display:grid` výš má stejnou specificitu jako pravidlo prohlížeče, takže
   by ho přebilo — stejná past jako u `.map-attrib[hidden]` (CLAUDE.md). */
.boot-overlay[hidden] { display: none; }
/* Chybový stav: žádné kolečko (nic se už neděje) a hláška smí být delší. */
.boot-overlay--error .boot-spinner { display: none; }
.boot-overlay--error .boot-overlay__box {
  max-width: 18rem;
  text-align: center;
  border-color: var(--accent);
}
.boot-overlay__box {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem .8rem;
  border-radius: .6rem;
  background: var(--glass);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: .8rem;
}
.boot-spinner {
  width: .9rem;
  height: .9rem;
  border-radius: 50%;
  border: 2px solid var(--line);
  border-top-color: var(--accent);
  animation: boot-spin .8s linear infinite;
}
@keyframes boot-spin { to { transform: rotate(360deg); } }

/* --- přehled „Co zobrazit" (#72, přepsáno 2026-10-27) ---------------------
   Nahoře oblast (mapka + volba), pod ní sekce Aktuálně / Předpověď, v nich
   rodiny a členové jako dlaždice s náhledem. Prázdné a neaktivní členy jsou
   ve výchozím stavu neviditelné (CLAUDE.md „Dvě kvality"), odhalí je oko. */
.pick-sec {
  font-size: .66rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 1rem 0 .35rem;
}
.sheet__scroll > .pick-sec:first-child { margin-top: .2rem; }
.pick-map .regmap { height: 9rem; margin-bottom: .45rem; cursor: pointer; }
.pick-areas { display: flex; flex-wrap: wrap; gap: .35rem; margin-bottom: .3rem; }
#app .pick-area {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  min-height: calc(var(--tap) - 4px);
  padding: .25rem .65rem;
  border: 1px solid var(--line);
  border-radius: .55rem;
  background: var(--btn);
  color: var(--text);
  text-align: left;
}
.pick-area b { font-size: .8rem; font-weight: 600; }
.pick-area span { font-size: .64rem; color: var(--muted); }
#app .pick-area[aria-pressed="true"] { border-color: var(--accent); background: var(--btn-on); box-shadow: 0 0 0 1px var(--accent); }
.pick-area.off b, .pick-area.off span { color: var(--lock); }
.pick-area b svg.ic { width: .9em; height: .9em; vertical-align: -.1em; margin-left: .25em; }
.pick-fam {
  padding: .45rem 0 .6rem;
  border-top: 1px solid var(--line);
}
.pick-fam .fh {
  display: flex;
  align-items: center;
  gap: .4rem;
  font-weight: 600;
  font-size: .84rem;
  margin-bottom: .4rem;
  color: var(--text);
}
.pick-fam .fh svg.ic { width: 1.2em; height: 1.2em; color: var(--muted); }
.pick-fam.sel .fh svg.ic { color: var(--accent); }
.pick-fam .ms {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(5.6rem, 1fr));
  gap: .4rem;
}
#app .ptile {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: .3rem;
  padding: .3rem .3rem .4rem;
  border: 1px solid var(--line);
  border-radius: .55rem;
  background: var(--btn);
  color: var(--text);
  text-align: left;
  min-width: 0;
}
#app .ptile[aria-selected="true"] { border-color: var(--accent); background: var(--btn-on); box-shadow: 0 0 0 1px var(--accent); }
/* Náhled: celá buňka spritu (4 : 1), stejná pozice jako `.mthumb`. */
.pthumb {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 1;
  border-radius: .35rem;
  background-image: var(--member-thumbs);
  background-repeat: no-repeat;
  background-size: calc(var(--cells) * 100%) auto;
  background-position: calc(var(--cell) / (var(--cells) - 1) * 100%) 50%;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .14);
}
.pthumb--icon { display: flex; align-items: center; justify-content: center; background: rgba(255, 255, 255, .06); }
.pthumb--icon svg.ic { width: 1.1rem; height: 1.1rem; color: var(--muted); }
.plabel { font-size: .74rem; font-weight: 600; line-height: 1.2; padding: 0 .1rem; }
.ptile small { font-size: .64rem; color: var(--muted); padding: 0 .1rem; }
/* Prázdný člen čárkovaně, neaktivní tečkovaně, oba ztlumené a bez odkazu. */
#app .ptile.gone { border-style: dashed; cursor: default; }
#app .ptile.off { border-style: dotted; cursor: default; }
.ptile.gone .pthumb, .ptile.off .pthumb { filter: grayscale(1); opacity: .45; }
.ptile.gone .plabel, .ptile.off .plabel { color: var(--lock); }
.pick-foot { margin-top: .9rem; }
#app .pick-eye {
  min-height: calc(var(--tap) - 10px);
  padding: 0 .6rem;
  border: 1px solid var(--line);
  border-radius: .45rem;
  background: var(--btn);
  color: var(--muted);
  font-size: .72rem;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
}
.pick-eye[aria-pressed="true"] { border-color: var(--accent); background: var(--btn-on); color: var(--text); }

/* Zásah do všech animací pod jedním pravidlem (issue #46, bod 7) — jednodušší
   a spolehlivější než hlídat `prefers-reduced-motion` v každé komponentě
   zvlášť. Kolečko loaderu se tím zastaví taky — text „Načítám data…" nese
   sdělení sám, nepotřebuje ho. */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* --- průvodce ovládáním (2026-09-18) ------------------------------------
   Nováček si spodního panelu nemusí všimnout vůbec a druhý stupeň (členové
   rodiny nad řádkem rodin) mu zůstane skrytý — viz `tour.js`. Reflektor je
   jedna dírka s obrovským stínem, ne čtyři překryvné obdélníky. */
.tour { position: fixed; inset: 0; z-index: 60; }
/* Ztmavení: SVG s vyříznutým obdélníkem (viz tour.js). */
.tour__dim { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.tour__dim > rect { fill: rgba(6, 10, 18, .74); }
/* Krok, který ukazuje produkt na mapě: okolí ztmavené méně, ať je mapa
   vidět. Do 2026-10-26 jen .3 — na světlé mapě to nebylo poznat a uživatelé
   nevěděli, kam se dívat; .55 nechá mapu čitelnou a ovládání vyčnívá. */
.tour--light .tour__dim > rect { fill: rgba(6, 10, 18, .55); }

.tour__hole {
  position: absolute;
  border-radius: 14px;
  /* Obrys dírky: na tmavém panelu by samotné "méně tmavé" místo nebylo
     dost vidět. */
  outline: 2px solid var(--accent);
  outline-offset: 0;
  transition: top .18s ease, left .18s ease, width .18s ease, height .18s ease;
  pointer-events: none;
}
/* Jemné „dýchání" kolem zvýrazněné části (2026-10-26: některých prvků si
   uživatelé nevšimli ani s ztmaveným okolím). Pomalu, jen záře a světlost,
   žádné blikání; `prefers-reduced-motion` vypíná animace globálně. */
.tour__hole::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 17px;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .85), 0 0 18px 6px rgba(120, 190, 255, .55);
  animation: tour-breathe 1.8s ease-in-out infinite;
}
@keyframes tour-breathe {
  0%, 100% { opacity: .15; }
  50% { opacity: 1; }
}

.tour__bubble {
  position: absolute;
  width: min(21rem, calc(100vw - 24px));
  padding: .7rem .8rem .6rem;
  border-radius: 14px;
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
  color: var(--text);
  transition: top .18s ease, left .18s ease;
}

.tour__step { font-size: .62rem; color: var(--muted); letter-spacing: .04em; }
.tour__title { font-weight: 650; margin-top: .1rem; }
.tour__text { font-size: .82rem; color: var(--muted); margin-top: .25rem; line-height: 1.35; }

.tour__actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  margin-top: .6rem;
}

.tour__skip,
.tour__next {
  min-height: calc(var(--tap) - 10px);
  padding: 0 .9rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--btn);
  color: var(--text);
  cursor: pointer;
}

.tour__skip { border-color: transparent; background: transparent; color: var(--muted); }
.tour__next { background: var(--btn-on); border-color: var(--accent); font-weight: 600; }

/* Úvodní krok průvodce nemá co osvítit — dírka se schová a bublina sedí
   uprostřed obrazovky (zpětná vazba 2026-09-18: první dojem má být uvítání,
   ne rovnou instruktáž). Ztmavení (SVG) zůstává celé, výřez má nulový
   rozměr — průvodkyně se na světlém podkladu Mapy.cz ztrácela (zpětná vazba
   z telefonu). */
.tour--intro .tour__hole { display: none; }

.tour__spacer { flex: 1 1 auto; }

.tour__back {
  min-height: calc(var(--tap) - 10px);
  padding: 0 .7rem;
  border-radius: 999px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}

.tour__back--off { visibility: hidden; }

/* Průvodkyně stojí na horní hraně bubliny (2026-09-18). Výška je v `rem`,
   takže roste s krokem písma stejně jako zbytek průvodce; na nízkém okně se
   `tour.js` rozhodne ji vůbec nekreslit, místo aby zakryla to, co má
   reflektor ukázat. */
.tour__mascot {
  position: absolute;
  height: 11rem;
  width: auto;
  pointer-events: none;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .45));
}

@media (min-width: 700px) {
  .tour__mascot { height: 13rem; }
}

.tour__mascot[hidden] { display: none; }

/* --- logo nad mapou (2026-09-23) -------------------------------------------
   Jako Windy a Flightradar24: značka nahoře uprostřed mapy, vidět i v režimu
   celé mapy — buduje se tím povědomí o značce. Nápis se na úzkém displeji
   schová (vedle popisku produktu a času by se nevešel), značka zůstává.
   Návrh k posouzení, ne definitivní logo. */
.brand {
  position: absolute;
  top: calc(var(--hdr) + .6rem);
  right: .6rem;
  z-index: 2;
  /* Ikona NAD nápisem (zpětná vazba 2026-09-23): logo je úzké, takže se
     vejde i na telefonu a nevytlačí název produktu na dva řádky. */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  pointer-events: none;
  color: #fff;
  font-weight: 700;
  font-size: .7rem;
  line-height: 1.1;
  letter-spacing: -.01em;
  text-shadow: 0 0 3px rgba(0, 0, 0, .75), 0 0 8px rgba(0, 0, 0, .5);
  opacity: .92;
}
.brand svg { width: 1.6rem; height: 1.6rem; flex: 0 0 auto; filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .5)); }
.brand b { font-weight: 700; }
.brand b span { color: #9cc9ff; }
/* Vpravo nahoře na všech displejích (2026-09-23): uprostřed širokého
   displeje rušilo a na telefonu kolidovalo s časem. Čas je teď v kartě
   vlevo, takže pravý horní roh patří jen logu. */

/* --- režim celé mapy (2026-09-23) -------------------------------------------
   Klepnutí do mapy (`setImmersive()` v app.js). Každý prvek odjede ke svému
   nejbližšímu okraji: lišta nahoru, navigace nad osou dolů, legenda doprava,
   tlačítka vlevo doleva. Zůstane posuvník, název produktu, čas, logo
   a atribuce.

   Tři pravidla, každé po chybě z prvního kola:
   - NIC se nevyřazuje z rozložení (`display:none`). Prvky jen odjedou
     a zprůhlední, rozměry i polohy zůstanou platné — po návratu se nic
     nepřepočítává a nepřehraje se vnitřní animace záložky a panelu členů.
   - Mapa nemění velikost (lišta leží nad ní), takže obraz neposkočí.
   - Posuvník se nehne: navigace nad ním se zavírá na nulovou výšku uvnitř
     bloku ukotveného dole a šířku bloku v tomhle režimu nikdo nepřepočítá.
   `visibility` se přepíná až po dojetí, aby schované prvky nešly klepnout. */
:root { --imm-t: .34s; --imm-ease: cubic-bezier(.2, .8, .2, 1); }
.nav-rows {
  display: grid;
  grid-template-rows: 1fr;
  /* `minmax(0, 1fr)` + `min-width: 0` na obsahu: panel členů má šířku
     `max-content` a bez tohohle by roztáhl sloupec mřížky přes okraj karty
     (past z #26: grid položka potřebuje vlastní `min-width: 0`). */
  grid-template-columns: minmax(0, 1fr);
  /* Obsah zajíždí dolů POD hranu obalu, ne přes osu. */
  overflow: hidden;
  transition: grid-template-rows var(--imm-t) var(--imm-ease);
}
.nav-rows__in {
  min-height: 0;
  min-width: 0;
  /* Vlastní výška = obsah, i když je řádek mřížky zavřený na 0 — podle ní
     `placeOverlays()` drží legendu a tlačítko polohy na místě. */
  align-self: start;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  transition: transform var(--imm-t) var(--imm-ease), opacity var(--imm-t) var(--imm-ease);
}
.legend-strip, .layers-btn, .locate-btn, .probe-btn, .ogn-live-btn, .install-nudge, .ov-label .info, .ov-label .caret,
.ov-topleft, .brand {
  transition: transform var(--imm-t) var(--imm-ease), opacity var(--imm-t) var(--imm-ease), visibility 0s;
}
/* Průběh přednačítání snímků (2026-09-30): pruh na spodní hraně lišty,
   plní se zleva doprava a po dokončení zmizí. Ukáže se jen, když načítání
   trvá déle než chvilku (`LOAD_BAR_DELAY_MS`), z cache neproblikne. */
/* Přepínač oblastí je od #102 pryč: model vybírá přepínač horizontu
   (48 h / 5 dní / 60 h) a mapa se posouvá prstem. Element zůstává kvůli
   kódu, který do něj píše název oblasti. */
#regionBtn { display: none; }

.load-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s ease;
}
.load-bar.on { opacity: 1; }
/* Bez údaje o postupu (zobrazený krok se dotahuje): úsek pruhu jezdí. */
.load-bar.busy { opacity: 1; overflow: hidden; }
.load-bar.busy:not(.on) span { width: 35%; transition: none; animation: load-sweep 1.1s ease-in-out infinite; }
@keyframes load-sweep { from { transform: translateX(-100%); } to { transform: translateX(290%); } }
.load-bar span {
  display: block;
  height: 100%;
  width: var(--load, 0%);
  background: var(--accent);
  box-shadow: 0 0 6px var(--accent);
  transition: width .25s ease;
}

#app.immersive .hdr { transform: translateY(calc(-100% - env(safe-area-inset-top))); }
#app.immersive .nav-rows { grid-template-rows: 0fr; }
#app.immersive .nav-rows__in { transform: translateY(40%); opacity: 0; visibility: hidden; transition-property: transform, opacity, visibility; transition-delay: 0s, 0s, var(--imm-t); }
/* Legenda zůstává (zpětná vazba z pilotu 2026-09-23): je nedílná součást
   obrazu, bez ní mapa neříká, co ukazuje. */
#app.immersive .layers-btn,
#app.immersive .probe-btn,
#app.immersive .ogn-live-btn,
#app.immersive .ogn-fav-filter-btn,
#app.immersive .map-side-btn,
#app.immersive .locate-btn { transform: translateX(-150%); opacity: 0; }
#app.immersive .install-nudge,
#app.immersive .ov-label .info,
#app.immersive .ov-label .caret { opacity: 0; }
#app.immersive .layers-btn,
#app.immersive .probe-btn,
#app.immersive .ogn-live-btn,
#app.immersive .ogn-fav-filter-btn,
#app.immersive .map-side-btn,
#app.immersive .locate-btn,
#app.immersive .install-nudge,
#app.immersive .ov-label .info,
#app.immersive .ov-label .caret { visibility: hidden; transition-delay: 0s, 0s, var(--imm-t); }
/* Co zůstává nahoře, vyjede do místa po liště — jinak by nad ním zůstal
   prázdný pruh. */
#app.immersive .ov-topleft,
#app.immersive .brand { transform: translateY(calc(-1 * var(--hdr))); }
#app.immersive .ov-label .prod { pointer-events: none; }

/* --- vlnový výhled (#196) -------------------------------------------------
   Čtyři pásma skóre z viridis: velký rozdíl světlosti mezi sousedy, číslo je
   v odznaku vždy (barva je jen druhý kanál — porucha barvocitu). Nula je
   jen obrys, aby prázdné dny nepoutaly pozornost. */
.ol-badge {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; min-width: 2em; height: 2em; border-radius: .5em;
  font-weight: 700; font-variant-numeric: tabular-nums;
}
.ol-badge.sm { min-width: 1.6em; height: 1.6em; font-size: .85em; }
.b0 { background: transparent; color: var(--muted); box-shadow: inset 0 0 0 1px var(--line); }
.b1 { background: #3b528b; color: #ffffff; }
.b2 { background: #21908d; color: #ffffff; }
.b3 { background: #5dc863; color: #0b1220; }
.b4 { background: #fde725; color: #0b1220; }
.ol-meta { margin: 0 0 .5rem; font-size: .8rem; color: var(--muted); }
.ol-scale { margin: 0 0 .8rem; }
.ol-scale__title { font-size: .85rem; font-weight: 600; margin: 0 0 .35rem; }
.ol-scale__title b { font-variant-numeric: tabular-nums; }
.ol-scale__row { display: grid; grid-template-columns: .7fr 1fr 1fr 1fr 1.5fr; gap: 3px; }
.ol-scale__cell { display: flex; flex-direction: column; gap: .25rem; min-width: 0; }
.ol-scale__bar {
  display: flex; align-items: center; justify-content: center;
  height: 1.5em; border-radius: .35em; font-size: .75rem; font-weight: 700;
}
.ol-scale__text { font-size: .66rem; line-height: 1.2; color: var(--muted); }
.ol-day { border: 1px solid var(--line); border-radius: .6rem; background: var(--btn); margin-bottom: .35rem; }
.ol-day[open] { border-color: var(--accent); }
.ol-day summary {
  display: flex; align-items: center; gap: .6rem;
  min-height: var(--tap); padding: .45rem .6rem; cursor: pointer; list-style: none;
}
.ol-day summary::-webkit-details-marker { display: none; }
.ol-date { flex: 0 0 4.6em; font-size: .8rem; font-weight: 600; }
/* Model, ze ktereho den je (ICON-D2, ICON-EU, ECMWF; 2026-10-23). */
.ol-model { display: block; margin-top: .15rem; font-size: .62rem; font-weight: 500; color: var(--muted); }
.ol-mid { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: .25rem; }
.ol-reason { font-size: .78rem; line-height: 1.25; }
.ol-slots { display: flex; gap: 3px; }
.ol-slot { width: 1.1em; height: .4em; border-radius: 2px; }
.ol-slot.b0 { box-shadow: inset 0 0 0 1px var(--line); }
.ol-rain { flex: 0 0 auto; font-size: .75rem; color: #9cc7ff; white-space: nowrap; }
/* Proklik do předpovědní mapy (2026-10-23). */
.ol-map { flex: 0 0 auto; font: inherit; font-size: .72rem; font-weight: 600; color: var(--accent);
  background: transparent; border: 1px solid var(--accent); border-radius: 999px;
  padding: .2rem .55rem; cursor: pointer; white-space: nowrap; }
.ol-map:hover { background: rgba(78, 161, 255, .14); }
.ol-table .ol-hour { font: inherit; font-weight: 600; color: var(--accent); background: none; border: 0;
  padding: 0; cursor: pointer; text-decoration: underline dotted; }
/* Komplikace dne (2026-10-22): jantarová, ale nese ji i znak ⚠ a text. */
.ol-haz { font-size: .72rem; line-height: 1.25; color: #ffd48a; }
.ol-haz b { font-weight: 600; margin-right: .2em; }
.ol-table td.haz { color: #ffd48a; }
.ol-day--far summary { opacity: .72; }
.ol-table-wrap { overflow-x: auto; padding: 0 .6rem .6rem; }
.ol-table { border-collapse: collapse; font-size: .75rem; font-variant-numeric: tabular-nums; }
.ol-table th, .ol-table td { padding: .2rem .45rem; text-align: center; white-space: nowrap; }
.ol-table tbody th { text-align: left; font-weight: 500; color: var(--muted); }
.ol-table thead th { color: var(--muted); font-weight: 600; }
.ol-table td.held { background: rgba(78, 161, 255, .14); }
/* Silný vítr: oranžový obrys — tvar i barva, čte se i při poruše barvocitu. */
.ol-table td.strong { box-shadow: inset 0 0 0 2px #ff9f43; border-radius: 4px; }
.ol-key { display: flex; align-items: center; gap: .35rem; margin: .45rem 0 0;
  font-size: .7rem; color: var(--muted); }
.ol-key__held, .ol-key__strong { display: inline-block; width: 1.1rem; height: .8rem; border-radius: 3px; }
.ol-key__held { background: rgba(78, 161, 255, .28); }
.ol-key__strong { box-shadow: inset 0 0 0 2px #ff9f43; margin-left: .6rem; }
/* Hodiny z předchozího běhu (ráno dneška u odpoledního běhu). */
.ol-table th.ol-prev, .ol-table th.ol-prev .ol-hour, .ol-key__prev { font-style: italic; opacity: .6; }
.ol-key__prev { margin-left: .6rem; font-size: .9em; }
/* Zeslabení větru: světlá „střecha“ přes horní hranu buňky — tvar a světlost,
 * ne odstín, ať to rozliší i porucha barvocitu (oranžový obrys je komplikace). */
.ol-table td.held.faded { background: rgba(78, 161, 255, .06); }
.ol-table td.brake { position: relative; }
.ol-table td.brake::before { content: ""; position: absolute; left: 3px; right: 3px; top: 0;
  border-top: 3px solid #e9eef6; border-radius: 2px; }
.ol-key__brake { display: inline-block; width: 1.1rem; height: .8rem; margin-left: .6rem;
  border-top: 3px solid #e9eef6; border-radius: 2px; }
.ol-table td span { margin-left: .2rem; }
.ol-sep th { padding-top: .5rem; font-size: .7rem; color: var(--muted); text-align: left; }
.ol-arrow { width: .9em; height: .9em; fill: currentColor; vertical-align: -.1em; }
.ol-note { font-size: .72rem; color: var(--muted); margin: .6rem 0 0; }

/* Karta otočného bodu (CUP, 2026-10-24) — tělo jako záznam letu OGN. */
.tp-panel__facts { color: #c3cedd; font-variant-numeric: tabular-nums; }
.tp-panel__rows { margin-top: .3rem; display: grid; gap: .15rem; }
.tp-panel__row { display: flex; justify-content: space-between; gap: .6rem; }
.tp-panel__row b { font-variant-numeric: tabular-nums; white-space: nowrap; }
.tp-panel__hint, .tp-panel__desc { color: #c3cedd; }
.tp-panel__desc { margin-top: .25rem; }
.tp-panel__desc[hidden] { display: none; }
.tp-row .drawer__row-label { min-width: 0; overflow-wrap: anywhere; }
.tp-row__btns { display: flex; gap: .35rem; flex: 0 0 auto; }
/* Tlačítko otočných bodů ve sloupci nad polohou (`placeProbeBtn()`). */
.map-side-btn { position: absolute; left: .5rem; z-index: 2; background: var(--glass); }
.map-side-btn[hidden] { display: none; }
.map-side-btn[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); }

/* Výzva k přechodu na novou doménu (přejmenování na SimplyMeteo, 2026-10-28),
   jen na starých doménách. Nad vším kromě průvodce, který se tu nespouští. */
.moved {
  position: fixed;
  inset: 0;
  z-index: 55;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(5, 10, 20, .6);
}
.moved__card {
  max-width: 24rem;
  max-height: 100%;
  overflow-y: auto;
  padding: 1.2rem 1.2rem 1rem;
  border-radius: 16px;
  background: var(--panel);
  color: var(--text, #fff);
  box-shadow: 0 10px 40px rgba(0, 0, 0, .5);
}
.moved__card h2 { margin: 0 0 .5rem; font-size: 1.15rem; }
.moved__card p { margin: 0 0 .6rem; line-height: 1.4; color: var(--muted, #b8c4d8); }
.moved__go {
  display: block;
  margin-top: .9rem;
  padding: .75rem 1rem;
  min-height: var(--tap, 44px);
  box-sizing: border-box;
  border-radius: 12px;
  background: var(--accent);
  color: #fff;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
}
/* Oznámení o přejmenování: staré jméno → nové (ikona je u obou stejná). */
.renamed__swap {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  margin: 0 0 .9rem;
}
.renamed__mark { display: inline-flex; align-items: center; gap: .3rem; white-space: nowrap; }
.renamed__mark svg { width: 1.4rem; height: 1.4rem; flex: 0 0 auto; }
.renamed__mark b { font-weight: 700; font-size: .95rem; }
.renamed__mark:first-child { opacity: .6; }
.renamed__mark:first-child b { text-decoration: line-through; }
.renamed__arrow { font-size: 1.4rem; color: var(--accent); }
/* Oznámení o přejmenování má místo odkazu tlačítko. */
button.moved__go { width: 100%; border: 0; font: inherit; font-weight: 700; cursor: pointer; }
.moved__later {
  display: block;
  width: 100%;
  margin-top: .4rem;
  min-height: var(--tap, 44px);
  border: 0;
  background: none;
  color: var(--muted, #b8c4d8);
  font: inherit;
  cursor: pointer;
}
