/* ============================================================================
   MAKA Studio
   Dark theme, locked page-wide. One accent (electric blue). The blue/violet
   gradient appears only where the brand mark itself appears, never as
   decoration. Radius rule: buttons are pill, everything else is 16px.
   ========================================================================= */

/* Self-hosted, not fetched from Google. A webfont request carries the
   visitor's IP address to whoever serves it, and that was the only third
   party this site touched. Google ships Archivo as one variable file for the
   whole 400-700 range, so hosting it costs 34KB and one request. */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('assets/fonts/archivo-var.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --ink:        #05060a;
  --ink-2:      #0a0c14;
  --ink-3:      #10131d;
  --line:       rgba(255, 255, 255, .085);
  --line-2:     rgba(255, 255, 255, .16);
  --text:       #e9ecf5;
  --muted:      #98a1b6;
  --accent:     #5b8cff;
  --accent-ink: #04060d;
  --brand-a:    #4dd8ff;
  --brand-b:    #7a5cf6;

  --r:      16px;
  --shell:  min(1240px, 100% - 2.5rem);
  --sec-y:  clamp(6rem, 13vh, 10.5rem);

  /* One family, carried by weight contrast rather than by a second typeface.
     Archivo is a working grotesque with enough width and a flat, engineered
     axis that sits with the wireframe mark; two similar sans-serifs would
     have read as indecision. */
  --display: 'Archivo', system-ui, sans-serif;
  --body:    'Archivo', system-ui, sans-serif;
  --ease:    cubic-bezier(.16, 1, .3, 1);

  /* How much of the screen the browser's own bars are covering RIGHT NOW.
     Anything pinned to the bottom of the stage is lifted by this, so it
     clears the bars while they are showing and drops back to the true bottom
     the moment they retract. Zero on every desktop browser.

     lvh minus dvh, not lvh minus svh: svh is a fixed number, so it lifted the
     copy by the height of bars that were no longer there and pushed it up
     into the film's own lockup. dvh tracks the live viewport. It only ever
     appears in a `bottom` offset, never in a height, so nothing resizes and
     the film is never reframed by a bar sliding away. */
  --chrome: 0px;

  /* semantic layers, so nothing ever reaches for an arbitrary 9999 */
  --z-base:  1;
  --z-page:  2;
  --z-nav:   30;
  --z-skip:  60;
}

* { box-sizing: border-box; }

/* The page ends where the footer ends: measured, there is no dead space after
   it. What reads as one on a phone is the elastic scroll, which drags the
   document up past its own end and shows bare background underneath. On a
   page this dark that looks like a black screen you scrolled into rather than
   a bounce. Turning it off costs pull-to-refresh, which this site does not
   want anyway, and the page then simply stops at its last line. */
html {
  scroll-behavior: smooth;
  overscroll-behavior-y: none;
  background: var(--ink);
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

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

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

.skip {
  position: absolute; left: -9999px; top: 0; z-index: var(--z-skip);
  background: var(--accent); color: var(--accent-ink);
  padding: .7rem 1.1rem; border-radius: 0 0 var(--r) 0; font-weight: 600;
}
.skip:focus { left: 0; }

/* ── type ─────────────────────────────────────────────────────────────── */

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: -.028em;
  /* light type on a dark ground reads lighter than it is, so headings get a
     little more room than the usual display leading */
  line-height: 1.1;
  margin: 0;
  text-wrap: balance;
}

.h2 { font-size: clamp(2rem, 4.4vw, 3.35rem); max-width: 19ch; }

.lede {
  color: var(--muted);
  font-size: clamp(1.02rem, 1.35vw, 1.18rem);
  max-width: 68ch;
  margin: 1.4rem 0 0;
  text-wrap: pretty;
}

p { text-wrap: pretty; }

/* ── buttons ──────────────────────────────────────────────────────────── */

.btn {
  --pad: .95rem 1.7rem;
  display: inline-flex; align-items: center; justify-content: center;
  gap: .5rem;
  padding: var(--pad);
  min-height: 46px;                  /* clears the 44px touch minimum outright */
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--display);
  font-weight: 700;
  font-size: .95rem;
  letter-spacing: -.01em;
  text-decoration: none;
  white-space: nowrap;
  border: 1px solid transparent;
  transition: transform .18s var(--ease), box-shadow .25s var(--ease),
              background .2s var(--ease);
}
.btn:hover { background: #7ba4ff; box-shadow: 0 12px 34px rgba(91, 140, 255, .28); }
.btn:active { transform: translateY(1px); }

.btn--ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--line-2);
}
.btn--ghost:hover { background: rgba(255, 255, 255, .06); box-shadow: none; }

