/* =========================================================================
   Aetheron — aetheron.cz  ·  v3, glass merge
   Single stylesheet. No framework, no build step.

   Colour discipline: --brand (#1081fa) appears in exactly six roles.
     1. primary CTA fill          .btn--primary
     2. the 3:00 timeline tick    .tl__step--key
     3. the comparison grip       .cmp__grip
     4. form input focus ring     .field :focus
     5. nav + footer underline    .nav__links / .footer__col
     6. recommended tier CTA      .tier--rec .btn--primary
   Nothing else. Not headings, not icons, not borders, not card backgrounds,
   not any large fill.

   Type: Newsreader for every headline, Outfit for body and UI, DM Mono for
   small labels only. Never mixed inside one line.

   The hero (section 7) is carried over untouched from the previous build.
   ========================================================================= */

/* -------------------------------------------------------------- 1. tokens */

:root {
  --cream:        #e9e3d6;
  --cream-light:  #f1ece0;
  --tile:         #fbf8f2;
  --panel:        #181818;
  --ink:          #1a1917;
  --ink-muted:    rgba(26, 25, 23, 0.60);
  --ink-faint:    rgba(26, 25, 23, 0.40);
  --line:         rgba(26, 25, 23, 0.10);
  --line-mid:     rgba(26, 25, 23, 0.18);
  --brand:        #1081fa;
  --brand-deep:   #066ede;

  /* on the dark cards */
  --on-dark:       #ffffff;
  --on-dark-soft:  rgba(255, 255, 255, 0.82);
  --on-dark-muted: rgba(255, 255, 255, 0.45);
  --on-dark-faint: rgba(255, 255, 255, 0.30);
  --on-dark-line:  rgba(255, 255, 255, 0.28);

  --serif: 'Newsreader', 'Iowan Old Style', Georgia, serif;
  --sans:  'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --mono:  'DM Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --gutter: clamp(20px, 5vw, 64px);
  --measure: 1400px;
  --pad: 22px;
  --nav-h: 58px;

  --card-radius: 20px;
  --card-pad: clamp(28px, 4.4vw, 64px);
  --r-pill: 999px;
  --r-tile: 24px;

  --sp-section: clamp(84px, 11vw, 168px);

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.25, 0.1, 0.25, 1);
  /* carries a little past the target before settling — the nav's size change
     reads as liquid rather than as a slide that stops dead */
  --ease-fluid: cubic-bezier(0.32, 1.14, 0.42, 1);
  --ease-mask: cubic-bezier(0.6, 0.01, 0.05, 0.95);
}

@media (max-width: 760px) { :root { --pad: 12px; } }

/* -------------------------------------------------------------- 2. reset */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 100px;
  /* `clip`, not `hidden`: overflow-x:hidden forces the other axis to `auto`,
     which turns the element into a scroll container and breaks fixed/sticky. */
  overflow-x: clip;
}
html.is-locked { overflow: hidden; }

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink-muted);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.7;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-hyphens: auto;
  hyphens: auto;
}

img, video, svg { display: block; max-width: 100%; }
img { height: auto; }

h1, h2, h3 {
  font-family: var(--serif);
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
  -webkit-hyphens: auto;
  hyphens: auto;
}
h1 { font-weight: 200; font-size: clamp(38px, 6.2vw, 82px); line-height: 1.05; letter-spacing: -0.03em; }
h2 { font-weight: 300; font-size: clamp(30px, 4vw, 56px);  line-height: 1.1;  letter-spacing: -0.025em; }
h3 { font-weight: 300; font-size: clamp(22px, 2.2vw, 30px); line-height: 1.2; letter-spacing: -0.02em; }

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
button, input, textarea { font: inherit; color: inherit; }

:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 2px; }
::selection { background: var(--ink); color: var(--cream); }

.skip { position: absolute; left: -9999px; top: 0; z-index: 300;
        background: var(--ink); color: var(--cream); padding: 12px 20px; }
.skip:focus { left: 8px; top: 8px; }

.vh { position: absolute !important; width: 1px; height: 1px; margin: -1px;
      padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ------------------------------------------------------------- 3. layout */

.wrap { width: 100%; max-width: var(--measure); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: var(--sp-section); }

.label {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--ink-faint);
}

.lede { font-size: clamp(16px, 1.4vw, 19px); line-height: 1.65; max-width: 52ch; color: var(--ink-muted); }

.head {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px clamp(32px, 6vw, 96px);
  margin-bottom: clamp(44px, 6vw, 84px);
}
@media (min-width: 900px) { .head { grid-template-columns: 7fr 5fr; align-items: end; } }

/* ================================================================ 4. GLASS
   Taken from the green build verbatim. It is built from white gradients and
   backdrop-filter, so it is palette-agnostic and needs no tinting on cream.
   The ::after refraction stop is the one change: neutralised from the green
   build's cool green to a warm grey so it sits correctly here. */

.glass {
  position: relative;
  background: linear-gradient(178deg,
      rgba(255, 255, 255, 0.62) 0%,
      rgba(255, 255, 255, 0.34) 42%,
      rgba(238, 233, 223, 0.40) 100%);
  backdrop-filter: blur(22px) saturate(185%) brightness(1.06);
  -webkit-backdrop-filter: blur(22px) saturate(185%) brightness(1.06);
  border: 1px solid rgba(255, 255, 255, 0.58);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    inset 0 -1px 0 rgba(255, 255, 255, 0.30),
    inset 0 0 22px rgba(255, 255, 255, 0.22),
    0 1px 2px rgba(74, 62, 44, 0.06),
    0 10px 30px rgba(74, 62, 44, 0.10),
    0 26px 60px rgba(74, 62, 44, 0.07);
}

.glass::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; mix-blend-mode: screen;
  background: linear-gradient(180deg,
      rgba(255, 255, 255, 0.55) 0%,
      rgba(255, 255, 255, 0.10) 26%,
      transparent 52%);
}

.glass::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(168deg,
      transparent 58%,
      rgba(214, 208, 196, 0.20) 82%,
      rgba(232, 222, 204, 0.30) 100%);
}

/* ------------------------------------------------------------ 5. buttons */

.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 15px 30px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.005em;
  cursor: pointer;
  /* isolate so the specular ::before blends against this button only, and so
     its z-index:-1 stays above the button's own fill */
  isolation: isolate;
  transition: background-color 500ms ease-out, border-color 500ms ease-out, color 500ms ease-out;
}

/* ---- the flat fallback. This is what ships wherever backdrop-filter is
   unavailable, so it has to be a complete button on its own, never a
   transparent shape that disappears into whatever is behind it. ---- */

/* BLUE 1 of 6 — the primary call to action */
.btn--primary { background: var(--brand); color: #fff; border-color: transparent; }
.btn--primary:hover { background: var(--brand-deep); }

.btn--outline { background: transparent; color: var(--on-dark); border-color: var(--on-dark-line); }
.btn--outline:hover { border-color: rgba(255, 255, 255, 0.6); }

.btn--quiet, .btn--ink { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--quiet:hover, .btn--ink:hover { border-color: var(--ink); }

/* ---- liquid glass. Two variants, because one clear style cannot serve both
   surfaces: a clear primary next to a clear secondary has no hierarchy left.
   Default rules target the dark surfaces (hero card, contact panel); .on-light
   raises the tint for cream so the button does not wash out. ---- */

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {

  .btn--primary,
  .btn--outline,
  .btn--quiet,
  .btn--ink {
    transition: transform 0.4s var(--ease),
                box-shadow 0.4s var(--ease),
                background 0.4s var(--ease),
                border-color 0.4s var(--ease);
  }

  .btn--primary::before,
  .btn--outline::before,
  .btn--quiet::before,
  .btn--ink::before {
    content: ''; position: absolute; inset: 0;
    border-radius: inherit; pointer-events: none;
    mix-blend-mode: screen;
    /* the label is a bare text node and cannot be raised above a positioned
       pseudo-element, so the highlight goes under it instead — otherwise
       screen-blending washes out dark text on the cream variants */
    z-index: -1;
  }

  /* ---------- primary: blue-tinted glass ---------- */
  .btn--primary {
    color: #fff;
    background: linear-gradient(178deg,
        rgba(56, 150, 255, 0.72)  0%,
        rgba(16, 129, 250, 0.56) 45%,
        rgba(6, 110, 222, 0.62) 100%);
    backdrop-filter: blur(16px) saturate(190%);
    -webkit-backdrop-filter: blur(16px) saturate(190%);
    border: 1px solid rgba(255, 255, 255, 0.34);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.55),
      inset 0 -1px 0 rgba(255, 255, 255, 0.10),
      inset 0 0 18px rgba(255, 255, 255, 0.14),
      0 2px 6px rgba(6, 52, 110, 0.18),
      0 12px 30px rgba(6, 52, 110, 0.24);
  }

  .btn--primary::before {
    background: linear-gradient(180deg,
        rgba(255, 255, 255, 0.42) 0%,
        rgba(255, 255, 255, 0.08) 34%,
        transparent 58%);
  }

  .btn--primary:hover {
    background: linear-gradient(178deg,
        rgba(56, 150, 255, 0.80)  0%,
        rgba(16, 129, 250, 0.64) 45%,
        rgba(6, 110, 222, 0.70) 100%);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.55),
      inset 0 -1px 0 rgba(255, 255, 255, 0.10),
      inset 0 0 18px rgba(255, 255, 255, 0.14),
      0 2px 8px rgba(6, 52, 110, 0.20),
      0 16px 42px rgba(6, 52, 110, 0.28);
  }

  /* on cream the tint has to carry itself — at 0.72 it reads as pale blue */
  .btn--primary.on-light {
    background: linear-gradient(178deg,
        rgba(56, 150, 255, 0.90)  0%,
        rgba(16, 129, 250, 0.82) 45%,
        rgba(6, 110, 222, 0.86) 100%);
    border: 1px solid rgba(255, 255, 255, 0.48);
  }

  .btn--primary.on-light:hover {
    background: linear-gradient(178deg,
        rgba(56, 150, 255, 0.98)  0%,
        rgba(16, 129, 250, 0.90) 45%,
        rgba(6, 110, 222, 0.94) 100%);
  }

  /* ---------- secondary: clear glass ---------- */
  .btn--outline {
    color: #fff;
    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.16) 0%,
        rgba(255, 255, 255, 0.07) 50%,
        rgba(255, 255, 255, 0.03) 100%);
    backdrop-filter: blur(16px) saturate(160%);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
    border: 1px solid rgba(255, 255, 255, 0.28);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.30),
      0 8px 24px rgba(0, 0, 0, 0.10);
  }

  .btn--outline::before {
    background: linear-gradient(180deg,
        rgba(255, 255, 255, 0.21) 0%,
        rgba(255, 255, 255, 0.04) 34%,
        transparent 58%);
  }

  .btn--outline:hover {
    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.22) 0%,
        rgba(255, 255, 255, 0.13) 50%,
        rgba(255, 255, 255, 0.09) 100%);
    border-color: rgba(255, 255, 255, 0.45);
  }

  /* the same clear glass on cream: whites swapped for ink at low opacity,
     because a white-on-white edge has nothing to define it */
  .btn--quiet, .btn--ink, .btn--outline.on-light {
    color: var(--ink);
    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.55) 0%,
        rgba(255, 255, 255, 0.28) 100%);
    backdrop-filter: blur(16px) saturate(160%);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
    border: 1px solid rgba(26, 25, 23, 0.12);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.70),
      0 8px 24px rgba(74, 62, 44, 0.10);
  }

  .btn--quiet::before, .btn--ink::before, .btn--outline.on-light::before {
    background: linear-gradient(180deg,
        rgba(255, 255, 255, 0.21) 0%,
        rgba(255, 255, 255, 0.04) 34%,
        transparent 58%);
  }

  .btn--quiet:hover, .btn--ink:hover, .btn--outline.on-light:hover {
    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.61) 0%,
        rgba(255, 255, 255, 0.34) 100%);
    border-color: rgba(26, 25, 23, 0.28);
  }

  /* ---------- states ---------- */
  /* the only transform allowed on a button anywhere on the site: a glass
     surface that does not answer a press reads as dead */
  .btn--primary:active,
  .btn--outline:active,
  .btn--quiet:active,
  .btn--ink:active {
    transform: scale(0.985);
    transition-duration: 0.15s;
  }
  .btn--primary:active {
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.55),
      inset 0 0 18px rgba(255, 255, 255, 0.14),
      0 1px 3px rgba(6, 52, 110, 0.16),
      0 4px 12px rgba(6, 52, 110, 0.18);
  }
  .btn--outline:active { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.30), 0 3px 10px rgba(0, 0, 0, 0.08); }
  .btn--quiet:active, .btn--ink:active, .btn--outline.on-light:active {
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.70), 0 3px 10px rgba(74, 62, 44, 0.08);
  }

  @media (prefers-reduced-motion: reduce) {
    .btn--primary:active, .btn--outline:active,
    .btn--quiet:active, .btn--ink:active { transform: none; }
  }
}

