/* ==========================================================================
   Perez Design Build Remodel — public site
   --------------------------------------------------------------------------
   "Lit."

   The page is a dark gallery wall. Charcoal carries every section, and the
   photography is the only thing on the site allowed to hold colour — the way
   Kohler hangs its rooms in near-black and lets the tile do the talking. The
   light is now the punctuation: exactly one bone band, at the proof, where
   the survey figures should land like a printed page.

   Structure is borrowed from the drawings this company produces before it
   builds: hairlines, and the DIMENSION LINE — a rule with tick terminators
   carrying a measured value. It runs under the hero headline, beside each
   process step, and under the photographs. Nothing else decorates.

   Palette:

     #171414  charcoal  primary. The ground for everything.
     #413D3D  slate     the trades panel — a neutral step above the charcoal,
                        so the photography in it carries no colour cast.
     #F5ECE8  bone      the type, every accent, and the single light band.
     #8A182A  brick     sampled from the logo artwork. Buttons, and the two
                        saturated sheets (promise, call to action).
     #A81E33  lift      the brighter poster red the social work uses as a
                        full-bleed ground.

   One light and one red, and nothing else. Bone carries every accent as well
   as the type: on charcoal the hierarchy is brightness, not hue — the label
   and the emphasis sit at full bone, the running text a step below it. Red
   is never type on a dark ground; it is a ground, or it sits on bone.

   The red is darker than signal red on purpose: brick, not siren. Deep enough
   to read as a forty-year-old firm, plain enough that a $12k bathroom feels as
   welcome here as a custom home.
   ========================================================================== */

:root {
  /* The drafting sheet: a quarter-inch field with a heavier line every
     eight squares, shared by every surface that shows it. */
  --sheet-grid:
    linear-gradient(to right,  rgba(168, 30, 51, .34) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(168, 30, 51, .34) 1px, transparent 1px),
    linear-gradient(to right,  rgba(168, 30, 51, .17) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(168, 30, 51, .17) 1px, transparent 1px);
  --sheet-size: 12rem 12rem, 12rem 12rem, 1.5rem 1.5rem, 1.5rem 1.5rem;

  /* Grounds — charcoal. The room is lit now, not primed: the page is the
     dark gallery wall and the photography is the only thing that carries
     colour. Three steps, close together, so a band change reads as a shift
     of light rather than as a stripe. */
  --char:       #171414;
  --char-2:     #1E1A1A;
  --char-3:     #2A2323;

  --paper:      var(--char);    /* .band and the body ground */
  --paper-2:    var(--char-2);  /* the alternating band */
  --blush-wash: var(--bone);    /* the one light band, see .band--blush */

  /* Deeper than the ground, for the footer and the hero backstop */
  --night:      #100E0E;
  --night-2:    #151212;
  --wine:       #371718;
  --midnight:   #211E2F;
  /* Slate. A true neutral step above the charcoal — the trades band reads as
     a lighter panel set into the page rather than as a second dark. Neutral
     rather than warm on purpose: it gives the brick worked into that panel a
     grey to sit against, so the red reads as red. */
  --slate:      #313131;
  --blush:      #EBCCCD;

  /* Red — sampled from the logo artwork itself (#8A182A). The old brick was
     both darker and warmer than the mark, which is why the wordmark never
     quite sat right on it. Lift is the brighter poster red the social work
     uses as a full-bleed ground. */
  --brick:      #8A182A;
  --brick-deep: #5E1020;
  --brick-lift: #A81E33;
  --brick-soft: rgba(245, 236, 232, .10);

  /* The off-white is the type now, not the ground */
  --bone:  #F5ECE8;

  /* Type colours on charcoal */
  --ink:   var(--bone);
  --ink-2: rgba(245, 236, 232, .72);
  --ink-3: rgba(245, 236, 232, .58);

  /* Scoped tokens — every component reads these, so the same markup works on
     charcoal and on the one light band without a single override. */
  --fg:      var(--ink);
  --fg-2:    var(--ink-2);
  --fg-3:    var(--ink-3);
  --accent:  var(--bone);
  /* What reads on top of an accent FILL. Separate from --btn-fg, which pairs
     with --btn-bg: once brass went, accent and btn-fg both resolved to bone
     and .link:hover painted bone on bone. */
  --accent-fg: var(--char);
  --rule:    rgba(245, 236, 232, .16);
  --rule-2:  rgba(245, 236, 232, .08);
  --surface: rgba(245, 236, 232, .04);
  --btn-bg:  var(--brick-lift);
  --btn-fg:  var(--bone);

  /* Legacy aliases — inline styles in the templates still read these */
  --signal:    var(--brick);
  --muted:     var(--ink-2);
  --umber:     var(--ink-2);
  --border:    var(--rule);
  --fg-muted:  var(--ink-2);
  --fg-faint:  var(--ink-3);
  --serif:     var(--display);

  /* Depth — one soft shadow, for photographs only. Nothing else lifts.
     Pitched to true black now: an ink-tinted shadow is invisible on charcoal. */
  --shadow:      0 1px 1px rgba(0, 0, 0, .28), 0 10px 30px rgba(0, 0, 0, .38);
  --shadow-lift: 0 2px 3px rgba(0, 0, 0, .32), 0 20px 52px rgba(0, 0, 0, .48);

  /* Typekit only — the site's two fonts, nothing else. Freight Big Pro is
     the voice at display sizes, Grtsk carries the body and every piece of
     UI. Eyebrows and quotes read the display face upright; the GuildQuality
     verdict is the one place italics run, and even there the award year is
     forced back upright. The bare generic after each is the CSS-required
     last resort, not a third font. */
  --display: 'freight-big-pro', serif;
  --body: 'grtsk-vf', sans-serif;
  --ui: 'grtsk-vf', sans-serif;

  --step--2: 0.7rem;
  --step--1: 0.85rem;
  --step-0:  1.0625rem;
  --step-1:  1.2rem;
  --step-2:  clamp(1.4rem, 1.24rem + 0.62vw, 1.82rem);
  --step-3:  clamp(1.9rem, 1.48rem + 1.7vw, 2.95rem);
  --step-4:  clamp(2.3rem, 1.7rem + 2.5vw, 3.9rem);
  --step-5:  clamp(2.5rem, 1.65rem + 3.85vw, 5.1rem);
  /* Masthead scale. Section heads are furniture on most sites and the event
     on an editorial one; this is the step that makes them the event. */
  --step-6:  clamp(2.6rem, 1.45rem + 5.4vw, 6.4rem);

  /* Tracking — negative through the serif, so the display sets tight and
     modern rather than airy and expensive. */
  --tight:   -0.022em;
  --tighter: -0.035em;

  --gutter: clamp(1.25rem, 0.9rem + 2vw, 3.5rem);
  --band:   clamp(4.75rem, 3.2rem + 6vw, 9rem);
  --shell:  74rem;

  --radius: 2px;
  /* Buttons round more than plates and photos: the softer corner reads as
     pressable, while cards keep the near-square edge of the print grid. */
  --radius-btn: 5px;
  /* Flex centring aligns the line box, not the ink: the font's descent
     space sits below the baseline with nothing in it on a label like
     "Text Us", so the type reads high. Every button trades this much
     padding from its bottom to its top to settle the label optically. */
  --btn-nudge: 1px;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* The dark scope. Now the same family as the base ground rather than its
   opposite — it only lifts the rules a little, because wine and brick are
   warmer than charcoal and a rule at .16 disappears on them. */
.on-dark,
.band--slate,
.ch-ground,
.band--brick,
.topbar,
.footer {
  --fg:      var(--bone);
  --fg-2:    rgba(245, 236, 232, .76);
  --fg-3:    rgba(245, 236, 232, .56);
  --accent:  var(--bone);
  --accent-fg: var(--char);
  --rule:    rgba(245, 236, 232, .22);
  --rule-2:  rgba(245, 236, 232, .12);
  --surface: rgba(245, 236, 232, .06);
  --btn-bg:  var(--bone);
  --btn-fg:  var(--char);
  color: var(--fg);
}

*, *::before, *::after { box-sizing: border-box; }

/* --------------------------------------------------------------------------
   Grain and registration marks — carried over from the social work

   Every poster the studio puts out is printed-feeling: a film grain across
   the whole sheet, and thin corner marks set in from two opposite corners,
   like crop marks left on a proof. The grain is most of why a flat red fill
   reads as a printed sheet rather than as a div, and charcoal needs it more
   than plaster did — a large dark fill is the flattest thing on a screen.

   Pitched deliberately below the threshold where it reads as texture: you
   should only notice it when it is gone.
   -------------------------------------------------------------------------- */

body::after {
  content: '';
  position: fixed; inset: 0; z-index: 400;
  pointer-events: none;
  opacity: .055;
  background-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20width='160'%20height='160'><filter%20id='n'><feTurbulence%20type='fractalNoise'%20baseFrequency='0.82'%20numOctaves='3'%20stitchTiles='stitch'/><feColorMatrix%20type='saturate'%20values='0'/></filter><rect%20width='160'%20height='160'%20filter='url%28%23n%29'/></svg>");
  background-size: 160px 160px;
}

/* The marks belong to the saturated sheets, the way they do on the posters —
   not to every band, or they stop meaning anything. */
.band--brick::after,
.cta::after,
.ch-note::after,
.ch-break--brick::after,
.ch-more::after,
.pr-step::after,
.aw-row::after,
.quote-stack--tiles .quote::after {
  content: '';
  position: absolute; inset: clamp(1rem, .6rem + 1.4vw, 2.1rem);
  pointer-events: none;
  background:
    linear-gradient(var(--rule), var(--rule)) left  top    / 1px 3.4rem no-repeat,
    linear-gradient(var(--rule), var(--rule)) left  top    / 3.4rem 1px no-repeat,
    linear-gradient(var(--rule), var(--rule)) right bottom / 1px 3.4rem no-repeat,
    linear-gradient(var(--rule), var(--rule)) right bottom / 3.4rem 1px no-repeat;
}

/* On the small tiles the marks sit tighter to the edge and run shorter. */
.pr-step::after,
.aw-row::after,
.quote-stack--tiles .quote::after {
  inset: .7rem;
  background-size: 1px 2.2rem, 2.2rem 1px, 1px 2.2rem, 2.2rem 1px;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: 9.5rem;
  -webkit-text-size-adjust: 100%;
}

/* The body face (grtsk-vf) is a variable font whose slant axis runs both
   ways, -15 to +15. Chrome settles upright text at 0; Safari draws it at the
   backward end unless told otherwise. Set on every element rather than
   inherited from body, because Safari's own styles for buttons and form
   fields reset font settings instead of inheriting them (the nav links are
   buttons). Nothing on the site sets another variation, so !important only
   guards against that reset. The display face is not variable and ignores
   it. */
*, *::before, *::after { font-variation-settings: 'slnt' 0 !important; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--fg);
  font-family: var(--body);
  font-size: var(--step-0);
  line-height: 1.65;
  letter-spacing: -0.003em;
  /* The body face (grtsk-vf) is a variable font with a slant axis that runs
     both ways, -15 to +15. Chrome settles upright text at 0, but Safari has
     drawn it leaning backwards, so the upright setting is pinned here
     rather than left to each browser's default. Inherited, so it holds for
     every element; the display face is not variable and ignores it. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

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

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: var(--tight);
  text-wrap: balance;
}
h1, h2 { font-weight: 700; }
h1 { letter-spacing: var(--tighter); }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }
figure, blockquote { margin: 0; }

::selection { background: var(--brick); color: var(--bone); }
:focus-visible { outline: 2px solid var(--brick); outline-offset: 3px; }
.on-dark :focus-visible, .band--slate :focus-visible,
.cta :focus-visible, .footer :focus-visible { outline-color: var(--bone); }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  padding: .75rem 1.25rem; background: var(--night); color: var(--bone);
}
.skip-link:focus { left: 0; }

.visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   Shell and bands
   -------------------------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: calc(var(--shell) + (var(--gutter) * 2));
  padding-inline: var(--gutter);
  margin-inline: auto;
}
.shell--narrow { max-width: calc(50rem + (var(--gutter) * 2)); }
.shell--wide   { max-width: calc(84rem + (var(--gutter) * 2)); }

.band { position: relative; padding-block: var(--band); background: var(--paper); }
.band--tight { padding-block: calc(var(--band) * .58); }
/* Sits close under whatever precedes it: the top padding is trimmed, the
   bottom is left alone. */
.band--close { padding-top: calc(var(--band) * .55); }

/* Alternating charcoal. A half-tone lift, nothing more — the eye should read
   a change of light in the same room, not a different surface. */
.band--dark, .band--tint { background: var(--paper-2); }

/* The one light band, and the only one on the page: bone, with the whole
   scope flipped back to dark-on-light. It is spent where the proof is, so
   the survey figures land on the page like a printed page rather than a
   screen. Everything above and below it is charcoal, which is what makes
   this one section arrive. */
.band--blush,
.masthead,
.on-light {
  --fg:      var(--char);
  --fg-2:    rgba(23, 20, 20, .74);
  /* .54 reads fine as a hairline but drops small captions to 3.8:1 on bone;
     the faint step has to be firmer on light than it is on charcoal. */
  --fg-3:    rgba(23, 20, 20, .66);
  --accent:  var(--brick);
  --accent-fg: var(--bone);
  --rule:    rgba(23, 20, 20, .18);
  --rule-2:  rgba(23, 20, 20, .10);
  --surface: rgba(23, 20, 20, .04);
  --btn-bg:  var(--brick);
  --btn-fg:  var(--bone);
  color: var(--fg);
}
.band--blush { background: var(--bone); }

/* The trades band — the section this whole direction was built out from.
   Neutral slate rather than wine: against charcoal it reads as a lighter
   panel set into the page, and it stops competing with the two saturated
   red sheets further down. The corner lights are kept but pulled to neutral,
   so the panel has some depth without a colour cast. */
/* Slate on its own reads as a grey box. Brick is worked into the panel two
   ways instead — as light and as line — because it cannot be worked in as
   type: #8A182A on #413D3D is 1.5:1, invisible. Neither of these carries any
   legibility load, so the red can be fully saturated. */
.band--slate,
.ch-ground {
  background:
    /* Two blooms of brick, low and soft, so the panel is lit warm from the
       top right and banked at the foot rather than tinted evenly. */
    radial-gradient(76rem 48rem at 94% -16%, rgba(138, 24, 42, .48), transparent 66%),
    radial-gradient(56rem 36rem at -8% 112%, rgba(138, 24, 42, .34), transparent 64%),
    radial-gradient(52rem 34rem at 20% 118%, rgba(0, 0, 0, .26), transparent 60%),
    var(--slate);
  --accent: var(--bone);
}

/* The drafting grid.

   This is the design half of design/build — the panel opens on a designer
   over blueprints — so the substrate behind it is the paper that work is
   drawn on: a quarter-inch field with a heavier line every eight squares,
   the way a drafting sheet is ruled. Generated rather than photographed, so
   it costs nothing and stays sharp at any density.

   Masked to a soft ellipse so it never reaches an edge. A grid that runs to
   the bleed reads as wallpaper; one that fades reads as the sheet the panel
   is resting on, which is the whole point. */
.band--slate::before,
.ch-ground::before {
  content: '';
  position: absolute; inset: 0; z-index: 0;
  pointer-events: none;
  background-image: var(--sheet-grid);
  background-size: var(--sheet-size);
  -webkit-mask-image: radial-gradient(115% 95% at 50% 42%, #000 26%, transparent 80%);
          mask-image: radial-gradient(115% 95% at 50% 42%, #000 26%, transparent 80%);
}
/* The band's own content sits above the grid: a positioned pseudo-element
   would otherwise paint over unpositioned in-flow children. */
.band--slate > .shell { position: relative; z-index: 1; }


/* The same lit slate ground on the pages built from photo chapters, where
   a charcoal card on a charcoal page read as black on black. It carries the
   runs of chapters (a service page's levels, offerings and local panel as
   one continuous sheet; a gallery section's projects; a project's story),
   and the intro, form and questions stay on charcoal, so the page
   alternates between the two. */
.ch-ground { position: relative; padding-top: var(--sv-space); }
.ch-ground > * { position: relative; z-index: 1; }
.ch-ground + .ch-section { padding-top: var(--sv-space); }
/* A questions section ends with no space of its own (.sv-section pads only
   its top), so the consultation that follows it opens with the gap itself. */
.sv-section + .ch-section { padding-top: var(--sv-space); }

/* A hairline seam wherever two plaster bands of the same tone meet, so the
   page reads as sheets set down next to each other. */
.band + .band:not(.band--slate)::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: var(--rule-2);
}

/* --------------------------------------------------------------------------
   The dimension line — the page's one recurring device
   -------------------------------------------------------------------------- */

.dim {
  display: flex; align-items: center; gap: .95rem;
  margin: 0;
  font-family: var(--ui);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.dim::before, .dim::after {
  content: '';
  flex: 1 1 auto;
  min-width: 1.5rem;
  height: 7px;
  border-left: 1px solid var(--rule);
  border-right: 1px solid var(--rule);
  background: linear-gradient(var(--rule), var(--rule)) 0 50% / 100% 1px no-repeat;
}
.dim--lead::before { display: none; }
.dim--lead { justify-content: flex-start; }
.dim--lead::after { flex: 0 1 14rem; }

/* --------------------------------------------------------------------------
   Type helpers
   -------------------------------------------------------------------------- */

/* Eyebrows are set in the body serif, upright, sentence case — editorial, not
   the wide-tracked capitals every remodeler's site reaches for. */
.label {
  display: block;
  margin: 0 0 1rem;
  font-family: var(--display);
  font-style: normal;
  font-size: 1.1rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--accent);
}
.head--center .label { text-align: center; }

.lede {
  font-size: var(--step-1);
  line-height: 1.6;
  letter-spacing: -0.008em;
  color: var(--fg-2);
  max-width: 54ch;
}

/* --------------------------------------------------------------------------
   Editorial furniture

   The rail: a section kicker in tiny tracked capitals at one end, and a
   hairline across the measure — the strip that runs across the top of a
   magazine spread. It used to carry a CSS-counter folio number at the other
   end too; dropped site-wide since it read as clutter rather than structure.
   -------------------------------------------------------------------------- */

.rail {
  display: flex; align-items: center; gap: clamp(.9rem, .6rem + 1vw, 1.6rem);
  margin: 0 0 clamp(1.6rem, 1rem + 1.8vw, 2.6rem);
  font-family: var(--ui);
  font-size: .68rem; font-weight: 600;
  letter-spacing: .3em; text-transform: uppercase;
  color: var(--accent);
}
.rail span { flex: 0 0 auto; order: 0; }
/* ::before is first in source order by default, so it needs an explicit
   order after the label — otherwise the tied order:0 falls back to source
   order and the hairline jumps ahead of the label instead of following it. */
.rail::before { content: ''; flex: 1 1 auto; height: 1px; background: var(--rule); order: 1; }

.prose { max-width: 66ch; }

/* The opening letter of a prose page, set as an initial. */
.prose > p:first-of-type::first-letter {
  float: left;
  font-family: var(--display);
  font-size: 4.1em; line-height: .8;
  font-weight: 600;
  padding: .04em .09em 0 0;
  color: var(--accent);
}
.prose h2 { font-size: var(--step-2); margin: 2.1em 0 .55em; }
.prose h3 { font-size: var(--step-1); margin: 1.8em 0 .45em; }
.prose p, .prose li { color: var(--fg-2); }
.prose ul, .prose ol { padding-left: 1.1em; margin: 0 0 1.1em; }
.prose li { margin-bottom: .35em; }
.prose a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
}
.prose a:hover { color: var(--brick-deep); }
.on-dark .prose a:hover, .band--slate .prose a:hover, .footer a:hover { color: var(--bone); }

em { font-style: normal; }
.rule { height: 1px; background: var(--rule-2); margin: 2.5rem 0; }

/* --------------------------------------------------------------------------
   Buttons and links — flat brick, no gradient, no glow
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: .55rem;
  padding: calc(.92rem + var(--btn-nudge)) 1.7rem calc(.92rem - var(--btn-nudge));
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid transparent;
  border-radius: var(--radius-btn);
  font-family: var(--body);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.006em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .18s var(--ease), color .18s var(--ease),
              border-color .18s var(--ease);
}
.btn:hover { background: var(--brick-deep); color: var(--bone); }
.on-dark .btn:hover, .band--slate .btn:hover { background: var(--bone); color: var(--night); }

.btn--outline {
  background: transparent;
  color: var(--fg);
  border-color: var(--rule);
}
.btn--outline:hover {
  background: var(--fg);
  color: var(--paper);
  border-color: var(--fg);
}

/* Secondary action: a quiet outlined button in the accent, so "see more"
   destinations read as actions without competing with the solid brick CTA. */
.link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: .55rem;
  padding: calc(.78rem + var(--btn-nudge)) 1.45rem calc(.78rem - var(--btn-nudge));
  border: 1px solid var(--accent);
  border-radius: var(--radius-btn);
  color: var(--accent);
  font-family: var(--body);
  font-size: .98rem;
  font-weight: 600;
  text-decoration: none;
  letter-spacing: -0.006em;
  transition: gap .18s var(--ease), color .18s var(--ease),
              background-color .18s var(--ease), border-color .18s var(--ease);
}
.link:hover { gap: .8rem; background: var(--accent); color: var(--accent-fg); }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.6rem; }

/* --------------------------------------------------------------------------
   Masthead — a brick strip over a quiet plaster bar. The logo sits left, the
   links right, and the three service menus open as full-width plaster panels
   (the "mega" below) built from the category's own summary and photograph.
   -------------------------------------------------------------------------- */

/* A solid brick strip at every scroll position: never glass, so it reads
   the same over the hero footage and over the light sections below. */
.topbar {
  background: var(--brick);
  color: var(--bone);
  font-family: var(--ui);
  font-size: .9rem;
  letter-spacing: .005em;
  /* Sticks above the masthead, so Call and Text stay on screen however far
     down the page you are. site.js measures it into --topbar-h, which is
     where the masthead sticks. */
  position: sticky; top: 0; z-index: 101;
}
.topbar__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  padding-block: .5rem;
}
.topbar__sep { font-style: normal; opacity: .55; margin-inline: .25rem; }
.topbar a { color: var(--bone); text-decoration: none; font-weight: 600; }
.topbar a:hover { color: var(--bone); }
.topbar__right { display: flex; align-items: center; gap: 1.1rem; }
/* Baseline, not center: the UI face carries its caps high in the line box,
   so a centred icon read low. On the baseline the clock spans the caps. */
.topbar__hours { display: flex; align-items: baseline; gap: .4rem; color: var(--bone); }
.topbar__hours i.fa-clock { opacity: .7; font-size: .85em; }
.topbar__hours .topbar__sep { margin-inline: .1rem; }
.topbar__left { display: inline-flex; align-items: center; gap: .6rem; }

/* Quiet chips rather than plain links — each reads as its own tappable
   action instead of a line of body text. Call and Text are two chips with
   two numbers, side by side at every width: on desktop each spells out its
   number, on a phone the mobile breakpoint swaps the number for "Call us" /
   "Text us". */
.topbar__text, .topbar__phone {
  align-items: center; gap: .4rem;
  padding: calc(.2rem + var(--btn-nudge)) .65rem calc(.2rem - var(--btn-nudge));
  border: 1px solid rgba(245, 236, 232, .4);
  border-radius: var(--radius-btn);
  font-weight: 600;
  transition: background-color .18s var(--ease), border-color .18s var(--ease);
}
.topbar__text, .topbar__phone { display: inline-flex; }
.topbar__phone-call { display: none; }
/* Desktop shows the text number as words, not a link; a phone gets the
   tappable "Text us" instead. The static chip drops the hover. */
.topbar__text--mobile { display: none; }
span.topbar__text { cursor: text; user-select: all; }
/* The floater's two faces; see partials/text_fab.html. */
.text-fab__desktop { display: contents; }
.text-fab__mobile { display: none; }
a.topbar__text:hover, .topbar__phone:hover {
  background: rgba(245, 236, 232, .12); border-color: rgba(245, 236, 232, .6);
}

