/* ═══════════════════════════════════════════════════════════════════
   RonLabs — design layer

   Blend brief: Apple's tile rhythm, typographic discipline and single
   accent · The Web Guys' near-black canvas, large light-weight hero
   and numbered project index.

   One type family. One accent. Alternating full-bleed tiles, where the
   surface change itself is the divider — no borders, no decorative
   gradients, no shadows on chrome.
   ═══════════════════════════════════════════════════════════════════ */

:root{
  /* Surfaces — the only structural device */
  --canvas: #FFFFFF;
  --pearl:  #F5F5F7;
  --void:   #0A0A0C;

  /* Ink */
  --ink:    #111113;
  --body:   #3A3A3E;
  --faint:  #86868B;
  --hair:   #E4E4E7;

  /* On dark */
  --on-dark:       #FFFFFF;
  --on-dark-body:  rgba(255,255,255,.62);
  --on-dark-faint: rgba(255,255,255,.42);
  --on-dark-hair:  rgba(255,255,255,.10);

  /* The single accent — sampled straight from the logo, whose gradient runs
     #368B70 (deep emerald) -> #ADEC59 (lime). Which end gets used depends on
     the surface: the lime reads 14:1 on the void but only 1.4:1 on white, and
     the emerald is the reverse. Both are the brand colour; only one of them is
     ever legible in a given place. */
  --brand:      #99DA5F;   /* lime end — dark tiles and fills   11.8:1 on void */
  --brand-hi:   #ADEC59;   /* gradient terminus — hover on a fill            */
  --brand-deep: #2E7A61;   /* emerald end — text on white         5.2:1      */
  --brand-grad: linear-gradient(100deg, #368B70 0%, #ADEC59 100%);

  /* The hero card's story, in one place. --story is the paper->app->ticked
     run; --story-delay holds it until the card has finished fading in, so the
     opening beat is not spent behind an invisible card. The flip follows, and
     JS reads both of these rather than hard-coding its own timing. */
  --story:       2.4s;
  --story-delay: .35s;

  --shell: 1240px;
  --ease:  cubic-bezier(.2,.7,.25,1);
  --ease-out: cubic-bezier(.16,1,.3,1);
}

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

html{ scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body{
  margin: 0;
  overflow-x: hidden;
  background: var(--void);
  font-size: 17px;
  line-height: 1.47;
  letter-spacing: -.011em;
  font-synthesis-weight: none;
}

a{ color: inherit; text-decoration: none; }
ul, ol, dl, dd, figure{ margin: 0; padding: 0; list-style: none; }
h1,h2,h3,p{ margin: 0; }

::selection{ background: var(--brand-deep); color: #fff; }

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

.skip{
  position: fixed; top: 8px; left: 8px; z-index: 200;
  transform: translateY(-160%);
  background: var(--ink); color: #fff;
  padding: 10px 16px; border-radius: 8px; font-size: 14px;
  transition: transform .3s var(--ease);
}
.skip:focus{ transform: none; }

/* ── Scroll progress ───────────────────────────────────────────── */

/* ═══════════════  NAVIGATION  ═══════════════ */
.nav{
  position: fixed; inset: 0 0 auto; z-index: 100;
  transition: background .45s var(--ease), backdrop-filter .45s var(--ease);
}
.nav.is-stuck{
  background: rgba(255,255,255,.72);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
}
.nav.is-stuck[data-tone="dark"]{ background: rgba(10,10,12,.62); }

.nav-inner{
  display: flex; align-items: center; justify-content: space-between;
  height: 60px;
}

/* Lockup: the real mark + wordmark artwork.
   Both exist in two cuts. The logo gradient runs emerald -> lime, so the
   as-supplied artwork sings on the void but washes out on white; the -ink cut
   is the same gradient darkened to 5.6-12.5:1. The pair is cross-faded on tone
   rather than swapped, so the nav never flickers mid-scroll. */
.wordmark{
  display: inline-flex; align-items: center; gap: 9px;
  line-height: 0;
}
.wm-mark, .wm-word{ position: relative; display: block; flex: none; }
.wm-mark{ height: 27px; width: auto; transition: transform .55s var(--ease-out); }
.wm-word{ height: 14px; width: auto; }
.wordmark:hover .wm-mark{ transform: translateY(-1px) scale(1.06); }

/* The light cut sits on top and fades away over dark tiles. */
.wm-mark img, .wm-word img{
  display: block; height: 100%; width: auto;
}
.wm-swap{ position: relative; }
.wm-swap .on-light{ position: absolute; inset: 0; }
.wm-swap img{ transition: opacity .45s var(--ease); }
.nav[data-tone="dark"] .wm-swap .on-light,
.foot .wm-swap .on-dark{ opacity: 0; }
.nav[data-tone="light"] .wm-swap .on-dark{ opacity: 0; }

.nav-links{ display: none; gap: 34px; }
.nav-links a{
  position: relative;
  font-size: 14px; font-weight: 500; letter-spacing: -.012em;
  color: var(--body);
  transition: color .35s var(--ease);
}
.nav[data-tone="dark"] .nav-links a{ color: var(--on-dark-body); }
.nav-links a::after{
  content: ""; position: absolute; left: 0; right: 0; bottom: -6px; height: 1.5px;
  background: currentColor; border-radius: 2px;
  transform: scaleX(0); transform-origin: right;
  transition: transform .45s var(--ease-out);
}
.nav-links a:hover{ color: var(--ink); }
.nav[data-tone="dark"] .nav-links a:hover{ color: var(--on-dark); }
.nav-links a:hover::after{ transform: scaleX(1); transform-origin: left; }

.nav-end{ display: flex; align-items: center; gap: 10px; }
.nav-end .pill-sm{ display: none; }

.menu-btn{
  display: grid; place-items: center;
  width: 40px; height: 40px; margin-right: -8px;
  background: none; border: 0; cursor: pointer; color: var(--ink);
  transition: color .45s var(--ease);
}
.nav[data-tone="dark"] .menu-btn{ color: var(--on-dark); }

.menu-bars, .menu-bars::before, .menu-bars::after{
  display: block; width: 19px; height: 1.5px; border-radius: 2px;
  background: currentColor;
  transition: transform .4s var(--ease-out), opacity .2s var(--ease);
}
.menu-bars{ position: relative; }
.menu-bars::before, .menu-bars::after{ content: ""; position: absolute; left: 0; }
.menu-bars::before{ top: -6px; }
.menu-bars::after{ top: 6px; }
body.menu-open .menu-bars{ background: transparent; }
body.menu-open .menu-bars::before{ transform: translateY(6px) rotate(45deg); }
body.menu-open .menu-bars::after{ transform: translateY(-6px) rotate(-45deg); }

.menu{
  position: fixed; inset: 0; z-index: 95;
  background: rgba(10,10,12,.94);
  backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px);
  display: grid; place-items: center;
}
/* The display rule above would otherwise beat the browser's own [hidden]. */
.menu[hidden]{ display: none; }
.menu nav{ display: flex; flex-direction: column; gap: 4px; text-align: center; }
.menu a{
  font-size: clamp(2rem, 9vw, 2.75rem);
  font-weight: 500; letter-spacing: -.035em; line-height: 1.3;
  color: var(--on-dark);
  opacity: 0; transform: translateY(14px);
  animation: menuIn .55s var(--ease-out) forwards;
}
.menu a:nth-child(1){ animation-delay: .04s }
.menu a:nth-child(2){ animation-delay: .09s }
.menu a:nth-child(3){ animation-delay: .14s }
.menu a:nth-child(4){ animation-delay: .19s }
.menu a:nth-child(5){ animation-delay: .24s; color: var(--brand); }
@keyframes menuIn{ to{ opacity: 1; transform: none } }

/* ═══════════════  BUTTONS  ═══════════════ */
.pill{
  display: inline-flex; align-items: center; justify-content: center;
  padding: 11px 22px; border-radius: 980px;
  font-size: 15px; font-weight: 500; letter-spacing: -.014em; line-height: 1;
  white-space: nowrap;
  transition: background .3s var(--ease), color .3s var(--ease),
              border-color .3s var(--ease), transform .18s var(--ease);
}
.pill:active{ transform: scale(.96); }
.pill-sm{ padding: 8px 16px; font-size: 14px; }
.pill-lg{ padding: 15px 30px; font-size: 17px; }

.pill-accent{ background: var(--brand); color: var(--void); font-weight: 600; }
.pill-accent:hover{ background: var(--brand-hi); }

.pill-ghost-dark{
  border: 1px solid rgba(255,255,255,.24); color: var(--on-dark);
}
.pill-ghost-dark:hover{ border-color: rgba(255,255,255,.6); }

/* Circle-and-label CTA */
.ghost-cta{ display: inline-flex; align-items: center; gap: 14px; }
.ghost-ring{
  display: grid; place-items: center;
  width: 46px; height: 46px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,.26); color: var(--on-dark);
  transition: border-color .4s var(--ease), background .4s var(--ease), transform .4s var(--ease-out);
}
.ghost-cta:hover .ghost-ring{ border-color: transparent; background: rgba(255,255,255,.12); transform: translateY(3px); }
.ghost-label{
  font-size: 15px; font-weight: 500; line-height: 1.3;
  letter-spacing: -.01em; white-space: nowrap;
  color: var(--on-dark-body);
  transition: color .4s var(--ease);
}
.ghost-cta:hover .ghost-label{ color: var(--on-dark); }

/* ═══════════════  TILES & TYPE  ═══════════════ */
.tile{ position: relative; padding: clamp(80px, 11vw, 140px) 0; }
.tile-canvas{ background: var(--canvas); color: var(--ink); }
.tile-pearl{ background: var(--pearl); color: var(--ink); }
.tile-void{ background: var(--void); color: var(--on-dark); }

.eyebrow{
  display: block;
  font-size: 15px; font-weight: 500; line-height: 1.3;
  letter-spacing: -.01em;
  color: var(--faint);
}
.eyebrow-dark{ color: var(--on-dark-faint); }


.display{
  margin-top: 22px;
  font-size: clamp(2.125rem, 4.6vw, 3.5rem);
  font-weight: 600; line-height: 1.07; letter-spacing: -.035em;
  max-width: 18ch;
}
.display-sm{ font-size: clamp(1.875rem, 3.4vw, 2.75rem); max-width: 14ch; }
.display-dark{ color: var(--on-dark); }
.display:first-child{ margin-top: 0; }

.lead{
  margin-top: 24px; max-width: 46ch;
  font-size: clamp(1.0625rem, 1.35vw, 1.3125rem);
  font-weight: 400; line-height: 1.5; letter-spacing: -.016em;
  color: var(--body);
}
.lead-dark{ color: var(--on-dark-body); }

.tile-head{ margin-bottom: clamp(52px, 6vw, 84px); }
.tile-head-center{ text-align: center; }
.tile-head-center .display,
.tile-head-center .lead{ margin-left: auto; margin-right: auto; }
.tile-head-center .display{ max-width: 22ch; }

/* ═══════════════  HERO  ═══════════════ */
.hero{ padding: 0; overflow: hidden; }

/* A single soft light sweep. No decorative gradient stack. */
.hero-sheen{
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(120% 80% at 78% 8%,  rgba(255,255,255,.085) 0%, transparent 58%),
    radial-gradient(90%  70% at 12% 96%, rgba(110,200,100,.13)  0%, transparent 62%);
}

/* Scroll exit — the hero drifts up a little slower than the page and dims out,
   so the tile below feels like it rises to meet it. Driven from JS. */
.hero-inner{
  position: relative;          /* containing block for .proof */
  will-change: transform, opacity;
}

/* The whole hero warms a few percent toward green while the app is
   resolved, then settles back. Deliberately small: a full green hero every
   16s behind the headline would be a strobe, and surface colour is what
   separates sections on this page. Gated to the same breakpoint as the
   card, so the page never glows green with nothing to justify it. */
.hero-tint{
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(95% 75% at 76% 48%, rgba(153,218,95,.13) 0%, transparent 60%),
    linear-gradient(180deg, rgba(110,200,100,.05), rgba(110,200,100,.02));
  opacity: 0;
  animation: heroLift var(--story) var(--ease) var(--story-delay) both;
}
/* The card sits centre-stage on mobile and off to the right on desktop, so
   the warm spot follows it. */
@media (max-width: 1149px){
  .hero-tint{
    background:
      radial-gradient(85% 45% at 50% 50%, rgba(153,218,95,.13) 0%, transparent 62%),
      linear-gradient(180deg, rgba(110,200,100,.05), rgba(110,200,100,.02));
  }
}
@keyframes heroLift{
  0%,  34%  { opacity: 0 }
  54%, 82%  { opacity: 1 }
  100%      { opacity: .3 }   /* recede as the card turns to business */
}

/* ── Hero proof: paper becomes an app ────────────────────────────────
   The thing the studio actually sells, in one picture: a filled-in paper
   form straightens into a phone screen and ticks itself off.

   The rule that keeps it from looking like stock art is that the ROWS
   PERSIST across the morph — only the container and its furniture change.
   That reads as the same work moving, rather than two unrelated pictures
   cross-fading.

   Only the container's transform, border-radius and opacities animate, so
   nothing here triggers layout. Desktop only: there is no room beside the
   headline below ~1150px, and it is furniture rather than content, so it
   simply goes away. */
/* Mobile: in flow, centred in the dead space between the headline and the
   lead — which is exactly the job it does on the right at desktop. It is
   smaller and its internals tighten, rather than being hidden outright. */
.proof{
  position: relative;
  width: 236px; height: 300px;
  margin: 22px auto;          /* guaranteed air; justify-between alone leaves none */
  flex: none;
  perspective: 1400px;
  opacity: 0;
  animation: fadeUp .5s var(--ease-out) 150ms forwards;
}

/* ── The flip ────────────────────────────────────────────────────────
   The story plays once and the card lands on the form, rather than
   looping. A form that flips away every 16s mid-typing is unusable, and
   one that exists for 5s in every 16 is worse than no form at all. */
.proof-flip{
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  transition: transform .65s cubic-bezier(.66,0,.28,1);
}
.proof-flip.is-flipped{ transform: rotateY(180deg); }

.proof-face{
  position: absolute; inset: 0;
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
}
.proof-front{ pointer-events: none; }          /* decorative only */
.proof-back{
  transform: rotateY(180deg);
  border-radius: 26px;
  /* A plain white card with green buttons: user testing wanted it to read
     unmistakably as "a form to fill in", not as more of the animation. */
  border: 1px solid rgba(255,255,255,.6);
  background: var(--canvas);
  box-shadow: 0 40px 80px -30px rgba(0,0,0,.55);
  overflow: hidden;
}
/* Not tab-reachable while it is facing away. JS clears this on flip. */
.proof-back[inert]{ pointer-events: none; }

/* ── The form ────────────────────────────────────────────────────── */
.pf{
  display: flex; flex-direction: column;
  height: 100%; padding: 18px 16px 16px;
}
.pf-title{
  font-size: 17px; font-weight: 600; letter-spacing: -.024em;
  color: var(--void);
}
.pf-sub{
  margin-top: 4px; margin-bottom: 12px;
  font-size: 11.5px; line-height: 1.4; letter-spacing: -.006em;
  color: #6E6E73;
}
.pf-field{ display: block; margin-bottom: 9px; }
.pf-field-grow{ flex: 1; display: flex; flex-direction: column; }
.pf-field > span{
  display: block; margin-bottom: 4px;
  font-size: 12.5px; font-weight: 500;
  letter-spacing: -.005em;
  color: #6E6E73;
}
.pf-field input, .pf-field textarea{
  width: 100%; flex: 1;
  padding: 7px 9px;
  font: inherit; font-size: 13px; letter-spacing: -.008em;
  color: var(--void);
  background: var(--pearl);
  border: 1px solid #D9D9DE;
  border-radius: 8px;
  resize: none;
  transition: border-color .25s var(--ease), background .25s var(--ease);
}
.pf-field input:focus, .pf-field textarea:focus{
  outline: none;
  border-color: var(--brand-deep);
  background: var(--canvas);
  box-shadow: 0 0 0 3px rgba(46,122,97,.15);
}
.pf-field input:user-invalid, .pf-field textarea:user-invalid{
  border-color: #E06A5A;
}
.pf-send{
  margin-top: 4px; padding: 9px 16px;
  font: inherit; font-size: 14px; font-weight: 600; letter-spacing: -.012em;
  color: var(--void); background: var(--brand);
  border: 0; border-radius: 980px; cursor: pointer;
  transition: background .25s var(--ease), transform .18s var(--ease);
}
.pf-send:hover{ background: var(--brand-hi); }
.pf-send:active{ transform: scale(.97); }
.pf-status{
  margin-top: 7px; min-height: 13px;
  font-size: 11px; line-height: 1.35; letter-spacing: -.004em;
  color: var(--brand-deep);
}
.pf-status[data-state="error"]{ color: #C0392B; }
.pf.is-sent .pf-field, .pf.is-sent .pf-send, .pf.is-sent .pf-sub{ display: none; }
@media (min-width: 1150px){
  .proof{
    position: absolute; right: 2.5rem; top: 50%;
    width: 320px; height: 500px; margin: -250px 0 0;
  }

  /* Two classes deep so this beats Tailwind's utilities whatever order the
     stylesheets load in. Capping the height stops a tall monitor stretching
     the hero into a band of dead space under the nav. */
  .hero .hero-inner{
    min-height: min(100svh, 920px);
    padding-top: 120px;
  }
  /* The card is pinned to the hero's vertical centre, so the headline has to
     meet it there. Growing this block and centring inside it puts the two on
     a shared optical line and takes the pooled space out from underneath. */
  .hero-head{
    position: relative;
    flex: 1;
    display: flex; flex-direction: column; justify-content: center;
  }

  /* The eyebrow lifts out of the flow to sit up in the empty band under the
     nav, instead of hugging the headline. Taking it out of the centred block
     also means the headline now centres on itself, which tightens its
     alignment with the card rather than sitting a line-height low. */
  .hero-head .eyebrow{ position: absolute; top: 34px; left: 0; }
  .hero-head .hero-h1{ margin-top: 0; }
}

.proof-card{
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  padding: 26px 20px 20px;
  border: 1px solid rgba(255,255,255,.13);
  background: linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.015));
  animation: proofMorph var(--story) var(--ease) var(--story-delay) both;
  will-change: transform, border-radius;
}
/* The scale is the point: the thing does not just change shape, it gets
   bigger. Paper sits back at .92, the app comes forward at 1.05. */
