/*
 * Tmave schema zamerne: dispecink se kouka na obrazovku v setmele mistnosti
 * cely vecer a stav hadanky se pozna barvou, ne ctenim.
 */

:root {
  --bg: #0e1116;
  --panel: #161b22;
  --panel-2: #1c222b;
  --line: #2a323d;
  --text: #d7dee7;
  --muted: #8b95a3;

  --ok: #3fb950;
  --warn: #d29922;
  --err: #f85149;
  --idle: #4d5866;
  --accent: #58a6ff;
}

* { box-sizing: border-box; }

/*
 * Stranka se nescroluje jako celek. Hlavicka drzi nahore a obe sloupce
 * pod ni rolují samostatne - obsluha tak muze projizdet seznam hadanek,
 * aniz by ji zmizela mapa mistnosti.
 */
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 1.25rem;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

h1 { font-size: 1.05rem; margin: 0; font-weight: 600; }
h1 span { color: var(--muted); font-weight: 400; }
h2 { font-size: 0.85rem; margin: 0 0 0.6rem; text-transform: uppercase;
     letter-spacing: 0.06em; color: var(--muted); }

.header-right { display: flex; align-items: center; gap: 0.85rem; }

.badge {
  font-size: 0.75rem;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--muted);
}
.badge-ok   { color: var(--ok);   border-color: color-mix(in srgb, var(--ok) 40%, var(--line)); }
.badge-warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, var(--line)); }
.badge-err  { color: var(--err);  border-color: color-mix(in srgb, var(--err) 40%, var(--line)); }

.toggle { font-size: 0.8rem; color: var(--muted); display: flex; gap: 0.35rem;
          align-items: center; cursor: pointer; }

header { flex: 0 0 auto; }

main {
  flex: 1 1 auto;
  min-height: 0;              /* jinak by grid pretekl misto rolovani */
  display: grid;
  grid-template-columns: minmax(0, 1fr) 21rem;
  gap: 1rem;
  padding: 1rem 1.25rem;
  overflow: hidden;
}

/* Kazdy sloupec ma vlastni rolovani. */
#plans, aside {
  overflow-y: auto;
  overscroll-behavior: contain;   /* konec seznamu neposune stranku pod nim */
  min-height: 0;
  padding-right: 0.35rem;
}

/* Tenci posuvnik, at nekrade misto z uzkeho sloupce. */
#plans::-webkit-scrollbar, aside::-webkit-scrollbar { width: 0.5rem; }
#plans::-webkit-scrollbar-thumb, aside::-webkit-scrollbar-thumb {
  background: var(--line); border-radius: 999px;
}
#plans, aside { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }

/*
 * Nadpisy sekci v bocnim panelu zustavaji videt i pri rolovani, aby bylo
 * jasne, na jakou skupinu zarizeni se clovek diva.
 */
aside h2 {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg);
  padding: 0.35rem 0;
  margin: 0 0 0.5rem;
}

@media (max-width: 60rem) {
  body { height: auto; overflow: visible; }
  main { grid-template-columns: minmax(0, 1fr); overflow: visible; }
  #plans, aside { overflow: visible; }
}

/* Ovladani meritka mapy. */
.zoom { display: flex; align-items: center; gap: 0.25rem; }
#zoom-fit { font-size: 0.8rem; }
.zoom button { padding: 0.1rem 0.45rem; line-height: 1.2; font-size: 0.9rem; }
.zoom span { font-size: 0.72rem; color: var(--muted);
             min-width: 3rem; text-align: center;
             font-variant-numeric: tabular-nums; }

/* Odznak s poctem u nacrtu je mensi nez u kolecka. */
.badge-text { font-size: 0.19px; }

#plan-wrap {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 1rem;
}

#plan { width: 100%; height: auto; display: block; touch-action: none; }

.hint { color: var(--muted); font-size: 0.8rem; margin: 0.6rem 0 0; }
code { background: var(--panel-2); padding: 0.1rem 0.3rem; border-radius: 4px; }

