/* ==========================================================================
   AMIN APAC — immersive-hero.css: the dark-stage header and hero shell,
   shared by index.html and profile.html.

   Loaded after base.css and additive to it: everything below the hero is
   the existing page, untouched. The one thing this file changes about the rest
   of the site is the header, which has to sit on a dark stage here.

   Contents
   01. Stage
   02. Copy block
   03. The word over the globe
   04. Globe markers
   05. Markets rail
   06. Market card
   07. Scroll cue
   08. Header on dark
   09. Responsive
   10. Reduced motion / fallback
   ========================================================================== */

:root{
  --stage-ink:#06060A;        /* the dark the globe sits in */
  --stage-ink-2:#0B0A11;
  --stage-line:#33323E;       /* hairlines on dark, 3.0:1 on --stage-ink */
  --stage-text:#F2F1F6;       /* body copy on dark, 17.6:1 */
  --stage-dim:#A9A7B6;        /* secondary on dark, 8.1:1 */

  /* The hero is the one part of the page not held to the 1400px container.
     Copy goes to the left gutter, rail to the right, and the globe gets the
     whole middle instead of the ~570px of dead ground a centred container
     leaves on either side of a wide monitor. Capped at a 2200px measure so an
     ultrawide does not tear the two columns apart from each other. */
  --stage-gutter:max(var(--s6),calc((100vw - 2200px) / 2 + var(--s6)));
}


/* ==========================================================================
   01. Stage
   ========================================================================== */
.hero-globe{
  position:relative;
  /* A full screen, and only a full screen. svh rather than vh so mobile Safari's
     URL bar cannot push the scroll cue off the bottom of the very screen it is
     there to point down from; the vh line above it is the fallback for browsers
     that do not know the unit yet. */
  height:100vh;
  height:100svh;
  min-height:640px;
  /* Four layers, painted back to front. The two nebula washes are the point:
     one cool violet behind the sphere's lit shoulder and one warmer indigo
     low and left, so the "empty" dark reads as depth the globe is sitting in
     rather than as a flat panel. They are wide and weak on purpose — at these
     alphas nothing reads as a shape, only as air. */
  background:
    radial-gradient(58% 46% at 66% 26%, rgb(124 92 255 / .13) 0%, transparent 68%),
    radial-gradient(52% 52% at 22% 78%, rgb(70 58 140 / .11) 0%, transparent 70%),
    radial-gradient(120% 90% at 50% 42%, #14121C 0%, #0B0A11 48%, #06060A 82%),
    var(--stage-ink);
  color:var(--stage-text);
  overflow:hidden;
  isolation:isolate;
}

/* The stage bleeds into the white page below rather than butting against it,
   so the shift in ground reads as one surface turning over. */
.hero-globe::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:22%;
  background:linear-gradient(to bottom,transparent,rgb(255 255 255 / .06));
  pointer-events:none;z-index:4;
}

.globe-stage{
  position:absolute;inset:0;
  touch-action:pan-y;              /* vertical scroll still belongs to the page */
  cursor:grab;
}
.globe-stage.is-dragging{cursor:grabbing}

#globeCanvas{position:absolute;inset:0;width:100%;height:100%;display:block;z-index:1}

.stage-scrim{
  position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(100deg,
    rgb(6 6 10 / .92) 0%, rgb(6 6 10 / .64) 20%, rgb(6 6 10 / .18) 36%, transparent 50%);
}
/* The scrim exists to hold the copy. Once a market is selected the copy has
   gone, so it goes with it rather than darkening a third of the globe for no
   reason. */
.stage-scrim{transition:opacity .3s ease}
.has-selection .stage-scrim{opacity:0}
@media (max-width:900px){ .stage-scrim{display:none} }

/* Markers are projected into this layer, which is why it cannot be a flow
   container: every child is placed by transform from the top-left origin. */
.globe-layer{position:absolute;inset:0;z-index:3;pointer-events:none}
.globe-layer>*{pointer-events:auto}

/* The flare. One soft highlight where the key light falls, painted in CSS
   because a lens artefact belongs to the camera, not to the scene. */