@keyframes proofMorph{
  0%,   32% { transform: rotate(-3.5deg) scale(.92); border-radius: 3px;  }
  46%, 100% { transform: rotate(0deg)    scale(1.05); border-radius: 26px; }
}

/* Green bloom behind the card — the "this got better" signal. Sits before
   .proof-card in tree order, so it paints underneath without needing z-index. */
.proof::before{
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 190%; aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle closest-side,
              rgba(153,218,95,.26) 0%, rgba(153,218,95,.07) 46%, transparent 72%);
  opacity: 0;
  animation: proofBloom var(--story) var(--ease) var(--story-delay) both;
}
@keyframes proofBloom{
  0%,  34%  { opacity: 0; transform: translate(-50%,-50%) scale(.72) }
  52%, 100% { opacity: 1; transform: translate(-50%,-50%) scale(1)   }
}

/* Furniture that only exists once it is a phone. */
.proof-notch{
  position: absolute; top: 11px; left: 50%;
  width: 54px; height: 4px; margin-left: -27px;
  border-radius: 99px; background: rgba(255,255,255,.22);
  opacity: 0;
  animation: proofPhone var(--story) var(--ease) var(--story-delay) both;
}
.proof-foot{
  flex: none; height: 32px; margin-top: 18px;
  border-radius: 99px;
  background: rgba(153,218,95,.14);
  border: 1px solid rgba(153,218,95,.26);
  opacity: 0;
  animation: proofPhone var(--story) var(--ease) var(--story-delay) both;
}
@keyframes proofPhone{
  0%,  36%  { opacity: 0 }
  48%, 100% { opacity: 1 }
}

