/* Karatvue landing v3 — full screen, the jewels float free of any frame, every move follows the
   scroll. Loaded after styles.css. landing.ts only writes numbers as CSS variables: --in, --out
   and --c on [data-sa] blocks, --t, --w and --r on each frame and caption of a sequence, --p,
   --e, --l and --h on its stage, --v on the glints. How things move is decided here. */

:root {
  --screen: 100vh;
  --nav-h: 4.5rem;
  /* the rail on the right edge: the boards' words stay left of it */
  --rail-w: 2.4rem;
  /* the scroll over which one board surfaces while the last one sinks: the boards overlap by it */
  --fade: calc(var(--screen) * 0.5);
}

@supports (height: 100svh) {
  :root {
    --screen: 100svh;
  }
}

/* the page grows with a big screen: 16 px up to about 1600 px, then with the smaller of the width
   and the height (4K: about 27 px), so the menu, the type, the chips and the strips keep their
   proportions instead of shrinking into the middle */
html {
  font-size: clamp(16px, min(0.52vw + 7.2px, 0.9vh + 7.2px), 28px);
}

.landing .wrap {
  width: min(100% - 2 * var(--gutter), 96rem);
}

/* ---------- the corners: no bar — the dock in the top-left corner, the mark alone in the
   top-right. Under the pointer the name unfolds from the mark to its left („Karat” white, VUE
   gold); a click unfolds the menu down below it. --nav-h stays the room the boards leave at
   the top. */
.landing .nav {
  position: fixed;
  inset: max(0.9rem, env(safe-area-inset-top)) max(var(--gutter), env(safe-area-inset-right)) auto
    max(var(--gutter), env(safe-area-inset-left));
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  height: auto;
  padding: 0;
  border: 0;
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.landing .brand {
  display: inline-flex;
  align-items: center;
  margin-left: auto;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 1.3rem;
  letter-spacing: 0.02em;
  cursor: pointer;
}

.landing .brand svg {
  flex: none;
  width: 2.35rem;
  height: 2.35rem;
  filter: drop-shadow(0 0 10px rgba(247, 223, 158, 0.16));
  transition: filter 0.6s ease;
}

.landing .brand:hover svg,
.landing .brand:focus-visible svg,
.landing .brand[aria-expanded="true"] svg {
  filter: drop-shadow(0 0 14px rgba(247, 223, 158, 0.45));
}

.landing .brand:focus-visible {
  outline: none;
}

/* the name: folded into the mark, unfolding to its left under the pointer or with the menu */
.brand-name {
  display: inline-block;
  max-width: 0;
  margin-right: 0;
  padding: 0.3em 0.05em 0 0;
  opacity: 0;
  overflow: hidden;
  white-space: nowrap;
  transition:
    max-width 0.7s var(--ease),
    margin-right 0.7s var(--ease),
    opacity 0.45s ease;
}

.landing .brand:hover .brand-name,
.landing .brand:focus-visible .brand-name,
.landing .brand[aria-expanded="true"] .brand-name {
  max-width: 14rem;
  margin-right: 0.55rem;
  opacity: 1;
}

/* the menu: a glass panel unfolding down from under the mark, its lines arriving one after
   another, set to the right like the mark */
.landing .nav .nav-links {
  position: absolute;
  right: 0;
  top: calc(100% + 0.9rem);
  display: grid;
  gap: 0;
  min-width: 17rem;
  margin: 0;
  padding: 0.5rem 0;
  border: 1px solid rgba(220, 184, 103, 0.32);
  border-radius: 18px;
  background: rgba(8, 7, 6, 0.74);
  backdrop-filter: blur(22px) saturate(140%);
  -webkit-backdrop-filter: blur(22px) saturate(140%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 30px 80px -30px rgba(0, 0, 0, 0.85);
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, -6px, 0);
  clip-path: inset(0 0 100% 0 round 18px);
  transition:
    opacity 0.4s ease,
    transform 0.6s var(--ease),
    clip-path 0.6s var(--ease),
    visibility 0s linear 0.6s;
}

.landing .nav .nav-links.open {
  opacity: 1;
  visibility: visible;
  transform: none;
  clip-path: inset(0 0 0 0 round 18px);
  transition:
    opacity 0.3s ease,
    transform 0.7s var(--ease),
    clip-path 0.7s var(--ease),
    visibility 0s;
}

.landing .nav .nav-links a {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.7rem;
  padding: 0.72rem 1.35rem;
  border-top: 1px solid rgba(243, 236, 223, 0.07);
  color: var(--ink-soft);
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-decoration: none;
  transition: color 0.35s ease;
}

.landing .nav .nav-links a:first-child {
  border-top: 0;
}

/* a gold dash grows after the line under the pointer */
.landing .nav .nav-links a:not(.btn)::after {
  content: "";
  width: 0;
  height: 1px;
  background: var(--gold-2);
  transition: width 0.45s var(--ease);
}

.landing .nav .nav-links a:not(.btn):hover,
.landing .nav .nav-links a:not(.btn):focus-visible {
  color: var(--gold-1);
  outline: none;
}

.landing .nav .nav-links a:not(.btn):hover::after,
.landing .nav .nav-links a:not(.btn):focus-visible::after {
  width: 1.1rem;
}

.landing .nav .nav-links .btn {
  min-width: 0;
  margin: 0.6rem 1.1rem 0.5rem;
  padding: 0.75rem 1.4rem;
  border-top: 1px solid rgba(220, 184, 103, 0.5);
  font-size: 0.95rem;
}

.landing .nav .nav-links.open a {
  animation: menu-line 0.6s var(--ease) both;
}

.landing .nav .nav-links.open a:nth-child(2) {
  animation-delay: 0.08s;
}

.landing .nav .nav-links.open a:nth-child(3) {
  animation-delay: 0.16s;
}

.landing .nav .nav-links.open a:nth-child(4) {
  animation-delay: 0.24s;
}

.landing .nav .nav-links.open a:nth-child(5) {
  animation-delay: 0.32s;
}

.landing .nav .nav-links.open a:nth-child(6) {
  animation-delay: 0.4s;
}

.landing .nav .nav-links.open a:nth-child(7) {
  animation-delay: 0.48s;
}

/* the views of the page (?dla=): a small row under the menu's lines, the current view gold */
.landing .nav .nav-dla {
  display: grid;
  justify-items: end;
  gap: 0.35rem;
  padding: 0.75rem 1.35rem 0.55rem;
  border-top: 1px solid rgba(243, 236, 223, 0.07);
}

.landing .nav .nav-dla-label {
  color: var(--ink-faint);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}

.landing .nav .nav-dla-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.15rem 0.85rem;
  max-width: 15rem;
}

.landing .nav .nav-links .nav-dla a {
  padding: 0.2rem 0;
  border-top: 0;
  font-size: 0.8rem;
  letter-spacing: 0.06em;
}

.landing .nav .nav-links .nav-dla a::after {
  display: none;
}

.landing .nav .nav-links .nav-dla a[aria-current="page"] {
  color: var(--gold-1);
}

.landing .nav .nav-links.open .nav-dla {
  animation: menu-line 0.6s var(--ease) 0.4s both;
}

.landing .nav .nav-links.open .nav-dla a {
  animation: none;
}

@keyframes menu-line {
  from {
    opacity: 0;
    filter: blur(4px);
  }
}

/* [hidden] wins over the display of the landing's own blocks */
.landing [hidden] {
  display: none !important;
}

