/* ============================================================
   Eduardo Freira — site styles
   Direction: "Reading Pane". One dark visual world, with a single
   inverted paper section for emphasis. Every colour is painted
   explicitly from a token; nothing inherits a host background.
   ============================================================ */

:root {
  /* ── Colour ──
     Neutrals carry a blue-grey bias toward the signal hue, so the
     greys read as chosen rather than inherited defaults. */
  --bg:        #0B0D10;
  --surface:   #12161B;
  --surface-2: #191E26;
  --surface-3: #222833;

  --line:   rgba(231,233,236,0.10);
  --line-2: rgba(231,233,236,0.055);

  --text:   #E7E9EC;
  --text-2: #939BA7;
  --text-3: #656D7A;

  /* Accent is the hero's shine blue. It is light, so anything filled with
     it takes a near-black label — white on this hue is 1.8:1. */
  --signal:      #64CEFB;
  --signal-hi:   #8ADCFF;
  --signal-ink:  #06131A;
  --signal-wash: rgba(100,206,251,0.10);
  /* Button sweep: base and sheen. Sheen must be lighter than base. */
  --btn-a: #64CEFB;
  --btn-b: #FFFFFF;

  --paper:   #F3F2EF;
  --paper-2: #E8E7E2;

  /* ── Type ── */
  --display: 'Newsreader', Georgia, 'Times New Roman', serif;
  --sans:    'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono:    'DM Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --t-xl: clamp(42px, 5.4vw, 74px);
  --t-l:  clamp(31px, 3.9vw, 52px);
  --t-m:  clamp(24px, 2.6vw, 34px);
  --t-s:  22px;

  /* ── Space ── */
  --s-1: 4px;   --s-2: 8px;   --s-3: 12px;  --s-4: 16px;
  --s-5: 24px;  --s-6: 32px;  --s-7: 40px;  --s-8: 56px;
  --s-9: 72px;  --s-10: 96px; --s-11: 128px;

  --rail: 136px;
  --gut:  40px;
  --max:  1160px;
  --nav-h: 72px;

  --radius: 6px;
  --radius-s: 4px;

  /* ── Motion ──
     One curve for entrances, one for interface feedback. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-ui: cubic-bezier(0.4, 0, 0.2, 1);
}

/* Local token overrides. Components read tokens only, so an inverted
   block restyles itself without any component-level overrides. */
.invert {
  --surface:   #FFFFFF;
  --surface-2: var(--paper-2);
  --surface-3: #DCDAD4;
  --line:      rgba(11,13,16,0.13);
  --line-2:    rgba(11,13,16,0.07);
  --text:      #0E1116;
  --text-2:    #4B525C;
  --text-3:    #767D88;
  /* Same hue, darkened to hold on paper — the light accent is 1.6:1 here */
  --signal:      #17708F;
  --signal-hi:   #0C5E7D;
  --signal-ink:  #FFFFFF;
  --signal-wash: rgba(23,112,143,0.08);
  --btn-a: #17708F;
  --btn-b: #3E9CBE;
  background: var(--paper);
  color: var(--text);
}

/* ============================================================
   Base
   ============================================================ */

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 24px);
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--signal-hi);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: var(--signal); color: var(--signal-ink); }

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gut); }

/* Rail layout — a document margin carrying labels and numbering.
   The rail is structural, not decorative: it holds what the section is,
   so the content column never has to. */
.rail { display: grid; grid-template-columns: var(--rail) 1fr; gap: var(--gut); }
.rail-note {
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.55;
  letter-spacing: 0.02em;
  color: var(--text-3);
  padding-top: 0.5em;
}
.rail-note b { display: block; color: var(--text-2); font-weight: 400; }
.rail-note span { display: block; }
/* index.html no longer labels its sections. The note stays as an empty
   placeholder so the rail column remains occupied and the content column
   does not fall back into the 136px gutter. */
.rail-note:empty { padding-top: 0; }

/* Keeps a hyphenated figure like "20-30%" from splitting across lines */
.nb { white-space: nowrap; }

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--signal);
  color: var(--signal-ink);
  padding: 10px 18px;
  font-size: 14px;
  z-index: 200;
}
.skip:focus { left: 12px; top: 12px; }

/* ============================================================
   Type
   ============================================================ */

.t-xl, .t-l, .t-m {
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: -0.022em;
  text-wrap: balance;
}
.t-xl { font-size: var(--t-xl); line-height: 1.02; }
.t-l  { font-size: var(--t-l);  line-height: 1.06; }
.t-m  { font-size: var(--t-m);  line-height: 1.12; letter-spacing: -0.018em; }

/* Emphasis is the italic, not a colour swap alone — the serif's italic
   is the most characteristic thing about this typeface, so it carries
   the payoff phrase in every headline. */
em.mark { font-style: italic; font-weight: 300; color: var(--signal); }
em.quiet { font-style: italic; font-weight: 300; color: var(--text-2); }

.lede {
  font-size: 17px;
  line-height: 1.62;
  color: var(--text-2);
  max-width: 58ch;
}

.eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--signal);
  margin-bottom: var(--s-4);
}

/* Mono is reserved for machine output — inbox chrome, timings, flow
   metadata, tax IDs. It is never used for prose or section labels. */
.meta {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-3);
}

