/* ⚠️ SINGLE-COLUMN OVERRIDES USE minmax(0,1fr), NEVER A BARE 1fr.
   `1fr` means minmax(AUTO,1fr): the column cannot shrink below its widest
   unbreakable item, so a nowrap button or a pasted URL silently makes the
   column WIDER than the phone and clips the copy on the right. It bit us
   three separate times (blog TOC, .dive-inner, .article-grid) before we
   fixed the whole file at once. Keep new mobile overrides in this form. */
/* ============================================================
   Opus Interactive — Hero + Header
   Poppins (main) · IBM Plex Sans (labels). Brand cyan #2AC4F4.
   Full-bleed "servers in a field" hero.
   ============================================================ */

:root{
  --hd-h:85px;   /* fixed header height, unscrolled — see .phero padding */
  --brand:#2ac4f4;         /* logo cyan */
  --brand-sky:#2cabe2;     /* client brand blue — replaces the old navy accents */
  --brand-mid:#1f9acd;
  --brand-deep:#17789f;    /* same hue as --brand-sky, darkened to pass AA on white */
  --blue-800:#115a78;      /* deepest step of the brand-blue ramp (no navy) */

  /* Dark surfaces. Shannon: "there is the navy in the footer and a few
     sections — swap that with the dark grey." Navy is not in their palette;
     Dk Grey #404041 is. This ramp is that grey lightened/darkened on its own
     neutral, so the gradients keep their depth without going navy again. */
  --grey-700:#404041;      /* brand Dk Grey — same value as --ink */
  --grey-800:#333335;
  --grey-900:#242425;
  --brand-green:#b9d531;   /* client brand green (brand guidelines) */
  --leaf:#4e9e63;
  --leaf-deep:#3a8a4e;
  --leaf-50:#eaf5ec;

  --ink:#404041;           /* headings / primary text — client brand Dk Grey (was navy #12232f) */
  --ink-soft:#545454;      /* body copy — neutral match for the old #425668 (7.6:1 either way) */
  /* ⚠️ was #8d8d8d, which measured 2.7-3.3:1 on white and paper — EVERY one
     of the 7 text elements using it failed the 4.5 body minimum. Darkened to
     the lightest grey that passes on white (4.6:1). The decorative uses (the
     dots between meta items, the accordion chevron, the search icon) are
     unaffected by the change. */
  --ink-faint:#757575;     /* neutral match for the old #7c8fa0 */
  --ink-on-blue:#373737;   /* dark type on the #2cabe2 field — #404041 is only 3.96:1 there */
  --paper:#fbfdff;
  --sky-100:#e3f1fb;
  --white:#ffffff;
  --line:rgba(18,35,47,.12);
  --line-soft:rgba(18,35,47,.07);

  --shadow-sm:0 2px 10px rgba(18,35,47,.07);
  --shadow-md:0 16px 40px -12px rgba(18,54,74,.22);

  --font-main:"Poppins",system-ui,sans-serif;
  --font-label:"IBM Plex Sans",system-ui,sans-serif;

  --wrap:1280px;
  --sec-y:clamp(84px,11vw,150px);   /* single vertical rhythm for every content section */
  --sec-x:clamp(20px,5vw,44px);
  --head-gap:var(--sec-y);          /* heading block → its content, same rhythm as the section edges */
  --ease:cubic-bezier(.22,.61,.36,1);
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{
  font-family:var(--font-main);
  color:var(--ink);background:var(--paper);
  line-height:1.6;-webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
ul{list-style:none}

/* ---------- Buttons ---------- */
.btn{
  --pad-y:14px;--pad-x:26px;
  display:inline-flex;align-items:center;gap:.5em;
  font-family:var(--font-main);font-weight:600;font-size:1rem;
  letter-spacing:-.01em;padding:var(--pad-y) var(--pad-x);
  border-radius:100px;border:1.5px solid transparent;cursor:pointer;
  transition:transform .35s var(--ease),box-shadow .35s var(--ease),
             background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease);
  white-space:nowrap;
}
.btn-arrow{transition:transform .35s var(--ease)}
.btn:hover .btn-arrow{transform:translateX(3px)}

/* flat — solid fill, no gradient, no bevel highlight, no drop shadow, no lift */
.btn-primary{
  color:#fff;
  background:var(--brand-sky);
  box-shadow:none;
}
.btn-primary:hover{background:var(--brand-deep)}

/* doc section 1 names the partner hero's primary CTA as green.
   ⚠️ White label on #b9d531 measures 1.66:1 — far below the 4.5:1 that button
   text needs, and below even the 3:1 for large text. Set at the client's
   explicit request; darkening the green (≈#6f8a10) is what would fix it. */
.btn-primary.btn-green{color:#fff;background:var(--brand-green)}
.btn-primary.btn-green:hover{background:#a6c623}

.btn-ghost{
  color:var(--ink);background:#fff;
  border-color:var(--line);
  box-shadow:none;
}
.btn-ghost:hover{border-color:var(--brand-sky);color:var(--brand-deep)}

.btn-sm{--pad-y:11px;--pad-x:20px;font-size:.93rem}

/* ============================================================
   HEADER
   ============================================================ */
.site-header{
  position:fixed;top:0;left:0;right:0;z-index:100;
  background:rgba(255,255,255,.93);            /* flat glass, not heavy frost */
  backdrop-filter:saturate(115%) blur(8px);
  -webkit-backdrop-filter:saturate(115%) blur(8px);
  border-bottom:1px solid var(--line-soft);
  transition:background .4s var(--ease),box-shadow .4s var(--ease),border-color .4s var(--ease);
}
.site-header.scrolled{
  background:#fff;                              /* fully solid once scrolled */
  box-shadow:0 6px 22px -16px rgba(18,54,74,.4);
}
/* 100px wider than the body wrap: at --wrap the logo cleared the nav by only
   27px while the nav cleared the buttons by 77, which is what read as cramped.
   Three columns rather than space-between — with space-between the nav lands
   wherever the logo and button widths leave it (measured 21px left of centre,
   at every viewport), and extra width just splits between the two gaps without
   ever centring it. 1fr auto 1fr centres the nav on the header regardless. */
.header-inner{
  max-width:calc(var(--wrap) + 100px);margin:0 auto;
  padding:18px clamp(20px,4vw,44px);
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:24px;
  transition:padding .4s var(--ease);
}
.site-header.scrolled .header-inner{padding-top:12px;padding-bottom:12px}

/* The mark must never scale down. As a flex OR grid item the <img> shrinks
   below its intrinsic width instead of overflowing — measured 240 -> 0px between
   1280 and 1000 — so the column is pinned to the logo's own width and the header
   compresses everywhere else instead. */
.logo{min-width:max-content}
.logo img{height:46px;width:auto;filter:brightness(0);
  transition:height .4s var(--ease),filter .55s var(--ease)}
.site-header.scrolled .logo img{height:40px;filter:none}

.nav{display:flex;gap:28px}
.nav-item{display:flex;align-items:center}   /* static: lets .site-header be the mega's containing block */
.nav-link{
  font-size:.96rem;font-weight:500;color:var(--ink-soft);
  position:relative;padding:4px 0;cursor:pointer;transition:color .25s var(--ease);
}
.nav-link::after{
  content:"";position:absolute;left:0;bottom:-2px;height:2px;width:0;
  background:var(--brand);border-radius:2px;transition:width .3s var(--ease);
}
.nav-link:hover,.nav-item.open .nav-link{color:var(--ink)}
.nav-link:hover::after,.nav-item.open .nav-link::after{width:100%}

.header-actions{display:flex;align-items:center;gap:14px;justify-self:end}

.menu-toggle{
  display:none;width:44px;height:44px;border:1px solid var(--line);
  border-radius:12px;background:rgba(255,255,255,.7);cursor:pointer;
  flex-direction:column;align-items:center;justify-content:center;gap:5px;
}
.menu-toggle span{width:18px;height:2px;background:var(--ink);border-radius:2px;transition:.3s var(--ease)}
body.nav-open .menu-toggle span:nth-child(1){transform:translateY(7px) rotate(45deg)}
body.nav-open .menu-toggle span:nth-child(2){opacity:0}
body.nav-open .menu-toggle span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

/* ============================================================
   HERO — full screen
   ============================================================ */
.hero{
  position:relative;min-height:95svh;
  display:flex;align-items:center;
  padding:120px clamp(20px,4vw,44px);   /* symmetric — was 96px at the bottom */
  overflow:hidden;isolation:isolate;
}
.hero-photo{
  position:absolute;inset:0;z-index:-2;
  width:100%;height:100%;object-fit:cover;object-position:center 38%;
  background:var(--sky-100);
  transform-origin:center;will-change:transform;
  animation:kenburns 34s ease-out forwards;
}
@keyframes kenburns{from{transform:scale(1)}to{transform:scale(1.07)}}

.hero-inner{
  position:relative;z-index:2;
  max-width:var(--wrap);margin:0 auto;width:100%;
}

/* frosted glass card holding the copy */
.hero-card{
  max-width:580px;
  padding:clamp(26px,2.6vw,38px);
  border-radius:28px;
  background:#fff;
  border:1px solid rgba(255,255,255,.85);
  box-shadow:0 34px 80px -34px rgba(18,54,74,.5),
             inset 0 1px 0 rgba(255,255,255,.6);
}

.hero-eyebrow{
  display:flex;align-items:center;gap:12px;
  font-family:var(--font-label);font-size:.76rem;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--brand-deep);
  margin-bottom:14px;
}
.hero-eyebrow::before,
.hero-eyebrow::after{
  content:"";height:1.5px;width:34px;flex:none;border-radius:2px;
}
/* leads in: transparent → solid */
.hero-eyebrow::before{background:linear-gradient(90deg,transparent,currentColor)}
/* trails out: solid → transparent */
.hero-eyebrow::after{background:linear-gradient(90deg,currentColor,transparent)}
.hero-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(2rem,3vw,2.75rem);
  line-height:1.12;letter-spacing:-.03em;color:var(--ink);
  margin:0;
}
.hero-title .accent{color:var(--brand-deep);white-space:nowrap}

.hero-sub{
  font-size:clamp(1.02rem,1.25vw,1.14rem);font-weight:400;
  color:var(--ink-soft);margin-top:20px;line-height:1.6;
}
.hero-cta{display:flex;gap:14px;margin-top:30px;flex-wrap:wrap}

.trust-list{display:flex;gap:9px;flex-wrap:wrap;margin-top:30px}
.trust-list li{
  font-family:var(--font-label);font-size:.78rem;font-weight:500;color:var(--ink-soft);
  padding:5px 12px;border:1px solid var(--line);border-radius:8px;
  background:rgba(255,255,255,.55);
  animation:chipPlace .55s cubic-bezier(.28,.86,.32,1.06) both;
  animation-delay:calc(.7s + var(--ci,0)*.15s);
}
/* gently placed down: descends from above and settles */
@keyframes chipPlace{
  0%{opacity:0;transform:translateY(-13px) scale(1.05)}
  55%{opacity:1}
  100%{opacity:1;transform:translateY(0) scale(1)}
}
@media (prefers-reduced-motion:reduce){
  .trust-list li{animation:none;opacity:1}
}

/* ============================================================
   STRATEGIC PARTNERSHIPS (logo marquee)
   ============================================================ */
.partners{
  padding:clamp(38px,5vw,60px) 0;
  background:#fff;
  border-bottom:1px solid var(--line-soft);
  overflow:hidden;
}
.partners-eyebrow{
  display:flex;align-items:center;justify-content:center;gap:12px;
  font-family:var(--font-label);font-size:.76rem;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--brand-deep);
  margin:0 0 clamp(26px,3vw,38px);
}
.partners-eyebrow::before,
.partners-eyebrow::after{content:"";height:1.5px;width:34px;border-radius:2px}
.partners-eyebrow::before{background:linear-gradient(90deg,transparent,currentColor)}
.partners-eyebrow::after{background:linear-gradient(90deg,currentColor,transparent)}

.marquee{
  position:relative;overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
}
.marquee-track{
  display:flex;align-items:center;width:max-content;
  gap:clamp(44px,6vw,88px);
  animation:marqueeScroll 42s linear infinite;
}
.marquee:hover .marquee-track{animation-play-state:paused}
.marquee-track img{
  height:44px;width:auto;flex:none;
  filter:grayscale(1);opacity:.55;
  transition:filter .35s var(--ease),opacity .35s var(--ease),transform .35s var(--ease);
}
.marquee-track img:hover{filter:none;opacity:1;transform:scale(1.06)}
@keyframes marqueeScroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}

@media (prefers-reduced-motion:reduce){
  .marquee-track{animation:none;flex-wrap:wrap;justify-content:center;width:auto}
}

/* ============================================================
   PROOF / MISSION-CRITICAL
   ============================================================ */
.proof,.bg-aurora{
  position:relative;overflow:hidden;isolation:isolate;
  padding:var(--sec-y) var(--sec-x);
  background:linear-gradient(180deg,#ffffff 0%,#f0f8fd 46%,#eef7f1 100%);
}
.proof-bg,.bgfx{position:absolute;inset:0;z-index:-1;pointer-events:none}
.proof-glow,.bgfx > i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.6}
.proof-glow.g1,.bgfx-g1{width:560px;height:560px;top:-140px;left:-100px;
  background:radial-gradient(circle,rgba(42,196,244,.55),transparent 66%);
  animation:pDrift 24s ease-in-out infinite}
.proof-glow.g2,.bgfx-g2{width:520px;height:520px;bottom:-180px;right:-120px;
  background:radial-gradient(circle,rgba(120,196,133,.5),transparent 66%);
  animation:pDrift 30s ease-in-out infinite reverse}
.proof-glow.g3,.bgfx-g3{width:420px;height:420px;top:38%;left:52%;
  background:radial-gradient(circle,rgba(120,178,232,.4),transparent 68%);
  animation:pDrift 34s ease-in-out infinite}
@keyframes pDrift{0%,100%{transform:translate(0,0)}50%{transform:translate(34px,-28px)}}

.proof-inner{max-width:1180px;margin:0 auto;text-align:center}   /* wide enough for the headline to hold 2 lines */

.proof-eyebrow{
  font-family:var(--font-label);font-size:.78rem;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--brand-deep);
  opacity:0;transform:translateY(12px);transition:opacity .7s var(--ease),transform .7s var(--ease);
}
.proof.in .proof-eyebrow{opacity:1;transform:none}

.proof-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(1.95rem,4.4vw,3.35rem);
  line-height:1.16;letter-spacing:-.02em;color:var(--ink);
  margin:20px 0 0;
}
.proof-title .accent{color:var(--brand-deep)}
.proof-title .plus{transform:translateY(-.14em)}   /* lift the + so it reads more centered on 200 */

/* count-up odometer (JS-driven, single counting value) */
.counter{display:inline-flex;align-items:flex-start;vertical-align:baseline}
.counter .odo{
  display:inline-block;height:1em;line-height:1;overflow:hidden;
  width:.62em;text-align:center;
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum";
}
.counter .reel{display:flex;flex-direction:column;transform:translateY(0);will-change:transform}
.counter .reel>span{height:1em;line-height:1;display:block}
.counter .plus{display:inline-block;height:1em;line-height:1}

/* word-by-word rise */
.anim-words .w{display:inline-block;overflow:hidden;vertical-align:top;
  padding-bottom:.16em;margin-bottom:-.16em}
.anim-words .w>span{display:inline-block;transform:translateY(112%);opacity:0;
  transition:transform .72s var(--ease),opacity .72s var(--ease);
  transition-delay:calc(var(--i,0)*55ms)}
.proof.in .anim-words .w>span{transform:none;opacity:1}

.proof-text{
  max-width:640px;margin:26px auto 0;
  /* ⚠️ --ink, NOT --ink-soft. Body copy site-wide is --ink-soft (#545454), but
     the client asked for this paragraph to match the heading above it exactly
     (#404041) rather than sit a shade lighter. 2026-09-21, their request. */
  font-size:clamp(1.05rem,1.4vw,1.22rem);color:var(--ink);line-height:1.66;
  opacity:0;transform:translateY(18px);
  transition:opacity .8s var(--ease) .5s,transform .8s var(--ease) .5s;
}
.proof.in .proof-text{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
  .proof-eyebrow,.proof-text,.anim-words .w>span{opacity:1!important;transform:none!important}
  .proof-glow{animation:none}
}

/* ============================================================
   ADVANTAGES GRID
   ============================================================ */
.advantages,.bg-clouds{
  position:relative;
  overflow:hidden;                          /* clip the parallax overhang */
  padding:var(--sec-y) var(--sec-x);
  background-color:#e1f0f9;                 /* matches the image's faded blue */
  --adv-par:0px;                            /* set by scroll JS */
}
/* cloud layer — taller than the section so it can drift on scroll */
.advantages::before,.bg-clouds::before{
  content:"";position:absolute;left:0;right:0;top:-14%;height:128%;
  /* fade layer (on top) melts the image's bottom edge into the section blue so no seam shows */
  background-image:
    linear-gradient(to bottom, rgba(225,240,249,0) 50%, #e1f0f9 73%),
    url("images/adv-bg.jpg?v=2");
  background-size:100% 100%, 135% auto;
  background-position:top center, top center;
  background-repeat:no-repeat, no-repeat;
  transform:translate3d(0,var(--adv-par),0);
  will-change:transform;z-index:0;pointer-events:none;
}
.adv-inner{position:relative;z-index:1;max-width:1180px;margin:0 auto}

.adv-head{
  text-align:center;max-width:660px;margin:0 auto clamp(56px,6.5vw,92px);   /* tighter than --head-gap on purpose: pulls the heading in against the bento */
  opacity:0;translate:0 16px;transition:opacity .7s var(--ease),translate .7s var(--ease);
}
.advantages.in .adv-head{opacity:1;translate:0}
.adv-eyebrow{
  font-family:var(--font-label);font-size:.78rem;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--brand-deep);
}
.adv-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(1.7rem,3vw,2.4rem);line-height:1.16;letter-spacing:-.02em;
  color:var(--ink);margin-top:14px;
}

/* bento grid */
.bento{
  display:grid;gap:18px;
  grid-template-columns:repeat(4,1fr);
  grid-template-areas:
    "roi   roi   perf  perf"
    "roi   roi   peace sec"
    "cloud cloud eff   eff";
  grid-auto-rows:minmax(230px,auto);
}
/* Per-page grid variant. The default 4x1fr grid gives .b-peace and .b-sec only
   282px — about 21 characters per line, against ~50 in the lead cell — and on
   the partner page both of those headings wrap to two lines while the lead cell
   sits half empty. The bento does not have to be identical on every page, so
   pages whose content is bottom-heavy narrow the lead column and hand the width
   to the two single-column cells. Only the column ratio changes; the areas,
   spans and both breakpoints below are untouched. */
/* Desktop only. Media queries add no specificity, so an unscoped
   `.bento.bento-wide-right` (0,2,0) outranked the `.bento` (0,1,0) rules inside
   the 1020px and 560px breakpoints and kept forcing four columns — the cells
   collapsed to 163px at 980 and 90px at 560. */
@media (min-width:1021px){
  .bento.bento-wide-right{grid-template-columns:.78fr .78fr 1.22fr 1.22fr}
}

/* Swap the two single-column cells. Doing this in the DATA instead would move
   each card into the other's slot — .b-peace owns the display numeral and
   .b-sec owns the badge strip — so the "14 nines" and the compliance badges
   would both be silently dropped. Trading the grid areas keeps every card with
   its own content and just changes where it sits. */
.bento.bento-swap-pair .b-peace{grid-area:sec}
.bento.bento-swap-pair .b-sec  {grid-area:peace}
/* The hero numeral is sized for a 581px cell; at 457px it left the caption
   beside it only ~90px and the label ran 43px outside the card. Scaled to the
   narrower column (457/581 ≈ 0.79) so the stat row fits without wrapping oddly.
   flex-wrap is a backstop: a longer caption should stack, never overflow. */
.bento-wide-right .b-num{font-size:clamp(5.6rem,9.6vw,9rem)}
.bento-wide-right .b-roi .b-stat{flex-wrap:wrap;gap:14px}
.bento-wide-right .b-statlabel{min-width:0}

.b-roi{grid-area:roi}
.b-perf{grid-area:perf}
.b-peace{grid-area:peace}
.b-sec{grid-area:sec}
.b-cloud{grid-area:cloud}
.b-eff{grid-area:eff}

.bento-cell{
  position:relative;overflow:hidden;
  background:#fff;border:1px solid var(--line-soft);border-radius:24px;
  box-shadow:0 6px 22px -16px rgba(18,54,74,.4);
  display:flex;flex-direction:column;
  opacity:0;translate:0 24px;
  transition:opacity .6s var(--ease),translate .6s var(--ease),
             transform .4s var(--ease),box-shadow .4s var(--ease);
}
.advantages.in .bento-cell{
  opacity:1;translate:0;
  transition-delay:calc(var(--i,0)*80ms),calc(var(--i,0)*80ms),0s,0s;
}
.advantages.in .bento-cell:hover{
  transform:translateY(-5px);
  box-shadow:0 24px 50px -22px rgba(18,54,74,.5);
}

.b-body{padding:clamp(22px,2.2vw,30px);position:relative;z-index:2}
/* CTA row under the bento (client 2026-09-21: the Why Opus section had no way
   out of it). Reveals with the section like the cells do, after the last one. */
.adv-cta{
  display:flex;flex-wrap:wrap;justify-content:center;gap:14px;
  margin-top:clamp(26px,3vw,38px);
  opacity:0;translate:0 16px;
  transition:opacity .6s var(--ease) .45s,translate .6s var(--ease) .45s;
}
.advantages.in .adv-cta{opacity:1;translate:0}
@media (max-width:520px){
  .adv-cta{flex-direction:column;align-items:stretch}
  .adv-cta .btn{justify-content:center}
}
.bento-cell h3{
  font-family:var(--font-main);font-size:1.16rem;font-weight:600;
  letter-spacing:-.01em;color:var(--ink);margin-bottom:9px;
}
.bento-cell p{font-size:.96rem;color:var(--ink-soft);line-height:1.6}

/* animated draw-on feature icons */
.adv-ic{position:relative;display:inline-grid;width:60px;height:60px;flex:none}
.adv-ic.adv-ic-lg{width:70px;height:70px}
.adv-ic svg{
  grid-area:1/1;width:100%;height:100%;
  fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;overflow:visible;
}
.adv-ic .ai-base{stroke:rgba(18,35,47,.16);transition:stroke .35s var(--ease)}
.adv-ic .ai-draw{stroke:var(--brand-sky)}   /* client brand blue #2cabe2 */
.adv-ic .ai-draw > *{
  stroke-dasharray:1.02;stroke-dashoffset:1.02;
  transition:stroke-dashoffset .7s linear .05s;
}
.bento-cell:hover .adv-ic .ai-base{stroke:rgba(44,171,226,.28)}
.bento-cell:hover .adv-ic .ai-draw > *{stroke-dashoffset:0}

/* ROI — big feature: icon top, big stat pinned bottom */
.b-roi .b-body{display:flex;flex-direction:column;height:100%}
.b-roi .adv-ic{margin-bottom:20px}
.b-roi h3{font-size:1.32rem}
.b-roi .b-stat{
  display:flex;align-items:center;gap:18px;margin-top:auto;padding-top:24px;
}
.b-num{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(7.5rem,12.8vw,11.9rem);   /* hero stat, ~15% smaller */
  line-height:.82;letter-spacing:-.05em;color:var(--brand-deep);
}
.b-statlabel{
  font-family:var(--font-label);font-size:.82rem;font-weight:600;
  letter-spacing:.08em;text-transform:uppercase;color:var(--ink-faint);line-height:1.45;
}

/* wide cells — text left, icon panel right */
.b-perf,.b-cloud,.b-eff{flex-direction:row;align-items:stretch}
.b-perf .b-body,.b-cloud .b-body,.b-eff .b-body{flex:1.35;align-self:center}
/* brand blue → green gradient panel */
.b-iconwrap{
  position:relative;overflow:hidden;
  flex:1;min-width:0;display:grid;place-items:center;padding:20px;
  background:linear-gradient(150deg,#ddf1fb 0%,#eaf7d8 100%);
  border-left:1px solid var(--line-soft);
}
.b-iconwrap .adv-ic{width:78px;height:78px}

/* stat cell */
.b-peace{justify-content:flex-end}
.b-peace .b-bignum{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(2.6rem,3.6vw,3.6rem);line-height:1;letter-spacing:-.03em;
  color:var(--brand-deep);padding:clamp(22px,2.2vw,30px) clamp(22px,2.2vw,30px) 0;
}
.b-peace .b-bignum i{font-style:normal;font-size:.6em}
.b-peace .b-bignum-label{
  font-family:var(--font-label);font-size:.74rem;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;color:var(--ink-faint);
  padding:4px clamp(22px,2.2vw,30px) 0;
}
.b-peace .b-body{padding-top:14px}

/* badges cell */
.b-sec{justify-content:flex-end}
.b-badges{
  display:flex;flex-wrap:wrap;gap:8px;list-style:none;
  padding:clamp(22px,2.2vw,30px) clamp(22px,2.2vw,30px) 0;
}
.b-badges li{
  font-family:var(--font-label);font-size:.74rem;font-weight:600;color:var(--brand-deep);
  border:1px solid rgba(42,196,244,.45);background:rgba(42,196,244,.07);
  padding:5px 11px;border-radius:8px;
}
.b-sec .b-body{padding-top:14px}

@media (max-width:1020px){
  .bento{
    grid-template-columns:repeat(2,1fr);
    grid-template-areas:
      "roi   roi"
      "perf  perf"
      "peace sec"
      "cloud cloud"
      "eff   eff";
    grid-auto-rows:auto;
  }
}
@media (max-width:560px){
  .bento{
    grid-template-columns:minmax(0,1fr);gap:14px;
    grid-template-areas:"roi" "perf" "peace" "sec" "cloud" "eff";
  }
  .b-perf,.b-cloud,.b-eff{flex-direction:column}
  .b-iconwrap{border-left:none;border-top:1px solid var(--line-soft);padding:30px}
}
@media (prefers-reduced-motion:reduce){
  .adv-head,.bento-cell{opacity:1!important;translate:none!important}
}

/* ============================================================
   SOLUTIONS / SERVICES TRIO (full-width)
   ============================================================ */
.solutions{
  background:#fff;
  padding:var(--sec-y) 0 0;   /* no white below — the panel images cut straight into the blue Colocation band */
}
.sol-head{
  max-width:1080px;margin:0 auto var(--head-gap);   /* gap below the intro == the gap above the title */
  padding:0 clamp(20px,5vw,44px);text-align:center;
  opacity:0;translate:0 16px;transition:opacity .7s var(--ease),translate .7s var(--ease);
}
.solutions.in .sol-head{opacity:1;translate:0}
.sol-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(1.7rem,3vw,2.4rem);line-height:1.16;letter-spacing:-.02em;color:var(--ink);
}
.sol-title .accent{color:var(--brand-deep)}
.sol-intro{
  font-size:clamp(1.02rem,1.25vw,1.14rem);color:var(--ink-soft);
  line-height:1.66;margin-top:18px;
}

/* full-bleed 3 tall panels, text overlaid on the image */
.sol-grid{
  display:grid;grid-template-columns:repeat(3,1fr);gap:0;width:100%;
}
.sol-col{
  position:relative;overflow:hidden;
  height:clamp(560px,80vh,940px);
  display:flex;align-items:flex-end;
  opacity:0;translate:0 24px;
  transition:opacity .6s var(--ease),translate .6s var(--ease);
}
.solutions.in .sol-col{opacity:1;translate:0;transition-delay:calc(var(--i,0)*90ms)}

/* image layer (blank placeholder for now) + scrim for text legibility */
.sol-media{
  position:absolute;inset:0;z-index:0;display:grid;place-items:center;
  background:linear-gradient(160deg,#dfe6ee,#c9d4de);
}
.sol-media img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transition:transform .7s var(--ease);
}
.sol-col:hover .sol-media img{transform:scale(1.04)}
/* dark padding band below the panels → melts into the globe section */
.sol-fade{
  height:clamp(150px,20vh,280px);
  background:#2cabe2;
}
.sol-media::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(6,18,26,0) 32%,rgba(6,18,26,.42) 62%,rgba(6,18,26,.88) 100%);
}
.sol-media .ph{
  position:relative;z-index:1;
  font-family:var(--font-label);font-size:.8rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(64,64,65,.42);
}

.sol-body{
  position:relative;z-index:2;
  padding:clamp(28px,3vw,46px) clamp(28px,3vw,46px) clamp(60px,7.5vh,104px);   /* lift CTA up off the bottom fade */
  color:#fff;
}
.sol-body h3{
  font-family:var(--font-main);font-size:clamp(1.35rem,1.9vw,1.75rem);font-weight:600;
  letter-spacing:-.01em;color:#fff;margin-bottom:12px;
}
.sol-body p{font-size:1rem;color:rgba(255,255,255,.9);line-height:1.6;margin-bottom:20px}
.sol-link{
  display:inline-flex;align-items:center;gap:.5em;
  font-family:var(--font-main);font-weight:600;font-size:.98rem;color:#fff;
}
.sol-link svg{transition:transform .3s var(--ease)}
.sol-link:hover svg{transform:translateX(4px)}

@media (max-width:860px){
  .sol-grid{grid-template-columns:minmax(0,1fr)}
  .sol-col{height:clamp(440px,64vh,620px)}
}
@media (prefers-reduced-motion:reduce){
  .sol-head,.sol-col{opacity:1!important;translate:none!important}
}

/* The three blurbs are different lengths, so they wrap to different line
   counts — and because the block is anchored to the bottom of the panel, that
   pushed the shorter middle title lower than its neighbours.
   `subgrid` shares one set of rows across all three columns: spacer / title /
   copy / link. Each row is as tall as its tallest sibling, so the titles start
   on one line and the links on another, at ANY width and with ANY copy — no
   min-heights tuned to today's sentences.
   Only in the 3-up layout: stacked, each panel owns its own rows. */
@media (min-width:861px){
  @supports (grid-template-rows:subgrid){
    .sol-grid{grid-template-rows:1fr auto auto auto;height:clamp(560px,80vh,940px)}
    .sol-col{
      height:auto;grid-row:1 / -1;
      display:grid;grid-template-rows:subgrid;
      /* the base rule sets align-items:flex-end for the flex fallback. In the
         grid that reads as `end`, which sticks every item to the BOTTOM of its
         row — so the paragraphs lined up by their last line and their tops
         drifted by however many lines each one wrapped to. Items go to the
         START of their row; the empty 1fr row above does the bottom-anchoring. */
      align-items:start;
      /* moved off .sol-body, which is now display:contents. The image is
         position:absolute inset:0, so it still covers the padding box. */
      padding:clamp(28px,3vw,46px) clamp(28px,3vw,46px) clamp(60px,7.5vh,104px);
    }
    .sol-col:nth-of-type(1){grid-column:1}
    .sol-col:nth-of-type(2){grid-column:2}
    .sol-col:nth-of-type(3){grid-column:3}
    .sol-body{display:contents}
    /* placed, not auto-flowed — auto-placement starts at row 1 and would put
       the heading in the spacer row */
    .sol-body > h3{grid-row:2}
    .sol-body > p{grid-row:3}
    .sol-body > .sol-link{grid-row:4;justify-self:start}
    .sol-body > *{position:relative;z-index:2}
  }
}

/* ============================================================
   LOCATIONS / GLOBE
   ============================================================ */
.locations{
  position:relative;overflow:hidden;isolation:isolate;
  color:#fff;
  /* brand-blue field: stays deep behind the heading (white text keeps its
     contrast), opens into the client's #2cabe2 behind the globe, then deepens
     again so it blends into the dark White Glove section below. */
  background:#2cabe2;
}
/* subtle star particles to match the space vibe of the earth */
.loc-stars{display:none}   /* no starfield on the blue field */
.loc-stars::before,.loc-stars::after{content:"";position:absolute;inset:-25% 0;background-repeat:repeat}
.loc-stars::before{
  background-image:
    radial-gradient(1.5px 1.5px at 40px 60px,rgba(255,255,255,.9),transparent),
    radial-gradient(1px 1px at 130px 30px,rgba(255,255,255,.7),transparent),
    radial-gradient(1px 1px at 95px 165px,rgba(255,255,255,.6),transparent),
    radial-gradient(1.5px 1.5px at 205px 120px,rgba(255,255,255,.85),transparent),
    radial-gradient(1px 1px at 255px 205px,rgba(255,255,255,.5),transparent),
    radial-gradient(1px 1px at 20px 232px,rgba(255,255,255,.6),transparent);
  background-size:290px 290px;
  animation:starTwinkle 5.5s ease-in-out infinite;
}
.loc-stars::after{
  background-image:
    radial-gradient(1px 1px at 60px 100px,rgba(255,255,255,.55),transparent),
    radial-gradient(1.6px 1.6px at 180px 45px,rgba(255,255,255,.8),transparent),
    radial-gradient(1px 1px at 232px 175px,rgba(255,255,255,.5),transparent),
    radial-gradient(1px 1px at 110px 250px,rgba(255,255,255,.55),transparent);
  background-size:360px 360px;opacity:.75;
  animation:starTwinkle 7.5s ease-in-out infinite reverse;
}
@keyframes starTwinkle{0%,100%{opacity:.5}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.loc-stars::before,.loc-stars::after{animation:none}}
/* heading + intro sit in their own solid black band ABOVE the globe */
.loc-head{
  text-align:center;max-width:1120px;margin:0 auto;
  padding:var(--sec-y) clamp(20px,4vw,44px) clamp(48px,7vw,106px);   /* top matches every other section; bottom lands the earth gap on 150 too */
}
/* the globe + cycling card live in their own stage below the heading */
.loc-stage{position:relative;min-height:100svh;overflow:hidden;display:flex;flex-direction:column;justify-content:center}
.loc-stage::before{
  content:"";position:absolute;top:0;left:0;right:0;height:190px;z-index:1;
  background:none;
  pointer-events:none;
}

.loc-globe{
  position:absolute;top:0;right:0;height:100%;
  aspect-ratio:2752/1536;
  opacity:0;transform:translateY(74px);
  transition:opacity 1.1s var(--ease),transform 1.45s cubic-bezier(.16,.8,.24,1);
}
.locations.in .loc-globe{opacity:1;transform:translateY(0)}
@media (prefers-reduced-motion:reduce){
  .loc-globe{opacity:1;transform:none;transition:none}
}
.loc-globe img{width:100%;height:100%;object-fit:cover;display:block}

/* pins */
.loc-pin{
  position:absolute;left:var(--x);top:var(--y);transform:translate(-50%,-50%);
  display:flex;align-items:center;gap:9px;
  background:none;border:none;cursor:pointer;padding:8px;z-index:3;
  font-family:var(--font-main);
}
.pin-dot{
  width:13px;height:13px;border-radius:50%;flex:none;position:relative;
  background:#fff;
  box-shadow:0 0 0 3px rgba(255,255,255,.32),0 0 16px rgba(255,255,255,.85);
  transition:transform .3s var(--ease),box-shadow .3s var(--ease);
}
.pin-dot::after{
  content:"";position:absolute;inset:-3px;border-radius:50%;
  border:1.5px solid rgba(255,255,255,.75);
  animation:pinPulse 2.4s ease-out infinite;
}
@keyframes pinPulse{
  0%{transform:scale(1);opacity:1}
  70%,100%{transform:scale(2.6);opacity:0}
}
.pin-label{
  font-size:.82rem;font-weight:600;letter-spacing:.02em;color:#eaf6fd;
  background:rgba(4,16,28,.66);border:1px solid rgba(42,196,244,.35);
  padding:5px 12px;border-radius:100px;backdrop-filter:blur(8px);
  transition:background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease);
  white-space:nowrap;
}
.loc-pin:hover .pin-dot,
.loc-pin.active .pin-dot{transform:scale(1.35);box-shadow:0 0 0 4px rgba(255,255,255,.4),0 0 24px rgba(255,255,255,1)}
.loc-pin.active .pin-label{background:#fff;border-color:#fff;color:var(--ink)}

/* left panel */
.loc-inner{
  position:relative;z-index:2;pointer-events:none;   /* let pin hover/click pass through the empty overlay */
  max-width:var(--wrap);margin:0 auto;width:100%;
  padding:clamp(30px,5vh,64px) clamp(20px,4vw,44px);
}
.loc-panel{max-width:500px;pointer-events:auto}

.loc-eyebrow{
  display:flex;align-items:center;justify-content:center;gap:14px;
  font-family:var(--font-label);font-size:.92rem;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--brand);
}
.loc-eyebrow::before{content:"";height:1.5px;width:34px;border-radius:2px;
  background:linear-gradient(90deg,transparent,currentColor)}
