/* Asystent AI REMARKED — the standalone chat page (ADR-0008, §14, issue #22; the remarked.pl
   design system, issue #36 — dark, gold, Unbounded + Instrument Sans).

   Layout and components only. Every colour, size, radius, shadow and duration comes from
   `tokens.css` — no raw values here (tests/web/test_web_tokens.py checks), so a brand swap
   never touches this file. Only layout ratios (percentages, flex) live here.

   The page is an app shell: a fixed top bar, the transcript scrolling in the middle, the
   screen area (buttons, forms, the composer) pinned at the bottom. Nothing overlaps at any
   width, and the composer stays above the phone keyboard (dynamic viewport units). */

*, *::before, *::after { box-sizing: border-box; }

html {
  font-size: var(--czcionka-baza);
  -webkit-text-size-adjust: 100%;
  height: 100%;
}

body {
  margin: 0;
  /* --wys-okna: the visible height when the phone keyboard is open (app.js, iOS Safari
     keeps 100dvh under the keyboard); 100dvh otherwise. */
  height: var(--wys-okna, 100dvh);
  display: grid;
  /* the bar, the progress line, the transcript, the screen area, the AI note — named,
     so a hidden region (the bar in a frame, an empty progress line) keeps every other
     region in its own row */
  grid-template-rows: auto auto minmax(0, 1fr) auto auto;
  grid-template-areas: "pasek" "postep" "rozmowa" "ekran" "stopka";
  /* never wider than the viewport: a region's min-content (a long word, the progress
     line) must not widen the page (PR #38 review, B1) */
  grid-template-columns: minmax(0, 1fr);
  background: var(--kolor-tlo);
  color: var(--kolor-tekst);
  font-family: var(--czcionka);
  font-weight: var(--waga-normalna);
  line-height: var(--interlinia);
  overflow: hidden;
}

/* --- the top bar ------------------------------------------------------------------- */
.naglowek { grid-area: pasek; }
#postep { grid-area: postep; }
#rozmowa { grid-area: rozmowa; }
#ekran { grid-area: ekran; }
.stopka { grid-area: stopka; }
.naglowek {
  background: var(--kolor-powierzchnia);
  border-bottom: var(--grubosc-linii) solid var(--kolor-linia);
  padding-top: env(safe-area-inset-top);
  z-index: 2;
}
.naglowek-wnetrze {
  width: 100%;
  max-width: var(--kolumna);
  min-height: var(--pasek-wys);
  margin: 0 auto;
  padding: var(--odstep-2) var(--odstep-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--odstep-3);
}
.marka {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0 var(--odstep-2);
  min-width: 0;
}
/* The white REMARKED logo (the site kit), then the quiet mono „asystent”. */
/* A CSS background, not an <img>: the bar is hidden in a frame, and a hidden element's
   background is never fetched (PR #38 review). */
.marka-logo {
  display: block;
  flex: none;
  width: var(--logo-szer);
  height: var(--logo-wys);
  background: url("/static/remarked-logo-biale.svg") no-repeat center / contain;
}
.marka-podtytul {
  display: flex;
  align-items: center;
  gap: var(--odstep-2);
  color: var(--kolor-tekst-3);
  font-family: var(--czcionka-mono);
  font-size: var(--rozmiar-mono);
  letter-spacing: var(--odstep-liter-mono);
  text-transform: uppercase;
  white-space: nowrap;
}
/* Discreet staging marker (issue #8): small, muted, never competing with the brand. */
.odznaka-test {
  font-size: var(--rozmiar-xs);
  font-weight: var(--waga-pogrubiona);
  letter-spacing: var(--odstep-liter);
  text-transform: uppercase;
  color: var(--kolor-tekst-2);
  background: var(--kolor-powierzchnia-2);
  border-radius: var(--promien-okragly);
  padding: 0 var(--odstep-2);
  line-height: var(--interlinia);
}

/* Inside a frame — the remarked.pl panel (issue #36, the site's spec §1–2): the panel has
   its own header and close button, so the bar goes and the transcript takes its row;
   framed-only controls (the end screen's „Zamknij”, „Zostaw numer” under the composer)
   appear. html.w-ramce is set by straz.js before the body renders. */
/* not inside a frame: hidden whatever the element's own display rule (`.btn` comes
   later at the same specificity — issue #79: „Zamknij” showed and did nothing) */
html:not(.w-ramce) .tylko-w-ramce { display: none; }
html.w-ramce .naglowek { display: none; }
html.w-ramce form.tylko-w-ramce { display: flex; justify-content: center; }
html.w-ramce button.tylko-w-ramce { display: inline-flex; }
/* „Zamknij” posts rmk:close to the parent: only a parent app.js knows is allowed hears
   it (issue #79: on any other it did nothing) */
html.w-ramce:not(.rodzic-dozwolony) .zamknij-panel { display: none; }
html.w-ramce .ekran > .zostaw-numer { margin-top: 0; }
/* staging only: the test badge in the hidden bar's own grid row, so nothing in the
   transcript ever scrolls under it (m12, #46: it covered the booking confirmation) */
