/* More Steel Inc — page below the scroll-cinematic hero.
   Kept in its own file because the site ships script-src/style-src discipline
   and because the hero engine owns everything inside #world. */

:root{
  --ink:#f2f4f7; --ink-soft:rgba(242,244,247,.72); --ink-faint:rgba(242,244,247,.58);
  /* Steel ramp. Same hue family as the logo's chrome (--steel), but held
     near 11% saturation instead of 21% so the darks read graphite rather than
     navy, and spaced far enough apart that a raised block is visibly raised. */
  --bg-2:#090A0C;        /* deepest - hero ground and footer */
  --bg:#0E1013;          /* the page */
  --bg-alt:#171A1F;      /* alternating band */
  --bg-card:#1D2127;     /* anything raised off the page */
  --bg-card-2:#262B33;   /* raised and hovered */
  --line:rgba(186,194,206,.20); --line-soft:rgba(186,194,206,.13);
  /* One pixel of light on a top edge is what separates plate from paint. */
  --edge:rgba(226,232,240,.09);
  --accent:#2265D2;
  --accent-ink:#7fb0f5;
  --steel:#BAC2CE; --steel-dim:#7F8894;
  --disp:'Saira Stencil One',system-ui,sans-serif;
  --disp-2:'Chakra Petch',system-ui,sans-serif;
  --body:'Chakra Petch',system-ui,sans-serif;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion: reduce){ html{scroll-behavior:auto} }
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--body);-webkit-font-smoothing:antialiased}
img{max-width:100%;height:auto}
a{color:#7fb0f5}

.wrap{max-width:1240px;margin:0 auto}
.sec{padding:clamp(44px,6vh,84px) 6vw}
/* The band now differs from the page by enough to see, and takes a soft
   light fall from its top edge so it reads as a plate rather than a fill. */
.sec--alt{
  background:linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px),var(--bg-alt);
  border-block:1px solid var(--line-soft);
}
.rule{display:flex;align-items:center;gap:16px;margin:0 0 clamp(28px,4vh,48px)}
.rule .n{font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.24em;white-space:nowrap;color:var(--steel)}
.rule .dim{flex:1;display:flex;align-items:center;gap:0}
.rule .ln{flex:1;height:1px;background:var(--line)}
/* Extension ticks. Siblings of .ln, never children - .ln is scaled. */
.rule .t{width:1px;height:9px;background:var(--line);flex:none}
.anim [data-anim=draw] .t{opacity:0;transition:opacity .4s ease .55s}
.anim [data-anim=draw].is-in .t{opacity:1}
.rule a{font:600 13px/1 var(--body);letter-spacing:.08em;text-transform:uppercase;white-space:nowrap;color:var(--ink-soft);text-decoration:none}
.rule a:hover{color:var(--ink)}

h2.big{margin:0 0 18px;font:400 clamp(32px,5vw,62px)/1.02 var(--disp);text-transform:uppercase;letter-spacing:.005em;max-width:17ch}
p.lede:last-child{margin-bottom:0}
p.lede{margin:0 0 clamp(22px,3.2vh,36px);font:700 clamp(20.5px,2.25vw,26px)/1.4 var(--body);color:rgba(242,244,247,.76);max-width:44ch;text-wrap:pretty}

/* stat strip */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(190px,100%),1fr));gap:1px;background:var(--line-soft);border-block:1px solid var(--line-soft)}
.stats div{background:var(--bg-card);box-shadow:inset 0 1px 0 var(--edge);padding:32px 4vw;display:flex;flex-direction:column;gap:8px}
.stats b{font:400 clamp(36px,4.4vw,56px)/1 var(--disp);letter-spacing:.01em}
.stats span{font:500 12px/1.4 ui-monospace,Menlo,monospace;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-faint)}

/* service cards */
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(250px,100%),1fr));gap:1px}
.card{background:var(--bg-card);outline:1px solid var(--line);box-shadow:inset 0 1px 0 var(--edge);padding:30px 28px 34px;display:flex;flex-direction:column;gap:13px;min-height:196px}
/* Each card now leads with a photo of that exact service, from the client's own
   jobs. Full-bleed to the card edge, so it reads as the card's subject rather
   than as decoration sitting inside a box. */
.card__img{display:block;width:calc(100% + 56px);max-width:none;margin:-30px -28px 4px;aspect-ratio:4/3;object-fit:cover;background:#0b0e13}
.card .n{font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.2em;color:var(--steel)}
.card h3{margin:0;font:700 clamp(20px,2.2vw,26px)/1.15 var(--disp-2);text-transform:uppercase;letter-spacing:.02em}
.card p{margin:0;font:700 19px/1.42 var(--body);color:rgba(242,244,247,.82);text-wrap:pretty}

/* work */
.work{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));gap:14px}
.work figure{margin:0;position:relative;overflow:hidden;background:var(--bg-card);border:1px solid var(--line)}
.work img{display:block;width:100%;aspect-ratio:4/3;object-fit:cover;background:#0b0e13}
.work figcaption{padding:14px 18px;font:500 11.5px/1.5 ui-monospace,Menlo,monospace;letter-spacing:.13em;color:var(--ink-faint)}
.work .badge{position:absolute;left:14px;top:14px;font:600 10px/1 ui-monospace,Menlo,monospace;letter-spacing:.16em;padding:7px 10px;background:rgba(5,7,11,.78);border:1px solid rgba(255,255,255,.18);color:rgba(242,244,247,.85)}

/* split */
.split{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(320px,100%),1fr));gap:clamp(30px,5vw,68px);align-items:center}
.split h2{margin:0 0 16px}
.split p{margin:0 0 20px;font:700 clamp(20px,2.1vw,24.5px)/1.45 var(--body);color:rgba(242,244,247,.78);max-width:42ch;text-wrap:pretty}
.sig{font:700 15px/1.5 var(--body);letter-spacing:.06em;color:rgba(242,244,247,.85)}

/* chips */
.logoband{background:#EEF1F6;border-block:1px solid rgba(0,0,0,.12);padding:clamp(30px,3.8vw,48px) 6vw}
.logoband__in{max-width:1240px;margin:0 auto}
.logoband__lab{margin:0 0 clamp(26px,3.4vw,44px);text-align:center;text-transform:uppercase;font:700 clamp(16px,2vw,22px)/1.3 var(--disp-2);letter-spacing:.13em;color:rgba(18,24,34,.62)}
.logos{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,1fr);align-items:center;justify-items:center;gap:clamp(20px,3vw,38px)}@media(min-width:1000px){.logos{grid-template-columns:repeat(4,1fr)}}
.logos li{display:flex;align-items:center;justify-content:center;min-height:84px;flex:0 1 auto}
.logos img{display:block;width:auto;height:auto;max-height:var(--lh,48px);max-width:min(var(--lw,240px),100%);object-fit:contain;opacity:.94;transition:opacity .2s ease}
@media(max-width:640px){.logos img{max-height:calc(var(--lh,48px)*.78)}}
.logos li:hover img{opacity:1}
.logos__wm{font:700 18px/1.3 var(--disp-2);letter-spacing:.02em;color:rgba(242,244,247,.8);text-align:center;text-wrap:balance}
@media (prefers-reduced-motion:reduce){.logos img{transition:none}}
.chips{display:flex;flex-wrap:wrap;gap:8px}
.chips span{font:600 15px/1 var(--body);letter-spacing:.04em;white-space:nowrap;padding:11px 14px;background:rgba(255,255,255,.05);border:1px solid var(--line);color:rgba(242,244,247,.78)}
.chips.mono span{font:600 10.5px/1 ui-monospace,Menlo,monospace;letter-spacing:.14em;padding:10px 13px}

