/* ==========================================================================
   KREATOR „Ask About a Filter" — warstwa mapująca Fluent Forms na nasz system

   Wariant hybrydowy z DEC-005: silnik wtyczki, front nasz. Ten plik jest
   tym „frontem". Nie stylizuje formularza od zera — TŁUMACZY nazwy klas
   Fluent Forms na decyzje, które już zapadły w prototypie statycznym
   (DEC-014 paleta, DEC-020 fundamenty, DEC-021 interakcje).

   ⚠️ ZASADA: nic tutaj nie wymyśla nowej wartości. Każdy kolor, odstęp
   i stopień pisma idzie z `01-tokens.css` prototypu. Jeśli czegoś w tokenach
   nie ma, to znak, że decyzja jeszcze nie zapadła — nie że trzeba wpisać
   liczbę na miejscu.

   ── DLACZEGO W OGÓLE PODMIENIAMY ARKUSZ WTYCZKI ─────────────────────────
   `fluent-forms-public.css` waży 43,1 KB i niesie w sobie cały wygląd
   domyślnego formularza: niebieski akcent przeglądarkowy, własne promienie,
   własną skalę pisma. Zostawienie go znaczy nadpisywanie cudzych reguł
   naszymi, czyli wojna specyficzności na każdym polu.

   ⛔ ALE: w tych 43 KB siedzą też reguły KONSTRUKCYJNE, bez których
   formularz przestaje działać, a nie tylko brzydko wygląda. Zmierzone
   18.08 przez wyłączenie arkusza na żywym formularzu: po jego zdjęciu
   na kroku 2 pokazało się WSZYSTKIE 13 pól wymiarowych zamiast dwóch.
   Dlatego sekcja „KONSTRUKCJA" niżej jest przepisana z arkusza wtyczki
   1:1 i NIE WOLNO jej zmieniać razem z wyglądem.
   ========================================================================== */

/* Tokeny i fonty idą teraz z theme.json (patrz docs/token-map.tsv) — te dwa
   importy z prototypu statycznego zniknęły przy przenosinach do motywu.    */

/* ==========================================================================
   1. KONSTRUKCJA — przepisane z arkusza wtyczki, nie zmieniać przy stylowaniu
   ========================================================================== */

/* Ukrywanie pól warunkowych. To jest TA reguła: bez niej kreator pokazuje
   wszystkie 13 pól wymiarowych naraz (zmierzone).                          */
.fluentform .has-conditions { display: none; }

/* Mechanizm suwaka kroków. Krok nieaktywny nie znika przez `display`,
   tylko zwija się do 1 px i chowa przepełnienie — dzięki temu przejście
   da się animować. Zdjęcie tego psuje kroki, nie ich wygląd.              */
.fluentform .ff-step-container { overflow: hidden; }
.fluentform .ff-step-body { position: relative; top: 0; left: 0; }
.fluentform-step {
  float: left;
  height: 1px;
  overflow-x: hidden;
  padding: 3px;          /* miejsce na obwódkę fokusu — zostaje z arkusza wtyczki */
  box-sizing: border-box; /* ⚠️ nasz dodatek: bez tego krok jest o 6 px szerszy
                             niż pojemnik i `overflow:hidden` ścina prawą kolumnę
                             kafelków (zmierzone: 710 px w 704 px)               */
}
.fluentform-step.active { height: auto; width: 100%; }

.fluentform .ff-el-group::after,
.fluentform .ff-step-body::after { content: ""; display: table; clear: both; }

/* Element ukryty wzrokowo, ale obecny dla czytnika i klawiatury. Przepisane
   1:1 — bez tego natywny `input[type=file]` wychodzi z ukrycia i obok naszej
   strefy zrzutu staje przeglądarkowe „Choose files / No file chosen".     */
.fluentform .ff-screen-reader-element,
.fluentform .ff_screen_reader_title {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  min-height: 0 !important;   /* nasze `.ff-el-form-control` daje 44 px, a `min-height`
                                 bije `height` niezależnie od `!important` — to inna
                                 właściwość, nie ta sama z wyższym priorytetem      */
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  word-wrap: normal !important;
}

/* ⛔ `.ff_excluded` zostawiamy nietknięte. Auto-pomijanie pustych kroków
   czyta tę klasę z DOM, nie z konfiguracji (SPIKE §4c) — zmiana jej
   znaczenia łamie logikę, nie dotykając ani linii JS.                     */

/* ==========================================================================
   2. RAMA FORMULARZA
   ========================================================================== */

.fluentform {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--fs-body);
  line-height: var(--wp--custom--line-height--body);
  color: var(--wp--preset--color--text);
  max-width: var(--wp--style--global--content-size);
  margin-inline: auto;
}

.fluentform fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }

/* Odstęp między polami z rytmu 4 px (DEC-020 b), nie z domyślnych 15 px
   wtyczki, które nie należą do żadnej skali.                              */
.fluentform .ff-el-group { margin-bottom: var(--wp--preset--spacing--space-6); }
.fluentform .ff-el-group:last-child { margin-bottom: 0; }

/* ==========================================================================
   3. WSKAŹNIK KROKÓW — TEN SAM KOMPONENT CO „How to Order" NA STRONIE GŁÓWNEJ

   ⭐ PRZEPISANE OD ZERA 19.08 (tura siódma). Poprzednia wersja była własnym
   pomysłem: kropka 14 px i podpis pisany krojem DANYCH, wersalikami, 12 px,
   z rozstrzeleniem. To jest w naszym systemie styl ETYKIETY NADRZĘDNEJ,
   a nie tytułu — więc wskaźnik kroków wyglądał jak trzy podpisy techniczne
   pod kropkami i był po prostu nieczytelny. Do tego krok bieżący dostawał
   płaską obwódkę w tonie akcentu, która czytała się jak poświata, czyli
   jak rzecz spoza systemu (DEC-020 d: zero cieni, warstwy budujemy
   podłożem i linią 1 px).

   Ta wersja nie wymyśla niczego. Jest odwzorowaniem `components/steps.css`
   z prototypu statycznego, czyli sekcji „How to Order" ze strony głównej:

     • węzłem jest IKONA 28 px, nie kropka,
     • podpis idzie krojem NAGŁÓWKOWYM (Archivo 600), nie danymi,
     • łącznik należy do kroku, nie do całego rzędu, więc oś kończy się
       na ostatnim węźle i nie zostawia ogona w pustce,
     • ikona i podpis mają ZAWSZE ten sam kolor (`currentColor`), bo to
       jeden obiekt, a nie ikonka obok napisu.

   Cztery ikony są dosłownie tymi samymi, których serwis używa do tych samych
   pojęć: `i-mounting`, `i-ruler`, `i-media`, `mail` (Iconoir, kreska 1,5 — DEC-019).
   ⚠️ Tu siedzą jako maski w `data:`, bo formularz renderuje wtyczka i nie
   da się wstawić `<use>` w jej `<li>`. W produkcji to będzie `<use>` ze
   sprite'u motywu, dokładnie jak na stronie głównej.
   ========================================================================== */

.fluentform .ff-step-header { margin-bottom: var(--wp--preset--spacing--space-7); }

.fluentform .ff-step-titles {
  display: flex;
  gap: var(--wp--preset--spacing--space-5);
  list-style: none;
  margin: 0;
  padding: 0;
}

.fluentform .ff-step-titles li {
  flex: 1 1 0;
  position: relative;
  min-width: 0;

  /* Miejsce na węzeł stojący NAD podpisem — ten sam zabieg co
     `padding-top: calc(var(--wp--custom--icon--lg) + var(--wp--preset--spacing--space-4))` w `.steps`.      */
  padding-top: calc(var(--wp--custom--icon--lg) + var(--wp--preset--spacing--space-3));

  font-family: var(--wp--preset--font-family--heading);
  font-weight: 600;
  font-size: var(--wp--preset--font-size--fs-small);
  line-height: var(--wp--custom--line-height--3);
  color: var(--wp--preset--color--text-muted);
  transition: color var(--wp--custom--motion--hover) var(--wp--custom--motion--ease);
}