html.w-ramce .odznaka-ramka {
  display: block;
  grid-area: pasek;
  /* centred, with room below: at the right edge it sat on top of the client's own
     bubbles as they scrolled under the row's edge (#53 m6) */
  justify-self: center;
  margin: var(--odstep-1) var(--odstep-2) var(--odstep-1);
  pointer-events: none;
}

/* --- the remarked.pl kit's mono pieces (issue #36): the progress line, the service chip,
   the AI note under the composer ------------------------------------------------- */
.mono {
  font-family: var(--czcionka-mono);
  font-size: var(--rozmiar-mono);
  font-weight: var(--waga-normalna);
  letter-spacing: var(--odstep-liter-mono);
  text-transform: uppercase;
}
.postep:empty { display: none; }
.postep-wnetrze {
  display: flex;
  align-items: center;
  gap: var(--odstep-3);
  max-width: var(--kolumna);
  margin: 0 auto;
  padding: var(--odstep-2) var(--odstep-4);
  color: var(--kolor-tekst-2);
  white-space: nowrap;
}
.postep-wnetrze > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.postep { border-bottom: var(--grubosc-linii) solid var(--kolor-linia); }
.postep-pasek { flex: 1 1 0%; min-width: 0; height: var(--postep-wys); accent-color: var(--kolor-akcent); }
.postep-pasek::-webkit-progress-bar { background: var(--kolor-linia); border-radius: var(--promien-okragly); }
.postep-pasek::-webkit-progress-value { background: var(--kolor-akcent); border-radius: var(--promien-okragly); }
.postep-pasek::-moz-progress-bar { background: var(--kolor-akcent); border-radius: var(--promien-okragly); }
.postep-pasek { appearance: none; border: 0; background: var(--kolor-linia); border-radius: var(--promien-okragly); }
.usluga-chip {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: var(--odstep-2);
  padding: var(--odstep-1) var(--odstep-3);
  color: var(--kolor-tekst-2);
  background: var(--kolor-powierzchnia) var(--tlo-szklo);
  border: var(--grubosc-linii) solid var(--kolor-szklo-ramka);
  border-radius: var(--promien-przycisk);
}
.usluga-chip::before { content: ""; width: var(--kropka); height: var(--kropka); border-radius: var(--promien-okragly); background: var(--kolor-akcent); }
.stopka {
  margin: 0;
  line-height: var(--interlinia-ciasna);
  padding: 0 var(--odstep-4) calc(var(--odstep-2) + env(safe-area-inset-bottom));
  color: var(--kolor-tekst-3);
  background: var(--kolor-powierzchnia);
  text-align: center;
  text-transform: none;
  letter-spacing: 0;
}
/* The booking confirmation (issue #36): a card with the gold check, not a bubble. */
.potwierdzenie {
  display: flex;
  gap: var(--odstep-3);
  align-items: flex-start;
  align-self: stretch;
  padding: var(--odstep-4);
  background: var(--kolor-powierzchnia) var(--tlo-szklo);
  border: var(--grubosc-linii) solid var(--kolor-szklo-ramka);
  border-radius: var(--promien-l);
}
.potwierdzenie-ptaszek {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: var(--ptaszek);
  height: var(--ptaszek);
  color: var(--kolor-na-glownym);
  background: var(--kolor-glowny) var(--tlo-glowne);
  border-radius: var(--promien-okragly);
  font-weight: var(--waga-pogrubiona);
}
.potwierdzenie-tytul { margin: 0 0 var(--odstep-1); font-family: var(--czcionka-display); font-size: var(--rozmiar-xl); font-weight: var(--waga-tytul-karty); line-height: var(--interlinia-tytul); letter-spacing: var(--odstep-liter-tytul); }
.potwierdzenie-tekst { margin: 0; color: var(--kolor-tekst-2); white-space: pre-wrap; overflow-wrap: anywhere; }

/* --- the transcript ------------------------------------------------------------------ */
.rozmowa {
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-behavior: smooth;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--odstep-2);
  /* the reading column: the scroller itself is full-width so the scrollbar sits at the edge */
  padding: var(--odstep-4) max(var(--odstep-4), calc((100% - var(--kolumna)) / 2)) var(--odstep-5);
}
/* The §3 greeting: the page heading of the start screen (not a bubble). It sits at the
   bottom of a short transcript, right above the start rows, like the approved mockup. */
