/* ==========================================================================
   Rooftop HVAC — Design System v3

   Discipline, not variety. Everything below obeys three rules:

   1. SPACING — an 8px grid with exactly seven steps. No other values exist.
   2. TYPE    — fixed sizes at two breakpoints. No clamp(), no fluid scaling.
                Fluid type never lands on a consistent value, which is what
                made v2 read as arbitrary.
   3. REPEATS — one section padding, one card padding, one grid gap, used
                everywhere without exception.

   Colors sampled from the supplied logo (PRD D-1).
   ========================================================================== */

:root {
  /* ---- Brand ---- */
  --navy:      #000122;
  --navy-800:  #0A1533;
  --navy-700:  #142549;
  --blue:      #2F5E96;
  --blue-600:  #3A6DA8;
  --blue-500:  #368ABF;
  --blue-300:  #8CBBDC;
  --blue-200:  #A8CFE8;   /* on-photo text only — see the hero scrim note */
  --blue-100:  #E7F0F8;
  --blue-50:   #F3F8FC;

  --alert:      #D9541A;
  --alert-dark: #B23F0D;
  --alert-50:   #FDF3EE;

  /* ---- Neutrals ---- */
  --white:   #FFFFFF;
  --grey-50: #F6F8FA;
  --grey-100:#EBEFF4;
  --grey-200:#DCE2EA;
  --grey-300:#B6C0CD;
  --grey-500:#77828F;
  --grey-600:#5A6572;
  --grey-700:#3E4854;
  --ink:     #131A24;

  --note-bg:     #FBF8F0;
  --note-border: #DFD3AE;
  --note-ink:    #6E5F2C;

  /* ---- Spacing: 8px grid, seven steps. Nothing else. ---- */
  --s1: 8px;
  --s2: 16px;
  --s3: 24px;
  --s4: 32px;
  --s5: 48px;
  --s6: 64px;
  --s7: 96px;

  /* ---- Repeating values ---- */
  /* Section padding applies twice between any two sections, so this value is
     doubled in the gap a reader actually sees. At 72px that gap was 144px and
     read as a break in the page rather than a division of it. 56px gives 112px.
     Both values are multiples of 8. */
  --section-y:  40px;        /* 40px mobile, 56px desktop — see media query */
  --card-pad:   var(--s4);   /* 32px, every card, always */
  --gap:        var(--s3);   /* 24px, every grid, always */
  --gutter:     var(--s3);

  --maxw: 1160px;
  --measure: 66ch;

  --radius: 6px;
  --radius-lg: 10px;

  --ring: 0 0 0 3px rgba(47, 94, 150, .16);
  --shadow-card: 0 1px 2px rgba(19, 26, 36, .04), 0 4px 16px rgba(19, 26, 36, .06);
  --shadow-lift: 0 2px 4px rgba(19, 26, 36, .05), 0 12px 32px rgba(19, 26, 36, .10);

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  --font-head: "Inter Tight", "Inter", -apple-system, BlinkMacSystemFont, Arial, sans-serif;

  --ease: cubic-bezier(.4, 0, .2, 1);
}

@media (min-width: 768px) {
  :root { --section-y: 56px; --gutter: var(--s4); --gap: var(--s4); }
}

/* ==========================================================================
   Reset
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 28px;          /* on the grid */
  color: var(--grey-700);
  background: var(--white);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, video, svg { max-width: 100%; height: auto; display: block; }
a { color: var(--blue); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--navy-700); }

/* ==========================================================================
   Type — fixed steps. Mobile first, one bump at 768px.
   Line heights are multiples of 4 so text sits on the grid.
   ========================================================================== */
h1, h2, h3, h4 {
  font-family: var(--font-head);
  color: var(--navy);
  margin: 0 0 var(--s2);
  font-weight: 600;
  text-wrap: balance;
}
h1 { font-size: 34px; line-height: 40px; letter-spacing: -.025em; font-weight: 700; }
h2 { font-size: 26px; line-height: 32px; letter-spacing: -.02em; }
h3 { font-size: 19px; line-height: 28px; letter-spacing: -.01em; }
h4 { font-size: 16px; line-height: 24px; letter-spacing: -.005em; }

@media (min-width: 768px) {
  h1 { font-size: 52px; line-height: 56px; }
  h2 { font-size: 36px; line-height: 44px; }
  h3 { font-size: 20px; line-height: 28px; }
}

p  { margin: 0 0 var(--s3); max-width: var(--measure); }
ul, ol { margin: 0 0 var(--s3); padding-left: 24px; max-width: var(--measure); }
/* A trailing bottom margin stacks on top of the section padding, so a section
   ending in a list sat 24px lower than one ending in a paragraph. This was
   zeroed for p but never for lists, which is where the uneven section gaps
   came from. */
p:last-child, ul:last-child, ol:last-child { margin-bottom: 0; }
li { margin-bottom: var(--s1); }
li:last-child { margin-bottom: 0; }
strong, b { font-weight: 600; color: var(--ink); }

.eyebrow {
  font-family: var(--font-head); font-weight: 600;
  font-size: 13px; line-height: 16px;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--blue-600); margin: 0 0 var(--s2);
}

/* ==========================================================================
   Accessibility
   ========================================================================== */
:focus-visible { outline: 2px solid var(--blue-500); outline-offset: 3px; border-radius: 3px; }
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--navy); color: #fff; padding: var(--s2) var(--s3); font-weight: 600;
}
.skip-link:focus { left: 0; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* ==========================================================================
   Layout — one section padding, one gap, no exceptions
   ========================================================================== */
.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); }

