/* ============================================================
   CARDS — wygląd poszczególnych kart
   Etap 1: tylko style zaślepek (tag + tytuł). Treść w kolejnych etapach.
   ============================================================ */

/* --- Zaślepki (tymczasowe, znikną wraz z budową kart) ------ */
.card__stub-tag {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.14em;
  color: var(--accent-eng);
  margin: 0 0 0.75rem;
}

.card__stub-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-hero);
  line-height: 0.95;
  letter-spacing: -0.01em;
  margin: 0;
  color: var(--text);
}

/* ============================================================
   KARTA 1 — HERO (Etap 2)
   ============================================================ */

.card--hero { background: var(--bg); }

.hero {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  align-items: center;
  gap: clamp(2rem, 5vw, 4.5rem);
}

/* --- Kolumna tekstowa ------------------------------------- */
.hero__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-eng);
  margin: 0 0 1rem;
}

.hero__title {
  font-family: var(--font-display);
  font-weight: 700;
  /* Węższy clamp niż globalny --fs-hero: przy szerokościach desktopowych
     (~1024–1440px) tytuł łamie się na frazy „Budujemy Twoje / pomysły",
     a linia akcentu „warstwa po warstwie" mieści się w jednej linii —
     zamiast łamania na pojedyncze słowa. Token --fs-hero zostaje bez zmian. */
  font-size: clamp(2.75rem, 4.4vw, 3.625rem);
  line-height: 0.98;
  letter-spacing: -0.02em;
  margin: 0 0 1.25rem;
  color: var(--text);
}
.hero__title-accent {
  background: linear-gradient(120deg, var(--accent-hot-2), var(--accent-hot));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero__lead {
  font-size: var(--fs-body);
  color: var(--text-dim);
  max-width: 46ch;
  margin: 0 0 2rem;
}

.hero__actions { display: flex; flex-wrap: wrap; gap: 0.9rem; }

/* Dyskretny link do bazy wiedzy pod przyciskami CTA — mniejsza waga wizualna
   (mały font, --text-dim); NIE konkuruje z btn--hot/btn--ghost powyżej. */
.hero__kb {
  margin: 1.1rem 0 0;
  font-size: var(--fs-small);
  color: var(--text-dim);
  line-height: 1.5;
}
.hero__kb a {
  color: inherit;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.18s ease;
}
.hero__kb a:hover,
.hero__kb a:focus-visible { color: var(--accent-hot); text-decoration: underline; text-underline-offset: 3px; }

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.01em;
  padding: 0.85rem 1.5rem;
  border-radius: 0.6rem;
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.18s var(--ease-out),
              background-color 0.25s ease,
              border-color 0.25s ease,
              box-shadow 0.25s ease,
              color 0.25s ease;
}
.btn:active { transform: translateY(1px); }

.btn--hot {
  background: linear-gradient(180deg, var(--accent-hot-2), var(--accent-hot));
  color: #1a0e05;
  box-shadow: 0 8px 22px rgba(255, 106, 43, 0.28);
}
.btn--hot:hover { box-shadow: 0 10px 28px rgba(255, 106, 43, 0.42); }

.btn--ghost { background: transparent; color: var(--text); border-color: var(--line); }
.btn--ghost:hover { border-color: var(--accent-eng); color: #fff; }

/* --- Kolumna wizualna: drukarka --------------------------- */
.hero__visual { display: flex; justify-content: center; }

.printer {
  --obj-h: clamp(210px, 32vh, 300px);
  --obj-w: clamp(150px, 22vw, 210px);
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: calc(var(--obj-h) + 72px);
  margin-inline: auto;
}
.printer::before {
  content: "";
  position: absolute;
  bottom: 34px;
  left: 50%;
  transform: translateX(-50%);
  width: calc(var(--obj-w) + 130px);
  height: calc(var(--obj-h) + 60px);
  background: radial-gradient(58% 58% at 50% 72%, rgba(61, 139, 255, 0.12), transparent 70%);
  z-index: 0;
}

.printer__object {
  position: relative;
  z-index: 1;
  width: var(--obj-w);
  height: var(--obj-h);
  display: flex;
  flex-direction: column-reverse;   /* pierwsza warstwa (i=0) na dole */
  align-items: center;
  gap: 2px;
}

.printer__layer {
  flex: 1 1 0;
  min-height: 2px;
  width: 60%;                        /* nadpisywane per-warstwa w JS */
  border-radius: 2px;
  background-color: #2e333b;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
}

.printer__plate {
  position: relative;
  z-index: 1;
  width: calc(var(--obj-w) + 48px);
  height: 14px;
  margin-top: 4px;
  border-radius: 3px;
  background: linear-gradient(180deg, #21252c, #14171b);
  border: 1px solid var(--line);
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.45);
}
.printer__plate::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: repeating-linear-gradient(90deg, transparent 0 11px, rgba(61, 139, 255, 0.12) 11px 12px);
}
.printer__plate::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: -1px;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent-eng), transparent);
  opacity: 0.5;
}

