/* =========================================================
   Zettacraftsman
   Design language: annotated technical drawing, on white paper.
   Azure is the drawn line. Coral is the thing you act on.
   The page is light throughout; the hero and contact block are the
   two dark bookends.
   ========================================================= */

/* ---------- tokens ---------- */
:root {
  /* light surfaces — the page is white-dominant */
  --paper:      #FFFFFF;
  --surface:    #F2F5F8;
  --surface-2:  #E5EBF2;
  --rule-light: #DCE3EB;

  /* dark surfaces — masthead, hero, contact, footer */
  --ink:        #0F1722;
  --ink-raise:  #16202E;
  --deep:       #1B2A3F;
  --rule:       #27364C;

  /* accents. -deep variants are the ones with enough contrast to be text
     on white; the plain ones are for strokes, fills and dark grounds. */
  --azure:      #1D6FE0;
  --azure-soft: #1D6FE033;
  /* Lifted from #4E92EE: the hero eyebrow sits where the scrim thins to
     .84, and against the brightest cloud the old value measured 4.41:1 —
     just under AA. Only ever used on dark grounds, so lighter is safer
     everywhere it appears. */
  --azure-lift: #5C9BF0;
  --azure-deep: #14539F;
  --coral:      #FF6B4A;
  --coral-lift: #FF8B70;
  --coral-deep: #C43F22;

  /* text */
  --on-ink:      #EEF3F9;
  --on-ink-dim:  #93A4B8;
  --on-paper:    #0F1722;
  --on-paper-dim:#5A6B7A;

  /* type */
  /* Instrument Serif ships ONE weight (400). Asking it for 600 or 700
     makes the browser fake a bold by smearing the strokes, which ruins a
     high-contrast serif — so --display is always used at 400, and
     anything needing weight to hold its own uses --text instead. */
  --display: "Instrument Serif", Georgia, "Times New Roman", serif;
  /* Archivo, not Inter: Inter is the default everyone reaches for, and a body
     face should be chosen rather than inherited. Archivo runs slightly wider
     with a larger x-height, so tracking is looser here than Inter wanted. */
  --text:    "Archivo", system-ui, "Segoe UI", sans-serif;
  --mono:    "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

  --s--1: clamp(0.78rem, 0.76rem + 0.10vw, 0.84rem);
  --s-0:  clamp(1rem, 0.96rem + 0.20vw, 1.125rem);
  --s-1:  clamp(1.15rem, 1.08rem + 0.35vw, 1.35rem);
  --s-2:  clamp(1.45rem, 1.28rem + 0.85vw, 2rem);
  --s-3:  clamp(1.8rem, 1.45rem + 1.75vw, 2.9rem);
  --s-4:  clamp(2.35rem, 1.65rem + 3.5vw, 4.6rem);

  /* space */
  --gut:  clamp(1.25rem, 4vw, 2.5rem);
  --band: clamp(4.5rem, 9vw, 8rem);
  --wide: 1240px;

  /* header height — the mobile drawer and the sticky plan table both
     offset themselves by this, so it must not be hard-coded twice */
  --bar: 110px;

  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  background: var(--paper);
  color: var(--on-paper);
  font-family: var(--text);
  font-size: var(--s-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* `overflow-x: hidden` silently computes overflow-y to `auto`, which makes
     body a scroll container and stops every position:sticky on the page from
     binding to the viewport. `clip` guards against sideways scroll without
     creating a scrollport. */
  overflow-x: hidden;
  overflow-x: clip;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
/* 400 is not a style choice — it is the only weight the face has. The
   looser tracking and taller line are because a serif needs both: the
   grotesque this replaced could take -.022em and 1.04 without closing up. */
h1, h2, h3 { font-family: var(--display); font-weight: 400; line-height: 1.08; letter-spacing: -0.015em; }
strong { font-weight: 600; color: inherit; }

:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 3px;
  border-radius: 3px;
}
.band--dark :focus-visible,
.hero :focus-visible,
.masthead :focus-visible,
.foot :focus-visible { outline-color: var(--coral-lift); }

.skip {
  position: absolute;
  left: 1rem;
  top: -4rem;
  z-index: 100;
  padding: .7rem 1.1rem;
  background: var(--coral);
  color: var(--ink);
  font-weight: 600;
  border-radius: 5px;
  transition: top .18s var(--ease);
}
.skip:focus { top: 1rem; }

.shell {
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding-inline: var(--gut);
}

.eyebrow {
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--azure-deep);
  margin-bottom: 1.1rem;
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 50px;
  padding: .8rem 1.6rem;
  border-radius: 6px;
  font-weight: 600;
  font-size: var(--s-0);
  text-decoration: none;
  letter-spacing: -.005em;
  transition: transform .18s var(--ease), background-color .18s var(--ease), border-color .18s var(--ease);
}
/* White on coral is only 2.8:1; graphite on coral is 5.9:1, and the brighter
   fill suits the palette better than darkening the button would. */
.btn--coral { background: var(--coral); color: var(--ink); }
.btn--coral:hover { background: var(--coral-lift); transform: translateY(-2px); }
.btn--ghost { border: 1px solid var(--rule-light); color: var(--on-paper); }
.btn--ghost:hover { border-color: var(--azure); color: var(--azure-deep); transform: translateY(-2px); }

/* on the dark bookends the ghost button flips */
.band--dark .btn--ghost,
.hero .btn--ghost { border-color: var(--rule); color: var(--on-ink); }
.band--dark .btn--ghost:hover,
.hero .btn--ghost:hover { border-color: var(--azure-lift); color: var(--on-ink); }

/* =========================================================
   masthead
   ========================================================= */
/* The hero is pulled up behind this bar, so at the top of the page there is
   nothing to paint — the logo and links sit straight on the hero and the seam
   disappears. `.is-stuck` is added by script once the hero has scrolled past,
   because from there the white page would show through and swallow the white
   logo.

   `.is-away` slides it out of the way entirely: past the hero the bar hides
   while the visitor reads downward and returns the moment they scroll up.
   visibility is what keeps the hidden links out of the tab order — a bar that
   is merely translated off-screen can still be focused. */
.masthead {
  position: sticky;
  top: 0;
  z-index: 60;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color .3s var(--ease), border-color .3s var(--ease),
              backdrop-filter .3s var(--ease), transform .35s var(--ease),
              visibility 0s;
}
.masthead.is-away {
  transform: translateY(-100%);
  visibility: hidden;
  transition: background-color .3s var(--ease), border-color .3s var(--ease),
              backdrop-filter .3s var(--ease), transform .35s var(--ease),
              visibility 0s linear .35s;
}
.masthead.is-stuck {
  background: color-mix(in srgb, var(--ink) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom-color: var(--rule);
}

.masthead__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
  min-height: var(--bar);
}
.masthead__inner .mark { grid-column: 2; justify-self: center; }
.masthead__inner .burger { grid-column: 3; justify-self: end; }

/* links left of the logo */
.masthead__links {
  grid-column: 1;
  justify-self: start;
  display: flex;
  align-items: center;
  gap: clamp(.9rem, 2vw, 1.9rem);
}
.masthead__links a {
  position: relative;
  /* a label must never break mid-phrase into two rows inside the bar */
  white-space: nowrap;
  font-size: .95rem;
  text-decoration: none;
  color: var(--on-ink-dim);
  padding-block: .4rem;
  transition: color .18s var(--ease);
}
/* hairline that grows from the left — the drawing language, not a generic underline */
.masthead__links a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 1px;
  width: 100%;
  background: var(--azure-lift);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .26s var(--ease);
}
.masthead__links a:hover { color: var(--on-ink); }
.masthead__links a:hover::after { transform: scaleX(1); }

/* the one action, given real presence */
.masthead__cta {
  grid-column: 3;
  justify-self: end;
  min-height: 46px;
  padding: .62rem 1.35rem;
  font-size: .95rem;
  border-radius: 8px;
  white-space: nowrap;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .22) inset,
              0 10px 24px -12px rgba(255, 107, 74, .85);
}
.masthead__cta:hover {
  box-shadow: 0 1px 0 rgba(255, 255, 255, .28) inset,
              0 14px 30px -12px rgba(255, 107, 74, .95);
}

/* The logo file is solid black on transparency, so `invert(1)` turns it pure
   white wherever it sits on a dark ground. One file serves both. */
.mark {
  display: inline-flex;
  align-items: center;
  padding-block: .5rem;
  text-decoration: none;
}
.mark__logo {
  display: block;
  width: auto;
  /* The ellipse lockup is 2.13:1, so height drives width: 68px tall is 145px
     wide. Source art is 1497px across, so there is ample resolution for this. */
  height: calc(var(--bar) - 42px);
  filter: invert(1);
  transition: opacity .18s var(--ease);
}
.mark:hover .mark__logo { opacity: .8; }