.gold-em {
  font-style: italic;
  font-weight: 300;
  background: var(--gold-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* the mark in running text: Karat in the text's own face, VUE thin and gold in the display
   serif (a fashion masthead), ™ small in the upper corner */
.brandmark {
  white-space: nowrap;
  color: var(--ink);
  /* the name is Latin whatever the page's direction: the mark stays after it on an Arabic page */
  direction: ltr;
  unicode-bidi: isolate;
}

.brandmark em {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: 1.1em;
  letter-spacing: 0.08em;
  background: var(--gold-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.brandmark sup {
  margin-left: 0.08em;
  font-family: inherit;
  font-style: normal;
  font-weight: 500;
  font-size: 0.4em;
  letter-spacing: 0.04em;
  line-height: 0;
  vertical-align: 0.52em;
  color: var(--gold-2);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  border-radius: 999px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink-soft);
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  white-space: nowrap;
}

.chip i {
  display: inline-grid;
  place-items: center;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: linear-gradient(110deg, #fff1c4, #d3ad5a);
  color: #1a1408;
  font-style: normal;
  font-size: 0.75rem;
}

/* ---------- scroll-driven basics. Nothing on this page travels up or down with the scroll:
   what comes, surfaces — clears from a blur, brightens, at most grows a little — and what goes,
   sinks back into the blur where it stands. ---------- */

[data-sa] {
  --in: 1;
  --out: 0;
  --c: 0;
}

.sa-rise,
.sa-zoom {
  --k: clamp(0, calc((var(--in) - var(--d, 0)) / (1 - var(--d, 0))), 1);
  opacity: calc(var(--k) * (1 - var(--out)));
}

.sa-rise {
  filter: blur(calc((1 - var(--k)) * 8px + var(--out) * 6px));
}

.sa-zoom {
  transform: scale(calc(0.8 + 0.2 * var(--k)));
}

.d1 {
  --d: 0.14;
}

.d2 {
  --d: 0.28;
}

.d3 {
  --d: 0.42;
}

/* a glint that crosses a jewel while the page moves and fades when it stops; it lies only on the
   jewel itself: the frame's own alpha is its mask */
.sheen {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
      100deg,
      transparent 44%,
      rgba(255, 247, 224, 0.85) 50%,
      transparent 56%
    )
    no-repeat;
  background-size: 300% 100%;
  background-position: calc(50% + var(--r, 0) * 100%) 0;
  /* light is added, never painted over: the glint brightens the jewel it crosses */
  mix-blend-mode: screen;
  mix-blend-mode: plus-lighter;
  opacity: var(--v, 0);
  -webkit-mask: var(--mask) center / contain no-repeat;
  mask: var(--mask) center / contain no-repeat;
}

.sheen-link {
  --mask: url("/img/exp/f1-1-bar-k.webp");
}

.sheen-product {
  --mask: url("/img/exp/k-naszyjnik-card.webp");
}

.sheen-packshot {
  --mask: url("/img/exp/k-naszyjnik-packshot.webp");
}

/* ---------- the film is the door: the frame grows to the whole screen as the page moves ---------- */

.film3 {
  position: relative;
  height: calc(var(--screen) * 2.3);
}

/* --g: the growth, 0 at the top of the page, 1 once the frame fills the screen; the head row
   (the promise above the film) shrinks away in step and the side gutters close */
.seq-stage.film-stage {
  --g: clamp(0, calc(var(--p) * 1.5), 1);
  /* the head row never shrinks below the menu bar, so the grown film is not under the glass */
  --head: calc(var(--nav-h) + 40svh * (1 - var(--g)));
  /* grown, the foot row equals the head row: the film stands in the middle of the screen */
  --foot: calc(4svh * (1 - var(--g)) + var(--nav-h) * var(--g));
  container-type: size;
  grid-template-columns: 100%;
  grid-template-rows: var(--head) minmax(0, 1fr);
  gap: 0;
  /* grown, the film still keeps clear of the rail on its right */
  padding: 0 max(var(--rail-w), calc(var(--gutter) * (1 - var(--g)))) var(--foot)
    calc(var(--gutter) * (1 - var(--g)));
  align-items: center;
  justify-items: center;
}

.film3-head {
  grid-row: 1;
  grid-column: 1;
  align-self: end;
  display: grid;
  justify-items: center;
  gap: clamp(0.6rem, 1.8svh, 1.2rem);
  max-width: 62rem;
  padding-bottom: 3svh;
  text-align: center;
  overflow: hidden;
  opacity: calc(1 - var(--g) * 1.6);
  filter: blur(calc(var(--g) * 8px));
}

.door h1,
.film3-title {
  font-size: clamp(2.2rem, min(5.4vw, 8svh), 5.6rem);
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.film3-sub {
  color: var(--ink-soft);
  font-size: clamp(1rem, min(1.5vw, 2.4svh), 1.35rem);
  text-wrap: balance;
}

.film3-video {
  grid-row: 2;
  grid-column: 1;
  position: relative;
  /* the film is 1440 × 900: the box keeps that ratio, so nothing of it is ever cut off */
  width: min(100%, calc((100cqh - var(--head) - var(--foot)) * 1.6));
  aspect-ratio: 16 / 10;
  border-radius: calc(18px * (1 - var(--g)));
  overflow: hidden;
  background: #0a0908;
  box-shadow:
    0 60px 120px -40px rgba(0, 0, 0, 0.9),
    0 0 0 1px rgba(247, 223, 158, calc(0.16 * (1 - var(--g))));
}

.film3-video video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  cursor: pointer;
  transition: filter 0.7s ease;
}

/* the film waits for a click on the picture (a tap on a phone): a thin outline glyph in the
   middle says so, and no button. A paused film loses most of its colour under a soft blur and
   the glyph comes back; playing, nothing lies on the picture. Over, the last picture stays
   clear with the glyph (a click plays it again) */
.film3-video.started:not(.playing):not(.over) video {
  filter: saturate(0.45) brightness(0.86);
}

.film3-video::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 50%, rgba(12, 10, 8, 0.04), rgba(12, 10, 8, 0.3));
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  opacity: 0;
  transition: opacity 0.7s ease;
}

.film3-video.started:not(.playing):not(.over)::after {
  opacity: 1;
}

.film-cue {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 4.4rem;
  height: 4.4rem;
  margin: -2.2rem 0 0 -2.2rem;
  border: 1px solid rgba(247, 223, 158, 0.55);
  border-radius: 50%;
  color: var(--gold-1);
  pointer-events: none;
  opacity: 0.85;
  filter: drop-shadow(0 0 14px rgba(247, 223, 158, 0.25));
  transition:
    opacity 0.5s ease,
    transform 0.5s var(--ease);
}

.film-cue svg {
  width: 1.35rem;
  height: 1.35rem;
  margin-left: 0.2rem;
}

.film3-video.playing .film-cue,
.film3-video.broken .film-cue {
  opacity: 0;
  transform: scale(0.8);
}

/* the film's time bar: a thin line at the foot of the picture, in the rail's manner — the played
   part gold, a tick for the playhead, no times; to click or drag along. It shows, with the sound
   button, for a moment after the pointer moves or a finger touches (landing.ts: .awake), and
   always while the film waits */
.film3-video .scrub {
  position: absolute;
  left: 1.1rem;
  right: 1.1rem;
  bottom: 0.6rem;
  z-index: 2;
  mix-blend-mode: plus-lighter;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s ease;
}

.film3-video .sound {
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s ease;
}

.film3-video.awake .scrub,
.film3-video.scrubbing .scrub,
.film3-video .scrub:focus-within,
.film3-video:not(.playing) .scrub,
.film3-video.awake .sound,
.film3-video.scrubbing .sound,
.film3-video .sound:focus-visible,
.film3-video:not(.playing) .sound {
  opacity: 1;
  pointer-events: auto;
}

.scrub-track {
  --k: 0;
  position: relative;
  height: 1.6rem;
  color: rgba(255, 255, 255, 0.36);
  cursor: pointer;
  touch-action: none;
  outline: none;
}

/* the line, and the tick at its end */
.scrub-track::before,
.scrub-track::after {
  content: "";
  position: absolute;
  background: currentColor;
}

.scrub-track::before {
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  opacity: 0.6;
}

.scrub-track::after {
  right: 0;
  top: calc(50% - 0.25rem);
  width: 1px;
  height: 0.5rem;
}

/* what has played: gold, with the tick where it began */
.scrub-fill {
  position: absolute;
  left: 0;
  top: 50%;
  width: calc(var(--k) * 100%);
  height: 1px;
  background: var(--gold-2);
  box-shadow: 0 0 8px rgba(247, 223, 158, 0.45);
}

.scrub-fill::before {
  content: "";
  position: absolute;
  left: 0;
  top: -0.25rem;
  width: 1px;
  height: 0.5rem;
  background: var(--gold-2);
}

/* the playhead: a tick, not a knob */
.scrub-head {
  position: absolute;
  left: calc(var(--k) * 100%);
  top: calc(50% - 0.35rem);
  width: 1px;
  height: 0.7rem;
  background: #fff1c4;
  box-shadow: 0 0 8px 1px rgba(247, 223, 158, 0.55);
}

.scrub-track:focus-visible .scrub-head {
  outline: 1px solid rgba(247, 223, 158, 0.8);
  outline-offset: 3px;
}

/* a phone gets the tall cut of the same film, where the app's text can be read */
.film3-video.portrait {
  display: none;
  width: min(100%, calc((100cqh - var(--head) - var(--foot)) * 9 / 16));
  aspect-ratio: 9 / 16;
}

@media (max-aspect-ratio: 4/5) {
  .film3-video.wide {
    display: none;
  }
  .film3-video.portrait {
    display: block;
  }
}

@media (max-width: 820px) {
  .door h1,
  .film3-title {
    font-size: clamp(2rem, 10vw, 3.6rem);
  }
}

/* ---------- the door: the first screen — the promise. Its words are pinned for a short hold,
   then sink into the blur where they stand while the intro board surfaces over them (--out from
   motion(), over the fade the two share) ---------- */

.door {
  position: relative;
  height: calc(var(--screen) * 1.3 + var(--fade));
}

.door-inner {
  position: sticky;
  top: 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: clamp(0.7rem, 2svh, 1.3rem);
  width: 100%;
  max-width: 62rem;
  height: var(--screen);
  margin-inline: auto;
  padding: calc(var(--nav-h) + 6svh) max(var(--gutter), var(--rail-w)) 8svh var(--gutter);
  text-align: center;
  opacity: calc(1 - var(--out, 0) * 1.4);
  filter: blur(calc(var(--out, 0) * 8px));
}

.door-sub {
  color: var(--ink-soft);
  font-size: clamp(1rem, min(1.5vw, 2.4svh), 1.35rem);
  text-wrap: balance;
}

/* the promise: „Cała kolekcja,” and, on a line of its own that never breaks, a shade narrower
   than the first (landing.ts fits its size to the line above), „w najpiękniejszej odsłonie.” */
.door h1 .door-w[data-door="3"] {
  display: block;
  white-space: nowrap;
  line-height: 1.12;
}

/* the door presents itself one thing at a time — who it is for, the promise, how little it takes —
   each settling into place with time to read; the buttons follow (landing.ts adds .shown) */
.door .eyebrow,
.door h1,
.door-sub {
  animation:
    door-in 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) both,
    door-dolly 9s cubic-bezier(0.15, 0.6, 0.25, 1) both;
}

.door .eyebrow {
  animation-delay: 0.2s, 0.2s;
}

.door h1 {
  animation-delay: 0.9s, 0.9s;
  animation-duration: 1.2s, 9s;
}

.door-sub {
  animation-delay: 2.1s, 2.1s;
}

/* each line comes slowly towards the camera and keeps coming while it is read */
@keyframes door-dolly {
  from {
    transform: scale(0.88);
  }
  to {
    transform: scale(1);
  }
}

@keyframes door-in {
  from {
    opacity: 0;
    filter: blur(6px);
  }
  to {
    opacity: 1;
    filter: blur(0);
  }
}

/* ---------- the dock: four outline icons under the brand in the top-left corner — full screen,
   the music, the voice, the auto-scroll. Each came here from the gate (landing.ts flies the
   chosen button into its slot); a return visit finds them in place. Drawn additively
   (plus-lighter): they brighten the film under them and never cover it. On = gold, off = almost
   white; the fill arrives only under the pointer, and nothing grows or moves. ---------- */

.corner {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  animation: corner-dock 0.9s ease both;
}

/* at the gate the flying buttons stand in for it, and it is simply there when the gate lifts */
.first .corner {
  animation: none;
}

@keyframes corner-dock {
  from {
    opacity: 0;
    filter: blur(4px);
  }
}

.corner button {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 2.35rem;
  height: 2.35rem;
  padding: 0;
  border: 1px solid rgba(243, 236, 223, 0.4);
  border-radius: 50%;
  background: none;
  color: rgba(243, 236, 223, 0.78);
  cursor: pointer;
  mix-blend-mode: plus-lighter;
  transition:
    color 0.7s ease,
    border-color 0.7s ease,
    box-shadow 0.7s ease;
}

/* the words live in the aria-label */
.corner button span {
  display: none;
}

.corner button svg,
.gate-yes svg,
.gate-fly svg {
  width: 1rem;
  height: 1rem;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: filter 0.7s ease;
}

.corner button[aria-pressed="true"] {
  color: var(--gold-1);
  border-color: rgba(247, 223, 158, 0.7);
  box-shadow: 0 0 18px -4px rgba(247, 223, 158, 0.4);
}

.corner button[aria-pressed="true"] svg {
  filter: drop-shadow(0 0 5px rgba(247, 223, 158, 0.5));
}

.corner button::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    120% 120% at 30% 20%,
    rgba(255, 241, 196, 0.32),
    rgba(220, 184, 103, 0.1) 60%,
    transparent 100%
  );
  opacity: 0;
  transition: opacity 0.5s ease;
}

.corner button:hover::before,
.corner button:focus-visible::before {
  opacity: 1;
}

.corner button:focus-visible {
  outline: none;
  border-color: var(--gold-1);
}

/* a phone: a tighter corner; the centred eyebrows wrap here, and the dash would stand alone at
   the left */
@media (max-width: 42rem) {
  .landing .nav {
    gap: 0.45rem;
  }

  .landing .brand {
    font-size: 1.15rem;
  }

  .landing .brand svg {
    width: 2.1rem;
    height: 2.1rem;
  }

  .corner {
    gap: 0.4rem;
  }

  .corner button {
    width: 2.1rem;
    height: 2.1rem;
  }

  .landing .nav .nav-links {
    min-width: min(17rem, calc(100vw - 2 * var(--gutter)));
  }

  .seq-foot {
    padding-bottom: 1.7rem;
  }

  .door .eyebrow::before,
  .film3-head .eyebrow::before {
    display: none;
  }
}