.prose p { font-size: 16px; line-height: 1.7; color: var(--text-2); max-width: 62ch; }
.prose p + p { margin-top: var(--s-4); }
.prose strong { color: var(--text); font-weight: 500; }

/* ============================================================
   Buttons
   ============================================================ */

/* Primary button carries the hero's sweep on its fill instead of its text.
   Same 100deg angle, same 3s loop, same 200%/0–100% coverage rule. The
   sheen only ever runs lighter than the base, so the dark label's contrast
   improves as it passes rather than dropping. */
.btn {
  position: relative;
  /* Own stacking context, so the sweep layer's negative z-index stays
     inside the button instead of dropping behind the page. */
  isolation: isolate;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background-color: var(--btn-a);
  color: var(--signal-ink);
  padding: 14px 26px;
  border-radius: var(--radius-s);
  font-size: 14.5px;
  font-weight: 500;
  letter-spacing: 0.005em;
  transition: transform 0.18s var(--ease-ui), filter 0.18s var(--ease-ui);
}
/* The sweep sits on its own layer so it can be blurred. Blur is what
   removes the shoulder either side of the sheen — the band then arrives
   and leaves as light rather than as a moving edge. The layer is inset
   well past all four sides so the blur never samples past the gradient
   and darkens the button's own corners. Negative z-index keeps it above
   the flat fill and below the label. */
.btn::before {
  content: '';
  position: absolute;
  inset: -140% -35%;
  z-index: -1;
  background-image: linear-gradient(
    100deg,
    var(--btn-a) 0%,
    var(--btn-a) 30%,
    var(--btn-b) 50%,
    var(--btn-a) 70%,
    var(--btn-a) 100%
  );
  background-size: 200% 100%;
  background-repeat: repeat-x;
  background-position: 200% 0;
  filter: blur(16px);
  animation: shinySweep 3s linear infinite;
  pointer-events: none;
}
.btn:hover { transform: translateY(-1px); filter: brightness(1.07); }
.btn svg { transition: transform 0.18s var(--ease-ui); }
.btn:hover svg { transform: translateX(3px); }

.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 13px 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  transition: border-color 0.18s var(--ease-ui), background 0.18s var(--ease-ui);
}
.btn-ghost:hover { border-color: var(--text-3); background: var(--surface); }
.btn-ghost svg { transition: transform 0.18s var(--ease-ui); }
.btn-ghost:hover svg { transform: translateX(3px); }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 14px;
  font-weight: 500;
  color: var(--signal);
}
.link-arrow svg { transition: transform 0.18s var(--ease-ui); }
.link-arrow:hover svg { transform: translateX(3px); }

.cta-row { display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap; }
.cta-note { font-family: var(--mono); font-size: 11.5px; color: var(--text-3); }

/* ============================================================
   Nav
   ============================================================ */

.nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 90;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  /* Solid once scrolled, never translucent. A translucent bar over
     running text produced half-blurred, half-sharp ghosting. */
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background 0.25s var(--ease-ui), border-color 0.25s var(--ease-ui);
}
.nav.is-stuck {
  background: var(--bg);
  border-bottom-color: var(--line);
}
.nav-in { display: flex; align-items: center; justify-content: space-between; gap: var(--s-6); width: 100%; }

.logo {
  font-family: var(--display);
  font-size: 19px;
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--text);
  white-space: nowrap;
  /* Plain inline flow, not flex — flex would swallow the word space
     between the given name and the surname. */
  display: inline-block;
}
.logo b { font-weight: 600; }

/* Links ride in a rounded pill so the bar reads as one object over
   the footage rather than text floating on video */
.nav-links {
  display: flex;
  align-items: center;
  gap: 22px;
  font-size: 14px;
  padding: 9px 20px;
  border: 1px solid var(--line);
  border-radius: 999px;
}
.nav.is-stuck .nav-links { border-color: var(--line); }
.nav-links a { color: rgba(231,233,236,0.8); transition: color 0.18s var(--ease-ui); }
.nav-links a:hover { color: #FFFFFF; }
.nav-links a[aria-current="page"] { color: #FFFFFF; }
.nav-links .has-arrow { display: inline-flex; align-items: center; gap: 6px; }
.nav-links .has-arrow svg { transition: transform 0.18s var(--ease-ui); }
.nav-links .has-arrow:hover svg { transform: translateX(3px); }

.nav-cta {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text);
  padding-bottom: 3px;
  border-bottom: 1px solid var(--signal);
  transition: color 0.18s var(--ease-ui), border-color 0.18s var(--ease-ui);
  white-space: nowrap;
}
.nav-cta:hover { color: var(--signal-hi); border-bottom-color: var(--signal-hi); }

.burger { display: none; width: 26px; height: 18px; position: relative; flex-shrink: 0; }
.burger span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: var(--text);
  border-radius: 2px;
  transition: transform 0.28s var(--ease), opacity 0.18s var(--ease-ui);
}
.burger span:nth-child(1) { top: 2px; }
.burger span:nth-child(2) { top: 8px; }
.burger span:nth-child(3) { top: 14px; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.menu {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s-4);
  padding: var(--nav-h) var(--gut) var(--s-9);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.28s var(--ease-ui), visibility 0.28s;
}
.menu.is-open { opacity: 1; visibility: visible; }
.menu a {
  font-family: var(--display);
  font-size: 34px;
  line-height: 1.25;
  letter-spacing: -0.02em;
  color: var(--text);
  border-bottom: 1px solid var(--line-2);
  padding-bottom: var(--s-4);
}
.menu a:last-child {
  border-bottom: 0;
  margin-top: var(--s-4);
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 500;
  color: var(--signal);
}