.rozmowa > :first-child { margin-top: auto; }
.wstep { display: flex; flex-direction: column; gap: var(--odstep-3); margin-bottom: var(--odstep-2); }
.wstep-tytul {
  margin: 0;
  font-family: var(--czcionka-display);
  font-size: var(--rozmiar-tytul);
  font-weight: var(--waga-tytul);
  line-height: var(--interlinia-tytul);
  letter-spacing: var(--odstep-liter-tytul);
  text-wrap: balance;
}
.wstep-tekst { margin: 0; color: var(--kolor-tekst-2); text-wrap: pretty; }
.dymek {
  max-width: 85%;
  padding: var(--odstep-3) var(--odstep-4);
  border-radius: var(--promien-m);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.dymek.asystent {
  align-self: flex-start;
  background: var(--kolor-powierzchnia) var(--tlo-szklo);
  border: var(--grubosc-linii) solid var(--kolor-szklo-ramka);
}
.dymek.asystent + .dymek.asystent { margin-top: calc(-1 * var(--odstep-1)); }
.dymek.klient {
  align-self: flex-end;
  background: var(--kolor-tlo) var(--tlo-dymek-klienta);
  color: var(--kolor-na-dymku-klienta);
  border: var(--grubosc-linii) solid var(--kolor-zloto-ramka);
}
/* A system note: something the client did (ticked consents), not something they said. */
.notatka {
  align-self: center;
  margin: var(--odstep-1) 0;
  padding: var(--odstep-1) var(--odstep-3);
  color: var(--kolor-tekst-3);
  font-size: var(--rozmiar-s);
  text-align: center;
  border-radius: var(--promien-okragly);
  background: var(--kolor-powierzchnia-2);
}
.notatka::before { content: "✓ "; color: var(--kolor-ok); font-weight: var(--waga-pogrubiona); }

/* The "assistant is thinking" indicator (ADR-0027, variant 5; templates/mysli.html). A
   one-line assistant bubble: two dark dots and the gold brand dot wave in turn (the
   brand dot breathes a halo), the label shimmers. It takes its place at once but shows
   only after --mysli-opoznienie, so a fast reply never flickers it and nothing jumps when
   the finished reply replaces it. */
.mysli {
  display: flex;
  align-items: center;
  gap: var(--odstep-3);
  max-width: 100%;
  white-space: nowrap;
  animation: mysli-pokaz 0s linear var(--mysli-opoznienie) both;
}
@keyframes mysli-pokaz { from { visibility: hidden; } to { visibility: visible; } }
.mysli-kropki { display: inline-flex; align-items: center; gap: var(--odstep-1); flex: none; }
.mysli-kropki i {
  width: var(--kropka); height: var(--kropka); border-radius: var(--promien-okragly);
  background: var(--kolor-tekst);
  opacity: 0.3;
  animation: mysli-fala var(--mysli-fala) ease-in-out infinite;
}
.mysli-kropki i:nth-child(2) { animation-delay: var(--mysli-fala-krok); }
.mysli-kropki .mysli-marka {
  position: relative;
  width: var(--kropka-marka); height: var(--kropka-marka);
  background: var(--kolor-akcent);
  opacity: 1;
  animation-name: mysli-fala-marka;
  animation-delay: calc(var(--mysli-fala-krok) * 2);
}
.mysli-marka::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--promien-okragly);
  background: var(--kolor-akcent);
  opacity: 0;
  animation: mysli-oddech var(--mysli-fala) ease-out calc(var(--mysli-fala-krok) * 2) infinite;
}
@keyframes mysli-fala {
  0%, 60%, 100% { transform: none; opacity: 0.3; }
  30% { transform: translateY(calc(-1 * var(--mysli-skok))); opacity: 0.9; }
}
@keyframes mysli-fala-marka {
  0%, 60%, 100% { transform: none; }
  30% { transform: translateY(calc(-1 * var(--mysli-skok))) scale(1.1); }
}
@keyframes mysli-oddech {
  0% { transform: scale(1); opacity: 0; }
  30% { transform: scale(1); opacity: 0.35; }
  100% { transform: scale(3); opacity: 0; }
}
.mysli-etykieta {
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: var(--waga-srednia);
  color: var(--kolor-mysli);
  background: linear-gradient(100deg, var(--kolor-mysli) 40%, var(--kolor-akcent) 50%, var(--kolor-mysli) 60%) 0 0 / 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: mysli-blysk var(--mysli-blysk) linear infinite;
}
@keyframes mysli-blysk { from { background-position: 100% 0; } to { background-position: -100% 0; } }
/* The timeout state (app.js): the message and the retry action replace the dots. */
.mysli-blad { white-space: normal; }
.mysli.mysli-przerwane { animation: none; }
.mysli.mysli-przerwane .mysli-kropki, .mysli.mysli-przerwane .mysli-etykieta { display: none; }
@media (prefers-reduced-motion: reduce) {
  /* .mysli-kropki .mysli-marka repeats the base rule's specificity (0-2-0), which would
     otherwise keep the brand dot waving (PR #33 review). */
  .mysli-kropki i, .mysli-kropki .mysli-marka, .mysli-marka::after, .mysli-etykieta { animation: none; }
  .mysli-kropki i { opacity: 0.6; }
  .mysli-marka::after { display: none; }
  .mysli-etykieta { background: none; -webkit-text-fill-color: currentColor; }
}

