/* ============================================================================
   Keepino — tokeny marki „Precyzja"
   ----------------------------------------------------------------------------
   Dwie warstwy, celowo rozdzielone:

   1. PRYMITYWY  (:root, --kp-*)
      Sama paleta i typografia. Nic nie maluje — wczytanie tego pliku NIE zmienia
      wyglądu aplikacji. Bezpieczne do wpięcia od razu.

   2. MOTYW      ([data-brand=precision])
      Przemapowanie semantycznych zmiennych aplikacji (--canvas, --ink, --accent…)
      z motywu „Highlighter" na Precyzję. Włącza się jednym atrybutem:
          <html data-brand="precision">
      i wyłącza jego usunięciem. styles.css zostaje nietknięty.

   Kolejność wczytywania: brand.css PO styles.css.
       <link rel="stylesheet" href="css/styles.css">
       <link rel="stylesheet" href="css/brand.fa45fb48.css?d=9b04846">
   ============================================================================ */

:root {
  /* ── rdzeń marki ─────────────────────────────────────────────────────────
     Pięć kolorów z brand-boardu. Wszystko poniżej to ich pochodne.          */
  --kp-papier: #ECEBE3;   /* tło       */
  --kp-tusz:   #17181C;   /* tekst     */
  --kp-kobalt: #2743E8;   /* sygnał    */
  --kp-grafit: #6B6D66;   /* drugorzęd */
  --kp-karta:  #FFFFFF;   /* karta     */

  /* ── papier / tusz: skala neutralna (ciepła, nie siwa) ────────────────── */
  --kp-n-000: #FFFFFF;
  --kp-n-050: #F7F6F0;
  --kp-n-100: #ECEBE3;    /* = Papier */
  --kp-n-200: #E1DFD5;
  --kp-n-300: #DAD9CE;    /* linie     */
  --kp-n-400: #C6C5B9;    /* linie mocniejsze */
  --kp-n-500: #9A9A90;
  --kp-n-600: #6B6D66;    /* = Grafit  */
  --kp-n-700: #4A4C50;
  --kp-n-800: #2C2E33;
  --kp-n-900: #17181C;    /* = Tusz    */

  /* ── kobalt: skala sygnału ────────────────────────────────────────────────
     Kontrast (WCAG, tekst normalny):
       500 na Papierze ....... 5.75:1  ✓ AA
       400 na Nocy (n-950) ... 4.31:1  ✓ AA large / UI, ✗ AA body
       300 na Nocy ........... 6.94:1  ✓ AA        ← linki w ciemnym motywie
     Dlatego jasny motyw używa 500, ciemny 400 na akcenty i 300 na tekst.    */
  --kp-c-050: #EEF0FF;
  --kp-c-100: #DDE1FF;
  --kp-c-200: #B9C0FF;
  --kp-c-300: #8894FF;
  --kp-c-400: #5468FF;
  /* 450 istnieje dla JEDNEJ roli: wypełnienie kontrolki głównej w Nocy.
     500 jest za ciemne wobec Nocy 950 (2,5:1 < 3:1 z WCAG 1.4.11), 400 jest za
     jasne pod biel (4,37:1 < 4,5:1). 450 przechodzi oba warunki naraz —
     biel 5,95:1, kafel vs tło 3,17:1 — i nadal jest kobaltem, nie lawendą. */
  --kp-c-450: #3550EE;
  --kp-c-500: #2743E8;    /* = Kobalt */
  --kp-c-600: #2136C4;
  --kp-c-700: #1B2FA8;

  /* ── noc: ciemne powierzchnie wyprowadzone z Tuszu ─────────────────────────
     Neutralne, nie granatowe — dzisiejsze #0d0d13 ciągnie w niebieski,
     co bije się z kobaltem. Te są zbudowane wokół #17181C.                  */
  --kp-noc-950: #101115;
  --kp-noc-900: #15161A;
  --kp-noc-850: #1A1B20;
  --kp-noc-800: #23242A;
  --kp-noc-700: #2B2C33;
  --kp-noc-600: #3A3B43;

  /* ── typografia ───────────────────────────────────────────────────────────
     Monospace jest krojem marki. Dla tekstu dokumentu patrz --kp-font-doc:
     mono w interfejsie = precyzja, mono w akapicie na 5 tysiącach znaków
     = zmęczone oczy. Rozdzielenie jest zamierzone.                          */
  --kp-font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas,
                  "Liberation Mono", monospace;
  --kp-font-doc:  -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
                  Roboto, Helvetica, Arial, sans-serif;

  --kp-tracking-display: -.045em;  /* wordmark, duże nagłówki */
  --kp-tracking-tight:   -.02em;
  --kp-tracking-label:    .08em;   /* etykiety wersalikami   */

  /* ── kształt ──────────────────────────────────────────────────────────── */
  --kp-radius-sm: 6px;
  --kp-radius:    10px;
  --kp-radius-lg: 14px;
  --kp-radius-tile: 22.3%;         /* proporcja kafla aplikacji (114/512) */
}

