/* =========================================================
   StaffCloud — Homepage stylesheet
   Structure: 1 Tokens · 2 Reset · 3 Utilities · 4 Components
              5 Sections · 6 Responsive
   Brand tokens sampled from staffcloud.net
   ========================================================= */

/* ---------- 1. TOKENS ---------- */
:root{
  /* brand */
  --brand:#3763E7;
  --brand-dark:#2A4FC4;
  --brand-darker:#1F3C9B;
  --brand-tint:#EAEFFD;
  --brand-tint-2:#F5F7FE;
  --navy:#001035;
  --navy-2:#0A1C47;

  /* neutrals */
  --ink:#161C2D;
  --muted:#5A6478;
  --grey:#F1F4F8;        /* navigation ribbon */
  --grey-dark:#E3E9F3;   /* About block — one step darker than the ribbon */
  --grey-darker:#D7E0EE; /* …and its hover */
  --line:#E2E8F2;
  --white:#fff;

  /* type */
  --font:"Inter","Neue Haas Grotesk Text","Helvetica Neue",Arial,system-ui,sans-serif;
  --fs-h1:clamp(2.1rem,1.2rem + 3.4vw,3.375rem);
  --fs-h2:clamp(1.65rem,1.05rem + 2.1vw,2.625rem);
  --fs-h3:clamp(1.15rem,.95rem + .7vw,1.375rem);
  --fs-body:1.0625rem;

  /* layout */
  --container:1240px;
  --container-wide:1560px;   /* pillar pages and the mega panels run wide */
  --gutter:24px;
  --radius:16px;
  /* One radius for every button on the site. It was hard-coded at 10px on
     .btn while cards used 16px and chips 999px, so a button sitting next to
     a card read as a slightly different shape language. 12px sits in the
     same family as the 16px card without looking like a pill. */
  --btn-radius:12px;
  --radius-sm:10px;
  --radius-lg:24px;
  --section-y:clamp(56px,7vw,104px);
  --section-y-sm:clamp(36px,4.2vw,62px);   /* tightened section boundaries */

  /* banner height — one token, shared by the homepage hero and every service
     hero, so the two can never drift apart */
  --hero-h:min(578px, calc(420px + 11vw));

  /* effects */
  --shadow-sm:0 1px 2px rgba(0,16,53,.06), 0 2px 8px rgba(0,16,53,.05);
  --shadow:0 10px 30px rgba(0,16,53,.08);
  --shadow-lg:0 24px 60px rgba(0,16,53,.14);
  --ease:cubic-bezier(.22,.61,.36,1);
}

/* ---------- 2. RESET ---------- */
*,*::before,*::after{box-sizing:border-box}

/* THE `hidden` ATTRIBUTE MUST ACTUALLY HIDE THINGS.
   The browser's own rule is `[hidden]{display:none}` — a single attribute
   selector, which ANY class rule setting `display` beats. So `el.hidden = true`
   in JavaScript silently does nothing to a component styled `display:flex`,
   and the only symptom is that something which should have disappeared is
   still on screen.
   This had already been patched one component at a time in seven places
   (.panel, .csPanel, .faq__item, .faq__group, .rte__bar, .rte__link,
   .work__empty, .lbox) as each was discovered. Three more were still broken
   when the blog search was reported: `.bcard` (search filtered the count but
   left every card visible), `.bmore` (the Load more button never went away)
   and `.faq__nav` (the topic list stayed up during a search).
   `!important` rather than source order, so a class rule added below this
   point cannot quietly reintroduce the bug.
   The one deliberate exception is the Client Success Stories hub, which ships
   its panels `hidden` so they ALL render without JavaScript — see
   `.csHub__panels .csPanel[hidden]` further down, which overrides this on
   purpose and says so. */
[hidden]{display:none !important}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
/* `clip` (not `hidden`) keeps the off-canvas mobile drawer from widening the
   page without turning <html> into a scroll container — position:sticky stays alive. */