.masthead {
  position: sticky; top: var(--topbar-h, 0px); z-index: 100;
  background: var(--bone);
  border-bottom: 1px solid var(--rule-2);
  transition: border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.masthead[data-scrolled='true'] {
  border-bottom-color: var(--rule);
  box-shadow: 0 1px 0 rgba(0, 0, 0, .22), 0 10px 30px rgba(0, 0, 0, .30);
}

/* A 5-track grid only balances the two *spacer* columns against each other.
   It does not put the links on the bar's true midpoint unless the logo and
   Call Now happen to be the same width, which they aren't (197px vs 109px),
   so the whole row still skewed by half that difference. Absolute
   positioning sidesteps the asymmetry entirely: inset: 0 plus margin: auto
   on both axes centres the (shrink-to-fit, width: max-content) link run on
   this box's actual midpoint regardless of what sits on either side of it.
   Deliberately not left: 50% + a translate(-50%): a transform here, even a
   centring one, makes this element a containing block for any
   position: fixed descendant (the mega panels below need to fix themselves
   to the viewport, not to this row). <nav> collapses to `display: contents`
   so its two children (the links and Call Now) act as direct children of
   this row; the mobile breakpoint gives it a real box back for the drawer. */
.masthead__inner {
  position: relative;
  display: flex; align-items: center;
  gap: 1.5rem; padding-block: .3rem;
}

.wordmark { display: inline-flex; align-items: center; flex: 0 0 auto; }
.wordmark img { display: block; height: 4rem; width: auto; }

.nav { display: contents; }
.nav__links {
  position: absolute; inset: 0; margin: auto;
  width: max-content; height: max-content;
  display: flex; align-items: center; gap: .6rem;
}
.nav-item { position: relative; }

.nav-link {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .75rem .8rem;
  background: none; border: 0; cursor: pointer;
  font-family: var(--body);
  font-size: 1.08rem; font-weight: 400;
  letter-spacing: .015em;
  white-space: nowrap;
  color: var(--fg-2); text-decoration: none;
  transition: color .18s var(--ease);
}
.nav-link:hover, .nav-item[data-open='true'] .nav-link { color: var(--brick); }
/* The desktop row is capped by the shell, so its links sit a little
   tighter than the drawer's. */
@media (min-width: 72.501rem) {
  .nav__links { gap: .2rem; }
  .nav-link { padding-inline: .55rem; font-size: 1rem; }
}

/* The Andersen link is the horizontal Elite Certified Contractors mark. The
   drawer has room for it a little larger; in the desktop row it sits at
   about the height of the link text, so it doesn't crowd its neighbours. */
.nav-link--andersen { padding-block: .25rem; }
.nav-link--andersen img { display: block; height: 2.4rem; width: auto; transition: opacity .18s var(--ease); }
.nav-link--andersen:hover img { opacity: .8; }
@media (min-width: 72.501rem) {
  .nav-link--andersen img { height: 2.1rem; }
}

.nav__cta { margin-left: auto; }
/* Same liquid glass as the hero buttons, but the tint has to work over two
   very different backdrops: transparent-over-video pre-scroll, and solid
   bone once the bar resolves (here, and on every page without a hero at
   all). The same translucency that reads as brick over dark footage washes
   out to pink over white paper, so the scrolled/no-hero state gets a denser,
   near-opaque fill instead of a lighter one — same glass, same blur, just
   enough pigment behind it to hold its color on paper. */
.nav__cta .btn {
  padding: calc(.7rem + var(--btn-nudge)) 1.25rem calc(.7rem - var(--btn-nudge));
  font-size: 1.05rem; font-weight: 400; white-space: nowrap;
  border: 0;
  background: rgba(168, 30, 42, .5);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  box-shadow: 0 6px 18px rgba(16, 14, 14, .18);
  transition: background-color .25s var(--ease), transform .25s var(--ease),
              box-shadow .25s var(--ease);
}
.nav__cta .btn:hover { background: rgba(138, 24, 42, .3); transform: translateY(-1px); }
/* Over the resolved bar — every non-hero page, where the masthead is bone
   from the first paint, and a hero page once it's scrolled past the video. */
body:not(.has-hero) .nav__cta .btn,
.has-hero .masthead[data-scrolled='true'] .nav__cta .btn {
  background: var(--brick);
}
body:not(.has-hero) .nav__cta .btn:hover,
.has-hero .masthead[data-scrolled='true'] .nav__cta .btn:hover {
  background: var(--brick-lift);
}

/* Compact list panels: Projects and About. Same radius and shadow family as
   the other floating popover on the page (.text-fab-panel), rather than the
   sharp 2px .card radius, since this is a card, not a piece of the page. */
.submenu {
  position: absolute; top: calc(100% + .35rem); left: 0;
  min-width: 16.5rem; padding: .6rem; margin: 0; list-style: none;
  background: var(--bone);
  border: 1px solid var(--rule);
  border-radius: var(--radius-btn);
  box-shadow: var(--shadow);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .16s var(--ease), transform .16s var(--ease), visibility .16s;
}
.nav-item[data-open='true'] .submenu { opacity: 1; visibility: visible; transform: none; }
.submenu a {
  display: block; padding: .55rem .75rem; border-radius: 3px;
  font-size: .95rem;
  color: var(--fg-2); text-decoration: none;
  transition: color .14s var(--ease), background-color .14s var(--ease);
}
.submenu a:hover {
  color: var(--brick);
  background: var(--brick-soft);
}

/* The mega panel: pinned to the viewport, not the item, so its width tracks
   the page's own container instead of the nav row. They're optically
   centred with position: absolute on .nav__links, above, which would
   otherwise become the mega panel's containing block too and squeeze it
   down to the width of the link row instead of the shell; position: fixed
   sidesteps that entirely. Sized and centred the same way .shell is (same
   max-width, same gutter), so the panel lines up with the rest of the
   page's content instead of running to the browser edges; .mega__inner
   skips the shell class it would otherwise need for that, since .mega is
   already doing it. --nav-drop-top is the bar's live bottom edge, tracked
   in site.js since the sticky bar isn't flush with the viewport top until
   scroll has carried it there. The link's hit area extends down to the
   bar's bottom edge so the pointer can cross into the panel without
   closing it. */
.nav-item--mega { position: static; }
.nav-item--mega .nav-link { position: relative; }
.nav-item--mega .nav-link::after {
  content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 1rem;
}
.mega {
  position: fixed; top: var(--nav-drop-top, 4.5rem);
  left: 50%;
  width: 100%; max-width: calc(var(--shell) + (var(--gutter) * 2));
  padding-inline: var(--gutter);
  z-index: 5;
  background: var(--bone);
  border-top: 1px solid var(--rule-2);
  border-bottom: 1px solid var(--rule);
  box-shadow: 0 1px 1px rgba(0, 0, 0, .3), 0 24px 50px rgba(0, 0, 0, .45);
  opacity: 0; visibility: hidden;
  /* The -50% keeps the panel horizontally centred at all times; only the
     translateY (the closed-state's slight upward tuck) toggles. */
  transform: translateX(-50%) translateY(-2px);
  transition: opacity .16s var(--ease), transform .16s var(--ease), visibility .16s;
}
.nav-item[data-open='true'] .mega { opacity: 1; visibility: visible; transform: translateX(-50%); }
/* Leaving the page (site.js): panels shut at once, not over the fade, since
   the browser holds this frame on screen while the next page loads. */
.is-leaving .mega, .is-leaving .submenu { transition: none; }
.mega__inner {
  display: grid; grid-template-columns: 1fr 1.2fr 1fr;
  gap: 3rem; align-items: stretch;
  padding-block: 2.2rem 2.4rem;
}
/* The CTA sits right under the paragraph, not pinned to the panel foot. */
.mega__intro { display: flex; flex-direction: column; }
.mega__intro h3 {
  font-family: var(--display); font-weight: 600;
  font-size: 1.7rem; letter-spacing: -0.02em; line-height: 1.1;
  margin: 0 0 .6rem;
}
.mega__intro p { margin: 0 0 1.2rem; color: var(--fg-2); font-size: .95rem; max-width: 30ch; }
/* A solid brick button, the same as Contact Us in the bar: as a line of
   red text it was lost at the foot of the panel. */
.mega__all {
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: .5rem;
  padding: calc(.7rem + var(--btn-nudge)) 1.25rem calc(.7rem - var(--btn-nudge));
  font-family: var(--body); font-size: 1rem; font-weight: 600;
  color: var(--bone); background: var(--brick);
  border-radius: var(--radius-btn); text-decoration: none;
  transition: background-color .2s var(--ease);
}
.mega__all:hover { color: var(--bone); background: var(--brick-deep); }

/* The links column, everywhere a mega panel has one: a stack of tiles, not
   a ruled list (a hairline under every row read as notebook lines), at an
   even gap from the top. Spreading a short list (two services) to the full
   column height left a hole between the tiles that read as a bug. */
.mega__links {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; justify-content: flex-start;
  gap: .5rem;
}
.mega__links a {
  display: flex; align-items: center; gap: .7rem;
  padding: .6rem .7rem; font-size: .95rem;
  color: var(--fg-2); text-decoration: none;
  border-radius: var(--radius);
  background: rgba(0, 0, 0, .045);
  transition: background .14s var(--ease), padding-left .18s var(--ease);
}
.mega__links a:hover { color: var(--brick); background: rgba(138, 24, 42, .09); padding-left: .9rem; }
.mega__links a i {
  display: flex; flex: 0 0 auto; align-items: center; justify-content: center;
  width: 1.9rem; height: 1.9rem; border-radius: 50%;
  background: rgba(0, 0, 0, .07); color: var(--fg-3); font-size: .8em;
  transition: color .14s var(--ease), background .14s var(--ease);
}
.mega__links a:hover i { background: var(--brick); color: var(--bone); }

.mega__figure { margin: 0; display: flex; flex-direction: column; height: 100%; }
.mega__figure img { display: block; width: 100%; flex: 1 1 auto; min-height: 0; object-fit: cover; }
.mega__figure figcaption {
  display: flex; align-items: flex-start; gap: .7rem;
  margin-top: .7rem;
  font-family: var(--ui); font-size: .82rem; line-height: 1.4;
  color: var(--fg-3);
}
/* A short dimension tick before the caption, in the language of the drawings. */
.mega__figure figcaption::before {
  content: ''; flex: 0 0 2rem; height: 7px; margin-top: .35em;
  border-left: 1px solid var(--rule); border-right: 1px solid var(--rule);
  background: linear-gradient(var(--rule), var(--rule)) 0 50% / 100% 1px no-repeat;
}

.nav-toggle {
  display: none; width: 2.6rem; height: 2.6rem;
  align-items: center; justify-content: center;
  position: relative; z-index: 95;
  background: none; border: 1px solid var(--rule); border-radius: var(--radius-btn);
  color: var(--fg); cursor: pointer; flex: 0 0 auto;
  /* .nav goes position:fixed at the mobile breakpoint, which pulls it out of
     masthead__inner's flex flow — this is the only flex child left to carry
     the auto margin that pushes it to the bar's right edge. */
  margin-left: auto;
}
.nav-toggle span, .nav-toggle span::before, .nav-toggle span::after {
  display: block; width: 1.05rem; height: 1px; background: currentColor;
  transition: transform .25s var(--ease), opacity .2s;
}
.nav-toggle span::before, .nav-toggle span::after { content: ''; position: absolute; }
.nav-toggle span::before { transform: translateY(-5px); }
.nav-toggle span::after  { transform: translateY(5px); }
.nav-toggle[aria-expanded='true'] span { background: transparent; }
.nav-toggle[aria-expanded='true'] span::before { transform: rotate(45deg); }
.nav-toggle[aria-expanded='true'] span::after  { transform: rotate(-45deg); }

/* --------------------------------------------------------------------------
   Floating masthead — pages that open on the splash (body.has-hero)

   The bar rides over the footage instead of sitting on a plaster shelf above
   it: ink gathered at the very top and thinning to nothing, white links, and
   the wordmark on a white plate, because the logo is brick and would sink
   into the video without one. site.js flips data-scrolled the moment the foot
   of the hero reaches the underside of the bar; from there the bar resolves to
   plaster, the plate fades out and the links return to ink.

   Everything is scoped to .has-hero, so every other page keeps the plaster bar
   exactly as it was.
   -------------------------------------------------------------------------- */

/* Fallback only — site.js overrides this with the bar's measured height.
   .75rem padding x2 + logo + .45rem plate padding x2. */
.has-hero { --head-h: 7rem; }
@media (max-width: 80rem) { .has-hero { --head-h: 6.4rem; } }
@media (max-width: 52rem) { .has-hero { --head-h: 5.8rem; } }

/* The masthead keeps its place in the flow (it is sticky), so the hero is
   pulled up by exactly the bar's height to run the video behind it. */
.has-hero .hero { margin-top: calc(var(--head-h) * -1); }

/* No bar at all over the splash: the darkening that keeps the links legible
   is a scrim graded from the top edge, not a solid strip — dark where the
   glass meets the frame, gone by the underside of the bar, so it reads as
   the top of the photograph darkening rather than as a panel laid over it.
   The text-shadow on the links still carries the brightest frames. */
.has-hero .masthead {
  background: transparent;
  border-bottom-color: transparent;
  transition: background-color .35s var(--ease), border-color .35s var(--ease),
              box-shadow .35s var(--ease);
}
/* The scrim is glass now, not just a tint: a blurred, darkened pane behind
   the wordmark and the nav. It has to cover the bar itself edge to edge,
   full strength, with the whole text row sitting on it — the fade is not
   inside the bar, it is the bar bleeding down into the footage below it.
   So this pane is taller than the masthead it's attached to (250% of it) and
   only starts fading past the point where the real bar ends (its bottom
   edge lands at 40% of that extra height); the rest of its height is the
   tail that thins out over the video underneath. */
.has-hero .masthead::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 190%;
  background: linear-gradient(180deg,
    rgba(24, 15, 17, .52) 0%, rgba(24, 15, 17, .46) 40%,
    rgba(24, 15, 17, .40) 53%, rgba(24, 15, 17, .30) 65%,
    rgba(24, 15, 17, .20) 75%, rgba(24, 15, 17, .11) 85%,
    rgba(24, 15, 17, .04) 93%, rgba(24, 15, 17, 0) 100%);
  backdrop-filter: blur(4px) saturate(120%);
  -webkit-backdrop-filter: blur(4px) saturate(120%);
  -webkit-mask-image: linear-gradient(180deg,
    #000 0%, #000 53%, rgba(0, 0, 0, .85) 62%,
    rgba(0, 0, 0, .65) 71%, rgba(0, 0, 0, .42) 80%,
    rgba(0, 0, 0, .22) 88%, rgba(0, 0, 0, .08) 95%, transparent 100%);
  mask-image: linear-gradient(180deg,
    #000 0%, #000 53%, rgba(0, 0, 0, .85) 62%,
    rgba(0, 0, 0, .65) 71%, rgba(0, 0, 0, .42) 80%,
    rgba(0, 0, 0, .22) 88%, rgba(0, 0, 0, .08) 95%, transparent 100%);
  opacity: 1;
  transition: opacity .35s var(--ease);
  pointer-events: none;
  z-index: 0;
}
.has-hero .masthead[data-scrolled='true']::before { opacity: 0; }
.has-hero .masthead__inner { position: relative; z-index: 1; }
.has-hero .masthead .nav-link {
  color: rgba(245, 236, 232, .88);
  text-shadow: 0 1px 12px rgba(24, 15, 17, .55);
}
.has-hero .masthead .nav-link:hover,
.has-hero .masthead .nav-item[data-open='true'] .nav-link { color: var(--bone); }
.has-hero .masthead .nav-toggle { color: var(--bone); border-color: rgba(245, 236, 232, .5); }

/* The wordmark itself goes white over the footage — no plate behind it — and
   returns to full colour when the bar resolves to plaster. The logo is a
   transparent PNG of solid artwork, so flattening it to white is exact. */
.has-hero .masthead .wordmark img {
  /* A brightness/invert filter lands on pure white; the mark is swapped for a
     bone-tinted copy of the same artwork so it matches the type exactly. */
  content: url("../img/perez-logo-bone.png");
  filter: drop-shadow(0 1px 10px rgba(24, 15, 17, .45));
  transition: filter .35s var(--ease);
}
.has-hero .masthead[data-scrolled='true'] .wordmark img { content: normal; filter: none; }
/* The Andersen mark's black type would sink into the footage, so it gets
   the white-type copy until the bar resolves. */
.has-hero .masthead .nav-link--andersen img { content: url("../img/andersen-elite-certified-nav-white.webp"); }
.has-hero .masthead[data-scrolled='true'] .nav-link--andersen img { content: normal; }

/* Past the hero: plaster bar, no plate, ink links. */
.has-hero .masthead[data-scrolled='true'] {
  background: var(--bone);
  border-bottom-color: var(--rule);
}
.has-hero .masthead[data-scrolled='true'] .nav-link { color: var(--fg-2); text-shadow: none; }
.has-hero .masthead[data-scrolled='true'] .nav-link:hover,
.has-hero .masthead[data-scrolled='true'] .nav-item[data-open='true'] .nav-link { color: var(--brick); }
.has-hero .masthead[data-scrolled='true'] .nav-toggle { color: var(--fg); border-color: var(--rule); }


/* --------------------------------------------------------------------------
   Hero — the splash. A silent, looping video of finished work, the question
   the visitor is already asking, and one way to answer it.

   The type sits in the lower left rather than dead centre, so it never covers
   the subject of the shot, and the room is graded once from the foot instead
   of being spotlit by a vignette. One solid action, one hairline link beside
   it, and the GuildQuality figures reduced to a single line ranged right.
   Two buttons of equal weight give the eye no order to read them in; four
   statistics along the base give it nowhere to rest. Both are gone.
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  display: grid; align-items: end;
  /* No upper cap: the splash is a share of the window at every size, so the
     footage keeps its proportions on a laptop and on a 5K panel alike. Kept
     a few points short of the full viewport (rather than 92vh) so the
     bottom-anchored CTA row clears both the fold and the scroll-reveal
     observer's -12% bottom margin without the visitor having to scroll. */
  min-height: clamp(34rem, 86vh, 463rem);
  overflow: hidden;
  background: var(--night);
  /* Plain white throughout. Blush is the accent everywhere else on the site,
     but over footage it reads as a tint rather than as a decision. */
  --fg:     var(--bone);
  --fg-2:   rgba(245, 236, 232, .86);
  --fg-3:   rgba(245, 236, 232, .64);
  --accent: var(--bone);
  --accent-fg: var(--night);
  --rule:   rgba(245, 236, 232, .3);
  --rule-2: rgba(245, 236, 232, .16);
  color: var(--fg);
}

.hero__media { position: absolute; inset: 0; z-index: 0; }
.hero__media video, .hero__media img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* Brighter, warmer, a touch more saturated (client roadmap, October
     2026). A stopgap on the footage as delivered: when the clip is
     regraded, take this back out. */
  filter: brightness(1.08) saturate(1.14) sepia(.08);
}

/* One grade, weighted to the foot where the type sits, with just enough at
   the head to carry the masthead. Deliberately not a radial: a vignette
   spotlights the words and leaves the corners of the room bright, which is
   what makes a hero read as a banner rather than as a photograph. Because the
   grade is even, the type needs no shadow of its own. */
.hero__media::after {
  content: ''; position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      rgba(24, 15, 17, .50) 0%,
      rgba(24, 15, 17, .24) 14%,
      rgba(24, 15, 17, 0) 30%,
      rgba(24, 15, 17, .06) 42%,
      rgba(24, 15, 17, .58) 72%,
      rgba(24, 15, 17, .86) 100%),
    rgba(24, 15, 17, .06);
}

.hero__inner {
  position: relative; z-index: 1;
  width: 100%;
  display: grid; justify-items: start;
  gap: 1rem;
  padding-block: clamp(4rem, 3rem + 4vw, 6rem) clamp(2.6rem, 2rem + 2.4vw, 4rem);
}

/* The eyebrow, in the display face upright, exactly as .label sets it
   everywhere else on the site. */
.hero__eyebrow {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.1rem;
  letter-spacing: 0;
  color: var(--bone);
}

.hero__title {
  /* Capped by the screen's width as well as the scale, so the longest line
     the video sync puts here ("your windows & doors?", about 9 em wide)
     still fits inside the gutters on the narrowest phones. Above roughly
     450px the cap is larger than the scale and changes nothing. */
  font-size: min(var(--step-5), calc((100vw - 3rem) / 9));
  line-height: .92;
  letter-spacing: var(--tighter);
  margin: 0;
  max-width: 15ch;
  text-wrap: balance;
  text-shadow:
    0 0 6px rgba(16, 14, 14, .7),
    0 1px 20px rgba(16, 14, 14, .9);
}
.hero__title em { font-style: normal; color: var(--bone); }

.hero__lede {
  margin: .6rem 0 0;
  font-size: var(--step-1);
  color: var(--fg-2);
  max-width: 55%;
  text-wrap: balance;
  text-shadow:
    0 0 6px rgba(16, 14, 14, .7),
    0 1px 20px rgba(16, 14, 14, .9);
}

/* The rotating word. Each line of the headline is fixed, so the swap can
   never re-wrap the sentence; site.js measures every word once and eases
   the slot's width between them, so the rest of the line glides rather
   than jumps. The text itself crossfades inside the slot. */
.hero__line { display: block; white-space: nowrap; }

/* The rotating word is set in the button's red — no plate, no box.

   This is below the WCAG bar and knowingly so: #A81E33 tops out at 2.9:1 even
   against pure black, so no grade behind it can rescue the ratio. A soft dark
   halo is carried on the glyphs instead, which lifts the red off the footage
   without drawing an edge around it. The word is decorative — the sentence
   still reads with it ignored, and the same five words are in the markup for
   anything that cannot see colour. */
.hero__word {
  display: inline-block; vertical-align: top; text-align: left;
  transition: width .38s var(--ease);
}
.hero__title em.hero__word { color: var(--bone); }
.hero__word > span { display: inline-block; }
.hero__word.is-out > span { animation: hero-word-out .26s var(--ease) forwards; }
.hero__word.is-in > span { animation: hero-word-in .3s var(--ease); }
@keyframes hero-word-out { to { opacity: 0; transform: translateY(-.18em); } }
@keyframes hero-word-in { from { opacity: 0; transform: translateY(.18em); } }

/* The foot: the action ranged left, the survey figures ranged right against
   it. One row on a desktop, two on a phone. */
.hero__foot {
  display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap: 1.1rem 2rem;
  width: 100%;
  margin-top: .4rem;
}

.hero__actions { justify-content: flex-start; }
/* Liquid glass over the footage: a blurred, translucent pane rather than a
   flat fill, so the video keeps moving through the button instead of being
   blocked by it. No inner rim highlight — that read as a stray border along
   the top edge — just the blur, the tint, and a soft drop shadow to lift it
   off the footage. */
.hero__actions .btn {
  padding: calc(.8rem + var(--btn-nudge)) 1.7rem calc(.8rem - var(--btn-nudge));
  font-size: .92rem;
  font-weight: 500;
  letter-spacing: .01em;
  border-radius: var(--radius-btn);
  border: 0;
  background: rgba(168, 30, 42, .5);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  box-shadow: 0 10px 30px rgba(16, 14, 14, .35);
  color: var(--bone);
  transition: background-color .25s var(--ease), transform .25s var(--ease),
              box-shadow .25s var(--ease);
}
.hero__actions .btn:hover {
  background: rgba(138, 24, 42, .3);
  transform: translateY(-1px);
  box-shadow: 0 14px 34px rgba(16, 14, 14, .4);
}
.hero .btn--outline {
  background: rgba(245, 236, 232, .1);
  border: 0;
  color: var(--bone);
}
.hero .btn--outline:hover {
  background: rgba(245, 236, 232, .22);
  color: var(--bone);
}

/* The proof, as one line. The figures are set in the display face so they
   read as type rather than as badges. No lining-nums here: freight-big-pro's
   lnum lookup has no glyphs behind it in the kit subset and renders junk —
   the face's native oldstyle figures are what we want anyway. */
.hero__proof {
  margin: 0;
  font-size: .9rem;
  color: var(--fg-2);
  text-align: right;
}
.hero__proof b {
  font-family: var(--display); font-weight: 500; font-size: 1.2rem;
  letter-spacing: -0.01em; color: var(--fg);
}

/* --------------------------------------------------------------------------
   Section heads
   -------------------------------------------------------------------------- */

.head { max-width: 52rem; margin-bottom: 3rem; }
.head--center { margin-inline: auto; text-align: center; }
/* Masthead scale with negative leading, so the lines lock into a block
   instead of sitting as separate sentences. This single pair of numbers is
   most of the difference between a website heading and a magazine one. */
