/* ============================================================
   shared/shell.css — the shell every page wears
   ------------------------------------------------------------
   Deliberately tiny. This file owns exactly three things:
     1. the transition grammar (console monitor  <->  world stage)
     2. the return key object (「夜」)
     3. reduced-motion defaults for both
   Everything else belongs to the console (console/) or to a
   world (worlds/<name>/). See docs/04-world-contract.md.
   ============================================================ */

/* ---------- baseline --------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }

/* ---------- 1. transition grammar -------------------------- */
/* Opt every page into cross-document view transitions.
   Browsers without support fall through to a hard cut; worlds
   still get their onEnter/onLeave hooks from shell.js. */
@view-transition { navigation: auto; }

/* The shared element. The console's monitor and a world's stage
   carry the same name, so navigating between them morphs one
   rectangle into the other: the screen grows to fill the viewport
   on the way in, and shrinks back into the device on the way out. */
.yo-stage { view-transition-name: monitor; }

:root {
  --yo-dur: 420ms;
  --yo-ease: cubic-bezier(0.22, 1, 0.36, 1);
}

::view-transition-group(monitor) {
  animation-duration: var(--yo-dur);
  animation-timing-function: var(--yo-ease);
  z-index: 2;
}
::view-transition-group(root) {
  animation-duration: var(--yo-dur);
  animation-timing-function: var(--yo-ease);
}

/* Both snapshots fill the morphing box and crop (the monitor is
   16:9, a phone viewport is not) so the move reads as a zoom, not
   a letterboxed fade. */
::view-transition-old(monitor),
::view-transition-new(monitor) {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  animation-duration: var(--yo-dur);
  animation-timing-function: var(--yo-ease);
}

/* Entering a world: the dark monitor stays solid while the box
   grows; the world's first paint comes up underneath it late.
   Worlds may override any of this in world.css via
   html:active-view-transition-type(to-<slug>) — that is where
   "the destination decides the transition" lives. */
html:active-view-transition-type(from-console)::view-transition-old(monitor) {
  animation-name: yo-hold-then-fade;
}
html:active-view-transition-type(from-console)::view-transition-new(monitor) {
  animation-name: yo-late-fade-in;
}
/* Leaving a world: the closed stage shrinks into the device; the
   console underneath is already there. */
html:active-view-transition-type(to-console)::view-transition-old(monitor) {
  animation-name: yo-hold-then-fade;
}
html:active-view-transition-type(to-console)::view-transition-new(monitor) {
  animation-name: yo-late-fade-in;
}

@keyframes yo-hold-then-fade {
  0%   { opacity: 1; }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes yo-late-fade-in {
  0%   { opacity: 0; }
  55%  { opacity: 0; }
  100% { opacity: 1; }
}

/* ---------- 2. the return key ------------------------------ */
/* One shape, five materials. Every world renders the same crescent-
   with-return-arrow inline SVG in its own material (neon / bevel /
   HUD bracket / glass / ice). The shell only guarantees: it exists,
   it is fixed, it is reachable by keyboard, it has a 44px hit area,
   and the mark is the waning-moon glyph from the site's masthead —
   the shape a visitor learned to recognise on the console — with a
   left-pointing chevron nested in its concave side. Path geometry
   is frozen: the same SVG is baked into every world by contract, so
   nothing here scales or repaints it beyond size + colour. */
.yo-return {
  position: fixed;
  top: 16px;
  left: 16px;
  z-index: 1000;
  display: grid;
  place-items: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  margin: 0;
  border: 0;
  background: transparent;
  color: inherit;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.yo-return svg { display: block; width: 26px; height: 24px; }
.yo-return:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }

/* ---------- 3. reduced motion ------------------------------ */
/* The morph becomes an instant swap. Worlds must also provide a
   still version of their own entrance (shell.js exposes
   yoru.reduceMotion for that). */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}