@media (min-width: 48rem) {
  .fluentform .ff-step-titles li { font-size: var(--wp--preset--font-size--fs-body); }
}

/* ŁĄCZNIK. Należy do kroku, nie do rzędu: biegnie od prawej krawędzi
   własnego węzła do węzła następnego, więc ostatnia pozycja nie rysuje go
   wcale i oś kończy się na ostatnim kroku. Odstęp po obu stronach jest
   równy (12 px), bo `--space-5` minus `--space-3` daje dokładnie tyle
   z drugiej strony — ten sam rachunek co w `components/steps.css`.

   Odcinek do kroku PRZEBYTEGO jest w akcencie: oś mówi, ile drogi za tobą.  */
.fluentform .ff-step-titles li::before {
  content: "";
  position: absolute;
  top: calc(var(--wp--custom--icon--lg) / 2);
  left: calc(var(--wp--custom--icon--lg) + var(--wp--preset--spacing--space-3));
  right: calc((var(--wp--preset--spacing--space-5) - var(--wp--preset--spacing--space-3)) * -1);
  height: var(--wp--custom--border--hair);
  background: var(--wp--preset--color--border-strong);
}
.fluentform .ff-step-titles li.ff_completed::before { background: var(--wp--preset--color--accent); }
.fluentform .ff-step-titles li:last-child::before { display: none; }

/* WĘZEŁ = ikona. Maska plus `currentColor` znaczy, że ikona nie ma własnego
   koloru: bierze go z pozycji, więc stan ustawia się w jednym miejscu.     */
.fluentform .ff-step-titles li::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: var(--wp--custom--icon--lg);
  height: var(--wp--custom--icon--lg);
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-size: contain;
          mask-size: contain;
}

.fluentform .ff-step-titles li[data-step-number="0"]::after {
  -webkit-mask-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'><path%20d='M14%2020.4V14.6C14%2014.2686%2014.2686%2014%2014.6%2014H20.4C20.7314%2014%2021%2014.2686%2021%2014.6V20.4C21%2020.7314%2020.7314%2021%2020.4%2021H14.6C14.2686%2021%2014%2020.7314%2014%2020.4Z'%20stroke='%23000'/>%20<path%20d='M3%2020.4V14.6C3%2014.2686%203.26863%2014%203.6%2014H9.4C9.73137%2014%2010%2014.2686%2010%2014.6V20.4C10%2020.7314%209.73137%2021%209.4%2021H3.6C3.26863%2021%203%2020.7314%203%2020.4Z'%20stroke='%23000'/>%20<path%20d='M14%209.4V3.6C14%203.26863%2014.2686%203%2014.6%203H20.4C20.7314%203%2021%203.26863%2021%203.6V9.4C21%209.73137%2020.7314%2010%2020.4%2010H14.6C14.2686%2010%2014%209.73137%2014%209.4Z'%20stroke='%23000'/>%20<path%20d='M3%209.4V3.6C3%203.26863%203.26863%203%203.6%203H9.4C9.73137%203%2010%203.26863%2010%203.6V9.4C10%209.73137%209.73137%2010%209.4%2010H3.6C3.26863%2010%203%209.73137%203%209.4Z'%20stroke='%23000'/></svg>");
          mask-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'><path%20d='M14%2020.4V14.6C14%2014.2686%2014.2686%2014%2014.6%2014H20.4C20.7314%2014%2021%2014.2686%2021%2014.6V20.4C21%2020.7314%2020.7314%2021%2020.4%2021H14.6C14.2686%2021%2014%2020.7314%2014%2020.4Z'%20stroke='%23000'/>%20<path%20d='M3%2020.4V14.6C3%2014.2686%203.26863%2014%203.6%2014H9.4C9.73137%2014%2010%2014.2686%2010%2014.6V20.4C10%2020.7314%209.73137%2021%209.4%2021H3.6C3.26863%2021%203%2020.7314%203%2020.4Z'%20stroke='%23000'/>%20<path%20d='M14%209.4V3.6C14%203.26863%2014.2686%203%2014.6%203H20.4C20.7314%203%2021%203.26863%2021%203.6V9.4C21%209.73137%2020.7314%2010%2020.4%2010H14.6C14.2686%2010%2014%209.73137%2014%209.4Z'%20stroke='%23000'/>%20<path%20d='M3%209.4V3.6C3%203.26863%203.26863%203%203.6%203H9.4C9.73137%203%2010%203.26863%2010%203.6V9.4C10%209.73137%209.73137%2010%209.4%2010H3.6C3.26863%2010%203%209.73137%203%209.4Z'%20stroke='%23000'/></svg>");
}
.fluentform .ff-step-titles li[data-step-number="1"]::after {
  -webkit-mask-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'><path%20d='M16%207V2.6C16%202.26863%2015.7314%202%2015.4%202H8.6C8.26863%202%208%202.26863%208%202.6V21.4C8%2021.7314%208.26863%2022%208.6%2022H15.4C15.7314%2022%2016%2021.7314%2016%2021.4V17M16%207H13M16%207V12M16%2012H13M16%2012V17M16%2017H13'%20stroke='%23000'%20stroke-linecap='round'%20stroke-linejoin='round'/></svg>");
          mask-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'><path%20d='M16%207V2.6C16%202.26863%2015.7314%202%2015.4%202H8.6C8.26863%202%208%202.26863%208%202.6V21.4C8%2021.7314%208.26863%2022%208.6%2022H15.4C15.7314%2022%2016%2021.7314%2016%2021.4V17M16%207H13M16%207V12M16%2012H13M16%2012V17M16%2017H13'%20stroke='%23000'%20stroke-linecap='round'%20stroke-linejoin='round'/></svg>");
}
.fluentform .ff-step-titles li[data-step-number="2"]::after {
  -webkit-mask-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'><path%20d='M3.99961%203H19.9997C20.552%203%2020.9997%203.44764%2020.9993%204C20.9982%205.61151%2020.9899%206.81544%2020.6928%207.7716C20.3872%208.75521%2019.7833%209.54151%2018.5754%2010.7494L15.4442%2013.8806C15.1591%2014.1657%2015%2014.5528%2015%2014.9558V17.7638C15%2018.5218%2014.5719%2019.2148%2013.8938%2019.5538L11.8938%2020.5538C10.5645%2021.2185%209%2020.2521%209%2018.7638V14.9558C9%2014.5528%208.84095%2014.1657%208.55584%2013.8806L5.42462%2010.7494C4.21671%209.54151%203.61276%208.75521%203.30722%207.7716C3.01011%206.81544%203.00178%205.61151%203.00069%204C3.00032%203.44764%203.44733%203%203.99961%203Z'%20stroke='%23000'%20stroke-linecap='round'%20stroke-linejoin='round'/></svg>");
          mask-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'><path%20d='M3.99961%203H19.9997C20.552%203%2020.9997%203.44764%2020.9993%204C20.9982%205.61151%2020.9899%206.81544%2020.6928%207.7716C20.3872%208.75521%2019.7833%209.54151%2018.5754%2010.7494L15.4442%2013.8806C15.1591%2014.1657%2015%2014.5528%2015%2014.9558V17.7638C15%2018.5218%2014.5719%2019.2148%2013.8938%2019.5538L11.8938%2020.5538C10.5645%2021.2185%209%2020.2521%209%2018.7638V14.9558C9%2014.5528%208.84095%2014.1657%208.55584%2013.8806L5.42462%2010.7494C4.21671%209.54151%203.61276%208.75521%203.30722%207.7716C3.01011%206.81544%203.00178%205.61151%203.00069%204C3.00032%203.44764%203.44733%203%203.99961%203Z'%20stroke='%23000'%20stroke-linecap='round'%20stroke-linejoin='round'/></svg>");
}