/* ============================================================================
   MOTYW — Precyzja na jasnym (papier + tusz + kobalt)
   ============================================================================ */

[data-brand=precision][data-theme=light],
[data-brand=precision]:not([data-theme=dark]) {
  --canvas: var(--kp-n-100);
  --side: var(--kp-n-050);
  --surface: var(--kp-karta);
  --surface-2: var(--kp-n-200);
  --inset: var(--kp-n-050);

  --ink: var(--kp-n-900);
  --muted: var(--kp-n-600);
  --faint: var(--kp-n-500);
  --border: var(--kp-n-300);
  --border-soft: var(--kp-n-200);

  --accent: var(--kp-c-500);
  --accent-ink: #fff;

  /* zakreślacz zostaje żółty — to jedyny drugi sygnał w produkcie
     i naprawdę oznacza „to jest zaznaczone", więc go nie ruszamy */
  --hl: rgba(245, 197, 66, .38);
  --hl-strong: rgba(245, 197, 66, .72);

  --ok: #1F8A5B;
  --danger: #C8353B;

  /* graf — jedna rodzina z kobaltem, nie tęcza */
  --g-summary: #2743E8;
  --g-concept: #157F5F;
  --g-entity:  #A96A12;
  --g-inbox:   #2C6E9B;
  --g-todo:    #B23A55;

  --edge: rgba(255, 255, 255, .8);
  --shadow: 0 1px 2px rgba(23, 24, 28, .05), 0 10px 30px rgba(23, 24, 28, .07);
  --dot: color-mix(in srgb, var(--kp-n-400) 62%, transparent);
}

/* ============================================================================
   MOTYW — Precyzja Noc (tusz + papier + kobalt 400)
   Nie „ciemny fiolet". Neutralne powierzchnie, żeby kobalt był jedynym
   kolorem na ekranie, który coś znaczy.
   ============================================================================ */

[data-brand=precision][data-theme=dark] {
  --canvas: var(--kp-noc-950);
  --side: var(--kp-noc-900);
  --surface: var(--kp-noc-850);
  --surface-2: var(--kp-noc-800);
  --inset: var(--kp-noc-850);

  --ink: #E8E7E0;
  --muted: #9A9A93;
  --faint: #77776F;
  --border: var(--kp-noc-700);
  --border-soft: var(--kp-noc-800);

  --accent: var(--kp-c-400);
  --accent-ink: #fff;

  --hl: rgba(245, 197, 66, .30);
  --hl-strong: rgba(245, 197, 66, .66);

  --ok: #34D399;
  --danger: #F2555A;

  --g-summary: #5468FF;
  --g-concept: #2AAE84;
  --g-entity:  #D09A34;
  --g-inbox:   #3E9BD1;
  --g-todo:    #E0637C;

  --edge: rgba(255, 255, 255, .045);
  --shadow: 0 1px 2px rgba(0, 0, 0, .45), 0 12px 38px rgba(0, 0, 0, .38);
  --dot: color-mix(in srgb, var(--kp-noc-600) 70%, transparent);
}

/* ============================================================================
   Typografia motywu — mono w interfejsie, proporcjonalny w treści dokumentu.
   ============================================================================ */

[data-brand=precision] {
  --ff: var(--kp-font-mono);
  --mono: var(--kp-font-mono);
  letter-spacing: -.005em;
}

/* Tekst dokumentu zostaje proporcjonalny — czytelność akapitu wygrywa
   z konsekwencją kroju. Jeśli chcesz mono wszędzie, usuń tę regułę. */
[data-brand=precision] .doc .blk,
[data-brand=precision] .doc p,
[data-brand=precision] .doc li {
  font-family: var(--kp-font-doc);
  letter-spacing: 0;
}

/* Tytuł dokumentu i etykiety zostają mono — tam mono czyta się jak precyzja. */
[data-brand=precision] .dochead .dt {
  font-family: var(--kp-font-mono);
  letter-spacing: var(--kp-tracking-tight);
}

