/* ============================================================
   NJ INDOOR OUTDOOR MAINTENANCE, LLC — site.css

   Structure is the Home Built And Renovations build, unchanged:
   dark cinematic video hero with the quote panel alongside it,
   fully-rounded pills, one high-chroma accent, and the nav that
   is transparent over the hero then solid once it is behind you.

   Reskinned to this brand: Montserrat (from the reference site)
   in place of Poppins, and the logo's blue as the accent. The
   headline carries the reference site's accent bar behind one
   word — see .mark.
   ============================================================ */

:root {
  /* Dark — pulled toward the logo's navy rather than neutral black. */
  --ink:       #0B1226;
  --ink-2:     #121C3A;
  --ink-deep:  #060A16;

  /* Light surfaces */
  --paper:     #FFFFFF;
  --paper-2:   #F5F6F9;
  --line:      #E4E7EE;

  /* Type on light */
  --text:      #0B1226;
  --text-2:    #4C5265;
  --text-3:    #767C90;

  /* The logo's blue, opened up. A literal navy (#1B2A5B, the shade in the
     mark itself) is only ~4% luminance away from --ink, so as the hero
     underline and the button fill it would read as a hole in the dark
     rather than an accent. This keeps the hue and lifts the value. */
  --accent:     #2F6FE5;
  --accent-hi:  #4B87F2;
  --accent-dim: rgba(47, 111, 229, 0.34);

  /* The green from the logo's ellipse. Used sparingly — the eco/recycling
     claims are the only place their brand actually spends it. */
  --leaf:       #6FAF3E;

  --white:    #FFFFFF;
  --white-80: rgba(255,255,255,.80);
  --white-60: rgba(255,255,255,.60);

  --font: 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --page-max: 1240px;
  --gutter:   28px;
  --nav-h:    104px;

  --r-card: 18px;
}

*, *::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;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.65;
  color: var(--text-2);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

/* ============================================================
   NO SIDEWAYS SCROLL — same guard as the v2 build

   This was `overflow-x: hidden` on body alone, which does less than
   it looks like it does. Overflow PROPAGATES from body to the
   viewport when html is `visible`: the viewport takes the hidden and
   body's own overflow computes back to `visible`, so body never
   clips its own content — it only suppresses the scrollbar. iOS
   Safari will still pan through it.

   Now declared on the ROOT, where `hidden` is safe for sticky
   positioning (the root's overflow propagates to the viewport and
   its own used value becomes visible, so no scroll container forms),
   with `clip` upgrading it where supported. `clip` actually clips
   and, unlike `hidden`, never creates a scroll container.
   ============================================================ */
html { overflow-x: hidden; }
@supports (overflow: clip) {
  html, body { overflow-x: clip; }
}

img, video { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }

.container { max-width: var(--page-max); margin: 0 auto; padding: 0 var(--gutter); }
.section { padding: 104px 0; }
@media (max-width: 780px) { .section { padding: 68px 0; } }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--accent); color: #FFFFFF;
  padding: 12px 20px; font-weight: 600;
}
.skip-link:focus { left: 0; top: 0; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

/* ---------- Type ---------- */
.label {
  margin: 0 0 16px;
  font-size: 14px; font-weight: 600;
  letter-spacing: .02em;
  color: var(--accent);
}
.display {
  margin: 0;
  font-size: clamp(30px, 4vw, 50px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.015em;
  color: var(--text);
}
.display--xl { font-size: clamp(36px, 5.4vw, 68px); }
.lede { margin: 20px 0 0; font-size: 17px; line-height: 1.75; color: var(--text-2); max-width: 62ch; }
.sec-head { margin-bottom: 54px; max-width: 760px; }

/* ---------- Pills ---------- */
.pill-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 56px; padding: 15px 38px;
  border-radius: 999px;
  font-size: 16px; font-weight: 600; line-height: 1;
  white-space: nowrap;
  border: 2px solid var(--accent);
  color: var(--accent);
  background: transparent;
  transition: background-color .22s ease, color .22s ease, border-color .22s ease;
}
.pill-btn:hover { background: var(--accent); color: #FFFFFF; }
.pill-btn--solid {
  background: var(--accent); border-color: var(--accent); color: #FFFFFF;
  font-weight: 700; font-size: 15px; letter-spacing: .07em; text-transform: uppercase;
  padding: 15px 44px;
}
.pill-btn--solid:hover { background: var(--accent-hi); border-color: var(--accent-hi); }
.pill-btn--ghost { color: var(--white); border-color: rgba(255,255,255,.55); }
.pill-btn--ghost:hover { background: var(--white); color: var(--ink); border-color: var(--white); }
/* Solid white secondary for the hero: filled like the primary so its
   label never depends on whatever video frame is underneath (the same
   argument as .nav-pill), but white so the accent CTA still reads
   first. Hover dims toward the page's cool grey instead of inverting. */
.pill-btn--white {
  background: var(--white); border-color: var(--white); color: var(--ink);
  font-weight: 700; font-size: 15px; letter-spacing: .07em; text-transform: uppercase;
  padding: 15px 44px;
}
.pill-btn--white:hover { background: #D9E0EF; border-color: #D9E0EF; color: var(--ink); }

/* ---------- NAV ---------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  /* Transparent and borderless over the hero — no bar, no hairline. */
  background: transparent;
  transition: background-color .3s ease, box-shadow .3s ease;
}
.nav--solid {
  background: rgba(11, 18, 38, .95);
  backdrop-filter: blur(10px);
  box-shadow: 0 8px 30px rgba(0,0,0,.28);
}
.nav-inner {
  max-width: var(--page-max); margin: 0 auto;
  padding: 0 var(--gutter);
  height: var(--nav-h);
  display: flex; align-items: center; gap: 24px;
}
/* The mark lives in the HERO at full size and only migrates up here
   once the hero is behind you — otherwise you'd briefly see it twice. */
.nav-brand {
  flex: 0 0 auto;
  opacity: 0; visibility: hidden;
  transition: opacity .3s ease, visibility .3s ease;
}
.nav--solid .nav-brand { opacity: 1; visibility: visible; }
.nav-brand img { height: 54px; width: auto; }

.nav-links { margin-left: auto; display: flex; align-items: center; gap: 34px; }
.nav-link {
  font-size: 16px; font-weight: 500;
  color: var(--white);
  padding: 9px 0;
  transition: color .2s ease;
}
.nav-link:hover { color: var(--accent); }
.nav-phone { font-weight: 600; }
.nav-pill {
  min-height: 50px; padding: 13px 30px; margin-left: 4px;
  /* Filled, not outlined. Over the hero video an outlined accent pill
     put accent-on-video text at the mercy of whatever frame was
     underneath it; a solid fill keeps the primary CTA legible. */
  background: var(--accent); border-color: var(--accent); color: var(--white);
}
.nav-pill:hover { background: var(--accent-hi); border-color: var(--accent-hi); }

.menu-btn {
  display: none; margin-left: auto;
  width: 48px; height: 48px;
  background: transparent;
  border: 1px solid rgba(255,255,255,.3);
  border-radius: 999px; padding: 0;
  flex-direction: column; align-items: center; justify-content: center; gap: 5px;
}
.menu-btn .bar { display: block; width: 20px; height: 2px; background: var(--white); border-radius: 2px; }

@media (max-width: 1080px) {
  :root { --nav-h: 84px; }
  .nav-links { display: none; }
  .menu-btn { display: flex; }
  /* On phones the bar carries the mark permanently — the hero one is
     hidden, so it is never two logos on one screen. */
  .nav-brand { opacity: 1; visibility: visible; }
  .nav-brand img { height: 46px; }
}

.mobile-menu {
  display: none;
  position: fixed; inset: var(--nav-h) 0 0 0; z-index: 99;
  background: var(--ink);
  padding: 28px var(--gutter) 48px;
  flex-direction: column; gap: 2px; overflow-y: auto;
}
.mobile-menu.open { display: flex; }
.mobile-menu a {
  padding: 17px 0; font-size: 20px; font-weight: 500; color: var(--white);
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.mobile-menu .mm-pill { margin-top: 26px; border-bottom: none; align-self: flex-start; }

/* ---------- HERO ---------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex; align-items: center;
  padding: calc(var(--nav-h) + 20px) 0 36px;
  overflow: hidden;
  background: var(--ink-deep);
}
.hero-media { position: absolute; inset: 0; z-index: 0; }
.hero-media img, .hero-media video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.hero-media video { opacity: 0; transition: opacity .7s ease; }
.hero-media video.ready { opacity: 1; }

/* NO tint of any kind over the footage — no wash, no directional
   gradient. The video plays at full contrast edge to edge and legibility
   is carried entirely by type weight and text-shadow, which darken the
   glyph rather than the picture. tools/luma.js measures the result. */

.hero-inner {
  position: relative; z-index: 2;
  width: 100%; max-width: var(--page-max);
  margin: 0 auto; padding: 0 var(--gutter);
  /* Panel widened ~1.5x (was 396px). clamp scales it with the viewport so
     it lands near 600 on a wide screen and steps down on narrower ones,
     where the headline still needs its share of the row. */
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(430px, 44vw, 600px);
  gap: 48px; align-items: center;
}
/* Load-bearing. Grid items default to min-width:auto, so a column can
   never shrink below its content's min-content width — and the quote
   panel's <select> carries the width of its longest option ("Project
   Planning & Management"), which pins the column at ~337px and forces
   the whole hero to overflow a 360px phone. */
.hero-inner > * { min-width: 0; }

.hero-copy { max-width: 680px; }
.hero-brand { display: block; margin-bottom: 16px; }
.hero-brand img { height: 92px; width: auto; }

/* ---------- Hero badges ----------
   These sit BELOW the two CTAs, with the rating badge below them. */
.badges {
  list-style: none; margin: 20px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 7px;
}
.badges li {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 11px;
  font-size: 12.5px; font-weight: 500; color: var(--white);
  background: rgba(11,18,38,.42);
  border: 1px solid rgba(255,255,255,.24);
  border-radius: 999px;
  backdrop-filter: blur(6px);
}
.badges svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--accent); }

/* ---------- Rating badge ----------
   Same shape as a platform badge but deliberately unbranded — the score
   comes from the review form on the client's own site. -->*/
.rating-badge {
  display: inline-flex; align-items: center; gap: 14px;
  margin-top: 16px; padding: 9px 16px;
  background: rgba(11,18,38,.52);
  border: 1px solid rgba(255,255,255,.22);
  border-radius: 999px;
  backdrop-filter: blur(6px);
}
.rb-stars { display: inline-flex; gap: 3px; color: var(--accent); }
.rb-stars svg { width: 17px; height: 17px; }
.rb-divider { width: 1px; align-self: stretch; background: rgba(255,255,255,.24); }
.rb-meta { display: flex; flex-direction: column; line-height: 1.3; }
.rb-score { font-size: 14px; font-weight: 600; color: var(--white); }
.rb-sub { font-size: 12px; color: var(--white-60); }

.eyebrow {
  display: flex; align-items: center; gap: 20px;
  margin: 0 0 14px;
  font-size: 18px; font-weight: 600; color: var(--white);
}
.eyebrow-rule { flex: 0 0 auto; width: 56px; height: 2px; background: var(--accent); }

.hero-title {
  margin: 0;
  /* The low end is vw-driven, not a fixed floor: a fixed minimum that
     fits a 390px phone still overflows a 320px one, so the small end
     has to keep scaling rather than stop. This headline is long — nine
     words, and "Junk Removal" has to stay on one line for the .mark bar
     to make sense — so the ceiling is lower than the skeleton's. */
  font-size: clamp(23px, 4.4vw, 44px);
  font-weight: 700; line-height: 1.06; letter-spacing: -.015em;
  color: var(--white);
  /* Own stacking context, so the .mark bar's z-index:-1 lands behind the
     glyphs and not behind the hero video. */
  position: relative;
  z-index: 0;
}

/* The reference site's accent bar under one word of the headline. Theirs is
   a fixed 152x13 background-image pinned at "0 59px" — it only lines up for
   the exact word and size they shipped, and they switch it off under 480px.
   This rebuilds it as a pseudo-element on a span: the negative left/right
   make the bar run slightly proud of the word, and sizing it in em keeps
   the proportion at every step of the clamp down to 320px.
   Their 13/64 (.203em) proportion was drawn on a plain page; here the bar
   sits under the headline's dark glyph-shadow with video behind it, which
   ate most of a thin bar. So it runs thicker and brighter than the
   original — same gesture, tuned to survive the footage. */
.mark { position: relative; display: inline-block; }
.mark::after {
  content: "";
  position: absolute;
  left: -.08em; right: -.08em;
  bottom: .03em;
  height: .32em;
  background: var(--accent-hi);
  z-index: -1;
}

.hero-sub {
  margin: 14px 0 0;
  max-width: 46ch;
  font-size: clamp(16px, 1.5vw, 19px);
  line-height: 1.6;
  /* Full white, not white-80. With no scrim under it, an 80% white on a
     mid-bright frame was the least readable line on the page. */
  color: var(--white);
  font-weight: 500;
}

.hero-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-top: 22px; }