/* ---------- the intro board: the promise in three captions, then the two ways in ---------- */

.seq-intro .seq-head {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.7rem;
}

.seq-intro .seq-title {
  font-size: clamp(1.7rem, min(3.4vw, 5.5svh), 3.4rem);
  max-width: 18em;
  text-wrap: balance;
}

/* ---------- the sequences: one pinned screen per chapter. A board's pinned scroll is
   [fade in][its frames][fade out]; the next pinned board begins where this one's fade out begins
   (the negative margin), so the two cross-fade in place — nothing slides. motion() writes --e
   (0 → 1 over the fade in, once pinned), --p (the frames) and --l (the fade out) on the section.
   The formula of a board: the title at the top, the day and the hour bottom-left, the caption
   bottom-right, a constant dusk at the top and the bottom so the words read over any picture. */

.seq {
  --n: 4;
  --e: 1;
  --l: 0;
  --p: 0;
  --h: 0;
  position: relative;
  height: calc(var(--screen) * (1 + 0.8 * var(--n)) + 2 * var(--fade));
}

.door + .seq,
.seq + .seq {
  margin-top: calc(-1 * (var(--screen) + var(--fade)));
}

/* a board that has not surfaced yet lies over the one before it, unseen and untouchable */
.seq.idle .seq-stage,
.seq.idle .seq-frame.reel {
  visibility: hidden;
}

.seq-stage {
  position: sticky;
  top: 0;
  height: var(--screen);
  display: grid;
  grid-template-columns: 100%;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: clamp(0.5rem, 2svh, 1.6rem);
  padding: calc(var(--nav-h) + 2svh) max(var(--gutter), var(--rail-w)) 5svh var(--gutter);
  overflow: clip;
}

/* the dusk: the same at the top and the bottom of every board (not the film), on an element of
   its own under the stage (landing.ts puts it there): the stage is added to the picture, so
   nothing on it could darken anything. It fades with the board's words */
.seq-dusk {
  position: sticky;
  top: 0;
  z-index: 0;
  height: var(--screen);
  margin-bottom: calc(-1 * var(--screen));
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(13, 12, 11, 0.8) 0%, rgba(13, 12, 11, 0.42) 50%, transparent 100%)
      top / 100% 34svh no-repeat,
    linear-gradient(0deg, rgba(13, 12, 11, 0.92) 0%, rgba(13, 12, 11, 0.5) 45%, transparent 100%)
      bottom / 100% 42svh no-repeat;
  opacity: calc(min(1, calc(var(--e, 1) * 1.6)) * (1 - var(--l, 0)));
}

.seq.idle .seq-dusk {
  visibility: hidden;
}

/* every word on a board is added to the picture: light over light, never a patch of paint */
.seq-stage:not(.film-stage) {
  mix-blend-mode: plus-lighter;
}

/* grid items take a z-index without being positioned: the stage stays the containing block of
   the absolutely placed day and hour */
.seq-head,
.seq-foot {
  z-index: 1;
}

.seq-head {
  --p: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: baseline;
  gap: 0.4rem 1rem;
  text-align: left;
  transform-origin: 0 50%;
  transform: scale(
    calc(0.9 + 0.1 * min(1, calc(var(--e) * 1.6)) + 0.06 * var(--p) + 0.08 * var(--l))
  );
  opacity: calc(min(1, calc(var(--e) * 1.6)) * (1 - var(--l)));
  filter: blur(calc((1 - min(1, calc(var(--e) * 1.6))) * 8px + var(--l) * 8px));
}

/* the day and the hour: bottom-left, always */
.seq-index {
  position: absolute;
  left: var(--gutter);
  bottom: 5svh;
  z-index: 1;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.3em;
  color: var(--gold-2);
  opacity: calc(min(1, calc(var(--e) * 1.6)) * (1 - var(--l)));
  filter: blur(calc((1 - min(1, calc(var(--e) * 1.6))) * 8px + var(--l) * 8px));
}

.seq-title {
  font-size: clamp(1.3rem, min(2.3vw, 3.8svh), 2.3rem);
}

.seq-scene {
  position: relative;
  z-index: 1;
  min-height: 0;
  /* the photo cards below size themselves from the scene (cqw, cqh) */
  container-type: size;
  opacity: calc(min(1, calc(var(--e) * 1.4)) * (1 - var(--l)));
  transform: scale(calc((0.86 + 0.14 * var(--e)) * (1 - 0.08 * var(--l))));
}

.seq-scene::before {
  /* the pool of light the jewels float in — no box around them */
  content: "";
  position: absolute;
  inset: 8% 18%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(
    closest-side,
    hsl(var(--amb-h) calc(var(--amb-s) + 10%) 64% / calc(0.26 - 0.12 * var(--amb-dark))),
    transparent 74%
  );
  mix-blend-mode: screen;
  mix-blend-mode: plus-lighter;
  transform: scale(calc(0.9 + 0.2 * var(--p)));
}

.seq-frame {
  --t: 1;
  --w: 0;
  position: absolute;
  inset: 0;
  display: grid;
  grid-template: 100% / 100%;
  place-items: center;
  /* the two frames of a swap overlap only briefly */
  opacity: clamp(0, calc(var(--w) * 1.6 - 0.45), 1);
  transform: scale(calc(1 + var(--t) * 0.1));
  filter: blur(calc((1 - var(--w)) * 10px));
  will-change: transform, opacity, filter;
}

.seq-frame:first-child {
  --t: 0;
  --w: 1;
}

.seq-frame > img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 34px 44px rgba(0, 0, 0, 0.5));
  /* --k runs 0 → 1 while the frame rests (landing.ts): the picture keeps arriving under the words */
  transform: scale(calc(0.985 + 0.015 * var(--k, 1)));
}

/* a thin strip (the link bar, the product card) keeps about the size of the bar in the app instead
   of stretching across a wide screen; on a phone it fits the width. (Not ".strip": styles.css
   draws that one as a bordered panel.) */
.seq-frame.seq-strip > img,
.seq-frame.seq-strip > .sheen {
  width: min(100%, 46rem, 88svh);
}

.seq-frame.seq-strip > .sheen {
  margin-inline: auto;
}

.seq-foot {
  display: grid;
  justify-items: end;
  justify-self: end;
  width: min(100%, 34rem);
  gap: clamp(0.7rem, 2svh, 1.3rem);
  text-align: right;
  opacity: calc(min(1, calc(var(--e) * 1.6)) * (1 - var(--l)));
  filter: blur(calc((1 - min(1, calc(var(--e) * 1.6))) * 8px + var(--l) * 8px));
}

.seq-caps {
  display: grid;
  width: 100%;
  text-align: right;
}

.seq-foot .story-film-link {
  min-width: 0;
  max-width: 100%;
  padding: 0.65rem 1.15rem;
  font-size: 0.85rem;
  pointer-events: auto;
}

.seq-cap {
  --t: 1;
  --w: 0;
  --k: 0;
  grid-area: 1 / 1;
  display: grid;
  justify-items: end;
  align-content: end;
  gap: 0.5rem;
  /* one caption at a time: the old one is gone before the new one shows */
  opacity: clamp(0, calc(var(--w) * 2.5 - 1.25), 1);
  filter: blur(calc((1 - var(--w)) * 6px));
  transform-origin: 100% 100%;
  transform: scale(calc(0.95 + 0.05 * var(--w) + 0.03 * var(--k)));
}

.seq-cap:first-child {
  --t: 0;
  --w: 1;
}

.seq-cap strong {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.8rem, min(4.2vw, 6svh), 4.4rem);
  line-height: 1.02;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.seq-cap span {
  max-width: 36em;
  color: var(--ink-soft);
  font-size: clamp(0.95rem, min(1.4vw, 2.3svh), 1.3rem);
  text-wrap: balance;
}

/* the sentence under the heading follows it while the frame rests, as the voice reaches it */
.seq-cap > span:not(.cap-fact):not(.cap-q):not(.cta-actions) {
  opacity: calc(0.2 + 0.8 * var(--k, 1));
  filter: blur(calc((1 - var(--k, 1)) * 3px));
}

.seq-cap em {
  font-style: normal;
  color: var(--gold-2);
  font-weight: 600;
  letter-spacing: 0.12em;
}

.seq-bar {
  justify-self: end;
  width: clamp(8rem, 16vw, 14rem);
  height: 2px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
}

.seq-bar i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--gold-3), var(--gold-1));
  transform-origin: left;
  transform: scaleX(var(--p));
}

/* the finished prints arrive stacked and fan out as the page keeps moving */
.prints {
  --a: var(--h, 1);
  position: relative;
  width: 100%;
  height: 100%;
}

.print {
  position: absolute;
  left: 50%;
  top: 4%;
  height: 84%;
  aspect-ratio: 2 / 3;
  margin: 0;
  border-radius: 12px;
  overflow: hidden;
  box-shadow:
    0 40px 70px -24px rgba(0, 0, 0, 0.9),
    0 0 0 1px rgba(255, 241, 196, 0.16);
  transform-origin: 50% 100%;
}

.print img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.print:nth-child(1) {
  transform: translateX(calc(-50% - var(--a) * 64%)) rotate(calc(var(--a) * -9deg));
}

.print:nth-child(2) {
  z-index: 2;
  transform: translateX(-50%);
}

.print:nth-child(3) {
  transform: translateX(calc(-50% + var(--a) * 64%)) rotate(calc(var(--a) * 9deg));
}

.prints .chip {
  position: absolute;
  left: 50%;
  bottom: 0;
  z-index: 3;
  translate: -50% 0;
  opacity: var(--a);
}

@media (max-aspect-ratio: 1/1) {
  .print {
    top: 14%;
    height: 60%;
  }
}

/* on a phone the fan stays on the screen */
@media (max-aspect-ratio: 4/5) {
  .print {
    top: 16%;
    height: 50%;
  }
  .print:nth-child(1) {
    transform: translateX(calc(-50% - var(--a) * 44%)) rotate(calc(var(--a) * -7deg));
  }
  .print:nth-child(3) {
    transform: translateX(calc(-50% + var(--a) * 44%)) rotate(calc(var(--a) * 7deg));
  }
}

/* once the photo has arrived, the loupe glides down the chain to the pendant (at 57% × 49% of the
   photo) as the page keeps moving */
.loupe-shot {
  --a: var(--h, 1);
  --lx: calc(0.82 - 0.25 * var(--a));
  --ly: calc(0.24 + 0.25 * var(--a));
  --z: 6.25;
  position: relative;
  height: 100%;
  aspect-ratio: 2 / 3;
  max-width: 100%;
}

/* under a mouse, or a finger on the glass, the loupe goes where the reader points */
.loupe-shot.follow {
  --lx: var(--px, 0.5);
  --ly: var(--py, 0.5);
}

.loupe {
  touch-action: none;
  cursor: grab;
}

.loupe-shot > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 14px;
  box-shadow:
    0 40px 70px -24px rgba(0, 0, 0, 0.9),
    0 0 0 1px rgba(255, 241, 196, 0.16);
}