/* buttons */
.btns{display:flex;flex-wrap:wrap;gap:12px}
.btn{display:inline-flex;align-items:center;justify-content:center;min-height:56px;padding:0 28px;text-decoration:none;font:700 17.5px/1 var(--body);letter-spacing:.02em;border:1px solid transparent}
.btn--p{background:var(--accent);color:#fff;text-transform:uppercase}
.btn--p:hover{background:#1b57bb;color:#fff}
.btn--g{border-color:rgba(242,244,247,.4);color:var(--ink);font:700 17.5px/1 var(--disp-2);letter-spacing:.04em}
.btn--g:hover{border-color:var(--ink);color:var(--ink)}
.btn--dark{background:#0b0d11;color:#fff;font:700 17.5px/1 var(--disp-2);letter-spacing:.04em}

/* closing CTA */
.cta{background:var(--accent);color:#fff;padding:clamp(52px,7.5vh,96px) 6vw}
.cta .in{max-width:1240px;margin:0 auto;display:flex;flex-wrap:wrap;gap:36px;align-items:flex-end;justify-content:space-between}
.cta .eye{font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.24em;color:rgba(255,255,255,.9)}
.cta h2{margin:16px 0;font:400 clamp(34px,5.6vw,72px)/0.98 var(--disp);text-transform:uppercase;letter-spacing:.005em}
.cta p{margin:0;font:700 clamp(20.5px,2.25vw,26px)/1.4 var(--body);color:rgba(255,255,255,.84);max-width:36ch;text-wrap:pretty}
.cta .col{display:flex;flex-direction:column;gap:12px}

/* disclosure + footer */
.disclose{background:var(--bg-2);border-top:1px solid var(--line-soft);padding:22px 6vw;font:500 14.5px/1.65 var(--body);color:var(--ink-faint)}
footer{background:var(--bg-2);border-top:1px solid var(--line-soft);padding:52px 6vw 36px;font:500 16px/1.7 var(--body);color:rgba(242,244,247,.62)}
footer .grid{max-width:1240px;margin:0 auto;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(210px,100%),1fr));gap:40px}
footer .brand{font:700 20px/1.1 var(--disp-2);letter-spacing:.1em;color:var(--ink)}
/* Full lockup, no container: the nameplate already says the name. */
footer .brandmark{height:118px;width:auto;display:block;margin:0 0 16px}

/* One oversized ghost stamp on the blue band, off a 4K master, so it holds a
   clean edge at 660px instead of being a 298px file stretched four times over.
   The opacity was .1 only to hide that softness; a sharp mark reads as a
   deliberate watermark at .13.

   It is a background rather than an <img> because it is decorative and hidden
   below 820px, and a display:none <img> is still downloaded on most browsers.
   Inside a min-width query nothing requests it on a phone at all. */
.cta{position:relative;overflow:hidden;isolation:isolate}
@media (min-width:821px){
  .cta::before{
    content:'';position:absolute;z-index:-1;pointer-events:none;
    right:-5%;top:50%;translate:0 -50%;
    width:min(660px,58%);aspect-ratio:1320/761;
    background:url(/assets/img/logo-ghost.f8dca42e.webp) center/contain no-repeat;
    opacity:.20;
  }
}
footer h3{margin:0 0 4px;font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.22em;color:var(--steel)}
/* 44px minimum touch target (WCAG 2.5.8). These were 29px tall, which is a
   miss on a page whose whole conversion path is "tap the phone number". */
footer a{color:rgba(242,244,247,.72);text-decoration:none;display:flex;align-items:center;min-height:44px;padding:2px 0}
footer a:hover{color:var(--ink)}
footer .bot{max-width:1240px;margin:40px auto 0;padding-top:18px;border-top:1px solid rgba(255,255,255,.08);display:flex;flex-wrap:wrap;gap:12px;justify-content:space-between;font-size:12.5px}
footer .bot>span{white-space:nowrap}
footer .bot a{display:inline-flex;min-height:0;padding:0}
footer .phone{font:700 21px/1.1 var(--disp-2);letter-spacing:.04em;color:var(--ink)}

/* the page needs a way to convert before the film ends */
.railcta{position:fixed;right:18px;bottom:18px;z-index:80;display:inline-flex;align-items:center;gap:9px;min-height:50px;padding:0 20px;background:var(--accent);color:#fff;text-decoration:none;font:700 17px/1 var(--disp-2);letter-spacing:.03em;box-shadow:0 6px 26px rgba(0,0,0,.45)}
.railcta:hover{background:#1b57bb;color:#fff}
@media (max-width:640px){ .railcta{left:14px;right:14px;justify-content:center} }
@supports (padding:max(0px)){ .railcta{bottom:max(18px,env(safe-area-inset-bottom))} }

/* The who-you-are-hiring photo is a portrait phone shot of the crew. Cap the
   height so the split stays balanced, and hold the crop high so the hard hats
   stay in frame. */
#about img{width:100%;max-height:560px;object-fit:cover;object-position:center 26%}

/* ==========================================================================
   Multi-page components. The site used to be one page with anchor links, so
   none of this existed: every page below the home page needs its own header,
   and the service pages need a way to lay out scope, sequence and questions.
   ========================================================================== */

/* Compact page header. Home keeps the film; every other page gets a still. */
.phero{position:relative;min-height:clamp(340px,46vh,520px);display:flex;align-items:flex-end;overflow:hidden;isolation:isolate}
.phero__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-2}
.phero__scrim{position:absolute;inset:0;z-index:-1;background:linear-gradient(to right,rgba(5,7,11,.90) 0%,rgba(5,7,11,.64) 46%,rgba(5,7,11,.20) 82%,rgba(5,7,11,.12) 100%),linear-gradient(to top,rgba(5,7,11,.74) 0%,rgba(5,7,11,.10) 52%,rgba(5,7,11,.42) 100%)}
/* .wrap centres and caps; the inset comes from .sec, and .phero is not one.
   It cannot go on .phero either, because .phero__img and .phero__scrim are
   pinned with inset:0 and would inset with it. Widening the box by the same
   6vw it spends keeps this copy on the body text's left edge at every width. */
.phero__inner{max-width:calc(1240px + 12vw);padding-inline:6vw;padding-block:clamp(64px,8.5vh,104px) clamp(26px,4vh,40px)}
.phero__eyebrow{margin:0 0 10px;font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.24em;color:var(--steel)}
.phero__h1{margin:0;font:400 clamp(36px,6.4vw,78px)/0.97 var(--disp);text-transform:uppercase;letter-spacing:.005em;color:var(--ink);text-wrap:balance}
.phero__lede{margin:18px 0 0;max-width:44ch;font:700 clamp(20.5px,2.4vw,27px)/1.4 var(--body);color:rgba(242,244,247,.82);text-wrap:pretty}

.crumb{margin:0 0 20px;font:500 12px/1.5 ui-monospace,Menlo,monospace;letter-spacing:.1em;color:var(--ink-faint)}
/* Breadcrumb links get a full 44px tap height (WCAG 2.5.8) with the extra
   height taken back off the row, so they stay visually compact. */
.crumb{display:flex;flex-wrap:wrap;align-items:center;margin-block:-14px 6px}
.crumb a,.crumb [aria-current]{display:inline-flex;align-items:center;min-height:44px;padding-inline:2px}
.crumb a{color:rgba(242,244,247,.72);text-decoration:none}
.crumb a:hover{color:var(--ink)}
.crumb span{opacity:.5;padding:0 4px}
.crumb [aria-current]{color:var(--accent);opacity:1}

.wrap--narrow{max-width:860px}
.dual>p.lede{margin-bottom:0}
@media(min-width:920px){.dual{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,3.4vw,56px)}}
.dual+.work{margin-top:clamp(34px,5vh,56px)}
p.lede--wide{max-width:78ch}

/* Service cards that are actual links to actual pages. */
.svcgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr));gap:1px;margin-top:34px}
.svccard{display:flex;flex-direction:column;background:var(--bg-card);outline:1px solid var(--line);text-decoration:none;color:inherit;transition:background .18s ease,outline-color .18s ease}
.svccard:hover{background:var(--bg-card-2);outline-color:rgba(34,101,210,.55)}
.svccard img{display:block;width:100%;aspect-ratio:4/3;object-fit:cover;background:var(--bg-alt)}
.svccard__body{padding:26px 26px 30px;display:flex;flex-direction:column;gap:11px;flex:1}
.svccard__body .n{font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.2em;color:var(--steel)}
.svccard__body h2,.svccard__body h3{margin:0;font:700 clamp(19px,2.1vw,25px)/1.15 var(--disp-2);text-transform:uppercase;letter-spacing:.02em}
.svccard__body p{margin:0;font:700 19px/1.42 var(--body);color:rgba(242,244,247,.8);text-wrap:pretty}
.svccard__go{margin-top:auto;padding-top:12px;font:600 12px/1 ui-monospace,Menlo,monospace;letter-spacing:.14em;color:var(--steel)}
.svccard:hover .svccard__go{color:#7fb0f5}

/* Scope: what a package actually includes. */
.scope{list-style:none;margin:30px 0 0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(330px,100%),1fr));gap:1px;background:var(--line-soft)}
.scope li{background:var(--bg-card);box-shadow:inset 0 1px 0 var(--edge);padding:22px 24px 24px 52px;display:flex;flex-direction:column;gap:7px}
.scope strong{font:700 19px/1.25 var(--disp-2);letter-spacing:.02em;color:var(--ink)}
.scope span{font:700 19px/1.42 var(--body);color:rgba(242,244,247,.8)}