.printer__nozzle {
  position: absolute;
  left: 50%;
  bottom: 20px;
  width: 34px;
  height: 32px;
  z-index: 3;
  pointer-events: none;
  transform: translate(-50%, calc(-1 * var(--obj-h)));   /* stan spoczynkowy: przy szczycie */
}
.printer__nozzle::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  transform: translateX(-50%);
  width: 26px;
  height: 16px;
  background: linear-gradient(180deg, #4c525c, #2b2f36);
  border: 1px solid #565c66;
  border-radius: 3px 3px 0 0;
}
.printer__nozzle-tip {
  position: absolute;
  left: 50%;
  top: 15px;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 9px solid transparent;
  border-right: 9px solid transparent;
  border-top: 14px solid var(--accent-hot);
  animation: tip-glow 2.2s ease-in-out infinite;
}

/* --- Stany animacji (klasa is-building dodawana przez js/hero.js) --- */
.hero.is-building .printer__layer {
  animation-name: layer-place;
  animation-duration: var(--layer-dur, 520ms);
  animation-timing-function: var(--ease-out);
  animation-fill-mode: both;
  animation-delay: var(--d, 0ms);
}
.hero.is-building .printer__nozzle {
  animation: nozzle-rise var(--nozzle-dur, 1500ms) linear both;
}
.hero.is-building .hero__text > * {
  animation: rise-in 0.7s var(--ease-out) both;
}
.hero.is-building .hero__eyebrow { animation-delay: 0.05s; }
.hero.is-building .hero__title   { animation-delay: 0.14s; }
.hero.is-building .hero__lead    { animation-delay: 0.26s; }
.hero.is-building .hero__actions { animation-delay: 0.40s; }
.hero.is-building .hero__kb      { animation-delay: 0.50s; }

/* --- Responsywność --------------------------------------- */
@media (max-width: 820px) {
  .hero { grid-template-columns: 1fr; gap: clamp(2rem, 8vw, 3rem); }
  .printer { --obj-h: clamp(180px, 40vh, 260px); }
}

/* ============================================================
   KARTA 2 — PROBLEM / ROZWIĄZANIE (Etap 3): licznik czasu
   ============================================================ */

.timing {
  display: flex;
  flex-direction: column;
  gap: clamp(1.75rem, 4.5vh, 3.25rem);
}

/* --- Nagłówek --- */
.timing__head { max-width: 52rem; }
.timing__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-eng);
  margin: 0 0 0.9rem;
}
.timing__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h2);
  line-height: 1;
  letter-spacing: -0.02em;
  margin: 0 0 1rem;
  color: var(--text);
}
.timing__title-accent {
  background: linear-gradient(120deg, var(--accent-hot-2), var(--accent-hot));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.timing__lead {
  font-size: var(--fs-body);
  color: var(--text-dim);
  max-width: 54ch;
  margin: 0;
}

/* --- Porównanie --- */
.timing__compare {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
}

.tcard {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 1rem;
  padding: clamp(1.25rem, 3vw, 2rem);
}
.tcard--fast {
  background: linear-gradient(180deg, rgba(255, 106, 43, 0.06), transparent), var(--bg-deep);
  border-color: rgba(255, 106, 43, 0.35);
  box-shadow: 0 12px 44px rgba(255, 106, 43, 0.08);
}

.tcard__label {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0 0 0.85rem;
}
.tcard--fast .tcard__label { color: var(--accent-hot-2); }

.tcard__value {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  margin: 0;
  line-height: 1;
}
.tcard__num {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: clamp(2.5rem, 7vw, 4.25rem);
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
}
.tcard--fast .tcard__num { color: var(--accent-hot); }
.tcard__unit {
  font-family: var(--font-display);
  font-size: clamp(1rem, 2vw, 1.4rem);
  color: var(--text-faint);
}
.tcard--fast .tcard__unit { color: var(--text-dim); }

.tcard__bar {
  height: 6px;
  margin: 1.1rem 0 0.8rem;
  border-radius: 99px;
  background: var(--line-soft);
  overflow: hidden;
}
.tcard__bar span {
  display: block;
  height: 100%;
  width: var(--w);
  border-radius: inherit;
  background: linear-gradient(90deg, #3a4048, #4b535d);   /* wolno = szary */
}
.tcard--fast .tcard__bar span {
  background: linear-gradient(90deg, var(--accent-hot), var(--accent-hot-2));
}

.tcard__note {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--text-faint);
  margin: 0;
}

.timing__arrow {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2.5rem);
  color: var(--text-faint);
  justify-self: center;
}
/* Kierunek przez glif (nie transform) — transform jest zajęty przez rise-in. */
.timing__arrow::before { content: "→"; }

.timing__save {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 2.2vw, 1.6rem);
  color: var(--text);
  margin: 0;
}
.timing__save-num {
  font-family: var(--font-mono);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--accent-hot);
}