/* Krok 4 (Contact, DEC-059): ta sama ikona koperty, której serwis używa
   przy adresie e-mail (`assets/icons/mail.svg`, Iconoir).                */
.fluentform .ff-step-titles li[data-step-number="3"]::after {
  -webkit-mask-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'><path%20d='M7%209L12%2012.5L17%209'/><path%20d='M2%2017V7C2%205.89543%202.89543%205%204%205H20C21.1046%205%2022%205.89543%2022%207V17C22%2018.1046%2021.1046%2019%2020%2019H4C2.89543%2019%202%2018.1046%202%2017Z'/></svg>");
          mask-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'><path%20d='M7%209L12%2012.5L17%209'/><path%20d='M2%2017V7C2%205.89543%202.89543%205%204%205H20C21.1046%205%2022%205.89543%2022%207V17C22%2018.1046%2021.1046%2019%2020%2019H4C2.89543%2019%202%2018.1046%202%2017Z'/></svg>");
}

/* Trzy stany, jeden token na stan — ikona idzie za podpisem sama.
   Krok przebyty jest w pełnym kolorze tekstu, bo to miejsce, do którego
   się wraca; przyszły w tekście pomocniczym; bieżący w akcencie.          */
.fluentform .ff-step-titles li.ff_completed { color: var(--wp--preset--color--text); }
.fluentform .ff-step-titles li.ff_active { color: var(--wp--preset--color--accent); }

/* WĄSKI EKRAN: CZTERY KROKI, JEDEN PODPIS (DEC-060).
   Poniżej 30rem cztery tytuły obok siebie się nie mieszczą (przy 320 px
   komórka 58 px, „Dimensions” 77 px) i rozpychały formularz poza ekran.
   Rząd zostaje samymi węzłami z osią, a pod nim jeden podpis bieżącego
   kroku, który składa creator-matrix.js. Tytuły chowamy tylko wizualnie:
   czytnik ekranu nadal czyta wszystkie cztery, a podpis ma `aria-hidden`.
   Granica 30rem: przy niej komórka ma 90 px, czyli najdłuższy tytuł mieści
   się z zapasem.                                                          */
.fluentform .ef-steps-caption { display: none; }

@media (width < 30rem) {
  .fluentform .ff-step-titles li { padding-top: var(--wp--custom--icon--lg); }

  .fluentform .ff-step-titles .ff-step-title-text {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .fluentform .ef-steps-caption {
    display: block;
    margin: var(--wp--preset--spacing--space-3) 0 0;
    font-family: var(--wp--preset--font-family--heading);
    font-weight: 600;
    font-size: var(--wp--preset--font-size--fs-small);
    line-height: var(--wp--custom--line-height--3);
    color: var(--wp--preset--color--accent);
  }

  .fluentform .ef-steps-caption__count { color: var(--wp--preset--color--text-muted); }
}

/* Tytuły są klikalne z renderera (`ff-step-titles--clickable`) i to ZOSTAJE:
   zmierzone 19.08, skok do przodu nie omija walidacji (DEC-053 a). Skoro
   zostaje, musi wyglądać na klikalne — kursor, najazd i widoczny fokus.
   Bez ostatniego pozycja z `role="button"` i `tabindex="0"` była celem
   klawiatury bez żadnego śladu na ekranie.                                 */
.fluentform .ff-step-titles--clickable li { cursor: pointer; }
.fluentform .ff-step-titles--clickable li:hover { color: var(--wp--preset--color--accent-hover); }

.fluentform .ff-step-titles--clickable li:focus-visible {
  outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
  outline-offset: var(--wp--custom--focus--offset);
}

/* Pole trafienia 44 px (DEC-021 c) — tytuł kroku jest realnym celem. */
.fluentform .ff-step-titles li::before,
.fluentform .ff-step-titles li::after { pointer-events: none; }
.fluentform .ff-step-titles--clickable li { min-height: var(--wp--custom--hit--min); }

/* ==========================================================================
   4. ETYKIETY, PODPOWIEDZI, BŁĘDY
   ========================================================================== */

/* Etykieta i ikona podpowiedzi w jednym wierszu. Renderer stawia je jako
   dwa bloki, więc ikona spadała pod etykietę i wyglądała jak osierocony
   znaczek nad polem.                                                       */
/* ⚠️ `center`, nie `baseline`, a odstęp pod etykietą należy do POJEMNIKA,
   nie do samej etykiety. Zmierzone 19.08: przy `baseline` i marginesie na
   wewnętrznym `label` pojemnik z ikoną podpowiedzi miał **34 px**, a bez
   ikony **29 px** — czyli pole pod etykietą z podpowiedzią startowało 5 px
   niżej niż pole obok i rytm formularza rozjeżdżał się bez powodu.        */
.fluentform .ff-el-input--label {
  display: flex;
  align-items: center;
  gap: var(--wp--preset--spacing--space-2);
  margin-bottom: var(--wp--preset--spacing--space-2);
}

.fluentform .ff-el-tooltip { color: var(--wp--preset--color--text-muted); }

.fluentform .ff-el-input--label label {
  display: inline-block;
  margin-bottom: 0;
  font-family: var(--wp--preset--font-family--heading);
  font-size: var(--wp--preset--font-size--fs-small);
  font-weight: 600;
  line-height: var(--wp--custom--line-height--small);
  color: var(--wp--preset--color--text);
}

.fluentform .ff-el-input--label.ff-el-is-required label::after {
  content: "";           /* gwiazdki nie ma — patrz components/form.css */
}

.fluentform .ff-el-help-message {
  margin-top: var(--wp--preset--spacing--space-2);
  font-size: var(--wp--preset--font-size--fs-small);
  line-height: var(--wp--custom--line-height--small);
  color: var(--wp--preset--color--text-muted);
}

/* Błąd niesie kolor i tekst, nigdy sam kolor. */
.fluentform .error.text-danger {
  margin-top: var(--wp--preset--spacing--space-2);
  font-size: var(--wp--preset--font-size--fs-small);
  line-height: var(--wp--custom--line-height--small);
  color: var(--wp--preset--color--error);
}

.fluentform .ff-el-is-error .ff-el-form-control { border-color: var(--wp--preset--color--error); }

/* ==========================================================================
   5. KONTROLKI — 1:1 z `components/form.css` prototypu
   ========================================================================== */

/* ⚠️ Bez `:not(.ff-screen-reader-element)`, choć kusi. Taki zapis dokłada
   trzecią klasę do specyficzności i ta reguła zaczyna WYGRYWAĆ z regułą
   `select.ff-el-form-control` niżej (2 klasy + element) — skutek zmierzony:
   strzałka pola wyboru przestaje mieć `no-repeat` i kafelkuje się przez całe
   pole. Ukryciem kontrolki czytnikowej zajmuje się reguła w sekcji 1,
   która ma `!important` dokładnie po to.                                   */
.fluentform .ff-el-form-control {
  width: 100%;

  /* ⚠️ `box-sizing` MUSI tu stać jawnie. Bez niego pole wyboru liczyło
     `min-height` od pudełka zewnętrznego, a pole tekstowe od zawartości —
     zmierzone 19.08: **lista 54 px, pole e-mail i liczba 70 px**, czyli
     16 px różnicy między sąsiednimi polami tego samego formularza.
     To nie jest ustawienie „na wszelki wypadek", tylko poprawka usterki. */
  box-sizing: border-box;
  min-height: var(--wp--custom--hit--min);
  padding: var(--wp--preset--spacing--space-3) var(--wp--preset--spacing--space-4);

  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--fs-body);
  line-height: var(--wp--custom--line-height--body);
  color: var(--wp--preset--color--text);

  background: var(--wp--preset--color--page);
  border: var(--wp--custom--border--hair) solid var(--wp--preset--color--border-strong);
  border-radius: var(--wp--custom--radius);
  box-shadow: none;

  transition: border-color var(--wp--custom--motion--hover) var(--wp--custom--motion--ease);
}

