/* ==========================================================================
   01 HERO — full-bleed photograph, centred type, static instrument readout.
   Above the fold: loads render-blocking. 1 image (the LCP element).
   ========================================================================== */

.hero {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  /* svh, with a vh line under it. Safari before 15.4 does not know the unit
     and an unknown unit invalidates the WHOLE declaration, so a lone svh line
     ships no min-height at all here — and, forty lines down, no height cap on
     .hero__media, which is the rule that keeps the photograph an LCP
     candidate. Old engines take the vh line, new ones overwrite it; the
     difference between the two units is the collapsing mobile toolbar, which
     is precisely the case those engines predate. */
  min-height: 88vh;
  min-height: 88svh;
  margin-block-start: calc(var(--header-h) * -1);
  padding-block: calc(var(--header-h) + var(--space-3xl)) var(--space-2xl);
  overflow: hidden;
}

/* LCP. Chrome drops an <img> from LCP candidacy once its box is as large as the
   viewport — it reads it as a page background — and every hero on this site is
   content-driven taller than the fold at some supported height, so the LCP
   element was the sub-heading and not the photograph. The rule is area, not
   position: measured at 485px wide against a 900.4px-tall image, a 900px-tall
   viewport (436,500px2) emits no image entry and a 901px one (436,985px2) emits
   an entry of 436,694px2. Offsetting the image downward instead was tried and
   does not work — Lighthouse's trace carried no image candidate at all —
   because the box stays the same size.

   So the photograph has to be shorter than the fold, at EVERY width. The cap
   was scoped below 1024 when it was written because at 1440x900 it took 252px
   off the bottom of the untightened hero and put a seam across the readout;
   the desktop rhythm below now removes that, so the cap is unconditional.
   Measured 2026-09-06: the home hero was 1161px tall against a 900px viewport
   and timed h1.hero__title; every service/city hero measured 790-842px, which
   passes at 900 but fails a 1440x756 laptop. One rule fixes both.

   It caps the MEDIA BOX, not the img inside it: the specimen bezel and the
   spec chip belong to the photograph, so they travel with its bottom edge
   rather than framing the dark band underneath. min() means the cap is inert
   on any hero already shorter than the fold — at 1920x1080 nothing here
   applies at all. */
.hero__media {
  position: absolute;
  inset: 0 0 auto;
  height: min(100%, calc(100vh - var(--space-2xs)));
  height: min(100%, calc(100svh - var(--space-2xs)));
  z-index: var(--z-media);
  background: var(--surface-media);
}
/* the scrim already carries the tint; .media's own overlay would double it.
   The specimen bezel on ::after stays. */
.hero__media::after { background: none; }
.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 58%;
}

/* The negative top margin exists to slide the hero under a FIXED header. With
   no script and below 1024 the header is a block in the flow instead (see
   shell.css), and the pull would drag the photograph over the navigation. */
@media (max-width: 1023px) {
  html:not(.js) .hero { margin-block-start: 0; padding-block-start: var(--space-2xl); }
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: var(--z-scrim);
  background: var(--scrim-hero);
  pointer-events: none;
}

.hero__inner { position: relative; z-index: var(--z-content); }

.hero__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  text-align: center;
  max-width: var(--width-measure);
  margin-inline: auto;
}

.hero__title {
  font-size: var(--text-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  color: var(--text-on-media);
  text-wrap: balance;
}

.hero__sub {
  font-size: var(--text-lead);
  line-height: var(--leading-body);
  color: var(--text-secondary);
  max-width: var(--width-prose);
}

.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-xs);
  margin-block-start: var(--space-2xs);
}

.hero__meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-xs) var(--space-md);
  margin-block-start: var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.hero__meta li { display: flex; align-items: center; gap: var(--space-2xs); }
.hero__meta li::before {
  content: "";
  width: var(--space-3xs);
  height: var(--space-3xs);
  border-radius: var(--radius-round);
  background: var(--surface-accent);
}

/* --------------------------------------------------------------------------
   READOUT — the instrument corner. Static: the vocabulary is content, not
   choreography, so it reads identically with JS off.
   -------------------------------------------------------------------------- */
.hero__readout {
  margin-block-start: var(--space-xl);
  margin-inline: auto;
  max-width: var(--card-min-wide);
  padding: var(--card-pad);
  border: var(--border-width-hair) solid var(--border-soft);
  border-radius: var(--radius-card);
  clip-path: var(--chamfer-clip);
  background: var(--chamfer-edge), var(--surface-header);
  text-align: start;
}

