/* =============================================================================
   Open Patrol — arkusz tokenów. ŹRÓDŁO, W REPO, W UŻYCIU.
   =============================================================================

   Ten plik leży w repozytorium pod `openpatrol/assets/open-patrol.css` i jest
   kompilowany przez AssetMapper do `public/build/` pod nazwą z hashem treści.
   Nagłówek mówił do 2026-09-03, że arkusz "świadomie NIE leży w repo" i podawał
   `openpatrol/public/open-patrol.css` jako docelową ścieżkę produkcyjną — oba
   zdania były nieprawdziwe od przejścia na AssetMapper. Poprawione, bo faza
   DISPATCH wysyła ten plik w paczce do renderera: nagłówek, który kłamie o tym,
   gdzie arkusz mieszka, jest instrukcją wysyłaną na zewnątrz.

   CO TO JEST
   Arkusz TOKENÓW, nie arkusz komponentów. Klasy komponentów giną przy
   przeprojektowaniu od zera; paleta, typografia i rytm przeżywają. Kontrakt
   pilnuje więc wartości, nie układu.

   Reguła obowiązująca w markupie:
       ZERO SUROWYCH WARTOŚCI. Kolory, fonty, promienie, odstępy, szerokość
       kontenera i punkty łamania wyłącznie przez var(--op-*).
       Styl inline jest dozwolony, o ile nie zawiera surowej wartości:
           style="color:#8C9BB2"          ← źle
           style="color:var(--op-text-3)" ← dobrze

   DWIE WARSTWY, ROZDZIELONE I NIEMIESZANE
       WARSTWA 1 — ZASTANE.      Token wyprowadzony z kodu. Każdy ma komentarz:
                                 plik źródłowy i liczba wystąpień. To są FAKTY.
       WARSTWA 2 — PROPONOWANE.  Normalizacja tam, gdzie kod jest wewnętrznie
                                 sprzeczny albo bezładny. To są PROPOZYCJE.
                                 Nic z warstwy 2 nie nadpisuje warstwy 1.

   Liczby wystąpień policzone na wszystkich szablonach w openpatrol/templates/
   oraz na openpatrol/public/report.css i openpatrol/public/report-hover.css.
   Stan na commit 3212b47, gałąź feature/symfony-migration.

   CZEGO TU NIE MA, ŚWIADOMIE
   Kolory studiów (Playtech #003A70, Pragmatic Play #F19021, …) NIE są tokenami.
   To dane. Żyją w openpatrol/config/openpatrol/catalog.json i tam zostają —
   trafiają do markupu jako style="background:{{ p.color }}". Jedyny wyjątek
   niżej to kolor „reszty studiów", który dziś jest zaszyty w PHP zamiast
   w danych; opisany jako dług, nie jako token do użycia.
   ============================================================================= */


/* =============================================================================
   WARSTWA 1 — ZASTANE
   Każda wartość poniżej WYSTĘPUJE w kodzie. Nic tu nie jest wymyślone.
   ============================================================================= */
