:root{
  --pcb-green: #0E3D5C;
  --pcb-green-deep: #071F30;
  --copper: #2E7FBF;
  --copper-bright: #3FA9F5;
  --fr4-tan: #E7ECF1;
  --fr4-tan-deep: #DCE4EA;
  --silkscreen: #F5F8FA;
  --ink: #131A22;
  --ink-soft: #4C5C6B;
  --test-yellow: #4FD1E8;
  --line: rgba(19,26,34,0.12);
  /* Form field borders need a real 3:1 boundary; --line measured 1.21:1.
     Kept separate so decorative dividers stay as light as they were. */
  --line-control: #767E86;
}

*{ margin:0; padding:0; box-sizing:border-box; }

html{ scroll-behavior:smooth; }

body{
  background: var(--silkscreen);
  color: var(--ink);
  font-family:'IBM Plex Sans', sans-serif;
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}

h1,h2,h3{
  font-family:'Space Grotesk', sans-serif;
  font-weight:600;
  letter-spacing:-0.01em;
  color: var(--ink);
}

.mono{ font-family:'IBM Plex Mono', monospace; }

.eyebrow{
  font-family:'IBM Plex Mono', monospace;
  font-size:0.72rem;
  letter-spacing:0.14em;
  text-transform:uppercase;
  color: var(--copper);
  display:flex;
  align-items:center;
  gap:0.6em;
}
.eyebrow::before{
  content:'';
  width:18px; height:2px;
  background: var(--copper);
  display:inline-block;
}

a{ color:inherit; text-decoration:none; }

img{ max-width:100%; display:block; }

.wrap{
  max-width:1180px;
  margin:0 auto;
  padding:0 32px;
}

/* ---------- NAV ---------- */
header{
  position:sticky; top:0; z-index:100;
  background: rgba(14,61,92,0.94);
  backdrop-filter: blur(8px);
  border-bottom:1px solid rgba(245,248,250,0.1);
}
nav.wrap{
  display:flex; align-items:center; justify-content:space-between;
  height:76px;
}
/* The brand block is wrapped in this link on every page, homepage included.
   It used to carry style="display:contents", which removes the anchor's own
   box — that leaves nothing to hit and makes the link unreliable to click. */
.brand-link{ display:flex; align-items:center; text-decoration:none; }
.brand{ display:flex; flex-direction:column; align-items:flex-start; gap:2px; }
.brand-mark{
  width:34px; height:34px; border-radius:6px;
  background: var(--pcb-green);
  position:relative;
  flex-shrink:0;
}
.brand-mark svg{ position:absolute; inset:0; width:100%; height:100%; }
.brand-name{ font-family:'Space Grotesk',sans-serif; font-weight:700; font-size:1.05rem; line-height:1.15; }
.brand-name span{ display:block; font-family:'IBM Plex Mono',monospace; font-weight:400; font-size:0.62rem; letter-spacing:0.1em; color:var(--ink-soft); text-transform:uppercase; margin-top:2px; }

.brand-logo{ height:44px; width:auto; display:block; }
.brand-tagline{
  font-family:'IBM Plex Mono',monospace; font-weight:400; font-size:0.5rem; letter-spacing:-0.01em;
  color:rgba(245,248,250,0.55); text-transform:none;
  white-space:nowrap;
}

.nav-links{ display:flex; gap:32px; align-items:center; }

.nav-dropdown{ position:relative; }
.dropdown-trigger{ display:inline-flex; align-items:center; gap:4px; }
.dropdown-trigger .caret{ font-size:0.65rem; opacity:0.6; transition:transform .2s ease; }
.nav-dropdown:hover .dropdown-trigger .caret,
.nav-dropdown:focus-within .dropdown-trigger .caret{ transform:rotate(180deg); }

.dropdown-menu{
  position:absolute; top:100%; left:50%; transform:translateX(-50%) translateY(6px);
  background:var(--pcb-green-deep); border:1px solid rgba(245,248,250,0.12); border-radius:6px;
  padding:8px; min-width:210px; box-shadow:0 16px 32px rgba(7,31,48,0.4);
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .18s ease, transform .18s ease, visibility .18s ease;
  z-index:200;
}
.nav-dropdown:hover .dropdown-menu,
.nav-dropdown:focus-within .dropdown-menu{
  opacity:1; visibility:visible; pointer-events:auto; transform:translateX(-50%) translateY(0);
}
.dropdown-menu a{
  display:block; padding:10px 14px; border-radius:4px;
  font-size:0.84rem; font-weight:500; white-space:nowrap; color:rgba(245,248,250,0.75);
  transition:background .15s ease, color .15s ease;
}
.dropdown-menu a:hover{ background:rgba(245,248,250,0.08); color:var(--silkscreen); }
.nav-links a{
  font-size:0.86rem; font-weight:500; color:rgba(245,248,250,0.72);
  position:relative; padding:6px 0;
  transition:color .2s ease;
}
.nav-links a:hover{ color:var(--silkscreen); }
.nav-links a::after{
  content:''; position:absolute; left:0; bottom:0; height:2px; width:0;
  background:var(--copper-bright); transition:width .2s ease;
}
.nav-links a:hover::after{ width:100%; }

/* ---------- MOBILE NAV ---------- */
/* Hidden on desktop; the breakpoint below turns it on and converts .nav-links
   into a drop-down panel. */
