/* ============================================================
   Innovation Lab — the page's own design.

   The page is built from this site's tokens and idioms rather than the ai.beyondsoft.com
   capture it replaced, so this file is where the Lab gets an identity of its own without
   introducing a second design system. Nothing here invents a colour: every value is a site
   token or a shade mixed from --blue.
   ============================================================ */

/* ---- The top of the page: a white bar that dissolves into the picture --------------- */
/* This page shipped with .nav-dark — the theme's white-on-navy bar — on the reasoning that a
   white lid does not belong on a night scene. Two things were wrong with that.

   The first is measurable. The header mark is assets/img/logo-bci-640.png, and it is a single
   flat colour: rgb(0,92,165), the brand blue, over transparency. There is no white variant in
   the bar (the white logo is the footer's), and the client's standing rule is that the logo's
   colour does not change. On the navy the mark therefore ran at 2.75:1 — below the 3:1 a
   graphic needs to be made out at all — against 6.84:1 on white. The bar was hiding the
   company's own name.

   The second is what the render showed: two different darks stacked, #0A1220 over the
   artwork's magenta top edge, with a 1px border between them. That is a seam, and a seam is
   the one thing the artwork cannot have across its own sky.

   So the bar goes white and the seam is answered rather than drawn: the hero opens on the same
   white and lets it fall away into the picture over the depth of the masthead's own top
   padding. The mark reads, the nav reads, and the header has no bottom edge — it ends where
   the white runs out, which is inside the artwork.

   No border-bottom, deliberately. The scrolled state keeps the shared light skin's rule
   (rgba(255,255,255,.9) + blur + hairline), which is correct once the bar is floating over
   content rather than sitting on top of the picture. */
