/* ===================================================================
   nesips.com
   Full-bleed hero · reference-manual structure · drafting detailing.
   Palette is grounded in the material: OSB brown is the logo colour,
   blueprint blue carries technical annotation, graphite is the ink.
   Single committed visual world — every colour painted explicitly.
   =================================================================== */
:root{
  --ink:#1b1f22;
  --paper:#fbfaf8;
  --surface:#f2efe9;
  --dark:#0e0f11;
  --dark-2:#16181b;
  --osb:#83684d;
  --osb-lt:#c2a077;
  --blue:#14508f;
  --rule:#d5cec1;
  --rule-d:#2a2d31;
  --muted:#6b675e;
  --muted-d:#9a958c;
  --sans:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  /* Desktop header height — 69px of logo plate plus its padding and rule.
     The sticky offsets, the anchor targets and the two sticky panels all
     measure from this. Redeclared per width band below, because the nav wraps
     on a narrow laptop and takes the bar with it. */
  --hdr-h:99px;
  /* How far the two sticky panels sit from the top of the scrollport. A
     variable rather than an override, because both rules are declared
     further down the file and would win on source order. */
  --stick-top:1.5rem;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*{animation:none!important;transition:none!important}}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans);font-size:17px;line-height:1.6;-webkit-font-smoothing:antialiased}
