/* ==========================================================================
   REINFORCE CREATIVE / Design System
   Red / White / Cream. Red is reserved for action. Nothing else is red.
   Mobile-first. No framework. No build step.
   ========================================================================== */

/* ---------- Fonts, self-hosted ----------
   Not loaded from Google. The site owns its typefaces, so it renders
   identically offline, on a locked-down network, and the first time a
   visitor lands, with no flash of fallback text. 132kb total. */
@font-face{
  font-family:'Space Grotesk'; font-style:normal; font-weight:500; font-display:swap;
  src:url('../fonts/space-grotesk-latin-500-normal.woff2') format('woff2');
}
@font-face{
  font-family:'Space Grotesk'; font-style:normal; font-weight:700; font-display:swap;
  src:url('../fonts/space-grotesk-latin-700-normal.woff2') format('woff2');
}
@font-face{
  font-family:'Inter'; font-style:normal; font-weight:400; font-display:swap;
  src:url('../fonts/inter-latin-400-normal.woff2') format('woff2');
}
@font-face{
  font-family:'Inter'; font-style:normal; font-weight:500; font-display:swap;
  src:url('../fonts/inter-latin-500-normal.woff2') format('woff2');
}
@font-face{
  font-family:'Inter'; font-style:normal; font-weight:600; font-display:swap;
  src:url('../fonts/inter-latin-600-normal.woff2') format('woff2');
}
@font-face{
  font-family:'Inter'; font-style:normal; font-weight:700; font-display:swap;
  src:url('../fonts/inter-latin-700-normal.woff2') format('woff2');
}

/* ---------- Tokens ---------- */
:root{
  /* Brand */
  --red:        #D21F26;
  --red-bright: #E8352C;
  --red-deep:   #A8161C;
  --red-wash:   #FCEEEC;

  --ink:        #141110;
  --ink-soft:   #2A2320;
  --ink-line:   #3A322E;

  --cream:      #F7F1E4;
  --cream-lift: #FDF9F0;
  --cream-edge: #E9DFCB;
  --white:      #FFFFFF;

  --body:       #574E48;
  --muted:      #756A61;

  /* Type */
  --font-display: 'Space Grotesk','Archivo','Helvetica Neue',Helvetica,Arial,sans-serif;
  --font-body:    'Inter','Helvetica Neue',Helvetica,Arial,sans-serif;
  --font-mono:    ui-monospace,'SF Mono',Menlo,Consolas,monospace;

  /* Space */
  --gut: 20px;
  --max: 1180px;
  --sec: 72px;

  /* Effects */
  --r:    14px;
  --r-lg: 22px;
  --shadow:    0 1px 2px rgba(20,17,16,.05), 0 8px 24px -12px rgba(20,17,16,.16);
  --shadow-lg: 0 2px 4px rgba(20,17,16,.06), 0 30px 60px -30px rgba(20,17,16,.30);
  --ease: cubic-bezier(.22,.61,.36,1);

  /* Layout */
  --bar-h: 62px;
}

@media (min-width:768px){ :root{ --gut:32px; --sec:104px; --bar-h:72px; } }
@media (min-width:1100px){ :root{ --sec:128px; } }

/* ---------- Reset ---------- */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
@media (prefers-reduced-motion:reduce){ html{ scroll-behavior:auto; } }

body{
  margin:0;
  background:var(--cream);
  color:var(--ink);
  font-family:var(--font-body);
  font-size:17px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  /* iOS Safari turns the body into a scroll container when this is hidden,
     which breaks momentum scrolling and the sticky header with it. clip
     contains the same overflow without creating a scroller. hidden first,
     as the fallback for anything that does not understand clip. */
  overflow-x:hidden;
  overflow-x:clip;
}
img,svg,video{ max-width:100%; display:block; }
a{ color:inherit; }
button,input,select,textarea{ font:inherit; color:inherit; }
button{ cursor:pointer; }

/* ---------- Type ---------- */
h1,h2,h3,h4{
  font-family:var(--font-display);
  font-weight:700;
  line-height:1.04;
  letter-spacing:-.03em;
  margin:0 0 .5em;
  text-wrap:balance;
}
h1{ font-size:clamp(2.35rem,8.5vw,4.6rem); }
h2{ font-size:clamp(1.9rem,5.6vw,3.1rem); }
h3{ font-size:clamp(1.2rem,3vw,1.5rem); letter-spacing:-.02em; }
h4{ font-size:1.05rem; letter-spacing:-.01em; }
p{ margin:0 0 1.1em; }
p:last-child{ margin-bottom:0; }

.lede{ font-size:clamp(1.06rem,2.6vw,1.3rem); line-height:1.55; color:var(--body); max-width:60ch; }
.small{ font-size:.9rem; }
.tiny{ font-size:.8rem; }

.eyebrow{
  font-family:var(--font-display);
  font-size:.72rem; font-weight:700;
  letter-spacing:.16em; text-transform:uppercase;
  /* --red on cream measures 4.45 against the 4.5 floor for small text. This
     is the same hue a shade deeper, used only for small uppercase labels. */
  color:#B31B21; margin:0 0 14px;
  display:flex; align-items:center; gap:9px; flex-wrap:wrap;
}
.eyebrow::before{
  content:""; width:22px; height:2px; background:var(--red); flex:none;
}
.eyebrow--plain::before{ display:none; }

/* Red is meaning, not decoration */
.hl{ color:var(--red); }
mark.hl{ background:none; color:var(--red); }

/* ---------- Layout ---------- */
.wrap{ width:100%; max-width:var(--max); margin-inline:auto; padding-inline:var(--gut); }
.wrap--narrow{ max-width:820px; }
.section{ padding-block:var(--sec); }
.section--tight{ padding-block:calc(var(--sec) * .62); }

/* The section head is deliberately narrow, which leaves the right half of a
   wide screen empty. That is the right call: a 44ch measure is readable and
   a full width paragraph is not. But it only works if the left side is strong
   enough to hold the eye on its own, and it was not. It read as a page that
   had run out of things to say.

   So the whitespace stays and the left gets weight: a red rule down the side,
   a bigger heading, and a lede with real contrast. */
.sec-head{
  /* 46ch used to be on the whole block, which is a sensible measure for a
     paragraph and a straitjacket for a 56px heading: "Four phases. You know
     the date before you pay the deposit." came out four lines tall. The
     heading gets room, the prose keeps its measure below. */
  max-width:54rem; margin-bottom:44px;
  position:relative; padding-left:clamp(18px,2.4vw,30px);
}
.sec-head::before{
  content:""; position:absolute; left:0; top:6px; bottom:6px; width:3px;
  border-radius:3px;
  background:linear-gradient(180deg, var(--red) 0%, var(--red) 38%, transparent 100%);
}
.sec-head h2{
  font-size:clamp(2.05rem,5.9vw,3.5rem);
  letter-spacing:-.035em;
}
.sec-head .lede{
  font-size:clamp(1.05rem,2.3vw,1.22rem);
  color:var(--body);
}
.sec-head p{ color:var(--body); max-width:48ch; }
.sec-head--center p{ margin-inline:auto; }

/* Centred heads have no left edge to hang a rule on, so they get the rule
   above instead of beside. */
.sec-head--center{
  margin-inline:auto; text-align:center; padding-left:0;
}
.sec-head--center::before{
  left:50%; top:-22px; bottom:auto; width:54px; height:3px;
  transform:translateX(-50%);
  background:var(--red);
}
.sec-head--center .eyebrow{ justify-content:center; }

/* Surfaces.
   --muted is tuned for cream. On dark grounds the same value drops under
   4.5:1, so the token is rebound per surface instead of patching each rule. */
/* --muted is tuned for cream and drops under 4.5:1 on a dark ground, so it
   is rebound per surface rather than patched at each rule. --red-bright has
   exactly the same problem: it measures 4.45 on ink for small text. Rebinding
   it here fixes every eyebrow, hero point and accent span at once, instead of
   chasing them one selector at a time. */
.bg-ink, .hero, .page-hero, .site-footer, .section--dark, .cta-band{
  --muted:#9C9187;
  --red-bright:#F4564D;
}