/* With brass gone, accent and type are the same colour, so emphasis inside a
   headline is carried by brightness: the running words sit a step down and
   the emphasised phrase comes up to full bone. Works unchanged on the bone
   band, where the same two steps run dark-on-light. */
.head__title {
  font-size: var(--step-6);
  line-height: .88;
  letter-spacing: -0.042em;
  margin-bottom: 1.15rem;
  color: var(--fg-2);
}
.head__title em { color: var(--fg); }
.head p { max-width: 44ch; }
.head--center p { margin-inline: auto; }
.head__title em { font-style: normal; color: var(--accent); }
.head p { color: var(--fg-2); font-size: var(--step-1); line-height: 1.6; }
.head__aside { color: var(--fg-2); }

/* The first section head under the hero. Bigger, centred, and given room —
   it is doing the job the removed value block used to do. */
.head--lead {
  max-width: 52rem;
  margin-bottom: clamp(3.25rem, 2.6rem + 2.4vw, 4.5rem);
}
/* Looser than the .88 the other heads run: this one is three full sentences
   stacked, and at that count the negative leading stopped reading as a locked
   block and started reading as crowding. */
.head--lead .head__title {
  font-size: var(--step-6);
  line-height: .95;
  letter-spacing: -0.042em;
  margin-bottom: 1.25rem;
  text-wrap: balance;
}
.head--lead p { margin-inline: auto; max-width: 52ch; }

/* Wider still — for a head that needs the room but doesn't want the lead
   size bump. */
.head--wide { max-width: 68rem; }
.head--wide p { max-width: 62ch; }
.head p a, .promise p a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
}
.head p a:hover { color: var(--brick-deep); }

/* --------------------------------------------------------------------------
   Cards — a photograph over a hairline-ruled body
   -------------------------------------------------------------------------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: 2rem 1.75rem;
}

.card {
  position: relative;
  display: flex; flex-direction: column;
  background: transparent;
  text-decoration: none;
}

.card__media {
  position: relative; display: block; order: -1;
  aspect-ratio: 3 / 2; overflow: hidden;
  background: var(--paper-2);
  margin-bottom: 1.35rem;
  border-radius: var(--radius);
}
.card__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .8s var(--ease);
}
.card:hover .card__media img { transform: scale(1.035); }

.card__body {
  padding-top: 1.35rem; display: flex; flex-direction: column; flex: 1;
  border-top: 1px solid var(--rule);
  transition: border-color .25s var(--ease);
}
.card:hover .card__body { border-top-color: var(--accent); }
.card__title { font-size: var(--step-2); margin-bottom: .5rem; color: var(--fg); }
.card:hover .card__title { color: var(--accent); }
.card__more {
  margin-top: auto;
  font-family: var(--body); font-size: .95rem; font-weight: 600;
  letter-spacing: -0.006em; color: var(--accent);
  display: inline-flex; align-items: center; gap: .4rem;
  transition: gap .18s var(--ease);
}
.card:hover .card__more { gap: .7rem; }

/* Card with no photograph: the rule does the work */
.card:not(:has(.card__media)) .card__body { padding-top: 1.5rem; }

/* --------------------------------------------------------------------------
   Bento — one anchor tile, then photo tiles
   --------------------------------------------------------------------------
   One grid on twelve columns. The lead is twice the width of the tiles
   beside it but the same height, so it leads without dwarfing the rest;
   the row below is three wider tiles. The tiles sit a shade brighter than
   the plaster with a hairline edge and the photograph shadow, so they lift
   off the band instead of dissolving into it. Every tile is the same object:
   a photograph running edge to edge with its name and its Explore line
   centred on top of it. */

.bento {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1.1rem;
}
.bento > a {
  display: flex; flex-direction: column;
  position: relative;
  background: var(--char-2);
  border: 1px solid var(--rule-2);
  border-radius: 3px; overflow: hidden;
  box-shadow: var(--shadow);
  /* Every tile sizes its own type off its own width. The lead is twice the
     width of a quarter tile, so one fixed size can only ever suit one of
     them — it shouts in the small tiles or whispers in the big one. cqi ties
     the scale to the tile, which also means the breakpoints where tiles
     change width need no type overrides of their own. */
  container-type: inline-size;
  text-decoration: none; color: var(--fg);
  transition: transform .3s var(--ease), box-shadow .3s var(--ease);
}
.bento > a:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.bento > a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* The photograph is the tile's ground, not a band across its top: it fills
   the anchor and the words sit on it. */
.bento__media {
  display: block; position: absolute; inset: 0;
  overflow: hidden; background: var(--paper-2);
}
.bento__media img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .8s var(--ease);
}
/* The wash that separates the words from the picture. Centre-weighted rather
   than flat or bottom-weighted: the labels are centred, so the darkness
   belongs in the middle and the corners can stay open — the island, the
   pendants and the cabinetry keep reading as photography. Measured against
   the brightest cabinetry in the Lukasik kitchen it puts bone at 4.57:1
   where the words land, against 2.39:1 for a flat 35% and 1.85:1 for a
   bottom scrim, which spends its darkness along an edge nothing is written
   on. Sits over the image but under the words, which are positioned and
   later in the DOM. */
.bento__media::after {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(ellipse at center,
    rgba(0, 0, 0, .55) 0%,
    rgba(0, 0, 0, .4) 45%,
    rgba(0, 0, 0, .18) 100%);
  pointer-events: none;
}
.bento > a:hover .bento__media img { transform: scale(1.035); }

.bento__title {
  /* Fixed, not fluid, and the same value on every tile regardless of class
     (overridden, still uniformly, at the breakpoints below) rather than
     cqi-interpolated against each tile's own width or sized bigger on the
     lead tile. */
  font-size: 1.5rem;
  line-height: 1.08; letter-spacing: -.018em;
  margin-bottom: .55rem; color: var(--bone);
  /* Where a name breaks to a second line is decided explicitly in the
     template (break_last_word), not left to auto-wrap, so every tile's
     line count is deliberate rather than whatever the browser's own wrap
     algorithm happens to choose at a given width. max-width here is just
     wide enough that the longest manually-broken half ("Exterior
     Remodeling", 19 characters) still renders as one line rather than
     wrapping a second, unplanned time.
     Reserving a fixed two-line height below (min-height, in em so it
     tracks whatever font-size applies at each breakpoint) is what keeps
     every tile the same overall height regardless of whether its own
     title actually used one line or two.
     That reservation is worthless on its own, though, if the text just
     sits at the top of it: a one-line name would then leave a dead gap
     below itself, before "Explore", that a two-line name never has (the
     bug the site actually shipped with). display: flex + justify-content:
     flex-end drops the (however many lines) text to the BOTTOM of the
     reserved box instead, so any slack lands above the title, invisible
     against the photo, and "Explore" sits the same fixed distance under
     the title's last line every time, one line or two. */
  display: flex; flex-direction: column; justify-content: flex-end;
  /* A flex container's own cross-axis size defaults to content-fit rather
     than filling available space, which (for a column flex container
     whose only "item" is a run of text) tends to settle on whatever width
     wraps the MOST, not the least. width: 100% overrides that so the box
     actually reaches max-width before wrapping, instead of wrapping early. */
  width: 100%; max-width: 21ch; margin-inline: auto;
  min-height: 2.16em;
  text-wrap: balance;
  /* The client found the names too quiet against the photographs: a
     heavier cut and a close shadow under a soft one lift them clear of
     even the brightest cabinetry. */
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .6), 0 2px 18px rgba(0, 0, 0, .55);
}

/* The label block: centred on both axes, so "Explore" sits in the same
   spot tile to tile regardless of whether the title above it ran one line
   or two. That only holds because the title reserves a fixed two-line
   height above (min-height, ch cap): everything below it in the flex
   column is otherwise the same height on every tile, so centering the
   whole group lands "Explore" level without needing to anchor it to the
   foot. No text-shadow: the wash beneath is carrying the separation, and a
   glow on top of it would be doing the same job twice. */
.bento__body,
.bento__lead .bento__plate {
  position: relative; z-index: 1;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center;
  flex: 1;
  min-height: var(--bento-img);
  padding: 1.75rem clamp(1rem, 7cqi, 2.25rem);
  color: var(--bone);
}
/* The base rule pushes this to the bottom of the card; here it belongs with
   the title it sits under. Set inline rather than inline-flex so a long name
   wraps as text — the underline then follows the words instead of running the
   full width of a flex line. */
.bento .card__more {
  display: inline;
  margin-top: 0; color: var(--bone);
  font-size: clamp(.8rem, 5.2cqi, .95rem);
  line-height: 1.45;
  /* "Explore →" is two words and never needs to wrap; Safari's balance
     split it, dropping the arrow onto a line of its own. */
  white-space: nowrap;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .22em;
}
/* An atomic inline box, so the rule stops at the words and does not run
   under the arrow. */
.bento .card__more span { display: inline-block; }

/* Tiles are a fixed height rather than a fixed ratio, so a quarter-width
   tile and a third-width tile carry the same picture height and the two rows
   read as one set. The photograph is absolute, so this is set on the label
   block and the picture fills whatever it makes. */
.bento { --bento-img: clamp(11rem, 7rem + 7vw, 14rem); }

/* The anchor: half the row, as tall as the photo tiles beside it */
.bento__lead {
  grid-column: span 6;
  background: var(--night);
}
/* No photograph to sit on: the charcoal ground carries the same bone type. */
.bento__lead:not(:has(.bento__media)) { background: var(--night); }

/* The photo tiles: a quarter of the row beside the lead, a third below it */
.bento__tile { grid-column: span 3; }
.bento__tile--wide { grid-column: span 4; }

/* Under the shell width the quarter tiles get too narrow to hold their
   copy, so the lead takes the full width and the rest pair up two to a row. */
@media (max-width: 71rem) {
  .bento { --bento-img: clamp(11rem, 6rem + 10vw, 14rem); }
  .bento__lead { grid-column: span 12; }
  .bento__lead .bento__plate { min-height: clamp(14rem, 8rem + 14vw, 20rem); }
  .bento__tile { grid-column: span 6; }
  .bento__title { font-size: 1.75rem; }
  /* Tiles pair up from the second item, so an even last one is on its own
     row: let it take the full width rather than sit beside a gap. */
  .bento__tile:nth-child(even):last-child { grid-column: span 12; }
}
@media (max-width: 36rem) {
  .bento { --bento-img: 12rem; }
  .bento > a { grid-column: span 12; }
  .bento__title { font-size: 1.6rem; }
  .bento__lead .bento__plate { min-height: 14rem; }
}

/* --------------------------------------------------------------------------
   Steps — each one measured off a dimension line
   -------------------------------------------------------------------------- */

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13.5rem), 1fr));
  gap: 2.75rem 2.5rem;
}
.step { position: relative; padding-top: 1.35rem; border-top: 1px solid var(--rule); }
.step__n {
  display: block; margin-bottom: .9rem;
  font-family: var(--display); font-size: .95rem; font-weight: 700;
  letter-spacing: .02em; color: var(--accent);
}
.step__n::after {
  content: ''; display: inline-block; vertical-align: middle;
  width: 1.4rem; height: 5px; margin-left: .55rem;
  border-right: 1px solid var(--rule);
  background: linear-gradient(var(--rule), var(--rule)) 0 50% / 100% 1px no-repeat;
}
.step h3 { font-size: var(--step-1); margin-bottom: .5rem; }
.step p { color: var(--fg-2); font-size: 1rem; margin: 0; }

/* --------------------------------------------------------------------------
   Roster — the trades on the job, set out the way a drawing set schedules
   them. This is the differentiator, so it is a list of names, not a claim.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Cast — the roster as a lineup
   --------------------------------------------------------------------------
   Ten crops in a row, one per trade. At rest each is a narrow strip with the
   trade name running up it; the open one widens to show the work and a line
   about it. The first is open by default so the strip reads without a hand. */

.cast-head {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1rem 3rem; align-items: end;
  margin-bottom: 2.25rem;
}
.cast-head .head__title {
  font-size: var(--step-6); line-height: .88; letter-spacing: -0.042em; margin: 0;
}
.cast-head p { margin: 0; color: var(--fg-2); font-size: var(--step-1); line-height: 1.5; max-width: 34ch; }
.clear-path__foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 1.25rem 2rem; margin-top: 2.5rem;
}
.clear-path__close {
  margin: 0; font-family: var(--display); font-size: var(--step-2); line-height: 1.15;
}
.clear-path__close em { font-style: normal; color: var(--accent); }
@media (max-width: 52rem) {
  .cast-head { grid-template-columns: 1fr; gap: .75rem; }
}

.cast {
  list-style: none; margin: 0; padding: 0;
  display: flex; gap: .35rem;
  height: clamp(22rem, 24rem + 6vw, 34rem);
}
.cast__item {
  position: relative; flex: 1 1 0; min-width: 0;
  overflow: hidden; border-radius: 2px;
  color: var(--bone); cursor: pointer;
  transition: flex-grow .55s var(--ease);
}
.cast__item:hover, .cast__item:focus-visible, .cast__item.is-open { flex-grow: 3.2; }
.cast__item:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }
.cast__media { position: absolute; inset: 0; display: block; }
.cast__media img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  filter: saturate(.75) brightness(.8);
  transition: filter .5s var(--ease), transform .8s var(--ease);
}
.cast__item:hover img, .cast__item:focus-visible img, .cast__item.is-open img { filter: none; transform: scale(1.03); }
.cast__media::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(24, 15, 17, .05) 40%, rgba(24, 15, 17, .82) 100%);
}
.cast__name {
  position: absolute; left: 0; bottom: 0; padding: 1rem .9rem;
  writing-mode: vertical-rl; transform: rotate(180deg);
  font-family: var(--display); font-weight: 700; font-size: 1.85rem;
  letter-spacing: -0.015em;
  white-space: nowrap; transition: opacity .3s var(--ease);
}
/* The plate has a fixed measure, so its lines are set once and never
   re-wrap while the tile is widening. It fades in after the tile has
   opened, and drops out at once when it starts to close. */
.cast__plate {
  position: absolute; left: .9rem; bottom: .9rem;
  width: 15.5rem;
  opacity: 0; transition: opacity .15s var(--ease);
}
.cast__plate b {
  display: block; font-family: var(--display); font-weight: 400;
  font-size: 2rem; letter-spacing: -0.02em; line-height: 1.1;
}
.cast__plate span { display: block; font-size: 1.02rem; line-height: 1.45; color: rgba(245, 236, 232, .75); margin-top: .3rem; }
.cast__item:hover .cast__plate, .cast__item:focus-visible .cast__plate, .cast__item.is-open .cast__plate { opacity: 1; transition: opacity .35s var(--ease) .32s; }
.cast__item:hover .cast__name, .cast__item:focus-visible .cast__name, .cast__item.is-open .cast__name { opacity: 0; }

/* Phones: there is no hover, and this list is doing sales work (every trade
   we carry in-house), so it stays a 2-up grid instead of a swipe carousel —
   engagement on a carousel falls off after the first card and a large share
   of visitors never swipe past it at all. Five rows of two, all on screen
   without a gesture. */
@media (max-width: 52rem) {
  .cast {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: .5rem; height: auto;
  }
  .cast__item { aspect-ratio: 4 / 5; }
  .cast__item:hover, .cast__item.is-open { flex-grow: 0; }
  .cast__name { opacity: 1 !important; writing-mode: horizontal-tb; transform: none; font-size: 1.1rem; }
  .cast__plate { display: none; }
  .cast__media img { filter: none; }
}

/* --------------------------------------------------------------------------
   Scores — survey results, stated as measured values
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Case studies — See What's Possible. A photograph beside the four-part
   story, alternating sides, ahead of the before/after pairs.
   -------------------------------------------------------------------------- */

.case {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 1rem + 2.5vw, 3.5rem); align-items: center;
  margin: 0 0 clamp(3rem, 2rem + 3vw, 5rem);
}
.case--flip .case__photo { order: 2; }
.case__photo { display: block; border-radius: 3px; overflow: hidden; box-shadow: var(--shadow); aspect-ratio: 4 / 3; }
.case__photo img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .8s var(--ease); }
.case__photo:hover img { transform: scale(1.03); }
.case__title { font-size: var(--step-2); line-height: 1.15; margin: 0 0 1.2rem; }
.case__title a { color: inherit; text-decoration: none; }
.case__title a:hover { text-decoration: underline; text-underline-offset: .15em; }
.case__story { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem 1.8rem; margin: 0 0 1.5rem; }
.case__story dt {
  font-size: .74rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); margin-bottom: .3rem;
}
.case__story dd { margin: 0; font-size: .95rem; line-height: 1.5; color: var(--fg-2); }
@media (max-width: 52rem) {
  .case { grid-template-columns: 1fr; }
  .case--flip .case__photo { order: 0; }
}
@media (max-width: 36rem) { .case__story { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------------------
   Verdict — the GuildQuality proof, as one number
   --------------------------------------------------------------------------
   The rating set enormous and centred, the six survey scores as a single
   ruled row of figures beneath it, then the homeowners. Numbers are type,
   set in the display face with lining figures. */

.verdict { text-align: center; }
.verdict .head--center { margin-bottom: 1.5rem; }

.verdict__hero {
  display: flex; justify-content: center; align-items: baseline; gap: 1rem;
  margin: 0 0 .4rem;
}
.verdict__num {
  font-family: var(--display); font-weight: 400;
  font-size: clamp(6rem, 4rem + 9vw, 12rem);
  line-height: .95; letter-spacing: -0.035em; color: var(--fg);
  font-variant-numeric: lining-nums tabular-nums;
}
.verdict__of {
  font-family: var(--display); font-style: italic;
  font-size: clamp(1.4rem, 1rem + 1.6vw, 2.4rem); color: var(--fg-3);
}
/* "out of 5": the 5 set upright and larger than the words before it, so the
   scale reads at a glance (the client's review). */
.verdict__den {
  font-style: normal; font-size: 1.6em; line-height: 1; color: var(--fg-2);
  font-variant-numeric: lining-nums;
}
/* Stars and the award on one line: five brick stars, a hairline, then the
   award set in the display italic with the year upright. */
.verdict__sub {
  margin: .5rem 0 0;
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: .5rem 1.1rem;
}
.verdict__stars {
  color: var(--accent); font-size: 1.25rem; line-height: 1;
  letter-spacing: .2em; margin-right: -.2em;
}
.verdict__award {
  display: inline-flex; align-items: baseline; gap: .35em;
  font-family: var(--display); font-style: italic; font-size: var(--step-1);
  color: var(--fg); letter-spacing: -0.01em;
}
.verdict__award::before {
  content: ''; align-self: center; width: 1px; height: 1.1em;
  background: var(--rule); margin-right: .75em;
}
.verdict__award b { font-style: normal; font-weight: 500; color: var(--fg-2); font-variant-numeric: lining-nums; }

.verdict__row {
  list-style: none; margin: 3rem 0 0; padding: 1.5rem 0 0;
  display: grid; grid-template-columns: repeat(6, 1fr); gap: 1rem;
  border-top: 1px solid var(--rule);
  text-align: left;
}
.verdict__score {
  display: block;
  font-family: var(--display); font-weight: 400; font-size: 2.1rem;
  line-height: 1; letter-spacing: -0.03em; color: var(--fg);
  font-variant-numeric: lining-nums tabular-nums;
}
.verdict__score sup {
  font-size: .58em; vertical-align: top; margin-left: .05em;
  font-style: normal; font-weight: 600; letter-spacing: 0; color: var(--accent);
}
.verdict__claim { display: block; margin-top: .35rem; font-size: .84rem; line-height: 1.4; color: var(--fg-2); }

.verdict__quotes { margin-top: 3.5rem; text-align: left; }
.verdict__more { margin: 2.5rem 0 0; justify-content: center; }

/* The two sources, side by side under the big figure: GuildQuality and
   Google, each its rating, name and count. A link each, to the source. */
.review-sources {
  list-style: none; margin: 1.6rem 0 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: .75rem 2.5rem;
}
.review-sources a {
  display: inline-flex; align-items: center; gap: .7rem;
  color: var(--fg); text-decoration: none;
}
.review-sources__num {
  font-family: var(--display); font-size: 2.2rem; line-height: 1;
  letter-spacing: -0.03em; font-variant-numeric: lining-nums;
}
.review-sources__src { display: flex; flex-direction: column; text-align: left; font-size: .84rem; line-height: 1.35; color: var(--fg-2); }
.review-sources__src b { font-weight: 600; color: var(--fg); }
.review-sources a:hover .review-sources__src b { text-decoration: underline; }
.sv-verdict .review-sources { justify-content: flex-start; margin-top: 2rem; }

@media (max-width: 60rem) { .verdict__row { grid-template-columns: repeat(3, 1fr); gap: 1.5rem 1rem; } }
@media (max-width: 40rem) { .verdict__row { grid-template-columns: 1fr 1fr; } }

/* --------------------------------------------------------------------------
   Stages — the Perez Process. A schedule of works: number, name, and what
   actually happens. The last stage is marked, because it is the one where the
   price stops moving.
   -------------------------------------------------------------------------- */

.stages { list-style: none; margin: 0; padding: 0; }
.stage {
  display: grid;
  grid-template-columns: 2.6rem minmax(0, 15rem) minmax(0, 1fr);
  gap: .4rem 2.5rem;
  align-items: start;
  padding: 1.6rem 0;
  border-top: 1px solid var(--rule);
}
.stage__n {
  font-family: var(--display); font-size: 1.05rem; font-weight: 700;
  letter-spacing: .01em; color: var(--accent); line-height: 1.5;
}
.stage h3 { font-size: var(--step-1); line-height: 1.3; }
.stage p { color: var(--fg-2); font-size: 1rem; margin: 0; }

/* The stage the guarantee attaches to */
.stage--promise { border-top-color: var(--accent); }
.stage--promise h3 { color: var(--accent); }
.stage__seal {
  grid-column: 2 / -1;
  margin-top: .9rem;
  padding-left: 1rem;
  border-left: 2px solid var(--accent);
  font-family: var(--display); font-style: normal; font-weight: 400;
  font-size: 1.1rem; color: var(--fg) !important;
}

/* --------------------------------------------------------------------------
   Promise — the guarantee, and the conditions it is earned under
   -------------------------------------------------------------------------- */

.promise {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: 2.5rem 4rem;
  align-items: center;
}
.promise__title { font-size: var(--step-3); margin-bottom: 1.1rem; }
.promise__title em { font-style: normal; }
.promise__lead { font-size: var(--step-1); line-height: 1.55; text-wrap: pretty; }
.promise__video video {
  display: block; width: 100%; aspect-ratio: 16 / 9;
  border-radius: var(--radius); background: var(--fg);
}
/* What the Promise means before the price is set (the Process page). */
.promise__terms { display: grid; gap: 1.75rem; }
.promise__term strong {
  display: block; margin-bottom: .4rem;
  font-family: var(--ui); font-size: .82rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--accent);
}
.promise__term p { margin: 0; color: var(--fg-2); }

/* The Perez Process: five steps that should read as one row on a wide
   screen rather than four and a straggler. */
.process-steps {
  list-style: none; margin: 0; padding: 0;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  gap: 2rem 1.75rem;
}

/* The Andersen hub's installation: six steps, three to a row. */
.andersen-steps {
  list-style: none; margin: 0; padding: 0;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.andersen-resources { list-style: none; margin: .5rem 0 0; padding: 0; display: grid; gap: .6rem; }

/* --------------------------------------------------------------------------
   Work — plates with measured captions
   -------------------------------------------------------------------------- */

.work {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr));
  gap: 2.5rem 1.75rem;
}
.work__item { text-decoration: none; display: block; }
.work__media {
  position: relative; display: block;
  aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--radius);
  background: var(--paper-2); margin-bottom: 1rem;
}
.work__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .8s var(--ease);
}
.work__item:hover .work__media img { transform: scale(1.035); }
/* The caption under a project photograph, in the UI face: the client found
   the small display serif hard to read here. */
.work__title {
  font-family: var(--ui); font-size: 1.15rem; font-weight: 600;
  line-height: 1.35; letter-spacing: 0; margin-bottom: .3rem; color: var(--fg);
}
.work__item:hover .work__title { color: var(--accent); }
.work__meta {
  font-family: var(--ui); font-size: .95rem; font-weight: 400;
  letter-spacing: 0; color: var(--fg-2);
  margin: 0;
}