img{max-width:100%;height:auto}
a{color:inherit}
:focus-visible{outline:2px solid var(--blue);outline-offset:3px}
.wrap{max-width:1280px;margin:0 auto;padding:0 1.75rem}
.skip{position:absolute;left:-9999px;top:0;background:var(--ink);color:#fff;padding:.7rem 1rem;z-index:99}
.skip:focus{left:0}

/* ---------- shared primitives ---------- */
.lbl{font-family:var(--mono);font-size:.7rem;letter-spacing:.13em;text-transform:uppercase}
.rule-head{display:flex;align-items:center;gap:.9rem;margin:0 0 .9rem}
.rule-head::after{content:"";flex:1;height:1px;background:var(--rule)}
.rule-head .lbl{color:var(--osb)}
.btn{display:inline-block;font-family:var(--mono);font-size:.74rem;letter-spacing:.11em;text-transform:uppercase;padding:.82rem 1.3rem;text-decoration:none;border:1px solid var(--ink);color:var(--ink);background:transparent;cursor:pointer}
.btn.blue{background:var(--blue);border-color:var(--blue);color:#fff}
.btn.solid{background:var(--ink);color:var(--paper)}
.btn+.btn{margin-left:.5rem}
figure{margin:0;border:1px solid var(--ink)}
figure img{width:100%;display:block;aspect-ratio:4/3;object-fit:cover}
figcaption{display:grid;grid-template-columns:1fr auto;border-top:1px solid var(--ink);font-family:var(--mono);font-size:.64rem;letter-spacing:.07em;text-transform:uppercase}
figcaption span{padding:.5rem .7rem}
figcaption span+span{border-left:1px solid var(--ink);color:var(--blue)}

/* ---------- header ---------- */
.hdr{background:var(--dark)}
/* Floating over the hero photo, the nav has no ground of its own — a soft
   shadow keeps it legible whatever the sky is doing behind it. */
.hdr.over{position:absolute;top:0;left:0;right:0;z-index:3;background:transparent}
.hdr.over .nav a,.hdr.over .brand b{text-shadow:0 1px 12px rgba(14,15,17,.75)}
.hdr .bar{display:flex;align-items:center;justify-content:space-between;gap:2rem;padding:.9rem 1.75rem;border-bottom:1px solid rgba(255,255,255,.16)}

/* Sticky above 880px only. On a phone the bar is 145px — a sixth of the
   screen — and worth more as space than as a permanent control.
   Over the home hero the header has to overlay the photo rather than sit
   above it, which position:absolute did by leaving the flow entirely. Sticky
   cannot do that, so it stays in flow and pulls the hero back up under itself
   by its own height: same picture, but the bar now sticks when the page
   moves. It has no ground of its own up there, so it takes one once the hero
   has gone by — see .solid, set from the footer script. */
@media (min-width:881px){
  .hdr{position:sticky;top:0;z-index:10}
  .hdr.over{position:sticky;left:auto;right:auto;z-index:10;
    margin-bottom:calc(var(--hdr-h) * -1);transition:background-color .2s ease}
  .hdr.over.solid{background:var(--dark)}
  .hdr.over.solid .nav a,.hdr.over.solid .brand b{text-shadow:none}
  /* Anything scrolled to by fragment would otherwise land behind the bar:
     #main on every page, #why and #crew on the home page, and the numbered
     sections the white-paper contents list jumps to. Keyed off [id] rather
     than :target so it holds for a scrollIntoView too, and wrapped in :where()
     so it carries no specificity of its own. */
  :where([id]){scroll-margin-top:calc(var(--hdr-h) + 1rem)}
  /* The drawing panel on /details and the white-paper contents list already
     stick; they have to clear the header rather than slide under it. */
  :root{--hdr-h:109px;--stick-top:calc(var(--hdr-h) + 1.5rem)}
}
/* The seven labels and the phone wrap to a second row below about 1010px,
   which makes the bar 10px taller — and the hero overlay, the anchor offsets
   and the sticky panels all measure from --hdr-h, so a single number would be
   wrong on a narrow laptop. Measured at 1012; the switch sits at 1040 to leave
   room for a font that renders a little wider. */
@media (min-width:1040px){
  :root{--hdr-h:99px}
}
.brand{display:flex;align-items:center;gap:.8rem;text-decoration:none}
/* The mark carries its own white plate, so it reads as a deliberate panel
   against the dark header rather than a knocked-out outline. */
.brand img{width:69px;height:69px;display:block;background:#fff}
.brand b{color:#fff;font-size:.82rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase}
.nav{display:flex;gap:1.7rem;align-items:center;flex-wrap:wrap}
/* Between the 880px mobile breakpoint and about 1100px the bar is narrower
   than the labels need, so the row wrapped and the header grew a second line.
   That band predates the Contact label but got wider with it. Tightening the
   gap across the band only — the full-width bar keeps its original spacing —
   costs nothing and holds the header at one row all the way down to the
   hamburger. */
@media (min-width:881px) and (max-width:1100px){.nav{gap:1.1rem}}
.nav a{color:#fff;text-decoration:none;font-family:var(--mono);font-size:.72rem;letter-spacing:.11em;text-transform:uppercase;opacity:.86}
.nav a:hover,.nav a[aria-current]{opacity:1;color:var(--osb-lt)}
.nav a.tel{border:1px solid rgba(255,255,255,.4);padding:.42rem .7rem;opacity:1}
/* The Menu button wears the same bordered plate as the phone number, so the
   two right-hand controls read as a pair. Hidden above 880px — the desktop
   bar has room for every label and gives up none of them. */
.nav .menu{display:none;align-items:center;gap:.55rem;background:transparent;color:#fff;
  font-family:var(--mono);font-size:.68rem;letter-spacing:.09em;text-transform:uppercase;
  border:1px solid rgba(255,255,255,.4);padding:.42rem .7rem;cursor:pointer}
.nav .menu .bars{width:14px;height:10px;border-top:2px solid;border-bottom:2px solid;position:relative}
.nav .menu .bars::after{content:"";position:absolute;left:0;top:calc(50% - 1px);width:100%;border-top:2px solid}

/* Below 880px the bar stacks: brand on top, nav beneath it. Seven labels plus
   the phone wrapped to three rows here — a fifth of a phone screen spent on
   chrome — so the secondary five fold behind Menu and the bar holds one row.
   Packages, Projects and the phone stay out: two carry the pitch and the
   third is a tap away from a call. .pri and .sec do nothing above
   this width, so the desktop nav is exactly what it was. */
@media (max-width:880px){
  /* Side padding stays 1.75rem to match .wrap — the logo and the first nav
     label have to hang on the same line as the breadcrumb and the headline
     below them. The row buys its space from letter-spacing and gaps instead. */
  .hdr .bar{flex-direction:column;align-items:flex-start;gap:.85rem;padding:.9rem 1.75rem}
  .nav{gap:.65rem .7rem;width:100%}
  .nav a{font-size:.66rem;letter-spacing:.04em}
  .nav a.tel{margin-left:auto;padding:.42rem .45rem}
  .nav .sec{display:none}
  .nav .menu{display:inline-flex;font-size:.66rem;letter-spacing:.04em;gap:.4rem;padding:.42rem .45rem}
  /* Open, each folded link takes a row of its own and the bar keeps its own,
     so the panel grows the header downward rather than covering the page —
     no overlay, no scroll lock, nothing to slide underneath. Full width and
     padded: .66rem type is a 17px target on its own, which is no size for a
     thumb, and the hairlines make the stack read as a ruled list rather than
     five labels that lost their row. */
  .hdr.open .nav{row-gap:.15rem}
  .hdr.open .nav .sec{display:block;flex:0 0 100%;padding:.5rem 0;
    border-top:1px solid rgba(255,255,255,.12)}
  .hdr.open .nav .pri,.hdr.open .nav .tel,.hdr.open .nav .menu{order:-1}
  /* Over the home hero the bar is transparent and has no ground to lend the
     panel, so opening it paints one. */
  .hdr.over.open{background:var(--dark)}
}

/* Small Androids and the SE, where four controls no longer fit a row against
   1.75rem of padding. Priority+ is a ranking, so it degrades in order: the
   lowest-ranked visible link folds in with the rest rather than the row
   breaking, and Packages and the phone hold the bar on their own. */
@media (max-width:380px){
  .nav a{font-size:.62rem}
  .nav .menu{font-size:.62rem}
  .nav .pri.lo{display:none}
  .hdr.open .nav .pri.lo{display:block;flex:0 0 100%;padding:.5rem 0;
    border-top:1px solid rgba(255,255,255,.12);order:0}
}

/* ---------- home hero ---------- */
.hero{position:relative;background:var(--dark);height:min(110vh,950px);overflow:hidden}
/* Taller than the viewport on desktop, deliberately — the photo is the pitch.
   Capped on phones so the headline and CTA stay above the fold. */
.hero-slides{position:absolute;inset:0}
.hero-slides img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;opacity:0;transition:opacity 1.1s ease-in-out}
.hero-slides img.on{opacity:1}
@media (max-width:880px){.hero{height:min(76vh,620px)}}
/* Bottom-weighted so the copy block always has ground under it, whatever
   the photo does. The light band sits above the text, never behind it. */
.hero .scrim{position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(14,15,17,.70) 0%,rgba(14,15,17,.18) 22%,rgba(14,15,17,0) 42%,rgba(14,15,17,0) 100%)}
/* The copy block carries its own ground, so it stays legible however many
   lines the eyebrow or headline wrap to — the page-level scrim alone can't
   know how tall this gets. */
.hero .txt{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:4rem 0 2.6rem;text-shadow:0 1px 16px rgba(14,15,17,.7);
  background:linear-gradient(180deg,rgba(14,15,17,0) 0%,rgba(14,15,17,.30) 26%,rgba(14,15,17,.60) 58%,rgba(14,15,17,.76) 100%)}
.hero h1{font-size:clamp(2.5rem,5.6vw,4.4rem);line-height:1.02;letter-spacing:-.038em;font-weight:750;margin:.6rem 0 1rem;max-width:15ch;color:#fff;text-wrap:balance}
.hero h1 span{color:var(--osb-lt)}
.hero h1 .lbl{display:block;font-weight:400;line-height:1.3;margin-bottom:.6rem}
.hero p{margin:0 0 1.7rem;color:#d9d5ce;max-width:47ch;font-size:1.06rem}
.hero .lbl{color:var(--osb-lt)}
.hero .btn{border-color:rgba(255,255,255,.55);color:#fff}
.hero .btn.blue{border-color:var(--blue);background:var(--blue)}
/* Title block, drawing-set style — now a link to the project it labels.
   It sits over photography, so it carries its own solid ground rather than
   relying on whatever happens to be behind it. */
.hero .tblock{position:absolute;right:1.75rem;bottom:2.6rem;display:none;z-index:3;
  border:1px solid rgba(255,255,255,.45);background:rgba(14,15,17,.82);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  font-family:var(--mono);font-size:.66rem;letter-spacing:.08em;color:#fff;
  text-transform:uppercase;text-decoration:none;max-width:22rem;transition:border-color .2s,background .2s}
.hero .tblock span{display:block;padding:.45rem .7rem}
.hero .tblock span+span{border-top:1px solid rgba(255,255,255,.28);color:var(--osb-lt)}
.hero .tblock .go{border-top:1px solid rgba(255,255,255,.28);color:#fff;font-size:.62rem;opacity:.85}
.hero .tblock:hover{border-color:var(--osb-lt);background:rgba(14,15,17,.92)}
.hero .tblock:hover .go{color:var(--osb-lt);opacity:1}
.hero .tblock:focus-visible{outline:2px solid var(--osb-lt);outline-offset:2px}
@media (min-width:1000px){.hero .tblock{display:block}}
.hero-dots{position:absolute;right:1.75rem;bottom:2.6rem;z-index:3;display:flex;gap:.5rem}
.hero-dots button{width:2.1rem;height:3px;padding:0;border:0;cursor:pointer;background:rgba(255,255,255,.38)}
.hero-dots button[aria-current="true"]{background:var(--osb-lt)}
.hero-dots button:hover{background:rgba(255,255,255,.7)}
@media (min-width:1000px){.hero-dots{bottom:auto;top:calc(50% + 3rem)}}
@media (max-width:999px){.hero-dots{bottom:2.6rem}}
@media (prefers-reduced-motion:reduce){.hero-slides img{transition:none}}

/* ---------- interior page head ---------- */
.phead{background:var(--dark);color:#fff;padding:3rem 0 2.6rem}
.phead h1{margin:.5rem 0 .6rem;font-size:clamp(2rem,4vw,3rem);letter-spacing:-.035em;font-weight:750;max-width:22ch;text-wrap:balance}
.phead p{margin:0;color:var(--muted-d);max-width:56ch}
.phead h1 .sub{display:block;font-size:.5em;font-weight:400;letter-spacing:-.02em;line-height:1.25;margin-top:.4rem;color:var(--osb-lt)}
.phead .lbl{color:var(--osb-lt)}
.crumb{font-family:var(--mono);font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted-d);margin:0 0 .3rem}
.crumb a{color:var(--osb-lt);text-decoration:none}

/* ---------- stats ---------- */
.stats{background:var(--dark-2);color:#fff;border-top:1px solid var(--rule-d)}
.stats .wrap{display:grid;grid-template-columns:repeat(3,1fr)}
.stats div{padding:1.5rem 0}
.stats .wrap{padding-inline:1.75rem}
.stats div+div{border-left:1px solid var(--rule-d);padding-left:1.6rem}
.stats b{display:block;font-size:1.85rem;letter-spacing:-.03em;font-weight:750;font-variant-numeric:tabular-nums;line-height:1.1}
.stats .lbl{color:var(--muted-d);margin-top:.25rem;display:block}

/* ---------- sections ---------- */
section{padding:4.5rem 0;border-bottom:1px solid var(--rule)}
.shead{display:flex;justify-content:space-between;align-items:flex-end;gap:2rem;flex-wrap:wrap;margin-bottom:2rem}
.shead h2{margin:0;font-size:clamp(1.7rem,3vw,2.3rem);letter-spacing:-.032em;font-weight:750;text-wrap:balance}
.shead .meta{font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.prose p{max-width:66ch;color:var(--muted)}
.prose p strong{color:var(--ink);font-weight:620}
.prose h3{font-size:1.2rem;font-weight:720;letter-spacing:-.02em;margin:2rem 0 .4rem}
/* A step below h3, for the named options inside a section. */
.prose h4{font-size:1rem;font-weight:680;letter-spacing:-.01em;margin:1.5rem 0 .3rem}

/* ---------- intro two-col ---------- */
.intro{display:grid;grid-template-columns:1fr 1fr;gap:3.5rem;align-items:center}
.intro h2{font-size:clamp(1.6rem,2.8vw,2.15rem);letter-spacing:-.032em;font-weight:750;margin:0 0 1rem;text-wrap:balance}
.intro h2 span{color:var(--osb)}
.intro p{color:var(--muted);margin:0 0 1rem;max-width:52ch}
.intro p strong{color:var(--ink);font-weight:620}
/* Closing copy sits above the picture, in its column, filling the space the
   photograph leaves rather than running the full width below everything. The
   heading takes a row of its own so both columns of body copy start level —
   the alternative, padding the right column down, guesses at a heading height
   that changes with the viewport. */
.intro-side{display:flex;flex-direction:column;gap:1.8rem}
.intro-foot p{color:var(--muted);margin:0}
#why .intro{align-items:stretch;row-gap:1rem}
#why .intro-head{grid-column:1;grid-row:1}
#why .intro-body{grid-column:1;grid-row:2}
#why .intro-side{grid-column:2;grid-row:2}

/* ---------- owner benefits ---------- */
.bens{display:grid;grid-template-columns:repeat(4,1fr);gap:1.75rem;margin-top:3rem;padding-top:2rem;border-top:1px solid var(--rule)}
.bens article{border-top:2px solid var(--osb);padding-top:.9rem}
.bens .lbl{color:var(--osb);display:block;margin-bottom:.45rem}
.bens p{margin:0;color:var(--muted);font-size:.94rem}

/* ---------- one source: a genuine sequence, so it is numbered ---------- */
.lead-p{font-size:1.12rem;max-width:64ch;color:var(--muted);margin:0 0 2.2rem}
.lead-p strong{color:var(--ink);font-weight:620}
.chain{display:grid;grid-template-columns:repeat(4,1fr);gap:1.75rem;counter-reset:stage}
.chain article{position:relative;border-top:1px solid var(--ink);padding-top:1rem}
.chain .step{font-family:var(--mono);font-size:.68rem;letter-spacing:.12em;color:var(--blue);display:block;margin-bottom:.5rem}
/* min-height keeps the four descriptions on one line together, even though
   stage 04's title needs two lines. */
.chain h3{margin:0 0 .4rem;font-size:1.02rem;font-weight:700;letter-spacing:-.02em;text-wrap:balance;min-height:2.6em}
.chain p{margin:0;color:var(--muted);font-size:.92rem}
/* connective arrow between stages, desktop only */
@media (min-width:881px){
  .chain article:not(:last-child)::after{content:"";position:absolute;top:-1px;right:-1.1rem;width:.55rem;height:.55rem;
    border-top:1px solid var(--ink);border-right:1px solid var(--ink);transform:translateY(-50%) rotate(45deg)}
}

/* ---------- crew ---------- */
.crew{background:var(--surface);border-bottom:1px solid var(--rule)}
.crew .grid{display:grid;grid-template-columns:.95fr 1.05fr;gap:3.5rem;align-items:center}
.crew h2{margin:0 0 1rem;font-size:clamp(1.7rem,3vw,2.35rem);letter-spacing:-.034em;font-weight:750;text-wrap:balance}
.crew h2 span{color:var(--osb)}
.crew p{color:var(--muted);margin:0 0 1rem;max-width:52ch}
.crew p strong{color:var(--ink);font-weight:620}
.bignum{display:flex;align-items:flex-start;gap:1rem;border-top:2px solid var(--ink);padding-top:1rem;margin:0 0 1.4rem}
.bignum b{font-size:clamp(3rem,7vw,4.6rem);line-height:.9;letter-spacing:-.045em;font-weight:780;color:var(--osb);font-variant-numeric:tabular-nums}
.bignum span{font-size:.95rem;color:var(--muted);max-width:22ch;line-height:1.4}
/* b and small are separate element children, so they are separate grid items.
   Named areas keep the badge in its own column and stack the two text rows
   beside it, instead of letting them wrap onto a third row. */

/* ---------- ladder: rule weight encodes escalating involvement ---------- */
.ladder{margin-top:3.5rem;padding-top:2rem;border-top:1px solid var(--rule)}
.ladder .head{display:flex;justify-content:space-between;align-items:baseline;gap:2rem;flex-wrap:wrap;margin-bottom:1.6rem}
.ladder h3{margin:0;font-size:1.35rem;letter-spacing:-.028em;font-weight:740}
.ladder .head .meta{font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.rungs{display:grid;grid-template-columns:repeat(3,1fr);gap:1.75rem}
.rung{padding-top:.9rem}
.rung:nth-child(1){border-top:1px solid var(--ink)}
.rung:nth-child(2){border-top:3px solid var(--ink)}
.rung:nth-child(3){border-top:6px solid var(--ink)}
.rung .lvl{font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;color:var(--blue);display:block;margin-bottom:.5rem}
.rung h4{margin:0 0 .4rem;font-size:1.05rem;font-weight:700;letter-spacing:-.02em}
.rung p{margin:0;color:var(--muted);font-size:.92rem;max-width:34ch}
.rung .who{display:block;margin-top:.7rem;font-family:var(--mono);font-size:.66rem;letter-spacing:.07em;text-transform:uppercase;color:var(--osb)}

/* ---------- detail library ---------- */
.manual{display:grid;grid-template-columns:1fr 1fr;gap:3rem;align-items:start}
/* With 55 sheets the index towers over the drawing beside it. Letting the
   column stretch gives the sticky sheet room to travel instead of leaving
   half the page blank. */
.lib-long .manual{align-items:stretch}
/* À la carte services. Same two columns as .intro above it, so the copy sits
   at the width the opening paragraphs set rather than running to its own
   measure. The photographs are a loose column beside it — they carry their own
   rhythm and are not meant to line up with the headings. */
.alacarte{display:grid;grid-template-columns:1fr 1fr;gap:3.5rem;align-items:start}
/* .intro p caps at 52ch; match it so the two blocks of copy are one column,
   and hold the rule to the same measure so it ends where the text ends. */
.alacarte .prose p{max-width:52ch}
.alacarte .rule-head{max-width:52ch;margin-top:2.4rem}
.alacarte-figs{display:grid;gap:2.2rem}
/* The four plates go somewhere, so they need the cue .pc gets — but there is
   no heading here to colour, only the frame and its caption. The drawn border
   is the whole object, so moving it to blue is cue enough. */
.figlink{display:block;text-decoration:none;color:inherit}
.figlink figure,.figlink figcaption,.figlink figcaption span+span{transition:border-color .15s ease}
.figlink:hover figure{border-color:var(--blue)}
.figlink:hover figcaption{border-top-color:var(--blue)}
.figlink:hover figcaption span+span{border-left-color:var(--blue)}
.figlink:hover figcaption span:first-child{color:var(--blue)}
@media (max-width:880px){
  .alacarte{grid-template-columns:1fr;gap:2rem}
  .alacarte-figs{grid-template-columns:repeat(2,1fr);gap:1rem}
}
/* Library switch — sits beside the intro copy in the dark page head. Two
   halves of one control, so it reads as a choice rather than two buttons. */
.phead-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2.5rem;align-items:start}
.phead-row p{margin:0}
.libswitch{display:inline-flex;border:1px solid rgba(255,255,255,.45);flex-shrink:0}
.libswitch button{appearance:none;background:transparent;border:0;cursor:pointer;
  font-family:var(--mono);font-size:.74rem;letter-spacing:.11em;text-transform:uppercase;
  color:#fff;padding:.82rem 1.5rem;opacity:.72;transition:background .15s,opacity .15s}
.libswitch button+button{border-left:1px solid rgba(255,255,255,.45)}
.libswitch button:hover{opacity:1}
.libswitch button[aria-selected="true"]{background:#fff;color:var(--ink);opacity:1}
.libswitch button:focus-visible{outline:2px solid var(--osb-lt);outline-offset:-2px}
@media (max-width:880px){
  .phead-row{grid-template-columns:1fr;gap:1.3rem}
  /* One column: the control is a grid item and stretches, while its buttons
     size to their text — which left the border wrapping a strip of empty
     space. Let the two halves share the width instead. */
  .libswitch{display:flex;align-self:start}
  .libswitch button{flex:1;padding-left:0;padding-right:0;text-align:center}
}
/* The switch sits beside the copy on a wide screen and under it on a narrow
   one, so the sentence pointing at it has to say two different things. */
.at-wide{display:inline}
.at-narrow{display:none}
@media (max-width:880px){
  .at-wide{display:none}
  .at-narrow{display:inline}
}
.grp{margin-bottom:1.5rem}
.grp h3{margin:0 0 .1rem;font-family:var(--mono);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;color:var(--osb);font-weight:500;padding-bottom:.4rem;border-bottom:1px solid var(--ink)}
.grp a{display:grid;grid-template-columns:1fr auto;gap:1rem;align-items:baseline;text-decoration:none;font-size:.94rem;padding:.42rem 0;border-bottom:1px solid var(--rule)}
.grp a:hover{color:var(--blue)}
.grp a code{font-family:var(--mono);font-size:.74rem;color:var(--blue);letter-spacing:.04em}
.sheet{border:1px solid var(--ink);background:#fff}
.sheet.stick{position:sticky;top:var(--stick-top)}
.sheet img{width:100%;display:block}
.sheet .tb{display:grid;grid-template-columns:1fr auto;border-top:1px solid var(--ink);font-family:var(--mono);font-size:.64rem;letter-spacing:.07em;text-transform:uppercase}
.sheet .tb span{padding:.55rem .7rem}
.sheet .tb span+span{border-left:1px solid var(--ink);color:var(--blue)}
.credit{font-family:var(--mono);font-size:.66rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin:.8rem 0 0}

/* detail index cards */
.dcards{display:grid;grid-template-columns:repeat(4,1fr);gap:1.5rem}
.dcard{text-decoration:none;display:block;border:1px solid var(--rule);background:#fff}
.dcard img{width:100%;display:block;aspect-ratio:3/4;object-fit:cover;object-position:center;background:#fff}
.dcard .b{padding:.7rem .8rem;border-top:1px solid var(--rule)}
.dcard code{font-family:var(--mono);font-size:.66rem;letter-spacing:.08em;color:var(--blue);display:block;margin-bottom:.2rem}
.dcard h3{margin:0;font-size:.92rem;font-weight:620;line-height:1.3}
.dcard:hover{border-color:var(--ink)}
.dcard:hover h3{color:var(--blue)}

/* single detail page */
.dpage{display:grid;grid-template-columns:1.25fr .75fr;gap:3rem;align-items:start}
.dmeta{border-top:2px solid var(--ink);padding-top:1rem}
.dmeta h2{margin:0 0 .8rem;font-family:var(--mono);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);font-weight:500}
/* .intro centres its columns; the facts are shorter than the copy beside
   them, so centring dropped them half a screen down the page. */
.intro>.dmeta{align-self:start}
.dmeta dl{margin:0 0 1.5rem;display:grid;grid-template-columns:auto 1fr;gap:.55rem 1.1rem;font-size:.94rem}
.dmeta dt{font-family:var(--mono);font-size:.66rem;letter-spacing:.11em;text-transform:uppercase;color:var(--muted);padding-top:.2rem}
.dmeta dd{margin:0}
.dmeta dd code{font-family:var(--mono);color:var(--blue)}
.award{margin-top:1.6rem;padding-top:1.2rem;border-top:2px solid var(--ink);display:grid;grid-template-columns:auto 1fr;gap:1rem;align-items:center}
.award img{width:120px;height:auto;display:block;background:#000}
.award p{margin:0;font-size:.94rem;font-weight:620;line-height:1.3}
.award .lbl{display:block;color:var(--osb);margin-bottom:.3rem;font-weight:400}

.related{margin-top:2rem;border-top:1px solid var(--rule);padding-top:1rem}
.related h3{margin:0 0 .5rem;font-family:var(--mono);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;color:var(--osb);font-weight:500}
.related a{display:grid;grid-template-columns:1fr auto;gap:1rem;text-decoration:none;font-size:.92rem;padding:.36rem 0;border-bottom:1px solid var(--rule)}
.related a code{font-family:var(--mono);font-size:.72rem;color:var(--blue)}
.related a:hover{color:var(--blue)}

/* ---------- interactive 3D model viewer ---------- */
.models{margin-top:.5rem}
/* Six tabs wrap raggedly in a flex row, so lay them out as an even grid. */
.model-tabs{display:grid;grid-template-columns:repeat(3,1fr);border:1px solid var(--ink);border-bottom:0;background:var(--surface)}
.model-tabs button{font-family:var(--mono);font-size:.7rem;letter-spacing:.09em;text-transform:uppercase;
  padding:.75rem .9rem;background:transparent;border:0;border-right:1px solid var(--rule);border-bottom:1px solid var(--rule);
  color:var(--muted);cursor:pointer;text-align:left}
.model-tabs button:nth-child(3n){border-right:0}
.model-tabs button:nth-last-child(-n+3){border-bottom:0}
.model-tabs button:hover{color:var(--ink)}
.model-tabs button[aria-selected="true"]{background:var(--ink);color:var(--paper)}
.model-frame{border:1px solid var(--ink);background:#fff}
.model-frame iframe{width:100%;aspect-ratio:16/10;display:block;border:0}
/* Facade: a static poster stands in until someone asks for the 3D viewer,
   so switching tabs costs an image rather than a third-party app load. */
.model-stage{position:relative;aspect-ratio:16/10;background:#f2f3f6;display:block}
.model-stage img{width:100%;height:100%;object-fit:contain;display:block;cursor:pointer}
.model-load{position:absolute;left:50%;bottom:1.1rem;transform:translateX(-50%);
  font-family:var(--mono);font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;
  padding:.7rem 1.15rem;background:var(--ink);color:var(--paper);border:0;cursor:pointer;white-space:nowrap}
.model-load:hover{background:var(--blue)}
.model-stage iframe{width:100%;height:100%;display:block;border:0}
.model-frame .tb{display:grid;grid-template-columns:1fr auto;border-top:1px solid var(--ink);
  font-family:var(--mono);font-size:.64rem;letter-spacing:.07em;text-transform:uppercase}
.model-frame .tb span{padding:.55rem .7rem}
.model-frame .tb span+span{border-left:1px solid var(--ink);color:var(--blue)}
.model-note{margin:.9rem 0 0;color:var(--muted);max-width:60ch}
@media (max-width:880px){
  .model-tabs{grid-template-columns:1fr}
  .model-tabs button{border-right:0;border-bottom:1px solid var(--rule)}
  .model-tabs button:last-child{border-bottom:0}
  .model-frame iframe{aspect-ratio:4/3}
}

/* ---------- projects ---------- */
.pgrid{display:grid;grid-template-columns:repeat(2,1fr);gap:2rem}
.pc{text-decoration:none;display:block}
.pc figure{border-color:var(--rule)}
.pc figcaption{border-top-color:var(--rule)}
.pc figcaption span+span{border-left-color:var(--rule)}
.pc h3{margin:.9rem 0 .3rem;font-size:1.25rem;font-weight:720;letter-spacing:-.022em}
.pc p{margin:0;color:var(--muted);font-size:.92rem;max-width:46ch}
.pc:hover h3{color:var(--blue)}

.pq{margin:1.6rem 0;padding:1rem 0 1rem 1.2rem;border-left:3px solid var(--osb)}
.pq p{margin:0;font-size:1.08rem;font-style:italic;color:var(--ink);max-width:46ch}
.pq cite{display:block;margin-top:.5rem;font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;font-style:normal;color:var(--muted)}

/* ---------- full-width project carousel ---------- */
.carousel-wrap{padding-bottom:0}
.carousel{position:relative;background:var(--dark);height:min(82vh,760px);overflow:hidden;margin-top:.5rem}
.carousel:focus-visible{outline:2px solid var(--blue);outline-offset:-2px}
.cslide{position:absolute;inset:0;margin:0;border:0;opacity:0;transition:opacity .5s ease;pointer-events:none}
.cslide.on{opacity:1;pointer-events:auto}
/* contain, not cover: the shoot mixes portrait and landscape, and cropping a
   photographer's framing to fill a box is worse than showing letterbox. */
.cslide img{width:100%;height:100%;object-fit:contain;display:block;aspect-ratio:auto}
.cnav{position:absolute;top:0;bottom:0;width:16%;min-width:64px;border:0;background:transparent;cursor:pointer;z-index:2}
.cprev{left:0}
.cnext{right:0}
.cnav::before{content:"";position:absolute;top:50%;left:50%;width:.9rem;height:.9rem;
  border-top:2px solid rgba(255,255,255,.85);border-right:2px solid rgba(255,255,255,.85);
  filter:drop-shadow(0 1px 6px rgba(0,0,0,.8))}
.cprev::before{transform:translate(-30%,-50%) rotate(-135deg)}
.cnext::before{transform:translate(-70%,-50%) rotate(45deg)}
.cnav:hover::before{border-color:var(--osb-lt)}
.carousel-wrap .shead{margin-bottom:0}
.carousel-wrap .meta{font-variant-numeric:tabular-nums}
@media (max-width:880px){.carousel{height:min(62vh,480px)}.cnav{width:22%}}

/* project hero + gallery */
.phero{position:relative;background:var(--dark)}
.phero img{width:100%;height:min(70vh,600px);object-fit:cover;object-position:50% var(--focus,50%);display:block;opacity:.9}
.gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;margin-top:1.5rem}
.gallery button{padding:0;border:1px solid var(--rule);background:#fff;cursor:pointer;display:block}
.gallery button img{width:100%;display:block;aspect-ratio:4/3;object-fit:cover}
.gallery button:hover{border-color:var(--ink)}

/* ---------- services ---------- */
/* Photo variant: the picture sits above the rule so the card still reads as a
   card when the image is slow, missing, or the row wraps to one column. */

/* ---------- white papers ---------- */
.paper-card{border:1px solid var(--rule);border-top:3px solid var(--osb);background:#fff;padding:1.4rem 1.5rem;height:100%}
.paper-card .lbl{color:var(--osb);display:block;margin-bottom:.6rem}
.paper-card h3{margin:0 0 .6rem;font-size:1.3rem;font-weight:740;letter-spacing:-.024em;line-height:1.2;text-wrap:balance}
.paper-card p{margin:0;color:var(--muted);font-size:.94rem}
.paper-card .more{display:block;margin-top:1rem;font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;color:var(--blue)}
.pc:hover .paper-card{border-color:var(--ink);border-top-color:var(--osb)}

.paper{display:grid;grid-template-columns:16rem 1fr;gap:3.5rem;align-items:start}
.toc{position:sticky;top:var(--stick-top);border-top:2px solid var(--ink);padding-top:1rem}
.toc h2{margin:0 0 .7rem;font-family:var(--mono);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);font-weight:500}
.toc nav{display:grid}
.toc nav a{display:grid;grid-template-columns:1.7rem 1fr;gap:.3rem;text-decoration:none;font-size:.9rem;padding:.36rem 0;border-bottom:1px solid var(--rule-soft,var(--rule));line-height:1.35}
.toc nav a:hover{color:var(--blue)}
.toc .sec{font-family:var(--mono);font-size:.72rem;color:var(--osb)}
.toc-cta{margin:1.2rem 0 0}

.paper-body{max-width:70ch}
/* Diagrams inside a white paper. The figure sits on its own plate so a line
   drawing reads as a drawing rather than as a floating image. */
.pfig{margin:2rem 0}
.pfig-plate{border:1px solid var(--rule);background:#fff;padding:1.4rem 1.2rem}
.pfig-plate svg,.pfig-plate img{width:100%;height:auto;display:block}
.pfig figcaption{font-family:var(--mono);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-top:.6rem}

.paper-body > h2{font-size:1.5rem;font-weight:750;letter-spacing:-.028em;margin:2.6rem 0 .7rem;line-height:1.2;text-wrap:balance;
  display:grid;grid-template-columns:2.4rem 1fr;gap:.4rem;align-items:baseline}
.paper-body > h3{font-size:1.12rem;font-weight:700;letter-spacing:-.02em;margin:1.9rem 0 .5rem;line-height:1.3;
  display:grid;grid-template-columns:2.4rem 1fr;gap:.4rem;align-items:baseline}
.paper-body .sec{font-family:var(--mono);font-size:.74rem;color:var(--blue);font-weight:400}
.paper-body > h2:first-child{margin-top:0}
.paper-body p{margin:0 0 1.05rem;color:var(--ink)}
/* Table caption: sits tight under its table, smaller and set apart so it
   never reads as the start of the next paragraph. */
.paper-body .tcap{margin:-.9rem 0 1.6rem;font-size:.84rem;line-height:1.5;color:var(--muted);
  font-style:italic;max-width:none;padding-left:.1rem}
/* .pbul started life inside .paper-body, but the same marker is wanted in
   ordinary .prose copy too (/green-building, /404, /long-eddy). Scoped to
   both rather than made global, so a plain <ul> elsewhere still gets discs. */
.paper-body .pbul,.prose .pbul{margin:0 0 1.05rem;padding-left:0;list-style:none}
.paper-body .pbul li,.prose .pbul li{position:relative;padding-left:1.5rem;margin:.35rem 0;color:var(--ink)}
.paper-body .pbul li::before,.prose .pbul li::before{content:"\25B8";position:absolute;left:0;top:0;
  color:var(--osb);font-size:.8em;line-height:1.7}
.paper-body table{font-size:.9rem}
.paper-body .scroller{margin:1.4rem 0 1.2rem;border:1px solid var(--rule)}
.paper-body td,.paper-body th{padding:.55rem .75rem;border-bottom:1px solid var(--rule-soft,var(--rule));vertical-align:top}
.paper-body thead th{background:var(--surface);font-family:var(--mono);font-size:.68rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted);font-weight:500}

.gate{border:1px solid var(--ink);border-top:4px solid var(--osb);background:var(--surface);padding:1.8rem;margin:3rem 0 0}
.gate h2{margin:.3rem 0 .6rem;font-size:1.35rem;font-weight:740;letter-spacing:-.024em;display:block}
.gate p{color:var(--muted);max-width:52ch}
.gate form{margin-top:1.2rem;max-width:34rem}
.paper-more{margin-top:3.5rem;padding-top:2rem;border-top:1px solid var(--rule)}
.paper-more h2{font-size:1.3rem;font-weight:740;letter-spacing:-.024em;margin:0 0 1.2rem;display:block}
.paper-more .pgrid{grid-template-columns:1fr}

/* ---------- form ---------- */
.fgrid{display:grid;grid-template-columns:1fr 1fr;gap:3rem;align-items:start}
.frow{display:grid;gap:.3rem;margin-bottom:1rem}
.frow label{font-family:var(--mono);font-size:.68rem;letter-spacing:.11em;text-transform:uppercase;color:var(--muted)}
.frow input,.frow textarea,.frow select{font:inherit;font-size:.95rem;padding:.62rem .7rem;border:1px solid var(--rule);background:#fff;color:var(--ink);width:100%;border-radius:0}
.frow input:focus,.frow textarea:focus,.frow select:focus{border-color:var(--blue);outline:none;box-shadow:0 0 0 1px var(--blue)}
.frow textarea{min-height:8rem;resize:vertical}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.fstatus{margin:.9rem 0 0;font-size:.92rem;min-height:1.4em}
.fstatus.ok{color:#2d6a4f}
.fstatus.err{color:#a8442a}
.two-up{display:grid;grid-template-columns:1fr 1fr;gap:1rem}

/* ---------- closing / footer ---------- */
.end{background:var(--dark);color:#fff;border:0;padding:4.5rem 0}
.end .wrap{display:grid;grid-template-columns:1.1fr .9fr;gap:3rem;align-items:center}
.end h2{margin:.5rem 0 .7rem;font-size:clamp(1.8rem,3.4vw,2.6rem);letter-spacing:-.034em;font-weight:750;max-width:16ch;text-wrap:balance}
.end p{color:var(--muted-d);margin:0 0 1.6rem;max-width:44ch}
.end .lbl{color:var(--osb-lt)}
.end .btn{border-color:rgba(255,255,255,.5);color:#fff}
.end .btn.blue{background:var(--blue);border-color:var(--blue)}
.contact{border:1px solid var(--rule-d);padding:1.5rem}
.contact dl{margin:0;display:grid;grid-template-columns:auto 1fr;gap:.6rem 1.2rem;font-size:.94rem}
.contact dt{font-family:var(--mono);font-size:.66rem;letter-spacing:.11em;text-transform:uppercase;color:var(--muted-d);padding-top:.22rem}
.contact dd{margin:0}
.contact a{color:var(--osb-lt);text-decoration:none}
.credential{margin:1.2rem 0 0;padding-top:1rem;border-top:1px solid var(--rule-d);
  font-family:var(--mono);font-size:.7rem;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted-d);line-height:1.7}
.credential strong{color:var(--osb-lt);font-weight:500}
footer{background:var(--dark);color:var(--muted-d);padding:0 0 2.5rem;font-size:.8rem}
footer .wrap{border-top:1px solid var(--rule-d);padding-top:1.5rem;display:flex;justify-content:space-between;gap:1.5rem;flex-wrap:wrap;align-items:center}
footer a{color:var(--muted-d)}
footer nav{display:flex;gap:1.2rem;flex-wrap:wrap}

@media (max-width:980px){
  .dcards{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:880px){
  .intro,.crew .grid,.manual,.pgrid,.end .wrap,.dpage,.fgrid,.paper{grid-template-columns:1fr}
  /* One column: let the three blocks stack in source order rather than fight
     over the two-column placement above. */
  #why .intro-head,#why .intro-body,#why .intro-side{grid-column:auto;grid-row:auto}
  .toc{position:static}
  .rungs,.chain{grid-template-columns:1fr}
  .bens{grid-template-columns:repeat(2,1fr)}
  .stats .wrap{grid-template-columns:repeat(2,1fr)}
  .stats div+div{border-left:0;padding-left:0}
  .stats div:nth-child(n+3){border-top:1px solid var(--rule-d)}
  /* Three claims in a two-column grid leave a hole; the last one takes the row. */
  .stats div:nth-child(3):last-child{grid-column:1/-1}
  .sheet.stick{position:static}
  .dcards,.gallery{grid-template-columns:repeat(2,1fr)}
  .two-up{grid-template-columns:1fr}
}

/* Client drawing set (/long-eddy): one card per room, each offering the sheet
   as a PDF and the same room as a Trimble model. Distinct from .sheet, which
   is the bordered drawing plate used across the detail library. */
.dwgs{display:grid;grid-template-columns:repeat(3,1fr);gap:1.2rem}
.dwg{border:1px solid var(--rule);background:#fff;padding:1rem 1.1rem;display:flex;flex-direction:column;gap:.85rem}
.dwg h3{margin:0;font-size:.95rem;font-weight:620;line-height:1.3}
.dwl{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:auto}
.dwl .btn{font-size:.74rem;padding:.4rem .7rem}
.dwl .btn span{opacity:.6;font-variant-numeric:tabular-nums}
@media (max-width:880px){.dwgs{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.dwgs{grid-template-columns:1fr}}

/* The interactive viewer boots slowly, so it fades in over the poster rather
   than replacing it with an empty box. Both stack in .model-stage, which is
   already position:relative. */
.model-stage .model-live{position:absolute;inset:0;width:100%;height:100%;border:0;background:#fff}
.model-wait{position:absolute;left:50%;bottom:1.1rem;transform:translateX(-50%);margin:0;z-index:2;
  font-family:var(--mono);font-size:.68rem;letter-spacing:.09em;text-transform:uppercase;
  color:#fff;background:rgba(0,0,0,.62);padding:.42rem .8rem}
