/* ==========================================================================
   NOCTA — nocta.css  ·  STORYBOARD FINALNY 5 AKTÓW (LOCK 2026-06-16)
   Pack glass+editorial restraint = data-pack="nocta" (foundation.css).
   Tu tylko warstwy layout + components. Tokeny: semantyczne NOCTA z foundation.
   Każdy akt = zamknięta rama kadru (grid + z-index, asymetryczny bias).
   ========================================================================== */

/* ---- utilities lokalne -------------------------------------------------- */
@layer utilities {
  .vis-hidden {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .skip-link {
    position: absolute; inset-inline-start: var(--space-2); inset-block-start: -100%;
    z-index: var(--z-toast); padding: var(--space-2) var(--space-4);
    background: var(--amber); color: var(--obsidian-deep);
    font-family: var(--font-mono); font-size: var(--font-size-caption);
    text-decoration: none; border-radius: 2px;
  }
  .skip-link:focus-visible { inset-block-start: var(--space-2); }
}

@layer base {
  body {
    background: var(--obsidian);
    color: var(--text-primary);
    font-family: var(--font-body);
    overflow-x: hidden;
  }

  /* eyebrow mono — mikro-szept W24 */
  .eyebrow {
    font-family: var(--font-mono);
    font-size: clamp(0.625rem, 0.7vw, 0.75rem);
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--text-faint);
  }

  /* prawo: jeden krój display, jeden mono. Display = rzeźba ze słowa. */
  h1, h2, h3 {
    font-family: var(--font-display);
    font-weight: var(--font-weight-heavy);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    color: var(--text-primary);
    text-wrap: balance;
  }
}

/* ==========================================================================
   LAYOUT
   ========================================================================== */
@layer layout {

  /* ----------------------------------------------------------------------
     SCROLL-SNAP — viewport=kadr: scroll zatrzymuje się na każdym AKCIE.
     Root scrolla = html (dokument). Snap na PRZYSTANKACH (akty), NIE co 100vh.
     Każdy akt = jeden przystanek (align:start). Sekcje wyższe niż ekran
     (Akt 2 ~200vh sticky, Akt 4 spec, Akt 5 stage+footer) = JEDEN przystanek
     z WEWNĘTRZNYM scrollem: snap łapie tylko GÓRĘ aktu, treść doczytywalna,
     snap-stop:always blokuje przeskok kilku aktów jednym gestem.
     reduced-motion: scroll-behavior:auto wymuszone w foundation (bariera a11y).
     ---------------------------------------------------------------------- */
  /* DOMYŚLNIE (bez JS / reduced-motion / dotyk): natywny mandatory snap +
     smooth. To fallback progressive-enhancement — strona snapuje bez JS. */
  html {
    scroll-snap-type: y mandatory;
    scroll-behavior: smooth;
  }

  /* KONTROLER PRZEJĄŁ SCROLL (eased-snap.js, desktop+mysz, bez reduced-motion):
     JS jest JEDYNYM mechanizmem przejść między aktami — natywny mandatory snap
     WYŁĄCZONY NA STAŁE (nie tylko podczas animacji). Powód: natywny mandatory
     snap SAM wyrywa do następnego przystanku przy granicy tall-sekcji (jedno
     dygnięcie u dna Aktu 4 → przeskok do Aktu 5) i konkuruje z krzywą JS. Gdy
     JS rządzi, snap robi wyłącznie kontroler (próg gestu/settle u granic tall,
     easeOut do sąsiada). Wewnątrz tall-sekcji scroll jest płynny natywny.
     Klasę nakłada initEasedSnap po sprawdzeniu, że kontroler jest aktywny. */
  html.js-snap-controlled {
    scroll-snap-type: none;
    /* Kontroler (eased-snap.js) jest JEDYNYM mechanizmem ruchu okna i animuje
       własną krzywą easeOut przez per-frame scrollTo. Natywny smooth musi być
       WYŁĄCZONY na stałe — inaczej każda klatka scrollTo odpala podrzędną
       smooth-animację przeglądarki, która walczy z krzywą JS (drift, ślamazara,
       zła pozycja). reduced-motion/dotyk nie dostają tej klasy → smooth zostaje. */
    scroll-behavior: auto;
  }

  /* Podczas animacji JS dodatkowo gasimy smooth, by krzywa easeOut nie nakładała
     się z natywnym smooth (gdyby klasa js-snap-controlled nie zdążyła zadziałać). */
  html.is-eased-scrolling {
    scroll-snap-type: none;
    scroll-behavior: auto;
  }

  .acts { display: block; }

  /* każdy akt = co najmniej 100vh, zamknięta rama */
  .act1, .act3, .act5 {
    position: relative;
    min-height: 100svh;
    display: grid;
    overflow: hidden;
    isolation: isolate;
  }

  /* każdy AKT = przystanek snapa na swojej GÓRNEJ krawędzi.
     align:start → tall-section zaczepia się górą; user przewija jej wnętrze
     zanim snap przeskoczy do następnego aktu (brak utknięcia w połowie). */
  .act1, .act2, .act3, .act4, .act5 {
    scroll-snap-align: start;
    scroll-snap-stop: always;
    /* floating nav (wyspa u góry) nie zasłania górnej krawędzi kotwicy/snapu */
    scroll-margin-block-start: 0;
  }
}

