@charset "UTF-8";

/* ===========================================================================
   WARSTWA MOTION — efekty wyższego rzędu
   1. Preloader          2. Kursor autorski      3. Pasek postępu
   4. Rozbicie typografii 5. Magnetyczne CTA     6. Marquee
   7. Scroll-driven      8. Hero: wyjście        9. Pasek poziomy
   10. Liczniki          11. Kinetyczna stopka   12. Nawigacja
   13. Przejścia stron   14. Redukcja ruchu
   ===========================================================================
   ZASADA: każdy efekt jest nakładką. Treść musi być czytelna, gdy efekt
   nie zadziała — bez JS, bez obsługi scroll-timeline, przy reduced-motion.
   =========================================================================== */

:root {
  --ease-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-back: cubic-bezier(0.34, 1.56, 0.64, 1);
  --t-curtain: 900ms;
}

/* --- 1. Preloader --------------------------------------------------------- */

.preloader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-content: center;
  gap: 1.75rem;
  justify-items: center;
  background-color: var(--ink);
  clip-path: inset(0 0 0 0);
  transition: clip-path var(--t-curtain) var(--ease-expo);
  /* BEZPIECZNIK: gdyby motion.js nie wystartował, zasłona i tak zejdzie.
     Ekran powitalny nie może zablokować strony na stałe. */
  animation: pl-failsafe 1ms linear 3.2s forwards;
}

@keyframes pl-failsafe {
  to {
    clip-path: inset(0 0 100% 0);
    visibility: hidden;
    pointer-events: none;
  }
}

.preloader[data-done="true"] {
  clip-path: inset(0 0 100% 0);
  pointer-events: none;
}

.preloader__mark {
  display: grid;
  place-items: center;
  width: 74px;
  height: 74px;
  color: var(--white);
  background-image: var(--gradient-brand);
  border-radius: 0;
  box-shadow: 0 20px 60px -18px rgba(124, 58, 237, 0.9);
  animation: pl-pop 760ms var(--ease-back) both;
}

.preloader__mark svg {
  width: 38px;
  height: 38px;
  stroke-dasharray: 60;
  stroke-dashoffset: 60;
  animation: pl-draw 900ms var(--ease-expo) 160ms forwards;
}

@keyframes pl-pop {
  from { opacity: 0; transform: translateY(18px) scale(0.86); }
  to   { opacity: 1; transform: none; }
}

@keyframes pl-draw {
  to { stroke-dashoffset: 0; }
}

.preloader__word {
  overflow: hidden;
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 2.4vw, 1.6rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--white);
}

.preloader__word span {
  display: inline-block;
  animation: pl-up 640ms var(--ease-expo) both;
}

@keyframes pl-up {
  from { transform: translateY(110%); }
  to   { transform: none; }
}

.preloader__bar {
  position: relative;
  width: min(240px, 50vw);
  height: 2px;
  overflow: hidden;
  background-color: rgba(255, 255, 255, 0.16);
  border-radius: 0;
}

.preloader__bar i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 100%;
  background-image: var(--gradient-brand);
  transform: scaleX(var(--p, 0));
  transform-origin: left center;
  transition: transform 180ms linear;
}

.preloader__count {
  font-family: var(--font-display);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  color: rgba(255, 255, 255, 0.55);
  font-variant-numeric: tabular-nums;
}

/* Dopóki preloader pracuje, strona pod spodem nie przewija się. */
body[data-loading="true"] {
  overflow: hidden;
}

/* --- 2. Kursor autorski — USUNIĘTY -------------------------------------- */

/* Pierścień goniący wskaźnik czytał się jak gadżet i odbierał natywną
   afordancję kursora. Została tylko klasa .magnetic (sekcja 5). */

/* --- 3. Pasek postępu ----------------------------------------------------- */

.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 150;
  width: 100%;
  height: 3px;
  background-image: var(--gradient-brand);
  transform: scaleX(var(--p, 0));
  transform-origin: left center;
  pointer-events: none;
}

@supports (animation-timeline: scroll()) {
  .scroll-progress {
    transform: scaleX(0);
    animation: sp-grow linear both;
    animation-timeline: scroll(root block);
  }
  @keyframes sp-grow {
    to { transform: scaleX(1); }
  }
}

/* --- 4. Rozbicie typografii ----------------------------------------------- */

/* Maska wierszowa: słowo wjeżdża zza krawędzi wiersza. */
.split {
  display: block;
}

.split__w {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  /* zapas na podcięcia i polskie ogonki (ą, ę, ż) */
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}