/* Sequence from award to handover. */
.steps{list-style:none;margin:32px 0 0;padding:0;display:flex;flex-direction:column;gap:1px;background:var(--line-soft)}
.steps li{background:var(--bg-card);box-shadow:inset 0 1px 0 var(--edge);display:flex;gap:22px;padding:24px 26px}
.steps__n{flex:none;font:700 clamp(22px,3vw,34px)/1 var(--disp-2);color:var(--steel-dim);min-width:56px}
.steps h3{margin:0 0 7px;font:700 clamp(18px,2.1vw,22px)/1.2 var(--disp-2);text-transform:uppercase;letter-spacing:.02em}
.steps p{margin:0;font:700 20.5px/1.45 var(--body);color:rgba(242,244,247,.82);max-width:52ch;text-wrap:pretty}

/* Three-up prose columns. */
.cols3{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr));gap:clamp(24px,3vw,44px);margin-top:34px}
.cols3 h3{margin:0 0 12px;font:700 clamp(19px,2.2vw,24px)/1.15 var(--disp-2);text-transform:uppercase;letter-spacing:.02em}
.cols3 p{margin:0;font:700 20.5px/1.45 var(--body);color:rgba(242,244,247,.76);text-wrap:pretty}

/* Service areas. */
.areas{display:grid;grid-template-columns:1fr;gap:1px;background:var(--line-soft);margin-top:30px}
@media(min-width:520px){.areas{grid-template-columns:repeat(2,1fr)}}
@media(min-width:760px){.areas{grid-template-columns:repeat(3,1fr)}}
@media(min-width:1060px){.areas{grid-template-columns:repeat(4,1fr)}}
.area{background:var(--bg-card);box-shadow:inset 0 1px 0 var(--edge);padding:20px 22px}
.area h3{margin:0 0 7px;font:700 20px/1.15 var(--disp-2);text-transform:uppercase;letter-spacing:.03em}
.area p{margin:0;font:700 19.5px/1.4 var(--body);color:rgba(242,244,247,.82);text-wrap:pretty}

/* FAQ. <details> keeps this working with script-src 'self' and no JS at all. */
.faq{margin-top:28px;display:flex;flex-direction:column;gap:1px;background:var(--line-soft)}
.faq details{background:var(--bg-card);box-shadow:inset 0 1px 0 var(--edge)}
.faq summary{cursor:pointer;list-style:none;padding:21px 24px;font:700 20px/1.35 var(--body);color:var(--ink);display:flex;justify-content:space-between;gap:18px;align-items:center;min-height:44px}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";font:700 22px/1 var(--disp-2);color:var(--steel);flex:none}
.faq details[open] summary::after{content:"–"}
.faq p{margin:0;padding:0 24px 24px;font:700 20.5px/1.45 var(--body);color:rgba(242,244,247,.82);max-width:54ch;text-wrap:pretty}

/* Contact rows. */
.contactlist{margin-top:26px;display:flex;flex-direction:column;gap:1px;background:var(--line-soft)}
.contactlist__row{background:var(--bg);display:flex;align-items:center;gap:18px;padding:16px 20px;min-height:44px;text-decoration:none;color:inherit}
a.contactlist__row:hover{background:#0e131b}
.contactlist__k{flex:none;min-width:92px;font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.18em;color:var(--steel)}
.contactlist__v{font:700 clamp(17px,2vw,22px)/1.2 var(--disp-2);letter-spacing:.03em;color:var(--ink)}

/* Active nav item. */
.nav__links a[aria-current="page"]{color:var(--ink)}
.nav__links a[aria-current="page"]::after{content:"";display:block;height:2px;margin-top:5px;background:var(--accent)}

@media (max-width:760px){
  .steps li{flex-direction:column;gap:10px}
  .steps__n{min-width:0}
  .phero{min-height:300px}
}

/* Their mark, sitting with the eyebrow on every page header. */
.phero__eyebrow{display:flex;align-items:center;gap:11px}
.phero__mark{width:auto;height:22px;flex:none;display:block;filter:drop-shadow(0 2px 7px rgba(0,0,0,.6))}

/* Service intro sits beside a short at-a-glance panel, so the page does not
   open with one narrow column of prose and a lot of empty space. */
.intro2{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);gap:clamp(28px,4vw,60px);align-items:start}
.glance{background:var(--bg-card);outline:1px solid var(--line);padding:26px 26px 28px}
.glance h2{margin:0 0 16px;font:600 13px/1 ui-monospace,Menlo,monospace;letter-spacing:.2em;text-transform:uppercase;color:var(--steel)}
.glance dl{margin:0 0 26px;display:flex;flex-direction:column;gap:26px}
.glance dt{font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.16em;text-transform:uppercase;color:rgba(242,244,247,.5)}
.glance dd{margin:6px 0 0;font:700 19.5px/1.4 var(--body);color:rgba(242,244,247,.86)}
@media (max-width:900px){.intro2{grid-template-columns:1fr}}



/* Lead form, matching the pattern on the other client sites. Inputs are 48px so
   they clear the 44px touch minimum, because these get filled in on a phone. */
.lead{margin:0 0 26px;display:flex;flex-direction:column;gap:14px}
.lead__row{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(210px,100%),1fr));gap:14px}
.lead label{display:flex;flex-direction:column;gap:7px;font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.16em;text-transform:uppercase;color:rgba(242,244,247,.6)}
.lead input,.lead select,.lead textarea{
  width:100%;min-height:48px;padding:12px 14px;background:#0b0e13;color:var(--ink);
  border:1px solid var(--line);border-radius:0;font:600 18px/1.4 var(--body);
  text-transform:none;letter-spacing:0}
.lead textarea{min-height:110px;resize:vertical}
.lead input:focus-visible,.lead select:focus-visible,.lead textarea:focus-visible{
  outline:2px solid var(--accent-ink);outline-offset:1px;border-color:transparent}