/* Drawer only. Desktop uses .masthead__links + .masthead__cta instead, so
   this stays out of the layout until the mobile breakpoint switches it on. */
.nav { display: none; align-items: center; gap: clamp(1rem, 2.2vw, 2rem); }
.nav a {
  font-size: .95rem;
  text-decoration: none;
  color: var(--on-ink-dim);
  transition: color .16s var(--ease);
}
.nav a:hover { color: var(--on-ink); }
.nav__cta {
  padding: .55rem 1.05rem;
  border: 1px solid var(--rule);
  border-radius: 5px;
  color: var(--on-ink) !important;
}
.nav__cta:hover { border-color: var(--azure); }

.burger { display: none; width: 44px; height: 44px; position: relative; }
.burger__bar {
  position: absolute;
  left: 11px;
  width: 22px;
  height: 1.5px;
  background: var(--on-ink);
  transition: transform .22s var(--ease), opacity .22s var(--ease);
}
.burger__bar:nth-child(1) { top: 19px; }
.burger__bar:nth-child(2) { top: 25px; }
.burger[aria-expanded="true"] .burger__bar:nth-child(1) { transform: translateY(3px) rotate(45deg); }
.burger[aria-expanded="true"] .burger__bar:nth-child(2) { transform: translateY(-3px) rotate(-45deg); }

/* ---- floating menu button ----
   Phones only, and only while the header has slid away. Script decides when
   it is on, because it also has to stand down over the footer — that already
   carries the full navigation and its own back-to-top, and two round buttons
   in the same corner would collide. */
.floatnav {
  display: none;
  position: fixed;
  right: var(--gut);
  bottom: calc(var(--gut) + env(safe-area-inset-bottom, 0px));
  z-index: 70;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 92%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid color-mix(in srgb, var(--on-ink) 18%, transparent);
  box-shadow: 0 12px 28px -10px rgba(15, 23, 34, .55);
  animation: floatIn .25s var(--ease) backwards;
}
.floatnav.is-on { display: block; }
.floatnav__bar {
  position: absolute;
  left: 15px;
  width: 22px;
  height: 1.5px;
  background: var(--on-ink);
}
.floatnav__bar:nth-child(1) { top: 23px; }
.floatnav__bar:nth-child(2) { top: 29px; }

@keyframes floatIn { from { opacity: 0; transform: scale(.8); } }

/* it exists to replace a hidden bar, so it has no business on a screen wide
   enough to still show the links */
@media (min-width: 1001px) { .floatnav { display: none !important; } }

@keyframes drawerRow {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: none; }
}

/* =========================================================
   hero
   ========================================================= */
.hero {
  color: var(--on-ink);
  position: relative;
  /* pulled up so the gradient and cloud field run behind the header, then
     padded back out so no content hides underneath it */
  margin-top: calc(-1 * var(--bar));
  padding-block: calc(var(--bar) + clamp(2rem, 4vw, 3.6rem)) clamp(4rem, 8vw, 7rem);
  overflow: hidden;
}
/* Hero layers, bottom to top:
     0  ::before   base gradient (also the fallback if WebGL never starts)
     0  canvas     the cloud field
     1  ::after    scrim that guarantees text contrast
     2  __grid     the headline, buttons and drawing
   The scrim is what lets the shader run bright without touching legibility. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(88% 68% at 76% 24%, rgba(29, 111, 224, .17), transparent 62%),
    radial-gradient(70% 60% at 92% 78%, rgba(255, 107, 74, .10), transparent 66%),
    linear-gradient(168deg, var(--deep) 0%, var(--ink) 56%);
  pointer-events: none;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* A pool of ink sitting under the copy column, plus a gentle wash. Shaped
     to the text rather than a straight left-to-right fade, so the drawing
     side stays bright while the headline keeps its contrast. */
  background:
    radial-gradient(62% 92% at 20% 48%,
      var(--ink) 0%,
      rgba(15, 23, 34, .94) 44%,
      rgba(15, 23, 34, .58) 68%,
      transparent 100%),
    linear-gradient(101deg,
      rgba(15, 23, 34, .88) 0%,
      rgba(15, 23, 34, .40) 40%,
      transparent 66%);
}
.hero__grid { z-index: 2; }


/* WebGL cloud field. Hidden until the script confirms it can actually run,
   so a phone or a failed compile falls back to the gradient above. */
.hero__shader {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  opacity: .95;
  pointer-events: none;
  /* The scrim above handles text contrast, so this only has to soften the
     outer edges rather than hide half the canvas. */
  mask-image: radial-gradient(145% 115% at 70% 30%, #000 0%, #000 42%, transparent 92%);
  -webkit-mask-image: radial-gradient(145% 115% at 70% 30%, #000 0%, #000 42%, transparent 92%);
}
.hero__shader.is-live { display: block; }

/* The hero stacks on small screens: the drawing sits on top, the copy below,
   so the scrim turns vertical and the clouds concentrate at the top. */
@media (max-width: 900px) {
  .hero::after {
    background: linear-gradient(178deg,
      transparent 0%,
      rgba(15, 23, 34, .22) 20%,
      rgba(15, 23, 34, .78) 36%,
      rgba(15, 23, 34, .96) 46%,
      var(--ink) 54%);
  }
  .hero__shader {
    opacity: .9;
    mask-image: radial-gradient(135% 62% at 56% 20%, #000 0%, #000 34%, transparent 88%);
    -webkit-mask-image: radial-gradient(135% 62% at 56% 20%, #000 0%, #000 34%, transparent 88%);
  }
}
.hero__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 5vw, 4.5rem);
  align-items: center;
}

.hero__h {
  font-size: var(--s-4);
  letter-spacing: -.022em;
  margin-bottom: 1.4rem;
}
.hero__h-em { color: var(--azure-lift); }

.hero__sub {
  font-size: var(--s-1);
  color: var(--on-ink-dim);
  max-width: 34ch;
  margin-bottom: 2.2rem;
}

.hero__actions { display: flex; flex-wrap: wrap; gap: .8rem; margin-bottom: 3rem; }

.hero__facts {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.4rem, 3.5vw, 3rem);
  padding-top: 1.6rem;
  border-top: 1px solid var(--rule);
}
.hero__fact dt {
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--on-ink-dim);
  margin-bottom: .3rem;
}
.hero__fact dd { font-weight: 600; font-size: .98rem; }

/* ---- the drawing ---- */
.hero__figure { position: relative; }
.draft { width: 100%; height: auto; }

.draft .ink { stroke: var(--azure); stroke-width: 1; opacity: .55; }
.draft__frame { stroke: var(--azure); stroke-width: 1.4; opacity: .8; fill: color-mix(in srgb, var(--deep) 40%, transparent); }
.draft__frame-line { stroke: var(--azure); stroke-width: 1; opacity: .45; }
.draft__dot { fill: var(--azure); opacity: .5; }
.draft__solid { fill: var(--azure); opacity: .85; }
.draft__hair-fill { fill: var(--on-ink); opacity: .22; }
.draft__hair { stroke: var(--on-ink); stroke-width: 1.5; opacity: .22; stroke-linecap: round; }
.draft__panel { stroke: var(--azure); stroke-width: 1; opacity: .38; fill: none; }
.draft__cta { fill: var(--coral); }
.draft__tick { fill: var(--coral); }
.draft__label {
  font-family: var(--mono);
  font-size: 11px;
  fill: var(--on-ink-dim);
  letter-spacing: .04em;
}
.draft__label--coral { fill: var(--coral-lift); }

/* draw-on sequence */
.draft.is-live .draft__frame,
.draft.is-live .draft__panel,
.draft.is-live .draft__frame-line,
.draft.is-live .ink,
.draft.is-live .draft__hair {
  stroke-dasharray: var(--len, 1400);
  stroke-dashoffset: var(--len, 1400);
  animation: scribe 1.25s var(--ease) forwards;
}
.draft.is-live .draft__solid,
.draft.is-live .draft__hair-fill,
.draft.is-live .draft__cta,
.draft.is-live .draft__dot,
.draft.is-live .draft__tick,
.draft.is-live .draft__label {
  opacity: 0;
  animation: settle .5s var(--ease) forwards;
}
.draft.is-live .draft__frame        { animation-delay: .05s; }
.draft.is-live .draft__frame-line   { animation-delay: .35s; }
.draft.is-live .draft__dot          { animation-delay: .5s; }
.draft.is-live .draft__solid        { animation-delay: .6s; }
.draft.is-live .draft__hair-fill    { animation-delay: .7s; }
.draft.is-live .draft__hair         { animation-delay: .6s; }
.draft.is-live .draft__panel        { animation-delay: .55s; }
.draft.is-live .draft__cta          { animation-delay: .85s; }
.draft.is-live .draft__dim .ink     { animation-delay: 1s; }
.draft.is-live .draft__note .ink    { animation-delay: 1.15s; }
.draft.is-live .draft__tick         { animation-delay: 1.3s; }
.draft.is-live .draft__label        { animation-delay: 1.4s; }