.nav-toggle{
  display:none; width:44px; height:44px; padding:0; margin-left:auto;
  align-items:center; justify-content:center;
  background:transparent; border:1px solid rgba(245,248,250,0.22);
  border-radius:4px; cursor:pointer;
}
.nav-toggle-bars{ position:relative; }
.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after{
  display:block; width:18px; height:2px; border-radius:2px;
  background:var(--silkscreen);
  transition:transform .22s ease, background .18s ease;
}
.nav-toggle-bars::before,
.nav-toggle-bars::after{ content:''; position:absolute; left:0; }
.nav-toggle-bars::before{ top:-6px; }
.nav-toggle-bars::after{ top:6px; }
/* bars fold into an X while the panel is open */
header[data-nav-open] .nav-toggle-bars{ background:transparent; }
header[data-nav-open] .nav-toggle-bars::before{ transform:translateY(6px) rotate(45deg); }
header[data-nav-open] .nav-toggle-bars::after{ transform:translateY(-6px) rotate(-45deg); }

/* The quote button inside the panel — mobile only, since the header's own copy
   is hidden at that size. Scoped to .nav-links so it outranks .btn's
   display:inline-flex; a bare .nav-cta ties on specificity and loses on source
   order, which put a second quote button in the desktop header. */
.nav-links .nav-cta{ display:none; }

.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

.btn{
  display:inline-flex; align-items:center; gap:8px;
  font-family:'IBM Plex Mono', monospace;
  font-size:0.8rem; font-weight:500; letter-spacing:0.03em;
  padding:12px 22px; border-radius:3px;
  border:1px solid transparent;
  cursor:pointer; transition: all .2s ease;
  white-space:nowrap;
}
.btn-copper{
  background: var(--copper); color:var(--silkscreen);
}
.btn-copper:hover{ background: var(--copper-bright); transform:translateY(-1px); box-shadow:0 8px 20px rgba(46,127,191,0.35); }
.btn-ghost{
  border-color: var(--ink); color:var(--ink); background:transparent;
}
.btn-ghost:hover{ background:var(--ink); color:var(--silkscreen); }
.btn-ghost-light{
  border-color: rgba(245,248,250,0.4); color:var(--silkscreen); background:transparent;
}
.btn-ghost-light:hover{ background:rgba(245,248,250,0.12); border-color:var(--silkscreen); }

/* ---------- HERO (homepage) ---------- */
.hero{
  background-image:
    /* Lighter mid-navy over the left, where the copy sits, easing into the deep
       navy on the right. The left stops were near-opaque, which crushed a
       mid-green image to almost black for no benefit — contrast there was
       ~14:1 against text needing 4.5:1. */
    linear-gradient(115deg, rgba(14,61,92,0.84) 0%, rgba(14,61,92,0.72) 38%, rgba(7,31,48,0.52) 68%, rgba(7,31,48,0.76) 100%),
    url('assets/img/hero-board-focus.jpg');
  background-size: cover, cover;
  background-position: center, 60% 45%;
  color: var(--silkscreen);
  overflow:hidden;
  position:relative;
}
.hero .wrap{
  display:grid; grid-template-columns: 1.05fr 0.95fr;
  align-items:center; gap:40px;
  /* Trimmed from 88px. The hero's height is set by the copy column (~689px at
     desktop), not the 420px animation, so padding is the only lever that
     shortens it without cutting words. */
  padding-top:64px; padding-bottom:64px;
  min-height:520px;
}
.hero .eyebrow{ color: var(--copper-bright); margin-bottom:22px; }
.hero h1{
  font-size:clamp(2.3rem, 4.6vw, 3.4rem);
  line-height:1.08;
  color: var(--silkscreen);
  margin-bottom:22px;
}
.hero h1 em{ font-style:normal; color: var(--copper-bright); }
.hero p.lede{
  font-size:1.06rem; color: rgba(245,248,250,0.78);
  max-width:46ch; margin-bottom:34px;
}
.hero-copy{ margin-top:22px; margin-bottom:34px; }
.hero-copy .eyebrow{ margin-bottom:14px; }
.hero-copy .subhead{
  font-family:'Space Grotesk', sans-serif; font-weight:600; font-size:1.25rem;
  color: var(--silkscreen); margin-bottom:16px;
}
.hero-copy p:not(.subhead){
  font-size:1.02rem; color: rgba(245,248,250,0.78);
  max-width:52ch; margin-bottom:16px;
}
.hero-copy p:last-child{ margin-bottom:0; }

.hero-ctas{ display:flex; gap:14px; flex-wrap:wrap; margin-top:34px; }

.hero-art{ position:relative; height:420px; }
.hero-art svg{ width:100%; height:100%; overflow:visible; }
.trace-path{
  fill:none; stroke: var(--copper-bright); stroke-width:2.5;
  stroke-linecap:square; stroke-linejoin:miter;
  stroke-dasharray: 900; stroke-dashoffset:900;
  animation: draw 2.4s 0.3s cubic-bezier(.4,.7,.3,1) forwards;
}
.trace-path.dim{ stroke: rgba(245,248,250,0.22); animation-delay:0s; }
@keyframes draw{ to{ stroke-dashoffset:0; } }
.pad{ fill: var(--fr4-tan); opacity:0; animation: fadein .5s ease forwards; }
@keyframes fadein{ to{ opacity:1; } }
.pad-label{
  font-family:'IBM Plex Mono',monospace; font-size:10px; fill: rgba(245,248,250,0.55);
  opacity:0; animation: fadein .5s ease forwards;
}
.pulse{
  fill: var(--test-yellow);
  filter: drop-shadow(0 0 6px rgba(79,209,232,0.9));
}

