/* ============================================================================
   EVC Franchise Kit — network map, territory marquee, generated backgrounds.

   Extends the design tokens already declared in evc-master-franchise.html
   (--void / --panel / --line / --ice / --mute / --cold / --mint / --amber).
   Nothing here redefines those; the kit only adds its own layer on top, so
   retheming the page retheme the map for free.
   ========================================================================= */

:root{
  /* Pipeline ramp, weakest to strongest. */
  --st-soon:#7C8B9C;
  --st-signed:#2B4BD8;
  --st-boarding:#FFB020;
  --st-open:#3BE0A0;

  /* Franchise classes. */
  --ty-hq:#FFD166;
  --ty-mothership:#3BE0A0;
  --ty-legacy:#7FA6C4;

  --map-land:#1B2530;
  --map-land-hi:#26334252;
  --map-land-hi:#263342;
  --map-stroke:#31455A;
  --map-sea:#0C1219;

  --ease-out:cubic-bezier(.2,.7,.2,1);
}

/* Country marker. Not a flag emoji — Windows has no glyphs for regional
   indicator pairs, so those render there as two bare letters. */
.iso{
  display:inline-block;font-family:var(--mono);font-size:.72em;font-weight:500;
  letter-spacing:.1em;color:var(--mute);
  border:1px solid var(--line);border-radius:2px;
  padding:.15em .4em;margin-right:.15em;
  vertical-align:.12em;line-height:1;
}
.map-tip .iso{border-color:#2C3A4A;color:var(--mute)}
.detail-head .flag .iso{font-size:12px;color:var(--amber);border-color:currentColor}

/* ---------------------------------------------------------------- backgrounds
   Everything visual here is generated — no image files, nothing to upload. */

.bg-mesh{
  position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(58% 44% at 14% 18%, rgba(43,75,216,.20), transparent 64%),
    radial-gradient(46% 38% at 86% 12%, rgba(59,224,160,.10), transparent 66%),
    radial-gradient(70% 52% at 62% 96%, rgba(255,176,32,.08), transparent 68%);
}

/* Fine hairline grid that drifts very slowly — gives the eye a parallax cue. */
.bg-grid{
  position:absolute;inset:-2px;z-index:0;pointer-events:none;opacity:.5;
  background-image:
    linear-gradient(to right, rgba(124,139,156,.07) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(124,139,156,.07) 1px, transparent 1px);
  background-size:64px 64px;
  mask-image:radial-gradient(72% 60% at 50% 42%, #000 30%, transparent 100%);
  animation:grid-drift 62s linear infinite;
}
@keyframes grid-drift{to{background-position:64px 64px}}

/* SVG turbulence grain, referenced from the <filter> defined in the page. */
.bg-grain{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  opacity:.055;mix-blend-mode:overlay;
}

/* ------------------------------------------------------------ network section */

.network{
  position:relative;z-index:3;overflow:hidden;
  background:var(--void);
  padding:clamp(74px,9vw,120px) 0 clamp(60px,7vw,96px);
}
/* Lift the content above the background layers. Deliberately NOT `.network > *`:
   that has the same specificity as .bg-mesh/.bg-grid/.bg-grain but comes later,
   so it overrode their position:absolute and dropped all three into the flow. */
.network > .network-head,
.network > .map-shell{position:relative;z-index:2}
.network-head{
  max-width:1240px;margin:0 auto clamp(28px,4vw,48px);
  padding:0 var(--gut);
  display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:24px;
}
.network-head .head-copy{max-width:620px}
.network-head h2{margin-bottom:14px}
.network-head p{margin:0}

/* Live/stale data badge. */
.feed-state{
  font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--mute);display:flex;align-items:center;gap:9px;white-space:nowrap;
}
.feed-state::before{
  content:"";width:6px;height:6px;border-radius:50%;
  background:var(--mute);box-shadow:0 0 0 0 currentColor;
}
.feed-state[data-source="live"]{color:var(--mint)}
.feed-state[data-source="live"]::before{background:var(--mint);animation:live-ping 2.6s ease-out infinite}
.feed-state[data-source="cache"]{color:var(--mute)}
.feed-state[data-source="fallback"]{color:var(--amber)}
.feed-state[data-source="fallback"]::before{background:var(--amber)}
@keyframes live-ping{
  0%{box-shadow:0 0 0 0 rgba(59,224,160,.55)}
  70%{box-shadow:0 0 0 9px rgba(59,224,160,0)}
  100%{box-shadow:0 0 0 0 rgba(59,224,160,0)}
}

/* ------------------------------------------------------------------ map shell */

.map-shell{
  max-width:1560px;margin:0 auto;padding:0 var(--gut);
  display:grid;grid-template-columns:minmax(0,1fr) 340px;
  gap:clamp(12px,1.4vw,22px);
  background:none;border:0;
}
/*
 * The stage owns its height; the map is not allowed a vote.
 *
 * This used to be `min-height`, which leaves the height indefinite — and an
 * indefinite height makes the child `height:100%` fall back to `auto`, which
 * for an SVG means "as tall as the viewBox aspect ratio says". That closed a
 * loop: fit() sets the viewBox aspect from the container, the container took
 * its height from the viewBox aspect. Gain of exactly one, so it sat still
 * until something nudged it — a scrollbar appearing, the side panel changing
 * height — and then it walked away downwards without ever settling, dragging
 * the page scrollbar with it.
 *
 * A definite height is the cut: `height:100%` on the map now resolves against
 * a real number, so the map can never be taller than the box it is measured
 * from. (Taking the map out of flow also cuts it, but absolute positioning
 * changes the stacking order inside the stage and cost four markers their
 * clicks, so the height alone does the job.)
 */
.map-stage{
  position:relative;background:var(--map-sea);
  height:min(70svh,660px);overflow:hidden;
  border-radius:16px;
}
.map-stage svg{display:block;width:100%;height:100%;touch-action:none}

/* A soft edge instead of a frame — enough to settle pins near the border,
   not so much that the map looks like it sits in a window. */
.map-stage::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:3;
  border-radius:inherit;
  box-shadow:inset 0 0 70px 14px rgba(9,13,19,.72);
}

