/* Maine-ly Foam - shared styles
   Palette: deep evergreen + birch white from Paul's "Maine Woods" pick on the kickoff form
   (2026-07-29), with the swatch's rust orange as the accent.

   The rust is #c2521f exactly as picked. It cannot carry every job on its own the way the
   logo red could: as small text on birch it is only 4.23:1, and on the dark evergreen it is
   2.57:1. So the rust family splits by job rather than by shade preference.

   Measured against WCAG AA (4.5:1 normal text, 3:1 large text and UI):

     --brand       #c2521f  the rust itself - button and pill BACKGROUNDS, rules, focus
                            rings, the callout border. White on it is 4.65:1.
     --brand-ink   #a8431a  the same rust taken down for TEXT on light: links, nav current,
                            eyebrows, card headings. 5.49:1 on birch, 6.03:1 on white.
     --brand-dark  #8f3714  button hover. White on it 8.11:1.
     --brand-light #e8935e  accents on the dark evergreen nav/footer. 4.98:1 on forest.

   Note this is NOT the logo red (#ff1e2a on the trailer and Mainly Foam.png). Rust against
   that mark measures 1.21:1 - near-identical luminance, adjacent hue - so wherever the real
   logo appears beside rust UI the two will read as a near-miss rather than a pair.

   --forest on --birch is 10.76:1 and white on --forest is 11.93:1, both comfortable.
*/

:root {
  --forest: #1f3d2b;
  --forest-deep: #142a1d;
  --forest-mid: #2d5540;
  --birch: #f6f4ef;
  --surface: #ffffff;

  --brand: #c2521f;
  --brand-ink: #a8431a;
  --brand-dark: #8f3714;
  --brand-light: #e8935e;

  --ink: #1c2b23;
  --ink-soft: #4f6157;
  --ink-faint: #77877d;
  --line: #dde3dd;
  --line-soft: #eaeee9;

  --radius: 10px;
  --shadow: 0 2px 14px rgba(20, 42, 29, 0.10);
  --shadow-lift: 0 8px 28px rgba(20, 42, 29, 0.14);
  --maxw: 1120px;
  --maxw-header: 1280px;

  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font-body);
  color: var(--ink);
  line-height: 1.65;
  background: var(--surface);
  -webkit-font-smoothing: antialiased;
}

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

a { color: var(--brand-ink); }
a:hover { color: var(--brand-dark); }

h1, h2, h3, h4 { line-height: 1.25; color: var(--forest); font-weight: 800; }
h1 { font-size: clamp(1.9rem, 4.2vw, 2.9rem); }
h2 { font-size: clamp(1.5rem, 3vw, 2.1rem); }
h3 { font-size: 1.2rem; }

.container { max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }

/* Visible focus ring - the whole site is keyboard reachable */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 3px solid var(--brand);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--forest);
  color: #fff;
  padding: 12px 20px;
  z-index: 200;
}
.skip-link:focus { left: 0; }

/* ---------- Utility bar ----------
   Phone number lives here and stays visible on every page. Paul and Leigh work off
   the phone, so the number is the primary conversion, not the form. */