/* --------------------------------------------------------------------------
   Before / after — a literal slider. A native range input sits over the
   whole frame for keyboard support (focus + arrow keys move it natively),
   but -webkit-appearance/appearance: none on the input turns off the
   browser's own click-anywhere-on-the-track behavior, leaving only its
   thumb as a hit target — and a thumb stretched to the track's full width
   to compensate collapses the browser's position math (which divides by
   trackWidth - thumbWidth) to zero, so dragging snaps straight to 0 or 100
   instead of tracking the pointer. So the input itself is pointer-events:
   none and site.js drives pointer/touch dragging by hand on the `.ba`
   frame, computing the position directly from the pointer's X and writing
   it to both the input's value (so it stays in sync for the keyboard) and
   the --pos custom property the "after" image and handle line are clipped
   and positioned by. Without JS the control still renders at a fixed 50/50
   split — degraded, not broken.
   -------------------------------------------------------------------------- */

.ba {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius);
  overflow: hidden;
  --pos: 50%;
  touch-action: pan-y;
  cursor: ew-resize;
}
.ba__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  user-select: none; -webkit-user-drag: none;
}
.ba__img--before { filter: saturate(.82); }
.ba__img--after { clip-path: inset(0 0 0 var(--pos)); }
.ba__label {
  position: absolute; bottom: .9rem;
  padding: .5rem 1rem; z-index: 1; pointer-events: none;
  font-family: var(--ui); font-size: var(--step--2); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--bone); background: var(--night);
}
.ba__label--before { left: .9rem; }
.ba__label--after { right: .9rem; background: var(--brick); }
.ba__handle {
  position: absolute; top: 0; bottom: 0; left: var(--pos);
  width: 2px; margin-left: -1px; background: var(--bone);
  pointer-events: none; z-index: 1;
  box-shadow: 0 0 0 1px rgba(16, 14, 14, .35);
}
.ba__handle::before {
  content: '\2194';
  position: absolute; top: 50%; left: 50%;
  width: 2.75rem; height: 2.75rem;
  display: flex; align-items: center; justify-content: center;
  transform: translate(-50%, -50%);
  border-radius: 50%; background: var(--bone); color: var(--night);
  font-size: 1.1rem;
  box-shadow: 0 .4rem 1rem rgba(16, 14, 14, .35);
}
.ba__range {
  position: absolute; inset: 0; z-index: 2;
  width: 100%; height: 100%; margin: 0;
  appearance: none; -webkit-appearance: none;
  background: transparent; pointer-events: none;
}
.ba__range::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: 1px; height: 100%; background: transparent; }
.ba__range::-moz-range-thumb { width: 1px; height: 100%; border: 0; background: transparent; opacity: 0; }
.ba__range::-moz-range-track { background: transparent; border: 0; }
.ba__range:focus-visible ~ .ba__handle { outline: 2px solid var(--bone); outline-offset: 3px; }

/* Two pairs, side by side rather than stacked full-width — at the shell's
   own width a single 4:3 slider runs nearly the height of the viewport. The
   measured note under each one says what the work was; whose house it is
   stays out of it. */
.ba-set {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(2rem, 1.5rem + 2vw, 3.5rem);
}
.ba-pair__note { margin-top: 1rem; }
.ba-pair__note span, .glass__note span { text-wrap: balance; }
.ba-pair__note::after { flex: 0 1 10rem; }

/* --------------------------------------------------------------------------
   Split — statement beside a framed photograph, the composition fixxmenow's
   argument sections are built on. Text reads first, the plate proves it.
   -------------------------------------------------------------------------- */

.split {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: 3rem 4.5rem;
  align-items: center;
}
.split__text .head__title { margin-bottom: 1rem; }
.split__text .lede { margin-bottom: .35rem; }
.split__media { margin: 0; }
.split__media img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
}
.split__media figcaption { margin-top: 1rem; }

/* Head beside a plate, for text-heavy bands that need a photograph */
.split--head { margin-bottom: clamp(2.5rem, 2rem + 2vw, 3.5rem); }
.split--head .head { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   Service pages: photo chapters
   --------------------------------------------------------------------------
   After henrybuilt.com. Each section is one photograph with a charcoal card
   set into its corner, the cards alternating sides down the page, so the
   page reads as a walk through finished rooms. The card is the one lifted
   object (the site's single shadow); everything else sits flat.

   Photographs stop at two-thirds of the shell. The files on hand are 1600px
   wide, and a photograph any larger than this goes soft on a retina screen.
   -------------------------------------------------------------------------- */

.sv-page {
  --sv-inset: max(var(--gutter), calc((100vw - var(--shell)) / 2));
  --sv-space: clamp(5rem, 3rem + 6vw, 9rem);
  --ch-width: min(100% - (var(--gutter) * 2), var(--shell));
}

/* The service and project pages stand on the homepage's lifted charcoal
   (the "We Design It" band) rather than the base black. What used that
   same tone to stand apart from the black (the cards, the alternating
   bands) steps down to the base black instead, so the contrast is kept,
   only reversed. */
.page-ground {
  --paper: var(--char-2);
  --paper-2: var(--char);
  background: var(--char-2);
}
.page-ground .ch-card,
.page-ground .pj-mosaic__tile { background: var(--char); }

/* The card: the one raised thing on the page. */
.ch-card {
  position: relative; z-index: 1;
  background: var(--char-2);
  box-shadow: var(--shadow-lift);
}
.ch-card__title {
  display: block;
  font-family: var(--display); font-weight: 600;
  font-size: var(--step-2); line-height: 1.1; letter-spacing: -0.02em;
  color: var(--fg);
  margin: 0 0 .75rem;
}
.ch-card__title--h2 { font-size: var(--step-3); font-weight: 700; margin-bottom: 1.1rem; }
.ch-card__body { margin: 0 0 1.4rem; font-size: .98rem; line-height: 1.65; color: var(--fg-2); }
.ch-card__body p { margin: 0 0 1em; }
.ch-card__body p:last-child { margin-bottom: 0; }
.ch-link {
  color: var(--fg); text-decoration: none; font-size: .92rem;
  padding-bottom: .3rem;
  background: linear-gradient(currentColor, currentColor) 0 100% / 100% 1px no-repeat;
  transition: background-size .35s var(--ease);
}
.ch-link:hover { background-size: 35% 1px; }

/* The hero: the photograph two-thirds wide on the right, the title card
   laid over its lower-left corner and running out onto the charcoal. */
.ch-hero {
  position: relative;
  width: var(--ch-width); margin: 0 auto;
  padding: clamp(2rem, 1rem + 2vw, 3.5rem) 0 clamp(6rem, 4rem + 5vw, 9rem);
  min-height: 36rem;
}
.ch-hero__photo { margin: 0 0 0 auto; width: 66%; }
.ch-hero__photo img, .ch-hero__photo video { width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; display: block; }
.ch-hero__card {
  position: absolute; left: 0; bottom: clamp(3rem, 2rem + 2vw, 5rem);
  width: min(33rem, 46%);
  padding: clamp(2rem, 1.4rem + 1.6vw, 3.2rem);
}
.ch-hero__card .crumbs { margin-bottom: 2.2rem; }
/* A long page name ("Landscaping & Hardscaping") gets a wider card, so the
   title breaks into two lines instead of leaving the ampersand alone. */
.ch-hero--long .ch-hero__card { width: min(38rem, 54%); }
.ch-hero__title { font-size: var(--step-5); line-height: .92; margin: 0; }
.ch-hero__lede { margin: 1.3rem 0 2rem; font-size: var(--step-1); line-height: 1.6; color: var(--fg-2); max-width: 34ch; }
.ch-hero--bare { min-height: 0; }
.ch-hero--bare .ch-hero__card { position: static; width: min(40rem, 100%); }

/* Raised: the card high, the photograph set just below it (the gallery
   sections). The band behind opens in the slate of the drafting sheet and
   falls to black, and the projects below rise from black back into slate,
   so the two meet in the dark instead of at an edge. The sheet's grid runs
   up into the gray at the top and fades with it.
   Desktop only: a phone keeps the stacked hero as it was. */
@media (min-width: 60.001rem) {
  .ch-hero-band {
    position: relative;
    background: linear-gradient(to bottom, var(--slate) 0%, var(--char-2) 55%, var(--char) 100%);
  }
  .ch-hero-band::before {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background-image: var(--sheet-grid);
    background-size: var(--sheet-size);
    -webkit-mask-image: linear-gradient(to bottom, #000 0, transparent 60%);
            mask-image: linear-gradient(to bottom, #000 0, transparent 60%);
  }
  .ch-hero-band > .ch-hero { z-index: 1; }
  /* Followed by the page's charcoal rather than a slate sheet (the gallery
     index, a project page): the band settles into that charcoal instead. */
  .ch-hero-band--page {
    background: linear-gradient(to bottom, var(--slate) 0%, var(--char-2) 70%);
  }
  .ch-hero--raised { padding-bottom: clamp(2rem, 1.5rem + 1.5vw, 3rem); }
  .ch-hero--raised .ch-hero__photo { margin-top: clamp(2.5rem, 1.5rem + 2.5vw, 4.25rem); }
  .ch-hero--raised .ch-hero__card { top: clamp(1.25rem, .5rem + 1.5vw, 2.25rem); bottom: auto; }
  /* The hero's own padding already opens the space; the sheet's full
     top padding on top of it left a dead band before the first project. */
  .ch-hero-band + .ch-ground {
    padding-top: clamp(2.5rem, 1.5rem + 2.5vw, 4rem);
    background:
      linear-gradient(to bottom, var(--char) 0, transparent 24rem),
      radial-gradient(76rem 48rem at 94% -16%, rgba(138, 24, 42, .48), transparent 66%),
      radial-gradient(56rem 36rem at -8% 112%, rgba(138, 24, 42, .34), transparent 64%),
      var(--slate);
  }
  .ch-hero-band + .ch-ground::before {
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 22rem, #000 calc(100% - 18rem), transparent 100%);
            mask-image: linear-gradient(to bottom, transparent 0, #000 22rem, #000 calc(100% - 18rem), transparent 100%);
  }
}

/* The answer: short, set in the card's column, not a slab. */
.ch-intro__inner {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 1.5rem clamp(3rem, 2rem + 4vw, 7rem);
  padding-bottom: var(--sv-space);
}
.ch-intro__title { font-size: var(--step-3); line-height: 1.05; max-width: 14ch; }
.ch-intro__body { margin: 0; max-width: 56ch; font-size: var(--step-1); line-height: 1.7; color: var(--fg-2); }
/* With the team beside it, the heading and paragraph stack in the left
   column and the trades strip takes the right. */
.ch-intro__inner--team { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: center; }
.ch-intro__inner--team .ch-intro__title { margin-bottom: 1.4rem; }
/* A long page name ("Landscaping & Hardscaping in Scranton & Clarks
   Summit") takes half the row, so the heading sets in two or three lines
   instead of four. */
.ch-intro__inner--long { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.ch-intro__inner--long .ch-intro__title { max-width: 22ch; }
.ch-team { height: clamp(22rem, 18rem + 6vw, 28rem); }
/* The full roster (more than six trades) is too many for the side column:
   the strip runs the width of the page under the paragraph instead, at the
   homepage's height. */
.ch-intro__inner--full-team { grid-template-columns: minmax(0, 1fr); }
.ch-intro__inner--full-team .ch-intro__title { max-width: 22ch; }
.ch-intro__inner--full-team .ch-team { margin-top: 1.5rem; }
@media (min-width: 52.0625rem) {
  .ch-intro__inner--full-team .ch-team { height: clamp(22rem, 24rem + 6vw, 34rem); }
}

.ch-section { padding-bottom: var(--sv-space); }
.ch-section__title { font-size: var(--step-4); line-height: 1; margin: 0 0 clamp(2.5rem, 2rem + 2vw, 4rem); max-width: 16ch; }
/* A heading that is a sentence rather than a name ("Three phases, from
   first sketch to first day on site") sets in two lines, not four. */
.ch-section__title--wide { max-width: 28ch; }

/* A chapter: photograph on one side, the card overlapping its inner edge
   and dropping below it. Alternates down the page.

   A grid, not an absolutely placed card: the card spans the photo's row
   and a 4rem row under it, so a long write-up makes the chapter taller
   instead of running out of the top of it. --card is the card's width;
   the photo is always 64%, so the middle track is where the two overlap. */
.ch-chapter {
  --card: 42%;
  position: relative;
  width: var(--ch-width); margin: 0 auto;
  display: grid; grid-template-rows: auto 4rem;
}
.ch-chapter + .ch-chapter { margin-top: clamp(3.5rem, 2rem + 4vw, 6rem); }
.ch-chapter--left  { grid-template-columns: calc(100% - var(--card)) calc(var(--card) - 36%) 36%; }
.ch-chapter--right { grid-template-columns: 36% calc(var(--card) - 36%) calc(100% - var(--card)); }
.ch-chapter__photo { margin: 0; grid-row: 1; align-self: start; min-width: 0; }
.ch-chapter__photo img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; }
.ch-chapter--left  .ch-chapter__photo { grid-column: 1 / 3; }
.ch-chapter--right .ch-chapter__photo { grid-column: 2 / 4; }
.ch-chapter__card {
  position: relative; z-index: 1;
  grid-row: 1 / 3; align-self: end; min-width: 0;
  padding: 2rem 2.2rem 2.2rem;
}
/* The card's outer edge sits on the shell's edge, so the text lines up with
   the page; its width alone sets how far it laps over the photograph. */
.ch-chapter--left  .ch-chapter__card { grid-column: 2 / 4; }
.ch-chapter--right .ch-chapter__card { grid-column: 1 / 3; }
.ch-chapter--wide { --card: 46%; }
.ch-chapter--wide .ch-chapter__photo img { aspect-ratio: 4 / 3; }
.ch-appointment .ch-section__title { font-size: var(--step-3); line-height: 1.05; margin-bottom: 0; }

/* Project pages reuse the chapters. A project title can run long
   ("Transforming a Dark Kitchen into a Showcase of Light and Craft"), so
   it steps down a size from a service name. */
.pj-title { font-size: var(--step-4); line-height: .98; }
/* The write-up: up to three short columns under the mosaic, each headed
   by a small rail-style label, the body a step under reading size. One
   passage alone keeps a reading measure instead of stretching full width. */
.pj-notes {
  display: grid; gap: clamp(1.8rem, 1rem + 2.5vw, 3.5rem);
  grid-template-columns: repeat(3, minmax(0, 1fr));
  padding-top: clamp(2.5rem, 1.5rem + 3vw, 4.5rem);
}
.pj-notes--1 { grid-template-columns: minmax(0, 46rem); }
.pj-notes--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pj-note { border-top: 1px solid var(--rule); padding-top: 1.1rem; }
.pj-note__title {
  margin: 0 0 .9rem; font-family: var(--ui);
  font-size: .72rem; font-weight: 600; line-height: 1.3;
  letter-spacing: .24em; text-transform: uppercase; color: var(--muted);
}
.pj-note__body p { margin: 0 0 .8em; font-size: .95rem; line-height: 1.6; color: var(--fg-2); }
.pj-note__body p:last-child { margin-bottom: 0; }
@media (max-width: 56rem) {
  .pj-notes, .pj-notes--2 { grid-template-columns: minmax(0, 1fr); }
}
.ch-note__prose p { margin: 0 0 1em; max-width: 52ch; font-size: var(--step-1); line-height: 1.7; color: var(--fg); }
.ch-note__prose p:last-child { margin-bottom: 0; }
.ch-hero__photo a { display: block; }

/* The mosaic under a project's hero. One shape per tile count the view
   hands over (7, 5, 3, 2, 1), so the grid is always full. Every tile is a
   button that opens the viewer at its photograph. */
.pj-mosaic-wrap { width: var(--ch-width); margin: 0 auto; padding-bottom: var(--sv-space); }
/* The hero's usual foot room is for the card that hangs below the photo;
   with the mosaic following, the hero keeps just enough to clear the card. */
.ch-hero--mosaic { padding-bottom: clamp(3.5rem, 2.5rem + 3vw, 5.5rem); }
/* Raised, the card no longer hangs below the photo, so the hero can close
   up to the mosaic (desktop; the stacked phone hero keeps the rule above). */
@media (min-width: 60.001rem) {
  .ch-hero--raised.ch-hero--mosaic { padding-bottom: clamp(2rem, 1.5rem + 1.5vw, 3rem); }
}
.pj-mosaic { position: relative; display: grid; gap: .8rem; grid-auto-rows: clamp(9rem, 6rem + 7vw, 15rem); }
.pj-mosaic--7 { grid-template-columns: 2fr 1fr 1fr; }
.pj-mosaic--7 > :first-child { grid-row: span 2; }
.pj-mosaic--7 > :nth-child(4) { grid-column: span 2; }
.pj-mosaic--5 { grid-template-columns: 2fr 1fr 1fr; }
.pj-mosaic--5 > :first-child { grid-row: span 2; }
.pj-mosaic--3 { grid-template-columns: 2fr 1fr; }
.pj-mosaic--3 > :first-child { grid-row: span 2; }
.pj-mosaic--2 { grid-template-columns: 1fr 1fr; grid-auto-rows: clamp(12rem, 8rem + 10vw, 22rem); }
.pj-mosaic--1 { grid-template-columns: 1fr; grid-auto-rows: clamp(14rem, 8rem + 16vw, 28rem); }
.pj-mosaic__tile {
  display: block; padding: 0; border: 0; background: var(--char-2);
  overflow: hidden; cursor: zoom-in; min-height: 0;
}
.pj-mosaic__tile img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 1.2s var(--ease), opacity .3s var(--ease); }
.pj-mosaic__tile:hover img { transform: scale(1.03); }
.pj-mosaic__tile:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }
.pj-mosaic__all {
  position: absolute; right: 1rem; bottom: 1rem; z-index: 2;
  --btn-bg: var(--bone); --btn-fg: var(--brick-deep);
  gap: .6rem; padding: calc(.75rem + var(--btn-nudge)) 1.2rem calc(.75rem - var(--btn-nudge));
  font-size: .95rem; font-weight: 600;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .38);
  transition: background-color .2s var(--ease), color .2s var(--ease), transform .2s var(--ease);
}
.pj-mosaic__all:hover { background: var(--brick-lift); color: var(--bone); transform: translateY(-1px); }
.pj-mosaic__all:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }
@media (max-width: 40rem) {
  .pj-mosaic__all { right: .6rem; bottom: .6rem; padding: .6rem .9rem; font-size: .85rem; }
}
.pj-story { padding-top: 0; }

/* The viewer: one photograph at a time, on near-black, arrows either side. */
.pj-viewer {
  width: 100vw; height: 100vh; max-width: none; max-height: none;
  margin: 0; padding: 0; border: 0; background: rgba(16, 14, 14, .97); color: var(--bone);
}
.pj-viewer::backdrop { background: rgba(16, 14, 14, .9); }
.pj-viewer[open] { display: grid; grid-template-columns: 4.5rem 1fr 4.5rem; align-items: center; }
.pj-viewer__slide { margin: 0; grid-column: 2; display: grid; justify-items: center; gap: .8rem; }
.pj-viewer__slide[hidden] { display: none; }
.pj-viewer__slide img { max-width: 100%; max-height: calc(100vh - 6rem); object-fit: contain; }
.pj-viewer__frame { max-width: 100%; }
.pj-viewer__slide figcaption { font-size: .85rem; color: rgba(245, 236, 232, .6); font-variant-numeric: tabular-nums; }
/* "Before" on every before photograph: the hero, the mosaic and the
   viewer. The same dark plate as the homepage sliders' label. */
.pj-mosaic__tile, .ch-hero__photo { position: relative; }
.pj-viewer__frame { position: relative; display: block; line-height: 0; }
.pj-before {
  position: absolute; left: .9rem; bottom: .9rem; z-index: 1; pointer-events: none;
  padding: .5rem 1rem; line-height: 1.2;
  font-family: var(--ui); font-size: var(--step--2); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--bone); background: var(--night);
}
.pj-viewer__nav, .pj-viewer__close {
  background: none; border: 0; color: var(--bone); cursor: pointer;
  font-family: var(--display); line-height: 1;
}
.pj-viewer__nav { font-size: 3rem; height: 100%; }
.pj-viewer__nav--prev { grid-column: 1; grid-row: 1; }
.pj-viewer__nav--next { grid-column: 3; grid-row: 1; }
.pj-viewer__slide { grid-row: 1; }
.pj-viewer__close { position: absolute; top: 1rem; right: 1.4rem; font-size: 2.4rem; z-index: 1; }
.pj-viewer button:focus-visible { outline: 2px solid var(--bone); outline-offset: 2px; }

/* The facts, as a drawing's title block. */
/* About this project: one brick strip between the two slate grounds, the
   title over a single row of facts, each a plain label over a plain answer
   in the body face at reading size. The section keeps a short measure of
   charcoal either side, not the full band spacing. */
#about-this-project { padding-bottom: clamp(3rem, 2rem + 2vw, 4.5rem); }
/* The story's ground ends a normal step below its last element, and the
   facts start the same step below the ground: the full band spacing on
   both sides, plus a passage's own margin, stacked into a gap of some
   25rem on a page whose story is a single passage. */
.pj-story { padding-bottom: clamp(3.5rem, 2rem + 4vw, 6rem); }
.pj-story + .pj-close { padding-top: clamp(3rem, 2rem + 2vw, 4.5rem); }
/* The facts as a spec sheet: the title on the left, one fact to a ruled
   row on the right, the label in small caps beside a larger answer, so
   each line reads straight across. */
.ch-note.pj-about {
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); align-items: start;
  margin-top: 0;
  padding: clamp(2.25rem, 1.5rem + 2.5vw, 4rem) clamp(2rem, 1.5rem + 3vw, 4.5rem);
}
.ch-note.pj-about .ch-note__title { max-width: 10ch; }
.pj-facts { margin: 0; border-bottom: 1px solid var(--rule); }
.pj-fact {
  display: grid; grid-template-columns: minmax(8rem, 13rem) minmax(0, 1fr);
  gap: .3rem 1.5rem; align-items: baseline;
  padding: 1.05rem 0; border-top: 1px solid var(--rule);
}
.pj-fact dt {
  margin: 0;
  font-family: var(--ui); font-size: var(--step--2); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-2);
}
.pj-fact dd {
  margin: 0;
  font-family: var(--display); font-size: var(--step-1); font-weight: 600;
  line-height: 1.25; color: var(--fg);
}
.pj-fact a { color: var(--fg); text-decoration: underline; text-decoration-color: var(--rule); text-decoration-thickness: 1px; text-underline-offset: .25em; }
.pj-fact a:hover { text-decoration-color: var(--fg); }
@media (max-width: 52rem) {
  .ch-note.pj-about { grid-template-columns: 1fr; }
  .ch-note.pj-about .ch-note__title { max-width: none; }
}
@media (max-width: 40rem) {
  .pj-fact { grid-template-columns: 1fr; }
}

/* The heading over a run of work, with its "See all" button across from
   it: room under both before the first photograph (service, category and
   project pages alike), and the button as a solid bone plate, since brick
   on the drafting sheet's red bloom barely reads as a button. */
.ch-work__head { margin-bottom: clamp(3.5rem, 2.5rem + 3vw, 6rem); }
.ch-work__head .sv-actions .btn {
  --btn-bg: var(--bone); --btn-fg: var(--brick-deep);
  gap: .7rem; padding: calc(1rem + var(--btn-nudge)) 1.7rem calc(1rem - var(--btn-nudge));
  font-size: 1.02rem; font-weight: 600;
  box-shadow: 0 10px 24px rgba(0, 0, 0, .28);
  transition: background-color .2s var(--ease), color .2s var(--ease), transform .2s var(--ease);
}
.ch-work__head .btn i { transition: transform .2s var(--ease); }
.ch-work__head .btn:hover { background: var(--brick-lift); color: var(--bone); transform: translateY(-1px); }
.ch-work__head .btn:hover i { transform: translateX(3px); }

/* Section and index grids: many cards, so a row gap that clears the
   caption card hanging below each photograph. */