/* Po zdjęciu `appearance` pole wyboru wygląda jak pole tekstowe, więc
   strzałkę trzeba narysować. Kreska 1,5 i kąt 90° — ten sam język, co
   rysunek techniczny (DEC-020 g), nie trójkącik z systemu operacyjnego.  */
.fluentform select.ff-el-form-control {
  appearance: none;
  padding-right: var(--wp--preset--spacing--space-8);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%23575E62' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--wp--preset--spacing--space-4) center;
}

.fluentform select.ff-el-form-control:hover,
.fluentform select.ff-el-form-control:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%230A6E78' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
}

.fluentform .ff-el-form-control:hover { border-color: var(--wp--preset--color--accent); }

.fluentform .ff-el-form-control:focus,
.fluentform .ff-el-form-control:focus-visible {
  outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
  outline-offset: var(--wp--custom--focus--offset);
  border-color: var(--wp--preset--color--accent);
}

.fluentform .ff-el-form-control::placeholder { color: var(--wp--preset--color--disabled-text); }

/* ==========================================================================
   5b. MACIERZ DOBORU — dwie listy zamiast dziesięciu pól warunkowych

   Pole `chained_select` zasilane arkuszem klienta (DEC-050). Renderer
   wypuszcza tyle list, ile CSV ma kolumn, każdą w `.ff-t-cell` wewnątrz
   `.ff-t-container`. Domyślny arkusz wtyczki układał to we `flex` — my
   go zdejmujemy (DEC-047), więc układ trzeba napisać, inaczej listy stoją
   jedna pod drugą jak zwykłe pola i gubi się to, że opisują JEDEN wymiar.
   ========================================================================== */

/* `auto-fit`, a nie `1fr 1fr`, i to nie jest wybór stylistyczny: przy stałych
   dwóch kolumnach lista OD stoi na POŁOWIE szerokości wtedy, gdy druga jest
   ukryta (Jet/Lug i Steck nie mają ID w arkuszu) — czyli w jedynym miejscu
   kreatora, gdzie pole nagle jest węższe od sąsiadów bez żadnego powodu.
   `auto-fit` zwija pustą kolumnę i pole zajmuje wiersz. Przy okazji znika
   potrzeba punktu łamania: poniżej ok. 2 × 14 rem układ sam schodzi do jednej
   kolumny, a to jest dokładnie ta szerokość, przy której etykieta
   „Outer diameter (OD, mm)" przestaje mieścić się w jednym wierszu.       */
/* Pojemnik pola Chained Select NIE jest `.ff-el-group`, więc nie dostaje
   odstępu grupy z sekcji 2 — a stoi w kroku jako pełnoprawne pole i musi
   trzymać ten sam rytm co reszta. Bez tego wszystko, co po nim następuje,
   przykleja się do listy średnic.                                          */
.fluentform .ff-chained-select-field-wrapper { margin-bottom: var(--wp--preset--spacing--space-6); }

/* Grupy WEWNĘTRZNE macierzy (jedna na listę) siedzą w komórkach siatki,
   więc ich własny odstęp grupy nic nie porządkuje, a potrafi się zebrać
   w pustą przestrzeń pod wierszem.                                         */
.fluentform .ef-matrix .ff-el-group { margin-bottom: 0; }

.fluentform .ef-matrix .ff-t-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));

  /* Dwie różne wartości i to jest celowe: w poziomie 24 px, bo listy opisują
     JEDEN wymiar i mają się czytać jako para; w pionie odstęp grupy (32 px),
     bo po zejściu do jednej kolumny (telefon) stoją już jak zwykłe pola
     jedno pod drugim i muszą trzymać rytm formularza. Zmierzone przed
     poprawką: 24 px w pionie przy 32 px między pozostałymi polami.        */
  gap: var(--wp--preset--spacing--space-6) var(--wp--preset--spacing--space-5);
}

/* Pierwsza lista to KLUCZ ZŁĄCZENIA, nie wybór użytkownika: wartość wpisuje
   w nią mostek z kafelka (`js/ef-matrix.js`). Widoczna byłaby prośbą
   o wskazanie mocowania drugi raz, w innej formie, na następnym kroku.    */
.fluentform .ef-matrix .ef-matrix__driver { display: none; }

/* Lista, dla której arkusz nie podaje wartości (Jet/Lug i Steck nie mają ID),
   znika razem z komórką. Ukrycie robi para klas wtyczki na `.ff-el-group`
   — patrz komentarz w `ef-matrix.js` — a to tutaj domyka lukę w siatce.   */
.fluentform .ef-matrix .ff-t-cell:has(> .ff-el-group.ff_excluded) { display: none; }

/* Stan wyłączony ma własne tokeny i NIGDY nie jest robiony przezroczystością
   (DEC-021 d). Lista ID stoi wyłączona, dopóki nie padnie średnica
   zewnętrzna — i mówi o tym wprost, bo sam szary prostokąt czyta się jak
   usterka, a nie jak kolejność.                                           */
.fluentform .ef-matrix select:disabled {
  background-color: var(--wp--preset--color--disabled-bg);
  color: var(--wp--preset--color--disabled-text);
  border-color: var(--wp--preset--color--border);
  cursor: not-allowed;
}

.fluentform .ef-matrix select:disabled:hover { border-color: var(--wp--preset--color--border); }

.ef-matrix__hint {
  margin: var(--wp--preset--spacing--space-2) 0 0;
  font-size: var(--wp--preset--font-size--fs-small);
  line-height: var(--wp--custom--line-height--small);
  color: var(--wp--preset--color--text-muted);
}

/* ==========================================================================
   5c. PRZEŁĄCZNIK „NIE WIEM" — wyjście awaryjne przy polu

   DEC-021 (g) postawiło zasadę przy kafelkach: **nieumiejętność wyboru jest
   poprawną odpowiedzią i nie wyrzuca człowieka ze ścieżki.** Do 19.08 stała
   ona wyłącznie na kroku 1, więc kto nie znał wysokości, nie miał jak wysłać
   zapytania. Ten przełącznik przenosi tę samą zasadę na pojedyncze pole.

   ⛔ Nie jest ozdobiony ani schowany. Ma wyglądać na równorzędną odpowiedź,
   a nie na rezygnację — stąd zwykły krój tekstu, nie szarość „drobnego druku".
   ========================================================================== */