.btn--sm { --pad: .6rem 1.15rem; font-size: .85rem; }
.btn--lg { --pad: 1.1rem 2.3rem; font-size: 1.02rem; }

/* ── nav ──────────────────────────────────────────────────────────────── */

.nav {
  position: fixed; inset: 0 0 auto; z-index: var(--z-nav);
  height: 70px;
  display: flex; align-items: center; gap: 2rem;
  padding: 0 max(1.25rem, calc((100vw - var(--shell)) / 2));
  background: rgba(5, 6, 10, .55);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid transparent;
  transition: background .3s var(--ease), border-color .3s var(--ease);
}
.nav.is-stuck {
  background: rgba(5, 6, 10, .86);
  border-bottom-color: var(--line);
}

.brand {
  display: inline-flex; align-items: center; gap: .6rem;
  min-height: 44px;                 /* touch target, not just a text run */
  color: var(--text); text-decoration: none;
  font-family: var(--display); font-size: 1.02rem; letter-spacing: -.01em;
  font-weight: 500;
}
.brand b { font-weight: 700; }
.brand img { width: 34px; height: auto; }

.nav__links {
  display: flex; gap: 1.9rem; margin-left: auto;
  font-size: .92rem;
}
.nav__links a {
  color: var(--muted); text-decoration: none;
  transition: color .2s var(--ease);
}
.nav__links a:hover { color: var(--text); }

@media (max-width: 860px) {
  .nav { gap: 1rem; height: 64px; }
  .nav__links { display: none; }
  .nav .btn { margin-left: auto; }
}

/* ── intro: the film ──────────────────────────────────────────────────── */

/* The stage is sized to the LARGEST the viewport ever gets, not the smallest.
   svh is the height with the browser's own bars showing; the moment a phone
   retracts them on the first scroll the screen grows and a stage built to svh
   comes up short, which is the black strip that appeared under the film. lvh
   always covers. The cost is that the bottom of the stage sits behind the
   bars while they are visible, so everything down there is lifted by
   --chrome, which is exactly that difference.

   dvh would also cover, and would also resize the canvas on every bar
   transition, which means reframing the film mid-scroll. Not worth it. */
.intro { position: relative; height: 420svh; height: 420lvh; }

.intro__stage {
  position: sticky; top: 0;
  height: 100svh;
  height: 100lvh;
  overflow: hidden;
  background: var(--ink);
}

@supports (height: 100lvh) and (height: 100dvh) {
  :root { --chrome: calc(100lvh - 100dvh); }
}

.intro__canvas,
.intro__fallback {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}

/* Its own compositor layer. The canvas repaints on every frame of the scrub,
   and without this each repaint dirties the sticky container it sits in,
   which on a phone means re-rastering the whole stage instead of swapping
   one texture. */
.intro__canvas {
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* Comes up with the closing copy, not before it. At the top of the track the
   film is clean, with nothing laid over it and nothing dimming it. */
.intro__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to top,
    rgba(5, 6, 10, .92) 0%,
    rgba(5, 6, 10, .55) 22%,
    rgba(5, 6, 10, 0) 46%);
  opacity: var(--scrim, 1);
  pointer-events: none;
}

/* Arrives at the end of the film, into the space under its closing lockup,
   not at the top over the opening mark. Bottom of the stage, centred under a
   centred composition, sized as a line of copy rather than a display
   headline. It is still the h1, so the page still leads with what is sold.

   The opacity default is 1, not 0. The script drives it down to 0 at the top
   of the track and back up at the end; a browser that never runs the script
   shows the copy outright rather than shipping an invisible headline. */
.intro__open {
  position: absolute; left: 0; right: 0;
  bottom: calc(clamp(1.8rem, 5vh, 3.2rem) + 3.6rem + var(--chrome));
  padding: 0 max(1.25rem, calc((100vw - var(--shell)) / 2));
  text-align: center;
  opacity: var(--open-o, 1);
  transform: translateY(calc(var(--open-y, 0) * 1px));
  pointer-events: var(--open-pe, auto);
}

.intro__open h1 {
  font-size: clamp(1.02rem, 1.5vw, 1.42rem);
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: 0;
  max-width: 44ch;
  margin-inline: auto;
  text-wrap: balance;
}

