// scenes_a.jsx — Scene 1 (Title/Pinwheel) + Scene 2 (80/20 fact)
// Monochrome: ink strokes/fills on warm paper.

const W = 1920, H = 1080;
const CX = W / 2, CY = H / 2;

// ─── Scene 1 ───────────────────────────────────────────────────────────────
// Five circles drift in from space around a center, forming a gentle pinwheel.
// Then text lands: "a calmer home" / "one task at a time."
function SceneTitle({ start, end }) {
  return (
    <Sprite start={start} end={end}>
      <TitleInner sceneStart={start} sceneEnd={end} />
    </Sprite>
  );
}

function TitleInner() {
  const { localTime, duration } = useSprite();
  const fade = useSpriteFade({ inDur: 0.4, outDur: 0.6 });

  // 5 petals around a center. Each petal is a circle traveling on a slight spiral.
  const petals = [0, 1, 2, 3, 4];
  const baseR = 360; // final orbit radius
  const dotR = 110;

  return (
    <g style={{ opacity: fade }}>
      {/* background rule */}
      <Eyebrow x={CX} y={120} align="center" text="Calmer Home  ·  An animated field guide" size={18} color={PAL.sub} />

      <svg width={W} height={H} style={{ position: 'absolute', inset: 0 }}>
        <g transform={`translate(${CX} ${CY + 40})`}>
          {petals.map((i) => {
            const angleFinal = -Math.PI / 2 + (i / 5) * Math.PI * 2;
            const tArrive = 0.3 + i * 0.18;
            const tArriveDur = 1.0;
            const p = Easing.easeOutCubic(clamp((localTime - tArrive) / tArriveDur, 0, 1));
            const r = baseR * p;
            const angle = angleFinal + (1 - p) * 1.2;
            const x = Math.cos(angle) * r;
            const y = Math.sin(angle) * r;

            // Gentle breathing after arrival
            const breath = p >= 1
              ? Math.sin((localTime - (tArrive + tArriveDur)) * 0.9 + i) * 6
              : 0;

            // Rotation of whole figure for sustained motion
            const rot = (localTime * 4) % 360;

            const opacity = p;
            return (
              <g key={i} transform={`rotate(${rot * 0.02 * (i - 2)})`}>
                <circle
                  cx={x} cy={y + breath}
                  r={dotR * (0.6 + 0.4 * p)}
                  fill="none"
                  stroke={PAL.ink}
                  strokeWidth={1.5}
                  opacity={opacity}
                />
                {/* inner dot when arrived */}
                <circle
                  cx={x} cy={y + breath}
                  r={6}
                  fill={PAL.ink}
                  opacity={Math.max(0, p - 0.6) * 2.5}
                />
              </g>
            );
          })}

          {/* central seed dot */}
          <circle cx={0} cy={0} r={6 + (localTime < 0.5 ? 0 : Math.sin(localTime * 2) * 2)} fill={PAL.ink}
            opacity={Easing.easeOutCubic(clamp(localTime / 0.4, 0, 1))} />
        </g>
      </svg>

      {/* Title text layered on top, arrives last */}
      <Sprite start={0} end={Infinity}>
        <TitleType localTime={localTime} />
      </Sprite>
    </g>
  );
}