/* ============================================================================
   Wordmark w interfejsie — RYSOWANA GEOMETRIA + kursor z CSS.
   Użycie:  <span class="kp-wordmark">{SVG}<i></i><span class="kp-sr">Keepino</span></span>
   (w apce składa to `wordmark()` z js/app.js).

   Do 2026-07-27 stało tu „składany z tokenów, bez pliku SVG": nazwa była SŁOWEM
   w foncie monospace. Guide book i landing rysowały ją z brand/wordmark.svg, więc
   apka pokazywała INNY KRÓJ niż reszta materiałów — zgłoszone przez właściciela
   („logo na mobilce jest inne niż na naszym guide booku"), README miał to
   odnotowane jako znane i nienaprawione.
   Sam brand/README.md mówi zresztą: „wordmark jest RYSOWANY, nie ustawiany z fontu
   (niezależność od SF Mono, która jest zamknięta)" — apka była jedynym miejscem,
   które tej zasady nie trzymało.

   `font-size` steruje całą skalą: SVG ma `height: 1em`, kursor jest podany w `em`,
   więc jedna liczba skaluje znak i kursor razem i nic się nie rozjeżdża.
   ============================================================================ */

.kp-wordmark {
  color: var(--ink, var(--kp-tusz));
  display: inline-flex;
  /* flex-end, nie baseline: w środku nie ma już tekstu, więc nie ma linii bazowej,
     na której kursor mógłby usiąść. Wyrównanie do dolnej krawędzi + margines
     w `em` odtwarza dokładnie pozycję z pliku marki. */
  align-items: flex-end;
  white-space: nowrap;
  line-height: 1;
}
/* (0,1,1) — bije `svg { width:18px; height:18px }` z styles.css (0,0,1) niezależnie
   od kolejności wczytywania arkuszy. Bez tego wordmark miałby 18 px i wyglądałby
   jak zgnieciona ikona. */
.kp-wordmark > svg {
  height: 1em;
  width: auto;
  display: block;
}
/* Kursor = podkreślnik na linii bazowej, NIE pionowa belka. Belka od ascendera do
   linii bazowej statycznie czyta się jako ósma litera („keepinol"). Podkreślnik jest
   poziomy, więc żadna litera nie ma jego kształtu — i dlatego wolno go animować:
   miganie jest dodatkiem, nie protezą ratującą nieczytelny kształt.
   Proporcje WPROST z pliku marki: w brand/wordmark.svg kursor to rect 30×16 przy
   wysokości znaku 62 jednostki, więc przy `height: 1em` wychodzi .484em szerokości,
   .258em wysokości i .226em nad dolną krawędzią. Wcześniejsze .52 × .28 były
   przybliżeniem pod tekst w foncie — teraz obok stoi prawdziwa geometria, więc
   przybliżenie byłoby widoczne jako przesunięcie. Te same liczby ma landing
   (`.lp-poster__cur`), i to jest cel: jeden kursor, jedno miejsce, jedna wartość. */
.kp-wordmark > i {
  display: block;
  flex: 0 0 auto;
  width: .484em;
  height: .258em;
  margin-left: .1em;
  margin-bottom: .226em;
  border-radius: 1px;
  background: var(--accent, var(--kp-kobalt));
}

/* Miganie ma DWA tryby, bo WCAG 2.2.2 („Pause, Stop, Hide") nie zakazuje migania bez końca —
   wymaga, żeby dla czegokolwiek migającego dłużej niż 5 s istniał MECHANIZM zatrzymania.
   Stąd:
     [data-blink]          → 3 × 1.1 s = 3.3 s. Poniżej progu 5 s, więc żaden mechanizm nie
                             jest potrzebny. Bezpieczny domyślny wybór dla powierzchni, na
                             których nie ma gdzie postawić przełącznika.
     [data-blink="always"] → bez końca. WOLNO, ale tylko tam, gdzie mechanizm ISTNIEJE:
                             w apce to Ustawienia → Ruch, w reszcie systemowe „ogranicz ruch".
   Osobna sprawa to wyjątek „essential” z 2.2.2: kursor w POLU WPISYWANIA jest niezbędny do
   zadania i jest z wymogu zwolniony. Nasz kursor w logo jest dekoracyjny, więc się na ten
   wyjątek nie powołujemy — dajemy prawdziwy przełącznik zamiast naciąganej interpretacji.
   Częstotliwość: 1/1.1 s ≈ 0.9 Hz, czyli daleko pod progiem 3 błysków/s z WCAG 2.3.1. */