.lead input::placeholder,.lead textarea::placeholder{color:rgba(242,244,247,.34)}
.lead [aria-invalid="true"]{border-color:#e0776c}
.lead button{align-self:flex-start;min-height:48px;cursor:pointer;border:0}
.lead button[disabled]{opacity:.6;cursor:default}
/* Honeypot sits off-screen rather than display:none, so bots that check
   computed style still fill it in. */
.lead__hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
/* Consent is a checkbox beside running text, so it must not inherit the
   uppercase mono label styling. */
.lead label.lead__consent{flex-direction:row;align-items:flex-start;gap:11px;
  font:500 15px/1.6 var(--body);letter-spacing:0;text-transform:none;color:rgba(242,244,247,.62)}
.lead label.lead__consent input{width:20px;height:20px;min-height:0;flex:none;margin-top:2px;padding:0}
.lead label.lead__consent a{color:var(--accent-ink)}
.lead__alt{margin:0;font:600 17px/1.5 var(--body);color:rgba(242,244,247,.75)}
.lead__alt a{color:var(--accent-ink);display:inline-flex;align-items:center;min-height:44px;padding-inline:2px}
.lead__status{margin:0;padding:13px 15px;font:600 16px/1.5 var(--body);border:1px solid}
.lead__status--ok{color:#c8e6c9;border-color:rgba(120,200,130,.5);background:rgba(60,120,70,.16)}
.lead__status--err{color:#ffd7d2;border-color:rgba(230,120,110,.55);background:rgba(150,50,45,.18)}

/* Legal pages: long-form running text. */
.story h2,.legal h2{margin:34px 0 10px;font:700 clamp(19px,2.2vw,24px)/1.2 var(--disp-2);text-transform:uppercase;letter-spacing:.02em}
.legal p{margin:0 0 15px;font:500 17px/1.68 var(--body);color:var(--ink-soft);max-width:62ch;text-wrap:pretty}
.wrap--narrow.story{max-width:50ch}
@media (min-width:940px){
  .wrap--narrow.story{max-width:min(104ch,1180px);columns:2;column-gap:clamp(44px,4.6vw,80px)}
  .story p{break-inside:avoid;margin-bottom:22px}
  .story p:first-child{margin-top:0}
}
.story p{margin:0 0 20px;font:700 clamp(20px,2.1vw,24.5px)/1.45 var(--body);color:rgba(242,244,247,.79);text-wrap:pretty}
.story a,.legal a{color:var(--accent-ink)}
.legal__updated{font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.16em;text-transform:uppercase;color:rgba(242,244,247,.45)}

/* Consent links are inline inside a sentence, so the WCAG inline exception
   applies, but they are legally required links: give them a bigger hit area
   than 13px without breaking the run of text. */
.lead label.lead__consent a{padding-block:6px;display:inline-block}

/* Coverage map. Three tiers, and the legend repeats the palette baked into the
   SVG because the map is an <img> and cannot inherit page colours. */
.cvblock{margin-top:30px;display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);gap:clamp(24px,3vw,44px);align-items:center}
.cvblock__map{display:block;width:100%;height:auto;background:#0b0e13;border:1px solid var(--line)}
.cvlegend{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:20px}
.cvlegend li{display:grid;grid-template-columns:18px 1fr;gap:6px 12px;align-items:start}
.cvlegend strong{font:700 19px/1.25 var(--disp-2);letter-spacing:.02em;color:var(--ink)}
.cvlegend__d{grid-column:2;font:700 18.5px/1.4 var(--body);color:rgba(242,244,247,.8);text-wrap:pretty}
.sw{width:18px;height:18px;margin-top:2px;border:1px solid}
.sw--home{background:#2265D2;border-color:#9cc4fb}
.sw--se{background:#1d4f9e;border-color:#3b7ad4}
.sw--reach{background:#1a2a41;border-color:#7fb0f5;border-style:dashed}
.sw--pin{border:0;background:none;color:#fff;font-size:19px;line-height:17px;text-align:center}
@media (max-width:900px){.cvblock{grid-template-columns:1fr}}

/* ============================================================ motion
 * Every start state below is gated on .anim, which assets/anim.js adds to
 * <html>. No script, blocked script, or reduced-motion preference means the
 * class never lands and the page renders in its finished state. Nothing here
 * is allowed to hide content on its own.
 *
 * One effect per kind of block. A rule draws, a headline wipes, a photo
 * uncovers, a scope cell catches a light sweep, a step latches in from the
 * left. Using one motion everywhere is what makes a site feel templated.
 * Only transform, opacity, filter and clip-path move, so none of this
 * triggers layout. */

/* section rule: the hairline runs out from the left, the number lifts after it */
.anim [data-anim=draw] .ln{transform:scaleX(0);transform-origin:left;transition:transform .9s cubic-bezier(.16,.84,.44,1)}
.anim [data-anim=draw].is-in .ln{transform:scaleX(1)}
.anim [data-anim=draw] .n{opacity:0;transform:translateY(7px);transition:opacity .5s ease .12s,transform .5s ease .12s}
.anim [data-anim=draw].is-in .n{opacity:1;transform:none}

/* display headline: uncovers upward behind its own baseline */
.anim [data-anim=wipe]{clip-path:inset(0 0 108% 0);transform:translateY(12px);transition:clip-path 1s cubic-bezier(.16,.84,.44,1),transform 1s cubic-bezier(.16,.84,.44,1)}
.anim [data-anim=wipe].is-in{clip-path:inset(0);transform:none}

/* running prose: rises out of focus */
.anim [data-anim=defog]{opacity:0;transform:translateY(18px);transition:opacity .7s ease,transform .8s cubic-bezier(.16,.84,.44,1)}
.anim [data-anim=defog].is-in{opacity:1;transform:none}

/* client marks: lift and settle in sequence */
.anim [data-anim=pop]{opacity:0;transform:translateY(15px) scale(.93);transition:opacity .5s ease,transform .65s cubic-bezier(.2,.9,.3,1);transition-delay:calc(var(--i,0)*70ms)}
.anim [data-anim=pop].is-in{opacity:1;transform:none}

/* credential chips: widen from their left edge */
.anim [data-anim=latch]{opacity:0;transform:scaleX(.72);transform-origin:left;transition:opacity .4s ease,transform .55s cubic-bezier(.2,.9,.3,1);transition-delay:calc(var(--i,0)*45ms)}
.anim [data-anim=latch].is-in{opacity:1;transform:none}

/* stat cells: rise, then the figure decodes (assets/anim.js) */
.anim [data-anim=tally]{opacity:0;transform:translateY(20px);transition:opacity .5s ease,transform .65s cubic-bezier(.2,.9,.3,1);transition-delay:calc(var(--i,0)*90ms)}
.anim [data-anim=tally].is-in{opacity:1;transform:none}
.anim [data-anim=tally] b{font-variant-numeric:tabular-nums}

/* service cards: tip up onto their front edge */
.anim [data-anim=deal]{opacity:0;transform:perspective(1000px) rotateX(7deg) translateY(32px);transform-origin:50% 100%;transition:opacity .6s ease,transform .85s cubic-bezier(.16,.84,.44,1);transition-delay:calc(var(--i,0)*95ms)}
.anim [data-anim=deal].is-in{opacity:1;transform:none}

/* photographs: a panel pulls off the frame while the image eases back to size */
.anim [data-anim=curtain]::after{content:"";position:absolute;inset:0;z-index:3;background:var(--bg-card);transform:scaleY(1);transform-origin:top;transition:transform .85s cubic-bezier(.7,0,.2,1);transition-delay:calc(var(--i,0)*75ms)}
.anim [data-anim=curtain].is-in::after{transform:scaleY(0);transform-origin:bottom}
.anim [data-anim=curtain] img{transform:scale(1.14);transition:transform 1.3s cubic-bezier(.16,.84,.44,1);transition-delay:calc(var(--i,0)*75ms)}
.anim [data-anim=curtain].is-in img{transform:none}

/* two-column blocks: the halves come in from opposite sides */
.anim [data-anim=part]{opacity:0;transform:translateX(-30px);transition:opacity .7s ease,transform .9s cubic-bezier(.16,.84,.44,1)}
.anim [data-anim=part]:nth-child(even){transform:translateX(30px)}
.anim [data-anim=part].is-in{opacity:1;transform:none}

/* scope cells: a light passes across each one in turn */
.anim [data-anim=sweep]{opacity:0;position:relative;overflow:hidden;transition:opacity .45s ease;transition-delay:calc(var(--i,0)*55ms)}
.anim [data-anim=sweep].is-in{opacity:1}
.anim [data-anim=sweep]::before{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;transform:translateX(-130%);
  background:linear-gradient(100deg,transparent 34%,rgba(127,176,245,.15) 50%,transparent 66%)}
.anim [data-anim=sweep].is-in::before{animation:ms-sweep 1.15s cubic-bezier(.3,0,.2,1) forwards;animation-delay:calc(var(--i,0)*55ms + 120ms)}
@keyframes ms-sweep{to{transform:translateX(130%)}}

/* numbered steps: the row latches in, then its figure snaps to size */
.anim [data-anim=ladder]{opacity:0;transform:translateX(-28px);transition:opacity .5s ease,transform .7s cubic-bezier(.16,.84,.44,1);transition-delay:calc(var(--i,0)*110ms)}
.anim [data-anim=ladder].is-in{opacity:1;transform:none}
.anim [data-anim=ladder] .steps__n{display:inline-block;opacity:0;transform:scale(.55);transition:opacity .35s ease,transform .5s cubic-bezier(.22,1,.36,1);transition-delay:calc(var(--i,0)*110ms + 130ms)}
.anim [data-anim=ladder].is-in .steps__n{opacity:1;transform:none}

/* three-column blocks: rise and straighten */
.anim [data-anim=settle]{opacity:0;transform:translateY(28px) rotate(-.9deg);transform-origin:left bottom;transition:opacity .6s ease,transform .85s cubic-bezier(.16,.84,.44,1);transition-delay:calc(var(--i,0)*120ms)}
.anim [data-anim=settle].is-in{opacity:1;transform:none}

/* coverage map: powers up out of the dark */
.anim [data-anim=bloom]{opacity:0;transform:scale(.975);transition:opacity .8s ease,transform 1.1s cubic-bezier(.16,.84,.44,1)}
.anim [data-anim=bloom].is-in{opacity:1;transform:none}
.anim [data-anim=bloom] .cvblock__map{opacity:.35;transition:opacity 1.2s ease .15s}
.anim [data-anim=bloom].is-in .cvblock__map{opacity:1}

/* city cards and map legend: hinge down from their top edge */
.anim [data-anim=wave]{opacity:0;transform:perspective(760px) rotateX(-14deg);transform-origin:top center;transition:opacity .5s ease,transform .7s cubic-bezier(.2,.9,.3,1);transition-delay:calc(var(--i,0)*50ms)}
.anim [data-anim=wave].is-in{opacity:1;transform:none}

/* stacked rows: slide in from the right */
.anim [data-anim=shunt]{opacity:0;transform:translateX(32px);transition:opacity .5s ease,transform .68s cubic-bezier(.16,.84,.44,1);transition-delay:calc(var(--i,0)*70ms)}
.anim [data-anim=shunt].is-in{opacity:1;transform:none}

/* form fields: quiet on purpose, this is the part people have to use */
.anim [data-anim=stack]{opacity:0;transform:translateY(12px);transition:opacity .45s ease,transform .55s ease;transition-delay:calc(var(--i,0)*70ms)}
.anim [data-anim=stack].is-in{opacity:1;transform:none}

/* home hero: the copy arrives on load, it is already in view */
.anim .hero__inner > *{opacity:0;transform:translateY(24px);transition:opacity .85s ease,transform .95s cubic-bezier(.16,.84,.44,1)}
.anim .hero__inner > *:nth-child(1){transition-delay:.2s}
.anim .hero__inner > *:nth-child(2){transition-delay:.36s}
.anim .hero__inner > *:nth-child(3){transition-delay:.52s}
.anim .hero__inner > *:nth-child(4){transition-delay:.68s}
.anim .hero__inner.is-in > *{opacity:1;transform:none}

/* inner page headers: the photograph drifts back to true over the first look */
.anim .phero__img{animation:ms-ken 20s cubic-bezier(.2,.6,.3,1) forwards}
@keyframes ms-ken{from{transform:scale(1.09)}to{transform:scale(1)}}

/* ---- hover, which is motion the visitor asks for ---- */
.svccard{overflow:hidden}
.svccard img{transition:transform .55s cubic-bezier(.16,.84,.44,1)}
.svccard:hover img{transform:scale(1.05)}
.svccard__go{transition:transform .3s ease,color .18s ease}
.svccard:hover .svccard__go{transform:translateX(6px)}

.work figure img{transition:transform .6s cubic-bezier(.16,.84,.44,1)}
.work figure:hover img{transform:scale(1.045)}

.btn{position:relative;overflow:hidden;isolation:isolate}
.btn::after{content:"";position:absolute;inset:0;z-index:-1;background:currentColor;opacity:0;transform:translateX(-101%);
  transition:transform .45s cubic-bezier(.16,.84,.44,1),opacity .45s ease}
.btn:hover::after{opacity:.1;transform:none}

.nav__links a{position:relative}
.nav__links a::before{content:"";position:absolute;left:0;right:0;bottom:-5px;height:2px;background:var(--accent);
  transform:scaleX(0);transform-origin:right;transition:transform .35s cubic-bezier(.16,.84,.44,1)}
.nav__links a:hover::before{transform:scaleX(1);transform-origin:left}
.nav__links a[aria-current="page"]::before{display:none}

.area{transition:background .25s ease}
.area:hover{background:var(--bg-card)}

.railcta{transition:background .18s ease,transform .25s cubic-bezier(.2,.9,.3,1)}
.railcta:hover{transform:translateY(-3px)}

/* One switch turns all of it off, including the hover work above. */
@media (prefers-reduced-motion:reduce){
  .anim [data-anim],.anim [data-anim] *,.anim .hero__inner > *{transition:none!important;animation:none!important}
  .svccard img,.svccard__go,.work figure img,.btn::after,.nav__links a::before,.railcta,.phero__img{transition:none!important;animation:none!important}
  .svccard:hover img,.work figure:hover img,.railcta:hover{transform:none}
}

.hl{color:#fff}
.anim .hl{color:inherit;transition:color .75s ease .25s}
.anim .hl.is-in{color:#fff}
@media (prefers-reduced-motion:reduce){.anim .hl{color:#fff;transition:none}}



/* ========================================================== lightbox
 * A native <dialog>, so the focus trap, Escape and background inerting come
 * from the platform. Only the appearance is ours. */
.lb{
  width:100%;max-width:100%;height:100dvh;max-height:100dvh;
  margin:0;padding:0;border:0;background:rgba(6,8,12,.97);color:var(--ink);
  overflow:hidden;
}
.lb::backdrop{background:rgba(4,6,9,.9)}
.lb__fig{
  margin:0;height:100%;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:16px;padding:clamp(52px,7vw,72px) clamp(14px,4vw,64px);
}
.lb__img{
  max-width:100%;max-height:calc(100dvh - 190px);
  width:auto;height:auto;object-fit:contain;display:block;
  border:1px solid var(--line);background:#0b0e13;
}
.lb__cap{
  display:flex;flex-wrap:wrap;align-items:baseline;justify-content:center;gap:8px 16px;
  text-align:center;max-width:70ch;
}
.lb__text{font:600 12px/1.5 ui-monospace,Menlo,monospace;letter-spacing:.15em;color:var(--steel)}
.lb__count{font:600 12px/1.5 ui-monospace,Menlo,monospace;letter-spacing:.15em;color:var(--ink-faint)}

/* Controls: 48px minimum so a thumb can hit them. */
.lb__x,.lb__nav{
  position:absolute;z-index:2;cursor:pointer;
  min-width:48px;min-height:48px;display:flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.07);border:1px solid var(--line);color:var(--ink);
  font:400 26px/1 var(--body);
  transition:background .18s ease,border-color .18s ease;
}
.lb__x:hover,.lb__nav:hover{background:rgba(255,255,255,.14);border-color:var(--ink)}
.lb__x{top:14px;right:14px;font-size:30px}
.lb__nav{top:50%;transform:translateY(-50%);font-size:32px}
.lb__prev{left:14px}
.lb__next{right:14px}
@media (max-width:640px){
  /* Thumbs sit at the bottom of a phone, not the middle of the screen. */
  .lb__nav{top:auto;bottom:16px;transform:none;min-width:64px}
  .lb__prev{left:16px}
  .lb__next{right:16px}
  .lb__img{max-height:calc(100dvh - 230px)}
}
@media (prefers-reduced-motion:reduce){.lb__x,.lb__nav{transition:none}}

/* The photographs advertise themselves as openable only once the script has
   run and made them so. */
.anim .work figure{cursor:zoom-in}
.work figure[role="button"]:focus-visible{outline:2px solid var(--accent-ink);outline-offset:3px}

/* ==================================================== phone layout
 * Measured before this block: the work page ran 21,843px at 390 wide, which is
 * 26 phone screens of scrolling, and the home page 12.9. Every grid on the site
 * collapsed to one column, so a set of four cards became four screens.
 *
 * The fix is not smaller type. It is refusing to let a set become a stack:
 * card sets swipe sideways one screen at a time, the photo grids go two up with
 * their captions moved onto the image, and the tall portrait photographs stop
 * eating a whole screen each. Section padding comes down to match.
 *
 * Everything here is scoped to phones. The desktop layout is untouched. */
@media (max-width:700px){

  /* Bands were built for a laptop. On a phone that padding is dead scroll. */
  .sec{padding:clamp(40px,6.5vh,64px) 6vw}
  .logoband{padding:clamp(24px,4vw,34px) 6vw}

  /* ---- card sets swipe instead of stacking ----
     Four service cards were four screens. Now they are one, and the row bleeds
     to both edges so the cut-off card at the right announces there is more. */
  .svcgrid,.cols3{
    display:grid;grid-auto-flow:column;grid-template-columns:none;
    grid-auto-columns:80%;
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;
    margin-inline:-6vw;padding:0 6vw 14px;
    scrollbar-width:none;
  }
  .svcgrid{gap:10px;margin-top:26px}
  .cols3{gap:14px;margin-top:26px}
  .svcgrid::-webkit-scrollbar,.cols3::-webkit-scrollbar{display:none}
  .svcgrid>*,.cols3>*{scroll-snap-align:start}
  /* A grid item with an image needs a floor or the track collapses. */
  .svccard{min-width:0}
  .svccard img{aspect-ratio:16/10}

  /* ---- photographs go two up, captions move onto the image ----
     57 captions below 57 photos was 2,000px of text nobody reads while
     scrolling. On the image it costs nothing and reads better. */
  .work{grid-template-columns:1fr 1fr;gap:6px;margin-top:24px}
  .work img{aspect-ratio:1/1}
  /* Every third one runs full width, so the grid has a rhythm instead of being
     a wall of squares. */
  .work figure:nth-child(7n+1){grid-column:1 / -1}
  .work figure:nth-child(7n+1) img{aspect-ratio:4/3}
  .work figcaption{
    position:absolute;left:0;right:0;bottom:0;z-index:2;
    padding:22px 10px 8px;font-size:9.5px;letter-spacing:.08em;line-height:1.35;
    color:rgba(242,244,247,.92);
    background:linear-gradient(to top,rgba(5,7,11,.92),rgba(5,7,11,0));
  }
  .work .badge{display:none}

  /* ---- scope and area lists go two up ---- */
  .scope{grid-template-columns:1fr 1fr;margin-top:24px}
  .scope li{padding:15px 14px 17px}
  .scope strong{font-size:15px;line-height:1.2}
  .scope span{font-size:14px;line-height:1.35}

  /* ---- the tall portrait photo in split sections ----
     900x1200 at full width is most of a screen on its own. */
  .split{gap:24px}
  .split img{max-height:46vh;width:100%;object-fit:cover;object-position:center}

  /* ---- numbered steps stay a sequence, just tighter ---- */
  .steps li{padding:16px 16px 18px;gap:6px}
  .steps p{font-size:17px;line-height:1.4}

  /* ---- everything else that was sized for a desk ---- */
  p.lede{margin-bottom:26px;font-size:19px;line-height:1.35}
  .split p,.story p{font-size:18px;line-height:1.4;margin-bottom:14px}
  .cols3 p{font-size:17px;line-height:1.4}
  .area p{font-size:14.5px;line-height:1.35}
  .faq p{font-size:17px;line-height:1.45}
  .faq summary{font-size:17px;padding:16px 16px}
  .faq p{padding:0 16px 18px}
  .cvlegend{gap:14px}
  .cvlegend__d{font-size:14.5px;line-height:1.35}
  .glance{padding:20px 20px 22px}
  .glance dl{gap:18px}
  .cta{padding:clamp(48px,7vh,72px) 6vw}

  /* The two-column prose block is a stack on a phone, so it needs its gap back. */
  .dual>p.lede:not(:last-child){margin-bottom:22px}
}

/* A swipeable row is only obvious if something is cut off at the edge. Below
   this width the cards are wide enough that one and a bit always shows. */
@media (max-width:420px){
  .svcgrid{grid-auto-columns:84%}
  .cols3{grid-auto-columns:86%}
}

@media (prefers-reduced-motion:reduce){
  .svcgrid,.cols3{scroll-behavior:auto}
}

/* Phone performance. 3D transforms and long image lists are where an iPhone
   actually struggles, so both are simplified below 700px. */
@media (max-width:700px){
  .anim [data-anim=deal]{transform:translateY(24px)}
  .anim [data-anim=wave]{transform:translateY(16px)}
  .anim [data-anim=settle]{transform:translateY(20px)}
  .work figure{content-visibility:auto;contain-intrinsic-size:auto 220px}
}


/* ==========================================================================
   DRAFTING LAYER
   Borrowed from erection drawings, which is the document this trade runs on.
   All of it is background-image or pseudo-element work: no extra DOM, no
   requests, and nothing animated except transform and opacity.
   ========================================================================== */

/* Each page gets its own drawing surface. The field is a variable so a page
   is one declaration and its bands can never drift from its body. */
body{ background-image:var(--sheet,none); background-size:var(--sheet-size,auto); }
.sec--alt{ background-image:var(--sheet-alt,linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px)); background-size:var(--sheet-alt-size,auto); }

/* Registration targets, the way a drawing sheet is cropped and aligned.
   On a pseudo-element for two reasons: a background layer list is sized by its
   IMAGE count, so the previous single image with four positions drew exactly
   one mark on a plain section; and it keeps the marks independent of a pattern
   whose layer count changes from page to page. */
.sec{ position:relative; isolation:isolate; }
.sec::before{
  content:'';position:absolute;inset:0;z-index:-3;pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='19'%3E%3Cg fill='none' stroke='%23BAC2CE' stroke-width='1' opacity='.42'%3E%3Cpath d='M9.5 0v5.4M9.5 13.6V19M0 9.5h5.4M13.6 9.5H19'/%3E%3Ccircle cx='9.5' cy='9.5' r='3.1'/%3E%3C/g%3E%3C/svg%3E"),url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='19'%3E%3Cg fill='none' stroke='%23BAC2CE' stroke-width='1' opacity='.42'%3E%3Cpath d='M9.5 0v5.4M9.5 13.6V19M0 9.5h5.4M13.6 9.5H19'/%3E%3Ccircle cx='9.5' cy='9.5' r='3.1'/%3E%3C/g%3E%3C/svg%3E"),url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='19'%3E%3Cg fill='none' stroke='%23BAC2CE' stroke-width='1' opacity='.42'%3E%3Cpath d='M9.5 0v5.4M9.5 13.6V19M0 9.5h5.4M13.6 9.5H19'/%3E%3Ccircle cx='9.5' cy='9.5' r='3.1'/%3E%3C/g%3E%3C/svg%3E"),url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='19'%3E%3Cg fill='none' stroke='%23BAC2CE' stroke-width='1' opacity='.42'%3E%3Cpath d='M9.5 0v5.4M9.5 13.6V19M0 9.5h5.4M13.6 9.5H19'/%3E%3Ccircle cx='9.5' cy='9.5' r='3.1'/%3E%3C/g%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:
    2.1vw 26px,
    calc(100% - 2.1vw) 26px,
    2.1vw calc(100% - 26px),
    calc(100% - 2.1vw) calc(100% - 26px);
}

/* --- the sheets ---------------------------------------------------------- */

/* Home: the erection isometric. Two axes at 60 degrees, the way a frame is
   drawn when you need to see it in three dimensions at once. */
[data-sheet=home]{
  --sheet:
    repeating-linear-gradient(60deg, rgba(186,194,206,.034) 0 1px, transparent 1px 38px),
    repeating-linear-gradient(-60deg, rgba(186,194,206,.034) 0 1px, transparent 1px 38px);
  --sheet-alt:
    repeating-linear-gradient(60deg, rgba(186,194,206,.058) 0 1px, transparent 1px 38px),
    repeating-linear-gradient(-60deg, rgba(186,194,206,.058) 0 1px, transparent 1px 38px),
    linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px);
}

/* Services index: section hatching, the poche that fills a cut member. */
[data-sheet=services]{
  --sheet: repeating-linear-gradient(45deg, rgba(186,194,206,.041) 0 1px, transparent 1px 15px);
  --sheet-alt:
    repeating-linear-gradient(45deg, rgba(186,194,206,.058) 0 1px, transparent 1px 13px),
    linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px);
}

/* Structural erection: the column grid. The plan sheet, with majors. */
[data-sheet=erection]{
  --sheet:
    repeating-linear-gradient(to right, rgba(186,194,206,.040) 0 1px, transparent 1px 30px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.040) 0 1px, transparent 1px 30px);
  --sheet-alt:
    repeating-linear-gradient(to right, rgba(186,194,206,.058) 0 1px, transparent 1px 150px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.058) 0 1px, transparent 1px 150px),
    repeating-linear-gradient(to right, rgba(186,194,206,.034) 0 1px, transparent 1px 30px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.034) 0 1px, transparent 1px 30px),
    linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px);
}

/* Ornamental: tighter, finer, crossed both ways - the busiest field on the
   site, because the work on this page is the most worked. */
[data-sheet=ornamental]{
  --sheet:
    repeating-linear-gradient(45deg, rgba(186,194,206,.031) 0 1px, transparent 1px 11px),
    repeating-linear-gradient(-45deg, rgba(186,194,206,.031) 0 1px, transparent 1px 11px);
  --sheet-alt:
    repeating-linear-gradient(45deg, rgba(186,194,206,.047) 0 1px, transparent 1px 10px),
    repeating-linear-gradient(-45deg, rgba(186,194,206,.047) 0 1px, transparent 1px 10px),
    linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px);
}

/* Miscellaneous steel: a bolt-hole field, the way a gusset or a base plate is
   laid out. The one page whose field is holes rather than lines. */
[data-sheet=misc]{
  --sheet: radial-gradient(circle, rgba(186,194,206,.058) 0 1.3px, transparent 1.7px);
  --sheet-size: 32px 32px;
  --sheet-alt:
    radial-gradient(circle, rgba(186,194,206,.058) 0 1.4px, transparent 1.8px),
    linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px);
  --sheet-alt-size: 26px 26px, auto;
}

