/* ═══════════════════════════════════════════════════════════════════
   APP SHELL v5 — pixel-perfect shell parity with KOKPIT
   ─────────────────────────────────────────────────────────────────────
   Extracted from kokpit-v5.css (the canonical reference). Every page
   that loads this file gets the SAME shell as KOKPIT:
     - <div class="ekg-wrapper">  (in-flow, above agent-bar)
     - <section class="agent-bar"><div class="agent-input-wrapper">...</div></section>
     - <footer class="statusbar"> (5 segments, GLASS HOUSE injected by utils.js)

   Pages must use the IDENTICAL DOM structure documented in
   docs/audit/kokpit_reference_measurements.md.

   Kadr i rynnik biorą się z --page-max i --page-pad-x (base-v5.css).
   Poniższe --kk-* to tylko aliasy pod starą nazwą; wartości NIE wolno
   tu powtórzyć. Patrz scripts/check_layout_tokens.sh.
   ═══════════════════════════════════════════════════════════════════ */

:root {
  --kk-max:   var(--page-max);
  --kk-pad-x: var(--page-pad-x);
}

/* Match kokpit's body padding so shell rows + content rows share the
   same content width on every tab. KOKPIT itself sets this via
   kokpit-v5.css; we skip body[data-page="kokpit"] to avoid clobbering
   its grid layout.

   STICKY-FOOTER SHELL: body is a flex column with height: 100vh and
   overflow: hidden. Nav, ekg, agent-bar, statusbar are all
   flex-shrink: 0 and stay in place. <main> is flex: 1 + overflow-y:
   auto (with min-height: 0 — the classic flex-overflow fix), so
   long timelines / lists scroll inside main without ever pushing the
   footer rows out of the viewport. Drawers (.iterum-drawer etc) are
   position: fixed so they live outside the flex flow. */
html, body { margin: 0; padding: 0; }
body:not([data-page="kokpit"]) {
  display: flex;
  flex-direction: column;
  height: 100vh;
  max-height: 100vh;
  overflow: hidden;
  padding-left: var(--kk-pad-x);
  padding-right: var(--kk-pad-x);
  box-sizing: border-box;
  scrollbar-gutter: stable;
}

body:not([data-page="kokpit"]) > header.nav,
body:not([data-page="kokpit"]) > .nav,
body:not([data-page="kokpit"]) > .ekg-wrapper,
body:not([data-page="kokpit"]) > section.agent-bar,
body:not([data-page="kokpit"]) > footer.statusbar,
body:not([data-page="kokpit"]) > .org-pulse-bar {
  flex-shrink: 0;
}