@keyframes scribe { to { stroke-dashoffset: 0; } }
@keyframes settle { from { opacity: 0; } to { opacity: var(--to, 1); } }
@keyframes breathe { 0% { transform: translate(-50%, -50%) scale(1); opacity: .55; } 100% { transform: translate(-50%, -50%) scale(1.12); opacity: 1; } }
@keyframes heartbeat { 0%, 100% { transform: scale(1); } 20%, 40% { transform: scale(1.25); } 30% { transform: scale(1.05); } }

.draft.is-live .draft__hair-fill { --to: .22; }
.draft.is-live .draft__hair      { --to: .22; }
.draft.is-live .draft__solid     { --to: .85; }
.draft.is-live .draft__dot       { --to: .5; }

/* =========================================================
   bands
   ========================================================= */
/* Light is the default. Only --dark opts out, and it re-tints the few
   children whose colours would otherwise be unreadable on it. */
.band { padding-block: var(--band); background: var(--paper); }
.band--surface { background: var(--surface); }
.band--dark {
  background: var(--ink);
  color: var(--on-ink);
  border-top: 1px solid var(--rule);
}
.band--dark .eyebrow,
.hero .eyebrow { color: var(--azure-lift); }

/* ---------- ambient wash ----------
   A soft azure bleed from one top corner and a coral one from the opposite
   bottom corner, so the flat grounds gain depth without any pattern.

   The hero and the footer are deliberately NOT included: both already carry
   their own gradient fields, and a third would fight them.

   Direction alternates band to band so scrolling does not feel like the same
   mark stamped repeatedly. Everything is driven by the four variables below
   rather than duplicated gradients, so there is one definition to tune. */
.band {
  position: relative;
  --wash-azure: 12%;
  --wash-coral: 9%;
  --wash-x1: 12%;   /* azure, top    */
  --wash-x2: 92%;   /* coral, bottom */
}
.band:nth-of-type(even) { --wash-x1: 88%; --wash-x2: 8%; }
/* ink swallows a wash this light, so the dark band gets roughly double */
.band--dark { --wash-azure: 26%; --wash-coral: 16%; }

.band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(58% 62% at var(--wash-x1) 0%,
      color-mix(in srgb, var(--azure) var(--wash-azure), transparent), transparent 70%),
    radial-gradient(48% 55% at var(--wash-x2) 100%,
      color-mix(in srgb, var(--coral) var(--wash-coral), transparent), transparent 72%);
}
/* lift the content clear of the wash */
.band > * { position: relative; z-index: 1; }

.lede { max-width: 62ch; margin-bottom: clamp(2.8rem, 6vw, 4.5rem); }
.lede__h { font-size: var(--s-3); margin-bottom: 1.2rem; }
.lede__p { font-size: var(--s-1); color: var(--on-paper-dim); }
.band--dark .lede__p { color: var(--on-ink-dim); }

/* =========================================================
   gradient cards
   A tinted tile with a badge, a heading and an optional arrow link.
   The corner motif is drawn with a repeating radial gradient rather than
   an image, so the whole component costs nothing to download.
   ========================================================= */
.gcards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr));
  gap: clamp(1rem, 2vw, 1.4rem);
}
.gcards--three { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.gcards--flow { list-style: none; padding: 0; }

/* The five process steps land as 3 + 2 rather than 4 + 1. */
@media (min-width: 1000px) {
  .gcards--flow { grid-template-columns: repeat(3, 1fr); }
}

.gcard {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: clamp(1.5rem, 3vw, 2.1rem);
  border: 1px solid var(--rule-light);
  border-radius: 16px;
  background: var(--paper);
  transition: transform .3s var(--ease), border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.gcard:hover {
  transform: translateY(-4px);
  box-shadow: 0 18px 38px -22px rgba(15, 23, 34, .30);
}

/* corner motif — concentric hairlines, like a compass target */
.gcard::after {
  content: "";
  position: absolute;
  right: -16%;
  bottom: -26%;
  width: 58%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: repeating-radial-gradient(circle at center, currentColor 0 1px, transparent 1px 19px);
  opacity: .13;
  pointer-events: none;
  transition: transform .5s var(--ease), opacity .5s var(--ease);
}
.gcard:hover::after { transform: scale(1.12) rotate(7deg); opacity: .2; }

/* Each variant is a white card washed with its accent from the top-left.
   `color` sets the accent for the corner motif; the text colours are set
   explicitly below so nothing inherits a hue that fails on white. */
.gcard--azure {
  color: var(--azure);
  background-image: linear-gradient(152deg, rgba(29, 111, 224, .14), rgba(29, 111, 224, .03) 44%, var(--paper) 76%);
}
.gcard--coral {
  color: var(--coral);
  background-image: linear-gradient(152deg, rgba(255, 107, 74, .15), rgba(255, 107, 74, .03) 44%, var(--paper) 76%);
}
.gcard--slate {
  color: var(--on-paper-dim);
  background-image: linear-gradient(152deg, rgba(90, 107, 122, .14), rgba(90, 107, 122, .02) 44%, var(--paper) 76%);
}
.gcard--pine {
  color: var(--deep);
  background-image: linear-gradient(152deg, rgba(27, 42, 63, .15), rgba(27, 42, 63, .03) 46%, var(--paper) 78%);
}
.gcard--azure:hover { border-color: color-mix(in srgb, var(--azure) 55%, var(--rule-light)); }
.gcard--coral:hover { border-color: color-mix(in srgb, var(--coral) 60%, var(--rule-light)); }
.gcard--slate:hover { border-color: color-mix(in srgb, var(--on-paper-dim) 55%, var(--rule-light)); }
.gcard--pine:hover  { border-color: color-mix(in srgb, var(--deep) 45%, var(--rule-light)); }

/* the plainest variant — used where nine cards would be noisy in colour */
.gcard--paper {
  color: var(--azure-deep);
  background-image: linear-gradient(152deg, rgba(29, 111, 224, .09), rgba(29, 111, 224, .015) 42%, var(--paper) 74%);
}
.gcard--paper:hover { border-color: color-mix(in srgb, var(--azure) 45%, var(--rule-light)); }
.gcard--paper::after { opacity: .12; }
.gcard--paper:hover::after { opacity: .18; }

/* =========================================================
   trade reel — the expanding accordion in "Who we build for"
   Six panels share one row. The open one takes 6 parts of the space,
   the rest take 1 each, so opening one squeezes its neighbours.
   ========================================================= */
.reel {
  display: flex;
  gap: clamp(.35rem, .8vw, .7rem);
  height: 440px;
}
.reel__panel {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  padding: 0;
  border: 1px solid var(--rule-light);
  border-radius: 14px;
  background: var(--surface-2);
  text-align: left;
  cursor: pointer;
  /* flex-grow carries the resize; filter dims the closed panels */
  transition: flex-grow .7s cubic-bezier(.25, 1, .5, 1),
              filter .5s var(--ease),
              border-color .5s var(--ease);
  filter: brightness(.62) saturate(.85);
}
.reel__panel[aria-expanded="true"] {
  flex-grow: 6;
  filter: none;
  cursor: default;
}
/* only real pointers get hover; on touch the first tap would otherwise
   fire hover and expand a panel the user was trying to scroll past */
@media (hover: hover) and (pointer: fine) {
  .reel__panel:not([aria-expanded="true"]):hover { filter: brightness(.82) saturate(.95); }
}
.reel__panel[aria-expanded="true"] { border-color: var(--rule-light); }
.reel__panel--azure[aria-expanded="true"] { border-color: color-mix(in srgb, var(--azure) 55%, var(--rule-light)); }
.reel__panel--coral[aria-expanded="true"] { border-color: color-mix(in srgb, var(--coral) 60%, var(--rule-light)); }
.reel__panel--slate[aria-expanded="true"] { border-color: color-mix(in srgb, var(--on-paper-dim) 55%, var(--rule-light)); }
.reel__panel--pine[aria-expanded="true"]  { border-color: color-mix(in srgb, var(--deep) 45%, var(--rule-light)); }

.reel__media { position: absolute; inset: 0; }
.reel__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.12);
  transition: transform 1s var(--ease);
}
.reel__panel[aria-expanded="true"] .reel__media img { transform: scale(1); }