.loc-eyebrow::after{content:"";height:1.5px;width:34px;border-radius:2px;
  background:linear-gradient(90deg,currentColor,transparent)}

.loc-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(2.3rem,4.2vw,3.4rem);line-height:1.12;letter-spacing:-.02em;
  color:#fff;margin:18px 0 0;
}
.loc-title .accent{color:var(--brand)}
.loc-intro{
  font-size:clamp(1.08rem,1.35vw,1.28rem);color:rgba(255,255,255,.78);line-height:1.6;
  margin-top:18px;
}

/* cycling card */
.loc-card{
  margin-top:0;padding:26px 28px;border-radius:20px;
  background:rgba(6,13,22,.58);            /* dark glass instead of white tint */
  border:1px solid rgba(255,255,255,.16);
  backdrop-filter:saturate(150%) blur(18px);
  -webkit-backdrop-filter:saturate(150%) blur(18px);
  box-shadow:0 26px 60px -26px rgba(0,0,0,.65),inset 0 1px 0 rgba(255,255,255,.28);
  transition:opacity .19s ease,transform .19s ease;
}
.loc-card.swapping{opacity:0;transform:translateY(9px)}
.loc-card-img{
  width:100%;aspect-ratio:16/8;object-fit:cover;display:block;
  border-radius:14px;margin-bottom:18px;border:1px solid rgba(255,255,255,.16);
}
.loc-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.loc-card-head h3{
  font-family:var(--font-main);font-size:1.95rem;font-weight:600;
  letter-spacing:-.02em;color:#fff;
}
.loc-grid{
  font-family:var(--font-label);font-size:.7rem;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--brand);
  background:rgba(42,196,244,.14);border:1px solid rgba(42,196,244,.5);border-radius:100px;padding:5px 12px;
  white-space:nowrap;
}
.loc-city{
  font-family:var(--font-label);font-size:1.02rem;color:rgba(255,255,255,.86);
  margin-top:6px;
}
.loc-desc{font-size:.98rem;color:rgba(255,255,255,.95);line-height:1.62;margin-top:14px}
.loc-feats{margin-top:16px;display:grid;gap:9px}
.loc-feats li{
  display:flex;align-items:center;gap:10px;
  font-size:.93rem;color:rgba(255,255,255,.94);
}
.loc-feats li::before{
  content:"";width:16px;height:16px;flex:none;border-radius:50%;
  background:rgba(42,196,244,.16) no-repeat center/9px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M1.5 5.2 4 7.6 8.5 2.6' fill='none' stroke='%232AC4F4' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.loc-cta{
  margin-top:22px;display:inline-flex;align-items:center;gap:.5em;
  font-family:var(--font-main);font-weight:600;font-size:.97rem;color:var(--brand);
}
.loc-cta svg{transition:transform .3s var(--ease)}
.loc-cta:hover svg{transform:translateX(4px)}

/* cycle progress bars */
.loc-cycle{display:flex;gap:10px;margin-top:26px}
.cyc-bar{
  width:44px;height:3px;border-radius:3px;overflow:hidden;
  background:rgba(255,255,255,.16);
}
.cyc-bar i{display:block;width:0;height:100%;background:var(--brand);border-radius:3px}
.cyc-bar.run i{animation:cycFill 5s linear forwards}
.loc-cycle.paused .cyc-bar.run i{animation-play-state:paused}
@keyframes cycFill{from{width:0}to{width:100%}}

@media (max-width:900px){
  .locations{display:block}
  .loc-stage{min-height:auto}
  .loc-globe{position:relative;height:auto;width:100%}
  /* ⚠️ 10px let the earth sit ON the card: measured -1px at 601 and 0px at
     768. The globe is a full-width block here, so this padding IS the gap. */
  .loc-inner{padding-top:38px;padding-bottom:72px}
  .loc-panel{max-width:none}
  .pin-label{display:none;font-size:.74rem;padding:4px 9px}
  .loc-pin.active .pin-label{display:block}
}
@media (prefers-reduced-motion:reduce){
  .pin-dot::after{animation:none}
  .cyc-bar.run i{animation:none;width:100%}
}

/* ============================================================
   REVEAL
   ============================================================ */
.reveal{opacity:0;transform:translateY(18px);animation:rise .9s var(--ease) forwards;animation-delay:var(--d,0s)}
@keyframes rise{to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .reveal{opacity:1;transform:none}
  .hero-photo{transform:none!important}
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
/* Between the drawer breakpoint and ~1300 the full desktop header no longer fits
   at its natural sizes (logo 240 + nav 616 + buttons 232 + gaps + padding needs
   ~1280). Rather than let something shrink, tighten the gaps through that band. */
@media (max-width:1300px) and (min-width:1181px){
  .header-inner{gap:16px;padding-left:24px;padding-right:24px}
  .nav{gap:18px}
  .nav-cluster{gap:14px}
}

/* Was 980. The desktop header cannot fit below ~1180 without squeezing the logo,
   so the drawer now takes over there instead of at 980. */
@media (max-width:1180px){
  .nav,.header-actions .btn{display:none}
  .menu-toggle{display:flex}
  .logo img{height:40px}
  /* the drawer .nav below goes position:fixed, so it leaves the grid and the
     centre column collapses — which would strand the buttons mid-header.
     Back to flex for the two remaining in-flow children. */
  .header-inner{display:flex;justify-content:space-between}

  .nav{
    position:fixed;inset:70px 14px auto;display:flex;flex-direction:column;gap:2px;
    background:rgba(251,253,255,.97);backdrop-filter:blur(20px);
    border:1px solid var(--line);border-radius:20px;padding:14px;
    box-shadow:var(--shadow-md);
    opacity:0;transform:translateY(-12px) scale(.98);pointer-events:none;
    transition:.32s var(--ease);
  }
  body.nav-open .nav{opacity:1;transform:none;pointer-events:auto}
  .nav-item{width:100%}
  .nav-link{width:100%;padding:13px 14px;border-radius:12px;font-size:1.05rem}
  .nav-link::after{display:none}
  .nav-link:hover{background:var(--brand);color:#fff;opacity:1}
  .mega{display:none}   /* mega panels are desktop-only; drawer shows top-level links */

  .hero{padding-top:108px;padding-bottom:108px}
}
@media (max-width:520px){
  .hero-title{font-size:clamp(2rem,8vw,2.6rem)}
  /* The accent line is nowrap on desktop so the phrase never breaks mid-thought.
     On a phone that pushes the longer inner-page headlines ("Tailored for
     Healthcare", "Tailored for Real Results") clean off the card — up to 68px
     past its edge. Let it wrap here; there is no room to hold the line. */
  .hero-title .accent{white-space:normal}
  .hero-cta{flex-direction:column;align-items:stretch}
  .hero-cta .btn{justify-content:center}
}

/* ============================================================
   WHITE GLOVE SUPPORT (dark, human + counting stats)
   ============================================================ */
.glove{
  position:relative;overflow:hidden;isolation:isolate;
  background:#2cabe2;
  color:#fff;
  padding:calc(var(--sec-y) + 50px) var(--sec-x);   /* taller than the base rhythm; equal top and bottom keeps it centred */
}
.glove-bg{position:absolute;inset:0;z-index:-1;pointer-events:none}
/* black fade at the top so it blends into the earth section above */
.glove-bg::after{content:"";position:absolute;top:0;left:0;right:0;height:380px;
  background:none}
.glove-glow{position:absolute;border-radius:50%;filter:blur(100px);opacity:.5}
.glove-glow.gg1{width:640px;height:640px;top:-220px;right:-160px;
  background:radial-gradient(circle,rgba(42,196,244,.34),transparent 66%);
  animation:pDrift 26s ease-in-out infinite}
.glove-glow.gg2{width:520px;height:520px;bottom:-240px;left:-140px;
  background:radial-gradient(circle,rgba(44,171,226,.3),transparent 66%);
  animation:pDrift 32s ease-in-out infinite reverse}

.glove-inner{max-width:var(--wrap);margin:0 auto}
.glove-top{
  display:grid;grid-template-columns:1.05fr 1fr;gap:clamp(40px,5.5vw,80px);
  align-items:center;
}
.glove-eyebrow{
  display:flex;align-items:center;gap:12px;
  font-family:var(--font-label);font-size:.76rem;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--brand);
}
.glove-eyebrow::before{content:"";height:1.5px;width:34px;border-radius:2px;
  background:linear-gradient(90deg,transparent,currentColor)}
.glove-eyebrow::after{content:"";height:1.5px;width:34px;border-radius:2px;
  background:linear-gradient(90deg,currentColor,transparent)}
.glove-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(1.9rem,3.3vw,2.7rem);line-height:1.13;letter-spacing:-.02em;
  margin-top:16px;
  opacity:0;translate:0 16px;transition:opacity .7s var(--ease),translate .7s var(--ease);
}
.glove.in .glove-title{opacity:1;translate:0}
.glove-title .accent{color:var(--brand)}
.glove-intro{
  font-size:clamp(1.02rem,1.3vw,1.16rem);color:rgba(255,255,255,.78);line-height:1.68;
  margin-top:18px;max-width:34em;
  opacity:0;translate:0 16px;transition:opacity .7s var(--ease) .12s,translate .7s var(--ease) .12s;
}
.glove.in .glove-intro{opacity:1;translate:0}
.glove-copy .btn{margin-top:28px}

.glove-media{
  position:relative;border-radius:26px;overflow:hidden;
  border:1px solid rgba(255,255,255,.16);
  box-shadow:0 40px 90px -34px rgba(0,0,0,.85),0 0 0 6px rgba(255,255,255,.03);
  opacity:0;translate:0 24px;transition:opacity .8s var(--ease) .18s,translate .8s var(--ease) .18s;
}
.glove.in .glove-media{opacity:1;translate:0}
.glove-media img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block}
.glove-media::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(200deg,rgba(42,196,244,.12) 0%,transparent 42%);
  pointer-events:none;
}
.glove-live{
  position:absolute;left:16px;bottom:16px;
  display:flex;align-items:center;gap:9px;
  font-family:var(--font-label);font-size:.8rem;font-weight:600;color:#eaf6fd;
  background:rgba(4,16,28,.72);border:1px solid rgba(42,196,244,.35);
  padding:8px 14px;border-radius:100px;backdrop-filter:blur(10px);
}
.live-dot{
  width:8px;height:8px;border-radius:50%;background:#3ddc84;
  box-shadow:0 0 0 4px rgba(61,220,132,.22);
  animation:pulse 2.2s ease-in-out infinite;
}

.glove-stats{
  display:grid;grid-template-columns:repeat(4,1fr);gap:18px;
  margin-top:var(--head-gap);list-style:none;
}
.glove-stats li{
  position:relative;overflow:hidden;
  padding:clamp(26px,2.6vw,36px) 22px;border-radius:20px;
  background:rgba(255,255,255,.055);
  border:1px solid rgba(255,255,255,.13);
  backdrop-filter:blur(10px);
  transition:opacity .6s var(--ease),translate .6s var(--ease),
             border-color .35s var(--ease),background .35s var(--ease);
  opacity:0;translate:0 22px;
}
.glove-stats li::before{
  content:"";position:absolute;left:0;top:0;height:2px;width:100%;
  background:linear-gradient(90deg,transparent,rgba(42,196,244,.7),transparent);
  opacity:0;transition:opacity .35s var(--ease);
}
.glove-stats li:hover{border-color:rgba(42,196,244,.4);background:rgba(42,196,244,.07)}
.glove-stats li:hover::before{opacity:1}
.glove.in .glove-stats li{opacity:1;translate:0;transition-delay:calc(.25s + var(--i,0)*90ms),calc(.25s + var(--i,0)*90ms),0s,0s}
.gs-num{
  display:flex;align-items:baseline;
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(2.4rem,3.6vw,3.4rem);line-height:1;letter-spacing:-.03em;color:var(--brand);
}
.gs-num .plus{font-size:.42em;margin-left:3px;letter-spacing:0}
.gs-label{
  display:block;margin-top:12px;
  font-family:var(--font-label);font-size:.88rem;color:rgba(255,255,255,.8);line-height:1.5;
}
@media (max-width:980px){
  .glove-top{grid-template-columns:minmax(0,1fr)}
  .glove-stats{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:520px){.glove-stats{grid-template-columns:minmax(0,1fr)}}

/* ============================================================
   EXPLORING CLOUD ALTERNATIVES (journey timeline)
   ============================================================ */
.explore{
  position:relative;overflow:hidden;
  background:
    radial-gradient(80% 55% at 12% 8%, rgba(42,196,244,.09) 0%, transparent 55%),
    radial-gradient(70% 50% at 95% 90%, rgba(120,196,133,.08) 0%, transparent 60%),
    var(--paper);
  padding:var(--sec-y) var(--sec-x);
}
.explore-inner{
  max-width:var(--wrap);margin:0 auto;
  display:grid;grid-template-columns:1fr 1.25fr;gap:clamp(40px,6vw,96px);
  align-items:center;   /* left card centers against the steps (aligns with step 2) */
}
.explore-left{position:relative;transform:translateY(-50px)}
/* The -50px above offsets the card against a step column that runs much taller
   (70-180px on every other page). On the partner page the CARD is the taller of
   the two, so the same lift pushes it off-centre instead of centring it. */
.explore.x-even .explore-left{transform:none}
/* align-items:center lines up the MIDDLE OF THE BLOCK, but marker 2 sits at the
   top of its step, not at the block's centre — so the numbers read high against
   the card. The offset is (half the column height − marker 2's distance from the
   top), which no CSS length can express, so it is measured: 23-37px across
   901-1600, and 26px splits that. Below 901 the two columns stack and this is
   moot. */
.explore.x-even .x-steps{transform:translateY(26px)}
.x-card{
  padding:clamp(28px,3vw,42px);border-radius:26px;
  background:#fff;
  border:1px solid rgba(42,196,244,.25);
  box-shadow:0 30px 70px -34px rgba(18,54,74,.4),inset 0 1px 0 rgba(255,255,255,.9);
}
.x-eyebrow{
  display:flex;align-items:center;gap:12px;
  font-family:var(--font-label);font-size:.76rem;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--brand-deep);
}
.x-eyebrow::before{content:"";height:1.5px;width:34px;border-radius:2px;
  background:linear-gradient(90deg,transparent,currentColor)}
.x-eyebrow::after{content:"";height:1.5px;width:34px;border-radius:2px;
  background:linear-gradient(90deg,currentColor,transparent)}
.x-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(1.9rem,3.1vw,2.5rem);line-height:1.12;letter-spacing:-.02em;
  color:var(--ink);margin-top:16px;
}
.x-title .accent{color:var(--brand-deep)}
.x-chips{display:flex;gap:9px;flex-wrap:wrap;margin-top:18px;list-style:none}
.x-chips li{
  font-family:var(--font-label);font-size:.78rem;font-weight:600;color:var(--brand-deep);
  background:#fff;border:1px solid rgba(42,196,244,.4);
  padding:6px 13px;border-radius:100px;
}
.x-ready{font-size:1.02rem;font-weight:600;color:var(--ink);margin-top:22px}
.x-card .btn{margin-top:16px}

.x-steps{
  list-style:none;position:relative;
  display:grid;gap:clamp(28px,3.4vw,44px);
  padding-left:6px;
}
.x-step{
  position:relative;display:flex;gap:22px;align-items:flex-start;
  opacity:0;translate:0 20px;
  transition:opacity .7s var(--ease) calc(var(--i,0)*140ms),
             translate .7s var(--ease) calc(var(--i,0)*140ms);
}
.explore.in .x-step{opacity:1;translate:0}
.x-step:not(:last-child)::before{
  content:"";position:absolute;left:21px;top:52px;bottom:calc(-1 * clamp(28px,3.4vw,44px));
  width:2px;background:linear-gradient(180deg,rgba(42,196,244,.5),rgba(42,196,244,.1));
}
.x-marker{
  width:44px;height:44px;flex:none;border-radius:50%;
  display:grid;place-items:center;
  font-family:var(--font-main);font-weight:600;font-size:1.05rem;color:var(--brand-deep);
  background:#fff;border:1.5px solid rgba(42,196,244,.55);
  box-shadow:0 8px 20px -8px rgba(23,120,159,.4),0 0 0 6px rgba(42,196,244,.08);
}
.x-step-label{
  font-family:var(--font-main);font-weight:600;font-size:1.12rem;color:var(--ink);
  margin-bottom:8px;letter-spacing:-.01em;
}
.x-step p:not(.x-step-label){
  font-size:clamp(1rem,1.25vw,1.1rem);color:var(--ink-soft);line-height:1.7;
}
.x-step strong{color:var(--ink)}
@media (max-width:900px){
  .explore-inner{grid-template-columns:minmax(0,1fr)}
  .explore-left{position:static}
}

/* ============================================================
   CLOUD SERVICES INDEX (dark glass cards)
   ============================================================ */
.cloudsvc{
  position:relative;overflow:hidden;isolation:isolate;
  background:#2cabe2;
  color:#fff;
  padding:var(--sec-y) var(--sec-x);
}
.cs-bg{position:absolute;inset:0;z-index:-1;pointer-events:none}
.cs-glow{position:absolute;border-radius:50%;filter:blur(100px);opacity:.5}
.cs-glow.csg1{width:600px;height:600px;top:-180px;left:-140px;
  background:radial-gradient(circle,rgba(42,196,244,.3),transparent 66%);
  animation:pDrift 28s ease-in-out infinite}
.cs-glow.csg2{width:520px;height:520px;bottom:-220px;right:-140px;
  background:radial-gradient(circle,rgba(44,171,226,.32),transparent 66%);
  animation:pDrift 34s ease-in-out infinite reverse}
.cs-gridveil{
  position:absolute;inset:0;opacity:.35;
  background-image:linear-gradient(rgba(255,255,255,.045) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(255,255,255,.045) 1px,transparent 1px);
  background-size:56px 56px;
  mask-image:radial-gradient(ellipse 75% 55% at 50% 42%,#000 25%,transparent 76%);
  -webkit-mask-image:radial-gradient(ellipse 75% 55% at 50% 42%,#000 25%,transparent 76%);
}

.cs-head{
  max-width:860px;margin:0 auto var(--head-gap);text-align:center;
  opacity:0;translate:0 16px;transition:opacity .7s var(--ease),translate .7s var(--ease);
}
.cloudsvc.in .cs-head{opacity:1;translate:0}
.cs-eyebrow{
  display:flex;align-items:center;justify-content:center;gap:12px;
  font-family:var(--font-label);font-size:.76rem;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--brand);
}
.cs-eyebrow::before,.cs-eyebrow::after{content:"";height:1.5px;width:34px;border-radius:2px}
.cs-eyebrow::before{background:linear-gradient(90deg,transparent,currentColor)}
.cs-eyebrow::after{background:linear-gradient(90deg,currentColor,transparent)}
.cs-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(1.8rem,3.2vw,2.6rem);line-height:1.14;letter-spacing:-.02em;
  color:#fff;margin-top:16px;
}
.cs-title .accent{color:var(--brand)}
.cs-intro{font-size:clamp(1rem,1.25vw,1.12rem);color:rgba(255,255,255,.75);line-height:1.66;margin-top:16px}

.cs-grid{
  max-width:var(--wrap);margin:0 auto;list-style:none;
  display:grid;grid-template-columns:repeat(3,1fr);gap:18px;
}
.cs-cell{
  position:relative;overflow:hidden;
  padding:clamp(26px,2.6vw,36px);border-radius:22px;
  background:rgba(255,255,255,.055);
  border:1px solid rgba(255,255,255,.12);
  backdrop-filter:blur(10px);
  transition:opacity .6s var(--ease) calc(var(--i,0)*70ms),
             translate .6s var(--ease) calc(var(--i,0)*70ms),
             border-color .35s var(--ease),background .35s var(--ease),transform .35s var(--ease);
  opacity:0;translate:0 18px;
}
.cloudsvc.in .cs-cell{opacity:1;translate:0}
.cs-cell:hover{
  border-color:rgba(42,196,244,.45);background:rgba(42,196,244,.08);
  transform:translateY(-4px);
}
.cs-ghost{
  position:absolute;top:6px;right:14px;
  font-family:var(--font-main);font-weight:600;font-size:4.4rem;line-height:1;
  color:transparent;-webkit-text-stroke:1px rgba(255,255,255,.14);
  transition:-webkit-text-stroke-color .35s var(--ease);
  pointer-events:none;
}
.cs-cell:hover .cs-ghost{-webkit-text-stroke-color:rgba(42,196,244,.5)}

/* Private Cloud micro-interaction: 02 ⇄ lock */
.cs-ghost-swap{display:grid;place-items:center}
.cs-ghost-swap .g-num,
.cs-ghost-swap .g-icon{grid-area:1/1;transition:opacity .35s var(--ease)}
.cs-ghost-swap .g-icon{
  width:52px;height:auto;
  color:rgba(255,255,255,.14);opacity:0;
  fill:none;stroke:currentColor;stroke-width:.95;
  stroke-linecap:round;stroke-linejoin:round;
  transition:opacity .2s var(--ease);
}
/* every drawable shape traces itself (linear = constant pen speed) */
.cs-ghost-swap .g-icon > *{
  stroke-dasharray:1.02;stroke-dashoffset:1.02;
  transition:stroke-dashoffset .7s linear .06s;
}
.cs-cell:hover .cs-ghost-swap .g-num{opacity:0}
.cs-cell:hover .cs-ghost-swap .g-icon{opacity:1;color:rgba(42,196,244,.5)}
.cs-cell:hover .cs-ghost-swap .g-icon > *{stroke-dashoffset:0}
@media (prefers-reduced-motion:reduce){
  .cs-ghost-swap .g-icon > *{stroke-dasharray:none;stroke-dashoffset:0;transition:none}
}
.cs-cell h3{
  font-family:var(--font-main);font-size:1.14rem;font-weight:600;
  letter-spacing:-.01em;color:#fff;margin-bottom:9px;
  padding-right:60px;
}
.cs-cell p{font-size:.94rem;color:rgba(255,255,255,.72);line-height:1.62}
.cs-arrow{
  position:absolute;right:20px;bottom:18px;
  width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  color:var(--brand);border:1px solid rgba(42,196,244,.4);
  opacity:0;transform:translateX(-6px);
  transition:opacity .3s var(--ease),transform .3s var(--ease);
}
.cs-cell:hover .cs-arrow{opacity:1;transform:none}
.cs-cta{text-align:center;margin-top:clamp(36px,4vw,52px)}
@media (max-width:900px){.cs-grid{grid-template-columns:1fr 1fr}}
@media (max-width:560px){.cs-grid{grid-template-columns:minmax(0,1fr)}}

/* ============================================================
   BOOK A MEETING
   ============================================================ */
.booking{
  background:
    radial-gradient(90% 60% at 85% 10%, rgba(42,196,244,.1) 0%, transparent 55%),
    linear-gradient(180deg,#eef7fb 0%,var(--paper) 70%);
  padding:var(--sec-y) var(--sec-x);
  border-top:1px solid var(--line-soft);
}
.bk-inner{
  max-width:var(--wrap);margin:0 auto;
  display:grid;grid-template-columns:1fr 1.05fr;gap:clamp(40px,6vw,88px);
  align-items:start;
}
.bk-eyebrow{
  display:flex;align-items:center;gap:12px;
  font-family:var(--font-label);font-size:.76rem;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--brand-deep);
}
.bk-eyebrow::before{content:"";height:1.5px;width:34px;border-radius:2px;
  background:linear-gradient(90deg,transparent,currentColor)}
.bk-eyebrow::after{content:"";height:1.5px;width:34px;border-radius:2px;
  background:linear-gradient(90deg,currentColor,transparent)}
.bk-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(1.9rem,3.3vw,2.7rem);line-height:1.12;letter-spacing:-.02em;
  color:var(--ink);margin-top:16px;
}
.bk-title .accent{color:var(--brand-deep)}
.bk-sub{font-size:1.05rem;color:var(--ink-soft);line-height:1.66;margin-top:16px;max-width:30em}
.bk-contact{list-style:none;margin-top:30px;display:grid;gap:16px}
.bk-contact li{
  display:flex;align-items:center;gap:13px;
  font-size:.99rem;color:var(--ink);
}
.bk-contact a{color:var(--brand-deep);font-weight:500}
.bk-contact a:hover{text-decoration:underline}
.bk-ic{
  width:38px;height:38px;flex:none;border-radius:11px;display:grid;place-items:center;
  background:rgba(42,196,244,.1);color:var(--brand-deep);
  border:1px solid rgba(42,196,244,.25);
}

.bk-progress{
  display:flex;gap:8px;margin-bottom:20px;
}
.bkp{
  flex:1;display:flex;align-items:center;justify-content:center;gap:7px;
  font-family:var(--font-label);font-size:.74rem;font-weight:600;color:var(--ink-faint);
  padding:8px 4px;border-radius:100px;background:var(--paper);
  border:1px solid var(--line-soft);white-space:nowrap;
  transition:background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease);
}
.bkp i{
  font-style:normal;width:18px;height:18px;border-radius:50%;
  display:grid;place-items:center;font-size:.68rem;
  background:rgba(18,35,47,.08);color:var(--ink-soft);
  transition:background .3s var(--ease),color .3s var(--ease);
}
.bkp.active{color:var(--brand-deep);border-color:rgba(42,196,244,.4);background:var(--sky-100)}
.bkp.active i{background:var(--brand-deep);color:#fff}
.bkp.done{color:var(--brand-deep);border-color:rgba(44,171,226,.35)}
.bkp.done i{background:var(--brand-deep);color:#fff}

.bk-contact li{
  background:#fff;border:1px solid var(--line-soft);border-radius:16px;
  padding:12px 16px 12px 12px;
  box-shadow:0 8px 24px -18px rgba(18,54,74,.35);
  transition:transform .3s var(--ease),box-shadow .3s var(--ease),border-color .3s var(--ease);
}
.bk-contact li:hover{
  transform:translateX(4px);border-color:rgba(42,196,244,.35);
  box-shadow:0 14px 30px -18px rgba(18,54,74,.45);
}

.bk-card{
  background:#fff;border:1px solid var(--line-soft);border-radius:24px;
  box-shadow:0 30px 70px -30px rgba(18,54,74,.35);
  padding:clamp(20px,2vw,28px);margin-top:50px;   /* nudge down to center with the info column */
  opacity:0;translate:0 22px;transition:opacity .7s var(--ease) .15s,translate .7s var(--ease) .15s;
}
.booking.in .bk-card{opacity:1;translate:0}

.bk-cal-head{
  display:flex;align-items:center;justify-content:space-between;
  font-family:var(--font-main);font-weight:600;font-size:1.05rem;color:var(--ink);
  margin-bottom:14px;
}
.bk-nav{
  width:36px;height:36px;border-radius:10px;border:1px solid var(--line);
  background:#fff;cursor:pointer;font-size:1.2rem;line-height:1;color:var(--ink);
  transition:border-color .25s var(--ease),background .25s var(--ease);
}
.bk-nav:hover:not(:disabled){border-color:var(--brand);background:var(--sky-100)}
.bk-nav:disabled{opacity:.35;cursor:default}
.bk-dow{
  display:grid;grid-template-columns:repeat(7,1fr);gap:4px;margin-bottom:4px;
  font-family:var(--font-label);font-size:.7rem;font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink-faint);text-align:center;
}
.bk-days{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}
.bk-day{
  aspect-ratio:1;border:none;border-radius:10px;background:none;cursor:pointer;
  font-family:var(--font-main);font-size:.92rem;font-weight:500;color:var(--ink);
  transition:background .2s var(--ease),color .2s var(--ease),box-shadow .2s var(--ease);
}
.bk-day:hover:not(:disabled):not(.empty){background:var(--sky-100)}
.bk-day.sel{
  background:linear-gradient(135deg,var(--brand-mid),var(--blue-800));color:#fff;font-weight:600;
  box-shadow:0 8px 18px -8px rgba(23,120,159,.7);
}
.bk-day:disabled{color:rgba(64,64,65,.24);cursor:default}
.bk-day.empty{cursor:default}

/* step 2: calendar on the left, times expand on the right.
   ⚠️ This used to be .bk-step-1. The steps were reordered (details first, then
   the date) because Calendly's free plan cannot create the booking, so the
   enquiry has to be captured before the hand-off. The flex now lives on its own
   wrapper so the picked-time line and the buttons stay full width beneath it. */
.bk-pick{display:flex;gap:22px;align-items:flex-start}
.bk-cal{flex:1 1 auto;min-width:0}
.bk-times{flex:0 0 178px;min-width:0;border-left:1px solid var(--line-soft);padding-left:16px}
@media (max-width:600px){
  /* align-items:flex-start on the base rule is a CROSS-axis rule; once the
     direction flips to column it stops meaning "top" and starts meaning
     "shrink to content width", which left the slots at 178px on a phone. */
  .bk-pick{flex-direction:column;align-items:stretch}
  .bk-times{flex:1 1 auto;border-left:none;border-top:1px solid var(--line-soft);padding-left:0;padding-top:12px;margin-top:0}
}
/* Two fixed columns, not auto-fit. auto-fit made the count a function of
   leftover card width — 4 across at 900, 2 at 1440, but ONE at 1180-1280, where
   nine slots became a tall strip that dragged the card hundreds of px below the
   calendar. Two columns is always 5 short rows, so the card keeps the
   calendar's height at every width. .bk-times is a fixed basis for the same
   reason: the slot area must not be whatever happens to be left over. */
.bk-slots{display:grid;grid-template-columns:repeat(2,1fr);gap:7px}
.bk-slot{
  padding:9px 4px;border-radius:10px;border:1px solid var(--line);
  background:#fff;cursor:pointer;white-space:nowrap;
  font-family:var(--font-main);font-size:.85rem;font-weight:500;color:var(--brand-deep);
  transition:border-color .2s var(--ease),background .2s var(--ease),transform .2s var(--ease);
}
.bk-slot:hover{border-color:var(--brand);background:var(--sky-100);transform:translateY(-1px)}
.bk-slot.sel{
  border-color:var(--brand);color:#fff;font-weight:600;
  background:linear-gradient(135deg,var(--brand-mid),var(--blue-800));
  box-shadow:0 8px 18px -8px rgba(23,120,159,.7);
}
/* the picked-time box only exists once a time is picked */
.bk-picked:empty{display:none}
.bk-load{text-align:center;margin-top:14px}
/* step 1 has a single Next button: keep it on the right, not floated left by
   the space-between that the two-button steps need */
.bk-step-1 .bk-actions{justify-content:flex-end}

.bk-picked{
  font-size:.97rem;color:var(--ink);
  background:var(--sky-100);border:1px solid rgba(42,196,244,.3);
  border-radius:12px;padding:12px 16px;margin-bottom:20px;
}
.bk-field{display:block;margin-bottom:16px}
/* first + last side by side so splitting the name costs no extra height;
   stacks on narrow cards (the widget also runs inside the booking modal) */
.bk-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 14px}
@media (max-width:420px){.bk-row{grid-template-columns:minmax(0,1fr)}}
.bk-field span{
  display:block;font-family:var(--font-label);font-size:.82rem;font-weight:600;
  color:var(--ink);margin-bottom:7px;
}
.bk-field input{
  width:100%;padding:13px 15px;border-radius:12px;border:1px solid var(--line);
  font-family:var(--font-main);font-size:.97rem;color:var(--ink);
  outline:none;transition:border-color .25s var(--ease),box-shadow .25s var(--ease);
  background:var(--paper);
}
.bk-field input:focus{border-color:var(--brand);box-shadow:0 0 0 3px rgba(42,196,244,.18)}
.bk-actions{display:flex;justify-content:space-between;gap:12px;margin-top:22px}
.bk-actions .btn:disabled{opacity:.45;cursor:default;transform:none;box-shadow:none}

.bk-success{text-align:center;padding:26px 8px}
.bk-check{
  width:58px;height:58px;margin:0 auto 18px;border-radius:50%;
  display:grid;place-items:center;color:var(--ink);
  background:var(--brand-green);
  box-shadow:0 14px 30px -10px rgba(185,213,49,.5);
}
.bk-success h3{
  font-family:var(--font-main);font-size:1.4rem;font-weight:600;color:var(--ink);
  margin-bottom:10px;
}
.bk-success p{font-size:1rem;color:var(--ink-soft);line-height:1.6}
.bk-note{font-size:.85rem;margin-top:10px;color:var(--ink-faint)}
@media (max-width:900px){.bk-inner{grid-template-columns:minmax(0,1fr)}}


/* glass button (for dark sections) */
.btn-glass{
  color:#fff;background:rgba(255,255,255,.08);
  border-color:rgba(255,255,255,.3);backdrop-filter:blur(8px);
}
.btn-glass:hover{border-color:var(--brand-sky);background:rgba(44,171,226,.16)}

/* ============================================================
   PRE-FOOTER CTA (field bookend)
   ============================================================ */
.prefoot{
  position:relative;overflow:hidden;isolation:isolate;
  padding:clamp(140px,14vw,210px) clamp(20px,5vw,44px);   /* ~100px taller */
  text-align:center;color:#fff;
  --pf-par:0px;                             /* set by scroll JS */
}
.prefoot-bg{
  position:absolute;left:0;right:0;top:-20%;z-index:-2;
  width:100%;height:140%;object-fit:cover;object-position:center 42%;
  transform:translate3d(0,var(--pf-par),0);   /* scroll parallax */
  will-change:transform;
}
@media (prefers-reduced-motion:reduce){
  .prefoot-bg{top:0;height:100%;transform:none}
}
/* soft 15% white wash — keeps the sky bright and airy */
/* soft centred scrim: only darkens behind the headline so the sun, clouds and
   racks stay bright at the edges (white text hits 1:1 on the cloud otherwise) */
