/* APOLLO VPN — landing: cosmic stage, hero, cinematic scene, sections */

/* ============================================================
   STAGE — the fixed cosmic canvas shared by hero and the
   cinematic scroll scene. Everything else layers on top.
   ============================================================ */

.stage {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  contain: strict;
  opacity: 1;
  transition: opacity 450ms var(--ease-out);
}
/* The sequence releases exactly once, on navigation or on its own safety
   timeout — cinematic.js sets this and nothing ever clears it. */
.stage[data-done="true"] { opacity: 0; }
/* The footage. Two elements of the same file: one loops as ambience behind
   the hero, the other is paused and scrubbed by the scrollbar. Swapping
   between them happens through a dip to black, so the jump in timecode
   reads as a cut rather than a glitch. */
/* The hero loop lives in its own wrapper so the whole pair can fade toward
   the scene as one unit, independent of the crossfade JS runs between the
   two instances inside it to hide the loop seam. */
.stage__hero {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  will-change: opacity;
}
.stage__vid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 58% 50%;
  will-change: opacity;
  /* Graded toward the page palette: the source is cooler and brighter. */
  filter: saturate(1.06) contrast(1.05) brightness(0.92) hue-rotate(-6deg);
}
#heroVidB { opacity: 0; }
#cineVid { opacity: 0; }

.stage__fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Colour grade + radial mask: dissolves the rectangular edge of the video
   into the page so the footage never reads as a boxed-in player, and is the
   ONLY thing responsible for keeping text-safe zones dark enough to read —
   nothing else on the stage darkens text independently any more. That used
   to be split across this layer, a hero scrim, and a per-beat scrim, each
   fading on its own curve from its own center; wherever two of those curves
   disagreed, the mismatch read as a visible edge, which is exactly the
   "block on the background" seam this was reported as. One layer means
   one curve, so there is nothing left for it to disagree with.

   Six stops per axis rather than three: a long, gradual roll-off is what
   makes a gradient read as ambient light rather than a shape. The vignette
   is centred (50% 50%) rather than offset, so it can't itself introduce a
   diagonal seam against the axis-aligned fades. */
.stage__grade {
  position: absolute;
  inset: -2px;
  background:
    linear-gradient(90deg,
      oklch(0.055 0.018 276 / 0.90) 0%,
      oklch(0.056 0.019 276 / 0.82) 12%,
      oklch(0.058 0.019 276 / 0.64) 24%,
      oklch(0.059 0.019 276 / 0.42) 37%,
      oklch(0.06 0.02 276 / 0.20) 50%,
      oklch(0.061 0.02 276 / 0.07) 63%,
      transparent 76%),
    linear-gradient(180deg,
      oklch(0.058 0.02 276 / 0.52) 0%,
      oklch(0.059 0.02 276 / 0.26) 12%,
      oklch(0.06 0.02 276 / 0.08) 24%,
      transparent 36%,
      transparent 56%,
      oklch(0.06 0.02 276 / 0.22) 72%,
      oklch(0.061 0.02 276 / 0.55) 86%,
      oklch(0.062 0.02 276 / 0.90) 100%),
    radial-gradient(125% 105% at 50% 50%, transparent 52%, oklch(0.062 0.020 276 / 0.30) 100%);
}

/* Pause control: anything that plays by itself for more than five seconds
   needs a way to stop it. */
.stage__pause {
  position: absolute;
  right: max(16px, calc(var(--gutter) * 0.4));
  bottom: 26px;
  z-index: 4;
  pointer-events: auto;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: oklch(0.10 0.026 274 / 0.6);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  color: var(--ink-3);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--d-menu) ease, color var(--d-menu) ease,
              border-color var(--d-menu) ease, transform var(--d-press) var(--ease-out);
}
.stage__pause svg { width: 14px; height: 14px; }
.stage__pause:active { transform: scale(0.92); }
@media (hover: hover) and (pointer: fine) {
  .stage__pause:hover { color: var(--ink); border-color: var(--line-hi); }
}
.stage[data-hero="true"] .stage__pause { opacity: 1; }
.stage__pause:focus-visible { opacity: 1; }
.stage__bloom {
  position: absolute; inset: 0;
  background: radial-gradient(46% 46% at var(--bloom-x, 70%) var(--bloom-y, 44%), oklch(0.55 0.21 292 / 0.28), transparent 68%);
  opacity: var(--bloom-o, 1);
  transition: opacity 400ms ease;
}