/* `[data-blink=""]`, nie `[data-blink]` — celowo. Goły atrybut w HTML ma wartość pustą, więc
   ten selektor łapie WYŁĄCZNIE tryb „raz". Gdyby zostało `[data-blink]`, łapałoby też
   `="always"`; oba selektory mają tę samą specyficzność (0,2,0), więc rozstrzygałaby
   KOLEJNOŚĆ w pliku — i przestawienie tych dwóch linii po cichu skróciłoby migotanie
   bez końca do trzech cykli. Taki błąd jest niewidoczny w code review. */
.kp-wordmark[data-blink=""] > i { animation: kp-blink 1.1s step-end 3; }
.kp-wordmark[data-blink="always"] > i { animation: kp-blink 1.1s step-end infinite; }
@keyframes kp-blink { 50% { opacity: 0; } }
/* Systemowe „ogranicz ruch" wygrywa z każdym trybem — także z „always”. To jest ta ścieżka,
   którą dostają ludzie z nadwrażliwością na ruch, i nie wolno jej ominąć ustawieniem w apce. */
@media (prefers-reduced-motion: reduce) {
  .kp-wordmark[data-blink] > i { animation: none; }   /* goły atrybut ŁAPIE OBA tryby — tu tak chcemy */
}

/* ============================================================================
   DODATEK — tokeny pod kit komponentów (css/kit.12e18770.css?d=9b04846)
   ----------------------------------------------------------------------------
   Dopisane, nic nie nadpisują. Blok istnieje, bo kit potrzebował ról, których
   w rdzeniu nie było: kolor stanu „ostrzeżenie", ciemniejsze warianty zieleni
   i czerwieni pod TEKST (--ok/--danger same z siebie nie mają 4.5:1 na
   Papierze), obrys kontrolki o kontraście ≥3:1 (WCAG 1.4.11) i rytm kontrolek.
   ============================================================================ */

:root {
  /* ── stany: skale pod tekst, wypełnienie i tinty ────────────────────────────
     Kontrast policzony (tekst normalny):
       ok-700  #14724A na Papierze .... 4.97:1  ✓ AA   (samo --ok = 3.62:1  ✗)
       warn-700 #8A5A00 na Papierze ... 4.96:1  ✓ AA
       err-700 #B62A30 na Papierze .... 5.22:1  ✓ AA   (samo #C8353B = 4.36:1 ✗)
       biel na err-500 #C8353B ........ 5.21:1  ✓ AA
       ok-300 / warn-300 / err-300 na Nocy ...... >5:1 ✓ AA               */
  --kp-ok-700:   #14724A;
  --kp-ok-500:   #1F8A5B;
  --kp-ok-300:   #34D399;
  --kp-warn-700: #8A5A00;
  --kp-warn-500: #B07A12;
  --kp-warn-300: #F0C24B;
  --kp-err-700:  #B62A30;
  --kp-err-500:  #C8353B;
  --kp-err-300:  #F2555A;
  --kp-err-200:  #FF7A7E;

  /* Noc 500 — obrys kontrolki w ciemnym motywie. noc-600 dawało tylko 1.55:1
     na powierzchni karty, czyli za mało na widoczną ramkę pola/checkboxa.
     #6A6B75 na noc-850 = 3.25:1 ✓ (WCAG 1.4.11, komponent nietekstowy).      */
  --kp-noc-500: #6A6B75;

  /* ── rytm kontrolek ─────────────────────────────────────────────────────── */
  --kp-h-sm: 32px;          /* przycisk/pole „sm"            */
  --kp-h-md: 40px;          /* przycisk/pole domyślne        */
  --kp-tap:  44px;          /* minimalny cel dotykowy (HIG)  */

  --kp-sp-1: 4px;
  --kp-sp-2: 8px;
  --kp-sp-3: 12px;
  --kp-sp-4: 16px;
  --kp-sp-5: 24px;
  --kp-sp-6: 32px;

  --kp-fs-xs: 11px;         /* etykiety wersalikami, badge   */
  --kp-fs-sm: 12.5px;       /* przyciski, tabela, podpowiedzi*/
  --kp-fs-md: 14px;         /* tekst interfejsu (mono)       */
  --kp-fs-lg: 16px;         /* tytuł karty / dialogu         */

  --kp-radius-pill: 999px;

  /* ── ostrość i ruch ─────────────────────────────────────────────────────── */
  --kp-ring-w:   2px;
  --kp-ring-off: 2px;
  --kp-dur-1: 90ms;         /* „mig" — wciśnięcie            */
  --kp-dur-2: 160ms;        /* przejście stanu               */
  --kp-ease: cubic-bezier(.2, .7, .3, 1);
}