.split__w > i {
  display: inline-block;
  font-style: inherit;
  transform: translateY(110%);
  opacity: 0;
}

.split.is-in .split__w > i {
  transform: none;
  opacity: 1;
  transition: transform 900ms var(--ease-expo), opacity 600ms linear;
  transition-delay: calc(var(--i, 0) * 42ms);
}

/* Zjazd znakowy dla krótkich etykiet */
.split--chars .split__w > i {
  transform: translateY(100%) rotate(6deg);
}

.split.is-in.split--chars .split__w > i {
  transform: none;
}

/* --- 5. Magnetyczne CTA i wypełnienie ------------------------------------- */

.magnetic {
  --mx: 0px;
  --my: 0px;
  transform: translate3d(var(--mx), var(--my), 0);
  transition: transform 420ms var(--ease-expo);
}

.magnetic:active {
  transition-duration: 90ms;
}

/* Płynne wypełnienie przycisku obrysowego */
.btn--ghost {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.btn--ghost::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--gradient-brand);
  transform: translateY(101%);
  transition: transform 520ms var(--ease-expo);
}

@media (hover: hover) and (pointer: fine) {
  .btn--ghost:hover::before,
  .btn--ghost:focus-visible::before {
    transform: none;
  }
  .btn--ghost:hover,
  .btn--ghost:focus-visible {
    color: var(--white);
    border-color: transparent;
  }
}

/* Połysk przebiegający przez główne CTA.
   Przycisk MUSI przycinać zawartość — bez tego pasek światła widać
   obok przycisku także w spoczynku. */
.btn--primary {
  overflow: hidden;
}

.btn--primary::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    105deg,
    transparent 38%,
    rgba(255, 255, 255, 0.42) 50%,
    transparent 62%
  );
  transform: translateX(-120%);
  pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover::after {
    animation: sheen 760ms var(--ease-out);
  }
}

@keyframes sheen {
  to { transform: translateX(120%); }
}

/* --- 6. Marquee ----------------------------------------------------------- */

.marquee {
  position: relative;
  display: flex;
  overflow: hidden;
  /* Pas pochyla się przy szybkim przewijaniu — skew nakładamy na kontener,
     bo transform samego toru jest zajęty przez animację pętli. */
  transform: skewX(var(--skew, 0deg));
  transition: transform 420ms var(--ease-out);
  padding-block: clamp(0.75rem, 1.6vw, 1.25rem);
  user-select: none;
  /* wygaszenie krawędzi, żeby pas nie urywał się twardo */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}

.marquee__track {
  display: flex;
  flex: none;
  gap: clamp(1.5rem, 3vw, 3rem);
  padding-right: clamp(1.5rem, 3vw, 3rem);
  white-space: nowrap;
  animation: marquee-run var(--dur, 34s) linear infinite;
  animation-play-state: running;
  will-change: transform;
}

.marquee--reverse .marquee__track {
  animation-direction: reverse;
}

.marquee:hover .marquee__track {
  animation-play-state: paused;
}

@keyframes marquee-run {
  to { transform: translateX(-100%); }
}

.marquee__item {
  display: inline-flex;
  align-items: center;
  gap: clamp(1.5rem, 3vw, 3rem);
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 4.2vw, 3.75rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--c-heading);
}

.marquee__item::after {
  content: "";
  flex: none;
  width: clamp(10px, 1.4vw, 18px);
  height: clamp(10px, 1.4vw, 18px);
  border-radius: 50%;
  background-image: var(--gradient-brand);
}

/* Co drugi wyraz tylko w obrysie — rytm wizualny */
.marquee__item--outline {
  color: transparent;
  -webkit-text-stroke: 1.5px var(--c-border-strong);
}

/* --- 6b. Pas haseł: oprawa sekcji ----------------------------------------- */

.section--flush {
  padding-block: clamp(1.5rem, 3vw, 3rem);
}

/* Dekoracyjna aureola wystaje poza sekcję i bez przycięcia rozciągałaby
   dokument w poziomie. `clip` zamiast `hidden` — nie tworzy kontenera
   przewijania, więc nie psuje position: sticky w środku. */
.section--clip,
.section:has(> .glow) {
  overflow: clip;
}

.marquee-band {
  border-block: 1px solid rgba(255, 255, 255, 0.1);
}

/* --- 6c. Wskaźnik przewijania --------------------------------------------- */

.scroll-cue {
  position: absolute;
  bottom: clamp(1rem, 3vw, 2.25rem);
  left: 50%;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  transform: translateX(-50%);
  font-family: var(--font-ui);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
  pointer-events: none;
}

