/* ZeroGrav DM: the DM's way into Galactic Legends (galactic/js/departure.js). Nobody else ever sees any of this:
   every rule hangs on a class set only once the DM's desk has answered (#gl.dm), or on the jump itself. */

/* the terminal face of the hologram's caption: the Galactic Legends desk's own readout type */
@font-face { font-family: "IBM Plex Mono"; src: url(../assets/fonts/IBMPlexMono-400-latin.woff2) format("woff2"); font-display: swap; }

/* ── the hologram as the DM's way in: a link, with a pointer ── */
#gl.dm, #gl.dm .body { cursor: pointer; -webkit-tap-highlight-color: transparent; }
#gl.dm .body { touch-action: manipulation; }

/* ACCESS GRANTED, and then COORDINATES LOCKED: small capitals in the hologram's blue, each letter in an even slot.
   At rest it's Aurebesh, like the line it replaces. */
#gl .decode.term {
  margin-top: calc(10px * var(--k, 1)); font-family: "IBM Plex Mono", "Cascadia Mono", Consolas, ui-monospace, monospace;
  font-size: max(12px, calc(14px * var(--k, 1))); line-height: 1.6; color: #a9e2ff; transform: none;
  text-shadow: 0 0 .7em rgba(95, 212, 255, .5);
}
#gl .decode.term .c { position: relative; }
#gl .decode.term .c.aur { font-size: .72em; }
/* once it has decoded, the line flickers once, as a readout does when it catches */
#gl.dm.red:not(.locked) .decode.term { animation: zg-granted 1.8s steps(1, end) .95s both; }
@keyframes zg-granted { 0% { opacity: 1; } 3% { opacity: .45; } 5% { opacity: 1; } 9% { opacity: .7; } 11%, 100% { opacity: 1; } }
/* typing: a block cursor runs ahead of the letters */
#gl .decode.term .c.typing { color: transparent; }
#gl .decode.term .c.at::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: .56em; height: 1.02em; translate: -50% -50%;
  background: #d8f1ff; box-shadow: 0 0 .5em rgba(95, 212, 255, .8); animation: zg-cursor .5s steps(1, end) infinite;
}
@keyframes zg-cursor { 50% { opacity: 0; } }
#gl.locked .decode.term { color: #e4f5ff; text-shadow: 0 0 .6em rgba(125, 214, 255, .9), 0 0 1.6em rgba(95, 212, 255, .45); }

/* ── coordinates locked: the projector holds a steady blue ── */
#gl.locked .holo-flicker { animation: none; opacity: 1; }
#gl.locked.ready .beam { opacity: .95; transition: opacity .3s ease; }
#gl.locked.ready .emitter::after, #gl.gl-holo.locked.ready .emitter::after {
  background: #effaff; box-shadow: 0 0 10px 2px rgba(160, 222, 255, .95), 0 0 26px 6px rgba(95, 190, 255, .45); transition: background .25s ease, box-shadow .25s ease;
}

/* ── the jump: the rest of the page dims and eases toward you (the jump's script sets the numbers, every frame) ── */
/* (galactic/js/departure.js sets main's scale and these elements' opacity straight on them, every frame) */
html.jumping main { transform-origin: var(--jump-x, 50%) var(--jump-y, 50%); }
/* the page that zooms is its own layer only while it zooms: a layer from the moment the DM was known put the star and
   world cards (inside main) under the title (outside it) */
html.jumping main { will-change: scale; }
/* the page grown past the screen's edge mustn't widen a phone's view (the desk would open at another size, and the
   browser would drop the page transition) */
html.jumping body { contain: paint; }
html.jumping :is(#arania, #others, #stars, #star-lines, #brand, #orrery, #light, footer.credits, #sound) { transition: none; }
html.jumping :is(#star-card, #world-card) { visibility: hidden; }
html.jumping #gl .cap { transition: none; }
html.jumping #gl { cursor: default; }
/* the streaks take the sky's place */
html.streaking #sky { visibility: hidden; }
.jump-sky, .jump-flash { position: fixed; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; }
/* the light is blended over the page as light: it brightens what's under it rather than greying it */
.jump-flash { z-index: 40; mix-blend-mode: screen; }
.jump-flash.full { mix-blend-mode: normal; }        /* ...but at full it's the flash alone, as the desk's first frame is */
.jump-flash.hold { pointer-events: auto; cursor: default; }
/* made ahead of the jump (so the click doesn't stall it), and out of the way until then */
.jump-sky.idle, .jump-flash.idle { visibility: hidden; }

/* ── back from the desk: the first frame is the jump's flash (the jump's script takes it over at once; if it never does,
   the flash still clears on its own) ── */
html.hyperspace-return::after {
  content: ""; position: fixed; inset: 0; z-index: 41; pointer-events: none;
  background: radial-gradient(circle farthest-corner at var(--hs-x, 72%) var(--hs-y, 45%), #fff, #ecf7ff 38%, #c2e4ff);
  animation: zg-flash-clears .9s ease-in .5s both;
}
@keyframes zg-flash-clears { to { opacity: 0; visibility: hidden; } }
/* the desk's last frame burns out into the flash, rushing past */
html:active-view-transition-type(hyperspace-out)::view-transition-old(root) {
  z-index: 1; mix-blend-mode: normal; transform-origin: 50% 50%; animation: zg-burn-out .26s cubic-bezier(.5, 0, .9, .5) both;
}
html:active-view-transition-type(hyperspace-out)::view-transition-new(root) { mix-blend-mode: normal; animation: none; }
@keyframes zg-burn-out {
  0% { opacity: 1; transform: none; filter: none; }
  100% { opacity: 0; transform: scale(1.12); filter: brightness(2.4) saturate(.4); }
}

@media (prefers-reduced-motion: reduce) {
  #gl.dm.red .decode.term { animation: none; }
  #gl .decode.term .c.at::after { animation: none; }
  html.hyperspace-return::after { display: none; }
}
