/* =============================================================================
   Mold Free USA — /is-it-mold/ paid-traffic lander.

   The lander keeps the v0 lander's SECTION ORDER and argument flow and throws
   away its skin. Every colour, face, radius and line weight below comes from
   style.css's own tokens; nothing here is a second design language:

     navy #000B4C      -> charcoal --c-ink / near-black --c-ink-2
     red #E43B2C       -> amber --c-amber (black text) + olive --c-olive
     #F5F5F5 grey band -> off-white --c-off between two cream bands
     Oswald + Open Sans-> Rajdhani + Barlow
     radius 10-16px    -> radius 2px, the site's square corners
     drop shadows      -> hard 3px charcoal frames (the .tm__frame device)
     starburst seals   -> the site's pentagon badge chrome
     round-cap ticks   -> square-cap chevrons, the site's line vocabulary

   Loaded after style.css, before form.css. Own class prefix (.l*) so nothing
   collides with the homepage's components; .btn / .wrap / .logo / .callbar /
   .topo / .sr-only / .dia are reused as-is.
   ========================================================================== */

/* The lander's content measure — narrower than the site's 1352px chrome measure,
   exactly as the v0 lander was, so the argument stays dense. ONE token, because
   the header and the body did drift: the header sat in the site's .wrap and the
   logo and phone hung 106px outside every block beneath them. This file loads
   only on /is-it-mold/, so a :root property here cannot reach another page. */
:root { --lcol: 1140px; }

.lwrap {
  max-width: var(--lcol);
  margin-inline: auto;
  padding-inline: var(--pad);
}

/* -----------------------------------------------------------------------------
   BUTTON RADIUS — lander-local. The reference's buttons measure a 10px radius
   (refspec/spec.json → buttons[].borderRadius); the site skin is square at 2px.
   This file is loaded ONLY by /is-it-mold/, so the override cannot reach the
   other pages — style.css itself is untouched, and /free-assessment/ keeps the
   site's 2px corners. Placed first so the section rules below can still win.
   -------------------------------------------------------------------------- */
.btn { border-radius: 10px; }

/* =============================================================================
   SLIM HEADER — logo + phone only. A lander must not leak clicks, so there is
   no nav; ad review only needs the identity, and that is what this carries.
   ========================================================================== */
.lhdr {
  position: relative;
  z-index: 10;
  background: var(--c-ink);
  border-bottom: 3px solid var(--c-amber);
}
/* The header rides the LANDER's column, not the site's — the markup reuses
   .wrap for the flex row, so the measure has to be reset here or the logo and
   the phone sit outside every block below them. */
.lhdr .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  max-width: var(--lcol);
  padding-block: 14px;
}
/* the site lockup, laid on its side for a slim bar */
.lhdr .logo { flex-direction: row; align-items: center; gap: 13px; }
.lhdr .logo svg { width: 54px; height: 54px; }
.lhdr .logo b { font-size: 28px; line-height: 30px; }