function TitleType({ localTime }) {
  const showMain = localTime > 1.6;
  const showSub = localTime > 2.6;
  const showKanji = localTime > 0.2;

  return (
    <>
      {/* Small kanji mark top-left, sets the tone */}
      <div style={{
        position: 'absolute', left: 140, top: 140,
        opacity: Easing.easeOutCubic(clamp((localTime - 0.2) / 0.8, 0, 1)),
        fontFamily: FONT.kanji, fontSize: 56, color: PAL.ink,
        letterSpacing: '0.08em',
      }}>
        整理 · 整頓 · 清掃 · 清潔 · 躾
      </div>
      <div style={{
        position: 'absolute', left: 140, top: 214,
        opacity: Easing.easeOutCubic(clamp((localTime - 0.5) / 0.8, 0, 1)),
        fontFamily: FONT.sans, fontSize: 13, color: PAL.sub,
        letterSpacing: '0.3em', textTransform: 'uppercase',
      }}>
        the 5 S  ·  a japanese rhythm for home
      </div>

      {/* Main title */}
      {showMain && (
        <Sprite start={0} end={Infinity}>
          <div style={{ position: 'absolute', left: 0, top: 720, width: W, textAlign: 'center' }}>
            <StaggerWordsAt text="a calmer home." size={168} italic={true} localTimeOffset={1.6} localTime={localTime} />
          </div>
        </Sprite>
      )}
      {showSub && (
        <div style={{
          position: 'absolute', left: 0, top: 900, width: W, textAlign: 'center',
          fontFamily: FONT.serif, fontStyle: 'italic',
          fontSize: 40, color: PAL.sub,
          opacity: Easing.easeOutCubic(clamp((localTime - 2.6) / 0.8, 0, 1)),
          letterSpacing: '-0.01em',
        }}>
          one room · one task · one breath
        </div>
      )}
    </>
  );
}

// Inline version of StaggerWords that takes an offset so we can nest inside a larger sprite.
function StaggerWordsAt({ text, size, italic, localTimeOffset = 0, localTime, color = PAL.ink, weight = 400 }) {
  const words = text.split(/(\s+)/);
  return (
    <div style={{
      fontFamily: FONT.serif, fontStyle: italic ? 'italic' : 'normal',
      fontWeight: weight, fontSize: size, color,
      letterSpacing: '-0.025em', lineHeight: 1,
    }}>
      {words.map((w, i) => {
        if (/^\s+$/.test(w)) return <span key={i}>{w}</span>;
        const wStart = localTimeOffset + i * 0.09;
        const t = Easing.easeOutBack(clamp((localTime - wStart) / 0.55, 0, 1));
        const op = clamp((localTime - wStart) / 0.55, 0, 1);
        return (
          <span key={i} style={{
            display: 'inline-block',
            transform: `translateY(${(1 - t) * 40}px)`,
            opacity: op,
            filter: `blur(${Math.max(0, 6 * (1 - t))}px)`,
          }}>{w}</span>
        );
      })}
    </div>
  );
}

// ─── Scene 2 ───────────────────────────────────────────────────────────────
// 80/20 fact: "You use 20% of your stuff 80% of the time."
// Grid of 100 dots. 20 stay filled/ink. 80 become ghost/empty.

function SceneEightyTwenty({ start, end }) {
  return (
    <Sprite start={start} end={end}>
      <EightyTwentyInner />
    </Sprite>
  );
}

