/* ==========================================================================
   4ELEMENTS — vault.css  (KLAMRA: WEJŚCIE + POWRÓT/CTA)
   "The Vault" — betonowy, bezbarwny przedsionek-negatyw żywiołów.
   Mapuje brief.md (§3–§8) na tokeny. Estetyka pochodzi z briefu, nie z palca.
   Warstwy: themes (pack-override) + components (klamra) + utilities.
   Akcent = WYŁĄCZNIE piksele fotografii żywiołu w szczelinie (W1) — zero tokenu barwy.
   ========================================================================== */

/* --------------------------------------------------------------------------
   THEMES — nadpisanie packa brutalist na bezbarwną paletę-parasol (§4).
   Brutalist daje surowość/twardość, ale jego --acid łamałby zasadę W1
   (klamra bezbarwna). Tu trzymamy L-only, saturacja 0.
   -------------------------------------------------------------------------- */
@layer themes {
  [data-pack="brutalist"].vault {
    /* Paleta-parasol: tylko oś jasności L, chroma 0 (§4) */
    --surface-void:  oklch(0.15 0 0);          /* głęboki chłodny grafit; NIE #000 */
    --surface-void-2: oklch(0.19 0 0);         /* ściana o stopień jaśniejsza */
    --text-primary:  oklch(0.90 0 0);          /* złamana surowa biel; NIE #fff */
    --text-muted:    oklch(0.55 0 0);          /* metadane, hairline'y */
    --text-faint:    oklch(0.38 0 0);          /* mikro-szept (wordmark) */

    --bg-primary: var(--surface-void);
    --hairline:   color-mix(in oklch, var(--text-primary), transparent 82%);

    /* Akcja/fokus bezbarwne — biel, nie kwas (zostaje surowość bez barwy) */
    --surface-action-primary: var(--text-primary);
    --text-on-action: var(--surface-void);
    --focus-ring: var(--text-primary);

    /* Kroje (§5): display ekstremalny grotesk; metadane serif; mikro-UI serif/mono */
    --font-display: "Big Shoulders Display", "Archivo", system-ui, sans-serif;
    --font-meta:    "Newsreader", Georgia, serif;

    --tracking-display: -0.02em;               /* Big Shoulders już wąski; lekki minus by zbić w blok */
    --leading-display:  0.82;                   /* < 1.0, ciaśniej — bloki odlewu (§5) */

    /* Skala display ucięta krawędzią (§5) — duża, by crop był agresywny */
    --size-element: clamp(6.5rem, 16.5vw, 16rem);
    --size-meta:    0.8rem;
    --size-whisper: clamp(0.62rem, 0.7vw, 0.78rem);

    /* Szczelina filmowa scope 2.39:1 (§7 sek.2) */
    --slit-ratio: 2.39;

    background-color: var(--surface-void);
    color: var(--text-primary);
  }
}

/* --------------------------------------------------------------------------
   COMPONENTS — architektura przedsionka i finału.
   -------------------------------------------------------------------------- */
