/* quotable.to — the hub. Scaffold only (Task 1): tokens shared with the
   card apps (stoke/becoming/proverb) plus a full-bleed stage host for the
   vendored pools engine's canvas. World/card/theme styling is later tasks. */

:root {
  --ground: #241a33;
  --ground-2: #141019;
  --ink: #ede8f2;
  --ink-soft: #9a8fb0;
  --accent: #b98cf0;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

* {
  box-sizing: border-box;
  margin: 0;
}

html,
body {
  height: 100%;
}

body {
  background: radial-gradient(130% 100% at 50% 8%, var(--ground) 0%, var(--ground-2) 62%);
  color: var(--ink);
  font-family: var(--sans);
  overflow: hidden;
}

.pool-glory {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The basin is the background: mountPool mounts the pool canvas here, filling
   the viewport behind everything. */
#basin {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  overflow: hidden;
}

/* The stage floats above the basin and holds the card. It passes pointer
   events through to nothing of its own — the drag is read on the window. */
.stage {
  position: relative;
  z-index: 1;
  height: 100%;
  width: 100%;
}

.stage canvas {
  display: block;
}

/* Law 1: turn.ts drives --turn-rot/--turn-x/--turn-shadow directly, once per
   animation frame — no CSS transition on transform, so the page turn is paced
   entirely by turn.ts and never by the browser. The card is the focused pack's
   title/blurb, resting above the water near the lower third where the eye
   settles. It is not a control surface: pointer events pass through to the
   stage so a drag anywhere turns the focus. */
.card {
  position: absolute;
  left: 50%;
  bottom: 18%;
  width: min(78vw, 30rem);
  margin-left: calc(min(78vw, 30rem) / -2);
  padding: 1.4rem 1.6rem;
  text-align: center;
  pointer-events: none;
  transform: perspective(900px) rotateY(var(--turn-rot, 0deg)) translateX(var(--turn-x, 0px));
  transform-origin: 50% 50%;
  filter: drop-shadow(var(--turn-shadow, none));
  /* tilt.ts writes --tilt-x/--tilt-shadow on the title; the card holds the
     turn transform, the title holds the sway, so the two never fight. */
}

/* Law 3: the words are material. tilt.ts writes --tilt-x/--tilt-y/--tilt-track
   on this element; the shadow offset shifts with device motion and the letters
   breathe via letter-spacing. Defaults match tilt.ts's own static fallback, so
   a desktop with no orientation sensor still reads as deliberately set, not
   broken. */
.card-title {
  font-size: clamp(1.5rem, 5vw, 2.2rem);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: calc(0.01em + var(--tilt-track, 0.01em));
  text-shadow: calc(var(--tilt-x, 0.6px)) calc(var(--tilt-y, 0.9px)) 6px rgba(16, 20, 31, 0.5);
}

.card-blurb {
  margin-top: 0.6rem;
  font-size: clamp(0.95rem, 2.6vw, 1.1rem);
  line-height: 1.5;
  color: var(--ink-soft);
}

/* Law 4: the blurb arrives phrase by phrase at reading pace. unveil.ts renders
   each phrase as a `.phrase` span and lights it a beat after the last. */
.phrase {
  display: inline-block;
  opacity: 0;
  transform: translateY(2px);
  transition:
    opacity 320ms ease-out,
    transform 320ms ease-out;
}

.phrase.lit {
  opacity: 1;
  transform: translateY(0);
}

/* Law 6: reduced motion keeps the words but drops the movement — unveil.ts
   lights every phrase at once, and nothing here animates into place. */
@media (prefers-reduced-motion: reduce) {
  .phrase {
    transition: none;
  }
}

/* Law 6: with no packs loaded the card simply has no text — it collapses to
   nothing rather than showing an empty frame or an error. */
.card:empty,
.card-title:empty {
  display: none;
}