/* ---------- PAGE HERO (interior pages) ---------- */
.page-hero{
  background-image:
    linear-gradient(115deg, rgba(7,31,48,0.93) 0%, rgba(7,31,48,0.86) 50%, rgba(7,31,48,0.93) 100%),
    var(--page-hero-img, none);
  background-size: cover;
  background-position: center 42%;
  color: var(--silkscreen);
  padding:52px 0 46px;
}
/* video-backed page hero: video (z0) -> gradient scrim (z1) -> content (z2) */
/* 122/112 is the standard height for a video hero. It started as a scoped
   modifier for Box Builds and is now the default for all of them. */
/* Every video header is the same height as Box Builds' at each screen size, whatever
   the length of its text: the height is fixed and the text is centred inside it.
   (It used to be padding plus text, so a three-line description ran 26px taller.)
   The padding is only a floor for unusually long text, split 10px heavier on top so
   Box Builds' text sits exactly where it always has. */
.page-hero.has-video{
  position:relative; overflow:hidden;
  min-height:370px; padding:53px 0 43px;
  display:flex; flex-direction:column; justify-content:center;
}
@media (max-width:900px){ .page-hero.has-video{ min-height:352px; } }
.page-hero .hero-video{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; z-index:0; pointer-events:none;
  /* Which slice of the frame stays visible once cover crops it. Per-page via
     --hero-video-y and --hero-video-x, the same way each hero sets its own
     --page-hero-img. Wide screens crop top and bottom, so -y is the one that
     shows there (lower % = more of the top of the footage). Phones crop the
     sides instead, so -x is what shows there (higher % = more of the right). */
  object-position: var(--hero-video-x, 50%) var(--hero-video-y, 50%);
}
.page-hero.has-video::after{
  content:''; position:absolute; inset:0; z-index:1;
  background: linear-gradient(115deg, rgba(7,31,48,0.89) 0%, rgba(7,31,48,0.82) 50%, rgba(7,31,48,0.89) 100%);
}
.page-hero.has-video > .wrap{ position:relative; z-index:2; }

/* Don't autoplay motion for visitors who ask not to — the still poster/background shows instead */
@media (prefers-reduced-motion: reduce){
  .page-hero .hero-video{ display:none; }
}

.page-hero h1{ color:var(--silkscreen); font-size:clamp(2rem,4vw,2.7rem); margin-bottom:14px; }
.page-hero p.lede{ color:rgba(245,248,250,0.78); max-width:62ch; font-size:1.03rem; }

/* ---------- SECTION SHELLS ---------- */
section{ padding:96px 0; }
.section-head{ max-width:640px; margin-bottom:56px; }
.section-head h2{ font-size:clamp(1.7rem,3vw,2.3rem); margin-top:14px; }
.section-head p{ color:var(--ink-soft); margin-top:14px; font-size:1.02rem; }

/* ---------- SERVICES ---------- */
.services{ background: var(--fr4-tan); position:relative; }
.service-grid{
  display:grid; grid-template-columns:repeat(4,1fr); gap:0;
  border-top:1px solid var(--line);
}
.service-card{
  padding:34px 26px 0; border-right:1px solid var(--line);
  position:relative;
}
.service-card:last-child{ border-right:none; }
.service-num{
  font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:var(--copper);
  margin-bottom:18px; display:block;
}
.service-card svg{ width:44px; height:44px; margin-bottom:20px; }
.service-card h3{ font-size:1.06rem; margin-bottom:10px; }
.service-card p{ color:var(--ink-soft); font-size:0.92rem; margin-bottom:30px; }
.service-card a.more{
  font-family:'IBM Plex Mono',monospace; font-size:0.76rem; color:var(--ink);
  border-top:1px solid var(--line); display:block; padding:16px 0;
  display:flex; align-items:center; justify-content:space-between;
  transition:color .2s ease;
}
.service-card a.more:hover{ color:var(--copper); }

/* ---------- WHY PRECISE ---------- */
.why{ background: var(--ink); color: var(--silkscreen); }
.why .eyebrow{ color:var(--copper-bright); }
.why .section-head h2{ color:var(--silkscreen); }
.why .section-head p{ color: rgba(245,248,250,0.6); }
.why-stats{
  display:flex; flex-wrap:wrap; gap:40px;
  margin:36px 0 56px; padding-bottom:44px;
  border-bottom:1px solid rgba(245,248,250,0.12);
}
.why-stat .num{ font-family:'Space Grotesk',sans-serif; font-weight:700; font-size:2.1rem; color:var(--test-yellow); line-height:1; }
.why-stat .label{ font-size:0.86rem; color:rgba(245,248,250,0.6); margin-top:8px; max-width:20ch; }

.why-grid{ display:grid; grid-template-columns:repeat(2,1fr); gap:36px; }
.why-card{ border-left:2px solid rgba(245,248,250,0.15); padding-left:22px; }
.why-card .tag{ font-family:'IBM Plex Mono',monospace; font-size:0.7rem; color:var(--test-yellow); text-transform:uppercase; letter-spacing:0.08em; }
.why-card h3{ color:var(--silkscreen); font-size:1.15rem; margin:10px 0 10px; }
.why-card p{ color:rgba(245,248,250,0.62); font-size:0.94rem; }
/* Heading and seals share a row on the Market access card. The seals do not
   shrink, so a long heading wraps rather than squeezing them. */
.why-card-head{ display:flex; align-items:center; justify-content:space-between; gap:16px; }
.why-card-head h3{ margin:10px 0; }
.why-card-seals{ display:flex; align-items:center; gap:8px; flex-shrink:0; }
.why-card-seals img{ width:62px; height:auto; display:block; }
@media (max-width:520px){
  .why-card-seals img{ width:52px; }
}