/* --- Wejście + wzrost pasków (klasa is-counting z js/timing.js) --- */
.timing.is-counting .timing__head > *,
.timing.is-counting .tcard,
.timing.is-counting .timing__arrow,
.timing.is-counting .timing__save {
  animation: rise-in 0.7s var(--ease-out) both;
}
.timing.is-counting .timing__head > *:nth-child(2) { animation-delay: 0.08s; }
.timing.is-counting .timing__head > *:nth-child(3) { animation-delay: 0.16s; }
.timing.is-counting .tcard--slow  { animation-delay: 0.22s; }
.timing.is-counting .timing__arrow { animation-delay: 0.30s; }
.timing.is-counting .tcard--fast  { animation-delay: 0.36s; }
.timing.is-counting .timing__save { animation-delay: 0.52s; }
.timing.is-counting .tcard__bar span { animation: bar-grow 1s var(--ease-out) 0.3s both; }

/* --- Responsywność --- */
@media (max-width: 720px) {
  .timing__compare { grid-template-columns: 1fr; }
  .timing__arrow::before { content: "↓"; }
}

/* ============================================================
   KARTA 3 — MATERIAŁY (Etap 4): przełącznik materiału
   Akcenty --mat / --mat-soft są LOKALNE dla karty (ustawia je
   js/materials.js). To nie są globalne tokeny.
   ============================================================ */

.materials {
  --mat: var(--accent-hot);
  --mat-soft: rgba(255, 106, 43, 0.14);
  display: flex;
  flex-direction: column;
  gap: clamp(1.5rem, 4vh, 2.75rem);
}

.materials__head { max-width: 52rem; }
.materials__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-eng);
  margin: 0 0 0.9rem;
}
.materials__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h2);
  line-height: 1;
  letter-spacing: -0.02em;
  margin: 0 0 1rem;
  color: var(--text);
}
.materials__title-accent {
  background: linear-gradient(120deg, var(--accent-hot-2), var(--accent-hot));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.materials__lead {
  font-size: var(--fs-body);
  color: var(--text-dim);
  max-width: 56ch;
  margin: 0;
}

/* --- Zakładki (segmented control) --- */
.materials__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  width: fit-content;
  max-width: 100%;
  padding: 0.4rem;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 0.85rem;
}
.mat__tab {
  flex: 0 1 auto;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 0.6rem;
  padding: 0.6rem 1.2rem;
  cursor: pointer;
  transition: color 0.2s ease, background-color 0.25s ease, border-color 0.25s ease;
}
.mat__tab:hover { color: var(--text); }
.mat__tab[aria-selected="true"] {
  color: var(--mat);
  background: var(--mat-soft);
  border-color: var(--mat);
}

/* --- Panel materiału --- */
.materials__panel {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
}
.materials__panel:focus-visible {
  outline: 2px solid var(--accent-eng);
  outline-offset: 6px;
  border-radius: 0.5rem;
}

.mat__namerow {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.75rem;
}
.mat__name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.75rem, 3.5vw, 2.5rem);
  line-height: 1;
  margin: 0;
  color: var(--mat);
  transition: color 0.35s ease;
}
.mat__tag {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.08em;
  color: var(--text-dim);
}
.mat__desc {
  font-size: var(--fs-body);
  color: var(--text-dim);
  max-width: 46ch;
  margin: 0 0 1.25rem;
}

.mat__uses { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.mat__use {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--text-dim);
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--line);
  border-left: 2px solid var(--mat);
  border-radius: 0.4rem;
  background: var(--bg-elev);
  transition: border-color 0.35s ease;
}