/* ---------- Copy over untinted media ----------
   There is no scrim anywhere on this site, so every piece of white copy
   sitting on the hero video, the CTA video or the About photograph has to
   carry its own legibility. This is a glyph-level treatment, not a wash:
   a hard 1-2px dark rim at the letter edge plus a wide soft falloff. The
   image between the letters stays exactly as shot. tools/luma.js measures
   what it actually buys. */
.hero-title, .eyebrow, .hero-sub,
.cta-inner .display, .cta-lede, .cta-inner .label,
.nav:not(.nav--solid):not(.nav--page) .nav-link {
  text-shadow:
    0 1px 2px rgba(3, 6, 14, .92),
    0 0 6px rgba(3, 6, 14, .78),
    0 2px 18px rgba(3, 6, 14, .62);
}
/* The headline is the biggest surface and takes the most light, so it gets
   a heavier rim than the body copy around it. */
.hero-title, .cta-inner .display {
  text-shadow:
    0 1px 2px rgba(3, 6, 14, .95),
    0 0 8px rgba(3, 6, 14, .85),
    0 2px 26px rgba(3, 6, 14, .70);
}
/* Chips and the rating badge already sit on their own translucent plate;
   deepen it rather than shadowing the small type, which would smudge. */
.badges li, .rating-badge { background: rgba(6, 10, 22, .72); }

/* ---------- Quote panel ---------- */
.quote-panel {
  background: var(--paper);
  border-radius: 20px;
  padding: 24px 26px 24px;
  box-shadow: 0 30px 70px rgba(0,0,0,.42);
}
.quote-title { margin: 0 0 15px; font-size: 21px; font-weight: 700; letter-spacing: -.01em; color: var(--text); }
.quote-sub { margin: 0 0 20px; font-size: 14px; color: var(--text-3); }
.q-label { display: block; margin: 0 0 7px; font-size: 13px; font-weight: 500; color: var(--text-2); }
.q-input {
  width: 100%; padding: 13px 15px;
  font-family: var(--font); font-size: 16px;   /* 16px stops iOS zoom-on-focus */
  color: var(--text); background: var(--paper-2);
  border: 1px solid var(--line); border-radius: 12px;
  transition: border-color .2s ease, background-color .2s ease;
}
.q-input:focus { border-color: var(--accent); background: var(--paper); }
.q-select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--text) 50%), linear-gradient(135deg, var(--text) 50%, transparent 50%);
  background-position: calc(100% - 20px) 50%, calc(100% - 14px) 50%;
  background-size: 6px 6px, 6px 6px; background-repeat: no-repeat;
  /* Half-width column: keep the chevron gutter tight and drop a point of
     type so "Choose Service" fits without clipping. */
  padding-right: 26px;
  font-size: 15px;
  text-overflow: ellipsis;
}
#quoteForm {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 14px;
  row-gap: 12px;
  align-items: start;
}
.q-field { min-width: 0; }
.q-field--full { grid-column: 1 / -1; }
@media (max-width: 400px) { #quoteForm { grid-template-columns: 1fr; } }

.q-textarea { resize: vertical; min-height: 74px; line-height: 1.55; }
.q-submit { width: 100%; margin-top: 6px; min-height: 54px; }
.q-note { margin: 9px 0 0; font-size: 12px; color: var(--text-3); text-align: center; }
.q-note.is-error { color: #B3261E; }
/* Consent + legal disclosure under the quote form. Required alongside the SMS
   opt-in language in the Privacy Policy / Terms, so it ships with the form
   rather than only living in the footer. */
.q-consent { margin: 10px 0 0; font-size: 11.5px; line-height: 1.55; color: var(--text-3); text-align: center; }
.q-consent a { text-decoration: underline; text-underline-offset: 2px; }
.q-consent a:hover { color: var(--accent); }
.q-done { font-size: 16px; line-height: 1.6; color: var(--text); }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

/* 1081-1160px: still the two-column hero, but the copy column is narrow
   enough that the headline takes an extra line and tips the section ~16px
   past the fold. Buy it back rather than let the layout break its promise. */
@media (min-width: 1081px) and (max-width: 1400px) {
  .hero { padding-bottom: 24px; }
  .hero-title { font-size: clamp(23px, 3.4vw, 39px); }
  .hero-brand img { height: 78px; }
  .eyebrow { font-size: 16px; margin-bottom: 12px; }
}

@media (max-width: 1080px) {
  .hero { min-height: 0; padding: 0 0 60px; }
  .hero-inner { grid-template-columns: 1fr; gap: 0; align-items: start; }
  .hero-copy { max-width: none; }
  .hero-brand { display: none; }   /* nav carries the mark on phones */
  .hero-brand img { height: 120px; }

  /* The copy block owns the first screenful on its own, so the footage
     behind it is actually visible; the quote panel starts below the fold
     rather than covering the video the moment the page loads.
     padding-top clears the fixed nav — without it, content taller than
     the block overflows upward and slides under the bar. */
  .hero-copy {
    min-height: calc(100svh - var(--nav-h));
    display: flex; flex-direction: column; justify-content: center;
    padding: calc(var(--nav-h) + 20px) 0 44px;
  }
  .quote-panel { margin-bottom: 8px; }

  /* The media used to be inset:0, i.e. it covered the WHOLE hero —
     including the quote panel — so on a 390px screen `cover` was fitting
     a 16:9 frame into a ~1500px-tall box and showing barely a seventh of
     it. Confining it to one screenful roughly doubles what you see. */
  .hero-media { bottom: auto; height: calc(100svh - var(--nav-h)); }

  /* Phones read top-down into a fold, so the order changes here: the
     5.0 badge is the strongest one-line trust signal and moves up
     between the sub and the CTAs — eyebrow, title, sub, RATING,
     actions, badges — which is what guarantees the rating lands inside
     the first screenful even on a 320px phone, instead of being the
     last item in a stack far taller than any phone screen. Desktop
     keeps the DOM order; everything fits its fold there anyway.
     Nothing between sub and actions is focusable, so tab order still
     matches visual order. */
  .hero-copy > .eyebrow      { order: 1; }
  .hero-copy > .hero-title   { order: 2; }
  .hero-copy > .hero-sub     { order: 3; }
  .hero-copy > .rating-badge { order: 4; margin-top: 18px; align-self: flex-start; max-width: 100%; }
  .hero-copy > .hero-actions { order: 5; }
  .hero-copy > .badges       { order: 6; }
}
@media (max-width: 680px) {
  /* Pills are nowrap by default, which is right on desktop but makes a
     long label ("Get your free estimate") a rigid 302px box that
     overflows a 320px phone — and once the document is wider than the
     viewport, the fixed nav stretches with it. Let them wrap and shrink. */
  .pill-btn {
    max-width: 100%;
    white-space: normal; text-align: center;
    padding-left: 26px; padding-right: 26px;
  }
  .about-copy .pill-btn, .cta-actions .pill-btn { width: 100%; }

  .hero-actions { flex-direction: column; align-items: stretch; gap: 12px; }
  .hero-actions .pill-btn { width: 100%; }
  .eyebrow { font-size: 16px; gap: 14px; }
  .eyebrow-rule { width: 40px; }
  /* Two per row rather than a four-deep stack eating the fold. */
  .badges { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 22px; }
  .badges li { padding: 8px 12px; font-size: 12px; gap: 7px; min-width: 0; }
  .badges svg { width: 15px; height: 15px; }
}
@media (max-width: 380px) {
  /* Keep the rating pill on one line for as long as possible — smaller
     stars and tighter gaps before the meta text is forced to wrap. */
  .rating-badge { gap: 10px; padding: 8px 12px; }
  .rb-stars { gap: 2px; }
  .rb-stars svg { width: 15px; height: 15px; }
  .rb-sub { font-size: 11.5px; }
}
@media (max-width: 440px) {
  /* No eyebrow is short enough to guarantee one line at every width, so
     stack the rule above the label rather than strand it beside a
     wrapped sentence. */
  .eyebrow { flex-direction: column; align-items: flex-start; gap: 12px; }
  .eyebrow-rule { width: 46px; }
}
/* Short viewports (phones in landscape): the copy is far taller than the
   screen, so forcing a full-height centred block just pushes it under the
   nav. Let it flow from the top instead. NOTE this also catches short
   PORTRAIT phones (320x568 etc.), which is why the order swap below
   lives in its own orientation-gated block. */
@media (max-width: 1080px) and (max-height: 620px) {
  .hero-copy { min-height: 0; justify-content: flex-start; }
  .hero-media { height: 100%; bottom: 0; }
}
/* Genuinely landscape only: a ~400px fold can't hold the rating AND the
   CTA, so the portrait reorder reverses — the CTA is the thing worth
   the fold, the rating returns to the end of the stack, and the
   paddings tighten to keep the CTA inside the screen. Short portrait
   phones never match this and keep the rating above the fold. */
@media (max-width: 1080px) and (max-height: 620px) and (orientation: landscape) {
  .hero-copy { padding-top: calc(var(--nav-h) + 12px); }
  .hero-copy > .rating-badge { order: 7; margin-top: 22px; }
  .eyebrow { margin-bottom: 10px; }
  .hero-actions { margin-top: 16px; }
}
@media (max-width: 340px) {
  /* Two columns hold down to here because .badges li has min-width:0, so
     a long label wraps inside its pill rather than forcing the grid
     wider. Below this even a wrapped pill gets too cramped. */
  .badges { grid-template-columns: 1fr 1fr; gap: 6px; }
  .badges li { padding: 6px 8px; font-size: 11.5px; gap: 5px; }
  .badges svg { width: 13px; height: 13px; }
}

/* ---------- TRUST BAND ---------- */
.trust { background: var(--ink); }
.trust-inner {
  padding-top: 26px; padding-bottom: 26px;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px;
}
.trust-item { display: flex; align-items: center; gap: 12px; font-size: 14px; font-weight: 500; color: var(--white); }
.trust-item svg { width: 22px; height: 22px; flex: 0 0 auto; color: var(--accent); }
@media (max-width: 900px) { .trust-inner { grid-template-columns: repeat(2, 1fr); gap: 18px; } }
@media (max-width: 420px) { .trust-item { font-size: 13px; } }

/* ---------- SERVICES ---------- */
.services { background: var(--paper); }
.card-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; }
.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  overflow: hidden;
  transition: transform .3s ease, box-shadow .3s ease;
}
.card:hover { transform: translateY(-4px); box-shadow: 0 18px 44px rgba(11,18,38,.10); }
.card-media { aspect-ratio: 3 / 2; overflow: hidden; }
.card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.card:hover .card-media img { transform: scale(1.05); }
.card-body { padding: 24px 24px 28px; }
.card-num { margin: 0 0 8px; font-size: 13px; font-weight: 600; color: var(--accent); }
.card-body h3 { margin: 0 0 10px; font-size: 20px; font-weight: 600; color: var(--text); line-height: 1.25; }
.card-body p { margin: 0; font-size: 15px; line-height: 1.7; color: var(--text-2); }