:root {

  /* --- kolor: tekst ------------------------------------------------------- */
  --op-ink:                #0F172B;  /* 38× — tekst główny, tło stopki, tooltip; base.html.twig:60 theme-color, :66 body color */
  --op-ink-rgb:            15,23,43; /* ten sam granat w zapisie rgb; źródło 28 wystąpień rgba(15,23,43,α) — patrz cienie */
  --op-text-2:             #45556C;  /* 54× — tekst drugorzędny, akapity */
  --op-text-3:             #8C9BB2;  /* 70× — tekst trzeciorzędny, etykiety, placeholder (base.html.twig:72) */

  /* tekst na granacie (stopka, panel sprzedaży) */
  --op-on-ink:             #A9B6CB;  /*  4× — _footer.html.twig:4, _body.html.twig:449,453 */
  --op-on-ink-dim:         #7C8BA5;  /*  3× — _body.html.twig:451, sales/show.html.twig:130,131 */
  --op-on-ink-strong:      #DCE4F5;  /*  2× — sales/show.html.twig:117 (lista „Inside the report") */

  /* --- kolor: powierzchnie ------------------------------------------------ */
  --op-surface:            #FFF;     /* 66× — tło kart. UWAGA: w kodzie także #FFFFFF (2×), ta sama wartość */
  --op-page:               #F3F4F6;  /*  9× — tło strony; base.html.twig:66 */
  --op-band:               #EDEDF5;  /* 14× — pas sekcji przemiennej, tło pustego paska danych */
  --op-surface-tint:       #FCFCFE;  /*  1× — _body.html.twig:205, panel kasyna w sekcji dominance */
  --op-divider-on-ink:     #1B2542;  /*  1× — sales/show.html.twig:115, linia na granacie */

  /* --- kolor: linie i obramowania ----------------------------------------- */
  --op-hairline:           #E7EBF2;  /* 21× — włos rozdzielający wewnątrz kart */
  --op-border:             #CCD9ED;  /* 28× — obramowanie kontrolek i kart */
  --op-hairline-index:     #E1E5EC;  /*  1× — index/show.html.twig:26, jedyne użycie */

  /* --- kolor: marka, teal ------------------------------------------------- */
  /* #29A6A4 to teal kanonu www PlayPatrola. Zgodność Open Patrola z paletą www
     potwierdzona: teal + Poppins. Patrz DESIGN_CONTRACT.md sekcja E. */
  --op-teal-active:        #29A6A4;  /* 19× — obramowanie aktywne, focus ring (base.html.twig:68) */
  --op-teal:               #238D8B;  /* 49× — link, liczba, tekst akcentowany (base.html.twig:70) */
  --op-teal-hover:         #29A6A4;  /* base.html.twig:71 — hover linku; ta sama wartość co teal-active */
  --op-teal-wash:          #E6F8F7;  /* 17× — tło pigułki/pola aktywnego */
  --op-teal-wash-2:        #F1FBFA;  /*  1× — sales/show.html.twig:29, pole e-mail w stanie poprawnym */
  --op-teal-bright:        #00BFB3;  /*  6× — link w stopce, punktor listy */

  /* --- kolor: gradient akcentu (kreska pod nagłówkiem, logotyp) ----------- */
  --op-accent-from:        #0CCAC5;  /*  9× */
  --op-accent-to:          #00A9A5;  /*  9× — zawsze w parze z --op-accent-from */
  --op-accent:             linear-gradient(135deg, var(--op-accent-from), var(--op-accent-to));

  /* --- kolor: gradient CTA ------------------------------------------------ */
  /* Możliwy dryf względem kanonu www — patrz nota na końcu pliku. */
  --op-cta-from:           #DF2651;  /*  7× */
  --op-cta-to:             #6F4BB6;  /*  6× */
  --op-cta:                linear-gradient(90deg, var(--op-cta-from), var(--op-cta-to));
  --op-cta-hover-from:     #E86A8C;  /*  3× */
  --op-cta-hover-to:       #9B7AC9;  /*  3× */
  --op-cta-hover:          linear-gradient(90deg, var(--op-cta-hover-from), var(--op-cta-hover-to));
  --op-cta-active-from:    #9B1C3E;  /*  1× — sales/show.html.twig:33, tylko stan :active przycisku płatności */
  --op-cta-active-to:      #4E2E85;  /*  1× */
  --op-cta-active:         linear-gradient(90deg, var(--op-cta-active-from), var(--op-cta-active-to));

  /* --- kolor: kierunek zmiany (rosnie / spada) ---------------------------- */
  --op-up:                 #2E9E5B;  /*  5× — „new since the last scan", delta dodatnia */
  --op-down:               #EC221F;  /*  8× — „gone since the last scan", błąd formularza */
  --op-down-wash:          #FEECEC;  /*  1× — report.css:179, tło pigułki spadku */
  --op-down-surface:       #FDF0F0;  /*  2× — sales/show.html.twig:30,97, tło komunikatu błędu */

  /* --- kolor: stany interakcji -------------------------------------------- */
  --op-wash-hover:         #F3F6FA;  /*  3× — report.css:167 (pozycja menu), report-hover.css:4 */
  --op-wash-hover-alt:     #F7F9FC;  /*  2× — report.css:82,83 (wiersz tabeli ubiquity) */
                                     /*        DWA różne odcienie na to samo zadanie — patrz WARSTWA 2 */
  --op-dot-dim:            #E4E9F1;  /*  1× — report.css:90, kropka wygaszona przy focusie na studio */
  --op-mono-ink:           #425A7D;  /*  1× — _body.html.twig:78, adres kasyna w karcie operatora */

  /* --- kolor: dane, nie CSS ----------------------------------------------- */
  /* NIE UŻYWAĆ jako tokenu. Wpisany tu wyłącznie po to, żeby był widoczny:
     kolor „pozostałych studiów" jest dziś zaszyty w PHP
     (src/Report/ReportView.php:34, const OTHERS_COLOR), a wszystkie pozostałe
     kolory studiów są w catalog.json. Niespójność do rozstrzygnięcia. */
  --op-legacy-others:      #C9CDD5;  /* src/Report/ReportView.php:34 */

  /* --- typografia: rodziny ------------------------------------------------ */
  /* Google Fonts, base.html.twig:63. Wagi wczytywane: 400, 500, 600, 700 —
     i dokładnie te cztery są używane, żadnej innej w kodzie nie ma. */
  --op-font-sans:          'Poppins', sans-serif;      /* wpisany inline w <main> każdej z 5 stron */
  --op-font-mono:          'IBM Plex Mono', monospace; /* 117× inline — liczby, etykiety, adresy */

  --op-weight-regular:     400;  /*   2× */
  --op-weight-medium:      500;  /*  11× */
  --op-weight-semibold:    600;  /* 114× — waga domyślna tego projektu */
  --op-weight-bold:        700;  /*  35× — nagłówki i liczby-bohaterowie */

  /* --- typografia: rozmiary występujące w kodzie -------------------------- */
  /* To NIE jest skala. To lista tego, co zastałem: 37 różnych rozmiarów,
     w tym sześć z połówką piksela. Propozycja skali — WARSTWA 2. */
  --op-size-hero:          clamp(50px, 10vw, 120px);   /*  1× — słowo „Open Patrol", _body.html.twig:14 */
  --op-size-h1-a:          clamp(32px, 5.4vw, 58px);   /*  2× — index:17, sales:45 */
  --op-size-h1-b:          clamp(30px, 5.4vw, 56px);   /*  3× — full-report/gate:19,26, thank-you:42 */
  --op-size-h1-c:          clamp(32px, 5.6vw, 60px);   /*  1× — site/coming-soon:41 */
  --op-size-h1-report:     clamp(22px, 3vw, 34px);     /*  1× — _body.html.twig:16, jedyne prawdziwe H1 raportu */
  --op-size-h2:            clamp(26px, 3.5vw, 36px);   /*  9× — wszystkie H2 raportu, jedyny w pełni spójny rozmiar */
  --op-size-lead:          clamp(16px, 1.9vw, 19px);   /*  5× — akapit wiodący */
  --op-size-stat:          clamp(22px, 3vw, 30px);     /*  4× — licznik w pasku hero */

  /* Jedna deklaracja na linię — inaczej weryfikacja tokenów w INTAKE.md
     (grep zakotwiczony na początku linii) przeoczy każdą drugą. */
  --op-size-28:            28px;    /*  2× */
  --op-size-22:            22px;    /*  3× */
  --op-size-21:            21px;    /*  2× */
  --op-size-20:            20px;    /*  4× */
  --op-size-18:            18px;    /*  6× */
  --op-size-17:            17px;    /*  5× */
  --op-size-16:            16px;    /*  8× */
  --op-size-15:            15px;    /* 49× — rozmiar bazowy tekstu */
  --op-size-14:            14px;    /*  9× */
  --op-size-13:            13px;    /* 27× */
  --op-size-12:            12px;    /* 33× */
  --op-size-11:            11px;    /* 18× */
  --op-size-10:            10px;    /*  1× */
  /* połówki pikseli — patrz WARSTWA 2, propozycja likwidacji */
  --op-size-16-5:          16.5px;  /*  1× */
  --op-size-15-5:          15.5px;  /*  4× */
  --op-size-14-5:          14.5px;  /*  2× */
  --op-size-13-5:          13.5px;  /* 14× */
  --op-size-12-5:          12.5px;  /* 25× */
  --op-size-11-5:          11.5px;  /* 18× */
  --op-size-10-5:          10.5px;  /* 22× — etykieta mono wersalikami */

  /* --- typografia: interlinia --------------------------------------------- */
  --op-lh-tight:           1;       /* 18× */
  --op-lh-hero:            0.95;    /*  1× — _body.html.twig:14 */
  --op-lh-h1:              1.05;    /*  5× */
  --op-lh-heading:         1.2;     /*  4× */
  --op-lh-snug:            1.25;    /* 12× */
  --op-lh-title:           1.3;     /*  5× */
  --op-lh-label:           1.4;     /*  5× */
  --op-lh-body:            1.5;     /* 35× */
  --op-lh-body-2:          1.55;    /*  8× */
  --op-lh-body-3:          1.6;     /* 25× */
  --op-lh-body-4:          1.65;    /*  6× */
  --op-lh-loose:           1.8;     /*  1× */
                                    /* CZTERY interlinie tekstu ciągłego — patrz WARSTWA 2 */

  /* --- typografia: światło międzyliterowe --------------------------------- */
  --op-tracking-hero:      -0.03em; /*  1× */
  --op-tracking-display:   -0.025em;/*  6× — H1 stron */
  --op-tracking-h2:        -0.015em;/* 17× — H2 i H3 */
  --op-tracking-tight:     -0.01em; /* 10× — nazwy studiów, tytuły kart */
  --op-tracking-number:    -0.02em; /*  4× — duże liczby mono */
  --op-tracking-caps:      0.14em;  /* 22× — etykieta mono wersalikami */
  --op-tracking-caps-2:    0.1em;   /*  1× — index/show.html.twig:48, plakietka „Latest" */
  --op-tracking-mono:      0.08em;  /*  1× — report.css:71 */
  --op-tracking-mono-2:    0.04em;  /*  2× — report.css:147,169 */

  /* --- promienie ---------------------------------------------------------- */
  --op-radius-pill:        999px;   /* 40× — pigułki, przyciski, kontrolki */
  --op-radius-card:        16px;    /* 26× — karty i panele */
  --op-radius-dialog:      12px;    /*  3× — dialogi proof i gate. Karty mają 16px — niespójność */
  --op-radius-menu-item:   10px;    /*  1× — report.css:164 */
  --op-radius-field:       8px;     /*  5× — pola formularza, dymki */
  --op-radius-field-inner: 7px;     /*  1× — sales/show.html.twig:88, input wewnątrz ramki 8px */
  --op-radius-rule:        3px;     /* 11× — kreska akcentu, próbka koloru flagi */
  --op-radius-chip:        2px;     /*  6× — kafel danych, kropka mozaiki */

  /* --- cienie ------------------------------------------------------------- */
  /* Wszystkie oparte o ten sam granat 15,23,43 — poza jednym wyłomem niżej. */
  --op-shadow-card:        0 2px 10px rgba(15,23,43,.08);  /* 14× — cień karty */
  --op-shadow-card-alt:    0 2px 10px rgba(15,23,43,.06);  /*  2× — base.html.twig:84 (.op-card), site/coming-soon:61
                                                                  KONFLIKT: ta sama karta, dwa cienie */
  --op-shadow-lift:        0 12px 28px rgba(15,23,43,.16); /*  5× — karta uniesiona, panel paywalla */
  --op-shadow-stuck:       0 8px 22px rgba(15,23,43,.14);  /*  1× — report.css:122, pasek przyklejony */
  --op-shadow-dialog:      0 22px 48px rgba(15,23,43,.14); /*  2× — dialogi */
  --op-shadow-tip:         0 6px 18px rgba(15,23,43,.25);  /*  2× — tooltip, dymek info */
  --op-shadow-order:       0 18px 40px rgba(0,0,0,.28);    /*  1× — sales/show.html.twig:67
                                                                  WYŁOM: jedyny cień na czystej czerni */
  --op-shadow-order-alt:   0 18px 40px rgba(15,23,43,.08); /*  1× — ten sam rozmiar cienia, inna barwa i alfa */

  /* Uwaga zapisowa: w Twigach alfa jest pisana 0.08, w report.css .08.
     Ta sama wartość, dwa zapisy — ujednolicone tutaj do .08. */

  /* --- układ -------------------------------------------------------------- */
  --op-container:          1120px;                  /* 31× — szerokość treści, każdorazowo wpisana inline */
  --op-gutter:             clamp(20px, 5vw, 64px);  /* 29× — margines boczny kontenera, najstabilniejsza wartość w kodzie */

  /* --- ruch --------------------------------------------------------------- */
  --op-ease:               cubic-bezier(0.2, 0, 0, 1); /* report.css:18 — JEDYNA zmienna CSS istniejąca dziś w repo */
  --op-dur-fast:           .15s;   /* stany hover */
  --op-dur-base:           .2s;    /* najczęstsza; w kodzie zapisana i jako 0.2s, i jako .2s */
  --op-dur-slow:           .25s;
  --op-dur-panel:          .3s;
  --op-dur-reveal:         .35s;
  --op-dur-bar:            .45s;   /* animacja szerokości paska danych */

  /* --- warstwy ------------------------------------------------------------ */
  --op-z-sticky-cell:      1;    /* przyklejona komórka tabeli */
  --op-z-legend:           20;   /* report.css:92 */
  --op-z-chrome:           40;   /* _body.html.twig:28, pasek nawigacji */
  --op-z-popover:          60;   /* tooltip, panel menu */
  --op-z-info:             65;   /* dymek info */
  --op-z-dialog:           70;   /* dialog paywalla */
  --op-z-dialog-top:       75;   /* dialog z dowodem */

  /* --- punkty łamania (do referencji; @media nie czyta var()) -------------- */
  --op-bp-narrow:          767px;   /* report.css:133 — pasek nawigacji zawija */
  --op-bp-sales:           920px;   /* sales/show.html.twig:22 — zamiana kolumn */
  --op-bp-wide:            1023px;  /* report.css:105 — legenda z pionu w poziom */
  /* plus @media (pointer:coarse) w base.html.twig:69 — cel dotykowy min. 44px */
}