/* ------------------------------------------------------------------ land ---- */

.evc-land path{
  fill:var(--map-land);
  stroke:var(--map-stroke);
  stroke-width:.7;                 /* non-scaling-stroke -> this is CSS pixels */
  vector-effect:non-scaling-stroke;
  opacity:0;
  transition:
    opacity .75s var(--ease-out),
    fill .35s var(--ease-out),
    stroke .25s var(--ease-out);
}
/* Continents sweep in west-to-east; the per-country delay is set once in JS. */
.map-stage.is-lit .evc-land path{opacity:1}
.evc-land path[data-status]{cursor:pointer}
.evc-land path[data-status="open"]     {fill:color-mix(in srgb,var(--st-open) 15%,var(--map-land))}
.evc-land path[data-status="boarding"] {fill:color-mix(in srgb,var(--st-boarding) 14%,var(--map-land))}
.evc-land path[data-status="signed"]   {fill:color-mix(in srgb,var(--st-signed) 22%,var(--map-land))}
.evc-land path[data-status="soon"]     {fill:color-mix(in srgb,var(--st-soon) 13%,var(--map-land))}
.evc-land path[data-status="available"]{
  fill:var(--map-land-hi);
  stroke:rgba(255,176,32,.34);
  stroke-dasharray:2.5 2.5;
}
.evc-land path.is-home{stroke:var(--mint);stroke-width:1.4}
.evc-land path[data-status]:hover{fill:var(--map-land-hi);stroke:var(--ice);stroke-width:1.2}

/* Dim everything that is not the picked country. Declared after the .is-lit
   rule above so it wins on source order at equal specificity. */
.map-stage.is-lit.is-drilled .evc-land path:not(.is-sel){opacity:.55}
.map-stage.is-lit.is-drilled .evc-land path.is-sel{opacity:1}

/* --------------------------------------------------------------- pulse rings */

.evc-pulse circle{
  fill:none;stroke:var(--amber);stroke-width:.6;
  transform-box:fill-box;transform-origin:center;
  /* Scaling a fixed r is animatable everywhere; animating `r` itself is not. */
  animation:pulse-ring 3.4s var(--ease-out) infinite;
}
.evc-pulse circle:nth-child(2){animation-delay:1.13s}
.evc-pulse circle:nth-child(3){animation-delay:2.26s}
@keyframes pulse-ring{
  0%  {transform:scale(.18);opacity:.9}
  100%{transform:scale(1.5);opacity:0}
}
.evc-pulse text{
  font-size:5.5px;text-anchor:middle;dominant-baseline:central;
  paint-order:stroke;pointer-events:none;
  animation:pulse-glyph 3.4s ease-in-out infinite;
}
@keyframes pulse-glyph{
  0%,100%{opacity:.55}
  50%{opacity:1}
}

/* ------------------------------------------------------------------- markers */

.evc-pin{cursor:pointer;transform-box:fill-box;transform-origin:center}
/* Invisible, but it takes the pointer — so the marker is clickable everywhere,
   not only where a visible shape happens to be. */
