/* ── Design tokens ────────────────────────────────────────────────────────── */
:root {
    --color-background-primary: #ffffff;
    --color-background-secondary: #f5f5f5;
    --color-background-tertiary: #ebebeb;
    --color-background-info: #e6f1fb;
    --color-background-success: #eaf3de;
    --color-background-warning: #faeeda;
    --color-background-danger: #fcebeb;

    --color-text-primary: #1a1a1a;
    --color-text-secondary: #5a5a5a;
    --color-text-tertiary: #858585;
    /* Akcent — używany przez slidery, pierścienie postępu, linki, itp.
       Złoto marki (taki sam odcień co pasek warstw na karcie medytacji). */
    --color-text-info: #C5A56C;
    --color-text-success: #3b6d11;
    --color-text-warning: #854f0b;
    --color-text-danger: #a32d2d;

    --color-border-tertiary: rgba(0,0,0,0.08);
    --color-border-secondary: rgba(0,0,0,0.16);
    --color-border-primary: rgba(0,0,0,0.24);
    --color-border-info: #b5d4f4;
    --color-border-warning: #fac775;

    /* Primary button — granatowy odcień marki (zamiast czarnego text-primary,
       który dotychczas pełnił rolę background-u "main CTA"). Tekst zawsze
       biały, kontrast WCAG AA spełniony w obu motywach. */
    --color-button-primary: #012e48;
    --color-button-primary-fg: #ffffff;

    --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* Ciemny motyw — opt-in przez atrybut na <html>. Brak atrybutu = jasny (domyślny).
   Wybór usera siedzi w localStorage (klucz medytao.theme) i jest aplikowany
   przez inline script w index.html jeszcze przed załadowaniem tego pliku. */
:root[data-theme="dark"] {
    --color-background-primary: #1e1e1e;
    --color-background-secondary: #2a2a2a;
    --color-background-tertiary: #171717;
    --color-background-info: #042c53;
    --color-background-success: #173404;
    --color-background-warning: #412402;
    --color-background-danger: #501313;

    --color-text-primary: #e8e8e8;
    --color-text-secondary: #b0b0b0;
    --color-text-tertiary: #858585;
    /* Akcent w dark — złoto rozjaśnione o ton, żeby lepiej wybijało się
       na ciemnym tle (ten sam hue co w light, wyższa luminancja). */
    --color-text-info: #D4B884;
    --color-text-success: #c0dd97;
    --color-text-warning: #fac775;
    --color-text-danger: #f7c1c1;

    --color-border-tertiary: rgba(255,255,255,0.08);
    --color-border-secondary: rgba(255,255,255,0.16);
    --color-border-primary: rgba(255,255,255,0.24);

    /* W dark mode rozjaśniamy granat o ton — #012e48 na ciemnym tle gubi się
       wizualnie z #1e1e1e background, jaśniejsza wersja zachowuje czytelność
       i dalej jest jednoznacznie "granatowy CTA" (ten sam hue). */
    --color-button-primary: #1f5a7e;
    --color-button-primary-fg: #ffffff;
}

* { box-sizing: border-box; }

html, body {
    margin: 0; padding: 0;
    font-family: var(--font-sans);
    font-size: 14px;
    line-height: 1.5;
    color: var(--color-text-primary);
    background: var(--color-background-tertiary);
    -webkit-font-smoothing: antialiased;
}

a { color: var(--color-text-info); text-decoration: none; }
a:hover { text-decoration: underline; }

button { font-family: inherit; }

input, textarea { font-family: inherit; outline: none; }
input:focus, textarea:focus { border-color: var(--color-border-primary); }

/* Focus ring tylko dla nawigacji klawiaturowej (Tab). Przeglądarka
   domyślnie maluje outline po każdym focusie — w tym po kliku myszą,
   programowym .focus() i (czasem) po reload strony, gdy auto-focus
   lub restore-focus podnosi pierwszy interactable. To denerwowało
   przy ładowaniu aplikacji. :focus-visible to standardowy mechanizm
   różnicujący "focus z keyboard-a" od "focus z myszy" — używamy go
   żeby a11y dla klawiatury została, a clickerzy nie widzieli outline-u.
   Nie rusza input/textarea — te już wcześniej miały reset i własną
   stylizację przez border-color. */
:focus:not(:focus-visible) { outline: none; }

/* Headingi (h1-h6) — Blazor <FocusOnNavigate Selector="h1"/> w App.razor
   programmatycznie focusuje pierwszy h1 po każdej nawigacji (skip-link
   pattern dla screen readerów). Niektóre przeglądarki klasyfikują
   programmatic focus jako "keyboard-like" i :focus-visible aktywuje
   się — efekt: czarna ramka wokół "My programs", "Sign in" itd. po
   wejściu na stronę. Headingi nie są naturalnie w tab-orderze, więc
   keyboard user ich i tak nie odwiedzi Tab-em; outline na nich nie
   pomaga, tylko irytuje. Wymuszamy brak outline-u również dla
   focus-visible. Screen reader dalej dostaje focus (programmatic
   focus działa niezależnie od stylów wizualnych). */
h1:focus, h2:focus, h3:focus, h4:focus, h5:focus, h6:focus,
h1:focus-visible, h2:focus-visible, h3:focus-visible,
h4:focus-visible, h5:focus-visible, h6:focus-visible {
    outline: none;
}

/* Hero background pod kartami — opcjonalny toggle z /settings. Sterowany
   przez HeroBackgroundService (atrybut data-hero-bg na <html>). Domyślnie
   wyłączone, .main-content ma standardowe szare tło.
   background-attachment: fixed sprawia że hero "stoi w miejscu" podczas
   scrollowania, treść jeździ po nim — bardziej eleganckie niż scroll razem
   z contentem.
   Edytor medytacji jawnie nadpisuje swoje tło na editor-shell, więc nawet
   z włączonym hero pozostaje neutralny (workflow > ozdoba). */
html[data-hero-bg="on"] .main-content {
    background: var(--color-background-tertiary) url('/img/hero-zen.jpg') center/cover no-repeat fixed;
}

/* W dark mode hero przygaszone — bez tego jasne zdjęcie wyglądało
   nienaturalnie obok ciemnych kart i topbar-a. Linear-gradient z dwoma
   identycznymi czarnymi stopami (~55% opacity) działa jak overlay nad
   hero — first w shorthand = top layer, hero pod nim. background-color
   pozostaje fallback-iem na wypadek braku obrazka. Tweak intensywności
   przez procent w rgba. */
html[data-hero-bg="on"][data-theme="dark"] .main-content {
    background:
        linear-gradient(rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.55)) fixed,
        var(--color-background-tertiary) url('/img/hero-zen.jpg') center/cover no-repeat fixed;
}