aside { display: flex; flex-direction: column; gap: 1rem; }

aside section {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 1rem;
}

/* ---- karty hadanek ---- */

.puzzle {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.7rem 0.8rem;
  margin-bottom: 0.7rem;
  background: var(--panel-2);
}
.puzzle:last-child { margin-bottom: 0; }

.puzzle-head { display: flex; justify-content: space-between; align-items: center;
               gap: 0.5rem; margin-bottom: 0.5rem; }
.puzzle-head strong { font-size: 0.95rem; }

.plates { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.35rem; }

.plate {
  border-radius: 6px;
  padding: 0.4rem 0.45rem;
  background: var(--bg);
  border: 1px solid var(--line);
  border-left-width: 3px;
  font-size: 0.75rem;
  min-width: 0;
}
.plate b { display: block; font-weight: 600; white-space: nowrap;
           overflow: hidden; text-overflow: ellipsis; }
.plate span { color: var(--muted); }

.s-ok        { border-left-color: var(--ok); }
.s-wrong     { border-left-color: var(--err); }
.s-empty     { border-left-color: var(--idle); }
.s-collision { border-left-color: var(--warn); }
.s-error     { border-left-color: var(--err); }
.s-unset     { border-left-color: var(--accent); }

.actions { display: flex; gap: 0.4rem; margin-top: 0.6rem; }

button {
  font: inherit;
  font-size: 0.78rem;
  padding: 0.3rem 0.7rem;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
}
button:hover { border-color: var(--accent); color: var(--accent); }

/* ---- log ---- */

#log { list-style: none; margin: 0; padding: 0; max-height: 20rem;
       overflow-y: auto; font-size: 0.78rem; }
#log li { display: flex; gap: 0.5rem; padding: 0.25rem 0;
          border-bottom: 1px solid var(--line); }
#log li:last-child { border-bottom: none; }
#log time { color: var(--muted); font-variant-numeric: tabular-nums;
            flex: 0 0 auto; }
.l-success { color: var(--ok); }
.l-warn    { color: var(--warn); }
.l-error   { color: var(--err); }

/* ---- pudorys ---- */

.wall     { stroke: #3b4653; stroke-width: 0.08; stroke-linecap: square; }
/*
 * Barvu dveri nastavuje skript podle stavu hadanky, ktera je otevira,
 * a to atributem stroke. Kdyby ji urcovalo i tohle pravidlo, prebilo by
 * atribut - CSS ma prednost pred prezentacnimi atributy - a dvere by
 * zustaly porad modre.
 */
.door     { stroke-width: 0.12; stroke-linecap: round; }
.furniture{ fill: #1b212a; stroke: #313a46; stroke-width: 0.03; }
/*
 * Obtah barvou panelu, aby text zustal citelny i kdyz se prekryva s jinym
 * prvkem. paint-order: stroke vykresli obtah POD vypln, takze pismena
 * nezhrubnou - jen dostanou cistou mezeru kolem sebe.
 */
.label, .node-caption {
  stroke: var(--panel);
  stroke-width: 0.07px;
  stroke-linejoin: round;
  paint-order: stroke;
}

.label    { fill: var(--muted); font-size: 0.17px; text-anchor: middle; }

.node { cursor: pointer; }
.node.dragging { opacity: 0.6; }
/*
 * Barvy glyfu se nastavuji primo v kresbe (public/lib/glyphs.js), ne tady.
 * CSS ma prednost pred prezentacnimi atributy, takze jedno pravidlo pro
 * .glyph by prebilo zamerne vyplne uvnitr - klicovou dirku zamku nebo
 * objektiv kamery. Skupina glyfu nese jen atribut color a jednotlive
 * casti si ho berou pres currentColor.
 */
.node-text { fill: #0e1116; font-size: 0.24px; font-weight: 700;
             text-anchor: middle; dominant-baseline: central; }
.node-caption { fill: var(--text); font-size: 0.15px; text-anchor: middle; }

.cam-cone { fill: var(--accent); opacity: 0.07; }

/* ---- lightbox ---- */

#lightbox {
  position: fixed; inset: 0; background: rgba(8, 10, 14, 0.88);
  display: flex; align-items: center; justify-content: center; padding: 1.5rem;
  z-index: 10;
}
/*
 * display:flex vyse by prebilo atribut hidden a lightbox by zustal viset
 * pres celou stranku i zavreny. Musi se schovat explicitne.
 */
#lightbox[hidden] { display: none; }
.lightbox-inner { max-width: min(96vw, 70rem); width: 100%; }
.lightbox-bar { display: flex; justify-content: space-between;
                align-items: center; margin-bottom: 0.5rem; }
.lightbox-bar h2 { margin: 0; color: var(--text); font-size: 1rem;
                   text-transform: none; letter-spacing: 0; }
#lightbox-close { font-size: 1rem; line-height: 1; padding: 0.25rem 0.6rem; }
#lightbox-img { width: 100%; border-radius: 10px; border: 1px solid var(--line);
                background: #000; display: block; }

/* ======================================================================
 * Univerzalni kostra: prihlaseni, vic mistnosti, animace SVG prvku
 * ====================================================================== */

body.centered {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

#login {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 1.75rem;
  width: min(22rem, 92vw);
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}
#login h1 { font-size: 1.05rem; margin: 0 0 0.4rem; }
#login label { display: flex; flex-direction: column; gap: 0.3rem;
               font-size: 0.8rem; color: var(--muted); }