@media (max-width: 860px) {
  /* Portrait crops a 16:9 frame hard, so bias the visible window toward the
     subject and let the copy sit over the darkened top. */
  /* On a 16:9 clip stretched to cover a tall narrow phone screen, only
     about a quarter of the frame's width is ever visible — object-position
     is the only thing deciding whether that quarter lands on the astronaut
     or on empty sky. The suit sits at roughly 50-52% of the source width
     in the wide shot (measured directly off the footage), so the crop
     window is centred a little left of that, with room either side. */
  .stage__vid { object-position: 44% 50%; }
  /* No side column on a phone — copy runs edge to edge over a darkened top
     band, so only the vertical curve needs to carry real weight here. */
  .stage__grade {
    background:
      linear-gradient(180deg,
        oklch(0.056 0.019 276 / 0.86) 0%,
        oklch(0.058 0.019 276 / 0.62) 14%,
        oklch(0.059 0.02 276 / 0.34) 26%,
        oklch(0.06 0.02 276 / 0.12) 38%,
        transparent 50%,
        transparent 62%,
        oklch(0.06 0.02 276 / 0.30) 78%,
        oklch(0.062 0.02 276 / 0.68) 90%,
        oklch(0.062 0.02 276 / 0.92) 100%),
      radial-gradient(140% 90% at 50% 50%, transparent 50%, oklch(0.062 0.020 276 / 0.28) 100%);
  }
  .stage__pause { bottom: 16px; right: 16px; }
}

/* ============================================================
   HERO
   ============================================================ */

.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-top: calc(var(--header-h) + 28px);
  padding-bottom: 88px;
}
.hero__in { width: 100%; }

/* The copy sits on moving footage. It used to carry its own scrim (a radial
   patch behind the text), but that scrim and the stage's permanent grade
   faded out at different rates and from different centers — two soft edges
   that don't line up read as one hard edge where they cross. One
   always-on, carefully tuned .stage__grade now does this job for every
   piece of text on the stage, hero copy included, so there is only ever
   one falloff curve to line up with, not several fighting each other. */
.hero__copy {
  position: relative;
  max-width: 620px;
}

/* Staged entrance. Deliberately quick: a headline that takes two seconds to
   arrive reads as a page that failed to load, not as choreography. First
   element at 220ms, 70ms between steps, everything settled inside 1.1s. */
.hero__copy > * {
  opacity: 0;
  transform: translateY(18px);
  animation: heroIn 560ms var(--ease-out) both;
}
.hero__badge   { animation-delay: 220ms; }
.hero__title   { animation-delay: 290ms; }
.hero__sub     { animation-delay: 380ms; }
.hero__cta     { animation-delay: 450ms; }
.hero__bens    { animation-delay: 520ms; }
.hero__micro   { animation-delay: 590ms; }

@keyframes heroIn {
  from { opacity: 0; transform: translateY(22px); filter: blur(5px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}
@media (prefers-reduced-motion: reduce) {
  .hero__copy > * { animation: none; opacity: 1; transform: none; }
}

.hero__title {
  font-size: var(--t-hero);
  line-height: 0.98;
  letter-spacing: -0.035em;
  text-transform: uppercase;
  font-weight: 800;
  margin: var(--s-5) 0 var(--s-5);
  text-wrap: balance;
}
.hero__title em {
  font-style: normal;
  color: var(--violet);
  display: block;
}

.hero__sub { color: var(--ink-3); font-size: var(--t-lead); max-width: 48ch; }

.hero__cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: clamp(32px, 2.6vw, 44px); }

.hero__bens {
  display: flex; flex-wrap: wrap; gap: var(--s-5) var(--s-6);
  margin-top: var(--s-7);
}
.hero__ben { display: flex; align-items: center; gap: 12px; }
.hero__ben-ic {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: oklch(0.14 0.03 272 / 0.5);
  color: var(--blue);
  transition: color var(--d-menu) ease, border-color var(--d-menu) ease;
}
.hero__ben-ic svg { width: 17px; height: 17px; }
.hero__ben:nth-child(2) .hero__ben-ic { color: var(--violet); }
.hero__ben:nth-child(3) .hero__ben-ic { color: var(--cyan); }
.hero__ben span {
  font-size: var(--t-xs); font-weight: 600; color: var(--ink-2);
  line-height: 1.35; max-width: 15ch;
}

.hero__micro {
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line-soft);
  font-size: var(--t-xs);
  color: var(--ink-4);
  max-width: 44ch;
}