/* scrim only under the open panel, so closed strips stay clean */
.reel__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(15,23,34,.92) 0%, rgba(15,23,34,.55) 42%, rgba(15,23,34,.08) 100%);
  opacity: 0;
  transition: opacity .5s var(--ease);
}
.reel__panel[aria-expanded="true"] .reel__media::after { opacity: 1; }

/* closed: the trade name runs vertically up the strip */
.reel__spine {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 1px 6px rgba(15,23,34,.7);
  white-space: nowrap;
  opacity: 1;
  transition: opacity .35s var(--ease);
  transition-delay: .35s;
}
.reel__panel[aria-expanded="true"] .reel__spine {
  opacity: 0;
  transition-delay: 0s;
  pointer-events: none;
}

/* open: the content slides up from below */
.reel__body {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .7rem;
  padding: clamp(1rem, 2vw, 1.9rem);
  opacity: 0;
  transform: translateY(2.2rem);
  transition: opacity .45s var(--ease), transform .45s var(--ease);
  pointer-events: none;
}
.reel__panel[aria-expanded="true"] .reel__body {
  opacity: 1;
  transform: none;
  transition-delay: .22s;
}
.reel__badge {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .28rem .7rem .28rem .55rem;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,.28);
  background: rgba(255,255,255,.12);
  backdrop-filter: blur(6px);
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #fff;
}
/* sits over a photograph, so it needs weight the display face does not
   have — a 400 serif loses its edges against a busy image */
.reel__h {
  font-family: var(--text);
  font-weight: 700;
  font-size: clamp(1.15rem, 1.7vw, 1.8rem);
  line-height: 1.15;
  letter-spacing: -.018em;
  color: #fff;
  text-wrap: balance;
}
.reel__p {
  font-size: clamp(.82rem, .95vw, .97rem);
  line-height: 1.5;
  color: rgba(255,255,255,.86);
  max-width: 42ch;
}

/* Phones: same mechanism, just tighter. 6:1 gives a ~172px open panel and
   ~29px strips at 375px — enough for the vertical label to stay readable. */
@media (max-width: 720px) {
  .reel { gap: .3rem; height: 440px; }
  .reel__panel { border-radius: 11px; }
  .reel__spine { font-size: .68rem; letter-spacing: .1em; }
  .reel__body { gap: .55rem; padding: .8rem .7rem 1rem; }
  .reel__badge { font-size: .6rem; padding: .2rem .45rem .2rem .4rem; gap: .35rem; }
  .reel__h { font-size: 1.02rem; }
  .reel__p { font-size: .78rem; line-height: 1.42; }
}

/* badge */
.gcard__badge {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  width: fit-content;
  margin-bottom: 1.3rem;
  padding: .3rem .7rem .3rem .55rem;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--rule-light);
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--on-paper);
}
.gcard__dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.gcard__dot--azure { background: var(--azure); }
.gcard__dot--coral { background: var(--coral); }
.gcard__dot--slate { background: var(--on-paper-dim); }
.gcard__dot--pine  { background: var(--deep); }

/* tick, for the "in every build" cards */
.gcard__tick {
  position: relative;
  z-index: 1;
  width: 13px;
  height: 7px;
  margin-bottom: 1.1rem;
  border-left: 2px solid var(--coral-deep);
  border-bottom: 2px solid var(--coral-deep);
  transform: rotate(-45deg);
}

/* Card headings run at 1.35rem, which is below the size a 400-weight
   display serif can carry — it goes thin and loses its authority. The
   text face at 600 holds the hierarchy properly at this size. */
.gcard__h {
  position: relative;
  z-index: 1;
  font-family: var(--text);
  font-weight: 600;
  font-size: var(--s-2);
  line-height: 1.25;
  letter-spacing: -.018em;
  margin-bottom: .7rem;
}
.gcard__h--sm { font-size: var(--s-1); letter-spacing: -.012em; }
/* set explicitly: inheriting the card's accent would put coral on white,
   which is only 2.8:1 */
.gcard__h { color: var(--on-paper); }
.gcard__p {
  position: relative;
  z-index: 1;
  color: var(--on-paper-dim);
  font-size: .97rem;
  max-width: 34ch;
}

/* arrow link */
.gcard__go {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  align-self: flex-start;
  margin-top: 1.2rem;
  padding: .55rem 0;
  min-height: 44px;          /* tap-target floor */
  font-weight: 600;
  font-size: .93rem;
  text-decoration: none;
  color: var(--on-paper);
  transition: color .2s var(--ease);
}
.gcard__go:hover { color: var(--azure-deep); }
.gcard__arrow {
  position: relative;
  width: 15px;
  height: 9px;
  transition: transform .25s var(--ease);
}
.gcard__arrow::before {
  content: "";
  position: absolute;
  left: 0;
  top: 4px;
  width: 15px;
  height: 1.6px;
  background: currentColor;
}
.gcard__arrow::after {
  content: "";
  position: absolute;
  right: 0;
  top: 1.5px;
  width: 6px;
  height: 6px;
  border-top: 1.6px solid currentColor;
  border-right: 1.6px solid currentColor;
  transform: rotate(45deg);
}
.gcard__go:hover .gcard__arrow { transform: translateX(4px); }

/* the stat cards reuse the gradient card shell */
.gcard .stat__fig { margin-top: auto; }

/* =========================================================
   steps
   ========================================================= */
/* =========================================================
   plans — the two ways to work
   Two cards rather than a comparison table. Every line is a tick because
   both plans include everything; what differs is who handles it, so a
   cross would wrongly imply something is missing.
   ========================================================= */
.plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr));
  gap: clamp(1.1rem, 2.4vw, 1.8rem);
  align-items: start;
}

.plan {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(1.6rem, 3vw, 2.4rem);
  border: 1px solid var(--rule-light);
  border-radius: 18px;
  background-color: var(--paper);
  background-image:
    linear-gradient(158deg, rgba(29, 111, 224, .07), rgba(29, 111, 224, .01) 38%, var(--paper) 72%);
  box-shadow: 0 1px 2px rgba(15, 23, 34, .04);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease), border-color .35s var(--ease);
}
.plan:hover {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--azure) 45%, var(--rule-light));
  box-shadow: 0 22px 44px -26px rgba(15, 23, 34, .38);
}

/* the recommended one: coral ring, warmer wash, sitting slightly proud */
.plan--pick {
  border-color: var(--coral);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--coral) 16%, transparent),
              0 20px 42px -26px rgba(196, 63, 34, .5);
  background-image:
    linear-gradient(158deg, rgba(255, 107, 74, .10), rgba(255, 107, 74, .02) 40%, var(--paper) 74%);
}
.plan--pick:hover {
  border-color: var(--coral);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--coral) 22%, transparent),
              0 26px 50px -26px rgba(196, 63, 34, .6);
}
@media (min-width: 800px) {
  .plan--pick { transform: translateY(-10px); }
  .plan--pick:hover { transform: translateY(-15px); }
}
/* Stacked, the badge hangs into the gap above and would sit ~4px off the
   card before it. Extra room so a longer label cannot collide. */
@media (max-width: 799px) {
  .plan--pick { margin-top: .9rem; }
}

.plan__flag {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: .3rem .85rem;
  border-radius: 999px;
  background: var(--coral);
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: 0 6px 16px -8px rgba(196, 63, 34, .9);
}

.plan__icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-bottom: 1.1rem;
  border-radius: 13px;
  border: 1px solid var(--rule-light);
  background: var(--paper);
  color: var(--azure);
}
.plan--pick .plan__icon { color: var(--coral-deep); border-color: color-mix(in srgb, var(--coral) 30%, var(--rule-light)); }
.plan__icon svg { width: 26px; height: 26px; }

.plan__name { font-size: var(--s-2); letter-spacing: -.018em; margin-bottom: .35rem; }
.plan__note { color: var(--on-paper-dim); font-size: .97rem; }

.plan__cta {
  width: 100%;
  margin: 1.5rem 0 1.6rem;
  border-radius: 9px;
}