/* =============================================================================
   WARSTWA 2 — PROPONOWANE
   =============================================================================
   Nic poniżej NIE występuje w repo w tej postaci. To są propozycje normalizacji
   miejsc, w których kod jest bezładny albo sam ze sobą sprzeczny.

   Zasada: żaden token z tej warstwy nie nadpisuje tokenu z warstwy 1. Gdzie
   proponuję wybór między dwiema zastanymi wartościami, piszę wprost, którą i co
   to zmienia na ekranie.

   Te tokeny są gotowe do użycia przez Claude Design w następnej rundzie. Nie są
   zastosowane w istniejących szablonach — migracja markupu nie jest zadaniem tej
   fazy i odbędzie się przy okazji rundy przeprojektowania.
   ============================================================================= */
:root {

  /* --- PROPOZYCJA 1: skala typograficzna ---------------------------------- */
  /*
     Problem: 37 różnych rozmiarów, z czego sześć z połówką piksela
     (10.5 / 11.5 / 12.5 / 13.5 / 15.5 / 16.5). Połówki to osad po eksporcie
     z narzędzia projektowego, nie decyzja. 12.5px użyty 25×, 13.5px 14× —
     są rozpowszechnione, ale nie znaczące: nie da się wskazać różnicy roli
     między 12px (33×) a 12.5px (25×).

     Propozycja: osiem stopni, zero połówek. Dryf maksymalny 0.5px.
  */
  --op-fs-xs:    11px;   /* zastępuje 10px, 10.5px, 11px            — etykieta mono wersalikami */
  --op-fs-sm:    12px;   /* zastępuje 11.5px, 12px, 12.5px          — podpis, metryka */
  --op-fs-base:  13px;   /* zastępuje 13px, 13.5px                  — tekst pomocniczy */
  --op-fs-md:    15px;   /* zastępuje 14px, 14.5px, 15px, 15.5px    — tekst bazowy (15px już jest najczęstszy, 49×) */
  --op-fs-lg:    17px;   /* zastępuje 16px, 16.5px, 17px            — tytuł karty */
  --op-fs-xl:    20px;   /* zastępuje 18px, 20px, 21px, 22px        — H3 */
  --op-fs-2xl:   clamp(26px, 3.5vw, 36px);  /* = --op-size-h2, jedyny spójny rozmiar w kodzie, zostaje bez zmian */
  --op-fs-3xl:   clamp(32px, 5.4vw, 58px);  /* JEDEN rozmiar H1 zamiast trzech (58/56/60px w maksimum) */
  --op-fs-hero:  clamp(50px, 10vw, 120px);  /* logotyp słowny, bez zmian */

  /* --- PROPOZYCJA 2: skala odstępów --------------------------------------- */
  /*
     Problem: skala nie istnieje. W kodzie jest 61 różnych wywołań clamp(),
     z czego kilkanaście to warianty tej samej rzeczy różniące się o 2px:
       rytm sekcji:   clamp(64px,9vw,104px) 9× | clamp(56px,8vw,96px) 8× | clamp(56px,8vw,88px) 3×
       padding karty: clamp(22px,3vw,32px) 7×  | clamp(20px,3vw,32px) 4×  | clamp(20px,3vw,28px) 5×
       kreska akcentu:clamp(72px,10vw,116px) 6×| clamp(80px,12vw,132px) 1×
     Żadna z tych różnic nie jest widoczna ani zamierzona.

     Propozycja: skala statyczna 4→64 plus trzy rytmy płynne.
  */
  --op-space-1:   4px;
  --op-space-2:   8px;
  --op-space-3:   12px;
  --op-space-4:   16px;
  --op-space-5:   20px;
  --op-space-6:   24px;
  --op-space-8:   32px;
  --op-space-10:  40px;
  --op-space-12:  48px;
  --op-space-16:  64px;

  --op-rhythm-card:     clamp(20px, 3vw, 32px);   /* JEDEN padding karty zamiast trzech */
  --op-rhythm-section:  clamp(56px, 8vw, 96px);   /* JEDEN rytm pionowy sekcji zamiast trzech */
  --op-rhythm-hero:     clamp(44px, 7vw, 96px);   /* odstęp otwierający stronę, bez zmian (1× w kodzie) */
  --op-rule-width:      clamp(72px, 10vw, 116px); /* kreska akcentu pod nagłówkiem, wariant częstszy (6× vs 1×) */

  /* --- PROPOZYCJA 3: interlinia ------------------------------------------- */
  /*
     Problem: cztery interlinie tekstu ciągłego — 1.5 (35×), 1.55 (8×),
     1.6 (25×), 1.65 (6×) — bez rozróżnienia roli.
     Propozycja: dwie.
  */
  --op-leading-tight:  1.25;  /* nagłówki i tytuły kart; scala 1.2 / 1.25 / 1.3 */
  --op-leading-body:   1.55;  /* tekst ciągły; scala 1.5 / 1.55 / 1.6 / 1.65 */
  --op-leading-flat:   1;     /* liczby-bohaterowie, bez zmian */

  /* --- PROPOZYCJA 4: promienie z nazwami ---------------------------------- */
  /*
     Problem: osiem promieni bez nazw, w tym 7px w środku 8px (sales:88) i
     dialogi na 12px przy kartach na 16px.
     Propozycja: pięć, dialog zrównany z kartą.
  */
  --op-r-pill:   999px;
  --op-r-lg:     16px;  /* karty ORAZ dialogi — likwiduje 12px */
  --op-r-md:     10px;  /* pozycja menu */
  --op-r-sm:     8px;   /* pola formularza; likwiduje 7px */
  --op-r-xs:     2px;   /* kafle danych; likwiduje 3px */

  /* --- PROPOZYCJA 5: jeden cień karty ------------------------------------- */
  /*
     Problem: .op-card jest zdefiniowany dwa razy i różnie —
       base.html.twig:84   cień .06, border 1px #E7EBF2, padding 20px
       report.css:62       cień .08, bez bordera,        padding 18px 20px 20px
     Ta sama karta wygląda inaczej na / niż na /es/july-2026, bo report.css
     ładuje się później i wygrywa.

     Rekomendacja: .08 (14 wystąpień kontra 2) i bez bordera.
     Skutek: karty na stronie głównej, /full-report i kurtynie staną się
     odrobinę ciemniejsze w cieniu i stracą włos obramowania.
  */
  --op-elevation-1:  0 2px 10px rgba(15,23,43,.08);   /* karta w spoczynku */
  --op-elevation-2:  0 12px 28px rgba(15,23,43,.16);  /* karta uniesiona, panel paywalla */
  --op-elevation-3:  0 22px 48px rgba(15,23,43,.14);  /* dialog; scala też cień 0 18px 40px */
  --op-elevation-tip:0 6px 18px rgba(15,23,43,.25);   /* tooltip */
  /* Likwiduje cztery tokeny z warstwy ZASTANE: cień karty .06, cień zamówienia
     na czystej czerni .28, jego wariant granatowy, oraz osobny cień paska
     przyklejonego. */

  /* --- PROPOZYCJA 6: jedno tło stanu hover -------------------------------- */
  /*
     Problem: #F3F6FA (3×) i #F7F9FC (2×) pełnią to samo zadanie.
     Rekomendacja: #F3F6FA, jako częstsze i ciemniejsze o włos, więc czytelniejsze.
  */
  --op-wash:  #F3F6FA;

  /* --- PROPOZYCJA 7: jeden zestaw punktów łamania ------------------------- */
  /*
     Problem: trzy niezgodne progi — 767px, 920px, 1023px.
     Propozycja: dwa strukturalne, 768 i 1024. Próg 920px jest treściowy
     (moment, w którym karta zamówienia mieści się obok listy na stronie
     sprzedaży) i albo przesuwa się do 1024, albo zostaje udokumentowanym
     wyjątkiem jednego widoku. NIE rozstrzygam — rekomenduję przesunięcie.

     @media nie czyta var(), więc to są wartości do wklejenia, nie do użycia.
  */
  --op-bp-md:  768px;
  --op-bp-lg:  1024px;

  /* --- PROPOZYCJA 8: nazwane hovery zamiast numerów ----------------------- */
  /*
     Problem: public/report-hover.css to siedem reguł [data-hov="0"]…[data-hov="6"].
     Numery nie mówią nic, są rozsiane po _body.html.twig, a komentarz w pliku
     każe je regenerować z design/report.dc.html — GENERATORA W REPO NIE MA.

     Propozycja nazw (do wprowadzenia przy rundzie przeprojektowania):
       [data-hov="0"] → .op-hover-ghost   tło teal-wash                (przycisk obrysowany)
       [data-hov="1"] → .op-hover-quiet   tło wash + tekst teal        (przełącznik edycji)
       [data-hov="2"] → .op-hover-icon    obramowanie i tekst teal     (przycisk „i")
       [data-hov="3"] → .op-hover-lift    unosi o 3px + elevation-2    (karta)
       [data-hov="4"] → .op-hover-action  tło teal-wash + obramowanie  (przycisk w karcie)
       [data-hov="5"] → .op-hover-cta     gradient CTA jaśniejszy      (przycisk główny)
       [data-hov="6"] → .op-hover-close   tło band                     (zamknięcie dialogu)
  */
  --op-lift:  -3px;  /* przesunięcie karty w hoverze; report-hover.css:6 */
}