@media (max-width: 1100px) { .hero__copy { max-width: 540px; } }

/* Mobile hero is a different composition, not a squeezed desktop (§49).
   Copy first, scene below it — the stage repositions itself in JS. */
@media (max-width: 860px) {
  .hero {
    min-height: 100svh;
    align-items: flex-start;
    padding-top: calc(var(--header-h) + 22px);
    padding-bottom: 46vh;
  }
  .hero__copy { max-width: none; }
  .hero__title { margin-block: var(--s-4); }
  .hero__bens { margin-top: var(--s-5); gap: var(--s-4) var(--s-5); }
  .hero__ben span { font-size: var(--t-micro); max-width: 12ch; }
  .hero__micro { margin-top: var(--s-5); padding-top: var(--s-4); }
}

/* ============================================================
   CINEMATIC SCROLL SCENE (§8–§18)
   ============================================================ */

/* The story plays on its own clock — cineVid runs forward at 1x once
   started, gated by a scroll lock rather than by scroll distance — so the
   beats live as fixed overlays directly on #stage instead of as content
   pinned by a tall scroll-flow section. See cinematic.js for the lock. */

/* Text beats. Each one is placed in the part of the frame the camera has
   just vacated, so the copy never sits on the astronaut or the visor.
   Absolute + inset + max-width + auto margins is the classic way to centre
   a capped-width box inside an edge-to-edge positioning parent. */
.cine__beats {
  position: absolute;
  inset: 0;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
  pointer-events: none;
}
/* Each beat used to carry its own radial scrim, same idea as the old hero
   scrim above and the same problem: four independent soft patches, each
   fading on its own curve, none lined up with the permanent .stage__grade
   sitting underneath all of them. Every visible edge the beats had was two
   mismatched fades crossing, not a real hard edge — removing the patches
   and asking .stage__grade to cover these zones properly, once, is the
   actual fix rather than softening each patch further. */
.beat {
  position: absolute;
  opacity: 0;
  will-change: opacity, transform, filter;
  pointer-events: none;
}
.beat[data-live="true"] { pointer-events: auto; }

.beat__k {
  font-family: var(--font-mono);
  font-size: var(--t-micro);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--violet);
  display: block;
  margin-bottom: var(--s-4);
}
.beat h2 {
  font-size: clamp(1.7rem, 1rem + 2.7vw, 3.2rem);
  text-transform: uppercase;
  letter-spacing: -0.03em;
  line-height: 1.02;
  margin-bottom: var(--s-4);
}
.beat p { color: var(--ink-2); font-size: var(--t-lead); max-width: 30ch; }
.beat__cta { display: flex; gap: 10px; flex-wrap: wrap; margin-top: var(--s-6); }

/* Left column: used while the subject occupies the right of the frame. */
.beat--left {
  left: var(--gutter);
  top: 50%;
  transform: translateY(-50%);
  max-width: min(30rem, 42vw);
}

/* Lower left: for the middle of the push, where the figure has drifted into
   the left of the frame and only the corner below it stays clear. */
.beat--bl {
  left: var(--gutter);
  bottom: 11vh;
  max-width: min(27rem, 38vw);
}
.beat--bl h2 { font-size: clamp(1.5rem, 0.95rem + 2vw, 2.5rem); }

/* Bottom strip: used for the visor close-up, where the logo is the subject
   and any text beside it would compete with it. */