/* Active nav link styling for Blazor NavLink. Sidebar ma stałe ciemne tło
   (#012e48) niezależnie od motywu, więc aktywny element podświetlamy półprzezroczystą
   bielą — nie tokenami motywu. !important dlatego, że scoped CSS w MainLayout
   nie zawsze bije selektor Blazor NavLink. */
.nav-item.active {
    background: rgba(255,255,255,0.1) !important;
    color: #ffffff !important;
}

/* ── Volume slider — pasuje wizualnie do audio-preview-progress.
   Wypełnienie od lewej kontrolowane zmienną --slider-fill (np. "42%"). ── */
input[type=range].medytao-slider {
    -webkit-appearance: none;
    appearance: none;
    height: 6px;
    border: 1px solid var(--color-border-tertiary);
    border-radius: 3px;
    background: linear-gradient(
        to right,
        var(--color-text-info) 0%,
        var(--color-text-info) var(--slider-fill, 0%),
        var(--color-border-tertiary) var(--slider-fill, 0%),
        var(--color-border-tertiary) 100%);
    outline: none;
    cursor: pointer;
    padding: 0;
    margin: 0;
    vertical-align: middle;
}
input[type=range].medytao-slider::-webkit-slider-runnable-track {
    height: 6px; border-radius: 3px; background: transparent;
}
input[type=range].medytao-slider::-moz-range-track {
    height: 6px; border-radius: 3px; background: transparent; border: none;
}
input[type=range].medytao-slider::-moz-range-progress {
    height: 6px; border-radius: 3px; background: transparent;
}
input[type=range].medytao-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 14px; height: 14px;
    margin-top: -5px;
    border-radius: 50%;
    background: var(--color-text-info);
    border: 2px solid var(--color-background-primary);
    box-shadow: 0 0 0 1px var(--color-border-secondary);
    cursor: grab;
    transition: transform 0.1s;
}
input[type=range].medytao-slider::-moz-range-thumb {
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--color-text-info);
    border: 2px solid var(--color-background-primary);
    box-shadow: 0 0 0 1px var(--color-border-secondary);
    cursor: grab;
    transition: transform 0.1s;
}
input[type=range].medytao-slider:active::-webkit-slider-thumb { transform: scale(1.1); cursor: grabbing; }
input[type=range].medytao-slider:active::-moz-range-thumb { transform: scale(1.1); cursor: grabbing; }
input[type=range].medytao-slider:focus-visible { box-shadow: 0 0 0 2px var(--color-border-info); }