.scroll-cue i {
  display: block;
  width: 1px;
  height: 3rem;
  overflow: hidden;
  background-color: rgba(255, 255, 255, 0.16);
}

.scroll-cue i::after {
  content: "";
  display: block;
  width: 100%;
  height: 40%;
  background-image: linear-gradient(to bottom, var(--violet-500), var(--magenta-500));
  animation: cue-run 2.1s var(--ease-in-out) infinite;
}

@keyframes cue-run {
  0%   { transform: translateY(-100%); }
  100% { transform: translateY(250%); }
}

@media (max-width: 1023.98px) {
  .scroll-cue {
    display: none;
  }
}

/* Żywa kropka przy etykiecie */
.eyebrow--live::after {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background-color: var(--mint-300);
  box-shadow: 0 0 0 0 rgba(103, 232, 249, 0.65);
  animation: live-pulse 2.4s var(--ease-out) infinite;
}

@keyframes live-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(103, 232, 249, 0.6); }
  70%  { box-shadow: 0 0 0 10px rgba(103, 232, 249, 0); }
  100% { box-shadow: 0 0 0 0 rgba(103, 232, 249, 0); }
}

/* --- 6d. Rząd liczb -------------------------------------------------------- */

.stats-row {
  gap: clamp(1.75rem, 3.5vw, 3rem);
}

.stats-row .stat {
  position: relative;
  padding-left: clamp(1rem, 2vw, 1.75rem);
  border-left: 1px solid var(--c-border);
}

@media (max-width: 639.98px) {
  .stats-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* --- 7. Scroll-driven ----------------------------------------------------- */

/* Dostępne w Chrome/Edge 115+ i Safari 26+. Firefox ignoruje blok @supports,
   a tam o widoczność dba obserwator w JS. */
@supports (animation-timeline: view()) {
  html.sda [data-sda="rise"] {
    animation: sda-rise linear both;
    animation-timeline: view();
    animation-range: entry 4% cover 26%;
  }

  html.sda [data-sda="scale"] {
    animation: sda-scale linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 34%;
  }

  html.sda [data-sda="tilt"] {
    animation: sda-tilt linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 40%;
  }

  /* Pasek obrazów przesuwa się przeciwnie do scrolla */
  html.sda [data-sda="drift"] {
    animation: sda-drift linear both;
    animation-timeline: view();
    animation-range: cover;
  }
}

@keyframes sda-rise {
  from { opacity: 0; transform: translateY(46px); }
  to   { opacity: 1; transform: none; }
}

@keyframes sda-scale {
  from { opacity: 0; transform: scale(0.92) translateY(30px); }
  to   { opacity: 1; transform: none; }
}

@keyframes sda-tilt {
  from { opacity: 0; transform: perspective(1000px) rotateX(12deg) translateY(50px); }
  to   { opacity: 1; transform: perspective(1000px) rotateX(0) translateY(0); }
}

@keyframes sda-drift {
  from { transform: translateX(6%); }
  to   { transform: translateX(-6%); }
}

/* --- 8. Hero: wyjście przy scrollu ---------------------------------------- */

@supports (animation-timeline: view()) {
  html.sda .hero__copy,
  html.sda .hero__visual {
    animation: hero-exit linear both;
    animation-timeline: view();
    animation-range: exit 0% exit 100%;
  }
}

@keyframes hero-exit {
  to {
    opacity: 0;
    transform: translateY(-60px) scale(0.96);
    filter: blur(6px);
  }
}

/* Aureola oddychająca pod hero */
.glow--breathe {
  animation: breathe 9s var(--ease-in-out) infinite alternate;
}

@keyframes breathe {
  from { transform: translate3d(0, 0, 0) scale(1); opacity: 0.42; }
  to   { transform: translate3d(2%, -3%, 0) scale(1.14); opacity: 0.62; }
}

/* --- 9. Pasek poziomy (realizacje) ---------------------------------------- */

.hstrip {
  position: relative;
}

.hstrip__viewport {
  display: flex;
  gap: clamp(1rem, 2vw, 1.75rem);
  padding-inline: var(--gutter);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
  scrollbar-color: var(--violet-600) transparent;
}

.hstrip__viewport > * {
  flex: 0 0 min(86vw, 25rem);
  scroll-snap-align: center;
}

.hstrip__viewport::-webkit-scrollbar {
  height: 6px;
}

.hstrip__viewport::-webkit-scrollbar-thumb {
  background-image: var(--gradient-brand);
  border-radius: 0;
}

.hstrip__hint {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.25rem;
  padding-inline: var(--gutter);
  font-family: var(--font-ui);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-text-muted);
}