.intro__cta {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: .8rem; margin-top: 1.25rem;
}

/* Nothing on this page moves until you scroll, and a film that holds still
   reads as a page that has finished loading. The cue is a word and a line
   with a light running down it, not a bouncing arrow: it says which way,
   once, and gets out of the way the moment the first scroll happens. */
.intro__cue {
  position: absolute; left: 50%;
  bottom: calc(clamp(.9rem, 2.4vh, 1.5rem) + var(--chrome));
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: .55rem;
  opacity: var(--cue-o, 1);
  pointer-events: none;
}
.intro__cue span {
  font-family: var(--display);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .34em;
  text-indent: .34em;
  text-transform: uppercase;
  color: rgba(233, 236, 245, .74);
}
.intro__cue i {
  position: relative; overflow: hidden;
  width: 1px; height: 30px;
  background: rgba(255, 255, 255, .17);
}
.intro__cue i::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to bottom,
    transparent, var(--accent) 45%, transparent);
  animation: cue 2.2s var(--ease) infinite;
}
@keyframes cue {
  0%        { transform: translateY(-100%); }
  55%, 100% { transform: translateY(100%); }
}

/* On a laptop the film is barely taller than the viewport, so the wordmark it
   draws lands only just above this block. Laying the line and the buttons on
   one row instead of two takes about 60px back, which is the whole clearance
   on a 16:9 screen. Measured at 966x560, the tightest shape that still gets
   the landscape sequence. */
@media (min-width: 900px) {
  .intro__open {
    display: flex; align-items: center; justify-content: center;
    gap: 2.2rem;
    text-align: left;
    /* the cue is compact here, so it costs the copy less headroom than it
       does on a phone, where the two stack with room to breathe */
    bottom: calc(clamp(1.8rem, 5vh, 3.2rem) + 2.4rem + var(--chrome));
  }
  /* two lines, not three. On a 16:9 laptop the film's own wordmark sits at
     about 71% of the screen and everything below it has to fit in what is
     left, so the third line was the difference between a clear gap and a
     collision. */
  .intro__open h1 { max-width: 46ch; }
  .intro__cta { margin-top: 0; flex: none; }

  .intro__cue {
    bottom: calc(clamp(.6rem, 1.5vh, 1rem) + var(--chrome));
    gap: .4rem;
  }
  .intro__cue i { height: 20px; }
}

/* ── sections ─────────────────────────────────────────────────────────── */

main { position: relative; z-index: var(--z-page); background: var(--ink); }

.sec {
  width: var(--shell);
  margin-inline: auto;
  padding-block: var(--sec-y);
}

/* ── what we sell: three outcomes, three visual worlds ────────────────── */

/* Two tall tiles over one wide one. Deliberately not a row of equal cards:
   the film gives each outcome its own frame, and the colour on this section
   comes from the footage itself rather than from a tint invented for it. */
.sell {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1rem, 1.6vw, 1.4rem);
  margin-top: clamp(3rem, 6vw, 4.5rem);
}

.out {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: calc(var(--r) + 6px);
  border: 1px solid var(--line);
  display: flex;
  align-items: flex-end;
  padding: clamp(1.6rem, 3vw, 2.6rem);
  min-height: clamp(360px, 46vh, 520px);
  transition: border-color .45s var(--ease);
}
.out--wide { grid-column: 1 / -1; min-height: clamp(300px, 34vh, 380px); }

.out__art {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.02);
  transition: transform 1.1s var(--ease);
}
/* the scrim is brand blue, not neutral black: it keeps the copy at contrast
   while letting the section read as coloured rather than as grey footage */
.out::after {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background:
    /* the copy sits in the bottom half of the tile, so the scrim has to stay
       near-opaque that far up rather than fading at the midpoint */
    linear-gradient(to top,
      rgba(3, 5, 14, .97) 0%,
      rgba(4, 7, 20, .95) 55%,
      rgba(8, 13, 38, .60) 78%,
      rgba(12, 20, 54, .16) 100%),
    linear-gradient(120deg,
      rgba(91, 140, 255, .16), rgba(122, 92, 246, .10) 60%, transparent);
}
.out:hover { border-color: rgba(91, 140, 255, .45); }
.out:hover .out__art { transform: scale(1.06); }

