/* =============================================================
   Preload: wireframe stylesheet
   Plain white page, black text. Structure first; visual design
   comes later. Everything is driven by the tokens in :root so a
   later design pass can restyle without touching the markup.
   ============================================================= */

:root {
  --ink: #000;
  --paper: #fff;
  --muted: #000;
  --rule: #000;
  --rule-strong: #000;

  --max: 1120px;
  --gutter: clamp(28px, 4.5vw, 72px);
  --section-y: clamp(24px, 4svh, 40px);

  --font: "Manrope", "Helvetica Neue", Helvetica, Arial, system-ui, -apple-system, sans-serif;

  /* Display face, used for the nav and the hero headline. Saira is a
     variable font with wdth and wght axes, driven via
     font-variation-settings at each use site. */
  --font-display: "Saira", "Manrope", "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Corner language. Everything on the page uses one of these three:
     panels the largest, cards the middle, anything interactive a pill. */
  --radius-panel: 30px;
  --radius-card: 18px;
  --pill: 999px;

  /* Hero transition. --p (0 to 1) and --header-h are written by
     scroll.js; everything below is derived from them, so the whole
     effect can be retuned from these four values. */
  --p: 0;
  --header-h: 72px;
  --hero-inset: 16px;
  --hero-radius: 30px;

  /* How much of the resting state survives at the current scroll
     position. 1 at the top of the page, 0 once the hero is full bleed. */
  --rest: calc(1 - var(--p));
}

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 19px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

a { color: inherit; }

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

/* ---------- Type ---------- */

/* Saira sets the large headlines; Manrope carries reading text and card titles. */
h1, h2, h3, h4 {
  margin: 0 0 16px;
  font-family: var(--font-display);
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: -0.015em;
}

h1 { font-size: clamp(38px, 5.6vw, 68px); }
h2 { font-size: clamp(32px, 3.8vw, 46px); }
h3 { font-family: var(--font); font-size: 23px; font-weight: 500; letter-spacing: -0.015em; }
h4 { font-family: var(--font); font-size: 18px; font-weight: 500; letter-spacing: -0.01em; }

p { margin: 0 0 16px; }
p:last-child { margin-bottom: 0; }

/* The hero starts at the very top of the document and clips itself in
   from under the header, so no padding is reserved here. */
main { padding-top: 0; }

.eyebrow {
  margin-bottom: 20px;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.lede {
  max-width: 60ch;
  font-size: clamp(20px, 2.2vw, 24px);
  line-height: 1.55;
}

.section-lede {
  max-width: 68ch;
  font-size: 20px;
  color: var(--muted);
}

.subhead {
  margin: 80px 0 24px;
  font-size: 25px;
}

.muted { color: var(--muted); }

.footnote {
  max-width: 78ch;
  margin-top: 64px;
  font-size: 17px;
  color: var(--muted);
}

.list {
  margin: 0;
  padding-left: 20px;
}

.list li { margin-bottom: 8px; }
.list li:last-child { margin-bottom: 0; }

/* ---------- 1. Header banner ---------- */

/* A plain full-width bar attached to the top edge: square corners, no
   inset, no shadow. It stays pinned the whole way down and never moves.
   The only thing that changes is the surface: at --p 0 it is solid
   white over the white page with no border, so there is no line
   between it and the hero; by --p 1 the black hero has risen under it
   and it has become white frosted glass. */

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  background: rgba(255, 255, 255, calc(1 - var(--p) * 0.10));
  -webkit-backdrop-filter: blur(calc(var(--p) * 20px)) saturate(180%);
  backdrop-filter: blur(calc(var(--p) * 20px)) saturate(180%);
  border-bottom: 1px solid rgba(0, 0, 0, calc(var(--p) * 0.08));
}

/* Logo hard left, nav hard right, both pushed out to the page edges
   rather than sitting inside the centered content column. */
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 68px;
  /* Pulls the logo and nav in from the viewport edges so the header
     content sits over a narrower span than the full bar. */
  padding: 0 clamp(28px, 6vw, 96px);
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
}