/* Visually hidden, still read: the page's status region (#stan-asystenta). */
.tylko-czytnik {
  position: absolute;
  width: var(--grubosc-linii);
  height: var(--grubosc-linii);
  margin: 0;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- the screen area (buttons, forms, composer) ------------------------------------- */
.ekran {
  background: var(--kolor-powierzchnia);
  border-top: var(--grubosc-linii) solid var(--kolor-linia);
  padding: var(--odstep-3) var(--odstep-4) calc(var(--odstep-3) + env(safe-area-inset-bottom));
  max-height: var(--ekran-wys-max);
  overflow-y: auto;
}
.ekran-wnetrze, .ekran > * { width: 100%; max-width: var(--kolumna); margin-inline: auto; }
.ekran > * + * { margin-top: var(--odstep-3); }
/* the office e-mail under the consent card stays in the column (issue #85 m3: .drobne's
   own margin: 0 put it in the window's corner) */
.ekran > .drobne { margin-inline: auto; }
.ekran:has(.kontakt-form) { max-height: var(--kontakt-wys-max); }

/* One action at a time (issue #85, B2/M1). While the composer holds text (html.pisze,
   set by app.js — text, not just spaces: review of #86, N1), sending it is the one
   action: the quick answers and the actions beside it step aside (the two buttons under
   the composer, „Pomiń”, the options, the start rows, „Zostaw numer”), and come back
   when it is empty — Edgar's two buttons (#73) are there whenever the client is not
   typing. The send arrow is quiet while there is nothing to send, so one control
   carries the gold in every state. Forms and slots stay; app.js keeps the draft
   whatever is clicked (B1). */
html.pisze .ekran :is(.akcje-pod, .wybory, .wybory-start, .wybory-akcje, .zostaw-numer),
html.pisze #naglowek-akcja form { display: none; }
html.pisze .ekran :is(.karta .btn, .karta-akcje .btn) {
  color: var(--kolor-tekst);
  background: var(--kolor-powierzchnia-2) var(--tlo-szklo);
  border-color: var(--kolor-szklo-ramka);
  box-shadow: none;
}

/* Buttons: the primary is the dark action, the secondary a light fill; only the send
   button carries the accent. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--odstep-2);
  min-height: var(--dotyk);
  padding: var(--odstep-2) var(--odstep-5);
  font: inherit;
  font-weight: var(--waga-srednia);
  line-height: var(--interlinia-ciasna);
  color: var(--kolor-na-glownym);
  background: var(--kolor-glowny) var(--tlo-glowne);
  border: var(--grubosc-linii-pola) solid var(--kolor-glowny);
  border-radius: var(--promien-przycisk);
  box-shadow: var(--cien-zloty);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--ruch-szybki) var(--ruch-krzywa), border-color var(--ruch-szybki) var(--ruch-krzywa);
}
.btn:hover { background: var(--kolor-glowny-hover) var(--tlo-glowne-hover); border-color: var(--kolor-glowny-hover); }
.btn:disabled { opacity: var(--wylaczone); cursor: default; }
.btn-drugi { color: var(--kolor-tekst); background: var(--kolor-powierzchnia-2) var(--tlo-szklo); border-color: var(--kolor-szklo-ramka); box-shadow: none; }
.btn-drugi:hover { color: var(--kolor-tekst); background: var(--kolor-linia); border-color: var(--kolor-linia-mocna); }
.btn-ikona {
  flex: none;
  width: var(--dotyk);
  height: var(--dotyk);
  padding: 0;
  color: var(--kolor-na-akcencie);
  background: var(--kolor-akcent) var(--tlo-glowne);
  border-color: var(--kolor-akcent);
  border-radius: var(--promien-okragly);
}
.btn-ikona:hover { background: var(--kolor-akcent-hover) var(--tlo-glowne-hover); border-color: var(--kolor-akcent-hover); }
html:not(.pisze) .kompozytor .btn-ikona {
  color: var(--kolor-tekst-2);
  background: var(--kolor-powierzchnia-2) var(--tlo-szklo);
  border-color: var(--kolor-szklo-ramka);
  box-shadow: none;
}
.btn-ikona svg { width: var(--ikona); height: var(--ikona); }
/* A quiet action that reads as an underlined link but keeps a full tap target. */
.btn-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--dotyk-s);
  padding: var(--odstep-1);
  font: inherit;
  font-size: var(--rozmiar-s);
  font-weight: var(--waga-normalna);
  line-height: var(--interlinia-ciasna);
  color: var(--kolor-tekst-2);
  background: transparent;
  border: 0;
  border-radius: var(--promien-s);
  text-decoration: underline;
  text-underline-offset: var(--podkreslenie);
  cursor: pointer;
  transition: color var(--ruch-szybki) var(--ruch-krzywa);
}
.btn-link:hover { color: var(--kolor-akcent); }
.btn-link:disabled { opacity: var(--wylaczone); cursor: default; }
/* „Zostaw numer” in the top bar: always there, the body colour, a little stronger. */
.btn-naglowek { color: var(--kolor-tekst); font-weight: var(--waga-srednia); }

