/* ============================================================
   On Point Roofing — Texas
   v4. Rebranded 2026-09-14 from On Point Roofing.

   Palette is derived from the logo's three colours only:
     charcoal #212221 · slate #7D98AB · red #E72F2F
   Slate is darkened into the field ramp; red is darkened for
   anything that carries text. Nothing foreign entered.

   COLOUR RULES — do not break:
   - The logo red #E72F2F is 3.98:1 on paper and 4.33:1 under
     white. It FAILS AA as text and as a button label. It is a
     RULE colour only: peaks, card top-rules, hairline breaks.
     Anything text-bearing uses --red-dk (5.61:1 paper, 6.11:1
     under white).
   - Red is invisible on slate (1.53:1 bright, 3.11:1 deep) —
     the same constraint crimson had on blue. On any slate
     ground: emphasis = white vs --on-slate (value, not hue);
     red appears ONLY as a filled button, and that button needs
     a light border or its edge vanishes into the field.
   - --hair-2 is a border colour (3.10:1). It fails as body text.
   - Red is rationed: peaks, buttons, links, eyebrows.
   ============================================================ */

:root{
  --red:        #E72F2F;   /* logo red — RULES ONLY, never text */
  --red-dk:     #C21818;   /* text-bearing red — 5.61:1 paper, 6.11:1 under white */
  --red-dkr:    #9E1212;   /* button hover — 8.24:1 under white */
  --slate:      #456070;
  --slate-dk:   #33475A;
  --slate-deep: #22303C;
  --on-slate:   #E0E7ED;   /* 5.32:1 bright · 7.68:1 mid · 10.81:1 deep */

  --paper:      #F7F5F2;
  --paper-2:    #EFECE7;
  --white:      #FFFFFF;
  --ink:        #1A2028;
  --ink-2:      #53585E;
  --hair:       #D2D8DD;
  --hair-2:     #7E8E9A;
  --hair-rev:   rgba(255,255,255,.20);
  --surface:    #FFFFFF;

  --serif:'Newsreader', Georgia, 'Times New Roman', serif;
  --sans: 'Source Sans 3', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* tightened scale — display sizes cut roughly a third from v2 */
  --t-eyebrow: 11px;
  --t-sm:      14px;
  --t-base:    17px;
  --t-lead:    clamp(18px, 1.6vw, 20px);
  --t-h3:      clamp(18px, 1.5vw, 20px);
  --t-h2:      clamp(27px, 3.2vw, 40px);
  --t-h1:      clamp(34px, 5vw, 62px);
  --t-display: clamp(28px, 3.6vw, 46px);

  --s1:6px; --s2:12px; --s3:20px; --s4:32px; --s5:48px; --s6:64px; --s7:88px;

  --measure: 58ch;
  --wrap: 1180px;
  --gutter: clamp(20px, 4vw, 44px);
  --radius: 4px;
}

/* ---------------- reset ---------------- */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
body{
  margin:0; background:var(--paper); color:var(--ink);
  font-family:var(--sans); font-size:var(--t-base); line-height:1.55;
  -webkit-font-smoothing:antialiased; overflow-wrap:break-word;
}
.grid>*,.hero__cta>*,.duo>*,.steps>*,.foot__grid>*,.split>*{ min-width:0; }
:focus-visible{ outline:3px solid var(--red-dk); outline-offset:2px; }
/* The focus ring must clear 3:1 against whatever it sits on (WCAG 2.4.11).
   --red-dk manages that on every light ground (5.18:1 - 6.11:1) but collapses
   on the slate fields: 1.09:1 on bright, 1.57:1 mid, 2.21:1 deep. Same trap the
   old crimson-on-blue ring fell into. On dark grounds the ring goes white —
   6.65:1 bright, 9.59:1 mid, 13.50:1 deep, 6.11:1 on the red call bar. */
.sec--pop :focus-visible,.sec--mid :focus-visible,.sec--deep :focus-visible,
.utility :focus-visible,.foot :focus-visible,.callbar :focus-visible{
  outline-color:var(--white);
}

h1,h2{ font-family:var(--serif); font-weight:700; margin:0; }
h1{ font-size:var(--t-h1); line-height:1.02; letter-spacing:-.021em; }
h2{ font-size:var(--t-h2); line-height:1.08; letter-spacing:-.016em; color:var(--slate); }
/* h3 is sans — this is most of what makes it read modern rather than editorial */
h3{ font-family:var(--sans); font-size:var(--t-h3); font-weight:700; line-height:1.3;
    letter-spacing:-.005em; margin:0; color:var(--ink); }
p{ margin:0 0 .9em; max-width:var(--measure); }
p:last-child{ margin-bottom:0; }

/* ---------------- layout ---------------- */
.wrap{ max-width:var(--wrap); margin:0 auto; padding:0 var(--gutter); }
.sec{ padding:var(--s6) 0; }
.sec--sm{ padding:var(--s5) 0; }
@media(max-width:700px){ .sec{ padding:var(--s5) 0; } }

.sec--tint{ background:var(--paper-2); }
.sec--pop{  background:var(--slate); }
.sec--mid{  background:var(--slate-dk); }
.sec--deep{ background:var(--slate-deep); }