.section { padding: var(--section-y) 0; }
.section--tight { padding: var(--section-y) 0; }   /* deliberately identical */

.section--grey { background: var(--grey-50); }
.section--blue { background: var(--blue-50); }
.section--navy { background: var(--navy); color: #B4C1D6; }
.section--navy h2, .section--navy h3, .section--navy h4 { color: #fff; }
.section--navy strong { color: #fff; }
.section--navy a { color: var(--blue-300); }
.section--navy .eyebrow { color: var(--blue-300); }

.section__intro { max-width: 620px; margin-bottom: var(--s4); }
.section__intro h2 { margin-bottom: var(--s2); }
/* :not(.eyebrow) is load-bearing. The eyebrow is also a <p>, so a bare
   `.section__intro p` outweighs `.eyebrow` (0,1,1 vs 0,1,0) and was zeroing its
   margin and overriding its colour — eyebrows inside an intro sat flush against
   the heading in grey, while the same pair elsewhere had 16px and read blue. */
.section__intro p:not(.eyebrow) { color: var(--grey-600); margin-bottom: 0; }
.section--navy .section__intro p:not(.eyebrow) { color: #8D9CB5; }

.grid { display: grid; gap: var(--gap); }
/* A photo row that follows body copy directly, with no heading between them.
   Without this it inherits only the paragraph's 24px and sits too tight. */
.media-row { margin-top: var(--s4); }
@media (min-width: 700px)  { .grid--2, .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) {
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
  .grid--4 { grid-template-columns: repeat(4, 1fr); }
}

/* ==========================================================================
   Carousel — three cards at a time, arrows either side

   Built on native scroll-snap rather than transforms, so it works with no
   JavaScript at all: without JS it is simply a horizontal scroller you can
   swipe or shift-scroll, which is the behaviour a touch user expects anyway.
   The arrow buttons only add keyboard and mouse affordances on top.
   ========================================================================== */
.carousel { position: relative; }
.carousel__track {
  display: grid; grid-auto-flow: column; gap: var(--gap);
  grid-auto-columns: calc((100% - var(--gap) * 2) / 3);
  overflow-x: auto; scroll-snap-type: x mandatory;
  list-style: none; margin: 0; padding: 0 0 var(--s2); max-width: none;
  scrollbar-width: none;
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__item { scroll-snap-align: start; margin: 0; min-width: 0; }
.carousel__item > .card { height: 100%; }

@media (max-width: 900px) { .carousel__track { grid-auto-columns: calc((100% - var(--gap)) / 2); } }
@media (max-width: 640px) { .carousel__track { grid-auto-columns: 86%; } }

/* The button keeps a 44px hit area for touch and keyboard, but paints nothing —
   no circle, no border, no fill. Only the chevron is visible. */
.carousel__btn {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  background: none; border: 0; padding: 0;
  color: var(--navy);
  cursor: pointer;
  transition: color .16s var(--ease), opacity .16s var(--ease);
}
/* Without a chip behind it the chevron has to carry itself, so it is drawn
   heavier, and it has to be re-lit on dark sections or it disappears into them.
   The projects carousel sits on .section--navy. */
.carousel__btn svg {
  width: 26px; height: 26px; fill: none; stroke: currentColor;
  stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round;
}
.carousel__btn:hover { color: var(--blue); }
.section--navy .carousel__btn { color: #fff; }
.section--navy .carousel__btn:hover { color: var(--blue-200); }

.carousel__btn--prev { left: calc(var(--s6) * -1); }
.carousel__btn--next { right: calc(var(--s6) * -1); }
/* At the ends the button dims rather than hiding, so the control never moves
   position as you page through. */
.carousel__btn[disabled] { opacity: .25; cursor: default; }

/* Below ~1180px there is no room outside the track, so the carousel reserves
   its own gutters and the arrows sit in them — overlapping a card would be
   worse now that the chevron has no chip to separate it from the artwork. */
@media (max-width: 1180px) and (min-width: 641px) {
  .carousel { padding-left: 44px; padding-right: 44px; }
  .carousel__btn--prev { left: 0; }
  .carousel__btn--next { right: 0; }
}
@media (max-width: 640px) { .carousel__btn { display: none; } }

/* Project blocks on the index are adjacent siblings with nothing between them,
   so the next heading landed directly under the previous block's button and read
   as part of it. The rule is scoped to .project-list rather than applied to
   .split generally — other pages use .split for unrelated two-column layouts. */
.project-list > article + article {
  margin-top: var(--s6);
  padding-top: var(--s6);
  border-top: 1px solid var(--grey-100);
}

.split { display: grid; gap: var(--s5); align-items: start; }
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; gap: var(--s6); }
  .split--wide-left  { grid-template-columns: 1.5fr 1fr; }
  .split--wide-right { grid-template-columns: 1fr 1.5fr; }
}

/* ==========================================================================
   Buttons — one height, one padding
   ========================================================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s1);
  font-family: var(--font-head); font-weight: 600; font-size: 16px; line-height: 24px;
  padding: 0 var(--s3); height: 48px;
  border-radius: var(--radius); border: 1px solid transparent;
  text-decoration: none; cursor: pointer; text-align: center; white-space: nowrap;
  transition: background .16s var(--ease), border-color .16s var(--ease), color .16s var(--ease);
}
.btn--primary  { background: var(--blue); color: #fff; }
.btn--primary:hover { background: var(--navy-700); color: #fff; }
.btn--alert    { background: var(--alert); color: #fff; }
.btn--alert:hover { background: var(--alert-dark); color: #fff; }
.btn--ghost    { background: transparent; color: #fff; border-color: rgba(255,255,255,.32); }
.btn--ghost:hover { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.6); color: #fff; }
.btn--outline  { background: #fff; color: var(--navy); border-color: var(--grey-200); }
.btn--outline:hover { border-color: var(--blue-500); color: var(--blue); }
.btn--lg { height: 56px; padding: 0 var(--s4); font-size: 17px; }
.btn--block { display: flex; width: 100%; }

/* ==========================================================================
   Header — logo leads. Bar height is set by the logo, not by padding.
   ========================================================================== */
.utility {
  background: var(--navy); color: #97A6BF;
  font-size: 14px; line-height: 20px; text-align: center;
  padding: var(--s1) var(--gutter);
}
.utility a { color: #fff; font-weight: 600; text-decoration: none; white-space: nowrap; }
.utility a:hover { text-decoration: underline; }

.site-header {
  position: sticky; top: 0; z-index: 100;
  background: #fff; border-bottom: 1px solid var(--grey-100);
}
.header-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s3); padding: var(--s2) var(--gutter);
  max-width: var(--maxw); margin: 0 auto;
}
.brand { display: block; flex-shrink: 0; line-height: 0; }
.brand img { height: 48px; width: auto; }
@media (min-width: 768px) { .brand img { height: 60px; } }

.nav { display: none; }
.nav ul { display: flex; align-items: center; gap: 2px; list-style: none; margin: 0; padding: 0; max-width: none; }
.nav li { margin: 0; }
.nav a {
  display: block; padding: var(--s1) 14px;
  font-family: var(--font-head); font-weight: 500; font-size: 16px; line-height: 24px;
  color: var(--grey-700); text-decoration: none; border-radius: var(--radius);
  /* Two-word items were breaking mid-label — "Our / Work" stacked over two
     lines — which made the whole bar look broken rather than just tight. */
  white-space: nowrap;
}
.nav a:hover { color: var(--navy); background: var(--grey-50); }
.nav a[aria-current="page"] { color: var(--blue); }

.header-cta { display: none; align-items: center; gap: var(--s3); }
.header-phone {
  font-family: var(--font-head); font-weight: 600; font-size: 18px; line-height: 20px;
  color: var(--navy); text-decoration: none; white-space: nowrap;
}
.header-phone:hover { color: var(--blue); }
.header-phone small {
  display: block; font-size: 12px; line-height: 16px; font-weight: 500;
  letter-spacing: .08em; text-transform: uppercase; color: var(--grey-500);
}

.nav-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 48px; height: 48px; background: transparent;
  border: 1px solid var(--grey-200); border-radius: var(--radius);
  cursor: pointer; color: var(--navy); flex-shrink: 0;
}
.nav-toggle span { display: block; width: 20px; height: 2px; background: currentColor; position: relative; }
.nav-toggle span::before, .nav-toggle span::after {
  content: ""; position: absolute; left: 0; width: 20px; height: 2px; background: currentColor;
}
.nav-toggle span::before { top: -6px; } .nav-toggle span::after { top: 6px; }

.mobile-nav { display: none; border-top: 1px solid var(--grey-100); background: #fff; }
.mobile-nav.is-open { display: block; }
.mobile-nav ul { list-style: none; margin: 0; padding: 0 var(--gutter) var(--s3); max-width: none; }
.mobile-nav li { margin: 0; }
.mobile-nav a {
  display: block; padding: var(--s2) 0;
  font-family: var(--font-head); font-weight: 500; font-size: 17px;
  color: var(--navy); text-decoration: none; border-bottom: 1px solid var(--grey-100);
}

@media (min-width: 1040px) {
  .nav, .header-cta { display: flex; }
  .nav-toggle { display: none; }
  .mobile-nav { display: none !important; }
}

/* Mobile action bar */
.action-bar {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 99;
  display: grid; grid-template-columns: repeat(2, 1fr);  /* Call + Request; the line takes no SMS */
  background: var(--navy); border-top: 1px solid rgba(255,255,255,.1);
  padding-bottom: env(safe-area-inset-bottom);
}
.action-bar a {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; height: 56px; color: #D5DDEA; text-decoration: none;
  font-family: var(--font-head); font-weight: 500; font-size: 12px; line-height: 16px;
  letter-spacing: .05em; text-transform: uppercase;
}
.action-bar a.is-alert { background: var(--alert); color: #fff; }
.action-bar svg { width: 18px; height: 18px; fill: currentColor; }
@media (max-width: 1039px) { body { padding-bottom: 56px; } }
@media (min-width: 1040px) { .action-bar { display: none; } }

/* ==========================================================================
   Hero
   ========================================================================== */
.hero { position: relative; background: var(--navy); color: #fff; overflow: hidden; }
.hero__media { position: absolute; inset: 0; }
.hero__media img, .hero__media video { width: 100%; height: 100%; object-fit: cover; }
/* Two-layer scrim. The horizontal layer keeps the headline readable on the left
   while letting the photograph carry the rest of the frame; the vertical layer
   seats the header above and the buttons below.

   These stops are not guesses. They were solved against the actual pixels of
   the hero photograph, sampling only the bounding boxes of the three text
   elements, and they are lighter than the previous set at every stop. Measured
   worst-case contrast over rtu-crane-set-rooftop:

     eyebrow  --blue-200  13px  5.01:1   (needs 4.5 — small text)
     h1       #fff        52px  5.58:1   (needs 3.0 — large text)
     .hero__sub --sub     19px  6.09:1   (needs 4.5 — 19px is NOT large text)

   The binding constraint is the eyebrow, not the headline, and the worst point
   is around x=48% where the gradient has fallen off but the subhead has not yet
   ended. Re-measure before lightening further, and re-measure if the hero photo
   changes — a brighter sky moves all three numbers. */
.hero__media::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(90deg,
      rgba(0,1,34,.80) 0%, rgba(0,1,34,.74) 35%, rgba(0,1,34,.48) 58%,
      rgba(0,1,34,.20) 78%, rgba(0,1,34,.08) 100%),
    linear-gradient(180deg,
      rgba(0,1,34,.24) 0%, rgba(0,1,34,0) 30%, rgba(0,1,34,.32) 100%);
}
/* Narrow screens: text spans the full width, so the scrim has to close up.
   Held deliberately conservative — the solve above was run at desktop width. */
@media (max-width: 899px) {
  .hero__media::after {
    background:
      linear-gradient(180deg, rgba(0,1,34,.78) 0%, rgba(0,1,34,.82) 55%, rgba(0,1,34,.88) 100%);
  }
}
.hero__inner {
  position: relative; padding: var(--section-y) var(--gutter);
  max-width: var(--maxw); margin: 0 auto;
}
.hero__content { max-width: 700px; }
/* The hero is not .section--navy, so the eyebrow was falling through to the
   default --blue-600 — a mid blue chosen for white backgrounds. On the scrim
   that measured 1.88:1 against a required 4.5:1, i.e. all but invisible. */
.hero .eyebrow { color: var(--blue-200); }
.hero h1 { color: #fff; margin-bottom: var(--s3); }
.hero h1 em { font-style: normal; color: var(--blue-300); }
.hero__sub { font-size: 19px; line-height: 32px; color: #C3CFE2; margin-bottom: var(--s5); max-width: 30em; }
.hero__cta { display: flex; flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s6); }

.trust-strip {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s4);
  padding-top: var(--s5); border-top: 1px solid rgba(255,255,255,.16); max-width: 700px;
}
.trust-strip strong {
  display: block; font-family: var(--font-head); font-size: 26px; line-height: 32px;
  font-weight: 600; color: #fff; letter-spacing: -.02em;
}
.trust-strip span { font-size: 14px; line-height: 20px; color: #7E8FAB; }
@media (min-width: 768px) { .trust-strip { grid-template-columns: repeat(4, 1fr); } }

/* ==========================================================================
   Cards — one padding value
   ========================================================================== */
.card {
  background: #fff; border: 1px solid var(--grey-100); border-radius: var(--radius-lg);
  overflow: hidden; display: flex; flex-direction: column;
  transition: box-shadow .2s var(--ease), border-color .2s var(--ease);
}
.card:hover { box-shadow: var(--shadow-lift); border-color: var(--grey-200); }
/* position: relative is load-bearing — the image inside is absolutely
   positioned (see "Job photography" below) and without a positioned parent it
   escapes the card entirely. */
.card__media {
  position: relative; aspect-ratio: 3 / 2; overflow: hidden;
  background: var(--grey-50);
}
.card__body { padding: var(--card-pad); display: flex; flex-direction: column; flex: 1; }
.card__body h3 { margin-bottom: var(--s1); }
.card__body p { color: var(--grey-600); font-size: 16px; line-height: 26px; flex: 1; margin-bottom: var(--s3); }
.card__link {
  font-family: var(--font-head); font-weight: 600; font-size: 15px; line-height: 24px;
  color: var(--blue); text-decoration: none; display: inline-flex; align-items: center; gap: 6px;
}
.card__link::after { content: "→"; transition: transform .16s var(--ease); }
.card:hover .card__link::after { transform: translateX(3px); }

/* Building-type tiles. These were fixed-height boxes holding nothing but a
   label, which left most of each box empty and made six identical rectangles
   the reader had no reason to look at. Each now carries an icon and one line of
   specifics, so the block says something instead of listing something — and the
   height comes from the content rather than a magic 72px. */
.tiles { list-style: none; padding: 0; margin: 0; max-width: none; }
.tiles .tile { margin: 0; }

.tile {
  display: flex; align-items: flex-start; gap: var(--s2);
  padding: var(--s3);
  background: #fff; border: 1px solid var(--grey-100); border-radius: var(--radius);
  text-decoration: none; color: var(--navy);
  transition: border-color .16s var(--ease), box-shadow .16s var(--ease);
}
.tile__icon {
  width: 24px; height: 24px; flex: none; margin-top: 2px;
  fill: none; stroke: var(--blue); stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.tile strong {
  display: block; color: var(--navy);
  font-family: var(--font-head); font-weight: 600; font-size: 16px; line-height: 24px;
  margin-bottom: 2px;
}
.tile span { display: block; color: var(--grey-600); font-size: 15px; line-height: 22px; }
/* Only the linked variant reacts to the cursor. These are plain labels, so they
   must not look clickable. */
a.tile:hover { border-color: var(--blue-300); box-shadow: var(--shadow-card); color: var(--navy); }
li.tile, span.tile { cursor: default; }

.checklist { list-style: none; padding: 0; }
.checklist li { position: relative; padding-left: var(--s4); margin-bottom: var(--s2); }
.checklist li::before {
  content: ""; position: absolute; left: 2px; top: 10px;
  width: 12px; height: 6px;
  border-left: 2px solid var(--blue-500); border-bottom: 2px solid var(--blue-500);
  transform: rotate(-45deg);
}
.section--navy .checklist li::before { border-color: var(--blue-300); }

.steps { list-style: none; padding: 0; counter-reset: step; max-width: var(--measure); }
.steps li { position: relative; padding-left: var(--s6); margin-bottom: var(--s4); counter-increment: step; }
.steps li:last-child { margin-bottom: 0; }
.steps li::before {
  content: counter(step);
  position: absolute; left: 0; top: 0;
  font-family: var(--font-head); font-weight: 600; font-size: 15px;
  color: var(--blue); background: var(--blue-100);
  width: var(--s4); height: var(--s4); border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.steps li strong {
  display: block; color: var(--navy); font-family: var(--font-head);
  font-weight: 600; font-size: 17px; line-height: 28px;
}

/* ==========================================================================
   Build annotations
   ========================================================================== */
.tbd {
  background: var(--note-bg); border-bottom: 1px dashed var(--note-border);
  color: var(--note-ink); font-size: .95em; padding: 0 4px;
}
.tbd-block {
  background: var(--note-bg); border-left: 2px solid var(--note-border);
  color: var(--note-ink); padding: var(--s2) var(--s3);
  margin: 0 0 var(--s4); font-size: 15px; line-height: 24px;
  max-width: var(--measure); border-radius: 0;
}
.tbd-block strong {
  display: block; font-family: var(--font-head); color: var(--note-ink);
  text-transform: uppercase; letter-spacing: .1em; font-size: 12px; line-height: 16px;
  font-weight: 600; margin-bottom: var(--s1);
}
.tbd-block p { margin-bottom: 0; max-width: none; color: var(--note-ink); }

.section--navy .tbd, .site-footer .tbd {
  background: rgba(255,255,255,.06); border-bottom-color: rgba(223,211,174,.35); color: #BCB08A;
}
.section--navy .tbd-block { background: rgba(255,255,255,.04); border-left-color: rgba(223,211,174,.4); color: #ACA079; }
.section--navy .tbd-block strong, .section--navy .tbd-block p { color: #ACA079; }

.ph {
  display: flex; align-items: center; justify-content: center;
  background: var(--grey-50); border: 1px dashed var(--grey-200);
  border-radius: var(--radius); color: var(--grey-500);
  text-align: center; padding: var(--s4) var(--s3); min-height: 180px;
}
.ph span { font-size: 14px; line-height: 22px; max-width: 280px; }
.ph strong {
  display: block; font-family: var(--font-head); color: var(--grey-600);
  font-size: 12px; line-height: 16px; letter-spacing: .1em; text-transform: uppercase;
  font-weight: 600; margin-bottom: var(--s1);
}
.card__media.ph { aspect-ratio: 3 / 2; min-height: 0; border: 0; border-bottom: 1px solid var(--grey-100); border-radius: 0; }

/* Hero placeholder: flat navy fill only. The descriptive label is pinned to the
   bottom-right so it never collides with the headline column — it was overlapping
   the hero paragraph and reading as a rendering fault. */
.hero .ph {
  background: var(--navy-800); border: 0; border-radius: 0;
  color: #3C4A66; align-items: flex-end; justify-content: flex-end;
  padding: var(--s3);
}
.hero .ph span { max-width: 210px; text-align: right; font-size: 12px; line-height: 18px; }
.hero .ph strong { color: #4A5A78; }
@media (max-width: 899px) { .hero .ph span { display: none; } }

/* ==========================================================================
   Forms
   ========================================================================== */
.form-card {
  background: #fff; border: 1px solid var(--grey-100);
  border-radius: var(--radius-lg); padding: var(--card-pad); box-shadow: var(--shadow-card);
}
@media (min-width: 768px) { .form-card { padding: var(--s5); } }

.fieldset { border: 0; padding: 0; margin: 0 0 var(--s5); }
.fieldset legend {
  font-family: var(--font-head); font-weight: 600; font-size: 19px; line-height: 28px;
  color: var(--navy); padding: 0; margin-bottom: 4px; letter-spacing: -.01em;
}
.fieldset__hint { color: var(--grey-500); font-size: 15px; line-height: 24px; margin-bottom: var(--s3); }

.field { margin-bottom: var(--s3); }
.field label, .field .label {
  display: block; font-family: var(--font-head); font-weight: 500; font-size: 15px; line-height: 24px;
  color: var(--navy); margin-bottom: 6px;
}
.field .req { color: var(--alert); font-weight: 400; }
.field .help {
  font-family: var(--font); font-weight: 400; color: var(--grey-500);
  font-size: 14px; line-height: 20px; display: block; margin-top: 2px;
}
.field input[type="text"], .field input[type="tel"], .field input[type="email"],
.field input[type="date"], .field input[type="file"], .field select, .field textarea {
  width: 100%; font-family: var(--font); font-size: 16px; line-height: 24px;
  padding: 0 14px; height: 48px;
  border: 1px solid var(--grey-200); border-radius: var(--radius);
  background: #fff; color: var(--ink);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.field textarea { height: auto; min-height: 112px; padding: 12px 14px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--blue-500); box-shadow: var(--ring); outline: none;
}
.field--2col { display: grid; gap: var(--s3); }
@media (min-width: 620px) { .field--2col { grid-template-columns: 1fr 1fr; } }

.radio-grid { display: grid; gap: var(--s2); }
@media (min-width: 700px) { .radio-grid { grid-template-columns: 1fr 1fr; } }
.radio-card { position: relative; }
.radio-card input { position: absolute; opacity: 0; width: 100%; height: 100%; cursor: pointer; margin: 0; }
.radio-card span {
  display: block; padding: 14px 16px 14px 46px; min-height: 64px;
  border: 1px solid var(--grey-200); border-radius: var(--radius);
  font-family: var(--font-head); font-weight: 500; font-size: 16px; line-height: 24px;
  color: var(--navy); cursor: pointer; background: #fff;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.radio-card span::before {
  content: ""; position: absolute; left: 16px; top: 50%; transform: translateY(-50%);
  width: 18px; height: 18px; border: 1px solid var(--grey-300);
  border-radius: 50%; background: #fff; transition: box-shadow .15s var(--ease), border-color .15s var(--ease);
}
.radio-card:hover span { border-color: var(--grey-300); }
.radio-card input:checked + span { border-color: var(--blue); background: var(--blue-50); }
.radio-card input:checked + span::before { border-color: var(--blue); box-shadow: inset 0 0 0 4px var(--blue); }
.radio-card input:focus-visible + span { outline: 2px solid var(--blue-500); outline-offset: 2px; }
.radio-card small {
  display: block; font-family: var(--font); font-weight: 400;
  color: var(--grey-500); font-size: 14px; line-height: 20px;
}
.radio-card.is-alert input:checked + span { border-color: var(--alert); background: var(--alert-50); }

.checkbox { display: flex; gap: var(--s2); align-items: flex-start; }
.checkbox input { width: 20px; height: 20px; margin: 4px 0 0; flex-shrink: 0; }
.checkbox label { font-family: var(--font); font-weight: 400; font-size: 15px; line-height: 24px; color: var(--grey-600); }

.conditional { display: none; }
.conditional.is-visible { display: block; animation: fade .2s var(--ease); }
@keyframes fade { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.emergency-notice {
  display: none; background: var(--alert-50); border: 1px solid #EFC7AE;
  border-radius: var(--radius); padding: var(--s3); margin-bottom: var(--s3); text-align: center;
}
.emergency-notice.is-visible { display: block; }
.emergency-notice p { font-weight: 600; color: var(--alert-dark); margin: 0 auto var(--s1); }
.emergency-notice a {
  display: block; font-family: var(--font-head); font-weight: 700;
  font-size: 34px; line-height: 40px; color: var(--navy); text-decoration: none; letter-spacing: -.025em;
}

/* ==========================================================================
   Page furniture
   ========================================================================== */
.page-head { background: var(--navy); color: #fff; padding: var(--s5) 0 var(--s6); }
@media (min-width: 768px) { .page-head { padding: var(--s6) 0 var(--s7); } }
.page-head h1 { color: #fff; margin-bottom: var(--s3); max-width: 17em; }
.page-head p { color: #A4B3CC; max-width: 44em; font-size: 19px; line-height: 32px; margin-bottom: 0; }
/* The global `strong` rule paints text --ink, which is near-black. On the navy
   page head that is unreadable, so any bold run here has to be re-lit. */
.page-head strong { color: #fff; }

.crumbs { font-size: 14px; line-height: 20px; color: var(--grey-500); margin-bottom: var(--s3); }
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; padding: 0; margin: 0; max-width: none; }
.crumbs li { margin: 0; }
.crumbs li + li::before { content: "/"; margin-right: 6px; color: var(--grey-300); }
.crumbs a { color: var(--grey-500); text-decoration: none; }
.crumbs a:hover { color: var(--grey-700); }
.page-head .crumbs, .page-head .crumbs a { color: #6E80A0; }
.page-head .crumbs a:hover { color: #B4C1D6; }
.page-head .crumbs li + li::before { color: #445572; }

.callout {
  background: var(--blue-50); border: 1px solid #DAE7F2;
  padding: var(--s3); border-radius: var(--radius); margin-bottom: var(--s4);
}
.callout p { margin-bottom: var(--s2); font-size: 16px; line-height: 26px; }
.callout p:last-child { margin-bottom: 0; }
.callout strong { color: var(--navy); }

.table-wrap { overflow-x: auto; margin-bottom: var(--s4); -webkit-overflow-scrolling: touch; }
table { width: 100%; border-collapse: collapse; font-size: 15px; line-height: 24px; min-width: 460px; }
caption { text-align: left; font-size: 14px; color: var(--grey-500); padding-bottom: var(--s2); }
th, td { text-align: left; padding: 12px 16px; vertical-align: top; }
th {
  font-family: var(--font-head); font-size: 13px; line-height: 16px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--grey-600); background: var(--grey-50); border-bottom: 1px solid var(--grey-200);
}
td { border-bottom: 1px solid var(--grey-100); }
tbody tr:last-child td { border-bottom: 0; }

/* Captioned project photograph. The caption is the point — it is what turns a
   picture of a crane into evidence of a specific job. */
.media-frame-fig { margin: 0; }
.media-frame-fig figcaption {
  margin-top: var(--s2);
  font-size: 15px; line-height: 24px; color: var(--grey-600);
}

.faq-toc {
  list-style: none; padding: 0; max-width: none;
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3);
}
.faq-toc li { margin: 0; }

.faq { max-width: 760px; }
.faq__item { padding: var(--s4) 0; border-bottom: 1px solid var(--grey-100); }
.faq__item:first-child { padding-top: 0; }
.faq__item:last-child { border-bottom: 0; padding-bottom: 0; }
.faq__item h3 { margin-bottom: var(--s1); }
.faq__item p { color: var(--grey-600); margin-bottom: 0; }

.emergency-hero { background: var(--navy); color: #fff; text-align: center; padding: var(--section-y) var(--gutter); }
.emergency-hero h1 { color: #fff; margin-bottom: var(--s2); }
.emergency-hero p { color: #A4B3CC; max-width: 30em; margin: 0 auto var(--s5); font-size: 19px; line-height: 32px; }
.big-call {
  display: inline-flex; flex-direction: column; align-items: center;
  background: var(--alert); color: #fff; text-decoration: none;
  padding: var(--s3) var(--s6); border-radius: var(--radius-lg);
  transition: background .16s var(--ease);
}
.big-call:hover { background: var(--alert-dark); color: #fff; }
.big-call span { font-size: 13px; line-height: 16px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; }
.big-call strong { font-family: var(--font-head); font-size: 40px; line-height: 48px; color: #fff; letter-spacing: -.025em; font-weight: 700; }
@media (min-width: 768px) { .big-call strong { font-size: 52px; line-height: 56px; } }

.cta-band { background: var(--navy); color: #fff; text-align: center; padding: var(--section-y) var(--gutter); }
.cta-band h2 { color: #fff; margin-bottom: var(--s2); }
.cta-band p { color: #A4B3CC; max-width: 34em; margin: 0 auto var(--s5); font-size: 19px; line-height: 32px; }
.cta-band__btns { display: flex; flex-wrap: wrap; gap: var(--s2); justify-content: center; }

aside h3 { margin-top: var(--s5); }
aside h3:first-child { margin-top: 0; }
aside p, aside ul { font-size: 16px; line-height: 26px; }

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer { background: var(--navy); color: #7E8FAB; padding: var(--s6) 0 0; font-size: 15px; line-height: 24px; }
.footer-grid { display: grid; gap: var(--s5); }
@media (min-width: 760px)  { .footer-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .footer-grid { grid-template-columns: 2fr 1fr 1.2fr; } }
/* Services carries seven links against Company's five and the contact block's
   four lines, so as a single column it set the height of the whole footer.
   Two columns halves it and the footer stops being the tallest thing on the page. */
@media (min-width: 560px) {
  .footer-services ul { columns: 2; column-gap: var(--s3); }
  .footer-services li { break-inside: avoid; }
}
.site-footer h4 {
  color: #fff; font-family: var(--font-head); font-size: 13px; line-height: 16px;
  letter-spacing: .1em; text-transform: uppercase; margin-bottom: var(--s3); font-weight: 600;
}
.site-footer ul { list-style: none; padding: 0; margin: 0; max-width: none; }
.site-footer li { margin-bottom: var(--s2); }
.site-footer a { color: #7E8FAB; text-decoration: none; }
.site-footer a:hover { color: #fff; }
.site-footer p { max-width: 30em; }
.footer-brand img { height: 56px; width: auto; margin-bottom: var(--s3); }
/* Contact column. Every line is a grid child on the 8px scale. The previous
   version chained <br> tags and then reached for an inline margin-top:14px,
   which was the only off-grid value in the stylesheet; it also ran four type
   treatments in one narrow column, with the company name (17px) losing to the
   phone number (19px). Now there are two emphasis levels: the phone, and
   everything else. */
.footer-nap {
  font-style: normal;
  display: grid;
  gap: var(--s2);
  line-height: 24px;
}
/* Address, phone and email all sit at the same weight now. The phone used to be
   19px white head-font, which made it the loudest thing in the footer; the
   header and the mobile action bar already carry the call-to-action. */
/* The address is the longest unbroken string in the footer and the column is
   the narrowest — without this it overflows the grid track rather than wrapping. */
.footer-nap__email { overflow-wrap: anywhere; }
.footer-nap a:hover { color: #fff; text-decoration: underline; }
.footer-hours { margin: var(--s3) 0 0; }

/* Social sits on its own centred row below the columns, not inside one of them. */
.footer-socials {
  margin-top: var(--s5);
  padding-top: var(--s4);
  border-top: 1px solid rgba(255,255,255,.1);
}
.footer-social {
  display: flex; flex-wrap: wrap; gap: var(--s4);
  justify-content: center;
  list-style: none; padding: 0; margin: 0; max-width: none;
}
.footer-social li { margin: 0; }
.footer-social a { display: inline-flex; align-items: center; gap: var(--s1); }
.footer-social svg { width: 20px; height: 20px; fill: currentColor; flex: none; }
/* The legal row already has a top border; two in a row would read as a boxed
   strip, so it loses its own once social is sitting above it. */
.footer-socials + .footer-bottom { border-top: 0; margin-top: var(--s4); }
.footer-bottom {
  border-top: 1px solid rgba(255,255,255,.1); margin-top: var(--s5); padding: var(--s3) 0 var(--s4);
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); justify-content: space-between; align-items: center;
  font-size: 14px; line-height: 20px; color: #5B6B87;
}
.footer-bottom p { margin: 0; max-width: none; }
.footer-bottom ul { display: flex; flex-wrap: wrap; gap: var(--s3); }
.footer-bottom li { margin: 0; }

/* ==========================================================================
   Job photography
   ========================================================================== */
/* Photos are absolutely positioned inside a ratio box rather than sized with
   width/height percentages. With a percentage height the parent's aspect-ratio
   loses to the image's own intrinsic ratio — a portrait job photo stretched the
   service cards to double height. Taking the image out of flow makes the crop
   deterministic whatever shape the source happens to be. */
/* A faint diagonal hatch behind every photo slot. While an image is still
   fetching the slot reads as "picture loading" rather than as a blank box,
   which is how a partly-scrolled page was being misread as broken. */
.media-frame,
.card__media {
  background-color: var(--grey-50);
  background-image: repeating-linear-gradient(45deg,
    rgba(0,1,34,.028) 0 8px, rgba(0,1,34,0) 8px 16px);
}
.media-frame {
  position: relative; aspect-ratio: 3 / 2; overflow: hidden; display: block;
  border-radius: var(--radius);
  border: 1px solid var(--grey-100);
  min-height: 200px;          /* never collapses, even before the image lands */
}
.media-frame img,
.card__media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.media-note {
  font-size: 14px; line-height: 20px; color: var(--grey-500);
  margin-top: var(--s2); font-style: italic;
}

/* ==========================================================================
   Service-area map — stylised inline SVG, no dependencies
   ========================================================================== */
/* The map is an embed, so it is invisible to crawlers and to AI assistants.
   The county text list beside it is what those read — keep both. */
.svc-map-embed {
  width: 100%; max-width: 560px;
  border: 1px solid var(--grey-100); border-radius: var(--radius);
  overflow: hidden; background: var(--grey-50);
}
.svc-map-embed iframe { display: block; }
.svc-map { width: 100%; height: auto; max-width: 560px; display: block; }
.svc-served  { fill: var(--blue-100); stroke: var(--blue); stroke-width: 1.25; }
.svc-outside { fill: var(--grey-50);  stroke: var(--grey-200); stroke-width: 1.25; }
.svc-label {
  font-family: var(--font-head); font-size: 13px; font-weight: 600;
  fill: var(--navy); letter-spacing: -.01em;
}
.svc-label--muted { fill: var(--grey-500); font-weight: 500; }
.svc-state { font-size: 10px; font-weight: 500; fill: var(--grey-600); }
.svc-label--muted.svc-state { fill: var(--grey-500); }
.svc-cities .svc-city { fill: var(--grey-700); }
.svc-cities .svc-city-label {
  font-family: var(--font); font-size: 11px; fill: var(--grey-700);
}
.section--navy .svc-state { fill: #8D9CB5; }
.section--navy .svc-cities .svc-city { fill: #B4C1D6; }
.section--navy .svc-cities .svc-city-label { fill: #B4C1D6; }
.svc-river { stroke: var(--blue-300); stroke-width: 2.5; opacity: .7; stroke-linejoin: round; }
/* Philadelphia is confirmed coverage, so it reads as served rather than as a
   grey out-of-area landmark. */
.svc-city { fill: var(--blue); }
.svc-city-label { font-family: var(--font); font-size: 12px; fill: var(--blue); font-weight: 500; }
.svc-hq-ring { fill: none; stroke: var(--alert); stroke-width: 2; }
.svc-hq-dot  { fill: var(--alert); }
.svc-hq-label {
  font-family: var(--font-head); font-size: 13px; font-weight: 600; fill: var(--alert-dark);
}
.section--navy .svc-served  { fill: rgba(54,138,191,.3); stroke: var(--blue-300); }
.section--navy .svc-outside { fill: rgba(255,255,255,.05); stroke: rgba(255,255,255,.16); }
.section--navy .svc-label { fill: #fff; }
.section--navy .svc-label--muted { fill: #7E8FAB; }
.section--navy .svc-city-label { fill: #8D9CB5; }
.section--navy .svc-hq-label { fill: #F2A277; }

.svc-legend { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s3); }
.svc-legend span {
  display: inline-flex; align-items: center; gap: var(--s1);
  font-size: 14px; line-height: 20px; color: var(--grey-600);
}
.svc-legend i { width: 14px; height: 14px; border-radius: 3px; display: block; font-style: normal; }
.svc-legend .k-served  { background: var(--blue-100); border: 1.25px solid var(--blue); }
.svc-legend .k-outside { background: var(--grey-50);  border: 1.25px solid var(--grey-200); }
.svc-legend .k-hq { background: var(--alert); border-radius: 50%; }
.section--navy .svc-legend span { color: #8D9CB5; }

.county-list { list-style: none; padding: 0; margin: 0 0 var(--s4); max-width: none; }
.county-list li {
  display: flex; justify-content: space-between; gap: var(--s3); align-items: baseline;
  padding: var(--s2) 0; border-bottom: 1px solid var(--grey-100); margin: 0;
}
.county-list li:last-child { border-bottom: 0; }
.county-list strong { font-family: var(--font-head); font-weight: 600; color: var(--navy); }
.county-list span { color: var(--grey-500); font-size: 15px; text-align: right; }
.section--navy .county-list li { border-bottom-color: rgba(255,255,255,.1); }
.section--navy .county-list strong { color: #fff; }
.section--navy .county-list span { color: #7E8FAB; }

/* ==========================================================================
   Instagram feed — markup generated at build time by build.mjs
   ========================================================================== */
.ig-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s2);
  margin-bottom: var(--s4);
}
@media (min-width: 700px)  { .ig-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1000px) { .ig-grid { grid-template-columns: repeat(3, 1fr); gap: var(--s3); } }

.ig-tile {
  position: relative; display: block; aspect-ratio: 1; overflow: hidden;
  border-radius: var(--radius); background: var(--grey-100);
  border: 1px solid var(--grey-100);
}
.ig-tile img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .3s var(--ease);
}
.ig-tile:hover img { transform: scale(1.03); }
.ig-tile__video {
  position: absolute; top: var(--s2); right: var(--s2);
  width: 24px; height: 24px; border-radius: 50%;
  background: rgba(0,1,34,.6); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; line-height: 1;
}
.ig-follow { margin: 0; }

.badges { display: flex; flex-wrap: wrap; gap: var(--s2); }
.badge {
  display: inline-flex; align-items: center; gap: var(--s1); height: 40px;
  border: 1px solid var(--grey-200); background: #fff; border-radius: 100px; padding: 0 var(--s3);
  font-family: var(--font-head); font-size: 15px; font-weight: 500; color: var(--grey-700);
}
.badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--blue-500); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  html { scroll-behavior: auto; }
}
@media print {
  .site-header, .action-bar, .utility, .cta-band, .site-footer { display: none !important; }
  body { padding-bottom: 0; }
}