/* Multi-family: level lines. Stacked floors, podium to roof - horizontal only,
   because that is what the page is about. */
[data-sheet=multifamily]{
  --sheet: repeating-linear-gradient(to bottom, rgba(186,194,206,.054) 0 1px, transparent 1px 46px);
  --sheet-alt:
    repeating-linear-gradient(to bottom, rgba(186,194,206,.058) 0 1px, transparent 1px 46px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.034) 0 1px, transparent 1px 15px),
    linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px);
}

/* Work: diamond tread plate. The shop floor, and the deck every one of these
   photographs was taken standing on. */
[data-sheet=work]{
  --sheet:
    repeating-linear-gradient(45deg, rgba(186,194,206,.043) 0 2px, transparent 2px 28px),
    repeating-linear-gradient(-45deg, rgba(186,194,206,.043) 0 2px, transparent 2px 28px);
  --sheet-alt:
    repeating-linear-gradient(45deg, rgba(186,194,206,.058) 0 2px, transparent 2px 24px),
    repeating-linear-gradient(-45deg, rgba(186,194,206,.058) 0 2px, transparent 2px 24px),
    linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px);
}

/* About: brushed grain. Not a drawing of steel - the material. Two
   frequencies, because a real brushed finish is not evenly spaced. */
[data-sheet=about]{
  /* Was brushed grain, which Lester picked out as the weakest field on the
     site. Replaced with the widest, quietest drafting grid on the site: this
     page is Jorge talking, and it should feel like an open sheet rather than a
     metal surface. */
  --sheet:
    repeating-linear-gradient(to right, rgba(186,194,206,.030) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.030) 0 1px, transparent 1px 64px);
  --sheet-alt:
    repeating-linear-gradient(to right, rgba(186,194,206,.042) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.042) 0 1px, transparent 1px 64px),
    linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px);
}