.loupe {
  position: absolute;
  left: calc(var(--lx) * 100%);
  top: calc(var(--ly) * 100%);
  width: 40%;
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  overflow: hidden;
  background: #0a0908;
  box-shadow:
    0 0 0 2px rgba(247, 223, 158, 0.9),
    0 0 0 7px rgba(13, 12, 11, 0.45),
    0 30px 60px -20px rgba(0, 0, 0, 0.95);
}

.loupe img {
  position: absolute;
  max-width: none;
  width: calc(var(--z) * 100%);
  height: auto;
  left: calc(50% - var(--lx) * var(--z) * 100%);
  top: calc(50% - var(--ly) * var(--z) * 150%);
}

/* ---------- the swap: a generator's "almost the same" pendant gives way to the real one ---------- */

/* --h runs 0 → 1 once the last frame has arrived: the wrong pendant loses its colour and its focus and
   shrinks back, the jeweller's own pendant comes forward and a glint keeps crossing it */
.swap {
  --k: var(--h, 1);
  position: relative;
  height: 100%;
  aspect-ratio: 965 / 1356;
  max-width: 100%;
  display: grid;
  grid-template: 100% / 100%;
}

.swap > img,
.swap-glint {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.swap-wrong {
  filter: grayscale(var(--k)) blur(calc(var(--k) * 9px)) drop-shadow(0 34px 44px rgba(0, 0, 0, 0.5));
  opacity: calc(1 - 0.6 * var(--k));
  transform: scale(calc(1 - 0.14 * var(--k)));
}

.swap-true {
  opacity: clamp(0, calc(var(--k) * 1.4 - 0.3), 1);
  transform: scale(calc(0.72 + 0.28 * var(--k)));
  filter: drop-shadow(0 34px 44px rgba(0, 0, 0, 0.55));
}

.swap-glint {
  pointer-events: none;
  opacity: var(--k);
  -webkit-mask: url("/img/exp/hero-k.webp") center / contain no-repeat;
  mask: url("/img/exp/hero-k.webp") center / contain no-repeat;
  background: linear-gradient(
    112deg,
    transparent 38%,
    rgba(255, 246, 214, 0.55) 46%,
    rgba(255, 255, 255, 0.95) 50%,
    rgba(255, 246, 214, 0.55) 54%,
    transparent 62%
  );
  background-size: 260% 100%;
  mix-blend-mode: screen;
  mix-blend-mode: plus-lighter;
  animation: swap-glint 3.4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

@keyframes swap-glint {
  0% {
    background-position: 120% 0;
  }
  55%,
  100% {
    background-position: -40% 0;
  }
}

.still .swap-glint {
  animation: none;
  opacity: 0;
}

/* the glint runs only while its board is on the screen and its frame can be seen: an animation
   that nobody sees still dirties the style of the page every frame */
.seq.idle .swap-glint {
  animation-play-state: paused;
}

/* ---------- real photos in a sequence: the crop, the close-up, the outpaint, the guider ---------- */

/* a photo card sized from the scene, so a photo and a sketch of the same ratio land on exactly
   the same box */
.shot,
.crop-shot {
  --ar: 2 / 3;
  position: relative;
  width: min(100%, calc(100cqh * var(--ar)));
  aspect-ratio: var(--ar);
  margin: 0;
}

.shot > img,
.crop-shot > img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 14px;
  box-shadow:
    0 40px 70px -24px rgba(0, 0, 0, 0.9),
    0 0 0 1px rgba(255, 241, 196, 0.16);
}

.shot-detail {
  --ar: 3 / 4;
}

.shot-wide {
  --ar: 16 / 9;
  width: min(94cqw, calc(100cqh * 16 / 9));
}

.shot .chip {
  position: absolute;
  left: 50%;
  bottom: 4%;
  translate: -50% 0;
}

.shot .chip-action {
  left: 5%;
  translate: none;
}

/* the 4:5 crop frame closes in on the pendant (57% × 49% of the photo) while the page moves;
   outside it the photo dims, as in the app */
.crop-shot {
  --k: clamp(0, calc(var(--r, 0.4) + 0.6), 1);
  --bw: calc(1 - 0.7 * var(--k));
  --bh: calc(var(--bw) * 0.8333);
  --cx: calc(0.5 + 0.07 * var(--k));
  --cy: calc(0.5 - 0.01 * var(--k));
  overflow: hidden;
  border-radius: 14px;
  box-shadow:
    0 40px 70px -24px rgba(0, 0, 0, 0.9),
    0 0 0 1px rgba(255, 241, 196, 0.16);
}

.crop-shot > img {
  border-radius: 0;
  box-shadow: none;
}

.crop-box {
  position: absolute;
  left: calc((var(--cx) - var(--bw) / 2) * 100%);
  top: calc((var(--cy) - var(--bh) / 2) * 100%);
  width: calc(var(--bw) * 100%);
  height: calc(var(--bh) * 100%);
  border: 1.5px solid rgba(247, 223, 158, 0.95);
  border-radius: 4px;
  box-shadow:
    0 0 0 200vmax rgb(8 7 6 / calc(0.55 * var(--k))),
    0 0 24px rgba(247, 223, 158, 0.35);
}

.crop-box i {
  position: absolute;
  left: 0.5rem;
  top: 0.5rem;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-style: normal;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #1a1408;
  background: linear-gradient(110deg, #fff1c4, #d3ad5a);
}

/* past the photo: the 16:9 frame grows beyond its edges over the light-blue canvas the model
   fills in; the next frame is the filled banner, exactly the frame's size */
.crop-wide {
  --bw: calc(1 + 1.6667 * var(--k));
  width: calc(min(100cqh, 52.9cqw) * 2 / 3);
  overflow: visible;
  box-shadow: none;
}

.crop-wide > img {
  position: relative;
  z-index: 1;
  border-radius: 14px;
  box-shadow: 0 30px 60px -24px rgba(0, 0, 0, 0.9);
}

.crop-wide .crop-box,
.crop-fill {
  left: calc((1 - var(--bw)) / 2 * 100%);
  top: 0;
  width: calc(var(--bw) * 100%);
  height: 100%;
}

.crop-wide .crop-box {
  z-index: 2;
  box-shadow: 0 0 24px rgba(247, 223, 158, 0.35);
}

.crop-fill {
  position: absolute;
  border-radius: 6px;
  background: repeating-linear-gradient(
    135deg,
    rgb(124 200 255 / 0.3) 0 7px,
    rgb(124 200 255 / 0.1) 7px 14px
  );
}

/* the guider's sketch: light lines only, a touch brighter so they read on the velvet */
.seq-frame > img.sketch {
  filter: brightness(1.9) drop-shadow(0 0 1px rgba(255, 236, 190, 0.35));
}

.bulk {
  position: relative;
  width: 100%;
  height: 100%;
}

.bulk > img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 34px 44px rgba(0, 0, 0, 0.5));
}

.chip-soon {
  position: absolute;
  top: 2%;
  left: 50%;
  translate: -50% 0;
  color: var(--gold-1);
  font-size: 0.78rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

/* the MCP conversation: the assistant's answer arrives while the page moves */
.chat {
  display: grid;
  gap: 1.2rem;
  width: min(100%, 40rem);
}

.bubble {
  max-width: 88%;
  margin: 0;
  padding: 1rem 1.3rem;
  border-radius: 22px;
  font-size: clamp(1rem, min(1.5vw, 2.4svh), 1.35rem);
  line-height: 1.45;
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  box-shadow: var(--glass-shadow);
}

.bubble-you {
  justify-self: end;
  border-bottom-right-radius: 6px;
}

.bubble-ai {
  --b: clamp(0, calc((var(--r, 1) + 0.12) * 5), 1);
  justify-self: start;
  border-bottom-left-radius: 6px;
  border-color: rgba(247, 223, 158, 0.35);
  opacity: var(--b);
  filter: blur(calc((1 - var(--b)) * 6px));
}

.bubble-ai i {
  margin-right: 0.35rem;
  font-style: normal;
  color: var(--gold-2);
}

/* board 02: the customer writes first, the jeweller's reply arrives while the frame rests */
.bubble-her {
  justify-self: start;
  border-bottom-left-radius: 6px;
  border-color: rgba(247, 223, 158, 0.35);
}

.bubble-late {
  --b: clamp(0, calc((var(--r, 1) + 0.12) * 5), 1);
  opacity: var(--b);
  filter: blur(calc((1 - var(--b)) * 6px));
}

.still .bubble-late {
  opacity: 1;
  filter: none;
}

/* board 02: the jeweller's own phone photo — the packshot on a sheet of paper under a desk lamp:
   yellow, soft, a hand in the light, the frame not quite straight */
.bad-shot {
  --ar: 3 / 4;
  overflow: hidden;
  border-radius: 14px;
  box-shadow:
    0 40px 70px -24px rgba(0, 0, 0, 0.9),
    0 0 0 1px rgba(255, 241, 196, 0.16);
}

.bad-shot > img {
  box-sizing: border-box;
  padding: 14% 10%;
  object-fit: contain;
  border-radius: 0;
  box-shadow: none;
  background:
    radial-gradient(
      120% 90% at 28% 18%,
      rgba(255, 234, 176, 0.98),
      rgba(218, 190, 126, 0.95) 52%,
      rgba(110, 92, 58, 0.98)
    ),
    #b9a070;
  filter: sepia(0.55) saturate(1.25) contrast(0.82) brightness(1.04) blur(1.3px);
  transform: rotate(-2.5deg) scale(1.08);
}

.bad-shot::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(200deg, transparent 44%, rgba(24, 14, 4, 0.5) 60%, rgba(24, 14, 4, 0.78) 100%),
    radial-gradient(72% 62% at 48% 38%, transparent 58%, rgba(0, 0, 0, 0.5));
}

/* ---------- film ---------- */

.sound {
  position: absolute;
  top: 0.8rem;
  right: 0.8rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--glass-edge);
  border-radius: 999px;
  color: var(--ink);
  background: rgba(13, 12, 11, 0.6);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}

.sound svg {
  width: 1.1rem;
  height: 1.1rem;
}

/* ---------- the form: one screen of glass for those who prefer writing ---------- */

/* the price: one gold number on its board */
/* a question over its answer (the FAQ board) */
.seq-cap .cap-q {
  font-size: clamp(0.95rem, min(1.3vw, 2.1svh), 1.2rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--gold-2);
}

/* a fact under a caption: the number that proves the sentence */
.cap-fact,
.seq-cap .cap-fact {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-2);
}

/* On a wide screen a board is two columns: the picture on one side, the words sliding out from
   behind it on the other. Every second board mirrors, so the eye keeps moving. */
@media (min-width: 62rem) and (min-aspect-ratio: 1/1) {
  .seq-cap strong {
    font-size: clamp(1.6rem, min(3.1vw, 5svh), 3.4rem);
  }

  .seq-cap span {
    max-width: 26em;
  }
}

/* ---------- the video sample: the product turning in the light ---------- */