.prefoot-scrim{
  position:absolute;inset:0;z-index:-1;
  background:radial-gradient(78% 62% at 50% 52%,
    rgba(6,22,38,.55) 0%, rgba(6,22,38,.34) 46%, rgba(6,22,38,0) 80%);
}
.pf-eyebrow{
  display:flex;align-items:center;justify-content:center;gap:12px;
  font-family:var(--font-label);font-size:.78rem;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;color:#fff;
}
.pf-eyebrow::before,.pf-eyebrow::after{content:"";height:1.5px;width:34px;border-radius:2px}
.pf-eyebrow::before{background:linear-gradient(90deg,transparent,currentColor)}
.pf-eyebrow::after{background:linear-gradient(90deg,currentColor,transparent)}
.pf-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(2rem,4vw,3.2rem);line-height:1.1;letter-spacing:-.02em;
  margin-top:16px;text-shadow:0 2px 30px rgba(0,0,0,.45);
}
.pf-title .accent{color:#fff}
.pf-cta{display:flex;gap:14px;justify-content:center;margin-top:34px;flex-wrap:wrap}

/* ============================================================
   FOOTER
   ============================================================ */
/* opens on the brand Dk Grey and settles one step deeper, so the footer has
   some depth without being flat — and without being navy */
.footer{background:linear-gradient(180deg,var(--grey-700) 0%,var(--grey-800) 100%);
  color:rgba(255,255,255,.82)}
.ft-inner{
  max-width:var(--wrap);margin:0 auto;
  padding:clamp(56px,7vw,88px) clamp(20px,5vw,44px) clamp(40px,5vw,56px);
  display:grid;grid-template-columns:1.45fr 1fr 1fr 1fr 1.25fr;gap:clamp(28px,3.2vw,46px);
}
.ft-logo{height:44px;width:auto;filter:brightness(0) invert(1);opacity:.95}
.ft-brand p{
  margin-top:18px;font-size:.95rem;line-height:1.66;color:rgba(255,255,255,.6);max-width:30em;
}
.ft-head{
  font-family:var(--font-label);font-size:.76rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--brand);
  margin-bottom:16px;
}
.ft-col{display:flex;flex-direction:column;gap:11px;align-items:flex-start}
.ft-col a{
  font-size:.95rem;color:rgba(255,255,255,.75);line-height:1.5;
  transition:color .25s var(--ease);
}
.ft-col a:hover{color:var(--brand)}
.ft-loc{display:block}
.ft-loc-tag{
  display:block;
  font-family:var(--font-label);font-size:.68rem;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--brand);
  margin-bottom:3px;
}
.ft-bottom{
  border-top:1px solid rgba(255,255,255,.1);
  max-width:var(--wrap);margin:0 auto;
  padding:22px clamp(20px,5vw,44px);
  display:flex;align-items:center;justify-content:space-between;gap:18px;flex-wrap:wrap;
  font-size:.85rem;color:rgba(255,255,255,.5);
}
.ft-legal{list-style:none;display:flex;gap:20px}
.ft-legal a{color:rgba(255,255,255,.5);transition:color .25s var(--ease)}
.ft-legal a:hover{color:var(--brand)}
.ft-credit a{color:rgba(255,255,255,.65);font-weight:500;transition:color .25s var(--ease)}
.ft-credit a:hover{color:var(--brand)}
@media (max-width:980px){
  .ft-inner{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ft-brand{grid-column:1/-1}
}
@media (max-width:560px){
  .ft-inner{grid-template-columns:minmax(0,1fr)}
  .ft-bottom{flex-direction:column;align-items:flex-start;gap:10px}
}

/* ============================================================
   AI SITE SEARCH  — magnifier toggle + frosted "Bright Field" bubble
   ============================================================ */
.nav-cluster{display:flex;align-items:center;gap:20px}
.ai-search{position:relative;display:flex;top:-3px}   /* nudge icon to optically center with nav text */
.ai-search [hidden]{display:none !important}   /* hidden attr must beat flex/grid */

.ai-toggle{
  width:30px;height:30px;padding:0;border:0;background:transparent;
  display:grid;place-items:center;cursor:pointer;
}
.ai-ic{
  width:18px;height:18px;display:block;
  background:var(--ink-soft);                 /* match nav link color */
  -webkit-mask:url("images/ai-search.png") center/contain no-repeat;
          mask:url("images/ai-search.png") center/contain no-repeat;
  transition:background .25s var(--ease);
}
.ai-toggle:hover .ai-ic{background:var(--ink)}      /* just darkens on hover, no animation */
.ai-search.open .ai-ic{background:linear-gradient(140deg,var(--brand),var(--brand-deep))}

/* ---- the bubble ---- */
.ai-bubble{
  position:absolute;top:calc(100% + 16px);right:0;width:392px;
  max-width:calc(100vw - 32px);
  background:#fff;
  border:1px solid var(--line-soft);border-radius:22px;
  box-shadow:0 30px 70px -28px rgba(11,95,132,.42), var(--shadow-sm);
  padding:20px 20px 14px;z-index:130;
  transform-origin:top right;
  opacity:0;transform:translateY(-10px) scale(.96);pointer-events:none;
  transition:opacity .3s var(--ease),transform .34s var(--ease);
}
.ai-bubble::before{
  content:"";position:absolute;top:-7px;right:15px;width:14px;height:14px;
  background:#fff;
  border-left:1px solid var(--line-soft);border-top:1px solid var(--line-soft);
  transform:rotate(45deg);border-radius:3px 0 0 0;
}
.ai-search.open .ai-bubble{opacity:1;transform:none;pointer-events:auto}

/* ---- head ---- */
.ai-head{margin-bottom:14px}
.ai-badge{
  display:inline-flex;align-items:center;gap:6px;
  font-family:var(--font-label);font-size:.7rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--brand-deep);
}
.ai-spark{fill:var(--brand);filter:drop-shadow(0 1px 3px rgba(42,196,244,.5));animation:aiTwinkle 3.4s var(--ease) infinite}
@keyframes aiTwinkle{0%,100%{opacity:1;transform:scale(1) rotate(0)}50%{opacity:.65;transform:scale(.82) rotate(18deg)}}
.ai-head-sub{margin-top:6px;font-size:.82rem;line-height:1.45;color:var(--ink-soft)}

/* ---- input ---- */
.ai-form{position:relative;margin-bottom:12px}
.ai-in-ic{
  position:absolute;left:14px;top:50%;transform:translateY(-50%);
  width:18px;height:18px;pointer-events:none;
  background:linear-gradient(140deg,var(--brand-mid),var(--brand-deep));
  -webkit-mask:url("images/ai-search.png") center/contain no-repeat;
          mask:url("images/ai-search.png") center/contain no-repeat;
}
.ai-input{
  width:100%;padding:13px 50px 13px 42px;
  border:1.5px solid var(--line);border-radius:14px;background:var(--white);
  font-family:var(--font-main);font-size:.92rem;color:var(--ink);
  transition:border-color .25s var(--ease),box-shadow .25s var(--ease);
}
.ai-input::placeholder{color:var(--ink-faint)}
.ai-input:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 4px rgba(42,196,244,.14)}
.ai-send{
  position:absolute;right:6px;top:50%;transform:translateY(-50%);
  width:34px;height:34px;border:none;border-radius:10px;cursor:pointer;
  display:grid;place-items:center;color:#fff;
  background:var(--brand-sky);
  box-shadow:none;
  transition:transform .25s var(--ease),box-shadow .25s var(--ease),opacity .2s;
}
.ai-send:hover{transform:translateY(-50%) scale(1.06)}
.ai-send:active{transform:translateY(-50%) scale(.94)}

