/* ============ TOKENS ============ */
:root{
  --navy:#0B2A5B; --navy-900:#071B3D; --ink:#111827; --slate:#64748B;
  --blue:#2563EB; --blue-700:#1D4ED8; --blue-soft:#EFF6FF; --signal:#06B6D4; --signal-soft:#E0F7FA;
  --paper:#FFFFFF; --mist:#F3F6FB; --line:#E2E8F0;
  /* Text sitting ON dark surfaces (photo panels, CTA block, footer, top bar).
     These were hardcoded #fff / #C7D3EA in ~14 rules; tokenised so the admin
     panel's "Text on photos" controls can repoint them. Purely a find/replace
     of the same values — no visual change on its own. */
  --on-dark:#FFFFFF; --on-dark-muted:#C7D3EA;
  /* --heading is the dark TEXT colour; --navy above stays the dark SURFACE
     colour (footer, CTA block, photo panels, active filter chip). They start
     identical, but keeping them separate means recolouring headings from the
     admin panel can never repaint the footer background. */
  --heading:#0B2A5B;
  --home-bg:#EAF6FF; --section-light:#F0F8FF; --page-bg:#F4F7FA;
  --display:'Sora',system-ui,sans-serif; --body:'IBM Plex Sans',system-ui,sans-serif; --mono:'IBM Plex Mono',ui-monospace,monospace;
  --max:1200px; --gutter:clamp(20px,4vw,48px); --r:14px;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{font-family:var(--body);color:var(--ink);background:var(--paper);line-height:1.6;font-size:16px;-webkit-font-smoothing:antialiased}

/* Home gets a distinct soft sky-blue identity; every inner page shares a
   clean light-gray canvas so cards/content blocks read as clearly "raised". */
body[data-page="home"]{background:var(--home-bg)}
body[data-page="about"],body[data-page="services"],body[data-page="products"],body[data-page="contact"],body[data-page="404"]{background:var(--page-bg)}
body[data-page="home"] .section.mist{background:var(--section-light)}
body:not([data-page="home"]) .section.mist{background:var(--paper)}
img,svg{display:block;max-width:100%}
a{color:var(--blue);text-decoration:none}
button{font:inherit;cursor:pointer}
:focus-visible{outline:3px solid var(--signal);outline-offset:3px;border-radius:4px}
.wrap{max-width:var(--max);margin:0 auto;padding:0 var(--gutter)}
h1,h2,h3,h4{font-family:var(--display);color:var(--heading);line-height:1.12;letter-spacing:-0.02em}
h1{font-size:clamp(38px,5.4vw,66px);font-weight:600}
h2{font-size:clamp(28px,3.4vw,42px);font-weight:600}
h3{font-size:20px;font-weight:600}
p.lead{font-size:clamp(17px,1.4vw,20px);color:var(--slate);max-width:56ch}
.mono{font-family:var(--mono);font-size:12.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--blue)}
.eyebrow{display:inline-flex;align-items:center;gap:10px;margin-bottom:18px}
.eyebrow::before{content:"";width:28px;height:2px;background:var(--signal);border-radius:2px}
.section{padding:clamp(64px,8vw,112px) 0}
.section.mist{background:var(--mist)}
.section-head{display:grid;grid-template-columns:1fr;gap:16px;margin-bottom:clamp(36px,5vw,56px);max-width:760px}
.btn{display:inline-flex;align-items:center;gap:10px;padding:14px 22px;border-radius:10px;font-weight:600;font-size:15px;border:1.5px solid transparent;transition:transform .15s ease,background .2s,border-color .2s,color .2s}
.btn:hover{transform:translateY(-1px)}
.btn:disabled{opacity:.6;cursor:not-allowed;transform:none}
.btn-primary{background:var(--blue);color:#fff}
.btn-primary:hover{background:var(--blue-700)}
.btn-ghost{background:transparent;color:var(--heading);border-color:var(--blue)}
.btn-ghost:hover{background:var(--blue-soft);border-color:var(--blue-700)}
.btn svg{width:16px;height:16px;transition:transform .2s ease}
.btn:hover svg{transform:translateX(3px)}

/* ============ HEADER ============ */
.topbar{background:var(--navy-900);color:var(--on-dark-muted);font-family:var(--mono);font-size:12px;letter-spacing:.04em}
.topbar .wrap{display:flex;justify-content:space-between;align-items:center;height:36px}
.topbar a{color:var(--on-dark)}
.topbar span.dot{color:var(--signal);margin:0 8px}
header.site{position:sticky;top:0;z-index:50;background:rgba(255,255,255,.92);backdrop-filter:blur(10px);border-bottom:1px solid var(--line);transition:box-shadow .25s ease}
header.site.scrolled{box-shadow:0 8px 24px rgba(11,42,91,.10)}
header.site .wrap{display:flex;align-items:center;justify-content:space-between;height:74px}
.brand{display:flex;align-items:center;gap:12px;font-family:var(--display);font-weight:700;color:var(--heading);font-size:19px;letter-spacing:-.01em}
.brand .mark{width:38px;height:38px;background:#fff;border-radius:8px;padding:4px;box-sizing:border-box;object-fit:contain}
.brand small{display:block;font-family:var(--mono);font-weight:400;font-size:10.5px;letter-spacing:.14em;color:var(--slate);text-transform:uppercase;line-height:1.1;margin-top:2px}
nav.main{display:flex;gap:4px}
nav.main a{background:none;border:0;padding:10px 14px;border-radius:8px;font-weight:500;color:var(--ink);font-size:15px;position:relative;display:inline-block}
nav.main a::after{content:"";position:absolute;left:14px;right:14px;bottom:4px;height:2px;background:var(--signal);transform:scaleX(0);transform-origin:left;transition:transform .25s}
nav.main a[aria-current="page"]{color:var(--heading);font-weight:600}
nav.main a[aria-current="page"]::after,nav.main a:hover::after{transform:scaleX(1)}
.header-cta{display:flex;align-items:center;gap:12px}
.menu-btn{display:none;background:none;border:1.5px solid var(--line);border-radius:8px;width:44px;height:44px;place-items:center}
.menu-btn svg{width:22px;height:22px;stroke:var(--navy)}

/* ============ HERO ============ */
.hero{position:relative;overflow:hidden;padding:clamp(64px,7.5vw,108px) 0 clamp(56px,6.5vw,88px)}
.hero .wrap{position:relative;z-index:1;display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(32px,5vw,72px);align-items:center}
.hero h1 span{color:var(--blue)}
.hero .actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:32px}
.hero .facts{display:flex;gap:20px;flex-wrap:nowrap;margin-top:44px;padding-top:28px;border-top:1px solid var(--line)}
.hero .facts>div{flex:1 1 0;min-width:0}
.hero .facts div{font-family:var(--mono);font-size:11px;color:var(--slate);letter-spacing:.03em}
.hero .facts b{display:block;font-family:var(--display);font-size:clamp(14px,2.4vw,22px);color:var(--heading);font-weight:600;letter-spacing:-.01em;margin-bottom:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fiber-art{position:relative;width:100%;max-width:580px;justify-self:end;transition:transform .25s cubic-bezier(.22,1,.36,1)}
.fiber-art svg{width:100%;height:100%}
.fiber-art .sheath use{fill:none;stroke:#E6EDF7;stroke-width:12;stroke-linecap:round}
.fiber-art .core use{fill:none;stroke:var(--navy);stroke-width:1.8;opacity:.45}
.fiber-art .pulse{fill:none;stroke:var(--signal);stroke-width:4;stroke-linecap:round;stroke-dasharray:70 1400;stroke-dashoffset:1470;filter:drop-shadow(0 0 6px rgba(6,182,212,.9));animation:travel 4.2s linear infinite}
.fiber-art .pulse.p2{animation-delay:-1.4s;animation-duration:5s}
.fiber-art .pulse.p3{animation-delay:-2.7s;animation-duration:3.6s}
.fiber-art .pulse.p4{animation-delay:-.6s;animation-duration:4.6s}
.fiber-art .pulse.p5{animation-delay:-3.3s;animation-duration:5.4s}
@keyframes travel{to{stroke-dashoffset:0}}
.fiber-art .node circle{fill:#fff;stroke:var(--navy);stroke-width:1.8}
.fiber-art .node-hot{fill:var(--signal);stroke:none;animation:blink 2.4s ease-in-out infinite}
@keyframes blink{0%,100%{opacity:.35}50%{opacity:1}}
.fiber-art .tag{font-family:var(--mono);font-size:11px;fill:var(--slate);letter-spacing:.08em}
.fiber-art .tag.hot{fill:var(--blue)}
.fiber-art .readout{position:absolute;right:0;bottom:-4px;background:#fff;border:1px solid var(--line);border-radius:12px;padding:14px 16px;font-family:var(--mono);font-size:12px;color:var(--slate);box-shadow:0 10px 30px rgba(11,42,91,.08);min-width:200px}
.fiber-art .readout b{display:block;color:var(--heading);font-size:15px;font-weight:500;margin-top:4px}
.fiber-art .readout i{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--signal);margin-right:8px;animation:blink 1.6s infinite}

/* signal rule between sections */
.signal-rule{height:2px;background:var(--line);position:relative;overflow:hidden}
.signal-rule::after{content:"";position:absolute;top:0;left:-20%;width:20%;height:100%;background:linear-gradient(90deg,transparent,var(--signal),transparent);animation:sweep 3.2s linear infinite}
@keyframes sweep{to{left:120%}}

/* ============ FIELD / LAB SPLIT ============ */
.split{display:grid;grid-template-columns:1fr auto 1fr;gap:20px;position:relative}
.panel{border-radius:18px;overflow:hidden;position:relative;min-height:420px;display:flex;flex-direction:column;justify-content:flex-end;padding:32px;color:var(--on-dark);background:var(--navy)}
.panel.lab{background:var(--navy-900)}
.panel .ph{position:absolute;inset:0;background:
  radial-gradient(120% 80% at 80% 10%,rgba(6,182,212,.28),transparent 55%),
  repeating-linear-gradient(135deg,rgba(255,255,255,.035) 0 2px,transparent 2px 14px)}
/* Readability scrim. The panel's title/description/tags are white and sit
   ON TOP of the photo, so a bright daylight photo (blue sky, pale ground)
   makes them unreadable. This darkens the photo from the bottom up — hardest
   exactly where the text sits — so ANY photo can be swapped in without the
   copy disappearing. Tune the three alpha values below to taste; higher =
   darker photo and crisper text. It also replaces the old placeholder badge
   from the design prototype, which used content:attr(data-note) and drew an
   EMPTY dashed box on every panel because no page ever sets data-note. */
.panel .ph::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(7,27,61,.20) 0%,rgba(7,27,61,.52) 45%,rgba(7,27,61,.88) 100%)}
.panel .ph img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.panel h3{color:var(--on-dark);font-size:26px;position:relative;margin-bottom:10px}
.panel p{position:relative;color:var(--on-dark-muted);max-width:44ch}
.panel ul{position:relative;list-style:none;margin-top:18px;display:flex;flex-wrap:wrap;gap:8px}
.panel li{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;padding:6px 10px;border:1px solid rgba(255,255,255,.28);border-radius:6px}

/* ============ SERVICES ============ */
.svc-list{display:grid;grid-template-columns:1fr;border-top:1px solid var(--line)}
.svc{position:relative;padding:40px 0;border-bottom:1px solid var(--line);transition:background .2s;scroll-margin-top:130px}
.svc::after{content:"";position:absolute;left:0;bottom:-1px;height:1px;width:0;background:linear-gradient(90deg,var(--signal),transparent);transition:width .8s cubic-bezier(.22,1,.36,1) .15s}
.svc.in::after{width:100%}
.svc:hover{background:linear-gradient(90deg,var(--mist),transparent)}
.svc-info{display:grid;grid-template-columns:90px 1.1fr 1.3fr auto;gap:28px;align-items:start}
.svc-info .code{font-family:var(--mono);font-size:12px;color:var(--blue);letter-spacing:.08em;padding-top:6px}
.svc-info h3{font-size:21px;margin-bottom:6px}
.svc-info .sub{color:var(--slate);font-size:14.5px}
.svc-info .deliver{display:flex;flex-wrap:wrap;gap:8px}
.svc-info .deliver span{font-family:var(--mono);font-size:11.5px;letter-spacing:.05em;padding:6px 10px;background:var(--mist);border:1px solid var(--line);border-radius:6px;color:var(--ink)}
.svc-info .go,.home-svc .go{width:44px;height:44px;border-radius:50%;border:1.5px solid var(--line);display:grid;place-items:center;transition:.2s;background:#fff}
.svc-info .go svg,.home-svc .go svg{width:18px;height:18px;stroke:var(--navy);fill:none;stroke-width:2;transition:transform .2s ease}
.svc:hover .go{background:var(--navy);border-color:var(--navy)}
.svc:hover .go svg{stroke:#fff;transform:translateX(2px)}

/* related-image gallery under each service */
.svc-gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-top:24px}
.svc-img{background:var(--paper);border:1px solid var(--line);border-radius:12px;overflow:hidden;box-shadow:0 6px 18px rgba(11,42,91,.06);transition:box-shadow .2s ease}
.svc-img:hover{box-shadow:0 14px 32px rgba(11,42,91,.12)}
.svc-img .frame{position:relative;aspect-ratio:4/3;overflow:hidden}
.svc-img .frame::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 55%,rgba(11,42,91,.32));opacity:0;transition:opacity .3s ease}
.svc-img:hover .frame::after{opacity:1}
.svc-img img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .35s ease}
.svc-img:hover img{transform:scale(1.045)}
.svc-img figcaption{padding:9px 12px;font-size:12px;color:var(--slate);border-top:1px solid var(--line)}
.svc-gallery-empty{margin-top:24px;padding:20px;text-align:center;color:var(--slate);font-size:13.5px;border:1px dashed var(--line);border-radius:10px;background:var(--mist)}