/* They sell exactly two services, so the services grid runs two-up with a
   taller image rather than being padded out to the six the skeleton had.
   The six-card grid still earns its keep further down, on the use cases. */
.card-grid--duo { grid-template-columns: repeat(2, 1fr); gap: 32px; }
.card-grid--duo .card-media { aspect-ratio: 16 / 10; }
.card-grid--duo .card-body { padding: 30px 30px 34px; }
.card-grid--duo .card-body h3 { font-size: 25px; }
.card-grid--duo .card-body p { font-size: 16px; }

.more-wrap { display: flex; justify-content: center; margin-top: 36px; }
.more-btn { color: var(--text); border-color: var(--text); }
.more-btn:hover { background: var(--text); color: var(--white); }

@media (max-width: 1040px) { .card-grid { grid-template-columns: repeat(2, 1fr); gap: 22px; } }
@media (max-width: 680px) {
  .card-grid { grid-template-columns: 1fr; gap: 20px; }
  /* .js-gated for the same reason as the FAQ: the "See all 6" button
     starts [hidden] and only JS reveals it, so without JS this rule
     would silently drop half the cards with no way to get them back. */
  .js .card-grid[data-collapsed="true"] .card:nth-child(n+4) { display: none; }
}
@media (min-width: 681px) { .more-wrap { display: none; } }

/* ---------- ABOUT ----------
   Full bleed, at the client's request: the photograph runs edge to edge
   behind the copy. The navy gradient is left-heavy on desktop (the copy
   lives there, the truck stays visible on the right) and bottom-heavy on
   phones, where the copy sits over the lower half. Photo + gradient also
   means no flat dark solid for a dithering pipeline to latch onto. */
.about { position: relative; overflow: hidden; background: var(--ink); }
.about-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.about-scrim {
  position: absolute; inset: 0;
  background: linear-gradient(90deg,
    rgba(11,18,38,.94) 0%, rgba(11,18,38,.80) 40%,
    rgba(11,18,38,.34) 74%, rgba(11,18,38,.10) 100%);
}
.about-inner { position: relative; z-index: 1; padding-top: 118px; padding-bottom: 118px; }
.about-copy { max-width: 600px; }

.about-copy .label { color: var(--accent-hi); }
.about-copy .display { color: var(--white); }
.about-quote {
  margin: 22px 0 16px; padding-left: 22px;
  border-left: 3px solid var(--accent);
  font-size: 17px; line-height: 1.8; color: var(--white-80);
}
.about-attrib { margin: 0 0 28px; font-size: 14px; font-weight: 600; color: var(--accent-hi); }

/* Phones: cover-cropping ANY landscape photo into a tall narrow slice
   shows a third of the frame — unreadable fragments, whatever the
   photo. So mobile art-directs instead: the photograph runs as a
   full-width band, FULLY visible, and the copy sits below it on the
   section's own navy gradient (+ the shared noise overlay, so the dark
   area is never the flat solid that dithers into a diagonal). Desktop
   keeps the true full-bleed. */
@media (max-width: 900px) {
  .about { background: linear-gradient(180deg, var(--ink-2) 0%, var(--ink-deep) 100%); }
  .about-bg { position: static; height: auto; aspect-ratio: 16 / 10; object-fit: cover; }
  .about-scrim { display: none; }
  .about-inner { padding-top: 44px; padding-bottom: 68px; }
}

/* ---------- CAROUSEL (projects + reviews) ---------- */
.work { background: var(--paper-2); }
/* The showcase rows run wider than the rest of the page — the gallery,
   the use-case grid and the reviews all take 80%+ of the screen instead
   of floating in dead margin. max() so the 86vw term only ever widens:
   effectively edge-to-edge (minus gutters) up to ~1800px screens, and
   86% of anything bigger. */
.work > .container, .usecases > .container, .reviews > .container { max-width: max(1560px, 86vw); }
.work .tile { flex-basis: calc((100% - 28px) / 2); }
@media (max-width: 1040px) { .work .tile { flex-basis: calc((100% - 26px) / 2); } }
@media (max-width: 680px)  { .work .tile { flex-basis: 88%; } }
.carousel { position: relative; }
.car-track {
  display: flex; gap: 26px;
  overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch; scrollbar-width: none; padding-bottom: 4px;
  /* Without this, a swipe that runs off the end of the carousel
     CHAINS to the page and drags the whole document sideways, which
     is indistinguishable from the page being broken. The v2 build's
     equivalent rails already carry it; this one did not. */
  overscroll-behavior-x: contain;
  /* overflow clips PAINT but does not make this a containing block,
     so an absolutely positioned descendant escapes to the initial
     containing block and widens the DOCUMENT. See the long note on
     .showcase__grid in v2/v2.css — same mechanism. */
  contain: paint;
}
.car-track::-webkit-scrollbar { display: none; }
@media (prefers-reduced-motion: reduce) { .car-track { scroll-behavior: auto; } }

.tile {
  flex: 0 0 calc((100% - 52px) / 3);
  margin: 0; scroll-snap-align: start;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  overflow: hidden;
}
.tile img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.tile figcaption { display: block; padding: 18px 20px 22px; font-size: 16px; font-weight: 600; line-height: 1.35; color: var(--text); }
.tile-n { display: block; margin-bottom: 8px; font-size: 13px; font-weight: 600; color: var(--accent); }
.tile-loc { display: block; margin-top: 7px; font-size: 13px; font-weight: 400; color: var(--text-3); }

/* ---------- Tile links (gallery only) ----------
   The photo area is a link into the lightbox. The corner chip is the
   standing "clickable" affordance — hover can't be the only signal
   when most visitors are on touch. */
.tile-link { position: relative; display: block; overflow: hidden; cursor: zoom-in; }
.tile-link img { transition: transform .5s ease; }
.tile-link:hover img, .tile-link:focus-visible img { transform: scale(1.045); }
.tile-hint {
  position: absolute; right: 12px; bottom: 12px;
  width: 38px; height: 38px; border-radius: 999px;
  display: grid; place-items: center;
  background: rgba(6,10,22,.62); color: var(--white);
  border: 1px solid rgba(255,255,255,.32);
  backdrop-filter: blur(6px);
  transition: background-color .2s ease, border-color .2s ease;
}
.tile-hint svg { width: 16px; height: 16px; }
.tile-link:hover .tile-hint, .tile-link:focus-visible .tile-hint { background: var(--accent); border-color: var(--accent); }

/* ---------- Lightbox ----------
   Native <dialog>, shrink-wrapped to the image at its OWN aspect —
   this is where the before/after strips the 3:2 tiles crop away get
   seen whole. */
.lightbox { border: none; padding: 0; background: transparent; overflow: visible; }
.lightbox::backdrop { background: rgba(6, 10, 22, .9); }
.lightbox img { display: block; max-width: min(1240px, 92vw); max-height: 80vh; width: auto; height: auto; border-radius: 14px; }
.lb-cap { margin: 14px 0 0; text-align: center; font-size: 15px; font-weight: 600; color: var(--white); }
.lb-close {
  position: absolute; top: 10px; right: 10px; z-index: 1;
  width: 42px; height: 42px; border-radius: 999px;
  display: grid; place-items: center;
  background: rgba(6,10,22,.66); color: var(--white);
  border: 1px solid rgba(255,255,255,.32);
  transition: background-color .2s ease, border-color .2s ease;
}
.lb-close:hover { background: var(--accent); border-color: var(--accent); }
.lb-close svg { width: 18px; height: 18px; }