.evc-pin .hit{fill:transparent;stroke:none}
.evc-pin .halo{
  fill:currentColor;opacity:.16;
  animation:halo-breathe 4.2s ease-in-out infinite;
}
@keyframes halo-breathe{
  0%,100%{opacity:.10}
  50%{opacity:.26}
}
.evc-pin .body{
  fill:currentColor;
  stroke:var(--void);stroke-width:.5;
  filter:drop-shadow(0 0 3px currentColor);
}
.evc-pin .ring{fill:none;stroke:currentColor;stroke-width:.5;opacity:.75}
/* Solid ground for the mark, so a branch reads the same over any country. */
.evc-pin .disc{
  fill:#0A1017;
  stroke:currentColor;stroke-width:.6;
  filter:drop-shadow(0 0 3px rgba(6,8,11,.9));
}
.evc-pin[data-type="hq"] .disc{fill:#12100A;stroke-width:.85}

/* The EVC mark itself, worn by HQ and by every trading centre. */
.evc-pin .body-logo{
  pointer-events:none;
  filter:drop-shadow(0 0 2px rgba(6,8,11,.9));
}
.evc-pin[data-type="hq"] .body-logo{filter:drop-shadow(0 0 4px rgba(255,209,102,.55))}
.evc-pin:hover .body-logo,
.evc-pin:focus-visible .body-logo{filter:drop-shadow(0 0 5px currentColor)}
/* HQ gets a second, wider ring so it still outranks the trading centres. */
.evc-pin[data-type="hq"] .halo{opacity:.22}
.evc-pin[data-status="soon"] .ring{stroke-dasharray:1.6 1.6}
.evc-pin[data-type="hq"]        {color:var(--ty-hq)}
.evc-pin[data-type="mothership"]{color:var(--ty-mothership)}
.evc-pin[data-type="legacy"]    {color:var(--ty-legacy)}
/* Status still wins on the ring, so an unopened mothership reads as pipeline. */
.evc-pin[data-status="soon"]     .ring{stroke:var(--st-soon)}
.evc-pin[data-status="signed"]   .ring{stroke:var(--st-signed)}
.evc-pin[data-status="boarding"] .ring{stroke:var(--st-boarding)}
.evc-pin[data-status="open"]     .ring{stroke:var(--st-open)}
.evc-pin.is-home .body{filter:drop-shadow(0 0 6px currentColor) drop-shadow(0 0 12px currentColor)}
.evc-pin:hover,.evc-pin:focus-visible{outline:none}
.evc-pin:hover .body,.evc-pin:focus-visible .body{filter:drop-shadow(0 0 8px currentColor)}
.evc-pin:focus-visible .ring{stroke:var(--ice);stroke-width:.9;opacity:1}

/* Entry animation, driven by the scroll cinematic. */
.evc-pin{opacity:0;transition:opacity .5s var(--ease-out)}
.map-stage.is-lit .evc-pin{opacity:1}

/* ------------------------------------------------------------------ clusters */

/*
 * Where several centres sit within one marker's width of each other, they are
 * replaced by a single badge carrying the count — otherwise the topmost one
 * silently eats every click aimed at the others.
 */
.evc-pin.is-clustered{display:none}

.evc-clusters{opacity:0;transition:opacity .5s var(--ease-out)}
.map-stage.is-lit .evc-clusters{opacity:1}
.evc-cluster{cursor:pointer}
.evc-cluster .halo{fill:var(--st-open);opacity:.16}
.evc-cluster .disc{fill:var(--raise,#111823);stroke:var(--st-open);stroke-width:1.3}
.evc-cluster .count{
  fill:var(--ice);font-family:var(--mono);font-size:10px;font-weight:600;
  text-anchor:middle;pointer-events:none;
}
.evc-cluster .hit{fill:transparent}
.evc-cluster:hover .disc,.evc-cluster:focus-visible .disc{
  fill:var(--st-open);stroke:var(--ice);
}
.evc-cluster:hover .count,.evc-cluster:focus-visible .count{fill:#06131C}
.evc-cluster:hover,.evc-cluster:focus,.evc-cluster:focus-visible{outline:none}
.evc-cluster.has-hq .halo{fill:var(--amber);opacity:.2}
.evc-cluster.has-hq .disc{stroke:var(--amber);stroke-width:1.6}
.evc-cluster.has-hq:hover .disc,.evc-cluster.has-hq:focus-visible .disc{fill:var(--amber)}
.evc-cluster.is-open .disc{fill:var(--st-open);stroke:var(--ice)}
.evc-cluster.is-open .count{fill:#06131C}

/* The list a badge opens: one row per centre hiding underneath. */
.pop-list{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:2px}
.pop-list button{
  width:100%;display:grid;grid-template-columns:auto 1fr;
  align-items:center;gap:4px 9px;
  background:none;border:0;cursor:pointer;text-align:left;
  padding:9px 10px;border-radius:9px;color:inherit;font:inherit;
  transition:background .2s var(--ease-out);
}
.pop-list button:hover,.pop-list button:focus-visible{background:rgba(255,255,255,.06);outline:none}
.pop-list .dot{width:7px;height:7px;border-radius:50%;grid-row:span 2;background:var(--mute)}
.pop-list .dot[data-k="open"]{background:var(--st-open)}
.pop-list .dot[data-k="boarding"]{background:var(--st-boarding)}
.pop-list .dot[data-k="signed"]{background:var(--st-signed)}
.pop-list .dot[data-k="soon"]{background:var(--st-soon)}
.pop-list b{font-family:var(--display);font-weight:600;font-size:13.5px;color:var(--ice)}
.pop-list i{
  grid-column:2;font-style:normal;font-family:var(--mono);
  font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--mute);
}

/* --------------------------------------------------------------- energy arcs */

.evc-arcs{opacity:0;transition:opacity 1s var(--ease-out) .5s}
.map-stage.is-lit .evc-arcs{opacity:1}
.evc-arcs path{
  fill:none;stroke:var(--mint);opacity:.22;
  stroke-dasharray:3 7;
  animation:arc-flow 3.6s linear infinite;
}
@keyframes arc-flow{to{stroke-dashoffset:-20}}

/* Pulses fade in with the land rather than popping. */
.evc-pulses{opacity:0;transition:opacity .9s var(--ease-out) .45s}
.map-stage.is-lit .evc-pulses{opacity:1}

/* ------------------------------------------------------------------- tooltip */

.map-tip{
  position:absolute;z-index:11;pointer-events:none;
  transform:translate(-50%,-140%);
  background:rgba(12,17,23,.94);border:1px solid var(--line);border-radius:2px;
  padding:9px 12px;backdrop-filter:blur(10px);
  font-family:var(--mono);font-size:11px;letter-spacing:.06em;color:var(--ice);
  white-space:nowrap;opacity:0;transition:opacity .16s ease;
}
.map-tip.is-on{opacity:1}
.map-tip::after{
  content:"";position:absolute;left:var(--arrow,50%);top:100%;
  transform:translateX(-50%);
  border:5px solid transparent;border-top-color:var(--line);
}
.map-tip.is-below::after{top:auto;bottom:100%;border-top-color:transparent;border-bottom-color:var(--line)}
.map-tip b{display:block;font-weight:500;margin-bottom:3px}
.map-tip i{font-style:normal;color:var(--mute);font-size:10px;letter-spacing:.14em;text-transform:uppercase}

/* ============================================================================
   Cell-mosaic video backdrop (mounted by evc-backdrop.js)

   The module inserts #backdrop as the first child of <body> and styles nothing
   itself, so all of its geometry lives here. It must be taken out of flow: as
   a static block it was a full viewport tall and pushed the entire page down
   by one screen, so the page opened on empty background and the headline
   started below the fold.

   It sits at z-index 0 like the WebGL stage and earlier in the DOM, so the
   stage paints over it — which is the intent, "behind the 3D story". For that
   to be visible rather than merely true, the stage's base gradient carries
   alpha (see the page's own <style>).
   ========================================================================= */

#backdrop{
  position:fixed;inset:0;z-index:0;
  pointer-events:none;overflow:hidden;
  opacity:var(--bd-opacity,.34);
}

/* The mosaic is made here, not in the canvas: the canvas holds roughly one
   pixel per cell, this scales it up without smoothing and punches a circle out
   of every cell on the same pitch. */
#bd-canvas{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  image-rendering:pixelated;
  /* Lifted, not sharpened.
     This is dark workshop footage on a dark page, so the cells were coming out
     *darker* than the ground behind them: the mosaic read as a dull halftone
     rather than as moving pictures, and letting more of it through only made
     the dots darker. Brightness raises it above the page; contrast slightly
     under 1 lifts the blacks instead of crushing them, which is the opposite
     of what you would do to bright footage and exactly right here. */
  filter:brightness(1.15) saturate(1.4) contrast(.97);
  -webkit-mask-image:radial-gradient(circle at center,#000 41%,transparent 46%);
          mask-image:radial-gradient(circle at center,#000 41%,transparent 46%);
  -webkit-mask-size:var(--bd-cell,15px) var(--bd-cell,15px);
          mask-size:var(--bd-cell,15px) var(--bd-cell,15px);
  -webkit-mask-repeat:repeat;
          mask-repeat:repeat;
}

/* The frame source. It has to be rendered for Chrome to keep decoding into the
   canvas, so it is present and tiny rather than hidden. */
.bd-src{
  position:absolute;left:0;top:0;width:2px;height:2px;
  opacity:.01;pointer-events:none;
}

/* Pulls the footage back to the page palette and darkens the edges so the
   headline always has quiet ground under it. */
.bd-tint{
  position:absolute;inset:0;
  /* Clear through the middle, dark at the edges — which is where the story's
     text columns sit, so legibility is bought exactly where it is needed and
     nowhere else. */
  background:
    radial-gradient(82% 72% at 50% 40%, transparent 24%, rgba(11,16,23,.56) 100%),
    linear-gradient(180deg, rgba(16,24,34,.06) 0%, rgba(11,16,23,.34) 100%);
}

@media (max-width:900px){ #backdrop{display:none} }
@media (prefers-reduced-motion:reduce){ #backdrop{display:none} }

/* ------------------------------------------------------------------- popup

   What a marker opens. It lives inside .map-stage and is positioned by
   place(), which writes left/top and an --arrow offset, so nothing here may
   set a transform: that would fight the measured position.

   (These rules were lost when the gallery section was rewritten — the popup
   kept working, but with no styling at all it fell back to a full-width block
   in normal flow underneath the map.)
   ------------------------------------------------------------------------ */

.map-pop{
  position:absolute;z-index:12;
  width:clamp(248px,26vw,312px);
  max-height:calc(100% - 20px);overflow-y:auto;overscroll-behavior:contain;
  background:rgba(12,17,23,.96);border:1px solid var(--line);border-radius:3px;
  padding:16px 17px 15px;backdrop-filter:blur(14px);
  box-shadow:0 18px 44px rgba(0,0,0,.55);
  color:var(--ice);
  animation:pop-in .18s var(--ease-out);
}
/* `hidden` must win over the display the rules above imply. */
.map-pop[hidden]{display:none}

@keyframes pop-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.map-pop{animation:none}}

.map-pop::after{
  content:"";position:absolute;left:var(--arrow,50%);top:100%;
  transform:translateX(-50%);
  border:6px solid transparent;border-top-color:var(--line);
}
.map-pop.is-below::after{
  top:auto;bottom:100%;
  border-top-color:transparent;border-bottom-color:var(--line);
}

.pop-close{
  position:absolute;top:7px;right:8px;
  width:24px;height:24px;line-height:1;
  display:flex;align-items:center;justify-content:center;
  background:none;border:0;border-radius:2px;cursor:pointer;
  color:var(--mute);font-size:17px;
  transition:color .18s var(--ease-out),background .18s var(--ease-out);
}
.pop-close:hover,.pop-close:focus-visible{color:var(--ice);background:rgba(255,255,255,.07);outline:none}

.pop-status{
  display:flex;align-items:center;gap:7px;margin:0 0 9px;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--mute);
}
.pop-status .dot{width:6px;height:6px;border-radius:50%;background:var(--mute);flex:none}
.pop-status[data-k="open"]     .dot{background:var(--st-open);box-shadow:0 0 8px var(--st-open)}
.pop-status[data-k="boarding"] .dot{background:var(--st-boarding);box-shadow:0 0 8px var(--st-boarding)}
.pop-status[data-k="signed"]   .dot{background:var(--st-signed)}
.pop-status[data-k="soon"]     .dot{background:var(--st-soon)}

.map-pop h4{
  margin:0 22px 5px 0;
  font-family:var(--display);font-weight:600;
  font-size:16.5px;letter-spacing:-.01em;line-height:1.24;color:var(--ice);
}
.pop-where{
  margin:0 0 10px;font-size:12.5px;color:var(--mute);
}
.pop-desc{
  margin:0 0 12px;font-size:12.5px;line-height:1.5;color:#B6C4D2;
}

.pop-meta{
  margin:0 0 13px;padding:11px 0 0;border-top:1px solid var(--line);
  display:grid;grid-template-columns:auto 1fr;gap:6px 12px;
}
.pop-meta dt{
  font-family:var(--mono);font-size:9px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--mute);padding-top:2px;
}
.pop-meta dd{margin:0;font-size:12.5px;line-height:1.4;color:var(--ice)}

.pop-actions{display:flex;flex-wrap:wrap;gap:6px}
.pop-btn{
  flex:1 1 auto;text-align:center;white-space:nowrap;
  padding:8px 12px;border-radius:2px;
  border:1px solid var(--line);background:rgba(255,255,255,.03);
  color:var(--ice);text-decoration:none;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;
  transition:background .2s var(--ease-out),border-color .2s var(--ease-out),color .2s var(--ease-out);
}
.pop-btn:hover,.pop-btn:focus-visible{background:rgba(255,255,255,.09);border-color:#33465A;outline:none}
.pop-btn.primary{background:var(--mint);border-color:var(--mint);color:#06131C;font-weight:600}
.pop-btn.primary:hover,.pop-btn.primary:focus-visible{background:#5BEDB6;border-color:#5BEDB6}

/* --------------------------------------------------------------- side panel */

.map-side{
  background:var(--raise,#111823);display:flex;flex-direction:column;
  min-height:0;max-height:min(70svh,660px);
  border-radius:16px;overflow:hidden;
}
.map-side .side-scroll{overflow-y:auto;flex:1;min-height:0}
.side-block{padding:22px 24px;border-bottom:1px solid var(--line)}
.side-block:last-child{border-bottom:0}
.side-label{
  font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--mute);margin:0 0 14px;
}

/* Legend / filter chips. */
.legend{display:flex;flex-wrap:wrap;gap:7px;margin:0;padding:0;list-style:none}
.chip{
  display:inline-flex;align-items:center;gap:7px;
  font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--mute);background:none;
  border:1px solid var(--line);border-radius:2px;padding:6px 10px;
  cursor:pointer;transition:border-color .2s,color .2s,background .2s;
}
.chip .dot{width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}
.chip[data-k="open"]     {color:var(--st-open)}
.chip[data-k="boarding"] {color:var(--st-boarding)}
.chip[data-k="signed"]   {color:var(--st-signed)}
.chip[data-k="soon"]     {color:var(--st-soon)}
.chip[data-k="available"]{color:var(--amber)}
.chip[data-k="available"] .dot{background:none;border:1px dashed currentColor}
.chip[aria-pressed="false"]{color:var(--mute);opacity:.45}
.chip:hover{border-color:currentColor}
.chip:focus-visible{outline:2px solid var(--mint);outline-offset:2px}

/* Class key uses marker glyphs rather than dots. */
.classkey{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.classkey li{
  display:grid;grid-template-columns:22px 1fr;align-items:center;gap:11px;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;color:var(--mute);
}
.classkey b{color:var(--ice);font-weight:500;letter-spacing:.14em;text-transform:uppercase}
.classkey svg{width:22px;height:22px;overflow:visible}
.classkey [data-type="hq"]{color:var(--ty-hq)}
.classkey [data-type="mothership"]{color:var(--ty-mothership)}
.classkey [data-type="legacy"]{color:var(--ty-legacy)}
.classkey em{display:block;font-style:normal;color:var(--mute);margin-top:2px}
.key-note{
  font-family:var(--mono);font-size:10px;letter-spacing:.08em;color:var(--mute);
  margin:14px 0 0;padding-top:12px;border-top:1px solid var(--line);
}

/* Territory / centre list. */
.side-list{list-style:none;margin:0;padding:0}
.side-list li + li{border-top:1px solid var(--line)}
.side-item{
  width:100%;display:grid;grid-template-columns:1fr auto;gap:10px;align-items:center;
  background:none;border:0;color:inherit;text-align:left;cursor:pointer;
  padding:13px 24px;font:inherit;transition:background .2s;
}
.side-item:hover,.side-item:focus-visible{background:var(--panel);outline:none}
.side-item .nm{font-size:14px;color:var(--ice)}
.side-item .sub{
  display:block;font-family:var(--mono);font-size:10px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--mute);margin-top:3px;
}
.pill{
  font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;
  border:1px solid currentColor;border-radius:2px;padding:3px 7px;white-space:nowrap;
}
.pill[data-k="open"]     {color:var(--st-open)}
.pill[data-k="boarding"] {color:var(--st-boarding)}
.pill[data-k="signed"]   {color:var(--st-signed)}
.pill[data-k="soon"]     {color:var(--st-soon)}
.pill[data-k="available"]{color:var(--amber);border-style:dashed}

/* Detail view for a picked country. */
.detail-head{display:flex;align-items:baseline;gap:10px;margin-bottom:6px}
.detail-head .flag{line-height:1;display:inline-flex;align-items:center}
.detail-head h3{margin:0;font-size:20px}
.detail-back{
  background:none;border:0;padding:0;margin:0 0 16px;cursor:pointer;
  font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--mute);transition:color .2s;
}
.detail-back:hover{color:var(--mint)}
.detail-meta{
  list-style:none;margin:16px 0 0;padding:0;border-top:1px solid var(--line);
}
.detail-meta li{
  display:flex;justify-content:space-between;gap:14px;padding:10px 0;
  border-bottom:1px solid var(--line);
  font-family:var(--mono);font-size:11px;color:var(--mute);
}
.detail-meta li span{color:var(--ice);text-align:right}

/* The "be the first" invitation, shown for an available territory. */
.invite{padding:24px}
.invite .eyebrow{margin-bottom:16px}
.invite h3{font-size:22px;margin-bottom:10px}
.invite p{font-size:14px;margin-bottom:14px}
.invite ul{list-style:none;margin:0 0 20px;padding:0;display:grid;gap:8px}
.invite li{
  font-family:var(--mono);font-size:11px;letter-spacing:.06em;color:var(--mute);
  display:grid;grid-template-columns:14px 1fr;gap:9px;
}
.invite li::before{content:"—";color:var(--amber)}
.invite .btn{display:inline-block}

/* ------------------------------------------------------------------ marquee */

.marquee{
  position:relative;z-index:3;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  background:var(--void);overflow:hidden;
  padding:16px 0;
  mask-image:linear-gradient(to right,transparent,#000 8%,#000 92%,transparent);
}
.marquee-track{
  display:flex;width:max-content;gap:0;
  animation:marquee 64s linear infinite;
  transform:skewX(calc(var(--scroll-v,0) * -0.6deg));
  transition:transform .3s var(--ease-out);
}
.marquee:hover .marquee-track{animation-play-state:paused}
@keyframes marquee{to{transform:translateX(-50%)}}
.marquee-item{
  display:flex;align-items:center;gap:10px;padding:0 26px;
  border-right:1px solid var(--line);
  font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--mute);background:none;border-top:0;border-bottom:0;border-left:0;
  cursor:pointer;white-space:nowrap;transition:color .2s;
}
.marquee-item:hover{color:var(--ice)}
.marquee-item .flag{font-size:15px}
.marquee-item .dot{width:6px;height:6px;border-radius:50%;flex:none}
.marquee-item[data-k="open"]      .dot{background:var(--st-open)}
.marquee-item[data-k="boarding"]  .dot{background:var(--st-boarding)}
.marquee-item[data-k="signed"]    .dot{background:var(--st-signed)}
.marquee-item[data-k="soon"]      .dot{background:var(--st-soon)}
.marquee-item[data-k="available"] .dot{background:none;border:1px dashed var(--amber)}

/* -------------------------------------------------------------- map controls */

.map-ctl{
  position:absolute;left:14px;bottom:14px;z-index:5;display:flex;gap:6px;
}
.map-ctl button{
  width:30px;height:30px;display:grid;place-items:center;
  background:rgba(12,17,23,.86);border:1px solid var(--line);border-radius:2px;
  color:var(--mute);cursor:pointer;font-family:var(--mono);font-size:13px;line-height:1;
  backdrop-filter:blur(8px);transition:color .2s,border-color .2s;
}
.map-ctl button:hover{color:var(--ice);border-color:var(--mute)}
.map-ctl button:focus-visible{outline:2px solid var(--mint);outline-offset:2px}
.map-ctl button.wide{width:auto;padding:0 11px;font-size:10px;letter-spacing:.14em;text-transform:uppercase}

/* --------------------------------------------------------------- responsive */

@media (max-width:1080px){
  .map-shell{grid-template-columns:1fr}
  /* Bounded even when stacked. Unbounded, picking a country with several
     centres grows the panel, which grows the page, which moves the scrollbar —
     and the map is watching for exactly that. */
  .map-side{max-height:min(62svh,560px)}
  .map-stage{height:min(58svh,520px)}
}
@media (max-width:760px){
  .map-shell{padding:0;border-left:0;border-right:0}
  .map-stage{height:62svh}
  .network-head{flex-direction:column;align-items:flex-start}
  .side-block{padding:18px var(--gut)}
  .side-item{padding:13px var(--gut)}
  .legend{
    flex-wrap:nowrap;overflow-x:auto;padding-bottom:4px;
    scrollbar-width:none;-ms-overflow-style:none;
  }
  .legend::-webkit-scrollbar{display:none}
  .chip{flex:none}
}

@media (prefers-reduced-motion:reduce){
  .bg-grid,
  .evc-pulse circle,.evc-pulse text,
  .evc-pin .halo,.evc-arcs path,
  .marquee-track,
  .feed-state::before{animation:none!important}
  .evc-pulse circle{opacity:.45;transform:scale(.9)}
  .evc-pulse circle:nth-child(n+2){display:none}
  .evc-pin,.evc-arcs,.evc-pulses{opacity:1;transition:none}
  /* No !important here, so drilling into a country still dims its neighbours. */
  .evc-land path{opacity:1;transition:none}
  .marquee-track{transform:none}
}


/* ============================================================================
   Proof section — real footage from the Zagreb R&D centre.

   Everything else on this page is generated: the WebGL story, the map, the
   gradients. This is the one place with photographs, and it sits straight after
   the 3D story so the render is immediately answered by the real thing.

   No frame, no grid lines, no even rows. The tiles flow down columns at their
   own proportions rather than being cropped into a grid: a fixed grid of mixed
   spans always leaves holes where the next tile will not fit, and nothing about
   a photograph of a workshop wants to be trimmed to a module. They are
   duotoned to the page palette so a red
   polo shirt and a yellow bench do not fight the design, and they resolve to
   full colour on hover: the work is real, and it says so when you look at it
   directly.
   ========================================================================= */

.proof{
  position:relative;z-index:3;
  padding:clamp(70px,9vw,120px) var(--gut) clamp(84px,10vw,140px);
  background:
    radial-gradient(70% 44% at 12% 0%, rgba(43,75,216,.13), transparent 68%),
    radial-gradient(56% 40% at 92% 24%, rgba(59,224,160,.08), transparent 70%);
}
.proof-inner{max-width:1320px;margin:0 auto}
.proof .section-head{margin-bottom:clamp(34px,4.4vw,58px)}

.proof-grid{
  column-count:3;
  column-gap:clamp(12px,1.2vw,20px);
  background:none;border:0;
}

/* The span classes now only nudge how tall a tile is allowed to be, so a
   portrait shot still reads as a portrait without a fixed row to fit. */
.t-wide img{max-height:none}
.t-tall img{max-height:none}

.tile{
  position:relative;overflow:hidden;
  break-inside:avoid;-webkit-column-break-inside:avoid;
  margin:0 0 clamp(12px,1.2vw,20px);
  border-radius:14px;
  background:var(--raise,#111823);
  box-shadow:0 1px 0 rgba(255,255,255,.04) inset;
}
.tile img,.tile video{
  display:block;width:100%;height:auto;
  filter:grayscale(1) contrast(1.02) brightness(.94);
  transform:scale(1.03);
  transition:filter .55s var(--ease-out),transform .9s var(--ease-out);
}
/* mix-blend-mode:color is a true duotone — hue from this layer, luminance from
   the photograph underneath. */
.tile::before{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(150deg,#16386b 0%,#1d7a5f 56%,#4a3410 100%);
  mix-blend-mode:color;
  transition:opacity .55s var(--ease-out);
}
.tile::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(to top,rgba(6,9,13,.9) 0%,rgba(6,9,13,.14) 52%,transparent 76%);
  transition:opacity .55s var(--ease-out);
}
.tile:hover img,.tile:hover video,
.tile:focus-within img,.tile:focus-within video{filter:none;transform:scale(1.05)}
.tile:hover::before,.tile:focus-within::before{opacity:0}
.tile:hover::after,.tile:focus-within::after{opacity:.72}

.tile figcaption{
  position:absolute;left:0;right:0;bottom:0;z-index:3;
  padding:clamp(12px,1.2vw,20px);
  display:flex;flex-direction:column;gap:4px;
}
.tile figcaption b{
  font-family:var(--display);font-weight:600;
  font-size:clamp(13px,1.05vw,16px);letter-spacing:-.01em;color:var(--ice);
  text-shadow:0 1px 12px rgba(0,0,0,.6);
}
.tile figcaption span{
  font-family:var(--mono);font-size:9px;letter-spacing:.16em;
  text-transform:uppercase;color:#A9B8C8;
  text-shadow:0 1px 10px rgba(0,0,0,.6);
}

/* Marks a tile as moving footage rather than a still. */
.tile .live{
  position:absolute;top:12px;left:12px;z-index:3;
  display:flex;align-items:center;gap:6px;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--ice);
  background:rgba(11,16,23,.58);border-radius:99px;
  padding:5px 10px;backdrop-filter:blur(8px);
}
.tile .live::before{
  content:"";width:5px;height:5px;border-radius:50%;background:var(--mint);
  animation:live-ping 2.6s ease-out infinite;
}

/* Until the video is scrolled to, only the still has been downloaded. The
   video is laid over its own poster, so it has to be told to cover. */
.tile video{
  position:absolute;inset:0;height:100%;object-fit:cover;
  opacity:0;transition:opacity .6s var(--ease-out);
}
.tile video.is-on{opacity:1}

@media (max-width:1080px){
  .proof-grid{column-count:2}
}
@media (max-width:620px){
  .proof-grid{column-count:1}
  .tile{border-radius:10px}
}
@media (prefers-reduced-motion:reduce){
  .tile img,.tile video{transform:none;transition:none}
  .tile .live::before{animation:none}
}

/* ============================================================================
   Country banner + language picker

   The banner answers "is EV Clinic in my country" before the visitor scrolls
   anywhere. It is fixed above the nav, and publishes its own height as
   --evc-banner-h so the nav and hero can move down by exactly that much.
   ========================================================================= */

.evc-banner{
  position:fixed;top:0;left:0;right:0;z-index:30;
  background:rgba(8,12,17,.94);
  border-bottom:1px solid var(--line);
  backdrop-filter:blur(14px);
}
.evc-banner-inner{
  max-width:1560px;margin:0 auto;
  padding:9px var(--gut);
  display:flex;align-items:center;justify-content:space-between;gap:16px;
}
.evc-banner-msg{
  margin:0;display:flex;align-items:center;gap:10px;min-width:0;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ice);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.evc-banner-msg .pip{
  width:7px;height:7px;border-radius:50%;flex:none;
  background:var(--mint);
}
.evc-banner[data-tone="soon"]      .pip{background:var(--st-soon)}
.evc-banner[data-tone="available"] .pip{background:none;border:1px dashed var(--amber)}
.evc-banner[data-tone="open"]      .pip{animation:live-ping 2.6s ease-out infinite}

.evc-banner-act{display:flex;align-items:center;gap:8px;flex:none}
.evc-banner-cta{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
  padding:8px 15px;border-radius:2px;cursor:pointer;white-space:nowrap;
  background:var(--amber);border:1px solid var(--amber);color:#0A0704;font-weight:500;
  transition:background .2s,border-color .2s,opacity .2s;
}
.evc-banner-cta:hover{background:#ffc247;border-color:#ffc247}
.evc-banner-cta[disabled]{opacity:.6;cursor:default}
.evc-banner[data-tone="soon"] .evc-banner-cta{
  background:none;border-color:var(--line);color:var(--ice);
}
.evc-banner[data-tone="soon"] .evc-banner-cta:hover{border-color:var(--mint);color:var(--mint)}
.evc-banner-x{
  width:28px;height:28px;display:grid;place-items:center;
  background:none;border:0;border-radius:2px;cursor:pointer;
  color:var(--mute);font-size:18px;line-height:1;transition:color .2s,background .2s;
}
.evc-banner-x:hover{color:var(--ice);background:rgba(255,255,255,.06)}
.evc-banner-cta:focus-visible,.evc-banner-x:focus-visible{
  outline:2px solid var(--mint);outline-offset:2px;
}

/* The banner sits above the fixed nav, so the hero moves down by its height.
   The nav's own offset is set in the page's inline stylesheet, which is loaded
   after this file and would otherwise win. */
.hero{padding-top:var(--evc-banner-h,0px)}

.lang-pick{position:relative;display:flex;align-items:center}
.lang-pick select{
  appearance:none;-webkit-appearance:none;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;
  background:transparent;border:1px solid var(--line);border-radius:2px;
  color:var(--mute);padding:9px 26px 9px 12px;cursor:pointer;
  transition:border-color .2s,color .2s;
}
.lang-pick select:hover{border-color:var(--mute);color:var(--ice)}
.lang-pick select:focus-visible{outline:2px solid var(--mint);outline-offset:2px}
.lang-pick option{background:var(--panel);color:var(--ice);text-transform:none}
.lang-pick::after{
  content:"";position:absolute;right:10px;top:50%;pointer-events:none;
  width:0;height:0;margin-top:-1px;
  border:4px solid transparent;border-top-color:var(--mute);
}

@media (max-width:760px){
  .evc-banner-inner{padding:8px var(--gut);gap:10px}
  .evc-banner-msg{font-size:10px;letter-spacing:.06em}
  .evc-banner-cta{padding:7px 11px;font-size:9.5px;letter-spacing:.1em}
  .lang-pick select{padding:8px 22px 8px 9px;font-size:9.5px}
}
@media (prefers-reduced-motion:reduce){
  .evc-banner[data-tone="open"] .pip{animation:none}
}


/* ============================================================================
   Focus on the map

   Countries and markers are focusable, so they can be reached by keyboard. On
   click, Chrome draws its own focus ring around the SVG element's bounding box
   — a thick white rounded rectangle that looks like a rendering fault, not a
   focus state, and which spans the whole country. The page's generic
   :focus-visible rule does not reach it because an outline on an SVG shape is
   not painted the way it is on a box.

   So: no outline on these elements, and a focus state drawn with the shape's
   own stroke instead, shown only for keyboard focus.
   ========================================================================= */

.evc-land path:focus,
.evc-land path:focus-visible,
.evc-pin:focus,
.evc-pin:focus-visible,
.map-stage svg:focus,
.map-stage svg:focus-visible{
  outline:none;
}

/* Keyboard focus still has to be obvious — drawn in the shape, not around it. */
.evc-land path:focus-visible{
  stroke:var(--ice);
  stroke-width:2;
  fill:var(--map-land-hi);
}
.evc-pin:focus-visible .ring{stroke:var(--ice);stroke-width:1.1;opacity:1}
.evc-pin:focus-visible .halo{opacity:.4}