function EightyTwentyInner() {
  const { localTime, duration } = useSprite();
  const fade = useSpriteFade({ inDur: 0.5, outDur: 0.6 });

  // 10x10 grid of 100 dots.
  const cols = 10, rows = 10;
  const cell = 60;
  const gridW = cols * cell;
  const gridH = rows * cell;
  const gx = CX - gridW / 2;
  const gy = 360;

  // Choose 20 "used" indices — pseudo-random but stable.
  const usedSet = React.useMemo(() => {
    const set = new Set();
    let s = 7;
    while (set.size < 20) {
      s = (s * 9301 + 49297) % 233280;
      set.add(s % 100);
    }
    return set;
  }, []);

  return (
    <div style={{ opacity: fade }}>
      <Eyebrow x={CX} y={170} align="center" text="Fun fact  ·  №  0 1" size={18} />

      {/* Fact headline */}
      <div style={{
        position: 'absolute', left: 0, top: 220, width: W, textAlign: 'center',
        fontFamily: FONT.serif, fontSize: 78, color: PAL.ink,
        letterSpacing: '-0.02em', lineHeight: 1.05,
        opacity: Easing.easeOutCubic(clamp((localTime - 0.2) / 0.7, 0, 1)),
        transform: `translateY(${(1 - Easing.easeOutCubic(clamp((localTime - 0.2) / 0.7, 0, 1))) * 24}px)`,
      }}>
        You use <span style={{ fontStyle: 'italic' }}>twenty percent</span> of your stuff
      </div>

      {/* Grid of dots */}
      <svg width={W} height={H} style={{ position: 'absolute', inset: 0 }}>
        {Array.from({ length: 100 }).map((_, i) => {
          const col = i % cols, row = Math.floor(i / cols);
          const cx = gx + col * cell + cell / 2;
          const cy = gy + row * cell + cell / 2;
          const appear = 0.4 + (row * 0.04) + (col * 0.02);
          const a = Easing.easeOutBack(clamp((localTime - appear) / 0.5, 0, 1));
          const isUsed = usedSet.has(i);

          // Sort moment: after 2.8s, the "not used" fade to empty rings.
          const sortT = clamp((localTime - 2.6) / 0.8, 0, 1);

          let r, fill, strokeOp = 1, fillOp = 1;
          if (isUsed) {
            r = 14 + 2 * sortT;  // used dots grow slightly
            fill = PAL.ink;
            fillOp = 1;
          } else {
            r = 12 - 4 * sortT;
            fill = PAL.ink;
            fillOp = 1 - sortT;
          }

          return (
            <g key={i} transform={`translate(${cx} ${cy}) scale(${a})`} opacity={a}>
              <circle r={r} fill={fill} opacity={fillOp} />
              {!isUsed && (
                <circle r={r + 2 * sortT} fill="none" stroke={PAL.ghost} strokeWidth={1} opacity={sortT * 0.7} />
              )}
            </g>
          );
        })}
      </svg>

      {/* Labels that appear as sort resolves */}
      <div style={{
        position: 'absolute', left: gx - 260, top: gy + 40,
        fontFamily: FONT.serif, fontStyle: 'italic',
        fontSize: 42, color: PAL.ink,
        opacity: Easing.easeOutCubic(clamp((localTime - 3.2) / 0.6, 0, 1)),
        transform: `translateX(${(1 - Easing.easeOutCubic(clamp((localTime - 3.2) / 0.6, 0, 1))) * -20}px)`,
        lineHeight: 1,
      }}>
        <div style={{ fontFamily: FONT.mono, fontStyle: 'normal', fontSize: 64, color: PAL.ink, letterSpacing: '-0.02em' }}>20</div>
        <div style={{ fontSize: 28, color: PAL.sub, marginTop: 6 }}>kept close</div>
      </div>

      <div style={{
        position: 'absolute', left: gx + gridW + 60, top: gy + 40,
        fontFamily: FONT.serif, fontStyle: 'italic',
        fontSize: 42, color: PAL.ink,
        opacity: Easing.easeOutCubic(clamp((localTime - 3.4) / 0.6, 0, 1)),
        lineHeight: 1,
      }}>
        <div style={{ fontFamily: FONT.mono, fontStyle: 'normal', fontSize: 64, color: PAL.sub, letterSpacing: '-0.02em' }}>80</div>
        <div style={{ fontSize: 28, color: PAL.mute, marginTop: 6 }}>rarely touched</div>
      </div>

      {/* Closing line */}
      <div style={{
        position: 'absolute', left: 0, top: gy + gridH + 70, width: W, textAlign: 'center',
        fontFamily: FONT.serif, fontStyle: 'italic', fontSize: 44, color: PAL.sub,
        letterSpacing: '-0.01em',
        opacity: Easing.easeOutCubic(clamp((localTime - 4.0) / 0.8, 0, 1)),
      }}>
        &mdash; eighty percent of the time.
      </div>
    </div>
  );
}

Object.assign(window, { SceneTitle, SceneEightyTwenty, W, H, CX, CY });