.mat__specs {
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 1rem;
  padding: clamp(1.25rem, 3vw, 1.75rem);
}
.mat__props {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.mat__prop { display: grid; gap: 0.4rem; }
.mat__prop-label {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.mat__bar {
  display: block;
  height: 8px;
  border-radius: 99px;
  background: var(--line-soft);
  overflow: hidden;
}
.mat__bar > span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background-color: var(--mat);
  transition: width 0.55s var(--ease-out), background-color 0.4s ease;
}
.mat__temp {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin: 0;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
}
.mat__temp-label {
  font-size: var(--fs-small);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.mat__temp-val { font-size: var(--fs-body); color: var(--text); }

/* --- Wejście karty (is-shown, tylko poza reduced-motion) --- */
.materials.is-shown .materials__head > *,
.materials.is-shown .materials__tabs,
.materials.is-shown .materials__panel {
  animation: rise-in 0.7s var(--ease-out) both;
}
.materials.is-shown .materials__head > *:nth-child(2) { animation-delay: 0.07s; }
.materials.is-shown .materials__head > *:nth-child(3) { animation-delay: 0.14s; }
.materials.is-shown .materials__tabs  { animation-delay: 0.20s; }
.materials.is-shown .materials__panel { animation-delay: 0.28s; }

/* --- Zmiana materiału: delikatny fade treści (is-swapping) --- */
.materials__panel.is-swapping .mat__info { animation: fade-swap 0.35s var(--ease-out); }

/* --- Responsywność --- */
@media (max-width: 720px) {
  .materials__panel { grid-template-columns: 1fr; }
  .materials__tabs { width: 100%; }
  .mat__tab { flex: 1 1 0; padding: 0.55rem 0.5rem; font-size: 0.9rem; }
}

/* ============================================================
   KARTA 4 — PROCES (Etap 5): wariant krokowy, linia sterowana scrollem
   Karta jest WYŻSZA niż ekran: 4 kroki po 100dvh, każdy z własnym
   snap-pointem. Lewa kolumna (wizualizacja) jest przyklejona (sticky),
   prawa przewija się przez kroki. Postęp liczy js/process.js (--progress).
   ============================================================ */

.card.process {
  display: grid;
  grid-template-columns: minmax(0, 20rem) 1fr;
  gap: clamp(1.5rem, 5vw, 5rem);
  place-items: stretch;
  align-content: start;
  padding: 0 var(--pad-card);
  overflow: visible;
  scroll-snap-align: none;   /* snap zapewniają kroki, nie cała karta */
}

/* --- Wizualizacja (sticky) --- */
.process__viz {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(1.5rem, 3vh, 2.5rem);
  padding-block: var(--pad-card);
}
.process__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-eng);
  margin: 0;
}
.process__heading {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--text);
  margin: 0;
}

/* --- Szyna postępu z węzłami --- */
.process__rail { position: relative; height: min(56vh, 22rem); }
.process__track {
  position: absolute;
  left: 6px;
  top: 12.5%;
  bottom: 12.5%;
  width: 2px;
  background: var(--line);
  border-radius: 2px;
  overflow: hidden;
}
.process__fill {
  position: absolute;
  inset: 0;
  transform-origin: top;
  transform: scaleY(var(--progress, 0));   /* bez calc — niezawodne z niezarejestrowanym --progress */
  background: linear-gradient(180deg, var(--accent-hot-2), var(--accent-hot));
  transition: transform 0.12s linear;
}
.process__nodes {
  position: relative;
  z-index: 1;
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
}
.process__node {
  flex: 1;
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding-left: 32px;
}
.process__node::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--bg-elev);
  border: 2px solid var(--line);
  transition: background-color 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}
.process__node.is-done::before,
.process__node.is-active::before {
  background: var(--accent-hot);
  border-color: var(--accent-hot);
}
.process__node.is-active::before { box-shadow: 0 0 0 5px rgba(255, 106, 43, 0.18); }
.process__node-num {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--text-faint);
  transition: color 0.35s ease;
}
.process__node-label {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--text-dim);
  transition: color 0.35s ease;
}
.process__node.is-active .process__node-num,
.process__node.is-done .process__node-num { color: var(--accent-hot); }
.process__node.is-active .process__node-label { color: var(--text); }

/* --- Kroki (przewijane, snap) --- */
.process__steps { list-style: none; margin: 0; padding: 0; }
.process__step {
  min-height: 100dvh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.process__step-inner {
  max-width: 44ch;
  transition: opacity 0.4s ease, transform 0.4s var(--ease-out);
}
.process.is-enhanced .process__step:not(.is-active) .process__step-inner { opacity: 0.28; }
.process.is-enhanced .process__step.is-active .process__step-inner { opacity: 1; }
.process__step-kicker {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-hot);
  margin: 0 0 1rem;
}
.process__step-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h2);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0 0 1rem;
}
.process__step-desc {
  font-size: var(--fs-body);
  color: var(--text-dim);
  margin: 0;
}

/* --- Mobile: sticky pasek postępu zamiast pionowej szyny --- */
@media (max-width: 899px) {
  .card.process { grid-template-columns: 1fr; gap: 0; padding: 0; }
  .process__viz {
    position: sticky;
    top: 0;
    height: auto;
    padding: 0;
    z-index: 5;
    display: block;
  }
  .process__eyebrow,
  .process__heading,
  .process__nodes { display: none; }
  .process__rail { height: auto; }
  .process__track {
    position: relative;
    left: 0;
    top: 0;
    bottom: auto;
    width: 100%;
    height: 3px;
    border-radius: 0;
  }
  .process__fill { transform-origin: left; transform: scaleX(var(--progress, 0)); }
  .process__step { padding: 0 var(--pad-card); }
}

/* ============================================================
   KARTA 5 — REALIZACJE (Etap 6): siatka bento
   Kolory kafli (--acc, rgb) są LOKALNE — kodują branżę, nie są tokenami.
   ============================================================ */