/* ============================================================
   Sections
   ============================================================ */

.section { padding: var(--s-10) 0; }
.section--tight { padding: var(--s-8) 0; }
.section--wide  { padding: var(--s-11) 0; }
.section + .section:not(.invert) { border-top: 1px solid var(--line-2); }

.section-head { margin-bottom: var(--s-8); }
.section-head .lede { margin-top: var(--s-4); }

/* ============================================================
   Hero
   ============================================================ */

.hero {
  position: relative;
  padding: calc(var(--nav-h) + var(--s-9)) 0 var(--s-10);
  overflow: hidden;
}
/* Atmosphere is static. A slow perpetual drift behind running text
   reads as unfinished; a fixed wash reads as lighting. */
.hero::before {
  content: '';
  position: absolute;
  top: -30%;
  left: 42%;
  width: 92vw;
  height: 120%;
  background: radial-gradient(ellipse 46% 42% at 50% 50%,
    rgba(59,107,255,0.20) 0%,
    rgba(59,107,255,0.09) 34%,
    rgba(59,107,255,0.03) 56%,
    transparent 76%);
  pointer-events: none;
  z-index: 0;
}
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0.035;
  mix-blend-mode: overlay;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 160 160' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.2' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 140px 140px;
}
.hero > .wrap { position: relative; z-index: 2; }

.hero h1 { max-width: 15ch; }
.hero .lede { margin-top: var(--s-5); }
.hero .cta-row { margin-top: var(--s-7); }

/* ============================================================
   Film hero — full-screen video background (index only)
   Three rows inside one viewport: intro pair, centre statement,
   byline. Everything sits above the video on its own layer.
   ============================================================ */

.hero-film {
  position: relative;
  min-height: 100svh;
  background: #000000;
  overflow: hidden;
  display: flex;
  align-items: stretch;
}
.hero-film-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  pointer-events: none;
}
/* Readability scrim: the copy column must sit on a stable dark base
   wherever the light form in the footage happens to drift. */
.hero-film-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(0,0,0,0.72) 0%, rgba(0,0,0,0.28) 26%, rgba(0,0,0,0.30) 62%, rgba(0,0,0,0.80) 100%),
    radial-gradient(120% 85% at 22% 55%, rgba(0,0,0,0.58) 0%, rgba(0,0,0,0.18) 48%, transparent 78%);
}
.hero-film-in {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  width: 100%;
  padding-top: calc(var(--nav-h) + var(--s-6));
  padding-bottom: var(--s-6);
  gap: var(--s-6);
}

/* Row 1 — the intro pair */
.hero-film-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.72fr);
  gap: var(--s-7);
  align-items: start;
}
.hero-film-top p {
  font-size: 14px;
  line-height: 1.6;
  color: rgba(255,255,255,0.8);
  max-width: 54ch;
}
.hero-film-stat {
  text-align: right;
  justify-self: end;
}
.hero-film-stat b {
  display: block;
  font-family: var(--display);
  font-weight: 400;
  font-size: 30px;
  line-height: 1;
  letter-spacing: -0.02em;
  color: #FFFFFF;
  margin-bottom: 6px;
  font-variant-numeric: tabular-nums;
}

/* Row 2 — the statement */
.hero-film-mid {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--s-6) 0;
}
.hero-film-eyebrow {
  font-size: 12px;
  line-height: 1.4;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.8);
  margin-bottom: var(--s-4);
}
/* Sized so the setup clause holds one line at the container's widest —
   three rows have to share one viewport, so the statement cannot sprawl. */
