/* ═══════════════════════════════════════════════
   EyeScore — first-run introduction

   Shown once, to someone who has never opened the tool. The scene itself is
   drawn on a canvas by splash.js; this file is the frame around it — the
   copy, the button, and how the two share the screen at each size.

   Everything is namespaced .sp-* and nothing here touches the dial. A
   returning visitor never has any of it in the DOM: the markup is built by
   the script only when it is going to be shown.
   ═══════════════════════════════════════════════ */

/* The page underneath must not scroll behind a full-screen cover, and on iOS
   a scrollable body lets the cover rubber-band away from the edges. The
   height is pinned as well as the overflow: the dial page is taller than a
   small phone's screen, and overflow alone still left that height there to
   be scrolled on some mobile browsers. */
html.splash-on,
html.splash-on body { height: 100%; overflow: hidden; }
/* The page fades in only once its scripts have run (base.css), and the cover
   is part of the page, so it used to wait in the dark with everything else
   and then appear already finished — which was the abruptness. The cover is
   opaque, so nothing behind it needs hiding: while it is up, the page is
   simply shown, and the cover's own arrival is what is seen from the start. */
html.splash-on body { opacity: 1; animation: none; transition: none; }

.sp {
  --sp-mono: 'IBM Plex Mono', ui-monospace, monospace;
  position: fixed; inset: 0; z-index: 1000;
  /* The page's own ground, so the hand-over is a dissolve between two
     pictures on the same paper rather than a change of backdrop. */
  background: #050914;
  color: #eaf4ff;
  overflow: hidden;
  isolation: isolate;
  /* A drag on a phone would otherwise select the title. Scrolling is already
     stopped by the overflow lock above, so touch-action is left permissive:
     `none` would also take pinch-zoom away from someone who needs it to read
     the one paragraph on this screen. */
  -webkit-user-select: none; user-select: none;
  touch-action: manipulation;
}

.sp-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
}

/* Sits between the scene and the words. The lowest orbit and the foot of the
   corona pass behind the copy on a short screen, and thin bright lines behind
   body text cost legibility; this lets the scene run on underneath without
   ever competing with a sentence. */
.sp-shade {
  position: absolute; left: 0; right: 0; bottom: 0;
  /* Begins just above the words, wherever the layout has put them. */
  top: var(--sp-shade-top, 42%);
  pointer-events: none;
  background: linear-gradient(to bottom,
    rgba(5,9,20,0) 0,
    rgba(5,9,20,0.72) 5.5rem,
    rgba(5,9,20,0.86) 100%);
}

/* Measures the small viewport for splash.js — see layout() there. */
.sp-svh {
  position: absolute; top: 0; left: 0; width: 0;
  height: 100vh; height: 100svh;
  visibility: hidden; pointer-events: none;
}

/* ── Copy ────────────────────────────────────── */
/* Placed by splash.js, which sets --sp-copy-top once it has sized the scene:
   the words sit a fixed gap under the sphere rather than against the bottom
   of the screen. The fallbacks are the old bottom-anchored position, for the
   instant before the script has measured anything. */
.sp-copy {
  position: absolute; left: 0; right: 0;
  top: var(--sp-copy-top, auto); bottom: var(--sp-copy-bottom, 0);
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  padding: 0 max(1.5rem, env(safe-area-inset-left))
           env(safe-area-inset-bottom)
           max(1.5rem, env(safe-area-inset-right));
}

.sp-title {
  font-family: 'pixer', Georgia, serif;
  font-weight: normal;
  font-size: clamp(3rem, 12.5vw, 5.6rem);
  line-height: 1;
  /* Letter-spacing trails the last glyph; the padding puts the word back on
     the centre line. */
  letter-spacing: .07em; padding-left: .07em;
  color: #eef6ff;
  text-shadow: 0 0 34px rgba(95,198,234,0.28), 0 0 2px rgba(255,255,255,0.25);
}

.sp-lede {
  max-width: 31rem;
  margin-top: 1.15rem;
  font-size: clamp(.95rem, 4.2vw, 1.16rem); line-height: 1.55;
  color: rgba(255,255,255,0.84);
  text-wrap: balance;
}
.sp-lede span { white-space: nowrap; }

/* The one control on the page. Light on dark, so there is no question what
   the next step is; everything else here is quieter than it on purpose. */