.utility-bar {
  background: var(--forest-deep);
  color: #cfdbd2;
  font-size: 0.86rem;
}
.utility-bar .container {
  max-width: var(--maxw-header);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding-top: 7px;
  padding-bottom: 7px;
  flex-wrap: wrap;
}
.utility-bar a { color: #fff; text-decoration: none; }
.utility-bar a:hover { text-decoration: underline; color: #fff; }
.utility-bar .tagline { color: var(--brand-light); font-style: italic; font-weight: 600; }
.utility-links { display: flex; gap: 18px; flex-wrap: wrap; align-items: center; }

/* ---------- Header ---------- */
.site-header {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 50;
}
.site-header .container {
  max-width: var(--maxw-header);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 16px;
}
.logo img { max-height: 62px; width: auto; }
.logo { text-decoration: none; display: block; }

.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 1rem;
  color: var(--forest);
  cursor: pointer;
}

.main-nav ul {
  list-style: none;
  display: flex;
  gap: 22px;
  align-items: center;
  flex-wrap: wrap;
}
.main-nav a {
  text-decoration: none;
  color: var(--forest);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 6px 0;
  border-bottom: 2px solid transparent;
}
.main-nav a:hover,
.main-nav a[aria-current="page"] {
  color: var(--brand-ink);
  border-bottom-color: var(--brand);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  background: var(--brand);
  color: #fff;
  text-decoration: none;
  font-weight: 700;
  padding: 13px 26px;
  border-radius: var(--radius);
  border: none;
  cursor: pointer;
  font-size: 1rem;
  transition: background .15s ease, transform .15s ease;
}
.btn:hover { background: var(--brand-dark); color: #fff; transform: translateY(-1px); }
.btn-lg { padding: 16px 34px; font-size: 1.08rem; }
.btn-outline {
  background: transparent;
  color: #fff;
  border: 2px solid #fff;
}
.btn-outline:hover { background: #fff; color: var(--forest); }
.btn-forest { background: var(--forest); }
.btn-forest:hover { background: var(--forest-deep); }

.btn-row { display: flex; gap: 14px; flex-wrap: wrap; }

/* ---------- Hero ----------
   Modelled on the riversedge home hero band: no dark scrim, the photo keeps its
   own daylight, and the copy sits on a WHITE gradient that dissolves into the
   image rather than dimming it. The difference is that the photo here is full
   bleed instead of an inset panel.

   The copy sits on the LEFT, same side as riversedge.

   The photo is Chris's retouched IMG_1514, the cathedral ceiling with the crew
   painted out. It briefly was the truck-and-trailer village frame instead, and
   the band was tuned tightly around that photo's signwriting; Chris asked for
   the ceiling back on 2026-08-05, band treatment unchanged. Everything the truck
   forced is now relaxed, and the notes are kept below so nobody re-tightens them
   for a reason that no longer applies.

   What this photo needs instead is the opposite problem. The truck frame was
   busy and legible and the wash had to keep off it; sprayed foam is cream and
   near-white edge to edge, so a white wash on it has almost no visible boundary.
   Two consequences, both handled below:

     - The ramp is long (260px), not short. A short ramp against a pale photo
       terminates in a seam you can see but not read as a blend. A long one
       dissolves. There is no lettering left in the frame for it to spoil.
     - Text contrast is NOT at risk, though it looks like it should be. The copy
       column sits on the gradient's solid #fff end by construction (see the
       ::before geometry), so it is --forest on white at 10.76:1 regardless of
       what the photograph does behind it.

   The dark diagonal duct and the ladder in the lower left of the source sit at
   about 0-16%, under the copy, and are covered by the solid zone at every
   desktop width. They are the reason the wash cannot be made translucent.

   The source is pre-cropped to 2.10:1 in build-images.sh, so object-fit has very
   little to discard at band proportions and plain centring is correct. */
.hero {
  position: relative;
  background: var(--birch);
  overflow: hidden;
}
.hero-media {
  position: absolute;
  inset: 0;
}
.hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Pre-cropped to 2.10:1, close to the band, so there is almost nothing to
     discard and plain centring keeps both the vault line and the window heads.
     The 42% bias that was here belonged to the truck photo, which had sky to
     lose at the top; this frame's top edge is the ridge and cannot be trimmed. */
  object-position: center;
}
/* Deliberately NOT --maxw-header, and so deliberately out of line with the logo
   above it. The copy runs to the viewport edge so the white zone stays a narrow
   strip and the photo keeps the rest, which is the proportion riversedge has -
   there the panel is 0-30% and the building owns everything past it.
   To put it back on the container line: max-width: var(--maxw-header) and drop
   the padding overrides. One edit, but it pushes the wash past halfway and the
   band stops reading as a photograph at all. */
.hero .container {
  position: relative;
  z-index: 2;
  padding-top: 62px;
  padding-bottom: 62px;
  padding-left: clamp(20px, 3vw, 44px);
  padding-right: 20px;
  max-width: none;
  display: flex;
  justify-content: flex-start;
  min-height: 520px;
  align-items: center;
}
/* 400px is a floor, not a preference: below it the two CTAs stop fitting on one
   row, and a second button row adds 60px to the band. */
.hero-inner { position: relative; max-width: 400px; }
/* The white wash is anchored to the COPY COLUMN, not to the band.
   A percentage gradient on .hero-media looked right at 1440 and broke at 1024:
   the container hits its max-width and stops moving while the viewport keeps
   shrinking, so the column slides out from under a fade that stayed put.
   Pinning the fade to .hero-inner means the two can never separate - the ramp is
   always the same 260px immediately past the last character, at every width.
   260 and not the 150 the truck version used: that number existed only to keep
   haze off the truck door at 42-48% of that frame. This photograph has no
   lettering in it, and a pale subject needs the longer dissolve or the edge of
   the wash reads as a seam. 260px lands the far end at about 46% at 1440.
   Vertically it is deliberately oversized and clipped by .hero's overflow:hidden,
   because the copy box is only as tall as the copy and the wash must run the full
   height of the band. */
.hero-inner::before {
  content: '';
  position: absolute;
  z-index: -1;
  top: -600px;
  bottom: -600px;
  left: -50vw;
  right: -260px;
  /* 270deg so the gradient line runs right-to-left, which puts the 0px origin at
     this box's RIGHT edge. That matters: the left overhang is a viewport unit and
     the right ramp is a fixed 260px, so the stops have to be measured from the
     fixed end. Stops are in PIXELS, not percentages, for the same reason -
     percentages resolve against the whole box (260px ramp + column + 50vw
     overhang, about 1380px at 1440) and land nowhere near the copy.
     Note the last stop is at the ramp's full width, so the copy column itself is
     always on flat #fff - that is what keeps --forest at 10.76:1 over a photo
     that is itself almost white. */
  background: linear-gradient(270deg,
    rgba(255, 255, 255, 0) 0,
    rgba(255, 255, 255, 0.22) 70px,
    rgba(255, 255, 255, 0.62) 150px,
    rgba(255, 255, 255, 0.92) 215px,
    #fff 260px);
}
.hero h1 {
  color: var(--forest);
  margin-bottom: 16px;
  /* Smaller than the global h1. At the full 2.9rem this headline broke to four
     lines in a 420px column and drove the band to ~800px tall, which forced
     object-fit to crop the photo horizontally. */
  font-size: clamp(1.75rem, 2.5vw, 2.3rem);
}
.hero .kicker {
  display: inline-block;
  background: var(--brand);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: 5px 14px;
  border-radius: 30px;
  margin-bottom: 18px;
}
.hero .lede { font-size: 1.06rem; color: var(--ink-soft); margin-bottom: 26px; }
.hero .slogan {
  font-style: italic;
  font-weight: 700;
  color: var(--brand-ink);
  font-size: 1.05rem;
  margin-bottom: 10px;
}
/* The shared .btn-outline is white-on-transparent for dark bands and would
   vanish against this one. */
.hero .btn-outline {
  border: 2px solid var(--brand);
  color: var(--brand-ink);
  background: rgba(255, 255, 255, 0.75);
}
.hero .btn-outline:hover { background: #fff; color: var(--brand-dark); }
/* .btn-lg is sized for a full-width band and the two of them come to 464px side
   by side, which wraps to two rows in this column. A second row adds 60px to the
   band, and a taller band makes object-fit crop the photo horizontally. Measured
   at these values the pair is 391px against a 400px column. Do not raise the
   padding or the gap without re-measuring. */
.hero .btn-lg { padding: 13px 16px; font-size: 1rem; }
.hero .btn-row { gap: 12px; }

/* Stacked below 1100px, not riversedge's 900. A 400px column over a photo is
   unreadable on a phone no matter how it is faded, which gets you to about
   700px on its own. 1100 rather than 700 is a proportion argument: column plus
   ramp is 660px, so at 1024 the wash covers two-thirds of the band and there is
   no photograph left to speak of - the overlay is abandoned while it still looks
   deliberate. The ramp grew from 150px to 260px with the change of photo, so
   this threshold is now if anything slightly low; leave it, the stacked layout
   at 1024-1100 is not worse, just plainer. */
@media (max-width: 1100px) {
  .hero { overflow: visible; }
  .hero-media { position: static; }
  .hero-media img { height: 260px; object-position: center 50%; }
  .hero .container {
    display: block;
    min-height: 0;
    max-width: var(--maxw);
    padding-top: 34px;
    padding-bottom: 42px;
  }
  .hero-inner { max-width: none; }
  .hero-inner::before { content: none; }
  .hero .btn-lg { padding: 16px 34px; font-size: 1.08rem; }
}
@media (max-width: 560px) {
  .hero-media img { height: 200px; }
}

/* ---------- Pillar band ----------
   Lifted from riversedge, which runs this directly under the hero to state the
   positioning in four words before any body copy asks to be read. It also does
   real work on this page specifically: the hero now fades to white on its left,
   and without a band here the page runs white from the fade straight down into
   the first section.

   Evergreen rather than rust. The band sits a few hundred pixels below the rust
   hero buttons and the rust kicker pill, and a third rust element that size
   would make the accent the loudest thing on the page. Evergreen also ties the
   band to the utility bar above the header and the footer below.

   Not links, same as riversedge. Blown-in and dense pack have no page in Phase 1
   and linking three of four would look like the fourth was broken. */
.pillar-band { background: var(--forest); color: #fff; }
/* Edge padding matched to .hero .container, NOT riversedge's --maxw-header.
   The hero here runs to the viewport edge, so a band on the 1280 container line
   would start 57px right of the headline above it and the two full-bleed strips
   would look misaligned. Matching the hero gives one left edge for the whole
   full-bleed stack, with the centered --maxw content starting below it. */
.pillar-band .container {
  max-width: none;
  padding-left: clamp(20px, 3vw, 44px);
  padding-right: clamp(20px, 3vw, 44px);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  padding-top: 26px;
  padding-bottom: 26px;
}
.pillar {
  display: flex;
  align-items: flex-start;
  gap: 15px;
  padding: 4px 26px;
  border-left: 1px solid rgba(255, 255, 255, 0.22);
}
.pillar:first-child { border-left: 0; padding-left: 0; }
.pillar svg {
  width: 34px;
  height: 34px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.92;
}
/* A <p>, not an <h3> as riversedge has it. This band sits between the h1 and the
   page's first h2, so an h3 here skips a level and every accessibility audit
   flags it. These four words are labels, not document sections. */
.pillar-title {
  color: #fff;
  margin: 0 0 2px;
  font-size: 1rem;
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
/* 0.86 white on --forest is 9.4:1, comfortably past AA. */
.pillar p {
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.86);
}
@media (max-width: 900px) {
  .pillar-band .container { grid-template-columns: repeat(2, 1fr); gap: 22px 0; }
  .pillar:nth-child(odd) { border-left: 0; padding-left: 0; }
}
@media (max-width: 520px) {
  .pillar-band .container { grid-template-columns: 1fr; }
  .pillar { border-left: 0; padding-left: 0; }
}

/* ---------- Sections ---------- */
.section { padding: 64px 0; }
.section-tint { background: var(--birch); }
.section-forest { background: var(--forest); color: #fff; }
.section-forest h2, .section-forest h3 { color: #fff; }
.section-forest p { color: #dbe5dd; }

.section-head { max-width: 760px; margin-bottom: 34px; }
.section-head .eyebrow {
  display: block;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--brand-ink);
  margin-bottom: 8px;
}
.section-forest .eyebrow { color: var(--brand-light); }
.section-head p { color: var(--ink-soft); margin-top: 12px; font-size: 1.03rem; }

/* ---------- Cards ---------- */
.grid { display: grid; gap: 22px; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px;
  box-shadow: var(--shadow);
}
.card h3 { margin-bottom: 8px; }
.card p { color: var(--ink-soft); font-size: 0.96rem; }
a.card { text-decoration: none; color: inherit; display: block; transition: box-shadow .15s ease, transform .15s ease; }
a.card:hover { box-shadow: var(--shadow-lift); transform: translateY(-2px); }
a.card h3 { color: var(--brand-ink); }

.card-media { padding: 0; overflow: hidden; }
.card-media img { aspect-ratio: 4 / 3; object-fit: cover; width: 100%; }
.card-media .card-body { padding: 20px 22px 24px; }

/* ---------- Prose ---------- */
.prose { max-width: 760px; }
.prose > * + * { margin-top: 1.1rem; }
.prose h2 { margin-top: 2.2rem; }
.prose h3 { margin-top: 1.6rem; }
.prose ul, .prose ol { padding-left: 1.3rem; }
.prose li + li { margin-top: .45rem; }
.prose img { border-radius: var(--radius); margin: 1.6rem 0; }
.prose figure figcaption {
  font-size: 0.87rem;
  color: var(--ink-faint);
  margin-top: .5rem;
}

/* ---------- Page header (interior pages) ---------- */
.page-head {
  background: var(--forest);
  color: #fff;
  padding: 52px 0;
}
.page-head h1 { color: #fff; }
.page-head p { color: #cfdbd2; margin-top: 10px; max-width: 660px; }

.breadcrumbs {
  font-size: 0.85rem;
  color: #a9bcae;
  margin-bottom: 12px;
}
.breadcrumbs a { color: #fff; text-decoration: none; }
.breadcrumbs a:hover { text-decoration: underline; }

/* ---------- Gallery ---------- */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}
.gallery-grid figure {
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--birch);
  border: 1px solid var(--line);
}
.gallery-grid img { aspect-ratio: 4 / 3; object-fit: cover; width: 100%; }
.gallery-grid figcaption {
  padding: 11px 14px;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

/* Before/after pair - Leigh's photo sequence is the strongest asset on the site,
   so it gets a dedicated treatment rather than being scattered through the grid. */
.ba-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 18px; }
.ba-pair figure { position: relative; border-radius: var(--radius); overflow: hidden; }
/* The two halves are different shapes - the "foam" shot is landscape and the "finished"
   shot is portrait (shot on a phone turned sideways). Forcing a shared 4:3 keeps the pair
   reading as a matched set, which is the whole point of showing them together. Slightly
   above center because the crew and the finished wall sit in the middle of the tall frame. */
.ba-pair img {
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: center 42%;
  width: 100%;
}
.ba-pair figcaption {
  position: absolute;
  left: 12px;
  top: 12px;
  background: var(--forest-deep);
  color: #fff;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 20px;
}

/* ---------- Jobsite clips ----------
   Every clip Paul has given us is portrait 9:16, shot on a phone held upright, so the card is
   phone-shaped rather than fighting it into a landscape box. `max-width` on the card is what
   stops a single clip stretching into a full-height column on a wide screen - auto-fill alone
   would hand one item the entire row.

   aspect-ratio here is belt to the width/height attributes' braces: the box is reserved before
   the poster arrives, so nothing below shifts as media loads. */
.video-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 18px;
}
.video-card {
  position: relative;
  max-width: 340px;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--birch);
  border: 1px solid var(--line);
}
.video-card video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 9 / 16;
  background: var(--forest-deep);
}
.video-card figcaption {
  padding: 11px 14px;
  font-size: 0.88rem;
  color: var(--ink-soft);
}
.video-fallback { padding: 14px; color: #fff; }

/* ---------- Full screen clips ----------
   `.has-custom-fs` is added by main.js, never written into the HTML. That is what makes this
   safe: if the script does not run, the native fullscreen button below is NOT hidden and the
   reader keeps the browser's own control. See the long note in site/js/main.js.

   Both buttons ship from JS too, so a no-JS reader never sees a control that does nothing. */
.video-expand,
.video-close {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  cursor: pointer;
  color: #fff;
  background: rgba(20, 42, 29, 0.72);
  font-size: 1.05rem;
  line-height: 1;
}
.video-expand:hover,
.video-close:hover { background: var(--brand); }

.video-expand {
  top: 10px;
  right: 10px;
  width: 38px;
  height: 38px;
  border-radius: 50%;
}
/* The X is HIDDEN until the card is actually fullscreen, and it is deliberately bigger and
   further from the edge than the expand button. It is the only way out that does not require
   knowing about Esc, so it is sized to be hit with a thumb, not found with a cursor. */
.video-close { display: none; }

.has-custom-fs video::-webkit-media-controls-fullscreen-button { display: none; }

/* :fullscreen and :-webkit-full-screen MUST stay in separate blocks. A browser that cannot parse
   one of them throws away the WHOLE selector list, so comma-joining these would silently drop
   the styling in exactly the browsers the prefix exists for. */
/* The surround is --forest-deep, not black, and it has to be set on BOTH the card and the video.
   The video element keeps its own background for the pre-play state, so leaving it alone puts a
   black card behind a green-backed video and you can see the seam across the top of the screen. */
.video-card:fullscreen { max-width: none; width: 100%; height: 100%; border: 0; border-radius: 0;
  background: var(--forest-deep); display: flex; flex-direction: column; justify-content: center; }
.video-card:-webkit-full-screen { max-width: none; width: 100%; height: 100%; border: 0;
  border-radius: 0; background: var(--forest-deep); display: flex; flex-direction: column;
  justify-content: center; }

/* Height-driven, so the ELEMENT box is the shape of the clip rather than a full-width box with
   the picture letterboxed inside it. The native control bar is as wide as the element, so
   without this it stretches the width of the screen under a video a third that wide. */
.video-card:fullscreen video { width: auto; height: 86vh; max-width: 100%; margin: 0 auto;
  background: var(--forest-deep); }
.video-card:-webkit-full-screen video { width: auto; height: 86vh; max-width: 100%; margin: 0 auto;
  background: var(--forest-deep); }

.video-card:fullscreen figcaption { color: #cfdbd2; text-align: center; padding: 14px 60px; }
.video-card:-webkit-full-screen figcaption { color: #cfdbd2; text-align: center; padding: 14px 60px; }

.video-card:fullscreen .video-expand { display: none; }
.video-card:-webkit-full-screen .video-expand { display: none; }

/* Rust, not the translucent dark the expand button uses. Against a --forest-deep surround the
   translucent version is nearly invisible as a shape - the white glyph reads but the button does
   not, and this is the only exit a reader who does not know about Esc is going to find. */
.video-card:fullscreen .video-close { display: flex; top: 18px; right: 18px; width: 52px;
  height: 52px; border-radius: 50%; font-size: 1.5rem; background: var(--brand); }
.video-card:-webkit-full-screen .video-close { display: flex; top: 18px; right: 18px; width: 52px;
  height: 52px; border-radius: 50%; font-size: 1.5rem; background: var(--brand); }

.video-card:fullscreen .video-close:hover { background: var(--brand-dark); }
.video-card:-webkit-full-screen .video-close:hover { background: var(--brand-dark); }

/* A single clip standing beside its explanation, rather than in a grid of peers. The card is
   held to a narrow column because a 9:16 video given half a 1120px container becomes taller
   than the viewport and the copy beside it ends up floating against nothing. */
/* CENTER, not start. A 9:16 clip is always going to be taller than three paragraphs beside it -
   on the gallery the copy is 314px against a 588px card. Top-aligning puts all 274px of that
   difference in one hole under the last line, which reads as a layout fault. Splitting it above
   and below reads as a deliberate inset figure. Narrowing the clip cannot fix this on its own:
   a narrower card wraps its caption onto more lines and gives most of the height straight back. */
.case-video {
  display: grid;
  grid-template-columns: minmax(200px, 280px) 1fr;
  gap: 30px;
  align-items: center;
  margin-top: 26px;
}
/* Clip on the RIGHT instead. Used below the hero on the home page, where the argument has to be
   read before the evidence is worth anything - so the copy comes first in the DOM and the clip
   sits alongside it, which also means the mobile stack is text-then-video rather than the
   reverse. Nothing is reordered visually; the DOM order is the reading order in both layouts. */
/* NARROWER than the gallery's 280, because this one sits beside SHORT copy. Measured at a 1280
   viewport, which is the worst case: the container caps at 1120 so the copy column cannot get
   any wider, and a wider column means shorter text and more overhang. At 280 the card ran 588px
   against 397px of copy - nearly 200px of dead space under the callout. At 230, with the tighter
   caption this page uses, it is about 80px, which reads as level.

   Below 1120 the container shrinks, the copy reflows taller and the gap closes further, so this
   only ever gets better going down. */
.case-video.media-right { grid-template-columns: 1fr minmax(190px, 230px); }

@media (max-width: 640px) {
  /* .media-right is repeated here on purpose. `.case-video.media-right` is two classes and beats
     a bare `.case-video` at any width, so without it the two-column layout would survive down to
     a phone and crush the clip into a sliver. */
  .case-video,
  .case-video.media-right { grid-template-columns: 1fr; gap: 20px; }
  .video-card { max-width: none; }
}

/* ---------- FAQ ---------- */
.faq-item {
  border-bottom: 1px solid var(--line);
  padding: 4px 0;
}
.faq-item summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--forest);
  padding: 16px 0;
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: flex-start;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: '+';
  color: var(--brand-ink);
  font-size: 1.4rem;
  line-height: 1;
  flex-shrink: 0;
}
.faq-item[open] summary::after { content: '\2013'; }
.faq-item .faq-body { padding-bottom: 18px; color: var(--ink-soft); }
.faq-item .faq-body > * + * { margin-top: .8rem; }

/* ---------- Service area / towns ---------- */
.town-columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 28px;
}
.town-list { list-style: none; columns: 2; column-gap: 24px; }
.town-list li { padding: 4px 0; break-inside: avoid; }
.town-list a { text-decoration: none; font-weight: 600; }
.town-list a:hover { text-decoration: underline; }

/* ---------- Callout / CTA band ---------- */
.cta-band {
  background: var(--forest);
  color: #fff;
  padding: 54px 0;
  text-align: center;
}
.cta-band h2 { color: #fff; margin-bottom: 12px; }
.cta-band p { color: #cfdbd2; max-width: 620px; margin: 0 auto 24px; }
.cta-band .btn-row { justify-content: center; }
.cta-phone {
  display: block;
  font-size: clamp(1.6rem, 4vw, 2.3rem);
  font-weight: 800;
  color: #fff;
  text-decoration: none;
  margin-bottom: 6px;
}
.cta-phone:hover { color: var(--brand-light); }

.callout {
  background: var(--birch);
  border-left: 4px solid var(--brand);
  border-radius: 8px;
  padding: 20px 24px;
  margin: 1.8rem 0;
}
.callout p { color: var(--ink-soft); }
.callout strong { color: var(--forest); }

/* ---------- Rate table (cost page) ----------
   Stacks into labelled rows under 560px rather than scrolling sideways - the table is only
   three columns and the cost is the thing people are here for, so it should never need a
   horizontal drag on a phone. */
.rate-table {
  width: 100%;
  border-collapse: collapse;
  margin: 1.6rem 0;
  font-size: 0.97rem;
}
.rate-table caption {
  caption-side: top;
  text-align: left;
  font-size: 0.87rem;
  color: var(--ink-faint);
  padding-bottom: .6rem;
}
.rate-table th,
.rate-table td {
  text-align: left;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.rate-table thead th {
  background: var(--birch);
  color: var(--forest);
  font-size: 0.8rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-bottom: 2px solid var(--brand);
}
.rate-table tbody th { font-weight: 700; color: var(--ink); }
.rate-table tbody tr:last-child th,
.rate-table tbody tr:last-child td { border-bottom: none; }
.rate-note {
  display: block;
  font-weight: 400;
  font-size: 0.85rem;
  color: var(--ink-faint);
  margin-top: 2px;
}
.rate-cost {
  font-weight: 700;
  color: var(--brand-ink);
  white-space: nowrap;
}

@media (max-width: 560px) {
  .rate-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .rate-table, .rate-table tbody, .rate-table tr, .rate-table th, .rate-table td { display: block; }
  /* Without this the caption keeps display:table-caption inside a now-block table, shrink-wraps
     to its longest word, and renders one word per line. */
  .rate-table caption { display: block; width: 100%; }
  .rate-table tr {
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 4px 0;
    margin-bottom: 12px;
  }
  .rate-table th, .rate-table td { border-bottom: none; padding: 6px 16px; }
  .rate-table tbody td::before {
    content: attr(data-label) ": ";
    color: var(--ink-faint);
    font-weight: 400;
  }
}

/* ---------- Cost calculator ---------- */
.calc {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px;
  margin: 2rem 0;
  background: var(--birch);
}
.calc h3 { margin-top: 0; }
.calc-group { border: 0; margin: 0 0 18px; padding: 0; }
.calc-group legend {
  font-weight: 700;
  color: var(--forest);
  padding: 0;
  margin-bottom: 10px;
}
.calc-check { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.calc-check input { width: 18px; height: 18px; accent-color: var(--brand); }
.calc-hint { font-size: .88rem; color: var(--ink-faint); margin-top: 8px; }
.calc .field input, .calc .field select { background: var(--surface); }

.calc-working { margin-top: 24px; }
.calc-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 18px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
}
.calc-row .k { color: var(--ink-soft); }
.calc-row .v { font-variant-numeric: tabular-nums; font-weight: 600; text-align: right; }
.calc-sub .k, .calc-sub .v { color: var(--ink-faint); font-weight: 400; font-size: .93rem; }
.calc-total {
  border-bottom: none;
  border-top: 2px solid var(--brand);
  margin-top: 6px;
  padding-top: 14px;
}
.calc-total .k { color: var(--forest); font-weight: 700; }
.calc-total .v { color: var(--brand-ink); font-size: 1.3rem; font-weight: 700; }
.calc-caveat { font-size: .92rem; color: var(--ink-soft); margin-top: 16px; }
.calc-error { color: var(--brand-ink); font-weight: 600; margin-top: 18px; }

/* The shared .btn-outline is white-on-transparent for dark bands and disappears against this
   birch panel - the same fix .hero .btn-outline needs, for the same reason. */
.calc .btn-outline { border: 2px solid var(--brand); color: var(--brand-ink); }
.calc .btn-outline:hover { background: var(--brand); color: #fff; }

@media (max-width: 560px) {
  .calc { padding: 20px 16px; }
  .calc-row { flex-direction: column; gap: 2px; }
  .calc-row .v { text-align: left; }
}

/* ---------- Forms ---------- */
.form-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.field { display: flex; flex-direction: column; gap: 6px; }
.field-full { grid-column: 1 / -1; }
.field label { font-weight: 600; font-size: 0.92rem; color: var(--forest); }
.field .hint { font-size: 0.82rem; color: var(--ink-faint); font-weight: 400; }
.field input,
.field select,
.field textarea {
  font-family: inherit;
  font-size: 1rem;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
}
.field textarea { min-height: 140px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--brand); }

/* Honeypot - hidden from people, visible to bots */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-status { margin-top: 14px; font-weight: 600; }
.form-status.error { color: #a1281f; }
.form-status.ok { color: #1d6b3f; }

/* ---------- Footer ---------- */
.site-footer {
  background: var(--forest-deep);
  color: #b9c9be;
  padding: 52px 0 26px;
  font-size: 0.94rem;
}
.site-footer h4 {
  color: #fff;
  font-size: 0.8rem;
  letter-spacing: .11em;
  text-transform: uppercase;
  margin-bottom: 14px;
}
.site-footer a { color: #dfe8e1; text-decoration: none; }
.site-footer a:hover { color: var(--brand-light); text-decoration: underline; }
.site-footer ul { list-style: none; }
.site-footer li { padding: 3px 0; }
.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 32px;
  padding-bottom: 30px;
  border-bottom: 1px solid rgba(255,255,255,.12);
}
.footer-bottom {
  padding-top: 20px;
  display: flex;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  font-size: 0.86rem;
  color: #8ea395;
}
.footer-slogan { color: var(--brand-light); font-style: italic; font-weight: 600; }

/* ---------- Sticky mobile call bar ----------
   Deliberate: leads reach Paul and Leigh by phone, not email. On mobile the call
   button is always one thumb-tap away. */
.call-bar { display: none; }

/* ---------- Responsive ---------- */
@media (max-width: 860px) {
  .nav-toggle { display: block; }
  .main-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow);
    padding: 8px 20px 18px;
  }
  .main-nav.open { display: block; }
  .main-nav ul { flex-direction: column; align-items: stretch; gap: 0; }
  .main-nav li { border-bottom: 1px solid var(--line-soft); }
  .main-nav a { display: block; padding: 13px 0; }
  .site-header .container { position: relative; }

  .hero .container { padding-top: 56px; padding-bottom: 56px; }
  .section { padding: 46px 0; }
  .town-list { columns: 1; }

  .call-bar {
    display: flex;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 90;
    box-shadow: 0 -2px 14px rgba(20,42,29,.2);
  }
  /* WHITE-SPACE: NOWRAP IS THE WHOLE FIX HERE, not the padding. The label used to read
     "Call (207) 452-2930", which wrapped onto a second line on a phone and made this bar
     DOUBLE HEIGHT - it was eating roughly 110px off the bottom of every screen and cutting
     the page copy off mid-sentence. The word "Call" is gone from the visible label (it lives
     in aria-label now) and the number is pinned to one line so it can never come back.

     Sized to survive a 320px screen: at 0.95rem the number is about 120px, plus a 16px icon,
     a 6px gap and 12px of padding, inside a 160px half. */
  .call-bar a {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    white-space: nowrap;
    text-align: center;
    padding: 12px 6px;
    line-height: 1.25;
    font-weight: 700;
    text-decoration: none;
    color: #fff;
    font-size: 0.95rem;
  }
  .call-bar svg { flex: none; }
  .call-bar .call { background: var(--brand); }
  .call-bar .quote { background: var(--forest); }
  /* Keep the fixed bar from covering the end of the page. THIS NUMBER MUST TRACK THE BAR'S
     ACTUAL HEIGHT - it was 54px for a bar that had quietly become ~110px tall by wrapping onto
     two lines, which is why the last paragraph of every page was sitting underneath it. Measure
     the bar after changing its padding or font size rather than guessing. */
  body { padding-bottom: 44px; }
}

@media (max-width: 520px) {
  .utility-bar .tagline { display: none; }
  .btn { width: 100%; text-align: center; }
  .btn-row { flex-direction: column; }
}

/* ---------- Print ---------- */
@media print {
  .utility-bar, .site-header, .call-bar, .cta-band, .site-footer { display: none; }
  body { padding-bottom: 0; }
  .hero-media { display: none; }
  .hero { background: none; color: #000; }
  .hero h1 { color: #000; }
}

/* ---------- Motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation: none !important; }
}