.brand-mark { width: 28px; height: auto; }
.brand-word { width: 118px; height: auto; }

.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.site-nav a {
  font-family: var(--font-display);
  /* wght 200 is the light end of the axis. font-weight is set too so the
     fallback face lands somewhere sensible if Saira has not loaded. */
  font-variation-settings: "wdth" 100, "wght" 200;
  font-weight: 300;
  /* Caps read larger than lowercase, so the size comes down and the
     tracking opens up to keep them legible at this weight. */
  text-transform: uppercase;
  font-size: 15px;
  letter-spacing: 0.09em;
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
}

.site-nav a:hover { border-bottom-color: var(--ink); }

/* ---------- Sections ---------- */

.section {
  padding: var(--section-y) 0;
  margin-bottom: clamp(96px, 14svh, 144px);
  scroll-margin-top: 110px; /* clears the floating header on anchor jumps */
}

/* Editorial sections use evenly spaced dotted boundaries below. */

/* ---------- 2. Hero ---------- */

/* .hero is only a scroll runway. The visible panel sticks inside it,
   so the page keeps scrolling while the panel expands underneath the
   header. Height beyond 100vh is what gives the transition room. */
/* Runway only just long enough to finish the transition. Anything
   more and the hero holds you in place, which reads as sticky. */
.hero {
  position: relative;
  height: 128vh;
}

/* The panel is always a full-viewport box pinned at the top. The inset
   and rounded corners are drawn by clipping it, not by changing its
   size, so scrolling never recalculates layout. Note that this clip is
   NOT composited: it is driven by a custom property that scroll.js
   rewrites each frame, so the value is recomputed on the main thread.
   What keeps it cheap is that the canvases below have their own layers,
   which lets the compositor apply this clip to them rather than
   repainting the panel. Removing their will-change roughly doubles the
   raster work of a hero scroll. */
.hero-panel {
  position: sticky;
  top: 0;
  height: 100vh;
  background: var(--ink);
  color: var(--paper);
  display: flex;
  align-items: center;
  justify-content: flex-start;
  text-align: left;
  --hero-content-inset: clamp(44px, 9vw, 144px);
  padding: 0 var(--hero-content-inset);
/* Insets are top / right / bottom / left. Bottom is a hard zero so the
   panel always runs off the bottom of the screen, and the radius list
   rounds only the top two corners; the bottom two stay square because
   there is no visible bottom edge for them to sit on. */
  clip-path: inset(
    calc(var(--header-h) * var(--rest))
    calc(var(--hero-inset) * var(--rest))
    0
    calc(var(--hero-inset) * var(--rest))
    round
      calc(var(--hero-radius) * var(--rest))
      calc(var(--hero-radius) * var(--rest))
      0
      0
  );
  will-change: clip-path;
}

/* The panel above animates its clip-path every scroll frame. Giving the
   canvases their own compositor layers lets that clip be applied by the
   compositor instead of repainting the whole panel each frame. This is a
   rendering hint only: nothing moves and nothing is styled differently. */
.hero-dots {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  will-change: transform;
}
.hero-inner, .yc-badge { z-index: 1; }

/* Re-centres the text inside the visible (clipped) area, since at rest
   the clip takes a header's height off the top and nothing off the
   bottom. */
.hero-inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 50%;
  max-width: 680px;
  transform: translateY(calc(var(--header-h) * var(--rest) * 0.5));
}

/* Pill call to action. Hairline outline at rest, fills to solid on
   hover, no colour beyond the two the page already uses. */
.hero-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-top: 36px;
  padding: 14px 34px;
  border: 1px solid var(--paper);
  border-radius: 999px;
  color: var(--paper);
  text-decoration: none;
  text-align: center;
  font-family: var(--font-display);
  font-variation-settings: "wdth" 100, "wght" 300;
  font-size: 14px;
  line-height: 1.5;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  transition: background-color 0.35s ease, color 0.35s ease, border-color 0.35s ease;
}