.hero-film h1 {
  font-family: var(--display);
  font-size: clamp(38px, 6.2vw, 94px);
  line-height: 0.9;
  letter-spacing: -0.035em;
  font-weight: 400;
  margin: 0;
}
.hero-film h1 .line {
  display: block;
}
.hero-film h1 .line-1 { color: #FFFFFF; }
.hero-film .cta-row { margin-top: var(--s-6); }

/* Row 3 — byline */
.hero-film-byline {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding-top: var(--s-6);
  border-top: 1px solid rgba(255,255,255,0.14);
  max-width: 68ch;
}
.hero-film-byline img {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
  filter: grayscale(100%) contrast(1.04);
  border: 1px solid rgba(255,255,255,0.2);
}
.hero-film-byline p {
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255,255,255,0.8);
}
.hero-film-byline strong { color: #FFFFFF; font-weight: 500; }

/* ── Shiny text ──
   A gradient sweeping left to right, clipped to the glyphs. Pure CSS
   does what the spec's framer-motion loop does, with no JS and no
   dependency, and it degrades to a flat fill under reduced motion. */
.shiny {
  display: block;
  color: #64CEFB;
}
/* The gradient tiles, so the box is always fully painted at every phase.
   That matters here specifically: the fill is transparent, so any unpainted
   run would render as invisible text rather than merely unshaded text. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .shiny {
    background-image: linear-gradient(
      100deg,
      #64CEFB 0%,
      #64CEFB 38%,
      #ffffff 50%,
      #64CEFB 62%,
      #64CEFB 100%
    );
    background-size: 200% 100%;
    background-repeat: repeat-x;
    background-position: 200% 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: shinySweep 3s linear infinite;
  }
}
/* 200% -> 0% is exactly one tile of the 200%-wide gradient, so the sweep
   loops without a visible snap. */
@keyframes shinySweep {
  from { background-position: 200% 0; }
  to   { background-position: 0% 0; }
}

/* Solid pill CTA, per the film-hero spec */
.btn-film {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: #000000;
  color: #FFFFFF;
  border-radius: 999px;
  padding: 13px 24px;
  font-size: 14.5px;
  font-weight: 500;
  transition: background 0.2s var(--ease-ui);
}
.btn-film:hover { background: #16181C; }
.btn-film svg { transition: transform 0.2s var(--ease-ui); }
.btn-film:hover svg { transform: translateX(4px); }
.hero-film .cta-note { color: rgba(255,255,255,0.65); }

@media (prefers-reduced-motion: reduce) {
  /* Hold the sweep still and drop the footage back to its poster frame */
  .shiny { animation: none !important; background-position: 50% 0 !important; }
  .btn::before { animation: none !important; opacity: 0 !important; }
  .hero-film-video { display: none; }
  .hero-film { background: #000000 url('hero-poster.jpg') center / cover no-repeat; }
}

@media (max-width: 900px) {
  .hero-film-top { grid-template-columns: 1fr; gap: var(--s-5); }
  .hero-film-stat { text-align: left; justify-self: start; }
  .hero-film h1 { max-width: none; }
}

@media (max-width: 640px) {
  .hero-film-in { padding-top: calc(var(--nav-h) + var(--s-7)); gap: var(--s-7); }
  .hero-film-mid { padding: var(--s-7) 0; }
  .hero-film-stat b { font-size: 26px; }
  .hero-film-byline { padding-top: var(--s-5); }
  .hero-film-byline img { width: 42px; height: 42px; }
}

/* ============================================================
   Stats
   ============================================================ */

.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); }
.stat { padding-right: var(--s-6); }
.stat + .stat { border-left: 1px solid var(--line-2); padding-left: var(--s-6); }
.stat-n {
  font-family: var(--display);
  font-size: 42px;
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
}
.stat-l { margin-top: var(--s-3); font-size: 13px; color: var(--text-3); max-width: 26ch; }

/* ============================================================
   About
   ============================================================ */

.about-grid { display: grid; grid-template-columns: 260px 1fr; gap: var(--s-9); align-items: start; }
.portrait { position: relative; border-radius: var(--radius); overflow: hidden; background: var(--surface); }
.portrait img { width: 100%; aspect-ratio: 4/5; object-fit: cover; filter: grayscale(100%) contrast(1.04); }
.portrait figcaption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: var(--s-5) var(--s-4) var(--s-3);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #E7E9EC;
  background: linear-gradient(to top, rgba(11,13,16,0.85), transparent);
}

.tags { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-6); }
.tag {
  font-size: 12px;
  letter-spacing: 0.02em;
  padding: 6px 13px;
  border: 1px solid var(--line);
  border-radius: 100px;
  color: var(--text-2);
}

/* ============================================================
   Services — card grid
   Icon badge overlaps the card's top-left corner, so the card reads as
   a labelled object rather than a box with a picture inside it.
   ============================================================ */

.svc-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-6);
  /* Room for the badges, which hang outside the first column and the top row */
  padding: 26px 0 0 26px;
  margin: 0 0 0 -26px;
}
/* The grid reclaims the rail's width. Three columns inside the text column
   leave ~30 characters per line, which is too narrow to read comfortably. */
@media (min-width: 901px) {
  .svc-grid { margin-left: calc(-26px - var(--rail) - var(--gut)); }
}

.svc {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--s-7) var(--s-6) var(--s-5);
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  transition: transform 0.4s var(--ease),
              border-color 0.3s var(--ease-ui),
              background 0.3s var(--ease-ui),
              box-shadow 0.4s var(--ease);
}
/* Accent bloom, revealed on hover only — at rest the grid stays quiet */
.svc::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(120% 80% at 12% 0%, var(--signal-wash) 0%, transparent 62%);
  transition: opacity 0.4s var(--ease-ui);
}
.svc:hover {
  transform: translateY(-5px);
  border-color: rgba(100,206,251,0.34);
  background: var(--surface-2);
  box-shadow: 0 22px 44px -26px rgba(0,0,0,0.85);
}
.svc:hover::before { opacity: 1; }

.svc-icon {
  position: absolute;
  top: -20px;
  left: -20px;
  width: 48px;
  height: 48px;
  border-radius: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--signal);
  background: var(--surface-2);
  border: 1px solid var(--line);
  box-shadow: 0 10px 22px -10px rgba(0,0,0,0.9), inset 0 1px 0 rgba(255,255,255,0.05);
  transition: transform 0.4s var(--ease),
              color 0.3s var(--ease-ui),
              border-color 0.3s var(--ease-ui),
              box-shadow 0.4s var(--ease);
}
.svc:hover .svc-icon {
  transform: translateY(-3px) scale(1.06);
  color: var(--signal-hi);
  border-color: rgba(100,206,251,0.42);
  box-shadow: 0 14px 26px -12px rgba(0,0,0,0.9),
              0 0 0 4px var(--signal-wash),
              inset 0 1px 0 rgba(255,255,255,0.07);
}