.beat--bottom {
  left: 50%;
  bottom: 9vh;
  transform: translateX(-50%);
  text-align: center;
  max-width: 36rem;
}
.beat--bottom h2 { font-size: clamp(1.3rem, 0.9rem + 1.5vw, 2rem); }
.beat--bottom p { margin-inline: auto; font-size: var(--t-sm); max-width: 40ch; }

@media (max-width: 860px) {
  /* Portrait has no side column to speak of, so every beat becomes a band:
     the top two over the darkened sky, the last two over the darkened floor. */
  .beat--left {
    left: var(--gutter);
    right: var(--gutter);
    top: calc(var(--header-h) + 5vh);
    transform: none;
    max-width: none;
  }
  .beat p { font-size: var(--t-body); max-width: 34ch; }
  .beat--bl,
  .beat--bottom {
    bottom: 10vh; left: var(--gutter); right: var(--gutter);
    transform: none; max-width: none;
  }
  .beat--bl { text-align: left; }
}

/* Scene progress rail */
.cine__rail {
  position: absolute;
  right: max(18px, calc(var(--gutter) * 0.55));
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  gap: 10px;
}
.cine__rail i {
  display: block; width: 2px; height: 26px; border-radius: 2px;
  background: var(--line);
  transition: background-color 260ms var(--ease-out), transform 260ms var(--ease-out);
  transform-origin: 50% 50%;
}
.cine__rail i[data-on="true"] {
  background: var(--violet);
  transform: scaleX(2);
  box-shadow: 0 0 10px var(--violet);
}
@media (max-width: 860px) { .cine__rail { display: none; } }

/* Reduced motion: no lock, no autoplay, no fixed overlay — the scene stops
   being a performance and becomes a short stack of readable cards sitting
   in normal document flow. cinematic.js moves #cineBeats out of the fixed
   stage and into #cineSlot (right after the hero section) for exactly this
   case, which is what makes `position: static` below actually take. */
@media (prefers-reduced-motion: reduce) {
  .cine__slot { padding-block: clamp(48px, 7vw, 96px); }
  .cine__beats {
    position: static;
    inset: auto;
    display: grid;
    gap: clamp(28px, 4vw, 48px);
    pointer-events: auto;
  }
  .beat {
    position: static;
    opacity: 1;
    transform: none;
    max-width: 52ch;
    pointer-events: auto;
  }
  .beat--bottom { text-align: left; }
  .beat--bottom p { margin-inline: 0; }
  .cine__rail { display: none; }
}

/* ============================================================
   STATS STRIP
   ============================================================ */

.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.stat {
  display: flex; align-items: center; gap: 14px;
  padding: 24px 26px;
  background: oklch(0.098 0.028 273 / 0.7);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
}
.stat__ic {
  width: 40px; height: 40px; flex: none; display: grid; place-items: center;
  border-radius: 50%; border: 1px solid var(--line-hi);
  color: var(--blue); background: var(--blue-a12);
}
.stat:nth-child(even) .stat__ic { color: var(--violet); background: var(--violet-a12); }
.stat__ic svg { width: 18px; height: 18px; }
.stat__v { font-family: var(--font-display); font-size: 1.4rem; font-weight: 800; color: var(--ink); line-height: 1.1; }
.stat__k { font-size: var(--t-xs); color: var(--ink-4); }
.stats__note {
  grid-column: 1 / -1;
  padding: 13px 26px;
  background: oklch(0.098 0.028 273 / 0.7);
  font-size: var(--t-xs); color: var(--ink-4); text-align: center;
}
@media (max-width: 900px) { .stats { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .stats { grid-template-columns: 1fr; } .stat { padding: 18px 20px; } }

/* ============================================================
   FEATURES (§20) — deliberately asymmetric bento, not a
   six-identical-card grid.
   ============================================================ */

.feat {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 14px;
}
.feat__card {
  position: relative;
  grid-column: span 2;
  padding: 28px 26px 30px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line-soft);
  background: linear-gradient(168deg, oklch(0.125 0.030 272 / 0.72), oklch(0.085 0.024 275 / 0.6));
  overflow: hidden;
  isolation: isolate;
  transition: transform 320ms var(--ease-out), border-color 320ms ease, box-shadow 320ms ease;
}
.feat__card:nth-child(1) { grid-column: span 3; }
.feat__card:nth-child(2) { grid-column: span 3; }
.feat__card:nth-child(6) { grid-column: span 6; display: grid; grid-template-columns: 1.1fr 1fr; gap: var(--s-6); align-items: center; }