body:not([data-page="kokpit"]) > main {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

/* Pages whose <main> already capped itself at --page-max: reset that
   cap so main width follows the new body padding. Per-page padding-x
   is dropped — body padding is canonical. */
body:not([data-page="kokpit"]) main.missions-main,
body:not([data-page="kokpit"]) main.threats-main,
body:not([data-page="kokpit"]) main.proof-main,
body:not([data-page="kokpit"]) main.org-page,
body:not([data-page="kokpit"]) main.au-wrap,
body:not([data-page="kokpit"]) main.cs-wrap,
body:not([data-page="kokpit"]) main.sb-wrap,
body:not([data-page="kokpit"]) main.sh-wrap,
body:not([data-page="kokpit"]) main.theatrum-main,
body:not([data-page="kokpit"]) main.tm-page,
body:not([data-page="kokpit"]) main.tm-page-v6,
body:not([data-page="kokpit"]) main.scd-shell,
body:not([data-page="kokpit"]) main.av-wrap,
body:not([data-page="kokpit"]) main.cp-wrap,
body:not([data-page="kokpit"]) main.ts-main,
body:not([data-page="kokpit"]) main.in-wrap,
body:not([data-page="kokpit"]) main.dw-wrap,
body:not([data-page="kokpit"]) main.nx-wrap,
body:not([data-page="kokpit"]) main.ex-page,
body:not([data-page="kokpit"]) main.bs-wrap,
body:not([data-page="kokpit"]) main.ar-wrap,
body:not([data-page="kokpit"]) main.org-icu,
body:not([data-page="kokpit"]) main.us-wrap,
body:not([data-page="kokpit"]) main.op-wrap,
/* #1126 Batch A: 12 pages that centered their column (max-width + margin:0 auto)
   because they never loaded app-shell. Onboard them onto the canonical reset so
   body padding owns full width and .cy-page-head goes flush-left. */
body:not([data-page="kokpit"]) main.n2-wrap,
body:not([data-page="kokpit"]) main.mt-wrap,
body:not([data-page="kokpit"]) main.rp-wrap,
body:not([data-page="kokpit"]) main.sp-page,
body:not([data-page="kokpit"]) main.an-page,
body:not([data-page="kokpit"]) main.um-page,
body:not([data-page="kokpit"]) main.tp-wrap,
body:not([data-page="kokpit"]) main.forum-page,
body:not([data-page="kokpit"]) main.cn-wrap,
body:not([data-page="kokpit"]) main.gd-wrap,
body:not([data-page="kokpit"]) main.ch-wrap,
body:not([data-page="kokpit"]) main.pf-wrap,
/* #1126 Batch C: ai-audit dostał <main class="aia-wrap"> (był <div> bez main →
   treść clippowana pod app-shell overflow:hidden, brak scrolla). Reset centrowania. */
body:not([data-page="kokpit"]) main.aia-wrap,
body:not([data-page="kokpit"]) main.sg-wrap,
/* #1131 Batch D: strony nigdy nie onboardowane do app-shell (audyt v2) —
   competitor-intel, modules, els_validation, portrait, tools + f32pulse (był <div>). */
body:not([data-page="kokpit"]) main.ci-wrap,
body:not([data-page="kokpit"]) main.md-wrap,
body:not([data-page="kokpit"]) main.ev-wrap,
body:not([data-page="kokpit"]) main.pt-wrap,
body:not([data-page="kokpit"]) main.tl-wrap,
body:not([data-page="kokpit"]) main.fp-wrap,
/* #2271: /purple centrował kolumnę na 1280px, a /probes i /suasor dokładały
   własny padding poziomy do paddingu body, przez co treść startowała 48px
   dalej niż na pozostałych stronach. */
body:not([data-page="kokpit"]) main.pu-wrap,
body:not([data-page="kokpit"]) main.pr-wrap,
body:not([data-page="kokpit"]) main.su-wrap,
/* #2657: /lex dokładał własny `padding: 24px var(--kk-pad-x) 64px` plus
   `margin: 0 auto` (lex.html), przez co treść startowała 178px od krawędzi
   zamiast 48px jak wszędzie indziej. Ta sama klasa co #2271. */
body:not([data-page="kokpit"]) main.lex-wrap,
body:not([data-page="kokpit"]) main.forum-admin {
  max-width: none;
  margin: 0;
  padding-left: 0;
  padding-right: 0;
}

/* Wave 3+4 legacy pages use <div class="wrapper"> + <div id="cyrber-nav-root">
   instead of <main> + <header class="nav">. The wrapper becomes the scrollable
   flex:1 main row; the nav-root becomes the flex-shrink:0 nav row. Page-
   specific .wrapper styles (max-width caps, horizontal padding, min-height:100vh)
   are reset so body padding owns the canonical width. Pages that need to opt-out
   can redeclare these on body[data-page="<their_page>"] > .wrapper with higher
   specificity. */
body:not([data-page="kokpit"]) > #cyrber-nav-root,
body:not([data-page="kokpit"]) > nav#cyrber-nav-root {
  flex-shrink: 0;
}
body:not([data-page="kokpit"]) > .wrapper,
body:not([data-page="kokpit"]) > .cy-page {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  max-width: none;
  width: auto;
  margin: 0;
  padding-left: 0;
  padding-right: 0;
}