:is(.btn, .btn-link, .wiersz, .opcja, .termin, .rozmowa, textarea, input, a, summary):focus-visible,
.opcja:has(input:focus-visible) {
  outline: var(--fokus-grubosc) solid var(--kolor-fokus);
  outline-offset: var(--fokus-odstep);
}
.opcja input:focus-visible { outline: none; }

/* htmx indicators. The library's own <style> injection is switched off (strona.html:
   the CSP has no 'unsafe-inline'), so the two default rules live here, with token motion. */
.htmx-indicator { opacity: 0; transition: opacity var(--ruch-normalny) var(--ruch-krzywa); }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { opacity: 1; }

/* Choices: quick-reply chips (single = buttons, multi = checkbox chips + „Dalej”). */
.wybory {
  display: flex;
  flex-wrap: wrap;
  gap: var(--odstep-2);
}
.opcja {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--odstep-2);
  min-height: var(--dotyk);
  padding: var(--odstep-2) var(--odstep-4);
  font: inherit;
  font-weight: var(--waga-normalna);
  line-height: var(--interlinia-ciasna);
  text-align: center;
  color: var(--kolor-tekst);
  background: var(--kolor-powierzchnia) var(--tlo-szklo);
  border: var(--grubosc-linii-pola) solid var(--kolor-linia-mocna);
  border-radius: var(--promien-przycisk);
  cursor: pointer;
  position: relative;
  transition: background var(--ruch-szybki) var(--ruch-krzywa), border-color var(--ruch-szybki) var(--ruch-krzywa);
}
.opcja:hover { background: var(--kolor-powierzchnia-2); border-color: var(--kolor-tekst); }
.opcja:disabled { opacity: var(--wylaczone); cursor: default; }
/* De-emphasised, still clearly an action: the border keeps the ≥ 3:1 boundary colour. */
.opcja-cicha { color: var(--kolor-tekst-2); }
.opcja input { width: var(--pole-wyboru); height: var(--pole-wyboru); margin: 0; flex: none; accent-color: var(--kolor-akcent); }
.opcja:has(input:checked) { background: var(--kolor-akcent-tlo) var(--tlo-dymek-klienta); border-color: var(--kolor-akcent); color: var(--kolor-akcent-tlo-tekst); }
.wybory-akcje { display: flex; flex-wrap: wrap; gap: var(--odstep-2); align-items: center; }
/* The two actions under the composer once the contact is saved (issue #73): a call or the
   meeting, side by side, each ≥ 44 px; the meeting carries the gold. */
.akcje-pod { display: flex; flex-wrap: wrap; gap: var(--odstep-2); justify-content: center; margin-top: var(--odstep-2); }
.akcje-pod form { display: contents; }
.akcje-pod .opcja { flex: 1 1 0%; min-width: 0; }
.opcja-zlota {
  font-weight: var(--waga-srednia);
  color: var(--kolor-na-glownym);
  background: var(--kolor-glowny) var(--tlo-glowne);
  border-color: var(--kolor-glowny);
}
.opcja-zlota:hover { background: var(--kolor-glowny-hover) var(--tlo-glowne-hover); border-color: var(--kolor-glowny-hover); }

/* The start screen (issue #73): the gold primary row, two light rows, each with an arrow. */
.wybory-start { display: flex; flex-direction: column; gap: var(--odstep-2); }
.wiersz {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--odstep-3);
  width: 100%;
  min-height: var(--wiersz-wys-2);
  padding: var(--odstep-2) var(--odstep-5);
  font: inherit;
  line-height: var(--interlinia-ciasna);
  text-align: start;
  color: var(--kolor-tekst);
  background: var(--kolor-powierzchnia-2) var(--tlo-szklo);
  border: var(--grubosc-linii) solid var(--kolor-szklo-ramka);
  border-radius: var(--promien-przycisk);
  cursor: pointer;
  transition: background var(--ruch-szybki) var(--ruch-krzywa);
}
.wiersz:hover { background: var(--kolor-linia); }
.wiersz:disabled { opacity: var(--wylaczone); cursor: default; }
.wiersz .strzalka { flex: none; color: var(--kolor-tekst-3); transition: transform var(--ruch-szybki) var(--ruch-krzywa); }
.wiersz:hover .strzalka { transform: translateX(var(--odstep-1)); }
.wiersz-glowny {
  min-height: var(--wiersz-wys);
  font-weight: var(--waga-srednia);
  color: var(--kolor-na-glownym);
  background: var(--kolor-glowny) var(--tlo-glowne);
  border-color: var(--kolor-glowny);
  box-shadow: var(--cien-zloty);
}
.wiersz-glowny:hover { background: var(--kolor-glowny-hover) var(--tlo-glowne-hover); }
.wiersz-glowny .strzalka { color: var(--kolor-strzalka-glowna); }
.wiersz.w-trakcie { opacity: 1; }
/* On the start screen the rows continue the heading above: no divider between them, one
   hairline above the composer instead. */