/* moving gradient wash on hover */
.feat__card::before {
  content: "";
  position: absolute; inset: -1px; z-index: -1;
  background: radial-gradient(360px 220px at var(--mx, 50%) var(--my, 0%), oklch(0.60 0.22 294 / 0.16), transparent 70%);
  opacity: 0;
  transition: opacity 320ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .feat__card:hover { transform: translateY(-4px); border-color: var(--line-hi); box-shadow: 0 24px 60px -34px oklch(0.665 0.235 296 / 0.8); }
  .feat__card:hover::before { opacity: 1; }
  .feat__card:hover .feat__ic { transform: scale(1.08); color: var(--violet); border-color: var(--line-hi); }
}
.feat__n {
  font-family: var(--font-mono); font-size: var(--t-micro);
  letter-spacing: 0.2em; color: var(--ink-4);
  position: absolute; top: 24px; right: 26px;
}
.feat__ic {
  width: 46px; height: 46px; display: grid; place-items: center;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: oklch(0.16 0.032 272 / 0.6);
  color: var(--blue);
  margin-bottom: var(--s-5);
  transition: transform 320ms var(--ease-out), color 320ms ease, border-color 320ms ease;
}
.feat__ic svg { width: 21px; height: 21px; }
.feat__card h3 { margin-bottom: 10px; }
.feat__card p { color: var(--ink-4); font-size: var(--t-sm); }
.feat__protos { display: flex; flex-wrap: wrap; gap: 7px; margin-top: var(--s-4); }

@media (max-width: 900px) {
  .feat { grid-template-columns: repeat(2, 1fr); }
  .feat__card, .feat__card:nth-child(1), .feat__card:nth-child(2) { grid-column: span 1; }
  .feat__card:nth-child(6) { grid-column: span 2; grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .feat { grid-template-columns: 1fr; }
  .feat__card:nth-child(6) { grid-column: span 1; }
}

/* ============================================================
   STEPS (§22)
   ============================================================ */

.steps { position: relative; display: grid; gap: var(--s-6); grid-template-columns: repeat(3, 1fr); }
.steps::before {
  content: "";
  position: absolute; top: 27px; left: 8%; right: 8%; height: 1px;
  background: linear-gradient(90deg, transparent, var(--line-hi), var(--line-hi), transparent);
}
.step { position: relative; padding-top: 0; }
.step__n {
  width: 54px; height: 54px; display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--line-hi);
  background: oklch(0.10 0.026 274 / 0.95);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  font-family: var(--font-display); font-weight: 800; font-size: 1.05rem;
  color: var(--violet);
  margin-bottom: var(--s-5);
  transition: box-shadow 420ms ease, color 420ms ease, transform 420ms var(--ease-out);
}
.step.is-in .step__n { box-shadow: var(--glow-violet); }
.step h3 { margin-bottom: 9px; }
.step p { color: var(--ink-4); font-size: var(--t-sm); max-width: 34ch; }
@media (max-width: 800px) {
  .steps { grid-template-columns: 1fr; gap: var(--s-5); }
  .steps::before { top: 0; bottom: 0; left: 27px; right: auto; width: 1px; height: auto;
    background: linear-gradient(180deg, transparent, var(--line-hi), transparent); }
  .step { display: grid; grid-template-columns: 54px 1fr; gap: var(--s-4); align-items: start; }
  .step__n { margin-bottom: 0; }
}

/* ============================================================
   CONNECT WIDGET (§23)
   ============================================================ */