.why-more{ margin:20px 0 24px; }
.why-more-lead{ font-family:'Space Grotesk',sans-serif; font-weight:600; font-size:1.15rem; color:var(--silkscreen); margin-bottom:18px; }
.why-more .eyebrow{ margin-bottom:14px; }
.why-more p:not(.why-more-lead){ color:rgba(245,248,250,0.62); font-size:0.98rem; margin-top:14px; }

/* ---------- TESTIMONIAL ---------- */
.testimonial{ background: var(--silkscreen); }
.testi-box{
  max-width:820px; margin:0 auto; text-align:left;
  border:1px solid var(--line); border-radius:6px; padding:48px;
  position:relative; background:var(--fr4-tan);
  transition: opacity .4s ease;
}
.testi-box.fade-out{ opacity:0; }
.testi-box::before{
  content:'"'; position:absolute; top:18px; left:32px;
  font-family:'Space Grotesk',sans-serif; font-size:4rem; color:var(--copper); opacity:0.35; line-height:1;
}
.testi-box p.quote{ font-size:1.2rem; line-height:1.55; margin-bottom:22px; padding-left:8px; }
.testi-box .attribution{ font-family:'IBM Plex Mono',monospace; font-size:0.82rem; color:var(--ink-soft); }

/* ---------- CTA BAND ---------- */
.cta-band{
  background: linear-gradient(120deg, var(--pcb-green) 0%, var(--pcb-green-deep) 100%);
  color:var(--silkscreen); text-align:center;
}
/* h1 as well as h2: on thank-you.html and 404.html this band holds the page's main
   heading, which is an h1. Without it, it fell back to the dark base heading colour
   and vanished against the navy. */
.cta-band h1, .cta-band h2{ color:var(--silkscreen); font-size:clamp(1.6rem,3vw,2.1rem); margin-bottom:16px; }
.cta-band p{ color:rgba(245,248,250,0.7); margin-bottom:32px; }
.cta-band .btns{ display:flex; gap:14px; justify-content:center; flex-wrap:wrap; }

/* ---------- INTERIOR CONTENT (capability copy + specs + gallery) ---------- */
.content-lead{ max-width:760px; }
.content-lead p{ margin-bottom:18px; font-size:1.04rem; color:var(--ink-soft); }
.content-lead p:first-child{ font-size:1.15rem; color:var(--ink); }

/* Long-form legal text (privacy-policy-terms-conditions.html). Deliberately NOT a
   .reveal block: the observer needs 15% of an element on screen at once, which a
   page-long block can never reach, so it would never fade in. */
.legal{ max-width:72ch; }
.legal .legal-meta{ font-family:'IBM Plex Mono',monospace; font-size:0.8rem; letter-spacing:0.03em; color:var(--ink-soft); margin-bottom:10px; }
.legal .legal-jump{ font-size:0.92rem; color:var(--ink-soft); margin-bottom:40px; }
.legal h2{ font-size:1.7rem; margin:56px 0 4px; scroll-margin-top:96px; }
.legal h2:first-of-type{ margin-top:0; }
.legal h3{ font-size:1.05rem; margin:28px 0 8px; }
.legal p, .legal address{ color:var(--ink-soft); line-height:1.7; margin-bottom:12px; font-style:normal; }
.legal a{ color:var(--copper); text-decoration:underline; }

.spec-grid{
  display:grid; grid-template-columns:repeat(3,1fr); gap:1px;
  background:var(--line); border:1px solid var(--line); margin-top:52px;
}
.spec-item{ background:var(--silkscreen); padding:26px 24px; }
.spec-item .k{
  font-family:'IBM Plex Mono',monospace; font-size:0.7rem; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--copper); display:block; margin-bottom:10px;
}
.spec-item .v{ font-size:1.5rem; font-family:'Space Grotesk',sans-serif; font-weight:600; line-height:1.2; }
.spec-item .d{ font-size:0.86rem; color:var(--ink-soft); margin-top:6px; }

.capability-list{ margin-top:18px; }
.capability-list li{
  list-style:none; padding:16px 0; border-bottom:1px solid var(--line);
  display:flex; gap:18px; align-items:baseline;
}
.capability-list li .tick{ color:var(--copper); font-family:'IBM Plex Mono',monospace; flex-shrink:0; }

.checklist-table{ margin-top:18px; border:1px solid var(--line); border-radius:6px; overflow:hidden; }
.checklist-row{
  display:flex; justify-content:space-between; gap:24px;
  padding:14px 20px; border-bottom:1px solid var(--line);
  font-size:0.96rem;
}
.checklist-row:last-child{ border-bottom:none; }
.checklist-row:nth-child(odd){ background:var(--fr4-tan); }
.checklist-row .opts{
  font-family:'IBM Plex Mono',monospace; font-size:0.82rem; color:var(--ink-soft);
  white-space:nowrap;
}
.checklist-footnote{ font-size:0.84rem; color:var(--ink-soft); margin-top:16px; }

.contact-strip{
  display:flex; flex-wrap:wrap; align-items:center; gap:10px 28px;
  padding-bottom:24px; border-bottom:1px solid var(--line);
  font-family:'IBM Plex Mono',monospace; font-size:0.86rem; color:var(--ink-soft);
}
.contact-strip a{ color:var(--ink-soft); transition:color .2s ease; }
.contact-strip a:hover{ color:var(--copper); }

.map-embed{ border-radius:6px; overflow:hidden; border:1px solid var(--line); margin-top:8px; }
.map-embed iframe{ width:100%; height:360px; border:0; display:block; }

