:root {
  --bg: #e9e9e9;
  --ink: #111114;
  --dim: #b9b9bd;
  --nervous: #2d4ada;
  --circulatory: #e23a3a;
  --skeletal: #2e8b57;   /* green: colours the "active" keyword when on */
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.hero {
  min-height: 100vh;
  max-width: 1400px;
  margin: 0 auto;
  padding: 6vh 6vw;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(3rem, 8vw, 9rem);
  /* the zoomed figure overflows on purpose: clip it instead of scrolling */
  overflow: hidden;
}

/* --- pixel figure -------------------------------------------------------- */

.figure {
  position: relative;
  flex: 0 1 clamp(260px, 30vw, 440px);
  aspect-ratio: 2 / 3;
  /* keyword clicks zoom the figure (main.js sets an inline scale) so the
     bottom third of the canvas lands below the viewport's bottom edge */
  transform-origin: top center;
  transition: transform 0.7s ease;
}

/* idle breathing: the wrapper holds every canvas, so the stack stretches as
   one rigid piece and the layers can't drift apart. It sits absolute/inset-0
   inside the relative .figure, filling exactly the same box — the canvases
   below resolve their own inset: 0 against it, so at rest nothing moves.
   The stretch is anchored at the feet and the zoom lives on .figure, one
   level up, so the two transforms compose instead of fighting. */
.figure-idle {
  position: absolute;
  inset: 0;
  transform-origin: bottom center;   /* feet stay planted; growth goes upward */
  animation: idle-breathe 3.6s ease-in-out infinite;
  will-change: transform;
}

/* barely there on purpose: 0.8% over 3.6s reads as breath, not as a bounce */
@keyframes idle-breathe {
  0%,
  100% {
    transform: scaleY(1);
  }
  50% {
    transform: scaleY(1.008);
  }
}

@media (prefers-reduced-motion: reduce) {
  .figure {
    transition: none;
  }
  /* no idle movement at all — the figure just stands there */
  .figure-idle {
    animation: none;
  }
}

.pixel-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  opacity: 0;
  /* apply animation: layers appear slightly enlarged/offset and settle in */
  transform: scale(1.03) translateY(4px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}

.pixel-layer.always-on,
.pixel-layer.active {
  opacity: 1;
  transform: none;
}

/* staggered assembly: when several layers switch on together, the bottom
   layer animates first and the top one last (nervous needs no rule: 0ms).
   The delay lives on .active so switching a layer off starts immediately. */
.pixel-layer.active[data-layer="circulatory"] {
  transition-delay: 60ms;
}

.pixel-layer.active[data-layer="skeletal"] {
  transition-delay: 120ms;
}

/* --- prose ---------------------------------------------------------------- */

.prose {
  flex: 0 1 620px;
  font-size: clamp(1.15rem, 1.9vw, 1.7rem);
  line-height: 1.55;
  font-weight: 500;
  letter-spacing: -0.01em;
  /* keep the text readable above the zoomed figure */
  position: relative;
  z-index: 1;
}

.prose p {
  margin: 0 0 1.4em;
}

.greeting {
  font-size: 1.05em;
}

.dim {
  color: var(--dim);
}

/* keyword buttons inside the prose: an in-order unlock, then ordered
   toggling (passions > active > thoughts — layers come back off in the same
   prose order they went on). A locked word reads as plain prose (no cue);
   the single "current" word is dimmed and underlined to invite the next
   click; an unlocked word shows its layer's colour while the layer is on.
   main.js decides per move which words may act. */
.keyword {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;          /* locked: blends into the surrounding prose */
  cursor: default;
  transition: color 0.3s ease, border-color 0.3s ease;
}

/* the one word to click now: dimmed + underlined */
.keyword.is-current {
  color: var(--dim);
  border-bottom-color: var(--dim);
  cursor: pointer;
}

.keyword.is-current:hover {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

/* any word that can be clicked right now carries an underline in its own
   colour: dim for the next unlock, layer colour while on, ink when it can
   come back on */
.keyword:not(:disabled) {
  cursor: pointer;
  border-bottom-color: currentColor;
}

/* layer on: reveal the layer's colour */
.keyword.active[data-layer="nervous"] {
  color: var(--nervous);
}

.keyword.active[data-layer="circulatory"] {
  color: var(--circulatory);
}

.keyword.active[data-layer="skeletal"] {
  color: var(--skeletal);
}

/* don't grey out disabled (locked / done) words — keep our own colours */
.keyword:disabled {
  opacity: 1;
}

.hint {
  margin-top: 1.2rem;
  font-size: 0.55em;
  font-weight: 500;
  color: var(--dim);
}

/* --- ambient background ---------------------------------------------------- */

/* the background lives behind everything (figure and prose), pinned to the
   full viewport */
.mirage-stage {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

/* the single background image/video: faint, blurred and desaturated so it
   hangs in the air like a mirage rather than reading as a photo. Hidden
   until the first keyword lights a layer; fades back out when every layer
   is switched off again. */
.bg-media {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  filter: blur(6px) saturate(0.9);
  transform: scale(1.04);
  mix-blend-mode: multiply;
  /* the slow fade is what sells the dream: nothing snaps */
  transition: opacity 2.0s ease, transform 6s ease;
  will-change: opacity, transform;
}

.bg-media.show {
  opacity: 0.75;
  transform: scale(1);
}

@media (prefers-reduced-motion: reduce) {
  .bg-media {
    transition: opacity 0.4s ease;
    transform: none;
  }
  .bg-media.show {
    transform: none;
  }
}

/* --- responsive ------------------------------------------------------------- */

@media (max-width: 860px) {
  .hero {
    flex-direction: column;
    justify-content: flex-start;
    gap: 3rem;
    padding-top: 8vh;
  }

  .figure {
    flex-basis: auto;
    width: min(70vw, 320px);
  }

  /* phones stack the prose right over the background image, so give it a
     panel of the page colour to sit on. Slightly translucent and blurred,
     so the image still shows through as a wash rather than competing with
     the words. */
  .prose {
    /* the column layout turns flex-basis into a *height*, which would leave
       the panel standing 620px tall under the last line — size it to the
       text instead and let the width fill the hero */
    flex: 0 0 auto;
    width: 100%;
    padding: 1.1rem 1.25rem;
    border-radius: 0.6rem;
    background: rgba(233, 233, 233, 0.82);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
  }

  .prose p:last-child {
    margin-bottom: 0;
  }
}
