/* ── Panel edytorski Big History — fundament stylów ──────────────────────────
   Jedno źródło prawdy dla wyglądu panelu. Linkowane z layouts/app.blade.php
   (cache-busting przez filemtime). Bez Vite/preprocesorów — czysty CSS. */

:root {
    --bg:#f6f5f2; --panel:#fff; --line:#e3e0d8;
    --ink:#2b2b2b; --muted:#7a756b; --accent:#b5613a; --accent-dark:#a4542f;
    /* --draft świadomie WYPADA z ciepłej rodziny (terakota / bursztyn / cegła / oliwka):
       stan publikacji to inna oś niż świeżość treści, a oliwka siadała zbyt blisko
       amber `--warn` — na liście oba sygnały czytało się jak jeden. */
    --ok:#2f6b3a; --warn:#9a6b1c; --danger:#9b3b1c; --draft:#5a4b9c;
    --field-bg:#fff; --field-disabled:#f1efe9;
}

* { box-sizing:border-box; }
body { margin:0; font:15px/1.5 system-ui,-apple-system,Segoe UI,Roboto,sans-serif; color:var(--ink); background:var(--bg); }
a { color:var(--accent); text-decoration:none; }
a:hover { text-decoration:underline; }
code { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:.92em; }

/* ── Szkielet strony ─────────────────────────────────────────────────────── */
header.topbar { display:flex; align-items:center; justify-content:space-between;
    padding:.7rem 1.2rem; background:var(--panel); border-bottom:1px solid var(--line);
    position:sticky; top:0; z-index:100; }