.pj-grid, .pj-sections { row-gap: clamp(3rem, 2rem + 2vw, 4.5rem); }
.pj-sections { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pj-sections .ch-work__card { min-width: 0; right: 1.5rem; }

@media (max-width: 60rem) { .pj-sections { grid-template-columns: 1fr 1fr; } }
@media (max-width: 40rem) {
  .pj-mosaic--7, .pj-mosaic--5 { grid-template-columns: 1fr 1fr; }
  .pj-mosaic--7 > :first-child, .pj-mosaic--5 > :first-child { grid-column: span 2; grid-row: auto; }
  .pj-mosaic--7 > :nth-child(4) { grid-column: auto; }
  .pj-viewer[open] { grid-template-columns: 2.5rem 1fr 2.5rem; }
  .pj-sections { grid-template-columns: 1fr; }
}

/* Offerings without a photograph, after the chapters. */
.ch-more {
  /* The offerings without a photograph, as a ruled schedule on the brick
     sheet. The column count follows the count of items (set in the
     template), so four sit two by two instead of three and an orphan.
     Rules sit on top of each item, so the first row runs clean under the
     sheet's edge. */
  display: grid; grid-template-columns: repeat(var(--more-cols, 3), minmax(0, 1fr));
  margin-top: 4rem;
  padding: clamp(1.2rem, .6rem + 2vw, 2.6rem) clamp(2.5rem, 1.5rem + 3vw, 4.5rem);
}
.ch-more--1 { --more-cols: 1; }
.ch-more--2, .ch-more--4 { --more-cols: 2; }
.ch-more > article {
  padding: 2.2rem 2.5rem 2.4rem 0;
  border-top: 1px solid var(--rule);
}
/* Three columns is the default, so the rules for it apply at any count the
   two-column and single cases don't claim: seven items once drew a rule on
   every edge because only three, five and six were named. */
.ch-more--1 > article:first-child,
.ch-more--2 > article:nth-child(-n+2), .ch-more--4 > article:nth-child(-n+2),
.ch-more:where(:not(.ch-more--1, .ch-more--2, .ch-more--4)) > article:nth-child(-n+3) { border-top: 0; }
.ch-more > article + article { padding-left: 2.5rem; border-left: 1px solid var(--rule); }
.ch-more--2 > article:nth-child(odd), .ch-more--4 > article:nth-child(odd),
.ch-more:where(:not(.ch-more--1, .ch-more--2, .ch-more--4)) > article:nth-child(3n+1) { padding-left: 0; border-left: 0; }
/* One item left over on a row of its own (seven, ten) sits in the middle
   column, ruled on both sides so the column lines run down to it. The row
   above carries the full-width rule, since the lone item can only draw one
   over its own cell. */
@media (min-width: 52.001rem) {
  .ch-more:where(:not(.ch-more--1, .ch-more--2, .ch-more--4)) > article:nth-child(3n+1):last-child {
    grid-column: 2;
    padding-left: 2.5rem;
    border-top: 0;
    border-left: 1px solid var(--rule);
    border-right: 1px solid var(--rule);
  }
  .ch-more:where(:not(.ch-more--1, .ch-more--2, .ch-more--4)):has(> article:nth-child(3n+1):last-child)
    > article:nth-last-child(-n+4):not(:last-child) { border-bottom: 1px solid var(--rule); }
}
.ch-more .ch-card__body { margin: 0; max-width: 46ch; }
@media (max-width: 52rem) {
  .ch-more { --more-cols: 1; }
  .ch-more > article, .ch-more > article + article { padding: 1.8rem 0; border-left: 0; }
  .ch-more > article:not(:first-child) { border-top: 1px solid var(--rule); }
}

/* A process page's phases: after each phase's chapter, its steps, each
   on a brick tile of its own (as on the testimonials page). */
.pr-phase { margin-block: clamp(3.5rem, 2.5rem + 3vw, 5.5rem) clamp(5rem, 3.5rem + 5vw, 8.5rem); }
.pr-phase:last-child { margin-bottom: 0; }
.pr-steps {
  display: grid; grid-template-columns: repeat(var(--steps-cols, 3), minmax(0, 1fr));
  gap: 1.5rem;
  margin: 0; padding: 0; list-style: none;
}
.pr-steps--2, .pr-steps--4 { --steps-cols: 2; }
.pr-steps--1 { --steps-cols: 1; }
.pr-step {
  padding: clamp(1.75rem, 1.25rem + 1.5vw, 2.5rem);
}
.pr-step__title {
  margin: 0 0 .8rem;
  font-family: var(--display); font-weight: 600;
  font-size: var(--step-1); line-height: 1.2; letter-spacing: -0.01em;
  color: var(--fg);
}
.pr-step__points { margin: 0; padding: 0; list-style: none; }
.pr-step__points li {
  position: relative; padding-left: 1.1rem; margin-bottom: .45rem;
  font-size: .95rem; line-height: 1.6; color: var(--fg-2);
}
.pr-step__points li::before {
  content: ''; position: absolute; left: 0; top: .8em;
  width: .45rem; height: 1px; background: var(--fg-3);
}
.pr-step__body { margin: 0; font-size: 1rem; line-height: 1.65; color: var(--fg-2); }
.wdb-tiles { margin-top: clamp(4rem, 3rem + 3vw, 6rem); }
/* Bigger and bolder, as the client asked. */
.wdb-tiles .pr-step__title { font-size: var(--step-2); font-weight: 700; line-height: 1.12; margin-bottom: 1rem; }
/* "Phase 1: Preliminary planning" over each phase's name. The client found
   it too faint to read in the light serif, so it is set in the UI face,
   bold, at near the size of the card's body copy, in bone. */
.pr-phase__kicker {
  margin-bottom: .75rem;
  font-family: var(--ui); font-size: 1.35rem; font-weight: 700;
  letter-spacing: .01em; line-height: 1.3; color: var(--fg);
}
@media (max-width: 60rem) {
  .pr-steps, .pr-steps--2, .pr-steps--4 { --steps-cols: 2; }
}
@media (max-width: 40rem) {
  .pr-steps, .pr-steps--2, .pr-steps--4 { --steps-cols: 1; }
}

/* Veterans: the three VA grants, each a ruled row with its name and the
   most it pays on the left and who qualifies on the right. */
.vg__head { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 1rem clamp(2rem, 1rem + 4vw, 5rem); align-items: end; margin-bottom: clamp(2.5rem, 2rem + 2vw, 4rem); }
.vg__head .ch-section__title { margin: 0; }
.vg__intro { margin: 0; max-width: 52ch; font-size: var(--step-1); line-height: 1.7; color: var(--fg-2); }
.vg__grants { margin: 0; padding: 0; list-style: none; }
.vg-grant {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 1.5rem clamp(2rem, 1rem + 4vw, 5rem);
  padding-block: clamp(2.25rem, 1.75rem + 2vw, 3.5rem);
  border-top: 2px solid var(--brick-lift);
}
.vg-grant:last-child { border-bottom: 2px solid var(--brick-lift); }
.vg-grant__head > p { margin: 0; }
.vg-grant__num { font-family: var(--body); font-size: 1rem; color: var(--fg-2); margin-bottom: .4rem !important; }
.vg-grant__name {
  margin: 0 0 1.4rem;
  font-family: var(--display); font-weight: 600;
  font-size: var(--step-3); line-height: 1.08; letter-spacing: -0.02em; color: var(--fg);
}
.vg-grant__figure {
  font-family: var(--display); font-weight: 600;
  font-size: var(--step-4); line-height: 1; letter-spacing: -0.02em; color: var(--fg);
}
.vg-grant__figure--second { margin-top: 1.2rem !important; }
.vg-grant__fy { margin-top: .4rem !important; font-size: .95rem; color: var(--fg-2); }
.vg-grant__body p { margin: 0 0 1.1rem; font-size: var(--step-0); line-height: 1.7; color: var(--fg); max-width: 60ch; }
.vg-list { margin: 0 0 1.4rem; padding: 0; list-style: none; max-width: 60ch; }
.vg-list li {
  position: relative; padding: .55rem 0 .55rem 1.4rem;
  font-size: var(--step-0); line-height: 1.6; color: var(--fg);
  border-top: 1px solid var(--rule-2);
}
.vg-list li:first-child { border-top: 0; }
.vg-list li::before {
  content: ''; position: absolute; left: 0; top: 1.25em;
  width: .55rem; height: 2px; background: var(--brick-lift);
}
.vg-grant__body .vg-note {
  margin: 0; padding: 1rem 1.25rem;
  font-size: .95rem; line-height: 1.65; color: var(--fg-2);
  border-left: 3px solid var(--brick-lift); background: var(--surface);
}
@media (max-width: 60rem) {
  .vg__head, .vg-grant { grid-template-columns: 1fr; }
}

/* The appointment: the form in a card, the ways to call beside it. */
.ch-appointment {
  display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: 2.5rem clamp(3rem, 2rem + 4vw, 6rem); align-items: start;
}
.ch-appointment__form { padding: clamp(1.8rem, 1.2rem + 2vw, 3rem); }

/* The work: two photographs, each with a small card on its foot. */
.ch-work__head { display: flex; justify-content: space-between; align-items: center; gap: 1rem 2rem; flex-wrap: wrap; }
.ch-work__head .ch-section__title { margin-bottom: 0; }
.ch-work { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 1rem + 2vw, 3rem); margin-top: clamp(2.5rem, 2rem + 2vw, 4rem); }
.ch-work__item { position: relative; display: block; text-decoration: none; padding-bottom: 3rem; }
.ch-work__photo { display: block; overflow: hidden; }
.ch-work__photo img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; transition: transform 1.2s var(--ease); }
.ch-work__item:hover .ch-work__photo img { transform: scale(1.025); }
.ch-work__card { position: absolute; left: 1.5rem; bottom: 0; display: block; padding: 1.3rem 1.6rem; min-width: 60%; }
.ch-work__card .ch-card__title { margin-bottom: .3rem; }
.ch-work__place { font-size: .88rem; color: var(--fg-3); }

/* Shared by the verdict, questions and links. */
.sv-section { position: relative; padding-block: var(--sv-space) 0; }
.sv-section:last-child { padding-bottom: var(--sv-space); }
.sv-section--rule { padding-bottom: var(--sv-space); }
.sv-section--rule::before {
  content: ''; position: absolute; top: calc(var(--sv-space) * .5);
  left: var(--sv-inset); right: var(--sv-inset);
  height: 1px; background: var(--rule-2);
}
.sv-split {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: 2rem clamp(3rem, 1.5rem + 5vw, 8rem);
  align-items: start;
}
.sv-h2 { font-size: var(--step-3); line-height: 1.02; max-width: 14ch; }
.sv-pin { position: sticky; top: calc(var(--head-h, 6rem) + 2rem); }
.sv-prose p { max-width: 54ch; font-size: var(--step-1); line-height: 1.65; color: var(--fg-2); }
.sv-prose a { color: var(--fg); text-underline-offset: .2em; text-decoration-thickness: 1px; }
.sv-prose a:hover { color: var(--accent); }
.sv-elite { display: flex; align-items: center; gap: 1.1rem; margin-top: 1.4rem; color: var(--fg); }
/* The shield comes on white, so it gets a small white tile of its own
   rather than a hard square cut out of the charcoal. */
.sv-elite img { flex: none; width: 4.75rem; height: auto; padding: .45rem; background: #fff; border-radius: var(--radius-btn); }

.sv-note { max-width: 36ch; margin: 1.4rem 0 0; font-size: var(--step-1); line-height: 1.6; color: var(--fg-2); }
.sv-note--small { font-size: .92rem; color: var(--fg-3); }
.sv-contact { display: flex; flex-wrap: wrap; gap: .6rem 2rem; margin: 2rem 0 0; }
.sv-contact a {
  color: var(--fg); text-decoration: none;
  padding-bottom: .3rem;
  background: linear-gradient(currentColor, currentColor) 0 100% / 100% 1px no-repeat;
  transition: background-size .35s var(--ease), color .2s var(--ease);
}
.sv-contact a:hover { background-size: 30% 1px; color: var(--accent); }
.sv-contact--end { justify-content: flex-end; margin: 0; }
/* Call and text beside the form: real buttons, not underlined links. */
.sv-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin: 2rem 0 0; }
/* Always the red button, even on the slate grid, where .btn turns bone. */
.sv-actions .btn { --btn-bg: var(--brick-lift); --btn-fg: var(--bone); }
.sv-actions--end { justify-content: flex-end; margin: 0; }
@media (max-width: 60rem) { .sv-actions--end { justify-content: flex-start; } }

/* The form with its boxes taken away: only the rule a hand writes on. */
.sv-form .form-grid { gap: 2rem 2rem; }
.sv-form .field-input {
  background: transparent;
  border: 0; border-bottom: 1px solid var(--rule);
  border-radius: 0;
  padding: .6rem 0;
}
.sv-form .field-input:focus { border-bottom-color: var(--fg); box-shadow: none; outline: none; }
.sv-form .field-input:focus-visible { box-shadow: 0 1px 0 0 var(--fg); }
.sv-form select.field-input { background: transparent; }
.sv-form textarea.field-input { min-height: 5.5rem; }
.sv-form .actions { margin-top: 2.6rem !important; }
.sv-form .form-note { display: none; }

.sv-verdict { padding-bottom: var(--sv-space); }
.sv-verdict__figure { display: flex; align-items: baseline; gap: .6rem; margin: 2.2rem 0 0; }
.sv-verdict .sv-verdict__quote blockquote { font-size: var(--step-2); line-height: 1.3; max-width: 34ch; }
.sv-verdict__quote { max-width: none; }

.sv-faq .faq__q { font-size: var(--step-2); line-height: 1.2; padding-block: 1.6rem; }
.sv-faq .faq__a p { max-width: 58ch; color: var(--fg-2); }
.sv-onward p { font-size: var(--step-0); }

/* Breaks: what stands between runs of chapters, never more than three in
   a row (seo/pacing.py). A homeowner's words at pull-quote size, set in
   from the left so they read as a different shape from the cards; or the
   survey figure; or, on a gallery section, the next projects as plates. */
.ch-break { width: var(--ch-width); margin: clamp(5rem, 3.5rem + 5vw, 8.5rem) auto; }
.ch-break--plates { width: auto; }
.ch-break .ch-break__quote { max-width: 56rem; margin: 0 0 0 clamp(0rem, -6rem + 16vw, 12rem); }
.ch-break .ch-break__quote blockquote { font-size: var(--step-2); line-height: 1.25; letter-spacing: -0.015em; }
/* A homeowner's words go on the brick sheet, the same one as the
   not-sure note, so the quote reads as a stop and not another card. */
.ch-break--brick { padding: clamp(2.5rem, 1.5rem + 3vw, 4.5rem); }
.ch-break--brick .ch-break__quote { margin-left: clamp(0rem, -4rem + 10vw, 6rem); }
.ch-break__proof {
  max-width: 30ch; margin: 0 0 0 clamp(0rem, -6rem + 16vw, 12rem);
  font-family: var(--display); font-size: var(--step-3); line-height: 1.12;
  letter-spacing: -0.02em; color: var(--fg-2);
}
.ch-break__proof b { color: var(--fg); font-weight: 600; }

/* Levels: the direction band on a page that sells a range of scopes (whole
   house: refresh, rework, reimagine). A chapter each, with the same room
   before pinned over the photograph's outer corner. */
.ch-levels .ch-levels__intro {  /* beats p:last-child */
  max-width: 52ch; margin: calc(clamp(2.5rem, 2rem + 2vw, 4rem) * -.5) 0 clamp(5rem, 4rem + 3vw, 7rem);
  font-size: var(--step-1); line-height: 1.7; color: var(--fg-2);
}
.ch-level__photos { position: relative; }
.ch-level__photos > img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; }
.ch-level__before {
  position: absolute; top: -1.5rem; width: 34%; margin: 0;
  border: 6px solid var(--char); box-shadow: var(--shadow);
}
.ch-chapter--left .ch-level__before { left: -1.5rem; }
.ch-chapter--right .ch-level__before { right: -1.5rem; }
.ch-chapter__photo .ch-level__before img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }
.ch-level__before figcaption {
  position: absolute; left: .5rem; bottom: .4rem;
  font-size: var(--step--2); letter-spacing: .08em; text-transform: uppercase;
  color: var(--bone); text-shadow: 0 1px 3px rgba(0, 0, 0, .9);
}
.ch-level + .ch-level { margin-top: clamp(4.5rem, 3rem + 4vw, 7rem); }
.ch-level { --card: 44%; }
.ch-level__name {
  font-family: var(--display); font-weight: 600;
  font-size: var(--step-4); line-height: .95; letter-spacing: -0.02em;
  margin: 0 0 .8rem;
}
.ch-level__quote {
  font-family: var(--display); font-size: var(--step-2); line-height: 1.2;
  color: var(--fg); margin: 0 0 1.2rem;
}
.ch-level .ch-level__body { margin: 0 0 1.6rem; font-size: var(--step-0); line-height: 1.7; color: var(--fg-2); }
.ch-note {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 1.5rem clamp(2rem, 1rem + 4vw, 5rem); align-items: start;
  margin-top: clamp(4rem, 3rem + 3vw, 6rem);
  padding: clamp(2.5rem, 1.5rem + 3vw, 4.5rem);
}
.ch-note__title {
  margin: 0; font-family: var(--display); font-weight: 600;
  font-size: var(--step-3); line-height: 1.05; letter-spacing: -.02em;
  color: var(--fg); max-width: 14ch;
}
.ch-note .ch-note__body { margin: 0 0 1.8rem; font-size: var(--step-1); line-height: 1.7; max-width: 52ch; }
@media (max-width: 52rem) { .ch-note { grid-template-columns: 1fr; } }

@media (max-width: 60rem) {
  .ch-chapter--left .ch-level__before, .ch-chapter--right .ch-level__before {
    top: .75rem; left: .75rem; right: auto; width: 38%; border-width: 4px;
  }
  .ch-level__card { width: calc(100% - 2rem); }
}

@media (max-width: 60rem) {
  .ch-hero { padding-bottom: 3rem; min-height: 0; }
  .ch-hero__photo, .ch-chapter__photo { width: 100%; }
  .ch-hero__card, .ch-chapter__card,
  .ch-chapter--left .ch-chapter__card, .ch-chapter--right .ch-chapter__card {
    position: relative; left: auto; right: auto; bottom: auto;
    width: calc(100% - 2rem); margin: -3rem 0 0 1rem;
  }
  .ch-chapter { display: block; }
  .ch-intro__inner, .ch-appointment, .sv-split { grid-template-columns: 1fr; }
  .sv-pin { position: static; }
  .sv-contact--end { justify-content: flex-start; }
}
@media (max-width: 52rem) {
  .ch-team { height: auto; }
  /* Five trades in a 2-up grid would leave one alone: the first spans. */
  .ch-team .cast__item:first-child:nth-last-child(odd) { grid-column: 1 / -1; aspect-ratio: 16 / 9; }
}
@media (max-width: 40rem) {
  .ch-work { grid-template-columns: 1fr; }
  .sv-form .form-grid { grid-template-columns: 1fr; }
}

/* Proof, as short ticks */
.ticks {
  list-style: none; padding: 0;
  margin: 1.4rem 0 2.1rem;
  display: grid; gap: .6rem;
}
.ticks li {
  display: flex; align-items: baseline; gap: .75rem;
  color: var(--fg-2); font-size: 1.05rem;
}
.ticks li::before {
  content: '\2713';
  flex: 0 0 auto;
  font-family: var(--display); font-weight: 700;
  color: var(--accent);
}
.ticks--row {
  display: flex; flex-wrap: wrap;
  gap: .7rem 2.2rem;
  margin: 1.2rem 0 1.9rem;
}
.ticks--row li { font-size: 1rem; }

/* --------------------------------------------------------------------------
   Quotes
   -------------------------------------------------------------------------- */

.quote { max-width: 40rem; }
.quote blockquote {
  margin: 0 0 1.1rem;
  font-family: var(--display);
  /* A pull quote is set at headline scale in print. At body scale it is just
     an indented paragraph. */
  font-size: var(--step-4);
  line-height: 1.08;
  letter-spacing: -0.03em;
  /* The tight tracking closes the spaces up too, until "to, gave" reads as
     one word; this gives the word gaps back. */
  word-spacing: .1em;
  color: var(--fg);
}
.quote figcaption {
  font-family: var(--ui); font-size: var(--step--2); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-3);
}

.quote-stack {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: 2rem 2.5rem;
}
.quote-stack .quote {
  border-top: 1px solid var(--rule);
  padding-top: 1.4rem;
}
.quote-stack .quote blockquote {
  font-family: var(--display); font-style: normal; font-weight: 400;
  font-size: 1.15rem; line-height: 1.55; letter-spacing: -0.006em;
}
/* The testimonials page: each homeowner on a brick tile of their own. */
.quote-stack--tiles { grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr)); gap: 1.5rem; }
.quote-stack--tiles .quote {
  max-width: none; display: flex; flex-direction: column; justify-content: space-between;
  padding: clamp(1.75rem, 1.25rem + 1.5vw, 2.5rem);
  border-top: 0;
  background: var(--brick);
  --fg: var(--bone); --fg-2: rgba(245, 236, 232, .84); --fg-3: rgba(245, 236, 232, .76);
  color: var(--fg);
}
.quote-stack--tiles .quote blockquote {
  /* The client found the display serif hard to read at quote length, so
     the testimonials page sets its quotes in the UI face. */
  margin-bottom: 1.5rem;
  font-family: var(--ui); font-size: 1.15rem; line-height: 1.65;
  letter-spacing: 0; word-spacing: normal;
}
.quote-stack--tiles .quote figcaption {
  font-family: var(--body); font-size: 1rem; font-weight: 600;
  letter-spacing: 0; text-transform: none; color: var(--fg);
}

/* --------------------------------------------------------------------------
   Places
   -------------------------------------------------------------------------- */

.places {
  list-style: none; margin: 0; padding: 0;
  columns: 4; column-gap: 2.5rem; font-size: 1rem;
}
.places li { break-inside: avoid; margin-bottom: .45rem; }
.places a { text-decoration: none; color: var(--fg-2); }
.places a:hover { color: var(--accent); }

/* Service area by county: five columns divided by hairlines, the county name
   in the display face, the towns beneath it as one run of small links. */
.counties {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  border-top: 1px solid var(--rule);
}
.county { padding: 1.6rem 1.6rem 0 0; }
.county + .county { padding-left: 1.6rem; border-left: 1px solid var(--rule-2); }
/* The service page's county grid holds only .county__name, none of the
   homepage's .county__towns that the base padding is
   built for, so the same top-heavy 1.6rem/0 split leaves the row's foot
   bare and the hairlines between cells read as short stubs. Match the
   bottom padding to the top instead of changing the shared rule above. */
.county--bare { padding-bottom: 1.6rem; }
.county__name {
  font-family: var(--display); font-weight: 600;
  font-size: var(--step-2); letter-spacing: -0.02em; line-height: 1.1;
  margin: 0 0 .25rem;
}
.county__name a { color: var(--fg); text-decoration: none; }
.county__name a:hover { color: var(--accent); }
.county__name + .county__towns { margin-top: .75rem; }
.county__towns { list-style: none; margin: 0; padding: 0; font-size: .95rem; line-height: 1.75; }
.county__towns li { display: inline; }
.county__towns li:not(:last-child)::after { content: ', '; color: var(--fg-3); }
.county__towns a { color: var(--fg-2); text-decoration: none; }
.county__towns a:hover { color: var(--accent); }

/* Bring Your Inspiration: three ways in, ruled the same way as the county
   grid so the row reads as fact rather than as a sales pitch. */
.inspire {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--rule); max-width: 62rem; margin-inline: auto;
  text-align: center;
}
.inspire__item { padding: 1.6rem 1.6rem 0; }
.inspire__item + .inspire__item { border-left: 1px solid var(--rule-2); }
.inspire__title {
  font-family: var(--display); font-weight: 600;
  font-size: var(--step-2); letter-spacing: -0.02em; line-height: 1.1;
  margin: 0 0 .6rem;
}
.inspire__body { margin: 0; font-size: .95rem; line-height: 1.6; color: var(--fg-2); }


/* --------------------------------------------------------------------------
   Andersen — the lit window
   --------------------------------------------------------------------------
   Copy left, and on the right a bone sash of six lites, two across and
   three down, the proportions of a double-hung, each lite its own
   photograph of windows or doors the firm fitted. Against charcoal bright
   pictures inside a pale frame read as a lit window seen from the yard at
   dusk, which is the whole pitch made without a word. */