/* ⭐ POPRAWKA 20.08 — ODSTĘP NAD PRZEŁĄCZNIKIEM PRZESTAJE BYĆ UJEMNY.

   --- Historia, bo to druga poprawka tego samego miejsca

   19.08 stało tu `margin-top: -12px`, czyli ślepe „przyciągnij bliżej”.
   Zastąpił je `calc(var(--wp--preset--spacing--space-3) - var(--wp--preset--spacing--space-6))`, czyli **‒20 px** —
   liczba wyprowadzona z tokenów, ale nadal UJEMNA. Zamysł był taki, że
   ujemny margines skasuje 32 px odstępu grupy stojącej WYŻEJ i zostanie
   z tego 12 px.

   --- Dlaczego to było złe i co dokładnie się psuło

   ⚠️ Ujemny margines kompensuje odstęp SĄSIADA. Kiedy sąsiad znika
   (`display: none`), nie ma czego kompensować i przechyleń idzie w górę
   o pełne 20 px. A pierwszy przełącznik na kroku 2 stoi dokładnie pod polem,
   które jego własne zaznaczenie UKRYWA — czyli sam sobie zabierał sąsiada.

   Zmierzone 20.08: po zaznaczeniu „I do not know the diameters yet”
   przełącznik stawał **17 px POWYŻEJ górnej krawędzi własnego kroku**,
   a pojemnik kroków ma `overflow: hidden` (mechanizm suwaka, sekcja 1) —
   więc kwadracik i tekst były ścięte w połowie wysokości. Drugi przełącznik
   (wysokość) wyglądał poprawnie, bo nad nim zostaje widoczne pole kołnierza,
   stąd objaw „psuje się tylko ten pierwszy z góry”.

   --- Jak jest teraz

   Odstęp idzie **z jednego kierunku i jest dodatni**: przełącznik ma własne
   12 px od góry, a element bezpośrednio nad nim oddaje swój odstęp grupy.
   Kiedy ten element zniknie, jego margines i tak nie liczy się do układu,
   więc przełącznik zostaje 12 px pod tym, co akurat stoi wyżej, i **nigdy
   nie wychodzi poza swój krok**.

   Reguła ogólna do zapamiętania: **odstęp między dwoma elementami ustawia
   się na tym z nich, który na pewno jest widoczny.** Tutaj widoczny zawsze
   jest przełącznik — pole obok bywa ukryte, on nie.                        */
.fluentform .ef-unknown { margin-top: var(--wp--preset--spacing--space-3); }

/* Element nad przełącznikiem oddaje swój odstęp grupy, żeby nie sumował się
   z powyższymi 12 px.

   ⚠️ „Nad” nie znaczy tu „poprzedni w DOM”, i to jest cała trudność tej
   reguły. Pól wysokości jest w formularzu kilka — po jednym na zakres
   (`height_300` dla sześciu grup, `height_200` dla RD) — a widoczne jest
   zawsze jedno. Bezpośrednim sąsiadem przełącznika bywa więc wariant
   UKRYTY, przez który `+` nie sięga do pola realnie stojącego wyżej.
   Zmierzone przed tą poprawką: przy średnicach odstęp wychodził 12 px,
   a przy wysokości 32 px, bo między polem a przełącznikiem stał ukryty
   `height_200`.

   Stąd trzy dodatkowe warianty przeskakujące ogniwa ukryte warunkowo:
   wtyczka trzyma widoczność na klasie `ff_cond_v`, więc `has-conditions`
   BEZ niej to dokładnie „pole schowane przez warunek”. Dwa ogniwa
   z zapasem — dziś potrzebne jest jedno, ósmy typ filtra może dołożyć
   drugie, a każdy kolejny wariant wysokości nadal nie wymaga dotykania
   samego formularza (DEC-051 d).                                           */
.fluentform .ff-el-group:has(+ .ef-unknown),
.fluentform .ff-chained-select-field-wrapper:has(+ .ef-unknown),
.fluentform .ff-el-group:has(+ .has-conditions:not(.ff_cond_v) + .ef-unknown),
.fluentform .ff-chained-select-field-wrapper:has(+ .has-conditions:not(.ff_cond_v) + .ef-unknown),
.fluentform .ff-el-group:has(+ .has-conditions:not(.ff_cond_v) + .has-conditions:not(.ff_cond_v) + .ef-unknown) {
  margin-bottom: 0;
}

.fluentform .ef-unknown .ff-el-form-check { position: relative; }

.fluentform .ef-unknown .ff-el-form-check-label {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--wp--preset--spacing--space-3);
  font-size: var(--wp--preset--font-size--fs-small);
  line-height: var(--wp--custom--line-height--small);
  color: var(--wp--preset--color--text);
  cursor: pointer;
}

/* Pole trafienia 44 px NIEWIDZIALNYM `::after`, nie `min-height` (DEC-021 c
   mówi o tym wprost przy przycisku 32 px).

   ⚠️ Poprzednio stało tu `min-height: 44px`, przez co etykieta wysoka na
   21 px zajmowała 44 px i zostawiała **13 px pustego nad kwadracikiem**.
   Ten pusty pas doliczał się do każdego odstępu wokół przełącznika, więc
   sąsiedztwo z polem wyglądało inaczej, niż mówiły liczby w kodzie — i to
   jest powód, dla którego margines nad przełącznikiem był wcześniej
   dobierany na oko.                                                        */
.fluentform .ef-unknown .ff-el-form-check-label::after {
  content: "";
  position: absolute;
  inset: calc((var(--wp--custom--hit--min) - 1.3125rem) / -2) calc(-1 * var(--wp--preset--spacing--space-2));
}

.fluentform .ef-unknown .ff-el-form-check-input {
  flex: 0 0 auto;
  width: 1.125rem;
  height: 1.125rem;
  margin: 0;
  accent-color: var(--wp--preset--color--accent);
  cursor: pointer;
}

.fluentform .ef-unknown .ff-el-form-check-input:focus-visible {
  outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
  outline-offset: var(--wp--custom--focus--offset);
}

/* Zaznaczone „nie wiem" jest STANEM, nie kliknięciem w przeszłości —
   pole obok właśnie zniknęło, więc etykieta musi to unieść wzrokowo.    */
.fluentform .ef-unknown .ff-el-form-check-input:checked + span,
.fluentform .ef-unknown .ff-el-form-check-input:checked ~ span {
  color: var(--wp--preset--color--accent);
}

/* ==========================================================================
   6. KAFELKI MOCOWANIA — mapa na `components/mount-picker.css`

   Siedem grup różni się WYŁĄCZNIE geometrią kołnierza, więc wybór idzie
   obrazem, nie nazwą: odbiorca z Niemiec nie wie, co znaczy „STECK",
   ale rozpozna kołnierz, który trzyma w ręku.
   ========================================================================== */

/* ⭐ POPRAWKA 19.08 — ODSTĘP. Było 12 px przy obrysie 1 px na każdym kafelku
   i przy zdjęciu wciętym o kolejne 8 px. Efekt: dwie linie pionowe biegnące
   przez całą siatkę w odległości 12 px od siebie, czyli obraz TABELI, a nie
   ośmiu osobnych rzeczy do wyboru. Odstęp musi być wyraźnie większy niż
   grubość obrysu razy kilka, inaczej sąsiadujące krawędzie czytają się
   jak jedna linia podziału kolumn.                                         */
.fluentform .ff_el_checkable_photo_holders {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--wp--preset--spacing--space-4);
}