/* one text treatment for every blue ground */
.sec--pop,.sec--mid,.sec--deep{ color:var(--on-slate); }
.sec--pop h1,.sec--pop h2,.sec--pop h3,
.sec--mid h1,.sec--mid h2,.sec--mid h3,
.sec--deep h1,.sec--deep h2,.sec--deep h3{ color:var(--white); }
.sec--pop p,.sec--mid p,.sec--deep p,
.sec--pop .lead,.sec--mid .lead,.sec--deep .lead{ color:var(--on-slate); }
.sec--pop .eyebrow,.sec--mid .eyebrow,.sec--deep .eyebrow{ color:var(--white); }
.sec--pop strong,.sec--mid strong,.sec--deep strong{ color:var(--white); }
.sec--pop a,.sec--mid a,.sec--deep a{ color:var(--white); }
.sec--pop .peak,.sec--mid .peak,.sec--deep .peak{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 11'%3E%3Cpath d='M1.2 9.8 11 1.4l9.8 8.4' fill='none' stroke='%23FFFFFF' stroke-width='2' stroke-linecap='square'/%3E%3C/svg%3E");
}

/* ---------------- the roofline peak ---------------- */
.peak{
  display:block; width:22px; height:11px; flex:none;
  background:no-repeat center/contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 11'%3E%3Cpath d='M1.2 9.8 11 1.4l9.8 8.4' fill='none' stroke='%23E72F2F' stroke-width='2' stroke-linecap='square'/%3E%3C/svg%3E");
}

/* ---------------- section head ---------------- */
.eyebrow{
  display:flex; align-items:center; gap:9px; max-width:none;
  font-size:var(--t-eyebrow); font-weight:700; letter-spacing:.17em;
  text-transform:uppercase; color:var(--red-dk); margin:0 0 var(--s2);
}
/* An eyebrow carrying a whole clause rather than a 2–3 word label
   (2026-09-23, the 25-years line). The base .eyebrow is a flex row built for
   short labels — it would push a long clause onto one line beside the peak
   and blow past the column. This lets it wrap, keeps the peak aligned to the
   first line, and eases the tracking back since letterspacing that reads as
   deliberate on three words reads as strained on eight. */
.eyebrow--long{
  /* No max-width. The 42ch cap this carried resolved to about 230px at 11px
     and broke the clause across two lines while the hero column offered 694.
     The line needs 694 and gets it; it sets on one line at every width down
     to the 980px breakpoint, and wraps below that, which is unavoidable —
     44 characters of tracked uppercase cannot fit a 350px phone column at a
     legible size, and dropping the tracking entirely only recovers ~58px. */
  align-items:flex-start; letter-spacing:.12em; line-height:1.5;
}
/* Nudged down so the peak reads as aligned to the cap height of the first
   line rather than its full line-box, which matters once the text wraps. */
.eyebrow--long .peak{ margin-top:5px; }

.shead{ margin-bottom:var(--s4); }
.shead h1,.shead h2{ max-width:19ch; }
.shead .lead{ margin-top:var(--s2); }
.lead{ font-size:var(--t-lead); line-height:1.45; color:var(--ink-2); max-width:52ch; }

/* ---------------- utility + header ---------------- */
.utility{ background:var(--slate-deep); color:var(--on-slate); font-size:13px; padding:7px 0; }
.utility .wrap{ display:flex; justify-content:space-between; gap:14px; flex-wrap:wrap; }
.utility a{ color:var(--white); font-weight:600; text-decoration:none; }
.utility a:hover{ text-decoration:underline; }
@media(max-width:640px){ .utility__area{ display:none; } .utility .wrap{ justify-content:center; } }

.mast{ background:var(--paper); border-bottom:1px solid var(--hair); }
.mast .wrap{ display:flex; align-items:center; justify-content:space-between; gap:18px; padding-top:13px; padding-bottom:13px; }
.nav{ display:flex; align-items:center; gap:2px; }
.nav a{ color:var(--ink); text-decoration:none; font-weight:600; font-size:15px; padding:9px 13px; }
.nav a:hover,.nav a[aria-current="page"]{ color:var(--red-dk); }
.nav .btn{ margin-left:8px; }
.nav-toggle{ display:none; }
@media(max-width:900px){
  .mast .wrap{ flex-wrap:wrap; }
  .nav-toggle{ display:inline-block; background:transparent; border:1px solid var(--hair-2);
    border-radius:var(--radius); color:var(--ink); font:inherit; font-weight:600; font-size:14.5px;
    padding:8px 15px; cursor:pointer; }
  .nav{ display:none; width:100%; flex-direction:column; align-items:stretch; padding-bottom:8px; }
  .nav.is-open{ display:flex; }
  .nav a{ padding:11px 2px; border-top:1px solid var(--hair); }
  .nav .btn{ margin:10px 0 0; text-align:center; }
}

/* ---------------- buttons ---------------- */
.btn{
  display:inline-block; font-family:var(--sans); font-weight:600; font-size:15.5px;
  padding:12px 22px; text-decoration:none; border:1px solid transparent;
  border-radius:var(--radius); cursor:pointer; transition:background .15s,color .15s,border-color .15s;
}
.btn--primary{ background:var(--red-dk); color:var(--white); }
.btn--primary:hover{ background:var(--red-dkr); color:var(--white); }
.btn--line{ border-color:var(--hair-2); color:var(--ink); }
.btn--line:hover{ background:var(--ink); color:var(--paper); border-color:var(--ink); }
.btn--rev{ background:var(--white); color:var(--slate-deep); }
.btn--rev:hover{ background:var(--on-slate); }
.btn--sm{ padding:9px 17px; font-size:14px; }
.btnrow{ display:flex; gap:var(--s2); flex-wrap:wrap; align-items:center; }
/* a red button on slate has a 1.53:1 edge — the border is the boundary (8.37:1) */
.sec--pop .btn--primary,.sec--mid .btn--primary,.sec--deep .btn--primary{ border-color:rgba(255,255,255,.6); }
.sec--pop .btn--line,.sec--mid .btn--line,.sec--deep .btn--line{ border-color:rgba(255,255,255,.55); color:var(--white); }
.sec--pop .btn--line:hover,.sec--mid .btn--line:hover,.sec--deep .btn--line:hover{ background:var(--white); color:var(--slate-deep); }