.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }

.arrow { width: 11px; height: 11px; flex: 0 0 auto; transition: transform 0.4s ease-out; }

/* ---------------------------------------------------------------- 6. nav */

.nav-shell {
  position: fixed;
  top: calc(var(--pad) + 12px);
  left: 0; right: 0;
  z-index: 100;
  display: flex;
  justify-content: center;
  padding: 0 var(--pad);
  pointer-events: none;
}

.nav {
  pointer-events: auto;
  width: 100%;
  max-width: 1180px;
  height: var(--nav-h);
  border-radius: var(--r-pill);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 12px 0 18px;
  /* one duration across all four: at 620/460/460 the width was still
     travelling after the height had stopped, which reads mechanical. Water
     changes shape as a single body. */
  transition: max-width     560ms var(--ease-fluid),
              height        560ms var(--ease-fluid),
              padding       560ms var(--ease-fluid),
              border-radius 560ms var(--ease-fluid);
  transform-origin: 50% 0;
}

.nav__logo { display: flex; align-items: center; flex: 0 0 auto; }
.nav__logo img { height: 26px; width: auto; transition: height 420ms var(--ease); }

/* centre links, written as a sentence — the commas live inside the anchors */
.nav__links {
  display: flex;
  align-items: baseline;
  gap: 5px;
  margin: 0 auto;
  white-space: nowrap;
}
.nav__links a {
  position: relative;
  font-weight: 500;
  font-size: clamp(14px, 1.1vw, 17px);
  letter-spacing: -0.01em;
  color: var(--ink);
  padding-block: 2px;
}
/* BLUE 5 of 6 — underline wipe, nav and footer only */
.nav__links a::after,
.footer__col a::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--brand);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 400ms var(--ease-soft);
}
.nav__links a:hover::after,
.footer__col a:hover::after { transform: scaleX(1); }

.nav__right { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; margin-left: auto; }

/* the one link that converts stays visible in the minimized pill */
.nav__keep { font-weight: 500; font-size: 14px; color: var(--ink); white-space: nowrap; padding: 0 4px; }

/* ---- language toggle, sliding thumb ---- */
.lang {
  position: relative;
  display: flex;
  align-items: center;
  padding: 3px;
  border-radius: var(--r-pill);
  background: rgba(26, 25, 23, 0.055);
  box-shadow: inset 0 1px 2px rgba(26, 25, 23, 0.07),
              inset 0 -1px 0 rgba(255, 255, 255, 0.6);
}
.lang__thumb {
  position: absolute;
  top: 3px; left: 3px;
  width: 40px; height: calc(100% - 6px);
  border-radius: var(--r-pill);
  background: linear-gradient(180deg, #ffffff, #F4EFE6);
  box-shadow: 0 1px 2px rgba(74, 62, 44, 0.16), inset 0 1px 0 rgba(255, 255, 255, 1);
  transition: transform 520ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.lang.is-en .lang__thumb { transform: translateX(40px); }
.lang__opt {
  position: relative; z-index: 1;
  width: 40px; height: 28px;
  border: 0; background: none; cursor: pointer;
  font-family: var(--sans);
  font-size: 11px; font-weight: 600; letter-spacing: 0.06em;
  color: var(--ink-faint);
  transition: color 300ms var(--ease-soft);
}
.lang__opt.is-on { color: var(--ink); }

.nav__cta { height: 38px; padding: 0 18px; font-size: 14px; }

/* ---- burger ---- */
.burger {
  position: relative;
  display: grid;
  place-content: center;
  gap: 5px;
  width: 40px; height: 40px;
  flex: 0 0 auto;
  padding: 0; border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.5);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), inset 0 -1px 0 rgba(26, 25, 23, 0.05);
  cursor: pointer;
  color: var(--ink);
  /* out at the top of the page — it blurs in, it does not fade in */
  opacity: 0;
  filter: blur(6px);
  transform: scale(0.5);
  pointer-events: none;
  transition: opacity 350ms var(--ease), filter 350ms var(--ease), transform 350ms var(--ease);
}
.burger span {
  display: block;
  width: 17px; height: 1.6px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 380ms var(--ease), opacity 200ms;
}

/* ---- state 2: the pill ---- */
.nav.is-min { max-width: 520px; height: 48px; padding: 0 8px 0 14px; }
.nav.is-min .nav__logo img { height: 23px; }

/* the groups that go out. blur, not fade. */
.nav__links, .nav__lang, .nav__cta {
  transition: opacity 350ms var(--ease), filter 350ms var(--ease), transform 350ms var(--ease);
}
.nav.is-min .nav__links,
.nav.is-min .nav__lang,
.nav.is-min .nav__cta {
  opacity: 0;
  filter: blur(6px);
  transform: scale(0.94);
  pointer-events: none;
  position: absolute;
  left: 50%;
  /* left:50% puts the LEFT edge on the centre line, so the group hung 26px
     past the pill's right edge on the way out. Pull it back by half itself. */
  translate: -50%;
}
.nav.is-min .nav__lang, .nav.is-min .nav__cta { left: auto; right: 64px; translate: none; }

.nav.is-min .burger { opacity: 1; filter: blur(0); transform: scale(1); pointer-events: auto; }

/* ══════════════════════ MARKETING CHAPTER ═══════════════════════════════
   No portfolio, so no portfolio layout. The web chapter can afford density
   because it has seventeen real screenshots; this one has nothing, so it
   goes the other way — very little text at display size, one idea per
   screen, and the only surface is the field you type into.

   Everything here reuses the chapter's own scale: .fx__title for the claim,
   the .gal-note mask for the lines, .best-cta__btn for the button. Nothing
   new is invented visually.
   ═══════════════════════════════════════════════════════════════════════ */

.aud { margin-top: clamp(72px, 9vw, 128px); }

/* the two lines rise out of a mask, same move as the gallery note but at
   title scale — this is the peak of the chapter */
.aud__l { overflow: hidden; margin: 0; }
.js .aud__l > span {
    display: block;
    font-family: var(--serif);
    font-weight: 200;
    font-size: clamp(28px, 4.4vw, 60px);
    line-height: 1.1;
    letter-spacing: -0.03em;
    color: #fff;
    transform: translateY(105%);
    transition: transform 900ms var(--ease);
}
.aud__l:nth-child(2) > span {
    color: rgba(255, 255, 255, 0.55);
    transition-delay: 120ms;
}
.aud.is-in .aud__l > span { transform: translateY(0); }

/* ---- the field: the one interactive thing in the chapter --------------- */

.js .aud__form {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: clamp(34px, 4vw, 54px);
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 700ms var(--ease) 320ms, transform 700ms var(--ease) 320ms;
}
.aud.is-in .aud__form { opacity: 1; transform: none; }

.aud__field {
    flex: 1 1 320px;
    min-width: 0;
    display: block;
    position: relative;
}
/* the same glass as .best-arrow, stretched into a pill */
.aud__field input {
    width: 100%;
    height: 54px;
    padding: 0 22px;
    border-radius: var(--r-pill);
    font-family: var(--sans);
    font-size: 16px;
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.28);
    background: rgba(255, 255, 255, 0.06);
    backdrop-filter: blur(14px) saturate(160%);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
    transition: border-color 300ms var(--ease), background 300ms var(--ease);
}
.aud__field input::placeholder { color: rgba(255, 255, 255, 0.38); }
.aud__field input:hover  { border-color: rgba(255, 255, 255, 0.42); }
.aud__field input:focus  {
    outline: none;
    border-color: rgba(255, 255, 255, 0.72);
    background: rgba(255, 255, 255, 0.10);
}
.aud__field input:focus-visible { outline: 2px solid rgba(255,255,255,0.75); outline-offset: 3px; }

.aud__go { flex: 0 0 auto; border: 1px solid rgba(255, 255, 255, 0.40); cursor: pointer; }

.js .aud__fine {
    margin: 16px 0 0;
    font-size: 14px;
    color: rgba(255, 255, 255, 0.45);
    opacity: 0;
    transition: opacity 700ms var(--ease) 460ms;
}
.aud.is-in .aud__fine { opacity: 1; }

/* ---- what is on the page: three lines, hairlines, no cards ------------- */

