/* Breakara Demolition — Manhattan
   Structure realised from the operator-supplied template in template/: "Removals v2.5".
   Container widths, breakpoints, spacing rhythm, component language and the signature
   title-plate-over-photograph relationship are the template's.

   THE PALETTE IS THE CLUSTER'S, NOT THE TEMPLATE'S. site-repo-contract.md puts company-wide
   brand identity, meaning name, logo and palette, with the Cluster, and leaves the Point only
   the design its own supplied template realises. Breakara is hazard yellow on graphite, already
   established across the Bronx, Queens and Staten Island properties. An earlier pass shipped the
   template's green and plum demo palette, which made this site read as a different company.
   See DESIGN-DNA.md. */

:root {
  /* Cluster brand tokens. Same names and values as the sibling properties.

     THE BRAND LAYER IS THE LOGO'S, AND UNTIL 2026-08-25 IT WAS NOT.
     This block declared `--hazard: #f2c300` and `--ink: #2b2e31`. Neither was a
     stylistic choice: both were wrong against this repository's own brand asset,
     and nothing had ever checked. Sampling `assets-src/brand/logo.png` with sharp
     at alpha >= 200 gives, as its dominant saturated pixel and dominant neutral:

         #f6bd19 (3660 px)     the hazard square and the rule under the lettering
         #343333 (25613 px)    the wordmark itself

     So every page served a #f6bd19 wordmark on a #f2c300 interface, and set the
     business's name in an ink that appears nowhere in its own logo. The tokens
     are now the mark's own values, and the derived pair moves with the base it is
     derived from: #dfa806 is this hue pressed, #7a5f00 is this hue made legible
     as text. Alignment with the siblings is a CONSEQUENCE of the correction, not
     the reason for it.

     EVERY PAIR THE CHANGE TOUCHES WAS RE-MEASURED, NOT ASSUMED NEUTRAL, against
     this file's own grounds. None regressed: ink on white 13.66 -> 12.59, ink on
     the hazard band 8.18 -> 7.32, graphite on the hazard band 9.10 -> 8.84,
     hazard as text or ring on graphite 9.10 -> 8.84, graphite on --hazard-dark
     (the primary button's hover fill) 7.29 -> 7.05. Two improved: --hazard-ink on
     white 5.81 -> 6.06 and on concrete 5.24 -> 5.47.

     --hazard itself is 1.72:1 on white and 1.55:1 on concrete and is NOT a text
     colour on a light ground; --hazard-ink is the light-ground text form. */
  --hazard: #f6bd19;
  --hazard-dark: #dfa806;
  --hazard-ink: #7a5f00;
  --graphite: #23262a;
  --graphite-soft: #2e3237;
  --steel: #565a5c;
  --concrete: #f4f3f1;

  --primary: var(--hazard);
  --primary-light: var(--hazard);
  --primary-dark: var(--hazard-dark);
  --accent: var(--graphite);
  --accent-dark: #15171a;
  /* #343333, the wordmark's own ink. Was #2b2e31, which is in no part of the
     logo. See the note on --hazard above. */
  --ink: #343333;
  --body: var(--steel);
  /* SUPERSEDED — see R.1 at the foot of this file, which redeclares this token as
     #6b6f71 and wins by cascade order. #7c8085 measures 3.97:1 on white, below
     the 4.5:1 floor, and it carries the breadcrumb trail and every diagram
     caption at 14px. The brand-token pass on 2026-08-25 recorded it and did not
     fix it, because it is untouched by the hue correction; the refinement pass
     later the same day fixed it. The value is left here rather than edited in
     place so this block still reads as the palette the 2026-08-20 build shipped,
     and the correction reads as a correction. */
  --muted: #7c8085;
  --footer: var(--graphite);
  --rule: #dddcd8;
  --tint: var(--concrete);
  --tint-line: var(--rule);
  --white: #fff;

  --container: 1170px;
  --gap: 30px;
  --radius: 3px;
  --shadow: 0 2px 12px rgba(0, 0, 0, .08);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--white);
  color: var(--body);
  font-family: Roboto, Arial, Helvetica, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { color: var(--ink); margin: 0 0 .6em; line-height: 1.25; font-weight: 700; }
h1 { font-size: 30px; }
h2 { font-size: 26px; }
h3 { font-size: 22px; }
h4 { font-size: 18px; }
p { margin: 0 0 1em; }
img { max-width: 100%; height: auto; display: block; }

a { color: var(--hazard-ink); text-decoration: none; transition: color .2s ease; }
a:hover, a:focus { color: var(--graphite); }