@layer components {

  /* ---- Materiał: beton (§4 Materiał) — winieta radialna + ziarno filmowe ----
     Dwie warstwy: (a) gradient radialny daje głębię/fizyczność betonu i pogłębia
     ziejącą pustkę w centrum (memorable §8); (b) ziarno filmowe na wierzchu. */
  .vault {
    min-block-size: 100svh;
    overflow-x: clip;
    position: relative;
    isolation: isolate;
    background-color: var(--surface-void);
    background-image:
      radial-gradient(
        ellipse 62% 70% at 50% 50%,
        color-mix(in oklch, var(--surface-void), black 38%) 0%,
        var(--surface-void) 40%,
        var(--surface-void-2) 100%);
  }
  /* ziarno filmowe — osobna warstwa nad winietą */
  .vault::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: var(--z-noise);
    pointer-events: none;
    background-image: var(--texture-noise);
    background-size: 220px 220px;
    opacity: 0.9;
    mix-blend-mode: screen;
  }

  /* ---- Wordmark: mikro-szept w rogu (§2 edge-minimal, §5 W24) ---- */
  .wordmark {
    position: fixed;
    inset-block-start: var(--space-6);
    inset-inline-start: var(--space-8);
    z-index: var(--z-nav);
    font-family: var(--font-meta);
    font-size: var(--size-whisper);
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--text-faint);
    text-decoration: none;
    transition: color var(--duration-fast) var(--ease-standard);
  }
  .wordmark:hover, .wordmark:focus-visible { color: var(--text-muted); }

  /* ====================================================================
     WEJŚCIE — asymetryczny indeks (§2, §7 sek.1)
     Pusta scena, 4 monumentalne nazwy rozstrzelone na osi Y,
     ucięte krawędziami viewportu. W centrum ziejąca pustka (memorable §8).
     ==================================================================== */
  /* Ramą indeksu jest cały viewport. Nazwy żyją w jego CZTERECH narożnikach,
     centrum (~60%) zostaje całkowicie puste — architektoniczna pustka (§8). */
  .index {
    min-block-size: 100svh;
    block-size: 100svh;
    position: relative;
    z-index: var(--z-content);
  }

  /* Każda nazwa = blok dociśnięty do swojej krawędzi, ucięty viewportem.
     Litery wychodzą ZZA krawędzi (translate poza ekran), beton zjada resztę. */
  .element {
    position: absolute;
    display: block;
    text-decoration: none;
    color: var(--text-primary);
    line-height: var(--leading-display);
    /* font-size na elemencie = skala liter → wszystkie wymiary slit w `em`
       liczą się względem WIELKOŚCI NAZWY, nie root 16px (inaczej pas mikro). */
    font-size: var(--size-element);
    /* isolation: kontekst dla mix-blend-mode szczeliny i nazwy — difference
       blenduje TYLKO w obrębie elementu (lawa × litera), nie z całym voidem. */
    isolation: isolate;
  }
  .element__name { font-size: 1em; }
  .element__name {
    display: block;
    font-family: var(--font-display);
    font-weight: 900;
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    color: var(--text-muted);
    white-space: nowrap;
    transition: color var(--duration-fast) var(--ease-standard);
    will-change: color;
  }

  /* Asymetria narożnikowa — agresywny crop zza krawędzi (W5 słowo-jako-obiekt).
     FIRE: góra-lewo, wjeżdża z lewej (litera ucięta krawędzią inline-start).
     WATER: góra-prawo, wyjeżdża w prawo (ogon poza ekranem).
     AIR: dół-lewo, wjeżdża z lewej.
     EARTH: dół-prawo, wyjeżdża w prawo. */
  /* UWAGA: transform NIE na .element (tworzyłby containing block dla fixed .slit).
     Crop zza krawędzi realizuje translateX na samym .element__name. */
  .element--fire {
    inset-block-start: -0.18em;
    inset-inline-start: 0;
  }
  .element--fire  .element__name { transform: translateX(-0.40em); }
  .element--water {
    inset-block-start: 15svh;
    inset-inline-end: 0;
    text-align: end;
  }
  .element--water .element__name { transform: translateX(0.22em); }
  .element--air {
    inset-block-end: 15svh;
    inset-inline-start: 0;
  }
  .element--air   .element__name { transform: translateX(-0.36em); }
  .element--earth {
    inset-block-end: -0.16em;
    inset-inline-end: 0;
    text-align: end;
  }
  .element--earth .element__name { transform: translateX(0.20em); }

  /* Metadane serif przyklejone TWARDO do osi typografii (§5, W25, architekt. grid).
     Mikro-label siada na baseline nazwy, nie wisi w próżni — wspólna oś inline. */
  .element__meta {
    display: block;
    font-family: var(--font-meta);
    font-size: var(--size-meta);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-faint);
    margin-block-start: calc(var(--space-1) * -1);
    padding-inline-start: 0.14em;          /* na pionowej osi pierwszej litery */
    transition: color var(--duration-fast) var(--ease-standard);
  }
  /* górne nazwy: label POD nazwą; dolne nazwy: label NAD nazwą (klin do krawędzi) */
  .element--air .element__meta,
  .element--earth .element__meta {
    margin-block-start: 0;
    margin-block-end: calc(var(--space-1) * -1);
    order: -1;
  }
  .element--air,
  .element--earth { display: flex; flex-direction: column; }
  .element--water .element__meta,
  .element--earth .element__meta { padding-inline: 0 0.14em; }

  /* ---- Hover/focus: SZCZELINA jako FIZYCZNE CIĘCIE KADRU (§7 sek.2, P1) ----
     Szczelina to pęknięcie w betonie ZAKOTWICZONE w elemencie (nie fixed pod
     literami). Startuje jako WĄSKA, OSTRA szpara z której bije żar; otwierając
     się TNIE WSZYSTKO — litera w jej obrębie przechodzi w mix-blend-mode:
     difference (inwersja koloru tam, gdzie przecina światło żywiołu). To nie
     obrazek-pod-tekstem: tekst i światło wchodzą w matematyczną interakcję. */
  .slit {
    position: absolute;
    /* pas szerszy niż box nazwy — sięga w void po obu stronach (cięcie kadru),
       ale zakotwiczony w isolated elemencie → difference działa litera×lawa */
    inset-inline-start: -8vw;
    inline-size: 116vw;
    block-size: 0.10em;                 /* WĄSKA szpara na starcie (pęknięcie) */
    /* zakotwiczona na ŚRODKU wysokości liter — pewnie tnie trzon (nie nad nimi) */
    inset-block-start: 0.46em;
    transform: translateY(-50%);
    z-index: -1;                        /* tuż pod nazwą w tym samym kontekście */
    overflow: hidden;
    pointer-events: none;
    /* zamknięta: zwinięta do ostrej poziomej linii (szpara z której bije żar) */
    clip-path: polygon(0 46%, 100% 42%, 100% 58%, 0 54%);
    opacity: 0;
    transition:
      block-size var(--duration-base) var(--ease-out-expo),
      clip-path  var(--duration-base) var(--ease-out-expo),
      opacity    var(--duration-snappy) var(--ease-standard);
    will-change: block-size, clip-path, opacity;
  }
  /* poziom cięcia dostrojony do widocznej masy liter per żywioł (crop ucina box) */
  .element--fire  .slit { inset-block-start: 0.60em; }
  .element--water .slit { inset-block-start: 0.50em; inset-inline-start: auto; inset-inline-end: -8vw; }
  .element--air   .slit { inset-block-start: 0.42em; }
  .element--earth .slit { inset-block-start: 0.42em; inset-inline-start: auto; inset-inline-end: -8vw; }

  .slit > img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    transform: scale(1.04);
    /* desaturacja + przygaszenie w spoczynku → barwa/żar wraca na otwarciu */
    filter: grayscale(0.30) contrast(1.05) brightness(0.78);
    transition: transform 1600ms var(--ease-out-expo),
                filter var(--duration-base) var(--ease-standard);
    will-change: transform;
  }
  /* KONTRA cinematic grading szczeliny: winieta po bokach + dół (żar bije ze
     środka, brzegi wtapiają się w beton — nie czysty jpg wklejony 1:1) */
  .slit::after {
    content: "";
    position: absolute;
    inset: 0;
    background:
      linear-gradient(to right,
        var(--surface-void) 0%, transparent 22%,
        transparent 78%, var(--surface-void) 100%),
      radial-gradient(120% 160% at 50% 40%,
        transparent 30%, color-mix(in oklch, var(--surface-void), transparent 30%) 100%);
    pointer-events: none;
  }

  .element:hover  .slit,
  .element:focus-visible .slit {
    opacity: 1;
    block-size: 1.18em;                 /* rozwiera się: szpara → cięcie */
    /* otwiera asymetryczny skos — pęknięcie rozłupuje kadr (niezależnie od liter) */
    clip-path: polygon(0 14%, 100% 0, 100% 86%, 0 100%);
  }
  /* dolly-in: świat "żyje" za murem; żar wraca (barwa + jasność) — uwaga 7 */
  .element:hover  .slit > img,
  .element:focus-visible .slit > img {
    transform: scale(1.14);
    filter: grayscale(0) contrast(1.12) brightness(1.0) saturate(1.05);
  }
  /* P1 RDZEŃ: litera tnięta przez światło → mix-blend-mode: difference.
     Tam gdzie litera przecina żar lawy = inwersja (matematyczne przenikanie,
     full-spec §4.3, Prawo 4). Szary tekst nad lawą = błąd → tu znika. */
  .element:hover  .element__name,
  .element:focus-visible .element__name {
    color: oklch(0.98 0 0);
    mix-blend-mode: difference;
    text-shadow: none;
  }
  .element:hover  .element__meta,
  .element:focus-visible .element__meta { color: var(--text-primary); }

  /* ====================================================================
     PRZEJŚCIE — "Połknięcie" (§7 sek.3): klik na nazwę.
     Wybrana szczelina rozszerza się aż wypełni viewport, przedsionek
     odjeżdża w głąb (scale 0.95, opacity 0). clip-path + transform = GPU.
     ==================================================================== */
  .swallow {
    position: fixed;
    inset: 0;
    z-index: var(--z-toast);
    overflow: hidden;
    pointer-events: none;
    opacity: 0;
    /* startuje z TEGO SAMEGO skosu co szczelina hover (ciągłość gestu) */
    clip-path: polygon(0 46%, 100% 38%, 100% 54%, 0 62%);
    transition:
      clip-path var(--duration-cinematic) var(--ease-out-expo),
      opacity   var(--duration-snappy)    var(--ease-standard);
    will-change: clip-path, opacity;
  }
  .swallow > img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    transform: scale(1.08);
    /* KONTRA cinematic grading (Gemini #1): mroczna wizja, nie pocztówka 4K.
       - saturacja −36% (kolory przestają krzyczeć)
       - czernie zmiażdżone: contrast↑ + brightness↓ topi cienie w czerni sekcji
       - lekki desaturate w cieniach przez niski brightness */
    filter: saturate(0.64) contrast(1.34) brightness(0.66);
    transition: transform var(--duration-cinematic) var(--ease-out-expo),
                filter var(--duration-cinematic) var(--ease-out-expo);
    will-change: transform;
  }
  /* warstwa gradingu: crushed blacks (mnożenie czerni od dołu/brzegów do voidu)
     + winieta — kadr stapia się z czernią sekcji, nie jest płaskim prostokątem */
  .swallow::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
      radial-gradient(130% 130% at 50% 42%,
        transparent 28%,
        color-mix(in oklch, var(--surface-void), transparent 35%) 72%,
        var(--surface-void) 100%),
      linear-gradient(to bottom,
        color-mix(in oklch, var(--surface-void), transparent 55%) 0%,
        transparent 30%,
        transparent 64%,
        color-mix(in oklch, var(--surface-void), transparent 8%) 100%);
    mix-blend-mode: multiply;
  }
  /* warstwa ziarna: brutalna faktura celuloidu/cyfrowego brudu na wierzchu kadru
     (nie gładki JPG). Dedykowany gęsty noise (feTurbulence baseFrequency 0.9,
     opacity 0.5) + screen blend — na ciemnym polu rozjaśnia ziarnem, faktura
     czytelna. --texture-noise (0.04) ginął na crushed blacks. */
  .swallow::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 160 160' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)' opacity='0.5'/%3E%3C/svg%3E");
    background-size: 160px 160px;
    opacity: 0.4;
    mix-blend-mode: screen;
  }
  .swallow.is-active {
    opacity: 1;
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);  /* połyka cały viewport */
    pointer-events: auto;
  }
  .swallow.is-active > img { transform: scale(1.0); }      /* dosiad kadru, settle bez odbicia */
  /* przedsionek wypchnięty w głąb na czas połknięcia */
  .vault.is-swallowing .index,
  .vault.is-swallowing .wordmark {
    transform: scale(0.95);
    opacity: 0;
    transition:
      transform var(--duration-cinematic) var(--ease-out-expo),
      opacity   var(--duration-base)      var(--ease-standard);
  }

  /* ====================================================================
     CTA / POWRÓT — "katharsis" (§7 sek.5): void, jedno słowo serif
     off-center w dolnej tercji; hairline wypełnia słowo od dołu na hover.
     Inwersja walorów wobec wejścia (W15 klamra-pętla).
     ==================================================================== */
  .finale {
    min-block-size: 100svh;
    display: grid;
    grid-template-rows: 1fr auto;
    align-items: end;
    z-index: var(--z-content);
    position: relative;
  }
  /* uwaga 9: blok dociśnięty EKSTREMALNIE do lewego+dolnego marginesu.
     Void absolutny zajmuje całą górę i prawą stronę kadru. Zero wahania. */
  .finale__inner {
    grid-row: 2;
    justify-self: start;
    padding-block-end: clamp(var(--space-8), 8vh, var(--space-16));
    padding-inline-start: clamp(var(--space-6), 4vw, var(--space-12));
    padding-inline-end: 0;
  }
  .finale__eyebrow {
    font-family: var(--font-meta);
    font-size: var(--size-meta);
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--text-faint);
    margin-block-end: var(--space-6);
  }

  /* słowo-CTA jako rzeźba (§5, W5). Wypełnienie od dołu = klip nakładki. */
  .katharsis {
    position: relative;
    display: inline-block;
    font-family: var(--font-meta);          /* serif — powaga napisów końcowych */
    font-weight: 500;
    font-size: clamp(3rem, 11vw, 9rem);
    letter-spacing: -0.02em;
    line-height: 0.95;
    text-decoration: none;
    color: var(--text-muted);
    transition: color var(--duration-base) var(--ease-standard);
    isolation: isolate;
  }
  /* warstwa-wypełnienie: kopia słowa w pełnej bieli, odsłaniana od dołu */
  .katharsis__fill {
    position: absolute;
    inset: 0;
    color: var(--text-primary);
    clip-path: inset(100% 0 0 0);           /* schowana (od dołu 100%) */
    transition: clip-path var(--duration-cinematic) var(--ease-out-expo);
    pointer-events: none;
    will-change: clip-path;
  }
  .katharsis:hover, .katharsis:focus-visible { color: var(--text-faint); }
  .katharsis:hover .katharsis__fill,
  .katharsis:focus-visible .katharsis__fill { clip-path: inset(0 0 0 0); }

  /* hairline pod słowem (§7 sek.5, uwaga 10) — w spoczynku KRÓTKI (szer. słowa);
     na hover WYSTRZELIWUJE przez całą szerokość viewportu (fixed, tnie ekran na pół).
     Fizyczny akt: linia bazowa słowa staje się cięciem architektonicznym kadru. */
  .katharsis::after {
    content: "";
    position: fixed;
    inset-inline-start: 0;
    /* baseline-align (Gemini #4, DETERMINISTYCZNIE, ZWIĄZANE Z BASELINE NIE Z VH):
       Słowo "begin." jest DOCIŚNIĘTE DO DOŁU viewportu (.finale align:end + finale__inner
       padding-block-end). Dlatego baseline alfabetyczny słowa to STAŁY dystans OD DOŁU
       ekranu, NIEZALEŻNY od wysokości viewportu — zmierzony Playwright dla VH 900/1000/800:
       baselineFromBottom = 97.5px (constant), VH768 ~94.9 (clamp paddingu). Poprzednie
       `top: 803px` (dystans OD GÓRY) trafiało baseline TYLKO przy VH=900 — przy innej
       wysokości linia dryfowała i tnie litery. Stąd skarga Gemini.
       Pomiar baseline z PIKSELI RENDERU (clip 1:1 + ImageMagick row-profile po stronie
       prawej n/i/kropka oraz lewej b/e, hairline ukryty): dół serifowych stóp b/e/i/n =
       pageY 802.5 przy VH900 → 97.5px od dołu. Stopy spoczywają NA górnej krawędzi linii,
       kropka "." leży na linii, TYLKO descender "g" przebija w dół.
       Pozycjonowanie OD DOŁU: górna krawędź linii = baselineFromBottom; linia (block-size
       2px) rośnie W DÓŁ → bottom = baselineFromBottom - block-size. */
    bottom: calc(var(--hairline-baseline-from-bottom, 97.5px) - 2px);
    inline-size: 100vw;
    block-size: 2px;
    background: var(--text-primary);
    transform-origin: left;
    transform: scaleX(var(--hairline-rest, 0.18));
    opacity: 0.9;
    transition: transform var(--duration-cinematic) var(--ease-out-expo);
    will-change: transform;
    pointer-events: none;
  }
  .katharsis:hover::after,
  .katharsis:focus-visible::after { transform: scaleX(1); }

  /* dyskretny powrót do wejścia (§2) */
  .finale__return {
    display: inline-block;
    margin-block-start: var(--space-8);
    font-family: var(--font-meta);
    font-size: var(--size-whisper);
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--text-faint);
    text-decoration: none;
    border-block-end: 1px solid transparent;
    transition: color var(--duration-fast) var(--ease-standard),
                border-color var(--duration-fast) var(--ease-standard);
  }
  .finale__return:hover, .finale__return:focus-visible {
    color: var(--text-muted);
    border-block-end-color: var(--hairline);
  }
}

/* --------------------------------------------------------------------------
   UTILITIES — a11y i fallbacki ruchu.
   -------------------------------------------------------------------------- */
@layer utilities {
  .visually-hidden {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
}

/* reduced-motion: twarde cięcie zamiast rozszerzania (§Uwagi tech. 1).
   Bariera w foundation gasi transition-duration; tu dodatkowo gwarantujemy,
   że "Połknięcie" pojawia się natychmiast w stanie końcowym, bez animacji. */
@media (prefers-reduced-motion: reduce) {
  .slit { transition: none; }
  .swallow { transition: none; }
  .katharsis__fill, .katharsis::after { transition: none; }
}
