/* ==========================================================================
   Bitwards website — shared stylesheet
   Brand: Night sky #0D1146 · Electric #0D4DDE · Cirrus #EFEFF4
          Sea foam #05B4A0 · Submarine #FDEA00
   Type:  Poppins (headings) · Open Sans (body), Arial fallback per brand guide
   ========================================================================== */

:root{
  --night:#0D1146; --electric:#0D4DDE; --cirrus:#EFEFF4; --white:#fff;
  --seafoam:#05B4A0; --submarine:#FDEA00; --danger:#C62828;
  --n80:rgba(13,17,70,.80); --n60:rgba(13,17,70,.60); --n40:rgba(13,17,70,.40);
  --w75:rgba(255,255,255,.75); --w50:rgba(255,255,255,.50);
  --maxw:1180px; --r:14px;
  --f-head:'Poppins','Century Gothic','Avenir Next','Segoe UI',Arial,sans-serif;
  --f-body:'Open Sans','Segoe UI',-apple-system,BlinkMacSystemFont,'Helvetica Neue',Arial,sans-serif;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{font-family:var(--f-body);font-size:17px;line-height:1.65;color:var(--night);background:#fff;-webkit-font-smoothing:antialiased}
h1,h2,h3,h4{font-family:var(--f-head);font-weight:600;line-height:1.14;letter-spacing:-.02em}
h1{font-size:clamp(2.3rem,4.5vw,3.8rem);font-weight:700}
h2{font-size:clamp(1.8rem,3vw,2.6rem)}
h3{font-size:1.2rem}
p{max-width:68ch}
a{color:inherit;text-decoration:none}
img{max-width:100%}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 28px}
section{padding:100px 0}
.eyebrow{font-family:var(--f-head);font-weight:600;font-size:.78rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--electric);margin-bottom:18px}
.eyebrow.light{color:#8FB4FF}
.lede{font-size:1.13rem;color:var(--n80);margin-top:18px}
.lede.light{color:var(--w75)}
.center{text-align:center}
.center p{margin-left:auto;margin-right:auto}
.dark{background:var(--night);color:#fff}
.dark h2,.dark h3{color:#fff}
.tint{background:var(--cirrus)}

/* ---------- buttons ---------- */
/* background:transparent and appearance:none matter for <button class="btn">:
   a button carries the browser's own light-grey face by default, so .btn-ghost
   — which sets white text and nothing else — rendered white-on-grey and was
   effectively invisible. The <a> siblings never had the problem, which is why
   only one of the three buttons in the CTA disappeared. */
.btn{display:inline-flex;align-items:center;gap:9px;font-family:var(--f-head);font-weight:600;
  font-size:.96rem;padding:15px 27px;border-radius:9px;border:1.5px solid transparent;
  background:transparent;-webkit-appearance:none;appearance:none;
  cursor:pointer;transition:.18s;white-space:nowrap}
.btn-primary{background:var(--electric);color:#fff}
.btn-primary:hover{background:#0B41BC;transform:translateY(-1px)}
.btn-ghost{border-color:rgba(255,255,255,.42);color:#fff}
.btn-ghost:hover{border-color:#fff;background:rgba(255,255,255,.1)}
.btn-outline{border-color:rgba(13,17,70,.25);color:var(--night)}
.btn-outline:hover{border-color:var(--night);background:rgba(13,17,70,.04)}
.btn-white{background:#fff;color:var(--electric)}
.btn-white:hover{background:#EEF2FF}
.arrow{font-family:var(--f-head);font-weight:600;color:var(--electric);
  display:inline-flex;align-items:center;gap:7px;font-size:.95rem}
.arrow i{font-style:normal;transition:transform .18s}
.arrow:hover i{transform:translateX(4px)}
.arrow.light{color:#8FB4FF}
.btn-row{display:flex;gap:13px;flex-wrap:wrap;margin-top:34px}

/* ---------- nav ---------- */
header{position:sticky;top:0;z-index:900;background:var(--night);border-bottom:1px solid rgba(255,255,255,.1)}
.nav{display:flex;align-items:center;gap:32px;height:74px}
.logo{display:flex;align-items:center;line-height:0}
.logo img{height:26px;width:auto;display:block}
.foot .logo img{height:24px}
.nav ul{display:flex;gap:26px;list-style:none;margin-left:10px}
.nav ul a{color:var(--w75);font-size:.94rem;font-weight:600;padding:6px 0;
  border-bottom:2px solid transparent;transition:.15s}
.nav ul a:hover{color:#fff;border-color:var(--electric)}
.nav ul a.on{color:#fff;border-color:var(--electric)}
.nav ul a.soon{color:var(--w50);cursor:default}
.nav ul a.soon:hover{border-color:transparent}
.nav ul a.soon:after{content:"soon";font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;
  background:rgba(255,255,255,.14);padding:2px 6px;border-radius:4px;margin-left:6px;vertical-align:2px}
.nav-right{margin-left:auto;display:flex;align-items:center;gap:18px}
.lang{color:var(--w50);font-size:.85rem;font-weight:600}
.lang b{color:#fff}
.signin{color:#fff;font-size:.92rem;font-weight:600;border:1.5px solid rgba(255,255,255,.32);
  padding:9px 18px;border-radius:8px;transition:.15s}
.signin:hover{border-color:#fff}
/* the nav list carries a Sign in item for the collapsed mobile menu only —
   on a wide screen the button on the right is the one, and two would read as
   two different things */
.nav ul .m-signin{display:none}

/* ---------- hero ---------- */
.hero{background:radial-gradient(900px 520px at 82% -10%,rgba(13,77,222,.55),transparent 62%),
  radial-gradient(620px 420px at 2% 108%,rgba(5,180,160,.2),transparent 60%),var(--night);
  color:#fff;padding:62px 0 84px}
.hero h1{color:#fff}
/* The home page hero is white. The glow it used to carry moved INTO the stage
   (see below), so the film keeps the dark ground its artwork is drawn for and
   now reads as an object sitting on the page rather than a hole in it. */
.hero-light{background:#fff;color:var(--night);padding:48px 0 64px}
.hero-light h1,.hero-light h2{color:var(--night)}
.hero .lede{font-size:1.19rem;max-width:56ch}
.hero-2col{display:grid;grid-template-columns:1.06fr .94fr;gap:60px;align-items:center}
/* .hero-note removed with the "Finnish since 2016 · 300+ customers" line */

/* ---------- "no infrastructure" hero ---------- */
.gone{list-style:none;margin:26px 0 4px}
.gone li{position:relative;padding-left:22px;margin-bottom:9px;font-size:1.06rem;
  font-family:var(--f-head);font-weight:600;color:#fff}
.gone li:before{content:"";position:absolute;left:0;top:.62em;width:7px;height:7px;
  border-radius:50%;background:var(--electric)}
.gone li.keep{color:#fff}
.gone li.keep:before{background:var(--submarine)}
.pillars{display:grid;gap:12px}
.pillar{border:1px solid rgba(255,255,255,.16);border-radius:13px;padding:20px 22px;
  background:rgba(255,255,255,.05);display:flex;gap:16px;align-items:flex-start}
.pillar.core{background:linear-gradient(100deg,var(--electric),#2a6bf0);border-color:transparent}
.pillar .ic{flex:0 0 40px;width:40px;height:40px;border-radius:10px;background:rgba(255,255,255,.14);
  display:flex;align-items:center;justify-content:center}
.pillar .ic svg{width:20px;height:20px;stroke:#fff;fill:none;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}
.pillar h4{color:#fff;font-size:1.05rem;margin-bottom:3px}
.pillar p{color:var(--w75);font-size:.89rem;max-width:none;line-height:1.5}
.pillar.core p{color:rgba(255,255,255,.92)}
/* .pillar-foot removed with the "Four parts, one platform" line */

/* ---------- cards ---------- */
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;margin-top:48px}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:26px;margin-top:44px}
.card{border:1px solid rgba(13,17,70,.13);border-radius:var(--r);padding:32px;background:#fff;transition:.2s}
.card:hover{border-color:var(--electric);box-shadow:0 14px 40px rgba(13,17,70,.09);transform:translateY(-2px)}
/* a row of cards that needs to read as a set rather than as separate panels:
   a wash of brand blue, deep enough to separate them from a white section
   and light enough to leave the body copy at full contrast */
.grid-3.tinted .card{background:rgba(13,77,222,.055);border-color:rgba(13,77,222,.16)}
.grid-3.tinted .card:hover{background:rgba(13,77,222,.085);border-color:var(--electric)}
.grid-3.tinted .card .tag.dark{background:var(--electric);color:#fff}
/* a photo band across the top of a .card, the same idea as .seg-media on the
   home page: full bleed to the card edge, fixed height so a row stays level */
.card-media{margin:-32px -32px 20px;height:124px;overflow:hidden;
  border-radius:var(--r) var(--r) 0 0;background:rgba(13,77,222,.07);
  border-bottom:1px solid rgba(13,17,70,.08)}
.card-media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .35s ease}
.card:hover .card-media img{transform:scale(1.03)}
.card h3{font-size:1.32rem;margin-bottom:11px}
.card p{font-size:.97rem;color:var(--n80)}
.card .tag{display:inline-block;font-family:var(--f-head);font-weight:600;font-size:.72rem;
  letter-spacing:.1em;text-transform:uppercase;padding:5px 11px;border-radius:6px;
  background:rgba(13,77,222,.09);color:var(--electric);margin-bottom:16px}
.card .tag.teal{background:rgba(5,180,160,.14);color:#04907F}
.card .tag.dark{background:rgba(13,17,70,.09);color:var(--night)}
/* An icon beside each offering's tag. Same three tints as the tags themselves,
   so the badge and the label read as one unit rather than two decorations. */
.card-head{display:flex;align-items:center;gap:12px;margin-bottom:16px}
.card-head .tag{margin-bottom:0}
.card-ic{flex:0 0 84px;width:84px;height:84px;border-radius:20px;
  display:flex;align-items:center;justify-content:center;background:rgba(13,77,222,.09)}
.card-ic svg{width:62px;height:62px;fill:none;stroke:var(--electric);stroke-width:1.35;
  stroke-linecap:round;stroke-linejoin:round}
.card-ic.teal{background:rgba(5,180,160,.14)}
.card-ic.teal svg{stroke:#04907F}
.card-ic.navy{background:rgba(13,17,70,.08)}
/* the chip is drawn on a 24 grid, the door scenes on 32 — thin its stroke to match */
.card-ic.navy svg{stroke:var(--night);stroke-width:1.05}

/* A band at the top of each offering card. The two mobile products show the
   real app in a phone, running off the bottom edge so the screen can be read
   at a useful size; the licensing card shows its glyph in the same frame. */
.card-band{margin:-32px -32px 22px;height:176px;overflow:hidden;
  border-radius:var(--r) var(--r) 0 0;display:flex;justify-content:center;
  align-items:flex-start;padding-top:18px;background:rgba(13,77,222,.09)}
.card-band img{width:194px;height:auto;display:block}
.card-band.teal{background:rgba(5,180,160,.14)}
.card-band.navy{background:rgba(13,17,70,.08);align-items:center;padding-top:0}
.card-band svg{width:96px;height:96px;fill:none;stroke:var(--night);stroke-width:1.05;
  stroke-linecap:round;stroke-linejoin:round}
/* licensing has no app of its own to show — a photograph of somebody else's
   app, with our SDK inside it, says the same thing more plainly */
.card-band.shot{padding:0;align-items:stretch}
.card-band.shot img{width:100%;height:100%;object-fit:cover}
/* The cards in a row are the same height already (grid stretches them), so
   pushing the closing link down with auto margin lands all three on one line
   however long the copy above it runs. */
.offers .card{display:flex;flex-direction:column}
.offers .card > .arrow{margin-top:auto;padding-top:14px}
.ticks{list-style:none;margin:20px 0}
.ticks li{position:relative;padding-left:26px;margin-bottom:10px;font-size:.95rem;color:var(--n80)}
.ticks li:before{content:"";position:absolute;left:0;top:8px;width:8px;height:8px;
  border-radius:2px;background:var(--electric)}
.ticks.teal li:before{background:var(--seafoam)}
.dark .ticks li{color:var(--w75)}
/* A .card brings its own white background, so inside a navy section its type has
   to stay dark. Without this, ".dark .ticks li" (two classes) beats ".ticks li"
   and paints the bullet list white on a white card. */
.dark .card h3{color:var(--night)}
.dark .card p{color:var(--n80)}
.dark .card .ticks li{color:var(--n80)}
.dark .card .arrow{color:var(--electric)}

/* ---------- advantage grid ---------- */
.adv-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(252px,1fr));gap:20px;margin-top:48px}
.adv{border:1px solid rgba(13,17,70,.13);border-radius:var(--r);padding:28px 26px;background:#fff;transition:.2s}
.adv:hover{border-color:var(--electric);box-shadow:0 12px 34px rgba(13,17,70,.09);transform:translateY(-2px)}
.adv .ic{width:42px;height:42px;border-radius:11px;background:rgba(13,77,222,.09);
  display:flex;align-items:center;justify-content:center;margin-bottom:17px}
.adv .ic svg{width:21px;height:21px;stroke:var(--electric);fill:none;stroke-width:1.85;
  stroke-linecap:round;stroke-linejoin:round}
.adv h3{font-size:1.1rem;margin-bottom:8px}
.adv p{font-size:.93rem;color:var(--n60);max-width:none}
.adv.hero-adv{background:linear-gradient(115deg,var(--electric),#0A2FA0 85%);border-color:transparent}
.adv.hero-adv h3{color:#fff}
.adv.hero-adv p{color:rgba(255,255,255,.86)}
.adv.hero-adv .ic{background:rgba(255,255,255,.18)}
.adv.hero-adv .ic svg{stroke:#fff}

/* ---------- split feature rows ---------- */
.row{display:grid;grid-template-columns:1fr 1fr;gap:60px;align-items:start;margin-top:52px}
.row.flip .row-media{order:-1}
.row-media{background:var(--cirrus);border-radius:16px;padding:30px}
.dark .row-media{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.13)}
.mini{border:1px solid rgba(13,17,70,.12);background:#fff;border-radius:10px;padding:14px 16px;margin-bottom:10px}
.mini b{font-family:var(--f-head);font-size:.95rem;display:block;margin-bottom:3px}
.mini span{font-size:.87rem;color:var(--n60)}
.dark .mini{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.14)}
.dark .mini span{color:var(--w50)}

/* ================= HERO FILM ================= */
.film{margin-top:40px}
/* The stage carries its own night sky now. Every act is drawn in white text and
   translucent white strokes with no background of its own, so this is what they
   are painted on — if it ever goes light, the film disappears. */
.stage{position:relative;width:100%;max-width:900px;margin:0 auto;aspect-ratio:640/380;
  background:radial-gradient(900px 520px at 82% -10%,rgba(13,77,222,.55),transparent 62%),
             radial-gradient(620px 420px at 2% 108%,rgba(5,180,160,.2),transparent 60%),
             var(--night);
  border:1px solid rgba(13,17,70,.10);border-radius:20px;overflow:hidden;
  box-shadow:0 18px 48px rgba(13,17,70,.16)}
.act{position:absolute;inset:0;display:none}
.act.on{display:block}
.act svg{width:100%;height:100%;display:block}
/* The act's claim, above the film. It changes with the act and fades in each
   time; min-height holds four lines' worth of space so the film never jumps as
   the claim changes length. Navy, because the hero is white now. */
.film-head{text-align:center;margin:0 auto 22px;max-width:24ch;
  font-family:var(--f-head);font-weight:700;letter-spacing:-.025em;line-height:1.12;
  font-size:clamp(1.5rem,3.4vw,2.5rem);color:var(--night);min-height:2.24em;
  display:flex;align-items:flex-end;justify-content:center}
.film-head.turn{animation:headIn .5s cubic-bezier(.2,.7,.3,1) both}
@keyframes headIn{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}

/* Below the film: four dots, centred, and no words at all. The act that is
   playing opens out into a short bar and fills as it runs; the others stay
   dots — darker for the acts already seen, lighter for those still to come —
   so the set doubles as a position indicator and as the navigation.

   The bar is the same element as the dot, widened. Animating width rather than
   swapping elements keeps the fill's animation uninterrupted: replacing the
   node would restart segFill, and segFill ending is what advances the film. */
.film-time{display:flex;justify-content:center;align-items:center;gap:6px;
  width:100%;max-width:900px;margin:16px auto 0}
.film-time .tick{flex:0 0 auto;padding:14px 6px;border:0;background:none;
  cursor:pointer;-webkit-appearance:none;appearance:none;line-height:0}
.film-time .tick i{display:block;position:relative;overflow:hidden;
  width:10px;height:10px;border-radius:50%;background:rgba(13,17,70,.40);
  transition:width .45s cubic-bezier(.4,0,.2,1),border-radius .45s,background .2s}
.film-time .tick.done i{background:rgba(13,17,70,.60)}
.film-time .tick:hover i{background:rgba(13,17,70,.72)}
.film-time .tick.now i{width:132px;border-radius:5px;background:rgba(13,17,70,.45)}
.film-time .tick i b{display:block;position:absolute;top:0;right:0;bottom:0;left:0;
  border-radius:5px;background:var(--electric);transform:scaleX(0);transform-origin:left center}
.film-time .tick.now i b{animation:segFill var(--act,10s) linear forwards}
.film-time.paused .tick.now i b{animation-play-state:paused}
.film-time .tick:focus-visible{outline:2px solid var(--electric);outline-offset:4px;border-radius:8px}
@keyframes segFill{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* for screen readers and crawlers only — the page still needs a real h1 */
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

.stage{cursor:pointer}
.stage-hint{position:absolute;inset:0;display:none;align-items:center;justify-content:center;
  background:rgba(8,12,48,.55);z-index:5;pointer-events:none}
.stage.paused .stage-hint{display:flex}
.stage-hint span{font-family:var(--f-head);font-weight:600;font-size:.9rem;color:#fff;
  background:rgba(13,17,70,.85);border:1.5px solid rgba(255,255,255,.3);
  padding:11px 20px;border-radius:99px;letter-spacing:.02em}
.stage.paused .act *{animation-play-state:paused !important}

/* --- shared film primitives --- */
.fly{transform-box:fill-box;transform-origin:center;opacity:0}
.pop{transform-box:fill-box;transform-origin:center;opacity:0}
.on .fly{animation:flyIn var(--dur,1.3s) cubic-bezier(.45,0,.2,1) forwards var(--d,0s)}
.on .pop{animation:popIn .62s cubic-bezier(.3,1.4,.4,1) forwards var(--d,0s)}
.on .draw{stroke-dasharray:var(--len,300);stroke-dashoffset:var(--len,300);
  animation:draw .9s ease forwards var(--d,0s)}
.on .undraw{animation:undraw .8s ease forwards var(--d,0s)}
/* One cable, drawn then retracted by TWO animations on the SAME element.
   The old arrangement used a second "undraw" path per cable, which carried a
   dash-array with offset 0 and was therefore fully drawn from frame one — every
   cable in the act was on screen before anything else had appeared. A wire now
   starts fully offset (invisible) and cannot exist before it is drawn. */
.wire{stroke-dasharray:var(--len,300);stroke-dashoffset:var(--len,300)}
.on .wire{animation:wireIn .9s ease forwards var(--d,0s),
                    wireOut .8s ease forwards var(--d2,99s)}
@keyframes wireIn{to{stroke-dashoffset:0}}
@keyframes wireOut{0%{stroke-dashoffset:0;opacity:1}
                   100%{stroke-dashoffset:var(--len,300);opacity:.15}}
.on .fade{opacity:0;animation:fadeIn .6s ease forwards var(--d,0s)}
.vanish{transform-box:fill-box;transform-origin:center}
.on .vanish{animation:vanish .9s ease forwards var(--d,0s)}
/* opacity:0 on the base class, not just in the keyframe — without it the ring
   is fully visible during its delay, i.e. from the first frame of the act */
.pulse{transform-box:fill-box;transform-origin:center;opacity:0}
.on .pulse{animation:pulse 1.1s ease-out forwards var(--d,0s)}

.travel{transform-box:fill-box;transform-origin:center;opacity:0}
.on .travel{animation:travel var(--tdur,2.8s) cubic-bezier(.5,0,.25,1) forwards var(--d,0s)}
@keyframes travel{
  0%{opacity:0;transform:translate(var(--fx,0),var(--fy,0)) scale(.5) rotate(0)}
  12%{opacity:1;transform:translate(var(--fx,0),var(--fy,0)) scale(1) rotate(var(--fr,0deg))}
  46%{opacity:1;transform:translate(var(--fx,0),var(--fy,0)) scale(1) rotate(var(--fr,0deg))}
  100%{opacity:0;transform:translate(0,0) scale(.16) rotate(0)}
}
.glide{transform-box:fill-box;transform-origin:center}
.on .glide{animation:glide var(--gdur,1.5s) cubic-bezier(.45,0,.2,1) forwards var(--d,0s)}
@keyframes glide{
  0%{transform:translate(var(--gx,0),var(--gy,0)) scale(var(--gs,1))}
  100%{transform:translate(0,0) scale(1)}
}
.gather{transform-box:fill-box;transform-origin:center;opacity:0}
.on .gather{animation:gather var(--gadur,2.2s) cubic-bezier(.5,0,.25,1) forwards var(--d,0s),
                      gfade .3s linear forwards var(--d2,6s)}
@keyframes gather{
  0%{opacity:0;transform:translate(var(--fx,0),var(--fy,0)) scale(.45)}
  16%{opacity:1;transform:translate(var(--fx,0),var(--fy,0)) scale(1)}
  70%,100%{opacity:1;transform:translate(0,0) scale(1)}
}
@keyframes gfade{to{opacity:0}}
/* A label that appears in place, waits, then travels — with the appearance and
   the departure on independent delays, so it can be synchronised exactly with
   whatever it is labelling. `labmove` below bakes its hold into fixed keyframe
   percentages, which meant the label always set off before its glyphs. */
.movelabel{transform-box:fill-box;transform-origin:center;opacity:0}
.on .movelabel{animation:mlIn .34s ease forwards var(--d,0s),
                         mlGo var(--mdur,1.2s) cubic-bezier(.5,0,.25,1) forwards var(--d2,99s)}
@keyframes mlIn{0%{opacity:0;transform:translate(var(--fx,0),var(--fy,0))}
                100%{opacity:1;transform:translate(var(--fx,0),var(--fy,0))}}
@keyframes mlGo{0%{opacity:1;transform:translate(var(--fx,0),var(--fy,0))}
                100%{opacity:1;transform:translate(0,0)}}
.labmove{transform-box:fill-box;transform-origin:center;opacity:0}
.on .labmove{animation:labmove var(--ldur,4.4s) cubic-bezier(.5,0,.25,1) forwards var(--d,0s)}
@keyframes labmove{
  0%{opacity:0;transform:translate(var(--fx,0),var(--fy,0))}
  7%{opacity:1;transform:translate(var(--fx,0),var(--fy,0))}
  20%{opacity:1;transform:translate(var(--fx,0),var(--fy,0))}
  64%,100%{opacity:1;transform:translate(0,0)}
}
@keyframes flyIn{
  0%{opacity:0;transform:translate(var(--fx,-160px),var(--fy,0)) scale(1.25) rotate(var(--fr,-12deg))}
  55%{opacity:1}
  100%{opacity:0;transform:translate(0,0) scale(.18) rotate(0)}
}
/* assemble: land on stage, HOLD as a group, then depart into the phone.
   Two animations so arrival and departure are timed independently — the
   hold is simply the gap between them, and asmIn's forwards fill covers it. */
.assemble{transform-box:fill-box;transform-origin:center;opacity:0}
.on .assemble{animation:asmIn  var(--adur,.8s)  cubic-bezier(.25,1.25,.4,1) forwards var(--ad,0s),
                        asmOut var(--odur,1.2s) cubic-bezier(.5,0,.25,1)    forwards var(--od,9s)}
@keyframes asmIn{
  0%{opacity:0;transform:translate(var(--fx,0),var(--fy,0)) scale(.4) rotate(0)}
  100%{opacity:1;transform:translate(var(--fx,0),var(--fy,0)) scale(1) rotate(var(--fr,0deg))}
}
@keyframes asmOut{
  0%{opacity:1;transform:translate(var(--fx,0),var(--fy,0)) scale(1) rotate(var(--fr,0deg))}
  62%{opacity:1}
  100%{opacity:0;transform:translate(0,0) scale(.16) rotate(0)}
}
/* fade in, then out again at a second, independent delay */
.fadeo{opacity:0}
.on .fadeo{animation:fadeIn var(--fi,.5s) ease forwards var(--d,0s),
                     fadeOut var(--fo,.45s) ease forwards var(--d2,9s)}
@keyframes fadeOut{to{opacity:0}}

/* --- things opening (Act 3) --- */
/* a leaf swinging away from its hinge: foreshortening, not rotation, so it
   stays readable at icon size and needs no 3D transform */
.swing,.swingR{transform-box:fill-box}
.swing{transform-origin:left center}
.swingR{transform-origin:right center}
.on .swing,.on .swingR{animation:swingOpen .5s cubic-bezier(.35,0,.2,1) forwards var(--d,0s)}
@keyframes swingOpen{to{transform:scaleX(.16)}}
.roll{transform-box:fill-box;transform-origin:center top}
.on .roll{animation:rollUp .5s cubic-bezier(.35,0,.2,1) forwards var(--d,0s)}
@keyframes rollUp{to{transform:scaleY(.1)}}
.shackle{transform-box:fill-box;transform-origin:right bottom}
.on .shackle{animation:shackleOpen .45s cubic-bezier(.3,1.5,.5,1) forwards var(--d,0s)}
@keyframes shackleOpen{to{transform:translateY(-3px) rotate(28deg)}}
/* traffic running along a wire (Act 4) */
.flow{stroke-dasharray:3 9;stroke-dashoffset:0;opacity:0}
.on .flow{animation:flowFade .4s ease forwards var(--d,0s),
                    flowRun 1.1s linear infinite var(--d,0s)}
@keyframes flowFade{to{opacity:.9}}
@keyframes flowRun{to{stroke-dashoffset:-24}}
.tapin{transform-box:fill-box;transform-origin:center;opacity:0}
.on .tapin{animation:tapIn .5s cubic-bezier(.3,1.3,.4,1) forwards var(--d,0s)}
@keyframes tapIn{0%{opacity:0;transform:translateY(-14px) scale(.7)}100%{opacity:1;transform:translateY(0) scale(1)}}
@keyframes popIn{0%{opacity:0;transform:scale(.7)}100%{opacity:1;transform:scale(1)}}
@keyframes draw{to{stroke-dashoffset:0}}
@keyframes undraw{to{stroke-dashoffset:var(--len,300);opacity:.15}}
@keyframes fadeIn{to{opacity:1}}
@keyframes vanish{to{opacity:0;transform:scale(.5)}}
@keyframes pulse{0%{opacity:0;transform:scale(.72)}35%{opacity:.9;transform:scale(1.04)}100%{opacity:0;transform:scale(1.16)}}

@media (prefers-reduced-motion: reduce){
  .on .fly,.on .pop,.on .draw,.on .undraw,.on .wire,.on .movelabel,.on .fade,.on .vanish,.on .pulse,.on .travel,.on .gather,.on .glide,.on .labmove,.on .assemble,.on .fadeo,.on .swing,.on .swingR,.on .roll,.on .shackle,.on .tapin,.on .flow{animation:none !important}
  .tapin{opacity:1}
  .flow{display:none}
  .labmove{opacity:1}
  .movelabel{opacity:1}
  .gather{display:none}
  .travel{display:none}
  .fly{display:none}
  .assemble{display:none}
  .fadeo{display:none}
  .wire{stroke-dasharray:none;stroke-dashoffset:0}
  .pulse{opacity:0}
  .pop,.fade{opacity:1}
  .on .draw{stroke-dashoffset:0}
  /* no crawling bar — the current act's segment simply reads as full, and the
     controller advances on a timer instead of on the animation ending */
  .film-time .tick.now i b{animation:none;transform:scaleX(1)}
  /* and the logo carousel stops moving. The script does not clone the list
     under reduced motion, so this only has to undo the rolling layout; the
     aria-hidden rule is a belt-and-braces against a duplicated row. */
  .marquee.rolling .track{animation:none;width:100%;justify-content:center;
    flex-wrap:wrap;gap:28px 44px}
  .marquee .track li[aria-hidden="true"]{display:none}
  .marquee{-webkit-mask-image:none;mask-image:none}
}

/* ---------- hero phone artwork ---------- */
.hero-phone{display:flex;justify-content:center}
.hero-phone svg{width:100%;max-width:340px;height:auto}

/* ---------- poster statement ---------- */
.poster{text-align:center;padding:22px 0 8px}
.poster .line{font-family:var(--f-head);font-weight:700;letter-spacing:-.03em;line-height:1.06;
  font-size:clamp(2.1rem,6.2vw,4.4rem);color:var(--w50);margin-bottom:4px}
.poster .line.hit{color:#fff}
.poster .line.hit em{font-style:normal;color:var(--submarine)}
.poster .kicker{font-family:var(--f-head);font-weight:600;font-size:clamp(1.05rem,2vw,1.42rem);
  color:var(--w75);margin-top:30px;max-width:26ch;margin-left:auto;margin-right:auto;line-height:1.35}
.flow{display:flex;flex-wrap:wrap;justify-content:center;gap:10px 16px;margin-top:44px;
  padding-top:30px;border-top:1px solid rgba(255,255,255,.16)}
.flow div{display:flex;align-items:center;gap:16px;flex-wrap:wrap;justify-content:center}
.flow b{font-family:var(--f-head);font-weight:600;font-size:.98rem;color:var(--w50)}
.flow b.end{color:#fff}
.flow i{font-style:normal;color:rgba(255,255,255,.3)}
.flow .lbl{font-family:var(--f-head);font-weight:700;font-size:.68rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--w50);min-width:112px;text-align:right}

/* ---------- mission punchlines ---------- */
.tagline{font-family:var(--f-head);font-weight:700;letter-spacing:-.025em;
  font-size:clamp(1.9rem,4.4vw,3.2rem);line-height:1.1;max-width:20ch}
.punch{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:26px;margin-top:48px}
.punch div{border-top:3px solid var(--electric);padding-top:18px}
.punch b{font-family:var(--f-head);font-weight:700;font-size:1.22rem;display:block;margin-bottom:5px}
.punch span{font-size:.94rem;color:var(--n60)}
.oneline{font-family:var(--f-head);font-weight:600;font-size:clamp(1.1rem,2vw,1.45rem);
  line-height:1.4;margin-top:46px;padding-left:26px;border-left:4px solid var(--submarine);max-width:34ch}

/* ---------- transformation tracks ---------- */
.track{margin-top:44px}
.track+.track{margin-top:34px}
.track-head{display:flex;align-items:baseline;gap:14px;margin-bottom:16px;flex-wrap:wrap}
.track-head h3{font-size:1.18rem}
.track-head .state{font-family:var(--f-head);font-weight:700;font-size:.7rem;letter-spacing:.13em;
  text-transform:uppercase;padding:4px 10px;border-radius:99px}
.state.done{background:rgba(5,180,160,.15);color:#04907F}
.state.now{background:rgba(13,77,222,.12);color:var(--electric)}
.steps-row{display:grid;grid-template-columns:1fr auto 1fr auto 1fr;gap:14px;align-items:stretch}
.stepbox{border:1.5px solid rgba(13,17,70,.15);border-radius:12px;padding:20px 18px;background:#fff}
.stepbox .when{font-family:var(--f-head);font-weight:700;font-size:.68rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--n40);margin-bottom:8px}
.stepbox b{font-family:var(--f-head);font-weight:600;font-size:1.04rem;display:block;margin-bottom:5px}
.stepbox span{font-size:.88rem;color:var(--n60);line-height:1.5}
.stepbox.past{background:var(--cirrus);border-color:transparent}
.stepbox.past b{color:var(--n60)}
.stepbox.now{border-color:var(--electric);box-shadow:0 10px 30px rgba(13,77,222,.16)}
.stepbox.now .when{color:var(--electric)}
.chev{display:flex;align-items:center;justify-content:center;color:var(--n40);font-size:1.5rem;font-weight:300}
.track-note{margin-top:16px;font-size:.95rem;color:var(--n60);max-width:none}

/* ---------- mission ---------- */
.mission{border-left:4px solid var(--electric);padding:6px 0 6px 28px;margin-top:30px}
.mission p{font-family:var(--f-head);font-weight:600;font-size:clamp(1.25rem,2.2vw,1.7rem);
  line-height:1.32;color:var(--night);max-width:30ch}
.dark .mission p{color:#fff}
/* electric blue on night sky is nearly invisible as a 4px rule — on dark, the
   accent steps up to the same pale blue the eyebrows use */
.dark .mission{border-left-color:#8FB4FF}
.lede+.lede{margin-top:14px}
.mission-steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px;margin-top:36px}
.ms{border-top:2px solid var(--electric);padding-top:16px}
.ms b{font-family:var(--f-head);font-weight:600;font-size:1rem;display:block;margin-bottom:4px}
.ms span{font-size:.9rem;color:var(--n60)}
.dark .ms span{color:var(--w75)}

@media(max-width:820px){
  .steps-row{grid-template-columns:1fr;gap:10px}
  .chev{transform:rotate(90deg);padding:2px 0}
}

/* ---------- segments ---------- */
.segs{display:grid;grid-template-columns:repeat(auto-fit,minmax(268px,1fr));gap:22px;margin-top:46px}
/* Six boxes in two labelled rows of three. auto-fit would give four-and-two on
   a wide screen, which breaks the grouping the labels are there to establish,
   so these rows are explicitly three across and drop to two, then one. */
.seg-group+.seg-group{margin-top:42px}
.seg-lead{display:flex;align-items:center;gap:14px;font-family:var(--f-head);font-weight:700;
  font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;color:var(--n40);margin-top:44px}
.seg-lead:after{content:"";flex:1;height:1px;background:rgba(13,17,70,.14)}
.segs-3{grid-template-columns:repeat(3,1fr);margin-top:18px}

/* Segments page: a photo beside each segment's copy, then its references.
   A dashed card marks a case study that is still to be written, so an empty
   slot reads as deliberate rather than as a gap nobody noticed. */
.seg-head{display:grid;grid-template-columns:420px 1fr;gap:36px;align-items:center;margin-bottom:38px}
.seg-photo{border-radius:var(--r);overflow:hidden;height:250px}
.seg-photo img{width:100%;height:100%;object-fit:cover;display:block}
.case.todo{border-style:dashed;background:transparent;box-shadow:none}
.case.todo:hover{border-color:rgba(13,17,70,.3);box-shadow:none}
.case.todo .who,.case.todo .what{color:var(--n60)}
@media(max-width:900px){.seg-head{grid-template-columns:1fr;gap:22px}.seg-photo{height:200px}}


/* ---------- article reader ----------
   The article is a magazine spread: two columns, pull quotes, photographs. Set
   as web text it lost all of that, so the PDF itself is shown, in a viewer over
   the page. The link underneath is a plain link to the same file, which is what
   happens on a phone (a PDF page in a small frame is unreadable) and whenever
   the script does not run. */
.reader{border:0;border-radius:16px;padding:0;max-width:1040px;width:calc(100% - 40px);
  height:92vh;color:var(--night);background:#fff;box-shadow:0 30px 80px rgba(13,17,70,.3);
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);overflow:hidden;z-index:1000}
.reader:not([open]){display:none}
.reader[open]{display:flex;flex-direction:column}
.reader[open]{outline:100vmax solid rgba(8,12,48,.62)}
@supports selector(dialog::backdrop){ .reader[open]{outline:0} }
.reader::backdrop{background:rgba(8,12,48,.62)}
.reader-bar{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;
  gap:16px;padding:13px 16px 13px 20px;border-bottom:1px solid rgba(13,17,70,.12);
  font-size:.92rem;background:#fff}
.reader-bar b{font-family:var(--f-head);font-weight:600}
.reader-acts{display:flex;align-items:center;gap:10px;flex:0 0 auto}
.reader-open{font-size:.88rem;font-weight:600;color:var(--electric)}
.reader-close-form{margin:0}
.reader-x{border:0;background:none;cursor:pointer;font-size:1.05rem;color:var(--n60);
  line-height:1;padding:6px 4px}
.reader-x:hover{color:var(--night)}
.reader-pdf{flex:1 1 auto;width:100%;border:0;display:block;background:var(--cirrus)}
@media(max-width:700px){.reader-bar b{display:none}}


/* ---------- a story told as web text, in the same overlay as the PDF reader ----------
   NB: .doc is already taken — it is a row in the document-request dialog, and
   an <article class="doc"> silently inherited display:flex and a border from
   it. Hence .story. */
.reader.story-reader{height:auto;max-height:90vh;max-width:840px;overflow:hidden}
.reader.story-reader[open]{display:flex;flex-direction:column}
.story-scroll{overflow:auto;-webkit-overflow-scrolling:touch}
.story{max-width:66ch;margin:0 auto;padding:34px 44px 44px}
.story-kicker{font-family:var(--f-head);font-weight:600;font-size:.74rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--electric);margin-bottom:13px}
.story h1{font-size:1.8rem;line-height:1.24;margin-bottom:14px}
.story h2{font-size:1.2rem;margin:32px 0 10px}
.story-stand{font-size:1.06rem;color:var(--night);font-weight:600;line-height:1.55;margin-bottom:22px}
.story p{font-size:1rem;color:var(--n80);line-height:1.68;margin-bottom:15px}
.story-pull{border-left:3px solid var(--electric);padding:4px 0 4px 20px;margin:24px 0}
.story-pull p{font-size:1.08rem;font-style:italic;color:var(--night);margin:0 0 10px}
.story-pull .by{font-family:var(--f-head);font-weight:600;font-size:.9rem}
.story-pull .by span{display:block;font-family:var(--f-body);font-weight:400;color:var(--n60);font-size:.85rem}
.story-fig{margin:26px 0}
.story-fig img{width:100%;height:auto;display:block;border-radius:12px}
.story-fig figcaption{font-size:.87rem;color:var(--n60);margin-top:9px;line-height:1.5}
.story-list{list-style:none;margin:6px 0 4px}
.story-list li{position:relative;padding-left:26px;margin-bottom:10px;font-size:1rem;color:var(--n80);line-height:1.6}
.story-list li:before{content:"";position:absolute;left:4px;top:.62em;width:8px;height:8px;border-radius:50%;background:var(--electric)}
.story-credit{font-size:.87rem;color:var(--n60);margin-top:26px;
  border-top:1px solid rgba(13,17,70,.12);padding-top:18px}
@media(max-width:700px){.story{padding:24px 20px 32px}.story h1{font-size:1.44rem}}



/* the solution's name, large enough to be the thing you see first */
.sol-name{display:inline-block;font-family:var(--f-head);font-weight:700;font-size:1.46rem;
  line-height:1.1;color:var(--electric);margin-bottom:16px;padding-bottom:8px;
  border-bottom:3px solid var(--electric)}
.sol-name.teal{color:#04907F;border-color:#04907F}
.dark .sol-name{color:#fff;border-color:var(--electric)}
@media(max-width:700px){.sol-name{font-size:1.24rem}}

/* ---------- solution sections ----------
   Each of the three solutions leads with a picture of itself: the app for the
   two mobile products, a photograph for licensing. The phone shots are PNGs
   with transparency, so they sit on a tinted panel; the photo fills its panel. */
.sol-media{margin:0 0 34px;height:300px;border-radius:var(--r);overflow:hidden;
  display:flex;align-items:flex-start;justify-content:center;padding-top:26px;
  background:rgba(13,77,222,.09)}
.sol-media img{width:232px;height:auto;display:block}
.sol-media.teal{background:rgba(5,180,160,.14)}
/* a composed shot that carries its own backdrop: let it fill the panel */
.sol-media.full{height:auto;padding:0;background:transparent;align-items:stretch}
.sol-media.full img{width:100%;height:auto}
.sol-media.shot{padding:0;align-items:stretch;background:rgba(13,17,70,.08)}
.sol-media.shot img{width:100%;height:100%;object-fit:cover}
.dark .sol-media{background:rgba(255,255,255,.07)}
@media(max-width:700px){.sol-media{height:230px;padding-top:18px}.sol-media img{width:176px}}

/* an explanatory diagram sitting inside a solution section */
.sol-diagram{margin:46px auto 44px;max-width:940px}
.sol-diagram img{width:100%;height:auto;display:block;border-radius:var(--r);
  border:1px solid rgba(255,255,255,.14)}
.sol-diagram.light img{border-color:rgba(13,17,70,.12);background:#fff}
.sol-diagram figcaption{margin-top:14px;font-size:.93rem;line-height:1.6;color:var(--n60);text-align:center}
.dark .sol-diagram figcaption{color:var(--w75)}

/* running body copy: give consecutive paragraphs air */
.prose p + p{margin-top:16px}

/* a column of cards beside a diagram */
.sol-split{display:grid;grid-template-columns:1fr 1.12fr;gap:40px;align-items:center;margin:46px 0 44px}
.sol-split-text{display:grid;gap:18px;align-content:center}
.sol-split .sol-diagram{margin:0;max-width:none}
@media(max-width:900px){.sol-split{grid-template-columns:1fr;gap:30px}}

/* photographs lifted from the solution brochure */
.sol-photos{display:grid;grid-template-columns:1fr 1fr;gap:26px;margin:40px 0 44px}
.sol-photos.one{grid-template-columns:1fr;max-width:940px;margin-left:auto;margin-right:auto}
.sol-photos figure{margin:0}
.sol-photos img{width:100%;height:auto;display:block;border-radius:var(--r)}
.sol-photos figcaption{margin-top:12px;font-size:.92rem;line-height:1.6;color:var(--n60)}
.dark .sol-photos figcaption{color:var(--w75)}
@media(max-width:760px){.sol-photos{grid-template-columns:1fr}}


@media(max-width:1000px){.segs-3{grid-template-columns:1fr 1fr}}
.seg{border:1px solid rgba(13,17,70,.13);border-radius:var(--r);padding:30px 28px;background:#fff;
  display:flex;flex-direction:column;transition:.2s}
.seg:hover{border-color:var(--electric);box-shadow:0 14px 38px rgba(13,17,70,.1);transform:translateY(-2px)}
.seg .kicker{font-family:var(--f-head);font-weight:700;font-size:.7rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--electric);margin-bottom:12px}
.seg h3{font-size:1.24rem;margin-bottom:10px}
.seg .hook{font-family:var(--f-head);font-weight:600;font-size:1rem;color:var(--night);margin-bottom:10px}
.seg p{font-size:.94rem;color:var(--n60);flex:1}
.seg .arrow{margin-top:18px}
/* A picture band at the top of each card. It bleeds to the card edge by
   cancelling the card's own padding, so a photo can sit flush without the card
   needing a second wrapper — which matters because the subgrid below aligns the
   card's DIRECT children, and wrapping the text would collapse that to one row.
   Until real photography arrives it holds an icon on a tinted ground; dropping
   an <img> in replaces the icon and nothing else has to change. */
.seg-media{margin:-30px -28px 18px;height:118px;border-radius:13px 13px 0 0;
  overflow:hidden;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(135deg,rgba(13,77,222,.13),rgba(13,77,222,.05) 60%,rgba(5,180,160,.12));
  border-bottom:1px solid rgba(13,17,70,.08)}
.seg-group.distribution .seg-media{
  background:linear-gradient(135deg,rgba(5,180,160,.16),rgba(5,180,160,.05) 60%,rgba(13,77,222,.10))}
.seg-media img{width:100%;height:100%;object-fit:cover;display:block}
.seg-media svg{width:40px;height:40px;fill:none;stroke:var(--electric);stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;opacity:.72}
.seg-group.distribution .seg-media svg{stroke:#04907F}
.seg:hover .seg-media img{transform:scale(1.03)}
.seg-media img{transition:transform .35s ease}
/* Aligning a row of cards.
   First attempt reserved a fixed number of lines for the title and the key
   message. That cannot be right at every width: at a 1180px window the
   public-sector hook wraps to three lines, at 1001px it wraps to four, and the
   reservation that suits one is wrong for the other — which is precisely the
   extra row that appeared between that hook and its body.
   Subgrid does the job properly. Every card spans the same five rows of the
   container, so kicker, title, hook, body and link line up across the row at
   ANY width, with no number to keep in step with the copy. */
@supports (grid-template-rows: subgrid){
  @media(min-width:1001px){
    .segs-3{grid-template-rows:auto auto auto auto 1fr auto;row-gap:0}
    .segs-3 .seg{display:grid;grid-template-rows:subgrid;grid-row:span 6}
  }
}
/* Older browsers (Safari below 16, Chrome below 117) have no subgrid, so they
   keep the reservation — sized for the NARROWEST three-column case, since being
   one line too generous only adds white space, while being one short is the bug
   above. */
@supports not (grid-template-rows: subgrid){
  .seg-group.customers .seg h3{min-height:2.4em}          /* 2 lines at 1.2  */
  .seg-group.customers .seg .hook{min-height:5.4em}       /* 4 lines at 1.35 */
  .seg-group.distribution .seg h3{min-height:2.4em}
  .seg-group.distribution .seg .hook{min-height:2.7em}    /* 2 lines at 1.35 */
}
.dark .seg{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.15)}
.dark .seg h3,.dark .seg .hook{color:#fff}
.dark .seg p{color:var(--w75)}
.dark .seg .kicker{color:#8FB4FF}

/* ---------- big claim band ---------- */
.claim{display:grid;grid-template-columns:auto 1fr;gap:46px;align-items:center}
.claim .num{font-family:var(--f-head);font-weight:700;font-size:clamp(4.5rem,11vw,9rem);
  line-height:.86;letter-spacing:-.04em;color:var(--electric)}
.dark .claim .num{color:#fff}
.claim .num small{display:block;font-size:.9rem;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;color:var(--n60);margin-top:12px}
.dark .claim .num small{color:var(--w50)}

/* ---------- Q&A accordion ---------- */
.qa{margin-top:42px;border-top:1px solid rgba(13,17,70,.14)}
.qa details{border-bottom:1px solid rgba(13,17,70,.14)}
.qa summary{cursor:pointer;list-style:none;padding:22px 44px 22px 0;position:relative;
  font-family:var(--f-head);font-weight:600;font-size:1.08rem;color:var(--night)}
.qa summary::-webkit-details-marker{display:none}
.qa summary:hover{color:var(--electric)}
.qa summary:after{content:"+";position:absolute;right:8px;top:19px;font-size:1.5rem;
  font-weight:400;color:var(--electric);transition:transform .2s}
.qa details[open] summary:after{content:"−"}
.qa .ans{padding:0 44px 24px 0}
.qa .ans p{font-size:1rem;color:var(--n80)}
.qa .decode{margin-top:16px;background:rgba(13,77,222,.06);border-left:3px solid var(--electric);
  padding:13px 16px;border-radius:0 9px 9px 0}
.qa .decode b{font-family:var(--f-head);font-size:.75rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--electric);display:block;margin-bottom:5px}
.qa .decode p{font-size:.94rem;color:var(--n80);margin:0}

/* ---------- spec chips ---------- */
.specs{display:flex;flex-wrap:wrap;gap:10px;margin-top:26px}
.specs span{font-family:var(--f-head);font-weight:600;font-size:.83rem;padding:8px 14px;
  border-radius:8px;border:1.5px solid rgba(13,17,70,.16);color:var(--n80)}
.dark .specs span{border-color:rgba(255,255,255,.24);color:var(--w75)}

/* ---------- logo strip ---------- */
.strip{padding:36px 0;background:var(--cirrus)}
.strip-in{display:flex;flex-wrap:wrap;gap:12px 38px;justify-content:center;align-items:center}
.strip-label{width:100%;text-align:center;font-size:.79rem;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--n60);margin-bottom:4px}
.strip-in span.name{font-family:var(--f-head);font-weight:600;font-size:1rem;color:var(--night);opacity:.6}

/* ---------- document request dialog ---------- */
/* <dialog> arrived in iOS Safari 15.4. Older phones ignore showModal(), and the
   script falls back to the open attribute — which without these rules renders
   the panel inline down by the footer, looking broken. Positioned explicitly so
   the fallback is a real centred panel, and ::backdrop degrades to nothing. */
.docs{border:0;border-radius:18px;padding:0;max-width:600px;width:calc(100% - 32px);
  color:var(--night);background:#fff;box-shadow:0 30px 80px rgba(13,17,70,.3);
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);
  max-height:88vh;overflow:auto;z-index:1000;-webkit-overflow-scrolling:touch}
.docs:not([open]){display:none}
/* the fallback has no backdrop of its own, so the panel supplies the contrast */
.docs[open]{outline:100vmax solid rgba(8,12,48,.62)}
@supports selector(dialog::backdrop){ .docs[open]{outline:0} }
.docs::backdrop{background:rgba(8,12,48,.62)}
.docs-close-form{margin:0}
.docs-x{position:absolute;top:14px;right:16px;border:0;background:none;cursor:pointer;
  font-size:1.05rem;color:var(--n40);line-height:1;padding:6px}
.docs-x:hover{color:var(--night)}
.docs-body{padding:34px 34px 30px}
.docs h3{font-size:1.5rem;margin-bottom:8px}
.docs-sub{font-size:.96rem;color:var(--n60);margin-bottom:22px}
.docs-list{border:0;padding:0;margin:0 0 22px}
.docs-list legend{font-family:var(--f-head);font-weight:600;font-size:.74rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--n40);margin-bottom:10px;padding:0}
.doc{display:flex;gap:12px;align-items:flex-start;border:1.5px solid rgba(13,17,70,.14);
  border-radius:11px;padding:13px 15px;margin-bottom:9px;cursor:pointer;transition:.15s}
.doc:hover{border-color:rgba(13,77,222,.5);background:rgba(13,77,222,.03)}
.doc:has(input:checked){border-color:var(--electric);background:rgba(13,77,222,.05)}
.doc input{margin-top:3px;flex:0 0 auto;width:17px;height:17px;accent-color:var(--electric)}
.doc b{display:block;font-family:var(--f-head);font-weight:600;font-size:.98rem}
.doc em{display:block;font-style:normal;font-size:.85rem;color:var(--n60);margin-top:2px;line-height:1.45}
.docs-lang{display:block;margin-bottom:15px;max-width:16em}
.docs-grid{display:grid;grid-template-columns:1fr 1fr;gap:13px}
.docs-grid .span2{grid-column:1 / -1}
.fld textarea{width:100%;font:inherit;font-size:.95rem;padding:11px 13px;color:var(--night);
  border:1.5px solid rgba(13,17,70,.18);border-radius:10px;background:#fff;
  resize:vertical;min-height:92px;display:block}
.fld textarea:focus{outline:none;border-color:var(--electric)}
/* ---------------- the downloads page ---------------- */
.dl{display:grid;grid-template-columns:300px 1fr;gap:42px;align-items:start;
  padding:38px 0;border-top:1px solid rgba(13,17,70,.12)}
.dl:first-of-type{border-top:0;padding-top:8px}
.dl-cover{border-radius:14px;overflow:hidden;background:rgba(13,17,70,.05);
  box-shadow:0 14px 34px rgba(13,17,70,.14);display:flex;align-items:center;
  justify-content:center;aspect-ratio:1 / 1.38}
.dl-cover.wide{aspect-ratio:1 / 1.38}
.dl-cover img{width:100%;height:100%;object-fit:cover;object-position:top center;display:block}
.dl-cover.wide img{object-fit:contain;background:#fff}
.dl-text h2{font-size:1.72rem;margin:4px 0 10px}
.dl-text .lede{font-size:1.02rem;margin-bottom:16px}
.dl-text .ticks{margin-bottom:22px}
.dl-text .ticks li{font-size:.95rem}
.dl-meta{display:flex;align-items:center;gap:12px;flex-wrap:wrap;font-size:.84rem;
  color:var(--n60)}
.dl-note{margin-top:34px;font-size:.95rem;color:var(--n60)}
.linklike{border:0;background:none;padding:0;font:inherit;color:var(--electric);
  text-decoration:underline;cursor:pointer}
@media(max-width:800px){
  .dl{grid-template-columns:1fr;gap:24px}
  .dl-cover{max-width:260px}
}

/* Turnstile mounts its iframe here; the min-height stops the dialog jumping
   when the widget finally appears */
.cf-box{margin-top:18px;min-height:65px}
.cf-note{font-size:.84rem;color:var(--n60);margin-top:8px;line-height:1.5}
.cf-note.bad{color:var(--danger);font-weight:600}
.docs-send[disabled]{opacity:.5;cursor:not-allowed;box-shadow:none}
.fld span{display:block;font-family:var(--f-head);font-weight:600;font-size:.74rem;
  letter-spacing:.08em;text-transform:uppercase;color:var(--n60);margin-bottom:5px}
.fld span i{font-style:normal;color:var(--n40);letter-spacing:0;text-transform:none;font-weight:400}
.fld span i.req{color:var(--electric);font-weight:600}
.fld input{width:100%;font:inherit;font-size:.95rem;padding:11px 13px;color:var(--night);
  border:1.5px solid rgba(13,17,70,.2);border-radius:9px;background:#fff}
.fld select{width:100%;font:inherit;font-size:.95rem;padding:11px 13px;color:var(--night);
  border:1.5px solid rgba(13,17,70,.18);border-radius:10px;background:#fff;display:block;
  cursor:pointer}
.fld select:focus{outline:none;border-color:var(--electric)}
/* a dialling-code picker beside the number, so nobody types +358 by hand */
.tel{display:grid;grid-template-columns:minmax(0,13.5em) 1fr;gap:10px;align-items:start}
@media(max-width:560px){.tel{grid-template-columns:1fr}}
.fld select.bad{border-color:var(--danger);background:rgba(198,40,40,.04)}
.fld input:focus{outline:none;border-color:var(--electric)}
.fld input.bad{border-color:var(--danger);background:rgba(198,40,40,.04)}
/* The opt-in stays unticked — pre-ticked consent is not consent under GDPR.
   It earns a panel of its own instead, so it reads as something offered rather
   than as small print to scroll past. */
.docs-opt{display:flex;gap:13px;align-items:flex-start;margin-top:22px;font-size:.93rem;
  color:var(--n80);line-height:1.55;cursor:pointer;padding:15px 17px;border-radius:12px;
  border:1.5px solid rgba(13,77,222,.28);background:rgba(13,77,222,.045);transition:.18s}
.docs-opt:hover{border-color:rgba(13,77,222,.55);background:rgba(13,77,222,.08)}
.docs-opt:has(input:checked){border-color:var(--electric);background:rgba(13,77,222,.09)}
.docs-opt input{margin-top:2px;width:20px;height:20px;flex:0 0 auto;accent-color:var(--electric);
  cursor:pointer}
.docs-opt b{display:block;font-family:var(--f-head);font-weight:600;font-size:.97rem;
  margin-bottom:3px}
.docs-legal{font-size:.82rem;color:var(--n40);margin-top:14px;line-height:1.5}
.docs-legal a{color:var(--electric);text-decoration:underline}
.docs-error{margin-top:14px;font-size:.88rem;font-weight:600;color:var(--danger)}
.docs-tick{width:46px;height:46px;border-radius:50%;background:rgba(5,180,160,.14);
  color:var(--seafoam);display:flex;align-items:center;justify-content:center;
  font-size:1.4rem;margin-bottom:14px}
.docs-links{display:grid;gap:9px}
.docs-links a{display:flex;align-items:center;gap:10px;border:1.5px solid rgba(13,17,70,.14);
  border-radius:11px;padding:13px 15px;font-family:var(--f-head);font-weight:600;font-size:.95rem}
.docs-links a:hover{border-color:var(--electric);color:var(--electric)}
@media(max-width:560px){
  .docs-body{padding:26px 20px 22px}
  .docs-grid{grid-template-columns:1fr}
}

/* ---------- latest news ---------- */
.news-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;margin-top:44px}
.news-card{display:flex;flex-direction:column;background:#fff;border:1px solid rgba(13,17,70,.13);
  border-radius:var(--r);padding:28px;transition:.2s}
.news-card:hover{border-color:var(--electric);box-shadow:0 14px 40px rgba(13,17,70,.09);
  transform:translateY(-2px)}
.news-meta{display:flex;align-items:center;gap:12px;margin-bottom:14px}
.news-meta .cat{font-family:var(--f-head);font-weight:600;font-size:.7rem;letter-spacing:.1em;
  text-transform:uppercase;padding:4px 10px;border-radius:5px;
  background:rgba(13,77,222,.09);color:var(--electric)}
.news-meta time{font-size:.82rem;color:var(--n40)}
.news-card h3{font-size:1.14rem;line-height:1.28;margin-bottom:10px}
.news-card p{font-size:.94rem;color:var(--n60);flex:1;margin-bottom:16px}
.news-card .arrow{font-size:.9rem}
/* a news item may point at more than one place; those links sit under the
   card rather than inside it, because a link inside a link is invalid */
.news-item{display:flex;flex-direction:column}
.news-item .news-card{flex:1 1 auto}
.news-links{display:flex;flex-wrap:wrap;gap:8px 18px;margin:11px 2px 0;font-size:.86rem}
.news-links a{color:var(--electric);text-decoration:underline;text-underline-offset:2px}
.news-links a:hover{text-decoration-thickness:2px}

/* ---------- trusted-by carousel ---------- */
.marquee{position:relative;overflow:hidden;margin-top:22px;
  /* the track runs under the edges rather than stopping dead at them */
  -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:flex-end;list-style:none;margin:0;padding:4px 0;
  gap:56px;width:max-content}
.marquee.rolling .track{animation:roll var(--roll,46s) linear infinite}
.marquee:hover .track,.marquee:focus-within .track{animation-play-state:paused}
@keyframes roll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.marquee .track li{display:flex;flex-direction:column;align-items:center;gap:11px;
  flex:0 0 auto;text-align:center}
/* A FIXED SLOT, not a fixed height. Real logos arrive in wildly different
   proportions — Securitas Technology is two stacked lines plus three dots, near
   enough square; a wordmark like YIT will be four times as wide as it is tall.
   Sizing by height alone would make the square one enormous. object-fit:contain
   in a constant box lets each one use whichever dimension it needs and keeps
   every slot the same size. */
.marquee .track img{display:block;width:150px;height:60px;object-fit:contain;
  /* grey at rest so nine different brand palettes don't fight each other, and
     so a logo supplied only in full colour still sits with the rest */
  filter:grayscale(1);opacity:.62;transition:filter .22s,opacity .22s}
.marquee .track li:hover img{filter:none;opacity:1}
.marquee .track span.name{font-family:var(--f-head);font-weight:600;font-size:.92rem;
  color:var(--night);opacity:.62;white-space:nowrap}
/* before the script clones the list there is only one copy: centre it */
.marquee:not(.rolling) .track{width:100%;justify-content:center;flex-wrap:wrap;gap:32px 46px}

/* ---------- tabs ---------- */
.tabs{display:flex;gap:10px;flex-wrap:wrap;margin:38px 0 32px}
.tab{font-family:var(--f-head);font-weight:600;font-size:.94rem;padding:13px 22px;border-radius:9px;
  border:1.5px solid rgba(13,17,70,.16);background:#fff;color:var(--night);cursor:pointer;transition:.16s}
.tab:hover{border-color:var(--n60)}
.tab[aria-selected="true"]{background:var(--night);color:#fff;border-color:var(--night)}
.panel{display:none}
.panel.active{display:block;animation:fade .28s ease}
@keyframes fade{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}

/* ---------- case cards ---------- */
.cases{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.case{border:1px solid rgba(13,17,70,.13);border-radius:var(--r);padding:28px;background:#fff;
  display:flex;flex-direction:column;transition:.2s}
.case:hover{border-color:var(--electric);box-shadow:0 12px 34px rgba(13,17,70,.09)}
.case .who{font-family:var(--f-head);font-weight:700;font-size:1.12rem;margin-bottom:5px}
.case .where{font-size:.83rem;color:var(--n60);margin:-2px 0 9px}
.case .what{font-size:.8rem;color:var(--electric);font-weight:600;text-transform:uppercase;
  letter-spacing:.08em;margin-bottom:14px}
.case p{font-size:.94rem;color:var(--n80);flex:1}
/* one figure per line, all the figures in a column of their own, so the
   numbers line up vertically instead of wrapping into a ragged block */
.case .metrics{display:grid;gap:9px;margin:16px 0 4px}
.case .metrics div{display:grid;grid-template-columns:5.4em 1fr;align-items:baseline;column-gap:12px}
.case .metrics div b{font-family:var(--f-head);font-size:1.32rem;display:block;line-height:1.1}
.case .metrics div span{font-size:.8rem;color:var(--n60);line-height:1.3}
.case .src{margin-top:14px;font-size:.87rem}

/* ---------- quotes ---------- */
.quote{background:var(--cirrus);border-radius:16px;padding:38px;margin-top:44px}
.dark .quote{background:rgba(255,255,255,.06)}
.quote p{font-size:1.16rem;font-style:italic;color:var(--n80);max-width:none}
.dark .quote p{color:var(--w75)}
.quote .by{margin-top:18px;font-family:var(--f-head);font-weight:600;font-size:.93rem}
.quote .by span{display:block;font-family:var(--f-body);font-weight:400;color:var(--n60);font-size:.87rem}
.dark .quote .by span{color:var(--w50)}

/* ---------- table ---------- */
.tbl{width:100%;border-collapse:collapse;margin-top:34px;font-size:.93rem}
.tbl th,.tbl td{padding:14px 12px;text-align:left;border-bottom:1px solid rgba(13,17,70,.12)}
.tbl th{font-family:var(--f-head);font-weight:600;font-size:.85rem;letter-spacing:.03em}
.tbl thead th{border-bottom:2px solid var(--night)}
.tbl td.y{color:var(--seafoam);font-weight:700}
.tbl td.n{color:var(--n40)}
.tbl tbody tr:hover{background:rgba(13,77,222,.03)}
/* a package comparison: the feature name reads left, every package column is
   centred so the ticks line up under their heading */
.tbl.pkg th+th,.tbl.pkg td+td{text-align:center}
.tbl.pkg thead th+th{color:var(--night)}

/* ---------- CTA ---------- */
.cta{background:linear-gradient(115deg,var(--electric),#0A2FA0 78%);color:#fff;border-radius:20px;
  padding:58px;display:grid;grid-template-columns:1.3fr 1fr;gap:42px;align-items:center}
.cta h2{color:#fff}
.cta p{color:rgba(255,255,255,.86);margin-top:15px}
.cta-actions{display:flex;flex-direction:column;gap:11px}
.cta-actions .btn{justify-content:center;width:100%}

/* ---------- footer ---------- */
footer{background:var(--night);color:var(--w75);padding:70px 0 32px}
.f-grid{display:grid;grid-template-columns:1.5fr 1fr 1fr 1fr;gap:38px}
/* the social link carries its mark, because that is what the eye looks for
   in a footer — the text alone gets read only by people already hunting */
.f-social{display:inline-flex;align-items:center;gap:10px;margin-top:18px;
  padding:9px 15px 9px 11px;border-radius:999px;font-size:.9rem;font-weight:600;
  color:#fff;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.16);
  transition:.2s}
.f-social:hover{background:var(--electric);border-color:var(--electric)}
.f-social svg{width:19px;height:19px;flex:0 0 auto;fill:currentColor;display:block}
footer h4{color:#fff;font-size:.94rem;margin-bottom:16px}
footer ul{list-style:none}
footer li{margin-bottom:9px;font-size:.91rem}
footer a:hover{color:#fff}
.build-stamp b{color:var(--w75);font-family:var(--f-head)}
.f-bot{margin-top:48px;padding-top:22px;border-top:1px solid rgba(255,255,255,.12);
  display:flex;justify-content:space-between;flex-wrap:wrap;gap:12px;font-size:.84rem;color:var(--w50)}

@media(max-width:960px){
  .hero-2col,.grid-3,.grid-2,.row,.cases,.cta,.f-grid{grid-template-columns:1fr}
  .row.flip .row-media{order:0}
  .nav ul{display:none}
  section{padding:68px 0}
  .cta,.quote{padding:32px}
  .tbl{font-size:.84rem}
  .tbl th,.tbl td{padding:10px 7px}
}

/* ==========================================================================
   MOBILE
   The 960px breakpoint already collapses the big grids. Below 760px the phone
   cases need more than that: there was no navigation at all (the menu was set
   to display:none with nothing to replace it), the tables overflowed the
   viewport, and several fixed two-column blocks had no fallback.
   ========================================================================== */

/* nothing may push the page sideways — one overflowing child scrolls the lot */
html,body{max-width:100%;overflow-x:hidden}
img,svg,table,pre{max-width:100%}

/* ---------- the menu button (hidden on desktop) ---------- */
.navtoggle{display:none;background:none;border:1.5px solid rgba(255,255,255,.32);
  border-radius:8px;width:42px;height:38px;cursor:pointer;padding:0;
  align-items:center;justify-content:center;flex-direction:column;gap:4px}
.navtoggle span{display:block;width:18px;height:2px;background:#fff;border-radius:2px;transition:.2s}
.navtoggle[aria-expanded="true"] span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.navtoggle[aria-expanded="true"] span:nth-child(2){opacity:0}
.navtoggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

@media(max-width:760px){
  body{font-size:16px}
  .wrap{padding:0 20px}
  section{padding:54px 0}
  h1{font-size:clamp(1.95rem,8.4vw,2.6rem)}
  h2{font-size:clamp(1.5rem,6.2vw,2rem)}
  h3{font-size:1.1rem}
  p,.lede{max-width:none}
  .lede{font-size:1.02rem}

  /* ---------- nav becomes a real menu ---------- */
  .nav{height:62px;gap:14px}
  .logo img{height:22px}
  .navtoggle{display:flex}
  .nav-right{gap:12px}
  .nav-right .signin{display:none}          /* lives in the open menu instead */
  .nav ul{display:none;position:absolute;top:62px;left:0;right:0;
    background:var(--night);border-bottom:1px solid rgba(255,255,255,.14);
    flex-direction:column;gap:0;margin:0;padding:6px 20px 16px;
    box-shadow:0 18px 40px rgba(0,0,0,.4)}
  header.open .nav ul{display:flex}
  .nav ul li{width:100%}
  .nav ul a{display:block;width:100%;padding:13px 0;font-size:1rem;
    border-bottom:1px solid rgba(255,255,255,.08)}
  .nav ul a:hover{border-color:rgba(255,255,255,.08)}
  .nav ul a.on{color:#fff}
  header.open .nav ul li:last-child a{border-bottom:none}
  .nav ul .m-signin{display:block;color:#fff;border:1.5px solid rgba(255,255,255,.32);
    border-radius:8px;text-align:center;margin-top:12px;padding:12px 0}

  /* ---------- hero ---------- */
  .hero{padding:30px 0 46px}
  .hero .lede{font-size:1.04rem}
  .btn-row{gap:10px;margin-top:26px}
  .btn{padding:14px 20px;font-size:.92rem;flex:1 1 auto;justify-content:center}
  .gone li{font-size:.98rem}

  /* ---------- the film ---------- */
  /* full bleed: at this width every pixel of stage counts */
  .film-wrap,.stage{max-width:none}
  .stage{margin-left:-20px;margin-right:-20px;width:calc(100% + 40px);border-radius:0}
  /* a thumb needs more than a 4px line to aim at: the bar stays thin, the
     invisible hit area around it grows to 44px */
  .film-head{margin:0 auto 14px;max-width:none;min-height:2.5em;
    font-size:clamp(1.25rem,6vw,1.7rem)}
  /* a thumb needs a bigger target than a 10px dot, and the bar has to fit a
     narrow screen alongside three dots */
  .film-time{gap:4px;margin-top:10px}
  .film-time .tick{padding:18px 8px}
  .film-time .tick.now i{width:104px}
  .stage-hint{font-size:.8rem}

  /* ---------- blocks with no 960px fallback ---------- */
  .claim{grid-template-columns:1fr;gap:18px;text-align:left}
  .claim .num{font-size:clamp(3.4rem,20vw,5rem)}
  .pillar{padding:16px 16px;gap:12px}
  .pillar .ic{flex:0 0 34px;width:34px;height:34px}
  .card,.cta,.quote{padding:24px}
  .adv-grid,.punch,.segs,.segs-3,.mission-steps,.news-grid{grid-template-columns:1fr}
  /* one column: there is nothing left to line up, so reclaim the space */
  .seg h3,.seg .hook{min-height:0}
  .seg-lead{margin-top:34px}
  .news-card{padding:22px}
  .row{gap:28px;margin-top:32px}
  .grid-3,.grid-2{margin-top:28px;gap:16px}

  /* ---------- tables scroll rather than overflow ---------- */
  .tbl-scroll,.tbl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}
  .tbl thead,.tbl tbody,.tbl tr{display:table;width:100%;table-layout:fixed}
  .tbl th,.tbl td{padding:10px 6px;font-size:.8rem;word-break:break-word}
  .tbl th:first-child,.tbl td:first-child{width:44%}

  /* ---------- footer ---------- */
  .f-grid{gap:26px}
  .foot .logo img{height:20px}

  }

@media(max-width:420px){
  .wrap{padding:0 16px}
  .stage{margin-left:-16px;margin-right:-16px;width:calc(100% + 32px)}
  .btn{width:100%}
}

/* coarse pointers: hover styles never un-stick, so make targets big instead */
@media(hover:none){
  .card:hover{transform:none;box-shadow:none}
  .btn-primary:hover{transform:none}
  a,button{-webkit-tap-highlight-color:rgba(13,77,222,.18)}
}

/* ---------------------------------------------------------------- consent
   The cookie banner. It sits at the foot of the window rather than across the
   middle: nothing on the page is covered except the last few centimetres, and
   a reader who wants to read first can. Accept and Decline are the same size
   and weight — a Decline that is harder to find than Accept is not a free
   choice, and under the GDPR that makes the consent invalid. */
.cc{position:fixed;left:16px;right:16px;bottom:16px;z-index:60;
    max-width:720px;margin:0 auto;background:var(--night);color:#fff;
    border-radius:16px;padding:22px 24px;
    box-shadow:0 18px 50px rgba(13,17,70,.38);
    font-size:.95rem;line-height:1.55}
.cc[hidden]{display:none}
.cc h2{font-size:1.05rem;margin:0 0 8px;color:#fff}
.cc p{margin:0 0 16px;color:var(--w75);max-width:62ch}
.cc a{color:#fff;text-decoration:underline}
.cc-row{display:flex;gap:10px;flex-wrap:wrap}
.cc-row .btn{flex:0 0 auto}
.cc .btn-white{background:#fff;color:var(--night)}
.cc .btn-ghost{background:transparent;color:#fff;box-shadow:inset 0 0 0 1px rgba(255,255,255,.45)}
.cc .btn-ghost:hover{background:rgba(255,255,255,.1)}
@media(max-width:560px){
  .cc{left:10px;right:10px;bottom:10px;padding:18px}
  .cc-row .btn{flex:1 1 100%;text-align:center}
}
/* the way back: a link in the footer, so a choice can always be changed */
.cc-reopen{background:none;border:0;padding:0;color:inherit;font:inherit;
           text-decoration:underline;cursor:pointer}