#login input {
  font: inherit;
  padding: 0.5rem 0.6rem;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--text);
}
#login input:focus { outline: none; border-color: var(--accent); }
#login button { padding: 0.5rem; font-size: 0.9rem; }
.error { color: var(--err); font-size: 0.8rem; margin: 0; }

/* ---- hlavicka ---- */

.header-left { display: flex; align-items: center; gap: 0.75rem; }
.controls { display: flex; gap: 0.35rem; }

.clock {
  font-variant-numeric: tabular-nums;
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--muted);
}
.clock.urgent { color: var(--err); animation: blink-slow 1s steps(2) infinite; }

button:disabled { opacity: 0.4; cursor: not-allowed; }
button:disabled:hover { border-color: var(--line); color: var(--text); }

/* ---- pudorys ---- */

#plans {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0;
  overflow: hidden;          /* pudorys si roluje sam pres zoom a posun */
  display: flex;
  min-height: 0;
}

.plan-svg {
  width: 100%;
  height: 100%;
  display: block;
  /*
   * Bez tohohle si prohlizec vezme gesto pro sebe a roztazeni dvema prsty
   * zoomuje celou stranku misto mapy.
   */
  touch-action: none;
  cursor: grab;
}
.plan-svg:active { cursor: grabbing; }

.floor {
  fill: var(--panel);
  stroke: none;
}
.room-active .floor {
  fill: color-mix(in srgb, var(--ok) 7%, var(--panel));
}