.car-nav {
  position: absolute; top: 32%; z-index: 3;
  width: 48px; height: 48px;
  display: none; align-items: center; justify-content: center;
  background: var(--paper); color: var(--text);
  border: 1px solid var(--line); border-radius: 999px;
  box-shadow: 0 6px 20px rgba(11,18,38,.12);
  transition: background-color .2s ease, color .2s ease, opacity .2s ease;
}
.carousel.is-ready .car-nav { display: flex; }
.car-nav:hover:not(:disabled) { background: var(--accent); color: #FFFFFF; border-color: var(--accent); }
.car-nav:disabled { opacity: .3; cursor: default; }
.car-nav svg { width: 20px; height: 20px; }
.car-prev { left: -20px; }
.car-next { right: -20px; }
.car-dots { display: none; justify-content: center; gap: 4px; margin-top: 20px; }
.carousel.is-ready .car-dots { display: flex; }
.car-dot { position: relative; width: 34px; height: 40px; padding: 0; background: transparent; border: none; }
.car-dot::before {
  content: ''; position: absolute; left: 3px; right: 3px; top: 50%;
  height: 3px; margin-top: -1.5px; border-radius: 2px;
  background: var(--line); transition: background-color .2s ease;
}
.car-dot[aria-current="true"]::before { background: var(--accent); }

@media (max-width: 1040px) { .tile { flex-basis: calc((100% - 26px) / 2); } }
@media (max-width: 680px) {
  .tile { flex-basis: 86%; }
  .car-track { gap: 16px; }
  .car-nav { display: none !important; }
}
@media (max-width: 1340px) and (min-width: 681px) { .car-prev { left: 6px; } .car-next { right: 6px; } }

/* ---------- STATS ---------- */
.stats { background: var(--ink); }
.stats-inner {
  padding-top: 56px; padding-bottom: 56px;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px;
}
.stat { text-align: center; }
.stat-v { margin: 0 0 8px; font-size: clamp(32px, 4.2vw, 48px); font-weight: 700; line-height: 1; color: var(--white); letter-spacing: -.02em; }
.stat-v span { color: var(--accent); }
.stat-l { margin: 0; font-size: 14px; color: var(--white-60); }
@media (max-width: 780px) { .stats-inner { grid-template-columns: repeat(2, 1fr); gap: 34px 20px; } }

/* ---------- REVIEWS ----------
   Square Google-style cards. The row runs 80%+ of the screen, so the
   per-view count scales with width — FOUR up on big screens, three on
   smaller desktops — to keep each square at a normal review-widget size
   rather than a giant. Each card is a real square (aspect-ratio 1/1)
   with the star row and the Google glyph up top, the testimony in the
   middle, and an initial-avatar + name pinned to the bottom. All six
   are five-star — the aggregate is 5.0 across 6, which is only
   reachable if every one is a five — so the stars are factual. */
.reviews { background: var(--paper-2); }
.reviews .car-track { gap: 24px; align-items: stretch; }
.review {
  flex: 0 0 calc((100% - 72px) / 4);
  margin: 0; padding: 26px 26px 24px;
  scroll-snap-align: start;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 10px 30px rgba(11,18,38,.05);
  aspect-ratio: 1 / 1;
  display: flex; flex-direction: column; gap: 16px;
  transition: transform .25s ease, box-shadow .25s ease;
}
.review:hover { transform: translateY(-4px); box-shadow: 0 20px 44px rgba(11,18,38,.12); }

.rv-top { display: flex; align-items: center; justify-content: space-between; }
.rv-stars { display: inline-flex; gap: 3px; color: #FBBC05; }
.rv-stars svg { width: 18px; height: 18px; }
.rv-g { width: 22px; height: 22px; flex: 0 0 auto; }

.review blockquote {
  margin: 0; flex: 1 1 auto; min-height: 0;
  font-size: 15px; line-height: 1.65; color: var(--text-2);
  /* Squares are fixed-height, so the longest testimony (~90 words) is
     clamped to what the card holds. Most reviews are far shorter and never
     reach the cap; the ellipsis only shows on the one long one, and the
     full text lives on Google. */
  display: -webkit-box;
  -webkit-line-clamp: 7;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.review figcaption {
  display: flex; align-items: center; gap: 12px;
  padding-top: 16px; border-top: 1px solid var(--line);
}
.rv-avatar {
  flex: 0 0 auto;
  width: 42px; height: 42px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: var(--white);
  font-size: 17px; font-weight: 700; line-height: 1;
}
.rv-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rv-name { font-size: 15px; font-weight: 700; color: var(--text); }
.rv-meta { font-size: 12.5px; color: var(--text-3); }

/* Three-up on smaller desktops, two-up below 1080 — still square; the
   line-clamp ellipsis absorbs whatever the 90-word review can't fit
   (the full text lives on Google). Only phones drop the square, where
   a forced 1:1 at ~300px would clamp away most of the long reviews. */
@media (max-width: 1400px) {
  .review { flex-basis: calc((100% - 48px) / 3); }
}
@media (max-width: 1080px) {
  .review { flex-basis: calc((100% - 24px) / 2); }
  .review blockquote { -webkit-line-clamp: 8; }
}
@media (max-width: 680px) {
  .review { flex-basis: 86%; aspect-ratio: auto; min-height: 0; }
  .review blockquote { -webkit-line-clamp: unset; overflow: visible; }
}

/* ---------- FAQ ---------- */
.faq { background: var(--paper-2); }
.faq-list { max-width: 860px; }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item:first-child { border-top: 1px solid var(--line); }
.faq-q {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 22px 0;
  font-size: 17px; font-weight: 600; text-align: left;
  color: var(--text); background: transparent; border: none;
}
.faq-q:hover { color: var(--accent); }
.plus { position: relative; flex: 0 0 auto; width: 15px; height: 15px; }
.plus::before, .plus::after { content: ''; position: absolute; background: var(--accent); transition: transform .25s ease; }
.plus::before { top: 6.5px; left: 0; width: 15px; height: 2px; }
.plus::after { left: 6.5px; top: 0; width: 2px; height: 15px; }
.faq-q[aria-expanded="true"] .plus::after { transform: scaleY(0); }
/* visibility, not just max-height: a clipped panel stays in the
   accessibility tree and gets read out. */
/* .js-gated: only collapse once the script that can re-open it is
   running. Otherwise every answer is hidden with no working control. */
.js .faq-a { max-height: 0; overflow: hidden; visibility: hidden; transition: max-height .3s ease, visibility 0s linear .3s; }
.js .faq-q[aria-expanded="true"] + .faq-a { visibility: visible; transition: max-height .3s ease, visibility 0s linear 0s; }
.faq-a p { margin: 0 0 22px; font-size: 16px; line-height: 1.75; color: var(--text-2); max-width: 68ch; }

/* ---------- CTA ---------- */
.cta { position: relative; overflow: hidden; background: var(--ink); }
.cta video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.cta-inner { position: relative; z-index: 2; padding-top: 120px; padding-bottom: 120px; text-align: center; }
.cta-inner .display { color: var(--white); }
/* White, not the accent: mid-blue over moving footage bottomed out at
   1:1 contrast whenever a frame drifted toward the accent's own hue.
   White + the glyph shadow is the same treatment the hero eyebrow
   uses, which measures ~5:1 worst-case. */
.cta-inner .label { color: var(--white); font-weight: 700; }

.cta-lede { margin: 22px auto 34px; color: rgba(255,255,255,.92); }
.cta-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 16px; }
@media (max-width: 680px) {
  .cta-inner { padding-top: 76px; padding-bottom: 76px; }
  .cta-actions { flex-direction: column; }
}

/* ---------- FOOTER ----------
   Gradient plus noise, never a flat dark fill: a perfectly flat dark
   panel is what a spatial-dithering display pipeline latches onto, and
   it surfaces as a faint diagonal hairline across the whole band. */
.footer { position: relative; background: linear-gradient(180deg, var(--ink-2) 0%, var(--ink-deep) 100%); color: var(--white-80); }
.noise-overlay {
  position: absolute; inset: 0; pointer-events: none;
  opacity: .035; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/></svg>");
}
.footer-inner { position: relative; z-index: 1; padding-top: 76px; }
.footer-grid { display: grid; grid-template-columns: 1.6fr 1fr 1.3fr 1fr; gap: 44px; }
.footer-brand img { height: 72px; width: auto; margin-bottom: 18px; }
.footer-brand p { margin: 0 0 14px; font-size: 14.5px; line-height: 1.75; max-width: 40ch; }
.footer-reg { font-size: 13px; color: var(--white-60); }
.footer h3 { margin: 0 0 16px; font-size: 14px; font-weight: 600; color: var(--accent); }
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
/* njindooroutdoormaintenance@gmail.com is 35 unbroken characters. Left
   alone it sets a min-content floor wider than a 320px phone, the grid
   column refuses to shrink past it, and the whole document goes 16px
   wide — which the fixed nav then stretches to match. */
.footer li { font-size: 14.5px; line-height: 1.5; overflow-wrap: anywhere; }
.footer-grid > * { min-width: 0; }
.footer a { transition: color .2s ease; }
.footer a:hover { color: var(--accent); }
/* 28 town names. As a list it would be a wall; as a single wrapped
   paragraph at reduced contrast it reads as the SEO footprint it is. */
.footer-areas { margin-top: 48px; padding-top: 34px; border-top: 1px solid rgba(255,255,255,.12); }
.footer-areas p {
  margin: 0; max-width: 96ch;
  font-size: 13.5px; line-height: 2; color: var(--white-60);
}

.footer-bottom {
  margin-top: 40px; padding: 22px 0 30px;
  border-top: 1px solid rgba(255,255,255,.12);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px;
  font-size: 13px; color: var(--white-60);
}
.footer-legal a { text-decoration: underline; text-underline-offset: 2px; }
/* ---------- FOOTER NEWSLETTER ----------
   Mirrors the signup on the client's live footer. Posts to the same
   FormSpark endpoint as the quote form. */
.footer-news { margin-top: 22px; max-width: 420px; }
.footer-news-label {
  display: block; margin-bottom: 10px;
  font-size: 13.5px; line-height: 1.5; color: var(--white-60);
}
.footer-news-row { display: flex; gap: 8px; flex-wrap: wrap; }
.footer-news-input {
  flex: 1 1 190px; min-width: 0;
  padding: 11px 14px;
  font: inherit; font-size: 14px; color: #FFFFFF;
  background: rgba(255,255,255,.07);
  border: 1px solid rgba(255,255,255,.18); border-radius: 10px;
}
.footer-news-input::placeholder { color: rgba(255,255,255,.42); }
.footer-news-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.footer-news-btn {
  flex: 0 0 auto; padding: 11px 20px;
  font: inherit; font-size: 14px; font-weight: 700; color: #FFFFFF;
  background: var(--accent); border: 0; border-radius: 10px; cursor: pointer;
  transition: filter .2s ease;
}
.footer-news-btn:hover { filter: brightness(1.08); }
.footer-news-btn:disabled { opacity: .6; cursor: default; }
.footer-news-note { margin: 9px 0 0; font-size: 12.5px; color: var(--white-60); min-height: 1em; }
.footer-news-note.is-error { color: #FFB4AB; }
@media (max-width: 1040px) { .footer-grid { grid-template-columns: 1fr 1fr; gap: 36px; } }
@media (max-width: 560px) { .footer-grid { grid-template-columns: 1fr; gap: 30px; } }

/* ---------- MOBILE STICKY CTAs ----------
   Two floating pills, not a full-width panel. The container itself is
   transparent — only the pills have a surface. */
.mobile-cta {
  position: fixed; left: 14px; right: 14px; z-index: 90;
  bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  display: none; gap: 10px;
  background: transparent;
  transform: translateY(calc(100% + 24px));
  transition: transform .32s cubic-bezier(.22,.61,.36,1), opacity .32s ease;
  opacity: 0;
}
.mobile-cta.show { transform: translateY(0); opacity: 1; }
.mobile-cta a {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 54px; padding: 0 14px;
  font-size: 15px; font-weight: 600;
  border-radius: 999px;
  box-shadow: 0 12px 30px rgba(0,0,0,.42);
}
.mobile-cta svg { width: 18px; height: 18px; }
.mc-call { background: var(--accent); color: #FFFFFF; }
.mc-quote { background: rgba(11,18,38,.94); color: var(--white); border: 1px solid rgba(255,255,255,.24); backdrop-filter: blur(8px); }
@media (max-width: 900px) {
  .mobile-cta { display: flex; }
  /* Reserve the pills' height so they can never cover the last of the
     footer, even though they hide there. */
  body { padding-bottom: 82px; }
}

/* ---------- Reveal ----------
   Default VISIBLE; site.js opts in via .js-reveal on <html>, so a no-JS
   or JS-error visitor gets a finished page rather than a blank one. */
.reveal { opacity: 1; transform: none; }
.js-reveal .reveal { opacity: 0; transform: translateY(16px); transition: opacity .6s ease, transform .6s cubic-bezier(.22,.61,.36,1); }
.js-reveal .reveal.in { opacity: 1; transform: none; }

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .js-reveal .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
  .card:hover { transform: none; }
  .card:hover .card-media img { transform: none; }
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

/* ============================================================
   INTERIOR PAGES — added for the About, Services, Pricing,
   Gallery, Blog and Contact pages. The one-page site above is
   untouched; everything below is only used off the homepage.

   Two ground rules carried over: dark bands are ALWAYS a two-stop
   gradient plus the noise overlay, never a flat fill (a flat dark
   panel is what a dithering display pipeline turns into a diagonal
   hairline); and there is one stylesheet, so all of this lives here
   rather than in per-page <style> blocks.
   ============================================================ */

/* ---------- Nav on interior pages ----------
   The homepage nav is transparent over the hero and site.js toggles
   .nav--solid on scroll. Interior pages have no full-bleed hero, so
   they ship .nav--page: solid and branded from the first paint, with
   or without JS. site.js may still add/remove .nav--solid freely —
   over .nav--page it is a no-op. */
.nav--page {
  background: rgba(11, 18, 38, .95);
  backdrop-filter: blur(10px);
  box-shadow: 0 8px 30px rgba(0,0,0,.28);
}
.nav--page .nav-brand { opacity: 1; visibility: visible; }
.nav-link[aria-current="page"] { color: var(--accent-hi); }

/* Services dropdown — CSS only, so it works with JS off. The parent
   "Services" is a real link (to junk-removal.html), so a touch-desktop
   tap navigates rather than dead-ending; keyboard users reach the panel
   via :focus-within because its links are tabbable. */
.nav-drop { position: relative; display: inline-flex; align-items: center; }
.nav-drop-toggle { display: inline-flex; align-items: center; gap: 5px; }
.nav-caret { width: 14px; height: 14px; flex: 0 0 auto; transition: transform .2s ease; }
.nav-drop:hover .nav-caret,
.nav-drop:focus-within .nav-caret { transform: rotate(180deg); }
/* Invisible bridge across the gap so the hover survives the trip from
   the toggle down to the panel. */
.nav-drop::before { content: ""; position: absolute; top: 100%; left: -10px; right: -10px; height: 16px; }
.nav-drop-menu {
  position: absolute; top: calc(100% + 12px); left: 50%;
  transform: translateX(-50%) translateY(6px);
  min-width: 208px; padding: 10px;
  background: rgba(11, 18, 38, .98);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 14px;
  box-shadow: 0 20px 50px rgba(0,0,0,.44);
  display: grid; gap: 2px;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .2s ease, transform .2s ease, visibility 0s linear .2s;
}
.nav-drop:hover .nav-drop-menu,
.nav-drop:focus-within .nav-drop-menu {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translateX(-50%) translateY(0);
  transition: opacity .2s ease, transform .2s ease, visibility 0s linear 0s;
}
.nav-drop-menu a {
  padding: 11px 16px; border-radius: 9px;
  font-size: 15px; font-weight: 500; color: var(--white); white-space: nowrap;
  transition: background-color .18s ease, color .18s ease;
}
.nav-drop-menu a:hover { background: rgba(255,255,255,.08); color: var(--accent-hi); }
.nav-drop-menu a[aria-current="page"] { color: var(--accent-hi); background: rgba(255,255,255,.06); }
.mobile-menu a[aria-current="page"] { color: var(--accent-hi); }

/* ---------- Page hero ----------
   The compact dark band that opens every interior page. NOT .hero
   (that is 100svh); this just clears the fixed nav and states the
   page. Gradient + noise, never flat. */
.page-hero {
  position: relative; overflow: hidden;
  background: linear-gradient(180deg, var(--ink-2) 0%, var(--ink-deep) 100%);
  padding: calc(var(--nav-h) + 66px) 0 74px;
}
.page-hero > .container { position: relative; z-index: 1; }
.page-hero .label { color: var(--accent-hi); }
.page-hero .lede { color: var(--white-80); max-width: 68ch; }
.display--hero {
  font-size: clamp(33px, 5vw, 58px);
  color: var(--white);
  /* Own stacking context so the .mark bar sits behind the glyphs,
     not behind the section. */
  position: relative; z-index: 0;
}
.crumbs {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin: 0 0 22px; font-size: 13px; color: var(--white-60);
}
.crumbs a { color: var(--white-60); transition: color .2s ease; }
.crumbs a:hover { color: var(--accent-hi); }
.crumbs .sep { opacity: .5; }
.crumbs [aria-current] { color: var(--white-80); }
@media (max-width: 780px) { .page-hero { padding: calc(var(--nav-h) + 40px) 0 52px; } }

/* ---------- Section helpers ---------- */
.section--alt { background: var(--paper-2); }
.section--ink {
  position: relative; overflow: hidden; color: var(--white-80);
  background: linear-gradient(180deg, var(--ink-2) 0%, var(--ink-deep) 100%);
}
.section--ink > .container { position: relative; z-index: 1; }
.section--ink .label { color: var(--accent-hi); }
.section--ink .display,
.section--ink .sec-head h2 { color: var(--white); }
.section--ink .lede { color: var(--white-80); }
.sec-head--center { max-width: 760px; margin-left: auto; margin-right: auto; text-align: center; }
.btn-row { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 34px; }
.btn-row--center { justify-content: center; }

/* ---------- Split (text + media) ---------- */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 52px; align-items: center; }
.split--wide-text { grid-template-columns: 1.15fr .85fr; }
.media-frame { border-radius: var(--r-card); overflow: hidden; border: 1px solid var(--line); }
.media-frame img { width: 100%; height: 100%; object-fit: cover; }
.media-frame--tall img { aspect-ratio: 4 / 5; }
.media-frame--wide img { aspect-ratio: 3 / 2; }
@media (max-width: 860px) {
  .split, .split--wide-text { grid-template-columns: 1fr; gap: 34px; }
  .split .media-frame { order: -1; }
}

/* Verbatim story quote on a LIGHT section (the dark .about-quote above
   is white-on-navy; this is its light-background sibling). */
.story-quote {
  margin: 0 0 18px; padding-left: 22px;
  border-left: 3px solid var(--accent);
  font-size: 18px; line-height: 1.8; color: var(--text);
}
.story-attrib { margin: 0 0 6px; font-size: 14px; font-weight: 700; color: var(--accent); }

/* ---------- Feature cards (icon + text) ---------- */
.feature-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 26px; }
.feature {
  padding: 32px 28px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  transition: transform .3s ease, box-shadow .3s ease;
}
.feature:hover { transform: translateY(-4px); box-shadow: 0 18px 44px rgba(11,18,38,.10); }
.feature-ico {
  width: 52px; height: 52px; border-radius: 14px;
  display: grid; place-items: center;
  background: rgba(47,111,229,.12); color: var(--accent);
  margin-bottom: 20px;
}
.feature-ico svg { width: 26px; height: 26px; }
.feature h3 { margin: 0 0 10px; font-size: 19px; font-weight: 700; color: var(--text); line-height: 1.3; }
.feature p { margin: 0; font-size: 15px; line-height: 1.7; color: var(--text-2); }

/* ============================================================
   BACKGROUND TREATMENTS (bg-fx)
   Ten reusable section surfaces so no two sections on a page share a
   look. These are DECORATION, not imagery: CSS gradients, grids and
   outline geometry drawn behind the content at low opacity. Photographs
   stay in frames where they can be seen clearly, rather than being
   flattened under a tint.

   Usage:  <section class="section bg-fx bg-grid"> … </section>
   Dark variants pair with .section--ink / .stats.
   ============================================================ */
.bg-fx { position: relative; isolation: isolate; overflow: hidden; }
/* Content has to be positioned to paint above the ::before/::after
   layers. Decorative children are excluded by their aria-hidden flag —
   noise overlays, hero photographs and scrims are all absolutely
   positioned, and blanket `.bg-fx > *` would reset them to relative and
   drop them into the flow. */
.bg-fx > *:not([aria-hidden="true"]) { position: relative; z-index: 1; }
.bg-fx::before,
.bg-fx::after { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; }

/* 1 — Dot matrix. Two layers on one 26px grid so they line up exactly:
   a resting field weighted to the corners, and a brighter accent field
   revealed only where the pointer is. site.js eases the pointer
   position, so the reveal trails the cursor rather than snapping to it.

   The resting field is deliberately drawn strong enough to stand on its
   own, because a hover effect does not exist for most of this traffic —
   phones get a properly visible pattern, not an empty section. */
.bg-dots { --mx: 50%; --my: 50%; }
.bg-dots::before {
  background-image: radial-gradient(rgba(11,18,38,.20) 2px, transparent 2px);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(ellipse 62% 68% at 100% 0%, #000 0%, transparent 78%), radial-gradient(ellipse 62% 68% at 0% 100%, #000 0%, transparent 78%);
          mask-image: radial-gradient(ellipse 62% 68% at 100% 0%, #000 0%, transparent 78%), radial-gradient(ellipse 62% 68% at 0% 100%, #000 0%, transparent 78%);
  -webkit-mask-composite: source-over; mask-composite: add;
}
/* The reveal: same grid, accent-coloured and a touch larger, masked to
   a soft disc that follows the cursor. */
.bg-dots::after {
  background-image: radial-gradient(rgba(47,111,229,.58) 2.2px, transparent 2.2px);
  background-size: 26px 26px;
  opacity: 0;
  transition: opacity .55s ease;
  /* Wider disc, but it gives up much earlier — a bloom that fades out
     rather than a bright pool with a visible rim. */
  -webkit-mask-image: radial-gradient(circle 270px at var(--mx) var(--my), #000 0%, rgba(0,0,0,.32) 38%, transparent 78%);
          mask-image: radial-gradient(circle 270px at var(--mx) var(--my), #000 0%, rgba(0,0,0,.32) 38%, transparent 78%);
}
.bg-dots.is-lit::after { opacity: .6; }

/* No cursor to follow on a phone, so the highlight drives itself: the
   same bloom sweeps across the band every few seconds and fades out at
   each end. Here the mask is a fixed-size disc and its POSITION is what
   animates — the dot grid underneath never moves, so it reads as light
   travelling over the dots rather than the dots sliding. */
@media (hover: none), (pointer: coarse) {
  .bg-dots::after {
    -webkit-mask-image: radial-gradient(circle at center, #000 0%, rgba(0,0,0,.32) 38%, transparent 78%);
            mask-image: radial-gradient(circle at center, #000 0%, rgba(0,0,0,.32) 38%, transparent 78%);
    -webkit-mask-size: 150% 320%; mask-size: 150% 320%;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    animation: dotSweep 7.5s ease-in-out infinite;
  }
}
@keyframes dotSweep {
  0%   { opacity: 0;  -webkit-mask-position: -45% 50%; mask-position: -45% 50%; }
  18%  { opacity: .6; }
  82%  { opacity: .6; }
  100% { opacity: 0;  -webkit-mask-position: 145% 50%; mask-position: 145% 50%; }
}

.section--ink.bg-dots::before, .stats.bg-dots::before, .page-hero.bg-dots::before {
  background-image: radial-gradient(rgba(255,255,255,.24) 2px, transparent 2px);
}
.section--ink.bg-dots::after, .stats.bg-dots::after, .page-hero.bg-dots::after {
  background-image: radial-gradient(rgba(75,135,242,.65) 2.2px, transparent 2.2px);
}

/* 11 — Layered panels. Two offset planes tilted a couple of degrees for
   depth. Restored on a LIGHT surface: the version that read as ugly was
   this sitting on deep navy, which is where the heaviness came from —
   the shapes themselves were never the problem. */
.bg-panels::before {
  inset: 54px 6.5% auto auto; width: 42%; height: 62%;
  background: linear-gradient(150deg, var(--paper-2) 0%, rgba(47,111,229,.09) 100%);
  border-radius: 32px;
  box-shadow: 0 30px 70px rgba(11,18,38,.055);
  transform: rotate(-2.4deg);
}
.bg-panels::after {
  inset: auto auto 42px 5.5%; width: 30%; height: 48%;
  border: 1.6px solid rgba(47,111,229,.22);
  border-radius: 28px;
  transform: rotate(3.2deg);
}
/* Kept on phones rather than switched off — just re-proportioned so the
   two planes still frame the copy instead of crowding it. */
@media (max-width: 900px) {
  .bg-panels::before { inset: 26px 4% auto auto; width: 64%; height: 34%; border-radius: 24px; }
  .bg-panels::after  { inset: auto auto 26px 4%; width: 48%; height: 26%; border-radius: 20px; }
}

/* 2 — Scattered outline geometry. */
.bg-confetti::before {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='640' height='540'><g fill='none' stroke='%232F6FE5' stroke-opacity='.22' stroke-width='1.4'><circle cx='86' cy='78' r='34'/><circle cx='262' cy='452' r='21'/><rect x='430' y='300' width='44' height='44' rx='10'/><path d='M312 54v32M296 70h32'/><path d='M556 96l40-50'/></g><g fill='none' stroke='%230B1226' stroke-opacity='.13' stroke-width='1.4'><circle cx='508' cy='188' r='46'/><rect x='120' y='368' width='34' height='34' rx='8'/></g><g fill='%232F6FE5' fill-opacity='.20'><circle cx='612' cy='250' r='3.2'/><circle cx='60' cy='470' r='3.2'/><circle cx='372' cy='150' r='3.2'/></g></svg>");
  background-repeat: repeat;
}

.section--ink.bg-confetti::before, .page-hero.bg-confetti::before {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='640' height='540'><g fill='none' stroke='%23FFFFFF' stroke-opacity='.15' stroke-width='1.4'><circle cx='86' cy='78' r='34'/><circle cx='262' cy='452' r='21'/><rect x='430' y='300' width='44' height='44' rx='10'/><path d='M312 54v32M296 70h32'/><path d='M556 96l40-50'/></g><g fill='none' stroke='%234B87F2' stroke-opacity='.30' stroke-width='1.4'><circle cx='508' cy='188' r='46'/><rect x='120' y='368' width='34' height='34' rx='8'/></g></svg>");
}

/* 4 — Line-art landmark. An oversized outline of a roll-off container
   bleeding off one edge — the pictorial cousin of the wordmark, so like
   the wordmark it earns its keep only once per page. */
.bg-landmark::before {
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='620' height='330' viewBox='0 0 620 330'><g fill='none' stroke='%230B1226' stroke-opacity='.10' stroke-width='3.2' stroke-linejoin='round' stroke-linecap='round'><path d='M70 252V186l104-78h366v144z'/><path d='M92 232V196l92-70h334v106z'/><path d='M250 112v140M330 112v140M410 112v140M480 112v140'/><circle cx='214' cy='276' r='22'/><circle cx='458' cy='276' r='22'/><path d='M214 254h244'/><path d='M174 108c-18-44 22-66 84-58'/><path d='M540 130v100'/></g></svg>") right -40px bottom 8px / 620px auto no-repeat;
}
.section--ink.bg-landmark::before, .page-hero.bg-landmark::before {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='620' height='330' viewBox='0 0 620 330'><g fill='none' stroke='%23FFFFFF' stroke-opacity='.14' stroke-width='3.2' stroke-linejoin='round' stroke-linecap='round'><path d='M70 252V186l104-78h366v144z'/><path d='M92 232V196l92-70h334v106z'/><path d='M250 112v140M330 112v140M410 112v140M480 112v140'/><circle cx='214' cy='276' r='22'/><circle cx='458' cy='276' r='22'/><path d='M214 254h244'/><path d='M174 108c-18-44 22-66 84-58'/><path d='M540 130v100'/></g></svg>");
}

/* 5 — Coverage rings. Rebuilt as a true radiating signal: rings drawn
   by a repeating radial gradient from one anchor point, then masked so
   they genuinely fade with distance instead of stopping dead. Breathes
   slowly so it reads as a pulse, not a target. */
.bg-rings::before {
  background: repeating-radial-gradient(circle at 12% 76%,
    rgba(47,111,229,.20) 0 1.6px, transparent 1.6px 72px);
  -webkit-mask-image: radial-gradient(circle at 12% 76%, #000 4%, transparent 58%);
          mask-image: radial-gradient(circle at 12% 76%, #000 4%, transparent 58%);
  animation: ringBreathe 7s ease-in-out infinite;
}
.bg-rings::after {
  inset: auto auto 22.5% 11.4%; width: 11px; height: 11px; border-radius: 50%;
  background: var(--accent); opacity: .45;
}
.section--ink.bg-rings::before, .page-hero.bg-rings::before {
  background: repeating-radial-gradient(circle at 12% 76%,
    rgba(75,135,242,.34) 0 1.6px, transparent 1.6px 72px);
}
@keyframes ringBreathe { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }

/* 6 — Aurora drift. Brand colour moving on its own — no cursor needed,
   so it behaves identically on a phone. Fills the whole surface rather
   than decorating an edge. */
.bg-aurora::before {
  inset: -12%;
  background:
    radial-gradient(46% 52% at 18% 26%, rgba(47,111,229,.30), transparent 62%),
    radial-gradient(40% 46% at 84% 20%, rgba(111,175,62,.20), transparent 64%),
    radial-gradient(54% 52% at 70% 86%, rgba(75,135,242,.26), transparent 66%);
  animation: auroraDrift 20s ease-in-out infinite alternate;
}
.section--ink.bg-aurora::before, .page-hero.bg-aurora::before {
  background:
    radial-gradient(46% 52% at 18% 26%, rgba(47,111,229,.55), transparent 62%),
    radial-gradient(40% 46% at 84% 20%, rgba(111,175,62,.30), transparent 64%),
    radial-gradient(54% 52% at 70% 86%, rgba(75,135,242,.42), transparent 66%);
}
@keyframes auroraDrift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(-2.5%, 2%, 0) scale(1.08); }
  100% { transform: translate3d(2.5%, -2%, 0) scale(1.04); }
}

/* 7 — Icon wallpaper. The kit repeated as a tile — container, crate,
   truck. Legible because you see the same shapes over and over, which
   is what the single staggered stack never managed. */
.bg-wallpaper::before {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='330' height='270' viewBox='0 0 330 270'><g fill='none' stroke='%232F6FE5' stroke-opacity='.22' stroke-width='2' stroke-linejoin='round' stroke-linecap='round'><path d='M22 106V84l22-18h72v40z'/><path d='M44 66h72v40'/><path d='M66 66v40M92 66v40'/><path d='M206 58h62v50h-62z'/><path d='M206 74h62'/><path d='M237 58v50'/><path d='M46 232v-30h58l16-20h46v50z'/><path d='M104 182v50'/><circle cx='74' cy='240' r='9'/><circle cx='150' cy='240' r='9'/><path d='M228 236v-22l18-14h54v36z'/><path d='M246 200h54v36'/></g></svg>");
  background-repeat: repeat;
}
.section--ink.bg-wallpaper::before {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='330' height='270' viewBox='0 0 330 270'><g fill='none' stroke='%23FFFFFF' stroke-opacity='.16' stroke-width='2' stroke-linejoin='round' stroke-linecap='round'><path d='M22 106V84l22-18h72v40z'/><path d='M44 66h72v40'/><path d='M66 66v40M92 66v40'/><path d='M206 58h62v50h-62z'/><path d='M206 74h62'/><path d='M237 58v50'/><path d='M46 232v-30h58l16-20h46v50z'/><path d='M104 182v50'/><circle cx='74' cy='240' r='9'/><circle cx='150' cy='240' r='9'/><path d='M228 236v-22l18-14h54v36z'/><path d='M246 200h54v36'/></g></svg>");
}

/* 8 — Route map. Dashed pickup routes threading the section with pins
   dropped along them. Fills the surface and says "we come to you". */
.bg-route::before {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='940' height='540' viewBox='0 0 940 540'><g fill='none' stroke='%232F6FE5' stroke-opacity='.30' stroke-width='2.4' stroke-dasharray='11 10' stroke-linecap='round'><path d='M-30 392C130 306 232 428 392 344S636 196 970 268'/><path d='M-30 168C150 104 268 232 470 168S792 56 970 128'/></g><g fill='%232F6FE5' fill-opacity='.28'><path d='M214 300c-11 0-20 9-20 20 0 14 20 34 20 34s20-20 20-34c0-11-9-20-20-20zm0 27a7 7 0 110-14 7 7 0 010 14z'/><path d='M612 232c-11 0-20 9-20 20 0 14 20 34 20 34s20-20 20-34c0-11-9-20-20-20zm0 27a7 7 0 110-14 7 7 0 010 14z'/><path d='M842 366c-11 0-20 9-20 20 0 14 20 34 20 34s20-20 20-34c0-11-9-20-20-20zm0 27a7 7 0 110-14 7 7 0 010 14z'/></g></svg>");
  background-repeat: repeat;
}
.section--ink.bg-route::before {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='940' height='540' viewBox='0 0 940 540'><g fill='none' stroke='%234B87F2' stroke-opacity='.42' stroke-width='2.4' stroke-dasharray='11 10' stroke-linecap='round'><path d='M-30 392C130 306 232 428 392 344S636 196 970 268'/><path d='M-30 168C150 104 268 232 470 168S792 56 970 128'/></g><g fill='%234B87F2' fill-opacity='.40'><path d='M214 300c-11 0-20 9-20 20 0 14 20 34 20 34s20-20 20-34c0-11-9-20-20-20zm0 27a7 7 0 110-14 7 7 0 010 14z'/><path d='M612 232c-11 0-20 9-20 20 0 14 20 34 20 34s20-20 20-34c0-11-9-20-20-20zm0 27a7 7 0 110-14 7 7 0 010 14z'/><path d='M842 366c-11 0-20 9-20 20 0 14 20 34 20 34s20-20 20-34c0-11-9-20-20-20zm0 27a7 7 0 110-14 7 7 0 010 14z'/></g></svg>");
}

/* 9 — Perspective floor. A grid raked back to a horizon, so the section
   has depth instead of a flat texture. Reads as the lot the trucks pull
   into. */
.bg-floor::before {
  inset: auto 0 0 0; height: 82%;
  background-image:
    repeating-linear-gradient(90deg, rgba(11,18,38,.16) 0 1.6px, transparent 1.6px 92px),
    repeating-linear-gradient(0deg,  rgba(11,18,38,.16) 0 1.6px, transparent 1.6px 92px);
  transform: perspective(560px) rotateX(64deg);
  transform-origin: 50% 100%;
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 58%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 58%);
}
.section--ink.bg-floor::before {
  background-image:
    repeating-linear-gradient(90deg, rgba(255,255,255,.20) 0 1.6px, transparent 1.6px 92px),
    repeating-linear-gradient(0deg,  rgba(255,255,255,.20) 0 1.6px, transparent 1.6px 92px);
}

/* 10 — Drift marquee. A moving band of what they actually do. Pauses on
   hover; the global reduced-motion rule stops it outright. */
.marquee {
  overflow: hidden; padding: 13px 0;
  background: var(--accent); color: #FFFFFF;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.marquee--ink { background: var(--ink); }
.marquee-track {
  display: inline-flex; align-items: center; gap: 42px;
  white-space: nowrap; will-change: transform;
  animation: marqueeRun 34s linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-track span {
  font-size: 14px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
}
.marquee-track .sep { opacity: .5; font-size: 11px; }
@keyframes marqueeRun { to { transform: translateX(-50%); } }

/* 3 — Oversized ghost wordmark. Set data-mark="SINCE 2000" on the section.
   Like the landmark, once per page at most.

   It must FIT. The first version hung off the bottom-right on negative
   insets inside a container that clips its overflow, so it was sliced on
   two edges by construction, and at up to 240px a long phrase was wider
   than the viewport as well. Now it spans the full width, sits wholly
   inside, and is sized so the longest phrase in use still clears the
   gutters at 320px. */
.bg-mark::after {
  content: attr(data-mark);
  inset: auto 0 6% 0;
  padding: 0 24px;
  text-align: center;
  /* ~0.6em average per uppercase character in Montserrat 800: at this
     size a 17-character phrase clears the gutters from 320px up. */
  font-size: var(--mark-size, clamp(22px, 7.6vw, 118px));
  font-weight: 800; letter-spacing: -.03em; line-height: 1.05;
  color: rgba(11,18,38,.06);
  white-space: nowrap;
}
/* Phrases of ~10 characters or fewer can run considerably larger and
   still fit, so they are not left looking undersized next to the long
   ones. Apply alongside .bg-mark. */
.bg-mark--short { --mark-size: clamp(30px, 11vw, 176px); }
.section--ink.bg-mark::after, .stats.bg-mark::after, .page-hero.bg-mark::after { color: rgba(255,255,255,.075); }

/* ---------- Supporting details ---------- */
/* Eyebrow as a pill badge with a leading dot. */
.eyebrow-pill {
  display: inline-flex; align-items: center; gap: 8px;
  margin: 0 0 16px; padding: 7px 15px 7px 12px;
  background: rgba(47,111,229,.10); border-radius: 999px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--accent);
}
.eyebrow-pill::before { content: ""; width: 6px; height: 6px; border-radius: 999px; background: currentColor; }
.section--ink .eyebrow-pill, .page-hero .eyebrow-pill { background: rgba(255,255,255,.12); color: var(--accent-hi); }

/* Accent corner bracket on a framed photograph. */
.frame-bracket { position: relative; }
.frame-bracket::before {
  content: ""; position: absolute; z-index: 2;
  top: -12px; left: -12px; width: 74px; height: 74px;
  border-top: 3px solid var(--accent); border-left: 3px solid var(--accent);
  border-top-left-radius: 8px;
}
.frame-bracket--br::before { top: auto; left: auto; bottom: -12px; right: -12px;
  border-top: none; border-left: none;
  border-bottom: 3px solid var(--accent); border-right: 3px solid var(--accent);
  border-radius: 0 0 8px 0; }

/* Photo mosaic — a band of real job photos, shown clear and untinted. */
.mosaic { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: 168px; gap: 16px; }
.mosaic figure { margin: 0; overflow: hidden; border-radius: var(--r-card); border: 1px solid var(--line); background: var(--paper); }
.mosaic img { width: 100%; height: 100%; object-fit: cover; transition: transform .55s ease; }
.mosaic figure:hover img { transform: scale(1.06); }
.mosaic .m-tall { grid-row: span 2; }
.mosaic .m-wide { grid-column: span 2; }
@media (max-width: 900px) { .mosaic { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 150px; } }
@media (max-width: 520px) { .mosaic { grid-auto-rows: 128px; gap: 12px; } .mosaic .m-wide { grid-column: span 2; } }

/* ============================================================
   PREMIUM SECTION TREATMENTS
   Each interior section gets its own surface rather than repeating
   one flat panel: a photographic hero, a dark stat band, a light
   editorial split with an overlapping note card, a photographic
   dark band, and chip grids. Dark surfaces are always photo+scrim
   or gradient, plus noise — never a flat fill.
   ============================================================ */

/* ---------- Page hero over photography ---------- */
.page-hero--media { padding: calc(var(--nav-h) + 84px) 0 84px; background: var(--ink-deep); }
.page-hero-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Directional, so the copy side stays dense and the photograph opens
   up on the right — the same logic as the homepage About band. */
/* Weighted hard to the copy side and released fast, so the right half
   of the photograph reads at close to full colour instead of sitting
   under a blanket tint. */
.page-hero-scrim {
  position: absolute; inset: 0;
  background: linear-gradient(103deg,
    rgba(6,10,22,.92) 0%, rgba(6,10,22,.76) 36%,
    rgba(6,10,22,.38) 66%, rgba(6,10,22,.12) 100%);
}
.page-hero--media > .container { position: relative; z-index: 2; }
.page-hero--media .lede { max-width: 58ch; }
.page-hero--media .display--hero,
.page-hero--media .lede,
.page-hero--media .label,
.page-hero--media .crumbs {
  text-shadow: 0 1px 2px rgba(3,6,14,.88), 0 0 8px rgba(3,6,14,.62);
}
.page-hero--media .badges { margin-top: 26px; }
.page-hero-actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 30px; }
@media (max-width: 780px) { .page-hero--media { padding: calc(var(--nav-h) + 44px) 0 56px; } }
@media (max-width: 680px) { .page-hero-actions .pill-btn { width: 100%; } }

/* ---------- Stat band (dark, divided) ---------- */
.stats--band {
  position: relative; overflow: hidden;
  background: linear-gradient(180deg, var(--ink-2) 0%, var(--ink-deep) 100%);
}
.stats--band .stats-inner { position: relative; z-index: 1; padding-top: 48px; padding-bottom: 48px; }
.stats--band .stat + .stat { border-left: 1px solid rgba(255,255,255,.13); }
@media (max-width: 780px) {
  .stats--band .stat:nth-child(odd) { border-left: none; }
}

/* ---------- Editorial figure with an overlapping note card ---------- */
.story-figure { position: relative; }
.media-note {
  position: absolute; left: -20px; bottom: -20px; max-width: 78%;
  padding: 18px 22px; border-radius: 16px;
  background: linear-gradient(180deg, var(--ink-2) 0%, var(--ink-deep) 100%);
  box-shadow: 0 22px 50px rgba(11,18,38,.34);
}
.media-note strong { display: block; font-size: 17px; font-weight: 700; color: var(--white); line-height: 1.25; }
.media-note span { display: block; margin-top: 4px; font-size: 13px; color: var(--white-60); }
@media (max-width: 860px) {
  .split > .story-figure { order: -1; margin-bottom: 30px; }
  .media-note { left: 12px; bottom: -16px; max-width: calc(100% - 24px); }
}

/* ---------- Section over photography (dark band) ----------
   This is what keeps a full-width dark section from being the flat
   panel that dithers into a diagonal hairline: a photograph carries
   the surface, a scrim holds the contrast, noise breaks up the rest. */
.section--media { position: relative; overflow: hidden; color: var(--white-80); background: var(--ink-deep); }
.sec-media-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Dense where the heading sits, opened up through the middle so the
   photograph is actually legible behind the cards, dense again at the
   foot so the section closes cleanly into the next one. */
.sec-media-scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg,
    rgba(6,10,22,.90) 0%, rgba(6,10,22,.76) 46%, rgba(6,10,22,.91) 100%);
}
.section--media > .container { position: relative; z-index: 2; }
.section--media .label { color: var(--accent-hi); }
.section--media .display, .section--media .sec-head h2 { color: var(--white); }
.section--media .lede { color: var(--white-80); }

/* ---------- Linked card (services teaser) ---------- */
.card--link { display: block; }
.card--link .card-body h3 { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.card-go {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 999px;
  display: grid; place-items: center;
  background: rgba(47,111,229,.1); color: var(--accent);
  transition: background-color .2s ease, color .2s ease, transform .2s ease;
}
.card-go svg { width: 15px; height: 15px; }
.card--link:hover .card-go { background: var(--accent); color: #FFFFFF; transform: translateX(3px); }

/* ---------- Service-area chips ----------
   28 towns as a wrapped chip field rather than a run-on paragraph:
   the same SEO footprint, but it reads as a designed surface. */
.town-grid { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.town-chip {
  display: inline-block; padding: 9px 17px;
  background: var(--paper); border: 1px solid var(--line); border-radius: 999px;
  font-size: 14px; font-weight: 500; color: var(--text-2);
  transition: border-color .2s ease, color .2s ease, transform .2s ease, box-shadow .2s ease;
}
.town-chip:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-2px); box-shadow: 0 8px 20px rgba(11,18,38,.08); }
.areas-note { margin: 32px auto 0; max-width: 62ch; text-align: center; font-size: 15px; line-height: 1.7; color: var(--text-3); }
.areas-note a { color: var(--accent); font-weight: 600; }
@media (max-width: 560px) { .town-chip { padding: 8px 14px; font-size: 13px; } }

/* ---------- Trust cards (About "Why Trust Us") ----------
   Richer than the plain .feature: colour-coded gradient medallions,
   a real Google mark on the reviews card, and a hover accent sweep,
   so the four proof points read as living badges rather than flat
   line-icons. They sit on the dark section, so the white cards and
   colour medallions pop the way the client's own layout does. */
.trust-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; }
.trust-card {
  position: relative; overflow: hidden;
  padding: 38px 26px 32px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  text-align: center;
  /* Centred vertically so the shorter cards don't leave a pocket of
     dead space beside the taller one (the Google card carries stars). */
  display: flex; flex-direction: column; justify-content: center;
  transition: transform .3s ease, box-shadow .3s ease;
}
.trust-card:hover { transform: translateY(-6px); box-shadow: 0 24px 52px rgba(6,10,22,.34); }
.trust-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 4px;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi));
  transform: scaleX(0); transform-origin: left;
  transition: transform .4s cubic-bezier(.22,.61,.36,1);
}
.trust-card:hover::before { transform: scaleX(1); }
.trust-medal {
  width: 76px; height: 76px; margin: 0 auto 22px;
  border-radius: 22px;
  display: grid; place-items: center;
  color: #FFFFFF;
  box-shadow: 0 12px 26px rgba(11,18,38,.18);
}
.trust-medal svg { width: 38px; height: 38px; }
.trust-medal--green { background: linear-gradient(145deg, #7FC24C 0%, #5B9E32 100%); box-shadow: 0 12px 26px rgba(91,158,50,.30); }
.trust-medal--navy  { background: linear-gradient(145deg, #24365F 0%, #101a36 100%); }
.trust-medal--blue  { background: linear-gradient(145deg, #4B87F2 0%, #2F6FE5 100%); box-shadow: 0 12px 26px rgba(47,111,229,.30); }
.trust-medal--light { background: #FFFFFF; border: 1px solid var(--line); box-shadow: 0 12px 26px rgba(11,18,38,.12); }
.trust-medal--light svg { width: 40px; height: 40px; }
.trust-card h3 { margin: 0 0 9px; font-size: 17.5px; font-weight: 700; color: var(--text); line-height: 1.3; }
.trust-card p { margin: 0; font-size: 13.5px; line-height: 1.6; color: var(--text-3); }
.trust-stars { display: inline-flex; gap: 3px; margin-top: 12px; color: #FBBC05; }
.trust-stars svg { width: 16px; height: 16px; }
@media (max-width: 980px) { .trust-grid { grid-template-columns: 1fr 1fr; gap: 18px; } }
@media (max-width: 460px) { .trust-grid { grid-template-columns: 1fr; } }

/* ---------- Numbered steps (process) ---------- */
.steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
.steps--3 { grid-template-columns: repeat(3, 1fr); }
.step {
  padding: 32px 28px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
}
.step-n {
  width: 46px; height: 46px; border-radius: 999px;
  display: grid; place-items: center;
  background: var(--accent); color: #FFFFFF;
  font-size: 18px; font-weight: 700; line-height: 1;
  margin-bottom: 20px;
}
.step h3 { margin: 0 0 9px; font-size: 19px; font-weight: 700; color: var(--text); line-height: 1.3; }
.step p { margin: 0; font-size: 15px; line-height: 1.7; color: var(--text-2); }
@media (max-width: 900px) { .steps, .steps--3 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .steps, .steps--3 { grid-template-columns: 1fr; } }

/* ---------- Accept / reject lists ---------- */
.check-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; align-items: start; }
.check-card {
  padding: 34px 32px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
}
.check-card > h3 {
  margin: 0 0 22px; font-size: 21px; font-weight: 700; color: var(--text);
  display: flex; align-items: center; gap: 10px;
}
.check-card > h3 svg { width: 22px; height: 22px; flex: 0 0 auto; }
.check-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.check-list li { position: relative; padding-left: 34px; font-size: 15.5px; line-height: 1.6; color: var(--text-2); }
.check-list li strong { display: block; color: var(--text); font-weight: 600; }
.check-list li::before {
  content: ""; position: absolute; left: 0; top: 1px;
  width: 22px; height: 22px; border-radius: 999px;
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E") center / 13px no-repeat;
}
.check-list--no li::before {
  background-color: #C4372E;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6L6 18M6 6l12 12'/%3E%3C/svg%3E");
}
@media (max-width: 780px) { .check-cols { grid-template-columns: 1fr; gap: 22px; } }

/* ---------- Pricing ---------- */
.price-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; align-items: start; }
.price-card {
  position: relative;
  padding: 40px 32px 34px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  transition: transform .3s ease, box-shadow .3s ease;
}
.price-card:hover { transform: translateY(-4px); box-shadow: 0 18px 44px rgba(11,18,38,.10); }
.price-card--featured { border-color: var(--accent); box-shadow: 0 18px 44px rgba(47,111,229,.16); }
.price-badge {
  position: absolute; top: -14px; left: 50%; transform: translateX(-50%);
  padding: 7px 16px; white-space: nowrap;
  background: var(--accent); color: #FFFFFF;
  font-size: 11.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  border-radius: 999px;
}
.price-size { margin: 0 0 4px; font-size: 21px; font-weight: 700; color: var(--text); }
.price-amt { margin: 6px 0 2px; font-size: 44px; font-weight: 800; line-height: 1; letter-spacing: -.02em; color: var(--text); }
.price-amt span { font-size: 15px; font-weight: 600; color: var(--text-3); letter-spacing: 0; }
.price-tons { margin: 0 0 20px; font-size: 14px; font-weight: 600; color: var(--accent); }
.price-desc { margin: 0 0 22px; font-size: 15px; line-height: 1.7; color: var(--text-2); }
.price-feats { list-style: none; margin: 0 0 28px; padding: 0; display: grid; gap: 12px; }
.price-feats li { position: relative; padding-left: 28px; font-size: 14.5px; line-height: 1.55; color: var(--text-2); }
.price-feats li::before {
  content: ""; position: absolute; left: 0; top: 2px;
  width: 18px; height: 18px; border-radius: 999px;
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E") center / 11px no-repeat;
}
.price-card .pill-btn { width: 100%; }
.price-note { margin: 34px auto 0; max-width: 74ch; text-align: center; font-size: 13.5px; line-height: 1.7; color: var(--text-3); }
.promo {
  margin: 0 auto 44px; max-width: 660px; text-align: center;
  padding: 16px 28px;
  background: var(--accent); color: #FFFFFF;
  border-radius: 14px; font-size: 16px; font-weight: 700; line-height: 1.5;
}
.promo strong { font-weight: 800; }
/* "Limited Time Dumpster Offer" sits above the offer itself, the way the
   client's live pricing page frames it. */
.promo-eyebrow {
  display: block; margin-bottom: 6px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: rgba(255,255,255,.82);
}
/* Truckload tiers — a compact four-up under the roll-off cards. */
.price-mini-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
.price-mini {
  padding: 28px 22px; text-align: center;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-card);
}
.price-mini h4 { margin: 0 0 6px; font-size: 16px; font-weight: 700; color: var(--text); }
/* Each truckload tier is a fraction of the same 15-yard truck — the live
   pricing page labels every tier with it, so the fraction reads against
   something concrete. */
.price-mini .price-truck {
  margin: 0 0 10px; font-size: 11.5px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--text-3);
}
.price-mini .price-amt { font-size: 27px; }
.price-mini p { margin: 12px 0 0; font-size: 13.5px; line-height: 1.6; color: var(--text-2); }
@media (max-width: 960px) {
  .price-grid { grid-template-columns: 1fr; max-width: 460px; margin: 0 auto; }
  .price-card--featured { order: -1; }
  .price-mini-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 460px) { .price-mini-grid { grid-template-columns: 1fr; } }

/* ---------- Contact ---------- */
.contact-grid { display: grid; grid-template-columns: 1fr clamp(420px, 42vw, 540px); gap: 52px; align-items: start; }
.contact-grid .quote-panel { box-shadow: 0 18px 44px rgba(11,18,38,.10); border: 1px solid var(--line); }
.info-list { list-style: none; margin: 0; padding: 0; }
.info-item { display: flex; gap: 16px; padding: 20px 0; border-bottom: 1px solid var(--line); }
.info-item:first-child { padding-top: 0; }
.info-item:last-child { border-bottom: none; }
.info-ico {
  flex: 0 0 auto; width: 46px; height: 46px; border-radius: 12px;
  display: grid; place-items: center;
  background: rgba(47,111,229,.12); color: var(--accent);
}
.info-ico svg { width: 22px; height: 22px; }
.info-body { min-width: 0; }
.info-k { margin: 0 0 3px; font-size: 12.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--text-3); }
.info-v { margin: 0; font-size: 16px; line-height: 1.5; color: var(--text); font-weight: 500; overflow-wrap: anywhere; }
.info-v a { color: var(--text); transition: color .2s ease; }
.info-v a:hover { color: var(--accent); }
/* Day-by-day hours, as the live contact page lists them. Same hours all
   seven days, but spelled out so nobody has to guess about weekends. */
.hours-list { list-style: none; margin: 10px 0 0; padding: 0; max-width: 300px; }
.hours-list li {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 5px 0; font-size: 14px; color: var(--text-2);
  border-bottom: 1px solid var(--line);
}
.hours-list li:last-child { border-bottom: 0; }
.hours-list li span:first-child { font-weight: 600; color: var(--text); }
/* Call / Text / Service Areas — three separate actions, same as live. */
.contact-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }
.map-embed { margin-top: 40px; border-radius: var(--r-card); overflow: hidden; border: 1px solid var(--line); }
.map-embed iframe { display: block; width: 100%; height: 300px; border: 0; }
@media (max-width: 900px) { .contact-grid { grid-template-columns: 1fr; gap: 38px; } }

/* ---------- Gallery ----------
   Reuses the .tile / .tile-link / .tile-hint markup so the lightbox JS
   works unchanged; only the container changes from a scroll row to a
   grid. */
.gallery-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.gallery-grid .tile { margin: 0; }
@media (max-width: 1040px) { .gallery-grid { grid-template-columns: repeat(2, 1fr); gap: 20px; } }
@media (max-width: 640px)  { .gallery-grid { grid-template-columns: 1fr; } }

/* ---------- Blog index ---------- */
.chip-row { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 42px; }
.chip {
  padding: 10px 20px; font-size: 14px; font-weight: 600;
  color: var(--text-2); background: var(--paper);
  border: 1px solid var(--line); border-radius: 999px;
  transition: background-color .2s ease, color .2s ease, border-color .2s ease;
}
.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #FFFFFF; }
.post-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; }
.post-card {
  display: flex; flex-direction: column;
  padding: 28px 26px 30px;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-card);
  transition: transform .3s ease, box-shadow .3s ease;
}
.post-card:hover { transform: translateY(-4px); box-shadow: 0 18px 44px rgba(11,18,38,.10); }
.post-cat {
  align-self: flex-start; margin-bottom: 16px;
  padding: 5px 12px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--accent); background: rgba(47,111,229,.1);
  border-radius: 999px;
}
.post-card h3 { margin: 0 0 12px; font-size: 19px; font-weight: 700; line-height: 1.32; color: var(--text); }
.post-card h3 a { transition: color .2s ease; }
.post-card:hover h3 a { color: var(--accent); }
.post-excerpt { margin: 0; font-size: 14.5px; line-height: 1.65; color: var(--text-2); flex: 1 1 auto; }
.post-meta {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--line);
  font-size: 13px; color: var(--text-3);
}
.post-more { font-weight: 600; color: var(--accent); white-space: nowrap; }
.post-card[hidden] { display: none; }
@media (max-width: 1040px) { .post-grid { grid-template-columns: repeat(2, 1fr); gap: 22px; } }
@media (max-width: 680px)  { .post-grid { grid-template-columns: 1fr; } }