.hero-cta:hover,
.hero-cta:focus-visible {
  background: var(--paper);
  border-color: var(--paper);
  color: var(--ink);
}

/* Sits at the foot of the hero, quiet enough to read as a credential
   rather than a claim. */
.yc-badge {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 30px;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-family: var(--font-display);
  font-variation-settings: "wdth" 100, "wght" 200;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.17em;
  color: var(--paper);
}

/* The mark stands alone after "Backed by", so it runs a little larger
   than it would beside a wordmark. */
.yc-logo {
  width: 19px;
  height: 19px;
  border-radius: 3px;
  display: block;
}

.hero-panel h1 {
  margin: 0;
  /* Wide enough that the tagline breaks over two lines, not three. */
  max-width: 680px;
  font-family: var(--font-display);
  /* wght 400 is the regular end of the axis. */
  font-variation-settings: "wdth" 100, "wght" 400;
  font-weight: 400;
  font-size: clamp(32px, 4.2vw, 62px);
  letter-spacing: -0.02em;
  line-height: 1.12;
  text-wrap: balance;
}

/* One short paragraph under the tagline: what we do, in plain terms. */
.hero-blurb {
  max-width: 58ch;
  margin: 22px 0 0;
  font-size: clamp(17px, 1.5vw, 20px);
  line-height: 1.65;
  color: var(--paper);
}

/* Inset rounded panel, echoing the hero's resting state. */
.section-invert {
  background: var(--ink);
  color: var(--paper);
  margin: 0 var(--hero-inset);
  border-radius: var(--radius-panel);
}

.section-invert .section-lede { color: var(--paper); }

/* ---------- Buttons ---------- */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 32px;
}

.btn {
  display: inline-block;
  padding: 13px 28px;
  border: 1px solid var(--ink);
  border-radius: var(--pill);
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  background: none;
  transition: background-color 0.3s ease, color 0.3s ease;
}

.btn-primary { background: var(--ink); color: var(--paper); }
.btn-primary:hover { background: var(--paper); color: var(--ink); }

.btn-secondary { background: var(--paper); color: var(--ink); }
.btn-secondary:hover { background: var(--ink); color: var(--paper); }

.btn-invert {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--paper);
}

.btn-invert:hover { background: var(--ink); color: var(--paper); }

/* ---------- Card grids ---------- */

/* Real gaps between separate rounded cards, rather than one bordered
   block subdivided by hairlines. */
.grid {
  display: grid;
  gap: 16px;
  margin-top: 40px;
}

.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }

.card {
  padding: 30px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
}

.card p { color: var(--muted); font-size: 18px; }
.card .list { color: var(--muted); font-size: 18px; }

/* ---------- Simple editorial sections ---------- */

.section.section-simple {
  position: relative;
  display: grid;
  align-items: center;
  min-height: max(760px, 100svh);
  margin: 0;
  padding: clamp(96px, 12svh, 144px) 0;
  text-align: left;
}
#problem.section-simple { margin-top: clamp(32px, 4vw, 56px); }

@media (max-width: 620px) {
  .section.section-simple { min-height: 100svh; padding-block: 88px; }
}
.section-simple h2 { max-width: none; }
.section-copy {
  max-width: 76ch;
  margin: 24px 0 0;
  font-size: 20px;
  line-height: 1.7;
  color: var(--ink);
}

