/* ============================================================
   Layout — full-screen hero: two-column grid (content + city).
   ============================================================ */

.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  background: var(--tw-black);
}

/* Layered backdrop: glow orbs → drifting grid → vignette */
.hero__backdrop {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.hero__glow {
  position: absolute;
  width: 620px;
  height: 620px;
  border-radius: 50%;
  filter: blur(120px);
  opacity: 0.4;
  animation: orb-drift 24s ease-in-out infinite;
}

.hero__glow--1 {
  background: radial-gradient(circle, rgba(41, 151, 255, 0.5), transparent 60%);
  top: -200px;
  left: -160px;
}

.hero__glow--2 {
  background: radial-gradient(circle, rgba(125, 211, 252, 0.28), transparent 60%);
  bottom: -220px;
  right: -180px;
  animation-delay: -12s;
}

.hero__grid {
  position: absolute;
  inset: 0;
  background-image: linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(ellipse at 62% 50%, rgba(0, 0, 0, 0.85), transparent 68%);
  -webkit-mask-image: radial-gradient(ellipse at 62% 50%, rgba(0, 0, 0, 0.85), transparent 68%);
}

/* ---------- Fog — soft, slow-drifting depth layer ---------- */
.hero__fog {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  opacity: 0.22;
  animation: fog-drift 32s ease-in-out infinite;
}

.hero__fog--1 {
  width: 720px;
  height: 380px;
  background: radial-gradient(ellipse, rgba(125, 211, 252, 0.35), transparent 70%);
  top: 8%;
  left: 30%;
}

.hero__fog--2 {
  width: 640px;
  height: 340px;
  background: radial-gradient(ellipse, rgba(41, 151, 255, 0.28), transparent 70%);
  bottom: 4%;
  left: 6%;
  animation-delay: -16s;
}

/* ---------- Light rays — gentle blue beams ---------- */
.hero__rays {
  position: absolute;
  inset: 0;
  mix-blend-mode: screen;
}

.hero__ray {
  position: absolute;
  top: -10%;
  width: 220px;
  height: 140%;
  background: linear-gradient(180deg, rgba(125, 211, 252, 0.1), transparent 75%);
  transform-origin: top center;
  animation: ray-pulse 10s ease-in-out infinite;
}

.hero__ray--1 {
  left: 18%;
  transform: rotate(8deg);
}

.hero__ray--2 {
  right: 12%;
  transform: rotate(-10deg);
  animation-delay: -5s;
}

/* ---------- Background network mesh — faint, distant nodes ---------- */
.bg-network {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.5;
}

.bg-network__lines line {
  stroke: rgba(125, 211, 252, 0.14);
  stroke-width: 0.12;
  animation: node-line-pulse 6s ease-in-out infinite;
  animation-delay: var(--nd, 0s);
}

.bg-network__nodes circle {
  fill: var(--tw-electric-bright);
  animation: node-pulse 4.5s ease-in-out infinite;
  animation-delay: var(--nd, 0s);
}

/* ---------- Background particles — slow upward drift ---------- */
.bg-particles {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.bg-particle {
  position: absolute;
  bottom: -4%;
  width: 2px;
  height: 2px;
  border-radius: 50%;
  background: var(--tw-electric-pale);
  box-shadow: 0 0 5px 1px rgba(125, 211, 252, 0.5);
  opacity: 0;
  animation-name: bg-particle-drift;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

.hero__vignette {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse at 62% 50%, transparent 40%, rgba(0, 0, 0, 0.4) 80%, rgba(0, 0, 0, 0.72) 100%),
    linear-gradient(180deg, rgba(0, 0, 0, 0.35) 0%, transparent 18%, transparent 82%, rgba(0, 0, 0, 0.55) 100%);
}

/* ---------- Two-column hero grid ---------- */
.hero__grid-layout {
  position: relative;
  z-index: 2;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-md);
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(320px, 400px) 1fr;
  align-items: center;
  gap: var(--space-lg);
}

/* ---------- Left panel ---------- */
.hero__panel {
  padding-block: var(--space-lg);
  /* Nudged left within its column, away from the globe. Reset to none on
     the stacked (<=1080px) layout below, where it's centred instead. */
  transform: translateX(-10%);
}

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--tw-electric);
  margin-bottom: 1.1rem;
}