.gallery {
  display: flex;
  flex-direction: column;
  gap: clamp(1.25rem, 3vh, 2rem);
  width: 100%;
}
.gallery__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-eng);
  margin: 0 0 0.6rem;
}
.gallery__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h2);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0;
}
.gallery__title-accent {
  background: linear-gradient(120deg, var(--accent-hot-2), var(--accent-hot));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.bento {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-template-rows: repeat(2, 1fr);
  grid-template-areas:
    "a a a b b b"
    "a a a c d e";
  gap: clamp(0.6rem, 1.2vw, 1rem);
  height: min(64vh, 600px);
}
/* Zdjęcia realizacji (placeholdery AI — patrz CLAUDE.md). Pierwsza deklaracja
   (plain JPG) = fallback dla przeglądarek bez image-set; druga (image-set)
   wybiera WebP tam, gdzie jest wspierany, inaczej JPG. */
.bento__item--a {
  grid-area: a;
  background-image: url("../assets/obudowa-iot.jpg");
  background-image: image-set(url("../assets/obudowa-iot.webp") type("image/webp"), url("../assets/obudowa-iot.jpg") type("image/jpeg"));
}
.bento__item--b {
  grid-area: b;
  background-image: url("../assets/osprzet-produkcyjny.jpg");
  background-image: image-set(url("../assets/osprzet-produkcyjny.webp") type("image/webp"), url("../assets/osprzet-produkcyjny.jpg") type("image/jpeg"));
}
.bento__item--c {
  grid-area: c;
  background-image: url("../assets/element-auto.jpg");
  background-image: image-set(url("../assets/element-auto.webp") type("image/webp"), url("../assets/element-auto.jpg") type("image/jpeg"));
}
.bento__item--d {
  grid-area: d;
  background-image: url("../assets/makieta-konkursowa.jpg");
  background-image: image-set(url("../assets/makieta-konkursowa.webp") type("image/webp"), url("../assets/makieta-konkursowa.jpg") type("image/jpeg"));
}
.bento__item--e {
  grid-area: e;
  background-image: url("../assets/model-anatomiczny.jpg");
  background-image: image-set(url("../assets/model-anatomiczny.webp") type("image/webp"), url("../assets/model-anatomiczny.jpg") type("image/jpeg"));
}

.bento__item {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  min-height: 0;
  border-radius: 0.9rem;
  border: 1px solid var(--line);
  padding: clamp(0.85rem, 1.5vw, 1.25rem);
  /* Zdjęcie realizacji ustawia każdy kafel z osobna (background-image: image-set
     WebP+JPG). Tu tylko: ciemny fallback (gdy zdjęcie się nie wczyta) + cover. */
  background-color: var(--bg-deep);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  transition: transform 0.3s var(--ease-out), border-color 0.3s ease, box-shadow 0.3s ease;
}
.bento__item::before {          /* linie warstw — motyw druku 3D */
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(0deg, transparent 0 6px, rgba(255, 255, 255, 0.035) 6px 7px);
  pointer-events: none;
}
.bento__item::after {           /* scrim pod tekst */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 45%, rgba(0, 0, 0, 0.5));
  pointer-events: none;
}
.bento__item:hover {
  transform: translateY(-4px);
  border-color: rgba(var(--acc), 0.55);
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.4);
}

.bento__caption { position: relative; z-index: 1; }
.bento__tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgb(var(--acc));
  margin-bottom: 0.4rem;
}
.bento__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1rem, 1.6vw, 1.35rem);
  line-height: 1.1;
  color: var(--text);
  margin: 0;
  overflow-wrap: break-word;   /* długie słowa łamią się zamiast wychodzić poza kafel */
  hyphens: auto;               /* dzielenie wyrazów (siatka ma lang="pl") */
}
.bento__item--a .bento__title { font-size: clamp(1.3rem, 2.4vw, 2rem); }
/* Najwęższe kafle (dolne trójki) — mniejszy tytuł, by dłuższe nazwy się mieściły. */
.bento__item--c .bento__title,
.bento__item--d .bento__title,
.bento__item--e .bento__title { font-size: clamp(0.95rem, 1.25vw, 1.1rem); }

/* --- Wejście (is-shown, tylko poza reduced-motion) --- */
.gallery.is-shown .gallery__head > *,
.gallery.is-shown .bento__item {
  animation: rise-in 0.6s var(--ease-out) both;
}
.gallery.is-shown .bento__item--a { animation-delay: 0.06s; }
.gallery.is-shown .bento__item--b { animation-delay: 0.13s; }
.gallery.is-shown .bento__item--c { animation-delay: 0.20s; }
.gallery.is-shown .bento__item--d { animation-delay: 0.27s; }
.gallery.is-shown .bento__item--e { animation-delay: 0.34s; }

/* --- Responsywność --- */
/* 2 kolumny już od 1024px — poniżej tego 6 kolumn robi za wąskie małe kafle. */
@media (max-width: 1024px) {
  .bento {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1.3fr 1fr 1fr;
    grid-template-areas:
      "a a"
      "b c"
      "d e";
    height: min(72vh, 560px);
  }
  /* W układzie 2-kolumnowym kafle są szerokie — przywróć większy tytuł. */
  .bento__item--c .bento__title,
  .bento__item--d .bento__title,
  .bento__item--e .bento__title { font-size: clamp(1rem, 1.6vw, 1.35rem); }
}
@media (max-width: 560px) {
  .bento { gap: 0.6rem; }
  .bento__item { padding: 0.8rem; }
}