.vpnw {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
.vpnw__card {
  padding: clamp(24px, 3vw, 34px);
  border-radius: var(--r-xl);
  border: 1px solid var(--line-hi);
  background: linear-gradient(160deg, oklch(0.145 0.034 274 / 0.82), oklch(0.085 0.024 276 / 0.78));
  backdrop-filter: blur(24px) saturate(1.3); -webkit-backdrop-filter: blur(24px) saturate(1.3);
  box-shadow: var(--sh-3), inset 0 1px 0 oklch(1 0 0 / 0.06);
  position: relative;
  overflow: hidden;
}
.vpnw__card::after {
  content: "";
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(70% 50% at 50% -10%, oklch(0.60 0.22 294 / 0.18), transparent 70%);
}
.vpnw__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); margin-bottom: var(--s-6); }
.vpnw__brand { display: flex; align-items: center; gap: 11px; font-family: var(--font-display); font-weight: 800; letter-spacing: 0.08em; color: var(--ink); text-transform: uppercase; font-size: var(--t-sm); }
.vpnw__rows { display: grid; gap: 1px; background: var(--line-soft); border: 1px solid var(--line-soft); border-radius: var(--r-md); overflow: hidden; }
.vpnw__row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
  padding: 13px 16px;
  background: oklch(0.08 0.022 276 / 0.6);
  font-size: var(--t-sm);
}
.vpnw__row dt { color: var(--ink-4); font-size: var(--t-xs); }
.vpnw__row dd { margin: 0; color: var(--ink); font-weight: 600; display: flex; align-items: center; gap: 8px; }
.vpnw__ring {
  position: relative;
  width: 100%; aspect-ratio: 1; max-width: 210px; margin: 0 auto var(--s-6);
  display: grid; place-items: center;
}
.vpnw__ring svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.vpnw__ring circle { fill: none; stroke-width: 2; }
.vpnw__ring .trk { stroke: var(--line); }
.vpnw__ring .bar {
  stroke: url(#apolloRing);
  stroke-linecap: round;
  stroke-dasharray: var(--circ, 628);
  stroke-dashoffset: var(--circ, 628);
  transition: stroke-dashoffset 700ms var(--ease-out);
  filter: drop-shadow(0 0 6px oklch(0.665 0.235 296 / 0.7));
}
.vpnw[data-state="connected"] .vpnw__ring .bar { stroke-dashoffset: 0; }
.vpnw[data-state="connecting"] .vpnw__ring .bar { stroke-dashoffset: calc(var(--circ, 628) * 0.55); }
.vpnw__core {
  width: 58%; aspect-ratio: 1; border-radius: 50%;
  display: grid; place-items: center; text-align: center;
  border: 1px solid var(--line);
  background: oklch(0.10 0.026 274 / 0.7);
  transition: box-shadow 500ms ease, border-color 500ms ease;
}
.vpnw[data-state="connected"] .vpnw__core { border-color: oklch(0.76 0.17 162 / 0.4); box-shadow: 0 0 44px -10px oklch(0.76 0.17 162 / 0.5); }
.vpnw__core b { display: block; font-family: var(--font-display); font-size: 1.1rem; color: var(--ink); }
.vpnw__core small { font-size: var(--t-micro); color: var(--ink-4); letter-spacing: 0.14em; text-transform: uppercase; }
.vpnw__cta { margin-top: var(--s-5); }
.vpnw__note { margin-top: var(--s-4); font-size: var(--t-xs); color: var(--ink-4); text-align: center; }
@media (max-width: 900px) { .vpnw { grid-template-columns: 1fr; } }

/* ============================================================
   INTERACTIVE GLOBE + SERVER SELECTOR (§19)
   ============================================================ */

.net { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: clamp(24px, 4vw, 56px); align-items: center; }
.globe {
  position: relative;
  aspect-ratio: 1;
  width: 100%;
  max-width: 620px;
  margin-inline: auto;
  touch-action: pan-y;
  cursor: grab;
}
.globe:active { cursor: grabbing; }
.globe canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.globe__hit { position: absolute; inset: 0; }
.globe__labels { position: absolute; inset: 0; pointer-events: none; }
.globe__label {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 7px;
  padding: 5px 10px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-hi);
  background: oklch(0.10 0.026 274 / 0.88);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  font-size: var(--t-micro); font-weight: 700; color: var(--ink);
  white-space: nowrap;
  opacity: 0;
  transition: opacity 220ms var(--ease-out);
}
.globe__label[data-on="true"] { opacity: 1; }
.globe__label[data-sel="true"] { border-color: var(--violet); box-shadow: var(--glow-violet); }
.globe__label em { font-style: normal; color: var(--ink-4); font-weight: 500; }