/* The solution card expands on entry and returns to its inset on exit. */
#solution {
  --solution-p: 0;
  position: relative;
  isolation: isolate;
  min-height: 120svh;
  align-items: start;
  padding-block: clamp(160px, 20svh, 220px) clamp(100px, 12svh, 144px);
  color: #fff;
  margin-block: clamp(32px, 4vw, 56px);
}
#solution::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  clip-path: inset(calc(24px * (1 - var(--solution-p))) calc(var(--hero-inset) * (1 - var(--solution-p))) round calc(30px * (1 - var(--solution-p))));
  background: #000;
  pointer-events: none;
}
#solution::after { content: none; }
#solution .solution-content { max-width: 1360px; width: 100%; }
.solution-heading { text-align: center; }
.solution-heading .eyebrow { margin-bottom: 16px; }
.solution-heading h2 { margin: 0; }
.solution-parts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 48px);
  list-style: none;
  padding: 0;
  margin: clamp(64px, 9svh, 100px) 0 0;
  text-align: center;
}
.solution-icon-space { height: clamp(200px, 29svh, 320px); margin-bottom: 32px; }
.solution-summary { margin: clamp(44px, 6svh, 72px) auto 0; text-align: center; font-size: 19px; line-height: 1.6; color: #fff; }
.solution-parts h3 { margin: 0 0 12px; font-size: 24px; font-weight: 600; }
.solution-parts p { margin: 0; font-size: 17px; line-height: 1.6; color: #fff; }
@media (max-width: 900px) {
  .solution-parts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 40px 28px; }
  .solution-icon-space { height: 160px; margin-bottom: 24px; }
}
@media (max-width: 480px) {
  .solution-parts { gap: 32px 20px; }
  .solution-icon-space { height: 120px; }
  .solution-summary { font-size: 17px; }
  .solution-parts h3 { font-size: 21px; }
  .solution-parts p { font-size: 15px; }
}
#solution > .wrap { position: relative; z-index: 1; padding-inline: max(var(--gutter), 48px); }
.solution-dots {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  clip-path: inset(calc(24px * (1 - var(--solution-p))) calc(var(--hero-inset) * (1 - var(--solution-p))) round calc(30px * (1 - var(--solution-p))));
}
/* A distinct glass banner in either theme. */
.site-header {
  transition: background-color 360ms ease, color 360ms ease, border-color 360ms ease;
}
.site-header .brand img { transition: filter 360ms ease; }
html.solution-banner-active .site-header {
  background: rgba(0, 0, 0, .9);
  color: #fff;
  border-bottom-color: rgba(255, 255, 255, .08);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
}
html.solution-banner-active .site-header .brand img { filter: invert(1); }
.site-nav a:hover { border-bottom-color: currentColor; }
@media (prefers-reduced-motion: reduce) {
  .site-header, .site-header .brand img { transition: none; }
}
@media (prefers-reduced-motion: reduce) {
  #solution { min-height: 100svh; }
}

#customers { margin-bottom: 0; }
#contact {
  min-height: 100svh;
  margin-top: clamp(96px, 14svh, 144px);
  position: relative;
  isolation: isolate;
  background: transparent;
  padding-block: clamp(140px, 18svh, 180px);
}
#contact::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset-block: 0;
  inset-inline: calc(-1 * var(--hero-inset));
  clip-path: inset(0 calc(var(--hero-inset) * (1 - var(--contact-p, 0))) round calc(var(--radius-panel) * (1 - var(--contact-p, 0))));
  background: var(--ink);
  pointer-events: none;
}
html.is-wheel-scrolling { scroll-behavior: auto; }
#contact .contact-form { margin-top: 24px; gap: 16px; }
#contact textarea { min-height: 100px; height: 112px; }

@media (min-width: 1001px) and (max-height: 820px) {
  .section { padding-block: 24px; }
}
@media (max-width: 620px) {
  .section-copy { font-size: 18px; }
}

/* ---------- 6. Contact form ---------- */

.contact-form {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  margin-top: 48px;
  max-width: 860px;
}

.field { display: flex; flex-direction: column; gap: 8px; }
.field-full { grid-column: 1 / -1; }
.field .btn { align-self: flex-start; } /* keep the button from stretching to the column */

.field label {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

/* Single-line fields take the pill; the textarea takes the card radius,
   since a pill on a tall box reads as a mistake. */
.field input,
.field textarea {
  padding: 13px 20px;
  background: transparent;
  color: inherit;
  border: 1px solid var(--rule);
  border-radius: var(--pill);
  font-family: inherit;
  font-size: 18px;
  resize: vertical;
}

.field textarea {
  border-radius: var(--radius-card);
  padding: 16px 20px;
}

.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: currentColor;
}