/* =============================================================================
   WARSTWA 3 — DODANE W RUNDZIE 19 (migracja na statyczny HTML)
   =============================================================================
   Wartości, które występują w zastanym kodzie strony raportu, ale nie były
   wyprowadzone do warstwy 1. Opis i uzasadnienie: CHANGES.md, runda 19.
   ============================================================================= */
:root {

  /* --- kolor: brakujące -------------------------------------------------- */
  --op-scrim:          rgba(15,23,43,.55);      /* tło pod dialogiem proof i gate; 2× w kodzie strony */
  --op-rule-on-ink:    rgba(255,255,255,.12);   /* linia nad linią źródłową w stopce; 1× */
  --op-on-ink-body:    #fff;                    /* tekst w dymku i tooltipie na granacie */

  /* --- efekt zasłony płatnej --------------------------------------------- */
  --op-blur-gate:      blur(14px) saturate(0.8); /* 2× w kodzie strony; zawsze na atrapach */

  /* --- wymiary elementów danych ------------------------------------------ */
  /* „Dane są grafiką" (kontrakt D), więc rozmiar kafla jest wartością projektową,
     nie daną. Wszystkie poniższe występują w zastanym kodzie strony. */
  --op-tile:           14px;   /* kafel mozaiki „Whose games dominate each homepage?" */
  --op-tile-gap:       3px;
  --op-mark:           18px;   /* kwadrat tabeli „Which games show up almost everywhere?" */
  --op-swatch:         12px;   /* próbka koloru w legendzie i w dialogu */
  --op-strip:          6px;    /* pas brandowy na karcie rankingu */
  --op-bar-h:          26px;   /* tor słupka „Who wins the rows players see first?" */
  --op-logo-w:         130px;  /* pole logotypu studia */
  --op-logo-h:         36px;

  /* --- kontrolki ---------------------------------------------------------- */
  --op-touch:          44px;   /* minimalny cel dotykowy, kontrakt E */
  --op-control:        40px;   /* wysokość kontrolki drugorzędnej na desktopie */
  --op-icon:           26px;   /* przycisk „i" przy H2 */

  /* --- szerokości szyn ---------------------------------------------------- */
  /* --op-rail-legend zniknął 2026-09-01 razem z .op-legend: sekcja dominance
     nie istnieje, a jedyna reguła, która czytała ten token, została usunięta. */
  --op-rail-table:     260px;  /* przyklejona kolumna tabeli ubiquity */
  --op-rail-push:      200px;  /* kolumna studia w sekcji new titles */

  /* --- rytm ---------------------------------------------------------------- */
  --op-rhythm-subhead: clamp(44px, 5vw, 60px); /* odstęp nad H3 wewnątrz bloku; 1× w kodzie strony */
}