.out h3 {
  font-size: clamp(1.6rem, 3vw, 2.35rem);
  margin-bottom: .8rem;
}
.out p { margin: 0; color: #c3cbe0; max-width: 46ch; }

.out__meta {
  margin-top: 1.15rem !important;
  font-size: .92rem;
  font-weight: 600;
  color: #9dbcff !important;
}

@media (max-width: 760px) {
  .sell { grid-template-columns: 1fr; }
  .out--wide { grid-column: 1 / -1; }
  .out { min-height: 330px; }
}

/* ── what we build: capability rows ───────────────────────────────────── */

.rows { list-style: none; margin: clamp(2.5rem, 5vw, 4rem) 0 0; padding: 0; }

.row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(.6rem, 4vw, 4rem);
  align-items: baseline;
  padding: clamp(1.4rem, 2.6vw, 2.1rem) clamp(1rem, 2vw, 1.6rem);
  border-top: 1px solid var(--line);
  transition: color .35s var(--ease);
}
.row:last-child { border-bottom: 1px solid var(--line); }

/* a wash of brand light that opens from the left edge on hover, plus a hairline
   that draws across the top. Motion with a job: it tells you which of eight
   near-identical rows you are actually on. */
.row::before {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  border-radius: 10px;
  background: linear-gradient(90deg,
    rgba(91, 140, 255, .14), rgba(122, 92, 246, .07) 45%, transparent 80%);
  opacity: 0;
  transition: opacity .4s var(--ease);
}
.row::after {
  content: '';
  position: absolute; left: 0; top: -1px; height: 1px; width: 0;
  background: linear-gradient(90deg, var(--brand-a), var(--brand-b));
  transition: width .55s var(--ease);
}
.row:hover::before { opacity: 1; }
.row:hover::after { width: 100%; }

.row h3 {
  font-size: clamp(1.35rem, 2.5vw, 1.95rem);
  font-weight: 500;
  letter-spacing: -.02em;
  transition: color .35s var(--ease);
}
.row:hover h3 { color: #9dbcff; }
.row p { margin: 0; color: var(--muted); font-size: .97rem; max-width: 56ch; }

/* the last row is the open invitation, so it carries the accent outright */
.row--ask h3 { color: var(--accent); }

@media (max-width: 760px) {
  .row { grid-template-columns: 1fr; gap: .5rem; padding-inline: 0; }
}

/* ── selected work ────────────────────────────────────────────────────── */

.case {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
  margin-top: clamp(2.5rem, 5vw, 4rem);
}
.case__shot img {
  width: 100%; height: auto;
  border-radius: var(--r);
  border: 1px solid var(--line);
}
.case__body h3 { font-size: clamp(1.6rem, 3vw, 2.3rem); }
.case__what { color: var(--text); margin: .8rem 0 0; }
.case__body p { color: var(--muted); }
.case__link {
  display: inline-block; margin-top: 1.4rem;
  color: var(--accent); text-decoration: none;
  border-bottom: 1px solid rgba(91, 140, 255, .4);
  padding-bottom: 2px;
}
@media (max-width: 860px) { .case { grid-template-columns: 1fr; } }

/* ── steps: how we work ───────────────────────────────────────────────── */

/* A track, not another stack of rows. The section immediately above it is a
   list of eight rows; repeating that shape here would have made the page read
   as one long undifferentiated column. This is genuinely a sequence, so it is
   drawn as one: a lit line with a node per stage. */
.steps {
  list-style: none;
  margin: clamp(3.5rem, 7vw, 5rem) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.6rem);
  position: relative;
}
/* the line the nodes sit on */
.steps::before {
  content: '';
  position: absolute; left: 0; right: 0; top: 7px; height: 1px;
  background: linear-gradient(90deg,
    var(--brand-a), var(--brand-b) 55%, rgba(122, 92, 246, .18));
}

.step { position: relative; padding-top: 2.6rem; }
.step::before {
  content: '';
  position: absolute; left: 0; top: 0;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: var(--ink);
  border: 2px solid var(--brand-a);
  box-shadow: 0 0 0 4px rgba(77, 216, 255, .12),
              0 0 18px rgba(77, 216, 255, .45);
}
.step:nth-child(2)::before { border-color: #6aa2ff;
  box-shadow: 0 0 0 4px rgba(106, 162, 255, .12), 0 0 18px rgba(106, 162, 255, .45); }
.step:nth-child(3)::before { border-color: #8a7bf8;
  box-shadow: 0 0 0 4px rgba(138, 123, 248, .12), 0 0 18px rgba(138, 123, 248, .45); }
.step:nth-child(4)::before { border-color: var(--brand-b);
  box-shadow: 0 0 0 4px rgba(122, 92, 246, .12), 0 0 18px rgba(122, 92, 246, .45); }