/* Service areas: a survey grid. Coarse majors with a fine field inside them,
   the way a site plan is gridded off. Sits under the coverage map. */
[data-sheet=areas]{
  --sheet:
    repeating-linear-gradient(to right, rgba(186,194,206,.056) 0 1px, transparent 1px 96px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.056) 0 1px, transparent 1px 96px),
    repeating-linear-gradient(to right, rgba(186,194,206,.023) 0 1px, transparent 1px 24px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.023) 0 1px, transparent 1px 24px);
  --sheet-alt:
    repeating-linear-gradient(to right, rgba(186,194,206,.058) 0 1px, transparent 1px 96px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.058) 0 1px, transparent 1px 96px),
    repeating-linear-gradient(to right, rgba(186,194,206,.029) 0 1px, transparent 1px 24px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.029) 0 1px, transparent 1px 24px),
    linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px);
}

/* Contact: the quietest field on the site on purpose. This page holds a form,
   and a form does not need a patterned surface arguing with it. */
[data-sheet=contact]{
  --sheet:
    repeating-linear-gradient(to right, rgba(186,194,206,.023) 0 1px, transparent 1px 34px),
    repeating-linear-gradient(to bottom, rgba(186,194,206,.023) 0 1px, transparent 1px 34px);
  --sheet-alt: linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px);
}