.lhdr__tel {
  gap: 10px;
  flex-shrink: 0;
  font-size: 22px;
  letter-spacing: .03em;
}
.lhdr__tel svg {
  width: 19px;
  height: 19px;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* =============================================================================
   sec00 — HERO  (reference: centred copy on a flat navy field)

   The photo is NOT in here. The reference's hero photo is a dark blur doing no
   work, so it can sit under a scrim; ours is a technician's face in a
   full-face respirator, and it IS the hook. A scrim heavy enough to carry
   58px type over that face is a scrim heavy enough to bury it, so the photo
   gets its own full-bleed band (.lshot) directly below — the slot the
   reference fills with its mascot. The hero keeps the reference's
   composition: centred headline, centred sub, centred button.
   ========================================================================== */
.lhero {
  position: relative;
  z-index: 1;
  padding: 88px 0 82px;
  background: var(--c-ink);
  text-align: center;
  overflow: hidden;
}
.lhero .lwrap { position: relative; z-index: 2; }
.lhero h1 {
  max-width: 940px;
  margin: 0 auto;
  font: 700 58px/64px var(--ff-display);
  letter-spacing: .012em;
  text-transform: uppercase;
  color: var(--c-off);
}
.lhero__sub {
  max-width: 760px;
  margin: 20px auto 0;
  font: 500 21px/29px var(--ff-body);
  color: rgba(251, 250, 248, .93);
}
.lhero__cta { margin-top: 30px; }
.lhero__cta .btn { font-size: 24px; padding: 14px 34px; }

.lcall {
  margin: 15px 0 0;
  font: 400 16px/22px var(--ff-body);
  color: rgba(251, 250, 248, .88);
}
.lcall a {
  color: var(--c-amber);
  font-weight: 700;
  text-underline-offset: 3px;
}
.lcall a:hover { color: var(--c-amber-hi); }
.lcall--ink { color: var(--c-body); }
.lcall--ink a { color: #8a6a10; }
.lcall--ink a:hover { color: #000; }

/* =============================================================================
   sec01 — THE FACE. Full viewport width at every breakpoint, no scrim, no
   overlay type, no frame — nothing between the visitor and the photo.

   THE MARK ON HIS SHIRT. The source is a real photograph and the polo carries
   the competitor's embroidered logo — mascot plus wordmark — measured at source
   (1960..2190, 1660..1830) of the 2560x1920 frame. Every crop below therefore
   has ONE non-negotiable constraint: the window must end above source y=1660.
   (The photo is queued for the Reve rewrite; until then the crop is what keeps
   it off the page, so these numbers are load-bearing, not taste.)

   Source is 2560x1920 (4:3); the head and mask occupy roughly y 400..1450 and
   x 1050..2200 — i.e. the mark sits directly below the right cartridge, so no
   horizontal pan can drop it without eating the man's face. The bottom has to
   be cut instead, and cutting the bottom while keeping the head BIG on a phone
   is exactly what object-fit cannot do: with a box wider than 4:3 it shows the
   full source width (head shrinks), and with a narrower box it shows the full
   source height (mark stays). So below 900 the section becomes a crop WINDOW
   and the image is positioned inside it — the same device as .lsplit__port,
   with every offset read straight off the source rect.

     >900   height 45vw, object-fit. Because the height tracks the width the
            slice always shows the SAME 60% of the frame's height whatever the
            viewport — centred, i.e. source y 384..1536. Head plus both
            cartridges, and 124px clear of the mark. Untouched.
     ≤900   window (230, 180, 2100, 1400) — a 3:2 band, mark clear by 80px.
     ≤560   window (940, 220, 1340, 1340) — square, zoomed 2x onto the face so
            the head reads ~305px tall on a 390px screen (it was 222px under
            the old 1:1 pan), mark clear by 100px.
   ========================================================================== */
.lshot {
  position: relative;
  z-index: 3;
  background: var(--c-ink);
  line-height: 0;              /* no inline-image descender gap under it */
}
/* On desktop the photo sits in the CONTENT column, not across the whole screen:
   its edges line up with the headline and every block below it, and the ink band
   it sits on runs full width so the hero's field carries through behind it.
   Full-bleed at this height was simply too much picture — 893px of it.
   8:5 keeps the same 83% of the 4:3 source that the full-bleed version showed,
   so nothing is cropped differently; the plate is just smaller. Phones keep the
   full-bleed crop window (see the <=900 block) — it reads correctly there. */
/* .topo on the section, because insetting the photo exposed the strips of ink
   beside it and they were the only flat panels in a dark field that is textured
   above and below. The photo has to sit ON the texture, not under it. */
.lshot { padding-inline: var(--pad); }
.lshot img {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  max-width: calc(var(--lcol) - var(--pad) * 2);
  height: auto;
  margin-inline: auto;
  aspect-ratio: 8 / 5;
  object-fit: cover;
  object-position: 50% 55%;
}

/* =============================================================================
   BANDS
   ========================================================================== */
.lband { position: relative; padding: 72px 0; }
.lband > .lwrap { position: relative; z-index: 1; }
.lband--ink { background: var(--c-ink); color: var(--c-off); }
.lband--cream { background: var(--c-cream); color: var(--c-body); }
.lband--off { background: var(--c-off); color: var(--c-body); }

.lhead { max-width: 900px; margin: 0 auto; text-align: center; }
.lhead h2 {
  margin: 0;
  font: 700 42px/48px var(--ff-display);
  letter-spacing: .012em;
  text-transform: uppercase;
  color: var(--c-amber);
}
.lhead--dark h2 { color: #000; }
.lhead p {
  margin: 16px 0 0;
  font: 400 19px/27px var(--ff-body);
  color: rgba(251, 250, 248, .9);
}
.lhead--dark p { color: var(--c-body); }

/* =============================================================================
   sec02 — the reframe: 3 outlined cards on charcoal + the "our way" CTA
   (v0: hairline cards with a white starburst seal notched over the top edge)
   ========================================================================== */
.lcards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 30px;
  margin-top: 62px;
}
.lcard {
  position: relative;
  padding: 42px 26px 28px;
  border: 1px solid rgba(251, 250, 248, .3);
  border-radius: 2px;
}
.lcard h3 {
  margin: 0;
  font: 700 24px/28px var(--ff-display);
  letter-spacing: .015em;
  text-transform: uppercase;
  color: var(--c-off);
}
.lcard p {
  margin: 12px 0 0;
  font: 400 16px/25px var(--ff-body);
  color: rgba(251, 250, 248, .85);
}
/* the seal slot, in the site's pentagon vocabulary rather than v0's starburst */
.lcard__seal {
  position: absolute;
  top: -25px;
  right: 20px;
  width: 52px;
  height: 49px;
  color: var(--c-amber);
  fill: var(--c-ink);
  stroke: currentColor;
  stroke-width: 3;
  stroke-linejoin: miter;
}
.lcard__seal .g { fill: none; stroke-width: 3.4; stroke-linecap: square; }

/* The heading and the restatement paragraph that used to sit here are gone: by
   this point the band's own H2, its sub and three cards have made the argument
   three times, and a fourth telling is what makes a page read as homework.
   What is left is what `.lcentre` already is — the ask, and the number.

   Deleting `.lway p` also fixed a live bug. It was `(0,1,1)` against `.lcall`'s
   `(0,1,0)` and came later in the file, so it silently won on the phone line
   nested inside this block: that one line rendered 19px/27px where the page's
   other three render 16px/22px. Measured, not spotted by eye. */
.lway { margin-top: 58px; text-align: center; }
.lway .btn { font-size: 22px; padding: 13px 30px; }

/* =============================================================================
   sec03 — bullets + the photo badge  (v0: white band, navy ticks, red burst)
   ========================================================================== */
.lsplit {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 62px;
  align-items: center;
}
.lsplit h2 {
  margin: 0;
  font: 700 38px/44px var(--ff-display);
  letter-spacing: .012em;
  text-transform: uppercase;
  color: #000;
}
.lsplit__lead {
  margin: 16px 0 0;
  font: 400 19px/27px var(--ff-body);
  color: var(--c-body);
}
.lchecks { margin: 26px 0 0; padding: 0; list-style: none; }
.lchecks li {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 13px 0;
  border-top: 1px solid #d8cfc3;
  font: 400 17px/25px var(--ff-body);
  color: var(--c-body);
}
.lchecks li:last-child { border-bottom: 1px solid #d8cfc3; }
/* the component draws its own marker — never a glyph repeated by the author */
.lchecks svg {
  width: 22px;
  height: 22px;
  margin-top: 2px;
  flex-shrink: 0;
  fill: none;
  stroke: var(--c-olive);
  stroke-width: 3.2;
  stroke-linecap: square;
  stroke-linejoin: miter;
}
.lchecks b { font-weight: 700; color: #000; }

/* --- the technician photo + our estimate seal --------------------------------

   The asset is not a plain photo. /assets/img/ref-tech-working.png is a
   692x736 canvas carrying a 600x694 PICTURE at its top-left; the rest is
   transparent, and it exists only so the reference company's red starburst can
   hang off the picture's bottom-right corner (that starburst is opaque out to
   x=690, y=735, well past the picture). Framing the file therefore framed 92px
   of empty canvas down the right-hand side — measured, after it rendered as a
   cream gutter inside the black frame.

   So the figure is two boxes:
     .lsplit__port  crops to the part of the picture worth showing and clips
                    everything outside it, including the part of their badge
                    that hangs off the picture;
     .lseal         is a sibling of the port, not a child, so it can overhang
                    the frame the way the old pentagon badge did instead of
                    being cut off by the crop.

   The frame is on the FIGURE and the port fills its content box, which makes
   the figure's padding box exactly equal to the crop window. That is what lets
   .lseal's percentages be read straight off the source image, with no 4px
   border error creeping into a placement that has to be pixel-exact.
   -------------------------------------------------------------------------- */
.lsplit__media {
  position: relative;
  margin: 0;                   /* the UA's 40px figure margin is not a design */
  border: 4px solid #1c1c1c;
  border-radius: 2px;
}

/* Crop window: source rect (0, 90, 500, 470). It drops a strip of blank
   ceiling and a lot of bare floor — and, usefully, most of their starburst,
   which shrinks the seal that has to cover the rest. */
.lsplit__port {
  display: block;
  position: relative;
  overflow: hidden;
  aspect-ratio: 500 / 470;
  background: #1c1c1c;         /* fills the picture's own rounded corners */
}
.lsplit__port img {
  position: absolute;
  left: 0;
  top: -19.149%;               /*  90 / 470 — the window's top edge */
  width: 138.4%;               /* 692 / 500 — the window's left..right span */
  max-width: none;
  height: auto;
}

/* The seal, placed by measurement rather than by eye.

   Their starburst is a disc of radius 144.5 centred at (546, 590.5) in the
   source file. Clipped to the crop window it becomes a corner lens whose
   smallest covering circle is r = 71.5 at (452.35, 506.75) source-px — that
   is 14.30% of the window width, centred at 90.47% / 88.67% of the window.

   #seal-burst's inscribed radius is 156.24/336 = 46.50% of its own box, so a
   box 36% of the window width carries an inner radius of 16.74% against the
   14.30% required: a 17% margin, and cover that holds at any point phase
   rather than depending on where the two stars' spikes happen to land. */
.lseal {
  position: absolute;
  left: 90.47%;
  top: 88.67%;
  width: 36%;
  height: auto;
  aspect-ratio: 1 / 1;
  transform: translate(-50%, -50%);
  fill: var(--c-amber);
  stroke: #1c1c1c;
  stroke-width: 6;
  stroke-linejoin: miter;
}
/* The label lives inside the SVG so it scales with the seal at every width —
   one geometry instead of a font-size per breakpoint. Real text, in the DOM;
   the <svg> carries role="img" so it is announced once, not word by word. */
.lseal text {
  fill: #1c1c1c;
  stroke: none;
  text-anchor: middle;
  font-family: var(--ff-display);
  font-weight: 700;
}
.lseal__a { font-size: 74px; letter-spacing: .01em; }
.lseal__b { font-size: 43px; letter-spacing: .015em; }

/* =============================================================================
   sec04 — "why choose" cards  (v0: white cards, 3px red border, drop shadow)
   ========================================================================== */
.lwhy {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 32px;
  margin-top: 50px;
}
.lwhy article {
  padding: 26px 26px 28px;
  border: 3px solid var(--c-olive);
  border-radius: 2px;
  background: #fff;
}
.lwhy__ic {
  width: 46px;
  height: 30px;
  margin-bottom: 16px;
  color: var(--c-amber);
  fill: none;
  stroke: currentColor;
  stroke-width: 4;
  stroke-linecap: square;
  stroke-linejoin: miter;
}
.lwhy h3 {
  margin: 0;
  font: 700 26px/30px var(--ff-display);
  letter-spacing: .015em;
  text-transform: uppercase;
  color: #000;
}
.lwhy p {
  margin: 10px 0 0;
  font: 400 16px/25px var(--ff-body);
  color: var(--c-body);
}
.lcentre { margin-top: 46px; text-align: center; }
.lcentre .btn { font-size: 22px; padding: 13px 30px; }

/* =============================================================================
   sec05 — the before/after proof

   Each pair is one job shot twice from the same spot, delivered as two 600x652
   halves with BEFORE and AFTER burned in. So this block draws no tags of its
   own, and never crops: an object-fit crop would cut those labels off.

   Desktop rejoins the halves inside ONE frame with no gutter, so the pair
   reads as the single split photograph it was shot as. The frame therefore
   belongs to the figure, not to each image — a border per image would draw a
   doubled 8px rule down the middle of the picture.

   ONE pair per row, not two. Two pairs side by side puts four panels on a line
   and the reader loses which half belongs to which.
   ========================================================================== */
.lpair {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 26px;
  max-width: 860px;
  margin: 46px auto 0;
}
/* Desktop: two frames of the same wall, not one smeared picture. Butted edge to
   edge inside a single border they read as a continuous photograph and the
   before/after point is lost — so each half carries its own frame and the
   ground shows between them, with the same arrow the stacked layout uses. */
.lba {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  position: relative;
  margin: 0;
  line-height: 0;
}
.lba__f {
  display: block;
  min-width: 0;
  border: 4px solid #1c1c1c;
  border-radius: 2px;
}
.lba img { display: block; width: 100%; height: auto; }
.lba__arrow {
  display: block;
  width: 34px;
  height: 46px;
  margin: 0 16px;
  color: var(--c-amber);
  transform: rotate(-90deg);   /* the shared glyph points down; here it points right */
}
/* Only the wall pair carries one, and that is the point: an AFTER stripped to
   bare block reads as the rip-and-tear this page argues against until the
   caption says how little was opened. The counter pair needs no defending, so
   it gets no caption — a line under every picture would be decoration. */
.lba__cap {
  grid-column: 1 / -1;
  margin-top: 14px;
  font: 400 15.5px/23px var(--ff-body);
  color: var(--c-body);
  text-align: center;
}

/* =============================================================================
   sec06 — reviews
   ========================================================================== */
.lrevs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 30px;
  margin-top: 54px;
}
.lrev {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 32px 26px 28px;
  border: 1px solid rgba(251, 250, 248, .3);
  border-radius: 2px;
  text-align: center;
}
.lrev blockquote {
  margin: 0;
  font: 400 16px/25px var(--ff-body);
  color: rgba(251, 250, 248, .92);
}
.lrev cite {
  display: block;
  margin-top: 18px;
  font: 700 20px/23px var(--ff-display);
  font-style: normal;
  letter-spacing: .02em;
  color: var(--c-amber);
}
.lrev cite small {
  display: block;
  margin-top: 3px;
  font: 400 15px/20px var(--ff-body);
  letter-spacing: 0;
  color: rgba(251, 250, 248, .8);
}
.lstars { display: inline-flex; gap: 5px; margin-top: 13px; }
.lstars svg { width: 19px; height: 19px; flex-shrink: 0; fill: var(--c-amber); }

/* =============================================================================
   sec07 — the closing block: the ladder + the form behind its reveal
   ========================================================================== */
.lfinal {
  position: relative;
  padding: 76px 0 84px;
  background: var(--c-cream);
  text-align: center;
}
.lfinal h2 {
  max-width: 900px;
  margin: 0 auto;
  font: 700 42px/48px var(--ff-display);
  letter-spacing: .012em;
  text-transform: uppercase;
  color: #000;
}
.lfinal__sub {
  max-width: 720px;
  margin: 16px auto 0;
  font: 400 19px/27px var(--ff-body);
  color: var(--c-body);
}

/* The ladder is always visible — it is the explanation, not the form.
   Pictograms rather than numerals: the numerals belong to the form's own
   progress rail below, where the visitor is actually standing in a sequence. */
/* ONE component, not three floating fragments: a single rule across the top
   and hairlines between the columns. Three separate short top-borders read as
   a row of unrelated scraps under a centred heading. */
.lladder {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  max-width: 1000px;
  margin: 46px auto 0;
  padding: 30px 0 0;
  border-top: 3px solid #1c1c1c;
  list-style: none;
  text-align: left;
}
.lladder li {
  display: flex;
  align-items: flex-start;
  gap: 17px;
  padding-inline: 28px;
}
.lladder li:first-child { padding-left: 0; }
.lladder li:last-child { padding-right: 0; }
.lladder li + li { border-left: 1px solid #d0c6b9; }
.lladder svg {
  width: 62px;
  height: 58px;
  flex-shrink: 0;
  color: var(--c-amber);
  fill: none;
  stroke: currentColor;
  stroke-width: 3;
  stroke-linejoin: miter;
}
/* Two of the three headings take a second line and one does not, so without a
   floor the three bodies start at three different heights and the row reads
   ragged. Two lines of the 21/25 display face = 50px. */
.lladder b {
  display: block;
  min-height: 50px;
  font: 700 21px/25px var(--ff-display);
  letter-spacing: .02em;
  text-transform: uppercase;
  color: #000;
}
.lladder span {
  display: block;
  margin-top: 6px;
  font: 400 16.5px/24px var(--ff-body);
  color: var(--c-body);
}

/* =============================================================================
   FOOTER — the legal footer, because ad review needs the identity and the
   policy links on the destination page itself.
   ========================================================================== */
.lfoot {
  position: relative;
  padding: 44px 0 34px;
  background: var(--c-ink-2);
  color: var(--c-off);
  text-align: center;
}
.lfoot .logo {
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 13px;
  margin-bottom: 20px;
}
.lfoot .logo svg { width: 58px; height: 58px; }
.lfoot .logo b { font-size: 28px; line-height: 30px; }
.lfoot__phone {
  margin: 0 0 20px;
  font: 700 26px/30px var(--ff-display);
  letter-spacing: .03em;
}
.lfoot__phone a { color: var(--c-amber); text-decoration: none; text-underline-offset: 4px; }
.lfoot__phone a:hover, .lfoot__phone a:focus-visible { text-decoration: underline; }
.lfoot__legal {
  max-width: 820px;
  margin: 0 auto;
  font: 400 15px/23px var(--ff-body);
  color: rgba(251, 250, 248, .72);
}
.lfoot__legal + .lfoot__legal { margin-top: 9px; }
.lfoot__legal a {
  display: inline-block;
  padding-block: 3px;
  color: var(--c-amber);
  text-decoration: none;
  text-underline-offset: 3px;
}
.lfoot__legal a:hover, .lfoot__legal a:focus-visible { text-decoration: underline; }

/* =============================================================================
   THE PINNED CALL BAR, GATED

   On this lander the bar is held back until the visitor has scrolled past the
   villain band. Two reasons: the first screen should carry ONE amber fill (the
   hero CTA), and a call bar shown before the page has made its argument is
   asking for the call before there is a reason to make it.

   The trigger is a sentinel at that section's bottom edge watched by an
   IntersectionObserver (form.js) — not a scroll handler, and not a pixel
   count, so a 667px phone and a 932px one flip at the same place in the ARGUMENT.

   `[data-gated]` is set by script during parse, before the first paint, so:
     - JavaScript off  -> the attribute never lands, the bar behaves as before;
     - JavaScript on   -> the bar is hidden from the first frame, no flash.
   It appears INSTANTLY. No transition, no transform, no fade: it is an
   interface state changing, and the no-animation rule still owns the content.
   Body padding is reserved at all times by style.css (body{padding-bottom:56px}
   at <=900), which does not depend on the bar being visible — so nothing
   shifts when it arrives.
   ========================================================================== */
.callbar[data-gated]:not([data-on]) { display: none; }

/* the sentinel itself — absolute, so it is worth exactly 0px of layout */
.lgate {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}

/* =============================================================================
   RESPONSIVE — one markup, CSS only
   ========================================================================== */
@media (max-width: 1040px) {
  .lhero h1 { font-size: 48px; line-height: 54px; }
  .lhead h2, .lfinal h2 { font-size: 34px; line-height: 39px; }
  .lsplit { gap: 40px; }
  .lsplit h2 { font-size: 32px; line-height: 37px; }
  .lcards, .lwhy, .lrevs { gap: 22px; }
  .lwhy h3 { font-size: 23px; line-height: 27px; }
  .lladder { gap: 20px; }

  /* The seal hangs ~8.5% of the figure width past the frame. Above 1040 the
     page's own side margin absorbs it; from here down the content column is
     only 24px from the viewport edge, and at 1024 the seal was pushing the
     document 11px wide (measured). The figure gives the overhang its own room
     instead of borrowing the page's. */
  .lsplit__media { margin-right: 44px; }
}

@media (max-width: 900px) {
  .lhdr .wrap { padding-block: 12px; }
  .lhdr .logo svg { width: 46px; height: 46px; }
  .lhdr .logo b { font-size: 24px; line-height: 26px; }
  /* GHOST, not filled. On a phone the first screen was carrying three amber
     fills at once — this button, the hero CTA and the pinned call bar — and
     three primaries mean none of them is primary. The hero CTA keeps the fill;
     this drops to amber-on-charcoal with a hairline, which still measures
     7.7:1 for the label and 7.7:1 for the border, and still fills the row so
     the tap target is unchanged. */
  .lhdr__tel {
    font-size: 19px;
    padding: 9px 16px;
    background: none;
    border: 1px solid var(--c-amber);
    color: var(--c-amber);
  }
  .lhdr__tel:hover, .lhdr__tel:focus-visible {
    background: none;
    border-color: var(--c-amber-hi);
    color: var(--c-amber-hi);
  }
  .lhdr__tel:active { background: rgba(233, 169, 34, .14); }

  .lhero { padding: 50px 0 52px; }
  .lhero h1 { font-size: 34px; line-height: 39px; }
  .lhero__sub { margin-top: 16px; font-size: 18px; line-height: 26px; }
  .lhero__cta { margin-top: 24px; }
  .lhero__cta .btn { width: 100%; font-size: 21px; padding: 13px 20px; }

  /* Crop window, source rect (60, 140, 2440, 1630) — the box's own aspect-ratio
     carries it, so the percentages stay width-relative and therefore
     viewport-independent:
       width 2560/2440 = 104.92%   left -60/2440 = -2.46%
       top  -140 * (2440/1630) / 2440 = -8.59%  (top % resolves against the box
       HEIGHT, hence the extra aspect factor).
     81% of the frame: it trims the empty top-left sky and the cabinet edge and
     nothing else. */
  /* back to full bleed below 900: the inset plate is a desktop device */
  .lshot { overflow: hidden; aspect-ratio: 2440 / 1630; padding-inline: 0; }
  .lshot img {
    position: absolute;
    left: -2.46%;
    top: -8.59%;
    width: 104.92%;
    height: auto;
    max-width: none;
    margin-inline: 0;
    aspect-ratio: auto;
  }

  .lband { padding: 48px 0; }
  .lhead h2, .lfinal h2 { font-size: 27px; line-height: 32px; }
  .lhead p { font-size: 17px; line-height: 25px; }

  .lcards, .lwhy, .lrevs {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
    max-width: 520px;
    margin-inline: auto;
  }
  .lcards { margin-top: 46px; }
  .lway { margin-top: 44px; }
  .lway .btn { width: 100%; }

  .lsplit { grid-template-columns: minmax(0, 1fr); gap: 34px; }
  .lsplit h2 { font-size: 27px; line-height: 32px; }
  .lsplit__lead { font-size: 17px; line-height: 25px; }
  /* Capped so a near-square photo does not run a full column deep on a tablet,
     and inset by 48px so the seal's overhang (8.5% of the figure width to the
     right, measured) still has somewhere to go instead of pushing the page
     sideways at 390.
     An explicit WIDTH, not max-width: auto margins on a grid item switch it
     from stretch to fit-content sizing, and this figure's only child is
     absolutely positioned, so fit-content is 0 — it collapsed to 8px of border
     at every width below 900 (measured). A definite width takes that path
     away and still lets the auto margins centre it.
     Left-aligned rather than centred: the frame then lines up with the
     bullets above it, and the 48px it gives up on the right is exactly the
     gutter the seal hangs into. */
  .lsplit__media { width: min(460px, calc(100% - 48px)); margin-inline: 0 auto; }

  .lwhy { margin-top: 40px; }
  .lcentre { margin-top: 36px; }
  .lcentre .btn { width: 100%; }

  .lpair { gap: 20px; margin-top: 34px; }

  .lfinal { padding: 52px 0 60px; }
  .lfinal__sub { font-size: 17px; line-height: 25px; }
  .lladder {
    grid-template-columns: minmax(0, 1fr);
    max-width: 520px;
    margin-top: 34px;
    padding-top: 0;
    border-top: 0;
  }
  .lladder b { min-height: 0; }        /* stacked: nothing to align across */
  .lladder li { padding: 16px 0; border-top: 2px solid #1c1c1c; }
  .lladder li:last-child { border-bottom: 2px solid #1c1c1c; }
  .lladder li + li { border-left: 0; }
  .lladder svg { width: 50px; height: 47px; }

  .lfoot { padding: 34px 0 28px; }
  .lfoot .logo svg { width: 48px; height: 48px; }
  .lfoot .logo b { font-size: 24px; line-height: 26px; }
  .lfoot__phone { font-size: 22px; line-height: 26px; }
}

/* =============================================================================
   PHONES — THE PHOTOGRAPHY RUNS EDGE TO EDGE

   At 390 the content column is 342px, so a 24px gutter on each side is eating
   a sixth of every photograph — and on this page the photographs ARE the
   argument (a face, a job in progress, a wall before and after). Below 700
   every picture escapes the column and runs the full viewport width; the type
   around it keeps its gutter, which is what makes the pictures read as
   evidence rather than as illustrations of the paragraph.

   The escape is a negative margin of exactly the wrap's padding, NEVER 100vw:
   100vw counts the classic scrollbar gutter and would push the document
   sideways on any browser that reserves one.
   ========================================================================== */
@media (max-width: 700px) {

  /* --- the technician photo ---------------------------------------------
     Full width, and on a NEW CROP. The desktop crop keeps a corner of their
     red "FULL 1-YEAR WARRANTY" starburst inside the window and buries it under
     our seal — which works only because the seal is free to hang past the
     frame's right edge. Edge to edge there is nowhere to hang: measured, their
     red runs from x=404 to x=690 of the 692px source and therefore always
     touches the right edge of any window wider than 404, and a star whose
     inscribed radius is .465 of its own box can never reach an edge it is
     inside of. So the phone crop simply ends before their badge begins —
     source rect (0, 70, 400, 420), right edge 4px clear of their leftmost red
     pixel — and our seal sits inside the picture as the promise it is, not as
     a patch. Nothing red survives the crop, at any width. */
  .lsplit__media {
    width: auto;
    margin-inline: calc(var(--pad) * -1);
    border-width: 4px 0;             /* edge to edge: no side rules to eat in */
    border-radius: 0;
  }
  .lsplit__port { aspect-ratio: 400 / 420; }
  .lsplit__port img {
    top: -16.667%;                   /*  70 / 420 — the window's top edge */
    width: 173%;                     /* 692 / 400 — its left..right span   */
  }
  .lseal {
    left: auto;
    top: auto;
    right: 4%;
    bottom: 4%;
    width: 34%;
    transform: none;
  }

  /* --- the before/after pairs -------------------------------------------
     Stacked, not side by side. At 390 a side-by-side pair leaves each state
     about 190px wide and the mold — the entire point of the photograph —
     stops being visible. Before on top, after below, the arrow between them
     carrying the "and then" that the side-by-side seam carries on desktop. */
  .lpair {
    max-width: none;
    margin-inline: calc(var(--pad) * -1);
    gap: 38px;
  }
  .lba {
    grid-template-columns: minmax(0, 1fr);
    align-items: stretch;
  }
  .lba__f {
    border-width: 4px 0;      /* full-bleed: side rules would float in space */
    border-radius: 0;
  }
  .lba__arrow {
    justify-self: center;
    width: 46px;
    height: 62px;
    margin: 15px 0;
    transform: none;          /* stacked, so the glyph points down as drawn */
  }
  /* the pictures escape the column, the words do not */
  .lba__cap { padding-inline: var(--pad); }
}

/* Below ~560 the lockup and the phone button cannot share a row: the wordmark
   is `white-space: nowrap` and the button is `flex-shrink: 0`, so the pair sits
   at a hard 389px minimum and pushed the page 29px wide at 360. Stacking them
   fixes it at every width down to 320 AND puts a full-width call button in the
   first 100px of a paid-traffic page, which is where it belongs. It is still
   only ONE pinned bar on mobile — this header is static. */
@media (max-width: 560px) {
  .lhdr .wrap { flex-direction: column; align-items: center; gap: 12px; }
  .lhdr .logo { justify-content: center; }
  .lhdr__tel { width: 100%; justify-content: center; }

  /* Phones: the same window device, only slightly tighter than the tablet one.
     Source rect (100, 230, 2400, 1580):
       width 2560/2400 = 106.67%   left -100/2400 = -4.17%
       top  -230 * (2400/1580) / 2400 = -14.56%
     77% of the frame. The earlier square 2x zoom onto the face was there to
     push a competitor's polo mark out of shot; that mark is being rewritten out
     of the photo, so the zoom bought nothing and cost the whole scene — the
     machine, the window, the room. Both respirator cartridges must stay in
     frame: cropping x past 2300 clips the right one and the face reads broken. */
  .lshot { aspect-ratio: 2400 / 1580; }
  .lshot img { left: -4.17%; top: -14.56%; width: 106.67%; }

  /* Tightened so the face clears the fold. Measured at 390x844: with the
     ≤900 padding the photo started at 579 and the man's eyes sat at 729,
     barely above the 788px call-bar edge — the first screen was sky and a
     helmet. Trimming 32px of hero padding lifts the eyes to ~697 and puts
     roughly two thirds of the face on the first screen, which is the whole
     point of this photo. */
  .lhero { padding: 34px 0 36px; }
}

@media (max-width: 420px) {
  .lhdr .logo svg { width: 40px; height: 40px; }
  .lhdr .logo b { font-size: 21px; line-height: 23px; letter-spacing: .04em; }
  .lhdr__tel { font-size: 19px; padding: 10px 12px; gap: 8px; }
  .lhero h1 { font-size: 30px; line-height: 35px; }
  .lhead h2, .lfinal h2, .lsplit h2 { font-size: 24px; line-height: 29px; }
}
