/* Optimus Distributor — shared chrome + design vocabulary (Phase 2).
   Base elements, promo bar, header/nav, footer, buttons, kickers, pills, cards, reveals.
   Lifted from designs/4-flagship with the deltas recorded in DESIGN-SYSTEM.md §2. */

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{background:var(--bg);color:var(--ink);font:400 16px/1.65 var(--body);-webkit-font-smoothing:antialiased;overflow-x:clip}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
ul{list-style:none}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 var(--pad)}
:focus-visible{outline:2px solid var(--cyan2);outline-offset:3px;border-radius:4px}
::selection{background:rgba(41,170,227,.35)}

/* The ramp was h1 50px / .final h2 44px / .shead h2 38px at 1440 -- a 12px band, so the
   hero was only 1.32x the section head and the CLOSING CTA came within 6px of the h1.
   No page had a top. Opening h1 to 72px puts the ratio at 1.89 against an unchanged
   .shead h2. Tracking tightens as the size grows: -.015em is too loose at 72px.
   (2026-08-21 design review, finding A-D4.) */
h1{font:600 clamp(30px,5vw,72px)/1.06 var(--disp);letter-spacing:-.025em;
   text-wrap:balance}
/* .hl was a 34px blur at 45% -- a neon bloom on 50px type, and the loudest consumer
   dark-SaaS gesture on a site selling valves to EPCC specifiers. (A-D7) */
h1 .hl{color:var(--cyan2);text-shadow:0 0 18px rgba(76,196,255,.26)}
main p a{color:var(--cyan2);text-decoration:underline;text-underline-offset:3px;text-decoration-color:rgba(76,196,255,.4)}
main p a:hover{text-decoration-color:var(--cyan2)}