/* Form sitting on the inverted panel needs its own borders. */
.section-invert .field input,
.section-invert .field textarea { border-color: var(--paper); }

.form-note {
  margin-top: 16px;
  font-size: 17px;
  color: var(--paper);
}

/* Spam trap. Taken out of flow rather than hidden with display:none,
   because bots routinely skip fields that are outright hidden and this
   one only works if they fill it in. */
.hp-field {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Submission feedback, written by contact-form.js. Collapsed while empty
   so it costs no space until there is something to say. */
.form-status {
  margin: 0;
  font-size: 17px;
  color: var(--paper);
}

.form-status:empty { display: none; }

/* ---------- 8. Footer ---------- */

/* No top rule: the black contact panel above already separates it. */
.site-footer {
  padding: clamp(80px, 9vw, 120px) 0 clamp(48px, 5vw, 72px);
}

/* Two columns while the "Elsewhere" links are out of the footer;
   restore the third (2fr 1fr 1fr) when they come back. */
.footer-inner {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 40px;
}

.footer-brand .brand-word { width: 132px; margin-bottom: 20px; }
.footer-brand p { font-size: 17px; margin-bottom: 8px; }

.footer-nav { display: flex; flex-direction: column; gap: 10px; }

.footer-nav h4 {
  margin: 0 0 4px;
  font-size: 14px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.footer-nav a {
  font-size: 17px;
  text-decoration: none;
  width: fit-content;
  border-bottom: 1px solid transparent;
}

.footer-nav a:hover { border-bottom-color: var(--ink); }

.footer-bottom {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 64px;
  padding-top: 24px;
  border-top: 1px solid var(--rule);
  font-size: 16px;
}

.footer-bottom p { margin: 0; }

/* ---------- Responsive ---------- */

@media (max-width: 900px) {
  :root { --section-y: 32px; }

  .grid-3 { grid-template-columns: repeat(2, 1fr); }

  .contact-form { grid-template-columns: repeat(2, 1fr); }
  .footer-inner { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 620px) {
  .hero-inner { width: 100%; }
  :root { --section-y: 24px; }
  body { font-size: 18px; }

  /* One row, always: nav left, logo right. The wordmark drops so the
     bar stays a single line at narrow widths. */
  .header-inner {
    gap: 12px;
    min-height: 56px;
    padding: 0 16px;
  }

  .site-nav { gap: 11px; }
  .site-nav a { font-size: 14px; }

  .brand-word { display: none; }
  .brand-mark { width: 24px; }

  :root { --hero-inset: 10px; --hero-radius: 20px; }

  .hero { height: 122vh; }

  .grid-2,
  .grid-3,
  .contact-form,
  .footer-inner { grid-template-columns: 1fr; }

  .actions .btn { width: 100%; text-align: center; }
}

/* ---------- Reduced motion ---------- */

/* No scroll-driven expansion. The hero stays a normal inset panel and
   the header stays a plain solid bar. scroll.js pins --p at 0 to match. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .hero { height: auto; }

  .hero-panel {
    position: static;
    height: auto;
    min-height: 72vh;
  }

  /* Plain solid bar pinned to the top, no glass transition. */
  .site-header {
    background: var(--paper);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* Shared rows align the copy with the dot field, excluding its source. */
.problem-stack {
  max-width: 1360px;
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  column-gap: clamp(32px, 4vw, 64px);
  row-gap: 0;
  align-items: stretch;
}
.problem-label { grid-column: 1; grid-row: 1; margin: 0 0 20px; }
.problem-copy {
  grid-column: 1;
  grid-row: 2;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 0;
}
.problem-copy h2 { margin-bottom: 24px; }
#problem .section-copy { margin: 0; max-width: none; }
.data-gap { display: contents; color: var(--ink); }
.data-gap-field { grid-column: 2; grid-row: 2; min-width: 0; position: relative; }
.data-gap-svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; overflow: visible; touch-action: pan-y; }
.data-gap figcaption { grid-column: 2; grid-row: 3; padding-inline: .667%; }
.data-gap-label, .data-gap-value { fill: currentColor; font-family: var(--font); font-size: 18px; }
.data-gap-label { font-weight: 500; }
.data-gap-value { font-weight: 600; }
.data-gap-dot-band { outline: none; }
.data-gap-benchmark .data-gap-label { font-weight: 700; }
.data-gap-dot-band:not(.data-gap-benchmark) .data-gap-label,
.data-gap-dot-band:not(.data-gap-benchmark) .data-gap-value { font-size: 15px; }
.data-gap-dot-band:focus-visible .data-gap-label { text-decoration: underline; text-underline-offset: 5px; }
.data-gap-source { margin-top: 20px; font-size: 12px; line-height: 1.6; }
@media (max-width: 1100px) {
  .problem-stack { grid-template-columns: 1fr; }
  .problem-copy { padding: 0; }
  .data-gap-field { grid-column: 1; grid-row: 3; margin-top: 48px; }
  .data-gap-svg { position: static; height: auto; aspect-ratio: 900 / 584; }
  .data-gap figcaption { grid-column: 1; grid-row: 4; }
}

/* One-time entrance, enabled only after the animation script initializes. */
.problem-motion-ready .problem-copy h2,
.problem-motion-ready .problem-copy .section-copy {
  opacity: 0;
}
.problem-motion-ready .problem-copy.is-revealed h2,
.problem-motion-ready .problem-copy.is-revealed .section-copy { transition: opacity 1800ms ease-in-out; }
.problem-motion-ready .problem-copy.is-revealed .section-copy { transition-delay: 400ms; }
.problem-motion-ready .problem-copy.is-revealed h2,
.problem-motion-ready .problem-copy.is-revealed .section-copy { opacity: 1; }
.problem-motion-ready .data-gap text,
.problem-motion-ready .data-gap figcaption {
  opacity: 0;
}
.problem-motion-ready .data-gap.is-revealed text,
.problem-motion-ready .data-gap.is-revealed figcaption { opacity: 1; transition: opacity 1400ms ease 400ms; }
@media (prefers-reduced-motion: reduce) {
  .problem-motion-ready .problem-copy h2,
  .problem-motion-ready .problem-copy .section-copy,
  .problem-motion-ready .data-gap text,
  .problem-motion-ready .data-gap figcaption { opacity: 1; transition: none; }
}

/* Continuous dot fields across Contact and the full footer. */
.contact-dot-layer {
  position: absolute;
  inset-block: 0;
  inset-inline: calc(-1 * var(--hero-inset));
  clip-path: inset(0 calc(var(--hero-inset) * (1 - var(--contact-p, 0))) round calc(var(--radius-panel) * (1 - var(--contact-p, 0))));
  overflow: hidden;
  pointer-events: none;
}
.contact-dots {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  display: block;
  width: 100vw;
  max-width: none;
  height: 100%;
}
#contact > .wrap { position: relative; z-index: 1; }
#contact input, #contact textarea { background: var(--ink); }
.site-footer { position: relative; }
.footer-dots {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.site-footer > .wrap { position: relative; z-index: 1; }

/* Audience copy aligned with its matching dot photograph. */
#customers .audience-content { max-width: 1360px; width: 100%; }
.audience-carousel { margin-top: clamp(40px, 6svh, 64px); }
.audience-stage { display: grid; grid-template-columns: 1fr 1fr; align-items: start; gap: clamp(40px, 6vw, 88px); }
.audience-slides { display: grid; min-width: 0; }
.audience-slide { grid-area: 1 / 1; opacity: 0; visibility: hidden; transform: translateY(4px); transition: opacity 1100ms cubic-bezier(.22,.61,.36,1), transform 1100ms cubic-bezier(.22,.61,.36,1), visibility 1100ms; pointer-events: none; }
.audience-slide[hidden] { display: none; }
.audience-slide.is-active { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }
.audience-slide h3 { font: 400 clamp(28px, 2.8vw, 38px) / 1.15 var(--font-display); margin: 0 0 20px; }
.audience-slide p { font-size: 20px; line-height: 1.65; max-width: 40ch; margin: 0; }
.audience-image-space { position: relative; width: 100%; aspect-ratio: 1100 / 780; }
.audience-controls { display: flex; align-items: center; justify-content: space-between; margin-top: 24px; }
.audience-controls[hidden] { display: none; }
.audience-dots, .audience-actions { display: flex; align-items: center; }
.audience-controls button { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; background: transparent; color: #000; cursor: pointer; }
.audience-dots button span { width: 7px; height: 7px; border: 1px solid #000; border-radius: 50%; transition: background-color 250ms, transform 250ms; }
.audience-dots button[aria-current="true"] span { background: #000; }
.audience-dots button:hover span { transform: scale(1.25); }
.audience-actions { gap: 8px; }
.audience-actions button { font: 400 24px var(--font); border-radius: 50%; transition: background-color 200ms, color 200ms; }
.audience-actions button:hover { color: #fff; background: #000; }
.audience-controls button:focus-visible { outline: 2px solid #000; outline-offset: 2px; }
.audience-announcement { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
@media (max-width: 700px) {
  .audience-stage { grid-template-columns: 1fr; gap: 32px; }

  .audience-slide p { font-size: 18px; }
  .audience-controls { margin-top: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .audience-slide, .audience-controls button, .audience-dots button span { transition: none; transform: none; }
}

.audience-picture { position: absolute; inset: 0; opacity: 0; visibility: hidden; pointer-events: none; overflow: hidden; border-radius: 10px; background: #fff; transition: opacity 1100ms cubic-bezier(.22,.61,.36,1), visibility 1100ms; touch-action: pan-y; }
.audience-picture.is-active { opacity: 1; visibility: visible; pointer-events: auto; }
.audience-picture img, .audience-picture canvas { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.audience-picture canvas { visibility: hidden; }
.audience-picture.dot-photo-ready canvas { visibility: inherit; }
.audience-picture.dot-photo-ready img { visibility: hidden; }
.audience-picture:focus-visible { outline: 2px dotted #000; outline-offset: 5px; }
@media (prefers-reduced-motion: reduce) { .audience-picture { transition: none; } }

.solution-icon-space { display: flex; align-items: center; justify-content: center; }

/* Quiet data patterns occupy the space below the audience copy. */
.audience-slides { align-self: stretch; grid-template-rows: auto minmax(120px, 1fr); row-gap: 32px; }
.audience-pattern { grid-area: 2 / 1; position: relative; min-height: 120px; }
.audience-pattern canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
@media (max-width: 700px) {
  .audience-slides { grid-template-rows: auto 112px; row-gap: 24px; }
  .audience-pattern { min-height: 0; }
}

.solution-factory { width: 100%; height: clamp(340px, 33vw, 440px); margin-top: 32px; pointer-events: none; }
#solution .solution-parts { margin-top: 12px; }
@media (max-width: 900px) {
  .solution-factory { height: clamp(230px, 36vw, 330px); margin-top: 28px; }
}
@media (max-width: 480px) {
  .solution-factory { height: 210px; margin-inline: -24px; width: calc(100% + 48px); }
}

.solution-factory-wrap { position: relative; }
/* Follow one crate through the four steps. */
#solution .solution-parts h3, #solution .solution-parts p { color: #666; transition: color 650ms ease; }
#solution .solution-parts .is-factory-active h3,
#solution .solution-parts .is-factory-active p { color: #fff; }
@media (prefers-reduced-motion: reduce) {
  #solution .solution-parts h3, #solution .solution-parts p { color: #fff; transition: none; }
}

/* Keep scroll-variable invalidation inside its own panel. */
.hero { --rest: calc(1 - var(--p)); }

/* Shaded dot hands occupy the hero's reserved illustration half. */
/* Shifted right of centre so the copy gets room to breathe, and the box runs
   31px past the content inset because the hands' dots stop about that far
   inside it. That lands the visible right edge of the hands on the same inset
   as the headline's left edge. */
.hero-art { overflow:hidden; position:absolute; left:calc(52% + 31px); right:calc(var(--hero-content-inset) - 31px); top:22%; bottom:18%; pointer-events:none; will-change:transform; }
.hero-hands-canvas { display:block; width:100%; height:100%; opacity:0; transition:none; }
.hero-art.is-ready .hero-hands-canvas { opacity:1; }
.hero-hands-fallback { display:none; position:absolute; inset:0; mask-image:radial-gradient(circle,#000 1.6px,transparent 1.9px); mask-size:4px 4px; }
.hero-hands-fallback img { position:absolute; width:144%; max-width:none; left:-22%; top:12%; }
.hero-art-fallback .hero-hands-fallback { display:block; }
.hero-art-fallback { mask-image:linear-gradient(90deg,transparent,#000 23%,#000 77%,transparent); }
@media (max-width:900px) {
  .hero-panel { align-items:flex-start; padding-top:calc(var(--header-h) + 64px); }
  .hero-inner { width:100%; max-width:640px; transform:none; }
  .hero-art { left:var(--hero-content-inset); right:var(--hero-content-inset); top:48%; bottom:5%; }
  .hero-panel h1 { font-size:clamp(34px,5.8vw,54px); }
  .hero-blurb { max-width:540px; }
}
@media (max-width:620px) {
  .hero-panel { --hero-content-inset:28px; padding:calc(var(--header-h) + 32px) var(--hero-content-inset) 0; min-height:760px; height:100svh; }
  .hero { height:calc(max(760px,100svh) + 220px); }
  .hero-panel h1 { font-size:34px; line-height:1.1; }
  .hero-blurb { font-size:16px; line-height:1.55; margin-top:18px; }
  .hero-cta { margin-top:20px; padding:11px 24px; }
  .hero-art { top:48%; bottom:6%; left:var(--hero-content-inset); right:var(--hero-content-inset); }
  .yc-badge { bottom:22px; }
}
@media (prefers-reduced-motion:reduce) { .hero-hands-canvas { transition:none; } }
.hero-hands-fallback img:first-child { transform:translateY(-50%); top:49%; }

@media (prefers-reduced-motion:reduce) {
  .hero { height:auto; }
  .hero-panel { position:relative; min-height:100svh; }
}

/* Reveal content once on entry, without moving its layout or dot lattice.
   The transition belongs on the revealed state, not the base one. On the base
   rule it also animated the initial hide, so every element faded out for 1.8s
   before it could fade in. */
.scroll-reveal { opacity:0; }
.scroll-reveal.has-entered, .scroll-reveal:focus-within { opacity:1; transition:opacity 1800ms ease-in-out var(--reveal-delay,0ms); }
.scroll-reveal:focus-within { transition:none; }
@media (prefers-reduced-motion:reduce) {
  .scroll-reveal { opacity:1; transition:none; }
  .factory-art-layer canvas { transition:none !important; }
}

/* Slightly smaller factory geometry, still sampled on the background lattice. */
.solution-factory { width:88%; margin-inline:auto; height:clamp(300px,29vw,388px); }
#solution .solution-parts { width:88%; margin-inline:auto; }
@media(max-width:900px) { .solution-factory { height:clamp(202px,32vw,290px); } }
@media(max-width:480px) { .solution-factory { width:88%; margin-inline:auto; height:186px; } }
.dot-build-pending { mask-image:linear-gradient(transparent,transparent); }
@media(prefers-reduced-motion:reduce) { .dot-build-pending { mask-image:none !important; } }
