/* ---------- Nav ---------- */
/* A solid surface, not a backdrop blur: 2 to 8 fps faster story scrolling (measured on an Intel UHD laptop; noisy). */
.nav {
  position: fixed; z-index: var(--z-nav); top: 18px; left: 50%; translate: -50% 0;
  width: min(var(--max), 100% - 2 * var(--gutter)); height: 64px;
  display: flex; align-items: center; gap: 12px; padding: 0 10px 0 22px; border-radius: 999px;
  background: var(--surface-solid); border: 1px solid var(--edge);
  box-shadow: inset 0 1px 0 var(--edge), 0 12px 40px -18px rgb(var(--shadow) / .28);
}
.brand { display: flex; align-items: center; gap: 10px; font-family: var(--font-display); font-weight: 650; letter-spacing: .14em; font-size: .92rem; }
.brand svg { width: 26px; height: 26px; fill: none; stroke: var(--ink); stroke-width: 2.4; stroke-linecap: round; }
.brand .sig { stroke: var(--accent); }
.brand .node { fill: var(--accent); stroke: none; }
.nav__links { display: flex; gap: 4px; margin-left: auto; }
.nav__links a { display: inline-flex; align-items: center; min-height: 44px; padding: 8px 14px; border-radius: 999px; font-size: .92rem; color: var(--ink-2); transition: background-color .2s, color .2s; }
.nav__links a:hover { background: var(--line); color: var(--ink); }
.theme-toggle, .icon-btn { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--line); background: transparent; color: var(--ink); cursor: pointer; }
.theme-toggle .icon, .icon-btn .icon { width: 20px; height: 20px; }
[data-theme="light"] .theme-toggle .i-sun, [data-theme="dark"] .theme-toggle .i-moon { display: none; }
.nav .btn { min-height: 44px; }
.menu-btn { display: none; }

/* Mobile menu: a native modal <dialog> (focus trap, Escape, inert page). No backdrop blur (it would sit over the animating globe).
   position and z-index are stated because Firefox and Safari, without `overlay` transitions, drop the sheet from the top layer for the exit fade. */