/* ============================================================
   KARTA 6 — LICZBY (Etap 7): liczniki count-up
   ============================================================ */

.stats {
  display: flex;
  flex-direction: column;
  gap: clamp(2rem, 5vh, 3.5rem);
  width: 100%;
}
.stats__head { max-width: 48rem; }
.stats__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-eng);
  margin: 0 0 0.9rem;
}
.stats__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h2);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0 0 1rem;
}
.stats__title-accent {
  background: linear-gradient(120deg, var(--accent-hot-2), var(--accent-hot));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.stats__lead {
  font-size: var(--fs-body);
  color: var(--text-dim);
  max-width: 52ch;
  margin: 0;
}

.stats__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1.5rem, 3vw, 3rem);
}
.stat {
  position: relative;
  padding-top: 1.1rem;
  border-top: 2px solid var(--line);
}
.stat::before {              /* akcentowy odcinek na górnej linii */
  content: "";
  position: absolute;
  top: -2px;
  left: 0;
  width: 2.75rem;
  height: 2px;
  background: var(--accent-hot);
}
.stat:nth-child(even)::before { background: var(--accent-eng); }
.stat__num {
  display: flex;
  align-items: baseline;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: clamp(2rem, 5.5vw, 4rem);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  margin: 0 0 0.7rem;
}
.stat__suffix { color: var(--accent-hot); margin-left: 0.08em; }
.stat:nth-child(even) .stat__suffix { color: var(--accent-eng); }
.stat__label {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0;
}

/* --- Wejście + start zliczania (klasa is-counting z js/counters.js) --- */
.stats.is-counting .stats__head > *,
.stats.is-counting .stat {
  animation: rise-in 0.6s var(--ease-out) both;
}
.stats.is-counting .stats__head > *:nth-child(2) { animation-delay: 0.06s; }
.stats.is-counting .stats__head > *:nth-child(3) { animation-delay: 0.12s; }
.stats.is-counting .stat:nth-child(1) { animation-delay: 0.18s; }
.stats.is-counting .stat:nth-child(2) { animation-delay: 0.25s; }
.stats.is-counting .stat:nth-child(3) { animation-delay: 0.32s; }
.stats.is-counting .stat:nth-child(4) { animation-delay: 0.39s; }

/* --- Responsywność --- */
@media (max-width: 860px) {
  .stats__grid { grid-template-columns: repeat(2, 1fr); gap: clamp(1.5rem, 4vw, 2.5rem); }
}

/* ============================================================
   KARTA 7 — WYCENA (Etap 8): formularz + upload STL
   ============================================================ */

.quote {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}

/* --- Lewa kolumna: zachęta --- */
.quote__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-eng);
  margin: 0 0 0.9rem;
}
.quote__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h2);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0 0 1rem;
}
.quote__title-accent {
  background: linear-gradient(120deg, var(--accent-hot-2), var(--accent-hot));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.quote__lead {
  font-size: var(--fs-body);
  color: var(--text-dim);
  max-width: 40ch;
  margin: 0;
}
.quote__points {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}
.quote__points li {
  position: relative;
  padding-left: 1.6rem;
  font-size: var(--fs-body);
  color: var(--text-dim);
}
.quote__points li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--accent-hot);
  font-weight: 700;
}

/* --- Prawa kolumna: formularz --- */
.quote__form { display: flex; flex-direction: column; gap: 0.9rem; }
.quote__row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.9rem; }

.field { display: flex; flex-direction: column; gap: 0.35rem; }
.field label,
.field__label {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 0.04em;
  color: var(--text-dim);
}
.field input,
.field select,
.field textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--text);
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  padding: 0.7rem 0.85rem;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.field textarea { resize: vertical; min-height: 3rem; }
.field input::placeholder,
.field textarea::placeholder { color: var(--text-faint); }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent-eng);
  box-shadow: 0 0 0 3px rgba(61, 139, 255, 0.15);
}

/* --- Dropzone (upload STL) --- */
.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  text-align: center;
  cursor: pointer;
  padding: 1.1rem;
  border: 1.5px dashed var(--line);
  border-radius: 0.6rem;
  background: var(--bg-elev);
  color: var(--text-dim);
  transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}