html,body{overflow-x:clip}
body{
  margin:0;font-family:var(--font);font-size:var(--fs-body);line-height:1.7;
  color:var(--ink);background:var(--white);-webkit-font-smoothing:antialiased;
}
img,svg{max-width:100%}
h1,h2,h3,h4{margin:0 0 .5em;line-height:1.18;font-weight:600;letter-spacing:-.02em;color:var(--navy)}
h1{font-size:var(--fs-h1)}h2{font-size:var(--fs-h2)}h3{font-size:var(--fs-h3)}
p{margin:0 0 1rem}
a{color:var(--brand);text-decoration:none;transition:color .2s var(--ease)}
a:hover{color:var(--brand-dark)}
ul,ol{margin:0;padding:0;list-style:none}
button{font:inherit;color:inherit;cursor:pointer;border:0;background:none}
:focus-visible{outline:3px solid var(--brand);outline-offset:3px;border-radius:4px}
.sprite{position:absolute;width:0;height:0;overflow:hidden}
.skip-link{position:absolute;left:-9999px;top:0;z-index:999;background:var(--brand);color:#fff;padding:12px 20px;border-radius:0 0 8px 0}
.skip-link:focus{left:0;color:#fff}

/* ---------- 3. UTILITIES ---------- */
.container{width:100%;max-width:var(--container);margin-inline:auto;padding-inline:var(--gutter)}
/* Wide variant — the mega panels and the pillar pages. It is a separate class
   rather than a wider --container so the global header and footer keep the
   homepage's 1240px measure on every page. */
.container--wide{max-width:var(--container-wide)}

.ico{width:24px;height:24px;flex:none;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.ico--sm{width:18px;height:18px}
.ico--xs{width:15px;height:15px;stroke-width:2}
.ico--brand{color:var(--brand)}
.ico.flip{transform:rotate(180deg)}
.ico.up{transform:rotate(-90deg)}

.eyebrow{
  display:inline-flex;align-items:center;gap:8px;margin:0 0 14px;
  font-size:.8125rem;font-weight:600;letter-spacing:.09em;text-transform:uppercase;color:var(--brand);
}
.eyebrow .dot{width:6px;height:6px;border-radius:50%;background:currentColor}
.eyebrow--light{color:#9DB6FF}

.grad{background:linear-gradient(100deg,#6C93FF,#B9CBFF);-webkit-background-clip:text;background-clip:text;color:transparent}

.sec__head{margin-bottom:clamp(32px,4vw,52px)}
.sec__title{margin:0 0 .4em}
.sec__lead{color:var(--muted);max-width:62ch;margin:0}
.sec__head--center{text-align:center}
.sec__head--center .sec__lead{margin-inline:auto}
.sec__head--split{display:flex;align-items:flex-end;justify-content:space-between;gap:32px;flex-wrap:wrap}
.sec__head--split>div:first-child{flex:1 1 480px;min-width:0}
.sec__lead--right{flex:0 1 360px;max-width:40ch;text-align:right}

.pill{padding:4px 10px;border-radius:999px;background:var(--brand-tint);color:var(--brand-dark);font-size:.75rem;font-weight:600}
.pill--live{background:#E6F7EE;color:#0E7C4A;display:inline-flex;align-items:center;gap:6px}
.pill--live::before{content:"";width:6px;height:6px;border-radius:50%;background:#16A46A;box-shadow:0 0 0 0 rgba(22,164,106,.6);animation:ping 2s infinite}
@keyframes ping{70%{box-shadow:0 0 0 7px rgba(22,164,106,0)}100%{box-shadow:0 0 0 0 rgba(22,164,106,0)}}


.link{display:inline-flex;align-items:center;gap:7px;font-weight:600;font-size:.9375rem}
.link .ico{transition:transform .25s var(--ease)}
.link:hover .ico{transform:translateX(4px)}

/* reveal on scroll */
.reveal{opacity:0;transform:translateY(22px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.reveal.is-in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
  .reveal{opacity:1;transform:none}
}

/* ---------- 4. COMPONENTS ---------- */
.btn{
  --btn-bg:var(--brand);--btn-fg:#fff;--btn-bd:transparent;
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:13px 24px;border-radius:var(--btn-radius);border:1.5px solid var(--btn-bd);
  background:var(--btn-bg);color:var(--btn-fg);font-weight:600;font-size:.9375rem;line-height:1.2;
  transition:transform .18s var(--ease),box-shadow .25s var(--ease),background .2s var(--ease),color .2s var(--ease),border-color .2s var(--ease);
  white-space:nowrap;
}
.btn:hover{transform:translateY(-2px);color:var(--btn-fg)}
.btn:active{transform:translateY(0)}
.btn--primary{box-shadow:0 8px 20px rgba(55,99,231,.28)}
.btn--primary:hover{--btn-bg:var(--brand-dark);box-shadow:0 12px 26px rgba(55,99,231,.34)}
.btn--outline{--btn-bg:transparent;--btn-fg:var(--brand);--btn-bd:var(--line)}
.btn--outline:hover{--btn-bd:var(--brand);--btn-bg:var(--brand-tint-2)}
.btn--outlineLight{--btn-bg:rgba(255,255,255,.06);--btn-fg:#fff;--btn-bd:rgba(255,255,255,.34)}
.btn--outlineLight:hover{--btn-bg:rgba(255,255,255,.14);--btn-fg:#fff}
.btn--ghost{--btn-bg:transparent;--btn-fg:var(--ink);--btn-bd:transparent}
.btn--ghost:hover{--btn-fg:var(--brand);--btn-bg:var(--brand-tint-2)}
.btn--sm{padding:10px 18px;font-size:.875rem}
.btn--lg{padding:16px 30px;font-size:1rem}
.btn--block{display:flex;width:100%}




/* ---------- 5. SECTIONS ---------- */

/* =========================================================
   HEADER — two tiers:
   1. .utility  logo + tagline | phone/portal + CTA buttons, email beneath
   2. .navbar   sticky ribbon: pillar links … About StaffCloud (far right)
   ========================================================= */
/* The whole header sticks, but with a negative offset equal to the utility bar's
   height — so tier 1 scrolls away and only the ribbon stays pinned.
   JS measures --utility-h; the fallback keeps it working with JS disabled. */
.header{position:sticky;top:calc(-1 * var(--utility-h, 84px));z-index:60;background:#fff}

/* --- Tier 1 · utility bar --- */
.utility{background:#fff}
.utility__inner{display:flex;align-items:center;gap:20px;padding-block:18px}
.utility__tagline{
  margin:0;padding-left:20px;border-left:1px solid var(--line);
  font-size:.8125rem;font-weight:600;line-height:1.45;color:var(--muted);letter-spacing:.01em;
}
.utility__right{margin-left:auto;display:flex;flex-direction:column;align-items:flex-end;gap:9px}
.utility__actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap;justify-content:flex-end}
.utility__email{
  display:inline-flex;align-items:center;gap:8px;font-size:.8125rem;font-weight:500;color:var(--muted);
  /* sits directly beneath the Contact Us button */
  padding-right:2px;
}
.utility__email .ico{color:var(--brand)}
.utility__email:hover{color:var(--brand)}

/* The .utility__contact / __tel / __telLabel / __telNote / __sep rules that
   lived here were removed with the markup they styled (rev 76). CSS leaves
   with its markup — a selector with nothing to match is a thing the next
   person has to prove is unused before they dare touch it. */

/* --- Tier 2 · navigation ribbon --- */
.navbar{
  background:var(--grey);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  transition:box-shadow .3s var(--ease);
}
.navbar.is-stuck{box-shadow:0 8px 24px rgba(0,16,53,.10)}
.navbar__inner{display:flex;align-items:stretch}

/* Logo — height-driven; the intrinsic width/height attributes on the <img>
   reserve the right space so nothing shifts while it loads. */
.logo{display:inline-flex;align-items:center;flex:none}
.logo img{height:29px;width:auto;display:block}
.footer .logo img{height:27px}

.nav{display:flex;align-items:stretch;width:100%}
/* The positioned ancestor for the mega panels. Its box runs from the start of
   the home icon to the outer edge of About StaffCloud, so a panel with
   left:0;right:0 lands exactly on those bounds at every desktop width — no
   width arithmetic, and nothing to re-tune per breakpoint. */
.nav__list{display:flex;align-items:stretch;width:100%;position:relative}
.nav__item{display:flex}
.nav__link{
  display:inline-flex;align-items:center;gap:7px;padding:17px 18px;
  color:var(--navy);font-weight:500;font-size:.9375rem;white-space:nowrap;
  border-bottom:3px solid transparent;transition:all .2s var(--ease);
}
.nav__link:hover,.nav__link.is-active,
.has-mega.is-open>.nav__link{color:var(--brand);background:#fff;border-bottom-color:var(--brand)}
.nav__link--home{padding-inline:16px;color:var(--muted)}
.nav__link--home:hover{color:var(--brand)}
.nav__caret{transform:rotate(90deg);width:13px;height:13px;opacity:.6;transition:transform .25s var(--ease)}
.has-mega.is-open>.nav__link .nav__caret,
.has-drop.is-open>.nav__link .nav__caret{transform:rotate(-90deg);opacity:1}

/* Featured right anchor — pushed to the trailing edge, high-contrast fill */
.nav__item--about{margin-left:auto}
.nav__link--about{
  padding:17px 26px;background:var(--grey-dark);color:var(--navy);font-weight:600;
  border-bottom:3px solid transparent;
  border-left:1px solid var(--line);border-right:1px solid var(--line);
}
.nav__link--about:hover,
.has-drop.is-open>.nav__link--about{background:var(--grey-darker);color:var(--brand);border-bottom-color:var(--brand)}
.nav__item--about .drop{left:auto;right:0}

/* Action block: drawer-only, these live in the utility bar on desktop */
.nav__cta{display:none;align-items:center;gap:10px}
.nav__ctaMail{display:inline-flex;align-items:center;gap:9px;font-size:.875rem;color:var(--muted)}
.nav__ctaMail .ico{color:var(--brand)}

/* --- Mega menu (five service pillars) --- */
/* The panel itself never fades — it is either not painted at all
   (visibility:hidden) or fully opaque. Only its contents fade in. Fading the
   whole box made the page behind it show through for the length of the
   transition, which is what a screenshot taken mid-open catches. */
.mega{
  position:absolute;left:0;right:0;top:calc(100% + 1px);background:#fff;
  border:1px solid var(--line);border-radius:0 0 12px 12px;
  box-shadow:0 22px 44px rgba(0,16,53,.10);
  visibility:hidden;transform:translateY(-10px);
  transition:transform .2s var(--ease),visibility .2s var(--ease);
  /* Safety valve for short viewports only — invisible while the panel fits. */
  max-height:calc(100vh - 168px);overflow-y:auto;overscroll-behavior:contain;
}
.mega__inner{opacity:0;transition:opacity .2s var(--ease)}
.has-mega.is-open .mega{visibility:visible;transform:none}
.has-mega.is-open .mega__inner{opacity:1}
/* Heading across the top, lead under it, then the groups — the arrangement on
   suntecindia.com. The panel is full-width and .container--wide sets the
   measure, so the links use the whole width instead of a 574px middle column. */
.mega__inner{padding:30px clamp(22px,2.2vw,34px) 34px}
.mega__title{
  display:inline-flex;align-items:center;gap:12px;
  font-size:1.5rem;font-weight:600;letter-spacing:-.025em;color:var(--navy);
}
.mega__title .ico{width:21px;height:21px;color:var(--brand);transition:transform .25s var(--ease)}
.mega__title:hover{color:var(--brand)}
.mega__title:hover .ico{transform:translateX(5px)}
.mega__lead{margin:9px 0 0;max-width:104ch;font-size:.875rem;line-height:1.6;color:var(--muted)}

/* Three levels: the nav label is the pillar, .mega__groupLink is the
   sub-category and .mega__sub holds its service links.

   A real three-column grid, not multi-column flow. Flow balances by height, so
   a panel with four groups filled two columns and left the third empty; a grid
   fills the row first — four groups read 3 + 1. Rows start at the top, so a
   short group leaves space under itself rather than stretching. */
.mega__links{display:grid;grid-template-columns:repeat(3,1fr);gap:18px 26px;align-content:start;
  margin-top:22px;padding-top:22px;border-top:1px solid var(--line)}
.mega__group{align-self:start}
.mega__links a{display:flex;gap:13px;padding:11px 12px;border-radius:11px;color:var(--ink);transition:background .2s var(--ease),color .2s var(--ease)}
.mega__links a:hover{background:var(--brand-tint-2)}
.mega__groupLink{align-items:center;padding:6px 12px}
.mega__groupLink .ico{width:21px;height:21px;flex:0 0 21px;color:var(--brand)}
.mega__groupLink strong{font-size:.9375rem;font-weight:600;color:var(--navy);line-height:1.35}
/* Level 3 aligns with the group label, not its icon: 21px icon + 13px gap. */
.mega__sub{padding-left:34px}
.mega__sub a{padding:2px 12px;font-size:.8125rem;color:var(--muted);line-height:1.4}
.mega__sub a:hover{color:var(--brand)}
/* The overflow link. It is an action, not one more capability, so it reads in
   brand blue with the same arrow the panel heading uses. */
.mega__sub .mega__all{align-items:center;gap:7px;margin-top:2px;font-weight:600;color:var(--brand)}
.mega__sub .mega__all .ico{transition:transform .25s var(--ease)}
.mega__sub .mega__all:hover .ico{transform:translateX(3px)}

/* --- Mega-menu hover stability ---------------------------------------
   Invisible bridges span the strip between a link and its panel so the
   pointer never crosses dead space on the way down (the About dropdown sits
   8px below its link). `.is-swapping` kills the transitions for one frame
   while one panel replaces another, so two panels can never cross-fade on
   top of each other. -------------------------------------------------- */
.has-mega>.nav__link,.has-drop>.nav__link{position:relative}
.has-mega>.nav__link::after,.has-drop>.nav__link::after{
  content:"";position:absolute;left:0;right:0;top:100%;height:14px;
}
.nav.is-swapping .mega,.nav.is-swapping .drop{transition:none}

/* --- Compact dropdown (About Us) --- */
.has-drop{position:relative}
.drop{
  position:absolute;top:calc(100% + 8px);left:0;min-width:236px;background:#fff;
  border:1px solid var(--line);border-radius:var(--radius);padding:8px;box-shadow:var(--shadow);
  opacity:0;visibility:hidden;transform:translateY(-8px);
  transition:opacity .2s var(--ease),transform .2s var(--ease),visibility .2s var(--ease);
}
.has-drop.is-open .drop{opacity:1;visibility:visible;transform:none}
.drop__list a{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:11px 13px;border-radius:9px;color:var(--navy);font-size:.9125rem;font-weight:500;
  transition:background .2s var(--ease),color .2s var(--ease);
}
.drop__list a .ico{color:var(--brand);opacity:0;transform:translateX(-4px);transition:all .2s var(--ease)}
.drop__list a:hover{background:var(--brand-tint-2);color:var(--brand)}
.drop__list a:hover .ico{opacity:1;transform:none}

.burger{display:none;width:44px;height:44px;border-radius:10px;border:1px solid var(--line);margin-left:auto;padding:0}
.burger span{display:block;width:19px;height:2px;margin:4px auto;background:var(--navy);border-radius:2px;transition:transform .3s var(--ease),opacity .2s var(--ease)}
.burger[aria-expanded="true"] span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

/* =========================================================
   HERO SLIDER
   --hero-h is a deliberate, compact banner: tall enough for the
   densest slide, short enough that the fold reaches the copy below.
   Heights were set by measuring each slide's content against the stage.
   ========================================================= */
.hero{
  /* Light banner tokens. Every hero element derives its colour from these, so
     the whole banner can be re-tinted from one place. */
  --hero-ink:var(--navy);                 /* headlines */
  --hero-body:var(--muted);               /* leads, meta, notes */
  --hero-line:#DCE4F2;                    /* card and divider hairlines */
  --hero-surface:#fff;                    /* card fill */
  --hero-art:#3763E7;                     /* animated artwork stroke */
  position:relative;height:var(--hero-h);background:#fff;color:var(--ink);overflow:hidden;
  border-bottom:1px solid var(--line);
}
.hero__bg{position:absolute;inset:0;
  background:
    radial-gradient(860px 440px at 78% 10%, rgba(55,99,231,.13), transparent 62%),
    radial-gradient(660px 460px at 6% 94%, rgba(35,72,190,.09), transparent 60%),
    linear-gradient(160deg,#FFFFFF 0%,#F7F9FF 54%,#ECF1FD 100%);
}
.hero__bg::after{
  content:"";position:absolute;inset:0;opacity:.5;
  background-image:linear-gradient(rgba(0,16,53,.045) 1px,transparent 1px),linear-gradient(90deg,rgba(0,16,53,.045) 1px,transparent 1px);
  background-size:64px 64px;
  -webkit-mask-image:radial-gradient(70% 70% at 50% 40%,#000,transparent);
  mask-image:radial-gradient(70% 70% at 50% 40%,#000,transparent);
}
/* The eyebrow and gradient word were tuned for a navy banner — re-point them
   inside the hero only; the navy Testimonials band still uses the light one. */
.hero .eyebrow--light{color:var(--brand)}
.hero .grad{background:linear-gradient(100deg,var(--brand-darker),var(--brand) 85%);-webkit-background-clip:text;background-clip:text;color:transparent}

/* --- Stage & slide transition --- */
/* Full-bleed stage: the backdrop reaches the foot of the banner, and the
   controls float over it. The space they occupy is reserved as padding on
   .slide instead, so the centred copy does not move. */
.hero__stage{position:absolute;inset:0}
.slide{
  position:absolute;inset:0;display:flex;align-items:center;padding-bottom:54px;
  opacity:0;transform:translateX(56px);pointer-events:none;
  transition:opacity .85s var(--ease), transform .85s var(--ease);
}
.slide.is-active{opacity:1;transform:none;pointer-events:auto}
.slide.is-leaving{opacity:0;transform:translateX(-56px)}
.slide__inner{position:relative;z-index:1;width:100%}
.slide__copy{max-width:600px}
.slide__copy--wide{max-width:none}
.slide__copy--wide .slide__title,.slide__copy--wide .slide__lead{max-width:680px}
.slide__title{color:var(--hero-ink);font-weight:600;letter-spacing:-.025em;margin-bottom:.35em;
  font-size:clamp(1.65rem,1rem + 2.2vw,2.5rem);line-height:1.15}
.slide__lead{color:var(--hero-body);font-size:clamp(.9125rem,.88rem + .25vw,1.0625rem);margin-bottom:22px;max-width:56ch}
.slide__note{margin:14px 0 0;font-size:.75rem;color:var(--hero-body)}

/* --- Full-bleed animated backdrop (one per slide) --- */
.slide__bg{position:absolute;inset:0;z-index:0;overflow:hidden}
.slide__bg *{transform-box:fill-box;transform-origin:center}
.slide__bg--world{background:radial-gradient(760px 430px at 70% 48%,rgba(55,99,231,.10),transparent 66%)}
.slide__bg--proof{background:radial-gradient(720px 400px at 72% 30%,rgba(108,147,255,.12),transparent 64%)}
.slide__bg--ecom{background:radial-gradient(700px 400px at 70% 58%,rgba(78,123,255,.11),transparent 64%)}
.slide__bg--data{background:radial-gradient(740px 420px at 72% 36%,rgba(42,79,196,.09),transparent 66%)}
.slide__bg--support{background:radial-gradient(700px 420px at 70% 52%,rgba(90,130,255,.11),transparent 64%)}

/* shared network mesh, cropped with slice so it never shows an edge */
.mesh{
  position:absolute;inset:-7%;width:114%;height:114%;color:var(--hero-art);
  animation:meshDrift 42s ease-in-out infinite alternate;
}
.mesh-l line{stroke:currentColor;stroke-width:1;opacity:.10}
.mesh-d circle{fill:currentColor}
.mesh-n{opacity:.18;animation:meshPulse 5.4s ease-in-out infinite}
.mesh-n.d1{animation-delay:.9s}.mesh-n.d2{animation-delay:1.8s}
.mesh-n.d3{animation-delay:2.7s}.mesh-n.d4{animation-delay:3.6s}.mesh-n.d5{animation-delay:4.5s}
@keyframes meshDrift{to{transform:translate3d(-30px,-20px,0) scale(1.05)}}
@keyframes meshPulse{0%,100%{opacity:.12}50%{opacity:.55}}

/* slide 1 · globe beneath the mesh */
.mesh--globe{color:var(--hero-art);animation:none}
.globe-g{opacity:.3}
.globe-g ellipse,.globe-g path,.globe-o,.globe-ring{fill:none;stroke:currentColor;stroke-width:1}
.globe-o{opacity:.22}
.globe-spin{animation:artSpin 100s linear infinite}
.globe-ring{opacity:.4;animation:artSpin 70s linear infinite reverse}
@media (prefers-reduced-motion:reduce){
  .mesh{animation:none}
  .mesh *,.slide__bg *{animation:none!important}
}

/* --- Full-bleed topic graphics ---------------------------------------
   Every slide's artwork is drawn on the same 1440x600 canvas and cropped with
   preserveAspectRatio="slice", exactly like the slide-1 globe. Nothing is
   anchored to an edge at a fixed pixel width, so no motif can be clipped into
   a stray fragment on a narrower screen. -------------------------------- */
.bgart{
  position:absolute;inset:0;width:100%;height:100%;
  fill:none;stroke:currentColor;stroke-width:1.2;color:rgba(55,99,231,.26);
}
.bgart *{transform-box:fill-box;transform-origin:center}
.bg-orbit{opacity:.9}
.bg-stars circle,.bg-tiles rect{opacity:.5}
.bg-hair,.bg-rail{opacity:.35}
.bg-wave{opacity:.55;stroke-width:1.6}
.bg-stream-field{opacity:.55}
.bg-bubbles{opacity:.6}

.art-spin{animation:artSpin 72s linear infinite}
.art-spin-rev{animation:artSpin 54s linear infinite reverse}
.art-float{animation:artFloat 6s ease-in-out infinite}
.art-tw{animation:artTwinkle 3.6s ease-in-out infinite}
.art-pulse{animation:artPulse 4.4s ease-in-out infinite}
.art-pop{animation:artPop 5s ease-in-out infinite}
.bg-flow{animation:bgFlow 9s linear infinite}
.bg-stream{animation:bgStream 3.8s linear infinite}
.d1{animation-delay:.8s}.d2{animation-delay:1.6s}
.d3{animation-delay:2.4s}.d4{animation-delay:3.2s}

@keyframes artSpin{to{transform:rotate(360deg)}}
@keyframes artFloat{50%{transform:translateY(-14px)}}
@keyframes artTwinkle{0%,100%{opacity:.15}50%{opacity:.9}}
@keyframes artPulse{0%,100%{opacity:.25}50%{opacity:.9}}
@keyframes artPop{0%,100%{opacity:.25;transform:scale(.94)}45%{opacity:1;transform:scale(1)}}
@keyframes bgFlow{0%{transform:translateX(0);opacity:0}8%{opacity:1}88%{opacity:1}100%{transform:translateX(1560px);opacity:0}}
@keyframes bgStream{0%{transform:translateY(0);opacity:0}14%{opacity:1}84%{opacity:1}100%{transform:translateY(44px);opacity:0}}
@media (prefers-reduced-motion:reduce){
  .bgart *{animation:none!important}
}

/* --- Slide 1 credential pyramid (rev 74) ---
   One square card centred above two more, all three 1:1. The row below is a
   two-column grid; the lead card is centred on it by giving it the same width
   as one of the two plus half the gap, which keeps the pyramid symmetrical at
   every width rather than only at the one it was designed at. --- */
.slide__inner--certs{grid-template-columns:1fr .96fr}
.pyramid{display:grid;justify-items:center;gap:clamp(12px,1.2vw,18px);
  --pcard:clamp(146px,11.5vw,168px);--pgap:clamp(10px,1.2vw,18px)}
.pyramid__row{display:grid;grid-template-columns:repeat(2,var(--pcard));gap:var(--pgap)}
/* The anchor holds the square and never moves. `.pcard__in` is the surface that
   lifts — because a transform on the hover target shifts its own hitbox, the
   cursor drops off the bottom edge, :hover ends, the card falls back, and it
   flickers. This codebase has hit that bug before; the rule is to animate an
   inner element. */
/* EVERY BARE `.pcard` RULE IN THIS BLOCK IS SCOPED TO `.pyramid`, and must
   stay that way. `.pcard` is ALSO the blog's sibling-article card
   (`ul.pcards > li.pcard`, stylesheet section further down) — two unrelated
   components that happened to pick the same name, added months apart.
   Unscoped, `aspect-ratio:1` and `display:block` here reached every blog
   article page and squashed those cards into squares with their titles cut
   off. It shipped in rev 74 and was only found on 12 October, when a link
   added inside the hero card picked up `.pcard a`'s white background from the
   blog rules and made the collision visible in the other direction.
   Both sides are scoped now. See claude/class-name-collisions.md. */
.pyramid .pcard{width:var(--pcard);aspect-ratio:1;display:block;color:var(--navy);
  border-radius:18px}
.pcard__in{
  width:100%;height:100%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:6px;padding:14px 12px;border-radius:18px;text-align:center;
  /* Glass: translucent white over the hero artwork, blurred behind so the
     network graphic reads as texture rather than as noise through the card.
     The solid fallback comes first, for anything without backdrop-filter. */
  background:rgba(255,255,255,.86);
  border:1px solid var(--hero-line);
  box-shadow:0 10px 26px rgba(0,16,53,.08),inset 0 1px 0 rgba(255,255,255,.7);
  transition:transform .28s var(--ease),box-shadow .28s var(--ease),
             border-color .28s var(--ease);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .pcard__in{background:linear-gradient(150deg,rgba(255,255,255,.82),rgba(255,255,255,.62));
    -webkit-backdrop-filter:blur(10px) saturate(1.3);
    backdrop-filter:blur(10px) saturate(1.3)}
}
.pyramid .pcard:hover .pcard__in{transform:translateY(-6px);border-color:#C6D6F6;
  box-shadow:0 22px 44px rgba(0,16,53,.16),inset 0 1px 0 rgba(255,255,255,.8)}
.pyramid .pcard:focus-visible{outline:2px solid var(--brand);outline-offset:3px;border-radius:18px}
.pcard__icon{display:grid;place-items:center;color:var(--brand)}
.pcard__icon .ico{width:clamp(20px,1.8vw,26px);height:clamp(20px,1.8vw,26px);stroke-width:1.6}
.pcard__big{display:flex;align-items:baseline;gap:3px;font-size:clamp(1.6rem,2.3vw,2.6rem);
  font-weight:700;letter-spacing:-.04em;line-height:1;color:var(--hero-ink)}
.pcard__big i{font-style:normal;font-size:.36em;font-weight:600;letter-spacing:.02em;
  text-transform:uppercase;color:var(--muted)}
.pcard__logo{width:auto;max-width:72%;max-height:clamp(30px,2.6vw,38px);
  object-fit:contain;margin-bottom:2px}
.pcard__logo--wide{max-height:clamp(19px,1.7vw,24px);max-width:82%}
.pcard__name{font-size:clamp(.75rem,.62vw + .55rem,.8125rem);font-weight:650;line-height:1.3;letter-spacing:-.01em}
.pcard__meta{font-size:.6563rem;line-height:1.4;color:var(--muted);max-width:18ch}

/* ---- Clutch widget slots (hero slides 1 and 2) ----------------------------
   A Clutch widget is a third-party IFRAME. Two things follow, and both of
   them are why this wrapper exists rather than dropping Clutch's snippet
   straight into the markup.

   1. IT MUST NOT RESIZE ITS CONTAINER. Both slots sit inside the hero, whose
      height is a fixed token (--hero-h) with absolutely-positioned slides, and
      slide 1's card is a 1:1 square in a three-card pyramid. An iframe that
      arrives at its own height would push the card out of square or the panel
      out of the slide. The slot reserves exactly --clutch-h from first paint,
      set per instance in the markup, and clips anything over it. The space is
      held whether the widget ever loads or not, so there is no shift either
      way.

   2. IT MUST DEGRADE. Third-party widgets are blocked often — privacy
      extensions, corporate proxies, and the shared prototype artifact's CSP,
      which blocks third-party frames outright. The fallback is our own markup
      and is VISIBLE BY DEFAULT, so a reader with JavaScript off or the script
      blocked gets the real content rather than a hole. js/clutch.js hides it
      the moment it starts watching and brings it back if the widget does not
      arrive. Starting it hidden would have been the obvious choice and is
      wrong: with JS off, nothing would ever unhide it. */
.clutchSlot{
  position:relative;width:100%;
  height:var(--clutch-h,40px);
  overflow:hidden;
  /* Centres the fallback in the reserved box. */
  display:flex;align-items:center;justify-content:center;
}
/* THE WIDGET IS TAKEN OUT OF FLOW, and that is load-bearing. As a normal
   block it fills the slot's full height, pushes the fallback below it, and
   `overflow:hidden` then clips the fallback away — a reserved box with
   nothing visible in it. That shipped for one build and was missed because
   the check asked whether the fallback was *in the layout* (offsetParent),
   which a clipped element still is. Out of flow, the two occupy the same
   box and the fallback is hidden by class when the widget actually lands. */
.clutchSlot .clutch-widget{
  position:absolute;inset:0;display:block;width:100%;height:100%;
  /* The scale js/clutch.js sets when the rendered iframe comes back wider
     than the slot. Origin is the centre so a shrunk badge stays centred under
     the logo rather than drifting to one corner. */
  transform:scale(var(--clutch-scale,1));transform-origin:center center;
}
.clutchSlot .clutch-widget iframe{display:block;border:0;max-width:100%}
/* The fallback sits in the same box, so swapping one for the other moves
   nothing on the page. */
.clutchSlot__fb{max-width:100%;z-index:1}
.clutchSlot.is-live .clutchSlot__fb{display:none}

/* Slide 2's CTA slot holds a button, which has its own height — centre it in
   the reserved 65px rather than stretching it to fill. */
.clutchSlot--cta{margin-bottom:10px}
.clutchSlot--cta .clutchSlot__fb{width:100%}

/* The Clutch tile is a <div>, not an <a>, because an iframe cannot live
   inside an anchor. It keeps every other .pcard rule; only the hover lift
   needs re-pointing, since that was written against a link. */
.pyramid .pcard--clutch{cursor:default}
.pyramid .pcard--clutch .pcard__in{gap:4px}

@media (max-width:980px){
  /* Below the split hero the pyramid becomes a row of three, which keeps the
     three cards the same size rather than stacking one wide over two narrow. */
  .pyramid{grid-auto-flow:column;justify-content:center}
  .pyramid__row{display:contents}
}
@media (max-width:520px){
  .pyramid{grid-auto-flow:row;--pcard:min(46vw,190px)}
  .pyramid__row{display:grid}
}
@media (prefers-reduced-motion:reduce){
  .pcard__in{transition:box-shadow .28s var(--ease),border-color .28s var(--ease)}
  .pyramid .pcard:hover .pcard__in{transform:none}
}

/* --- Slide 1 · legacy --- */
.slide__actions{display:flex;align-items:center;gap:20px;flex-wrap:wrap}
.slide__years{display:inline-flex;align-items:center;gap:11px;padding-left:20px;border-left:1px solid var(--hero-line)}
.slide__years b{font-size:1.875rem;font-weight:600;letter-spacing:-.03em;line-height:1;color:var(--hero-ink)}
.slide__years span{font-size:.6875rem;line-height:1.35;text-transform:uppercase;letter-spacing:.07em;color:var(--hero-body)}

/* --- Slide 2 · recognition --- */
.recog{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;max-width:940px}
.recog a{
  display:flex;flex-direction:column;gap:10px;height:100%;padding:16px 16px 14px;border-radius:var(--radius);
  background:var(--hero-surface);border:1px solid var(--hero-line);color:var(--hero-ink);
  box-shadow:0 8px 20px rgba(0,16,53,.05);
  transition:background .25s var(--ease),border-color .25s var(--ease),transform .25s var(--ease),box-shadow .25s var(--ease);
}
.recog a:hover{background:#fff;border-color:#C6D6F6;transform:translateY(-4px);color:var(--hero-ink);box-shadow:0 16px 30px rgba(0,16,53,.10)}
.recog__mark{font-size:1.125rem;font-weight:700;letter-spacing:-.02em;color:var(--hero-ink)}
.recog__txt{display:flex;flex-direction:column;gap:4px;font-size:.75rem;color:var(--hero-body)}
.recog__txt strong{font-size:.78rem;font-weight:600;color:var(--hero-ink)}
.recog__txt>span{display:inline-flex;align-items:center;gap:6px;color:var(--brand);font-weight:600}

/* --- Slides 3–5 · pillar + case study --- */
/* minmax(0,…) on both tracks, not a bare fr: an fr track resolves against its
   item's min-content width unless told otherwise, and one long unbroken token
   inside it (a filename in an empty gallery slot) then sets the whole
   layout's width. See the note further down where this used to live. */
.slide__inner--split{display:grid;grid-template-columns:minmax(0,1.08fr) minmax(0,.92fr);gap:clamp(26px,3.4vw,56px);align-items:center}
.ccard{
  display:flex;flex-direction:column;padding:22px 24px;border-radius:var(--radius-lg);color:var(--hero-ink);
  background:var(--hero-surface);border:1px solid var(--hero-line);box-shadow:0 14px 34px rgba(0,16,53,.08);
  transition:background .3s var(--ease),border-color .3s var(--ease),transform .3s var(--ease),box-shadow .3s var(--ease);
}
.ccard:hover{background:#fff;border-color:#C6D6F6;transform:translateY(-5px);color:var(--hero-ink);box-shadow:0 22px 44px rgba(0,16,53,.13)}
.ccard__tag{
  align-self:flex-start;margin-bottom:14px;padding:4px 11px;border-radius:999px;
  background:var(--brand-tint);border:1px solid #CFDCF5;
  font-size:.6563rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--brand-darker);
}
.ccard__metric{display:flex;flex-direction:column;gap:4px;padding-bottom:13px;margin-bottom:13px;border-bottom:1px solid var(--hero-line)}
.ccard__metric b{font-size:2.125rem;font-weight:600;line-height:1;letter-spacing:-.035em;color:var(--brand)}
.ccard__metric>span{font-size:.6875rem;letter-spacing:.07em;text-transform:uppercase;color:var(--hero-body)}
.ccard__title{font-size:1rem;font-weight:600;line-height:1.42;margin-bottom:6px;color:var(--hero-ink)}
.ccard__meta{font-size:.75rem;color:var(--hero-body);margin-bottom:14px}
.ccard__go{display:inline-flex;align-items:center;gap:8px;margin-top:auto;font-size:.8125rem;font-weight:600;color:var(--brand)}
.ccard__go .ico{transition:transform .25s var(--ease)}
.ccard:hover .ccard__go .ico{transform:translateX(4px)}

/* --- Minimal controls: bare chevrons + hairline dots --- */
.hero__controls{
  position:absolute;left:0;right:0;bottom:18px;z-index:2;
  display:flex;align-items:center;justify-content:center;gap:18px;
}
.heroBtn{
  width:28px;height:28px;display:grid;place-items:center;border:0;background:none;
  color:rgba(0,16,53,.5);transition:color .2s var(--ease),transform .2s var(--ease);
}
.heroBtn:hover{color:var(--brand)}
#heroPrev:hover{transform:translateX(-3px)}
#heroNext:hover{transform:translateX(3px)}
.hero__dots{display:flex;align-items:center;gap:7px}
.hero__dots button{
  width:6px;height:6px;border-radius:999px;background:rgba(0,16,53,.26);
  transition:width .35s var(--ease),background .35s var(--ease);
}
.hero__dots button:hover{background:rgba(0,16,53,.45)}
.hero__dots button.is-active{width:20px;background:var(--brand)}

/* Section accent rule */
.rule{display:block;width:44px;height:3px;border-radius:99px;margin-bottom:16px;
  background:linear-gradient(90deg,var(--brand),#9DB6FF)}
.rule--center{margin-inline:auto}
.rule--light{background:linear-gradient(90deg,#6C93FF,rgba(108,147,255,.25))}

/* Company overview — compact two-column read */
.overview{padding-block:var(--section-y-sm)}
.overview__inner{display:grid;grid-template-columns:.92fr 1.08fr;gap:clamp(28px,4vw,60px);align-items:start}
.overview__head{margin:0}
.overview__head .sec__title{margin-bottom:0;font-size:clamp(1.5rem,1.1rem + 1.4vw,2.125rem)}
.overview__body{display:grid;gap:14px}
.overview__lead{margin:0;font-size:1.0625rem;line-height:1.72;color:var(--ink)}
.overview__text{margin:0;font-size:.9375rem;line-height:1.72;color:var(--muted)}
.overview__marks{display:flex;flex-wrap:wrap;gap:10px;margin-top:6px}
.overview__marks li{
  display:inline-flex;align-items:center;gap:8px;padding:7px 14px;border-radius:999px;
  background:var(--brand-tint-2);border:1px solid var(--line);
  font-size:.8125rem;font-weight:600;color:var(--navy);
}
.overview__marks .ico{color:var(--brand)}

/* Stats ribbon — slim band with hairline dividers */
.stats{background:var(--navy);color:#fff;position:relative;overflow:hidden}
.stats::before{content:"";position:absolute;inset:0;background:radial-gradient(640px 220px at 18% 0%,rgba(55,99,231,.38),transparent 68%)}
.stats__grid{position:relative;display:grid;grid-template-columns:repeat(4,1fr);padding-block:22px}
.stat{display:flex;align-items:baseline;gap:10px;justify-content:center;padding-inline:14px;border-right:1px solid rgba(255,255,255,.12)}
.stat:last-child{border-right:0}
.stat b{font-size:1.5rem;font-weight:600;letter-spacing:-.025em;color:#fff;line-height:1.2}
.stat span{font-size:.75rem;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.6)}

/* Our services — three-column practice grid, SunTec blueprint: hook, summary,
   micro-features, CTA. */
.services{padding-block:var(--section-y) var(--section-y-sm);background:var(--brand-tint-2)}
.pillars{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}

/* HOVER HITBOX — read before changing anything here.
   The <article> is the grid cell, the hover target, and it never moves. Only
   `.pillar__card` inside it lifts. Transforming the hover target itself moves
   its own hitbox: with the pointer near the bottom edge the card slid out from
   under it, hover was lost, the card dropped back, hover was regained, and the
   card flickered at about 30 cycles a second. Any hover lift on this site puts
   the transform on a child of the element that owns :hover, or extends the hit
   area to cover the gap (see .hoverLift below). */
.pillar{display:flex}
.pillar__card{
  position:relative;overflow:hidden;display:flex;flex-direction:column;flex:1;
  background:#fff;border:1px solid var(--line);border-radius:var(--radius);
  padding:26px 24px 24px;box-shadow:var(--shadow-sm);
  transition:transform .3s ease-in-out,box-shadow .3s ease,border-color .3s ease;
  will-change:transform;
}
.pillar__card::before{
  content:"";position:absolute;inset:0 0 auto 0;height:3px;transform:scaleX(0);transform-origin:left;
  background:linear-gradient(90deg,var(--brand),#9DB6FF);transition:transform .38s var(--ease);
}
.pillar:hover .pillar__card{transform:translateY(-5px);box-shadow:var(--shadow);border-color:#CFDCF5}
.pillar:hover .pillar__card::before{transform:scaleX(1)}
.pillar__index{
  position:absolute;top:18px;right:22px;font-size:2rem;font-weight:700;line-height:1;
  letter-spacing:-.05em;color:var(--brand);opacity:.10;transition:opacity .3s var(--ease);
}
.pillar:hover .pillar__index{opacity:.18}
.pillar__icon{
  display:grid;place-items:center;width:46px;height:46px;margin-bottom:16px;border-radius:13px;
  background:var(--brand-tint);color:var(--brand);transition:background .3s var(--ease),color .3s var(--ease);
}
.pillar:hover .pillar__icon{background:var(--brand);color:#fff}
.pillar h3{font-size:1.1875rem;margin-bottom:.35em}
.pillar__hook{
  margin:0 0 10px;font-size:.9375rem;font-weight:600;line-height:1.45;
  letter-spacing:-.01em;color:var(--navy);
}
.pillar__body{margin:0 0 18px;font-size:.875rem;line-height:1.7;color:var(--muted)}
.pillar__list{
  padding-top:16px;border-top:1px solid var(--line);display:grid;gap:4px;margin-bottom:18px;
}
.pillar__list a{
  display:flex;align-items:flex-start;gap:9px;padding:3px 0;font-size:.8125rem;line-height:1.5;
  color:var(--ink);transition:color .2s var(--ease),transform .2s var(--ease);
}
/* micro-feature marker — a hairline tick drawn in CSS, no extra sprite use */
.pillar__list a::before{
  content:"";flex:none;width:6px;height:6px;margin-top:.5em;border-radius:50%;
  background:var(--brand);opacity:.45;transition:opacity .2s var(--ease);
}
.pillar__list a:hover{color:var(--brand);transform:translateX(3px)}
.pillar__list a:hover::before{opacity:1}
.pillar__more a{font-weight:600;color:var(--brand)}
.pillar__more a::before{opacity:0}
.pillar__cta{
  margin-top:auto;display:inline-flex;align-items:center;gap:7px;
  font-weight:600;font-size:.875rem;color:var(--brand);
}
.pillar__cta .ico{transition:transform .25s var(--ease)}
.pillar:hover .pillar__cta .ico{transform:translateX(4px)}

/* HOVER BUFFER — for cards that own their own :hover and cannot take a wrapper.
   A strip under the card that exists ONLY while the card is hovered, and is
   taller than the lift. That ordering is what makes it correct: the resting
   hover area is unchanged, and the hovered area is a strict superset of it, so
   a pointer that has triggered hover can never fall outside and start the
   on/off loop. A buffer present at rest just moves the unstable band down by
   its own height — measured, and it still flickered.
   Elements that clip their overflow cannot use this; they need a wrapper. */
.certcard,.recog a,.ccard,.mcard,.winCard,.ally,.btn,.ptab{position:relative}
.certcard::after,.recog a::after,.ccard::after,.mcard::after,
.winCard::after,.ally::after,.btn::after,.ptab::after{
  content:"";position:absolute;left:0;right:0;top:100%;height:0;
}
.certcard:hover::after,.recog a:hover::after,.ccard:hover::after,.mcard:hover::after,
.winCard:hover::after,.ally:hover::after,.btn:hover::after,.ptab:hover::after{height:10px}

.services__band{
  display:flex;align-items:center;justify-content:space-between;gap:22px;flex-wrap:wrap;
  margin-top:20px;padding:16px 24px;border-radius:var(--radius);
  background:linear-gradient(120deg,var(--brand-tint),#fff);border:1px solid #CFDCF5;
}
.services__band p{margin:0;font-size:.9125rem;color:var(--muted)}
.services__band strong{color:var(--navy)}

/* Client success stories — horizontal metric cards */
.work{padding-block:var(--section-y-sm)}
.tabs{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:26px}
.tab{
  display:inline-flex;align-items:center;gap:8px;padding:8px 16px;border-radius:999px;
  border:1.5px solid var(--line);background:#fff;font-size:.8125rem;font-weight:600;color:var(--muted);
  transition:all .25s var(--ease);
}
.tab i{font-style:normal;font-size:.6875rem;font-weight:700;padding:1px 7px;border-radius:999px;background:var(--grey);color:var(--muted)}
.tab:hover{border-color:var(--brand);color:var(--brand)}
.tab.is-active{background:var(--brand);border-color:var(--brand);color:#fff;box-shadow:0 6px 16px rgba(55,99,231,.24)}
.tab.is-active i{background:rgba(255,255,255,.22);color:#fff}

.story__grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.story{
  position:relative;display:flex;background:#fff;color:var(--ink);
  border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-sm);
  transition:transform .28s var(--ease),box-shadow .28s var(--ease),border-color .28s var(--ease);
}
.story::after{content:"";position:absolute;left:0;right:0;top:100%;height:0}
.story:hover::after{height:10px}
.story:hover{transform:translateY(-4px);box-shadow:var(--shadow);border-color:#CFDCF5;color:var(--ink)}
.story.is-hidden{display:none}
.story__metric{
  /* the card no longer clips, so the rail rounds its own outer corners */
  position:relative;overflow:hidden;border-radius:calc(var(--radius) - 1px) 0 0 calc(var(--radius) - 1px);
  flex:0 0 160px;display:flex;flex-direction:column;justify-content:center;
  padding:20px 18px;color:#fff;background:linear-gradient(140deg,var(--brand) 0%,var(--brand-darker) 100%);
}
.story__metric::after{
  content:"";position:absolute;right:-34px;bottom:-34px;width:110px;height:110px;border-radius:50%;
  background:rgba(255,255,255,.10);transition:transform .45s var(--ease);
}
.story:hover .story__metric::after{transform:scale(1.3)}
/* 1.5rem, down from 1.75rem. The rail is a fixed 160px and the longest figure
   on the homepage is $81,076.87 — at 1.75rem it ran the full width of its own
   padding, which is what made the set look cramped rather than emphatic. The
   label beneath is unchanged, so the size relationship between figure and
   caption still reads. */
.story__metric b{position:relative;font-size:1.5rem;font-weight:600;line-height:1;letter-spacing:-.035em}
.story__metric>span{position:relative;margin-top:7px;font-size:.6875rem;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.82);line-height:1.35}
.story__body{display:flex;flex-direction:column;flex:1;padding:18px 20px}
.story__meta{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-bottom:9px;font-size:.6875rem;color:var(--muted)}
.story__tag{padding:3px 9px;border-radius:999px;background:var(--brand-tint);color:var(--brand-dark);font-weight:700;letter-spacing:.05em;text-transform:uppercase}
.story__title{font-size:.9375rem;font-weight:600;line-height:1.45;color:var(--navy);letter-spacing:-.01em}
.story__go{display:inline-flex;align-items:center;gap:7px;margin-top:auto;padding-top:12px;font-size:.8125rem;font-weight:600;color:var(--brand)}
.story__go .ico{transition:transform .25s var(--ease)}
.story:hover .story__go .ico{transform:translateX(4px)}
.work__more{display:flex;justify-content:center;margin-top:28px}

/* Our clients — dual-direction marquee */
.clients{padding-block:var(--section-y-sm) clamp(40px,4.6vw,66px);background:var(--brand-tint-2);overflow:hidden}
.marquee{
  display:grid;gap:18px;margin-top:4px;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
}
.marquee__row{overflow:hidden}
.marquee__track{display:flex;gap:18px;width:max-content;animation:slide 46s linear infinite}
.marquee__row--reverse .marquee__track{animation-direction:reverse}
.marquee:hover .marquee__track{animation-play-state:paused}
@keyframes slide{from{transform:translateX(0)}to{transform:translateX(-50%)}}
/* The global reduced-motion rule sets animation-duration to .01ms on
   everything. On a loop set to `infinite` that does not stop the motion — it
   runs the whole cycle a hundred times a second, which is a flicker rather
   than a marquee and is worse than the animation it was meant to spare the
   viewer. Stop it outright and let the row sit still; the cards are all still
   there and the row scrolls horizontally if anyone wants them. */
@media (prefers-reduced-motion:reduce){
  .marquee__track{animation:none!important}
  .marquee__row{overflow-x:auto}
}
/* Client logo cards. The wordmarks these replaced were invented placeholders;
   these are real client marks, so the card now holds an <img> rather than text.
   Sizing is Rick's spec: the mark is capped at 40x140 and contained, never
   cropped or stretched, and the card keeps a fixed footprint so a wide
   lock-up and a square badge occupy the same space and the row reads evenly. */
.mlogo{
  flex:none;display:grid;place-items:center;min-width:216px;padding:16px 24px;
  background:#fff;border:1px solid var(--line);border-radius:14px;
  font-weight:700;font-size:1rem;letter-spacing:.02em;color:#8D9AB2;white-space:nowrap;
  transition:color .25s var(--ease),border-color .25s var(--ease),box-shadow .25s var(--ease);
}
.mlogo:hover{color:var(--navy);border-color:#CFDCF5;box-shadow:var(--shadow-sm)}

.client-logo-card{min-height:72px}
.client-logo-img{
  display:block;max-height:40px;max-width:140px;width:auto;height:auto;
  object-fit:contain;
  /* Grey by default so thirty-five different brand palettes read as one row;
     full colour on hover, which also rewards a visitor for looking. */
  filter:grayscale(100%) opacity(.7);
  transition:filter .3s ease,opacity .3s ease;
}
.client-logo-card:hover .client-logo-img{filter:grayscale(0%) opacity(1)}
/* A hover that only fires on the card the pointer is over would freeze the
   marquee under it and leave the rest grey; the row already pauses on hover
   (.marquee:hover), so this is the state a visitor actually sees. */
@media (hover:none){
  .client-logo-img{filter:grayscale(100%) opacity(.8)}
}

/* Testimonials — platform tabs */
.quotes{padding-block:clamp(44px,5vw,72px) var(--section-y-sm);background:var(--navy);color:#fff;position:relative;overflow:hidden}
.quotes::before{content:"";position:absolute;inset:0;background:radial-gradient(800px 380px at 85% 5%,rgba(55,99,231,.38),transparent 62%)}
.quotes .container{position:relative}
.quotes .sec__title{color:#fff;font-size:clamp(1.5rem,1.1rem + 1.4vw,2.125rem)}
.quotes .sec__head{margin-bottom:26px}

.ptabs{display:flex;justify-content:center;gap:10px;flex-wrap:wrap;margin-bottom:26px}
.ptab{
  display:inline-flex;align-items:center;gap:10px;padding:9px 18px;border-radius:999px;
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.16);
  color:rgba(255,255,255,.76);font-size:.875rem;font-weight:600;
  transition:background .25s var(--ease),border-color .25s var(--ease),color .25s var(--ease),transform .2s var(--ease);
}
.ptab:hover{background:rgba(255,255,255,.12);color:#fff;transform:translateY(-2px)}
.ptab.is-active{background:#fff;border-color:#fff;color:var(--navy)}
.ptab__score{display:inline-flex;align-items:center;gap:5px;font-size:.75rem;font-weight:700;color:#F6B93B}
.ptab.is-active .ptab__score{color:#D98A0B}

.panel[hidden]{display:none}
.panel{animation:fadeUp .4s var(--ease)}
@keyframes fadeUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.qgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.qcard{
  margin:0;display:flex;flex-direction:column;padding:22px 24px;border-radius:var(--radius);
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);backdrop-filter:blur(10px);
}
.qcard__stars{display:inline-flex;gap:3px;color:#F6B93B;margin-bottom:14px}
.qcard__stars .is-off{color:rgba(255,255,255,.22)}
.qcard blockquote{margin:0 0 18px;font-size:.9375rem;line-height:1.65;color:rgba(255,255,255,.9)}
.qcard figcaption{display:flex;align-items:center;gap:12px;margin-top:auto;padding-top:16px;border-top:1px solid rgba(255,255,255,.14)}
.qcard figcaption>span:last-child{display:flex;flex-direction:column;min-width:0}
.qcard figcaption strong{font-size:.875rem}
.qcard figcaption span span{font-size:.75rem;color:rgba(255,255,255,.58)}
.qcard__av{
  width:40px;height:40px;flex:none;border-radius:50%;display:grid;place-items:center;
  background:linear-gradient(140deg,#4E7BFF,#2A4FC4);font-weight:700;font-size:.8125rem;
  box-shadow:0 0 0 3px rgba(78,123,255,.2);
}
.quotes__note{margin:24px 0 0;text-align:center;font-size:.75rem;color:rgba(255,255,255,.5)}

/* Our alliances */
.alliances{padding-block:var(--section-y-sm) var(--section-y)}
.ally__label{display:flex;align-items:center;gap:18px;margin:0 0 20px;font-size:.75rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}
.ally__label::after{content:"";flex:1;height:1px;background:var(--line)}
.ally__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin-bottom:36px}
/* Three verified credentials, not four slots (Rick, 30 Sep 2026). */
.ally__grid--three{grid-template-columns:repeat(3,1fr)}
.ally{
  background:var(--brand-tint-2);border:1px solid var(--line);border-radius:var(--radius);padding:22px 20px;
  transition:transform .3s var(--ease),box-shadow .3s var(--ease),background .3s var(--ease),border-color .3s var(--ease);
}
.ally:hover{transform:translateY(-4px);background:#fff;border-color:#CFDCF5;box-shadow:var(--shadow)}
/* The three credential cards are links now (Rick, 7 Oct 2026) — the two ISO
   cards to /iso-certification, the Clutch card to the live profile. They were
   <article> elements, so the anchor needs `display:block` to keep the card
   shape, and `color:inherit` so the heading and body do not repaint link blue.
   Nothing else about the card changes. */
a.ally{display:block;color:inherit;text-decoration:none}
a.ally:focus-visible{outline:3px solid var(--brand);outline-offset:3px}
.ally__icon{
  display:grid;place-items:center;width:42px;height:42px;margin-bottom:13px;border-radius:12px;
  background:#fff;border:1px solid var(--line);color:var(--brand);
  transition:background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease);
}
.ally:hover .ally__icon{background:var(--brand);color:#fff;border-color:var(--brand)}
.ally h3{font-size:1rem;margin-bottom:.35em}
.ally p{font-size:.8125rem;line-height:1.55;color:var(--muted);margin-bottom:13px}
.ally__state{display:inline-flex;align-items:center;gap:7px;font-size:.6875rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#0E7C4A}
.ally__plats{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:24px}
.ally__plats li{
  display:inline-flex;align-items:center;gap:9px;padding:10px 16px;background:#fff;
  border:1px solid var(--line);border-radius:999px;font-size:.8125rem;font-weight:500;color:var(--navy);
  transition:border-color .25s var(--ease),background .25s var(--ease),color .25s var(--ease);
}
.ally__plats li:hover{border-color:var(--brand);background:var(--brand-tint-2);color:var(--brand)}
.ally__plats .ico{color:var(--brand)}
.ally__note{
  display:flex;align-items:flex-start;gap:11px;margin:0;padding:13px 16px;
  background:var(--grey);border:1px dashed #C9D5EA;border-radius:var(--radius-sm);
  font-size:.75rem;line-height:1.6;color:var(--muted);
}
.ally__note .ico{flex:none;margin-top:4px;color:var(--brand)}

/* Footer */
.footer{background:var(--navy);color:rgba(255,255,255,.66);font-size:.9125rem}
/* Five cells: brand, Services, About Us, Help & Support, Contact. Rev 49
   replaced the old Company / Help & Support / More trio with two columns, so
   About Us is the tall one and gets the wider track. */
/* Contact takes the widest track from rev 66: it now carries a three-line
   postal address, and at the old 1.1fr every line of it wrapped. */
.footer__top{display:grid;grid-template-columns:1.2fr .85fr 1fr .85fr 1.5fr;
  gap:clamp(22px,2.2vw,34px);padding-block:clamp(48px,6vw,72px)}
.footer h3{color:#fff;font-size:.9375rem;letter-spacing:.04em;text-transform:uppercase;margin-bottom:20px}
.footer a{color:rgba(255,255,255,.66)}
.footer a:hover{color:#fff}
.footer__brand p{margin:20px 0 22px;font-size:.9125rem;max-width:34ch}
.footer__col ul{display:grid;gap:11px}

.footer__contact ul{gap:14px;margin-bottom:24px}
.footer__contact li{display:flex;align-items:flex-start;gap:10px}
.footer__contact .ico{color:#7E9EFF;margin-top:5px}
.social{display:flex;gap:10px}
.social a{width:38px;height:38px;border-radius:10px;border:1px solid rgba(255,255,255,.18);display:grid;place-items:center;transition:all .25s var(--ease)}
.social a:hover{background:var(--brand);border-color:var(--brand);color:#fff}
.footer__bottom{display:flex;justify-content:space-between;align-items:center;gap:20px;flex-wrap:wrap;padding-block:22px;border-top:1px solid rgba(255,255,255,.12);font-size:.8125rem}
.footer__bottom p{margin:0}
.footer__bottom ul{display:flex;gap:22px}

/* Back to top */
.toTop{
  position:fixed;right:22px;bottom:22px;z-index:70;width:46px;height:46px;border-radius:50%;
  background:var(--brand);color:#fff;display:grid;place-items:center;box-shadow:0 10px 26px rgba(55,99,231,.4);
  opacity:0;visibility:hidden;transform:translateY(12px);transition:all .3s var(--ease);
}
.toTop.is-show{opacity:1;visibility:visible;transform:none}
.toTop:hover{background:var(--brand-dark)}

/* ---------- 6. RESPONSIVE ---------- */
@media (max-width:1180px){
  .footer__top{grid-template-columns:1.4fr 1fr 1fr;gap:34px}
}
@media (max-width:1024px){
  /* The header collapses to a single sticky row: logo + burger.
     The ribbon keeps no box of its own — .nav becomes position:fixed, so
     .navbar__inner has no in-flow children and its height falls to zero. */
  .header{top:0}                          /* one row — nothing to scroll away */
  .utility{border-bottom:1px solid var(--line)}
  .utility__inner{padding-block:14px}
  .utility__tagline,.utility__right{display:none}
  .navbar{background:transparent;border:0;box-shadow:none}
  .navbar__inner{padding-inline:0}
  .nav__item{display:block}
  .nav__item--home{display:none}          /* the logo already goes home */
  .nav__item--about{margin-left:0}
  .nav__link{border-bottom:0;border-radius:10px}
  .nav__link--about{
    background:var(--grey-dark);color:var(--navy);border-left:0;border-right:0;
    border-radius:10px;padding:14px 13px;margin-top:8px;
  }
  .nav__item--about .drop{left:0;right:auto}
  .nav{
    position:fixed;inset:0 0 0 auto;width:min(380px,86vw);background:#fff;flex-direction:column;
    align-items:stretch;gap:0;padding:26px 22px 40px;overflow-y:auto;z-index:80;
    transform:translateX(100%);transition:transform .34s var(--ease);box-shadow:-18px 0 50px rgba(0,16,53,.16);
  }
  .nav.is-open{transform:none}
  .nav__list{flex-direction:column;align-items:stretch;gap:2px;margin-top:58px}
  .nav__link{width:100%;justify-content:space-between;padding:14px 12px;font-size:1rem}
  .nav__cta{display:flex;flex-direction:column;align-items:stretch;gap:12px;margin-top:24px;padding-top:22px;border-top:1px solid var(--line)}
  .nav__cta .btn{width:100%}
  .nav__ctaMail{padding-inline:2px}
  .burger{display:block;z-index:90}
  /* Panels become in-drawer accordions */
  .mega,.drop{
    position:static;opacity:1;visibility:visible;transform:none;box-shadow:none;border:0;border-radius:0;
    padding:0;min-width:0;max-height:0;background:transparent;
    /* `clip`, with `hidden` first as the fallback for older engines.
       THIS IS A TOUCH FIX, not a visual one — the two render identically.
       `overflow:hidden` makes a box a SCROLL CONTAINER: one the user cannot
       scroll, because there is no scrollbar and max-height pins it. On
       WebKit a touch drag that begins inside such a box is swallowed by it
       and does not chain out to the scrollable ancestor, so the drawer
       freezes. Every menu item lives inside one of these panels, while the
       drawer's side padding does not — which is exactly the symptom: the
       blank margins scroll and the text does not.
       `overflow:clip` clips identically WITHOUT creating a scroll container,
       so there is nothing left to swallow the gesture. */
    overflow:hidden;
    overflow:clip;
    transition:max-height .35s var(--ease);
  }
  .has-mega.is-open .mega,.has-drop.is-open .drop{max-height:3400px}
  .mega .container{padding-inline:0}
  .mega__inner{padding:2px 0 14px}
  /* the accordion label already names the pillar, so the heading shrinks to
     what it is in the drawer: the link through to the pillar page */
  .mega__title{padding:6px 12px;font-size:.9375rem;color:var(--brand)}
  .mega__title .ico{width:15px;height:15px}
  /* the accordion label above already says "eCommerce", so in the drawer the
     heading spells out what it is: the way through to the pillar page */
  .mega__title span::before{content:"All "}
  .mega__title span::after{content:" services"}
  .mega__lead{padding:0 12px 12px;margin:0;border-bottom:1px solid var(--line)}
  .mega__links{grid-template-columns:1fr;gap:4px;margin-top:10px;padding-top:0;border-top:0}
  .mega__group{margin-bottom:4px}
  .mega__groupLink{padding:10px 12px}
  .mega__sub a{padding:7px 12px}
  .has-mega>.nav__link::after,.has-drop>.nav__link::after{display:none}
  .drop__list a{padding:12px 13px}
  .nav__caret{margin-left:auto}
  /* Sits below the header (z-index 60) so the drawer, which lives inside the
     header's stacking context, always stays on top of it. */
  .nav__backdrop{position:fixed;inset:0;background:rgba(0,16,53,.5);z-index:50;opacity:0;transition:opacity .3s var(--ease)}
  .nav__backdrop.is-open{opacity:1}


  /* Below the desktop breakpoint the banner takes a fixed height of its own —
     tall enough for the tallest slide, short enough not to swamp the fold. */
  .hero{--hero-h:520px}
  .slide{padding-bottom:50px}
  .slide__inner--split{grid-template-columns:1.04fr .96fr;gap:24px;align-items:center}
  .slide__copy{max-width:none}
  .slide__lead{margin-bottom:20px}
  .recog{grid-template-columns:1fr 1fr;max-width:560px}
  .ccard{padding:20px 22px}
  .ccard__metric b{font-size:2rem}
  .overview__inner{grid-template-columns:1fr;gap:22px}
  .pillars{grid-template-columns:1fr 1fr}
  .story__grid{grid-template-columns:1fr}
  .ally__grid{grid-template-columns:1fr 1fr}
  .qgrid{grid-template-columns:1fr 1fr}
  .qgrid .qcard:nth-child(3){grid-column:1/-1}
  .sec__lead--right{text-align:left;max-width:56ch}
  .stat{padding-inline:8px}
  .stat b{font-size:1.25rem}
  .stat span{font-size:.6875rem}
}
@media (max-width:860px){
  .utility__inner{gap:14px}
  .footer__top{grid-template-columns:1fr 1fr;gap:34px}
  .footer__brand{grid-column:1/-1}
  .stats__grid{grid-template-columns:1fr 1fr;row-gap:14px}
  .stat:nth-child(2n){border-right:0}
  .services__band{flex-direction:column;align-items:flex-start;gap:14px}
}
@media (max-width:640px){
  :root{--gutter:18px}
  .pillars,.ally__grid,.qgrid{grid-template-columns:1fr}
  .qgrid .qcard:nth-child(3){grid-column:auto}
  .story{flex-direction:column}
  .story__metric{flex:none;padding:16px 20px}
  /* stays a step under the desktop size, as it was before the reduction */
  .story__metric b{font-size:1.375rem}
  .mlogo{min-width:180px;padding:14px 20px;font-size:.9375rem}
  .client-logo-card{min-height:64px}
  .client-logo-img{max-height:34px;max-width:120px}
  .ptabs{gap:8px}
  .ptab{padding:8px 14px;font-size:.8125rem}
  .hero{--hero-h:550px}
  .slide__actions{gap:16px}
  .slide__years{display:none}
  .certgrid{gap:8px}
  .certcard{padding:12px 8px 11px;gap:5px;border-radius:13px}
  /* phones: the four certifications go 2-up and the Experience card drops —
     its numbers are already in the slide's own lead paragraph */
  .certgrid .certcard:first-child{display:none}
  .certcard--half,.certcard--third{grid-column:span 3}
  .certcard__icon .ico{width:24px;height:24px}
  .certcard__name{font-size:.75rem}
  .certcard__meta{font-size:.625rem}
  .certgrid__note{display:none}
  .recog{grid-template-columns:1fr 1fr;gap:8px}
  .recog a{padding:12px;gap:7px}
  .recog__mark{font-size:1rem}
  .recog__txt strong{font-size:.73rem}
  .slide__inner--split{grid-template-columns:1fr}
  /* the paired case-study card is dropped on phones so the pillar copy and its
     CTA stay above the fold inside the fixed banner height */
  .slide--pillar .ccard{display:none}
  /* flex-basis becomes a HEIGHT once the row turns into a column — reset both
     children or the split head opens a 480px hole between title and lead. */
  .sec__head--split{flex-direction:column;align-items:flex-start;gap:14px}
  .sec__head--split>div:first-child,.sec__lead--right{flex:0 0 auto}
  .footer__top{grid-template-columns:1fr}
  .footer__bottom{justify-content:center;text-align:center}
  .tabs{justify-content:flex-start;flex-wrap:nowrap;overflow-x:auto;padding-bottom:6px;-webkit-overflow-scrolling:touch}
  .tab{flex:none}
  .toTop{right:14px;bottom:14px}
}
@media (max-width:420px){
  .logo img{height:24px}
}

/* =========================================================
   7. PILLAR PAGE TEMPLATE
   One master layout shared by every Main Pillar landing page:
   breadcrumb · hero + floating win card · platform ribbon ·
   overview & experience · capability matrix · CTA band · FAQ.
   Every rule below is scoped to a pillar-page class, so nothing
   here can reach the homepage.
   ========================================================= */
.page--pillar{
  --p-ink:var(--navy);
  --p-body:var(--muted);
  --p-line:#DCE4F2;
  --p-surface:#fff;
}

/* --- Breadcrumb --- */
.crumbs{padding-top:18px}
.crumbs ol{display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-size:.8125rem;color:var(--p-body)}
.crumbs li{display:inline-flex;align-items:center;gap:8px}
.crumbs a{color:var(--p-body);font-weight:500}
.crumbs a:hover{color:var(--brand)}
.crumbs [aria-current="page"]{color:var(--navy);font-weight:600}
.crumbs .sep{width:12px;height:12px;color:#A9B4C8;flex:none}

/* --- Hero ---------------------------------------------------------------
   Same light wash as the homepage banner so the two read as one site. --- */
.pHero{position:relative;overflow:hidden;background:#fff;
  /* The Success Stories widget is the same component here as on the Level 2 and
     Level 3 pages, so the banner carries the same tokens and the same height
     floor. Everything about the panel — width, typography, carousel behaviour —
     comes from the one .stories block; only the containing block differs. */
  min-height:var(--hero-h);
  --stories-w:clamp(268px,21vw,312px);
  padding-bottom:clamp(34px,4vw,58px);border-bottom:1px solid var(--line)}
.pHero__bg{position:absolute;inset:0;z-index:0;overflow:hidden;
  background:
    radial-gradient(820px 420px at 80% 6%, rgba(55,99,231,.14), transparent 62%),
    radial-gradient(620px 420px at 2% 98%, rgba(35,72,190,.09), transparent 60%),
    linear-gradient(160deg,#FFFFFF 0%,#F7F9FF 54%,#ECF1FD 100%);
}
.pHero__bg::after{content:"";position:absolute;inset:0;opacity:.5;
  background-image:linear-gradient(rgba(0,16,53,.045) 1px,transparent 1px),linear-gradient(90deg,rgba(0,16,53,.045) 1px,transparent 1px);
  background-size:64px 64px;
  -webkit-mask-image:radial-gradient(70% 70% at 50% 35%,#000,transparent);
  mask-image:radial-gradient(70% 70% at 50% 35%,#000,transparent);
}
.pHero .grad{background:linear-gradient(100deg,var(--brand-darker),var(--brand) 85%);-webkit-background-clip:text;background-clip:text;color:transparent}
.pHero>.container{position:relative;z-index:1}
/* Heading first, on its own line and given room to breathe; the brief then
   runs horizontally beneath it in three columns rather than in one narrow
   block beside the artwork. */
.pHero__head{max-width:min(900px,66%);padding-top:clamp(22px,2.8vw,38px);margin-bottom:clamp(26px,3.4vw,46px)}
.pHero__body{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,.9fr);
  gap:clamp(24px,3vw,52px);align-items:start}
/* The third column used to hold a single hand-picked win card. The widget
   replaced it, and being out of flow it reserves its own room instead. */
.pHero__body--stories{padding-right:calc(var(--stories-w) + clamp(26px,2.8vw,52px))}
.pHero__title{font-size:clamp(1.9rem,1.1rem + 2.6vw,3rem);line-height:1.12;letter-spacing:-.025em;
  color:var(--p-ink);margin-bottom:0}
.pHero__lead{font-size:clamp(.95rem,.9rem + .3vw,1.125rem);color:var(--p-body);line-height:1.65;
  max-width:62ch;margin-bottom:22px}
.pHero__facts{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0}
.pHero__facts li{display:inline-flex;align-items:center;gap:8px;padding:7px 14px;border-radius:999px;
  background:rgba(255,255,255,.82);border:1px solid var(--p-line);
  font-size:.8125rem;font-weight:600;color:var(--navy)}
.pHero__facts .ico{width:15px;height:15px;color:var(--brand)}
.pHero__actions{display:flex;flex-wrap:wrap;align-items:center;gap:14px}

/* Category artwork — SVG scene on a 560x440 canvas. Since rev 27 it is a
   backdrop on the trailing half of the banner, masked so it fades out before
   it reaches the copy, instead of a column competing for the width. */
.pHero__scene{
  position:absolute;top:0;right:0;bottom:0;width:min(42%,700px);z-index:0;
  display:grid;place-items:center;pointer-events:none;opacity:.5;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 62%);
  mask-image:linear-gradient(90deg,transparent,#000 62%);
}
.pHero__art{display:block;width:100%;height:auto}
.pHero__art .st-float{animation:pFloat 7s ease-in-out infinite}
.pHero__art .st-float.d1{animation-delay:1.2s}
.pHero__art .st-float.d2{animation-delay:2.4s}
.pHero__art .st-spin{animation:pSpin 90s linear infinite;transform-box:fill-box;transform-origin:center}
.pHero__art .st-pulse{animation:pPulse 4.6s ease-in-out infinite}
@keyframes pFloat{50%{transform:translateY(-10px)}}
@keyframes pSpin{to{transform:rotate(360deg)}}
@keyframes pPulse{0%,100%{opacity:.35}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.pHero__art *{animation:none!important}}

/* --- Success-story card -------------------------------------------------
   Up to rev 26 this floated over the foot of the hero on an absolutely
   positioned rail. It is now simply the hero's third column, which removes
   the overlap arithmetic and the padding the ribbon had to reserve for it. */
.winCard{
  width:100%;
  display:flex;flex-direction:column;gap:2px;padding:20px 22px 18px;
  border-radius:var(--radius-lg);background:var(--p-surface);
  border:1px solid var(--p-line);box-shadow:0 22px 48px rgba(0,16,53,.14);
  color:var(--p-ink);transition:transform .3s var(--ease),box-shadow .3s var(--ease),border-color .3s var(--ease);
}
.winCard:hover{transform:translateY(-4px);color:var(--p-ink);border-color:#C6D6F6;box-shadow:0 28px 58px rgba(0,16,53,.18)}
.winCard__tag{align-self:flex-start;margin-bottom:12px;padding:4px 11px;border-radius:999px;
  background:var(--brand-tint);border:1px solid #CFDCF5;font-size:.6563rem;font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;color:var(--brand-darker)}
.winCard__metric{display:flex;align-items:baseline;gap:10px}
.winCard__metric b{font-size:2.125rem;font-weight:600;line-height:1;letter-spacing:-.035em;color:var(--brand)}
.winCard__metric span{font-size:.75rem;line-height:1.35;color:var(--p-body)}
.winCard__title{margin:12px 0 6px;font-size:.9375rem;font-weight:600;line-height:1.45;color:var(--p-ink)}
.winCard__meta{font-size:.75rem;color:var(--p-body);margin-bottom:12px}
.winCard__go{display:inline-flex;align-items:center;gap:8px;font-size:.8125rem;font-weight:600;color:var(--brand)}
.winCard__go .ico{transition:transform .25s var(--ease)}
.winCard:hover .winCard__go .ico{transform:translateX(4px)}

/* --- Platform / ecosystem ribbon --- */
.ribbon{background:var(--white);border-bottom:1px solid var(--line);padding-block:30px}
.ribbon__label{margin:0 0 18px;text-align:center;font-size:.75rem;font-weight:600;
  letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}
.ribbon__grid{display:flex;flex-wrap:wrap;justify-content:center;gap:10px 12px}
.ribbon__grid li{display:flex}
.ribbon__item{display:inline-flex;align-items:center;gap:9px;padding:10px 18px;border-radius:12px;cursor:default;
  background:var(--brand-tint-2);border:1px solid var(--line);
  font-size:.875rem;font-weight:600;color:var(--navy);letter-spacing:-.01em;
  transition:background .2s var(--ease),border-color .2s var(--ease),transform .2s var(--ease)}
.ribbon__item .ico{width:16px;height:16px;color:var(--brand)}
.ribbon__item:hover{background:#fff;border-color:#C6D6F6;color:var(--navy)}

/* --- Overview & experience --- */
.pOverview{padding-block:var(--section-y-sm)}
.pOverview__inner{display:grid;grid-template-columns:1.02fr .98fr;gap:clamp(28px,4vw,64px);align-items:start}
.pOverview__copy p{max-width:66ch;color:var(--muted);line-height:1.75;margin-bottom:1rem}
.pOverview__copy p:last-of-type{margin-bottom:22px}
.pOverview__stats{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:22px}
.pStat{padding:18px 20px;border-radius:var(--radius);background:var(--brand-tint-2);border:1px solid var(--line)}
.pStat b{display:block;font-size:1.75rem;font-weight:600;letter-spacing:-.03em;line-height:1.1;color:var(--brand)}
.pStat span{display:block;margin-top:4px;font-size:.8125rem;line-height:1.4;color:var(--muted)}
.pPoints{display:grid;gap:12px}
.pPoints li{display:flex;gap:12px;font-size:.9375rem;line-height:1.6;color:var(--ink)}
.pPoints .ico{width:20px;height:20px;flex:none;margin-top:3px;color:var(--brand)}
.pPoints strong{color:var(--navy)}

/* --- Capability matrix --- */
.matrix{padding-block:var(--section-y-sm);background:var(--brand-tint-2);border-block:1px solid var(--line)}
.matrix__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
/* Four categories 3-up leaves an orphan on the second row; 4-up fills it. */
.matrix__grid--4{grid-template-columns:repeat(4,1fr)}
.mcard{display:flex;flex-direction:column;padding:24px 24px 22px;border-radius:var(--radius);
  background:#fff;border:1px solid var(--line);will-change:transform;
  transition:transform .3s ease-in-out,box-shadow .3s ease,border-color .3s ease}
.mcard:hover{transform:translateY(-4px);border-color:#C6D6F6;box-shadow:var(--shadow)}
/* Arriving from a mega-menu deep link — make it obvious which card was meant. */
.mcard:target{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-tint),var(--shadow)}
.mcard:target .mcard__icon{background:var(--brand);color:#fff}
.mcard__icon{display:grid;place-items:center;width:42px;height:42px;margin-bottom:15px;
  border-radius:12px;background:var(--brand-tint);color:var(--brand);
  transition:background .25s var(--ease),color .25s var(--ease)}
.mcard:hover .mcard__icon{background:var(--brand);color:#fff}
.mcard__title{font-size:1.0625rem;font-weight:600;letter-spacing:-.015em;color:var(--navy);margin:0 0 8px}
.mcard__lead{font-size:.875rem;line-height:1.6;color:var(--muted);margin:0 0 14px}
.mcard__list{display:grid;gap:7px;margin-bottom:18px}
.mcard__list li{display:flex;gap:9px;font-size:.8125rem;line-height:1.5;color:var(--ink)}
.mcard__list .ico{width:14px;height:14px;flex:none;margin-top:3px;color:var(--brand)}
.mcard__more{font-size:.75rem;color:var(--muted);padding-left:23px}
.mcard__go{display:inline-flex;align-items:center;gap:8px;margin-top:auto;padding-top:14px;
  border-top:1px solid var(--line);font-size:.875rem;font-weight:600;color:var(--brand)}
.mcard__go .ico{transition:transform .25s var(--ease)}
.mcard:hover .mcard__go .ico{transform:translateX(4px)}

/* --- CTA band --- */
.faq{padding-block:var(--section-y-sm) var(--section-y)}
.faq__grid{display:grid;grid-template-columns:.86fr 1.14fr;gap:clamp(28px,4vw,56px);align-items:start}
.faq__list{display:grid;gap:10px}
.faqItem{border:1px solid var(--line);border-radius:14px;background:#fff;overflow:hidden;
  transition:border-color .25s var(--ease),box-shadow .25s var(--ease)}
.faqItem.is-open{border-color:#C6D6F6;box-shadow:var(--shadow-sm)}
.faqItem h3{margin:0;font-size:1rem}
.faqQ{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;width:100%;
  padding:16px 20px;text-align:left;font-size:.9375rem;font-weight:600;line-height:1.5;color:var(--navy);
  transition:color .2s var(--ease)}
.faqQ:hover{color:var(--brand)}
.faqQ .ico{width:18px;height:18px;flex:none;margin-top:3px;color:var(--brand);
  transition:transform .3s var(--ease)}
.faqItem.is-open .faqQ .ico{transform:rotate(45deg)}
.faqA{max-height:0;overflow:hidden;transition:max-height .35s var(--ease)}
.faqA>div{padding:0 20px 18px;font-size:.9375rem;line-height:1.7;color:var(--muted)}
.faqA p{margin:0 0 .8rem}
.faqA p:last-child{margin:0}
.faq__aside{padding:24px;border-radius:var(--radius);background:var(--brand-tint-2);border:1px solid var(--line)}
.faq__aside h3{font-size:1.0625rem;margin-bottom:.5em}
.faq__aside p{font-size:.875rem;color:var(--muted);line-height:1.65;margin-bottom:16px}

/* --- Pillar template responsive --- */
@media (max-width:1024px){
  .pHero__body{grid-template-columns:1fr;gap:24px}
  .pHero__head{margin-bottom:24px}
  .pHero__facts{flex-direction:row;flex-wrap:wrap}
  .pHero__scene{display:none}          /* the stacked hero has no free half */
  .winCard{max-width:420px}
  .pOverview__inner{grid-template-columns:1fr;gap:26px}
  .matrix__grid{grid-template-columns:repeat(2,1fr)}
  .faq__grid{grid-template-columns:1fr;gap:26px}
}
@media (max-width:640px){
  .crumbs ol{font-size:.75rem}
  .matrix__grid{grid-template-columns:1fr}
  .pOverview__stats{grid-template-columns:1fr 1fr;gap:10px}
  .pStat{padding:14px 16px}
  .pStat b{font-size:1.5rem}
}

/* =========================================================
   SERVICE PAGES — Level 2 hubs and Level 3 capabilities
   Sections: hero (+ conditional case-study rail) · body with a sticky
   Related Services rail · capability cards · workflow · callout ·
   platform grid · FAQ · two floating docks.
   Shares .matrix, .mcard, .faq and .crumbs with the pillar template.
   ========================================================= */

/* --- Hero --- */
.sHero{position:relative;overflow:hidden;background:#fff;
  /* the same banner height as the homepage hero, as a floor rather than a fixed
     height — a long lead may still push it taller, it just may not come out
     shorter and leave the floating widget hanging past the bottom edge */
  min-height:var(--hero-h);
  --stories-w:clamp(268px,21vw,312px);
  padding-bottom:clamp(30px,3.4vw,48px);border-bottom:1px solid var(--line)}
.sHero__bg{position:absolute;inset:0;z-index:0;
  background:
    radial-gradient(760px 380px at 82% 4%, rgba(55,99,231,.13), transparent 62%),
    radial-gradient(560px 380px at 0% 96%, rgba(35,72,190,.08), transparent 60%),
    linear-gradient(160deg,#FFFFFF 0%,#F7F9FF 58%,#EDF1FD 100%);
}
.sHero__bg::after{content:"";position:absolute;inset:0;opacity:.45;
  background-image:linear-gradient(rgba(0,16,53,.045) 1px,transparent 1px),linear-gradient(90deg,rgba(0,16,53,.045) 1px,transparent 1px);
  background-size:64px 64px;
  -webkit-mask-image:radial-gradient(70% 70% at 50% 35%,#000,transparent);
  mask-image:radial-gradient(70% 70% at 50% 35%,#000,transparent);
}
.sHero>.container{position:relative;z-index:1}
.sHero .grad{background:linear-gradient(100deg,var(--brand-darker),var(--brand) 85%);-webkit-background-clip:text;background-clip:text;color:transparent}
.sHero__head{max-width:min(880px,70%);padding-top:clamp(18px,2.4vw,32px);margin-bottom:clamp(22px,2.8vw,38px)}
.sHero__title{font-size:clamp(1.75rem,1.05rem + 2.3vw,2.75rem);line-height:1.13;
  letter-spacing:-.025em;color:var(--navy);margin:0}
/* Only a hero that actually carries the widget reserves room for it. The
   generator adds the modifier when it emits the panel, so a page with no
   mapped stories — and the Client Success Stories hub, which has none by
   definition — does not get a 340px hole down its right-hand side. */
.sHero__body--stories{
  padding-right:calc(var(--stories-w) + clamp(26px,2.8vw,52px))}
.sHero__lead{font-size:clamp(.95rem,.9rem + .3vw,1.0625rem);line-height:1.68;
  color:var(--muted);max-width:62ch;margin:0 0 20px}
.sHero__facts{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 24px}
.sHero__facts li{display:inline-flex;align-items:center;gap:8px;padding:7px 14px;border-radius:999px;
  background:rgba(255,255,255,.85);border:1px solid #DCE4F2;
  font-size:.8125rem;font-weight:600;color:var(--navy)}
.sHero__facts .ico{width:15px;height:15px;color:var(--brand)}
.sHero__actions{display:flex;flex-wrap:wrap;align-items:center;gap:14px}

/* --- Hero Success Stories widget (omitted when nothing is mapped) ---
   The SunTec reference: a compact portrait panel floated over the right of the
   hero graphic, showing exactly ONE story at a time. The slides are stacked in
   the same box and cross-faded on a timer; only the visible one is in the
   layout's height, so the panel never resizes between stories.

   It is deliberately small. It sits beside the H1 and the primary CTA and must
   not compete with them, so its width is capped and its card is a portrait:
   cover, tag, headline, one clamped line of summary, Read More. */
.stories{
  /* Centred on the banner itself.

     The containing block is .sHero — the whole banner. That is why the markup
     puts this panel beside .sHero's container rather than inside it: the
     container is itself positioned (it has to be, to sit above the background
     artwork), so a panel inside it centres on the copy instead of on the
     banner and ends up sitting high.

     That choice costs one thing: .sHero runs the full viewport width, so
     `right:var(--gutter)` would align the panel to the window edge rather than
     to the content column. The max() below reproduces .container--wide's own
     arithmetic — half the leftover width, plus the gutter — so the panel's right
     edge lands exactly on the text column's right edge at every width, and falls
     back to the plain gutter once the viewport is narrower than the container. */
  position:absolute;z-index:2;width:var(--stories-w);
  right:max(var(--gutter), calc((100% - var(--container-wide)) / 2 + var(--gutter)));
  top:50%;transform:translateY(-50%);
  display:flex;flex-direction:column;background:var(--navy);color:#fff;
  border-radius:var(--radius-lg);padding:17px 17px 13px;
  box-shadow:0 26px 54px rgba(0,16,53,.26);overflow:hidden}
.stories::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(360px 200px at 92% 0%,rgba(55,99,231,.46),transparent 70%)}
.stories>*{position:relative}
/* The heading is 1.25rem — double what it was — so the head stacks rather than
   running the label and the strap along one line. At 20px, uppercase, the
   label alone measures ~195px against 268px of usable panel width; side by
   side with the strap it wrapped mid-word. Stacked, the two read as a title
   and its subtitle, which is what they are.

   Tracking comes down from .11em to .04em at the same time: wide letter-spacing
   is what makes 10px uppercase readable and what makes 20px uppercase look
   spaced out. The size doubles, the tracking does not. */
.stories__head{display:flex;flex-direction:column;align-items:flex-start;gap:3px;
  margin-bottom:13px}
.stories__label{margin:0;font-size:1.25rem;font-weight:700;letter-spacing:.04em;
  line-height:1.15;text-transform:uppercase;color:#9DB6FF}
.stories__strap{margin:0;font-size:.6875rem;line-height:1.3;color:rgba(255,255,255,.58)}

/* One slide deep. The deck is a grid with a single cell: every slide is placed
   in it, so the deck is exactly as tall as its tallest card and nothing jumps
   when the timer fires. */
.stories__viewport{position:relative}
.stories__deck{display:grid}
.storyCard{grid-area:1/1;opacity:0;transform:translateY(10px);pointer-events:none;
  transition:opacity .55s var(--ease),transform .55s var(--ease)}
.storyCard.is-on{opacity:1;transform:none;pointer-events:auto}
.storyCard a{position:relative;display:block;border-radius:var(--radius);
  background:#fff;color:var(--ink);overflow:hidden;
  transition:box-shadow .3s ease}
.storyCard a:hover{box-shadow:0 16px 32px rgba(0,16,53,.28);color:var(--ink)}

/* Generated cover, not a photograph: there is no story artwork in the source
   documents and none may be invented. Replace the gradient with a real image
   here the day the client supplies one. */
.storyCard__cover{display:grid;place-items:center;height:88px;color:#fff}
.storyCard__cover .ico{width:30px;height:30px;opacity:.9;stroke-width:1.4}
.storyCard__cover::after{content:"";position:absolute;left:0;right:0;top:0;height:88px;
  opacity:.5;
  background-image:linear-gradient(rgba(255,255,255,.14) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(255,255,255,.14) 1px,transparent 1px);
  background-size:26px 26px}
.storyCard__cover::after{background-size:22px 22px}
.storyCard__cover--1{background:linear-gradient(135deg,#2A4FC4,#4E7BFF)}
.storyCard__cover--2{background:linear-gradient(135deg,#1F3C9B,#3763E7)}
.storyCard__cover--3{background:linear-gradient(135deg,#0A2058,#2A4FC4)}

.storyCard__body{display:flex;flex-direction:column;gap:7px;padding:15px 16px 16px}
.storyCard__tag{align-self:flex-start;padding:3px 8px;border-radius:5px;
  background:var(--brand-tint);color:var(--brand-dark);line-height:1.3;
  font-size:.5625rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase}
.storyCard__title{font-size:.875rem;font-weight:600;line-height:1.38;color:var(--navy);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.storyCard__sum{font-size:.75rem;line-height:1.5;color:var(--muted);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.storyCard__go{display:inline-flex;align-items:center;gap:6px;margin-top:2px;
  font-size:.75rem;font-weight:600;color:var(--brand)}
.storyCard__go .ico{transition:transform .25s var(--ease)}
.storyCard a:hover .storyCard__go .ico{transform:translateX(4px)}

.stories__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-top:13px;padding-top:12px;border-top:1px solid rgba(255,255,255,.14)}
.stories__dots{display:inline-flex;align-items:center;gap:6px}
.stories__dot{width:6px;height:6px;padding:0;border-radius:999px;background:rgba(255,255,255,.3);
  transition:width .35s var(--ease),background .35s var(--ease)}
.stories__dot:hover{background:rgba(255,255,255,.6)}
.stories__dot.is-on{width:16px;background:#9DB6FF}
.stories__all{display:inline-flex;align-items:center;gap:6px;font-size:.75rem;font-weight:600;
  color:#fff}
.stories__all:hover{color:#9DB6FF}
.stories__all .ico{transition:transform .25s var(--ease)}
.stories__all:hover .ico{transform:translateX(3px)}
@media (prefers-reduced-motion:reduce){
  .storyCard{transition:none}
}

/* --- Body grid with the sticky rail --- */
.sBody{padding-block:clamp(36px,4vw,60px)}
.sBody__grid{display:grid;grid-template-columns:minmax(0,1fr) 288px;gap:clamp(28px,3.4vw,56px);align-items:start}
.sBody__main>section{margin-bottom:clamp(34px,4vw,56px)}
.sBody__main>section:last-child{margin-bottom:0}
.prose p{color:var(--muted);line-height:1.78;max-width:68ch;margin-bottom:1rem}
.prose p:last-child{margin-bottom:0}
.sBody .sec__title{font-size:clamp(1.3rem,1.05rem + .9vw,1.75rem)}

/* capability cards inside the body */
.caps__grid{display:grid;grid-template-columns:repeat(2,1fr);gap:16px}
.cap{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:20px 20px 18px;
  box-shadow:var(--shadow-sm)}
.cap__icon{display:grid;place-items:center;width:38px;height:38px;margin-bottom:12px;border-radius:11px;
  background:var(--brand-tint);color:var(--brand)}
.cap h3{font-size:1rem;margin-bottom:.4em}
.cap p{margin:0;font-size:.875rem;line-height:1.65;color:var(--muted)}

/* workflow */
.flow__list{display:grid;gap:14px;counter-reset:flow}
.flow__step{display:flex;gap:16px;padding:18px 20px;border-radius:var(--radius);
  background:var(--brand-tint-2);border:1px solid var(--line)}
.flow__n{flex:none;font-size:.875rem;font-weight:700;color:var(--brand);letter-spacing:.04em;
  padding-top:2px}
.flow__step h3{font-size:.9375rem;margin-bottom:.35em}
.flow__step p{margin:0;font-size:.875rem;line-height:1.65;color:var(--muted)}

/* ROI callout */
.callout{position:relative;overflow:hidden;padding:26px 28px;border-radius:var(--radius-lg);
  background:linear-gradient(140deg,var(--navy),var(--navy-2));color:#fff;
  margin-bottom:clamp(34px,4vw,56px)}
.callout::after{content:"";position:absolute;right:-70px;top:-70px;width:240px;height:240px;
  border-radius:50%;background:rgba(55,99,231,.28)}
.callout h2{position:relative;color:#fff;font-size:clamp(1.15rem,1rem + .7vw,1.5rem);margin-bottom:.45em}
.callout p{position:relative;margin:0 0 16px;color:rgba(255,255,255,.82);font-size:.9375rem;line-height:1.7;max-width:64ch}
.callout__list{position:relative;display:grid;gap:9px}
.callout__list li{display:flex;gap:11px;font-size:.875rem;line-height:1.55;color:#fff}
.callout__list .ico{width:18px;height:18px;flex:none;margin-top:2px;color:#9DB6FF}

/* platform grid */
.plats__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:18px}
.plat{display:flex;flex-direction:column;gap:3px;padding:14px 16px;border-radius:var(--radius-sm);
  background:#fff;border:1px solid var(--line);transition:border-color .25s var(--ease),box-shadow .25s var(--ease)}
.plat:hover{border-color:#C6D6F6;box-shadow:var(--shadow-sm)}
.plat strong{font-size:.875rem;color:var(--navy)}
.plat span{font-size:.75rem;line-height:1.5;color:var(--muted)}

/* --- Sticky Related Services rail --- */
.rail{position:sticky;top:96px;align-self:start}
.rail__inner{padding:20px;border-radius:var(--radius);background:var(--brand-tint-2);border:1px solid var(--line)}
.rail__label{margin:0 0 14px;font-size:.6875rem;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--brand)}
.rail__list{display:grid;gap:2px;margin-bottom:14px}
.rail__list a{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;
  padding:9px 10px;border-radius:9px;font-size:.8125rem;line-height:1.45;color:var(--ink);
  transition:background .2s var(--ease),color .2s var(--ease)}
.rail__list a:hover{background:#fff;color:var(--brand)}
.rail__list .ico{flex:none;margin-top:3px;opacity:0;transform:translateX(-4px);
  transition:opacity .2s var(--ease),transform .2s var(--ease);color:var(--brand)}
.rail__list a:hover .ico{opacity:1;transform:none}
.rail__all{display:inline-flex;align-items:center;gap:7px;padding-top:12px;
  border-top:1px solid var(--line);width:100%;font-size:.8125rem;font-weight:600;color:var(--brand)}

/* --- Floating docks --- */
.dock{position:fixed;right:22px;bottom:78px;z-index:75;display:flex;flex-direction:column;
  align-items:flex-end;gap:12px}
.dock__wa{position:relative;display:grid;place-items:center;width:50px;height:50px;border-radius:50%;
  background:#25D366;color:#fff;box-shadow:0 10px 26px rgba(37,211,102,.38);
  transition:transform .3s ease-in-out,box-shadow .3s ease}
.dock__wa .ico{width:26px;height:26px;stroke-width:1.6}
.dock__wa:hover{transform:translateY(-3px);color:#fff;box-shadow:0 16px 32px rgba(37,211,102,.46)}
.dock__wa::after{content:"";position:absolute;left:0;right:0;top:100%;height:0}
.dock__wa:hover::after{height:10px}
.dock__tip{position:absolute;right:calc(100% + 10px);white-space:nowrap;padding:5px 10px;border-radius:8px;
  background:var(--navy);color:#fff;font-size:.75rem;font-weight:600;opacity:0;pointer-events:none;
  transform:translateX(6px);transition:opacity .2s var(--ease),transform .2s var(--ease)}
.dock__wa:hover .dock__tip{opacity:1;transform:none}

.dock__tab{display:inline-flex;align-items:center;gap:9px;padding:13px 18px;border-radius:999px;
  background:var(--brand);color:#fff;font-weight:600;font-size:.875rem;
  box-shadow:0 10px 26px rgba(55,99,231,.4);
  transition:transform .3s ease-in-out,box-shadow .3s ease,background .2s var(--ease)}
.dock__tab:hover{transform:translateY(-3px);background:var(--brand-dark)}
.dock__contact.is-open .dock__tab{display:none}
.dock__panel{width:min(340px,calc(100vw - 44px));padding:18px 20px 20px;border-radius:var(--radius-lg);
  background:#fff;border:1px solid var(--line);box-shadow:var(--shadow-lg)}
.dock__panelHead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:6px}
.dock__panelHead p{margin:0;font-size:.9375rem;color:var(--navy)}
.dock__close{display:grid;place-items:center;width:30px;height:30px;border-radius:8px;color:var(--muted)}
.dock__close:hover{background:var(--grey);color:var(--navy)}
.dock__note{margin:0 0 14px;font-size:.8125rem;line-height:1.6;color:var(--muted)}
.dock__form{display:grid;gap:10px}
.dock__form label{display:grid;gap:5px;font-size:.75rem;font-weight:600;color:var(--navy)}
.dock__form input,.dock__form textarea{
  font:inherit;font-size:.875rem;padding:9px 11px;border-radius:9px;border:1px solid var(--line);
  background:var(--brand-tint-2);color:var(--ink);resize:vertical}
.dock__form input:focus,.dock__form textarea:focus{outline:2px solid var(--brand);outline-offset:1px;background:#fff}
.dock__alt{margin:12px 0 0;font-size:.75rem;color:var(--muted)}

/* --- Service page responsive --- */
@media (max-width:1100px){
  .sBody__grid{grid-template-columns:1fr}
  .rail{position:static}
  .rail__inner{padding:18px 20px}
  .rail__list{grid-template-columns:1fr 1fr;display:grid}
}
@media (max-width:1024px){
  .sHero__head{max-width:none}
  /* Below the desktop breakpoint there is no room beside the copy, so the
     widget stops floating and takes its place in the flow underneath it. The
     hero stops being a fixed-height banner at the same time — the content sets
     the height once it is stacked. */
  .sHero,.pHero{min-height:0}
  .sHero__body--stories,.pHero__body--stories{padding-right:0}
  .pHero__body{grid-template-columns:1fr}
  /* `relative`, never `static`: the panel's ::before is inset:0, so the moment
     .stories stops being a positioned box that glow resolves against the hero
     container instead and covers the whole banner — which swallowed clicks on
     the breadcrumb and the Talk to us button on every phone-width page. */
  /* Back in the flow, under the copy. It is a sibling of the hero's
     container now, so it carries the gutter itself. */
  .stories{position:relative;width:auto;max-width:420px;
    margin:26px var(--gutter) 0;right:auto;top:auto;transform:none}
  .caps__grid{grid-template-columns:1fr}
  .plats__grid{grid-template-columns:1fr 1fr}
}
@media (max-width:640px){
  .rail__list{grid-template-columns:1fr}
  .plats__grid{grid-template-columns:1fr}
  .dock{right:14px;bottom:70px;gap:10px}
  .dock__wa{width:44px;height:44px}
  .dock__wa .ico{width:23px;height:23px}
  .dock__tab{padding:11px 15px;font-size:.8125rem}
  .callout{padding:22px 20px}
}

/* --- Client Success Stories hub: pillar tabs + capability jump nav ---
   Rev 49. Two tiers, both sticky: tier 1 filters the directory to one Main
   Pillar, tier 2 jumps to a Level 3 capability inside it. The bar's own
   offset is measured in js/stories.js (the header is sticky at a negative
   top, so what it occupies once stuck is its height minus the utility bar)
   and published as --csnav-top; the sections' scroll-margin reads the same
   number, so a native anchor jump lands where the scripted one does. */
.csHub{padding-bottom:clamp(40px,5vw,72px);--csnav-top:60px;--csnav-h:104px}
.csNav{position:sticky;top:var(--csnav-top);z-index:40;background:rgba(255,255,255,.94);
  backdrop-filter:saturate(1.6) blur(8px);border-bottom:1px solid var(--line);
  box-shadow:0 6px 18px rgba(0,16,53,.05)}
.csNav__tabs{display:flex;gap:4px;overflow-x:auto;scrollbar-width:none;
  border-bottom:1px solid var(--line)}
.csNav__tabs::-webkit-scrollbar{display:none}
.csTab{position:relative;flex:0 0 auto;padding:15px 18px 13px;border:0;background:none;
  font:inherit;font-size:.9375rem;font-weight:600;color:var(--muted);cursor:pointer;
  white-space:nowrap;transition:color .2s ease,background .2s ease}
.csTab i{display:inline-block;margin-left:7px;padding:1px 7px;border-radius:999px;
  background:var(--grey);font-size:.6875rem;font-style:normal;font-weight:700;
  color:var(--muted);vertical-align:2px}
.csTab:hover{color:var(--navy);background:var(--brand-tint-2)}
.csTab.is-on{color:#fff;background:var(--brand)}
.csTab.is-on i{background:rgba(255,255,255,.22);color:#fff}
.csTab:focus-visible{outline:2px solid var(--brand);outline-offset:-3px}

/* tier 2. Two rows at rest; the pillar that overflows gets a Show all, which
   js/stories.js unhides only after measuring — at a narrow width more rails
   overflow than at 1920, and a button that lies about there being more is
   worse than no button. */
.csNav__rails{padding-block:10px}
.csRail{display:none;align-items:flex-start;gap:12px}
.csRail.is-on{display:flex}
.csRail__pills{display:flex;flex-wrap:wrap;gap:7px;max-height:4.9rem;overflow:hidden;flex:1 1 auto}
.csRail.is-open .csRail__pills{max-height:none}
.csPill{display:inline-flex;align-items:center;gap:6px;padding:6px 13px;border-radius:999px;
  background:var(--grey);border:1px solid transparent;font-size:.8125rem;font-weight:500;
  color:var(--ink);transition:background .2s ease,border-color .2s ease,color .2s ease}
.csPill:hover{background:var(--brand-tint);border-color:#C6D6F6;color:var(--brand-darker)}
.csPill i{font-style:normal;font-size:.6875rem;font-weight:700;color:var(--muted)}
.csPill:hover i{color:var(--brand)}
.csRail__more{flex:0 0 auto;padding:6px 4px;border:0;background:none;font:inherit;
  font-size:.8125rem;font-weight:600;color:var(--brand);cursor:pointer;white-space:nowrap}
.csRail__more i{font-style:normal;font-weight:400;color:var(--muted)}
.csRail__more:hover{text-decoration:underline}


/* Without the script every panel stays visible and the page is one long
   directory — the generator's `hidden` attribute is honoured only once
   stories.js has marked the hub live. */
/* Deliberately overrides the global `[hidden]{display:none !important}` in the
   reset: without JavaScript every panel renders, so the hub degrades to one
   long readable directory. Needs `!important` of its own to win, and the
   `.is-live` rule below needs it to win in turn. */
.csHub__panels .csPanel[hidden]{display:block !important}
.csHub.is-live .csPanel[hidden]{display:none !important}

/* Air between the pinned pill rail and the first band.
   This used to come from `.csHub__note`'s margins, and removing that note at
   rev 91 left the first heading sitting 1px under the rail. The spacing was a
   side effect of a paragraph nobody wanted; it belongs on the panels, where it
   survives whatever is or is not above them. */
.csHub__panels{padding-top:clamp(26px,3vw,42px)}

.csBand{margin-bottom:clamp(30px,3.4vw,46px);scroll-margin-top:calc(var(--csnav-top) + var(--csnav-h) + 14px)}
.csBand__head{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin-bottom:18px;
  padding-bottom:12px;border-bottom:2px solid var(--navy)}
.csBand__pillar{margin:0;font-size:.6875rem;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--brand)}
.csBand__head h2{margin:0;font-size:clamp(1.3rem,1.05rem + .8vw,1.75rem)}
.csBand__head h2 a{color:var(--navy)}
.csBand__head h2 a:hover{color:var(--brand)}

.csSec{margin-bottom:clamp(22px,2.4vw,32px);padding-top:4px;
  scroll-margin-top:calc(var(--csnav-top) + var(--csnav-h) + 14px)}
.csSec__head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:14px}
.csSec__head h3{margin:0;font-size:clamp(1rem,.92rem + .3vw,1.15rem)}
.csSec__head h3 a{color:var(--navy)}
.csSec__head h3 a:hover{color:var(--brand)}
.csSec__n{font-size:.75rem;color:var(--muted)}
.csSec__head::after{content:"";flex:1 1 60px;height:1px;background:var(--line)}
/* a pill that has just jumped here marks its landing, so the reader can see
   which of forty sections they were sent to */
.csSec.is-target .csSec__head h3 a{color:var(--brand)}
.csSec.is-target .csSec__head::after{background:var(--brand);height:2px}
.csSec__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}

.story3{position:relative;display:flex;flex-direction:column;gap:7px;padding:20px 20px 18px;
  border-radius:var(--radius);background:#fff;border:1px solid var(--line);box-shadow:var(--shadow-sm);
  color:var(--ink);transition:transform .3s ease-in-out,box-shadow .3s ease,border-color .3s ease}
a.story3:hover{transform:translateY(-4px);border-color:#C6D6F6;box-shadow:var(--shadow);color:var(--ink)}
/* hover-only buffer: the card lifts, so without it the pointer falls off its
   own bottom edge and the card strobes. Height 0 at rest. */
a.story3::after{content:"";position:absolute;left:0;right:0;top:100%;height:0}
a.story3:hover::after{height:10px}
.story3--soon{background:var(--brand-tint-2);box-shadow:none}
.story3__ref{font-size:.625rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--brand)}
.story3__title{font-size:.9375rem;font-weight:600;line-height:1.45;color:var(--navy)}
.story3__lead{font-size:.8125rem;line-height:1.6;color:var(--muted)}
.story3__metrics{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}
.story3__metrics .metric{display:flex;flex-direction:column;gap:1px;padding:7px 10px;
  border-radius:var(--radius-sm);background:var(--brand-tint-2);border:1px solid var(--brand-tint)}
.story3__metrics b{font-size:.8125rem;font-weight:700;color:var(--navy);line-height:1.2}
.story3__metrics i{font-style:normal;font-size:.625rem;line-height:1.3;color:var(--muted)}
.story3__go{display:inline-flex;align-items:center;gap:7px;margin-top:auto;padding-top:12px;
  font-size:.8125rem;font-weight:600;color:var(--brand)}
.story3__go .ico{transition:transform .25s var(--ease)}
a.story3:hover .story3__go .ico{transform:translateX(4px)}
.story3__soon{margin-top:auto;padding-top:12px;font-size:.75rem;font-weight:600;color:var(--muted)}

/* The hub's hero carries no widget and no CTA row, so it does not need the
   full banner height the service pages hold to. */
.sHero--compact{min-height:0;padding-bottom:clamp(20px,2.6vw,36px)}
.sHero--compact .sHero__head{margin-bottom:clamp(14px,1.8vw,22px)}

/* ---- the split hero on /submit-an-enquiry and /contact-us ---------------
   THE POINT OF THIS LAYOUT IS THE FOLD. The form used to sit in a section
   below the hero, so on a 1080p screen the first field was off-screen and on
   a phone it was two swipes down. Lead capture is the page's only job, so the
   form is the hero's right-hand column and everything above it is cut to what
   a reader needs before typing: breadcrumb, eyebrow, headline.

   The hero's own vertical rhythm is tightened here rather than globally —
   `--hero-h` is shared with the homepage and every service banner, and this
   is two pages, not a site-wide change. */
.sHero--form{min-height:0;padding-top:clamp(14px,1.6vw,22px);
  padding-bottom:clamp(26px,3vw,44px)}
.sHero--form .sHero__head{margin-bottom:clamp(12px,1.4vw,18px)}
.sHero--form .sHero__title{font-size:clamp(1.75rem,1.2rem + 1.9vw,2.6rem)}
.sHero--form .sHero__body{max-width:none}
/* 34/66 rather than the 38/62 of rev 88: the card now carries two columns of
   its own, so the extra four points go where the fields and the guidance panel
   have to share a width. */
.sHero__formGrid{display:grid;grid-template-columns:minmax(0,34fr) minmax(0,66fr);
  gap:clamp(22px,2.6vw,40px);align-items:start}
.sHero--form .sHero__lead{margin-bottom:18px;max-width:46ch}
.sHero--form .sHero__facts{margin-bottom:20px}

/* the elevated form card */
.sHero__formCard{background:#fff;border:1px solid var(--line);
  border-radius:var(--radius-lg);padding:clamp(18px,1.8vw,28px);
  box-shadow:0 24px 60px rgba(0,16,53,.13),0 2px 6px rgba(0,16,53,.05)}
/* The card supplies the surface, so the form inside it drops its own frame and
   its two-column field grid becomes one — 62% of the measure is not enough for
   a label column plus two controls side by side. */
/* THE CARD IS TWO COLUMNS: fields, then the guidance panel. The form's own
   field rows are label-beside-control with a 172px label and a capped control,
   so a single-column card left roughly a third of its width empty — which is
   what Rick's annotation marks. `.enq` was already a form|aside grid for the
   full-width layout; compact reuses it rather than inventing a second one, so
   the two layouts cannot drift. The card supplies the surface, so the form
   drops its own frame. */
/* The card's own top line: "Write us at … or fill in the form below."
   It sits INSIDE the card and ABOVE the two-column grid, so it spans the fields
   and the guidance panel both — which is what Rick's annotation marks, a strip
   across the full inner width. The text is left-aligned to the card's padding
   edge; the box in the annotation marks where the line goes, not how wide the
   sentence runs. (Same lesson as the guidance panel's height at rev 89.)
   Separation from the first field is whitespace only — no rule is drawn,
   because none is in the annotation. */
.enqTop{margin:0 0 22px;padding-bottom:12px;font-size:.9375rem;color:var(--muted)}
.enqTop__mail{font-weight:600;color:var(--brand)}
.enqTop__mail:hover{color:var(--brand-dark);text-decoration:underline}

.enq--compact{margin:0;padding:0;background:none;border:0;box-shadow:none;
  grid-template-columns:minmax(0,1.62fr) minmax(0,.98fr);
  gap:clamp(20px,2vw,34px);align-items:start}
.enq--compact .enq__form{padding:0;background:none;border:0;box-shadow:none;max-width:none}
.enq--compact .enq__grid{grid-template-columns:1fr}
.enq--compact .enq__actions{margin-top:18px}
/* THE PANEL HUGS ITS CONTENT. Rev 89 stretched it to fill the column, reading
   the annotation's tall rectangle as the intended height; it was the drawing's
   callout box, not a spec, and stretched beside a long field list it became a
   mostly-empty tinted slab (Rick, 13 October).

   It is also not `position:sticky` — that was the first attempt and a no-op
   here, since `align-items:start` sizes the grid item to its content so the
   sticky box has no travel. Measured: scrolling 600px moved it the full 600px.

   Compacted with it: padding, heading size, item text and the gaps between
   items. This is guidance beside the form, not a second column of content. */
.enq--compact .enq__aside{align-self:start;
  padding:clamp(14px,1.2vw,18px);border-radius:14px}
.enq--compact .enq__aside h3{font-size:.9375rem;margin-bottom:10px}
.enq--compact .enq__aside .procList{gap:9px;margin-bottom:12px}
.enq--compact .enq__aside .procList li{font-size:.78125rem;line-height:1.45;gap:8px}
.enq--compact .enq__aside .procList .ico{width:13px;height:13px;margin-top:3px}
.enq--compact .enq__aside .enq__small{font-size:.75rem;line-height:1.5;margin:0}

/* the premises carousel, in Contact Us's left column.
   `.gal--banner` sizes itself against `--hero-h` because it used to live in the
   banner grid's media area; in a 38% column that formula overshoots, so the
   width is the column's and the cap is dropped. */
.heroGallery{padding-top:18px;border-top:1px solid var(--line)}
.heroGallery .gal--banner{max-width:none;width:100%;margin:0}

/* phone, office and hours under the lead */
.heroContact{display:grid;gap:12px;margin:0;padding-top:18px;
  border-top:1px solid var(--line)}
.heroContact li{display:flex;align-items:flex-start;gap:11px;
  font-size:.9125rem;line-height:1.45;color:var(--ink)}
.heroContact .ico{flex:none;margin-top:2px;color:var(--brand)}
.heroContact a{font-weight:650;color:var(--navy)}
.heroContact a:hover{color:var(--brand)}
.heroContact small{font-size:.75rem;color:var(--muted)}


@media (max-width:980px){
  /* Below this the two columns give the form under 420px of measure, which is
     narrower than the phone layout it would otherwise skip past.

     THE ORDER FLIPS WITH THE STACK, not at the phone breakpoint. Stacking
     without reordering would put the lead, the facts and three contact rows
     above the form at every width from 980 down to 769 — reinstating the exact
     problem this layout removes, in the band most likely to be a tablet. */
  .sHero__formGrid{grid-template-columns:1fr;gap:24px}
  .sHero__formCard{order:1}
  .sHero__formAside{order:2}
  .sHero--form .heroContact{border-top:0;padding-top:0}
}

@media (max-width:1024px){
  .csSec__grid{grid-template-columns:1fr 1fr}
  .csRail__pills{max-height:4.4rem}
}
@media (max-width:640px){
  .csSec__grid{grid-template-columns:1fr}
  .csTab{padding:13px 13px 11px;font-size:.875rem}
  /* On a phone a two-row rail plus the tab strip pinned 177px of an 844px
     screen. One scrolling row costs 44px and reads the way every other
     mobile filter rail does; with nothing wrapping, the overflow test in
     stories.js keeps Show all hidden on its own. */
  .csRail__pills{flex-wrap:nowrap;overflow-x:auto;max-height:none;
    scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .csRail__pills::-webkit-scrollbar{display:none}
  .csPill{flex:0 0 auto}
}

/* =========================================================
   CASE STUDY PAGES — a layout of their own.

   A client story is not a service page and must not read like one: the hero
   is a dark banner rather than the light service hero, it carries the
   Problem → Solution → Impact rail that names the narrative, and the
   quantified metrics sit in it rather than halfway down the page. The body
   below reuses the shared shell (.sBody, .rail, .callout, docks) so the page
   still belongs to the site.
   ========================================================= */
.caseHero{position:relative;overflow:hidden;background:var(--navy);color:#fff;
  padding-bottom:clamp(30px,3.6vw,50px)}
.caseHero__bg{position:absolute;inset:0;z-index:0;
  background:
    radial-gradient(820px 420px at 88% 0%, rgba(55,99,231,.42), transparent 62%),
    radial-gradient(620px 420px at 2% 100%, rgba(55,99,231,.20), transparent 60%),
    linear-gradient(160deg,#001035 0%,#061A45 58%,#0A2058 100%);
}
.caseHero__bg::after{content:"";position:absolute;inset:0;opacity:.30;
  background-image:linear-gradient(rgba(255,255,255,.07) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.07) 1px,transparent 1px);
  background-size:64px 64px;
  -webkit-mask-image:radial-gradient(70% 70% at 50% 30%,#000,transparent);
  mask-image:radial-gradient(70% 70% at 50% 30%,#000,transparent);
}
.caseHero>.container{position:relative;z-index:1}

.crumbs--light ol,.crumbs--light a{color:rgba(255,255,255,.62)}
.crumbs--light a:hover{color:#fff}
.crumbs--light [aria-current="page"]{color:#fff}
.crumbs--light .sep{color:rgba(255,255,255,.38)}

.caseHero__grid{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(0,.85fr);
  gap:clamp(24px,3.2vw,56px);align-items:start;
  padding-top:clamp(22px,2.6vw,38px)}
.caseHero__ref{display:inline-flex;align-items:center;gap:9px;margin:0 0 14px;
  font-size:.75rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:rgba(255,255,255,.72)}
.caseHero__ref .dot{width:7px;height:7px;border-radius:50%;background:#6E93FF;flex:none}
.caseHero__title{font-size:var(--fs-h1);line-height:1.08;letter-spacing:-.03em;color:#fff;margin:0}
.caseHero__title .grad{background:linear-gradient(92deg,#8FB0FF,#C9D9FF);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.caseHero__deck{margin:16px 0 0;max-width:62ch;
  font-size:clamp(.95rem,.9rem + .3vw,1.0625rem);line-height:1.68;color:rgba(255,255,255,.76)}

/* the narrative rail — the three stages this template is built around */
.psi{display:flex;flex-wrap:wrap;gap:10px;margin:clamp(20px,2.4vw,30px) 0 0;
  counter-reset:psi}
.psi li{counter-increment:psi}
.psi a{display:flex;flex-direction:column;gap:3px;padding:11px 16px 12px;border-radius:var(--radius-sm);
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.14);
  font-size:.875rem;font-weight:600;color:#fff;
  transition:background .25s ease,border-color .25s ease}
.psi a:hover{background:rgba(255,255,255,.13);border-color:rgba(255,255,255,.3)}
.psi a span{font-size:.6875rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:#8FB0FF}
.psi a span::before{content:counter(psi,decimal-leading-zero) " · "}

/* stage label above each of the three body sections */
.csStage{display:inline-flex;align-items:center;gap:8px;margin:0 0 10px;
  padding:5px 12px;border-radius:999px;
  font-size:.6875rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase}
.csStage::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
.csStage--problem{background:#FDEEEA;color:#B4472A}
.csStage--solution{background:var(--brand-tint);color:var(--brand-darker)}
.csStage--impact{background:#E7F5EC;color:#1D7A44}

/* engagement facts */
.csFacts{display:grid;gap:0;padding:6px 20px;border-radius:var(--radius);
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.16);
  backdrop-filter:blur(2px)}
.csFacts li{display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  padding:12px 0;border-bottom:1px solid rgba(255,255,255,.12)}
.csFacts li:last-child{border-bottom:0}
.csFact__k{font-size:.75rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  color:rgba(255,255,255,.58)}
.csFact__v{font-size:.875rem;font-weight:600;color:#fff;text-align:right}

/* quantified impact grid — omitted when the source document has no figures */
.csMetrics{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;
  margin-top:clamp(26px,3vw,40px);position:relative;z-index:1}
.csMetric{display:flex;flex-direction:column;gap:6px;padding:20px 22px;border-radius:var(--radius);
  background:#fff;border:1px solid #DCE4F2;box-shadow:0 14px 32px rgba(0,16,53,.08)}
.csMetric b{font-size:clamp(1.5rem,1.2rem + 1.1vw,2.125rem);font-weight:600;line-height:1;
  letter-spacing:-.035em;color:var(--brand)}
.csMetric span{font-size:.8125rem;line-height:1.5;color:var(--muted)}

/* challenge detail cards */
.csPoints{display:grid;grid-template-columns:repeat(2,1fr);gap:16px;
  margin-bottom:clamp(34px,4vw,56px)}
.csPoint{padding:18px 20px;border-radius:var(--radius);background:var(--brand-tint-2);
  border:1px solid var(--line)}
.csPoint h3{font-size:.9375rem;margin-bottom:.4em}
.csPoint p{margin:0;font-size:.875rem;line-height:1.65;color:var(--muted)}

/* approach */
.csFlow__list{display:grid;gap:16px;margin-top:18px}
.csStep{display:flex;gap:18px;padding:22px 24px;border-radius:var(--radius);
  background:#fff;border:1px solid var(--line);box-shadow:var(--shadow-sm)}
.csStep__n{flex:none;font-size:.875rem;font-weight:700;color:var(--brand);padding-top:2px}
.csStep h3{font-size:1rem;margin-bottom:.45em}
.csStep p{margin:0 0 .7rem;font-size:.875rem;line-height:1.7;color:var(--muted)}
.csStep p:last-child{margin:0}

/* results */
.csResults__list{display:grid;gap:10px;margin-top:18px}
.csResults__list li{display:flex;gap:12px;padding:13px 18px;border-radius:var(--radius-sm);
  background:var(--brand-tint-2);border:1px solid var(--line);
  font-size:.9375rem;line-height:1.6;color:var(--ink)}
.csResults__list .ico{width:19px;height:19px;flex:none;margin-top:3px;color:var(--brand)}

/* services used */
.csServices__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:18px}
.csServices__grid a{position:relative;display:flex;align-items:flex-start;justify-content:space-between;
  gap:12px;padding:15px 17px;border-radius:var(--radius-sm);background:#fff;border:1px solid var(--line);
  font-size:.875rem;font-weight:600;line-height:1.45;color:var(--navy);
  transition:transform .3s ease-in-out,box-shadow .3s ease,border-color .3s ease}
.csServices__grid a:hover{transform:translateY(-3px);border-color:#C6D6F6;box-shadow:var(--shadow-sm);color:var(--brand)}
.csServices__grid a::after{content:"";position:absolute;left:0;right:0;top:100%;height:0}
.csServices__grid a:hover::after{height:8px}
.csServices__grid .ico{flex:none;margin-top:3px;color:var(--brand)}

/* next step band */
.csNext{padding-block:clamp(34px,4vw,54px);background:var(--brand-tint-2);border-top:1px solid var(--line)}
.csNext__inner{display:flex;align-items:center;justify-content:space-between;gap:26px;flex-wrap:wrap}
.csNext h2{font-size:clamp(1.15rem,1rem + .7vw,1.5rem);margin-bottom:.35em}
.csNext p{margin:0;max-width:58ch;font-size:.9375rem;line-height:1.65;color:var(--muted)}
.csNext__actions{display:flex;align-items:center;gap:18px;flex-wrap:wrap}

/* ---- document figures -------------------------------------------------
   Screenshots and flowcharts lifted from the client's own document, placed at
   the section they sat under there. Captions are placeholders until the client
   confirms the wording, and say so on the page rather than inventing one. */
.csFig{margin:0 0 clamp(20px,2.4vw,30px);padding:10px;border-radius:var(--radius);
  background:#fff;border:1px solid var(--line);box-shadow:var(--shadow-sm)}

/* HEIGHT IS CAPPED, WIDTH IS NOT, AND THE IMAGE IS NEVER CROPPED.
   These run from 1999x266 to 658x1999. Unconstrained, the tallest rendered
   2,430px in an 800px column — two full screens for one screenshot, with 22 of
   the 59 over 400px. A width cap (`max-width:80%`) would have shrunk the wide
   console captures too, and those are the ones whose text has to stay readable
   in place; capping height only touches the tall ones, which are the problem.
   `object-fit:contain` rather than `cover`: cropping evidence to fit a box is
   not a styling decision, it is deleting part of the record. A tall image
   therefore sits centred on the tinted plate, which reads as deliberate. */
.csFig__zoom{--fig-h:400px;
  position:relative;display:flex;align-items:center;justify-content:center;
  overflow:hidden;border-radius:var(--radius-sm);background:var(--brand-tint-2);
  cursor:zoom-in}
.csFig__zoom img{display:block;width:auto;height:auto;
  max-width:100%;max-height:var(--fig-h);object-fit:contain;
  transition:transform .35s var(--ease)}
.csFig__zoom:hover img{transform:scale(1.02)}
.csFig__zoom:focus-visible{outline:3px solid var(--brand);outline-offset:2px}
.csFig__hint{position:absolute;right:10px;bottom:10px;
  display:inline-flex;align-items:center;gap:6px;padding:5px 10px;border-radius:999px;
  background:rgba(6,11,24,.72);color:#fff;font-size:.6875rem;font-weight:650;
  letter-spacing:.02em;opacity:0;transform:translateY(4px);
  transition:opacity .25s var(--ease),transform .25s var(--ease)}
.csFig__zoom:hover .csFig__hint,.csFig__zoom:focus-visible .csFig__hint{opacity:1;transform:none}
/* On a touchscreen there is no hover, so the affordance has to be permanent —
   otherwise the only cue that these open is that they happen to be tappable. */
@media (hover:none){
  .csFig__hint{opacity:1;transform:none}
  .csFig__zoom:hover img{transform:none}
}
@media (prefers-reduced-motion:reduce){
  .csFig__zoom img,.csFig__hint{transition:none}
  .csFig__zoom:hover img{transform:none}
}
.csStep .csFig{margin-top:14px;margin-bottom:0;padding:8px;box-shadow:none}

.csEvidence{margin-bottom:clamp(34px,4vw,56px)}
.csEvidence__grid{display:grid;gap:16px}
.csEvidence--strip .csEvidence__grid{grid-template-columns:repeat(2,1fr);margin-top:18px}
.csEvidence__grid .csFig{margin:0}

/* --- Supplemental case-study sections -------------------------------------
   Four fixed treatments shared by every story that needs one. They deliberately
   reuse the page's existing grammar — csStage label, sec__title, the same card
   radius and hairline border as csResults and callout — so a story that grows a
   section still reads as the same series rather than as a one-off layout. Any
   new shape belongs here as a fifth kind, not as markup in a content file. */
.csExtra{margin-bottom:clamp(34px,4vw,56px)}
.csExtra__lead{margin-top:10px;color:var(--ink-2);max-width:70ch}
.csExtra .csEvidence__grid{margin-top:20px}

/* workflow — an ordered pipeline */
.csExtra__flow{display:grid;gap:12px;margin-top:20px;padding:0;list-style:none;counter-reset:none}
.csExtra__stepCard{display:flex;gap:14px;align-items:flex-start;padding:14px 18px;
  border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface)}
.csExtra__num{flex:none;width:26px;height:26px;border-radius:999px;display:grid;place-items:center;
  font-size:13px;font-weight:700;color:#fff;background:var(--brand)}
.csExtra__stepBody{min-width:0}
.csExtra__stepBody b{display:block;margin-bottom:2px}

/* stack — label/value badges */
/* 300px, not 220px: both stack blocks carry four badges, and at 220px the
   column fits three, leaving a 3 + 1 wrap with a conspicuous hole. At 300px
   two columns fit and four items square off, while three still wrap 2 + 1. */
.csExtra__badges{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
  gap:12px;margin-top:20px;padding:0;list-style:none}
.csExtra__badge{padding:13px 16px;border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--surface-2)}
.csExtra__badgeK{display:block;font-size:12px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);margin-bottom:4px}
.csExtra__badgeV{display:block;font-weight:600}

/* metrics — one highlight panel per group */
.csExtra__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
  gap:16px;margin-top:20px}
.csExtra__panel{padding:18px 20px;border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--surface)}
.csExtra__panelTitle{font-size:15px;margin:0 0 10px}
.csExtra__points{display:grid;gap:8px;padding:0;list-style:none}
.csExtra__points li{position:relative;padding-left:18px;color:var(--ink-2)}
.csExtra__points li::before{content:"";position:absolute;left:0;top:9px;width:6px;height:6px;
  border-radius:999px;background:var(--brand)}

/* reading — key takeaways from a chart or a result set */
.csExtra__takeaways{display:grid;gap:10px;margin-top:20px;padding:0;list-style:none}
.csExtra__takeaways li{position:relative;padding:12px 18px 12px 38px;
  border:1px solid var(--line);border-left:3px solid var(--brand);
  border-radius:var(--radius-sm);background:var(--surface)}
.csExtra__takeaways li::before{content:"";position:absolute;left:18px;top:19px;width:7px;height:7px;
  border-radius:999px;background:var(--brand)}

@media (max-width:1024px){
  .caseHero__grid{grid-template-columns:1fr;gap:24px}
  .csEvidence--strip .csEvidence__grid{grid-template-columns:1fr}
  .csMetrics{grid-template-columns:1fr 1fr}
  .csPoints{grid-template-columns:1fr}
  .csServices__grid{grid-template-columns:1fr 1fr}
}
@media (max-width:640px){
  .csMetrics,.csServices__grid{grid-template-columns:1fr}
  .csStep{flex-direction:column;gap:8px;padding:18px 20px}
  .psi{flex-direction:column}
  .psi a{flex-direction:row;align-items:baseline;gap:10px}
}

/* --- Site search: header widget + results page (rev 50) ---------------
   The trigger sits in the utility bar's empty middle, left of Portal Login.
   Clicking it grows the input rather than opening a modal, so the page never
   moves and nothing is covered. The box is NOT overflow:hidden — the
   suggestion panel is absolutely positioned inside it, and clipping the box
   would clip the panel; the input's own width is what animates. */
.hsearch{position:relative;display:flex;align-items:center;gap:6px}
.hsearch__trigger{display:grid;place-items:center;width:38px;height:38px;flex:none;
  border-radius:10px;border:1.5px solid var(--line);background:#fff;color:var(--navy);
  transition:background .2s var(--ease),border-color .2s var(--ease),color .2s var(--ease)}
.hsearch__trigger:hover{background:var(--brand-tint-2);border-color:var(--brand);color:var(--brand)}
.hsearch.is-open .hsearch__trigger{background:var(--brand);border-color:var(--brand);color:#fff}
.hsearch__box{position:relative;display:flex;align-items:center}
.hsearch__input{width:0;height:38px;padding:0;border:1.5px solid transparent;border-radius:10px;
  background:#fff;font:inherit;font-size:.875rem;color:var(--ink);
  transition:width .3s var(--ease),padding .3s var(--ease),border-color .2s var(--ease)}
.hsearch__input::placeholder{color:#94A0B6}
.hsearch__input:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-tint)}
.hsearch.is-open .hsearch__input{width:clamp(190px,17vw,268px);padding:0 34px 0 13px;border-color:var(--line)}
.hsearch__go{position:absolute;right:4px;display:none;place-items:center;width:26px;height:26px;
  border-radius:7px;border:0;background:none;color:var(--brand)}
.hsearch.is-open .hsearch__go{display:grid}
.hsearch__go:hover{background:var(--brand-tint)}
.hsearch__lead{flex:none;margin-right:8px;color:var(--muted)}

/* the suggestion list */
.hsearch__panel{position:absolute;top:calc(100% + 9px);right:0;z-index:80;
  width:min(430px,86vw);max-height:min(62vh,460px);overflow-y:auto;overscroll-behavior:contain;
  background:#fff;border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow-lg);
  padding:6px}
.hsearch__item a{display:flex;flex-direction:column;gap:3px;padding:9px 12px;border-radius:9px;
  color:var(--ink);text-align:left}
.hsearch__item.is-on a,.hsearch__item a:hover{background:var(--brand-tint-2);color:var(--ink)}
.hsearch__t{font-size:.875rem;font-weight:600;line-height:1.35;color:var(--navy)}
.hsearch__t b{color:var(--brand)}
.hsearch__m{display:flex;align-items:center;gap:8px;font-size:.6875rem;line-height:1.4;color:var(--muted)}
.hsearch__kind{flex:none;padding:1px 7px;border-radius:999px;background:var(--grey);
  font-weight:700;letter-spacing:.05em;text-transform:uppercase;font-size:.5938rem;color:var(--muted)}
.hsearch__none{padding:12px 13px;font-size:.8125rem;color:var(--muted)}

/* the drawer copy: no trigger, always open, full width, and first in the
   drawer — below a six-item pillar list it needed a scroll to be found */
.hsearch--drawer{display:none;width:100%;margin-bottom:14px}
.hsearch--drawer .hsearch__box{width:100%;padding:0 10px;border:1.5px solid var(--line);
  border-radius:10px;background:#fff}
.hsearch--drawer .hsearch__input,
.hsearch--drawer.is-open .hsearch__input{width:100%;padding:10px 26px 10px 0;border-color:transparent;box-shadow:none}
.hsearch--drawer .hsearch__panel{left:0;right:0;width:auto}

/* --- search results page --- */
.srForm{display:flex;align-items:center;gap:10px;max-width:660px;padding:6px 6px 6px 16px;
  border:1.5px solid var(--line);border-radius:14px;background:#fff;box-shadow:var(--shadow-sm)}
.srForm:focus-within{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-tint)}
.srForm__ico{flex:none;color:var(--muted)}
.srForm__input{flex:1;min-width:0;border:0;background:none;font:inherit;font-size:1rem;color:var(--ink)}
.srForm__input:focus{outline:none}
.srCount{margin:14px 0 0;font-size:.875rem;color:var(--muted)}
.srBody{padding-block:clamp(28px,3.4vw,48px) clamp(40px,5vw,72px)}
.srFilters{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:clamp(18px,2vw,26px)}
.srChip{padding:6px 14px;border-radius:999px;border:1.5px solid var(--line);background:#fff;
  font:inherit;font-size:.8125rem;font-weight:600;color:var(--muted);cursor:pointer;
  transition:all .2s var(--ease)}
.srChip i{font-style:normal;font-size:.6875rem;font-weight:700;margin-left:5px;color:var(--muted)}
.srChip:hover{border-color:var(--brand);color:var(--brand)}
.srChip.is-on{background:var(--brand);border-color:var(--brand);color:#fff}
.srChip.is-on i{color:rgba(255,255,255,.8)}
.srList{display:grid;gap:2px;max-width:82ch}
.srItem{padding:16px 18px;border-radius:var(--radius-sm);border:1px solid transparent;
  transition:background .2s var(--ease),border-color .2s var(--ease)}
.srItem:hover{background:var(--brand-tint-2);border-color:var(--brand-tint)}
.srItem__title{display:inline-block;font-size:1.0625rem;font-weight:600;line-height:1.4;color:var(--navy)}
.srItem__title b{color:var(--brand)}
.srItem__title:hover{color:var(--brand)}
.srItem__crumb{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin:5px 0 6px;
  font-size:.75rem;color:var(--muted)}
.srItem__kind{padding:1px 8px;border-radius:999px;background:var(--grey);font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;font-size:.625rem}
.srItem__snip{margin:0;font-size:.875rem;line-height:1.65;color:var(--muted)}
.srItem--more{font-size:.8125rem;color:var(--muted);background:var(--grey);margin-top:10px}
.srEmpty{max-width:70ch;padding:22px 24px;border-radius:var(--radius);background:var(--grey);
  border:1px dashed #C9D5EA;font-size:.9125rem;color:var(--muted)}
.srEmpty strong{color:var(--navy)}
.srEmpty p:last-child{margin-bottom:0}

/* Between 1024 and 1180 the utility row has no slack left: an inline field
   wide enough to type in pushed the three action buttons onto a second line
   and the header grew by 51px every time the search opened. Below 1180 the
   field therefore overlays the buttons instead of displacing them — anchored
   to the actions row, starting just right of the trigger, so the trigger stays
   visible and nothing on the page moves. */
@media (max-width:1180px){
  .utility__actions{position:relative}
  /* the form's own position:relative would otherwise be the containing block,
     and the box would stretch to 46px rather than across the row */
  .utility .hsearch{position:static}
  /* scoped to the utility bar: the drawer copy also carries .is-open, and this
     rule tore it out of the drawer's flow and dropped it over About StaffCloud */
  .utility .hsearch.is-open .hsearch__box{position:absolute;left:46px;right:0;top:50%;
    transform:translateY(-50%);background:#fff;border-radius:10px;z-index:20}
  .utility .hsearch.is-open .hsearch__input{width:100%}
}
@media (max-width:1024px){
  /* the drawer's close button is fixed at its top-right (14–58px), so the
     field starts below it rather than putting its submit arrow under the X */
  .hsearch--drawer{display:flex;margin-top:40px}
}
@media (max-width:640px){
  .srForm{flex-wrap:wrap;padding:12px}
  .srForm .btn{width:100%}
}
.hsearch__fix{padding:9px 13px 7px;font-size:.75rem;color:var(--muted);border-bottom:1px solid var(--line);margin-bottom:4px}
.hsearch__fix b{color:var(--navy)}

/* --- About Us page (rev 55) -------------------------------------------
   Section order and component types follow suntecindia.com/about-us.htm; the
   tokens, the hover pattern and every value below are this site's own. Each
   block is named for the SunTec section it stands in for. */

/* 1 · hero counters — SunTec's three-up stat row, five-up here because two of
   the figures are open slots rather than numbers */
/* auto-fit rather than a hard column count: the row went from five cards to
   four on 6 October, and a `repeat(5,1fr)` would have left the fourth card
   stretched across a gap where the fifth used to be. Now the row fits whatever
   COUNTERS holds, at every width, without a matching edit here. */
.ctrRow{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:14px;
  margin-top:clamp(20px,2.4vw,30px)}
.ctr{display:flex;flex-direction:column;gap:5px;padding:20px 18px;border-radius:var(--radius);
  background:rgba(255,255,255,.78);border:1px solid #D7E1F4;backdrop-filter:blur(6px)}
.ctr__v{font-size:clamp(1.5rem,1.2rem + .9vw,2rem);font-weight:600;line-height:1;
  letter-spacing:-.035em;color:var(--brand-darker)}
.ctr__l{font-size:.8125rem;font-weight:600;color:var(--navy);line-height:1.35}
.ctr__n{font-size:.6875rem;line-height:1.5;color:var(--muted)}
.ctr--tbc{background:rgba(241,244,248,.8);border:1px dashed #C2D0E8}
.ctr--tbc .ctr__v{color:#B6C2D6}
.chipTBC{align-self:flex-start;margin-top:2px;padding:2px 9px;border-radius:999px;
  background:#FFF4DA;border:1px solid #F0DCAE;font-size:.625rem;font-weight:700;
  letter-spacing:.04em;text-transform:uppercase;color:#8A6300}

/* milestone rail — the company has a documented history and SunTec does not, so
   it rides inside the hero block rather than becoming a section of its own */
.ms{margin-top:clamp(20px,2.4vw,30px);padding-top:clamp(18px,2vw,26px);
  border-top:1px solid #D7E1F4}
.ms__head{margin:0 0 14px;font-size:.6875rem;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--brand)}
.ms__list{position:relative;display:grid;grid-template-columns:repeat(5,1fr);gap:12px}
.ms__list::before{content:"";position:absolute;left:6px;right:6px;top:5px;height:1px;
  background:#C7D5EE}
.ms__item{position:relative;padding-top:20px}
.ms__item::before{content:"";position:absolute;left:0;top:0;width:11px;height:11px;
  border-radius:50%;background:var(--brand);box-shadow:0 0 0 4px rgba(234,239,253,.95)}
.ms__year{display:block;font-size:.9375rem;font-weight:700;color:var(--navy);line-height:1.2}
.ms__label{display:block;margin-top:3px;font-size:.75rem;line-height:1.45;color:var(--muted)}

.srcNote{display:flex;align-items:flex-start;gap:9px;margin:22px 0 0;max-width:86ch;
  font-size:.75rem;line-height:1.6;color:var(--muted)}
.srcNote .ico{flex:none;margin-top:3px;color:var(--brand)}

/* 2 · certifications — SunTec's "Expertise" badge grid, as open slots */
.certSec{padding-block:var(--section-y-sm);background:var(--brand-tint-2)}
/* Three badges, one row, always. `1fr` alone is min-content-floored, so the
   Clutch wordmark could push its own column wider than the two ISO ones;
   minmax(0,1fr) makes the three columns genuinely equal.
   The row is capped and centred rather than stretched edge to edge — at 1440px
   three full-width thirds give ~460px tiles holding one short line of text
   each, which is what made them read as oversized. */
/* Screen-reader-only text. `.sr-only` was already in the markup (blog.html, and
   now the credential badges) with no rule behind it anywhere in this
   stylesheet, so it rendered as ordinary visible text. `clip-path` rather than
   `display:none` or `visibility:hidden`, both of which remove the text from the
   accessibility tree as well as from the screen, which is the opposite of what
   this is for. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}

.certGrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;
  max-width:600px;margin-inline:auto;align-items:stretch}
/* Certification tiles. Symmetrical padding and a fixed-height logo well, so
   three marks of very different proportions — a square ISO globe and a wide
   Clutch wordmark — sit on the same optical centre line. */
/* The three badges are links now (Rick, 6 Oct 2026), so this is an <a> on every
   page that holds a real credential. Everything below is written to work for
   either element: `color:inherit` and `text-decoration:none` stop the anchor
   repainting the name and scope in link blue, and `height:100%` makes the three
   tiles equal height whichever one wraps to two lines. */
.certTile{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  gap:5px;padding:14px 12px;height:100%;
  border-radius:var(--radius);background:#fff;border:1px solid var(--line);text-align:center;
  box-shadow:var(--shadow-sm);color:inherit;text-decoration:none;
  transition:border-color .18s var(--ease),box-shadow .18s var(--ease),
             transform .18s var(--ease)}
/* The lift is on the tile itself and it is tiny (1px). A larger hover transform
   on a grid item drags its own hitbox out from under the cursor and the card
   flickers — the same trap the service cards hit; see claude/layout-rules.md. */
a.certTile:hover{border-color:var(--brand);box-shadow:var(--shadow-md);
  transform:translateY(-1px)}
a.certTile:focus-visible{outline:3px solid var(--brand);outline-offset:3px}
@media (prefers-reduced-motion:reduce){
  a.certTile{transition:none}
  a.certTile:hover{transform:none}
}
.certTile--tbc{background:transparent;border:1px dashed #C2D0E8;box-shadow:none}

/* The logo well. This used to be a 60x60 tinted square with a 15px radius,
   built for the placeholder award icon. Once real logos went in they were
   wider than 60px, so the mark overflowed its own tinted pill and read as
   off-centre — the pill sat behind the left of the logo rather than around it.
   The tint now belongs to the icon variant only; with an image the well is
   transparent and does nothing but hold the height. */
.certTile__badge{display:flex;align-items:center;justify-content:center;
  height:34px;margin-bottom:3px}          /* 3px + the card's 5px gap = 8px */
.certTile__badge:has(.ico){width:44px;border-radius:12px;
  background:var(--brand-tint);color:var(--brand)}
.certTile--tbc .certTile__badge{background:#E8EDF7;color:#A8B6CE}
.certTile__badge .ico{width:24px;height:24px}

.certTile__name{font-size:.8125rem;font-weight:700;color:var(--navy);line-height:1.3}
.certTile__scope{font-size:.625rem;line-height:1.4;color:var(--muted)}
/* margin-top:auto, so the three pills sit on one line even when a scope line
   wraps in one tile and not the others. The flex gap still guarantees 6px of
   clearance above, so this only ever adds space, never removes it. */
.certTile__state{display:inline-block;margin:auto auto 0;
  padding:2px 8px;border-radius:999px;background:#E6F7EE;
  border:1px solid #BFE6D2;font-size:.5625rem;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;color:#0E7C4A}
.certTile .chipTBC{align-self:center}
/* The badge grid's only break, and it lives HERE — beside the component, after
   the base rule it overrides. The first attempt went into an unrelated
   `@media (max-width:640px)` block up in the homepage section, which sits
   EARLIER in this file than `.certGrid` above. Same specificity, so the base
   rule won on source order and the override did nothing at all. A media query
   does not raise specificity; position still decides. */
@media (max-width:560px){
  /* Below this the three names ("ISO/IEC 27001:2022") stop fitting on one line
     in a third of the viewport, so the row becomes a column rather than three
     cramped tiles of wrapped text. */
  .certGrid{grid-template-columns:1fr;max-width:320px;gap:10px}
}

/* Centred, not left-aligned. It has had `max-width:86ch` and no `margin-inline`
   since it was written, which parked it against the left gutter under a centred
   heading. Invisible while the badge row was full-width; obvious the moment the
   badges shrank to a centred 600px. */
.certNote{margin:22px auto 0;max-width:86ch;padding:16px 20px;border-radius:var(--radius-sm);
  background:#fff;border:1px dashed #C9D5EA}
.certNote p{margin:0;font-size:.8125rem;line-height:1.7;color:var(--muted)}
.certNote strong{color:var(--navy)}

/* 3 · clients — SunTec's logo wall, as empty frames */
.logoSec{padding-block:var(--section-y-sm)}
.logoWall{display:grid;grid-template-columns:repeat(6,1fr);gap:14px}
.logoSlot{display:grid;place-items:center;aspect-ratio:16/7;border-radius:var(--radius-sm);
  background:var(--grey);border:1px dashed #C9D5EA;color:#B6C2D6}
.logoSlot .ico{width:26px;height:26px}

/* 4 · news — SunTec's five-row badge + headline list */
.newsSec{padding-block:var(--section-y-sm);background:var(--brand-tint-2)}
.newsList{display:grid;gap:2px;max-width:900px}
.newsRow{display:flex;align-items:center;gap:16px;padding:15px 18px;border-radius:var(--radius-sm);
  background:#fff;border:1px solid var(--line)}
.newsRow__badge{flex:0 0 130px;font-size:.6875rem;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--brand)}
.newsRow__line{flex:1;height:9px;border-radius:999px;
  background:linear-gradient(90deg,var(--grey),rgba(241,244,248,.25))}
.newsRow .chipTBC{align-self:center;margin:0}

/* 5 · services — SunTec's two-column linked list */
.svcSec{padding-block:var(--section-y-sm)}
.svcList{display:grid;grid-template-columns:1fr 1fr;gap:12px 18px}
.svcLink{position:relative;display:flex;align-items:center;gap:15px;padding:18px 20px;
  border-radius:var(--radius);background:#fff;border:1px solid var(--line);color:var(--ink);
  box-shadow:var(--shadow-sm);
  transition:transform .3s ease-in-out,box-shadow .3s ease,border-color .3s ease}
.svcLink::after{content:"";position:absolute;left:0;right:0;top:100%;height:0}
.svcLink:hover::after{height:10px}
.svcLink:hover{transform:translateY(-3px);border-color:#CFDCF5;box-shadow:var(--shadow);color:var(--ink)}
.svcLink__icon{display:grid;place-items:center;width:44px;height:44px;flex:none;border-radius:12px;
  background:var(--brand-tint);color:var(--brand);
  transition:background .3s var(--ease),color .3s var(--ease)}
.svcLink:hover .svcLink__icon{background:var(--brand);color:#fff}
.svcLink__body{display:flex;flex-direction:column;gap:2px;min-width:0}
.svcLink__body strong{font-size:.9375rem;font-weight:600;color:var(--navy);line-height:1.35}
.svcLink__body span{font-size:.75rem;color:var(--muted)}
.svcLink__go{margin-left:auto;flex:none;color:var(--brand);transition:transform .25s var(--ease)}
.svcLink:hover .svcLink__go{transform:translateX(4px)}

/* 6 · credentials — SunTec's partner logo grid, as named systems */
.platSec{padding-block:var(--section-y-sm);background:var(--brand-tint-2)}
.platGrid{display:grid;grid-template-columns:repeat(6,1fr);gap:12px}
.platTile{display:grid;place-items:center;padding:16px 12px;border-radius:var(--radius-sm);
  background:#fff;border:1px solid var(--line);text-align:center;
  font-size:.8125rem;font-weight:600;color:var(--navy);line-height:1.35;
  transition:border-color .25s var(--ease),color .25s var(--ease)}
.platTile:hover{border-color:#C6D6F6;color:var(--brand)}

/* 7 · three client stories + see all */
.csRow{padding-block:var(--section-y-sm)}
.csRow__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.csCard{position:relative;display:flex;flex-direction:column;gap:8px;padding:24px 22px;
  border-radius:var(--radius);background:#fff;border:1px solid var(--line);color:var(--ink);
  box-shadow:var(--shadow-sm);
  transition:transform .3s ease-in-out,box-shadow .3s ease,border-color .3s ease}
.csCard::after{content:"";position:absolute;left:0;right:0;top:100%;height:0}
.csCard:hover::after{height:10px}
.csCard:hover{transform:translateY(-4px);border-color:#C6D6F6;box-shadow:var(--shadow);color:var(--ink)}
.csCard__ref{font-size:.625rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--brand)}
.csCard__title{font-size:1rem;font-weight:600;line-height:1.4;color:var(--navy)}
.csCard__lead{font-size:.8125rem;line-height:1.65;color:var(--muted)}
.csCard__go{display:inline-flex;align-items:center;gap:7px;margin-top:auto;padding-top:12px;
  font-size:.8125rem;font-weight:600;color:var(--brand)}
.csCard__go .ico{transition:transform .25s var(--ease)}
.csCard:hover .csCard__go .ico{transform:translateX(4px)}
.csRow__all{display:flex;justify-content:center;margin-top:26px}

/* 8 · processes — SunTec's two-column block with two bulleted sub-blocks */
.procSec{padding-block:var(--section-y-sm);background:var(--navy);color:rgba(255,255,255,.72)}
.proc{display:grid;grid-template-columns:.9fr 1.1fr;gap:clamp(28px,3.4vw,56px);align-items:start}
.proc__intro .sec__title{color:#fff}
.proc__intro p{font-size:.9375rem;line-height:1.75;color:rgba(255,255,255,.72)}
.proc__intro .rule{background:linear-gradient(90deg,#6C93FF,rgba(108,147,255,.25))}
.proc__intro .link{color:#9DB6FF}
.proc__intro .link:hover{color:#fff}
.proc__blocks{display:grid;gap:16px}
.procBlock{padding:24px 24px 20px;border-radius:var(--radius);
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14)}
.procBlock__icon{display:grid;place-items:center;width:42px;height:42px;margin-bottom:14px;
  border-radius:12px;background:rgba(255,255,255,.1);color:#9DB6FF}
.procBlock h3{color:#fff;font-size:1.0625rem;margin-bottom:.6em}
.procList{display:grid;gap:10px}
.procList li{display:flex;align-items:flex-start;gap:10px;font-size:.875rem;line-height:1.65}
.procList .ico{flex:none;margin-top:4px;color:#6C93FF}

/* 9 · closing band */
.aboutCta{padding-block:var(--section-y-sm)}
.aboutCta__inner{display:flex;align-items:center;justify-content:space-between;gap:32px;
  flex-wrap:wrap;padding:clamp(26px,3vw,40px);border-radius:var(--radius-lg);
  background:linear-gradient(120deg,var(--brand-tint),#fff 70%);border:1px solid #CFDCF5}
.aboutCta h2{font-size:clamp(1.3rem,1.05rem + .8vw,1.75rem);margin-bottom:.4em}
.aboutCta p{margin:0;max-width:62ch;font-size:.9375rem;line-height:1.7;color:var(--muted)}
.aboutCta__actions{display:flex;gap:12px;flex-wrap:wrap}

@media (max-width:1180px){
  .ctrRow{grid-template-columns:repeat(3,1fr)}
  .logoWall,.platGrid{grid-template-columns:repeat(4,1fr)}
  .proc{grid-template-columns:1fr;gap:28px}
}
@media (max-width:1024px){
  /* The badges used to go 2-up here, which left one tile alone on a second row
     — three items never divide into two columns. They are small enough now to
     hold three across all the way down to a phone, so the only break left is
     the stack at 560px. Rick asked for one row; this is what keeps it. */
  .csRow__grid{grid-template-columns:1fr}
  .svcList{grid-template-columns:1fr}
  .ms__list{grid-template-columns:repeat(3,1fr);gap:18px 12px}
  .ms__list::before{display:none}
}
@media (max-width:640px){
  .ctrRow{grid-template-columns:1fr 1fr}
  .logoWall,.platGrid{grid-template-columns:repeat(2,1fr)}
  .ms__list{grid-template-columns:1fr 1fr}
  .newsRow{flex-wrap:wrap;gap:8px}
  .newsRow__badge{flex:0 0 auto}
  .newsRow__line{order:3;flex:1 0 100%}
  .aboutCta__inner{flex-direction:column;align-items:flex-start}
}

/* --- About StaffCloud mega panel (rev 56) ------------------------------
   Two link columns plus three fact cards, in the same panel box the pillar
   menus use — so it inherits the bounds, the no-fade rule and the hover
   bridges rather than re-implementing them. */
.mega--about .mega__inner{padding-bottom:30px}
.aboutPanel{display:grid;grid-template-columns:1fr 1fr 1.25fr;gap:clamp(20px,2.4vw,40px);
  margin-top:22px;padding-top:22px;border-top:1px solid var(--line)}
.aboutPanel__col{display:grid;gap:2px;align-content:start}
.aboutPanel__col a{display:block;padding:9px 12px;border-radius:9px;font-size:.9375rem;
  color:var(--ink);transition:background .2s var(--ease),color .2s var(--ease)}
.aboutPanel__col a:hover{background:var(--brand-tint-2);color:var(--brand)}
/* The two audience groups each carry a heading (rev 100). The heading is a
   real <h3>, so it needs resetting out of the global h3 scale — at 1.375rem it
   would compete with the panel title above it. */
.aboutPanel__group{min-width:0}
.aboutPanel__groupHead{margin:0 0 8px;padding:0 12px;font-size:.6875rem;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}

.aboutPanel__cards{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;align-content:start}

.aboutCard{display:flex;flex-direction:column;align-items:center;gap:4px;padding:18px 12px;
  border-radius:var(--radius);background:var(--brand-tint-2);border:1px solid var(--line);
  text-align:center}
.aboutCard__icon{display:grid;place-items:center;width:38px;height:38px;margin-bottom:4px;
  border-radius:11px;background:#fff;border:1px solid var(--line);color:var(--brand)}
.aboutCard__k{font-size:.625rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted)}
.aboutCard__v{font-size:1.25rem;font-weight:600;letter-spacing:-.03em;color:var(--brand-darker);line-height:1}
.aboutCard__n{font-size:.6875rem;line-height:1.4;color:var(--muted)}

/* --- shared shell for the eight About sub-pages ----------------------- */
.subSec{padding-block:var(--section-y-sm)}
.sec--tint{background:var(--brand-tint-2)}
.container--read{max-width:860px}
.proseCol{max-width:78ch}
.proseCol p{font-size:.9375rem;line-height:1.8;color:var(--muted)}

.infoGrid{display:grid;gap:18px}
.infoGrid--2{grid-template-columns:repeat(2,1fr)}
.infoGrid--3{grid-template-columns:repeat(3,1fr)}
.infoGrid--4{grid-template-columns:repeat(4,1fr)}
.infoCard{position:relative;padding:24px 22px;border-radius:var(--radius);background:#fff;
  border:1px solid var(--line);box-shadow:var(--shadow-sm);
  transition:transform .3s ease-in-out,box-shadow .3s ease,border-color .3s ease}
.infoCard::after{content:"";position:absolute;left:0;right:0;top:100%;height:0}
.infoCard:hover::after{height:10px}
.infoCard:hover{transform:translateY(-4px);border-color:#CFDCF5;box-shadow:var(--shadow)}
.infoCard__icon{display:grid;place-items:center;width:42px;height:42px;margin-bottom:14px;
  border-radius:12px;background:var(--brand-tint);color:var(--brand);
  transition:background .3s var(--ease),color .3s var(--ease)}
.infoCard:hover .infoCard__icon{background:var(--brand);color:#fff}
.infoCard h3{font-size:1rem;margin-bottom:.4em;line-height:1.35}
.infoCard p{margin:0;font-size:.875rem;line-height:1.7;color:var(--muted)}
.infoCard p:empty{display:none}

.bulletGrid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.bulletCard{padding:26px 24px 22px;border-radius:var(--radius);background:#fff;
  border:1px solid var(--line);box-shadow:var(--shadow-sm)}
.bulletCard__icon{display:grid;place-items:center;width:42px;height:42px;margin-bottom:14px;
  border-radius:12px;background:var(--brand-tint);color:var(--brand)}
.bulletCard h3{font-size:1.0625rem;margin-bottom:.6em}
.bulletCard .procList li{color:var(--muted)}
.bulletCard .procList .ico{color:var(--brand)}

.newsRow__title{flex:1;font-size:.9375rem;font-weight:600;color:var(--navy);line-height:1.4}
.newsRow__meta{flex:0 0 auto;font-size:.8125rem;font-weight:600;color:var(--brand)}

.stepGrid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;counter-reset:s}
.stepCard{position:relative;padding:24px 22px;border-radius:var(--radius);background:#fff;
  border:1px solid var(--line);box-shadow:var(--shadow-sm)}
.stepCard__n{display:block;margin-bottom:10px;font-size:1.5rem;font-weight:700;
  letter-spacing:-.04em;color:var(--brand);opacity:.3;line-height:1}
.stepCard h3{font-size:1rem;margin-bottom:.4em}
.stepCard p{margin:0;font-size:.875rem;line-height:1.7;color:var(--muted)}

.modelGrid{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
.modelCard{position:relative;padding:26px 24px 22px;border-radius:var(--radius);background:#fff;
  border:1px solid var(--line);box-shadow:var(--shadow-sm);
  transition:transform .3s ease-in-out,box-shadow .3s ease,border-color .3s ease}
.modelCard::after{content:"";position:absolute;left:0;right:0;top:100%;height:0}
.modelCard:hover::after{height:10px}
.modelCard:hover{transform:translateY(-4px);border-color:#CFDCF5;box-shadow:var(--shadow)}
.modelCard__icon{display:grid;place-items:center;width:44px;height:44px;margin-bottom:14px;
  border-radius:12px;background:var(--brand-tint);color:var(--brand)}
.modelCard h3{font-size:1.125rem;margin-bottom:.4em}
.modelCard>p{font-size:.875rem;line-height:1.7;color:var(--muted);margin-bottom:14px}
.modelCard .procList li{color:var(--muted);font-size:.8125rem}
.modelCard .procList .ico{color:var(--brand)}

/* --- the trust block: two tenure ladders either side of a badge -------- */
.trustSec{padding-block:var(--section-y-sm);background:var(--navy)}
.trustSec .sec__title{color:#fff}
.trustSec .sec__lead{color:rgba(255,255,255,.7)}
.trustSec .srcNote{color:rgba(255,255,255,.6);margin-inline:auto;justify-content:center}
.trustSec .srcNote .ico{color:#6C93FF}
.trustSec .rule{background:linear-gradient(90deg,#6C93FF,rgba(108,147,255,.25))}
.trust{display:grid;grid-template-columns:1fr auto 1fr;gap:clamp(18px,2.6vw,42px);
  align-items:center}
.trust__badge{display:grid;place-items:center;gap:4px;width:118px;height:118px;flex:none;
  border-radius:50%;background:#fff;border:6px solid var(--brand);color:var(--brand);
  box-shadow:0 0 0 8px rgba(55,99,231,.16)}
.trust__badge .ico{width:34px;height:34px}
.trust__badge span{font-size:.6875rem;font-weight:700;letter-spacing:.11em;text-transform:uppercase}
.tenure{padding:24px 24px 20px;border-radius:var(--radius);background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.14)}
.tenure h3{color:#fff;font-size:1.125rem;margin-bottom:.3em}
.tenure p{margin:0 0 16px;font-size:.8125rem;line-height:1.6;color:rgba(255,255,255,.62)}
.tenure__table{width:100%;border-collapse:collapse;font-size:.875rem}
.tenure__table th,.tenure__table td{padding:10px 14px;text-align:left}
.tenure__table thead th{font-size:.6875rem;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:#9DB6FF;background:rgba(255,255,255,.07);
  border-bottom:1px solid rgba(255,255,255,.14)}
.tenure__table thead th:first-child{border-radius:8px 0 0 0}
.tenure__table thead th:last-child{border-radius:0 8px 0 0}
.tenure__table tbody th{font-weight:500;color:rgba(255,255,255,.86)}
.tenure__table tbody tr+tr th,.tenure__table tbody tr+tr td{border-top:1px solid rgba(255,255,255,.1)}
.tenure__table td b{color:#fff;font-size:1.0625rem}
.tenure .chipTBC{background:rgba(255,244,218,.14);border-color:rgba(240,220,174,.4);color:#F0DCAE}

/* --- the privacy-policy shell ----------------------------------------- */
.legal{max-width:78ch}
.legal__meta{margin:0 0 20px;font-size:.8125rem;color:var(--muted)}
.legal__warn{padding:18px 22px;margin-bottom:34px;border-radius:var(--radius-sm);
  background:#FFF9EC;border:1px solid #F0DCAE}
.legal__warn p{margin:0;font-size:.875rem;line-height:1.75;color:#6B5218}
.legal__warn strong{color:#4A3808}
.legal__sec{padding-block:22px;border-top:1px solid var(--line)}
.legal__sec h2{display:flex;gap:12px;font-size:1.125rem;line-height:1.35;margin-bottom:.5em}
.legal__n{color:var(--brand);font-variant-numeric:tabular-nums}
.legal__subject{margin:0 0 12px;font-size:.9375rem;line-height:1.75;color:var(--ink)}
.legal__todo{display:flex;align-items:flex-start;gap:10px;margin:0;padding:12px 14px;
  border-radius:var(--radius-sm);background:var(--grey);border:1px dashed #C9D5EA;
  font-size:.8125rem;line-height:1.65;color:var(--muted)}
.legal__todo .chipTBC{flex:none;margin:1px 0 0}
.legal__officer{margin-top:30px;padding:22px 24px;border-radius:var(--radius);
  background:var(--brand-tint-2);border:1px solid var(--line)}
.legal__officer h3{font-size:1rem;margin-bottom:.5em}
.legal__officer p{margin:0;font-size:.9375rem;line-height:1.8;color:var(--muted)}

@media (max-width:1180px){
  .aboutPanel{grid-template-columns:1fr 1fr;gap:24px}
  .aboutPanel__cards{grid-column:1/-1;grid-template-columns:repeat(3,1fr)}
  .stepGrid{grid-template-columns:1fr 1fr}
  .trust{grid-template-columns:1fr;justify-items:center}
  .trust__badge{order:-1}
  .tenure{width:100%}
}
@media (max-width:1024px){
  .infoGrid--3,.infoGrid--4{grid-template-columns:1fr 1fr}
  .bulletGrid,.modelGrid{grid-template-columns:1fr}
  .aboutPanel{grid-template-columns:1fr}
  .aboutPanel__cards{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:640px){
  .infoGrid--2,.infoGrid--3,.infoGrid--4,.stepGrid{grid-template-columns:1fr}
  .aboutPanel__cards{grid-template-columns:1fr}
  .legal__sec h2{flex-direction:column;gap:2px}
}

/* --- rev 57: team profiles, the Decade Club hero, the real policy ------ */

/* Meet the Team — SunTec's our-team card: photo, name, role, nothing else */
.personGrid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.person{display:flex;flex-direction:column;align-items:center;gap:6px;padding:24px 20px 20px;
  border-radius:var(--radius);background:#fff;border:1px solid var(--line);text-align:center;
  box-shadow:var(--shadow-sm)}
/* The frame is square and its radius is the design system's, which on this site
   is the circle used by every other avatar. aspect-ratio rather than a matching
   height keeps it square if the width ever changes at a breakpoint. */
.person__photo{display:grid;place-items:center;width:104px;aspect-ratio:1/1;margin-bottom:8px;
  border-radius:50%;background:var(--grey);border:1px dashed #C9D5EA;color:#B6C2D6}
.person__photo .ico{width:34px;height:34px}
/* A frame holding a real portrait loses the dashed placeholder border and the
   grey fill, and gains the clip the zoom needs: without overflow:hidden the
   scaled image spills out of the circle into a square. */
.person__photo:has(img){overflow:hidden;background:var(--line);border:1px solid var(--line)}
.person__photo img{width:100%;height:100%;display:block;
  object-fit:cover;object-position:top center;
  transition:transform .35s ease}
/* The zoom is on the IMAGE, never on the card. A transform on the hover target
   moves its own hitbox, so the pointer leaves, the hover ends, the element
   snaps back and the whole thing flickers 60 times a second. Animating a child
   of the hover target has no such feedback loop. */
.person:hover .person__photo img{transform:scale(1.03)}
@media (prefers-reduced-motion:reduce){
  .person__photo img{transition:none}
  .person:hover .person__photo img{transform:none}
}
.person h3{margin:0;font-size:1.0625rem;line-height:1.3}
.person__role{margin:0 0 4px;font-size:.8125rem;font-weight:600;color:var(--brand)}
.logoWall--portrait .logoSlot{aspect-ratio:3/4;border-radius:var(--radius)}

/* Decade Club — one artwork frame beside the copy.
   Rev 60 composed the tree from an SVG and 43 positioned frames with a tenure
   filter over it. Rick is supplying the finished picture, so all of that came
   out: the hero splits in two at 1180 — copy and the tenure card on the left,
   one image on the right — and stacks below that. */
.sHero--split{overflow:hidden}
@media (min-width:1181px){
  .sHero--split>.container--wide{display:grid;
    grid-template-columns:minmax(0,1fr) minmax(0,1.02fr);
    column-gap:clamp(26px,3vw,56px);align-items:center}
  .sHero--split .crumbs{grid-column:1/-1}
  .sHero--split .sHero__head{grid-column:1;grid-row:2;margin-bottom:18px;max-width:none}
  .sHero--split .sHero__body{grid-column:1;grid-row:3}
  .sHero--split .vCard{grid-column:1;grid-row:4}
  .sHero--split .heroFig{grid-column:2;grid-row:2/6;align-self:center}
  .sHero--split .sHero__title{font-size:clamp(1.65rem,1rem + 1.7vw,2.4rem)}
}

/* the milestone badge — one fact, so it reads as a badge rather than a row */
.sHero--split .sHero__facts{margin-top:4px}
.sHero--split .sHero__facts li{padding:9px 18px;font-size:.9375rem;font-weight:700;
  color:var(--navy);background:linear-gradient(120deg,var(--brand-tint),#fff);
  border-color:#C6D6F6}
.sHero--split .sHero__facts .ico{color:var(--brand)}

/* the translucent tenure callout */
.vCard{margin-top:clamp(18px,2.2vw,26px);max-width:400px;padding:6px 6px 14px;
  border-radius:var(--radius);background:rgba(255,255,255,.72);
  border:1px solid rgba(255,255,255,.9);backdrop-filter:blur(10px) saturate(1.4);
  box-shadow:0 14px 34px rgba(0,16,53,.1)}
.vCard__table{width:100%;border-collapse:collapse;font-size:.875rem}
.vCard__table th,.vCard__table td{padding:11px 16px;text-align:left}
.vCard__table thead th{font-size:.6875rem;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--brand);background:rgba(234,239,253,.72);
  border-bottom:1px solid #D7E1F4}
.vCard__table thead th:first-child{border-radius:11px 0 0 0}
.vCard__table thead th:last-child{border-radius:0 11px 0 0;text-align:right}
.vCard__table tbody th{font-weight:600;color:var(--navy)}
.vCard__table tbody td{text-align:right}
.vCard__table tbody td b{font-size:1.0625rem;color:var(--brand-darker)}
.vCard__table tbody tr+tr th,.vCard__table tbody tr+tr td{border-top:1px solid #E2E8F2}
.vCard__note{margin:12px 16px 0;font-size:.6875rem;line-height:1.55;color:var(--muted)}

/* the artwork frame. Empty it is a labelled slot that says what belongs there
   and at what size — a blank box invites the question, a labelled one answers
   it. Filled, the frame gets out of the way entirely. */
.heroFig{margin:clamp(20px,2.4vw,30px) 0 0;position:relative}
.heroFig--set{margin-top:clamp(14px,1.6vw,22px)}
.heroFig--set img{display:block;width:100%;height:auto;border-radius:var(--radius-lg)}
.heroFig__slot{display:grid;place-items:center;align-content:center;gap:10px;
  aspect-ratio:5/4;padding:clamp(22px,3vw,44px);text-align:center;
  border-radius:var(--radius-lg);border:1.5px dashed #BCCDEA;
  background:linear-gradient(165deg,rgba(255,255,255,.86),rgba(234,239,253,.7));
  box-shadow:inset 0 0 0 10px rgba(255,255,255,.5)}
.heroFig__icon{display:grid;place-items:center;width:62px;height:62px;border-radius:18px;
  background:#fff;border:1px solid var(--line);color:var(--brand);
  box-shadow:0 8px 20px rgba(0,16,53,.08)}
.heroFig__icon .ico{width:28px;height:28px}
.heroFig__label{margin:0;font-size:1rem;font-weight:700;color:var(--navy)}
.heroFig__hint{margin:0;max-width:42ch;font-size:.75rem;line-height:1.65;color:var(--muted)}

/* stacked, the frame has the full container to fill and a 5:4 box at 1132px
   wide is 900px tall — taller than the copy above it. Cap it and centre it. */
@media (max-width:1180px){
  .heroFig{max-width:620px;margin-inline:auto}
}
@media (max-width:640px){
  .vCard{max-width:none}
  .heroFig{max-width:none}
  .heroFig__slot{aspect-ratio:4/3;gap:8px}
  .heroFig__icon{width:52px;height:52px}
}

/* `.person--open` lived here: the dashed "Open frame / Name and role to add"
   tiles at the end of the team grid. Removed with the markup on 6 October 2026
   (Rick) — the rules go too rather than being left behind, because a selector
   with nothing to match is a thing the next person has to prove is unused. */

.bandRow{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;max-width:900px;
  margin-inline:auto}
.band{display:flex;flex-direction:column;align-items:center;gap:10px;padding:26px 20px;
  border-radius:var(--radius);background:#fff;border:1px solid var(--line);
  box-shadow:var(--shadow-sm);text-align:center}
.band__years{font-size:1.125rem;font-weight:700;color:var(--navy)}
.band__count b{font-size:1.75rem;font-weight:600;color:var(--brand-darker);letter-spacing:-.03em}
.bandRow .chipTBC{align-self:center}

/* the published privacy policy */
.legal__toc{margin-bottom:34px;padding:20px 24px;border-radius:var(--radius);
  background:var(--brand-tint-2);border:1px solid var(--line)}
.legal__tocHead{margin:0 0 12px;font-size:.6875rem;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--brand)}
.legal__toc ol{display:grid;grid-template-columns:1fr 1fr;gap:4px 24px}
.legal__toc a{display:flex;gap:8px;padding:4px 0;font-size:.875rem;color:var(--ink)}
.legal__toc a span{color:var(--muted);font-variant-numeric:tabular-nums;min-width:1.6em}
.legal__toc a:hover{color:var(--brand)}
.legal__sec{scroll-margin-top:120px}
.legal__sec h3{margin:22px 0 .5em;font-size:1rem;color:var(--navy)}
.legal__sec p{margin:0 0 14px;font-size:.9375rem;line-height:1.8;color:var(--ink)}
.legal__sec p:last-child{margin-bottom:0}
.legal__list{margin:0 0 14px;padding-left:0;list-style:none;counter-reset:cl}
.legal__list li{position:relative;margin-bottom:10px;padding-left:34px;font-size:.9375rem;
  line-height:1.8;color:var(--ink);counter-increment:cl}
.legal__list li::before{content:"(" counter(cl, lower-alpha) ")";position:absolute;left:0;
  top:0;color:var(--brand);font-weight:600;font-variant-numeric:tabular-nums}
.legal__addr{line-height:1.9}
.legal__tableWrap{margin:0 0 18px;overflow-x:auto;border-radius:var(--radius-sm);
  border:1px solid var(--line)}
.legal__table{width:100%;border-collapse:collapse;font-size:.8125rem;min-width:520px}
.legal__table th,.legal__table td{padding:11px 14px;text-align:left;vertical-align:top;
  line-height:1.6}
.legal__table thead th{background:var(--brand-tint-2);color:var(--navy);font-weight:700;
  font-size:.75rem;letter-spacing:.03em}
.legal__table tbody tr+tr th,.legal__table tbody tr+tr td{border-top:1px solid var(--line)}
.legal__table--kv{min-width:420px}
.legal__table--kv th{width:38%;background:var(--brand-tint-2);font-weight:600;color:var(--navy)}
.legal__table--kv td{color:var(--muted)}

@media (max-width:1180px){
  .personGrid{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:1024px){
  .personGrid{grid-template-columns:repeat(2,1fr)}
  .legal__toc ol{grid-template-columns:1fr}
}
@media (max-width:640px){
  .personGrid{grid-template-columns:1fr 1fr}
  .person__photo{width:82px;height:82px}
  .bandRow{grid-template-columns:1fr}
}

/* ===========================================================================
   rev 49 — legal additions, How It Works, FAQ, enquiry form
   =========================================================================== */

/* Two block kinds the Terms and the Cookies policy need and the privacy policy
   did not: a bulleted list, and the PART A / PART B dividers. */
.legal__list--bul{list-style:disc}
.legal__list--bul li::marker{color:var(--brand)}
.legal__part{margin:30px 0 18px;font-weight:700;color:var(--ink);
  letter-spacing:.04em;text-transform:uppercase;font-size:.8125rem;
  padding-bottom:10px;border-bottom:2px solid var(--brand)}

/* --- How It Works: vertical tab set ------------------------------------- *
 * The source page's shape: a rail of six numbered labels, one panel beside it,
 * the whole thing about one image tall. Rev 63's stacked alternating rows were
 * six times that height for the same content.
 *
 * Switching is CSS only. Panels are selected on the radio's VALUE, never its
 * id: the combined artifact namespaces ids per route, so an #id selector is
 * dead there. Same lesson as the Decade Club filter.
 */
/* Capped at the source page's own 1140px content width: the section runs in a
   wide container, and an image slot stretched to 1100px would be taller than
   the whole widget is on staffcloud.net. */
.flow{position:relative;max-width:1140px;margin:clamp(28px,3.4vw,44px) auto 0}
/* Focusable but invisible — keyboard arrows walk the steps. Not display:none,
   which would take them out of the tab order entirely. */
.flow__radio{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}
.flow__inner{display:grid;grid-template-columns:minmax(210px,300px) 1fr;
  gap:clamp(20px,2.4vw,38px);align-items:start}
.flow__rail{list-style:none;display:grid;gap:2px;border-left:2px solid var(--line);
  padding-left:0}
.flow__rail label{display:grid;gap:2px;padding:13px 16px;margin-left:-2px;
  border-left:2px solid transparent;cursor:pointer;transition:background .15s ease}
.flow__rail label:hover{background:var(--brand-tint-2)}
.flow__n{font-size:.8125rem;font-weight:700;color:var(--muted);letter-spacing:.06em}
.flow__t{font-weight:650;color:var(--ink);line-height:1.35}
.flow__panels{min-width:0}
.flow__panel{display:none}
.flow__body{font-size:clamp(1.0625rem,1.3vw,1.25rem);line-height:1.6;color:var(--ink);
  margin-bottom:18px;max-width:52ch}
.flow__fig{margin:0}
.flow__slot{display:grid;place-content:center;justify-items:center;gap:8px;text-align:center;
  aspect-ratio:795/450;border:2px dashed var(--line);border-radius:16px;
  background:var(--brand-tint-2);padding:22px}
.flow__icon{display:grid;place-content:center;width:52px;height:52px;border-radius:14px;
  background:#fff;border:1px solid var(--line);color:var(--brand)}
.flow__label{font-weight:700;color:var(--ink)}
.flow__hint{font-size:.8125rem;color:var(--muted);max-width:34ch}

/* The six pairs, written out rather than generated: six is not enough to be
   worth adding a preprocessor for. */
.flow__radio[value="flowstep-1"]:checked ~ .flow__inner .flow__panel[data-step="1"],
.flow__radio[value="flowstep-2"]:checked ~ .flow__inner .flow__panel[data-step="2"],
.flow__radio[value="flowstep-3"]:checked ~ .flow__inner .flow__panel[data-step="3"],
.flow__radio[value="flowstep-4"]:checked ~ .flow__inner .flow__panel[data-step="4"],
.flow__radio[value="flowstep-5"]:checked ~ .flow__inner .flow__panel[data-step="5"],
.flow__radio[value="flowstep-6"]:checked ~ .flow__inner .flow__panel[data-step="6"]{display:block}

.flow__radio[value="flowstep-1"]:checked ~ .flow__inner .flow__rail li:nth-child(1) label,
.flow__radio[value="flowstep-2"]:checked ~ .flow__inner .flow__rail li:nth-child(2) label,
.flow__radio[value="flowstep-3"]:checked ~ .flow__inner .flow__rail li:nth-child(3) label,
.flow__radio[value="flowstep-4"]:checked ~ .flow__inner .flow__rail li:nth-child(4) label,
.flow__radio[value="flowstep-5"]:checked ~ .flow__inner .flow__rail li:nth-child(5) label,
.flow__radio[value="flowstep-6"]:checked ~ .flow__inner .flow__rail li:nth-child(6) label{
  border-left-color:var(--brand);background:var(--brand-tint)}
.flow__radio[value="flowstep-1"]:checked ~ .flow__inner .flow__rail li:nth-child(1) .flow__n,
.flow__radio[value="flowstep-2"]:checked ~ .flow__inner .flow__rail li:nth-child(2) .flow__n,
.flow__radio[value="flowstep-3"]:checked ~ .flow__inner .flow__rail li:nth-child(3) .flow__n,
.flow__radio[value="flowstep-4"]:checked ~ .flow__inner .flow__rail li:nth-child(4) .flow__n,
.flow__radio[value="flowstep-5"]:checked ~ .flow__inner .flow__rail li:nth-child(5) .flow__n,
.flow__radio[value="flowstep-6"]:checked ~ .flow__inner .flow__rail li:nth-child(6) .flow__n{
  color:var(--brand)}

/* Focus has to show on the label, because the input itself is invisible. */
.flow__radio[value="flowstep-1"]:focus-visible ~ .flow__inner .flow__rail li:nth-child(1) label,
.flow__radio[value="flowstep-2"]:focus-visible ~ .flow__inner .flow__rail li:nth-child(2) label,
.flow__radio[value="flowstep-3"]:focus-visible ~ .flow__inner .flow__rail li:nth-child(3) label,
.flow__radio[value="flowstep-4"]:focus-visible ~ .flow__inner .flow__rail li:nth-child(4) label,
.flow__radio[value="flowstep-5"]:focus-visible ~ .flow__inner .flow__rail li:nth-child(5) label,
.flow__radio[value="flowstep-6"]:focus-visible ~ .flow__inner .flow__rail li:nth-child(6) label{
  outline:2px solid var(--brand);outline-offset:2px}

/* --- FAQ: search over an accordion, grouped by folder -------------------- */
.faq{max-width:920px;margin:clamp(28px,3.4vw,44px) auto 0}
.faq__search{max-width:620px;margin-inline:auto}
.faq__label{display:block;font-size:.8125rem;font-weight:700;color:var(--muted);
  letter-spacing:.04em;text-transform:uppercase;margin-bottom:10px;text-align:center}
.faq__field{display:flex;align-items:center;gap:12px;padding:0 18px;
  border:1px solid var(--line);border-radius:999px;background:#fff;
  box-shadow:0 2px 10px rgba(16,24,40,.05);color:var(--muted)}
.faq__field:focus-within{border-color:var(--brand);box-shadow:0 0 0 4px rgba(55,99,231,.16)}
.faq__field input{flex:1;border:0;background:none;padding:15px 0;font:inherit;
  color:var(--ink);outline:none;min-width:0}
.faq__result{min-height:1.4em;margin-top:12px;text-align:center;font-size:.875rem;
  color:var(--muted)}
.faq__nav{margin:22px 0 clamp(26px,3vw,40px)}
.faq__nav ul{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;list-style:none}
.faq__nav a{display:inline-block;padding:8px 15px;border-radius:999px;
  border:1px solid var(--line);background:#fff;font-size:.875rem;font-weight:600;
  color:var(--muted)}
.faq__nav a:hover{border-color:var(--brand);color:var(--brand)}
.faq__group{margin-bottom:clamp(30px,3.4vw,48px);scroll-margin-top:140px}
.faq__h{display:flex;align-items:center;gap:12px;font-size:clamp(1.15rem,1.7vw,1.4rem);
  padding-bottom:14px;margin-bottom:6px;border-bottom:2px solid var(--line)}
.faq__count{display:inline-grid;place-content:center;min-width:26px;height:26px;
  padding:0 8px;border-radius:999px;background:rgba(55,99,231,.16);color:var(--brand);
  font-size:.8125rem;font-weight:700}
.faq__item{border-bottom:1px solid var(--line)}
.faq__item summary{display:flex;align-items:center;justify-content:space-between;gap:18px;
  padding:18px 2px;cursor:pointer;font-weight:650;color:var(--ink);list-style:none}
.faq__item summary::-webkit-details-marker{display:none}
.faq__item summary:hover{color:var(--brand)}
.faq__chev{flex:none;color:var(--brand);transition:transform .2s ease}
.faq__item[open] .faq__chev{transform:rotate(45deg)}
.faq__a{padding:0 2px 24px;max-width:72ch}
.faq__a p{margin-bottom:14px;color:var(--muted)}
.faq__a h4{margin:20px 0 10px;font-size:.9375rem;color:var(--ink)}
.faq__list{margin:0 0 14px 20px;display:grid;gap:8px;color:var(--muted)}
.faq__list li::marker{color:var(--brand)}
.faq__addr{font-style:normal;line-height:1.75}
.faq__flag{display:flex;align-items:flex-start;gap:9px;padding:11px 14px;border-radius:10px;
  background:var(--brand-tint-2);border:1px dashed var(--line);font-size:.8125rem;color:var(--muted)}
.faq__empty{text-align:center;padding:34px 0;color:var(--muted)}
.faq__item[hidden],.faq__group[hidden]{display:none}

/* --- Enquiry form -------------------------------------------------------- */
/* Capped rather than left to fill a wide container: a form line 900px long is
   a worse target than one at 600. */
.enq{display:grid;grid-template-columns:1.5fr .95fr;gap:clamp(28px,3.4vw,52px);
  align-items:start;max-width:1080px;margin:clamp(28px,3.4vw,42px) auto 0}
.enq__form{display:grid;gap:20px;padding:clamp(22px,2.6vw,34px);border:1px solid var(--line);
  border-radius:18px;background:#fff;box-shadow:0 4px 18px rgba(16,24,40,.05)}
/* The dock's status line shares every rule with the enquiry form's — same
   component, two placements — so they are selected together rather than
   duplicated. A second copy of these four rules is a second thing to remember
   when the colours change. */
.enq__status,.dock__status{margin:0;font-size:.9125rem}
.enq__status:empty,.dock__status:empty{display:none}
.enq__status[data-tone="ok"],.dock__status[data-tone="ok"]{padding:13px 16px;
  border-radius:10px;background:#ecfdf3;border:1px solid #abefc6;color:#067647}
.enq__status[data-tone="bad"],.dock__status[data-tone="bad"]{padding:13px 16px;
  border-radius:10px;background:#fef3f2;border:1px solid #fecdca;color:#b42318}
.fld{display:grid;gap:7px}
.fld label{font-weight:650;font-size:.9125rem;color:var(--ink)}
.fld .req{color:#b42318}
.fld .opt{font-weight:400;color:var(--muted);font-size:.8125rem}
.fld input,.fld select,.fld textarea{width:100%;padding:12px 14px;border:1px solid var(--line);
  border-radius:10px;font:inherit;color:var(--ink);background:#fff}
.fld textarea{resize:vertical;min-height:150px;line-height:1.6}
.fld input:focus,.fld select:focus,.fld textarea:focus{outline:none;border-color:var(--brand);
  box-shadow:0 0 0 4px rgba(55,99,231,.16)}
.fld input[type=file]{padding:10px 12px;background:var(--brand-tint-2)}
.fld__help{font-size:.8125rem;color:var(--muted);max-width:60ch}
.fld__err{font-size:.8125rem;color:#b42318;font-weight:600}
.fld[data-bad] input,.fld[data-bad] select,.fld[data-bad] textarea{border-color:#f97066}
/* The honeypot: off-screen rather than display:none, which some bots skip. */
.fld--hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.enq__actions{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.enq__small{font-size:.8125rem;color:var(--muted)}
.enq__aside{padding:clamp(22px,2.6vw,30px);border-radius:18px;background:var(--brand-tint-2);
  border:1px solid var(--line)}
.enq__aside h3{font-size:1.0625rem;margin-bottom:16px}
.enq__aside .procList{margin-bottom:20px}

@media (max-width:900px){
  .enq{grid-template-columns:1fr}
  /* Below 900 the rail sits above the panel as a scrolling pill row — same
     content, no horizontal squeeze. */
  .flow__inner{grid-template-columns:1fr;gap:20px}
  .flow__rail{grid-auto-flow:column;grid-auto-columns:max-content;gap:8px;
    border-left:0;overflow-x:auto;padding-bottom:6px;scrollbar-width:thin}
  .flow__rail label{margin-left:0;border:1px solid var(--line);border-radius:12px;
    padding:10px 14px}
  .flow__t{font-size:.875rem;white-space:nowrap}
  .flow__radio[value="flowstep-1"]:checked ~ .flow__inner .flow__rail li:nth-child(1) label,
  .flow__radio[value="flowstep-2"]:checked ~ .flow__inner .flow__rail li:nth-child(2) label,
  .flow__radio[value="flowstep-3"]:checked ~ .flow__inner .flow__rail li:nth-child(3) label,
  .flow__radio[value="flowstep-4"]:checked ~ .flow__inner .flow__rail li:nth-child(4) label,
  .flow__radio[value="flowstep-5"]:checked ~ .flow__inner .flow__rail li:nth-child(5) label,
  .flow__radio[value="flowstep-6"]:checked ~ .flow__inner .flow__rail li:nth-child(6) label{
    border-color:var(--brand)}
}
@media (max-width:640px){
  .faq__nav ul{justify-content:flex-start}
  .legal__part{font-size:.75rem}
}

/* Reduced motion: the chevron is the only new transition. */
@media (prefers-reduced-motion:reduce){
  .faq__chev{transition:none}
}

/* A footer entry Rick has asked to leave unlinked for now: same rhythm as its
   neighbours, visibly not a link. */
.footer__soon{color:rgba(255,255,255,.4);cursor:default}

/* The step artwork, once the files are in assets/how/. Same box as the slot it
   replaces, so the widget does not change height when the images land. */
.flow__img{display:block;width:100%;height:auto;aspect-ratio:795/450;object-fit:contain;
  border-radius:16px;background:var(--brand-tint-2)}

/* The footer's postal address. <address> is italic by default in every browser
   and inherits the list row's alignment, neither of which is wanted here. */
.footer__addr{font-style:normal;line-height:1.55;display:inline-block;vertical-align:top}

/* The two phone numbers (rev 64). The row is a flex line with one icon at the
   start, so everything after it is a single grid holding both numbers — that is
   what keeps the second number aligned under the first instead of under the
   glyph. */
.footer__phones{display:grid;gap:10px}
/* `block`, not `grid`: the label is its own line but the number and its
   "(Head-Office)" note must stay on ONE line together. As grid items they
   became two rows, which read as a third number. */
.footer__phone{display:block;line-height:1.5}

/* The labels are what make two numbers useful rather than confusing, so they
   are quiet but not decorative: small and uppercase to read as a field name,
   and NOT so faint that they fail contrast — .55 alpha on this navy is about
   4.8:1, which clears AA for the size. Do not take it lower. */
.footer__phoneLabel{display:block;font-size:.72rem;letter-spacing:.06em;
  text-transform:uppercase;color:rgba(255,255,255,.55)}
.footer__phoneNote{color:rgba(255,255,255,.55)}

/* ===========================================================================
   rev 67 — the Contact page
   =========================================================================== */

/* Hero. Rick asked for gradients and a grid; both are decoration, drawn in CSS
   rather than shipped as an image, so the page stays dependency-free and the
   pattern stays sharp at any size. The grid is masked so it fades out rather
   than stopping at a hard edge, which is what makes it read as texture instead
   of as a table. */
.sHero--contact .sHero__bg{
  background:
    radial-gradient(900px 480px at 88% -8%, rgba(55,99,231,.22), transparent 62%),
    radial-gradient(700px 420px at 4% 108%, rgba(55,99,231,.13), transparent 60%),
    linear-gradient(168deg, #F7F9FE 0%, #EDF1FD 46%, #FFF 100%)}
.sHero--contact .sHero__bg::after{
  content:"";position:absolute;inset:0;
  background-image:
    linear-gradient(to right, rgba(55,99,231,.09) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(55,99,231,.09) 1px, transparent 1px);
  background-size:56px 56px;
  -webkit-mask-image:radial-gradient(120% 90% at 50% 0%, #000 22%, transparent 76%);
  mask-image:radial-gradient(120% 90% at 50% 0%, #000 22%, transparent 76%)}
.sHero--contact .sHero__bg{overflow:hidden}
/* The two rules that lived here are gone (rev 79).

   `.sHero--contact .container{min-height:clamp(470px,40vw,600px)}` existed
   because the carousel used to float absolutely over the banner and so
   contributed no height of its own — the container had to be propped up or the
   panel was clipped. The carousel is now an ordinary grid item in
   `.sHero--banner`, so it contributes its own height, and that prop was the
   single reason the Contact banner came out 625px against the homepage's 578:
   40vw of 1440 is 576, and the banner was sized to the prop rather than to its
   contents. An extra padding-bottom went with it for the same reason.

   Anything propping up a height "because the thing inside is positioned" has to
   come out the moment that thing stops being positioned. */
.sHero--contact .sHero__copy{max-width:52ch}

/* The premises carousel, floating over the right of the hero. */
/* Landscape from rev 68, so the panel is wider and shorter than the portrait
   version it replaces. */
.gal{position:absolute;top:clamp(84px,11vw,124px);right:clamp(24px,4vw,64px);
  width:clamp(300px,34vw,470px);z-index:2;
  background:#fff;border:1px solid var(--line);border-radius:22px;padding:12px;
  box-shadow:0 18px 44px rgba(16,24,40,.14)}
/* A real scroll container, not stacked layers: with gallery.js missing this is
   still a swipeable strip of every photograph. */
.gal__track{list-style:none;display:flex;gap:12px;margin:0;padding:0;
  overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;
  border-radius:14px}
.gal__track::-webkit-scrollbar{display:none}
.gal__slide{flex:0 0 100%;scroll-snap-align:start;min-width:0}
/* `height:auto` is load-bearing, not tidying. The width/height ATTRIBUTES on
   the <img> map to presentational width/height properties, and a used `height`
   beats `aspect-ratio` — so with real photographs in place every frame was
   rendering at the file's own pixel height (588x941 for a 1672x941 shot)
   instead of the 16:9 box, squashing the picture and blowing out the banner.
   The attributes still have to be there and still have to be right: they are
   what reserves the space before this stylesheet arrives. `height:auto` lets
   aspect-ratio take over once it does. */
.gal__slide img{display:block;width:100%;height:auto;aspect-ratio:4/3;
  object-fit:cover;object-position:center;
  border-radius:14px;background:var(--brand-tint-2)}
.gal__slot{display:grid;place-content:center;justify-items:center;gap:8px;
  text-align:center;aspect-ratio:4/3;border:2px dashed var(--line);
  border-radius:14px;background:var(--brand-tint-2);padding:18px}
.gal__icon{display:grid;place-content:center;width:44px;height:44px;border-radius:12px;
  background:#fff;border:1px solid var(--line);color:var(--brand)}
.gal__slotLabel{font-weight:700;color:var(--ink);font-size:.9375rem}
.gal__slotHint{font-size:.75rem;color:var(--muted);line-height:1.5}
.gal__slotHint code{font-size:.9em;background:#fff;padding:1px 4px;border-radius:4px;
  border:1px solid var(--line)}
.gal__cap{margin-top:10px;font-size:.8125rem;font-weight:650;color:var(--ink);
  text-align:center}
/* The photo list is unbounded, so the dot row wraps and caps its height rather
   than pushing the panel wider. Past a couple of rows it reads as a strip,
   which is fine — the dots are a position indicator, not the main control. */
.gal__dots{display:flex;flex-wrap:wrap;justify-content:center;gap:7px;margin-top:10px;
  max-height:38px;overflow:hidden}
.gal__dot{width:7px;height:7px;padding:0;border:0;border-radius:50%;cursor:pointer;
  background:var(--line);transition:background .2s ease,width .2s ease}
.gal__dot:hover{background:var(--muted)}
.gal__dot.is-on{background:var(--brand);width:18px;border-radius:999px}
.gal__dot:focus-visible{outline:2px solid var(--brand);outline-offset:3px}
.gal__pause{position:absolute;top:20px;right:20px;border:0;border-radius:999px;
  padding:5px 11px;font:inherit;font-size:.6875rem;font-weight:700;cursor:pointer;
  letter-spacing:.04em;text-transform:uppercase;
  background:rgba(22,28,45,.62);color:#fff;backdrop-filter:blur(4px)}
.gal__pause:hover{background:rgba(22,28,45,.82)}
.gal__pause:focus-visible{outline:2px solid #fff;outline-offset:2px}
.gal__pauseOff{display:none}
.gal.is-paused .gal__pauseOn{display:none}
.gal.is-paused .gal__pauseOff{display:inline}

/* Where we are: details beside the map. */
.where{display:grid;grid-template-columns:.85fr 1.15fr;gap:clamp(24px,3vw,44px);
  align-items:stretch;margin-top:clamp(26px,3vw,40px)}
.where__info{display:flex;flex-direction:column;gap:18px}
.where__h{font-size:1.0625rem;letter-spacing:.04em;text-transform:uppercase;
  color:var(--muted)}
.where__addr{font-style:normal;font-size:1.0625rem;line-height:1.7;color:var(--ink)}
.where__list{list-style:none;display:grid;gap:12px}
.where__list li{display:flex;align-items:center;gap:10px;color:var(--muted)}
.where__list svg{color:var(--brand);flex:none}

/* The two phone numbers (rev 64). Only the first row draws the phone glyph;
   the second gets an empty span of the same width so its label and number line
   up under the first rather than under the icon. 15px is `.ico--xs` — there is
   no custom property for it, so if that rule's width changes this must too. */
.where__phone{align-items:flex-start}
.where__phoneGap{flex:none;width:15px}
/* `block`, not `grid` — see the footer note above: the number and its
   "(Head-Office)" must share a line, and grid items cannot. */
.where__phoneBody{display:block;line-height:1.5}
.where__phoneLabel{display:block;font-size:.72rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted)}
.where__phoneNote{color:var(--muted)}
/* The pair reads as one block, so the gap between the two numbers is tighter
   than the gap to the email row below them. */
.where__list .where__phone + .where__phone{margin-top:-4px}

.where__note{color:var(--muted);font-size:.9125rem;max-width:44ch}
.where__actions{display:flex;flex-wrap:wrap;gap:12px;margin-top:auto}

/* The fallback sits BEHIND the iframe, not beside it: wherever the frame is
   blocked — the shared artifact blocks external frames — this shows through
   with the address and the buttons above still working. */
.where__map{position:relative;border-radius:18px;overflow:hidden;
  border:1px solid var(--line);background:var(--brand-tint-2);min-height:380px}
.where__mapFallback{position:absolute;inset:0;display:grid;place-content:center;
  justify-items:center;gap:8px;text-align:center;padding:26px}
.where__mapIcon{display:grid;place-content:center;width:52px;height:52px;
  border-radius:14px;background:#fff;border:1px solid var(--line);color:var(--brand)}
.where__mapLabel{font-weight:700;color:var(--ink)}
.where__mapHint{font-size:.8125rem;color:var(--muted);max-width:30ch}
.where__frame{position:relative;display:block;width:100%;height:100%;
  min-height:380px;border:0}
/* `js-map` is added by gallery.js, so this only hides the frame where there is
   script to bring it back. A failed iframe paints its own grey error surface,
   which would otherwise sit on top of the fallback. */
.js-map .where__frame{opacity:0;transition:opacity .25s ease}
.js-map.is-live .where__frame{opacity:1}
.js-map.is-live .where__mapFallback{opacity:0;pointer-events:none}

@media (max-width:1180px){
  .gal{width:clamp(280px,32vw,380px);top:clamp(70px,9vw,100px)}
}
@media (max-width:980px){
  /* Below this the hero cannot hold a floating panel without squeezing the
     headline, so the carousel drops under the copy at full width. */
  .gal{position:static;width:100%;max-width:560px;margin:26px auto 0}
  .where{grid-template-columns:1fr}
  .where__actions{margin-top:0}
}
@media (max-width:640px){
  .where__map,.where__frame{min-height:300px}
}

/* Reduced motion: gallery.js starts paused, and the scroll jump is instant. */
@media (prefers-reduced-motion:reduce){
  .gal__track{scroll-behavior:auto}
  .gal__dot{transition:none}
}

/* The footer's Contact heading is a link now; keep it looking like the other
   column headings rather than like a body link. */
.footer__contact h3 a{color:#fff}
.footer__contact h3 a:hover{color:rgba(255,255,255,.72)}

/* ===========================================================================
   rev 69 — enquiry form: two-column grid and the description editor
   =========================================================================== */
/* Rev 70: one column, in the portal's own order, with the label beside its
   control rather than above it — the shape of the form in the screenshot. */
.enq__grid{display:grid;gap:20px}
.enq__grid .fld{grid-template-columns:172px minmax(0,1fr);align-items:start;
  column-gap:20px;row-gap:6px}
.enq__grid .fld > label{padding-top:11px}
/* The help text and the error sit under the control, not under the label. */
.enq__grid .fld > .fld__help,
.enq__grid .fld > .fld__err{grid-column:2}
/* Selects read as selects at a natural width; a full-width dropdown with three
   options in it looks like a mistake. */
.enq__grid .fld select{max-width:340px}

/* --- the rich-text description ------------------------------------------ */
/* The textarea ships visible and works on its own; enquiry.js hides it only
   once the editor that replaces it exists. */
.rte{border:1px solid var(--line);border-radius:10px;background:#fff;overflow:hidden}
.rte:focus-within{border-color:var(--brand);box-shadow:0 0 0 4px rgba(55,99,231,.16)}
.rte__bar{display:flex;flex-wrap:wrap;align-items:center;gap:2px;padding:6px 8px;
  border-bottom:1px solid var(--line);background:var(--brand-tint-2)}
.rte__bar[hidden]{display:none}
.rte__btn{min-width:30px;height:30px;padding:0 7px;border:1px solid transparent;
  border-radius:7px;background:none;cursor:pointer;color:var(--ink);
  font:inherit;font-size:.875rem;line-height:1;display:inline-grid;place-content:center}
.rte__btn:hover{background:#fff;border-color:var(--line)}
.rte__btn.is-on{background:var(--brand-tint);border-color:var(--brand);color:var(--brand)}
.rte__btn:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.rte__btn--bold{font-weight:800}
.rte__btn--italic{font-style:italic;font-family:Georgia,serif}
.rte__btn--underline{text-decoration:underline}
.rte__btn--strikethrough{text-decoration:line-through}
.rte__btn--removeformat{font-size:.8125rem;font-weight:700;letter-spacing:-.02em}
.rte__btn svg{display:block}
.rte__sep{width:1px;height:18px;margin:0 5px;background:var(--line)}
.rte__link{display:flex;align-items:center;gap:6px;flex:1 1 220px;margin-left:6px}
.rte__link[hidden]{display:none}
.rte__link input{flex:1;min-width:0;padding:5px 9px;border:1px solid var(--line);
  border-radius:7px;font:inherit;font-size:.875rem}
.rte__link input:focus{outline:none;border-color:var(--brand)}
.rte__go,.rte__cancel{border:1px solid var(--line);background:#fff;border-radius:7px;
  padding:5px 10px;font:inherit;font-size:.8125rem;font-weight:650;cursor:pointer}
.rte__go{background:var(--brand);border-color:var(--brand);color:#fff}
.rte__area{min-height:170px;max-height:420px;overflow-y:auto;padding:13px 14px;
  font:inherit;line-height:1.6;color:var(--ink);outline:none}
.rte__area:empty::before{content:attr(data-placeholder);color:var(--muted)}
.rte__area ul,.rte__area ol{margin:8px 0 8px 22px}
.rte__area li{margin:3px 0}
.rte__area a{color:var(--brand);text-decoration:underline}
/* Once mirrored, the textarea is the form's value and nothing else — off screen
   but still submitted. display:none would also work; this keeps it selectable
   by scripts that measure it. */
.fld textarea.is-mirrored{position:absolute;width:1px;height:1px;padding:0;border:0;
  opacity:0;pointer-events:none;overflow:hidden;clip-path:inset(50%)}
.fld[data-bad] .rte{border-color:#f97066}

/* Visually hidden, still announced. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}

@media (max-width:720px){
  /* Label above its control — 150px of label plus a usable field does not fit
     on a phone. */
  .enq__grid .fld{grid-template-columns:1fr}
  .enq__grid .fld > label{padding-top:0}
  .enq__grid .fld > .fld__help,
  .enq__grid .fld > .fld__err{grid-column:1}
  .enq__grid .fld select{max-width:none}
}

/* The story strip's empty state. A pillar can legitimately have no story on the
   homepage six, and an empty grid with no explanation reads as a broken filter. */
.work__empty{text-align:center;color:var(--muted);padding:34px 0 6px}
.work__empty[hidden]{display:none}
.story__grid.is-empty{min-height:0}

/* Certification tile marks: the real ISO and Clutch logos, height-capped so
   the wide Clutch wordmark and the square ISO mark sit on one line. */
.certTile__logo{max-height:26px;max-width:92px;width:auto;height:auto;
  object-fit:contain;display:block;margin:0}

/* Two recognition tiles, not four (Rick, 30 Sep 2026) — centre the pair
   rather than letting them stretch across the four-up track. */
.recog--two{max-width:640px}

/* ---------------------------------------------------------------------------
   The Clutch review request, hero slide 2 (rev 74)
   ---------------------------------------------------------------------------
   A card on the hero's own light background. It deliberately does NOT use the
   glassy .ccard treatment from the certifications slide: this is an ask, not a
   credential, and dressing it like the proof tiles beside it would blur the
   line between "here is our record" and "please add to it".
   -------------------------------------------------------------------------- */
.revAsk{
  justify-self:end;align-self:center;max-width:380px;width:100%;
  display:flex;flex-direction:column;align-items:flex-start;gap:12px;
  padding:clamp(24px,2.4vw,32px);border-radius:var(--radius-lg);
  background:rgba(255,255,255,.72);border:1px solid var(--line);
  /* The hero draws an animated mesh behind this. Without the blur the dots
     track through the card and the text sits on moving texture. */
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  box-shadow:0 12px 34px rgba(16,24,40,.10);
}
.revAsk__icon{
  display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;
  border-radius:12px;background:var(--brand-tint-2);color:var(--brand);flex:none;
}
.revAsk__h{font-size:1.25rem;font-weight:650;color:var(--hero-ink);line-height:1.2}
.revAsk__p{color:var(--hero-body);font-size:.9375rem;line-height:1.55}
.revAsk__cta{margin-top:2px}
.revAsk__note{color:var(--muted);font-size:.78rem;line-height:1.45}

/* 640px, NOT a round 900: that is where `.slide__inner--split` actually drops
   to one column (line ~1092). Guessing 900 would have stretched the card
   inside a still-two-column grid for the whole 640-900 band, which is the
   width most tablets land on. */
@media (max-width:640px){
  .revAsk{justify-self:stretch;max-width:none;margin-top:22px}
}

/* Testimonials: one live tab (Clutch) and one inert one (Direct), pending real
   reviews. The inert tab stays visible so the section reads as unfinished on
   purpose rather than missing — but it takes no pointer and no focus. */
.ptab--soon{opacity:.45;cursor:default;pointer-events:none}
.ptab--soon .ptab__score{font-size:.72rem;letter-spacing:.04em;text-transform:uppercase;opacity:.8}
.clutchMount{display:flex;justify-content:center}
.clutchFallback{max-width:560px;text-align:center;padding:34px 30px;border-radius:18px;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1)}
.clutchFallback__score{display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap}
.clutchFallback__score b{font-size:2.6rem;line-height:1;letter-spacing:-.02em}
.clutchFallback__stars{display:inline-flex;gap:2px;color:#f5b301}
.clutchFallback__meta{width:100%;font-size:.9rem;opacity:.72}
.clutchFallback__body{margin:16px 0 22px;font-size:.95rem;line-height:1.6;opacity:.85}

/* ===================== CLUTCH WIDGET =====================
   The reviews are Clutch's official rotator widget in an iframe we do not
   control. None of these rules reach inside it — they frame it, centre it and
   give it a surround that matches the section, so the widget's own primary
   colour (data-primary-color) sits on something close rather than on a hard
   edge. Do not try to restyle its contents; it is cross-origin and the rules
   would silently do nothing. The two real levers are data-widget-type and
   data-primary-color on the embed itself. */
.clutchMount{display:block}
.clutchFrame{max-width:1040px;margin:0 auto;padding:10px;border-radius:18px;
  background:rgba(15,23,42,.72);border:1px solid #1E293B;overflow:hidden}
.clutchFrame .clutch-widget{display:block;width:100%;margin:0}
.clutchFrame iframe{display:block;width:100%!important;border:0;border-radius:12px}
/* Until the widget lands the frame would be a 10px sliver; hold the height so
   the page does not jump when it arrives. data-height is 375. */
.clutchMount:not(.is-live) .clutchFrame{min-height:395px}
.clutchMount.is-fallback .clutchFrame{display:none}

.clutchFallback{max-width:560px;margin:0 auto;text-align:center;padding:34px 30px;
  border-radius:16px;background:rgba(15,23,42,.72);border:1px solid #1E293B}
.clutchFallback__score{display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap}
.clutchFallback__score b{font-size:2.6rem;line-height:1;letter-spacing:-.02em;color:#fff}
.clutchFallback__stars{display:inline-flex;gap:2px;color:#F5B301}
.clutchFallback__meta{width:100%;font-size:.9rem;color:#94A3B8}
.clutchFallback__body{margin:16px 0 0;font-size:.95rem;line-height:1.6;color:#CBD5E1}

.clutchCta{text-align:center;margin-top:26px}
.clutchCta__note{margin:14px auto 0;max-width:600px;font-size:.82rem;line-height:1.6;color:#64748B}

@media (max-width:640px){ .clutchFrame{padding:6px} }

/* ===================== RELATED CASE STUDIES =====================
   Three cards at the foot of every case study, chosen by shared services
   first and pillar second (see make_case.related_cases). Built on the same
   surface and lift as .csServices__grid so the two blocks read as one family
   rather than two designs stacked on each other.

   The card is the anchor, and the lift is on the card itself rather than an
   inner element — unlike the homepage story cards, nothing here overlaps, so
   moving the hover target cannot make the pointer flicker in and out. */
.csRel{margin-top:34px}
.csRel__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:18px}
.csRel__card{display:flex;flex-direction:column;gap:9px;padding:18px 20px;
  border-radius:var(--radius-sm);background:#fff;border:1px solid var(--line);
  text-decoration:none;
  transition:transform .3s ease-in-out,box-shadow .3s ease,border-color .3s ease}
.csRel__card:hover{transform:translateY(-3px);border-color:#C6D6F6;box-shadow:var(--shadow-sm)}
.csRel__eyebrow{font-size:.6875rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--brand)}
.csRel__title{font-size:.9375rem;font-weight:650;line-height:1.45;color:var(--navy)}
.csRel__go{margin-top:auto;display:inline-flex;align-items:center;gap:6px;
  font-size:.8125rem;font-weight:600;color:var(--muted)}
.csRel__card:hover .csRel__go{color:var(--brand)}
.csRel__go .ico{transition:transform .3s ease}
.csRel__card:hover .csRel__go .ico{transform:translateX(3px)}
@media (max-width:900px){ .csRel__grid{grid-template-columns:1fr} }

/* Inline contextual crosslinks (crosslink.py). Brand colour alone was not
   enough — un-underlined blue inside a grey paragraph reads as emphasis, not
   as a link, and the whole point of these is that a reader notices there is
   somewhere to go. The offset keeps the rule clear of descenders. */
.xlink{
  text-decoration:underline;
  text-decoration-color:rgba(55,99,231,.4);
  text-decoration-thickness:1px;
  text-underline-offset:3px;
  transition:text-decoration-color .2s var(--ease),color .2s var(--ease);
}
.xlink:hover,.xlink:focus-visible{text-decoration-color:currentColor}

/* ============================================================================
   BLOG — hub (.bhero/.bgrid) and article (.post*)
   Added 1 October 2026 with the migration of the 60 WordPress articles.
   Reuses .sBody / .rail from the case-study template rather than defining a
   third body layout, so an article inherits the sticky rail already proven
   there.
   ========================================================================= */

/* The 30ch cap that used to sit here was left over from a wider layout and
   held the h1 to a third of the column, so the title sat visibly left of the
   banner and body it belongs to. The measure is the container's job now. */

/* --- hub hero --- */
.bhero{padding:28px 0 8px;background:#fff}
.bhero__title{margin:10px 0 10px;font-size:clamp(1.9rem,4vw,2.9rem);line-height:1.1;
  letter-spacing:-.02em}
.bhero__lead{max-width:62ch;margin:0 0 22px;color:var(--muted);font-size:1.0625rem;line-height:1.7}

.bsearch{position:relative;max-width:520px;margin:0 0 18px}
.bsearch__i{position:absolute;left:14px;top:50%;transform:translateY(-50%);
  width:18px;height:18px;color:var(--muted);pointer-events:none}
.bsearch input{width:100%;padding:13px 40px 13px 42px;border:1px solid var(--line);
  border-radius:999px;background:var(--grey);font:inherit;font-size:.9375rem;color:inherit}
.bsearch input:focus{outline:none;border-color:var(--brand);background:#fff;
  box-shadow:0 0 0 3px rgba(55,99,231,.14)}
.bsearch__clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);
  width:28px;height:28px;border:0;border-radius:50%;background:transparent;
  color:var(--muted);font-size:1.25rem;line-height:1;cursor:pointer}
.bsearch__clear:hover{background:var(--line);color:var(--ink)}

.bpills{display:flex;flex-wrap:wrap;gap:8px;padding-bottom:24px}
.bpill{padding:8px 15px;border:1px solid var(--line);border-radius:999px;background:#fff;
  font:inherit;font-size:.875rem;font-weight:600;color:var(--muted);cursor:pointer;
  transition:background .18s,color .18s,border-color .18s}
.bpill:hover{border-color:var(--brand);color:var(--brand)}
.bpill.is-on{background:var(--brand);border-color:var(--brand);color:#fff}
.bpill__n{margin-left:6px;opacity:.65;font-weight:500}

.bcount{margin:0 0 16px;color:var(--muted);font-size:.875rem}
.bempty{margin:8px 0 0;color:var(--muted)}
.linkish{border:0;background:none;padding:0;font:inherit;color:var(--brand);
  text-decoration:underline;cursor:pointer}

/* --- hub grid --- */
.bgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;list-style:none;margin:0;padding:0}
.bcard{display:flex}
.bcard__link{display:flex;flex-direction:column;width:100%;border:1px solid var(--line);
  border-radius:var(--radius);background:#fff;overflow:hidden;text-decoration:none;
  color:inherit;box-shadow:var(--shadow-sm);transition:box-shadow .22s,transform .22s,border-color .22s}
.bcard__link:hover{border-color:#C9D8F6;box-shadow:0 10px 28px rgba(16,32,68,.10);transform:translateY(-2px)}
.bcard__media{display:block;aspect-ratio:16/9;background:var(--grey);overflow:hidden}
.bcard__media img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .4s ease}
/* The lift is on the card and the zoom on the image inside it. Both on the
   card would make the hover target move under the pointer. */
.bcard__link:hover .bcard__media img{transform:scale(1.04)}
.bcard__body{display:flex;flex-direction:column;flex:1;gap:7px;padding:18px 18px 20px}
.bcard__cat{align-self:flex-start;padding:3px 10px;border-radius:999px;background:#EEF3FF;
  color:var(--brand);font-size:.6875rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
.bcard__date{color:var(--muted);font-size:.8125rem}
.bcard__title{font-size:1.0625rem;font-weight:600;line-height:1.35}
.bcard__excerpt{color:var(--muted);font-size:.875rem;line-height:1.6;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.bcard__go{margin-top:auto;padding-top:10px;color:var(--brand);font-size:.875rem;font-weight:600;
  display:inline-flex;align-items:center;gap:6px}
.bcard__link:hover .bcard__go .ico{transform:translateX(3px)}
.bcard__go .ico{transition:transform .22s}
.bmore{display:flex;justify-content:center;padding-top:28px}

/* ---------------------------------------------------------------------------
   ARTICLE PAGE
   One centred column for everything: breadcrumb, banner, title, meta, body and
   the closing band all share `.postWrap`, so there is a single left edge down
   the page. The sticky side rail is gone — a sidebar and a centred measure
   cannot both be true, and the measure is what makes a 1,500-word guide
   readable.
   ------------------------------------------------------------------------ */
.postWrap{max-width:800px;margin:0 auto;padding:0 16px}

/* --- banner, first on the page --- */
.postBanner{max-width:1000px;margin:14px auto 26px;padding:0 16px}
/* The frame is what stops a small image being stretched. `object-fit:contain`
   alone does not prevent upscaling — the IMG box still grows to the container
   and the picture is drawn blurry inside it. A max-width on the image at its
   own intrinsic size, centred in a neutral frame, is what actually holds it. */
.postBanner__frame{display:flex;align-items:center;justify-content:center;
  background:var(--grey);border:1px solid var(--line);border-radius:var(--radius);
  overflow:hidden}
.postBanner__frame img{max-width:100%;width:auto;height:auto;display:block;
  object-fit:contain}

/* --- head --- */
.postHead{padding:0 16px}
.postCat{display:inline-block;margin:0 0 14px;padding:4px 12px;border-radius:999px;
  background:#EEF3FF;color:var(--brand);font-size:.6875rem;font-weight:700;
  letter-spacing:.04em;text-transform:uppercase;text-decoration:none}
.postCat:hover{background:var(--brand);color:#fff}
.postHead__title{margin:0 0 14px;font-size:clamp(1.7rem,3.2vw,2.3rem);line-height:1.25;
  letter-spacing:-.018em}
.postMeta{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 30px;
  color:var(--muted);font-size:.9375rem}
.postMeta__sep{opacity:.5}

/* --- contents card --- */
.postToc{margin:0 0 34px;padding:18px 22px;border:1px solid var(--line);
  border-radius:var(--radius);background:var(--grey)}
.postToc__label{margin:0 0 10px;font-size:.75rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted)}
.postToc ol{margin:0;padding-left:20px}
.postToc li{margin:0 0 7px;line-height:1.55;font-size:.9375rem}
.postToc a{color:var(--navy);text-decoration:none}
.postToc a:hover{color:var(--brand);text-decoration:underline}

/* --- body typography --- */
/* No max-width override here: .postBody also carries .postWrap, and setting
   max-width:none on it undid the 800px measure the whole layout is built on. */
.postBody p{margin:0 0 1.5rem;font-size:1.125rem;line-height:1.75;white-space:normal}
.postBody h2{margin:2.75rem 0 1rem;font-size:1.5rem;line-height:1.3;letter-spacing:-.012em}
.postBody h3{margin:2.25rem 0 .75rem;font-size:1.2rem;line-height:1.35}
.postBody h4{margin:1.75rem 0 .6rem;font-size:1.0625rem;line-height:1.4}
.postBody > :first-child{margin-top:0}
.postBody ul,.postBody ol{margin:0 0 1.5rem;padding-left:26px}
.postBody li{margin:0 0 .6rem;font-size:1.125rem;line-height:1.75}
.postBody li::marker{color:var(--muted)}
.postBody a{color:var(--brand);text-decoration:underline;
  text-decoration-color:rgba(55,99,231,.4);text-underline-offset:3px}
.postBody a:hover{text-decoration-color:var(--brand)}
.postBody blockquote{margin:0 0 1.5rem;padding:16px 20px;border-left:3px solid var(--brand);
  background:var(--grey);border-radius:0 var(--radius) var(--radius) 0}
.postBody blockquote p{margin:0}

/* --- in-article screenshots --- */
/* Centred, never upscaled. `width:auto` is the rule that matters: with
   width:100% a 400px screenshot is blown up to the column and goes soft, which
   is exactly what makes a UI capture unreadable. */
.postFig{margin:2rem auto;text-align:center}
.postFig img{max-width:min(100%,768px);width:auto;height:auto;display:inline-block;
  object-fit:contain;border:1px solid var(--line);border-radius:10px;
  background:var(--grey)}
.tableWrap{overflow-x:auto;margin:0 0 1.5rem}
.tableWrap table{border-collapse:collapse;width:100%;font-size:.9375rem}
.tableWrap td{border:1px solid var(--line);padding:9px 12px;vertical-align:top}

/* --- related articles --- */
.relPosts{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;list-style:none;margin:0;padding:0}
.relPost a{display:flex;flex-direction:column;height:100%;border:1px solid var(--line);
  border-radius:var(--radius);background:#fff;overflow:hidden;text-decoration:none;color:inherit;
  transition:box-shadow .22s,border-color .22s}
.relPost a:hover{border-color:#C9D8F6;box-shadow:0 8px 22px rgba(16,32,68,.09)}
.relPost__img{display:block;aspect-ratio:16/9;background:var(--grey)}
.relPost__img img{width:100%;height:100%;object-fit:cover;display:block}
.relPost__body{display:flex;flex-direction:column;gap:6px;padding:14px 16px 16px}
.relPost__cat{color:var(--brand);font-size:.6875rem;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase}
.relPost__title{font-size:.9375rem;font-weight:600;line-height:1.4}
.relPost__date{color:var(--muted);font-size:.8125rem}

@media (max-width:1024px){
  .bgrid,.relPosts{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:640px){
  .bgrid,.relPosts{grid-template-columns:1fr}
  .postHead__title{font-size:1.5rem}
  .postFig img{max-height:none}
}
@media (prefers-reduced-motion:reduce){
  .bcard__link,.bcard__media img,.bcard__go .ico{transition:none}
  .bcard__link:hover{transform:none}
  .bcard__link:hover .bcard__media img{transform:none}
}


/* ============================================================================
   CLOSING CTA BAND
   The blog templates first used a .cta block whose classes did not exist in
   this stylesheet at all, so the heading, the copy and both buttons rendered
   with browser defaults and sat flush against the footer with no gap. This is
   the real component.
   ========================================================================= */
.endCta{padding-top:8px;padding-bottom:56px}
.endCta__panel{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:24px;padding:38px 40px;border:1px solid var(--line);border-radius:var(--radius);
  background:linear-gradient(135deg,var(--brand-tint-2,#F2F6FF) 0%,#fff 70%)}
.endCta__copy{flex:1 1 380px;min-width:0}
.endCta__title{margin:0 0 8px;font-size:1.375rem;line-height:1.3;letter-spacing:-.012em}
.endCta__sub{margin:0;color:var(--muted);font-size:.9375rem;line-height:1.65;max-width:56ch}
.endCta__btns{display:flex;flex-wrap:wrap;gap:12px}

@media (max-width:640px){
  .endCta__panel{padding:26px 22px}
  .endCta__btns .btn{flex:1 1 100%}
}

/* ============================================================================
   BLOG ARTICLE PANELS — Related services, then More articles in <category>
   Both sit in the article's own 800px measure so the page keeps one left edge
   from the breadcrumb to the footer.
   ========================================================================= */
.panels{margin-top:48px}
.panelRule{height:0;margin:0 0 48px;border:0;border-top:1px solid var(--line)}
.panel{margin:0 0 48px}
.panel__title{margin:0 0 20px;font-size:1.25rem;line-height:1.3;letter-spacing:-.01em}

/* --- Panel 1: services --- */
.svcCards{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;
  list-style:none;margin:0;padding:0}
.svcCard a{display:flex;flex-direction:column;gap:8px;height:100%;padding:24px;
  border:1px solid #E2E8F0;border-radius:12px;background:#fff;text-decoration:none;
  color:inherit;box-shadow:var(--shadow-sm);
  transition:transform .22s ease,box-shadow .22s ease,border-color .22s ease}
.svcCard a:hover{transform:translateY(-2px);border-color:#C9D8F6;
  box-shadow:0 10px 26px rgba(16,32,68,.10)}
.svcCard__pill{align-self:flex-start;padding:3px 10px;border-radius:999px;
  background:#EEF3FF;color:var(--brand);font-size:.6875rem;font-weight:700;
  letter-spacing:.04em;text-transform:uppercase}
.svcCard__title{font-size:1rem;font-weight:600;line-height:1.35;color:var(--navy)}
.svcCard__lead{color:var(--muted);font-size:.875rem;line-height:1.6}
.svcCard__go{margin-top:auto;padding-top:10px;color:var(--brand);font-size:.875rem;
  font-weight:600;display:inline-flex;align-items:center;gap:6px}
.svcCard a:hover .svcCard__go .ico{transform:translateX(3px)}
.svcCard__go .ico{transition:transform .22s}

/* --- Panel 2: sibling articles --- */
.pcards{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;
  list-style:none;margin:0;padding:0}
.pcards .pcard a{display:flex;flex-direction:column;height:100%;border:1px solid #E2E8F0;
  border-radius:12px;background:#fff;overflow:hidden;text-decoration:none;color:inherit;
  box-shadow:var(--shadow-sm);
  transition:transform .22s ease,box-shadow .22s ease,border-color .22s ease}
.pcards .pcard a:hover{transform:translateY(-2px);border-color:#C9D8F6;
  box-shadow:0 10px 26px rgba(16,32,68,.10)}
/* flex:none is load-bearing. These are column flex items, and a flex child
   with an aspect-ratio will happily shrink when a sibling grows — a card with
   a five-line headline squashed its own thumbnail to a strip while the cards
   either side kept theirs. */
.pcard__media{display:block;flex:none;aspect-ratio:16/9;background:var(--grey);overflow:hidden}
.pcard__media img{width:100%;height:100%;object-fit:cover;display:block}
.pcard__body{display:flex;flex-direction:column;gap:6px;padding:16px 18px 18px}
.pcard__date{color:var(--muted);font-size:.8125rem}
/* Three lines, so one long headline cannot set the height of the whole row. */
.pcard__title{font-size:.9375rem;font-weight:600;line-height:1.4;color:var(--navy);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.pcard__excerpt{color:var(--muted);font-size:.8125rem;line-height:1.55;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

@media (max-width:900px){
  .svcCards,.pcards{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:560px){
  .svcCards,.pcards{grid-template-columns:1fr}
}
/* The lift is the only motion here; without this it still runs for a reader
   who has asked the system for none. */
@media (prefers-reduced-motion:reduce){
  .svcCard a,.pcards .pcard a,.svcCard__go .ico{transition:none}
  .svcCard a:hover,.pcards .pcard a:hover{transform:none}
  .svcCard a:hover .svcCard__go .ico{transform:none}
}

/* ============================================================================
   SITEMAP
   ========================================================================= */
.smGrid{display:grid;grid-template-columns:repeat(2,1fr);gap:28px 40px;margin-top:28px}
.smGroup__title{display:flex;align-items:baseline;gap:10px;margin:0 0 12px;
  font-size:1.0625rem;line-height:1.3}
.smGroup__n{font-size:.8125rem;font-weight:600;color:var(--muted)}
.smList{margin:0;padding:0;list-style:none;columns:2;column-gap:28px}
.smList li{margin:0 0 7px;break-inside:avoid;font-size:.875rem;line-height:1.5}
.smList a{color:var(--muted);text-decoration:none}
.smList a:hover{color:var(--brand);text-decoration:underline}
/* The blog and the service list are long; one column reads better than two
   broken mid-title. */
.smGroup:first-child .smList,.smGroup--wide .smList{columns:1}
@media (max-width:900px){
  .smGrid{grid-template-columns:1fr}
  .smList{columns:1}
}
/* The footer heading is a link now; it must not look like dead text. */
.footer__col h3 a{color:inherit;text-decoration:none}
.footer__col h3 a:hover{color:#fff;text-decoration:underline}

/* =========================================================================
   INSIDE OUR OFFICE — the facility tour
   Floor-by-floor sections, each with its own carousel. The carousel itself is
   the shared .gal component; everything here is either the in-flow variant of
   it or the furniture around it.
   ========================================================================= */

/* --- the carousel, in flow ------------------------------------------------
   The Contact hero's .gal floats over the banner (position:absolute). Here it
   is an ordinary block in a two-column section, so the positioning is undone
   and position:relative is set instead — the arrows and the pause button are
   absolutely positioned against it, and with position:static they would escape
   to the nearest positioned ancestor. */
.gal--flow{position:relative;top:auto;right:auto;width:auto;z-index:auto}
.gal--flow .gal__slide img,.gal--flow .gal__slot{aspect-ratio:16/9}
.gal--flow .gal__cap{margin-top:12px}

/* --- arrows ---------------------------------------------------------------
   Overlaid on the photograph rather than placed beside it, so the slide keeps
   the full width of the panel. 44px is the minimum comfortable touch target;
   they stay that size at every breakpoint. */
.gal__arrow{position:absolute;top:calc(50% - 26px);transform:translateY(-50%);
  width:44px;height:44px;display:grid;place-items:center;border:0;cursor:pointer;
  border-radius:50%;background:rgba(255,255,255,.92);color:var(--navy);
  box-shadow:0 4px 14px rgba(16,24,40,.18);
  opacity:0;transition:opacity .2s ease,background .2s ease,transform .2s ease}
.gal__prev{left:20px}
.gal__next{right:20px}
.gal__arrow:hover{background:#fff;color:var(--brand)}
.gal__prev:hover{transform:translateY(-50%) translateX(-2px)}
.gal__next:hover{transform:translateY(-50%) translateX(2px)}
/* Revealed on hover or keyboard focus. Hiding a control behind hover is only
   acceptable where it is not the sole route to the content: the dots are
   always visible, the track is swipeable, and the carousel advances on its
   own — the arrows are a convenience on top of three other ways through. */
.gal:hover .gal__arrow,.gal:focus-within .gal__arrow{opacity:1}
.gal__arrow:focus-visible{opacity:1;outline:2px solid var(--brand);outline-offset:2px}
/* Nothing hovers on a touchscreen, so there they are simply always on. */
@media (hover:none){
  .gal__arrow{opacity:1;background:rgba(255,255,255,.86)}
}

/* --- the highlights bar --------------------------------------------------- */
.hiBar{display:grid;grid-template-columns:repeat(5,1fr);gap:14px;margin:0;padding:0;
  list-style:none}
.hiBar__item{display:flex;flex-direction:column;align-items:center;gap:6px;
  text-align:center;padding:22px 16px;border-radius:var(--radius);background:#fff;
  border:1px solid var(--line);box-shadow:var(--shadow-sm)}
.hiBar__icon{display:grid;place-items:center;width:44px;height:44px;margin-bottom:4px;
  border-radius:13px;background:var(--brand-tint);color:var(--brand)}
.hiBar__v{font-size:1.0625rem;font-weight:700;letter-spacing:-.02em;color:var(--navy);
  line-height:1.25}
.hiBar__n{font-size:.78rem;line-height:1.45;color:var(--muted);max-width:22ch}

/* The floor rail (a five-card jump list) was removed in rev 75 along with the
   separate "Floor by floor" section it sat under — see r_building. Its styles
   went with it rather than being left behind to rot.
   -------------------------------------------------------------------------- */

/* --- a floor -------------------------------------------------------------- */
/* scroll-margin-top keeps a rail jump from parking the heading under the
   sticky navigation ribbon. */
/* The two tracks are named rather than written literally, because the
   alternation below has to swap them.

   `order` reverses what you SEE but not which track an item lands in: with a
   fixed `.85fr 1.15fr` the copy took the wide track on every even floor and the
   gallery took the narrow one, so the five galleries came out 772px, 571px,
   772px, 571px, 772px. Swapping the custom properties moves the widths with the
   items, so the gallery is the wide track on all five.

   It has to be done with custom properties, not by re-declaring
   grid-template-columns on :nth-of-type(even) — that selector outweighs plain
   `.floor`, so it would also beat the single-column rule inside the mobile
   media query and leave the even floors in two columns on a phone. */
.floor{--copy:.85fr;--media:1.15fr;
  display:grid;grid-template-columns:var(--copy) var(--media);
  gap:clamp(24px,3.4vw,52px);
  align-items:center;padding:clamp(28px,3.4vw,46px) 0;border-top:1px solid var(--line);
  scroll-margin-top:96px}
/* The first floor used to open its own section, so it had no rule above it.
   Now it follows the highlights bar inside the same section and needs the
   separator and the breathing room that every other floor gets. */
.floor:first-of-type{margin-top:clamp(10px,1.4vw,20px)}
/* Alternating sides, so five stacked floors do not read as one long column of
   identical rows. :nth-of-type counts .floor elements only. */
.floor:nth-of-type(even){--copy:1.15fr;--media:.85fr}
.floor:nth-of-type(even) .floor__copy{order:2}
.floor__lvl{display:flex;align-items:center;gap:10px;margin:0 0 6px;
  font-size:.8125rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--brand)}
.floor__icon{display:grid;place-items:center;width:34px;height:34px;border-radius:10px;
  background:var(--brand-tint);color:var(--brand)}
.floor__name{font-size:clamp(1.25rem,1rem + .9vw,1.625rem);margin:0 0 .5em}
.floor__lead{color:var(--muted);font-size:.9375rem;line-height:1.72;margin:0 0 18px;
  max-width:50ch}
.floor__amen{display:grid;gap:9px;margin:0;padding:0;list-style:none}
.floor__media{min-width:0}

@media (max-width:1080px){
  .hiBar{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:860px){
  .floor{grid-template-columns:1fr;gap:22px}
  /* The alternation is a desktop device. In one column it would put two of the
     five photographs above their own heading, which reads as a mistake. */
  .floor:nth-of-type(even) .floor__copy{order:0}
}
@media (max-width:620px){
  .hiBar{grid-template-columns:repeat(2,1fr)}
  .gal__arrow{width:40px;height:40px}
  .gal__prev{left:12px}
  .gal__next{right:12px}
}

/* =========================================================================
   ABOUT US — our physical infrastructure
   ========================================================================= */
.infra{display:grid;grid-template-columns:1.02fr .98fr;gap:clamp(26px,3.4vw,52px);
  align-items:center;margin-top:clamp(24px,3vw,38px)}
.infra__body p{color:var(--muted);font-size:.9375rem;line-height:1.75;max-width:54ch}
.infra__badges{display:flex;flex-wrap:wrap;gap:10px;margin:20px 0 22px;padding:0;
  list-style:none}
.infra__badge{display:inline-flex;align-items:center;gap:8px;padding:7px 14px;
  border-radius:999px;background:#fff;border:1px solid var(--line);
  box-shadow:var(--shadow-sm);font-size:.8125rem;font-weight:600;color:var(--navy)}
.infra__badge .ico{color:var(--brand)}
.infra__media{min-width:0}
@media (max-width:860px){
  .infra{grid-template-columns:1fr}
}

/* --- homepage hero, slide 3: the building ---------------------------------
   The same .gal carousel as the floor galleries and the About Us reel, wearing
   the hero's card tokens so the six slides read as one set rather than five
   plus an outlier. It was a single photograph until Rick asked for a gallery
   here (5 Oct 2026).

   No pause button on this one — see the note in make_home.office_media. The
   arrows, the dots and hover-to-hold are all still there, and the banner's own
   rotation already pauses on hover. */
.gal--hero{background:var(--hero-surface);border-color:var(--hero-line);
  border-radius:var(--radius-lg);padding:14px;
  box-shadow:0 14px 34px rgba(0,16,53,.08)}
.gal--hero .gal__track{border-radius:16px}
.gal--hero .gal__slide img,.gal--hero .gal__slot{border-radius:16px}
.gal--hero .gal__track{border-radius:16px}
/* The facility slide has no SVG artwork of its own — the photographs are the
   visual. The tinted wash keeps it from reading as a bare white band. */
.slide__bg--office{background:radial-gradient(720px 420px at 70% 40%,
  rgba(55,99,231,.11),transparent 64%)}
@media (max-width:980px){
  /* Below the split there is no room for it beside the copy, and underneath it
     would push the CTA off the banner. The same photographs are two taps away
     on the facility page the CTA goes to. */
  .slide--office .gal--hero{display:none}
}
.infra__lead{font-size:1.0625rem;line-height:1.72;color:var(--ink)!important;
  margin-bottom:14px}

/* =========================================================================
   THE TALL BANNER — .sHero--banner + .gal--banner
   Used by Inside Our Office (rev 73) and Contact Us (rev 79). Both carry a
   full-height banner, copy on the left, a photograph carousel on the right,
   and both are pinned to the homepage hero's height so moving between the
   three pages does not change the fold.

   It was written for the facility page and named after it. Contact needed the
   identical thing a day later — same height, same two columns, same carousel
   cap — so it is named for what it does rather than for the first page that
   wanted it.
   Rick asked for two things that pull against each other: a banner the same
   height as the homepage hero, and a carousel in it noticeably larger than the
   homepage hero's. The height is the fixed constraint, so the carousel is
   capped at the widest 16:9 frame that still fits inside --hero-h once the
   breadcrumb, the caption and the dot row are accounted for. It comes out
   wider than the homepage one; it could not come out as wide as the column
   would otherwise allow.
   ========================================================================= */

/* .sHero--compact (used by the other About pages) zeroes the min-height; this
   restores the homepage banner's. Declared after it in the file, so it wins at
   equal specificity without an !important. */
.sHero--banner{min-height:var(--hero-h);display:flex;align-items:center;
  padding-block:clamp(14px,1.7vw,24px)}
.sHero--banner>.container{width:100%;
  display:grid;align-items:center;
  grid-template-columns:minmax(0,.88fr) minmax(0,1.12fr);
  grid-template-areas:"crumbs crumbs"
                      "head   media"
                      "body   media";
  column-gap:clamp(26px,3.2vw,56px)}
.sHero--banner .crumbs{grid-area:crumbs;margin-bottom:10px}
.sHero--banner .sHero__head{grid-area:head;max-width:none;padding-top:0;
  margin-bottom:clamp(10px,1.2vw,16px)}
/* The headline and the copy sit in two grid rows that the carousel spans, so
   each was being centred in its own half and they drifted apart — most visible
   on Contact, where the copy is short and the gap opened to about 130px.
   Hugging them to the boundary between the rows keeps them reading as one
   block while the carousel still centres against the pair. */
.sHero--banner .sHero__head{align-self:end}
.sHero--banner .sHero__body{grid-area:body;align-self:start}
.sHero--banner .sHero__lead{max-width:56ch}
.sHero--banner .sHero__facts{margin-bottom:22px}
.sHero--banner .gal--banner{grid-area:media;justify-self:end;width:100%}

/* The copy column is set tighter than the other About heroes. It has to be:
   the banner height is fixed to the homepage's and the carousel is taking the
   larger share of the row, so the headline, lead and chips have to fit what is
   left at 1100px as well as at 1440px. */
.sHero--banner .sHero__title{font-size:clamp(1.5rem,.85rem + 1.9vw,2.375rem)}
.sHero--banner .sHero__lead{font-size:clamp(.875rem,.84rem + .22vw,1rem);
  line-height:1.62;max-width:52ch;margin-bottom:14px}
.sHero--banner .sHero__facts{gap:8px;margin-bottom:14px}
.sHero--banner .sHero__facts li{padding:6px 12px;font-size:.8125rem}
.sHero--banner .sHero__actions .btn{padding:13px 24px;font-size:.9375rem}

/* The cap, derived rather than guessed. The banner height is --hero-h, the same
   token the homepage uses, and it shrinks with the viewport; so does the space
   left for the carousel once the breadcrumb, the banner padding, the caption
   and the dot row are taken out. Subtracting that overhead and multiplying by
   16/9 gives the widest frame that still fits — at every width, not just the
   one this was designed at. A literal max-width was 57px too tall at 1440 and
   too small at 1280. The 760px ceiling stops it outgrowing its column on a
   very wide screen. */
.gal--banner{max-width:min(760px,calc((var(--hero-h) - 144px) * 16 / 9));
  background:var(--hero-surface);border-color:var(--hero-line);
  border-radius:var(--radius-lg);padding:12px;
  box-shadow:0 18px 44px rgba(0,16,53,.10)}
.gal--banner .gal__track{border-radius:16px}
.gal--banner .gal__slide img,.gal--banner .gal__slot{border-radius:16px}


/* Stacks at 1024, not 980. Between the two the copy column is under 400px: the
   headline breaks across four lines and pushes the banner taller than the
   homepage's, which is the one thing this layout is pinned to. */
@media (max-width:1024px){
  /* Stacked: copy, then the carousel at full width. It is kept here rather than
     hidden (as the homepage hero's is) because on this page the photographs are
     the point of the page, not a teaser for it. */
  .sHero--banner{display:block;min-height:0;padding-block:0}
  .sHero--banner>.container{display:block}
  /* Capped when stacked. At full column width a 16:9 frame on a 1024px tablet
     is 576px tall on its own, which pushed the banner past 900px — taller than
     the viewport, so a visitor landed on a photograph with the headline already
     scrolled off. 560px keeps the picture generous and the whole banner on one
     screen. */
  .sHero--banner .gal--banner{max-width:min(100%,560px);margin:24px auto 0}
}

/* A long filename in an unfilled slot must not set the layout's width.
   `grid-template-columns:1.08fr .92fr` resolves each track against its item's
   min-content size unless told otherwise, and the min-content of
   `<code>ground-floor-recreation-1.jpg</code>` is the whole token — so the
   homepage hero's carousel measured a fixed 629px from 1440px all the way down
   to 1000px, ignoring its column entirely. It would have corrected itself the
   day the photographs landed, which is the worst kind of layout bug: invisible
   now, and invisible in the before/after when it goes.

   THIS RULE MOVED, 12 October. It used to sit here unscoped, 3,200 lines
   BELOW the responsive section — so it re-declared two columns at every
   width and silently beat every media query above it. The hero had been
   un-stackable on phones ever since: `.slide__inner--split` at ≤640px was
   dead rule, and so was the mobile fix written on top of it, which is how an
   afternoon went into wondering why a correct-looking override did nothing.
   The `minmax(0,…)` it exists for now lives on the base rule itself (search
   `.slide__inner--split{display:grid`), where the cascade can reach it.

   > A rule written outside a media query, after the responsive section,
   > overrides the whole of it. Put the fix where the property is declared. */
.gal__slot{min-width:0}
.gal__slotHint,.gal__slotHint code{overflow-wrap:anywhere}

/* =========================================================================
   .gal--photo — a gallery of real photographs rather than placeholder frames.
   16:9 frame, caption as an overlay badge bottom-left. Shared by the homepage
   hero slide, the facility banner and the Contact hero, which had three
   near-identical copies of these rules between them.
   ========================================================================= */
.gal--photo .gal__slide{position:relative}
.gal--photo .gal__slide img,.gal--photo .gal__slot{aspect-ratio:16/9}
.gal--photo .gal__cap{position:absolute;left:12px;bottom:12px;margin:0;
  padding:5px 12px;border-radius:999px;font-size:.75rem;font-weight:650;
  letter-spacing:.01em;background:rgba(13,20,38,.62);color:#fff;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.gal--photo .gal__dots{margin-top:9px}

/* =========================================================================
   ISO CERTIFICATION — certificate cards, the assurance grid, the lightbox
   ========================================================================= */

/* `.certDocs`, NOT `.certGrid`. The two full certificate documents on this page
   are a different component from the three small `.certTile` badges on About Us,
   the homepage and Partnerships — which have used `.certGrid` since long before
   this page existed.
   Naming this one `.certGrid` too put a `repeat(2,...)` rule LATER in the
   stylesheet than the badge grid's `repeat(3,1fr)`, so it won everywhere: the
   three badges wrapped 2-then-1 and inherited this component's much larger gap
   and margin. Nothing on the ISO page looked wrong, which is why it went
   unnoticed — a class name collision only shows up on the page you were not
   looking at. */
.certDocs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(18px,2.2vw,28px);margin-top:clamp(22px,2.6vw,34px)}
.certCard{display:flex;flex-direction:column;background:#fff;
  border:1px solid var(--line);border-radius:var(--radius-lg);
  padding:clamp(20px,2.2vw,28px);box-shadow:var(--shadow-sm)}
.certCard__head{display:flex;align-items:center;gap:14px;margin-bottom:14px}
.certCard__icon{display:grid;place-items:center;width:46px;height:46px;flex:none;
  border-radius:13px;background:var(--brand-tint);color:var(--brand)}
.certCard__std{margin:0;font-size:1.1875rem;letter-spacing:-.02em}
.certCard__sys{margin:2px 0 0;font-size:.8125rem;color:var(--muted)}
.certCard__blurb{margin:0 0 18px;font-size:.9125rem;line-height:1.7;color:var(--muted)}

/* The preview. An <a>, not a button — see js/lightbox.js for why. */
.certShot{position:relative;display:block;overflow:hidden;border-radius:14px;
  border:1px solid var(--line);background:var(--brand-tint-2);line-height:0}
.certShot img{display:block;width:100%;height:auto;
  /* A certificate is a portrait document; showing the top two-thirds at a
     readable size beats shrinking the whole sheet to a thumbnail nobody can
     read. The lightbox is where the full page lives. */
  aspect-ratio:4/3;object-fit:cover;object-position:top center}
.certShot__zoom{position:absolute;right:12px;bottom:12px;display:inline-flex;
  align-items:center;gap:7px;padding:7px 13px;border-radius:999px;
  background:rgba(13,20,38,.68);color:#fff;font-size:.75rem;font-weight:650;
  line-height:1;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:background .2s var(--ease)}
.certShot:hover .certShot__zoom{background:var(--brand)}
.certShot:focus-visible{outline:3px solid var(--brand);outline-offset:3px}

.certMeta{margin:18px 0 0;display:grid;gap:0}
.certRow{display:grid;grid-template-columns:minmax(0,.62fr) minmax(0,1fr);
  gap:14px;padding:9px 0;border-top:1px solid var(--line)}
.certRow dt{font-size:.75rem;font-weight:650;color:var(--muted);line-height:1.5}
.certRow dd{margin:0;font-size:.8125rem;line-height:1.55;color:var(--navy);
  font-weight:600;overflow-wrap:anywhere}
.certCard__pdf{margin-top:16px;align-self:flex-start}

.certHolder{margin:clamp(18px,2vw,26px) 0 0;font-size:.9125rem;color:var(--muted)}
.certHolder strong{color:var(--navy)}
/* `.certCond`, NOT `.certNote` — the SECOND collision in this component family,
   after `.certGrid`/`.certDocs`. These two icon-and-text lines under the
   certificates are a different thing from the bordered "Three credentials, and
   no others" panel on About Us and Partnerships, which has owned `.certNote`
   for far longer. This rule sits LATER in the stylesheet, so its
   `display:flex;margin:10px 0 0` beat that panel's `margin:22px auto 0`
   everywhere and pinned it to the left gutter under a centred heading.
   Both names are now in the ownership gate in build_all.py. */
.certCond{display:flex;gap:9px;margin:10px 0 0;font-size:.8125rem;line-height:1.65;
  color:var(--muted);max-width:92ch}
.certCond .ico{flex:none;margin-top:.28em;color:var(--brand)}

/* --- the assurance framework grid --- */
.fwGrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;
  margin-top:clamp(22px,2.6vw,34px)}
.fwCard{display:flex;flex-direction:column;background:#fff;border:1px solid var(--line);
  border-radius:var(--radius);padding:24px 22px;box-shadow:var(--shadow-sm)}
.fwCard__icon{display:grid;place-items:center;width:44px;height:44px;margin-bottom:14px;
  border-radius:13px;background:var(--brand-tint);color:var(--brand)}
.fwCard h3{font-size:1.0625rem;margin:0 0 .5em;letter-spacing:-.015em}
.fwCard p{margin:0;font-size:.875rem;line-height:1.72;color:var(--muted)}
/* The citation is the point of the card, so it is pinned to the bottom and
   given a rule — it should read as a reference, not as more prose. */
.fwCard__src{display:flex;gap:8px;margin-top:auto!important;padding-top:14px;
  border-top:1px solid var(--line);font-size:.75rem;font-weight:650;
  color:var(--brand)!important}
.fwCard__src .ico{flex:none;margin-top:.2em}

/* --- the lightbox --- */
.lbox{position:fixed;inset:0;z-index:200;display:grid;place-items:center;padding:24px}
.lbox[hidden]{display:none}
.lbox__backdrop{position:absolute;inset:0;background:rgba(6,11,24,.78);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
.lbox__panel{position:relative;width:min(1180px,100%);max-height:calc(100vh - 48px);
  display:flex;flex-direction:column;align-items:center;gap:10px}
/* The stage is the clipping frame the zoomed image is panned inside. It has to
   own the overflow, not the panel: a transform that overflows the panel would
   paint over the toolbar and the caption. */
.lbox__stage{position:relative;width:100%;flex:1;min-height:0;
  display:grid;place-items:center;overflow:hidden;border-radius:12px;
  touch-action:none}
.lbox__img{max-width:100%;max-height:calc(100vh - 170px);width:auto;height:auto;
  border-radius:12px;background:#fff;box-shadow:0 30px 80px rgba(0,0,0,.5);
  transform-origin:center center;will-change:transform;
  -webkit-user-select:none;user-select:none}
.lbox.is-zoomed .lbox__stage{cursor:grab}
.lbox.is-zoomed .lbox__stage:active{cursor:grabbing}
.lbox__cap{margin:0;font-size:.8125rem;font-weight:650;color:rgba(255,255,255,.9);
  text-align:center}

/* toolbar */
.lbox__bar{display:flex;align-items:center;gap:6px;padding:6px;border-radius:999px;
  background:rgba(255,255,255,.1);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  border:1px solid rgba(255,255,255,.16)}
.lbox__btn{width:38px;height:38px;display:grid;place-items:center;border-radius:50%;
  cursor:pointer;background:#fff;color:var(--navy);box-shadow:0 6px 18px rgba(0,0,0,.35);
  transition:background .2s var(--ease),color .2s var(--ease),opacity .2s var(--ease)}
.lbox__btn:hover:not(:disabled){background:var(--brand);color:#fff}
.lbox__btn:disabled{opacity:.42;cursor:default}
.lbox__btn:focus-visible{outline:3px solid #fff;outline-offset:2px}
.lbox__pct{min-width:52px;text-align:center;font-size:.75rem;font-weight:700;
  color:#fff;font-variant-numeric:tabular-nums}

/* gallery arrows — only painted when the group has more than one image */
.lbox__nav{position:absolute;top:50%;transform:translateY(-50%);z-index:2;
  width:44px;height:44px;display:none;place-items:center;border-radius:50%;
  cursor:pointer;background:rgba(255,255,255,.92);color:var(--navy);
  box-shadow:0 6px 18px rgba(0,0,0,.35)}
.lbox.has-nav .lbox__nav{display:grid}
.lbox__nav:hover{background:var(--brand);color:#fff}
.lbox__nav:focus-visible{outline:3px solid #fff;outline-offset:2px}
.lbox__nav--prev{left:10px}
.lbox__nav--prev .ico{transform:rotate(180deg)}
.lbox__nav--next{right:10px}
/* Panning takes priority over paging once the reader has zoomed in, so the
   arrows get out of the way rather than sitting under the drag. */
.lbox.is-zoomed .lbox__nav{opacity:.25}
/* On <html>, not <body> — locking the body makes the sticky header jump as the
   scrollbar goes. */
.lbox-open{overflow:hidden}

@media (max-width:980px){
  .certDocs{grid-template-columns:1fr}
  .fwGrid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:640px){
  .fwGrid{grid-template-columns:1fr}
  .certRow{grid-template-columns:1fr;gap:2px}
  .lbox{padding:12px}
  .lbox__close{top:4px;right:4px}
}

/* =========================================================================
   CAREERS — current openings, as an accordion
   =========================================================================
   The mechanism is the site's existing accordion (faqItem / faqQ / faqA,
   driven by js/pillar.js). Everything here is layout on top of it, so these
   rules must sit AFTER the `.faq*` block they modify: `.jobQ` and `.faqQ` are
   both single class selectors, so source order is what decides, not
   specificity. Moving this block earlier in the file silently reverts the
   header to the FAQ's flex layout. */

/* 820px, down from 980 (Rick, 14 Oct). The title column is the flexible one,
   so with a short title and a right-aligned CTC the leftover width shows as a
   gap across the middle of the row — conspicuous now that the sheet often
   carries a single opening.
   The CTC stays right-aligned: with several roles that column is what makes
   them scannable, and left-aligning it would leave the figures ragged. The
   honest fix is a narrower row, not a different alignment. */
.jobList{display:grid;gap:10px;max-width:820px}

/* [department | title | CTC | chevron]. The title column is the flexible one;
   the department is capped so a two-word tag cannot push the title around,
   and `minmax(0,…)` lets a long title wrap instead of widening the track. */
.jobQ{display:grid;align-items:center;
  grid-template-columns:150px minmax(0,1fr) auto 20px;
  gap:18px;padding:16px 20px}
.jobQ__dept{font-size:.6875rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--brand);line-height:1.35}
.jobQ__title{font-size:.9375rem;font-weight:700;color:var(--navy);line-height:1.4}
.jobQ__ctc{justify-self:end;font-size:.8125rem;font-weight:700;color:var(--brand);
  white-space:nowrap}
/* The roles with no stated figure read as a note, not as a number: same slot,
   deliberately quieter, so the two real CTCs still carry the emphasis. */
.jobQ__ctc--open{padding:3px 10px;border-radius:999px;background:var(--brand-tint);
  border:1px solid #D8E2F8;color:var(--muted);font-weight:650;font-size:.6875rem;
  letter-spacing:.02em}
/* A chevron turns over; it does not rotate 45° like the FAQ's plus. This needs
   to out-specify `.faqItem.is-open .faqQ .ico`, hence the three classes. */
.jobQ__i{margin-top:0;justify-self:end;transition:transform .3s var(--ease)}
.jobItem.is-open .jobQ .jobQ__i{transform:rotate(180deg)}
.jobQ:hover .jobQ__title{color:var(--brand)}

/* Progressive enhancement, and the reason it matters more here than on a FAQ:
   the drawers ARE this page. Collapsed by default, a reader without JavaScript
   gets four headings, no requirements and no way to reach the Apply links.
   So the drawer is open until `js/pillar.js` has wired the row and added
   `.is-wired` — the same way the Contact map and the stories hub hide things
   only once their script is running. The collapse is instant, before paint, so
   nobody with JS sees the page unfold.
   The open state is not listed here: js/pillar.js sets an inline max-height in
   pixels to animate to, and an inline style beats both of these. */
.jobA{max-height:none}
.jobItem.is-wired .jobA{max-height:0}

.jobA>div{padding:2px 20px 20px}
.jobA__lead{margin:0 0 16px;font-size:.9375rem;line-height:1.7;color:var(--muted);
  max-width:72ch}
.jobA__h{margin:0 0 9px;font-size:.75rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--navy)}
.jobA__reqs{margin:0;padding:0;list-style:none;display:grid;gap:7px;max-width:72ch}
.jobA__reqs li{position:relative;padding-left:20px;font-size:.9375rem;
  line-height:1.65;color:var(--muted)}
.jobA__reqs li::before{content:"";position:absolute;left:3px;top:.62em;
  width:6px;height:6px;border-radius:50%;background:var(--brand)}
.jobA__cta{margin-top:18px}

.jobFoot{display:flex;gap:9px;align-items:flex-start;margin:16px 0 0;
  max-width:820px;font-size:.8125rem;line-height:1.6;color:var(--muted)}
.jobFoot .ico{flex:none;margin-top:.26em;color:var(--brand)}

/* Shown in place of the openings when the sheet has every row set to
   Inactive. Deliberately the same treatment as `.work__empty`, the story
   filter's empty state, so the two read as one site rather than as two
   people's idea of what "nothing here" looks like. The section keeps its
   heading and lead above this — a bare page with the heading removed would
   look broken rather than empty. */
.jobEmpty{margin:0;padding:34px 0 6px;text-align:center;color:var(--muted)}

/* While the openings sheet is being read. The class is applied by an inline
   script beside the list, so it takes effect before the baked openings are
   painted, and js/careers.js removes it however the fetch ends. Without it a
   role retired in the sheet flashes up on every load.
   Hiding the items rather than the whole list keeps the section heading and
   lead in place, so the page does not jump when the real list arrives. */
.jobfeed .jobList--pending > .jobItem{display:none}
.jobfeed .jobList--pending::after{content:"Checking current openings\2026";
  display:block;padding:34px 0 6px;text-align:center;color:var(--muted)}

@media (max-width:720px){
  /* The four-column header does not survive a phone: the department tag moves
     above the title and the CTC sits under it, with the chevron held in the
     top-right corner across both rows. */
  .jobQ{grid-template-columns:minmax(0,1fr) 20px;gap:4px 14px;padding:14px 16px}
  .jobQ__dept{grid-column:1;grid-row:1}
  .jobQ__title{grid-column:1;grid-row:2}
  .jobQ__ctc{grid-column:1;grid-row:3;justify-self:start;margin-top:5px}
  .jobQ__i{grid-column:2;grid-row:1/4;align-self:center}
  .jobA>div{padding:2px 16px 18px}
  .jobA__cta{width:100%;justify-content:center}
}

/* =========================================================================
   PORTFOLIO — before/after comparison slider, and the sample galleries
   ========================================================================= */

.showcase{padding-block:var(--section-y-sm)}
.showcase__head{max-width:74ch;margin-bottom:clamp(20px,2.4vw,30px)}
.showcase__lead{margin:8px 0 0;font-size:.9375rem;line-height:1.7;color:var(--muted)}
.showcase__note{display:flex;gap:9px;align-items:flex-start;
  margin:clamp(18px,2vw,26px) 0 0;font-size:.75rem;line-height:1.6;color:var(--muted)}
.showcase__note .ico{flex:none;margin-top:.25em;color:var(--brand)}

.cmpList{display:grid;gap:clamp(22px,2.6vw,34px)}
/* Two across once there is room for both to stay legible. A comparison at
   300px wide shows nothing — below this they stack. */
@media (min-width:1100px){
  .cmpList--multi{grid-template-columns:repeat(2,minmax(0,1fr))}
}

.cmp{--cmp:50%}

/* A PORTRAIT PAIR SITS BESIDE ITS CAPTION, not above it.
   The ghost-mannequin sample is a 760x878 frame, and alone in a single-column
   list it took the full text measure — rendering 975x1126, taller than the
   viewport, with its caption a screen and a half below the picture it
   describes. The modifier is set from the image's own intrinsic pixels in
   make_service.render_compare, so a future portrait sample gets the same
   treatment without anyone having to notice.
   `align-items:start` rather than centre: the caption belongs at the top of
   the frame, where the reader's eye already is. */
@media (min-width:860px){
  .cmpList--tall .cmp--tall{display:grid;align-items:start;
    grid-template-columns:minmax(0,clamp(300px,30vw,400px)) minmax(0,1fr);
    gap:clamp(22px,2.8vw,38px)}
  .cmpList--tall .cmp--tall .cmp__cap{margin-top:0;align-self:center}
  .cmpList--tall .cmp--tall .cmp__cap p{max-width:52ch}
}
/* Below that it stacks, and the frame is capped and centred rather than
   stretched — a portrait picture at full phone width is still a tall picture. */
@media (max-width:859px){
  .cmp--tall .cmp__frame{max-width:380px;margin-inline:auto}
}
.cmp__frame{position:relative;overflow:hidden;border-radius:var(--radius);
  border:1px solid var(--line);background:var(--brand-tint-2);
  line-height:0;touch-action:pan-y;cursor:ew-resize;isolation:isolate}
.cmp__frame img{display:block;width:100%;height:auto;object-fit:cover}
/* The "after" is the base layer and the "before" is clipped over it, so the
   fallback — no script, no clip support — shows the finished frame rather
   than the raw one. If a reader is only going to see one of the two, it
   should be the work. */
.cmp__after{position:relative;z-index:0}
.cmp__before{position:absolute;inset:0;z-index:1;
  clip-path:inset(0 calc(100% - var(--cmp)) 0 0)}
.cmp__before img{height:100%}

/* No script: the two frames stack, each shown whole and labelled, instead of
   a divider frozen at 50%. CSS cannot read a range input's value, so a wipe is
   not available here — half of each picture, with a handle that looks draggable
   and is not, would be worse than two complete pictures. */
.cmp:not(.is-live) .cmp__before{position:static;clip-path:none;margin-top:10px}
.cmp:not(.is-live) .cmp__frame{overflow:visible;border:0;background:none;
  cursor:default;display:grid;gap:0}
.cmp:not(.is-live) .cmp__after,
.cmp:not(.is-live) .cmp__before{border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden}
.cmp:not(.is-live) .cmp__div,
.cmp:not(.is-live) .cmp__tags{display:none}
.cmp:not(.is-live) .cmp__before img{height:auto}
/* The label has to come back, or the reader cannot tell which is which. */
.cmp:not(.is-live) .cmp__after::before,
.cmp:not(.is-live) .cmp__before::before{content:"After";position:absolute;
  z-index:2;margin:12px;padding:5px 12px;border-radius:999px;font-size:.6875rem;
  font-weight:700;letter-spacing:.05em;text-transform:uppercase;line-height:1;
  background:var(--brand);color:#fff}
.cmp:not(.is-live) .cmp__before::before{content:"Before";background:rgba(13,20,38,.72)}
.cmp:not(.is-live) .cmp__after,
.cmp:not(.is-live) .cmp__before{position:relative}

.cmp__div{position:absolute;top:0;bottom:0;left:var(--cmp);z-index:2;
  width:2px;margin-left:-1px;background:#fff;
  box-shadow:0 0 0 1px rgba(13,20,38,.18);pointer-events:none}
.cmp__grip{position:absolute;top:50%;left:50%;translate:-50% -50%;
  display:grid;place-items:center;grid-auto-flow:column;gap:1px;
  width:46px;height:46px;border-radius:999px;background:var(--brand);
  color:#fff;box-shadow:0 4px 14px rgba(13,20,38,.3)}
.cmp__grip .ico{width:15px;height:15px}
/* The two chevrons point outwards from the handle — the shape that says
   "drag me sideways" without a label. */
.cmp__grip .ico:first-child{transform:rotate(90deg)}
.cmp__grip .ico:last-child{transform:rotate(-90deg)}

/* The real control. Visually it is only the handle; functionally it is a
   native range input across the whole frame, which is where the keyboard
   support, the arrow keys, Home/End and the screen-reader announcement all
   come from for free. */
.cmp__range{position:absolute;inset:0;z-index:3;width:100%;height:100%;
  margin:0;padding:0;background:transparent;border:0;appearance:none;
  cursor:ew-resize;opacity:0}
/* Once compare.js is running it owns the pointer, because a native range only
   responds to its own invisible thumb and this input covers the whole frame —
   every press landed on it and nothing moved. `pointer-events:none` does not
   affect keyboard focus, so Tab, the arrow keys, Home/End and the
   screen-reader announcement all still come from the real control.
   Without the script the rule never applies and the input works normally. */
.cmp.is-live .cmp__range{pointer-events:none}
.cmp__range:focus-visible{opacity:1;outline:3px solid var(--brand);
  outline-offset:3px;background:rgba(55,99,231,.06)}

.cmp__tags{position:absolute;inset:auto 0 0 0;z-index:2;display:flex;
  justify-content:space-between;padding:12px;pointer-events:none}
.cmp__tag{padding:5px 12px;border-radius:999px;font-size:.6875rem;
  font-weight:700;letter-spacing:.05em;text-transform:uppercase;line-height:1;
  background:rgba(13,20,38,.72);color:#fff;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.cmp__tag--after{background:var(--brand)}

.cmp__cap{margin:13px 0 0}
.cmp__cap h3{margin:0 0 5px;font-size:1rem;letter-spacing:-.01em}
.cmp__cap p{margin:0;font-size:.875rem;line-height:1.65;color:var(--muted);
  max-width:62ch}

/* --- the sample galleries --- */
.pfGrid{display:grid;gap:clamp(18px,2.2vw,28px);
  grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr))}
.pfCard{display:flex;flex-direction:column;background:#fff;
  border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;
  box-shadow:var(--shadow-sm)}
/* Capped, scrollable window. A brand store capture is 1800px tall; shown
   whole it is a thumbnail nobody can read, and shown full size it is the
   entire page. The window shows it at a readable width and lets the reader
   move down it — and the lightbox has the whole thing. */
.pfCard__shot{position:relative;display:block;max-height:420px;overflow:hidden;
  background:var(--brand-tint-2);line-height:0}
.pfCard__shot img{display:block;width:100%;height:auto}
.pfCard__shot::after{content:"";position:absolute;inset:auto 0 0 0;height:84px;
  background:linear-gradient(to top,rgba(255,255,255,.96),rgba(255,255,255,0));
  pointer-events:none}
.pfCard__zoom{position:absolute;right:12px;bottom:12px;z-index:1;
  display:inline-flex;align-items:center;gap:7px;padding:7px 13px;
  border-radius:999px;background:rgba(13,20,38,.68);color:#fff;
  font-size:.75rem;font-weight:650;line-height:1;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:background .2s var(--ease)}
.pfCard__shot:hover .pfCard__zoom{background:var(--brand)}
.pfCard__body{padding:16px 18px 18px}
.pfCard__head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  margin-bottom:7px}
.pfCard__head h3{margin:0;font-size:.9375rem;letter-spacing:-.01em}
.pfCard__credit{font-size:.6875rem;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--brand)}
.pfCard__body p{margin:0;font-size:.8125rem;line-height:1.65;color:var(--muted)}

@media (prefers-reduced-motion:reduce){
  .pfCard__zoom{transition:none}
}
@media (max-width:640px){
  .cmp__grip{width:40px;height:40px}
  .cmp__tags{padding:9px}
  .pfCard__shot{max-height:320px}
}


/* =========================================================================
   8. MOBILE OVERRIDES — THIS BLOCK MUST STAY LAST IN THE FILE
   -------------------------------------------------------------------------
   Section 6 (RESPONSIVE) sits in the MIDDLE of this stylesheet, with roughly
   2,500 lines of component rules after it. Those later rules are unscoped, so
   they beat every media query above them at equal specificity — silently, and
   only at the widths the media query was written for.

   That had already cost real bugs before anyone noticed the pattern:
   `.slide__inner--split` was re-declared 3,200 lines below the responsive
   section, so the homepage hero could not be stacked on a phone at all and
   the <=640px rule written to stack it had never once applied. Four of the
   first-draft mobile fixes in this block landed the same way and reported
   success while doing nothing.

   So mobile overrides live HERE, at the end, where the cascade can reach
   them. Anything added below this block will outrank it — add to it instead.
   ========================================================================= */
@media (max-width:1024px){
  /* The lock is `position:fixed`, not `overflow:hidden`. iOS Safari ignores
     the latter on <body> behind a fixed overlay, keeps scrolling the page,
     and steals the gesture mid-swipe so the drawer stops scrolling and its
     lower items become unreachable. js/main.js saves and restores the scroll
     position, because fixing the body otherwise jumps the page to the top. */
  body.nav-open{position:fixed;left:0;right:0;width:100%;overflow:hidden}

  /* An accordion mid-animation must not clip the scroll container. The panel
     animates its own max-height; the drawer around it just gets taller. */
  .mega,.drop{will-change:max-height}
  .has-mega.is-open .mega,.has-drop.is-open .drop{max-height:5200px}

  /* EVERY ELEMENT IN THE DRAWER DECLARES ITS GESTURE, including the panels,
     lists, links and buttons the brief names. `touch-action` is NOT an
     inherited property, so setting it on the container alone leaves every
     child on `auto` — and `auto` is what lets an engine decide the gesture
     belongs to something other than the drawer's scroll.
     This is the belt to `overflow:clip`'s braces: `clip` removes the trap on
     iOS 16+ and Chrome 90+, and this covers the older engines where `clip`
     is ignored and the `overflow:hidden` fallback still applies.
     `pinch-zoom` is kept alongside `pan-y`. A bare `pan-y` would disable
     pinch zoom inside the menu, which takes a zoom gesture away from anyone
     who needs it to read the thing — too high a price for a scroll fix. */
  .nav,.nav *{touch-action:pan-y pinch-zoom}

  /* TEXT SELECTION IS THE OTHER HALF OF THE FREEZE, and this is the one place
     the brief and the evidence disagree — it asks for `user-select:none` to
     be REMOVED. The recording shows the opposite: in the frozen frame several
     service links are highlighted blue, a multi-line text selection. On iOS a
     drag that begins on selectable text can start a selection rather than a
     scroll, and once it does, the gesture belongs to the selection and the
     drawer stops moving. That is why it happens over the words and not over
     the blank padding — there is nothing to select there.
     So selection is switched OFF for the menu rows only, which are links and
     buttons nobody needs to select, and `-webkit-touch-callout:none` stops
     the long-press menu that comes with it.
     THE SEARCH FIELD IS EXEMPTED below — turning selection off in a text
     input would stop a reader editing what they typed, which is a real loss
     for no gain. */
  .nav a,.nav button,.nav .nav__link,.nav .mega__groupLink,.nav .mega__sub a,
  .nav .nav__ctaMail,.nav .mega__title{
    -webkit-user-select:none;user-select:none;
    -webkit-touch-callout:none;
  }
  .nav .hsearch,.nav .hsearch *,.nav input{
    -webkit-user-select:text;user-select:text;-webkit-touch-callout:default;
  }
  /* The grey flash on tap is a 300ms-era affordance; with selection off it is
     the only feedback left, so it stays but is toned to the brand tint. */
  .nav a,.nav button{-webkit-tap-highlight-color:rgba(55,99,231,.12)}

  /* --- The drawer's search, promoted (Rick, 12 October) ---
     It sits at the top of the drawer and was a bare line with a magnifier,
     easy to miss. On mobile the expand-on-click behaviour is pointless —
     there is nothing to expand into — so the field is simply always open,
     filled, bordered and full width. */
  /* SCOPED TO .hsearch--drawer. There are TWO search forms in the header:
     the utility bar's (collapsed behind a trigger button) and the drawer's
     own, which is always open and has its own `.hsearch__lead` icon. The
     utility bar is hidden below 1024px, so the only one a phone ever sees is
     the drawer's — styling bare `.hsearch` here would have been aimed at the
     wrong element, and dressing up a trigger button that is not on screen. */
  /* Clears the burger, which is fixed at z-index 90 over the drawer's top
     right corner — the search sat under it and lost its submit button. */
  .hsearch--drawer{margin-top:56px;margin-bottom:16px}
  .hsearch--drawer .hsearch__box{
    align-items:center;flex-wrap:nowrap;
    padding:4px 4px 4px 12px;border:1.5px solid #CFDAEC;border-radius:12px;
    background:var(--grey);
  }
  .hsearch--drawer .hsearch__box:focus-within{
    border-color:var(--brand);background:#fff;
    box-shadow:0 0 0 3px rgba(55,99,231,.14);
  }
  .hsearch--drawer .hsearch__lead{width:18px;height:18px;margin-right:9px;color:var(--brand)}
  .hsearch--drawer .hsearch__input,
  .hsearch--drawer.is-open .hsearch__input{padding:12px 8px 12px 0;font-size:.9375rem;background:transparent}
  .hsearch--drawer .hsearch__input::placeholder{color:var(--muted);opacity:.9}
  .hsearch--drawer .hsearch__go{
    flex:none;width:36px;height:36px;border-radius:9px;
    background:var(--brand);color:#fff;display:grid;place-items:center;
  }
  /* The suggestion list drops below the field. Absolute rather than a
     wrapped flex item: as a flex child it forced the row to wrap and pushed
     the submit button out of the box. */
  .hsearch--drawer .hsearch__panel{position:absolute;left:0;right:0;top:calc(100% + 6px);
    width:auto;box-shadow:var(--shadow);border:1px solid var(--line);border-radius:10px}
  /* The drawer's own list no longer needs to clear the burger on its own —
     the search above it does that. */
  .nav__list{margin-top:14px}

  /* --- The drawer's contact block --- */
  .nav__cta{gap:8px}
  .nav__ctaTel{display:flex;align-items:center;gap:9px;font-size:.875rem}
  .nav__ctaLabel{
    font-size:.6875rem;letter-spacing:.05em;text-transform:uppercase;
    color:var(--muted);opacity:.8;
  }
  .telNote{color:var(--muted);opacity:.8}
  /* The three action buttons keep their own spacing below the contact lines. */
  .nav__cta .btn:first-of-type{margin-top:10px}

  /* --- Floating docks (Rick, 12 October) ---
     HIDDEN WHILE THE DRAWER IS OPEN, and that is a stacking-context fix as
     much as a cosmetic one. `.dock` is z-index 75 in the ROOT stacking
     context; the drawer is z-index 80 but inside `.header`, which is z-index
     60 and creates its own context — so 80-inside-60 loses to 75, and the
     dock painted over the menu items. Raising numbers would be whack-a-mole;
     the dock has no business being visible over an open menu at all.
     `visibility` rather than `display`, so the open/close transition still
     runs and the dock's own panel keeps its state. */
  body.nav-open .dock{opacity:0;visibility:hidden;pointer-events:none}
  .dock{transition:opacity .2s var(--ease),visibility .2s var(--ease)}
}

/* =========================================================
   MOBILE HERO + FLOATING DOCKS  (Rick, 12 October)
   One block, under the 768px line the brief names.
   ========================================================= */
@media (max-width:768px){

  /* --- The hero grows with its content --------------------------------
     The overlap in the recording is one bug with one cause: the banner's
     height is a FIXED token and the slides are `position:absolute; inset:0`,
     so stacked content simply runs out through the bottom of the box and
     over whatever is underneath. Raising the token would not fix it — every
     slide carries a different amount of content, so any single number is
     wrong for five of the six.

     The slides become a one-cell GRID STACK instead: every slide occupies
     `grid-area:1/1`, so they still sit on top of each other and still
     crossfade, but now the stage has a real height — the tallest slide's —
     and nothing can overflow it. The fixed token is dropped on mobile. */
  .hero{height:auto;min-height:0}
  .hero__stage{position:relative;inset:auto;display:grid}
  /* Only the ACTIVE slide is in flow, so the banner is as tall as the slide
     being shown and no taller. All six sharing one grid cell would work too,
     but the stage would then size to the tallest of them — slide 2 is 778px
     against 284px for slides 3 to 6, which left half a screen of empty
     banner under every short slide. The others stay absolutely positioned in
     the same cell, which is what keeps the crossfade. */
  .slide{
    position:absolute;inset:0 0 auto 0;grid-area:1/1;align-items:start;
    padding:34px 0 72px;        /* room for the controls along the bottom */
  }
  .slide.is-active{position:relative}
  /* A stacked slide is no longer a side-by-side layout on any of the six. */
  .slide__inner--split,.slide__inner--certs{grid-template-columns:1fr;gap:26px}
  .slide__copy,.slide__copy--wide .slide__title,.slide__copy--wide .slide__lead{max-width:none}
  .slide__title{font-size:clamp(1.6rem,5.2vw,2.1rem);margin-bottom:.45em}
  .slide__lead{font-size:1rem;margin-bottom:0;max-width:40ch}
  /* Real vertical rhythm between the blocks, rather than each one carrying
     its own margin and hoping they add up. */
  .slide__copy{display:flex;flex-direction:column;gap:16px}
  .slide__copy>*{margin:0}
  .slide__actions{gap:14px;flex-wrap:wrap}

  /* The credential pyramid becomes one row of three small tiles under the
     copy. Stacked (the old <=520px rule) it was three 190px squares — about
     560px of banner on its own, which is most of a phone screen before the
     headline has been read. */
  /* A PYRAMID, not a row of three (Rick, 12 October): one card centred over
     two. rev 78 used a single row because the banner had to stay short; the
     banner is now a uniform 564px and has the room, and the pyramid is what
     the brief asks for and what the desktop layout already is — so the
     mobile and desktop hero stop being two different arrangements.
     `.pyramid__row{display:grid}` restores the two-up bottom row that
     `display:contents` had flattened. */
  .pyramid{grid-auto-flow:row;justify-content:center;
    --pcard:min(40vw,148px);--pgap:10px}
  .pyramid__row{display:grid}
  .pyramid .pcard__in{gap:3px;padding:9px 6px}
  .pyramid .pcard__logo{max-height:20px}
  .pyramid .pcard__logo--wide{max-height:15px}
  .pyramid .pcard__name{font-size:.6875rem;line-height:1.25}
  .pyramid .pcard__meta{font-size:.5938rem;line-height:1.3}
  .pyramid .pcard__big{font-size:1.5rem}
  .clutchSlot{--clutch-h:30px}

  /* --- Floating docks, scaled down -----------------------------------
     They were desktop-sized on a 390px screen: a 50px WhatsApp circle and a
     full-size pill, together covering a third of the width and sitting over
     the running copy. */
  .dock{right:12px;bottom:14px;gap:9px}
  .dock__wa{width:40px;height:40px}
  .dock__wa .ico{width:21px;height:21px}
  .dock__tip{display:none}          /* a hover tooltip on a touch screen */
  .dock__tab{padding:9px 13px;font-size:.8125rem;gap:7px}
  .dock__tab .ico{width:17px;height:17px}
  .toTop{width:38px;height:38px}

  /* Slide 2 is the tallest of the six and sets how far the banner can push
     the rest of the page down. Trimmed rather than redesigned: the panel's
     desktop padding and its decorative award icon are the two things costing
     the most height and the least meaning on a phone. */
  .revAsk{padding:18px 18px 16px;gap:10px}
  .revAsk__icon{display:none}
  .revAsk__h{font-size:1.0625rem}
  .revAsk__p{font-size:.875rem;line-height:1.5}
  .revAsk__note{font-size:.72rem}
  .recog{gap:8px}
  .recog a{padding:12px 13px}
}

/* =========================================================================
   SUNTEC-BENCHMARK MOBILE PASS (Rick, 12 October — rev 79)
   Still inside section 8, still last in the file, and every rule below is
   inside `@media (max-width:768px)`. The brief's breakpoint rule is absolute:
   desktop AND TABLET must not move, so nothing here touches the 769–1024
   band where the drawer is still a side panel.
   ========================================================================= */
@media (max-width:768px){

  /* --- 1 · One banner height for all six slides ------------------------
     rev 78 sized the stage to the active slide, which removed the overlap
     but left the page jumping by up to 400px as the carousel advanced —
     every section below the banner moved while the reader was looking at
     it. A floor of 500px holds the common case steady; slides are centred
     in it rather than stretched, so a short slide does not grow odd gaps. */
  /* ALL SIX SLIDES BACK IN FLOW, sharing one grid cell. rev 78 put only the
     active slide in flow, which gave each one its natural height — and meant
     the whole page moved by up to 90px every time the carousel advanced,
     while the reader was looking at it. Rick asked for the jump gone, and a
     jump is the price of per-slide height.
     In flow, the cell is as tall as the tallest slide and every slide is
     that height, so the banner never changes size. It also maintains
     itself: add a seventh slide and the floor follows it, with no number to
     remember. 500px is the minimum for the short ones. */
  .hero__stage{min-height:500px}
  .slide{position:relative;align-items:center}

  /* Slide 2 sets that common height, so trimming it shortens the banner on
     all six. Padding and type only — nothing is removed that the brief asks
     to be there. */
  .slide--proof .revAsk{padding:14px 15px 13px;gap:8px}
  .slide--proof .revAsk__p{font-size:.8125rem;line-height:1.45}
  .slide--proof .revAsk__note{font-size:.6875rem;line-height:1.35}
  .slide--proof .recog a{padding:10px 11px;gap:5px}
  .slide--proof .recog__txt{font-size:.6875rem}

  /* --- 1a · Slide 1: the eyebrow and the three badges --------------------
     NOTE FOR WHOEVER CHANGES THIS NEXT: the hidden element is the page's
     <h1>. It stays in the DOM — `display:none`, not removed — so it is
     still served to crawlers, but Google indexes mobile-first and
     discounts hidden text. If the homepage ever loses ranking for
     "remote staffing", this rule is the first thing to look at. The lead
     and the CTA are ordinary copy and carry no such risk. */
  .slide--legacy .slide__title,
  .slide--legacy .slide__lead,
  .slide--legacy .slide__actions{display:none}
  .slide--legacy .slide__copy{gap:0}

  /* --- 1b · Slide 2: two badges, the callout, then the widget ----------
     The arrangement the brief asks for is what the stacked order already
     gives once the headline, the lead and the sourcing note come out:
     eyebrow -> .recog (2 badges) -> .revAsk (callout + Clutch widget). */
  .slide--proof .slide__title,
  .slide--proof .slide__lead,
  .slide--proof .slide__note{display:none}
  .slide--proof .slide__copy{gap:14px}
  .slide--proof .recog{grid-template-columns:1fr 1fr;gap:10px}

  /* FULL-SCREEN OVERLAY (Rick, 12 October — the SunTec reference).
     It was a 380px panel sliding in from the right over a dimmed page. Edge
     to edge instead: a phone has no room for a menu and a peek of the page
     behind it, and the strip that was left showed a slice of hero with no
     meaning in it.
     `height:100dvh` after `100vh`: on iOS `100vh` is the height with the
     browser chrome HIDDEN, so a 100vh overlay is taller than the screen and
     its last item sits under the address bar. `dvh` is the visible height.
     The declarations are in that order so a browser without dvh keeps vh. */
  .nav{
    inset:0;width:100%;max-width:none;
    height:100vh;height:100dvh;
    max-height:100vh;max-height:100dvh;
    padding:0 20px 36px;border-radius:0;box-shadow:none;
    /* `pinch-zoom` alongside `pan-y`, matching the `.nav *` rule in the
       <=1024 block. A bare `pan-y` here beat that rule on the container
       itself and silently took pinch zoom away from the open menu. */
    overscroll-behavior:contain;touch-action:pan-y pinch-zoom;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
    /* Scroll anchoring tries to keep the element under the viewport pinned
       when content above it grows or shrinks. In a drawer whose accordions
       animate their height, that fights the user's own scroll and reads as
       the list seizing up — the symptom Rick reports on expand/collapse.
       It cannot be reproduced in Chromium here, where every state scrolls to
       its end; this is the one documented cause that is cheap to rule out. */
    overflow-anchor:none;
  }
  /* It covers the page completely, so there is no dimmed page to show. */
  .nav__backdrop{display:none}

  /* The open menu's own top bar: logo left, floating toggle right. */
  /* The logo sits on the same optical line as the floating trigger opposite
     it, rather than against the top edge. The burger is 46px tall at top:12px,
     so its centre is at 35px; 14px of padding over a 27px logo puts this one
     at 27.5px, and the two read as one row.
     No bottom rule: the drawer is a single white surface, and a hairline
     under the logo cut it into a header and a body that are not actually
     different things (Rick, 12 October). */
  .nav__logo{
    display:flex;align-items:center;min-height:58px;
    position:sticky;top:0;z-index:2;
    margin:0 -20px;padding:14px 20px 8px;
    background:#fff;
  }
  .nav__logo img{height:27px;width:auto;display:block}

  /* THE FLOATING TRIGGER. It is the same <button id="burger"> throughout —
     not a second close control — so there is one element with one state and
     `aria-expanded` stays truthful. Fixed rather than sticky: it has to hold
     its corner while the menu scrolls under it, which is what makes it
     "floating" rather than "a thing at the top of a long list". */
  .burger{
    position:fixed;top:12px;right:14px;
    width:46px;height:46px;border-radius:50%;
    background:#fff;border:1px solid var(--line);
    box-shadow:0 6px 18px rgba(0,16,53,.14);
    transition:background .2s var(--ease),box-shadow .2s var(--ease);
  }
  .burger[aria-expanded="true"]{background:var(--brand);border-color:var(--brand);
    box-shadow:0 8px 22px rgba(55,99,231,.38)}
  .burger[aria-expanded="true"] span{background:#fff}
  /* --- CLEAN TEXT ONLY (Rick, 12 October) ---------------------------------
     The mega panel is written for a wide desktop dropdown, where a sentence
     of context under each pillar is useful. Folded into a phone accordion the
     same sentences are three lines each between every pair of links, and the
     list stops being scannable — which is the whole job of a menu.
     Titles and links stay; prose goes. */
  .mega__lead{display:none}
  /* THE PANEL HEADING GOES TOO (Rick, 12 October). On desktop
     "All eCommerce & Marketplace Management services →" is the panel's way
     through to the pillar page. In the drawer it repeated the accordion
     label immediately above it and cost a row before the first real item.
     It is only safe to remove because the pillar LABEL itself now navigates
     — see the drill-down handler in js/main.js. If that ever goes back to
     being a pure toggle, this heading has to come back with it, or there is
     no route to the pillar page from the menu at all. */
  .mega__title{display:none}
  .mega__inner{padding:0 0 8px}
  .mega__links{margin-top:0}
  .mega__group{margin-bottom:0}
  .mega__groupLink{padding:11px 12px}
  .mega__sub a{padding:9px 12px;font-size:.875rem}

  /* --- 3 · Pure text, and the second accordion level ------------------- */
  /* The icons beside each category are panel furniture: useful in a
     three-column desktop panel, noise in a scannable list on a phone.
     (.mega__lead is hidden by the CLEAN TEXT block above.) */
  .mega__groupLink .ico{display:none}
  .mega__groupLink{padding-left:12px}
  .mega__title{padding:10px 12px}

  /* A category and its chevron share one row. */
  .mega__group{position:relative;border-bottom:1px solid var(--line)}
  .mega__group:last-child{border-bottom:0}
  .mega__groupToggle{
    position:absolute;top:0;right:0;
    width:48px;height:44px;                 /* a real tap target */
    display:grid;place-items:center;color:var(--muted);
  }
  .mega__caret{transform:rotate(90deg);transition:transform .3s var(--ease)}
  .mega__group.is-open .mega__caret{transform:rotate(-90deg)}
  /* `.mega__links .mega__groupLink`, not the bare class. `.mega__links a`
     already sets `padding:11px 12px` at specificity (0,2,0) and a single
     class is (0,1,0) — it loses however far down the file it sits. Source
     order only decides ties. */
  .mega__links .mega__groupLink{padding-right:52px}

  /* COLLAPSED ONLY ONCE THE SCRIPT HAS WIRED THE CONTROL. `.is-drilled` is
     added by js/main.js after it injects the toggles. Without JavaScript
     this rule never matches and all 61 service links stay on screen. */
  /* Same reasoning as `.mega` above — this is the second, nested scroll
     container a drag over a service link had to escape. */
  .nav.is-drilled .mega__sub{
    max-height:0;
    overflow:hidden;
    overflow:clip;
    transition:max-height .3s ease-in-out;
  }
  .nav.is-drilled .mega__group.is-open .mega__sub{max-height:1600px}
  .mega__sub{padding-left:12px}
  .mega__sub a{padding:9px 12px;font-size:.875rem}
  .mega__groupToggle{display:grid}

  /* --- 4 · Scroll, with every level open ------------------------------- */
  /* The container, its overscroll containment and `touch-action:pan-y` are
     set in the <=1024px block, which is where the drawer exists at all. Only
     the safe-area padding is phone-specific. */
  /* Clears the iOS home indicator so the last button is not half under it. */
  .nav__cta{padding-bottom:env(safe-area-inset-bottom,0px)}
}

/* Above the phone breakpoint the injected control must not appear: the
   desktop and tablet panels show every link at once, and a chevron that
   collapses nothing would be a dead control. Outside the media query on
   purpose — this has to beat the `display:grid` above when the viewport is
   resized up past 768px without a reload. */
@media (min-width:769px){
  /* The drawer's logo bar and the injected drill-down chevrons exist only
     for the phone overlay. Without this they fall through to the desktop
     nav — the logo renders inline in the navigation ribbon and takes it from
     63px to 238px tall. Outside the phone media query on purpose: it has to
     beat the `display:flex`/`display:grid` above when a window is dragged
     past the breakpoint without a reload. */
  .nav__logo{display:none}
  .mega__groupToggle{display:none}
}

/* =========================================================================
   The About panel's stat cards, out of the drawer (Rick, 12 October).
   Phone only; still inside section 8, still last in the file.
   ========================================================================= */
@media (max-width:768px){
  /* "Operating since 2004", "The team 300+", "Clients who stay 80%+".
     They earn their place in the desktop panel, which is a wide three-column
     dropdown with room beside the links. Folded into the drawer they become
     three full-width cards stacked under "Decade Club" — a third screen of
     scrolling after the last thing anybody opened the menu to reach.

     HIDDEN, NOT DELETED. The markup is generated from site_map.ABOUT_CARDS
     between the NAV:ABOUT sentinels and is the same partial the desktop
     header uses, so removing it would take the cards off the desktop panel
     too. Scoped to `.nav` as well as to the breakpoint: `.aboutCard` appears
     only inside the global header today, and scoping means it stays safe if
     a landing page ever reuses the class. */
  .nav .aboutPanel__cards{display:none}

  /* With the cards gone the list is the last thing in the panel, and its
     final link sat hard against the panel's edge. */
  .nav .mega--about .mega__inner{padding-bottom:18px}
  .nav .aboutPanel__col{padding-bottom:2px}
}

/* =========================================================================
   Case-study figures and the enquiry hero on a phone.
   Still inside section 8, still last in the file.
   ========================================================================= */
@media (max-width:768px){
  /* 400px of screenshot on a 844px-tall phone is half the viewport before any
     copy. The cap is a viewport fraction as well as a pixel value so it stays
     proportionate on a small phone as well as a large one. */
  .csFig__zoom{--fig-h:min(280px,38vh)}
  .csFig{padding:8px}

  .lbox{padding:12px}
  .lbox__img{max-height:calc(100vh - 150px)}
  .lbox__nav{width:38px;height:38px}
  .lbox__nav--prev{left:4px}
  .lbox__nav--next{right:4px}

  /* THE FORM COMES FIRST. On a phone the split collapses, and the order is a
     short headline, then the form card, then everything else — the facts, the
     office details and the "before you send" notes all move below it. The
     hero's own lead paragraph is not repeated above the form: at this width it
     is three lines between the headline and the first field, which is the
     thing this whole change exists to remove. */
  .sHero--form .sHero__formGrid{grid-template-columns:1fr;gap:22px}
  .sHero--form .sHero__formAside{order:2}
  .sHero--form .sHero__formCard{order:1}
  .sHero--form .sHero__lead{display:none}
  .sHero--form .sHero__facts{margin-top:0}
  .sHero--form .sHero__formCard{padding:16px 14px;border-radius:var(--radius)}
  .sHero--form .enq__grid{grid-template-columns:1fr}
  /* The card's second column goes under the fields rather than beside them,
     and stops sticking — a sticky panel in a stacked layout follows the reader
     down the page over the fields it is meant to sit beside. */
  .enq--compact{grid-template-columns:1fr;gap:20px}
}