.aud__list {
    list-style: none;
    margin: clamp(56px, 7vw, 96px) 0 0;
    padding: 0;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.js .aud__row {
    display: flex;
    align-items: baseline;
    gap: clamp(16px, 2.4vw, 34px);
    padding: clamp(20px, 2.6vw, 32px) 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 620ms var(--ease), transform 620ms var(--ease);
    transition-delay: calc(560ms + var(--i) * 120ms);
}
.aud.is-in .aud__row { opacity: 1; transform: none; }

.aud__n {
    flex: 0 0 auto;
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: 0.12em;
    color: rgba(255, 255, 255, 0.35);
}
.aud__t { overflow: hidden; margin: 0; }
.aud__t > span {
    display: block;
    font-family: var(--serif);
    font-weight: 200;
    font-size: clamp(20px, 2.4vw, 34px);
    line-height: 1.25;
    letter-spacing: -0.02em;
    color: rgba(255, 255, 255, 0.92);
}

/* the label is read by screen readers and indexed, it just is not drawn */
.vh {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    clip-path: inset(50%);
    overflow: hidden;
    white-space: nowrap;
}

@media (max-width: 700px) {
    .aud__go { width: 100%; }
    .aud__row { gap: 14px; }
}

@media (prefers-reduced-motion: reduce) {
    .aud__l > span { transform: none; }
    .aud__form, .aud__fine, .aud__row { opacity: 1; transform: none; transition: none; }
}

/* ---- the settle ----------------------------------------------------- */
/* A bead of water pulled into shape: the bar is thrown out of proportion by
   the size change, then oscillates back with the amplitude falling off each
   swing. Driven from the top edge, which is the one the layout pins, so the
   bottom edge does the moving — a surface, not a bounce.

   scale / rotate / translate are used as individual properties rather than
   one `transform`, so the squash and the slosh can run as two animations at
   different periods. A single transform channel could only ever give a
   symmetric pulse, and water is never symmetric.

   JS adds these classes on the state change only and drops them on
   animationend; nothing runs at rest. */

.nav.is-settling,
.nav.is-swelling {
  will-change: scale, rotate, translate;
  /* The sheen below is a screen-blended white sheet at inset:0, so any offset
     slides a bright sliver out past the rounded edge. Clip while the shape is
     moving — and only while it is moving, so a focus ring at rest still has
     its 3px offset to sit in. */
  overflow: hidden;
}

.nav.is-settling {
  animation: nav-bead  1100ms ease-in-out,
             nav-slosh 1320ms ease-in-out;
}

.nav.is-swelling {
  /* opening out is the calmer move: the breath, none of the slosh */
  animation: nav-swell 980ms ease-in-out;
}

@keyframes nav-bead {
   0%  { scale: 1     1;     }
  16%  { scale: 1.028 0.912; }   /* caught wide as it lands */
  34%  { scale: 0.986 1.048; }   /* and drawn tall on the rebound */
  50%  { scale: 1.012 0.976; }
  66%  { scale: 0.995 1.014; }
  80%  { scale: 1.004 0.993; }
  91%  { scale: 0.999 1.004; }
 100%  { scale: 1     1;     }
}

@keyframes nav-slosh {
  /* deliberately out of phase with the squash, and slower, so the two never
     cross zero together */
   0%  { rotate:  0deg;     translate: 0; }
  20%  { rotate: -0.30deg;  translate: -2.2px; }
  44%  { rotate:  0.20deg;  translate:  1.5px; }
  66%  { rotate: -0.10deg;  translate: -0.7px; }
  84%  { rotate:  0.04deg;  translate:  0.25px; }
 100%  { rotate:  0deg;     translate: 0; }
}

@keyframes nav-swell {
   0%  { scale: 1     1;     }
  22%  { scale: 0.982 1.045; }
  46%  { scale: 1.010 0.980; }
  70%  { scale: 0.996 1.008; }
  88%  { scale: 1.002 0.997; }
 100%  { scale: 1     1;     }
}

/* the specular edge rides the surface while it settles. .glass::before is the
   top highlight; only its offset and weight move, the gradient is inherited */
.nav.is-settling::before { animation: nav-sheen 1100ms ease-in-out; }

@keyframes nav-sheen {
   0%  { translate: 0  0;   opacity: 1;    }
  16%  { translate: 0  14%; opacity: 0.70; }
  34%  { translate: 0 -10%; opacity: 1;    }
  50%  { translate: 0  6%;  opacity: 0.85; }
  66%  { translate: 0 -3%;  opacity: 1;    }
 100%  { translate: 0  0;   opacity: 1;    }
}

/* Below 1000px the bar is permanently minimized, so there is no size change
   to settle from — the ripple would read as a twitch. */
@media (max-width: 999px) {
  .nav.is-settling, .nav.is-swelling { animation: none; }
  .nav.is-settling::before { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  .nav.is-settling, .nav.is-swelling { animation: none; }
  .nav.is-settling::before { animation: none; }
}

/* below 1000px the nav is permanently minimized: logo, Kontakt, burger */
@media (max-width: 999px) {
  .nav { max-width: 520px; height: 48px; padding: 0 8px 0 14px; }
  .nav .nav__links, .nav .nav__lang, .nav .nav__cta {
    opacity: 0; filter: blur(6px); transform: scale(0.94);
    pointer-events: none; position: absolute; left: 50%; translate: -50%;
  }
  .nav .nav__lang, .nav .nav__cta { left: auto; right: 64px; translate: none; }
  /* `.nav .burger` on purpose: the base .burger rule sets these at equal
     specificity and would win on source order, leaving it unclickable. */
  .nav .burger { opacity: 1; filter: blur(0); transform: scale(1); pointer-events: auto; }
  .nav .nav__logo img { height: 23px; }
}
/* Kontakt is redundant on the full bar (it is already in the sentence and
   the CTA), but in the minimized pill it is the one link that converts,
   so it stays beside the burger. */
@media (min-width: 1000px) { .nav:not(.is-min) .nav__keep { display: none; } }

/* ------------------------------------------------ 6b. fullscreen menu */
/* A takeover, not a dropdown: opaque --panel over the whole viewport, no
   glass, no blur of the page behind, no panel edge. The page is gone. */

.menu {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  flex-direction: column;
  padding: clamp(28px, 6vw, 88px);
  background: var(--panel);
  color: var(--cream);
  overflow: hidden;

  /* Closed, the panel is cut down to the navbar's own footprint, so opening
     reads as the bar unfolding rather than a curtain dropping. JS writes these
     four the moment you click, because the pill's rect moves with scroll,
     language and viewport — there is nothing safe to hard-code.
     The fallback is the old top-down wipe, for a panel that is never seated. */
  --m-top: 0px;
  --m-right: 0px;
  --m-bottom: 100%;
  --m-left: 0px;
  --m-r: 0px;

  visibility: hidden;
  opacity: 0;
  clip-path: inset(var(--m-top) var(--m-right) var(--m-bottom) var(--m-left)
                   round var(--m-r));

  /* the clip repaints the whole panel per frame, so it is promoted for the
     duration by JS rather than carrying a permanent layer */
  contain: paint;

  /* closing: it folds back into the pill first, and only lets go of the
     colour once it is the size of the pill again */
  transition: clip-path 560ms var(--ease),
              opacity 260ms var(--ease-soft) 520ms,
              visibility 0s linear 780ms;
}

.menu.is-open {
  visibility: visible;
  opacity: 1;
  clip-path: inset(0 0 0 0 round 0);
  /* Opening: the pill takes the panel's colour first, and only then does the
     panel unfold out of it. 130ms of linear opacity read as a flash — long
     enough to see the half-transparent grey, too short to read as a change.
     300ms on an ease-soft lands as one continuous darkening. */
  transition: clip-path 560ms var(--ease) 260ms,
              opacity 300ms var(--ease-soft),
              visibility 0s;
}

/* the list takes the space between the close button and the footer and
   centres inside it, so six items plus the contact block still fit at 100svh */
.menu__links {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
}

.menu__mask {
  display: block;
  overflow: hidden;
  /* the size lives here, not on the <a>, so the 0.12em headroom below is
     relative to the display size rather than the inherited 17px body */
  font-size: clamp(28px, 4.4vw, 56px);
  /* the mask clips, so descenders on g j y need headroom that costs no layout */
  padding-top: 0.12em;
  margin-top: -0.12em;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
.menu__mask > a {
  display: block;
  font-family: var(--serif);
  font-weight: 300;
  font-size: inherit;
  line-height: 1.15;
  letter-spacing: -0.025em;
  color: var(--cream);
  transform: translateY(110%);
  transition: transform 0.6s var(--ease);
}
/* the stagger starts 0.2s in, once the wipe is already underway */
.menu.is-open .menu__mask > a {
  transform: none;
  /* the colour beat plus a fifth of the unfold before the first line moves */
  transition-delay: calc(380ms + var(--i) * 55ms);
}
/* the hover shift lives on an inner span so it cannot fight the mask */
.menu__mask > a > span { display: inline-block; transition: transform 0.4s ease-out; }
.menu__links a:hover > span { transform: translateX(12px); }

/* a short viewport — an iPhone SE is 667px — has no room for the large scale */
@media (max-height: 700px) {
  .menu__mask { font-size: clamp(24px, 6vw, 34px); }
  .menu { padding: clamp(20px, 5vw, 40px); }
}

.menu__foot {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px 32px;
}
.menu__contact {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: var(--sans);
  font-size: 15px;
  color: var(--cream);
  opacity: 0.6;
}
.menu__contact a { transition: opacity 0.3s var(--ease-soft); }
.menu__contact a:hover { opacity: 0.75; }

/* ---- the bar hands over to the panel ---------------------------------- */
/* There is no separate close button any more. The bar loses its body, the
   burger crosses to the panel's cream and folds into an X, and it stays
   exactly where it has always been rather than jumping to a corner.

   The z-index has to go on .nav-shell, not .nav: the shell is position:fixed
   with a z-index of its own, so it is a stacking context and nothing inside
   it can climb over the panel on its own. */
html.is-menu .nav-shell { z-index: 320; }

html.is-menu .nav {
  background: none;
  border-color: transparent;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  /* held until the panel is opaque — strip the glass any earlier and you are
     looking straight through the bar while the colour is still arriving */
  transition: background 220ms linear 300ms,
              border-color 220ms linear 300ms,
              box-shadow 220ms linear 300ms;
}

/* the specular is the brightest thing under the darkening panel, so it is
   what makes a plain cross-fade look muddy. It leaves with the colour. */
html.is-menu .nav::before,
html.is-menu .nav::after { opacity: 0; transition: opacity 300ms var(--ease-soft); }

html.is-menu .nav__logo,
html.is-menu .nav__links,
html.is-menu .nav__keep,
html.is-menu .nav__lang,
html.is-menu .nav__cta {
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms var(--ease-soft);
}

html.is-menu .burger {
  opacity: 1;
  filter: none;
  transform: none;
  pointer-events: auto;
  color: var(--cream);
  background: rgba(255, 255, 255, 0.08);
  box-shadow: none;
  transition: color 300ms var(--ease-soft) 200ms,
              background 300ms var(--ease-soft) 200ms,
              box-shadow 300ms var(--ease-soft) 200ms,
              opacity 220ms var(--ease),
              filter 220ms var(--ease),
              transform 220ms var(--ease);
}
/* .burger span already carries transition: transform 380ms, so the two bars
   swing into the cross rather than snapping */
html.is-menu .burger span:nth-child(1) { transform: translateY(3.3px) rotate(45deg); }
html.is-menu .burger span:nth-child(2) { transform: translateY(-3.3px) rotate(-45deg); }

@media (prefers-reduced-motion: reduce) {
  html.is-menu .burger span { transition: none; }
}

/* the toggle has to invert on the dark takeover */
.menu .lang { background: rgba(255, 255, 255, 0.09); box-shadow: none; }
.menu .lang__thumb { background: rgba(255, 255, 255, 0.92); box-shadow: none; }
.menu .lang__opt { color: rgba(255, 255, 255, 0.55); }
.menu .lang__opt.is-on { color: var(--panel); }

/* =========================================================== 7. HERO
   Carried over untouched from the previous build. Do not restyle, do not
   apply .glass, do not change the scrim. */

.hero {
  padding: 20px;
  height: 100svh;
  min-height: 620px;
}

.hero__card {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: var(--card-radius);
  overflow: hidden;
  background: var(--panel);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.18);
  outline: 1px solid rgba(0, 0, 0, 0.06);
  outline-offset: -1px;
}

.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* The watermark is cropped out of the file itself now (1440x758), so the
     old transform: scale(1.2) crop is gone — it cost 20% of the frame and
     softened the image by upscaling. object-fit handles the rest. */
  object-fit: cover;
}

/* Angled, not vertical: heavy where the copy sits, clearing to almost nothing
   on the right so the footage still reads as footage.
   The supplied clip is a bright white-walled room rather than the mid-grey the
   original spec assumed, so the stops are pushed darker than 0.88/0.62/0.08 —
   otherwise white type on the left simply does not hold. A second bottom-up
   wash protects the copy, which sits in the lower-left corner.
   If you swap in darker footage, lighten these again. */
.hero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top,
      rgba(15, 14, 12, 0.55) 0%,
      rgba(15, 14, 12, 0.12) 46%,
      rgba(15, 14, 12, 0) 70%),
    linear-gradient(105deg,
      rgba(15, 14, 12, 0.92) 0%,
      rgba(15, 14, 12, 0.72) 42%,
      rgba(15, 14, 12, 0.14) 100%);
}