.dropzone:hover { border-color: var(--accent-eng); color: var(--text); }
.dropzone.is-drag { border-color: var(--accent-hot); background: rgba(255, 106, 43, 0.06); color: var(--text); }
.dropzone.has-file { border-style: solid; border-color: var(--accent-eng); color: var(--text); }
.dropzone.is-invalid { border-color: #e5533d; color: #ef8a76; }
.dropzone__text { font-family: var(--font-body); font-size: 0.9rem; word-break: break-word; }
.dropzone__hint { font-family: var(--font-mono); font-size: var(--fs-small); color: var(--text-faint); }

/* Dyskretna podpowiedź „gotowe bazy modeli" pod dropzone (tylko stan pusty).
   Mniejsza waga wizualna niż CTA: mały font, przygaszony kolor. */
.quote__nomodel {
  margin: 0.1rem 0 -0.15rem;
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--text-faint);
}
.quote__nomodel[hidden] { display: none; }
.quote__nomodel a {
  color: var(--text-dim);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color 0.15s ease;
}
.quote__nomodel a:hover,
.quote__nomodel a:focus-visible { color: var(--accent-hot); }

.quote__submit { width: 100%; justify-content: center; margin-top: 0.25rem; }

/* --- Stopka strony głównej (wpięta na dole karty 7) --- */
.site-footer {
  grid-column: 1 / -1;            /* pełna szerokość pod kolumnami .quote (i 1 kol. na mobile) */
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem 1.25rem;
  margin-top: clamp(1.5rem, 4vh, 2.5rem);
  padding: 1rem 0 clamp(1rem, 3vh, 2rem);
  border-top: 1px solid var(--line-soft);
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--text-faint);
}
.site-footer__copy { color: var(--text-faint); }
.site-footer__link { color: var(--text-dim); text-decoration: none; transition: color 0.18s ease; }
.site-footer__link:hover,
.site-footer__link:focus-visible { color: var(--accent-hot); text-decoration: underline; text-underline-offset: 2px; }

/* --- Stan „wysłano" --- */
.quote__success {
  display: none;
  text-align: center;
  padding: 2.25rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 0.8rem;
  background: var(--bg-elev);
}
.quote__formwrap.is-sent .quote__form { display: none; }
.quote__formwrap.is-sent .quote__success { display: block; }
.quote__success-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.5rem;
  color: var(--accent-hot);
  margin: 0 0 0.4rem;
}
.quote__success-text { color: var(--text-dim); margin: 0; }

/* --- Wejście (is-shown, poza reduced-motion) --- */
.quote.is-shown .quote__intro > *,
.quote.is-shown .quote__formwrap {
  animation: rise-in 0.6s var(--ease-out) both;
}
.quote.is-shown .quote__intro > *:nth-child(2) { animation-delay: 0.06s; }
.quote.is-shown .quote__intro > *:nth-child(3) { animation-delay: 0.12s; }
.quote.is-shown .quote__intro > *:nth-child(4) { animation-delay: 0.18s; }
.quote.is-shown .quote__formwrap { animation-delay: 0.14s; }

/* --- Responsywność --- */
@media (max-width: 820px) {
  .quote { grid-template-columns: 1fr; gap: clamp(1.25rem, 4vw, 2rem); align-items: start; }
  .quote__points { display: none; }
  .quote__form { gap: 0.75rem; }
  .dropzone { padding: 0.9rem; }
  /* Imię + e-mail zostają obok siebie także na mobile — oszczędza wysokość,
     żeby przycisk „Wyślij" mieścił się na krótkich telefonach (~667px). */
}

/* --- Wzrost karty po wgraniu pliku ---
   Świadome odstępstwo od reguły „1 karta = 1 ekran", ten sam wzorzec co karta
   „Proces": LEWA kolumna (intro: tekst + podgląd 3D) jest sticky, PRAWA
   (formularz + suwaki + panel ceny) się przewija. Wzrost STEROWANY TREŚCIĄ:
   kolumny mają min-height 100dvh, więc pusty stan = dokładnie 1 ekran; dopiero
   panel ceny podnosi prawą kolumnę ponad 100dvh i karta rośnie. Karta wyższa
   niż ekran = „oversized snap area" → mandatory-snap pozwala swobodnie przewijać. */
#card-7 { overflow: visible; }           /* sticky wymaga braku clipu (jak .card.process) */

@media (min-width: 821px) {
  #card-7 { padding-block: 0; align-items: start; }   /* wysokość dyktują kolumny, nie centrowanie karty */
  .quote { align-items: start; }
  .quote__intro,
  .quote__formwrap {
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-block: var(--pad-card);
  }
  .quote__intro { position: sticky; top: 0; }
  /* Stały, umiarkowany odstęp między punktami korzyści a viewerem (wyraźnie więcej
     niż bazowe 0.9rem, ale bez rozciągania na całą wolną przestrzeń). Grupa
     tekst+viewer pozostaje wyśrodkowana w kolumnie przez justify-content: center. */
  .quote__intro .viewer3d { margin-top: 2.5rem; }
}

/* --- Panel ceny orientacyjnej (kalkulator STL, Etap D) --- */
.quote__estimate {
  padding: 0.9rem 1rem;
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  background: var(--bg-elev);
}
.quote__estimate[hidden] { display: none; }
.quote__estimate--msg.is-error { border-color: rgba(229, 83, 61, 0.4); }
.quote__estimate--msg.is-warn  { border-color: rgba(255, 106, 43, 0.4); }
.estimate__msg { margin: 0; font-size: 0.92rem; color: var(--text); }