.hero__title {
  font-size: clamp(2.6rem, 4.1vw, 3.75rem);
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.08;
  color: var(--tw-white);
  margin-bottom: 1.3rem;
}

.hero__title .accent {
  display: block;
  background: linear-gradient(135deg, var(--tw-electric-pale) 0%, var(--tw-electric) 55%, var(--tw-electric-bright) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero__sub {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--tw-white);
  line-height: 1.4;
  margin-bottom: 0.9rem;
}

.hero__lead {
  font-size: 1.02rem;
  line-height: 1.6;
  color: var(--tw-ink-2);
  max-width: 42ch;
  margin-bottom: 1.75rem;
}

.feature-list {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  margin-bottom: 2rem;
  list-style: none;
}

/* No left nudge on either of these: the feature list above is flush with the
   panel's left edge (its -0.7rem margin is cancelled by an equal padding), so
   any indent here just knocks the CTA out of line with the ticks and the
   headings. Everything in the panel shares one left edge. */
.hero__cta-row {
  /* Tru-We stands to the LEFT of the button, so this is a flex pair rather
     than a lone button. He is inside this row (not a separate dock) so the
     two can never drift apart at any width. */
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-top: 0.6rem;
  margin-bottom: 0.9rem;
}

/* Sized to the room the panel actually has rather than picked by eye: the
   panel column is 400px and the button measures 278px, so 104px + the
   13.6px gap puts the pair at ~396px — inside the column, with the button
   still at its full size and nothing pushed toward the globe. */
.hero__cta-row .mascot {
  width: 104px;
  height: 104px;
}

/* His greeting, now a block of its own directly under the row. */
.hero__panel > .mascot-bubble {
  margin-top: 0.35rem;
  margin-bottom: 0.35rem;
}

.hero__microcopy {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.6rem;
  font-size: 0.78rem;
  color: var(--tw-ink-3);
}

/* ---------- Mascot dock (bottom-left corner) ---------- */
.mascot-dock {
  /* In normal document flow (not absolutely overlaid) so the speech bubble
     can never sit on top of the panel text above it — it simply pushes
     below the microcopy line instead of covering it. */
  position: static;
  z-index: 3;
  display: flex;
  align-items: flex-end;
  gap: 0.75rem;
  margin-top: 1.75rem;
  margin-left: -4.5rem;
  max-width: 100%;
}

/* ---------- Globe stage (right column) ---------- */
.city-stage {
  position: relative;
  /* aspect-ratio + width:100% (never a fixed height) is what keeps the
     stage — and therefore the WebGL camera's aspect, which js/globe.js
     derives from clientWidth/clientHeight — square-ish at every size, so
     the sphere can never render as an oval. Only ONE dimension is ever
     set; the other follows. */
  aspect-ratio: 1.05 / 1;
  width: 100%;
  max-width: 720px;
  margin-inline: auto;

  /* The two knobs the responsive block below turns. --badge-w is the
     category badge's own width; --pentagon-r is the radius of the ring
     the five badges sit on, expressed as a % of the stage. Both are
     inherited by the badges themselves, so the pentagon stays regular
     (all five at identical angular spacing and identical radius) no
     matter how far the stage scales down. */
  --badge-w: 124px;
  --pentagon-r: 60;
  /* Nudged right within its column so it reads less centred against the
     left text panel. Kept modest — .hero clips overflow, and at the
     narrower end of the two-column range (~1081-1350px) the 1fr column
     already runs flush to the right padding, so a larger shift here pushes
     the globe (and its category badges) past the viewport edge and gets it
     clipped. Reset to none on the stacked (<=1080px) layout below, where
     the stage is already centred under the text on its own row. */
  transform: translateX(9%);
}

/* Soft atmospheric haze sitting behind the whole illustration */
.city-stage__haze {
  position: absolute;
  inset: -8%;
  background: radial-gradient(ellipse at 50% 45%, rgba(41, 151, 255, 0.16), transparent 62%);
  filter: blur(18px);
  pointer-events: none;
  z-index: 0;
}

.globe-halo,
.globe-active-glow {
  z-index: 0;
}

.badge-links {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 1;
}

.category-badge {
  position: absolute;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Desktop value lives in --badge-w (set on .city-stage below) so the
     responsive block can shrink the badge and derive the stage size from
     the same number, instead of the two drifting apart. */
  width: var(--badge-w);
  text-align: center;
  background: none;
  border: 0;
  margin: 0;
  padding: 0.4rem;
  font: inherit;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.category-badge__label {
  display: block;
  margin-top: 0.55rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--tw-ink-2);
  line-height: 1.3;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.9);
  animation: label-sequence-pulse 10s ease-in-out infinite;
  animation-delay: var(--seq, 0s);
  animation-fill-mode: backwards;
  transition: color var(--dur-fast) var(--ease-out);
}