.hero__content {
  position: absolute;
  left: 0; bottom: 0;
  width: 100%;
  padding: var(--card-pad);
}

.hero h1 {
  color: var(--on-dark);
  max-width: 20ch;
}

.hero__sub {
  margin-top: clamp(18px, 2vw, 26px);
  max-width: 56ch;
  font-size: clamp(15px, 1.3vw, 18px);
  line-height: 1.6;
  color: var(--on-dark-soft);
}

.hero__cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: clamp(24px, 3vw, 36px); }

/* the stamp would collide with the copy on narrow cards */

@media (max-width: 767px) {
  .hero { padding: 0; height: 78svh; min-height: 520px; }
  .hero__card { border-radius: 0; box-shadow: none; }
}

/* --------------------------------------------- 7b. masked line reveal */
/* The one motion moment in the hero. Each line sits in an overflow-hidden
   box and slides up from below it. Padding + negative margin give the
   Czech diacritics and descenders room so they are never clipped. */

.line {
  display: block;
  overflow: hidden;
  padding-top: 0.14em;
  margin-top: -0.14em;
  padding-bottom: 0.1em;
  margin-bottom: -0.1em;
}

.line > span { display: block; transform: translateY(105%); }

.js .hero.is-ready .line > span {
  transform: none;
  transition: transform 700ms var(--ease-mask);
}
.js .hero.is-ready .line:nth-child(1) > span { transition-delay: 200ms; }
.js .hero.is-ready .line:nth-child(2) > span { transition-delay: 320ms; }
.js .hero.is-ready .line:nth-child(3) > span { transition-delay: 440ms; }

.js .hero .fade { opacity: 0; transform: translateY(12px); }
.js .hero.is-ready .fade {
  opacity: 1;
  transform: none;
  transition: opacity 700ms var(--ease-soft), transform 700ms var(--ease-soft);
  transition-delay: var(--d, 0ms);
}
.no-js .line > span { transform: none; }

/* ----------------------------------------------------------- 8. timeline */

/* BLUE 2 of 6 — only the 3:00 tick, the moment the whole page is about.
   Given more weight than the ink ticks because a 1px hairline is too small
   to register as a deliberate colour choice. */

/* -------------------------------------------- 8b. before / after slider */
/* The drag comparison, framed by a glass tile. The <input type="range"> is
   the real control: it gives pointer drag, touch drag and arrow keys for
   free, and we only mirror its value onto --pos. */

/* BLUE 3 of 6 — the grip. It is the one thing on the page you are meant to
   grab, so it carries the accent at rest rather than only on focus. */

/* the focus ring stays ink: on photography it has to be the high-contrast
   colour, and blue-on-blue would not read */

/* --- before/after entries: slider on one side, the story on the other */

@media (min-width: 940px) {
  
  /* mirror every second entry — the track sizes have to flip too, or `order`
     alone drops the slider into the narrow column */

}

/* ----------------------------------------------------------- 9. services */
/* Four glass tiles on one line: same width, same height, same baseline.
   No icons and no index numbers — the type is the only graphic element. */

.svc-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
  /* stretch, so every card takes the height of the tallest. No card may carry
     a fixed height — the longest copy sets the row height, once. */
  align-items: stretch;
}

@media (min-width: 680px)  { .svc-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .svc-grid { grid-template-columns: repeat(4, 1fr); } }

.svc {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 36px;
  border-radius: var(--r-tile);
  color: inherit;
}

.svc__name {
  position: relative;
  /* two lines reserved. "Cloud services" is one line and "Hosting in Prague"
     is two: without this the body copy starts at two different heights across
     a row that is otherwise exactly aligned. */
  display: flex;
  align-items: flex-start;
  min-height: 2.2em;
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(26px, 2.2vw, 34px);
  line-height: 1.1;
  letter-spacing: -0.025em;
  color: var(--ink);
  transition: transform 0.4s ease-out;
}

.svc__desc { position: relative; margin-top: 12px; font-size: 15px; line-height: 1.6; color: var(--ink-muted); }

.svc__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding-top: 24px;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
}

/* only these two move */
.svc:hover .svc__name { transform: translateX(6px); }
.svc:hover .svc__link .arrow { transform: translateX(6px); }

/* --------------------------------------------------- 9b. statement */
/* Sticky scroll-linked word reveal. Used ONCE on the site: it costs two
   viewport heights, and a second one would read as a tic. */

.stmt { position: relative; height: 200svh; }

.stmt__inner {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.stmt__label { margin-bottom: clamp(20px, 3vw, 34px); }

.stmt__text {
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(28px, 4.2vw, 62px);
  line-height: 1.25;
  letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 20ch;      /* forces short lines, which is the point */
  text-wrap: normal;
}

.stmt__text span {
  display: inline-block;
  opacity: 0.18;
  transform: translateY(4px);
  will-change: opacity, transform;
}

/* the whole effect is off: no sticky, no scroll handler, nothing to reveal */
@media (prefers-reduced-motion: reduce) {
  .stmt { height: auto; }
  .stmt__inner { position: static; height: auto; padding-block: var(--sp-section); }
  .stmt__text span { opacity: 1 !important; transform: none !important; }
}

/* -------------------------------------------------------------- 10. work */
/* One case per row, full-bleed. A single frame: the old build wrapped each
   dark card in a cream glass tile, so every case was double-framed. The
   screenshot carries nothing on top of it — the tag, title and facts all
   live in the panel beside it. */

/* one case visible at a time */

/* the work itself: nothing sits on top of it */

/* top LEFT, not top center: a centred crop cuts the left edge of the page,
   which is exactly where a website's headline and logo start */

/* two-tone: the first phrase carries, the rest recedes */

/* only the trailing phrase recedes — both phrases are spans now, so the
   language switch can replace each without destroying the other */

/* ----------------------------------------------------------- 11. pricing */

.price-group + .price-group { margin-top: clamp(44px, 5vw, 72px); }
.price-group__title { padding-bottom: 14px; border-bottom: 1px solid var(--line-mid); }

.price-note {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 18px clamp(24px, 4vw, 48px);
  padding: clamp(26px, 3vw, 38px) 0;
  border-bottom: 1px solid var(--line);
}
.price-note__line {
  flex: 1 1 380px;
  max-width: 46ch;
  font-size: clamp(17px, 1.7vw, 21px);
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.price-foot { margin-top: 20px; font-size: 14.5px; }

/* --- hosting tiers: hairline rules only, never cards or shadows */
.tiers { display: grid; grid-template-columns: 1fr; }
@media (min-width: 860px) {
  .tiers { grid-template-columns: repeat(3, 1fr); }
  .tier + .tier { border-left: 1px solid var(--line); }
}
@media (max-width: 859px) { .tier + .tier { border-top: 1px solid var(--line); } }

.tier { display: flex; flex-direction: column; padding: clamp(26px, 3vw, 40px) clamp(18px, 2.2vw, 32px); }
/* raised with background and padding only — no border, no shadow */
.tier--rec { background: var(--cream-light); padding-block: clamp(38px, 4.4vw, 58px); }

.tier__mark {
  min-height: 1.2em;
  font-family: var(--mono);
  font-size: 10px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.15em;
  color: var(--ink-muted);
  margin-bottom: 12px;
}
.tier__name {
  margin: 0;
  font-family: var(--sans);
  font-size: 15px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-muted);
}
.tier__price {
  display: flex; align-items: baseline;
  /* the number and its unit are separate elements, so an &nbsp; cannot hold
     them together — nowrap is what stops a price splitting across lines */
  flex-wrap: nowrap;
  gap: 4px 9px;
  margin-top: 14px;
  font-family: var(--serif); font-weight: 200;
  font-size: clamp(48px, 5vw, 72px);
  line-height: 1; letter-spacing: -0.03em;
  color: var(--ink);
}
.tier__unit { font-family: var(--sans); font-weight: 400; font-size: 14px; letter-spacing: 0; color: var(--ink-faint); white-space: nowrap; }
.tier__pitch { margin-top: 16px; font-size: 15px; line-height: 1.55; color: var(--ink-muted); max-width: 30ch; }

/* the hairline between two rows is the entire separator: no icons, no bullets */
.tier__features { margin-top: clamp(22px, 2.6vw, 30px); }
.tier__features li {
  padding: 11px 0;
  font-size: 15px; line-height: 1.45;
  color: var(--ink);
  border-top: 1px solid var(--line);
}
.tier__features li:first-child { border-top: 0; padding-top: 0; }

.tier__cta { margin-top: auto; padding-top: clamp(24px, 3vw, 34px); }
.tier__cta .btn { width: 100%; }

.tiers__foot { margin-top: clamp(22px, 2.6vw, 30px); font-size: 14px; color: var(--ink-faint); }

/* --------------------------------------------------------------- 12. why */

.why { display: grid; grid-template-columns: 1fr; border-top: 1px solid var(--line-mid); }
@media (min-width: 880px) { .why { grid-template-columns: 1fr 1fr; column-gap: clamp(40px, 6vw, 96px); } }
.why__item { padding-block: clamp(24px, 3vw, 36px); border-bottom: 1px solid var(--line); }
.why__item h3 { margin-bottom: 8px; }
.why__item p { font-size: 15.5px; line-height: 1.62; max-width: 42ch; }

/* --------------------------------------------------------------- 13. faq */

.faq { border-top: 1px solid var(--line-mid); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 24px;
  padding: clamp(18px, 2.2vw, 26px) 0;
  cursor: pointer; list-style: none;
  font-family: var(--serif); font-weight: 300;
  font-size: clamp(19px, 2vw, 26px);
  letter-spacing: -0.02em; line-height: 1.3;
  color: var(--ink);
  transition: color 400ms var(--ease-soft);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--ink-muted); }
.faq summary::after {
  content: ''; flex: 0 0 auto;
  width: 13px; height: 13px; margin-top: 9px;
  background:
    linear-gradient(var(--ink), var(--ink)) center / 100% 1px no-repeat,
    linear-gradient(var(--ink), var(--ink)) center / 1px 100% no-repeat;
  transition: transform 400ms var(--ease-soft);
}
.faq details[open] summary::after { transform: rotate(135deg); }
.faq__a { padding-bottom: clamp(20px, 2.4vw, 28px); max-width: 66ch; font-size: 16px; }
.faq__a p + p { margin-top: 12px; }