header.topbar .brand { font-weight:600; display:flex; align-items:center; gap:1.2rem; }
header.topbar .brand-name { color:var(--ink); text-decoration:none; display:inline-flex; align-items:center; gap:.5rem; }
header.topbar .brand-name:hover { text-decoration:none; }
header.topbar .brand-logo { width:22px; height:22px; flex:none; color:#e0b25c; }
header.topbar .brand nav { display:flex; gap:.2rem; font-weight:400; font-size:.92rem; }
header.topbar .brand nav a { padding:.3rem .6rem; border-radius:6px; color:var(--ink); }
header.topbar .brand nav a:hover { text-decoration:none; background:var(--bg); }
header.topbar .brand nav a.active { color:var(--accent); background:rgba(181,97,58,.1); font-weight:600; }
header.topbar .brand nav .nav-dd { position:relative; display:flex; align-items:center; }
/* Nagłówek dropdownu: button udający pozycję paska (nie nawiguje, tylko otwiera). */
header.topbar .brand nav .nav-dd-top { font:inherit; color:var(--ink); cursor:pointer;
    padding:.3rem .6rem; border:0; border-radius:6px; background:none; }
header.topbar .brand nav .nav-dd-top:hover { background:var(--bg); }
header.topbar .brand nav .nav-dd-top.active { color:var(--accent); background:rgba(181,97,58,.1); font-weight:600; }
header.topbar .brand nav .nav-dd-top .caret { font-size:.7em; opacity:.55; }
header.topbar .brand nav .nav-dd-menu { position:absolute; top:100%; left:0; min-width:160px;
    background:var(--panel); border:1px solid var(--line); border-radius:6px;
    box-shadow:0 4px 14px rgba(0,0,0,.12); padding:.25rem;
    display:none; flex-direction:column; gap:.1rem; z-index:110; }
header.topbar .brand nav .nav-dd:hover .nav-dd-menu,
header.topbar .brand nav .nav-dd:focus-within .nav-dd-menu { display:flex; }
header.topbar .brand nav .nav-dd-menu a { display:block; white-space:nowrap; }
header.topbar .user { color:var(--muted); font-size:.9rem; display:flex; align-items:center; gap:.8rem; }
/* Awatar konta — inicjały na kolorowym kółku (App\Support\Avatar; tło wstrzykiwane
   inline, bo kolor jest per konto). `flex:none` obowiązkowe: bez niego kółko
   spłaszcza się w elipsę, gdy na dłuższą nazwę zabraknie miejsca w pasku. */
.avatar { --avatar-size:1.7rem;
    display:inline-flex; align-items:center; justify-content:center; flex:none;
    width:var(--avatar-size); height:var(--avatar-size); border-radius:50%;
    color:#fff; font-size:.68rem; font-weight:600; letter-spacing:.02em;
    font-family:'Fira Sans Condensed', var(--font, inherit); }

/* Nazwa konta prowadzi do profilu, ale nie ma krzyczeć jak pozycja nawigacji:
   kolor jak reszta paska, podkreślenie dopiero pod kursorem. Podkreślenie siedzi
   na SPANIE z nazwą, nie na linku — na linku przeciągnęłoby kreskę także pod
   awatarem, bo dekoracja tekstu schodzi na potomków. */
header.topbar .user .user-link { color:inherit; text-decoration:none;
    display:inline-flex; align-items:center; gap:.45rem; }
header.topbar .user .user-link:hover { color:var(--ink); }
header.topbar .user .user-link:hover > span:not(.avatar) { text-decoration:underline; }
header.topbar .user .user-link.active { color:var(--ink); font-weight:500; }
main { max-width:1100px; margin:0 auto; padding:1.5rem 1.2rem; }
main.main--wide { max-width:1160px; }
main.main--wider { max-width:1320px; }

/* ── Nagłówek widoku ─────────────────────────────────────────────────────── */
.page-head { display:flex; align-items:baseline; justify-content:space-between; gap:1rem; margin-bottom:1rem; }
.page-title { font-size:1.3rem; font-weight:600; }
.page-head .page-title { margin:0; }
.page-title .count { color:var(--muted); font-weight:400; }
.toolbar { display:flex; gap:.6rem; align-items:center; }

/* ── Karty i sekcje ──────────────────────────────────────────────────────── */
.card { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:1.4rem; margin-bottom:1rem; }
.card--flush { padding:0; overflow:hidden; }            /* opakowanie tabeli */
.card--login { max-width:380px; margin:3rem auto 1rem; }
.card--narrow { max-width:560px; }                      /* formularz ustawień, nie treści */

/* Odznaka roli konta (lista Users). Admin dostaje akcent, bo to uprawnienie,
   które ma rzucać się w oczy przy przeglądaniu listy; editor zostaje neutralny. */
.role { display:inline-block; padding:.05rem .45rem; border-radius:999px; font-size:.78rem; }
.role--editor { background:#efece5; color:var(--muted); }
.role--admin { background:#f3e3c9; color:#8a5a00; font-weight:500; }
.section-label { font-weight:600; font-size:.85rem; color:var(--muted); margin-bottom:.6rem; }
.section-label--upper { text-transform:uppercase; font-size:.8rem; }
.section-label .hint { font-weight:400; }
.note { margin:.2rem 0 1rem; font-size:.85rem; color:var(--muted); }

/* ── Formularze ──────────────────────────────────────────────────────────── */
.form-narrow { max-width:760px; }
label.field { display:block; margin-bottom:1rem; }
label.field:last-child { margin-bottom:0; }
label.field span { display:block; font-size:.85rem; color:var(--muted); margin-bottom:.25rem; }

/* Pionowy segment: label + summary złączone (wspólny szew, promień tylko na
   zewnętrznych rogach) — jak .seg, ale w pionie i z polami tekstowymi. Rogi przy
   szwie spłaszczane jawnie (:first/:last-child = (0,2,0) bije input[type=text]
   = (0,1,1)); zewnętrzne rogi z bazowego border-radius pola. */
.text-seg { display:flex; flex-direction:column; }
.text-seg > * { position:relative; }
.text-seg > *:first-child { border-bottom-left-radius:0; border-bottom-right-radius:0; }
.text-seg > *:last-child { border-top-left-radius:0; border-top-right-radius:0; }
.text-seg > * + * { margin-top:-1px; }
.text-seg > *:focus { z-index:1; }

input[type=text], input[type=email], input[type=password], input[type=number],
textarea, select {
    width:100%; padding:.5rem .6rem; border:1px solid var(--line); border-radius:6px;
    font:inherit; color:var(--ink); background:var(--field-bg);
}
textarea { line-height:1.5; resize:vertical; }
select[multiple] { padding:.4rem; }
input:disabled, select:disabled { background:var(--field-disabled); color:var(--muted); cursor:not-allowed; }
input:focus, textarea:focus, select:focus {
    outline:none; border-color:var(--accent); box-shadow:0 0 0 2px rgba(181,97,58,.15);
}

input.field-ro { background:var(--field-disabled); color:var(--muted); cursor:default; }
input.field-ro:focus { border-color:var(--line); box-shadow:none; }

.field-grid { display:grid; grid-template-columns:1fr 1fr; gap:0 1rem; }
/* Karta TAGS: Dominant | Color (dwa kwadraty) | Importance (wąski, obok Color).
   MUSI być po .field-grid — równa specyficzność, wygrywa reguła późniejsza. */
.field-grid--tagmeta { grid-template-columns:1fr auto 1fr; align-items:start; }

/* Pole Color — własny nagłówek (NIE klasa .field, by display:block nie nadpisywał
   atrybutu [hidden] na innych .field, np. chowanym End). Dwa kwadraty wielkości
   inputa: lewy DZIEDZICZONY (klik kasuje własny), prawy WŁASNY wybór; is-active =
   który kolor obowiązuje. */
.field-color { margin-bottom:1rem; }
.field-color > span { display:block; font-size:.85rem; color:var(--muted); margin-bottom:.25rem; }
.color-field { display:flex; gap:.4rem; align-items:center; }
/* Point: pole tylko do wglądu — blokujemy interakcję, ale NIE wyszarzamy (kwadraty
   wciąż pokazują prawdziwy dziedziczony kolor; klik i tak nic by nie zmienił). */
.color-field.is-disabled { pointer-events:none; }
.color-sq {
    width:2.25rem; height:2.25rem; padding:0; box-sizing:border-box;
    border:1px solid var(--line); border-radius:6px; cursor:pointer; background:transparent;
    transition:box-shadow .12s, border-color .12s;
}
/* Oba kwadraty ZAWSZE w pełnej barwie (porównywalne). Który obowiązuje pokazuje sam
   pierścień accent + grubsza ramka — nie wyszarzanie. */
.color-sq.is-active {
    border-color:var(--accent); border-width:2px;
    box-shadow:0 0 0 3px rgba(181,97,58,.35);
}
/* Ukryty picker nałożony na swatch — niewidoczny, ale ZAJMUJE miejsce (nie display:none),
   by natywny popover kotwiczył się przy swatchu, nie w rogu 0,0. pointer-events:none →
   klik przechodzi do swatcha pod spodem; picker otwieramy przez .click() z JS. */
.color-own-wrap { position:relative; display:inline-flex; }
.color-own-picker {
    position:absolute; inset:0; width:100%; height:100%;
    opacity:0; pointer-events:none; border:none; padding:0; margin:0;
}

.check { display:flex; align-items:center; gap:.4rem; font-size:.9rem; }
.check input { width:auto; }
.inp-pos { width:64px; padding:.2rem .4rem; }

.form-actions { display:flex; gap:.6rem; align-items:center; }
/* Sticky pasek akcji formularza — przykleja się pod topbarem (top = wys. topbara). */
.form-head { position:sticky; top:51px; z-index:50; display:flex; align-items:center;
    justify-content:space-between; gap:1rem; padding:.7rem 0; margin-bottom:.6rem;
    background:var(--bg); border-bottom:1px solid var(--line); }
.form-head .page-title { margin:0; }
.form-head-actions { display:flex; gap:.6rem; align-items:center; flex:none; }
/* Zrównanie wyglądu <a> i <button> w pasku, ODPORNE też na rozszerzenia przeglądarki.
   Chrome bywa źródłem „injected stylesheet" (rozszerzenie wstrzykuje np.
   `.btn-primary{padding:8px;border-radius:4px}`, specyficzność 0,1,0), które bije bazowe
   `button` i psuje TYLKO przycisk z klasą .btn-primary (Publish). Ta reguła ma
   specyficzność 0,1,1 (wyższą), więc wymuszony tu box — stała wysokość 38px, radius 6px,
   poziomy padding — wygrywa nad wstrzykniętą regułą. appearance:none zdejmuje natywną
   chromę <button>; flex-centrowanie + całkowita wysokość eliminują też subpikselowe
   rozjazdy przy skalowaniu ekranu. */
.form-head-actions a, .form-head-actions button {
    appearance:none; -webkit-appearance:none;
    display:inline-flex; align-items:center; justify-content:center;
    height:38px; line-height:1; padding:0 .8rem; border-radius:6px; }
.btn-ghost { display:inline-block; padding:.4rem .8rem; border:1px solid var(--line);
    border-radius:6px; color:var(--ink); background:var(--panel); }
.btn-ghost:hover { border-color:var(--muted); text-decoration:none; }
.form-sticky-foot { position:sticky; bottom:0; background:var(--bg); padding:.8rem 0; border-top:1px solid var(--line); }

/* ── Przyciski ───────────────────────────────────────────────────────────── */
button, input[type=submit] { font:inherit; cursor:pointer; border:1px solid var(--line);
    background:var(--panel); color:var(--ink); border-radius:6px; padding:.4rem .8rem; }
button:hover, input[type=submit]:hover { border-color:var(--muted); }
/* Stan disabled: bez tej reguły przycisk (np. Autofill przy pustym polu) wygląda
   identycznie jak aktywny — brak sygnału, że jest zablokowany. Wygaszamy i zdejmujemy
   efekt hover (opacity nie odróżniałoby stanu, gdyby hover nadal reagował). */
button:disabled, input[type=submit]:disabled { opacity:.5; cursor:not-allowed; }
button:disabled:hover, input[type=submit]:disabled:hover { border-color:var(--line); }
.btn-primary { background:var(--accent); color:#fff; border-color:var(--accent); }
.btn-primary:hover { background:var(--accent-dark); border-color:var(--accent-dark); }
.btn-primary:disabled:hover { background:var(--accent); border-color:var(--accent); }
.btn-danger { background:var(--panel); color:#c0392b; border-color:#c0392b; }
.btn-danger:hover { background:#fbeae5; border-color:#c0392b; }
.btn-block { width:100%; }
button.link { border:none; background:none; color:var(--accent); padding:0; }
button.link:hover { text-decoration:underline; background:none; }
.link-danger { color:var(--danger); }
/* Ikona „Translate" na czterech listach, gdy bytowi brakuje któregoś tłumaczenia.
   Świeci OSTRZEJ niż `.link-stale` (amber, niżej) — pełnym kołem, nie tylko kolorem.

   Sam odcień NIE WYSTARCZA i to jest zmierzone: neutralna ikona to `--accent` #b5613a,
   brak `--danger` #9b3b1c, nieaktualny `--warn` #9a6b1c — trzy warianty tego samego
   ciepłego brązu, nie do rozróżnienia na kreskach 2 px. Odkąd wiersz nie koloruje się
   od długu przekładu, ikona jest JEDYNYM nośnikiem, więc różnicę niesie KSZTAŁT:
   brak = wypełnione koło, nieaktualny = samo obramowanie. */
.link-missing { color:var(--danger); font-weight:600; }
/* Koło jest WIĘKSZE od ikony, ale ujemny margines pionowy trzyma je poza rachunkiem
   wysokości linii: bez tego wiersze z sygnałem rosły o kilka pikseli i lista traciła
   równy rytm (a przy przewijaniu widać to bardziej niż sam kolor). */
a.link-missing, a.link-stale { display:inline-flex; align-items:center; justify-content:center;
    width:1.45rem; height:1.45rem; margin-block:-.2rem; vertical-align:middle;
    border-radius:50%; line-height:1; }
a.link-missing { background:var(--danger); color:#fff; }
a.link-missing:hover { background:#7d2f16; }
/* Etykieta podstawiona z EN, bo w języku roboczym redaktora jej nie ma (work-label).
   Wyszarzona świadomie: lista ma być użyteczna, ale nie udawać, że przekład istnieje. */
.trans-fallback { color:var(--muted); font-style:italic; }
button.link:disabled, button.link[disabled] { color:var(--muted); opacity:.5; cursor:not-allowed; text-decoration:none; }

/* ── Ikony akcji (same ikony zamiast tekstu Edit/Translate/Delete/Detach) ──── */
.ico { width:1.15em; height:1.15em; fill:none; stroke:currentColor; stroke-width:2;
    stroke-linecap:round; stroke-linejoin:round; vertical-align:-.18em; }
/* Link/przycisk będący samą ikoną: bez podkreślenia w hoverze, miękki nacisk. */
a:has(> .ico), button.link:has(> .ico) { text-decoration:none; }
a:has(> .ico):hover, button.link:has(> .ico):hover { opacity:.7; text-decoration:none; }

/* ── Komunikaty ──────────────────────────────────────────────────────────── */
.errors { background:#fbeae5; border:1px solid #e7c3b6; color:var(--danger);
    padding:.6rem .8rem; border-radius:6px; margin-bottom:1rem; font-size:.9rem; }
.flash { padding:.6rem .9rem; border-radius:6px; margin-bottom:1rem; font-size:.92rem; }
.flash.ok { background:#e9f3ea; border:1px solid #bcd9c0; color:var(--ok); }
.flash.err { background:#fbeae5; border:1px solid #e7c3b6; color:var(--danger); }
.flash ul { margin:.3rem 0 0; padding-left:1.1rem; }

/* ── Tabele ──────────────────────────────────────────────────────────────── */
table.grid { width:100%; border-collapse:collapse; font-size:.92rem; }
table.grid thead tr { text-align:left; background:#efece5; color:var(--muted); }
table.grid th, table.grid td { padding:.25rem .8rem; }
table.grid tbody tr { border-top:1px solid var(--line); }
/* Stałe szerokości kolumn — jednakowe między działami Tag dictionary. */
/* Ostatnie zmiany na pulpicie: ciaśniejszy wiersz, żeby 12 pozycji zmieściło się
   w wysokości karty ze słupkami kompletności. */
table.grid--dash th, table.grid--dash td { padding:.21rem .8rem; }

table.grid--fixed { table-layout:fixed; }
table.grid--fixed th, table.grid--fixed td { overflow:hidden; text-overflow:ellipsis; }
table.grid--fixed th:nth-child(1), table.grid--fixed td:nth-child(1) { width:24%; }  /* Slug */
table.grid--fixed th:nth-child(2), table.grid--fixed td:nth-child(2) { width:36%; }  /* Label */
table.grid--fixed th:nth-child(3), table.grid--fixed td:nth-child(3) { width:19%; }  /* Actions */
table.grid--fixed th:nth-child(4), table.grid--fixed td:nth-child(4) { width:9%; }   /* Events */
table.grid--fixed th:nth-child(5), table.grid--fixed td:nth-child(5) { width:12%; }  /* Contexts */

/* Pojemniki osi — cztery tabele (Eons/Eras/Periods/Epochs) jedna pod drugą, więc
   szerokości MUSZĄ być stałe: przy auto-layoucie każdy dział liczyłby je od własnej
   treści i kolumny przeskakiwałyby między kartami. Actions przy prawej krawędzi. */
table.grid--axis { table-layout:fixed; }
table.grid--axis th, table.grid--axis td { overflow:hidden; text-overflow:ellipsis; }
table.grid--axis th:nth-child(1), table.grid--axis td:nth-child(1) { width:26%; }  /* Slug */
table.grid--axis th:nth-child(2), table.grid--axis td:nth-child(2) { width:32%; }  /* Label */
table.grid--axis th:nth-child(3), table.grid--axis td:nth-child(3) { width:12%; }  /* Short */
/* Start/End — wczesny wszechświat daje długie „10^-32 s", stąd szerzej niż Short. */
table.grid--axis th:nth-child(4), table.grid--axis td:nth-child(4) { width:9%; }   /* Start */
table.grid--axis th:nth-child(5), table.grid--axis td:nth-child(5) { width:9%; }   /* End */
table.grid--axis th:nth-child(6), table.grid--axis td:nth-child(6) { width:12%; }  /* Actions */

/* ── Drobiazgi tekstowe / utility ────────────────────────────────────────── */
.mono { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:.85rem; }
.muted { color:var(--muted); }
.parent-line { margin:.85rem 0 0; padding-top:.7rem; border-top:1px solid var(--line); font-size:.9rem; }
.parent-line strong { color:var(--ink); }
.card.is-locked { opacity:.7; }
.field-invalid { border-color:var(--danger); }
.num { font-variant-numeric:tabular-nums; }
.right { text-align:right; }
.center { text-align:center; }
.nowrap { white-space:nowrap; }
.stat-ok { color:var(--ok); }
.stat-machine { color:var(--warn); }
.stat-missing { color:var(--danger); }

/* ── Drzewo klastra (rekurencyjne) ───────────────────────────────────────── */
.tree { margin:.2rem 0 .2rem 1rem; padding-left:.6rem; border-left:1px solid var(--line); list-style:none; }
.tree li { margin:.2rem 0; }
.tree-row { display:flex; align-items:center; justify-content:space-between; gap:.5rem; }
.tree-detach { border:none; background:none; cursor:pointer; padding:0 .25rem; line-height:1;
    color:var(--muted); font-size:.95rem; }
.tree-detach:hover { color:var(--danger); }

/* ── Klaster: dzieci ─────────────────────────────────────────────────────── */
.child-row { display:flex; align-items:center; justify-content:space-between; padding:.35rem 0; border-bottom:1px solid var(--line); }
.attach-row { display:flex; gap:.5rem; align-items:center; margin-top:.9rem; }

/* ── Kategorie tagów: lista z przeciąganiem ──────────────────────────────── */
.cat-list { list-style:none; margin:0; padding:0; }
.cat-row { display:flex; align-items:center; gap:.8rem; padding:.5rem .9rem; border-bottom:1px solid var(--line); }
.cat-row:last-child { border-bottom:none; }
.cat-row .mono { min-width:14rem; }
.cat-row .cat-label { flex:1; }
.cat-row .cat-color { display:flex; align-items:center; gap:.3rem; }
.cat-row .cat-color input[type=color] { width:1.8rem; height:1.4rem; padding:0; border:1px solid var(--line); border-radius:3px; background:none; cursor:pointer; }
.cat-row .num { min-width:5rem; text-align:right; }
.cat-row .cat-actions { white-space:nowrap; }
.cat-handle { cursor:grab; color:var(--muted); user-select:none; }
.cat-ghost { opacity:.5; background:var(--bg); }
.cat-order { margin-top:.9rem; }
.cat-row .cat-ctx { min-width:2.5rem; text-align:center; color:var(--accent); }
.cat-head { font-size:.78rem; text-transform:uppercase; letter-spacing:.04em; }
/* Kropka koloru kategorii przy tytule działu (widok Events „By category"). */
.cat-swatch { display:inline-block; width:.7rem; height:.7rem; border-radius:50%;
    border:1px solid rgba(0,0,0,.15); vertical-align:baseline; margin-right:.15rem; }
/* Ulotny komunikat AJAX-owego zapisu (wiersze tłumaczeń, kanoniczny EN). */
.ajax-flash { margin-left:.5rem; font-size:.8rem; color:var(--ok); white-space:nowrap; }
.ajax-flash.is-err { color:var(--danger); }
.ajax-flash.fade { animation:ajax-flash-fade 2.2s forwards; }
@keyframes ajax-flash-fade { 0%,55% { opacity:1; } 100% { opacity:0; } }
.cat-head .cat-handle { cursor:default; }

/* Lista kamieni landingu (Milestones) — na bazie .cat-row. */
/* Własna strzałka (chevron): natywna strzałka selecta ma sztywny, ciasny odstęp od
   krawędzi (Chrome ignoruje padding-right) — a złączenie z „+ Add" jeszcze ją dociska.
   appearance:none + SVG w kolorze --muted daje typowy oddech (strzałka .75rem od
   krawędzi, tekst odsunięty padding-right:2rem). Tło zostaje z bazowego selecta. */
.ms-add-select {
    flex:1;
    appearance:none; -webkit-appearance:none;
    padding-right:2rem;
    background-image:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%237a756b' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat:no-repeat;
    background-position:right .75rem center;
    background-size:.7rem;
}
/* Dodawanie kamienia: select + „+ Add" złączone w jeden SEGMENT (jak .ai-seed-row /
   kontrolki na TIMING). Modyfikator obok .attach-row — tamtej klasy nie ruszamy, bo
   dzielą ją categories i attach-child. align-items:stretch zrównuje wysokość select↔button;
   ujemny margines liczuje krawędzie, promień tylko na skrajnych rogach. Przycisk bez
   disabled — akcja jest obsłużona (walidacja `required` + serwer). */
.ms-add-row { gap:0; align-items:stretch; }
/* Celujemy wprost w select/button, nie w :first/:last-child — @csrf wstawia ukryty
   input _token jako pierwsze dziecko formularza (display:none, więc poza layoutem,
   ale strukturalnie łapałby :first-child i zjadał lewy promień). */
.ms-add-row > select, .ms-add-row > button { border-radius:0; position:relative; }
.ms-add-row > select { border-top-left-radius:6px; border-bottom-left-radius:6px; }
.ms-add-row > button { margin-left:-1px; border-top-right-radius:6px; border-bottom-right-radius:6px; }
.ms-add-row > :focus { z-index:1; }
.ms-row .ms-type { min-width:3.4rem; font-size:.72rem; text-transform:uppercase; letter-spacing:.04em;
    text-align:center; padding:.1rem .4rem; border-radius:4px; border:1px solid var(--line); color:var(--muted); }
.ms-row .ms-type--tag { color:var(--accent); border-color:var(--accent); }
/* Wiersz kamienia jest ZBUDOWANY JAK W CATEGORIES: slug (mono, szerokość z .cat-row)
   + etykieta w języku roboczym. Kotwica `↳ id (oldest)` mieści się w linii daty —
   „(oldest)" opisuje KOTWICĘ (tag bez representative_event bierze najstarszy datowany
   event), więc nie schodzi pod datę. Dzięki temu KAŻDY wiersz jest jednolinijkowy,
   tej samej wysokości co na liście kategorii. */
.ms-row .ms-label { flex:1; min-width:0; }
.ms-row .ms-date { display:flex; flex-direction:column; align-items:flex-end; gap:.05rem;
    min-width:11rem; text-align:right; }
.ms-row .ms-date-line { display:flex; align-items:baseline; gap:.5rem; }
.ms-row .ms-date .ms-anchor { font-size:.85rem; }
.ms-row .ms-date .ms-via { color:var(--warn); }
.ms-row .ms-date .ms-warn { color:var(--danger); font-size:.82rem; }
/* Nagłówek kolumn nosi styl `thead` z list Events/Tags (jasny pasek, tekst wyszarzony,
   bez wersalików), ale klasy wiersza — inaczej kolumny miałyby własne szerokości.
   Pastylka typu schodzi do zwykłego napisu; uchwyt i akcje są ukryte przez visibility,
   żeby skrajne kolumny mierzyły się treścią wiersza, nie pustką. */
.ms-head { background:#efece5; color:var(--muted); font-size:.92rem; font-weight:700;
    padding-top:.25rem; padding-bottom:.25rem; }
/* Nagłówek nie jest kodem — kolumna slugu pożycza od wiersza tylko SZEROKOŚĆ. */
.ms-head .mono { font-family:inherit; font-size:inherit; }
.ms-head .ms-type { border-color:transparent; padding:0;
    font-size:inherit; text-transform:none; letter-spacing:normal; text-align:left; color:inherit; }
.ms-head .cat-handle, .ms-head .cat-actions { visibility:hidden; }

/* ── Perspektywy: poziomy ────────────────────────────────────────────────── */
.level-row { border:1px solid var(--line); border-radius:8px; padding:.8rem; margin-bottom:.7rem; }
.level-head { display:flex; align-items:center; gap:1rem; margin-bottom:.5rem; }

/* ── Tłumacz ─────────────────────────────────────────────────────────────── */
.lang-tabs { display:flex; gap:.5rem; }
.lang-tabs a { padding:.25rem .6rem; border-radius:6px; border:1px solid var(--line); color:var(--ink); }
.lang-tabs a:hover { text-decoration:none; border-color:var(--muted); }
.lang-tabs a.active { background:var(--accent); color:#fff; border-color:var(--accent); }
.progress-row { display:flex; align-items:center; gap:1.2rem; }
.progress { flex:1; height:10px; background:#efece5; border-radius:5px; overflow:hidden; }
.progress > i { display:block; height:100%; background:var(--accent); }
/* Worek kompletności: dobre | nieaktualne | reszta paska = puste (tło). Trzy stany
   w jednym pasku, żeby język dało się ocenić jednym spojrzeniem. */
.progress--split { display:flex; }
.progress--split > i { height:100%; }
.progress--split .seg-ok { background:var(--ok); }
.progress--split .seg-stale { background:var(--warn); }
.stat-stale { color:var(--warn); }
.progress-stats { font-size:.9rem; color:var(--muted); white-space:nowrap; }
.mini-label { font-size:.78rem; color:var(--muted); margin-bottom:.15rem; }
/* Widok „Tłumacz" (event-centryczny) — EN na górze + tabela wierszy per język. */
/* Nagłówek karty z przełącznikiem po prawej. `.card-head` = ta sama mechanika przy karcie
   natywnej (drugi kosmetyk); `.trans-en-head` zostaje nazwą historyczną karty CANONICAL. */
.trans-en-head, .card-head { display:flex; align-items:center; justify-content:space-between; gap:1rem; margin-bottom:.6rem; }
.tr-en-fields { display:grid; grid-template-columns:1fr 2fr; gap:0 1rem; }
.tr-en-fields .field { margin-bottom:0; }
/* Translate pojemnika osi, tagu i perspektywy: szew między kolumnami karty CANONICAL ma wypaść w tym samym
   miejscu, co szew „label & short | summary" w tabeli niżej. Karta ma padding 1.4rem,
   tabela nie, więc równych proporcji nie da się przepisać wprost — lewa kolumna to
   trzecia część szerokości siatki minus stała korekta, wyprowadzona z torów `.tr-row`
   (3.2rem | 1fr | 2fr | 6.8rem) i różnicy paddingów. Zmieniasz tory wiersza → przelicz:
   lewa kolumna = 33.3333% − (kolumna języka + ostatnia kolumna − padding karty − gap)/3
   po sprowadzeniu do szerokości siatki karty. Korekta `− 50px` to TA SAMA korekta, jaką
   dostaje kolumna label w `.tr-row` — szew jedzie w lewo na obu kartach równo. */
.tr-en-fields--aligned { grid-template-columns:calc(33.3333% - 1.6rem - 50px) 1fr; gap:.8rem 1rem; }
/* Lewa kolumna karty CANONICAL osi: label + short trzymają się razem u góry, niezależnie
   od tego, jak wysokie zrobi się summary obok. */
.tr-en-stack { display:flex; flex-direction:column; gap:.8rem; align-self:start; }
/* Edit tag CANONICAL: lewa kolumna meta (slug/category/milestone) obok złączonego
   segmentu label+description (jak w Edit event). Textarea rośnie, by dorównać w dół.
   Szew 1:2 z korektą `− 50px` — ta sama, co w tabelach Translate (`.tr-row`). */
.tr-canon-grid { display:grid; grid-template-columns:calc((100% - 1rem)/3 - 50px) 1fr; gap:0 1rem; align-items:stretch; }
/* Toolbar markerów + Preview (wstawia summary-preview.js za polem prozy) trafia do siatki
   jako TRZECI element — auto-placement wrzuciłby go pod kolumnę meta, po lewej. Ma stać
   pod prozą: lewa krawędź równa z textarea, Preview dosunięty w prawo (jak w Edit event).
   Dotyczy obu stron z tą kartą: Edit tag i Edit perspective. */
.tr-canon-grid > .summary-tools { grid-column:2; }
.tr-canon-meta { display:flex; flex-direction:column; gap:1rem; }
.tr-canon-meta .field { margin-bottom:0; }
.tr-canon-text { height:100%; }
/* `flex:1` (basis 0) kazałoby przeglądarce zignorować wysokość, którą wpisuje
   autogrow.js — pole stałoby sztywno na wysokości lewej kolumny. `1 0 auto`:
   basis = własna wysokość pola (rośnie z tekstem), grow dociąga je do dna, gdy
   krótszy tekst nie dorównuje kolumnie meta. */
.tr-canon-text > textarea { flex:1 0 auto; min-height:7rem; resize:vertical; }
/* Nazwa pola w kolumnie meta w JEDNEJ linii z hintem (patrz reguła niżej). */
.tr-canon-meta .field > span { white-space:nowrap; }
/* Hint w tej samej linii co etykieta: bazowe `label.field span { display:block }`
   łapie też zagnieżdżony .hint i łamałby „Slug — immutable" na dwie linie. */
/* …ale sam hint MOŻE się złamać: po przesunięciu szewu w lewo kolumna meta jest węższa
   niż najdłuższy hint („— changing it renames the tag everywhere"), a przy `nowrap`
   wychodził on poza kolumnę, na prozę. Łamie się więc w środku hintu — nazwa pola
   zostaje przy nim w pierwszej linii. */
.tr-canon-meta .hint { display:inline; white-space:normal; }
.tr-en-actions { display:flex; align-items:center; gap:.5rem; }
/* Podgląd kroku A (AI): status + native do oceny sensu, niezapisywany. */
/* AI „Draft from name": pole nazwy + przycisk Autofill u góry formularza nowego eventu,
   złączone w jeden SEGMENT (jak .date-parts/.unc-enh na karcie TIMING): wspólna krawędź
   przez ujemny margines, promień tylko na skrajnych rogach, brak przerwy. align-items:
   stretch zrównuje wysokość mimo różnych paddingów input/button. Bez overflow:hidden —
   focus-ring inputu wynosimy z-index-em ponad sąsiada, żeby nie był przycięty. */
.ai-seed-row { display:flex; align-items:stretch; }
.ai-seed-row > input { flex:1; }
/* Reset kwalifikowany elementem, by pobić bazowe input[type=text]/button { border-radius:6px }. */
.ai-seed-row > input, .ai-seed-row > button { border-radius:0; margin-left:-1px; position:relative; }
.ai-seed-row > :first-child { margin-left:0; border-top-left-radius:6px; border-bottom-left-radius:6px; }
.ai-seed-row > :last-child { border-top-right-radius:6px; border-bottom-right-radius:6px; }
.ai-seed-row > :focus { z-index:1; }
.ai-status { font-size:.85rem; color:var(--muted); margin-top:.5rem; }
.ai-status.is-error { color:#b91c1c; }

/* „Translate to EN (AI)" — przycisk w wierszu label (prawy górny róg segmentu):
   label rośnie, przycisk dosunięty, złączone z textarea poniżej (płaskie dolne rogi). */
.seg-hrow { display:flex; }
.seg-hrow > input { flex:1; border-right:none; border-radius:0; border-top-left-radius:6px; }
.seg-hrow > .seg-hrow-btn { flex:none; white-space:nowrap; display:inline-flex; align-items:center;
    border-radius:0; border-top-right-radius:6px; }
/* Sekcja przeglądu (muted, do porównania). */
.refine-current, .refine-review { margin-top:.6rem; }
.review-cap { font-size:.78rem; color:var(--muted); margin:0 0 .3rem; }
/* Segment wyblakły: read-only, dashed — jednoznacznie „do porównania, nie edycji". */
.text-seg--muted > * { background:var(--field-disabled); color:var(--muted); border-style:dashed; cursor:default; }
.text-seg--muted > *:focus { box-shadow:none; border-color:var(--line); }
.refine-notes { margin-top:.7rem; padding:.55rem .7rem; border:1px solid var(--line);
    border-radius:6px; background:var(--bg); }
.refine-notes-body { margin:0; font-size:.9rem; color:var(--ink); white-space:pre-wrap; }
/* Tabela tłumaczeń w stylu „excelowym": pola bez własnych obwódek, tylko poziome
   linie wierszy (bez pionowych kresek). Save i Lang w osobnych kolumnach. */
.tr-table { overflow:hidden; }
/* Nagłówek AI translate w jednej karcie z tabelą — wspólny temat (bez linii nad tabelą). */
.tr-ai-head { padding:1.1rem; }
/* Scope + Translate (AI) jako jeden segment przy prawej/górnej krawędzi karty. */
.tr-ai-controls { display:flex; align-items:center; gap:.5rem; }
.tr-scope { display:flex; align-items:center; gap:.5rem; margin:0; }
.tr-scope > span { font-size:.85rem; color:var(--muted); }
/* Ostatnia kolumna STAŁA, nie `auto`: przy `auto` wiersz z dodatkowym przyciskiem
   („still current" pojawia się tylko przy nieaktualnym języku) rozpychał swoją kolumnę
   i rozjeżdżał tekst względem sąsiadów — a siatka ma się czytać jak tabela. Szerokość
   z pomiaru wariantu ZWYKŁEGO (Save + badge stanu + prawy margines 1.4rem, którym
   kolumna dosuwa się do pionu przycisku Preview) — nie najszerszego. Rzadszy wariant
   z „still current" (tylko język nieaktualny) zawija przycisk do drugiej linii, zamiast
   trzymać pustkę w każdym wierszu; odzyskane miejsce idzie do summary.
   UWAGA: `.tr-en-fields--aligned` liczy szew karty CANONICAL z TYCH torów. */
/* Kolumna label: proporcja 1:2 wobec summary (stąd trzecia część miejsca po odjęciu
   kolumn stałych), przesunięta o 50 px w lewo — tekstu przekładu jest zwykle więcej niż
   etykiety. Liczby, nie `fr`, bo szew musi dać się przepisać karcie CANONICAL wyżej. */
.tr-row { display:grid; grid-template-columns:3.2rem minmax(150px,calc((100% - 10rem)/3 - 50px)) minmax(200px,1fr) 6.8rem;
          gap:0; align-items:center; border-top:1px solid var(--line); margin:0; }
.tr-row:first-child { border-top:none; }
/* Oddech pod dolnym rzędem (short / Preview), żeby pola nie siadały na kresce wiersza.
   Nagłówek jest technicznie `.tr-row`, ale niesie same napisy — jego by rozepchnęło. */
.tr-row:not(.tr-head) { padding-bottom:10px; }
.tr-row > * { padding:.25rem .7rem; }
.tr-head { font-size:.78rem; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; }
/* Wiersz ma DWA rzędy: górny niesie label i Save, dolny `short` (tylko oś) oraz gniazdo
   przycisku Preview. Oba dolne dosunięte do dna rzędu (`align-self:end`), więc ich dolne
   krawędzie leżą na jednej linii. Summary przechodzi przez oba rzędy.
   Nagłówek `.tr-head` zostaje jednorzędowy — jego spany idą auto-placementem. */
.tr-row > .tr-summary { grid-row:1 / span 2; }
/* Kod języka stoi w GÓRNYM rzędzie, nie przez oba: przez oba wypadał w połowie wysokości
   wiersza, czyli poniżej etykiety, którą opisuje. W jednym rzędzie z label i tak samo
   wyśrodkowany trafia dokładnie w jego linię. */
.tr-row > .tr-lang { grid-row:1; }
.tr-row > .tr-label { grid-column:2; grid-row:1; }
.tr-row > .tr-short { grid-column:2; grid-row:2; align-self:end; }
/* Save opuszczony o 5 px — czyste przesunięcie optyczne (`top`), nie padding: komórka
   jest centrowana w rzędzie, więc dokładanie do niej wysokości przesunęłoby ją o połowę. */
.tr-row > .tr-save { grid-column:4; grid-row:1; position:relative; top:5px; }
.tr-row > .tr-prev { grid-column:4; grid-row:2; display:flex; justify-content:flex-end;
    align-self:end; padding-right:1.4rem; }
/* Skrótowiec paska osi. `short` JEST komórką (input), więc padding komórki działa mu
   w środku i nie odsuwa go od dna rzędu — dolny odstęp musi dać margines, inaczej pole
   siada 4 px niżej niż przycisk Preview, który stoi w divie z paddingiem. */
.tr-row > .tr-short { width:100%; font-size:.8rem; margin-bottom:.25rem; }
/* Pola bez ramki/tła — komórka siatki je obejmuje; aktywna komórka podświetlana. */
.tr-row textarea { margin:0; width:100%; resize:none; overflow:hidden; box-sizing:border-box;
                   border:none; border-radius:0; background:transparent; padding:.3rem .7rem; }
.tr-row textarea:focus { outline:none; box-shadow:none; }
.tr-row:focus-within { background:rgba(181,97,58,.05); }
/* Label: textarea jednoliniowa, zawija długi tekst, rośnie od 1 wiersza (JS). */
.tr-row .tr-label { font-weight:600; min-height:0; white-space:pre-wrap; padding-left:.35rem; }
/* ── Półka materiałów (sekcja MEDIA formularza eventu) ─────────────────────────
   Lista wgranych materiałów; ilustrację w treść wstawia toolbar summary (przycisk „obraz"). */
.media-shelf__items { display:flex; flex-direction:column; gap:.5rem; margin:.5rem 0; }
.media-shelf__empty { margin:.3rem 0; font-size:.85rem; color:var(--muted); }
.media-item { display:flex; align-items:flex-start; gap:.7rem; padding:.5rem;
              border:1px solid var(--line); border-radius:6px; }
.media-item__thumb { position:relative; width:120px; height:80px; flex:none; display:flex;
              align-items:center; justify-content:center; border-radius:4px; overflow:hidden;
              background:rgba(127,127,127,.12); color:var(--muted); font-size:1.4rem; }
.media-item__thumb img { width:100%; height:100%; object-fit:cover; }
.media-item__badge { position:absolute; left:3px; bottom:3px; padding:0 .3rem; border-radius:3px;
              background:rgba(0,0,0,.65); color:#fff; font-size:.6rem; letter-spacing:.05em; }
.media-item__body { flex:1; min-width:0; display:flex; flex-direction:column; gap:.35rem; }
.media-item__handle { display:flex; align-items:baseline; gap:.5rem; flex-wrap:wrap; }
.media-item__handle code { font-size:.9rem; color:var(--accent); overflow-wrap:anywhere; }
.media-item__handle .hint { overflow-wrap:anywhere; }
/* Kontrolki bloku (rozmiar + oblewanie) w jednym rzędzie; zawijają się na wąsko. */
.media-item__controls { display:flex; flex-wrap:wrap; align-items:center; gap:.35rem 1.1rem; }
.media-item__row { display:flex; align-items:center; gap:.5rem; }
.media-item__row select { padding:.15rem .4rem; font-size:.85rem; }
.media-item__row.is-disabled { opacity:.45; }  /* pozycja bez sensu przy size=full */
.media-item__del { flex:none; padding:.15rem .45rem; border:1px solid var(--line);
              border-radius:4px; background:transparent; color:var(--muted); cursor:pointer; }
.media-item__del:hover { border-color:#c0392b; color:#c0392b; }
.media-item__status { font-size:.8rem; color:var(--muted); }
.media-item__status.is-err { color:#c0392b; }
/* Warianty językowe pliku (zwijane; rzadki przypadek). */
.media-item__variants { font-size:.82rem; color:var(--muted); }
.media-item__variants > summary { cursor:pointer; padding:.15rem 0; user-select:none; }
.media-variant { display:flex; align-items:center; gap:.5rem; padding:.15rem 0; }
.media-variant__lang { width:2.2rem; font-weight:600; }
.media-variant__key { overflow-wrap:anywhere; color:var(--ink); }
.media-variant__rm { border:none; background:transparent; color:var(--muted); cursor:pointer; }
.media-variant__pick { width:4.5rem; padding:.1rem .35rem; font-size:.8rem; font-weight:600; }
.media-variant--add { cursor:pointer; }
.media-variant input[type=file] { font-size:.78rem; }
/* Strefa dodawania: zakładki źródeł (Upload / Library / YouTube) w wyodrębnionym bloku.
   Tytuł „ADD MEDIA" żyje NAD blokiem, nie w nim. */
.media-add__label { margin:.8rem 0 .35rem; font-size:.72rem; font-weight:600; letter-spacing:.06em;
             text-transform:uppercase; color:var(--muted); }
/* Bez otaczającego boxa (ramka/tło obejmowały wszystko i górą wyglądały jak dodatkowa
   „mega-zakładka"). Ramkę nosi teraz sam korpus paneli; zakładki-„teczki" siadają na
   jego górnej krawędzi (margin-bottom:-1px zszywa aktywną z korpusem). */
.media-add__tabs { display:flex; gap:.4rem; }
.media-add__tab { padding:.25rem .7rem; border:1px solid var(--line); border-bottom:none;
             border-radius:6px 6px 0 0; background:transparent; color:var(--ink); cursor:pointer;
             font-size:.85rem; margin-bottom:-1px; position:relative; }
.media-add__tab:hover { border-color:var(--muted); }
.media-add__tab.is-active { background:var(--accent); color:#fff; border-color:var(--accent); }
.media-add__panels { padding:.7rem .8rem; border:1px solid var(--line);
             border-radius:0 6px 6px 6px; background:rgba(127,127,127,.05); }
/* Stała wysokość korpusu — najwyższy panel (Upload) wyznacza próg, więc przełączanie
   zakładek nie przesuwa treści pod spodem. */
.media-add__panel { display:flex; flex-wrap:wrap; align-content:center; align-items:center;
             gap:.5rem .8rem; min-height:3.2rem; }
.media-add__panel[hidden] { display:none; }  /* display:flex bije UA [hidden]{display:none} — trzeba jawnie */
.media-add__exts { flex-basis:100%; font-size:.8rem; color:var(--muted); }
.media-add__file { display:flex; flex-direction:column; gap:.15rem; font-size:.9rem; }
.media-add__yt { display:flex; align-items:center; gap:.4rem; }
.media-add > .media-item__status:not(:empty) { padding-top:.4rem; }
.media-add__url { padding:.25rem .5rem; font-size:.85rem; min-width:16rem; }
.media-add__ytbtn { padding:.2rem .6rem; }
/* Picker uchwytów pod przyciskiem „obraz" na toolbarze summary. */
.summary-mediapick { display:flex; flex-wrap:wrap; gap:.4rem; margin:.35rem 0; padding:.5rem;
             border:1px solid var(--line); border-radius:6px; background:var(--panel, transparent); }
.summary-mediapick__empty { font-size:.85rem; color:var(--muted); }
.summary-mediapick__item { display:flex; align-items:center; gap:.4rem; padding:.25rem .45rem;
             border:1px solid var(--line); border-radius:5px; background:transparent; cursor:pointer; }
.summary-mediapick__item:hover { border-color:var(--accent); }
.summary-mediapick__item img { width:40px; height:28px; object-fit:cover; border-radius:3px; }
.summary-mediapick__ph { width:40px; height:28px; display:flex; align-items:center; justify-content:center;
             border-radius:3px; background:rgba(127,127,127,.12); color:var(--muted); }
.summary-mediapick__item code { font-size:.82rem; color:var(--accent); }
/* Figura ilustracji w podglądzie summary (marker) — parytet z read plane (timeline.css):
   size = bucket szerokości, position (align) = strona z oblewaniem (float). Buckety
   przeskalowane do węższego kontenera podglądu, żeby float zostawił miejsce na tekst obok. */
.summary-preview .node-media { margin:.7rem auto; max-width:18rem; border-radius:6px; overflow:hidden; }
.summary-preview .node-media--small  { max-width:12rem; }
.summary-preview .node-media--medium { max-width:18rem; }
.summary-preview .node-media--wide   { max-width:26rem; }
.summary-preview .node-media--full   { max-width:100%; }
/* Pozycja: left/right = float (tekst oblewa z drugiej strony); center (brak klasy) = blok
   wyśrodkowany (margin auto). full nie oblewa (brak miejsca na tekst obok) → wraca do bloku. */
.summary-preview .node-media--align-left  { float:left;  margin:.3rem 1rem .7rem 0; }
.summary-preview .node-media--align-right { float:right; margin:.3rem 0 .7rem 1rem; }
.summary-preview .node-media--full.node-media--align-left,
.summary-preview .node-media--full.node-media--align-right { float:none; margin:.7rem auto; }
.summary-preview .node-media__img { display:block; width:100%; height:auto; }
.summary-preview .node-media__video { display:block; width:100%; height:auto; background:#000; }

/* Biblioteka mediów (/media) — miniatury + znacznik sieroty. */
.media-lib__thumb { display:block; width:56px; height:42px; object-fit:cover; border-radius:4px; background:#efece5; }
.media-lib__thumb--none { display:flex; align-items:center; justify-content:center; color:var(--muted); font-size:1.1rem; }
.chip--orphan { display:inline-block; padding:.05rem .4rem; border-radius:999px; font-size:.72rem;
                background:#f3e3c9; color:#8a5a00; }

/* Picker ponownego użycia mediów (modal nad formularzem eventu). */
.media-add__libbtn { padding:.35rem .7rem; border:1px solid var(--line); border-radius:6px;
                     background:#fff; cursor:pointer; font-size:.9rem; }
.media-add__libbtn:hover { background:#efece5; }
.media-picker { position:fixed; inset:0; z-index:50; display:flex; align-items:center; justify-content:center;
                background:rgba(20,18,14,.5); padding:1rem; }
.media-picker__panel { background:var(--surface, #fff); border-radius:10px; max-width:760px; width:100%;
                       max-height:80vh; display:flex; flex-direction:column; box-shadow:0 10px 40px rgba(0,0,0,.3); }
.media-picker__head { display:flex; align-items:center; justify-content:space-between; padding:.8rem 1rem;
                      border-bottom:1px solid var(--line); }
.media-picker__close { border:0; background:none; font-size:1.1rem; cursor:pointer; color:var(--muted); }
.media-picker__grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(130px, 1fr)); gap:.6rem;
                      padding:1rem; overflow-y:auto; }
.media-picker__cell { display:flex; flex-direction:column; gap:.3rem; padding:.4rem; border:1px solid var(--line);
                      border-radius:8px; background:#fff; cursor:pointer; text-align:left; }
.media-picker__cell:hover { border-color:var(--accent, #8a5a00); }
.media-picker__cell img { width:100%; height:88px; object-fit:cover; border-radius:5px; background:#efece5; }
.media-picker__ph { display:flex; align-items:center; justify-content:center; height:88px; border-radius:5px;
                    background:#efece5; color:var(--muted); font-size:1.4rem; }
.media-picker__name { font-size:.74rem; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.media-picker__cell.is-used { opacity:.6; }
.media-picker__used { font-size:.68rem; color:#8a5a00; }
.summary-preview .node-media__embed { display:block; width:100%; aspect-ratio:16/9; }
.summary-preview .node-media__embed iframe { width:100%; height:100%; border:0; }
.summary-preview .node-media__caption { margin-top:.3rem; font-size:.8rem; font-style:italic;
             text-align:center; color:var(--muted); }
/* Kolumna Save (ostatnia): kompaktowy przycisk + ikona stanu obok. Dosunięta do
   PRAWEJ z tym samym marginesem, co przycisk Preview pod wierszem (padding karty
   CANONICAL, 1.4rem) — Save, znaczek stanu i Preview stoją w jednym pionie. Lewy
   padding komórki zdjęty: przy wąskim torze to była pustka, a zawartość i tak
   trzyma się prawej — miejsce oddane kolumnie summary. */
.tr-save { display:flex; flex-wrap:wrap; align-items:center; justify-content:flex-end;
    gap:.35rem .5rem; padding-left:0; padding-right:1.4rem; }
.tr-save button { padding:.2rem .6rem; line-height:1.3; }
/* „still current" schodzi na własną linię jako ostatni — Save i znaczek stanu (stała
   para każdego wiersza) zostają razem w pierwszej. */
.tr-save .sig-act { order:1; }
.tr-state { font-size:.9rem; color:var(--muted); }
/* Kolumna języka (pierwsza od lewej): kratka kodu, wyśrodkowana. */
.tr-lang { display:flex; align-items:center; justify-content:center; font-size:.85rem; }
/* Znacznik kodu języka (chip filtra na liście Events + wiersz tłumaczeń). */
.tr-dot { font-size:.72rem; font-weight:600; text-transform:uppercase; padding:.05rem .3rem; border-radius:4px; border:1px solid var(--line); }
.tr-dot.is-ok { color:var(--ok); border-color:var(--ok); }
.tr-dot.is-machine { color:var(--warn); border-color:var(--warn); }
.tr-dot.is-missing { color:var(--danger); border-color:var(--danger); opacity:.7; }

/* ── Pulpit (home) ───────────────────────────────────────────────────────── */
.stat-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); gap:1rem; margin-bottom:1.5rem; }
.stat-card { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:1.2rem 1.4rem; text-decoration:none; color:inherit; display:block; }
.stat-card:hover { text-decoration:none; border-color:var(--accent); }
.stat-card .stat-num { font-size:2rem; font-weight:600; line-height:1.1; }
.stat-card .stat-name { color:var(--muted); font-size:.9rem; margin-top:.2rem; }
.dash-cols { display:grid; grid-template-columns:1fr 1fr; gap:1rem; align-items:start; }
/* Worek kompletności jako SŁUPKI: kolumna na język, pod nią kod, niżej dług
   rozbity na cztery domeny (etykiety wierszy w lewej kolumnie siatki).
   Liczba > 0 jest linkiem do `?todo=<lang>` swojej listy; zero = pusta komórka. */
.trans-chart-scroll { overflow-x:auto; }
.trans-chart { display:grid; column-gap:.5rem; row-gap:.25rem; align-items:end; min-width:min-content; }
/* Słupek nie rozlewa się przy dwóch językach i nie chudnie przy dwudziestu. */
.tc-bar { width:min(100%, 2.4rem); margin-inline:auto; height:200px;
          display:flex; flex-direction:column-reverse;
          background:#efece5; border-radius:4px; overflow:hidden; }
.tc-bar > i { display:block; width:100%; }
.tc-bar .seg-ok { background:var(--ok); }
.tc-bar .seg-stale { background:var(--warn); }
.tc-lang { text-align:center; font-weight:600; text-transform:uppercase; font-size:.85rem;
           padding:.35rem 0 .5rem; border-bottom:1px solid var(--line); }
.tc-dom { font-size:.85rem; color:var(--muted); white-space:nowrap; padding-right:.6rem; }
.tc-cell { text-align:center; font-size:.85rem; min-height:1.3em; }
.tc-cell a { color:var(--muted); text-decoration:none; }
.tc-cell a:hover { color:var(--accent); text-decoration:underline; }
.action { display:inline-block; }
@media (max-width:720px) { .dash-cols { grid-template-columns:1fr; } }

/* ── Datowanie eventu (tryby Calendar/BP/After-BB) ───────────────────────── */
.dating-head { display:flex; justify-content:space-between; align-items:baseline; gap:1rem; }
.dating-bar { display:flex; align-items:center; gap:.75rem; flex-wrap:nowrap; margin-bottom:1rem; }
.dating-bar .seg { flex:0 0 auto; }
.seg[hidden], .dating-body[hidden] { display:none; }
.unc-inline { margin-left:auto; display:flex; align-items:center; gap:.4rem; font-size:.85rem; color:var(--muted); }
.unc-raw-input { width:120px; }
.unc-enh { display:inline-flex; gap:0; align-items:stretch; }
.unc-enh[hidden] { display:none; }
.unc-prefix, .unc-unit { width:auto; min-width:3rem; }
.unc-num { width:56px; }
.seg { display:inline-flex; border:1px solid var(--line); border-radius:8px; overflow:hidden; }
.seg-btn { border:none; border-radius:0; background:var(--panel); color:var(--ink);
    padding:.4rem .9rem; border-right:1px solid var(--line); }
.seg-btn:last-child { border-right:none; }
.seg-btn:hover { background:var(--bg); border-color:var(--line); }
.seg-btn.active { background:var(--accent); color:#fff; }
/* Marker „wartość zapisana w bazie" (tryb datowania / Extent) — kropka w rogu.
   currentColor: widoczna i na aktywnym (accent, biały tekst), i na nieaktywnym
   (panel, ciemny tekst). Pokazuje, którą opcję niesie zapis, gdy user ją zmieni. */
.seg-btn.is-saved { position:relative; }
.seg-btn.is-saved::after {
    content:''; position:absolute; top:4px; right:4px;
    width:5px; height:5px; border-radius:50%; background:currentColor; opacity:.7;
}
/* Przełącznik Flat/Tree na liście events: anchor-y stylizowane jak segmenty. */
.view-seg .seg-btn { text-decoration:none; display:inline-flex; align-items:center; font-size:.9rem; }
.view-seg .seg-btn:hover { text-decoration:none; }
table.grid .tree-pre { white-space:pre; color:var(--muted); opacity:.65; }
table.grid .tree-count { margin-right:.4rem; padding:0 .45rem; border-radius:6px;
    background:rgba(181,97,58,.12); color:var(--accent); font-size:.82rem; font-weight:600; }
/* Klaster w trybie Tree: klik w wiersz zwija/rozwija potomstwo. */
table.grid tr.is-cluster { cursor:pointer; }
table.grid tr.is-cluster:hover { background:var(--bg); }
table.grid tbody tr { transition:opacity .18s ease; }
/* Zwinięty klaster: chip ⊕N wypełniony akcentem (stan widoczny bez caretu). */
table.grid tr.is-collapsed .tree-count { background:var(--accent); color:#fff; }
/* Extent: radio stylizowane jak segmenty (działa bez JS). */
.extent-seg .seg-btn { display:inline-flex; align-items:center; cursor:pointer; }
.extent-seg .seg-btn input { position:absolute; opacity:0; pointer-events:none; }
.extent-seg .seg-btn:has(input:checked) { background:var(--accent); color:#fff; }
.dating-panel[hidden] { display:none; }
.date-parts, .bb-row { display:flex; gap:0; }
/* Inputy datowania (d/m/r/era, wartość+jednostka) i niepewności złączone w SEGMENT —
   wspólne krawędzie, promień tylko na końcach; wizualnie jak połączone buttony .seg.
   Ujemny margines zlicowuje sąsiednie ramki; bez overflow:hidden, żeby focus-ring
   inputu nie był przycięty (fokus wynosimy z-index-em ponad sąsiadów). */
/* Reset kwalifikowany elementem (input/select), by pobić bazowe input[type=…]
   { border-radius:6px } (specyficzność 0,1,1) — inaczej wewnętrzne rogi zostają zaokrąglone. */
.date-parts > input, .date-parts > select,
.bb-row > input, .bb-row > select,
.unc-enh > input, .unc-enh > select { border-radius:0; margin-left:-1px; position:relative; }
.date-parts > :first-child, .bb-row > :first-child, .unc-enh > :first-child {
    margin-left:0; border-top-left-radius:6px; border-bottom-left-radius:6px; }
.date-parts > :last-child, .bb-row > :last-child, .unc-enh > :last-child {
    border-top-right-radius:6px; border-bottom-right-radius:6px; }
.date-parts > :focus, .bb-row > :focus, .unc-enh > :focus { z-index:1; }
.date-parts .cal-y, .date-parts .cal-end-y { flex:2; }
.date-parts .cal-m, .date-parts .cal-d, .date-parts .cal-end-m, .date-parts .cal-end-d { flex:1; }
.date-parts .cal-era, .date-parts .cal-end-era { flex:0 0 3.6rem; width:3.6rem; padding-left:.4rem; padding-right:.2rem; }
.point-toggle { white-space:nowrap; }
/* Znacznik ery „BC" przy datach p.n.e. — mniejszy i węższy od liczby roku. */
.era-bc { font-size:.85em; letter-spacing:-.02em; color:var(--muted); display:inline-block; transform:scaleX(.92); transform-origin:left center; }
.bb-row input { flex:2; }
.bb-row select { flex:1; }
.preview { display:block; margin-top:.25rem; font-size:.8rem; color:var(--accent); min-height:1em; }
.bb-hint { display:block; margin-top:.25rem; font-size:.78rem; color:var(--muted); }

/* ── Wybrane tagi: pasek chipów (karta TAGS w evencie) ───────────────────── */
.tag-chips { list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:.4rem; }
.tag-chip { display:inline-flex; align-items:center; gap:.35rem; background:rgba(181,97,58,.1);
    border:1px solid #e0c7bb; border-radius:3px; padding:.1rem .2rem .1rem .5rem; font-size:.85rem; }
.tag-chip .chip-name { color:var(--ink); }
.tag-chip .chip-handle { cursor:grab; color:var(--muted); font-size:.85rem; line-height:1; user-select:none; }
.tag-chip .chip-handle:active { cursor:grabbing; }
.tag-chip .chip-del { border:none; background:none; padding:0 .25rem; color:var(--muted);
    font-size:.8rem; line-height:1; border-radius:4px; }
.tag-chip .chip-del:hover { color:var(--danger); background:rgba(155,59,28,.12); }
.tag-chip.chip-ghost { opacity:.4; }

/* ── Tag kanban: wspólny picker (pula działów + kubełki/pasma) ────────────── */
/* Fallback domyślnie widoczny; tag-kanban.js USUWA go z DOM po inicjalizacji. */
.tag-kanban-fallback { display:block; }

.tk-board { display:grid; grid-template-columns:1fr 320px; gap:1rem; align-items:start; }
@media (max-width:780px) { .tk-board { grid-template-columns:1fr; } }

.tk-list { list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:.4rem; }

/* Token = chip (ten sam byt w puli i w kubełku) */
.tk-token { display:inline-flex; align-items:center; gap:.35rem; background:rgba(181,97,58,.1);
    border:1px solid #e0c7bb; border-radius:3px; padding:.12rem .2rem .12rem .6rem;
    font-size:.85rem; line-height:1.3; cursor:grab; user-select:none; }
.tk-token:active { cursor:grabbing; }
.tk-token .tt-label { color:var(--ink); }
.tk-token .tt-x { border:none; background:none; padding:0 .25rem; color:var(--muted);
    font-size:.8rem; line-height:1; border-radius:4px; cursor:pointer; }
.tk-token .tt-x:hover { color:var(--danger); background:rgba(155,59,28,.12); }
.tk-token.sortable-ghost { opacity:.4; }
.tk-pool-list .tt-x { display:none; }               /* w puli × nie ma sensu */
.tk-pool-list .tk-token { padding:.18rem .55rem; }  /* kompaktowo jak .etag w events → więcej tagów w wierszu */

/* Kubełki / pasma (lewa kolumna, od najważniejszego u góry) */
.tk-left { display:flex; flex-direction:column; min-width:0; }
.tk-buckets { display:flex; flex-direction:column; gap:.6rem; }
.tk-bucket { border:1px solid var(--line); border-radius:8px; background:var(--bg); }
.tk-bucket-head { display:flex; align-items:center; justify-content:space-between; gap:.5rem;
    padding:.4rem .6rem; cursor:grab; border-bottom:1px solid var(--line); }
.tk-bucket-head:active { cursor:grabbing; }
.tk-bucket-title { font-weight:600; font-size:.85rem; }
.tk-band-del { border:none; background:none; color:var(--muted); cursor:pointer; font-size:.8rem;
    line-height:1; padding:.1rem .3rem; border-radius:4px; }
.tk-band-del:hover { color:var(--danger); background:rgba(155,59,28,.12); }
.tk-bucket-list { min-height:2.4rem; padding:.5rem .6rem; }
.tk-drop-hint { color:var(--muted); font-size:.82rem; font-style:italic; cursor:default; }
.tk-drop-hint[hidden] { display:none; }
.tk-add-band { margin-top:.6rem; }

/* Pula tagów — jak paleta w events: wiersze, bez bulletów, cała lista bez scrolla.
   Renderowana w osobnej karcie (data-pool-target) albo w .tk-pool (fallback create). */
.tk-pool { border:1px solid var(--line); border-radius:8px; padding:.6rem; }
.tk-filter { margin-bottom:.6rem; }
.tk-groups { display:flex; flex-direction:column; gap:.4rem; }
.tk-group[hidden] { display:none; }
.tk-group > summary { list-style:none; cursor:pointer; display:flex; align-items:center; gap:.5rem;
    padding:.35rem .4rem .35rem 0; font-size:.85rem; }
.tk-group > summary::-webkit-details-marker { display:none; }
.tk-cat { font-weight:600; text-transform:capitalize; }
.tk-cat-count { font-size:.76rem; }
.tk-group--empty { opacity:.5; }
.tk-pool-list { flex-direction:row; flex-wrap:wrap; gap:.4rem; padding:.2rem .2rem .6rem 0; }

/* ── Edit dwóch kolumn (formularz/karta + paleta tagów z prawej) ──────────── */
/* Wspólne dla Events i Perspectives → paleta ma w obu identyczną szerokość. */
.edit-cols { display:grid; grid-template-columns:760px 1fr; gap:1.5rem; align-items:start; }
.edit-cols-main { min-width:0; }                    /* nie rozpychaj siatki */
@media (max-width:1100px) { .edit-cols { grid-template-columns:1fr; } }

/* Perspectives: NIE poszerzamy strony (zostaje 1100) — zwężamy kartę LEVELS, a paleta
   dostaje stałą szerokość ~338px = tyle ile paleta w events (760/1fr na 1160). */
/* Odstęp pionowy siatki ZEROWY, bo między wierszami i tak stoi margines karty (1rem) —
   z własnym `row-gap` odstęp pod kartą YOUR LANGUAGE robił się 40px, dwa i pół raza
   większy niż wszędzie. Pozioma przerwa (kolumna ↔ paleta) zostaje 1.5rem. */
.levels-cols { display:grid; grid-template-columns:minmax(0,1fr) 338px; gap:0 1.5rem; align-items:start; }
.levels-cols-main { min-width:0; }
/* Formularz kanoniczny (CANONICAL + YOUR LANGUAGE) idzie przez obie kolumny; pod nim
   dopiero zaczyna się podział, więc paleta stoi już przy karcie MEDIA, a nie dopiero przy
   LEVELS. MEDIA i LEVELS są jednym elementem siatki (`.levels-cols-main`) właśnie po to,
   by wysoka paleta nie rozpychała wiersza MEDIA — kolumny mają rosnąć niezależnie. */
.canon-span { grid-column:1 / -1; }
@media (max-width:900px) { .levels-cols { grid-template-columns:1fr; } }

.tag-rail { border:1px solid var(--line); border-radius:8px; padding:.8rem; }
.tag-rail .etags-filter { margin:.5rem 0 .7rem; }
.etags-groups { display:flex; flex-direction:column; gap:.4rem; }
.etags-group[hidden] { display:none; }
.etags-group > summary { list-style:none; cursor:pointer; display:flex; align-items:center; gap:.5rem;
    padding:.35rem .4rem .35rem 0; font-size:.85rem; }
.etags-group > summary::-webkit-details-marker { display:none; }
.etags-cat { font-weight:600; text-transform:capitalize; }
.etags-cat-count { font-size:.76rem; }
/* Radio „dominująca kategoria" w nagłówku grupy (tylko kolorowe kategorie). */
.dom-cat-radio { display:inline-flex; align-items:center; }
.dom-cat-radio input[type=radio] { margin:0; cursor:pointer; accent-color:var(--dom, var(--accent)); }
/* Pole tylko-do-odczytu (podgląd wyliczonej/ustawianej gdzie indziej wartości). */
.readonly-field { display:block; padding:.4rem .55rem; border:1px dashed var(--line); border-radius:4px;
    color:var(--muted); background:var(--bg); font-size:.85rem; }
.etags-cloud { display:flex; flex-wrap:wrap; gap:.4rem; padding:.2rem .2rem .6rem 0; }

/* Tag w palecie = przełącznik (klik koloruje) */
.etag { border:1px solid var(--line); background:var(--card, #fff); color:var(--ink);
    border-radius:3px; padding:.18rem .55rem; font-size:.85rem; cursor:pointer; line-height:1.3; }
.etag[hidden] { display:none; }
.etag:hover { border-color:#cdbfae; }
.etag.is-on { background:rgba(181,97,58,.16); border-color:var(--accent); color:var(--ink); font-weight:600; }

/* ── Publikacja: konsola wyjścia ─────────────────────────────────────────── */
/* overflow:auto ŚWIADOMIE (nie zawijanie): przy błędzie długie linie gita i walidacji
   czyta się lepiej w całości, z suwakiem, niż połamane na kilka wierszy. */
.console { background:#1e1c1a; color:#e6e3dc; padding:1rem; border-radius:8px;
    overflow:auto; font-size:.82rem; line-height:1.4; }
/* Log zwinięty: po sukcesie nikt go nie czyta, po błędzie widok otwiera go sam (`open`). */
.log-details { margin-top:.6rem; }
.log-details > summary { cursor:pointer; user-select:none; color:var(--muted);
    font-size:.88rem; padding:.2rem 0; }
.log-details > summary:hover { color:var(--accent); }
.log-details > .console { margin-top:.4rem; }

/* ── Statystyka odwiedzających (strona Stats) ────────────────────────────── */
/* Liczby w kolumnach prawo-do-lewa: rzędy wielkości mają się zgadzać pionowo,
   inaczej porównanie „ile razy więcej" wymaga czytania cyfra po cyfrze. */
table.grid .num { text-align:right; font-variant-numeric:tabular-nums; }
/* Trzy tabele strony mają po sześć kolumn i stoją jedna pod drugą. table-layout:fixed
   rozkłada je RÓWNO na całą szerokość — przy auto-layoucie liczby zbijały się w lewo,
   a cała wolna przestrzeń szła do ostatniej kolumny. Przy okazji kolumny zgadzają się
   pionowo między tabelami, więc oko przeskakuje między nimi bez przestawiania. */
table.grid--stats { table-layout:fixed; min-width:44rem; }
/* Wąski ekran: tabela przewija się WE WŁASNYM pudle, zamiast rozpychać całą stronę.
   Bez tego `fixed` ściskał sześć kolumn do ~56 px i PRZYCINAŁ nagłówki (przy tym
   layoucie nadmiar się nie zawija, tylko znika) — a dokument dostawał poziomy suwak. */
.stats-scroll { overflow-x:auto; }

/* Udział: pasek POD liczbą (nie obok) — kolumna zostaje wąska, a oko i tak
   najpierw łapie proporcję. Szerokość paska podaje widok inline w procentach. */
/* Grid, nie flex: tor wypełnia kolumnę (1fr), a że table-layout:fixed daje tej kolumnie
   identyczną szerokość w KAŻDYM wierszu, procent liczy się od tej samej podstawy i wiersze
   zostają porównywalne. Na flexie skalowałby się od resztki miejsca po liczbie. */
.stats-share { display:grid; grid-template-columns:minmax(0,1fr) max-content;
    align-items:center; gap:.5rem; }
.stats-share__bar { height:.55rem; min-width:2px; border-radius:3px;
    background:var(--accent); opacity:.55; }
.stats-share__val { font-size:.85rem; color:var(--muted); font-variant-numeric:tabular-nums; }
/* Aktywne okno czasowe w pasku — ten sam język wizualny co przełączniki tagów. */
/* Przycisk „Translate" w Edit niosący dług przekładu — ta sama hierarchia i ten sam
   KSZTAŁT co koła ikon na listach: brak = wypełnienie, nieaktualny = samo obramowanie
   (odcienie palety są zbyt bliskie, żeby niosły to same z siebie). */
.btn-ghost--missing { color:#fff; border-color:var(--danger);
    background:var(--danger); font-weight:600; }
.btn-ghost--missing:hover { background:#7d2f16; border-color:#7d2f16; }
/* Tło DOKŁADNIE to samo co koło `.link-stale` na liście — `.btn-ghost` niesie własne
   białe `--panel`, więc bez nadpisania wariant zostawał bez wypełnienia. */
.btn-ghost--stale { color:var(--warn); border-color:var(--warn); font-weight:600;
    background:rgba(154,107,28,.10); }
.btn-ghost--stale:hover { border-color:var(--warn); background:rgba(154,107,28,.2); }
.btn-ghost.is-on { background:rgba(181,97,58,.16); border-color:var(--accent);
    color:var(--ink); font-weight:600; }

/* ── Świeżość tłumaczeń (rewizja źródła) ─────────────────────────────────────── */
/* NIEAKTUALNE (amber): przekład powstał przy starszej rewizji EN niż bieżąca. Stan
   wynika z porównania liczb, nie z ręcznej flagi — nie ma czego „odklikiwać". */
.tr-row--stale { background:rgba(154,107,28,.13); }
/* Wiersz Translate „przed źródłem" — odpowiednik `card--ahead` w Edit. Sam glif ⇡ przy
   kodzie języka ginął w wierszu (autor zgłosił, że w Edit ramka jest, a tu nie), więc
   sygnał dostaje ten sam KSZTAŁT co w Edit: obwódkę w terakocie `--accent`.
   `box-shadow`, nie `border`: wiersz jest komórką gridu o ustalonych torach, więc
   ramka rysowana obramowaniem przesunęłaby jego zawartość o piksel. Stan „nieaktualny"
   niesie TŁO, więc oba sygnały mogą świecić naraz bez zamazywania się. */
.tr-row--ahead { box-shadow:inset 0 0 0 1px var(--accent); }
.tr-dot.is-stale, .tr-state.is-stale { color:var(--warn); border-color:var(--warn); opacity:1; }
/* Nieaktualny przekład — obramowane koło (stopień słabszy od wypełnionego `.link-missing`
   wyżej: tekst wciąż działa, tylko odstał od źródła). Kształt, nie sam odcień. */
.link-stale { color:var(--warn); font-weight:600; }
a.link-stale { border:1.5px solid var(--warn); background:rgba(154,107,28,.10); }
a.link-stale:hover { background:rgba(154,107,28,.2); }
.link-warn { color:var(--warn); }
/* Karta YOUR LANGUAGE w Edit — ten sam amber i ten sam KSZTAŁT sygnału (lewy pasek)
   co wiersz `is-pending` na liście. Wcześniej Edit umiał pokazać tylko kierunek
   „język wyprzedził EN"; przeciwny — a to on jest robotą tłumacza — był niewidzialny. */
.card--stale { border-color:var(--warn); box-shadow:inset 3px 0 0 var(--warn); }
.stale-note { color:var(--warn); font-weight:600; font-size:.78rem; margin-left:.5rem;
    letter-spacing:0; text-transform:none; }
/* Akcje przy sygnale („what changed" / „still current"). Sygnał, który mówi tylko
   „coś jest nie tak", zostawia redaktora bez ruchu — te dwa linki są całą jego decyzją:
   przeczytaj diff albo potwierdź, że przekład nadal gra. Wygląd ŚWIADOMIE cichy: to
   akcje przy ostrzeżeniu, nie przyciski akcji głównej. */
.sig-act { font-size:.78rem; margin-left:.5rem; color:var(--muted); background:none;
    border:0; border-bottom:1px dotted currentColor; padding:0; cursor:pointer;
    font-family:inherit; letter-spacing:0; text-transform:none; white-space:nowrap; }
.sig-act:hover { color:var(--ink); text-decoration:none; }
.sig-act[disabled] { opacity:.5; cursor:default; }
/* Po potwierdzeniu — zieleń stanu „zgodne", ta sama co ✓ na Translate. */
.is-affirmed { color:var(--ok); font-weight:600; font-size:.78rem; margin-left:.5rem;
    letter-spacing:0; text-transform:none; opacity:1; }
.tr-dot.is-affirmed, .tr-state.is-affirmed { border-color:var(--ok); }
.affirm-error { font-size:.78rem; color:var(--danger); margin-left:.5rem; }
/* PRZED ŹRÓDŁEM: tekst zapisany w innym języku, a EN został z tyłu. To zadanie AUTORA
   (dopisz angielski), nie tłumacza — dlatego osobny, wąski znacznik, nie amber wiersza.
   Świadomie bez terakoty w tekście: sygnał miękki (boolean z heurystyki zapisu), a robota
   jest po stronie autora, nie tego, kto właśnie siedzi w formularzu. Jedyna akcja obok
   („was cosmetic") niesie się na wspólnym `.sig-act` — to samo ciche wzornictwo. */
.card--ahead { border-color:var(--accent); }
.ahead-note, .tr-ahead { color:var(--accent); font-weight:600; }
.ahead-note { font-size:.78rem; margin-left:.5rem; letter-spacing:0; text-transform:none; }
.ahead-tag { color:var(--accent); margin-right:.25rem; font-weight:700; }
/* Przełącznik „cosmetic edit" przy karcie CANONICAL — decyzja o unieważnieniu przekładów
   zapada tam, gdzie zmienia się źródło. */
.cosmetic-toggle { display:flex; align-items:center; gap:.4rem; font-size:.8rem;
    color:var(--muted); white-space:nowrap; cursor:pointer; }
.cosmetic-toggle input { margin:0; }
/* Ten sam przełącznik w WIERSZU Translate (kolumna Save ma 6.8rem, więc etykieta skraca
   się do „cosmetic", a całą treść niesie tooltip). Tam znaczy: zapisz tekst, ale zostaw
   stan przekładu — nieaktualny zostaje nieaktualny, maszynowy maszynowym. */
.cosmetic-toggle--row { font-size:.72rem; gap:.25rem; margin-top:.3rem; }
/* Podgląd EN na stronie Translate — źródło do czytania, nie do edycji. */
.tr-en-fields--ro input, .tr-en-fields--ro textarea { background:#f7f5f0; color:var(--muted); }
/* Kod języka w tytule listy filtrowanej kolejką pracy („PL Events to do"). Sam tytuł
   niesie informację o filtrze — nie ma przycisku gaszenia, bo wychodzi się z kolejki
   przełącznikiem widoku albo pozycją menu. */
.page-title .title-todo { color:var(--warn); }
/* ── Pasek przełączania kolejki tłumaczeń (partials/todo-bar) ─────────────────
   Widoczny tylko w kolejce. Amber jak tytuł `title-todo` wyżej — to jedna sprawa
   widziana z dwóch stron, więc nie dostaje własnej barwy. Pozycja z zerem zostaje
   na miejscu (wyszarzona), żeby pasek nie zmieniał kształtu w trakcie pracy. */
.todo-bar { display:flex; flex-wrap:wrap; align-items:center; gap:.4rem;
    margin:0 0 1rem; padding:.45rem .7rem; border:1px solid var(--line);
    border-left:3px solid var(--warn); border-radius:6px; background:rgba(154,107,28,.05);
    font-size:.85rem; }
.todo-bar__lang { color:var(--warn); font-weight:700; letter-spacing:.04em; margin-right:.3rem; }
.todo-bar__item { padding:.15rem .5rem; border-radius:4px; color:var(--ink); }
.todo-bar__item b { font-weight:700; }
a.todo-bar__item:hover { background:rgba(154,107,28,.14); text-decoration:none; }
.todo-bar__item.is-here { background:var(--warn); color:#fff; }
.todo-bar__item.is-clear { color:var(--muted); opacity:.55; }
.todo-bar__exit { margin-left:auto; color:var(--muted); font-size:.8rem; }
.todo-bar__exit:hover { color:var(--ink); }
/* Podświetlenie wiersza na czterech listach = TEKST NIESKOŃCZONY, czyli robota AUTORA.
   Amber: tekst zapisany przed angielskim (`ahead_of_source`) — zostaje dopisać kanon.
   Fiolet niżej: draft. Dług PRZEKŁADU (brak / nieaktualny) świadomie nie koloruje linii
   — to robota tłumacza i niosą ją kolory ikony Translate, inaczej lista świeciłaby
   niemal cała (suma po wszystkich językach docelowych) i przestałaby cokolwiek mówić. */
table.grid tr.is-pending > td { background:rgba(154,107,28,.09); }
table.grid tr.is-pending > td:first-child { box-shadow:inset 3px 0 0 var(--warn); }

/* ── Draft (event nieopublikowany): własny, fioletowy akcent — ODRÓŻNIALNY od amber
   świeżości wyżej. Lista: fioletowe tło wiersza; formularz: baner + przycisk. ── */
.flash.draft { background:#eeecf8; border:1px solid #cbc4e6; color:#443a7a; }
.btn-draft { background:var(--draft); color:#fff; border-color:var(--draft); }
.btn-draft:hover { background:#4b3f85; border-color:#4b3f85; }
/* Wiersz draftu na liście — ten sam fiolet co baner (draft wygrywa z `is-pending`). */
table.grid tr.is-draft > td { background:rgba(90,75,156,.12); }
table.grid tr.is-draft > td:first-child { box-shadow:inset 3px 0 0 var(--draft); }
/* Plakietka „draft" przy slugu (drobny znacznik obok tła wiersza). */
.draft-tag { display:inline-block; margin-right:.4rem; padding:0 .35rem; border-radius:4px;
    font-size:.7rem; font-weight:600; text-transform:uppercase; letter-spacing:.03em;
    background:var(--draft); color:#fff; vertical-align:middle; }

/* ── Summary: toolbar markerów + chowany podgląd (write plane) ───────────────
   Render przez renderSummary z summary-format.js (synced z read plane) — ten
   sam kanon formatu co oś. Podgląd STRUKTURALNY w jasnym motywie panelu (nie
   odwzorowuje ciemnych kolorów osi — pokazuje układ: akapity/podtytuły/listy/
   cytaty/link/pogrubienie/kursywę). --script type=module w blade. */
.summary-tools { margin:.5rem 0 0; }
/* Pasek nie niesie dolnego marginesu wcale: wszędzie stoi jako ostatni pod polem prozy,
   a odstęp w dół daje już padding karty albo margines następnej sekcji (na karcie
   CANONICAL własny margines dublował padding i Preview odjeżdżał od dna).
   Pod wierszem tabeli zostaje SAM podgląd (przycisk mieszka w kolumnie Save), więc
   zamknięty nie może zajmować ani piksela — marginesy wędrują na rozwinięty box. */
.tr-row + .summary-tools { margin:0; padding:0 1.4rem; }
.tr-row + .summary-tools .summary-preview:not([hidden]) { margin:.2rem 0 1rem; }
.summary-bar { display:flex; align-items:center; gap:.25rem; flex-wrap:wrap; }
/* Przyciski paska mają STAŁĄ szerokość, nie minimalną: glify emoji (link, hasło, obraz)
   są szersze od literowych i rozpychały rząd, przez co jeden przycisk odstawał od reszty.
   Padding poziomy schodzi do zera — szerokość trzyma teraz `width`. */
.summary-btn { padding:.2rem 0; width:1.9rem; min-width:1.9rem; border:1px solid var(--line);
    border-radius:6px; background:var(--panel); color:var(--ink); font:inherit;
    font-size:.85rem; line-height:1.3; cursor:pointer; }
/* Cytat jest ikoną WYPEŁNIONĄ, więc przy tej samej miarze co ikony obrysowe ma dużo
   więcej „atramentu" i wybija się z rzędu. Stąd o oczko mniejszy i w kolorze podpowiedzi;
   hover wraca do koloru przycisku, żeby zachowywał się jak każdy inny. */
.summary-ico-quote { width:1em; height:1em; color:var(--muted); }
.summary-btn:hover .summary-ico-quote { color:inherit; }
/* NIE ustawiać tu `height` ani `display:flex`. Stała wysokość naciąga rząd, a flex robi
   z `x<sup>2</sup>` DWA elementy potomne — indeks traci przesunięcie względem linii pisma
   i oba przyciski (górny/dolny) wyglądają identycznie: „x2". Sprawdzone 2026-08-19.
   Glif za drobny w rozmiarze paska rozwiązuje się IKONĄ ze sprite'a, nie skalowaniem. */
.summary-btn:hover { border-color:var(--accent); color:var(--accent); }
.summary-btn b { font-weight:700; } .summary-btn i { font-style:italic; }
.summary-spacer { flex:1; }
/* Preview jest przyciskiem-słowem, nie ikoną jak reszta paska — szerszy oddech poziomy. */
.summary-toggle { width:auto; padding-left:.7rem; padding-right:.7rem; }
.summary-toggle.is-on { background:var(--accent); border-color:var(--accent); color:#fff; }
.summary-toggle.is-on:hover { color:#fff; }
/* Fonty jak w detalu osi (#event-detail-content): Fira Sans / Fira Sans Condensed
   — ładowane w layoucie (Google Fonts). Motyw jasny panelu zostaje. */
/* :not([hidden]) — inaczej display:flow-root nadpisuje wbudowane [hidden]{display:none}
   (wyższa specyficzność) i zamknięty box wychodzi jako pusty biały pasek. */
.summary-preview:not([hidden]) { display:flow-root; }  /* domyka pływające figury (position) w ramce */
.summary-preview { margin-top:.5rem; padding:.7rem 1rem; border:1px solid var(--line);
    border-radius:8px; background:var(--panel);
    font-family:'Fira Sans', ui-sans-serif, system-ui, sans-serif; }
.summary-preview > :first-child { margin-top:0; }
.summary-preview .node-summary { margin:.55rem 0; font-size:1rem; line-height:1.6; }
.summary-preview .node-subtitle { margin:1rem 0 .3rem;
    font-family:'Fira Sans Condensed', 'Fira Sans', ui-sans-serif, sans-serif;
    font-size:1.25rem; font-weight:600; letter-spacing:-.01em; color:var(--ink); }
.summary-preview .node-md-list { margin:.4rem 0 .4rem 1.4rem; padding:0; list-style:disc; }
.summary-preview .node-md-list li { margin:.15rem 0; }
.summary-preview .node-quote { margin:.6rem 0; padding:.15rem 0 .15rem .8rem;
    border-left:3px solid var(--line); color:var(--muted); font-style:italic; }
.summary-preview .node-link { color:var(--accent); text-decoration:underline; }
/* Indeks górny/dolny (^{…}/_{…}) — wymiar jak wykładniki osi (.node-sci-exp), nie mały
   domyślny <sup>; line-height:0 nie rozpycha wiersza. Kolor dziedziczony (część treści). */
.summary-preview sup, .summary-preview sub { font-size:.8em; line-height:0; }
.summary-preview sup { vertical-align:.42em; }
.summary-preview sub { vertical-align:-.25em; }

/* ── Dziennik zmian (/history) ──────────────────────────────────────────────
   Rozwijalne wpisy audytu (<details>) z diffem before/after. Filtry na górze. */
.hist-filter { display:flex; flex-wrap:wrap; gap:.8rem 1rem; align-items:flex-end; }
.hist-filter label { display:flex; flex-direction:column; gap:.25rem; font-size:.8rem; color:var(--muted); }
.hist-filter select, .hist-filter input { padding:.35rem .5rem; border:1px solid var(--line);
   border-radius:6px; background:var(--panel); font-size:.9rem; color:var(--ink); }
.hist-filter__actions { display:flex; gap:.5rem; margin-left:auto; }

.hist-row { border-bottom:1px solid var(--line); }
.hist-row:last-child { border-bottom:0; }
.hist-sum { display:flex; align-items:center; gap:.6rem; padding:.55rem 1.4rem; cursor:pointer;
   list-style:none; user-select:none; }
.hist-sum::-webkit-details-marker { display:none; }
.hist-sum::before { content:'▸'; color:var(--muted); font-size:.8rem; transition:transform .12s; }
.hist-row[open] > .hist-sum::before { transform:rotate(90deg); }
.hist-row[open] > .hist-sum { background:#faf8f4; }
.hist-sum:hover { background:#faf8f4; }
.hist-sum__action { font-weight:600; font-size:.85rem; }
.hist-sum__subject { overflow:hidden; text-overflow:ellipsis; max-width:22rem; }
.hist-sum__spacer { flex:1 1 auto; }
.hist-sum__date { font-variant-numeric:tabular-nums; }

.chip--domain { display:inline-block; padding:.05rem .45rem; border-radius:999px; font-size:.72rem;
   background:#efece5; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; }

.hist-diff { width:100%; margin:0 0 .4rem; }
.hist-diff td, .hist-diff th { vertical-align:top; word-break:break-word; }
.hist-diff__key { color:var(--muted); white-space:nowrap; }
.hist-diff__before span:not(.muted) { background:rgba(155,59,28,.10); text-decoration:line-through;
   text-decoration-color:rgba(155,59,28,.4); border-radius:3px; padding:0 .2rem; }
.hist-diff__after span:not(.muted) { background:rgba(47,107,58,.12); border-radius:3px; padding:0 .2rem; }
.hist-diff__row.is-added .hist-diff__before { opacity:.5; }
.hist-diff__row.is-removed .hist-diff__after { opacity:.5; }
.hist-diff__empty { padding:.4rem 1.4rem 1rem; }

/* Inline word-diff (summary): jeden splot tekstu z zaznaczeniem zmian. pre-wrap
   zachowuje akapity/łamania; ins/del bez domyślnej dekoracji przeglądarki. */
.hist-diff__inline { white-space:pre-wrap; word-break:break-word; line-height:1.55; }
.hist-diff__inline ins { background:rgba(47,107,58,.16); text-decoration:none; border-radius:3px; padding:0 .1rem; }
.hist-diff__inline del { background:rgba(155,59,28,.13); text-decoration:line-through;
    text-decoration-color:rgba(155,59,28,.55); border-radius:3px; padding:0 .1rem; }

.hist-pager { display:flex; align-items:center; justify-content:center; gap:1rem; margin:1rem 0; }
.hist-pager .is-disabled { opacity:.4; pointer-events:none; }

/* Hasło glosariusza w podglądzie summary (marker `[etykieta](=slug)`). Na stronie termin jest
   tylko OZNACZONY, a wyjaśnienie stoi w przypisie na końcu detalu — więc i tu samo kropkowane
   podkreślenie, bez kursora i bez hovera (bliźniak reguły .node-term w timeline.css osi).
   Slug NIEZNANY renderer wygasza do zwykłej prozy, więc brak podkreślenia w podglądzie
   = literówka w slugu i redaktor widzi ją od razu.
   UWAGA: podgląd pokazuje SAMĄ PROZĘ — przypisów nie składa, bo dokłada je renderer detalu
   (renderTermNotes), a nie renderSummary. Treść haseł sprawdza się na /terms. */
.summary-preview .node-term { border-bottom:1px dotted currentColor; }
/* Picker haseł dziedziczy wygląd po pickerze mediów; różni się tym, że kafelek niesie
   samą nazwę hasła (slug siedzi w tooltipie) — nazwa jest tym, czym redaktor je pamięta. */
.summary-termpick .summary-mediapick__ph { width:22px; height:22px; font-size:.9rem; }
/* „+ nowe hasło" pod listą: zamówienie bez opuszczania tekstu. Pole slugu jest WIDOCZNE
   celowo (przeglądarka liczy go inaczej niż Str::slug — patrz summary-preview.js), więc
   dostaje własną, węższą kolumnę zamiast chować się za nazwą. */
.summary-termnew { display:flex; flex-wrap:wrap; align-items:center; gap:.35rem; width:100%;
             margin-top:.15rem; padding-top:.45rem; border-top:1px solid var(--line); }
.summary-termnew input { padding:.25rem .45rem; font-size:.85rem; }
.summary-termnew__name { flex:1 1 9rem; min-width:7rem; }
.summary-termnew__slug { flex:0 1 8rem; min-width:6rem; color:var(--accent); }
.summary-termnew__slug[aria-invalid="true"] { border-color:var(--danger); }
.summary-termnew__go { padding:.2rem .6rem; font-size:.85rem; }