.ekran:has(.wybory-start) { border-top-color: transparent; }
.wybory-start + .kompozytor {
  margin-top: var(--odstep-4);
  padding-top: var(--odstep-3);
  border-top: var(--grubosc-linii) solid var(--kolor-linia);
}

/* Slots: a tidy grid of day + time, then the two fallbacks, then the status line. */
.terminy-form { display: grid; gap: var(--odstep-3); }
.terminy {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--termin-min), 1fr));
  gap: var(--odstep-2);
}
.termin {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--odstep-1);
  min-height: calc(var(--dotyk) + var(--odstep-3));
  padding: var(--odstep-2) var(--odstep-3);
  font: inherit;
  line-height: var(--interlinia-ciasna);
  color: var(--kolor-tekst);
  background: var(--kolor-powierzchnia) var(--tlo-szklo);
  border: var(--grubosc-linii-pola) solid var(--kolor-linia-mocna);
  border-radius: var(--promien-l);
  cursor: pointer;
  transition: background var(--ruch-szybki) var(--ruch-krzywa), border-color var(--ruch-szybki) var(--ruch-krzywa);
}
.termin:hover { background: var(--kolor-powierzchnia-2); border-color: var(--kolor-tekst); }
.termin:disabled { opacity: var(--wylaczone); cursor: default; }
/* The slot just clicked stays fully visible and selected while the reservation runs. */
.termin.w-trakcie {
  opacity: 1;
  color: var(--kolor-na-glownym);
  background: var(--kolor-glowny) var(--tlo-glowne);
  border-color: var(--kolor-glowny);
  animation: puls calc(var(--ruch-normalny) * 5) var(--ruch-krzywa) infinite;
}
@keyframes puls { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }
.termin-dzien { font-family: var(--czcionka-mono); font-size: var(--rozmiar-mono); letter-spacing: var(--odstep-liter-mono); text-transform: uppercase; color: var(--kolor-tekst-2); }
.termin.w-trakcie .termin-dzien { color: inherit; }
.termin-godzina { font-size: var(--rozmiar-l); font-weight: var(--waga-srednia); font-variant-numeric: tabular-nums; }
/* A live status line (app.js fills it from the form's data-w-trakcie while a request runs). */
.status { margin: 0; color: var(--kolor-tekst-2); font-weight: var(--waga-srednia); }
.status:not(:empty)::before { content: ""; display: inline-block; width: var(--kropka); height: var(--kropka); margin-right: var(--odstep-2); vertical-align: middle; border-radius: var(--promien-okragly); background: var(--kolor-akcent); animation: puls calc(var(--ruch-normalny) * 5) var(--ruch-krzywa) infinite; }
.status:empty { display: none; }

/* The composer: an auto-growing textarea and the round gold send button. */
.kompozytor {
  display: flex;
  flex-wrap: wrap;
  gap: var(--odstep-2);
  align-items: flex-end;
}
.kompozytor textarea {
  flex: 1;
  min-width: 0;
  min-height: var(--dotyk);
  max-height: var(--pole-wys-max);
  resize: none;
  padding: calc((var(--dotyk) - var(--interlinia-pola) - 2 * var(--grubosc-linii-pola)) / 2) var(--odstep-4);
  font: inherit;
  line-height: var(--interlinia-pola);
  color: var(--kolor-tekst);
  background: var(--kolor-powierzchnia);
  border: var(--grubosc-linii-pola) solid var(--kolor-linia-mocna);
  border-radius: var(--promien-pole);
  transition: border-color var(--ruch-szybki) var(--ruch-krzywa);
}
.kompozytor textarea:focus { border-color: var(--kolor-akcent); }
.kompozytor textarea::placeholder { color: var(--kolor-tekst-3); opacity: 1; }
.kompozytor textarea:disabled { background: var(--kolor-powierzchnia-2); color: var(--kolor-tekst-3); }
/* Until htmx has wired the page (straz.js holds any submit meanwhile): the composer and the
   answer buttons look and act disabled. Without JS (no .js class) the forms POST natively. */
html.js:not(.htmx-gotowy) #ekran :is(textarea, button) { pointer-events: none; opacity: var(--wylaczone); }

/* Cards: consents, the callback form, the office contact. */
.karta {
  padding: var(--odstep-4);
  background: var(--kolor-powierzchnia) var(--tlo-szklo);
  border: var(--grubosc-linii) solid var(--kolor-szklo-ramka);
  border-radius: var(--promien-l);
  box-shadow: var(--cien-2);
}
.karta p { margin: 0 0 var(--odstep-3); }
.karta p:last-child { margin-bottom: 0; }
.karta-tytul { margin: 0 0 var(--odstep-1); font-family: var(--czcionka-display); font-size: var(--rozmiar-xl); font-weight: var(--waga-tytul-karty); line-height: var(--interlinia-tytul); letter-spacing: var(--odstep-liter-tytul); }
.karta-opis { margin: 0 0 var(--odstep-3); color: var(--kolor-tekst-2); font-size: var(--rozmiar-s); }
.karta-akcje { display: flex; flex-wrap: wrap; gap: var(--odstep-3); align-items: center; justify-content: space-between; margin-top: var(--odstep-4); }
.karta-srodek { max-width: var(--kolumna-waska); margin: var(--odstep-8) auto; }
/* A card can be taller than the screen area (the consent list, the callback form): its
   action row sticks to the bottom edge while the rest scrolls. */