/* ----------------------------------------------------------- 14. contact */
/* Mirrors the hero card so the page bookends. */

.contact { padding: 20px; }
@media (max-width: 767px) { .contact { padding: 0; } }

.contact__card {
  background: var(--panel);
  border-radius: var(--card-radius);
  padding: clamp(32px, 5vw, 88px);
  color: var(--on-dark-soft);
}
@media (max-width: 767px) { .contact__card { border-radius: 0; } }

.contact__grid { display: grid; grid-template-columns: 1fr; gap: clamp(36px, 5vw, 80px); }
@media (min-width: 900px) { .contact__grid { grid-template-columns: 5fr 6fr; } }

.contact h2 { color: var(--on-dark); }
.contact__lede { margin-top: 18px; max-width: 44ch; font-size: 16px; line-height: 1.65; color: var(--on-dark-soft); }

.contact__direct { margin-top: clamp(28px, 3.5vw, 44px); }
.contact__direct dt { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.15em; color: var(--on-dark-muted); }
.contact__direct dd {
  margin: 5px 0 20px;
  font-family: var(--serif); font-weight: 300;
  font-size: clamp(20px, 2vw, 26px); letter-spacing: -0.02em;
  color: var(--on-dark);
}
.contact__direct a { transition: opacity 400ms var(--ease-soft); }
.contact__direct a:hover { opacity: 0.72; }

.form { display: grid; gap: 16px; }
.field { display: grid; gap: 7px; }
.field label { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.15em; color: var(--on-dark-muted); }
.field .opt { text-transform: none; letter-spacing: 0.03em; opacity: 0.7; }

.field input, .field textarea {
  width: 100%;
  padding: 13px 16px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--on-dark-line);
  border-radius: 10px;
  color: var(--on-dark);
  font-size: 16px;
  transition: border-color 500ms ease-out, background-color 500ms ease-out;
}
.field textarea { resize: vertical; min-height: 120px; line-height: 1.6; }
.field input::placeholder, .field textarea::placeholder { color: rgba(255, 255, 255, 0.34); }
.field input:hover, .field textarea:hover { border-color: rgba(255, 255, 255, 0.45); }

/* BLUE 4 of 6 — the form focus ring. #1081fa on #181818 is ~4.6:1,
   comfortably past the 3:1 WCAG asks of a non-text focus indicator. */
.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--brand);
  background: rgba(255, 255, 255, 0.09);
}
.field input:focus-visible, .field textarea:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.form__foot { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 4px; }
.form__note { font-size: 13px; line-height: 1.5; color: var(--on-dark-muted); max-width: 32ch; }

/* ------------------------------------------------------------ 15. footer */

.site-footer { background: var(--cream-light); padding: clamp(56px, 7vw, 96px) var(--pad) var(--pad); }

.footer-tile {
  max-width: var(--measure);
  margin-inline: auto;
  border-radius: var(--r-tile);
  padding: clamp(30px, 3.4vw, 52px);
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(28px, 3vw, 52px);
}
@media (min-width: 860px) { .footer-tile { grid-template-columns: 1.5fr 1fr 1fr 1fr; } }

.footer__brand { position: relative; }
.footer__brand img { height: 28px; width: auto; }
.footer__brand p { margin-top: 16px; font-size: 15px; line-height: 1.65; color: var(--ink-muted); max-width: 30ch; }

.footer__col { position: relative; display: flex; flex-direction: column; align-items: flex-start; }
.footer__col h4 {
  margin: 0 0 14px;
  font-family: var(--mono);
  font-size: 10px; font-weight: 500;
  letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--ink-faint);
}
.footer__col a, .footer__col span {
  position: relative;
  font-size: 16px;
  color: var(--ink-muted);
  padding: 6px 0;
  overflow-wrap: anywhere;
  transition: color 400ms var(--ease-soft);
}
.footer__col a { width: fit-content; }
.footer__col a:hover { color: var(--ink); }

.footer__bar {
  position: relative;
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap;
  justify-content: space-between; align-items: center;
  gap: 12px 24px;
  margin-top: 8px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-size: 13.5px;
  color: var(--ink-faint);
}

.clock { display: inline-flex; align-items: center; gap: 9px; font-family: var(--mono); font-size: 12px; letter-spacing: 0.06em; color: var(--ink-muted); }
.clock__dot { width: 5px; height: 5px; border-radius: 50%; background: var(--ink-muted); animation: tick 2s ease-in-out infinite; }
@keyframes tick { 0%, 100% { opacity: 0.25; } 50% { opacity: 0.8; } }

/* ------------------------------------------------------------ 16. motion */

.js .reveal { opacity: 0; transform: translateY(20px); }
.js .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 700ms var(--ease-soft), transform 700ms var(--ease-soft);
  transition-delay: var(--d, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .js .reveal { opacity: 1; transform: none; }
  .line > span { transform: none !important; }
  .js .hero .fade { opacity: 1; transform: none; }
  .clock__dot { animation: none; opacity: 0.6; }
  .nav__links, .nav__lang, .nav__cta, .burger, .nav { filter: none !important; }
  .menu { transition: none !important; }
  .menu__mask > a { transform: none !important; }
}

/* ================================================================ HERO BUTTONS
   Transplanted from the green build so the hero CTAs read as one family:
   neutral white glass on the video, hierarchy carried by the arrow disc on
   the primary rather than by a colour difference.

   Scoped to .hero__cta on purpose — .btn--primary is also used in the contact
   panel and the pricing page, and those keep the blue treatment.
   ============================================================================ */

.hero__cta .btn.btn--primary,
.hero__cta .btn.btn--outline {
    height: 52px;
    padding: 0 26px;
    gap: 10px;
    font-size: 0.95rem;
    font-weight: 500;
    color: #fff;
    border-radius: var(--r-pill);
    border: 1px solid rgba(255, 255, 255, 0.40);

    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.30) 0%,
        rgba(255, 255, 255, 0.14) 45%,
        rgba(255, 255, 255, 0.09) 100%);

    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);

    box-shadow:
        inset 0  1px 0 rgba(255, 255, 255, 0.65),
        inset 0 -1px 0 rgba(255, 255, 255, 0.16),
        0 6px 22px rgba(10, 22, 16, 0.22);

    transition: transform 320ms var(--ease),
                box-shadow 320ms var(--ease),
                background 320ms var(--ease);
}

/* the base .btn::before is a screen-blend sheen; the donor bakes its highlight
   into the gradient + insets instead, so switch it off here to avoid doubling */
.hero__cta .btn.btn--primary::before,
.hero__cta .btn.btn--outline::before {
    background: none;
}

.hero__cta .btn.btn--primary:hover,
.hero__cta .btn.btn--outline:hover {
    transform: translateY(-1.5px);
    border-color: rgba(255, 255, 255, 0.40);
    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.40) 0%,
        rgba(255, 255, 255, 0.20) 45%,
        rgba(255, 255, 255, 0.13) 100%);
    box-shadow:
        inset 0  1px 0 rgba(255, 255, 255, 0.65),
        inset 0 -1px 0 rgba(255, 255, 255, 0.16),
        0 10px 30px rgba(10, 22, 16, 0.28);
}

.hero__cta .btn.btn--primary:active,
.hero__cta .btn.btn--outline:active {
    transform: translateY(0) scale(0.985);
}

/* ---- the arrow disc, carried over from the green build ---- */

.hero__cta .btn--arrow { padding: 0 8px 0 26px; }

.hero__cta .arrow-circle {
    display: grid;
    place-content: center;
    width: 34px;
    height: 34px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: #fff;
    color: var(--ink);
    transition: transform 420ms var(--ease), background-color 300ms var(--ease);
}

.hero__cta .arrow-circle svg { width: 15px; height: 15px; }

.hero__cta .btn--arrow:hover .arrow-circle {
    transform: rotate(45deg) scale(1.06);
}

@media (prefers-reduced-motion: reduce) {
    .hero__cta .btn.btn--primary,
    .hero__cta .btn.btn--outline,
    .hero__cta .arrow-circle { transition-duration: 1ms; }
}

/* ---- nav CTA: the light-glass variant from the green build ----------------
   Not the hero treatment — that one is white-on-dark and would vanish against
   the cream nav once the page is scrolled. This is the donor's default
   .btn-glass: warm white gradient, ink label, sized down to sit in the bar.
   Scoped to .nav__cta so the contact-panel and pricing buttons keep blue. --- */

.nav .btn.nav__cta {
    height: 38px;
    padding: 0 17px;
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--ink);
    border-radius: var(--r-pill);

    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.72) 0%,
        rgba(255, 255, 255, 0.40) 45%,
        rgba(240, 235, 225, 0.46) 100%);

    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, 0.62);

    box-shadow:
        inset 0  1px 0 rgba(255, 255, 255, 1),
        inset 0 -1px 0 rgba(255, 255, 255, 0.34),
        0 1px 2px rgba(74, 62, 44, 0.07),
        0 6px 18px rgba(74, 62, 44, 0.09);

    transition: transform 320ms var(--ease),
                box-shadow 320ms var(--ease),
                background 320ms var(--ease);
}

/* base .btn::before is a screen-blend sheen; the donor bakes its highlight
   into the gradient + insets, so switch it off to avoid doubling */
.nav .btn.nav__cta::before { background: none; }

.nav .btn.nav__cta:hover {
    transform: translateY(-1.5px);
    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.82) 0%,
        rgba(255, 255, 255, 0.50) 45%,
        rgba(240, 235, 225, 0.56) 100%);
    box-shadow:
        inset 0  1px 0 rgba(255, 255, 255, 1),
        inset 0 -1px 0 rgba(255, 255, 255, 0.34),
        0 2px 4px rgba(74, 62, 44, 0.08),
        0 12px 28px rgba(74, 62, 44, 0.13);
}

.nav .btn.nav__cta:active { transform: translateY(0) scale(0.985); }

@media (prefers-reduced-motion: reduce) {
    .nav .btn.nav__cta { transition-duration: 1ms; }
}

/* ---- nav CTA flush to the bevel ------------------------------------------
   On the full bar the burger is invisible (opacity:0, pointer-events:none)
   but still display:grid, so it reserved ~40px of layout plus the 10px flex
   gap and held the CTA 63px off the edge. Taking it out of flow lets the CTA
   sit against the pill; it returns to flow in .is-min, where it is the
   control that actually gets used.

   Padding-right is then (nav height - button height) / 2 = (58-38)/2 = 10px,
   so the button's curve is concentric with the bar's — flush all the way
   round rather than just close on one side. .nav is already a positioning
   context via .glass, so the absolute burger anchors to it.
   ------------------------------------------------------------------------- */

@media (min-width: 1000px) {

    .nav:not(.is-min) .burger {
        position: absolute;
        right: 8px;
        top: 50%;
        margin-top: -20px;
    }

    /* -1px because .glass puts a 1px border on the bar: the vertical inset
       is measured inside it, the padding is not. Without this the right gap
       lands at 11px against 10px top and bottom. */
    .nav:not(.is-min) {
        padding-right: calc((var(--nav-h) - 38px) / 2 - 1px);
    }
}