/* Privacy, SMS terms, thank-you: nothing. Dense legal text gets a plain page,
   and the registration marks alone still tie them to the set. */
[data-sheet=legal]{ --sheet:none; --sheet-alt:linear-gradient(180deg,rgba(226,232,240,.030) 0,rgba(226,232,240,0) 140px); }

/* The wide-flange section. The cut end of nearly every member on one of his
   jobs, so it is the one shape that belongs here. It replaces the bullet in
   the scope lists, where the old markup had none. */
.scope li{position:relative}
.scope li strong{display:block}
.scope li strong::before{
  content:'';position:absolute;left:24px;top:26px;width:14px;height:12px;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='12'%3E%3Cpath fill='%23BAC2CE' d='M0 0h14v2.6H8.3v6.8H14V12H0V9.4h5.7V2.6H0z'/%3E%3C/svg%3E") no-repeat center/contain;
  opacity:.62;
}
@media (max-width:700px){ .scope li strong::before{top:24px} }

/* Card art. Drafting corner ticks on the service cards, so a card reads as a
   detail drawn on the sheet rather than a tile. Drawn with one gradient set on
   a pseudo-element, so it costs no extra element and no request. */
.svccard{position:relative}
.svccard::after{
  content:'';position:absolute;inset:9px;pointer-events:none;z-index:2;
  background:
    linear-gradient(to right, var(--steel-dim) 0 11px, transparent 11px) 0 0/100% 1px no-repeat,
    linear-gradient(to bottom, var(--steel-dim) 0 11px, transparent 11px) 0 0/1px 100% no-repeat,
    linear-gradient(to left, var(--steel-dim) 0 11px, transparent 11px) 100% 0/100% 1px no-repeat,
    linear-gradient(to bottom, var(--steel-dim) 0 11px, transparent 11px) 100% 0/1px 100% no-repeat,
    linear-gradient(to right, var(--steel-dim) 0 11px, transparent 11px) 0 100%/100% 1px no-repeat,
    linear-gradient(to top, var(--steel-dim) 0 11px, transparent 11px) 0 100%/1px 100% no-repeat,
    linear-gradient(to left, var(--steel-dim) 0 11px, transparent 11px) 100% 100%/100% 1px no-repeat,
    linear-gradient(to top, var(--steel-dim) 0 11px, transparent 11px) 100% 100%/1px 100% no-repeat;
  opacity:.34;transition:opacity .22s ease;
}
.svccard:hover::after{opacity:.8}

/* The number on a service card becomes a piece mark, the way a fabricator
   tags a member, sitting against a W-shape. */
.svccard__body .n{display:inline-flex;align-items:center;gap:7px}
.svccard__body .n::before{
  content:'';width:14px;height:12px;flex:none;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='12'%3E%3Cpath fill='%23BAC2CE' d='M0 0h14v2.6H8.3v6.8H14V12H0V9.4h5.7V2.6H0z'/%3E%3C/svg%3E") no-repeat center/contain;
  opacity:.75;
}

/* Leader line. The elbow that ties a note to the thing it points at - here,
   the caption to the photograph above it. */
.work figcaption{position:relative;padding-left:30px}
.work figcaption::before{
  content:'';position:absolute;left:14px;top:0;width:9px;height:19px;
  border-left:1px solid var(--steel-dim);
  border-bottom:1px solid var(--steel-dim);
  opacity:.5;
}

/* Reduced motion is already handled by anim.js never adding .anim, so none of
   the transitions above ever engage. The linework itself stays. */


/* The title block that closes a drawing sheet. Every value here is true; a
   drawing with invented fields is worse than no drawing. */
.titleblock{
  max-width:1240px;margin:40px auto 0;
  border:1px solid var(--line);
  display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  background:var(--bg-card);box-shadow:inset 0 1px 0 var(--edge);
}
.titleblock > div{
  padding:13px 16px 14px;
  border-right:1px solid var(--line-soft);
  display:flex;flex-direction:column;gap:5px;min-width:0;
}
.titleblock > div:last-child{border-right:0}
.tb__k{
  font:600 9.5px/1 ui-monospace,Menlo,monospace;letter-spacing:.22em;
  color:var(--steel-dim);text-transform:uppercase;
}
.tb__v{
  font:700 14.5px/1.25 var(--disp-2);letter-spacing:.045em;
  color:var(--ink);text-transform:uppercase;overflow-wrap:anywhere;
}
.tb__v a{color:inherit;text-decoration:none}
.tb__v a:hover{color:var(--accent-ink)}
/* On a phone the cells stack two-up, and the right border becomes a bottom
   one so the block still reads as ruled cells rather than a list. */
@media (max-width:640px){
  .titleblock{grid-template-columns:repeat(2,1fr)}
  .titleblock > div{border-bottom:1px solid var(--line-soft)}
  .titleblock > div:nth-child(2n){border-right:0}
}
.anim .titleblock{opacity:0;transform:translateY(14px);transition:opacity .6s ease,transform .7s cubic-bezier(.16,.84,.44,1)}
.anim .titleblock.is-in{opacity:1;transform:none}


/* ==========================================================================
   THE DRAWING ON THE SHEET
   Each page carries one real detail at scale from assets/img/sheet-*.svg. The
   line field behind it is the paper; this is what is drawn on it.

   It goes on the PLAIN sections, not the alternating bands. The bands are
   wall-to-wall card grids on most pages, so a drawing behind one is simply
   covered; a plain section holds a lede capped at 44ch and leaves the right
   half of the page open, which is the only real space on the sheet.

   The light pool rides on the same pseudo-element rather than a third one,
   because .sec::before is already the registration crosshairs and a second
   rule for the same selector silently wiped them. Its alpha is pre-divided by
   the element opacity below.

   Not background-attachment: fixed - it looks like depth on a desktop and is a
   known scroll-jank problem on iOS, which this site has been tuned for twice.
   ========================================================================== */
.sec{position:relative}
/* Every section gets a detail, alternating drawing AND side. Two per page
   rather than one repeated: a page has several sections and their density
   varies, so one drawing gets buried behind whichever section happens to be a
   full-width card grid or a photo split. Two, alternating, means at least one
   lands in open space on every page - and a real sheet carries several details
   anyway, so repetition would have been the wrong answer even if it worked. */
.sec::after{
  content:'';position:absolute;inset:0;z-index:-2;pointer-events:none;
  background-repeat:no-repeat,no-repeat;
  background-image:radial-gradient(56% 66% at 74% 42%, rgba(186,194,206,.22), rgba(186,194,206,0) 70%);
  background-position:right 4% center,center;
  /* The set is mostly landscape now - trusses, portal frames, plans - so it
     is sized by width. Fitting a wide drawing to the band height pushed it
     off the side of the section. */
  background-size:min(52vw,760px) auto,auto;
  opacity:.46;
}
.sec:nth-of-type(even)::after{
  background-image:radial-gradient(56% 66% at 26% 42%, rgba(186,194,206,.22), rgba(186,194,206,0) 70%);
  background-position:left 4% center,center;
}