.plan__list {
  list-style: none;
  padding: 1.5rem 0 0;
  margin: 0;
  border-top: 1px solid var(--rule-light);
  display: grid;
  gap: 1.05rem;
}
.plan__item {
  position: relative;
  padding-left: 1.85rem;
}
/* the tick, drawn rather than an icon font */
.plan__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: .5em;
  width: 11px;
  height: 6px;
  border-left: 2px solid var(--azure);
  border-bottom: 2px solid var(--azure);
  transform: rotate(-45deg);
}
.plan--pick .plan__item::before { border-color: var(--coral-deep); }

.plan__k {
  display: block;
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--on-paper-dim);
  margin-bottom: .18rem;
}
.plan__v { display: block; font-size: .95rem; line-height: 1.5; }

/* ---- what moves the price ----
   A note, not a card. The hairline above and the open layout are what keep it
   from reading as a third plan sitting beside the other two. */
.scope {
  margin-top: clamp(2.2rem, 5vw, 3.2rem);
  padding-top: clamp(1.6rem, 4vw, 2.2rem);
  border-top: 1px solid var(--rule-light);
}
.scope__h {
  font-size: var(--s-2);
  max-width: 36ch;
  margin-bottom: clamp(1.3rem, 3vw, 1.9rem);
}
.scope__pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: clamp(1.3rem, 3vw, 2.6rem);
}
/* the text face, not the mono: the eyebrow above is already mono, and two
   uppercase mono labels stacked would compete */
.scope__k {
  font-family: var(--text);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: -.012em;
  color: var(--on-paper);
  margin-bottom: .45rem;
}
.scope__p {
  color: var(--on-paper-dim);
  font-size: .97rem;
  line-height: 1.6;
  max-width: 48ch;
}

.plans__foot {
  margin-top: clamp(1.8rem, 3.5vw, 2.6rem);
  max-width: 62ch;
  color: var(--on-paper-dim);
  font-size: .97rem;
}

@media (max-width: 560px) {
  .plan { padding: 1.4rem 1.2rem; border-radius: 15px; }
  .plan__list { gap: .9rem; }
  .plan__v { font-size: .89rem; }
}

/* =========================================================
   contact
   ========================================================= */
.contact {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
}
.contact__h { font-size: var(--s-3); margin-bottom: 1.1rem; }
.contact__p { color: var(--on-ink-dim); font-size: var(--s-1); max-width: 42ch; }

.contact__lines { display: grid; gap: 1rem; }
.line {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: .4rem 1rem;
  padding: clamp(1.3rem, 3vw, 1.8rem);
  border: 1px solid var(--rule);
  border-radius: 10px;
  text-decoration: none;
  transition: border-color .2s var(--ease), background-color .2s var(--ease), transform .2s var(--ease);
}
.line:hover { border-color: var(--coral); background: var(--ink); transform: translateY(-2px); }
.line__tag {
  grid-column: 1 / -1;
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--azure-lift);
}
/* a phone number and an email address are data to be read accurately,
   not display type — the text face is the safer read at this size */
.line__val {
  font-family: var(--text);
  font-weight: 600;
  font-size: clamp(1.15rem, 3.4vw, 1.6rem);
  letter-spacing: -.015em;
  word-break: break-word;
}
.line__go { font-family: var(--mono); font-size: var(--s--1); color: var(--coral); white-space: nowrap; }

/* =========================================================
   footer — curtain reveal
   #main is given z-index so its opaque background covers the footer,
   which is fixed and rendering full-screen underneath the whole time.
   .foot-curtain is 100vh of ordinary flow at the end of the document —
   the scroll room #main needs to clear the viewport. There is nothing
   after it, so once #main's own bottom edge passes, the fixed footer is
   left showing with nothing left over it: the "reveal".
   ========================================================= */
/* the background is load-bearing, not decoration: it is what hides the
   footer. Every band paints its own ground today, so this changes nothing
   visually — it is here so a future transparent section cannot let the
   footer show through mid-page. */
#main { position: relative; z-index: 1; background: var(--paper); }

/* Default: an ordinary footer in normal flow. This is what a short screen
   gets, and what everyone gets with no JavaScript — nothing is ever
   unreachable. The pinned curtain below is the enhancement. */
.foot-curtain { position: relative; }
.cinefoot {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--ink);
  color: var(--on-ink);
  border-top: 1px solid var(--rule);
  padding-top: clamp(2.5rem, 6vw, 4rem);
}

/* Pinned: script has measured that the footer fits one screen, so #main can
   travel up off it to reveal it. Only then is it safe to fix the height. */
.foot-curtain.is-pinned { height: 100vh; height: 100svh; }
.foot-curtain.is-pinned .cinefoot {
  position: fixed;
  inset: 0;
  justify-content: space-between;
  border-top: 0;
  /* the masthead is sticky for the whole document, so it is still sitting
     over the top of the screen when the footer is revealed. Without this
     it covers the eyebrow and the heading. */
  padding-top: var(--bar);
}

.cinefoot__aurora {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 80vw;
  height: 60vh;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  filter: blur(80px);
  background: radial-gradient(circle at 50% 50%,
    color-mix(in srgb, var(--azure) 22%, transparent) 0%,
    color-mix(in srgb, var(--coral) 15%, transparent) 45%,
    transparent 72%);
  animation: breathe 8s ease-in-out infinite alternate;
  pointer-events: none;
}
.cinefoot__grid {
  position: absolute;
  inset: 0;
  background-size: 60px 60px;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--on-ink) 6%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--on-ink) 6%, transparent) 1px, transparent 1px);
  mask-image: linear-gradient(to bottom, transparent, black 30%, black 70%, transparent);
  -webkit-mask-image: linear-gradient(to bottom, transparent, black 30%, black 70%, transparent);
  pointer-events: none;
}
.cinefoot__word {
  position: absolute;
  left: 50%;
  bottom: -4vh;
  transform: translateX(-50%) translateY(calc((1 - var(--p, 1)) * 6vh)) scale(calc(0.9 + var(--p, 1) * 0.1));
  opacity: var(--p, 1);
  font-family: var(--display);
  font-weight: 400;
  font-size: 22vw;
  line-height: .75;
  letter-spacing: -.02em;
  color: transparent;
  -webkit-text-stroke: 1px color-mix(in srgb, var(--on-ink) 6%, transparent);
  background-image: linear-gradient(180deg, color-mix(in srgb, var(--on-ink) 12%, transparent) 0%, transparent 60%);
  -webkit-background-clip: text;
  background-clip: text;
  white-space: nowrap;
  pointer-events: none;
  transition: opacity .2s linear;
}

.cinefoot__main {
  position: relative;
  z-index: 1;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.6rem;
  text-align: center;
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding-inline: var(--gut);
}
/* coral, not the usual azure: the aurora behind it is azure-tinted, where
   --azure-lift drops to 3.86:1. --coral-lift on the same ground is 5.31:1,
   and coral is the site's action colour anyway. */
.cinefoot__main .eyebrow { margin-bottom: 0; color: var(--coral-lift); }
.cinefoot__h {
  font-size: var(--s-4);
  /* the tail must not go below ~60%: at 45% the bottom of the letters
     measures 3.51:1 over the aurora, at 60% it is 5.01:1 */
  background-image: linear-gradient(180deg, var(--on-ink) 0%, color-mix(in srgb, var(--on-ink) 60%, transparent) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
/* --pp (0 to 1) is a per-element, already-staggered, already-clamped
   progress value computed and set by script — see syncCurtain(). It
   falls back to fully-settled, so the section still renders complete
   and static if the script never runs. */
.cinefoot__h, .cinefoot__ctas, .cinefoot__index {
  opacity: var(--pp, 1);
  transform: translateY(calc((1 - var(--pp, 1)) * 28px));
  transition: opacity .2s linear;
}

/* ---- the reference half: everything the old footer carried ---- */
.cinefoot__index {
  position: relative;
  z-index: 1;
  flex-shrink: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.7fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding: 0 var(--gut);
}
.cinefoot__brand .mark { padding-block: 0; }
.mark__logo--foot { height: 44px; }
.cinefoot__tag {
  margin-top: .7rem;
  max-width: 30ch;
  font-size: .88rem;
  line-height: 1.5;
  color: var(--on-ink-dim);
}
.cinefoot__cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 3vw, 2rem);
}
.cinefoot__col { display: grid; gap: .45rem; align-content: start; }
.cinefoot__ch {
  font-family: var(--mono);
  font-weight: 500;
  font-size: var(--s--1);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--coral-lift);
  margin-bottom: .15rem;
}
/* min-height 24px, not decoration: these measured 23px tall, one pixel
   under the WCAG 2.2 target-size minimum. */