.sheet { position: fixed; z-index: 60; inset: 12px 12px auto; width: auto; max-width: 560px; max-height: calc(100svh - 24px); margin: 0 0 0 auto; padding: 0; overflow: auto; border: 1px solid var(--edge); border-radius: var(--r-panel); background: var(--surface-solid); color: var(--ink); box-shadow: 0 40px 80px -30px rgb(var(--shadow) / .55); }
.sheet::backdrop { background: rgb(7 10 24 / .4); }
.sheet__inner { display: grid; gap: 8px; padding: 10px 10px 20px 22px; }
.sheet__head { display: flex; align-items: center; justify-content: space-between; }
.sheet__label { font: 500 .74rem/1 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.sheet__links { display: grid; padding-right: 12px; }
.sheet__links a { display: flex; align-items: center; min-height: 56px; border-bottom: 1px solid var(--line); font: 600 1.5rem/1 var(--font-display); letter-spacing: -.02em; }
.sheet .btn { justify-content: center; margin: 14px 12px 0 0; }
html:has(.sheet[open]) { overflow: hidden; scrollbar-gutter: stable; } /* no shift behind the sheet with classic scrollbars */
/* The custom cursor would sit under the dialog: hide it; the sheet keeps the native one. */
html:has(.sheet[open]) .cursor { display: none; }
.has-cursor .sheet { cursor: auto; }
.has-cursor .sheet a, .has-cursor .sheet button { cursor: pointer; }
@media (prefers-reduced-motion: no-preference) {
  .sheet { transition: opacity .3s var(--ease), translate .45s var(--ease), display .3s allow-discrete, overlay .3s allow-discrete; }
  .sheet::backdrop { transition: opacity .3s; }
  .sheet:not([open])::backdrop { opacity: 0; }
  .sheet:not([open]) { opacity: 0; translate: 0 -12px; pointer-events: none; } /* a fading sheet never eats a nav click */
  @starting-style { .sheet[open] { opacity: 0; translate: 0 -12px; } .sheet[open]::backdrop { opacity: 0; } }
}

/* ---------- Hero: centred copy, the globe rises from the bottom edge ("horizon") ---------- */
.hero {
  --globe: min(1180px, 92vw); /* frame size: the sphere fills ~78% of it */
  --gap: clamp(40px, 10vh, 90px); /* buttons to the sphere's crown */
  position: relative; min-height: 100dvh;
  width: min(var(--max), 100% - 2 * var(--gutter)); margin-inline: auto;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: clamp(112px, 16.7vh, 150px) 0 0;
}
.hero__copy { position: relative; z-index: 1; max-width: 920px; display: grid; justify-items: center; } /* above the globe frame */
/* The space under the copy: the globe rises from it and adds no hero height. The slot is centred with margins, never a
   translate (see the guard comment below). On phones it is wider than the screen; overflow-x: clip keeps the page from widening. */
.hero__horizon { position: relative; flex: 1 0 0; align-self: stretch; overflow-x: clip; }
.hero__slot { position: absolute; top: calc(var(--gap) - var(--globe) * .11); left: 50%; margin-left: calc(var(--globe) / -2); width: var(--globe); aspect-ratio: 1; }
html:not(.story) .hero__horizon { flex: none; padding-top: 24px; } /* no story: the globe sits below the copy */
html:not(.story) .hero__slot { position: relative; top: auto; left: auto; margin: 0 auto; width: min(100%, 640px); }
.hero__title { margin: 0; display: grid; font-family: var(--font-display); font-weight: 600; font-size: clamp(3rem, min(5.2vw, 10.5vh), 5rem); line-height: 1.04; letter-spacing: -.045em; text-wrap: balance; }
.hero__title .line { display: block; overflow: hidden; padding-block: .12em .08em; margin-block: -.12em -.08em; } /* room for accents and descenders in the mask */
.hero__title .line > span { display: inline-block; }
.hero__title .em { color: var(--accent); }
.hero__lead { margin: clamp(16px, 3.2vh, 28px) auto 0; max-width: 40ch; font-size: clamp(1.05rem, 1.25vw, 1.2rem); color: var(--muted); }
.hero__ctas { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: clamp(24px, 4.5vh, 40px); }

@media (prefers-reduced-motion: no-preference) {
  .hero__title .line > span { animation: line-up 1.1s var(--ease) both; }
  .hero__title .line:nth-child(2) > span { animation-delay: .1s; }
  .intro { animation: fade-up 1.1s var(--ease) both; }
  .hero__lead { animation-delay: .35s; }
  .hero__ctas { animation-delay: .45s; }
}
@keyframes line-up { from { transform: translateY(115%); } }
@keyframes fade-up { from { opacity: 0; transform: translateY(24px); } }

/* ---------- Globe stage ---------- */
/* .hero__slot reserves the globe's place. Without JS the stage fills it. With JS (html.story, set in the head) story.js makes
   the stage one fixed frame gliding between each scene's [data-slot], invisible until placed so the switch never shifts layout.
   Never put transform, translate, scale, filter, will-change, contain or container-type on html, body, main, .hero,
   .hero__horizon or .hero__slot: it would trap the fixed frame. */
.stage { position: absolute; inset: 0; margin: 0; container-type: inline-size; }
.story .stage { position: fixed; z-index: 0; inset: auto; left: 0; top: 0; width: var(--globe-base, 0px); height: var(--globe-base, 0px); transform-origin: 0 0; will-change: transform; visibility: hidden; opacity: 0; }
.story .stage.is-placed { visibility: visible; opacity: 1; transition: opacity .8s var(--ease); }
.stage canvas, .stage__still { position: absolute; inset: 0; width: 100%; height: 100%; }
.stage canvas { display: block; border-radius: 50%; cursor: grab; touch-action: pan-y pinch-zoom; }
.stage canvas:active { cursor: grabbing; }
/* The focus ring is a pseudo-element, not a canvas outline (about 57 fps against 48 with the globe focused; measured on an Intel UHD laptop).
   It is the frame's first child, so it paints under the canvas and never crosses the key hint. The frame scales down in
   smaller scenes (story.js sets --scale), so the ring's inset and width, like the hint's size and place below, divide by it. */
.stage canvas:focus-visible { outline: none; }
.stage:has(canvas:focus-visible)::before { content: ""; position: absolute; inset: calc(10% - 2px / var(--scale, 1)); border: calc(2px / var(--scale, 1)) solid var(--accent); border-radius: 50%; pointer-events: none; }
@media (forced-colors: active) { .stage:has(canvas:focus-visible)::before { border-color: Highlight; } }
@supports not selector(:has(*)) { .stage canvas:focus-visible { outline: 2px solid var(--accent); outline-offset: -10cqw; outline-width: calc(2px / var(--scale, 1)); } } /* no :has: plain outline, counter-scaled */
.stage__still { object-fit: contain; }
/* The hint sits just above the sphere: in the horizon hero the frame's bottom is below the fold. */
.stage__hint { position: absolute; left: 50%; bottom: calc(89% + 10px); translate: -50% 0; scale: calc(1 / var(--scale, 1)); transform-origin: 50% 100%; padding: 6px 12px; border-radius: 999px; background: var(--chip-bg); border: 1px solid var(--edge); font: 500 .78rem/1 var(--font); color: var(--muted); white-space: nowrap; opacity: 0; transition: opacity .2s; pointer-events: none; }
.stage:has(canvas:focus-visible) .stage__hint { opacity: 1; }
.halo { position: absolute; inset: 18%; border-radius: 50%; filter: blur(70px); opacity: var(--halo-opacity); background: conic-gradient(from 210deg, #8fd3ff, #7b8cff, #c39bff, #ffb0c8, #ffd9b0, #8fd3ff); }
.floor { position: absolute; left: 22%; right: 22%; bottom: 4%; height: 8%; border-radius: 50%; background: radial-gradient(closest-side, rgb(var(--shadow) / .22), transparent); filter: blur(8px); opacity: var(--hero, 1); }

.chip {
  position: absolute; left: 0; top: 0; z-index: 3; pointer-events: none;
  display: flex; align-items: center; gap: 10px; padding: 10px 14px 10px 12px; border-radius: 16px;
  background: var(--chip-bg); border: 1px solid var(--edge);
  box-shadow: inset 0 1px 0 var(--edge), 0 18px 40px -18px rgb(var(--shadow) / .45);
  font-size: .82rem; font-weight: 600; white-space: nowrap; opacity: 0;
  transition: opacity .35s var(--ease); will-change: transform, opacity;
}
.chip.is-on { opacity: 1; }
.chip .badge { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 9px; color: var(--ok); background: color-mix(in srgb, var(--ok) 14%, transparent); }
.chip .badge .icon { width: 16px; height: 16px; }
.chip small { display: block; font-weight: 500; color: var(--muted); font-size: .74rem; }
/* "Your business": a one-line callout above the sphere (chips.js keeps it full size and sets --lead), its leader line
   drawing down to the office once it shows. */
.chip.chip--label { transform-origin: 0 0; padding: 6px 14px 6px 6px; gap: 8px; }
.chip--label .badge { width: 24px; height: 24px; border-radius: 8px; color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, transparent); }
.chip--label::after { content: ""; position: absolute; left: calc(50% - .5px); top: 100%; width: 1px; height: var(--lead, 0px); background: color-mix(in srgb, var(--accent) 70%, transparent); transform-origin: 50% 0; scale: 1 0; transition: scale .5s var(--ease) .3s; }
.chip--label.is-on::after { scale: 1; }
@media (prefers-reduced-motion: reduce) { .chip--label::after { transition: none; } }

/* The 1000px breakpoint (here and in sections.css) is shared with the JS: main.js (tab orientation) and ui.js (closing
   the menu) read it with matchMedia, and the still's `sizes` in index.html mirrors it. Change them all together. */
@media (max-width: 1000px) {
  .nav__links { display: none; }
  .theme-toggle { margin-left: auto; }
  .menu-btn { display: grid; }
  .hero { --globe: min(122vw, 800px); padding-top: 120px; } /* wider than the text column */
  .hero__title { font-size: clamp(2.6rem, min(7vw, 10.5vh), 3.25rem); }
}
@media (max-width: 560px) {
  .nav { padding-left: 16px; gap: 8px; }
  .nav .btn .label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; } /* visually hidden, still the accessible name */
  .nav .btn { width: 44px; padding: 0; justify-content: center; }
  .hero__ctas .btn { flex: 1 1 100%; justify-content: center; }
  .chip { font-size: .74rem; padding: 8px 10px; }
  .chip .badge { width: 24px; height: 24px; }
}