/* ================================================================= SERVICE
   TILES — text hidden, film on two of them, row flush with the hero card
   ========================================================================= */

/* copy stays in the DOM for crawlers and screen readers, just not on screen */
.u-sr {
    position: absolute !important;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* full bleed: same 20px inset as .hero, so the row lines up with the card
   above it rather than with the narrower text column */
.svc-bleed { padding: 0 20px; }

.svc-bleed .svc-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
}

/* with the copy hidden the tiles have no intrinsic height left */
.svc-bleed .svc {
    padding: 0;
    /* both clips are 16:9 — matching the ratio means no crop at all */
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--card-radius);
    isolation: isolate;
}

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

.svc__media {
    position: absolute;
    inset: 0;
    overflow: hidden;
    border-radius: inherit;
    background: var(--panel);
}

.svc__video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transform: scale(1.01);
    transition: transform 900ms var(--ease);
}

.svc--film:hover .svc__video { transform: scale(1.05); }

/* .glass lays a light gradient under everything. On a film tile the video is
   meant to cover it, so if the video and poster both fail to paint the tile
   shows up as a pale square. This is the floor underneath: footage that has
   not arrived should read as dark, never as a blank white box. */
.svc--film { background-color: #060d0a; }
.svc--film .svc__video { background-color: #060d0a; }

/* a play affordance, since the tiles carry no visible label now */
.svc--film::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: inherit;
    pointer-events: none;
    /* the website showreel cuts to white frames, so the scrim has to carry
       the label on its own rather than just deepen already-dark footage */
    background: linear-gradient(180deg,
        rgba(8, 8, 8, 0.00) 34%,
        rgba(8, 8, 8, 0.30) 72%,
        rgba(8, 8, 8, 0.62) 100%);
}

.svc__play {
    position: absolute;
    z-index: 2;
    left: 20px;
    bottom: 20px;
    display: grid;
    place-content: center;
    width: 46px;
    height: 46px;
    border-radius: 50%;
    color: var(--ink);
    background: rgba(255, 255, 255, 0.82);
    backdrop-filter: blur(14px) saturate(180%);
    -webkit-backdrop-filter: blur(14px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, 0.7);
    box-shadow: inset 0 1px 0 rgba(255,255,255,1), 0 6px 18px rgba(10,10,10,0.24);
    transition: transform 420ms var(--ease), background-color 300ms var(--ease);
}
.svc__play svg { width: 15px; height: 15px; margin-left: 2px; }
.svc--film:hover .svc__play { transform: scale(1.08); background: #fff; }

@media (max-width: 767px) {
    .svc-bleed { padding: 0; }                 /* matches .hero at this width */
    /* two squares side by side — reads as a pair rather than a stack */
    .svc-bleed .svc-grid { grid-template-columns: repeat(2, 1fr); gap: 2px; }
    /* width: 100% is load-bearing, not tidying.

       Everything inside a film tile — .svc__media and .svc__cue — is
       position:absolute, so the tile has no in-flow content to be measured
       from. Blink stretches the grid item to its column anyway and the
       aspect-ratio then sets the height. WebKit resolves the width from the
       contents instead, finds nothing there, and the tile collapses to the
       2px its border occupies: the "small white cube" on iOS, on a page that
       looked perfect in every desktop browser.

       An explicit width removes the guess. */
    .svc-bleed .svc { border-radius: 0; aspect-ratio: 1 / 1; width: 100%; }
}

/* ================================================================== FILM
   Click a tile and its footage expands from where it sits to fill the view.
   ======================================================================= */

.film[hidden] { display: none; }

.film {
    position: fixed;
    inset: 0;
    z-index: 200;
    pointer-events: none;
}
.film.is-open { pointer-events: auto; }

.film__backdrop {
    position: absolute;
    inset: 0;
    background: #07100c;
    opacity: 0;
    transition: opacity 520ms var(--ease);
}
.film.is-open .film__backdrop { opacity: 1; }

/* Always the size of the viewport; the tile-to-fullscreen move is a
   transform off the top-left corner, so it runs on the compositor instead
   of relaying out a playing video 60 times a second. */
.film__stage {
    position: absolute;
    inset: 0;
    overflow: hidden;
    background: #07100c;
    transform-origin: 0 0;
    will-change: transform, border-radius;
    transition: transform 560ms var(--ease),
                border-radius 560ms var(--ease);
}

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

body.film-open { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
    .film__stage, .film__backdrop, .film__bar,
    .svc__video, .svc__play { transition-duration: 1ms !important; }
}

/* ---- cue row: the play disc with its label beside it --------------------- */

.svc__cue {
    position: absolute;
    z-index: 2;
    left: 18px;
    bottom: 18px;
    right: 18px;
    display: flex;
    align-items: center;
    gap: 12px;
    pointer-events: none;
}

/* the disc itself is positioned by the row now, not by the tile */
.svc__cue .svc__play {
    position: static;
    left: auto;
    bottom: auto;
}

.svc__cue-label {
    /* same face and weight as the card titles (.svc__name), scaled to sit
       beside the 46px disc rather than lead a block */
    font-family: var(--serif);
    font-size: clamp(21px, 1.9vw, 28px);
    font-weight: 300;
    letter-spacing: -0.025em;
    line-height: 1.1;
    color: #fff;
    text-shadow: 0 1px 3px rgba(8, 12, 10, 0.55), 0 2px 18px rgba(8, 12, 10, 0.45);
    /* the tile is only ~335px wide; long labels must not wrap under the disc */
    min-width: 0;
    overflow-wrap: anywhere;
}

/* ---- close the gap between the hero card and the tile row ---------------- */

#sluzby.section {
    padding-top: 32px;
    padding-bottom: clamp(56px, 7vw, 96px);
}

#sluzby .head {
    margin-bottom: 28px;
}

@media (max-width: 767px) {
    #sluzby.section { padding-top: 22px; }
    #sluzby .head   { margin-bottom: 18px; }
    .svc__cue       { left: 14px; bottom: 14px; right: 14px; gap: 10px; }
    .svc__cue-label { font-size: 20px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   FILM CHAPTERS
   The film is not a lightbox any more: it is a screen you can scroll. The
   footage stays fixed and playing, the copy rides over it on black, and the
   floating controls hand off to a shrunk bar on the way.
   ══════════════════════════════════════════════════════════════════════════ */

.film__scroll {
    position: absolute;
    inset: 0;
    z-index: 1;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    opacity: 0;
    transition: opacity 300ms var(--ease) 220ms;
}
.film.is-open .film__scroll { opacity: 1; }

/* the first screen is empty so you land on the footage, not on copy */
.film__first { height: 100svh; }

.film__body {
    position: relative;
    background: #07100c;
    box-shadow: 0 -40px 80px rgba(7, 16, 12, 0.5);
}

.fx[hidden] { display: none; }

.fx {
    max-width: 1180px;
    margin-inline: auto;
    /* top padding has to clear the fixed bar: it sits at --pad+12 and is
       48px tall, so the floor is set well below that rather than by vw */
    padding: clamp(124px, 11vw, 152px) var(--gutter) clamp(56px, 8vw, 104px);
    color: var(--on-dark);
}

.fx__kicker {
    display: block;
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.42);
    margin-bottom: 22px;
}

.fx__title {
    /* the base h1,h2,h3 rule paints headings --ink; on black that has to be
       overridden explicitly, inheriting from .fx is not enough */
    color: #fff;
    font-family: var(--serif);
    font-weight: 200;
    font-size: clamp(34px, 6vw, 76px);
    line-height: 1.04;
    letter-spacing: -0.03em;
    margin: 0 0 28px;
    max-width: 16ch;
}

.fx__lede {
    font-size: clamp(17px, 1.5vw, 21px);
    line-height: 1.62;
    color: rgba(255, 255, 255, 0.72);
    max-width: 58ch;
    margin: 0;
}

/* ---- the three points ---- */

.fx__points {
    list-style: none;
    margin: clamp(56px, 7vw, 96px) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(28px, 3.4vw, 56px);
}

.fx__points li { border-top: 1px solid rgba(255, 255, 255, 0.16); padding-top: 22px; }

.fx__points h3 {
    font-family: var(--serif);
    font-weight: 300;
    font-size: clamp(20px, 1.7vw, 25px);
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0 0 10px;
    color: #fff;
}

.fx__points p {
    font-size: 15px;
    line-height: 1.6;
    color: rgba(255, 255, 255, 0.58);
    margin: 0;
}

/* ---- cross-promo: the other division ---- */

.fx__cross {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: center;
    gap: 20px;
    /* break out of .fx's 1180px column so the tile lands on exactly the same
       footprint as the pair on the landing page: full bleed, 20px inset,
       20px gutter, two equal halves */
    margin-inline: calc(50% - 50vw);
    padding-inline: 20px;
    margin-top: clamp(72px, 9vw, 128px);
    padding-top: clamp(48px, 6vw, 80px);
    border-top: 1px solid rgba(255, 255, 255, 0.16);
}

.fx__crosscopy { padding-right: clamp(0px, 3vw, 48px); }

/* same footprint as the tile on the landing page */
.fx__crossfilm {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    padding: 0;
    border: 0;
    border-radius: var(--card-radius);
    overflow: hidden;
    background: #060d0a;
    cursor: pointer;
    isolation: isolate;
}

.fx__crossvideo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transform: scale(1.01);
    transition: transform 900ms var(--ease);
}
.fx__crossfilm:hover .fx__crossvideo { transform: scale(1.05); }

.fx__crossfilm::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(6,13,10,0) 40%, rgba(6,13,10,0.45) 100%);
}
.fx__crossfilm .svc__play { left: 18px; bottom: 18px; z-index: 2; }

/* the standalone pages use h2 here — h1 is the page title — so the rule has
   to cover both, or the heading falls back to the base ink colour and goes
   near-black on the dark band */
.fx__crosscopy h2,
.fx__crosscopy h3 {
    font-family: var(--serif);
    font-weight: 200;
    font-size: clamp(26px, 3vw, 40px);
    line-height: 1.1;
    letter-spacing: -0.025em;
    margin: 0 0 16px;
    color: #fff;
}

.fx__crosscopy p {
    font-size: 16px;
    line-height: 1.62;
    color: rgba(255, 255, 255, 0.6);
    margin: 0 0 28px;
    max-width: 40ch;
}

.fx__crosscta {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    height: 52px;
    padding: 0 8px 0 26px;
    border-radius: var(--r-pill);
    font-family: var(--sans);
    font-size: 0.95rem;
    font-weight: 500;
    color: #fff;
    cursor: pointer;
    border: 1px solid rgba(255, 255, 255, 0.28);
    background: rgba(255, 255, 255, 0.07);
    transition: background 320ms var(--ease), border-color 320ms var(--ease);
}
.fx__crosscta:hover { background: rgba(255, 255, 255, 0.13); border-color: rgba(255,255,255,0.44); }
.fx__crosscta .arrow-circle { background: #fff; color: #07100c; width: 34px; height: 34px;
    display: grid; place-content: center; border-radius: 50%; }
.fx__crosscta .arrow-circle svg { width: 15px; height: 15px; }
.fx__crosscta:hover .arrow-circle { transform: rotate(45deg); }

@media (max-width: 860px) {
    .fx__points { grid-template-columns: 1fr; gap: 26px; }
    .fx__cross  { grid-template-columns: 1fr; }
}