.hstrip__hint i {
  display: block;
  width: 2.5rem;
  height: 1px;
  background-image: var(--gradient-brand);
  animation: hint-slide 1.8s var(--ease-in-out) infinite;
  transform-origin: left center;
}

@keyframes hint-slide {
  0%, 100% { transform: scaleX(0.4); }
  50%      { transform: scaleX(1); }
}

/* --- 10. Liczniki --------------------------------------------------------- */

.stat {
  display: grid;
  gap: 0.35rem;
}

.stat__num {
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 6vw, 4.75rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  background: var(--gradient-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.surface-light .stat__num,
.surface-cloud .stat__num {
  background: linear-gradient(100deg, #6d28d9, #c026d3 55%, #4f46e5);
  -webkit-background-clip: text;
  background-clip: text;
}

.stat__label {
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
  max-width: 24ch;
}

/* --- 11. Kinetyczna stopka ------------------------------------------------ */

.kinetic {
  display: block;
  overflow: hidden;
  text-decoration: none;
  margin-block: clamp(2rem, 5vw, 4rem) 0;
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 12vw, 11rem);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.045em;
  text-align: center;
  color: transparent;
  -webkit-text-stroke: 1px rgba(255, 255, 255, 0.28);
  transition: color 520ms var(--ease-out), -webkit-text-stroke-color 520ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .kinetic:hover {
    color: transparent;
    background: var(--gradient-text);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-stroke-color: transparent;
  }
}

/* --- 12. Nawigacja — wyraźna afordancja ----------------------------------- */

/* Podkreślenie wyjeżdża od lewej przy najechaniu */
.nav__link::before {
  content: "";
  position: absolute;
  left: 0.85rem;
  right: 0.85rem;
  bottom: 0.3rem;
  height: 2px;
  border-radius: 0;
  background-image: var(--gradient-brand);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 420ms var(--ease-expo);
}

@media (hover: hover) and (pointer: fine) {
  .nav__link:hover::before,
  .nav__link:focus-visible::before {
    transform: scaleX(1);
    transform-origin: left center;
  }
}

/* Podmiana etykiety w pionie — czytelny sygnał „to jest klikalne” */
/* Maska ma wysokość DOKŁADNIE jednego wiersza. Gdyby przycinał dopiero link,
   kopia etykiety prześwitywałaby w jego dolnym paddingu. */
.nav__mask {
  display: block;
  overflow: hidden;
  line-height: 1.45;
}

.nav__mask > span {
  position: relative;
  display: block;
  transition: transform 420ms var(--ease-expo);
}

/* Kopia etykiety czeka tuż pod spodem i jedzie razem z oryginałem. */
.nav__mask > span::after {
  content: attr(data-label);
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  color: var(--violet-300);
}

.site-header--light .nav__mask > span::after {
  color: var(--violet-600);
}

@media (hover: hover) and (pointer: fine) {
  .nav__link:hover .nav__mask > span,
  .nav__link:focus-visible .nav__mask > span {
    transform: translateY(-100%);
  }
}

/* Karty: wyraźnie klikalne */
.work,
.pillar {
  cursor: pointer;
}

.work__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--gradient-brand);
  opacity: 0;
  mix-blend-mode: overlay;
  transition: opacity 420ms var(--ease-out);
  pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
  .work:hover .work__media::after {
    opacity: 0.45;
  }
}

/* --- 13. Przejścia stron -------------------------------------------------- */

@view-transition {
  navigation: auto;
}

::view-transition-old(root) {
  animation: vt-out 240ms var(--ease-out) both;
}

::view-transition-new(root) {
  animation: vt-in 380ms var(--ease-expo) both;
}

@keyframes vt-out {
  to { opacity: 0; transform: translateY(-10px); }
}

@keyframes vt-in {
  from { opacity: 0; transform: translateY(14px); }
}

/* --- 15. Żywe tło: siatka gradientów -------------------------------------- */

/* Cztery plamy światła krążące niezależnie. Tylko transform/opacity,
   więc nie wywołuje przeliczania układu. */
.mesh {
  position: absolute;
  inset: -20%;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  opacity: 0.55;
}

.mesh span {
  position: absolute;
  width: 48%;
  aspect-ratio: 1;
  border-radius: 50%;
  filter: blur(70px);
  will-change: transform;
}