body.pg-innovation-lab .site-header{background:#fff;border-bottom:0;}
body.pg-innovation-lab .site-header:not(.scrolled){background:#fff;}

/* ---- Masthead -------------------------------------------------------------------- */
/* The client supplied the artwork for this hero — "beyondsoft innovation lab V1-CLEANED.ai",
   a 2048x926 neon line-art transport scene — and asked for the metro on the viaduct to move.
   That is what this block is.

   HOW THE ARTWORK IS BUILT
   The .ai is PDF-compatible and its page content stream is 108 top-level q..Q groups. Two of
   them, in paint order, are the elevated metro: one paints the gradient body inside a clip of
   the train's silhouette, the next paints the white line detail over it. Ten Fm XObjects
   inside that second group are drawn under /GS4, which is BM/Screen — those are the roof
   highlight and the headlamps, and they are near-black everywhere else, so under Screen they
   pass the backdrop through. Source-over would paint them as a black slab; the difference
   measures 97/255 mean, so the Screen layer is not optional and cannot be baked in.

   So the artwork ships as three files, and stacking them reproduces the original to a mean of
   0.11/255 over 6.7M pixels — verified numerically, not by eye:
     lab-hero-plate.webp       everything except the metro, opaque, 3840x1737
     lab-hero-metro.webp       body + line detail, alpha, cropped to the train, 4x
     lab-hero-metro-glow.webp  the ten Screen elements, alpha, same crop, mix-blend-mode:screen
   The high-speed train, the bush that overlaps its tail, the aeroplane and everything else are
   in the plate. Only the metro moves, which is what was asked for ("让地铁动起来").

   HOW THE MOTION WORKS
   The viaduct is drawn in perspective, so travel along it is not a translate — it is a uniform
   SCALE about the track's vanishing point. That point was measured, not guessed: fit a line to
   the top edge of the train's alpha and another to the bottom edge, and they meet at
   (816.8, 744.8) in the 2048x926 frame (bottom-edge fit rms 0.14px). Scaling about it is exact
   perspective travel for any k, which is why the train stays welded to the deck for the whole
   run instead of drifting off it.
   transform-origin is that point expressed in the layer box's own percentages, hence the
   152.35% / 130.27% — the origin is outside the box, down and to the right, because the
   vanishing point is.

   The keyframes are not linear. At constant speed the distance falls linearly and the scale is
   its reciprocal, so k(t) = 1 / ((1-t)/k0 + t/k1); the 19 stops below sample that curve. Linear
   interpolation between k0 and k1 reads as a zoom, not as travel.

   THE TWO ENDS OF THE LOOP
   k runs 0.60 -> 1.86. At 0.60 the train is small and far, up where the viaduct meets the city
   haze; at 1.86 its nose has passed the left edge of the frame. It cannot drive out of frame —
   its own tail converges ON the vanishing point, so the drawing always contains that point and
   always occupies screen — which is why both ends fade rather than exit. The far end fades into
   the haze, which needs no help. The near end is fading INTO the artwork's own left-edge glare,
   and .lab-metro-clip's mask is what sells that: a stage-space gradient over the leftmost 15%,
   so the nose dissolves where the picture is already blown out to white rather than thinning in
   open sky. The mask has to be in stage space, so it sits on a wrapper that is NOT transformed;
   the <img> inside it is what scales.

   The same reasoning is why the high-speed train does not move. Its vanishing point sits inside
   its own outline too, and it is drawn nose-forward at 78% of the frame width, so any loop of it
   ends with a large, fully-lit train dissolving in open ground — measured and rejected. It stays
   as drawn, which is also where the artist put the focal point. */
.lab-hero{
  position:relative;isolation:isolate;overflow:hidden;
  /* Matched to .lab-hero::before's height: the copy starts where the white has finished. */
  padding:clamp(88px,9.2vw,150px) 0 0;
  color:#fff;
  /* Height follows the artwork's own 2048:926 so the picture is shown whole rather than
     cropped, up to a ceiling; past ~1900px wide the stage overflows the top and the sky —
     the emptiest part of the frame — is what gets clipped. The floor keeps the band from
     collapsing on a phone, where the copy needs the room anyway. */
  min-height:clamp(520px,calc(100vw / 2.21167),860px);
  /* Ground under the artwork, and the fallback if the images fail: the artwork's own top edge
     is magenta-and-teal and its foot is a deep blue road, so this runs the same way. */
  background:linear-gradient(180deg,#3A2A55 0%,#0A2A52 46%,#062845 100%);
  /* Column so the rail can be pushed to the foot of the band with margin-top:auto. It was
     min-height:100% on the inner div, which resolves against an auto-height parent and so
     did nothing — the rail sat straight under the strap, across the skyline. */
  display:flex;flex-direction:column;
}
.lab-hero-in{flex:1 1 auto;display:flex;flex-direction:column;}
/* The bridge. White at the top edge of the band, gone by the time the title starts — the fade
   depth and the hero's padding-top are the same clamp, so the two move together at every
   width and the headline never lands inside the veil. z-index:0 puts it over .lab-art (which
   sits at -1) and under .lab-hero-in (1), so it veils the picture and not the copy. */
.lab-hero::before{
  content:"";position:absolute;left:0;right:0;top:0;z-index:0;pointer-events:none;
  height:clamp(88px,9.2vw,150px);
  background:linear-gradient(180deg,
    #fff 0%,
    rgba(255,255,255,.86) 14%,
    rgba(255,255,255,.52) 38%,
    rgba(255,255,255,.22) 64%,
    rgba(255,255,255,.06) 84%,
    rgba(255,255,255,0) 100%);
}
/* The stage carries the artwork at its true aspect and is anchored to the FOOT of the band, so
   what a short viewport loses is sky. container-type:size is what lets it cover without JS:
   take the larger of the box's width and the width the box's height implies. */
.lab-art{position:absolute;inset:0;z-index:-1;overflow:hidden;pointer-events:none;container-type:size;}
.lab-art-stage{
  position:absolute;left:50%;bottom:0;translate:-50% 0;
  isolation:isolate;                 /* the Screen layer blends with the plate, not the page */
  width:100%;aspect-ratio:2048 / 926;
  width:max(100cqw,calc(100cqh * 2048 / 926));
}
.lab-art-stage img{position:absolute;display:block;}
.lab-plate{inset:0;width:100%;height:100%;}
/* Not transformed. Holds the stage-space edge mask; the <img> inside is what animates. */
.lab-metro-clip{position:absolute;inset:0;
  -webkit-mask-image:linear-gradient(90deg,transparent 0%,#000 15%);
          mask-image:linear-gradient(90deg,transparent 0%,#000 15%);}
.lab-metro-clip.is-glow{mix-blend-mode:screen;}
/* Box and origin are the measured geometry — see the note above. Do not round these. */
.lab-metro{
  left:17.6025%;top:56.5875%;width:14.624%;height:18.3045%;
  transform-origin:152.3539% 130.2655%;
  will-change:transform,opacity;
  animation:labMetro 17s linear infinite;
}
@keyframes labMetro{
  0%{transform:scale(0.6000);opacity:0.000;}
  5.556%{transform:scale(0.6235);opacity:0.397;}
  11.11%{transform:scale(0.6488);opacity:0.794;}
  16.67%{transform:scale(0.6764);opacity:1.000;}
  22.22%{transform:scale(0.7063);opacity:1.000;}
  27.78%{transform:scale(0.7391);opacity:1.000;}
  33.33%{transform:scale(0.7750);opacity:1.000;}
  38.89%{transform:scale(0.8146);opacity:1.000;}
  44.44%{transform:scale(0.8585);opacity:1.000;}
  50%{transform:scale(0.9073);opacity:1.000;}
  55.56%{transform:scale(0.9621);opacity:1.000;}
  61.11%{transform:scale(1.0239);opacity:1.000;}
  66.67%{transform:scale(1.0941);opacity:1.000;}
  72.22%{transform:scale(1.1747);opacity:1.000;}
  77.78%{transform:scale(1.2682);opacity:1.000;}
  83.33%{transform:scale(1.3778);opacity:0.980;}
  88.89%{transform:scale(1.5081);opacity:0.654;}
  94.44%{transform:scale(1.6657);opacity:0.327;}
  100%{transform:scale(1.8600);opacity:0.000;}
}
/* NARROW SCREENS — the artwork stops covering and becomes a band.
   Cover is wrong here and the arithmetic says why: at 390px the rail stacks to four rows and
   the band runs ~1100px tall, so a 2048:926 picture scaled to cover shows 390/1100*2.21 = 16%
   of its own width. Both trains and the whole viaduct are outside that crop; what is left is
   an abstract patch of city. So below 820px the stage is laid at its true width along the foot
   of the band and the copy sits above it on the section's gradient, which means the entire
   scene — viaduct, metro, road, high-speed train — is on screen at every width.
   The padding reserves the band's exact height so the rail lands above the picture rather than
   across it, and the mask dissolves the artwork's top edge into the gradient so there is no
   seam where the magenta corners would otherwise start abruptly. */
@media (max-width:820px){
  .lab-hero{padding-bottom:calc(100vw / 2.21167);}
  .lab-art{top:auto;bottom:0;height:auto;container-type:normal;}
  /* display:block is load-bearing: .lab-art-stage is a <span>, and position:absolute was
     what blockified it on desktop. Dropped back to position:relative it returns to inline,
     where width, height and aspect-ratio are all ignored and the artwork vanishes. */
  .lab-art-stage{display:block;position:relative;left:auto;bottom:auto;translate:none;width:100%;
    -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 24%);
            mask-image:linear-gradient(180deg,transparent 0,#000 24%);}
  /* The scrim now covers only the picture, and the picture no longer sits under the type, so
     it is only needed at the foot where the road is. */
  .lab-art::after{background:linear-gradient(180deg,rgba(4,14,32,0) 0%,rgba(4,14,32,0) 62%,rgba(4,14,32,.16) 100%);}
  /* The rail sits on the gradient above the picture, so it needs no plinth of its own. */
  .lab-rail::before{display:none;}
}
/* Reduced motion gets the artwork exactly as the client drew it: k=1, full opacity, no loop. */
@media (prefers-reduced-motion:reduce){
  .lab-metro{animation:none;transform:none;opacity:1;}
}
/* Scrim. The artwork was measured for white text before this was written: over the raw picture
   the top 45% runs a median 3.45-4.47:1 and dips to 1.37:1 in the centre, so it does not carry
   type on its own — the magenta corners and the bright circuit lines are what fail. This is
   heavy at the head where the title and the sub sit, clears completely across the middle band
   so the city, the horizon and both trains are seen as drawn, and comes back at the foot for
   the labs rail. */
.lab-art::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(4,14,32,.46) 0%,
    rgba(4,14,32,.30) 17%,
    rgba(4,14,32,.13) 32%,
    rgba(4,14,32,.00) 46%,
    rgba(4,14,32,.00) 68%,
    rgba(4,14,32,.10) 84%,
    rgba(4,14,32,.20) 100%);
}
/* Removed with the artwork's arrival: .lab-hero-bg's 26px dot grid, .lab-hero::after's
   perspective floor grid and .lab-hero-in::after's horizon glow. All three drew a horizon and
   a receding floor in CSS, which is precisely what the picture now draws — two horizons, one
   over the other. The span is kept in the markup as the artwork's own container. */
.lab-hero-in{position:relative;z-index:1;}
/* The name at display size, centred, with the brand gradient through it — the same
   .grad-text device the homepage uses, drawn here at the scale the page deserves. */
.lab-h1{
  margin:0;text-align:center;
  font:700 clamp(44px,8.4vw,108px)/1 var(--f-display);
  letter-spacing:-.04em;
  background:linear-gradient(100deg,#7FD4E4 0%,#4FB4DC 40%,#B9A6F2 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  /* The gradient fill sits on a picture now rather than on a flat band, so it gets the same
     drop shadow the site's other artwork heroes give their headlines. */
  filter:drop-shadow(0 2px 18px rgba(4,14,32,.55));
}
.lab-sub{
  margin:clamp(16px,1.8vw,24px) auto 0;max-width:34ch;text-align:center;
  font:400 clamp(16px,1.55vw,21px)/1.45 var(--f-body);
  color:rgba(255,255,255,.92);
  text-shadow:0 1px 14px rgba(4,14,32,.6);
}
.lab-strap{
  margin:clamp(22px,2.4vw,32px) auto 0;max-width:44ch;text-align:center;
  font:700 clamp(15px,1.35vw,19px)/1.5 var(--f-display);letter-spacing:-.01em;
  color:rgba(255,255,255,.8);
  text-shadow:0 1px 14px rgba(4,14,32,.6);
}
/* The rail closes the hero on the four labs, so the page states its subject before the
   reader scrolls. It doubles as the floor of the band — hence the top hairline and the
   padding rather than a margin. It is pushed to the foot of the band with margin-top:auto so
   the artwork keeps the whole middle; .lab-hero-in is the flex column that allows it. */
.lab-rail{
  display:grid;grid-template-columns:repeat(4,1fr);gap:0;
  margin:clamp(30px,3.4vw,48px) 0 0;padding:0;list-style:none;
  margin-top:auto;
  border-top:1px solid rgba(255,255,255,.26);
  /* The rail's ground is on the RAIL, not on the whole foot of the picture. A scrim wide
     enough to carry 12px mono type had to reach ~.62, and spread across the bottom of the
     artwork that buried the road and most of the high-speed train with it. Confined to the
     103px the rail actually occupies, the picture stays open to within a hair of the rail's
     top edge and only the strip under the type goes dark.
     Measured over the road, which is the worst ground on the page — its white lane markings
     are 1.00:1 raw. Composited with the picture scrim, this ramp puts the city names at a
     worst pixel of 4.62:1 and the dates at 8.72:1. The names are held to 4.5:1 rather than
     the 3:1 they would qualify for at 1440 (19.4px bold is large text), because the size is
     clamp(15px,1.35vw,19px) and between 820 and 1380px wide it sits at the 15px floor, where
     bold is NOT large text. Sized for the harder of the two cases. */
  position:relative;
}
/* The ground bleeds to the frame edges rather than stopping at the container's 40-72px
   gutters, so it reads as a plinth under the whole band and not as a floating panel.
   z-index:-1 keeps inside .lab-hero-in's stacking context, so it sits under the rail's own
   type and over the artwork. */
.lab-rail::before{
  content:"";position:absolute;z-index:-1;top:0;bottom:0;left:50%;translate:-50% 0;width:100vw;
  background:linear-gradient(180deg,rgba(4,14,32,.34) 0%,rgba(4,14,32,.68) 46%,rgba(4,14,32,.84) 100%);
}
.lab-rail-i{
  padding:clamp(18px,2vw,26px) 0 clamp(22px,2.6vw,34px);
  padding-right:18px;
  border-right:1px solid rgba(255,255,255,.14);
}
.lab-rail-i:last-child{border-right:0;}
.lab-rail-i b{
  display:block;
  font:700 clamp(15px,1.35vw,19px)/1.25 var(--f-display);letter-spacing:-.01em;color:#fff;
  text-shadow:0 1px 12px rgba(4,14,32,.7);
}
.lab-rail-i span{
  display:block;margin-top:6px;
  font:600 12px/1 var(--f-mono);letter-spacing:.12em;text-transform:uppercase;
  color:rgba(255,255,255,.62);
  text-shadow:0 1px 12px rgba(4,14,32,.7);
}
.lab-rail-i.is-soon b,
.lab-rail-i.is-soon span{color:rgba(255,255,255,.48);}

/* ====================================================================================
   THE PAGE IS ONE NIGHT SCENE, AND THE PALETTE IS THE HERO ARTWORK'S OWN
   ------------------------------------------------------------------------------------
   The brief was to match the FEELING of ai.beyondsoft.com without taking any of its
   design, and to build the page out of the hero image the client supplied. So none of
   what follows is sampled from that site. Every colour below was measured off
   assets/img/lab/lab-hero-plate.webp — median of a region, or the mean of the brightest
   0.5% for the ink:

     top-left / top-right corners   #AA7AB6 / #9E6DAA   the magenta-violet
     left / right edge glare        #6BC4D6 / #9AD6E1   the teal
     sky centre                     #4B7DBC
     city band                      #2D63B0
     the road                       #014F9A
     the neon stroke                #FBFFFF             near-white, not white
     darkest pixel in the picture   #004280

   THE GROUND IS NOT BLACK, and that is the one decision everything else follows from.
   The artwork has no true dark in it — its floor is a saturated #004280 — so it is a
   luminous picture, not a nocturne. Putting it on black would make the page a different
   thing from the picture and would also be the reference site's move (its body is
   #0a0a0a). --lab-night is the artwork's own hue taken below its darkest value, so the
   picture reads as the light source on a ground that belongs to it.

   WHAT THE PAGE BORROWS FROM THE PICTURE, and every one of these is literally in it:
     - wireframe plates: the buildings are thin near-white strokes over translucent blue,
       so cards are a 1px stroke on a translucent plate, never a white box with a shadow
     - the halftone dot field from the top-left corner, as a section texture
     - the circuit traces and their node rings, as section rules
     - the perspective floor from the road and the rail bed, under the closing band
     - the corner sweep, magenta to teal, as the one accent gradient
   ==================================================================================== */
body.pg-innovation-lab{
  --lab-night:#04152C;
  --lab-plate:#0A2547;
  --lab-ink-rgb:251,255,255;      /* the artwork's stroke */
  --lab-cyan:#6BC4D6;
  --lab-cyan-hi:#9AD6E1;
  --lab-violet:#AA7AB6;
  --lab-blue:#2D63B0;
  --lab-blue-deep:#014F9A;
  background:var(--lab-night);
}
/* The interior skin paints white on the wrapper and on every band; this page is a scene,
   so the sections carry no ground of their own and the body's night shows through. */
body.pg-innovation-lab :is(.site-main,.section,.section-tight){background:transparent;}
/* Base text colours are set for white paper. On the night they are unreadable, so the
   three shared type roles are restated once here rather than per component. */
body.pg-innovation-lab{color:rgba(var(--lab-ink-rgb),.72);}
body.pg-innovation-lab :is(.h2,h2,h3){color:#fff;}

/* The interior skin alternates its sections with a full-bleed pale wash —
   .interior-v2 .iv-section.iv-tone::before, a 100vw linear-gradient(#f8fafc,#f2f7fa) at
   z-index:-1 (base.css:3375). On a white page that is a quiet tonal step; on this one it
   printed a 540px sheet of near-white across the closing section, measured at
   rgb(247,248,251) against the page's rgb(4,21,44).

   It is restated rather than switched off, because the alternation itself is right — it is
   how the page keeps four long sections apart. Same device, this page's palette: a step
   DOWN into the deeper blue rather than up into paper, with the hairlines following. */
body.pg-innovation-lab .iv-section.iv-tone::before{
  background:
    radial-gradient(48% 72% at 96% 18%,color-mix(in srgb,var(--lab-cyan) 10%,transparent),transparent 70%),
    radial-gradient(40% 62% at 3% 90%,color-mix(in srgb,var(--lab-violet) 12%,transparent),transparent 72%),
    linear-gradient(180deg,rgba(10,37,71,.55),rgba(3,16,34,.55));
  border-top:1px solid rgba(var(--lab-ink-rgb),.08);
  border-bottom:1px solid rgba(var(--lab-ink-rgb),.08);
}

/* The circuit rule: a hairline with a node ring on it, which is the artwork's own way of
   ending a line. Used under every section head. */
body.pg-innovation-lab .lab-head::after{
  content:"";display:block;position:relative;
  margin-top:clamp(18px,2vw,26px);height:1px;
  background:linear-gradient(90deg,
    rgba(var(--lab-ink-rgb),.34) 0,
    rgba(var(--lab-ink-rgb),.10) 42%,
    transparent 78%);
}

/* ---- Shared section heads -------------------------------------------------------- */
.lab-head{max-width:74ch;margin-bottom:clamp(26px,3vw,38px);}
.lab-head .h2{margin-bottom:14px;}
.lab-lead{margin:0;font:400 16.5px/1.72 var(--f-body);color:rgba(var(--lab-ink-rgb),.72);}
.lab-eyebrow{
  margin:0 0 10px;
  font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--lab-cyan);
}

/* ---- The three partner routes: wireframe plates ---------------------------------- */
/* These were white cards with an 18px radius, a soft shadow and a 96px vector icon on a
   tinted disc — the site's standard card. On the night ground that is a bright rectangle
   sitting on top of a picture, which is the one thing the page cannot afford.

   The artwork's buildings are the model instead: a thin near-white stroke over a
   translucent blue face, corners hard. So the plate is a 1px stroke at 14% of the ink, a
   4px radius rather than 18 (enough to stop the corner shearing, not enough to read as a
   UI card) and no shadow at all — a drawing does not cast one.

   The illustration is a band across the head of the plate rather than a disc, because the
   drawings are perspective scenes with a horizon of their own and a circle crops them into
   badges. Their own line weight and colour come from the same measurement as this file's
   tokens, so plate and picture are drawn with one pen. */
.lab-routes{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,1.6vw,22px);}
.lab-route{
  position:relative;overflow:hidden;
  padding:0 0 clamp(26px,2.6vw,32px);
  border:1px solid rgba(var(--lab-ink-rgb),.14);border-radius:4px;
  background:
    linear-gradient(168deg,rgba(45,99,176,.16) 0%,rgba(1,79,154,.10) 58%,transparent 100%);
  transition:border-color .35s var(--ease),background .35s var(--ease);
}
/* The corner mark. Two hairlines meeting at the top-left, the way the artwork terminates a
   structure — it gives the plate a drawn corner without a second border. */
.lab-route::before{
  content:"";position:absolute;left:-1px;top:-1px;width:34px;height:34px;pointer-events:none;
  border-top:1px solid var(--lab-cyan);border-left:1px solid var(--lab-cyan);
  border-radius:4px 0 0 0;opacity:.55;
  transition:opacity .35s var(--ease),width .35s var(--ease),height .35s var(--ease);
}
.lab-route-art{
  display:block;width:100%;margin:0;
  border-bottom:1px solid rgba(var(--lab-ink-rgb),.10);
  /* The picture's own field, a shade deeper than the plate so the drawing sits IN the card
     rather than on it. The dot field is the artwork's halftone corner, at the same 8px
     pitch it uses there. */
  background:
    radial-gradient(rgba(var(--lab-ink-rgb),.07) 1px,transparent 1.4px) 0 0/8px 8px,
    linear-gradient(180deg,rgba(4,21,44,.55),rgba(4,21,44,0));
}
.lab-route-art img{display:block;width:100%;height:auto;aspect-ratio:320/240;}
.lab-route-no,
.lab-route-t,
.lab-route-b{margin-inline:clamp(22px,2.2vw,28px);}
.lab-route-no{
  display:block;margin-top:clamp(22px,2.2vw,28px);margin-bottom:12px;
  font:800 12px/1 var(--f-mono);letter-spacing:.2em;color:var(--lab-cyan);
}
.lab-route-no::after{
  content:"";display:block;width:26px;height:1px;margin-top:9px;
  background:var(--lab-cyan);
  transition:width .4s var(--ease);
}
.lab-route-t{margin-top:0;margin-bottom:10px;font:700 19px/1.32 var(--f-display);letter-spacing:-.01em;color:#fff;}
.lab-route-b{margin-top:0;margin-bottom:0;font:400 15.5px/1.68 var(--f-body);color:rgba(var(--lab-ink-rgb),.68);}
/* No lift and no zoom — both are out at the client's standing call. What answers the
   pointer is the drawn corner extending and the plate's own stroke coming up, which is a
   line-art page's version of the same gesture. */
@media (hover:hover){
  .lab-route:hover{
    border-color:rgba(var(--lab-ink-rgb),.30);
    background:linear-gradient(168deg,rgba(45,99,176,.24) 0%,rgba(1,79,154,.13) 58%,transparent 100%);
  }
  .lab-route:hover::before{opacity:1;width:52px;height:52px;}
  .lab-route:hover .lab-route-no::after{width:52px;}
}
.lab-cta-row{margin:clamp(28px,3vw,38px) 0 0;}

/* ---- Scale together -------------------------------------------------------------- */
/* Figures on a band, not a third row of cards: two card trios back to back read as one
   repeated component, and this block is a claim about the partnership, not a menu.

   The band was a pale blue slab with a 64px square grid on it. On the night that reads as
   a hole in the page, so it becomes the one place the artwork's TOP-LEFT CORNER is quoted
   directly: the halftone dot field at its own 8px pitch, and the magenta-to-teal corner
   sweep the picture makes across its sky. Both are measured values, not approximations —
   #AA7AB6 is the median of the artwork's top-left corner and #6BC4D6 of its left edge. */
.lab-band{
  position:relative;isolation:isolate;overflow:hidden;
  margin-top:clamp(58px,6vw,86px);
  padding:clamp(56px,6vw,86px) 0 clamp(50px,5.4vw,78px);
  background:
    radial-gradient(58% 74% at 88% -6%,color-mix(in srgb,var(--lab-violet) 26%,transparent),transparent 62%),
    radial-gradient(46% 60% at 4% 96%,color-mix(in srgb,var(--lab-cyan) 18%,transparent),transparent 66%),
    linear-gradient(180deg,rgba(10,37,71,.55) 0%,rgba(4,21,44,.35) 100%);
  border-top:1px solid rgba(var(--lab-ink-rgb),.10);
  border-bottom:1px solid rgba(var(--lab-ink-rgb),.10);
}
.lab-band::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;opacity:.9;
  background-image:radial-gradient(rgba(var(--lab-ink-rgb),.10) 1px,transparent 1.4px);
  background-size:8px 8px;
  -webkit-mask-image:radial-gradient(ellipse 62% 78% at 8% 34%,#000,transparent 100%);
          mask-image:radial-gradient(ellipse 62% 78% at 8% 34%,#000,transparent 100%);
}
.lab-head--band{margin-bottom:clamp(30px,3.4vw,44px);}
.lab-brings{
  display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(22px,3vw,46px);
  margin:0;padding:0;list-style:none;
}
/* A hairline, not a 2px rule: the picture has no heavy strokes in it. The node ring on the
   reading end is how the artwork's circuit traces start, and it is what tells three
   figures apart from three cards. */
.lab-bring{position:relative;padding-top:22px;border-top:1px solid rgba(var(--lab-ink-rgb),.26);}
.lab-bring::before{
  content:"";position:absolute;left:0;top:-4px;width:7px;height:7px;border-radius:50%;
  border:1px solid var(--lab-cyan);background:var(--lab-night);
}
.lab-bring-no{
  display:block;margin-bottom:10px;
  font:800 12px/1 var(--f-mono);letter-spacing:.2em;color:var(--lab-cyan);
}
.lab-bring-t{margin:0 0 8px;font:700 clamp(20px,1.9vw,25px)/1.2 var(--f-display);letter-spacing:-.02em;color:#fff;}
.lab-bring-b{margin:0;font:400 15.5px/1.68 var(--f-body);color:rgba(var(--lab-ink-rgb),.68);}

/* ---- Our Labs: globe left, list right --------------------------------------------- */
.lab-globe-split{
  display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);
  gap:clamp(20px,3vw,54px);align-items:center;
  margin-top:clamp(16px,2vw,30px);
}
.lab-globe-sec .ah-globe-stage{position:relative;width:100%;aspect-ratio:1/1;}
.lab-globe-sec .ah-globe-cv{position:absolute;inset:0;width:100%;height:100%;display:block;}
/* The label layer is positioned by the script in canvas pixels, so it must share the
   canvas's box exactly. */
.lab-globe-sec .ah-glabels{position:absolute;inset:0;pointer-events:none;}
.lab-globe-sec .ah-glabel{position:absolute;top:0;left:0;will-change:transform,opacity;
  transition:filter .3s var(--ease);}
.lab-globe-sec .ah-glabel-txt{
  position:absolute;left:13px;top:-15px;white-space:nowrap;
  padding:6px 9px;border-radius:8px;
  background:rgba(6,24,44,.74);border:1px solid rgba(127,212,228,.28);
  box-shadow:0 12px 26px -18px rgba(0,0,0,.8);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:background .25s var(--ease),border-color .25s var(--ease);
}
.lab-globe-sec .ah-glabel.is-on .ah-glabel-txt{
  background:rgba(12,48,74,.92);border-color:rgba(170,238,252,.75);
}
.lab-globe-sec .ah-glabel-txt b{
  display:block;font:700 12px/1.2 var(--f-display);letter-spacing:-.01em;color:#fff;
}
.lab-globe-sec .ah-glabel-txt em{
  display:block;margin-top:2px;font-style:normal;
  font:600 10px/1 var(--f-mono);letter-spacing:.1em;text-transform:uppercase;color:#7FD4E4;
}

/* The list. Each entry is a button because it drives the globe — that has to work from the
   keyboard, and focusin moves the globe exactly as hover does. */
.lab-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px;}
.lab-item{
  position:relative;display:block;width:100%;text-align:left;cursor:pointer;
  appearance:none;background:none;border:0;
  border-top:1px solid rgba(255,255,255,.12);
  padding:clamp(15px,1.7vw,21px) clamp(14px,1.5vw,20px) clamp(15px,1.7vw,21px) clamp(16px,1.8vw,24px);
  border-radius:0 12px 12px 0;
  font-family:inherit;color:inherit;
  transition:background .3s var(--ease),border-color .3s var(--ease);
}
.lab-list li:last-child .lab-item{border-bottom:1px solid rgba(255,255,255,.12);}
/* The spine is the active marker: it grows out of nothing on the reading edge, so the eye
   is told which entry the globe is currently showing without the row moving. */
.lab-item::before{
  content:"";position:absolute;left:0;top:50%;width:3px;height:0;
  border-radius:0 3px 3px 0;background:linear-gradient(180deg,#7FD4E4,#008AAB);
  transform:translateY(-50%);
  transition:height .34s var(--ease);
}
.lab-item.is-active::before{height:calc(100% - 20px);}
.lab-item.is-active{background:linear-gradient(90deg,rgba(0,138,171,.16),rgba(0,138,171,0) 82%);}
@media (hover:hover){ .lab-item:hover{background:linear-gradient(90deg,rgba(0,138,171,.10),rgba(0,138,171,0) 82%);} }
.lab-item:focus-visible{outline:2px solid #7FD4E4;outline-offset:-2px;}

.lab-item-h{display:flex;align-items:baseline;justify-content:space-between;gap:14px;margin-bottom:7px;}
.lab-item-place{font:700 clamp(17px,1.55vw,21px)/1.2 var(--f-display);letter-spacing:-.02em;color:#fff;}
.lab-item-when{
  flex:none;font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:#7FD4E4;
}
.lab-item-focus{
  display:block;margin-bottom:6px;
  font:700 13.5px/1.4 var(--f-display);color:rgba(255,255,255,.92);
}
.lab-item-b{display:block;font:400 14px/1.62 var(--f-body);color:rgba(255,255,255,.66);}
.lab-item-founded{
  display:block;margin-top:10px;
  font:400 11.5px/1.5 var(--f-body);letter-spacing:.03em;color:rgba(255,255,255,.42);
}
/* The US centre has a date and nothing else. Dimming the whole row says "not yet" more
   clearly than an empty gap where the copy should be. */
.lab-item--soon{opacity:.62;}
.lab-item--soon .lab-item-founded{margin-top:0;}

@media (max-width:980px){
  .lab-globe-split{grid-template-columns:1fr;gap:clamp(18px,3vw,32px);}
  .lab-globe-sec .ah-globe-stage{width:min(460px,86vw);margin:0 auto;}
  /* On a small sphere four labels crowd into one another, and the list underneath already
     names every city — so the globe steps back to being the picture. */
  .lab-globe-sec .ah-glabel{display:none;}
  .lab-item{border-radius:0 10px 10px 0;}
}
@media (prefers-reduced-motion:reduce){
  .lab-item,.lab-item::before,.lab-globe-sec .ah-glabel-txt{transition:none;}
}

/* ---- Tech Bridge CTA ------------------------------------------------------------- */
/* Three separate spacings stack here and measured 248px between the last lab panel and the
   band, against 0-75px everywhere else on the page: the labs section's padding-bottom
   (74px), this section's padding-top (87px) and .cta-band's own margin-top (87px).
   Zeroing the middle one and halving the last leaves ~124px.

   Both overrides have to be written to win a cascade they would otherwise lose:
   .interior-v2 .section-tight is (0,2,0) so .lab-cta alone was ignored, and the band's
   margin-top is !important in base.css. This file is enqueued after base.css, so at equal
   specificity these land. */
.interior-v2 .lab-cta{padding-top:0;}
.lab-cta .cta-band{margin-top:clamp(34px,4vw,56px)!important;}

/* The closing band is where the artwork's ROAD is quoted. The picture's whole lower half is
   a floor running to a vanishing point — the carriageway, the rail bed, the hatched ground —
   and this is the only section with nothing else in it, so it can carry that floor whole.

   Two repeating gradients on a rotateX plane, masked so the lines fade before the horizon
   rather than stopping at it, which is what makes it read as distance instead of as a
   texture with an edge. The device is this file's own — it was the masthead's floor before
   the artwork replaced it there, and it belongs here for the same reason it belonged there.

   Colour is the road's, #014F9A lifted to the ink for the lines themselves; the band's own
   ground moves off base.css's #002E72/#0A1220 onto the picture's blues. */
body.pg-innovation-lab .lab-cta .cta-band{
  isolation:isolate;
  background:
    radial-gradient(64% 90% at 84% -10%,color-mix(in srgb,var(--lab-violet) 22%,transparent),transparent 64%),
    linear-gradient(150deg,#062A52 0%,#04152C 62%,#03102A 100%);
  border:1px solid rgba(var(--lab-ink-rgb),.10);
}
/* The floor is DRAWN, not projected. The first pass built it the way the masthead used to:
   two repeating-linear-gradients on a plane with perspective() + rotateX(). That device is
   fine for a shallow band, but here the vanishing point, the transform-origin and the
   element's own perspective-origin all interact, and the result moved unpredictably against
   the copy — at 44% of the band's height it ran through the second line of the headline, and
   shortening it to 32% put it above the headline instead of below. Both were measured off a
   render, and neither was worth another guess.

   So the perspective is computed once, in geometry, and shipped as the picture it is: 27
   rails converging on a vanishing point 4px above the plate's top edge, and 34 sleepers at
   y = H(1 - 1/(1+ik)) with k=0.30, which is the spacing a ground plane actually produces.
   preserveAspectRatio="none" lets it stretch to any band width without the convergence
   shifting, because the vanishing point is at 50% of the viewBox either way.

   This is the artwork's own floor — its carriageway, its rail bed and its hatched ground are
   all the same construction — redrawn at the scale this band needs. */
body.pg-innovation-lab .lab-cta .cta-band::before{
  /* top:auto is load-bearing. base.css:3440 gives .interior-v2 .cta-band::before inset:0 —
     which sets top AND bottom — and with a height on top of that the top edge wins, so the
     floor stretched over the whole band and printed above the headline instead of under it.
     This rule out-specifies that one (0,3,2 against 0,3,1) but a shorthand it does not
     restate still applies. */
  content:"";position:absolute;left:0;right:0;top:auto;bottom:0;height:46%;
  z-index:0;pointer-events:none;opacity:.5;
  background-image:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 1200 300%22 preserveAspectRatio=%22none%22%3E%3Cg fill=%22none%22 stroke=%22%23FBFFFF%22 stroke-width=%221.1%22 opacity=%22.55%22%3E%3Cpath d=%22M600 -4L-934 300%22/%3E%3Cpath d=%22M600 -4L-816 300%22/%3E%3Cpath d=%22M600 -4L-698 300%22/%3E%3Cpath d=%22M600 -4L-580 300%22/%3E%3Cpath d=%22M600 -4L-462 300%22/%3E%3Cpath d=%22M600 -4L-344 300%22/%3E%3Cpath d=%22M600 -4L-226 300%22/%3E%3Cpath d=%22M600 -4L-108 300%22/%3E%3Cpath d=%22M600 -4L10 300%22/%3E%3Cpath d=%22M600 -4L128 300%22/%3E%3Cpath d=%22M600 -4L246 300%22/%3E%3Cpath d=%22M600 -4L364 300%22/%3E%3Cpath d=%22M600 -4L482 300%22/%3E%3Cpath d=%22M600 -4L600 300%22/%3E%3Cpath d=%22M600 -4L718 300%22/%3E%3Cpath d=%22M600 -4L836 300%22/%3E%3Cpath d=%22M600 -4L954 300%22/%3E%3Cpath d=%22M600 -4L1072 300%22/%3E%3Cpath d=%22M600 -4L1190 300%22/%3E%3Cpath d=%22M600 -4L1308 300%22/%3E%3Cpath d=%22M600 -4L1426 300%22/%3E%3Cpath d=%22M600 -4L1544 300%22/%3E%3Cpath d=%22M600 -4L1662 300%22/%3E%3Cpath d=%22M600 -4L1780 300%22/%3E%3Cpath d=%22M600 -4L1898 300%22/%3E%3Cpath d=%22M600 -4L2016 300%22/%3E%3Cpath d=%22M600 -4L2134 300%22/%3E%3Cpath d=%22M0 69h1200%22/%3E%3Cpath d=%22M0 112h1200%22/%3E%3Cpath d=%22M0 142h1200%22/%3E%3Cpath d=%22M0 164h1200%22/%3E%3Cpath d=%22M0 180h1200%22/%3E%3Cpath d=%22M0 193h1200%22/%3E%3Cpath d=%22M0 203h1200%22/%3E%3Cpath d=%22M0 212h1200%22/%3E%3Cpath d=%22M0 219h1200%22/%3E%3Cpath d=%22M0 225h1200%22/%3E%3Cpath d=%22M0 230h1200%22/%3E%3Cpath d=%22M0 235h1200%22/%3E%3Cpath d=%22M0 239h1200%22/%3E%3Cpath d=%22M0 242h1200%22/%3E%3Cpath d=%22M0 245h1200%22/%3E%3Cpath d=%22M0 248h1200%22/%3E%3Cpath d=%22M0 251h1200%22/%3E%3Cpath d=%22M0 253h1200%22/%3E%3Cpath d=%22M0 255h1200%22/%3E%3Cpath d=%22M0 257h1200%22/%3E%3Cpath d=%22M0 259h1200%22/%3E%3Cpath d=%22M0 261h1200%22/%3E%3Cpath d=%22M0 262h1200%22/%3E%3Cpath d=%22M0 263h1200%22/%3E%3Cpath d=%22M0 265h1200%22/%3E%3Cpath d=%22M0 266h1200%22/%3E%3Cpath d=%22M0 267h1200%22/%3E%3Cpath d=%22M0 268h1200%22/%3E%3Cpath d=%22M0 269h1200%22/%3E%3Cpath d=%22M0 270h1200%22/%3E%3Cpath d=%22M0 271h1200%22/%3E%3Cpath d=%22M0 272h1200%22/%3E%3Cpath d=%22M0 272h1200%22/%3E%3Cpath d=%22M0 273h1200%22/%3E%3C/g%3E%3C/svg%3E");
  background-size:100% 100%;background-repeat:no-repeat;background-position:bottom center;
  /* The far end dissolves rather than stopping on a line: the artwork's road runs into haze,
     and a grid with a hard top edge reads as a texture swatch. */
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 34%);
          mask-image:linear-gradient(180deg,transparent 0,#000 34%);
}
/* The horizon glow, sitting where the rails converge. */
body.pg-innovation-lab .lab-cta .cta-band::after{
  content:"";position:absolute;left:50%;translate:-50% 0;bottom:40%;
  width:120%;height:110px;z-index:0;pointer-events:none;
  background:radial-gradient(38% 100% at 50% 100%,color-mix(in srgb,var(--lab-cyan) 26%,transparent),transparent 74%);
}
body.pg-innovation-lab .lab-cta .cta-band .inner{position:relative;z-index:1;}
body.pg-innovation-lab .lab-cta .cta-band .h2{color:#fff;}
@media (prefers-reduced-motion:reduce){
  body.pg-innovation-lab .lab-cta .cta-band::before{transform:none;opacity:.16;height:38%;}
}

@media (max-width:960px){
  .lab-routes{grid-template-columns:1fr;}
  .lab-brings{grid-template-columns:1fr;gap:26px;}
  .lab-rail{grid-template-columns:repeat(2,1fr);}
  .lab-rail-i:nth-child(2n){border-right:0;}
  .lab-rail-i:nth-child(-n+2){border-bottom:1px solid rgba(255,255,255,.10);}
}
@media (max-width:520px){
  .lab-rail{grid-template-columns:1fr;}
  .lab-rail-i{border-right:0;border-bottom:1px solid rgba(255,255,255,.10);}
  .lab-rail-i:last-child{border-bottom:0;}
}
@media (prefers-reduced-motion:reduce){
  .lab-route,.lab-route-no::after{transition:none;}
}

/* ============================================================
   The dialog
   ============================================================ */
.lab-dialog{position:fixed;inset:0;z-index:300;}
.lab-dialog[hidden]{display:none;}
.lab-dialog-scrim{
  position:absolute;inset:0;background:rgba(4,6,12,.72);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  opacity:0;transition:opacity .28s cubic-bezier(.22,.61,.36,1);
}
.lab-dialog-panel{
  position:relative;z-index:1;
  width:min(560px,calc(100vw - 32px));
  max-height:calc(100vh - 48px);overflow:auto;
  margin:24px auto;
  background:#0F0F12;color:#fff;
  border:1px solid rgba(255,255,255,.13);border-radius:18px;
  padding:34px 34px 30px;
  font-family:Aileron,"Helvetica Neue",Arial,sans-serif;
  opacity:0;transform:translateY(10px);
  transition:opacity .3s cubic-bezier(.22,.61,.36,1),transform .3s cubic-bezier(.22,.61,.36,1);
}
.lab-dialog.is-open .lab-dialog-scrim{opacity:1;}
.lab-dialog.is-open .lab-dialog-panel{opacity:1;transform:none;}

.lab-dialog-x{
  position:absolute;top:16px;right:16px;
  width:36px;height:36px;display:grid;place-items:center;
  background:none;border:0;border-radius:9px;color:rgba(255,255,255,.6);cursor:pointer;
  transition:background .15s,color .15s;
}
.lab-dialog-x:hover{background:rgba(255,255,255,.08);color:#fff;}
.lab-dialog-x svg{width:18px;height:18px;}

.lab-dialog-t{margin:0 0 8px;font-size:28px;font-weight:700;line-height:1.2;letter-spacing:-.015em;}
.lab-dialog-p{margin:0 0 24px;font-size:15px;line-height:1.6;color:rgba(255,255,255,.58);}

/* The form carries .ct-card so app.js binds to it; that class also carries the light
   interior-v2 card skin, which would put near-black text on near-black here. */
.lab-dialog .lab-dialog-form{
  background:none;border:0;box-shadow:none;padding:0;margin:0;
}
.lab-dialog-row{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
.lab-dialog-field{display:block;margin-bottom:14px;}
.lab-dialog-field label{
  display:block;margin-bottom:6px;
  font-size:12.5px;font-weight:600;letter-spacing:.04em;color:rgba(255,255,255,.62);
}
.lab-dialog-field :is(input,textarea){
  width:100%;box-sizing:border-box;
  background:rgba(255,255,255,.05);
  border:1px solid rgba(255,255,255,.16);border-radius:10px;
  padding:12px 14px;
  font:400 15px/1.5 Aileron,"Helvetica Neue",Arial,sans-serif;color:#fff;
  transition:border-color .15s,background .15s;
}
.lab-dialog-field :is(input,textarea)::placeholder{color:rgba(255,255,255,.32);}
.lab-dialog-field :is(input,textarea):focus{
  outline:none;border-color:rgba(255,255,255,.5);background:rgba(255,255,255,.08);
}
.lab-dialog-field textarea{resize:vertical;min-height:96px;}
.lab-dialog-send{margin-top:6px;width:100%;}

/* Honeypot: off-screen rather than display:none, which some autofillers skip entirely. */
.lab-dialog-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;}

@media (max-width:900px){
  .lab-dialog-row{grid-template-columns:1fr;}
  .lab-dialog-panel{padding:28px 22px 24px;}
}

@media (prefers-reduced-motion:reduce){
  .lab-dialog-scrim,
  .lab-dialog-panel{transition:none;}
  .lab-dialog-panel{transform:none;}
}

/* ---- Our Labs: the globe ---------------------------------------------------------- */
/* VIOLET, not deep blue — the client picked this over a white band: "我喜欢这个".

   The band has now had three grounds. It started white, and the sphere was almost invisible:
   globe.js's strokes are rgba(0,138,171,.07-.5), drawn for the near-black band .ah-globe gives
   this canvas on Global Presence. It then ran near-black, which is what the client asked to be
   rid of ("our lab 的部分还是深蓝"). This is the third: still night, so the globe keeps the dark
   it was drawn for, but the hue moves off blue entirely.

   The violet is not a new colour on this page. #AA7AB6 is the measured median of the hero
   artwork's TOP-LEFT CORNER, and #150A28 is that hue taken below the picture's darkest value —
   the same construction --lab-night uses for the blue. So the section is lit by the two corners
   of the client's own drawing: the magenta-violet across the top right, the teal at the foot
   left, which are exactly where the artwork puts them.

   The two ENDS stay on --lab-night. That constraint has not changed and is why this reads as a
   band rather than a hole: the page either side is #04152C, so the section starts and finishes
   there and only crosses to the violet over the middle 56%, which is the band the canvas
   actually occupies. */
.lab-globe-sec{
  position:relative;isolation:isolate;overflow:hidden;
  padding:clamp(56px,5.8vw,82px) 0 clamp(34px,3.6vw,52px);
  color:#fff;
  background:
    radial-gradient(74% 80% at 80% 4%,rgba(170,122,182,.30),transparent 62%),
    radial-gradient(52% 58% at 8% 94%,rgba(0,138,171,.16),transparent 70%),
    linear-gradient(180deg,
      #04152C 0%,
      #150A28 22%,
      #150A28 78%,
      #04152C 100%);
}
.lab-globe-sec .h2{color:#fff;}
.lab-globe-sec .lab-lead{color:rgba(255,255,255,.72);}
/* The canvas has to be masked to its own sphere, and this is the one thing the violet ground
   exposed that the near-black one hid. globe.js paints an atmosphere wash out to R * 1.55,
   which is 1.41x the canvas's own half-height, so it is CLIPPED BY THE ELEMENT BOX — the wash
   simply stops on the box's straight edges. Against near-black that step was invisible; on the
   violet it measured a hard vertical edge of (20,14,44) -> (19,27,57) at the box's left, and
   the mirror of it at the right, i.e. a faint rectangle drawn around the globe.
   Fading the canvas out between 93% and 100% of its closest side puts the cut outside the
   limb — the ball itself reaches 91% — and inside the box, so the halo ends in air instead of
   on a corner. Nothing else about the section changes. */
.lab-globe-sec .ah-globe-cv{
  -webkit-mask-image:radial-gradient(circle closest-side,#000 0 93%,rgba(0,0,0,0) 100%);
          mask-image:radial-gradient(circle closest-side,#000 0 93%,rgba(0,0,0,0) 100%);
}
.lab-head--globe{max-width:64ch;margin-left:auto;margin-right:auto;text-align:center;}
.lab-head--globe .lab-lead{margin-left:auto;margin-right:auto;}
/* The script sizes the sphere as min(stageW, stageH) * 0.42, so a wide-but-short stage
   wastes the width: at 760x593 the sphere came out ~500px across in a 1280px section and the
   dark band read as mostly empty. Near-square gives the height back and the sphere with it. */
.lab-globe-sec .ah-globe-stage{
  position:relative;margin:clamp(10px,1.6vw,20px) auto 0;
  width:min(900px,92vw);aspect-ratio:1/.88;
}
.lab-globe-sec .ah-globe-cv{position:absolute;inset:0;width:100%;height:100%;display:block;}
/* The labels are positioned by the script in canvas pixels, so the layer must share the
   canvas's box exactly. */
.lab-globe-sec .ah-glabels{position:absolute;inset:0;pointer-events:none;}
.lab-globe-sec .ah-glabel{position:absolute;top:0;left:0;will-change:transform,opacity;}
.lab-globe-sec .ah-glabel-txt{
  position:absolute;left:14px;top:-16px;white-space:nowrap;
  padding:6px 9px;border-radius:8px;
  background:rgba(6,24,44,.72);border:1px solid rgba(127,212,228,.30);
  box-shadow:0 12px 26px -18px rgba(0,0,0,.8);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}
.lab-globe-sec .ah-glabel-txt b{
  display:block;font:700 12px/1.2 var(--f-display);letter-spacing:-.01em;color:#fff;
}
.lab-globe-sec .ah-glabel-txt em{
  display:block;margin-top:2px;font-style:normal;
  font:600 10.5px/1 var(--f-mono);letter-spacing:.1em;text-transform:uppercase;color:#7FD4E4;
}
/* The panels below the globe repeat what the labels say, so on a phone — where the labels
   crowd a small sphere — the globe steps back to a decorative role. */
@media (max-width:720px){
  .lab-globe-sec .ah-globe-stage{width:min(420px,92vw);}
  .lab-globe-sec .ah-glabel{display:none;}
}
/* Was: .lab-hero::after{transform:none;opacity:.22} — it flattened the CSS perspective floor
   grid under reduced motion. That grid is gone (the artwork draws the floor now) and this
   pseudo-element no longer exists, so the rule matched nothing. The reduced-motion rule that
   matters is next to .lab-metro, where it stops the loop. */