/* ---------- Blog post ---------- */
.post-hero-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; margin: 22px 0 0; }
.post-hero-meta .post-cat { margin: 0; color: #FFFFFF; background: var(--accent); }
.post-hero-meta time { font-size: 14px; color: var(--white-60); }
/* One-line summary under the post title, as the client's live posts carry.
   Sits on the dark post hero, so it reads at reduced white rather than body ink. */
.post-standfirst {
  margin: 18px 0 0; max-width: 68ch;
  font-size: 17px; line-height: 1.6; color: var(--white-60);
}
.prose { max-width: 74ch; margin: 0 auto; }
.prose > * + * { margin-top: 20px; }
.prose > h2 + *, .prose > h3 + * { margin-top: 14px; }
.prose h2 { margin-top: 46px; font-size: clamp(23px, 3vw, 29px); font-weight: 700; line-height: 1.25; letter-spacing: -.01em; color: var(--text); }
.prose h3 { margin-top: 34px; font-size: 20px; font-weight: 700; color: var(--text); }
.prose p, .prose li { font-size: 17px; line-height: 1.8; color: var(--text-2); }
.prose ul, .prose ol { margin: 0; padding-left: 24px; display: grid; gap: 10px; }
.prose li { padding-left: 4px; }
.prose li::marker { color: var(--accent); }
.prose strong { color: var(--text); font-weight: 700; }
.prose a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.prose blockquote {
  margin: 28px 0; padding: 6px 0 6px 24px;
  border-left: 3px solid var(--accent);
  font-size: 18px; line-height: 1.7; color: var(--text);
}
.post-foot { max-width: 74ch; margin: 50px auto 0; padding-top: 28px; border-top: 1px solid var(--line); }
.post-back { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; color: var(--accent); }
.post-back svg { width: 18px; height: 18px; }