.hero-globe::before{
  content:"";position:absolute;z-index:2;pointer-events:none;
  width:46vmax;height:46vmax;right:6%;top:2%;
  background:radial-gradient(circle,rgb(226 226 236 / .06) 0%,transparent 62%);
  filter:blur(18px);
  /* A very slow wander, far slower than anything the eye tracks. It is not an
     animation anyone should notice — it is there so the stage is never twice
     the same still frame. */
  animation:stage-flare 54s ease-in-out infinite alternate;
}
@keyframes stage-flare{
  from{transform:translate3d(0,0,0)              scale(1)}
  to  {transform:translate3d(-4vmax,3vmax,0)     scale(1.08)}
}

/* Grain and vignette, over the render but under nothing that has to be read.
   The grain is the piece that does the most work: a WebGL gradient banding
   across a large dark area is the thing that makes a background look cheap,
   and a few percent of noise breaks the bands up entirely. The SVG is inline
   as a data URI because the page has to run from file://. */
.globe-stage::after{
  /* z-index 2, not 4: above the render and the scrim, but under .globe-layer,
     so a vignette corner never dims a market's own label. */
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
    radial-gradient(124% 100% at 50% 44%, transparent 42%, rgb(3 3 6 / .58) 100%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.075'/%3E%3C/svg%3E");
  background-size:auto,160px 160px;
}


/* ==========================================================================
   02. Copy block
   ========================================================================== */
.hero-copy{
  position:absolute;z-index:5;left:0;right:0;top:clamp(76px,10vh,124px);
  pointer-events:none;
  transition:opacity .3s ease,transform .3s ease;
}

/* Drilling into a market is a change of subject, so the positioning line steps
   aside for the market's own name rather than being read through it. It comes
   back the moment the selection is cleared, and it stays in the accessibility
   tree throughout — this hides it from the eye, not from a reader. */
.has-selection .hero-copy{opacity:0;transform:translateY(-14px);pointer-events:none}
/* Off the container and onto the gutter: the headline is the left edge of the
   composition here, not a column centred in a measure. */
.hero-copy .wrap{
  display:block;max-width:none;margin:0;
  padding-left:var(--stage-gutter);padding-right:var(--s6);
}
.hero-copy>.wrap>*{pointer-events:auto}

.hero-globe .eyebrow{color:var(--stage-dim);margin-bottom:var(--s4)}

.hero-globe h1{
  max-width:14ch;margin:0;
  font-size:clamp(34px,4.2vw,56px);font-weight:400;line-height:1.06;
  color:var(--white);
  text-wrap:balance;
}
.hero-globe h1 em{font-style:normal;color:var(--lavender)}

.hero-globe .hero-lede{
  margin:var(--s5) 0 0;max-width:36ch;
  font-size:17px;line-height:26px;color:var(--stage-dim);
}


/* ==========================================================================
   03. The word over the globe
   ==========================================================================
   Set over the sphere rather than behind it, at an opacity that lets the
   continents through. It carries the selected market, so it is the one piece
   of type on the stage that changes — which is why it is aria-live and why
   the h1 above it stays fixed.
   ========================================================================== */
.hero-word{
  position:absolute;z-index:3;left:0;right:0;top:50%;
  transform:translateY(-50%);
  margin:0;padding:0 var(--s6);
  text-align:center;pointer-events:none;
  font-size:clamp(34px,6.4vw,96px);
  font-weight:600;line-height:1;
  letter-spacing:-.03em;
  white-space:nowrap;
  text-transform:uppercase;
  color:rgb(255 255 255 / .94);
  text-shadow:0 2px 44px rgb(14 7 32 / .8);
  transition:opacity .19s ease,transform .19s ease;
}
.hero-word.is-out{opacity:0;transform:translateY(-50%) scale(.985)}

/* Centred on the stage minus the column the card and the rail occupy, so a long
   market name is never read through a panel. */
@media (min-width:1181px){
  .hero-word{padding-right:560px}
}


/* ==========================================================================
   04. Globe markers
   ========================================================================== */
/* A real box, centred on the projected point by the negative margin, rather
   than a zero-sized element relying on its own children to catch the pointer.
   30px rather than the usual 44: Karachi and Mumbai are twenty-odd pixels apart
   on screen at this size, and a target big enough to swallow its neighbour is
   worse than a slightly small one. The rail below is the large target. */
.gmark{
  position:absolute;top:0;left:0;
  width:30px;height:30px;margin:-15px 0 0 -15px;
  padding:0;border:0;background:none;
  color:inherit;font:inherit;cursor:pointer;
  will-change:transform,opacity;
}
.gmark:hover,.gmark.is-linked{z-index:2}
.gmark.is-on{z-index:3}
.gmark:focus-visible{outline:none}
.gmark:focus-visible .gmark-dot{box-shadow:0 0 0 3px var(--stage-ink),0 0 0 6px var(--lavender)}

.gmark-dot,.gmark-ring,.gmark-glow{
  position:absolute;top:50%;left:50%;translate:-50% -50%;border-radius:50%;
}
.gmark-dot{
  width:10px;height:10px;background:var(--pin);
  box-shadow:0 0 0 2px rgb(14 7 32 / .55),0 0 12px rgb(79 208 141 / .8);
  transition:width .18s ease,height .18s ease,background .18s ease;
}
.gmark-ring{
  width:22px;height:22px;border:1.4px solid var(--pin);opacity:.55;
  transition:width .3s ease,height .3s ease,opacity .3s ease;
}
/* The bloom. This is what "the network is here" looks like on the sphere, and
   it is the piece standing in for the reference's filled country. */
.gmark-glow{
  width:0;height:0;opacity:0;
  mix-blend-mode:screen;
  background:radial-gradient(circle,
    rgb(232 214 255 / .90) 0%, rgb(168 116 255 / .55) 26%,
    rgb(144  79 255 / .22) 52%, transparent 72%);
  transition:width .5s cubic-bezier(.2,.8,.2,1),height .5s cubic-bezier(.2,.8,.2,1),opacity .4s ease;
}

.gmark-label{
  position:absolute;left:calc(50% + 13px);top:calc(50% - 9px + var(--ldy, 0px));white-space:nowrap;
  font-size:12px;font-weight:600;letter-spacing:.01em;
  color:var(--stage-text);
  text-shadow:0 1px 6px rgb(14 7 32 / .9);
  transition:color .18s ease;
}
.gmark.lbl-left .gmark-label{left:auto;right:calc(50% + 13px)}

.gmark-label i{
  font-style:normal;margin-left:6px;padding:1px 6px;border-radius:999px;
  background:var(--purple);color:var(--white);font-size:10px;font-weight:600;
}

.gmark.is-back .gmark-label{opacity:0}
/* A pin whose label would be printed through the headline keeps its dot and
   loses its name. The market is still in the rail, and the alternative is two
   pieces of type sharing the same pixels. */
.gmark.is-muted .gmark-label{opacity:0}
.gmark.is-muted .gmark-dot{opacity:.55}
.gmark.is-muted .gmark-ring{opacity:.25}
.gmark:hover .gmark-dot,.gmark.is-linked .gmark-dot{width:14px;height:14px}
.gmark:hover .gmark-label,.gmark.is-linked .gmark-label{color:var(--white)}
.gmark.is-linked .gmark-ring{width:30px;height:30px;opacity:.85}

.gmark.is-on .gmark-dot{width:14px;height:14px;background:var(--purple)}
.gmark.is-on .gmark-ring{width:34px;height:34px;border-color:var(--lavender);opacity:.9}
.gmark.is-on .gmark-glow{width:300px;height:300px;opacity:1}
.gmark.is-on .gmark-label{color:var(--white);font-size:13px}

/* Once a market is chosen the others step back rather than disappear: the map
   still has to show that the network is wider than the one dot. */
.has-selection .gmark:not(.is-on) .gmark-dot{opacity:.5}
.has-selection .gmark:not(.is-on) .gmark-ring{opacity:.2}
.has-selection .gmark:not(.is-on) .gmark-label{opacity:.45}


/* ==========================================================================
   05. Markets rail
   ========================================================================== */
.market-rail{
  position:absolute;z-index:6;right:var(--stage-gutter);
  top:50%;translate:0 -50%;
  display:flex;flex-direction:column;gap:2px;
  width:210px;
  padding-left:var(--s5);
  border-left:1px solid var(--stage-line);
}

.rail-row{
  position:relative;
  display:grid;grid-template-columns:1fr;gap:1px;
  padding:7px var(--s3) 7px 0;
  border:0;background:none;text-align:left;cursor:pointer;
  font:inherit;color:var(--stage-dim);
  border-radius:var(--r-sm);
  transition:color .16s ease,translate .16s ease;
}
.rail-name{font-size:13px;font-weight:600;letter-spacing:.01em}
.rail-meta{
  font-size:11px;line-height:15px;color:var(--stage-dim);opacity:.7;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* The dot sits on the rail's own hairline, so the list reads as a set of stops
   on one line rather than as a menu — the same idea as the reference. */
.rail-dot{
  position:absolute;left:calc(var(--s5) * -1 - 4px);top:14px;
  width:7px;height:7px;border-radius:50%;
  background:var(--stage-line);
  transition:background .16s ease,scale .16s ease;
}

.rail-row:hover,.rail-row:focus-visible{color:var(--white);translate:-3px 0;outline:none}
.rail-row:hover .rail-dot,.rail-row:focus-visible .rail-dot{background:var(--pin);scale:1.3}
.rail-row:focus-visible{box-shadow:0 0 0 2px var(--lavender)}

.rail-row.is-on{color:var(--white)}
.rail-row.is-on .rail-name{font-size:15px}
.rail-row.is-on .rail-meta{opacity:1;color:var(--white)}
.rail-row.is-on .rail-dot{background:var(--purple);scale:1.7}


/* ==========================================================================
   06. Market card
   ========================================================================== */
.market-card{
  position:absolute;z-index:7;
  right:calc(var(--stage-gutter) + 236px);
  top:50%;translate:0 -50%;
  width:min(360px,32vw);
  padding:var(--s5);
  background:rgb(14 7 32 / .82);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  border:1px solid var(--stage-line);
  border-radius:var(--r-lg);
  box-shadow:0 24px 60px rgb(0 0 0 / .45);
  opacity:0;transform:translateX(10px);
  transition:opacity .28s ease,transform .28s ease;
}
.market-card.is-open{opacity:1;transform:none}

.mc-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s2);margin-bottom:var(--s4)}
.mc-head b{font-size:18px;font-weight:600;color:var(--white)}
.mc-head span{font-size:13px;color:var(--stage-dim)}
.mc-clock{margin-left:auto;color:var(--stage-dim)}