@media (min-width: 30rem) { .fluentform .ff_el_checkable_photo_holders { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 48rem) {
  .fluentform .ff_el_checkable_photo_holders {
    grid-template-columns: repeat(4, 1fr);
    gap: var(--wp--preset--spacing--space-5);
  }
}

/* ⭐ POPRAWKA 19.08 — KAFELEK JEST KARTĄ, NIE KOMÓRKĄ TABELI.

   Było: obrys kafelka, wewnątrz 8 px marginesu, wewnątrz tego zdjęcie
   z własnym tłem. Czyli pudełko w pudełku, powtórzone osiem razy w równym
   rastrze — a to jest dokładnie rysunek tabeli. Podpis wisiał przy tym
   POD ramką zdjęcia i wyglądał jak wiersz nagłówkowy pod kolumną.

   Jest: zdjęcie dochodzi do krawędzi kafelka, a podpis siedzi w jego
   stopce. Kafelek ma jedną krawędź zamiast dwóch i czyta się jako jeden
   przedmiot.

   ⚠️ Dlaczego `border` + `outline`, a nie `box-shadow: inset` jak wcześniej:
   cień wewnętrzny jest rysowany POD elementami potomnymi, więc przy zdjęciu
   dochodzącym do krawędzi po prostu przestaje być widoczny. `outline` jest
   rysowany NAD potomkami i przy ujemnym `outline-offset` nie przesuwa
   układu ani o piksel — czyli spełnia to samo, co DEC-021 (f) wymagało
   od `inset`.                                                              */
.fluentform .ff-el-image-holder {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  height: 100%;
  padding: 0;
  overflow: hidden;
  background: var(--wp--preset--color--page);

  border: var(--wp--custom--border--hair) solid var(--wp--preset--color--border);
  border-radius: var(--wp--custom--radius);
  cursor: pointer;
  transition: border-color var(--wp--custom--motion--hover) var(--wp--custom--motion--ease),
              background var(--wp--custom--motion--hover) var(--wp--custom--motion--ease);
}

.fluentform .ff-el-image-holder:hover { border-color: var(--wp--preset--color--accent); }

/* Kafelek „I am not sure — advise me" nie ma i nie będzie miał zdjęcia,
   bo nie jest typem filtra, tylko wyjściem awaryjnym (DEC-021 g). Renderer
   i tak wstawia mu `label` ze **stylem `background-image: url()`** — pustym,
   ale obecnym, więc rozpoznajemy go po tym literale, nie po braku atrybutu.

   ⚠️ POPRAWKA 19.08. Wcześniej zwijaliśmy mu kadr i wyśrodkowywaliśmy
   etykietę w pionie. Zmierzone i obejrzane: kafelek stawał się **pustym
   polem z tekstem w środku**, czyli dziurą w siatce ośmiu zdjęć, a jego
   podpis stał 60 px wyżej niż podpisy sąsiadów.

   Teraz kadr ZOSTAJE i dostaje **siatkę arkusza rysunkowego** — to samo
   podłoże, którym serwis mówi „tu byłby rysunek" (DEC-041, DEC-043) — plus
   znak zapytania. Kafelek trzyma więc rytm siatki, a nadal nie udaje zdjęcia
   wyrobu. Kropkowany obrys zostaje, bo mówi „to nie jest typ filtra" tym
   samym językiem, co linia przerywana na rysunku (DEC-020 g).             */
.fluentform .ff-el-image-holder .ff-el-image-input-src[style*="url()"] {
  position: relative;
  background-color: var(--wp--preset--color--page);
  background-image:
    repeating-linear-gradient(to right,  var(--wp--preset--color--grid) 0 1px, transparent 1px var(--wp--custom--grid--step)),
    repeating-linear-gradient(to bottom, var(--wp--preset--color--grid) 0 1px, transparent 1px var(--wp--custom--grid--step));
  background-size: auto;
  background-position: center;
}

.fluentform .ff-el-image-holder .ff-el-image-input-src[style*="url()"]::after {
  content: "?";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--wp--preset--font-family--heading);
  font-size: var(--wp--preset--font-size--fs-1);
  color: var(--wp--preset--color--border-strong);
  pointer-events: none;
}

.fluentform .ff-el-image-holder:has(.ff-el-image-input-src[style*="url()"]) {
  border-style: dashed;
  border-color: var(--wp--preset--color--border-strong);
}

.fluentform .ff-el-image-holder:has(.ff-el-image-input-src[style*="url()"]) .ff-el-form-check-label {
  color: var(--wp--preset--color--text-muted);
}

/* Znak podpowiedzi przy etykiecie. Wtyczka rysuje go jako kształt WYPEŁNIONY
   czystą czernią — jedyny taki glif w całym kreatorze, więc odstawał od reszty
   podwójnie: kolorem (nasz tekst to `--wp--preset--color--text`, nie `#000`) i tym, że DEC-019
   dopuszcza wyłącznie ikony kreskowe.

   Grubości kreski nie da się tu ustawić, bo to kształt wypełniony, a nie obrys
   — to dokładnie ten powód, dla którego DEC-019 odrzuciło trzy z pięciu
   bibliotek ikon. Zostaje więc ściszenie koloru do tekstu pomocniczego.

   Pole trafienia rozszerzone niewidzialnym `::after` do 44 px (DEC-021 c),
   bez zmiany układu — sam glif zostaje 16 px, żeby nie krzyczał przy etykiecie. */
.fluentform .ff-el-tooltip {
  position: relative;
  color: var(--wp--preset--color--text-muted);

  /* ⚠️ Renderer daje tu `<div>` z ikoną 16 px w środku, więc pojemnik brał
     wysokość WIERSZA TEKSTU formularza (28 px) zamiast wysokości ikony.
     Zmierzone 19.08: etykieta z podpowiedzią 28 px, bez podpowiedzi 21 px,
     czyli pole pod nią startowało 7 px niżej niż pole obok.               */
  display: inline-flex;
  align-items: center;
  line-height: 0;
}

.fluentform .ff-el-tooltip svg,
.fluentform .ff-el-tooltip svg path {
  fill: currentColor;
}

/* 44 px pola trafienia wokół ikony 16 px: (44 − 16) / 2 = 14 px z każdej
   strony. ⚠️ Do 19.08 stało tu `-14px -14px -8px`, dobrane pod pojemnik
   wysoki na 28 px — po zrównaniu go z ikoną dawało już tylko 38 px.       */
.fluentform .ff-el-tooltip::after {
  content: "";
  position: absolute;
  inset: -14px;
}

.fluentform .ff-el-tooltip:hover { color: var(--wp--preset--color--accent); }

.fluentform .ff-el-image-input-src {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  background-size: cover;
  background-position: center;
  background-color: var(--wp--preset--color--surface);
  margin: 0;
  cursor: pointer;
}

.fluentform .ff-el-image-holder .ff-el-form-check-label {
  display: block;
  padding: var(--wp--preset--spacing--space-3) var(--wp--preset--spacing--space-3) var(--wp--preset--spacing--space-4);
  font-family: var(--wp--preset--font-family--heading);
  font-size: var(--wp--preset--font-size--fs-small);
  font-weight: 600;
  line-height: var(--wp--custom--line-height--small);
  color: var(--wp--preset--color--text);
  cursor: pointer;
}

/* Radio zostaje w drzewie i pod klawiaturą — chowamy je z widoku, nie
   z dostępności. `display:none` wyrzuciłoby je z kolejności Tab.          */
.fluentform .ff-el-image-holder .ff-el-form-check-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Zaznaczony kafelek niesie TRZY sygnały naraz: grubszy obrys, podłoże
   akcentu i kolor etykiety (DEC-021 f).                                    */
/* Zaznaczony kafelek niesie TRZY sygnały naraz: podwojoną krawędź, podłoże
   akcentu w stopce i kolor podpisu (DEC-021 f). Druga linia idzie `outline`
   z ujemnym odsunięciem, więc leży NA zdjęciu i nie rusza układu.          */
.fluentform .ff-el-image-holder:has(.ff-el-form-check-input:checked),
.fluentform .ff-el-image-holder.ff_item_selected {
  border-color: var(--wp--preset--color--accent);
  outline: var(--wp--custom--border--hair) solid var(--wp--preset--color--accent);
  outline-offset: -2px;
  background: var(--wp--preset--color--accent-soft);
}

.fluentform .ff-el-image-holder:has(.ff-el-form-check-input:checked) .ff-el-form-check-label,
.fluentform .ff-el-image-holder.ff_item_selected .ff-el-form-check-label {
  color: var(--wp--preset--color--accent);
}

.fluentform .ff-el-image-holder:has(.ff-el-form-check-input:focus-visible) {
  outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
  outline-offset: var(--wp--custom--focus--offset);
}

/* ==========================================================================
   7. PRZYCISKI — trzy poziomy z DEC-021 (a)

   Jeden przycisk główny na widok. Na kroku to `Next` albo `Wyślij`,
   a `Back` jest zawsze cichy — cofanie się nie konkuruje o uwagę
   z ruchem naprzód.
   ========================================================================== */