.spin {
  min-height: var(--screen);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: center;
  padding: calc(var(--nav-h) + 4svh) 0 6svh;
}

.spin .wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  align-items: center;
  gap: clamp(1.4rem, 4vw, 4rem);
}

.spin-copy {
  display: grid;
  justify-items: start;
  gap: clamp(0.8rem, 2svh, 1.6rem);
}

.spin h2 {
  font-size: clamp(2rem, min(4.6vw, 7svh), 4.2rem);
}

.spin-video {
  width: 100%;
  max-width: min(32rem, 62svh);
  aspect-ratio: 1;
  justify-self: center;
}

.spin-video video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-aspect-ratio: 1/1) {
  .spin .wrap {
    grid-template-columns: minmax(0, 1fr);
  }

  .spin-copy {
    justify-items: center;
    text-align: center;
  }
}

/* ---------- reduced motion: the frames still cross-fade, nothing travels ---------- */

.still .sa-rise,
.still .sa-zoom,
.still .film3-head,
.still .seq-head,
.still .seq-scene,
.still .seq-foot,
.still .seq-frame,
.still .seq-cap {
  transform: none;
  filter: none;
}

.still .sheen {
  display: none;
}

.still .prints,
.still .loupe-shot {
  --a: 1;
}

.still .crop-shot {
  --k: 1;
}

.still .bubble-ai {
  --b: 1;
}

/* ---------- a first arrival: the door comes up out of the dark, colour last, the menu after it
   (landing.ts puts .first on <html> when the page opens at its top) ---------- */

.dark {
  display: none;
}

.first .dark {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 90;
  background: #000;
  pointer-events: none;
  animation: dark-lift 2.4s cubic-bezier(0.4, 0, 0.2, 1) 0.3s both;
}

@keyframes dark-lift {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

/* ---------- the velvet on its own element. The page's shared velvet is body::before with the
   ambient colour on <html>; here the colour changes with every frame, and a registered property
   transitioned on <html> restyled the whole document every frame for 1.8 s. So the landing hides
   body::before and draws the same velvet on .velvet — a leaf: the colour and its transition live
   there (and on the scene of the frame, for its pool of light), and nothing else is restyled. */
.landing::before {
  content: none;
}

.velvet {
  position: fixed;
  inset: -20vmax;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(
      60vmax 40vmax at 20% 10%,
      hsl(var(--amb-h) var(--amb-s) 52% / calc(0.25 - 0.14 * var(--amb-dark))),
      transparent 60%
    ),
    radial-gradient(
      50vmax 40vmax at 85% 30%,
      hsl(calc(var(--amb-h) - 12) var(--amb-s) 34% / calc(0.2 - 0.1 * var(--amb-dark))),
      transparent 60%
    ),
    radial-gradient(
      70vmax 50vmax at 50% 100%,
      hsl(calc(var(--amb-h) + 6) calc(var(--amb-s) * 0.7) 22% / calc(0.38 - 0.1 * var(--amb-dark))),
      transparent 60%
    ),
    linear-gradient(
      180deg,
      hsl(35 10% calc(5.5% - 2.5% * var(--amb-dark))) 0%,
      hsl(35 8% calc(4.7% - 2.2% * var(--amb-dark))) 100%
    );
  animation: drift 26s ease-in-out infinite alternate;
}

.velvet,
.seq-scene {
  transition:
    --amb-h 1.8s ease,
    --amb-s 1.8s ease,
    --amb-dark 1.8s ease;
}

/* the gate stands in the dark until „Wejdź” (landing.ts adds .entered): only then the velvet's
   colour arrives, the words of the door come one by one, and the menu and the buttons follow */
.first:not(.entered) .velvet {
  opacity: 0;
}

.entered .velvet {
  animation:
    velvet-in 4s ease 0.2s both,
    drift 26s ease-in-out infinite alternate;
}

@keyframes velvet-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* on a first arrival the door's words wait for their turn (the stylesheet's own entrance is off) */
.first .door .eyebrow,
.first .door h1,
.first .door-sub {
  animation: none;
}

.first .door .eyebrow.in,
.first .door h1.in,
.first .door-sub.in {
  animation: door-dolly 10s cubic-bezier(0.15, 0.6, 0.25, 1) both;
}

.first .door-w {
  opacity: 0;
  filter: blur(6px);
  transition:
    opacity 0.9s ease,
    filter 0.9s ease;
}

.first .door-w.in {
  opacity: 1;
  filter: blur(0);
}

.first:not(.entered) .nav {
  opacity: 0;
}

.entered .brand {
  animation: nav-in 1.1s ease 0.8s both;
}

@keyframes nav-in {
  from {
    opacity: 0;
    filter: blur(4px);
  }
  to {
    opacity: 1;
    filter: blur(0);
  }
}

.first:not(.entered) .corner {
  opacity: 0;
  pointer-events: none;
}

/* ---------- the gate: four choices in the dark before the page — full screen, the music, the
   voice, then „Wejdź”. Black, the mark and the name, one question at a time. Every choice made
   (or skipped) turns its button into an outline icon that flies to its slot in the dock in the
   top-left corner (landing.ts: fly), gold when on and almost white when off; the next question
   surfaces slowly after it. ---------- */

html.gated {
  overflow: hidden;
}

.gate {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  padding: var(--gutter);
  background: #000;
  transition:
    opacity 1.1s ease,
    visibility 0s linear 1.1s;
}

.gate.closing {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.gate-inner {
  display: grid;
  justify-items: center;
  gap: clamp(0.9rem, 2.6svh, 1.6rem);
  text-align: center;
}

.gate-mark {
  width: clamp(5.4rem, 15svh, 8.4rem);
  height: auto;
  filter: drop-shadow(0 0 28px rgba(247, 223, 158, 0.22));
  animation: gate-mark 2s ease both;
}

@keyframes gate-mark {
  from {
    opacity: 0;
    transform: scale(0.94);
  }
}

.gate-title {
  font-family: var(--font-ui);
  font-size: clamp(1.5rem, 3.4vw, 2.4rem);
  letter-spacing: 0.02em;
  animation: gate-rise 1.6s ease 0.5s both;
}

/* the questions share one cell: a change never moves the mark */
.gate-steps {
  display: grid;
  margin-top: clamp(0.6rem, 3svh, 2rem);
  min-height: 10rem;
}

.gate-step {
  grid-area: 1 / 1;
  display: grid;
  justify-items: center;
  align-content: start;
  gap: 1rem;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity 0.5s ease,
    visibility 0s linear 0.5s;
}

.gate-step.on {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: none;
  animation: gate-fade 1.5s var(--ease) both;
}

/* the first question waits for the name */
.gate-step.on.first {
  animation-delay: 1.4s;
}

@keyframes gate-rise {
  from {
    opacity: 0;
    filter: blur(6px);
  }
}

/* a question comes exactly where the last one stood: it clears, it does not move */
@keyframes gate-fade {
  from {
    opacity: 0;
    filter: blur(6px);
  }
}

.gate-q {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-2);
}

/* the buttons: an outline and no fill — glass arrives under the pointer, added to the dark, and
   a light passes over it; nothing moves or grows */
.gate-pick-toggle,
.gate-yes,
.gate-enter,
.btn-line {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  min-width: 15rem;
  padding: 0.9rem 1.8rem;
  border: 1px solid rgba(220, 184, 103, 0.5);
  border-radius: 999px;
  background: none;
  color: var(--gold-1);
  font: inherit;
  font-size: 1.02rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.4;
  cursor: pointer;
  overflow: hidden;
  transition:
    border-color 0.6s ease,
    color 0.6s ease,
    box-shadow 0.6s ease;
}

.gate-yes svg {
  flex: none;
  width: 1.35rem;
  height: 1.35rem;
}

/* the same box as the questions: every button stands at the same level */
.gate-enter {
  letter-spacing: 0.12em;
}

.gate-pick-toggle::before,
.gate-yes::before,
.gate-enter::before,
.btn-line::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    165deg,
    rgba(255, 241, 196, 0.3),
    rgba(220, 184, 103, 0.08) 50%,
    rgba(255, 255, 255, 0.14)
  );
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  mix-blend-mode: plus-lighter;
  opacity: 0;
  transition: opacity 0.55s ease;
}

/* the light that passes over the glass */
.gate-pick-toggle::after,
.gate-yes::after,
.gate-enter::after,
.btn-line::after {
  content: "";
  position: absolute;
  inset: -40% -30%;
  background: linear-gradient(
    105deg,
    transparent 38%,
    rgba(255, 248, 226, 0.35) 50%,
    transparent 62%
  );
  mix-blend-mode: plus-lighter;
  opacity: 0;
  transform: translate3d(-60%, 0, 0);
  pointer-events: none;
}

.gate-pick-toggle:hover,
.gate-yes:hover,
.gate-enter:hover,
.btn-line:hover {
  border-color: rgba(247, 223, 158, 0.9);
  color: #fff4d6;
  box-shadow:
    0 0 0 1px rgba(247, 223, 158, 0.12),
    0 0 32px -8px rgba(247, 223, 158, 0.45);
}

.gate-pick-toggle:hover::before,
.gate-yes:hover::before,
.gate-enter:hover::before,
.btn-line:hover::before {
  opacity: 1;
}

.gate-pick-toggle:hover::after,
.gate-yes:hover::after,
.gate-enter:hover::after,
.btn-line:hover::after {
  animation: gate-sheen 1.1s ease 0.1s both;
}

/* the keyboard: a thin ring, no glass (the page focuses each question as it comes) */
.gate-pick-toggle:focus-visible,
.gate-yes:focus-visible,
.gate-enter:focus-visible,
.btn-line:focus-visible {
  outline: none;
  border-color: rgba(247, 223, 158, 0.85);
  box-shadow: 0 0 0 3px rgba(247, 223, 158, 0.16);
}

@keyframes gate-sheen {
  0% {
    opacity: 0;
    transform: translate3d(-60%, 0, 0);
  }

  20% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    transform: translate3d(60%, 0, 0);
  }
}

.gate-skip {
  padding: 0.4rem 0.8rem;
  border: 0;
  background: none;
  color: var(--ink-faint);
  font: inherit;
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
  transition: color 0.4s ease;
}

.gate-skip:hover {
  color: var(--ink-soft);
}

/* „Kim jesteś?”: one outline pill that opens the audiences as a list — black glass under a gold
   hairline, the answers one under another, a faded hairline between them. The list lies over
   what is below it, so opening it never moves the mark; when the room below is short it scrolls
   inside, faded over the cut edge, and only on a very low screen turns upward (landing.ts:
   gatePick). It clears in from its edge by the pill; nothing in it moves or grows. An answer opens the page cut for it,
   the question clears while it loads */
.gate-pick {
  position: relative;
  z-index: 2;
  width: min(22rem, 100%);
}

.gate-pick-toggle {
  width: 100%;
  min-width: 0;
  gap: 0.65rem;
}

.gate-pick-toggle svg {
  flex: none;
  width: 0.95rem;
  height: 0.95rem;
  opacity: 0.8;
  transition: transform 0.55s var(--ease);
}