.category-badge__desc {
  display: block;
  max-height: 0;
  margin-top: 0;
  opacity: 0;
  overflow: hidden;
  font-size: 0.66rem;
  font-weight: 500;
  line-height: 1.35;
  color: var(--tw-ink-3);
  text-shadow: 0 2px 6px rgba(0, 0, 0, 0.9);
  transition: max-height var(--dur-fast) var(--ease-out),
    opacity var(--dur-fast) var(--ease-out),
    margin-top var(--dur-fast) var(--ease-out);
}

/* Five nodes at exactly even (72°) angular spacing around the globe, each
   positioned by its true centre (top/left + translate(-50%,-50%)) so the
   spacing between every pair of neighbours reads as identical — a regular
   pentagon with one vertex fixed at the top.

   Each coordinate is now the trigonometry rather than the baked-in result:
   centre (50%) ± sin/cos(72°·n) × --pentagon-r. At the desktop --pentagon-r
   of 60 these evaluate to the exact values they replaced (-10 / 31.46 /
   107.07 / 98.54 / 85.27 / 14.73 / -7.07), so desktop is untouched — but
   shrinking --pentagon-r on a phone now pulls all five badges inward
   together, keeping the pentagon regular instead of moving two of them
   and leaving a lopsided ring. */
.category-badge--infrastructure {
  top: calc(50% - var(--pentagon-r) * 1%);
  left: 50%;
  transform: translate(-50%, -50%);
  --seq: 0s;
}
.category-badge--cybersecurity {
  top: calc(50% - var(--pentagon-r) * 0.309%);
  left: calc(50% + var(--pentagon-r) * 0.9511%);
  transform: translate(-50%, -50%);
  --seq: 2s;
}
.category-badge--operations {
  top: calc(50% + var(--pentagon-r) * 0.809%);
  left: calc(50% + var(--pentagon-r) * 0.5878%);
  transform: translate(-50%, -50%);
  --seq: 4s;
}
.category-badge--licensing {
  top: calc(50% + var(--pentagon-r) * 0.809%);
  left: calc(50% - var(--pentagon-r) * 0.5878%);
  transform: translate(-50%, -50%);
  --seq: 6s;
}
.category-badge--automation {
  top: calc(50% - var(--pentagon-r) * 0.309%);
  left: calc(50% - var(--pentagon-r) * 0.9511%);
  transform: translate(-50%, -50%);
  --seq: 8s;
}

/* ---------- Loading transition overlay ---------- */
.loading-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: center;
  background: var(--tw-black);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s var(--ease-out);
}

.loading-overlay.is-active {
  opacity: 1;
  pointer-events: auto;
}

.loading-overlay__content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
}

.loading-overlay__text {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--tw-white);
  letter-spacing: -0.01em;
}

/* ---------- Responsive ----------
   The globe is scaled, never re-designed: same square stage, same regular
   pentagon of badges, same halo/network/particle layers, same WebGL scene.
   The only things that change are the stage's size and the two knobs it
   feeds (--badge-w, --pentagon-r). */