/* =============================================================================
   TODO — brak w repo, do decyzji
   =============================================================================

   Poniżej wyłącznie rzeczy, których NIE DA SIĘ wyprowadzić z kodu. Nic nie
   zgaduję i nie podstawiam wartości.

   1. TODO: brak w repo, do decyzji — kolor „pozostałych studiów".
      #C9CDD5 jest zaszyty w PHP (src/Report/ReportView.php:34), podczas gdy
      wszystkie inne kolory studiów są danymi w catalog.json. Albo jest to
      dana i ma trafić do catalog.json, albo jest to element palety i ma trafić
      tutaj. Dziś jest w trzecim miejscu, w którym nie powinien być.

   2. TODO: brak w repo, do decyzji — dryf gradientu CTA względem kanonu www.
      Kanon www PlayPatrola opisuje tinty audiencji #6C5CE7, #0E8F75, #E43F7A,
      gdzie różowy jest kolorem providerów, czyli audiencji Open Patrola.
      Gradient CTA w kodzie to #DF2651 → #6F4BB6. Blisko, ale to nie są te
      wartości. Żadna z trzech wartości kanonu nie występuje w repo ani razu.
      Do decyzji właściciela marki; nie poprawiam.

   3. TODO: brak w repo, do decyzji — próg 920px (sales/show.html.twig:22).
      Czy zamiana kolumn na stronie sprzedaży ma zostać osobnym progiem,
      czy przesunąć się do 1024px razem z resztą.

   4. TODO: brak w repo, do decyzji — stan :focus-visible poza domyślnym.
      base.html.twig:68 daje jeden globalny obrys 2px #29A6A4 dla wszystkiego.
      Nie ma wariantu dla elementów na granatowym tle (stopka, panel sprzedaży),
      gdzie ten teal ma niski kontrast. Nie zgaduję wartości.

   5. TODO: brak w repo — arkusz druku.
      Raport badawczy bywa drukowany i cytowany. W repo nie ma ani jednej
      reguły @media print. Nie proponuję wartości, odnotowuję brak.

   ============================================================================= */