/* ============ PROCESS ============ */
.process{display:grid;grid-template-columns:repeat(4,1fr);gap:0;position:relative;counter-reset:step}
.process::before{content:"";position:absolute;left:0;right:0;top:22px;height:2px;background:var(--line)}
.step{padding:0 20px 0 0;position:relative;counter-increment:step}
.step::before{content:counter(step,decimal-leading-zero);display:grid;place-items:center;width:46px;height:46px;border-radius:50%;background:#fff;border:2px solid var(--navy);font-family:var(--mono);font-size:13px;color:var(--heading);position:relative;margin-bottom:18px}
.step h4{font-size:17px;margin-bottom:6px}
.step p{color:var(--slate);font-size:14.5px}

/* ============ PRODUCTS ============ */
.filters{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:28px}
.chip{border:1.5px solid var(--line);background:#fff;border-radius:999px;padding:8px 16px;font-size:14px;font-weight:500;color:var(--ink)}
.chip[aria-pressed="true"]{background:var(--navy);color:#fff;border-color:var(--navy)}
.prod-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.prod{background:#fff;border:1px solid var(--line);border-radius:var(--r);overflow:hidden;display:flex;flex-direction:column;transition:.2s}
.prod[hidden]{display:none}
.prod:hover{border-color:var(--blue);box-shadow:0 16px 40px rgba(11,42,91,.08);transform:translateY(-4px)}
.prod .img{aspect-ratio:4/3;background:linear-gradient(160deg,var(--mist),#E6EDF7);position:relative;display:grid;place-items:center;overflow:hidden}
.prod .img svg{width:42%;height:42%;stroke:var(--navy);fill:none;stroke-width:1.2;opacity:.75}
.prod .img img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .45s cubic-bezier(.22,1,.36,1)}
.prod:hover .img img{transform:scale(1.035)}
.prod .img::after{content:"Product photo";position:absolute;bottom:10px;right:12px;font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;color:var(--slate);text-transform:uppercase}
.prod .img.has-photo::after{content:none}
.prod .body{padding:20px 22px 22px;display:flex;flex-direction:column;gap:10px;flex:1}
.prod .cat{font-family:var(--mono);font-size:11px;letter-spacing:.1em;color:var(--blue);text-transform:uppercase}
.prod h3{font-size:18px}
.prod .spec{font-family:var(--mono);font-size:12px;color:var(--slate);display:grid;grid-template-columns:1fr auto;gap:4px 12px;border-top:1px dashed var(--line);padding-top:12px;margin-top:4px}
.prod .spec b{font-weight:500;color:var(--ink)}
.prod .foot{margin-top:auto;display:flex;justify-content:space-between;align-items:center;padding-top:8px}
.prod .foot a{font-weight:600;font-size:14px;margin-left:auto;display:inline-block;transition:transform .2s ease}
.prod .foot a:hover{transform:translateX(3px)}

/* ============ NEWS & ANNOUNCEMENTS ============ */
.news-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.news-card{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:26px;transition:border-color .2s,transform .2s,box-shadow .2s}
.news-card:hover{border-color:var(--blue);transform:translateY(-3px);box-shadow:0 16px 40px rgba(11,42,91,.08)}
.news-meta{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:14px}
.news-tag{background:var(--signal-soft);color:var(--blue);padding:5px 10px;border-radius:999px;font-size:11px;transition:background .25s ease,color .25s ease}
.news-card:hover .news-tag{background:var(--blue);color:#fff}
.news-date{color:var(--slate)}
.news-card h3{font-size:17px;margin-bottom:8px}
.news-card p{color:var(--slate);font-size:14.5px;line-height:1.55}
.news-card .news-image-frame{width:100%;aspect-ratio:16/9;border-radius:10px;overflow:hidden;margin-bottom:16px;background:var(--mist)}
.news-card .news-image{width:100%;height:100%;object-fit:cover;display:block;transition:transform .5s cubic-bezier(.22,1,.36,1)}
.news-card:hover .news-image{transform:scale(1.04)}
.news-card .news-link{display:inline-flex;align-items:center;gap:6px;margin-top:14px;font-weight:600;font-size:13.5px;color:var(--heading)}
.news-card .news-link:hover{color:var(--blue)}
.news-card .news-link svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2.2;transition:transform .2s ease}
.news-card:hover .news-link svg{transform:translateX(3px)}
.news-empty{grid-column:1/-1;padding:32px;text-align:center;color:var(--slate);font-size:14.5px;border:1px dashed var(--line);border-radius:var(--r);background:var(--mist)}

/* ============ PROOF ============ */
.proof{display:grid;grid-template-columns:1fr 1fr;gap:clamp(32px,5vw,72px);align-items:center}
.proof-list{display:grid;gap:0;border-top:1px solid var(--line)}
.proof-list div{position:relative;display:grid;grid-template-columns:120px 1fr;gap:20px;padding:22px 0;border-bottom:1px solid var(--line)}
.proof-list b{font-family:var(--display);font-size:26px;font-weight:600;color:var(--heading);letter-spacing:-.02em}
.proof-list p{color:var(--slate);font-size:15px}

/* ============ CTA ============ */
.cta{background:var(--navy);color:var(--on-dark);border-radius:22px;padding:clamp(36px,5vw,64px);display:grid;grid-template-columns:1.2fr .8fr;gap:32px;align-items:center;position:relative;overflow:hidden}
.cta::before{content:"";position:absolute;inset:0;z-index:0;background:
  radial-gradient(60% 120% at 100% 0%,rgba(6,182,212,.22),transparent 60%),
  linear-gradient(rgba(255,255,255,.05) 1px,transparent 1px),
  linear-gradient(90deg,rgba(255,255,255,.05) 1px,transparent 1px);
  background-size:auto,44px 44px,44px 44px}
.cta::after{content:"";position:absolute;z-index:0;width:6px;height:6px;border-radius:50%;background:var(--signal);top:20%;left:-3%;box-shadow:0 0 12px 2px rgba(6,182,212,.7);pointer-events:none;animation:ctaTravel 7s linear infinite}
@keyframes ctaTravel{0%{left:-3%;top:22%;opacity:0}8%{opacity:1}50%{left:50%;top:72%}92%{opacity:1}100%{left:103%;top:18%;opacity:0}}
.cta h2{color:var(--on-dark);position:relative;z-index:1}
.cta p{color:var(--on-dark-muted);position:relative;z-index:1;margin-top:10px}
.cta .actions{position:relative;z-index:1;display:flex;gap:12px;flex-wrap:wrap;justify-content:flex-end}
.cta .btn-ghost{color:var(--on-dark);border-color:rgba(255,255,255,.35)}
.cta .btn-ghost:hover{background:transparent;border-color:var(--on-dark)}

/* ============ ABOUT ============ */
.about-hero{display:grid;grid-template-columns:1fr 1fr;gap:clamp(32px,5vw,72px);align-items:end}
/* The HQ photo is shown WHOLE — no crop. It used to sit in a fixed 360px
   frame with object-fit:cover, which filled the frame by cutting the top and
   bottom off the building. The frame now takes its height from the photo
   itself, so the full image is visible with no letterbox bars either. The
   img keeps its width/height attributes, so the browser still reserves the
   right space before it loads and there is no layout shift. */
.about-hero .photo{border-radius:18px;background:var(--navy);position:relative;overflow:hidden}
.about-hero .photo .ph{position:relative;background:radial-gradient(100% 70% at 20% 90%,rgba(6,182,212,.3),transparent 55%),repeating-linear-gradient(45deg,rgba(255,255,255,.035) 0 2px,transparent 2px 14px)}
/* Same leftover placeholder badge as .panel .ph::after had — removed. No
   scrim needed here: this photo carries no text on top of it. */
.about-hero .photo .ph img{position:static;display:block;width:100%;height:auto}
.values{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.value{padding:28px;border-radius:var(--r);background:#fff;border:1px solid var(--line);transition:border-color .2s,transform .2s,box-shadow .2s}
.value:hover{border-color:var(--blue);transform:translateY(-3px);box-shadow:0 16px 40px rgba(11,42,91,.08)}
.value .num{display:block;font-family:var(--mono);font-size:12px;color:var(--signal);letter-spacing:.08em;margin-bottom:12px}
.value h3{margin-bottom:8px}
.value p{color:var(--slate);font-size:15px}
.timeline{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.tl{padding:26px;border-radius:var(--r);border:1px solid var(--line);background:#fff}
.tl .y{font-family:var(--mono);color:var(--blue);font-size:12.5px;letter-spacing:.08em}
.tl h4{margin:8px 0 6px;font-size:18px}
.tl p{color:var(--slate);font-size:14.5px}

/* ============ CONTACT ============ */
.contact{display:grid;grid-template-columns:1fr 1.1fr;gap:clamp(32px,5vw,72px)}
.info-card{border:1px solid var(--line);border-radius:var(--r);padding:26px;margin-bottom:16px;background:#fff}
.info-card .mono{display:block;margin-bottom:8px}
.info-card p,.info-card a{font-size:15.5px;line-height:1.55}
.info-card a{color:var(--heading);font-weight:600;transition:transform .2s ease;display:inline-block}
.info-card a:hover{transform:translateX(3px)}
.hours{display:grid;grid-template-columns:1fr auto;gap:6px 20px;font-size:15px}
.hours span:nth-child(even){font-family:var(--mono);font-size:13px;color:var(--slate)}
.form{background:#fff;border:1px solid var(--line);border-radius:18px;padding:clamp(24px,3vw,36px)}
.form h3{margin-bottom:6px}
.form>p{color:var(--slate);font-size:14.5px;margin-bottom:24px}
.field{display:grid;gap:6px;margin-bottom:16px}
.field label{font-size:13.5px;font-weight:600;color:var(--heading)}
.field input,.field select,.field textarea{font:inherit;padding:12px 14px;border:1.5px solid var(--line);border-radius:10px;background:#fff;color:var(--ink);transition:border-color .2s;width:100%}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--blue);outline:none;box-shadow:0 0 0 3px rgba(37,99,235,.12)}
/* Phase 19 accessibility fix. The rule above sets outline:none on plain
   :focus, which also suppressed the site's global 3px cyan :focus-visible
   ring for every form control — leaving keyboard users with only a 12%-alpha
   blue glow at roughly 1.1:1 contrast, far below the 3:1 a focus indicator
   needs. The soft glow is kept for POINTER focus (it is part of the design),
   and the strong ring is restored for KEYBOARD focus only. Must stay after
   the :focus rule: both selectors have equal specificity, so order decides.
   Blue (#2563EB) is used for the ring rather than the site's cyan: form
   fields always sit on white, where cyan measures only 2.4:1 and would
   still fail the 3:1 minimum for a focus indicator. Blue measures 5.2:1.
   A cyan halo is kept behind it so the brand accent is still present.
   Affects the Contact/quote form and, via the @import in admin/css/admin.css,
   every admin form too. */
.field input:focus-visible,.field select:focus-visible,.field textarea:focus-visible{outline:3px solid var(--blue);outline-offset:2px;box-shadow:0 0 0 3px rgba(6,182,212,.35);border-color:var(--blue)}
.field.has-error input,.field.has-error select,.field.has-error textarea{border-color:#D92D20}
.field .err{font-size:13px;color:#D92D20;display:none}
/* Replaces the removed attachment picker (Phase 19). Styled as a quiet
   instruction, not as a control, so nothing suggests an upload happens. */
.attach-note{font-size:13px;color:var(--slate);line-height:1.6;margin:0}
.attach-note a{color:var(--blue);font-weight:600}
.field.has-error .err{display:block}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.upload{border:1.5px dashed var(--line);border-radius:10px;padding:18px;text-align:center;color:var(--slate);font-size:14px}
.upload b{color:var(--blue)}
.upload input[type=file]{display:block;margin-top:10px;width:100%;font-size:13px}
.form-error{display:none;background:#FEF3F2;border:1px solid #FDA29B;color:#B42318;border-radius:10px;padding:12px 16px;font-size:14px;margin-bottom:16px}
.form-error.show{display:block}
.toast{display:none;background:#ECFDF3;border:1px solid #6CE9A6;color:#067647;border-radius:10px;padding:12px 16px;font-size:14px;margin-bottom:16px}
.toast.show{display:block}
.map{margin-top:16px;border-radius:var(--r);border:1px solid var(--line);height:220px;background:var(--mist);position:relative;overflow:hidden}
.map iframe{position:absolute;inset:0;width:100%;height:100%;border:0}

/* ============ QUOTE SUCCESS PANEL (Phase 18) ============ */
.quote-success{text-align:center;padding:24px 0}
.quote-success-icon{width:56px;height:56px;border-radius:50%;background:var(--signal-soft);display:grid;place-items:center;margin:0 auto 18px}
.quote-success-icon svg{width:26px;height:26px;stroke:var(--blue)}
.quote-success h3{margin-bottom:10px}
.quote-success p{color:var(--slate);font-size:15px;max-width:44ch;margin:0 auto 6px}
.quote-success-id{font-size:12.5px;margin-top:8px}
.quote-success .actions{display:flex;gap:10px;flex-wrap:wrap;justify-content:center;margin-top:24px}
.quote-success-track{margin-top:10px;font-size:13px}

/* ============ QUOTE TRACKING (Phase 18B) ============ */
.badge-status-lg{display:inline-block;font-family:var(--mono);font-size:13px;padding:6px 14px;border-radius:999px;letter-spacing:.04em}
.badge-status-lg.status-new{background:var(--signal-soft);color:var(--blue)}
.badge-status-lg.status-contacted{background:#FEF3C7;color:#92400E}
.badge-status-lg.status-quoted{background:#E0F7FA;color:#0E7490}
.badge-status-lg.status-approved{background:#ECFDF3;color:#067647}
.badge-status-lg.status-rejected{background:#FEF3F2;color:#B42318}
.badge-status-lg.status-completed{background:#ECFDF3;color:#067647}
.badge-status-lg.status-cancelled{background:#F3F4F6;color:#6B7280}
.quote-track{padding:8px 0}
.quote-track h3{margin:14px 0 6px}
.quote-track-meta{color:var(--slate);font-size:13.5px;margin-bottom:20px}
.quote-track-section{margin-bottom:20px}
.quote-track-section h4{font-size:12.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--slate);font-family:var(--mono);font-weight:500;margin-bottom:10px}
.quote-track-row{display:grid;grid-template-columns:140px 1fr;gap:10px;padding:7px 0;font-size:14.5px;border-bottom:1px solid var(--line)}
.quote-track-row:last-child{border-bottom:none}
.quote-track-row b{color:var(--slate);font-weight:500}
.quote-track-row span{word-break:break-word}
.quote-track-message{background:var(--mist);border:1px solid var(--line);border-radius:9px;padding:14px;font-size:14.5px;white-space:pre-wrap;word-break:break-word}
.quote-track .actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:24px}
.quote-track-error{text-align:center;padding:24px 0}
.quote-track-error p{color:var(--slate);margin:10px 0 20px}

/* pinned Accepted/Rejected badge — fixed to the viewport so it stays
   visible regardless of scroll position */
.quote-status-pin{position:fixed;top:16px;right:16px;z-index:60;background:#fff;border:1px solid var(--line);border-radius:999px;padding:6px;box-shadow:0 10px 30px rgba(11,42,91,.14)}
.quote-status-pin .badge-status-lg{font-size:13px}
@media (max-width:480px){
  .quote-status-pin{top:auto;bottom:16px;right:16px;left:16px;border-radius:var(--r);text-align:center}
}

.file-list{list-style:none;margin-top:10px;display:flex;flex-direction:column;gap:6px}
.file-list li{display:flex;align-items:center;justify-content:space-between;gap:10px;background:var(--mist);border:1px solid var(--line);border-radius:8px;padding:8px 10px;font-size:13px;color:var(--ink)}
.file-list .fname{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.file-list button{background:none;border:0;color:var(--slate);font-size:16px;line-height:1;padding:2px 4px;border-radius:4px}
.file-list button:hover{color:#D92D20;background:#FEF3F2}

/* ============ FOOTER ============ */
footer{background:var(--navy);color:var(--on-dark-muted);padding:56px 0 28px;margin-top:0}
footer .grid{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:32px;padding-bottom:36px;border-bottom:1px solid rgba(255,255,255,.12)}
footer h4{color:var(--on-dark);font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--mono);font-weight:500;margin-bottom:14px}
footer ul{list-style:none}
footer li{margin-bottom:8px;font-size:14.5px}
footer li a,footer .brand{color:var(--on-dark)}
footer li a{color:var(--on-dark-muted);position:relative;display:inline-block;transition:color .2s}
footer li a::after{content:"";position:absolute;left:0;right:100%;bottom:-3px;height:1px;background:#fff;transition:right .25s ease}
footer li a:hover{color:var(--on-dark)}
footer li a:hover::after{right:0}
footer .brand small{color:#8FA3C7}
footer p.small{font-size:14px;max-width:38ch;margin-top:14px;line-height:1.6}
footer .bottom{display:flex;justify-content:space-between;flex-wrap:wrap;gap:12px;padding-top:22px;font-family:var(--mono);font-size:12px;color:#8FA3C7}

/* ============ SKIP LINK ============ */
.skip-link{position:absolute;left:-999px;top:0;background:var(--navy);color:#fff;padding:12px 18px;border-radius:0 0 8px 0;z-index:100;font-family:var(--mono);font-size:13px}
.skip-link:focus{left:0}

/* ============ REVEAL ============ */
.rv{opacity:0;transform:translateY(16px);transition:opacity .6s cubic-bezier(.22,1,.36,1),transform .6s cubic-bezier(.22,1,.36,1)}
.rv.in{opacity:1;transform:none}

/* =========================================================
   PHASE 14 — PREMIUM TECHNOLOGY MOTION SYSTEM
   ========================================================= */

/* subtle whole-page fade-in on load — a self-completing CSS animation
   (not a JS-toggled class), so a JS failure never leaves the page hidden */
body{animation:pdFadeIn .4s ease}
@keyframes pdFadeIn{from{opacity:0}to{opacity:1}}

/* reusable motion utilities beyond the existing .rv (reveal-up) */
.scale-in{opacity:0;transform:scale(.96);transition:opacity .6s cubic-bezier(.22,1,.36,1),transform .6s cubic-bezier(.22,1,.36,1)}
.scale-in.in{opacity:1;transform:none}
.motion-delay-1{transition-delay:.1s}
.motion-delay-2{transition-delay:.2s}
.motion-delay-3{transition-delay:.3s}

/* light stagger for grid/list reveals — capped at ~180ms, repeats every 4 items */
.home-svc-list .rv:nth-child(4n+2),.prod-grid .rv:nth-child(4n+2),.news-grid .rv:nth-child(4n+2),.values .rv:nth-child(4n+2),.timeline .rv:nth-child(4n+2){transition-delay:.06s}
.home-svc-list .rv:nth-child(4n+3),.prod-grid .rv:nth-child(4n+3),.news-grid .rv:nth-child(4n+3),.values .rv:nth-child(4n+3),.timeline .rv:nth-child(4n+3){transition-delay:.12s}
.home-svc-list .rv:nth-child(4n),.prod-grid .rv:nth-child(4n),.news-grid .rv:nth-child(4n),.values .rv:nth-child(4n),.timeline .rv:nth-child(4n){transition-delay:.18s}

/* engineering grid layer behind the Home hero — very low opacity, fades out
   toward the edges so it never competes with the fiber diagram or text */
.hero::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:
    linear-gradient(rgba(37,99,235,.07) 1px,transparent 1px),
    linear-gradient(90deg,rgba(37,99,235,.07) 1px,transparent 1px);
  background-size:56px 56px;
  -webkit-mask-image:radial-gradient(120% 100% at 50% 0%,#000 40%,transparent 85%);
  mask-image:radial-gradient(120% 100% at 50% 0%,#000 40%,transparent 85%);
}

@media (prefers-reduced-motion:reduce){
  body{animation:none}
  .scale-in{opacity:1;transform:none}
  .fiber-art{transition:none!important}
  header.site{transition:none!important}
}

/* =========================================================
   PHASE 15 — HOME PAGE PREMIUM REDESIGN
   ========================================================= */

/* hero: a touch more headline dominance + a divider between trust facts */
.hero h1{font-size:clamp(40px,5.6vw,74px);letter-spacing:-.025em}
.hero .facts > div + div{padding-left:20px;border-left:1px solid var(--line)}

/* capability strip — thin technical bar between hero and services preview */
.cap-strip{background:#fff;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.cap-strip .wrap{display:flex;align-items:center;gap:clamp(20px,4vw,48px);flex-wrap:wrap;padding:18px 0}
.cap-strip-label{color:var(--heading);white-space:nowrap;font-weight:600}
.cap-strip-items{display:flex;flex-wrap:wrap;gap:clamp(18px,3vw,40px);flex:1}
.cap-strip-items span{font-family:var(--mono);font-size:12px;letter-spacing:.05em;color:var(--slate);position:relative;padding-left:16px}
.cap-strip-items span::before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);width:6px;height:6px;border-radius:50%;background:var(--signal)}

/* home services preview — numbered editorial rows */
.home-svc-list{display:grid;border-top:1px solid var(--line)}
.home-svc{display:grid;grid-template-columns:64px 1fr auto;gap:24px;align-items:center;padding:26px 4px;border-bottom:1px solid var(--line);transition:background .2s}
.home-svc:hover{background:linear-gradient(90deg,var(--mist),transparent)}
.home-svc .num{color:var(--blue);font-size:15px;letter-spacing:.04em;transition:transform .3s cubic-bezier(.22,1,.36,1)}
.home-svc:hover .num{transform:translateX(4px)}
.home-svc .t{display:grid;gap:4px}
.home-svc-title{font-family:var(--display);font-size:19px;font-weight:600;color:var(--heading);letter-spacing:-.01em}
.home-svc-desc{color:var(--slate);font-size:14.5px;max-width:56ch}
.home-svc:hover .go{background:var(--navy);border-color:var(--navy)}
.home-svc:hover .go svg{stroke:#fff;transform:translateX(2px)}

/* field/lab connector — a thin animated line joining the two panels,
   reusing the .signal-rule sweep motif in a vertical orientation */
.split-link{display:flex;align-items:center;justify-content:center;min-height:100%}
.split-link span{width:2px;height:70%;background:var(--line);position:relative;overflow:hidden;display:block}
.split-link span::after{content:"";position:absolute;left:0;top:-20%;width:100%;height:20%;background:linear-gradient(180deg,transparent,var(--signal),transparent);animation:sweepV 3.2s linear infinite}
@keyframes sweepV{to{top:120%}}

/* capability matrix (Why Power Deal) — small numbered index per block */
.proof-list .num{position:absolute;top:22px;right:0;font-family:var(--mono);font-size:12px;color:var(--signal);letter-spacing:.08em}

/* news: first card reads as the featured story on wide layouts */
.news-grid .news-card:first-child{display:grid;grid-template-columns:1.1fr 1fr;gap:24px;align-items:center}
.news-grid .news-card:first-child .news-image-frame{margin-bottom:0;aspect-ratio:4/3}
.news-grid .news-card:first-child h3{font-size:21px}

@media (max-width:1000px){
  .home-svc{grid-template-columns:44px 1fr;gap:6px 16px}
  .home-svc .go{display:none}
  .news-grid .news-card:first-child{grid-template-columns:1fr}
}
@media (max-width:820px){
  .split-link{display:none}
  .cap-strip .wrap{flex-direction:column;align-items:flex-start;gap:12px}
}

/* =========================================================
   PHASE 16 — SITE-WIDE VISUAL & UX POLISH
   ========================================================= */

/* 404 — a faint engineering grid instead of a bare error page */
.notfound{position:relative;overflow:hidden}
.notfound::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:
    linear-gradient(rgba(37,99,235,.06) 1px,transparent 1px),
    linear-gradient(90deg,rgba(37,99,235,.06) 1px,transparent 1px);
  background-size:48px 48px;
  -webkit-mask-image:radial-gradient(80% 90% at 50% 30%,#000 30%,transparent 80%);
  mask-image:radial-gradient(80% 90% at 50% 30%,#000 30%,transparent 80%);
}
.notfound .wrap{position:relative;z-index:1}

/* contact map — a touch more presence so it reads as an integrated panel */
.map{box-shadow:0 10px 30px rgba(11,42,91,.06)}

/* ============ RESPONSIVE ============ */
@media (max-width:1000px){
  .svc-gallery,.prod-grid,.values,.timeline,.news-grid{grid-template-columns:repeat(2,1fr)}
  .process{grid-template-columns:repeat(2,1fr);gap:28px 0}
  .process::before{display:none}
  .svc-info{grid-template-columns:70px 1fr;gap:14px 20px}
  .svc-info .deliver{grid-column:2}
  .svc-info .go{grid-column:2;justify-self:start;margin-top:4px}
  footer .grid{grid-template-columns:1fr 1fr}
}
@media (max-width:820px){
  .hero .wrap,.split,.proof,.cta,.about-hero,.contact{grid-template-columns:1fr}
  .fiber-art{max-width:520px;justify-self:center}
  .fiber-art .readout{position:static;margin:8px auto 0;width:max-content}
  .topbar .hide-sm{display:none}
  .cta .actions{justify-content:flex-start}
  nav.main{display:none;position:absolute;top:74px;left:0;right:0;background:#fff;border-bottom:1px solid var(--line);flex-direction:column;padding:12px var(--gutter) 18px}
  nav.main.open{display:flex}
  nav.main a{text-align:left;padding:14px 8px;font-size:17px}
  .menu-btn{display:grid}
  .header-cta .btn{display:none}
  .topbar .hide-sm{display:none}
}
@media (max-width:560px){
  .svc-gallery,.prod-grid,.values,.timeline,.news-grid,.row2,.process{grid-template-columns:1fr}
  .proof-list div{grid-template-columns:1fr;gap:6px}
  footer .grid{grid-template-columns:1fr}
  .brand small{display:none}
  .brand{gap:8px}
}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
  .rv{opacity:1;transform:none}
}

/* ====================================================================
   PHASE 19B — NARROW-VIEWPORT FIXES (320px / 375px)
   --------------------------------------------------------------------
   These are layout corrections, not a mobile redesign. Nothing here
   applies above 560px, so the approved desktop and tablet design is
   untouched.

   WHY THE BUG WAS INVISIBLE TO AUTOMATED CHECKS: .hero has
   overflow:hidden (it clips the decorative ::before grid). That means
   documentElement.scrollWidth stayed at 320 while the hero's children
   were genuinely 399px wide and simply CLIPPED. Any check based on
   scrollWidth reports a false pass. The real test is comparing each
   element's getBoundingClientRect().right against clientWidth.

   MEASURED ROOT CAUSES at 320px (container content box = 280px):
     1. .hero .facts used flex-wrap:nowrap with three columns. Its
        min-content was 83+134+100 + 40 gaps + 40 padding + 2 borders
        = 399px. A grid item cannot shrink below its min-content, so
        this one rule forced the whole hero track to 399px and every
        sibling (h1, lead, actions, fiber-art) inherited that width.
     2. .hero h1 used clamp(40px,...) so 40px was the floor. The CMS
        heading word 'Communication' is ~300px at 40px and could not
        fit the 280px content box.
     3. .fiber-art .readout had min-width:200px while in normal flow.
     4. Contact page: .form and .info-card are grid items with the
        default min-width:auto. A text input's intrinsic width (~252px)
        plus the form's 48px padding forced that track to 302px.
   ==================================================================== */

/* Let hero and contact grid items shrink below their intrinsic width.
   Grid/flex children default to min-width:auto, which is what let a
   single wide descendant drag the whole track past the viewport. */
.hero .wrap>*,.contact>*,.fiber-art{min-width:0}


/* Form controls carry a browser-default intrinsic width (~20 characters).
   width:100% does not change that, so they must be allowed to shrink. */
.field input,.field select,.field textarea{min-width:0}
.info-card p,.info-card a{overflow-wrap:break-word}

@media (max-width:560px){
  /* ROOT CAUSE 1. Stack the three hero facts and turn the vertical
     dividers into horizontal ones, keeping the same visual language.
     min-content drops from 399px to the widest single word. */
  .hero .facts{display:grid;grid-template-columns:1fr;gap:0;flex-wrap:wrap;margin-top:28px;padding-top:20px}
  .hero .facts>div+div{padding-left:0;border-left:0;padding-top:14px;margin-top:14px;border-top:1px solid var(--line)}
  /* The nowrap+ellipsis on these values was part of the 399px figure. */
  .hero .facts b{white-space:normal;overflow:visible;text-overflow:clip}

  /* ROOT CAUSE 2. Lower the heading floor for narrow screens only. At
     560px this resolves to 40px, exactly where the desktop rule also
     lands, so the two meet with no visible step. */
  .hero h1{font-size:clamp(28px,8.2vw,40px)}

  /* Safety net for a CMS word longer than the whole column. Scoped to
     narrow screens deliberately: above 560px there is room for the design
     to breathe, and forcing a mid-word break there would alter the
     approved desktop appearance for no safety benefit.
     NOTE: the current CMS heading contains the word 'Communication',
     which measures 616px at the desktop 74px size while the hero text
     column is 542px. That word overflows its column at 1440px. It is a
     content-length issue, not a CSS one, and is left exactly as it was. */
  .hero h1,.section-head h2,.cta h2,.notfound h1{overflow-wrap:break-word}

  /* ROOT CAUSE 3. */
  .fiber-art .readout{min-width:0;max-width:100%;width:auto}

  /* Hero CTAs: stack full-width rather than letting the second button
     hang outside the viewport. */
  .hero .actions{flex-direction:column;align-items:stretch;gap:10px;margin-top:24px}
  .hero .actions .btn{width:100%;justify-content:center}

  /* Top bar: allow the two groups to wrap instead of being forced onto
     one 36px line. Height becomes auto so a wrap cannot clip. */
  .topbar .wrap{flex-wrap:wrap;gap:2px 10px;height:auto;min-height:36px;padding-top:6px;padding-bottom:6px}
  .topbar{font-size:11px}
}

/* Below ~360px the gutter is the last thing worth reclaiming. */
@media (max-width:360px){
  :root{--gutter:16px}
}