@media (max-width: 1080px) {
  .hero__grid-layout {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
    padding-block: var(--space-xl) var(--space-lg);
    min-height: auto;
  }
  .hero__panel {
    padding-block: 0;
    text-align: center;
    transform: none;
  }
  .hero__lead {
    margin-inline: auto;
  }
  /* The three benefit items, centred as ONE block rather than three
     independently-centred rows. A centred *column* (the old
     align-items:center) centres each <li> on its own text width, so the
     three ticks land at three different x positions and the list reads
     staggered. As a grid with a fit-content track, every item takes the
     width of the widest one, so the ticks line up in a single column,
     the labels share one left edge, and the block as a whole is centred
     by the auto inline margins. */
  .feature-list {
    display: grid;
    grid-auto-rows: auto;
    justify-content: center;
    justify-items: stretch;
    align-items: center;
    width: fit-content;
    max-width: 100%;
    margin-inline: auto;
    gap: 0.55rem;
  }
  .feature-item {
    /* The -0.7rem pull is a desktop-only trick that keeps the tick flush
       with the panel's left edge; centred, it just skews the block. */
    margin-inline: 0;
    justify-content: flex-start;
  }
  .hero__title .accent {
    display: inline;
  }
  .city-stage {
    transform: none;
    /* Derived, not hand-tuned. The outermost badge's centre sits at
       (50% + 0.9511·r)% of the stage; with the stage centred in its column
       that puts its far edge at 50vw + 0.009511·r·S + --badge-w/2, which
       has to stay inside the viewport. Solving for S at r = 60 gives the
       /1.1413 divisor below (0.019022 × 60). 78vh keeps the square stage
       inside a short landscape-phone viewport as well. */
    max-width: min(460px, 78vh, calc((100vw - var(--badge-w) - 16px) / 1.1413));
  }
  /* Only the landing page's dock — the assessment page reuses .mascot-dock
     with its own (working) placement and must not be touched. The desktop
     -4.5rem pull hangs Tru-We off the left edge once the panel is centred. */
  .hero__panel .mascot-dock {
    margin-left: 0;
    margin-inline: auto;
    width: fit-content;
  }
  .mascot-dock {
    justify-content: center;
    margin-top: var(--space-lg);
  }
}

@media (max-width: 640px) {
  .hero__grid-layout {
    /* Brings the globe closer to the fold without touching the gap, which
       is what gives the top/bottom badges of the pentagon their clearance. */
    padding-block: var(--space-lg) var(--space-lg);
  }
  .city-stage {
    /* Badges tuck a little closer in (r 52 instead of 60) purely so the
       stage itself — and therefore the globe — can stay large on a phone.
       They still clear the sphere, which only fills ~93% of the stage.
       Divisor is 0.019022 × 52. */
    --badge-w: clamp(88px, 26vw, 124px);
    --pentagon-r: 52;
    max-width: min(460px, 78vh, calc((100vw - var(--badge-w) - 16px) / 0.9891));
  }
  .category-badge {
    padding: 0.3rem;
  }
  /* Explicit dimensions rather than transform: scale — the icon's own
     breathing/hover animations already drive transform every frame.
     Fluid so the badge shrinks in step with the stage rather than
     snapping to one size at the breakpoint. */
  .category-badge__icon {
    width: clamp(44px, 14vw, 63px);
    height: clamp(44px, 14vw, 63px);
  }
  .category-badge__icon svg {
    width: clamp(19px, 6vw, 27px);
    height: clamp(19px, 6vw, 27px);
  }
  .category-badge__label {
    font-size: clamp(0.66rem, 3.1vw, 0.8rem);
  }
  .category-badge__desc {
    font-size: clamp(0.58rem, 2.5vw, 0.66rem);
  }
}