.cinefoot__col a {
  color: var(--on-ink-dim);
  text-decoration: none;
  font-size: .9rem;
  width: fit-content;
  min-height: 24px;
  display: flex;
  align-items: center;
  transition: color .16s var(--ease);
}
.cinefoot__col a:hover { color: var(--on-ink); }
/* the address is the one item that cannot be shortened, so let it wrap
   rather than push the column grid wider than its share */
.cinefoot__mail { word-break: break-word; }

.cinefoot__ctas {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem;
  margin-top: .4rem;
}
.cinefoot__links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .6rem;
}

.cinefoot__pill {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  padding: .9rem 1.7rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--on-ink) 14%, transparent);
  background-image: linear-gradient(145deg,
    color-mix(in srgb, var(--on-ink) 10%, transparent) 0%,
    color-mix(in srgb, var(--on-ink) 3%, transparent) 100%);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  /* full-strength, not the dim tone: these pills sit directly over the
     aurora's brightest point, where --on-ink-dim measures 3.58:1 and
     fails AA. At --on-ink the same worst case is 8.19:1. */
  color: var(--on-ink);
  font-weight: 600;
  font-size: .92rem;
  text-decoration: none;
  box-shadow:
    inset 0 1px 1px color-mix(in srgb, var(--on-ink) 16%, transparent),
    0 10px 26px -14px rgba(0, 0, 0, .7);
  transition: background-image .3s var(--ease), border-color .3s var(--ease), transform .5s var(--ease);
}
.cinefoot__pill:hover {
  background-image: linear-gradient(145deg,
    color-mix(in srgb, var(--on-ink) 18%, transparent) 0%,
    color-mix(in srgb, var(--on-ink) 7%, transparent) 100%);
  border-color: color-mix(in srgb, var(--on-ink) 30%, transparent);
}
.cinefoot__pill svg { width: 18px; height: 18px; flex-shrink: 0; }

/* white on coral fails contrast — see the .btn--coral note above */
.cinefoot__pill--primary { padding: 1rem 2rem; background: var(--coral); color: var(--ink); border-color: transparent; font-weight: 700; }
.cinefoot__pill--primary:hover { background: var(--coral-lift); color: var(--ink); }

.cinefoot__totop { padding: .9rem; border-radius: 50%; }

.cinefoot__bottom {
  position: relative;
  z-index: 1;
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  max-width: var(--wide);
  margin: clamp(1.2rem, 3vw, 2rem) auto 0;
  padding: 1.3rem var(--gut) clamp(1.4rem, 4vw, 2rem);
  border-top: 1px solid color-mix(in srgb, var(--rule) 80%, transparent);
}
.cinefoot__legal { font-family: var(--mono); font-size: var(--s--1); color: var(--on-ink-dim); }
.cinefoot__badge {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .7rem 1.3rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--on-ink) 14%, transparent);
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--on-ink-dim);
}
.cinefoot__heart { color: var(--coral); animation: heartbeat 2.2s ease-in-out infinite; }

/* =========================================================
   fanned card stack — "in every build"
   Script sets --off (signed distance from the active card) and --abs on
   each card; every position below is derived from those two numbers, so
   the geometry lives in one place. With no JS the cards fall back to a
   plain readable column, which is why the markup is a list of articles
   rather than a canvas.
   ========================================================= */
.fan { --card-w: clamp(260px, 74vw, 520px); }

.fan__stage {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  perspective: 1100px;
  min-height: calc(var(--card-w) * 0.625 + 90px);
  touch-action: pan-y;              /* let the page scroll; we only read x */
}

.fan__card {
  position: relative;
  width: var(--card-w);
  aspect-ratio: 8 / 5;
  border-radius: 16px;
  overflow: hidden;
  background: var(--ink);
  border: 1px solid var(--rule-light);
  box-shadow: 0 26px 50px -30px rgba(15, 23, 34, .55);
}

/* Once script takes over, cards stack and fan out from the centre. */
.fan.is-live .fan__stage {
  display: block;
  height: calc(var(--card-w) * 0.625 + 90px);
  /* The cards beyond the fan are only faded out, and opacity does not take an
     element out of the scrollable area — without this they push the page
     sideways. `clip` rather than `hidden` so no scroll container is created
     and the lifted card's shadow still shows above. */
  overflow-x: clip;
}
.fan.is-live .fan__card {
  position: absolute;
  left: 50%;
  bottom: 0;
  margin-left: calc(var(--card-w) / -2);
  transform-style: preserve-3d;
  z-index: calc(100 - var(--abs, 0));
  cursor: pointer;
  /* 0.34 of the card width per step: with a reach of 2 that puts the outer
     card's far edge at 614px from centre, inside the 620px half-shell. Widen
     this and the fan runs off the page. */
  transform:
    translateX(calc(var(--off, 0) * var(--card-w) * 0.34))
    translateY(calc(var(--abs, 0) * 10px + var(--lift, 0px)))
    rotate(calc(var(--off, 0) * 5deg))
    scale(var(--scale, .94));
  transition: transform .55s var(--ease), opacity .4s var(--ease), box-shadow .4s var(--ease);
}
.fan.is-live .fan__card[data-active="true"] {
  --lift: -20px;
  --scale: 1.03;
  cursor: grab;
  box-shadow: 0 40px 70px -34px rgba(15, 23, 34, .7);
}
.fan.is-live .fan__card[data-active="true"]:active { cursor: grabbing; }
/* beyond the fan's reach: still in the DOM for screen readers, out of sight
   and out of the pointer's way */
.fan.is-live .fan__card[data-far="true"] { opacity: 0; pointer-events: none; }

.fan.is-live .fan__card:focus-visible { outline: 2px solid var(--coral); outline-offset: 4px; }

/* ---- the art layer ---- */
.fan__art, .fan__art picture { position: absolute; inset: 0; display: block; }
.fan__art img { width: 100%; height: 100%; object-fit: cover; }

/* The photographs are deliberately high-key, so the scrim under the copy has
   to be heavier than it would be over dark art — white text on a bright
   image is the classic way to lose a contrast ratio. Measured against the
   brightest pixel each photograph actually contains, not against an
   assumption. */
.fan__card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    rgba(15, 23, 34, .96) 0%,
    rgba(15, 23, 34, .90) 38%,
    rgba(15, 23, 34, .46) 66%,
    rgba(15, 23, 34, .12) 88%,
    transparent 100%);
}

.fan__no {
  position: absolute;
  top: clamp(.9rem, 2.4vw, 1.4rem);
  right: clamp(.9rem, 2.4vw, 1.4rem);
  z-index: 2;
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .12em;
  color: var(--on-ink);
  opacity: .75;
}
.fan__body {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  padding: clamp(1.1rem, 3vw, 1.8rem);
}
.fan__h {
  font-family: var(--text);
  font-weight: 600;
  font-size: clamp(1.05rem, 2.6vw, 1.4rem);
  line-height: 1.25;
  letter-spacing: -.012em;
  color: #fff;
  margin-bottom: .4rem;
}
.fan__p {
  font-size: clamp(.86rem, 1.9vw, .95rem);
  line-height: 1.5;
  color: rgba(255, 255, 255, .88);
  max-width: 46ch;
}

/* ---- the bar beneath ---- */
.fan__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: .9rem 1.4rem;
  margin-top: clamp(1.6rem, 4vw, 2.4rem);
}
.fan__count {
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--on-paper-dim);
}
.fan__count span { color: var(--azure-deep); font-weight: 500; }
.fan__dots { display: flex; align-items: center; gap: 0; }
/* The dot people see is 9px, but the thing they have to hit is 24x24 —
   WCAG 2.2 Target Size (Minimum). The dots were 9px with 17px between
   centres, which fails both the size rule and its spacing exception. */
.fan__dot {
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  background: none;
  display: grid;
  place-items: center;
}
.fan__dot::before {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--on-paper-dim) 38%, transparent);
  transition: background-color .2s var(--ease), transform .2s var(--ease);
}
.fan__dot:hover::before { background: var(--on-paper-dim); }
.fan__dot[aria-selected="true"]::before { background: var(--azure-deep); transform: scale(1.35); }
.fan__hint {
  font-family: var(--mono);
  font-size: var(--s--1);
  color: var(--on-paper-dim);
  opacity: .8;
}

/* no JS: a readable column, nothing hidden */
.fan:not(.is-live) .fan__stage { display: grid; gap: 1rem; }
.fan:not(.is-live) .fan__bar { display: none; }