.tlink{ font-weight:600; font-size:15.5px; color:var(--ink); text-decoration:none;
  border-bottom:2px solid var(--red); padding-bottom:2px; }
.tlink:hover{ color:var(--red-dk); }
.sec--pop .tlink,.sec--mid .tlink,.sec--deep .tlink{ color:var(--white); border-bottom-color:var(--white); }
.sec--pop .tlink:hover,.sec--mid .tlink:hover,.sec--deep .tlink:hover{ color:var(--on-slate); border-bottom-color:var(--on-slate); }

/* ---------------- logo ---------------- */
.logo{ display:inline-flex; align-items:center; text-decoration:none; }
.logo img{ display:block; height:54px; width:auto; }
.foot .logo--foot img{ height:60px; }
.logo--stack{ display:block; }
.logo--stack img{ height:132px; margin:0 auto var(--s3); }
@media(max-width:520px){
  .logo img{ height:44px; }
  .logo--stack img{ height:110px; }
}

/* ============================================================
   HERO — full width, type only
   ============================================================ */
.hero{ background:var(--slate); padding:var(--s7) 0; }
@media(max-width:700px){ .hero{ padding:var(--s6) 0 var(--s5); } }
/* 15ch -> 21ch, paired with the wider hero__grid split below (2026-09-23).
   The new H1 is 61 characters against the old 36. At the previous measure it
   set to FOUR lines and pushed "Get an Estimate" to y=693 — past the 668px
   fold on a 1366x768 laptop, i.e. the primary CTA was cut off on one of the
   commonest screens there is. Widening the measure and the column together
   brings it to three lines and the CTA back to y=630. Shrinking the type
   instead does not work: the line count holds at four all the way down to
   48px, so only the measure moves it. */
.hero h1{ color:var(--white); max-width:21ch; margin-bottom:var(--s3); }
.hero__sub{ font-size:var(--t-lead); line-height:1.5; color:var(--on-slate); max-width:50ch; margin-bottom:var(--s4); }
.hero__cta{ display:flex; gap:var(--s3); align-items:center; flex-wrap:wrap; }

/* ============================================================
   PANELS + GRIDS — the modern replacement for editorial columns
   ============================================================ */
.grid{ display:grid; gap:var(--s3); }
@media(min-width:720px){
  .grid--2{ grid-template-columns:repeat(2,1fr); }
  .grid--3{ grid-template-columns:repeat(3,1fr); }
}
@media(min-width:560px) and (max-width:719px){ .grid--3{ grid-template-columns:repeat(2,1fr); } }

.panel{
  background:var(--surface); border:1px solid var(--hair); border-radius:var(--radius);
  padding:var(--s3) var(--s3) calc(var(--s3) + 2px);
}
.panel h3{ margin-bottom:6px; }
.panel p{ font-size:15px; color:var(--ink-2); margin:0; }
.sec--mid .panel,.sec--deep .panel,.sec--pop .panel{
  background:rgba(255,255,255,.06); border-color:var(--hair-rev);
}
.sec--mid .panel p,.sec--deep .panel p,.sec--pop .panel p{ color:var(--on-slate); }

/* the two doors */
.duo{ display:grid; gap:var(--s3); }
@media(min-width:720px){ .duo{ grid-template-columns:1fr 1fr; } }
.door{
  display:block; text-decoration:none; color:var(--ink);
  background:var(--surface); border:1px solid var(--hair); border-radius:var(--radius);
  padding:var(--s3); transition:border-color .15s, box-shadow .15s;
}
.door:hover{ border-color:var(--red); box-shadow:0 2px 14px rgba(26,32,40,.07); }
.door__k{ display:block; font-size:var(--t-eyebrow); font-weight:700; letter-spacing:.17em;
  text-transform:uppercase; color:var(--red-dk); margin-bottom:8px; }
.door h3,.door .door__h{ font-family:var(--serif); font-size:24px; color:var(--slate); margin-bottom:6px; letter-spacing:-.012em; }
.door p{ font-size:15px; color:var(--ink-2); margin:0 0 var(--s2); }
.door__go{ font-weight:600; font-size:14.5px; color:var(--red-dk); }

/* service rows — dense list */
.slist{ border-top:1px solid var(--hair); }
.srow{
  display:grid; gap:2px var(--s4); padding:var(--s3) 0; border-bottom:1px solid var(--hair);
  text-decoration:none; color:var(--ink); transition:background .15s, padding-left .15s;
}
@media(min-width:820px){ .srow{ grid-template-columns:minmax(0,.26fr) minmax(0,1fr) auto; align-items:baseline; } }
.srow:hover{ background:var(--paper-2); padding-left:10px; }
.srow h3{ font-family:var(--serif); font-size:20px; color:var(--slate); letter-spacing:-.012em; }
.srow p{ margin:0; font-size:15px; color:var(--ink-2); max-width:56ch; }
.srow .go{ font-size:18px; color:var(--red-dk); line-height:1; }

/* steps — compact, small numerals in sans */
.steps{ counter-reset:s; display:grid; gap:var(--s3); }
@media(min-width:760px){ .steps{ grid-template-columns:repeat(3,1fr); gap:var(--s4); } }
.step{ border-top:2px solid var(--red); padding-top:var(--s2); }
.step::before{
  counter-increment:s; content:counter(s,decimal-leading-zero);
  display:block; font-family:var(--sans); font-size:13px; font-weight:700;
  letter-spacing:.14em; color:var(--red-dk); margin-bottom:8px;
}
.sec--mid .step,.sec--deep .step,.sec--pop .step{ border-top-color:var(--white); }
.sec--mid .step::before,.sec--deep .step::before,.sec--pop .step::before{ color:var(--white); }
.step h3{ margin-bottom:5px; }
.step p{ font-size:15px; color:var(--ink-2); margin:0; }
.sec--mid .step p,.sec--deep .step p,.sec--pop .step p{ color:var(--on-slate); }