.glass-band {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: 3rem clamp(3rem, 2rem + 4vw, 6rem);
  align-items: center;
}
.glass-band__title { font-size: var(--step-5); line-height: 1.05; margin-bottom: 1.25rem; }
.glass-band__line { display: block; white-space: nowrap; }
@media (max-width: 24rem) { .glass-band__line { white-space: normal; } }
.glass-band__lead {
  max-width: 44ch; margin: 0 0 2.1rem;
  font-size: var(--step-1); line-height: 1.6; color: var(--fg-2);
  text-wrap: pretty;
}
.andersen-cred {
  display: flex; align-items: center; gap: 1rem 1.4rem;
  margin-top: 2.2rem; max-width: 36rem;
  padding: 1rem 1.4rem; border-radius: var(--radius-btn);
  /* A soft warm gray rather than full bone, so the card sits in the
     charcoal instead of glaring off it; still light enough for the mark. */
  background: #D6D1CE; color: rgba(23, 20, 20, .78);
}
.andersen-cred__mark { display: block; flex: none; width: 5.5rem; height: auto; mix-blend-mode: multiply; }
.andersen-cred__claim {
  margin: 0; padding-left: 1.4rem; border-left: 1px solid rgba(23, 20, 20, .18);
  font-family: var(--display); font-size: var(--step-0); line-height: 1.35; font-weight: 600;
}
.andersen-cred__claim strong { font-weight: 700; color: var(--brick); }
@media (max-width: 30rem) {
  .andersen-cred { flex-direction: column; align-items: center; text-align: center; }
  .andersen-cred__claim { padding: .9rem 0 0; border-left: 0; border-top: 1px solid rgba(23, 20, 20, .18); }
}

.opening-picks {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .9rem; max-width: 36rem; margin-top: 2rem;
}
.opening-pick {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.05rem 1.35rem;
  border: 1px solid var(--rule); border-radius: var(--radius-btn);
  background: var(--surface);
  color: var(--fg); text-decoration: none;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.opening-pick:hover, .opening-pick:focus-visible {
  border-color: var(--fg); background: rgba(245, 236, 232, .08);
}
.opening-pick__word {
  font-family: var(--display); font-weight: 600; font-size: var(--step-2);
  line-height: 1.1; letter-spacing: -0.01em;
}
.opening-pick__arrow { color: var(--fg-2); transition: transform .2s var(--ease), color .2s var(--ease); }
.opening-pick:hover .opening-pick__arrow { transform: translateX(.25rem); color: var(--fg); }
/* The hub link under the pair: one button the width of both, set a pinch
   further down than the gap between them. */
.opening-pick--hub { max-width: 36rem; margin-top: 1.25rem; }
@media (max-width: 30rem) { .opening-picks { grid-template-columns: 1fr; } }

.glass { margin: 0; justify-self: end; width: min(100%, 30rem); }
.glass__sash {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: repeat(3, 1fr);
  /* The muntins are the gap, so the bone behind paints them. */
  gap: .4rem;
  aspect-ratio: 4 / 5;
  /* The frame: bone, with a shadow line at the reveal so it sits proud of
     the wall rather than printed on it. */
  padding: .55rem;
  background: var(--bone);
  border-radius: 3px;
  box-shadow:
    inset 0 0 0 1px rgba(23, 20, 20, .10),
    var(--shadow-lift),
    /* The spill: the room's own light on the siding around it. */
    0 0 7rem rgba(245, 236, 232, .09);
}
.glass__pane { display: block; min-height: 0; overflow: hidden; border-radius: 1px; background: var(--char-2); }
.glass__pane img {
  display: block; width: 100%; height: 100%;
  object-fit: cover;
}
.glass__note { margin-top: 1.1rem; }

/* Side by side, the two columns share guides: the headline starts on the
   sash's top edge and the buttons end on its bottom edge. The copy column
   stretches to the row and the buttons drop to the frame's bottom; the
   headline, lead and credential ride as one block centred in the height
   left above them (equal slack over and under); the caption hangs
   below the sash so the figure's box ends where the frame does. Where the
   copy wraps taller than a 4:5 sash (narrow desktops), the sash grows to
   meet it rather than leaving the buttons below the frame. */
@media (min-width: 70.01rem) {
  .glass-band { align-items: stretch; }
  .glass-band__copy { display: flex; flex-direction: column; }
  .glass-band__foot { display: contents; }
  .glass-band__title { margin-top: auto; }
  .glass-band__foot .andersen-cred { margin-top: 0; }
  .glass-band__foot .opening-picks { margin-top: auto; padding-top: 2rem; }
  .glass { position: relative; display: flex; flex-direction: column; }
  .glass__sash { flex: 1 0 auto; }
  .glass__note { position: absolute; top: 100%; left: 0; right: 0; }
}

/* Stacked through tablet: side by side below ~1120px, the unwrapping
   headline runs into the sash. Stacked, everything centres on one axis:
   the rail and caption take a rule either side, the copy and its blocks
   sit on the middle. */
@media (max-width: 70rem) {
  .glass-band { grid-template-columns: 1fr; gap: 2.5rem; }
  .glass-band__rail::after { content: ''; flex: 1 1 auto; height: 1px; background: var(--rule); order: -1; }
  .glass-band__copy { text-align: center; }
  .glass-band__lead, .andersen-cred, .opening-picks, .opening-pick--hub { margin-inline: auto; }
  .andersen-cred { text-align: left; }
  .glass__note { justify-content: center; }
  .glass__note::before { display: block; }
  .glass__note::after { flex: 1 1 auto; }
  .glass { justify-self: center; width: min(100%, 40rem); }
  /* Stacked, the sash turns landscape: three across, two down, so the
     six lites don't make a tall column the reader has to scroll past. */
  .glass__sash { grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(2, 1fr); aspect-ratio: 3 / 2; gap: .3rem; padding: .45rem; }
}

/* --------------------------------------------------------------------------
   Plain link list and index
   -------------------------------------------------------------------------- */

.list { border-top: 1px solid var(--rule); }
.list a {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 2rem; padding: 1.05rem 0;
  border-bottom: 1px solid var(--rule-2);
  text-decoration: none; font-size: var(--step-1);
  transition: color .18s var(--ease), padding-left .18s var(--ease);
}
.list a:hover { color: var(--accent); padding-left: .4rem; }
.list a > span:last-child { color: var(--accent); opacity: 0; transition: opacity .18s var(--ease); }
.list a:hover > span:last-child { opacity: 1; }
.list__empty {
  padding: 1.05rem 0; border-bottom: 1px solid var(--rule-2);
  font-size: var(--step-1); color: var(--fg-2);
}

.index { border-top: 1px solid var(--rule); }
.index__row {
  display: grid; grid-template-columns: minmax(0, 17rem) minmax(0, 1fr) auto;
  gap: .35rem 2.5rem; align-items: baseline;
  padding: 1.45rem 0; border-bottom: 1px solid var(--rule-2);
  text-decoration: none; transition: color .18s var(--ease);
}
.index__row:hover { color: var(--accent); }
.index__row:hover .index__mark { opacity: 1; }
.index__name { font-family: var(--display); font-size: var(--step-2);
               letter-spacing: var(--tight); line-height: 1.25; }
.index__note { color: var(--fg-2); font-size: 1rem; }
.index__mark { color: var(--accent); opacity: 0; transition: opacity .18s var(--ease); }

/* --------------------------------------------------------------------------
   Facts
   -------------------------------------------------------------------------- */

.facts { display: flex; flex-wrap: wrap; gap: 1.5rem 3.5rem; margin: 0; }
.facts > div { display: grid; gap: .15rem; }
.facts dt {
  font-family: var(--ui); font-size: var(--step--2); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-3);
}
.facts dd { margin: 0; color: var(--fg-2); }

/* --------------------------------------------------------------------------
   FAQ
   -------------------------------------------------------------------------- */

.faq { border-top: 1px solid var(--rule); }
.faq__item { border-bottom: 1px solid var(--rule-2); }
.faq__q {
  width: 100%; display: flex; align-items: flex-start;
  justify-content: space-between; gap: 2rem;
  padding: 1.3rem 0; background: none; border: 0; cursor: pointer;
  font-family: var(--display); font-size: var(--step-1);
  letter-spacing: var(--tight);
  color: var(--fg); text-align: left; line-height: 1.4;
}
.faq__q:hover { color: var(--accent); }
.faq__sign { flex: 0 0 auto; width: 1rem; height: 1rem; position: relative; margin-top: .4rem; }
.faq__sign::before, .faq__sign::after {
  content: ''; position: absolute; inset: 50% 0 auto 0; height: 1px;
  background: var(--accent); transition: transform .25s var(--ease);
}
.faq__sign::after { transform: rotate(90deg); }
.faq__q[aria-expanded='true'] .faq__sign::after { transform: rotate(0); }
.faq__a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .3s var(--ease); }
.faq__a > div { overflow: hidden; }
.faq__item[data-open='true'] .faq__a { grid-template-rows: 1fr; }
.faq__a p { padding-bottom: 1.3rem; color: var(--fg-2); max-width: 66ch; }

/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: 1.2rem;
}
.field { display: flex; flex-direction: column; gap: .4rem; }
.field--wide { grid-column: 1 / -1; }
.field-label {
  font-family: var(--ui); font-size: var(--step--2); font-weight: 600;
  letter-spacing: .13em; text-transform: uppercase; color: var(--fg-3);
}
.field-input {
  width: 100%; padding: .78rem .9rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius); color: var(--fg);
  font-family: var(--body); font-size: 1rem;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.field-input::placeholder { color: var(--fg-3); }
.field-input:focus {
  outline: none; border-color: var(--brick);
  box-shadow: 0 0 0 3px var(--brick-soft);
}
select.field-input { appearance: none; cursor: pointer; }
/* The open list is the system's own light menu, so on a dark band the
   options can't inherit the field's bone text: it vanished on white. */
select.field-input option { color: var(--char); background-color: #fff; }
textarea.field-input { resize: vertical; min-height: 7rem; line-height: 1.65; }
.field-error { font-size: .85rem; color: var(--brick); margin: 0; }
.field-help { font-size: .85rem; color: var(--fg-3); margin: 0; }
.form-note { font-size: .95rem; color: var(--fg-3); max-width: 42ch; }

.form-panel, .panel {
  background: var(--paper-2);
  border: 1px solid var(--rule-2);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 1rem + 2vw, 2.6rem);
}
.panel__body { display: grid; gap: 1.25rem; }

.two-up {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: 3rem 4rem;
  align-items: start;
}

.about__plate { margin: 0; }
.about__plate img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radius);
}
.about__plate video {
  display: block; width: 100%; aspect-ratio: 16 / 9;
  border-radius: var(--radius); background: var(--fg);
}
.about__plate figcaption { margin-top: .85rem; }
.facts { flex-direction: column; gap: 1.35rem; }
.facts dd a { color: var(--accent); text-underline-offset: .18em; }

.contact-email {
  font-family: var(--body); font-size: 1.05rem; color: var(--accent);
  text-underline-offset: .18em;
}

.map-frame {
  position: relative;
  aspect-ratio: 21 / 8;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--paper-2);
}
.map-frame iframe { width: 100%; height: 100%; border: 0; display: block; }
@media (max-width: 52rem) { .map-frame { aspect-ratio: 4 / 3; } }

.contact-line {
  font-family: var(--body); font-size: var(--step-3); font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--fg); text-decoration: none;
}
.contact-line:hover { color: var(--brick); }
/* The contact page's text line: words on a computer, an sms: link on a
   phone (swapped in the small-screen block, beside the topbar's). */
.contact-text__mobile { display: none; }

/* --------------------------------------------------------------------------
   Conversion band — brick. The one saturated surface on the site, and the
   only place the red is spent at full strength.
   -------------------------------------------------------------------------- */

.cta, .band--brick, .ch-note, .ch-break--brick, .ch-more, .pr-step, .aw-row,
.quote-stack--tiles .quote {
  position: relative;
  background: var(--brick);
  --fg:      var(--bone);
  --fg-2:    rgba(245, 236, 232, .84);
  /* The mark's red is lighter than the old brick, so the faint step has to
     come up with it or the small caps labels drop under AA. */
  --fg-3:    rgba(245, 236, 232, .76);
  --accent:  var(--bone);
  --accent-fg: var(--brick-deep);
  --rule:    rgba(245, 236, 232, .28);
  --rule-2:  rgba(245, 236, 232, .16);
  --btn-bg:  var(--bone);
  --btn-fg:  var(--brick-deep);
  color: var(--fg);
}
.cta .btn:hover, .band--brick .btn:hover, .ch-note .btn:hover { background: var(--night); color: var(--bone); }
.cta .btn--outline, .band--brick .btn--outline { background: transparent; color: var(--fg); border-color: rgba(245, 236, 232, .5); }
.cta .btn--outline:hover, .band--brick .btn--outline:hover { background: var(--fg); color: var(--brick-deep); border-color: var(--fg); }
.cta__inner {
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: 2.5rem 4rem; align-items: center;
}
.cta__title { font-size: var(--step-3); margin-bottom: .85rem; }
.cta__title em { font-style: normal; }
.cta p, .band--brick p { color: var(--fg-2); }
.cta__panel { display: grid; gap: 1.1rem; }
.cta__plate img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius);
}
.cta__hours {
  font-family: var(--ui); font-size: .86rem; color: var(--fg-3); margin: 0;
}
.cta__hours a { color: var(--fg-2); text-underline-offset: .18em; }
.cta__hours a:hover { color: var(--bone); }

/* --------------------------------------------------------------------------
   Breadcrumbs and page heads
   -------------------------------------------------------------------------- */

.crumbs {
  display: flex; flex-wrap: wrap; gap: .25rem .55rem;
  list-style: none; margin: 0 0 1.4rem; padding: 0;
  font-family: var(--ui); font-size: var(--step--2);
  letter-spacing: .1em; text-transform: uppercase; color: var(--fg-3);
}
.crumbs a { text-decoration: none; }
.crumbs a:hover { color: var(--accent); }
.crumbs li:not(:last-child)::after { content: '/'; margin-left: .55rem; opacity: .45; }

.page-head {
  position: relative;
  padding-block: clamp(2.75rem, 2rem + 3vw, 4.5rem) clamp(2.25rem, 1.8rem + 2.4vw, 3.5rem);
  background: var(--paper-2);
  border-bottom: 1px solid var(--rule-2);
}
.page-head__title { font-size: var(--step-4); max-width: 20ch; }
.page-head__title em { font-style: normal; color: var(--brick); }
.page-head__lede { margin-top: 1.2rem; }

/* --------------------------------------------------------------------------
   Services index: a branch per category, its photo chapter, then every
   page under it as a photo tile with its name on a card over the corner,
   the same tile as the recent work.
   -------------------------------------------------------------------------- */
.svc-branch__kicker {
  margin: 0 0 .6rem;
  font-family: var(--ui); font-size: var(--step--2); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-3);
}
.svc-grid {
  list-style: none; margin: clamp(3rem, 2rem + 3vw, 5rem) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
  gap: clamp(1.5rem, 1rem + 1.5vw, 2.5rem) clamp(1.25rem, 1rem + 1vw, 2rem);
}
.svc-tile .ch-work__photo { background: var(--char); }
.svc-tile__card { right: 1.5rem; min-width: 0; }
.svc-tile__card .ch-card__title { font-size: var(--step-1); margin-bottom: 0; }
.svc-tile__summary { display: block; margin-top: .45rem; font-size: .9rem; line-height: 1.5; color: var(--fg-2); }

/* --------------------------------------------------------------------------
   Awards: logos on bone plates. Most were supplied on white, so multiply
   lets the plate's tone through instead of a white box inside a bone one.
   -------------------------------------------------------------------------- */
.aw-intro p { margin: 0 0 1em; }
.aw-intro p:last-child { margin-bottom: 0; }
/* Each award on a brick tile of its own, two across, like the process
   steps and the testimonials. Every tile is the same shape at every width:
   a fixed plate on the left, the words beside it, both hung from the top,
   so no logo's proportions can move the text. */
.aw-ledger {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem;
}
.aw-row {
  display: grid; grid-template-columns: 11rem minmax(0, 1fr);
  gap: 1.6rem; align-items: start;
  padding: clamp(1.75rem, 1.25rem + 1.5vw, 2.5rem);
}
.aw-plate {
  display: flex; align-items: center; justify-content: center; isolation: isolate;
  width: 100%; height: 7.5rem; padding: .6rem .8rem;
  background: var(--bone); border-radius: var(--radius);
}
.aw-plate img {
  display: block; min-width: 0; min-height: 0;
  max-width: 100%; max-height: 100%; width: auto; height: auto;
  object-fit: contain; mix-blend-mode: multiply;
}
.aw-plate__name {
  font-family: var(--display); font-weight: 600; font-size: 1rem;
  line-height: 1.15; text-align: center; color: var(--brick-deep);
}
.aw-row__text { padding-top: .15rem; }
.aw-card__title {
  /* Bigger and bolder, as the client asked of the boxes with logos. */
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: var(--step-2); line-height: 1.12; letter-spacing: -.01em; color: var(--fg);
}
.aw-card__body { margin: .6rem 0 0; font-size: .96rem; line-height: 1.6; color: var(--fg-2); max-width: 46ch; }
.aw-card__link { display: inline-block; margin-top: 1rem; }

/* The local honors on the brick sheet. */
.aw-local .ch-card__title { margin: 0; font-size: var(--step-2); }

/* GuildQuality is the one affiliation that publishes a score, so the
   score is shown under its description. */
.aw-proof { margin: 1rem 0 0; font-size: .96rem; line-height: 1.5; color: var(--fg-2); }
.aw-proof b {
  display: block; margin-bottom: .2rem; font-family: var(--display); font-weight: 600;
  font-size: var(--step-3); line-height: 1; letter-spacing: -.03em; color: var(--fg);
}

/* One column once two would crowd; the plate steps down but stays beside. */
@media (max-width: 60rem) {
  .aw-ledger { grid-template-columns: 1fr; }
}
@media (max-width: 34rem) {
  .aw-row { grid-template-columns: 7rem minmax(0, 1fr); gap: 1.1rem; padding: 1.5rem 1.25rem; }
  .aw-plate { height: 5rem; padding: .4rem .5rem; }
}

/* --------------------------------------------------------------------------
   Rewards: the discounts set as figures on the brick sheet, then the terms
   as legal copy that still reads: headed, short paragraphs, a numbered
   list where the terms enumerate.
   -------------------------------------------------------------------------- */
.rw-glance__figure {
  margin: 0 0 .5rem; font-family: var(--display); font-weight: 600;
  font-size: var(--step-4); line-height: 1; letter-spacing: -.03em; color: var(--fg);
}
.rw-glance .ch-card__title { margin-bottom: .6rem; }
.rw-glance .ch-card__body { color: var(--fg-2); }
.rw-terms h3 {
  margin: 2.6rem 0 .9rem; font-family: var(--display); font-weight: 600;
  font-size: var(--step-2); line-height: 1.1; letter-spacing: -.01em; color: var(--fg);
}
.rw-terms h3:first-child { margin-top: 0; }
.rw-terms p { font-size: var(--step-0); line-height: 1.75; margin: 0 0 1.1em; }
.rw-terms__list {
  max-width: 54ch; margin: 0 0 1.1em; padding-left: 1.4em;
  list-style: lower-roman; color: var(--fg-2); line-height: 1.75;
}
.rw-terms__list li { padding-left: .3em; margin-bottom: .5em; }

/* --------------------------------------------------------------------------
   Team: portrait tiles, the gallery grid's proportions stood upright. The
   headshots are shot on white paper, and multiply lays them onto the
   tile's lit backdrop, so the set reads as one sitting rather than white
   cards on charcoal. isolation keeps the blend inside the tile.
   -------------------------------------------------------------------------- */
.team {
  list-style: none; margin: 0; padding: 0;
  /* Never fewer than three across: a tile's floor is 15rem or a third of
     the row, whichever is smaller, so the row never drops to a 2-up. */
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(15rem, calc((100% - 3.5rem) / 3)), 1fr));
  gap: 2.5rem 1.75rem;
}
.team__member { display: block; color: var(--fg); text-decoration: none; text-align: center; }
.headshot {
  position: relative; isolation: isolate; overflow: hidden;
  display: grid; place-items: center;
  width: 100%; aspect-ratio: 3 / 4; border-radius: 8px;
  /* A lit backdrop instead of flat studio paper: warm light behind the head
     falling away to a soft umber at the edges. The pool sits low and tall so
     the shoulders at the foot of the frame stay in the light. Multiply lays the grey paper
     onto it, so the photograph takes the falloff without a cut-out. */
  background:
    radial-gradient(ellipse 100% 95% at 50% 36%,
      #F8F0EB 0%, #E8DBD2 46%, #C3B0A6 80%, #94827A 100%);
}
.headshot img {
  width: 100%; height: 100%; object-fit: cover;
  mix-blend-mode: multiply;
  filter: contrast(1.06) saturate(.92) sepia(.06);
  transition: transform .8s var(--ease);
}
.headshot__initials {
  font-family: var(--display); font-weight: 600; font-size: 3.4rem;
  letter-spacing: -.02em; color: var(--brick);
}
.headshot--large .headshot__initials { font-size: 4.4rem; }
button.team__member { width: 100%; padding: 0; border: 0; background: none; font: inherit; cursor: pointer; }
.team__member--bio .headshot { transition: box-shadow .5s var(--ease); }
.team__member--bio:hover .headshot img, .team__member--bio:focus-visible .headshot img { transform: scale(1.03); }
.team__member--bio:hover .headshot, .team__member--bio:focus-visible .headshot { box-shadow: var(--shadow-lift); }
.team__member--bio:focus-visible { outline: 2px solid var(--bone); outline-offset: 6px; border-radius: 8px; }
.team__name {
  display: block; margin-top: 1rem; font-family: var(--display); font-weight: 600;
  font-size: var(--step-1); line-height: 1.15;
}
.team__role {
  display: block; margin-top: .3rem;
  font-family: var(--ui); font-size: var(--step--2); font-weight: 500;
  letter-spacing: .13em; text-transform: uppercase; color: var(--fg-3);
}
/* The bio: a quiet panel over the dimmed directory, the portrait on the
   left and the words on the right, set like a page of the site rather than
   a pop-up. It rises a little as it fades in. */
.bio {
  width: min(62rem, calc(100vw - 2rem)); max-width: none; max-height: calc(100vh - 3rem);
  padding: 0; border: 0; background: none; color: var(--fg); overflow: visible;
}
.bio::backdrop { background: rgba(16, 14, 14, .82); backdrop-filter: blur(3px); }
.bio[open] { animation: bio-in .45s var(--ease); }
.bio[open]::backdrop { animation: bio-fade .45s var(--ease); }
@keyframes bio-in { from { opacity: 0; transform: translateY(12px); } }
@keyframes bio-fade { from { opacity: 0; } }
/* A fixed frame: every bio opens at the same height, the portrait always a
   3:4 of that height, and a long bio scrolls inside its own column instead
   of stretching the photograph. */
.bio__panel {
  --bio-h: min(34rem, calc(100vh - 3rem));
  position: relative; display: grid; grid-template-columns: calc(var(--bio-h) * 3 / 4) minmax(0, 1fr);
  height: var(--bio-h); overflow: hidden;
  background: var(--char-2); border: 1px solid var(--rule); border-radius: 10px;
  box-shadow: var(--shadow-lift);
}
.bio__portrait { min-height: 0; }
.bio__portrait .headshot { height: 100%; aspect-ratio: auto; border-radius: 10px 0 0 10px; }
.bio__portrait .headshot__initials { font-size: 5rem; }
.bio__text {
  display: flex; flex-direction: column; justify-content: safe center;
  min-height: 0; overflow-y: auto; padding: clamp(2rem, 1.4rem + 2vw, 3.25rem);
  /* A long bio fades out at the foot of the frame rather than being cut. */
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 2.5rem), transparent);
          mask-image: linear-gradient(to bottom, #000 calc(100% - 2.5rem), transparent);
}
.bio__name {
  margin: 0; font-family: var(--display); font-weight: 600;
  font-size: var(--step-3); line-height: 1.05; letter-spacing: -.01em;
}
.bio__role {
  margin: .7rem 0 0; padding-bottom: 1.4rem; border-bottom: 1px solid var(--rule);
  font-family: var(--ui); font-size: var(--step--2); font-weight: 500;
  letter-spacing: .13em; text-transform: uppercase; color: var(--fg-3);
}
.bio__role:empty { display: none; }
.bio__body { margin-top: 1.4rem; color: var(--fg-2); font-size: var(--step-0); line-height: 1.65; }
.bio__body p { margin: 0 0 1em; }
.bio__body p:last-child { margin-bottom: 0; }
.bio__close {
  position: absolute; top: .6rem; right: .9rem; z-index: 1;
  background: none; border: 0; padding: .2rem .4rem; cursor: pointer;
  font-family: var(--display); font-size: 2rem; line-height: 1; color: var(--fg-3);
  transition: color .2s var(--ease);
}
.bio__close:hover, .bio__close:focus-visible { color: var(--fg); }
.bio__close:focus-visible { outline: 2px solid var(--bone); outline-offset: 2px; }
/* Tablets and phones: too narrow for the portrait beside the words, so a
   small 3:4 portrait (the same for everyone) sits beside the name and
   title, and the bio runs the full width beneath. The panel scrolls. */