/* ==========================================================================
   NAV — floating island (glass, prawie niewidoczny na czerni)
   ========================================================================== */
@layer components {
  .nav {
    position: fixed;
    inset-block-start: var(--space-4);
    inset-inline: 0;
    z-index: var(--z-nav);
    display: flex;
    justify-content: center;
    pointer-events: none;
  }
  .nav__island {
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: clamp(var(--space-4), 3vw, var(--space-12));
    padding: var(--space-2) var(--space-6);
    background: color-mix(in oklch, var(--obsidian-deep), transparent 28%);
    backdrop-filter: blur(var(--blur-glass)) saturate(1.1);
    border: 1px solid var(--hairline-faint);
    border-radius: var(--radius-pill);
  }
  .nav__wordmark {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: 0.18em;
    font-size: 0.9rem;
    color: var(--text-primary);
    text-decoration: none;
    /* separator-przestrzeń: wordmark jest marką, nie linkiem — rozbij optycznie od nav */
    margin-inline-end: clamp(var(--space-4), 2vw, var(--space-8));
    padding-inline-end: clamp(var(--space-4), 2vw, var(--space-8));
    border-inline-end: 1px solid var(--hairline-faint);
  }
  .nav__links {
    display: flex;
    gap: var(--space-6);
  }
  .nav__links a,
  .nav__lang-btn,
  .nav__cta {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-muted);
    text-decoration: none;
    background: none;
    border: 0;
    cursor: pointer;
    transition: color var(--duration-hover) var(--ease-nocta);
  }
  .nav__links a:hover,
  .nav__lang-btn:hover { color: var(--text-primary); }
  .nav__lang { display: flex; gap: var(--space-2); }
  .nav__lang-btn.is-active { color: var(--amber); }
  .nav__cta {
    color: var(--text-primary);
    border: 1px solid var(--hairline);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
  }
  .nav__cta:hover {
    color: var(--obsidian-deep);
    background: var(--amber);
    border-color: var(--amber);
  }

  /* ---- grain: tekstura materiału (W34); subtelny overlay na foto ------- */
  .grain {
    position: absolute; inset: 0;
    background-image: var(--texture-noise);
    background-size: 220px 220px;
    mix-blend-mode: soft-light;
    opacity: 0.5;
    pointer-events: none;
    z-index: 2;
  }
  .grain--visible {
    mix-blend-mode: normal;
    opacity: 0.06;
    z-index: 0;
  }

  /* ======================================================================
     AKT 1 — OTWARCIE · cinemagraph Freja, off-center prawo, typografia lewo
     Bias: prawa = Freja, lewa = czerń + typografia (overlap na włosy).
     ====================================================================== */
  .act1 {
    grid-template-columns: 1fr;
    align-items: center;
    background: var(--obsidian-deep);
  }
  .act1__frame {
    position: absolute;
    inset: 0;
    z-index: 0;
    margin: 0;
  }
  .act1__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Freja przy prawej krawędzi; ramię ucięte; lewa połowa czerń */
    object-position: 72% center;
  }
  /* winieta po lewej — wzmacnia negatywną czerń pod typografię */
  .act1__frame::after {
    content: "";
    position: absolute; inset: 0;
    background: linear-gradient(
      100deg,
      var(--obsidian-deep) 0%,
      color-mix(in oklch, var(--obsidian-deep), transparent 35%) 34%,
      transparent 60%
    );
    z-index: 1;
    pointer-events: none;
  }
  /* GLOW oddychający na muszle słuchawek (100% CSS, mix-blend screen) */
  .act1__glow {
    position: absolute;
    /* pozycja muszli na głowie Frei (ucho/skroń, lewa krawędź jej głowy od widza) */
    inset-block-start: 37%;
    inset-inline-start: 44%;
    width: clamp(4.5rem, 8vw, 8rem);
    transform-origin: center;
    aspect-ratio: 1;
    border-radius: 50%;
    background: radial-gradient(
      circle at center,
      oklch(0.80 0.15 70 / 0.85) 0%,
      oklch(0.78 0.14 75 / 0.42) 38%,
      transparent 70%
    );
    mix-blend-mode: screen;
    z-index: 1;
    pointer-events: none;
    animation: act1-breathe var(--duration-scene) var(--ease-in-out) infinite alternate;
    will-change: opacity, transform;
  }
  @keyframes act1-breathe {
    from { opacity: 0.55; transform: scale(1); }
    to   { opacity: 1;    transform: scale(1.04); }
  }
  .act1__type {
    position: relative;
    z-index: 3;
    align-self: end;
    justify-self: start;
    max-width: min(46ch, 50vw);
    /* więcej oddechu od dolnej krawędzi (audyt A1: paragraf nie dusi się przy krawędzi) */
    padding: clamp(var(--space-8), 8vh, var(--space-24)) clamp(var(--space-6), 6vw, var(--space-24)) clamp(var(--space-12), 12vh, var(--space-32));
    display: grid;
    /* oddziel „huk" tytułu od „ciszy" body — większy odstęp niż reszta gap */
    gap: clamp(var(--space-6), 4vh, var(--space-12));
  }
  .act1__tagline {
    /* skala nagłówka A1 jako token lokalny — nadpisywany per-język (twarz Frei
       jest focal pointem; dłuższe taglines PL/ES muszą zostawić oko odsłonięte) */
    --act1-tagline-size: var(--font-size-mega);
    font-size: var(--act1-tagline-size);
    font-weight: 850;
    line-height: 0.9;
    letter-spacing: -0.05em;
    /* overlap na włosy/postać — typografia-aktor wchodzi w plan Frei */
    margin-inline-end: -16vw;
  }
  /* PL/ES: łamanie na osobne linie → wąski pionowy filar po LEWEJ (architektura,
     nie pas leżący na twarzy). EN zostaje jednociągowy (data-i18n bez spanów). */
  .act1__tl {
    display: block;
    line-height: 0.92;
  }
  /* DYREKTYWA GEMINI A1 — chronimy TWARZ (focal point), inaczej niż A5:
     tu skala MALEJE per-język, bo dłuższe taglines PL/ES leżały na oku Frei. */
  /* PL: 4 linie (filar), skala −~12% (12rem→10.5rem max), tekst ≤50% VW.
     Filar zaczyna się od lewej — kasujemy ujemny margines (był pod overlap 1-linii). */
  :lang(pl) .act1__tagline {
    --act1-tagline-size: clamp(3.5rem, 11vw, 10.5rem);
    margin-inline-end: 0;
  }
  /* ES: 3 linie, skala −~6% (12rem→11.3rem max). Tak samo bez ujemnego marginesu. */
  :lang(es) .act1__tagline {
    --act1-tagline-size: clamp(3.75rem, 12vw, 11.3rem);
    margin-inline-end: 0;
  }
  /* PL/ES: zdjęcie Frei mocno dalej w PRAWO (88%) → twarz/oko ucieka do prawej
     krawędzi, lewa połowa to czysta negatywna czerń pod filar typografii.
     DYREKTYWA GEMINI A1: oko Frei MUSI być w 100% odsłonięte jak w EN —
     żadna litera go nie dotyka. Shift obrazu uwalnia źrenicę od liter. */
  :lang(pl) .act1__img,
  :lang(es) .act1__img { object-position: 88% center; }
  /* PL/ES: węższy filar typografii — kontener nagłówka trzymany dalej od twarzy,
     długie słowa łamią się wcześniej (więcej linii, ten sam monumentalny rozmiar).
     Blok zostaje przyklejony do lewej krawędzi (architektura), nie wjeżdża w oko. */
  :lang(pl) .act1__type,
  :lang(es) .act1__type { max-width: min(34ch, 38vw); }
  .act1__lead {
    font-family: var(--font-body);
    font-weight: 400;
    /* kontrast skali nagłówek↔body niosą ROZMIAR + oddech (walor muted = pewna czytelność na czerni) */
    font-size: clamp(0.85rem, 0.5vw + 0.65rem, 0.95rem);
    line-height: 1.6;
    color: var(--text-muted);
    /* krótsza linia — nie wchodzi pod twarz/ramię, oddech po prawej */
    max-width: 30ch;
  }
  .act1__scrollhint {
    position: absolute;
    inset-block-end: var(--space-6);
    inset-inline-start: 50%;
    transform: translateX(-50%);
    z-index: 3;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.2em;
    color: var(--text-faint);
    animation: act1-hint 2.6s var(--ease-in-out) infinite;
  }
  @keyframes act1-hint {
    0%, 100% { opacity: 0.35; transform: translate(-50%, 0); }
    50%      { opacity: 0.9;  transform: translate(-50%, 5px); }
  }

  /* ======================================================================
     AKT 2 — RYTM / SKALA · Mei sticky lewo, tekst scrolluje prawo (~200vh)
     Bias: lewa ciężka (figura), prawa oddycha (manifest).
     ====================================================================== */
  .act2 {
    position: relative;
    background: var(--obsidian);
  }
  .act2__inner {
    display: grid;
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
    gap: clamp(var(--space-6), 5vw, var(--space-24));
    align-items: start;
    padding-inline: clamp(var(--space-4), 5vw, var(--space-24));
  }
  .act2__figure {
    position: sticky;
    inset-block-start: 0;
    height: 100svh;
    margin: 0;
    overflow: hidden;
    /* full-bleed do lewej krawędzi viewportu */
    margin-inline-start: calc(-1 * clamp(var(--space-4), 5vw, var(--space-24)));
  }
  .act2__figure img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Mei dosunięta do lewej krawędzi; kadr od góry, dół (uda) poza ekran */
    object-position: 28% top;
  }
  .act2__text {
    padding-block: clamp(28vh, 36vh, 44vh) 30vh;
    display: grid;
    gap: var(--space-6);
    align-content: start;
    max-width: 52ch;
  }
  .act2__heading {
    font-size: clamp(2rem, 3.6vw, 3.6rem);
    font-weight: 850;
    line-height: 1.0;
    /* DRASTYCZNY oddech: „huk" tytułu odseparowany od „ciszy" opisu (audyt A2) */
    margin-block-end: clamp(var(--space-12), 10vh, var(--space-32));
  }
  .act2__body {
    display: grid;
    gap: var(--space-6);
    /* krótsza linia — Vogue, nie Wikipedia */
    max-width: 45ch;
  }
  .act2__body p {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: clamp(1rem, 0.6vw + 0.85rem, 1.25rem);
    line-height: 1.6;
    color: var(--text-muted);
    max-width: 45ch;
  }
  /* asymetria: 1. akapit wcięty — łamie równy lewy margines bloku */
  .act2__body p:first-child {
    margin-inline-start: clamp(var(--space-6), 4vw, var(--space-16));
  }
  .act2__body p:first-child::before {
    content: "";
    display: block;
    width: clamp(var(--space-8), 3vw, var(--space-12));
    border-block-start: 1px solid var(--accent);
    margin-block-end: var(--space-4);
    margin-inline-start: calc(-1 * clamp(var(--space-6), 4vw, var(--space-16)));
  }
  .act2__body em { color: var(--text-primary); font-style: italic; }

  /* ======================================================================
     AKT 3 — ZBLIŻENIE · Mei portret pełen viewport, copy prawy-górny
     Bias: masa twarzy lewo-centrum, słowo w prawym-górnym (cel wzroku).
     ====================================================================== */
  .act3 {
    grid-template-columns: 1fr;
    background: var(--obsidian);
  }
  .act3__image {
    position: absolute;
    inset: 0;
    z-index: 0;
    margin: 0;
  }
  .act3__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* przesuń twarz Mei w PRAWO — odsłoń ciemny lewy-dolny pod kotwicę copy */
    object-position: 58% center;
  }
  /* zakotwiczenie czytelności: ciemny klin w LEWYM DOLNYM rogu (najciemniejsza strefa kadru).
     Tekst NIE leży już na jasnej szyi/twarzy — leży na pewnej czerni. */
  .act3__image::after {
    content: "";
    position: absolute; inset: 0;
    background:
      linear-gradient(
        to top,
        var(--obsidian-deep) 0%,
        color-mix(in oklch, var(--obsidian-deep), transparent 35%) 22%,
        transparent 50%
      ),
      radial-gradient(
        130% 100% at 6% 100%,
        var(--obsidian-deep) 0%,
        color-mix(in oklch, var(--obsidian-deep), transparent 30%) 30%,
        transparent 58%
      );
    z-index: 1; pointer-events: none;
  }
  .act3__type {
    position: relative;
    z-index: 3;
    justify-self: start;
    align-self: end;
    max-width: min(40ch, 44vw);
    padding: 0 0 clamp(var(--space-12), 12vh, 18vh) clamp(var(--space-6), 6vw, var(--space-24));
    text-align: start;
    display: grid;
    gap: var(--space-4);
    justify-items: start;
  }
  .act3__line {
    font-size: clamp(1.8rem, 3.4vw, 3.4rem);
    font-weight: 850;
    line-height: 1.0;
  }
  .act3__lead {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: clamp(0.9rem, 0.9vw + 0.5rem, 1.0625rem);
    line-height: 1.55;
    color: var(--text-muted);
    max-width: 34ch;
  }

  /* ======================================================================
     AKT 4 — MATERIAŁ / DOWÓD · typografia-bohater, gigant-liczby, broadsheet
     BEZ twarzy. Cyfry grafit, gęstość sparse, noise jako materiał, inwersja.
     ====================================================================== */
  .act4 {
    position: relative;
    min-height: 100svh;
    overflow: hidden;
    isolation: isolate;
    /* inwersja walorów W27: tytan tło / obsydian tekst (data-tone="invert") */
    background: var(--bg-primary);
    color: var(--text-primary);
    padding: clamp(var(--space-16), 14vh, var(--space-40)) clamp(var(--space-4), 6vw, var(--space-40));
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--space-6) clamp(var(--space-4), 3vw, var(--space-12));
    align-content: start;
  }
  /* gigant-liczby ścięte krawędziami — cisza walorowa (grafit, minim. kontrast) */
  .act4__giants {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
  }
  .act4__giant {
    position: absolute;
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: var(--font-size-giant);
    line-height: 0.8;
    /* grafit na jasnym tle inwersji — minimalny kontrast, ledwie czytelne */
    color: color-mix(in oklch, var(--obsidian-deep), transparent 86%);
    letter-spacing: -0.04em;
  }
  .act4__giant--anc     { inset-block-start: -4vh; inset-inline-end: -3vw; }
  /* minus dosunięty do „48" — w mono advance-width znaku odrywa go wizualnie */
  .act4__giant-sign { margin-inline-end: -0.22em; }
  .act4__giant--driver  { inset-block-end: 18vh; inset-inline-start: -4vw; }
  .act4__giant--battery { inset-block-end: -6vh; inset-inline-end: 12vw; }

  .act4__head {
    position: relative;
    z-index: 1;
    grid-column: 1 / span 7;
    display: grid;
    gap: var(--space-4);
  }
  .act4__heading {
    font-size: clamp(2.4rem, 6vw, 6rem);
    font-weight: 850;
    line-height: 0.92;
    letter-spacing: -0.05em;
    color: var(--text-primary);
  }
  .act4__intro {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: clamp(0.95rem, 0.6vw + 0.8rem, 1.125rem);
    line-height: 1.55;
    color: var(--text-muted);
    max-width: 52ch;
  }

  /* ZŁAMANY grid — nie cennik SaaS. Kolumny nierówne (1. szersza), środkowa
     zepchnięta w dół osi Y, 3. lekko podniesiona = układ schodkowy/bento (editorial). */
  .act4__materials {
    position: relative;
    z-index: 1;
    grid-column: 1 / span 12;
    display: grid;
    grid-template-columns: 1.5fr 1fr 1.15fr;
    align-items: start;
    column-gap: clamp(var(--space-8), 6vw, var(--space-24));
    margin-block-start: clamp(var(--space-8), 6vh, var(--space-24));
    padding-block-start: var(--space-8);
    border-block-start: 1px solid var(--hairline);
  }
  .act4__mat { position: relative; display: grid; gap: var(--space-2); align-content: start; }
  /* schodkowe przesunięcia w pionie (position: top — niezależne od grid/reveal-transform) */
  .act4__mat:nth-child(1) { inset-block-start: 0; }
  .act4__mat:nth-child(2) { inset-block-start: clamp(var(--space-10), 7vh, var(--space-24)); }
  .act4__mat:nth-child(3) { inset-block-start: clamp(var(--space-4), 3.5vh, var(--space-12)); }
  .act4__mat-no {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.2em;
    color: var(--accent);
  }
  .act4__mat-name {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(1.1rem, 1.4vw, 1.5rem);
    letter-spacing: -0.02em;
    color: var(--text-primary);
  }
  .act4__mat-desc {
    font-family: var(--font-body);
    font-size: clamp(0.85rem, 0.5vw + 0.75rem, 0.95rem);
    line-height: 1.55;
    color: var(--text-muted);
  }

  .act4__table {
    position: relative;
    z-index: 1;
    grid-column: 1 / span 12;
    margin-block-start: clamp(var(--space-12), 9vh, var(--space-40));
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 clamp(var(--space-8), 6vw, var(--space-24));
  }
  .act4__row {
    display: grid;
    grid-template-columns: minmax(0, 0.42fr) minmax(0, 0.58fr);
    gap: var(--space-4);
    padding-block: var(--space-3);
    border-block-end: 1px solid var(--hairline);
    align-items: baseline;
  }
  .act4__row dt {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-faint);
  }
  .act4__row dd {
    font-family: var(--font-body);
    font-size: clamp(0.8125rem, 0.5vw + 0.7rem, 0.9375rem);
    color: var(--text-primary);
  }

  /* ======================================================================
     AKT 5 — FINAŁ · produkt z czerni; nagłówek wchodzi ZA słuchawki (overlap)
     MEMORABLE: 3 plany głębi z płaskich elementów. CTA prostokąt solid.
     ====================================================================== */
  .act5 {
    grid-template-rows: 1fr auto;
    align-items: stretch;
    background: var(--obsidian-deep);
    padding-block: 0;
  }
  /* SUBSTRAT (recepta Gemini pkt 3): światło formą — rozmyty radialny gradient
     ciepłego zgaszonego brązu/złota → czerń ZA słuchawkami (rim-light z tyłu),
     wyciąga sylwetkę z mroku, odkleja od tła. Akcent <5%: tłumione, miękkie. */
  .act5::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background:
      radial-gradient(58% 70% at 72% 46%,
        color-mix(in oklch, var(--amber), transparent 80%) 0%,
        color-mix(in oklch, var(--amber), transparent 92%) 34%,
        transparent 66%);
  }
  /* ziarno na CAŁEJ sekcji — spaja typografię z renderem (Prawo Materiału).
     Nad glow i produktem, ale niemal niewidoczne (soft-light, niska opacity). */
  .act5::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    background-image: var(--texture-noise);
    background-size: 180px 180px;
    /* screen wydobywa ziarno na obsydianowej czerni (overlay/soft-light tu martwe);
       na jasnym tytanie produktu wpływ minimalny — ziarno spaja pola, nie matowi */
    mix-blend-mode: screen;
    opacity: 0.55;
  }
  /* scena = grid z warstwami z-index: nagłówek (BG) · produkt (MG) · close (FG).
     Anti-funnel: produkt do PRAWEJ krawędzi, słowo i CTA zablokowane do LEWEJ. */
  .act5__stage {
    position: relative;
    grid-row: 1;
    display: grid;
    grid-template-columns: 1fr;
    /* jeden row dokładnie wysokości kadru — bez tego stacked content rozpycha track
       ponad 100svh i align-end liczy się od przerośniętego tracka (CTA pod fold) */
    grid-template-rows: 100%;
    align-items: center;
    width: 100%;
    /* dokładnie jeden kadr (zamknięta rama) — close kotwiczy realny dół viewportu */
    height: 100svh;
    overflow: hidden;
    padding-inline: clamp(var(--space-6), 6vw, var(--space-40));
    z-index: 1;
  }
  /* produkt: dosunięty do PRAWEJ, wychodzi poza kadr; MG nad nagłówkiem (overlap konturem) */
  .act5__product {
    grid-area: 1 / 1;
    z-index: 2;
    margin: 0;
    /* MONUMENTALNY (recepta Gemini pkt 1: +~140% masy): produkt dominuje prawą połowę kadru.
       Kotwiczony do PRAWEJ krawędzi z UJEMNYM offsetem — prawa muszla + część pałąka
       realnie wychodzą POZA prawą krawędź viewportu (ostry crop, nie margines).
       overflow:hidden na .act5 obcina to, co wystaje. Szerokość > połowy kadru,
       więc lewa muszla brutalnie najeżdża na „now." (overlap typografia↔produkt). */
    width: min(118vw, 1620px);
    justify-self: end;
    align-self: center;
    /* przesunięcie w prawo: prawa muszla poza kadr (~18% produktu ucięte) */
    margin-inline-end: clamp(-26vw, -19vw, -12vw);
    /* dolly do prawego-górnego: pałąk ucieka w prawy górny róg → przekątna */
    margin-block-start: clamp(-16vh, -11vh, -5vh);
    /* dosuw lewej muszli na słowo „now." (kropka + pół „w" pod produktem):
       statyczny offset trzymany przez zmienną, animacja dokłada Y+scale */
    --shift-x: clamp(-9vw, -6vw, -3vw);
    pointer-events: none;
    animation: act5-emerge var(--duration-reveal) var(--ease-nocta) both;
  }
  .act5__product img {
    width: 100%;
    height: auto;
    /* cutout PNG z alfą: cała sylwetka widoczna, lewituje nad czernią (NIE prostokąt).
       glow bursztynowy pod muszlą = lewitacja; cień miękki = oderwanie od tła */
    filter:
      drop-shadow(0 18px 60px oklch(0 0 0 / 0.55))
      drop-shadow(0 0 90px oklch(0.78 0.14 75 / 0.16));
  }
  @keyframes act5-emerge {
    from { opacity: 0; transform: translateX(var(--shift-x)) translateY(18px) scale(0.98); }
    to   { opacity: 1; transform: translateX(var(--shift-x)) translateY(0) scale(1); }
  }
  /* nagłówek: JEDEN integralny blok (litery nieuszkodzone), zablokowany do LEWEJ.
     Produkt (z-index 2) przykrywa jego prawą część SWOIM konturem — overlap bez maski. */
  .act5__title {
    grid-area: 1 / 1;
    z-index: 1;
    /* recepta pkt 4: rozbij centrowanie pionowe — zrzuć blok tekstu NIŻEJ.
       Nagłówek siada w dolnej połowie kadru, nad blokiem CTA → przekątna
       lewy-dół (CTA) ↘ prawy-góra (pałąk poza kadr). */
    justify-self: start;
    align-self: end;
    margin: 0 0 clamp(17rem, 41vh, 24rem) 0;
    text-align: start;
    font-family: var(--font-display);
    /* recepta pkt 2: variable Black/Heavy — architektoniczny blok, mięsiste litery */
    font-weight: 850;
    font-variation-settings: "wght" 850;
    font-size: clamp(2.6rem, 9vw, 8.5rem);
    line-height: 0.86;
    /* tracking ściśnięty mocniej — zbita bryła */
    letter-spacing: -0.062em;
    /* recepta pkt 2: NIE czysty biel/tytan — domieszka ciepłego beżu (~2-3%),
       koresponduje ze złotym detalem słuchawek. Lokalny ink, nie globalny --text-primary. */
    color: color-mix(in oklch, var(--text-primary), var(--amber) 7%);
    pointer-events: none;
  }
  /* każda linia osobno: L1 cała w lewej strefie (przed produktem),
     L2/L3 wchodzą pod produkt (overlap typografia↔produkt = memorable A5).
     EN = 2 linie (L1+L2). PL/ES = 3 linie (L1+L2+L3, span L3 z i18n). */
  .act5__title-l1,
  .act5__title-l2,
  .act5__title-l3 { display: block; white-space: nowrap; }
  /* L2/L3 minimalnie wcięte — łamana symetria, nie grzeczny blok */
  .act5__title-l2,
  .act5__title-l3 { padding-inline-start: 0.6ch; }
  /* DYREKTYWA GEMINI: skala h1 A5 NIETYKALNA — ten sam token clamp() dla WSZYSTKICH
     języków (EN/PL/ES). Różnice długości rozwiązuje ŁAMANIE WIERSZY (3 spany w PL/ES,
     2 w EN), nie zmniejszanie fontu. Tekst MA prawo być częściowo zasłonięty produktem,
     dopóki sens słowa nie ginie (L1 czysta, zasłonięte tylko końcówki L2/L3). */
  /* ES (dyrektywa): „dociśnij lewą stronę" — minimalnie zmniejsz ODSTĘP nagłówek→close
     (margines dolny), by masa 3 linii była zbita. To zmiana odstępu, NIE fontu. */
  :lang(es) .act5__title { margin-block-end: clamp(14rem, 36vh, 21rem); }
  /* close: lead + CTA + note — zablokowane do LEWEJ, FG nad wszystkim */
  /* recepta pkt 4: CTA kotwiczy LEWY DOLNY róg — absolutne zakotwiczenie w ramie stage
     (grid-stack rozpychał blok pod fold; absolut trzyma róg deterministycznie) */
  .act5__close {
    position: absolute;
    left: clamp(var(--space-6), 6vw, var(--space-40));
    bottom: clamp(var(--space-8), 7vh, var(--space-16));
    z-index: 4;
    display: grid;
    justify-items: start;
    gap: var(--space-6);
    max-width: 34ch;
    text-align: start;
  }
  .act5__lead {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: clamp(0.95rem, 0.6vw + 0.8rem, 1.125rem);
    line-height: 1.55;
    color: var(--text-muted);
    max-width: 32ch;
  }
  /* CTA = architektoniczny prostokąt, ostre kąty, solid bursztyn, mocna strzałka (NIE pigułka) */
  .act5__cta {
    display: inline-flex;
    align-items: center;
    gap: var(--space-4);
    font-family: var(--font-mono);
    font-size: 0.8125rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--obsidian-deep);
    background: var(--amber);
    padding-block: clamp(var(--space-4), 1.4vh, var(--space-6));
    padding-inline: clamp(var(--space-6), 3vw, var(--space-10));
    border-radius: 0;
    text-decoration: none;
    transition:
      background var(--duration-hover) var(--ease-nocta),
      gap var(--duration-hover) var(--ease-nocta);
  }
  .act5__cta-arrow { display: block; flex: none; }
  .act5__cta:hover {
    background: color-mix(in oklch, var(--amber), white 12%);
    gap: var(--space-6);
  }
  .act5__note {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.18em;
    color: var(--text-muted);
  }

  /* ---- FOOTER-INDEKS (W30) ------------------------------------------- */
  .findex {
    grid-row: 2;
    z-index: 4;
    width: 100%;
    padding: clamp(var(--space-12), 8vh, var(--space-24)) clamp(var(--space-4), 6vw, var(--space-24)) var(--space-8);
    border-block-start: 1px solid var(--hairline-faint);
    display: grid;
    gap: var(--space-8);
  }
  .findex__eyebrow { grid-column: 1 / -1; }
  .findex__cols {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-8);
  }
  .findex__label {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: 1rem;
    color: var(--text-primary);
    margin-block-end: var(--space-1);
  }
  .findex__note,
  .findex__colorway {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    color: var(--text-muted);
  }
  .findex__colorways { display: grid; gap: var(--space-2); }
  .findex__colorway--onyx  { color: var(--text-muted); }
  .findex__colorway--frost { color: var(--text-faint); }
  .findex__base {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--space-4);
    padding-block-start: var(--space-6);
    border-block-start: 1px solid var(--hairline-faint);
  }
  .findex__sig {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.1em;
    color: var(--text-faint);
  }
  .findex__legal {
    display: flex;
    gap: var(--space-6);
  }
  .findex__legal a {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-faint);
    text-decoration: none;
  }
  .findex__legal a:hover { color: var(--text-muted); }

  /* ======================================================================
     MOTION — reveal (T2): opacity + translate, easeOutExpo, stagger.
     Tylko transform/opacity. reduced-motion gasi w foundation + niżej.
     ====================================================================== */
  [data-reveal] {
    opacity: 0;
    transform: translateY(20px);
    transition:
      opacity var(--duration-reveal) var(--ease-nocta),
      transform var(--duration-reveal) var(--ease-nocta);
    transition-delay: var(--reveal-delay, 0ms);
  }
  [data-reveal].is-in {
    opacity: 1;
    transform: none;
  }
}