.net__panel { display: grid; gap: var(--s-5); }
.net__pick {
  padding: var(--s-6);
  border-radius: var(--r-xl);
  border: 1px solid var(--line-hi);
  background: oklch(0.11 0.028 273 / 0.75);
  backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px);
}
.net__pick-h { display: flex; align-items: center; gap: 12px; margin-bottom: var(--s-5); }
.net__pick-h .flag { font-size: 1.9rem; }
.net__pick-h b { font-family: var(--font-display); font-size: 1.3rem; color: var(--ink); display: block; line-height: 1.2; }
.net__pick-h span { font-size: var(--t-xs); color: var(--ink-4); }
.net__meta { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--line-soft); border: 1px solid var(--line-soft); border-radius: var(--r-md); overflow: hidden; margin-bottom: var(--s-5); }
.net__meta div { padding: 12px 14px; background: oklch(0.08 0.022 276 / 0.65); }
.net__meta dt { font-size: var(--t-micro); color: var(--ink-4); text-transform: uppercase; letter-spacing: 0.1em; }
.net__meta dd { margin: 4px 0 0; font-family: var(--font-display); font-weight: 700; color: var(--ink); font-size: var(--t-sm); }
@media (max-width: 980px) { .net { grid-template-columns: 1fr; } .globe { max-width: 440px; } }

/* ============================================================
   SERVERS (§24–§25)
   ============================================================ */

.srv__bar {
  display: flex; flex-wrap: wrap; gap: var(--s-4);
  align-items: center; justify-content: space-between;
  margin-bottom: var(--s-6);
}
.srv__search { position: relative; flex: 1; min-width: 240px; max-width: 340px; }
.srv__search .input { padding-left: 42px; }
.srv__search svg {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  width: 17px; height: 17px; color: var(--ink-4); pointer-events: none;
}
.srv__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.srv-card {
  position: relative;
  padding: 22px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line-soft);
  background: linear-gradient(168deg, oklch(0.125 0.030 272 / 0.7), oklch(0.085 0.024 275 / 0.62));
  display: grid;
  gap: var(--s-4);
  transition: transform 300ms var(--ease-out), border-color 300ms ease, box-shadow 300ms ease, opacity 300ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .srv-card:hover { transform: translateY(-3px); border-color: var(--line-hi); box-shadow: 0 22px 54px -34px oklch(0.665 0.235 296 / 0.75); }
}
.srv-card[data-sel="true"] { border-color: var(--violet); box-shadow: var(--glow-violet); }
.srv-card[data-hidden="true"] { display: none; }
.srv-card__top { display: flex; align-items: flex-start; gap: 12px; }
.srv-card__top .flag { font-size: 1.7rem; line-height: 1; }
.srv-card__ttl { flex: 1; min-width: 0; }
.srv-card__ttl b {
  display: block; font-family: var(--font-display); font-weight: 800;
  font-size: var(--t-body); color: var(--ink); text-transform: uppercase; letter-spacing: 0.02em;
}
.srv-card__ttl span { font-size: var(--t-xs); color: var(--ink-4); }
.srv-card__nums { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.srv-card__num { padding: 10px 12px; border-radius: var(--r-sm); background: oklch(0.06 0.02 276 / 0.55); border: 1px solid var(--line-soft); }
.srv-card__num dt { font-size: var(--t-micro); color: var(--ink-4); text-transform: uppercase; letter-spacing: 0.1em; }
.srv-card__num dd { margin: 3px 0 0; font-family: var(--font-display); font-weight: 700; font-size: var(--t-sm); color: var(--ink); }
.srv-card__load { margin-top: 7px; height: 3px; border-radius: 2px; background: var(--line); overflow: hidden; }
.srv-card__load i { display: block; height: 100%; border-radius: 2px; background: linear-gradient(90deg, var(--blue), var(--violet)); transform-origin: 0 50%; transform: scaleX(0); transition: transform 700ms var(--ease-out); }
.srv-card__protos { display: flex; flex-wrap: wrap; gap: 6px; }
.srv-card__foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }

