/* ============================================================================
   world.css : the drafting camera, its copy panels, and the static fallback
   One fixed canvas behind everything. Scrub segments are transparent spacers
   the canvas shows through. Editorial sections are opaque and scroll over it.
   ========================================================================= */

/* The canvas sits at the very back. The scrub segments are transparent
   spacers it shows through; every editorial sheet is opaque and rides over
   it, which is what lets the world dissolve into paper at a handoff. */
/* No transition on the opacity. The engine writes it every frame from its
   own eased value, and a CSS transition on a per-frame write restarts on
   every write, so the rendered opacity never reaches its target: the world
   sits permanently half faded and the handoffs read as stutter. */
#world-shell {
  position: fixed; inset: 0; z-index: 0;
  pointer-events: none;
  opacity: 0;
}
#world-shell.on { opacity: 1; }
#world { position: absolute; inset: 0; }
#world canvas { display: block; width: 100%; height: 100%; }

/* the sheet frame: four hairline registration corners over the canvas */
.world-frame { position: absolute; inset: clamp(14px, 2.2vw, 30px); }
.world-frame i {
  position: absolute; width: 22px; height: 22px;
  border: 0 solid var(--rule-2);
}
.world-frame i:nth-child(1) { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; }
.world-frame i:nth-child(2) { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; }
.world-frame i:nth-child(3) { bottom: 0; left: 0; border-bottom-width: 1px; border-left-width: 1px; }
.world-frame i:nth-child(4) { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }

/* ------------------------------------------------------------ copy panels */
.wcopy {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: min(43vw, 560px);
  padding: clamp(24px, 2.6vw, 38px);
  background: rgba(247, 244, 236, .8);
  backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
  pointer-events: auto;
  opacity: 0; visibility: hidden;
  transition: opacity .34s var(--ease), transform .34s var(--ease), visibility .34s;
}
.wcopy--l { left: clamp(24px, 6vw, 96px); border-left: 1px solid var(--ink); }
.wcopy--r { right: clamp(24px, 6vw, 96px); border-right: 1px solid var(--ink); }
.wcopy::before {
  content: ""; position: absolute; top: 0; width: 1px; height: 34px;
  background: var(--brass);
}
.wcopy--l::before { left: -1px; }
.wcopy--r::before { right: -1px; }

.wcopy.on { opacity: 1; visibility: visible; }
.wcopy--l { transform: translateY(-50%) translateX(-14px); }
.wcopy--r { transform: translateY(-50%) translateX(14px); }
.wcopy.on { transform: translateY(-50%); }

.wcopy__tag {
  font-family: var(--mono); font-size: 10px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--brass-text); margin-bottom: 16px;
}
.wcopy h1, .wcopy h2 { margin-bottom: 16px; }
.wcopy h1 { font-size: clamp(31px, 3.5vw, 52px); }
.wcopy h2 { font-size: clamp(27px, 2.8vw, 41px); }
.wcopy p { color: var(--ink-2); font-size: clamp(15px, 1.05vw, 16.5px); margin-bottom: 0; }
.wcopy__acts { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; align-items: center; }
.wcopy__tags { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 22px; }
.wcopy__tags span {
  font-family: var(--mono); font-size: 9px; letter-spacing: .15em;
  text-transform: uppercase; color: var(--ink-2);
  border: 1px solid var(--rule-2); padding: 6px 10px;
}
.wcopy__stats {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--rule); border: 1px solid var(--rule); margin-top: 24px;
}
.wcopy__stats > div { background: rgba(251, 249, 243, .82); padding: 14px 16px; }
.wcopy__stats .v {
  font-family: var(--display); font-size: clamp(23px, 2.2vw, 32px);
  font-weight: 300; letter-spacing: -.02em; color: var(--brass-text); line-height: 1;
}
.wcopy__stats .l {
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-3); margin-top: 9px;
}

/* scroll hint */
.whint {
  position: absolute; left: 50%; bottom: 30px; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  font-family: var(--mono); font-size: 9px; letter-spacing: .22em;
  text-transform: uppercase; color: var(--ink-3);
  opacity: 0; transition: opacity .5s var(--ease);
}
.whint.on { opacity: 1; }
.whint .bar { width: 1px; height: 34px; background: var(--rule-2); position: relative; overflow: hidden; }
.whint .bar::after {
  content: ""; position: absolute; inset: 0; background: var(--brass);
  animation: hintrun 2.1s var(--ease) infinite;
}
@keyframes hintrun {
  0% { transform: translateY(-100%); }
  60%, 100% { transform: translateY(100%); }
}

/* On a phone there is no free half to put a drawing in, so the copy becomes
   a bottom sheet and the drawing takes the frame above it. The framing solver
   reads the live panel rectangle, so it re-aims for this by itself. */
