/* ==========================================================================
   덕상이 · teaser
   A true black canvas and red used only ever as a glow. One figure, awake
   and adrift in the middle of the dark.
   ========================================================================== */

@font-face {
  font-family: "Pretendard";
  src: url("assets/fonts/PretendardStdVariable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --black: #000000;
  --paper: #f5f5f0;
  --muted: #9a9a94;
  --red: #ff2200;

  --body: "Pretendard", "Apple SD Gothic Neo", "Malgun Gothic", system-ui,
    -apple-system, "Segoe UI", sans-serif;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* one place to retime the whole reveal */
  --fade-in: 1300ms;
  --wake-flash: 900ms;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  background: var(--black);
  color: var(--paper);
  font-family: var(--body);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: manipulation;
}

::selection {
  background: var(--red);
  color: #fff;
}

/* ---------- star field ----------------------------------------------------
   Sparse and dim on purpose, so it reads as depth behind the black rather
   than as a night sky of its own. */
#stars {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 3.4s linear;
}
#stars.is-lit {
  opacity: 0.42;
}

/* ---------- stage ---------- */
.stage {
  position: relative;
  z-index: 1;
  min-height: 100svh;
  display: grid;
  place-content: center;
  justify-items: center;
  /* the halo and the rays are wider than a phone; left unclipped, mobile
     browsers zoom out to fit them and he ends up off-centre */
  overflow: hidden;
  padding: max(24px, env(safe-area-inset-top)) 24px
    max(24px, env(safe-area-inset-bottom));
}

/* Two glows, both centred on Deoksangi. The halo is the cool one that gives
   him something to sit in; the ember is the warm one, kept almost invisible so
   it only ever registers as warmth, and it is the thing that flares when he
   opens his eyes. */
.figure {
  position: relative;
  display: grid;
  place-items: center;
}
.halo,
.ember {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  pointer-events: none;
  border-radius: 50%;
  opacity: 0;
}
.halo {
  width: min(1100px, 150vmin);
  aspect-ratio: 1;
  background: radial-gradient(
    circle,
    rgba(245, 245, 240, 0.075) 0%,
    rgba(245, 245, 240, 0.028) 34%,
    transparent 68%
  );
  transition: opacity 3.2s linear;
}
.ember {
  width: min(620px, 88vmin);
  aspect-ratio: 1;
  background: radial-gradient(
    circle,
    rgba(255, 34, 0, 0.15) 0%,
    rgba(255, 34, 0, 0.045) 40%,
    transparent 70%
  );
  filter: blur(14px);
  transition: opacity 2.4s var(--ease);
}
.is-lit .halo {
  opacity: 1;
}
.is-lit .ember {
  opacity: 0.16;
}
/* the beat he wakes on: the ember swells and settles, nothing else moves */
.is-awake .ember {
  animation: emberFlare var(--wake-flash) var(--ease) forwards;
}
@keyframes emberFlare {
  0% {
    opacity: 0.16;
    scale: 1;
  }
  38% {
    opacity: 0.78;
    scale: 1.16;
  }
  100% {
    opacity: 0.3;
    scale: 1.04;
  }
}

/* ---------- the float ----------
   JS moves this around on a slow, never-repeating wander so he is never quite
   still. Everything that bursts out of him lives in here too. */
.float {
  position: relative;
  display: grid;
  place-items: center;
  will-change: transform;
}

/* ---------- the burst ----------
   Three layers behind him, all idle at zero and played from JS on a tap: a
   soft flash, a ring of rays that turns as it fades, and the sparks. They are
   sized off the float, so they scale with him. */
.flash,
.rays,
.sparks {
  position: absolute;
  left: 50%;
  top: 46%;
  translate: -50% -50%;
  pointer-events: none;
}
.flash {
  width: 150%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(255, 244, 236, 0.55) 0%,
    rgba(255, 120, 90, 0.22) 26%,
    rgba(255, 34, 0, 0.08) 46%,
    transparent 66%
  );
  opacity: 0;
}
.rays {
  width: 190%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: repeating-conic-gradient(
    from 4deg,
    rgba(245, 245, 240, 0.34) 0deg 2.2deg,
    transparent 2.2deg 15deg
  );
  /* hollow in the middle so the rays start at his edge, and gone before the
     rim so they read as light rather than as a wheel */
  -webkit-mask: radial-gradient(circle, transparent 17%, #000 27%, transparent 68%);
  mask: radial-gradient(circle, transparent 17%, #000 27%, transparent 68%);
  filter: blur(1.5px);
  opacity: 0;
}
.sparks {
  width: 0;
  height: 0;
  /* one shared glow for every spark: a tight white core, then the red, which
     is the only place red ever shows up on the page */
  filter: drop-shadow(0 0 2px rgba(255, 255, 255, 0.9))
    drop-shadow(0 0 9px rgba(255, 60, 20, 0.9));
}
.spark {
  position: absolute;
  left: 0;
  top: 0;
  background: #fff;
  /* a four-point star */
  clip-path: polygon(
    50% 0,
    62% 38%,
    100% 50%,
    62% 62%,
    50% 100%,
    38% 62%,
    0 50%,
    38% 38%
  );
  opacity: 0;
}
.spark--dot {
  clip-path: none;
  border-radius: 50%;
  background: #ffd9cc;
}

/* ---------- Deoksangi ---------- */
.deok {
  /* it is a button so a keyboard can tap him too; strip everything a button
     brings with it */
  appearance: none;
  display: block;
  margin: 0;
  padding: 0;
  border: 0;
  background-color: transparent;
  color: inherit;
  font: inherit;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;

  position: relative;
  width: clamp(240px, 26vw + 16vh, 460px);
  aspect-ratio: 310 / 306;
  background-image: url("assets/deoksangi-sheet.png");
  background-repeat: no-repeat;
  /* 5 columns x 4 rows */
  background-size: 500% 400%;
  background-position: 0% 0%;
  /* squash and stretch pivot from about where his feet are */
  transform-origin: 50% 88%;

  opacity: 0;
  transform: scale(1.045);
  filter: blur(12px);
  transition: opacity var(--fade-in) linear, transform var(--fade-in) var(--ease),
    filter var(--fade-in) var(--ease), scale 0.4s var(--ease);
}
.is-lit .deok {
  opacity: 1;
  transform: none;
  filter: none;
}
.is-awake .deok {
  cursor: pointer;
}
/* a small lean-in on hover says he can be tapped; `scale` stacks with the
   hop's `transform`, so the two never fight */
@media (hover: hover) {
  .is-awake .deok:hover {
    scale: 1.025;
  }
}
.deok:focus {
  outline: none;
}
.deok:focus-visible {
  outline: 1px solid rgba(245, 245, 240, 0.22);
  outline-offset: 10px;
}

/* ---------- reduced motion ----------
   No fade, no wake, no drifting, no hop. The last frame, lit, and a tap only
   warms the light behind him. */
@media (prefers-reduced-motion: reduce) {
  #stars,
  .halo,
  .ember,
  .deok {
    transition: none !important;
    animation: none !important;
  }
  .is-awake .ember {
    opacity: 0.3;
  }
}