.karta .karta-akcje {
  position: sticky;
  bottom: calc(-1 * var(--odstep-3) - env(safe-area-inset-bottom));
  margin: var(--odstep-3) calc(-1 * var(--odstep-4)) calc(-1 * var(--odstep-4));
  padding: var(--odstep-3) var(--odstep-4) var(--odstep-4);
  background: var(--kolor-powierzchnia);
  border-top: var(--grubosc-linii) solid var(--kolor-linia);
  border-radius: 0 0 var(--promien-l) var(--promien-l);
}
.karta-zgody .karta-akcje { justify-content: flex-end; }
.karta-zgody .drobne { margin-bottom: var(--odstep-2); }

/* Consents: flat rows separated by a hairline; the checkbox alone carries the state. */
.zgody-lista { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.zgody-lista li + li { border-top: var(--grubosc-linii) solid var(--kolor-linia); }
.zgoda {
  display: flex;
  gap: var(--odstep-3);
  align-items: flex-start;
  padding: var(--odstep-3) var(--odstep-1);
  border-radius: var(--promien-s);
  cursor: pointer;
}
.zgoda:has(input:focus-visible) { outline: var(--fokus-grubosc) solid var(--kolor-fokus); outline-offset: calc(-1 * var(--fokus-odstep)); }
.zgoda input { width: var(--pole-wyboru); height: var(--pole-wyboru); flex: none; margin: calc(var(--odstep-1) / 2) 0 0; accent-color: var(--kolor-akcent); }
.zgoda input:focus-visible { outline: none; }
.zgoda-tekst { flex: 1; }
.etykietka {
  display: inline-block;
  margin-left: var(--odstep-1);
  padding: 0 var(--odstep-2);
  font-family: var(--czcionka-mono);
  font-size: var(--rozmiar-mono);
  font-weight: var(--waga-normalna);
  letter-spacing: var(--odstep-liter-mono);
  text-transform: uppercase;
  color: var(--kolor-tekst-2);
  background: var(--kolor-powierzchnia-2);
  border-radius: var(--promien-okragly);
  vertical-align: middle;
}

.formularz { display: flex; flex-direction: column; gap: var(--odstep-3); }
.formularz label { display: flex; flex-direction: column; gap: var(--odstep-1); font-weight: var(--waga-srednia); }
.formularz label span { font-weight: var(--waga-normalna); color: var(--kolor-tekst-2); font-size: var(--rozmiar-s); }
.formularz input[type="tel"], .formularz input[type="text"], .formularz input[type="email"] {
  min-height: var(--dotyk);
  padding: var(--odstep-2) var(--odstep-4);
  font: inherit;
  color: var(--kolor-tekst);
  background: var(--kolor-tlo);
  border: var(--grubosc-linii-pola) solid var(--kolor-linia-mocna);
  border-radius: var(--promien-pole);
}
.formularz input:focus { border-color: var(--kolor-akcent); box-shadow: var(--cien-zloty); }
.formularz .zgoda { flex-direction: row; gap: var(--odstep-3); font-weight: var(--waga-normalna); }
.formularz .zgoda .zgoda-tekst { color: var(--kolor-tekst); font-size: var(--rozmiar-m); }

.drobne { margin: 0; color: var(--kolor-tekst-3); font-size: var(--rozmiar-s); }
.blad {
  margin: 0;
  padding: var(--odstep-2) var(--odstep-3);
  color: var(--kolor-blad);
  background: var(--kolor-blad-tlo);
  border-radius: var(--promien-s);
  font-weight: var(--waga-pogrubiona);
}
a { color: var(--kolor-tekst); text-underline-offset: var(--podkreslenie); }
.drobne a, .zgoda-tekst a { color: var(--kolor-akcent); }
a:hover { color: var(--kolor-akcent); }

/* The plain pages (the cancel link): a centred card, no app shell. */
body.strona-prosta {
  display: block;
  height: auto;
  min-height: 100dvh;
  overflow: auto;
  padding: var(--odstep-4);
}
/* The first load's failure screen (429, 503 — templates/awaria.html): the chat's own
   ground and card, centred; „Ponowna próba” and the countdown under the text. Inside
   the remarked.pl panel (html.w-ramce) the card fills the panel's width edge to edge and
   our logo goes — the panel's header names the assistant (spec §1). */
body.strona-awaria {
  display: flex;
  height: auto;
  min-height: var(--wys-okna, 100dvh);
  align-items: center;
  justify-content: center;
  overflow: auto;
  padding: var(--odstep-4);
}
.awaria-karta { width: 100%; max-width: var(--kolumna-waska); }
.awaria-karta .karta-akcje { position: static; margin: var(--odstep-4) 0 0; padding: 0; background: none; border: 0; }
.awaria-logo { margin-bottom: var(--odstep-5); }
.awaria-tytul { margin: 0 0 var(--odstep-3); font-family: var(--czcionka-display); font-size: var(--rozmiar-xl); font-weight: var(--waga-tytul-karty); line-height: var(--interlinia-tytul); letter-spacing: var(--odstep-liter-tytul); }
.awaria-odliczanie { color: var(--kolor-tekst-2); }
html.w-ramce .strona-awaria { align-items: flex-start; padding: var(--odstep-5); }
html.w-ramce .strona-awaria .awaria-logo { display: none; }
html.w-ramce .strona-awaria .awaria-karta { max-width: none; }
/* „Rozmowa wygasła – zaczynamy od nowa.” above the greeting: said, not ticked off. */
.ekran > .notatka.wygasla { display: block; width: fit-content; margin: 0 auto var(--odstep-3); }
.notatka.wygasla::before { content: none; }

.strona-prosta h1 { font-family: var(--czcionka-display); font-size: var(--rozmiar-xl); line-height: var(--interlinia-tytul); letter-spacing: var(--odstep-liter-tytul); margin: 0 0 var(--odstep-4); }

/* --- phones (the breakpoint is the one value a media query cannot take from a token) --- */
@media (max-width: 600px) {
  html { font-size: var(--czcionka-baza-telefon); }
  .naglowek-wnetrze { padding-inline: var(--odstep-5); }
  .rozmowa { padding-inline: var(--odstep-5); }
  .dymek { max-width: 92%; }
  /* The indicator's longest label must fit one line at 320 px (PR #33 review: it was cut
     to „To trwa dłużej niż zw…”): the full column, a tighter gap and inline padding. */
  .dymek.mysli { max-width: 100%; gap: var(--odstep-2); padding-inline: var(--odstep-3); }
  .wybory .opcja { flex: 1 1 auto; }
  .ekran { padding-inline: var(--odstep-5); }
  .wybory-start + .kompozytor { width: auto; max-width: none; margin-inline: calc(-1 * var(--odstep-5)); padding-inline: var(--odstep-5); }
  .wybory-akcje .btn { flex: 1 1 auto; }
  .terminy { grid-template-columns: repeat(2, 1fr); }
  .karta-akcje .btn { width: 100%; }
  /* The consent screen is one frame on a phone: the screen area itself, no card chrome. */
  .ekran .karta-zgody { padding: 0; background: transparent; border: 0; border-radius: 0; box-shadow: none; }
  .ekran .karta-zgody .karta-akcje {
    margin: var(--odstep-3) 0 calc(-1 * var(--odstep-3) - env(safe-area-inset-bottom));
    padding: var(--odstep-3) 0 calc(var(--odstep-3) + env(safe-area-inset-bottom));
    border-radius: 0;
  }
  /* All three boxes and „Dalej” in one view of a 390 × 664 panel (issue #79 M2: the
     third, required box sat below the fold behind the pinned „Dalej”): the consent
     screen takes the height it needs, its rows are tighter and their text smaller. */
  .ekran:has(.karta-zgody) { max-height: var(--zgody-wys-max); }
  .ekran .karta-zgody .zgoda { padding-block: var(--odstep-2); }
  .ekran .karta-zgody .zgoda-tekst { font-size: var(--rozmiar-s); }
  .ekran .karta-zgody .karta-opis { font-size: var(--rozmiar-s); }
  .ekran .karta-zgody .blad { font-size: var(--rozmiar-s); }
}

/* --- short screens (a height breakpoint, the same exception as above) -------------------
   The start screen scrolls as one page instead of squeezing the greeting into a small
   transcript window, so it opens on the headline (app.js scrolls it to the top). */
/* A short screen gives every line to the conversation: the AI note goes (the §4
   disclosure is in the greeting, and the site's panel header says „Asystent AI”). */
@media (max-height: 560px) {
  .stopka { display: none; }
}

@media (max-height: 700px) {
  body:has(.wybory-start) {
    height: auto;
    min-height: 100dvh;
    grid-template-columns: minmax(0, 1fr); /* no min-content overflow once it can scroll */
    overflow: visible;
  }
  body:has(.wybory-start) .rozmowa { overflow: visible; }
  body:has(.wybory-start) .ekran { max-height: none; overflow: visible; }
  /* the two quiet links stay on one line at 320 px: their own padding is the gap, and the
     row reaches into it so the text lines up with the rows above */
}

/* the composer's character cap, said aloud when reached (#53 m9) */
.limit-znakow {
  flex-basis: 100%;
  margin: var(--odstep-1) 0 0;
  font-size: var(--rozmiar-xs);
  color: var(--kolor-tekst-2);
}

/* A message on its way (issue #79: on a slow network it stayed greyed in the textarea
   with no bubble until the answer came); the server's own bubble replaces it. */
.dymek.wysylane { opacity: 0.6; }