.gate-pick.open .gate-pick-toggle {
  border-color: rgba(247, 223, 158, 0.9);
  color: #fff4d6;
}

.gate-pick.open .gate-pick-toggle svg {
  transform: rotate(180deg);
}

.gate-menu {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  max-height: var(--gate-room, 22rem);
  overflow: hidden;
  border: 1px solid rgba(220, 184, 103, 0.42);
  border-radius: 1.4rem;
  background: #070604;
  box-shadow:
    0 28px 60px -24px #000,
    0 0 44px -20px rgba(247, 223, 158, 0.3);
  opacity: 0;
  visibility: hidden;
  /* the reveal: the list clears in from its edge by the pill (the shadow stays inside the clip) */
  clip-path: inset(-3rem -3rem 100% -3rem);
  transition:
    opacity 0.3s ease,
    clip-path 0.45s var(--ease),
    visibility 0s linear 0.45s;
}

.gate-pick.up .gate-menu {
  top: auto;
  bottom: calc(100% + 8px);
  clip-path: inset(100% -3rem -3rem -3rem);
}

.gate-pick.open .gate-menu {
  opacity: 1;
  visibility: visible;
  clip-path: inset(-3rem);
  transition:
    opacity 0.35s ease,
    clip-path 0.6s var(--ease);
}

/* the answers: inside the frame, the part that scrolls when the room is short */
.gate-menu-list {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  padding: 0.4rem;
  list-style: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(220, 184, 103, 0.35) transparent;
  text-align: center;
}

/* a list that scrolls fades over the edge it is cut at; the frame and its dark stay whole */
.gate-menu-list.more-below {
  mask-image: linear-gradient(to bottom, #000 calc(100% - 2.8rem), transparent);
}

.gate-menu-list.more-above {
  mask-image: linear-gradient(to top, #000 calc(100% - 2.8rem), transparent);
}

.gate-menu-list.more-above.more-below {
  mask-image: linear-gradient(
    to bottom,
    transparent,
    #000 2.8rem,
    #000 calc(100% - 2.8rem),
    transparent
  );
}

.gate-menu li + li::before {
  content: "";
  display: block;
  height: 1px;
  margin: 0 1.4rem;
  background: linear-gradient(90deg, transparent, rgba(220, 184, 103, 0.22), transparent);
  transition: opacity 0.45s ease;
}

/* the hairlines next to the lit answer go out, so its glass stands alone */
.gate-menu li:has(> .gate-option:hover, > .gate-option:focus-visible)::before,
.gate-menu li:has(> .gate-option:hover, > .gate-option:focus-visible) + li::before {
  opacity: 0;
}

.gate-pick.open .gate-menu li {
  animation: gate-fade 0.7s var(--ease) both;
}

.gate-pick.open .gate-menu li:nth-child(2) {
  animation-delay: 0.05s;
}

.gate-pick.open .gate-menu li:nth-child(3) {
  animation-delay: 0.1s;
}

.gate-pick.open .gate-menu li:nth-child(4) {
  animation-delay: 0.15s;
}

.gate-pick.open .gate-menu li:nth-child(n + 5) {
  animation-delay: 0.2s;
}

/* an answer: the words alone; glass arrives under the pointer (or the keys), added to the dark */
.gate-option {
  position: relative;
  display: block;
  padding: 0.62rem 1.4rem;
  border-radius: 1rem;
  color: var(--gold-1);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.35;
  text-decoration: none;
  outline: none;
  overflow: hidden;
  transition:
    color 0.45s ease,
    box-shadow 0.45s ease;
}

.gate-option::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    165deg,
    rgba(255, 241, 196, 0.22),
    rgba(220, 184, 103, 0.06) 50%,
    rgba(255, 255, 255, 0.1)
  );
  mix-blend-mode: plus-lighter;
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}

.gate-option:hover,
.gate-option:focus-visible {
  color: #fff4d6;
  text-decoration: none;
}

.gate-option:hover::before,
.gate-option:focus-visible::before {
  opacity: 1;
}

/* the keyboard: a thin ring inside the glass */
.gate-option:focus-visible {
  box-shadow: inset 0 0 0 1px rgba(247, 223, 158, 0.55);
}

.gate.leaving .gate-steps {
  opacity: 0;
  filter: blur(6px);
  transition:
    opacity 0.4s ease,
    filter 0.4s ease;
}

/* a phone: the pill and its list across the column, the answers a little closer */
@media (max-width: 34rem) {
  .gate-pick {
    width: min(20rem, 100%);
  }

  .gate-option {
    padding: 0.62rem 1rem;
    font-size: 0.95rem;
  }
}

/* without motion the list only fades */
@media (prefers-reduced-motion: reduce) {
  .gate-menu,
  .gate-pick.up .gate-menu,
  .gate-pick.open .gate-menu {
    clip-path: none;
  }

  .gate-pick.open .gate-menu li {
    animation: none;
  }

  .gate-pick-toggle svg {
    transition: none;
  }
}

/* the flight: the chosen button, as its outline, closes into a circle around its icon and glides
   to its slot in the dock, where it stands in for the dock until the gate lifts; landing.ts
   sizes and moves it */
.gate-fly {
  position: fixed;
  left: 0;
  top: 0;
  display: block;
  border: 1px solid currentColor;
  border-radius: 999px;
  color: var(--gold-1);
  font: inherit;
  font-size: 1.02rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  pointer-events: none;
  mix-blend-mode: plus-lighter;
  will-change: transform, width;
}

/* the icon and the words keep the places they had in the button (landing.ts sets them) */
.gate-fly > * {
  position: absolute;
  display: block;
}

/* the glass the pointer had lit goes out as the pill closes */
.gate-fly::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    165deg,
    rgba(255, 241, 196, 0.3),
    rgba(220, 184, 103, 0.08) 50%,
    rgba(255, 255, 255, 0.14)
  );
  opacity: 0;
}

.gate-fly.lit::before {
  opacity: 1;
}

.gate-fly.lit.closing::before {
  opacity: 0;
  transition: opacity 0.7s ease;
}

.gate-fly svg {
  width: 1.35rem;
  height: 1.35rem;
}

.gate-fly.on svg {
  filter: drop-shadow(0 0 5px rgba(247, 223, 158, 0.5));
}

.gate-fly.docked svg {
  width: 1rem;
  height: 1rem;
}

.gate-fly.docked.off {
  border-color: rgba(243, 236, 223, 0.4);
}

.gate-fly.docked.on {
  border-color: rgba(247, 223, 158, 0.7);
  box-shadow: 0 0 18px -4px rgba(247, 223, 158, 0.4);
}

/* ---------- the rail: the scrollbar's place — a thin gold line at the right edge, a short
   thicker stroke that goes down with the story, and above it the number of the board out of
   all of them (landing.ts writes --rail, 0–1, and the count) ---------- */

:root:has(body.landing) {
  scrollbar-width: none;
}

:root:has(body.landing)::-webkit-scrollbar {
  display: none;
}

/* ---------- the rail: the story's chapters down the right edge, each as long as the time the
   presentation spends on it (landing.ts lays them out), named in small spaced capitals; the
   chapter on the screen is gold, the others grey; small ticks divide them; the pin travels with
   the reader. Its light is added to the picture. Everything on the boards keeps clear of it
   (--rail-w, the stages' right padding). A click goes to a chapter's first stop ---------- */
.rail {
  position: fixed;
  top: calc(var(--nav-h) + 0.8rem);
  right: 0;
  bottom: max(1.2rem, env(safe-area-inset-bottom));
  z-index: 40;
  width: var(--rail-w);
  mix-blend-mode: plus-lighter;
  transition: opacity 0.6s ease;
}

html.gated .rail {
  opacity: 0;
}

.rail-seg {
  position: absolute;
  left: 0;
  right: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: rgba(255, 255, 255, 0.36);
  font: inherit;
  cursor: pointer;
  transition: color 0.5s ease;
}

/* the chapter's line, between its tick and the next */
.rail-seg::before {
  content: "";
  position: absolute;
  top: 0.3rem;
  bottom: 0.3rem;
  right: 0.75rem;
  width: 1px;
  background: currentColor;
  opacity: 0.6;
}

/* the tick where the chapter begins */
.rail-seg::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0.5rem;
  width: 0.5rem;
  height: 1px;
  background: currentColor;
}

.rail-seg span {
  position: absolute;
  top: 0.8rem;
  right: 1.3rem;
  writing-mode: vertical-rl;
  font-family: var(--font-ui);
  font-size: 0.58rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  white-space: nowrap;
}

.rail-seg:hover {
  color: rgba(255, 255, 255, 0.62);
}

.rail-seg.on,
.rail-seg.on:hover {
  color: var(--gold-2);
  text-shadow: 0 0 12px rgba(247, 223, 158, 0.35);
}

.rail-seg:focus-visible {
  outline: 1px solid var(--gold-2);
  outline-offset: -1px;
}

/* the smaller stops inside a chapter (the problem's three frames): shorter ticks, by time */
.rail-tick {
  position: absolute;
  right: 0.5rem;
  width: 0.28rem;
  height: 1px;
  background: currentColor;
  opacity: 0.7;
}

/* the last tick, at the foot of the rail */
.rail::after {
  content: "";
  position: absolute;
  bottom: 0;
  right: 0.5rem;
  width: 0.5rem;
  height: 1px;
  background: rgba(255, 255, 255, 0.36);
}

/* the pin: where the reader is, along the time of the story */
.rail-pin {
  position: absolute;
  top: calc(var(--rail, 0) * 100%);
  right: calc(0.75rem - 2px);
  width: 5px;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 50%;
  background: #fff1c4;
  box-shadow: 0 0 10px 2px rgba(247, 223, 158, 0.55);
  pointer-events: none;
}

/* ---------- „Dalej…”: while the run is off, one gold word at the foot of the screen offers the
   next stop (landing.ts shows it and glides there on a click) ---------- */
.onward {
  position: fixed;
  left: 50%;
  bottom: max(1.4rem, env(safe-area-inset-bottom));
  z-index: 45;
  translate: -50% 0;
  margin: 0;
  padding: 0.4rem 1.2rem 0.5rem;
  border: 0;
  background: none;
  color: var(--gold-2);
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.5rem, min(2.4vw, 3.6svh), 2.2rem);
  letter-spacing: 0.04em;
  line-height: 1;
  text-shadow: 0 0 22px rgba(247, 223, 158, 0.35);
  mix-blend-mode: plus-lighter;
  cursor: pointer;
  opacity: 0;
  transform: translate3d(0, 8px, 0);
  pointer-events: none;
  transition:
    opacity 0.6s ease,
    transform 0.6s ease,
    color 0.3s ease;
}

.onward.shown {
  opacity: 1;
  transform: none;
  pointer-events: auto;
  animation: onward-breathe 3.2s ease-in-out infinite;
}

.onward:hover {
  color: var(--gold-1);
}

.onward:focus-visible {
  outline: 1px solid var(--gold-2);
  outline-offset: 4px;
  border-radius: 999px;
}

