  /* Szata CXLABS. Kolory, fonty, odstępy, promienie i cienie pochodzą WYŁĄCZNIE
     z /colors_and_type.css (design system CXLABS wystawiony na tej domenie) -
     żadnej wartości marki nie ma tu wpisanej z ręki. Układ i nazwy klas są te same
     co w portalu LINKSPOT, bo zmienia się szata, nie mechanika.
     Uwaga o wagach: Clash Display ma tylko 300/400/500, więc nagłówki nie schodzą
     poniżej 300 i nie idą powyżej 500 - 700 przeglądarka pogrubiłaby sztucznie. */
  /* Avenir - ten sam plik, którym pisze cxlabs.digital (Webflow CDN), skopiowany
     do assets/design/fonts/. To domyka decyzję 6 z `01`: tamten Avenir odpadł, bo
     lokalny Avenir-Light.ttf nie miał polskich diakrytyków. Te dwa mają pełne PL -
     sprawdza to scripts/fetch_design_system.py tablicą cmap przy każdym pobraniu.
     Serwujemy z własnego katalogu, więc portal nie odpytuje Google Fonts. */
  @font-face{font-family:"Avenir";src:url("/fonts/Avenir-Book.woff2") format("woff2");
    font-weight:300;font-style:normal;font-display:swap}
  @font-face{font-family:"Avenir";src:url("/fonts/Avenir-Roman.woff2") format("woff2");
    font-weight:400;font-style:normal;font-display:swap}

  :root{
    /* Tekst leci Avenirem jak na stronie firmowej. Token design systemu nadpisujemy
       tylko tutaj - colors_and_type.css jest wspólny z panelem zgłoszeń i portal go
       nie zmienia (Nunito Sans zostaje jako zapas). */
    --font-body:"Avenir","Nunito Sans",system-ui,sans-serif;
    /* promień dużych powierzchni: „radius large" na stronie firmowej to 2rem */
    --radius-2xl:32px;
    /* powierzchnie */
    --surface:var(--cx-white);
    --surface-alt:var(--cx-mist);
    --surface-chip:var(--cx-paper);
    --header-bg:rgba(18,32,33,.86);              /* --cx-ink z przezroczystością */
    --hero:linear-gradient(165deg,var(--cx-ink-80) 0%,var(--cx-ink) 100%);
    --hero-glow:radial-gradient(circle,rgba(173,247,99,.20),transparent 62%);
    /* treść */
    --text:var(--cx-ink);
    --body-fg:var(--cx-gray-1);
    --muted:var(--cx-gray-2);
    --soft:var(--cx-gray-3);
    --line:var(--cx-cloud);
    --line2:var(--cx-cloud-2);
    /* Tokeny doszły z paczką 16.09: zieleń stanu „działa", ciemniejszy
       turkus na plakietki na mgle i czerwień awarii. Arkusz design systemu
       na domenie ich jeszcze nie ma, więc stoją tu wprost. */
    --cx-green-500:rgb(107,210,16);
    --cx-turquoise-600:rgb(68,104,103);
    /* Podświetlenie w pasku i w menu rozwijanym - JEDEN kolor na wszystkie
       trzy piętra (pozycje paska, produkty, kategorie). Wcześniej każde
       miało swój: czerń 30%, biel 6% i biel 7%, przez co menu wyglądało,
       jakby złożono je z dwóch różnych komponentów. */
    --nav-hover:rgba(0,0,0,.18);
    /* Wysokość pozycji paska = wysokość guzika „Nowe zgłoszenie". Jedna
       wartość dla obu, żeby nie rozjechały się przy zmianie kroju. */
    --nav-h:48px;
    /* Znak „i" na kropce okna serwisowego - maska SVG, żeby kształt nie
       zależał od tego, czy krój zdążył się wczytać. */
    --navdot-i:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><circle cx="12" cy="5.4" r="2.2"/><rect x="9.8" y="10" width="4.4" height="11" rx="2.2"/></svg>');
    --cx-error:rgb(180,35,24);
    --cx-ink-90:rgb(22,36,37);
    /* akcenty */
    --accent:var(--cx-ink-10);                   /* odnośniki i etykiety na jasnym */
    --accent-strong:var(--cx-ink);
    --accent-soft:var(--cx-lime-soft);
    --on-dark:var(--fg-on-dark);
    --on-dark-muted:rgba(219,236,233,.78);
    --on-dark-soft:var(--cx-ink-40);
  }

  /* ── znaki marki przeniesione ze strony firmowej ───────────────────────────
     Na cxlabs.digital tytuły pozycji stoją między dwoma szewronami (SVG 16×29,
     kolor #8BBDB8 - to dokładnie token --cx-ink-20), a nagłówki sekcji mają nad
     sobą „eyebrow": znak CXLABS plus szara etykieta. Trzymamy je jako maski CSS,
     żeby brały kolor z currentColor i nie puchły w markupie. */
  .cx-chev-l,.cx-chev-r{display:inline-block;width:9px;height:16px;flex:0 0 auto;
      background:currentColor}
  .cx-chev-l{-webkit-mask:url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2016%2029%27%3E%3Cpath%20d%3D%27M-2.18146e-06%2014.0535C0.0045718%2015.9288%200.672363%2017.8635%202.15888%2019.3866L9.90022%2028.0977L15.2197%2028.0977L5.00843%2016.4708L4.94668%2016.4022C4.26746%2015.6772%203.95414%2014.8516%203.95185%2014.0489C3.95185%2013.2462%204.26974%2012.4206%204.94668%2011.6956L5.00843%2011.627L15.2197%200.000127792L9.90022%200.000128257L2.16117%208.71114C0.674648%2010.232%200.00685648%2012.1667%200.00228282%2014.0443L0.00228282%2014.0558L-2.18146e-06%2014.0535Z%27%20fill%3D%27black%27/%3E%3C/svg%3E") no-repeat center/contain;
              mask:url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2016%2029%27%3E%3Cpath%20d%3D%27M-2.18146e-06%2014.0535C0.0045718%2015.9288%200.672363%2017.8635%202.15888%2019.3866L9.90022%2028.0977L15.2197%2028.0977L5.00843%2016.4708L4.94668%2016.4022C4.26746%2015.6772%203.95414%2014.8516%203.95185%2014.0489C3.95185%2013.2462%204.26974%2012.4206%204.94668%2011.6956L5.00843%2011.627L15.2197%200.000127792L9.90022%200.000128257L2.16117%208.71114C0.674648%2010.232%200.00685648%2012.1667%200.00228282%2014.0443L0.00228282%2014.0558L-2.18146e-06%2014.0535Z%27%20fill%3D%27black%27/%3E%3C/svg%3E") no-repeat center/contain}
  .cx-chev-r{-webkit-mask:url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2016%2029%27%3E%3Cpath%20d%3D%27M15.2197%2014.0442C15.2151%2012.1689%2014.5473%2010.2341%2013.0608%208.71101L5.31946%200L0%200L10.2113%2011.6269L10.273%2011.6955C10.9522%2012.4205%2011.2655%2013.246%2011.2678%2014.0488C11.2678%2014.8515%2010.9499%2015.6771%2010.273%2016.402L10.2113%2016.4706L0%2028.0975H5.31946L13.0585%2019.3865C14.545%2017.8657%2015.2128%2015.9309%2015.2174%2014.0533V14.0419L15.2197%2014.0442Z%27%20fill%3D%27black%27/%3E%3C/svg%3E") no-repeat center/contain;
              mask:url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2016%2029%27%3E%3Cpath%20d%3D%27M15.2197%2014.0442C15.2151%2012.1689%2014.5473%2010.2341%2013.0608%208.71101L5.31946%200L0%200L10.2113%2011.6269L10.273%2011.6955C10.9522%2012.4205%2011.2655%2013.246%2011.2678%2014.0488C11.2678%2014.8515%2010.9499%2015.6771%2010.273%2016.402L10.2113%2016.4706L0%2028.0975H5.31946L13.0585%2019.3865C14.545%2017.8657%2015.2128%2015.9309%2015.2174%2014.0533V14.0419L15.2197%2014.0442Z%27%20fill%3D%27black%27/%3E%3C/svg%3E") no-repeat center/contain}

  /* tytuł w szewronach - jak „❰ monday CRM ❱" w sekcji Usługi CXLABS */
  /* Kolor NIE stoi na otoczce. Szewrony mają swój (--cx-ink-20, prosto
     z cxlabs.digital), a sama nazwa dziedziczy go po elemencie, w którym
     stoi - raz jest to <b> kafla, raz <h3> sekcji, i każdy z nich wie
     lepiej, jakiego koloru ma być na swoim tle.

     Wcześniej otoczka malowała wszystko na szewronowy szary, a wewnętrzny
     <span> wracał na sztywno do --text (ciemny atrament). Na kaflu kategorii
     - ciemna karta rgb(22,36,37) na jasnej sekcji - dawało to kontrast
     1,05:1, czyli nazwę kategorii niewidoczną. `.app b` ustawiało tam biel,
     ale ten <span> ją zjadał. Po zmianie: 7,67:1 na kaflu, 13,0:1
     w nagłówku sekcji na jasnym tle. */
  .chevtitle{display:inline-flex;align-items:center;flex-wrap:nowrap;gap:10px;
      max-width:100%}
  .chevtitle>.cx-chev-l,.chevtitle>.cx-chev-r{color:var(--cx-ink-20)}
  .chevtitle>span{color:inherit;min-width:0;overflow:hidden;text-overflow:ellipsis;
      white-space:nowrap}

  /* eyebrow nad nagłówkiem sekcji */
  .eyebrow{display:inline-flex;align-items:center;gap:10px;margin-bottom:var(--space-3);
      font-size:var(--fs-small);color:var(--muted)}
  .eyebrow .cx-mark{color:var(--cx-ink-20);gap:1px}
  .eyebrow .cx-chev-l,.eyebrow .cx-chev-r{width:7px;height:13px}
  .eyebrow--on-dark{color:var(--cx-lime-soft)}
  .eyebrow--on-dark .cx-mark{color:var(--cx-lime)}

  /* znak CXLABS: dwa szewrony zwrócone do siebie, jak w hero strony firmowej */
  .cx-mark{display:inline-flex;align-items:center;gap:2px;color:var(--cx-lime)}
  .cx-mark .cx-chev-l,.cx-mark .cx-chev-r{width:15px;height:27px}

  *{margin:0;padding:0;box-sizing:border-box}
  /* Płótno strony (to, co przeglądarka maluje POZA pudełkiem `body`) ma barwę
     stopki, nie białą - zgłoszenie Radka 29.09: „co to za jasny pasek na dole
     strony? widzę to na wszystkich urządzeniach".
     Skąd się brał: szata z domeny ustawia `html, body {background: var(--bg)}`,
     a `--bg` to biel. Tło `body` propaguje się na płótno WYŁĄCZNIE wtedy, gdy
     `html` własnego tła nie ma - tu ma, więc każdy piksel poza pudełkiem body
     wychodził biały: pas pod stopką, odbicie przy przewinięciu za koniec na
     iOS i błysk przy przeładowaniu. Ciemne płótno pasuje do OBU końców strony:
     u góry stoi ciemny pasek, u dołu ciemna stopka. */
  html{background:var(--cx-ink)}
  body{font-family:var(--font-body);background:var(--surface-alt);color:var(--text);
       font-size:var(--fs-body);line-height:var(--lh-body);min-height:100vh;
       display:flex;flex-direction:column;-webkit-font-smoothing:antialiased}
  a{color:var(--accent);text-decoration:none} a:hover{color:var(--cx-ink)}
  ::selection{background:var(--cx-lime);color:var(--cx-ink)}
  h1,h2,h3.sg{font-family:var(--font-display);font-weight:400}
  .wrap{max-width:1180px;margin:0 auto;padding:0 var(--space-6);width:100%}
  @keyframes cxUp{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}
  @keyframes cxFade{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}
  @keyframes cxPop{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}
  @keyframes cxGlow{0%,100%{opacity:.5}50%{opacity:.9}}
  @media(prefers-reduced-motion:reduce){*{animation:none!important}}

  /* Pasek wersji rozwojowej - WIDZI GO WYŁĄCZNIE RADEK (polecenie 29.09:
     „ten pasek pokazuj tylko mi, nikt inny nie może tego zobaczyć").
     Domyślnie schowany, odsłania go klasa `devpasek` na <html>, którą nakłada
     `setPortalUser()` po rozpoznaniu adresu z listy `PASEK_ROZWOJOWY`.
     Ukrycie jest DOMYŚLNE, a nie dokładane skryptem - inaczej każdy zobaczyłby
     pasek przez ułamek sekundy, zanim JavaScript zdąży go zdjąć.
     Co to znaczy naprawdę: pasek znika Z EKRANU, a jego treść zostaje w kodzie
     strony, bo tam trafia przy budowaniu. Nie ma w nim nic tajnego (liczba
     artykułów i data), więc to wystarcza - ale gdyby kiedyś miał nieść coś,
     czego nie wolno pokazać, ukrycie stylem NIE JEST zamkiem.
     Do 29.09 ten blok stał w arkuszu DWA razy - druga kopia (bez `display`)
     została po dawnym pasku i już nic nie robiła, ale każdy, kto trafił na nią
     pierwszą, poprawiałby martwy kod. Została zdjęta; jedyne, co zostaje
     osobno, to przyciemnienie w wąskim widoku na końcu pliku. */
  .devbar{display:none;background:var(--cx-ink);color:var(--cx-lime-soft);text-align:center;
      font-size:var(--fs-xs);padding:7px var(--space-4);border-bottom:1px solid var(--cx-ink-60)}
  html.devpasek .devbar{display:block}
  .devbar b{color:var(--cx-lime);font-weight:600}
  /* Plakietka podglądu przed wdrożeniem (6.10). Wisi w rogu i nie zasłania
     treści - to ma być przypomnienie, a nie pasek. Widzi ją wyłącznie
     przeglądarka z ciasteczkiem podglądu. */
  /* U góry, nie u dołu: dół zajmuje pasek cookies i zasłaniał plakietkę. */
  .podgladpl{position:fixed;left:50%;top:86px;transform:translateX(-50%);
      z-index:300;display:flex;white-space:nowrap;
      align-items:center;gap:10px;padding:8px 10px 8px 14px;border-radius:999px;
      background:var(--cx-ink);color:var(--cx-white);font-size:13px;
      box-shadow:0 6px 20px rgba(18,32,33,.3)}
  .podgladpl b{color:var(--cx-lime);font-weight:700}
  .podgladpl a{color:var(--cx-ink);background:var(--cx-lime);border-radius:999px;
      padding:4px 10px;font-weight:600;text-decoration:none}
  .podgladpl a:hover{color:var(--cx-ink)}

  body>header{position:sticky;top:0;z-index:60;background:var(--header-bg);
      backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
      border-bottom:1px solid var(--cx-ink-60)}
  .nav{max-width:1180px;margin:0 auto;display:flex;align-items:center;gap:26px;
      min-height:70px;flex-wrap:wrap;padding:var(--space-2) var(--space-6)}
  .brand{display:flex;align-items:center;color:var(--cx-white)}
  .brand .cx-logo{height:26px;width:auto;display:block}
  nav.menu{display:flex;align-items:center;gap:26px;flex-wrap:wrap;margin-left:auto}
  nav.menu a{color:var(--on-dark-muted);font-size:var(--fs-small);font-weight:600}
  nav.menu a:hover{color:var(--cx-white)}
  nav.menu a.active{color:var(--cx-white);font-weight:700}

  /* przycisk główny: lime z ciemną płytką szewronu (komponent .cx-btn design systemu) */
  .btn{display:inline-flex;align-items:center;gap:var(--space-3);background:var(--cx-lime);
      color:var(--cx-ink)!important;font-family:inherit;font-weight:600;font-size:13.5px;
      padding:4px 4px 4px var(--space-5);height:44px;border:1px solid transparent;
      border-radius:var(--radius-pill);cursor:pointer;text-decoration:none;
      transition:filter .14s ease,transform .12s ease}
  .btn:hover{filter:brightness(.96);color:var(--cx-ink)}
  .btn:active{transform:translateY(1px)}
  /* OBRYS SKUPIENIA JEST NASZ, nie przeglądarki (zgłoszenie Radka 1.10:
     „obramowanie guzika wyślij prośbę jest niebieskie"). Bez tej reguły guzik
     po kliknięciu dostawał systemowy niebieski pierścień - jedyny niebieski
     w całym portalu, a przy tym grubszy od wszystkiego dookoła.
     `:focus-visible`, a nie `:focus`: obrys ma się pokazać temu, kto chodzi
     klawiaturą, a nie zostawać po każdym kliknięciu myszą.
     Reguła jest WSPÓLNA dla wszystkich guzików - poprawka w tym jednym
     miejscu, w którym ktoś to zauważył, zostawiłaby resztę portalu
     z niebieskim. */
  .btn:focus-visible{outline:2px solid var(--cx-ink);outline-offset:2px}
  .btn--ghost:focus-visible{outline-color:var(--cx-lime)}
  .btn .chev{width:36px;height:36px;flex:0 0 auto;border-radius:50%;
      background:var(--cx-ink);color:var(--cx-lime);display:inline-flex;
      align-items:center;justify-content:center;font-size:15px;line-height:1}
  .btn--ghost{background:transparent;color:var(--cx-mist)!important;border-color:var(--cx-ink-60);
      padding:11px var(--space-5);height:auto;border-radius:var(--radius-pill)}
  .btn--ghost:hover{background:rgba(255,255,255,.08);color:var(--cx-white)}

  .hero{position:relative;overflow:hidden;background:var(--hero);color:var(--on-dark);
      padding:88px var(--space-6) 150px;text-align:center}
  .hero .glow{position:absolute;top:-30%;left:50%;transform:translateX(-50%);
      width:680px;height:680px;background:var(--hero-glow);filter:blur(10px);
      animation:cxGlow 7s ease-in-out infinite;pointer-events:none}
  .hero .inner{position:relative;max-width:820px;margin:0 auto}
  .badge{display:inline-flex;align-items:center;gap:var(--space-2);
      background:rgba(255,255,255,.06);border:1px solid var(--cx-ink-60);color:var(--cx-lime-soft);
      font-size:12.5px;font-weight:500;padding:7px 15px;border-radius:var(--radius-pill);
      margin-bottom:26px;animation:cxFade .6s ease forwards}
  .badge .dot{width:7px;height:7px;border-radius:50%;background:var(--cx-lime);
      box-shadow:0 0 10px var(--cx-lime)}
  .hero h1 em{font-style:normal;color:var(--cx-lime)}
  .hero h1{font-family:var(--font-display);font-weight:400;color:var(--cx-white);
      font-size:clamp(32px,5vw,var(--fs-hero));line-height:var(--lh-tight);
      letter-spacing:-.02em;animation:cxUp .6s ease forwards}
  .hero p.sub{margin:var(--space-5) auto 0;max-width:560px;font-size:18px;
      line-height:1.55;color:var(--cx-lime-soft);animation:cxUp .6s ease .05s forwards}
  .search{max-width:640px;margin:36px auto 0;display:flex;align-items:center;
      background:var(--cx-white);border-radius:var(--radius-pill);padding:6px 6px 6px var(--space-6);
      box-shadow:var(--shadow-xl);animation:cxUp .6s ease .1s forwards}
  .search .lens{color:var(--soft);font-size:19px;margin-right:10px}
  .search input{flex:1;border:none;outline:none;font-family:inherit;font-size:var(--fs-body);
      color:var(--text);background:none;padding:12px 0;min-width:0}
  .search button{display:inline-flex;align-items:center;gap:var(--space-2);
      background:var(--cx-lime);color:var(--cx-ink);font-family:inherit;font-weight:600;
      font-size:14.5px;padding:13px var(--space-6);border:none;border-radius:var(--radius-pill);
      cursor:pointer;transition:filter .14s}
  .search button:hover{filter:brightness(.96)}
  .sugg{margin-top:var(--space-5);display:flex;gap:9px;justify-content:center;flex-wrap:wrap;
      animation:cxFade .6s ease .2s forwards}
  .sugg .lbl{font-size:13px;color:var(--on-dark-soft)}
  .sugg button{font-size:13px;color:var(--cx-lime-soft);background:rgba(255,255,255,.06);
      border:1px solid var(--cx-ink-60);border-radius:var(--radius-pill);padding:5px 13px;
      cursor:pointer;font-family:inherit;transition:background .18s,border-color .18s}
  .sugg button:hover{background:rgba(173,247,99,.14);border-color:var(--cx-lime)}

  /* podpowiedzi wyszukiwarki (autocomplete) - panel w koordynatach dokumentu,
     dlatego leży na końcu <body>, poza hero (które przycina overflow) */
  .ac{position:absolute;z-index:55;display:none;background:var(--cx-white);
      border:1px solid var(--line);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);
      overflow:hidden;text-align:left}
  .ac.open{display:block;animation:cxPop .16s ease}
  .aclist{overflow-y:auto;overscroll-behavior:contain}   /* wysokość liczy acPosition() */
  .ac .acitem{display:flex;align-items:center;gap:var(--space-3);padding:8px var(--space-4);
      color:var(--text);border-bottom:1px solid var(--line);cursor:pointer}
  .ac .acitem:last-child{border-bottom:none}
  .ac .acitem:hover,.ac .acitem.on{background:var(--cx-mist);color:var(--text)}
  .ac .acic{width:34px;height:34px;border-radius:9px;background:var(--cx-mist);
      color:var(--accent);flex-shrink:0;font-family:var(--font-display);font-weight:400;
      font-size:11px;display:flex;align-items:center;justify-content:center}
  .ac .actx{min-width:0;display:flex;flex-direction:column}
  .ac .actx b{font-size:14.5px;font-weight:600;line-height:1.35;white-space:nowrap;
      overflow:hidden;text-overflow:ellipsis}
  .ac .acsub{font-size:var(--fs-xs);color:var(--muted);white-space:nowrap;overflow:hidden;
      text-overflow:ellipsis}
  .ac .acown{margin-left:auto;flex-shrink:0;font-size:10.5px;font-weight:700;letter-spacing:.03em;
      color:var(--cx-ink);background:var(--cx-lime);border-radius:var(--radius-pill);padding:3px 8px}
  .ac mark{background:rgba(173,247,99,.45);color:inherit;border-radius:3px;padding:0 1px}
  .ac .acmore{display:block;width:100%;text-align:left;padding:11px var(--space-4);
      background:var(--cx-mist);border:none;border-top:1px solid var(--line);
      font-family:inherit;font-size:13px;font-weight:700;color:var(--accent);cursor:pointer}
  .ac .acmore:hover,.ac .acmore.on{background:var(--accent-soft)}
  .ac .acempty{padding:15px;font-size:13.5px;color:var(--muted)}
  .ac .achint{display:flex;gap:var(--space-4);padding:var(--space-2) var(--space-4);
      background:var(--cx-mist);border-top:1px solid var(--line);font-size:11.5px;color:var(--soft)}
  .ac .achint kbd{font-family:inherit;font-weight:700;color:var(--muted);background:var(--cx-white);
      border:1px solid var(--line2);border-radius:5px;padding:0 5px}
  @media(max-width:640px){ .ac .achint{display:none} }

  .hero.small{padding:40px var(--space-6) 46px;text-align:left}
  .hero.small .search{margin:var(--space-5) auto 0;max-width:560px;border-radius:13px;
      padding:5px 5px 5px var(--space-4);box-shadow:var(--shadow-lg)}
  .hero.small .search input{font-size:15px;padding:11px 0}
  .hero.small .search button{font-size:var(--fs-small);padding:11px var(--space-5);border-radius:10px}
  .heroCrumbs{font-size:13px;color:var(--cx-lime-soft);margin-bottom:var(--space-4)}
  .heroCrumbs a{color:var(--cx-lime-soft)} .heroCrumbs a:hover{color:var(--cx-white)}
  .heroCrumbs .sep{margin:0 var(--space-2);opacity:.5}
  .heroCrumbs .here{color:var(--cx-white);font-weight:600}
  .appHead{display:flex;align-items:center;gap:var(--space-4)}
  /* Telefon: znak nad nagłówkiem, nie obok. Przy szerokości 390 px opis
     zjada całą kolumnę, a znak wisi w połowie akapitu i wygląda na zgubiony. */
  @media(max-width:700px){
    .hero .appHead{flex-direction:column;align-items:flex-start;gap:var(--space-3)}
  }
  .appHead .ic{width:52px;height:52px;border-radius:var(--radius-lg);background:rgba(255,255,255,.08);
      border:1px solid var(--cx-ink-60);color:var(--cx-lime);display:flex;align-items:center;
      justify-content:center;font-family:var(--font-display);font-weight:400;font-size:17px;flex-shrink:0}
  .appHead h1{font-family:var(--font-display);font-weight:400;color:var(--cx-white);
      font-size:30px;letter-spacing:-.01em}
  .appHead p{font-size:var(--fs-small);color:var(--cx-lime-soft);margin-top:2px}

  body>main{flex:1}
  .panel{margin-top:-92px;position:relative;z-index:5;background:var(--cx-white);
      border:1px solid var(--line);border-radius:var(--radius-2xl);padding:30px;
      box-shadow:var(--shadow-lg);animation:cxUp .6s ease .15s forwards}
  .panel .phead{display:flex;align-items:baseline;justify-content:space-between;
      margin-bottom:var(--space-5);flex-wrap:wrap;gap:var(--space-2)}
  .panel h2{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h5);letter-spacing:-.01em}
  .panel .total{font-size:13px;color:var(--muted)}
  .apps{display:grid;grid-template-columns:repeat(auto-fill,minmax(288px,1fr));gap:var(--space-3)}
  .app{text-align:left;background:var(--cx-mist);border:1px solid var(--line);
      border-radius:var(--radius-2xl);padding:var(--space-5);cursor:pointer;font-family:inherit;
      display:flex;align-items:center;gap:13px;
      transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease}
  .app:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);
      border-color:var(--cx-lime);color:inherit}
  .app .ic{flex-shrink:0;width:40px;height:40px;border-radius:11px;background:var(--cx-lime);
      color:var(--cx-ink);display:flex;align-items:center;justify-content:center;
      font-family:var(--font-display);font-weight:400;font-size:13px}
  .app .tx{min-width:0}
  /* Tytuł kafla stoi między szewronami, więc musi być układem w rzędzie -
     -webkit-box z line-clamp ustawiał szewrony jeden pod drugim. Ucinanie długiej
     nazwy bierze na siebie wewnętrzny <span> w .chevtitle. */
  .app b{display:block;font-family:var(--font-display);font-weight:400;
      font-size:var(--fs-h6);color:var(--text);line-height:1.3;min-width:0}
  /* tylko wiersz z liczbą artykułów - bez tego zawężenia reguła łapała także
     <span>y szewronów w tytule kafla i ustawiała je jeden pod drugim */
  .app .tx>span{display:block;font-size:12.5px;color:var(--muted);margin-top:2px}


  /* ── sekcje huba wzorowane na centrum pomocy monday.com ───────────────────
     Tam strona główna to: hero z wyszukiwarką, „Explore by product" w jasnym
     panelu, „Explore by topic" w panelu wypełnionym kolorem marki, rząd kafelków
     popularnych tematów i blok „Still have questions?". Kolory bierzemy ze swojego
     design systemu: rolę fioletu monday.com gra ciemny ink CXLABS, akcentem jest lime. */
  .hubsec{padding:var(--space-8) 0 0}
  .hubsec:first-of-type{padding-top:var(--space-7)}
  .hubhead{display:flex;align-items:flex-end;justify-content:space-between;
      gap:var(--space-5);flex-wrap:wrap;margin-bottom:var(--space-5)}
  .hubhead h2{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h3);
      letter-spacing:-.01em}
  .hubhead p{font-size:15px;color:var(--muted);margin-top:6px}
  .hubhead--on-dark h2{color:var(--cx-white)}
  .hubhead--on-dark p{color:var(--cx-lime-soft)}

  .pane{background:var(--cx-white);border:1px solid var(--border-subtle);
      border-radius:var(--radius-2xl);padding:var(--space-6)}
  .pane--brand{background:var(--hero);border:1px solid var(--cx-ink-60);color:var(--on-dark)}

  .topics{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:var(--space-4)}
  .topic{display:flex;flex-direction:column;gap:6px;padding:var(--space-5);
      background:rgba(255,255,255,.05);border:1px solid var(--cx-ink-60);
      border-radius:var(--radius-lg);text-decoration:none;
      transition:background .16s ease,border-color .16s ease,transform .16s ease}
  .topic:hover{background:rgba(173,247,99,.10);border-color:var(--cx-lime);transform:translateY(-2px)}
  .topic b{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h5);
      color:var(--cx-white);line-height:1.25}
  .topic span{font-size:13.5px;color:var(--cx-lime-soft)}


  /* blok „nadal masz pytania" */
  .helpwrap{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);
      gap:var(--space-7);align-items:center;margin:var(--space-9) 0 0}
  .helpwrap h2{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h2);
      line-height:var(--lh-tight);letter-spacing:-.01em}
  .helpbox{background:var(--cx-lime);border-radius:var(--radius-2xl);padding:var(--space-6);
      display:flex;flex-direction:column;gap:var(--space-3)}
  .helprow{display:flex;align-items:flex-start;gap:var(--space-4);text-decoration:none;
      color:var(--cx-ink);padding:var(--space-3);border-radius:var(--radius-md);
      transition:background .16s ease}
  .helprow:hover{background:rgba(18,32,33,.08);color:var(--cx-ink)}
  .helprow .ico{width:40px;height:40px;flex:0 0 auto;border-radius:var(--radius-sm);
      background:var(--cx-ink);color:var(--cx-lime);display:flex;align-items:center;
      justify-content:center;font-size:18px}
  .helprow b{display:block;font-weight:700;font-size:15px}
  .helprow em{display:block;font-style:normal;font-size:13.5px;line-height:1.5;
      color:rgba(18,32,33,.72);margin-top:2px}

  /* grupa sekcji w widoku kategorii (drugi poziom taksonomii źródła) */
  .secgroup{margin:0 0 var(--space-7)}
  .secgroup-head{display:flex;align-items:baseline;justify-content:space-between;
      gap:var(--space-4);margin:0 0 var(--space-4);padding-bottom:var(--space-3);
      border-bottom:1px solid var(--line)}
  .secgroup-head h3{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h5)}
  .secgroup-count{font-size:13px;color:var(--soft);white-space:nowrap}

  @media(max-width:900px){
    .helpwrap{grid-template-columns:minmax(0,1fr);gap:var(--space-5)}
    .hubsec{padding-top:var(--space-7)}
  }

  section.kb{padding:26px 0 var(--space-5)}
  section.kb.hub{padding:54px 0 var(--space-5)}
  .secHead{display:flex;align-items:baseline;justify-content:space-between;
      margin-bottom:22px;flex-wrap:wrap;gap:var(--space-2)}
  .secHead h2{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h4);letter-spacing:-.01em}
  .secHead p{font-size:14.5px;color:var(--muted);margin-top:var(--space-1)}
  .kbsub{font-size:var(--fs-small);color:var(--muted);margin-bottom:var(--space-4)}
  .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:var(--space-4);
      animation:cxUp .4s ease forwards}
  .card{position:relative;background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-2xl);padding:26px;display:flex;flex-direction:column;
      gap:10px;cursor:pointer;
      transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease}
  .card:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);border-color:var(--cx-lime)}
  .card .cat{display:flex;align-items:center;gap:7px;font-size:11.5px;font-weight:700;
      text-transform:uppercase;letter-spacing:.05em;color:var(--accent)}
  .card .cat::before{content:"";width:5px;height:5px;border-radius:50%;
      background:currentColor;flex-shrink:0}
  .card h3{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h6);line-height:1.3}
  /* długie tytuły ucinamy na trzeciej linii; pełny tytuł pokazuje podpowiedź (title) */
  .card h3 a{color:var(--text);display:-webkit-box;-webkit-line-clamp:3;
      -webkit-box-orient:vertical;overflow:hidden}
  .card:hover h3 a{color:var(--accent)}
  /* data publikacji pod nagłówkiem kafelka (artykuły własne), drobnym szarym pismem */
  .card .pubd{font-size:var(--fs-xs);color:var(--muted);margin-top:-4px}
  /* „Czytaj" z okrągłym szewronem zawsze w prawym dolnym rogu kafelka */
  .card .cardfoot{margin-top:auto;padding-top:var(--space-3);display:flex;
      justify-content:flex-end;font-size:12.5px}
  /* na stronie firmowej akcja wtórna to tekst plus mały OKRĄGŁY przycisk szewronu */
  .card .more{display:inline-flex;align-items:center;gap:10px;font-weight:400;
      color:var(--muted);white-space:nowrap}
  .card .more::after{content:"›";width:26px;height:26px;border-radius:50%;
      background:var(--cx-paper);border:1px solid var(--border-subtle);color:var(--cx-ink);
      display:inline-flex;align-items:center;justify-content:center;font-size:15px;
      line-height:1;transition:background .16s ease,border-color .16s ease}
  .card:hover .more{color:var(--text)}
  .card:hover .more::after{background:var(--cx-lime);border-color:var(--cx-lime)}
  /* klikalna cała karta: link tytułu rozciągnięty na kafelek (semantyka i klawiatura
     zostają przy odnośniku, a myszka trafia w każdy punkt karty) */
  .card h3 a::after{content:"";position:absolute;inset:0;border-radius:inherit}
  .card h3 a:focus-visible::after{outline:2px solid var(--accent);outline-offset:2px}
  .card p{font-size:13.5px;line-height:1.55;color:var(--muted);display:-webkit-box;
      -webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  mark{background:rgba(173,247,99,.45);border-radius:2px;padding:0 1px}
  /* Pusty stan stoi wprost na tle sekcji, bez płyty (decyzja 31): biała karta
     na jasnym pasie tylko dzieliła pustkę na dwie. */
  .noresults{text-align:center;padding:56px var(--space-5)}
  /* Jedna wielkość ilustracji pustego stanu w całym portalu - szukanie,
     produkt, kategoria, status. */
  .noresults .err404img{width:172px;height:auto;margin:0 auto var(--space-5)}
  .noresults h3{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h6);margin-bottom:6px}
  .noresults p{font-size:var(--fs-small);color:var(--muted);margin-bottom:var(--space-5)}
  .loadmore{display:flex;margin:26px auto 0}

  .crumbs{font-size:13px;color:var(--muted);padding:26px 0 0;animation:cxFade .4s ease forwards}
  .crumbs a{color:var(--muted)} .crumbs a:hover{color:var(--accent)}
  .crumbs .sep{margin:0 7px;opacity:.5}
  .crumbs .here{color:var(--text)}
  .chips{display:flex;flex-wrap:wrap;gap:9px;margin:0 0 26px;animation:cxFade .4s ease forwards}
  .chip{font-family:inherit;font-size:13.5px;font-weight:600;padding:var(--space-2) 15px;
      border-radius:var(--radius-pill);cursor:pointer;border:1px solid var(--line2);
      background:var(--cx-white);color:var(--body-fg);transition:all .16s ease}
  .chip:hover{border-color:var(--cx-lime);color:var(--cx-ink)}
  .chip.on{background:var(--cx-ink);border-color:var(--cx-ink);color:var(--cx-lime);font-weight:700}
  .chip small{opacity:.6;margin-left:3px;font-size:inherit}
  /* Chip ze znakiem produktu Work OS. Znaki monday.com mają własne kolorowe tło,
     więc czytają się i na białym chipie, i na zaznaczonym - dostają tylko stały
     rozmiar i zaokrąglenie. Na wąskim ekranie chip i tak zawija się w kolejny rząd. */
  .chip--znak{display:inline-flex;align-items:center;gap:9px;padding-left:6px}
  /* Chip „Nie wiem" ma sie ODROZNIAC od odpowiedzi (prosba Radka 29.09):
     to nie jest szosty plan monday.com, tylko przyznanie sie, ze sie nie wie.
     Dlatego kreskowany obrys i przygaszone pismo, a przed nim odstep - zeby
     oko od razu widzialo, ze konczy sie lista, a zaczyna wyjscie awaryjne.
     Zaznaczony robi sie pelny jak kazdy inny, bo wtedy JEST odpowiedzia. */
  .chip--niewiem{border-style:dashed;color:var(--soft);margin-left:var(--space-3)}
  .chip--niewiem:hover{border-color:var(--cx-ink-20);color:var(--body-fg)}
  .chip--niewiem.on{border-style:solid}
  @media (max-width:520px){ .chip--niewiem{margin-left:0} }

  .chip--znak img{width:26px;height:26px;flex:0 0 auto;display:block;
      border-radius:8px;object-fit:contain}

  .artwrap{display:grid;grid-template-columns:minmax(0,1fr) 240px;gap:36px;align-items:start;
      margin:18px 0 10px;animation:cxUp .45s ease forwards}
  /* Dokument bez kolumny bocznej (regulamin) - na pełną szerokość, bez pustego
     pasa po prawej po wyłączonym spisie/powiązanych. */
  .artwrap--solo{grid-template-columns:minmax(0,1fr);max-width:860px;margin-left:auto;margin-right:auto}
  /* Zagnieżdżona lista literowa (a./b./c.) w regulaminie: numeracja literowa
     ustawiona inline w widoku, tu tylko oddech nad/pod. */
  .doc--prawny .reglit{margin:var(--space-2) 0 var(--space-3)}
  /* min-width:0 jest konieczne: bez niego element gridu przyjmuje minimalną szerokość
     swojej treści (najdłuższa linia kodu, szeroka tabela) i artykuł wychodzi za ekran */
  article.doc{position:relative;min-width:0;background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-2xl);padding:40px 46px;box-shadow:var(--shadow-sm)}
  .docapp{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;font-weight:700;
      text-transform:uppercase;letter-spacing:.05em;color:var(--accent);margin-bottom:var(--space-3)}
  .docapp::before{content:"";width:5px;height:5px;border-radius:50%;background:currentColor}
  article.doc h1.doctitle{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h3);
      line-height:var(--lh-tight);letter-spacing:-.01em;color:var(--text)}
  /* Pastylki z kategoriami pod tytułem - jak na support.monday.com. Obwódka
     zamiast wypełnienia, bo stoją tuż pod dużym tytułem i plama koloru
     przeciągałaby na siebie uwagę, która należy się nagłówkowi. */
  .docchipy{display:flex;flex-wrap:wrap;gap:var(--space-2);margin:var(--space-4) 0 0}
  .docchip{display:inline-flex;align-items:center;padding:5px 14px;
      border:1px solid var(--cx-ink-20);border-radius:999px;font-size:13px;
      line-height:1.2;color:var(--text);text-decoration:none;
      transition:border-color .16s ease,background .16s ease}
  a.docchip:hover{border-color:var(--cx-ink-60);background:var(--cx-mist)}
  .docchip--gluchy{color:var(--cx-ink-80);cursor:default}
  .docmeta{font-size:13px;color:var(--soft);margin:var(--space-3) 0 28px;padding-bottom:22px;
      border-bottom:1px solid var(--line);min-height:1px}
  /* Notka nad artykułem zdjętym przez monday.com z dokumentacji. Ma być
     widoczna, ale nie krzyczeć - to nie awaria, tylko informacja o wieku
     tekstu. Stąd pasek z boku zamiast ramki i tła w kolorze ostrzeżenia. */
  .docarch{margin:0 0 26px;padding:12px 16px;border-left:3px solid var(--cx-ink-20);
      background:var(--cx-mist);border-radius:0 var(--radius-md) var(--radius-md) 0;
      font-size:13.5px;line-height:1.6;color:var(--soft)}
  .docbody{font-size:var(--fs-body);line-height:1.75;color:var(--body-fg)}
  .docbody h1,.docbody h2{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h5);
      margin:30px 0 var(--space-3);color:var(--text)}
  .docbody h1,.docbody h2,.docbody h3,.docbody h4,.docbody h5,.docbody h6{scroll-margin-top:96px}
  .docbody h3{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h6);
      margin:22px 0 10px;color:var(--text)}
  .docbody h4{font-family:var(--font-display);font-weight:400;font-size:var(--fs-body);
      margin:18px 0 var(--space-2);color:var(--text)}
  .docbody p{margin:var(--space-3) 0}
  .docbody ul,.docbody ol{margin:var(--space-3) 0 var(--space-3) var(--space-5)}
  .docbody li{margin:5px 0}
  /* odnośniki w treści artykułu: 4,3:1 to o włos za mało przy 16 px */
  .docbody a{color:var(--cx-ink-60);text-decoration:underline;text-decoration-color:var(--cx-ink-20)}
  /* w centrum pomocy monday.com nagłówki bywają zawinięte w odnośnik-kotwicę
     (spis treści Zendeska) - podkreślony, kolorowy nagłówek wyglądał jak błąd */
  .docbody :is(h1,h2,h3,h4,h5,h6) a{text-decoration:none;color:inherit}
  .docbody :is(h1,h2,h3,h4,h5,h6) a:hover{color:var(--accent)}
  /* Baner kursu na telefonie jest PRZENOSZONY do .docbody (ukladArtykuluNaWasko,
     decyzja 30.09: baner za pierwszy blok treści). Tam dziedziczył reguły
     odnośników treści: ciemny `--cx-ink-60` i podkreślenie. Z ghostowego guzika
     „Kup kurs" robiło to ciemny tekst na ciemnym banerze (kontrast ~1,2:1 -
     wyglądał na wyłączony), a oba guziki dostawały podkreślenie. Przywracamy im
     własny wygląd. Specyficzność `.docbody .kursban .kursbanmore` (0,3,0) bije
     `.docbody a` (0,2,1); dla podkreślenia `.docbody .kursban a` (0,2,1) stoi
     PÓŹNIEJ, więc wygrywa remis. Dotyczy TYLKO banera (`.kursban`); karta
     w kolumnie bocznej (`.kursside`) nie wchodzi do `.docbody`. */
  .docbody .kursban a{text-decoration:none}
  .docbody .kursban .kursbanmore{color:#F4F9F8}
  .docbody img{max-width:100%;height:auto;border:1px solid var(--line);
      border-radius:var(--radius-md);margin:var(--space-3) 0;cursor:zoom-in;
      transition:box-shadow .18s ease,transform .18s ease}
  .docbody img:hover{box-shadow:var(--shadow-md);transform:scale(1.005)}
  /* Obrazek, którego monday.com już nie ma (decyzja Radka 30.09: chowamy).
     `display:none`, a nie `visibility` czy `opacity`: te dwa zostawiają po
     obrazku miejsce, czyli dokładnie tę dziurę w tekście, którą chcemy
     usunąć. Klasa ląduje też na akapicie, gdy nie było w nim nic poza tym
     obrazkiem - inaczej po ukryciu zostaje pusty `<p>` z odstępem.
     Zakładać ją wolno WYŁĄCZNIE po zdarzeniu `error`, nigdy „na wszelki
     wypadek": ukryty obrazek, który dałoby się pokazać, jest gorszy od
     pękniętej ikonki, bo nikt się o nim nie dowie. */
  .docbody .imgbrak{display:none}

  /* miejsce na zrzut ekranu - szare pole z podpisem pod nim. Agent AI zapisuje
     „[ZRZUT: co ma być widoczne]", konsultant podmienia to na prawdziwy obrazek. */
  .docbody .shot-ph{margin:18px 0}
  .docbody .shot-ph-box{display:flex;align-items:center;justify-content:center;
      min-height:170px;background:var(--cx-mist);border:2px dashed var(--line2);
      border-radius:var(--radius-md);color:var(--soft)}
  .docbody .shot-ph figcaption,.docbody figcaption{margin-top:var(--space-2);font-size:13.5px;
      line-height:1.5;color:var(--muted);font-style:italic}
  /* obrazek zastępczy wstawiony do monday doca wygląda w portalu tak samo */
  .docbody img[src*="zrzut-placeholder"]{border-style:dashed;cursor:default}
  .docbody img[src*="zrzut-placeholder"]:hover{box-shadow:none;transform:none}

  /* ── komponenty przeniesione z MDX Readme.io (build_portal.py, readme_mdx_to_html) ── */
  /* <Callout theme="…"> - ramka z ikoną; motywy Readme: info, warn, error, okay */
  /* Kotwica sekcji: pusty znacznik tuż przed nagłówkiem. `scroll-margin-top`
     odsuwa cel skoku spod paska nawigacji - bez tego nagłówek, do którego
     prowadzi odsyłacz, chowa się za nim. */
  .docbody .kot{display:block;height:0;scroll-margin-top:90px}
  .docbody .callout{position:relative;margin:18px 0;padding:var(--space-4) var(--space-5);
      border:1px solid var(--line);border-left:3px solid var(--cx-ink-20);
      border-radius:var(--radius-md);background:var(--cx-mist)}
  /* `:first-child` w ramce to KÓŁKO Z IKONĄ, nie tekst - więc reguła zdejmująca
     górny odstęp nie dotykała pierwszego akapitu. Ramka rosła o jego margines,
     tekst zjeżdżał 15 px niżej niż ikona i całość wyglądała, jakby ikona uciekła
     do góry. Drugi selektor bierze to, co stoi zaraz za kółkiem. */
  .docbody .callout>:first-child,
  .docbody .callout>.cico+*{margin-top:0}
  .docbody .callout>:last-child{margin-bottom:0}
  /* `padding-top` wyrównuje ZNAK, nie kółko: emoji rysują się wysoko w swoim
     wierszu (odsadka górna kroju jest większa od dolnej), więc wyśrodkowanie
     wiersza przez `align-items:center` zostawiało piorun o 1,5 px nad środkiem
     kółka - przy 26 px widać to gołym okiem. Przeglądarka przyciąga wiersz
     do pełnych pikseli, więc dobieramy parę wartości, nie liczymy jej:
     14 px znaku z 2 px odsadki daje odchyłkę 0,18 px zamiast 1,47 px
     (zmierzone na zrzucie w skali 8x, po środku ciężkości tuszu). */
  .docbody .callout .cico{position:absolute;top:var(--space-3);left:-14px;width:26px;height:26px;
      border-radius:50%;background:var(--cx-white);border:1px solid var(--line);
      display:flex;align-items:center;justify-content:center;font-size:14px;line-height:1;
      padding-top:2px}
  .docbody .callout--warn{border-left-color:var(--cx-yellow)}
  .docbody .callout--error{border-left-color:#df2f4a}
  .docbody .callout--okay{border-left-color:var(--cx-green)}
  .docbody .callout--info{border-left-color:var(--cx-ink-20)}
  /* Ramka planów („Who can use this feature") - jedyna ramka z układem, a nie
     samym akapitem: tytuł, a pod nim osobne wiersze z ikonami, jak na
     support.monday.com. Kółka z piorunem z lewej tu NIE MA - piorun stoi przy
     wierszu o planach i drugi raz przy krawędzi znaczyłby to samo dwa razy. */
  .docbody .callout--plany{padding-left:var(--space-5)}
  .docbody .plantyt{margin:0 0 var(--space-2);font-weight:700}
  .docbody .planlista{list-style:none;margin:0;padding:0;
      display:flex;flex-direction:column;gap:var(--space-1)}
  .docbody .planwiersz{display:flex;align-items:flex-start;gap:var(--space-2);margin:0;
      padding:0}
  .docbody .planwiersz::before{content:none}
  /* Ikona ma nie kurczyć się przy długim wierszu i ma stać w linii pisma,
     nie na środku wiersza - stąd `margin-top`, a nie `align-items:center`. */
  .docbody .planik{flex:0 0 18px;width:18px;height:18px;margin-top:2px;
      color:var(--cx-ink-60)}
  .docbody .planik svg{display:block;width:18px;height:18px}
  /* <Cards>/<Card> - lista odnośników do powiązanych stron dokumentacji */
  .docbody .cardlist{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));
      gap:var(--space-3);margin:18px 0}
  .docbody .cardlink{display:flex;flex-direction:column;gap:var(--space-1);
      padding:var(--space-4);background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-md);text-decoration:none;transition:border-color .16s ease}
  .docbody .cardlink:hover{border-color:var(--cx-lime)}
  .docbody .cardlink b{color:var(--text);font-size:14.5px;line-height:1.35}
  .docbody .cardlink span{color:var(--muted);font-size:13px;line-height:1.45}
  /* <Tabs>/<Tab> - bez JS-a w treści: każda zakładka zostaje sekcją z nagłówkiem */
  .docbody .tabsec{margin:var(--space-4) 0}
  .docbody h4.tabh{color:var(--accent);text-transform:uppercase;letter-spacing:.04em;
      font-family:var(--font-body);font-size:11.5px;font-weight:700;margin:18px 0 var(--space-2)}
  /* <Accordion> */
  .docbody details.acc{margin:var(--space-3) 0;padding:var(--space-3) var(--space-4);
      border:1px solid var(--line);border-radius:var(--radius-md);background:var(--cx-white)}
  .docbody details.acc>summary{cursor:pointer;font-weight:700;color:var(--text)}
  .docbody details.acc[open]>summary{margin-bottom:var(--space-3)}

  /* filmy instruktażowe (YouTube) - kafle generowane w build_portal.py (embed_videos) */
  .docbody .vid{display:inline-block;vertical-align:top;width:318px;max-width:100%;
      margin:10px var(--space-4) var(--space-5) 0;border:1px solid var(--line);
      border-radius:var(--radius-lg);overflow:hidden;background:var(--cx-white);
      box-shadow:var(--shadow-xs);transition:box-shadow .18s ease,transform .18s ease}
  .docbody .vid:hover{box-shadow:var(--shadow-md);transform:translateY(-2px)}
  .docbody .vidthumb{position:relative;display:block;aspect-ratio:16/9;
      background:var(--hero);cursor:pointer}
  .docbody .vidthumb img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
      margin:0;border:none;border-radius:0;cursor:pointer;transition:none}
  .docbody .vidthumb img:hover{box-shadow:none;transform:none}
  /* znacznik YouTube - film otwiera się w nowej karcie. Portal jest publiczny,
     a osadzony odtwarzacz dokłada ciasteczka i skrypty obcej domeny. */
  .docbody .vidplay{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
      width:62px;height:44px;border-radius:var(--radius-md);background:#ff0033;
      box-shadow:var(--shadow-md);transition:transform .18s ease}
  .docbody .vidplay::after{content:"";position:absolute;top:50%;left:54%;
      transform:translate(-50%,-50%);border-style:solid;border-width:9px 0 9px 15px;
      border-color:transparent transparent transparent var(--cx-white)}
  .docbody .vid:hover .vidplay{transform:translate(-50%,-50%) scale(1.08)}
  .docbody .vidcap{padding:11px var(--space-4) 13px;font-size:13.5px;font-weight:600;
      line-height:1.4;color:var(--text);min-height:78px;cursor:pointer}
  .docbody .vidcap::after{content:"Otwórz w YouTube ↗";display:block;margin-top:6px;
      font-size:11.5px;font-weight:700;color:var(--accent)}
  @media(max-width:560px){ .docbody .vid{width:100%;margin-right:0} }
  .docbody table{border-collapse:collapse;margin:var(--space-4) 0;width:100%;max-width:100%;
      display:block;overflow-x:auto;font-size:var(--fs-small)}
  .docbody th,.docbody td{border:1px solid var(--line);padding:var(--space-2) var(--space-3);
      text-align:left;vertical-align:top}
  .docbody th{background:var(--cx-mist);font-weight:700;color:var(--text)}
  .docbody code{background:var(--cx-paper);border:1px solid var(--line);border-radius:var(--radius-xs);
      padding:1px 5px;font-family:var(--font-mono);font-size:.88em}
  /* podpis nad blokiem kodu - Readme.io trzyma go w otwarciu fence'a (```shell Terminal) */
  .docbody .codecap{margin:var(--space-4) 0 -10px;font-size:11.5px;font-weight:700;
      text-transform:uppercase;letter-spacing:.04em;color:var(--soft)}
  .docbody pre{background:var(--cx-ink);color:var(--cx-mist);border-radius:var(--radius-sm);
      padding:var(--space-4);overflow-x:auto;max-width:100%;margin:var(--space-4) 0;
      font-size:13px;line-height:1.6}
  .docbody pre code{background:none;border:none;padding:0;color:inherit}
  .docactions{display:flex;align-items:center;gap:var(--space-4);margin-top:34px;
      padding-top:var(--space-5);border-top:1px solid var(--line);flex-wrap:wrap}
  .docactions .src{font-size:13px;color:var(--soft)}
  aside.artside{position:sticky;top:92px;background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-lg);padding:22px}
  .sideh{font-size:11.5px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;
      color:var(--soft);margin-bottom:var(--space-3)}
  .votes{display:flex;gap:var(--space-2);margin-bottom:22px}
  .votes button{flex:1;padding:10px;border:1px solid var(--line2);background:var(--cx-mist);
      border-radius:11px;cursor:pointer;font-size:17px;font-family:inherit;
      transition:border-color .15s,background .15s}
  .votes button.up:hover{border-color:var(--cx-lime);background:var(--accent-soft)}
  .votes button.down:hover{border-color:#f0a0a0;background:#fdf0f0}
  .votethx{font-size:13px;color:var(--cx-ink-10);margin:-12px 0 var(--space-5)}
  .rel{display:flex;flex-direction:column;gap:2px}
  .rel a{text-align:left;padding:9px 0;border-bottom:1px solid var(--line);font-size:13.5px;
      line-height:1.4;color:var(--body-fg);transition:color .15s}
  /* Ostatni odnośnik bez kreski pod spodem - kończył listę separatorem
     donikąd (paczka 16.09). */
  .rel a:last-child{border-bottom:0;padding-bottom:0}
  .rel a:hover{color:var(--accent)}

  .cta{background:var(--cx-lime-soft);text-align:center;padding:64px var(--space-6);
      margin-top:52px;border-top:1px solid var(--line2)}
  .cta h2{font-family:var(--font-display);font-weight:400;font-size:var(--fs-h3);
      letter-spacing:-.01em;color:var(--text)}
  .cta p{color:var(--body-fg);margin:var(--space-3) 0 26px;font-size:var(--fs-body)}
  .cta .btn{font-size:15px;height:52px;padding:4px 4px 4px 26px}
  .cta .btn .chev{width:44px;height:44px}

  body>footer{background:var(--cx-ink);color:var(--on-dark);padding:52px var(--space-6) 0;
      font-size:var(--fs-small)}
  .fgrid{display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr;gap:40px;
      padding-bottom:36px;max-width:1180px;margin:0 auto}
  .fbrand{display:flex;align-items:center;width:fit-content;margin-bottom:var(--space-4);
      color:var(--cx-lime)}
  .fbrand .cx-logo{height:24px;width:auto;display:block}
  footer h4{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;
      color:var(--on-dark-soft);margin-bottom:var(--space-3)}
  footer p{font-size:var(--fs-small);line-height:1.65;color:var(--on-dark-muted);max-width:360px}
  footer ul{list-style:none;display:flex;flex-direction:column;gap:9px}
  footer ul a{color:var(--on-dark-muted)} footer ul a:hover{color:var(--cx-lime)}
  .socials{display:flex;gap:10px;margin-top:18px}
  .socials a{display:flex;align-items:center;justify-content:center;width:34px;height:34px;
      border:1px solid var(--cx-ink-60);border-radius:50%;transition:background .15s,border-color .15s}
  .socials a:hover{background:rgba(173,247,99,.14);border-color:var(--cx-lime)}
  .socials svg{width:15px;height:15px;fill:var(--on-dark-muted)}
  .socials a:hover svg{fill:var(--cx-lime)}
  .copy{border-top:1px solid var(--cx-ink-60);text-align:left;padding:22px 0;font-size:13px;
      color:var(--on-dark-soft);max-width:1180px;margin:0 auto}

  .spin{text-align:center;color:var(--muted);padding:50px 0}

  /* Tryb panelu zgłoszeń: aplikacja panelu ma własny nagłówek, stopkę i własny
     arkusz, więc portal chowa swoje ramy i oddaje jej całą stronę. Jej arkusz
     wjeżdża osobnym <link> dopiero przy montowaniu i wyłącza się przy wyjściu -
     inaczej jego reguły (m.in. `.kb`) mieszałyby się z portalem. */
  /* Panel zgłoszeń dostaje ramy portalu: NASZ nagłówek i NASZA stopka zostają,
     znika to, co należy do bazy wiedzy (widok, pasek sekcji, podpowiedzi), oraz
     własny nagłówek i stopka aplikacji panelu - inaczej strona miała dwa
     nagłówki i dwie stopki. */
  /* Aplikacja panelu ma własny guzik do swojej bazy wiedzy - w portalu baza
     wiedzy jest całą resztą serwisu i stoi w pasku, więc ten guzik dubluje
     nawigację i prowadzi do innej, starszej treści. */
  /* Wezwanie do zgłoszenia nie ma czego dodać komuś, kto już jest w panelu */
  /* aplikacja liczyła na własny, przyklejony nagłówek - po jego zdjęciu
     treść potrzebuje oddechu pod naszym paskiem */
      /* aplikacja liczyła sobie pełną wysokość okna na własny nagłówek i stopkę;
         u nas ma nad sobą pasek portalu, więc zostawiona `100vh` robiła pod
         treścią pusty pas i niepotrzebny suwak */
  /* TU STAŁA OSIEROCONA DEKLARACJA `min-height:0}` - została po sprzątaniu
     stylów dawnej apki panelu i przyjechała razem z rozbiciem szablonu.
     Kosztowała NASTĘPNĄ regułę w pliku: parser czytał `min-height:0}` jako
     początek selektora, doklejał do niego `.lightbox` i całą regułę
     odrzucał jako niepoprawną. Skutki widać było w dwóch miejscach naraz
     i żadne nie wyglądało na problem z CSS-em: pod stopką stał pusty pas
     (podgląd obrazka bez `position:fixed` zostawał w układzie strony),
     a kliknięcie obrazka w artykule rozjeżdżało stronę zamiast otworzyć
     podgląd. */
  /* Ekran logowania bierze całą stronę: to jedno zadanie i ma własną,
     dwukolumnową kompozycję - menu portalu tylko by je rozpraszało. */

  /* `touch-action:manipulation` zdejmuje przeglądarce jej własne
     „dwukrotne stuknięcie = powiększ stronę". Bez tego na telefonie nasze
     powiększenie i powiększenie Safari biją się o ten sam gest, a `dblclick`
     przychodzi z opóźnieniem albo wcale. */
  .lightbox{display:none;position:fixed;inset:0;background:rgba(18,32,33,.82);
      backdrop-filter:blur(4px);z-index:200;
      padding:var(--space-5);animation:cxFade .18s ease forwards;
      touch-action:manipulation}
  .lightbox.open{display:flex}
  /* Centrowanie przez `margin:auto` na dziecku, a NIE przez `justify-content`
     na rodzicu - i to nie jest kaprys. Przy `justify-content:center` element
     szerszy od kontenera zostaje ucięty od LEWEJ i nie da się do tej krawędzi
     doprzewijać: przewijanie nie sięga przed początek zawartości. Widać to
     dopiero po powiększeniu szerokiego zrzutu, czyli w jedynym stanie, w którym
     to ma znaczenie. `margin:auto` centruje tak samo, a przy nadmiarze
     po prostu przestaje działać i zawartość zaczyna się od krawędzi. */
  .lbwrap{position:relative;display:inline-block;margin:auto;
      max-width:94vw;max-height:92vh}
  .lbwrap img{display:block;max-width:94vw;max-height:92vh;width:auto;height:auto;
      border-radius:10px;box-shadow:var(--shadow-xl);background:var(--cx-white);
      animation:cxPop .22s ease forwards;cursor:zoom-in}

  /* ── Powiększenie: wysokość obrazka na cały ekran ──────────────────────
     Prośba Radka 30.09: dwukrotne kliknięcie ma powiększyć obrazek tak, żeby
     jego WYSOKOŚĆ wypełniła okno; drugie kliknięcie wraca do poprzedniego
     widoku. Bierze się to stąd, że zrzuty z monday.com są szerokie (ok. 16:9),
     a na telefonie ogranicza je SZEROKOŚĆ - więc na ekranie zostaje pasek
     wysoki na jedną trzecią i nie da się odczytać, co jest na obrazku.
     Po powiększeniu obrazek jest szerszy od ekranu i przewija się w poziomie. */
  .lightbox.zoom{padding:0;overflow:auto;-webkit-overflow-scrolling:touch}
  .lightbox.zoom .lbwrap{max-width:none;max-height:none}
  .lightbox.zoom .lbwrap img{max-width:none;max-height:none;
      height:100vh;height:100dvh;width:auto;border-radius:0;cursor:zoom-out;
      /* Bez tego animacja pojawienia odtwarza się przy KAŻDYM powiększeniu
         i obrazek podskakuje w trakcie przewijania. */
      animation:none}
  /* Krzyżyk ZOSTAJE na ekranie po powiększeniu (prośba Radka). W stanie
     zwykłym wisi na rogu `.lbwrap`, a ta po powiększeniu wyjeżdża poza ekran
     razem z obrazkiem - więc tutaj przypinamy go do OKNA. `.lightbox` jest
     `position:fixed`, ale to nie wystarcza: `position:absolute` liczyłby się
     względem przewijanej zawartości, nie względem widocznego kawałka. */
  .lightbox.zoom .lbx{position:fixed;top:12px;right:12px;z-index:3}
  .lbx{position:absolute;z-index:2;top:-14px;right:-14px;width:34px;height:34px;border-radius:50%;
      border:none;background:var(--cx-white);color:var(--cx-ink);font-size:19px;line-height:1;
      font-weight:700;cursor:pointer;box-shadow:var(--shadow-md);display:flex;align-items:center;
      justify-content:center;font-family:inherit;transition:transform .15s}
  .lbx:hover{transform:scale(1.08)}
  @media(max-width:600px){.lbx{top:8px;right:8px}}

  @media(max-width:900px){
    .fgrid{grid-template-columns:1fr 1fr}
    article.doc{padding:26px 22px}
    .artwrap{grid-template-columns:minmax(0,1fr)}
    aside.artside{position:static}
    .hero{padding:64px var(--space-5) 130px}
  }
  @media(max-width:600px){
    .fgrid{grid-template-columns:1fr}
    .nav{gap:var(--space-2);padding:var(--space-2) var(--space-4)}
    /* na telefonie menu i tak się łamie - zmniejszamy wszystko, żeby zmieściło się
       w dwóch rzędach, a nie w trzech z przyciskiem obok pojedynczego odnośnika */
    .brand .cx-logo{height:20px}
    nav.menu{gap:var(--space-3);margin-left:0;width:100%}
    nav.menu a{font-size:13px}
    nav.menu a.btn{margin-left:auto;height:38px;padding:3px 3px 3px var(--space-4);gap:var(--space-2);font-size:13px}
    nav.menu a.btn .chev{width:32px;height:32px}
    .panel{padding:var(--space-5)}
    article.doc{padding:var(--space-5) var(--space-4)}
    .hero h1{font-size:clamp(26px,8vw,34px)}
  }

  /* ══════════════════════════════════════════════════════════════════════
     NADPISANIA - PR „ramy strony i strona główna" (Claude Design)
     Stoją na końcu arkusza świadomie: w tym pliku pracuje równolegle Claude
     Code, więc diff ma być jednym blokiem. Wszystko powyżej to arkusz
     produkcyjny sprzed zmian, nietknięty.
     ══════════════════════════════════════════════════════════════════════ */
  /* ── znaki marki przeniesione ze strony firmowej ───────────────────────────
     Na cxlabs.digital tytuły pozycji stoją między dwoma szewronami (SVG 16×29,
     kolor #8BBDB8 - to dokładnie token --cx-ink-20), a nagłówki sekcji mają nad
     sobą „eyebrow": znak CXLABS plus szara etykieta. Trzymamy je jako maski CSS,
     żeby brały kolor z currentColor i nie puchły w markupie. */
  .cx-chev-l,.cx-chev-r{display:inline-block;width:9px;height:16px;flex:0 0 auto;
      background:currentColor}
  .cx-chev-l{-webkit-mask:url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2016%2029%27%3E%3Cpath%20d%3D%27M-2.18146e-06%2014.0535C0.0045718%2015.9288%200.672363%2017.8635%202.15888%2019.3866L9.90022%2028.0977L15.2197%2028.0977L5.00843%2016.4708L4.94668%2016.4022C4.26746%2015.6772%203.95414%2014.8516%203.95185%2014.0489C3.95185%2013.2462%204.26974%2012.4206%204.94668%2011.6956L5.00843%2011.627L15.2197%200.000127792L9.90022%200.000128257L2.16117%208.71114C0.674648%2010.232%200.00685648%2012.1667%200.00228282%2014.0443L0.00228282%2014.0558L-2.18146e-06%2014.0535Z%27%20fill%3D%27black%27/%3E%3C/svg%3E") no-repeat center/contain;
              mask:url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2016%2029%27%3E%3Cpath%20d%3D%27M-2.18146e-06%2014.0535C0.0045718%2015.9288%200.672363%2017.8635%202.15888%2019.3866L9.90022%2028.0977L15.2197%2028.0977L5.00843%2016.4708L4.94668%2016.4022C4.26746%2015.6772%203.95414%2014.8516%203.95185%2014.0489C3.95185%2013.2462%204.26974%2012.4206%204.94668%2011.6956L5.00843%2011.627L15.2197%200.000127792L9.90022%200.000128257L2.16117%208.71114C0.674648%2010.232%200.00685648%2012.1667%200.00228282%2014.0443L0.00228282%2014.0558L-2.18146e-06%2014.0535Z%27%20fill%3D%27black%27/%3E%3C/svg%3E") no-repeat center/contain}
  .cx-chev-r{-webkit-mask:url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2016%2029%27%3E%3Cpath%20d%3D%27M15.2197%2014.0442C15.2151%2012.1689%2014.5473%2010.2341%2013.0608%208.71101L5.31946%200L0%200L10.2113%2011.6269L10.273%2011.6955C10.9522%2012.4205%2011.2655%2013.246%2011.2678%2014.0488C11.2678%2014.8515%2010.9499%2015.6771%2010.273%2016.402L10.2113%2016.4706L0%2028.0975H5.31946L13.0585%2019.3865C14.545%2017.8657%2015.2128%2015.9309%2015.2174%2014.0533V14.0419L15.2197%2014.0442Z%27%20fill%3D%27black%27/%3E%3C/svg%3E") no-repeat center/contain;
              mask:url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2016%2029%27%3E%3Cpath%20d%3D%27M15.2197%2014.0442C15.2151%2012.1689%2014.5473%2010.2341%2013.0608%208.71101L5.31946%200L0%200L10.2113%2011.6269L10.273%2011.6955C10.9522%2012.4205%2011.2655%2013.246%2011.2678%2014.0488C11.2678%2014.8515%2010.9499%2015.6771%2010.273%2016.402L10.2113%2016.4706L0%2028.0975H5.31946L13.0585%2019.3865C14.545%2017.8657%2015.2128%2015.9309%2015.2174%2014.0533V14.0419L15.2197%2014.0442Z%27%20fill%3D%27black%27/%3E%3C/svg%3E") no-repeat center/contain}

  /* tytuł w szewronach - jak „❰ monday CRM ❱" w sekcji Usługi CXLABS */
  /* Kolor NIE stoi na otoczce. Szewrony mają swój (--cx-ink-20, prosto
     z cxlabs.digital), a sama nazwa dziedziczy go po elemencie, w którym
     stoi - raz jest to <b> kafla, raz <h3> sekcji, i każdy z nich wie
     lepiej, jakiego koloru ma być na swoim tle.

     Wcześniej otoczka malowała wszystko na szewronowy szary, a wewnętrzny
     <span> wracał na sztywno do --text (ciemny atrament). Na kaflu kategorii
     - ciemna karta rgb(22,36,37) na jasnej sekcji - dawało to kontrast
     1,05:1, czyli nazwę kategorii niewidoczną. `.app b` ustawiało tam biel,
     ale ten <span> ją zjadał. Po zmianie: 7,67:1 na kaflu, 13,0:1
     w nagłówku sekcji na jasnym tle. */
  .chevtitle{display:inline-flex;align-items:center;flex-wrap:nowrap;gap:10px;
      max-width:100%}
  .chevtitle>.cx-chev-l,.chevtitle>.cx-chev-r{color:var(--cx-ink-20)}
  .chevtitle>span{color:inherit;min-width:0;overflow:hidden;text-overflow:ellipsis;
      white-space:nowrap}

  /* eyebrow nad nagłówkiem sekcji */
  .eyebrow{display:inline-flex;align-items:center;gap:10px;margin-bottom:var(--space-3);
      font-size:var(--fs-small);color:var(--muted)}
  .eyebrow .cx-mark{color:var(--cx-ink-20);gap:1px}
  .eyebrow .cx-chev-l,.eyebrow .cx-chev-r{width:7px;height:13px}
  .eyebrow--on-dark{color:var(--cx-lime-soft)}
  .eyebrow--on-dark .cx-mark{color:var(--cx-lime)}

  /* znak CXLABS: dwa szewrony zwrócone do siebie, jak w hero strony firmowej */
  .cx-mark{display:inline-flex;align-items:center;gap:2px;color:var(--cx-lime)}
  .cx-mark .cx-chev-l,.cx-mark .cx-chev-r{width:15px;height:27px}

  *{margin:0;padding:0;box-sizing:border-box}
  body{font-family:var(--font-body);background:var(--surface-alt);color:var(--text);
       font-size:var(--fs-body);line-height:var(--lh-body);min-height:100vh;
       display:flex;flex-direction:column;-webkit-font-smoothing:antialiased}
  a{color:var(--accent);text-decoration:none} a:hover{color:var(--cx-ink)}
  ::selection{background:var(--cx-lime);color:var(--cx-ink)}
  h1,h2,h3.sg{font-family:var(--font-display);font-weight:400}
  .wrap{max-width:1180px;margin:0 auto;padding:0 var(--space-6);width:100%}
  @keyframes cxUp{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}
  @keyframes cxFade{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}
  @keyframes cxPop{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}
  @keyframes cxGlow{0%,100%{opacity:.5}50%{opacity:.9}}
  @media(prefers-reduced-motion:reduce){*{animation:none!important}}

  /* ── Nagłówek 1:1 z makiety cxlabs.digital/pl (plik „index (3)" od CXLABS):
     przezroczysty pasek NAD treścią hero, marka = znak + kreska + dwuwierszowy
     podpis partnera, odnośniki 16 px co 36 px, CTA w lime. Wariant ciemny
     (portal ma ciemne hero) bierze kolory z .hero--dark z tamtego pliku. */
  /* pasek „wersja rozwojowa" stoi nad wszystkim, więc nagłówek zaczyna się
     pod nim (--chrome), a nie na samej górze dokumentu */
  header.nav{position:relative;z-index:30;display:flex;
      align-items:center;justify-content:space-between;gap:clamp(16px,2.5vw,40px);
      padding:clamp(16px,2.4vh,24px) clamp(24px,4vw,64px);
      background:none;border:0;backdrop-filter:none;-webkit-backdrop-filter:none}
  .nav__brand{display:flex;align-items:center;gap:20px;text-decoration:none}
  .nav__logo{height:18px;width:auto;display:block;color:var(--cx-mist)}
  .nav__partner{display:flex;flex-direction:column;gap:1px;line-height:1.2}
  .nav__partner-name{font-family:var(--font-body);font-weight:700;font-size:14px;
      color:var(--cx-mist)}
  .nav__partner-sub{font-size:12px;color:var(--cx-ink-20)}
  .nav__links{display:flex;align-items:center;flex-wrap:nowrap;gap:3px;
      list-style:none;margin:0;padding:0}
  /* Pozycje menu stoją w jednej linii także wtedy, gdy któraś ma ikonę:
     inline-flex z wyśrodkowaniem zamiast obrazka na linii pisma, przez który
     „Baza wiedzy" siedziała wyżej od reszty. */
  .nav__links>li{display:flex;align-items:center}
  /* Selektor celuje w BEZPOŚREDNIE dzieci pozycji listy. Panel produktów
     siedzi w `<li class="navdrop">`, więc `.nav__links a` łapało także
     wiersze menu rozwijanego - stąd brały one wysokość, padding i kolor
     podświetlenia z paska i nie zgadzały się z resztą panelu. */
  .nav__links>li>a,.nav__links>li>.navdropbtn{display:inline-flex;align-items:center;
      line-height:1.18}
  .nav__links>li>a{font-family:var(--font-body);font-size:16px;white-space:nowrap;color:var(--cx-mist);
      text-decoration:none;transition:color 150ms ease}
  /* Podświetlenie pozycji paska: płytka przenika (fade), bez pulsowania
     i bez zaokrągleń, na całą wysokość guzika „Nowe zgłoszenie" - dzięki
     temu pasek ma jedną linię podstawy, a nie dwie. Ten sam kolor niosą
     oba piętra menu rozwijanego. Aktywna pozycja trzyma płytkę na stałe,
     więc widać, gdzie się jest, a nie tylko gdzie stoi kursor. */
  .nav__links>li{position:relative}
  .nav__links>li>a,.nav__links>li>.navdropbtn{height:var(--nav-h);padding:0 12px;border-radius:0;
      transition:background-color .22s ease,color .22s ease}
  .nav__links>li>a:hover,.nav__links>li>.navdropbtn:hover,
  .nav__links>li>a:focus-visible,.nav__links>li>.navdropbtn:focus-visible{
      color:var(--cx-white);background-color:var(--nav-hover)}
  .nav__links>li:has(a[aria-current="page"])>a,
  .nav__links>li:has(.navdropbtn[aria-current])>.navdropbtn{background-color:var(--nav-hover)}
  /* Ruch daszka („Icon Down") stoi przy regułach menu rozwijanego, niżej. */
  @keyframes navIconDown{0%{transform:translateY(0)}50%{transform:translateY(5px)}100%{transform:translateY(0)}}
  @media (prefers-reduced-motion: reduce){
    .nav__links>li>a:hover,.nav__links>li>.navdropbtn:hover,
    .nav__links>li>a:focus-visible,.nav__links>li>.navdropbtn:focus-visible{animation:none}
  }
  .navico{width:16px;height:15px;flex:none;margin-right:8px;color:var(--cx-white)}
  .nav__cta{display:inline-flex;align-items:center;height:var(--nav-h);padding:0 24px;
      border-radius:var(--radius-md);background:var(--cx-lime);color:var(--cx-ink);
      font-family:var(--font-body);font-size:16px;text-decoration:none;
      transition:filter 150ms ease,transform 120ms ease}
  .nav__cta:hover{filter:brightness(.96);color:var(--cx-ink)}
  .nav__cta:active{transform:translateY(1px)}
  /* Na telefonie odnośniki stopki miały 19 px wysokości - palec potrzebuje
     więcej. Sam odstęp, bez zmiany wyglądu na desktopie. */
  @media(max-width:600px){
    footer .fcol a,footer ul a{display:inline-block;padding:7px 0}
  }
  @media(max-width:760px){
    header.nav{padding:16px 22px}
    /* Menu ZOSTAJE także na telefonie - w dwóch rzędach mieści się bez
       chowania pozycji. Dawniej znikało tu w całości i portal tracił
       nawigację na najczęstszej szerokości ekranu. */
    .nav__divider,.nav__partner{display:none}
  }

  .btn{height:44px;font-size:14.5px;font-weight:600;border-radius:var(--radius-md);
      padding:3px 3px 3px var(--space-5);gap:var(--space-3)}
  .btn .chev{width:38px;height:38px;border-radius:var(--radius-sm);font-size:15px}
  .btn--ghost{border-radius:var(--radius-md);padding:11px var(--space-5)}

  /* ── hero: radialny gradient jak w komponencie Hero, kable w lime, jeden cel */
  /* ── Strona jak prezentacja: jedna sekcja = jeden ekran ─────────────────
     --chrome to zmierzona wysokość paska „wersja rozwojowa" i nagłówka
     (ustawia ją initDeck w JS, bo obie są zmienne - pasek znika w produkcji,
     a nagłówek rośnie przy zawijaniu menu). Sekcja ma min-height, nie height:
     gdy treści jest więcej niż ekran (lista dziesięciu artykułów na niskim
     oknie), sekcja rośnie zamiast chować treść. */
  :root{--chrome:0px}
  #view>.hero,#view>.band{min-height:calc(100svh - var(--chrome));
      display:flex;flex-direction:column;justify-content:center;
      scroll-snap-align:start;
      /* „normal", nie „always": przy „always" przeglądarka wymuszała pełny
         gest na każdą sekcję i powrót do wyszukiwarki był ciężki */
      scroll-snap-stop:normal}
  #view>.hero{padding:clamp(24px,4vh,56px) 0 clamp(40px,6vh,80px);
      text-align:center;
      /* zaczep pierwszej sekcji obejmuje pasek „wersja rozwojowa": bez tego
         silnik snapu parkował hero przy górnej krawędzi i pasek - z informacją
         o stanie indeksu i trybie noindex - był nieosiągalny */
      scroll-margin-top:var(--chrome,0px)}
  #view>.band{padding:clamp(28px,4.5vh,64px) 0}
  /* tło i kolory hero (zgubione przy przebudowie na sekcje pełnoekranowe) */
  #view>.hero{color:var(--on-dark);
      background:radial-gradient(ellipse 120% 90% at 50% 34%,rgb(36,58,58) 0%,var(--cx-ink) 72%)}
  #view>.hero h1{color:var(--cx-white)}
  #view>.hero h1 em{color:var(--cx-lime);font-style:normal}
  #view>.hero p.sub{color:var(--cx-lime-soft)}
  .hero .inner{width:100%}
  #view>.band,#view>.wrap{position:relative;z-index:1}
  #view>.wrap{background:var(--bg)}
  /* Zaczepy przewijania włączamy TYLKO tam, gdzie są sekcje-ekrany, czyli na
     stronie głównej. Wcześniej reguła obejmowała cały portal i na widoku
     artykułu jedynym zaczepem zostawała stopka - przeglądarka od razu
     ściągała widok na sam dół i nie dało się wrócić w górę.

     Rozpoznanie „to strona główna" szło przez `html:has(#view>.band)`. Warunek
     jest poprawny, ale ZAWODNY: router wymienia wnętrze #view przez innerHTML,
     a przeglądarki różnie przeliczają `:has()` po takiej podmianie. Gdy
     przeliczenie nie nastąpi, na podstronie zostaje włączony snap, jedynym
     zaczepem jest stopka i strona zjeżdża na sam dół, a każda próba powrotu
     w górę wraca do stopki. Stan trzymamy więc sami, klasą `deck` na <html>
     (ustawia ją deckMode() przy każdej zmianie widoku) - bez zgadywania. */
  /* ── MAGNESU PRZEWIJANIA JUŻ NIE MA (polecenie Radka 1.10: „wyłączamy
     magnes przesuwający do sekcji na stronie głównej") ────────────────────
     Stało tu `html.deck{scroll-snap-type:y proximity}` razem z zaczepem na
     stopce. Układ sekcji-ekranów ZOSTAJE (`min-height:100svh`, wyśrodkowanie,
     `scroll-snap-align` na sekcjach) - znika wyłącznie przyciąganie, czyli to,
     co zabierało czytelnikowi kontrolę nad przewijaniem. Same `scroll-snap-align`
     bez `scroll-snap-type` na przodku nic nie robią, więc zostawiamy je
     nietknięte: gdyby magnes kiedyś wracał, wraca jedną linijką.
     Klasa `deck` zostaje i dalej jest zakładana przez `deckMode()` - inne
     reguły na niej stoją. */
  @media(max-width:700px){
    #view>.hero,#view>.band{min-height:0;padding:clamp(44px,7vh,72px) 0}
    html{scroll-snap-type:none}
  }
  /* krawędź nasuwającej się sekcji - cień robi widoczny „próg" */
  #view>.band--dark{box-shadow:0 -30px 60px rgba(0,0,0,.45)}
  @media(max-width:700px){
    .hero{min-height:auto;padding:clamp(56px,9vh,88px) 0 clamp(48px,8vh,72px);position:static}
  }
  .hero .inner{position:relative;z-index:1;max-width:1180px;margin:0 auto;
      padding:0 var(--space-6);display:flex;flex-direction:column;align-items:center}
  /* kanwa mózgu: pełne hero, ale wymaskowana od środka, żeby nagłówek
     i wyszukiwarka stały na czystym tle (kontrast > pokaz) */
  /* kanwa mózgu: wyśrodkowana za treścią. Krycie .55 - punkty są rzadkie
     i jasne tylko na grzbietach zakrętów, więc tekst zachowuje kontrast */
  .hero .brainbg{position:absolute;inset:0;width:100%;height:100%;z-index:0;
      opacity:.55;touch-action:pan-y}
  @media(prefers-reduced-motion:reduce){.hero .brainbg{opacity:.4}}
  .hero h1{font-size:clamp(32px,4.6vw,54px);max-width:19ch;letter-spacing:-.015em;line-height:1.08}
  .hero p.sub{margin:var(--space-4) auto 0;max-width:52ch;font-size:17.5px;line-height:1.6}
  .hero .eyebrow{margin-bottom:var(--space-4);justify-content:center}
  .search{margin:var(--space-6) auto 0;width:100%;max-width:640px;border-radius:var(--radius-md);
      padding:6px 6px 6px var(--space-5);box-shadow:0 16px 40px rgba(0,0,0,.28)}
  .search input{font-size:16px}
  /* guzik: waga 500 (600 było za gęste przy 14,5 px) i lupa inline SVG */
  .search button{display:inline-flex;align-items:center;gap:9px;border-radius:var(--radius-sm);
      padding:12px var(--space-5);font-size:14.5px;font-weight:500;letter-spacing:0}
  .search button svg{width:16px;height:16px;flex:none}
  .sugg{justify-content:center;align-items:center;margin-top:var(--space-4)}
  .sugg button{border-radius:var(--radius-sm)}
  .herostats{justify-content:center}
  .hero .search input{padding-left:0}
  /* natywny „×" w polu type=search kleił się do przycisku Szukaj */
  .search input::-webkit-search-cancel-button{margin-right:var(--space-3)}

  /* pasek liczb: duże cyfry w lime, jak stat-bloki design systemu */
  .herostats{display:flex;flex-wrap:wrap;gap:clamp(22px,4vw,60px);
      margin-top:clamp(34px,4vw,52px);padding-top:var(--space-5);
      border-top:1px solid var(--cx-ink-60)}
  .herostats div{display:flex;flex-direction:column;gap:3px}
  .herostats b{font-family:var(--font-display);font-weight:500;font-size:clamp(26px,3.4vw,38px);
      line-height:1;color:var(--cx-lime);letter-spacing:-.01em}
  .herostats span{font-size:12.5px;letter-spacing:.09em;text-transform:uppercase;
      color:var(--cx-ink-20)}

  /* ── sekcje: jasne bez ramki (koniec pudełka w pudełku), ciemne jako karta */
  .hubsec{padding:clamp(52px,6vw,84px) 0 0}
  .hubhead{margin-bottom:clamp(14px,2.2vh,26px)}
  .hubhead h2{font-size:clamp(26px,3vw,38px);font-weight:500;letter-spacing:-.015em}
  /* :not() bo nadpisanie stoi niżej niż .hubhead--on-dark p o tej samej
     specyficzności - bez tego --muted wygrywało na ciemnym tle (2,4:1) */
  .hubhead:not(.hubhead--on-dark) p{font-size:15.5px;color:var(--muted)}
  .hubhead--on-dark p{font-size:15.5px}
  .pane{background:transparent;border:0;padding:0}
  .pane--brand{position:relative;overflow:hidden;background:var(--hero);
      border:1px solid var(--cx-ink-60);border-radius:var(--radius-2xl);
      padding:clamp(28px,3.4vw,44px)}

  /* ── ciemny pas: karty produktów na tle marki, jak sekcja „Wartość dodana"
     szablonu oferty - kolorowe obramowanie techniką padding-box/border-box */
  .band{padding:clamp(52px,6vw,84px) 0}
  .band--dark{background:var(--hero);color:var(--on-dark);border-top:1px solid var(--cx-ink-60);
      border-bottom:1px solid var(--cx-ink-60)}
  .band--dark .hubhead h2{color:var(--cx-white)}
  .band--dark .hubhead p{color:var(--cx-lime-soft)}
  .band .hubsec{padding:0}

  .apps{grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:clamp(10px,1.6vh,16px)}
  /* obramowanie kart: ten sam --cx-ink-60 co separatory na ciemnym tle
     (kolorowe gradienty były zbyt krzykliwe przy ośmiu kartach obok siebie) */
  .app{display:flex;flex-direction:column;align-items:stretch;
      padding:clamp(14px,2vh,20px) var(--space-5);border:1px solid var(--cx-ink-60);border-radius:var(--radius-lg);
      background:rgb(22,36,37);
      transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease}
  .app:hover,.app:focus-within{transform:translateY(-4px);
      box-shadow:0 16px 40px rgba(0,0,0,.35);border-color:var(--cx-ink-40)}
  .appmain{display:flex;flex-direction:column;align-items:flex-start;gap:clamp(10px,1.6vh,16px);
      flex:1 1 auto;text-decoration:none}

  /* rozwijana lista kategorii: grid 0fr → 1fr animuje wysokość bez znajomości
     jej wartości (max-height dawałoby skok przy różnej liczbie pozycji) */
  .appcats{display:grid;grid-template-rows:0fr;
      transition:grid-template-rows .26s ease,opacity .2s ease;opacity:0}
  .app:hover .appcats,.app:focus-within .appcats{grid-template-rows:1fr;opacity:1}
  .appcatsin{overflow:hidden;min-height:0}
  .appcatlist{display:flex;flex-direction:column;margin-top:var(--space-4);
      padding-top:var(--space-3);border-top:1px solid var(--cx-ink-60)}
  .appcat{display:flex;align-items:center;gap:var(--space-3);padding:7px 0;
      font-size:13.5px;color:var(--cx-lime-soft);text-decoration:none;line-height:1.35}
  .appcat span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .appcat small{margin-left:auto;flex:none;font-size:12px;color:var(--cx-ink-20)}
  .appcat:hover,.appcat:focus-visible{color:var(--cx-lime)}
  .appcat:hover small{color:var(--cx-lime)}
  .appcat--all{margin-top:2px;font-weight:600;color:var(--cx-white)}
  /* bez wskaźnika (dotyk, klawiatura z pominięciem karty) lista stoi otwarta -
     hover na ekranie dotykowym nie istnieje, a treść nie może być nieosiągalna */
  @media(hover:none){
    .appcats{grid-template-rows:1fr;opacity:1}
    .app:hover{transform:none}
  }
  .app .ic{display:grid;place-items:center;width:46px;height:46px;border-radius:10px;
      background:rgba(173,247,99,.14);color:var(--cx-lime);font-size:0;overflow:hidden}
  .app .ic svg{width:23px;height:23px}
  /* znak firmowy ma własne kolorowe tło - wypełnia płytkę, ta nie dokłada swojego.
     :has() z zapasem: .prodico wyłącza tło także tam, gdzie :has() nie działa */
  .app .ic:has(.prodico){background:none}
  .app .ic .prodico{width:100%;height:100%;display:block;object-fit:contain;
      border-radius:inherit;background:none}
  /* znak „API i aplikacje" jest czarny - na ciemnej karcie zlewałby się z tłem,
     więc płytka ze znakiem dostaje cienką obwódkę */
  .app .ic:has(.prodico){box-shadow:inset 0 0 0 1px rgba(219,236,233,.16)}
  .app .tx{display:flex;flex-direction:column;gap:var(--space-2)}
  .app b{font-family:var(--font-display);font-weight:500;font-size:20px;line-height:1.18;
      letter-spacing:-.01em;color:var(--cx-white)}
  /* selektory z .tx>span, bo bazowa reguła .app .tx>span (0,2,1) jest
     specyficzniejsza niż .app .cnt i ustawiała --muted (2,6:1 na ciemnym) */
  .app .tx>span.cnt{font-size:12px;font-weight:600;letter-spacing:.09em;
      text-transform:uppercase;color:var(--cx-ink-20);margin-top:0}
  /* Kafle kategorii (ekran produktu) nie mają klasy .cnt - ich wiersz z liczbą
     artykułów zostawał na --muted, czyli na kolorze dobranym pod JASNE tło.
     Na ciemnej karcie dawało to 2,64:1 przy 12,5 px, poniżej progu czytelności.
     Ten sam --cx-ink-20 co wyżej daje 7,67:1. Wyłączamy tytuł (ma własny kolor
     z nagłówka) i opis karty wiodącej (ma swój, limonkowy). */
  .app .tx>span:not(.chevtitle):not(.lead-desc):not(.cnt){color:var(--cx-ink-20)}
  .appmain .go{margin-top:auto;display:inline-flex;align-items:center;gap:7px;font-size:13.5px;
      font-weight:600;color:var(--cx-lime)}
  .app .go svg{width:13px;height:13px}

  /* karta wiodąca: cały rząd, układ poziomy, mocniejsza płytka ikony */
  .app--lead{grid-column:1/-1;padding:clamp(14px,2vh,20px) var(--space-6)}
  .app--lead .appmain{flex-direction:row;align-items:center;gap:var(--space-5)}
  /* karta wiodąca prowadzi do produktu zbiorczego - jego kategorie to cała
     taksonomia źródła, więc listy tu nie rozwijamy */
  .app--lead .appcats{display:none}
  .app--lead .ic{width:58px;height:58px;border-radius:12px;background:var(--cx-lime);
      color:var(--cx-ink);flex:none}
  .app--lead .ic svg{width:29px;height:29px}
  /* znak monday.com ma własne kolory - lime płytka pod nim nie wchodzi */
  .app--lead .ic:has(.prodico){background:none}
  .app--lead .tx{flex:1 1 auto;gap:7px}
  .app--lead b{font-size:clamp(20px,2.2vw,26px)}
  .app--lead .tx>span.lead-desc{font-size:14.5px;line-height:1.55;
      color:var(--cx-lime-soft);max-width:62ch;margin-top:0}
  .app--lead .go{margin:0;flex:none}

  /* ── tematy zostają na ciemnym: druga sekcja w tym samym pasie, oddzielona
     kreską zamiast karty (karta w karcie dawałaby pudełko w pudełku) */
  .hubsec--split{margin-top:clamp(20px,3vh,40px);padding-top:0}

  /* wejścia sekcji - każda inaczej, wszystkie raz i wszystkie na transformacie.
     Warianty: up (18 px w górę), left (24 px z lewej), zoom (98% → 100%),
     mask (odsłonięcie od góry). Element z data-plx ma transform zajęty przez
     dryf, więc jego wejście idzie tylko po kryciu i filtrze. */
  .rise:not(.is-settled){opacity:0;
      transition:opacity .7s ease,transform .8s cubic-bezier(.16,.84,.3,1),
      clip-path .85s cubic-bezier(.16,.84,.3,1),filter .7s ease}
  /* po wejściu element wraca pod własne reguły - żadnych resztkowych
     opóźnień ani ośmiusetmilisekundowych przejść na hoverze */
  .rise.is-settled{opacity:1;transform:none;clip-path:none;filter:none;transition-delay:0s}
  .rise--up{transform:translate3d(0,56px,0)}
  .rise--left{transform:translate3d(-72px,0,0)}
  .rise--zoom{transform:scale(.9)}
  .rise--flip{transform:perspective(900px) rotateX(9deg) translate3d(0,42px,0);
      transform-origin:50% 0}
  .rise--mask{clip-path:inset(0 0 100% 0)}
  /* Przycięcie zostaje TYLKO tam, gdzie jest czym animować - w wariancie
     „maska". Wcześniej `inset(0 0 0 0)` dostawał każdy element wejścia i
     zostawał z nim na stałe (`is-settled` stoi w arkuszu wyżej, więc przy
     równej wadze przegrywało): kafel podniesiony na hoverze tracił górną
     krawędź z obramowaniem, a cień był ucinany. Maska kończy na lekkim
     zapasie, żeby po odsłonięciu też niczego nie obcinała. */
  .rise.is-in{opacity:1;transform:none}
  .rise--mask.is-in{clip-path:inset(-6px)}
  .rise[data-plx]{transform:none}
  .rise[data-plx]:not(.is-in){filter:blur(2px)}
  @media(prefers-reduced-motion:reduce){
    .rise{opacity:1;transform:none;clip-path:none;filter:none;transition:none}
  }

  /* ── najczęściej czytane: lista dziesięciu wierszy na ciemnym pasie ─────
     Separatory na rgba(219,236,233,.08) zamiast --cx-ink-60: przy dziesięciu
     wierszach pełna kreska robiła z listy tabelę w kratkę. */
  .reads{list-style:none;margin:0;padding:0}
  .reads li+li{border-top:1px solid rgba(219,236,233,.08)}
  .read{display:grid;grid-template-columns:24px 20px minmax(0,1fr) auto;
      align-items:center;gap:var(--space-4);padding:11px var(--space-3);
      text-decoration:none;transition:background .16s ease}
  .read:hover{background:rgba(255,255,255,.04)}
  .readno,.readic{align-self:center}
  .readno{font-family:var(--font-mono);font-size:11.5px;color:var(--cx-ink-20);
      letter-spacing:.04em}
  .readic{width:20px;height:20px;border-radius:5px;overflow:hidden;
      display:grid;place-items:center;color:var(--cx-lime);font-size:0;
      box-shadow:inset 0 0 0 1px rgba(219,236,233,.16)}
  .readic svg{width:12px;height:12px}
  .readic .prodico{width:100%;height:100%;display:block;object-fit:contain}
  .readtx{min-width:0;display:flex;flex-direction:column;gap:3px;text-align:left}
  .readline{display:flex;align-items:baseline;gap:var(--space-3);min-width:0}
  .readtitle{font-size:14.5px;font-weight:600;line-height:1.4;color:var(--cx-white);
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .read:hover .readtitle{color:var(--cx-lime)}
  /* kategoria ustępuje tytułowi dopiero, gdy zabraknie miejsca w wierszu
     (flex-shrink), a nie na sztywnym limicie 22 znaków */
  .readcat{flex:0 1 auto;min-width:0;font-size:12px;color:var(--cx-ink-20);
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .readline .readtitle{flex:0 1 auto}
  /* zajawka przycięta do jednej linijki - wielokropek dokłada przeglądarka */
  .readlede{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
      font-size:13px;line-height:1.5;color:var(--cx-lime-soft)}
  /* data w wierszu tytułu, z ikoną kalendarza; biała, bo to jedyna twarda
     informacja w tej linii poza tytułem */
  .readdate{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:5px;
      font-family:var(--font-mono);font-size:11.5px;color:var(--cx-white)}
  .readdate svg{width:12px;height:12px}
  /* „Czytaj dalej" jako guzik w ciemnej zieleni marki (--cx-ink-80 na tle
     karty rgb(22,36,37)); w hoverze podnosi się do lime na ciemnym */
  .readgo{flex:none;display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
      padding:7px 13px;border-radius:var(--radius-sm);
      background:var(--cx-ink-80);border:1px solid var(--cx-ink-60);
      font-size:12.5px;font-weight:600;color:var(--cx-lime-soft);
      transition:background .16s ease,border-color .16s ease,color .16s ease}
  .readgo svg{width:12px;height:12px;transition:transform .16s ease}
  .read:hover .readgo{background:var(--cx-lime);border-color:var(--cx-lime);
      color:var(--cx-ink)}
  .read:hover .readgo svg{transform:translateX(2px)}
  @media(max-width:900px){
    .read{grid-template-columns:20px minmax(0,1fr) auto}
    .readno{display:none}
  }
  @media(max-width:600px){
    .read{grid-template-columns:20px minmax(0,1fr);gap:var(--space-3)}
    .readline{flex-direction:column;align-items:flex-start;gap:2px}
    /* w kolumnie dzieci nie kurczą się same - bez tego tytuł z `nowrap`
       rozpychał stronę poza ekran telefonu */
    .readline>*{max-width:100%}
    .readdate{margin-left:0}
    .readgo{display:none}
  }
  .hubsec--split .hubhead{margin-top:0}
  .band--dark .topic>span:last-child{color:var(--cx-ink-20)}
  .helprow:hover b{color:var(--accent-strong)}
  .app .go svg{width:13px;height:13px}

  /* ── tematy w ciemnej karcie: spis z numerem, nie kafelki */
  /* dwie kolumny, nie auto-fill: przy szerokim ekranie wchodziła trzecia
     i wiersze robiły się za krótkie, żeby dało się je czytać jak spis */
  .topics{grid-template-columns:repeat(2,minmax(0,1fr));gap:0 clamp(24px,4vw,56px)}
  .topic{flex-direction:row;align-items:baseline;gap:var(--space-4);padding:clamp(7px,1.1vh,12px) 0;
      background:none;border:0;border-radius:0;border-bottom:1px solid var(--cx-ink-60)}
  .topic:hover{background:none;transform:none;border-color:var(--cx-lime)}
  .topic .num{font-family:var(--font-mono);font-size:11.5px;color:var(--cx-lime);
      min-width:22px;letter-spacing:.04em}
  .topic b{font-family:var(--font-body);font-weight:600;font-size:15.5px;
      color:var(--cx-white);line-height:1.4}
  .topic:hover b{color:var(--cx-lime)}
  .topic>span:last-child{margin-left:auto;white-space:nowrap;font-size:13px;color:var(--cx-ink-20)}

  /* ── blok wsparcia: jasna lista odnośników + ciemna karta logowania */
  .helpwrap{grid-template-columns:minmax(0,1fr) minmax(0,.88fr);gap:clamp(24px,3vw,44px);
      align-items:start;padding:clamp(60px,7vw,96px) 0 clamp(72px,8vw,112px)}
  .helpwrap h2{font-size:clamp(26px,3vw,36px);font-weight:500;letter-spacing:-.015em}
  .helplead{margin-top:var(--space-3);max-width:44ch;font-size:15.5px;line-height:1.65;
      color:var(--muted)}
  .helpbox{background:var(--cx-white);border:1px solid var(--line2);
      border-left:3px solid var(--cx-lime);border-radius:var(--radius-lg);
      padding:var(--space-3) var(--space-5);gap:0;margin-top:var(--space-5);
      box-shadow:var(--shadow-xs)}
  .helprow{gap:var(--space-4);padding:var(--space-4) 0;border-radius:0;
      border-bottom:1px solid var(--line)}
  .helprow:last-child{border-bottom:0}
  .helprow:hover{background:none}
  .helprow .ico{display:grid;place-items:center;width:36px;height:36px;
      border-radius:var(--radius-sm);background:var(--cx-mist);color:var(--cx-ink);font-size:0}
  .helprow .ico svg{width:18px;height:18px}
  .helprow b{font-size:15px;font-weight:600}
  .helprow em{font-size:13.5px;line-height:1.55;color:var(--muted)}
  /* Strzałka na końcu wiersza: bez rozmiaru SVG rozpychał się na całą wysokość
     wiersza (290 px zamiast 16). Ikony w `.ico` mają swoją regułę, ta nie miała. */
  .helprow>svg{flex:0 0 auto;align-self:center;margin-left:auto;width:16px;height:16px;
      color:var(--cx-ink-20);transition:transform .16s ease,color .16s ease}
  .helprow:hover>svg{color:var(--cx-lime);transform:translateX(3px)}

  .loginbox{position:relative;overflow:hidden;border:1px solid var(--cx-ink-60);
      border-radius:var(--radius-2xl);padding:clamp(26px,3vw,36px);color:var(--on-dark);
      background:var(--hero)}
  .loginbox .eyebrow{margin-bottom:var(--space-3)}
  .loginbox h2{font-family:var(--font-display);font-weight:500;font-size:24px;
      color:var(--cx-white);letter-spacing:-.01em}
  .loginbox p{margin-top:var(--space-2);font-size:14px;line-height:1.6;
      color:var(--cx-lime-soft)}
  .loginnote{margin-top:var(--space-5);padding-top:var(--space-4);
      border-top:1px solid var(--cx-ink-60);font-size:13px;line-height:1.55;
      color:var(--cx-ink-20)}
  .loginnote a{color:var(--cx-lime-soft);text-decoration:underline}

  /* ── stopka: chudsza, żeby nie ważyła więcej niż treść */
  body>footer{padding:clamp(48px,5vw,64px) var(--space-6) 0}
  .fgrid{gap:clamp(28px,3vw,44px);padding-bottom:var(--space-6)}
  footer h4{font-size:11.5px;margin-bottom:var(--space-2)}
  footer p{font-size:13.5px;line-height:1.6;max-width:340px}
  footer ul{gap:8px}
  footer ul a{font-size:13.5px}
  .socials{margin-top:var(--space-4)}
  .socials a{width:30px;height:30px}
  .copy{padding:var(--space-4) 0;font-size:12px;line-height:1.6}

  /* poprawki kontrastu wyłapane na podglądzie: liczniki na jasnym szły --soft
     (2,8:1), metadane na ciemnym --cx-ink-40 (4,3:1); znak marki w eyebrow miał
     27 px, bo .cx-mark .cx-chev-* stoi niżej i wygrywał specyficznością */
  .eyebrow .cx-mark .cx-chev-l,.eyebrow .cx-mark .cx-chev-r{width:8px;height:15px}
  /* --on-dark-soft to 3,97:1 na tle hero - poniżej progu przy 13 px */
  .sugg .lbl{color:var(--cx-ink-20)}

  @media(max-width:900px){
    .helpwrap{grid-template-columns:minmax(0,1fr)}
    .apps{grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}
    .topics{grid-template-columns:minmax(0,1fr);gap:0}
  }
  @media(max-width:600px){
    /* karta wiodąca wraca do kolumny - w rzędzie kolumna .tx ściskała się
       do ~116 px i opis rozlewał się na trzy wyrazy w wierszu */
    .app--lead{flex-direction:column;align-items:flex-start;padding:var(--space-4)}
    .app--lead .ic{width:46px;height:46px}
    .app--lead .ic svg{width:23px;height:23px}
    .app--lead .go{margin-top:var(--space-2)}
    .hero .inner{padding:0 var(--space-4)}
    .hero h1{font-size:clamp(27px,7.4vw,34px);max-width:none}
    .hero .brainbg{opacity:.6}
    .search{padding:5px 5px 5px var(--space-4)}
    .search button{padding:12px var(--space-4)}
    .herostats{gap:var(--space-5) var(--space-6)}
    .apps{grid-template-columns:minmax(0,1fr)}
    .app{padding:var(--space-4)}
  }

  /* ── lockup marki 1:1 z navbar_container na cxlabs.digital/pl:
     znak CXLABS, pionowa kreska, sygnet partnera monday.com */
  .brandlock{display:flex;align-items:center;gap:var(--space-4);flex:none}
  /* podpis pod znakiem: pion wyrównany do wordmarku, więc lockup i podpis
     tworzą jeden blok, a kreska i sygnet partnera stoją obok niego */
  .brandlock>.brand{flex-direction:column;align-items:flex-start;gap:5px}
  /* znak rysuje się currentColor, a globalne a:hover ustawia --cx-ink -
     na ciemnym pasku logo po najechaniu znikało */
  .brand:hover,.brand:focus-visible{color:var(--cx-white)}
  .brand:hover .brandsub{color:var(--cx-lime)}
  .brand .brandsub{font-size:11.5px;letter-spacing:.06em;
      text-transform:uppercase;color:var(--cx-ink-20);white-space:nowrap}
  .nav{gap:var(--space-5)}
  nav.menu{gap:var(--space-5)}
  .brand .cx-logo{height:17px;width:auto;display:block}
  .brandsep{flex:none;width:1px;height:26px;background:var(--cx-ink-60)}
  .partner{display:flex;align-items:center;color:var(--cx-mist)}
  .partner .cx-partner{height:29px;width:auto;display:block}
  .fbrand .cx-logo{height:19px}
  @media(max-width:700px){
    .brandlock{gap:var(--space-3)}
    .brand .cx-logo{height:15px}
    .brandsep{height:22px}
    .partner .cx-partner{height:25px}
  }
  @media(max-width:430px){.brandsep,.partner{display:none}}

  /* ── menu „Zasoby" - układ z cxlabs.digital/pl ─────────────────────────── */
  .drop{position:static;display:flex}
  .dropbtn{display:inline-flex;align-items:center;gap:6px;padding:0;border:0;background:none;
      font-family:inherit;font-size:14px;font-weight:500;color:var(--cx-lime-soft);cursor:pointer}
  .dropbtn .caret{width:14px;height:14px;transition:transform .15s ease}
  .drop:hover .dropbtn,.drop:focus-within .dropbtn{color:var(--cx-white)}
  .drop:hover .caret,.drop:focus-within .caret{transform:rotate(180deg)}
  /* opakowanie trzyma odstęp od paska jako padding, nie margines - inaczej
     kursor gubi hover na przerwie między przyciskiem a panelem */
  /* panel kotwiczymy do paska (.nav ma position:relative), a nie do przycisku:
     przy 760 px szerokości wychodził lewą krawędzią poza ekran */
  .nav{position:relative}
  .dropwrap{position:absolute;top:100%;right:0;padding-top:12px;opacity:0;visibility:hidden;
      transform:translateY(-4px);transition:opacity .15s ease,transform .15s ease,visibility .15s;
      z-index:60}
  .drop:hover .dropwrap,.drop:focus-within .dropwrap{opacity:1;visibility:visible;
      transform:translateY(0)}
  .droppanel{display:grid;grid-template-columns:auto minmax(230px,1fr) minmax(250px,1fr);
      gap:var(--space-6);min-width:min(720px,calc(100vw - 32px));
      max-width:calc(100vw - 32px);padding:var(--space-5);
      background:var(--cx-ink);border:1px solid var(--cx-ink-60);
      border-radius:var(--radius-lg);box-shadow:0 16px 40px rgba(0,0,0,.45)}
  .dropcol{display:flex;flex-direction:column;gap:2px;min-width:0}
  .drophead{font-size:11px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
      color:var(--cx-ink-20);padding:0 var(--space-3) 6px}
  .dropitem{display:block;padding:9px var(--space-3);border-radius:var(--radius-md);
      font-size:14px;color:var(--cx-lime-soft);text-decoration:none}
  .dropitem:hover{background:rgba(255,255,255,.06);color:var(--cx-white)}
  .dropitem.is-here{color:var(--cx-lime);font-weight:600}
  .dropitem--rich b{display:block;font-size:14px;font-weight:600;color:var(--cx-white)}
  .dropitem--rich em{display:block;margin-top:3px;font-size:12.5px;line-height:1.45;
      font-style:normal;color:var(--cx-ink-20)}
  .dropitem--rich:hover em{color:var(--cx-lime-soft)}
  @media(max-width:900px){
    .dropwrap{position:static;padding-top:var(--space-3);transform:none}
    .droppanel{grid-template-columns:minmax(0,1fr);min-width:0;gap:var(--space-4)}
  }

  /* ── pasy naprzemienne: hero ciemne → produkty jasne → tematy ciemne →
     najczęściej czytane jasne → wsparcie ciemne. Komponenty (.app, .read)
     są pisane pod ciemne tło, więc jasny pas je przestawia - jeden blok
     nadpisań zamiast drugiego kompletu klas. */
  .band--light{background:var(--cx-mist);color:var(--text)}
  .band--light .hubhead h2{color:var(--text)}
  .band--light .hubhead p{color:var(--muted)}
  /* Etykieta sekcji na jasnym pasie: turkus (decyzja 53). W design systemie
     turkus jest rolą tekstu akcentowego na jasnym tle, limonka na ciemnym.
     Kontrast turquoise-600 na mgle to 6,5:1 - z zapasem ponad 4,5:1
     wymagane przy 13 px. */
  .band--light .eyebrow{color:var(--cx-turquoise-600)}
  .band--light .cx-mark .cx-chev-l,.band--light .cx-mark .cx-chev-r{background:var(--accent)}

  .band--light .app{background:var(--cx-white);border-color:var(--line2);
      box-shadow:var(--shadow-xs)}
  .band--light .app:hover{box-shadow:var(--shadow-lg);border-color:var(--cx-ink-20)}
  .band--light .app b{color:var(--cx-ink)}
  .band--light .app .ic{background:var(--cx-mist);color:var(--accent-strong)}
  .band--light .app .ic:has(.prodico){box-shadow:inset 0 0 0 1px var(--line2)}
  .band--light .app .tx>span.cnt{color:var(--muted)}
  .band--light .app--lead .tx>span.lead-desc{color:var(--muted)}
  .band--light .app--lead .ic{background:var(--cx-ink)}
  .band--light .app .go{color:var(--text)}
  .band--light .app:hover .go{color:var(--accent-strong)}
  .band--light .appcatlist{border-color:var(--line)}
  .band--light .appcat{color:var(--text)}
  .band--light .appcat small{color:var(--soft)}
  .band--light .appcat:hover,.band--light .appcat:focus-visible{color:var(--accent-strong)}
  .band--light .appcat:hover small{color:var(--accent-strong)}
  .band--light .appcat--all{color:var(--cx-ink)}

  .band--light .reads li+li{border-color:var(--line)}
  .band--light .read:hover{background:var(--cx-white)}
  .band--light .readno{color:var(--muted)}
  .band--light .readic{box-shadow:inset 0 0 0 1px var(--line2)}
  .band--light .readtitle{color:var(--text)}
  .band--light .read:hover .readtitle{color:var(--accent-strong)}
  .band--light .readcat,.band--light .readlede{color:var(--muted)}
  .band--light .readdate{color:var(--text)}
  /* na jasnym pasie guzik jest obrysem w kolorze marki, nie białym prostokątem
     (biel na mgle gubiła kształt); w hoverze wypełnia się ciemną zielenią */
  .band--light .readgo{background:transparent;border-color:var(--cx-ink-20);
      color:var(--accent-strong)}
  .band--light .read:hover .readgo{background:var(--cx-ink);border-color:var(--cx-ink);color:var(--cx-lime)}

  /* ostatni pas jest ciemny i styka się z ciemną stopką - kreska je rozdziela */
  .band--last{border-bottom:1px solid var(--cx-ink-60)}
  /* lista wsparcia na ciemnym: przezroczysta karta z obrysem, nie biały
     prostokąt (na ciemnym pasie wyglądał jak wklejka z innej strony) */
  .band--dark .helpbox{background:rgb(22,36,37);border-color:var(--cx-ink-60);
      border-left-color:var(--cx-lime);box-shadow:none}
  .band--dark .helprow{border-bottom-color:var(--cx-ink-60)}
  .band--dark .helprow b{color:var(--cx-white)}
  .band--dark .helprow em{color:var(--cx-ink-20)}
  .band--dark .helprow:hover b{color:var(--cx-lime)}
  .band--dark .helprow .ico{background:rgba(173,247,99,.14);color:var(--cx-lime)}
  .band--dark .helpwrap h2{color:var(--cx-white)}
  .band--dark .helplead{color:var(--cx-lime-soft)}
  .band--dark .helpwrap .eyebrow{color:var(--cx-lime)}
  /* karta logowania stoi teraz obok ciemnej listy - odróżnia ją lime obrys,
     nie inne tło */
  .band--dark .loginbox{background:rgb(26,42,42);border-color:rgba(173,247,99,.35)}


  /* ── Sekcja produktów ma się zmieścić na jednym ekranie ────────────────
     Kafelek z kolumny robi się wierszem: znak, nazwa, licznik. „Przejdź"
     i rozwijana lista kategorii wypadają - przy dzisiejszych danych i tak
     nie miały czego pokazać (sześć produktów ma jedną kategorię o własnej
     nazwie), a zjadały dwie trzecie wysokości sekcji. */
  .apps{grid-template-columns:repeat(auto-fill,minmax(228px,1fr));gap:clamp(8px,1.2vh,14px)}
  .app{padding:clamp(10px,1.5vh,14px) var(--space-4)}
  .appmain{flex-direction:row;align-items:center;gap:var(--space-3)}
  .app .ic{width:38px;height:38px}
  .app .ic svg{width:19px;height:19px}
  .app b{font-size:16px;line-height:1.2}
  .app .tx{gap:2px}
  .app .tx>span.cnt{font-size:11px;letter-spacing:.08em}
  .app .go,.appcats{display:none}
  .app--lead{padding:clamp(12px,1.8vh,18px) var(--space-5)}
  .app--lead .ic{width:46px;height:46px}
  .app--lead .ic svg{width:23px;height:23px}
  .app--lead b{font-size:clamp(17px,1.8vw,21px)}
  .app--lead .tx>span.lead-desc{font-size:13.5px;line-height:1.4;
      display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .hubhead h2{font-size:clamp(22px,2.4vw,30px)}
  .hubsec--split .hubhead h2{font-size:clamp(19px,2vw,24px)}
  .topic{padding:clamp(5px,.9vh,10px) 0}
  .topic b{font-size:14.5px}
  .topic>span:last-child{font-size:12px}

  /* sekcja wsparcia też musi zmieścić się w ekranie */
  .helpwrap{padding:0}
  .helpwrap h2{font-size:clamp(22px,2.4vw,30px)}
  .helplead{margin-top:var(--space-2);font-size:14.5px}
  .helpbox{margin-top:clamp(12px,2vh,20px);padding:var(--space-2) var(--space-4)}
  .helprow{padding:clamp(9px,1.4vh,14px) 0;gap:var(--space-3)}
  .helprow .ico{width:32px;height:32px}
  .helprow .ico svg{width:16px;height:16px}
  .helprow b{font-size:14.5px}
  .helprow em{font-size:12.5px;line-height:1.45;
      display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .loginbox{padding:clamp(18px,2.6vh,28px)}
  .loginbox h2{font-size:21px}
  .loginbox p{font-size:13.5px}
  .loginnote{margin-top:clamp(12px,2vh,20px);padding-top:clamp(10px,1.6vh,16px);font-size:12.5px}

  /* Bazowe deklaracje układu zgubione przy przebudowie na sekcje
     pełnoekranowe - bez nich .apps i .helpwrap były blokami, a wiersze
     wsparcia elementami inline. */
  .apps{display:grid}
  .helpwrap{display:grid}
  .topics{display:grid}
  .topic{display:flex;text-decoration:none}
  .helpbox{display:flex;flex-direction:column}
  .helprow{display:flex;align-items:flex-start;text-decoration:none}
  .helprow>span:last-child{display:flex;flex-direction:column;gap:3px;min-width:0}
  .helprow em{font-style:normal}
  .herostats{display:flex}
  .sugg{display:flex;flex-wrap:wrap;align-items:center;gap:9px}

  /* Bazowy wygląd przycisków - również zgubiony przy przebudowie. Kolory
     z design systemu: lime na ink, ciemna płytka z szewronem na krawędzi. */
  .btn{display:inline-flex;align-items:center;justify-content:center;
      background:var(--cx-lime);color:var(--cx-ink);border:0;cursor:pointer;
      font-family:var(--font-body);text-decoration:none;
      transition:filter .14s ease,transform .12s ease}
  .btn:hover{filter:brightness(.96);color:var(--cx-ink)}
  .btn:active{transform:translateY(1px)}
  .btn .chev{display:inline-flex;align-items:center;justify-content:center;
      background:var(--cx-ink);color:var(--cx-lime);flex:none}
  .btn--ghost{background:none;border:1px solid var(--cx-ink-60);color:var(--cx-mist)}
  .btn--ghost:hover{background:rgba(255,255,255,.06);color:var(--cx-white);filter:none}
  .search{display:flex;align-items:center;background:var(--cx-white)}
  .search input{flex:1 1 auto;min-width:0;border:0;outline:0;background:none;
      font-family:var(--font-body);color:var(--text)}
  .search button{display:inline-flex;align-items:center;border:0;cursor:pointer;
      font-family:var(--font-body);background:var(--cx-lime);color:var(--cx-ink);
      transition:filter .14s ease}
  .search button:hover{filter:brightness(.96)}
  /* Na ciemnych pasach kolor nadpisują `.eyebrow--on-dark` i reguły sekcji,
     więc zmiana na jasnym tle ich nie dotyka. */
  /* 13 px wymaga 4,5:1. Kolor zależy od pasa: turkus na jasnym, miękki lime
     na ciemnym - tak stoi rola tekstu akcentowego w design systemie. */
  .eyebrow{display:flex;align-items:center;gap:9px;font-size:13px;font-weight:600;
      color:var(--cx-turquoise-600);text-transform:none}
  .hero .eyebrow,.band--dark .eyebrow,.pane--brand .eyebrow{color:var(--cx-lime-soft)}
  .cx-mark{display:inline-flex;align-items:center;gap:2px}

  /* ══════════════════════════════════════════════════════════════════════
     Poprawki po przeglądzie (Radek, 14.09) - nagłówek, hero, karty, tła
     ══════════════════════════════════════════════════════════════════════ */

  /* Nagłówek w JEDNEJ linii: pasek nie zawija, CTA jest ostatni i nie kurczy
     się, a przy ciaśniejszym oknie oddaje miejsce menu (nie odwrotnie). */
  header.nav{flex-wrap:nowrap}
  .nav__brand{flex:none}
  /* Bez overflow:hidden - obcinało wyrazy w ciszy („Pomo”) zamiast zmusić
     układ do reakcji. Pozycje nie zawijają się i nie kurczą; o tym, ile ich
     widać, decydują progi niżej, policzone z realnych szerokości:
     lockup 209 + prawa strona 264 + pięć pozycji 471 ≈ 1100px. */
  .nav__links{flex:0 0 auto;min-width:0}
  .nav__cta{flex:none;order:3;white-space:nowrap}

  /* Tło hero: siatka kropek z materiałów CXLABS (bg_dots.svg) zamiast
     rysowanej sieci - ten sam motyw co na stronie firmowej. */
  .hero .herodots{position:absolute;inset:0;z-index:0;pointer-events:none;
      background:url("/assets/tlo/pattern-kropki.svg") center/min(1100px,120%) no-repeat;
      opacity:.5;
      -webkit-mask-image:radial-gradient(ellipse 62% 60% at 50% 48%,#000 40%,transparent 78%);
      mask-image:radial-gradient(ellipse 62% 60% at 50% 48%,#000 40%,transparent 78%)}
  @media(prefers-reduced-motion:reduce){.hero .herodots{opacity:.34}}

  /* odstęp pod akapitem hero - wcześniej wyszukiwarka kleiła się do tekstu */
  #view>.hero p.sub{margin-bottom:clamp(26px,3.4vh,42px)}
  #view>.hero:not(.small) .search{margin-top:0}

  /* ── Karty produktów: opis wraca, wszystkie równej wysokości ───────────
     Karta jest siatką: treść u góry, stopka („Przejdź") zawsze na dole -
     bez tego trzy ostatnie kafelki były niższe i gubiły dolną krawędź. */
  .apps{align-items:stretch}
  .app{height:100%}
  .appmain{flex-direction:column;align-items:flex-start;height:100%;
      gap:clamp(9px,1.4vh,14px)}
  .app .ic{width:40px;height:40px}
  .app .tx{flex:1 1 auto;gap:4px}
  .app .tx>span.app-desc{font-size:12.5px;line-height:1.45;color:var(--cx-lime-soft);
      display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .app .go{display:inline-flex;margin-top:0}

  /* rozwinięcie po najechaniu: karta pokazuje swoje kategorie */
  .app .appcats{display:grid}
  .app{transition:transform .22s ease,box-shadow .22s ease,border-color .22s ease}
  .app:hover,.app:focus-within{transform:translateY(-3px);
      box-shadow:0 18px 44px rgba(0,0,0,.38);z-index:2}
  .appcatlist a{display:flex;align-items:baseline;gap:9px;padding:5px 0;
      font-size:12.5px;color:var(--cx-lime-soft);text-decoration:none}
  .appcatlist a:hover{color:var(--cx-lime)}
  .appcatlist a span:last-child{margin-left:auto;color:var(--cx-ink-20);font-size:11.5px}

  /* separator między tematami: w dwóch kolumnach Firefox gubił kreskę na
     przedostatnim wierszu przy regule :last-child - rysujemy ją zawsze */
  .topics .topic{border-bottom:1px solid var(--cx-ink-60)!important}

  /* ── Najczęściej czytane: pattern w tle i guziki na #F3F4F4 ───────────── */
  .band--light{position:relative;isolation:isolate}
  .band--light::before{content:"";position:absolute;inset:0;z-index:-1;
      /* Jednolite #F4F9F8 zamiast gradientu z bieli (paczka 16.09): przejście
         było widoczne jako pas na styku z sąsiednią sekcją. */
      background:url("/assets/tlo/pattern-czytane.svg") right -180px top -220px/900px no-repeat,
                 var(--cx-mist);
      opacity:.85;pointer-events:none}
  .band--light .readgo{background:#F3F4F4;border:0;color:var(--text)}
  .band--light .read:hover .readgo{background:var(--cx-ink);color:var(--cx-lime)}

  /* ── Wsparcie: grafika tła z materiałów CXLABS ────────────────────────── */
  /* ── Kurs online monday.com ─────────────────────────────────────────────
     Odtworzone 1:1 ze strony firmowej: kolory wpisane wprost, bo to cytat
     z innej witryny, a nie komponent portalu. */
  #view>.band--kurs{background:#243838;box-shadow:none}
  .kurswrap{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.86fr);
      gap:clamp(32px,4vw,64px);align-items:center}
  .kurstx{display:flex;flex-direction:column}
  .kurstag{display:flex;align-items:center;gap:10px;font-size:16px;line-height:1.5;color:#ADF763}
  .kurstag svg{flex:none;width:16px;height:16px}
  .kurstx h2{font-family:var(--font-display);font-size:clamp(28px,3vw,40px);font-weight:400;
      letter-spacing:-.01em;line-height:1.2;color:#F4F9F8;margin-top:var(--space-4);max-width:22ch}
  .kurslead{margin-top:var(--space-4);max-width:58ch;font-size:16px;line-height:1.5;color:#DBECE9}
  .kurscta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);
      margin-top:clamp(20px,3vh,32px)}
  /* „Kup kurs": lime płytka z ciemnym kwadratem 40×40 i limonkowym szewronem */
  .kursbuy{display:inline-flex;align-items:center;gap:var(--space-4);
      padding:4px 4px 4px 24px;border-radius:12px;background:#ADF763;color:#122021;
      font-size:16px;text-decoration:none;transition:filter .15s ease,transform .12s ease}
  .kursbuy:hover{filter:brightness(.96);color:#122021}
  .kursbuy:active{transform:translateY(1px)}
  .kursbuy svg{display:block;flex:none}
  .kursmore{display:inline-flex;align-items:center;padding:14px 24px;border-radius:12px;
      background:#F4F9F81a;color:#F4F9F8;font-size:16px;text-decoration:none;
      transition:background .15s ease}
  .kursmore:hover{background:#F4F9F833;color:#F4F9F8}
  .kursfig{margin:0;border-radius:2rem;overflow:hidden;background:var(--cx-ink-80)}
  .kursfig img{display:block;width:100%;aspect-ratio:1/1;object-fit:cover}
  .kursfacts{list-style:none;display:flex;flex-direction:column;
      gap:clamp(16px,2.4vh,24px);margin-top:clamp(28px,5vh,56px)}
  .kursfacts li{display:flex;align-items:center;gap:var(--space-4);
      font-family:var(--font-display);font-weight:400;line-height:1.4;
      font-size:clamp(17px,1.6vw,24px);color:#F4F9F8}
  .kursbul{display:inline-flex;flex:none;width:30px;justify-content:center}
  .kursbul svg{display:block;width:auto;height:26px}
  @media(max-width:900px){
    .kurswrap{grid-template-columns:minmax(0,1fr)}
    .kursfig{order:-1}
    .kursfig img{aspect-ratio:4/3}
  }

  .band--last{position:relative;isolation:isolate}
  .band--last::before{content:"";position:absolute;inset:0;z-index:-1;
      background:url("/assets/tlo/pattern-wsparcie.svg") center bottom/cover no-repeat;
      opacity:.5;pointer-events:none}

  /* ── Podpowiedzi: oddech w stanie pustym ──────────────────────────────── */
  .ac .acempty{display:flex;flex-direction:column;align-items:flex-start;
      gap:var(--space-3);padding:var(--space-5)}
  .ac .acempty b{font-size:14.5px;color:var(--text)}
  .ac .acempty span{font-size:13px;line-height:1.5;color:var(--muted)}
  .ac .acempty .btn{margin-top:var(--space-3)}

  /* ── Wyniki: znak produktu nie może rozpychać karty ───────────────────── */
  .card .cat img,.card img.prodico,.acic img.prodico{max-width:100%;max-height:100%;
      width:auto;height:auto;object-fit:contain;flex:none}
  .card .cat{min-width:0}
  .card .cat img{width:16px;height:16px}

  /* ── Stopka: znaki produktów przy nazwach ─────────────────────────────── */
  footer .fprod{display:inline-flex;align-items:center;gap:9px}
  footer .fprod img{width:18px;height:18px;object-fit:contain;flex:none;
      border-radius:4px}

  /* ── Pasek postępu strony (prawa krawędź) ─────────────────────────────── */
  /* Pasek ma leżeć NAD treścią strony, ale POD paskiem nawigacji: `header.nav`
     stoi na 30, a ten miał 40 i wygrywał. Skutek było widać dopiero
     w rozwiniętym menu konta na stronie głównej - kropki i ich etykiety
     kładły się na pozycjach menu, więc „Admin" i „Wyloguj się" dawało się
     przeczytać tylko w połowie. Treść strony siedzi na 1, więc 20 wystarczy
     z zapasem. */
  .rail{position:fixed;right:clamp(14px,2vw,28px);top:50%;transform:translateY(-50%);
      z-index:20;display:flex;flex-direction:column;gap:2px;padding:6px;
      border-radius:999px;background:rgba(18,32,33,.55);border:1px solid rgba(255,255,255,.10);
      backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
  .railitem{position:relative;display:flex;align-items:center;justify-content:center;
      width:30px;height:30px;border:0;background:none;cursor:pointer;padding:0}
  .raildot{width:7px;height:7px;border-radius:50%;background:rgba(219,236,233,.42);
      transition:background .2s ease,transform .2s ease}
  .railitem:hover .raildot{background:var(--cx-lime-soft);transform:scale(1.25)}
  .railitem.on .raildot{background:var(--cx-lime);transform:scale(1.5)}
  /* etykieta wyjeżdża w lewo po najechaniu; nie zajmuje miejsca w spoczynku */
  .raillabel{position:absolute;right:calc(100% + 10px);white-space:nowrap;
      padding:5px 11px;border-radius:var(--radius-sm);background:var(--cx-ink);
      border:1px solid var(--cx-ink-60);color:var(--cx-mist);font-size:12.5px;
      opacity:0;transform:translateX(6px);pointer-events:none;
      transition:opacity .16s ease,transform .16s ease}
  .railitem:hover .raillabel,.railitem:focus-visible .raillabel{opacity:1;transform:none}
  /* pionowa kreska postępu za kropkami */
  .railbar{position:absolute;left:50%;top:10px;bottom:10px;width:2px;margin-left:-1px;
      border-radius:2px;background:rgba(219,236,233,.16);overflow:hidden}
  .railbar i{display:block;width:100%;background:var(--cx-lime);border-radius:2px;
      transition:height .18s ease}
  @media(max-width:900px){.rail{display:none}}

  /* dots są w --cx-ink-60 na ciemnym tle - przy krytu 0,5 nikną zupełnie */
  .hero .herodots{opacity:1;background-size:min(1280px,135%)}
  @media(prefers-reduced-motion:reduce){.hero .herodots{opacity:.8}}

  /* Sekcja produktów na jednym ekranie mimo opisów: cztery kolumny zamiast
     trzech (siedem kafli mieści się w dwóch rzędach) i ciaśniejsze odstępy. */
  .apps{grid-template-columns:repeat(auto-fill,minmax(196px,1fr));gap:clamp(8px,1.1vh,13px)}
  .app{padding:clamp(10px,1.4vh,14px) var(--space-4)}
  .app .tx>span.app-desc{-webkit-line-clamp:3}
  .hubsec--split{margin-top:clamp(16px,2.4vh,30px)}
  .topics .topic{padding:clamp(4px,.7vh,8px) 0}
  @media(max-width:1000px){.apps{grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}}

  /* kropki w pliku są w #305555 przy krytu 0,3 - na ciemnym tle prawie
     niewidoczne; rozjaśniamy je filtrem zamiast podmieniać plik */
  .hero .herodots{filter:brightness(2.1)}

  /* Sekcja Produkty na jednym ekranie - ostatnie zacieśnienie.
     Kafel traci wiersz „Przejdź": cała karta jest odnośnikiem, a strzałka
     przy nazwie mówi to samo w jednej linii. Opis dwie linie zamiast trzech. */
  .apps{grid-template-columns:repeat(auto-fill,minmax(188px,1fr))}
  .app:not(.app--lead) .go{display:none}
  .app .tx>span.app-desc{-webkit-line-clamp:2}
  .app .ic{width:34px;height:34px}
  .app b{font-size:15px}
  .appmain{gap:clamp(7px,1.1vh,11px)}
  @media(max-width:1000px){.apps{grid-template-columns:repeat(auto-fill,minmax(188px,1fr))}}
  @media(max-width:820px){.apps{grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}}
  .band--first .hubhead{margin-bottom:clamp(10px,1.6vh,18px)}
  .band--first .hubhead p{font-size:14px}
  .hubsec--split .hubhead{margin-bottom:clamp(8px,1.2vh,14px)}

  /* Nagłówek stoi teraz w przepływie, nie na ciemnym hero - musi więc nieść
     własne tło marki, inaczej jasny znak leży na jasnym tle strony. */
  header.nav{background:var(--cx-ink)}
  .devbar{background:var(--cx-ink-80)}

  /* body jest kolumną flex z wyśrodkowaniem, więc nagłówek - odkąd stoi
     w przepływie, a nie nad hero - kurczył się do szerokości treści */
  header.nav{align-self:stretch;width:100%}

  /* Nagłówek na pełną szerokość - bazowa reguła body>header ograniczała go
     do szerokości treści, przez co po bokach świeciło jasne tło strony. */
  header.nav{max-width:none;width:100%;box-sizing:border-box}

  /* tło hero bez patternu: sam gradient marki */
  .hero .herodots{display:none}

  /* Pattern „Frame" w sekcji Najczęściej czytane - mocniej widoczny,
     bo w pliku jest w jasnym #305555 przy niskim kryciu. */
  .band--light::before{
      background:url("/assets/tlo/pattern-czytane.svg") right -140px top -160px/820px no-repeat,
                 linear-gradient(180deg,var(--cx-white) 0%,var(--cx-mist) 100%);
      opacity:1}

  /* Pattern „Frame": wcześniej stał na calc(100% + 140px) -160px, czyli
     w praktyce poza kadrem. Teraz wypełnia sekcję. */
  .band--light::before{
      /* Jednolite #F4F9F8 zamiast gradientu z bieli: przejscie bylo widoczne
         jako pas na styku z sasiednia sekcja (paczka 17.09). */
      background:#F4F9F8;
      opacity:1}
  .band--light::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
      background:url("/assets/tlo/pattern-czytane.svg") center/cover no-repeat;
      opacity:.55}

  /* Cień na styku z sekcją wsparcia: pada W DÓŁ, na ciemną sekcję poniżej.
     Osobny element, bo ::before i ::after są już zajęte przez tła. */
  .band--light>.wrap{position:relative}
  .band--light{box-shadow:0 26px 46px -18px rgba(18,32,33,.45)}
  .band--last{box-shadow:none}

  /* ── Pasek nawigacji: etykiety sterowane zmienną --labels (0…1) ───────── */
  .rail{--labels:0}
  .raillabel{opacity:0;transform:translateX(6px);
      transition:opacity .22s ease,transform .22s ease,color .2s ease,
                 background .2s ease,border-color .2s ease}
  /* nieaktywne sekcje: połowa tego, co widać w danej chwili */
  .rail.labels-on .raillabel{opacity:calc(var(--labels) * .5);transform:none}
  /* bieżąca sekcja jest widoczna ZAWSZE - to ona mówi „jesteś tutaj",
     więc nie podlega gaśnięciu po 3 s ani strefie czułości kursora */
  .railitem.on .raillabel{opacity:1;transform:none;
      border-color:var(--cx-lime);color:var(--cx-white)}
  /* najechanie na konkretną pozycję zawsze pokazuje ją w pełni */
  .railitem:hover .raillabel,.railitem:focus-visible .raillabel{opacity:1;transform:none;
      border-color:var(--cx-lime);color:var(--cx-white)}
  @media(prefers-reduced-motion:reduce){.raillabel{transition:none}}

  /* pasek nawigacji: pełne tło marki zamiast przezroczystej szybki */
  .rail{background:#152424;border-color:rgba(255,255,255,.08);
      backdrop-filter:none;-webkit-backdrop-filter:none}
  .raillabel{background:#152424}

  /* na telefonach paska nie ma - zabierałby kciukowi prawą krawędź ekranu.
     Warunek na brak hovera łapie też tablety dotykowe w poziomie. */
  @media(max-width:900px),(hover:none){.rail{display:none!important}}


  /* Etykieta miała pointer-events:none (była tylko podpowiedzią przy hoverze),
     więc kliknięcie w napis trafiało w treść pod spodem. Teraz jest klikalna
     razem z kropką - to ona jest największym celem na pasku. */
  .raillabel{pointer-events:auto;cursor:pointer}

  /* ── Karta produktu: jeden spójny stan hover ───────────────────────────
     Glitch brał się z trzech nakładających się reguł: każda ustawiała inny
     kolor obramowania (--cx-ink-40, --cx-ink-20, --cx-lime) i inny czas
     przejścia (.18s/.2s/.22s), więc krawędź „dojeżdżała" jeszcze sekundę po
     najechaniu. Do tego cień 0 18px 44px rozlewał się na wszystkie strony
     i zjadał górną krawędź na ciemnym tle.
     Teraz: obramowanie NIE jest animowane i ma jedną wartość, a cień pada
     wyłącznie w dół (ujemny rozrzut przycina go u góry). */
  .app,.app:hover,.app:focus-within{
      transition:transform .18s ease,box-shadow .18s ease}
  .band--dark .app:hover,.band--dark .app:focus-within{
      border-color:var(--cx-ink-40);
      box-shadow:0 16px 30px -12px rgba(0,0,0,.55)}
  .band--light .app:hover,.band--light .app:focus-within{
      border-color:var(--cx-ink-20);
      box-shadow:0 14px 26px -12px rgba(18,32,33,.22)}

  /* ══ Lista artykułów (widok produktu i kategorii) ══════════════════════
     Wiersz zamiast karty: jedna kolumna tytułów do skanowania w pionie,
     sekcja i data dosunięte do prawej, cienka linia zamiast ramki. */
  .arts{list-style:none;margin:0;padding:0}
  .artrow{display:grid;grid-template-columns:minmax(0,1fr) auto auto 18px;
      align-items:center;gap:var(--space-5);padding:13px var(--space-4) 13px var(--space-3);
      border-bottom:1px solid var(--line);text-decoration:none;color:inherit;
      border-left:2px solid transparent;
      transition:background .14s ease,border-left-color .14s ease}
  .artrow:hover{background:var(--cx-white);border-left-color:var(--cx-lime)}
  .artmain{display:flex;flex-direction:column;gap:2px;min-width:0}
  .arttitle{font-size:15px;font-weight:600;line-height:1.35;color:var(--text);
      display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}
  .artrow:hover .arttitle{color:var(--accent-strong)}
  .artlede{font-size:12.5px;line-height:1.45;color:var(--muted);
      display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}
  .artcat{font-size:11.5px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;
      color:var(--muted);white-space:nowrap}
  .artdate{font-size:12px;color:var(--cx-gray-2);white-space:nowrap;font-variant-numeric:tabular-nums}
  .artgo{display:flex;align-items:center;justify-content:center;color:var(--cx-ink-20)}
  .artgo svg{width:14px;height:14px}
  .artrow:hover .artgo{color:var(--accent-strong)}
  .arts mark{background:rgba(173,247,99,.45);color:inherit;padding:0 2px;border-radius:3px}
  @media(max-width:760px){
    .artrow{grid-template-columns:minmax(0,1fr) auto;gap:var(--space-3);padding:11px var(--space-3)}
    .artrow .artcat,.artrow .artgo{display:none}
  }

  /* nagłówek grupy sekcji nad listą */
  .secgroup{margin-top:clamp(28px,3.5vw,44px)}
  .secgroup-head{display:flex;align-items:baseline;gap:var(--space-4);
      margin-bottom:var(--space-3)}
  .secgroup-head h3{font-family:var(--font-display);font-weight:500;font-size:19px;
      letter-spacing:-.01em;color:var(--text)}
  .secgroup-count{font-size:12px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
      color:var(--muted)}

  /* wyszukiwarka na podstronie - węższa niż w hero, wyrównana do lewej */
  .search--sub{margin:var(--space-5) 0 0;max-width:520px;width:100%;
      border-radius:var(--radius-md);padding:5px 5px 5px var(--space-5);
      box-shadow:0 12px 30px rgba(0,0,0,.22)}
  .search--sub input{font-size:15px;padding-left:0}
  .search--sub button{padding:11px var(--space-4);font-size:14px;font-weight:500;
      border-radius:var(--radius-sm);display:inline-flex;align-items:center;gap:8px}
  .search--sub button svg{width:15px;height:15px}
  /* znak produktu w nagłówku podstrony zamiast skrótu literowego */
  .appHead .ic{display:grid;place-items:center;width:52px;height:52px;border-radius:12px;
      overflow:hidden;background:rgba(173,247,99,.14);flex:none}
  .appHead .ic .prodico{width:100%;height:100%;object-fit:contain;display:block}

  /* Mały hero podstrony nie jest sekcją-ekranem: reguły #view>.hero
     (100svh, wyśrodkowanie, zaczep scroll-snap) dotyczą tylko strony głównej. */
  #view>.hero.small{min-height:0;display:block;text-align:left;
      padding:clamp(28px,4vh,48px) 0 clamp(26px,3.6vh,42px);
      scroll-snap-align:none;scroll-snap-stop:normal}
  #view>.hero.small .wrap{width:100%}
  .hero.small .heroCrumbs{justify-content:flex-start}
  .appHead{display:flex;align-items:center;gap:var(--space-4);margin-top:var(--space-4)}
  .appHead h1{font-size:clamp(26px,3.4vw,40px);line-height:1.1;color:var(--cx-white);
      /* `.hero h1` zwęża nagłówek do 19ch - to miara wielkiego napisu na
         stronie głównej, nie nagłówka podstrony, który ma tu jeden wiersz */
      max-width:none}
  .appHead p{margin-top:5px;font-size:14.5px;color:var(--cx-lime-soft)}
  /* na podstronach scroll-snap nie ma sensu - treść jest ciągłą listą */
  /* Zaczepy przewijania to mechanizm STRONY GŁÓWNEJ. Na podstronie jedynym
     zaczepem została stopka, więc przy „y mandatory" przeglądarka od razu
     ściągała widok na sam dół. Wyłączamy je na każdym widoku z małym hero. */
  /* (reguła zbędna - zaczepy włącza teraz warunek na #view>.band) */

  /* .hero .search ma margin:auto (wyśrodkowanie w hero strony głównej) -
     na podstronie pole ma stać przy lewej krawędzi kolumny */
  /* .hero.small .search (0,3,0) wygrywało z .hero .search--sub (0,2,0)
     i wciąż centrowało pole - stąd ta sama waga po lewej stronie. */
  .hero.small .search,.hero.small .search--sub{margin-left:0;margin-right:auto;
      margin-top:clamp(22px,3vh,34px)}

  /* ── Nagłówek: pasek pełnej szerokości, treść w ramie 1440 px ──────────
     Tyle ma desktopowa ramka w design systemie CXLABS (padding 64 px), więc
     na szerokim monitorze logo i CTA nie rozjeżdżają się na krańce ekranu.
     Tło zostaje pełnowymiarowe - obcinamy tylko zawartość. */
  header.nav{padding:0;justify-content:center}
  /* Pasek trzyma tę samą szerokość co kolumna treści (1180 px) - wcześniej
     ramka 1440 px rozciągała go szerzej niż tekst pod nim i lockup z CTA
     odjeżdżały na krańce ekranu (paczka 16.09, punkt 1). */
  /* Kropka stanu usług przy pozycji „Status" w nawigacji. Ten sam sygnał, co
     pasek na ekranie Status - tylko widoczny z każdej strony portalu. */
  /* Stan platformy przy pozycji „Status" (decyzja 54). Kolor nie jest jedynym
     nośnikiem: obok stoi tekst dla czytnika ekranu (.sr), a okno serwisowe ma
     własny kształt - znak „i" wrysowany maską SVG, nie znakiem z kroju.
     Kropka stoi PRZED etykietą; w płachcie mobilnej przenosi ją za etykietę
     navSheetBuduj(), bo rynna przed tekstem wcinała tam tylko „Status".
     Poświata to 3-px obwódka box-shadow - przy awarii ona się rozszerza,
     więc pulsuje sam sygnał, a nie cała kropka. */
  .navdot{display:inline-grid;place-items:center;width:8px;height:8px;margin-right:8px;
      border-radius:50%;background:var(--cx-green);vertical-align:1px;flex:none;
      box-shadow:0 0 0 3px rgba(255,255,255,.14)}
  .navsheet__links .navdot{margin-right:0;margin-left:8px}
  .navdot[data-stan="okno"]{width:15px;height:15px;vertical-align:-2px;
      background:var(--cx-yellow)}
  .navdot[data-stan="okno"]::before{content:"";width:100%;height:100%;
      background:var(--cx-ink);
      -webkit-mask:var(--navdot-i) center/9px 9px no-repeat;
      mask:var(--navdot-i) center/9px 9px no-repeat}
  .navdot[data-stan="awaria"]{background:var(--cx-error);
      animation:navdotpuls 1.8s ease-in-out infinite}
  .navdot[data-stan="nieznany"]{background:var(--cx-cloud-2)}
  @keyframes navdotpuls{
    0%,100%{box-shadow:0 0 0 3px rgba(224,80,60,.35)}
    50%{box-shadow:0 0 0 7px rgba(224,80,60,0)}
  }
  @media (prefers-reduced-motion: reduce){ .navdot[data-stan="awaria"]{animation:none} }
  /* Wezwanie „Nowe zgłoszenie" przy wygasłym wsparciu. Wygaszone, ale nadal
     widoczne i dostępne z klawiatury - znika obietnica, nie orientacja. */
  .cta--off{opacity:.45;cursor:not-allowed;filter:grayscale(1)}
  /* Tekst wyłącznie dla czytnika ekranu - zostaje w drzewie dostępności. */
  .sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
      clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

  .navin{display:flex;align-items:center;justify-content:space-between;
      gap:clamp(14px,1.8vw,26px);width:100%;max-width:1180px;
      padding:clamp(16px,2.4vh,24px) var(--space-6);box-sizing:border-box}

  /* „Najczęściej czytane": treść wyśrodkowana w pionie jak w pozostałych
     sekcjach. Wcześniej lista była dociągana do góry i rozpychana na całą
     wysokość, przez co pod ostatnim wierszem zostawało puste pole. */
  #view>.band--light{justify-content:center}
  .band--light .hubsec{display:block}
  .band--light .reads{display:block}

  /* Odjęcie --chrome dotyczy WYŁĄCZNIE pierwszego ekranu: pasek i nagłówek
     są u góry dokumentu, więc zabierają miejsce tylko hero. Dalsze sekcje
     stoją już pod nimi i muszą mieć pełne 100svh - inaczej pod każdą z nich
     widać skrawek następnej (dokładnie tyle, ile wynosi --chrome). */
  #view>.band{min-height:100svh}
  #view>.hero{min-height:calc(100svh - var(--chrome,0px))}
  @media(max-width:700px){#view>.band,#view>.hero{min-height:0}}

  /* Inline SVG bez atrybutów width/height przyjmuje domyślne 300×150 albo
     rozciąga się na szerokość rodzica - w panelu podpowiedzi strzałka przy
     „Pokaż wszystkie wyniki" urosła do pół ekranu. Rozmiar nadajemy z CSS
     wszystkim ikonom panelu. */
  .ac svg{width:14px;height:14px;flex:none}
  .ac .acgo svg,.ac .acmorearr svg{width:13px;height:13px}
  .ac .acempty .btn svg{width:13px;height:13px}
  .ac .acmore{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3)}
  .ac .acmorearr{display:inline-flex;align-items:center}
  .ac .acgo{display:inline-flex;align-items:center;margin-left:auto;color:var(--cx-ink-20)}
  /* nagłówek panelu: etykieta z lewej, licznik z prawej */
  .ac .achead{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-3);
      padding:9px var(--space-4);border-bottom:1px solid var(--line);
      font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
      color:var(--muted)}
  .ac .achead .account{letter-spacing:0;text-transform:none;font-weight:600;color:var(--soft)}
  .ac .acitem{display:flex;align-items:center;gap:var(--space-3)}
  .ac .acic{overflow:hidden}
  .ac .acic .prodico{width:100%;height:100%;object-fit:contain;display:block}

  /* „Pokaż więcej" dziedziczył wygląd głównego przycisku: lime i padding
     3px 3px 3px 24px pod płytkę szewronu, której ten guzik nie ma - stąd
     tekst dosunięty do lewej i wąski, przyklejony do krawędzi kształt.
     To akcja porządkowa pod listą, nie CTA marki: pełna szerokość listy,
     obrys zamiast wypełnienia, tekst na środku. */
  /* Przycisk wtórny, nie pas na całą szerokość: rozciągnięty na 100% wyglądał
     w hoverze jak ciemna belka przez całą kolumnę. Teraz dopasowuje się do
     treści i stoi na środku. */
  .loadmore{display:inline-flex;width:auto;min-width:200px;max-width:100%;
      justify-content:center;align-items:center;gap:9px;
      height:auto;margin:var(--space-5) auto 0;padding:12px var(--space-6);
      background:transparent;border:1px solid var(--line2);border-radius:var(--radius-md);
      color:var(--text);font-size:14px;font-weight:500;
      transition:background .14s ease,border-color .14s ease,color .14s ease}
  /* hover jak w innych elementach jasnych sekcji - rozjaśnienie, nie inwersja */
  .loadmore:hover{background:var(--cx-mist);border-color:var(--cx-ink-20);
      color:var(--accent-strong);filter:none}
  .loadmore .chev{display:none}

  /* Wiersz listy kończy się tym samym guzikiem „Czytaj dalej" co wiersze
     na stronie głównej - jeden komponent, jeden wygląd. Kolumna strzałki
     (18px) ustępuje miejsca guzikowi o naturalnej szerokości. */
  .artrow{grid-template-columns:minmax(0,1fr) auto auto auto}
  .arts .readgo{flex:none;display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
      padding:7px 13px;border-radius:var(--radius-sm);border:0;background:#F3F4F4;
      font-size:12.5px;font-weight:600;color:var(--text);
      transition:background .16s ease,color .16s ease}
  .arts .readgo svg{width:13px;height:13px}
  /* ── Wiersz listy po nowemu (paczka 16.09) ──────────────────────────────
     Kategoria i data jako eyebrow nad tytułem, więc wiersz ma dwie kolumny:
     treść i „Czytaj dalej". */
  .artrow{grid-template-columns:minmax(0,1fr) auto}
  .arteyebrow{display:flex;align-items:center;gap:10px;margin-bottom:3px}
  .arteyebrow .artcat{font-size:10.5px}
  .arteyebrow .artdate{font-size:11.5px}
  .arteyebrow .artcat + .artdate{padding-left:10px;border-left:1px solid var(--line2)}

  /* ── Paginacja ──────────────────────────────────────────────────────────
     Licznik po lewej mówi, gdzie jesteś; numery po prawej pozwalają skoczyć.
     Bieżąca strona to plakietka ink/lime - ten sam sygnał co plakietki stanu,
     żeby nie mnożyć wariantów. */
  .pager{display:flex;align-items:center;justify-content:space-between;
      flex-wrap:wrap;gap:var(--space-4);margin-top:var(--space-6);
      padding-top:var(--space-5);border-top:1px solid var(--line)}
  .pagercount{font-size:13px;color:var(--muted)}
  .pagercount b{font-weight:600;color:var(--text)}
  .pagernav{display:flex;align-items:center;gap:var(--space-4)}
  .pagerlist{list-style:none;display:flex;align-items:center;gap:4px;margin:0;padding:0}
  .pagergap{padding:0 2px;color:var(--soft);font-size:13.5px}
  .pagerpage{display:grid;place-items:center;min-width:34px;height:34px;padding:0 8px;
      border:0;background:none;cursor:pointer;font-family:inherit;
      border-radius:var(--radius-sm);font-size:13.5px;font-variant-numeric:tabular-nums;
      color:var(--body-fg);transition:background .14s ease,color .14s ease}
  .pagerpage:hover{background:var(--cx-mist);color:var(--text)}
  .pagerpage.on{background:var(--cx-ink);color:var(--cx-lime);font-weight:600}
  .pagerstep{display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 12px;
      border:0;background:none;cursor:pointer;font-family:inherit;
      border-radius:var(--radius-sm);font-size:13.5px;color:var(--text);
      transition:background .14s ease}
  .pagerstep:hover:not(:disabled){background:var(--cx-mist)}
  .pagerstep svg{width:14px;height:14px}
  .pagerstep.is-off{color:var(--cx-cloud-2);cursor:default}
  @media(max-width:640px){
    .pager{justify-content:center;text-align:center}
    .pagerstep span{display:none}
  }

  /* „Czytaj dalej" w liście wyników jest TEKSTEM, nie guzikiem (paczka
     16.09): akcją wiersza jest cały wiersz, więc plakietka tylko z nim
     konkurowała. Tym samym znika problem z jej kolorem na hoverze. */
  .arts .readgo{padding:0;background:none;border:0;color:var(--muted);
      font-weight:500;font-size:12.5px}
  .artrow:hover .readgo{background:none;color:var(--accent-strong)}
  .artrow:hover .readgo svg{transform:translateX(2px)}
  @media(max-width:760px){
    .artrow{grid-template-columns:minmax(0,1fr) auto}
    .arts .readgo{display:none}
  }

  /* ── Kolumna boczna artykułu ───────────────────────────────────────────
     Spis treści przyklejony pod nagłówkiem strony, powiązane, a na końcu
     wyjście do wsparcia - kolejność od „poruszam się po tym artykule"
     do „ten artykuł mi nie wystarczył". */
  .artside{align-self:start;position:sticky;top:var(--space-5);
      display:flex;flex-direction:column;gap:var(--space-5)}
  .sidetoc .sideh{margin-bottom:var(--space-3)}
  /* Spis treści jest ROZWINIĘTY W CAŁOŚCI, bez własnego paska przewijania
     (polecenie Radka 30.09: „nie chcę tutaj paska przewijania, wszystko ma być
     rozwinięte"). Do tego dnia stał tu sufit `52vh` z `overflow-y:auto`, więc
     przy dłuższym artykule w karcie siedziało okienko na kilka pozycji,
     a reszta chowała się za szarym paskiem - czyli spis treści, którego nie
     widać w całości.
     Co ten sufit naprawdę załatwiał, patrz `.artside--dluga` niżej: kolumna
     jest przyklejona, a element przyklejony WYŻSZY OD OKNA ma dół poza
     zasięgiem. Sufit rozwiązywał to kosztem tego, po co spis istnieje. */
  .toc{display:flex;flex-direction:column;gap:1px;
      border-left:2px solid var(--line2)}
  .tocitem{display:block;padding:6px 0 6px var(--space-4);margin-left:-2px;
      border-left:2px solid transparent;font-size:13px;line-height:1.4;
      color:var(--muted);text-decoration:none;
      transition:color .14s ease,border-color .14s ease}
  .tocitem--h3{padding-left:calc(var(--space-4) + 12px);font-size:12.5px}
  .tocitem:hover{color:var(--text)}
  .tocitem.on{color:var(--accent-strong);border-left-color:var(--cx-lime);font-weight:600}

  .sidehelp{display:flex;flex-direction:column;gap:6px;padding:var(--space-5);
      background:var(--cx-ink);border-radius:var(--radius-lg);color:var(--on-dark)}
  .sidehelp b{font-family:var(--font-display);font-weight:500;font-size:16px;
      color:var(--cx-white)}
  .sidehelp span{font-size:13px;line-height:1.5;color:var(--cx-lime-soft)}
  .sidehelp .btn{margin-top:var(--space-3);align-self:flex-start}
  /* Kolumna boczna przestaje być przyklejona, gdy jest WYŻSZA OD OKNA.
     Klasę nakłada `ukladArtykuluNaWasko()` po zmierzeniu - CSS tego nie umie
     powiedzieć, bo nie zna wysokości własnej treści.
     Powód jest twardy: element `position:sticky` wyższy od okna zatrzymuje się
     na `top` i jego DÓŁ jest nie do obejrzenia - przewijanie strony go nie
     dosuwa. Przy spisie z dwudziestoma nagłówkami znaczyłoby to ostatnie
     pozycje, do których nie da się dojść. Niepoprzyklejana kolumna po prostu
     jedzie z treścią i widać ją całą.
     Selektor musi być `aside.artside--dluga`, a nie sama klasa: wyżej stoi
     `aside.artside{position:sticky}` o mocy (0,1,1), której reguła o mocy
     (0,1,0) nie przebije. Zmierzone - klasa się nakładała, a `position`
     dalej czytał `sticky`, czyli „klasa jest" wyglądało jak „działa". */
  aside.artside--dluga{position:static}
  @media(max-width:900px){
    .artside{position:static}
  }

  .tocitem--h1{padding-left:var(--space-4)}
  .tocitem--h2{padding-left:calc(var(--space-4) + 12px);font-size:12.5px}

  /* Nagłówek i lista to dwa osobne dzieci .artside, więc dzielił je zarówno
     margines nagłówka (12px), jak i odstęp kolumny (24px) - razem 36px, czyli
     więcej niż przerwa MIĘDZY blokami. Nagłówek traci własny margines, a lista
     odejmuje odstęp kolumny, zostawiając 10px pod tytułem. */
  /* Odstęp pod etykietą kolumny - jedna wartość dla wszystkich takich
     nagłówków. Nagłówki będące osobnym dzieckiem .artside muszą jeszcze
     odjąć odstęp kolumny (24px), bo ten dolicza się do marginesu. */
  .artside{--sideh-gap:16px}
  .artside .sideh{margin-bottom:var(--sideh-gap)}
  .artside>.sideh{margin-bottom:0}
  .artside>.sideh + *{margin-top:calc(var(--sideh-gap) - var(--space-5))}

  /* Przycisk główny: tekst miał 24px z lewej, a do płytki szewronu tylko 12px
     - optycznie siedział przyklejony do prawej. Wyrównujemy oba odstępy
     i schodzimy z wagi 600 na 500 (przy 14,5px 600 było zbyt gęste). */
  .btn{font-weight:500;gap:18px}
  .btn:not(.loadmore):not(.btn--ghost){padding-left:18px}

  /* ══ Widok źródła: kafle kategorii ═══════════════════════════════════════
     Siatka na włosach: kontener ma kolor linii jako tło, kafle są białe,
     a przerwa 1px odsłania tło TYLKO między nimi. Dzięki temu nie ma ramek
     zewnętrznych ani podwójnych linii, a układ działa przy dowolnej liczbie
     kolumn - bez reguł na ostatni wiersz i ostatnią kolumnę.
     Hierarchia idzie z typografii i znaku, nie z rozmiaru kafla: wszystkie
     są równe, prowadzi nazwa w Clash Display, liczba jest przy niej. */
  /* Włosy rysują same kafle (górna i lewa krawędź), a siatka jest przesunięta
     o -1px i przycięta - dzięki temu nie ma linii na zewnętrznym obrysie ani
     podwójnych linii w środku, przy dowolnej liczbie kolumn.
     Wcześniej linie robiło tło kontenera widoczne w przerwach: działało, ale
     w ostatnim, niepełnym rzędzie puste miejsca świeciły szarą płachtą. */
  /* Dwie kolumny na sztywno: kafel jest szeroki, więc nazwa, liczba i sekcje
     stoją w jednej linii, a spis czyta się jak dwie kolumny tekstu. */
  /* Ujemny margines wystawał o piksel poza kolumnę i uruchamiał poziomy pasek
     przewijania - to jego widać było jako ciemną listwę nad siatką. Przy
     dwóch stałych kolumnach zewnętrzne włosy da się zdjąć wprost regułami
     na pierwszy rząd i pierwszą kolumnę, bez przesuwania całej siatki. */
  /* `grid-auto-rows:1fr` wyrównuje WSZYSTKIE kafle, nie tylko te w jednym
     rzędzie (decyzja 29). Bez tego kafel z długą listą sekcji rozpychał swój
     rząd, a sąsiednie zostawały niskie i siatka falowała. */
  .cats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
      grid-auto-rows:1fr;gap:0;margin-top:var(--space-6);
      background:var(--cx-white);border-radius:var(--radius-lg);overflow:hidden}
  .cattile:nth-child(-n+2){border-top:0}
  .cattile:nth-child(odd){border-left:0}
  @media(max-width:640px){
    .cattile{border-left:0}
    .cattile:first-child{border-top:0}
    .cattile:nth-child(2){border-top:1px solid var(--line)}
  }
  .cattile{display:grid;grid-template-columns:auto minmax(0,1fr) auto;
      align-items:center;gap:var(--space-4);
      padding:var(--space-4) var(--space-5);background:var(--cx-white);
      border-top:1px solid var(--line);border-left:1px solid var(--line);
      text-decoration:none;color:inherit;
      transition:background .18s ease,color .18s ease}
  /* Jasna mgła zamiast ciemnej zieleni - kafel ma się rozjaśnić, nie zmienić
     w inny widok. Sygnał niesie lime na znaku i strzałce, nie całe tło. */
  .cattile:hover{background:var(--cx-mist)}

  /* kwadratowa płytka ze znakiem - ta sama co przy produktach na stronie głównej */
  .catic{display:grid;place-items:center;width:44px;height:44px;flex:none;
      aspect-ratio:1;border-radius:10px;overflow:hidden;
      background:var(--cx-mist);color:var(--accent);
      transition:background .18s ease,color .18s ease}
  .catic svg{width:21px;height:21px}
  .catic .prodico{width:100%;height:100%;object-fit:contain;display:block}
  .cattile:hover .catic{background:var(--cx-lime);color:var(--cx-ink)}

  .cattx{display:flex;flex-direction:column;gap:3px;min-width:0}
  .catname{display:flex;align-items:baseline;gap:9px;min-width:0;
      font-family:var(--font-display);font-weight:500;font-size:16.5px;line-height:1.25;
      letter-spacing:-.01em;color:var(--text)}
  /* liczba artykułów: mała, tuż przy nazwie, cyframi tabelarycznymi */
  .catname i{font-style:normal;font-family:var(--font-body);font-weight:600;
      font-size:11.5px;letter-spacing:.04em;color:var(--muted);white-space:nowrap;
      font-variant-numeric:tabular-nums}
  .cattile:hover .catname{color:var(--accent-strong)}
  .cattile:hover .catname i{color:var(--accent-strong)}
  .catmeta{font-size:12px;color:var(--soft)}
  .cattile:hover .catmeta{color:var(--muted)}

  .catgo{display:flex;align-items:center;justify-content:center;color:var(--cx-cloud-2);
      transition:color .18s ease,transform .18s ease}
  .catgo svg{width:14px;height:14px}
  .cattile:hover .catgo{color:var(--accent-strong);transform:translateX(2px)}

  /* płytka ze znakiem marki w nagłówku źródła (źródła nie mają logotypów) */
  .appHead .ic--mark{background:rgba(173,247,99,.14);color:var(--cx-lime)}
  .appHead .ic--mark .cx-mark{transform:scale(1.25)}

  /* nagłówek sekcji nad kaflami */
  .secHead{margin-bottom:var(--space-2)}
  .secHead h2{font-family:var(--font-display);font-weight:400;
      font-size:clamp(22px,2.4vw,30px);letter-spacing:-.01em;margin-top:6px}
  .secHead p{margin-top:6px;font-size:14.5px;color:var(--muted)}

  /* ══ Listing z kolumną sekcji ════════════════════════════════════════════
     Prawa kolumna trzyma spis sekcji tej strony i przykleja się przy
     przewijaniu. Ten sam wzorzec co spis treści w artykule - czytelnik
     dostaje mapę tego, co niżej, zamiast przewijać 93 pozycje w ciemno. */
  .kbwrap{display:grid;grid-template-columns:minmax(0,1fr) 236px;
      gap:clamp(24px,3vw,48px);align-items:start}
  /* Jedna sekcja = nie ma czego spisywać, więc `buildSecNav()` wyrzuca prawą
     kolumnę z drzewa. Bez tej reguły siatka trzymała po niej 236 px pustki
     i lista stała wąsko przy lewej krawędzi bez powodu. Warunek patrzy na
     obecność kolumny, a nie na liczbę grup - to układ ma iść za treścią. */
  .kbwrap:not(:has(> .kbside)){grid-template-columns:minmax(0,1fr)}
  .kbmain{min-width:0}
  .kbside{position:sticky;top:var(--space-5);align-self:start}
  .secnavlist{display:flex;flex-direction:column;gap:1px;
      border-left:2px solid var(--line2)}
  .secnavitem{display:flex;align-items:baseline;gap:var(--space-3);
      padding:7px 0 7px var(--space-4);margin-left:-2px;
      border-left:2px solid transparent;font-size:13px;line-height:1.4;
      color:var(--muted);text-decoration:none;
      transition:color .14s ease,border-color .14s ease}
  .secnavitem span{min-width:0}
  /* liczby przy sekcjach miały 2,8:1 na białym - ciemniejszy szary daje 5,7:1 */
  .secnavitem i{margin-left:auto;font-style:normal;font-size:11.5px;
      font-variant-numeric:tabular-nums;color:var(--cx-gray-2)}
  .secnavitem:hover{color:var(--text)}
  .secnavitem.on{color:var(--accent-strong);border-left-color:var(--cx-lime);font-weight:600}
  .secnavitem.on i{color:var(--accent-strong)}
  /* pierwsza grupa nie potrzebuje górnego odstępu - kolumna wyrównuje się z listą */
  .kbmain .secgroup:first-child{margin-top:0}
  /* Próg zszedł z 1000 na 880 px: przy 1000 kolumna gasła już w podglądzie
     na laptopie, a lista ma wtedy i tak ~560 px, czyli dość na wiersz
     artykułu (paczka 16.09). */
  @media(max-width:880px){
    .kbwrap{grid-template-columns:minmax(0,1fr)}
    .kbside{display:none}
  }

  @media(max-width:640px){.cats{grid-template-columns:minmax(0,1fr)}}

  /* ══ Lockup i menu ═══════════════════════════════════════════════════════
     Nazwa portalu prowadzi, znak CXLABS jest podpisem wydawcy. Menu ma teraz
     pięć pozycji plus stan zalogowania i CTA, więc gaśnie wcześniej i oddaje
     miejsce prawej stronie paska. */
  .nav__brand{display:flex;flex-direction:column;gap:2px;text-decoration:none;flex:none}
  .brandname{font-family:var(--font-display);font-weight:500;font-size:17px;line-height:1.1;
      letter-spacing:-.01em;color:var(--cx-white)}
  .brandby{display:flex;align-items:center;gap:7px;font-size:11px;letter-spacing:.04em;
      color:var(--cx-ink-20)}
  .brandby .brandmark{height:11px;width:auto;display:block;color:var(--cx-mist)}
  .nav__brand:hover .brandby .brandmark{color:var(--cx-lime)}

  /* Sześć pozycji (doszły „Plany") nie mieści się już w 1180 px przy dawnych
     odstępach - pasek nachodził na menu konta. Odstępy są ciaśniejsze
     i liczone od szerokości okna, a pod 1100 px pasek i tak idzie w dwa rzędy. */
  /* Odstęp zjechał do zera: pozycje niosą teraz własny padding pod płytkę
     podświetlenia i to on daje światło między nimi. Przy dawnych 12-20 px
     pasek rozpychał się tak, że „Status" wchodził na „Zaloguj się". */
  /* Płytka podświetlenia dokłada do każdej pozycji własny padding, więc
     odstęp między nimi zszedł do zera - inaczej pasek rósł o ~130 px i przy
     włączonym wezwaniu „Nowe zgłoszenie" pozycje wchodziły na menu konta.
     Światła między etykietami jest tyle samo co dawniej, tylko niesie je
     teraz padding, nie gap. */
  /* 3 px przerwy, nie zero: gdy podświetlona pozycja sąsiaduje z aktywną,
     dwie płytki zlewały się w jeden szeroki prostokąt z dwoma napisami. */
  .nav__links{flex:0 1 auto;min-width:0;gap:3px}
  .nav__links>li>a,.nav__links>li>.navdropbtn{font-size:14.5px;white-space:nowrap;
      padding:0 10px}
  .nav__links>li>a,.nav__links>li>.navdropbtn{display:inline-flex;align-items:center;line-height:1.18}
  /* ikona domku przy „Bazie wiedzy" - biała, w linii z tekstem */
  .navico{width:16px;height:15px;flex:none;margin-right:8px;color:var(--cx-white)}
  .nav__right{display:flex;align-items:center;gap:clamp(10px,1.2vw,16px);flex:none}
  .nav__auth{display:inline-flex;align-items:center;gap:9px;font-size:14.5px;
      color:var(--cx-mist);text-decoration:none;white-space:nowrap}
  .nav__auth:hover{color:var(--cx-white)}
  .nav__auth--on{padding:6px 6px 6px 14px;border:1px solid var(--cx-ink-60);
      border-radius:var(--radius-md)}

  /* ── Konto zalogowanego: menu jak „Produkty" - na :hover i :focus-within,
     bez skryptu, więc działa też z klawiatury. Pozycje prowadzą do ekranów
     aplikacji panelu (ustawienia, hasło, wylogowanie), bo to ona trzyma sesję. */
  .acct{position:relative;display:flex}
  .acctbtn{display:inline-flex;align-items:center;gap:9px;padding:5px 10px 5px 6px;
      border:1px solid var(--cx-ink-60);border-radius:var(--radius-md);background:none;
      cursor:pointer;font-family:var(--font-body);font-size:14px;color:var(--cx-mist);
      transition:border-color .14s ease,color .14s ease}
  .acct:hover .acctbtn,.acct:focus-within .acctbtn{border-color:var(--cx-lime);color:var(--cx-white)}
  .acctava{display:grid;place-items:center;width:26px;height:26px;flex:none;
      border-radius:7px;background:var(--cx-lime);color:var(--cx-ink);
      font-size:11px;font-weight:700;letter-spacing:.02em}
  .acctname{max-width:170px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .acctbtn>svg{width:13px;height:13px;transition:transform .15s ease}
  .acct:hover .acctbtn>svg,.acct:focus-within .acctbtn>svg{transform:rotate(180deg)}
  .acctwrap{position:absolute;top:100%;right:0;padding-top:10px;opacity:0;visibility:hidden;
      transform:translateY(-4px);z-index:60;
      transition:opacity .15s ease,transform .15s ease,visibility .15s}
  .acct:hover .acctwrap,.acct:focus-within .acctwrap{opacity:1;visibility:visible;transform:none}
  .acctpanel{display:flex;flex-direction:column;gap:1px;width:288px;padding:var(--space-3);
      background:var(--cx-ink);border:1px solid var(--cx-ink-60);border-radius:var(--radius-lg);
      box-shadow:0 16px 40px rgba(0,0,0,.45)}
  .accthead{padding:4px 10px 9px;margin-bottom:5px;border-bottom:1px solid var(--cx-ink-60)}
  .accthead b{display:block;font-size:13.5px;font-weight:600;color:var(--cx-white);
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .accthead span{display:block;font-size:11.5px;color:var(--cx-ink-20);
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .acctitem{display:flex;align-items:center;gap:10px;width:100%;padding:8px 10px;border:0;
      border-radius:8px;background:none;cursor:pointer;text-align:left;
      font-family:var(--font-body);font-size:13.5px;color:var(--cx-lime-soft);
      text-decoration:none;transition:background .14s ease,color .14s ease}
  .acctitem svg{width:15px;height:15px;flex:none}
  .acctitem:hover{background:rgba(255,255,255,.07);color:var(--cx-white)}
  /* Plan wsparcia - ta sama informacja, którą aplikacja panelu pokazywała
     w swoim menu: czy wsparcie jest aktywne i do kiedy. Dane z sesji, nie z
     naszej strony. */
  /* Tarcza na środku wiersza, nie przy górnej krawędzi (decyzja 13):
     przy dwóch wierszach tekstu wyrównanie do góry zostawiało ją wysoko
     i płytka wyglądała, jakby się przekrzywiła. */
  .acctsup{display:flex;align-items:center;gap:9px;margin:0 0 6px;padding:9px 10px;
      border-radius:8px;background:rgba(173,247,99,.10)}
  .acctsup--expired{background:rgba(223,47,74,.12)}
  /* Konto bez planu. Nie jest to ani awaria, ani powód do zielonej tarczy, więc
     płytka jest stonowana: wsparcie działa, tylko na naszym koszcie i do trzech
     zgłoszeń. Wariant domyślny (limonkowy) zostaje wykupionej subskrypcji. */
  .acctsup--free{background:rgba(219,236,233,.08)}
  .acctsup--free .acctsup-ic{background:rgba(219,236,233,.12);color:var(--cx-mist)}
  .acctsup-ic{display:grid;place-items:center;width:26px;height:26px;flex:none;
      border-radius:7px;background:rgba(173,247,99,.18);color:var(--cx-lime)}
  .acctsup--expired .acctsup-ic{background:rgba(223,47,74,.18);color:#ff9fae}
  /* `display:block` na svg. Bez tego ikona jest elementem liniowym i siada na
     linii pisma - pod nią zostaje miejsce na ogonki liter, więc w kwadracie
     wygląda na podniesioną i przesuniętą, choć `place-items:center` niby ją
     wyśrodkowało. Centrowany był wiersz tekstu, nie rysunek. */
  .acctsup-ic svg{display:block;width:15px;height:15px}
  /* Korona „Admin" ma odróżniać się od pozycji dla każdego, ale nie krzyczeć:
     to skrót dla dwóch osób, a nie główna akcja ekranu. */
  .acctitem--admin{color:var(--cx-lime)}
  .acctitem--admin svg{color:inherit}
  .acctsup b{display:block;font-size:12.5px;font-weight:600;color:var(--cx-white)}
  /* `> div span`, a NIE `.acctsup span`. Kwadrat z ikoną też jest spanem, więc
     szersza reguła nadpisywała mu `display:grid` (ma wyższą wagę: klasa+typ
     bije samą klasę) - kwadrat przestawał być siatką, a tarcza siadała na jego
     GÓRNEJ krawędzi. Wyglądało to na źle wyśrodkowaną płytkę, choć sam kwadrat
     stał idealnie pośrodku: zmierzone 29.09 na produkcji - kwadrat vs płytka
     0,00 px, rysunek vs kwadrat 5,42 px za wysoko. Ograniczenie reguły do
     kolumny z tekstem zdejmuje kolizję u źródła, zamiast leczyć ją wagą. */
  .acctsup > div span{display:block;font-size:11.5px;color:var(--cx-ink-20)}
  .acctsup a{color:var(--cx-lime);text-decoration:underline}
  /* Kropka stanu w menu konta stoi na końcu wiersza, nie przed etykietą:
     pozycje są tu listą pod sobą i rynna przed tekstem wcinałaby tylko tę
     jedną. Poświata zbędna - tło panelu jest jednolite. */
  .acctdot{margin-right:0;margin-left:auto;box-shadow:none}
  /* „Wyloguj się" czyta się jak pozycja wyłączona: `--cx-ink-20` to kolor
     podpisów, nie pozycji do kliknięcia. Kreska nad nim wystarczy, żeby
     oddzielić go od reszty - kolor ma mówić „klikalne", a nie „niedostępne". */
  .acctitem--out{margin-top:5px;padding-top:11px;border-top:1px solid var(--cx-ink-60);
      border-radius:0;color:var(--cx-mist)}
  .acctitem--out:hover{background:none;color:var(--cx-lime)}
  @media(max-width:560px){.acctname{display:none}.acctbtn{padding:5px 8px}}
  .nav__out{display:grid;place-items:center;width:28px;height:28px;border-radius:8px;
      background:rgba(255,255,255,.06);color:var(--cx-lime-soft);
      transition:background .14s ease,color .14s ease}
  .nav__out svg{width:15px;height:15px}
  .nav__auth--on:hover .nav__out{background:var(--cx-lime);color:var(--cx-ink)}
  /* Pięć pozycji mieści się do ~1080px. Niżej pasek najpierw zwęża odstępy
     i zmniejsza pismo, potem oddaje pozycje panelu (są też w stopce),
     a na końcu zostaje sam lockup z CTA. */
  @media(max-width:1080px){
    .nav__links{gap:14px}
    .nav__links>li>a,.nav__links>li>.navdropbtn{font-size:13.5px}
  }
  /* Zwężanie paska: zamiast gubić pozycje (wcześniej od 1100px znikały
     wszystkie poza trzema, a od 840px całe menu), pasek przechodzi w DWA
     RZĘDY - lockup z prawą stroną u góry, pełne menu pod nimi, oddzielone
     linią. Żadna pozycja nie wypada i nie trzeba do tego skryptu. */
  @media(max-width:1100px){
    .navin{flex-wrap:wrap;row-gap:var(--space-3)}
    .nav__brand{order:1}
    .nav__right{order:2;margin-left:auto}
    .nav__links{order:3;flex:1 0 100%;flex-wrap:wrap;row-gap:var(--space-2);
        padding-top:var(--space-3);border-top:1px solid var(--cx-ink-60)}
  }
  /* Zalogowany pasek jest szerszy o guzik konta (awatar + imię + strzałka),
     więc w 1180 px przestaje się mieścić i pozycje menu wchodzą pod ten guzik -
     awatar siadał na słowie „Status". Zmierzone: brakowało ~50 px przy każdej
     szerokości okna, bo ogranicza nas `max-width` paska, a nie okno.

     Stąd dwa stopnie, oba TYLKO dla zalogowanego:
       powyżej 1330 px  pasek dostaje 1290 px zamiast 1180 - miejsca w oknie
                        jest pod dostatkiem, więc wystarczy poluzować kaganiec;
       do 1330 px       menu schodzi do drugiego rzędu - dokładnie tak, jak
                        robi to od dawna na wąskich oknach. */
  body[data-konto="tak"] .navin{max-width:1290px}
  @media(max-width:1330px){
    body[data-konto="tak"] .navin{flex-wrap:wrap;row-gap:var(--space-3)}
    body[data-konto="tak"] .nav__brand{order:1}
    body[data-konto="tak"] .nav__right{order:2;margin-left:auto}
    body[data-konto="tak"] .nav__links{order:3;flex:1 0 100%;flex-wrap:wrap;
        row-gap:var(--space-2);padding-top:var(--space-3);
        border-top:1px solid var(--cx-ink-60)}
  }
  @media(max-width:560px){
    .nav__auth{display:none}
    /* lockup i CTA muszą się zmieścić w 400 px: nazwa portalu ustępuje
       miejsca, a CTA schodzi o stopień */
    .nav__brand{min-width:0}
    .brandname{font-size:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .brandby{font-size:10px}
    .nav__cta{padding:9px 14px;font-size:13px}
  }

  /* Powietrze między treścią a stopką - sekcja .kb kończyła się tuż nad nią. */
  #view>.kb{padding-bottom:clamp(56px,7vh,96px)}

  /* Nazwy sekcji na kaflu: trzy pierwsze od najliczniejszej, reszta jako „+n".
     Wcześniej stała tu sama liczba („4 sekcje”), która nie mówiła nic o tym,
     co w kategorii jest - a to ona decyduje, czy warto tam wejść. */
  .catsecs{display:flex;flex-wrap:wrap;gap:5px;margin-top:2px}
  .catsecs i{font-style:normal;font-size:11.5px;line-height:1.3;
      padding:3px 8px;border-radius:6px;background:var(--cx-mist);color:var(--muted);
      white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis;
      transition:background .18s ease,color .18s ease}
  .catsecs .catmore{background:none;color:var(--soft);padding-left:2px}
  .cattile:hover .catsecs i{background:var(--cx-white);color:var(--text)}
  .cattile:hover .catsecs .catmore{background:none;color:var(--muted)}
  /* kafel rośnie o rząd żetonów - wyrównanie do góry czyta się lepiej */
  .cattile{align-items:start}
  .catic{margin-top:2px}
  .catgo{margin-top:0;align-self:center}

  /* ══ Rozwijane „Produkty" w pasku ════════════════════════════════════════
     Menu dwupoziomowe: produkty w pionowej liście, kategorie produktu
     wysuwają się w bok. Całość na :hover / :focus-within - bez skryptu,
     działa z klawiatury. */
  .navdrop{position:relative;display:flex}
  .navdropbtn{display:inline-flex;align-items:center;gap:6px;padding:0;border:0;
      background:none;cursor:pointer;white-space:nowrap;
      /* przycisk nie dziedziczy kroju po rodzicu - bez tego „Produkty" szło
         systemowym fontem, inaczej niż pozostałe pozycje */
      font-family:var(--font-body);font-size:inherit;font-weight:inherit;
      line-height:inherit;letter-spacing:inherit;color:var(--cx-mist)}
  /* Daszek: „Icon Down" z Hover.css - po najechaniu podskakuje w dół.
     Dawny obrót o 180 stopni na :hover zszedł, bo gryzł się z tym ruchem
     (animacja na transform i tak wygrywa z regułą). Obrót zostaje przy
     panelu otwartym klikiem (.is-open, niżej w arkuszu) - tam niesie stan,
     a nie samo najechanie. */
  .navdropbtn svg{width:13px;height:13px;transition:transform .3s ease-out}
  .navdrop:hover .navdropbtn,.navdrop:focus-within .navdropbtn{color:var(--cx-white)}
  .navdropbtn:hover svg{animation:navIconDown .75s ease-out}
  @media (prefers-reduced-motion: reduce){ .navdropbtn:hover svg{animation:none} }

  .navdropwrap{position:absolute;top:100%;left:0;padding-top:10px;
      opacity:0;visibility:hidden;transform:translateY(-4px);z-index:60;
      transition:opacity .15s ease,transform .15s ease,visibility .15s}
  .navdrop:hover .navdropwrap,.navdrop:focus-within .navdropwrap{opacity:1;visibility:visible;
      transform:none}
  /* Padding poziomy zszedł z panelu na wiersze: dzięki temu podświetlenie
     idzie od krawędzi do krawędzi, a nie kończy się w powietrzu kilka
     pikseli przed ramką.

     `overflow:hidden` tu NIE WOLNO postawić, choć samo się prosi o przycięcie
     rogów wierszy: drugi poziom (kategorie) wysuwa się poza prawą krawędź
     panelu, więc obcięcie zjadało go w całości - menu wyglądało, jakby
     najechanie nic nie robiło. Rogi i tak są czyste, bo wiersze zaczynają się
     12 px od krawędzi, a promień ma 16 px. */
  .navdroppanel{display:flex;flex-direction:column;gap:1px;width:326px;
      padding:var(--space-3) 0;background:var(--cx-ink);border:1px solid var(--cx-ink-60);
      border-radius:var(--radius-lg);box-shadow:0 16px 40px rgba(0,0,0,.45)}

  .navrow{position:relative}
  .navprod{display:flex;align-items:center;gap:var(--space-3);
      padding:9px var(--space-4);border-radius:0;text-decoration:none;
      transition:background-color .22s ease}
  .navrow:hover>.navprod,.navrow:focus-within>.navprod,
  .navprod:hover{background-color:var(--nav-hover)}
  .navprodic{display:grid;place-items:center;width:32px;height:32px;flex:none;
      border-radius:8px;overflow:hidden;background:rgba(173,247,99,.14);color:var(--cx-lime)}
  .navprodic svg{width:17px;height:17px}
  .navprodic .prodico{width:100%;height:100%;object-fit:contain;display:block}
  .navprodtx{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1 1 auto}
  .navprodtx b{font-size:14px;font-weight:600;color:var(--cx-white);line-height:1.25}
  .navprodtx span{font-size:11.5px;color:var(--cx-ink-20)}
  .navmore{display:flex;align-items:center;color:var(--cx-ink-20);flex:none;
      transition:color .14s ease,transform .14s ease}
  .navmore svg{width:13px;height:13px}
  .navrow:hover>.navprod .navmore{color:var(--cx-lime);transform:translateX(2px)}

  /* drugi poziom */
  /* ODSTĘP ZERO (prośba Radka 30.09). Było tu 8 px i miało trzymać wysuwkę
     w zasięgu wskaźnika po drodze z wiersza - tyle że ten pasek NALEŻY do
     `.navrow`, więc przy zerze nie ma czego mijać: panele stykają się
     krawędziami i wskaźnik ani na chwilę nie wychodzi poza wiersz. */
  .navsubwrap{position:absolute;top:-9px;left:100%;width:326px;padding-left:0;
      opacity:0;visibility:hidden;transform:translateX(-4px);z-index:70;
      transition:opacity .14s ease,transform .14s ease,visibility .14s}
  .navrow:hover>.navsubwrap,.navrow:focus-within>.navsubwrap{opacity:1;visibility:visible;
      transform:none}
  /* `max-height` jest tu WARTOŚCIĄ WYJŚCIOWĄ, nie ostateczną - prawdziwą
     wylicza `dopasujWysuwke()` w szkielecie. Powód: wysuwka zaczyna się na
     wysokości SWOJEGO wiersza, a wiersz bywa nisko w panelu, więc `70vh`
     nie mówi nic o tym, ile miejsca zostało do dołu okna. Przy ostatnich
     produktach wysuwka schodziła pod krawędź ekranu (zgłoszenie Radka 30.09).
     Sama reguła zostaje, bo działa, zanim ruszy JavaScript. */
  .navsubpanel{display:flex;flex-direction:column;gap:1px;width:100%;
      max-height:min(420px,70vh);overflow-y:auto;overscroll-behavior:contain;
      padding:var(--space-3) 0;
      background:var(--cx-ink);border:1px solid var(--cx-ink-60);
      border-radius:var(--radius-lg);box-shadow:0 16px 40px rgba(0,0,0,.5);
      /* Firefox i nowe przeglądarki. Systemowy pasek jest tu jasny i wchodzi
         na ciemną płytę jak plama (prośba Radka 30.09). */
      scrollbar-width:thin;scrollbar-color:var(--cx-ink-40) transparent}
  /* Chromium i Safari - własny pasek. Suwak dostaje przezroczystą obwódkę
     i `background-clip:content-box`, bo inaczej dotyka krawędzi płyty:
     obwódka robi odstęp, którego `::-webkit-scrollbar` nie ma jak ustawić
     marginesem. */
  .navsubpanel::-webkit-scrollbar{width:10px}
  .navsubpanel::-webkit-scrollbar-track{background:transparent}
  .navsubpanel::-webkit-scrollbar-thumb{background:var(--cx-ink-40);
      border-radius:999px;border:3px solid transparent;background-clip:content-box}
  .navsubpanel::-webkit-scrollbar-thumb:hover{background:var(--cx-ink-20);
      border:3px solid transparent;background-clip:content-box}
  .navsubh{padding:2px var(--space-4) 7px;font-size:10.5px;font-weight:600;letter-spacing:.12em;
      text-transform:uppercase;color:var(--cx-ink-20)}
  /* Nagłówek grupy w wysuwce: nazwa SEKCJI, a pod nią jej kategorie. Jest
     odnośnikiem, nie etykietą - i to nie jest ozdoba: w dokumentacji API
     101 artykułów leży w sekcji poza jakąkolwiek kategorią, więc bez tego
     kliknięcia nie ma do nich wejścia z menu. Wielkość liter i odstęp jak
     w `.navsubh`, żeby poziom był widoczny od pierwszego spojrzenia, ale
     kolor jest limonkowy - to jest miejsce, w które można kliknąć. */
  .navsubg{display:flex;align-items:baseline;gap:var(--space-3);
      padding:9px var(--space-4) 7px;margin-top:7px;
      border-top:1px solid rgba(219,236,233,.1);
      font-size:11px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;
      color:var(--cx-lime);text-decoration:none;
      transition:background-color .22s ease}
  .navsubg:first-child{margin-top:0;padding-top:2px;border-top:0}
  .navsubg span{min-width:0}
  .navsubg i{margin-left:auto;font-style:normal;font-size:11px;letter-spacing:0;
      color:var(--cx-ink-20);font-variant-numeric:tabular-nums}
  /* Kolor MUSI tu stać, choć wygląda na powtórzenie tego wyżej. Portal ma
     globalną regułę `a:hover{color:var(--cx-ink)}` - dobrą na jasnych
     płytach i zabójczą tutaj, bo `--cx-ink` to DOKŁADNIE tło tej wysuwki.
     Bez tej linijki napis po najechaniu znikał (zgłoszenie Radka 30.09):
     zmierzone `getComputedStyle` dawało `rgb(18,32,33)` na tle
     `rgb(18,32,33)`. `.navsub` obok ma to od początku (`--cx-white`), więc
     usterka dotyczyła wyłącznie nagłówków grup, które dołożyłem tego dnia.
     Morał ten sam, co przy dymku klienta w wątku: tło i farba chodzą w parze,
     a przy odnośniku na ciemnym tle farbę trzeba podać JAWNIE. */
  .navsubg:hover{background-color:var(--nav-hover);color:var(--cx-lime)}

  .navsub{display:flex;align-items:baseline;gap:var(--space-3);
      padding:7px var(--space-4);border-radius:0;
      font-size:13px;color:var(--cx-lime-soft);text-decoration:none;
      transition:background-color .22s ease,color .22s ease}
  .navsub span{min-width:0}
  .navsub i{margin-left:auto;font-style:normal;font-size:11px;color:var(--cx-ink-20);
      font-variant-numeric:tabular-nums}
  .navsub:hover{background-color:var(--nav-hover);color:var(--cx-white)}

  .navprod--all{justify-content:center;gap:8px;margin-top:var(--space-3);padding-top:11px;
      border-top:1px solid var(--cx-ink-60);border-radius:0;
      font-size:13px;font-weight:600;color:var(--cx-lime)}
  .navprod--all svg{width:13px;height:13px}
  .navprod--all:hover{background:none;color:var(--cx-white)}
  /* przy wąskim oknie drugi poziom nie zmieści się w prawo - wychodzi w lewo */
  @media(max-width:1320px){
    .navsubwrap{left:auto;right:100%;padding-left:0;padding-right:0;
        transform:translateX(4px)}
  }
  /* Poniżej 840px „wg. produktu" zostaje pozycją menu, ale nie rozwija
     panelu - panel z dwoma poziomami potrzebuje szerokości, której tam nie ma. */
  @media(max-width:840px){
    .navdropwrap{display:none}
    .navdropbtn svg{display:none}
  }

  /* ══ Ekran „Status” (planowane wyłączenia) ══════════════════════════════
     Przeniesiony z aplikacji panelu do portalu: ta strona tylko pokazuje
     dane i nie wymaga logowania, więc nie ma powodu, żeby ładować pod nią
     Reacta z obcego serwera. Szata z paczki 16.09. */
  /* Pasek stanu NIE jest kaflem, więc świadomie nie ma klasy .band - inaczej `html:has(#view>.band)` włączyłoby na tej stronie scroll-snap-type:y mandatory (ekran kaflowy ze strony głównej), a razem z nim min-height:100svh i wyśrodkowanie. */
  .statusband{padding:var(--space-5) 0 0}
  .statusbar{display:flex;align-items:center;gap:var(--space-4); padding:var(--space-4) var(--space-5);background:var(--cx-white); border:1px solid var(--line);border-radius:var(--radius-md)}
  .statusdot{flex:none;width:10px;height:10px;border-radius:50%; background:var(--cx-green-500); box-shadow:0 0 0 4px rgba(107,210,16,.16)}
  .statustx{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
  .statustx b{font-size:15px;color:var(--text)}
  .statustx span{font-size:13px;color:var(--muted)}
  /* .btn--ghost jest wariantem pod ciemne tło (mist na ink); pasek stanu jest biały, więc tutaj ink na białym */
  .statusbar .btn--ghost{color:var(--text)!important;border-color:var(--line2)}
  .ic--out{display:grid;place-items:center;color:var(--cx-lime)}
  .ic--out svg{width:34px;height:34px}
  /* Telefon: pasek stanu przestaje być jednym rzędem. Wezwanie („Status
     monday.com", „Zobacz plany") nie kurczy się, więc w rzędzie zabierało
     opisowi całą szerokość i „Wszystkie usługi działają normalnie" łamało się
     po jednym słowie. Kropka i opis zostają obok siebie, wezwania schodzą
     pod nie na pełną szerokość. Reguła obejmuje też pasek na rozliczeniu,
     gdzie zamiast guzika stoi `.planacts`. */
  @media(max-width:700px){
    .statusbar{display:grid;grid-template-columns:10px minmax(0,1fr);
        column-gap:var(--space-3);row-gap:var(--space-4);align-items:start}
    .statusbar .statusdot{margin-top:6px}
    .statusbar>:not(.statusdot):not(.statustx){grid-column:1/-1;justify-content:center}
    .statusbar .planacts{display:flex;flex-wrap:wrap;gap:var(--space-3)}
    .statusbar .planacts>*{flex:1 1 auto;justify-content:center}
  }

  .statusbar--alert{border-color:rgba(180,35,24,.35); box-shadow:0 8px 16px rgba(180,35,24,.08)}
  .statusdot--alert{background:var(--cx-error); box-shadow:0 0 0 4px rgba(180,35,24,.16); animation:incPulse 2s ease-in-out infinite}
  .statusbar--alert .btn--ghost{color:var(--text)!important;border-color:var(--line2)}

  /* ── Pasek dostępności 90 dni + oś incydentów (#status) ──────────────────
     Kolory segmentów są SEMANTYCZNE (stan usługi), nie z palety marki: zielony
     = operacyjne, żółty = częściowa awaria, pomarańcz = poważna, czerwony =
     krytyczna. Tak samo jak --cx-error jest już poza paletą marki. */
  .uptband{padding:var(--space-6) 0 0}
  .uptband .wrap{position:relative}
  .secgroup-head--up{margin-bottom:var(--space-4)}
  .upgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:var(--space-5)}
  .upcard{background:var(--cx-white);border:1px solid var(--line);border-radius:var(--radius-lg);padding:var(--space-5)}
  .upcard-head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-4);margin-bottom:var(--space-4)}
  .upname{font-size:16px;color:var(--text)}
  .upmeta{display:block;font-size:12px;color:var(--muted);margin-top:2px}
  .upright{text-align:right;flex:none}
  .upuptime{display:block;font-size:20px;font-weight:700;color:var(--text);line-height:1.1}
  .upuptime-l{display:block;font-size:11px;font-weight:400;color:var(--soft);letter-spacing:.04em}
  .uplink{display:inline-block;margin-top:4px;font-size:12px;color:var(--muted)}
  .uplink:hover{color:var(--text)}
  .upbar{display:flex;gap:2px;height:38px;align-items:stretch}
  .upseg{flex:1 1 0;min-width:0;border-radius:2px;background:var(--cx-green-500);transition:transform .08s ease}
  .upseg:hover{transform:scaleY(1.12)}
  .upseg--minor{background:#f0a815}
  .upseg--major{background:#e8730c}
  .upseg--critical{background:var(--cx-error)}
  .upseg--maintenance{background:#7bb0e8}
  .upscale{display:flex;justify-content:space-between;font-size:11px;color:var(--soft);margin-top:6px}
  .uptip{position:absolute;transform:translate(-50%,-100%);background:var(--cx-ink);color:var(--cx-white);
      font-size:12px;line-height:1.4;padding:7px 10px;border-radius:8px;max-width:240px;
      pointer-events:none;z-index:5;box-shadow:0 8px 20px rgba(0,0,0,.2)}
  .uptip b{display:block;font-weight:700;margin-bottom:2px;color:var(--cx-lime-soft)}
  .upnone{font-size:13px;color:var(--muted);margin:var(--space-4) 0 0}
  .incall{margin-top:var(--space-5);border-top:1px solid var(--line)}
  .incall>summary{display:flex;align-items:center;gap:var(--space-3);padding:12px 0 2px;
      cursor:pointer;list-style:none;font-size:13px;font-weight:600;color:var(--muted)}
  .incall>summary::-webkit-details-marker{display:none}
  .incall>summary::before{content:"▸";color:var(--soft);transition:transform .12s ease;font-size:11px}
  .incall[open]>summary::before{transform:rotate(90deg)}
  .incall>summary:hover{color:var(--text)}
  .incall>summary:focus-visible{outline:2px solid var(--cx-lime);outline-offset:2px;border-radius:4px}
  .incall-n{display:inline-grid;place-items:center;min-width:20px;height:20px;padding:0 6px;
      border-radius:999px;background:var(--surface-alt);color:var(--muted);font-size:12px}
  .incwrap{padding-top:var(--space-2)}
  .incrow{border-bottom:1px solid var(--line)}
  .incrow:last-child{border-bottom:0}
  .incrow>summary{display:flex;align-items:center;gap:var(--space-3);padding:10px 0;cursor:pointer;list-style:none}
  .incrow>summary::-webkit-details-marker{display:none}
  .incrow>summary:focus-visible{outline:2px solid var(--cx-lime);outline-offset:2px;border-radius:4px}
  .incdot{flex:none;width:9px;height:9px;border-radius:50%;background:var(--cx-green-500)}
  .incrow--minor .incdot{background:#f0a815}
  .incrow--major .incdot{background:#e8730c}
  .incrow--critical .incdot{background:var(--cx-error)}
  .incname{flex:1;min-width:0;font-size:14px;color:var(--text);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .incmeta{font-size:12px;color:var(--muted);white-space:nowrap}
  .incimpact{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--soft);white-space:nowrap}
  .inctl{list-style:none;margin:2px 0 var(--space-3);padding:0 0 0 var(--space-5);border-left:2px solid var(--line)}
  .inctl li{display:grid;grid-template-columns:auto auto 1fr;gap:var(--space-3);align-items:baseline;padding:4px 0;font-size:13px}
  .tlst{font-weight:600;color:var(--text);white-space:nowrap}
  .tltm{font-size:12px;color:var(--soft);font-variant-numeric:tabular-nums;white-space:nowrap}
  .tltx{color:var(--body-fg);min-width:0}
  .inckomp{font-size:12px;color:var(--muted);margin:0 0 var(--space-3)}
  .inclink{display:inline-block;font-size:12px;color:var(--muted);margin-bottom:var(--space-4)}
  .inclink:hover{color:var(--text)}
  @media(max-width:520px){
    .inctl li{grid-template-columns:1fr;gap:1px;padding:6px 0}
    .incname{white-space:normal}
    .incrow>summary{flex-wrap:wrap}
    .upbar{height:32px}
  }

  .outnote--wide li{max-width:72ch}
  .outcard{display:grid;grid-template-columns:96px minmax(0,1fr); gap:var(--space-5);padding:var(--space-5);margin-bottom:var(--space-4); background:var(--cx-white);border:1px solid var(--line); border-radius:var(--radius-lg)}
  .outcard--next{border-color:var(--line2);box-shadow:0 8px 16px rgba(0,0,0,.06)}
  .outwhen{display:flex;flex-direction:column;align-items:center;justify-content:center; gap:2px;padding:var(--space-3) 0;background:var(--cx-mist); border-radius:var(--radius-md);text-align:center}
  /* dzień tygodnia nad datą - okna serwisowe wypadają nocą, więc to, czy to weekend, jest ważniejsze niż sama liczba */
  .outdow{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--soft)}
  .outday{font-family:var(--font-display);font-size:34px;line-height:1;color:var(--text)}
  .outmon{font-size:12.5px;color:var(--body-fg)}
  .outyear{font-size:11.5px;color:var(--soft)}
  .outbody{min-width:0}
  .outtop{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-3)}
  .outhours{font-size:13.5px;color:var(--body-fg)}
  .outhours i{color:var(--soft);font-style:normal}
  .outstate{display:inline-flex;align-items:center;padding:4px 10px;border-radius:8px; font-size:11.5px;font-weight:700;letter-spacing:.03em;text-transform:uppercase}
  .outstate--plan{background:var(--cx-ink);color:var(--cx-lime)}
  .outstate--maybe{background:var(--cx-cloud);color:var(--cx-gray-1)}
  .outstate--done{background:var(--cx-mist);color:var(--cx-turquoise-600)}
  .outbody h4{font-family:var(--font-display);font-weight:500;font-size:19px; line-height:1.25;color:var(--text);margin:var(--space-3) 0 0}
  .outbody>p{margin:var(--space-2) 0 0;max-width:62ch;font-size:14.5px; line-height:1.6;color:var(--body-fg)}
  .outmeta{list-style:none;display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:var(--space-3);margin:var(--space-4) 0 0;padding:var(--space-4) 0 0; border-top:1px solid var(--line)}
  .outmeta li{display:flex;flex-direction:column;gap:3px}
  /* lista komponentów bywa długa („Website - make.com, Scenario Executions
     - make.com, Apps - make.com”) - dostaje całą szerokość karty */
  .outmeta li.outmeta--wide{grid-column:1/-1}
  .outchips{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}
  /* waga selektora jak `.outmeta b` (0,2,0) i dalej w pliku, więc wygrywa */
  .outmeta b.outchip{display:inline-flex;align-items:center;gap:6px;padding:3px 9px;
      border-radius:7px;background:var(--cx-mist);border:1px solid var(--line);
      font-size:12.5px;font-weight:500;color:var(--body-fg)}
  .outmeta b.outchip i{font-style:normal;font-weight:700;font-size:10.5px;
      letter-spacing:.05em;color:var(--cx-turquoise-600)}
  .outmeta span{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--soft)}
  .outmeta b{font-size:14px;font-weight:500;color:var(--text)}
  .outtags{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-top:var(--space-4)}
  .outtag{padding:4px 10px;border-radius:8px;background:var(--cx-mist); border:1px solid var(--line);font-size:12.5px;color:var(--body-fg)}
  /* ── Sygnet przy znaku ────────────────────────────────────────────────────
     Do 29.09 stał tu komplet reguł na wariant „adres portalu" (`.nav__brand--url`,
     `.brandurl`). Adres ustąpił miejsca znakowi CXLABS (polecenie Radka 29.09,
     reguły `--znak` niżej), więc tamte selektory nie mają już czego opisywać
     i zostały zdjęte - w szablonie nie ma ani jednego elementu z tymi klasami.
     Zostaje sam sygnet, bo jego używa OBA warianty. Uwaga przy sprzątaniu CSS-u:
     usuwamy CAŁE reguły, nigdy pojedynczą deklarację - osierocona deklaracja
     zjada regułę, która stoi po niej, i objawia się dopiero gdzie indziej. */
  .brandsyg{display:block;width:32px;height:32px;flex:none}

  /* Znak z logotypem CXLABS (polecenie Radka 29.09). Układ jak przy adresie -
     koło ratunkowe, odstęp, znak - więc reguły są bliźniacze; osobna nazwa
     klasy jest po to, żeby dało się wrócić do adresu bez ruszania niczego.
     Podwójna klasa z tego samego powodu co przy `--url`: starsza reguła
     `.nav__brand` ustawia `flex-direction:column` i bez niej znak stanąłby
     POD kołem. */
  .nav__brand.nav__brand--znak{display:inline-flex;flex-direction:row;
      align-items:center;gap:12px;text-decoration:none}
  /* Wysokość, a nie szerokość: znak ma w pliku 36 jednostek wysokości, ale
     same litery zajmują z tego 16 (reszta to powietrze nad i pod), więc przy
     30 px wysokości pudełka litery mają ~13 px - tyle, ile miał napis, który
     tu stał wcześniej. Szerokość liczy się sama z proporcji. */
  .brandlogo{display:block;height:30px;width:auto;flex:none;
      color:var(--cx-white);opacity:.92;transition:opacity .15s}
  .nav__brand--znak:hover .brandlogo{opacity:1}
  @media(max-width:560px){.brandsyg{width:28px;height:28px}}

  /* ── Jeden guzik zgłoszenia w całym portalu ──────────────────────────────
     Krążyło sześć wariantów treści („Poproś o wsparcie", „Załóż zgłoszenie",
     „Mam problem z tym tematem"…) i dwa układy ikony. Teraz jeden: plus PRZED
     napisem, bez ciemnej płytki - akcja jest dodawaniem, więc plus czyta się
     pierwszy. */
  .btn--tk{gap:10px;padding:12px 20px}
  .btn--tk .btnic--pre{width:auto;height:auto;background:none;color:currentColor;order:-1}
  .btn--tk .btnic--pre svg{width:17px;height:17px}
  .btn--tksm{padding:9px 16px;font-size:13.5px}
  .btn--tksm .btnic--pre svg{width:15px;height:15px}
  /* Płytka `.btnic` niesie wyśrodkowanie tylko wewnątrz `.btn`, a `.nav__cta`
     nie jest `.btn` - bez własnego inline-flex SVG siadał na linii bazowej
     tekstu, czyli za nisko. */
  .nav__cta{gap:9px;align-items:center}
  .nav__cta .btnic--pre{display:inline-flex;align-items:center;justify-content:center;
      width:auto;height:auto;background:none;color:currentColor;line-height:0}
  .nav__cta .btnic--pre svg{display:block;width:16px;height:16px}

  /* ── Moje rozliczenie ────────────────────────────────────────
     Reguły z makiety `rozliczenie.html` (paczka 16.09-2). Ekran stoi na
     istniejących cegiełkach portalu (kb, secgroup, statusband, kbside) -
     dochodzą tylko lista stanów usługi, nota pod kartą planu i warianty
     paska stanu dla planu wygasającego i wygasłego. */
.statusbar--alert{border-color:rgba(180,35,24,.35);
      box-shadow:0 8px 16px rgba(180,35,24,.08)}
.statusdot--alert{background:var(--cx-error);
      box-shadow:0 0 0 4px rgba(180,35,24,.16);
      animation:incPulse 2s ease-in-out infinite}
.statusbar--alert .btn--ghost{color:var(--text)!important;border-color:var(--line2)}
/* Lista stanów usug w kolumnie bocznej */
  .svclist{list-style:none;display:flex;flex-direction:column}
.svclist li{display:flex;align-items:center;justify-content:space-between;
      gap:var(--space-3);padding:8px 0;border-bottom:1px solid var(--line);
      font-size:13.5px;color:var(--text)}
.svclist li:last-child{border-bottom:0}
.svc{font-style:normal;font-size:11.5px;font-weight:700;letter-spacing:.03em;
      padding:3px 8px;border-radius:6px}
/* turquoise-600, nie 500: plakietka ma wasne tło mist, więc kontrast
     liczy się wobec #F4F9F8, nie wobec białego */
  .svc--ok{background:var(--cx-mist);color:var(--cx-turquoise-600)}
.svc--warn{background:rgba(255,204,0,.18);color:#6b5200}
.svc--bad{background:rgba(180,35,24,.10);color:var(--cx-error)}
.accsave{display:flex;align-items:center;justify-content:space-between;
      flex-wrap:wrap;gap:var(--space-3);margin-top:var(--space-5);
      padding-top:var(--space-4);border-top:1px solid var(--line)}
.accsavetx{font-size:12.5px;color:var(--muted)}
.accsave .btn{white-space:nowrap}
/* ══ Moje rozliczenie ═════════════════════════════════════════════════════ */
  .statusdot--warn{background:#ffcc00;box-shadow:0 0 0 4px rgba(255,204,0,.18)}
.statusdot--off{background:var(--cx-error);box-shadow:0 0 0 4px rgba(180,35,24,.14)}
.statusbar--soon{border-color:rgba(255,204,0,.5);background:rgba(255,204,0,.06)}
.statusbar--out{border-color:rgba(180,35,24,.35);background:rgba(180,35,24,.04)}
/* Plakietka przy pozycji menedżera - mówi, dlaczego ten ktoś widzi więcej
     niz reszta zespolu. */
  .acctrola{font-style:normal;margin-left:auto;padding:2px 7px;border-radius:4px;
      background:var(--cx-mist);color:var(--muted);font-size:10px;font-weight:700;
      letter-spacing:.04em;text-transform:uppercase}
.accsavetx:empty{display:none}
/* Guzik zapisu stoi sam w wierszu, więc do prawej. Guzik zostaje limonkowy
     z ciemnym napisem; odwrócona jest tylko ikona - sama dyskietka w ink,
     bez ciemnej płytki pod spodem (płytka jest sygnałem akcji nawigacyjnej). */
  .accsave:has(>.btnsave:only-child){justify-content:flex-end}
/* Kropka nad guzikiem zapisu: jedyny sygnał, że na ekranie wiszą zmiany,
     których nikt jeszcze nie zapisał. Obwódka w kolorze karty, żeby kropka
     odcinała się od guzika. */
  .btnsave{gap:10px;padding:11px 20px}
  .btnsave--on{position:relative}
  .btnsave--on::after{content:"";position:absolute;top:-3px;right:-3px;
      width:9px;height:9px;border-radius:50%;background:var(--cx-ink);
      box-shadow:0 0 0 2px var(--cx-white)}
/* Stan wygasania i wygaśnięcia: nota pod kartą planu zmienia ton, a
     plakietki schodzą z zielonego na neutralne - inaczej przełącznik stanów
     zmieniał tylko pasek u góry i wyglądał na martwy. */
  .accsavetx--warn{color:#6b5200}
.accsavetx--off{color:var(--cx-error)}
.svc--off{background:var(--cx-mist);color:var(--muted)}
@media(prefers-reduced-motion:reduce){
  .statusdot--alert{animation:none}
  }

  /* ── Cennik (ekran „Plany") ───────────────────────────────────────────────
     Reguły przeniesione z makiety `plany.html` / `_nowy.css` (paczka 16.09-2)
     w całości, razem z modalem „Co jest w raporcie" i kalkulatorem Enterprise.
     Ekran jest ciemny i pełnoekranowy pasmami - stąd `#view.plpage`, klasę
     zakłada i zdejmuje viewPlany(). */
/* .btn--ghost jest wariantem pod ciemne tło (mist na ink); pasek stanu
     jest biały, więc tutaj ink na białym */
  #view:not(.plpage) .statusbar .btn--ghost{color:var(--text);border-color:var(--line2)}
#view:not(.plpage) .statusbar .btn--ghost:hover{color:var(--cx-ink);background:var(--cx-mist);
      border-color:var(--cx-gray-3)}
/* ══ Plany wsparcia ══════════════════════════════════════════════════════
     Strona ofertowa na ciemnym tle marki. Cennik trzy karty: środkowa jest
     polecana - wyższa (ujemny margines), lime obrys i pełny przycisk;
     boczne mają obrys zamiast wypełnienia, więc wzrok idzie do środka. */
  .plpage{background:var(--cx-ink)}
.plband{padding:clamp(48px,7vh,88px) 0}
/* Padding pasm musi być pisany przez id - `#view>.band` (1,0,1) bije
     każdą regułę klasową, więc sama `.plband` nie miała szans. */
  /* Cień „progu" należy do kaflowego ekranu strony głównej (jedna sekcja na
     ekran). Na cenniku pasma są zwykłą treścią, więc go nie ma. */
  #view.plpage>.band--dark{box-shadow:none}
#view.plpage>.plband{padding:clamp(56px,8vh,96px) 0}
/* Cennik idzie zaraz po naglowku strony, wiec pelny gorny oddech pasm
     jest tu zbedny - pierwsze pasmo dostaje wlasna, mniejsza miare. */
  #view.plpage>#warianty{padding-top:clamp(24px,3.5vh,40px)}
#view.plpage>.plband--cmp{background:var(--cx-ink-80);
      padding-bottom:clamp(80px,11vh,120px)}
.plband--cmp{background:var(--cx-ink-80)}
.plh2{font-family:var(--font-display);font-size:clamp(26px,3vw,38px);font-weight:400;
      letter-spacing:-.01em;line-height:1.2;color:var(--cx-white);margin-top:var(--space-3)}
.pllead{margin-top:var(--space-4);max-width:62ch;font-size:15.5px;line-height:1.6;
      color:var(--cx-lime-soft)}
/* Odstęp nad kartami daje padding kontenera, nie margines: marginesy
     sąsiadujące zlewają się w jeden. Plakietka „Rekomendowany dla Ciebie"
     wystaje 13 px ponad kartę, więc stąd ma miejsce. */
  .pltiers{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
      gap:var(--space-4);align-items:start;margin-top:0;
      padding-top:clamp(32px,5vh,48px)}
.pltier{display:flex;flex-direction:column;padding:var(--space-6);
      background:rgba(255,255,255,.03);border:1px solid var(--cx-ink-60);
      border-radius:var(--radius-lg)}
/* Karta wskazana przez konfigurator. Wyróżnienie NIE ZMIENIA wymiarów:
     zmienia się przy każdym ruchu suwaka, więc podciągnięcie karty albo
     grubsza ramka szarpałyby całym rzędem. Drugi piksel ramki robi cień
     wewnętrzny, który nie zajmuje miejsca. */
  .pltier{position:relative;transition:border-color .16s ease,box-shadow .16s ease,background .16s ease}
.pltier--best{background:var(--cx-ink-80);border-color:var(--cx-lime);
      box-shadow:inset 0 0 0 1px var(--cx-lime),0 16px 40px rgba(0,0,0,.35)}
.plflag{position:absolute;top:-13px;left:var(--space-6);
      padding:5px 12px;background:var(--cx-lime);color:var(--cx-ink);
      font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
      border-radius:6px}
/* „Twój plan” stoi po PRAWEJ i w innej barwie niż „Rekomendowany dla Ciebie”
   - na jednej karcie mogą stać obie plakietki naraz. */
.plflag--moj{left:auto;right:var(--space-6);background:var(--cx-white);color:var(--cx-ink)}
.plname{font-family:var(--font-display);font-size:22px;font-weight:500;
      color:var(--cx-white)}
.pldesc{margin-top:6px;font-size:13.5px;line-height:1.5;color:var(--cx-ink-20);
      min-height:40px}
/* odstęp między kwotą a „netto" robi gap, nie spacja w kodzie */
  .plprice{display:flex;align-items:baseline;flex-wrap:wrap;gap:8px;
      margin:var(--space-4) 0 var(--space-5);padding-bottom:var(--space-5);
      border-bottom:1px solid var(--cx-ink-60)}
.plprice b{font-family:var(--font-display);font-size:clamp(28px,3vw,36px);
      font-weight:400;letter-spacing:-.01em;color:var(--cx-white)}
.plprice span{font-size:13px;color:var(--cx-ink-20)}
/* „Indywidualna wycena" to nie kwota - mniejszy stopień, żeby mieściła się
     w jednej linii i nie udawała liczby obok 499 / 2 000 zł. */
  .pltier:last-child .plprice b{font-size:22px;white-space:nowrap}
.pllist{list-style:none;display:flex;flex-direction:column;gap:11px;flex:1}
.pllist li{display:flex;gap:10px;font-size:13.5px;line-height:1.5;
      color:var(--cx-lime-soft)}
.pllist li b{font-weight:600;color:var(--cx-white)}
.pllist li.off{color:var(--cx-turquoise-300)}
.plbul{flex:none;display:inline-flex;margin-top:2px;color:var(--cx-lime)}
.pllist li.off .plbul{color:var(--cx-ink-60)}
.plbul svg{width:15px;height:15px}
/* Kotwice na cenniku musza zatrzymac sie pod paskiem menu, inaczej naglowek
     sekcji chowa sie za nim. Wysokosc paska plus oddech. */
  #moj-plan,#warianty,#porownanie,#faq,#kalkulator{scroll-margin-top:96px}
.plbtn{margin-top:var(--space-5);justify-content:center}
.pltier .plbtn.btn--ghost{border-color:var(--cx-ink-60);color:var(--cx-mist)!important}
.plnote{margin-top:var(--space-3);font-size:11.5px;text-align:center;color:var(--cx-ink-20)}
/* Zdanie o innych formach płatności pod kartami planów (polecenie Radka
   1.10). Celowo cichsze od kart: to droga poboczna, nie drugie wezwanie. */
.plpay{margin:var(--space-6) 0 0;text-align:center;font-size:14px;
    color:var(--cx-lime-soft)}
.plpay a{color:var(--cx-lime);text-decoration:underline;
    text-underline-offset:3px}
.plpay a:hover{color:var(--cx-white)}
/* Tabela porównawcza: nagłówki wierszy po lewej, kolumna polecana
     podświetlona na całej wysokości. Poziomy przewijaj na wąskich ekranach. */
  .cmpwrap{margin-top:clamp(28px,4vh,48px);overflow-x:auto;
      border:1px solid var(--cx-ink-60);border-radius:var(--radius-lg)}
  /* Tabela ma 640 px minimum, a telefon 326 - przewija się w bok wewnątrz
     ramki. Bez znaku na krawędzi nikt na to nie wpadnie, bo przy prawym
     brzegu urywa się akurat w połowie kolumny. Cieniowanie znika, gdy
     przewiniemy do końca (`scroll-timeline` nie jest jeszcze wszędzie,
     więc zostaje stały gradient - i tak mówi „tu jest dalej"). */
  @media(max-width:700px){
    .cmpwrap{position:relative}
    .cmpwrap::after{content:"";position:absolute;inset:0 0 0 auto;width:42px;
        pointer-events:none;border-radius:0 var(--radius-lg) var(--radius-lg) 0;
        background:linear-gradient(90deg,rgba(255,255,255,0),var(--cx-white))}
  }
.cmp{width:100%;min-width:640px;border-collapse:collapse;font-size:14px}
.cmpcap{padding:var(--space-4) var(--space-5);text-align:left;font-size:12.5px;
      color:var(--cx-ink-20);border-bottom:1px solid var(--cx-ink-60)}
.cmp thead th{padding:var(--space-4) var(--space-5);text-align:left;
      font-family:var(--font-display);font-size:15px;font-weight:500;
      color:var(--cx-white);border-bottom:1px solid var(--cx-ink-60);
      white-space:nowrap}
.cmp tbody th{padding:14px var(--space-5);text-align:left;font-weight:400;
      font-size:13.5px;color:var(--cx-lime-soft)}
.cmp tbody td{padding:14px var(--space-5);color:var(--cx-white);
      font-variant-numeric:tabular-nums;white-space:nowrap}
.cmp tbody tr+tr th,.cmp tbody tr+tr td{border-top:1px solid rgba(48,85,85,.6)}
/* Hover przyciemnia CAŁY wiersz: czerń jako warstwa background-image
     kompozytuje się nad własnym tłem komórki, więc podświetlona kolumna
     ciemnieje razem z resztą, zamiast wychodzić przed wiersz. */
  .cmp tbody tr:hover th,.cmp tbody tr:hover td{
      background-image:linear-gradient(rgba(0,0,0,.4),rgba(0,0,0,.4))}
.cmpbest{background:rgba(173,247,99,.07)}
.cmp thead .cmpbest{color:var(--cx-lime);box-shadow:inset 0 -2px 0 var(--cx-lime)}
.cmpyes{display:inline-flex;color:var(--cx-lime)}
.cmpyes svg{width:16px;height:16px}
.cmpno{color:var(--cx-turquoise-300)}
/* FAQ: rozwijane pozycje (details/summary - bez JS) plus box z pytaniem. */
  .faqwrap{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);
      gap:clamp(24px,4vw,56px);align-items:start;margin-top:clamp(28px,4vh,48px)}
.faqlist{display:flex;flex-direction:column;border-top:1px solid var(--cx-ink-60)}
.faqit{border-bottom:1px solid var(--cx-ink-60)}
.faqit summary{display:flex;align-items:center;justify-content:space-between;
      gap:var(--space-4);padding:var(--space-4) 0;cursor:pointer;list-style:none;
      font-size:15.5px;font-weight:500;color:var(--cx-white)}
.faqit summary::-webkit-details-marker{display:none}
.faqit summary::after{content:"";flex:none;width:11px;height:11px;
      border-right:2px solid var(--cx-lime);border-bottom:2px solid var(--cx-lime);
      transform:rotate(45deg);transition:transform .16s ease}
.faqit[open] summary::after{transform:rotate(-135deg)}
.faqit p{margin:0 0 var(--space-4);max-width:70ch;font-size:14px;line-height:1.6;
      color:var(--cx-lime-soft)}
.faqask{padding:var(--space-5);background:var(--cx-ink-80);
      border:1px solid var(--cx-ink-60);border-radius:var(--radius-lg)}
.faqask b{display:block;font-family:var(--font-display);font-size:18px;
      font-weight:500;color:var(--cx-white)}
.faqask p{margin:var(--space-3) 0 var(--space-5);font-size:13.5px;line-height:1.6;
      color:var(--cx-lime-soft)}
/* Guzik przedłużenia i pod nim cichszy odnośnik do porównania planów
   (decyzja 41): jedna droga główna, druga do wzięcia, gdy klient chce
   najpierw popatrzeć. Kolumna, bo obok siebie oba wyglądały jak para
   równorzędnych guzików - a nie o to chodzi. */
.planacts{display:flex;flex-direction:column;align-items:stretch;gap:8px}
.planacts__alt{font-size:12.5px;text-align:center;color:var(--soft);
    text-decoration:underline;text-underline-offset:2px}
.planacts__alt:hover{color:var(--text)}
.statusbar--out .planacts__alt,.statusbar--soon .planacts__alt{color:var(--body-fg)}
/* Pasma na stronie planów są pasmami treści, nie kaflami: bez zaczepu
     i bez wysokości ekranu, żeby treść nie pływała pośrodku pustego pasma.
     Selektor musi być oparty o id, bo `#view>.band` (1,0,1) bije każdą
     regułę klasową - to samo zawężenie co przy pasku stanu. */
  #view.plpage>.band{min-height:0;display:block;scroll-snap-align:none;
      scroll-snap-stop:normal}
/* Na ciemnej stronie planów pasek nie może być jasną płytką - dostaje
     powierzchnię ink-80 i jasny tekst; zielona kropka zostaje sygnałem
     „plan aktywny". */
  .plpage .statusband{background:var(--cx-ink);border-color:var(--cx-ink-60)}
.plpage .statusbar{background:var(--cx-ink-80);border-color:var(--cx-ink-60)}
.plpage .statustx b{color:var(--cx-white)}
.plpage .statustx span{color:var(--cx-lime-soft)}
.plpage .statustx a{color:var(--cx-lime)}
.plpage .statusbar .btn--ghost{border-color:var(--cx-ink-60);color:var(--cx-mist)}
.plpage .statusbar .btn--ghost:hover{border-color:var(--cx-lime);color:var(--cx-white)}
.plpage .hero.small{background:var(--cx-ink)}
/* ══ Cennik: pasek o darmowych rzeczach ══════════════════════════════════
     Stoi nad planami, bo to on zdejmuje opór przed pierwszym kontaktem. */
  .plfree{display:flex;align-items:center;gap:var(--space-4);flex-wrap:wrap;
      margin-top:clamp(20px,3vh,32px);padding:var(--space-4) var(--space-5);
      background:rgba(173,247,99,.08);border:1px solid rgba(173,247,99,.35);
      border-radius:var(--radius-md)}
.plfreeic{flex:none;display:inline-flex}
.plfreeic .cx-chev-l,.plfreeic .cx-chev-r{background:var(--cx-lime)}
.plfree p{flex:1;min-width:240px;margin:0;font-size:14.5px;line-height:1.55;
      color:var(--cx-lime-soft)}
.plfree p b{color:var(--cx-white);font-weight:600}
.plfreego{flex:none;font-size:13.5px;color:var(--cx-lime);
      border-bottom:1px solid rgba(173,247,99,.4);padding-bottom:2px}
.plfreego:hover{color:var(--cx-white);border-color:var(--cx-white)}
/* „Wszystko z planu X, plus:" - spina plany w drabinę */
  .plfrom{margin:0 0 var(--space-3);font-size:13px;color:var(--cx-ink-20)}
.plfrom b{color:var(--cx-white);font-weight:600}
.plfine{margin-top:var(--space-3);font-size:11.5px;line-height:1.5;
      color:var(--cx-ink-20)}
.plnote b{color:var(--cx-mist);font-weight:600}
.pltier .btn--dark{justify-content:center}
/* ══ Konfigurator planu (Artur, 5.10) ═══════════════════════════════════
     Jeden pasek nad kartami: licencja, liczba osób, co jest w środowisku
     i - po zaznaczeniu Make - liczba scenariuszy. Pod nim jedno zdanie
     z rekomendacją; samo wskazanie robi ramka na karcie planu. */
  .konf{margin-top:clamp(28px,4vh,44px)}
.konfpasek{display:flex;flex-wrap:wrap;align-items:center;gap:20px 24px;
      padding:18px 24px;border:1px solid var(--cx-ink-60);border-radius:16px;
      background:rgba(48,68,69,.32)}
.konfpole{display:flex;flex-direction:column;gap:8px}
.konfpole--suwak{flex:1 1 140px;min-width:130px;gap:10px}
.konfpole[hidden]{display:none}
/* Szaro-morski z projektu Artura. Pasek leży na paśmie --cx-ink, gdzie ta
     barwa ma 5,5:1; na --cx-ink-80 spadłaby do 4,07:1, więc nie przenosić. */
  .konflab{font-size:11px;letter-spacing:.07em;text-transform:uppercase;
      color:rgb(112,156,154)}
.konfsuw{display:flex;align-items:baseline;justify-content:space-between;gap:12px;cursor:pointer}
.konfsuw b{font-family:var(--font-display);font-weight:400;font-size:18px;line-height:1;
      color:var(--cx-lime);font-variant-numeric:tabular-nums}
.konfchipy{display:flex;flex-wrap:wrap;gap:6px}
.konfchip{display:inline-flex;align-items:center;gap:8px;height:32px;padding:0 14px;
      border-radius:8px;border:1px solid var(--cx-ink-60);background:rgba(48,68,69,.45);
      color:var(--cx-mist);font:inherit;font-size:13px;white-space:nowrap;cursor:pointer;
      transition:border-color .14s ease,background .14s ease}
.konfchip:hover{border-color:rgb(112,156,154)}
.konfchip[aria-checked="true"]{border-color:var(--cx-lime);background:rgba(173,247,99,.12);
      box-shadow:inset 0 0 0 .5px var(--cx-lime)}
.konfchip:focus-visible,.konfrange:focus-visible{outline:2px solid var(--cx-lime);outline-offset:3px}
.konfbox{flex:none;display:inline-flex;align-items:center;justify-content:center;
      width:14px;height:14px;border-radius:4px;border:1px solid rgb(112,156,154);
      color:transparent}
.konfbox svg{width:10px;height:10px}
.konfchip[aria-pressed="true"] .konfbox{background:var(--cx-lime);border-color:var(--cx-lime);
      color:var(--cx-ink)}
/* Suwak rysowany od zera; zielona część toru to `--fill`, ustawiane
     skryptem przy każdym ruchu. */
  .konfrange{-webkit-appearance:none;appearance:none;width:100%;height:4px;margin:0;
      border-radius:2px;outline:none;cursor:pointer;background-color:var(--cx-ink-60);
      background-image:linear-gradient(var(--cx-lime),var(--cx-lime));
      background-repeat:no-repeat;background-size:var(--fill,0%) 100%}
.konfrange::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
      width:18px;height:18px;border-radius:50%;background:var(--cx-lime);
      border:4px solid var(--cx-ink-80);box-shadow:0 0 0 1.5px var(--cx-lime);cursor:grab}
.konfrange::-moz-range-thumb{width:18px;height:18px;border-radius:50%;
      background:var(--cx-lime);border:4px solid var(--cx-ink-80);
      box-shadow:0 0 0 1.5px var(--cx-lime);cursor:grab}
.konfwynik{display:flex;flex-wrap:wrap;align-items:center;gap:12px 24px;margin-top:20px}
.konfrek{margin:0;font-size:14px;color:rgb(112,156,154)}
.konfrek b{font-family:var(--font-display);font-weight:400;font-size:18px;color:var(--cx-lime)}
.konfsum{margin:0;flex:1 1 320px;min-width:0;font-size:13px;line-height:1.5;
      color:rgb(112,156,154)}
.konfsum span{color:var(--cx-lime-soft)}
.konfbtn{flex:none}
.billhead{display:flex;align-items:flex-end;justify-content:space-between;
      flex-wrap:wrap;gap:var(--space-4);padding-bottom:var(--space-4);
      margin-bottom:var(--space-4);border-bottom:1px solid var(--line)}
.billlab{display:block;font-size:11px;text-transform:uppercase;
      letter-spacing:.06em;color:var(--muted)}
.billname{font-family:var(--font-display);font-size:26px;font-weight:500;
      color:var(--text)}
.billprice{display:flex;align-items:baseline;gap:8px}
.billprice b{font-family:var(--font-display);font-size:26px;font-weight:500;
      color:var(--text)}
.billprice span{font-size:13px;color:var(--muted)}
.billwhat{margin-bottom:0}
.billlist li{grid-template-columns:76px minmax(0,1fr) auto}
/* Odnośnik wewnątrz pozycji listy planu - prowadzi do modalu z opisem.
     Guzik, nie <a>, bo nie zmienia adresu; wygląda jak odnośnik. */
  .pllink{display:block;margin-top:4px;padding:0;background:none;border:0;
      cursor:pointer;font:inherit;font-size:12.5px;color:var(--cx-lime);
      border-bottom:1px solid rgba(173,247,99,.4);padding-bottom:1px;
      width:fit-content}
.pllink:hover{color:var(--cx-white);border-color:var(--cx-white)}
/* Guziki zamówienia w obrysie: ikona bez ciemnej płytki (ta jest sygnałem
     przycisku głównego), sam glif w limie. */
  .pltier .btn--ghost .btnic{width:auto;height:auto;background:none;
      color:var(--cx-lime)}
.pltier .btn--ghost .btnic svg{width:18px;height:18px}
  /* Eyebrow na ciemnych pasmach. Reguła koloru dla .plpage .eyebrow
     (ta sama specyficzność) przebijała wariant --on-dark, więc etykiety na
     pasmach ink wychodziły turkusem 2,5:1. Przywracam lime-soft z lime
     szewronami - tak wyglądają eyebrow na ciemnych sekcjach strony głównej. */
  .band--dark .eyebrow--on-dark,.plpage .eyebrow--on-dark{color:var(--cx-lime-soft)}
.band--dark .eyebrow--on-dark .cx-chev-l,
  .band--dark .eyebrow--on-dark .cx-chev-r,
  .plpage .eyebrow--on-dark .cx-chev-l,
  .plpage .eyebrow--on-dark .cx-chev-r{background:var(--cx-lime)}
  /* Porównanie planów na jasnym tle.
     Sekcja zeszła z ink na mist (#F4F9F8) - to samo jasne tło co „Najczęściej
     czytane" na stronie głównej. Kolory tabeli idą za powierzchnią: ramki
     i linie na --line2, tekst na --text/--body-fg, ptaszki w ink (lime na
     białym ma 1,6:1), kolumna polecana w limonkowym odcieniu z ink tekstem. */
  #view.plpage>.plband--cmp{background:none;padding-bottom:clamp(80px,11vh,120px)}
.plh2--light{color:var(--text)}
.plband--cmp .cmpwrap{border-color:var(--line2);background:var(--cx-white)}
.plband--cmp .cmpcap{color:var(--muted);border-color:var(--line)}
/* Ton tekstu o stopień łagodniejszy niż czysty ink: nagłówki i wartości
     na --body-fg, nazwy wierszy na --muted. Czysty ink na białym (15,7:1)
     robił z tabeli najmocniejszy element strony. */
  .plband--cmp .cmp thead th{color:var(--body-fg);border-color:var(--line2)}
.plband--cmp .cmp tbody th{color:var(--muted)}
.plband--cmp .cmp tbody td{color:var(--body-fg)}
.plband--cmp .cmp tbody tr+tr th,
  .plband--cmp .cmp tbody tr+tr td{border-color:var(--line)}
/* hover: na jasnym wystarczy delikatny mist, czerń 40% byłaby krzykiem */
  .plband--cmp .cmp tbody tr:hover th,
  .plband--cmp .cmp tbody tr:hover td{
      background-image:linear-gradient(rgba(18,32,33,.05),rgba(18,32,33,.05))}
.plband--cmp .cmpbest{background:rgba(173,247,99,.22)}
.plband--cmp .cmp thead .cmpbest{color:var(--text);
      box-shadow:inset 0 -2px 0 var(--cx-green-500)}
.plband--cmp .cmpyes{color:var(--cx-turquoise-600)}
.plband--cmp .cmpno{color:var(--soft)}
.band--dark .eyebrow,.plpage .eyebrow,.eyebrow--on-dark,
  .hubsec .eyebrow,.hero .eyebrow{color:var(--cx-lime)}
/* FAQ na jasnym tle - te same rozwijane pozycje co na stronie planów,
     tylko kreski i tekst w barwach jasnej powierzchni. */
  .faqlist--light{margin-top:var(--space-4);border-top-color:var(--line)}
.faqlist--light .faqit{border-bottom-color:var(--line)}
.faqlist--light .faqit summary{color:var(--text)}
/* Strzałka potrzebuje odstępu od prawej krawędzi - w ciemnym FAQ na stronie
     planów siedzi w węższej kolumnie, tu dotykała brzegu pasma. */
  .faqlist--light .faqit summary{padding-right:var(--space-4)}
.faqlist--light .faqit summary::after{border-right-color:var(--cx-turquoise-600);
      border-bottom-color:var(--cx-turquoise-600)}
.faqlist--light .faqit p{color:var(--body-fg)}
/* Kroki na ekranie Pomocy. Numer jedzie tekstem w .stepno, bo lista ma
     list-style:none i domyślna numeracja by zniknęła. */
  .steps{list-style:none;display:flex;flex-direction:column;
      gap:clamp(40px,6vh,72px);margin:0;padding:0}
  .step{display:flex;flex-direction:column;gap:var(--space-3);
      padding-top:clamp(28px,4vh,44px);border-top:1px solid var(--line)}
  .step:first-child{padding-top:0;border-top:0}
  .stephead{display:flex;flex-direction:column;gap:6px}
  .stepno{font-size:11px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
      color:var(--cx-turquoise-600)}
  .step h2{font-family:var(--font-display);font-size:clamp(22px,2.4vw,30px);
      font-weight:500;letter-spacing:-.01em;line-height:1.2;color:var(--text)}
  .step p{max-width:70ch;font-size:15px;line-height:1.7;color:var(--body-fg)}
  .stepfigs{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-4);
      margin-top:var(--space-3)}
  .stepfigs--2{grid-template-columns:repeat(2,minmax(0,1fr))}
  .stepfig{aspect-ratio:16/10;border-radius:12px;overflow:hidden;
      background:var(--cx-cloud);border:1px solid var(--line2)}
  @media(max-width:700px){.stepfigs--2{grid-template-columns:minmax(0,1fr)}}
  #view .kbmain:only-child{max-width:none}
#view .kbmain:only-child :is(.step p,.faqit p){max-width:none}
@media(max-width:980px){
  .pltiers{grid-template-columns:minmax(0,1fr);max-width:520px}
  }
@media(max-width:900px){
  .faqwrap{grid-template-columns:minmax(0,1fr)}
  }

  /* ── Zgłoszenia: lista, szczegół, nowe zgłoszenie ────────────────────────
     Przeniesione z aplikacji React (`tickets.jsx`, `form-core.jsx`). Układ jak
     w oryginale: lista kart, a pod nią wątek korespondencji. Kolory stanów idą
     z monday.com (STANY w skrypcie), więc plakietka na portalu wygląda tak samo
     jak etykieta na tablicy - to samo nazewnictwo po obu stronach. */
  .zgwrap{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:var(--space-6);
      align-items:start}
  @media(max-width:1000px){.zgwrap{grid-template-columns:minmax(0,1fr)}}
  .zgtop{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
      gap:var(--space-4);margin-bottom:var(--space-5)}
  .zgfiltry{display:flex;flex-wrap:wrap;gap:6px}
  .zgfiltr{font:inherit;font-size:13.5px;padding:7px 14px;border-radius:999px;cursor:pointer;
      background:var(--cx-white);border:1px solid var(--line);color:var(--body-fg)}
  .zgfiltr:hover{background:var(--cx-mist);color:var(--text)}
  .zgfiltr[aria-pressed="true"]{background:var(--cx-ink);border-color:var(--cx-ink);color:var(--cx-lime)}
  .zgfiltr b{font-weight:600;margin-left:6px;opacity:.75}

  /* ── Lista zgłoszeń: tabela ─────────────────────────────────────────────
     Cztery kolumny: sprawa, uczestnicy, aktywność, status. Kolumna statusu
     ma tworzyć pion, dlatego plakietki dostają jednakową szerokość
     (mierzy ją zgWyrownajPlakietki w skrypcie - szerokość zależy od kroju
     i od tego, które statusy są akurat na ekranie).
     Wiersz jest odnośnikiem tylko w pierwszej kolumnie: gdyby cały wiersz
     był <a>, awatary i plakietka wpadłyby do treści odnośnika i czytnik
     ekranu odczytywałby je jako część tytułu sprawy. */
  .tktab{--tkkol:minmax(0,1fr) 150px 160px 168px;
      list-style:none;display:flex;flex-direction:column;margin:0;padding:0;
      border-top:1px solid var(--line)}
  .tktab>li{display:grid;grid-template-columns:var(--tkkol);align-items:center;
      gap:var(--space-4);border-bottom:1px solid var(--line)}
  .tkhead{padding:11px var(--space-3);font-size:11px;font-weight:600;letter-spacing:.12em;
      text-transform:uppercase;color:var(--soft)}
  .tkrow{transition:background .15s}
  .tkrow:hover{background:var(--cx-mist)}
  .tkrow--zamkniete{opacity:.66}
  .tkrow--zamkniete:hover{opacity:1}
  .tkcell{padding:var(--space-4) var(--space-3);min-width:0}
  /* Pierwsza komórka jest odnośnikiem i rozciąga się na wysokość wiersza,
     więc klikalne jest całe pole tytułu, nie sam napis. */
  .tkcell--sprawa{display:flex;flex-direction:column;gap:3px;
      text-decoration:none;color:inherit}
  .tknad{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-3);
      font-size:11px;letter-spacing:.09em;text-transform:uppercase;color:var(--soft)}
  .tkkat{font-weight:600}
  .tknr{font-weight:600;color:var(--cx-turquoise-600);letter-spacing:.02em;
      text-transform:none;font-size:12px}
  .tktytul{font-family:var(--font-display);font-weight:500;font-size:16px;line-height:1.3;
      color:var(--text);overflow-wrap:anywhere}
  .tkcell--sprawa:hover .tktytul{color:var(--cx-turquoise-600)}
  .tkzajawka{font-size:13px;line-height:1.5;color:var(--body-fg);
      display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}
  /* Awatary zachodzą na siebie - dwie, trzy osoby mieszczą się wtedy
     w wąskiej kolumnie bez ściskania wiersza. */
  .tkludzie{display:inline-flex;align-items:center}
  /* Inicjały człowieka: BIAŁE litery na szarym kole, zawsze i wszędzie
     (decyzja Radka 26.09). Dotąd stały turkusem na mgle, czyli jasne na
     jasnym - przy 10,5 px ledwo się to czytało. Szarość jest z palety
     (`--cx-gray-2`), więc kółko nie udaje plakietki statusu ani guzika;
     znak CXLABS zostaje osobno, na ciemnym tle. */
  .tkav{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;flex:none;
      font-size:10.5px;font-weight:600;overflow:hidden;
      background:var(--cx-gray-2);color:var(--cx-white);
      border:2px solid var(--cx-white);margin-left:-7px}
  .tkav:first-child{margin-left:0}
  .tkav--cx{background:var(--cx-ink)}
  .tkav--cx svg{width:100%;height:100%;display:block}
  .tkcell--ruch{display:flex;flex-direction:column;gap:2px}
  .tkkiedy{font-size:13.5px;color:var(--text)}
  .tkco{font-size:12px;color:var(--soft)}
  .tkstate{display:inline-flex;align-items:center;justify-content:center;
      padding:6px 12px;border-radius:8px;font-size:11.5px;font-weight:600;
      letter-spacing:.02em;text-align:center}
  /* Zgłoszenie rozwiązane ma plakietkę TAK SAMO jak każde inne (poprawka
     Radka 29.09: „status rozwiązane nie ma tła, jest sam napis"). Wcześniej
     ją tu gasiliśmy - cały wiersz jest przygaszony, więc plakietka wydawała
     się zbędna. Wyszło odwrotnie: kolumna statusu miała pięć kolorowych
     plakietek i jeden goły napis, co wygląda na niedokończony wiersz, a nie
     na sprawę zamkniętą. Przygaszenie wiersza zostaje i wystarcza.
     Przygaszenie idzie przez `opacity` NA WIERSZU, a tego dziecko nie cofnie
     (przezroczystość rodzica składa całą gałąź naraz) - więc plakietka gaśnie
     razem z resztą i tak ma być. */

  /* pasek stron */
  .tkstopka{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
      gap:var(--space-4);padding:var(--space-4) var(--space-3) 0;
      font-size:13px;color:var(--soft)}
  .tkstopka b{color:var(--text);font-weight:600}
  .tkstrony{display:flex;flex-wrap:wrap;align-items:center;gap:4px}
  .tknav,.tkstr{font:inherit;font-size:13px;cursor:pointer;border-radius:8px;
      background:none;border:1px solid transparent;color:var(--body-fg)}
  .tknav{display:inline-flex;align-items:center;gap:5px;padding:7px 11px}
  .tknav svg{width:15px;height:15px}
  .tkstr{min-width:32px;padding:7px 9px;text-align:center}
  .tknav:hover:not(:disabled),.tkstr:hover:not(.on){background:var(--cx-mist);color:var(--text)}
  .tknav:disabled{opacity:.4;cursor:default}
  .tkstr.on{background:var(--cx-ink);border-color:var(--cx-ink);color:var(--cx-lime);font-weight:600}

  /* Na wąskim ekranie tabela rozsypuje się na wiersze: sprawa u góry,
     pod nią uczestnicy, czas i status w jednej linii. Nagłówek kolumn
     znika - nie ma już czego opisywać. */
  @media(max-width:820px){
    /* `.tktab>li` ustawia display:grid i wygrywa specyficznością z samym
       `.tkhead`, więc nagłówek chowamy tym samym stopniem szczegółowości. */
    .tktab>.tkhead{display:none}
    .tktab>li{grid-template-columns:auto minmax(0,1fr) auto;
        gap:var(--space-3);padding:var(--space-4) 0}
    .tkcell{padding:0}
    .tkcell--sprawa{grid-column:1/-1;grid-row:1}
    .tkcell--ludzie{grid-column:1;grid-row:2;justify-self:start}
    .tkcell--ruch{grid-column:2;grid-row:2;flex-direction:row;flex-wrap:wrap;
        align-items:baseline;gap:6px}
    .tkcell--stan{grid-column:3;grid-row:2;justify-self:end}
    /* Stała szerokość plakietki ma sens tylko w kolumnie - tu zabiera miejsce
       tytułowi. Szerokość wpisuje skrypt do atrybutu style, więc zdejmujemy
       ją wyjątkiem. */
    .tkstate{min-width:0!important}
  }

  /* Wejście wprost do sekcji profilu (#konto/haslo i spółka). Pasek nawigacji
     jest przyklejony, więc bez marginesu przewijania sekcja chowała się pod
     nim. 96 px to wysokość paska z zapasem na pasek „wersja rozwojowa". */
  #k-dane,#k-org,#k-haslo,#k-haslo-link,.kbmain .secgroup,
  #warianty,#kalkulator,#porownanie,#faq,#produkty{scroll-margin-top:96px}

  /* ══ Panel tłumaczeń (/admin/tlumaczenie) ═════════════════════════════════
     Ekran wewnętrzny, nie klientowski - stąd gęstsza siatka i tabela zamiast
     kart. Styl zostaje portalowy, żeby nie utrzymywać drugiego języka wizualnego. */
  /* Zakładki to „języczki teczki": aktywna ma zaokrąglone tylko górne rogi
     i tło w kolorze sekcji pod spodem, więc ma się z nią STYKAĆ. Nagłówek
     zostawiał pod nimi swój dolny odstęp (30 px na telefonie, 34 na
     komputerze) i między języczkiem a sekcją stał ciemny pasek - wyglądało
     to jak usterka, bo języczek nie prowadził już donikąd.
     `:has()` zawęża to do tego jednego ekranu; gdzie nie działa, zostaje
     dotychczasowy odstęp i nic się nie psuje. */
  #view>.hero.small:has(.tlzakladki){padding-bottom:0}
  .tlzakladki{display:flex;gap:4px;margin-top:var(--space-4)}
  .tlzak{font:inherit;font-size:14px;padding:9px 16px;cursor:pointer;border:0;
      border-radius:10px 10px 0 0;background:rgba(255,255,255,.06);color:var(--cx-mist);
      transition:background .2s ease,color .2s ease}
  .tlzak:hover{background:rgba(255,255,255,.12);color:var(--cx-white)}
  .tlzak.on{background:var(--cx-mist);color:var(--cx-ink);font-weight:600}

  /* ══ Wybór kategorii w produkcie (makieta Claude Design: zrodlo-kategorie) ══
     Do 23.09 stały tu ciemne pigułki po cztery w rzędzie - komponent pożyczony
     z kafli produktów, bo po przejściu ze „źródeł" na produkty przebudowałem
     ten ekran naprędce i nigdy nie wróciłem po wygląd z makiety.

     Makieta daje listę, nie siatkę: dwie kolumny jasnych wierszy w jednej
     zaokrąglonej płycie, znak kategorii po lewej, szewron po prawej. Kreski
     rysują same kafle (górna i lewa), a zewnętrzne włosy zdejmujemy regułami
     na pierwszy rząd i pierwszą kolumnę - ujemny margines wystawałby poza
     płytę i budził poziomy pasek przewijania. */
  .cats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0;
      margin-top:var(--space-6);background:var(--cx-white);
      border-radius:var(--radius-lg);overflow:hidden}
  .cattile{display:grid;grid-template-columns:auto minmax(0,1fr) auto;
      align-items:start;gap:var(--space-4);padding:var(--space-4) var(--space-5);
      background:var(--cx-white);border-top:1px solid var(--line);
      border-left:1px solid var(--line);text-decoration:none;color:inherit;
      transition:background .18s ease,color .18s ease}
  .cattile:nth-child(-n+2){border-top:0}
  .cattile:nth-child(odd){border-left:0}
  /* Jasna mgła zamiast ciemnej zieleni: kafel ma się rozjaśnić, nie zmienić
     w inny widok. Sygnał niesie limonka na znaku i szewronie, nie całe tło. */
  .cattile:hover,.cattile:focus-visible{background:var(--cx-mist)}

  .catic{display:grid;place-items:center;width:44px;height:44px;flex:none;
      aspect-ratio:1;border-radius:10px;overflow:hidden;margin-top:2px;
      background:var(--cx-mist);color:var(--accent);
      transition:background .18s ease,color .18s ease}
  .catic svg{width:21px;height:21px}
  .catic .prodico{width:100%;height:100%;object-fit:contain;display:block}
  .cattile:hover .catic{background:var(--cx-lime);color:var(--cx-ink)}

  .cattx{display:flex;flex-direction:column;gap:3px;min-width:0}
  .catname{display:flex;align-items:baseline;gap:9px;min-width:0;
      font-family:var(--font-display);font-weight:500;font-size:16.5px;
      line-height:1.25;letter-spacing:-.01em;color:var(--text)}
  /* liczba artykułów: mała, tuż przy nazwie, cyframi tabelarycznymi */
  .catname i{font-style:normal;font-family:var(--font-body);font-weight:600;
      font-size:11.5px;letter-spacing:.04em;color:var(--muted);white-space:nowrap;
      font-variant-numeric:tabular-nums}
  .cattile:hover .catname,.cattile:hover .catname i{color:var(--accent-strong)}
  .catmeta{font-size:12px;color:var(--soft)}
  .cattile:hover .catmeta{color:var(--muted)}

  .catsecs{display:flex;flex-wrap:wrap;gap:5px;margin-top:2px}
  .catsecs i{font-style:normal;font-size:11.5px;line-height:1.3;padding:3px 8px;
      border-radius:6px;background:var(--cx-mist);color:var(--muted);
      white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis;
      transition:background .18s ease,color .18s ease}
  .catsecs .catmore{background:none;color:var(--soft);padding-left:2px}
  .cattile:hover .catsecs i{background:var(--cx-white);color:var(--text)}
  .cattile:hover .catsecs .catmore{background:none;color:var(--muted)}

  .catgo{display:flex;align-items:center;justify-content:center;align-self:center;
      color:var(--cx-cloud-2);transition:color .18s ease,transform .18s ease}
  .catgo svg{width:14px;height:14px}
  .cattile:hover .catgo{color:var(--accent-strong);transform:translateX(2px)}

  /* Telefon: jedna kolumna, więc lewych kresek nie ma wcale, a kreska górna
     wraca drugiemu kaflowi - w dwóch kolumnach był w pierwszym rzędzie. */
  @media(max-width:640px){
    .cats{grid-template-columns:1fr}
    .cattile{border-left:0;padding:var(--space-4)}
    .cattile:first-child{border-top:0}
    .cattile:nth-child(2){border-top:1px solid var(--line)}
  }

  /* Pasek „co się teraz tłumaczy". Stoi nad podsumowaniem, bo to jedyna rzecz
     na tym ekranie, która zmienia się sama - reszta czeka na klik. */
  .tlkolejka{margin-bottom:var(--space-5);padding:var(--space-4) var(--space-5);
      background:var(--cx-white);border:1px solid var(--line);
      border-left:3px solid var(--tlk,var(--cx-green));border-radius:var(--radius-md)}
  .tlkolejka__gora{display:flex;align-items:baseline;gap:var(--space-3);flex-wrap:wrap;
      font-size:13.5px;color:var(--muted)}
  .tlkolejka__gora b{font-size:15px;color:var(--text)}
  .tlkolejka__gora a{margin-left:auto;font-size:12.5px}
  /* Tor bez animacji „w nieskończoność": pasek stoi na etapie, na którym
     naprawdę jest przebieg. Ruchoma kreska sugerowałaby wiedzę co do sekundy,
     której nie mamy - między odpytaniami mija 10 s. */
  .tlkolejka__tor{margin-top:var(--space-3);height:6px;border-radius:3px;
      background:var(--cx-mist);overflow:hidden}
  .tlkolejka__tor i{display:block;height:100%;background:var(--tlk,var(--cx-green));
      transition:width .4s ease}
  .tlkolejka__lista{margin-top:7px;font-size:12.5px;color:var(--soft);
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  /* Ślad po zakończonym przebiegu. Zielony, gdy coś przybyło; czerwony, gdy
     przebieg skończył się bez nowych tłumaczeń - bo to jedyny moment, w którym
     panel ma szansę powiedzieć, że coś poszło nie tak. */
  .tlnota{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;
      margin-bottom:var(--space-4);padding:11px var(--space-4);font-size:13.5px;
      background:var(--cx-white);border:1px solid var(--line);
      border-left:3px solid var(--cx-green);border-radius:var(--radius-md)}
  .tlnota--zle{border-left-color:var(--cx-error)}
  /* Tekst rozpycha wiersz, więc odnośnik i krzyżyk siadają przy prawej
     krawędzi także wtedy, gdy odnośnika nie ma. */
  .tlnota>span{flex:1 1 auto;min-width:0}
  .tlnota a{font-size:12.5px}
  .tlnota__x{font:inherit;font-size:17px;line-height:1;cursor:pointer;padding:0 4px;
      color:var(--soft);background:none;border:0}
  /* Tytuły w poczekalni: druga linia, drobniej - to podpis, nie treść. */
  .tlnota__co{display:block;margin-top:2px;font-style:normal;font-size:12px;
      color:var(--soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .tlnota__x:hover{color:var(--text)}

  .tlsum{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));
      gap:var(--space-3);margin-bottom:var(--space-5)}
  .tlsumtile{padding:var(--space-4);background:var(--cx-white);
      border:1px solid var(--line);border-radius:var(--radius-md)}
  .tlsumtile b{display:block;font-family:var(--font-display);font-size:24px;
      font-weight:500;color:var(--text)}
  .tlsumtile span{font-size:12px;color:var(--soft)}
  .tlsumtile--glowny{grid-column:span 2}
  /* Kafelek z rachunkiem: kwota pismem tekstowym, nie nagłówkowym - liczby
     ze spacją tysięczną i przecinkiem czytają się w nim lepiej niż w Clash
     Display, który ma cyfry o tej samej szerokości co litery. */
  .tlsumtile--koszt{grid-column:span 2}
  .tlsumtile--koszt b{font-family:var(--font-body);font-size:21px;font-weight:700;
      font-variant-numeric:tabular-nums;cursor:help}
  .tlsumtile--koszt span{cursor:help}
  /* Prognoza ma własny dymek („skąd ta liczba"), inny niż kwota obok - stąd
     osobny element, a nie sam tekst w `span`. Kursywy nie chcemy: to liczba,
     nie cytat. */
  .tlprog{font-style:normal;cursor:help;border-bottom:1px dotted var(--line)}
  /* Lista modeli stoi w rzędzie kafli, więc ma wyglądać jak kafel z polem,
     a nie jak formularz wciśnięty między liczby. */
  .tlsumtile--model{grid-column:span 2}
  /* Rachunek z OpenAI stoi obok naszego wyliczenia i ma się od niego różnić
     na pierwszy rzut oka - to liczba z zewnątrz, nie nasza. */
  .tlsumtile--rachunek{grid-column:span 2}
  .tlsumtile--rachunek b{font-family:var(--font-body);font-size:21px;font-weight:700;
      font-variant-numeric:tabular-nums;cursor:help;color:var(--cx-green-600)}
  .tlsumtile--rachunek span{cursor:help}
  .tlmodelrzad{display:flex;gap:6px;align-items:center}
  .tlmodelrzad select{flex:1 1 auto;min-width:0}
  .tlmodelrzad .tlprodbtn{flex:none;padding:6px 12px}
  .tlmodelrzad .tlprodbtn[disabled]{opacity:.45;cursor:default}
  .tlsumtile--model select{font:inherit;font-size:15px;font-weight:600;width:100%;
      padding:5px 8px;border-radius:9px;color:var(--body-fg);
      background:var(--cx-white);border:1px solid var(--line);cursor:pointer}
  .tlsumtile--model select:focus-visible{outline:2px solid var(--cx-green-500);
      outline-offset:1px}
  /* Nagłówek kolumny jest guzikiem, ale ma dalej wyglądać jak nagłówek:
     bez ramki, bez tła, z tą samą wielkością i odstępem liter co reszta
     wiersza. Zmienia się dopiero pod kursorem i przy kolumnie, po której
     akurat sortujemy. */
  .tlsort{font:inherit;font-size:inherit;letter-spacing:inherit;text-transform:inherit;
      color:inherit;background:none;border:0;padding:0;cursor:pointer;
      display:inline-flex;align-items:center;gap:2px}
  .tlsort:hover{color:var(--cx-green-600)}
  .tlsort--tu{color:var(--body-fg);font-weight:700}
  .tlsort i{font-style:normal}
  .tlsort:focus-visible{outline:2px solid var(--cx-green-500);outline-offset:2px;
      border-radius:4px}
  /* Znak firmowy produktu na guziku filtra. Pliki mają własne kolorowe tło,
     więc dostają tylko zaokrąglenie - bez płytki i bez obwódki. Rozmiar
     dobrany do wysokości napisu: guzik ma zostać guzikiem z ikoną,
     a nie kafelkiem z obrazkiem. */
  .tlznak{width:16px;height:16px;border-radius:4px;flex:none;object-fit:cover}
  /* „Jak działa tłumaczenie" pod nagłówkiem panelu. Domyślnie zwinięte do
     jednego wiersza, bo ekran służy do pracy, a nie do czytania instrukcji -
     ale odpowiedź na „czemu ten artykuł stoi na czerwono" ma być tutaj,
     a nie w cudzej głowie. */
  .tljak{margin-top:10px;max-width:640px}
  .tljak summary{display:inline-flex;align-items:center;gap:7px;cursor:pointer;
      font-size:13px;font-weight:600;color:var(--cx-green-500);
      padding:4px 0;list-style:none;width:max-content}
  .tljak summary::-webkit-details-marker{display:none}
  .tljak summary:hover{color:var(--cx-lime)}
  .tljak summary:focus-visible{outline:2px solid var(--cx-green-500);
      outline-offset:3px;border-radius:4px}
  .tljak[open] summary{margin-bottom:4px}
  .tljak__tresc{font-size:13px;line-height:1.55;color:rgba(255,255,255,.78);
      border-left:2px solid rgba(255,255,255,.16);padding:2px 0 2px 12px}
  .tljak__tresc p{margin:0 0 7px}
  .tljak__tresc p:last-child{margin-bottom:0}
  .tljak__tresc b{color:#fff;font-weight:600}
  .tlpasek{height:5px;margin-top:9px;border-radius:3px;background:var(--cx-cloud);overflow:hidden}
  /* `min-width` na wypełnieniu: przy 0,5 % bazy pasek miał pół piksela i było
     go widać jak nic. Kikut o szerokości paska czyta się jako „ruszyliśmy",
     a nie jako usterka rysowania. */
  .tlpasek i{display:block;height:100%;min-width:5px;border-radius:3px;
      background:var(--cx-green-500)}

  .tlfiltry{display:flex;flex-direction:column;gap:var(--space-3);margin-bottom:var(--space-4)}
  .tlprod{display:flex;flex-wrap:wrap;gap:5px}
  .tlprodbtn{display:inline-flex;align-items:center;gap:7px;font:inherit;font-size:13px;
      padding:7px 13px;cursor:pointer;border-radius:999px;color:var(--body-fg);
      background:var(--cx-white);border:1px solid var(--line);transition:all .16s ease}
  .tlprodbtn i{font-style:normal;font-size:11.5px;color:var(--soft);
      font-variant-numeric:tabular-nums}
  .tlprodbtn:hover{border-color:var(--cx-ink-20);color:var(--text)}
  .tlprodbtn.on{background:var(--cx-ink);border-color:var(--cx-ink);color:var(--cx-lime)}
  .tlprodbtn.on i{color:var(--cx-mist)}
  /* Drugie piętro filtra. Lżejsze od produktów: mniejszy krój i jaśniejsza
     wybrana pigułka, żeby z jednego spojrzenia było widać, co jest nadrzędne. */
  .tlsekcje{display:flex;flex-wrap:wrap;gap:5px}
  .tlprodbtn--sekcja{font-size:12.5px;padding:6px 11px}
  .tlprodbtn--sekcja.on{background:var(--cx-mist);border-color:var(--cx-ink-20);
      color:var(--text)}
  .tlprodbtn--sekcja.on i{color:var(--muted)}
  /* „Zaznacz wszystkie widoczne" stoi w jednym rzędzie z szukajką - ma być
     widoczne bez szukania kwadracika w nagłówku tabeli. */
  .tlzazn{display:inline-flex;align-items:center;gap:9px;flex:none;cursor:pointer;
      padding:9px 13px;font-size:13.5px;color:var(--body-fg);
      background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-md);transition:border-color .16s ease}
  .tlzazn:hover{border-color:var(--cx-ink-20);color:var(--text)}
  .tlzazn input{cursor:pointer}
  .tlzazn i{font-style:normal;margin-left:7px;font-size:11.5px;color:var(--soft);
      font-variant-numeric:tabular-nums}
  .tlrzad{display:flex;flex-wrap:wrap;gap:var(--space-3);align-items:center}
  .tlszuk{display:flex;align-items:center;gap:9px;flex:1 1 260px;min-width:0;
      padding:9px 13px;background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-md)}
  .tlszuk svg{width:16px;height:16px;flex:none;color:var(--soft)}
  .tlszuk input{flex:1;min-width:0;border:0;outline:0;background:none;font:inherit;font-size:14px}
  /* Stany: guziki wielokrotnego wyboru, każdy ze swoją kropką. Lista
     rozwijana pokazywała jeden stan naraz i trzeba ją było otworzyć, żeby
     w ogóle zobaczyć, ile czego jest. */
  .tlstany{display:flex;flex-wrap:wrap;gap:5px}
  .tlstanbtn{display:inline-flex;align-items:center;gap:7px;font:inherit;font-size:13px;
      padding:7px 13px;cursor:pointer;border-radius:999px;color:var(--body-fg);
      background:var(--cx-white);border:1px solid var(--line);transition:all .16s ease}
  .tlstanbtn i{font-style:normal;font-size:11.5px;color:var(--soft);
      font-variant-numeric:tabular-nums}
  .tlstanbtn .tlkropka{width:9px;height:9px;box-shadow:none;cursor:pointer}
  .tlstanbtn:hover{border-color:var(--cx-ink-20);color:var(--text)}
  .tlstanbtn.on{font-weight:600}
  .tlstanbtn.on i{color:inherit;opacity:.7}
  /* Stan bez ani jednego artykułu w tym widoku zostaje klikalny - po zmianie
     produktu albo po przebiegu liczba przestanie być zerem, a znikający
     i wracający guzik przestawiałby cały rząd pod kursorem. */
  .tlstanbtn--pusty{opacity:.45}

  /* Pasek akcji przykleja się do dołu: przy 982 artykułach zaznaczenie
     wypadałoby poza ekran i guzik wysyłki byłby nie do znalezienia. */
  .tlakcje{position:sticky;bottom:var(--space-4);z-index:20;
      display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);
      margin-bottom:var(--space-4);padding:12px var(--space-4);
      background:var(--cx-ink);color:var(--cx-mist);border-radius:var(--radius-md);
      box-shadow:0 12px 32px -14px rgba(18,32,33,.6)}
  .tlakcje b{color:var(--cx-lime)}
  .tlakcje .btn{margin-left:auto}
  .tlakcje .chip--tekst{background:none;border-color:var(--cx-ink-60);color:var(--cx-mist)}

  /* Panel dostał WŁASNĄ szerokość, szerszą niż 1180 px reszty portalu.
     Powód jest rachunkowy: dwanaście słupków tabeli zajmuje ponad tysiąc
     pikseli, więc na wspólnej szerokości na tytuł artykułu zostawało 60 px
     i nazwa łamała się na osiem wierszy po jednej sylabie. Portal czyta
     klient na dowolnym ekranie i tam wąska kolumna tekstu jest zaletą; panel
     oglądamy my, na monitorze, i tu liczy się, ile mieści się w wierszu. */
  .wrap--panel{max-width:1560px}

  /* Ramka planów w podglądzie panelu - ten sam układ, co na stronie, tylko
     bez własnych ikon przy wierszach: w podglądzie liczy się, CZY fakt jest,
     a nie czym go oznaczono. */
  .tlramka--plany{display:block}
  .tlramka--plany .plantyt{margin:0 0 6px;font-weight:700}
  .tlramka--plany .planlista{list-style:none;margin:0;padding:0}
  .tlramka--plany .planwiersz{margin:0;padding:0 0 0 12px;position:relative}
  .tlramka--plany .planwiersz::before{content:'·';position:absolute;left:2px;
      color:var(--soft)}

  /* ── użytkownicy panelu ────────────────────────────────────────────── */
  .uztab{list-style:none;margin:var(--space-5) 0 0;padding:0;
      border-top:1px solid var(--line)}
  .uztab>li{display:grid;grid-template-columns:minmax(0,1fr) 140px 140px;
      gap:var(--space-3);align-items:center;padding:12px var(--space-3);
      border-bottom:1px solid var(--line)}
  .uzhead{font-size:11px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
      color:var(--soft)}
  .uzrow--ja{background:rgba(173,247,99,.12)}
  .uzimie{font-weight:600;display:flex;align-items:baseline;gap:var(--space-2)}
  .uzja{font-style:normal;font-size:11px;font-weight:600;color:var(--cx-ink-60)}
  .uzskrot{font-size:12.5px;color:var(--soft)}
  .uzskrot--stary{color:var(--cx-yellow-ink,#8a6d00)}
  .uzzakres{font-size:12.5px;color:var(--soft)}
  .uzstopka{margin-top:var(--space-3)}
  .uzjak{margin-top:var(--space-7);padding:var(--space-5);background:var(--cx-mist);
      border:1px solid var(--line);border-radius:var(--radius-md)}
  .uzjak h3{margin:0 0 var(--space-3)}
  .uzjak p{margin:0 0 var(--space-3)}
  .uzjak pre{margin:0 0 var(--space-3);padding:var(--space-3);overflow:auto;
      background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-md);font-size:12.5px}

  /* ── Bany IP ───────────────────────────────────────────────────────── */
  /* Tabela banow ma o jedna kolumne wiecej niz tabela kont (doszedl guzik
     „Zdejmij"). Reszta klas .uz* jest wspolna. */
  .banytab>li{grid-template-columns:minmax(0,1fr) 130px 150px 92px}
  .banakcja{justify-self:end}
  .banzdejm{padding:7px 14px;font-size:12.5px}
  .banytab code,.banform code{font-size:12.5px}
  .banform{margin:0 0 var(--space-6);padding:var(--space-5);background:var(--cx-mist);
      border:1px solid var(--line);border-radius:var(--radius-md)}
  .banform h3{margin:0 0 var(--space-4)}
  .banform .btn{margin-top:var(--space-2)}
  .banpola{display:grid;grid-template-columns:minmax(0,1fr) 150px minmax(0,1.4fr);
      gap:var(--space-3);margin-bottom:var(--space-4)}
  .banpola label{display:flex;flex-direction:column;gap:6px;font-size:12.5px;
      font-weight:600;color:var(--soft)}
  .banpola input{font:inherit;font-weight:400;color:var(--text);padding:10px 12px;
      border:1px solid var(--cx-ink-40);border-radius:var(--radius-md);
      background:var(--cx-white)}
  .banpola input:focus-visible{outline:2px solid var(--cx-green);outline-offset:1px}
  .banok{margin:0 0 var(--space-4);padding:10px var(--space-4);
      background:color-mix(in srgb,var(--cx-green) 12%,transparent);
      border:1px solid color-mix(in srgb,var(--cx-green) 40%,transparent);
      border-radius:var(--radius-md);font-size:13px;color:var(--text)}
  @media(max-width:640px){
    .banpola{grid-template-columns:1fr}
    .banytab>li{grid-template-columns:1fr auto;row-gap:4px}
    .banytab .uzhead{display:none}
    .banakcja{grid-column:2;grid-row:1/4;align-self:center}
  }

  /* ── poprawianie artykułu na jego stronie ──────────────────────────── */
  /* Pasek stoi NA DOLE i na środku, a nie w rogu: jest jedyną rzeczą, która
     w trybie edycji mówi, co się dzieje i jak z niego wyjść. W rogu ginie. */
  .artedpasek{position:fixed;left:50%;bottom:calc(24px + env(safe-area-inset-bottom));
      transform:translateX(-50%);
      z-index:60;display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;
      max-width:min(760px,92vw);padding:10px 14px;border-radius:999px;
      background:var(--cx-white);border:1px solid var(--line);
      box-shadow:0 8px 28px rgba(13,27,30,.16)}
  .artedpasek .btn{padding:8px 16px;font-size:13px}
  .artedpasek .btn svg{width:15px;height:15px;margin-right:6px}
  /* „Zapisz i opublikuj" bez zmian jest wyłączony, ale wyglądał identycznie jak
     włączony - pełna zieleń głównego guzika. Człowiek klikał i nic się nie
     działo, bez słowa wyjaśnienia. Teraz widać, że jeszcze nie ma czego zapisać;
     co trzeba zrobić, mówi napis obok. */
  .artedpasek .btn:disabled{opacity:.45;cursor:default;box-shadow:none}
  .artedstan{font-size:13px;color:var(--soft)}
  .artedstan--zle{color:var(--cx-error)}
  .artedpasek .authalert{flex:1 0 100%;margin:0;font-size:12.5px}
  /* Na telefonie pasek NIE jest pigułką. `border-radius:999px` na pudełku,
     które zawinęło się na trzy wiersze, robi z niego biały placek zasłaniający
     pół artykułu - dokładnie to zobaczył Radek na iPhonie 25.09. Tu pasek jest
     listwą na całą szerokość: napis w swoim wierszu, guziki w drugim, każdy
     tej samej szerokości, bo palcem trafia się w cel, a nie w piksel. */
  @media(max-width:640px){
    .artedpasek{left:10px;right:10px;transform:none;max-width:none;
        border-radius:var(--radius-lg);padding:10px 12px;gap:8px;
        bottom:calc(10px + env(safe-area-inset-bottom))}
    .artedpasek .artedstan{flex:1 0 100%;text-align:center;font-size:12.5px}
    .artedpasek .btn{flex:1 1 0;justify-content:center;padding:11px 12px;
        font-size:13px;min-height:44px}
    /* Sam „Popraw artykuł" nie ma się z czym dzielić szerokością - rozciągnięty
       na cały ekran wygląda jak główna akcja strony, a jest skrótem dla nas. */
    .artedpasek .btn:only-child{flex:0 1 auto;margin:0 auto}
  }
  /* Kiedy otwarty jest blok, pasek schodzi z drogi. Na telefonie stał dokładnie
     tam, gdzie klawiatura wypycha pole i guziki „Gotowe"/„Anuluj" - zasłaniał
     to, czym się z pola wychodzi. Nic przez to nie ginie: zapis i wyjście
     z trybu są o jedno kliknięcie dalej, po zamknięciu bloku. */
  body.artedpisze .artedpasek{display:none}
  /* Miejsce pod pasek na dole strony - tylko dla tego, kto go widzi. */
  body.artedjest>footer{padding-bottom:calc(88px + env(safe-area-inset-bottom))}
  @media(max-width:640px){
    body.artedjest>footer{padding-bottom:calc(128px + env(safe-area-inset-bottom))}
  }
  /* Blok do poprawienia. Podkreślenie, nie ramka: ramka wokół każdego akapitu
     zamienia artykuł w tabelkę i nie da się go czytać, a o to właśnie chodzi -
     poprawia się to, co się czyta. Obwódka pojawia się dopiero pod kursorem. */
  .docbody.artedycja .artedblok{position:relative;cursor:text;border-radius:6px;
      box-shadow:inset 0 -1px 0 color-mix(in srgb,var(--cx-green) 55%,transparent);
      transition:background .14s ease}
  .docbody.artedycja .artedblok:hover{background:color-mix(in srgb,var(--cx-green) 9%,transparent)}
  .docbody.artedycja .artedblok--zmieniony{box-shadow:inset 0 -2px 0 var(--cx-yellow);
      background:color-mix(in srgb,var(--cx-yellow) 12%,transparent)}
  .artedpole{display:block;width:100%;min-height:80px;resize:vertical;
      font:13px/1.65 ui-monospace,SFMono-Regular,Menlo,monospace;
      border:1px solid var(--cx-ink-40);border-radius:var(--radius-md);
      padding:var(--space-3);background:var(--cx-white);color:var(--text)}
  .artedakcje{display:flex;align-items:center;gap:var(--space-2);
      margin-top:var(--space-2);flex-wrap:wrap}
  .artedakcje span{flex:1 1 auto;font-size:11.5px;color:var(--soft)}
  .artedakcje .btn{padding:5px 12px;font-size:12px}
  /* Dotyk: skrótów klawiszowych nie ma na czym wcisnąć, więc podpowiedź o nich
     zabierała miejsce guzikom i nic nie dawała. Same guziki rosną do rozmiaru,
     w który da się trafić palcem. */
  @media(hover:none){
    .artedakcje span{display:none}
    .artedakcje{justify-content:flex-end}
    .artedakcje .btn{flex:1 1 0;justify-content:center;padding:11px 12px;
        font-size:13px;min-height:44px}
    /* Pole mniejsze niż 16px każe Safari przybliżyć całą stronę przy wejściu
       w nie kursorem - i strona już z tego przybliżenia sama nie wraca. */
    .artedpole{font-size:16px;line-height:1.55}
  }
  /* Guzik „ghost" powstał dla CIEMNEGO hero: ma `color:var(--cx-mist)`, czyli
     prawie biel, i to z `!important`. W edytorze stoi na białym tle - napis
     „Pobierz plik" i „Anuluj" był praktycznie niewidoczny, wyglądał jak guzik
     wyłączony. Tu przestawiamy sam kolor napisu i obwódki; kształt zostaje. */
  .mdlstopka .btn--ghost,
  .artedakcje .btn--ghost,
  .artedpasek .btn--ghost{color:var(--text)!important;border-color:var(--cx-ink-20)}
  .mdlstopka .btn--ghost:hover,
  .artedakcje .btn--ghost:hover,
  .artedpasek .btn--ghost:hover{background:var(--cx-mist);color:var(--text)!important;
      border-color:var(--cx-ink-40)}
  /* Obwódka pola przy pisaniu w kolorze marki, nie domyślnym niebieskim
     przeglądarki - niebieski w tym portalu nie znaczy nic i wygląda obco. */
  .artedpole:focus,.artedpole:focus-visible{outline:2px solid var(--cx-green);
      outline-offset:1px;border-color:var(--cx-green)}

  /* Pasek planu: ile zostało i kiedy pójdzie następna partia. Stoi NAD listą,
     bo to jest odpowiedź na pierwsze pytanie po wejściu - „czy to się w ogóle
     rusza". Ton spokojny, bez koloru alarmu: plan nie jest zdarzeniem, tylko
     stanem, w którym portal jest przez kilkanaście godzin. */
  .tlplan{display:flex;align-items:center;gap:var(--space-4);flex-wrap:wrap;
      margin:var(--space-4) 0 0;padding:var(--space-4) var(--space-5);
      background:var(--cx-mist);border:1px solid var(--line);
      border-left:3px solid var(--cx-green);border-radius:var(--radius-md)}
  .tlplan__co{flex:1 1 320px;display:flex;flex-direction:column;gap:3px;min-width:0}
  .tlplan__co b{font-size:14.5px}
  .tlplan__co span{font-size:13px;color:var(--cx-ink-80)}
  .tlplan__wolno{font-size:12px;color:var(--soft)}
  .tlplan__co i{font-style:normal;font-size:11.5px;color:var(--soft)}
  .tlplan__zle{margin-top:var(--space-2);font-size:13.5px;color:var(--cx-error)}
  .tlplan .btn{flex:none}
  .tlplan--koniec{border-left-color:var(--cx-ink-20)}

  /* ── edytor tłumaczenia (okno) ─────────────────────────────────────── */
  /* Selektory dwu- i trzyczłonowe, nie dla ozdoby: `.mdlbox`, `.mdlbody`
     i `.tlkol .docbody` stoją NIŻEJ w tym arkuszu, więc przy równym ciężarze
     wygrywają. Bez tego okno edytora dziedziczyło `padding` i `max-height`
     okna podglądu, a trzy kolumny składały się w jedną. Ta sama pułapka,
     co przy `.mdlbox.mdlbox--szeroki` niżej. */
  /* Okno zajmuje ekran, bo trzy kolumny tekstu w małym pudełku są nieczytelne.
     `grid` z trzema rzędami (głowa, treść, stopka) zamiast `flex`: głowa
     z polem tytułu rosła wcześniej ponad swój rząd i dolna krawędź obcinała
     jej połowę - `min-height:0` na środkowym rzędzie mówi przeglądarce, że
     to ON ma się kurczyć, a nie głowa. */
  .mdlbox.tledbox{display:grid;grid-template-rows:auto 1fr auto;
      width:min(1680px,96vw);height:92vh;max-height:92vh}
  .mdlbox.tledbox .mdlhead{align-items:flex-start;gap:var(--space-4)}
  .tledtyt{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:4px}
  .tlodrztyt{width:100%;font:600 20px/1.35 var(--font-display,inherit);
      border:1px solid var(--line);border-radius:var(--radius-md);
      padding:var(--space-2) var(--space-3);background:var(--cx-white);
      color:var(--text)}
  .mdlbody.tledbody{display:flex;flex-direction:column;gap:var(--space-3);min-height:0;
      overflow:hidden;padding-bottom:0}
  .tledkolumny{display:grid;grid-template-columns:1fr 1fr 1fr;gap:var(--space-4);
      min-height:0;flex:1 1 auto}
  .tledkolumny--dwie{grid-template-columns:1fr 1fr}
  /* Kolumna, w której się pisze. Ta sama mechanika, co na stronie artykułu:
     podkreślenie zamiast ramki, obwódka dopiero pod kursorem - inaczej
     tłumaczenie wygląda jak tabelka i nie da się go czytać. */
  .tledpisz .artedblok{cursor:text;border-radius:6px;
      box-shadow:inset 0 -1px 0 color-mix(in srgb,var(--cx-green) 55%,transparent);
      transition:background .14s ease}
  .tledpisz .artedblok:hover{background:color-mix(in srgb,var(--cx-green) 9%,transparent)}
  .tledpisz .artedblok--zmieniony{box-shadow:inset 0 -2px 0 var(--cx-yellow);
      background:color-mix(in srgb,var(--cx-yellow) 12%,transparent)}
  .sideh i{font-style:normal;font-weight:400;text-transform:none;letter-spacing:0;
      color:var(--soft)}
  .tledbody .tledkolumny .tlkol{display:flex;flex-direction:column;min-height:0;min-width:0}
  .tledbody .tledpole{flex:1 1 auto;min-height:0;resize:none;width:100%;
      font:13px/1.65 ui-monospace,SFMono-Regular,Menlo,monospace;
      border:1px solid var(--line);border-radius:var(--radius-md);
      padding:var(--space-3);background:var(--cx-white);color:var(--text)}
  .tledbody .tlkol .tledwidok{flex:1 1 auto;min-height:0;overflow:auto;
      border:1px solid var(--line);border-radius:var(--radius-md);
      padding:var(--space-4);background:var(--cx-white)}
  .mdlstopka{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;
      padding:var(--space-4) var(--space-5);border-top:1px solid var(--line)}
  .mdlstopka .authalert{margin:0;flex:1 1 240px}
  .mdlstopka .btn{margin-left:auto}
  .mdlstopka .btn + .btn{margin-left:0}

  /* Czego brakuje. Pasek stoi NAD kolumnami, bo to jest pierwsze pytanie po
     otwarciu edytora: co właściwie jest nie tak. Znika sam, gdy braków nie ma -
     zielona plakietka „bez zastrzeżeń" mówi wtedy, że można zapisywać. */
  .tledbraki{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;
      padding:10px var(--space-4);border-radius:var(--radius-md);
      background:color-mix(in srgb,var(--cx-error) 8%,transparent);
      border:1px solid color-mix(in srgb,var(--cx-error) 30%,transparent);
      font-size:13px}
  .tledbraki--ok{background:color-mix(in srgb,var(--cx-green) 12%,transparent);
      border-color:color-mix(in srgb,var(--cx-green) 40%,transparent)}
  .tledbraki i{font-style:normal;color:var(--soft);font-size:12px}
  .tledbrak{padding:2px 10px;border-radius:999px;background:var(--cx-white);
      border:1px solid var(--line);font-size:12px;cursor:help}
  /* Element, którego w tłumaczeniu brakuje - zaznaczamy JEGO, w kolumnie
     oryginału. Obwódka, nie samo tło: zgubiony odsyłacz bywa jednym słowem
     w środku zdania i sam kolor tła ginie w tekście. */
  .tledbody .tledwidok .brakuje{outline:2px solid var(--cx-error);outline-offset:2px;
      border-radius:3px;background:color-mix(in srgb,var(--cx-error) 14%,transparent)}
  @media (max-width:1200px){
    .tledkolumny{grid-template-columns:1fr;overflow:auto}
    .tledbody .tledpole,.tledbody .tlkol .tledwidok{min-height:44vh;max-height:none}
  }

  .tltab{list-style:none;display:flex;flex-direction:column;margin:0;padding:0;
      border-top:1px solid var(--line)}
  /* Osiem kolumn: zaznaczenie, artykuł, objętość, koszt prognozowany,
     koszt poniesiony, kiedy, stan, akcje. Koszty są DWIE kolumny, nie jedna
     przełączana: to dwie różne liczby o tym samym artykule i zestawienie ich
     obok siebie pokazuje, czy szacunek trzyma się rzeczywistości.
     Stan to dziś kropka, a akcje cztery ikonki - obie kolumny zwęziły się
     z 170 i 238 px do 44 i 150. Odzyskane px poszły na tytuł, bo to
     po nim czytelnik rozpoznaje artykuł. */
  .tltab>li{display:grid;
      grid-template-columns:34px minmax(0,1fr) 80px 78px 88px 76px 76px 104px 90px 128px 118px 128px;
      align-items:center;gap:10px;border-bottom:1px solid var(--line)}
  .tlhead{padding:10px var(--space-3);font-size:11px;font-weight:600;letter-spacing:.1em;
      text-transform:uppercase;color:var(--soft)}
  /* Najdłuższy nagłówek („PRZETŁUMACZONO") przy rozstrzelonych wersalikach
     wychodził poza swój słupek i dosuwał się do sąsiada - wyglądało to jak
     jeden napis „PRZETŁUMACZONOSTAN". Słupek jest szerszy, a nagłówek i tak
     ma zakaz wychodzenia poza niego. */
  .tlhead>span{min-width:0;overflow:hidden}
  /* Na szerokim ekranie otoczka liczb nie istnieje dla układu - dzieci
     wpadają wprost do siatki wiersza, każde do swojej kolumny. */
  .tlmeta{display:contents}
  .tlrow{padding:11px var(--space-3);transition:background .16s ease}
  .tlrow:hover{background:var(--cx-mist)}
  .tlrow--wybrany{background:rgba(173,247,99,.12)}
  /* Wiersz przetłumaczonego artykułu otwiera porównanie. Kursor musi to
     zapowiadać - klikalny obszar, który wygląda jak zwykły tekst, znajduje
     tylko ten, kto już wie, że jest. */
  .tlrow--klik{cursor:pointer}
  .tltytul{display:flex;flex-direction:column;gap:2px;min-width:0}
  /* Koszt: szacunek przygaszony, zapłacone naprawdę - pełnym kolorem.
     Różnica ma być widoczna bez czytania dymka. */
  .tlkoszt{font-size:13px;color:var(--soft);font-variant-numeric:tabular-nums;
      white-space:nowrap;cursor:help}
  .tlkoszt--prognoza{font-size:12.5px}
  .tlkoszt--realny{color:var(--text);font-weight:700}
  /* Brak rachunku to myślnik, nie zero - zero znaczyłoby „za darmo". */
  .tlkoszt--pusty{color:var(--cx-ink-20)}
  .tlakcjer{display:flex;align-items:center;gap:2px;justify-content:flex-end}

  /* Stopka tabelki: te same kolumny, co wiersze, więc sumy stoją dokładnie
     pod liczbami, które sumują. Bez tego trzeba by je czytać po kolei
     i zgadywać, do której kolumny należą. */
  .tlsuma{padding:12px var(--space-3);background:var(--cx-mist);
      border-bottom:none;font-size:13px}
  .tlsuma__co{color:var(--text)}
  .tlsuma .tlznaki,.tlsuma .tlkoszt{font-weight:700;color:var(--text)}
  .tlsuma__stan{font-size:12px;color:var(--soft);font-variant-numeric:tabular-nums;
      white-space:nowrap;cursor:help}

  /* Akcje na ikonach. Podpis idzie w `title` i `aria-label`: trzy napisy
     w wierszu zjadały połowę szerokości listy, a lista ma 1197 pozycji.
     Pole dotyku zostaje pełne (34 px), mimo że sam znak ma 17. */
  .tlik{display:inline-flex;align-items:center;justify-content:center;
      width:34px;height:34px;padding:0;border:1px solid transparent;border-radius:9px;
      background:none;color:var(--soft);cursor:pointer;
      transition:background .16s ease,color .16s ease,border-color .16s ease}
  /* Rozmiar znaku ustala ARKUSZ, nie atrybuty w SVG. Ikonki przychodzą
     z różnych miejsc i część z nich nie deklaruje `width`/`height` - taka
     rozciągała się na cały 34-pikselowy guzik i ołówek był dwa razy większy
     od sąsiadów. Jedna reguła zamiast pilnowania atrybutów w każdej ikonie. */
  .tlik svg{width:19px;height:19px;flex:none}
  /* Wszystkie ikony w wierszu zachowują się tak samo: szare w spoczynku,
     zielone po najechaniu. Wcześniej najechanie dawało `--text`, czyli ciemny
     atrament - ruch było widać, ale nic nie mówił. Zieleń mówi „to zadziała",
     tym samym kolorem, co reszta portalu. */
  .tlik:hover{background:var(--cx-mist);color:var(--cx-green);border-color:var(--line)}
  .tlik:focus-visible{outline:2px solid var(--cx-green);outline-offset:2px;color:var(--cx-green)}
  /* Tłumaczenie było dotąd wyróżnione: ciemniejsze w spoczynku i z pełną plamą
     limonki po najechaniu. Radek poprosił, żeby WSZYSTKIE ikony wyglądały tak
     samo, więc wyróżnienie znika - rząd czyta się teraz jako jeden zestaw
     narzędzi, a nie jako jedna akcja i trzy dodatki. Klasa zostaje, bo niesie
     znaczenie w znaczniku i gdyby wyróżnienie miało wrócić, wraca tutaj. */

  /* Stan jednym kolorem. Kółko ma `title`, więc nazwa jest pod kursorem,
     a legenda nad listą wypisuje wszystkie stany słowami. */
  .tlkropka{display:inline-block;width:11px;height:11px;border-radius:50%;
      box-shadow:0 0 0 3px rgba(18,32,33,.05);cursor:help}
  .tlstan{display:flex;justify-content:center}
  /* Etykieta stanu w stylu tablicy monday.com: pełne tło w kolorze stanu,
     biały napis, cały dostępny słupek. Biel czyta się na każdym z pięciu
     naszych kolorów - najjaśniejszy („Nie przetłumaczono") jest szary
     #c4c4c4, a nie pastel, więc kontrast wystarcza. */
  .tletykieta{display:flex;align-items:center;justify-content:center;width:100%;
      min-height:28px;padding:4px 8px;border-radius:4px;color:#fff;font-size:12px;
      font-weight:600;line-height:1.25;text-align:center;cursor:help}

  /* Legenda: co znaczy kolor kropki i czym różni się prognoza od rachunku. */
  .tllegenda{display:flex;flex-wrap:wrap;align-items:center;gap:6px 18px;
      margin:var(--space-3) 0 var(--space-2);font-size:12px;color:var(--soft)}
  .tllegenda span{display:inline-flex;align-items:center;gap:6px}
  .tllegenda .tlkropka{width:9px;height:9px;box-shadow:none;cursor:default}
  .tllegenda .tlkoszt{cursor:default}
  .tllegenda__kurs{margin-left:auto;font-variant-numeric:tabular-nums}

  /* Ramka „w jakich planach to działa" w podglądzie przed i po. Ten sam
     kształt co `.callout` w artykule, tylko drobniejszy - podgląd jest wąski. */
  .tlramka{display:flex;gap:10px;margin:14px 0;padding:12px 14px;
      border-left:3px solid var(--cx-green);border-radius:8px;background:var(--cx-mist)}
  .tlramka>span{flex:none;font-size:15px;line-height:1.4}
  .tlramka p{margin:0;font-size:14px;line-height:1.55}
  .tltytul b{font-size:14px;font-weight:500;color:var(--text);overflow-wrap:anywhere}
  /* Flaga stoi przed tytułem i ma NIE wpływać na wysokość wiersza - emoji
     bywają wyższe od tekstu obok. */
  .tlflaga{margin-right:7px;font-size:13px;line-height:1;cursor:help;
      vertical-align:1px}
  /* Kolumna „Kiedy": data przy skończonych, „zlecono …" przy tych w robocie.
     Cyfry o stałej szerokości, żeby daty stały w pionie jedna pod drugą. */
  .tlkiedy{font-size:12.5px;color:var(--soft);font-variant-numeric:tabular-nums;
      white-space:nowrap}
  .tlkiedy i{font-style:normal}
  .tlkiedy .tlpusto{color:var(--cx-ink-20)}
  /* Konto, które zleciło. Cyfry stałej szerokości są tu niepotrzebne, a nazwa
     dłuższa od słupka ma się przyciąć, a nie rozepchnąć wiersza. */
  .tlkto{font-variant-numeric:normal;overflow:hidden;text-overflow:ellipsis}
  .tltytul i{font-style:normal;font-size:11.5px;color:var(--soft);overflow-wrap:anywhere}
  .tlznaki{font-size:12.5px;color:var(--soft);font-variant-numeric:tabular-nums}
  .tlblad{display:block;margin-top:3px;font-style:normal;font-size:11px;color:var(--cx-error)}

  .tlwyt{display:flex;flex-direction:column;gap:var(--space-3)}
  .tlwytmenu{display:flex;flex-wrap:wrap;gap:5px}
  .tlwytbtn{font:inherit;font-size:13.5px;padding:8px 14px;cursor:pointer;
      border-radius:var(--radius-md);background:var(--cx-white);border:1px solid var(--line);
      color:var(--body-fg)}
  .tlwytbtn.on{background:var(--cx-ink);border-color:var(--cx-ink);color:var(--cx-lime);font-weight:600}
  .tlwythint{margin:0;font-size:13px;line-height:1.6;color:var(--muted);max-width:75ch}
  .tlwytpole{width:100%;min-height:60vh;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
      font-size:13px;line-height:1.65;padding:var(--space-4);tab-size:2;
      color:var(--text);background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-md);resize:vertical}
  .tlwytpole:focus{outline:none;border-color:var(--cx-turquoise-600);
      box-shadow:0 0 0 3px rgba(74,158,150,.16)}
  .tlwytstopka{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3)}
  /* To samo pole w okienku zlecenia mieści trzy wiersze, nie pół ekranu -
     tam jest edytorem wytycznych, tutaj tylko listą identyfikatorów. */
  .mdlbody .tlwytpole{min-height:0;margin:var(--space-3) 0}
  .tlwytstopka .btn{margin-left:auto}

  /* Podgląd „przed i po" - dwie kolumny, na wąskim ekranie jedna pod drugą. */
  /* Dwa selektory klas zamiast jednego, i to nie dla ozdoby: `.mdlbox`
     i `.mdlbody` stoją NIŻEJ w tym arkuszu, więc przy równym ciężarze
     wygrywały i podgląd składał się w jedną kolumnę na pełnej szerokości. */
  .mdlbox.mdlbox--szeroki{width:min(1280px,96vw);max-width:none}
  .mdlbody.tlpodglad{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
      gap:var(--space-5)}
  .tlkol{min-width:0}
  .tlkol .docbody{margin-top:var(--space-3);max-height:66vh;overflow-y:auto;
      padding-right:var(--space-3)}
  .tlkol .docbody img{max-width:100%;height:auto;border:1px solid var(--line);
      border-radius:var(--radius-md);margin:var(--space-3) 0}
  @media(max-width:900px){
    /* Okno dostaje wysokość, żeby dwie połowy miały się czym podzielić -
       przy wysokości z treści `1fr 1fr` rozłożyłoby się po tekście i polskie
       tłumaczenie znowu wylądowałoby pod ekranem. */
    .mdlbox--szeroki{height:min(92svh,900px)}
    .mdlbody.tlpodglad{grid-template-columns:minmax(0,1fr);
        grid-template-rows:1fr 1fr;gap:0;flex:1 1 auto;min-height:0;
        overflow:hidden;padding:0}
    .tlpodglad .tlkol{min-height:0;display:flex;flex-direction:column;
        padding:var(--space-4) var(--space-5)}
    /* Granica między oryginałem a tłumaczeniem: gruba i w kolorze marki,
       bo to jedyny sygnał, że niżej zaczyna się druga wersja tekstu. */
    .tlpodglad .tlkol+.tlkol{border-top:3px solid var(--cx-lime);
        background:var(--cx-mist)}
    .tlpodglad .tlkol .docbody{max-height:none;flex:1 1 auto;overflow-y:auto;
        margin-top:var(--space-2);padding-right:var(--space-3)}
    .tlpodglad .sideh{flex:none}

    /* Na telefonie w wierszu zostaje tytuł, kropka stanu i akcje. Objętość
       i koszt schodzą z KAŻDEGO wiersza, bo to liczby do decyzji przy biurku,
       a nie w biegu - ale zostają w stopce, gdzie jeden zestaw sum mówi
       tyle samo i zajmuje jeden wiersz zamiast dwudziestu siedmiu.

       Każdy kawałek dostaje wskazane miejsce. Bez tego automatyczne układanie
       wpychało kropkę stanu w osobny wiersz na środku, a akcje pod nią. */
    .tltab>li{grid-template-columns:28px minmax(0,1fr) auto;
        column-gap:var(--space-3);row-gap:10px;align-items:start;
        padding:14px var(--space-3)}
    /* Nagłówek kolumn znika razem z kolumnami. Musi być przez `.tltab>li`,
       bo samo `.tlhead` przegrywa specyficznością z regułą wyżej i etykiety
       „PROGNOZA" i „PONIESIONY" nachodziły na siebie na środku ekranu. */
    .tltab>li.tlhead{display:none}
    .tltab>li>span:first-child{grid-area:1/1/2/2;padding-top:2px}
    .tltytul{grid-area:1/2/2/3}
    /* Adres artykułu bywa dłuższy niż ekran i zabierał dwa wiersze na coś,
       co jest tylko podpisem pod tytułem. Jedna linia z wielokropkiem. */
    .tltytul i{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

    .tlstan{grid-area:1/3/2/4;justify-self:end;padding-top:5px}
    .tllegenda{display:none}
    /* Liczby schodzą pod tytuł, w jeden wiersz, zamiast znikać z listy.
       Drobnym pismem, bo to podpis, a nie treść wiersza. */
    .tlmeta{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px var(--space-3);
        grid-area:2/2/3/-1;font-size:12px;color:var(--soft)}
    .tlmeta .tlznaki{display:inline}
    .tlrow .tlkoszt{display:inline-flex;font-size:12px}
    .tlrow .tlkoszt--realny{font-size:12px}
    /* Akcje pod tytułem, na pełną szerokość i z odstępem pod palec. */
    .tlakcjer{grid-area:3/1/4/-1;flex-wrap:wrap;justify-content:flex-start;gap:6px}
    .tlik{width:40px;height:40px}

    /* Stopka zostaje z liczbami - to jedyne miejsce, gdzie sumy mają sens
       na małym ekranie. Układamy ją w wiersz, który sam się zawija. */
    .tltab>li.tlsuma{display:flex;flex-wrap:wrap;align-items:baseline;
        gap:4px var(--space-4);padding:14px var(--space-3)}
    .tlsuma>span:empty{display:none}
    .tlsuma__co{flex:1 0 100%}
    .tlsuma .tlznaki,.tlsuma .tlkoszt,.tlsuma__stan{display:inline-flex}

    .tlsumtile--glowny{grid-column:1/-1}
  }

  /* pasek ważności planu */
  .zgplan{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);
      background:var(--cx-mist);border:1px solid var(--line);border-radius:var(--radius-md);
      padding:12px var(--space-4);font-size:13.5px;color:var(--body-fg);margin-bottom:var(--space-5)}
  .zgplan--minal{background:rgba(180,35,24,.06);border-color:rgba(180,35,24,.28)}
  /* Konto darmowe - ton zachęty, nie ostrzeżenia. */
  .zgplan--free{background:rgba(173,247,99,.14);border-color:rgba(18,32,33,.16)}
  .zgplan b{color:var(--text);font-weight:600}
  .zgplan .btn{margin-left:auto;padding:7px 14px;font-size:13px}

  /* szczegół zgłoszenia */
  .zgnag{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;
      gap:var(--space-4);padding-bottom:var(--space-4);border-bottom:1px solid var(--line)}
  /* Nadtytuł i plakietka na szczególe sprawy. Te same klasy stały kiedyś
     na kartach listy - po przejściu listy na tabelę zostały już tylko tutaj. */
  .zgglowa{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-3);
      font-size:12px;color:var(--soft)}
  .zgnr{font-weight:600;color:var(--cx-turquoise-600);letter-spacing:.02em}
  .zgmeta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3)}
  .zgstan{display:inline-flex;align-items:center;padding:6px 12px;border-radius:8px;
      font-size:11.5px;font-weight:600;letter-spacing:.02em}

  /* Nagłówek sprawy jest teraz jedynym <h1> na stronie (decyzja 9): większy
     stopień, lżejsza waga, więcej powietrza pod kreską. */
  .zgnag{padding-bottom:clamp(20px,3vh,28px)}
  /* Zgłoszenie kolegi widziane przez menedżera (#97). */
  .zgcudze{margin:8px 0 0;max-width:62ch;font-size:13.5px;line-height:1.5;color:var(--soft)}
  .tkkto{display:block;margin-top:2px;font-size:12px;color:var(--soft)}
  .zgnag h1{font-family:var(--font-display);font-weight:400;font-size:clamp(24px,3vw,34px);
      line-height:1.15;letter-spacing:-.01em;color:var(--text);margin:8px 0 0;max-width:34ch}
  /* ── Wątek jako rozmowa ────────────────────────────────────────────────
     Wiadomość klienta odbija się na prawo i ma własne tło z ogonkiem, nasza
     zostaje po lewej na białym. Dymek nie rozlewa się na całą szerokość -
     min(76ch, 86%) - bo długiego akapitu na pełnej kolumnie nie da się czytać. */
  .thread{list-style:none;display:flex;flex-direction:column;gap:var(--space-5);
      margin:clamp(28px,4vh,44px) 0 0;padding:0}
  .msg{display:grid;grid-template-columns:34px minmax(0,1fr);
      grid-template-areas:"av kto" ". babel";gap:6px var(--space-3);
      justify-items:start}
  /* Prośba o potwierdzenie siedzi W ŚRODKU białego dymka ostatniej odpowiedzi
     (poprawka Radka 29.09). Do tego dnia była osobną płytką pod dymkiem,
     w kreskowanej ramce - czyli czymś OBOK wiadomości, a pytanie dotyczy
     właśnie TEJ wiadomości. Oddziela je sama kreska nad, bez drugiego tła:
     płytka w płytce wygląda jak wtrącenie z innego ekranu. */
  .msgprosba{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);
      margin:var(--space-4) 0 0;padding:var(--space-4) 0 0;
      border-top:1px solid var(--line)}
  .msgprosba p{margin:0;font-size:14.5px;line-height:1.5;flex:1;min-width:180px}
  /* Minimalny odstęp POD wiadomością z prośbą - dymek urósł o pytanie, więc
     bez tego następna wiadomość zaczyna się zaraz za guzikiem. */
  .msg--prosba{margin-bottom:var(--space-3)}
  /* Pytanie „na pewno?" zamiast okienka przeglądarki - staje dokładnie
     w miejscu klikniętego guzika, w nagłówku i w dymku tak samo. */
  .zgpotw{display:inline-flex;flex-wrap:wrap;align-items:center;gap:8px var(--space-3)}
  .zgpotwtx{font-size:14px;color:var(--text);font-weight:600}
  .zgpotwbtn{display:inline-flex;flex-wrap:wrap;gap:8px}
  .zgpotwblad{flex-basis:100%;font-size:13px;color:var(--cx-error)}
  @media (max-width:599px){
    .msgprosba{flex-direction:column;align-items:stretch}
    .msgprosba .btn{width:100%;justify-content:center}
    .zgpotw{display:flex;align-items:stretch;flex-direction:column}
    .zgpotwbtn{display:grid;grid-template-columns:1fr 1fr}
    .zgpotwbtn .btn{width:100%;justify-content:center}
  }
  .msg--klient{grid-template-columns:minmax(0,1fr) 34px;
      grid-template-areas:"kto av" "babel .";justify-items:end}
  /* Ta sama zasada co w liście zgłoszeń: inicjały człowieka to białe litery
     na szarym kole. Wątek ma je przy każdej wiadomości klienta. */
  .msgav{grid-area:av;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
      font-size:11.5px;font-weight:600;flex:none;overflow:hidden;
      background:var(--cx-gray-2);color:var(--cx-white);border:1px solid var(--cx-gray-2)}
  .msgav--cx{background:var(--cx-ink);color:var(--cx-lime);border-color:var(--cx-ink)}
  .msgav svg{width:100%;height:100%;display:block}
  .msgkto{grid-area:kto;display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-3);
      font-size:12px;color:var(--soft);align-self:center}
  .msg--klient .msgkto{flex-direction:row-reverse}
  .msgkto b{font-size:13.5px;font-weight:600;color:var(--text)}
  /* Ogonek dymka: jeden róg zostaje ostry po stronie awatara. */
  .msgbabel{grid-area:babel;max-width:min(76ch,86%);min-width:0;
      padding:13px var(--space-4);border:1px solid var(--line);
      border-radius:var(--radius-md) var(--radius-md) var(--radius-md) 4px;
      background:var(--cx-white)}
  /* Wiadomość KLIENTA siedzi na jasnej płycie w barwie szaty, z CIEMNĄ farbą -
     kolory odczytane z makiety Claude Design przysłanej przez Radka 1.10
     (`rgb(237,243,241)` dymek, `rgb(232,236,237)` kółko awatara), a nie dobrane
     z oka.
     TO ZASTĘPUJE decyzję z 29.09, w której dymek był `#ACACAC`, a farba biała.
     Tamto zestawienie dawało kontrast **2,2:1**, czyli poniżej progu WCAG AA
     (4,5:1) - i było to przy tej decyzji zapisane wprost jako jej koszt. Nowa
     para daje **13,5:1**, więc koszt zniknął razem ze starym tłem.
     Zasada zostaje ta sama i warto ją powtórzyć, bo łatwo się o nią potknąć
     przy następnej zmianie: **tło i farba chodzą w parze** - zmiana samego tła
     zostawia farbę z poprzedniego świata. */
  .msg--klient .msgbabel{background:rgb(237,243,241);border-color:rgb(226,234,231);
      border-radius:var(--radius-md) var(--radius-md) 4px var(--radius-md)}
  .msg--klient .zgtresc{color:var(--text)}
  /* Kółko z inicjałami klienta: jasne, z ciemnymi literami - jak w makiecie.
     Domyślne `.msgav` (ciemnoszare tło, biała farba) zostaje dla miejsc, gdzie
     awatar stoi na ciemnym pasku. */
  .msg--klient .msgav{background:rgb(232,236,237);color:var(--text);
      border-color:rgb(222,228,229)}
  /* Adres pod nazwiskiem - w firmie pisze kilka osób i to on rozstrzyga,
     która. Stoi tylko wtedy, gdy podpis go nie zawiera. */
  .msgmail{font-style:normal;font-size:12px;color:var(--soft)}
  @media(max-width:640px){
    .msgbabel{max-width:100%}
  }

  /* treść przychodzi z maila, więc może przynieść własne znaczniki - trzymamy ją
     w ryzach, żeby nie rozjechała kolumny */
  .zgtresc{font-size:14.5px;line-height:1.65;color:var(--body-fg);overflow-wrap:anywhere}
  .zgtresc p{margin:0 0 .7em}
  .zgtresc p:last-child{margin-bottom:0}
  .zgtresc a{color:var(--cx-turquoise-600);text-decoration:underline}
  .zgtresc img{max-width:100%;height:auto;border-radius:8px}
  .zgtresc table{max-width:100%;display:block;overflow-x:auto}
  .zgtresc blockquote{margin:0 0 .7em;padding-left:var(--space-4);
      border-left:2px solid var(--line);color:var(--soft)}

  /* odpowiedź */
  /* Pole odpowiedzi nie jest już kartą: sama kreska nad nim wystarczy,
     żeby oddzielić je od wątku, a ekran robi się o kartę lżejszy.
     Turkusowy fokus na polu zostaje - to mocniejszy sygnał dostępnościowy
     niż samo przyciemnienie obrysu. */
  .zgodp{margin-top:clamp(28px,4vh,44px);padding-top:clamp(24px,3.5vh,36px);
      border-top:1px solid var(--line)}
  .zgodp textarea{width:100%;font:inherit;font-size:14.5px;line-height:1.6;padding:12px 13px;
      color:var(--text);background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-sm);resize:vertical;min-height:110px}
  .zgodp textarea:focus{outline:none;border-color:var(--cx-turquoise-600);
      box-shadow:0 0 0 3px rgba(74,158,150,.16)}
  .zgodpstopka{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);
      margin-top:var(--space-3)}
  .zgodpstopka .btn{margin-left:auto}
  .zgpliki{display:flex;flex-wrap:wrap;gap:8px;margin-top:var(--space-3)}
  .zgplik{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;padding:5px 10px;
      border-radius:7px;background:var(--cx-mist);border:1px solid var(--line);color:var(--body-fg)}
  .zgplik button{background:none;border:0;padding:0;cursor:pointer;color:var(--soft);line-height:0}
  .zgplik button:hover{color:var(--cx-error)}
  .zgdodaj{display:inline-flex;align-items:center;gap:7px;font:inherit;font-size:13.5px;
      padding:8px 13px;border-radius:var(--radius-sm);cursor:pointer;
      background:var(--cx-white);border:1px solid var(--line);color:var(--body-fg)}
  .zgdodaj:hover{background:var(--cx-mist);color:var(--text)}

  /* ankieta po rozwiązaniu */
  .zgcsat{margin-top:var(--space-5);background:var(--cx-mist);border:1px solid var(--line);
      border-radius:var(--radius-md);padding:var(--space-5);text-align:center}
  .zgcsat h3{font-family:var(--font-display);font-weight:500;font-size:18px;color:var(--text);margin:0}
  .zggwiazdki{display:flex;justify-content:center;gap:6px;margin:var(--space-4) 0}
  .zggwiazdka{background:none;border:0;padding:4px;cursor:pointer;color:var(--cx-cloud-2);line-height:0}
  .zggwiazdka:hover,.zggwiazdka.on{color:#e8b33a}
  /* PODGLĄD POD KURSOREM ZAPALA GWIAZDKI OD PIERWSZEJ, nie samą wskazaną
     (zgłoszenie Radka 29.09: „w przypadku oceny cztery powinny podświetlić się
     gwiazdki od jeden do cztery, a nie tylko czwarta"). Kliknięcie robiło to
     poprawnie od początku - `.on` dostają wszystkie do wybranej - ale najazd
     zapalał jedną i wyglądało to jak zepsuta ocena.
     Sam najazd na pasek GASI poprzedni wybór, żeby podgląd mówił prawdę:
     inaczej przy ocenie 4 i kursorze na 2 świeciłyby się cztery.
     `:has(~ …)` sięga do gwiazdek STOJĄCYCH PRZED tą pod kursorem - inaczej
     trzeba by odwracać kolejność w znaczniku, a wtedy czytnik ekranu czyta
     ocenę od pięciu do jednego. Gdzie `:has()` nie działa, zostaje stare
     zachowanie - czyli gorszy podgląd, a nie zepsuty ekran. */
  .zggwiazdki:hover .zggwiazdka{color:var(--cx-cloud-2)}
  .zggwiazdki .zggwiazdka:has(~ .zggwiazdka:hover),
  .zggwiazdki .zggwiazdka:hover{color:#e8b33a}

  /* ekran oceny obsługi (własny formularz CSAT, wejście z maila bez logowania).
     Osobne klasy, a nie `.zgcsat`: tam ankieta jest dopiskiem pod wątkiem,
     tutaj jest CAŁYM ekranem - inna skala gwiazdek, inne odstępy, inna waga. */
  .ocnwrap{max-width:620px;margin:0 auto}
  .ocnkarta{background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-md);padding:var(--space-6);text-align:center}
  .ocnkicker{display:inline-flex;align-items:center;gap:8px;font-size:12px;font-weight:600;
      letter-spacing:.06em;text-transform:uppercase;color:var(--body-fg)}
  .ocnkicker::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--cx-lime)}
  .ocnkarta h1,.ocndzieki h1{font-family:var(--font-display);font-weight:500;font-size:27px;
      line-height:1.25;color:var(--text);margin:var(--space-3) 0 0}
  .ocnsub{font-size:15px;color:var(--body-fg);margin:var(--space-2) auto 0;max-width:44ch}
  .ocnkontekst{margin-top:var(--space-4);padding:12px 14px;background:var(--cx-mist);
      border:1px solid var(--line);border-radius:var(--radius-sm);
      display:flex;flex-wrap:wrap;gap:4px 10px;justify-content:center;align-items:baseline}
  .ocnnumer{font-weight:600;font-size:14px;color:var(--text)}
  .ocntemat{font-size:14px;color:var(--body-fg)}
  .ocngwiazdy{display:flex;justify-content:center;gap:4px;margin:var(--space-5) 0 var(--space-2)}
  .ocngwiazda{background:none;border:0;padding:4px;cursor:pointer;line-height:0;
      color:var(--cx-cloud-2);transition:transform .16s ease,color .16s ease}
  .ocngwiazda svg{width:40px;height:40px}
  .ocngwiazda:hover{transform:scale(1.14)}
  .ocngwiazda:hover,.ocngwiazda.on{color:#e8b33a}
  /* To samo co przy gwiazdkach pod zgłoszeniem: najazd zapala od pierwszej. */
  .ocngwiazdy:hover .ocngwiazda{color:var(--cx-cloud-2)}
  .ocngwiazdy .ocngwiazda:has(~ .ocngwiazda:hover),
  .ocngwiazdy .ocngwiazda:hover{color:#e8b33a}
  .ocngwiazdy--wynik .ocngwiazda{color:var(--cx-cloud-2);line-height:0;padding:4px}
  .ocngwiazdy--wynik .ocngwiazda.on{color:#e8b33a}
  .ocnpodpis{font-size:14px;color:var(--body-fg);margin:0;min-height:20px}
  .ocnzmaila{display:block;font-size:12.5px;color:var(--muted-fg,var(--body-fg));margin-top:4px}
  .ocnpole{margin-top:var(--space-5);text-align:left}
  .ocnpole textarea{width:100%;font:inherit;font-size:15px;line-height:1.6;padding:11px 13px;
      color:var(--text);background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-sm);resize:vertical}
  .ocnwyslij{margin-top:var(--space-5);width:100%;justify-content:center}
  .ocnwyslij[disabled]{opacity:.5;cursor:default}
  .ocndzieki{text-align:center;padding:var(--space-6) var(--space-4)}
  .ocndzieki p{font-size:15px;color:var(--body-fg);margin:var(--space-2) auto var(--space-5);max-width:44ch}
  @media (max-width:560px){
    .ocnkarta{padding:var(--space-5) var(--space-4)}
    .ocngwiazda svg{width:34px;height:34px}
    .ocnkarta h1,.ocndzieki h1{font-size:23px}
  }

  /* formularz nowego zgłoszenia */
  .zgnowe{max-width:720px}
  .zgnowe .fld textarea{width:100%;font:inherit;font-size:15px;line-height:1.6;padding:11px 13px;
      color:var(--text);background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-sm);resize:vertical;min-height:150px}
  .zgnowe .fld textarea:focus{outline:none;border-color:var(--cx-turquoise-600);
      box-shadow:0 0 0 3px rgba(74,158,150,.16)}
  .zglicznik{font-size:12px;color:var(--soft);text-align:right}
  .zgdrop{border:1.5px dashed var(--line);border-radius:var(--radius-md);padding:var(--space-5);
      text-align:center;color:var(--body-fg);font-size:14px;cursor:pointer;
      transition:border-color .15s,background .15s}
  .zgdrop:hover,.zgdrop.nad{border-color:var(--cx-turquoise-600);background:var(--cx-mist)}
  .zgdrop b{display:block;color:var(--text);font-weight:600;margin-bottom:3px}
  /* Pole na załączniki w formularzu zgłoszenia (makieta Claude Design): ikona
     „wgraj" nad dwiema liniami, w ramce z kreski. Tło jest jasne OD RAZU, a nie
     dopiero na najechaniu - panel po prawej ma się czytać jako osobna płyta,
     nie jako puste miejsce. */
  .zncol--bok .zgdrop{display:flex;flex-direction:column;align-items:center;gap:4px;
      padding:var(--space-5) var(--space-4);background:var(--surface-alt);
      border-color:var(--line2)}
  .zncol--bok .zgdrop svg{color:var(--body-fg)}
  .zncol--bok .zgdrop b{margin:0;font-weight:500}
  .zncol--bok .zgdrop b u{font-weight:700;text-decoration:none}
  .zncol--bok .zgdrop>span{font-size:12.5px;color:var(--muted)}

  /* `.btn--ghost` jest pomyślany na ciemne płyty (ma `color:mist !important`),
     więc na białej karcie znika. Ten wariant jest jego odpowiednikiem na jasnym
     tle - stąd `!important`, inaczej przegrywa z regułą bazową. */
  .btn--obrys{background:var(--cx-white)!important;color:var(--text)!important;
      border:1px solid var(--line)!important}
  .btn--obrys:hover{background:var(--cx-mist)!important;color:var(--cx-ink)!important;filter:none}

  .zgpusto{text-align:center;padding:var(--space-7) var(--space-4)}
  .zgpusto img{width:min(300px,70%);height:auto;margin-bottom:var(--space-4)}
  .zgpusto :is(h2,h3){font-family:var(--font-display);font-weight:500;font-size:19px;color:var(--text);margin:0}
  .zgpusto p{font-size:14.5px;color:var(--body-fg);margin:var(--space-2) auto 0;max-width:46ch}

  /* ── Konto: logowanie, prośba o dostęp, reset hasła ──────────────────────
     Układ z makiety Claude Design: dwie karty obok siebie na jasnym tle -
     biała z formularzem, ciemna z ofertą planu. Wcześniej stały tu dwie płyty
     na całą szerokość ekranu (tak wyglądała aplikacja React) i ciemna połowa
     wyglądała jak pusta plama. Poniżej 900 px karty idą jedna pod drugą,
     formularzem do góry - na telefonie ludzie przychodzą się zalogować,
     a nie czytać ofertę. */
  .authwrap{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.82fr);
      gap:clamp(24px,3vw,48px);align-items:stretch;
      max-width:1180px;margin:0 auto;width:100%;
      padding:clamp(36px,6vh,80px) var(--space-6) clamp(48px,7vh,88px)}
  .authmain{display:flex;flex-direction:column;align-items:center;gap:var(--space-4)}
  .authcard{width:100%;max-width:none;background:var(--cx-white);border:1px solid var(--line2);
      border-radius:var(--radius-lg);padding:clamp(28px,3.5vw,44px);
      box-shadow:0 1px 2px rgba(18,32,33,.04),0 18px 40px -28px rgba(18,32,33,.35)}
  /* Ciemna karta: ten sam promień i to samo powietrze co biała, plus poświata
     w rogu - ta sama, którą mają sekcje na ciemnym tle na stronie głównej. */
  .authside{position:relative;overflow:hidden;background:var(--cx-ink);color:var(--on-dark);
      border-radius:var(--radius-lg);padding:clamp(28px,3.5vw,44px);
      display:flex;flex-direction:column;justify-content:center;gap:var(--space-3)}
  .authside::before{content:"";position:absolute;inset:auto -20% -30% -20%;height:70%;
      background:var(--hero-glow);pointer-events:none}
  .authside>*{position:relative}
  .authside h2{font-family:var(--font-display);font-weight:500;font-size:clamp(23px,2.6vw,31px);
      line-height:1.15;color:var(--cx-white);margin:var(--space-2) 0 0}
  .authside .pkgline{font-size:13.5px;color:var(--cx-lime);margin:var(--space-2) 0 0}
  .authside .authlead{font-size:14.5px;line-height:1.6;color:var(--cx-lime-soft);
      margin:var(--space-3) 0 0;max-width:46ch}
  .authpts{list-style:none;display:flex;flex-direction:column;gap:var(--space-3);
      margin:var(--space-4) 0 0;font-size:14px;line-height:1.5;color:var(--cx-lime-soft)}
  .authpts li{display:flex;gap:var(--space-3);align-items:flex-start}
  .authpts b{color:var(--cx-white);font-weight:500}
  .authpts .pkgbul{flex:none;margin-top:3px}
  /* Guzik „Porównaj plany" w płycie oferty (prośba Radka 29.09). Płyta
     opowiada o subskrypcji, a nie prowadziła nigdzie - czytelnik dostawał
     argumenty i żadnego następnego kroku. `align-self` trzyma guzik przy
     szerokości treści: płyta jest kolumną flex, więc bez tego rozciągnąłby
     się na całą jej szerokość i wyglądał jak pasek. */
  .authside .pkgbtn{align-self:flex-start;margin-top:var(--space-4)}
  /* Nota pod listą - jak w makiecie: baza wiedzy stoi otworem bez logowania. */
  .authnote{margin-top:var(--space-5);padding-top:var(--space-4);
      border-top:1px solid var(--cx-ink-60);font-size:13px;line-height:1.6;
      color:var(--cx-ink-20)}
  .authnote a{color:var(--cx-lime)}
  .authcard :is(h1,.acch){font-family:var(--font-display);font-weight:500;font-size:26px;
      line-height:1.15;color:var(--text);margin:0}
  .authcard .authsub{font-size:14.5px;line-height:1.55;color:var(--body-fg);margin:var(--space-2) 0 0}
  .authform{display:flex;flex-direction:column;gap:var(--space-4);margin-top:var(--space-5)}
  .authcard--center{text-align:center}
  .authcard--center .authsub{max-width:42ch;margin-left:auto;margin-right:auto}
  .authlegal{font-size:12.5px;color:var(--soft);text-align:center;max-width:420px}

  /* ── Urządzenia (Z039) ────────────────────────────────────────────────────
     Lista sesji konta na ekranie profilu. Wiersz to jedna linia nazwy
     (przeglądarka + system) i druga, cichsza, z adresem i datą. Bieżące
     urządzenie wyróżnia lewa krawędź w kolorze marki - nie kolor tła, bo ten
     sam wiersz ma być czytelny i w jasnym, i w ciemnym motywie. */
  .urzlista{margin-top:var(--space-4)}
  .urzlist{list-style:none;display:flex;flex-direction:column;gap:var(--space-3)}
  /* 9.10: po lewej znaki systemu i przeglądarki, pośrodku opis z miejscem,
     po prawej guzik „Wyloguj" (tylko przy cudzych urządzeniach). Na wąskim
     ekranie guzik schodzi pod opis, a znaki zostają w swojej kolumnie. */
  .urzrow{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-3) var(--space-4);
      border:1px solid var(--line);border-radius:var(--radius-md);background:var(--surface)}
  .urzrow--ja{border-color:var(--cx-turquoise-600);
      box-shadow:inset 3px 0 0 var(--cx-turquoise-600)}
  .urzikony{display:flex;gap:6px;flex:none;color:var(--text)}
  .urzik{display:grid;place-items:center;width:30px;height:30px;border-radius:8px;
      background:var(--cx-cloud);color:var(--cx-ink)}
  .urzik svg{width:17px;height:17px}
  .urzopis{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}
  .urznaz{font-size:14px;font-weight:600;color:var(--text)}
  .urzja{display:inline-flex;align-items:center;gap:3px;margin-left:4px;
      font-weight:600;color:var(--cx-turquoise-600)}
  .urzja svg{width:15px;height:15px}
  .urzmeta{font-size:12.5px;color:var(--muted);overflow-wrap:anywhere}
  .urzwyl{flex:none;padding:6px 14px!important;min-height:0!important;font-size:13px!important}
  .urzzrodlo{margin-top:var(--space-3);font-size:11.5px;color:var(--muted)}
  .urzzrodlo a{color:inherit;text-decoration:underline}
  @media(max-width:560px){
    .urzrow{flex-wrap:wrap}
    .urzwyl{margin-left:calc(66px + var(--space-3))}
  }

  /* ── Oczekiwanie po logowaniu Google (paczka 17.09) ───────────────────────
     Nakładka na czas między zgodą w Google a wejściem do portalu. Kroki nazywają
     to, co się dzieje - sam kręcący się znak nie mówi, czy proces stoi, czy trwa.
     Znak marki bierzemy z tego samego preloadera co reszta portalu. */
  .authwait{position:fixed;inset:0;z-index:120;display:grid;place-items:center;
      padding:var(--space-5);background:rgba(18,32,33,.94);backdrop-filter:blur(6px);
      animation:waitIn .18s ease-out}
  @keyframes waitIn{from{opacity:0}to{opacity:1}}
  .authwaitbox{width:min(420px,100%);display:flex;flex-direction:column;
      align-items:center;text-align:center}
  .authwaitbox .cxpre{width:96px;height:96px;margin-bottom:var(--space-4)}
  .authwaitbox h2{font-family:var(--font-display);font-weight:400;
      font-size:clamp(20px,2.4vw,26px);letter-spacing:-.01em;color:var(--cx-white)}
  .authwaitbox p{margin-top:8px;font-size:14px;line-height:1.55;color:var(--cx-lime-soft)}
  .waitsteps{list-style:none;display:flex;flex-direction:column;gap:10px;
      margin-top:clamp(22px,3.4vh,32px);width:100%;text-align:left}
  .waitsteps li{display:flex;align-items:center;gap:11px;padding:10px 14px;
      border-radius:var(--radius-sm);font-size:13.5px;
      /* pełny kolor, nie krycie: tekst 13,5 px z alfą .45 dawał 3,7:1 */
      color:rgb(143,159,157);background:rgba(255,255,255,.03)}
  /* Tekst kroku siedzi w <b> tylko po to, żeby dało się go podmienić po
     odpowiedzi backendu - grubość zostaje taka jak reszty listy. */
  .wsteptx{font-weight:inherit}
  .wstepic{display:grid;place-items:center;flex:none;width:20px;height:20px;
      border-radius:50%;border:1px solid rgba(219,236,233,.3);color:var(--cx-ink)}
  .wstepic svg{width:11px;height:11px;opacity:0}
  .waitsteps .is-done{color:var(--cx-lime-soft)}
  .waitsteps .is-done .wstepic{background:var(--cx-lime);border-color:var(--cx-lime);
      color:var(--cx-ink)}
  .waitsteps .is-done .wstepic svg{opacity:1}
  /* bieżący krok: pierścień, który się obraca - stan widać też bez koloru */
  .waitsteps .is-now{color:var(--cx-white);background:rgba(173,247,99,.08)}
  .waitsteps .is-now .wstepic{border-color:var(--cx-lime);border-top-color:transparent;
      border-width:2px}
  /* Obrót deklarujemy TYLKO dla widocznej nakładki. Zapisany globalnie na
     `.wstepic` wisiał w arkuszu także przy `hidden` i blokował eksport PNG
     całego ekranu logowania - narzędzie klonuje DOM razem z regułą, nie
     patrząc na `display:none` przodka. */
  .authwait:not([hidden]) .waitsteps .is-now .wstepic{
      animation:waitSpin .8s linear infinite}
  @keyframes waitSpin{to{transform:rotate(360deg)}}
  @media(prefers-reduced-motion:reduce){
    .authwait{animation:none}
    .authwait:not([hidden]) .waitsteps .is-now .wstepic{animation:none}
    .waitsteps .is-now .wstepic{border-top-color:var(--cx-lime)}
  }
  .authlegal a{color:var(--cx-turquoise-600)}

  /* pola formularza */
  .fld{display:flex;flex-direction:column;gap:6px}
  /* `.fldlab` to etykieta grupy (np. Priorytet), która nie moze byc <label>,
     bo wskazywalaby na pierwszy przycisk radiowy zamiast na cala grupe. */
  .fld :is(label,.fldlab){font-size:13px;font-weight:500;color:var(--text)}
  .fldrow{display:flex;justify-content:space-between;align-items:baseline;gap:var(--space-3)}
  .fld input{width:100%;font:inherit;font-size:15px;padding:11px 13px;color:var(--text);
      background:var(--cx-white);border:1px solid var(--line);border-radius:var(--radius-sm);
      transition:border-color .15s,box-shadow .15s}
  .fld input:focus{outline:none;border-color:var(--cx-turquoise-600);
      box-shadow:0 0 0 3px rgba(74,158,150,.16)}
  .fld input[aria-invalid="true"]{border-color:var(--cx-error)}
  /* Pola w modalu zgłoszenia: ta sama forma co reszta formularzy, tylko że
     `select` trzeba ubrać samemu - systemowy wygląda obco na tle reszty. */
  .fld textarea,.fld select{width:100%;font:inherit;font-size:15px;line-height:1.6;
      padding:11px 13px;color:var(--text);background:var(--cx-white);
      border:1px solid var(--line);border-radius:var(--radius-sm);
      transition:border-color .15s,box-shadow .15s}
  .fld textarea{resize:vertical;min-height:130px}
  .fld textarea:focus,.fld select:focus{outline:none;border-color:var(--cx-turquoise-600);
      box-shadow:0 0 0 3px rgba(74,158,150,.16)}
  .fld select{appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:38px;
      background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23498381' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
      background-repeat:no-repeat;background-position:right 13px center}
  /* Logowanie kontem Google: rozdzielacz i gniazdo na przycisk, który
     rysuje sam Google (ich znak, ich zasady). */
  .authgoogle{display:flex;flex-direction:column;gap:var(--space-3)}
  .authlub{display:flex;align-items:center;gap:var(--space-3);color:var(--soft);
      font-size:12.5px}
  .authlub[hidden]{display:none}
  .authlub::before,.authlub::after{content:"";flex:1;height:1px;background:var(--line)}
  .gbtn{display:flex;justify-content:center;min-height:44px}
  .fldwrap{position:relative;display:flex}
  /* przycisk podglądu hasła siedzi w polu, więc pole musi mieć miejsce po prawej */
  .fldwrap .fldeye{position:absolute;right:6px;top:50%;transform:translateY(-50%);
      background:none;border:0;padding:6px;cursor:pointer;color:var(--soft);line-height:0;border-radius:6px}
  .fldwrap .fldeye:hover{color:var(--text);background:var(--cx-cloud)}
  .fldwrap input{padding-right:42px}
  .flderr{font-size:12.5px;color:var(--cx-error)}
  .fldhint{font-size:12.5px;color:var(--soft)}
  /* Podpowiedź w miejscu błędu („jeszcze 3 cyfry") - jeszcze nie błąd. */
  .flderr.flderr--info{color:var(--soft)}
  /* Pole telefonu (#218): pigułka z flagą i kierunkowym, za nią same cyfry.
     `select` leży NA pigułce, przezroczysty - lista krajów jest systemowa,
     a w zamkniętym stanie widać tylko flagę i kierunkowy. */
  .tel{display:flex;gap:8px;align-items:stretch}
  .tel input{flex:1;min-width:0}
  .telkraj{position:relative;flex:none;display:inline-flex;align-items:center;
      padding:0 30px 0 12px;font-size:15px;color:var(--text);white-space:nowrap;
      background:var(--cx-white);border:1px solid var(--line);border-radius:var(--radius-sm);
      background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23498381' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
      background-repeat:no-repeat;background-position:right 11px center;
      transition:border-color .15s,box-shadow .15s}
  .telkraj:focus-within{border-color:var(--cx-turquoise-600);box-shadow:0 0 0 3px rgba(74,158,150,.16)}
  .fld .telkraj select,.telkraj select{position:absolute;inset:0;width:100%;height:100%;
      opacity:0;cursor:pointer;font-size:16px;padding:0;border:0;margin:0}
  /* Ta sama para w wierszu profilu: bez ramek, bo ramką jest cały wiersz. */
  .tel--ed{flex:1;min-width:0;align-items:center}
  .tel--ed .telkraj{padding:0 22px 0 0;border:0;border-right:1px solid var(--line);
      border-radius:0;background-color:transparent;background-position:right 6px center;
      font-size:14.5px;align-self:stretch}
  .tel--ed .telkraj:focus-within{box-shadow:none}
  .telstan{flex:none;font-size:12px;color:var(--soft);white-space:nowrap}
  .telstan--blad{color:var(--cx-error);white-space:normal;flex:0 1 auto;max-width:55%}
  /* Referencja artykułu nad formularzem zgłoszenia. Wygląda jak notka, nie jak
     pole do wypełnienia - bo nie jest pytaniem do człowieka, tylko informacją,
     co poleci razem z opisem. Krzyżyk stoi po prawej i zdejmuje ją w całości. */
  .znref{display:flex;align-items:center;gap:var(--space-3);padding:12px var(--space-4);
      border:1px solid var(--line);border-left:3px solid var(--cx-lime);
      border-radius:var(--radius-md);background:var(--surface-alt)}
  .znreflab{flex:0 0 auto;font-size:11.5px;font-weight:700;text-transform:uppercase;
      letter-spacing:.05em;color:var(--soft)}
  .znreftyt{flex:1 1 auto;min-width:0;font-size:13.5px;line-height:1.4;color:var(--text);
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .znreftyt a{color:var(--text);text-decoration:underline;text-underline-offset:2px}
  .znreftyt a:hover{color:var(--accent)}
  .znrefx{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
      width:26px;height:26px;padding:0;border:0;border-radius:50%;background:transparent;
      color:var(--soft);cursor:pointer;transition:background .15s,color .15s}
  .znrefx:hover{background:var(--line);color:var(--text)}
  .znrefx svg{width:14px;height:14px}
  @media(max-width:600px){
    /* Na telefonie etykieta i tytuł nie mieszczą się w jednym rzędzie:
       etykieta idzie nad tytuł, krzyżyk zostaje po prawej. */
    .znref{flex-wrap:wrap}
    .znreflab{flex:1 0 100%}
    .znreftyt{white-space:normal}
  }
  .authalert{background:rgba(180,35,24,.08);border:1px solid rgba(180,35,24,.3);
      color:var(--cx-error);border-radius:var(--radius-sm);padding:11px 13px;font-size:13.5px;
      line-height:1.5;margin-top:var(--space-4)}
  /* Ten sam pasek w wariancie „udało się". ZIELEŃ JEST KLASĄ, NIE STYLEM
     WPISANYM Z PALCA (zgłoszenie Radka 1.10: „nie uważasz, że taki błąd
     powinien wyświetlać się na czerwono?"). Do tej pory sukces malował pasek
     `style.cssText`, a `authAlert()` - który pokazuje BŁĄD - tego stylu nie
     zdejmował. Styl wpisany w element bije każdą regułę z arkusza, więc po
     jednym udanym zapisie KAŻDY następny błąd na tym ekranie był zielony.
     Morał szerszy: **stan, który jeden kod nakłada, a drugi ma zdjąć, nie może
     mieszkać w `style`** - tam nie widać go z arkusza i nikt nie pamięta
     o sprzątaniu. Klasa daje jedno miejsce na oba warianty i jedno na wyjęcie. */
  .authalert--ok{background:rgba(30,158,82,.08);border-color:rgba(30,158,82,.3);
      color:var(--cx-green-500)}
  /* Wariant „uwaga" - ostrzeżenie, które NIE jest błędem (adres z prywatnej
     skrzynki przy rejestracji). Czerwień mówiłaby „tak nie wolno", a wolno. */
  .authalert--uwaga{background:rgba(236,191,14,.12);border-color:rgba(176,138,0,.4);
      color:var(--text)}
  .authchk{display:flex;align-items:flex-start;gap:9px;font-size:14px;line-height:1.45;cursor:pointer}
  .authchk input{margin:2px 0 0;accent-color:var(--cx-turquoise-600);flex:none;width:16px;height:16px}
  .authlink{background:none;border:0;padding:0;font:inherit;font-size:13.5px;color:var(--cx-turquoise-600);
      cursor:pointer;text-decoration:underline;text-underline-offset:2px}
  .authlink:hover{color:var(--cx-ink)}
  .authalt{font-size:14px;color:var(--body-fg);margin:var(--space-4) 0 0;text-align:center}
  /* Podpowiedź pod polem - tłumaczy, czym jest slug, zanim ktoś zapyta. */
  .authhint{margin:calc(var(--space-3) * -1) 0 0;font-size:12.5px;line-height:1.55;
      color:var(--muted)}
  .authhint code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;
      background:var(--cx-mist);border-radius:var(--radius-xs);padding:1px 5px}
  .authhint code b{color:var(--text);font-weight:600}
  .authback{display:inline-flex;align-items:center;gap:7px;background:none;border:0;padding:0;
      font:inherit;font-size:13.5px;color:var(--soft);cursor:pointer;margin-bottom:var(--space-4)}
  .authback:hover{color:var(--text)}
  .authbtn{width:100%;justify-content:center}
  .authbtn[disabled]{opacity:.6;cursor:progress}
  .authbadge{width:56px;height:56px;border-radius:50%;background:var(--cx-mist);
      display:grid;place-items:center;margin:0 auto var(--space-4);color:var(--cx-turquoise-600)}
  /* siła hasła - trzy kreski, bo cztery nikt nie czyta */
  .authsila{display:flex;gap:5px;margin-top:8px}
  .authsila i{height:4px;flex:1;border-radius:2px;background:var(--cx-cloud);transition:background .2s}
  .authsila--1 i:nth-child(1){background:var(--cx-error)}
  .authsila--2 i:nth-child(-n+2){background:#d59b0e}
  .authsila--3 i{background:var(--cx-green-500)}
  .authsilatx{font-size:12px;color:var(--soft);margin-top:5px}
  @media(max-width:900px){
    .authwrap{grid-template-columns:minmax(0,1fr);padding-left:var(--space-5);
        padding-right:var(--space-5)}
    /* formularz przed ofertą: na telefonie ludzie przychodzą tu się zalogować */
    .authmain{order:1}
    .authside{order:2}
  }

  /* Zakończone: wiersze, nie karty - to archiwum, ma być gęste */
  .outpast{list-style:none;display:flex;flex-direction:column}
  .outpast li{display:grid;grid-template-columns:22px 96px minmax(0,1fr) auto; align-items:center;gap:var(--space-4);padding:var(--space-4) 0; border-bottom:1px solid var(--line)}
  /* Znaczek usługi: od razu widać, czy wpis dotyczy monday.com czy make.com,
     bez czytania karty. Wielkość jak favicon - to znak, nie ilustracja. */
  .outpastznak{display:flex;align-items:center;justify-content:center}
  .outznak{display:block;width:16px;height:16px;object-fit:contain;flex:none;border-radius:3px}
  .outznak--lista{width:18px;height:18px}
  .outmeta b .outznak{margin-right:7px}
  .outmeta b{display:inline-flex;align-items:center}
  .outpastdate{font-size:13px;color:var(--soft)}
  .outpasttx{display:flex;flex-direction:column;gap:3px;font-size:13.5px; line-height:1.5;color:var(--body-fg)}
  .outpasttx b{font-size:15px;font-weight:500;color:var(--text)}
  .outpastczas{font-size:12.5px;color:var(--soft)}
  /* Wariant awarii - karta bez kolumny daty (incydent trwa, nie ma jednej daty do pokazania). Musi stać PO .outcard: ta sama specyficzność. */
  .outcard--alert{grid-template-columns:minmax(0,1fr); border-color:rgba(180,35,24,.35)}
  .outstate--alert{background:var(--cx-error);color:var(--cx-white)}
  .kbside--out{display:flex;flex-direction:column;gap:var(--space-3); padding:var(--space-5);background:var(--cx-white); border:1px solid var(--line);border-radius:var(--radius-lg)}
  .kbside--out .sideh:not(:first-child){margin-top:var(--space-4)}
  /* slot na grafikę w kolumnie bocznej - proporcja 4:3, żeby zrzut maila był czytelny, ale nie zjadał całej kolumny */
  .outnote{list-style:none;display:flex;flex-direction:column;gap:var(--space-3)}
  .outnote li{font-size:13.5px;line-height:1.5;color:var(--body-fg)}
  .outnote b{color:var(--text)}
  .outsidetx{font-size:13.5px;line-height:1.55;color:var(--body-fg)}
  /* kolumna ma stałe 236px - bez nowrap etykieta CTA łamała się na dwa wiersze i dotykała krawędzi płytki szewronu */
  .kbside--out .btn{margin-top:var(--space-4);justify-content:center;white-space:nowrap}
  @media(max-width:700px){
    .outcard{grid-template-columns:minmax(0,1fr)}
    .outwhen{flex-direction:row;gap:var(--space-2);padding:var(--space-3)}
    .outday{font-size:22px}
    .outpast li{grid-template-columns:22px minmax(0,1fr) auto;
        column-gap:var(--space-3);row-gap:8px;align-items:center}
    .outpastznak{grid-area:1/1/2/2}
    .outpastdate{grid-area:1/2/2/3}
    .outpast .outstate{grid-area:1/3/2/4;justify-self:end}
    .outpasttx{grid-area:2/1/3/-1}
  }

  /* ══ Ekran ładowania ═════════════════════════════════════════════════════
     Na środku dostępnej wysokości (viewport minus pasek i nagłówek), nie
     50px od góry. Animacja Lottie „contour chaser" chodzi w pętli do czasu,
     aż indeks się wczyta. */
  .spin{display:flex;flex-direction:column;align-items:center;justify-content:center;
      gap:var(--space-4);min-height:calc(100svh - var(--chrome,0px) - 80px);
      padding:var(--space-6);text-align:center;color:var(--muted)}
  /* Kanwa preloadera: 96×96 px, kwadratowa, BEZ własnego tła - animacja
     siedzi wprost na tle strony (decyzja Radka 15.09; wcześniej stała na
     ciemnej płycie --cx-ink, bo pod takie tło przygotowano plik).
     Powietrze wokół znaku jest wbudowane w kadr, nie przycinamy go do
     logotypu. Poniżej 48 px kontur zlewa się w plamę, więc nie zmniejszamy.
     Odtwarzacz stoi w <head>, więc animacja rusza od pierwszej klatki i nie
     ma czego podmieniać w trakcie. */
  /* Pasek trybu demo - ma być widać, że dane są przesunięte w czasie. */
  #demobar{position:fixed;left:0;right:0;bottom:0;z-index:90;
      padding:9px var(--space-5);background:var(--cx-gray-1);color:var(--cx-white);
      font-size:13px;line-height:1.45;text-align:center;
      padding-bottom:calc(9px + env(safe-area-inset-bottom, 0px))}
  #demobar b{font-weight:700;color:var(--cx-lime)}
  #demobar a{color:var(--cx-lime);text-decoration:underline;margin-left:6px}

  /* 96 px - rozmiar wariantu jasnego zatwierdzony w paczce 16.09. */
  .cxpre{width:96px;height:96px;display:grid;place-items:center}
  .cxpre svg{display:block;width:100%;height:100%}
  /* Zapas na wypadek, gdyby odtwarzacz nie wstał: zostaje sam znak marki. */
  .cxpre>.cx-mark{width:64px;height:64px;color:var(--cx-ink);
      animation:spinPulse 1.6s ease-in-out infinite;border-radius:16px}
  .spintx{font-size:14.5px;letter-spacing:.01em}
  /* Paska postępu nie ma (decyzja z paczki 16.09): animacja sama niesie
     informację „trwa", a pasek był drugim takim sygnałem obok niej. */
  @keyframes spinPulse{
    0%,100%{transform:scale(1);box-shadow:0 0 0 0 rgba(173,247,99,.30)}
    50%{transform:scale(1.06);box-shadow:0 0 0 14px rgba(173,247,99,0)}
  }
  @media(prefers-reduced-motion:reduce){
    .cxpre>.cx-mark{animation:none}
  }

  /* ══ Nieistniejący artykuł ═══════════════════════════════════════════════
     Jedna kolumna, wyśrodkowana: nagłówek, wyjaśnienie, grafika 404 od CXLABS,
     a pod nią dwa wyjścia z zaułka - powrót do bazy i droga do konsultanta.
     Całość na środku dostępnej wysokości. */
  .err404{display:flex;flex-direction:column;align-items:center;justify-content:center;
      text-align:center;gap:var(--space-4);
      min-height:calc(100svh - var(--chrome,0px) - 220px);
      padding:clamp(32px,5vh,64px) 0}
  .err404 h3{font-family:var(--font-display);font-weight:500;
      font-size:clamp(24px,3vw,34px);line-height:1.15;letter-spacing:-.01em;color:var(--text)}
  .err404 p{margin:0;max-width:52ch;font-size:15px;line-height:1.6;color:var(--muted)}
  .err404img{display:block;width:auto;height:auto;
      max-width:min(600px,100%);max-height:46vh;
      flex:0 1 auto;min-height:0;object-fit:contain;margin:var(--space-3) 0}
  .err404go{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--space-3)}
  .err404go .btn--ghost{border-color:var(--line2);color:var(--text)!important;
      padding:12px var(--space-5)}
  .err404go .btn--ghost:hover{background:var(--cx-mist);color:var(--cx-ink)!important}
  @media(max-width:760px){.err404img{max-width:min(320px,78vw)}}
  /* niskie okno: grafika jest ozdobą, przyciski nie - ona ustępuje pierwsza */
  @media(max-height:620px){.err404img{max-height:34vh;margin:4px 0}}
  @media(max-height:480px){.err404img{display:none}}

  /* ══ Kafle produktów: 4×2, wszystkie równe ═══════════════════════════════
     Karta wiodąca przestaje zajmować cały rząd - osiem produktów układa się
     w dwa rzędy po cztery. Wyróżnia ją opis i lime płytka znaku, nie rozmiar.
     Blok stoi na końcu arkusza świadomie: nadpisuje wcześniejsze warianty
     (rząd poziomy, auto-fill), które powstały przy poprzednim układzie. */
  /* Wejścia sekcji rysują kafle w perspektywie 3D - w trakcie animacji ich
     pudełko wystaje poza kolumnę i strona dostawała suwak poziomy. `clip`,
     nie `hidden`: nie robi z body kontenera przewijania, więc przyklejony
     nagłówek i zaczepy przewijania działają dalej. */
  html,body{overflow-x:clip}
  /* Kilka pikseli nad siatką: kafel na hoverze podnosi się o 4 px i rzuca
     cień - bez tego luzu górna krawędź wchodziła pod nagłówek sekcji. */
  .apps{grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(10px,1.4vh,16px);
      padding-top:6px}
  .app--lead{grid-column:auto;padding:clamp(10px,1.4vh,14px) var(--space-4)}
  .app--lead .appmain{flex-direction:column;align-items:flex-start;gap:clamp(9px,1.4vh,14px)}
  .app--lead .ic{width:40px;height:40px;border-radius:10px}
  .app--lead .ic svg{width:21px;height:21px}
  .app--lead .tx{flex:1 1 auto;gap:4px}
  .app--lead b{font-size:16px;line-height:1.2}
  /* dwie linie jak w pozostałych kaflach - trzecia robiła rząd wyższym o 25 px */
  .app--lead .tx>span.lead-desc{font-size:12.5px;line-height:1.45;max-width:none;
      display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .app--lead .go{display:none}
  @media(max-width:700px){.apps{grid-template-columns:repeat(2,minmax(0,1fr))}}
  @media(max-width:520px){.apps{grid-template-columns:minmax(0,1fr)}}

  /* ══ Sekcja produktów: rośnie z treścią ══════════════════════════════════
     Zdejmujemy ograniczenie do wysokości ekranu - przy ośmiu kaflach i ośmiu
     tematach wszystko było ściśnięte do granicy czytelności. Sekcja nadal
     jest zaczepem przewijania (start), tylko nie udaje slajdu na siłę.
     Odstępy wracają do rytmu design systemu (8 px), bez ściskania przez vh. */
  #view>.band--first{min-height:0;padding:clamp(72px,9vh,112px) 0}
  .band--first .hubhead{margin-bottom:var(--space-6)}
  .band--first .apps{gap:var(--space-4)}
  .band--first .app{padding:var(--space-5)}
  .band--first .app--lead{padding:var(--space-5)}
  .band--first .appmain,.band--first .app--lead .appmain{gap:var(--space-4)}
  .band--first .app .ic,.band--first .app--lead .ic{width:46px;height:46px}
  .band--first .app .ic svg,.band--first .app--lead .ic svg{width:23px;height:23px}
  .band--first .app b,.band--first .app--lead b{font-size:17px}
  .band--first .app .tx>span.app-desc,
  .band--first .app--lead .tx>span.lead-desc{font-size:13px;line-height:1.5;
      -webkit-line-clamp:2}
  .band--first .hubsec--split{margin-top:clamp(48px,6vh,80px);
      padding-top:clamp(40px,5vh,64px)}
  .band--first .topics .topic{padding:var(--space-4) 0}
  .band--first .topic b{font-size:15.5px}

  /* ══ Najczęściej czytane: sześć pozycji, luźniej ═════════════════════════
     Przy dziesięciu wierszach lista musiała być ściśnięta, żeby zmieścić się
     w ekranie. Sześć pozycji daje miejsce na rytm 8 px i oddech między nimi. */
  .band--light .reads{gap:var(--space-2)}
  .band--light .read{padding:var(--space-4) var(--space-4)}
  .band--light .readtx{gap:5px}
  .band--light .readlede{font-size:13px;line-height:1.55}
  .band--light .hubhead{margin-bottom:var(--space-6)}

  /* Lista korzyści zamiast pól - wypełnia kartę treścią, nie powietrzem */
  .loginpts{list-style:none;margin:var(--space-5) 0 0;padding:0;
      display:flex;flex-direction:column;gap:var(--space-3)}
  .loginpts li{display:flex;align-items:flex-start;gap:var(--space-3);
      font-size:14px;line-height:1.5;color:var(--cx-lime-soft)}
  .loginpt-ic{display:grid;place-items:center;width:20px;height:20px;flex:none;
      margin-top:1px;border-radius:6px;background:rgba(173,247,99,.16);color:var(--cx-lime)}
  .loginpt-ic svg{width:12px;height:12px}
  .loginbtn{margin-top:var(--space-5)}

  /* Karta logowania sięga pełnej wysokości kolumny i rozkłada treść:
     nagłówek u góry, lista korzyści w środku (rozpycha się), przycisk
     i nota u dołu - wcześniej kończyła się wyżej niż lista wsparcia obok. */
  .helpwrap{align-items:stretch}
  .loginbox{display:flex;flex-direction:column;height:100%}
  .loginpts{flex:1 1 auto;justify-content:center}
  .loginnote{margin-top:auto}

  .loginpts{gap:var(--space-5)}

  /* Przycisk logowania: do prawej krawędzi karty i tylko na swoją szerokość
     (domyślnie rozciągał się na całą kolumnę flexa). */
  .loginbtn{align-self:flex-end;width:auto;flex:none}

  /* ══ Sekcja „Plan wsparcia" na stronie głównej ════════════════════════
     Ta sama treść co na stronie logowania panelu - portal i panel mają mówić
     jedno. Układ: podtytuł w lime, akapit, lista z szewronami marki jako
     punktorami, na dole zakup oddzielony kreską. */
  .pkgline{margin-top:var(--space-3);font-size:15px;color:var(--cx-lime)}
  .helpwrap .helplead{margin-top:var(--space-4)}
  .pkghead{margin-top:var(--space-6);font-size:11.5px;font-weight:600;
      letter-spacing:.12em;text-transform:uppercase;color:var(--cx-ink-20)}
  .pkglist{list-style:none;margin:var(--space-4) 0 0;padding:0;
      display:flex;flex-direction:column;gap:var(--space-4)}
  .pkglist li{display:flex;align-items:flex-start;gap:var(--space-4);
      font-size:15px;line-height:1.55;color:var(--cx-lime-soft)}
  .pkglist li b{font-weight:600;color:var(--cx-white)}
  .pkgbul{display:flex;align-items:center;flex:none;margin-top:4px;color:var(--cx-lime)}
  .pkgbul .cx-mark{display:inline-flex;gap:2px}
  .pkgbuy{margin-top:var(--space-6);padding-top:var(--space-5);
      border-top:1px solid var(--cx-ink-60);display:flex;flex-direction:column;
      align-items:center;gap:var(--space-4);text-align:center}
  .pkgask{font-size:14.5px;color:var(--cx-lime-soft)}
  .pkgbtn{height:52px;font-size:15.5px}
  .pkgbtn .chev{width:40px;height:40px;border-radius:10px}
  .pkgbtn .chev svg{width:19px;height:19px}
  .pkgpay{font-size:12.5px;color:var(--cx-ink-20)}

  /* ── Sekcja planu: typografia i znaki jak na stronie logowania ───────
     Tam nagłówek jest w Clash Display Light, etykieta kapitalikami w lime,
     a punktory to podwójny szewron w prawo (»). Portal miał nagłówek 400,
     etykietę zdaniową i parę lustrzaną - stąd wrażenie innego kroju. */
  .helpwrap .eyebrow{font-size:13px;font-weight:600;letter-spacing:.14em;
      text-transform:uppercase;color:var(--cx-lime)}
  .band--last .helpwrap>div:first-child h2{font-weight:300;
      font-size:clamp(30px,3.6vw,46px);line-height:1.12;color:var(--cx-white)}
  .pkgline{font-size:16px}
  .pkghead{letter-spacing:.14em;color:var(--soft)}
  .helpwrap .helplead{font-size:16px;line-height:1.6}
  .pkglist li{font-size:16px;line-height:1.6}
  .pkgbul{margin-top:5px}
  .pkgbul .cx-mark{gap:1px}
  .pkgbul .cx-chev-r{width:8px;height:14px}

  /* Karta logowania wraca do wysokości swojej treści: rozciąganie na 100%
     miało sens, gdy obie kolumny miały podobną treść; po wstawieniu planu
     lewa jest dwa razy dłuższa i w karcie zostawała pusta płachta. */
  .loginbox{height:auto;align-self:center;padding:clamp(32px,4vh,44px) clamp(32px,3.4vw,44px)}
  .loginpts{flex:0 0 auto;justify-content:flex-start;gap:var(--space-4)}
  .loginnote{margin-top:var(--space-5)}

  /* Karta wyśrodkowana względem treści NAD separatorem: blok zakupu jest
     osobną komórką w drugim rzędzie siatki, więc pierwszy rząd kończy się
     dokładnie na kresce. */
  .helpwrap{grid-template-rows:auto auto}
  .helpwrap>div:first-child{grid-column:1;grid-row:1}
  .helpwrap .loginbox{grid-column:2;grid-row:1;align-self:center}
  .helpwrap .pkgbuy{grid-column:1;grid-row:2}
  @media(max-width:900px){
    .helpwrap{grid-template-rows:none}
    .helpwrap>div:first-child,.helpwrap .loginbox,.helpwrap .pkgbuy{grid-column:1;grid-row:auto}
  }

  /* Blok zakupu trzyma szerokość lewej kolumny, a treść wyrównuje do prawej. */
  .pkgbuy{align-items:flex-end;text-align:right}

  /* ══ Menu rozwijane: zwijanie po wyborze ═════════════════════════════════
     Menu stoi na czystym CSS (:hover/:focus-within). Po kliknięciu pozycji
     kursor i ognisko zostają w panelu, więc wisiał on otwarty nad nową stroną.
     Klasa `is-shut` (nakłada ją skrypt) wygrywa z :hover i zwija panel w górę:
     lekkie uniesienie, ćwierć procenta skali i zanik - bez podskoku. */
  .navdropwrap,.acctwrap{transform:translateY(-8px) scale(.985);
      transform-origin:top center;
      transition:opacity .16s ease,transform .24s cubic-bezier(.16,.84,.3,1),
                 visibility .24s}
  .navdrop:hover .navdropwrap,.navdrop:focus-within .navdropwrap,
  .acct:hover .acctwrap,.acct:focus-within .acctwrap{transform:none}
  .navdrop.is-shut .navdropwrap,.acct.is-shut .acctwrap{opacity:0;visibility:hidden;
      transform:translateY(-8px) scale(.985);pointer-events:none}
  /* Klik w „Produkty" otwiera i zamyka menu - samo najechanie nie wystarcza
     na dotyku, gdzie :hover w ogóle nie istnieje. `is-open` trzyma panel
     otwarty bez kursora; `is-shut` nadal wygrywa (są rozłączne). */
  .navdrop.is-open .navdropwrap,.acct.is-open .acctwrap{opacity:1;visibility:visible;
      transform:none;pointer-events:auto}
  .navdrop.is-open .navdropbtn{color:var(--cx-white)}
  .navdrop.is-open .navdropbtn svg,.acct.is-open .acctbtn>svg{transform:rotate(180deg)}

  /* ══ Znak marki jako jeden SVG ═══════════════════════════════════════════
     Bierze kolor z otoczenia (`currentColor`), więc w „eyebrow" jest dokładnie
     w kolorze jego tekstu - o to prosił Radek. Dawne reguły malujące maski
     osobnym kolorem (`.eyebrow .cx-mark{color:…}`) nadpisujemy tutaj; zostają
     w arkuszu dla podwójnego szewronu w punktorach planu, który jest czym
     innym niż znak marki. */
  svg.cx-mark{width:1em;height:1em;flex:none;color:inherit;display:inline-block;
      vertical-align:-.12em}
  .eyebrow svg.cx-mark{width:13px;height:13px;color:inherit}
  .band--light .eyebrow svg.cx-mark,.eyebrow--on-dark svg.cx-mark{color:inherit}
  .hero .inner>svg.cx-mark{width:26px;height:26px}
  .appHead .ic--mark svg.cx-mark{width:22px;height:22px}

  /* ══ Modal ════════════════════════════════════════════════════════════════
     Jedno okno dla dwóch ekranów: opisu raportu na „Plany" i formularza
     nowego zgłoszenia. Markup modalu cennika przyjechał z paczki 16.09-2
     bez stylów - te reguły domykają jedno i drugie. */
  .mdl{position:fixed;inset:0;z-index:200;display:grid;place-items:center;
      padding:var(--space-5)}
  .mdl[hidden]{display:none}
  .mdlbg{position:absolute;inset:0;background:rgba(18,32,33,.62);backdrop-filter:blur(3px)}
  .mdlbox{position:relative;display:flex;flex-direction:column;
      width:min(680px,100%);max-height:min(88vh,860px);background:var(--cx-white);
      border-radius:var(--radius-lg);box-shadow:0 24px 64px rgba(0,0,0,.28);overflow:hidden}
  .mdlhead{display:flex;align-items:flex-start;justify-content:space-between;
      gap:var(--space-4);padding:var(--space-5) var(--space-5) var(--space-4);
      border-bottom:1px solid var(--line)}
  /* Opis obok guzika zamknięcia MUSI móc się skurczyć. Domyślne
     `min-width:auto` na elemencie giętkim nie pozwala zejść poniżej treści,
     więc długi adres artykułu rozpychał nagłówek i wypychał krzyżyk poza
     ekran - na telefonie nie dało się zamknąć podglądu. */
  .mdlhead>div{min-width:0}
  .mdlhead .mdleyebrow{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mdlhead h2{overflow-wrap:anywhere}
  .mdlx{flex:none}
  /* Podgląd załącznika: obrazek pokazuje treść, inny format - rozszerzenie.
     Płytka 40 px w promieniu ikon z design systemu (8 px). Selektor z rodzicem,
     bo samo `.fileth` (0,1,0) przegrywa z `.files li span` (0,2,1). */
  .files{list-style:none;display:flex;flex-direction:column;gap:6px;margin:0;padding:0}
  .files li{display:flex;align-items:center;gap:var(--space-3);padding:8px 10px;
      background:var(--cx-mist);border-radius:var(--radius-sm);font-size:13.5px;
      color:var(--text)}
  .files li .fileth{flex:none;display:grid;place-items:center;width:40px;height:40px;
      border-radius:8px;overflow:hidden;background:var(--cx-mist);
      border:1px solid var(--line2)}
  .files li .fileth img{width:100%;height:100%;object-fit:cover;display:block}
  .files li .fileth--doc{background:var(--cx-ink);border-color:var(--cx-ink)}
  .files li .fileth--doc::after{content:attr(data-ext);font-size:9.5px;font-weight:700;
      letter-spacing:.04em;color:var(--cx-lime)}
  .files li .filenm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .files li i{font-style:normal;font-size:12px;color:var(--muted)}

  .mdlhead h2,.mdlhead b{font-family:var(--font-display);font-weight:400;font-size:24px;
      letter-spacing:-.01em;color:var(--text);display:block;margin-top:6px}
  .mdleyebrow{display:block;font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;
      color:var(--cx-turquoise-600)}
  .mdlx{flex:none;display:grid;place-items:center;width:36px;height:36px;background:none;
      border:1px solid var(--line2);border-radius:var(--radius-sm);color:var(--body-fg);
      cursor:pointer;transition:background .14s ease}
  .mdlx:hover{background:var(--cx-mist);color:var(--text)}
  .mdlx svg{width:16px;height:16px}
  .mdlbody{display:flex;flex-direction:column;gap:var(--space-4);padding:var(--space-5);
      overflow-y:auto}
  .mdlfoot{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;
      gap:var(--space-3);padding:var(--space-4) var(--space-5);background:var(--cx-mist);
      border-top:1px solid var(--line)}
  .mdlsla,.mdlfine{font-size:12.5px;color:var(--muted)}
  .mdlsla b{color:var(--text)}
  .mdlbtns,.mdlacts{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap}
  .mdlfoot .btn{white-space:nowrap}
  .mdllead{margin:0 0 var(--space-5);font-size:14.5px;line-height:1.6;color:var(--body-fg)}
  /* Numer wysłanego zgłoszenia. Stoi osobno, a nie w zdaniu, bo to jedyna
     rzecz z tego ekranu, którą klient przepisuje albo zapamiętuje - po niej
     szuka sprawy w liście i po niej pyta w mailu. */
  .mdlnumer{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-3);
      margin:0;padding:var(--space-4);border:1px solid var(--line);
      border-radius:var(--radius-md);background:var(--surface-alt)}
  .mdlnumer span{font-size:12.5px;color:var(--muted)}
  .mdlnumer b{font-family:var(--font-display);font-weight:400;font-size:20px;
      letter-spacing:.01em;color:var(--text)}
  .mdlwhat{list-style:none;display:flex;flex-direction:column;gap:var(--space-4);
      border-top:1px solid var(--line)}
  .mdlwhat li{display:flex;flex-direction:column;gap:3px;padding:var(--space-4) 0;
      border-bottom:1px solid var(--line)}
  .mdlwhat li:last-child{border-bottom:0}
  .mdlwhat b{font-size:14.5px;font-weight:600;color:var(--text)}
  .mdlwhat span{font-size:13.5px;line-height:1.55;color:var(--muted)}
  .mdlnote{margin:var(--space-4) 0 0;font-size:13px;line-height:1.6;color:var(--muted)}
  /* ── Formularz zgłoszenia: dwie kolumny w szerszym oknie ─────────────────
     Polecenie Radka 1.10: „cały jego content powinien mieścić się w jednym
     oknie". W jednej kolumnie siedem pól miało ponad 1400 px, czyli na każdym
     laptopie coś zostawało pod krawędzią - a pole, którego nie widać, jest dla
     klienta polem, którego nie ma.
     Dwa selektory klas (`.mdlbox.mdlbox--zgl`), nie jeden: `.mdlbox` stoi
     NIŻEJ w tym arkuszu, więc przy równym ciężarze wygrywa ono - ta sama
     pułapka, co przy `.mdlbox--szeroki` w podglądzie tłumaczeń. */
  /* Sufit wysokości wyższy niż domyślne `min(88vh,860px)`: ten jeden formularz
     ma się zmieścić w CAŁOŚCI, a każde 30 px zabrane krawędzi ekranu to jedno
     pole mniej pod spodem. `svh` zamiast `vh`, bo na telefonie `vh` liczy się
     od okna BEZ paska przeglądarki i okno wystaje poza ekran. */
  .mdlbox.mdlbox--zgl{width:min(1060px,100%);max-height:min(92svh,920px)}
  /* Nagłówek o stopień niższy - te kilkanaście pikseli rozstrzygało na
     laptopie 1366x768 o tym, czy priorytet jest widoczny w całości. */
  .mdlbox--zgl .mdlhead{padding:var(--space-4) var(--space-5) var(--space-3)}
  /* Kafle produktów są w tym oknie CIAŚNIEJSZE niż gdzie indziej: trzy rzędy po
     58 px to 174 px na pytanie, które jest tylko wstępem do opisu sprawy. */
  .mdlbox--zgl .prodtile{padding:6px 10px;font-size:12.5px}
  .mdlbox--zgl .prodtile img{width:20px;height:20px}
  /* Licznik znaków staje W JEDNEJ LINII z podpowiedzią pod polem, zamiast
     zajmować własny wiersz - i tak dotyczy wyłącznie tego pola, a osobna linia
     kosztowała 18 px.
     Robi to SIATKA, a nie `position:absolute`, i to nie jest gust: `.fld` jest
     pojemnikiem giętkim, a element bezwzględny w takim pojemniku NIE dostaje
     swojego miejsca w szeregu, tylko lewy górny róg rodzica. Pierwsza wersja
     tej poprawki wylądowała przez to przy polu „Temat", dwa pola wyżej. */
  .mdlbox--zgl [data-fld="zn-tresc"]{display:grid;
      grid-template-columns:minmax(0,1fr) auto;align-items:end;
      column-gap:var(--space-3);row-gap:6px}
  .mdlbox--zgl [data-fld="zn-tresc"]>:is(label,textarea,.flderr){grid-column:1/-1}
  .mdlbox--zgl [data-fld="zn-tresc"]>.zglicznik{white-space:nowrap}
  /* Pole opisu niższe o 30 px niż domyślne 130: na laptopie 1366x768 to była
     różnica między „priorytet widać" a „priorytet ucięty o 28 px". Róg do
     rozciągania zostaje (`resize:vertical`), więc kto pisze dużo, powiększy je
     sobie sam - a kto pisze dwa zdania, nie płaci za to przewijaniem. */
  .mdlbox--zgl .fld textarea{min-height:88px}
  /* Odstępy są tu o stopień ciaśniejsze niż w innych oknach i to jest ŚWIADOMY
     koszt: ósemka między polami razy pięć przerw to pięćdziesiąt kilka pikseli,
     czyli dokładnie tyle, ile brakowało, żeby formularz zmieścił się na
     laptopie 1280x800. Zmierzone: bez tego zostawało 49 px do przewinięcia. */
  .mdlbody.zngrid{display:grid;grid-template-columns:minmax(0,1.45fr) minmax(0,1fr);
      gap:var(--space-4) var(--space-6);align-items:start;
      padding:var(--space-4) var(--space-5)}
  .zngrid .zncol{display:flex;flex-direction:column;gap:var(--space-3);min-width:0}
  /* Kreska oddzielająca panel - w makiecie prawa kolumna jest marginesem obok
     listu, nie dalszym ciągiem formularza. */
  .zngrid .zncol--bok{padding-left:var(--space-6);border-left:1px solid var(--line)}
  /* Pasek błędu idzie przez OBIE kolumny: dotyczy całego formularza, a wciśnięty
     w jedną wyglądałby na uwagę do sąsiedniego pola. */
  .zngrid>.authalert{grid-column:1/-1}
  .zneyeb{display:block;margin-bottom:7px;font-size:10.5px;letter-spacing:.08em;
      text-transform:uppercase;color:var(--cx-turquoise-600)}

  @media(max-width:620px){
    .mdl{padding:0}
    .mdlbox{width:100%;max-height:100vh;border-radius:0}
  }
  /* Na wąskim ekranie kolumny wracają JEDNA POD DRUGĄ - dwie kolumny po 300 px
     nie mieszczą ani kafli produktów, ani adresów w pigułkach. Próg 900 px,
     a nie 620: przy 700 px druga kolumna formalnie się mieści i wygląda na
     działającą, a kafle produktów łamią się wtedy po jednym w rzędzie. */
  @media(max-width:900px){
    .mdlbox.mdlbox--zgl{width:min(680px,100%)}
    .mdlbody.zngrid{grid-template-columns:minmax(0,1fr)}
    .zngrid .zncol--bok{padding-left:0;border-left:0;
        padding-top:var(--space-5);border-top:1px solid var(--line)}
  }

  /* ── kreator danych firmy ────────────────────────────────────────────
     Osobny ekran na każdy krok: jedno pytanie, jedna ilustracja, dwa
     przyciski. Modal dziedziczy szkielet po `.mdl`. */
  .krkroki{display:flex;align-items:center;gap:6px}
  .krkrok{width:22px;height:4px;border-radius:2px;background:var(--cx-cloud-2)}
  .krkrok--jest{background:var(--cx-ink)}
  .krkrok--byl{background:var(--cx-lime)}
  .krlead{margin:0;font-size:14.5px;line-height:1.65;color:var(--body-fg)}
  .krlead b{color:var(--text)}
  .krfig{margin:0;border:1px solid var(--line);border-radius:var(--radius-md);
      background:var(--cx-mist);padding:var(--space-4);overflow:hidden}
  .krfig svg{display:block;width:100%;height:auto}
  .krfig figcaption{margin-top:var(--space-3);font-size:12.5px;line-height:1.55;
      color:var(--muted);text-align:center}
  .krfig figcaption code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
      font-size:11.5px;background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-xs);padding:1px 5px}
  .krlista{list-style:none;display:flex;flex-direction:column;gap:var(--space-3)}
  .krlista li{display:flex;gap:var(--space-3);font-size:14px;line-height:1.55;
      color:var(--body-fg)}
  .krlista b{color:var(--text)}
  .krnum{flex:none;display:grid;place-items:center;width:22px;height:22px;
      border-radius:999px;background:var(--cx-ink);color:var(--cx-white);
      font-size:12px;font-weight:600}
  .krpod{display:flex;flex-direction:column;gap:2px;padding:var(--space-4);
      border:1px solid var(--line);border-radius:var(--radius-md);background:var(--cx-mist)}
  .krpod dt{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
  .krpod dd{margin:0 0 var(--space-3);font-size:14.5px;color:var(--text);font-weight:600}
  .krpod dd:last-child{margin-bottom:0}
  .krblad{margin:0;font-size:13.5px;line-height:1.55;color:var(--cx-gray-1);
      background:rgba(255,204,0,.16);border-radius:var(--radius-sm);padding:var(--space-3)}
  .krlink{background:none;border:0;padding:0;font:inherit;font-size:13.5px;
      color:var(--cx-ink-10);text-decoration:underline;cursor:pointer}
  .krlink:hover{color:var(--text)}

  /* Chipy priorytetu zachowują się jak radio - wygląd bierzemy z .chip. */
  .fldchips{display:flex;flex-wrap:wrap;gap:var(--space-2)}

  /* ── Kafelki produktów i gwiazdki priorytetu w nowym zgłoszeniu ──────────
     Decyzja 11: zamiast listy kategorii klient wskazuje produkt (można kilka),
     a priorytet ustawia gwiazdkami z podpisem w dymku. */
  .prodtiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
      gap:8px}
  .prodtile{display:flex;align-items:center;gap:9px;padding:9px 11px;cursor:pointer;
      font:inherit;font-size:13px;text-align:left;line-height:1.25;
      color:var(--body-fg);background:var(--cx-white);
      border:1px solid var(--line);border-radius:var(--radius-md);
      transition:border-color .16s ease,background .16s ease,color .16s ease}
  .prodtile img{width:22px;height:22px;flex:none;object-fit:contain}
  .prodtile:hover{border-color:var(--cx-ink-20);color:var(--text)}
  /* Wybrany kafelek niesie sygnał obrysem i tłem, nie samym kolorem pisma -
     przy wyborze wielokrotnym trzeba widzieć komplet jednym rzutem oka. */
  .prodtile.on{border-color:var(--cx-ink);background:var(--cx-mist);color:var(--text);
      font-weight:600}
  .prodtile:focus-visible{outline:2px solid var(--cx-turquoise-600);outline-offset:2px}

  .prio{display:flex;align-items:center;gap:4px}
  .priostar{position:relative;display:grid;place-items:center;width:38px;height:38px;
      padding:0;cursor:pointer;background:none;border:0;border-radius:9px;
      color:var(--cx-cloud-2);transition:color .16s ease,background .16s ease}
  .priostar svg{width:24px;height:24px;display:block}
  .priostar:hover{background:var(--cx-mist)}
  .priostar.on{color:var(--cx-green-500)}
  /* Czwarta gwiazdka na czerwono - „krytyczna awaria" ma odstawać od reszty
     jeszcze zanim ktoś ją kliknie. */
  .priostar--kryt{color:rgba(180,35,24,.35)}
  .priostar--kryt.on{color:var(--cx-error)}
  .priostar:focus-visible{outline:2px solid var(--cx-turquoise-600);outline-offset:2px}
  /* Dymek z podpisem: wchodzi na najechaniu i na ognisku, żeby klawiatura
     dostała to samo co mysz. */
  /* Dymek POD gwiazdką, nie nad nią: nad nią wchodził na podpis „Priorytet". */
  .priotip{position:absolute;top:calc(100% + 6px);left:50%;transform:translateX(-50%);
      white-space:nowrap;font-style:normal;font-size:11.5px;line-height:1;
      padding:6px 9px;border-radius:7px;background:var(--cx-ink);color:var(--cx-white);
      opacity:0;pointer-events:none;transition:opacity .14s ease;z-index:5}
  .priostar:hover .priotip,.priostar:focus-visible .priotip{opacity:1}
  .priolab{margin-left:8px;font-size:13px;color:var(--soft)}
  @media (prefers-reduced-motion: reduce){ .priotip{transition:none} }

  /* ── osoby w korespondencji ──────────────────────────────────────────────
     Adresy jako plakietki dopisywane Enterem albo przecinkiem. Zgłaszającego
     nie da się usunąć - to on prowadzi sprawę. */
  .mailbox{display:flex;flex-wrap:wrap;align-items:center;gap:7px;padding:9px 10px;
      background:var(--cx-white);border:1px solid var(--line2);border-radius:var(--radius-sm)}
  .mailbox:focus-within{border-color:var(--cx-ink-20)}
  .mail{display:inline-flex;align-items:center;gap:7px;padding:5px 8px 5px 10px;
      background:var(--cx-mist);border:1px solid var(--line);border-radius:8px;
      font-size:13px;color:var(--text)}
  .mailme{font-style:normal;font-size:10.5px;font-weight:700;letter-spacing:.03em;
      text-transform:uppercase;padding:2px 6px;border-radius:5px;
      background:var(--cx-ink);color:var(--cx-lime)}
  .mailx{display:grid;place-items:center;width:18px;height:18px;padding:0;background:none;
      border:0;border-radius:5px;cursor:pointer;font:inherit;font-size:15px;line-height:1;
      color:var(--muted)}
  .mailx:hover{background:var(--cx-cloud);color:var(--text)}
  .mailin{flex:1;min-width:190px;padding:6px 4px;border:0;background:none;font:inherit;
      font-size:14px;color:var(--text);outline:none}
  .mailin[aria-invalid="true"]{color:var(--cx-error)}

  /* ══ Filtry listy zgłoszeń ════════════════════════════════════════════════
     Rozwinięte filtry zjadały pół szerokości paska, więc siedzą pod jedną
     ikoną. Liczba czynnych filtrów jest w plakietce na przycisku, a menu
     zamyka Esc, klik poza nim i „Gotowe". */
  .tkbar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;
      gap:var(--space-4);margin-bottom:var(--space-5)}
  .tkfilthost{position:relative}
  .tkfilt{display:inline-flex;align-items:center;gap:9px;height:44px;padding:0 16px;
      background:var(--cx-white);border:1px solid var(--line2);border-radius:var(--radius-md);
      cursor:pointer;font:inherit;font-size:14px;color:var(--text);
      transition:border-color .14s ease,background .14s ease}
  .tkfilt:hover{border-color:var(--cx-ink-20)}
  .tkfilt[aria-expanded="true"]{background:var(--cx-ink);border-color:var(--cx-ink);
      color:var(--cx-white)}
  .tkfilt svg{width:17px;height:17px;flex:none}
  .tkfiltn{font-style:normal;min-width:20px;height:20px;padding:0 6px;display:inline-grid;
      place-items:center;border-radius:6px;background:var(--cx-lime);color:var(--cx-ink);
      font-size:11.5px;font-weight:700}
  .tkfiltn[hidden]{display:none}
  .tkfiltmenu{position:absolute;top:calc(100% + 8px);left:0;z-index:70;
      width:min(420px,92vw);display:flex;flex-direction:column;gap:var(--space-4);
      padding:var(--space-5);background:var(--cx-white);border:1px solid var(--line2);
      border-radius:var(--radius-lg);box-shadow:0 16px 40px rgba(0,0,0,.08)}
  .tkfiltmenu[hidden]{display:none}
  .fmgrp{display:flex;flex-direction:column;gap:8px}
  .fmgrp[hidden]{display:none}
  .fmlab{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
  .fmin{height:40px;padding:0 12px;border:1px solid var(--line2);border-radius:var(--radius-sm);
      background:var(--cx-white);font:inherit;font-size:14px;color:var(--text);outline:none}
  .fmin:focus{border-color:var(--cx-ink-20)}
  .fmseg{display:flex;justify-content:space-between;gap:6px;padding:4px;
      background:var(--cx-mist);border-radius:var(--radius-md)}
  .fmopt{flex:0 1 auto;min-width:0;display:flex;align-items:center;justify-content:center;
      gap:8px;min-height:40px;padding:0 20px;background:none;border:0;
      border-radius:var(--radius-sm);cursor:pointer;font:inherit;font-size:12.5px;
      color:var(--body-fg);white-space:nowrap;transition:background .14s ease,color .14s ease}
  .fmopt:hover{background:var(--cx-white);color:var(--text)}
  .fmopt.on{background:var(--cx-ink);color:var(--cx-white);font-weight:600}
  .fmopt i{font-style:normal;font-size:11.5px;color:var(--muted);flex:none}
  .fmopt.on i{color:var(--cx-lime)}
  /* Własna lista zamiast <select> - systemowej nie da się ostylować. */
  .fmdd{position:relative}
  .fmddbtn{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;
      height:40px;padding:0 12px;background:var(--cx-white);border:1px solid var(--line2);
      border-radius:var(--radius-sm);cursor:pointer;font:inherit;font-size:14px;
      color:var(--text);text-align:left;transition:border-color .14s ease}
  .fmddbtn:hover,.fmddbtn[aria-expanded="true"]{border-color:var(--cx-ink-20)}
  .fmddbtn svg{width:13px;height:13px;flex:none;color:var(--accent);transition:transform .14s ease}
  .fmddbtn[aria-expanded="true"] svg{transform:rotate(180deg)}
  .fmddval{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .fmddlist{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:80;list-style:none;
      margin:0;padding:6px;max-height:248px;overflow-y:auto;background:var(--cx-white);
      border:1px solid var(--line2);border-radius:var(--radius-md);
      box-shadow:0 8px 16px rgba(0,0,0,.06)}
  .fmddlist[hidden]{display:none}
  .fmddlist li{padding:9px 12px;border-radius:var(--radius-sm);cursor:pointer;font-size:14px;
      color:var(--body-fg)}
  .fmddlist li:hover{background:var(--cx-mist);color:var(--text)}
  .fmddlist li.on{background:var(--cx-ink);color:var(--cx-white);font-weight:600}
  .fmrangein{display:flex;align-items:center;gap:8px}
  .fmrangein .fmin{flex:1;min-width:0}
  .fmdash{color:var(--muted)}
  .fmfoot{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);
      padding-top:var(--space-3);border-top:1px solid var(--line)}
  /* „Wyczyść filtry" jest odnośnikiem, nie guzikiem - dwa guziki obok siebie
     sugerowałyby dwie równoważne akcje. */
  .fmclear{display:inline-flex;align-items:center;gap:7px;background:none;border:0;
      cursor:pointer;font:inherit;font-size:13px;color:var(--muted);padding:0}
  .fmclear svg{width:13px;height:13px}
  .fmclear:hover{color:var(--text)}
  .fmdone{height:40px;padding:0 24px;white-space:nowrap}
  .tkbaract{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap}
  .tksearch{display:inline-flex;align-items:center;gap:9px;padding:0 14px;height:44px;
      background:var(--cx-white);border:1px solid var(--line2);border-radius:var(--radius-md);
      color:var(--muted)}
  .tksearch:focus-within{border-color:var(--cx-ink-20)}
  .tksearch svg{width:16px;height:16px;flex:none}
  .tksearch input{width:min(240px,42vw);border:0;background:none;font:inherit;font-size:14px;
      color:var(--text);outline:none}

  /* ══ Mój profil: zdjęcie i wiersze danych ═════════════════════════════════
     Zdjęcie portal zaciąga z Gravatara albo z konta Google; opcje zmiany
     wychodzą po najechaniu na samo zdjęcie, żeby nie trzymać czterech
     guzików na stałe. */
  .navavatar{display:grid;place-items:center;flex:none;width:32px;height:32px;
      border-radius:10px;background:var(--cx-lime);color:var(--cx-ink);font-size:12.5px;
      font-weight:700;letter-spacing:.02em;overflow:hidden}
  .navavatar img{width:100%;height:100%;object-fit:cover}
  /* Pole ze ZDJĘCIEM ma białe tło i cienką jasną ramkę, a nie limonkę spod
     inicjałów (polecenie Radka 1.10). Dwa powody, oba widoczne dopiero na
     ekranie: zdjęcie z przezroczystością przepuszcza tło pod spodem, a biała
     koszula na białym zdjęciu bez ramki zlewa się z kartą.
     `:has(img)`, a nie osobna klasa z JavaScriptu: zdjęcie wstawiają trzy
     różne miejsca (karta konta, pasek, płachta menu) i każde musiałoby
     pamiętać o dokładaniu tej klasy. */
  .navavatar:has(img){background:var(--cx-white);
      box-shadow:inset 0 0 0 1px var(--line)}
  .navavatar--xl{width:56px;height:56px;border-radius:16px;font-size:19px}
  .acc{padding:var(--space-5);background:var(--cx-white);border:1px solid var(--line);
      border-radius:var(--radius-lg)}
  .accava{display:flex;align-items:flex-start;gap:var(--space-4);padding-bottom:var(--space-5);
      margin-bottom:var(--space-5);border-bottom:1px solid var(--line)}
  .accavatx{display:flex;flex-direction:column;gap:3px}
  .accavatx b{font-size:15px;font-weight:600;color:var(--text)}
  .accavatx span{font-size:12.5px;color:var(--muted)}
  /* Zdjęcie to samo kółko (decyzja 36) - guziki stoją pod opisem, widoczne
     zawsze. Nakładka na zdjęciu pokazywała się dopiero po najechaniu, więc
     na wąskim oknie z myszą nie było jej w ogóle, a etykiety i tak nie
     mieściły się w 56 px. */
  .accava>.navavatar{flex:none}
  .accavabtn{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
  .chip--tekst{font:inherit;font-size:12.5px;cursor:pointer}
  .avaname{font-family:var(--font-display);font-size:20px!important;font-weight:500;
      color:var(--text)}
  .avahint{margin-top:6px;font-size:12px!important;line-height:1.5;color:var(--soft)!important;
      max-width:46ch}
  /* Podświetla się samo pole wartości, nie cały wiersz - podpis zostaje
     spokojny, a obramowanie pokazuje dokładnie to, co da się kliknąć. */
  .edlist{list-style:none;display:flex;flex-direction:column;gap:0}
  .edrow{display:grid;grid-template-columns:190px minmax(0,1fr);align-items:center;
      gap:var(--space-4);min-height:44px}
  .edlab{font-size:12.5px;color:var(--muted)}
  .edbox{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);
      min-height:36px;padding:0 12px;border:1px solid transparent;border-radius:var(--radius-sm);
      cursor:pointer;transition:border-color .14s ease,background .14s ease}
  .edrow:not(.edrow--ro) .edbox:hover{border-color:var(--line2);background:var(--cx-mist)}
  .edval{font-size:14.5px;color:var(--text)}
  .edval--empty{color:var(--muted)}
  .edpen{display:inline-flex;flex:none;color:var(--muted);opacity:0;transition:opacity .14s ease}
  .edbox:hover .edpen{opacity:1}
  .edpen svg,.edlock svg{width:15px;height:15px}
  .edinput{flex:1;min-width:0;border:0;background:none;outline:none;font:inherit;
      font-size:14.5px;color:var(--text);padding:0}
  /* W trakcie edycji wiersz ma wygladac jak pole, a nie jak tekst - inaczej
     nie widac, ze cokolwiek jest otwarte do wpisania. */
  .edbox--edit,.edbox--edit:hover{background:var(--cx-white);border-color:var(--cx-ink);cursor:text}
  .eddraft{flex:none;font-size:10.5px;padding:3px 8px;border-radius:5px;
      background:rgba(255,204,0,.18);color:#6b5200;white-space:nowrap}
  .edrow--draft .edval{font-weight:600}
  /* Adres e-mail: na nim stoi logowanie i identyfikacja zgłoszeń, więc
     zmienia go CXLABS - wiersz nie reaguje na hover, a w miejscu ołówka
     stoi kłódka. */
  .edrow--ro .edbox{cursor:default}
  .edrow--ro .edval{color:var(--body-fg)}
  .edlock{flex:none;display:inline-flex;pointer-events:none;color:var(--muted);opacity:0;
      transition:opacity .14s ease}
  .edrow--ro .edbox:hover .edlock{opacity:1}
  /* Adres monday.com: prośba o zmianę zamiast edycji. */
  .slugform{display:flex;flex-direction:column;align-items:flex-start;gap:var(--space-3);
      margin-top:var(--space-4)}
  .slugrow{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);width:100%}
  .slugrow[hidden]{display:none}
  .slugpole{display:inline-flex;align-items:center;gap:2px;padding:0 12px;height:44px;
      background:var(--cx-white);border:1px solid var(--line2);border-radius:var(--radius-sm)}
  .slugpole input{border:0;background:none;outline:none;font:inherit;font-size:15px;
      color:var(--text);width:min(220px,44vw)}
  .slugpole i{font-style:normal;font-size:15px;color:var(--soft)}
  .slugczeka{margin-top:var(--space-4);padding:var(--space-4);border-radius:var(--radius-md);
      background:rgba(253,171,61,.10);border:1px solid rgba(253,171,61,.35);font-size:14px;
      line-height:1.55;color:var(--text)}
  .slugczeka span{color:var(--body-fg);font-size:13px}
  .accsave{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-4);
      margin-top:var(--space-5);padding-top:var(--space-5);border-top:1px solid var(--line)}
  .accsavetx{font-size:12.5px;color:var(--muted)}
  @media(max-width:620px){
    .edrow{grid-template-columns:minmax(0,1fr);row-gap:2px}
    .edlab{padding-left:12px}
  }

  /* ══ Kurs monday.com w artykule ═══════════════════════════════════════════
     Dwa warianty tej samej reklamy, zależne od kategorii artykułu:
     - „Pierwsze kroki" -> szeroki baner NAD tytułem: czytelnik dopiero wchodzi
       w monday.com i kurs realnie mu pomaga, więc reklama ma prawo być z przodu,
     - pozostałe kategorie -> wąska karta w kolumnie bocznej, nad spisem treści:
       czytelnik szuka konkretu, więc reklama nie przerywa czytania.
     Obie na tej samej ciemnej płycie marki - jasna karta ginęła na tle kolumny. */
  .kursban{display:grid;grid-template-columns:132px minmax(0,1fr);
      gap:clamp(18px,2.5vw,28px);align-items:center;
      margin:0 0 clamp(28px,4vh,44px);padding:clamp(18px,2.4vw,26px);
      background:#243838;border-radius:var(--radius-lg)}
  .kursbanfig{margin:0;border-radius:var(--radius-md);overflow:hidden}
  /* height:auto jest konieczne: atrybut height="640" w znaczniku to podpowiedź
     przeglądarki i wygrywa z aspect-ratio, przez co zdjęcie rosło do 640 px. */
  .kursbanfig img{display:block;width:100%;height:auto;aspect-ratio:1/1;object-fit:cover}
  .kursbantx{display:flex;flex-direction:column;gap:8px;min-width:0}
  .kursbantag{display:inline-flex;align-items:center;gap:8px;font-size:12px;
      color:var(--cx-lime)}
  .kursbantag svg{flex:none;width:14px;height:14px}
  .kursbantx b{font-family:var(--font-display);font-size:clamp(19px,2vw,24px);
      font-weight:400;line-height:1.2;letter-spacing:-.01em;color:#F4F9F8}
  .kursbantx p{max-width:58ch;font-size:14px;line-height:1.55;color:#DBECE9;margin:0}
  .kursbancta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);
      margin-top:var(--space-2)}
  .kursbanmore{display:inline-flex;align-items:center;padding:11px 18px;
      border-radius:10px;background:#F4F9F81a;color:#F4F9F8;font-size:14px;
      transition:background .15s ease}
  .kursbanmore:hover{background:#F4F9F833;color:#F4F9F8}

  /* Karta jest rodzeństwem .artside, nie jej dzieckiem: siedzi w drugiej
     kolumnie siatki nad spisem treści i ma własne miejsce w hierarchii.
     `grid-template-rows:auto 1fr` jest konieczne - bez tego wiersz 1 dzielił
     wysokość z artykułem (który spina oba wiersze) i spis treści startował
     dopiero w połowie strony. */
  .artwrap:has(>.kursside){grid-template-rows:auto 1fr}
  .artwrap>.kursside{grid-column:2;grid-row:1}
  .artwrap:has(>.kursside)>.artside{grid-column:2;grid-row:2}
  .artwrap:has(>.kursside)>.doc{grid-column:1;grid-row:1/span 2}
  @media(max-width:980px){
    .artwrap>.kursside,.artwrap:has(>.kursside)>.artside,
    .artwrap:has(>.kursside)>.doc{grid-column:1;grid-row:auto}
  }
  /* Spis treści wyjęty na telefonie z kolumny bocznej POD TYTUŁ, do środka
     artykułu (robi to `ukladArtykuluNaWasko` w szkielecie). Jako dziecko
     `article.doc` musi sam wziąć wygląd karty - dotąd miał go po kolumnie,
     w której siedział. Selektor celuje w dziecko artykułu, więc na szerokim
     ekranie, gdzie spis wraca do kolumny, nie łapie go wcale.
     Sufitu wysokości tu NIE MA i nie wraca (polecenie Radka 30.09): spis jest
     rozwinięty w całości. Owszem, przy artykule z dwudziestoma nagłówkami
     odpycha to początek tekstu - ale spis, którego nie widać w całości, nie
     jest spisem treści, tylko okienkiem do przewijania w środku strony,
     którą i tak się przewija. */
  article.doc>.sidetoc{margin:var(--space-4) 0;padding:20px;
      background:var(--cx-mist);border:1px solid var(--line);
      border-radius:var(--radius-lg)}

  /* Baner kursu wsunięty na telefonie za pierwszy blok treści. W `.docbody`
     odstępy mają akapity, nie on, więc dokłada sobie własne - inaczej kleiłby
     się do tekstu nad i pod sobą. */
  .docbody>.kursban{margin:var(--space-5) 0}

  .kursside{display:flex;flex-direction:column;gap:9px;
      padding:var(--space-4);margin-bottom:var(--space-5);
      background:#243838;border-radius:var(--radius-lg)}
  .kurssidefig{margin:0 0 var(--space-2);border-radius:var(--radius-md);overflow:hidden}
  .kurssidefig img{display:block;width:100%;height:auto;aspect-ratio:16/10;object-fit:cover}
  .kurssidetag{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;
      color:var(--cx-lime)}
  .kurssidetag svg{flex:none;width:13px;height:13px}
  .kursside b{font-family:var(--font-display);font-size:17px;font-weight:400;
      line-height:1.25;letter-spacing:-.01em;color:#F4F9F8}
  .kurssidefacts{list-style:none;display:flex;flex-direction:column;gap:6px;
      margin:2px 0 var(--space-2);padding:0}
  .kurssidefacts li{display:flex;gap:8px;font-size:12.5px;line-height:1.4;
      color:#DBECE9}
  .kurssidefacts li::before{content:"";flex:none;width:5px;height:5px;
      margin-top:6px;border-radius:50%;background:var(--cx-lime)}
  /* Guzik kursu: zwykły hover - lekkie przygaszenie płytki. */
  .kurssidebuy,.kursbanbuy{display:flex;align-items:center;
      justify-content:space-between;gap:10px;height:42px;
      padding:3px 3px 3px 16px;border-radius:10px;background:var(--cx-lime);
      color:var(--cx-ink);font-size:13.5px;font-weight:500;text-decoration:none;
      transition:filter .15s ease}
  .kurssidebuy:hover,.kursbanbuy:hover{filter:brightness(.94);color:var(--cx-ink)}
  .kurssidebuy:active,.kursbanbuy:active{transform:translateY(1px)}
  .kbplate{flex:none;display:block}
  .kbplate svg{display:block;width:36px;height:36px}
  .kursbanbuy{min-width:212px;font-size:14px}
  .kurssidemore{font-size:12.5px;color:#DBECE9;text-align:center;padding-top:2px}
  .kurssidemore:hover{color:var(--cx-lime)}
  /* Na telefonie baner składa się w jedną kolumnę - i wtedy zdjęcie przestaje
     być OKŁADKĄ obok tekstu, a staje się kwadracikiem doklejonym w lewym
     górnym rogu (tak było do 30.09: `max-width:120px`). Na szerokim ekranie
     kadr 1:1 ma sens, bo wypełnia całą wysokość banera; w pionie ten sam kadr
     nie ma czego wypełnić i wygląda jak przypadkowa miniatura.
     Dlatego na wąskim zdjęcie idzie PASEM na całą szerokość, w proporcji
     16/10 - tej samej, którą ma karta kursu w kolumnie bocznej
     (`.kurssidefig`), czyli w pionie obie reklamy wyglądają tak samo.
     Guziki dostają równą szerokość: przy zawijaniu „Kup kurs" schodził pod
     spód jako wąski szary prostokąt o przypadkowej długości. */
  @media(max-width:620px){
    .kursban{grid-template-columns:minmax(0,1fr);gap:16px}
    .kursbanfig{max-width:none}
    .kursbanfig img{aspect-ratio:16/10}
    .kursbancta{gap:10px}
    .kursbanbuy,.kursbanmore{width:100%;min-width:0}
    .kursbanmore{justify-content:center}
  }

  /* ══ Raport zespołu (widok menedżera) ═════════════════════════════════════
     Wykresy rysujemy inline (SVG + CSS), bez biblioteki: to kilka serii,
     a portal nie ma bundlera. */
  :root{
    --ch-new:#305555;      /* turquoise-700 - nowe */
    --ch-done:#6BD210;     /* lime-deep - zamknięte */
    --ch-grid:rgba(18,32,33,.07);
  }
  .dashbar{display:flex;align-items:center;justify-content:space-between;
      flex-wrap:wrap;gap:var(--space-4)}
  .dashbar .stanybar{margin-bottom:0}
  .stanybar{display:flex;flex-wrap:wrap;gap:4px;padding:4px;
      background:var(--cx-mist);border:1px solid var(--line);border-radius:var(--radius-md)}
  .stanopt{padding:9px 16px;background:none;border:0;border-radius:var(--radius-sm);
      cursor:pointer;font:inherit;font-size:13px;color:var(--body-fg);
      transition:background .14s ease,color .14s ease}
  .stanopt:hover{background:var(--cx-white);color:var(--text)}
  .stanopt.on{background:var(--cx-ink);color:var(--cx-white);font-weight:600}
  .dashacts{display:flex;align-items:center;gap:var(--space-3)}
  .kpis{list-style:none;display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
      gap:var(--space-4);margin:var(--space-5) 0;padding:0}
  .kpis li{position:relative;display:flex;flex-direction:column;gap:2px;
      padding:var(--space-5);border:1px solid var(--line);border-radius:var(--radius-lg);
      background:linear-gradient(180deg,#fff 0%,#FBFDFC 100%);
      box-shadow:0 1px 2px rgba(18,32,33,.04),0 8px 24px -12px rgba(18,32,33,.10)}
  /* cienka limonkowa krecha u góry karty - sygnał marki bez krzyku */
  .kpis li::before{content:"";position:absolute;inset:0 0 auto;height:2px;
      border-radius:var(--radius-lg) var(--radius-lg) 0 0;
      background:linear-gradient(90deg,var(--cx-lime),rgba(173,247,99,0))}
  .kpis b{font-family:var(--font-display);font-weight:400;font-size:clamp(28px,3vw,38px);
      line-height:1.05;letter-spacing:-.01em;color:var(--text);
      font-variant-numeric:tabular-nums}
  .kpis li>span{font-size:13.5px;color:var(--text)}
  .kpis i{font-style:normal;font-size:12px;color:var(--muted)}
  .dashgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));
      gap:var(--space-4)}
  .chartcard{padding:var(--space-5);border:1px solid var(--line);
      border-radius:var(--radius-lg);
      background:linear-gradient(180deg,#fff 0%,#FBFDFC 100%);
      box-shadow:0 1px 2px rgba(18,32,33,.04),0 10px 30px -16px rgba(18,32,33,.12)}
  .chartcard .secgroup-head{margin-bottom:var(--space-4);flex-wrap:wrap;gap:8px}
  .chartcard .secgroup-head h3{white-space:nowrap}
  .lgd{display:inline-block;width:9px;height:9px;border-radius:3px;
      margin:0 5px 0 12px;vertical-align:middle;
      box-shadow:0 1px 2px rgba(18,32,33,.16)}
  .secgroup-count .lgd:first-child{margin-left:0}
  .lgd--new{background:var(--ch-new)}
  .lgd--done{background:var(--ch-done)}

  /* Słupki pionowe. Siatka poziomych linii daje oku miarę wysokości - bez
     niej słupki wiszą w pustce. Rysujemy ją tłem kontenera. */
  .bars{position:relative;display:flex;align-items:flex-end;
      gap:clamp(8px,2vw,20px);height:200px;padding-bottom:1px;
      background-image:repeating-linear-gradient(to top,
          var(--ch-grid) 0 1px,transparent 1px 25%);
      background-position:0 -1px}
  .barcol{flex:1;display:flex;flex-direction:column;align-items:center;gap:8px;height:100%}
  .barpair{flex:1;display:flex;align-items:flex-end;justify-content:center;gap:5px;
      width:100%;min-height:0}
  .bar{position:relative;width:clamp(12px,2.4vw,22px);border-radius:5px 5px 2px 2px;
      cursor:default;transform-origin:bottom;
      animation:barIn .5s cubic-bezier(.22,1,.36,1) backwards;
      transition:filter .16s ease,transform .16s ease}
  @keyframes barIn{from{transform:scaleY(.2);opacity:0}to{transform:scaleY(1);opacity:1}}
  .barcol:nth-child(2) .bar{animation-delay:.04s}
  .barcol:nth-child(3) .bar{animation-delay:.08s}
  .barcol:nth-child(4) .bar{animation-delay:.12s}
  .barcol:nth-child(5) .bar{animation-delay:.16s}
  .bar:hover,.bar:focus-visible{filter:brightness(1.06) saturate(1.05);
      transform:translateY(-2px);outline:none}
  .bar em{position:absolute;top:-19px;left:50%;transform:translateX(-50%);
      font-style:normal;font-size:11px;font-weight:600;color:var(--text);
      font-variant-numeric:tabular-nums;opacity:0;pointer-events:none;
      transition:opacity .14s ease}
  .bar:hover em,.bar:focus-visible em{opacity:1}
  .bar--new{background:linear-gradient(180deg,#3E6C6B 0%,var(--ch-new) 62%,#26474700 100%),
      var(--ch-new);box-shadow:0 2px 8px -3px rgba(48,85,85,.55),
      inset 0 1px 0 rgba(255,255,255,.14)}
  .bar--done{background:linear-gradient(180deg,#C6FF8B 0%,var(--ch-done) 58%,#93DC4E 100%);
      box-shadow:0 2px 8px -3px rgba(107,210,16,.45),
      inset 0 1px 0 rgba(255,255,255,.45)}
  .barlab{font-size:11.5px;color:var(--muted)}

  /* Pierścień statusów */
  .donutwrap{display:flex;align-items:center;gap:var(--space-5);flex-wrap:wrap}
  .donut{flex:none;width:158px;height:158px;transform:rotate(-90deg);
      filter:drop-shadow(0 6px 14px rgba(18,32,33,.10))}
  .donut .dtrack{stroke:var(--cx-mist)}
  .donut .seg{transition:stroke-width .16s ease,opacity .16s ease;transform-origin:21px 21px}
  .donutwrap:hover .seg{opacity:.55}
  .donut .seg:hover{stroke-width:7;opacity:1}
  .donut text{transform:rotate(90deg);transform-origin:21px 21px;text-anchor:middle;
      font-family:var(--font-display)}
  .dnum{font-size:6.4px;fill:var(--text)}
  .dlab{font-size:2.4px;fill:var(--muted);font-family:var(--font-body)}
  .donutlgd{list-style:none;flex:1;min-width:150px;display:flex;flex-direction:column;
      gap:7px;margin:0;padding:0}
  .donutlgd li{display:flex;align-items:center;gap:9px;font-size:13px;color:var(--body-fg);
      padding:3px 6px;margin:0 -6px;border-radius:6px;transition:background .14s ease}
  .donutlgd li:hover{background:var(--cx-mist)}
  .donutlgd em{flex:none;width:10px;height:10px;border-radius:3px;
      box-shadow:0 1px 3px rgba(18,32,33,.2)}
  .donutlgd i{margin-left:auto;font-style:normal;font-variant-numeric:tabular-nums;
      color:var(--text);font-weight:600}

  /* Słupki poziome */
  .hbars{list-style:none;display:flex;flex-direction:column;gap:13px;margin:0;padding:0}
  .hbars li{display:grid;grid-template-columns:minmax(0,150px) minmax(0,1fr) 34px;
      align-items:center;gap:var(--space-3);font-size:13px}
  .hblab{color:var(--body-fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .hbtrack{height:10px;border-radius:5px;background:var(--cx-mist);overflow:hidden;
      box-shadow:inset 0 1px 2px rgba(18,32,33,.06)}
  .hbfill{display:block;height:100%;border-radius:5px;
      background:linear-gradient(90deg,#3E6C6B,var(--ch-new));
      box-shadow:0 1px 3px -1px rgba(48,85,85,.5);
      animation:hbIn .55s cubic-bezier(.22,1,.36,1) backwards;transform-origin:left}
  @keyframes hbIn{from{transform:scaleX(0)}to{transform:scaleX(1)}}
  .hbars i{font-style:normal;text-align:right;font-variant-numeric:tabular-nums;
      color:var(--text);font-weight:600}

  /* Panel: statystyki portalu (9.10). Klocki z widoku statystyk firmy
     (kafle, karty, paski) - tu tylko to, czego tamten widok nie miał. */
  .stokres{justify-content:flex-end;margin-bottom:var(--space-2)}
  .stsekcja{margin-top:var(--space-6);align-items:baseline}
  .stsekcja .zsh{margin:0}
  .stzrodlo{font-size:12.5px;color:var(--muted)}
  .chartcard.stszeroka{grid-column:1/-1}
  #st-tresc .hbars i{min-width:34px}
  #st-tresc .hbars li{grid-template-columns:minmax(0,170px) minmax(0,1fr) auto}
  /* Trzydzieści słupków dziennych nie zmieści się z odstępem z widoku firmy:
     słupek bierze szerokość kolumny, a odstęp jest stały i mały. */
  .chartcard.stszeroka .bars{gap:3px}
  .chartcard.stszeroka .bar{width:min(100%,22px)}
  .chartcard.stszeroka .barlab{font-size:10.5px;white-space:nowrap}
  .stgodziny{height:140px}
  .stlista{display:flex;flex-direction:column;margin:0}
  .stlista>div{display:flex;justify-content:space-between;gap:var(--space-4);
      padding:9px 0;border-bottom:1px solid var(--line);font-size:13.5px}
  .stlista>div:last-child{border-bottom:0}
  .stlista dt{color:var(--body-fg)}
  .stlista dd{margin:0;text-align:right;font-weight:600;color:var(--text);
      font-variant-numeric:tabular-nums}
  .stlista small{display:block;font-weight:400;font-size:11.5px;color:var(--muted)}
  .stpod{margin-top:var(--space-5)}
  .stnota{margin:var(--space-6) 0 0;font-size:12.5px;line-height:1.6;color:var(--muted)}
  /* Druga runda (9.10 wieczorem): filtry, mapa, tabela fraz. */
  .stfiltry{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3) var(--space-4);
      margin-bottom:var(--space-2)}
  .stdaty{display:flex;flex-wrap:wrap;gap:var(--space-3)}
  .stdaty label{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--body-fg)}
  .stdaty input{font:inherit;font-size:13px;padding:7px 9px;color:var(--text);
      background:var(--cx-white);border:1px solid var(--line);border-radius:var(--radius-sm)}
  .stprzel{display:flex;align-items:center;gap:10px;margin-left:auto;cursor:pointer;
      font-size:13.5px;color:var(--text);line-height:1.3}
  .stprzel small{display:block;font-size:11.5px;color:var(--muted)}
  .stprzel input{position:absolute;opacity:0;width:1px;height:1px}
  .stprzel__tor{flex:none;position:relative;width:38px;height:22px;border-radius:11px;
      background:var(--cx-cloud-2,#c9d3d2);transition:background .16s ease}
  .stprzel__tor::after{content:"";position:absolute;top:3px;left:3px;width:16px;height:16px;
      border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(18,32,33,.3);
      transition:transform .16s ease}
  .stprzel input:checked + .stprzel__tor{background:var(--ch-new,#305555)}
  .stprzel input:checked + .stprzel__tor::after{transform:translateX(16px)}
  .stprzel input:focus-visible + .stprzel__tor{outline:2px solid var(--cx-turquoise-600);outline-offset:2px}
  .stmapatab{margin:0}
  .stmapa{display:block;width:100%;height:auto;max-height:640px;
      background:#EEF5F4;border-radius:var(--radius-md)}
  .stlad{fill:#FBFDFC;stroke:#B9C9C7;stroke-width:.8;stroke-linejoin:round}
  .stwoj{fill:#fff;stroke:#7FA7A5;stroke-width:1;stroke-linejoin:round}
  .stpkt{fill:rgba(48,85,85,.55);stroke:#fff;stroke-width:1.5;transition:fill .14s ease}
  .stpkt:hover{fill:rgba(14,140,130,.85)}
  .stpktlab{font-size:15px;font-weight:600;fill:var(--text);paint-order:stroke;
      stroke:#fff;stroke-width:4px;stroke-linejoin:round;pointer-events:none}
  .stmapapod{margin:var(--space-3) 0 0;font-size:12.5px;color:var(--muted)}
  .stgscinfo{margin:0;font-size:13.5px;line-height:1.6;color:var(--body-fg);max-width:80ch}
  .sttabwrap{overflow-x:auto}
  .sttab{width:100%;border-collapse:collapse;font-size:13px}
  .sttab th{text-align:left;font-weight:600;color:var(--muted);font-size:12px;
      padding:6px 8px;border-bottom:1px solid var(--line);white-space:nowrap}
  .sttab td{padding:7px 8px;border-bottom:1px solid var(--line);color:var(--text);
      font-variant-numeric:tabular-nums}
  .sttab td:not(:first-child),.sttab th:not(:first-child){text-align:right}
  @media (max-width:700px){ .stprzel{margin-left:0} }

  /* Kto zgłasza */
  .dashludzie{list-style:none;display:flex;flex-direction:column;margin:0;padding:0;
      border-top:1px solid var(--line)}
  .dashludzie li{display:grid;
      grid-template-columns:auto minmax(0,1fr) minmax(60px,110px) 40px;
      align-items:center;gap:var(--space-4);padding:var(--space-3) 0;
      border-bottom:1px solid var(--line)}
  .dashav{display:grid;place-items:center;width:32px;height:32px;border-radius:50%;
      background:var(--cx-ink);color:var(--cx-lime);font-size:11.5px;font-weight:700}
  .dashkto{display:flex;flex-direction:column;gap:2px;min-width:0}
  .dashkto b{font-size:14px;font-weight:500;color:var(--text)}
  .dashkto span{font-size:12px;color:var(--muted)}
  .peobar{height:10px;border-radius:5px;background:var(--cx-mist);overflow:hidden;
      box-shadow:inset 0 1px 2px rgba(18,32,33,.06)}
  .peobar span{display:block;height:100%;border-radius:5px;
      background:linear-gradient(90deg,var(--ch-done),#93DC4E);
      box-shadow:0 1px 3px -1px rgba(107,210,16,.45)}
  .peonum{font-style:normal;text-align:right;font-variant-numeric:tabular-nums;
      color:var(--text);font-weight:600;font-size:13px}
  @media(max-width:620px){
    .dashludzie li{grid-template-columns:auto minmax(0,1fr) 40px}
    .peobar{display:none}
  }

  /* Bateria priorytetów: jeden pasek podzielony proporcjonalnie - ten sam
     sposób pokazywania podziału co „battery" w monday.com. */
  .batt{display:flex;height:38px;border-radius:10px;overflow:hidden;
      background:var(--cx-mist);margin-bottom:var(--space-4);
      box-shadow:inset 0 1px 3px rgba(18,32,33,.08)}
  .battseg{position:relative;display:grid;place-items:center;font-size:11.5px;
      font-weight:700;color:var(--cx-ink);transition:filter .16s ease;
      box-shadow:inset 0 1px 0 rgba(255,255,255,.28)}
  .battseg::after{content:"";position:absolute;inset:0;
      background:linear-gradient(180deg,rgba(255,255,255,.22),rgba(0,0,0,.10))}
  .battseg:hover{filter:brightness(1.07)}

  /* Statystyki firmy nad listą „Zgłoszenia firmy” (6.10). Ten sam zestaw
     kart co dawny Dashboard; dochodzą tylko nagłówki dwóch części ekranu
     i odstęp, który oddziela liczby od tabeli. */
  .zsstaty{margin-bottom:var(--space-7)}
  .zsh{margin:0;font-family:var(--font-display);font-weight:400;
      font-size:clamp(22px,2.4vw,28px);line-height:1.15;color:var(--text)}
  .zsh--lista{margin-bottom:var(--space-4)}
  .zsuwaga{margin:var(--space-4) 0 0;font-size:12.5px;color:var(--muted)}
  .zspusto{margin:0;font-size:13.5px;color:var(--muted)}
  .dashkto b,.dashkto span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* Węższy pasek niż w dawnym Dashboardzie: tu karta stoi w siatce trzech
     kolumn, a nazwisko z dopiskiem „(Ty)” ma się zmieścić. */
  #zs-ludzie li{grid-template-columns:auto minmax(0,1fr) minmax(36px,64px) 28px;gap:var(--space-3)}
  @media(prefers-reduced-motion:reduce){
    .bar,.hbfill{animation:none}
  }

  /* ══ Moje raporty ═════════════════════════════════════════════════════════
     Lista wydań, widok pojedynczego raportu (rama) i dwa stany bez treści.
     Wiersz raportu ma stałą kolumnę daty - wydania czyta się po dacie,
     nie po tytule. */
  .rptop{display:flex;align-items:center;justify-content:space-between;
      flex-wrap:wrap;gap:var(--space-4);padding:var(--space-4) var(--space-5);
      margin-bottom:var(--space-5);background:var(--cx-white);
      border:1px solid var(--line);border-radius:var(--radius-lg)}
  .rpsum{display:flex;flex-direction:column;gap:3px;min-width:0}
  .rpsum b{font-size:15px;font-weight:600;color:var(--text)}
  .rpsum span{font-size:12.5px;color:var(--muted)}
  .rplist{list-style:none;display:flex;flex-direction:column;margin:0;padding:0;
      border-top:1px solid var(--line)}
  .rpitem{border-bottom:1px solid var(--line)}
  .rprow{display:grid;grid-template-columns:92px minmax(0,1fr) 28px;
      align-items:center;gap:var(--space-4);padding:var(--space-4) var(--space-3);
      border-radius:var(--radius-md);text-decoration:none;color:inherit;
      transition:background .14s ease}
  .rprow:hover{background:var(--cx-mist)}
  .rpdate{display:flex;flex-direction:column;align-items:flex-start;gap:1px}
  .rpdate b{font-family:var(--font-display);font-weight:400;font-size:20px;
      line-height:1.1;color:var(--text)}
  .rpdate span{font-size:11.5px;color:var(--muted)}
  .rptx{display:flex;flex-direction:column;gap:3px;min-width:0}
  .rptx>b{font-size:15px;font-weight:500;color:var(--text)}
  .rptx>span:last-child{font-size:12.5px;color:var(--muted)}
  .rpeyebrow{display:flex;align-items:center;gap:8px;font-size:11px;
      text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
  .rpnew{font-style:normal;padding:2px 7px;border-radius:4px;
      background:var(--cx-ink);color:var(--cx-lime);font-size:10px;font-weight:700;
      letter-spacing:.04em}
  .rpitem--new .rptx>b{font-weight:600}
  .rpgo{display:grid;place-items:center;color:var(--cx-turquoise-500)}
  .rpgo svg{width:18px;height:18px}
  .rprow:hover .rpgo{color:var(--text)}
  .rpfoot{margin-top:var(--space-5);font-size:12.5px;color:var(--muted)}

  /* widok pojedynczego raportu */
  .rpback{display:inline-flex;align-items:center;gap:7px;margin-bottom:var(--space-4);
      font-size:13px;color:var(--muted);text-decoration:none}
  .rpback:hover{color:var(--text)}
  .rpback svg{width:15px;height:15px}
  .rphead{display:flex;align-items:flex-start;justify-content:space-between;
      flex-wrap:wrap;gap:var(--space-4);padding-bottom:var(--space-5);
      border-bottom:1px solid var(--line)}
  .rpheadtx{display:flex;flex-direction:column;gap:6px;min-width:0}
  .rpheadtx h2{font-family:var(--font-display);font-weight:400;
      font-size:clamp(22px,2.6vw,30px);line-height:1.15;letter-spacing:-.01em;
      color:var(--text)}
  .rpmeta{font-size:12.5px;color:var(--muted)}
  .rpacts{display:flex;flex-wrap:wrap;gap:var(--space-3)}
  .rpnav{display:flex;align-items:center;justify-content:space-between;
      gap:var(--space-3);padding:var(--space-3) 0;
      border-bottom:1px solid var(--line);font-size:13px}
  .rpnavgo{display:inline-flex;align-items:center;gap:7px;color:var(--text);
      text-decoration:none}
  .rpnavgo:hover{color:var(--cx-turquoise-600)}
  .rpnavgo svg{width:15px;height:15px}
  .rpnavgo.is-off{color:var(--cx-cloud-2);pointer-events:none}
  .rpnavnow{font-weight:600;color:var(--text)}

  /* slot na treść raportu i stany bez treści */
  .rpslot,.rpempty{display:flex;flex-direction:column;align-items:center;
      text-align:center;gap:var(--space-3);
      padding:clamp(32px,6vh,64px) var(--space-5);margin-top:var(--space-5);
      border:1px dashed var(--line2);border-radius:var(--radius-lg);
      background:var(--cx-mist)}
  .rpempty{border-style:solid;background:var(--cx-white)}
  .rpslot b{font-size:15px;font-weight:600;color:var(--text)}
  .rpslot p,.rpempty p{max-width:56ch;margin:0;font-size:14px;line-height:1.6;
      color:var(--body-fg)}
  .rpempty h2{font-family:var(--font-display);font-weight:400;
      font-size:clamp(20px,2.4vw,28px);letter-spacing:-.01em;color:var(--text)}
  /* Sygnet CXLABS wstawiamy jako oryginalny SVG - nigdy nie składamy go
     z szewronów na ciemnej płytce, bo to podróbka znaku, nie znak. */
  .rpslotmark,.rpemptymark{display:block;width:44px;height:44px}
  .rpslotmark svg,.rpemptymark svg{width:100%;height:100%;display:block;border-radius:10px}
  .rpemptygo{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--space-3);
      margin-top:var(--space-3)}
  .rpfree{padding:4px 12px;border-radius:4px;background:var(--cx-lime);
      color:var(--cx-ink);font-size:11px;font-weight:700;letter-spacing:.05em;
      text-transform:uppercase}
  @media(max-width:620px){
    .rprow{grid-template-columns:70px minmax(0,1fr);gap:var(--space-3)}
    .rpgo{display:none}
  }

  /* ══ Oferta pierwszego zgłoszenia ═══════════════════════════════════════
     Panel stoi pod statystykami hero, nie w pasku: pierwszym ruchem na tej
     stronie jest szukanie, a zgłoszenie to krok dopiero wtedy, gdy baza nie
     wystarczy. Copy mówi o ofercie, nie o porażce - na wejściu nikt jeszcze
     nie szukał. SLA 48 godzin (decyzja Radka 18.09; makieta miała 24). */
  #view>.hero:has(.heroact)>.inner{display:flex;flex-direction:column}
  .heroact{flex:none;margin-top:clamp(22px,3vh,34px);width:100%;max-width:860px;
      margin-left:auto;margin-right:auto;
      display:flex;align-items:center;flex-wrap:wrap;gap:clamp(14px,2vw,22px);
      padding:16px 22px;background:rgba(18,32,33,.6);
      border:1px solid rgba(173,247,99,.32);border-radius:var(--radius-md);
      text-align:left}
  /* Plakietka jest etykietą, nie akcją - stąd obrys i lime tekst zamiast
     pełnego limonkowego wypełnienia, które czytało się jak drugi guzik. */
  .heroactfree{flex:none;display:grid;place-items:center;height:34px;
      padding:0 13px;border-radius:7px;background:transparent;
      border:1px solid var(--cx-lime);color:var(--cx-lime);
      font-family:var(--font-body);font-size:11.5px;font-weight:700;
      letter-spacing:.08em;text-transform:uppercase;white-space:nowrap}
  .heroacttx{flex:1;min-width:190px;display:flex;flex-direction:column;gap:3px}
  .heroacttx b{font-size:15px;font-weight:600;color:var(--cx-white);line-height:1.3}
  .heroacttx>span{font-size:13px;line-height:1.5;color:var(--cx-lime-soft)}
  .heroact .btn{flex:none}
  @media(max-width:700px){
    .heroact{gap:var(--space-3);padding:14px 16px;margin-top:clamp(20px,3vh,32px)}
  }
  @media(max-width:620px){
    .heroact{flex-direction:column;align-items:flex-start;text-align:left}
    .heroact .btn{width:100%;justify-content:center}
  }

  /* ── Podpowiedź o pierwszym zgłoszeniu ────────────────────────────────────
     Zamiast banera pod listą: kropka na guziku i dymek stylizowany na
     wiadomość, rozwijany zbliżeniem kursora. Stoi przy akcji, której dotyczy,
     i nie zajmuje miejsca, dopóki nikt na nią nie patrzy. Hosta oznacza
     skrypt, więc podpowiedź działa na każdym guziku prowadzącym do nowego
     zgłoszenia, bez wpisywania jej w markup każdego ekranu. */
  .tkhinted{position:relative}
  .tkhint-off .tkbubble{display:none!important}
  /* KROPKI JUŻ NIE MA (24.09). Była niebieska i pulsowała na rogu zielonego
     wezwania, a w portalu niebieska kropka nigdzie indziej nic nie znaczy -
     czytało się to jak powiadomienie o czymś nowym, czego tam nie było.
     Podpowiedź została i pokazuje się pod kursorem; to ona niesie treść.
     Reguły zostawiamy puste celowo: `.tkhint-off .tkdot` wyżej dotyczy
     elementu, którego skrypt już nie tworzy, a szukającemu w arkuszu
     ten komentarz tłumaczy, czemu nic nie znajdzie. */
  .tkbubble{position:absolute;top:calc(100% + 12px);right:0;z-index:70;
      display:flex;width:min(330px,80vw);padding:14px 16px;font-weight:400;
      letter-spacing:normal;white-space:normal;cursor:default;
      background:var(--cx-ink);border-radius:16px 16px 16px 4px;
      box-shadow:0 16px 40px rgba(0,0,0,.24);text-align:left;
      opacity:0;visibility:hidden;transform:translateY(-6px) scale(.97);
      transform-origin:top right;pointer-events:none;
      transition:opacity .18s ease-out,transform .18s ease-out,visibility .18s}
  /* ogonek dymka celuje w guzik */
  .tkbubble::before{content:"";position:absolute;top:-5px;right:22px;
      width:12px;height:12px;background:var(--cx-ink);transform:rotate(45deg)}
  .tkhinted:hover .tkbubble,.tkhinted:focus-within .tkbubble{
      opacity:1;visibility:visible;transform:translateY(0) scale(1);
      pointer-events:auto}
  .tkbubtx{display:flex;flex-direction:column;gap:4px;min-width:0;
      font-family:var(--font-body)}
  .tkbubtx b{font-size:13.5px;font-weight:600;line-height:1.3;color:var(--cx-white)}
  .tkbubtx span{font-size:12.5px;line-height:1.5;color:var(--cx-lime-soft)}
  @media(prefers-reduced-motion:reduce){
    .tkbubble{transition:opacity .01s}
  }
  @media(max-width:620px){
    .tkbubble{right:auto;left:0;transform-origin:top left;
        border-radius:16px 16px 4px 16px}
    .tkbubble::before{right:auto;left:22px}
  }
  /* Wezwanie STOI W PASKU TAKŻE NA STRONIE GŁÓWNEJ (polecenie Radka 1.10:
     „skoro pomoc zniknęła z headera, to dajemy guzik nowe zgłoszenie").
     Do tego dnia chowała je reguła `body[data-trasa="hub"] .nav__cta
     {display:none}` powyżej 901 px - ofertę niósł panel w hero i dwa te same
     guziki obok siebie dublowały przekaz. Pasek miał wtedy cztery pozycje;
     po zdjęciu Pomocy została w nim dziura i wezwanie ma gdzie stanąć.
     Dublowania już nie ma z drugiego powodu: guzik w hero prowadzi dziś
     tam, gdzie człowiek naprawdę zaczyna (rejestracja albo kreator),
     a nie zawsze na ten sam formularz co ten w pasku. */
  /* Na ekranach konta wezwanie schodzi na każdej szerokości - z formularza
     logowania nie ma dokąd nim iść. */
  body[data-trasa="auth"] .nav__cta,
  body[data-trasa="auth"] .navsheet__cta{display:none}

  /* ══ Menu na telefonie ════════════════════════════════════════════════════
     Pasek nie mieści sześciu pozycji na wąskim ekranie - wcześniej rozlewał
     się na dwa rzędy i zjadał pół ekranu. Teraz jest jedna limonkowa pigułka
     „Menu" ze znakiem CXLABS w ciemnym kwadracie, tak jak na cxlabs.digital,
     a pod nią pełnoekranowa płachta.

     UWAGA: makieta z 17.09 ma w tym miejscu gołą ikonę burgera. Nie wchodzi -
     menu ma być 1:1 z cxlabs.digital (decyzja Radka, 18.09).

     Wymiary są ZMIERZONE na cxlabs.digital (29.09, prośba Radka „dopasuj tak,
     żeby był identyczny"), a nie dobrane na oko: `.navbar_menu-button-content`
     ma tam 4px odstępu wokół ciemnego kwadratu i 20px z lewej, 16px przerwy,
     zaokrąglenie 12px i tekst 16/24 w grubości ZWYKŁEJ. Wysokości nie ustawiamy
     wcale - bierze się z kwadratu (32px) i odstępu, czyli 40px, dokładnie jak
     tam. Nasza wersja była o 4px wyższa, zaokrąglona do pigułki i pisana
     półgrubo, i to ta grubość rzucała się w oczy najbardziej. */
  .navpill{display:none;align-items:center;gap:16px;padding:4px 4px 4px 20px;
      background:var(--cx-lime);border:0;border-radius:12px;cursor:pointer;
      font-family:var(--font-body);font-size:16px;font-weight:400;line-height:24px;
      color:var(--cx-ink)}
  .navpill__ic{display:grid;place-items:center;width:32px;height:32px;border-radius:8px;
      background:var(--cx-ink);color:var(--cx-lime)}
  .navpill__ic svg{width:21px;height:21px}
  /* Napis w pigułce ma stałą szerokość - tyle, ile zajmuje DŁUŻSZY z dwóch
     wyrazów. Zmierzone przy 390 px: „Menu" 41,2 px, „Zamknij" 55,7 px, czyli
     pigułka rosła o 14,5 px przy otwarciu menu i ciągnęła za sobą znak.
     Szerokość bierzemy z samego napisu, a nie z wpisanej liczby pikseli:
     `::after` niesie dłuższy wyraz, siedzi w drugim wierszu siatki o zerowej
     wysokości i jest niewidoczny, więc nie widać go ani okiem, ani czytnikiem
     ekranu - a siatka i tak musi się do niego zmieścić. Przy zmianie napisu
     wystarczy poprawić tę jedną stałą; przy zmianie kroju pisma nie trzeba nic,
     bo miara liczy się sama.
     Wysokości, odstępów ani zaokrąglenia to NIE RUSZA - te są zmierzone
     1:1 z cxlabs.digital i pilnuje ich `scripts/proba_pigulki.py`. */
  .navpill__txt{display:grid;justify-items:start}
  .navpill__txt::after{content:"Zamknij";height:0;overflow:hidden;
      visibility:hidden;white-space:nowrap;pointer-events:none}
  /* Boczny odstęp płachty jest TEN SAM, co w pasku (`var(--space-6)` na
     `.navin`) - zgłoszenie Radka 1.10: „na mobilce szerokość guzika menu
     rozwiniętego i zwiniętego jest inna, przez co przeskakuje logo na boki".
     Zmierzone przy 390 px przed poprawką: znak stał na 32 px w pasku i na
     24 px w płachcie, więc po otwarciu menu przeskakiwał o 8 px w lewo.
     Druga połowa tego skoku siedziała w szerokości samej pigułki - patrz
     `.navpill__txt` niżej. */
  .navsheet{position:fixed;inset:0;z-index:300;background:var(--cx-ink);
      overflow-y:auto;-webkit-overflow-scrolling:touch;
      padding:0 var(--space-6) calc(var(--space-6) + env(safe-area-inset-bottom))}
  .navsheet[hidden]{display:none}
  .navsheet__head{position:sticky;top:0;z-index:1;display:flex;align-items:center;
      justify-content:space-between;gap:var(--space-4);
      padding:clamp(14px,2.4vh,20px) 0;background:var(--cx-ink)}
  /* Pasek ma regułę `order` dla znaku (układ dwurzędowy sprzed zmiany) -
     w płachcie kolejność ma być zwyczajna: znak z lewej, pigułka z prawej. */
  .navsheet__head>*{order:0}
  /* Pozycje są duże i luźne - to ekran do kciuka, nie pasek nawigacji. */
  .navsheet__links{list-style:none;display:flex;flex-direction:column;
      margin:var(--space-3) 0 0;border-top:1px solid var(--cx-ink-60)}
  .navsheet__links>li{border-bottom:1px solid var(--cx-ink-60)}
  .navsheet__links a,.navsheet__links summary{display:flex;align-items:center;gap:12px;
      padding:16px 2px;font-family:var(--font-display);font-weight:400;font-size:21px;
      line-height:1.2;color:var(--cx-white);cursor:pointer}
  .navsheet__links a:hover,.navsheet__links summary:hover{color:var(--cx-lime)}
  .navsheet__links .navico{width:17px;height:16px;color:var(--cx-lime)}
  .navsheet__links summary{list-style:none;justify-content:space-between}
  .navsheet__links summary::-webkit-details-marker{display:none}
  .navsheet__links summary svg{width:18px;height:18px;color:var(--cx-ink-20);
      transition:transform .18s ease}
  .navsheet__links details[open] summary svg{transform:rotate(180deg)}
  /* Produkty: te same kafle co w rozwijanym menu na dużym ekranie,
     tylko jeden pod drugim. */
  .navsheet__prods{display:flex;flex-direction:column;gap:2px;padding:0 0 var(--space-4)}
  .navsheet__prods .navprod{display:flex;align-items:center;gap:12px;padding:10px 0;
      color:var(--cx-mist)}
  .navsheet__prods .navprodic{width:34px;height:34px;flex:none;display:grid;place-items:center;
      border-radius:9px;background:rgba(255,255,255,.06);overflow:hidden}
  .navsheet__prods .prodico{width:26px;height:26px;object-fit:contain}
  .navsheet__prods .navprodtx{display:flex;flex-direction:column;gap:1px;min-width:0}
  .navsheet__prods .navprodtx b{font-size:14.5px;font-weight:600;color:var(--cx-white)}
  .navsheet__prods .navprodtx span{font-size:12px;color:var(--cx-ink-20)}
  .navsheet__prods .navrow--has .navprod{opacity:1}
  /* Konto i wezwanie na dole - tam, gdzie kciuk. */
  .navsheet__konto{margin-top:var(--space-4);display:flex;flex-direction:column;gap:2px}
  .navsheet__kto{display:flex;align-items:center;gap:12px;margin-bottom:var(--space-3)}
  .navsheet__kto .navavatar{width:40px;height:40px;border-radius:12px;font-size:14px}
  .navsheet__ktotx{display:flex;flex-direction:column;min-width:0}
  .navsheet__ktotx b{font-size:15px;color:var(--cx-white);font-weight:600}
  .navsheet__ktotx span{font-size:12.5px;color:var(--cx-ink-20);overflow:hidden;
      text-overflow:ellipsis;white-space:nowrap}
  .navsheet__konto a,.navsheet__konto button{display:flex;align-items:center;gap:11px;
      padding:13px 2px;background:none;border:0;font:inherit;font-size:15px;
      color:var(--cx-mist);text-align:left;cursor:pointer}
  .navsheet__konto a:hover,.navsheet__konto button:hover{color:var(--cx-lime)}
  .navsheet__konto svg{width:17px;height:17px;flex:none;color:var(--cx-ink-20)}
  .navsheet__cta{display:flex;align-items:center;justify-content:center;gap:10px;
      margin-top:var(--space-5);width:100%;padding:16px;background:var(--cx-lime);
      border-radius:999px;font-weight:600;font-size:16px;color:var(--cx-ink)}
  .navsheet__cta svg{width:18px;height:18px}
  /* Płachta zastępuje dawny układ „dwa rzędy": na wąskim ekranie pasek ma
     tylko znak i pigułkę. */
  @media(max-width:900px){
    /* `order:1` na znaku zostało po układzie dwurzędowym - pigułka musi iść
       za nim, inaczej ląduje po lewej. */
    .navpill{display:inline-flex;order:3;margin-left:auto}
    .nav__links{display:none}
    .nav__right{display:none}
    .navin{flex-wrap:nowrap;row-gap:0}
  }
  @media(min-width:901px){
    .navsheet{display:none}
  }

  /* ── Pasek przyklejony na telefonie (prośba Radka 29.09) ─────────────────
     Do 29.09 pasek zjeżdżał z treścią i nie wracał: po dwóch ekranach
     przewijania jedyną drogą do menu było przewinięcie strony na samą górę.
     Teraz wraca sam - ale dopiero PO scenie hero, żeby nie zabierać jej
     kawałka ekranu; stany opisuje `oceniPasek()` w szkielecie.

     `position:sticky`, nie `fixed`: sticky zostawia pasek w układzie strony,
     więc przełączenie stanu nie zmienia wysokości niczego i treść pod spodem
     nie podskakuje. Selektor musi być `body>header.nav` - samo `header.nav`
     wyżej ma `position:relative` i tej samej mocy reguła by go nie przebiła.

     `--chrome` (wysokość paska nad treścią) liczy `initDeck` z położenia
     #view i nie zmienia się od przyklejenia, bo sticky nie wychodzi z układu. */
  @media(max-width:900px){
    body>header.nav{position:sticky;top:0;z-index:60;
        transition:transform .26s ease,background-color .26s ease,
                   border-color .26s ease}
    /* w trakcie sceny hero - poza kadr, razem z cieniem i dotykiem */
    html.paseknad body>header.nav{transform:translateY(-100%);pointer-events:none}
    /* po scenie - wraca na szkle, żeby napisy nie wpadały w treść pod spodem */
    html.paseklepki body>header.nav{background:var(--header-bg);
        backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
        border-bottom:1px solid var(--cx-ink-60)}
    /* Płachta menu ma z-index 300 i zasłania pasek - to celowe: gdy jest
       otwarta, pod spodem nie ma czego pokazywać. */
    @media(prefers-reduced-motion:reduce){
      body>header.nav{transition:none}
    }
  }

  /* ── Guziki: zgubiony znak i odstęp z prawej ─────────────────────────────
     Dwie wady tej samej rodziny, obie z przeniesienia makiety na portal.

     1. `.btnic` nigdy nie dostało reguły bazowej. Z makiety przyjechały same
        warianty - `.btn--tk .btnic--pre`, `.nav__cta .btnic--pre`
        i `.pltier .btn--ghost .btnic` - więc wszędzie indziej SVG w środku
        nie miał wymiaru i schodził do zera. Znak po prostu znikał:
        nad listą zgłoszeń, na kaflach planów i na ekranie rozliczenia.

     2. `.btn` ma z prawej 3px, bo tam siedzi ciemna płytka `.chev` dociśnięta
        do krawędzi. Guziki bez płytki - a to większość: „Anuluj", „Zapisz
        zmiany", „Wyślij zgłoszenie", „Dalej" - dziedziczyły te 3px i napis
        dotykał krawędzi. Przy dłuższej treści („Umów spotkanie") wychodził
        poza nią. Tam, gdzie płytki nie ma, odstęp z prawej równa się lewemu.
        `:not(:has(.chev))` sprawdza to na guziku, a nie na liście nazw -
        nowy guzik bez płytki dostanie poprawny odstęp bez dopisywania reguły. */
  .btnic{display:inline-flex;align-items:center;justify-content:center;flex:none;
      line-height:0}
  .btnic svg{display:block;width:17px;height:17px}
  .btn:not(:has(.chev)):not(.btn--tk):not(.btn--ghost){padding-right:18px}

  /* ── `hidden` ma wygrywać z arkuszem ─────────────────────────────────────
     Atrybut `hidden` gasi element regułą przeglądarki `[hidden]{display:none}`,
     ale wystarczy WŁASNA reguła z `display`, żeby ją przebić - i element wraca
     na ekran mimo atrybutu. Tak przepadła nakładka logowania Google: miała
     `hidden`, a `.authwait{display:grid}` odsłaniało ją nad formularzem, więc
     ekran logowania był zasłonięty ciemną płachtą i nie dało się zalogować.
     Tym samym mechanizmem świecił pasek sekcji `.rail` na wszystkich trasach
     panelu, gdzie jest zbędny.

     Zamiast dopisywać `[hidden]` do każdej reguły z osobna, domykamy to raz.
     `!important` jest tu na miejscu: `hidden` znaczy „nie ma tego na ekranie"
     i nic w arkuszu nie ma prawa tego podważyć. */
  [hidden]{display:none!important}

  /* ── Pasek „Zaufali nam" ─────────────────────────────────────────────────
     Pasmo w tym samym tuszu co sasiednie sekcje. Wyzsze niz zwykle, bo znaki
     potrzebuja powietrza. Naglowek chodzi na tym samym `.hubhead` co
     „Produkty" i „Najczesciej czytane", zeby nie wypadal z rytmu strony. */
  #view>.band--klienci{min-height:0;display:block;background:var(--cx-ink);
      padding:clamp(56px,8vh,92px) 0;scroll-snap-align:none;box-shadow:none}
  .klhead{margin-bottom:clamp(30px,4.5vh,48px)}
  .klpas{--kl-czas:34s;display:flex;width:100%;overflow:hidden;
      mask-image:linear-gradient(90deg,transparent,#000 90px,
          #000 calc(100% - 90px),transparent);
      -webkit-mask-image:linear-gradient(90deg,transparent,#000 90px,
          #000 calc(100% - 90px),transparent)}
  .kltor{flex:none;display:flex;align-items:center;gap:clamp(64px,9vw,128px);
      padding-right:clamp(64px,9vw,128px);
      animation:klJedzie var(--kl-czas) linear infinite}
  .klpas:hover .kltor{animation-play-state:paused}
  @keyframes klJedzie{to{transform:translateX(-100%)}}
  /* Znaki maja ROWNA WYSOKOSC, nie rowna szerokosc: kafelek dopasowuje sie
     do proporcji znaku (`width:auto`), wiec zaden nie jest scisniety ani
     rozdety, a rzad czyta sie jako jedna linia. Przygaszone do jednego
     poziomu, pelna jasnosc pod kursorem. */
  .klslot{flex:none;height:46px;display:block;opacity:.55;
      transition:opacity .2s ease}
  .klslot:hover{opacity:1}
  .klslot img{display:block;height:100%;width:auto;object-fit:contain}
  @media(prefers-reduced-motion:reduce){
    .kltor{animation:none}
    .klpas{overflow-x:auto}
  }

  /* ---------- dymek własny ----------
     Zastępuje natywny `title`: tamten pokazuje się po sekundzie i rysuje go
     system, więc ani nie zdąży, ani nie udźwignie rozpisanego rachunku.
     Ten wchodzi natychmiast (bez `transition-delay`), trzyma szerokość na
     tyle dużą, żeby liczby nie łamały się w połowie, i szanuje `white-space:
     pre-line` - dzięki temu każda pozycja rachunku stoi w swoim wierszu. */
  .dymek{position:fixed;top:0;left:0;z-index:120;max-width:min(360px,calc(100vw - 24px));
      padding:9px 12px;border-radius:10px;background:var(--cx-ink);color:#fff;
      font-size:12.5px;line-height:1.5;white-space:pre-line;
      box-shadow:0 10px 30px rgba(18,32,33,.28);
      opacity:0;visibility:hidden;pointer-events:none;
      transition:opacity .09s ease}
  .dymek.is-on{opacity:1;visibility:visible}
  /* Nagłówek wielolinijkowego dymka. `::first-line` tu nie wystarczał:
     przy dymku jednolinijkowym barwił CAŁĄ treść, więc podpis guzika świecił
     tak samo jak nagłówek rachunku. */
  .dymektyt{color:var(--cx-lime);font-weight:600}
  @media(prefers-reduced-motion:reduce){ .dymek{transition:none} }

  /* ── Sceny tła hero (paczka 23.09, initHeroFx w szablonie) ──────────────
     Hero rośnie o pas .herofx-run, a scena .herofx-pin stoi przyklejona -
     przewijanie tego pasa jest całym sterowaniem animacji.
     `overflow:clip` zamiast `hidden`: hidden robi z hero kontener
     przewijania i `sticky` przestaje działać. Selektory przez #view,
     bo reguły #view>.hero biją same klasy. */
  #view>.hero.hero--fx{display:block;min-height:0;padding:0;overflow:clip;
      background:var(--cx-ink);scroll-snap-align:start}
  #view>.hero.hero--fx .herofx-pin{position:sticky;top:0;min-height:100svh;
      display:flex;flex-direction:column;justify-content:center;overflow:hidden;
      padding:clamp(24px,4vh,56px) 0 clamp(40px,6vh,80px);
      background:radial-gradient(ellipse 120% 90% at 50% 34%,rgb(36,58,58) 0%,var(--cx-ink) 72%)}
  #view>.hero.hero--fx .herofx-run{height:95svh}
  #view>.hero.hero--fx .inner{will-change:opacity,transform}
  .herofx{position:absolute;inset:0;width:100%;height:100%;z-index:0;pointer-events:none}
  .herofx-cap{position:absolute;left:0;right:0;bottom:clamp(40px,9vh,96px);z-index:1;margin:0;
      padding:0 var(--space-6);text-align:center;opacity:0;pointer-events:none;
      font-family:var(--font-display);font-weight:400;letter-spacing:-.01em;line-height:1.2;
      font-size:clamp(22px,2.8vw,34px);color:var(--cx-white);text-wrap:balance}
  @media(max-width:700px){
    #view>.hero.hero--fx{padding:0}
    #view>.hero.hero--fx .herofx-pin{padding:clamp(44px,7vh,72px) 0}
    #view>.hero.hero--fx .herofx-run{height:80svh}
    .herofx-cap{padding:0 var(--space-5);bottom:clamp(32px,7vh,64px)}
  }
  /* bez ruchu: klasa hero--fx znika w skrypcie, ale scena zostaje w DOM */
  @media(prefers-reduced-motion:reduce){.herofx-cap{display:none}}

  /* Sygnet w hero strony głównej, na miejscu dawnego napisu nad nagłówkiem.
     Selektor przez `#view`, bo reguły `#view>.hero` biją same klasy.
     `aspect-ratio` trzyma kwadrat, gdy `clamp` zmienia szerokość.
     W środku siedzi wyłącznie kanwa modelu 3D - `perspective` została,
     bo cień pod kołem dalej liczy się w przestrzeni. */
  #view .hero .herosyg{position:relative;display:block;width:clamp(184px,16.5vw,216px);aspect-ratio:1;
      margin:0 auto 24px;perspective:780px}
  /* Koło można obracać palcem, więc przechwytuje dotyk: bez `touch-action`
     przeglądarka zabrałaby ruch na przewijanie strony. Kursor mówi, że da
     się je złapać. */
  /* `user-select` i `touch-callout` na zero: na iOS dłuższe przytrzymanie
     palca na kanwie otwiera menu obrazka albo zaczyna zaznaczanie, a to
     przerywa obracanie zdarzeniem `pointercancel` w połowie gestu. */
  #view .hero .herosyg{touch-action:none;cursor:grab;
    -webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
  #view .hero .herosyg--ciagniety{cursor:grabbing}
  /* Kanwa modelu. Zaczyna przezroczysta i pojawia się dopiero z klasą
     `herosyg--3d`, czyli po wczytaniu sceny - inaczej przez ułamek sekundy
     widać byłoby pusty prostokąt, zanim padnie pierwsza klatka. */
  #view .hero .herosyg3d{position:absolute;inset:0;z-index:1;display:block;
      width:100%;height:100%;opacity:0;transition:opacity .45s ease}
  #view .hero .herosyg--3d .herosyg3d{opacity:1}
  /* Sceny nie da się uruchomić (brak WebGL-a, oszczędzanie danych, błąd
     wczytywania): chowamy CAŁY element razem z miejscem, które zajmował.
     Dziura po nim wyglądałaby na usterkę, a sygnet jest ozdobą - hero
     bez niego jest po prostu ciaśniejsze. */
  #view .hero .herosyg--brak{display:none}
  @media(prefers-reduced-motion:reduce){
    #view .hero .herosyg3d{transition:none}
  }

  #view .hero .herosyg-shadow{position:absolute;left:14%;right:14%;bottom:-6%;height:16%;z-index:0;
      border-radius:50%;background:radial-gradient(closest-side,rgba(0,0,0,.45),rgba(0,0,0,0));
      filter:blur(4px);will-change:transform}
  /* „monday.com" w podtytule hero na biało i półgrubo - nazwa produktu ma
     wyjść z akapitu, bo to o niej jest cały portal. */
  .hero p.sub strong{font-weight:600;color:var(--cx-white)}

  /* ── Panel CXLABS: rozdroże ─────────────────────────────────────────── */
  /* Kafle narzędzi wewnętrznych. Kafel „w budowie" wygląda inaczej i NIE jest
     odsyłaczem - obietnica bez adresu jest gorsza niż uczciwe „jeszcze nie ma". */
  .admsiatka{display:grid;gap:var(--space-3);margin:var(--space-5) 0 var(--space-6);
      grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
  .admkafel{display:flex;flex-direction:column;gap:7px;padding:var(--space-4);
      border-radius:14px;background:var(--cx-white);border:1px solid var(--line);
      color:var(--body-fg);text-decoration:none;transition:all .16s ease}
  a.admkafel:hover{border-color:var(--cx-green-500);transform:translateY(-2px);
      box-shadow:0 8px 24px rgba(18,32,33,.08)}
  .admkafel__ic{display:grid;place-items:center;width:42px;height:42px;
      border-radius:11px;background:var(--cx-mist);color:var(--cx-green-600)}
  .admkafel__ic svg{display:block}
  .admkafel b{display:flex;align-items:center;gap:8px;font-size:17px;font-weight:700}
  .admkafel__op{font-size:13px;line-height:1.5;color:var(--soft)}
  .admkafel--wbudowie{opacity:.72;cursor:default}
  .admkafel--wbudowie .admkafel__ic{color:var(--soft)}
  .admznak{font-style:normal;font-size:11px;font-weight:600;letter-spacing:.04em;
      text-transform:uppercase;color:var(--soft);background:var(--cx-mist);
      border-radius:999px;padding:3px 9px}

  /* ── Produkt jeszcze nieotwarty („Wkrótce") ──────────────────────────
     Ta sama zasada, co przy kaflu „w budowie" w panelu: kafel stoi, ale NIE
     jest odsyłaczem, więc nie może wyglądać na klikalny. Zdejmujemy podnoszenie
     po najechaniu i kursor-rękę, przygaszamy znak produktu, a w miejscu
     „Przejdź" stoi pastylka z napisem. Sam kafel zostaje pełnej jasności -
     przygaszenie całości czytałoby się jak błąd wczytywania, a nie jak
     zapowiedź. */
  .app--wkrotce,.app--wkrotce:hover,.app--wkrotce:focus-within{
      transform:none;box-shadow:none;cursor:default}
  .app--wkrotce .appmain{cursor:default}
  /* Wyszarzenie CAŁEGO kafla, nie samego znaku: kategoria ma czytać się jako
     niedostępna od pierwszego spojrzenia, zanim ktokolwiek dojdzie do napisu.
     Pastylce oddajemy pełne krycie z powrotem - to jedyna informacja na kaflu
     i nie może gasnąć razem z resztą. */
  .app--wkrotce .appmain{opacity:.45;filter:grayscale(1)}
  .app--wkrotce .wkrznak{opacity:1;filter:none}
  /* Napis stoi przy TYTULE, a nie w stopce kafla: stopka („Przejdź") znika
     w połowie szerokości ekranu i zapowiedź razem z nią, a to jedyne miejsce,
     które mówi, dlaczego kafel nie prowadzi nigdzie. */
  .wkrznak{font-style:normal;font-size:10.5px;font-weight:600;letter-spacing:.06em;
      text-transform:uppercase;white-space:nowrap;vertical-align:middle;
      color:var(--cx-ink-20);background:rgba(255,255,255,.08);
      border:1px solid rgba(255,255,255,.16);border-radius:999px;padding:2px 8px}
  .band--light .wkrznak{color:var(--soft);background:var(--cx-mist);
      border-color:var(--line2)}

  /* To samo w rozwijanym menu paska: wiersz bez odsyłacza i bez strzałki. */
  .navprod--wkrotce{cursor:default}
  .navrow--wkrotce:hover>.navprod--wkrotce{background-color:transparent}
  .navprod--wkrotce .navprodic{opacity:.55}
  .navprod--wkrotce .navprodtx b{color:var(--cx-ink-20)}
  .navwkr{flex:none;font-size:10.5px;font-weight:600;letter-spacing:.06em;
      text-transform:uppercase;color:var(--cx-ink-20);
      background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.16);
      border-radius:999px;padding:2px 9px}

  /* Adres obok nazwy konta na ekranie „Użytkownicy". Nazwa jest kluczem
     (stoi w kolumnie „Zlecił"), ale to po adresie człowiek rozpoznaje osobę -
     „kso" nic nie mówi, „kso@cxlabs.digital" już tak. */
  .uzmail{font-style:normal;font-weight:400;font-size:12.5px;color:var(--soft)}
  @media (max-width:640px){
    /* Na telefonie wiersz i tak się łamie - adres schodzi pod nazwę zamiast
       ściskać obie części do nieczytelności. */
    .uzimie{flex-wrap:wrap;gap:0 var(--space-2)}
    .uzmail{flex-basis:100%}
  }

  /* ── Widok kategorii / produktu: lista artykułów (paczka 25.09) ────────
     Cała sekcja na białym tle. Grupa = nagłówek Clash + plakietka z liczbą,
     wiersz = tytuł 20 px, opis w dwóch liniach, data pod opisem, strzałka
     w płytce po prawej. Bez kresek między wierszami: rytm robi odstęp,
     hover to płytka w kolorze --cx-mist (dawne tło sekcji).
     Zakres przez :has(.kbmain .arts), żeby nie ruszać konta, rozliczenia
     i artykułu, które też stoją na .kb. Wyniki wyszukiwania stoją na
     `.arts#grid` POZA `.kbmain` i zostają po staremu. */
  #view>.kb:has(.kbmain .arts){background:var(--cx-white);padding-top:clamp(40px,5vw,64px)}
  #view .kbmain .secgroup{margin-top:clamp(40px,5vw,64px);scroll-margin-top:96px}
  #view .kbmain .secgroup:first-child{margin-top:0}
  #view .kbmain .secgroup-head{display:flex;align-items:center;gap:12px;margin:0 0 16px;
      padding:0 0 16px;border-bottom:1px solid var(--cx-cloud)}
  #view .kbmain .secgroup-head h3{margin:0;font-family:var(--font-display);font-weight:400;
      font-size:28px;line-height:1.2;letter-spacing:-.01em;color:var(--cx-ink)}
  #view .kbmain .secgroup-count{display:inline-flex;align-items:center;height:26px;padding:0 10px;
      border-radius:8px;background:var(--cx-mist);color:var(--cx-ink-80);
      font-size:13px;font-weight:500;letter-spacing:0;text-transform:none;white-space:nowrap}
  #view .kbmain .arts{display:flex;flex-direction:column;gap:4px;margin:0 -16px}
  #view .kbmain .artrow{display:grid;grid-template-columns:minmax(0,1fr) auto;
      grid-template-areas:"main go" "date go";column-gap:24px;row-gap:8px;align-items:center;
      padding:16px;border:0;border-left:0;border-radius:12px;background:none;
      transition:background .15s ease}
  #view .kbmain .artrow:hover{background:var(--cx-mist)}
  #view .kbmain .artmain{grid-area:main;gap:6px}
  #view .kbmain .arttitle{font-size:20px;font-weight:600;line-height:1.35;color:var(--cx-ink)}
  #view .kbmain .artrow:hover .arttitle{color:var(--cx-ink)}
  #view .kbmain .artlede{font-size:15px;line-height:1.55;color:rgb(88,110,112);-webkit-line-clamp:2}
  #view .kbmain .artrow .artdate{grid-area:date;order:0;font-size:13px;color:var(--cx-ink-40);
      font-variant-numeric:tabular-nums;text-align:left}
  /* „Czytaj dalej" zostaje jako strzałka w płytce: tekst powtarzał się 93 razy */
  #view .kbmain .arts .readgo{grid-area:go;width:40px;height:40px;padding:0;gap:0;justify-content:center;
      border-radius:8px;background:none;border:1px solid var(--cx-cloud);color:var(--cx-ink);
      font-size:0;transition:background .15s ease,border-color .15s ease,color .15s ease}
  #view .kbmain .arts .readgo svg{width:16px;height:16px;transition:transform .15s ease}
  /* !important, bo starsza reguła .artrow:hover .readgo zeruje tło -
     bez tego limonkowa strzałka stałaby na jasnym tle i znikała */
  #view .kbmain .artrow:hover .readgo{background:var(--cx-ink)!important;border-color:var(--cx-ink);color:var(--cx-lime)}
  #view .kbmain .artrow:hover .readgo svg{transform:translateX(1px)}
  #view .kbmain .artrow:focus-visible{outline:2px solid var(--cx-ink);outline-offset:-2px}
  @media(max-width:760px){
    #view .kbmain .arts{margin:0 -12px}
    #view .kbmain .artrow{padding:14px 12px;column-gap:12px}
    #view .kbmain .secgroup-head h3{font-size:24px}
    #view .kbmain .arttitle{font-size:18px}
    #view .kbmain .artlede{font-size:14px}
    #view .kbmain .arts .readgo{display:inline-flex;width:36px;height:36px}
  }
  /* spis sekcji po prawej na białym: kreska w kolorze chmury zamiast line2 */
  #view>.kb:has(.kbmain .arts) .secnavlist{border-left-color:var(--cx-cloud)}

  /* zwijanie grup (buildCollapse w szkielecie): cały nagłówek jest celem
     kliknięcia, płytka ze strzałką po prawej niesie stan dla czytnika ekranu */
  #view .kbmain .secgroup-head:has(.secgroup-tog){cursor:pointer;user-select:none}
  #view .kbmain .secgroup-tog{margin-left:auto;flex:none;width:36px;height:36px;padding:0;
      display:grid;place-items:center;border-radius:8px;border:1px solid var(--cx-cloud);
      background:var(--cx-white);color:var(--cx-ink);cursor:pointer;
      transition:background .15s ease,border-color .15s ease}
  #view .kbmain .secgroup-tog svg{width:16px;height:16px;transition:transform .2s ease}
  #view .kbmain .secgroup-head:hover .secgroup-tog{background:var(--cx-mist);border-color:var(--cx-cloud-2)}
  #view .kbmain .secgroup-tog:focus-visible{outline:2px solid var(--cx-ink);outline-offset:2px}
  #view .kbmain .secgroup.is-zw .secgroup-tog svg{transform:rotate(-90deg)}
  #view .kbmain .secgroup.is-zw .arts{display:none}
  #view .kbmain .secgroup.is-zw .secgroup-head{margin-bottom:0}
  #view .kbmain .secgroup.is-zw + .secgroup{margin-top:24px}

  /* Ekran nieistniejącego adresu: dwa wyjścia obok siebie, na wąskim ekranie
     jedno pod drugim. Korzysta z gotowego bloku `.noresults`, więc rysunek
     i typografia są te same co przy braku wyników wyszukiwania. */
  .err404akcje{display:flex;flex-wrap:wrap;gap:var(--space-3);
      justify-content:center;margin-top:var(--space-5)}
  .noresults code{font-size:.92em;padding:2px 7px;border-radius:6px;
      background:var(--cx-mist);color:var(--cx-ink);word-break:break-all}
  @media(max-width:520px){
    .err404akcje{flex-direction:column;align-items:stretch}
    .err404akcje .btn{justify-content:center}
  }

  /* === serpentyny (#140) ===
     Pokazują się raz, na ekranie „dane firmy zapisane", i same znikają po
     dwóch sekundach. Leżą NAD oknem kreatora, ale bez przechwytywania
     kliknięć - guzik pod spodem działa przez cały czas ich lotu.
     Wyłączone przy `prefers-reduced-motion`: fruwające obiekty to dokładnie
     ten ruch, dla którego ktoś to ustawienie włącza. Ekran mówi to samo
     słowami, więc nic nie ginie. */
  .konfetti{position:absolute;inset:0;overflow:hidden;pointer-events:none;
    border-radius:inherit;z-index:3}
  .konfetti i{position:absolute;top:-24px;display:block;border-radius:2px;
    opacity:0;animation-name:konfettiSpada;animation-timing-function:cubic-bezier(.25,.6,.4,1);
    animation-fill-mode:forwards}
  @keyframes konfettiSpada{
    0%{opacity:0;transform:translateY(0) rotate(0deg)}
    12%{opacity:1}
    100%{opacity:0;transform:translateY(420px) rotate(540deg)}
  }
  @media(prefers-reduced-motion:reduce){ .konfetti{display:none} }

  /* === zgoda na telefon zapoznawczy (kreator firmy, ostatni krok) ===
     Oddzielona ramką od podsumowania: to nie jest kolejne pole formularza,
     tylko osobna decyzja, którą człowiek podejmuje świadomie. */
  .krzgoda{margin-top:var(--space-5);padding:var(--space-4);
    border:1px solid var(--cx-cloud);border-radius:var(--radius-md);
    background:var(--cx-mist)}
  .krzgodanag{font-family:var(--font-display);font-weight:500;font-size:15px;
    margin:0 0 var(--space-3)}
  .krzgoda .authchk{align-items:flex-start}
  .krzgoda .fld{margin-top:var(--space-4)}
  /* Zachęta: nasza rada, nie część zgody. Ma być czytelniejsza od drobnego
     druku, ale wyraźnie cichsza od zdania, które człowiek zaznacza - inaczej
     zaczyna wyglądać jak warunek, a zgoda pod presją nie jest zgodą. */
  .krzgodazach{margin:var(--space-3) 0 0;font-size:13.5px;line-height:1.55;
    color:var(--cx-ink-30)}
  .krzgodabrak{margin:var(--space-3) 0 0;font-size:13px;line-height:1.5;
    padding:9px 12px;border-radius:var(--radius-sm);background:var(--cx-white);
    border:1px solid var(--cx-cloud)}
  .krzgodatx{margin:var(--space-3) 0 0;font-size:12.5px;line-height:1.5;
    color:var(--cx-ink-10)}
  .krzgodatx a{color:inherit;text-decoration:underline}

  /* ── baner cookies ───────────────────────────────────────────────────────
     Wariant „Pasek dolny" 1a z paczki Claude Design
     (`design/handoffy/2026-09-29_baner-cookies-1a/`). Nazwy klas i wymiary
     zostają z makiety, żeby dało się ją przyłożyć do wdrożenia i porównać.

     `z-index` 1000 jest NAD wszystkim, co portal ma dziś na wierzchu
     (najwyższe to 300 - ciemna płachta pod modalem). Pasek musi być widoczny
     także na ekranie logowania i w kreatorze, bo dotyczy całej strony. */
  .ck{position:fixed;left:0;right:0;bottom:0;z-index:1000;background:var(--cx-ink);
      border-top:1px solid var(--cx-ink-60);box-shadow:0 -16px 40px rgba(0,0,0,.18);
      color:var(--cx-lime-soft);font-family:var(--font-body);
      padding-bottom:env(safe-area-inset-bottom);animation:ck-in .2s ease-out}
  @keyframes ck-in{from{transform:translateY(100%)}to{transform:none}}
  .ck[hidden],.ck__set[hidden],.ck__cat[hidden],.ck__ghost[hidden]{display:none}
  .ck__in{max-width:1440px;margin:0 auto;padding:20px 64px;
      display:flex;flex-direction:column;gap:20px}
  .ck__row{display:flex;align-items:center;gap:24px}
  .ck__txt{margin:0;flex:1;min-width:0;font-size:14px;line-height:1.55;text-wrap:pretty}
  .ck__txt a{color:var(--cx-lime)}
  .ck__txt a:hover{color:var(--cx-white)}
  .ck__act{display:flex;align-items:center;gap:8px;flex:none}
  /* „Edytuj ustawienia" / „Zapisz wybór" - sam tekst, bez ramki. Odstępy
     zostają symetryczne, żeby pole kliknięcia miało 40 px (na telefonie 48). */
  .ck__ghost{height:40px;padding:0 16px;border-radius:12px;border:0;background:none;
      color:var(--cx-white);font:inherit;font-size:14px;font-weight:500;cursor:pointer;
      white-space:nowrap;text-decoration:underline;text-underline-offset:3px;
      text-decoration-color:rgba(219,236,233,.5);transition:text-decoration-color .15s ease}
  .ck__ghost:hover{text-decoration-color:currentColor}
  /* Główny guzik: limonka z ciemną płytką szewronu, stąd niesymetryczny
     odstęp 4px 4px 4px 20px - płytka ma swój własny margines w środku. */
  .ck__ok{display:inline-flex;align-items:center;gap:12px;height:40px;
      padding:4px 4px 4px 20px;border-radius:12px;border:0;background:var(--cx-lime);
      color:var(--cx-ink);font:inherit;font-size:14px;font-weight:600;cursor:pointer;
      white-space:nowrap;transition:filter .15s ease,transform .15s ease}
  .ck__ok:hover{filter:brightness(.96)}
  .ck__ok:active{transform:translateY(1px)}
  /* Szewron w guziku zgody jest NASZ (`.cx-chev-r`), a nie podwójny znak
     z makiety - zgłoszenie Radka 1.10. Rozmiar bierzemy mniejszy niż
     w znaku firmowym, bo tu to strzałka „dalej", nie logo. */
  .ck__chev{width:32px;height:32px;border-radius:8px;display:grid;place-items:center;
      background:var(--cx-ink);color:var(--cx-lime)}
  .ck__chev .cx-chev-r{width:7px;height:13px}
  /* „Tylko niezbędne" - odmowa jednym kliknięciem (decyzja Radka 1.10) -
     nosi TEN SAM wygląd `ck__ghost`, co dawne „Edytuj ustawienia"
     (polecenie Radka 1.10). Przez kilka godzin tego dnia miała własną klasę
     `ck__second` o wadze równej „Akceptuj wszystkie" - ramka, grube pismo,
     te same wymiary - właśnie po to, żeby odmowa nie wyglądała na drogę
     poboczną. Radek zważył to inaczej i tak zostaje.
     To, czego pilnuje prawo, nie ucierpiało: EROD i część interpretacji UODO
     mówią o RÓWNEJ ŁATWOŚCI, a ta mierzy się LICZBĄ KLIKNIĘĆ - i jest po obu
     stronach jedna. Dlatego `scripts/proba_cookies.py` mierzy kliknięcia,
     a nie wygląd guzika. */
  .ck__ghost:focus-visible,.ck__ok:focus-visible{outline:2px solid var(--cx-lime);
      outline-offset:2px}

  .ck__set{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;
      padding-bottom:20px;border-bottom:1px solid var(--cx-ink-60)}
  .ck__cat{display:flex;flex-direction:column;gap:8px}
  .ck__head{display:flex;justify-content:space-between;align-items:center;gap:12px}
  .ck__name{font-size:14px;font-weight:600;color:var(--cx-white)}
  .ck__always{font-size:12px;color:var(--cx-ink-20)}
  .ck__desc{margin:0;font-size:13px;line-height:1.5}
  /* Przełącznik: zwykły checkbox, rysowany tłem. Zostaje checkboxem, więc
     czytniki ekranu i klawiatura obsługują go bez naszej pomocy. */
  .ck__sw{appearance:none;-webkit-appearance:none;flex:none;margin:0;width:40px;height:24px;
      border-radius:12px;background:rgba(112,156,154,.45);position:relative;cursor:pointer;
      transition:background .15s ease}
  .ck__sw::after{content:"";position:absolute;top:2px;left:2px;width:20px;height:20px;
      border-radius:10px;background:var(--cx-white);transition:transform .15s ease}
  .ck__sw:checked{background:var(--cx-lime)}
  .ck__sw:checked::after{transform:translateX(16px)}
  .ck__sw:focus-visible{outline:2px solid var(--cx-lime);outline-offset:2px}


  @media (max-width:899px){
    .ck__in{padding:20px 32px}
    .ck__row{flex-direction:column;align-items:stretch;gap:16px}
    .ck__act{justify-content:flex-end}
  }
  @media (max-width:599px){
    .ck__in{padding:20px 20px 24px;gap:16px}
    /* Kolejność odwraca `column-reverse`: w kodzie „Edytuj" stoi pierwszy
       (bo to on rozwija ustawienia), a na telefonie pod palcem ma być
       najpierw guzik główny. Jeden DOM, dwa układy. Pod „Akceptuj wszystkie"
       staje więc „Tylko niezbędne" - obie drogi w zasięgu kciuka. */
    .ck__act{flex-direction:column-reverse;align-items:stretch;gap:8px}
    .ck__ok{height:48px;justify-content:space-between;font-size:15px}
    .ck__chev{width:40px;height:40px}
    .ck__ghost{height:48px;width:100%}
    .ck__set{grid-template-columns:1fr;gap:0;padding:0;border-top:1px solid var(--cx-ink-60)}
    .ck__cat{padding:10px 0;border-bottom:1px solid var(--cx-ink-60);gap:2px}
    .ck__head{min-height:44px}
    .ck__desc{font-size:12px}
    .ck__sw{width:48px;height:28px;border-radius:14px}
    .ck__sw::after{width:24px;height:24px;border-radius:12px}
    .ck__sw:checked::after{transform:translateX(20px)}
  }
  @media (prefers-reduced-motion:reduce){.ck{animation:none}}

  /* Powiadomienie o limicie zaproszeń w kreatorze firmy (9.10) - na dole
     ekranu, nad oknem kreatora i NAD paskiem cookies (1000). Ciemna płyta. */
  .krlimit{position:fixed;left:16px;right:16px;bottom:calc(16px + env(safe-area-inset-bottom));
      z-index:1001;max-width:560px;margin:0 auto;padding:14px 18px;border-radius:12px;
      background:var(--cx-ink);color:var(--cx-lime-soft);font-family:var(--font-body);
      font-size:14.5px;line-height:1.45;box-shadow:0 16px 40px rgba(0,0,0,.28);
      animation:ck-in .2s ease-out}
  .krlimit b{color:var(--cx-white)}
  .krlimit a{color:var(--cx-lime);text-decoration:underline}
  .krlimit a:hover{color:var(--cx-white)}

  /* ankieta przed anulowaniem planu (`views/viewRezygnacja.html`, 9.10) -
     karta z ekranu oceny, ale lista powodów czyta się od lewej */
  .rezkarta .rezform{text-align:left;margin-top:var(--space-5)}
  .reznag{display:block;font-weight:600;font-size:15px;color:var(--text);margin:0 0 var(--space-3)}
  .reznag span{font-weight:400;color:var(--body-fg)}
  .rezlista{display:flex;flex-direction:column;gap:11px}
  .rezlista .authchk{font-size:15px;color:var(--text)}
  .rezinne{align-items:center}
  .rezinne input[type=text]{flex:1;min-width:0;font:inherit;font-size:15px;padding:8px 11px;
      color:var(--text);background:var(--cx-white);border:1px solid var(--line);border-radius:var(--radius-sm)}
  .rezbtns{justify-content:center;flex-wrap:wrap;margin-top:var(--space-5)}
  .rezpod{margin:var(--space-4) 0 0;font-size:14px}
  .rezpod a{color:var(--body-fg);text-decoration:underline}

/* Zapraszanie do organizacji - pole adresów w koncie (14.10) */
  .zaprostxt{width:100%;box-sizing:border-box;font:inherit;font-size:15px;line-height:1.5;
      padding:9px 11px;border:1px solid var(--line);border-radius:var(--radius-sm);
      background:var(--cx-white);color:var(--text);resize:vertical;min-height:72px;
      margin-bottom:6px}
  .zaprostxt:focus{outline:2px solid #0E8C82;border-color:transparent}

/* ── Panel admina: SEO (14.10) ─────────────────────────────────────────────
   Jasny motyw jak reszta /admin/ (hero small + sekcja kb na bieli). */
  .seokarta{border:1px solid var(--line);border-left-width:4px;border-radius:var(--radius-sm);
      padding:14px 16px;margin:0 0 var(--space-4);background:var(--cx-white)}
  .seokarta--ok{border-left-color:#0a7d32}
  .seokarta--blok{border-left-color:#c56b4a}
  .seokarta b{display:block;font-size:16px;margin-bottom:2px}
  .seokarta>span{display:block;font-size:14px;color:var(--body-fg)}
  .seokarta .fldhint{margin-top:8px}
  .seotak{color:#0a7d32;font-weight:600;font-style:normal}
  .seonie{color:#c56b4a;font-weight:600;font-style:normal}
  .seolinki{list-style:none;margin:0 0 var(--space-4);padding:0;display:flex;
      flex-direction:column;gap:6px}
  .seolinki li{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
  .seolinki a{font-weight:600;color:var(--body-fg);text-decoration:underline}
  .seolinki i{color:var(--cx-ink-60);font-size:13px;font-style:normal}
  .seookp{color:#0a7d32;font-weight:500}
  .seookp a{color:var(--body-fg);text-decoration:underline}
  .seobrak{border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px 14px;
      background:#fbf6ef;margin:0 0 var(--space-4)}
  .seobrak p{margin:0 0 8px}
  .seokroki{margin:0 0 8px;padding-left:20px;display:flex;flex-direction:column;gap:5px}
  .seokroki li{font-size:14px;line-height:1.45}
  .seostrony{list-style:none;margin:0 0 var(--space-4);padding:0;display:flex;
      flex-direction:column;gap:10px}
  .seorow{border:1px solid var(--line);border-radius:var(--radius-sm);padding:11px 14px}
  .seorow--blad{color:var(--cx-ink-60)}
  .seorow>b{display:block;margin-bottom:6px}
  .seometa{margin:0;display:flex;flex-direction:column;gap:4px}
  .seometa div{display:grid;grid-template-columns:110px 1fr;gap:8px;font-size:13.5px}
  .seometa dt{color:var(--cx-ink-60);margin:0}
  .seometa dd{margin:0;word-break:break-word}
  @media(max-width:560px){.seometa div{grid-template-columns:1fr}
      .seometa dt{font-weight:600}}
  /* Edytor meta stron (14.10) */
  .seoedlista{display:flex;flex-direction:column;gap:14px;margin:0 0 var(--space-4)}
  .seoed{border:1px solid var(--line);border-radius:var(--radius-sm);padding:13px 15px}
  .seoed--zmiana{border-left:4px solid #e0b90e;background:#fffdf5}
  .seoed--blad{color:var(--cx-ink-60)}
  .seoed__head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px}
  .seoed__head b{font-size:15px}
  .seoed__head code{font-size:12px;color:var(--cx-ink-60)}
  .seoed__znak{margin-left:auto;display:none;font-size:12px;font-weight:600;
      color:#8a6d00;background:#fff4cf;border-radius:999px;padding:2px 10px}
  .seoed--zmiana .seoed__znak{display:inline-block}
  .seoed__grid{display:grid;grid-template-columns:1fr 340px;gap:16px}
  @media(max-width:820px){.seoed__grid{grid-template-columns:1fr}}
  .seoed__pola{display:flex;flex-direction:column;gap:11px}
  .seoed__lab{display:flex;flex-direction:column;gap:4px;font-size:13px;font-weight:600;
      color:var(--body-fg)}
  .seoed__lab .seo-in{font:inherit;font-weight:400;font-size:14px;padding:8px 10px;
      border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--cx-white);
      color:var(--text);width:100%;box-sizing:border-box;resize:vertical}
  .seoed__lab .seo-in:focus{outline:2px solid #e0b90e;border-color:#e0b90e}
  .seomier{font-weight:400;font-size:12px;margin-left:6px}
  .seomier small{color:var(--cx-ink-60)}
  .seomier--ok{color:#0a7d32}
  .seomier--uwaga{color:#c56b4a}
  .seomier--zla{color:#bb3354}
  /* `.btn--ghost` ma `color:mist !important` pod ciemne płyty, a karta zmiany
     jest prawie biała (`#fffdf5`) - bez tego guzik „Cofnij zmiany tej strony"
     znika (ta sama łatka co przy 404 i stopce edytora). */
  .seoed__cofnij{align-self:flex-start;font-size:12.5px;padding:5px 10px;
      color:var(--text)!important;border-color:var(--cx-ink-20);display:none}
  .seoed--zmiana .seoed__cofnij{display:inline-flex}
  .seoed__cofnij:hover{background:var(--cx-mist);color:var(--cx-ink)!important;
      border-color:var(--cx-ink-40)}
  .seoed__serp{display:flex;flex-direction:column;gap:5px}
  .seoed__serplab{font-size:12px;color:var(--cx-ink-60);font-weight:600}
  .seoserp{border:1px solid var(--line);border-radius:var(--radius-sm);padding:11px 13px;
      background:var(--cx-white);font-family:Arial,sans-serif}
  .seoserp__url{color:#202124;font-size:12.5px;margin-bottom:2px}
  .seoserp__tytul{color:#1a0dab;font-size:17px;line-height:1.3;margin-bottom:2px}
  .seoserp__opis{color:#4d5156;font-size:13px;line-height:1.5}
  :root[data-theme="dark"] .seoserp,:root:not([data-theme="light"]) .seoserp{background:#fff}
  .seoakcje{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 10px}
  .seoakcje__licz{font-size:13px;color:var(--cx-ink-60)}
  /* Jeden guzik „Zapisz" na sekcję, w prawym dolnym rogu (prośba Radka 16.10). */
  .seozapis{display:flex;align-items:center;justify-content:flex-end;gap:12px;
      flex-wrap:wrap;margin:4px 0 10px}
  /* `.btn--ghost` ma jasny tekst pod ciemne płyty - w tym panelu tło jest
     kremowe, więc bez tego „+ Dodaj przekierowanie" i „Przebuduj mapę teraz"
     renderują się bez tekstu (ta sama łatka co „Cofnij", 404, stopka edytora). */
  #seo-tresc .btn--ghost{color:var(--text)!important;border-color:var(--cx-ink-20)}
  #seo-tresc .btn--ghost:hover{background:var(--cx-mist);color:var(--cx-ink)!important;
      border-color:var(--cx-ink-40)}
  .seoakcje__msg{font-size:13.5px;margin:0 0 var(--space-4);min-height:1px}
  .seoakcje__msg:empty{display:none}
  .seoakcje__msg--ok{color:#0a7d32}
  .seoakcje__msg--uwaga{color:#bb3354}
  .seoakcje__msg--info{color:var(--cx-ink-60)}
  .seoover{border:1px solid var(--line);border-left:4px solid #0a7d32;background:#f2f9f4;
      border-radius:var(--radius-sm);padding:11px 14px;margin:0 0 var(--space-4)}
  .seoover b{display:block;font-size:14px;margin-bottom:4px}
  .seoover ul{margin:0 0 6px;padding-left:18px;font-size:13.5px}
  .seoover code{font-size:12px}
  :root[data-theme="dark"] .seoover,:root:not([data-theme="light"]) .seoover{background:#15241b}
  .seozdrowie{list-style:none;margin:0 0 var(--space-4);padding:0;display:flex;
      flex-direction:column;gap:5px}
  .seozdrowie li{font-size:13.5px;padding:7px 11px;border-radius:var(--radius-sm);
      border-left:3px solid var(--line)}
  .seozdrowie--uwaga{background:#fbf6ef;border-left-color:#c56b4a}
  .seozdrowie--zla{background:#fcf0f3;border-left-color:#bb3354}
  .seozdrowie--blad{background:#f4f4f4;border-left-color:#999}
  ul.seozdrowie.seookp,.seookp.seozdrowie{list-style:none}
  .seo301{margin:0 0 var(--space-4)}
  .seo301__lista{display:flex;flex-direction:column;gap:8px;margin:0 0 10px}
  .seo301__row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  .seo301-src,.seo301-dst{flex:1 1 220px;min-width:0;font-size:13.5px;
      padding:7px 10px;border:1px solid var(--line);border-radius:var(--radius-sm);
      background:var(--field-bg,var(--cx-white));color:var(--body-fg)}
  .seo301__arr{color:var(--cx-ink-60);font-size:15px;flex:0 0 auto}
  .seo301__usun{flex:0 0 auto;width:28px;height:28px;line-height:1;font-size:17px;
      border:1px solid var(--line);border-radius:var(--radius-sm);background:transparent;
      color:var(--cx-ink-60);cursor:pointer}
  .seo301__usun:hover{background:#fcf0f3;color:#bb3354;border-color:#bb3354}
  .seo301__dodaj{margin:0 0 10px}
  @media (max-width:560px){.seo301__arr{display:none}.seo301-src,.seo301-dst{flex:1 1 100%}}

/* ── Propozycje tekstów SEO (recenzja na PODGLĄDZIE, 13.10) ─────────────────
   Style działają tylko wtedy, gdy na stronie są znaczniki `.seoprop` -
   a te wstrzykuje `assets/seo-propozycje.js` WYŁĄCZNIE w podglądzie. Na
   produkcji nikt tych klas nie ma, więc reguły są martwe. */
  mark.seoprop{background:#ffe55c;color:#122021;border-radius:4px;padding:0 4px;
      position:relative;cursor:default;
      -webkit-box-decoration-break:clone;box-decoration-break:clone;
      box-shadow:0 0 0 1px #e0b90055}
  mark.seoprop--ok{background:#b9e7c2}
  /* Guzik-ptaszek: kółko zaraz po tekście. Niezaakceptowany - obrys,
     zaakceptowany - wypełniony zielenią. */
  .seoprop-ptaszek{display:inline-flex;align-items:center;justify-content:center;
      width:22px;height:22px;margin-left:6px;vertical-align:middle;
      border-radius:999px;border:1.5px solid #12202155;background:#fff;
      color:#12202188;cursor:pointer;padding:0;transition:all .12s ease;
      position:relative;top:-1px}
  .seoprop-ptaszek svg{width:13px;height:13px}
  .seoprop-ptaszek:hover{border-color:#0a7d32;color:#0a7d32}
  mark.seoprop--ok .seoprop-ptaszek{background:#0a7d32;border-color:#0a7d32;color:#fff}
  /* Hover: poprzedni tekst nad podświetleniem. */
  mark.seoprop::after{content:"było: " attr(data-stary);
      position:absolute;left:0;bottom:calc(100% + 8px);z-index:4000;
      min-width:200px;max-width:min(92vw,440px);width:max-content;
      white-space:normal;font-weight:400;font-style:normal;
      font-size:13px;line-height:1.45;letter-spacing:0;text-align:left;
      color:#F4F9F8;background:#122021;border:1px solid #2b4a48;
      padding:9px 12px;border-radius:10px;box-shadow:0 10px 28px #0007;
      opacity:0;transform:translateY(4px);pointer-events:none;
      transition:opacity .12s ease,transform .12s ease}
  mark.seoprop:hover::after,mark.seoprop:focus-within::after,
  mark.seoprop--pokaz::after{opacity:1;transform:translateY(0)}

  /* Panel recenzji - lewy dolny róg, nie zasłania treści. */
  #seoprop-panel{position:fixed;left:16px;bottom:16px;z-index:4000;
      width:min(320px,calc(100vw - 32px));
      background:#122021;color:#F4F9F8;border:1px solid #2b4a48;
      border-radius:14px;box-shadow:0 14px 40px #0008;
      padding:14px 16px 12px;font-size:13px;line-height:1.5;
      font-family:var(--font-sans,system-ui,sans-serif)}
  #seoprop-panel.sp-schowany .sp-lista,
  #seoprop-panel.sp-schowany .sp-tryb,
  #seoprop-panel.sp-schowany .sp-nawig,
  #seoprop-panel.sp-schowany .sp-kopiuj,
  #seoprop-panel.sp-schowany .sp-gotowe{display:none}
  #seoprop-panel .sp-head{font-weight:700;font-size:13.5px;margin-bottom:8px;
      padding-right:24px}
  #seoprop-panel .sp-head b{color:#ffe55c;margin-left:4px}
  /* Przełącznik trybu edycji */
  #seoprop-panel .sp-tryb{display:flex;align-items:flex-start;gap:7px;
      font-size:12px;color:#DBECE9;margin-bottom:9px;cursor:pointer;line-height:1.35}
  #seoprop-panel .sp-tryb input{margin-top:1px;accent-color:#ffe55c}
  /* Lista zmian: wiersz = ptaszek + opis */
  #seoprop-panel .sp-lista{list-style:none;margin:0 0 8px;padding:0;
      display:flex;flex-direction:column;gap:2px;max-height:38vh;overflow:auto}
  #seoprop-panel .sp-lista li{display:flex;align-items:center;gap:7px;
      padding:4px 6px;border-radius:7px}
  #seoprop-panel .sp-lista li:hover{background:#ffffff14}
  #seoprop-panel .sp-lista li.sp-ok .sp-opis{color:#9fe0ad}
  #seoprop-panel .sp-opis{flex:1;min-width:0;color:#DBECE9;font-size:12.5px;
      white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  #seoprop-panel .sp-opis i{color:#9fb6b3;font-style:normal;font-size:11px}
  #seoprop-panel .sp-pusto{color:#9fb6b3;font-size:12px;padding:4px 2px;
      white-space:normal}
  #seoprop-panel .sp-ptak2{flex:0 0 auto;display:inline-flex;align-items:center;
      justify-content:center;width:20px;height:20px;border-radius:999px;
      border:1.5px solid #2b4a48;background:#1b2e2e;color:#DBECE9;cursor:pointer;
      font-size:12px;line-height:1;padding:0}
  #seoprop-panel .sp-lista li.sp-ok .sp-ptak2{background:#0a7d32;
      border-color:#0a7d32;color:#fff}
  #seoprop-panel .sp-nawig{color:#9fb6b3;font-size:12px;margin-bottom:8px}
  #seoprop-panel .sp-nawig a{color:#ffe55c;text-decoration:none}
  #seoprop-panel .sp-nawig a:hover{text-decoration:underline}
  #seoprop-panel .sp-gotowe{color:#9fe0ad;font-weight:600;font-size:12.5px;
      margin-bottom:8px}
  #seoprop-panel .sp-kopiuj{width:100%;font:inherit;font-size:12.5px;font-weight:600;
      padding:8px 10px;border-radius:9px;border:1px solid #2b4a48;background:#1b2e2e;
      color:#F4F9F8;cursor:pointer}
  #seoprop-panel .sp-kopiuj:hover{background:#243838}
  #seoprop-panel .sp-zwin{position:absolute;top:10px;right:10px;width:22px;
      height:22px;border-radius:7px;border:1px solid #2b4a48;background:#1b2e2e;
      color:#DBECE9;cursor:pointer;line-height:1;font-size:16px;padding:0}
  #seoprop-panel .sp-zwin:hover{background:#243838}
  /* Tryb edycji: podświetl pola, które wolno przepisać */
  html.seo-tryb [data-seo-edyt]{outline:1.5px dashed #e0b90088;outline-offset:2px;
      border-radius:3px;cursor:text}
  html.seo-tryb [data-seo-edyt]:hover{outline-color:#ffe55c;background:#ffe55c18}
  html.seo-tryb [data-seo-edyt]:focus{outline:2px solid #ffe55c;
      background:#ffe55c22}