.mc-entry{
  display:flex;align-items:flex-start;gap:var(--s3);width:100%;
  padding:var(--s3);margin-bottom:var(--s2);
  background:rgb(255 255 255 / .04);
  /* transparent, kept only so the row does not shrink by 2px - it never shows
     in any state. The hover used to light it up, which put an edge round a
     control whose rest state is a fill; the ground alone carries it now. */
  border:1px solid transparent;border-radius:var(--r-md);
  text-align:left;font:inherit;color:inherit;cursor:pointer;
  transition:background .16s ease;
}
.mc-entry:hover,.mc-entry:focus-visible{
  background:rgb(255 255 255 / .12);outline:none;
}
.mc-entry:focus-visible{box-shadow:0 0 0 2px var(--lavender)}
.mc-text{flex:1;min-width:0}
.mc-text h3{margin:0 0 2px;font-size:14px;font-weight:600;color:var(--white)}
.mc-text p{margin:0;font-size:12px;line-height:17px;color:var(--stage-dim)}
.mc-go{color:var(--lavender);font-size:15px;line-height:1.2}
.mc-hint{margin:var(--s3) 0 0;font-size:11px;color:var(--stage-dim);opacity:.75}


/* ==========================================================================
   07. Scroll cue
   ========================================================================== */
.hero-cue{
  position:absolute;z-index:6;left:50%;translate:-50% 0;bottom:var(--s7);
  display:flex;align-items:center;gap:var(--s2);
  font-size:12px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--stage-dim);text-decoration:none;
}
.hero-cue:hover{color:var(--white)}
.hero-cue i{
  display:block;width:1px;height:26px;
  background:linear-gradient(to bottom,var(--stage-line),transparent);
  animation:cueDrop 2.4s ease-in-out infinite;
}
@keyframes cueDrop{0%,100%{opacity:.4;transform:translateY(-3px)}50%{opacity:1;transform:translateY(3px)}}