/* ══════════════════════ CONTROLS — state A over the video ═══════════════ */

.film__bar {
    position: absolute;
    left: 0; right: 0;
    bottom: max(28px, env(safe-area-inset-bottom, 0px));
    z-index: 4;
    display: flex;
    justify-content: center;
    padding: 0 20px;
    pointer-events: none;
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 320ms var(--ease) 240ms, transform 420ms var(--ease) 240ms;
}
.film.is-open .film__bar { opacity: 1; transform: none; }
.film.is-open .film__bar > * { pointer-events: auto; }

/* once the copy is on screen the floating CTA is redundant — the bar has one */
.film.is-past .film__bar {
    opacity: 0;
    transform: translateY(-6px) scale(0.96);
    transition: opacity 220ms var(--ease), transform 320ms var(--ease);
    pointer-events: none;
}
.film.is-past .film__bar > * { pointer-events: none; }

/* ══════════════════════ CONTROLS — state B, the shrunk bar ══════════════ */

.film__top {
    position: absolute;
    top: calc(var(--pad) + 12px);
    left: 50%;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 4px;
    height: 48px;            /* same as .nav.is-min, the site's shrunk bar */
    padding: 0 8px;
    border-radius: var(--r-pill);
    /* starts folded into nothing behind the close button, then opens out */
    transform: translateX(-50%) scale(0.86);
    opacity: 0;
    pointer-events: none;
    transition: opacity 300ms var(--ease), transform 480ms var(--ease);
}
.film.is-past .film__top {
    opacity: 1;
    transform: translateX(-50%) scale(1);
    pointer-events: auto;
}

.film__home,
.film__contact {
    appearance: none;
    border: 0;
    background: none;
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 500;
    color: var(--ink);
    padding: 10px 16px;
    border-radius: var(--r-pill);
    cursor: pointer;
    text-decoration: none;
    line-height: 1;
    transition: background-color 240ms var(--ease);
}
.film__home:hover,
.film__contact:hover { background: rgba(255, 255, 255, 0.5); }

/* ═══════════════════ the close button, one element, two homes ═══════════ */

.film__close {
    position: absolute;
    z-index: 6;
    top: calc(var(--pad) + 12px);      /* its home is the corner, level with the bar */
    left: var(--pad);
    width: 52px;
    height: 52px;
    padding: 0;
    border-radius: 50%;
    display: grid;
    place-content: center;
    cursor: pointer;
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.40);
    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.30) 0%,
        rgba(255, 255, 255, 0.14) 45%,
        rgba(255, 255, 255, 0.09) 100%);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    box-shadow:
        inset 0  1px 0 rgba(255, 255, 255, 0.65),
        inset 0 -1px 0 rgba(255, 255, 255, 0.16),
        0 6px 22px rgba(10, 22, 16, 0.22);
    opacity: 0;
    /* --cx/--cy are measured in JS: the offset from this corner home down to
       the spot beside the CTA in the floating bar */
    transform: translate(var(--cx, 0px), var(--cy, 0px));
    transition: opacity 320ms var(--ease) 240ms,
                transform 560ms var(--ease),
                width 560ms var(--ease),
                height 560ms var(--ease),
                background 320ms var(--ease),
                color 320ms var(--ease),
                border-color 320ms var(--ease);
}
.film__close svg { width: 18px; height: 18px; }
.film.is-open .film__close { opacity: 1; }

/* state B: slide home to the corner and take the bar's colouring */
.film.is-past .film__close {
    /* drops to the shrunk bar's height; the top edge is shared so both sit
       on the same line as the site's own minimised nav */
    width: 48px;
    height: 48px;
    transform: translate(0, 0);
    color: var(--ink);
    border-color: rgba(255, 255, 255, 0.58);
    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.62) 0%,
        rgba(255, 255, 255, 0.34) 42%,
        rgba(238, 233, 223, 0.40) 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.95),
        inset 0 -1px 0 rgba(255, 255, 255, 0.30),
        0 1px 2px rgba(74, 62, 44, 0.06),
        0 10px 30px rgba(74, 62, 44, 0.10);
}

.film__close:hover { filter: brightness(1.08); }
.film__close:active { transform: translate(var(--cx, 0px), var(--cy, 0px)) scale(0.94); }
.film.is-past .film__close:active { transform: translate(0, 0) scale(0.94); }

.film__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 52px;
    padding: 0 28px;
    border-radius: var(--r-pill);
    font-family: var(--sans);
    font-size: 0.95rem;
    font-weight: 500;
    color: #fff;
    text-decoration: none;
    border: 1px solid rgba(255, 255, 255, 0.40);
    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.30) 0%,
        rgba(255, 255, 255, 0.14) 45%,
        rgba(255, 255, 255, 0.09) 100%);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    box-shadow:
        inset 0  1px 0 rgba(255, 255, 255, 0.65),
        inset 0 -1px 0 rgba(255, 255, 255, 0.16),
        0 6px 22px rgba(10, 22, 16, 0.22);
    transition: transform 320ms var(--ease), background 320ms var(--ease);
}
.film__cta:hover { transform: translateY(-1.5px); background: linear-gradient(178deg,
        rgba(255,255,255,0.40) 0%, rgba(255,255,255,0.20) 45%, rgba(255,255,255,0.13) 100%); }

body.film-open { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
    .film__stage, .film__backdrop, .film__bar, .film__top, .film__close,
    .svc__video, .svc__play, .fx__crossvideo { transition-duration: 1ms !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   WEB CHAPTER — GALLERY
   Three variants share one tile, one caption and one note block. Only the
   arrangement and the motion differ, so they can be judged side by side.
   ══════════════════════════════════════════════════════════════════════════ */

.gal[hidden] { display: none; }

/* ---- the tile, shared by all three ---- */

.g {
    position: relative;
    margin: 0;
    border-radius: 14px;
    overflow: hidden;
    background: #0d1713;
    cursor: pointer;
    isolation: isolate;
}

.g img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top center;   /* these are page screenshots — keep the header */
    display: block;
    transition: transform 900ms var(--ease), filter 500ms var(--ease);
}

.g::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(6,13,10,0) 46%, rgba(6,13,10,0.82) 100%);
    opacity: 0;
    transition: opacity 420ms var(--ease);
}

.g figcaption {
    position: absolute;
    left: 16px;
    right: 16px;
    bottom: 14px;
    z-index: 2;
    display: flex;
    flex-direction: column;
    gap: 2px;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 380ms var(--ease), transform 460ms var(--ease);
    pointer-events: none;
}

.g__name {
    font-family: var(--serif);
    font-weight: 300;
    font-size: 19px;
    letter-spacing: -0.02em;
    color: #fff;
}
.g__cat {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
}

.g:hover img { transform: scale(1.05); }
.g:hover::after,
.g:hover figcaption { opacity: 1; }
.g:hover figcaption { transform: none; }

/* ─────────────────── B · focus rows ─────────────────── */

.gal--b { display: flex; flex-direction: column; gap: 14px; }

.gal-b__row { display: flex; gap: 14px; height: clamp(180px, 22vw, 280px); }

.gal--b .g {
    flex: 1 1 0;
    min-width: 0;
    transition: flex-grow 620ms var(--ease), filter 500ms var(--ease);
}
/* hovering one opens it and lets the others give way */
.gal-b__row:hover .g            { flex-grow: 0.72; filter: brightness(0.62) saturate(0.8); }
.gal-b__row:hover .g:hover      { flex-grow: 3.2;  filter: none; }
.gal-b__row:hover .g:hover::after,
.gal-b__row:hover .g:hover figcaption { opacity: 1; }

@media (max-width: 900px) {
    /* the focus interaction needs hover, which phones do not have — so the
       rows become a plain two-up grid and every project stays visible */
    .gal--b { gap: 10px; }
    .gal-b__row {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 10px;
        height: auto;
    }
    .gal--b .g { aspect-ratio: 4 / 3; }
    .gal-b__row:hover .g { flex-grow: initial; filter: none; }
    /* captions can't be hovered into view, so they simply stay — but at
       ~163px wide they have to come right down in size or they wrap over
       the screenshot they are labelling */
    .gal--b .g::after,
    .gal--b .g figcaption { opacity: 1; transform: none; }
    .gal--b figcaption { left: 10px; right: 10px; bottom: 9px; gap: 0; }
    .gal--b .g__name { font-size: 14px; line-height: 1.15; }
    .gal--b .g__cat  { font-size: 9px; letter-spacing: 0.06em; line-height: 1.3; }
    /* deepen the scrim so a permanent caption stays readable on pale shots */
    .gal--b .g::after {
        background: linear-gradient(180deg, rgba(6,13,10,0) 38%, rgba(6,13,10,0.88) 100%);
    }
}

/* ─────────────────── the two sentences ─────────────────── */

.gal-note {
    margin-top: clamp(48px, 6vw, 84px);
    max-width: 46ch;
}
.gal-note__l {
    overflow: hidden;          /* the mask the line rises out of */
    margin: 0;
}
.js .gal-note__l > span {
    display: block;
    font-family: var(--serif);
    font-weight: 200;
    font-size: clamp(21px, 2.3vw, 31px);
    line-height: 1.32;
    letter-spacing: -0.02em;
    color: rgba(255, 255, 255, 0.92);
    transform: translateY(105%);
    transition: transform 900ms var(--ease);
}
.gal-note__l:nth-child(2) > span { transition-delay: 110ms; }
.gal-note.is-in .gal-note__l > span { transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
    .gal--b .g { transition-duration: 1ms; }
    .gal-note__l > span { transform: none; }
}

/* ─────────────────── the full view ─────────────────── */

.bview[hidden] { display: none; }

.bview { position: fixed; inset: 0; z-index: 210; pointer-events: none; }
.bview.is-open { pointer-events: auto; }

.bview__backdrop {
    position: absolute; inset: 0;
    background: #07100c;
    opacity: 0;
    transition: opacity 520ms var(--ease);
}
.bview.is-open .bview__backdrop { opacity: 1; }

/* viewport-sized; the trip from the tile is a transform, as with the film */
.bview__stage {
    position: absolute;
    inset: 0;
    margin: 0;
    overflow: auto;
    overscroll-behavior: contain;
    transform-origin: 0 0;
    will-change: transform, border-radius;
    border-radius: 0;
    background: #07100c;
    transition: transform 620ms var(--ease), border-radius 620ms var(--ease);
}
.bview__img { width: 100%; height: auto; display: block; }

.bview__bar {
    position: absolute;
    left: 0; right: 0;
    bottom: max(28px, env(safe-area-inset-bottom, 0px));
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 0 20px;
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 360ms var(--ease) 240ms, transform 440ms var(--ease) 240ms;
}
.bview.is-open .bview__bar { opacity: 1; transform: none; }