/* ============================================================
   PRICING (§37)
   ============================================================ */

.price { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; align-items: stretch; }
.price-card {
  position: relative;
  display: grid;
  gap: var(--s-5);
  align-content: start;
  padding: clamp(26px, 3vw, 36px);
  border-radius: var(--r-xl);
  border: 1px solid var(--line-soft);
  background: linear-gradient(168deg, oklch(0.118 0.030 272 / 0.72), oklch(0.082 0.024 276 / 0.62));
  transition: transform 320ms var(--ease-out), border-color 320ms ease, box-shadow 320ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .price-card:hover { transform: translateY(-4px); border-color: var(--line-hi); }
}
.price-card--best {
  border-color: oklch(0.665 0.235 296 / 0.45);
  background: linear-gradient(168deg, oklch(0.17 0.06 288 / 0.62), oklch(0.09 0.03 280 / 0.7));
  box-shadow: 0 30px 80px -44px oklch(0.665 0.235 296 / 0.95);
}
.price-card__flag {
  position: absolute; top: 18px; right: 18px;
  font-family: var(--font-display); font-size: var(--t-micro); font-weight: 800;
  letter-spacing: 0.14em; text-transform: uppercase;
  padding: 5px 11px; border-radius: var(--r-pill);
  background: var(--violet); color: oklch(0.99 0 0);
}
.price-card__k { font-family: var(--font-display); font-size: var(--t-sm); font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-3); }
.price-card__limit {
  display: inline-flex; align-self: start;
  font-size: var(--t-micro); font-weight: 700; letter-spacing: 0.06em;
  padding: 4px 10px; border-radius: var(--r-pill);
  background: oklch(0.20 0.07 292 / 0.55); color: var(--ink-2);
  border: 1px solid var(--line-soft);
}
.price-card__v { display: flex; align-items: baseline; gap: 8px; }
.price-card__v b { font-family: var(--font-display); font-size: clamp(2.4rem, 1.6rem + 2.4vw, 3.4rem); font-weight: 800; color: var(--ink); line-height: 1; letter-spacing: -0.04em; }
.price-card__v span { font-size: var(--t-sm); color: var(--ink-4); }
.price-card__total { font-size: var(--t-xs); color: var(--ink-4); padding: 10px 13px; border-radius: var(--r-sm); background: oklch(0.06 0.02 276 / 0.5); border: 1px solid var(--line-soft); }
.price-card__total b { color: var(--ink-2); font-weight: 700; }
.price-card ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.price-card li { display: flex; align-items: flex-start; gap: 10px; font-size: var(--t-sm); color: var(--ink-3); }
.price-card li svg { width: 15px; height: 15px; flex: none; margin-top: 4px; color: var(--violet); }
@media (max-width: 980px) { .price { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .price { grid-template-columns: 1fr; } }

/* ============================================================
   FAQ + SUPPORT
   ============================================================ */

.faq-grid { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: clamp(28px, 5vw, 80px); align-items: start; }
@media (max-width: 900px) { .faq-grid { grid-template-columns: 1fr; } }

.support {
  display: grid; grid-template-columns: 1.2fr auto; gap: var(--s-6);
  align-items: center;
  padding: clamp(30px, 4vw, 54px);
  border-radius: var(--r-xl);
  border: 1px solid var(--line-hi);
  background: linear-gradient(130deg, oklch(0.16 0.05 288 / 0.6), oklch(0.085 0.024 276 / 0.7));
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  position: relative; overflow: hidden;
}
.support::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(60% 120% at 88% 10%, oklch(0.60 0.22 294 / 0.22), transparent 66%);
}
.support h2 { text-transform: uppercase; margin-bottom: var(--s-4); }
.support p { color: var(--ink-3); font-size: var(--t-sm); }
.support__cta { display: flex; gap: 10px; flex-wrap: wrap; position: relative; z-index: 1; }
@media (max-width: 780px) { .support { grid-template-columns: 1fr; } }