/* ==========================================================================
   08. Header on dark
   ==========================================================================
   The header is shared markup, so it is re-grounded here rather than forked.
   The wordmark ships as a black SVG; inverting it is the only way to put it on
   a dark stage without asking for a second asset.
   ========================================================================== */
body.v2 .site-header{
  position:absolute;top:0;left:0;right:0;z-index:20;
  background:transparent;border-bottom:1px solid rgb(255 255 255 / .08);
}
body.v2 .site-header .brand img{filter:invert(1) brightness(1.9)}
body.v2 .site-header .btn-primary{
  background:var(--purple);color:var(--white);
}
body.v2 .site-header .btn-primary:hover{background:var(--purple-deep)}

/* The section nav, inverted for this bar. base.css draws it for the white
   header the five light pages use - --gray ink, --plum on hover - and both of
   those are near-invisible here: this bar is transparent over a dark hero.

   The values are the ones .hdr-crumb already uses in the SAME slot on
   index.html, deliberately: a visitor crossing from the map to a profile sees
   one bar with one treatment, and the breadcrumb and the section nav are the
   same piece of furniture wearing two hats. .62 white for the links, full white
   on hover, matching .hdr-country and .hdr-root:hover.

   Only profile.html is reached by this in practice - index.html carries the
   breadcrumb here instead and has no .ins-nav - but it is written against
   body.v2 rather than body.pf so that any future dark page gets it too. */