/* share: a small spaced line with an arrow in the bottom-right corner, left of the rail; it
   hands the address to the system share sheet (or the clipboard), and steps aside for the fine
   print at the very end (--in from paint()) */
.share {
  position: fixed;
  right: max(var(--gutter), calc(var(--rail-w) + 0.5rem));
  bottom: max(1.55rem, env(safe-area-inset-bottom));
  z-index: 44;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
  padding: 0.4rem 0.2rem;
  border: 0;
  background: none;
  color: color-mix(in srgb, var(--gold-2) 72%, transparent);
  font: inherit;
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: calc(1 - var(--in, 0));
  transition:
    color 0.4s ease,
    text-shadow 0.4s ease,
    opacity 0.4s ease;
}

.share svg {
  width: 0.85rem;
  height: 0.85rem;
  stroke-width: 1.6;
}

.share:hover,
.share:focus-visible {
  color: var(--gold-1);
  text-shadow: 0 0 12px rgba(247, 223, 158, 0.35);
  outline: none;
}

.share.done {
  color: var(--ink);
}

html.gated .share,
.share[style*="--in: 1"] {
  opacity: 0;
  pointer-events: none;
}

@media (max-width: 42rem) {
  .share span {
    font-size: 0.58rem;
  }
}

@keyframes onward-breathe {
  0%,
  100% {
    opacity: 0.78;
  }
  50% {
    opacity: 1;
  }
}

@media (max-width: 42rem) {
  .rail-seg span {
    font-size: 0.52rem;
  }

  /* on a phone the word sits under the boards' foot: the day and the caption move up for it */
  .seq-stage:not(.film-stage) {
    padding-bottom: calc(5svh + 2.9rem);
  }

  .seq-index {
    bottom: calc(5svh + 2.9rem);
  }
}

/* ---------- the reactor: the whole page breathes with the bass of the music. landing.ts reads
   the low band of the loop and writes --bass (0–1) on the root; the glow is gold light added
   over everything, soft-edged, never more than a felt warmth ---------- */

/* ---------- the soft glow: a faint, blurred copy of the whole picture laid over it (the Orton
   look) — the film, the prints and the type keep their edges under a light haze. Not with
   reduced motion, and not under the gate ---------- */
.soft-glow {
  position: fixed;
  inset: 0;
  z-index: 84;
  pointer-events: none;
  backdrop-filter: blur(12px) brightness(1.08) saturate(1.06);
  -webkit-backdrop-filter: blur(12px) brightness(1.08) saturate(1.06);
  opacity: 0.2;
}

html.still .soft-glow,
html.gated .soft-glow {
  display: none;
}

/* the reactor is on the page only while the music plays (music() adds html.music) */
html:not(.music) .reactor {
  display: none;
}

.reactor {
  position: fixed;
  inset: -8vmax;
  z-index: 85;
  pointer-events: none;
  mix-blend-mode: plus-lighter;
  background:
    radial-gradient(65% 50% at 50% 100%, rgba(240, 207, 123, 0.5), transparent 70%),
    radial-gradient(62% 54% at 50% 46%, rgba(255, 241, 196, 0.09), transparent 74%);
  filter: blur(28px);
  opacity: calc(var(--bass, 0) * 0.24);
  will-change: opacity;
}

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

/* the flash between two chapters' clips: a burst of warm light added over the swap (landing.ts
   writes the opacity as one board crosses the one before; the clips blur for that moment) */
.flash {
  position: fixed;
  inset: 0;
  z-index: 30;
  pointer-events: none;
  mix-blend-mode: plus-lighter;
  background: radial-gradient(
    80% 70% at 50% 50%,
    rgba(255, 241, 205, 0.55),
    rgba(240, 207, 123, 0.18) 50%,
    transparent 78%
  );
  opacity: 0;
  will-change: opacity;
}

.still .flash {
  display: none;
}

.still .dark,
.still.first .dark {
  display: none;
}

.still .door-inner,
.still .brand,
.still .velvet {
  animation: none;
}

/* reduced motion: the door's lines fade, nothing grows */
.still .door .eyebrow,
.still .door h1,
.still .door-sub {
  animation: door-in 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

.still.first .door .eyebrow,
.still.first .door h1,
.still.first .door-sub,
.still.first .door .eyebrow.in,
.still.first .door h1.in,
.still.first .door-sub.in {
  animation: none;
}

/* ---------- the note when the presentation has been stopped by hand ---------- */

.auto-paused {
  position: fixed;
  left: 50%;
  bottom: calc(max(1.2rem, env(safe-area-inset-bottom)) + 4.2rem);
  z-index: 45;
  translate: -50% 0;
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.5rem 0.55rem 0.5rem 1.05rem;
  border: 1px solid var(--glass-edge);
  border-radius: 999px;
  color: var(--ink);
  background: rgba(13, 12, 11, 0.74);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  box-shadow: 0 24px 50px -20px rgba(0, 0, 0, 0.9);
  font-size: 0.88rem;
  white-space: nowrap;
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  pointer-events: none;
  transition:
    opacity 0.45s ease,
    transform 0.45s ease;
}

.auto-paused.shown {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.auto-paused button {
  padding: 0.42rem 0.9rem;
  border: 0;
  border-radius: 999px;
  color: #1a1408;
  background: var(--gold-2);
  font: inherit;
  font-size: 0.84rem;
  font-weight: 700;
  cursor: pointer;
}

@media (max-width: 42rem) {
  .auto-paused {
    bottom: auto;
    top: calc(var(--nav-h) + 0.7rem);
  }
}

/* ---------- the note for a reader in a hurry (attention.ts) ---------- */

.pause-note {
  width: min(92vw, 36rem);
  max-height: 90svh;
  padding: clamp(1.4rem, 4vw, 2.6rem);
  border: 1px solid rgba(247, 223, 158, 0.22);
  border-radius: var(--radius);
  color: var(--ink);
  background: rgba(22, 20, 16, 0.94);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 50px 100px -30px rgba(0, 0, 0, 0.95);
  animation: note-in 0.55s var(--ease) both;
}

.pause-note::backdrop {
  background: rgba(5, 4, 3, 0.72);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.pause-note.closing {
  animation: note-out 0.26s ease forwards;
}

@keyframes note-in {
  from {
    opacity: 0;
    transform: translate3d(0, 14px, 0) scale(0.98);
  }
}

@keyframes note-out {
  to {
    opacity: 0;
    transform: translate3d(0, 8px, 0) scale(0.99);
  }
}

.pause-note h2 {
  margin: 0.6rem 0 0.9rem;
  font-size: clamp(1.5rem, 3.4vw, 2.3rem);
  line-height: 1.08;
  text-wrap: balance;
}

.pause-note p {
  margin: 0 0 1rem;
  color: var(--ink-soft);
  text-wrap: pretty;
}

.pause-when {
  display: grid;
  gap: 0.4rem;
  margin: 1.3rem 0;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-2);
}

.pause-when input {
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--glass-edge);
  border-radius: 12px;
  color: var(--ink);
  background: var(--glass);
  color-scheme: dark;
  font: inherit;
  letter-spacing: 0;
  text-transform: none;
}

/* the two ways into the calendar, equal and side by side; the .ics line under them; the way
   out alone at the bottom, the full width of the note */
.pause-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
}

.pause-actions .btn,
.pause-exit .btn {
  display: flex;
  justify-content: center;
  width: 100%;
  text-align: center;
  white-space: nowrap;
}

.pause-fine {
  margin: 0.8rem 0 0;
  font-size: 0.8rem;
  color: var(--ink-faint);
}

.pause-exit {
  margin-top: 1.4rem;
  padding-top: 1.1rem;
  border-top: 1px solid rgba(247, 223, 158, 0.14);
}

@media (max-width: 30rem) {
  .pause-actions {
    grid-template-columns: 1fr;
  }
}

/* ---------- the loupe on a phone: a grip under the glass, so the finger never covers what it
   magnifies (landing.ts keeps the glass above the finger) ---------- */

.loupe-grip {
  display: none;
}

@media (pointer: coarse) {
  .loupe-grip {
    position: absolute;
    left: calc(var(--lx) * 100%);
    top: calc(var(--ly) * 100% + 16%);
    translate: -50% 0;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 0.9rem;
    border-radius: 999px;
    color: #1a1408;
    background: var(--gold-2);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    white-space: nowrap;
    box-shadow: 0 14px 30px -10px rgba(0, 0, 0, 0.85);
    touch-action: none;
    transition: opacity 0.3s ease;
  }

  .loupe-grip::before {
    content: "";
    width: 0.8rem;
    height: 0.8rem;
    border: 2px solid #1a1408;
    border-radius: 50%;
  }

  .loupe-shot.held .loupe-grip {
    opacity: 0.55;
  }
}

/* ---------- the reel: the photo session nobody has to book, the whole screen behind the words.
   It lives outside the stage (the stage clips and scales its scene), pinned by its own sticky box,
   and takes its place among the frames with data-at (landing.ts) ---------- */

.seq-frame.reel {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  /* motion() writes the opacity itself (the frame's weight × the board's surfacing × its
     sinking): no variable on this frame, so the videos' shadow trees are never restyled */
  opacity: 0;
  transform: none;
  filter: none;
  will-change: opacity;
  pointer-events: none;
}

.reel video {
  position: sticky;
  top: 0;
  display: block;
  width: 100%;
  height: var(--screen);
  object-fit: cover;
  background: #000;
}

.reel .reel-tall {
  display: none;
}

/* a scrim, so the words on the board stay legible over the picture */
.reel::after {
  content: "";
  position: sticky;
  top: 0;
  display: block;
  height: var(--screen);
  margin-top: calc(-1 * var(--screen));
  /* the board's own dusk at the top and the bottom does the work; this only softens the corners */
  background: radial-gradient(90% 70% at 50% 50%, transparent 45%, rgba(13, 12, 11, 0.45) 100%);
}

/* words over a moving picture keep an edge (on the velvet the shadow is invisible) */
.seq-cap {
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.55),
    0 0 28px rgba(0, 0, 0, 0.45);
}

@media (max-aspect-ratio: 1/1) {
  .reel .reel-wide {
    display: none;
  }

  /* a board with the wide cut alone shows it on a phone too, cropped to the middle */
  .reel .reel-wide:only-of-type {
    display: block;
  }

  .reel .reel-tall {
    display: block;
  }
}

/* no reel uploaded (or a broken file): the frame keeps its place, dark */
.seq-frame.reel-off video {
  visibility: hidden;
}

/* ---------- the gold cursor (cursor.ts): a faceted arrowhead over everything, its own glow, a
   short trail and a ring on a click; only where a fine pointer exists ---------- */

.kvc-on,
.kvc-on * {
  cursor: none !important;
}

.kvc-on.kvc-native input,
.kvc-on.kvc-native textarea,
.kvc-on.kvc-native [contenteditable="true"] {
  cursor: text !important;
}

/* the cursor is two fixed layers straight in the page's own stacking context (the wrapper has no
   box of its own): the light — halo, trail, rings — is added to the page with plus-lighter, so it
   brightens what it crosses; the arrow lies over it and is painted plainly */