/* The title rule never changes — it is the anchor that proves it is
   still the same document. */
.proof-head{
  flex: none; width: 52%; height: 6px; margin-bottom: 24px;
  border-radius: 2px; background: rgba(255,255,255,.28);
}

.proof-rows{ flex: 1; display: flex; flex-direction: column; gap: 18px; }
.proof-row{ display: flex; align-items: center; gap: 12px; }

.proof-box{
  flex: none; width: 15px; height: 15px;
  display: grid; place-items: center;
  border: 1.5px solid rgba(255,255,255,.22); border-radius: 4px;
  animation: proofTick var(--story) var(--ease) both;
  animation-delay: calc(var(--story-delay) + var(--i) * .07s);
}
.proof-box svg{ width: 9px; height: 9px; }
.proof-box path{
  fill: none; stroke: var(--void); stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 12; stroke-dashoffset: 12;
  animation: proofCheck var(--story) var(--ease) both;
  animation-delay: calc(var(--story-delay) + var(--i) * .07s);
}
@keyframes proofTick{
  0%,  48%  { border-color: rgba(255,255,255,.22); background: transparent; }
  57%, 100% { border-color: var(--brand);          background: var(--brand); }
}
@keyframes proofCheck{
  0%,  50%  { stroke-dashoffset: 12 }
  60%, 100% { stroke-dashoffset: 0  }
}