body.v2 .ins-nav a{color:rgb(255 255 255 / .62)}
body.v2 .ins-nav a:hover{color:var(--white)}
/* The purple underline survives the inversion - it reads on dark - so the
   current-page mark only needs its ink lifted. */
body.v2 .ins-nav a[aria-current="page"]{color:var(--white)}

/* --------------------------------------------------------------------------
   The bar as a floating plate
   Moved here from hero-map.css, where it only reached the map page. Both dark
   pages carry it now: a full-bleed transparent bar over a hero and a contained
   one over the same hero are two different chromes, and a reader crossing from
   the map to a profile has no way to read that as anything but a change of
   site.

   Why contained at all: a wordmark pinned to one edge and an action pinned to
   the other, with eleven hundred pixels of nothing between them, reads as
   unfinished rather than restrained. Inside a frame the same emptiness is
   composed.

   Selectors are body.v2 rather than .has-v2 on purpose: the dark header above
   is declared at that weight, and a lighter selector loses to it.
   -------------------------------------------------------------------------- */
@media (min-width:901px){
  body.v2 .site-header{
    top:var(--s5);
    border-bottom:0;
    /* The plate below is the subject; the bar must not clip it. */
    pointer-events:none;
  }
  body.v2 .site-header .wrap{
    pointer-events:auto;
    position:relative;                       /* the crumb centres against this */
    max-width:min(1400px,calc(100vw - var(--s10)));
    /* 72 tall against a 44 button leaves it 14 clear top and bottom, which is
       the vertical answer to the 20 beside it - a filled pill reads as its own
       bounding box, so its gaps only look equal when they are. The logo takes
       24 rather than 20: letterforms carry side bearings the button does not. */
    min-height:72px;
    padding:0 var(--s5) 0 var(--s6);
    /* Fully round, not --r-lg. The action inside is 43 tall and 14 clear of the
       top and bottom edges, and concentric corners want outer = inner + gap:
       21.5 + 14 is 35.5, which is half of 72. Anything less curves the two
       corners at different rates inside the same corner. It is also what
       --r-pill already means everywhere else - that token only ever lands on
       things under 48 tall, where 24 IS fully round. This says the same thing
       at a height where 24 would no longer deliver it. */
    border-radius:999px;
    /* --lavender at 10%, which lands near white at 8%: quieter than the
       neutral rule it replaces, and the same tinted edge the profile card
       carries, so the two pieces of chrome floating over the map are lit by
       the same palette rather than one grey and one violet. */
    border:1px solid rgb(211 185 255 / .10);   /* var(--lavender) */
    background:rgb(18 20 25 / .58);
    /* Progressive: without backdrop-filter the panel is simply more opaque,
       which is why the colour above is not fully transparent to start with. */
    backdrop-filter:blur(16px) saturate(1.25);
    -webkit-backdrop-filter:blur(16px) saturate(1.25);
    box-shadow:0 18px 44px -28px rgb(0 0 0 / .9);
  }
  @supports (backdrop-filter:blur(1px)){
    body.v2 .site-header .wrap{background:rgb(18 20 25 / .42)}
  }
}