.wall     { stroke: #3b4653; stroke-width: 0.08; stroke-linecap: square; }
.room-active .wall { stroke: color-mix(in srgb, var(--ok) 45%, #3b4653); }

.furniture{ fill: var(--panel-2); stroke: #313a46; stroke-width: 0.025; }

/* Velikost pisma nastavuje app.js podle sirky mistnosti, proto tu neni -
   pravidlo v CSS by prebilo atribut na prvku a jmena by zase pretekala. */
.room-name {
  fill: var(--ink-faint, var(--muted));
  font-weight: 600;
}
.room-active .room-name { fill: var(--ok); }

.room-here { fill: var(--ok); }

.cam-cone { fill: var(--accent); opacity: 0.07; }

.node { cursor: pointer; }
.node.dragging { opacity: 0.6; }
.node-body { stroke-width: 0.05; }

/*
 * Barvy glyfu se nastavuji primo v kresbe (public/lib/glyphs.js), ne tady.
 * CSS ma prednost pred prezentacnimi atributy, takze jedno pravidlo pro
 * .glyph by prebilo zamerne vyplne uvnitr - klicovou dirku zamku nebo
 * objektiv kamery.
 */

/*
 * Obtah barvou panelu, aby text zustal citelny i kdyz se prekryva s jinym
 * prvkem. paint-order: stroke vykresli obtah POD vypln, takze pismena
 * nezhrubnou - jen dostanou cistou mezeru kolem sebe.
 */
.label, .node-caption, .room-name, .room-here {
  stroke: var(--panel);
  stroke-width: 0.07px;
  stroke-linejoin: round;
  paint-order: stroke;
}

.label    { fill: var(--muted); font-size: 0.17px; text-anchor: middle; }
.node-text { fill: #0e1116; font-size: 0.24px; font-weight: 700;
             text-anchor: middle; dominant-baseline: central; }
.node-caption { fill: var(--text); font-size: 0.17px; text-anchor: middle; }

/*
 * Popisky zarizeni az od urcite blizkosti. Na celkovem pohledu na budovu
 * by se pres sebe navrsily a mapa ma z dalky ukazovat stav, ne jmena.
 */
.plan-svg .node-caption,
.plan-svg .label { display: none; }
.plan-svg.with-captions .node-caption,
.plan-svg.with-captions .label { display: inline; }

/* ---- karty zarizeni ---- */

.device {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.65rem 0.75rem;
  margin-bottom: 0.6rem;
  background: var(--panel-2);
}
.device-head { display: flex; justify-content: space-between; align-items: center;
               gap: 0.5rem; }
.device-head strong { font-size: 0.9rem; }
.device .actions { margin-top: 0.55rem; }

.slots { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.35rem;
         margin-top: 0.5rem; }
.slot {
  border-radius: 6px;
  padding: 0.35rem 0.4rem;
  background: var(--bg);
  border: 1px solid var(--line);
  border-left-width: 3px;
  font-size: 0.72rem;
  min-width: 0;
}
.slot b { display: block; font-weight: 600; white-space: nowrap;
          overflow: hidden; text-overflow: ellipsis; }
.slot span { color: var(--muted); }

.s-ok        { border-left-color: var(--ok); }
.s-wrong     { border-left-color: var(--err); }
.s-empty     { border-left-color: var(--idle); }
.s-collision { border-left-color: var(--warn); }
.s-error     { border-left-color: var(--err); }
.s-unset     { border-left-color: var(--accent); }

/* ---- SVG prvky ---- */


/* ---- animace ----
 *
 * Vsechny bezi v CSS, ne v JS. Prekresleni mapy pri kazde zmene stavu by
 * jinak animaci porad restartovalo a vysledkem by bylo skubani.
 */

@keyframes blink-slow { 50% { opacity: 0.25; } }
@keyframes blink-fast { 50% { opacity: 0.15; } }
@keyframes pulse      { 50% { transform: scale(1.12); } }
@keyframes pulse-once {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.25); }
  100% { transform: scale(1); }
}
@keyframes ping {
  0%   { transform: scale(1);   opacity: 1; }
  70%  { transform: scale(1.4); opacity: 0.4; }
  100% { transform: scale(1);   opacity: 1; }
}
/* Vlna kolem cidla. Kratsi dosah, at nezasahuje do sousednich ikon. */
@keyframes ring {
  0%   { transform: scale(0.6); opacity: 0.85; }
  100% { transform: scale(1.35); opacity: 0; }
}

.anim-blink-slow { animation: blink-slow 1.4s steps(2) infinite; }
.anim-blink-fast { animation: blink-fast 0.4s steps(2) infinite; }
.anim-pulse      { animation: pulse 1.6s ease-in-out infinite; }
.anim-pulse-once { animation: pulse-once 0.6s ease-out; }
.anim-ping       { animation: ping 1.8s ease-in-out infinite; }
.anim-ring       { animation: ring 1.8s ease-out infinite; transform-origin: center; }

/* Kdo si vypnul animace v systemu, at je nedostane ani tady. */
@media (prefers-reduced-motion: reduce) {
  .anim-blink-slow, .anim-blink-fast, .anim-pulse,
  .anim-pulse-once, .anim-ping, .anim-ring,
  .clock.urgent { animation: none; }
}

/* ---- reset checklist ---- */

#reset { list-style: none; margin: 0; padding: 0; font-size: 0.78rem;
         max-height: 16rem; overflow-y: auto; }
#reset li { display: flex; gap: 0.45rem; align-items: flex-start;
            padding: 0.25rem 0; border-bottom: 1px solid var(--line); }