/* Each row fills in, then holds. The width resets while invisible so the
   loop never visibly snaps back. */
.proof-line{
  height: 6px; width: 0;
  border-radius: 2px; background: rgba(255,255,255,.16);
  animation: proofFill var(--story) var(--ease) both;
  animation-delay: calc(var(--story-delay) + var(--i) * .07s);
}
@keyframes proofFill{
  0%,   6%  { width: 0;          opacity: 0 }
  11%       {                    opacity: 1 }
  26%, 100% { width: var(--w);   opacity: 1 }
}

/* Tighter metrics at the smaller mobile size. Scaling the whole card with a
   transform would have been fewer lines, but transforms do not affect layout —
   it would still reserve 408px in a 276px gap. */
@media (max-width: 1149px){
  /* The card has to hold a form now, so it is sized for that rather than for
     the decorative front face. Kept just inside the ~276px gap under the
     headline so the CTAs below stay on the fold. */
  .proof{ width: 216px; height: 250px; margin: 12px auto; }
  /* Two fields, not three. Name is optional precisely so hiding it here
     cannot block submission the way a hidden required field would. */
  .pf-optional{ display: none; }
  .pf{ padding: 13px 12px 12px; }
  .pf-title{ font-size: 15px; }
  .pf-sub{ display: none; }        /* copy, not a control — safe to hide */
  .pf-field{ margin-bottom: 7px; }
  .pf-field > span{ font-size: 11.5px; margin-bottom: 3px; }
  .pf-field input, .pf-field textarea{ padding: 6px 8px; font-size: 12px; border-radius: 7px; }
  .pf-send{ padding: 8px 14px; font-size: 13px; }
  .pf-status{ font-size: 10px; margin-top: 5px; }

  .proof::before{
    width: 150%;
    background: radial-gradient(circle closest-side,
                rgba(153,218,95,.20) 0%, rgba(153,218,95,.05) 46%, transparent 72%);
  }
  .proof-card{ padding: 14px 12px 11px; }
  .proof-head{ height: 5px; margin-bottom: 13px; }
  .proof-rows{ gap: 10px; }
  .proof-row{ gap: 9px; }
  .proof-box{ width: 12px; height: 12px; border-width: 1.3px; border-radius: 3px; }
  .proof-box svg{ width: 7px; height: 7px; }
  .proof-line{ height: 5px; }
  .proof-foot{ height: 22px; margin-top: 10px; }
  .proof-notch{ width: 40px; height: 3px; top: 8px; margin-left: -20px; }
  .proof-card{ border-radius: 3px; }
}

/* ── Mobile hero: the reel ───────────────────────────────────────────
   Below 1150px the form did not fit beside the headline without being
   squeezed, so this space shows the work instead: three real screens play
   one at a time: each turns in, builds itself,
   then turns away for the next. After the third, all three turn back in
   together as one staggered stack and stay there. JS drives the sequence
   (see main.js); CSS holds every position and state.

   A turn is two half-turns: out to edge-on one way, in from edge-on the
   other. Each layer's transform is composed from custom properties so the
   same transition serves both the solo turns and the move into the stack. */
.reel{ display: none; }