/* ==========================================================================
   09. Responsive
   ========================================================================== */
@media (max-width:1180px){
  .market-card{
    right:auto;left:var(--s6);top:auto;bottom:calc(var(--s7) + 44px);translate:none;
    width:min(360px,calc(100vw - var(--s6) * 2));
  }
  .market-card.is-open{transform:none}
}

@media (max-width:900px){
  .hero-globe{
    height:auto;min-height:0;padding-bottom:var(--s10);
    display:flex;flex-direction:column;
  }
  .hero-copy{order:1}
  .globe-stage{order:2}
  .market-rail{order:3}
  .market-card{order:4}
  .globe-stage{position:relative;inset:auto;height:min(64svh,520px);margin-top:96px}
  .hero-copy{position:static;padding-top:104px;padding-bottom:var(--s6)}
  .hero-copy .wrap{padding-inline:var(--s6)}
  .hero-globe h1{max-width:none}
  .hero-globe .hero-lede{max-width:52ch}

  /* The rail stops being a rail and becomes a scroller under the globe: ten
     stacked rows do not fit beside a sphere on a phone, and a horizontal strip
     is the control a thumb expects there anyway. */
  .market-rail{
    position:static;translate:none;width:auto;
    flex-direction:row;gap:var(--s2);
    padding:var(--s5) var(--s6) var(--s2);
    border-left:0;border-top:1px solid var(--stage-line);
    margin-top:var(--s5);
    overflow-x:auto;scrollbar-width:none;
  }
  .market-rail::-webkit-scrollbar{display:none}
  /* Filled, not outlined. On this row the hairline was the only thing between
     one market and the next, and a scroller of six empty boxes reads as chrome;
     the same #33323E now works as a ground instead of an edge. The 1px moves
     into the padding so the row keeps the height it had. */
  .rail-row{
    flex:0 0 auto;padding:calc(var(--s3) + 1px) calc(var(--s4) + 1px);
    border:0;border-radius:var(--r-pill);background:var(--stage-line);
  }
  .rail-row.is-on{background:var(--purple)}
  .rail-dot{display:none}
  .rail-meta{display:none}

  .market-card{
    position:static;translate:none;width:auto;margin:var(--s5) var(--s6) 0;
    transform:none;
  }
  .hero-cue{display:none}
  .hero-word{font-size:clamp(24px,8vw,56px)}

  body.v2 .site-header{position:static;border-bottom:0}
  body.v2 .site-header .brand img{filter:none}
}

@media (max-width:900px){
  /* The header sits on white above the stage on small screens, so the hero
     needs its own top edge back. */
  .hero-globe{border-top:1px solid var(--stage-line)}
  .hero-copy{padding-top:var(--s8)}
  .globe-stage{margin-top:0}
}