.step h3 { font-size: clamp(1.35rem, 2.2vw, 1.8rem); margin-bottom: .6rem; }
.step p { margin: 0; color: var(--muted); font-size: .95rem; max-width: 34ch; }

@media (max-width: 880px) {
  .steps { grid-template-columns: 1fr; gap: 0; padding-left: 2.2rem; }
  /* the track turns vertical rather than disappearing */
  .steps::before {
    left: 7px; right: auto; top: 8px; bottom: 8px; width: 1px; height: auto;
    background: linear-gradient(180deg,
      var(--brand-a), var(--brand-b) 60%, rgba(122, 92, 246, .18));
  }
  .step { padding-top: 0; padding-bottom: 2.2rem; padding-left: 0; margin-left: -2.2rem; }
  .step::before { left: 0; top: 4px; }
  .step h3, .step p { margin-left: 2.2rem; }
  .step p { max-width: 46ch; }
}

/* ── fit: who this is for, and who it is not ──────────────────────────── */

.fit {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1rem, 2vw, 1.6rem);
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}

/* the qualifying column sits on a lit surface, the disqualifying one stays
   flat against the page. The material does the arguing before the copy does. */
.fit__col {
  border-radius: calc(var(--r) + 4px);
  padding: clamp(1.5rem, 2.6vw, 2.2rem);
}
.fit__col:first-child {
  background:
    linear-gradient(160deg, rgba(91, 140, 255, .13), rgba(122, 92, 246, .05) 70%,
      transparent),
    var(--ink-2);
  border: 1px solid rgba(91, 140, 255, .28);
}
.fit__col:last-child {
  border: 1px solid var(--line);
}

/* real headings, not tracked micro-labels */
.fit__head {
  font-size: 1.22rem;
  font-weight: 600;
  letter-spacing: -.015em;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--line);
}
.fit__head--yes { color: var(--accent); }
.fit__head--no  { color: var(--text); }

.fit ul { list-style: none; margin: 0; padding: 0; }
.fit li {
  color: var(--muted);
  padding-block: clamp(.9rem, 1.6vw, 1.2rem);
  border-bottom: 1px solid var(--line);
  max-width: 46ch;
}

/* the disqualifying column is quieter, but only just: it dropped under 4.5:1
   at the tint it had before, and unreadable is not the same as understated */
.fit__col:last-child li { color: rgba(152, 161, 182, .88); }

@media (max-width: 760px) {
  .fit { grid-template-columns: 1fr; gap: 2.5rem; }
}

/* ── marquee ──────────────────────────────────────────────────────────── */

.marquee {
  border-block: 1px solid var(--line);
  overflow: hidden;
  padding-block: 1.5rem;
  background: var(--ink-2);
}
.marquee__track {
  display: flex; width: max-content; gap: 3.5rem;
  animation: slide 42s linear infinite;
}
.marquee__track span {
  font-family: var(--display);
  font-size: clamp(1.1rem, 2.4vw, 1.7rem);
  color: rgba(233, 236, 245, .62);
  white-space: nowrap;
}
@keyframes slide { to { transform: translateX(-50%); } }

/* ── contact ──────────────────────────────────────────────────────────── */

/* The one drenched moment on the page. Everything above it is dark and
   restrained, which is what lets this land as an event rather than as another
   section: the conversion step should not look like the reading steps. */
.contact {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  text-align: center;
  padding-block: clamp(6rem, 15vh, 11rem);
  padding-inline: max(1.25rem, calc((100vw - var(--shell)) / 2));
}
.contact__art {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: .55;
}
.contact::after {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(ellipse 80% 70% at 50% 45%,
      rgba(58, 96, 224, .55), rgba(84, 46, 210, .40) 45%, rgba(4, 6, 16, .92) 82%),
    linear-gradient(180deg, var(--ink) 0%, transparent 22%, transparent 78%, var(--ink) 100%);
}