@media (max-width: 900px) {
  .wcopy {
    top: auto; bottom: 0; left: 0; right: 0;
    width: 100%; max-height: 68dvh; overflow-y: auto;
    padding: 22px var(--gut) calc(22px + env(safe-area-inset-bottom));
    background: rgba(247, 244, 236, .9);
    border: 0; border-top: 1px solid var(--ink);
    transform: translateY(16px);
  }
  .wcopy--l, .wcopy--r { border-left: 0; border-right: 0; }
  .wcopy.on { transform: none; }
  .wcopy::before,
  .wcopy--l::before,
  .wcopy--r::before { left: 0; right: auto; top: -1px; width: 40px; height: 1px; }
  .wcopy h1 { font-size: clamp(28px, 7.6vw, 38px); }
  .wcopy h2 { font-size: clamp(25px, 6.8vw, 34px); }
  .wcopy p { font-size: 15px; }
  .wcopy__acts { margin-top: 18px; }
  .wcopy__acts .btn { flex: 1 1 auto; justify-content: center; }
  .wcopy__stats { margin-top: 16px; }
  .whint { display: none; }
}

/* ------------------------------------------------------------- the spacers */
/* Transparent scroll runway the fixed canvas shows through.

   The height is set precisely per segment by the engine, from data-scroll.
   This default matters anyway: without it the spacers are zero high until
   the engine boots, so the whole document is briefly bunched at the top and
   anything watching for "scrolled into view" fires immediately on load. */
.wseg { position: relative; z-index: 1; height: 160vh; }
.wseg__static { display: none; }

/* the static path: no WebGL, or reduced motion, or the module never booted */
.static-world #world-shell { display: none !important; }
.static-world .wseg { height: auto !important; }
.static-world .wseg__static { display: block; }

/* static blocks mirror the scrub copy, with the drafted plate beside it */
.sblock { padding-block: clamp(50px, 7vw, 96px); }
.sblock + .sblock { border-top: 1px solid var(--rule); }
.sblock__in {
  display: grid; grid-template-columns: 1fr 1.05fr;
  gap: clamp(28px, 4.6vw, 72px); align-items: center;
}
@media (max-width: 900px) { .sblock__in { grid-template-columns: 1fr; } }
.sblock .lede { margin-top: 20px; }
.sblock__acts { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; margin-top: 28px; }
.sblock__stats {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
  background: var(--rule); border: 1px solid var(--rule); margin-top: 30px;
}
.sblock__stats > div { background: var(--card); padding: 18px 20px; }
.sblock__stats .v {
  font-family: var(--display); font-size: clamp(26px, 2.6vw, 38px);
  font-weight: 300; letter-spacing: -.02em; color: var(--brass-text); line-height: 1;
}
.sblock__stats .l {
  font-family: var(--mono); font-size: 9px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-3); margin-top: 10px;
}

/* ------------------------------------------------------------- the globe */
/* solid navy, true blueprint punctuation. inked land on a navy sphere. */
.globe { position: relative; overflow: hidden; }
.globe__in {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 4vw, 70px); align-items: center;
}
@media (max-width: 940px) { .globe__in { grid-template-columns: 1fr; } }
.globe__copy { max-width: 52ch; }
.globe__copy p { color: var(--ink-2); }
/* the stage for the lifted canvas globe */
.globe-stage {
  position: relative; display: flex;
  justify-content: center; align-items: center;
  user-select: none; -webkit-user-select: none;
}
#globe {
  width: min(112%, 900px);
  aspect-ratio: 1 / 1;
  display: block;
  cursor: grab;
  touch-action: pan-y;
  -webkit-tap-highlight-color: transparent;
  outline: none;
}
#globe.dragging { cursor: grabbing; }
.globe-hint {
  position: absolute; left: 50%; bottom: 2%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 14px;
  font-family: var(--mono); font-size: 9px; letter-spacing: .22em;
  text-transform: uppercase; color: rgba(247, 244, 236, .62);
  white-space: nowrap; pointer-events: none; transition: opacity .6s var(--ease);
}
.globe-hint::before, .globe-hint::after {
  content: ""; width: clamp(26px, 4vw, 54px); height: 1px;
  background: rgba(247, 244, 236, .3);
}

.globe__legend { display: flex; flex-wrap: wrap; gap: 10px 26px; margin-top: clamp(24px, 3vw, 34px); }
.globe__legend div { display: flex; align-items: center; gap: 9px; font-family: var(--mono); font-size: 9.5px; letter-spacing: .15em; text-transform: uppercase; color: var(--ink-2); }
.globe__legend i { width: 7px; height: 7px; border: 1px solid rgba(247,244,236,.75); border-radius: 50%; flex: 0 0 7px; }
.globe__legend .hub i { border-color: var(--brass); background: var(--brass); }

@media (max-width: 560px) {
  .globe__stage { max-height: 62vh; }
}