/* ==========================================================================
   10. Entrance
   ==========================================================================
   The globe already arrives on its own — hero-globe.js flies the camera in
   from a wider, higher pose on load. This is the type catching up with it:
   the two columns settle in from their own edges, so the composition assembles
   outwards-in rather than everything appearing at once.

   Everything animates children, never .hero-copy or .market-rail themselves —
   those carry the has-selection transforms and an animation would win the
   cascade over them.
   ========================================================================== */
@keyframes stage-rise{
  from{opacity:0;transform:translateY(14px)}
  to  {opacity:1;transform:none}
}
@keyframes stage-in-left{
  from{opacity:0;transform:translateX(-12px)}
  to  {opacity:1;transform:none}
}
@keyframes stage-in-right{
  from{opacity:0;transform:translateX(12px)}
  to  {opacity:1;transform:none}
}
@keyframes stage-draw{
  from{transform:scaleY(0)}
  to  {transform:scaleY(1)}
}

.hero-copy .eyebrow,
.hero-copy h1,
.hero-copy .hero-lede{
  animation:stage-in-left .72s cubic-bezier(.22,.68,.28,1) both;
}
.hero-copy .eyebrow  {animation-delay:.16s}
.hero-copy h1        {animation-delay:.26s}
.hero-copy .hero-lede{animation-delay:.38s}

/* The rail's hairline draws down before anything is hung on it, which is what
   makes the rows read as stops on a line rather than as a list that faded in. */
.market-rail::before{
  content:"";position:absolute;left:-1px;top:0;bottom:0;width:1px;
  background:var(--stage-line);
  transform-origin:top;
  animation:stage-draw .6s cubic-bezier(.22,.68,.28,1) .42s both;
}
/* …so the border itself goes, or the line would already be there to draw. */
.market-rail{border-left-color:transparent}

.rail-row{animation:stage-in-right .5s cubic-bezier(.22,.68,.28,1) both}
.rail-row:nth-child(1) {animation-delay:.60s}
.rail-row:nth-child(2) {animation-delay:.66s}
.rail-row:nth-child(3) {animation-delay:.72s}
.rail-row:nth-child(4) {animation-delay:.78s}
.rail-row:nth-child(5) {animation-delay:.84s}
.rail-row:nth-child(6) {animation-delay:.90s}
.rail-row:nth-child(7) {animation-delay:.96s}
.rail-row:nth-child(8) {animation-delay:1.02s}
.rail-row:nth-child(9) {animation-delay:1.08s}
.rail-row:nth-child(10){animation-delay:1.14s}
.rail-row:nth-child(11){animation-delay:1.20s}

.hero-cue{animation:stage-rise .6s cubic-bezier(.22,.68,.28,1) 1.28s both}

@media (max-width:900px){
  /* Stacked, the rail is a horizontal scroller with a top border, so the
     drawn hairline has nothing to draw — hand the border back. */
  .market-rail{border-left-color:var(--stage-line)}
  .market-rail::before{display:none}
  .hero-copy .eyebrow,.hero-copy h1,.hero-copy .hero-lede{animation-name:stage-rise}
}


/* ==========================================================================
   11. Reduced motion / fallback
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  .hero-cue i,.hero-globe::before{animation:none}
  .hero-word,.market-card,.rail-row,.gmark-dot,.gmark-ring,.gmark-glow{transition:none}
  /* The entrance is decoration, not information: everything it reveals is
     already in the document, so it is simply skipped rather than shortened. */
  .hero-copy .eyebrow,.hero-copy h1,.hero-copy .hero-lede,
  .rail-row,.hero-cue,.market-rail::before{animation:none}
  .market-rail{border-left-color:var(--stage-line)}
}

/* No WebGL: the stage keeps its shape and its navigation. The markets rail is
   the part that actually does the work, so the only thing lost is the picture. */