.estimate__top { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; flex-wrap: wrap; }
.estimate__label {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.estimate__price {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.5rem, 4vw, 2.1rem);
  line-height: 1;
  color: var(--accent-hot);
}
.estimate__net { font-size: 0.55em; color: var(--text-dim); font-weight: 600; }
.estimate__disclaimer { margin: 0.5rem 0 0; font-size: var(--fs-small); color: var(--text-dim); }
.estimate__meta {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0.7rem 0 0;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.1rem;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--text-dim);
}
.estimate__meta li { margin: 0; }
.estimate__note {
  margin: 0.6rem 0 0;
  padding: 0.5rem 0.65rem;
  border-radius: 0.4rem;
  font-size: var(--fs-small);
  color: var(--text);
}
.estimate__note--info { background: rgba(61, 139, 255, 0.09); border: 1px solid rgba(61, 139, 255, 0.28); }
.estimate__note--warn { background: rgba(255, 106, 43, 0.09); border: 1px solid rgba(255, 106, 43, 0.32); }

/* --- Suwaki jakości / wytrzymałości (Etap 2 kalkulatora) --- */
.psliders { display: flex; flex-direction: column; gap: 1.1rem; }
.pslider__head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.4rem; }
.pslider__title {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 0.04em;
  color: var(--text-dim);
}
.pslider__value { font-family: var(--font-display); }
.pslider__name { color: var(--text); font-weight: 600; font-size: 0.98rem; }
.pslider__tech { font-family: var(--font-mono); font-size: var(--fs-small); color: var(--text-faint); }

.pslider__range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 6px;
  border-radius: 99px;
  /* Fallback zanim JS ustawi tło. js/quote.js wpisuje na .style.background
     dwuwarstwowy gradient: notche pozycji (repeating) NAD wypełnieniem 0→kciuk. */
  background: var(--line);
  cursor: pointer;
  /* Brak osobnego rzędu kropek → minimalne marginesy (odzysk wysokości na mobile). */
  margin: 0.15rem 0 0.15rem;
}
/* Firefox: odsłoń tło elementu (notche+wypełnienie z JS) zamiast natywnego toru. */
.pslider__range::-moz-range-track { background: transparent; border: none; height: 6px; border-radius: 99px; }
.pslider__range::-moz-range-progress { background: transparent; }
.pslider__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--accent-hot);
  border: 2px solid var(--bg);
  box-shadow: 0 0 0 1px var(--accent-hot);
  cursor: pointer;
}
.pslider__range::-moz-range-thumb {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--accent-hot);
  border: 2px solid var(--bg);
  box-shadow: 0 0 0 1px var(--accent-hot);
  cursor: pointer;
}
/* Focus suwaka: zamiast globalnego niebieskiego prostokąta (:focus-visible w
   layout.css rysuje outline w kolorze --accent-eng) dajemy pomarańczowy
   pierścień NA KCIUKU — spójny z akcentem suwaka, wymuszony także po powrocie
   na kartę (utrzymuje się póki suwak ma :focus-visible; card:enter go nie zmienia). */
.pslider__range:focus-visible { outline: none; }
.pslider__range:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 1px var(--accent-hot), 0 0 0 5px rgba(255, 106, 43, 0.35);
}
.pslider__range:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 1px var(--accent-hot), 0 0 0 5px rgba(255, 106, 43, 0.35);
}


/* --- Podgląd 3D modelu STL (Etap 3 kalkulatora) --- */
.viewer3d {
  margin-top: 0.9rem;
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  background: var(--bg-deep);
  overflow: hidden;
}
.viewer3d[hidden] { display: none; }
.viewer3d__canvas {
  position: relative;
  width: 100%;
  /* Mniejszy niż wcześniej — viewer żyje teraz w lewej (sticky) kolumnie obok
     tekstu i całość musi zmieścić się w 100dvh. Skaluje się z wysokością okna;
     próg 160px dobrany tak, by tekst + 2.5rem odstęp + viewer mieściły się w
     lewej kolumnie także na 1280×720 (najniższy testowany laptop). */
  height: clamp(160px, 22vh, 240px);
  touch-action: none;                 /* przeciąganie obraca, nie przewija strony */
}
.viewer3d__gl {
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
}
.viewer3d__gl.is-grabbing { cursor: grabbing; }
.viewer3d__status {
  position: absolute;
  inset: 0;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--text-dim);
  pointer-events: none;
  text-align: center;
  padding: 0 1rem;
}
.viewer3d__status[hidden] { display: none; }
.viewer3d__hint {
  margin: 0;
  padding: 0.45rem 0.6rem;
  text-align: center;
  border-top: 1px solid var(--line-soft);
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--text-faint);
}