.kvc {
  --glow: 0;
  display: contents;
}

.kvc > * {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 2147483000;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s ease;
}

/* as popovers (the top layer, over any dialog) the two layers drop the browser's popover dress:
   no box, no border, no background, pinned at the viewport's corner */
.kvc > [popover] {
  inset: auto;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  overflow: visible;
}

.kvc > [popover]:not(:popover-open) {
  display: block;
}

.kvc.shown > * {
  opacity: 1;
}

.kvc-native .kvc > * {
  opacity: 0;
}

.kvc-light {
  mix-blend-mode: screen;
  mix-blend-mode: plus-lighter;
}

.kvc-arrow {
  will-change: transform;
}

.kvc-arrow svg {
  display: block;
  margin: -2.8px 0 0 -2.8px;
  transform-origin: 2.8px 2.8px;
  transform: scale(1);
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55));
  transition: transform 0.16s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.kvc-arrow.hover svg {
  transform: scale(1.14);
}

.kvc-arrow.down svg {
  transform: scale(0.84);
  transition-duration: 0.08s;
}

/* every piece of the light is a fixed, sizeless anchor that cursor.ts moves with a translate; the
   visible disc is its ::before. The disc's size lives on the ::before on purpose: the `scale`
   property is applied BEFORE the transform's translate (CSS Transforms 2, the rendering model),
   so a scale on the anchor itself would scale its position too — the halo, the trail and the ring
   used to sit at a fraction of the pointer's coordinates and stretch out of the top-left corner */
.kvc-halo,
.kvc-ghost,
.kvc-ring {
  position: fixed;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  pointer-events: none;
  will-change: transform;
}

.kvc-halo::before,
.kvc-ghost::before,
.kvc-ring::before {
  content: "";
  position: absolute;
  border-radius: 50%;
}

/* the halo: a soft pool of gold light under the tip, a little always, wide and bright in motion */
.kvc-halo::before {
  left: -24px;
  top: -24px;
  width: 48px;
  height: 48px;
  background: radial-gradient(
    circle,
    rgba(255, 216, 130, 0.6) 0%,
    rgba(255, 196, 90, 0.22) 38%,
    rgba(255, 180, 70, 0) 70%
  );
  opacity: calc(0.3 + 0.7 * var(--glow));
  transform: scale(calc(0.5 + var(--glow) * 1.2));
}

.kvc-ghost::before {
  left: -4px;
  top: -4px;
  width: 8px;
  height: 8px;
  background: radial-gradient(circle, rgba(255, 232, 170, 0.9), rgba(233, 190, 100, 0) 72%);
  opacity: calc(var(--trail, 0) * (1 - var(--i) / 6.5) * 0.8);
  transform: scale(calc(1.1 - var(--i) * 0.13));
}

.kvc-ring::before {
  left: -14px;
  top: -14px;
  width: 28px;
  height: 28px;
  border: 1.5px solid rgba(255, 224, 150, 0.9);
  background: radial-gradient(circle, rgba(255, 210, 120, 0.35), rgba(255, 210, 120, 0) 70%);
  animation: kvc-ring 0.55s cubic-bezier(0.2, 0.7, 0.2, 1) forwards;
}

@keyframes kvc-ring {
  from {
    opacity: 0.9;
    transform: scale(0.3);
  }
  to {
    opacity: 0;
    transform: scale(1.9);
  }
}

/* a still hand: after a few seconds the arrow and its light fade away (cursor.ts adds .idle);
   the first move brings them straight back */
.kvc.shown.idle > * {
  opacity: 0;
  transition: opacity 0.9s ease;
}

.kvc.shown.idle .kvc-arrow svg {
  transform: scale(0.72);
  transition: transform 0.9s ease;
}

.still .kvc-ghost,
.still .kvc-halo,
.still .kvc-ring {
  display: none;
}

/* a resize puts the reader back at the same place in the story (landing.ts): the browser's own
   scroll anchoring would pull the other way */
body {
  overflow-anchor: none;
}

/* the door's eyebrow is one sentence in two parts (landing.ts reveals them one after the other):
   it flows and wraps as text, with the dash inline before it, not as two columns of a flex row */
.door .eyebrow {
  display: block;
  text-align: center;
}

.door .eyebrow::before {
  display: inline-block;
  vertical-align: middle;
  margin-right: 0.6rem;
}

@media (max-width: 720px) {
  .door .eyebrow::before {
    display: none;
  }
}

/* ---------- phones: a blur filter on every surfacing element is a full-screen filter per
   element per frame, and a phone's GPU cannot keep up — the story looked frozen on Android.
   There, opacity and scale carry the surfacing alone, the frames drop their drop shadows and
   the reactor stays off. ---------- */
@media (pointer: coarse), (max-width: 48rem) {
  .sa-rise,
  .film3-head,
  .door-inner,
  .seq-head,
  .seq-index,
  .seq-frame,
  .seq-foot,
  .seq-cap,
  .seq-cap > span:not(.cap-fact):not(.cap-q):not(.cta-actions),
  .seq-frame > img,
  .shot > img,
  .bubble-ai,
  .bubble-late,
  .first .door-w,
  .first .door-w.in {
    filter: none;
  }

  .swap-wrong {
    filter: grayscale(var(--k));
  }

  .swap-true {
    filter: none;
  }

  .reactor {
    display: none;
  }

  /* the velvet arrives but does not drift: a background animation restyles every frame */
  .entered .velvet {
    animation: velvet-in 4s ease 0.2s both;
  }
}

/* ---------- ?diag: the diagnostics overlay (landing.ts diag()) ---------- */
.diag {
  position: fixed;
  left: 0.5rem;
  bottom: 0.5rem;
  z-index: 1000;
  margin: 0;
  padding: 0.5rem 0.6rem;
  max-width: calc(100vw - 1rem);
  overflow: hidden;
  font:
    11px/1.35 ui-monospace,
    Menlo,
    Consolas,
    monospace;
  color: #f7dfa0;
  background: rgba(0, 0, 0, 0.72);
  border: 1px solid rgba(217, 180, 100, 0.45);
  border-radius: 0.4rem;
  white-space: pre-wrap;
  word-break: break-all;
  pointer-events: none;
}

/* ---------- nothing on the page is text to select. On a phone the button under the thumb moves
   when the screen goes full; the touch turned into a selection and the page looked stuck. The
   form's fields stay editable, buttons and links answer the first tap. ---------- */
.landing,
.landing * {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

.landing input,
.landing textarea,
.landing [contenteditable] {
  -webkit-user-select: text;
  user-select: text;
}

.landing button,
.landing a {
  touch-action: manipulation;
}

/* ---------- the last board's buttons: the meeting and the phone, under the caption ---------- */
.cta-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  margin-top: 1.1rem;
  pointer-events: auto;
}

/* the last board is the one thing on it: the caption alone, in the middle of the screen — no
   title, no picture, no day and hour, no bar */
.seq-close .seq-foot {
  grid-row: 2;
  align-self: center;
  justify-self: center;
}

.seq-close .seq-caps {
  text-align: center;
}

.seq-close .seq-cap {
  justify-items: center;
  transform-origin: 50% 50%;
}

.seq-close .seq-cap strong {
  font-size: clamp(2.1rem, min(4.8vw, 7svh), 5rem);
}

.cta-actions .btn {
  font-size: 0.95rem;
}

/* the last board speaks in order, with the narrator: „Umów spotkanie”, then its button rising
   out of the depth, then „albo zadzwoń.” and the phone (landing.ts adds .arrived as the board's
   frame settles and takes it away when the reader leaves, so a return plays it again) */
.seq-close .cta-w {
  display: inline-block;
}

.seq-close .cta-w,
.seq-close .cta-actions .btn {
  opacity: 0;
}

.seq-close.arrived .cta-w {
  animation: cta-word 1s var(--ease) both;
}

.seq-close.arrived .cta-actions .btn {
  animation: cta-rise 1.3s var(--ease) both;
}

.seq-close.arrived .cta-w[data-cta="1"] {
  animation-delay: 0.1s;
}

.seq-close.arrived .cta-actions .btn[data-cta="2"] {
  animation-delay: 1.2s;
}

.seq-close.arrived .cta-w[data-cta="3"] {
  animation-delay: 2.1s;
}

.seq-close.arrived .cta-actions .btn[data-cta="4"] {
  animation-delay: 3s;
}

@keyframes cta-word {
  from {
    opacity: 0;
    filter: blur(8px);
  }
  to {
    opacity: 1;
    filter: blur(0);
  }
}

@keyframes cta-rise {
  from {
    opacity: 0;
    transform: scale(0.72) translateY(0.3rem);
    filter: blur(10px);
  }
  to {
    opacity: 1;
    transform: none;
    filter: blur(0);
  }
}

.still .seq-close .cta-w,
.still .seq-close .cta-actions .btn {
  opacity: 1;
  animation: none;
}

/* the phone button on a desktop, after a click: the number in the button's own place */
.cta-call.shown {
  letter-spacing: 0.06em;
}

/* the last board ends the page: the company line and the documents sit under the buttons */
/* the fine print under the story: a normal block after the pinned boards, so it rises from
   below only when the visitor scrolls past the last one (the auto-scroll never goes there) */
/* the room after the story: the scroll over which the strip rises (landing.ts gives it the
   strip's height); the last board stays held on the screen through it (.held) */
.fine-room {
  height: 0;
}

.seq-close.held .seq-stage,
.seq-close.held .seq-dusk {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}

/* the strip: fixed at the foot of the screen, out of sight until the reader scrolls past the
   last board, then rising over it (--in 0 → 1, landing.ts); a few short items in one flowing
   line, dots between them, nothing broken inside an item */
.fine {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  padding: 0.9rem max(var(--gutter), var(--rail-w)) calc(0.9rem + env(safe-area-inset-bottom))
    max(var(--gutter), env(safe-area-inset-left));
  background: rgba(11, 10, 9, 0.82);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-top: 1px solid color-mix(in srgb, var(--gold) 22%, transparent);
  color: color-mix(in srgb, var(--ink-soft) 72%, transparent);
  font-size: 0.66rem;
  line-height: 1.6;
  letter-spacing: 0.03em;
  text-align: center;
  opacity: var(--in, 0);
  transform: translateY(calc((1 - var(--in, 0)) * 100%));
  pointer-events: none;
}

.fine:not([style*="--in: 0.0000"]) {
  pointer-events: auto;
}

.fine-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 0.1rem 0;
}

.fine p {
  margin: 0;
  white-space: nowrap;
}

/* the dot after every item but the last: a line that wraps ends on a dot, never starts on one */
.fine p:not(:last-child)::after {
  content: "·";
  margin: 0 0.6em;
  opacity: 0.55;
}

.fine-brand {
  color: var(--ink-soft);
  letter-spacing: 0.06em;
}

.fine a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

/* the company's registration line (KSH art. 206), word for word: a row of its own under the
   items, and the one line here allowed to wrap, so on a phone it folds instead of running past
   the edge */
.fine .fine-legal {
  margin-top: 0.3rem;
  white-space: normal;
  text-wrap: balance;
}