/* Organism's body[data-page=organism] also overrides shell .agent-bar with
   its own min-height — clamp it back to kokpit canon so .agent-input-wrapper
   does not stretch. */
body[data-page="organism"] section.agent-bar { min-height: 0; height: auto; padding: 0; }

/* base-v5.css gives header.nav its own padding-x and max-width. With
   body padding now canonical we don't want a double pad — strip nav's
   horizontal padding and let body's padding place it. */
body:not([data-page="kokpit"]) > header.nav,
body:not([data-page="kokpit"]) > .nav {
  padding-left: 0;
  padding-right: 0;
  max-width: none;
}

/* Kokpit potrzebuje tego samego, tylko z innego powodu. Reguła
   `html, body { margin: 0; padding: 0 }` wyżej w tym pliku kasuje
   kokpitowi jego własny `padding: 0 var(--page-pad-x)` z kokpit-v5.css
   (ta sama specyficzność, ten arkusz ładuje się później), a przywrócenie
   paddingu w `body:not([data-page="kokpit"])` omija kokpit. Zostawało więc
   body bez paddingu (od #2655 przywrócony powyżej 1400px, niżej nadal zero),
   wiersze vitals/board
   płasko na krawędzi boxa, a nav 48px do środka na własnym
   `padding: 0 var(--page-pad-x)` z cyrber-shell.css. Zdejmujemy ten pad,
   żeby pasek trzymał tę samą krawędź co kafle pod nim. kokpit-v5.css:120
   deklarowało `padding: 0` właśnie w tym celu; cyrber-shell.css ładuje się
   po nim i przy równej specyficzności to nadpisywał. max-width zostaje
   (--page-max i --kk-max to ta sama klamra, więc obie kolumny się kryją). */
body[data-page="kokpit"] > header.nav,
body[data-page="kokpit"] > .nav {
  padding-left: 0;
  padding-right: 0;
}

/* #2655: kokpit odzyskuje poziomy rynnik. Reguła `html, body { padding: 0 }`
   wyżej w tym pliku kasowała mu własny poziomy padding z
   kokpit-v5.css, a przywrócenie pod `body:not([data-page="kokpit"])` go omija,
   więc kafle, plansza, EKG i pasek stanu dociskały do krawędzi okna, gdy każda
   inna strona trzyma margines.

   Próg 1400px NIE jest z sufitu. Wiersze kokpitu mają minimalną szerokość
   ~1270px i poniżej tego nie potrafią się zwęzić, a `body { overflow: hidden }`
   zjada prawą krawędź bez żadnego sygnału. Zmierzone z rynnikiem: przy 1280
   dostępne 1193 i ostatni kafel ucięty o 38px, przy 1320 dostępne 1231 i ucięty
   o 40px, przy 1366 dostępne 1274 przy minimum 1274, czyli zapas 4px, za cienki
   na wahania fontu i powiększenia. Przy 1400 zapas to 36px.

   Poniżej progu kokpit zostaje płaski przy krawędzi, dokładnie jak przed tą
   zmianą, więc na wąskich oknach nie ma regresji. Warunkiem wstępnym było
   #2653: przed naprawą siatki rynnik zabierał paskowi 96px i marka wchodziła
   na pierwszą pozycję. */
@media (min-width: 1400px) {
  body[data-page="kokpit"] {
    padding-left: var(--page-pad-x);
    padding-right: var(--page-pad-x);
  }
}

/* Ta sama zasada dla paska podnawigacji wstrzykiwanego przez nav.js.
   base-v5.css:404 daje .cyrber-subnav-inner `padding: 8px 24px`, więc na
   stronach z tym shellem okruszek startował 24px głębiej niż napisy w
   navie i tytuł strony (zmierzone na /threats: crumb 72, nav 48, tytuł 48).
   Poziomy pad należy do body, tak jak w .ekg-wrapper i .statusbar. */
body > nav.cyrber-subnav > .cyrber-subnav-inner {
  padding-left: 0;
  padding-right: 0;
}