/* =============================================================================
   WARSTWA — DODANE 10 sierpnia 2026: gęstość osi edycji
   =============================================================================
   Oś edycji zagęszcza kropki tak długo, jak da się utrzymać czytelną datę pod
   każdą z nich. Poniżej tej szerokości oś nie ma sensu jako oś, więc kontener
   przewija się w bok (poziomo) albo w dół (pionowo w panelu), a punkty trzymają
   swoją minimalną szerokość. To jest granica projektowa, nie dana: opis
   w CHANGES.md, runda z 10 sierpnia 2026.
   ============================================================================= */
:root {

  /* Najwęższy punkt osi, przy którym data w jednej linii jeszcze się mieści. */
  --op-axis-point-min: 92px;

  /* Ile punktów oś pokazuje bez przewijania: powyżej tej liczby zaczyna się
     przewijanie, a nie dalsze zagęszczanie. Przy 7 punktach i 92 px na punkt
     oś zajmuje 644 px, czyli mieści się w kontenerze na desktopie. */
  --op-axis-points-max: 7;

  /* Wysokość punktu w wariancie pionowym: cel dotykowy plus miejsce na stan. */
  --op-axis-point-height: 64px;
}


/* =============================================================================
   WARSTWA — DODANE W RUNDZIE L01 (strona główna /)
   =============================================================================
   Tokeny strony głównej. Większość wartości siedziała inline w
   layout-reference.html; tu dostają nazwy, żeby markup był czysty z surowych
   wartości. Nowe (bez pierwowzoru w referencji) są wyłącznie wartości guzika
   hero i powiększona liczba taśmy. Uzasadnienie: CHANGES.md, runda L01.
   ============================================================================= */