#reset li:last-child { border-bottom: none; }
#reset input { margin-top: 0.15rem; flex: 0 0 auto; accent-color: var(--ok); }
#reset label { color: var(--text); cursor: pointer; }
#reset b { color: var(--muted); font-weight: 500; margin-right: 0.3rem; }
/* Odškrtnuté zešedne, at je videt, co jeste zbyva. */
#reset input:checked + label { color: var(--muted); text-decoration: line-through; }

.blocked { color: var(--warn); }

/* ---- odpocet do startu ----
 *
 * Velka cislice, ktera se zmensuje a mizi. Kazda sekunda dostane novy
 * uzel, takze se animace spolehlive spusti od zacatku.
 */

#countdown {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  /* Pruhledne pro mys - obsluha muze mezitim dal klikat. */
  pointer-events: none;
  background: radial-gradient(ellipse at center,
              rgba(14, 17, 22, 0.92) 0%,
              rgba(14, 17, 22, 0.72) 55%,
              rgba(14, 17, 22, 0.45) 100%);
}
#countdown[hidden] { display: none; }

#countdown-number {
  /* Pevna vyska, aby pod cislem neposkakoval popisek. */
  height: clamp(9rem, 34vh, 22rem);
  display: flex;
  align-items: center;
  justify-content: center;
}

#countdown-number span {
  display: block;
  font-size: clamp(7rem, 26vw, 22rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  text-shadow: 0 0 3rem rgba(88, 166, 255, 0.35);
  transform-origin: center;
}

#countdown-note {
  margin: 0;
  color: var(--muted);
  font-size: 0.95rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

/* Cislice: nalétne velka a zmensuje se, jak sekunda ubiha. */
@keyframes count-tick {
  0%   { transform: scale(2.4); opacity: 0; }
  12%  { transform: scale(1.5); opacity: 1; }
  100% { transform: scale(0.82); opacity: 0.12; }
}

/* START! je kratsi a naopak vyrazny do konce. */
@keyframes count-go {
  0%   { transform: scale(0.4); opacity: 0; }
  25%  { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1); opacity: 0.9; }
}

.count-tick { animation: count-tick 1s cubic-bezier(0.22, 0.9, 0.3, 1) forwards; }
/*
 * START! je sest znaku proti jedne cislici, takze pri stejne velikosti
 * pisma pretece z obrazovky. Vlastni velikost, ne spolecna.
 */
.count-go   { animation: count-go 0.5s cubic-bezier(0.2, 1.4, 0.4, 1) forwards;
              font-size: clamp(3rem, 13vw, 9rem);
              color: var(--ok); text-shadow: 0 0 3rem rgba(63, 185, 80, 0.45); }

/* Behem odpoctu hodiny jeste nebezi - at to je videt. */
.clock.waiting { opacity: 0.45; }

@media (prefers-reduced-motion: reduce) {
  .count-tick, .count-go { animation: none; opacity: 1; transform: none; }
}

/* ---- kamerova stena ----
 *
 * Stejna mrizka se pouziva v plovoucim ramecku i v samostatnem okne,
 * proto je stylovani spolecne a lisi se jen obal.
 */

.camwall-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.65rem;
  border-bottom: 1px solid var(--line);
}

.camwall-modes, .camwall-pick { display: flex; gap: 0.25rem; flex-wrap: wrap; }

.camwall-bar button {
  font-size: 0.72rem;
  padding: 0.2rem 0.5rem;
}
.camwall-bar button.active {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--panel));
}
.camwall-popout { margin-left: auto; }