/* promise rows */
.plist{ list-style:none; margin:0; padding:0; }
.plist li{ display:grid; gap:2px var(--s4); padding:var(--s3) 0; border-top:1px solid var(--hair); }
.plist li:last-child{ border-bottom:1px solid var(--hair); }
@media(min-width:760px){ .plist li{ grid-template-columns:minmax(0,.36fr) minmax(0,1fr); align-items:start; } }
.plist strong{ font-size:15.5px; font-weight:700; color:var(--slate); }
.plist span{ font-size:15px; color:var(--ink-2); }
.sec--mid .plist li,.sec--deep .plist li,.sec--pop .plist li{ border-color:var(--hair-rev); }
.sec--mid .plist strong,.sec--deep .plist strong,.sec--pop .plist strong{ color:var(--white); }
.sec--mid .plist span,.sec--deep .plist span,.sec--pop .plist span{ color:var(--on-slate); }

/* peak-bulleted list */
.peaklist{ list-style:none; padding:0; margin:var(--s2) 0 0; max-width:var(--measure); }
.peaklist li{ padding:7px 0 7px 22px; position:relative; font-size:15.5px; border-top:1px solid var(--hair); }
.peaklist li:first-child{ border-top:0; }
.peaklist li::before{ content:""; position:absolute; left:0; top:14px; width:10px; height:5px;
  background:no-repeat center/contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 11'%3E%3Cpath d='M1.2 9.8 11 1.4l9.8 8.4' fill='none' stroke='%23E72F2F' stroke-width='2.6' stroke-linecap='square'/%3E%3C/svg%3E"); }
.peaklist--2col{ max-width:none; }
@media(min-width:720px){ .peaklist--2col{ columns:2; column-gap:var(--s4); } }
.peaklist--2col li{ break-inside:avoid; }
.sec--mid .peaklist li,.sec--deep .peaklist li,.sec--pop .peaklist li{ border-color:var(--hair-rev); }
.sec--mid .peaklist li::before,.sec--deep .peaklist li::before,.sec--pop .peaklist li::before{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 11'%3E%3Cpath d='M1.2 9.8 11 1.4l9.8 8.4' fill='none' stroke='%23FFFFFF' stroke-width='2.6' stroke-linecap='square'/%3E%3C/svg%3E"); }

/* note + tags */
.note-block{ border-left:2px solid var(--red); padding:2px 0 2px var(--s3); margin:var(--s3) 0 0; }
.note-block p{ margin:0; font-size:15.5px; }
.note-block strong{ color:var(--slate); }
.sec--mid .note-block,.sec--deep .note-block,.sec--pop .note-block{ border-left-color:var(--white); }
.sec--mid .note-block strong,.sec--deep .note-block strong,.sec--pop .note-block strong{ color:var(--white); }
.tag{ display:inline-block; font-size:11px; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  padding:5px 10px; border-radius:var(--radius); background:#E4EAEF; color:var(--slate-dk); margin:0 6px 6px 0; }
.sec--mid .tag,.sec--deep .tag{ background:rgba(255,255,255,.13); color:var(--white); }

/* split: heading left, content right — used sparingly now */
.split{ display:grid; gap:var(--s4); }
@media(min-width:900px){ .split{ grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr); gap:var(--s5); align-items:center; } }
/* when the list is the whole right column, let it use the column, not 58ch */
.split > .peaklist{ max-width:none; margin-top:0; }

/* ---------------- statement ---------------- */
.statement{ background:var(--slate-deep); color:var(--on-slate); padding:var(--s7) 0; }
.statement .eyebrow{ color:var(--white); }
.statement h2{ font-family:var(--serif); font-size:var(--t-display); line-height:1.06;
  letter-spacing:-.02em; color:var(--white); max-width:17ch; margin:0; }
.statement p{ color:var(--on-slate); max-width:50ch; }
.statement .btnrow{ margin-top:var(--s3); }
.statement .peak{ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 11'%3E%3Cpath d='M1.2 9.8 11 1.4l9.8 8.4' fill='none' stroke='%23FFFFFF' stroke-width='2' stroke-linecap='square'/%3E%3C/svg%3E"); }
.statement .tlink{ color:var(--white); border-bottom-color:var(--white); }
.statement .btn--primary{ border-color:rgba(255,255,255,.6); }

/* ---------------- page head ---------------- */
.phead{ background:var(--slate); padding:var(--s6) 0; }
.phead h1{ color:var(--white); max-width:17ch; margin-bottom:var(--s2); }
.phead .lead{ color:var(--on-slate); max-width:54ch; }
.phead .eyebrow{ color:var(--white); }
.phead .peak{ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 11'%3E%3Cpath d='M1.2 9.8 11 1.4l9.8 8.4' fill='none' stroke='%23FFFFFF' stroke-width='2' stroke-linecap='square'/%3E%3C/svg%3E"); }

/* ---------------- anchor nav ---------------- */
.anchornav{ background:var(--paper-2); border-bottom:1px solid var(--hair); position:sticky; top:0; z-index:25; }
.anchornav ul{ list-style:none; margin:0; padding:0; display:flex; overflow-x:auto; }
.anchornav a{ display:block; padding:13px 15px 11px; font-size:14px; font-weight:600;
  color:var(--ink); text-decoration:none; white-space:nowrap; border-bottom:2px solid transparent; }
.anchornav a:hover{ color:var(--red-dk); border-bottom-color:var(--red); }
.anchornav li:first-child a{ padding-left:0; }

/* ---------------- numbered guide — two per row ---------------- */
.guide{ display:grid; gap:0 var(--s5); }
@media(min-width:860px){ .guide{ grid-template-columns:repeat(2,1fr); } }
/* each item stacks: number, heading, body. No inner two-column split, or the
   text column gets too narrow once the guide itself is halved. */
.guide__item{ display:block; padding:var(--s3) 0 var(--s4); border-top:1px solid var(--hair); }
.guide__n{ display:block; font-size:12px; font-weight:700; letter-spacing:.16em; color:var(--red-dk); margin-bottom:5px; }
.guide__item h3{ margin:0 0 8px; }
.guide__item .body p{ font-size:15.5px; color:var(--ink-2); margin-bottom:.7em; }
.guide__item .body p:last-child{ margin-bottom:0; }

/* ---------------- contact ---------------- */
/* ---- contact head: pitch left, details right ---- */
.contact-head{ display:grid; gap:var(--s4); }
@media(min-width:900px){
  .contact-head{ grid-template-columns:1.1fr .9fr; gap:var(--s6); align-items:center; }
}
.contact-head>*{ min-width:0; }
.contact-head h1{ max-width:none; }
.contact-head .lead{ max-width:46ch; }

.infolist{ list-style:none; margin:0; padding:0; }
.infolist li + li{ margin-top:var(--s3); padding-top:var(--s3); border-top:1px solid var(--hair-rev); }
.infolist .k{
  display:block; font-size:var(--t-eyebrow); font-weight:700; letter-spacing:.17em;
  text-transform:uppercase; color:var(--white); margin-bottom:5px;
}
.infolist .v{ display:block; font-size:17px; line-height:1.45; color:var(--on-slate); }
.infolist .v a{ color:var(--white); text-decoration:none; border-bottom:1px solid rgba(255,255,255,.45); }

/* Name tag on a personal number/address (2026-09-23). Two unlabelled numbers
   left the reader guessing which to ring; with an office line added that got
   worse. The tag sits INSIDE the anchor so it works wherever the anchor is
   display:block (hero) or inline (footer, info list) without extra layout. */
.who{
  font-size:12px; font-weight:700; letter-spacing:.1em; text-transform:uppercase;
  opacity:.72; margin-right:7px;
}
.infolist .v a:hover{ border-bottom-color:var(--white); }

/* ---------------- closer + footer ---------------- */
/* single centred column: copy, then the actions stacked beneath it */
.closer{ background:var(--slate); color:var(--on-slate); padding:var(--s6) 0; text-align:center; }
.closer__in{ max-width:620px; margin:0 auto; }
.closer h2{ color:var(--white); max-width:none; margin:0; }
.closer p{ color:var(--on-slate); margin:var(--s2) auto 0; max-width:48ch; }
.closer .btnrow{ justify-content:center; margin-top:var(--s4); }
.closer .btn--primary{ border-color:rgba(255,255,255,.6); }
.closer .tlink{ color:var(--white); border-bottom-color:var(--white); }

.foot{ background:var(--slate-deep); color:var(--on-slate); padding:var(--s5) 0 var(--s3); font-size:15px; }
.foot__grid{ display:grid; gap:var(--s4); }
@media(min-width:760px){ .foot__grid{ grid-template-columns:1.5fr 1fr 1fr; gap:var(--s5); } }
.foot .foot__h{ font-size:var(--t-eyebrow); letter-spacing:.17em; text-transform:uppercase; color:var(--white); margin:0 0 10px; font-weight:700; }
.foot a{ color:var(--white); text-decoration:none; }
.foot a:hover{ text-decoration:underline; }
.foot ul{ list-style:none; margin:0; padding:0; }
.foot li{ margin-bottom:7px; }
.foot p{ color:var(--on-slate); }
.foot__legal{ border-top:1px solid var(--hair-rev); margin-top:var(--s4); padding-top:var(--s3);
  display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap; font-size:13px; }

/* ---------------- mobile call bar ---------------- */
.callbar{ display:none; }
@media(max-width:760px){
  .callbar{ display:flex; position:fixed; left:0; right:0; bottom:0; z-index:60; background:var(--red-dk); }
  .callbar a{ flex:1; text-align:center; color:var(--white); text-decoration:none; font-weight:700; font-size:15.5px; padding:14px 8px; }
  .callbar a + a{ border-left:1px solid rgba(255,255,255,.28); }
  body{ padding-bottom:52px; }
}

/* ---------------- a11y ---------------- */
.skip{ position:absolute; left:-9999px; background:var(--red-dk); color:var(--white); padding:11px 16px; z-index:100; font-weight:600; text-decoration:none; }
.skip:focus{ left:10px; top:10px; }
@media(prefers-reduced-motion:reduce){ html{ scroll-behavior:auto; } *{ transition:none !important; } }

/* ---- white cards on a dark ground ----------------------------------
   .door is an <a>, so .sec--deep a{color:white} would paint its text
   white on a white card. The card keeps its light-ground colours. */
.sec--deep .door,.sec--mid .door{ background:var(--surface); border-color:var(--hair); color:var(--ink); }
.sec--deep .door h3,.sec--mid .door h3,.sec--deep .door .door__h,.sec--mid .door .door__h{ color:var(--slate); }
.sec--deep .door p,.sec--mid .door p{ color:var(--ink-2); }
.sec--deep .door__k,.sec--mid .door__k,
.sec--deep .door__go,.sec--mid .door__go{ color:var(--red-dk); }
.sec--deep .door:hover,.sec--mid .door:hover{ border-color:var(--red); box-shadow:0 4px 20px rgba(0,0,0,.28); }
/* the proof strip and this section are both deep slate, so drop the gap between them */
.proof + .sec--deep{ padding-top:var(--s4); }

/* ---- button label colours, specificity-proofed --------------------
   Context rules like `.nav a` and `.sec--deep a` are (0,1,1) and beat
   `.btn--primary` (0,1,0), which repainted button labels: the nav CTA
   rendered ink-on-red at 1.92:1 and .btn--rev rendered white-on-
   white at 1.00:1. Matching (0,1,1) later in the file settles it. */
a.btn--primary,a.btn--primary:hover{ color:var(--white); }
a.btn--rev,a.btn--rev:hover{ color:var(--slate-deep); }
a.btn--line{ color:var(--ink); }
.sec--pop a.btn--line,.sec--mid a.btn--line,.sec--deep a.btn--line{ color:var(--white); }
.sec--pop a.btn--line:hover,.sec--mid a.btn--line:hover,.sec--deep a.btn--line:hover{ color:var(--slate-deep); }

/* ordered list inside a panel (contact page) */
.panel ol{ font-size:15px; color:var(--ink-2); margin:0; padding-left:18px; }
.panel ol li{ margin-bottom:6px; }
.panel ol li:last-child{ margin-bottom:0; }

/* ---- promise list, horizontal ----------------------------------------
   Four across on desktop, two up at tablet, stacked on phones. Each item
   becomes a block with a rule over it rather than a label/description row. */
.plist--row{ display:grid; gap:var(--s3); }
@media(min-width:620px){ .plist--row{ grid-template-columns:repeat(2,1fr); gap:var(--s4) var(--s3); } }
@media(min-width:1000px){ .plist--row{ grid-template-columns:repeat(4,1fr); gap:var(--s4); } }
.plist--row li{
  display:block; padding:var(--s2) 0 0;
  border-top:2px solid var(--red); border-bottom:0;
}
.plist--row li:last-child{ border-bottom:0; }
.plist--row strong{ display:block; margin-bottom:7px; font-size:16px; line-height:1.3; }
.plist--row span{ display:block; font-size:14.5px; line-height:1.5; }
.sec--mid .plist--row li,.sec--deep .plist--row li,.sec--pop .plist--row li{ border-top-color:var(--white); }

/* ---- stacked statement: heading over prose, one column, full width ---- */
.statement--stack h2{ margin-bottom:var(--s3); max-width:none; }
.statement--stack p{ max-width:none; }


/* ============================================================
   ATMOSPHERE — abstract, not literal. Fractal turbulence with the
   horizontal frequency ~3x finer than the vertical, so density
   reads as drift rather than as noise or as cartoon clouds.
   Blurred, desaturated, soft-light so it only moves luminance.

   NOT tiled: the blur samples past the tile edge, so stitchTiles
   cannot make it seamless and a vertical seam shows up on wide
   screens. One instance is scaled with `cover` instead — 100% 100%
   squashes it flat on a wide short hero and it disappears.

   Opacity 0.58-0.72. Measured on rendered pixels: at 0.58 the
   bright-blue hero holds 7.02:1 for white headings (AAA) and
   5.48:1 for body. Pushing to 0.80 drops those to 6.48 and 5.06,
   which still passes AA but loses the AAA margin, so this sits
   just under. Darker fields carry more because soft-light does
   less work on a low-luminance base.
   ============================================================ */
.hero,.phead,.statement,.sec--mid,.sec--deep{ position:relative; isolation:isolate; overflow:hidden; }
.hero > *,.phead > *,.statement > *,.sec--mid > *,.sec--deep > *{ position:relative; z-index:1; }
.hero::before,.phead::before,.statement::before,.sec--mid::before,.sec--deep::before{
  content:""; position:absolute; inset:-2px; z-index:0; pointer-events:none;
  background-repeat:no-repeat; background-position:center; background-size:cover;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1200' height='700'%3E%3Cfilter id='a' x='-10%25' y='-10%25' width='120%25' height='120%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.0032 0.0105' numOctaves='3' seed='5'/%3E%3CfeGaussianBlur stdDeviation='7'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='1200' height='700' filter='url(%23a)'/%3E%3C/svg%3E");
  mix-blend-mode:soft-light;
}
.hero::before,.phead::before{ opacity:.58; }
.sec--mid::before{ opacity:.66; }
.statement::before,.sec--deep::before{ opacity:.72; }
/* decoration only */
@media(prefers-contrast:more){
  .hero::before,.phead::before,.statement::before,.sec--mid::before,.sec--deep::before{ display:none; }
}



/* ---- full-bleed image band ------------------------------------------
   Decoration and breathing room only. These are stock photographs, so
   they carry no caption and make no claim — nothing here implies the
   work is ours. Tinted toward the deep slate so they sit in the palette
   instead of reading as a dropped-in stock plate. */
.imgband{ position:relative; overflow:hidden; background:var(--slate-deep);
  height:clamp(190px,24vw,330px); }
.imgband img{ width:100%; height:100%; object-fit:cover; display:block; }
.imgband::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(180deg, rgba(34,48,60,.34) 0%, rgba(34,48,60,.62) 100%);
}

/* ---- hero contact block ----------------------------------------------
   Sits under the CTAs, in the left column beside the hero photograph. */
.hero__contact{
  display:grid; gap:var(--s3) var(--s5); margin-top:var(--s4);
  grid-template-columns:1fr; justify-content:start; max-width:560px;
  padding-top:var(--s3); border-top:1px solid rgba(255,255,255,.22);
}
@media(min-width:560px){ .hero__contact{ grid-template-columns:auto auto; } }
.hero__contact .k{
  display:block; font-size:var(--t-eyebrow); font-weight:700; letter-spacing:.17em;
  text-transform:uppercase; color:var(--white); margin-bottom:7px;
}
.hero__contact a{
  display:block; color:var(--on-slate); text-decoration:none;
  font-size:16px; line-height:1.65; width:fit-content;
}
.hero__contact a:hover{ color:var(--white); text-decoration:underline; text-underline-offset:3px; }
/* two stacked values per row in the contact panel */
.infolist .v + .v{ margin-top:4px; }

/* ---- homepage refinements ------------------------------------------- */

/* hero: copy left, photograph bleeding off the right edge */
.hero__grid{ display:grid; gap:var(--s4); align-items:center; }
.hero__grid > *{ min-width:0; }
.hero__copy{ min-width:0; }
@media(min-width:980px){
  /* stretch, not centre, so the photograph runs the full height of the hero
     rather than floating with blue above and below it */
  /* 1.02/.98 -> 1.35/.65 (2026-09-23). The copy column has to carry a much
     longer headline; the photograph is decorative stock that makes no claim,
     so it gives up the width rather than the CTA giving up the fold. */
  .hero__grid{ grid-template-columns:1.35fr .65fr; gap:var(--s6); align-items:stretch; }
  .hero__media{ margin-right:calc((100vw - min(100vw, var(--wrap)))/-2 - var(--gutter));
                margin-top:calc(var(--s7) * -1); margin-bottom:calc(var(--s7) * -1); }
}
.hero__media{ position:relative; }
.hero__media img{
  width:100%; height:100%; object-fit:cover; display:block;
  min-height:300px; max-height:520px;
}
@media(min-width:980px){ .hero__media img{ min-height:0; height:100%; max-height:none; } }

/* a heading that gets more size than the default h2 */
.h2--xl{ font-size:clamp(30px, 4.6vw, 58px); max-width:23ch; }
/* a heading held to one line */
.h2--line{ max-width:none; white-space:nowrap; }
@media(max-width:520px){ .h2--line{ white-space:normal; } }
/* section head that runs the full container width */
.shead--full h2{ max-width:none; }

/* a section standing in for a page head: it opens the page, so it carries
   the head's top padding rather than a mid-page section's. */
.sec--lead{ padding-top:var(--s6); }


/* ---- page head with a photograph ----------------------------------------
   Same shape as the home hero: copy left, image bleeding off the right edge.
   Padding here is --s6, so the negative margins match that, not --s7. */
.phead--split{ overflow:hidden; }
.phead__grid{ display:grid; gap:var(--s4); align-items:center; }
.phead__grid > *{ min-width:0; }
.phead--split h1{ max-width:14ch; }
.phead--split .lead{ max-width:46ch; }
.phead__media{ position:relative; }
.phead__media img{
  width:100%; height:100%; object-fit:cover; display:block;
  min-height:240px; max-height:400px;
}
@media(min-width:980px){
  .phead__grid{ grid-template-columns:1.05fr .95fr; gap:var(--s6); align-items:stretch; }
  .phead__media{ margin-right:calc((100vw - min(100vw, var(--wrap)))/-2 - var(--gutter));
                 margin-top:calc(var(--s6) * -1); margin-bottom:calc(var(--s6) * -1); }
  .phead__media img{ min-height:0; height:100%; max-height:none; }
}


/* ==========================================================================
   MOBILE REFINEMENTS
   Desktop is settled. Everything below is scoped to a max-width query and
   must stay that way — the layout at 1300px is signed off pixel for pixel.
   Breakpoints match the ones the affected components already use, so each
   rule covers exactly the range where that component is stacked.
   ========================================================================== */

/* --- the stacked hero: photograph before the contact details -------------
   Below 980px the hero is one column, so the source order puts the phone
   and email numbers between the buttons and the photograph. The photograph
   is the first thing pushed off screen, and those numbers already appear in
   the utility bar above and the call bar below. display:contents lifts the
   copy column's children into the hero grid so the photograph can be placed
   among them; the grid gap goes to zero because the children carry their
   own vertical rhythm. */
@media(max-width:979px){
  .hero__grid{ gap:0; }
  .hero__copy{ display:contents; }
  .hero__copy > .eyebrow{    order:1; }
  .hero__copy > h1{          order:2; }
  .hero__copy > .hero__sub{  order:3; }
  .hero__copy > .hero__cta{  order:4; }
  .hero__media{              order:5; margin:var(--s4) 0 0; }
  .hero__copy > .hero__contact{ order:6; }
}

/* --- service rows: park the arrow, don't orphan it -----------------------
   .srow only becomes a three-column grid at 820px. Below that the arrow
   drops onto its own line as a bare glyph with no label, which reads as a
   rendering fault. Pinning it to the right edge restores the affordance. */
@media(max-width:819px){
  .srow{ position:relative; padding-right:26px; }
  .srow .go{ position:absolute; right:0; top:var(--s3); }
}

@media(max-width:700px){
  /* Headings: the ch caps are a desktop measure. On a ~350px container they
     cut the line 70-95px short of the available width and force a ragged
     wrap. The container is already narrow enough to hold the measure. */
  .hero h1,.phead h1,.shead h1,.shead h2,
  .statement h2,.closer h2,.h2--xl{ max-width:none; }

  /* .sec drops to --s5 at this width; these never joined it, so they left
     80px voids of flat colour at the section seams. */
  .statement{ padding:var(--s5) 0; }
  .hero,.closer,.phead{ padding:var(--s5) 0; }

  /* The band subjects sit left of centre in their source frames. At this
     width a centred cover crop lands entirely on empty roof. */
  .imgband img{ object-position:left center; }

  /* No hero photograph on a phone. Stacked, it is a wide crop that costs a
     screenful before the reader reaches anything actionable, and the copy
     carries the section on its own. Above this width it stays. */
  .hero__media,.phead__media{ display:none; }

  /* The anchor nav is the only element that cannot fit its six labels at
     this width, and a second sticky bar competes with the call bar at the
     foot of the screen. The sections it jumps to are the page, in order, so
     nothing is lost by scrolling to them. It fits unaided from 701px up,
     which is why there is no fade here any more. */
  .anchornav{ display:none; }
}


/* ============================================================
   ROUGH-IN 2026-09-15 — affiliations
   (the "people" half was removed 2026-09-23; markup and CSS are
   preserved in _removed-people-section.*.bak beside the brief)
   Both blocks ship with visible dashed PLACEHOLDER frames. The
   dashed frame is scaffolding, not the design: when the real
   photo/logo lands, drop the --ph modifier and the frame goes
   with it, leaving the finished block. The frame is drawn in
   --ink-2 rather than --hair-2 because --hair-2 only reaches
   2.86:1 on the warm tint, under the 3:1 UI floor. Every slot is listed in
   PLACEHOLDERS.md. Nothing here states a fact we have not
   confirmed.
   ============================================================ */

/* ---- affiliations — logo strip ------------------------------------------
   Copy stripped 2026-09-15 at client's direction: logos only. So this is a
   quiet credential band, not a content section — shallower padding than .sec
   (which would leave the three marks stranded in a screenful of tint) and a
   hairline above to seat it against the section before it.
   Marks are shown at a consistent optical HEIGHT on a shared baseline rather
   than a shared width, because three trade-body logos never share an aspect
   ratio. max-width guards the one that turns out to be very wide. */
.credstrip{ padding:var(--s5) 0; border-top:1px solid var(--hair); }

/* Grid rather than flex-wrap, to match .steps and .shots — one column on
   phones, three from 620px. Tracks are minmax(0,1fr) rather than a bare 1fr
   so a wide mark can never push a track past its share of the row; grid
   minimums default to auto, which is content-based. Verified at true 320px
   and 375px viewports: no horizontal overflow, marks centred. */
.creds{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:minmax(0,1fr); gap:var(--s4); align-items:center;
}
/* Two marks, not three: BBB came off 2026-09-24 — its seal has to be the
   dynamic snippet from the BBB dashboard, not a static image. Two tracks
   rather than three with a hole where the third used to sit. */
@media(min-width:620px){
  .creds{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--s5); }
}

/* Cells stretch (the grid default) and the mark is centred by auto margins. */
.cred{ min-width:0; }
.cred__logo{
  display:flex; align-items:center; justify-content:center;
  height:84px; width:100%; max-width:230px; margin-inline:auto;
}
.cred__logo img{ max-height:100%; max-width:100%; width:auto; display:block; }

/* Per-mark heights. Three logos of different aspect ratios never balance at
   one shared height — a portrait seal reads tiny next to a wide wordmark at
   the same 84px. These are set by eye for equal visual mass, so each new mark
   gets its own value when the real packs land. */
.cred--ghba .cred__logo{ height:56px; }
.cred--ofh  .cred__logo{ height:64px; }

/* placeholder state — scaffolding, goes when the real mark lands */
.cred__logo--ph{
  box-sizing:border-box; padding:var(--s2);
  border:2px dashed var(--ink-2); border-radius:var(--radius);
  background:var(--surface);
  font-family:var(--sans); font-size:11.5px; font-weight:700; line-height:1.4;
  letter-spacing:.08em; text-transform:uppercase; color:var(--ink-2);
  text-align:center;
}


/* ============================================================
   WORK / PORTFOLIO GALLERY — added 2026-09-23
   Three across on desktop, two at tablet, one on phones. 3:2
   landscape frames so a phone photo held sideways drops in
   without recomposition — and so twelve photos taken on twelve
   different days still line up as a set.
   ============================================================ */
.shots{ display:grid; grid-template-columns:minmax(0,1fr); gap:var(--s4); }
@media(min-width:620px){ .shots{ grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media(min-width:980px){ .shots{ grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--s4) var(--s3); } }

/* Two-up. Tile and flat carry two photographs where shingle and metal carry
   three, so they get their own track count rather than sitting as two cells
   of a three-column grid with a hole where the third should be. The images
   come out larger, which reads as a deliberate change of pace instead of a
   gap — and it is why those two are supplied at 1200x800 rather than 900x600. */
@media(min-width:980px){ .shots--2{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--s4); } }

.shot{ margin:0; min-width:0; }
.shot__img{
  display:block; width:100%; aspect-ratio:3/2; margin-bottom:var(--s2);
  object-fit:cover; background:var(--paper-2); border-radius:var(--radius);
  /* height:auto is load-bearing. The <img> carries width/height attributes
     for CLS, and the height attribute acts as a presentational hint equal to
     height:600px. With height not auto, aspect-ratio cannot drive the box —
     the frames rendered 351x600 portrait instead of 3:2 landscape. */
  height:auto;
}
/* placeholder state — scaffolding, goes when a real photo lands */
.shot__img--ph{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:6px; text-align:center; padding:var(--s3);
  border:2px dashed var(--ink-2); background:var(--paper-2);
  font-family:var(--sans); font-size:12px; font-weight:700; line-height:1.4;
  letter-spacing:.08em; text-transform:uppercase; color:var(--ink-2);
}
.shot__img--ph em{ font-style:normal; font-weight:600; letter-spacing:.01em;
  text-transform:none; font-size:11.5px; opacity:.75; max-width:24ch; }
.sec--tint .shot__img--ph{ background:var(--paper); }

.shot figcaption{ font-size:14.5px; line-height:1.5; color:var(--ink-2); max-width:42ch; }
.sec--mid .shot figcaption,.sec--deep .shot figcaption,.sec--pop .shot figcaption{ color:var(--on-slate); }