@media (max-width: 620px) {
  /* a tighter fan, or nine cards would spill off a phone */
  .fan.is-live .fan__card {
    transform:
      translateX(calc(var(--off, 0) * var(--card-w) * 0.30))
      translateY(calc(var(--abs, 0) * 7px + var(--lift, 0px)))
      rotate(calc(var(--off, 0) * 3.5deg))
      scale(var(--scale, .9));
  }
  .fan__hint { display: none; }
}

/* =========================================================
   scroll reveal
   ========================================================= */
.rise { opacity: 0; transform: translateY(22px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
.rise.is-in { opacity: 1; transform: none; }

/* =========================================================
   responsive
   ========================================================= */

/* Hero and contact stack at 900px — that is about their own content. */
@media (max-width: 900px) {
  .hero__grid { grid-template-columns: 1fr; }
  .hero__sub { max-width: 46ch; }
  .hero__figure { order: -1; max-width: 520px; }
  .contact { grid-template-columns: 1fr; }
}

/* The nav switches to the drawer at 1000px. The ellipse logo is 111px wide —
   far narrower than the old script lockup — so the four links, logo and button
   still fit on one line at 995px with 68px to spare. Measured, not guessed:
   re-measure if the logo or the link labels change. */
@media (max-width: 1000px) {
  .burger { display: block; }
  .masthead__links,
  .masthead__cta { display: none; }
  .nav {
    display: flex;
    position: fixed;
    inset: var(--bar) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--gut);
    background: var(--ink);
    border-bottom: 1px solid var(--rule);
    /* Clears its own height plus the header, so no edge peeks out below the
       masthead. visibility also takes the links out of the tab order. */
    transform: translateY(calc(-100% - 80px));
    visibility: hidden;
    transition: transform .3s var(--ease), visibility 0s linear .3s;
    max-height: calc(100dvh - var(--bar));
    overflow-y: auto;
  }
  .nav.is-open {
    transform: none;
    visibility: visible;
    transition: transform .3s var(--ease), visibility 0s;
  }
  /* The drawer gets the same care as the desktop bar: generous rows, a
     hairline that draws in on the active row, and the CTA as a real button
     rather than one more link in the list. */
  .nav a {
    position: relative;
    padding: 1.15rem .25rem;
    border-bottom: 1px solid var(--rule);
    font-family: var(--text);
    font-weight: 600;
    font-size: 1.18rem;
    letter-spacing: -.012em;
    color: var(--on-ink);
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  /* a small chevron on each row, drawn in CSS */
  .nav a:not(.nav__cta)::after {
    content: "";
    width: 8px;
    height: 8px;
    border-top: 1.5px solid var(--on-ink-dim);
    border-right: 1.5px solid var(--on-ink-dim);
    transform: rotate(45deg);
    transition: transform .22s var(--ease), border-color .22s var(--ease);
  }
  .nav a:active:not(.nav__cta)::after { transform: rotate(45deg) translate(2px, -2px); border-color: var(--azure-lift); }

  /* qualified with `a` so it outranks `.nav a` above, which sets space-between */
  .nav a.nav__cta {
    justify-content: center;
    margin-top: 1.4rem;
    padding: 1.05rem 1.4rem !important;
    border: 0;
    border-radius: 10px;
    background: var(--coral);
    color: var(--ink) !important;
    font-size: 1.05rem;
    box-shadow: 0 1px 0 rgba(255, 255, 255, .22) inset,
                0 14px 28px -14px rgba(255, 107, 74, .9);
  }
  .nav__cta::after { content: none; }

  /* rows fade in one after another as the drawer comes down */
  .nav.is-open a {
    animation: drawerRow .34s var(--ease) backwards;
  }
  .nav.is-open a:nth-child(1) { animation-delay: .06s; }
  .nav.is-open a:nth-child(2) { animation-delay: .11s; }
  .nav.is-open a:nth-child(3) { animation-delay: .16s; }
  .nav.is-open a:nth-child(4) { animation-delay: .21s; }
  .nav.is-open a:nth-child(5) { animation-delay: .27s; }
}

@media (max-width: 480px) {
  .hero__actions .btn { width: 100%; }
  .line { grid-template-columns: 1fr; }
  .line__go { text-align: left; }
}

/* =========================================================
   stakes — the numbers
   ========================================================= */
.band--tight { padding-block: clamp(3.5rem, 7vw, 6rem); }
.band--ruled { border-top: 1px solid var(--rule-light); }
.band--dark.band--ruled { border-top-color: var(--rule); }
.lede--wide { max-width: 68ch; }

.stat__fig {
  display: flex;
  align-items: baseline;
  font-family: var(--display);
  font-weight: 400;
  color: var(--azure);
  font-size: clamp(2.8rem, 7vw, 4.2rem);
  line-height: 1;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  margin-bottom: 1rem;
}
.stat__unit { font-size: .5em; color: var(--coral-deep); }
.stat__say {
  position: relative;
  z-index: 1;
  color: var(--on-paper);
  font-size: var(--s-0);
  max-width: 30ch;
}
.stakes__close {
  margin-top: clamp(2rem, 4vw, 3rem);
  max-width: 60ch;
  font-size: var(--s-1);
  color: var(--on-paper-dim);
}
.stakes__close strong { color: var(--on-paper); font-weight: 600; }

/* =========================================================
   stat cards on photography
   Three dark tiles inside the white section. The photographs are already
   dark (mean luminance 24–42 of 255), and a scrim on top guarantees the
   floor so white text never depends on how bright a given frame is.
   ========================================================= */
#stakes .gcard {
  border-color: var(--rule);
  background: var(--ink);
  color: var(--on-ink);
  box-shadow: 0 18px 40px -28px rgba(15, 23, 34, .55);
}
#stakes .gcard:hover { border-color: color-mix(in srgb, var(--azure) 45%, var(--rule)); }
/* the corner motif competes with the photograph */
#stakes .gcard::after { display: none; }

.stat__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  border-radius: inherit;
}
.stat__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.04);
  transition: transform 1.1s var(--ease);
}
#stakes .gcard:hover .stat__bg img { transform: scale(1.09); }
/* the contrast floor — deepest where the number and sentence sit */
.stat__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    rgba(15, 23, 34, .92) 0%,
    rgba(15, 23, 34, .82) 45%,
    rgba(15, 23, 34, .66) 100%);
}

/* lift every piece of content above the photograph */
#stakes .gcard__badge,
#stakes .stat__fig,
#stakes .stat__say { position: relative; z-index: 1; }

#stakes .gcard__badge {
  background: rgba(255, 255, 255, .12);
  border-color: rgba(255, 255, 255, .26);
  color: #fff;
  backdrop-filter: blur(6px);
}
#stakes .stat__fig { color: var(--azure-lift); }
#stakes .stat__unit { color: var(--coral-lift); }
#stakes .stat__say { color: rgba(255, 255, 255, .93); }

/* Phones: the three stat cards turn on their side — badge across the top,
   then the figure and its sentence side by side instead of stacked. Roughly
   halves each card, and the section overall drops from ~1.6 screens to under
   one. Grid-area lets the layout change without touching the markup. */
@media (max-width: 720px) {
  #stakes.band--tight { padding-block: 2.6rem; }
  #stakes .lede { margin-bottom: 1.6rem; }
  #stakes .lede__h { font-size: 1.55rem; margin-bottom: .7rem; }
  #stakes .lede__p { font-size: .95rem; }
  #stakes .eyebrow { margin-bottom: .7rem; }

  #stakes .gcards { gap: .6rem; }

  #stakes .gcard {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "badge badge"
      "fig   say";
    align-items: center;
    column-gap: 1rem;
    row-gap: .5rem;
    padding: 1rem 1.1rem;
    border-radius: 12px;
  }
  #stakes .gcard__badge { grid-area: badge; margin-bottom: 0; }
  #stakes .stat__fig {
    grid-area: fig;
    margin: 0;
    font-size: 2.4rem;
    align-self: center;
  }
  #stakes .stat__say {
    grid-area: say;
    font-size: .86rem;
    line-height: 1.45;
    max-width: none;
  }
  /* the corner motif is decorative and gets cramped at this size */
  #stakes .gcard::after { display: none; }

  #stakes .stakes__close { margin-top: 1.4rem; font-size: .95rem; }
}

/* =========================================================
   questions
   ========================================================= */