.camwall-grid {
  display: grid;
  gap: 0.3rem;
  padding: 0.3rem;
  /* Jedna kamera pres celou plochu, dve vedle sebe, tri a ctyri do ctverce. */
  grid-template-columns: 1fr 1fr;
}
.camwall-grid[data-count="1"] { grid-template-columns: 1fr; }

.camtile {
  position: relative;
  margin: 0;
  background: #000;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid var(--line);
  aspect-ratio: 4 / 3;
}
.camtile.clickable { cursor: zoom-in; }
.camtile.clickable:hover { border-color: var(--accent); }

.camtile img { width: 100%; height: 100%; object-fit: cover; display: block; }

.camtile figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 0.2rem 0.45rem;
  font-size: 0.7rem;
  color: var(--text);
  /* Prechod misto plne listy, at obraz nezakryva vic, nez musi. */
  background: linear-gradient(to top, rgba(8, 10, 14, 0.85), transparent);
}

/* ---- plovouci ramecek na hlavni strance ---- */

#camframe {
  position: fixed;
  left: 1.25rem;
  bottom: 1rem;
  width: min(26rem, 40vw);
  z-index: 8;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 1rem 2.5rem rgba(0, 0, 0, 0.55);
  overflow: hidden;
}

.frame-bar {
  cursor: grab;
  user-select: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.4rem 0.65rem;
  background: var(--panel-2);
  border-bottom: 1px solid var(--line);
}
.frame-bar:active { cursor: grabbing; }
.frame-bar h2 { margin: 0; }
.frame-tools button { padding: 0.1rem 0.5rem; line-height: 1.2; }

/* Sbaleny ramecek necha na obrazovce jen listu. */
#camframe.collapsed .camwall-bar,
#camframe.collapsed #camwall .camwall-grid { display: none; }

@media (max-width: 60rem) {
  #camframe { position: static; width: auto; margin: 0 1.25rem 1rem; }
}

/* ---- samostatne okno ---- */

body.camwindow { overflow: hidden; }
body.camwindow main {
  display: block;
  padding: 0;
  overflow: hidden;
}
body.camwindow .camwall-grid {
  /* Vyska okna minus hlavicka a lista rezimu. */
  height: calc(100vh - 7.2rem);
  padding: 0.5rem;
  gap: 0.5rem;
}
body.camwindow .camtile { aspect-ratio: auto; }
body.camwindow .camtile figcaption { font-size: 0.85rem; padding: 0.35rem 0.6rem; }

/* ---- zvyrazneni zarizeni po kliknuti ve schematu ----
 *
 * Perioda 0.6 s musi sedet s FLASH_PERIOD v app.js - skript podle ni
 * pocita zaporne zpozdeni, ktere drzi fazi pres prekresleni panelu.
 */

@keyframes card-flash {
  0%, 100% { box-shadow: 0 0 0 0 transparent; border-color: var(--line); }
  40%      { box-shadow: 0 0 0 0.22rem color-mix(in srgb, var(--accent) 45%, transparent);
             border-color: var(--accent); }
}

.device.flash {
  animation: card-flash 0.6s ease-in-out infinite;
  /* Rámeček nesmí posunout obsah, proto stín a ne šířka okraje. */
  position: relative;
  z-index: 1;
}

@keyframes ring-flash {
  0%, 100% { stroke-opacity: 0; stroke-width: 0.05; }
  40%      { stroke-opacity: 0.95; stroke-width: 0.09; }
}

.flash-ring {
  stroke: var(--accent);
  animation: ring-flash 0.6s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  /* Bez animace, ale zvyrazneni musi zustat - je to sdeleni, ne ozdoba. */
  .device.flash { animation: none; border-color: var(--accent);
                  box-shadow: 0 0 0 0.18rem color-mix(in srgb, var(--accent) 35%, transparent); }
  .flash-ring { animation: none; stroke-opacity: 0.9; }
}