@media (max-width: 1080px) and (max-height: 560px) {
  /* Landscape phone — short, not narrow. The stacked layout is still the
     right shape, but the panel's portrait spacing pushes the globe a full
     screen down. Tighten the vertical rhythm and run the three feature
     items across instead of down; the globe itself is already capped at
     78vh so it lands fully visible. */
  .hero__grid-layout {
    padding-block: var(--space-md);
    gap: var(--space-md);
  }
  .feature-list {
    /* Same grid as portrait (so the ticks stay aligned), just flowed
       across instead of down. 1fr auto-columns inside a fit-content
       container gives all three items the widest one's width, so the
       row reads as three equal cells rather than three ragged ones. */
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 0.5rem 1.2rem;
    margin-bottom: 1.2rem;
  }
  .hero__panel .mascot-dock {
    margin-top: var(--space-md);
  }
}

@media (max-width: 480px) {
  /* Only the bubble here now — Tru-We's own size comes from the fluid
     clamp in the <=640 block above. A flat width at this breakpoint would
     beat that clamp (same specificity, later rule) and undo the scaling. */
  .hero__panel .mascot-bubble {
    max-width: 200px;
    font-size: 0.74rem;
  }
}

/* ---------- Stacked composition (<=1080px) — landing page only ----------

   THE BUG THIS BLOCK FIXES
   Desktop is a two-column grid: the branding panel on the left, the globe
   stage on the right, the two vertically centred against each other. The
   stacked (<=1080px) layout collapses that to `grid-template-columns: 1fr`,
   and because .hero__panel is a single grid item, the globe cannot land
   anywhere except *after the entire panel* — after the title, the lead
   paragraph, the three benefits, the CTA, the microcopy AND Tru-We. On a
   390px phone that put the stage ~990px down the page: a screen and a half
   of branding, then a globe nobody scrolls to.

   THE FIX
   .hero__panel becomes `display: contents` here, so its children join the
   hero grid directly and the globe stage can be interleaved *with* the
   branding instead of queued behind it. Ordering is then explicit:

     eyebrow -> title -> subhead -> GLOBE -> lead -> benefits -> CTA ->
     microcopy -> Tru-We

   which is the desktop reading order (branding, then the main visual, then
   the supporting content) folded into one column. The branding and the
   globe stay one connected unit at the top of the first screen; everything
   that was "around" the visual on desktop sits below it here.

   WHY NOT LITERALLY SIDE-BY-SIDE
   The globe composition is not just the sphere — the five category badges
   sit on a ring whose outermost pair spans stage x 1.14 plus a full badge
   width. At 390px that is the entire viewport, so a real two-column split
   would leave the text column under ~100px wide. The relationship is kept
   by adjacency and overlap (the stage's haze/halo bleeds up behind the
   headline) rather than by columns.

   SCOPE
   1080px is this site's own "stacked layout" breakpoint — the width at
   which the two-column grid already collapses — so the reorder covers
   exactly the range where the bug exists, and not one pixel of the
   two-column desktop layout above it. Everything is also scoped to
   .hero__grid-layout, which exists only on index.html, so the category
   page (which shares this stylesheet and has its own .city-stage) cannot
   be affected. */