.gallery-section{ background:var(--fr4-tan); }
.gallery-grid{
  display:grid; grid-template-columns:repeat(3,1fr); gap:18px; margin-top:8px;
}
.gallery-grid figure{ border-radius:6px; overflow:hidden; border:1px solid var(--line); }
.gallery-grid img{ width:100%; height:230px; object-fit:cover; display:block; transition:transform .4s ease; }
.gallery-grid figure:hover img{ transform:scale(1.05); }
.gallery-grid figcaption{
  font-family:'IBM Plex Mono',monospace; font-size:0.74rem; color:var(--ink-soft);
  padding:10px 14px; background:var(--silkscreen);
}

/* ---------- QUOTE FORM ---------- */
.quote-form-note{ max-width:640px; font-size:0.92rem; color:var(--ink-soft); margin-bottom:28px; }
.quote-form-note a{ color:var(--copper); text-decoration:underline; }
.quote-form{ max-width:640px; }
.hidden-field{ position:absolute; left:-9999px; }
.form-row{ margin-bottom:22px; display:flex; flex-direction:column; gap:8px; }
.form-row-split{ display:grid; grid-template-columns:1fr 1fr; gap:22px; }
.form-row-split > div{ display:flex; flex-direction:column; gap:8px; }
.quote-form label{
  font-family:'IBM Plex Mono',monospace; font-size:0.78rem; letter-spacing:0.03em;
  color:var(--ink-soft); text-transform:uppercase;
}
.quote-form .req{ color:var(--copper); }
.quote-form input,
.quote-form select,
.quote-form textarea{
  font-family:'IBM Plex Sans', sans-serif; font-size:0.98rem; color:var(--ink);
  background:var(--silkscreen); border:1px solid var(--line-control); border-radius:3px;
  padding:12px 14px; width:100%; resize:vertical;
}
.quote-form input[type="file"]{ padding:10px 14px; font-size:0.9rem; }
.quote-form input[type="file"]::file-selector-button{
  font-family:'IBM Plex Mono',monospace; font-size:0.76rem; font-weight:500;
  color:var(--silkscreen); background:var(--copper); border:none; border-radius:3px;
  padding:8px 14px; margin-right:14px; cursor:pointer; transition:background .2s ease;
}
.quote-form input[type="file"]::file-selector-button:hover{ background:var(--copper-bright); }
.quote-form input:focus,
.quote-form select:focus,
.quote-form textarea:focus{
  outline:2px solid var(--copper); outline-offset:1px; border-color:var(--copper);
}
.quote-form button{ margin-top:8px; }
.field-note{
  font-size:0.9rem; color:var(--ink-soft); line-height:1.55;
  background:var(--fr4-tan); border:1px solid var(--line); border-radius:4px;
  padding:12px 14px;
}
.field-note a{ color:var(--copper); text-decoration:underline; }

/* A group of radios needs a fieldset/legend, not a bare <label> — a label may
   only point at one control, so screen readers never announced the question. */
.quote-form .field-group{ border:0; padding:0; margin:0; }
.quote-form .field-group legend{
  font-family:'IBM Plex Mono',monospace; font-size:0.78rem; letter-spacing:0.03em;
  color:var(--ink-soft); text-transform:uppercase; padding:0; margin-bottom:8px;
}
/* Same look as a label, for text that introduces something which is not a control. */
.quote-form .field-heading{
  font-family:'IBM Plex Mono',monospace; font-size:0.78rem; letter-spacing:0.03em;
  color:var(--ink-soft); text-transform:uppercase;
}
.form-required-note{ font-size:0.85rem; color:var(--ink-soft); margin:4px 0 0; }

/* A rating scale. The generic rule above sets width:100% on every input, which
   stretched each radio across its whole label and pushed the text off to one
   side; radios and checkboxes need their intrinsic size. */
.quote-form .choice-list{ display:flex; flex-wrap:wrap; gap:12px 26px; }
.quote-form .choice{
  display:flex; align-items:center; gap:8px; cursor:pointer;
  font-family:'IBM Plex Sans',sans-serif; font-size:0.95rem;
  text-transform:none; letter-spacing:0; color:var(--ink);
}
.quote-form .choice input[type="radio"],
.quote-form .choice input[type="checkbox"]{
  width:auto; flex:none; margin:0; padding:0; accent-color:var(--copper);
}


/* ---------- FOOTER ---------- */
footer{ background: var(--ink); color: rgba(245,248,250,0.55); padding:60px 0 28px; }
.footer-grid{
  display:grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap:40px;
  padding-bottom:40px; border-bottom:1px solid rgba(245,248,250,0.1);
}
.footer-grid h4{ font-family:'IBM Plex Mono',monospace; font-size:0.72rem; letter-spacing:0.1em; text-transform:uppercase; color:var(--silkscreen); margin-bottom:16px; }
.footer-grid p, .footer-grid a{ font-size:0.88rem; display:block; margin-bottom:8px; color:rgba(245,248,250,0.55); transition:color .2s ease; }
.footer-grid a:hover{ color:var(--copper-bright); }
/* The rule above turns every footer link into a block, which is right for the
   link columns but breaks the address block, where the phone and email sit
   inside running text. Higher specificity, so it wins at every breakpoint,
   including the 900px rule that makes column links 40px flex rows. */
.footer-grid p a{ display:inline; margin:0; min-height:0; text-decoration:underline; }
.footer-grid p a:hover{ color:var(--copper-bright); }
.footer-bottom{
  display:flex; justify-content:space-between; align-items:center;
  padding-top:24px; font-size:0.78rem; flex-wrap:wrap; gap:12px;
}
/* Trust marks, footer. Grouped so they stay together when the row wraps on
   narrow screens rather than the seal orphaning onto its own line. */