/* ---- suggestion chips ---- */
.ai-chips{display:flex;flex-wrap:wrap;gap:8px}
.ai-chip{
  font-family:var(--font-main);font-size:.78rem;font-weight:500;
  padding:7px 12px;border-radius:100px;cursor:pointer;text-align:left;
  border:1px solid var(--line);background:rgba(42,196,244,.05);color:var(--ink-soft);
  transition:background .25s var(--ease),color .25s var(--ease),border-color .25s var(--ease),transform .2s var(--ease);
  opacity:0;transform:translateY(6px);
}
.ai-search.open .ai-chip{animation:aiChipIn .5s var(--ease) forwards}
.ai-search.open .ai-chip:nth-child(1){animation-delay:.14s}
.ai-search.open .ai-chip:nth-child(2){animation-delay:.2s}
.ai-search.open .ai-chip:nth-child(3){animation-delay:.26s}
.ai-search.open .ai-chip:nth-child(4){animation-delay:.32s}
@keyframes aiChipIn{to{opacity:1;transform:none}}
.ai-chip:hover{background:var(--brand);border-color:var(--brand);color:#fff;transform:translateY(-1px)}

/* ---- loading ---- */
.ai-loading{display:flex;gap:6px;align-items:center;padding:14px 2px 6px}
.ai-dot{width:8px;height:8px;border-radius:50%;background:var(--brand);animation:aiBounce 1.1s var(--ease) infinite}
.ai-dot:nth-child(2){animation-delay:.16s}
.ai-dot:nth-child(3){animation-delay:.32s}
@keyframes aiBounce{0%,80%,100%{transform:scale(.5);opacity:.4}40%{transform:scale(1);opacity:1}}

/* ---- result ---- */
.ai-result{padding-top:4px;animation:aiFade .4s var(--ease)}
@keyframes aiFade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.ai-answer{font-size:.9rem;line-height:1.6;color:var(--ink)}
.ai-actions{display:flex;flex-wrap:wrap;gap:9px;margin-top:14px}
.ai-link{
  display:inline-flex;align-items:center;gap:6px;
  font-size:.82rem;font-weight:600;color:var(--brand-deep);
  padding:8px 13px;border-radius:100px;
  border:1px solid rgba(42,196,244,.35);background:rgba(42,196,244,.08);
  transition:background .25s var(--ease),transform .2s var(--ease);
}
.ai-link:hover{background:rgba(42,196,244,.16);transform:translateY(-1px)}
.ai-link svg{transition:transform .3s var(--ease)}
.ai-link:hover svg{transform:translateX(3px)}
.ai-book{
  display:inline-flex;align-items:center;gap:7px;
  font-size:.82rem;font-weight:600;color:var(--ink);
  padding:8px 15px;border-radius:100px;
  background:var(--brand-green);          /* client brand green (was non-brand #4e9e63) */
  box-shadow:0 8px 18px -8px rgba(185,213,49,.55);
  transition:transform .2s var(--ease),box-shadow .25s var(--ease);
}
.ai-book:hover{transform:translateY(-1px);box-shadow:0 10px 22px -8px rgba(185,213,49,.7)}

/* ---- footer ---- */
.ai-foot{margin-top:14px;padding-top:11px;border-top:1px solid var(--line-soft);
  font-size:.68rem;color:var(--ink-faint);text-align:center}

/* ---- responsive: full-width sheet under the header ---- */
@media (max-width:980px){
  .ai-bubble{
    position:fixed;top:70px;left:16px;right:16px;width:auto;max-width:none;
    transform-origin:top center;
  }
  .ai-bubble::before{right:auto;left:calc(100% - 84px)}
  .site-header.scrolled .ai-bubble{top:62px}
}

/* ============ BOOKING MODAL ============ */
.bkm-overlay{
  position:fixed;inset:0;z-index:200;
  display:flex;align-items:flex-start;justify-content:center;
  padding:clamp(16px,5vh,64px) 16px;
  background:rgba(6,18,30,.55);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  opacity:0;transition:opacity .26s var(--ease);
  overflow-y:auto;
}
.bkm-overlay.open{opacity:1}
.bkm-overlay[hidden]{display:none}
.bkm-dialog{
  position:relative;width:min(940px,100%);margin:auto;
  background:var(--paper);border-radius:26px;
  border:1px solid rgba(42,196,244,.18);
  box-shadow:0 50px 120px -40px rgba(6,24,38,.6);
  padding:clamp(26px,3.4vw,46px) clamp(22px,3.4vw,46px) clamp(22px,3vw,36px);
  transform:translateY(18px) scale(.985);
  transition:transform .3s cubic-bezier(.16,.8,.24,1);
}
.bkm-overlay.open .bkm-dialog{transform:none}
@media (prefers-reduced-motion:reduce){
  .bkm-overlay,.bkm-dialog{transition:none}
  .bkm-dialog{transform:none}
}
.bkm-close{
  position:absolute;top:14px;right:14px;width:38px;height:38px;border-radius:50%;
  border:1px solid var(--line-soft);background:#fff;color:var(--ink-soft);
  font-size:1.5rem;line-height:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  transition:background .2s var(--ease),color .2s var(--ease),border-color .2s var(--ease);
}
.bkm-close:hover{background:var(--ink);color:#fff;border-color:var(--ink)}
.bkm-close:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.bkm-head{text-align:center;max-width:560px;margin:0 auto clamp(20px,2.4vw,28px)}
.bkm-head .bk-eyebrow{justify-content:center}
.bkm-title{
  font-family:var(--font-main);font-weight:600;
  font-size:clamp(1.5rem,2.6vw,2.1rem);line-height:1.12;letter-spacing:-.02em;
  color:var(--ink);margin-top:10px;
}
.bkm-title .accent{color:var(--brand-deep)}
.bkm-sub{color:var(--ink-soft);font-size:.98rem;line-height:1.55;margin-top:10px}

/* the live widget, once moved into the modal, must show immediately (no scroll-reveal here) */
.bkm-cardslot .bk-card{
  opacity:1;translate:none;margin-top:0;
  box-shadow:none;border:1px solid var(--line-soft);
  transition:none;
}

.bkm-contact{
  display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:center;
  margin-top:clamp(20px,2.6vw,28px);padding-top:clamp(18px,2.4vw,24px);
  border-top:1px solid var(--line-soft);
}
.bkm-contact-lead{
  font-family:var(--font-label);font-size:.88rem;font-weight:600;color:var(--ink-soft);
  width:100%;text-align:center;margin-bottom:2px;
}
.bkm-cc{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--font-label);font-weight:600;font-size:.92rem;
  color:var(--ink);text-decoration:none;
  padding:10px 17px;border-radius:100px;
  border:1px solid var(--line-soft);background:#fff;
  transition:border-color .2s var(--ease),color .2s var(--ease),background .2s var(--ease);
}
.bkm-cc svg{color:var(--brand-deep);flex:none}
.bkm-cc:hover{border-color:var(--brand);color:var(--brand-deep);background:rgba(42,196,244,.06)}
.bkm-cc:hover svg{color:var(--brand-deep)}

/* ============ MEGA MENU ============ */
.site-header{--mega-top:100%}
.mega{
  position:absolute;top:var(--mega-top);left:50%;
  transform:translateX(-50%) translateY(10px);
  width:min(1060px,calc(100vw - 32px));
  margin-top:9px;
  background:rgba(255,255,255,.98);
  -webkit-backdrop-filter:blur(22px) saturate(160%);backdrop-filter:blur(22px) saturate(160%);
  border:1px solid var(--line);border-radius:22px;
  box-shadow:0 44px 90px -42px rgba(16,44,64,.55),0 6px 18px -14px rgba(16,44,64,.3);
  padding:24px;
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .24s var(--ease),transform .3s cubic-bezier(.16,.8,.24,1),visibility .24s;
  z-index:90;
}
/* invisible hover-bridge across the gap between the trigger and the panel */
.mega::before{content:"";position:absolute;left:0;right:0;top:-20px;height:22px}
.nav-item.open .mega,
.nav-item.has-mega:focus-within .mega{
  opacity:1;visibility:visible;pointer-events:auto;
  transform:translateX(-50%) translateY(0);
}
@media (prefers-reduced-motion:reduce){.mega{transition:opacity .18s linear,visibility .18s}}

.mega-inner{display:grid;grid-template-columns:1.62fr .95fr;gap:24px;align-items:stretch}
.mega-links{display:grid;grid-template-columns:1fr 1fr;gap:3px 6px;align-content:start}

.mega-link{display:flex;align-items:center;gap:13px;padding:10px 12px;border-radius:14px;
  transition:background .2s var(--ease)}
.mega-link:hover{background:linear-gradient(120deg,rgba(42,196,244,.10),rgba(42,196,244,.03))}
.mega-ic{flex:none;width:38px;height:38px;border-radius:11px;display:grid;place-items:center;
  background:linear-gradient(150deg,#e9f7fe,#f4fbff);border:1px solid rgba(42,196,244,.22);
  color:var(--brand-deep);
  transition:background .22s var(--ease),border-color .22s var(--ease),color .22s var(--ease),transform .22s var(--ease)}
.mega-ic svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
/* The client's own icon set is outline art with ONE solid accent shape (the gear,
   the lock, the badge). The industries icons follow that pattern.
   NOTE: the .ic-solid paths also carry fill/stroke as presentation ATTRIBUTES,
   and that is what actually paints them — these symbols are drawn through <use>,
   and a CSS class cannot cross into the cloned shadow tree. This rule only covers
   the case where a symbol is inlined directly. Do not delete the attributes. */
.ic-solid{fill:currentColor;stroke:none}
.mega-link:hover .mega-ic{background:linear-gradient(150deg,var(--brand),var(--brand-deep));
  border-color:transparent;color:#fff;transform:translateY(-1px)}
.mega-tx{display:flex;flex-direction:column;line-height:1.2;min-width:0}
.mega-tx b{font-family:var(--font-main);font-weight:600;font-size:.92rem;color:var(--ink);letter-spacing:-.005em}
.mega-tx i{font-style:normal;font-size:.76rem;color:var(--ink-soft);margin-top:2px}

.mega-feature{border-radius:18px;padding:22px 22px 20px;display:flex;flex-direction:column;color:#fff;
  background:
    radial-gradient(130% 90% at 100% 0%,rgba(42,196,244,.20),transparent 62%),
    linear-gradient(158deg,var(--grey-900) 0%,var(--grey-700) 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06)}
.mega-eyebrow{font-family:var(--font-label);font-size:.66rem;font-weight:600;letter-spacing:.17em;
  text-transform:uppercase;color:var(--brand)}
.mega-ftitle{font-family:var(--font-main);font-weight:600;font-size:1.16rem;line-height:1.16;
  letter-spacing:-.01em;margin-top:9px}
.mega-points{list-style:none;margin-top:15px;display:grid;gap:9px}
.mega-points li{position:relative;padding-left:23px;font-size:.85rem;color:rgba(255,255,255,.85)}
.mega-points li::before{content:"";position:absolute;left:5px;top:.18em;width:6px;height:10px;
  border:solid var(--brand);border-width:0 2px 2px 0;transform:rotate(43deg)}
.mega-cta{margin-top:auto;padding-top:18px;display:inline-flex;align-items:center;gap:7px;
  font-family:var(--font-label);font-weight:600;font-size:.9rem;color:var(--brand);
  transition:gap .25s var(--ease),color .2s var(--ease)}
.mega-cta:hover{gap:11px;color:#fff}
.mega-cta svg{transition:transform .25s var(--ease)}

@media (max-width:1080px){
  .mega{width:min(760px,calc(100vw - 24px))}
  .mega-inner{grid-template-columns:minmax(0,1fr)}
  .mega-4 .mega-links,.mega-5 .mega-links,.mega-links{grid-template-columns:1fr 1fr}
}

/* ============================================================
   BRAND-BLUE ACCENTS  (client palette #2cabe2 — no navy)
   Display accents on LIGHT backgrounds use a gradient that starts at the
   client's exact brand blue and settles into the same-hue deeper tone, so the
   colour reads as theirs while keeping large type legible on white.
   ============================================================ */
.hero-title .accent,
.proof-title .accent,
.sol-title .accent,
.x-title .accent,
.bk-title .accent,
.bkm-title .accent{
  color:var(--brand-sky);
}
/* bento card stat numbers — client's light blue */
.b-num,
.b-peace .b-bignum{color:var(--brand-sky)}
/* on DARK sections the brand blue has plenty of contrast — use it flat */
.loc-title .accent,
.glove-title .accent,
.cs-title .accent{color:var(--brand-sky)}

/* ---- readability on the new blue field ----
   Brand cyan sits at only ~3:1 on the deep blue, so accent text steps up to a
   lighter tint of the same hue (small labels need 4.5:1, display text 3:1). */
.glove-eyebrow,
.loc-eyebrow{color:#a5e4fb}
.glove-title .accent{color:#7fd6f7}
.gs-num{color:#7fd6f7}
.glove-stats li{background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.2)}
.glove-intro{color:rgba(255,255,255,.9)}
.gs-label{color:rgba(255,255,255,.88)}
/* Cloud Services accents — same contrast lift as the other blue sections */
.cs-eyebrow{color:#a5e4fb}
.cs-title .accent{color:#7fd6f7}
.cs-intro{color:rgba(255,255,255,.88)}
.cs-cell{background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.2)}
.cs-arrow{color:#a5e4fb;border-color:rgba(165,228,251,.5)}
.cs-ghost{-webkit-text-stroke-color:rgba(255,255,255,.2)}

/* ============================================================
   TYPE ON THE FULL BRAND-BLUE FIELD
   White drops to 2.6:1 on #2cabe2, so copy sitting directly on the blue
   switches to dark ink (5.9:1). Cards stay dark glass so their white
   type keeps working — same treatment as the locations card.
   ============================================================ */

.loc-eyebrow,.glove-eyebrow,.cs-eyebrow{color:#083a4f}
.loc-title,.glove-title,.cs-title{color:var(--ink-on-blue)}
.loc-intro,.glove-intro,.cs-intro{color:var(--ink-on-blue)}
.loc-title .accent,.glove-title .accent,.cs-title .accent{color:#fff}

/* cards + tiles on the blue */
.glove-stats li,.cs-cell{background:rgba(8,40,56,.52);border-color:rgba(255,255,255,.2)}
.glove-stats li:hover{border-color:rgba(255,255,255,.4);background:rgba(8,40,56,.62)}
.gs-num{color:#7fd6f7}
.gs-label,.cs-cell p{color:rgba(255,255,255,.88)}
.cs-ghost{-webkit-text-stroke-color:rgba(255,255,255,.22)}
.cs-arrow{color:#fff;border-color:rgba(255,255,255,.45)}

/* primary CTA must not vanish into the blue */
.glove .btn-primary,.cs-cta .btn-primary{background:var(--ink);color:#fff}
.glove .btn-primary:hover,.cs-cta .btn-primary:hover{background:#2a2a2b}

/* the old cyan glows just muddy a bright blue field */
.glove-glow,.cs-glow{opacity:.18}

/* ---- White Glove keeps its original dark field (overrides the blue-field type) ---- */
/* brand Dk Grey, deepest at the top so the seam under the blue Colocation
   band still reads as a cut, resolving down onto #404041 itself */
.glove{background:linear-gradient(180deg,var(--grey-900) 0%,var(--grey-800) 60%,var(--grey-700) 100%)}
.glove-eyebrow{color:#a5e4fb}
.glove-title{color:#fff}
.glove-title .accent{color:#7fd6f7}
.glove-intro{color:rgba(255,255,255,.9)}
.glove-stats li{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.15)}
.glove-stats li:hover{background:rgba(42,196,244,.09);border-color:rgba(42,196,244,.45)}
.gs-label{color:rgba(255,255,255,.85)}
.glove .btn-primary{background:var(--brand-sky);color:#fff}
.glove .btn-primary:hover{background:var(--brand-deep)}
.glove-glow{opacity:.5}

/* ---- Cloud Services keeps its original dark field (overrides the blue-field type) ---- */
/* mirrors White Glove — starts on #404041, deepens downward */
.cloudsvc,.bg-slate{background:linear-gradient(180deg,var(--grey-700) 0%,var(--grey-800) 55%,var(--grey-900) 100%)}
.cs-eyebrow{color:#a5e4fb}
.cs-title{color:#fff}
.cs-title .accent{color:#7fd6f7}
.cs-intro{color:rgba(255,255,255,.78)}
.cs-cell{background:rgba(255,255,255,.055);border-color:rgba(255,255,255,.12)}
.cs-cell:hover{border-color:rgba(42,196,244,.45);background:rgba(42,196,244,.08)}
.cs-cell p{color:rgba(255,255,255,.75)}
.cs-arrow{color:var(--brand-sky);border-color:rgba(42,196,244,.4)}
.cs-cta .btn-primary{background:var(--brand-sky);color:#fff}
.cs-cta .btn-primary:hover{background:var(--brand-deep)}
.cs-glow{opacity:.5}

/* numerals out — the icon is the mark now: muted at rest, brand blue on hover */
.cs-ghost .g-num{display:none}
/* two stacked copies: a static muted mark, and a brand-blue line that traces
   itself over it on hover (same motion as the Why Opus icons) */
.cs-ghost-swap .g-icon{
  grid-area:1/1;opacity:1;width:60px;
  transition:transform .4s var(--ease);
}
.cs-ghost-swap .g-base{color:rgba(255,255,255,.19)}
/* the base copy must stay solid — the inherited .g-icon>* dash rule would hide it */
.cs-ghost-swap .g-base > *{stroke-dasharray:none;stroke-dashoffset:0;transition:none}
.cs-ghost-swap .g-draw{color:var(--brand-sky)}
.cs-ghost-swap .g-draw > *{
  stroke-dasharray:1.02;stroke-dashoffset:1.02;
  transition:stroke-dashoffset .75s linear .05s;
}
.cs-cell:hover .cs-ghost-swap .g-draw > *{stroke-dashoffset:0}
.cs-cell:hover .cs-ghost-swap .g-icon{transform:scale(1.06)}
/* keep the two layers distinct on hover (an older rule tints both) */
.cs-cell:hover .cs-ghost-swap .g-base{color:rgba(255,255,255,.19)}
.cs-cell:hover .cs-ghost-swap .g-draw{color:var(--brand-sky)}
@media (prefers-reduced-motion:reduce){
  .cs-ghost-swap .g-draw > *{stroke-dasharray:none;stroke-dashoffset:0;transition:none}
}

/* ---- Client-supplied icon set: line art + a filled object that animates ----
   Per the 2026 brand guidelines, Opus icons mix filled shapes with line art and
   the FILLED portion is what moves. Here the cloud is the line, the two arrows
   are the fill, and they separate on hover. */
.adv-ic-brand svg{grid-area:1/1;width:100%;height:100%;overflow:visible}
.adv-ic-brand .ic-line{
  fill:none;stroke:rgba(18,35,47,.16);stroke-width:2;stroke-miterlimit:10;
  transition:stroke .4s var(--ease);
}
/* `fill` is an inherited SVG property, so setting it on .ic-fill covers both a
   <g> of polygons (icon 1) and a bare <path> (icon 2) */
.adv-ic-brand .ic-fill{fill:rgba(18,35,47,.16);transition:fill .4s var(--ease)}
.adv-ic-brand .ic-up,.adv-ic-brand .ic-down{
  transition:translate .55s cubic-bezier(.34,1.25,.5,1);
}
.bento-cell:hover .adv-ic-brand .ic-line{stroke:var(--brand-sky)}
.bento-cell:hover .adv-ic-brand .ic-fill{fill:var(--brand-sky)}
.bento-cell:hover .adv-ic-brand .ic-up{translate:0 -10%}
.bento-cell:hover .adv-ic-brand .ic-down{translate:0 10%}
@media (prefers-reduced-motion:reduce){
  .adv-ic-brand .ic-up,.adv-ic-brand .ic-down{transition:fill .4s var(--ease)}
  .bento-cell:hover .adv-ic-brand .ic-up,
  .bento-cell:hover .adv-ic-brand .ic-down{translate:none}
}
/* the supplied artwork is wider than tall, so it letterboxes — size up to match
   the visual weight of the other icons in the panel */
.b-iconwrap .adv-ic-brand{width:94px;height:94px}

/* ---- Strengthen Security: supplied icon on top, chips below the copy ---- */
.adv-ic-brand .ic-line-w{fill:#fff}          /* this icon's line art carries a white fill */
.b-sec .adv-ic-sec{width:64px;height:64px;margin-bottom:16px}
.b-sec .b-body{padding-top:clamp(22px,2.2vw,30px)}
.b-sec .b-badges{padding:0;margin-top:16px}
/* the filled layer is the part that moves */
.adv-ic-sec .ic-fill{transition:fill .4s var(--ease),translate .55s cubic-bezier(.34,1.25,.5,1)}
.bento-cell:hover .adv-ic-sec .ic-fill{translate:0 -6%}

/* client icon set: line art keeps its native stroke width, no miter spikes */
.adv-ic-brand .ic-line{stroke-linejoin:round;stroke-linecap:round;vector-effect:non-scaling-stroke}
.b-roi .adv-ic-brand{width:86px;height:86px}

/* ============ HERO STACKED CARD ============
   Brand collateral layers a photo card over an offset blue and green card.
   The copy card itself stays upright — only the backing layers tilt. */
.hero-stack,.stacked{position:relative}
.hero-stack{max-width:580px;--stack-r:28px}
.hero-stack .hero-card{position:relative;z-index:2;max-width:none}
/* anything that is not a backing layer rides on top — was an explicit list of
   three homepage children, which meant every new .stacked user had to be
   remembered here or its photo rendered UNDER the colour cards */
.stacked > :not(.stack-card){position:relative;z-index:2}
/* ⚠️ DEFAULT ROUNDING FOR ANY DIRECT <img> IN A STACK.
   .stacked itself carries no border-radius - it is only a positioning
   context, the rounding lives on the .stack-card layers - so
   `border-radius:inherit` on the image resolves to 0 and the photo sits
   SQUARE inside two rounded cards. That bug shipped twice (the Oregon site
   plan, then the state-hub blurb image), each time fixed in one place only.
   This makes --stack-r the default; a component with its own more specific
   rule (.stacked.sr-media img) still wins. */
.stacked > img{border-radius:var(--stack-r)}
.stack-card{
  position:absolute;inset:0;border-radius:var(--stack-r,30px);z-index:1;pointer-events:none;
  box-shadow:0 6px 14px rgba(64,64,65,.24);
}
.stack-blue{background:#2cabe2;transform:rotate(-2.4deg) translate(-13px,-9px)}
.stack-green{background:var(--brand-green);transform:rotate(1.9deg) translate(13px,11px)}
@media (max-width:620px){
  .stack-blue{transform:rotate(-1.8deg) translate(-8px,-6px)}
  .stack-green{transform:rotate(1.4deg) translate(8px,7px)}
}
/* the copy card must be near-opaque now, or the blue/green layers bleed
   through the frosted glass and flood the whole card */
.hero-stack .hero-card{
  background:#fff;
  border-color:rgba(255,255,255,.95);
}

/* the stacked layers must not inherit the card's own entrance animation */
.stk-glove .stack-card,.stk-bk .stack-card{opacity:1}
/* World-Class Colocation sits ON brand blue, so the blue layer would vanish —
   use a deeper blue there and firm up the glass so the layers don't bleed through */
.stk-loc .stack-blue{background:#0e5c7c}
.stk-loc .loc-card{background:rgba(8,16,24,.82)}
/* the booking card is moved into the modal on open; the empty wrapper collapses */
.stk-bk{margin-top:50px}
.stk-bk .bk-card{margin-top:0}

/* ---- stacked-card corrections ----
   Any card that animates its own opacity will let the blue/green layers show
   straight through it, so the reveal moves to the wrapper and the cards go opaque. */
.stk-glove{opacity:0;translate:0 24px;
  transition:opacity .8s var(--ease) .18s,translate .8s var(--ease) .18s}
.glove.in .stk-glove{opacity:1;translate:0}
.stacked > .glove-media{opacity:1;translate:none;transition:none}

.stk-bk{opacity:0;translate:0 22px;
  transition:opacity .7s var(--ease) .15s,translate .7s var(--ease) .15s}
.booking.in .stk-bk{opacity:1;translate:0}
.stacked > .bk-card{opacity:1;translate:none;transition:none}

/* the cycling location card sits on brand blue: keep it opaque, and fade its
   CONTENTS on swap rather than the card (which would flash the green layer) */
.stk-loc .loc-card{background:rgba(6,14,22,.96)}
.loc-card.swapping{opacity:1;transform:none}
.loc-card > *{transition:opacity .19s ease,transform .19s ease}
.loc-card.swapping > *{opacity:0;transform:translateY(9px)}

/* ---- World-Class Colocation card: white surface, dark type ---- */
.stk-loc .loc-card{
  background:#fff;border-color:rgba(18,35,47,.1);
  box-shadow:0 26px 60px -26px rgba(6,24,38,.45);
}
.stk-loc .loc-card-img{border-color:rgba(18,35,47,.1)}
.stk-loc .loc-card-head h3{color:var(--ink)}
.stk-loc .loc-city{color:var(--ink-soft)}
.stk-loc .loc-desc{color:var(--ink-soft)}
.stk-loc .loc-feats li{color:var(--ink)}
.stk-loc .loc-grid{
  color:var(--brand-deep);background:rgba(44,171,226,.12);
  border-color:rgba(44,171,226,.45);
}
.stk-loc .loc-cta{color:var(--brand-deep)}

/* Cloud Services photo runs warm next to the two staff shots — pull it back
   toward neutral in CSS rather than re-generating the image */
/* Keyed to the PHOTO, not to the position. sol-cloud.jpg is a warm tungsten
   interior and needs pulling back to sit with the other two; as :first-child
   the correction landed on whatever panel happened to be first, which was the
   colocation portrait on the retail page and would follow any reorder. */
.sol-media img[src*="sol-cloud"]{
  filter:saturate(.52) brightness(1.05);
}

/* ---- Mega-menu feature card: brand blue with a light-blue gradient ----
   White type only hits 2.6:1 on #2cabe2, so the copy flips to dark ink (5.9:1). */
.mega-feature{
  background:
    radial-gradient(120% 90% at 100% 0%,rgba(255,255,255,.28),transparent 60%),
    linear-gradient(158deg,#2cabe2 0%,#7fd6f7 100%);
  color:var(--ink);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35);
}
.mega-feature .mega-eyebrow{color:#0a3f56}
.mega-feature .mega-ftitle{color:var(--ink)}
.mega-feature .mega-points li{color:rgba(64,64,65,.88)}
.mega-feature .mega-points li::before{border-color:#0a3f56}
.mega-feature .mega-cta{color:#0a3f56}
.mega-feature .mega-cta:hover{color:var(--ink)}

/* ---- Client icon set inside the mega menu ----
   These are two-tone (line + filled) illustrations, so both parts follow
   currentColor and flip to white with the tile on hover. Strokes use
   non-scaling-stroke or they'd render hairline-thin at 26px. */
.mega-ic-brand svg{width:26px;height:26px;overflow:visible}
.mega-ic-brand .ic-line{
  fill:none;stroke:currentColor;stroke-width:1.6;
  vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round;
}
.mega-ic-brand .ic-line-w{fill:#fff}
.mega-ic-brand .ic-fill{fill:currentColor;stroke:none}
.mega-link:hover .mega-ic-brand .ic-line-w{fill:transparent}

/* ============ MEGA MENU — wider, taller, larger icons ============
   Panel spans logo → Book-a-Meeting button (measured 1192px). The client's
   icons carry a lot of detail, so the tiles grow to give them room. */
.mega{width:min(1192px,calc(100vw - 32px));padding:30px}
.mega-inner{gap:30px}
.mega-links{gap:6px 12px}
.mega-link{gap:16px;padding:13px 14px;border-radius:16px}
.mega-ic{width:54px;height:54px;border-radius:15px}
.mega-ic svg{width:27px;height:27px}
.mega-ic-brand svg{width:38px;height:38px}
.mega-tx b{font-size:.96rem}
.mega-tx i{font-size:.79rem;margin-top:3px}

/* feature card: solid brand blue, white copy */
.mega-feature{
  background:#2cabe2;
  color:#fff;
  padding:26px 26px 24px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.25);
}
.mega-feature .mega-eyebrow{color:rgba(255,255,255,.92)}
.mega-feature .mega-ftitle{color:#fff;font-size:1.24rem}
.mega-feature .mega-points li{color:rgba(255,255,255,.96);font-size:.88rem}
.mega-feature .mega-points li::before{border-color:#fff}
.mega-feature .mega-cta{color:#fff}
.mega-feature .mega-cta:hover{color:rgba(255,255,255,.8)}

/* ============ CLIENT ICON SET — knock-outs + stroke weight ============
   Their icons build detail from WHITE shapes layered over the blue. Painting
   those white parts with currentColor collapsed each icon into a blob, and a
   fixed 1.6px non-scaling stroke then clogged the remaining gaps. Knock-outs
   now follow the tile colour, and the stroke drops to 1.1px. */
.adv-ic-brand,.mega-ic-brand{--ic-knock:#fff}
.adv-ic-brand .ic-fill,.mega-ic-brand .ic-fill{fill:currentColor;stroke:none}
.adv-ic-brand .ic-line,.mega-ic-brand .ic-line{
  stroke:currentColor;stroke-width:1.1;vector-effect:non-scaling-stroke;
  stroke-linejoin:round;stroke-linecap:round;
}
.adv-ic-brand .ic-knock-f,.mega-ic-brand .ic-knock-f{fill:var(--ic-knock)}
.adv-ic-brand .ic-knock-s,.mega-ic-brand .ic-knock-s{
  stroke:var(--ic-knock);stroke-width:1.1;vector-effect:non-scaling-stroke;
  stroke-linejoin:round;stroke-linecap:round;
}
/* knock-outs must match whatever sits behind the icon */
.mega-ic{--ic-knock:#f1fafe}
.mega-link:hover .mega-ic{--ic-knock:#2299cc}
.b-iconwrap .adv-ic-brand{--ic-knock:#e6f4ee}

/* ---- Colocation locations: state outlines instead of repeated map pins ---- */
.mega-ic-state svg{width:42px;height:42px}

/* ---- Cloud Services cards: client icon set on the dark panel ---- */
.cs-ghost-brand{
  position:absolute;top:8px;right:14px;pointer-events:none;
  /* the knockouts in the client's icon art have to match the card they sit on,
     or they read as a foreign dark shape. Sampled from the rendered pixels:
     the card is #424243 on the top row and #3c3c3d on the bottom — this sits
     between the two. (Was #16323d, tuned for the old navy field.) */
  --ic-knock:#3f3f40;
}
.cs-ghost-brand svg{
  width:66px;height:66px;overflow:visible;color:rgba(255,255,255,.2);
  transition:color .4s var(--ease),transform .45s cubic-bezier(.34,1.2,.5,1);
}
.cs-ghost-brand .ic-fill{fill:currentColor;stroke:none}
.cs-ghost-brand .ic-line{
  stroke:currentColor;stroke-width:1.1;vector-effect:non-scaling-stroke;
  stroke-linejoin:round;stroke-linecap:round;
}
.cs-ghost-brand .ic-knock-f{fill:var(--ic-knock)}
.cs-ghost-brand .ic-knock-s{stroke:var(--ic-knock);stroke-width:1.1;vector-effect:non-scaling-stroke}
.cs-cell:hover .cs-ghost-brand svg{color:var(--brand-sky);transform:scale(1.07)}

/* ---- pre-footer scrim: the new photo is already dark, so halve the overlay ---- */
.prefoot-scrim{
  background:radial-gradient(78% 62% at 50% 52%,
    rgba(6,22,38,.28) 0%, rgba(6,22,38,.17) 46%, rgba(6,22,38,0) 80%);
}

/* ---- World-Class Colocation spacing ----
   Tighten the gap above the heading by ~150px, and open 150px below the globe
   so the earth isn't crowded against the next section. */
.sol-fade{height:0}   /* the blue bridge is gone — the section now closes on its own white, matching the 150px above the heading */
.locations{padding-bottom:var(--sec-y)}   /* scales with every other section */

/* the bento icons switched to currentColor, so they inherited the card's near-black
   text colour — restore the translucent grey at rest, brand blue on hover */
.adv-ic-brand{color:rgba(64,64,65,.17)}
.bento-cell:hover .adv-ic-brand{color:var(--brand-sky)}

/* ---- Cloud Services cards: more room for the busier client icons ---- */
.cs-cell{
  padding-top:clamp(48px,4.6vw,64px);
  padding-bottom:clamp(32px,3.2vw,44px);
}
.cs-cell h3{padding-right:82px}
.cs-ghost-brand{top:14px;right:16px}

/* Strategic Partnerships logos +15% (44px -> 51px) */
.marquee-track img{height:51px}

/* ============================================================
   SECTION EYEBROWS — single source of truth
   Every callout gets the same pair of marks: solid, square-cut,
   no gradient fade. Previously 8 near-duplicate blocks (all
   fading transparent→colour) plus 2 sections with no marks at
   all, which is what let them drift apart.
   ============================================================ */
.hero-eyebrow,.proof-eyebrow,.partners-eyebrow,.adv-eyebrow,.loc-eyebrow,
.glove-eyebrow,.x-eyebrow,.cs-eyebrow,.bk-eyebrow,.pf-eyebrow{
  display:flex;align-items:center;gap:12px;
}
/* the two that had no marks sit in centred sections */
.proof-eyebrow,.adv-eyebrow{justify-content:center}

.hero-eyebrow::before,.hero-eyebrow::after,
.proof-eyebrow::before,.proof-eyebrow::after,
.partners-eyebrow::before,.partners-eyebrow::after,
.adv-eyebrow::before,.adv-eyebrow::after,
.loc-eyebrow::before,.loc-eyebrow::after,
.glove-eyebrow::before,.glove-eyebrow::after,
.x-eyebrow::before,.x-eyebrow::after,
.cs-eyebrow::before,.cs-eyebrow::after,
.bk-eyebrow::before,.bk-eyebrow::after,
.pf-eyebrow::before,.pf-eyebrow::after{
  content:"";
  height:2px;                       /* whole pixel — 1.5px antialiased differently in
                                       every section depending on where the line landed
                                       on the sub-pixel grid, which read as uneven weight */
  width:17px;                       /* half the old 34px — dash-length, not rule-length */
  flex:none;
  border-radius:0;                  /* square-cut, like a real dash */
  background:currentColor;          /* solid — no transparent→colour fade */
}

/* ============================================================
   CREDENTIAL CHIPS — single source of truth
   Hero trust chips, Why Opus badges and the Exploring-card chips
   are the same component and now share one rule, built on the
   client's #2cabe2 (was: hero all-grey, x-chips fully-rounded
   with no tint, only .b-badges correct).
   NOTE ON THE TEXT COLOUR: #2cabe2 as type on white is 2.62:1 and
   fails WCAG AA, so the label uses --brand-deep (#17789f) — the
   same hue stepped down to 4.97:1. The chip's border + fill carry
   #2cabe2 itself. This matches the Why Opus chips the client
   confirmed as correct.
   ============================================================ */
.trust-list li,
.b-badges li,
.x-chips li{
  font-family:var(--font-label);
  font-size:.75rem;font-weight:600;
  color:var(--brand-deep);
  border:1px solid rgba(44,171,226,.45);    /* #2cabe2 @ 45% */
  background:rgba(44,171,226,.07);          /* #2cabe2 @ 7%  */
  padding:5px 11px;
  border-radius:8px;
}

/* ============================================================
   CLIENT LOGIN — collapsed to a circle, expands on hover
   Brand green needs DARK type: white on #b9d531 is 1.66:1,
   --ink on it is 6.23:1. Width can't be transitioned from a
   fixed value to auto, so the LABEL animates its max-width and
   the pill grows around it.
   ============================================================ */
/* fixed 40px footprint: the pill is absolutely placed inside it and anchored
   LEFT, so expanding grows to the right and cannot push the nav or the
   Book a Meeting button (it used to steal 58px from the nav on hover). */
.cl-slot{position:relative;display:block;width:40px;height:40px;flex:none}
.client-login{
  position:absolute;left:0;top:0;z-index:2;
  display:inline-flex;align-items:center;
  height:40px;padding:0 10px;
  border-radius:100px;
  background:var(--brand-green);
  color:var(--ink);
  text-decoration:none;white-space:nowrap;overflow:hidden;
  transition:padding .32s var(--ease),box-shadow .25s var(--ease);
}
.client-login .cl-ic{flex:none;color:#fff}   /* white icon on the brand green */
.cl-tx{
  display:inline-block;max-width:0;opacity:0;margin-left:0;
  font-family:var(--font-label);font-size:.8rem;font-weight:600;
  letter-spacing:.01em;overflow:hidden;
  transition:max-width .32s var(--ease),opacity .22s var(--ease) .04s,margin-left .32s var(--ease);
}
.client-login:hover,
.client-login:focus-visible{
  padding-right:16px;
  box-shadow:0 6px 16px -6px rgba(185,213,49,.85);
}
.client-login:hover .cl-tx,
.client-login:focus-visible .cl-tx{max-width:130px;opacity:1;margin-left:8px}
@media (prefers-reduced-motion:reduce){
  .client-login,.cl-tx{transition:none}
}

/* ============================================================
   INNER PAGES (industries, partner program)
   Same tokens as the homepage — Poppins/IBM Plex, #2cabe2,
   --ink, --sec-y rhythm, chip + button atoms — but their own
   compositions. The homepage keeps its signature moments.
   ============================================================ */

/* --- compact page header: ~half the homepage hero, copy on the photo --- */
/* ⚠️ The header is position:fixed, so it OVERLAYS the first section. The
   .78/.62 top-to-bottom ratio below was the design intent, but the header
   silently ate 85px of the top: measured 32px of visible gap above the
   headline against 93px below the buttons at 1440. Adding --hd-h back
   restores the intended ratio as SEEN rather than as declared. */
.phero{position:relative;isolation:isolate;display:flex;align-items:center;
  min-height:calc(clamp(380px,52vh,540px) + var(--hd-h));
  padding:calc(var(--sec-y) * .62 + var(--hd-h)) var(--sec-x) calc(var(--sec-y) * .62);
  overflow:hidden}
/* ⚠️ A TALLER HERO IS THE ONLY WAY TO "ZOOM OUT" A FULL-BLEED PHOTO.
   object-fit:cover already shows 100% of the image's WIDTH; the crop is purely
   vertical, set by the box's aspect. At the default 636px the box is 2.26:1
   against a 1.5:1 photo, so a third of the height is lost. The facility
   exteriors need their roofline and forecourt to read as buildings, so those
   two pages get a taller box: 83% of the photo instead of 66%.
   Desktop only — the mobile hero is already taller than it is wide. */
@media (min-width:861px){
  .phero.is-tall{min-height:min(790px,86vh)}
}
.phero-photo{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-2}
/* ⚠️ The three stops are VARIABLES so a page can lighten its own scrim without
   a new class or a copy of this gradient. Defaults are the original values, so
   every existing hero is untouched; a page opts out by setting --scrim-l/m/r on
   its .phero. .phero-bare below still replaces the whole background outright,
   because the About hero needs the right half fully clear, not just lighter. */
.phero-scrim{position:absolute;inset:0;z-index:-1;
  background:linear-gradient(94deg,
    rgba(6,22,34,var(--scrim-l,.86)) 0%,
    rgba(6,22,34,var(--scrim-m,.66)) 46%,
    rgba(6,22,34,var(--scrim-r,.18)) 100%)}
/* about-opus 2026-09-23: the widened patio photo carries the headline almost
   unaided, so this hero gets the scrim at a quarter strength (client: "75%
   lighter") and nothing at all past the midpoint, which leaves the three
   people in full daylight. Alphas are the sitewide .86/.66/.18 x 0.25.
   Scoped to this one hero; drop the class to get the standard scrim back. */
.phero-bare .phero-scrim{
  background:linear-gradient(94deg,rgba(6,22,34,.215) 0%,rgba(6,22,34,.165) 28%,rgba(6,22,34,0) 50%)}
/* Phones, client 2026-09-23. The wide hero is 2400x1018, so on a 390px screen
   cover scales to HEIGHT and shows only ~26% of its width — and the three faces
   span 37% of it, so the third person was cropped off at every pan value. No
   --hero-x fixes that; phones get a portrait crop of the scene instead (see the
   <picture> in the page), AI-extended downward so the patio carries the copy.
   - the hero drops to 560px, which is the tallest box that still shows the full
     width of the portrait frame. Taller reintroduces the horizontal crop.
   - --hero-x:82% takes the last sliver of slack off the left, where there is
     only paving, rather than off the third person's shoulder.
   - the copy is bottom-aligned, so it sits on the table and their laps while
     all three faces stay clear above it.
   - the scrim turns vertical: the pale concrete under the copy needs the
     contrast, their faces do not. */
@media (max-width:600px){
  .phero-bare{--hero-x:82%;align-items:flex-end;min-height:min(560px,72vh)}
  .phero-bare .phero-scrim{
    background:linear-gradient(180deg,rgba(6,22,34,0) 26%,rgba(6,22,34,.30) 50%,rgba(6,22,34,.62) 100%)}
}
}
}
.phero-inner{max-width:var(--wrap);width:100%;margin:0 auto}
.phero-eyebrow{display:flex;align-items:center;gap:12px;
  font-family:var(--font-label);font-size:.76rem;font-weight:600;letter-spacing:.18em;
  text-transform:uppercase;color:#a5e4fb;margin-bottom:16px}
.phero-eyebrow::before,.phero-eyebrow::after{content:"";height:2px;width:17px;flex:none;background:currentColor}
/* (the trailing hero dash was hidden here until 2026-09-11: client wants both
   dashes everywhere, see EVERY DASHED LABEL at the end of this file) */
.phero-title{font-family:var(--font-main);font-weight:600;color:#fff;
  font-size:clamp(2.1rem,4.4vw,3.5rem);line-height:1.08;letter-spacing:-.02em;max-width:16ch}
.phero-title .accent{color:#7fd6f7}
.phero-sub{margin-top:18px;max-width:62ch;color:rgba(255,255,255,.9);
  font-size:clamp(1rem,1.25vw,1.12rem);line-height:1.62}
.phero-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:30px}
.phero .btn-ghost{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.42);color:#fff}
.phero .btn-ghost:hover{background:rgba(255,255,255,.18);border-color:#fff}

/* --- credential band: lead sentence + numbers on one line --- */
.statband{padding:var(--sec-y) var(--sec-x);background:var(--paper);
  border-bottom:1px solid var(--line-soft)}
.sb-inner{max-width:var(--wrap);margin:0 auto;display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);gap:clamp(32px,5vw,72px);align-items:center}
.sb-lead{font-size:clamp(1.02rem,1.35vw,1.18rem);line-height:1.66;color:var(--ink-soft)}
.sb-list{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(20px,2.6vw,34px);list-style:none}
.sb-list li{border-left:2px solid rgba(44,171,226,.5);padding-left:16px}
.sb-num{display:block;font-family:var(--font-main);font-weight:600;letter-spacing:-.02em;
  font-size:clamp(1.7rem,2.5vw,2.3rem);color:var(--brand-sky);line-height:1.1}
.sb-lab{display:block;margin-top:4px;font-family:var(--font-label);font-size:.8rem;color:var(--ink-soft)}

/* --- uniform outcome cards (no oversized numerals) --- */
.outcomes{padding:var(--sec-y) var(--sec-x);background:#fff}
.oc-inner{max-width:var(--wrap);margin:0 auto}
.oc-head{max-width:720px;margin:0 0 var(--head-gap)}
.oc-eyebrow{display:flex;align-items:center;gap:12px;font-family:var(--font-label);
  font-size:.78rem;font-weight:600;letter-spacing:.18em;text-transform:uppercase;
  color:var(--brand-deep);margin-bottom:12px}
.oc-eyebrow::before{content:"";height:2px;width:17px;flex:none;background:currentColor}
.oc-title{font-family:var(--font-main);font-weight:600;letter-spacing:-.02em;
  font-size:clamp(1.8rem,3.1vw,2.7rem);line-height:1.14;color:var(--ink)}
.oc-title .accent{color:var(--brand-sky)}
.oc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,1.7vw,22px)}
.oc-card{background:#fff;border:1px solid var(--line-soft);border-radius:20px;
  padding:clamp(24px,2.4vw,32px);box-shadow:var(--shadow-sm);
  opacity:0;translate:0 18px;transition:opacity .55s var(--ease),translate .55s var(--ease),
    border-color .3s var(--ease),box-shadow .3s var(--ease)}
.outcomes.in .oc-card{opacity:1;translate:0;transition-delay:calc(var(--i,0)*70ms)}
.oc-card:hover{border-color:rgba(44,171,226,.45);box-shadow:0 18px 40px -20px rgba(18,54,74,.4)}
.oc-card h3{font-family:var(--font-main);font-size:1.12rem;font-weight:600;color:var(--ink);margin-bottom:9px}
.oc-card p{font-size:.95rem;line-height:1.62;color:var(--ink-soft)}
.oc-stat{margin-top:16px;font-family:var(--font-main);font-weight:600;font-size:1.5rem;
  color:var(--brand-sky);letter-spacing:-.02em}
.oc-stat span{font-family:var(--font-label);font-size:.76rem;font-weight:600;color:var(--ink-faint);
  letter-spacing:.04em;display:block;margin-top:2px}
.oc-badges{display:flex;flex-wrap:wrap;gap:7px;margin-top:16px;list-style:none}

/* --- deep dive: sticky heading column + ticked rows --- */
/* Same dark grey ramp as the homepage's "Human Support" (.glove) band — this is
   the same story told on the partner page, so it gets the same treatment.
   Everything below re-colours the copy for a dark ground; the light-ground rules
   are further up the file and this block overrides them. */
.dive{padding:var(--sec-y) var(--sec-x);color:#fff;
  background:linear-gradient(180deg,var(--grey-900) 0%,var(--grey-800) 60%,var(--grey-700) 100%)}
.dive .dive-eyebrow{color:#a5e4fb}
.dive .dive-title{color:#fff}
.dive .dive-title .accent{color:#7fd6f7}
.dive .dive-body{color:rgba(255,255,255,.9)}
.dive .dive-close{color:rgba(255,255,255,.78)}
/* the rows were solid white cards; on the dark ground they become tinted glass */
.dive .dive-list li{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.15)}
.dive .dive-list li:hover{background:rgba(42,196,244,.1);border-color:rgba(42,196,244,.4)}
.dive .dive-list span{color:rgba(255,255,255,.93)}
.dive .dive-list svg{color:#7fd6f7}
/* align-items:center, not start: the copy column is the shorter of the two
   (304 vs 454), so starting both at the top left it hanging off the taller
   list beside it. */
.dive-inner{max-width:var(--wrap);margin:0 auto;display:grid;
  grid-template-columns:minmax(0,.95fr) minmax(0,1fr);gap:clamp(36px,6vw,86px);align-items:center}
/* This column used to be position:sticky;top:110px, so it tracked the scroll
   while the list beside it stayed put. Client asked for it to hold still. */
.dive-eyebrow{display:flex;align-items:center;gap:12px;font-family:var(--font-label);
  font-size:.78rem;font-weight:600;letter-spacing:.18em;text-transform:uppercase;
  color:var(--brand-deep);margin-bottom:12px}
.dive-eyebrow::before{content:"";height:2px;width:17px;flex:none;background:currentColor}
.dive-title{font-family:var(--font-main);font-weight:600;letter-spacing:-.02em;
  font-size:clamp(1.7rem,2.9vw,2.5rem);line-height:1.15;color:var(--ink)}
.dive-title .accent{color:var(--brand-sky);display:block}
.dive-body{margin:18px 0 26px;color:var(--ink-soft);line-height:1.68;font-size:1rem}
.dive-list{list-style:none;display:grid;gap:2px}
.dive-list li{display:flex;gap:14px;align-items:flex-start;
  padding:clamp(18px,1.8vw,24px) clamp(18px,1.8vw,26px);
  background:#fff;border:1px solid var(--line-soft);
  opacity:0;translate:0 14px;transition:opacity .5s var(--ease),translate .5s var(--ease),background .25s}
.dive-list li:first-child{border-radius:18px 18px 0 0}
.dive-list li:last-child{border-radius:0 0 18px 18px}
.dive.in .dive-list li{opacity:1;translate:0;transition-delay:calc(var(--i,0)*70ms)}
.dive-list li:hover{background:#f7fcfe}
.dive-list svg{color:var(--brand-sky);flex:none;margin-top:2px}
.dive-list span{font-size:.98rem;line-height:1.55;color:var(--ink)}

/* --- use cases --- */
/* This section used to be three bare paragraphs on flat white — it read as an
   afterthought at the end of every page. It now sits on a tinted band and uses
   the same card language as the bento (radius, border, shadow, lift on hover),
   so the page closes on something composed instead of trailing off. */
.usecases{
  position:relative;padding:var(--sec-y) var(--sec-x);
  background:
    radial-gradient(120% 76% at 50% 0%, #e8f5fd 0%, rgba(232,245,253,0) 62%),
    linear-gradient(180deg, var(--paper) 0%, #f2fafe 100%);
}
.uc-inner{max-width:var(--wrap);margin:0 auto;text-align:center}
.uc-title{font-family:var(--font-main);font-weight:600;letter-spacing:-.02em;
  font-size:clamp(1.7rem,2.9vw,2.5rem);line-height:1.15;color:var(--ink)}
.uc-title .accent{color:var(--brand-sky)}
/* auto-fit, not repeat(3): four of the client's "Why X chooses Opus" lists have
   FOUR entries, and a hard 3-column grid stranded the fourth on its own row. */
.uc-list{list-style:none;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(238px,1fr));
  gap:clamp(18px,2vw,26px);margin:var(--head-gap) 0 0;text-align:left}

.uc-card{
  position:relative;overflow:hidden;height:100%;
  background:#fff;border:1px solid var(--line-soft);border-radius:24px;
  padding:clamp(26px,2.4vw,34px);
  box-shadow:0 6px 22px -16px rgba(18,54,74,.4);
  opacity:0;translate:0 18px;
  transition:opacity .55s var(--ease),translate .55s var(--ease),
             transform .4s var(--ease),box-shadow .4s var(--ease),
             border-color .4s var(--ease);
}
.usecases.in .uc-card{opacity:1;translate:0;transition-delay:calc(var(--i,0)*90ms)}
.uc-card:hover{
  transform:translateY(-4px);border-color:rgba(44,171,226,.42);
  box-shadow:0 20px 44px -28px rgba(18,54,74,.55);
}
/* Icon tile, not a numeral — the client does not want numbers on these cards.
   Same rounded-tile treatment as the mega-menu icons so it reads as one system. */
.uc-ic{
  display:grid;place-items:center;width:46px;height:46px;border-radius:13px;
  margin-bottom:clamp(14px,1.4vw,18px);
  background:linear-gradient(150deg,#e4f4fd 0%,#eaf7d8 100%);
  color:var(--brand-deep);
  transition:background .4s var(--ease),color .4s var(--ease);
}
.uc-ic svg{
  width:23px;height:23px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;
}
.uc-card:hover .uc-ic{background:var(--brand-sky);color:#fff}

/* Partner page only (.uc-green is emitted when a card carries the sprout): the
   line-icons take the same brand green as the plant so the row reads as one
   thing. Lime on the old pale sky/green tile was ~1.3:1 at a 1.6px stroke —
   effectively invisible — so the tile drops to the brand grey ramp, which is
   7.6:1 and also gives the sprout's base something to sit against. */
.uc-green .uc-ic{
  background:linear-gradient(150deg,#e9f7ff 0%,#d8edfb 100%);
  color:var(--brand-green);
}
/* Brand green on a tint this light is about 1.5:1 — well under the 3:1 a graphic
   normally needs. The pairing is the client's call, so the glyph carries a
   heavier stroke than the 1.6 used elsewhere to hold its shape at that contrast.
   Scaled up here too (46->54 tile, 23->28 glyph): at this contrast, size is the
   other thing that buys legibility. Scoped to .uc-green so the six industries
   pages keep the original 46px tile. */
.uc-green .uc-ic{width:54px;height:54px;border-radius:15px}
/* :not(.uc-plant) is load-bearing — the sprout is an <svg> in this same tile, so
   a bare `.uc-green .uc-ic svg` rule (0,2,1) outranks `.has-plant .uc-plant`
   (0,2,0) and shrank the whole plant to a 28px glyph inside its box. */
.uc-green .uc-ic svg:not(.uc-plant){width:28px;height:28px;stroke-width:2}
.uc-green .uc-card:not(.has-plant):hover .uc-ic{
  background:linear-gradient(150deg,var(--brand-green) 0%,#a6c623 100%);
  color:var(--grey-900);
}
/* The sprout IS brand green, so the green HOVER tile would swallow it — this one
   tile keeps the light blue in both states. (It used to be a deeper blue so the
   sprout would read; now every tile is light, so matching them is what removes
   the odd-one-out.) */
.uc-green .uc-card.has-plant .uc-ic,
.uc-green .uc-card.has-plant:hover .uc-ic{
  background:linear-gradient(150deg,#e9f7ff 0%,#d8edfb 100%);
  color:var(--brand-green);
}
.uc-card h3{
  font-family:var(--font-main);font-weight:600;font-size:1.1rem;
  letter-spacing:-.01em;line-height:1.3;color:var(--ink);margin:0 0 9px;
}
.uc-card p{font-size:.97rem;line-height:1.62;color:var(--ink-soft);margin:0}

/* 72ch, not 62: at 62 the partner page's closing line broke to three, the last
   carrying a single 49px word. 72 holds two lines and keeps them balanced
   (897/618 at 1440) — going wider just makes the first line run long. */
.uc-close{
  margin:clamp(40px,4.4vw,58px) auto 0;max-width:72ch;
  /* below 1024 it wraps further and stranded a single 41px word on its own
     line; `pretty` is the property that exists to stop that. Ignored by
     browsers that lack it, which just get the ragged break they had. */
  text-wrap:pretty;
  font-family:var(--font-main);font-weight:500;
  font-size:clamp(1.06rem,1.5vw,1.26rem);line-height:1.55;color:var(--ink);
}
/* the short rule above this line was removed at the client's request — the
   margin on .uc-close is enough separation on its own */

/* --- solution panels: contained cards, not full-bleed --- */
.psol{padding:var(--sec-y) var(--sec-x);background:var(--paper)}
.psol-inner{max-width:var(--wrap);margin:0 auto}
.psol-head{max-width:760px;margin:0 0 var(--head-gap)}
.psol-head h2{font-family:var(--font-main);font-weight:600;letter-spacing:-.02em;
  font-size:clamp(1.8rem,3.1vw,2.7rem);line-height:1.14;color:var(--ink)}
.psol-head h2 .accent{color:var(--brand-sky)}
.psol-head p{margin-top:16px;color:var(--ink-soft);line-height:1.68}
.psol-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(18px,2vw,26px)}
.ps-card{border-radius:22px;overflow:hidden;background:#fff;border:1px solid var(--line-soft);
  box-shadow:var(--shadow-sm);display:flex;flex-direction:column;
  opacity:0;translate:0 20px;transition:opacity .6s var(--ease),translate .6s var(--ease),
    transform .35s var(--ease),box-shadow .35s var(--ease)}
.psol.in .ps-card{opacity:1;translate:0;transition-delay:calc(var(--i,0)*90ms)}
.ps-card:hover{transform:translateY(-4px);box-shadow:0 26px 54px -26px rgba(18,54,74,.45)}
.ps-media{aspect-ratio:16/10;overflow:hidden}
.ps-media img{width:100%;height:100%;object-fit:cover;display:block}
.ps-body{padding:clamp(22px,2.2vw,28px);display:flex;flex-direction:column;gap:9px;flex:1}
.ps-body h3{font-family:var(--font-main);font-size:1.14rem;font-weight:600;color:var(--ink)}
.ps-body p{font-size:.95rem;line-height:1.6;color:var(--ink-soft);flex:1}
.ps-link{display:inline-flex;align-items:center;gap:7px;margin-top:6px;
  font-family:var(--font-label);font-size:.86rem;font-weight:600;color:var(--brand-deep)}
.ps-link svg{transition:transform .3s var(--ease)}
.ps-card:hover .ps-link svg{transform:translateX(4px)}

@media (max-width:1020px){
  .sb-inner,.dive-inner{grid-template-columns:minmax(0,1fr)}
  .oc-grid,.psol-grid,.uc-list{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:680px){
  .oc-grid,.psol-grid,.uc-list,.sb-list{grid-template-columns:minmax(0,1fr)}
  .phero-title{max-width:none}
}

/* Peace of Mind is the one bento cell with no icon slot — it leads with a
   display numeral. Sized down and tucked above the number so it reads as a
   quiet mark rather than competing with it. */
.b-peace .adv-ic-brand{
  width:46px;height:46px;
  margin:clamp(20px,2vw,26px) 0 -4px clamp(22px,2.2vw,30px);
}

/* ============================================================
   PARTNER — FLEXIBLE PARTNERSHIP OPTIONS  (doc section 4)
   Two large photo cards. Copy sits on the photo behind a scrim
   rather than beside it, which is how the homepage's .sol-col
   panels work, so the page keeps one visual language.
   ============================================================ */
.duo{padding:var(--sec-y) var(--sec-x);background:var(--paper)}
.duo-inner{max-width:var(--wrap);margin:0 auto;text-align:center}
.duo-title{font-family:var(--font-main);font-weight:600;letter-spacing:-.02em;
  font-size:clamp(1.7rem,2.9vw,2.5rem);line-height:1.15;color:var(--ink)}
.duo-title .accent{color:var(--brand-sky)}
/* --head-gap (= --sec-y, up to 150px) left the heading floating well away from
   the pair. The space ABOVE the heading is section padding and is unchanged. */
.duo-grid{display:grid;grid-template-columns:repeat(2,1fr);
  gap:clamp(18px,2vw,26px);margin-top:clamp(30px,3.4vw,52px);text-align:left}

/* Was text over a full-bleed photo behind a scrim that had to ramp to 96% for
   white copy to pass contrast — which meant the photograph underneath was
   effectively black. Client: "these 2 columns are way too dark."
   Now the photo is its own band at the top of a white card and the copy sits
   below it in ink. Nothing is dimmed, the people in the frame are actually
   visible, and the card matches the light card language used everywhere else
   on the page (bento, use cases, services). */
.duo-card{
  display:flex;flex-direction:column;
  background:#fff;border:1px solid var(--line-soft);
  border-radius:24px;overflow:hidden;
  box-shadow:var(--shadow-sm);
  opacity:0;translate:0 20px;
  transition:opacity .6s var(--ease),translate .6s var(--ease),
             transform .45s var(--ease),box-shadow .45s var(--ease),border-color .3s var(--ease);
}
.duo.in .duo-card{opacity:1;translate:0;transition-delay:calc(var(--i,0)*110ms)}
.duo-card:hover{
  transform:translateY(-5px);
  border-color:rgba(44,171,226,.4);
  box-shadow:0 26px 54px -30px rgba(18,54,74,.45);
}
/* fixed band height so both cards' copy starts on the same line */
.duo-media{overflow:hidden;height:clamp(224px,20vw,290px);flex:none}
.duo-photo{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .7s var(--ease)}
.duo-card:hover .duo-photo{transform:scale(1.04)}

.duo-body{
  display:flex;flex-direction:column;flex:1;
  padding:clamp(24px,2.4vw,34px);color:var(--ink);
}
/* brand guideline pill: light-blue ground, blue copy */
.duo-kicker{
  align-self:flex-start;
  font-family:var(--font-label);font-size:.72rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--brand-deep);
  background:#d5eef9;
  padding:5px 12px;border-radius:100px;
  margin:0 0 14px;
}
.duo-card h3{
  font-family:var(--font-main);font-weight:600;letter-spacing:-.02em;
  font-size:clamp(1.3rem,1.9vw,1.65rem);line-height:1.18;margin:0 0 10px;color:var(--ink);
}
/* The two leads are different lengths, so at the same measure the reseller's ran
   two lines against the affiliate's three. min-height keeps the blocks the same
   HEIGHT; the padding below is what makes them the same number of LINES. */
.duo-lead{font-size:.99rem;line-height:1.6;color:var(--ink-soft);margin:0 0 18px;
  min-height:calc(3 * 1.6em)}
/* Narrows the (shorter) reseller lead until it wraps to the same line count as
   the affiliate one opposite. A percentage, not a px value: measured across 32
   viewport widths, 24% matches at 26 of them where a fixed padding held only at
   the width it was tuned for. The leftovers are one-line-off bands a few dozen
   px wide (~1050-1100, ~540-560), where the longer text tips over first — the
   min-height above keeps the cards level through those. */
.duo-card:first-child .duo-lead{padding-right:24%}
.duo-list{list-style:none;display:grid;gap:9px;margin:0 0 24px;padding:0}
.duo-list li{
  position:relative;padding-left:22px;
  font-size:.93rem;line-height:1.5;color:var(--ink-soft);
}
.duo-list li::before{
  content:"";position:absolute;left:0;top:.52em;
  width:8px;height:8px;border-radius:2px;background:var(--brand-sky);
}
/* margin-top:auto pins both CTAs to the card floor, so they line up across the
   pair even when one card's copy runs a line longer */
.duo-cta{
  margin-top:auto;align-self:flex-start;
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--font-main);font-size:.95rem;font-weight:600;
  color:#fff;text-decoration:none;
  padding:13px 24px;border-radius:100px;
  background:var(--brand-sky);
  transition:background .3s var(--ease),gap .3s var(--ease);
}
.duo-cta:hover{background:var(--brand-deep);gap:12px}

/* --- "Hardware Your Way" strip (doc section 6, additional strip) --- */
/* Was padding-top:0 — written as a strip tucked under the services grid on a
   page where .solutions ends with a hard photo cut, so the card sat flush
   against the panels above while carrying a full 150px below it. That
   asymmetry is what read as random. Straight --sec-y both sides, same as
   every other section on the page. */
/* The gradient is the SECTION now, not a card floating on the page — a tinted
   panel inside an untinted section read as a leftover strip rather than a band
   of the page. */
.hwstrip{
  padding:var(--sec-y) var(--sec-x);
  background:linear-gradient(120deg,#eef8fd 0%,#f2fae4 100%);
}
/* Was align-items:center, which floated the right-hand note at whatever height
   its three lines happened to land — its first line sat between the heading and
   the paragraph opposite, so the two halves read as unrelated. Both columns now
   start on the same line and the rule between them runs the full height, which
   is what makes it read as one deliberate card. */
.hw-inner{
  max-width:var(--wrap);margin:0 auto;
  display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(24px,3vw,52px);align-items:center;
}
.hw-copy h3{
  font-family:var(--font-main);font-weight:600;letter-spacing:-.02em;
  font-size:clamp(1.2rem,1.8vw,1.5rem);color:var(--ink);margin:0 0 8px;
}
.hw-copy p{font-size:.99rem;line-height:1.6;color:var(--ink-soft);margin:0}
/* moved into .hw-copy under the body text — no rule above it and none beside
   it; the paragraph break is enough separation.
   MUST be .hw-copy .hw-note: as a bare .hw-note it lost to `.hw-copy p{margin:0}`
   on specificity (0,1,1 beats 0,1,0), so the gap below silently never applied
   and the two paragraphs ran together at plain line-height. */
.hw-copy .hw-note{
  font-size:.95rem;line-height:1.65;color:var(--ink-soft);
  /* the rule it replaced sat in ~28px of space; keep that gap so the two
     paragraphs still read as separate without a line between them */
  margin:26px 0 0;
}
/* right column: the partners that sentence names, as their actual marks.
   Same greyscale-until-hover treatment as the homepage marquee. */
.hw-logos{
  list-style:none;margin:0;padding:0;align-self:center;
  /* Fixed columns, never wrapping flex: any wrapping layout strands a logo on
     its own row at some width — measured at 940 and 390 — and one lonely mark
     reads as a mistake. 3x2 rather than one row of six, which is what lets each
     mark render ~35% taller in the same column. */
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(18px,2.4vw,32px) clamp(10px,1.6vw,26px);
  align-items:center;justify-items:center;
}
.hw-logos img{
  /* width-driven so each mark fills its column and they stay optically equal
     (every source is 240x100); max-height stops them ballooning on wide screens */
  width:100%;height:auto;max-height:clamp(30px,3.1vw,46px);object-fit:contain;
  /* these PNGs are RGB with a solid white ground (no alpha), so on the tinted
     card they read as white boxes — multiply drops the white out */
  mix-blend-mode:multiply;
  filter:grayscale(1);opacity:.6;
  transition:filter .35s var(--ease),opacity .35s var(--ease),transform .35s var(--ease);
}
/* the SVG has real transparency — multiply is only needed to knock the white
   ground out of the PNGs, and on a transparent mark it just darkens it */
.hw-logos img[src$=".svg"]{mix-blend-mode:normal}
/* Scality is a 3.6 aspect against everyone else's 2.4, so at a matched cap
   height it renders half again as wide and dominates the block. Trimming its
   cap is what evens the optical weight — in the old single row the same aspect
   caused the opposite problem and needed a WIDER cell. */
.hw-logos img[src$="scality.svg"]{max-height:clamp(25px,2.5vw,37px)}
.hw-logos img:hover{filter:none;opacity:1;transform:scale(1.06)}
@media (prefers-reduced-motion:reduce){
  .hw-logos img:hover{transform:none}
}

@media (max-width:900px){
  .duo-grid{grid-template-columns:minmax(0,1fr)}
  .hw-inner{grid-template-columns:minmax(0,1fr)}
  /* 3x2 survives the stack — six logos divide evenly, so nothing is stranded */
  .hw-logos{margin-top:4px}
}

/* ============================================================
   AI SPARKLES  — opt-in hero overlay (AI Storage page)
   Sits between the photo (z-index -2) and the copy card (z-index 2),
   so the sparks read as coming off the racks without ever crossing
   the text. Pure CSS: one masked <i> per spark, no canvas, no JS.
   ============================================================ */
.hero-sparks{
  position:absolute;inset:0;z-index:-1;pointer-events:none;
  /* the four-point "AI" star, drawn once and reused as a mask */
  --spark-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 0c1 7 4 10 12 12-8 2-11 5-12 12-1-7-4-10-12-12C8 10 11 7 12 0Z' fill='black'/></svg>");
}
.hero-sparks i{
  position:absolute;
  left:calc(var(--x) * 1%);
  top:calc(var(--y) * 1%);
  width:calc(var(--s) * 1px);
  height:calc(var(--s) * 1px);
  background:var(--spark-col, #dff4ff);
  -webkit-mask:var(--spark-mask) center / contain no-repeat;
          mask:var(--spark-mask) center / contain no-repeat;
  opacity:0;
  /* two shadows: a tight core so the star keeps its points, and a wide bloom
     so it still reads against the bright sky */
  filter:drop-shadow(0 0 8px rgba(120,215,255,.95))
         drop-shadow(0 0 22px rgba(86,196,246,.6));
  animation:spark var(--dur, 5s) ease-in-out infinite;
  /* NEGATIVE — --d is a starting phase, not a wait. Every spark is already
     mid-cycle on the first frame, so the field is there immediately instead of
     filling in over five seconds. */
  animation-delay:calc(var(--d) * -1s);
  will-change:transform, opacity;
}
/* every other spark takes the brand cyan so the drift reads as two depths */
.hero-sparks i:nth-child(even){--spark-col:#8fe0ff}
.hero-sparks i:nth-child(3n){--spark-col:#ffffff}

/* full brightness is held across the middle half of the cycle — the old curve
   spent most of its life fading, which is what made it easy to miss */
@keyframes spark{
  0%   {opacity:0;  transform:translateY(16px)  scale(.3)   rotate(-25deg)}
  12%  {opacity:1;  transform:translateY(6px)   scale(1.08) rotate(8deg)}
  55%  {opacity:1;  transform:translateY(-16px) scale(.95)  rotate(45deg)}
  100% {opacity:0;  transform:translateY(-58px) scale(.35)  rotate(100deg)}
}

@media (prefers-reduced-motion:reduce){
  /* hold them still and faint rather than removing them — the hero keeps its
     texture without anything moving */
  .hero-sparks i{animation:none;opacity:.5;transform:none}
}

/* Below ~640px the copy card covers the photo: measured across widths, every
   spark is either behind the card or reduced to a couple of points poking past
   its edge. Drop the layer rather than run 33 animations on a phone for two
   stray specks. */
@media (max-width:639px){ .hero-sparks{display:none} }

/* ============================================================
   DURABILITY FIGURE — 99.9% grows a nine at a time to fourteen
   The card lets it overflow on purpose; .advantages is already
   overflow:hidden for the parallax, so the page can never gain a
   horizontal scrollbar no matter how long the number gets.
   ============================================================ */
/* The number stays INSIDE the card; the card itself widens as the figure grows.
   min-width:0 keeps the grid track at its fr share (a grid item's automatic
   minimum is its min-content width, so without this the nowrap figure just
   stretched its own column and shoved the whole row around). justify-self:start
   plus an explicit width from JS lets the card grow rightward on its own,
   without moving its neighbours. */
.bento-cell.has-nines{
  overflow:hidden;min-width:0;justify-self:start;
  transition:width .34s var(--ease);
}
/* .bento-cell p (0,1,1) sets colour and font-size on every paragraph in a card
   and outranked a bare .b-nines (0,1,0) — the figure rendered in body grey.
   Qualifying with the cell wins the cascade without !important. */
.bento-cell .b-nines{
  font-family:var(--font-main);font-weight:600;
  letter-spacing:-.035em;line-height:1;color:var(--brand-sky);
  padding:clamp(22px,2.2vw,30px) 18px 0 clamp(22px,2.2vw,30px);
  white-space:nowrap;
  font-size:2.4rem;          /* JS measures and overwrites this */
}
.b-nines .nines-fig{display:inline-block}
.b-nines .d{display:inline-block;transform-origin:50% 78%}
.b-nines .pc{display:inline-block;font-size:.6em;margin-left:.04em}

/* only the nine that just arrived carries this class */
.b-nines .d.in{animation:nine-pop .46s cubic-bezier(.2,.9,.25,1.15) both}
@keyframes nine-pop{
  0%  {opacity:0;transform:translateY(-.22em) scale(.5);filter:blur(3px)}
  55% {opacity:1;transform:translateY(0) scale(1.16);filter:blur(0)}
  100%{opacity:1;transform:none}
}
/* the whole figure gives a little each time it lengthens */
.b-nines.grow{animation:nine-nudge .46s var(--ease)}
@keyframes nine-nudge{50%{transform:translateX(-.012em) scale(1.012)}}

/* lands with a glow once it reaches fourteen */
.b-nines.done .nines-fig{animation:nine-land 1.05s var(--ease)}
@keyframes nine-land{
  0%  {text-shadow:0 0 0 rgba(44,171,226,0)}
  35% {text-shadow:0 0 30px rgba(44,171,226,.6)}
  100%{text-shadow:0 0 0 rgba(44,171,226,0)}
}

@media (prefers-reduced-motion:reduce){
  .b-nines .d.in,.b-nines.grow,.b-nines.done .nines-fig{animation:none}
}

/* ---- AI storage: seven cards, because the durability figure earned its own ----
   Every cell is two columns wide here, so the plain-text cards that were 343px
   get room and the figure gets a proper stage. Four rows instead of three. */
.b-extra{grid-area:extra}
@media (min-width:1021px){
  .bento.bento-seven{
    grid-template-columns:repeat(4,1fr);
    grid-template-areas:
      "roi   roi   perf  perf"
      "roi   roi   peace peace"
      "sec   sec   extra extra"
      "cloud cloud eff   eff";
  }
}
@media (max-width:1020px){
  .bento.bento-seven{
    grid-template-columns:repeat(2,1fr);
    grid-template-areas:"roi roi" "perf perf" "peace peace" "sec sec" "extra extra" "cloud cloud" "eff eff";
  }
}
@media (max-width:560px){
  .bento.bento-seven{
    grid-template-columns:minmax(0,1fr);
    grid-template-areas:"roi" "perf" "peace" "sec" "extra" "cloud" "eff";
  }
}
/* figure-only card: the number and its caption, nothing else */
.b-peace.has-nines{justify-content:center;padding-bottom:clamp(22px,2.2vw,30px)}

/* plain-English gloss under the durability caption */
.bento-cell .b-nines-note{
  margin:10px 0 0;
  padding:0 clamp(22px,2.2vw,30px);
  max-width:56ch;
  font-size:.95rem;line-height:1.6;color:var(--ink-soft);
}

/* ============================================================
   STAT ROW  (inner pages, doc block 7)
   The homepage carries these four figures inside the full White Glove block —
   eyebrow, paragraph, engineer photo, then the tiles. On an inner page that
   copy repeats the .dive section directly above it, so this is the tiles ONLY:
   a short dark band that breaks the run of light sections and hands off into
   the consultation block. Same dark grey ramp as White Glove, reversed so the
   seam with the light section above is the light end.
   ============================================================ */
.statrow{
  position:relative;overflow:hidden;isolation:isolate;
  padding:clamp(56px,6vw,88px) var(--sec-x);
  background:linear-gradient(180deg,var(--grey-800) 0%,var(--grey-900) 100%);
  color:#fff;
}
.sr-bg{position:absolute;inset:0;z-index:-1;pointer-events:none}
.sr-glow{
  position:absolute;width:720px;height:720px;top:-360px;left:50%;translate:-50% 0;
  border-radius:50%;filter:blur(110px);opacity:.42;
  background:radial-gradient(circle,rgba(42,196,244,.32),transparent 66%);
}
.sr-inner{max-width:var(--wrap);margin:0 auto}
.sr-eyebrow{
  display:flex;align-items:center;gap:12px;justify-content:center;
  font-family:var(--font-label);font-size:.78rem;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:#a5e4fb;margin-bottom:clamp(28px,3vw,40px);
}
.sr-eyebrow::before,.sr-eyebrow::after{content:"";height:1.5px;width:34px;background:currentColor}
.sr-list{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;list-style:none}
.sr-list[data-n="5"]{grid-template-columns:repeat(5,1fr)}
.sr-list li{
  position:relative;text-align:center;
  padding:clamp(22px,2.2vw,30px) 16px;border-radius:20px;
  background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.14);
  opacity:0;translate:0 20px;
  transition:opacity .6s var(--ease),translate .6s var(--ease),
             border-color .35s var(--ease),background .35s var(--ease);
}
.statrow.in .sr-list li{opacity:1;translate:0;transition-delay:calc(var(--i,0)*80ms)}
.sr-list li:hover{background:rgba(42,196,244,.09);border-color:rgba(42,196,244,.45)}
/* .gs-num is a flex row — centre it here, it is left-aligned inside .glove */
.sr-list .gs-num{justify-content:center;font-size:clamp(2rem,3vw,2.9rem)}
.sr-list .gs-label{margin-top:10px;font-size:.84rem;color:rgba(255,255,255,.82)}

@media (max-width:900px){
  .sr-list,.sr-list[data-n="5"]{grid-template-columns:repeat(2,1fr)}
  /* five figures into two columns leaves the last one stranded half-width
     beside a gap — let it take the full row instead */
  .sr-list[data-n="5"] li:last-child{grid-column:1 / -1}
}
@media (max-width:520px){
  .sr-list,.sr-list[data-n="5"]{grid-template-columns:minmax(0,1fr)}
}
@media (prefers-reduced-motion:reduce){
  .sr-list li{opacity:1!important;translate:none!important}
}
/* a decimal tail is part of the figure, not a unit — full size, no gap */
.gs-num.gs-dec .plus{font-size:1em;margin-left:0}

/* Partner page, doc block 3 — that section's brief gives it an intro line the
   industry briefs don't have. */
.adv-intro{
  margin-top:16px;max-width:70ch;
  font-size:clamp(1.02rem,1.25vw,1.14rem);line-height:1.66;color:var(--ink-soft);
}
/* Partner page, doc block 5 — the closing line under the support highlights. */
.dive-close{
  margin-top:22px;
  font-size:.98rem;line-height:1.66;color:var(--ink-soft);
}

/* The partner hero uses the doc's own CTA labels ("Explore Program Options"),
   which need 511px against the card's 503px — so the pair wrapped at 1440 but
   sat side by side at 1024, which read as an accident. Slightly tighter padding
   inside the hero card buys the 16px; other heroes lose 4px a side, unnoticeably. */
.hero-card .btn{--pad-x:22px}

/* ============================================================
   NET-ZERO SPROUT  (partner page — replaces the leaf icon on one card)
   Stands in for the sprite glyph inside the icon tile and grows up out of it,
   past the top of the card. Seven leaves: six alternating up a tapered stem,
   largest at the base and shrinking toward the top, plus a terminal leaf.
   ============================================================ */
.uc-card.has-plant{overflow:visible}
.has-plant .uc-ic{overflow:visible;position:relative}

.has-plant .uc-plant{
  position:absolute;bottom:3px;left:50%;
  /* the `translate` property, so `transform` stays free for the sway */
  translate:-50% 0;
  height:clamp(124px,13vw,192px);width:auto;aspect-ratio:100/212;
  overflow:visible;pointer-events:none;
  transform-origin:50% 100%;will-change:transform;
}
/* stroke:none matters — .uc-ic svg sets stroke:currentColor for the sprite
   line-icons and the shapes inherit it, which outlined everything in blue */
.uc-plant .st,.uc-plant .bl{fill:var(--brand-green);stroke:none}
.uc-plant .vn{
  fill:none;stroke:#fff;stroke-width:7;opacity:.42;stroke-linecap:round;
  /* dasharray is in the leaf's LOCAL space, before the placement scale, so one
     value covers every leaf however large it renders */
  stroke-dasharray:100;stroke-dashoffset:100;
}
/* The stem is a filled taper, so it cannot be drawn with stroke-dashoffset.
   This rect clips it; parked a full canvas below, it slides up to reveal the
   stem from the base — which is how the plant actually grows. */
.uc-plant .stem-mask{transform:translateY(212px)}
/* the leaf path is authored with its base at 0,0, so the unfurl scales from the
   exact point where it joins the stem — no transform-box guesswork */
.uc-plant .lf{transform:scale(.03);transform-origin:0 0;will-change:transform}

/* Timing. .in fires at 28% of the section visible, which is well before the
   plant is actually in front of you — so every delay below carries a flat
   +.25s hold, and the growth runs at .64x speed (two 25% passes) (durations AND the stagger between
   leaves, or slowing one without the other just changes the rhythm). */
.usecases.in .has-plant .stem-mask{animation:stemGrow 2.98s cubic-bezier(.36,.66,.3,1) .64s forwards}
.usecases.in .has-plant .lf1{animation:leafUnfurl 1.29s cubic-bezier(.26,.92,.3,1) 1.23s forwards}
.usecases.in .has-plant .lf2{animation:leafUnfurl 1.29s cubic-bezier(.26,.92,.3,1) 1.56s forwards}
.usecases.in .has-plant .lf3{animation:leafUnfurl 1.29s cubic-bezier(.26,.92,.3,1) 1.91s forwards}
.usecases.in .has-plant .lf4{animation:leafUnfurl 1.29s cubic-bezier(.26,.92,.3,1) 2.25s forwards}
.usecases.in .has-plant .lf5{animation:leafUnfurl 1.29s cubic-bezier(.26,.92,.3,1) 2.6s forwards}
.usecases.in .has-plant .lf6{animation:leafUnfurl 1.29s cubic-bezier(.26,.92,.3,1) 2.94s forwards}
.usecases.in .has-plant .lf7{animation:leafUnfurl 1.41s cubic-bezier(.26,.94,.3,1) 3.31s forwards}
.usecases.in .has-plant .lf1 .vn{animation:veinDraw .79s ease-out 1.91s forwards}
.usecases.in .has-plant .lf2 .vn{animation:veinDraw .79s ease-out 2.25s forwards}
.usecases.in .has-plant .lf3 .vn{animation:veinDraw .79s ease-out 2.6s forwards}
.usecases.in .has-plant .lf4 .vn{animation:veinDraw .79s ease-out 2.94s forwards}
.usecases.in .has-plant .lf5 .vn{animation:veinDraw .79s ease-out 3.29s forwards}
.usecases.in .has-plant .lf6 .vn{animation:veinDraw .79s ease-out 3.63s forwards}
.usecases.in .has-plant .lf7 .vn{animation:veinDraw .79s ease-out 4s forwards}
/* sway starts at 4.9s — after the last vein finishes at 4.79s, so the idle
   loop never overlaps the growth */
.usecases.in .has-plant .uc-plant{animation:plantSway 10.94s ease-in-out 4.9s infinite}

@keyframes stemGrow{to{transform:translateY(0)}}
@keyframes veinDraw{to{stroke-dashoffset:0}}
/* 0 -> overshoot -> settle: the overshoot is what reads as unfurling rather
   than inflating */
@keyframes leafUnfurl{
  0%   {transform:scale(.03) rotate(-22deg)}
  32%  {transform:scale(.56) rotate(-9deg)}
  60%  {transform:scale(1.06) rotate(3.5deg)}
  80%  {transform:scale(.98) rotate(-1deg)}
  100% {transform:scale(1) rotate(0deg)}
}
/* MUST begin and end at the resting value: a sway starting at -2deg snapped the
   whole plant sideways the instant it began, and again on every loop */
@keyframes plantSway{
  0%   {transform:rotate(0deg)}
  25%  {transform:rotate(1.8deg)}
  50%  {transform:rotate(0deg)}
  75%  {transform:rotate(-1.8deg)}
  100% {transform:rotate(0deg)}
}

@media (prefers-reduced-motion:reduce){
  .uc-plant .vn{stroke-dashoffset:0}
  .uc-plant .lf{transform:scale(1)}
  .uc-plant .stem-mask{transform:translateY(0)}
  .usecases.in .has-plant .stem-mask,.usecases.in .has-plant .lf,
  .usecases.in .has-plant .vn,.usecases.in .has-plant .uc-plant{animation:none}
}

/* ============================================================================
   BLOG ARTICLE TEMPLATE  ·  long-form editorial layout
   Poppins headings + IBM Plex Sans reading body, brand blue→green accents,
   sticky table of contents, reading-progress bar. Reused across every post.
   ========================================================================== */
.article{--measure:720px;--art-wide:880px;background:var(--paper)}

/* reading-progress bar — brand blue→green (matches brand-guideline gradient) */
.reading-progress{position:fixed;top:0;left:0;right:0;height:3px;z-index:1200;pointer-events:none;background:transparent}
.reading-progress i{display:block;height:100%;width:0;transform-origin:0 50%;
  background:linear-gradient(90deg,var(--brand-sky),var(--brand-green))}

/* ---- masthead ---- */
.article-head{position:relative;padding:clamp(94px,12vh,138px) var(--sec-x) clamp(26px,4.5vh,44px);
  background:radial-gradient(125% 135% at 50% 0%,#e9f6fd 0%,var(--paper) 60%)}
.article-head-inner{max-width:var(--art-wide);margin:0 auto;text-align:center}
.article-crumb{display:flex;gap:9px;justify-content:center;align-items:center;flex-wrap:wrap;
  font-family:var(--font-label);font-size:.78rem;font-weight:500;color:var(--ink-faint);margin:0 0 20px}
.article-crumb a{color:var(--ink-faint);text-decoration:none;transition:color .2s var(--ease)}
.article-crumb a:hover{color:var(--brand-deep)}
.article-crumb i{opacity:.45;font-style:normal}
.article-cat{display:inline-block;font-family:var(--font-label);font-size:.73rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--brand-deep);background:#d6eefa;
  border-radius:100px;padding:6px 15px;margin:0 0 20px}
.article-title{font-family:var(--font-main);font-weight:600;letter-spacing:-.022em;
  font-size:clamp(2.05rem,4.5vw,3.1rem);line-height:1.1;color:var(--ink);margin:0 auto 24px;max-width:17ch;
  text-wrap:balance}
.article-meta{display:flex;flex-wrap:wrap;gap:9px 16px;justify-content:center;align-items:center;
  font-family:var(--font-label);font-size:.87rem;color:var(--ink-soft)}
.article-byline{display:inline-flex;align-items:center;gap:10px;font-weight:600;color:var(--ink)}
.byline-mark{width:30px;height:30px;border-radius:50%;flex:none;display:grid;place-items:center;
  background:var(--brand-sky);color:#fff;font-family:var(--font-main);font-weight:600;font-size:.8rem;letter-spacing:.01em}
.article-meta .dot{width:3px;height:3px;border-radius:50%;background:var(--ink-faint);opacity:.55}

/* ---- cover ---- */
.article-cover{max-width:calc(var(--art-wide) * .8);margin:0 auto;padding:0 var(--sec-x)}
.article-cover img{display:block;width:100%;aspect-ratio:2/1;object-fit:cover;
  border-radius:clamp(16px,2.3vw,28px);box-shadow:var(--shadow-md)}

/* ---- reading zone: sticky TOC + body ---- */
.article-grid{max-width:1084px;margin:0 auto;
  padding:clamp(42px,6vh,66px) var(--sec-x) clamp(18px,4vh,38px);
  display:grid;grid-template-columns:220px minmax(0,1fr);gap:clamp(34px,4.4vw,60px);align-items:start}
.article-body{max-width:var(--measure);overflow-wrap:anywhere}

.article-toc{position:sticky;top:104px}
.toc-box{border:0}
.toc-box>summary{list-style:none;cursor:default;font-family:var(--font-label);font-size:.72rem;
  font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:var(--ink-faint);margin:0 0 14px}
.toc-box>summary::-webkit-details-marker{display:none}
.toc-box>summary::marker{content:""}
.article-toc ol{list-style:none;margin:0;padding:0;border-left:2px solid var(--line)}
.article-toc a{display:block;font-family:var(--font-label);font-size:.9rem;line-height:1.4;
  color:var(--ink-soft);text-decoration:none;padding:8px 0 8px 17px;margin-left:-2px;
  border-left:2px solid transparent;transition:color .2s var(--ease),border-color .2s var(--ease)}
.article-toc a:hover{color:var(--brand-deep)}
.article-toc a.active{color:var(--brand-deep);border-left-color:var(--brand-sky);font-weight:600}

/* ---- body typography (IBM Plex Sans reading face) ---- */
.article-body{font-family:var(--font-label);color:var(--ink-soft);font-size:1.06rem;line-height:1.8}
.article-body>p{margin:0 0 1.35em}
.article-body>p:first-of-type{font-size:1.24rem;line-height:1.62;color:var(--ink);margin-bottom:1.1em}
.article-body>p:first-of-type strong{font-weight:500}          /* neutralise the source's all-bold lead */
.article-body a{color:var(--brand-deep);text-decoration:underline;text-decoration-thickness:1.5px;
  text-underline-offset:2.5px;text-decoration-color:rgba(23,120,159,.34);
  transition:color .2s var(--ease),text-decoration-color .2s var(--ease)}
.article-body a:hover{color:var(--leaf-deep);text-decoration-color:var(--leaf)}
.article-body strong{color:var(--ink);font-weight:600}
.article-body em{font-style:italic}

.article-body h2{font-family:var(--font-main);font-weight:600;letter-spacing:-.015em;
  font-size:clamp(1.5rem,2.6vw,2rem);line-height:1.22;color:var(--ink);
  margin:1.9em 0 .55em;scroll-margin-top:98px;position:relative}
.article-body h2::before{content:"";position:absolute;left:-22px;top:.34em;width:9px;height:9px;
  border-radius:2px;background:var(--brand-green);transform:rotate(45deg)}
.article-body h3{font-family:var(--font-main);font-weight:600;font-size:1.24rem;line-height:1.3;
  color:var(--ink);margin:1.7em 0 .5em;scroll-margin-top:98px}

/* ---- lists ---- */
.article-body ul,.article-body ol{margin:0 0 1.5em;padding:0;list-style:none}
.article-body li{position:relative;padding-left:30px;margin:0 0 .68em;line-height:1.72}
.article-body ul>li::before{content:"";position:absolute;left:6px;top:.62em;width:8px;height:8px;
  border-radius:2px;background:var(--brand-green);transform:rotate(45deg)}
.article-body ol{counter-reset:oi}
.article-body ol>li{counter-increment:oi;padding-left:38px}
.article-body ol>li::before{content:counter(oi);position:absolute;left:0;top:.02em;width:24px;height:24px;
  border-radius:50%;background:#d9eff9;color:var(--brand-deep);font-family:var(--font-label);
  font-weight:600;font-size:.8rem;display:grid;place-items:center}

/* ---- figures, quotes, tables ---- */
.article-figure{margin:2.1em 0;text-align:center}
.article-figure img{width:100%;border-radius:clamp(14px,1.8vw,20px);box-shadow:var(--shadow-sm)}
.article-figure figcaption{font-family:var(--font-label);font-size:.85rem;color:var(--ink-faint);
  font-style:italic;margin-top:12px;line-height:1.5}
.article-body blockquote{margin:1.9em 0;padding:.2em 0 .2em 26px;border-left:4px solid var(--brand-green)}
.article-body blockquote p{font-family:var(--font-main);font-weight:400;font-style:italic;
  font-size:1.34rem;line-height:1.5;color:var(--ink);margin:0}
.article-table{overflow-x:auto;margin:1.7em 0}
.article-table table{border-collapse:collapse;width:100%;font-family:var(--font-label);font-size:.94rem}
.article-table td{border:1px solid var(--line);padding:10px 14px;color:var(--ink-soft);text-align:left;vertical-align:top}
.article-table tr:first-child td{background:#f1f9fd;color:var(--ink);font-weight:600}

/* ---- end matter ---- */
.article-end{max-width:var(--measure);margin:0 auto;padding:10px var(--sec-x) clamp(52px,7vh,84px)}
.article-end-rule{height:1px;background:var(--line);margin:0 0 30px}
.author-card{display:flex;gap:16px;align-items:center;background:var(--white);border:1px solid var(--line-soft);
  border-radius:20px;padding:20px 22px;box-shadow:var(--shadow-sm)}
.author-card .byline-mark{width:48px;height:48px;font-size:1.15rem}
.author-card h4{font-family:var(--font-main);font-weight:600;font-size:1.05rem;color:var(--ink);margin:0 0 3px}
.author-card p{font-family:var(--font-label);font-size:.9rem;color:var(--ink-soft);line-height:1.55;margin:0}
.article-back{display:inline-flex;align-items:center;gap:8px;margin-top:28px;font-family:var(--font-label);
  font-weight:600;font-size:.9rem;color:var(--brand-deep);text-decoration:none;transition:gap .2s var(--ease)}
.article-back:hover{gap:13px}

@media (max-width:980px){
  /* ⚠️ minmax(0,…) NOT 1fr. A bare `1fr` is minmax(AUTO,1fr), so the column
     cannot shrink below its widest unbreakable token — one post pastes a
     112-character URL as a citation, which pushed the column to 588px inside a
     360px phone and gave 25 blog posts a horizontal scrollbar. The desktop rule
     above already had minmax(0,1fr); this override was quietly undoing it. */
  .article-grid{grid-template-columns:minmax(0,1fr);max-width:var(--measure);gap:0}
  .article-toc{position:static;top:auto;margin:0 0 28px}
  .toc-box{border:1px solid var(--line-soft);border-radius:14px;padding:14px 18px;background:var(--white)}
  .toc-box>summary{cursor:pointer;margin:0;display:flex;align-items:center;justify-content:space-between}
  .toc-box>summary::after{content:"";width:8px;height:8px;border-right:2px solid var(--ink-faint);
    border-bottom:2px solid var(--ink-faint);transform:rotate(45deg);transition:transform .2s var(--ease)}
  .toc-box[open]>summary::after{transform:rotate(-135deg)}
  .toc-box[open]>ol{margin-top:12px}
}
@media (prefers-reduced-motion:reduce){
  .reading-progress i{transition:none}
  .article-back,.article-toc a{transition:none}
}

/* ============================================================================
   BLOG ARCHIVE  ·  /blog  (+ /blog/page/N)
   Card grid of posts, 25 per page, with pagination. Shares the article
   template's tokens so the archive and the posts read as one system.
   ========================================================================== */
.blog-head{position:relative;overflow:hidden;text-align:center;
  /* taller than a normal masthead on purpose: the cloud layer needs room to
     read before it melts into the blue, the way the Outcomes section does */
  padding:clamp(120px,17vh,205px) var(--sec-x) clamp(76px,10vh,120px);
  background-color:#e1f0f9;                 /* matches the image's faded blue */
  --adv-par:0px;                            /* set by the shared cloud-parallax JS */
}
/* same cloud layer as the Outcomes section, melting into the blue field below */
.blog-head::before{
  content:"";position:absolute;left:0;right:0;top:-14%;height:128%;
  background-image:
    linear-gradient(to bottom, rgba(225,240,249,0) 50%, #e1f0f9 73%),
    url("images/adv-bg.jpg?v=2");
  background-size:100% 100%, 135% auto;
  background-position:top center, top center;
  background-repeat:no-repeat, no-repeat;
  transform:translate3d(0,var(--adv-par),0);
  will-change:transform;z-index:0;pointer-events:none;
}
.blog-head-inner{position:relative;z-index:1;max-width:760px;margin:0 auto}
.blog-title{font-family:var(--font-main);font-weight:600;letter-spacing:-.022em;
  font-size:clamp(2.1rem,4.6vw,3.1rem);line-height:1.1;color:var(--ink);margin:0 0 14px}
.blog-sub{font-family:var(--font-label);font-size:clamp(1rem,1.4vw,1.15rem);line-height:1.6;
  color:var(--ink-soft);margin:0}

.blog-wrap{background:#e1f0f9;padding:clamp(34px,5vh,54px) var(--sec-x) clamp(60px,8vh,96px)}
.blog-grid{max-width:var(--wrap);margin:0 auto;display:grid;gap:clamp(22px,2.6vw,34px);
  grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}

.blog-card{display:flex;flex-direction:column;background:var(--white);border:1px solid var(--line-soft);
  border-radius:clamp(14px,1.6vw,20px);overflow:hidden;box-shadow:var(--shadow-sm);
  transition:transform .25s var(--ease),box-shadow .25s var(--ease)}
.blog-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-md)}
.bc-media{display:block;aspect-ratio:16/9;overflow:hidden;background:var(--sky-100)}
.bc-media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .5s var(--ease)}
.blog-card:hover .bc-media img{transform:scale(1.04)}
.bc-body{display:flex;flex-direction:column;flex:1;padding:clamp(18px,2vw,24px)}
.bc-cat{align-self:flex-start;font-family:var(--font-label);font-size:.7rem;font-weight:600;
  letter-spacing:.13em;text-transform:uppercase;color:var(--brand-deep);background:#d6eefa;
  border-radius:100px;padding:5px 12px;margin:0 0 12px}
.bc-title{font-family:var(--font-main);font-weight:600;font-size:1.12rem;line-height:1.32;
  letter-spacing:-.01em;margin:0 0 10px}
.bc-title a{color:var(--ink);text-decoration:none;transition:color .2s var(--ease)}
.bc-title a:hover{color:var(--brand-deep)}
.bc-excerpt{font-family:var(--font-label);font-size:.94rem;line-height:1.62;color:var(--ink-soft);
  margin:0 0 16px}
/* date + read time is real content, so it takes --ink-soft (7.4:1 on the card)
   not --ink-faint, which measures 3.26:1 against a 4.5 body minimum. The dot
   between them is decorative and keeps the faint grey. */
.bc-meta{margin-top:auto;display:flex;align-items:center;gap:9px;font-family:var(--font-label);
  font-size:.82rem;color:var(--ink-soft)}
.bc-meta .dot{width:3px;height:3px;border-radius:50%;background:var(--ink-faint);opacity:.6}

/* pagination */
.pagination{max-width:var(--wrap);margin:clamp(40px,5vh,60px) auto 0;display:flex;justify-content:center;
  align-items:center;gap:8px;flex-wrap:wrap}
.pg-link,.pg-current{font-family:var(--font-label);font-size:.92rem;font-weight:600;
  min-width:42px;height:42px;padding:0 14px;border-radius:100px;display:inline-flex;
  align-items:center;justify-content:center;text-decoration:none;
  transition:background .2s var(--ease),color .2s var(--ease),border-color .2s var(--ease)}
.pg-link{color:var(--ink-soft);background:var(--white);border:1px solid var(--line-soft)}
.pg-link:hover{color:var(--brand-deep);border-color:var(--brand-sky)}
.pg-current{color:#fff;background:var(--brand-sky);border:1px solid var(--brand-sky);cursor:default}
.pg-gap{color:var(--ink-faint);padding:0 4px}
.pg-edge{gap:7px}
@media (prefers-reduced-motion:reduce){
  .blog-card,.blog-card:hover,.bc-media img,.blog-card:hover .bc-media img{transition:none;transform:none}
}

/* blog card "Read more" — their own label from the live archive */
.bc-more{align-self:flex-start;display:inline-flex;align-items:center;gap:8px;margin-top:16px;
  font-family:var(--font-label);font-size:.86rem;font-weight:600;text-decoration:none;
  color:var(--brand-deep);background:var(--white);border:1px solid var(--line);
  border-radius:100px;padding:9px 18px;
  transition:background .2s var(--ease),color .2s var(--ease),border-color .2s var(--ease)}
.bc-more:hover{background:var(--brand-sky);border-color:var(--brand-sky);color:#fff}
.bc-more svg{transition:transform .3s var(--ease)}
.bc-more:hover svg{transform:translateX(3px)}
@media (prefers-reduced-motion:reduce){.bc-more,.bc-more svg{transition:none}}

/* ============================================================================
   FAQ ACCORDION  ·  reusable component (see _build/components.py: faq())
   Built on <details>/<summary>: opens without JS, keyboard accessible.
   The design is recycled; the questions are passed in per page.
   ========================================================================== */
/* Transparent on purpose: the accordion is a REUSABLE component, so it takes
   whatever background the section it sits in provides. It used to paint
   --paper itself, which showed as a mismatched slab the moment it was
   dropped into a grey section on /about-opus/our-certifications/. */
.faqs{padding:var(--sec-y) var(--sec-x);background:transparent}
.faq-inner{max-width:860px;margin:0 auto}
.faq-head{text-align:center;margin:0 auto clamp(38px,4.5vw,60px);max-width:660px}
.faq-eyebrow{font-family:var(--font-label);font-size:.78rem;font-weight:600;letter-spacing:.18em;
  text-transform:uppercase;color:var(--brand-deep);margin:0 0 12px}
.faq-title{font-family:var(--font-main);font-weight:600;letter-spacing:-.02em;
  font-size:clamp(1.7rem,3vw,2.4rem);line-height:1.16;color:var(--ink);margin:0 0 14px}
.faq-intro{font-family:var(--font-label);font-size:1.02rem;line-height:1.7;color:var(--ink-soft);margin:0}

.faq-list{display:flex;flex-direction:column;gap:12px}
.faq-item{background:var(--white);border:1px solid var(--line-soft);border-radius:16px;
  box-shadow:var(--shadow-sm);overflow:hidden;
  transition:border-color .25s var(--ease),box-shadow .25s var(--ease)}
.faq-item[open]{border-color:var(--brand-sky);box-shadow:var(--shadow-md)}

.faq-q{list-style:none;cursor:pointer;display:flex;align-items:flex-start;justify-content:space-between;
  gap:20px;padding:clamp(16px,1.8vw,21px) clamp(18px,2vw,26px);
  font-family:var(--font-main);font-weight:600;font-size:clamp(1rem,1.25vw,1.1rem);
  line-height:1.45;color:var(--ink);transition:color .2s var(--ease)}
.faq-q::-webkit-details-marker{display:none}
.faq-q::marker{content:""}
.faq-q:hover{color:var(--brand-deep)}
.faq-item[open] .faq-q{color:var(--brand-deep)}

/* plus → minus */
.faq-ic{position:relative;flex:none;width:22px;height:22px;margin-top:2px;border-radius:50%;
  background:#d6eefa;transition:background .25s var(--ease),transform .3s var(--ease)}
.faq-ic::before,.faq-ic::after{content:"";position:absolute;left:50%;top:50%;background:var(--brand-deep);
  border-radius:2px;transform:translate(-50%,-50%);transition:opacity .25s var(--ease),background .25s var(--ease)}
.faq-ic::before{width:10px;height:2px}
.faq-ic::after{width:2px;height:10px}
.faq-item[open] .faq-ic{background:var(--brand-sky);transform:rotate(180deg)}
.faq-item[open] .faq-ic::before{background:#fff}
.faq-item[open] .faq-ic::after{opacity:0}

.faq-a{padding:0 clamp(18px,2vw,26px) clamp(18px,2vw,24px);
  font-family:var(--font-label);font-size:1rem;line-height:1.72;color:var(--ink-soft);
  animation:faqIn .28s var(--ease)}
.faq-a>*:last-child{margin-bottom:0}
.faq-a p{margin:0 0 12px}
.faq-a a{color:var(--brand-deep);text-decoration:underline;text-underline-offset:2px}
.faq-a a:hover{color:var(--leaf-deep)}
.faq-a ul,.faq-a ol{margin:0 0 12px;padding-left:22px}
.faq-a li{margin:0 0 6px}
@keyframes faqIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}

@media (prefers-reduced-motion:reduce){
  .faq-a{animation:none}
  .faq-item,.faq-ic,.faq-ic::before,.faq-ic::after,.faq-q{transition:none}
}

/* ============================================================================
   ABOUT PAGE  ·  /about-opus  (see _build/about.py)
   Reuses the Bright Field system (tokens, Poppins/IBM Plex, card radii, --sec-y)
   in a composition of its own, per the inner-page rule.
   ========================================================================== */
/* intro + quick facts */
.abt-intro{padding:var(--sec-y) var(--sec-x);background:var(--paper)}
.abt-grid{max-width:var(--wrap);margin:0 auto;display:grid;gap:clamp(36px,5vw,72px);
  grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);align-items:center}
.abt-copy p{font-family:var(--font-label);font-size:1.06rem;line-height:1.78;color:var(--ink-soft);margin:0 0 22px}
/* :not(.btn) — the inline-link treatment was also repainting the CTA button's
   label brand-deep-on-brand-sky and underlining it */
.abt-copy a:not(.btn){color:var(--brand-deep);text-decoration:underline;text-underline-offset:2.5px;
  text-decoration-color:rgba(23,120,159,.34);transition:color .2s var(--ease)}
.abt-copy a:not(.btn):hover{color:var(--leaf-deep)}
.abt-copy .abt-sig{font-family:var(--font-main);font-weight:600;color:var(--ink);font-size:1.12rem}
.qf{margin:30px 0 0;padding:0;list-style:none;border-top:1px solid var(--line-soft)}
.qf li{display:flex;justify-content:space-between;gap:18px;align-items:baseline;
  padding:13px 0;border-bottom:1px solid var(--line-soft);font-family:var(--font-label)}
.qf dt,.qf .qf-k{font-size:.78rem;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-faint)}
.qf .qf-v{font-family:var(--font-main);font-weight:600;font-size:1.02rem;color:var(--ink);text-align:right}
.abt-media{position:relative}
.abt-media img{width:100%;height:auto;aspect-ratio:3/4;object-fit:cover;
  border-radius:clamp(18px,2.4vw,30px);box-shadow:var(--shadow-md);display:block}

/* values */
/* Same backdrop as the homepage's "Trusted at scale" band — the gradient and
   the three blurred glow spans are reused verbatim (.proof-bg / .proof-glow
   are NOT scoped under .proof, so the markup works anywhere). Reused rather
   than copied so the two bands cannot drift apart.
   position/overflow/isolation are load-bearing: the glows are absolutely
   positioned and oversized, so without them they escape the section. */
/* The background now comes from the library (see components.background and
   _build/PAGE-RULES.md rule 8), so this rule carries spacing only. */
.values{padding:var(--sec-y) var(--sec-x)}
/* --head-gap is a full --sec-y (150px), which is right between two SECTIONS
   but far too much between this heading and its own cards */
.values .oc-head{margin-bottom:clamp(34px,4vw,56px)}
.val-card:hover .uc-ic{background:var(--brand-sky);color:#fff}
.values-inner{max-width:var(--wrap);margin:0 auto}
.val-grid{display:grid;gap:clamp(18px,2.2vw,26px);grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
.val-card{background:var(--white);border:1px solid var(--line-soft);border-radius:clamp(16px,1.8vw,22px);
  padding:clamp(24px,2.6vw,32px);box-shadow:var(--shadow-sm);
  transition:transform .25s var(--ease),box-shadow .25s var(--ease)}
.val-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-md)}
.val-card h3{font-family:var(--font-main);font-weight:600;font-size:1.12rem;color:var(--ink);
  margin:0 0 10px}
.val-card p{font-family:var(--font-label);font-size:.98rem;line-height:1.68;color:var(--ink-soft);margin:0}

/* story split */
/* .team above is --paper, and two sections must never share a background.
   Neutral light grey rather than another blue tint, so it reads as a break.
   The hairline that used to do this job is gone — the colour does it now. */
.story{padding:var(--sec-y) var(--sec-x);background:#f2f3f4}
.story-grid{max-width:var(--wrap);margin:0 auto;display:grid;gap:clamp(36px,5vw,72px);
  grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr);align-items:start}
.story-media img{width:100%;height:auto;aspect-ratio:3/4;object-fit:cover;
  border-radius:clamp(18px,2.4vw,30px);box-shadow:var(--shadow-md);display:block}
.story-copy p{font-family:var(--font-label);font-size:1.06rem;line-height:1.78;color:var(--ink-soft);margin:0 0 20px}
.story-lead{font-family:var(--font-main)!important;font-weight:600;font-size:clamp(1.25rem,2vw,1.55rem)!important;
  line-height:1.4!important;color:var(--ink)!important}

/* mission / vision */
/* Mission/Vision live INSIDE the story copy column. Side by side there, so
   they read as a pair and the column stays short; they fall to one column
   once the split itself stacks. align-items:start keeps each card the
   height of its own copy instead of stretching Mission to match Vision. */
.mv-grid{display:grid;gap:clamp(14px,1.6vw,20px);margin-top:clamp(26px,3vw,36px);
  grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}
@media (max-width:860px){.mv-grid{grid-template-columns:minmax(0,1fr)}}
.mv-card{background:var(--white);border:1px solid var(--line-soft);border-radius:clamp(14px,1.6vw,20px);
  padding:clamp(20px,2.2vw,28px);box-shadow:var(--shadow-sm)}
.mv-card .mv-eyebrow{display:flex;align-items:center;gap:10px;
  font-family:var(--font-label);font-size:.76rem;font-weight:600;letter-spacing:.18em;
  text-transform:uppercase;color:var(--brand-deep);margin:0 0 14px}
/* it was the one eyebrow on the page carrying no mark at all */
.mv-card .mv-eyebrow::before{content:"";height:2px;width:14px;flex:none;background:currentColor}
.mv-card p{font-family:var(--font-label);font-size:.98rem;line-height:1.7;color:var(--ink-soft);margin:0}

/* leadership */
.team{padding:var(--sec-y) var(--sec-x);background:var(--paper)}
.team-inner{max-width:var(--wrap);margin:0 auto;text-align:center}
.team-grid{display:grid;gap:clamp(20px,2.6vw,34px);
  grid-template-columns:repeat(auto-fit,minmax(175px,1fr))}
.team-card{text-align:center}
.team-photo{width:100%;max-width:210px;margin:0 auto 18px;aspect-ratio:1;border-radius:50%;
  overflow:hidden;background:var(--sky-100);box-shadow:var(--shadow-sm);
  border:3px solid var(--white);transition:transform .3s var(--ease),box-shadow .3s var(--ease)}
.team-card:hover .team-photo{transform:translateY(-5px);box-shadow:var(--shadow-md)}
.team-photo img{width:100%;height:100%;object-fit:cover;display:block}
.team-card h3{font-family:var(--font-main);font-weight:600;font-size:1.08rem;color:var(--ink);margin:0 0 4px}
.team-role{font-family:var(--font-label);font-size:.85rem;color:var(--brand-deep);font-weight:600;
  letter-spacing:.04em;margin:0}

/* responsibility */
.resp{padding:var(--sec-y) var(--sec-x);background:#eef7fb}
.resp-inner{max-width:var(--wrap);margin:0 auto}
/* heading left, the copy and its CTA right — a single 760px column left the
   right half of the band empty above the cards */
.resp-head{display:grid;gap:clamp(28px,4vw,64px);align-items:start;
  grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr)}
.resp-head p{font-family:var(--font-label);font-size:1.04rem;line-height:1.75;color:var(--ink-soft);margin:0 0 16px}
.resp-copy .oc-eyebrow{margin-bottom:14px}
.resp-cta{margin:26px 0 0}
@media (max-width:860px){.resp-head{grid-template-columns:minmax(0,1fr)}}
.resp-grid{display:grid;gap:clamp(20px,2.4vw,30px);margin-top:clamp(34px,4vw,52px);
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
.resp-card{background:var(--white);border:1px solid var(--line-soft);border-radius:clamp(16px,1.8vw,22px);
  overflow:hidden;box-shadow:var(--shadow-sm);
  transition:transform .25s var(--ease),box-shadow .25s var(--ease)}
.resp-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-md)}
.resp-card img{width:100%;height:auto;aspect-ratio:513/325;object-fit:cover;display:block}
.resp-card h3{font-family:var(--font-main);font-weight:600;font-size:1.06rem;color:var(--ink);
  margin:0;padding:clamp(18px,2vw,24px) clamp(20px,2.2vw,26px);text-align:center}

/* contact */
.abt-contact{padding:var(--sec-y) var(--sec-x);background:var(--paper)}
.ct-grid{max-width:var(--wrap);margin:0 auto;display:grid;gap:clamp(36px,5vw,72px);
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:center}
.ct-copy p{font-family:var(--font-label);font-size:1.06rem;line-height:1.76;color:var(--ink-soft);margin:0 0 22px}
.ct-lead{font-family:var(--font-main)!important;font-weight:600;font-size:clamp(1.2rem,1.9vw,1.45rem)!important;
  color:var(--ink)!important;line-height:1.4!important}
.ct-addr{font-style:normal;font-family:var(--font-label);font-size:1rem;line-height:1.7;color:var(--ink);
  padding:18px 22px;background:var(--white);border:1px solid var(--line-soft);border-radius:16px;
  box-shadow:var(--shadow-sm);margin:0 0 24px}
.ct-addr strong{display:block;font-family:var(--font-main);font-weight:600;margin-bottom:4px}
.ct-cta{display:flex;gap:14px;flex-wrap:wrap}
.ct-media img{width:100%;height:auto;aspect-ratio:3/4;object-fit:cover;
  border-radius:clamp(18px,2.4vw,30px);box-shadow:var(--shadow-md);display:block}
/* Contact photo, client 2026-09-23: "a bit bigger, and zoom out of the picture,
   same size and shape we have on the home page" — i.e. the White Glove frame,
   which is the full column at 4:3. The source is 1536x1152, exactly 4:3, so
   cover has nothing to crop and the whole photo shows. */
.ct-media.is-wide img{aspect-ratio:4/3}

@media (max-width:860px){
  .abt-grid,.story-grid,.ct-grid{grid-template-columns:minmax(0,1fr)}
  .story-media{order:-1}
}
@media (prefers-reduced-motion:reduce){
  .val-card,.val-card:hover,.team-photo,.team-card:hover .team-photo{transition:none;transform:none}
}
/* about hero: the H2 sentence sits in the .phero-sub slot but carries more weight */
.phero-lead{font-family:var(--font-main);font-weight:500;color:rgba(255,255,255,.94);
  font-size:clamp(1.08rem,1.75vw,1.4rem);line-height:1.46;max-width:34ch}
/* the stat band runs without its eyebrow here, so it needs its own breathing room */
.statrow .sr-inner > .sr-list:first-child{margin-top:clamp(6px,1vw,14px)}
/* .oc-title doubles as this page's section heading; in the copy columns it is
   followed immediately by body text, so it needs its own bottom margin */
.abt-copy .oc-title{margin-bottom:20px}
.ct-copy .oc-title{margin-bottom:12px}
/* the responsibility head is a full copy block ending in a button, so the
   150px --head-gap below it would double up with the grid's own margin */


/* ---- stacked cards on CONTENT images: narrow-viewport clearance ----
   The blue and green layers sit OUTSIDE their wrapper (translate + rotate), so
   against --sec-x's 20px mobile gutter the blue card was clipped by the screen
   edge (measured -3px at 390 and 430). Scoped to .stk-media, which
   components.stacked() puts on every content image: the homepage's own stacks
   (hero, glove, globe, booking) are client-approved and must not shift.
   NOT the cause of the 360px horizontal scrollbar — that is the header. */
@media (max-width:600px){
  .stk-media .stack-blue{transform:rotate(-1.7deg) translate(-8px,-6px)}
  .stk-media .stack-green{transform:rotate(1deg) translate(5px,5px)}
  .stk-media{margin-inline:10px}
}

/* ---- header: narrow-viewport fit ----
   Below the drawer breakpoint the header is flex with three children —
   logo 208 + AI search 30 + actions 98, plus 48px of gaps and 40px of padding
   = 424px against a 390px phone. `.logo{min-width:max-content}` (needed on
   DESKTOP, where the img otherwise collapses to 0 between 1280 and 1000) meant
   the logo could not give any of it back, so the hamburger was pushed off
   screen: fully invisible at 360, half cut at 375-390. Every phone but the
   largest.
   The logo is the only child that can safely shrink, so it becomes the flexible
   one; tightening gap and gutter first means it barely has to. At 390 it gives
   up 2px (iPhone 14 stays as approved), at 360 about 32px. */
@media (max-width:1180px){
  .logo{min-width:0}
  .logo img,
  .site-header.scrolled .logo img{height:auto;max-height:40px;max-width:100%}
}
@media (max-width:600px){
  .header-inner{gap:12px;padding-left:16px;padding-right:16px}
}

/* The photos are 2:3 portraits (1024x1536). A max-height cap SILENTLY beat the
   declared aspect-ratio — the box rendered at 0.869 rather than 0.8, so cover
   threw away a third of a tall frame and the crop read as a stretch. The cap is
   gone and the ratio is 3:4 (0.75), much nearer the source, so the frame keeps
   its subject. object-position pulls each crop to where the subject actually
   sits rather than trusting dead centre.
   NB the box (0.75) is WIDER than the source (0.667), so the image fills the
   width and is cropped VERTICALLY only — the X half of object-position does
   nothing here. Y is the whole control. */
.abt-media img{object-position:50% 50%}    /* engineer and logo panel both sit centre */
/* about-opus intro, 2026-09-23: the client cropped this one themselves
   (people-leadership.jpg, 4104x3840), so the frame keeps the photo's own ratio
   at EVERY width. Without this the mobile default (3:4 on the img) re-cropped
   it and clipped both outer shoulders off a crop that was already correct. */
.abt-media.is-asis img{aspect-ratio:1400/1310}
.story-media img{object-position:50% 38%}  /* two figures sit high in the aisle */
.ct-media img{object-position:50% 70%}     /* tagline is etched low-left, so bias down */

/* Intro photo: 25% narrower and centred, so it gains air on both sides.
   Mobile only now — at >=861 the aspect-ratio rule below derives the same
   width (~427px of a 574px column) from the height instead. */
@media (max-width:860px){
  .abt-media{width:75%;margin-inline:auto}
}

/* ---- booking card: sized to its content ----
   The card stretched to fill its 1.05fr grid column (611px at 1440) while the
   calendar was pinned to 340, so the calendar read as floating in a card twice
   its width — and at 1280 the card ran past the column edge. Capping the
   WRAPPER (the stack layers are inset:0 on it, so they follow) lets the card be
   as wide as calendar + two slot columns and no wider. */
/* A fraction for the card column made its width a leftover, so the calendar
   got whatever was spare (212px, 30px day cells). A fixed column pins the
   card and lets the INFO column absorb the slack instead.
   ⚠️ Scoped to min-width:901 on purpose — unscoped, this sits AFTER the
   @media (max-width:900px) single-column rule above and silently undoes it.
   ⚠️ No margin-left:auto on .stk-bk either: an auto inline margin makes a
   grid item shrink-to-fit, so the card stopped filling its own column. */
@media (min-width:901px){
  .bk-inner{grid-template-columns:minmax(0,1fr) 560px}
}
@media (max-width:900px){
  /* width:100% is required — an auto inline margin alone makes a grid item
     shrink-to-fit, which is what stopped the card filling its column. */
  .stk-bk{width:100%;max-width:560px;margin-inline:auto}
}

/* The narrower card took the 360px horizontal scroll from 13px down to 1px.
   Trimming 12px of card width on phones clears it outright, without touching
   the stack's offsets (that look is client-approved). */
@media (max-width:600px){
  .stk-bk{max-width:calc(100% - 12px)}
}

/* In the modal the card gets the full dialog width (846px at desktop), so the
   calendar — now free to grow — sprawled to 82px day cells while the times
   stayed pinned at 178. Capping it keeps the modal reading like the on-page
   card rather than a different widget. */
.bkm-cardslot .bk-card{max-width:600px;margin-inline:auto}

/* ---- rule: an image beside copy is never TALLER than that copy ----
   Contact ran 805px against 463px of text and read as a stretched slab. Sizing
   these off their own aspect-ratio meant the image decided the row height.
   Now the <img> is absolutely positioned, so it contributes NOTHING to the row
   — the row is sized purely by the copy column, and align-self:stretch hands
   that height back to the media wrapper.
   The 640px cap is the other half of the rule: where the copy is very tall
   (the intro column is 862px) an equal-height image would become a narrow
   640px+ ribbon, so it stops there and stays comfortably shorter.
   Desktop only. Below 861 the columns stack, the row height IS the wrapper,
   and an absolute image would collapse it to nothing. */
@media (min-width:861px){
  /* The box takes the photos' OWN 2:3 (1024x1536), so object-fit:cover has
     nothing to crop — the whole frame shows, just smaller. Height still
     comes from the copy column (the img below is absolute, so it adds
     nothing to the row); width then follows from the ratio, which needs
     justify-self:center — the default stretch would force the width and
     put us back to cropping. */
  .abt-media,.story-media,.ct-media{
    align-self:stretch;justify-self:center;position:relative;
    /* ⚠️ do NOT add margin-block:auto to centre the leftover gap — auto block
       margins absorb free space INSTEAD of stretching, so the height falls
       back to content (the img is absolute = 0) and the box collapses. */
    aspect-ratio:2/3;width:auto;max-height:640px;
    /* the backing cards sit ~13px outside the box; at 861-1000 the column is
       tight enough that the green one reached past the viewport (910 at 900).
       Clamping width makes the ratio drive the height DOWN instead. */
    max-width:calc(100% - 22px)}
  /* .stacked.<name> (0,2,1) is required: the generic on-top rule
     `.stacked > :not(.stack-card)` is (0,2,0) and beats a plain
     `.ct-media img` (0,1,1), so position:absolute was being ignored. */
  .stacked.abt-media img,.stacked.story-media img,.stacked.ct-media img{
    position:absolute;inset:0;z-index:2;width:100%;height:100%;max-height:none;object-fit:cover}
  /* ...except the contact card, which the client asked to match the homepage:
     full column width at 4:3. It goes back to sizing itself (static img, ratio
     on the box) rather than borrowing the copy column's height. */
  .ct-media.is-wide{aspect-ratio:4/3;width:100%;max-width:calc(100% - 22px);
    max-height:none;align-self:center}
  /* relative, not static: z-index needs a positioned element, and without
     it the photo sits UNDER the green backing card. */
  .stacked.ct-media.is-wide img{position:relative;z-index:2;width:100%;height:auto}
}

/* Centred eyebrows take BOTH marks. A single leading dash is the inner-page
   convention and reads correctly when the label is left-aligned, but under a
   centred heading it just looks lopsided. */
.oc-eyebrow.is-centred{justify-content:center}
.oc-eyebrow.is-centred::after{content:"";height:2px;width:17px;flex:none;background:currentColor}

/* ============================================================
   ABOUT PAGE — ENTRANCE ANIMATIONS
   Same mechanism as the homepage, not a second one: the observer in
   _tail.html adds `.in` to EVERY section once it is 28% visible (or its top
   has scrolled past), so these rules only have to describe the resting state
   and the settled state. Stagger rides on --i, which about.py already emits on
   the quick-facts rows and every card.
   ⚠️ The media wrappers ARE the .stacked elements, so the reveal sits on the
   WRAPPER. Fading the <img> instead would let the blue and green backing
   layers show straight through the half-transparent photo — the same trap
   .stk-glove and .stk-bk already document.
   ============================================================ */
.abt-copy,.abt-media,
.values .oc-head,.val-card,
.team .oc-head,.team-card,
.story-media,.story-copy,.mv-card,
.resp-head,.resp-card,
.ct-copy,.ct-media,
.qf li{
  opacity:0;translate:0 22px;
  transition:opacity .72s var(--ease),translate .72s var(--ease);
}
/* the photo follows its copy in, rather than arriving together */
.abt-media,.story-media,.ct-media{translate:0 28px;transition-delay:.12s}

.abt-intro.in .abt-copy,.abt-intro.in .abt-media,
.values.in .oc-head,.values.in .val-card,
.team.in .oc-head,.team.in .team-card,
.story.in .story-media,.story.in .story-copy,.story.in .mv-card,
.resp.in .resp-head,.resp.in .resp-card,
.abt-contact.in .ct-copy,.abt-contact.in .ct-media,
.abt-intro.in .qf li{opacity:1;translate:0}

/* staggers — the grids run off --i, the fact rows off their own index */
.values.in .val-card,
.team.in .team-card,
.resp.in .resp-card{transition-delay:calc(.1s + var(--i,0)*85ms)}
.story.in .mv-card{transition-delay:calc(.2s + var(--i,0)*90ms)}
.abt-intro.in .qf li{transition-delay:calc(.18s + var(--i,0)*55ms)}

/* hero: it is above the fold, so the observer marks it `in` on load */
.phero-title,.phero-lead,.phero-cta{
  opacity:0;translate:0 20px;
  transition:opacity .8s var(--ease),translate .8s var(--ease);
}
/* ⚠️ .qhero must be listed too. These hide at opacity 0 until their section
   gets `in`, and the form/legal pages use .qhero, not .phero — so the title
   sat invisible on a photo band forever. Any NEW hero class must be added
   here as well. */
.phero.in .phero-title,.qhero.in .phero-title{opacity:1;translate:0}
.phero.in .phero-lead,.qhero.in .phero-lead{opacity:1;translate:0;transition-delay:.12s}
.phero.in .phero-cta,.qhero.in .phero-cta{opacity:1;translate:0;transition-delay:.24s}

@media (prefers-reduced-motion:reduce){
  .abt-copy,.abt-media,.values .oc-head,.val-card,.team .oc-head,.team-card,
  .story-media,.story-copy,.mv-card,.resp-head,.resp-card,.ct-copy,.ct-media,
  .qf li,.phero-title,.phero-lead,.phero-cta{
    opacity:1;translate:none;transition:none}
}

/* ============================================================
   BACKGROUND LIBRARY   ·   see _build/PAGE-RULES.md
   A section picks a background by adding one class. Five are lifted from the
   homepage and share their ORIGINAL declarations (the class is appended to the
   existing selector list, so there is still exactly one definition of each
   ramp and the two can never drift). Three are new wide images.
   Rule 3 still applies: never put two of these back to back.
   ============================================================ */

/* --- 1. bg-aurora · the "Trusted at scale" gradient + three drifting glows ---
   Needs markup: <div class="bgfx" aria-hidden="true"><i class="bgfx-g1"></i>
   <i class="bgfx-g2"></i><i class="bgfx-g3"></i></div> as the first child.
   The glows are oversized and blurred, so the section MUST keep its
   position/overflow/isolation or they escape it. */

/* --- 2. bg-clouds · "Why Opus Interactive" ---
   No markup needed. The parallax script in _tail.html already drives
   `.advantages, .blog-head`; add `.bg-clouds` there if a new page wants the
   drift too.
   ⚠️ The cloud layer is a ::before with no z-index, so it paints OVER anything
   that is not itself positioned. On the homepage `.adv-inner` handles that with
   position:relative;z-index:1; here it is done for any child, so a new section
   cannot lose its content behind the clouds. */
.bg-clouds > *{position:relative;z-index:1}

/* --- 3. bg-slate · the dark "Cloud Services" grey ramp ---
   ⚠️ Icon art on this field carries a knockout colour tuned to the card over
   the gradient (--ic-knock). Re-tune it if the field ever changes. */

/* --- 4. bg-paper · the plain near-white content field --- */
.bg-paper{background:var(--paper)}
.bg-grey{background:#f2f3f4}          /* the neutral break used on /about-opus/ story */

/* --- 5. bg-photo · client photograph under the hero scrim ---
   Needs markup: <img class="bg-photo-img" src="…" alt="" /> plus
   <span class="bg-photo-scrim" aria-hidden="true"></span>. Same treatment as
   .phero, available to content sections, not just heroes. */
.bg-photo{position:relative;isolation:isolate;overflow:hidden}
.bg-photo-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-2}
.bg-photo-scrim{position:absolute;inset:0;z-index:-1;
  background:linear-gradient(94deg,rgba(6,22,34,.86) 0%,rgba(6,22,34,.66) 46%,rgba(6,22,34,.18) 100%)}
/* lighter scrim for a section that only needs the text to hold, not a hero */
.bg-photo.is-soft .bg-photo-scrim{
  background:linear-gradient(94deg,rgba(6,22,34,.62) 0%,rgba(6,22,34,.34) 55%,rgba(6,22,34,.08) 100%)}

/* --- 6-8. the generated sustainability fields ---
   2400x1340 WebP, hero style, each with a calm area for a headline:
   wind -> open on the right, solar -> upper left, seedling -> left half.
   They are LIGHT images, so dark ink reads on them directly; add
   .is-scrimmed when text needs more help. */
.bg-wind,.bg-solar,.bg-seedling{
  position:relative;isolation:isolate;overflow:hidden;
  background-size:cover;background-position:center;background-repeat:no-repeat}
.bg-wind{background-image:url("images/bg/wind.webp")}
.bg-solar{background-image:url("images/bg/solar.webp")}
.bg-seedling{background-image:url("images/bg/seedling.webp")}
/* ⚠️ The 5% black wash is NOT optional on these three — it is part of the
   background. Client rule: whenever one of the generated fields is used, it
   carries the overlay and light type. It settles the sky just enough for white
   to sit on it without dulling the colour.
   An earlier version ported the prefoot's radial vignette here and was rejected
   through three rounds of tuning: that vignette works because it sits on an
   already-dark server room, but on a bright sky any focused radial reads as a
   smudge. Flat and even is the answer. */
.bg-wind::after,.bg-solar::after,.bg-seedling::after{
  content:"";position:absolute;inset:0;z-index:-1;background:rgba(0,0,0,.05)}
/* ⚠️ TEXT COLOUR IS PER IMAGE, MEASURED, NOT PER FAMILY.
   A blanket `color:#fff` used to sit here for all three. It is wrong: these
   are high-key images and a 5% wash does not change that. Measured in situ,
   white on the SEEDLING field gave 1.37-1.60:1 against a 3.0/4.5 minimum,
   which is unreadable, not merely non-compliant. Dark ink measures ~7:1 on the
   same pixels. So seedling and wind take the normal ink, and only solar keeps
   white.
   ⚠️ Even solar's white is NOT passing: /about-opus/'s "Values" heading
   measures 2.06:1 on rgb(141,186,223). It is large display type so it reads,
   but it is under the bar. The client ASKED for that word in white and
   approved the look, so it is left alone pending their call — see
   REVIEW-QUEUE. Dark ink would measure 5.43:1 there. */
.bg-solar{color:#fff}
.bg-solar .oc-title,.bg-solar .oc-eyebrow{color:#fff}

/* ---- hero crop: never cut a face ----
   The band is short and wide, so `cover` on this 3:2 photo discards a lot of
   height: 488px at 1440 and 740px at 1920, split evenly top and bottom by the
   default 50%. That put the left engineer's head above the top edge.
   Measured against the source (his hairline sits at about row 160 of 1024),
   the window has to start above that at EVERY width:
       Y     1920   1440   1180    900
       50%    296    260    241    157   <- cuts him at 1180 and up
       30%    178    156    145     94   <- still clips at 1920
       25%    148    130    121     79   <- clear everywhere
   A fixed length was tried first and is wrong: 30px is enough at 1440 but not
   at 1920, where the overflow is half again as large. A percentage scales with
   the overflow, which is exactly the quantity that varies.
   ⚠️ If you do reach for a length, note the sign is inverted from the obvious
   reading: object-position resolves against (container - image) height, which
   is NEGATIVE when the image overflows, so 50% PLUS 30px reveals more of the
   TOP and minus reveals more of the bottom. */
/* ⚠️ PER-PHOTO, never global. 25% is only right for the /about-opus/ hero,
   whose hairline sits at source row ~160 of 1024. The certifications hero
   (security-badge-entry) has its subject at row ~75 and needs ~10%, and a
   shared value clipped his head at every width from 900 up. Each page sets
   --hero-y for ITS photo; the default is the About page's value. */
/* --hero-flip:-1 mirrors the photo so the subject sits opposite the copy.
   Per-page like --hero-y. ⚠️ Only safe on a frame with no readable text or
   logo in it — a mirrored word or brand mark reads as a mistake. */
/* --hero-x matters ONLY where the frame is taller than the source ratio, i.e.
   phones: there the crop is horizontal and a face near one edge falls out.
   Above ~600 the hero is width-driven and this value has no visible effect. */
.phero-photo{object-position:var(--hero-x,50%) var(--hero-y,25%);
  transform:scaleX(var(--hero-flip,1))}


/* the header loses 5px of logo below the drawer breakpoint */
@media (max-width:1180px){ :root{--hd-h:81px} }

/* Optical centring for the hero: the headline's box top sits ~0.14em above the
   cap (font ascent + half-leading), so matching the PADDING top and bottom
   still reads 10px top-heavy — which is what the eye measures from, the visible
   letter, not the box. An em-based negative margin trims exactly that leading
   at every clamp step: 8px at the 56px desktop size, 4.7px at 33.6px on a
   phone, with no per-breakpoint values to maintain. */
.phero-title{margin-top:-.14em}

/* ============================================================================
   SOCIAL RESPONSIBILITY  ·  /about-opus/social-responsibility/
   Four "Proudly Supporting" pillars, alternating sides and backgrounds.
   Built to _build/PAGE-RULES.md; see _build/social.py for the per-rule calls.
   ========================================================================== */
.sr-lead{padding:calc(var(--sec-y) * .82) var(--sec-x)}
.sr-lead-inner{max-width:820px;margin:0 auto;text-align:center}
.sr-lead p{font-family:var(--font-main);font-weight:500;margin:0;
  font-size:clamp(1.12rem,1.9vw,1.45rem);line-height:1.58;color:var(--ink)}

.sr-pillar{position:relative;isolation:isolate;overflow:hidden;
  padding:var(--sec-y) var(--sec-x)}
.sr-grid{max-width:var(--wrap);margin:0 auto;display:grid;align-items:center;
  gap:clamp(32px,5vw,72px);grid-template-columns:minmax(0,1fr) minmax(0,.92fr)}
/* alternate which side the photo sits on */
.sr-pillar.is-flip .sr-copy{order:2}
.sr-pillar.is-flip .sr-media{order:1}

.sr-copy p{font-family:var(--font-label);font-size:1.06rem;line-height:1.76;
  color:var(--ink-soft);margin:0}
.sr-copy .oc-title{margin-bottom:18px}
.sr-cta{margin:28px 0 0 !important}

/* rule 1 — never taller than the copy, shrunk at its OWN ratio. These are
   513x325 landscape, not the 2:3 the retouched shoot uses. */
.sr-media img{width:100%;height:auto;aspect-ratio:var(--media-ar,1400/1046);object-fit:cover;display:block;
  border-radius:clamp(14px,1.8vw,22px);box-shadow:var(--shadow-md)}

/* a large watermark of the pillar's own icon, bled off the far edge */
.sr-ic{position:absolute;z-index:-1;right:-40px;bottom:-40px;
  width:clamp(180px,22vw,300px);height:clamp(180px,22vw,300px);
  opacity:.05;pointer-events:none}
.sr-pillar.is-flip .sr-ic{right:auto;left:-40px}
.sr-ic svg{width:100%;height:100%;fill:none;stroke:currentColor;stroke-width:1;
  stroke-linecap:round;stroke-linejoin:round}
/* on the image field the watermark would fight the photo */
.sr-pillar.bg-wind .sr-ic,.sr-pillar.bg-solar .sr-ic,.sr-pillar.bg-seedling .sr-ic{opacity:.12}

/* ⚠️ On an image field the copy sits on a CARD, not straight on the photo.
   White type on a bright sky measured ~2:1; a large heading survives that (the
   client accepted it for the Values band) but a full paragraph does not — body
   copy wants 4.5:1 and it was genuinely hard to read. The card is the
   homepage's own answer to the same problem behind its hero.
   The card also cancels the white type the .bg-* class sets. */
.sr-pillar.bg-wind .sr-copy,.sr-pillar.bg-solar .sr-copy,
.sr-pillar.bg-seedling .sr-copy{
  background:rgba(255,255,255,.94);color:var(--ink);
  max-width:660px;padding:clamp(28px,3.2vw,46px);
  border-radius:clamp(18px,2.2vw,28px);box-shadow:var(--shadow-md)}
.sr-pillar.bg-wind .sr-copy p,.sr-pillar.bg-solar .sr-copy p,
.sr-pillar.bg-seedling .sr-copy p{color:var(--ink-soft)}
.sr-pillar.bg-wind .sr-copy .oc-eyebrow,.sr-pillar.bg-solar .sr-copy .oc-eyebrow,
.sr-pillar.bg-seedling .sr-copy .oc-eyebrow{color:var(--brand-deep)}
.sr-pillar.bg-wind .sr-copy .oc-title,.sr-pillar.bg-solar .sr-copy .oc-title,
.sr-pillar.bg-seedling .sr-copy .oc-title{color:var(--ink)}

/* rule 7 — entrance animations, same mechanism as every other page */
.sr-lead-inner,.sr-copy,.sr-media{
  opacity:0;translate:0 22px;
  transition:opacity .72s var(--ease),translate .72s var(--ease)}
.sr-media{translate:0 28px;transition-delay:.12s}
.sr-lead.in .sr-lead-inner,.sr-pillar.in .sr-copy,.sr-pillar.in .sr-media{opacity:1;translate:0}

@media (max-width:860px){
  .sr-grid{grid-template-columns:minmax(0,1fr)}
  .sr-pillar.is-flip .sr-copy,.sr-pillar.is-flip .sr-media{order:0}
  .sr-ic{display:none}
}
@media (prefers-reduced-motion:reduce){
  .sr-lead-inner,.sr-copy,.sr-media{opacity:1;translate:none;transition:none}
}

/* rule 1 for the pillar photos: never taller than their copy, and never
   cropped. The stretch-and-clamp trick used on /about-opus/ is wrong here —
   those are 2:3 portraits in tall columns, these are 1.58 landscapes in wide
   ones, and stretching to the copy height then clamping the width crushed the
   ratio (1.41 against a source 1.58) and started cropping.
   Capping at the image's NATIVE width is both simpler and better: the derived
   height is 325px, at or under every pillar's copy (325-431 at 1440, 340-396
   at 1180), the ratio stays exact so cover has nothing to crop, and the photo
   is never upscaled past its own resolution. */
/* Each photo sizes to ITS OWN copy: the <img> is absolute so it adds nothing
   to the row, the row is sized by the copy column, align-self:stretch hands
   that height back, and aspect-ratio derives the width from it. No max-width —
   an earlier attempt clamped the width and the clamp fought the ratio, which
   is what started cropping. Result: the photo beside the long Women in Tech
   paragraph is large, the one beside the short Digital Inclusion paragraph is
   smaller, and none is ever taller than the words next to it. */
.sr-media{justify-self:center}
@media (min-width:861px){
  /* ⚠️ PER-PHOTO, never hardcoded. 1400/1046 is only the social-responsibility
     programme photos; the certifications page pairs a 2:3 portrait with a 3:2
     landscape, and a shared ratio squashed the portrait to near-square. Each
     section passes --media-ar for ITS image. */
  .sr-media{align-self:stretch;position:relative;aspect-ratio:var(--media-ar,1400/1046);
    width:auto;max-width:100%;
    /* FLOOR of 400px so a short paragraph cannot shrink its photo to a stamp.
       Sizing purely off the copy left Sustainability at 395x295 beside Women
       in Tech at 577x431 — a 182px spread driven by paragraph length rather
       than by design. Above the floor the photo still grows with its copy.
       A 400-tall photo at 1.338 wants 535px of width and the column is
       narrower than that below ~1280, so there the frame crops rather than
       shrinking — the client's call, and the right trade: a consistent size
       matters more here than showing every last edge of the frame.
       min-width is capped at 100% so the floor can never overflow the column. */
    min-height:400px;min-width:min(400px,100%)}
  .stacked.sr-media img{position:absolute;inset:0;z-index:2;
    width:100%;height:100%;max-height:none;object-fit:cover}
}

/* ---- /about-opus/our-certifications/ ----
   Reuses the .sr-pillar split from social-responsibility (same shape: eyebrow,
   heading, copy, photo) and adds a ticked credential list. */
/* deck line under a section heading — /colocation/ pairs a short headline
   ("Super Powered. Planet Friendly.") with an explanatory line beneath it. */
/* leaf beside a heading — /colocation/ "Super Powered. Planet Friendly."
   Inside the .accent span so it never wraps onto a line of its own, sized in em
   so it tracks the clamped heading, and green rather than the heading's blue
   because it is the sustainability mark used across the site. */
.title-leaf{
  width:1.05em;height:1.05em;margin-left:.16em;vertical-align:-.15em;
  fill:none;stroke:var(--brand-green);stroke-width:2.1;
  stroke-linecap:round;stroke-linejoin:round;
  /* ⚠️ transform-box:fill-box — without it an SVG transform-origin resolves
     against the whole SVG viewport, not the glyph, and the leaf swings off
     the baseline instead of pivoting on its own stem. */
  transform-box:fill-box;transform-origin:18% 82%;
  opacity:0;transform:scale(.55) rotate(-24deg);
}
/* unfurls once its section scrolls in, a beat after the heading has settled */
.sr-pillar.in .title-leaf{animation:leafUnfurl .72s cubic-bezier(.22,.9,.3,1.06) .38s both}
@keyframes leafUnfurl{
  0%{opacity:0;transform:scale(.55) rotate(-24deg)}
  60%{opacity:1;transform:scale(1.08) rotate(4deg)}
  100%{opacity:1;transform:scale(1) rotate(0)}
}
@media (prefers-reduced-motion:reduce){
  .title-leaf{opacity:1;transform:none}
  .sr-pillar.in .title-leaf{animation:none}
}
.sr-sub{font-size:clamp(1.02rem,1.25vw,1.16rem);line-height:1.6;color:var(--ink-soft);margin-top:14px}
.sr-copy .trust-list{margin-top:20px;margin-bottom:26px}
.cred-list{list-style:none;margin:24px 0 0;padding:0;display:grid;gap:11px}
.cred-list li{display:flex;align-items:flex-start;gap:11px;
  font-family:var(--font-label);font-size:1rem;line-height:1.55;color:var(--ink)}
.cred-list li svg{flex:none;margin-top:.24em;color:var(--brand-green)}

/* the hero's compliance chips sit on the dark scrim, not on a white card */
.phero-chips{margin-top:26px}
/* Cap the chip row so it wraps to TWO rows and stays clear of a hero photo
   whose subject sits on the right (/dedicated-iaas, client 2026-09-23).
   The six chips measure 1244px laid out in one line, so ~660px splits them
   3 + 3. A column of six was the first attempt and made the hero 120px taller
   for no gain. */
.phero-chips.is-stacked{max-width:min(660px,100%)}
.phero-chips li{color:#fff;border-color:rgba(255,255,255,.36);
  background:rgba(255,255,255,.12);backdrop-filter:blur(2px)}

/* the FAQ accordion sits in a wrapper so the SECTION owns the background */
.faqwrap{padding:0}

/* rule 7 — entrance animation, same mechanism as everywhere else */
.faqwrap .faq-item{opacity:0;translate:0 16px;
  transition:opacity .6s var(--ease),translate .6s var(--ease)}
.faqwrap.in .faq-item{opacity:1;translate:0}
.faqwrap.in .faq-item:nth-child(-n+8){transition-delay:calc(var(--fi,0)*40ms)}
@media (prefers-reduced-motion:reduce){
  .faqwrap .faq-item{opacity:1;translate:none;transition:none}
}

/* ---- /about-opus/policies/ : the document cards ----
   Six PDFs, so these are navigation targets rather than a spec list — cards
   with a sprite icon each (rule 2), not bullets. */
.docs{padding:calc(var(--sec-y) * .78) var(--sec-x)}
.docs-inner{max-width:1120px;margin:0 auto}
/* six documents, so THREE columns — auto-fit gave four and left a hole where
   the last two cards should have balanced the row */
.docs-grid{display:grid;gap:clamp(16px,2vw,24px);grid-template-columns:repeat(3,1fr)}
@media (max-width:900px){.docs-grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.docs-grid{grid-template-columns:minmax(0,1fr)}}
.doc-card{display:flex;flex-direction:column;align-items:flex-start;
  background:var(--white);border:1px solid var(--line-soft);
  border-radius:clamp(16px,1.8vw,22px);padding:clamp(22px,2.4vw,30px);
  box-shadow:var(--shadow-sm);text-decoration:none;
  transition:transform .25s var(--ease),box-shadow .25s var(--ease),border-color .25s var(--ease)}
.doc-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-md);border-color:rgba(44,171,226,.4)}
.doc-card:hover .uc-ic{background:var(--brand-sky);color:#fff}
.doc-name{font-family:var(--font-main);font-weight:600;font-size:1.06rem;
  color:var(--ink);line-height:1.35;margin-bottom:10px}
.doc-meta{display:flex;align-items:center;gap:7px;margin-top:auto;
  font-family:var(--font-label);font-size:.82rem;font-weight:600;
  letter-spacing:.04em;color:var(--brand-deep)}
.doc-go{transition:translate .25s var(--ease)}
.doc-card:hover .doc-go{translate:0 2px}

/* rule 7 */
.doc-card{opacity:0;translate:0 20px;
  transition:opacity .6s var(--ease),translate .6s var(--ease),
             transform .25s var(--ease),box-shadow .25s var(--ease),border-color .25s var(--ease)}
.docs.in .doc-card{opacity:1;translate:0;transition-delay:calc(var(--i,0)*70ms)}
@media (prefers-reduced-motion:reduce){
  .doc-card{opacity:1;translate:none;transition:none}
}
.sr-title{font-family:var(--font-main);font-weight:600;color:#fff;text-align:center;
  font-size:clamp(1.5rem,2.6vw,2.15rem);letter-spacing:-.02em;
  margin:0 0 clamp(30px,3.4vw,46px)}

/* ---- /datacenters/ ----
   Reuses .sr-pillar for the three facilities and .cred-list for their feature
   lists; adds the site-selection block and the post cards. */
.sitesel{padding:var(--sec-y) var(--sec-x)}
/* copy left, criteria right — the section is full-bleed and the list alone in
   a 760px column left the right half of the clouds empty. */
.sitesel-inner{max-width:var(--wrap);margin:0 auto;display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,.82fr);
  gap:clamp(28px,4vw,72px);align-items:start}
.sitesel-head p{font-family:var(--font-label);font-size:1.04rem;line-height:1.75;
  color:var(--ink-soft);margin:0 0 4px}
/* ⚠️ NOT `columns:2` — .cred-list is display:grid and CSS multi-column is
   inert on a grid container, so the two columns silently never happened. */
.sitesel .cred-list{margin-top:0;gap:14px}
@media (max-width:860px){
  .sitesel-inner{grid-template-columns:minmax(0,1fr)}
  .sitesel .cred-list{margin-top:8px}
}

/* ---- components.recent_posts() ----
   The "latest from the blog" strip. It reuses .blog-card / .blog-grid from the
   archive verbatim — bloggen.blog_card() renders both — so only the section
   frame lives here. Do NOT restyle .blog-card from this block: a change here
   would silently redesign /blog too. */
.recent-posts{padding:var(--sec-y) var(--sec-x)}
.rp-inner{max-width:var(--wrap);margin:0 auto}
/* the archive uses auto-fill so 25 cards reflow freely; a 3-card strip wants a
   fixed 3 so the row cannot break to 2 + 1 on a mid-size screen. */
.recent-posts .blog-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:980px){.recent-posts .blog-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:640px){.recent-posts .blog-grid{grid-template-columns:minmax(0,1fr)}}
.rp-more{margin:clamp(34px,4vw,52px) 0 0;text-align:center}

/* rule 7 — the card's own hover transform is preserved in the transition list,
   otherwise the entrance rule would replace it and kill the lift on hover. */
.recent-posts .blog-card{opacity:0;translate:0 20px;
  transition:opacity .6s var(--ease),translate .6s var(--ease),
             transform .25s var(--ease),box-shadow .25s var(--ease)}
.recent-posts.in .blog-card{opacity:1;translate:0}
.recent-posts .blog-card:nth-child(2){transition-delay:70ms}
.recent-posts .blog-card:nth-child(3){transition-delay:140ms}
@media (prefers-reduced-motion:reduce){
  .recent-posts .blog-card{opacity:1;translate:none;transition:none}
}
.sitesel-head,.sitesel .cred-list{opacity:0;translate:0 22px;
  transition:opacity .7s var(--ease),translate .7s var(--ease)}
.sitesel .cred-list{transition-delay:.12s}
.sitesel.in .sitesel-head,.sitesel.in .cred-list{opacity:1;translate:0}
@media (prefers-reduced-motion:reduce){
  .sitesel-head,.sitesel .cred-list{opacity:1;translate:none;transition:none}
}


/* ============================================================
   /colocation/oregon/
   ============================================================ */

/* .facility reuses .sitesel-inner's copy-left / list-right split (see the
   /datacenters/ block) and adds a full-measure figure beneath it. */
.facility{padding:var(--sec-y) var(--sec-x)}
.fac-cta{margin:26px 0 0}
.facility .cred-list{margin-top:0;gap:14px}

/* the site plan is 840x400 of small type: give it the whole measure, never a
   column, and never upscale past its own resolution or the hall labels blur. */
.fac-planwrap{max-width:var(--wrap);margin:clamp(38px,4.5vw,64px) auto 0;padding:0}
.fac-plan{max-width:840px;margin:0 auto;display:block}
/* ⚠️ NOT border-radius:inherit — .stacked sets no radius of its own (it is a
   positioning context; the rounding lives on the .stack-card layers), so
   `inherit` resolved to 0 and the plan sat square inside two rounded cards.
   Take --stack-r directly.
   The 4px white border is breathing room: the source PNG is cropped hard to
   its own content, with "SECURITY GATE NORTH/WEST" almost touching the edges,
   so without it the corner rounding eats into the diagram. The border is white
   because the plan's own field is white — it reads as padding, not a frame. */
.fac-plan img{display:block;width:100%;height:auto;
  border-radius:var(--stack-r);border:4px solid #fff;background:#fff}
/* Below ~840 the hall labels stop being readable if the plan just shrinks, so
   it keeps its own size and the FIGURE scrolls instead. The stacked cards sit
   outside the image box, so the scroller needs padding or it clips them. */
@media (max-width:900px){
  .fac-planwrap{overflow-x:auto;padding:6px 18px 14px;
    -webkit-overflow-scrolling:touch;scrollbar-width:thin}
  .fac-plan{min-width:760px}
}

/* On the seedling field the copy stays DARK. White measured 1.37-1.60:1 on
   these pixels; ink measures ~7:1. The 5% wash still comes from
   components.background() — it settles the sky, it does not darken it. */
.facility.is-onphoto .cred-list li svg{color:#4a8f14}

.pricing{padding:var(--sec-y) var(--sec-x)}
.pricing-inner{max-width:760px;margin:0 auto;text-align:center}
.pricing-inner .oc-eyebrow{justify-content:center}
.pricing-inner p{font-family:var(--font-label);font-size:1.04rem;line-height:1.75;
  color:var(--ink-soft);margin:0}

/* ⚠️ VERTICAL RHYTHM, and it has to out-specify the reset above.
   `.pricing-inner p` is (0,1,1) and was silently beating `.pricing-cta` at
   (0,1,0), so the CTA's 30px top margin never applied and the heading,
   the line under it and the button rendered with a measured gap of ZERO
   between all three. Every rule here is (0,2,0) so it actually lands.
   This band is shared by the location, service and facility pages, so the
   fix reaches all of them. */
.pricing-inner .oc-eyebrow{margin:0 0 14px}
.pricing-inner .oc-title{margin:0 0 20px}
.pricing-inner p + p{margin-top:15px}
.pricing-inner .band-list{margin:28px auto 0}
.pricing-inner .pricing-cta{margin:34px 0 0}

/* their local-SEO city block: real page text, kept, but presented as a quiet
   footer strip rather than the keyword run it is on the live page. */
.areas{padding:clamp(46px,6vh,72px) var(--sec-x)}
.areas-inner{max-width:var(--wrap);margin:0 auto;text-align:center}
.areas-title{font-family:var(--font-main);font-weight:400;
  font-size:clamp(1.24rem,2.1vw,1.62rem);line-height:1.3;color:var(--ink);margin:0}
/* ⚠️ NOT --brand-deep. This strip sits on paper on most pages but on GREY
   where the page has no testimonial above it, and --brand-deep measures
   4.48:1 there — a hair under the 4.5 minimum. Same hue, one step darker, so
   it passes on both fields. */
.areas-sub{font-family:var(--font-label);font-size:.86rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:#12647f;margin:12px 0 0}
.areas-cols{display:flex;flex-wrap:wrap;justify-content:center;
  gap:10px clamp(14px,1.6vw,22px);margin:26px auto 0;max-width:960px}
.areas-col{list-style:none;margin:0;padding:0;display:contents}
.areas-col li{font-family:var(--font-label);font-size:.92rem;color:var(--ink-soft);
  display:flex;align-items:center;gap:clamp(14px,1.6vw,22px)}
.areas-col li::after{content:"";width:3px;height:3px;border-radius:50%;
  background:var(--ink-faint);opacity:.65}
.areas-col:last-child li:last-child::after{display:none}

/* rule 7 */
.facility .sitesel-head,.facility .cred-list,.fac-planwrap,
.pricing-inner,.areas-inner{opacity:0;translate:0 22px;
  transition:opacity .7s var(--ease),translate .7s var(--ease)}
.facility .cred-list{transition-delay:.1s}
.fac-planwrap{transition-delay:.2s}
.facility.in .sitesel-head,.facility.in .cred-list,.facility.in .fac-planwrap,
.pricing.in .pricing-inner,.areas.in .areas-inner{opacity:1;translate:0}
@media (prefers-reduced-motion:reduce){
  .facility .sitesel-head,.facility .cred-list,.fac-planwrap,
  .pricing-inner,.areas-inner{opacity:1;translate:none;transition:none}
}


/* ============================================================
   /request-a-quote/
   ⚠️ This page deliberately has NO booking section — it is a contact form,
   not a booking flow (client, 2026-09-10). Do not "restore" #book here.
   ============================================================ */
.qhero{position:relative;isolation:isolate;overflow:hidden;color:#fff;
  display:grid;align-items:center;
  min-height:calc(clamp(230px,26vh,300px) + var(--hd-h));
  padding:calc(var(--sec-y) * .42 + var(--hd-h)) var(--sec-x) calc(var(--sec-y) * .42)}
.qhero-inner{max-width:var(--wrap);margin:0 auto;width:100%}
.qhero-quote{margin:0;max-width:820px}
.qhero-quote p{font-family:var(--font-main);font-weight:400;
  font-size:clamp(1.1rem,2vw,1.5rem);line-height:1.5;color:#fff;margin:0}
.qhero-quote cite{display:block;margin-top:16px;font-style:normal;
  font-family:var(--font-label);font-size:.82rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:#a5e4fb}

.quote{padding:var(--sec-y) var(--sec-x)}
.quote-inner{max-width:var(--wrap);margin:0 auto;display:grid;
  grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);
  gap:clamp(30px,4vw,70px);align-items:start}
.quote-lead{font-family:var(--font-label);font-size:1.04rem;line-height:1.75;
  color:var(--ink-soft);margin:18px 0 0}
.quote-assure{list-style:none;margin:26px 0 0;padding:0;display:grid;gap:12px}
.quote-assure li{position:relative;padding-left:24px;font-family:var(--font-label);
  font-size:.97rem;line-height:1.6;color:var(--ink-soft)}
.quote-assure li::before{content:"";position:absolute;left:0;top:.55em;
  width:8px;height:8px;border-radius:50%;background:var(--brand-green)}
.quote-assure a{color:var(--brand-deep);font-weight:600}

/* ---- the form ----
   One column below 860 and for the long controls; name/company/email/phone
   pair up on wide screens. */
.qform{background:var(--white);border:1px solid var(--line-soft);
  border-radius:clamp(16px,1.8vw,24px);padding:clamp(22px,2.6vw,36px);
  box-shadow:var(--shadow-sm)}
.qf-note{font-family:var(--font-label);font-size:.82rem;color:var(--ink-soft);margin:0 0 18px}
.qf-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(12px,1.4vw,18px)}
.qf-row{margin:0;display:flex;flex-direction:column;gap:7px}
.qf-full{grid-column:1 / -1}
.qf-row label{font-family:var(--font-label);font-size:.86rem;font-weight:600;color:var(--ink)}
.qf-req{color:#c0392b}
.qf-row input,.qf-row select,.qf-row textarea{
  font-family:var(--font-label);font-size:.97rem;color:var(--ink);
  background:var(--paper);border:1px solid var(--line-soft);
  border-radius:11px;padding:12px 14px;width:100%;
  transition:border-color .2s var(--ease),box-shadow .2s var(--ease)}
.qf-row textarea{resize:vertical;min-height:96px}
.qf-row input:focus-visible,.qf-row select:focus-visible,.qf-row textarea:focus-visible{
  outline:none;border-color:var(--brand-sky);box-shadow:0 0 0 3px rgba(44,171,226,.22)}
.qf-row input[aria-invalid="true"],.qf-row select[aria-invalid="true"],
.qf-row textarea[aria-invalid="true"]{border-color:#c0392b;background:#fdf5f4}
.qf-err{font-family:var(--font-label);font-size:.8rem;color:#a5281b;margin:0}
/* honeypot: off-screen rather than display:none — some bots skip hidden inputs */
.qf-trap{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.qf-actions{margin:24px 0 0}
.qf-actions .btn{width:100%;justify-content:center}
.qf-status{margin:14px 0 0;font-family:var(--font-label);font-size:.92rem;
  line-height:1.55;color:var(--ink-soft);min-height:1.2em}
.qf-status.is-ok{color:#1f7a3d}
.qf-status.is-bad{color:#a5281b}
.qform.is-sending{opacity:.65;pointer-events:none}

@media (max-width:980px){
  .quote-inner{grid-template-columns:minmax(0,1fr)}
}
@media (max-width:600px){
  .qf-grid{grid-template-columns:minmax(0,1fr)}
  .qf-half{grid-column:1 / -1}
}

/* the closing stat band, their "30 Years / Proven Reliability" */
.qstat{padding:clamp(46px,6vh,74px) var(--sec-x);
  background:linear-gradient(180deg,var(--grey-800) 0%,var(--grey-900) 100%);color:#fff}
.qstat-inner{max-width:var(--wrap);margin:0 auto;text-align:center}
.qstat-num{font-family:var(--font-main);font-weight:400;
  font-size:clamp(2.2rem,5vw,3.4rem);line-height:1;color:#7fd6f7;margin:0}
.qstat-lab{font-family:var(--font-label);font-size:.9rem;font-weight:600;
  letter-spacing:.15em;text-transform:uppercase;color:rgba(255,255,255,.82);margin:14px 0 0}

/* rule 7 */
.quote-copy,.qform,.qstat-inner,.qhero-quote{opacity:0;translate:0 22px;
  transition:opacity .7s var(--ease),translate .7s var(--ease)}
.qform{transition-delay:.1s}
.qhero.in .qhero-quote,.quote.in .quote-copy,.quote.in .qform,
.qstat.in .qstat-inner{opacity:1;translate:0}
@media (prefers-reduced-motion:reduce){
  .quote-copy,.qform,.qstat-inner,.qhero-quote{opacity:1;translate:none;transition:none}
}


/* ---- service pages: the customer testimonial ----
   One quote, no carousel: the source is a slider with a single slide, and its
   prev/next controls are furniture, not content. */
.testi{padding:var(--sec-y) var(--sec-x)}
.testi-inner{max-width:900px;margin:0 auto;text-align:center}
.testi-quote{margin:0;position:relative;padding-top:52px}
/* the section heading, when the quote IS the section (careers) - clear of the big quote mark */
.testi-inner > .oc-eyebrow{margin-bottom:30px}
.testi-quote::before{content:"\201C";position:absolute;top:-12px;left:50%;
  transform:translateX(-50%);font-family:var(--font-main);font-size:104px;
  line-height:1;color:var(--brand-sky);opacity:.26}
.testi-quote p{font-family:var(--font-main);font-weight:400;
  font-size:clamp(1.12rem,2.1vw,1.52rem);line-height:1.55;color:var(--ink);margin:0}
.testi-quote cite{display:block;margin-top:22px;font-style:normal;
  font-family:var(--font-label);font-size:.82rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-soft)}

/* the pricing band on a service page can carry a ticked list under its copy */
.band-list{max-width:520px;margin:26px auto 0;text-align:left}

/* rule 7 */
.testi-quote{opacity:0;translate:0 22px;
  transition:opacity .7s var(--ease),translate .7s var(--ease)}
.testi.in .testi-quote{opacity:1;translate:0}
@media (prefers-reduced-motion:reduce){
  .testi-quote{opacity:1;translate:none;transition:none}
}


/* ---- form pages: radios, the plain hero variant, and the unwired notice ---- */
.qf-lab{font-family:var(--font-label);font-size:.86rem;font-weight:600;color:var(--ink)}
.qf-radios{display:grid;gap:10px;margin-top:4px}
/* ⚠️ min-width:0 + overflow-wrap: a flex CHILD defaults to min-width:auto, so a
   long unbroken option ("Affiliate - You earn commissions for referrals") pushed
   the row past the viewport at 390 instead of wrapping. */
.qf-radio{display:flex;align-items:flex-start;gap:10px;font-family:var(--font-label);
  font-size:.95rem;color:var(--ink-soft);cursor:pointer;padding:11px 14px;
  border:1px solid var(--line-soft);border-radius:11px;background:var(--paper);
  min-width:0;transition:border-color .2s var(--ease),background .2s var(--ease)}
.qf-radio span{min-width:0;overflow-wrap:anywhere}
.qf-radios{min-width:0}
.qf-row,.qf-grid{min-width:0}
.qf-radio:hover{border-color:var(--brand-sky)}
.qf-radio input{accent-color:var(--brand-sky);margin-top:.16em;flex:none}
.qf-radio:has(input:checked){border-color:var(--brand-sky);background:#f2fbff}

/* The ACH consent tick and the terms it agrees to. The paragraph is small but
   deliberately NOT hidden behind a link: it is the thing being authorised. */
.qf-check{display:flex;align-items:flex-start;gap:10px;font-family:var(--font-label);
  font-size:.95rem;font-weight:600;color:var(--ink);cursor:pointer;padding:11px 14px;
  margin-top:4px;border:1px solid var(--line-soft);border-radius:11px;background:var(--paper);
  min-width:0;transition:border-color .2s var(--ease),background .2s var(--ease)}
.qf-check:hover{border-color:var(--brand-sky)}
/* ⚠️ the generic `.qf-row input` above sets width:100% + padding + border on
   EVERY input, which stretched this checkbox to the full 688px row and left
   its label 0px, wrapping "Agreed, Authorized" one letter per line. The
   radio rows escape it only because they sit inside .qf-radios. Reset here. */
.qf-check input{accent-color:var(--brand-sky);margin-top:.16em;flex:none;
  width:auto;min-width:0;padding:0;border:0;border-radius:0;background:none;
  box-shadow:none}
.qf-check span{min-width:0;overflow-wrap:anywhere}
.qf-check:has(input:checked){border-color:var(--brand-sky);background:#f2fbff}
.qf-legal{display:block;margin-top:10px;font-family:var(--font-label);font-size:.82rem;
  line-height:1.65;color:var(--ink-soft)}

/* ⚠️ the ACH page. Not a decoration — it is the only signal a visitor gets
   that the form will not submit, so it must read like a notice, not a hint. */
.qf-warn{background:#fdf6e6;border:1px solid #e6c98a;border-radius:11px;
  padding:13px 15px;color:#7a5a12;font-size:.9rem;line-height:1.55;margin:0 0 18px}
.qform button[disabled]{opacity:.45;cursor:not-allowed}

/* ⚠️ .is-flat = a band with NO photo behind it. .phero-title is white because
   every other hero sits on a dark image; on the flat grey band that measured
   1.11:1. The title takes normal ink here. */
.qhero.is-flat{color:var(--ink)}
.qhero.is-flat .phero-title{color:var(--ink)}
.qhero.is-flat .phero-title .accent{color:var(--brand-deep)}
/* ⚠️ --brand-deep measured 4.48:1 on the flat grey band, a hair under the 4.5
   body minimum. Same hue, one step darker, so the eyebrow still reads as brand
   blue rather than falling back to grey ink. */
.qhero.is-flat .phero-eyebrow{color:#12647f}

/* a form page with no testimonial gets the title in the band instead */
.qhero.is-plain{min-height:calc(clamp(200px,22vh,260px) + var(--hd-h))}
.qhero.is-plain .phero-title{margin:0}
.qhero.is-plain .phero-eyebrow{margin:0 0 10px}


/* ---- /terms-condition/ : legal prose ---- */
.doc{padding:var(--sec-y) var(--sec-x)}
.doc-inner{max-width:760px;margin:0 auto}
.doc-inner h2{font-family:var(--font-main);font-weight:400;
  font-size:clamp(1.3rem,2.4vw,1.72rem);line-height:1.25;color:var(--ink);
  margin:clamp(34px,4vw,52px) 0 14px}
.doc-inner h2:first-child{margin-top:0}
.doc-inner p{font-family:var(--font-label);font-size:1rem;line-height:1.78;
  color:var(--ink-soft);margin:0 0 16px}
.doc-inner ul{margin:0 0 18px;padding-left:22px}
.doc-inner li{font-family:var(--font-label);font-size:1rem;line-height:1.7;
  color:var(--ink-soft);margin-bottom:9px}
.doc-inner a{color:var(--brand-deep);font-weight:600}

/* ---- /reviews/ : the Google review wall ----
   Their plugin renders an avatar, a name, an age and a "read more/hide"
   toggle. Only the words are content; the rest is furniture. */
.reviews{padding:var(--sec-y) var(--sec-x)}
.rv-inner{max-width:var(--wrap);margin:0 auto}
.rv-grid{display:grid;gap:clamp(16px,2vw,24px);margin-top:clamp(30px,4vw,48px);
  grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}
.rv-card{margin:0;display:flex;flex-direction:column;background:var(--white);
  border:1px solid var(--line-soft);border-radius:clamp(14px,1.6vw,20px);
  padding:clamp(20px,2.2vw,28px);box-shadow:var(--shadow-sm)}
.rv-card blockquote{margin:0;flex:1}
.rv-card blockquote p{font-family:var(--font-label);font-size:.98rem;line-height:1.66;
  color:var(--ink-soft);margin:0}
.rv-card figcaption{display:flex;flex-wrap:wrap;gap:4px 10px;align-items:baseline;
  margin-top:18px;padding-top:16px;border-top:1px solid var(--line-soft)}
.rv-who{font-family:var(--font-label);font-size:.9rem;font-weight:600;color:var(--ink)}
.rv-when{font-family:var(--font-label);font-size:.8rem;color:var(--ink-soft)}

/* rule 7 */
.rv-card{opacity:0;translate:0 18px;
  transition:opacity .6s var(--ease),translate .6s var(--ease)}
.reviews.in .rv-card{opacity:1;translate:0;transition-delay:calc(var(--i,0)*55ms)}
@media (prefers-reduced-motion:reduce){
  .rv-card{opacity:1;translate:none;transition:none}
}


/* ============================================================
   /sitemap/
   ============================================================ */
/* ⚠️ .sr-only was USED but never defined, so the sitemap's "Search the site"
   label rendered as visible text beside the input. Any visually-hidden label
   anywhere on the site depends on this rule existing. */
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
.sitemap{padding:clamp(40px,5.5vh,68px) var(--sec-x) var(--sec-y)}
.sm-inner{max-width:var(--wrap);margin:0 auto}

.sm-search{position:relative;display:flex;align-items:center;max-width:620px}
.sm-ic{position:absolute;left:16px;display:flex;color:var(--ink-faint);pointer-events:none}
.sm-search input{width:100%;font-family:var(--font-label);font-size:1rem;color:var(--ink);
  background:var(--white);border:1px solid var(--line-soft);border-radius:100px;
  padding:15px 46px 15px 46px;box-shadow:var(--shadow-sm);
  transition:border-color .2s var(--ease),box-shadow .2s var(--ease)}
.sm-search input:focus-visible{outline:none;border-color:var(--brand-sky);
  box-shadow:0 0 0 3px rgba(44,171,226,.22)}
.sm-search input::-webkit-search-cancel-button{display:none}
.sm-clear{position:absolute;right:12px;width:26px;height:26px;border:0;border-radius:50%;
  background:var(--grey-100,#eceff1);color:var(--ink-soft);font-size:17px;line-height:1;
  cursor:pointer;display:flex;align-items:center;justify-content:center}
.sm-clear:hover{background:var(--brand-sky);color:#fff}
.sm-hint{font-family:var(--font-label);font-size:.86rem;color:var(--ink-soft);
  margin:12px 0 0}
.sm-hint strong{color:var(--ink)}

/* the full listing */
.sm-grid{display:grid;gap:clamp(22px,3vw,40px);margin-top:clamp(34px,4.5vw,58px);
  grid-template-columns:repeat(auto-fill,minmax(270px,1fr));align-items:start}
.sm-group h2{font-family:var(--font-label);font-size:.82rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--brand-deep);
  margin:0 0 14px;display:flex;align-items:center;gap:9px}
.sm-count{font-family:var(--font-label);font-size:.72rem;font-weight:600;
  letter-spacing:0;color:var(--ink-soft);background:var(--grey-100,#eceff1);
  border-radius:100px;padding:2px 8px}
.sm-group ul{list-style:none;margin:0;padding:0;display:grid;gap:2px}
/* a group with 90+ entries (the city pages) would be one absurdly tall column
   in the 270px grid, so it takes the full width and flows in CSS columns. */
.sm-group.sm-wide{grid-column:1 / -1}
.sm-group.sm-wide ul{display:block;columns:5;column-gap:clamp(14px,2vw,28px)}
.sm-group.sm-wide li{break-inside:avoid}
@media (max-width:1180px){.sm-group.sm-wide ul{columns:4}}
@media (max-width:900px){.sm-group.sm-wide ul{columns:3}}
@media (max-width:660px){.sm-group.sm-wide ul{columns:2}}
@media (max-width:440px){.sm-group.sm-wide ul{columns:1}}
.sm-group li a{display:block;font-family:var(--font-label);font-size:.95rem;
  line-height:1.45;color:var(--ink-soft);text-decoration:none;padding:7px 10px;
  border-radius:9px;transition:background .18s var(--ease),color .18s var(--ease)}
.sm-group li a:hover{background:var(--white);color:var(--brand-deep)}
.sm-more a{font-weight:600;color:var(--brand-deep)}

/* results */
.sm-loading{opacity:.75}
.sm-n,.sm-none{font-family:var(--font-label);font-size:.95rem;color:var(--ink-soft);
  margin:clamp(28px,3.5vw,44px) 0 16px}
.sm-n strong,.sm-none strong{color:var(--ink)}
.sm-none a{color:var(--brand-deep);font-weight:600}
.sm-hits{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.sm-hits a{display:grid;gap:4px;background:var(--white);border:1px solid var(--line-soft);
  border-radius:13px;padding:15px 18px;text-decoration:none;
  transition:border-color .2s var(--ease),transform .2s var(--ease),box-shadow .2s var(--ease)}
.sm-hits a:hover{border-color:var(--brand-sky);transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.sm-h-t{font-family:var(--font-main);font-weight:600;font-size:1.02rem;color:var(--ink)}
.sm-h-g,.sm-h-w{font-family:var(--font-label);font-size:.76rem;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--brand-deep)}
.sm-h-w{color:var(--ink-soft);font-weight:500;letter-spacing:.06em}
.sm-h-d{font-family:var(--font-label);font-size:.9rem;line-height:1.55;
  color:var(--ink-soft);margin-top:3px}
.sm-hits li:nth-child(n+2) a{}

/* ============================================================
   iOS ZOOM ON FOCUS  (client 2026-09-28: the AI search box "zooms in a bit
   and the layout shifts")

   Safari on iPhone zooms the page whenever a focused field's font-size is
   under 16px, then leaves the layout shifted. It is not a bug in the field,
   it is the size. Four rules were under the line:

     .ai-input                       14.7px   <- the one reported
     .bk-field input                 15.5px   booking widget
     .qf-row input/select/textarea   15.5px   every contact / quote / ACH field
     .qform .qf-half input           15.5px   the discovery page's extra field

   Fixed by size rather than by `maximum-scale=1` on the viewport, which also
   blocks deliberate pinch-zoom and is an accessibility regression.
   ⚠️ pointer:coarse, not a width query: an iPad at 800px zooms too, and a
   narrow desktop window does not.
   ============================================================ */
@media (pointer:coarse){
  .ai-input,
  .bk-field input,
  .qf-row input, .qf-row select, .qf-row textarea,
  .sm-search input{font-size:16px}
}

/* rule 7 */
.sm-search,.sm-hint,.sm-grid{opacity:0;translate:0 16px;
  transition:opacity .6s var(--ease),translate .6s var(--ease)}
.sm-hint{transition-delay:.07s}
.sm-grid{transition-delay:.14s}
.sitemap.in .sm-search,.sitemap.in .sm-hint,.sitemap.in .sm-grid{opacity:1;translate:0}
@media (prefers-reduced-motion:reduce){
  .sm-search,.sm-hint,.sm-grid{opacity:1;translate:none;transition:none}
}

/* footer credit — house standard on every client site */
.ft-credit{color:rgba(255,255,255,.72);text-decoration:none;border-bottom:1px solid rgba(255,255,255,.28)}
.ft-credit:hover{color:#fff;border-bottom-color:currentColor}


/* ============================================================
   Location pages (/oregon/<city>/, /washington/<city>/)
   ============================================================ */
.locsvc,.locblurb{padding:var(--sec-y) var(--sec-x)}
.locsvc-inner{max-width:var(--wrap);margin:0 auto}

/* their eight service links were a bullet list; as cards they read as
   navigation and actually pass link equity to the service pages. */
/* ⚠️ .lsv-, not .loc-. The globe component has owned .loc-card / .loc-card-img
   / .loc-card-head since line 813, and reusing those names inherited its
   styling: the service labels rendered as oversized letter-spaced uppercase
   and the globe card's rounded blue field showed through behind the grid.
   Check styles.css for an existing owner before picking a class prefix. */
/* ⚠️ FIXED 4 columns, not auto-fill. There are always exactly 8 service cards,
   so 4 across gives two even rows. auto-fill fitted 5 at 1440 and left a
   ragged 5 + 3. The step down is 4 -> 2 -> 1: three columns would give 3+3+2,
   which is the same raggedness one breakpoint lower. */
.lsv-grid{display:grid;gap:clamp(12px,1.5vw,18px);
  grid-template-columns:repeat(4,minmax(0,1fr))}
@media (max-width:1080px){.lsv-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){.lsv-grid{grid-template-columns:minmax(0,1fr)}}
.lsv-card{display:flex;align-items:center;gap:14px;background:var(--white);
  border:1px solid var(--line-soft);border-radius:14px;padding:16px 18px;
  text-decoration:none;box-shadow:var(--shadow-sm);
  transition:transform .22s var(--ease),box-shadow .22s var(--ease),border-color .22s var(--ease)}
.lsv-card:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);
  border-color:rgba(44,171,226,.45)}
.lsv-ic{flex:none;width:38px;height:38px;border-radius:10px;display:flex;
  align-items:center;justify-content:center;background:var(--sky-100,#e6f5fd);
  color:var(--brand-deep)}
.lsv-ic svg{width:20px;height:20px}
.lsv-card:hover .lsv-ic{background:var(--brand-sky);color:#fff}
/* ⚠️ min-width:0 — a flex child defaults to min-width:auto, so the longest
   label ("Virtual Desktop Infrastructure") pushed the arrow out of the card
   instead of wrapping. */
.lsv-name{font-family:var(--font-label);font-size:.98rem;font-weight:600;
  color:var(--ink);line-height:1.3;min-width:0;overflow-wrap:anywhere}
.lsv-card{min-width:0}
.lsv-go{margin-left:auto;display:flex;color:var(--brand-deep);
  transition:translate .22s var(--ease)}
.lsv-card:hover .lsv-go{translate:3px 0}

/* the two service blurbs, side by side. On the STATE HUBS a photo takes the
   first cell (where their redundant "Also serving" heading used to sit), so
   the row is image + blurb + blurb. */
.lsv-two{display:grid;gap:clamp(20px,3vw,44px);
  grid-template-columns:repeat(auto-fit,minmax(280px,1fr));align-items:start}
.lsv-figcell{display:block}
/* rule 1: the photo is capped so it never runs taller than the copy beside it.
   3:2 matches the shoot, and cover means the crop is the frame, not a squash. */
.lsv-fig{display:block;width:100%;aspect-ratio:3/2}
.lsv-fig img{display:block;width:100%;height:100%;object-fit:cover}
.lsv-blurb h3{font-family:var(--font-main);font-weight:600;
  font-size:clamp(1.06rem,1.7vw,1.22rem);line-height:1.35;color:var(--ink);margin:0 0 12px}
.lsv-blurb p{font-family:var(--font-label);font-size:.99rem;line-height:1.72;
  color:var(--ink-soft);margin:0}
.lsv-blurb a{color:var(--brand-deep);font-weight:600}

/* the sibling-city row. A name is a LINK once that page exists and plain text
   until then, so the mesh switches on as the 93 get built. */
/* ⚠️ NOT --ink-faint (3.26:1). These are city names — real content, not
   decoration. The linked/unlinked difference is carried by the hover underline
   on the anchors, not by dimming the text below the readable threshold. */
.lsv-cities li span{color:var(--ink-soft)}
.lsv-cities li a{color:var(--ink-soft);text-decoration:none;
  border-bottom:1px solid transparent;transition:color .18s var(--ease),border-color .18s var(--ease)}
.lsv-cities li a:hover{color:var(--brand-deep);border-bottom-color:currentColor}

/* rule 7 */
.lsv-card,.lsv-blurb{opacity:0;translate:0 18px;
  transition:opacity .6s var(--ease),translate .6s var(--ease),
             transform .22s var(--ease),box-shadow .22s var(--ease),border-color .22s var(--ease)}
.locsvc.in .lsv-card,.locblurb.in .lsv-blurb{opacity:1;translate:0;
  transition-delay:calc(var(--i,0)*55ms)}
@media (prefers-reduced-motion:reduce){
  .lsv-card,.lsv-blurb{opacity:1;translate:none;transition:none}
}

/* the hidden host that lets the booking modal borrow its widget on pages that
   deliberately have no booking section in the page flow. */
.bk-host{display:none!important}

/* ⚠️ LONG CTA LABELS ON SMALL PHONES.
   .btn sets white-space:nowrap, which is right for "Get a Quote" but not for
   "Schedule a compliance walkthrough" — that pill measures 370px and hung 10px
   past a 360px viewport on the industries pages, clipping its own right edge.
   Below 400px, let a long label take a second line instead. */
@media (max-width:400px){
  .btn{white-space:normal;text-align:center;max-width:100%}
}

/* ============================================================
   SERVICE CARD GRID (/cloud-services/) + TAB CARDS (/private-cloud/)
   Built on the industries pages' .outcomes/.oc-card, so it inherits their
   reveal and hover. onepage.py renders these; they used to be flattened into
   one text column that also cut off after five paragraphs.
   ============================================================ */
.svc-cards .oc-head{max-width:780px}
.svc-cards .oc-head p{margin-top:14px;color:var(--ink-soft);line-height:1.68}
.svc-cards .oc-head .sr-cta{margin-top:22px}
@media (min-width:1101px){
  .oc-grid[data-n="8"],.oc-grid[data-n="4"]{grid-template-columns:repeat(4,minmax(0,1fr))}
}
/* the whole card is the link; "Learn more" stays visible for touch screens */
a.oc-card{display:flex;flex-direction:column;color:inherit;text-decoration:none}
.svc-card p{flex:1}
.svc-more{margin-top:16px;display:inline-flex;align-items:center;gap:6px;
  font-family:var(--font-label);font-weight:600;font-size:.9rem;color:var(--link,#136a8c)}
.svc-more svg{transition:transform .25s var(--ease)}
a.oc-card:hover .svc-more svg{transform:translateX(3px)}
a.oc-card:focus-visible{outline:2px solid var(--brand-deep);outline-offset:3px}
.svc-help{margin-top:clamp(18px,2vw,26px);display:flex;align-items:center;justify-content:space-between;
  gap:clamp(18px,3vw,40px);background:#fff;border:1px solid var(--line-soft);border-radius:20px;
  padding:clamp(24px,2.8vw,36px);box-shadow:var(--shadow-sm)}
.svc-help h3{font-family:var(--font-main);font-weight:600;font-size:clamp(1.3rem,2vw,1.6rem);
  color:var(--ink);margin-bottom:8px}
.svc-help p{color:var(--ink-soft);line-height:1.65;max-width:62ch}
.svc-help .btn{flex:none}
@media (max-width:760px){.svc-help{flex-direction:column;align-items:flex-start}}
.svc-tab-label{font-family:var(--font-label);font-size:.74rem;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--brand-deep);margin-bottom:8px}
.svc-tab p{margin-bottom:10px}
.svc-tab .cred-list{margin-top:8px}
/* a later heading inside a split section (the first one is the section title) */
.sr-copy .sr-sub{font-family:var(--font-main);font-weight:600;font-size:1.18rem;
  line-height:1.3;color:var(--ink);margin:24px 0 8px}

/* ⚠️ LINKS INSIDE SECTION COPY MUST LOOK LIKE LINKS. These sections never
   styled an inline <a>, so "Learn More >" and "Book a Discovery Call >" sat
   in body colour and read as plain text (/cloud-services/, /colocation/,
   /private-cloud/), as did the three facility links in the remote-services
   hero and 93 city links on the state hubs.
   --link is --brand-deep one step darker: #17789f is 4.48:1 on the grey
   (#f2f3f4) sections, just under AA; this is 5.4:1 there. */
:root{--link:#136a8c}
.sr-copy p a:not(.btn),.sr-copy li a:not(.btn),.svc-cards .oc-head p a:not(.btn),.svc-tab p a:not(.btn),.svc-help p a:not(.btn){
  color:var(--link);font-weight:600;text-decoration:underline;text-decoration-thickness:1.5px;
  text-underline-offset:3px;text-decoration-color:rgba(19,106,140,.35);transition:text-decoration-color .2s}
.sr-copy p a:not(.btn):hover,.sr-copy li a:not(.btn):hover,.svc-cards .oc-head p a:not(.btn):hover{text-decoration-color:currentColor}
.phero-sub a{color:#a5e4fb;font-weight:600;text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(165,228,251,.5)}
.phero-sub a:hover{text-decoration-color:currentColor}
.areas li a{color:var(--link)}
.areas li a:hover{text-decoration:underline;text-underline-offset:3px}

/* /contact/ — the three offices, in the copy column beside the form */
.ct-locs{margin-top:clamp(26px,3vw,36px);padding-top:clamp(22px,2.6vw,30px);border-top:1px solid var(--line-soft)}
.ct-locs h3{font-family:var(--font-label);font-size:.78rem;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--brand-deep);margin-bottom:14px}
.ct-locs ul{list-style:none;display:grid;gap:16px}
.ct-locs li{display:grid;gap:3px;line-height:1.55;color:var(--ink-soft)}
.ct-locs b{font-family:var(--font-main);font-weight:600;color:var(--ink)}
.ct-locs a{justify-self:start;font-family:var(--font-label);font-weight:600;font-size:.88rem;
  color:var(--link);text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(19,106,140,.35)}
.ct-locs a:hover{text-decoration-color:currentColor}

/* ---- headline split section (/cloud-services/ "Cloud solutions, tailored…")
   label + state tags on one row, sentence headline, intro + its button, then
   the second idea as a callout with its own link. onepage.intro_copy(). ---- */
.sr-intro .sr-eyerow{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;margin-bottom:14px}
.sr-intro .sr-eyerow .oc-eyebrow{margin-bottom:0}
.sr-states{display:flex;gap:6px;list-style:none;margin:0;padding:0}
.sr-states li{font-family:var(--font-label);font-size:.72rem;font-weight:600;letter-spacing:.08em;
  color:var(--link,#136a8c);background:rgba(44,171,226,.1);border:1px solid rgba(44,171,226,.28);
  border-radius:999px;padding:4px 10px;line-height:1}
.sr-intro .oc-title{max-width:21ch;margin-bottom:20px}
/* a 4-word label + the state tags: the site-wide mobile eyebrow size (~17px)
   wraps it to two lines on a phone, with the dash stranded between them */
@media (max-width:560px){.sr-intro .sr-eyerow .oc-eyebrow{font-size:.8rem;letter-spacing:.1em}}
.sr-intro .sr-leadp{font-size:1.14rem;line-height:1.72;color:var(--ink-soft);max-width:54ch}
.sr-intro .sr-cta{margin-top:24px !important}
.sr-callout{margin-top:clamp(26px,3vw,34px);padding:18px 22px;border-radius:16px;background:#fff;
  border:1px solid var(--line-soft);border-left:4px solid var(--brand-sky);box-shadow:var(--shadow-sm);max-width:54ch}
.sr-callout p{font-size:.98rem !important;line-height:1.65;margin:0}
.sr-callout strong{color:var(--ink);font-weight:600}
.sr-callout .svc-more{margin-top:10px;text-decoration:none}
.sr-callout .svc-more:hover svg{transform:translateX(3px)}

/* paragraphs in split sections had NO gap between them: 31 pairs ran together
   on 8 pages (careers, cloud-services, dedicated-iaas, managed IT + 3 of its
   service pages, private-cloud) */
.sr-copy p + p:not(.sr-cta){margin-top:14px}

/* ============================================================
   FEATURE GRID — a long "Label: description" list, full width.
   /cloud-services/ "Why Choose Opus…" was eight 4-line bullets in half the
   width beside a stretched photo, labels in body weight. onepage.feature_section
   ============================================================ */
.features{padding:var(--sec-y) var(--sec-x)}
.feat-inner{max-width:var(--wrap);margin:0 auto}
.feat-head{max-width:760px;margin:0 0 clamp(26px,3.2vw,42px)}
.feat-head .oc-title{margin-bottom:14px}
.feat-head p{color:var(--ink-soft);line-height:1.72;font-size:1.08rem}
.feat-grid{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));column-gap:clamp(28px,4.5vw,72px)}
.feat{display:grid;grid-template-columns:48px minmax(0,1fr);gap:18px;align-items:start;
  padding:26px 0;border-top:1px solid var(--line-soft);
  opacity:0;translate:0 14px;transition:opacity .55s var(--ease) calc(var(--i,0)*55ms),translate .55s var(--ease) calc(var(--i,0)*55ms)}
.features.in .feat{opacity:1;translate:0}
.feat-ic{width:48px;height:48px;border-radius:14px;display:grid;place-items:center;
  background:rgba(44,171,226,.1);color:var(--link,#136a8c)}
.feat-ic svg{width:23px;height:23px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.feat h3{font-family:var(--font-main);font-weight:600;font-size:1.1rem;line-height:1.35;color:var(--ink);margin:2px 0 7px}
.feat p{font-family:var(--font-label);font-size:.98rem;line-height:1.68;color:var(--ink-soft)}
.feat-cta{margin-top:clamp(24px,3vw,36px) !important}
@media (max-width:760px){
  .feat-grid{grid-template-columns:minmax(0,1fr)}
  .feat{grid-template-columns:42px minmax(0,1fr);gap:14px;padding:22px 0}
  .feat-ic{width:42px;height:42px;border-radius:12px}
}
@media (prefers-reduced-motion:reduce){.feat{opacity:1;translate:none;transition:none}}

/* service cards: the client's icon per service (same art as the mega menu),
   on the menu's tile, with the menu's hover flip. --ic-knock must match the
   tile behind the icon or its white cut-outs read as blobs. */
.svc-ic{width:54px;height:54px;border-radius:15px;display:grid;place-items:center;margin-bottom:18px;
  background:linear-gradient(150deg,#e9f7fe,#f4fbff);border:1px solid rgba(42,196,244,.22);
  color:var(--brand-deep);--ic-knock:#f1fafe;
  transition:background .25s var(--ease),border-color .25s var(--ease),color .25s var(--ease)}
.svc-ic svg{width:28px;height:28px;overflow:visible}
a.svc-card:hover .svc-ic{background:linear-gradient(150deg,var(--brand),var(--brand-deep));
  border-color:transparent;color:#fff;--ic-knock:#2299cc}

/* ⚠️ --head-gap is a full --sec-y (150px): right BETWEEN sections, far too much
   between a heading and its own content. /cloud-services/ showed 150px under
   "Cloud Services For All Your Enterprise Needs" and under "Blog Posts", against
   14-60px under every other heading. Same fix as .values / .duo above; the
   homepage keeps its approved spacing. */
.svc-cards .oc-head,.recent-posts .oc-head{margin-bottom:clamp(34px,4vw,56px)}

/* ⚠️ CENTRED EYEBROWS NEED A LINE ON BOTH SIDES. .oc-eyebrow draws its accent
   line as ::before only, which is right when it is left-aligned. Centred (the
   pricing band on every service + city page), "— GETTING STARTED" sat lopsided
   next to "—— RESULTS ——". Same treatment as .oc-eyebrow.is-centred. */
.pricing-inner .oc-eyebrow::after{content:"";height:2px;width:17px;flex:none;background:currentColor}

/* numbered steps in a band (/dedicated-iaas/ "Begin in three easy steps:") */
.pricing-inner.has-steps{max-width:1100px}
.pricing-inner.has-steps > p:not(.pricing-cta){max-width:640px;margin-left:auto;margin-right:auto}
.band-steps{list-style:none;margin:clamp(22px,2.6vw,32px) 0 0;padding:0;counter-reset:none;
  display:grid;grid-template-columns:repeat(var(--n,3),minmax(0,1fr));gap:clamp(16px,2vw,24px);text-align:left;position:relative}
.band-steps[data-n="2"]{--n:2}.band-steps[data-n="3"]{--n:3}.band-steps[data-n="4"]{--n:4}
.band-steps li{position:relative;background:#fff;border:1px solid var(--line-soft);border-radius:20px;
  padding:clamp(22px,2.4vw,30px);box-shadow:var(--shadow-sm)}
.band-steps .step-n{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;margin-bottom:16px;
  font-family:var(--font-main);font-weight:600;font-size:1.05rem;color:#fff;
  background:linear-gradient(150deg,var(--brand),var(--brand-deep))}
.band-steps h3{font-family:var(--font-main);font-weight:600;font-size:1.1rem;color:var(--ink);margin-bottom:8px}
.band-steps p{font-size:.97rem !important;line-height:1.65 !important;color:var(--ink-soft);margin:0 !important}
/* a thin connector between the numbered circles */
@media (min-width:761px){
  .band-steps li:not(:last-child)::after{content:"";position:absolute;top:calc(clamp(22px,2.4vw,30px) + 20px);
    left:calc(100% - clamp(22px,2.4vw,30px) + 10px);width:calc(clamp(16px,2vw,24px) + clamp(22px,2.4vw,30px)*2 - 20px);
    height:2px;background:linear-gradient(90deg,rgba(44,171,226,.5),rgba(44,171,226,.15));z-index:1}
}
.band-after{margin-top:clamp(22px,2.6vw,30px) !important}
@media (max-width:760px){.band-steps{grid-template-columns:minmax(0,1fr)}}

/* ---- /private-cloud/ "Why Choose Opus Interactive" tab cards ---- */
.svc-tabs .oc-head{max-width:820px}
.svc-ask{margin-top:22px !important;font-family:var(--font-main);font-weight:600;color:var(--ink) !important}
.svc-tabs .svc-ask + .sr-cta{margin-top:14px !important}
.svc-uses{list-style:none;margin:6px 0 0;padding:0;display:grid;gap:12px}
.svc-uses li{font-size:.95rem;line-height:1.6;color:var(--ink-soft);padding-left:14px;border-left:2px solid rgba(44,171,226,.35)}
.svc-uses strong{color:var(--ink);font-weight:600}
.svc-steps{list-style:none;margin:8px 0 0;padding:0;counter-reset:st;display:grid;gap:14px}
.svc-steps li{counter-increment:st;position:relative;padding-left:40px;font-size:.95rem;line-height:1.6;color:var(--ink-soft)}
.svc-steps li::before{content:counter(st);position:absolute;left:0;top:0;width:26px;height:26px;border-radius:50%;
  display:grid;place-items:center;font-family:var(--font-main);font-weight:600;font-size:.82rem;color:#fff;
  background:linear-gradient(150deg,var(--brand),var(--brand-deep))}
.svc-tab .svc-tab-label{color:var(--link,#136a8c)}   /* beats .oc-card p */

/* ============================================================
   ⚠️ EVERY DASHED LABEL GETS A DASH ON BOTH SIDES (client rule, 2026-09-11)
   "If we use a dash eyebrow we need to have it on both sides", matching the
   homepage, whose callout marks are the single source of truth above
   (solid 2px x 17px, square-cut, currentColor, 12px from the text).
   Four label styles drew a leading dash only: the section label
   (.oc-eyebrow), the hero label (.phero-eyebrow, whose trailing dash was
   HIDDEN on purpose on inner pages), the industry deep-dive label and the
   About Mission/Vision label. 804 one-sided labels on 133 pages.
   A NEW dashed label must draw both marks, or reuse one of these classes.
   Check with ~/pw-tools/_dashes.js (catches hidden dashes too).
   ============================================================ */
.oc-eyebrow::after,
.dive-eyebrow::after,
.phero-eyebrow::after{
  content:"";display:block;height:2px;width:17px;flex:none;border-radius:0;background:currentColor;
}
.mv-card .mv-eyebrow{gap:12px}
.mv-card .mv-eyebrow::before,
.mv-card .mv-eyebrow::after{content:"";display:block;height:2px;width:17px;flex:none;background:currentColor}

/* ⚠️ ONE LABEL SIZE. .oc-eyebrow is a <p>, so a section's paragraph rule
   (.sr-copy p, .pricing-inner p, .feat-head p … all 0,1,1) out-specified it
   (0,1,0) and set every label in those sections at 16.6-17.3px, against
   12.2-12.5px for every homepage label style and for .oc-eyebrow everywhere
   else. The doubled class is only there to win that fight. */
.oc-eyebrow.oc-eyebrow{font-size:.78rem;letter-spacing:.18em;line-height:1.45;font-weight:600}

/* on a phone a long label can still wrap; as flex items the two dashes then
   float out on either side of a two-line block. Inline, they sit before the
   first word and after the last, like punctuation. */
@media (max-width:560px){
  .oc-eyebrow,.phero-eyebrow,.dive-eyebrow{display:block}
  /* ⚠️ Each dash is a no-break space with the line painted as its background,
     NOT an inline-block. An inline-block is a line-break opportunity, so on a
     long label ("Pricing and getting started") the trailing dash wrapped onto
     a line of its own. A no-break space stays glued to the word beside it.
     Doubled classes: section-specific dash rules (.pricing-inner .oc-eyebrow::after)
     are 0,2,1 and otherwise repaint the whole glued space solid. */
  .oc-eyebrow.oc-eyebrow::before,.phero-eyebrow.phero-eyebrow::before,.dive-eyebrow.dive-eyebrow::before,
  .oc-eyebrow.oc-eyebrow::after,.phero-eyebrow.phero-eyebrow::after,.dive-eyebrow.dive-eyebrow::after{
    display:inline;content:"\00a0";width:auto;height:auto;position:static;
    background:linear-gradient(currentColor,currentColor) no-repeat;background-size:17px 2px}
  .oc-eyebrow.oc-eyebrow::before,.phero-eyebrow.phero-eyebrow::before,.dive-eyebrow.dive-eyebrow::before{
    padding-right:17px;margin-right:6px;background-position:left 55%}
  .oc-eyebrow.oc-eyebrow::after,.phero-eyebrow.phero-eyebrow::after,.dive-eyebrow.dive-eyebrow::after{
    padding-left:17px;margin-left:6px;background-position:right 55%}
}

/* ============================================================
   HOME / INDUSTRY HERO ON PHONES (client, 2026-09-11)
   The white card filled the whole screen and hid the photo. On a phone:
   - the photo is a band at the top, sized so ~80% of the scene's width shows
     (full-height "cover" on a tall screen showed a ~25% slice of sky)
   - the card starts ~25% of the screen below the header, overlapping the
     photo's bottom edge, and everything inside it is set smaller
   Desktop is untouched: every rule here is inside max-width:640px.
   --hero-mx: which part of the photo to keep (the racks sit right of centre).
   ============================================================ */
.hero-photo{--hero-mx:50%}
.hero-photo[src*="hero-cages"]{--hero-mx:70%}
@media (max-width:640px){
  .hero{display:block;min-height:0;background:var(--paper);
    padding:calc(var(--hd-h,81px) + 25svh) 16px 44px}
  .hero-photo{bottom:auto;height:calc(var(--hd-h,81px) + 25svh + 44px);
    object-position:var(--hero-mx) 62%;animation:none;
    -webkit-mask-image:linear-gradient(#000 82%,transparent);mask-image:linear-gradient(#000 82%,transparent)}
  .hero-stack{max-width:none;--stack-r:22px}
  .hero-card{padding:20px 18px 22px;border-radius:22px}
  .hero-eyebrow{font-size:.66rem;letter-spacing:.13em;margin-bottom:10px;gap:10px}
  .hero-title{font-size:clamp(1.5rem,6.6vw,1.8rem);line-height:1.14}
  .hero-sub{font-size:.94rem;line-height:1.55;margin-top:10px}
  .hero-cta{flex-direction:row;flex-wrap:nowrap;gap:8px;margin-top:16px}
  .hero-cta .btn{flex:1 1 0;justify-content:center;font-size:.9rem;--pad-y:11px;--pad-x:10px;white-space:nowrap}
  .trust-list{gap:5px;margin-top:16px}
  .trust-list li{font-size:.68rem;padding:3px 8px;border-radius:7px}
}

/* ⚠️ CLOUD LAYER ON PHONES/TABLETS (.advantages "Why Opus Interactive" and
   every .bg-clouds strip). The layer is 128% of the section's HEIGHT but the
   photo inside is sized to its WIDTH (135% auto). Once the bento cards stack,
   the section is ~2,400px tall and the photo only ~290px, sitting almost
   entirely ABOVE the section; the scroll parallax (+/-100px, --adv-par) then
   dragged its hard bottom edge into view as a darker strip that moved as you
   scrolled. Here the layer gets a fixed height the photo COVERS, starting
   110px above the section so the 100px drift never opens a gap, and the
   existing fade (50%->73% of the layer) melts it into the section blue.
   Desktop (>980px) keeps its original rule. */
@media (max-width:980px){
  .advantages::before,.bg-clouds::before{
    top:-110px;height:min(128%,1000px);
    background-size:100% 100%, cover;
    background-position:top center, center top;
  }
}

/* Solutions panel: keep the two engineers' faces clear of the text overlay */
.sol-media img[src*="engineers-walking-aisle"]{object-position:50% 30%}

/* booking widget: time-zone note under the slots, and a real error line
   (the widget used to confirm without sending anything) */
.bk-tz{margin-top:10px;font-family:var(--font-label);font-size:.78rem;color:var(--ink-soft)}
.bk-err{margin:4px 0 12px;padding:10px 12px;border-radius:10px;font-size:.88rem;line-height:1.5;
  color:#8a2b12;background:#fdf0ec;border:1px solid #f3c7b8}
/* the discovery page's extra "What are you solving for?" box: same look as the inputs */
.bk-field textarea{width:100%;font-family:var(--font-main);font-size:.97rem;color:var(--ink);resize:vertical;min-height:84px;
  padding:13px 15px;border:1px solid var(--line);border-radius:12px;background:var(--paper);outline:none;
  transition:border-color .2s var(--ease),box-shadow .2s var(--ease)}
.bk-field textarea:focus{border-color:var(--brand);box-shadow:0 0 0 3px rgba(42,196,244,.18)}

/* booking PAGES (/schedule-a-discovery/): on a phone the calendar is the point
   of the page, so it follows the heading + intro and the contact cards move
   below it (they pushed it ~350px down). The site-wide booking section keeps
   its order. */
@media (max-width:900px){
  .bk-page .bk-inner{row-gap:0}          /* the 40px grid gap now sat between label, title and intro */
  .bk-page .bk-info{display:contents}
  .bk-page .bk-eyebrow,.bk-page .bk-title,.bk-page .bk-sub{order:0}
  .bk-page .stacked{order:1;margin-top:30px}
  .bk-page .bk-contact{order:2;margin-top:34px}
}

/* heading inside the booking card, above the step tabs (every booking widget,
   client approved 2026-09-11 after a trial on /schedule-a-discovery/) */
.bk-card-title{font-family:var(--font-main);font-weight:600;font-size:1.2rem;letter-spacing:-.01em;
  color:var(--ink);margin:0 0 16px}

/* ---- a pricing band on an image field (Veeam "Fully Managed…", trial) ----
   The field is the picture; the copy sits on the same readability card the
   split sections and facility pages use. Card on the RIGHT, client's call after
   seeing it on the left; the big turbine then stays open on the left. */
.pricing.is-field .pf-wrap{max-width:var(--wrap);margin:0 auto}
.pricing.is-field .pricing-card{margin:0 0 0 auto;max-width:620px;text-align:left;color:var(--ink);
  background:rgba(255,255,255,.94);padding:clamp(28px,3.2vw,46px);
  border-radius:clamp(18px,2.2vw,28px);box-shadow:var(--shadow-md)}
.pricing.is-field .pricing-card .oc-eyebrow{justify-content:flex-start;color:var(--brand-deep)}
.pricing.is-field .pricing-card .oc-title{color:var(--ink)}
.pricing.is-field .pricing-card p{color:var(--ink-soft);margin-left:0;margin-right:0}
.pricing.is-field .pricing-cta{text-align:left}

/* a section you jump to (#faqs, #facility …) stops below the fixed header
   instead of under it; the header is 81-85px tall */
main section[id]{scroll-margin-top:calc(var(--hd-h,81px) + 12px)}

/* ============================================================
   WORLD-CLASS COLOCATION — BACK TO SPACE  (client 2026-09-23:
   "swap the background to actual")
   The globe is a photoreal night Earth and it had been cut out onto a flat
   #2cabe2 swatch, so a real photograph was floating on a poster colour. This
   puts the section back on the dark field it was designed for: near-black with
   the star layer showing in the top band, easing into the #242425 that White
   Glove opens on so the two sections meet without a seam.
   ⚠️ Scoped to .loc-* / .stk-loc ONLY. The cyan conversion higher up the file
   set .loc-, .glove- and .cs- together in shared selectors; White Glove and
   Cloud Services stay exactly as they are.
   ⚠️ Lives at the END of the file on purpose — it has to outrank the blue-field
   blocks at ~1914, ~1935 and ~2118, which are all the same specificity.
   ============================================================ */
.locations{
  /* matched to the globe photo's own space, which samples #061123 at its top
     edge down to #02070d at the bottom — the section field has to be the same
     black or the cut-out edge of the image shows as a vertical seam. The ramp
     to #242425 is held back to the last 12%, which is the section's bottom
     padding, BELOW the globe, and is what hands off to White Glove. */
  background:
    radial-gradient(110% 30% at 50% 0%,#0f2d46 0%,rgba(15,45,70,0) 70%),
    linear-gradient(180deg,#05101f 0%,#040a13 30%,#03080e 88%,#242425 100%);
}
/* ⚠️ THE SEAM. The globe is a JPEG with its own space baked in, so its
   rectangle meets the section's gradient on a hard edge, and the two blacks are
   not identical (#060f20 against #040a14 at the top, and at the bottom the
   section is already ramping to grey while the image is still near-black). That
   read as "a block of dark blue and black" rather than one smooth field.
   Rather than chase the image's colours — they vary across its own width, and
   the boundary moves per page — the image is faded out at top and bottom so
   there is no edge to see. The stops are safe: the disc and its glow occupy
   19%-80% of the frame, so 13% and 86% only ever touch empty space.
   The left stop matters above ~1800px, where the frame is narrower than the
   viewport and its left edge would otherwise cut a vertical line. */
.loc-globe{
  -webkit-mask-image:
    linear-gradient(180deg,transparent 0,#000 13%,#000 86%,transparent 100%),
    linear-gradient(90deg,transparent 0,#000 9%,#000 100%);
  mask-image:
    linear-gradient(180deg,transparent 0,#000 13%,#000 86%,transparent 100%),
    linear-gradient(90deg,transparent 0,#000 9%,#000 100%);
  -webkit-mask-composite:source-in;
          mask-composite:intersect;
}
/* the starfield was built with the section and switched off when it went blue.
   z-index:-1 keeps it above the background and under every bit of content —
   safe because .locations already sets isolation:isolate, so it cannot fall
   behind the page. The mask is what keeps it a TOP band rather than a wash. */
.loc-stars{
  display:block;position:absolute;inset:0;z-index:-1;pointer-events:none;
  -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 26%,transparent 58%);
          mask-image:linear-gradient(180deg,#000 0%,#000 26%,transparent 58%);
}
/* heading block: back to white type and cyan accents */
/* ---- phones only: the World-Class Colocation band (client 2026-09-28) ----
   Desktop and tablet are untouched; all three of these are <=600 problems. */
@media (max-width:600px){
  /* 1. "THREE REGIONS · THREE POWER GRIDS" wrapped to two lines. At the
        desktop .92rem/.16em it needs 419px against 350px of room. .70rem/.10em
        needs 302px, which still fits a 360px phone with room to spare. */
  .loc-eyebrow{font-size:.70rem;letter-spacing:.10em;gap:9px}
  .loc-eyebrow::before,.loc-eyebrow::after{width:22px}

  /* 2. The earth sat hard right. ⚠️ object-position alone could not fix it:
        the box ratio (2752/1536) matched the photo's (1.792) exactly, so
        nothing was being cropped and there was nothing to pan. Squaring the
        box on phones makes cover crop the width, and THEN the disc — whose
        centre is at 70.5% of the image — can be pulled to the middle. */
  .loc-globe{aspect-ratio:1/1}
  .loc-globe img{object-position:96% 50%}

}

.loc-eyebrow{color:#a5e4fb}
.loc-title{color:#fff}
.loc-title .accent{color:var(--brand)}
.loc-intro{color:rgba(255,255,255,.78)}
/* the blue backing layer was deepened to stay visible against cyan; on black
   the brand blue itself reads, so it goes back to matching every other stack */
.stk-loc .stack-blue{background:#2cabe2}
/* The card stays WHITE on the black field (client 2026-09-23). The dark-glass
   treatment it had on the blue is deliberately NOT restored here — the "white
   surface, dark type" block further up the file carries it, and only its
   shadow is deepened so a light card reads as lifted off space rather than
   pasted onto it. */
.stk-loc .loc-card{box-shadow:0 30px 70px -24px rgba(0,0,0,.7)}

/* Pages that drop the heading block (the facility and data-centre pages) put
   the globe 7px under the section's top edge, against 441px on the home page
   where the copy makes the room. Without the heading there is nothing to make
   it, so the section buys its own: the stage is a normal-flow child, and the
   globe is absolute WITHIN the stage, so padding here moves both. */
.locations:not(:has(.loc-head)){padding-top:clamp(84px,11vh,150px)}

/* ---- 404 ----------------------------------------------------------------
   Deliberately quiet: a stranger landing here followed a broken link, so the
   page leads with the way OUT (the assistant) rather than with the error.
   Reuses the system tokens only, no new colours. */
.nf{padding:calc(var(--hd-h) + 90px) 24px 130px;background:var(--paper);min-height:68vh;display:flex;align-items:center}
.nf-inner{max-width:720px;margin:0 auto;text-align:center;width:100%}
.nf-eyebrow{margin:0 0 18px;font-family:'IBM Plex Sans',Helvetica,Arial,sans-serif;font-size:.78rem;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--brand-deep);display:flex;align-items:center;justify-content:center;gap:6px}
.nf-dash{display:inline-block;width:17px;height:2px;background:var(--brand-deep)}
.nf-title{margin:0;font-family:'Poppins',Helvetica,Arial,sans-serif;font-weight:600;letter-spacing:-.02em;
  line-height:1.1;font-size:clamp(2.1rem,5.2vw,3.35rem);color:var(--ink)}
.nf-title .accent{color:var(--brand-sky)}
.nf-sub{margin:18px auto 0;max-width:520px;font-size:1.04rem;line-height:1.7;color:var(--ink-soft)}

/* the search: the page's primary action, so it is the biggest thing on it */
.nf-form{position:relative;display:flex;align-items:center;margin:34px auto 0;max-width:560px;
  background:var(--white);border:1px solid var(--line);border-radius:100px;box-shadow:var(--shadow-sm);
  transition:border-color .18s ease,box-shadow .18s ease}
.nf-form:focus-within{border-color:var(--brand-sky);box-shadow:0 0 0 4px rgba(44,171,226,.13)}
.nf-in-ic{position:absolute;left:22px;width:16px;height:16px;border:2px solid var(--ink-faint);border-radius:50%;pointer-events:none}
.nf-in-ic::after{content:'';position:absolute;right:-6px;bottom:-5px;width:7px;height:2px;background:var(--ink-faint);transform:rotate(45deg)}
.nf-input{flex:1;min-width:0;border:0;background:none;outline:none;padding:18px 8px 18px 52px;
  font-family:'Poppins',Helvetica,Arial,sans-serif;font-size:1rem;color:var(--ink)}
.nf-input::placeholder{color:var(--ink-faint)}
.nf-send{flex:none;margin:6px;width:44px;height:44px;border:0;border-radius:50%;background:var(--brand-sky);color:#fff;
  display:grid;place-items:center;cursor:pointer;transition:background .18s ease}
.nf-send:hover{background:var(--brand-mid)}

.nf-out{margin:26px auto 0;max-width:560px;text-align:left;background:var(--white);
  border:1px solid var(--line-soft);border-radius:20px;box-shadow:var(--shadow-sm);padding:24px 26px}
.nf-answer{margin:0;font-size:1rem;line-height:1.68;color:var(--ink-soft)}
.nf-note{margin:0;font-size:.95rem;line-height:1.6;color:var(--ink-faint)}
.nf-cta{display:inline-block;margin-top:18px}

.nf-or{margin:44px 0 14px;font-size:.88rem;letter-spacing:.02em;color:var(--ink-faint)}
.nf-links{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:10px;justify-content:center}
.nf-links a{display:inline-block;padding:9px 18px;border:1px solid var(--line);border-radius:100px;
  background:var(--white);font-size:.92rem;color:var(--ink);text-decoration:none;transition:border-color .18s ease,color .18s ease}
.nf-links a:hover{border-color:var(--brand-sky);color:var(--brand-deep)}

@media (max-width:640px){
  .nf{padding:calc(var(--hd-h) + 54px) 20px 90px}
  .nf-input{padding:16px 6px 16px 46px}
  .nf-in-ic{left:18px}
}
/* iOS zooms any input under 16px on focus; same guard the other forms use */
@media (pointer:coarse){.nf-input{font-size:16px}}

/* ---- chips on the LIGHT-SCRIM hero -----------------------------------------
   ⚠️ .phero-bare's scrim is deliberately faint and goes FULLY TRANSPARENT at
   50% width, so the About patio faces read through it. The credential chips
   run to about 60% width, i.e. past the point where there is no scrim left at
   all, and their normal treatment is white text on rgba(255,255,255,.12) — a
   LIGHTER fill. Over a sunlit photo that is white on white and unreadable.
   These chips therefore carry their own dark backing instead of the hero being
   darkened, which would undo the lighter scrim that was asked for. */
.phero-bare .phero-chips li{
  background:rgba(6,22,34,.55);
  border-color:rgba(255,255,255,.3);
  backdrop-filter:blur(3px);
  -webkit-backdrop-filter:blur(3px)}

/* ---- image on a service/industry card ---------------------------------------
   .oc-card carries its own padding, so a full-bleed image has to cancel it with
   a matching negative margin, hence the repeated clamp(). Everything else
   mirrors .bc-media on the blog card (16:9, cover, slow zoom on hover) so an
   industry card and a post card behave identically. */
.svc-media{display:block;aspect-ratio:16/9;overflow:hidden;background:var(--sky-100);
  border-radius:19px 19px 0 0;
  margin:calc(clamp(24px,2.4vw,32px) * -1) calc(clamp(24px,2.4vw,32px) * -1) clamp(18px,1.8vw,22px)}
.svc-media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .5s var(--ease)}
a.svc-card:hover .svc-media img{transform:scale(1.04)}

/* ---- hero crossfade ---------------------------------------------------------
   Several .phero-photo frames stacked in one .phero-slides, cross-dissolving.
   ⚠️ EACH FRAME KEEPS ITS OWN --hero-y. The band shows only ~58% of an image's
   height, and these four photos put their subject at very different heights
   (the construction workers sit low, the rack engineers high), so one shared
   crop clips somebody in every cycle.
   The first frame is opaque without the animation too, so a browser that blocks
   or fails the animation still shows a hero rather than a blank band. Negative
   delay on that frame starts it already faded in, avoiding a flash on load. */
.phero-slides .phero-photo{opacity:0;animation:phero-fade 16s linear infinite}
.phero-slides .phero-photo:first-child{opacity:1}
/* ⚠️ THE -1s IS ON EVERY FRAME, NOT JUST THE FIRST. Frame 1 needs a negative
   delay so it is already faded in at load instead of flashing up from nothing.
   But a negative delay shifts that frame's whole window earlier, so leaving the
   others on exact 4s multiples gave frame 1 a FIVE second turn and the other
   three four, which reads as the first image lagging. Every delay carries the
   same -1s offset, so the changeovers land evenly at 3s, 7s, 11s and 15s. */
.phero-slides .phero-photo:nth-child(1){animation-delay:-1s}
.phero-slides .phero-photo:nth-child(2){animation-delay:3s}
.phero-slides .phero-photo:nth-child(3){animation-delay:7s}
.phero-slides .phero-photo:nth-child(4){animation-delay:11s}
/* 16s cycle / 4 frames = 4s each. The 6%/31% stops are a 1s dissolve at that
   cycle length; they are percentages, so shortening the cycle shortens the fade
   too unless they move with it. */
/* ⚠️ A FRAME NEVER FADES OUT. The obvious version (fade one out while the next
   fades in) dips through the page background: mid-dissolve BOTH frames are
   semi-transparent, so the near-white --paper behind them shows through and the
   hero visibly flashes pale between every photo.
   Instead every frame stays fully opaque once shown and the incoming one fades
   in OVER it, which needs the z-index to move with the opacity so the newest
   frame is on top. All three z-index values stay below the scrim's -1, or the
   photo would paint over the headline. */
@keyframes phero-fade{
  0%   {opacity:0; z-index:-2}
  6%   {opacity:1; z-index:-2}
  25%  {opacity:1; z-index:-3}
  100% {opacity:1; z-index:-4}}
@media (prefers-reduced-motion:reduce){
  .phero-slides .phero-photo{animation:none;opacity:0}
  .phero-slides .phero-photo:first-child{opacity:1}}

/* ---- hero crossfade progress ------------------------------------------------
   One bar per frame, the current one filling over its 4s. Four bars rather than
   a single sweeping line on purpose: the point is to say "there are four of
   these and you are on the second", which one line cannot.
   ⚠️ Delays MUST match .phero-slides above. They are two separate animations on
   the same timeline, so if the cycle length or the frame order changes here and
   not there, the bar fills against the wrong photo. */
.phero-ticks{position:absolute;left:0;right:0;bottom:clamp(20px,2.6vw,34px);z-index:1;
  padding:0 var(--sec-x);pointer-events:none}
.phero-ticks span{display:flex;gap:9px;max-width:var(--wrap);margin:0 auto}
.phero-ticks i{position:relative;display:block;height:3px;border-radius:99px;
  width:clamp(30px,4.2vw,54px);background:rgba(255,255,255,.32);overflow:hidden}
.phero-ticks i::after{content:"";position:absolute;inset:0;border-radius:inherit;
  background:#fff;transform:scaleX(0);transform-origin:left;
  animation:phero-tick 16s linear infinite}
.phero-ticks i:nth-child(1)::after{animation-delay:-1s}
.phero-ticks i:nth-child(2)::after{animation-delay:3s}
.phero-ticks i:nth-child(3)::after{animation-delay:7s}
.phero-ticks i:nth-child(4)::after{animation-delay:11s}
@keyframes phero-tick{
  0%{transform:scaleX(0)} 25%{transform:scaleX(1)}
  25.01%{transform:scaleX(0)} 100%{transform:scaleX(0)}}
@media (prefers-reduced-motion:reduce){
  .phero-ticks i::after{animation:none;transform:scaleX(0)}
  .phero-ticks i:first-child::after{transform:scaleX(1)}}

/* sub-line under an .oc-title, same treatment as .sr-sub elsewhere */
.oc-sub{margin-top:14px;font-size:clamp(1.02rem,1.25vw,1.16rem);
  line-height:1.68;color:var(--ink-soft)}