.bg-ink{ background:var(--ink); color:var(--cream-lift); }
.bg-ink h1,.bg-ink h2,.bg-ink h3,.bg-ink h4{ color:var(--cream-lift); }
.bg-ink p, .bg-ink .lede{ color:#BCB1A6; }
/* The eyebrow red is tuned for cream. On every dark ground it needs the
   brighter one, and .page-hero was never in this list, so deepening the red
   for small-text contrast on light made it worse on dark. */
.bg-ink .eyebrow, .hero .eyebrow, .page-hero .eyebrow, .section--dark .eyebrow,
.cta-band .eyebrow, .site-footer .eyebrow{ color:var(--red-bright); }
.bg-ink .eyebrow::before, .hero .eyebrow::before, .page-hero .eyebrow::before,
.section--dark .eyebrow::before, .cta-band .eyebrow::before{ background:var(--red-bright); }
.bg-white{ background:var(--white); }
.bg-lift{ background:var(--cream-lift); }

/* The two lists on the included / not included block. Same type size on both
   sides on purpose: an exclusion set in small grey type is a disclaimer, and
   a disclaimer is what people feel misled by later. */
.tick-list, .cross-list{ list-style:none; margin:16px 0 0; padding:0; display:grid; gap:11px; }
.tick-list li, .cross-list li{
  position:relative; padding-left:30px; font-size:.95rem; line-height:1.5;
  color:var(--body);
}
.tick-list li::before, .cross-list li::before{
  position:absolute; left:0; top:1px;
  width:19px; height:19px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  font-size:.7rem; font-weight:900; font-family:var(--font-display);
}
.tick-list li::before{
  content:"\2713"; background:rgba(210,31,38,.12); color:var(--red);
}
.cross-list li::before{
  content:"\00D7"; background:rgba(20,17,16,.07); color:var(--body);
  font-size:.85rem;
}

.rule{ height:1px; background:var(--cream-edge); border:0; margin:0; }
.bg-ink .rule{ background:var(--ink-line); }

/* ---------- Buttons ---------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:9px;
  font-family:var(--font-display); font-weight:700; font-size:1rem;
  letter-spacing:-.01em; text-decoration:none;
  padding:16px 26px; border-radius:999px; border:2px solid transparent;
  transition:transform .18s var(--ease), background .18s var(--ease),
             color .18s var(--ease), border-color .18s var(--ease),
             box-shadow .18s var(--ease);
  line-height:1; white-space:nowrap;
}
.btn:active{ transform:translateY(1px); }
.btn svg{ flex:none; }

.btn--primary{ background:var(--red); color:var(--white); box-shadow:0 10px 24px -12px rgba(210,31,38,.9); }
.btn--primary:hover{ background:var(--red-bright); box-shadow:0 16px 30px -14px rgba(210,31,38,1); }

.btn--ink{ background:var(--ink); color:var(--cream-lift); }
.btn--ink:hover{ background:var(--ink-soft); }

.btn--ghost{ background:transparent; color:var(--ink); border-color:rgba(20,17,16,.22); }
.btn--ghost:hover{ border-color:var(--ink); background:rgba(20,17,16,.04); }
/* A ghost button only had its light treatment inside .bg-ink, so on the hero
   and inside any dark card it rendered dark text on a dark ground and was
   effectively invisible. That button is the phone number, which is second in
   the whole priority list. Every dark surface gets the light version. */
.bg-ink .btn--ghost, .hero .btn--ghost, .builder-card .btn--ghost,
/* This class was used on the demo section and never defined, so the section
   stayed cream while its heading carried a hardcoded near-white. White text
   on cream, invisible, shipped, and spotted by Grant rather than by me. */
.section--dark{ background:var(--ink); color:var(--cream-lift); --muted:#9C9187; }
.section--dark h1, .section--dark h2, .section--dark h3, .section--dark h4{ color:var(--cream-lift); }
.section--dark p, .section--dark .lede{ color:#BCB1A6; }
.section--dark .eyebrow{ color:var(--red-bright); }
.section--dark .eyebrow::before{ background:var(--red-bright); }
.section--dark .sec-head::before{ background:linear-gradient(180deg,var(--red-bright) 0%,var(--red-bright) 38%,transparent 100%); }

.section--dark .btn--ghost, .cta-band .btn--ghost, .page-hero .btn--ghost{
  color:var(--cream-lift); border-color:rgba(253,249,240,.45);
}
.bg-ink .btn--ghost:hover, .hero .btn--ghost:hover, .builder-card .btn--ghost:hover,
.section--dark .btn--ghost:hover, .cta-band .btn--ghost:hover, .page-hero .btn--ghost:hover{
  border-color:var(--cream-lift); background:rgba(253,249,240,.10);
}

.btn--light{ background:var(--cream-lift); color:var(--ink); }
.btn--light:hover{ background:var(--white); }

.btn--lg{ padding:19px 34px; font-size:1.08rem; }
.btn--sm{ padding:11px 18px; font-size:.88rem; }
/* 36px is comfortable with a mouse and short of the 44px thumb minimum. On a
   touch screen the small button gets the height without the desktop header
   growing to match. */
@media (max-width:899px){ .btn--sm{ min-height:44px; padding-block:13px; } }
.btn--block{ width:100%; }

.btn-row{ display:flex; gap:12px; flex-wrap:wrap; align-items:center; }

/* ---------- Header ---------- */
.topbar{
  background:var(--ink); color:#B9AEA3;
  font-size:.78rem; letter-spacing:.01em;
  padding:7px 0; display:none;
}
.topbar .wrap{ display:flex; justify-content:space-between; align-items:center; gap:20px; }
.topbar a{ text-decoration:none; color:var(--cream-lift); font-weight:600; }
.topbar a:hover{ color:var(--red-bright); }
.topbar-list{ display:flex; gap:22px; align-items:center; }
@media (min-width:900px){ .topbar{ display:block; } }

.site-header{
  position:sticky; top:0; z-index:60;
  background:rgba(247,241,228,.88);
  backdrop-filter:saturate(160%) blur(14px);
  -webkit-backdrop-filter:saturate(160%) blur(14px);
  border-bottom:1px solid var(--cream-edge);
}
.site-header.is-stuck{ box-shadow:0 10px 30px -22px rgba(20,17,16,.6); }
.nav{ height:var(--bar-h); display:flex; align-items:center; gap:16px; }
/* Mark plus real text. The wordmark used to live inside the logo SVG, and
   an SVG in an <img> cannot load the page's fonts, so REINFORCE rendered in
   a different typeface from every other word on the site, picked by whatever
   the machine had. As HTML it is Space Grotesk, like the headings. */
.brand{ display:flex; align-items:center; gap:9px; text-decoration:none; margin-right:auto; }
.brand img{ height:26px; width:auto; display:block; }
.brand-word{ display:block; line-height:1; }
.brand-word .bn{
  display:block; font-family:var(--font-display); font-weight:700;
  font-size:1rem; letter-spacing:-.01em; color:var(--ink);
}
.brand-word .bc{
  display:block; font-family:var(--font-display); font-weight:600;
  font-size:.42rem; letter-spacing:.34em; color:var(--red); margin-top:3px;
}
.brand--light .bn{ color:var(--cream-lift); }
.brand--light .bc{ color:var(--red-bright); }
@media (min-width:768px){
  .brand img{ height:30px; }
  .brand-word .bn{ font-size:1.12rem; }
  .brand-word .bc{ font-size:.46rem; }
}

.nav-links{ display:none; gap:26px; align-items:center; }
.nav-links a{
  text-decoration:none; font-weight:600; font-size:.94rem; color:var(--ink-soft);
  position:relative; padding:6px 0;
}
.nav-links a::after{
  content:""; position:absolute; left:0; right:100%; bottom:0; height:2px;
  background:var(--red); transition:right .25s var(--ease);
}
.nav-links a:hover::after, .nav-links a[aria-current="page"]::after{ right:0; }
.nav-links a[aria-current="page"]{ color:var(--ink); }
.nav-cta{ display:none; }
@media (min-width:900px){ .nav-links{ display:flex; } .nav-cta{ display:inline-flex; } }

.nav-phone{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  text-decoration:none;
  font-family:var(--font-display); font-weight:700; font-size:.95rem; color:var(--ink);
  /* On a phone the label is hidden and only the icon remains, which left a
     16x16 tap target on the second most important control on the site. The
     minimums below are what make it hittable with a thumb. */
  min-height:44px; min-width:44px;
}
@media (max-width:899px){ .nav-phone span{ display:none; } }

.burger{
  display:inline-flex; align-items:center; justify-content:center;
  width:44px; height:44px; border:1px solid var(--cream-edge);
  background:var(--white); border-radius:11px; padding:0;
}
.burger span{ display:block; width:17px; height:2px; background:var(--ink); position:relative; transition:background .2s var(--ease), transform .2s var(--ease); }
.burger span::before,.burger span::after{
  content:""; position:absolute; left:0; width:17px; height:2px; background:var(--ink); transition:top .2s var(--ease), transform .2s var(--ease);
}
.burger span::before{ top:-6px; } .burger span::after{ top:6px; }
.burger[aria-expanded="true"] span{ background:transparent; }
.burger[aria-expanded="true"] span::before{ top:0; transform:rotate(45deg); }
.burger[aria-expanded="true"] span::after{ top:0; transform:rotate(-45deg); }
@media (min-width:900px){ .burger{ display:none; } }

.mobile-menu{
  position:fixed; inset:var(--bar-h) 0 0; z-index:55;
  background:var(--cream); padding:22px var(--gut) 40px;
  display:flex; flex-direction:column; gap:4px;
  transform:translateY(-8px); opacity:0; pointer-events:none;
  transition:opacity .2s var(--ease), transform .2s var(--ease);
  overflow-y:auto;
}
.mobile-menu.is-open{ opacity:1; transform:none; pointer-events:auto; }
.mobile-menu a.m-link{
  text-decoration:none; font-family:var(--font-display); font-weight:700;
  font-size:1.5rem; letter-spacing:-.02em; padding:14px 0;
  border-bottom:1px solid var(--cream-edge); display:flex; justify-content:space-between; align-items:center;
}
.mobile-menu a.m-link::after{ content:"→"; color:var(--red); font-size:1.1rem; }
.mobile-menu .m-actions{ margin-top:24px; display:grid; gap:10px; }
@media (min-width:900px){ .mobile-menu{ display:none; } }

/* ---------- Sticky mobile action bar (call + quote, zero scroll) ---------- */
.actionbar{
  position:fixed; left:0; right:0; bottom:0; z-index:70;
  display:grid; grid-template-columns:1fr 1fr; gap:8px;
  padding:9px 12px calc(9px + env(safe-area-inset-bottom));
  background:rgba(253,249,240,.94);
  backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
  border-top:1px solid var(--cream-edge);
}
.actionbar .btn{ padding:15px 10px; font-size:.95rem; }
@media (min-width:900px){ .actionbar{ display:none; } }
@media (max-width:899px){ body{ padding-bottom:74px; } }

/* ---------- HERO: the live self-building demo ---------- */
.hero{
  /* clip, not hidden. The red bloom behind the builder card is inset past the
     hero's edges, so something has to contain it horizontally. `hidden` would
     also clip the trade menu when it drops open; `overflow-x:clip` contains
     the bleed while leaving the vertical axis genuinely visible. */
  position:relative;
  overflow-x:clip; overflow-y:visible;
  background:var(--ink); color:var(--cream-lift);
  /* Pulled up. The quote form is the point of this block, so the less dead
     space above the headline the more of the form clears the fold. The
     bottom stays generous so the section ends on a deliberate edge rather
     than the next one creeping into view. */
  padding-block:clamp(26px,4.5vw,52px) clamp(48px,7vw,80px);
  /* A hard break instead of a bleed. The dark hero stops, a line, then the
     next section starts. Nothing peeks. */
  border-bottom:1px solid rgba(253,249,240,.10);
}
/* The bloom and the grid both faded downward into whatever came next, which
   read as the next section revealing itself early. Contain them to the hero. */
.hero::before, .hero::after{ bottom:0; }

/* The builder card's red bloom is deliberately inset PAST the card's own
   edges, so whatever contains it has to clip horizontally. The hero always
   did. When the demo moved into its own section that section did not, and
   the bloom widened the document by 6px, which is a sideways scroll on every
   phone. Anything holding a .builder needs this. */
#demo{ overflow-x:clip; }
/* The demo has no left column of copy, so it is one centred card rather than
   the hero's two up grid. Without this the empty column leaves a dead gap
   above the card on a phone. */
/* Doubled up on purpose. The plain .hero-grid--demo selector has the same
   specificity as the .hero-grid rule inside the desktop media query below,
   and that one comes later in the file, so it won. The demo stayed a two
   column grid with its first column hidden, which left the card in a 370px
   slot: the skinny box. */
.hero-grid.hero-grid--demo{
  grid-template-columns:1fr; max-width:720px; margin-inline:auto;
}
.hero-grid.hero-grid.hero-grid--demo .builder-card{ max-width:none; }
@media (min-width:560px){
  .hero-grid.hero-grid--demo .b-fields{ grid-template-columns:1fr 1fr; }
}
.hero-grid--demo > div:first-child{ display:none; }
/* The work, behind the copy. Every site on this page's Recent Work section
   leads with a real photo of real finished work, and for a while this hero
   was the only one of the four that led with a flat gradient. For a web
   designer the finished work IS websites, so the backdrop is the three real
   ones, dimmed hard enough that the headline still wins. */
.hero-bg{
  position:absolute; inset:0; overflow:hidden; pointer-events:none;
  background-image:url('../images/hero-work.jpg?v=18d7500231');
  background-size:cover; background-position:right center;
  /* Texture, not content. At .30 the three screenshots were legible enough to
     compete with the headline and the ghost button was unreadable over them.
     Blurred and dropped to .12 they read as "there is real work behind this"
     without asking to be looked at. */
  /* blur(2px) left the collage legible enough that its own tile edges drew
     hard vertical and horizontal lines across the hero, which is the "split"
     look. Taken far enough out of focus it stops being three screenshots and
     becomes light and shadow, which is all it was ever meant to contribute.
     The mask now fades on both axes so no edge of the image meets an edge of
     the section. */
  opacity:.24;
  /* The blur and the desaturation are baked into the file by
     _build/shrink-hero-bg.mjs. They used to be computed here, and on a
     throttled phone that one declaration cost 2.6 seconds of first
     contentful paint: 3,340ms with it, 752ms without, nothing else changed.
     A full-bleed blur has to be rasterised before anything can paint, and
     the result was never more than texture at 14% opacity. Do not put a
     filter back on this element; regenerate the image instead. */
  /* The edge fade is baked into the file by _build/shrink-hero-bg.mjs.
     It used to be two gradients composited with mask-composite:intersect,
     which forces this element onto its own compositing layer that has to be
     rasterised before the page can paint. With the blur already baked out,
     the mask alone still cost 2.4 seconds of first contentful paint:
     3,216ms against 760ms without it. The layer sits at 14% opacity over a
     solid #141110 hero, so a pixel faded to #141110 and a pixel masked to
     transparent resolve to the same colour. Do not add a mask or a filter
     back here; regenerate the image instead. */
}
@media (max-width:899px){
  /* On a phone the copy fills the width, so the work sits low and faint
     rather than behind the headline. */
  .hero-bg{ opacity:.22; background-position:right top; }
}

.hero::before{
  content:""; position:absolute; inset:0;
  background:
    /* Vertical first, and it matters. The backdrop is a collage, so its own
       tile edges ran across the bottom of the hero as a bright horizontal
       band, which read as the section being split in two rather than as
       texture. Fading to solid ink over the last third ends the block on a
       clean edge against the cream below it. */
    linear-gradient(180deg, rgba(20,17,16,.35) 0%, rgba(20,17,16,0) 26%, rgba(20,17,16,.72) 74%, var(--ink) 100%),
    linear-gradient(90deg, var(--ink) 8%, rgba(20,17,16,.86) 40%, rgba(20,17,16,.58) 100%),
    radial-gradient(120% 90% at 78% 0%, rgba(210,31,38,.30), transparent 62%),
    radial-gradient(90% 70% at 4% 100%, rgba(232,53,44,.14), transparent 60%);
  pointer-events:none;
}
.hero::after{
  content:""; position:absolute; inset:0; opacity:.5; pointer-events:none;
  background-image:linear-gradient(rgba(253,249,240,.045) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(253,249,240,.045) 1px,transparent 1px);
  background-size:56px 56px;
  mask-image:radial-gradient(120% 100% at 50% 0%,#000,transparent 72%);
  -webkit-mask-image:radial-gradient(120% 100% at 50% 0%,#000,transparent 72%);
}
.hero .wrap{ position:relative; z-index:2; }

/* The headline is the loudest thing on the page. It gets the biggest type,
   the tightest leading, and a colour change on the clause that lands the
   punch, so the eye has somewhere to stop instead of reading four even lines. */
.hero h1{
  color:var(--cream-lift); max-width:16ch;
  font-size:clamp(2.3rem,7.4vw,4.05rem);
  line-height:.98; letter-spacing:-.038em;
  margin-bottom:.42em;
}
.hero h1 .hl{ color:var(--red-bright); }
.hero .lede{ color:#C3B8AC; max-width:46ch; font-size:clamp(1.02rem,2.2vw,1.16rem); }

/* The offer, under the headline. Three stacked rows with a hairline between
   them, so it reads as terms you can check rather than another paragraph. */
.offer-terms{ margin:26px 0 0; max-width:46ch; }
.offer-terms > div{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 14px;
  padding:11px 0; border-top:1px solid rgba(253,249,240,.13);
}
.offer-terms > div:last-child{ border-bottom:1px solid rgba(253,249,240,.13); }
.offer-terms dt{
  font-family:var(--font-display); font-weight:700;
  font-size:clamp(1rem,2.2vw,1.12rem); color:#FDF9F0;
  letter-spacing:-.02em; flex:none;
}
.offer-terms dd{ margin:0; font-size:.92rem; color:#C3B8AC; }

/* Two columns on desktop so the demo is never below the fold */
/* Top aligned, not centred. The card is shorter than the copy column, so
   centring dropped it 80px below the headline and it read as sitting low
   rather than beside it. */
.hero-grid{ display:grid; gap:38px; align-items:start; }
@media (min-width:1000px){
  .hero-grid{ grid-template-columns:1.04fr .96fr; gap:48px; }
  .hero-grid .builder-card{ max-width:none; }
}

/* ---------- Trade combobox ----------
   A long list stays simple if you can type at it. Grouped when idle,
   ranked when searching, with alternate names under each option so people
   recognise their own words. Inherits the surface it sits on. */
.combo{ position:relative; }
.combo-input{ padding-right:42px !important; }
.combo-toggle{
  position:absolute; right:6px; top:6px; bottom:6px; width:34px;
  display:flex; align-items:center; justify-content:center;
  background:none; border:0; padding:0; color:var(--muted);
  border-radius:8px; transition:transform .2s var(--ease), color .2s var(--ease);
}
.combo-toggle:hover{ color:var(--ink); }
.combo.is-open .combo-toggle{ transform:rotate(180deg); }
.combo.has-value .combo-input{ font-weight:600; }

.combo-panel{
  position:absolute; z-index:40; left:0; right:0; top:calc(100% + 6px);
  /* .combo--up is set by JS when the field is near the bottom of the screen */
  max-height:320px; overflow-y:auto; overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  background:var(--white); border:1px solid var(--cream-edge);
  border-radius:14px; box-shadow:var(--shadow-lg);
  padding:6px;
}
.combo-head{
  font-family:var(--font-mono); font-size:.64rem; letter-spacing:.12em;
  text-transform:uppercase; color:var(--muted);
  padding:12px 12px 6px; position:sticky; top:-6px;
  background:var(--white);
}
.combo-opt{
  padding:9px 12px; border-radius:9px; cursor:pointer;
  display:flex; flex-direction:column; gap:2px;
}
.combo-opt:hover,
.combo-opt.is-active{ background:var(--red-wash); }
.combo-opt .co-label{ font-weight:600; font-size:.95rem; color:var(--ink); line-height:1.25; }
.combo-opt.is-active .co-label{ color:var(--red); }
.combo-opt .co-alt,
.combo-opt .co-note{
  font-size:.76rem; color:var(--muted); line-height:1.35;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.combo-opt .co-note{ color:var(--red); white-space:normal; }
.combo-opt--alt{ border-top:1px solid var(--cream-edge); border-radius:0 0 9px 9px; margin-top:4px; padding-top:12px; }
.combo-empty{ padding:16px 12px; font-size:.88rem; color:var(--body); line-height:1.5; }

.combo-big{
  margin-top:10px; padding:12px 14px; border-radius:11px;
  background:var(--red-wash); border:1px solid var(--red);
  font-size:.88rem; line-height:1.45; color:var(--body);
}
.combo-big a{ color:var(--red); font-weight:700; }
.builder-card .combo-big,
.hero .form-card .combo-big{ background:rgba(232,53,44,.14); color:#CBC0B4; }
.builder-card .combo-big a,
.hero .form-card .combo-big a{ color:var(--red-bright); }

.combo-other{ margin-top:10px; }
.combo-other input{
  width:100%; background:var(--white); border:1.5px solid var(--red);
  border-radius:11px; padding:14px 15px; font-size:1rem; min-width:0;
}
.combo-other input:focus{ outline:none; box-shadow:0 0 0 3px var(--red-wash); }

/* On the dark hero surfaces */
.builder-card .combo-toggle,
.hero .form-card .combo-toggle{ color:#8A7F76; }
.builder-card .combo-toggle:hover,
.hero .form-card .combo-toggle:hover{ color:var(--cream-lift); }
.builder-card .combo-panel,
.hero .form-card .combo-panel{
  background:#1C1613; border-color:#453B35;
  box-shadow:0 24px 60px -24px rgba(0,0,0,.95);
}
.builder-card .combo-head,
.hero .form-card .combo-head{ background:#1C1613; color:#8A7F76; }
.builder-card .combo-opt .co-label,
.hero .form-card .combo-opt .co-label{ color:var(--cream-lift); }
.builder-card .combo-opt:hover,
.builder-card .combo-opt.is-active,
.hero .form-card .combo-opt:hover,
.hero .form-card .combo-opt.is-active{ background:rgba(232,53,44,.18); }
.builder-card .combo-opt.is-active .co-label,
.hero .form-card .combo-opt.is-active .co-label{ color:var(--red-bright); }
.builder-card .combo-opt .co-note,
.hero .form-card .combo-opt .co-note{ color:var(--red-bright); }
.builder-card .combo-opt--alt,
.hero .form-card .combo-opt--alt{ border-top-color:#453B35; }
.builder-card .combo-empty,
.hero .form-card .combo-empty{ color:#BCB1A6; }
.builder-card .combo-other input,
.hero .form-card .combo-other input{
  background:rgba(253,249,240,.07); border-color:var(--red-bright); color:var(--cream-lift);
}
.builder-card .combo-other input::placeholder,
.hero .form-card .combo-other input::placeholder{ color:#8A7F76; }

.combo--up .combo-panel{ top:auto; bottom:calc(100% + 6px); }
@media (max-width:520px){ .combo-panel{ max-height:262px; } }

/* ---------- Selling points ----------
   Stacked, bold, red, above the headline. The bullet is the K's own chevron,
   so the mark repeats down the page instead of a generic dot. */
.hero-points{
  list-style:none; margin:0 0 18px; padding:0;
  display:flex; flex-direction:row; flex-wrap:wrap;
  gap:8px 24px; align-items:center;
}
.hero-points li{
  display:flex; align-items:center; gap:11px;
  font-family:var(--font-display); font-weight:700;
  font-size:clamp(1rem,2.3vw,1.14rem);
  letter-spacing:-.015em; line-height:1.25;
  color:var(--red-bright);
}
.hero-points li::before{
  content:""; flex:none; width:9px; height:12px;
  background:currentColor;
  clip-path:polygon(0 0, 45% 0, 100% 50%, 45% 100%, 0 100%, 55% 50%);
}
@media (max-width:520px){
  /* Still a row, just tighter. Wraps to two lines on a narrow phone,
     which reads as a row rather than a stacked list. */
  .hero-points{ gap:7px 16px; margin-bottom:18px; font-size:.94rem; }
  .hero-points li{ font-size:.95rem; }
}

/* Service area: set as type, not as a row of tags */
.states{
  font-family:var(--font-display); font-weight:700;
  font-size:clamp(1.08rem,2.7vw,1.4rem); letter-spacing:-.025em;
  line-height:1.5; color:var(--ink); margin:0 0 18px; max-width:none;
}
.states i{ color:var(--red); font-style:normal; padding:0 .18em; }

/* --- Builder input card ---
   Made to pop WITHOUT competing with the H1. Every type size in here stays
   put; the attention comes from light and colour around the card, not from
   making anything inside it bigger. The headline is still the biggest thing
   on the screen; this just reads as the lit object you're meant to touch. */
/* No top margin: the hero grid's gap handles the spacing, and doubling
   them left the card floating too far from the headline on a phone. */
.builder{ margin-top:0; position:relative; }

/* Red bloom behind the card. Sits under it, never over the headline. */
.builder::before{
  content:""; position:absolute; z-index:0; pointer-events:none;
  inset:-34px -26px -44px;
  background:radial-gradient(58% 58% at 50% 48%, rgba(232,53,44,.34), transparent 72%);
  filter:blur(26px);
}

/* Smoked glass, not a white slab. A large cream rectangle on a near-black
   hero is the highest-contrast object on the page, and area beats type, so
   it stole the first look from the headline. Dark keeps it part of the hero
   and leaves the red button as the single brightest thing on the screen. */
.builder-card{
  position:relative; z-index:1;
  /* Opaque enough to sit cleanly on the work backdrop. At .72 the ghost
     button inside it was unreadable against a screenshot behind. */
  background:rgba(26,20,18,.93);
  backdrop-filter:blur(18px) saturate(140%);
  -webkit-backdrop-filter:blur(14px) saturate(140%);
  color:var(--cream-lift);
  border-radius:var(--r-lg); padding:24px 20px 20px;
  max-width:640px;
  box-shadow:
    0 0 0 1px rgba(232,53,44,.34),
    0 0 0 7px rgba(232,53,44,.06),
    0 30px 70px -34px rgba(0,0,0,.9),
    0 34px 70px -30px rgba(232,53,44,.34);
  animation:cardIn .6s var(--ease) .1s both;
}
@media (min-width:768px){ .builder-card{ padding:30px 26px 26px; } }

/* Any form card sitting on a dark hero gets the same smoked-glass surface.
   Form cards on cream sections (quote, contact, the homepage offer block)
   stay light, because they're on a light ground, so there's no slab to create. */
.hero .form-card{
  background:rgba(26,20,18,.72);
  backdrop-filter:blur(14px) saturate(140%);
  -webkit-backdrop-filter:blur(14px) saturate(140%);
  color:var(--cream-lift);
  border:1px solid rgba(232,53,44,.34);
  box-shadow:
    0 0 0 6px rgba(232,53,44,.05),
    0 30px 70px -34px rgba(0,0,0,.9),
    0 34px 70px -30px rgba(232,53,44,.28);
}
.hero .form-card .form-title{ color:var(--cream-lift); }
.hero .form-card .form-sub{ color:#9C9187; }
.hero .form-card .form-note{ color:#9C9187; }
.hero .form-card .hint{ color:#9C9187; }
.hero .form-card .checkrow{ color:#9C9187; }

/* Everything inside the card, recoloured for the dark surface */
.builder-card .b-label{ color:var(--cream-lift); }
.builder-card .b-sub{ color:#9C9187; }
.builder-card .field label,
.hero .form-card .field label{ color:#8A7F76; }
/* background-color, never the `background` shorthand: the shorthand resets
   background-repeat and position, which tiles the select's arrow across it. */
.builder-card .field input,
.builder-card .field select,
.hero .form-card .field input,
.hero .form-card .field select,
.hero .form-card .field textarea{
  background-color:rgba(253,249,240,.07);
  border-color:#453B35;
  color:var(--cream-lift);
}
.builder-card .field input::placeholder,
.hero .form-card .field input::placeholder,
.hero .form-card .field textarea::placeholder{ color:#8F8379; }
.builder-card .field select,
.hero .form-card .field select{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' stroke='%23A79B90' stroke-width='2' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 15px center;
}
.builder-card .field input:hover,
.builder-card .field select:hover,
.hero .form-card .field input:hover,
.hero .form-card .field select:hover,
.hero .form-card .field textarea:hover{ border-color:#5C504A; }
.builder-card .field input:focus,
.builder-card .field select:focus,
.hero .form-card .field input:focus,
.hero .form-card .field select:focus,
.hero .form-card .field textarea:focus{
  border-color:var(--red-bright);
  background-color:rgba(253,249,240,.11);
  box-shadow:0 0 0 3px rgba(232,53,44,.22);
}
/* The select's own option list is drawn by the OS, so force readable colours */
.builder-card .field select option,
.hero .form-card .field select option{ background:#1C1613; color:#FDF9F0; }
.builder-card .b-foot{ color:#9C9187; }

@keyframes cardIn{ from{ opacity:0; transform:translateY(16px); } to{ opacity:1; transform:none; } }

/* Corner flag: small, red, and the only new element on the card */
.b-flag{
  position:absolute; top:-12px; left:20px;
  display:inline-flex; align-items:center; gap:7px;
  background:var(--red); color:#fff;
  font-family:var(--font-display); font-weight:700; font-size:.68rem;
  letter-spacing:.11em; text-transform:uppercase;
  padding:6px 13px; border-radius:999px; white-space:nowrap;
  box-shadow:0 10px 22px -10px rgba(210,31,38,1);
}
.b-flag i{
  width:6px; height:6px; border-radius:50%; background:#fff; flex:none;
  animation:liveDot 2s ease-in-out infinite;
}
@keyframes liveDot{ 0%,100%{ opacity:1; } 50%{ opacity:.35; } }

.builder-card .b-label{
  font-family:var(--font-display); font-weight:700; font-size:1.02rem;
  letter-spacing:-.02em; margin:0 0 4px;
}
.builder-card .b-sub{ font-size:.86rem; color:var(--muted); margin:0 0 16px; }

/* One-time sheen across the submit button, then it stops and stays quiet */
.btn--sheen{ position:relative; overflow:hidden; isolation:isolate; }
.btn--sheen::after{
  content:""; position:absolute; z-index:-1; top:-10%; bottom:-10%;
  left:-70%; width:42%;
  background:linear-gradient(100deg, transparent, rgba(255,255,255,.42), transparent);
  transform:skewX(-18deg);
  animation:sheen 3.6s var(--ease) 1.4s 3;
}
@keyframes sheen{ 0%{ left:-70%; } 52%,100%{ left:140%; } }

/* If nobody has touched the card after a few seconds, nudge it once */
.builder-card.nudge{ animation:nudge 1.5s var(--ease) 2; }
@keyframes nudge{
  0%,100%{
    box-shadow:0 0 0 1px rgba(232,53,44,.34), 0 0 0 7px rgba(232,53,44,.06),
               0 30px 70px -34px rgba(0,0,0,.9), 0 34px 70px -30px rgba(232,53,44,.34);
  }
  50%{
    box-shadow:0 0 0 1.5px rgba(232,53,44,.9), 0 0 0 12px rgba(232,53,44,.13),
               0 30px 70px -34px rgba(0,0,0,.9), 0 34px 80px -28px rgba(232,53,44,.7);
  }
}

@media (prefers-reduced-motion:reduce){
  .builder-card, .b-flag i, .btn--sheen::after{ animation:none; }
  .builder-card.nudge{ animation:none; }
}

.b-fields{ display:grid; gap:10px; }
@media (min-width:600px){ .b-fields{ grid-template-columns:1fr 1fr; } }

.field{ display:flex; flex-direction:column; gap:6px; }
.field label{ font-size:.78rem; font-weight:700; letter-spacing:.03em; text-transform:uppercase; color:var(--muted); }
.field input,.field select,.field textarea{
  width:100%; background:var(--white); border:1.5px solid var(--cream-edge);
  border-radius:11px; padding:14px 15px; font-size:1rem;
  transition:border-color .15s var(--ease), box-shadow .15s var(--ease);
  -webkit-appearance:none; appearance:none;
}
.field select{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' stroke='%238A7F76' stroke-width='2' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 15px center; padding-right:40px;
}
.field textarea{ min-height:118px; resize:vertical; line-height:1.5; }
.field input:focus,.field select:focus,.field textarea:focus{
  outline:none; border-color:var(--red); box-shadow:0 0 0 3px var(--red-wash);
}
.field--full{ grid-column:1/-1; }
.field .hint{ font-size:.76rem; color:var(--muted); font-weight:400; text-transform:none; letter-spacing:0; }

.builder-card .btn{ margin-top:14px; }
/* Three short terms under the button. Left aligned at a 14px gap they ran
   together into one line of grey and wrapped awkwardly, so they are centred
   under the card, given room to breathe, and separated by a rule that appears
   only between them. */
.b-foot{
  font-size:.78rem; color:var(--muted); margin-top:18px;
  padding-top:15px; border-top:1px solid rgba(253,249,240,.12);
  display:flex; flex-wrap:wrap; justify-content:center;
  gap:9px 22px; text-align:center;
}
.b-foot span{ display:inline-flex; align-items:center; gap:6px; white-space:nowrap; }
/* On a narrow phone they stack, and a centred stack with the dots aligned
   reads better than three ragged lines. */
@media (max-width:420px){
  .b-foot{ flex-direction:column; align-items:center; gap:7px; }
}

/* --- Build console (the 4-second "it's working" moment) --- */
.build-stage{ display:none; }
.build-stage.is-on{ display:block; }
.console{
  background:#0C0A09; border:1px solid var(--ink-line); border-radius:var(--r-lg);
  padding:22px; font-family:var(--font-mono); font-size:.82rem;
  max-width:640px; color:#8FE39B; min-height:190px;
  box-shadow:var(--shadow-lg);
}
.console .c-top{
  display:flex; gap:6px; margin-bottom:16px; align-items:center;
}
.console .c-top i{ width:10px; height:10px; border-radius:50%; background:#3A322E; display:block; }
.console .c-top i:first-child{ background:var(--red); }
.console .c-title{ margin-left:10px; color:#6B615A; font-size:.76rem; letter-spacing:.04em; }
.console p{ margin:0 0 7px; opacity:0; transform:translateY(4px); animation:lineIn .3s var(--ease) forwards; }
.console p .t{ color:#5C534C; margin-right:9px; }
.console p .ok{ color:var(--red-bright); }
@keyframes lineIn{ to{ opacity:1; transform:none; } }

.progress{ height:3px; background:var(--ink-line); border-radius:2px; overflow:hidden; margin-top:16px; }
.progress i{ display:block; height:100%; width:0; background:var(--red-bright); border-radius:2px; transition:width .3s linear; }

/* --- The reveal: their site, built --- */
.reveal-stage{ display:none; scroll-margin-top:calc(var(--bar-h) + 18px); }
.reveal-stage.is-on{ display:block; animation:revealUp .55s var(--ease) both; }
@keyframes revealUp{ from{ opacity:0; transform:translateY(22px); } to{ opacity:1; transform:none; } }

.reveal-head{ margin-bottom:20px; }
.reveal-head .k{
  display:inline-flex; align-items:center; gap:8px;
  font-family:var(--font-display); font-weight:700; font-size:.8rem;
  letter-spacing:.14em; text-transform:uppercase; color:var(--red-bright);
  margin-bottom:10px;
}
.reveal-head h2{ font-size:clamp(1.6rem,4.4vw,2.4rem); margin-bottom:8px; color:var(--cream-lift); }
.reveal-head p{ color:#B3A79B; font-size:.98rem; max-width:56ch; }

/* Device frame */
.mock-wrap{
  display:grid; gap:18px; align-items:start;
}
@media (min-width:980px){ .mock-wrap{ grid-template-columns:1fr 306px; gap:26px; } }
.mock-side{ display:grid; gap:18px; }

.mock{
  background:var(--white); border-radius:var(--r-lg); overflow:hidden;
  box-shadow:var(--shadow-lg); border:1px solid rgba(20,17,16,.08);
}
.mock-chrome{
  background:#EDE7DC; padding:9px 12px; display:flex; align-items:center; gap:7px;
  border-bottom:1px solid var(--cream-edge);
}
.mock-chrome i{ width:9px; height:9px; border-radius:50%; background:#C9BFB2; display:block; }
.mock-chrome .url{
  margin-left:8px; background:var(--white); border-radius:6px; padding:4px 11px;
  font-size:.7rem; color:var(--muted); font-family:var(--font-mono);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; flex:1;
}
.mock-body{ padding:0; }

.mock-nav{
  display:flex; align-items:center; justify-content:space-between;
  padding:13px 16px; border-bottom:1px solid rgba(20,17,16,.07);
}
.mock-nav .mn-brand{ font-family:var(--font-display); font-weight:700; font-size:.86rem; letter-spacing:-.02em; color:var(--ink); }
.mock-nav .mn-links{ display:none; gap:14px; font-size:.7rem; color:var(--muted); font-weight:600; }
@media (min-width:560px){ .mock-nav .mn-links{ display:flex; } }
.mock-nav .mn-cta{
  font-size:.68rem; font-weight:700; padding:7px 12px; border-radius:999px;
  background:var(--m-accent,#D21F26); color:#fff; white-space:nowrap;
}

.mock-hero{
  padding:26px 18px 24px; position:relative; overflow:hidden;
  background:linear-gradient(150deg, var(--m-dark,#1a1512) 0%, var(--m-dark2,#2a201b) 100%);
  color:#fff;
}
.mock-hero::after{
  content:""; position:absolute; inset:0;
  background:radial-gradient(80% 70% at 85% 10%, var(--m-glow,rgba(210,31,38,.42)), transparent 65%);
}
.mock-hero > *{ position:relative; z-index:1; }
.mock-hero .mh-eyebrow{
  font-size:.62rem; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  color:var(--m-accent-l,#FF7A6E); margin-bottom:9px;
}
.mock-hero h3{
  font-size:clamp(1.25rem,4.4vw,1.85rem); line-height:1.05; color:#fff; margin:0 0 9px;
  letter-spacing:-.03em;
}
.mock-hero .mh-sub{ font-size:.83rem; color:rgba(255,255,255,.75); margin:0 0 15px; max-width:38ch; line-height:1.45; }
.mock-hero .mh-btns{ display:flex; gap:8px; flex-wrap:wrap; }
.mock-hero .mh-btn{
  font-size:.76rem; font-weight:700; padding:11px 17px; border-radius:999px;
  background:var(--m-accent,#D21F26); color:#fff;
}
.mock-hero .mh-btn.alt{ background:rgba(255,255,255,.13); border:1px solid rgba(255,255,255,.28); }
.mock-hero .mh-trust{
  display:flex; gap:12px; flex-wrap:wrap; margin-top:15px;
  font-size:.66rem; color:rgba(255,255,255,.62);
}
.mock-hero .mh-trust span{ display:inline-flex; align-items:center; gap:4px; }

.mock-strip{
  display:grid; grid-template-columns:repeat(3,1fr); gap:1px;
  background:rgba(20,17,16,.08);
}
.mock-strip div{ background:var(--white); padding:14px 10px; text-align:center; }
.mock-strip .ms-n{ font-family:var(--font-display); font-weight:700; font-size:1.05rem; color:var(--m-accent,#D21F26); letter-spacing:-.02em; }
.mock-strip .ms-l{ font-size:.6rem; color:var(--muted); letter-spacing:.05em; text-transform:uppercase; margin-top:2px; }

.mock-svcs{ padding:18px; }
.mock-svcs .mt{ font-family:var(--font-display); font-weight:700; font-size:.92rem; margin:0 0 11px; letter-spacing:-.02em; }
.mock-svcs ul{ list-style:none; margin:0; padding:0; display:grid; gap:7px; }
@media (min-width:520px){ .mock-svcs ul{ grid-template-columns:1fr 1fr; } }
.mock-svcs li{
  display:flex; align-items:center; gap:8px; font-size:.79rem; color:var(--body);
  background:var(--cream-lift); border:1px solid var(--cream-edge);
  border-radius:9px; padding:10px 12px;
}
.mock-svcs li::before{
  content:""; width:6px; height:6px; border-radius:50%; background:var(--m-accent,#D21F26); flex:none;
}

.mock-quote{
  padding:18px; border-top:1px solid rgba(20,17,16,.07); background:var(--cream-lift);
}
.mock-quote .mt{ font-family:var(--font-display); font-weight:700; font-size:.92rem; margin:0 0 4px; letter-spacing:-.02em; }
.mock-quote .msub{ font-size:.74rem; color:var(--muted); margin:0 0 11px; }
.mock-quote .mq-row{ display:grid; gap:7px; grid-template-columns:1fr 1fr; margin-bottom:7px; }
.mock-quote .mq-in{
  background:var(--white); border:1px solid var(--cream-edge); border-radius:8px;
  padding:10px 11px; font-size:.74rem; color:#B4A99E;
}
.mock-quote .mq-btn{
  background:var(--m-accent,#D21F26); color:#fff; text-align:center;
  border-radius:8px; padding:11px; font-size:.78rem; font-weight:700;
}

/* Phone mock beside it */
.mock-phone{
  width:230px; margin:0 auto; background:var(--ink); border-radius:30px; padding:8px;
  box-shadow:var(--shadow-lg); border:1px solid var(--ink-line);
}
.mock-phone .mp-screen{
  background:var(--white); border-radius:23px; overflow:hidden; position:relative;
}
.mock-phone .mp-notch{
  position:absolute; top:0; left:50%; transform:translateX(-50%);
  width:78px; height:17px; background:var(--ink); border-radius:0 0 11px 11px; z-index:3;
}
.mock-phone .mock-hero{ padding:30px 14px 18px; }
.mock-phone .mock-hero h3{ font-size:1.05rem; }
.mock-phone .mock-hero .mh-sub{ font-size:.72rem; }
.mock-phone .mp-bar{
  display:grid; grid-template-columns:1fr 1fr; gap:6px; padding:9px;
  border-top:1px solid var(--cream-edge); background:var(--cream-lift);
}
.mock-phone .mp-bar div{
  text-align:center; padding:9px 4px; border-radius:7px; font-size:.68rem; font-weight:700;
}
.mock-phone .mp-bar .call{ background:var(--ink); color:#fff; }
.mock-phone .mp-bar .quote{ background:var(--m-accent,#D21F26); color:#fff; }
@media (max-width:979px){ .mock-phone{ display:none; } }

.reveal-note{
  margin-top:20px; padding:20px; border-radius:var(--r);
  background:rgba(253,249,240,.05); border:1px solid rgba(253,249,240,.14);
}
.reveal-note p{ margin:0 0 14px; color:#CBC0B4; font-size:.98rem; }
.reveal-note strong{ color:var(--cream-lift); }
.reveal-actions{ display:flex; gap:10px; flex-wrap:wrap; }
.linkish{
  background:none; border:0; padding:0; color:#9C9187; text-decoration:underline;
  text-underline-offset:3px; font-size:.88rem; font-weight:600;
}
.linkish:hover{ color:var(--cream-lift); }

/* ---------- Stat bar ---------- */
.statbar{ border-block:1px solid var(--cream-edge); background:var(--cream-lift); }
.statbar .wrap{ display:grid; gap:0; }
@media (min-width:768px){ .statbar .wrap{ grid-template-columns:repeat(3,1fr); } }
.stat{ padding:28px 0; border-bottom:1px solid var(--cream-edge); }
@media (min-width:768px){
  .stat{ padding:38px 28px; border-bottom:0; border-left:1px solid var(--cream-edge); }
  .stat:first-child{ border-left:0; padding-left:0; }
  .stat:last-child{ padding-right:0; }
}
.stat:last-child{ border-bottom:0; }
.stat .n{
  font-family:var(--font-display); font-weight:700;
  font-size:clamp(2.2rem,6vw,3.2rem); line-height:1; letter-spacing:-.04em;
  color:var(--red); margin-bottom:7px;
}
.stat .l{ font-size:.95rem; color:var(--body); max-width:30ch; }

/* ---------- Pipeline (CLICK → SALE) ---------- */
.pipe{ display:grid; gap:10px; margin-top:10px; }
@media (min-width:860px){ .pipe{ grid-template-columns:repeat(5,1fr); gap:12px; } }
.pipe-step{
  position:relative; background:var(--white); border:1px solid var(--cream-edge);
  border-radius:var(--r); padding:20px 18px;
  opacity:0; transform:translateY(14px);
  transition:opacity .5s var(--ease), transform .5s var(--ease), border-color .3s var(--ease);
}
.bg-ink .pipe-step{ background:rgba(253,249,240,.045); border-color:var(--ink-line); }
.pipe-step.in{ opacity:1; transform:none; }
/* These were the only numbers on the page set in a monospace face, which
   read as an accident next to everything else in the display font. */
.pipe-step .p-n{
  font-family:var(--font-display); font-weight:700; font-size:.82rem;
  color:var(--red); margin-bottom:9px; letter-spacing:.06em;
}
.pipe-step h4{ margin:0 0 5px; font-size:1rem; }
.pipe-step p{ font-size:.85rem; color:var(--body); margin:0; }
.bg-ink .pipe-step p{ color:#9C9187; }
.pipe-step::after{
  content:"→"; position:absolute; color:var(--red); font-weight:700;
  right:-13px; top:50%; transform:translateY(-50%); font-size:1.05rem;
  display:none;
}
@media (min-width:860px){
  .pipe-step:not(:last-child)::after{ display:block; }
}
.pipe-step--last{ border-color:var(--red); background:var(--red-wash); }
.bg-ink .pipe-step--last{ background:rgba(210,31,38,.14); border-color:var(--red); }
.pipe-step--last h4{ color:var(--red); }
.bg-ink .pipe-step--last h4{ color:var(--red-bright); }

.pipe-caption{
  margin-top:24px; font-family:var(--font-display); font-weight:700;
  font-size:clamp(1.05rem,2.6vw,1.35rem); letter-spacing:-.02em; max-width:46ch;
}
.pipe-caption .hl{ color:var(--red); }

/* ---------- Cards ---------- */
.grid{ display:grid; gap:14px; }
.grid-2{ grid-template-columns:1fr; }
.grid-3{ grid-template-columns:1fr; }
.grid-4{ grid-template-columns:1fr; }
@media (min-width:640px){ .grid-2,.grid-4{ grid-template-columns:1fr 1fr; } .grid-3{ grid-template-columns:1fr 1fr; } }
@media (min-width:960px){ .grid-3{ grid-template-columns:repeat(3,1fr); } .grid-4{ grid-template-columns:repeat(4,1fr); } }

.card{
  background:var(--white); border:1px solid var(--cream-edge); border-radius:var(--r);
  padding:24px; transition:transform .22s var(--ease), box-shadow .22s var(--ease), border-color .22s var(--ease);
}
.card h3,.card h4{ margin-bottom:8px; }
.card p{ color:var(--body); font-size:.95rem; margin:0; }
.card:hover{ transform:translateY(-3px); box-shadow:var(--shadow); border-color:#D9CDB6; }
.bg-ink .card{ background:rgba(253,249,240,.045); border-color:var(--ink-line); }
.bg-ink .card p{ color:#9C9187; }
.bg-ink .card:hover{ border-color:#5A4F49; }

.card-ico{
  width:42px; height:42px; border-radius:11px; background:var(--red-wash);
  display:flex; align-items:center; justify-content:center; margin-bottom:16px; color:var(--red);
}
.bg-ink .card-ico{ background:rgba(210,31,38,.18); color:var(--red-bright); }

.card--link{ text-decoration:none; display:block; }
.card--link .go{
  margin-top:14px; font-family:var(--font-display); font-weight:700; font-size:.88rem;
  color:var(--red); display:inline-flex; align-items:center; gap:6px;
}
.card--link:hover .go{ gap:10px; }
.card--link .go span{ transition:transform .2s var(--ease); }

/* Symptom card: the problem section */
.symptom{
  background:var(--white); border:1px solid var(--cream-edge);
  border-left:3px solid var(--red); border-radius:0 var(--r) var(--r) 0;
  padding:20px 22px;
}
.symptom h4{ margin:0 0 6px; }
.symptom p{ margin:0; font-size:.92rem; color:var(--body); }

/* Numbered steps */
.steps{ display:grid; gap:2px; background:var(--cream-edge); border-radius:var(--r); overflow:hidden; border:1px solid var(--cream-edge); }
/* Was hard coded to three columns, which left the fourth phase sitting alone
   beside a dead panel once How It Works went from three steps to four. Auto
   fit means it does the right thing at three or four without being told. */
@media (min-width:620px){ .steps{ grid-template-columns:repeat(2,1fr); } }
@media (min-width:1040px){ .steps{ grid-template-columns:repeat(auto-fit,minmax(230px,1fr)); } }
.step{ background:var(--white); padding:30px 26px; }
.step .s-n{
  font-family:var(--font-display); font-weight:700; font-size:2.4rem; line-height:1;
  color:var(--red); letter-spacing:-.05em; margin-bottom:14px;
}
.step h3{ margin-bottom:8px; }
.step p{ color:var(--body); font-size:.94rem; margin:0; }

/* ---------- Photo slots (labeled, drop-in) ---------- */
.photo{
  position:relative; background:var(--cream-lift); border:1px dashed #C9BFB2;
  border-radius:var(--r); overflow:hidden; aspect-ratio:4/3;
  display:flex; align-items:center; justify-content:center; text-align:center;
}
.photo img{ width:100%; height:100%; object-fit:cover; }
.photo--wide{ aspect-ratio:16/9; }
.photo--square{ aspect-ratio:1/1; }
.photo--tall{ aspect-ratio:3/4; }
.photo-slot{ padding:22px; }
.photo-slot .ps-tag{
  display:inline-block; font-family:var(--font-mono); font-size:.66rem; letter-spacing:.08em;
  text-transform:uppercase; background:var(--red); color:#fff;
  padding:4px 9px; border-radius:5px; margin-bottom:10px;
}
.photo-slot .ps-file{ font-family:var(--font-mono); font-size:.82rem; color:var(--ink); font-weight:600; margin:0 0 4px; word-break:break-all; }
.photo-slot .ps-dim{ font-size:.75rem; color:var(--muted); margin:0; }
.bg-ink .photo{ background:rgba(253,249,240,.04); border-color:#4A413B; }
.bg-ink .photo-slot .ps-file{ color:var(--cream-lift); }

/* ---------- Before / After ---------- */
.ba{ display:grid; gap:14px; }
@media (min-width:760px){ .ba{ grid-template-columns:1fr 1fr; gap:18px; align-items:start; } }
.ba-item .ba-tag{
  display:inline-flex; align-items:center; gap:7px;
  font-family:var(--font-display); font-weight:700; font-size:.76rem;
  letter-spacing:.12em; text-transform:uppercase; margin-bottom:10px;
}
.ba-item.before .ba-tag{ color:var(--muted); }
.ba-item.after .ba-tag{ color:var(--red); }
.ba-item .ba-note{ margin-top:12px; font-size:.9rem; color:var(--body); }

/* ---------- Testimonial ---------- */
.quote-card{
  background:var(--white); border:1px solid var(--cream-edge); border-radius:var(--r);
  padding:28px;
}
.quote-card blockquote{
  margin:0 0 18px; font-family:var(--font-display); font-weight:500;
  font-size:clamp(1.05rem,2.4vw,1.28rem); line-height:1.35; letter-spacing:-.02em;
}
.quote-card .qc-who{ display:flex; align-items:center; gap:12px; }
.quote-card .qc-av{
  width:40px; height:40px; border-radius:50%; background:var(--red-wash); color:var(--red);
  display:flex; align-items:center; justify-content:center; flex:none;
  font-family:var(--font-display); font-weight:700; font-size:.9rem;
}
.quote-card .qc-n{ font-weight:700; font-size:.92rem; }
.quote-card .qc-r{ font-size:.82rem; color:var(--muted); }
.placeholder-note{
  font-family:var(--font-mono); font-size:.68rem; color:var(--muted);
  background:var(--cream); border:1px dashed #C9BFB2; border-radius:6px;
  padding:6px 9px; display:inline-block; margin-top:14px;
}

/* ---------- FAQ ---------- */
.faq{ border-top:1px solid var(--cream-edge); }
.faq details{ border-bottom:1px solid var(--cream-edge); }
.faq summary{
  cursor:pointer; list-style:none; padding:22px 40px 22px 0; position:relative;
  font-family:var(--font-display); font-weight:700; font-size:clamp(1rem,2.4vw,1.15rem);
  letter-spacing:-.02em;
}
.faq summary::-webkit-details-marker{ display:none; }
.faq summary::after{
  content:""; position:absolute; right:6px; top:50%; width:13px; height:13px;
  margin-top:-7px;
  background:no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 13 13'%3E%3Cpath d='M6.5 0v13M0 6.5h13' stroke='%23D21F26' stroke-width='2'/%3E%3C/svg%3E");
  transition:transform .22s var(--ease);
}
.faq details[open] summary::after{ transform:rotate(45deg); }
.faq .faq-a{ padding:0 0 24px; color:var(--body); max-width:66ch; }
.faq .faq-a p{ margin:0 0 .9em; }
.bg-ink .faq, .bg-ink .faq details{ border-color:var(--ink-line); }
.bg-ink .faq .faq-a{ color:#9C9187; }

/* ---------- CTA band ---------- */
.cta-band{
  background:var(--red); color:#fff; border-radius:var(--r-lg);
  padding:40px 26px; text-align:center; position:relative; overflow:hidden;
}
@media (min-width:768px){ .cta-band{ padding:64px 48px; } }
.cta-band::after{
  content:""; position:absolute; inset:0; opacity:.3; pointer-events:none;
  background:radial-gradient(70% 100% at 50% 0%, rgba(255,255,255,.35), transparent 70%);
}
.cta-band > *{ position:relative; z-index:1; }
.cta-band h2{ color:#fff; max-width:20ch; margin-inline:auto; }
.cta-band p{ color:rgba(255,255,255,.9); max-width:52ch; margin-inline:auto 1.4em; margin-inline:auto; margin-bottom:26px; }
.cta-band .btn-row{ justify-content:center; }
.cta-band .cta-fine{ margin-top:18px; font-size:.82rem; color:rgba(255,255,255,.78); }

/* ---------- Forms (Formspree-ready) ---------- */
.form-card{
  background:var(--white); border:1px solid var(--cream-edge);
  border-radius:var(--r-lg); padding:24px; box-shadow:var(--shadow);
}
@media (min-width:768px){ .form-card{ padding:34px; } }
.form-grid{ display:grid; gap:14px; }
@media (min-width:640px){ .form-grid{ grid-template-columns:1fr 1fr; } }
.form-card .form-title{ margin-bottom:6px; }
.form-card .form-sub{ color:var(--body); font-size:.95rem; margin-bottom:22px; }
.hp{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
  opacity:0; pointer-events:none;
}

.checkrow{ display:flex; gap:10px; align-items:flex-start; font-size:.88rem; color:var(--body); }
.checkrow input{ width:18px; height:18px; margin-top:2px; flex:none; accent-color:var(--red); }

.pick{ display:grid; gap:8px; }
@media (min-width:520px){ .pick{ grid-template-columns:1fr 1fr; } }
.pick label{
  display:flex; align-items:center; gap:10px; padding:14px 15px;
  border:1.5px solid var(--cream-edge); border-radius:11px; cursor:pointer;
  font-size:.92rem; font-weight:600; background:var(--white);
  transition:border-color .15s var(--ease), background .15s var(--ease);
}
.pick label:hover{ border-color:#C9BFB2; }
.pick input{ accent-color:var(--red); width:17px; height:17px; flex:none; }
.pick input:checked + span{ color:var(--red); }
.pick label:has(input:checked){ border-color:var(--red); background:var(--red-wash); }

.form-note{
  margin-top:16px; font-size:.82rem; color:var(--muted);
  display:flex; gap:8px; align-items:flex-start;
}

/* The honesty guard. Shown to everyone, not hidden behind ?setup, because a
   form that cannot deliver a message must say so to the person typing into
   it. _build/stamp.js removes this notice by itself the moment a real
   endpoint exists in reinforce.config.json, so it cannot be left on by
   accident and it cannot be forgotten. */
.form-offline{
  margin:18px 0 0; padding:13px 15px; border-radius:9px;
  background:#FFF3CD; border:1px solid #E0C97F; color:#5E4A00;
  font-size:.88rem; line-height:1.5;
}
.form-offline a{ color:inherit; font-weight:700; text-decoration:underline; }
form[data-not-connected] button[type="submit"]{ opacity:.55; }

/* Setup markers: visible only when you add ?setup to the URL */
.setup-flag{ display:none; }
body.show-setup .setup-flag{
  display:block; font-family:var(--font-mono); font-size:.7rem;
  background:#FFF3CD; border:1px solid #E0C97F; color:#6B5400;
  padding:6px 10px; border-radius:6px; margin:8px 0;
}

/* ---------- Footer ---------- */
.site-footer{ background:var(--ink); color:#9C9187; padding-block:56px 30px; }
.footer-grid{ display:grid; gap:34px; }
@media (min-width:760px){ .footer-grid{ grid-template-columns:1.5fr 1fr 1fr 1fr; gap:40px; } }
.site-footer img.f-logo{ height:28px; margin-bottom:16px; }
.site-footer p{ font-size:.92rem; max-width:34ch; }
.site-footer h5{
  font-family:var(--font-display); font-weight:700; font-size:.76rem;
  letter-spacing:.14em; text-transform:uppercase; color:var(--cream-lift);
  margin:0 0 14px;
}
.f-list{ list-style:none; margin:0; padding:0; display:grid; gap:2px; }
/* Vertical padding rather than a bigger gap, so the hit area grows without
   the footer growing. These are secondary links, but they are still being
   tapped with a thumb. */
.f-list a{ text-decoration:none; font-size:.92rem; display:inline-block; padding-block:7px; }
.f-list a:hover{ color:var(--red-bright); }
.f-contact a{ color:var(--cream-lift); font-weight:600; text-decoration:none; }
.f-contact a:hover{ color:var(--red-bright); }
.socials{ display:flex; gap:9px; margin-top:16px; }
.socials a{
  width:44px; height:44px; border-radius:10px; border:1px solid var(--ink-line);
  display:flex; align-items:center; justify-content:center; color:#9C9187;
  transition:border-color .18s var(--ease), color .18s var(--ease), background .18s var(--ease);
}
.socials a:hover{ border-color:var(--red); color:var(--red-bright); background:rgba(210,31,38,.1); }
.footer-bottom{
  margin-top:44px; padding-top:22px; border-top:1px solid var(--ink-line);
  display:flex; flex-wrap:wrap; gap:12px; justify-content:space-between;
  font-size:.82rem;
}
.footer-bottom a{ text-decoration:none; }
.footer-bottom a:hover{ color:var(--red-bright); }

/* ---------- Page hero (interior pages) ---------- */
.page-hero{
  background:var(--ink); color:var(--cream-lift);
  /* Was clamp(44px,8vw,84px), which put the same black band across three
     quarters of the fold on every page. The hero is an introduction, not the
     page. Anything below it should be visible without scrolling. */
  padding-block:clamp(34px,5vw,58px);
  position:relative; overflow:hidden;
}
.page-hero::before{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(100% 90% at 88% 0%, rgba(210,31,38,.26), transparent 62%);
}
.page-hero .wrap{ position:relative; z-index:1; }
.page-hero h1{ color:var(--cream-lift); max-width:18ch; font-size:clamp(2.1rem,6.4vw,3.6rem); }
.page-hero .lede{ color:#B3A79B; }
/* A page hero with a button puts it level with the headline, not under the
   lede. On a phone the button drops below, full width, where a thumb is. */
.page-hero-row{ display:grid; gap:22px; align-items:start; }
@media (min-width:900px){
  .page-hero--cta .page-hero-row{ grid-template-columns:1fr auto; column-gap:48px; }
  .page-hero-cta{ padding-top:.55em; }
}
.crumbs{ font-size:.82rem; color:#8A7F76; margin-bottom:18px; }
.crumbs a{ text-decoration:none; }
.crumbs a:hover{ color:var(--red-bright); }

/* ---------- Reveal on scroll ---------- */
.rv{ opacity:0; transform:translateY(16px); transition:opacity .6s var(--ease), transform .6s var(--ease); }
.rv.in{ opacity:1; transform:none; }
@media (prefers-reduced-motion:reduce){
  .rv,.pipe-step{ opacity:1 !important; transform:none !important; transition:none; }
  .reveal-stage.is-on{ animation:none; }
}

/* ---------- Small-screen safety ----------
   Grid/flex children default to min-width:auto, which lets long words and
   nowrap buttons push the page sideways on a 320px phone. This stops it. */
.grid > *, .form-grid > *, .b-fields > *, .pick > *, .hero-grid > *,
.mock-wrap > *, .mock-side > *, .footer-grid > *, .steps > *, .statbar .wrap > *,
.pipe > *, .ba > *{ min-width:0; }
.field input, .field select, .field textarea{ min-width:0; }
.card, .symptom, .form-card, .quote-card, .builder-card{ overflow-wrap:anywhere; }
@media (max-width:400px){
  .btn{ white-space:normal; text-align:center; line-height:1.25; }
  .btn--lg{ padding-inline:22px; }
}


/* ---------- Hero opening ----------
   The visitor's own week at life size. Three texts pop in the way they do on
   a phone, then the headline rises out of a clip, then the one button. Flat
   ink, no backdrop, no glow: the type and the bubbles are the whole picture.
   Every element is visible at rest; the keyframes start from hidden, so a
   browser that skips animation still gets the page. */
.hero--thread{ padding-block:clamp(48px,11.5vw,168px); min-height:0; }
.hero--thread::before, .hero--thread::after{ display:none; }
.hero--thread > .wrap{ position:relative; z-index:1; max-width:1180px; }

.thread-big{ display:grid; gap:12px; max-width:540px; }

/* Stacked, the line comes first and the texts arrive under it, which is the
   order the opening actually plays in. Written the other way round the phone
   showed the middle of the hero move, then the bottom, then the top. */
.hero-split{ display:flex; flex-direction:column; align-items:flex-start; }
.hero-split .hero-say{ order:1; width:100%; }
.hero-split .thread-big{ order:2; margin-top:clamp(30px,4.5vw,52px); }
.tb{
  justify-self:start; max-width:100%;
  background:#2B2521; color:#EDE5D9;
  border-radius:24px 24px 24px 7px; padding:14px 20px;
  font-size:clamp(1.02rem,1.7vw,1.3rem); line-height:1.3;
  transform-origin:left bottom;
  animation:bubIn .38s var(--ease) var(--d) both;
}
.tb:nth-child(2){ margin-left:22px; }
.tb:nth-child(3){ margin-left:8px; }
.tb:nth-child(4){ margin-left:30px; }
@keyframes bubIn{ from{ opacity:0; transform:translateY(10px) scale(.96); } to{ opacity:1; transform:none; } }

/* Wide enough for two columns: the line and its button on the left, the
   texts landing beside them on the right. Same band, composed across its
   whole width instead of stacked down the left edge with the right half of
   the page left empty. On a handset it stacks in DOM order. */
@media (min-width:1040px){
  .hero-split{ display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:clamp(40px,5vw,72px); }
  /* Nine pixels: the distance between the top of the headline's line box and
     the top of its first capital, measured at 1920, 1440 and 1100. Matching
     the boxes is not the same as matching what you see. */
  .hero-split .thread-big{ grid-area:1 / 2; align-self:start; margin:9px 0 0; }
  .hero-split .hero-say{ grid-area:1 / 1; align-self:end; }
  /* One sentence per line, always. Left to itself the headline put "Not"
     alone on the middle line above 1500px: the sentence needed 662px and the
     column was 660. Each half is its own block now, and the size below
     leaves about 50px of slack in the narrowest column this layout gets. */
  .hero--thread h1 .clip{ display:block; }
}

@keyframes heroIn{ from{ opacity:0; transform:translateY(14px); } to{ opacity:1; transform:none; } }
@keyframes rise{ from{ transform:translateY(108%); } to{ transform:none; } }
.hero-points{ animation:heroIn .55s var(--ease) .05s both; }
.hero h1{ animation:heroIn .6s var(--ease) .14s both; }
.hero--thread h1{
  animation:none; margin:0; max-width:none;
  font-size:clamp(2.6rem,7vw,5.8rem); line-height:.96; letter-spacing:-.04em;
}
.hero h1 .clip{ display:inline-block; overflow:hidden; vertical-align:bottom; padding-bottom:.08em; margin-bottom:-.08em; }
.hero h1 .l1, .hero h1 .l2{ display:inline-block; animation:rise .8s var(--ease) both; }
.hero h1 .l1{ animation-delay:.12s; }
.hero h1 .l2{ animation-delay:.28s; }
.hero .lede{ animation:heroIn .55s var(--ease) .5s both; }
.hero-exits{ margin-top:clamp(26px,3.5vw,40px); animation:heroIn .55s var(--ease) .72s both; }
.hero-exits .btn--block{ max-width:320px; }

@media (prefers-reduced-motion:reduce){
  .tb, .hero-points, .hero h1, .hero h1 .l1, .hero h1 .l2, .hero .lede, .hero-exits{ animation:none; }
}

/* ---------- One idea per screen ----------
   Every band below the hero is the same object: the statement on the left,
   the thing it is talking about on the right, sharing one centre line. Under
   980px they stack in the order they are written. */
/* The price and the quote request are one screen between them, not one
   each: at 1440 the pair lands inside a single 900px scroll. */
.section.after, .section.price{ padding-block:clamp(44px,5vw,72px); }
.section.work-band, .section.cta-close{ padding-block:clamp(52px,5.6vw,80px); }
.band-split{ display:grid; gap:clamp(34px,5vw,56px); }
.band-say{ min-width:0; }
@media (min-width:980px){
  .band-split{ grid-template-columns:minmax(0,1.2fr) minmax(0,.8fr); column-gap:clamp(40px,5vw,84px); align-items:center; }
  .band-split .stmt{ max-width:none; }
  .band-split .q-card--big{ margin-top:0; max-width:none; }
  .band-split--price{ align-items:end; }
  .band-split--price .price-line{ margin-top:0; }
  .price-terms{ padding-bottom:clamp(4px,1.4vw,18px); }
}
.stmt{
  /* Three lines is the house limit. In a 1.2fr column this is the size
     that keeps the longest line of the page inside it. */
  font-size:clamp(1.9rem,4.4vw,3.35rem); line-height:1.05; letter-spacing:-.035em;
  max-width:18ch; margin:0;
}
.stmt-sub{ font-size:clamp(1.1rem,1.9vw,1.4rem); color:#B8ADA1; margin:18px 0 0; }
.section.after{ background:var(--ink); color:var(--cream-lift); }
.q-card--big{
  margin-top:clamp(34px,5vw,56px); max-width:420px;
  background:var(--white); color:var(--ink); border:1px solid var(--cream-edge); border-radius:18px; padding:18px 20px 16px;
  box-shadow:0 30px 60px -34px rgba(20,17,16,.35);
}
.q-note{ font-size:.68rem; font-weight:600; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); margin:0 0 12px; }
.q-head{ display:flex; align-items:center; gap:9px; font-family:var(--font-display); font-weight:700; font-size:1.05rem; letter-spacing:-.01em; margin-bottom:8px; }
.q-head em{ margin-left:auto; font-style:normal; font-family:var(--font-body); font-weight:500; font-size:.78rem; color:var(--muted); }
.q-dot{ width:9px; height:9px; border-radius:50%; background:var(--red); box-shadow:0 0 0 3px rgba(210,31,38,.16); flex:none; }
.q-row{ display:grid; grid-template-columns:64px 1fr; gap:10px; font-size:.95rem; line-height:1.35; padding:9px 0; border-top:1px solid var(--cream-edge); }
.q-row b{ color:var(--muted); font-weight:600; font-size:.68rem; letter-spacing:.08em; text-transform:uppercase; padding-top:3px; }

.price .eyebrow{ color:var(--red); }
.price-amt{
  margin:6px 0 0; font-family:var(--font-display); font-weight:700;
  font-size:clamp(5rem,15vw,12rem); line-height:.88; letter-spacing:-.06em; color:var(--ink);
}
.price-line{ font-size:clamp(1.15rem,2.2vw,1.6rem); color:var(--muted); margin:22px 0 0; max-width:30ch; }
.link-arrow{
  display:inline-block; margin-top:26px; color:var(--ink); text-decoration:none;
  font-weight:600; border-bottom:2px solid var(--red); padding-bottom:3px;
}
.link-arrow::after{ content:" \2192"; }
.link-arrow:hover{ color:var(--red); }

.work-band h2{ font-size:clamp(1.9rem,4.2vw,3.2rem); letter-spacing:-.035em; margin:0 0 clamp(22px,3vw,30px); }
.work-card{ display:block; text-decoration:none; color:inherit; background:transparent; border:0; border-radius:0; overflow:visible; }
.work-shot{ position:relative; padding-top:26px; background:#2A2320; border-bottom:0; border-radius:var(--r-lg); overflow:hidden; box-shadow:0 26px 50px -28px rgba(20,17,16,.55); }
.work-shot::before{ content:""; position:absolute; top:9px; left:13px; width:8px; height:8px; border-radius:50%; background:#E8352C; box-shadow:14px 0 0 #D9B24A, 28px 0 0 #58B368; }
/* Two cards, so they take the width three used to rather than leaving a
   third of the band empty. */
@media (min-width:760px){
  .work-grid--two{ grid-template-columns:repeat(2, minmax(0,1fr)); }
}
.work-meta h3{ margin:0 0 3px; font-size:1.05rem; }
.work-note{ margin:8px 0 0; font-size:.94rem; color:var(--muted); max-width:44ch; }
.work-meta .work-where{ margin:0; }

.cta-band--quiet p, .cta-band--quiet .cta-fine{ display:none; }
@media (min-width:900px){
  .cta-band--quiet{
    display:flex; align-items:center; justify-content:space-between;
    gap:40px; text-align:left; padding:44px 48px;
  }
  .cta-band--quiet h2{ margin:0; max-width:22ch; }
  .cta-band--quiet .btn-row{ margin:0; flex:none; }
}

/* ---------- Footer, one row ---------- */
.site-footer--compact{ padding-block:38px 26px; }
/* The sticky bar and the menu both want the bottom of the screen. While the
   menu is open the menu wins: two Get Started buttons stacked on each other
   is not a choice, it is a bug you can see. */
.mobile-menu.is-open ~ .actionbar{ display:none; }
.foot-row{ display:flex; flex-wrap:wrap; align-items:center; gap:18px 36px; }
.site-footer--compact img.f-logo{ height:26px; margin:0; display:block; }
.foot-links{ display:flex; flex-wrap:wrap; gap:4px 22px; }
.foot-links a{ color:#B8ADA1; text-decoration:none; font-size:.92rem; padding-block:6px; }
.foot-links a:hover{ color:var(--red-bright); }
.foot-phone{ margin-left:auto; color:var(--cream-lift); font-weight:700; text-decoration:none; font-family:var(--font-display); }
@media (max-width:759px){
  .foot-row{ flex-direction:column; align-items:flex-start; gap:16px; }
  .foot-phone{ margin-left:0; }
  .foot-bottom{ margin-top:22px; }
}
.foot-phone:hover{ color:var(--red-bright); }
.foot-bottom{
  display:flex; flex-wrap:wrap; justify-content:space-between; gap:8px 20px;
  margin-top:26px; padding-top:18px; border-top:1px solid rgba(253,249,240,.1);
  font-size:.82rem; color:#9C9187;
}
.foot-bottom a{ color:#9C9187; text-decoration:none; margin-left:16px; }
.foot-bottom a:hover{ color:var(--red-bright); }
.work-meta{ padding:18px 2px 0; }

/* Anchor targets clear the sticky header */
[id]{ scroll-margin-top:calc(var(--bar-h) + 20px); }

/* The trade menu's own scrollbar, so a long list looks finished */
.combo-panel{ touch-action:pan-y; scrollbar-width:thin; scrollbar-color:#C9BFB2 transparent; }
.combo-panel::-webkit-scrollbar{ width:10px; }
.combo-panel::-webkit-scrollbar-track{ background:transparent; }
.combo-panel::-webkit-scrollbar-thumb{
  background:#C9BFB2; border-radius:99px;
  border:3px solid var(--white); background-clip:padding-box;
}
.combo-panel::-webkit-scrollbar-thumb:hover{ background:#A79B90; background-clip:padding-box; }
.builder-card .combo-panel,
.hero .form-card .combo-panel{ scrollbar-color:#5C504A transparent; }
.builder-card .combo-panel::-webkit-scrollbar-thumb,
.hero .form-card .combo-panel::-webkit-scrollbar-thumb{
  background:#5C504A; border-color:#1C1613;
}

/* ---------- Print ----------
   If this gets printed or saved to PDF in a meeting, it should look
   deliberate: ink on white, links spelled out, no dead furniture. */
@media print{
  *{ background:transparent !important; color:#000 !important; box-shadow:none !important; }
  body{ font-size:11pt; line-height:1.45; padding:0 !important; }
  .site-header, .topbar, .mobile-menu, .actionbar, .burger,
  .build-stage, .reveal-stage, .combo-panel, .combo-toggle,
  .b-flag, .btn, .socials, .setup-flag{ display:none !important; }
  .hero, .page-hero, .section{ padding-block:18pt !important; }
  .hero::before, .hero::after, .page-hero::before,
  .builder::before, .cta-band::after{ display:none !important; }
  h1{ font-size:24pt; } h2{ font-size:17pt; } h3{ font-size:13pt; }
  h1,h2,h3,h4{ break-after:avoid; }
  .card, .symptom, .quote-card, .form-card, .builder-card,
  .step, .leak, .photo{ border:1pt solid #999 !important; break-inside:avoid; }
  a[href^="http"]::after{ content:" (" attr(href) ")"; font-size:9pt; color:#555 !important; }
  a[href^="tel:"]::after, a[href^="mailto:"]::after, a[href^="#"]::after{ content:""; }
  .grid, .steps, .leaks, .hero-grid{ display:block !important; }
  .card, .symptom, .step{ margin-bottom:10pt; }
  .site-footer{ border-top:1pt solid #999; padding-top:12pt; }
}

/* ---------- Utilities ---------- */
.center{ text-align:center; }
.mt-0{ margin-top:0; } .mt-1{ margin-top:10px; } .mt-2{ margin-top:20px; }
.mt-3{ margin-top:30px; } .mt-4{ margin-top:44px; }
.mb-0{ margin-bottom:0; }
.max-50{ max-width:50ch; } .max-60{ max-width:60ch; }
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}
/* Instant, never animated: a focus ring that fades in reads as lag to
   anyone navigating by keyboard. */
:focus-visible{
  outline:3px solid var(--red); outline-offset:3px; border-radius:4px;
  transition:none !important;
}
.bg-ink :focus-visible, .hero :focus-visible, .site-footer :focus-visible,
.page-hero :focus-visible{ outline-color:var(--red-bright); }
::selection{ background:var(--red); color:#fff; }

/* The two exits in the hero. Stacked, full width, primary above secondary,
   because on a phone they are read in that order and tapped with a thumb. */
.exit-stack{ display:grid; gap:10px; margin-top:20px; }
.exit-stack .btn{ width:100%; }
.b-note{
  margin:14px 0 0; font-size:.86rem; line-height:1.5; color:#C3B8AC;
  text-align:center;
}

/* ---------- Recent work ---------- */
/* Real screenshots of live sites. Three across on a wide screen, stacked on a
   phone. The shot is a link, because the strongest thing this section can do
   is get someone onto a site that actually exists. */
.work-grid{ display:grid; gap:26px; }
@media (min-width:820px){ .work-grid{ grid-template-columns:repeat(3,1fr); gap:24px; } }

.work-card{
  background:var(--white); border:1px solid var(--cream-edge);
  border-radius:var(--r-lg); overflow:hidden;
  display:flex; flex-direction:column;
}
.work-shot{ display:block; line-height:0; border-bottom:1px solid var(--cream-edge); }
.work-shot img{
  width:100%; height:auto; aspect-ratio:2/1; object-fit:cover; object-position:top center;
  transition:transform .35s var(--ease);
}
.work-card:hover .work-shot img{ transform:scale(1.02); }

.work-meta{ padding:20px 22px 22px; display:flex; flex-direction:column; flex:1; }
.work-meta h3{ margin:0 0 4px; }
.work-where{
  font-family:var(--font-display); font-weight:700; font-size:.76rem;
  letter-spacing:.08em; text-transform:uppercase; color:var(--red);
  margin:0 0 12px;
}
.work-meta p{ font-size:.92rem; color:var(--body); }
.work-link{
  margin-top:auto; padding-top:14px;
  font-family:var(--font-display); font-weight:700; font-size:.92rem;
  text-decoration:none; color:var(--ink);
  display:inline-flex; align-items:center; gap:7px; min-height:44px;
}
.work-link:hover{ color:var(--red); }

/* The proof line. Three claims, each one checkable without leaving the page:
   the sites are linked in Recent Work, and the phone number is in the header. */
.hero-proof{
  list-style:none; margin:22px 0 0; padding:0;
  display:flex; flex-wrap:wrap; gap:8px 20px;
  font-size:.86rem; color:#C3B8AC;
}
.hero-proof li{ display:flex; align-items:center; gap:8px; }
.hero-proof li::before{
  content:""; width:15px; height:15px; flex:none; border-radius:50%;
  background:rgba(210,31,38,.22);
  box-shadow:inset 0 0 0 1.5px var(--red-bright);
}

/* ---------- One we built, on the industry pages ---------- */
/* These pages had no image anywhere in a 3400px scroll, which is most of why
   they read as a template. A real, live, clickable build fixes that and
   argues at the same time. */
.proof-split{ display:grid; gap:24px; align-items:center; }
@media (min-width:880px){ .proof-split{ grid-template-columns:1.25fr 1fr; gap:38px; } }
.proof-shot{
  display:block; line-height:0; border-radius:var(--r-lg); overflow:hidden;
  border:1px solid var(--cream-edge);
  box-shadow:0 18px 40px -24px rgba(20,17,16,.45);
}
.proof-shot img{
  width:100%; height:auto; aspect-ratio:2/1; object-fit:cover; object-position:top center;
  transition:transform .35s var(--ease);
}
.proof-shot:hover img{ transform:scale(1.02); }
.proof-meta h3{ margin:0 0 3px; }
.proof-meta p{ font-size:.95rem; color:var(--body); }

/* ---------- Our Work page: one row per build ---------- */
.build-list{ display:grid; gap:56px; }
.build-row{ display:grid; gap:22px; align-items:center; }
@media (min-width:900px){
  .build-row{ grid-template-columns:1.25fr 1fr; gap:40px; }
  /* Alternate which side the screenshot sits on, so three rows do not read
     as the same template repeated three times. */
  .build-row:nth-child(even) .proof-shot{ order:2; }
}
.build-meta h3{ margin:0 0 3px; font-size:clamp(1.35rem,3vw,1.7rem); }
.build-meta p{ font-size:.95rem; color:var(--body); margin:0 0 10px; }
.build-meta p strong{ color:var(--ink); }

/* The offer terms are styled for the dark hero. On the industry pages the same
   block sits inside a light card, where near-white on white made the price
   terms invisible on all 17 of them. This is the second class I used without
   defining; the rendered gate caught this one before Grant did. */
.offer-terms--light > div{
  border-top-color:var(--cream-edge);
}
.offer-terms--light > div:last-child{ border-bottom-color:var(--cream-edge); }
.offer-terms--light dt{ color:var(--ink); }
.offer-terms--light dd{ color:var(--body); }


/* One action in the sticky bar. A call button next to the booking button is a
   way round the calendar, and the calendar is the only thing that makes this
   workable around two other jobs. The number is still in the header. */
.actionbar--single{ grid-template-columns:1fr; }

/* ---------- Hero on a phone: get the button above the fold ---------- */
/* Measured at 390x844 the button landed at 934px, ninety short. The offer
   terms were 202px because each term wrapped onto two lines, and the proof
   line sat between the copy and the card. Both are fixed below: the terms go
   horizontal, and the proof line moves under the card, where it reads as
   reassurance after the ask rather than another thing to get past. */
@media (max-width:899px){
  /* display:contents dissolves the copy wrapper so its children become grid
     items and can be reordered around the card. */
  .hero-grid > div:first-child{ display:contents; }
  .hero-grid h1{ order:1; }
  .hero-grid .lede{ order:2; }
  .hero-grid .offer-terms{ order:3; }
  .hero-grid .builder{ order:4; }

  /* Term and detail on one line instead of stacked. */
  .offer-terms{ margin-top:20px; }
  .offer-terms > div{
    display:grid; grid-template-columns:auto 1fr; align-items:baseline;
    gap:0 12px; padding:9px 0;
  }
  .offer-terms dt{ font-size:.95rem; }
  .offer-terms dd{ font-size:.85rem; text-align:right; }

  /* The three points across the top fit on one line at this size. */
  .hero-points{ gap:6px 16px; margin-bottom:14px; }
  .hero-points li{ font-size:.92rem; }

  /* Not zero. The price flag overhangs the top edge of the card, so a zero
     gap put it on top of the last line of the lede. This clears the badge
     and no more. */
  .hero-grid{ gap:30px; }

  /* The card's explanatory paragraph is worth reading on a desktop and is
     three lines of delay on a phone, where the sticky bar also eats the
     bottom 75px. The headline and the offer terms above have already made
     the point, so on a phone the card gets straight to the button. */
  #heroExits{ padding:18px 16px 16px; }
  #heroExits .b-label{ margin-bottom:14px; }
}

/* ---------- Industries index ---------- */
/* Seventeen flat cards was a wall you gave up on. Five groups is a thing you
   navigate, and the pain line does the work the trade name cannot: it is the
   sentence somebody recognises as their own week. */
.trade-group{ margin-bottom:34px; }
.trade-group:last-child{ margin-bottom:0; }
.trade-group-name{
  font-size:clamp(1.05rem,2.4vw,1.25rem); margin:0 0 18px;
  padding-bottom:12px; border-bottom:1px solid var(--cream-edge);
  display:flex; align-items:center; gap:12px;
}
.trade-group-name::before{
  content:""; width:22px; height:3px; border-radius:3px;
  background:var(--red); flex:none;
}

.trade-list{ display:grid; gap:10px; }
@media (min-width:700px){ .trade-list{ grid-template-columns:repeat(2,1fr); } }
@media (min-width:1080px){ .trade-list{ grid-template-columns:repeat(3,1fr); } }

.trade-item{
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  background:var(--white); border:1px solid var(--cream-edge);
  border-radius:var(--r); padding:15px 16px 15px 18px;
  text-decoration:none; color:var(--ink);
  font-family:var(--font-display); font-weight:700;
  font-size:.98rem; letter-spacing:-.015em; line-height:1.25;
  transition:border-color .18s var(--ease), background .18s var(--ease),
             transform .18s var(--ease);
}
.trade-item:hover{
  border-color:var(--red); background:var(--red-wash);
  transform:translateY(-2px);
}
.trade-arrow{ color:var(--red); flex:none; transition:transform .18s var(--ease); }
.trade-item:hover .trade-arrow{ transform:translateX(3px); }



/* A section that directly follows a CTA band does not need its own full top
   padding: the band already has 64px inside it, so the two stack into about
   210px of empty ground between two elements that belong together. */
.cta-band + .section, .section:has(> .wrap > .cta-band) + .section{
  padding-top:clamp(20px,3vw,36px);
}

/* The proof line sits inside the offer card now, where the grey terms row
   used to be. On a dark ground it needs the lighter red and a top rule to
   separate it from the note above. */
#heroExits .hero-proof{
  margin:18px 0 0; padding-top:15px;
  border-top:1px solid rgba(253,249,240,.12);
  flex-direction:column; align-items:flex-start; gap:9px;
  font-size:.82rem;
}
#heroExits .hero-proof li{ color:#C3B8AC; }

/* ---------- Split page hero: copy left, card right ---------- */
/* A page whose job is to be acted on should not open with an empty half.
   Single column below 900 so the card follows the sentence that earns it,
   rather than sitting above the headline. */
.page-hero--split .wrap{ display:grid; gap:34px; align-items:center; }
@media (min-width:900px){
  .page-hero--split .wrap{ grid-template-columns:1.08fr .92fr; gap:52px; }
  .page-hero--split h1{ max-width:15ch; }
}
.hero-aside .builder-card{ max-width:none; margin:0; }
.hero-aside .b-fine{
  font-size:.9rem; color:#9C9187; margin:14px 0 0; line-height:1.5;
}
.hero-aside .hero-proof{
  margin-top:18px; padding-top:16px; border-top:1px solid rgba(253,249,240,.12);
}

/* ---------- Proof line, landscape ---------- */
/* Stacked, three short terms read as a list to get through. Across, they read
   as a row of reasons, and cost four lines less height above the fold. Two
   columns on the narrowest phones, where three would put every item on three
   lines and undo the saving. */
.hero-proof--row{
  display:grid; grid-template-columns:1fr 1fr; gap:10px 16px;
  margin-top:18px; padding-top:16px;
  border-top:1px solid rgba(253,249,240,.12);
  font-size:.78rem; line-height:1.35; color:#B8ADA1;
}
/* Three equal grid cells put the dots on an even grid but not the words:
   "No surprise invoices" filled its cell and "Yours when paid" left half of
   its cell empty, so the gaps the eye sees were 30px then 53px. Spacing the
   items themselves, not the cells, makes the visible gaps equal. */
@media (min-width:430px){
  /* #heroExits .hero-proof sets flex-direction:column for the homepage's
     stacked list. It never mattered while this was a grid; it stacks the row
     the moment this is flex, and the id outranks the class, so name it. */
  .hero-proof--row, #heroExits .hero-proof--row{ display:flex; flex-direction:row; justify-content:space-between; }
}
.hero-proof--row li{ align-items:flex-start; gap:7px; }
.hero-proof--row li::before{ width:13px; height:13px; margin-top:2px; }

/* ---------- Work carousel ---------- */
/* A horizontal scroller first, a carousel second. The arrows and dots are
   enhancement: with no JS this still swipes, and all three builds stay
   reachable. That ordering is the whole reason to build it this way. */
.carousel{ position:relative; }
.carousel-track{
  display:flex; gap:0;
  overflow-x:auto; overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory; scroll-behavior:smooth;
  scrollbar-width:none; -ms-overflow-style:none;
  border-radius:var(--r-lg);
}
.carousel-track::-webkit-scrollbar{ display:none; }
.carousel-track:focus-visible{ outline:2px solid var(--red); outline-offset:4px; }
@media (prefers-reduced-motion:reduce){ .carousel-track{ scroll-behavior:auto; } }

.work-slide{
  flex:0 0 100%; scroll-snap-align:start; scroll-snap-stop:always;
  min-width:0; display:grid; gap:22px; align-content:start;
}
@media (min-width:900px){
  .work-slide{ grid-template-columns:1.35fr 1fr; gap:36px; align-items:center; }
}
.work-slide .proof-shot{ display:block; border-radius:var(--r); overflow:hidden; }
.work-slide .proof-shot img{ display:block; width:100%; height:auto; }
.work-slide .build-meta h3{ margin:0 0 4px; }
.work-slide .build-meta p{ margin:0 0 10px; }
.work-slide .build-meta .btn{ margin-top:6px; }

.carousel-bar{
  display:flex; align-items:center; justify-content:center; gap:16px;
  margin-top:22px;
}
.c-arrow{
  width:44px; height:44px; flex:none; display:grid; place-items:center;
  border-radius:50%; border:1px solid var(--cream-edge);
  background:var(--white); color:var(--ink); cursor:pointer;
  transition:border-color .18s var(--ease), color .18s var(--ease);
}
.c-arrow:hover{ border-color:var(--red); color:var(--red); }
.c-arrow[disabled]{ opacity:.34; cursor:default; }
.c-arrow[disabled]:hover{ border-color:var(--cream-edge); color:var(--ink); }
.c-dots{ display:flex; gap:9px; }
.c-dot{
  width:9px; height:9px; padding:0; border-radius:50%; cursor:pointer;
  border:1px solid var(--red); background:transparent;
  transition:background .18s var(--ease), transform .18s var(--ease);
}
.c-dot[aria-selected="true"]{ background:var(--red); transform:scale(1.28); }
/* The dots are 9px of paint inside a 34px target, because a 9px tap target
   fails on a phone and growing the dot itself would make it a blob. */
.c-dots .c-dot{ position:relative; }
.c-dots .c-dot::after{ content:""; position:absolute; inset:-13px; border-radius:50%; }

/* ---------- Closing box ---------- */
/* Text left, the way out right. Stacked, the buttons ended up under a
   paragraph with half the box sitting empty beside them. */
.closer{
  background:var(--ink); color:var(--cream-lift);
  border-radius:var(--r-lg); padding:30px 32px;
  display:grid; gap:22px;
}
@media (min-width:860px){
  .closer{ grid-template-columns:1fr auto; align-items:center; gap:44px; }
}
.closer h3{ color:var(--cream-lift); margin:0 0 8px; }
.closer p{ color:#9C9187; margin:0; max-width:60ch; }
.closer .btn-row{ margin:0; flex-wrap:wrap; }

/* ---------- Lead price card ---------- */
/* Three identical boxes said nothing about which one is the product. */
.card--lead{
  border-color:var(--red); position:relative;
  box-shadow:0 18px 44px -30px rgba(210,31,38,.55);
}
.card-flag{
  display:inline-block; margin-bottom:10px;
  background:var(--red); color:var(--white);
  font-family:var(--font-mono); font-size:.66rem; letter-spacing:.12em;
  text-transform:uppercase; padding:5px 10px; border-radius:999px;
}
/* Cream version of the closer band, for use on a light section. */
.closer--lift{ background:var(--white); color:var(--ink); border:1px solid var(--cream-edge); }
.closer--lift h3{ color:var(--ink); }
.closer--lift p{ color:var(--body); }

/* A ghost button inherits ink-coloured text, which on the dark closer band is
   the background colour exactly. Caught by the contrast gate at ratio 1.00. */
.closer .btn--ghost{ color:var(--cream-lift); border-color:rgba(253,249,240,.34); }
.closer .btn--ghost:hover{ border-color:var(--cream-lift); background:rgba(253,249,240,.06); }
.closer--lift .btn--ghost{ color:var(--ink); border-color:var(--cream-edge); }
.closer--lift .btn--ghost:hover{ border-color:var(--red); color:var(--red); background:transparent; }

/* ---------- Carousel screenshots ---------- */
/* The three source files are different heights on purpose: each site's hero
   is framed at the height that shows it whole. Marcum's callback form runs
   the full height of its hero, so a short frame slices it mid-button and
   reads as a broken render. Superior Waste centres a short block of text in
   whatever viewport it is given, so a tall frame buries it under sky, which
   is the complaint that started this.

   They can differ because .proof-shot img already crops to a 2:1 box from the
   top, so the slides are one shape on the page regardless. */


/* ---------- Landing block height ---------- */
/* The hero ended at 48% of the fold, so the landing read as a dark stripe
   with cream underneath rather than as the first screen. Filling most of the
   viewport is the difference between a band and a landing.

   Capped in px as well as vh so a tall monitor does not turn it into a
   scroll of empty ink, and only above 900 because on a phone the stacked
   copy and card already make the height on their own. */
@media (min-width:900px){
  .hero{
    /* Not a round number and not a fraction of the viewport: the section
       below starts its heading a constant 160px under this edge, so
       viewport minus 312 is what leaves roughly 45px of that 116px heading
       showing. Cut mid-heading is the only version that reads as "there is
       more", rather than "the page ends here" or "here is the next
       heading, in full, with nothing under it". Capped so a very tall
       monitor does not turn the first screen into empty ink. */
    min-height:min(calc(100svh - 312px), 820px);
    display:grid; align-content:center;
  }
  .hero > .wrap{ width:100%; }
}


/* ---------- Mobile paint budget ---------- */
/* Everything here is a backdrop-filter on something that moves under the
   finger. A sticky header and a fixed bar re-run their blur on every scroll
   frame, and the hero card multiplied from one page to twenty when it
   replaced the builder. At 88 to 94 percent opacity the blur is close to
   invisible, so on a phone these go opaque and the filter comes off.
   Desktop keeps the glass. */
@media (max-width:899px){
  .site-header{
    background:#F7F1E4;
    backdrop-filter:none; -webkit-backdrop-filter:none;
  }
  .actionbar{
    background:#FDF9F0;
    backdrop-filter:none; -webkit-backdrop-filter:none;
  }
  .builder-card, .hero .form-card{
    background:#191311;
    backdrop-filter:none; -webkit-backdrop-filter:none;
  }
  /* A blur(26px) bloom behind the card, on a layer the size of the card.
     It is decoration and it costs a rasterise. */
  .builder::before{ display:none; }
}

/* ---------- Stand-in for a form with nowhere to post ---------- */
/* Not a disabled form and not an apology. The two routes that work, in the
   space the form occupied. Removed automatically once worker_url is set. */
.form-standin{ display:grid; gap:14px; }
.standin-note{ margin:0; font-size:.92rem; color:var(--muted); line-height:1.5; }
.standin-or{
  display:flex; align-items:center; gap:12px;
  font-size:.78rem; letter-spacing:.12em; text-transform:uppercase;
  color:var(--muted); margin:2px 0;
}
.standin-or::before, .standin-or::after{
  content:""; flex:1; height:1px; background:var(--cream-edge);
}
.standin-mail{ margin:2px 0 0; font-size:.9rem; color:var(--muted); }
.standin-mail a{ color:var(--red); font-weight:600; }

/* Every icon in the footer socials row is conditional: an unset social URL,
   or an email at a domain we do not own, is removed rather than guessed at.
   When all of them are gone the container has to go too, or it leaves its
   16px of margin behind as a gap nobody can explain. :empty alone misses it,
   because the generated markup leaves whitespace inside. */
.socials:empty{ display:none; }
.socials:not(:has(a)){ display:none; }
