@font-face{font-family:'Poppins';font-style:normal;font-weight:400;font-display:swap;src:url(/_fonts/poppins-400.woff2) format('woff2')}@font-face{font-family:'Poppins';font-style:normal;font-weight:700;font-display:swap;src:url(/_fonts/poppins-700.woff2) format('woff2')}@font-face{font-family:'Poppins';font-style:normal;font-weight:800;font-display:swap;src:url(/_fonts/poppins-800.woff2) format('woff2')}:root{--lp-accent:#1f6feb;--lp-accent-ink:#ffffff;--lp-accent-ink-soft:#b1cdf8;--lp-accent-ink-dim:#edf3fd;--lp-accent-soft:#e4eefd;--lp-accent-line:#cedffb;--lp-accent-hover:#1b62cf;--lp-ground:#ffffff;--lp-ground-alt:#f7f8fa;--lp-ink:#111827;--lp-ink-muted:#4b5563;--lp-line:#e3e7ec;--lp-line-strong:#cdd4dc;--lp-footer-bg:#101418;--lp-footer-ink:#c9d3e0;--lp-footer-muted:#8d99a8}*,*::before,*::after{box-sizing:border-box}body{margin:0;font-family:'Poppins',system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;font-size:1.0625rem;color:var(--lp-ink);background:var(--lp-ground);line-height:1.55;-webkit-text-size-adjust:100%}h1,h2,h3{font-family:'Poppins',system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;font-weight:800;line-height:1.15;margin:0;letter-spacing:-.01em}.lp-wrap{max-width:70rem;margin:0 auto}.lp-header{padding:.7rem 1.25rem;background:var(--lp-ground)}.lp-header .lp-wrap{display:flex;align-items:center;gap:.7rem}.lp-hero{padding:0}.lp-hero-copy{background:var(--lp-accent-soft);border-top:4px solid var(--lp-accent);padding:1.6rem 1.25rem 2.4rem}.lp-hero h1{font-size:clamp(2.05rem,7.6vw,3.45rem);line-height:1.08}
/* ── frame ──────────────────────────────────────────────────────────────── */
img{max-width:100%;height:auto}
a{color:var(--lp-accent)}
p{margin:0}
h2{font-size:clamp(1.7rem,5.6vw,2.5rem)}
h3{font-size:1.2rem}
.lp-ico{flex:none}
/* Every section carries the board's padding; `.lp-wrap` only centers the 1120px
   measure inside it. The hero is absent from this list on purpose: its ground
   moves between the section and the copy at the desktop breakpoint. */
.lp-services,.lp-trust,.lp-reviews,.lp-areas-sec,.lp-faq,.lp-cta,.lp-formsec{
  padding:2.75rem 1.25rem}
.lp-band{padding:2rem 1.25rem}
.lp-services,.lp-faq{background:var(--lp-ground-alt)}
.lp-reviews{background:var(--lp-accent-soft)}
.lp-formsec{background:var(--lp-ground-alt)}
/* A43 R2: a hairline at every ground change, so a short white section reads as a
   BAND rather than as a gap. Jack's words were that the sections "feel like just
   so much blank space" — an edge is what tells the eye a section ended. The
   tinted ones already announce themselves with their ground; these four do not. */
.lp-trust,.lp-areas-sec,.lp-services,.lp-faq{border-top:1px solid var(--lp-line)}
/* Q6 grounds. AFTER the per-kind rules on purpose: same specificity, so source
   order is what makes an owner's choice win over the rhythm. `lp-g-page` has to
   exist as a real rule — on a services or reviews section the plain ground IS an
   override, which is why absence and `page` are different answers. */
/* A66. The owner's own section: the shared padding and measure, and nothing
   else. Its shape is whatever they typed. */
.lp-custom{padding:2.75rem 1.25rem;border-top:1px solid var(--lp-line)}
.lp-custom h2{margin-bottom:.75rem}
.lp-custom p{max-width:68ch;margin-bottom:.75rem}
.lp-points{margin:0;padding-left:1.15rem;max-width:68ch}
.lp-points li{margin-bottom:.4rem}
.lp-g-page{background:var(--lp-ground)}
.lp-g-tint{background:var(--lp-ground-alt)}
.lp-g-accent{background:var(--lp-accent-soft)}
/* P6 A77/A78. SPECIFICITY, not source order: reasoning above `_stylesheet`. */
.lp-hero.lp-g-page{background:var(--lp-ground);
  border-bottom:1px solid var(--lp-line)}
.lp-hero.lp-g-tint{background:var(--lp-ground-alt)}
.lp-hero.lp-g-accent{background:var(--lp-accent-soft)}
.lp-g-page .lp-hero-copy{background:var(--lp-ground)}
.lp-g-tint .lp-hero-copy{background:var(--lp-ground-alt)}
.lp-g-accent .lp-hero-copy{background:var(--lp-accent-soft)}
/* A43 R2 for the kinds that are only white when the owner asks: the four that
   are white by rhythm already carry this hairline, these three never did.
   🔴 A `border-*-color` WITHOUT A STYLE DRAWS NOTHING. The first cut gave these
   three a color under `.lp-g-accent` and no border to color, so it was dead CSS
   with a live consequence: on a phone a tint or accent hero runs straight into
   the CTA below it in the same color with no rule between them. The edge has to
   be DECLARED here, per ground, and the resolver now counts an edge only when
   its style resolves so a repeat cannot read as fixed. */
.lp-reviews.lp-g-page,.lp-cta.lp-g-page,.lp-formsec.lp-g-page{
  border-top:1px solid var(--lp-line)}
.lp-reviews.lp-g-tint,.lp-cta.lp-g-tint,.lp-formsec.lp-g-tint,
.lp-reviews.lp-g-accent,.lp-cta.lp-g-accent,.lp-formsec.lp-g-accent{
  border-top:1px solid var(--lp-line-strong)}
.lp-g-accent .lp-trust-item::before,.lp-g-accent .lp-areas li{
  background:var(--lp-ground)}
.lp-g-tint .lp-trust-item::before,.lp-g-tint .lp-areas li{
  background:var(--lp-accent-line)}
/* 🔴 THE HAIRLINES GO WITH THE GROUND TOO. `--lp-line` is #e3e7ec, and a DARK
   accent's 12% wash lands on #e4e5e9: the two are 1.013:1 apart, so on an
   accent-grounded page every FAQ row rule, every service-card divider and every
   section edge simply stops existing. Measured against the wash: `--lp-line`
   1.013 (navy) / 1.033 (green) / 1.182 (yellow); `--lp-accent-line` would fix the
   first two and break the third (1.022); this neutral is 1.185 / 1.241 / 1.421,
   the only one of the three that is better everywhere.
   It lives in the palette as `LINE_STRONG` beside `LINE` (granted after this
   lane carried the numbers), so the sheet reads a token and ONE file owns the
   value. */
.lp-g-accent.lp-trust,.lp-g-accent.lp-areas-sec,.lp-g-accent.lp-services,
.lp-g-accent.lp-faq,.lp-g-accent.lp-custom{border-top-color:var(--lp-line-strong)}
/* 🔴 `.lp-g-accent.lp-faq` IS ONE ELEMENT, NOT TWO. The FAQ's rows live directly
   inside the section that carries the ground, so the descendant form
   (`.lp-g-accent .lp-faq details`) asks for a `.lp-faq` UNDER a `.lp-g-accent`
   and matches nothing. The service cards are a real descendant (`.lp-card` sits
   inside `.lp-services`), which is why the identical-looking selector works
   there and only the FAQ came back still invisible. */
.lp-g-accent .lp-card,.lp-g-accent.lp-faq details{border-bottom-color:var(--lp-line-strong)}
/* Only where the field sits ON the wash. The hero panel and the closing card are
   `--lp-ground`, and `--lp-line` is 1.242:1 there: a field on a white card keeps
   the hairline every other white card on the estate uses. */
.lp-g-accent.lp-formsec .lp-form input,.lp-g-accent.lp-formsec .lp-form textarea,
.lp-g-accent.lp-formsec .lp-form select{border-color:var(--lp-line-strong)}
/* A white card inside a section the owner grounded gets an edge. On the rhythm's
   own accent wash it reads without one, which is why absence is left alone. */
.lp-reviews.lp-g-page figure,.lp-reviews.lp-g-page>.lp-wrap>blockquote,
.lp-reviews.lp-g-tint figure,.lp-reviews.lp-g-tint>.lp-wrap>blockquote,
.lp-reviews.lp-g-accent figure,.lp-reviews.lp-g-accent>.lp-wrap>blockquote,
.lp-cta.lp-g-page .lp-cta-panel,.lp-cta.lp-g-tint .lp-cta-panel,
.lp-cta.lp-g-accent .lp-cta-panel{border:1px solid var(--lp-line)}
/* The hero's outline hover is the page ground by default, because the hero is
   the accent wash by default; a page or tinted hero wants the wash back. */
.lp-hero.lp-g-page .lp-ctarow .lp-btn-primary:hover,
.lp-hero.lp-g-tint .lp-ctarow .lp-btn-primary:hover{
  background:var(--lp-accent-soft);border-color:var(--lp-accent)}
.lp-cta.lp-g-page{background:var(--lp-ground)}
.lp-cta.lp-g-tint{background:var(--lp-ground-alt)}
.lp-cta.lp-g-accent{background:var(--lp-accent-soft)}
.lp-cta.lp-g-page,.lp-cta.lp-g-page h2,.lp-cta.lp-g-page p,
.lp-cta.lp-g-tint,.lp-cta.lp-g-tint h2,.lp-cta.lp-g-tint p,
.lp-cta.lp-g-accent,.lp-cta.lp-g-accent h2,.lp-cta.lp-g-accent p{
  color:var(--lp-ink)}
.lp-cta.lp-g-page>.lp-wrap>p,.lp-cta.lp-g-tint>.lp-wrap>p,
.lp-cta.lp-g-accent>.lp-wrap>p{color:var(--lp-ink-muted)}
/* The card's own inks, which `.lp-cta p` has always outranked: a white note on
   a white card, on every layout whose CTA owns the form. */
.lp-cta .lp-cta-panel p{color:var(--lp-ink)}
.lp-cta .lp-cta-panel .lp-form-note,
.lp-cta .lp-cta-panel .lp-opt{color:var(--lp-ink-muted)}
.lp-cta .lp-cta-panel .lp-req{color:#b3261e}
/* 🔴 THE CALL STAYS THE FILLED ONE. The band fills the phone and outlines the
   quote; a ground must not reorder the owner's two asks, and the first cut did:
   it handed the CTA the PAGE default (quote filled, call outline), which flipped
   the emphasis AND put the raw accent on a light ground as the phone number's
   ink. On a pale accent that is 1.42:1, unreadable, and it was readable at
   12.63:1 one ground earlier, so the CONTROL broke it and P16's warn-only does
   not cover it. Filled buttons carry `--lp-accent-ink`, which `readable_ink`
   derives, so the phone is legible at every accent on every ground. */
.lp-cta.lp-g-page .lp-ctarow .lp-btn-call,
.lp-cta.lp-g-tint .lp-ctarow .lp-btn-call,
.lp-cta.lp-g-accent .lp-ctarow .lp-btn-call{background:var(--lp-accent);
  color:var(--lp-accent-ink);border-color:var(--lp-accent)}
.lp-cta.lp-g-page .lp-ctarow .lp-btn-call:hover,
.lp-cta.lp-g-tint .lp-ctarow .lp-btn-call:hover,
.lp-cta.lp-g-accent .lp-ctarow .lp-btn-call:hover{
  background:var(--lp-accent-hover);border-color:var(--lp-accent-hover)}
/* 🔴 THE OUTLINE LABEL IS THE PAGE INK, NOT THE ACCENT, and this is the second
   half of the same lesson. Filling the call button fixed the phone and moved the
   defect to the quote button: an outline label in the RAW accent is 1.42:1 on
   white for a pale accent, where the band had it at 12.51:1. Both buttons on a
   grounded CTA are legible at every accent only if NEITHER label is the owner's
   color. The accent stays as the border, which is what still says the button is
   ours. (The hero's outline label IS the raw accent and stays that way: it reads
   the same with a ground and without one, so P16 governs it, not this lane.) */
.lp-cta.lp-g-page .lp-ctarow .lp-btn-primary,
.lp-cta.lp-g-tint .lp-ctarow .lp-btn-primary,
.lp-cta.lp-g-accent .lp-ctarow .lp-btn-primary{background:transparent;
  color:var(--lp-ink);border-color:var(--lp-accent)}
.lp-cta.lp-g-page .lp-ctarow .lp-btn-primary:hover,
.lp-cta.lp-g-tint .lp-ctarow .lp-btn-primary:hover{
  background:var(--lp-accent-soft);border-color:var(--lp-accent)}
.lp-cta.lp-g-accent .lp-ctarow .lp-btn-primary:hover{background:var(--lp-ground);
  border-color:var(--lp-accent)}
/* The desktop half of the hero-hover overrides is at the END of this
   sheet's own 48rem block, not in a second one: `_media_block` in
   test_lp_render.py slices by FIRST occurrence, so a second block
   would silently re-aim the A42 pins at mine. */

/* ── header ─────────────────────────────────────────────────────────────── */
.lp-brandline{display:flex;align-items:center;gap:.6rem;min-width:0}
.lp-bizname{line-height:1.2;min-width:0}
.lp-logo{display:block;height:38px;width:auto;border-radius:9px;flex:none}
/* Hidden on a phone: the hero's Call button and the sticky bar already carry the
   number, and a third one crowds a 390px header off the line. */
.lp-header .lp-headcall{margin-left:auto;display:none;min-height:2.75rem;
  font-size:1rem;padding:.6rem 1.1rem}

/* ── hero ───────────────────────────────────────────────────────────────── */
.lp-hero-grid{display:grid}
.lp-hero-copy>p{margin:.85rem 0 0}
.lp-sub{font-size:1.125rem;line-height:1.45;color:var(--lp-ink-muted)}
.lp-trustbar{display:flex;flex-direction:column;gap:.55rem;margin:1.35rem 0 0;
  padding-top:1.1rem;border-top:1px solid var(--lp-accent-line);font-size:.94rem;
  color:var(--lp-ink-muted)}
.lp-hero-panel{background:var(--lp-ground);border:1px solid var(--lp-accent-line);
  border-top:4px solid var(--lp-accent);border-radius:.75rem;padding:1.35rem;
  margin:2rem 1.25rem}
.lp-panel-title{font-size:1.5rem;margin:0 0 .95rem}
.lp-hero-center .lp-hero-copy{text-align:center;max-width:44rem;margin:0 auto}
/* 🔴 A42 D2. `text-align:center` centers the WORDS INSIDE a box; it does not
   center the box. `.lp-sub` is capped at 33rem on desktop (see the 48rem block),
   so without these auto margins the supporting line sat in a 33rem box hugging
   the left edge of a 70rem wrap — a left-of-center paragraph under a centered
   headline, which is the most visible half of "the text is off center". */
.lp-hero-center .lp-sub{margin-left:auto;margin-right:auto}
/* A42 D4: `align-items:center` USED TO BE HERE and it was wrong in both
   directions. Below 40rem `.lp-ctarow` is a COLUMN, so it shrank each button to
   its text width while the other layouts stretch theirs full width (the research
   rule for phones). Above 40rem the row's own rule already sets it. What the
   centered hero actually needs is `justify-content` on the MAIN axis, which is in
   the 40rem block. */

/* ── buttons ────────────────────────────────────────────────────────────── */
.lp-ctarow{display:flex;flex-direction:column;gap:.75rem;margin:1.5rem 0 0}
.lp-btn{display:flex;align-items:center;justify-content:center;gap:.6rem;
  min-height:3.5rem;padding:.8rem 1.6rem;border-radius:.5rem;font-weight:700;
  font-size:1.125rem;line-height:1.2;text-decoration:none;
  border:2px solid var(--lp-accent);background:var(--lp-accent);
  color:var(--lp-accent-ink)}
.lp-btn:hover{background:var(--lp-accent-hover);border-color:var(--lp-accent-hover)}
.lp-btn-call{background:transparent;color:var(--lp-accent)}
.lp-btn-call:hover{background:var(--lp-accent-soft);border-color:var(--lp-accent)}
/* On a phone the CALL leads and the quote is the outline: the form is a scroll
   away and emergency intent dials. The desktop block puts the quote back first. */
.lp-hero .lp-ctarow .lp-btn-primary{background:transparent;color:var(--lp-accent)}
.lp-hero .lp-ctarow .lp-btn-primary:hover{background:var(--lp-ground);
  border-color:var(--lp-accent)}
.lp-hero .lp-ctarow .lp-btn-call{order:-1;background:var(--lp-accent);
  color:var(--lp-accent-ink)}
.lp-hero .lp-ctarow .lp-btn-call:hover{background:var(--lp-accent-hover);
  border-color:var(--lp-accent-hover)}
.lp-callline{margin:1.1rem 0 0;font-weight:700}

/* ── the accent bands (mid-page and closing) ────────────────────────────── */
/* No second solid CTA color (P24): the bands are the accent, and the two buttons
   on them are the ink and an outline OF the ink, so a page never shows a color
   the owner did not pick. */
.lp-band,.lp-cta{background:var(--lp-accent);color:var(--lp-accent-ink)}
.lp-cta{text-align:center}
.lp-cta h2,.lp-cta p{color:var(--lp-accent-ink)}
.lp-cta>.lp-wrap>p{margin:.85rem auto 0;max-width:40rem;font-size:1.0625rem;
  color:var(--lp-accent-ink-dim)}
.lp-band .lp-ctarow{margin:0;align-items:center;justify-content:center}
.lp-cta .lp-ctarow{margin:1.15rem 0 0}
.lp-cta .lp-ctarow{align-items:center}
.lp-band .lp-ctarow .lp-btn-call,.lp-cta .lp-ctarow .lp-btn-call{order:-1;
  background:var(--lp-accent-ink);color:var(--lp-accent);
  border-color:var(--lp-accent-ink)}
.lp-band .lp-ctarow .lp-btn-call:hover,.lp-cta .lp-ctarow .lp-btn-call:hover{
  background:var(--lp-accent-ink-dim);border-color:var(--lp-accent-ink-dim)}
.lp-band .lp-ctarow .lp-btn-primary,.lp-cta .lp-ctarow .lp-btn-primary{
  background:transparent;color:var(--lp-accent-ink);
  border-color:var(--lp-accent-ink-soft)}
.lp-band .lp-ctarow .lp-btn-primary:hover,.lp-cta .lp-ctarow .lp-btn-primary:hover{
  background:transparent;border-color:var(--lp-accent-ink)}
.lp-cta-panel{background:var(--lp-ground);color:var(--lp-ink);text-align:left;
  border-radius:.75rem;padding:1.35rem;margin:1.5rem auto 0;max-width:30rem}

/* ── three-up trust ─────────────────────────────────────────────────────── */
.lp-trustlist{list-style:none;padding:0;margin:1.4rem 0 0;display:grid;gap:1.5rem}
/* A43 R6 (measure): a line of prose stops being comfortable past ~45rem. These
   three run full width in a 70rem wrap otherwise. */
.lp-trust-item{position:relative;padding-left:3.5rem;min-height:2.75rem;
  display:flex;align-items:center;font-size:1.0625rem;max-width:45rem}
.lp-trust-item::before{content:'';position:absolute;left:0;top:0;width:2.75rem;
  height:2.75rem;border-radius:50%;background:var(--lp-accent-soft)}
.lp-trust-item::after{content:'';position:absolute;left:1.05rem;top:.9rem;
  width:.5rem;height:.85rem;border:solid var(--lp-accent);
  border-width:0 .16rem .16rem 0;transform:rotate(45deg)}

/* ── services, as a checked list rather than cards ──────────────────────── */
.lp-lede{margin:.5rem 0 0;font-size:1.0625rem;color:var(--lp-ink-muted);max-width:45rem}
.lp-cards{list-style:none;padding:0;margin:1.2rem 0 0;display:grid;gap:0 3.5rem}
.lp-card{position:relative;padding:1rem 0 1rem 2rem;
  border-bottom:1px solid var(--lp-line)}
.lp-card::before{content:'';position:absolute;left:.2rem;top:1.35rem;width:.5rem;
  height:.85rem;border:solid var(--lp-accent);border-width:0 .16rem .16rem 0;
  transform:rotate(45deg)}
.lp-card h3{font-family:inherit;font-weight:700;font-size:1.0625rem;
  letter-spacing:0;margin:0}
.lp-card p{margin:.15rem 0 0;font-size:1rem;color:var(--lp-ink-muted)}

/* ── reviews ────────────────────────────────────────────────────────────── */
.lp-reviews>.lp-wrap>*{margin:.9rem 0 0}
.lp-reviews>.lp-wrap>h2{margin:0}
.lp-reviews figure,.lp-reviews>.lp-wrap>blockquote{background:var(--lp-ground);
  border-radius:.75rem;padding:1.25rem}
.lp-reviews figure blockquote{margin:0;background:none;padding:0}
blockquote{margin:0;font-size:1.0625rem;color:var(--lp-ink)}
figcaption{margin:.75rem 0 0;font-size:.92rem;color:var(--lp-ink-muted)}
.lp-stat{font-weight:700;font-size:1.15rem}

/* ── service area ───────────────────────────────────────────────────────── */
.lp-areas-sec>.lp-wrap>p{margin:.8rem 0 0;font-size:1.0625rem;max-width:45rem}
.lp-areas{list-style:none;padding:0;margin:1rem 0 0;display:flex;flex-wrap:wrap;
  gap:.45rem}
.lp-areas li{background:var(--lp-accent-soft);border-radius:1rem;
  padding:.3rem .85rem;font-size:.95rem}

/* ── FAQ ────────────────────────────────────────────────────────────────── */
.lp-faq details{border-bottom:1px solid var(--lp-line);padding:1rem 0}
.lp-faq .lp-wrap>details:first-of-type{margin-top:1.2rem}
summary{display:flex;align-items:center;gap:.75rem;cursor:pointer;font-weight:700;
  font-size:1.09rem;list-style:none}
summary::-webkit-details-marker{display:none}
summary::after{content:'';flex:none;margin-left:auto;width:.55rem;height:.55rem;
  border:solid var(--lp-ink-muted);border-width:0 .13rem .13rem 0;
  transform:translateY(-.15rem) rotate(45deg)}
details[open] summary::after{transform:translateY(.1rem) rotate(-135deg)}
.lp-faq details p{margin:.65rem 0 0;max-width:45rem;color:var(--lp-ink-muted)}

/* ── the one lead form ──────────────────────────────────────────────────── */
.lp-form{display:grid;gap:.85rem;margin-top:1rem}
.lp-hero-panel .lp-form,.lp-cta-panel .lp-form{margin-top:0}
.lp-form label{display:block;font-size:.94rem;font-weight:700;margin-bottom:.35rem}
.lp-req{color:#b3261e}
.lp-opt{font-weight:400;color:var(--lp-ink-muted)}
.lp-form input,.lp-form textarea{display:block;padding:.8rem .875rem;
  border:1px solid var(--lp-line);border-radius:.5rem;font:inherit;font-size:1rem;
  background:var(--lp-ground);color:var(--lp-ink);width:100%}
.lp-form input{height:3.25rem;padding:0 .875rem}
/* WP22 + P4: the choice lists and boxes an owner-shaped form can carry. */
.lp-form select{display:block;width:100%;height:3.25rem;padding:0 .875rem;
  font:inherit;color:var(--lp-ink);background:#fff;
  border:1px solid var(--lp-line);border-radius:8px}
/* A39 photos. A FIXED ASPECT BOX plus cover: the space is reserved before the
bytes arrive so nothing shifts, and any upload aspect fills it without being
stretched. This is what makes width/height attributes unnecessary, which is what
keeps a Pillow decode out of a renderer that has to be byte-deterministic. */
.lp-photo{display:block;width:100%;max-width:100%;height:auto;aspect-ratio:3/2;
object-fit:cover;border-radius:10px;margin:1.4rem 0 0}
.lp-photoband{padding:0}
.lp-photoband .lp-photo{margin:0;border-radius:0;aspect-ratio:5/2;max-height:340px}
@media(max-width:720px){.lp-photoband .lp-photo{aspect-ratio:3/2;max-height:none}}

.lp-form input[type="checkbox"],.lp-form input[type="radio"]{display:inline-block;
  width:auto;height:auto;margin:.15rem .5rem 0 0;padding:0;flex:none;
  accent-color:var(--lp-accent)}
.lp-form .lp-check label{display:flex;align-items:flex-start;font-weight:500;
  line-height:1.45}
.lp-form fieldset{border:0;padding:0;margin:0;min-width:0;display:grid;gap:.4rem}
.lp-form legend{display:block;padding:0;font-size:.94rem;font-weight:700;
  margin-bottom:.35rem}
.lp-form input:focus,.lp-form textarea:focus,.lp-form select:focus{outline:2px solid var(--lp-accent);
  outline-offset:1px}
.lp-form .lp-btn-primary{width:100%;margin-top:.15rem;font:inherit;
  font-size:1.125rem;font-weight:700;cursor:pointer;background:var(--lp-accent);
  color:var(--lp-accent-ink);border-color:var(--lp-accent)}
.lp-form .lp-btn-primary:hover{background:var(--lp-accent-hover);
  border-color:var(--lp-accent-hover)}
.lp-form-note{margin:.15rem 0 0;font-size:.8rem;color:var(--lp-ink-muted)}
.lp-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* ── footer ─────────────────────────────────────────────────────────────── */
.lp-footer{background:var(--lp-footer-bg);color:var(--lp-footer-ink);
  padding:2.25rem 1.25rem 5.5rem}
.lp-footer a{color:#fff}
.lp-footer p{margin:.4rem 0 0;font-size:.97rem}
.lp-footer .lp-nap{font-size:1.15rem;color:#fff;margin:0}
.lp-footer .lp-byline{margin:.9rem 0 0;font-size:.9rem;color:var(--lp-footer-muted)}

/* ── the sticky mobile bar (P24) ────────────────────────────────────────── */
.lp-callbar{position:fixed;left:0;right:0;bottom:0;z-index:20;display:grid;
  grid-auto-flow:column;grid-auto-columns:1fr;gap:1px;
  background:var(--lp-accent-hover);
  padding-bottom:env(safe-area-inset-bottom)}
.lp-callbar a{display:flex;align-items:center;justify-content:center;gap:.4rem;
  height:3.5rem;padding:0 .5rem;background:var(--lp-accent);
  color:var(--lp-accent-ink);font-weight:700;font-size:.95rem;white-space:nowrap;
  text-decoration:none}
/* Hidden while a form field has focus: the keyboard eats up to 60% of the
   screen, and the bar lands on the submit button. Pure CSS, no script — the
   page carries none. A browser without `:has()` simply keeps the bar, which is
   what every browser did before this rule existed. */
body:has(.lp-form:focus-within) .lp-callbar{display:none}
body{padding-bottom:3.6rem}

@media(min-width:40rem){
  .lp-callbar{display:none}
  body{padding-bottom:0}
  .lp-ctarow{flex-direction:row;flex-wrap:wrap;align-items:center;gap:.875rem}
  .lp-btn{padding:.95rem 1.7rem}
  .lp-cta .lp-ctarow{justify-content:center}
  .lp-trustbar{flex-direction:row;flex-wrap:wrap;gap:1.15rem;align-items:center}
  /* 🔴 A42 D1/D3. The MAIN axis, which is what centers a row. Once `.lp-ctarow`
     flips to `flex-direction:row` just above, the centered hero's only old rule
     (`align-items:center`) governed the CROSS axis, so the Quote and Call
     buttons sat flush LEFT under a centered H1. `.lp-cta .lp-ctarow` two lines up
     has always done this correctly for the accent band; the hero never got the
     equivalent. Same for the trust strip, which wraps into a row here too. */
  .lp-hero-center .lp-ctarow,.lp-hero-center .lp-trustbar{justify-content:center}
  /* A43 R4: thin content fills the row instead of leaving a ragged gap — one
     trust item becomes one wide cell, two become halves. */
  .lp-cards{grid-template-columns:repeat(auto-fit,minmax(20rem,1fr))}
}
@media(min-width:48rem){
  .lp-header .lp-headcall{display:flex}
  .lp-logo{height:44px;border-radius:10px}
  .lp-bizname{font-size:1.25rem}
  /* A43 R4: auto-fit so one or two trust items fill the row instead of
     leaving two empty thirds. Three still lay out as three. */
  .lp-trustlist{grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));gap:2.5rem}
  .lp-reviews>.lp-wrap{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
    gap:1.375rem;align-items:start}
  .lp-reviews>.lp-wrap>*{margin:0}
  .lp-reviews>.lp-wrap>h2,.lp-reviews>.lp-wrap>p{grid-column:1/-1}
  .lp-services,.lp-trust,.lp-reviews,.lp-areas-sec,.lp-faq,.lp-cta,
  .lp-formsec{padding:4rem 2.5rem}
  .lp-band{padding:2.75rem 2.5rem}
  .lp-footer{padding:3rem 2.5rem}
  .lp-header{padding:1rem 2.5rem}
  /* The desktop hero: the tint becomes the whole band and the form card sits in
     it beside the copy, so the ground moves from the copy to the section. */
  .lp-hero{background:var(--lp-accent-soft);border-top:4px solid var(--lp-accent);
    border-bottom:1px solid var(--lp-accent-line);padding:3.5rem 2.5rem 3.75rem}
  .lp-hero-copy{background:none;border-top:0;padding:0}
  .lp-hero-panel{margin:0;padding:1.75rem}
  .lp-hero-grid{grid-template-columns:1.1fr .9fr;gap:3rem;align-items:start}
  .lp-hero .lp-ctarow .lp-btn-call{order:0;background:transparent;
    color:var(--lp-accent)}
  .lp-hero .lp-ctarow .lp-btn-call:hover{background:var(--lp-ground);
    border-color:var(--lp-accent)}
  .lp-hero .lp-ctarow .lp-btn-primary{background:var(--lp-accent);
    color:var(--lp-accent-ink)}
  .lp-hero .lp-ctarow .lp-btn-primary:hover{background:var(--lp-accent-hover);
    border-color:var(--lp-accent-hover)}
  /* 🔴 A42 F2: "Call first" means the CALL is first. The four rules above are
     the desktop default and they put the quote button first and filled, which
     is right for Lead capture and exactly backwards for the layout whose card
     promises "big phone number". These come AFTER them on purpose: same
     specificity plus one class, so source order decides and the pair reads as
     default-then-override rather than a specificity puzzle. */
  .lp-hero .lp-ctarow-call .lp-btn-call{order:-1;background:var(--lp-accent);
    color:var(--lp-accent-ink)}
  .lp-hero .lp-ctarow-call .lp-btn-call:hover{background:var(--lp-accent-hover);
    border-color:var(--lp-accent-hover)}
  .lp-hero .lp-ctarow-call .lp-btn-primary{background:transparent;
    color:var(--lp-accent)}
  .lp-hero .lp-ctarow-call .lp-btn-primary:hover{background:var(--lp-ground);
    border-color:var(--lp-accent)}
  .lp-sub{font-size:1.3rem;max-width:33rem}
  .lp-panel-title{font-size:1.625rem}
  .lp-form input,.lp-form select{height:3.125rem}
  .lp-reviews figure,.lp-reviews>.lp-wrap>blockquote{padding:1.6rem}
  .lp-card p{font-size:1.03rem}
  /* P6 A78, the desktop half. This width swaps which of the hero's two buttons
     is the outline, so the ground override swaps with it, and the FILLED pair is
     restated at the ground's own specificity because the base rule would
     otherwise reach in here and un-fill it. */
  .lp-hero.lp-g-page .lp-ctarow .lp-btn-call:hover,
  .lp-hero.lp-g-tint .lp-ctarow .lp-btn-call:hover{
    background:var(--lp-accent-soft);border-color:var(--lp-accent)}
  .lp-hero.lp-g-page .lp-ctarow .lp-btn-primary:hover,
  .lp-hero.lp-g-tint .lp-ctarow .lp-btn-primary:hover{
    background:var(--lp-accent-hover);border-color:var(--lp-accent-hover)}
  /* 🔴 CALL-FIRST SWAPS THEM, AND THESE MUST COME AFTER. `.lp-ctarow-call` is
     the SAME specificity as `.lp-ctarow` here (both add one class to the same
     chain), so source order alone decides, exactly as A42 F2 does twelve lines
     up. Interleaved with the defaults above, the default `.lp-ctarow` rule won
     for a call-first row and hovered the OUTLINE button to `--lp-accent-hover`,
     leaving accent-colored text on an accent-colored fill: 1.07:1 for a navy
     accent. Caught by this lane's own filled-button pin, not by reading. */
  .lp-hero.lp-g-page .lp-ctarow-call .lp-btn-call:hover,
  .lp-hero.lp-g-tint .lp-ctarow-call .lp-btn-call:hover{
    background:var(--lp-accent-hover);border-color:var(--lp-accent-hover)}
  .lp-hero.lp-g-page .lp-ctarow-call .lp-btn-primary:hover,
  .lp-hero.lp-g-tint .lp-ctarow-call .lp-btn-primary:hover{
    background:var(--lp-accent-soft);border-color:var(--lp-accent)}
}
@media(min-width:64rem){
  .lp-services,.lp-trust,.lp-reviews,.lp-areas-sec,.lp-faq,.lp-cta,
  .lp-formsec{padding:5rem}
  .lp-band{padding:3.25rem 5rem}
  .lp-footer{padding:3rem 5rem}
  .lp-header{padding:1rem 5rem}
  .lp-hero{padding:4rem 5rem 4.25rem}
  .lp-hero-grid{gap:3.5rem}
  .lp-trustlist{gap:2.75rem}
}
.lp-legalpage{max-width:44rem;padding:2.5rem 1.25rem}

/* ── Wave D: service-card photos, the carousel, the logo sizes ────────────
   Lane 5-F's ONE contiguous block in this stylesheet (announced in NOTES;
   `_stylesheet` otherwise belongs to 5-E this round). Everything here is
   CSS-only by requirement, not by preference: a published page carries no
   script but the frozen token script.

   🔴 THE ANCHOR IS THE END OF THE STYLESHEET, ONE RULE EARLY. 5-E asked for this
   block after the WP20 underline rule; `test_lp_render.py::
   test_the_underline_rule_is_still_last_and_unindented` pins that rule as the
   LAST one, so going after it reds a guard. Sitting immediately BEFORE it is the
   same end-of-file seam, is outside every region 5-E announced, and needs no
   edit to a pin — weakening a guard to fit a placement that had a one-line
   alternative is not a trade worth making. Source order still puts these rules
   after the desktop media block, which is what the logo sizes need. */
.lp-photo-card{aspect-ratio:4/3;margin:0 0 .8rem;border-radius:10px}
/* With a thumbnail the bullet rule is noise, and the left indent it reserved is
   space the image wants. The bullet stays for every text-only grid. */
.lp-cards-photos .lp-card{padding-left:0}
.lp-cards-photos .lp-card::before{display:none}
/* The carousel: native horizontal overflow plus scroll-snap. No dots and no
   arrows, because either would want a script. `overscroll-behavior-x:contain`
   keeps a swipe inside the row from walking the whole page back. */
.lp-cards-carousel{display:flex;grid-template-columns:none;overflow-x:auto;
  scroll-snap-type:x mandatory;overscroll-behavior-x:contain;gap:1.5rem;
  padding-bottom:.5rem;-webkit-overflow-scrolling:touch}
.lp-cards-carousel .lp-card{scroll-snap-align:start;flex:0 0 min(20rem,78%)}
@media(prefers-reduced-motion:reduce){.lp-cards-carousel{scroll-behavior:auto}}
/* D2/A55. Two classes, not three: `m` is the DEFAULT and emits no class at all,
   so a page that never chose a size renders byte-for-byte as it did before this
   feature existed. The doubled selector is belt-and-braces: at THIS anchor these
   rules already win on source order, but the specificity means they keep winning
   if the block is ever moved again. */
.lp-logo.lp-logo-s{height:32px}
.lp-logo.lp-logo-l{height:60px}

/* ── P6-D (A80): the owner section's layouts ─────────────────────────────
   Lane 6-D1's ONE contiguous block: the END of the Wave D block, immediately
   BEFORE the WP20 underline rule (which a pin keeps last). Same seam 5-F chose,
   for the same reason. CSS-only by requirement: the photo row is scroll-snap,
   the columns are `column-count`, the picture-beside-text is a grid whose
   DOM order (picture first) is the mobile order and whose desktop order is
   `order`, so the markup is one shape for every viewport. */
.lp-figure{margin:0 0 1rem}
.lp-photo-custom{margin:0}
/* 🔴 A PICTURE THAT STACKS UNDER TEXT IS CAPPED BY WIDTH, and the screenshot
   matrix is what said so twice. A picture in an owner's section is 3:2 like
   every other, so at the full `lp-wrap` width it comes out 1120 x 745 — in a
   text, `two_columns` or `faq` section, whose point is words, two of those are
   a wall with a paragraph on top and the section is 1900px for 200px of copy.
   Capping the HEIGHT was the first answer and it was the wrong axis: it cropped
   a full-width band instead of making the picture a picture (the review read it
   as a 1120 x 510 wall, which it was).
   ONE cap for every layout that STACKS — text, two columns, faq, and the extra
   pictures beside picture-left/right — left-aligned with the copy, cropping on
   the owner's own focal point because `object-position` is already set from
   `photo_focus`. The two layouts that size a picture deliberately opt out below:
   the photo ROW sizes by flex-basis, and picture-left/right's column IS the
   picture. */
.lp-custom .lp-figure{max-width:32rem}
.lp-custom-fig .lp-figure,.lp-photo-row .lp-figure{max-width:none}
/* And the picture after the two-column block needs the gap every other stacked
   thing has: `.lp-figure`'s margin is bottom-only, so the first figure after the
   columns sat flush against the last line of text. */
.lp-custom-cols+.lp-figure{margin-top:1.2rem}
.lp-custom figcaption{margin:.5rem 0 0}
/* The pairs: `.lp-faq details`' twins, scoped to the owner section. */
.lp-custom details{border-bottom:1px solid var(--lp-line);padding:1rem 0}
.lp-custom details p{margin:.65rem 0 0;max-width:45rem;color:var(--lp-ink-muted)}
/* Picture beside text. One column on a phone with the picture first (its DOM
   position); two columns from 48rem with the picture on the side the owner
   chose. `minmax(0, …)` so a long word cannot blow the column out. */
.lp-custom-grid{display:grid;gap:1.25rem;align-items:start}
.lp-custom-grid .lp-figure{margin:0}
/* ...except the EXTRA pictures, which stack inside the copy column and
   would otherwise sit flush against each other: the rule above is for the
   picture COLUMN, whose figure is the only thing in it. */
.lp-custom-copy .lp-figure{margin:0 0 1rem}
.lp-custom-copy h2{margin-top:0}
/* The photo row: native horizontal overflow plus scroll-snap, the carousel's
   idiom. No dots and no arrows, because either would want a script. */
.lp-photo-row{display:flex;gap:1rem;overflow-x:auto;scroll-snap-type:x mandatory;
  overscroll-behavior-x:contain;padding-bottom:.5rem;margin:.25rem 0 1rem;
  -webkit-overflow-scrolling:touch}
.lp-photo-row .lp-figure{flex:0 0 min(24rem,78%);scroll-snap-align:start;margin:0}
@media(prefers-reduced-motion:reduce){.lp-photo-row{scroll-behavior:auto}}
/* Two columns: paragraphs and points flow across two columns from 48rem; the
   measure rule is lifted because the column IS the measure now. */
.lp-custom-cols p,.lp-custom-cols .lp-points{break-inside:avoid;max-width:none}
@media(min-width:48rem){
  .lp-custom-grid{grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:2rem}
  .lp-pic-right .lp-custom-fig{order:2}
  .lp-custom-cols{column-count:2;column-gap:2.5rem}
}

/* WP20: an underline that reads as emphasis, not as a link (P18). */
u{text-decoration-thickness:.09em;text-underline-offset:.18em;
  text-decoration-color:currentColor}