.footer-marks{ display:flex; align-items:center; gap:12px; }
.footer-bottom span a{ color:inherit; text-decoration:underline; margin-left:10px; white-space:nowrap; }
.footer-bottom span a:hover{ color:var(--copper-bright); }
.trust-seal{ width:58px; height:auto; display:block; flex-shrink:0; }

/* Featured on the Texas page, where the claims are the subject rather than a
   footnote. Floated as a pair so the opening copy wraps around both. */
.trust-seals{
  float:right; margin:0 0 18px 28px;
  display:flex; align-items:center; gap:16px;
}
.trust-seals img{ width:118px; height:auto; display:block; }
@media (max-width:640px){
  /* Too narrow for text to wrap around them — centre the pair above the copy. */
  .trust-seals{ float:none; margin:0 auto 22px; justify-content:center; gap:14px; }
  .trust-seals img{ width:96px; }
}

.iso-badge{
  font-family:'IBM Plex Mono',monospace; font-size:0.72rem; border:1px solid rgba(245,248,250,0.25);
  padding:6px 12px; border-radius:3px; color:rgba(245,248,250,0.7);
  transition: color .2s ease, border-color .2s ease;
}
.iso-badge:hover{ color:var(--copper-bright); border-color:var(--copper-bright); }

/* ---------- OUR PEOPLE ---------- */
/* Three tiers of cards. Every card in a tier has the same parts in the same order
   (photo, name, role, line, optional expander); keep it that way, since mismatched
   cards are what makes a team page look amateur. Photos go in .person-photo at 4:5,
   replacing the initials placeholder — see the PHOTO comments in our-people.html. */
.team-group{ margin-top:72px; }
.team-group .section-head{ margin-bottom:32px; }
.team-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:24px; align-items:start; }
.team-grid.cols-4{ grid-template-columns:repeat(4,1fr); }
.person-card{
  background:#fff; border:1px solid var(--line); border-radius:4px; overflow:hidden;
  display:flex; flex-direction:column; height:100%;
}
.person-photo{
  aspect-ratio:4/5; display:flex; align-items:center; justify-content:center;
  background:linear-gradient(160deg, var(--fr4-tan) 0%, var(--fr4-tan-deep) 100%);
}
.person-photo img{ width:100%; height:100%; object-fit:cover; display:block; }
.person-photo .initials{
  font-family:'Space Grotesk',sans-serif; font-weight:600; font-size:2.6rem;
  letter-spacing:0.02em; color:rgba(14,61,92,0.32);
}
.person-body{ padding:20px 20px 22px; display:flex; flex-direction:column; gap:6px; flex:1; }
.person-card h3{ font-size:1.12rem; }
.person-card.lead h3{ font-size:1.35rem; }
.person-role{
  font-family:'IBM Plex Mono',monospace; font-size:0.72rem; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--copper);
}
.person-line{ color:var(--ink-soft); font-size:0.93rem; margin-top:6px; line-height:1.6; }
.person-card.lead .person-line{ font-size:0.98rem; }
.person-more{ margin-top:8px; font-size:0.9rem; color:var(--ink-soft); }
.person-more summary{
  cursor:pointer; list-style:none; width:max-content;
  font-family:'IBM Plex Mono',monospace; font-size:0.75rem; letter-spacing:0.03em; color:var(--copper);
}
.person-more summary::-webkit-details-marker{ display:none; }
.person-more summary::after{ content:" +"; }
.person-more[open] summary::after{ content:" −"; }
.person-more p{ margin-top:10px; line-height:1.6; }
.person-contact{ margin-top:auto; padding-top:14px; }
.person-contact .btn{ padding:9px 16px; font-size:0.75rem; }
@media (max-width:900px){
  .team-grid, .team-grid.cols-4{ grid-template-columns:repeat(2,1fr); gap:18px; }
}
@media (max-width:520px){
  .team-grid.lead-grid{ grid-template-columns:1fr; }
  .team-grid{ gap:14px; }
  .person-body{ padding:14px 14px 16px; }
  .person-photo .initials{ font-size:2rem; }
  .person-contact .btn{ padding:8px 12px; }
}

/* ---------- SCROLL REVEAL ---------- */
/* Scroll-reveal. The hiding half is scoped to html.js, which the inline head
   script sets. If scripts never run — disabled, stripped by a corporate proxy,
   blocked by a CSP, or an error earlier in the page — the class is never added,
   this rule never matches, and the content is simply visible with no animation.
   Previously .reveal was hidden unconditionally, so a page whose script did not
   run rendered as a header and footer around empty space. */
html.js .reveal{ opacity:0; transform:translateY(18px); transition: opacity .7s ease, transform .7s ease; }
html.js .reveal.in{ opacity:1; transform:translateY(0); }