.hero__readout-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding-block-end: var(--space-2xs);
  border-block-end: var(--border-width-hair) solid var(--border-hairline);
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-faint);
}
.hero__readout-live { color: var(--text-muted); }

.hero__readout-rows { display: grid; gap: var(--space-2xs); margin-block-start: var(--space-2xs); }
.hero__readout-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-sm);
  align-items: baseline;
}
.hero__readout-key {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-faint);
}
.hero__readout-val {
  font-family: var(--font-mono);
  font-size: var(--text-body-sm);
  font-weight: var(--weight-medium);
  color: var(--text-primary);
  text-align: end;
}
.hero__readout-val--depth { color: var(--text-accent); }
.hero__readout-note {
  margin-block-start: var(--space-2xs);
  font-size: var(--text-micro);
  line-height: var(--leading-snug);
  color: var(--text-faint);
}

@media (min-width: 1024px) {
  .hero { min-height: 94vh; min-height: 94svh; }
  .hero__inner { display: grid; grid-template-columns: 1fr auto; align-items: end; gap: var(--grid-gap); }
  .hero__body { grid-column: 1 / -1; }
  .hero__readout { margin-block-start: var(--space-2xl); margin-inline: 0 0; grid-column: 2; justify-self: end; }
}

/* --------------------------------------------------------------------------
   THE HOME HERO'S DESKTOP RHYTHM, TIGHTENED — the other half of the LCP fix.
   The cap above is what makes the photograph an LCP candidate; this is what
   keeps the readout ON the photograph while it happens.

   Measured at 1440x900 before: 1161px of hero against a 900px fold, so the cap
   cut the plate at 892 and the readout, which ends at 1098, straddled the cut
   with 206px of instrument floating on flat ground. Tightened: 929px of hero,
   the readout ends at 897, five pixels inside the cut, and the remaining band
   is 37px — read as the hero's own bottom margin rather than as a seam. At
   1920x1080 the hero is shorter than the cap and there is no band at all.

   Nothing here shrinks a type size, a measure or a control: the 232px comes
   entirely from padding, gaps and one 64px offset that only ever existed to
   push the readout down a viewport that no longer has the room. Scoped off
   .hero--svc — the service and city heroes are 700-842px, already inside the
   fold at 900, and their approved composition is not part of this problem.
   -------------------------------------------------------------------------- */
@media (min-width: 1024px) {
  .hero:not(.hero--svc) { padding-block: calc(var(--header-h) + var(--space-lg)) var(--space-lg); }
  .hero:not(.hero--svc) .hero__body { gap: var(--space-sm); }
  .hero:not(.hero--svc) .hero__ctas { margin-block-start: 0; }
  .hero:not(.hero--svc) .hero__meta { margin-block-start: var(--space-2xs); }
  .hero:not(.hero--svc) .hero__inner { row-gap: var(--space-sm); }
  .hero:not(.hero--svc) .hero__readout { margin-block-start: 0; }
}

/* --------------------------------------------------------------------------
   SERVICE-PAGE HERO — same plate, left-aligned. Shorter than the home hero:
   a service page has an argument below the fold and must not spend a full
   viewport on the title. The h1 stays at --text-display; dropping to --text-h2
   to fit a longer sentence would fail the 6:1 h1:body contrast rule.
   -------------------------------------------------------------------------- */
.hero--svc { min-height: 62vh; min-height: 62svh; }
.hero--svc .hero__body { align-items: flex-start; text-align: start; margin-inline: 0; max-width: none; }
.hero--svc .hero__ctas,
.hero--svc .hero__meta { justify-content: flex-start; }
.hero--svc .hero__sub { max-width: var(--width-measure); }
.hero--svc .hero__media img { object-position: center 45%; }

/* The service heroes are brighter under the title band than hero-bay is, and
   .hero__media::after is set to `background: none` above so the home scrim is
   not doubled. Measured per CLAUDE.md "Measuring contrast over photography":
   without this layer the h1 over svc-hero-ceramic sampled 7.47% of background
   pixels below 4.5:1 against an 11.96:1 mean, which fails the 0.5% floor. The
   remedy the spec names is an overlay, never a text colour change. */
.hero--svc .hero__media::after { background: var(--overlay-media-heavy); }

@media (min-width: 1024px) { .hero--svc { min-height: 68vh; min-height: 68svh; } }