.svc-n {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--text-3);
  margin-bottom: var(--s-4);
}
.svc-title {
  font-family: var(--display);
  font-size: 25px;
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -0.018em;
  margin-bottom: var(--s-3);
  transition: color 0.3s var(--ease-ui);
}
.svc:hover .svc-title { color: var(--signal); }
.svc-body { font-size: 14.5px; line-height: 1.62; color: var(--text-2); }
.svc-body + .svc-body { margin-top: var(--s-3); }
.svc-spec {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.05em;
  color: var(--text-3);
  margin-top: auto;
  padding-top: var(--s-5);
}
.svc-foot { display: flex; justify-content: center; margin-top: var(--s-9); }

@media (max-width: 1080px) {
  .svc-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 700px) {
  .svc-grid {
    grid-template-columns: 1fr;
    gap: var(--s-7);
    padding-left: 22px;
    margin-left: -22px;
  }
  .svc-icon { width: 42px; height: 42px; border-radius: 13px; top: -17px; left: -17px; }
  .svc-title { font-size: 23px; }
}

/* ============================================================
   Process — the inverted section
   ============================================================ */

/* One rail, four nodes, one panel. --tl-i is the index of the open
   node; the travelled rail and nothing else reads from it. */
.tl { --tl-i: 0; --tl-dot: 54px; }

.tl-track {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  padding-top: var(--s-2);
}
/* Rail and travelled rail. Both stop at the node centres — with four
   equal columns, that is 12.5% in from each end, one quarter apart. */
.tl-track::before,
.tl-track::after {
  content: '';
  position: absolute;
  top: calc(var(--s-2) + (var(--tl-dot) / 2) - 1px);
  left: 12.5%;
  height: 2px;
  border-radius: 2px;
  pointer-events: none;
}
.tl-track::before { right: 12.5%; background: var(--line); }
.tl-track::after {
  width: calc(var(--tl-i) * 25%);
  background: var(--signal);
  transition: width 0.62s var(--ease);
}

.tl-step {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-4);
  padding: 0 var(--s-3) var(--s-5);
  text-align: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
/* Opaque, so the rail passes behind the node rather than through it */
.tl-dot {
  width: var(--tl-dot);
  height: var(--tl-dot);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: var(--paper);
  border: 2px solid var(--line);
  color: var(--text-3);
  transition: transform 0.45s var(--ease),
              color 0.3s var(--ease-ui),
              background 0.3s var(--ease-ui),
              border-color 0.3s var(--ease-ui),
              box-shadow 0.45s var(--ease);
}
.tl-step:hover .tl-dot {
  transform: translateY(-2px);
  color: var(--text);
  border-color: var(--text-3);
}
.tl-step.is-active .tl-dot {
  background: var(--signal);
  border-color: var(--signal);
  color: var(--signal-ink);
  transform: translateY(-3px) scale(1.06);
  box-shadow: 0 16px 28px -14px rgba(11,13,16,0.5), 0 0 0 5px var(--signal-wash);
}

.tl-label { display: flex; flex-direction: column; gap: 4px; }
.tl-n {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--text-3);
  transition: color 0.3s var(--ease-ui);
}
.tl-t {
  font-family: var(--display);
  font-size: 19px;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--text-2);
  transition: color 0.3s var(--ease-ui);
}
.tl-step.is-active .tl-n { color: var(--signal); }
.tl-step:hover .tl-t,
.tl-step.is-active .tl-t { color: var(--text); }

.tl-panels {
  position: relative;
  margin-top: var(--s-5);
  padding-top: var(--s-6);
  border-top: 1px solid var(--line-2);
}
.tl-panels.is-live { transition: height 0.55s var(--ease); }
.tl-panel p { font-size: 17px; line-height: 1.65; color: var(--text-2); max-width: 64ch; }
.tl-panel p + p { margin-top: var(--s-4); }

/* Panels only stack and hide once the script is running. Without it the
   four paragraphs simply sit one after another and stay readable. */
.is-ready .tl-panel {
  position: absolute;
  top: var(--s-6);
  left: 0;
  right: 0;
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
  transition: opacity 0.38s var(--ease-ui), transform 0.5s var(--ease);
}
.is-ready .tl-panel.is-active {
  opacity: 1;
  transform: none;
  pointer-events: auto;
  transition-delay: 0.08s;
}

/* ============================================================
   Work
   ============================================================ */

.cases { display: flex; flex-direction: column; }
.case-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-9);
  align-items: start;
  padding: var(--s-9) 0;
  border-top: 1px solid var(--line);
}
.case-row:first-child { border-top: 0; padding-top: 0; }
.case-brand { font-family: var(--mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--signal); margin-bottom: var(--s-3); }
.case-title { font-family: var(--display); font-size: var(--t-m); font-weight: 400; line-height: 1.1; letter-spacing: -0.02em; margin-bottom: var(--s-4); }
.case-block { margin-top: var(--s-5); }
.case-block h4 {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: var(--s-2);
}
.case-block p { font-size: 15px; line-height: 1.65; color: var(--text-2); max-width: 56ch; }
.case-row .btn-ghost { margin-top: var(--s-6); }