/* ⚠️ `flex-end` plus `margin-right: auto` na cofaniu, NIE `space-between`.
   Zmierzone: przy `space-between` krok 1 nie ma jeszcze przycisku `Back`,
   więc jedyny przycisk lądował po LEWEJ (prawa krawędź na 236 px), a od
   kroku 2 główny przycisk skakał na prawo (krawędź 357 px). Przy tym
   zapisie prawa krawędź głównego przycisku jest ta sama na wszystkich
   trzech krokach, a `Back` dokleja się do lewej tylko wtedy, gdy istnieje. */
.fluentform .step-nav {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--wp--preset--spacing--space-4);
  margin-top: var(--wp--preset--spacing--space-7);
}
.fluentform .step-nav .ff-btn-prev { margin-right: auto; }

/* ⚠️ OSTATNI krok ma inną strukturę DOM niż poprzednie i bez tej reguły
   układ przycisków się rozjeżdża. Na krokach 1–2 `Back` i `Next` siedzą
   w jednym `.step-nav`. Na kroku ostatnim renderer rozdziela je na dwie
   komórki `.ff-t-cell` wewnątrz `.ff-inner_submit_container`, bo przycisk
   wysyłki jest osobnym elementem formularza, nie częścią nawigacji kroków.
   Komórki bez `flex` układały się JEDNA POD DRUGĄ i zmierzone było to tak:
   `Back` na 676 px, `Send` na 720 px, oba dosunięte do lewej.

   Skutek nie jest kosmetyczny: przycisk główny wyskakiwał w innym miejscu
   niż na dwóch wcześniejszych krokach, czyli dokładnie tam, gdzie ręka
   już się go nie spodziewa.                                              */
.fluentform .ff-inner_submit_container {
  display: flex;
  align-items: center;
  gap: var(--wp--preset--spacing--space-4);
  margin-top: var(--wp--preset--spacing--space-7);
}
.fluentform .ff-inner_submit_container .step-nav { margin-top: 0; }
.fluentform .ff-inner_submit_container .ff-t-column-2 {
  margin-left: auto;
  text-align: right;
}
.fluentform .ff-inner_submit_container .ff_submit_btn_wrapper { margin-bottom: 0; }

/* 🗄️ Odrzucone po pomiarze: łamanie tych dwóch przycisków do pionu na
   wąskim ekranie. Wyglądało na konieczne, bo `Send my specification` mierzy
   238 px, ale Back ma 42 px, odstęp 16 px, a kolumna na telefonie 324 px —
   czyli **mieszczą się w wierszu z 28 px zapasu**. Wariant pionowy dawał
   przy tym gorszy wynik niż problem, który miał naprawić: przy
   `column-reverse` główny przycisk lądował NAD Backiem, czyli dalej od
   kciuka, a bez `reverse` wracaliśmy dokładnie do usterki wyżej.
   Jeden wiersz na wszystkich szerokościach jest tu i spójniejszy,
   i bliższy ręki.                                                        */

.fluentform .ff-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--wp--preset--spacing--space-2);
  min-height: var(--wp--custom--hit--min);
  padding: 0 var(--wp--preset--spacing--space-6);

  font-family: var(--wp--preset--font-family--heading);
  font-size: var(--wp--preset--font-size--fs-body);
  font-weight: 600;
  line-height: 1;

  border: var(--wp--custom--border--hair) solid transparent;
  border-radius: var(--wp--custom--radius);
  cursor: pointer;
  box-shadow: none;

  transition:
    background var(--wp--custom--motion--hover) var(--wp--custom--motion--ease),
    color      var(--wp--custom--motion--hover) var(--wp--custom--motion--ease),
    transform  var(--wp--custom--motion--hover) var(--wp--custom--motion--ease);
}

/* Wciśnięcie 1 px w 40 ms — próg, poniżej którego reakcja czyta się jako
   równoczesna z ruchem ręki (DEC-021 b). Asymetria wobec 120 ms najazdu
   jest celowa.                                                            */
.fluentform .ff-btn:active {
  transform: translateY(1px);
  transition-duration: var(--wp--custom--motion--press);
}

.fluentform .ff-btn-next,
.fluentform .ff-btn-submit {
  background: var(--wp--preset--color--accent);
  color: var(--wp--preset--color--text-on-accent);
}

.fluentform .ff-btn-next:hover,
.fluentform .ff-btn-submit:hover { background: var(--wp--preset--color--accent-hover); }
.fluentform .ff-btn-next:active,
.fluentform .ff-btn-submit:active { background: var(--wp--preset--color--accent-press); }

.fluentform .ff-btn-prev {
  background: transparent;
  color: var(--wp--preset--color--text-muted);
  padding-inline: 0;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.fluentform .ff-btn-prev:hover { color: var(--wp--preset--color--accent); }

/* Na pierwszym kroku nie ma dokąd wracać — renderer i tak stawia tam
   przycisk, więc go chowamy zamiast pokazywać martwy cel.                 */
.fluentform .ff_step_nav_last .ff-btn-prev:only-child,
.fluentform .fluentform-step:first-of-type .ff-btn-prev { visibility: hidden; }

.fluentform .ff-btn:focus-visible {
  outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
  outline-offset: var(--wp--custom--focus--offset);
}

/* Stan wyłączony ma własne tokeny, nigdy `opacity` (DEC-021 d). */
.fluentform .ff-btn:disabled {
  background: var(--wp--preset--color--disabled-bg);
  color: var(--wp--preset--color--disabled-text);
  cursor: not-allowed;
}

/* ==========================================================================
   7b. ZAŁĄCZNIK — zdjęcie starego wkładu

   Zdjęcie jest ZAŁĄCZNIKIEM do wypełnionego zapytania, nie ścieżką zamiast
   niego (DEC-026). Dlatego pole stoi na końcu ostatniego kroku i wygląda
   jak pole opcjonalne, a nie jak drugie, konkurencyjne wejście.

   Renderer Pro daje: label.ff_file_upload_holder > span.ff_upload_btn
   plus ukryty input i listę wgranych plików. Bez arkusza wtyczki wychodzi
   z tego goły przycisk „Choose files" z przeglądarki.
   ========================================================================== */

.fluentform .ff_file_upload_holder {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--wp--custom--hit--min);
  padding: var(--wp--preset--spacing--space-5);
  border: var(--wp--custom--border--hair) dashed var(--wp--preset--color--border-strong);
  border-radius: var(--wp--custom--radius);
  background: var(--wp--preset--color--page);
  cursor: pointer;
  transition: border-color var(--wp--custom--motion--hover) var(--wp--custom--motion--ease), background var(--wp--custom--motion--hover) var(--wp--custom--motion--ease);
}

.fluentform .ff_file_upload_holder:hover {
  border-color: var(--wp--preset--color--accent);
  background: var(--wp--preset--color--accent-soft);
}

/* Przycisk wewnątrz strefy jest poziomem CICHYM (DEC-021 a) — na tym widoku
   przyciskiem głównym jest „Wyślij zapytanie" i ma nim zostać.            */
.fluentform .ff_upload_btn.ff-btn {
  background: none;
  color: var(--wp--preset--color--accent);
  font-family: var(--wp--preset--font-family--heading);
  font-size: var(--wp--preset--font-size--fs-small);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 0;
  min-height: 0;
}

.fluentform .ff_file_upload_holder:has(input:focus-visible) {
  outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
  outline-offset: var(--wp--custom--focus--offset);
}