/* ---------- RESPONSIVE ---------- */
@media (max-width: 900px){
  header nav.wrap{ position:relative; }
  .nav-toggle{ display:flex; }
  header > nav > .btn-copper{ display:none; }   /* replaced by .nav-cta in the panel */

  /* .nav-links was simply display:none here, which left phones and small
     tablets with no navigation at all — only the footer links. It is now a
     panel that drops out of the header. */
  .nav-links{
    display:block; position:absolute; top:100%; left:0; right:0;
    /* Fully opaque, and no backdrop-filter of its own. The header already has
       one, and nesting them composited badly enough to let the hero headline
       read through the menu. Nothing shows through an opaque panel anyway. */
    background:#0E3D5C;
    border-bottom:1px solid rgba(245,248,250,0.12);
    box-shadow:0 18px 30px rgba(7,31,48,0.35);
    padding:0 20px; gap:0;
    max-height:0; overflow:hidden; visibility:hidden;
    transition:max-height .3s ease, visibility .3s ease;
  }
  header[data-nav-open] .nav-links{
    max-height:min(78vh,640px); overflow-y:auto; visibility:visible;
  }
  .nav-links > a,
  .nav-links .dropdown-trigger{
    display:flex; align-items:center; min-height:48px;
    font-size:0.95rem; border-bottom:1px solid rgba(245,248,250,0.08);
  }
  .nav-links a::after{ display:none; }          /* hover underline is pointless on touch */

  /* Dropdowns opened on hover, which touch has no equivalent for. Inside the
     panel they are simply expanded and indented. */
  .nav-dropdown{ position:static; }
  .dropdown-trigger .caret{ display:none; }
  /* visibility is inherited, and a descendant setting visibility:visible
     overrides an ancestor's hidden. Declaring it unconditionally here left the
     12 dropdown links keyboard-focusable while the panel was shut — a sighted
     keyboard user tabbed into an invisible menu. It is now scoped to the open
     panel, so the closed panel's visibility:hidden reaches them. */
  .dropdown-menu{
    position:static; transform:none; opacity:1;
    pointer-events:auto; background:transparent; border:none; box-shadow:none;
    min-width:0; padding:0 0 6px 14px;
  }
  header[data-nav-open] .dropdown-menu{ visibility:visible; }
  .dropdown-menu a{
    display:flex; align-items:center; min-height:44px;
    white-space:normal; font-size:0.9rem;
  }
  /* The desktop rules re-apply translateX(-50%) on :hover and :focus-within to
     centre the floating menu. Overriding the base .dropdown-menu above was not
     enough: those selectors carry three classes to its one, so tapping an item
     re-matched :focus-within and snapped the whole group left by half its
     width — 167px of a 335px menu. Restated here to win on source order. */
  .nav-dropdown:hover .dropdown-menu,
  .nav-dropdown:focus-within .dropdown-menu{
    transform:none;
  }
  .nav-links .nav-cta{ display:flex; justify-content:center; margin:16px 0 20px; }

  /* Footer links were 20-30px tall — under the 44px minimum for a tap target. */
  .footer-grid a{ display:flex; align-items:center; min-height:40px; }
  .hero .wrap{ grid-template-columns:1fr; padding-top:56px; padding-bottom:56px; }
  /* The animation used to sit above the copy, pushing the headline and both
     buttons below the fold. It now follows them, in DOM order.
     The viewBox is square (420x420), so a square container fills it edge to
     edge instead of fitting to height and wasting the sides. Capped at the
     viewBox's own size so it never scales up past its native resolution, and
     the hero grows with it, so it stays inside the background photo. */
  .hero-art{
    height:auto; aspect-ratio:1/1;
    width:100%; max-width:420px;
    margin:12px auto 0;
  }
  .service-grid{ grid-template-columns:1fr 1fr; }
  .service-card{ border-bottom:1px solid var(--line); padding-bottom:30px; }
  .service-card:nth-child(2n){ border-right:none; }
  .why-grid{ grid-template-columns:1fr; gap:28px; }
  .why-stats{ gap:28px 32px; margin:28px 0 40px; padding-bottom:32px; }
  .footer-grid{ grid-template-columns:1fr 1fr; gap:28px; }
  section{ padding:64px 0; }
  .spec-grid{ grid-template-columns:1fr 1fr; }
  .gallery-grid{ grid-template-columns:1fr 1fr; }
}
/* Narrow tablets and large phones. Kept separate from the 900px tier so an
   860px tablet keeps its full 32px gutters and its tagline. */
@media (max-width:700px){
  .wrap{ padding:0 24px; }
  /* Was hidden here while the header still carried the 182px quote button.
     That button now lives in the menu, so there is room again — scaled down,
     and still on a single line. */
  .brand-tagline{ font-size:0.46rem; }
  .brand-logo{ height:40px; }
  section{ padding:56px 0; }
  .page-hero{ padding:44px 0 38px; }
  .page-hero.has-video{ min-height:296px; padding:45px 0 35px; }
}

@media (max-width:520px){
  .wrap{ padding:0 18px; }
  .brand-logo{ height:36px; }
  .brand-tagline{ font-size:0.43rem; }

  /* The clamp() floors never engage on a phone — 4.6vw of 375px is only 17px,
     so every heading rendered at its desktop floor regardless of screen. These
     set real phone sizes. */
  .hero h1{ font-size:2.05rem; line-height:1.12; }
  .page-hero h1{ font-size:1.62rem; }
  .section-head h2{ font-size:1.42rem; }
  .cta-band h1, .cta-band h2{ font-size:1.32rem; }

  .page-hero.has-video{ min-height:316px; padding:39px 0 33px; }
  .hero-art{ max-width:340px; margin-top:10px; }
  .hero-ctas{ display:flex; flex-direction:column; align-items:stretch; gap:12px; }
  .hero-ctas .btn{ justify-content:center; }

  /* Label and options were competing for 280px and wrapping to three lines.
     Wrapping rather than stacking lets short rows stay on one line and only
     the long ones ("IPC/WHMA-A-620B Class*", "TURNKEY / CONSIGNED") take a
     second — forcing a column made all 13 rows two lines and grew the table. */
  .checklist-row{ flex-wrap:wrap; gap:2px 16px; padding:12px 16px; }
  .checklist-row .opts{ white-space:normal; }

  .form-row-split{ grid-template-columns:1fr; gap:14px; }

  .service-grid{ grid-template-columns:1fr; }
  .footer-grid{ grid-template-columns:1fr; }
  .testi-box{ padding:32px 24px; }
  .spec-grid{ grid-template-columns:1fr; }
  .gallery-grid{ grid-template-columns:1fr; }
}

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  .trace-path{ animation:none; stroke-dashoffset:0; }
  .pad, .pad-label{ animation:none; opacity:1; }
  /* Must carry the same html.js prefix as the rule it overrides — a media
     query adds no specificity, so a bare .reveal here would lose to it. */
  html.js .reveal{ transition:none; opacity:1; transform:none; }
}