/* ── role semantyczne: jasny motyw ────────────────────────────────────────── */
[data-brand=precision][data-theme=light],
[data-brand=precision]:not([data-theme=dark]) {
  --focus: var(--kp-c-500);
  --border-strong: var(--kp-n-600);   /* obrys kontrolki: 5.24:1 na bieli */

  --accent-text: var(--kp-c-500);     /* kobalt jako TEKST/ikona          */
  /* --kp-spark — JEDEN węzeł znaku, ten u góry („żywy worker"). Reszta znaku jedzie
     `currentColor`, czyli tuszem. Bez tej zmiennej `MARK` w js/app.js spadał na
     `currentColor` i cały znak stawał się kobaltowy — dokładnie ten „jednolity
     niebieski", który właściciel odrzucił 2026-07-27. Na jasnym tle znak marki jest
     CZARNO-NIEBIESKI i tylko taki: tusz + jeden kobaltowy węzeł, zgodnie z mark.svg. */
  --kp-spark: var(--kp-c-500);
  --fill:        var(--kp-c-500);     /* wypełnienie kontrolki głównej    */
  --fill-ink:    var(--kp-karta);
  --fill-hover:  var(--kp-c-600);
  --fill-active: var(--kp-c-700);

  --ok-ink:     var(--kp-ok-700);
  --warn:       var(--kp-warn-500);
  --warn-ink:   var(--kp-warn-700);
  --danger-ink: var(--kp-err-700);

  --danger-fill:       var(--kp-err-500);
  --danger-fill-ink:   var(--kp-karta);
  --danger-fill-hover: var(--kp-err-700);

  --scrim: rgba(23, 24, 28, .48);
}

/* ── role semantyczne: Noc ─────────────────────────────────────────────────────
   Wypełnienie kontrolki głównej to w ciemnym motywie kobalt **300 + tusz**,
   nie 400 + biel: biel na #5468FF ma 4.37:1 (✗ AA dla 12–14 px), a tusz na
   #8894FF ma 6.53:1 ✓ i sam kafel odbija się od tła 6.7:1. Kobalt 400 zostaje
   pierścieniem ostrości, kobalt 300 tekstem akcentu (400 jako tekst = 3.93:1 ✗).
   ────────────────────────────────────────────────────────────────────────────── */
[data-brand=precision][data-theme=dark] {
  --focus: var(--kp-c-400);
  --border-strong: var(--kp-noc-500);

  /* POPRAWKA 2026-07-26 (sesja DESIGN). Było `--fill: --kp-c-300` + tusz i pod
     kątem kontrastu było poprawnie (tusz na #8894FF = 6,53:1 ✓) — ale kobalt 300
     to już nie kobalt: na ekranie czytał się jako LAWENDA i to on odpowiadał za
     zgłoszenie „apka nie wygląda jak design". Błąd BARWY, nie kontrastu, więc
     żaden pomiar AA go nie łapał.
     Argument „biel na #5468FF ma 4,37:1 ✗" dotyczy kobaltu 400 i jest prawdziwy —
     pomijał jednak, że wypełnieniem może zostać kobalt 500 (biel na #2743E8 =
     7,6:1 ✓). Samo 500 jest za ciemne wobec Nocy 950 (2,5:1, poniżej 3:1 z WCAG
     1.4.11), dlatego jest krok pośredni — 450:
       biel na kobalcie 450 #3550EE ... 5,95:1  ✓ AA
       kafel 450 vs Noc 950 ........... 3,17:1  ✓ 1.4.11
     Trójka jest teraz spójna, każdy odcień robi jedną rzecz:
       300 = tekst akcentu · 400 = pierścień ostrości · 450 = wypełnienie. */
  --accent-text: var(--kp-c-300);
  /* W Nocy węzeł na kobalcie 400 — ten sam odcień, który dla ciemnego tła wybiera
     `brand/mark-dark.svg`. 500 byłby za ciemny obok papierowego tuszu znaku. */
  --kp-spark: var(--kp-c-400);
  --fill:        var(--kp-c-450);
  --fill-ink:    var(--kp-karta);
  --fill-hover:  var(--kp-c-400);
  --fill-active: var(--kp-c-300);

  --ok-ink:     var(--kp-ok-300);
  --warn:       var(--kp-warn-300);
  --warn-ink:   var(--kp-warn-300);
  --danger-ink: var(--kp-err-300);

  --danger-fill:       var(--kp-err-300);
  --danger-fill-ink:   var(--kp-n-900);
  --danger-fill-hover: var(--kp-err-200);

  --scrim: rgba(0, 0, 0, .62);
}