/* ── Lista wgranych plików ────────────────────────────────────────────────
   ⭐ DOPISANE 19.08 po obejrzeniu kadru z dwoma wgranymi zdjęciami.

   Renderer Pro daje tu WIĘCEJ, niż było widać: miniaturę (`.ff-upload-thumb`
   z podglądem na `blob:`), pasek postępu, nazwę, wagę i przycisk usunięcia.
   Bez arkusza wtyczki żaden z tych elementów nie ma wymiaru, więc miniatura
   renderowała się jako 698 × 0 px (zmierzone), a całość spadała w cztery
   wiersze gołego tekstu zakończone samotnym „×" o polu trafienia 8 × 15 px.

   Ta sekcja nadaje im kształt karty pliku: podgląd, nazwa, waga, usunięcie.
   Podgląd jest tu ważniejszy niż nazwa — człowiek robi zdjęcie wkładu
   telefonem w hali i chce zobaczyć, że wgrał TO zdjęcie, a nie plik
   „IMG_20260819_113402.jpg".

   ⚠️ `!important` na dwóch własnościach: renderer wpisuje `font-size:12px`
   i `margin-top:15px` STYLEM WPISANYM W ZNACZNIK, więc klasa ich nie bije.
   Obie liczby są przy tym spoza naszej skali (DEC-020 a i b).              */
.fluentform .ff-uploaded-list {
  display: flex;
  flex-direction: column;
  gap: var(--wp--preset--spacing--space-2);
  margin-top: var(--wp--preset--spacing--space-4) !important;
  font-size: var(--wp--preset--font-size--fs-small) !important;
  color: var(--wp--preset--color--text-muted);
}

.fluentform .ff-upload-preview {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--wp--preset--spacing--space-3);
  padding: var(--wp--preset--spacing--space-2);
  background: var(--wp--preset--color--page);
  border: var(--wp--custom--border--hair) solid var(--wp--preset--color--border);
}

.fluentform .ff-upload-thumb {
  width: 56px;
  height: 56px;
  flex: none;
}

.fluentform .ff-upload-preview-img {
  width: 100%;
  height: 100%;
  background-size: cover;
  background-position: center;
  background-color: var(--wp--preset--color--surface);
  border: var(--wp--custom--border--hair) solid var(--wp--preset--color--border);
}

/* ⚠️ Kolumna opisowa jest JEDNOKOLUMNOWA, a przycisk usuwania stoi poza
   tokiem (niżej). Wariant „druga kolumna siatki" wyglądał poprawnie w kodzie
   i rozjeżdżał się na ekranie: przycisk ma 44 px, więc rozpychał PIERWSZY
   wiersz siatki do 44 px, a waga pliku spadała pod niego — nazwa siadała
   wtedy 11 px nad środkiem karty i całość czytała się jak przekrzywiona
   (zmierzone: wysokość karty 83 px zamiast 72 px).                          */
.fluentform .ff-upload-details {
  min-width: 0;
  display: grid;
  row-gap: var(--wp--preset--spacing--space-1);
  padding-right: calc(var(--wp--custom--hit--min) + var(--wp--preset--spacing--space-2));
}

/* Nazwa pliku bywa dłuższa niż kolumna („Screenshot 2026-04-13 at
   12.49.44.png"), więc urywa się wielokropkiem zamiast łamać kartę.       */
.fluentform .ff-upload-filename {
  min-width: 0;
  font-size: var(--wp--preset--font-size--fs-small);
  line-height: var(--wp--custom--line-height--small);
  color: var(--wp--preset--color--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fluentform .ff-upload-filesize {
  font-family: var(--wp--preset--font-family--data);
  font-size: var(--wp--preset--font-size--fs-micro);
  line-height: var(--wp--custom--line-height--micro);
  color: var(--wp--preset--color--text-muted);
}

.fluentform .ff-upload-progress-inline-text {
  font-family: var(--wp--preset--font-family--data);
  font-size: var(--wp--preset--font-size--fs-micro);
  color: var(--wp--preset--color--text-muted);
}

/* Pasek postępu — 2 px, ten sam język co linia w rysunku. */
.fluentform .ff-el-progress {
  width: 100%;
  height: 2px;
  background: var(--wp--preset--color--surface-sunken);
}

.fluentform .ff-el-progress-bar {
  height: 100%;
  background: var(--wp--preset--color--accent);
  transition: width var(--wp--custom--motion--expand) var(--wp--custom--motion--ease);
}

/* Po wgraniu pasek i „100% Completed" nie niosą już nic — plik widać
   na miniaturze, a wagę w wierszu niżej. Zostają wyłącznie na czas
   wgrywania, czyli wtedy, gdy naprawdę odpowiadają na pytanie.            */
.fluentform .ff-upload-preview.ff_uploading_complete .ff-el-progress,
.fluentform .ff-upload-preview.ff_uploading_complete .ff-upload-progress-inline-text { display: none; }

.fluentform .ff-upload-error {
  color: var(--wp--preset--color--error) !important;
  font-size: var(--wp--preset--font-size--fs-micro);
}
.fluentform .ff-upload-error:empty { display: none; }

/* Usunięcie pliku to realny cel dotykowy, a nie znak w tekście: 44 px
   (DEC-021 c) i czerwień dopiero przy najeździe, żeby lista nie krzyczała
   ostrzeżeniem w stanie spoczynku.

   ⚠️ POPRAWKA 19.08 — KRZYŻYK RYSUJEMY KRESKĄ, NIE LITERĄ.
   Renderer wstawia tu znak `×` (U+00D7). Wyśrodkowanie pudełka wyśrodkowuje
   POLE ZNAKU, a nie samą kreskę: mnożenie leży w kroju na osi matematycznej,
   czyli wyraźnie nad środkiem pola, i dlatego krzyżyk siedział krzywo mimo
   `place-items: center`. Żadna wartość `line-height` tego nie naprawia
   uczciwie, bo przesunięcie zależy od kroju.

   Dwie kreski 1,5 px pod 45° są przy okazji zgodne z językiem rysunku
   (DEC-020 g) i z DEC-019, które dopuszcza wyłącznie ikony kreskowe.       */
.fluentform .ff-upload-remove {
  position: absolute;
  top: 50%;
  right: var(--wp--preset--spacing--space-2);
  transform: translateY(-50%);
  width: var(--wp--custom--hit--min);
  height: var(--wp--custom--hit--min);
  font-size: 0;              /* chowa znak × z renderera */
  color: var(--wp--preset--color--text-muted);
  cursor: pointer;
  border-radius: var(--wp--custom--radius);
  transition: color var(--wp--custom--motion--hover) var(--wp--custom--motion--ease),
              background var(--wp--custom--motion--hover) var(--wp--custom--motion--ease);
}

.fluentform .ff-upload-remove::before,
.fluentform .ff-upload-remove::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 15px;
  height: 1.5px;
  background: currentColor;
}

.fluentform .ff-upload-remove::before { transform: translate(-50%, -50%) rotate(45deg); }
.fluentform .ff-upload-remove::after  { transform: translate(-50%, -50%) rotate(-45deg); }

/* Cel klawiatury. Renderer daje goły `<span>`, więc pliku NIE DAŁO SIĘ
   usunąć bez myszy; `tabindex` i obsługę klawisza dokłada `js/ef-upload.js`,
   a tutaj stoi tylko widoczny ślad fokusu.                                 */
.fluentform .ff-upload-remove:focus-visible {
  outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
  outline-offset: calc(-1 * var(--wp--custom--focus--offset));
  color: var(--wp--preset--color--accent);
}

.fluentform .ff-upload-remove:hover {
  color: var(--wp--preset--color--error);
  background: var(--wp--preset--color--surface);
}

/* ==========================================================================
   8. KOMUNIKAT PO WYSŁANIU
   ========================================================================== */

.fluentform .ff-message-success,
.ff-message-success {
  padding: var(--wp--preset--spacing--space-6);
  background: var(--wp--preset--color--accent-soft);
  border-left: 3px solid var(--wp--preset--color--accent);
  font-size: var(--wp--preset--font-size--fs-lead);
  line-height: var(--wp--custom--line-height--lead);
  color: var(--wp--preset--color--text);
}

/* ==========================================================================
   9. RUCH
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .fluentform *,
  .fluentform *::before,
  .fluentform *::after { transition-duration: 1ms !important; animation-duration: 1ms !important; }
}