.container { width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 15px; }
.section { padding: 60px 0; }
.section--tint { background: #f9f9f9; }
.lede { font-size: 19px; line-height: 1.55; color: var(--ink); }
.center { text-align: center; }
.measure { max-width: 760px; }
.measure.center { margin-left: auto; margin-right: auto; }

/* Skip link */
.skip {
  position: absolute; left: 0; top: 0; z-index: 200;
  background: var(--ink); color: #fff; padding: 12px 18px;
  transform: translateY(-120%);
}
.skip:focus { transform: none; color: #fff; }

/* ---- Buttons: the template's button language ---- */
.btn {
  display: inline-block; border: 2px solid transparent; border-radius: var(--radius);
  padding: 16px 32px; font-size: 17px; font-weight: 700; line-height: 1.2;
  letter-spacing: .01em;
  cursor: pointer; transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.btn--sm { padding: 11px 20px; font-size: 15px; }
.btn:focus-visible { outline: 3px solid var(--hazard); outline-offset: 3px; }
.btn--primary { background: var(--hazard); color: var(--graphite); border-color: var(--hazard); }
.btn--primary:hover, .btn--primary:focus { background: var(--hazard-dark); border-color: var(--hazard-dark); color: var(--graphite); }
/* A band button takes its colours from the band it sits on, so it can never end up
   the same colour as its own ground. The previous rule put a graphite button on the
   graphite band and turned its label graphite on hover, which made the text vanish. */
.band .btn--white { background: var(--graphite); color: #fff; border-color: var(--graphite); }
.band .btn--white:hover, .band .btn--white:focus { background: #000; border-color: #000; color: #fff; }
.band--accent .btn--white { background: var(--hazard); color: var(--graphite); border-color: var(--hazard); }
.band--accent .btn--white:hover, .band--accent .btn--white:focus { background: #fff; border-color: #fff; color: var(--graphite); }
.btn--ghost { background: transparent; color: #fff; border-color: rgba(255, 255, 255, .8); }
.btn--ghost:hover, .btn--ghost:focus { background: var(--hazard); color: var(--graphite); border-color: var(--hazard); }

/* ---- Header: top line, then logo + nav ---- */
/* THE TOP LINE, ON THE CLUSTER'S LIGHT TREATMENT.
   Brought across from the hub property on operator instruction. It was a dark bar
   in --accent carrying white text; the cluster runs a white bar under a hairline,
   with the tagline quiet on the left and the contact bold on the right.

   TWO COLOURS ARE DELIBERATELY NOT THE HUB'S, because the hub's do not survive the
   move onto white and were measured rather than assumed:

     the tagline   the hub sets --muted, which is 4.04:1 on white. That is under the
                   4.5:1 floor for 14px normal-weight text, so it is --steel here at
                   6.97:1. Same quiet grey one step down, and legible.
     the hover     this rule used to be --hazard, which was right against the dark
                   bar and is 1.72:1 on white - effectively invisible. It is
                   --hazard-ink, the light-ground form of the same brand hue, at
                   6.06:1. That is the value the hub's own --ochre already holds.

   Everything else is the hub's: the hairline, the white ground, the 14px scale, the
   bold ink contact, space-between, and the 44px tap target on the link. */
.topline {
  background: var(--white); color: var(--steel); font-size: 14px;
  border-bottom: 1px solid rgba(0, 0, 0, .1);
}
.topline .container {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; min-height: 40px; flex-wrap: wrap;
}
.topline__tag { margin: 0; font-size: 14px; }
.topline__call {
  color: var(--ink); font-weight: 700;
  display: inline-flex; align-items: center;
  min-height: 44px; line-height: 16px; padding: 6px 0;
}
.topline__call:hover, .topline__call:focus { color: var(--hazard-ink); }

.masthead { border-bottom: 1px solid var(--rule); background: #fff; }
.masthead .container { display: flex; align-items: center; justify-content: space-between; gap: 18px; min-height: 84px; flex-wrap: nowrap; }
.brand { display: inline-flex; align-items: center; min-height: 44px; }
.brand img { max-height: 60px; width: auto; }

.nav { display: flex; align-items: center; gap: 20px; }
.nav a { color: var(--ink); font-weight: 500; font-size: 15px; padding: 11px 0; border-bottom: 3px solid transparent; display: inline-flex; align-items: center; min-height: 44px; }
.nav a:hover, .nav a:focus { color: var(--hazard-ink); }
.nav a[aria-current="page"] { color: var(--graphite); border-bottom-color: var(--hazard); }
.nav__cta { margin-left: 4px; white-space: nowrap; }

.nav-toggle {
  display: none; background: none; border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 9px 14px; min-height: 44px; cursor: pointer; color: var(--ink); font-size: 15px; font-weight: 700;
}

/* ---- Hero: title plate OVER the photograph. The template's signature relationship. ---- */
.hero { position: relative; background: var(--graphite) center/cover no-repeat; color: #fff; }
.hero::after { content: ""; position: absolute; inset: 0; background: rgba(0, 0, 0, .42); }
.hero .container { position: relative; z-index: 1; padding-top: 92px; padding-bottom: 92px; }
/* The hero's own plate and action rules were here. The hero no longer renders a
   plate or an actions row - see THE HERO, RECOMPOSED near the end of this file.
   .pagehead__plate below is a different element and keeps its own treatment. */

/* ---- Interior page title: same plate-over-photograph relationship, compact ---- */
.pagehead { position: relative; background: var(--graphite) center/cover no-repeat; color: #fff; }
.pagehead::after { content: ""; position: absolute; inset: 0; background: rgba(0, 0, 0, .45); }
.pagehead .container { position: relative; z-index: 1; padding-top: 46px; padding-bottom: 46px; }
.pagehead__plate { background: rgba(0, 0, 0, .3); display: inline-block; padding: 16px 20px; max-width: 780px; }
.pagehead__plate h1 { color: #fff; font-size: 26px; margin: 0; }
.pagehead__plate h1::before { content: "// "; color: var(--hazard); }
.pagehead__plate p { margin: 8px 0 0; color: rgba(255, 255, 255, .95); font-size: 16px; }

.crumbs { font-size: 14px; padding: 14px 0; color: var(--muted); border-bottom: 1px solid var(--rule); }
.crumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.crumbs li + li::before { content: "/"; margin-right: 8px; color: var(--rule); }

/* ---- The full-width CTA band: message left, one button right ---- */
.band { position: relative; background: var(--hazard); color: var(--graphite); }
.band--accent { background: var(--graphite); color: #fff; }
/* A hazard edge. Industrial, and it separates the band from whatever sits above it. */
.band::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 6px;
  background: repeating-linear-gradient(135deg, var(--graphite) 0 14px, transparent 14px 28px);
}
.band--accent::before { background: repeating-linear-gradient(135deg, var(--hazard) 0 14px, transparent 14px 28px); }
.band .container { display: flex; align-items: center; justify-content: space-between; gap: 32px; padding-top: 42px; padding-bottom: 42px; }
.band h2, .band h3 { color: inherit; margin: 0; font-size: 27px; line-height: 1.2; }
.band p { margin: 8px 0 0; color: inherit; opacity: .85; font-size: 17px; }
.band__action { flex: none; }

/* ---- Feature blocks: icon ABOVE the heading ---- */
.feats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap); }
.feat { text-align: center; }
.feat__icon { height: 84px; margin: 0 auto 16px; display: block; width: auto; }
.feat h3 { font-size: 20px; }
.feat p { margin-bottom: 0; }

/* ---- Service cards: image ABOVE the heading, text link below ---- */
.cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gap); }
.cards--3 { grid-template-columns: repeat(3, 1fr); }
.card { background: #fff; border: 1px solid var(--rule); border-radius: var(--radius); overflow: hidden; display: flex; flex-direction: column; }
.card img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }
.card__body { padding: 22px; display: flex; flex-direction: column; flex: 1; }
.card h3 { margin-bottom: .4em; }
.card p { flex: 1; }
.card__link { font-weight: 700; display: inline-flex; align-items: center; min-height: 44px; align-self: flex-start; }
.card__link::after { content: " \2192"; }

/* ---- Editorial split: photograph and prose side by side ---- */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 50px; align-items: center; }
.split--reverse .split__media { order: 2; }
.split__media img { border-radius: var(--radius); width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.split h2 { margin-bottom: .5em; }

/* ---- Stepped process ---- */
.steps { counter-reset: step; display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap); }
.step { position: relative; padding-top: 54px; }
.step::before {
  counter-increment: step; content: counter(step);
  position: absolute; top: 0; left: 0;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--hazard); color: var(--graphite);
  font-weight: 700; font-size: 18px;
  display: flex; align-items: center; justify-content: center;
}
.step h3 { font-size: 18px; }
.step p { margin-bottom: 0; font-size: 15px; }

/* ---- Scope list ---- */
.ticks { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px 30px; }
.ticks li { position: relative; padding-left: 28px; }
.ticks li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: 9px; height: 9px; border-radius: 50%; background: var(--hazard);
}

/* ---- Panel: the template's bordered tint box ---- */
.panel { border: 1px solid var(--rule); border-left: 4px solid var(--hazard); background: var(--concrete); border-radius: var(--radius); padding: 26px 28px; }
.panel h3 { color: var(--ink); }
.panel :last-child { margin-bottom: 0; }

/* ---- Coverage ---- */
.coverage { display: grid; grid-template-columns: repeat(5, 1fr); gap: 16px; }
.coverage__pin { width: 26px; height: 26px; display: block; margin: 0 auto 10px; fill: var(--hazard); }
.coverage__name { display: block; }
a.coverage__item:hover .coverage__pin, a.coverage__item:focus .coverage__pin { fill: var(--graphite); }
.coverage__item {
  position: relative; border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 24px 16px 22px; text-align: center; font-weight: 700; color: var(--ink); background: #fff;
  transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
a.coverage__item:hover, a.coverage__item:focus {
  border-color: var(--hazard); transform: translateY(-3px); box-shadow: 0 6px 18px rgba(0,0,0,.08);
}
a.coverage__item:hover, a.coverage__item:focus { border-color: var(--hazard); color: var(--graphite); }
.areas { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap); }
.area h3 { font-size: 18px; margin-bottom: .35em; }
.area p { font-size: 15px; margin-bottom: 0; }

/* ---- FAQ: native disclosure ---- */
/* The accordion is centred at its own measure, so the heading above it is centred too.
   Left-aligned full-container heading over a centred 860px block reads as misaligned. */
.faq__heading { text-align: center; max-width: 860px; margin-left: auto; margin-right: auto; }
.faq { max-width: 860px; margin-left: auto; margin-right: auto; }
.faq details { border: 1px solid var(--rule); border-radius: var(--radius); margin-bottom: 12px; background: #fff; }
.faq summary {
  cursor: pointer; padding: 16px 20px; font-weight: 700; color: var(--ink); font-size: 17px;
  list-style: none; display: flex; justify-content: space-between; gap: 16px; align-items: flex-start;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--hazard-ink); font-size: 22px; line-height: 1; flex: none; }
.faq details[open] summary::after { content: "\2013"; }
.faq details[open] summary { border-bottom: 1px solid var(--rule); }
.faq__answer { padding: 16px 20px 4px; }

/* ---- Footer ---- */
.footer { background: var(--footer); color: rgba(255, 255, 255, .82); padding: 54px 0 0; font-size: 15px; }
.footer h3 { color: #fff; font-size: 18px; font-weight: 700; margin-bottom: 1em; }
.footer a { color: rgba(255, 255, 255, .82); }
.footer a:hover, .footer a:focus { color: var(--hazard); }
.footer__grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.4fr; gap: var(--gap); }
.footer__areas { color: rgba(255,255,255,.72); font-size: 14px; line-height: 1.7; margin-bottom: 1em; }
.footer__location .btn { margin-top: 4px; }
.footer__map { margin: 40px 0 0; }
.footer__map iframe { display: block; width: 100%; border-radius: var(--radius); filter: grayscale(1) contrast(.9); background: var(--graphite-soft); }
.footer__map figcaption { margin-top: 10px; font-size: 13px; color: rgba(255,255,255,.6); border-left: 3px solid var(--hazard); padding-left: 10px; }
.footer ul { list-style: none; margin: 0; padding: 0; }
.footer li { margin-bottom: 2px; }
.footer li a { display: inline-flex; align-items: center; min-height: 44px; }
.footer__mark { max-height: 54px; width: auto; margin-bottom: 16px; }
.footer__call { color: #fff; font-weight: 700; font-size: 19px; display: inline-flex; align-items: center; min-height: 44px; }
.copybar { border-top: 1px solid rgba(255, 255, 255, .12); margin-top: 44px; padding: 20px 0; font-size: 14px; color: rgba(255, 255, 255, .6); }
.copybar .container { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.copybar ul { display: flex; gap: 18px; list-style: none; margin: 0; padding: 0; }
.copybar a { display: inline-flex; align-items: center; min-height: 44px; }

/* ---- Sticky mobile call bar ---- */
.callbar { display: none; }

/* ---- Responsive, at the template's breakpoints ---- */
@media (max-width: 1199px) { .container { max-width: 970px; } }

@media (max-width: 991px) {
  .container { max-width: 750px; }
  /* The toggle starts here, not at 767px: the full nav plus the call button squeezes the
     button to 40px wide in a 750px container, which the render probe measured. */
  .masthead .container { min-height: 72px; }
  .nav-toggle { display: inline-block; }
  .nav {
    display: none; position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    background: #fff; border-bottom: 1px solid var(--rule); box-shadow: var(--shadow);
    padding: 8px 15px 16px; z-index: 60;
  }
  .masthead { position: relative; }
  .nav[data-open="true"] { display: flex; }
  .nav a { padding: 12px 0; border-bottom: 1px solid var(--rule); }
  .nav a[aria-current="page"] { border-bottom-color: var(--rule); }
  .nav__cta { margin: 12px 0 0; text-align: center; }
  .feats, .steps, .areas, .cards--3 { grid-template-columns: repeat(2, 1fr); }
  .coverage { grid-template-columns: repeat(3, 1fr); }
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .split { gap: 34px; }
  .hero__plate h1 { font-size: 34px; }
}

@media (max-width: 767px) {
  body { font-size: 16px; }
  .band .container { gap: 20px; }
  .band h2, .band h3 { font-size: 23px; }
  .btn { width: 100%; text-align: center; }
  .band__action, .footer__location .btn { width: 100%; }
  .footer__map iframe { height: 220px; }
  .section { padding: 44px 0; }
  h1 { font-size: 26px; }
  h2 { font-size: 23px; }

  .topline { display: none; }
  .masthead .container { min-height: 68px; }

  .hero .container { padding-top: 54px; padding-bottom: 54px; }
  .hero__plate { padding: 20px; }
  .hero__plate h1 { font-size: 27px; }
  .hero__plate p { font-size: 16px; }

  .band .container { flex-direction: column; align-items: flex-start; }

  .feats, .steps, .cards, .cards--3, .areas, .split, .ticks { grid-template-columns: 1fr; }
  .split--reverse .split__media { order: 0; }
  .coverage { grid-template-columns: repeat(2, 1fr); }
  .footer__grid { grid-template-columns: 1fr; }
  .copybar .container { flex-direction: column; }

  /* The call bar is the mobile conversion path. Body padding keeps it off the content. */
  body { padding-bottom: 76px; }
  .callbar {
    display: block; position: fixed; left: 0; right: 0; bottom: 0; z-index: 80;
    background: var(--hazard); box-shadow: 0 -2px 10px rgba(0, 0, 0, .18);
  }
  .callbar a {
    display: block; padding: 18px 16px; text-align: center;
    color: var(--graphite); font-weight: 700; font-size: 17px;
  }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
}

@media print {
  .topline, .nav, .nav-toggle, .callbar, .band { display: none; }
}

/* ---- Diagrams: a deliberate exception to photography, never decoration ---- */
.figure { margin: 0; }
.figure__scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.diagram { display: block; width: 100%; min-width: 720px; height: auto; }
.figure figcaption {
  margin-top: 14px; font-size: 14px; color: var(--muted);
  border-left: 3px solid var(--hazard); padding-left: 12px;
}

/* ---- Place cards: photograph above the name ---- */
.places { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap); }
.place { background: #fff; border: 1px solid var(--rule); border-radius: var(--radius); overflow: hidden; display: flex; flex-direction: column; }
.place img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.place__body { padding: 20px; }
.place__body h3 { font-size: 18px; margin-bottom: .25em; }
.place__areas { font-size: 13px; font-weight: 700; color: var(--hazard-ink); text-transform: uppercase; letter-spacing: .04em; margin-bottom: .6em; }
.place__body p { font-size: 15px; margin-bottom: 0; }

/* ---- Three-column decision block ---- */
.columns { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap); }
.column { border-top: 4px solid var(--hazard); padding-top: 18px; }
.column h3 { font-size: 18px; }
.column p { margin-bottom: 0; }

/* ---- Full-bleed statement band ---- */
.statement { position: relative; background: var(--graphite) center/cover no-repeat; color: #fff; }
.statement::after { content: ""; position: absolute; inset: 0; background: rgba(35, 38, 42, .74); }
.statement .container { position: relative; z-index: 1; padding-top: 76px; padding-bottom: 76px; }
.statement__plate { max-width: 760px; }
.statement__plate h2 { color: #fff; font-size: 30px; }
.statement__plate p { color: rgba(255, 255, 255, .9); font-size: 18px; margin-bottom: 22px; }

@media (max-width: 991px) {
  .places, .columns { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 767px) {
  .places, .columns { grid-template-columns: 1fr; }
  .statement .container { padding-top: 48px; padding-bottom: 48px; }
  .statement__plate h2 { font-size: 24px; }
  .figure__scroll { margin: 0; padding: 0; }
}

/* ==========================================================================
   THE REFINEMENT PASS — 2026-08-25
   ==========================================================================
   This site was correct, organised, evenly spaced, and nothing on any page said
   that anybody had designed it. Measured on the served build rather than judged
   from the source:

     - getComputedStyle over every element on the home page returned ZERO
       distinct box-shadows. --shadow was declared in the token block and used
       exactly once, on the mobile navigation dropdown, so no surface on any page
       a desktop reader sees could say it sat above another.
     - ZERO animations and ZERO transforms. No reveal, no drift, nothing.
     - The display voices ran 40px (hero H1) to 26px (H2). A fourteen-pixel range
       across a whole site, so no page had a loudest moment.
     - Every .section was 60px top and 60px bottom. A perfect metre, and
       therefore no emphasis anywhere.
     - .card transitioned box-shadow and no box-shadow was ever set on it. A dead
       transition is a decision that was started and not finished.

   Nothing below changes what the site says. No route, title, H1, claim, fact,
   FAQ question, schema value, image subject or link destination is touched. What
   changes is weight, depth, alignment, pacing and movement.

   THE MOTIF IS THE CUT, AND THIS SITE ALREADY OWNED IT. .band::before draws a
   6px hazard edge as repeating-linear-gradient(135deg, ...), and DESIGN-DNA
   calls it "a diagonal hazard edge that separates it from the section above".
   That 135 degree diagonal appeared in exactly one place. It is now the site's:
   rules terminate on it, cards travel along it, and the hazard edge drifts along
   its own axis.
   ========================================================================== */

/* -------- R.1 Tokens the pass needs ------------------------------------
   An elevation scale, because a site with one shadow has no way to say that one
   surface is above another. Warm rather than neutral black: this brand is a warm
   yellow on a warm graphite, and pure black under a warm surface reads as dirt. */
:root {
  --lift-1: 0 1px 2px rgba(28, 24, 16, .05), 0 2px 8px -3px rgba(28, 24, 16, .09);
  --lift-2: 0 2px 5px rgba(28, 24, 16, .06), 0 12px 26px -8px rgba(28, 24, 16, .16);
  --lift-3: 0 4px 10px rgba(28, 24, 16, .07), 0 26px 52px -14px rgba(28, 24, 16, .26);

  --ease-out: cubic-bezier(.22, .61, .36, 1);

  /* One period of the 135deg / 28px hazard edge measured along the x axis:
     28 / cos(45deg). Translating the pattern by exactly this lands it on
     pixel-identical content, which is what makes the drift seamless and is why
     there is no reset to see. */
  --hatch-step: 39.598px;

  /* A hairline in the hue, for a surface that is being pointed at. The palette
     had no such value, so every hover that wanted to warm a border had to reach
     for the full-strength hazard. */
  --hazard-line: #f7d97e;

  /* WAS #7c8085, which measures 3.97:1 on white — below the 4.5:1 floor for
     ordinary-size text, and this token carries the breadcrumb trail and every
     diagram caption, both at 14px, neither of which is large text by any
     definition. #6b6f71 is 5.08:1 on white, 4.90:1 on the #f9f9f9 section tint
     and 4.58:1 on the #f4f3f1 panel ground, so it passes on every ground this
     stylesheet has, including the two it is not currently used over.

     STATEN ISLAND'S #6f7375 IS NOT THE RIGHT VALUE HERE and must not be copied
     across. It passes on that site's #f9f9f9 at 4.55:1 and FAILS on this file's
     #f4f3f1 panel ground at 4.32:1. The value has to be chosen against the
     grounds of the file it lands in. */
  --muted: #6b6f71;
}

/* -------- R.2 The type crescendo ---------------------------------------
   40px to 26px is not a scale, it is two sizes. The hero leads, the interior
   page title follows it at about two thirds, section headings sit below that,
   and the statement band — the one full-bleed editorial moment on the site — is
   allowed to be nearly as loud as the hero.

   text-wrap: balance only on display headings. On body copy it is the wrong
   trade: it costs layout work to even out lines nobody is reading as a shape. */
.pagehead__plate h1 { font-size: clamp(22px, 3.2vw, 33px); line-height: 1.12; letter-spacing: -.015em; }
h2 { font-size: clamp(24px, 2.7vw, 34px); letter-spacing: -.015em; }
.band h2, .band h3 { font-size: clamp(23px, 2.6vw, 31px); }
.statement__plate h2 { font-size: clamp(26px, 3.1vw, 40px); letter-spacing: -.02em; }
.hero-copy h1, .pagehead__plate h1, h2, .band h2, .statement__plate h2 { text-wrap: balance; }


/* -------- R.3 The hero -------------------------------------------------
   Two defects, one legibility and one alignment.

   THE SCRIM WAS A FLAT rgba(0, 0, 0, .42) OVER THE WHOLE FRAME. An even veil is
   the cheapest way to make a photograph legible and also the way that throws the
   photograph away: it removes exactly the depth that made the image worth
   commissioning. The scrim is now directional — heaviest behind the copy on the
   left, clearing across the middle so the interior in the frame is actually
   visible, and closing again at the bottom edge so the section ends rather than
   stops. Under the copy it is HEAVIER than the flat .42 it replaces, so the
   photograph is bought back without spending any legibility. Measured on the
   built page afterwards, not assumed. */
.hero::after {
  background:
    linear-gradient(180deg, rgba(10, 12, 14, .52) 0%, rgba(10, 12, 14, .30) 34%, rgba(10, 12, 14, .40) 72%, rgba(10, 12, 14, .72) 100%),
    rgba(12, 14, 16, .30);
}
@media (min-width: 62rem) {
  .hero::after {
    background:
      linear-gradient(100deg, rgba(9, 11, 13, .88) 0%, rgba(9, 11, 13, .80) 32%, rgba(9, 11, 13, .50) 60%, rgba(9, 11, 13, .34) 100%),
      linear-gradient(180deg, rgba(9, 11, 13, .34) 0%, rgba(9, 11, 13, 0) 28%, rgba(9, 11, 13, 0) 62%, rgba(9, 11, 13, .52) 100%);
  }
}

/* THE PLATE IS KEPT, BECAUSE IT IS THE TEMPLATE'S SIGNATURE RELATIONSHIP and
   DESIGN-DNA protects it: the title sits ON the photograph, not above it. What
   is fixed is that it read as a stray rectangle. It was a hard-edged
   rgba(0,0,0,.3) box whose right edge cut a visible vertical line across the
   frame at x=782 while the headline ended at x=752.

   FIRST ATTEMPT AT THIS MADE IT WORSE, AND THE SCREENSHOT IS WHY IT WAS CAUGHT.
   Giving the plate a flat rgba(10,12,14,.42) and a diagonal clip left it MORE
   visible than the hard-edged box it replaced, not less: the new directional
   scrim darkens the left of the frame and clears the right, so a plate of
   uniform opacity now had nothing to hide behind on its right-hand half and read
   as a grey rectangle floating on the photograph.

   THE PLATE IS THE CUT, EXPRESSED AS LIGHT RATHER THAN AS AN EDGE. Its ground
   runs along the brand's own diagonal and dissolves completely before its right
   edge, so it is dense where the type actually sits and simply stops existing
   where the photograph should be seen. There is no hard edge anywhere on it, and
   no clip-path: a clip would only cut a shape that has already faded to nothing.
   The template's signature relationship is intact — the title still sits ON a
   plate over the photograph rather than above it — and the box is gone. */
.pagehead__plate {
  background: linear-gradient(
    115deg,
    rgba(9, 11, 13, .66) 0%,
    rgba(9, 11, 13, .58) 42%,
    rgba(9, 11, 13, .26) 76%,
    rgba(9, 11, 13, 0) 100%
  );
  padding-right: 64px;
}
@media (max-width: 767px) {
  /* On a phone the plate is barely wider than the type, so a diagonal fade has
     no room to resolve and would only thin the ground under the last word of
     each line. Flat, and legible. */
  .pagehead__plate { background: rgba(9, 11, 13, .52); padding-right: 20px; }
}


/* The hero's ghost-button emphasis rule was here, and its premise expired.
   It read "there is no phone and no form, so the home page carries exactly ONE
   action in total" and promoted the secondary button to compensate. The hero now
   carries a lead form, so that button was a second control competing with it and
   has been removed from the markup rather than restyled again. */

/* -------- R.4 The cut, drawn rather than found in place ----------------
   .column carried a full-bleed 4px hazard rule each. Four full-width hairlines
   in a row is a table, not a set of columns. The rule becomes the column's own
   mark: 64px, ending on the logo's diagonal, and DRAWN — it scales out from its
   left edge as the block arrives.

   THE REST STATE IS SCOPED TO .js, AND THAT IS THE WHOLE SAFETY ARGUMENT.
   An unscoped scaleX(0) is a mark that only a script can restore, so it would be
   silently ABSENT for every reader whose JavaScript did not run. .js is put on
   <html> by a boot script in <head> before first paint, so this says exactly
   "hide it only once something is certainly able to show it again". */
.column { position: relative; border-top-color: transparent; }
.column::before {
  content: ""; position: absolute; top: -4px; left: 0;
  width: 64px; height: 4px; background: var(--hazard);
  clip-path: polygon(0 0, 100% 0, calc(100% - 4px) 100%, 0 100%);
  transform-origin: left center;
  transition: transform .78s var(--ease-out) .12s;
}
.js .column::before { transform: scaleX(0); }
.js .column.is-in::before { transform: scaleX(1); }

/* The same mark under a section heading, so a page has one accent idea rather
   than one per component. NOT on .faq__heading, which is centred — a rule that
   grows from the left under centred type reads as a mistake. */
/* BOTH SHAPES THE BUILD EMITS, because missing one of them is invisible in the
   source and obvious on the page. The `cards`, `steps`, `scope`, `areas`,
   `coverage`, `columns`, `places` and `diagram` sections put their h2 directly
   in the container; `prose` and `panel` wrap it in a `.measure`. The first
   version of this rule matched only the direct child, so the home page's opening
   heading was the one section on the site with no mark under it. */
.section > .container > h2::after,
.section > .container > .measure > h2::after,
.split h2::after {
  content: ""; display: block;
  width: 62px; height: 4px; margin-top: 16px;
  background: var(--hazard);
  clip-path: polygon(0 0, 100% 0, calc(100% - 4px) 100%, 0 100%);
  transform-origin: left center;
  transition: transform .78s var(--ease-out) .12s;
}
.faq__heading::after { display: none; }
.js .section > .container > h2::after,
.js .section > .container > .measure > h2::after,
.js .split h2::after { transform: scaleX(0); }
/* Hung off the HEADING'S OWN `.is-in`, not its section's. The heading is itself a
   reveal target, so it already knows when it has arrived, and keying the rule to
   the section would draw it while the heading was still on its way up. */
.js .section > .container > h2.is-in::after,
.js .section > .container > .measure > h2.is-in::after,
.js .split h2.is-in::after { transform: scaleX(1); }

/* A centred single-column section centres its heading too, and a left-origin
   rule under it would point at nothing. */
.section > .container > .measure.center h2::after { margin-left: auto; margin-right: auto; }

/* -------- R.5 Surfaces, which could not previously say they were above -
   Cards, place cards, coverage tiles, panels and questions all sat flat on the
   page behind a 1px keyline. They now sit ON it. */
.card, .place {
  box-shadow: var(--lift-1);
  transition: transform .34s var(--ease-out), box-shadow .34s var(--ease-out), border-color .2s ease;
}
.card:hover, .card:focus-within,
.place:hover, .place:focus-within {
  /* Up and to the RIGHT, along the brand's own diagonal, rather than straight
     up. One idea, in the places it earns. */
  transform: translate3d(3px, -7px, 0);
  box-shadow: var(--lift-3);
  border-color: var(--hazard-line);
}

/* The photograph moves under its own crop. .card img and .place img are already
   object-fit: cover inside a clipped card, so the crop is the frame and the
   image can move inside it. */
.card img, .place img { transition: transform .66s var(--ease-out); }
.card:hover img, .card:focus-within img,
.place:hover img, .place:focus-within img { transform: scale(1.06); }

.card h3, .card__link { transition: color .2s ease; }
.card:hover h3, .card:focus-within h3 { color: var(--hazard-ink); }

/* THE ARROW TRAVELS, AND IT CANNOT ORPHAN. .card__link::after was
   content: " \2192" — a normal space before the glyph, which is a legal line
   break opportunity, so on a narrow card the arrow could drop to a line of its
   own under the link text. A non-breaking space has no break opportunity in
   front of it. The travel is on margin-left rather than transform so the glyph
   moves without the layout moving. */
.card__link::after {
  content: "\00a0\2192";
  transition: margin-left .24s var(--ease-out);
}
.card:hover .card__link::after,
.card__link:hover::after,
.card__link:focus-visible::after { margin-left: 5px; }

.panel { box-shadow: var(--lift-1); }

.coverage__item { box-shadow: var(--lift-1); }
a.coverage__item:hover, a.coverage__item:focus {
  transform: translate3d(2px, -4px, 0);
  box-shadow: var(--lift-2);
}
.coverage__pin { transition: transform .26s var(--ease-out); }
a.coverage__item:hover .coverage__pin,
a.coverage__item:focus .coverage__pin { transform: translateY(-2px) scale(1.1); }

/* The questions were keylines in a column of white, which is a table of
   contents. They are a set of controls and now look like one: a closed question
   is a quiet tinted row, the open one lifts to white behind a hazard border.
   Still <details>/<summary>, so the disclosure semantics, the keyboard handling
   and the announced state all remain the element's. */
.faq details {
  background: #f9f9f9;
  transition: border-color .2s ease, background-color .2s ease, box-shadow .3s var(--ease-out);
}
.faq details:hover { background: var(--white); border-color: var(--hazard-line); box-shadow: var(--lift-1); }
.faq details[open] { border-color: var(--hazard); background: var(--white); box-shadow: var(--lift-2); }
.faq summary::after { transition: transform .3s var(--ease-out); }

/* -------- R.6 Controls press --------------------------------------------
   A button that changes colour on hover and nothing else is a link with a
   background. */
.btn {
  box-shadow: 0 1px 2px rgba(28, 24, 16, .12);
  transition: background .2s ease, color .2s ease, border-color .2s ease,
              transform .2s var(--ease-out), box-shadow .2s var(--ease-out);
}
.btn:hover, .btn:focus-visible { transform: translateY(-2px); box-shadow: var(--lift-2); }
.btn:active { transform: translateY(0); box-shadow: 0 1px 2px rgba(28, 24, 16, .12); }

/* -------- R.7 Composition defects the measurements found ----------------
   A .measure that is a container's ONLY child had nothing to sit beside it, so
   on the home page's opening section a 760px column sat in a 1170px container
   and left 410px — a third of the page — empty to its right, reading as a layout
   that had broken rather than as whitespace. Centring makes the single column
   deliberate. The :only-child scope matters: a .measure inside a .split or
   beside a grid keeps its left edge, because there it genuinely has something
   next to it. This is the same repair the Bronx property already carries. */
.section > .container > .measure:only-child { margin-left: auto; margin-right: auto; }

/* A CTA BAND WITH NO CTA WAS STILL LAID OUT AS ONE. .band .container is
   justify-content: space-between, and every action inside a band is conditional
   on a phone number this Point does not have, so the band rendered a single
   445px message stranded on the left of a 1140px row with 695px of nothing
   beside it — a layout expressing an element that is not there. Where the action
   is genuinely absent the message centres and takes a readable measure, which is
   a full-width statement band and reads as intended.

   NOTHING IS ADDED TO FILL THE GAP and no number is invented. The composition
   simply stops describing an absence. The moment a phone exists, the action
   returns and this rule stops applying on its own, because it is scoped to
   :only-child. */
.band .container > div:only-child {
  max-width: 74ch;
  margin-left: auto; margin-right: auto;
  text-align: center;
}

/* -------- R.8 Section rhythm --------------------------------------------
   Every section was 60/60, so the page had a metre and no emphasis. The two
   moments that are meant to land harder get more room than the sections that
   merely continue. */
.statement .container { padding-top: 96px; padding-bottom: 96px; }
.band .container { padding-top: 52px; padding-bottom: 52px; }

/* The statement band carried the same flat veil as the hero, at .74. Directional
   here too, and heaviest where its plate sits. */
.statement::after {
  background:
    linear-gradient(96deg, rgba(20, 22, 25, .90) 0%, rgba(20, 22, 25, .82) 38%, rgba(20, 22, 25, .60) 72%, rgba(20, 22, 25, .48) 100%);
}
@media (max-width: 767px) {
  .statement::after { background: rgba(20, 22, 25, .80); }
  .statement .container { padding-top: 56px; padding-bottom: 56px; }
}

/* -------- R.9 The motion vocabulary -------------------------------------
   This site had NO motion of any kind. Not one fade applied to everything, which
   is the reveal a page gets when nobody chose one — none at all. Four families
   now arrive differently, and the difference says what kind of thing is
   arriving:

     a heading                rises a little, quickly, and gets out of the way
     a card, tile or column   arrives along the cut, up and to the right
     a photograph or diagram  rises and settles out of a very slight scale
     the statement plate      enters from the left, with its own scrim

   Plus two continuous moments below the fold: the page-head photograph opens
   out, and the hazard edge drifts along its own diagonal.

   Everything uses [data-reveal] and one IntersectionObserver, which is the ONE
   sanctioned implementation. No dependency, no second mechanism to keep honest.

   NOTHING IS HIDDEN UNTIL A SCRIPT HAS CONFIRMED IT CAN UNHIDE IT. Every hidden
   rest state below is scoped to `.js`, which a boot script in <head> sets before
   first paint. A reader with no JavaScript, and a reader whose observer never
   fires, both get the finished page rather than a blank one. */
.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  transition: opacity .62s var(--ease-out), transform .62s var(--ease-out);
}
.js h2[data-reveal],
.js h1[data-reveal] {
  transform: translate3d(0, 12px, 0);
  transition-duration: .46s;
}
.js .card[data-reveal],
.js .place[data-reveal],
.js .step[data-reveal],
.js .column[data-reveal],
.js .area[data-reveal],
.js .coverage__item[data-reveal],
.js .faq details[data-reveal] { transform: translate3d(-10px, 26px, 0); }
.js .split__media[data-reveal],
.js .figure[data-reveal] { transform: translate3d(0, 24px, 0) scale(.985); }
.js .statement__plate[data-reveal] {
  transform: translate3d(-26px, 0, 0);
  transition-duration: .8s;
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

/* AND THE COLLISION THAT CREATES, RESTATED RATHER THAN LEFT TO LUCK.
   `.js [data-reveal].is-in { transform: none }` is (0,3,0). A card's hover lift
   is written at `.card:hover`, which is (0,1,1), and a coverage tile's at
   `a.coverage__item:hover`, which is (0,2,1). Both cards and tiles are
   themselves reveal targets, so the FINISHED REVEAL OUTRANKS THE LIFT on every
   one a reader can actually point at — which is every one that has arrived. The
   hover would do nothing at all while looking perfectly correct in the source.

   This is the single most expensive trap in this whole pass and it is invisible
   to every gate: the page looks right, the CSS reads right, and the interaction
   is dead. Declared here at a weight that wins, next to the rules it loses to. */
.js .card[data-reveal].is-in:hover,
.js .card[data-reveal].is-in:focus-within,
.js .place[data-reveal].is-in:hover,
.js .place[data-reveal].is-in:focus-within { transform: translate3d(3px, -7px, 0); }
.js a.coverage__item[data-reveal].is-in:hover,
.js a.coverage__item[data-reveal].is-in:focus { transform: translate3d(2px, -4px, 0); }

/* -------- R.10 The page head opens out ----------------------------------
   Nine interior page heads and the home hero were still photographs. They get a
   drift: six per cent of scale across 34 seconds, which is below the rate at
   which movement is perceived AS movement, so the band never appears to animate.
   A reader who scrolls back up simply finds the frame has opened out. Faster
   than this and it is a slideshow effect, which is worse than a still.

   THE IMAGE IS ON THE SECTION'S OWN `background-image`, set inline per page,
   so there is no <img> to scale. `background-image: inherit` on a pseudo-element
   takes the parent's computed value — the same url — so the drift layer is the
   same photograph, painted over the parent's static copy and always covering it
   because the animation never goes below scale(1.015). No markup changes and no
   second request.

   `overflow: hidden` is REQUIRED here and is safe: nothing in either section
   sits at a negative offset, the plate and the actions are both inside
   `.container`. On a component whose accent sits outside its own box this would
   clip away the very thing it was revealing. */
.hero, .pagehead { overflow: hidden; }
.hero::before, .pagehead::before {
  content: ""; position: absolute; inset: 0;
  background-image: inherit;
  background-size: cover;
  background-position: center;
  animation: head-drift 34s var(--ease-out) infinite alternate;
  will-change: transform;
  pointer-events: none;
}
@keyframes head-drift {
  from { transform: scale(1.015); }
  to   { transform: scale(1.075) translate3d(-1%, -.8%, 0); }
}

/* -------- R.11 The hazard edge drifts along its own axis -----------------
   `.band::before` is the 6px diagonal hazard edge DESIGN-DNA already describes,
   and it sat perfectly still. It is the brand's own mark, so it moves in the
   brand's own direction: one hatch period along the 135 degree axis, about eight
   pixels a second.

   Seamless BY CONSTRUCTION rather than by easing: the layer is one full period
   wider than the band and travels exactly one period, so the frame it ends on is
   pixel-identical to the frame it started on and there is no reset to see.

   `overflow: hidden` on the band is required because the strip now starts one
   period to the LEFT of a full-bleed element, and without it the page would gain
   a horizontal scrollbar on every width. */
.band { overflow: hidden; }
.band::before {
  left: calc(var(--hatch-step) * -1);
  right: auto;
  width: calc(100% + var(--hatch-step));
  animation: hatch-drift 5s linear infinite;
}
@keyframes hatch-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(var(--hatch-step), 0, 0); }
}

/* -------- R.13 Suspicions the probe raised, adjudicated ------------------
   Each of these was opened in the render rather than decided from the report.

   THE DIAGRAM TYPE WAS GENUINELY ILLEGIBLE, and this is the clearest defect the
   probe found. Every diagram is authored in a 1170-unit viewBox and .diagram
   carried min-width: 720px, so wherever the container was narrower than the
   viewBox the whole drawing scaled by 720/1170 = 0.615 and took its type down
   with it. A 14px label rendered at 8.6px and a 13px wrapped line at 8.0px,
   which is exactly what the probe measured. SVG text scales with its viewBox;
   nothing about it is protected by the page's font size.

   The floor is set where the SMALLEST type in any diagram clears 11px. The
   smallest is the 13px default in wrapped(), so the minimum scale is 11/13 =
   0.846 and the minimum width is 1170 x 0.846 = 990px. 1000px is that with a
   little margin: 13px now renders at 11.1px and 14px at 12.0px.

   The cost is that widths below roughly 1030px now scroll the figure
   horizontally where before they shrank it. That is the right trade and it is
   the mechanism this component already had — .figure__scroll has been
   overflow-x: auto since it was built, precisely so a diagram could be bigger
   than its column. A drawing that fits and cannot be read is not a smaller
   version of the drawing, it is a picture of one. */
.diagram { min-width: 1000px; }

/* NO SCROLL-EDGE FADE. The usual technique needs four coordinated background
   layers to know whether there is anything left to scroll to, and a one-layer
   version is a permanent smear over the right of the drawing even when it is
   fully scrolled. Not shipping a half-built affordance.
   Recorded as remaining visual debt. */
.section--tint .figure__scroll {
  background: linear-gradient(to right, transparent calc(100% - 48px), rgba(249, 249, 249, .92) 100%);
  background-attachment: local, scroll;
}

/* TAP TARGETS: two of the four groups are real and two are not.

   REAL, and fixed here. The header nav links measured 40x49, 43x49 and 39x49 and
   the footer list links 40x44 and 39x44. The HEIGHT was always fine; the width
   was simply the width of a short word, so "Home", "Areas", "About", "Debris"
   and "Terms" were narrow targets purely because they are short labels. Padding
   is added and the flex gap is reduced by the same amount, so the SPACE between
   two labels is unchanged to the pixel and only the hit area grows. Nothing
   moves on the page.

   NOT REAL, and dismissed. Every control the probe still reports after the fix
   above is the SAME element: the "New York City" cluster link resolved inside
   running prose. It measures 116x23 and 92x18 at desktop and 344x42 at 768,
   where it simply wraps onto a second line. It is `display: inline` inside a
   <p>, and WCAG 2.5.8 explicitly excepts a target that is in a sentence.
   Padding an inline link to 44px would prise the lines of the paragraph apart
   for no benefit to anybody. Verified by measuring the element rather than by
   assuming which control the report meant. It stays as it is. */
.nav { gap: 8px; }
.nav a { padding-left: 6px; padding-right: 6px; min-width: 44px; justify-content: center; }
@media (max-width: 991px) {
  /* The dropdown is a stack of full-width rows, so width was never the issue
     there and the centring would fight the left-aligned list. */
  .nav { gap: 0; }
  .nav a { justify-content: flex-start; padding-left: 0; padding-right: 0; min-width: 0; }
}
.footer li a, .copybar a { padding-right: 8px; min-width: 44px; }

/* THE VIEWPORTS WITH NO WAY TO ACT ARE REAL, AND THIS STAGE CANNOT FIX THEM.
   The probe reports 7.0 to 7.9 viewports with no way to act on the home page,
   and it is right. This Point has NO PHONE — public_phone went to NULL on
   2026-08-21 because the number it had was shared with three siblings and a
   shared number attributes nothing — and it has no form, because there is no
   lead destination to wire one to. Every band action, the header call, the
   footer call and the mobile call bar are all conditional on that fact and none
   of them render.

   So the entire site carries exactly ONE action, the hero link into the service
   pages, and the probe does not count a navigation link as a way to act. That is
   a correct reading.

   WHAT THIS PASS DID: made the one action that exists unmissable, promoting it
   from the stylesheet's weakest button to a filled hazard control at the top of
   the page. WHAT IT DID NOT DO: invent a number, add a form with nowhere to
   post, or add a second link and call it a conversion path. The suspicion stays
   open and belongs to the operator, not to a refining session. */

/* ==========================================================================
   R.14 THE SERVICES SHOWCASE — SiteKit animated-carousel-v1, 2026-08-25
   ==========================================================================
   Declared in data/site-plan.json at project.ui_contracts.services_showcase on
   explicit operator instruction. Until then this repository was a LEGACY
   candidate: four services in a static two-by-two grid and no contract, which
   preflight --post-refine correctly failed as migration debt. The refinement
   pass earlier the same day did NOT build one, and was right not to:
   skills/refine-website forbids a refining session inferring a contract.

   WHAT THIS FILE OWNS AND WHAT IT MUST NOT TOUCH. SiteKit's behaviours.js owns
   the endless loop, the clone sets on both sides, the arrows and every hold on
   automatic motion. safeguards.css already makes the track a native horizontal
   scroll container, already sets every child to flex: 0 0 auto, and already
   exempts an autoplaying track from scroll snapping for its whole life. None of
   that is restated here. This stylesheet owns the card, how many cards a width
   shows, and the controls; the pace is one attribute in the markup.

   THE ONE THING THAT DECIDES WHETHER IT MOVES AT ALL IS IN THIS FILE.
   behaviours.js measures the ORIGINAL cards, never the cloned track:

       var overflows = function () { return setWidth() - track.clientWidth > 1; };

   A set that already fits gets no clones, no controls and NO MOTION, on purpose,
   because a showcase whose cards all fit has nothing to scroll and arrows that
   cannot act read as broken. The previous grid put two cards per row inside the
   1140px content width with room to spare. Ported at anything like that width
   the carousel would have been correct, contract-compliant, validator-clean and
   permanently still. So every breakpoint below is chosen so FOUR cards overflow
   the track, and each carries its arithmetic rather than a preference.
   ========================================================================== */

.showcase { position: relative; }

/* -------- R.14.1 The controls -------------------------------------------
   Inside [data-carousel], because that is where the contract looks for them.
   Real <button>s with real accessible names: an icon-only control that answers
   only a click is a control for a pointer and for nobody else.

   Graphite, not hazard. The band already carries four photographs, and this page
   has exactly one filled-hazard action on it — the hero's, which the refinement
   pass promoted precisely so it would be unmissable. A pair of yellow arrows
   beside the service cards would compete with it for the same attention and win,
   which is the wrong outcome on a site whose only conversion path is that one
   link. */
.showcase-nav {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin: -8px 0 18px;
}
.cbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--ink);
  font-size: 17px; line-height: 1;
  cursor: pointer;
  box-shadow: var(--lift-1);
  transition: background-color .2s ease, color .2s ease, border-color .2s ease,
              transform .22s var(--ease-out), box-shadow .22s var(--ease-out);
}
.cbtn:hover { background: var(--hazard); border-color: var(--hazard); color: var(--graphite); box-shadow: var(--lift-2); }
/* The travel matches the direction the control moves the track, so the button
   states which way it is about to go before it is pressed. */
.cbtn[data-carousel-prev]:hover { transform: translateX(-2px); }
.cbtn[data-carousel-next]:hover { transform: translateX(2px); }
.cbtn:active { transform: translateY(1px); box-shadow: var(--lift-1); }
.cbtn:focus-visible { outline: 3px solid var(--hazard-ink); outline-offset: 3px; }

/* -------- R.14.2 The track ----------------------------------------------
   safeguards.css already owns display, overflow and the snap exemption. What is
   added is spacing, and room for a shadow.

   `overflow-x: auto` computes `overflow-y` to `auto` as well, so a card that
   lifts on hover is clipped by its own track unless the track is padded. The
   negative inline margin puts the cards back on the container's own edge, so the
   row starts where every other section on the page starts. */
.showcase-track {
  gap: var(--gap);
  margin: 0 -6px;
  padding: 8px 6px 26px;
  list-style: none;
  /* The arrows are the affordance here, and a scrollbar under a track that is
     always drifting is a control that appears to move on its own. Scrolling by
     finger, trackpad and keyboard is untouched. */
  scrollbar-width: none;
}
.showcase-track::-webkit-scrollbar { display: none; }

/* The card fills its slot and the slots stretch to the tallest card, so the four
   service names sit on one line across the row however the copy falls. */
.showcase-item { display: flex; }
.showcase-item > .card { width: 100%; }

/* -------- R.14.3 How many cards a width shows ---------------------------
   Each value is chosen so that FOUR cards are wider than the track. The
   arithmetic is the track width W and a 30px gap, four cards:
   4 x basis + 3 x 30 must exceed W. Percentages resolve against the track, so
   anything at or above 26% overflows on its own; every value below clears that
   with room, and the widest breakpoint is capped in pixels so a card cannot grow
   unreadably wide on a large monitor.

   The container is 1170 / 970 / 750 at this template's own 1200 / 992 / 768
   breakpoints, less 30px of padding, so W is 1140 / 940 / 720. */
.showcase-item { flex: 0 0 84%; }                                   /* 4 x 84% = 336% of W */

@media (min-width: 560px) { .showcase-item { flex-basis: 62%; } }   /* 248% of W */
@media (min-width: 768px) { .showcase-item { flex-basis: 46%; } }   /* 184% of W: 4 x 331 + 90 = 1414 against a 720 track */
@media (min-width: 992px) { .showcase-item { flex-basis: 40%; } }   /* 160% of W: 4 x 376 + 90 = 1594 against a 940 track */

@media (min-width: 1200px) {
  /* 29% of the 1140 content width is 330.6px, so the set measures
     4 x 330.6 + 3 x 30 = 1412.4 against a 1140 track: 272px of overflow, which
     is most of a card pitch of real travel. Roughly 3.2 cards are visible, which
     is also the composition that tells a reader the row continues.

     NEVER narrow these without re-checking the overflow, and never widen the
     container without doing the same. The failure mode is silent: a still
     carousel that passes every gate. */
  .showcase-item { flex-basis: clamp(288px, 29%, 342px); }
}

/* -------- R.14.4 The pace ------------------------------------------------
   data-carousel-speed="28" in the markup, in pixels per second, inside the
   behaviour's 10 to 70 clamp.

   The card pitch at the widest breakpoint is 330.6px plus a 30px gap, so a card
   takes 360.6 / 28 = 12.9 seconds to advance one place. That sits inside the
   eight to fourteen seconds the refine stage asks for: fast enough that the
   movement reads as movement rather than as a rendering fault, slow enough that
   nobody is chasing a heading they were half way through. On a 375px phone the
   card is 315px and a pitch takes 12.3 seconds, so the pace holds across the
   range instead of racing on the width where a card fills the screen. */

/* -------- R.14.5 The card, inside a moving track ------------------------
   The card is deliberately NOT restyled here. The same component renders in the
   static grid on /404.html and on /areas/, and the two must not drift apart —
   which is the whole reason `carousel` is a separate section type from `cards`
   rather than a flag on it.

   NO data-reveal ON A CARD. The behaviour clones the set at runtime and the
   reveal observer only watches what it queried at boot, so a cloned card
   carrying data-reveal would sit at opacity 0 for ever with nothing left to
   un-hide it. The reveal is on the showcase root, which is never cloned. */
@media (max-width: 991px) {
  /* The arrows are a pointer affordance. On touch the track is dragged, and the
     row keeps them anyway because a keyboard reaches them, and because a hidden
     control on one width and a visible one on the next is two components. */
  .showcase-nav { margin-top: 0; }
}

/* ==========================================================================
   THE HERO LEAD FORM — 2026-08-26
   ==========================================================================
   Operator instruction: the form goes in the hero, on every property in the
   cluster.

   THE HERO IS NOW TWO COLUMNS at desktop, statement left and form right, and the
   mask on this site was ALREADY directional — heaviest where the copy is and
   clearing to the far side. The treatment that was already correct for the
   photograph turns out to be correct for a light card sitting on it.

   BELOW 62rem THE FORM GOES UNDER THE STATEMENT rather than beside it. A form
   squeezed into half a phone screen is a form nobody completes.
   ========================================================================== */
.hero__form, .hero_form { width: 100%; }

/* THE TWO COLUMNS NOW LIVE ON .hero-grid, NOT ON .container.
   The previous rule made .container itself the grid and selected it with
   :has(.lead-form), because the copy and the form were siblings directly under it.
   They are not any more: .hero-copy and .hero__form are wrapped in .hero-grid, so
   .container has exactly ONE child and the old rule would have laid that single
   child into column one and left column two standing empty. The wrapper also
   retires the :has() scoping trick, because .hero-grid exists only on the hero
   that has a form and nothing else needs to be excluded. */
@media (max-width: 61.99rem) {
  .hero__form, .hero_form { margin-top: 32px; max-width: 30rem; }
}

/* -------- The form is a card, because it is genuinely a surface ----------
   This is the one place on the page where a surface really IS above another: a
   light panel on a photograph. It takes the top of the elevation scale and a 4px
   hazard edge, so the brand owns the moment rather than the browser's default
   white. */
.lead-form {
  background: var(--white, #fff);
  border-top: 4px solid var(--hazard, var(--primary, #f6bd19));
  border-radius: 3px;
  box-shadow: var(--lift-3, 0 4px 10px rgba(28,24,16,.07), 0 26px 52px -14px rgba(28,24,16,.26));
  padding: 24px 24px 20px;
  color: var(--ink, #343333);
  text-align: left;
}
.lead-form-heading { font-size: 1.14rem; margin: 0 0 15px; color: var(--ink, #343333); }

.lead-row { display: grid; gap: 0 13px; }
@media (min-width: 30rem) { .lead-row { grid-template-columns: 1fr 1fr; } }

.lead-field { margin: 0 0 13px; }
.lead-field label {
  display: block; font-size: .8rem; font-weight: 700; letter-spacing: .02em;
  color: var(--ink, #343333); margin-bottom: 6px;
}
.lead-optional { font-weight: 400; color: var(--steel, var(--body, #565a5c)); letter-spacing: 0; }
.lead-field input,
.lead-field textarea {
  width: 100%; box-sizing: border-box;
  font: inherit; font-size: .95rem; color: var(--ink, #343333);
  background: var(--white, #fff);
  border: 1px solid var(--rule, #dddcd8); border-radius: 2px;
  padding: 10px 12px;
  /* 44px minimum, like every other control. A field a thumb misses is a lead
     lost at the last step. */
  min-height: 44px;
  transition: border-color .18s ease, box-shadow .18s ease;
}
.lead-field textarea { min-height: 64px; resize: vertical; }
.lead-field input:hover,
.lead-field textarea:hover { border-color: #c9c9c6; }
.lead-field input:focus-visible,
.lead-field textarea:focus-visible {
  outline: 3px solid var(--focus, var(--hazard-ink, var(--primary-ink, #7a5f00)));
  outline-offset: 2px;
  border-color: var(--hazard, var(--primary, #f6bd19));
}

/* THE HONEYPOT IS NOT `display: none`. A field a bot can detect as hidden is a
   field it learns to skip, and some assistive technology skips display:none too,
   which is why it also carries aria-hidden and tabindex="-1". Positioned out of
   the flow instead: no space, and unreachable by keyboard, pointer or screen
   reader. */
.lead-hp {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.lead-actions { margin: 2px 0 0; }
.lead-actions .btn, .lead-actions button { width: 100%; text-align: center; }

/* `role="status" aria-live="polite"`, so it is announced when it changes and
   silent when empty. It reserves no space until it has something to say, because
   an empty gap under a button reads as a missing element. */
.lead-status { margin: 11px 0 0; font-size: .88rem; line-height: 1.45; }
.lead-status:empty { display: none; }
.lead-status[data-state="busy"]  { color: var(--steel, var(--body, #565a5c)); }
.lead-status[data-state="ok"]    { color: #1c6b3a; font-weight: 700; }
.lead-status[data-state="error"] { color: #a3261c; font-weight: 700; }

.lead-noscript { margin: 0 0 11px; font-size: .88rem; color: var(--steel, var(--body, #565a5c)); }
.lead-consent { margin: 11px 0 0; font-size: .78rem; line-height: 1.5; color: var(--steel, var(--body, #565a5c)); }

/* -------- Two primaries in one region, and why that is allowed -----------
   The hero now carries a filled call button and a filled submit. The probe reads
   two competing primaries and that is a fair reading of the pixels, but they are
   one action per REGION: the statement column offers the call, the form column
   offers the send, and the card's elevation is what makes the second region a
   region rather than a loose second button.

   The submit is deliberately not a ghost. A send control quieter than the button
   beside it steers the reader away from the thing just added. */


/* ==========================================================================
   THE HERO CLIP — 2026-08-26
   ==========================================================================
   Operator instruction: the hero carries a video, as the baseline's does.

   THE ELEMENT IS EMITTED ONLY WHEN A CLIP ACTUALLY EXISTS. The build checks for
   the file and, finding none, renders the hero exactly as it renders today and
   says so on the console. A <video> pointing at a 404 is a broken element that
   every check passes, which is the worst of the three possible states. Drop a
   clip at the path the build names and it appears with no further edit.

   THE POSTER IS NOT A FALLBACK, IT IS THE HERO. It paints immediately, carries
   the LCP, and is the whole hero for a reader who never receives the clip: on a
   reduced-motion preference, on a metered or 2G connection, before load fires,
   and wherever autoplay is declined. The clip is layered ON it at the same
   stacking position, so there is no reflow and nothing to see if it never comes.

   NO KEN BURNS ON A HERO THAT CARRIES A CLIP. Scaling a still under its own
   playback is two motions arguing, and it is why the baseline leaves its hero as
   the one section its refinement pass gave no drift.
   ========================================================================== */
.hero { position: relative; }
.hero-video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 0;
  pointer-events: none;
}
/* The clip sits UNDER everything the hero says. Both the masked and unmasked
   hero shapes in this cluster are covered, because a z-index on a static element
   does nothing and the omission would put the clip over the headline. */
.hero > .hero__mask { z-index: 1; }
.hero > .container,
.hero > .opacity-mask,
.hero__form { position: relative; z-index: 2; }


/* ==========================================================================
   THE HERO, RECOMPOSED TO THE CLUSTER'S SHAPE
   --------------------------------------------------------------------------
   Brought into line with the sibling properties, Staten Island in particular,
   which the operator named as the reference. What changed, and why each one is
   presentation rather than meaning:

   THE PLATE IS GONE. The copy sat on a translucent panel that had grown its own
   diagonal fade. The siblings put the words straight onto the darkened frame, so
   the ground moves from the panel into the scrim and the photograph is no longer
   looking through a box. The scrim below is correspondingly heavier under the
   copy: legibility is bought back in the same move that removed what supplied it.

   THE HEADLINE IS SENTENCE CASE. It was uppercase at weight 700. The cluster sets
   its H1 at weight 900 in sentence case, which is both more legible at a glance
   and materially narrower per character. The H1 TEXT is untouched - case here is
   a text-transform, and what the headline says belongs to the build, not to this.

   THE EYEBROW is the registry's own location string in the brand's hazard, which
   is how the siblings open the hero. It asserts nothing that is not already in
   the schema and the footer.

   THE SECOND BUTTON IS GONE, from the markup rather than from the paint. The hero
   holds a form now, and a form beside a button is two answers to "what do I do
   next". Its destination is reachable from the header, the next section and the
   footer.
   ========================================================================== */
.hero--split .container { padding-top: 34px; padding-bottom: 34px; }

/* Heavier under the copy than the plate-era scrim, and still directional rather
   than a flat veil - the reason the earlier pass gave for the gradient holds, and
   only the weights move. The copy column now has no ground of its own, so this is
   the only thing between white type and whatever the frame is showing. */
.hero--split::after {
  background:
    linear-gradient(100deg,
      rgba(9, 11, 13, .88) 0%,
      rgba(9, 11, 13, .80) 36%,
      rgba(9, 11, 13, .58) 64%,
      rgba(9, 11, 13, .46) 100%),
    rgba(12, 14, 16, .24);
}

/* One column until there is genuinely room for two. Below the breakpoint the form
   follows the copy, which is the order a screen reader and a keyboard already get,
   so nothing depends on the grid existing. */
.hero-grid { display: grid; grid-template-columns: 1fr; gap: 1.6rem; align-items: center; }
.hero-copy { color: var(--white); min-width: 0; }

.hero-eyebrow {
  display: inline-block;
  background: var(--hazard); color: var(--ink);
  font-size: .72rem; font-weight: 900; letter-spacing: .16em; text-transform: uppercase;
  padding: 6px 12px; border-radius: 2px;
  margin: 0 0 18px;
}

.hero-copy h1 {
  color: var(--white);
  font-size: clamp(28px, 3.6vw, 40px);
  font-weight: 900;
  text-transform: none;
  letter-spacing: -.015em;
  line-height: 1.08;
  margin: 0 0 12px;
}

.hero-standfirst {
  font-size: 17px; line-height: 1.65;
  color: rgba(255, 255, 255, .9);
  margin: 0 0 18px;
  max-width: 46ch;
}

/* The trust line. Short facts and a tick, never a badge graphic: a drawn crest
   asserts a credential the way a certificate does, and what stands behind an entry
   here is a record in data/site-config.json and nothing more. */
.hero-trust {
  display: flex; flex-wrap: wrap; gap: 8px 18px;
  list-style: none; margin: 0 0 20px; padding: 0;
}
.hero-trust li {
  display: inline-flex; align-items: center; gap: 7px;
  margin: 0;
  font-size: 14px; font-weight: 700; letter-spacing: .01em;
  color: var(--white);
}
.hero-trust li::before {
  content: "\2713";
  color: var(--hazard);
  font-size: 15px; font-weight: 900; line-height: 1;
}

/* THE CTA ROW. The hub property runs its call button and a secondary link side by
   side and this matches that shape, with one difference that is structural rather
   than stylistic: this Point has no public_phone yet, so the row may hold one
   control or two and has to look deliberate either way.

   Phoneless it holds the secondary alone, and the secondary carries the keyline
   treatment rather than being promoted - the form beside it in the right-hand
   column is the primary path, and promoting the link would set up exactly the
   competition the earlier pass removed it to avoid. With a phone the call button
   comes FIRST in source order and takes the filled treatment, so the primary is
   the first thing in the row for a reader and for a screen reader alike.

   `align-items: center` rather than stretch: the call button is two stacked lines
   and the secondary is one, so stretching would make the shorter control grow to
   match a height it has no content for. */
.hero-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin: 0 0 4px; }
.hero-cta__secondary { border-width: 2px; }

/* Call or type, and the "or" says so. Renders only once the Registry carries a
   public_phone, which is the same condition every other call surface on this site
   already branches on: with no number there is no "or", because there is no second
   path for the sentence to point at. The number is the button's own second line
   rather than a separate link, so the whole control is one tap target. */
.hero-call-btn {
  display: inline-flex; flex-direction: column; align-items: flex-start;
  gap: 2px; padding: 11px 22px;
  background: var(--hazard); color: var(--graphite); border-color: var(--hazard);
  box-shadow: var(--lift-2);
}
.hero-call-btn:hover, .hero-call-btn:focus {
  background: var(--white); border-color: var(--white); color: var(--graphite);
}
.hero-call-kicker {
  font-size: .68rem; font-weight: 900; letter-spacing: .14em; text-transform: uppercase;
  opacity: .82;
}
.hero-call-number { font-size: 1.15rem; font-weight: 900; letter-spacing: -.01em; }
.hero-call-or { margin: 10px 0 0; font-size: 14px; color: rgba(255, 255, 255, .82); }

@media (min-width: 62rem) {
  /* The copy takes the wider half so the headline keeps a sensible measure, and
     the form is capped rather than allowed to grow with the viewport, which is
     what stops it reading as the subject of the page on a wide monitor. */
  .hero-grid { grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr); gap: 2.75rem; }
  .hero--split .container { padding-top: 44px; padding-bottom: 44px; }
  .hero__form { justify-self: end; max-width: 26.5rem; }
}


/* -------- R.12 THE REDUCED-MOTION PATH, RESTATED ------------------------
   THIS BLOCK IS LOAD-BEARING AND MUST STAY LAST IN THIS FILE.

   The stylesheet already carries `@media (prefers-reduced-motion: reduce)
   { * { transition: none !important; animation: none !important } }` further up.
   That block is NOT enough and would have shipped a broken page: it resets
   transition and animation, and it does NOT reset `opacity` or `transform`.
   Every reveal above arms itself at `opacity: 0`, so a reader who asked for less
   motion would have got a page whose content was permanently invisible, with the
   transition that was supposed to reveal it switched off.

   That is also the exact condition `render-probe.mjs` raises as a hard INVARIANT
   rather than a suspicion, because the probe captures WITH the preference
   emulated — so the screenshots meant to prove this design would have been
   screenshots of the defect, and every one of them would have been blank below
   the fold.

   `transform: none` is the identity transform, which is precisely what the drawn
   rules want: a bar that never animates is a bar at full width. */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal],
  .js h1[data-reveal],
  .js h2[data-reveal],
  .js .card[data-reveal],
  .js .place[data-reveal],
  .js .step[data-reveal],
  .js .column[data-reveal],
  .js .area[data-reveal],
  .js .coverage__item[data-reveal],
  .js .faq details[data-reveal],
  .js .split__media[data-reveal],
  .js .figure[data-reveal],
  .js .statement__plate[data-reveal] { opacity: 1 !important; transform: none !important; }

  .js .column::before,
  .js .section > .container > h2::after,
  .js .section > .container > .measure > h2::after,
  .js .split h2::after { transform: none !important; }

  .hero::before,
  .pagehead::before,
  .band::before { animation: none !important; transform: none !important; }

  /* AND THE HOVER TRAVEL, CONSISTENTLY. Suppressing the transform on every
     reveal target above already killed the card and tile lift here, because
     those rules carry !important. The button's lift is NOT a reveal target and
     so survived, which left one component still displacing itself on hover
     while its neighbours did not — an inconsistency introduced by this pass and
     caught by measuring the reduced-motion state rather than by reading it.

     Nothing about the affordance is lost. Every one of these still answers a
     pointer with its elevation and its colour; only the displacement goes. */
  .btn:hover, .btn:focus-visible, .btn:active { transform: none !important; }
}