.bview__close,
.bview__open {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 52px;
    font-family: var(--sans);
    font-weight: 500;
    font-size: 0.95rem;
    color: #fff;
    text-decoration: none;
    cursor: pointer;
    border: 1px solid rgba(255, 255, 255, 0.40);
    background: linear-gradient(178deg,
        rgba(255,255,255,0.30) 0%, rgba(255,255,255,0.14) 45%, rgba(255,255,255,0.09) 100%);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.65),
                inset 0 -1px 0 rgba(255,255,255,0.16),
                0 6px 22px rgba(10,22,16,0.22);
    transition: transform 320ms var(--ease), background 320ms var(--ease);
}
.bview__close { width: 52px; padding: 0; border-radius: 50%; flex: 0 0 auto; }
.bview__close svg { width: 18px; height: 18px; }
.bview__open  { gap: 12px; padding: 0 8px 0 26px; border-radius: var(--r-pill); }
.bview__open[hidden] { display: none; }
.bview__open .arrow-circle {
    width: 34px; height: 34px; border-radius: 50%;
    display: grid; place-content: center;
    background: #fff; color: #07100c;
}
.bview__open .arrow-circle svg { width: 15px; height: 15px; }

.bview__close:hover, .bview__open:hover {
    transform: translateY(-1.5px);
    background: linear-gradient(178deg,
        rgba(255,255,255,0.40) 0%, rgba(255,255,255,0.20) 45%, rgba(255,255,255,0.13) 100%);
}
.bview__open:hover .arrow-circle { transform: rotate(45deg); }

body.bview-open { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
    .best__t, .best__t img, .bview__stage, .bview__bar { transition-duration: 1ms !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   OUR BEST WORK — a horizontal run of 16:9 tiles.
   Whichever tile is nearest the centre of the viewport is the one in focus:
   it sits at full size and full clarity, the rest scale to 0.8 and blur, so
   the centre one is exactly 25% larger. Scroll-snap parks one at a time.
   ══════════════════════════════════════════════════════════════════════════ */

.best-head { margin: clamp(64px, 8vw, 108px) 0 clamp(28px, 3.5vw, 44px); }

/* it now opens the chapter, so .fx's own top padding is the whole gap */
.best-head:first-child { margin-top: 0; }

/* and the gallery follows the carousel's arrows — it needs the break the
   heading used to provide */
.best-nav + .gal { margin-top: clamp(72px, 9vw, 120px); }

/* the button now closes the chapter, after the gallery and its two lines */
.gal-note + .best-cta { margin-top: clamp(56px, 7vw, 92px); }
.best-head__h { font-size: clamp(28px, 4vw, 52px); margin-bottom: 16px; max-width: 20ch; }

.best {
    display: flex;
    gap: clamp(18px, 2.4vw, 34px);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    /* the leading and trailing space is what lets the first and last tile
       reach the centre of the rail */
    padding: 44px calc(50% - min(31vw, 420px)) 52px;
    margin-inline: calc(50% - 50vw);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
}
.best::-webkit-scrollbar { display: none; }

.best__t {
    position: relative;
    flex: 0 0 min(62vw, 840px);
    scroll-snap-align: center;
    padding: 10px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--r-tile);
    background: rgba(255, 255, 255, 0.05);
    cursor: pointer;
    isolation: isolate;

    /* the resting state is the *unfocused* one */
    transform: scale(0.8);
    filter: blur(3px) saturate(0.85);
    opacity: 0.55;
    transition: transform 620ms var(--ease),
                filter 520ms var(--ease),
                opacity 520ms var(--ease),
                box-shadow 620ms var(--ease);
}

.best__t.is-focus {
    transform: scale(1);          /* 1 / 0.8 — a quarter larger than the rest */
    filter: none;
    opacity: 1;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.20),
        0 4px 12px rgba(4, 10, 7, 0.34),
        0 26px 64px rgba(4, 10, 7, 0.40);
}

.best__t img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    object-position: top center;
    border-radius: calc(var(--r-tile) - 8px);
    display: block;
}

/* the cue only belongs to the tile you can actually act on */
.best__cue {
    position: absolute;
    left: 26px;
    bottom: 26px;
    z-index: 2;
    display: flex;
    align-items: center;
    pointer-events: none;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 380ms var(--ease) 120ms, transform 460ms var(--ease) 120ms;
}
.best__t.is-focus .best__cue { opacity: 1; transform: none; }

.best__disc {
    display: grid;
    place-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    color: var(--ink);
    background: rgba(255, 255, 255, 0.9);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, 0.75);
    box-shadow: inset 0 1px 0 rgba(255,255,255,1), 0 8px 24px rgba(4,10,7,0.34);
    transition: transform 460ms var(--ease), background-color 320ms var(--ease);
}
.best__disc svg { width: 17px; height: 17px; }
.best__t.is-focus:hover .best__disc { transform: rotate(45deg) scale(1.06); background: #fff; }

.best__t::after {
    content: '';
    position: absolute;
    inset: 10px;
    z-index: 1;
    border-radius: calc(var(--r-tile) - 8px);
    pointer-events: none;
    background: linear-gradient(180deg, rgba(6,13,10,0) 62%, rgba(6,13,10,0.5) 100%);
}

.best-cta { display: flex; justify-content: center; margin-top: clamp(18px, 2.2vw, 28px); }

.best-cta__btn {
    height: 54px;
    padding: 0 34px;
    border-radius: var(--r-pill);
    font-family: var(--sans);
    font-size: 15px;
    font-weight: 500;
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.40);
    background: linear-gradient(178deg,
        rgba(255, 255, 255, 0.30) 0%,
        rgba(255, 255, 255, 0.14) 45%,
        rgba(255, 255, 255, 0.09) 100%);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    box-shadow:
        inset 0  1px 0 rgba(255, 255, 255, 0.65),
        inset 0 -1px 0 rgba(255, 255, 255, 0.16),
        0 6px 22px rgba(10, 22, 16, 0.22);
    transition: transform 320ms var(--ease), background 320ms var(--ease);
}
.best-cta__btn::before { background: none; }
.best-cta__btn:hover {
    transform: translateY(-1.5px);
    background: linear-gradient(178deg,
        rgba(255,255,255,0.40) 0%, rgba(255,255,255,0.20) 45%, rgba(255,255,255,0.13) 100%);
}
.best-cta__btn:active { transform: translateY(0) scale(0.985); }

@media (max-width: 860px) {
    .best { padding: 30px calc(50% - 42vw) 38px; gap: 14px; }
    .best__t { flex: 0 0 84vw; }
    .best__cue { left: 18px; bottom: 18px; }
    .best__disc { width: 46px; height: 46px; }
}

@media (prefers-reduced-motion: reduce) {
    .best__t { transition-duration: 1ms !important; filter: none; opacity: 1; transform: scale(0.92); }
    .best__t.is-focus { transform: scale(1); }
}

/* ---- carousel arrows ---------------------------------------------------- */

/* the arrows sit centred between the rail and the closing call to action,
   so the eye travels tiles -> controls -> button on one axis */
.best-nav {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-top: 2px;
}

.best-arrow {
    display: grid;
    place-content: center;
    width: 46px;
    height: 46px;
    padding: 0;
    border-radius: 50%;
    cursor: pointer;
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.28);
    background: rgba(255, 255, 255, 0.06);
    backdrop-filter: blur(14px) saturate(160%);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
    transition: background-color 260ms var(--ease),
                border-color 260ms var(--ease),
                transform 300ms var(--ease),
                opacity 260ms var(--ease);
}
.best-arrow svg { width: 18px; height: 18px; }

.best-arrow:hover {
    background: rgba(255, 255, 255, 0.14);
    border-color: rgba(255, 255, 255, 0.5);
    transform: scale(1.06);
}
.best-arrow:active { transform: scale(0.94); }

/* at either end there is nowhere left to go */
.best-arrow[disabled] {
    opacity: 0.3;
    cursor: default;
    pointer-events: none;
}

@media (max-width: 860px) {
    .best-nav { margin-top: 0; }
    .best-arrow { width: 42px; height: 42px; }
}

/* ── the dark band on the standalone /weby/ page ─────────────────────────
   The carousel and the gallery were written for the film overlay, where the
   surface behind them is #07100c and the type is on-dark. Given their own
   page they need that surface back, so the band supplies it and .fx inside
   supplies the column and the colour — no second copy of either component. */
.band-dark { background: #07100c; }
.band-dark .fx { padding-top: clamp(72px, 8vw, 112px); }

/* ── standalone chapter pages: hero type and the scroll cue ──────────────
   .fx__title is sized for a chapter that owns the whole viewport. Inside the
   hero card it shares the space with the lede and the cue, so it comes down a
   step — the card is a frame, not a page. */
.hero .fx__head   { max-width: 44ch; }
.hero .fx__kicker { margin-bottom: 14px; }
.hero .fx__title  { font-size: clamp(23px, 3.3vw, 42px); max-width: 22ch; margin-bottom: 16px; }
.hero .fx__lede   { font-size: clamp(14px, 1.15vw, 17px); max-width: 50ch; }

/* the cue sits on the card, not in .hero__content, so it centres on the frame
   rather than on the column of copy */
.hero__cue {
    position: absolute;
    left: 50%;
    bottom: clamp(16px, 2.4vw, 30px);
    z-index: 2;
    display: grid;
    place-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    color: var(--on-dark);
    border: 1px solid rgba(255, 255, 255, 0.28);
    background: rgba(255, 255, 255, 0.06);
    backdrop-filter: blur(14px) saturate(160%);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
    translate: -50% 0;
    animation: hero-cue 2.6s var(--ease-soft) infinite;
    transition: background 300ms var(--ease), border-color 300ms var(--ease);
}
.hero__cue svg { width: 18px; height: 18px; }
.hero__cue:hover {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.52);
}

/* the whole travel is 7px — it should read as a nudge, not a bounce */
@keyframes hero-cue {
      0% { translate: -50% 0;   }
     45% { translate: -50% 7px; }
     70% { translate: -50% 2px; }
    100% { translate: -50% 0;   }
}

/* the copy is bottom-left and the cue is bottom-centre; on a narrow card the
   two would meet, so the copy gets out of its way */
.hero:has(.hero__cue) .hero__content { padding-bottom: calc(var(--card-pad) + 46px); }

@media (prefers-reduced-motion: reduce) {
    .hero__cue { animation: none; }
}

/* ── mobile: the same move, paid for differently ─────────────────────────
   Three things were animating at once on a phone: a full-viewport clip-path
   with a 999px rounded corner, the nav's backdrop-filter still live
   underneath it, and the panel's own fade. The rounded clip is the costly
   part — it forces a per-pixel corner evaluation across the whole screen
   every frame, and phones do not have the fill rate for it.

   The unfold is kept. It just runs on a square clip, over a shorter
   distance in time, with the glass torn down first instead of 300ms late. */
@media (max-width: 767px) {

    .menu {
        transition: clip-path 400ms var(--ease),
                    opacity 200ms var(--ease-soft) 320ms,
                    visibility 0s linear 520ms;
    }
    .menu.is-open {
        transition: clip-path 400ms var(--ease) 180ms,
                    opacity 200ms var(--ease-soft),
                    visibility 0s;
    }

    /* the bar drops its glass immediately: compositing a 22px backdrop blur
       underneath a moving full-screen clip is what cost the frames */
    html.is-menu .nav {
        transition: background 160ms linear,
                    border-color 160ms linear,
                    box-shadow 160ms linear;
    }

    /* the stagger has to fit inside the shorter unfold */
    .menu.is-open .menu__mask > a { transition-delay: calc(260ms + var(--i) * 40ms); }
}