/* On a phone the detail drops to the bottom of the section, where there is no
   text, at low strength so it never competes for the same pixels. */
@media (max-width:820px){
  .sec::after,.sec:nth-of-type(even)::after{
    background-position:center bottom 10px,center;
    background-size:min(112vw,560px) auto,auto;
    opacity:.44;
  }
}

/* About: the connection detail. This was the page whose field Lester liked
   least, and a beam-to-column connection with the weld symbol on it is the
   most convincing drawing in the set. */



/* ==========================================================================
   PROSE HALOS
   The drawings sit behind the page, so anywhere copy runs over one it would
   read as lines through type - which is exactly what it did on a phone. Each
   prose block clears a soft area of the surface it already sits on: invisible
   against the section, but the drawing fades out under the words and returns
   around them. No card, no border, no edge.
   ========================================================================== */
.sec{--plate:var(--bg)}
.sec--alt{--plate:var(--bg-alt)}

.story,
.split > div,
.cols3 > div,
.cvlegend,
.dual,
.glance,
.sec > .wrap > p.lede,
.sec > .wrap > h2,
.phero__inner{position:relative}

.story::before,
.split > div::before,
.cols3 > div::before,
.cvlegend::before,
.dual::before,
.glance::before,
.sec > .wrap > p.lede::before,
.sec > .wrap > h2::before{
  content:'';position:absolute;z-index:-1;pointer-events:none;
  inset:-34px -52px;
  background:radial-gradient(farthest-side, var(--plate) 40%, rgba(0,0,0,0) 92%);
}
/* A photograph inside a split already has its own ground; a halo behind one
   would only lighten the gap around it. */
.split > div:has(> img)::before,
.split > div:has(> figure)::before{content:none}

/* The legend on the service-areas map is the block the drawing crossed worst,
   and it is a list of short rows with generous gaps, so it needs a wider clear
   area than a paragraph does. */
.cvlegend::before{inset:-22px -30px}

@media (max-width:820px){
  /* Phones have no side margin for the drawing to live in, so the cleared area
     has to be a little more generous or a line still grazes a descender. */
  .story::before,
  .split > div::before,
  .cols3 > div::before,
  .cvlegend::before,
  .dual::before,
  .glance::before,
  .sec > .wrap > p.lede::before,
  .sec > .wrap > h2::before{
    inset:-20px -6vw;
    background:radial-gradient(farthest-side, var(--plate) 52%, rgba(0,0,0,0) 94%);
  }
}


/* Opaque blocks clear the drawing too. A card or a photograph does not soften
   a line passing under it - it cuts it at a hard rectangular edge, which reads
   as a mistake rather than a layer. Same halo as the prose. */
.svccard,.work figure,.card,.scope li,.steps li,.area,.faq details{position:relative}
.svccard::before,
.work figure::before,
.card::before,
.scope li::before,
.steps li::before,
.area::before,
.faq details::before{
  content:'';position:absolute;z-index:-1;pointer-events:none;
  inset:-13px -15px;
  background:radial-gradient(farthest-side, var(--plate) 62%, rgba(0,0,0,0) 96%);
}
@media (max-width:820px){
  .svccard::before,.work figure::before,.card::before,
  .scope li::before,.steps li::before,.area::before,.faq details::before{inset:-14px -16px}
}


/* One drawing style per page, and its second from a different kind again, so
   no two sheets in the set look alike. */


/* ==========================================================================
   ART SLOTS
   Out of the flow entirely. As blocks these added their own height and stacked
   into a column; the brief is to use the empty space the page already has, not
   to make more. assets/art-place.css measures the real rendered page and gives
   each one a rectangle nothing else occupies. Unplaced means hidden, never a
   fallback into the flow.
   ========================================================================== */
.secart{display:none!important}
/* Applies wherever a .secart is shown - absolute placement or grid column.
   Without the column direction the caption sits beside the drawing; without
   an explicit basis the SVG has no intrinsic width to resolve 100% against
   and collapses to zero. */
.secart{flex-direction:column;align-items:center;justify-content:center;gap:10px}
.secart img{flex:0 1 auto;min-width:0;min-height:0}
@media (min-width:1180px){
  .secart{
    position:absolute;z-index:-1;pointer-events:none;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;
  }
  .secart img{
    display:block;max-width:100%;max-height:100%;width:auto;height:auto;
    object-fit:contain;opacity:.9;
  }
  .secart span{
    font:600 10px/1 ui-monospace,Menlo,monospace;letter-spacing:.2em;
    text-transform:uppercase;color:var(--steel-dim);white-space:nowrap;
  }
  /* The prose grid is gone: a drawing no longer needs a column reserved for
     it, because it is placed into space that already exists. */
  .sec--art{display:block}
  .sec--art > .wrap{max-width:1240px;margin:0 auto}
}


/* ==========================================================================
   MOBILE BANDS
   A phone has no gutter for an absolute box, so the subset the placer switches
   on becomes an in-flow band. flex-direction MUST be column here: as a row the
   image and caption sit side by side and push the document past the viewport,
   which is what made an earlier attempt overflow to 435px.
   ========================================================================== */
@media (max-width:1179px){
  .secart{
    position:static!important;left:auto!important;top:auto!important;
    width:100%!important;height:auto!important;max-width:min(520px,100%);
    flex-direction:column;align-items:center;gap:10px;
    margin:clamp(24px,4vh,40px) auto 0;
  }
  .secart img{display:block;width:100%;height:auto;max-height:150px!important;object-fit:contain;opacity:.9}
  .secart span{font:600 10px/1.3 ui-monospace,Menlo,monospace;letter-spacing:.18em;text-transform:uppercase;color:var(--steel-dim);text-align:center}
}


/* ==========================================================================
   ART COLUMN
   A page with no large free rectangle cannot be given a large drawing by
   scattering; the room has to be made. A prose section hands a column to the
   drawing, which fills it. That is a spread, not the floating band that was
   wrong before - the difference is whether the drawing fills its space or
   drifts in it.
   ========================================================================== */
@media (min-width:1180px){
  .sec--art{
    display:grid;
    grid-template-columns:minmax(0,1fr) clamp(360px,32vw,540px);
    gap:clamp(40px,3.8vw,80px);
    align-items:center;
  }
  .sec--art > .wrap{max-width:none;margin:0;min-width:0}
  /* The art in a column is a grid item, not an absolutely placed box, so the
     placement sheet must not move it. */
  .sec--art > .secart{display:flex!important;
    position:static!important;left:auto!important;top:auto!important;
    width:auto!important;height:auto!important;
    display:flex!important;grid-column:2;
    flex-direction:column;align-items:center;gap:14px;
  }
  .sec--art > .secart img{
    width:100%;height:auto;max-height:clamp(300px,34vw,460px);
    object-fit:contain;opacity:.92;
  }
  .sec--art > .secart span{
    font:600 11px/1 ui-monospace,Menlo,monospace;letter-spacing:.22em;
    text-transform:uppercase;color:var(--steel-dim);
  }
}

@media (min-width:1180px){
  [data-sheet=contact] .sec--art{grid-template-columns:minmax(0,1fr) clamp(260px,20vw,320px);gap:clamp(28px,2.6vw,48px)}
}


/* #about img is width:100%, max-height:560px, object-fit:cover, and at
   specificity 1,0,1 it beat .secart img at 0,2,0 - so two drawings on the home
   page rendered 702x414 inside a 226px slot and ran 188px into the crew
   photograph. A drawing is never a content photo; say so at a specificity
   nothing incidental can outrank. */
/* width/object-fit carry !important because #about img (specificity 1,0,1)
   would otherwise treat a drawing as a content photo. max-height must NOT:
   max-height:100% against an auto-height parent is no constraint at all, and
   with !important it also killed the grid column's cap and the mobile cap,
   which is how a 0.26-aspect drawing came to render 1790px tall. */
.secart img{width:100%!important;height:100%!important;object-fit:contain!important;max-width:100%!important;max-height:100%!important}
.sec--art > .secart img{width:100%!important;max-height:clamp(300px,34vw,460px)!important}


/* ==========================================================================
   COLUMN FALLBACK
   Absolute placements are measured at one width and only hold near it, so they
   are gated to 1360 and up. Between 1180 and 1360 the grid columns carry the
   page on their own - that mechanism measured collision-free at every width
   tested, because the layout reserves the space rather than guessing at it.
   ========================================================================== */
@media (min-width:1180px) and (max-width:1365px){
  .sec--art > .secart{display:flex!important}
}