.mesh span:nth-child(1) {
  top: 2%;
  left: 4%;
  background: radial-gradient(circle, rgba(124, 58, 237, 0.85), transparent 68%);
  animation: mesh-a 22s var(--ease-in-out) infinite alternate;
}

.mesh span:nth-child(2) {
  top: 28%;
  right: 0%;
  background: radial-gradient(circle, rgba(217, 70, 239, 0.65), transparent 68%);
  animation: mesh-b 27s var(--ease-in-out) infinite alternate;
}

.mesh span:nth-child(3) {
  bottom: 0%;
  left: 24%;
  background: radial-gradient(circle, rgba(99, 102, 241, 0.75), transparent 68%);
  animation: mesh-c 31s var(--ease-in-out) infinite alternate;
}

.mesh span:nth-child(4) {
  top: 44%;
  left: 38%;
  width: 34%;
  background: radial-gradient(circle, rgba(103, 232, 249, 0.3), transparent 66%);
  animation: mesh-d 19s var(--ease-in-out) infinite alternate;
}

@keyframes mesh-a { to { transform: translate3d(28%, 18%, 0) scale(1.25); } }
@keyframes mesh-b { to { transform: translate3d(-24%, 26%, 0) scale(0.82); } }
@keyframes mesh-c { to { transform: translate3d(22%, -22%, 0) scale(1.2); } }
@keyframes mesh-d { to { transform: translate3d(-30%, -16%, 0) scale(1.4); } }

/* --- 16. Karty 3D ---------------------------------------------------------- */

/* Warianty wejścia BEZ transform — dla elementów, które same sterują
   transformem (karty 3D). Inaczej animacja wejścia z fill: both nadpisałaby
   pochylenie na stałe i karta przestałaby reagować na kursor. */
@supports (animation-timeline: view()) {
  html.sda [data-sda="fade"] {
    animation: sda-fade linear both;
    animation-timeline: view();
    animation-range: entry 4% cover 24%;
  }
}

@keyframes sda-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Reguła wejścia i pochylenie kart walczyłyby o właściwość transform
   (selektor wejścia ma wyższą swoistość i wygrywał). Dlatego pochylenie
   mieszka w zmiennej, a obie reguły tylko ją konsumują. */
html.js [data-reveal="fade"],
html.js [data-reveal="fade"].is-visible {
  transform: var(--tilt-transform, none);
}

.tilt {
  --rx: 0deg;
  --ry: 0deg;
  --tz: 0px;
  --tilt-transform: perspective(1100px) rotateX(var(--rx)) rotateY(var(--ry))
    translateZ(var(--tz));
  transform: var(--tilt-transform);
  transform-style: preserve-3d;
  transition: transform 520ms var(--ease-expo);
}

.tilt.is-tilting {
  transition: transform 120ms linear;
}

/* Odblask wędrujący po karcie za kursorem */
.tilt::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  background: radial-gradient(
    22rem circle at var(--gx, 50%) var(--gy, 50%),
    rgba(167, 139, 250, 0.16),
    transparent 62%
  );
  opacity: 0;
  transition: opacity 420ms var(--ease-out);
  pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
  .tilt:hover::before {
    opacity: 1;
  }
}

/* --- 17. Reflektor kursora ------------------------------------------------- */

.spotlight {
  position: relative;
  --sx: 50%;
  --sy: 50%;
}