@media (max-width: 56rem) {
  .bio { width: min(36rem, calc(100vw - 2rem)); }
  .bio__panel {
    height: auto; max-height: calc(100vh - 2rem); overflow-y: auto;
    grid-template-columns: 7.5rem minmax(0, 1fr); align-items: end; column-gap: 1.25rem;
    grid-template-areas: "pic name" "pic role" "body body";
    padding: 1.5rem;
  }
  .bio__text { display: contents; }
  .bio__portrait { grid-area: pic; }
  .bio__portrait .headshot { width: 7.5rem; height: 10rem; border-radius: 6px; }
  .bio__portrait .headshot__initials { font-size: 2.4rem; }
  .bio__name { grid-area: name; font-size: var(--step-2); padding-right: 1.5rem; }
  .bio__role { grid-area: role; align-self: start; padding-bottom: 0; border-bottom: 0; }
  .bio__body {
    grid-area: body; margin-top: 1.25rem; padding-top: 1.25rem;
    border-top: 1px solid var(--rule); font-size: var(--step--1);
  }
}
@media (prefers-reduced-motion: reduce) {
  .bio[open], .bio[open]::backdrop { animation: none; }
}
/* Phones: three to a row, with the name and initials stepped down to fit. */
@media (max-width: 40rem) {
  .team { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem .75rem; }
  .team__name { margin-top: .5rem; font-size: .95rem; }
  .team__role { font-size: .6rem; letter-spacing: .08em; }
  .team .headshot { border-radius: 6px; }
  .team .headshot__initials { font-size: 1.8rem; }
}

/* --------------------------------------------------------------------------
   Footer — ink, where the page ends
   -------------------------------------------------------------------------- */

.footer {
  position: relative;
  background:
    radial-gradient(64rem 38rem at 88% 0%, rgba(33, 30, 47, .55), transparent 62%),
    radial-gradient(50rem 30rem at 2% 100%, rgba(55, 23, 24, .5), transparent 60%),
    var(--night);
  padding-block: calc(var(--band) * .66) 1.75rem;
  font-size: .95rem;
}
.footer a { color: var(--fg-2); text-decoration: none; }
.footer a:hover { color: var(--bone); }
.footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) repeat(auto-fit, minmax(8rem, 1fr));
  gap: 2.75rem 2.5rem; margin-bottom: 3rem;
}
.footer h3 {
  font-family: var(--body);
  font-size: 1.05rem; font-weight: 800; letter-spacing: -0.01em;
  text-transform: none; color: var(--bone);
  margin-bottom: 1.1rem;
}
.footer__brand { display: inline-flex; margin-bottom: 1.25rem; }
.footer__brand img { display: block; height: 5.6rem; width: auto; }
.footer ul { list-style: none; margin: 0; padding: 0; }
.footer li { margin-bottom: .45rem; }
.footer__phone-row { margin-bottom: 1rem; }
.footer__phone {
  font-family: var(--body); font-size: 1.5rem; font-weight: 500; letter-spacing: -0.01em;
  color: var(--bone) !important; text-decoration: none;
}

/* Address, email, hours: an icon column and a text column, ruled from the
   phone number rather than boxed on their own. */
.footer__info {
  display: grid; gap: .65rem;
  font-size: .88rem; color: var(--fg-2);
}
.footer__info li {
  display: flex; align-items: baseline; gap: .7rem;
  margin-bottom: 0;
}
.footer__info i {
  flex: 0 0 1.1rem;
  font-size: .82rem; color: var(--fg-3);
  transform: translateY(.05em);
}
.footer__info a { color: var(--fg-2); }
.footer__info a:hover { color: var(--bone); }
.footer__info small { font-size: .85em; color: var(--fg-3); }
.footer__response { margin-top: .65rem; font-size: .82rem; color: var(--fg-3); }
.footer__guild {
  display: flex; align-items: flex-start; gap: .7rem;
  margin-top: 1.35rem; padding-top: 1.1rem;
  border-top: 1px solid var(--rule-2);
  font-family: var(--ui); font-size: .84rem; line-height: 1.5;
  color: var(--fg-2);
}
.footer__guild:hover { color: var(--bone); }
.footer__guild i { flex: 0 0 1.1rem; margin-top: .2rem; font-size: .9rem; color: var(--fg-3); }
.footer__guild strong {
  /* The UI face with lining figures: the display face's old-style figures
     made "4.8/5" read as "485". */
  font-family: var(--ui); font-size: .95rem; font-weight: 600;
  font-variant-numeric: lining-nums; letter-spacing: 0; color: var(--bone);
}
.footer__hours span { display: block; }
.footer__hours span + span { white-space: nowrap; }
.footer__guild small { display: block; margin-top: .2rem; color: var(--fg-3); }
/* `.footer ul` zeroes list margins and outranks `.social`, so the gap under
   the GuildQuality line is set here. */
.footer .social { margin-top: 1.5rem; }

.footer__legal {
  display: flex; flex-wrap: wrap; gap: .5rem 2rem; justify-content: space-between;
  padding-top: 1.5rem; border-top: 1px solid var(--rule-2);
  font-family: var(--ui); font-size: var(--step--2); color: var(--fg-3);
}
.social { display: flex; flex-wrap: wrap; gap: .6rem; list-style: none;
          margin: 1.3rem 0 0; padding: 0; }
.social a {
  display: flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem;
  border: 1px solid var(--rule-2); border-radius: 50%;
  font-size: 1rem; color: var(--fg-2);
  transition: border-color .2s var(--ease), color .2s var(--ease), background-color .2s var(--ease);
}
.social a:hover { color: var(--bone); border-color: var(--brick-lift); background: var(--brick-lift); }

/* --------------------------------------------------------------------------
   Contact corner widget — the persistent action, bottom right
   -------------------------------------------------------------------------- */

/* The button never moves: the panel is absolutely positioned off its own
   box, so opening it can't nudge the button that opened it. */
.text-fab-wrap {
  position: fixed; z-index: 80;
  right: clamp(1rem, 0.6rem + 1.2vw, 1.75rem);
  bottom: clamp(1rem, 0.6rem + 1.2vw, 1.75rem);
}

/* GuildQuality's sticky badge: a white card the height of the ReviewsUp
   Google badge (a 65 x 65 square ReviewsUp pins 20px from the bottom left,
   above everything at z-index 8000), 10px to its right. GuildQuality's seal
   names the source at a glance; the score and the survey count sit beside
   it in GuildQuality's navy. */
.gq-badge {
  position: fixed; z-index: 8000;
  left: calc(20px + 65px + 10px); bottom: 20px;
  height: 65px;
  display: flex; align-items: center; gap: 8px;
  padding: 0 12px 0 9px;
  background: #fff; color: #1f3d6e;
  border-left: 4px solid #1f3d6e;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .25);
  font-family: Arial, Helvetica, sans-serif; text-decoration: none; line-height: 1;
  transition: transform .18s var(--ease), box-shadow .18s var(--ease);
}
.gq-badge:hover { color: #1f3d6e; transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0, 0, 0, .3); }
.gq-badge__seal { width: 44px; height: 44px; flex: none; }
.gq-badge__body { display: flex; flex-direction: column; gap: 5px; }
.gq-badge__score { display: flex; align-items: center; gap: 6px; }
.gq-badge__num { font-size: 22px; font-weight: 700; letter-spacing: -.01em; }
.gq-badge__stars { position: relative; font-size: 10px; letter-spacing: 1px; color: rgba(255, 255, 255, .28); }
.gq-badge .gq-badge__stars { color: #d5dbe6; }
.gq-badge__fill { position: absolute; inset: 0 auto 0 0; overflow: hidden; white-space: nowrap; color: #f5b301; }
.gq-badge__src { font-size: 10px; font-weight: 700; white-space: nowrap; }
/* The ReviewsUp badge in Perez red: a face laid over ReviewsUp's own
   iframe (see partials/reviewsup_badge.html). site.js sets its box to the
   iframe's; it sits one layer above and lets clicks through. */
.ru-badge {
  position: fixed; z-index: 8001;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px;
  background: var(--brick); color: #fff;
  font-family: Arial, Helvetica, sans-serif; line-height: 1;
  pointer-events: none;
}
.ru-badge[hidden] { display: none; }
.ru-badge__num { font-size: 22px; font-weight: 700; letter-spacing: -.01em; }
body:has(.nav[data-open='true']) :is(.gq-badge, .ru-badge) { opacity: 0; pointer-events: none; }

/* Solid brick rather than the glass used on the hero: this one has to hold
   its colour over whatever happens to be scrolling beneath it — footage,
   plaster, the brick CTA band — so it can't borrow a backdrop. Sits under the
   masthead (100) and under the mobile drawer (90) so neither is ever blocked. */
.text-fab {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  gap: .5rem;
  padding: calc(.8rem + var(--btn-nudge)) 1.25rem calc(.8rem - var(--btn-nudge));
  background: var(--brick);
  color: var(--bone);
  border-radius: var(--radius-btn);
  box-shadow: 0 10px 30px rgba(16, 14, 14, .35);
  font-family: var(--body); font-size: .95rem; font-weight: 600;
  letter-spacing: -0.006em;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .25s var(--ease), transform .25s var(--ease),
              box-shadow .25s var(--ease), opacity .25s var(--ease);
}
.text-fab:hover {
  background: var(--brick-lift);
  color: var(--bone);
  transform: translateY(-2px);
  box-shadow: 0 14px 34px rgba(16, 14, 14, .42);
}
.text-fab:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }
.text-fab i { font-size: 1.05em; }

/* The drawer slides over the whole right edge; a button floating on top of it
   would sit in the middle of the menu. */
body:has(.nav[data-open='true']) .text-fab-wrap {
  opacity: 0; pointer-events: none; transform: translateY(8px);
}

/* The panel — a printed card set on the one light band's tokens (.on-light),
   so it always reads the same regardless of what's scrolling behind it.
   Positioned off the button's own box so the button's size and position
   never change when it opens. */
.text-fab-panel {
  position: absolute; right: 0; bottom: calc(100% + .85rem);
  width: min(25rem, calc(100vw - 2rem));
  /* Left room for the fixed masthead above (--head-h, set by site.js) and
     for the button + its own offset below, so the panel never grows up
     behind the nav bar — it scrolls internally instead. */
  max-height: calc(100vh - var(--head-h, 4.5rem) - 8rem);
  overflow-y: auto;
  background: var(--bone);
  border-radius: var(--radius-btn);
  box-shadow: 0 24px 60px rgba(16, 14, 14, .38);
  padding: 1.1rem 1.3rem;
  opacity: 0; visibility: hidden; transform: translateY(10px) scale(.98);
  transform-origin: bottom right;
  transition: opacity .22s var(--ease), transform .22s var(--ease), visibility .22s;
}
.text-fab-wrap[data-open='true'] .text-fab-panel {
  opacity: 1; visibility: visible; transform: none;
}
.text-fab-panel__close {
  position: absolute; top: .7rem; right: .7rem;
  width: 1.7rem; height: 1.7rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: 50%;
  color: var(--fg-3); cursor: pointer;
  transition: background-color .18s var(--ease), color .18s var(--ease);
}
.text-fab-panel__close:hover { background: var(--surface); color: var(--fg); }
.text-fab-panel__intro h3 {
  margin: 0 1.4rem .2rem 0;
  font-family: var(--display); font-size: var(--step-1);
  letter-spacing: var(--tight); color: var(--fg);
}
.text-fab-panel__intro p { margin: 0 0 .7rem; font-size: .85rem; color: var(--fg-2); }

.text-fab-form { display: flex; flex-direction: column; gap: .55rem; }
.text-fab-form[hidden] { display: none; }
.text-fab-form__field { display: flex; flex-direction: column; gap: .2rem; }
.text-fab-form__field span {
  font-family: var(--ui); font-size: var(--step--2); font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--fg-3);
}
.text-fab-form__field .field-input { padding: .55rem .75rem; font-size: .92rem; }
.text-fab-form__hp { position: absolute; left: -9999px; width: 1px; height: 1px; }
.text-fab-form__services { border: 0; margin: 0; padding: .1rem 0 0; }
.text-fab-form__services legend {
  padding: 0 0 .35rem; font-family: var(--ui); font-size: var(--step--2);
  font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--fg-3);
}
.text-fab-form__checks { display: flex; flex-wrap: wrap; gap: .3rem; }
.text-fab-form__check {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .28rem .55rem; border: 1px solid var(--rule-2); border-radius: 999px;
  font-size: var(--step--2); color: var(--fg-2); cursor: pointer;
  transition: background-color .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
.text-fab-form__check input { accent-color: var(--brick); width: .85rem; height: .85rem; }
.text-fab-form__check:has(input:checked) {
  background: var(--brick-soft); border-color: var(--brick); color: var(--fg);
}
.text-fab-form__submit {
  width: 100%; margin-top: .2rem;
  padding: .65rem 1.2rem; font-size: .92rem;
}
.text-fab-form__error { margin: 0; font-size: .85rem; color: var(--brick); }

.text-fab-panel__success { display: flex; align-items: flex-start; gap: .7rem; padding: .3rem 1.6rem .3rem 0; }
.text-fab-panel__success[hidden] { display: none; }
.text-fab-panel__success i { font-size: 1.3rem; color: var(--brick); margin-top: .1rem; }
.text-fab-panel__success p { margin: 0; color: var(--fg); font-size: .95rem; }

/* --------------------------------------------------------------------------
   Reveals — a short lift, nothing more
   -------------------------------------------------------------------------- */

[data-reveal] {
  opacity: 0; transform: translateY(28px);
  transition: opacity .85s var(--ease), transform .85s var(--ease);
}
[data-reveal].is-visible { opacity: 1; transform: none; }
[data-reveal][data-reveal-delay='1'] { transition-delay: .09s; }
[data-reveal][data-reveal-delay='2'] { transition-delay: .18s; }
[data-reveal][data-reveal-delay='3'] { transition-delay: .27s; }

/* Staggered reveals: the container stays put and its children arrive one
   after another, left to right, 90ms apart. site.js numbers the children. */
[data-reveal][data-reveal-stagger] { opacity: 1; transform: none; transition: none; }
[data-reveal-stagger]:not(.is-visible) > * { opacity: 0; }
/* An animation rather than a transition, and no forwards fill, so once a
   child has arrived its own hover transitions and transforms are untouched. */
[data-reveal-stagger].is-visible > * {
  animation: reveal-rise .85s var(--ease) backwards;
  animation-delay: calc(var(--i, 0) * 90ms);
}
@keyframes reveal-rise {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: none; }
}

.messages { list-style: none; margin: 0; padding: 0; }
.messages li {
  padding: .8rem 1.05rem; margin-bottom: .5rem;
  background: var(--brick-soft); border-left: 2px solid var(--brick);
  font-size: .95rem;
}

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 68rem) { .places { columns: 3; } }

@media (max-width: 60rem) {
  /* auto-fit keeps five footer columns alive well past the point they fit;
     below this the grid is set explicitly instead. */
  .footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cta__inner { grid-template-columns: 1fr; }
  .split { grid-template-columns: 1fr; gap: 2.25rem; }
  .two-up { grid-template-columns: 1fr; }
  .promise { grid-template-columns: 1fr; }
  .stage { grid-template-columns: 2.2rem minmax(0, 1fr); }
  .stage p, .stage__seal { grid-column: 2 / -1; }
  .stage p { margin-top: .35rem; }
  .ba-set { grid-template-columns: 1fr; }
  .ba { aspect-ratio: 3 / 2; }
  .places { columns: 2; }
  .counties { grid-template-columns: repeat(2, minmax(0, 1fr)); border-top: 0; }
  .county, .county + .county { padding: 1.4rem 1.4rem 1.4rem 0; border-left: 0; border-top: 1px solid var(--rule); }
  .county:nth-child(2n) { padding-left: 1.4rem; border-left: 1px solid var(--rule-2); }
}

/* The nav collapses to the drawer while the big logo + full menu cannot share
   one row. */