/* ==========================================================================
   REDUCED MOTION — pełny fallback (user MA reduced-motion ON)
   Glow/puls/hint wyłączone; treść statyczna i w pełni widoczna.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .act1__glow { animation: none; opacity: 0.7; transform: none; }
  .act1__scrollhint { animation: none; opacity: 0.6; }
  /* reduced: bez wejścia, ale kompozycja TRZYMA — dosuw lewej muszli na „now." zostaje */
  .act5__product { animation: none; transform: translateX(var(--shift-x)); }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}

/* ==========================================================================
   RESPONSYWNOŚĆ — desktop = kadr poziomy (scope). Wąsko: złóż do stosu.
   Container/MQ tylko jako ostatnia obrona układu, nie jako jedyny RWD.
   ========================================================================== */
@media (max-width: 64rem) {
  .act2__inner { grid-template-columns: 1fr; }
  .act2__figure {
    position: relative;
    height: 70svh;
    margin-inline-start: calc(-1 * clamp(var(--space-4), 5vw, var(--space-24)));
    margin-inline-end:   calc(-1 * clamp(var(--space-4), 5vw, var(--space-24)));
  }
  .act2__text { padding-block: var(--space-12) var(--space-16); }
  .act4__head { grid-column: 1 / -1; }
  .act4__materials { grid-template-columns: 1fr; }
  .act4__table { grid-template-columns: 1fr; }
  .act1__tagline { margin-inline-end: 0; }
  .act3__type { max-width: min(48ch, 80vw); }
}