.spotlight__grid {
  display: grid;
  gap: clamp(0.5rem, 1.4vw, 1rem) clamp(1rem, 3vw, 2.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
}

.spotlight__item {
  position: relative;
  padding-block: clamp(0.5rem, 1vw, 0.85rem);
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 2.2vw, 1.75rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.3;
  /* Warstwa bazowa jest CZYTELNA — reflektor tylko dokłada kolor.
     Nic nie jest ukryte przed osobą bez myszki. */
  color: var(--c-text-muted);
  border-bottom: 1px solid var(--c-border);
}

/* Warstwa gradientowa odsłaniana maską pod kursorem */
.spotlight__item::after {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  padding-block: inherit;
  background: var(--gradient-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  opacity: 0;
  transition: opacity 320ms var(--ease-out);
  pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
  .spotlight__grid:hover .spotlight__item::after {
    opacity: 1;
  }

  /* Krąg światła wokół kursora. Spadek jest CELOWO łagodny — tekst poza
     reflektorem musi zostać czytelny, efekt ma dokładać kolor, nie gasić
     resztę sekcji. */
  .spotlight__grid:hover {
    -webkit-mask-image: radial-gradient(
      20rem circle at var(--sx) var(--sy),
      #000 0%,
      rgba(0, 0, 0, 0.93) 45%,
      rgba(0, 0, 0, 0.82) 100%
    );
    mask-image: radial-gradient(
      20rem circle at var(--sx) var(--sy),
      #000 0%,
      rgba(0, 0, 0, 0.93) 45%,
      rgba(0, 0, 0, 0.82) 100%
    );
  }
}

/* --- 18. Odsłanianie maską (clip-path) ------------------------------------ */

@supports (animation-timeline: view()) {
  html.sda [data-sda="wipe"] {
    animation: sda-wipe linear both;
    animation-timeline: view();
    animation-range: entry 6% cover 32%;
  }
}

@keyframes sda-wipe {
  from {
    clip-path: inset(0 100% 0 0 round var(--r-card));
    opacity: 0.4;
  }
  to {
    clip-path: inset(0 0 0 0 round var(--r-card));
    opacity: 1;
  }
}

/* --- 19. Rozsypywanie znaków (scramble) ----------------------------------- */

.scramble {
  font-variant-numeric: tabular-nums;
}

.scramble[data-scrambling="true"] {
  color: var(--magenta-500);
}

/* --- 20. Menu mobilne jako przejęcie ekranu -------------------------------- */

.mobile-nav {
  counter-reset: mn;
  align-content: center;
}

.mobile-nav a:not(.btn) {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: clamp(0.5rem, 1.6vw, 0.9rem) 0.25rem;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 8vw, 3rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.mobile-nav a:not(.btn)::before {
  counter-increment: mn;
  content: "0" counter(mn);
  font-family: var(--font-ui);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--violet-300);
  opacity: 0.65;
}

.mobile-nav[data-open="true"] a,
.mobile-nav[data-open="true"] .mobile-nav__meta {
  animation: mn-in 620ms var(--ease-expo) both;
}

.mobile-nav[data-open="true"] a:nth-of-type(1) { animation-delay: 60ms; }
.mobile-nav[data-open="true"] a:nth-of-type(2) { animation-delay: 110ms; }
.mobile-nav[data-open="true"] a:nth-of-type(3) { animation-delay: 160ms; }
.mobile-nav[data-open="true"] a:nth-of-type(4) { animation-delay: 210ms; }
.mobile-nav[data-open="true"] a:nth-of-type(5) { animation-delay: 260ms; }
.mobile-nav[data-open="true"] a:nth-of-type(6) { animation-delay: 310ms; }
.mobile-nav[data-open="true"] a:nth-of-type(7) { animation-delay: 360ms; }
.mobile-nav[data-open="true"] a:nth-of-type(8) { animation-delay: 410ms; }
.mobile-nav[data-open="true"] .mobile-nav__meta { animation-delay: 470ms; }

@keyframes mn-in {
  from { opacity: 0; transform: translateY(26px); }
  to   { opacity: 1; transform: none; }
}

/* Tło menu — ta sama siatka gradientów co w hero */
.mobile-nav .mesh {
  inset: 0;
  opacity: 0.4;
}

.mobile-nav > *:not(.mesh) {
  position: relative;
  z-index: 2;
}

/* --- 21. Pasek przewijania ------------------------------------------------- */

@media (min-width: 1024px) {
  html {
    scrollbar-width: thin;
    scrollbar-color: var(--violet-600) rgba(124, 58, 237, 0.12);
  }

  ::-webkit-scrollbar {
    width: 10px;
  }

  ::-webkit-scrollbar-track {
    background-color: rgba(124, 58, 237, 0.1);
  }

  ::-webkit-scrollbar-thumb {
    background-image: linear-gradient(to bottom, var(--violet-600), var(--magenta-500));
    border: 2px solid transparent;
    border-radius: 0;
    background-clip: padding-box;
  }
}

/* --- 22. Linki w tekście ciągłym ------------------------------------------ */

.prose a,
.faq__answer a {
  position: relative;
  text-decoration: none;
  background-image: linear-gradient(var(--c-link), var(--c-link));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  transition: background-size 420ms var(--ease-expo);
}

@media (hover: hover) and (pointer: fine) {
  .prose a:hover,
  .faq__answer a:hover {
    background-size: 100% 2px;
  }
}

/* Nazwa marki jako osobny blok — rozsypuje się przy najechaniu na logo.
   Stała szerokość nie jest potrzebna, bo podmiana zachowuje liczbę znaków. */
.logo__name {
  display: block;
}

/* --- 23. Tekst zapalający się podczas czytania ---------------------------- */

/* Słowa rozjaśniają się w rytm przewijania — jak podświetlanie wiersza
   przy czytaniu. Na przeglądarkach bez scroll-timeline gra wariant
   kaskadowy wyzwalany obserwatorem (klasa .is-in). */
.readalong {
  color: var(--c-text-muted);
}

/* Stan „niezapalony” to PEŁNOPRAWNY kolor tekstu drugorzędnego, nie
   przygaszony duch. Gdyby animacja się nie wykonała, akapit i tak ma
   kontrast 7:1. Efekt polega na pogłębieniu koloru, nie na ukrywaniu. */
.ra__w {
  display: inline-block;
  color: var(--c-text-muted);
  transition: color 420ms var(--ease-out);
}

.readalong.is-in .ra__w {
  color: var(--c-heading);
  transition-delay: calc(var(--i, 0) * 26ms);
}

@supports (animation-timeline: view()) {
  html.sda .readalong .ra__w {
    color: var(--c-text-muted);
    animation: ra-light linear both;
    animation-timeline: view();
    /* Każde kolejne słowo zapala się nieco później w drodze przez kadr. */
    animation-range: entry calc(26% + var(--i) * 0.9%) entry calc(58% + var(--i) * 0.9%);
  }
}

@keyframes ra-light {
  to {
    color: var(--c-heading);
  }
}

/* --- 24. Rysowanie ścieżek SVG -------------------------------------------- */

.draw path,
.draw line,
.draw circle,
.draw rect {
  stroke-dasharray: var(--len, 400);
  stroke-dashoffset: var(--len, 400);
}

.draw.is-in path,
.draw.is-in line,
.draw.is-in circle,
.draw.is-in rect {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 700ms var(--ease-expo);
  transition-delay: calc(var(--i, 0) * 30ms);
}

/* --- 25. Obracający się obrys gradientowy --------------------------------- */

@property --ring-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

.ringlight {
  position: relative;
  isolation: isolate;
}

.ringlight::after {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  background: conic-gradient(
    from var(--ring-angle),
    transparent 0deg,
    var(--violet-500) 60deg,
    var(--magenta-500) 120deg,
    transparent 190deg,
    transparent 360deg
  );
  opacity: 0;
  transition: opacity 420ms var(--ease-out);
  pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
  .ringlight:hover::after,
  .ringlight:focus-within::after {
    opacity: 1;
    animation: ring-spin 3.6s linear infinite;
  }
}

@keyframes ring-spin {
  to { --ring-angle: 360deg; }
}

/* --- 26. Pierścień postępu + powrót na górę ------------------------------- */

.progress-ring {
  position: fixed;
  right: clamp(1rem, 2.5vw, 2rem);
  bottom: clamp(1rem, 2.5vw, 2rem);
  z-index: 120;
  display: none;
  place-items: center;
  width: 60px;
  height: 60px;
  color: var(--white);
  background-color: rgba(11, 16, 35, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 50%;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0;
  transform: scale(0.7);
  transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-back),
    background-color 300ms var(--ease-out);
}

.progress-ring[data-visible="true"] {
  opacity: 1;
  transform: none;
}

.progress-ring:hover {
  background-color: var(--violet-600);
}

.progress-ring svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

.progress-ring circle {
  fill: none;
  stroke-width: 2.5;
}

.progress-ring .pr-track {
  stroke: rgba(255, 255, 255, 0.14);
}

.progress-ring .pr-bar {
  stroke: url(#pr-grad);
  stroke-linecap: round;
  stroke-dasharray: var(--c, 176);
  stroke-dashoffset: calc(var(--c, 176) - var(--c, 176) * var(--p, 0));
}

@supports (animation-timeline: scroll()) {
  .progress-ring .pr-bar {
    stroke-dashoffset: var(--c, 176);
    animation: pr-fill linear both;
    animation-timeline: scroll(root block);
  }
  @keyframes pr-fill {
    to { stroke-dashoffset: 0; }
  }
}

.progress-ring__num {
  position: relative;
  z-index: 2;
  font-family: var(--font-ui);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}

.progress-ring__arrow {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  opacity: 0;
  transition: opacity 260ms var(--ease-out);
}

.progress-ring__arrow svg {
  position: static;
  width: 18px;
  height: 18px;
  transform: none;
}

@media (hover: hover) and (pointer: fine) {
  .progress-ring:hover .progress-ring__num { opacity: 0; }
  .progress-ring:hover .progress-ring__arrow { opacity: 1; }
}

@media (min-width: 1024px) {
  .progress-ring {
    display: grid;
  }
}

/* --- 28. Mockup, który sam się składa ------------------------------------- */

/* Pętla co 9 s: słupki odrastają, wiersze wpisują się od nowa. Ruch jest
   mały powierzchniowo, więc nie łamie zasady „bez ciągłego ruchu dużych
   płaszczyzn”. */
.mock__chart span {
  animation: bar-grow 900ms var(--ease-out) backwards, bar-loop 9s var(--ease-in-out) infinite;
}

@keyframes bar-loop {
  0%, 62%  { transform: scaleY(1); }
  70%      { transform: scaleY(0.25); }
  86%, 100% { transform: scaleY(1); }
}

.mock__rows i {
  transform-origin: left center;
  animation: row-type 9s var(--ease-in-out) infinite;
}

.mock__rows i:nth-child(1) { animation-delay: 0.2s; }
.mock__rows i:nth-child(2) { animation-delay: 0.4s; }
.mock__rows i:nth-child(3) { animation-delay: 0.6s; }

@keyframes row-type {
  0%, 58%   { transform: scaleX(1); }
  66%       { transform: scaleX(0.05); }
  82%, 100% { transform: scaleX(1); }
}

.mock__kpi b {
  animation: kpi-pulse 9s var(--ease-in-out) infinite;
}

@keyframes kpi-pulse {
  0%, 60%, 100% { opacity: 1; }
  68%           { opacity: 0.25; }
}

/* --- 29. Hasła w pasie reagują na kursor ---------------------------------- */

@media (hover: hover) and (pointer: fine) {
  .marquee__item {
    transition: color 320ms var(--ease-out), -webkit-text-stroke-color 320ms var(--ease-out);
  }

  .marquee__item:hover {
    color: transparent;
    background: var(--gradient-text);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-stroke-color: transparent;
  }
}

/* --- 14. Redukcja ruchu --------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .preloader {
    display: none !important;
  }

  .marquee__track {
    animation: none !important;
    transform: none !important;
  }

  .marquee {
    overflow-x: auto;
    transform: none !important;
  }

  .glow--breathe,
  .hstrip__hint i,
  .scroll-cue i::after,
  .eyebrow--live::after,
  .preloader__mark,
  .preloader__mark svg,
  .preloader__word span {
    animation: none !important;
  }

  .scroll-cue {
    display: none;
  }

  .split__w > i {
    transform: none !important;
    opacity: 1 !important;
  }

  .btn--ghost::before,
  .btn--primary::after {
    display: none;
  }

  .magnetic,
  .tilt {
    transform: none !important;
  }

  .mesh span {
    animation: none !important;
  }

  .mesh {
    opacity: 0.35;
  }

  .mobile-nav[data-open="true"] a,
  .mobile-nav[data-open="true"] .mobile-nav__meta {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  /* Reflektor znika, ale napisy zostają w pełni czytelne. */
  .spotlight__grid,
  .spotlight__grid:hover {
    -webkit-mask-image: none !important;
    mask-image: none !important;
  }

  .spotlight__item {
    color: var(--c-heading);
  }

  .spotlight__item::after {
    display: none;
  }

  .tilt::before,
  .ringlight::after {
    display: none;
  }

  /* Tekst „czytany” pokazujemy od razu w docelowym kolorze. */
  .ra__w,
  html.sda .readalong .ra__w {
    color: var(--c-heading) !important;
    animation: none !important;
    transition: none !important;
  }

  /* Ścieżki SVG narysowane do końca, bez kreślenia. */
  .draw path,
  .draw line,
  .draw circle,
  .draw rect {
    stroke-dashoffset: 0 !important;
    transition: none !important;
  }

  /* Mockup zastyga na gotowym widoku zamiast składać się w pętli. */
  .mock__chart span,
  .mock__rows i,
  .mock__kpi b {
    animation: none !important;
    transform: none !important;
    opacity: 1 !important;
  }

  .mock__chart span {
    transform: scaleY(1) !important;
  }

  .progress-ring {
    transition: none !important;
  }

  /* Scroll-driven: zostawiamy stan końcowy, kasujemy ruch */
  html.sda [data-sda] {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  html.sda .hero__copy,
  html.sda .hero__visual {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }

  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none !important;
  }
}

/* Mobile: uproszczony motion (spec, rozdz. 11) */
@media (max-width: 767.98px) {
  .split.is-in .split__w > i {
    transition-delay: calc(var(--i, 0) * 24ms);
    transition-duration: 620ms;
  }

  .glow--breathe {
    animation-duration: 14s;
  }

  .kinetic {
    -webkit-text-stroke-width: 0.5px;
  }
}