@media (max-width: 1080px) {
  .hero__grid-layout {
    /* gap goes to 0 because the panel's children now ARE the grid items
       and already carry their own margins; a 4rem gap between all nine of
       them would tear the composition apart. The globe's clearance for
       its top/bottom badges is given back explicitly below. */
    gap: 0;
    padding-block: var(--space-md) var(--space-lg);
    align-content: start;
  }

  .hero__grid-layout > .hero__panel {
    display: contents;
  }

  .hero__grid-layout > .hero__panel > .hero__eyebrow    { order: 1; }
  .hero__grid-layout > .hero__panel > .hero__title      { order: 2; }
  .hero__grid-layout > .hero__panel > .hero__sub        { order: 3; }
  .hero__grid-layout > .city-stage                      { order: 4; }
  .hero__grid-layout > .hero__panel > .hero__lead       { order: 5; }
  .hero__grid-layout > .hero__panel > .feature-list     { order: 6; }
  .hero__grid-layout > .hero__panel > .hero__cta-row    { order: 7; }
  .hero__grid-layout > .hero__panel > .mascot-bubble    { order: 8; }
  .hero__grid-layout > .hero__panel > .hero__microcopy  { order: 9; }

  /* These two are inline-flex on desktop and were centred by the panel's
     text-align. As direct grid items they blockify, so they need to be
     centred as items instead. */
  .hero__grid-layout > .hero__panel > .hero__eyebrow,
  .hero__grid-layout > .hero__panel > .hero__microcopy,
  .hero__grid-layout > .hero__panel > .mascot-bubble,
  .hero__grid-layout > .hero__panel > .hero__cta-row {
    justify-self: center;
  }

  /* The row is a flex box now, so centring the panel's text is not enough
     to centre Tru-We and the button — they need centring as flex items. */
  .hero__cta-row {
    justify-content: center;
  }

  .hero__grid-layout > .hero__panel > .hero__sub {
    /* Tightened: this line and the globe below it read as one unit. */
    margin-bottom: 0.35rem;
  }

  .hero__grid-layout > .city-stage {
    /* Clearance for the pentagon's top and bottom badges, which hang
       OUTSIDE the stage box — the top badge's centre sits at -2% of the
       stage height, so roughly half a badge pokes out above it, and the
       two bottom badges hang below in the same way. Without this the
       stage's own box would butt against the subhead and the top badge
       would land on top of the text.

       The amount is a variable rather than a literal because the badge
       is not one fixed size: the <=640px block shrinks the icon, the
       label and the padding, which is why the overflow measures ~94px
       above 640px but only ~43-57px below it. Each breakpoint therefore
       declares its own clearance and this rule just consumes it. */
    --stage-clear-top: 6.5rem;
    --stage-clear-bottom: 4rem;
    margin-top: var(--stage-clear-top);
    margin-bottom: var(--stage-clear-bottom);
  }

  .hero__grid-layout > .hero__panel > .hero__lead {
    margin-bottom: 1.5rem;
  }
}

@media (max-width: 640px) {
  /* Phones: the badge is fluid here (--badge-w and the icon/label clamps
     in the <=640 block above), so its overflow shrinks with the viewport
     and the clearance has to shrink with it — a flat 6.5rem would leave
     a hole between the subhead and the globe on a 320px screen. */
  .hero__grid-layout > .city-stage {
    --stage-clear-top: clamp(3.25rem, 15vw, 4.5rem);
    --stage-clear-bottom: clamp(2.5rem, 10vw, 3.25rem);
  }

  /* Tru-We and the CTA share one row on a phone too, so both have to be
     sized against the content column rather than left at their desktop
     figures. .mascot is flex-shrink:0, so whatever he takes, the button
     gets the rest — and if the button is left at its full 278px it simply
     wraps "Start Free Assessment" onto two lines. He scales with the
     viewport and the button gives up a little type size and padding, which
     together keep the label on ONE line from 360px up. At 320px it still
     wraps, exactly as it did before he moved here — there is no way to fit
     a 190px pill and a legible robot into a 256px column. */
  .hero__cta-row {
    gap: 0.6rem;
  }
  .hero__cta-row .mascot {
    width: clamp(56px, 18vw, 104px);
    height: clamp(56px, 18vw, 104px);
  }
  .hero__cta-row .btn--primary {
    font-size: 0.95rem;
    padding-inline: 1.05rem;
  }
}

@media (max-width: 1080px) and (max-height: 560px) {
  /* Landscape phone. Same order and the same badge geometry, but the
     stage is capped at 78vh, so the surrounding rhythm tightens to keep
     the globe on the first screen. Clearance only comes down as far as
     the badges allow — an overlap is worse than a scroll. */
  .hero__grid-layout {
    padding-block: var(--space-sm) var(--space-md);
  }
  .hero__grid-layout > .city-stage {
    --stage-clear-top: 6rem;
    --stage-clear-bottom: 3.5rem;
  }
}

@media (max-width: 640px) and (max-height: 560px) {
  .hero__grid-layout > .city-stage {
    --stage-clear-top: 3.75rem;
    --stage-clear-bottom: 2.5rem;
  }
}