.sp-enter {
  margin-top: 2rem;
  display: inline-flex; align-items: center; gap: .7rem;
  min-height: 52px;
  padding: 0 1.45rem 0 1.75rem;
  font: inherit; font-size: .98rem; font-weight: 600; letter-spacing: .01em;
  color: #06101f;
  background: linear-gradient(180deg, #ffffff, #dcebf8);
  border: 0; border-radius: 999px;
  cursor: pointer;
  box-shadow:
    0 0 0 1px rgba(255,255,255,0.5) inset,
    0 10px 34px -8px rgba(95,198,234,0.55),
    0 0 0 0 rgba(95,198,234,0);
  transition: transform .22s cubic-bezier(.22,1,.36,1),
              box-shadow .28s ease, background .2s ease;
  -webkit-tap-highlight-color: transparent;
}
.sp-enter svg { display: block; transition: transform .28s cubic-bezier(.22,1,.36,1); }
@media (hover: hover) {
  .sp-enter:hover {
    transform: translateY(-2px);
    box-shadow:
      0 0 0 1px rgba(255,255,255,0.6) inset,
      0 16px 44px -8px rgba(95,198,234,0.75),
      0 0 0 6px rgba(95,198,234,0.12);
  }
  .sp-enter:hover svg { transform: translateX(4px); }
}
.sp-enter:active { transform: translateY(0) scale(.975); }
.sp-enter:focus-visible { outline: 2px solid #9fdcf2; outline-offset: 4px; }
/* Pressed before the app behind it had finished loading: it has been heard,
   and will go as soon as there is a dial to go to. */
.sp-enter[aria-busy="true"] { opacity: .72; cursor: progress; }


/* ── Arrival ─────────────────────────────────────
   The scene builds out of the dark first (splash.js, about three and a half
   seconds). The name surfaces from a blur while the last bodies are lighting,
   the three short sentences follow one at a time, and the button comes last,
   so the eye ends where the hand should go. Hidden, not merely transparent,
   until it arrives: an invisible button is still a button. */
@keyframes sp-surface {
  from { opacity: 0; filter: blur(12px); transform: scale(1.04); }
  60%  { filter: blur(1px); }
}
@keyframes sp-rise {
  from { opacity: 0; filter: blur(4px); transform: translateY(10px); }
}
@keyframes sp-arrive {
  from { opacity: 0; transform: translateY(12px); visibility: hidden; }
}
.sp-title { animation: sp-surface 1.6s cubic-bezier(.25,.6,.3,1) 2.6s both; }
/* Inline-block so each sentence can move; the spaces between them are text,
   so the line still wraps only between sentences. */
.sp-lede span { display: inline-block; animation: sp-rise 1.1s cubic-bezier(.22,1,.36,1) both; }
.sp-lede span:nth-of-type(1) { animation-delay: 3.15s; }
.sp-lede span:nth-of-type(2) { animation-delay: 3.4s; }
.sp-lede span:nth-of-type(3) { animation-delay: 3.65s; }
.sp-enter { animation: sp-arrive 1s cubic-bezier(.22,1,.36,1) 3.95s both; }

/* ── Departure ───────────────────────────────────
   The words leave at once and the scene is left alone on the screen to do the
   hand-over. Opacity on the wrapper, so it composes with the arrival
   animation on the children instead of fighting it. */
.sp-copy, .sp-shade {
  transition: opacity .34s ease, transform .5s cubic-bezier(.4,0,.2,1);
}
.sp.is-leaving .sp-copy  { opacity: 0; transform: translateY(14px); pointer-events: none; }
.sp.is-leaving .sp-shade { opacity: 0; }

/* The plain exit: reduced motion, or no dial on screen to resolve into. */
.sp.is-fading { opacity: 0; transition: opacity .45s ease; }

/* ── Sideways on a phone ─────────────────────────
   There is no height to stack a scene over a column of text, so they sit side
   by side: words left, sphere right. splash.js reads the same query to decide
   where the sphere goes. */
@media (orientation: landscape) and (max-height: 520px) {
  .sp-copy {
    right: auto; top: 0; bottom: 0; width: 52%;
    justify-content: center; align-items: flex-start; text-align: left;
    padding: 0 0 0 max(2rem, calc(env(safe-area-inset-left) + 1rem));
  }
  .sp-title { font-size: clamp(2.2rem, 13vh, 3.2rem); }
  .sp-lede  { font-size: .88rem; margin-top: .8rem; max-width: 24rem; text-wrap: pretty; }
  .sp-enter { margin-top: 1.15rem; min-height: 46px; font-size: .92rem; }
  .sp-shade {
    inset: 0 auto 0 0; width: 62%;
    background: linear-gradient(to right,
      #050914 20%, rgba(5,9,20,0.8) 62%, rgba(5,9,20,0) 100%);
  }
}

/* A phone held upright: the same column, drawn a little closer together, so
   the group is compact and there is height to spare around it. */
@media (max-width: 560px) {
  .sp-lede  { margin-top: .9rem; }
  .sp-enter { margin-top: 1.5rem; min-height: 50px; }
}

@media (prefers-reduced-motion: reduce) {
  .sp-title, .sp-lede span, .sp-enter { animation: none; }
  .sp-copy, .sp-shade, .sp-enter, .sp-enter svg { transition: none; }
  .sp.is-fading { transition: opacity .2s linear; }
}