/* Compact index instead of duplicate summary cards */
.index-list { border-top: 1px solid var(--line); }
.index-row {
  display: flex;
  align-items: baseline;
  gap: var(--s-5);
  padding: var(--s-5) 0;
  border-bottom: 1px solid var(--line-2);
  transition: padding-left 0.24s var(--ease);
}
.index-row:hover { padding-left: var(--s-3); }
.index-row .n { font-family: var(--mono); font-size: 11px; color: var(--text-3); width: 24px; flex-shrink: 0; }
.index-row .brand { font-family: var(--mono); font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--signal); width: 190px; flex-shrink: 0; }
.index-row .t { font-family: var(--display); font-size: 21px; letter-spacing: -0.015em; }
.index-row .go { margin-left: auto; color: var(--text-3); flex-shrink: 0; transition: transform 0.24s var(--ease), color 0.18s var(--ease-ui); }
.index-row:hover .go { color: var(--signal); transform: translateX(4px); }

/* Work preview cards on the home page */
.work-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-5); }
.work-card {
  display: flex;
  flex-direction: column;
  padding: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  transition: border-color 0.22s var(--ease-ui), background 0.22s var(--ease-ui);
}
.work-card:hover { border-color: var(--text-3); background: var(--surface-2); }
.work-card .brand { font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--signal); margin-bottom: var(--s-3); }
.work-card h3 { font-family: var(--display); font-size: 23px; font-weight: 400; line-height: 1.15; letter-spacing: -0.018em; margin-bottom: var(--s-3); }
.work-card p { font-size: 14px; line-height: 1.6; color: var(--text-2); }
/* margin-top:auto pins the link to the card floor, so links align
   across cards no matter how the copy wraps */
.work-card .link-arrow { margin-top: auto; padding-top: var(--s-5); font-size: 13.5px; }

/* ── Email screenshot frame ── */
.shot {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}
.shot-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--text-3);
}
.shot-dots { display: flex; gap: 5px; }
.shot-dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--surface-3); }
.shot-end { margin-left: auto; }
.shot-scroll {
  height: 470px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--surface-3) transparent;
  background: #fff;
}
.shot-scroll::-webkit-scrollbar { width: 5px; }
.shot-scroll::-webkit-scrollbar-track { background: transparent; }
.shot-scroll::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 100px; }
.shot-scroll img { width: 100%; }
.shot-hint {
  position: absolute;
  right: 12px;
  bottom: 12px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 100px;
  background: rgba(11,13,16,0.78);
  color: #E7E9EC;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  pointer-events: none;
  transition: opacity 0.28s var(--ease-ui);
}
.shot.is-ended .shot-hint { opacity: 0; }

/* ── Rendered email mock (MindFlow) ──
   Lives inside the same .shot frame as the screenshot cases, so all three
   case visuals share one height and one chrome. */