.globe-stage.is-flat::before{
  content:"";position:absolute;top:50%;left:50%;translate:-50% -50%;
  width:min(62vh,520px);aspect-ratio:1;border-radius:50%;
  background:
    radial-gradient(circle at 34% 30%, #4B2E8F 0%, #2A1650 52%, #150C28 100%);
  box-shadow:0 0 90px rgb(158 107 255 / .35),inset -30px -20px 80px rgb(0 0 0 / .5);
}
.globe-stage.is-flat .gmark{display:none}
.globe-stage.is-flat{cursor:default}


/* ==========================================================================
   11. Region plate  (?map=apac)
   ==========================================================================
   The plate sits in the gap between the copy column and the rail, so unlike the
   globe it never has to be read through the headline. Two consequences: the
   label-suppression rule is switched off, because no label lands on the copy,
   and the scrim goes, because there is nothing behind the copy to hold it up.
   ========================================================================== */
.mode-apac .stage-scrim{display:none}
.mode-apac .gmark.is-muted .gmark-label{opacity:1}
.mode-apac .gmark.is-muted .gmark-dot{opacity:1}
.mode-apac .gmark.is-muted .gmark-ring{opacity:.55}
.mode-apac .globe-stage{cursor:default}

/* Every market is on screen at once, so the labels are load-bearing and get a
   little more weight than the globe's, which were decoration for a sphere that
   had a rail to fall back on. */
.mode-apac .gmark-label{font-size:12.5px}
.mode-apac .gmark-dot{width:11px;height:11px}
.mode-apac .gmark.is-on .gmark-glow{width:220px;height:220px}

/* The market name lands in the column the headline just vacated, rather than
   over the map. On the globe the sphere filled the middle and the name had
   nowhere else to go; here the left column is empty the moment the copy fades,
   and a name in the place the sentence was reads as the same voice continuing. */
.mode-apac .hero-word{
  top:clamp(76px,10vh,124px);
  transform:none;text-align:left;white-space:normal;
  padding-left:max(var(--s6),calc((100vw - 1400px) / 2 + var(--s6)));
  padding-right:0;
  max-width:min(46vw,15ch);
  font-size:clamp(30px,4.4vw,60px);
  letter-spacing:-.02em;
  text-shadow:none;
}
.mode-apac .hero-word.is-out{transform:translateY(-6px)}

@media (min-width:1181px){
  .mode-apac .hero-word{padding-right:0}
}

/* The rail stays on the right, where the globe has it. Moving it under the copy
   on the left was tried first, for the Tempo reference's one-column-plus-map
   composition: it bought the plate about seventy pixels of width and cost a
   collision between a ten-row list and the headline above it. Not a trade.

   What the plate does need is a narrower copy column, so the headline is set a
   step smaller here than on the globe and the gaps either side are tightened. */
.mode-apac .hero-copy{top:clamp(68px,8vh,104px)}
.mode-apac h1{max-width:12ch;font-size:clamp(30px,3.5vw,46px)}
.mode-apac .hero-lede{max-width:32ch;font-size:16px;line-height:25px}

/* Labels get a chip. White type on white dots is unreadable wherever a market
   sits inland, and this is the one composition where every label is on screen
   permanently, so none of them can afford to be a maybe. The reference does the
   same thing for the same reason. */
.mode-apac .gmark-label{
  padding:3px 7px;border-radius:5px;
  background:rgb(6 6 10 / .74);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  text-shadow:none;
}
.mode-apac .gmark.is-on .gmark-label{background:var(--purple);color:var(--white)}

@media (max-width:900px){
  /* Stacked, the plate has the full width and needs no dodging, so the copy
     column stops being a thing it has to avoid. */
  .mode-apac .globe-stage{height:min(52svh,420px)}

  /* Ten permanent chips do not fit a 390px map: they overran both edges and each
     other. The scroller below names every market anyway, so on a phone the map
     keeps its pins and labels only what is selected. */
  .mode-apac .gmark-label{display:none}
  .mode-apac .gmark.is-on .gmark-label{display:block}
  .mode-apac .hero-word{
    position:static;padding:0 var(--s6);max-width:none;
    font-size:clamp(26px,7vw,44px);margin-top:var(--s5);
  }
}