@media (max-width: 1149px){
  .proof{ display: none; }
  .hero-tint{ display: none; }     /* its timing belongs to the desktop card */

  .reel{
    display: block; position: relative;
    width: 100%; max-width: 360px; height: 286px;
    margin: 18px auto 6px;
    perspective: 1100px;
    opacity: 0;
    animation: fadeUp .5s var(--ease-out) 150ms forwards;
  }
  /* Soft green glow that arrives with the stack: the "all together" beat. */
  .reel::before{
    content: ""; position: absolute; left: 50%; top: 50%;
    width: 130%; aspect-ratio: 1; border-radius: 50%;
    transform: translate(-50%,-50%) scale(.7);
    background: radial-gradient(circle closest-side,
                rgba(153,218,95,.20) 0%, rgba(153,218,95,.05) 48%, transparent 72%);
    opacity: 0;
    transition: opacity .9s var(--ease), transform 1.1s var(--ease-out);
  }
  .reel.is-stacked::before{ opacity: 1; transform: translate(-50%,-50%) scale(1); }

  .reel-layer{
    --x: 0px; --y: 0px; --s: 1; --r: 90deg;
    position: absolute; left: 50%; top: 50%;
    width: 300px;
    transform: translate(-50%,-50%) translate(var(--x), var(--y)) scale(var(--s)) rotateY(var(--r));
    opacity: 0;
    backface-visibility: hidden;
    transition: transform .36s cubic-bezier(.2,.75,.3,1), opacity .18s linear;
    transition-delay: var(--delay, 0ms);
  }
  .reel-layer.is-in { --r: 0deg; opacity: 1; }
  .reel-layer.is-out{
    --r: -90deg; opacity: 0;
    transition: transform .28s cubic-bezier(.55,0,.85,.35), opacity .1s linear .18s;
  }
  .reel-layer.is-reset{ transition: none; }

  /* The reel's screens: a browser frame for the desktop tools and sites,
     a phone for the app. The order reader's close-up pops in a moment after
     its screen, as the one bit of build-up left. */
  .rl-shot{ position: relative; }
  .rl-desk, .rl-zoom, .rl-phone, .rl-mini{
    overflow: hidden; background: var(--canvas);
    box-shadow: 0 26px 50px -18px rgba(0,0,0,.75), 0 0 0 1px rgba(255,255,255,.14);
  }
  .rl-desk{ width: 100%; border-radius: 9px; }
  .rl-shot img{ display: block; width: 100%; height: auto; }
  .rl-desk .shot-bar{ background: #ECECEF; height: 16px; padding: 0 9px; gap: 4px; }
  .rl-desk .shot-bar i{ width: 6px; height: 6px; background: #CDCDD2; }
  .rl-zoom{
    position: absolute; right: -10px; bottom: -22px; width: 64%;
    border-radius: 8px;
    opacity: 0; transform: translateY(10px) scale(.96);
  }
  .cap-art.is-active .rl-zoom{ animation: capPop .5s var(--ease-out) .45s forwards; }
  .rl-phone{ width: 128px; border-radius: 18px; border: 3px solid #1D1D20; background: #000; }
  .rl-mini{
    position: absolute; right: -8px; bottom: -26px; width: 68px;
    border-radius: 11px; border: 2px solid #1D1D20; background: #000;
  }

  /* Together: dashboard at the back, website across the middle, phone in
     front. Each turns in a beat after the one behind it. (A fanned layout
     was tried and dropped: this cascade read better.) */
  .reel.is-stacked .reel-layer[data-k="1"]{ --x: -42px; --y: -56px; --s: .7; --delay:   0ms; z-index: 1; }
  .reel.is-stacked .reel-layer[data-k="3"]{ --x:  46px; --y:  22px; --s: .7; --delay: 120ms; z-index: 2; }
  .reel.is-stacked .reel-layer[data-k="2"]{ --x: -98px; --y:  34px; --s: .82; --delay: 240ms; z-index: 3; }

}



/* Three short masked lines — sized so none of them ever wraps. */
.hero-h1{
  margin-top: 30px;
  font-size: clamp(2.375rem, 7.2vw, 6.25rem);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -.045em;
  color: var(--on-dark);
}

/* ═══════════════  CAPABILITIES  ═══════════════
   Three cards, each carrying its own graphic and its own copy. This replaced
   a scroll-pinned list after user testing: the pinned section sat in white
   space and read as the bottom of the page, so people stopped scrolling.
   Nothing here is hidden behind interaction now — everything is on screen,
   and each graphic plays once as its card scrolls into view.

   The graphics are built from plain elements in the brand palette, the same
   way as the hero card, so they belong to this site rather than looking
   bought in. */
.cap-grid{ display: grid; gap: 48px 28px; }

.cap-card{ display: flex; flex-direction: column; }

.cap-visual{
  position: relative;
  display: grid; place-items: center;
  height: 320px; padding: 22px;
  background: var(--pearl);
  border-radius: 20px;
  overflow: hidden;
}
.cap-art{ margin: 0; width: 100%; display: grid; place-items: center; }

/* Real screens in each card. These replaced drawn mock-ups after feedback
   that people had to scroll a long way before seeing any actual work.
   Each piece slides up once as the card arrives (same trigger as before). */
.cap-shots{ position: absolute; inset: 0; display: block; }
.cap-shots > div{
  position: absolute; overflow: hidden; background: var(--canvas);
  box-shadow: 0 22px 44px -22px rgba(22,40,32,.38), 0 0 0 1px rgba(17,17,19,.06);
  opacity: 0; transform: translateY(14px);
}
.cap-art.is-active.cap-shots > div{
  animation: capIn .6s var(--ease-out) forwards;
  animation-delay: calc(.1s + var(--i) * .25s);
}
.cap-shots img{ display: block; width: 100%; height: auto; }
.cap-shots .shot-bar{ background: #ECECEF; height: 16px; padding: 0 8px; gap: 4px; }
.cap-shots .shot-bar i{ width: 6px; height: 6px; background: #CDCDD2; }
.sh-desk{ border-radius: 8px; }
.sh-phone{ border-radius: 14px; border: 3px solid #1D1D20; background: #000; }

.cap-shots[data-k="web"] .sh-desk{ left: 5%; top: 12%; width: 82%; }
.cap-shots[data-k="web"] .sh-panel{ right: 6%; top: 24%; width: 40%; border-radius: 12px; }

.cap-shots[data-k="team"] .sh-phone{ top: 8%; width: 36%; }
.cap-shots[data-k="team"] .sh-phone:first-child{ left: 11%; }
.cap-shots[data-k="team"] .sh-phone + .sh-phone{ right: 11%; top: 15%; }

.cap-shots[data-k="site"] .sh-desk{ left: 6%; top: 13%; width: 80%; }
.cap-shots[data-k="site"] .sh-phone{ right: 6%; top: 27%; width: 23%; }


.cap-body{ padding: 24px 2px 0; }
.cap-t{
  font-size: 23px; font-weight: 600; line-height: 1.18; letter-spacing: -.028em;
  color: var(--ink);
}
.cap-d{
  margin-top: 10px;
  font-size: 15.5px; line-height: 1.58; letter-spacing: -.012em;
  color: var(--body);
}

@media (min-width: 980px){
  .cap-grid{ grid-template-columns: repeat(3, minmax(0,1fr)); }
}

@keyframes capIn{ to{ opacity: 1; transform: none } }
@keyframes capPop{ to{ opacity: 1; transform: none } }


/* ═══════════════  WORK  ═══════════════
   User testing: "Where is the work? Where are the images so I can see what
   you've done?" So the section leads with real screenshots of real sites,
   shown on the page rather than behind a link that sends people away.

   Software comes second, as plain-English result cards. Most of it cannot be
   screenshotted without exposing a client's data, and for this audience the
   headline result ("2 trucks caught over their limit") says more than an
   interface would. No technical tags: testing called those jargon. */
.work-sub{
  margin: 0 0 22px;
  font-size: 17px; font-weight: 600; letter-spacing: -.02em;
  color: var(--on-dark-body);
}
.case-grid{ margin-bottom: 0; }
.case-grid + .work-sub{ margin-top: clamp(64px, 7vw, 96px); }

/* ── Website showcase ───────────────────────────────────────────── */
.show-grid{ display: grid; gap: 28px; }

.show-visual{
  position: relative;
  aspect-ratio: 16 / 11;
  border-radius: 18px;
  background:
    radial-gradient(90% 80% at 30% 20%, rgba(153,218,95,.07) 0%, transparent 60%),
    #141417;
  border: 1px solid var(--on-dark-hair);
  overflow: hidden;
}

/* Desktop screenshot in a quiet browser frame */
.shot-desk{
  position: absolute; left: 6%; top: 8%; width: 78%;
  border-radius: 9px; overflow: hidden;
  background: #fff;
  box-shadow: 0 30px 60px -28px rgba(0,0,0,.75), 0 0 0 1px rgba(255,255,255,.06);
  transition: transform .7s var(--ease-out);
}
.shot-bar{
  display: flex; gap: 5px; align-items: center;
  height: 20px; padding: 0 10px;
  background: #1E1E22;
}
.shot-bar i{ width: 7px; height: 7px; border-radius: 50%; background: rgba(255,255,255,.18); }
.shot-desk img{
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 10; object-fit: cover; object-position: top;
}

/* Same page on a phone, overlapping the corner — shows it was built to work
   on both, which is half of what a small business is buying. */
.shot-phone{
  position: absolute; right: 6%; bottom: 7%; width: 21%;
  aspect-ratio: 9 / 19.5;
  border-radius: 16px; overflow: hidden;
  border: 3px solid #26262B;
  background: #000;
  box-shadow: 0 26px 50px -20px rgba(0,0,0,.8);
  transition: transform .7s var(--ease-out);
}
.shot-phone img{ display: block; width: 100%; height: 100%; object-fit: cover; object-position: top; }


.show-meta{ padding: 20px 4px 0; }
.show-name{
  margin-top: 12px;
  font-size: clamp(1.25rem, 2vw, 1.5rem);
  font-weight: 600; letter-spacing: -.026em; line-height: 1.2;
  color: var(--on-dark);
}
.show-d{
  margin-top: 8px; max-width: 52ch;
  font-size: 15px; line-height: 1.58; letter-spacing: -.01em;
  color: var(--on-dark-body);
}
.show-link{
  display: inline-flex; align-items: center; gap: 6px; margin-top: 14px;
  font-size: 13.5px; letter-spacing: -.006em;
  color: var(--on-dark-faint);
  transition: color .35s var(--ease);
}
.show-link svg{ transition: transform .4s var(--ease-out); }
a.show-link:hover{ color: var(--brand); }
a.show-link:hover svg{ transform: translate(2px,-2px); }
.show-link.is-soon{ font-style: normal; }

/* Status chips, shared by both halves */
.site-status, .work-status{
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 500; letter-spacing: -.005em;
  color: var(--on-dark-faint);
}
.site-status::before, .work-status::before{
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor;
}
.site-status[data-state="live"], .work-status[data-state="live"]{ color: var(--brand); }

/* ── Software results ───────────────────────────────────────────── */
.case-grid{ display: grid; gap: 16px; }
.case{
  display: flex; flex-direction: column;
  padding: 26px 24px 24px;
  border: 1px solid var(--on-dark-hair); border-radius: 18px;
  background: rgba(255,255,255,.02);
}
/* Screenshot panel across the top of each software card. The apps are
   phone-first, so they are shown as phones; the order reader is a desktop
   tool, so it gets the same browser frame as the websites. Every screen is
   from a sandbox with invented data: no client's records appear. */
.case-visual{
  position: relative;
  aspect-ratio: 4 / 3;
  margin: -26px -24px 22px;
  border-radius: 17px 17px 0 0;
  border-bottom: 1px solid var(--on-dark-hair);
  background:
    radial-gradient(90% 80% at 30% 20%, rgba(153,218,95,.07) 0%, transparent 60%),
    #141417;
  overflow: hidden;
}
.case-phone{
  position: absolute; top: 11%; width: 37%;
  border-radius: 16px; overflow: hidden;
  border: 3px solid #26262B; background: #000;
  box-shadow: 0 26px 50px -20px rgba(0,0,0,.8);
  transition: transform .7s var(--ease-out);
}
.case-phone:first-child{ left: 10%; }
.case-phone + .case-phone{ right: 10%; top: 19%; }
.case-phone img{ display: block; width: 100%; height: auto; }
.case-desk{
  position: absolute; left: 6%; top: 11%; width: 88%;
  border-radius: 9px; overflow: hidden; background: #fff;
  box-shadow: 0 30px 60px -28px rgba(0,0,0,.75), 0 0 0 1px rgba(255,255,255,.06);
  transition: transform .7s var(--ease-out);
}
.case-desk img{ display: block; width: 100%; height: auto; }
/* The full screen is too small to read in a card, so the one line that
   matters is lifted out and shown at reading size over it. */
.case-zoom{
  position: absolute; right: 5%; bottom: 8%; width: 58%;
  border-radius: 10px; overflow: hidden; background: #fff;
  box-shadow: 0 24px 48px -16px rgba(0,0,0,.85), 0 0 0 1px rgba(255,255,255,.08);
  transition: transform .7s var(--ease-out);
}
.case-zoom img{ display: block; width: 100%; height: auto; }
.case .work-status{ align-self: flex-start; }

.case-stat{
  margin-top: 20px;
  font-size: clamp(2.1rem, 3.6vw, 2.8rem);
  font-weight: 600; line-height: 1; letter-spacing: -.045em;
  color: var(--brand);
}
.case-stat-l{
  margin-top: 8px; max-width: 44ch;
  font-size: 15px; line-height: 1.45; letter-spacing: -.01em;
  color: var(--on-dark);
}
.case-t{
  margin-top: 26px; padding-top: 22px;
  border-top: 1px solid var(--on-dark-hair);
  font-size: 17px; font-weight: 600; letter-spacing: -.02em; line-height: 1.3;
  color: var(--on-dark);
}
.case-t em{ font-style: normal; color: var(--brand); }
.case-d{
  margin-top: 9px;
  font-size: 14.5px; line-height: 1.6; letter-spacing: -.008em;
  color: var(--on-dark-body);
}
.case-note{
  margin-top: auto; padding-top: 16px;
  font-size: 13.5px; line-height: 1.5; letter-spacing: -.006em;
  color: var(--on-dark-faint);
}

@media (min-width: 820px){
  .show-grid{ grid-template-columns: repeat(2, minmax(0,1fr)); column-gap: 28px; row-gap: 48px; }
}
.case-body{ display: flex; flex-direction: column; flex: 1; }

/* A client's own words, set between the project cards rather than in a
   testimonial strip of their own, so it sits beside the work it's about.
   No card: the type carries it. */
.case-quote{
  margin: 28px 0 32px;
  padding: 0 4px;
}
.case-quote blockquote p{
  max-width: 46ch;
  font-size: clamp(1.25rem, 2.1vw, 1.75rem);
  font-weight: 500; line-height: 1.38; letter-spacing: -.022em;
  color: var(--on-dark);
  text-indent: -.42em;               /* hang the opening quote mark */
}
.case-quote figcaption{
  display: flex; align-items: baseline; gap: 10px;
  margin-top: 18px;
  font-size: 14.5px; letter-spacing: -.01em;
  color: var(--on-dark-faint);
}
.case-quote figcaption::before{
  content: ""; flex: none; align-self: center;
  width: 18px; height: 1px;
  background: var(--brand);
}
@media (max-width: 767px){
  .case-quote{ margin: 12px 0 20px; }
  .case-quote blockquote p{ font-size: 1.125rem; line-height: 1.45; }
}

/* Wide screens: one project per row, screenshots on one side at a size you
   can actually read, alternating sides down the list. */
@media (min-width: 980px){
  .case-grid{ gap: 24px; }
  .case{
    display: grid; grid-template-columns: minmax(0,1.35fr) minmax(0,1fr);
    padding: 0; overflow: hidden;
  }
  .case-visual{
    margin: 0; aspect-ratio: auto; min-height: 480px;
    border-radius: 0; border-bottom: 0; border-right: 1px solid var(--on-dark-hair);
  }
  .case-body{ padding: 40px 44px 38px 40px; justify-content: center; }
  .case-body .case-note{ margin-top: 0; padding-top: 22px; }
  .case:nth-child(even){ grid-template-columns: minmax(0,1fr) minmax(0,1.35fr); }
  .case:nth-child(even) .case-visual{ order: 2; border-right: 0; border-left: 1px solid var(--on-dark-hair); }
  .case-phone{ width: 30%; top: 9%; }
  .case-phone:first-child{ left: 14%; }
  .case-phone + .case-phone{ right: 14%; top: 16%; }
  .case-desk{ top: 12%; }
  .case-zoom{ width: 52%; }
  .case-stat{ font-size: clamp(2.6rem, 3.6vw, 3.3rem); }
  .case-t{ font-size: 20px; }
  .case-d{ font-size: 15.5px; max-width: 46ch; }
}

/* ═══════════════  PROCESS  ═══════════════ */
.steps{ display: grid; gap: 0; }
.step{ position: relative; padding: 30px 0; border-top: 1px solid var(--hair); }
.step:last-child{ border-bottom: 1px solid var(--hair); }
/* A line icon in a soft tint of the brand green, replacing the step number.
   Stroke is inherited via currentColor, so one rule styles all four and any
   future icon only has to supply geometry. */
.step-ico{
  display: grid; place-items: center;
  width: 46px; height: 46px;
  border-radius: 50%;
  color: var(--brand-deep);
  background: rgba(46,122,97,.09);
}
.step-ico svg{ width: 22px; height: 22px; }
.step-ico :is(path, rect, circle){
  fill: none;
  stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.step-t{
  margin-top: 18px;
  font-size: 22px; font-weight: 600; line-height: 1.2; letter-spacing: -.028em;
}
.step-d{
  margin-top: 10px; max-width: 40ch;
  font-size: 15.5px; line-height: 1.55; letter-spacing: -.012em;
  color: var(--body);
}
/* Single column: the icon moves up beside the title and grows, so each
   step reads as one row led by its picture instead of a small icon
   floating above a heading. */
@media (max-width: 767px){
  .step{
    display: grid; grid-template-columns: 58px minmax(0,1fr);
    column-gap: 18px; align-items: start;
  }
  .step-ico{ grid-row: 1 / span 2; width: 58px; height: 58px; }
  .step-ico svg{ width: 27px; height: 27px; }
  .step-t{ margin-top: 3px; }
  .step-d{ margin-top: 7px; }
}

/* ═══════════════  STUDIO  ═══════════════ */
.statement{
  font-size: clamp(1.3125rem, 2.1vw, 1.75rem);
  font-weight: 500; line-height: 1.3; letter-spacing: -.028em;
  color: var(--ink);
}
.prose-block p + p{
  margin-top: 20px;
  font-size: 17px; line-height: 1.6; letter-spacing: -.014em;
  color: var(--body);
}

/* ═══════════════  CLOSING  ═══════════════ */
.closing{ overflow: hidden; }
.closing-sheen{
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(72% 110% at 50% 122%, rgba(110,200,100,.16) 0%, transparent 58%);
}
.closing-h{
  font-size: clamp(2.5rem, 6.4vw, 5rem);
  font-weight: 600; line-height: 1.04; letter-spacing: -.042em;
  color: var(--on-dark);
}
.closing-p{
  margin: 26px auto 0; max-width: 50ch;
  font-size: clamp(1.0625rem, 1.3vw, 1.25rem);
  line-height: 1.52; letter-spacing: -.016em;
  color: var(--on-dark-body);
}
.closing-actions{
  margin-top: 40px;
  display: flex; flex-wrap: wrap; justify-content: center; gap: 12px;
}

/* ═══════════════  FOOTER  ═══════════════ */
.foot{ background: var(--pearl); color: var(--ink); padding: 72px 0 40px; }
.foot-grid{ display: grid; gap: 44px; }
.foot-brand p{
  margin-top: 16px; max-width: 34ch;
  font-size: 14px; line-height: 1.6; letter-spacing: -.01em; color: var(--faint);
}
.foot-col h3{
  font-size: 14px; font-weight: 600; letter-spacing: -.01em;
  color: var(--ink);
}
.foot-col a, .foot-col p{
  display: block; margin-top: 12px;
  font-size: 14.5px; letter-spacing: -.012em; color: var(--body);
  transition: color .3s var(--ease);
}
.foot-col a:hover{ color: var(--brand-deep); }

.foot-legal{
  margin-top: 56px; padding-top: 24px; border-top: 1px solid var(--hair);
  display: grid; gap: 6px;
  font-size: 12px; letter-spacing: -.006em; color: var(--faint);
}

/* ═══════════════  LEGAL PAGES  ═══════════════
   The privacy policy. One readable column in the site's type; headings do
   the navigating, so there is no table of contents to maintain. */
.legal-page{ padding-top: clamp(128px, 14vw, 176px); }
.legal{ max-width: 68ch; }
.legal-h{
  font-size: clamp(2.25rem, 4.6vw, 3.25rem);
  font-weight: 600; line-height: 1.08; letter-spacing: -.035em;
}
.legal-updated{ margin-top: 14px; font-size: 14px; color: var(--faint); }
.legal-lead{
  margin-top: 30px;
  font-size: clamp(1.125rem, 1.5vw, 1.3125rem); line-height: 1.5; letter-spacing: -.016em;
  color: var(--ink);
}
.legal h2{
  margin-top: 48px;
  font-size: 1.375rem; font-weight: 600; line-height: 1.25; letter-spacing: -.024em;
}
.legal h3{
  margin-top: 22px;
  font-size: 1.0625rem; font-weight: 600; letter-spacing: -.016em;
}
.legal p, .legal li{
  font-size: 16.5px; line-height: 1.65; letter-spacing: -.011em;
  color: var(--body);
}
.legal h2 + p, .legal h3 + p{ margin-top: 10px; }
.legal p + p, .legal ul + p, .legal p + ul{ margin-top: 14px; }
.legal ul{ display: grid; gap: 8px; }
.legal li{ position: relative; padding-left: 18px; }
.legal li::before{
  content: ""; position: absolute; left: 0; top: .8em;
  width: 7px; height: 1px; background: var(--brand-deep);
}
.legal a{
  color: var(--brand-deep);
  text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px;
}
.legal a:hover{ text-decoration-thickness: 2px; }

.foot-legal a{ color: inherit; transition: color .3s var(--ease); }
.foot-legal a:hover{ color: var(--brand-deep); }
.pf-sub a{ color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* ═══════════════  RESPONSIVE  ═══════════════ */
@media (min-width: 640px){
  .foot-legal{ grid-template-columns: 1fr auto; }
}

@media (min-width: 768px){
  .cards{ grid-template-columns: repeat(3,1fr); }
  .steps{ grid-template-columns: repeat(2,1fr); column-gap: 60px; }
  .step:nth-child(2){ border-top: 1px solid var(--hair); }
  .foot-grid{ grid-template-columns: 2fr 1fr 1fr; gap: 32px; }
}

@media (min-width: 1024px){
  .nav-inner{ height: 68px; }
  .nav-links{ display: flex; }
  .nav-end .pill-sm{ display: inline-flex; }
  .menu-btn{ display: none; }


  .steps{ grid-template-columns: repeat(4,1fr); column-gap: 32px; }
  .step{ border-top: 1px solid var(--hair); }
  .step:last-child{ border-bottom: 0; }

}

/* ═══════════════  MOTION  ═══════════════ */

/* Hero line-mask reveal, then a single sheen pass across the headline.

   The gradient is white everywhere EXCEPT a narrow band, so the text is
   solid white before and after the sweep and there is no state to clean
   up — the band simply travels off the end and stays there (forwards).
   Each line is nudged 110ms later than the one above so the highlight
   reads as one diagonal pass over the block rather than three separate
   flickers. */
.line{ display: block; overflow: hidden; padding-bottom: .04em; }
.line-i{
  display: block;
  transform: translateY(105%);
  animation: lineUp .85s var(--ease-out) forwards;
  animation-delay: var(--d, 0ms);
}
@keyframes lineUp{ to{ transform: none } }

@supports ((background-clip: text) or (-webkit-background-clip: text)){
  .hero-h1 .line-i{
    background-image: linear-gradient(100deg,
        #fff 0 40%,
        rgba(255,255,255,.70) 45%,
        var(--brand-hi)        50%,
        rgba(255,255,255,.70) 55%,
        #fff 60% 100%);
    background-size: 300% 100%;
    background-repeat: no-repeat;
    background-position: 100% 0;
    -webkit-background-clip: text;
            background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    /* An even ease, deliberately NOT var(--ease): that curve is fast-out /
       slow-in, which fires the band across in the first few frames and then
       leaves a second of dead air. A sweep wants a constant-ish pace. */
    animation: lineUp .85s var(--ease-out)            forwards,
               sheen  1.2s cubic-bezier(.42,0,.58,1)   forwards;
    animation-delay: var(--d, 0ms), calc(var(--d, 0ms) + 880ms + var(--i, 0) * 90ms);
  }
}
@keyframes sheen{ to{ background-position: 0% 0 } }

/* Forced-colours mode paints no backgrounds, so transparent text would
   vanish entirely. Hand the glyphs their colour back. */
@media (forced-colors: active){
  .hero-h1 .line-i{
    background: none; color: var(--on-dark);
    -webkit-text-fill-color: currentColor;
  }
}

/* Hero copy fades in once on load. Nothing below the hero animates on
   scroll: the page has one orchestrated moment, and it is this one. */
.hero .up{
  opacity: 0; transform: translateY(18px);
  animation: fadeUp .9s var(--ease-out) forwards; animation-delay: var(--d, 0ms);
}
@keyframes fadeUp{ to{ opacity: 1; transform: none } }

@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .hero .up{ opacity: 1; transform: none; }
  .line-i{ transform: none; }
  .hero-h1 .line-i{
    background: none !important; color: var(--on-dark) !important;
    -webkit-text-fill-color: currentColor !important;
  }
  .hero-inner{ transform: none !important; opacity: 1 !important; will-change: auto; }

  /* Show the proof at its resolved state rather than an empty form. */
  .proof{ opacity: 1 !important; animation: none !important; }
  /* No story, no flip — the form is the useful state, so go straight there. */
  .proof-flip{ transition: none !important; transform: rotateY(180deg) !important; }
  .proof::before{ opacity: 1 !important; animation: none !important;
                  transform: translate(-50%,-50%) !important; }
  .hero-tint{ display: none !important; }
  .proof-card{ animation: none !important; transform: scale(1.05) !important; border-radius: 26px !important; }
  .proof-notch, .proof-foot{ animation: none !important; opacity: 1 !important; }
  .proof-line{ animation: none !important; width: var(--w) !important; opacity: 1 !important; }
  .proof-box{ animation: none !important; border-color: var(--brand) !important; background: var(--brand) !important; }
  .proof-box path{ animation: none !important; stroke-dashoffset: 0 !important; }
}