/* ---------- promo bar ---------- */
.promo{background:linear-gradient(90deg,#0E2A4A,#123A66 50%,#0E2A4A);border-bottom:1px solid var(--line);font-size:13.5px;color:#C9DCF0}
.promo .wrap{display:flex;align-items:center;justify-content:center;gap:var(--g2);min-height:40px;position:relative;padding-right:56px}
.promo b{color:#fff;font-weight:600}
.promo a{color:var(--cyan2);font-weight:500;white-space:nowrap}
.promo a:hover{text-decoration:underline}
.promo button{position:absolute;right:18px;top:50%;transform:translateY(-50%);background:none;border:0;color:#89A5C4;font-size:18px;line-height:1;cursor:pointer;padding:6px}
.promo button:hover{color:#fff}
.promo button{min-width:24px;min-height:24px}
.promo .pshort{display:none}
@media (max-width:700px){
  .promo .plong{display:none}
  .promo .pshort{display:inline}
  /* Stack, do not shrink. As a flex ROW the nowrap link forced the sentence into a
     ~150px column that wrapped to three lines AROUND it, so a phone reader parsed
     "send the WhatsApp +6019 750 3980 -> spec." Shortening the copy could never fix
     that -- the cause was the axis, not the length. (round 3, B R-5 / C-2 / A F6) */
  .promo .wrap{flex-direction:column;align-items:flex-start;gap:2px;font-size:12.5px;
               padding-right:44px;padding-block:8px;min-height:0}
}

/* ---------- header ---------- */
header{position:sticky;top:0;z-index:80;background:rgba(6,13,26,.82);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border-bottom:1px solid var(--line)}
.nav{display:flex;align-items:center;gap:var(--g3);height:74px}
.logo{display:flex;align-items:center;gap:var(--g1);flex-shrink:0}
.logo img{width:40px;height:40px;object-fit:contain}
.logo b{font:600 15px/1.2 var(--disp);letter-spacing:.02em}
.logo b span{display:block;font:500 12px/1.4 var(--mono);letter-spacing:.24em;color:var(--cyan);text-transform:uppercase}
/* Real site search (2026-08-21). It used to be a link dressed as a search field, which
   promised typing and delivered navigation. Now it is a form: no JS -> Enter goes to
   /products.html; with JS -> a filtered dropdown over search-index.json. */
.search{position:relative;flex:1 1 0;min-width:0;max-width:360px;margin:0;display:flex;align-items:center;gap:var(--g2);background:rgba(18,32,58,.6);border:1px solid var(--line);border-radius:999px;padding:12px 16px;color:var(--mut2);font-size:13.5px;transition:border-color .2s}
.search input{flex:1 1 auto;width:100%;min-width:0;background:none;border:0;outline:none;padding:0;color:var(--ink);font:inherit;font-size:13.5px}
.search input::placeholder{color:var(--mut2)}
.search input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}
.sres{position:absolute;top:calc(100% + 10px);left:0;right:0;max-height:62vh;overflow-y:auto;overflow-x:hidden;background:#0B1730;border:1px solid var(--line2);border-radius:var(--rad-s);box-shadow:0 30px 60px -20px rgba(0,0,0,.85);z-index:60;padding:6px;scrollbar-width:thin}
.sres a{display:block;padding:9px 12px;border-radius:8px}
.sres a:hover,.sres a.on{background:rgba(41,170,227,.14)}
.sres b{display:block;font:600 13.5px/1.35 var(--disp);color:var(--ink)}
.sres i{display:block;font:500 12px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--cyan);font-style:normal;margin-top:4px}
.sres p{margin:4px 0 0;font-size:12.5px;line-height:1.5;color:var(--mut)}
.sres .none{padding:12px;font-size:12.5px;color:var(--mut)}
.search:hover,.search:focus-within{border-color:var(--cyan);color:var(--mut)}
.search svg{flex-shrink:0}
.navlinks{display:flex;align-items:center;gap:var(--g3);margin-left:auto}
.navlinks a{font:500 13.5px var(--disp);letter-spacing:.03em;color:var(--mut);transition:color .2s;position:relative;padding:6px 0}
.navlinks a:hover{color:#fff}
.navlinks a::after{content:"";position:absolute;left:0;right:100%;bottom:0;height:2px;background:var(--cyan);transition:right .25s cubic-bezier(.22,.61,.36,1)}
.navlinks a:hover::after{right:0}
.navlinks a[aria-current="page"]{color:#fff}
.navlinks a[aria-current="page"]::after{right:0}
.cta{display:inline-flex;align-items:center;gap:var(--g1);background-color:#29AAE3;background-image:linear-gradient(135deg,var(--cyan),var(--blue));color:#04121F;font:600 13.5px var(--disp);letter-spacing:.03em;padding:12px 22px;border-radius:999px;box-shadow:0 0 0 1px rgba(76,196,255,.25),0 8px 24px -12px rgba(41,170,227,.55);transition:transform .22s cubic-bezier(.22,.61,.36,1),box-shadow .22s}
.cta:hover{transform:translateY(-2px);box-shadow:0 0 0 1px rgba(76,196,255,.4),0 14px 30px -10px rgba(41,170,227,.7)}
.btn2{display:inline-flex;align-items:center;gap:var(--g1);border:1px solid var(--line2);color:var(--ink);font:600 13.5px var(--disp);letter-spacing:.03em;padding:12px 24px;border-radius:999px;transition:border-color .2s,background .2s,transform .22s}
.btn2:hover{border-color:var(--cyan);background:rgba(41,170,227,.08);transform:translateY(-2px)}
.burger{display:none;flex:none;margin-left:auto;background:none;border:1px solid var(--line2);border-radius:12px;width:44px;height:44px;color:var(--ink);cursor:pointer;font-size:18px}
.mnav{display:none}
/* Below 1120 the search used to be DELETED, and below 1020 the CTA with it -- so at 768
   the header was a logo, a burger, and ~600px of nothing, carrying less than at 390 for
   the same height. 768 is a real buying context (an engineer on a tablet), and the two
   things removed were the site's only search and its primary conversion action.
   Now: the field keeps the freed track down to 640, and the CTA survives to 640 too.
   (2026-08-21 design review, findings B-D3 / C-D3.) */
/* Hand over to the magnifier at 840, not 640. Between 641 and 768 the field was crushed
   by the CTA and the burger -- 152px at 768, 84px at 700, a 25px sliver at 641 -- because
   flex:1 1 0 with min-width:0 lets it shrink to nothing. A floor stops it rendering
   crushed at any width it is visible. (round 4, C F-2) */
@media (max-width:1120px) and (min-width:901px){.search{max-width:360px;flex:1 1 0;min-width:210px}}
@media (max-width:900px){.search{display:none}}
@media (max-width:1120px){
  .navlinks{display:none}
  .burger{display:block;margin-left:0}
  .nav .cta{padding:11px 18px;margin-left:auto;margin-right:12px}
  /* The panel used to be position:fixed at a hardcoded inset of 114px = 40 (promo) + 74
     (nav). Both terms were wrong in practice: the promo bar wraps to two lines at 768 and
     390, and dismissing it removes 40px entirely -- leaving a band of page content showing
     through between the header and the menu. Anchoring to the header removes the
     arithmetic. (B-D10) */
  .mnav.open{display:block;position:absolute;top:100%;left:0;right:0;background:#0A1628;border-bottom:1px solid var(--line2);z-index:79;box-shadow:0 30px 60px -20px rgba(0,0,0,.7)}
  .mnav ul{padding:10px 24px 22px}
  .mnav a{display:block;padding:13px 4px;font:500 16px var(--disp);border-bottom:1px solid var(--line)}
  .mnav .cta{display:inline-flex;margin-top:16px}
  /* the search moves into the menu at the width it leaves the header */
  .mnav .search{display:flex;max-width:none;margin:14px 0 4px}
}
@media (max-width:700px){.nav .cta{display:none}}

/* ---------- mobile action bar ----------
   On a phone the header carried a logo and a burger and nothing else: the search was
   display:none below 1120 and the CTA below 1020, so the two things a site engineer
   standing next to a valve actually needs were the only two removed. Tap-to-call should
   be MORE prominent on mobile, not absent. Existing hrefs, no new claim, ~58px of chrome.
   (2026-08-21 design review, findings C-D3 / C-D8.) */
.actionbar{display:none}
@media (max-width:900px){
  .actionbar{display:grid;grid-template-columns:repeat(3,1fr);position:fixed;left:0;right:0;bottom:0;z-index:78;
    background:rgba(8,17,33,.94);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
    border-top:1px solid var(--line2);padding-bottom:env(safe-area-inset-bottom)}
  .actionbar a{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--g1);
    padding:10px 6px 11px;min-height:56px;font:500 12px var(--mono);letter-spacing:.12em;
    text-transform:uppercase;color:var(--mut)}
  .actionbar a+a{border-left:1px solid var(--line)}
  .actionbar a:hover,.actionbar a:focus-visible{color:#fff;background:rgba(41,170,227,.10)}
  .actionbar svg{width:19px;height:19px;stroke-width:1.9}
  .actionbar .wa{color:var(--cyan2)}
  /* The bar is --actionbar-h PLUS the home-indicator inset, so a flat number left the last
     of the content under it on any device with a gesture bar. (round 3, B F-8)
     ONE token drives both the bar and the padding, because they had drifted apart: the
     padding said 58px and the bar measured 64px, so six pixels of every page stayed under
     it -- which is what the live render gate saw as the sticky chip rail "covered" at 768.
     Two numbers that must agree should never be written twice. */
  :root{--actionbar-h:64px}
  .actionbar{min-height:var(--actionbar-h)}
  body{padding-bottom:calc(var(--actionbar-h) + env(safe-area-inset-bottom))}
}

/* ---------- the deep band ----------
   Tone alone cannot separate bands on a near-black ground. Measured: --bg-deep is 1.038:1
   from --bg -- LESS separation than the --bg/--bg2 pair it was added to fix (1.054:1), and
   well under the ~1.2:1 a large flat field needs before it reads as a plane. Lifting --bg2
   is not available either: it would pass --panel (#0C1830) and the cards sitting on it
   would stop reading as cards.

   So the deep tier gets a SECOND channel instead of a bigger tonal step -- a lit top edge
   and a glow anchored to the band head. The eye reads both as depth regardless of how small
   the tonal difference is. (round 3, B F-2.) */
.band-deep{position:relative;background:var(--bg-deep);
  box-shadow:inset 0 1px 0 rgba(96,168,232,.13)}
.band-deep::before{content:"";position:absolute;inset:0 0 auto;height:340px;pointer-events:none;
  background:radial-gradient(1000px 320px at 50% 0%,rgba(29,130,198,.11),transparent 72%)}
.band-deep>*{position:relative}

/* ---------- credential badges ----------
   OWNED HERE. This was defined in home.css AND about.css with divergent bodies -- one
   column with a --line border on index, three columns with a --line2 border on about --
   the identical twin of the team-row split that shipped a fix to one of two pages. The
   layout difference is legitimate and stays as an OVERRIDE in about.css; the component
   itself is defined once. */
.badges{display:grid;gap:var(--g2);margin-top:30px}
.badges li{display:flex;gap:var(--g2);align-items:center;border:1px solid var(--line);border-radius:var(--rad-s);padding:15px 18px;background:rgba(12,24,48,.4)}
.badges .bi{width:42px;height:42px;flex-shrink:0;border-radius:11px;display:grid;place-items:center;background:rgba(41,170,227,.1);border:1px solid rgba(76,196,255,.28);color:var(--cyan2)}
.badges b{display:block;font:600 14.5px var(--disp)}
.badges span{font-size:13px;color:var(--mut)}

/* ---------- team row ----------
   OWNED HERE, not in a page sheet. This component appears on index AND about, and it was
   defined twice -- once in home.css, once in about.css. about.html does not load home.css,
   so the round-3 fix that turned the row from a blind horizontal scroller into a wrapping
   grid reached the homepage and left the about page showing 5 of 11 people with no
   affordance that the other six existed. Same class of bug as the solo-column centring
   that shipped into comparison.css the round before.

   THE RULE, from the round-3 review: chrome.css owns every component that appears on more
   than one page family. Page sheets may override, never define. */
/* EXPLICIT COLUMN COUNTS, because eleven items do not divide evenly and no flex-basis can
   make them. Growing the cards was the second failed attempt: at 1024 five cards simply
   grow to fill 976px and the eleventh is still orphaned. What matters is how many fit per
   row, so the row states it. 11 splits cleanly as 6/5, 4/4/3 and 3/3/3/2 -- it is FIVE
   columns that strands one, so five is the one count never used.
   (round 5, B Regression A -- third attempt, and the first one measured before shipping.) */
.teamrow{display:grid;grid-template-columns:repeat(6,1fr);gap:var(--g2);padding:6px 4px 22px}
@media (max-width:1120px){.teamrow{grid-template-columns:repeat(4,1fr)}}
@media (max-width:900px){.teamrow{grid-template-columns:repeat(3,1fr)}}
@media (max-width:520px){.teamrow{grid-template-columns:repeat(2,1fr)}}
.tcard{border:1px solid var(--line);border-radius:var(--rad);overflow:hidden;background:var(--panel);transition:border-color .25s,transform .25s}
.tcard:hover{border-color:rgba(76,196,255,.4);transform:translateY(-4px)}
.tcard img{width:100%;aspect-ratio:4/5;object-fit:cover;object-position:50% 18%}
.tcard div{padding:14px 16px 16px}
.tcard b{display:block;font:600 14.5px var(--disp)}
.tcard span{font:400 12px/1.45 var(--body);color:var(--mut);display:block;margin-top:2px}

/* ---------- sticky section rail ----------
   Lifted out of glossary.css on 2026-08-21 and made shared. It was the glossary's
   private component, but the five longest pages on the site -- the comparisons, the
   sector pages and the ordering page -- had NO on-page navigation at all, and they
   interleave full-width bands, so a side rail cannot span them. A sticky horizontal
   rail works with that architecture instead of against it. (B-D1 / C-D9) */
.chiprail{border-block:1px solid var(--line2);background:rgba(6,13,26,.92)}
/* The rail is masked at its right edge, because the scrollbar is hidden and a chip cut
   dead at the viewport edge was the ONLY signal that there was more to scroll. (B-D6) */
.chiprail .wrap{display:flex;gap:var(--g1);overflow-x:auto;padding-top:14px;padding-bottom:14px;scrollbar-width:none;scroll-padding-inline:24px;mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent);-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent)}
.chiprail .wrap::-webkit-scrollbar{display:none}
.chiprail a{flex-shrink:0;font:500 12px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--mut);border:1px solid var(--line2);border-radius:999px;padding:8px 16px;background:rgba(12,24,48,.5);transition:color .2s,border-color .2s}
.chiprail a:hover{color:#fff;border-color:var(--cyan)}
.chiprail a[aria-current="true"]{color:#fff;border-color:var(--cyan);background:rgba(41,170,227,.14)}
/* A landing marker for the 88 deep-link targets. Without it a search result drops you
   into a two-column card grid with nothing saying which card you came for. (C-8) */
.term:target,details:target,.family:target,.catindex:target{box-shadow:inset 3px 0 0 var(--cyan);
  background:rgba(41,170,227,.06)}
[id]{scroll-margin-top:90px}
body:has(.chiprail) [id]{scroll-margin-top:140px}
/* Sticky at EVERY width. It used to be gated behind min-width:1020px -- switched off at
   exactly the two widths where the page is longest (16,244px at 390), leaving the reader
   with no wayfinding at all for 40 terms. There was never a technical reason: the header
   is sticky at 74px unconditionally. (B-D6) */
.chiprail{position:sticky;top:74px;z-index:60;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}


/* ---------- shared section vocabulary ---------- */
section{padding:var(--sec) 0}
.kicker{display:inline-flex;align-items:center;gap:var(--g2);font:500 12px var(--mono);letter-spacing:.22em;text-transform:uppercase;color:var(--cyan)}
.kicker::before{content:"";width:26px;height:1px;background:var(--cyan)}
.shead{max-width:640px;margin-bottom:54px}
.shead.center{margin-inline:auto;text-align:center}
.shead .kicker{margin-bottom:14px}
.shead h2{font:600 clamp(26px,3.2vw,38px)/1.18 var(--disp);letter-spacing:-.01em}
.shead p{margin-top:14px;color:var(--mut)}
.pill{font:500 12px var(--mono);letter-spacing:.08em;color:var(--mut);border:1px solid var(--line);border-radius:999px;padding:7px 14px;background:rgba(12,24,48,.5)}
.pill b{color:var(--cyan2);font-weight:500}
.btns{display:flex;flex-wrap:wrap;gap:var(--g2);align-items:center}
@media (max-width:520px){.hero .btns{display:grid}.hero .btns>*{width:100%;justify-content:center}}
.card{background:linear-gradient(180deg,rgba(18,33,61,.55),rgba(12,24,48,.35));border:1px solid var(--line);border-radius:var(--rad);transition:transform .25s cubic-bezier(.22,.61,.36,1),border-color .25s,box-shadow .25s}
.card:hover{transform:translateY(-5px);border-color:rgba(76,196,255,.4);box-shadow:0 22px 40px -22px rgba(41,170,227,.35)}
.photocard{position:relative;border-radius:var(--rad);overflow:hidden;border:1px solid var(--line);background:var(--panel)}
.photocard img{width:100%;height:100%;object-fit:cover;transition:transform .6s cubic-bezier(.22,.61,.36,1)}
.photocard:hover img{transform:scale(1.045)}
.photocard figcaption{position:absolute;left:0;right:0;bottom:0;padding:40px 16px 13px;font:500 12px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:#CBDDF0;background:linear-gradient(transparent,rgba(4,10,20,.88))}

/* ---------- the closing band ----------
   Every page type ends on this. It was declared BYTE-FOR-BYTE TWICE -- once in article.css
   and once in service.css -- and both sheets load together on 23 pages, so the browser
   parsed five identical rules and discarded five. Harmless to render and corrosive to
   maintain: an edit to one copy changes the page type it is loaded with and silently
   leaves the other alone. THE RULE (round 3, and it is why .teamrow and .badges live up
   here): chrome.css owns every component that appears on more than one page type. */
.endband{background:radial-gradient(680px 380px at 50% 0%,rgba(29,130,198,.18),transparent 65%),var(--bg);border-top:1px solid var(--line);text-align:center;padding:84px 0}
.endband h2{font:600 clamp(26px,3.2vw,38px)/1.18 var(--disp);max-width:22ch;margin:16px auto 0}
.endband p{color:var(--mut);margin:16px auto 30px;max-width:52ch}
.endband .kicker{justify-content:center}
.endband .btns{justify-content:center}

/* data tables — the load-bearing object on several types */
.tablewrap{overflow-x:auto;border:1px solid var(--line2);border-radius:var(--rad-s);background:rgba(12,24,48,.4);scrollbar-width:thin;scrollbar-color:var(--blue) rgba(96,168,232,.12)}
@media (max-width:700px){.tablewrap{mask-image:linear-gradient(90deg,#000 calc(100% - 28px),rgba(0,0,0,.25));-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),rgba(0,0,0,.25))}}
table{width:100%;border-collapse:collapse;font-size:15px}
caption{caption-side:top;position:sticky;left:0;max-width:86vw;text-align:left;font:500 12px var(--mono);letter-spacing:.18em;text-transform:uppercase;color:var(--mut2);padding:14px 18px 12px}
th{font:600 13px var(--disp);letter-spacing:.04em;text-align:left;color:var(--ink);border-bottom:1px solid var(--line-strong);padding:13px 18px;white-space:nowrap}
td{padding:13px 18px;border-bottom:1px solid var(--line);color:var(--mut);vertical-align:top}
tr:last-child td{border-bottom:0}
td b,td strong{color:var(--ink);font-weight:600}
th[scope="row"]{font:500 12px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--cyan);border-bottom:1px solid var(--line);white-space:normal;position:sticky;left:0;background:#0D1A33}

/* ---------- footer ---------- */
footer{background:#050B16;border-top:1px solid var(--line);padding:64px 0 34px;font-size:14px;color:var(--mut)}
.fgrid{display:grid;grid-template-columns:1.35fr 1fr 1fr 1fr 1.15fr;gap:var(--g4);margin-bottom:48px}
.fgrid h2{font:600 12px var(--mono);letter-spacing:.18em;text-transform:uppercase;color:var(--mut2);margin-bottom:16px}
.fgrid li{margin-bottom:10px}
.fgrid a:hover{color:var(--cyan2)}
.fbrand p{margin-top:14px;max-width:34ch;font-size:13.5px}
.fsoc{display:flex;gap:var(--g2);margin-top:16px;font-size:13px}
.fsoc a{color:var(--mut2)}
.fsoc a:hover{color:var(--cyan2)}
.fbot{border-top:1px solid var(--line);padding-top:26px;display:flex;flex-wrap:wrap;gap:var(--g2);justify-content:space-between;font-size:12.5px;color:var(--mut2)}
@media (max-width:1120px){.fgrid{grid-template-columns:1fr 1fr}}
@media (max-width:520px){.fgrid{grid-template-columns:1fr}}

/* ---------- reveal (INERT by design — DESIGN-SYSTEM.md chrome delta #8) ----------
   The concept's scroll-reveals are dropped on the built site: content is always painted,
   so no pixel gate or crawler ever meets an opacity-0 page. Hover/carousel motion stays. */
.rv{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  *{transition-duration:.01ms!important;animation-duration:.01ms!important}
}

/* the search affordance in the collapsed header -- see add_mobile_search_button.py */
.searchbtn{display:none;flex:none;margin-left:auto;background:none;border:1px solid var(--line2);
  border-radius:12px;width:44px;height:44px;color:var(--ink);cursor:pointer;
  align-items:center;justify-content:center}
.searchbtn:hover{border-color:var(--cyan);color:#fff}
@media (max-width:900px){
  .searchbtn{display:inline-flex}
  .burger{margin-left:var(--g1)}
  /* Two 44px controls that can no longer shrink need the room to come from
     somewhere: the nav gutter and the wordmark, not from the tap targets. Without
     this the burger overhangs by 10px and every page scrolls sideways. */
  .nav{gap:var(--g2)}
  /* flex-shrink:1 is the load-bearing half of this. The base rule sets .logo{flex-shrink:0},
     so the min-width:0 written here on its own did NOTHING -- an item that refuses to shrink
     does not care what its minimum is. The header therefore had a hard floor of 388px and
     every page scrolled sideways by 28px on a 360px phone, which the live render gate caught
     across a dozen pages. Both properties are needed; either alone is inert. */
  .logo{min-width:0;flex-shrink:1}
  .logo b{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}
/* Below 520 the tagline is dropped rather than ellipsised. It is 12px mono at .24em
   tracking -- about 200px of the 360px a small phone has -- and clipping a letter-spaced
   uppercase label mid-word reads as breakage, where removing it reads as a decision.
   The company name stays, which is the part that identifies the site. */
@media (max-width:520px){
  .logo b span{display:none}
  .logo img{width:34px;height:34px}
}

/* ---------- WhatsApp ----------
   Dan, 2026-08-21: "make this into whatsapp, and make sure the whatsapp button is
   populated throughout so it's easy for users to find."

   Every one of these buttons already opened WhatsApp with a nine-field enquiry written
   into the message box. None of them said so, so the fastest route into the business
   looked like a form link. The mark is the real WhatsApp glyph -- the one filled icon on
   a site whose vocabulary is 1.6px strokes -- because a house-style speech bubble is
   exactly what was there before and nobody read it as WhatsApp. */
.waglyph{width:1.15em;height:1.15em;flex:none;display:block}
.cta .waglyph{margin-right:2px}
/* Inside a text link the mark sits on the baseline rather than on the line box. */
a:not(.cta):not(.wafloat) > .waglyph{display:inline-block;vertical-align:-.18em;
  margin-right:6px}

/* The floating button. WhatsApp green, not the site cyan: the whole point is that it is
   recognised before it is read, and green-on-navy is what carries that. It is the only
   element on the site allowed outside the palette, and it earns it by being a third
   party's identity rather than ours.
   Hidden at phone widths -- the three-up action bar already owns the bottom edge there,
   and two fixed things fighting for the same corner is worse than either. */
.wafloat{position:fixed;right:22px;bottom:22px;z-index:76;display:inline-flex;
  align-items:center;gap:10px;min-height:52px;padding:0 22px 0 18px;border-radius:999px;
  background:#25D366;color:#06210F;font:600 14px var(--disp);letter-spacing:.01em;
  box-shadow:0 10px 30px -8px rgba(0,0,0,.6),0 0 0 1px rgba(255,255,255,.14);
  transition:transform .22s cubic-bezier(.22,.61,.36,1),box-shadow .22s}
.wafloat .waglyph{width:22px;height:22px}
.wafloat:hover{transform:translateY(-2px);background:#2AE372;
  box-shadow:0 16px 36px -10px rgba(0,0,0,.7),0 0 0 1px rgba(255,255,255,.24)}
.wafloat:focus-visible{outline:3px solid var(--cyan2);outline-offset:3px}
/* Tucked while the reader is still at the top of a page. The homepage hero carries a
   product carousel whose next-arrow sits in exactly this corner, and the float covered it;
   every other hero has something in its bottom-right too. It is not a loss of reach --
   the header is sticky and its own WhatsApp pill is on screen the whole time -- so this
   simply hands over from one to the other instead of stacking two.
   Progressive enhancement in the safe direction: the tuck is ADDED by script, so with no
   JavaScript the button is permanently visible rather than permanently gone. */
.wafloat{opacity:1;transform:translateY(0);
  transition:transform .22s cubic-bezier(.22,.61,.36,1),box-shadow .22s,opacity .22s}
.wafloat.tucked{opacity:0;transform:translateY(14px);pointer-events:none}
/* Hands over to the three-up action bar at 900, which is where that bar APPEARS -- not at
   700, where it was first written. Between 701 and 900 both were on screen and the float's
   bottom edge (22px up) sat inside the 64px bar. Measured, not assumed. */
@media (max-width:900px){.wafloat{display:none}}
@media (prefers-reduced-motion:reduce){.wafloat{transition:none}.wafloat:hover{transform:none}}