.qa { border-top: 1px solid var(--rule-light); max-width: 78ch; }
.q { border-bottom: 1px solid var(--rule-light); }
.q h3 { font: inherit; letter-spacing: normal; margin: 0; }
.q__btn {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 1.5rem;
  width: 100%;
  padding: 1.45rem 0;
  text-align: left;
}
.q__name {
  font-family: var(--text);
  font-weight: 600;
  font-size: var(--s-1);
  letter-spacing: -.012em;
  line-height: 1.35;
}
.q__btn[aria-expanded="true"] .q__name { color: var(--coral-deep); }
.q__sign { position: relative; width: 14px; height: 14px; }
.q__sign::before,
.q__sign::after {
  content: "";
  position: absolute;
  left: 0;
  top: 6px;
  width: 14px;
  height: 2px;
  background: var(--on-paper-dim);
  transition: transform .28s var(--ease), background-color .28s var(--ease);
}
.q__sign::after { transform: rotate(90deg); }
.q__btn[aria-expanded="true"] .q__sign::before,
.q__btn[aria-expanded="true"] .q__sign::after { background: var(--coral-deep); }
.q__btn[aria-expanded="true"] .q__sign::after { transform: rotate(0deg); }
.q__body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .32s var(--ease); }
.q__body > p { overflow: hidden; color: var(--on-paper-dim); max-width: 68ch; }
/* The button is wrapped in a heading, so .q__body is not its sibling —
   the open state is carried on the .q container instead. */
.q.is-open .q__body { grid-template-rows: 1fr; }
.q.is-open .q__body > p { padding-bottom: 1.6rem; }

/* =========================================================
   enquiry form
   ========================================================= */
.form {
  display: grid;
  gap: 1.1rem;
  align-content: start;
  border: 1px solid var(--rule);
  border-radius: 12px;
  padding: clamp(1.5rem, 3.5vw, 2.4rem);
  background: var(--ink);
}
.form__h { font-size: var(--s-2); letter-spacing: -.018em; }
.form__trap { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.field { display: grid; gap: .45rem; }
.field--pair { grid-template-columns: 1fr 1fr; gap: 1.1rem; }
.field--pair > div { display: grid; gap: .45rem; }
.field__label {
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--on-ink-dim);
}
.field__opt { text-transform: none; letter-spacing: .02em; opacity: .7; }
.field__input {
  width: 100%;
  min-height: 48px;
  padding: .7rem .9rem;
  font: inherit;
  font-size: 1rem;
  color: var(--on-ink);
  background: var(--ink-raise);
  border: 1px solid var(--rule);
  border-radius: 6px;
  transition: border-color .18s var(--ease), background-color .18s var(--ease);
}
.field__input--area { min-height: 118px; resize: vertical; line-height: 1.55; }
.field__input:hover { border-color: var(--on-ink-dim); }
.field__input:focus { border-color: var(--azure); background: var(--deep); }
.field__input[aria-invalid="true"] { border-color: var(--coral-lift); }
/* week-strip day picker */
.cal {
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--ink-raise);
  overflow: hidden;
}
.cal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  padding: .6rem .6rem .5rem;
  border-bottom: 1px solid var(--rule);
}
.cal__month {
  font-family: var(--mono);
  font-size: var(--s--1);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--on-ink);
  text-align: center;
}
.cal__nav {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: 7px;
  border: 1px solid transparent;
  transition: border-color .18s var(--ease), background-color .18s var(--ease);
}
.cal__nav:hover:not(:disabled) { border-color: var(--rule); background: var(--deep); }
.cal__nav:disabled { opacity: .3; cursor: not-allowed; }
.cal__chev {
  width: 8px;
  height: 8px;
  border-top: 1.6px solid var(--on-ink);
  border-right: 1.6px solid var(--on-ink);
  transform: translateX(-2px) rotate(45deg);
}
.cal__chev--back { transform: translateX(2px) rotate(-135deg); }

.cal__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  padding: .55rem;
}
.cal__day {
  display: grid;
  gap: .15rem;
  justify-items: center;
  padding: .5rem .1rem .45rem;
  border-radius: 7px;
  border: 1px solid transparent;
  transition: background-color .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
.cal__dow {
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--on-ink-dim);
}
.cal__num {
  font-family: var(--text);
  font-weight: 600;
  font-size: 1.05rem;
  line-height: 1.1;
  color: var(--on-ink);
  font-variant-numeric: tabular-nums;
}
/* the marker rail keeps every cell the same height, dot or no dot */
.cal__mark { width: 4px; height: 4px; border-radius: 50%; background: transparent; }
.cal__day--today .cal__mark { background: var(--azure); }

.cal__day:hover:not(:disabled) { border-color: var(--rule); background: var(--deep); }
.cal__day[aria-checked="true"] { background: var(--coral); border-color: var(--coral); }
.cal__day[aria-checked="true"] .cal__num { color: var(--ink); }
.cal__day[aria-checked="true"] .cal__dow { color: rgba(15, 23, 34, .75); }
.cal__day[aria-checked="true"] .cal__mark { background: var(--ink); }
.cal__day:disabled { opacity: .26; cursor: not-allowed; }

.cal__echo {
  padding: .7rem .8rem;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: var(--s--1);
  color: var(--on-ink-dim);
}
.cal__echo--set { color: var(--azure-lift); }

.form__send { width: 100%; margin-top: .3rem; }
.form__note {
  font-family: var(--mono);
  font-size: var(--s--1);
  color: var(--on-ink-dim);
  text-align: center;
}
.form__note--bad { color: var(--coral-lift); }
.form__note--good { color: var(--azure); }

/* =========================================================
   responsive — later sections
   ========================================================= */
@media (max-width: 900px) {
  .cinefoot__word { font-size: 26vw; bottom: -3vh; }
  .cinefoot__h { font-size: var(--s-3); }
  /* the brand block stops competing with the columns for width */
  .cinefoot__index { grid-template-columns: 1fr; gap: 1.6rem; }
}

/* One screen minus the masthead is a hard budget on a phone, and everything
   in this footer is content. So the space comes out of padding and spacing
   only — nothing readable is hidden. Measured at 375x812; if you add a row,
   re-measure, because the pinned footer clips what will not fit. */
@media (max-width: 620px) {

  .cinefoot__main { gap: .8rem; }
  .cinefoot__ctas { width: 100%; gap: .6rem; margin-top: .2rem; }
  .cinefoot__ctas .cinefoot__pill { width: 100%; justify-content: center; padding: .8rem 1.2rem; }

  .cinefoot__index { gap: 1rem; }
  .mark__logo--foot { height: 36px; }
  .cinefoot__tag { margin-top: .5rem; max-width: none; font-size: .82rem; }

  .cinefoot__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .9rem 1rem; }
  .cinefoot__col { gap: .3rem; }
  .cinefoot__col a { font-size: .86rem; }
  /* the address is the widest single item at this size, so its column gets
     the full width rather than forcing a two-line wrap */
  .cinefoot__col:last-child { grid-column: 1 / -1; }

  /* badge on its own line, then the copyright and the top button share one */
  .cinefoot__bottom {
    justify-content: center;
    text-align: center;
    gap: .7rem;
    margin-top: .9rem;
    padding: 1rem var(--gut) 1.2rem;
  }
  .cinefoot__badge { order: 1; padding: .55rem 1rem; }
  .cinefoot__legal { order: 2; }
  .cinefoot__totop { order: 3; padding: .7rem; }
}

@media (max-width: 560px) {
  .field--pair { grid-template-columns: 1fr; }
  .q__btn { gap: 1rem; }
  /* seven columns is a fixed constraint, so buy the day cells width back
     from the padding around them */
  .form { padding: 1.15rem; }
  .cal__grid { padding: .3rem; gap: 1px; }
  .cal__day { padding: .55rem .05rem .5rem; }
}

/* =========================================================
   reduced motion
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .rise { opacity: 1; transform: none; }
  .nav.is-open a { animation: none; }
  /* the reel still expands — that is the content, not decoration — but it
     snaps rather than eases, and nothing zooms or slides */
  .reel__media img { transform: none !important; }
  .reel__body { transform: none !important; }
  .gcard:hover { transform: none; }
  .gcard:hover::after { transform: none; }
  .gcard__go:hover .gcard__arrow { transform: none; }
  /* the footer still reveals — that is just the page ending — but nothing
     drifts, breathes or scrolls on its own while it does */
  .cinefoot__word,
  .cinefoot__h, .cinefoot__ctas, .cinefoot__index {
    opacity: 1 !important;
  }
  .cinefoot__word { transform: translateX(-50%) !important; }
  .cinefoot__h, .cinefoot__ctas, .cinefoot__index { transform: none !important; }
  .cinefoot__pill { transform: none !important; }
  .draft.is-live .draft__frame,
  .draft.is-live .draft__panel,
  .draft.is-live .draft__frame-line,
  .draft.is-live .ink,
  .draft.is-live .draft__hair { stroke-dasharray: none; stroke-dashoffset: 0; }
}