:root {

  /* --- typografia strony głównej ----------------------------------------- */
  --op-size-landing-h1:  clamp(44px, 8.4vw, 104px);  /* H1 hero; zastane w referencji */
  --op-size-door-title:  clamp(20px, 2.1vw, 32px);   /* tytuł karty raportu; zastane */
  --op-size-landing-fig: clamp(34px, 4.8vw, 64px);   /* liczba taśmy; referencja miała clamp(30px,4vw,58px), powiększone w L01 */

  /* --- rytm trzech ramek --------------------------------------------------- */
  --op-rhythm-frame:     clamp(24px, 4vh, 56px);     /* padding pionowy ramki kart; zastane */
  --op-rhythm-band:      clamp(28px, 4vh, 48px);     /* padding pasów: taśma, SEO, stopka; zastane */
  --op-rhythm-hero-cta:  clamp(28px, 4vh, 48px);     /* odstęp H1 do guzika; zastane */

  /* --- karty raportów i siatka rynków -------------------------------------- */
  --op-gap-doors:        clamp(14px, 1.8vw, 24px);   /* zastane */
  --op-pad-door-y:       clamp(18px, 2.6vh, 32px);   /* zastane */
  --op-pad-door-x:       clamp(24px, 3vw, 44px);     /* zastane */
  --op-door-min:         280px;                      /* minimalna wysokość karty; zastane */
  --op-col-min:          280px;                      /* minimalna kolumna tekstu SEO; zastane */
  --op-flag-h:           clamp(30px, 3.6vw, 48px);   /* wysokość flagi; referencja miała clamp(26px,3.4vw,44px), powiększone w L01 */

  /* --- guzik hero (nowe w L01) ---------------------------------------------- */
  --op-control-hero:     64px;   /* wysokość głównego CTA strony głównej */
  --op-bracket:          16px;   /* bok narożnika celownika wokół CTA oraz karetki karty */

  /* --- punkt łamania siatki kart (do wklejenia; @media nie czyta var) ------- */
  --op-bp-doors:         560px;
}

/* =============================================================================
   WARSTWA — DODANE W RUNDZIE R01 (sekcja „Who takes the best positions?")
   =============================================================================
   Wartości, które w referencji rundy (accepted-layout.html oraz cards.php,
   sum-share.php, sum-coverage.php) siedziały inline w markupie i w arkuszach
   komponentów. Tutaj dostają nazwy, żeby blok sekcji był czysty z surowych
   wartości. Różnice względem referencji opisane przy każdej wartości oraz
   w CHANGES.md, runda R01.
   ============================================================================= */
:root {

  /* --- wymiary elementów danych ------------------------------------------- */
  --op-card-op:        244px;  /* szerokość kafla operatora; referencja 232px inline, poszerzone o oddech na dwie kolumny liczb */
  --op-share-bar:      56px;   /* wysokość paska udziału; referencja 44px inline */
  --op-dot:            18px;   /* maksymalna średnica kropki macierzy zasięgu; referencja 11px inline */
  --op-reach-tick:     30px;   /* wysokość szczeliny w macierzy zasięgu (26 szczelin = 26 operatorów); NOWE */
  --op-dot-cols:       26;     /* jedna szczelina na operatora, ZAWSZE w jednym rzędzie (decyzja właściciela 2026-09-02: dwa rzędy czytają się jak dwie miary) */
  --op-bp-reach:       420px;  /* szerokość kafla, pod którą odstęp między szczelinami się zacieśnia - rząd zostaje jeden (do wklejenia: @container nie czyta var) */
  --op-axis-tick:      6px;    /* wysokość kreski osi pod paskiem udziału; NOWE, bez pierwowzoru */

  /* --- karuzela ------------------------------------------------------------ */
  --op-edge-fade:      112px;  /* szerokość wygaszonej krawędzi karuzeli; zastane w referencji */
  --op-control-nav:    56px;   /* średnica strzałki karuzeli; ≥ --op-touch */
  --op-blur-edge:      blur(3px); /* rozmycie zawartości pod strzałką; zastane w referencji */

  /* Rampy maski krawędzi. To NIE jest kolor palety: czarny koniec rampy jest
     kanałem alfa maski, nie barwą na ekranie. Wpisane tutaj, żeby literał nie
     leżał ani w markupie, ani w arkuszu bloku. */
  --op-mask-edge-l:    linear-gradient(to right, rgb(0 0 0) 55%, transparent);
  --op-mask-edge-r:    linear-gradient(to left, rgb(0 0 0) 55%, transparent);

  /* --- układ pary dużych kafli --------------------------------------------- */
  --op-pair-min:       420px;  /* najwęższa kolumna pary; referencja 400px inline */
}

/* =============================================================================
   WARSTWA — DODANE W RUNDZIE R02 (sekcja „Games most visible on the market")
   =============================================================================
   Wartości, które w szkicu rundy (warstwa F w preview/blocks-most-visible)
   siedziały inline w arkuszu warstwy albo w lokalnych zmiennych --f-*. Tutaj
   dostają nazwy, bo blok sekcji nie może nieść surowej wartości (§B2).
   Uzasadnienie każdej różnicy względem szkicu: CHANGES.md, runda R02.
   ============================================================================= */