/* Chat mascot. Geometry (size/right/bottom) is set by assets/js/mascot.js
   from the live bubble, so only the static traits belong here. z-index sits
   just under Tawk's bubble (1000003) so his feet tuck behind it rather than
   covering it, and pointer-events are off so he can never intercept a tap
   meant for the chat. */
.chat-mascot{
  /* Above Tawk's widget container (a direct child of body at z-index
     2000000000), so he paints in front of the greeting card. The icon is in
     that same container, so this puts him in front of the icon too — the
     occlusion is faked instead, by clipping his legs at the circle's top edge
     in mascot.js. No z-index can sit between the greeting and the icon: they
     are siblings inside the same container. */
  position:fixed; z-index:2147483000;
  pointer-events:none; user-select:none;
  opacity:0; transition:opacity .25s ease;
  /* The shadow belongs here, on the wrapper, and the fade on the image inside
     it. Both on one element does not work: a mask is sized to that element's
     box, so it erases whatever the filter paints beyond it — which is what cut
     off the raised hand's shadow. Separated, the wrapper's shadow paints freely
     because the wrapper itself is unmasked. */
  filter:drop-shadow(0 6px 10px rgba(7,31,48,0.35));
}
/* Dismiss button, set out to the right of his head rather than on it. Styled
   like the close control on Tawk's own welcome card so it reads as chrome
   rather than part of the illustration.

   Positioned in percentages because the wrapper is sized from the launcher at
   runtime. His head's right edge measures ~60% across the artwork, so 78%
   clears it with a gap, and the space out there is transparent margin. The
   wrapper is pointer-events none so he can never intercept a click meant for
   the chat; this re-enables them on itself alone. */
.chat-mascot-close{
  position:absolute; left:78%; top:5%;
  width:22px; height:22px; padding:0; margin:0;
  transform:translate(-50%,-50%) scale(0.7);
  display:flex; align-items:center; justify-content:center;
  border:0; border-radius:50%;
  background:#fff; color:#54656f;
  font-family:'IBM Plex Sans',sans-serif; font-size:15px; font-weight:400;
  line-height:1; cursor:pointer; pointer-events:auto;
  box-shadow:0 1px 4px rgba(7,31,48,0.3);
  opacity:0; visibility:hidden;
  transition:opacity .16s ease, transform .16s ease, visibility .16s ease;
}
.chat-mascot.near .chat-mascot-close{
  opacity:1; visibility:visible; transform:translate(-50%,-50%) scale(1);
}
.chat-mascot-close:hover{ background:#f1f3f5; color:#1f2d36; }

.chat-mascot img{
  display:block; width:100%; height:100%;

  /* His legs are opaque all the way down and the icon is stacked above him
     (see lift() in assets/js/mascot.js), so they simply disappear behind its
     edge — which reads as continuing behind it. The flat edge where the source
     footage clips his soles sits inside that overlap, so it is never visible.
     
     To fade them into the icon instead, uncomment the two lines below. The
     first number is where the fade begins, the middle stop keeps most of the
     softening in the band you can actually see rather than behind the icon.
     It must stay on this element and not on .chat-mascot: a mask is sized to
     its own element's box, and on the wrapper it erases the drop-shadow
     wherever that falls outside the box, which cuts off the raised hand. */
  /*
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 46px), rgba(0,0,0,0.55) calc(100% - 18px), rgba(0,0,0,0) 100%);
          mask-image: linear-gradient(to bottom, #000 calc(100% - 46px), rgba(0,0,0,0.55) calc(100% - 18px), rgba(0,0,0,0) 100%);
  */
}
/* Touch has no hover, so proximity can never reveal the dismiss button — it is
   always visible there instead, and enlarged, since 22px is a mean tap target.
   Kept in CSS rather than JS so it tracks the input type rather than the
   viewport: a touch laptop gets the same treatment. */
@media (hover: none){
  .chat-mascot .chat-mascot-close{
    width:34px; height:34px; font-size:22px;
    opacity:1; visibility:visible; transform:translate(-50%,-50%) scale(1);
  }
}
/* No dismiss control on phones. He is tied to the welcome banner there — he
   arrives with it and leaves with it — so there is nothing left to dismiss,
   and the corner is too tight to spend on a control. Tablets and touch
   laptops keep it via the rule above. */
@media (max-width:699px){
  .chat-mascot .chat-mascot-close{ display:none; }
}

/* Dual-ring focus indicator. A single copper ring measured 2.66:1 against the
   navy header — below the 3:1 WCAG needs for a non-text indicator. A dark ring
   wrapped in a light one contrasts against whichever background it lands on:
   the pale halo carries it on navy (10.7:1), the dark core on the light pages. */
:focus-visible{
  outline:2px solid var(--pcb-green-deep);
  outline-offset:2px;
  box-shadow:0 0 0 4px var(--silkscreen);
}

/* Lets a keyboard or screen-reader user jump the 17-link header. Off-screen
   until focused, which is the only time it is useful. */
.skip-link{
  position:absolute; left:-9999px; top:0; z-index:2147483001;
  background:var(--silkscreen); color:var(--pcb-green-deep);
  font-family:'IBM Plex Mono',monospace; font-size:0.85rem;
  padding:12px 18px; border-radius:0 0 4px 0; text-decoration:underline;
}
.skip-link:focus{ left:0; }