/* The three shell rows (ekg, agent-bar, statusbar) all stretch to the
   same content width as kokpit's vitals/board grids — visually centered
   inside the body, capped at --kk-max. */
.ekg-wrapper,
.agent-bar,
.statusbar {
  position: relative;
  z-index: 1;
}

/* ─── EKG (above agent bar) ───────────────────────────────────────── */
.ekg-wrapper {
  max-width: var(--kk-max);
  width: 100%;
  margin: 0 auto;
  padding: 0;
  height: clamp(48px, 6vh, 84px);
  min-height: 0;
  display: flex;
  align-items: center;
  overflow: hidden;
  animation: shell-fade-in 600ms 500ms ease both;
}
.ekg-wrapper .ekg-svg { height: 100%; }

.ekg-svg {
  position: relative;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
}

.ekg-waveform {
  stroke: var(--accent-signal, #e4e8e9);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
  filter: drop-shadow(0 0 3px rgba(var(--signal-rgb, 228, 232, 233), 0.5));
  vector-effect: non-scaling-stroke;
  transition: stroke 1.2s ease, filter 1.2s ease;
}

.ekg-mask-window {
  animation: ekg-sweep 4.5s linear infinite;
  will-change: transform;
}
@keyframes ekg-sweep {
  from { transform: translateX(-600px); }
  to   { transform: translateX(1500px); }
}

.ekg-wrapper.ekg-fast .ekg-mask-window { animation-duration: 2.4s; }
.ekg-wrapper.ekg-fast .ekg-waveform {
  stroke: rgb(209, 101, 101);
  filter: drop-shadow(0 0 5px rgba(209, 101, 101, 0.6));
}

/* ─── AGENT BAR + composer (kokpit canon) ─────────────────────────── */
.agent-bar {
  max-width: var(--kk-max);
  width: 100%;
  margin: 0 auto;
  padding: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  animation: shell-fade-in 300ms 400ms ease both;
}

.agent-input-wrapper {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: clamp(14px, 1.6vh, 22px) clamp(18px, 1.5vw, 28px);
  border-radius: 10px;
  background: rgba(var(--ink-rgb, 255, 255, 255), 0.02);
  box-shadow:
    rgba(var(--ink-rgb, 255, 255, 255), 0.06) 0 1px 0 0 inset,
    rgba(var(--ink-rgb, 255, 255, 255), 0.12) 0 0 0 1px inset,
    rgba(0, 0, 0, 0.3) 0 4px 20px -4px;
  transition: background 200ms cubic-bezier(0.4, 0, 0.2, 1),
              box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}

.agent-input-wrapper:focus-within {
  background: rgba(20, 20, 20, 0.85);
  box-shadow:
    rgba(var(--ink-rgb, 255, 255, 255), 0.04) 0 1px 0 0 inset,
    rgba(91, 127, 166, 0.25) 0 0 0 1px inset,
    rgba(0, 0, 0, 0.4) 0 4px 24px -4px;
}

/* #2961: pole agenta bez wlasnego pierscienia fokusu. Globalna regula a11y
   z base-v5.css (input:not([type="hidden"]):focus-visible, 0,2,1) rysowala
   turkusowy obrys ciasno wokol pola i zaslaniala wpisywany tekst. Fokus
   pokazuje pojemnik (.agent-input-wrapper:focus-within wyzej), wiec pole
   zostaje z samym migajacym kursorem. Selektor 0,3,1 wygrywa niezaleznie
   od kolejnosci arkuszy. */
input.agent-input:not([type="hidden"]):focus,
input.agent-input:not([type="hidden"]):focus-visible {
  outline: none;
  box-shadow: none;
  caret-color: var(--fg-primary, #f2f2f2);
}

.agent-prompt-glyph {
  font-family: var(--font-data);
  font-size: 18px;
  color: var(--accent-ratio);
  opacity: 0.8;
  flex-shrink: 0;
  line-height: 1;
}

.agent-input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  font-family: 'Inter', sans-serif;
  font-size: clamp(13px, 1.1vh, 16px);
  color: var(--fg-primary, #fafafa);
  padding: 4px 0;
  min-width: 0;
}

.agent-input::placeholder {
  color: var(--fg-tertiary, #6b6b6b);
  font-weight: 400;
}

.agent-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

.agent-send, .agent-cmdk {
  padding: 8px 12px;
  border-radius: 5px;
  background: rgba(var(--ink-rgb, 255, 255, 255), 0.04);
  box-shadow: rgba(var(--ink-rgb, 255, 255, 255), 0.08) 0 0 0 1px inset;
  color: var(--fg-secondary, #a1a1a1);
  font-family: var(--font-data);
  font-size: 11px;
  letter-spacing: 0.04em;
  white-space: nowrap;
  cursor: pointer;
  border: none;
  transition: background 200ms, color 200ms, box-shadow 200ms;
}
.agent-send:hover, .agent-cmdk:hover {
  background: rgba(var(--ink-rgb, 255, 255, 255), 0.08);
  color: var(--fg-primary, #fafafa);
  box-shadow: rgba(var(--ink-rgb, 255, 255, 255), 0.18) 0 0 0 1px inset;
}

/* ─── STATUS BAR ───────────────────────────────────────────────────── */
.statusbar {
  padding: clamp(11px, 1vh, 14px) 0;
  max-width: var(--kk-max);
  width: 100%;
  margin: 0 auto;
  display: flex; align-items: center; gap: 10px;
  box-shadow: var(--border-subtle, rgba(var(--ink-rgb, 255, 255, 255), 0.06)) 0 1px 0 0 inset;
  font-family: var(--font-data);
  font-size: clamp(11px, 0.85vh, 12px);
  color: var(--fg-tertiary, #6b6b6b);
  min-height: 0;
  animation: shell-fade-in 300ms 500ms ease both;
}

.statusbar .sep { color: var(--fg-tertiary); }

.sb-live {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--accent-live);
}
.sb-live-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent-live);
  animation: shell-pulse 2s ease-in-out infinite;
}

.sb-num { color: var(--fg-secondary, #a1a1a1); }

.sb-clock {
  margin-left: auto;
  display: inline-flex; align-items: baseline; gap: 8px;
  font-family: var(--font-data);
  font-size: clamp(13px, 1.15vh, 16px);
  letter-spacing: 0.06em;
}
.sb-clock #sbDate { color: var(--fg-tertiary, #6b6b6b); }
.sb-clock .sb-clock-sep { color: var(--fg-tertiary); }
.sb-clock #sbTime { color: var(--fg-primary, #fafafa); }

/* ─── Animations ──────────────────────────────────────────────────── */
@keyframes shell-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes shell-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.55; transform: scale(0.85); }
}

/* #3289: LIVE tylko przy świeżych danych; utils.js ustawia data-state. */
.statusbar .sb-live[data-state="wait"],
.statusbar .sb-live[data-state="wait"] .sb-live-dot { color: var(--fg-tertiary); background-color: transparent; }
.statusbar .sb-live[data-state="wait"] .sb-live-dot { background: var(--fg-tertiary); animation: none; opacity: .5; }
.statusbar .sb-live[data-state="nostream"] { color: var(--accent-warning); }
.statusbar .sb-live[data-state="nostream"] .sb-live-dot { background: var(--accent-warning); animation: none; box-shadow: none; }
.statusbar .sb-live[data-state="down"] { color: var(--accent-critical); }
.statusbar .sb-live[data-state="down"] .sb-live-dot { background: var(--accent-critical); animation: none; box-shadow: none; }

/* ─── #3629: telefon ───────────────────────────────────────────────────
   Na desktopie powłoka to kolumna 100vh: nav, przewijany <main> i trzy
   stałe pasy na dole (EKG, agent, stopka). Na 390x664 te pasy brały 208 px,
   czyli 31% ekranu, a treść przewijała się w okienku ~300 px. Poniżej 720 px
   przewija się cały dokument, EKG znika (jak .cyrber-ekg w cyrber-shell.css),
   pasek agenta przykleja się do dołu w jednym rzędzie, a stopka schodzi na
   koniec strony.

   overflow-x: clip zamiast hidden: reguła `html, body { overflow-x: hidden }`
   z cyrber-shell.css robi z body kontener przewijania i wtedy sticky trzyma
   się body zamiast ekranu. clip przycina bez tworzenia kontenera.
   Selektory z `body >` i `html:root`, bo cyrber-shell.css ładuje się po tym
   arkuszu i przy równej specyficzności wygrywał (position: relative). */
@media (max-width: 720px) {
  html:root, html:root > body { overflow-x: clip; }

  body:not([data-page="kokpit"]) {
    display: block;
    height: auto;
    max-height: none;
    min-height: 100vh;
    min-height: 100dvh;
    overflow-y: visible;
    padding-left: 16px;
    padding-right: 16px;
    scrollbar-gutter: auto;
  }
  body:not([data-page="kokpit"]) > main,
  body:not([data-page="kokpit"]) > .wrapper,
  body:not([data-page="kokpit"]) > .cy-page {
    overflow: visible;
    min-height: 0;
  }

  body[data-page="kokpit"] {
    display: block;
    height: auto;
    max-height: none;
    overflow-y: visible;
    padding-left: 16px;
    padding-right: 16px;
  }
  body[data-page="kokpit"] > * + * { margin-top: 12px; }

  body > .ekg-wrapper { display: none; }

  body > .agent-bar {
    position: sticky;
    bottom: 0;
    z-index: 50;
    margin-top: 16px;
    padding: 8px 0 calc(8px + env(safe-area-inset-bottom, 0px));
    background: var(--bg-canvas, #0a0a0a);
    box-shadow: var(--border-subtle, rgba(var(--ink-rgb, 255, 255, 255), 0.06)) 0 1px 0 0 inset;
  }
  .agent-input-wrapper { padding: 6px 6px 6px 14px; gap: 8px; }
  /* 16 px, bo iOS powiększa stronę przy fokusie pola z mniejszą czcionką. */
  .agent-input { font-size: 16px; }
  .agent-cmdk { display: none; }
  .agent-send { min-height: 40px; padding: 8px 14px; }

  body > .statusbar {
    flex-wrap: wrap;
    row-gap: 4px;
    padding: 10px 0 calc(12px + env(safe-area-inset-bottom, 0px));
  }
  .sb-clock { margin-left: 0; font-size: 12px; }

  /* FORUM i „do góry” nad przyklejonym paskiem agenta (~60 px), a nie na nim. */
  body #cyrber-forum-fab {
    right: 16px;
    bottom: calc(72px + env(safe-area-inset-bottom, 0px));
    width: 44px;
    height: 44px;
  }
  body #cyrberScrollTop {
    right: 22px;
    bottom: calc(128px + env(safe-area-inset-bottom, 0px));
  }

  /* Cele dotyku (#3629 PR2). Nawigacja jest na każdej stronie, więc 40 px;
     drobne linki i chipy pod 24 px (próg WCAG 2.2 AA) dostają co najmniej
     32 px. Rośnie obszar kliknięcia, rysunek zostaje ten sam. */
  body .nv-btn,
  body .nv-icon,
  body .nv-user { height: 40px; min-width: 40px; }
  body .nv-mobile-toggle { min-width: 40px; min-height: 40px; }
  body a.brand { min-height: 40px; }
  body .statusbar > #cyrber-glasshouse-link.gh--inline,
  body .statusbar .cap-cat-btn {
    display: inline-flex;
    align-items: center;
    min-height: 32px;
    min-width: 32px;
  }
  body a.sb-back,
  body a.md-quicklink,
  body a.tl-quicklink,
  body a.cn-quicklink {
    display: inline-flex;
    align-items: center;
    min-height: 32px;
  }
  body .timeline-zoom-btn { min-height: 32px; min-width: 40px; }
}