.contact .h2 { margin-inline: auto; max-width: 17ch; }
.contact .lede { margin-inline: auto; color: #cfd8ef; }
.contact .btn { margin-top: 2.6rem; }

/* on a colour field the blue CTA disappears into its own background, so the
   button inverts to carry the contrast instead */
.btn--light {
  background: #f2f5ff;
  color: #0a1030;
}
.btn--light:hover {
  background: #fff;
  box-shadow: 0 14px 40px rgba(10, 16, 48, .45);
}

/* ── footer ───────────────────────────────────────────────────────────── */

.foot {
  width: var(--shell); margin-inline: auto;
  border-top: 1px solid var(--line);
  padding-block: 2.6rem 3.4rem;
  display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 2rem;
}
.foot__line { color: var(--muted); font-size: .92rem; margin: 0; }
.foot__copy { margin: 0 0 0 auto; color: rgba(152, 161, 182, .92); font-size: .88rem; }

.foot__social,
.foot__legal { display: flex; flex-wrap: wrap; gap: .6rem; margin-inline: -.7rem; }
/* padded out to a 44px touch target: at their type size these links were 25px
   tall, which is a miss on a phone even when it reads fine on a desktop */
.foot__social a,
.foot__legal a {
  display: inline-flex; align-items: center;
  min-height: 44px; padding-inline: .7rem;
  color: var(--muted); text-decoration: none; font-size: .92rem;
  transition: color .2s var(--ease);
}
.foot__social a:hover,
.foot__legal a:hover { color: var(--text); }
.foot__social a:hover span { border-bottom-color: var(--line-2); }

@media (max-width: 620px) {
  .foot__copy { margin-left: 0; }
}

/* ── legal documents ──────────────────────────────────────────────────── */

/* Read, not skimmed: one column at a comfortable measure, generous leading,
   no cards and no decoration. The page has one job, which is to be legible
   and complete. */
.doc {
  position: relative; z-index: var(--z-page);
  background: var(--ink);
  padding-block: clamp(4.5rem, 11vh, 7.5rem) clamp(3rem, 7vh, 5rem);
}
.doc__shell { width: min(72ch, 100% - 2.5rem); margin-inline: auto; }

.doc__back {
  margin: 0 0 2.4rem;
  font-size: .92rem;
}
.doc__back a { color: var(--accent); text-decoration: none; }
.doc__back a:hover { text-decoration: underline; }

.doc h1 {
  font-size: clamp(2.1rem, 4.4vw, 3.1rem);
  line-height: 1.08;
  letter-spacing: -.025em;
  margin: 0;
  text-wrap: balance;
}
.doc__date {
  color: var(--muted);
  font-size: .92rem;
  margin: .9rem 0 0;
}
.doc__intro {
  font-size: 1.06rem;
  color: var(--text);
  margin: 2rem 0 0;
  padding-bottom: 2.2rem;
  border-bottom: 1px solid var(--line);
}

.doc h2 {
  font-size: clamp(1.18rem, 2vw, 1.42rem);
  line-height: 1.25;
  letter-spacing: -.01em;
  margin: 3rem 0 0;
}
.doc h3 {
  font-size: 1.02rem;
  margin: 2rem 0 0;
}
.doc p, .doc li {
  color: var(--muted);
  font-size: .99rem;
  line-height: 1.75;
  text-wrap: pretty;
}
.doc p { margin: .9rem 0 0; }
.doc ul { margin: .9rem 0 0; padding-left: 1.15rem; }
.doc li { margin-top: .5rem; }
.doc a { color: var(--accent); }
.doc strong { color: var(--text); font-weight: 600; }

/* the one place a document raises its voice: what the site does not do */
.doc__note {
  margin-top: 2.2rem;
  padding: 1.3rem 1.5rem;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: var(--ink-2);
}
.doc__note p { margin-top: .6rem; }
.doc__note p:first-child { margin-top: 0; color: var(--text); }

/* ── reveal ───────────────────────────────────────────────────────────── */

/* Visible is the default state. The hidden state only exists once the script
   has confirmed it can actually run the observer, and it is released again by
   a hard timeout. A reveal that gates visibility on a class ships the section
   blank anywhere the transition never fires: background tabs, headless
   renderers, any browser that throttles the observer. That is not a
   hypothetical, it happened on this page. */
html.reveals .reveal:not(.is-in) {
  opacity: 0;
  transform: translateY(22px);
}
html.reveals .reveal {
  transition: opacity .7s var(--ease), transform .7s var(--ease);
}

/* ── reduced motion ───────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  /* the film collapses to a single held frame: no scrub, no track */
  .intro { height: auto; }
  .intro__stage { position: static; height: 88svh; }
  .intro__open { --open-o: 1; --open-y: 0; }
  /* the cue still says which way to go, it just stops travelling */
  .intro__cue i::after { animation: none; background: var(--accent); top: 55%; }

  .marquee__track { animation: none; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .btn, .cell { transition: none; }
}