/* ── Ring spinner ─────────────────────────────────────────────────────────
   Klasyczny obracany pierścień: okrąg z border-em, jeden segment (top)
   przezroczysty, całość rotuje 360° w pętli. Kolor pierścienia = złoto
   marki (`--color-text-info`, #C5A56C w light, #D4B884 w dark — token
   adaptuje się do motywu, więc spinner pozostaje czytelny na ciemnym tle).

   Definiowane GLOBALNIE (nie scoped), bo używamy też w pre-Blazor splash
   w index.html (zanim scoped CSS isolation w ogóle zacznie działać) oraz
   w komponencie Components/Shared/Spinner.razor.

   Klasa nazywa się dalej `spinner-breathing` żeby wszystkie call-sites
   (i przekładany pre-Blazor splash) działały bez zmian — to tylko swap
   wnętrza animacji. Markup z dwoma <span>-ami z komponentu pozostaje
   kompatybilny (pierwszy <span> renderuje ring, drugi jest niewidoczny). */
.spinner-breathing {
    width: 48px; height: 48px;
    margin: 40px auto;
    display: block;
    position: relative;
}
.spinner-breathing.inline {
    width: 16px; height: 16px;
    margin: 0;
    display: inline-block;
    vertical-align: middle;
}
/* Pierwszy <span> = ring. border-top transparent tworzy "lukę" w okręgu,
   przez rotację wygląda jak biegnący koniec. border-width ~10% średnicy
   to klasyczna proporcja "ringa" — wyraźny ale nie ciężki. */
.spinner-breathing > span:first-child {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 5px solid var(--color-text-info, #C5A56C);
    border-top-color: transparent;
    box-sizing: border-box;
    animation: spinner-ring-rotate 0.9s linear infinite;
}
.spinner-breathing.inline > span:first-child {
    border-width: 2px;
}
/* Drugi <span> z komponentu jest zbędny dla ring-a (został po breathing
   wariancie) — chowamy żeby nie zaśmiecał DOM-u wizualnie. Zostaje
   w markup-ie, bo Spinner.razor go nadal renderuje. */
.spinner-breathing > span:nth-child(2) {
    display: none;
}
@keyframes spinner-ring-rotate {
    to { transform: rotate(360deg); }
}

/* Reduced motion — wyłączamy rotację, zostawiamy statyczny pierścień
   z pełną obwódką (bez "luki") jako neutralny wizualny marker "coś trwa".
   Nie idealne, ale lepsze niż agresywne 360°/s dla osób wrażliwych. */
@media (prefers-reduced-motion: reduce) {
    .spinner-breathing > span:first-child {
        animation: none;
        border-top-color: var(--color-text-info, #C5A56C);
        opacity: 0.4;
    }
}