.mock-inner {
  background: #FFFFFF;
  color: #16181C;
  font-family: var(--sans);
}
.mock-from { display: flex; align-items: center; gap: 11px; padding: 13px 18px; border-bottom: 1px solid rgba(11,13,16,0.09); }
.mock-avatar {
  width: 32px; height: 32px; border-radius: 50%;
  background: #2450E8; color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--display); font-size: 16px; font-style: italic;
  flex-shrink: 0;
}
.mock-from .who { flex: 1; min-width: 0; }
.mock-from .name { font-size: 12.5px; font-weight: 600; }
.mock-from .addr, .mock-from .time { font-family: var(--mono); font-size: 10.5px; color: #767D88; }
.mock-banner { padding: 15px 18px; background: #EEF1FE; text-align: center; }
.mock-banner span { font-family: var(--display); font-style: italic; font-size: 18px; color: #16181C; }
.mock-hero { position: relative; aspect-ratio: 16/9; background: #2450E8; overflow: hidden; }
.mock-hero img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 0.5s var(--ease-ui); }
.mock-hero img.is-loaded { opacity: 1; }
.mock-hero .fallback {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--display); font-style: italic; font-size: 24px; color: rgba(255,255,255,0.9);
}
.mock-body { padding: 20px 22px 8px; }
.mock-pre { font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.05em; text-transform: uppercase; color: #767D88; margin-bottom: var(--s-3); }
.mock-subject { font-family: var(--display); font-size: 21px; font-weight: 400; line-height: 1.2; letter-spacing: -0.012em; margin-bottom: var(--s-4); }
.mock-body p { font-size: 13.5px; line-height: 1.6; color: #383E47; margin-bottom: 10px; }
.mock-body p strong { color: #16181C; font-weight: 600; }
.mock-body p em { color: #16181C; }
.mock-list { list-style: none; padding: 12px 15px; margin: 4px 0 14px; background: #F4F6FE; border-radius: var(--radius-s); }
.mock-list li { font-size: 13px; line-height: 1.5; color: #383E47; padding: 3px 0 3px 20px; position: relative; }
.mock-list li::before { content: '→'; position: absolute; left: 0; color: #2450E8; }
.mock-cta { text-align: center; padding: 10px 0 4px; }
.mock-cta span { display: inline-block; background: #2450E8; color: #fff; padding: 11px 24px; border-radius: var(--radius-s); font-size: 13px; font-weight: 600; }
.mock-ps { margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid rgba(11,13,16,0.09); font-size: 12.5px; line-height: 1.5; color: #5A616B; font-style: italic; }
.mock-ps strong { font-style: normal; color: #16181C; }
.mock-foot { margin-top: var(--s-4); padding: 14px 22px 16px; background: #F5F5F2; border-top: 1px solid rgba(11,13,16,0.09); text-align: center; font-family: var(--mono); font-size: 9.5px; line-height: 1.7; color: #767D88; }

/* ============================================================
   Closing CTA
   ============================================================ */

.close {
  position: relative;
  padding: var(--s-11) 0;
  overflow: hidden;
  border-top: 1px solid var(--line);
}
.close::before {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  z-index: 2;
  transform: translate(-50%, -50%);
  width: 900px; height: 620px;
  background: radial-gradient(ellipse 50% 50% at 50% 50%, rgba(59,107,255,0.18) 0%, rgba(59,107,255,0.05) 45%, transparent 72%);
  pointer-events: none;
}
.close > .wrap { position: relative; z-index: 3; }

/* Closing CTA footage — the hero reprised rather than repeated: the
   same loop, blurred past the point of being readable as an image and
   dimmed, so it registers as light behind the copy and nothing more. */
.close-film-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  opacity: 0.38;
  /* Overscaled so the blur's soft edge falls outside the section and
     never leaves a pale seam along the borders. */
  transform: scale(1.16);
  filter: blur(26px) saturate(0.8);
  pointer-events: none;
}
/* The copy has to sit on a stable base wherever the light form in the
   footage drifts, and the section has to meet the neighbouring dark
   blocks with no visible seam — hence solid --bg at both ends. */
.close-film-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(180deg,
      var(--bg) 0%,
      rgba(11,13,16,0.62) 24%,
      rgba(11,13,16,0.62) 76%,
      var(--bg) 100%),
    radial-gradient(115% 90% at 28% 50%, rgba(11,13,16,0.55) 0%, rgba(11,13,16,0.22) 52%, transparent 82%);
}
.close h2 { max-width: 17ch; }
.close .lede { margin-top: var(--s-5); }
.close .cta-row { margin-top: var(--s-7); }
/* The caveat is prose. It was previously set in uppercase mono, which
   made the most human sentence on the page the hardest one to read. */
.close-caveat {
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line-2);
  font-size: 14px;
  line-height: 1.65;
  color: var(--text-3);
  max-width: 60ch;
}
.close-caveat strong { color: var(--text-2); font-weight: 500; }

/* ============================================================
   Footer
   ============================================================ */

.foot { border-top: 1px solid var(--line); padding: var(--s-8) 0 var(--s-7); }
.foot-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-6);
  flex-wrap: wrap;
  padding-bottom: var(--s-6);
  margin-bottom: var(--s-6);
  border-bottom: 1px solid var(--line-2);
}
.foot-tagline { font-family: var(--display); font-size: 23px; letter-spacing: -0.015em; }
.foot-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  flex-wrap: wrap;
}
.foot-meta { font-family: var(--mono); font-size: 11px; color: var(--text-3); }
.foot-links { display: flex; gap: var(--s-4); font-size: 13px; }
.foot-links a { color: var(--text-3); transition: color 0.18s var(--ease-ui); }
.foot-links a:hover { color: var(--text-2); }
.socials { display: flex; gap: var(--s-3); }
.socials a {
  width: 34px; height: 34px;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-3);
  transition: color 0.18s var(--ease-ui), border-color 0.18s var(--ease-ui);
}
.socials a:hover { color: var(--text); border-color: var(--text-3); }
.socials svg { width: 15px; height: 15px; }

/* ============================================================
   Legal page
   ============================================================ */

.legal { max-width: 720px; }
.legal-section { padding: var(--s-8) 0; border-bottom: 1px solid var(--line-2); }
.legal-section:last-of-type { border-bottom: 0; }
.legal-section h2 { font-family: var(--display); font-size: var(--t-m); font-weight: 400; letter-spacing: -0.02em; margin-bottom: var(--s-4); }
.legal-section h3 { font-size: 15px; font-weight: 600; color: var(--text); margin: var(--s-5) 0 var(--s-2); }
.legal-section p, .legal-section li { font-size: 15px; line-height: 1.72; color: var(--text-2); }
.legal-section p + p { margin-top: var(--s-3); }
.legal-section ul { margin: var(--s-3) 0 var(--s-3) var(--s-5); }
.legal-section li + li { margin-top: 6px; }
.legal-section a { color: var(--signal); }
.legal-section a:hover { color: var(--signal-hi); text-decoration: underline; }
.legal-section strong { color: var(--text); font-weight: 500; }
.todo {
  background: var(--signal-wash);
  border: 1px dashed var(--signal);
  color: var(--signal-hi);
  padding: 1px 7px;
  border-radius: 3px;
  font-family: var(--mono);
  font-size: 12px;
}

/* ============================================================
   Motion — one entrance, then the page holds still
   ============================================================ */

.rise { opacity: 0; transform: translateY(14px); }
.is-ready .rise { transition: opacity 0.62s var(--ease), transform 0.62s var(--ease); }
.rise.is-in { opacity: 1; transform: none; }

/* Hero entrance: a single orchestrated sequence that settles and stops.
   Delays live on the element so the order is readable in one place. */
.hero .rise:nth-child(1) { transition-delay: 0.02s; }
.hero .rise:nth-child(2) { transition-delay: 0.10s; }
.hero .rise:nth-child(3) { transition-delay: 0.18s; }
.hero .rise:nth-child(4) { transition-delay: 0.26s; }
.hero .rise:nth-child(5) { transition-delay: 0.34s; }

/* Staggered sets — only where the group genuinely is a set */
.stagger > * { opacity: 0; transform: translateY(14px); }
.is-ready .stagger > * { transition: opacity 0.55s var(--ease), transform 0.55s var(--ease); }
.stagger.is-in > * { opacity: 1; transform: none; }
.stagger.is-in > *:nth-child(1) { transition-delay: 0s; }
.stagger.is-in > *:nth-child(2) { transition-delay: 0.07s; }
.stagger.is-in > *:nth-child(3) { transition-delay: 0.14s; }
.stagger.is-in > *:nth-child(4) { transition-delay: 0.21s; }
.stagger.is-in > *:nth-child(5) { transition-delay: 0.28s; }
.stagger.is-in > *:nth-child(6) { transition-delay: 0.35s; }

/* Before JS marks the document ready, nothing is hidden — no-JS visitors
   get the full page rather than a blank one. */
html:not(.is-ready) .rise,
html:not(.is-ready) .stagger > * { opacity: 1; transform: none; }

@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;
    transition-delay: 0ms !important;
  }
  .rise, .stagger > * { opacity: 1 !important; transform: none !important; }
}

/* ============================================================
   Responsive
   ============================================================ */

@media (max-width: 1080px) {
  :root { --rail: 108px; --gut: 32px; }
  .about-grid { grid-template-columns: 220px 1fr; gap: var(--s-7); }
  .index-row .brand { width: 150px; }
}

@media (max-width: 900px) {
  :root { --gut: 28px; }
  /* The rail folds into a label above its section rather than
     squeezing into an unreadable column */
  .rail { grid-template-columns: 1fr; gap: var(--s-5); }
  .rail-note { padding-top: 0; }
  .rail-note b, .rail-note span { display: inline; }
  .rail-note b::after { content: ' · '; color: var(--text-3); }
  .rail-note:empty { display: none; }

  .about-grid { grid-template-columns: 1fr; gap: var(--s-6); }
  .portrait { max-width: 240px; }

  .tl-t { font-size: 17px; }

  .work-grid { grid-template-columns: 1fr; }
  .case-row { grid-template-columns: 1fr; gap: var(--s-6); }

  .index-row { flex-wrap: wrap; gap: var(--s-2) var(--s-4); }
  .index-row .brand { width: auto; }
  .index-row .t { width: 100%; }
}

@media (max-width: 860px) {
  .nav-links, .nav-cta { display: none; }
  .burger { display: block; }
}

@media (max-width: 640px) {
  :root { --gut: 22px; --nav-h: 64px; }
  body { font-size: 15.5px; }

  .hero { padding-top: calc(var(--nav-h) + var(--s-8)); }
  .hero h1 { max-width: none; }
  .section { padding: var(--s-9) 0; }
  .section--wide { padding: var(--s-10) 0; }
  .close { padding: var(--s-10) 0; }

  .stats-grid { grid-template-columns: 1fr; }
  .stat { padding: var(--s-5) 0; border-top: 1px solid var(--line-2); }
  .stat:first-child { border-top: 0; padding-top: 0; }
  .stat + .stat { border-left: 0; padding-left: 0; }
  .stat-l { max-width: none; }

  /* Vertical rail: four labelled nodes will not fit across a phone.
     Rows are a fixed height so the travelled rail can be a multiple
     of one row, exactly as the horizontal version is of one column. */
  .tl { --tl-dot: 46px; --tl-row: 64px; }
  .tl-track { grid-template-columns: 1fr; grid-auto-rows: var(--tl-row); padding-top: 0; }
  .tl-track::before,
  .tl-track::after {
    top: calc(var(--tl-dot) / 2 - 1px);
    left: calc(var(--tl-dot) / 2 - 1px);
    right: auto;
    width: 2px;
    height: auto;
  }
  .tl-track::before { bottom: calc(var(--tl-row) - var(--tl-dot) / 2); }
  .tl-track::after {
    width: 2px;
    height: calc(var(--tl-i) * var(--tl-row));
    transition: height 0.62s var(--ease);
  }
  /* Top-aligned in its row, so every node centre lands exactly one
     row apart and the travelled rail stays on the nodes. */
  .tl-step {
    align-self: start;
    flex-direction: row;
    align-items: center;
    gap: var(--s-4);
    padding: 0;
    text-align: left;
  }
  .tl-label { flex-direction: row; align-items: baseline; gap: 10px; }
  .tl-step.is-active .tl-dot,
  .tl-step:hover .tl-dot { transform: none; }
  .tl-step.is-active .tl-dot { transform: scale(1.04); }
  .tl-panels { margin-top: var(--s-4); }
  .tl-panel p { font-size: 16px; }

  .foot-top { flex-direction: column; align-items: flex-start; gap: var(--s-4); }
  .foot-bottom { flex-direction: column; align-items: flex-start; }
  .menu a { font-size: 28px; }
  .shot-scroll { height: 380px; }
}