@media (max-width: 72.5rem) {
  .nav-toggle { display: inline-flex; }
  .nav {
    display: flex;
    position: fixed; inset: 0 0 0 auto;
    width: min(88vw, 22rem);
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 5.5rem 1.5rem 2rem;
    background: var(--bone);
    border-left: 1px solid var(--rule);
    box-shadow: -16px 0 50px rgba(0, 0, 0, .5);
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform .3s var(--ease);
    z-index: 90;
  }
  .nav[data-open='true'] { transform: none; }
  .nav__links {
    position: static; margin: 0; width: auto; height: auto;
    display: flex; flex-direction: column; align-items: stretch; gap: 0;
  }
  /* The drawer is its own plaster panel, so its links stay ink even while the
     bar above is still floating over the hero — and so does the close button,
     which sits inside the panel once the drawer is open. */
  .has-hero .masthead .nav-link { color: var(--fg-2); text-shadow: none; }
  .has-hero .masthead .nav-link--andersen img { content: normal; }
  .has-hero .masthead .nav-link:hover,
  .has-hero .masthead .nav-item[data-open='true'] .nav-link { color: var(--brick); }
  .has-hero .masthead .nav-toggle[aria-expanded='true'] {
    color: var(--fg); border-color: var(--rule);
  }
  .nav-item { border-bottom: 1px solid var(--rule-2); }
  .nav-link { width: 100%; justify-content: space-between; padding: .85rem 0; white-space: normal; }
  .nav__cta {
    display: block; position: static; transform: none;
    margin: 1.25rem 0 0; border-bottom: 0;
  }
  /* In the drawer the button sits on bone, never over the video, so the
     glass tint would read pink: solid brick at every scroll position. */
  .nav__cta .btn { width: 100%;
    padding: calc(.85rem + var(--btn-nudge)) 1.2rem calc(.85rem - var(--btn-nudge));
    background: var(--brick); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .nav__cta .btn:hover { background: var(--brick-deep); }
  .submenu {
    position: static; opacity: 1; visibility: visible; transform: none;
    display: none; border: 0; box-shadow: none; min-width: 0;
    padding: 0 0 .7rem; background: transparent;
  }
  .nav-item[data-open='true'] .submenu { display: block; }
  .submenu a { padding: .38rem 0 .38rem .8rem; }
  .nav-item--mega { position: relative; }
  .nav-item--mega .nav-link::after { display: none; }
  .mega {
    position: static; opacity: 1; visibility: visible; transform: none;
    display: none; border: 0; box-shadow: none; background: transparent;
    /* The desktop rule pads .mega itself (not .mega__inner) out to the
       shell's gutter, since there it's a full-viewport strip with centred
       content. In the drawer .mega is just another block in the column
       flow, so that leftover gutter padding was shoving its content in
       from the left, out of step with the rest of the drawer's links. */
    width: auto; max-width: none; padding-inline: 0;
  }
  /* Same selector (and so the same specificity) as the desktop open-state
     rule that sets transform: translateX(-50%) for centring the full-width
     panel: a plain .mega { transform: none } here can't beat that rule once
     the drawer item is actually open, so the mega content was sliding half
     its own width to the left, off the edge of the drawer, revealing the
     hero photo behind it. This has to un-set the same transform, not just
     the base .mega rule above. */
  .nav-item[data-open='true'] .mega { display: block; transform: none; }
  .mega__inner { display: block; width: auto; padding: 0 0 .7rem; max-width: none; }
  .mega__intro h3, .mega__intro p, .mega__figure { display: none; }
  .mega__all { display: block; padding: .38rem 0 .38rem .8rem; font-size: 1rem;
    background: none; border-radius: 0; color: var(--brick); }
  .mega__all:hover { background: none; color: var(--brick-deep); }
  .mega__links { display: block; height: auto; }
  .mega__links a { padding: .38rem 0 .38rem .8rem; background: none; border-radius: 0; }
  .mega__links a:hover { padding-left: 1.05rem; background: none; }
  .mega__links a i { width: 1.4rem; height: 1.4rem; background: none; }
  .mega__links a:hover i { background: none; color: var(--brick); }
}

@media (max-width: 52rem) {
  .counties { grid-template-columns: minmax(0, 1fr); }
  .county:nth-child(2n) { padding-left: 0; border-left: 0; }
  .inspire { grid-template-columns: minmax(0, 1fr); }
  .inspire__item { padding: 1.6rem 0 0; }
  .inspire__item + .inspire__item { padding-left: 0; border-left: 0; border-top: 1px solid var(--rule-2); }
  /* One line on a phone: the hours go, the "free consultation" label goes,
     leaving the phone number and the Text Us button to centre together. */
  /* A smaller pill on a phone, still labelled: a round icon in this corner
     reads as a chatbot. The panel never shows here; a phone keeps the plain
     sms: link. */
  .text-fab { padding: .7rem 1rem .6rem; font-size: .9rem; }
  .text-fab__desktop { display: none; }
  .text-fab__mobile { display: contents; }
  .text-fab-panel { display: none !important; }
  .topbar__phone-number { display: none; }
  .topbar__phone-call { display: inline; }
  .topbar__text--desktop { display: none; }
  .topbar__text--mobile { display: inline-flex; }
  .contact-text__desktop { display: none; }
  .contact-text__mobile { display: inline; }
  .topbar__hours { display: none; }
  .topbar__consult-label { display: none; }
  .topbar__inner { justify-content: center; text-align: center; }
  .footer__grid { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
  /* The figures drop under the action rather than squeezing beside it. */
  .hero__foot { flex-direction: column; align-items: flex-start; }
  .hero__proof { text-align: left; }
  /* 55% is sized for a wide splash with room to spare; on a phone it leaves
     the lede just a few words wide and stacks it needlessly tall. Let it run
     the column's width instead, capped for reading length rather than viewport share. */
  .hero__lede { max-width: 34ch; }
  .wordmark img { height: 3.4rem; }
  .index__row { grid-template-columns: minmax(0, 1fr) auto; }
  .index__note { grid-column: 1 / -1; }
  .places { columns: 1; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important; transition-duration: .001ms !important;
  }
  [data-reveal], [data-reveal-stagger] > * { opacity: 1; transform: none; transition: none; animation: none; }
}

@media print {
  .masthead, .topbar, .nav, .cta, .footer, .text-fab-wrap { display: none; }
  body { background: #fff; color: #1E1416; }
}

/* --------------------------------------------------------------------------
   Blog

   The index is a set of spreads, one per topic: the lead article as a
   plate with its card hanging off the foot, the rest as a ruled reading
   list beside it, the sides swapping topic to topic. An article is one
   reading column with its contents pinned in the margin, numbered the way
   a drawing set numbers its sheets.
   -------------------------------------------------------------------------- */

.bl-meta {
  display: block; margin-top: .9rem;
  font-family: var(--ui); font-size: var(--step--2);
  letter-spacing: .1em; text-transform: uppercase; color: var(--fg-3);
}

/* The hero card's way into the newest article. */
.bl-feature {
  display: grid; grid-template-columns: 1fr auto; align-items: end; gap: .3rem 1.4rem;
  padding-top: 1.4rem; border-top: 1px solid var(--rule);
  text-decoration: none; color: var(--fg);
}
.bl-feature__kicker { grid-column: 1 / -1; font-family: var(--display); font-style: italic; font-size: 1.05rem; color: var(--fg-3); }
.bl-feature__title { font-family: var(--display); font-weight: 600; font-size: var(--step-1); line-height: 1.2; letter-spacing: -.01em; }
.bl-feature__go {
  display: grid; place-items: center; width: 2.9rem; height: 2.9rem;
  background: var(--btn-bg); color: var(--btn-fg);
  transition: transform .2s var(--ease), background-color .2s var(--ease);
}
.bl-feature:hover .bl-feature__go { transform: translateX(3px); background: var(--brick); }

/* Topics: a ruled strip under the hero; jumps on the index, links on a
   topic page. */
.bl-topics { border-block: 1px solid var(--rule-2); background: var(--char); }
.bl-topics__inner {
  display: flex; flex-wrap: wrap; gap: 0;
  padding-block: 0;
}
.bl-topics__link {
  display: inline-flex; align-items: baseline; gap: .55rem;
  padding: 1.15rem 1rem 1.05rem 0; margin-right: 1rem;
  font-size: .9rem; white-space: nowrap; color: var(--fg-2); text-decoration: none;
  border-right: 1px solid var(--rule-2);
  transition: color .2s var(--ease);
}
.bl-topics__link:last-child { border-right: 0; margin-right: 0; }
.bl-topics__link:hover { color: var(--fg); }
.bl-topics__link--all { color: var(--fg); }
.bl-topics__n { font-family: var(--display); font-style: italic; font-size: .95rem; color: var(--fg-3); }
.bl-topics--foot { margin-top: 0; }

/* A topic's spread. */
.bl-topic { padding-block: var(--sv-space) 0; scroll-margin-top: calc(var(--head-h, 6rem) + 1rem); }
.bl-topic:last-child { padding-bottom: var(--sv-space); }
.bl-topic__head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem 2rem; flex-wrap: wrap;
  margin-bottom: clamp(2rem, 1.5rem + 2vw, 3.25rem);
}
.bl-topic__title { font-size: var(--step-4); line-height: 1; margin: 0; }

.bl-spread {
  display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: 2.5rem clamp(2.5rem, 1.5rem + 4vw, 6rem); align-items: start;
}
.bl-topic--flip .bl-spread { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
.bl-topic--flip .bl-lead { order: 2; }
.bl-topic--flip .bl-lead .ch-work__card { left: auto; right: 1.5rem; }
.bl-spread--solo { grid-template-columns: minmax(0, 8fr) minmax(0, 4fr); }

.bl-lead { padding-bottom: 5rem; }
.bl-lead .ch-work__photo img { aspect-ratio: 3 / 2; }
.bl-lead__card { max-width: min(30rem, calc(100% - 3rem)); min-width: 0; padding: 1.6rem 1.9rem 1.5rem; }
.bl-lead__card .ch-card__title { font-size: var(--step-2); }
.bl-lead__sum { display: block; font-size: .95rem; line-height: 1.6; color: var(--fg-2); }

.bl-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.bl-list li { border-bottom: 1px solid var(--rule); }
.bl-list__item {
  display: block; padding: 1.6rem 0 1.5rem; text-decoration: none;
}
.bl-list__title {
  display: block;
  font-family: var(--display); font-weight: 600;
  font-size: var(--step-2); line-height: 1.12; letter-spacing: -.02em;
  color: var(--fg);
  background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
  transition: background-size .35s var(--ease);
  width: fit-content;
}
.bl-list__item:hover .bl-list__title { background-size: 100% 1px; }
.bl-list__sum {
  display: block; margin-top: .6rem; max-width: 50ch;
  font-size: .95rem; line-height: 1.6; color: var(--fg-2);
}
.bl-list .bl-meta { margin-top: .75rem; }

/* Topic pages and "Keep reading": the gallery's plates, card at the foot. */
.bl-plates { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: clamp(3rem, 2rem + 2vw, 4.5rem); }
.bl-plates .ch-work__card { right: 1.5rem; min-width: 0; }
.bl-plates .ch-work__card { padding: 1.2rem 1.4rem 1.1rem; }
.bl-plates .ch-card__title { font-size: var(--step-1); line-height: 1.2; margin: 0; }
.bl-plates .bl-meta { margin-top: .6rem; }

/* An article. */
.bl-hero__title { font-size: var(--step-4); line-height: 1; letter-spacing: -.02em; }
@media (min-width: 60.001rem) {
  .bl-hero .ch-hero__card { width: min(36rem, 50%); }
}
.bl-byline {
  display: flex; flex-wrap: wrap; gap: .4rem 1.4rem; margin: 1.6rem 0 0;
  font-family: var(--ui); font-size: var(--step--2);
  letter-spacing: .1em; text-transform: uppercase; color: var(--fg-3);
}
.bl-byline span + span::before { content: ''; display: inline-block; width: 1.4rem; height: 1px; margin-right: 1.4rem; vertical-align: middle; background: var(--rule); }

.bl-body { padding-block: clamp(3rem, 2rem + 3vw, 5rem) var(--sv-space); }
.bl-body__grid {
  display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  gap: 2.5rem clamp(3rem, 1.5rem + 5vw, 8rem); align-items: start;
}
.bl-body__grid > .bl-prose:only-child { grid-column: 2; }

.bl-aside__label { margin: 0 0 1rem; font-family: var(--display); font-style: italic; font-size: 1.1rem; color: var(--fg-3); }
.bl-toc { list-style: none; margin: 0 0 2rem; padding: 0; border-top: 1px solid var(--rule); counter-reset: none; }
.bl-toc li { border-bottom: 1px solid var(--rule); }
.bl-toc a {
  display: grid; grid-template-columns: 2.2rem 1fr; gap: .5rem;
  padding: .85rem 0; font-size: .95rem; line-height: 1.45;
  color: var(--fg-2); text-decoration: none; transition: color .2s var(--ease);
}
.bl-toc a:hover { color: var(--fg); }
.bl-toc__n { font-family: var(--display); font-style: italic; color: var(--fg-3); }

.bl-prose { max-width: 40rem; counter-reset: bl-h; }
.bl-prose p {
  margin: 0 0 1.25em;
  font-size: var(--step-1); line-height: 1.75; color: var(--fg-2);
}
/* The opening paragraph is the answer: set larger, in full bone, with an
   initial. */
.bl-prose > p:first-child {
  font-size: clamp(1.25rem, 1.1rem + .5vw, 1.5rem); line-height: 1.55; letter-spacing: -.01em; color: var(--fg);
}
.bl-prose > p:first-child::first-letter {
  float: left;
  font-family: var(--display); font-weight: 600;
  font-size: 3.6em; line-height: .8;
  padding: .06em .1em 0 0;
  color: var(--fg);
}
.bl-prose h2 {
  counter-increment: bl-h;
  position: relative;
  font-size: var(--step-3); line-height: 1.05; letter-spacing: -.02em;
  margin: 2.2em 0 .7em; padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
  scroll-margin-top: calc(var(--head-h, 6rem) + 1.5rem);
}
.bl-prose h2::before {
  content: counter(bl-h, decimal-leading-zero);
  display: block; margin-bottom: .7rem;
  font-family: var(--display); font-style: italic; font-weight: 400;
  font-size: 1.05rem; letter-spacing: 0; color: var(--fg-3);
}

.bl-next { margin-top: clamp(3rem, 2rem + 3vw, 4.5rem); }
.bl-next ul { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.bl-next li { border-bottom: 1px solid var(--rule); }
.bl-next a {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: 1.15rem 0; text-decoration: none;
  font-family: var(--display); font-weight: 600; font-size: var(--step-2);
  letter-spacing: -.015em; color: var(--fg);
}
.bl-next a i { font-size: .9rem; color: var(--fg-3); transition: transform .2s var(--ease), color .2s var(--ease); }
.bl-next a:hover i { transform: translateX(4px); color: var(--fg); }

.bl-related { padding-top: 0; }

@media (max-width: 60rem) {
  .bl-spread, .bl-topic--flip .bl-spread, .bl-spread--solo { grid-template-columns: 1fr; }
  .bl-topic--flip .bl-lead { order: 0; }
  .bl-topic--flip .bl-lead .ch-work__card { left: 1rem; right: auto; }
  .bl-lead .ch-work__card { left: 1rem; }
  .bl-body__grid { grid-template-columns: 1fr; }
  .bl-body__grid > .bl-prose:only-child { grid-column: auto; }
  .bl-aside { order: 0; }
  .bl-aside__cta { display: none; }
  .bl-plates { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 40rem) {
  .bl-topics__inner { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .bl-topics__link { flex: 0 0 auto; }
  .bl-plates { grid-template-columns: 1fr; }
  .bl-lead { padding-bottom: 0; }
  .bl-lead .ch-work__card, .bl-topic--flip .bl-lead .ch-work__card {
    position: relative; left: auto; right: auto; margin: -2.5rem 1rem 0; max-width: none;
  }
}

/* Bring Your Inspiration: the write-up as plain titles and paragraphs in
   one reading column. */
.bi { max-width: calc(46rem + (var(--gutter) * 2)); }
.bi h2 { margin: 3.2rem 0 1rem; font-size: var(--step-3); line-height: 1.08; }
.bi h2:first-child { margin-top: 0; }
.bi p, .bi li { font-size: var(--step-1); line-height: 1.7; color: var(--fg-2); }
.bi p { margin: 0 0 1em; }
.bi ul { margin: 0 0 1em; padding-left: 1.2rem; }
.bi li { margin-bottom: .35em; }
.bi .bi__action { margin-top: 2.4rem; }
/* Upload is not wired up yet: the button stays in the brand red but does
   nothing, and the cursor says so. */
.bi__upload, .bi__upload:hover { background: var(--btn-bg); color: var(--btn-fg); cursor: not-allowed; }
/* Upload is not wired up yet: the button is the brand red but disabled,
   with no action. */
.btn.bi__upload, .btn.bi__upload:hover, .btn.bi__upload:disabled {
  background: var(--brick-lift); border-color: var(--brick-lift); color: var(--bone);
  opacity: 1; cursor: not-allowed; transform: none;
}

/* --------------------------------------------------------------------------
   Virtual consultation booking (templates/bookings/_widget.html)
   A white two-panel card like a scheduling app, set on the dark pages:
   who and how long on the left, the calendar and times on the right.
   -------------------------------------------------------------------------- */
.bk {
  --bk-ink: #1E1A1B; --bk-ink-2: #4A4446; --bk-muted: #6E6769;
  --bk-rule: #E6E2DF; --bk-tint: #F7ECEE; --bk-brick: #8A182A; --bk-brick-hover: #721423;
  display: grid; grid-template-columns: minmax(16rem, 21rem) 1fr;
  background: #fff; color: var(--bk-ink); border-radius: 14px; overflow: hidden;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .2), 0 20px 50px rgba(0, 0, 0, .35);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  font-size: .95rem; line-height: 1.5; text-align: left;
}
.bk *, .bk *::before, .bk *::after { box-sizing: border-box; }
.bk [hidden] { display: none !important; }
.bk__side { padding: 1.75rem 1.5rem; border-right: 1px solid var(--bk-rule); }
.bk__eyebrow { margin: 0 0 .35rem; font-size: .82rem; font-weight: 600; color: var(--bk-muted); }
.bk__title { margin: 0 0 1rem; font-family: inherit; font-size: 1.45rem; font-weight: 700; letter-spacing: -.01em; color: var(--bk-ink); line-height: 1.2; }
.bk__facts { list-style: none; margin: 0 0 1rem; padding: 0; color: var(--bk-ink-2); font-weight: 500; }
.bk__facts li { display: flex; align-items: center; gap: .6rem; margin-bottom: .45rem; }
.bk__facts i { width: 1rem; text-align: center; color: var(--bk-muted); }
.bk__intro { margin: 0 0 1.25rem; color: var(--bk-ink-2); font-size: .9rem; }
.bk__who { border: 0; margin: 0; padding: 0; }
.bk__who legend { font-size: .78rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--bk-muted); margin-bottom: .5rem; }
.bk__person { display: flex; align-items: center; gap: .7rem; padding: .55rem .65rem; margin-bottom: .35rem;
  border: 1px solid var(--bk-rule); border-radius: 10px; cursor: pointer; transition: border-color .15s, background .15s; }
.bk__person:hover { border-color: #C9BFBB; }
.bk__person input { position: absolute; opacity: 0; pointer-events: none; }
.bk__person:has(input:checked) { border-color: var(--bk-brick); background: var(--bk-tint); box-shadow: inset 0 0 0 1px var(--bk-brick); }
.bk__person:has(input:focus-visible) { outline: 2px solid var(--bk-brick); outline-offset: 2px; }
.bk__person b { display: block; font-size: .9rem; color: var(--bk-ink); }
.bk__person small { display: block; font-size: .8rem; color: var(--bk-muted); line-height: 1.3; }
.bk__avatar { flex: none; width: 2.4rem; height: 2.4rem; border-radius: 50%; object-fit: cover; object-position: 50% 20%;
  display: grid; place-items: center; background: #EFE9E6; color: var(--bk-ink-2); font-size: .78rem; font-weight: 700; }
.bk__avatar--any { background: var(--bk-tint); color: var(--bk-brick); }
.bk__picked { display: flex; gap: .6rem; align-items: flex-start; margin-top: 1rem; padding: .75rem .85rem;
  border-radius: 10px; background: var(--bk-tint); color: var(--bk-brick); font-weight: 600; font-size: .9rem; }
.bk__picked i { margin-top: .2rem; }

.bk__main { padding: 1.75rem; min-height: 26rem; }
.bk__h { margin: 0 0 1.1rem; font-family: inherit; font-size: 1.15rem; font-weight: 700; color: var(--bk-ink); }
.bk__picker { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
.bk.has-times .bk__picker { grid-template-columns: minmax(0, 1fr) 13rem; }
.bk__month { display: flex; align-items: center; justify-content: center; gap: 1rem; margin-bottom: .75rem; font-weight: 600; }
.bk__month span { min-width: 9rem; text-align: center; }
.bk__nav { width: 2.2rem; height: 2.2rem; border-radius: 50%; border: 0; background: var(--bk-tint); color: var(--bk-brick); cursor: pointer; }
.bk__nav:disabled { background: transparent; color: #C9BFBB; cursor: default; }
.bk__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: .3rem; justify-items: center; }
.bk__grid--head { margin-bottom: .35rem; font-size: .72rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--bk-muted); }
.bk__grid button { width: 2.6rem; height: 2.6rem; border-radius: 50%; border: 0; background: none; font: inherit; font-weight: 500;
  color: #B4ABA8; cursor: default; position: relative; }
.bk__grid button.is-open { background: var(--bk-tint); color: var(--bk-brick); font-weight: 700; cursor: pointer; }
.bk__grid button.is-open:hover { background: #F0DADF; }
.bk__grid button.is-picked { background: var(--bk-brick); color: #fff; }
.bk__grid button.is-today::after { content: ''; position: absolute; left: 50%; bottom: .3rem; width: .25rem; height: .25rem;
  margin-left: -.125rem; border-radius: 50%; background: currentColor; }
.bk__grid button:focus-visible { outline: 2px solid var(--bk-brick); outline-offset: 2px; }
.bk__grid.is-loading { opacity: .5; }
.bk__note { margin: .75rem 0 0; min-height: 1.2em; text-align: center; font-size: .86rem; color: var(--bk-muted); }
.bk__times { border-left: 1px solid var(--bk-rule); padding-left: 1.25rem; }
.bk__day { margin: .35rem 0 .75rem; font-weight: 600; font-size: .92rem; }
.bk__slots { display: grid; gap: .45rem; max-height: 21rem; overflow-y: auto; padding-right: .2rem; }
.bk__slot { display: flex; gap: .4rem; }
.bk__slot button { flex: 1; padding: .6rem .5rem; white-space: nowrap; border-radius: 8px; font: inherit; font-weight: 700; cursor: pointer;
  border: 1px solid #D9B4BA; background: #fff; color: var(--bk-brick); transition: all .12s; }
.bk__slot button:hover { border-color: var(--bk-brick); box-shadow: inset 0 0 0 1px var(--bk-brick); }
.bk__slot.is-picked > button:first-child { flex: 0 0 48%; background: #6E6769; border-color: #6E6769; color: #fff; }
.bk__slot .bk__next { flex: 1; background: var(--bk-brick); border-color: var(--bk-brick); color: #fff; }
.bk__slot .bk__next:hover { background: var(--bk-brick-hover); }

.bk__back { border: 0; background: none; padding: 0; margin: 0 0 .9rem; font: inherit; font-weight: 600; color: var(--bk-brick); cursor: pointer; }
.bk__form { display: grid; gap: .85rem; max-width: 36rem; }
.bk__row { display: grid; grid-template-columns: 1fr 1fr; gap: .85rem; }
.bk__form label { display: grid; gap: .3rem; font-size: .86rem; font-weight: 600; color: var(--bk-ink); }
.bk__form label em { font-style: normal; color: var(--bk-brick); }
.bk__form input, .bk__form select, .bk__form textarea { width: 100%; padding: .6rem .7rem; border: 1px solid #D6D0CC; border-radius: 8px;
  font: inherit; font-weight: 400; color: var(--bk-ink); background: #fff; }
.bk__form input:focus, .bk__form select:focus, .bk__form textarea:focus { outline: none; border-color: var(--bk-brick); box-shadow: 0 0 0 3px rgba(138, 24, 42, .12); }
.bk__hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.bk__submit { justify-self: start; padding: .75rem 1.4rem; border: 0; border-radius: 999px; font: inherit; font-weight: 700;
  background: var(--bk-brick); color: #fff; cursor: pointer; }
.bk__submit:hover { background: var(--bk-brick-hover); }
.bk__submit.is-busy { opacity: .6; cursor: progress; }
.bk__confirm { font-size: 1rem; color: var(--bk-ink-2); }
.bk__error { padding: .65rem .8rem; border-radius: 8px; background: #FCEBEA; color: #9B1C14; font-size: .88rem; }
.bk__empty { display: grid; place-items: center; text-align: center; height: 100%; min-height: 20rem; color: var(--bk-ink-2); }
.bk__empty i { font-size: 2rem; color: #C9BFBB; margin-bottom: .75rem; }
.bk__empty a { color: var(--bk-brick); font-weight: 600; }

@media (max-width: 52rem) {
  .bk { grid-template-columns: 1fr; }
  .bk__side { border-right: 0; border-bottom: 1px solid var(--bk-rule); padding: 1.25rem; }
  .bk__main { padding: 1.25rem; min-height: 0; }
  .bk.has-times .bk__picker { grid-template-columns: 1fr; }
  .bk__times { border-left: 0; padding-left: 0; border-top: 1px solid var(--bk-rule); padding-top: 1rem; }
  .bk__slots { max-height: none; grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); }
  .bk__row { grid-template-columns: 1fr; }
  .bk__grid button { width: 2.4rem; height: 2.4rem; }
}

/* The booking page and the contact page section around the widget. */
.booking-band { padding-top: 0; }
/* No hairline seam over the booking section on the contact page. */
.band + .band.booking-band::before { content: none; }
.booking-intro { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1rem 2rem; align-items: end; margin-bottom: 1.75rem; }
.booking-intro h2 { margin: 0; }
.booking-intro p { margin: .5rem 0 0; color: var(--fg-2); max-width: 46ch; }
.booking-done { max-width: 40rem; margin: 0 auto; }
.booking-done .bk { grid-template-columns: 1fr; }
.bk__done { padding: 2rem; }
.bk__done-icon { width: 3.2rem; height: 3.2rem; border-radius: 50%; display: grid; place-items: center; margin-bottom: 1rem;
  background: #EAF5EC; color: #1E6B34; font-size: 1.3rem; }
.bk__done-icon--off { background: #F1EFED; color: #6E6769; }
.bk__done dl { display: grid; grid-template-columns: auto 1fr; gap: .45rem 1.25rem; margin: 1.25rem 0; }
.bk__done dt { color: var(--bk-muted); font-weight: 500; }
.bk__done dd { margin: 0; font-weight: 600; }
.bk__done dd a { color: var(--bk-brick); word-break: break-all; }
.bk__actions { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.25rem; }
.bk__btn { display: inline-flex; align-items: center; gap: .45rem; padding: .6rem 1.1rem; border-radius: 999px; font-weight: 700; font-size: .9rem;
  text-decoration: none; border: 1px solid #D6D0CC; color: var(--bk-ink); background: #fff; cursor: pointer; font-family: inherit; }
.bk__btn:hover { border-color: var(--bk-brick); color: var(--bk-brick); }
.bk__btn--primary { background: var(--bk-brick); border-color: var(--bk-brick); color: #fff; }
.bk__btn--primary:hover { background: var(--bk-brick-hover); color: #fff; }
.bk__btn--danger { color: #B42318; border-color: #F0C5C1; }
@media (max-width: 52rem) { .booking-intro { grid-template-columns: 1fr; } }
.bk__cancel { margin-top: .75rem; }
.bk__cancel summary { list-style: none; display: inline-flex; }
.bk__cancel summary::-webkit-details-marker { display: none; }
.bk__cancel[open] summary { display: none; }
.bk__cancel form { padding: .9rem 1rem; border-radius: 10px; background: #FCEBEA; }
.bk__cancel p { margin: 0 0 .75rem; color: #9B1C14; font-weight: 500; }

/* --------------------------------------------------------------------------
   Financing (templates/homepage/financing.html and the homepage band)
   -------------------------------------------------------------------------- */
.fin .shell { display: grid; grid-template-columns: minmax(14rem, 20rem) 1fr; gap: clamp(2rem, 1rem + 4vw, 5rem); align-items: center; }
.fin__offer { display: flex; align-items: center; gap: 1.1rem; }
.fin__rate { margin: 0; text-shadow: none; font-family: var(--display); font-size: clamp(5rem, 3rem + 6vw, 8.5rem); line-height: .85; color: var(--bone); letter-spacing: -.03em; }
.fin__term { margin: 0; font-size: var(--step-1); line-height: 1.25; color: var(--fg-2); }
.fin__term b { font-family: var(--display); font-weight: 400; font-size: var(--step-3); color: var(--bone); }
.fin__term span { display: block; margin-top: .4rem; font-size: .85rem; color: var(--fg-3); }
.fin__steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
.fin__steps li { padding-top: 1.1rem; border-top: 1px solid var(--rule); }
.fin__steps h3 { margin: .7rem 0 .4rem; font-family: var(--body); font-weight: 600; font-size: var(--step-1); letter-spacing: 0; color: var(--bone); }
.fin__steps p { margin: 0; color: var(--fg-2); line-height: 1.55; }
.fin__num { display: inline-grid; place-items: center; width: 2rem; height: 2rem; border-radius: 50%;
  background: var(--brick); color: var(--bone); font-weight: 700; font-size: .9rem; }
.fin__faqs { max-width: 52rem; border-top: 1px solid var(--rule); }
.fin__faq { border-bottom: 1px solid var(--rule); }
.fin__faq summary { cursor: pointer; list-style: none; padding: 1.1rem 2rem 1.1rem 0; position: relative; font-size: var(--step-1); font-weight: 500; }
.fin__faq summary::-webkit-details-marker { display: none; }
.fin__faq summary::after { content: '+'; position: absolute; right: .25rem; top: 50%; transform: translateY(-50%); font-size: 1.4rem; color: var(--fg-3); }
.fin__faq[open] summary::after { content: '\2212'; }
.fin__faq p { margin: 0 0 1.2rem; max-width: 60ch; color: var(--fg-2); line-height: 1.65; }
.fin__fine { padding-top: 0; }
.fin__disclosure { max-width: 70ch; margin: 0; font-size: .82rem; line-height: 1.6; color: var(--fg-3); }

/* The homepage band: the offer large, one line, the link. */
.fin-band .shell { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 1.5rem clamp(1.5rem, 1rem + 3vw, 4rem); }
.fin-band__rate { margin: 0; text-shadow: none; font-family: var(--display); font-size: clamp(4rem, 2.5rem + 4vw, 6.5rem); line-height: .85; color: var(--bone); }
.fin-band__copy h2 { margin: 0 0 .35rem; font-size: var(--step-2); }
.fin-band__copy p { margin: 0; color: var(--fg-2); max-width: 46ch; }
.fin-band__fine { grid-column: 1 / -1; margin: 0; font-size: .78rem; color: var(--fg-3); max-width: 90ch; }

/* The financing line beside a service page's form. */
.sv-finance { display: flex; gap: .75rem; align-items: flex-start; max-width: 36ch; margin: 1.6rem 0 0; padding: .9rem 1rem;
  border: 1px solid var(--rule); border-radius: var(--radius); font-size: .95rem; line-height: 1.5; color: var(--fg-2); }
.sv-finance b { color: var(--bone); }
.sv-finance a { color: var(--bone); }
.sv-finance i { margin-top: .2rem; color: var(--blush); }

@media (max-width: 52rem) {
  .fin .shell { grid-template-columns: 1fr; }
  .fin__steps { grid-template-columns: 1fr; }
  .fin-band .shell { grid-template-columns: 1fr; }
}