:root {

  /* --- spis tytułów: karta i numer grupy ---------------------------------- */
  --op-mv-card-max:     348px;  /* szerokość karty pojedynczego tytułu; zastane w szkicu */
  --op-mv-card-step:    45px;   /* o tyle karta maleje z każdym tytułem w grupie; zastane */
  --op-mv-card-floor:   168px;  /* dolna granica; niżej rząd przewija się zamiast ściskać tytuł */
  --op-mv-card-floor-md:132px;  /* ta sama granica poniżej --op-bp-mv; zastane */
  --op-mv-card-snap:    86%;    /* poniżej --op-bp-mv-sm karta bierze tyle szerokości rzędu, żeby następna wystawała */
  --op-mv-no-col:       clamp(56px, 7.2vw, 104px);  /* stała kolumna numeru grupy; zastane */
  --op-mv-no:           clamp(30px, 4.2vw, 54px);   /* stopień numeru grupy; zastane */
  --op-mv-no-min:       2.6ch;  /* szerokość dwóch cyfr w mono, żeby #1 i #10 stały w jednej osi */
  --op-mv-no-open:      3.4ch;  /* kolumna numeru w stanie otwartym; zastane */
  --op-mv-list-open:    288px;  /* szerokość spisu po otwarciu panelu; zastane */
  --op-mv-chev:         22px;   /* szewron karty; zastane */
  --op-mv-fade:         48px;   /* wygaszona prawa krawędź rzędu, który ma dalszy ciąg; zastane */
  --op-mv-mask-row:     linear-gradient(90deg, rgb(0 0 0) calc(100% - var(--op-mv-fade)), transparent);

  /* --- panel szczegółu ---------------------------------------------------- */
  --op-mv-title:        clamp(21px, 2.4vw, 28px);  /* NOWE: tytuł gry w panelu. Szkic brał --op-fs-2xl, czyli stopień H2 sekcji, więc nagłówek panelu i nagłówek sekcji stały w jednym rozmiarze */
  --op-mv-logo-h:       30px;   /* wysokość znaku studia w panelu; zastane */
  --op-mv-logo-w:       140px;  /* maksymalna szerokość znaku i zapasowego napisu; zastane */
  --op-mv-bar-h:        10px;   /* NOWE: pasek udziału w panelu. Szkic miał 6px, przy oznaczonych ćwiartkach osi pasek 6px czytał się jak włos */
  --op-mv-op-min:       220px;  /* NIEUŻYWANE po przebudowie z 2026-09-03 (siatka kafli operatorów), zostaje jako zapis wartości */
  --op-mv-page-w:       132px;  /* NIEUŻYWANE: poziomy pasek strony wycofany 2026-09-03, pasek wrócił do pionu */
  --op-mv-page-h:       22px;   /* NIEUŻYWANE, jak wyżej */
  --op-mv-pos-w:        168px;  /* NIEUŻYWANE: kolumna nazwy wiersza zeszła z ekranu 2026-09-03 */
  --op-bp-mv-ops:       700px;  /* NIEUŻYWANE: wiersz operatora ma dziś jeden próg, --op-bp-mv-op */
  --op-bp-mv-pair:      1240px; /* NIEUŻYWANE: nazwa wiersza nie stoi już na ekranie */
  --op-mv-strip-w:      12px;   /* szerokość pionowego paska strony w wierszu operatora; szkic 10px */
  --op-mv-strip-h:      56px;   /* wysokość paska strony, stała niezależnie od liczby wierszy; szkic 52px */
  --op-mv-strip-hit:    4px;    /* najmniejsza wysokość segmentu z trafieniem; zastane */
  --op-mv-ops-max:      520px;  /* NOWE: tabela operatorów jest tak szeroka, jak jej treść, i nie szersza */
  --op-mv-sticky-top:   96px;   /* NOWE: odstęp przyklejonego spisu tytułów od górnej krawędzi okna; równy wysokości paska nawigacji raportu, żeby spis nigdy nie wchodził pod niego */
  --op-mv-list-h:       min(62svh, 460px);  /* NIEUŻYWANE od 2026-09-03: spis nie ma własnego przewijania, bo dwa przewijane obszary pod jednym kursorem to była usterka, nie funkcja */
  --op-mv-list-h-open:  min(calc(100svh - 2 * var(--op-mv-sticky-top)), 560px);  /* NIEUŻYWANE, jak wyżej */
  --op-mv-mask-up:      linear-gradient(to bottom, rgb(0 0 0), transparent);  /* NIEUŻYWANE: wygaszenie krawędzi spisu zdjęte razem z jego przewijaniem */
  --op-mv-mask-down:    linear-gradient(to top, rgb(0 0 0), transparent);     /* NIEUŻYWANE, jak wyżej */
  --op-bp-mv-short:     660px;  /* wysokość okna, pod którą przyklejona kolumna tytułów jedzie ze stroną (do wklejenia; @media nie czyta var()). Zmierzone 2026-09-03 z WYŁĄCZONYMI przejściami: kolumna w stanie otwartym ma 449px i stoi 96px od góry, więc przyklejona potrzebuje 545px okna. Audyt tego samego dnia podniósł próg do 1200px na odczycie 998px zrobionym w trakcie 320ms przejścia - i tym samym odkleił kolumnę na każdym zwykłym laptopie */
  --op-mv-who-w:        180px;  /* NOWE: kolumna nazwy i adresu operatora, żeby pozycje zaczynały się w każdym wierszu w tym samym miejscu */
  --op-mv-mark-rule:    3px;    /* NOWE: kreska w kolorze studia pod jego znakiem, czyli klucz kolor do studia tego panelu */
  --op-bp-mv-op:        560px;  /* NOWE: pozycje schodzą pod nazwę operatora (do wklejenia; @media nie czyta var()) */
  --op-mv-brace-w:      2px;    /* NOWE: klamra spinająca tytuły jednego numeru w stanie otwartym; szkic nie miał żadnego znaku przynależności */
  --op-mv-brace-cap:    8px;    /* NOWE: zawinięcie klamry na jej obu końcach */

  /* --- kontrolki ---------------------------------------------------------- */
  --op-focus-ring:      2px;    /* NOWE: grubość obrysu focus. Wartość zastana w base.html.twig:68 (obrys 2px #29A6A4), dotąd bez nazwy */

  /* --- punkty łamania (do wklejenia; @media nie czyta var()) -------------- */
  --op-bp-mv:           900px;  /* spis i panel przestają stać obok siebie */
  --op-bp-mv-sm:        640px;  /* karta bierze szerokość rzędu i przewija się ze snapem */
}
