/* global React */
/* PHASE 2 (Brand Kit V2) — Awards (left/right split) + Bento Grid (Layout B: char + package).
   All taglines client-confirmed per BRIEF V2 §6. Do not auto-soften. */
const { useEffect: _useEffect, useRef: _useRef, useState: _useState, useCallback: _useCallback } = React;

// =====================================================================
// Character placeholder — SVG mascot stand-ins until final renders land
// at assets/char-*.png. The <img> below tries the real asset first; if
// it 404s, we fall back to the inline SVG marker.
// =====================================================================
function CharMark({ id, size = 220 }) {
  const marks = {
    hapimon: { // C.H.O活 — red heart, single smile
      bg: '#FF3F4F', fg: '#fff',
      svg: (
        <g>
          <path d="M100 170 C 40 130, 30 70, 70 45 C 95 32, 100 55, 100 65 C 100 55, 105 32, 130 45 C 170 70, 160 130, 100 170 Z" fill="#FF2030" stroke="#0A0A0A" strokeWidth="3"/>
          <circle cx="80" cy="85" r="6" fill="#0A0A0A"/>
          <circle cx="120" cy="85" r="6" fill="#0A0A0A"/>
          <path d="M82 110 Q 100 128 118 110" stroke="#0A0A0A" strokeWidth="4" fill="none" strokeLinecap="round"/>
          <circle cx="68" cy="100" r="5" fill="#FFB0B0" opacity="0.7"/>
          <circle cx="132" cy="100" r="5" fill="#FFB0B0" opacity="0.7"/>
        </g>
      )
    },
    'hapimon-pkg': { // ハピモン② holding package
      bg: '#FF3F4F', fg: '#fff',
      svg: (
        <g>
          <path d="M100 175 C 40 140, 30 75, 70 50 C 95 38, 100 60, 100 70 C 100 60, 105 38, 130 50 C 170 75, 160 140, 100 175 Z" fill="#FF2030" stroke="#0A0A0A" strokeWidth="3"/>
          <rect x="68" y="105" width="64" height="48" rx="4" fill="#F5F0EB" stroke="#0A0A0A" strokeWidth="2.5"/>
          <text x="100" y="128" textAnchor="middle" fontFamily="Cabin, sans-serif" fontWeight="700" fontSize="14" fill="#CC0000">C.H.O</text>
          <text x="100" y="144" textAnchor="middle" fontFamily="Cabin, sans-serif" fontSize="9" fill="#0A0A0A">MONSTER</text>
          <circle cx="80" cy="85" r="5" fill="#0A0A0A"/>
          <circle cx="120" cy="85" r="5" fill="#0A0A0A"/>
          <path d="M86 95 Q 100 105 114 95" stroke="#0A0A0A" strokeWidth="3" fill="none" strokeLinecap="round"/>
        </g>
      )
    },
    oimon: { // A.S.E活 — pale blue droplet (温浴)
      bg: '#7FC9E8', fg: '#fff',
      svg: (
        <g>
          <ellipse cx="100" cy="120" rx="62" ry="58" fill="#9DD8F0" stroke="#0A0A0A" strokeWidth="3"/>
          <path d="M100 30 Q 70 70 70 100 Q 70 130 100 130 Q 130 130 130 100 Q 130 70 100 30 Z" fill="#9DD8F0" stroke="#0A0A0A" strokeWidth="3"/>
          <circle cx="82" cy="118" r="6" fill="#0A0A0A"/>
          <circle cx="118" cy="118" r="6" fill="#0A0A0A"/>
          <circle cx="84" cy="116" r="2" fill="#fff"/>
          <circle cx="120" cy="116" r="2" fill="#fff"/>
          <path d="M85 140 Q 100 152 115 140" stroke="#0A0A0A" strokeWidth="3.5" fill="none" strokeLinecap="round"/>
          <path d="M50 60 q 8 -6 16 0" stroke="#fff" strokeWidth="3" fill="none" opacity="0.7"/>
          <path d="M134 70 q 8 -6 16 0" stroke="#fff" strokeWidth="3" fill="none" opacity="0.7"/>
        </g>
      )
    },
    'oimon-throne': { // オイモン王座Ver
      bg: '#FFE08A', fg: '#0A0A0A',
      svg: (
        <g>
          {/* throne */}
          <rect x="40" y="120" width="120" height="60" fill="#C8A346" stroke="#0A0A0A" strokeWidth="3"/>
          <rect x="36" y="80" width="14" height="100" fill="#C8A346" stroke="#0A0A0A" strokeWidth="3"/>
          <rect x="150" y="80" width="14" height="100" fill="#C8A346" stroke="#0A0A0A" strokeWidth="3"/>
          {/* oimon body */}
          <ellipse cx="100" cy="105" rx="48" ry="46" fill="#9DD8F0" stroke="#0A0A0A" strokeWidth="3"/>
          <path d="M100 30 Q 78 60 78 88 Q 78 110 100 110 Q 122 110 122 88 Q 122 60 100 30 Z" fill="#9DD8F0" stroke="#0A0A0A" strokeWidth="3"/>
          {/* crown */}
          <path d="M68 32 L 78 18 L 88 30 L 100 12 L 112 30 L 122 18 L 132 32 L 132 42 L 68 42 Z" fill="#F2B845" stroke="#0A0A0A" strokeWidth="3"/>
          <circle cx="100" cy="22" r="3" fill="#CC0000"/>
          {/* face */}
          <circle cx="86" cy="98" r="5" fill="#0A0A0A"/>
          <circle cx="114" cy="98" r="5" fill="#0A0A0A"/>
          <path d="M88 118 Q 100 128 112 118" stroke="#0A0A0A" strokeWidth="3" fill="none" strokeLinecap="round"/>
        </g>
      )
    },
    seapaz: { // M.I.N活 — シーパーズ眠り (white/violet)
      bg: '#A78BFA', fg: '#fff',
      svg: (
        <g>
          <ellipse cx="100" cy="115" rx="64" ry="56" fill="#F0EBFF" stroke="#0A0A0A" strokeWidth="3"/>
          {/* ears */}
          <path d="M50 75 L 35 40 L 70 65 Z" fill="#F0EBFF" stroke="#0A0A0A" strokeWidth="3"/>
          <path d="M150 75 L 165 40 L 130 65 Z" fill="#F0EBFF" stroke="#0A0A0A" strokeWidth="3"/>
          {/* sleeping eyes */}
          <path d="M72 108 Q 82 102 92 108" stroke="#0A0A0A" strokeWidth="3.5" fill="none" strokeLinecap="round"/>
          <path d="M108 108 Q 118 102 128 108" stroke="#0A0A0A" strokeWidth="3.5" fill="none" strokeLinecap="round"/>
          {/* mouth small */}
          <ellipse cx="100" cy="130" rx="5" ry="4" fill="#0A0A0A"/>
          {/* Z's */}
          <text x="148" y="48" fontFamily="Cabin, sans-serif" fontWeight="700" fontSize="22" fill="#7C3AED">Z</text>
          <text x="164" y="32" fontFamily="Cabin, sans-serif" fontWeight="700" fontSize="14" fill="#7C3AED">z</text>
        </g>
      )
    },
    'seapaz-wake': { // シーパーズ右版 起きたて
      bg: '#A78BFA', fg: '#fff',
      svg: (
        <g>
          <ellipse cx="100" cy="115" rx="64" ry="56" fill="#F0EBFF" stroke="#0A0A0A" strokeWidth="3"/>
          <path d="M50 75 L 35 40 L 70 65 Z" fill="#F0EBFF" stroke="#0A0A0A" strokeWidth="3"/>
          <path d="M150 75 L 165 40 L 130 65 Z" fill="#F0EBFF" stroke="#0A0A0A" strokeWidth="3"/>
          {/* open eyes */}
          <circle cx="82" cy="108" r="7" fill="#0A0A0A"/>
          <circle cx="118" cy="108" r="7" fill="#0A0A0A"/>
          <circle cx="84" cy="106" r="2" fill="#fff"/>
          <circle cx="120" cy="106" r="2" fill="#fff"/>
          {/* sparkle */}
          <path d="M148 60 l 4 -8 l 4 8 l 8 4 l -8 4 l -4 8 l -4 -8 l -8 -4 z" fill="#F2B845"/>
          {/* smile */}
          <path d="M82 130 Q 100 142 118 130" stroke="#0A0A0A" strokeWidth="3.5" fill="none" strokeLinecap="round"/>
        </g>
      )
    },
    hugmon: { // H.U.G活 placeholder
      bg: '#F4B8C8', fg: '#fff',
      svg: (
        <g>
          <circle cx="100" cy="110" r="60" fill="#FFD9E3" stroke="#0A0A0A" strokeWidth="3" strokeDasharray="6 6"/>
          <text x="100" y="125" textAnchor="middle" fontFamily="Cabin, sans-serif" fontWeight="700" fontSize="56" fill="#0A0A0A" opacity="0.4">?</text>
        </g>
      )
    },
    tinmon: { // T.I.N活 placeholder
      bg: '#1E3A5F', fg: '#fff',
      svg: (
        <g>
          <circle cx="100" cy="110" r="60" fill="#2C4D7A" stroke="#fff" strokeWidth="3" strokeDasharray="6 6"/>
          <text x="100" y="125" textAnchor="middle" fontFamily="Cabin, sans-serif" fontWeight="700" fontSize="56" fill="#fff" opacity="0.45">?</text>
        </g>
      )
    },
    akari: { // 白瀬あかり 3D placeholder
      bg: '#fff', fg: '#0A0A0A',
      svg: (
        <g>
          <ellipse cx="100" cy="155" rx="55" ry="18" fill="#0A0A0A" opacity="0.15"/>
          {/* hair back */}
          <path d="M55 80 Q 50 130 70 160 L 130 160 Q 150 130 145 80 Q 145 50 100 45 Q 55 50 55 80 Z" fill="#5C3A2A" stroke="#0A0A0A" strokeWidth="2.5"/>
          {/* lab coat */}
          <path d="M65 155 L 75 110 L 125 110 L 135 155 Z" fill="#FFFFFF" stroke="#0A0A0A" strokeWidth="2.5"/>
          {/* face */}
          <ellipse cx="100" cy="92" rx="30" ry="34" fill="#FCE3CC" stroke="#0A0A0A" strokeWidth="2.5"/>
          {/* bangs */}
          <path d="M72 75 Q 90 60 100 70 Q 110 60 128 75 L 128 92 Q 100 78 72 92 Z" fill="#5C3A2A" stroke="#0A0A0A" strokeWidth="2.5"/>
          {/* eyes */}
          <ellipse cx="88" cy="97" rx="3.5" ry="5" fill="#0A0A0A"/>
          <ellipse cx="112" cy="97" rx="3.5" ry="5" fill="#0A0A0A"/>
          {/* smile */}
          <path d="M90 113 Q 100 119 110 113" stroke="#0A0A0A" strokeWidth="2.2" fill="none" strokeLinecap="round"/>
          {/* hapimon in arms */}
          <path d="M90 138 C 78 132, 75 122, 85 118 C 92 116, 95 122, 95 124 C 95 122, 98 116, 105 118 C 115 122, 112 132, 100 138 Z" fill="#FF2030" stroke="#0A0A0A" strokeWidth="2"/>
        </g>
      )
    }
  };
  const m = marks[id] || marks.hugmon;
  return (
    <svg className="mm-charmark" viewBox="0 0 200 200" width={size} height={size} aria-hidden="true">
      <circle cx="100" cy="100" r="98" fill={m.bg} opacity="0.0"/>
      {m.svg}
    </svg>
  );
}

// ============= Awards row (Brand Kit V2 — left/right split) =============
function AwardsRow() {
  // Royal-hall loop video — onTimeUpdate fires ~4× per second; if we're within
  // 100ms of the end, snap back to 0 manually so the loop seam doesn't visibly
  // pause/snap on browsers that stall a few frames before native re-loop.
  const onAwardsBgTimeUpdate = (e) => {
    const v = e.currentTarget;
    if (!v.duration) return;
    if (v.duration - v.currentTime < 0.1) {
      try { v.currentTime = 0; } catch (_) {}
    }
  };
  return (
    <section className="mm-awards" data-screen-label="02 Awards" id="awards">
      <video
        className="mm-awards__bg-video"
        autoPlay
        loop
        muted
        playsInline
        preload="auto"
        aria-hidden="true"
        onTimeUpdate={onAwardsBgTimeUpdate}
      >
        <source src="assets/awards-royal-hall-locked.webm" type="video/webm" />
      </video>
      <div className="mm-awards__inner">
        <div className="mm-awards__text">
          <p className="mm-awards__eyebrow">— AWARDS · 実績</p>
          <h2 className="mm-awards__shout">
            <span>オイモンが、</span>
            <span className="mm-awards__amazon">AMAZON</span>
            <span>を制した。</span>
          </h2>
          <p className="mm-awards__sub">
            <span className="mm-awards__trophy" aria-hidden="true">★</span>
            カプサイシン部門 売れ筋ランキング1位
            <span className="mm-awards__date">（2026.02.27 時点）</span>
          </p>
        </div>
      </div>
    </section>
  );
}

// ============= Bento Grid (Brand Kit V2 — Layout B: char + package) =============
const MONSTERS = [
  {
    id: 'cho',
    sku: 'C.H.O活 MONSTER',
    sub: 'ハピモン',
    tag: 'ハピモンが、腸を整え、心まで変える。',
    badge: { kind: 'collab', label: '白瀬あかりコラボ予告' },
    char: 'hapimon',
    photo: 'assets/hapimon-1.png',
    video: 'assets/hapimon.webm',
    pkg: 'assets/cho-pkg-30day.png',
    bg: 'cho',
    live: true,
  },
  {
    id: 'ase',
    sku: 'A.S.E活 MONSTER',
    sub: 'オイモン',
    tag: 'オイモンが、君の内側のめぐりを変える。',
    badge: { kind: 'award', label: '🏆 AMAZON NO.1' },
    char: 'oimon',
    photo: 'assets/oimon.png',
    video: 'assets/oimon.webm',
    pkg: 'assets/ase-pkg-30day.png',
    bg: 'ase',
    live: true,
  },
  {
    id: 'hug',
    sku: 'H.U.G活 MONSTER',
    sub: 'ハグモン（仮）',
    tag: 'ハグモンが、ひとりの夜に味方になる。',
    badge: { kind: 'soon', label: 'COMING SOON' },
    char: 'hugmon',
    pkg: null,
    bg: 'hug',
    live: false,
  },
  {
    id: 'min',
    sku: 'M.I.N活 MONSTER',
    sub: 'シーパーズ',
    tag: 'シーパーズが、君の朝を変える。',
    badge: { kind: 'soon', label: 'COMING SOON' },
    char: 'seapaz',
    photo: 'assets/seapaz-center.png',
    video: 'assets/seapaz-center.webm',
    pkg: 'assets/min-pkg-30day.png',
    bg: 'min',
    live: false,
  },
  {
    id: 'tin',
    sku: 'T.I.N活 MONSTER',
    sub: 'ティンモン（仮）',
    tag: 'ティンモンが、男の根本を整える。',
    badge: { kind: 'soon', label: 'COMING SOON' },
    char: 'tinmon',
    pkg: null,
    bg: 'tin',
    live: false,
  },
];

function MonsterCard({ m }) {
  const locked = !m.live;
  const href = locked ? null : `products/${m.id}-katsu-monster.html`;
  // Whole-card navigation (method B — JS onClick on the <article>).
  //
  // The CSS-only "stretched link" approach was tried first but couldn't
  // work here: .mm-bento__foot / .mm-bento__head already have
  // `position: relative; z-index: 2` (set so they sit above the locked
  // card's diagonal-lattice ::after), so a `.mm-bento__cta::after`
  // resolves against the foot — not the card — and never reaches the
  // top half of the tile. Touching those z-indices would risk breaking
  // the lock overlay; instead we navigate via JS.
  //
  // Click rules:
  //   • Locked cards: no handler attached → nothing happens (no error).
  //   • Live cards: handler navigates UNLESS the click started on a
  //     real <a> / <button> inside (e.g. the VIEW MONSTER link). That
  //     keeps the inner CTA fully native — Cmd+click for a new tab,
  //     middle-click, right-click context menu all work because the
  //     wrapper handler simply yields when the inner link is the
  //     actual target.
  const onCardClick = (e) => {
    if (!href) return;
    if (e.defaultPrevented) return;
    // Don't hijack modifier-clicks / non-primary buttons — let the
    // browser handle Cmd/Ctrl/Shift/middle-click on the wrapper too.
    if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
    // If the click landed on a real interactive descendant (inner <a>
    // or <button>), let that element's native behaviour take over.
    if (e.target.closest('a, button')) return;
    window.location.href = href;
  };
  const onCardKey = (e) => {
    if (!href) return;
    // Native links inside (VIEW MONSTER) handle their own Enter.
    if (e.target.closest('a, button')) return;
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      window.location.href = href;
    }
  };
  return (
    <article
      className={`mm-bento__cell mm-bento__cell--monster bg-${m.bg} ${locked ? 'is-locked' : 'is-clickable'}`}
      aria-disabled={locked || undefined}
      role={href ? 'link' : undefined}
      tabIndex={href ? 0 : undefined}
      onClick={href ? onCardClick : undefined}
      onKeyDown={href ? onCardKey : undefined}
      data-href={href || undefined}
    >
      {/* TOP — badge + product name + character name */}
      <div className="mm-bento__head">
        <span className={`mm-badge mm-badge--${m.badge.kind}`}>{m.badge.label}</span>
        <div className="mm-bento__name-row">
          <h3 className="mm-bento__name">{m.sku}</h3>
          {m.sub ? <span className="mm-bento__sub">「{m.sub}」</span> : null}
        </div>
      </div>

      {/* MIDDLE — character (left) + package (right), baseline-aligned, no overlap */}
      <div className="mm-bento__stage" aria-hidden="true">
        <div className="mm-bento__char">
          {m.video ? (
            // WebM (currently non-alpha, VP8 + yuv420p, black bg).
            // No mix-blend-mode — character renders in its true colors. The
            // CSS `mask-image: radial-gradient(...)` on .mm-bento__char-video
            // softly fades the corners of the video out, hiding the black
            // background against whatever card color sits behind it.
            // When alpha-channel WebMs ship the mask can be relaxed/removed.
            <video
              className="mm-bento__char-photo mm-bento__char-video"
              autoPlay
              loop
              muted
              playsInline
              poster={m.photo}
              aria-hidden="true"
            >
              <source src={m.video} type="video/webm" />
              {m.photo ? <img src={m.photo} alt="" className="mm-bento__char-photo" /> : null}
            </video>
          ) : m.photo ? (
            <img src={m.photo} alt="" className="mm-bento__char-photo" />
          ) : (
            <CharMark id={m.char} size={200} />
          )}
        </div>
        <div className="mm-bento__pkg">
          {m.pkg ? (
            <img src={m.pkg} alt="" />
          ) : (
            <div className="mm-bento__pkg-placeholder">
              <span>PACKAGE</span>
              <span>TBD</span>
            </div>
          )}
        </div>
      </div>

      {/* BOTTOM — tagline + CTA */}
      <div className="mm-bento__foot">
        <p className="mm-bento__tag">{m.tag}</p>
        <div className="mm-bento__cta-row">
          {locked ? (
            <span className="mm-bento__cta is-locked">→ COMING SOON</span>
          ) : (
            <a className="mm-bento__cta" href={`products/${m.id}-katsu-monster.html`}>→ VIEW MONSTER</a>
          )}
        </div>
      </div>
    </article>
  );
}

// PAIN counter — LIVE TICKER. Already high on arrival (grows with real time
// since launch at a slow ~+1/hour pace so it stays in the 150,000s for the
// brand promise), then ticks up +1–3 every 2–5s while on screen with a
// damage-number "+N" pop, a heartbeat, a bounce, and a red glow pulse.
function computeLivePainCount() {
  const BASE = 1526;
  const REF_DATE = new Date('2026-06-04T00:00:00Z').getTime();
  const elapsedHours = Math.max(0, (Date.now() - REF_DATE) / (1000 * 60 * 60));
  return BASE + Math.floor(elapsedHours); // ~ +1 per hour — stays in the 1,500s
}

function PainCounterCard() {
  const ref = _useRef(null);
  const numRef = _useRef(null);
  const wrapRef = _useRef(null);
  const glowRef = _useRef(null);
  const timerRef = _useRef(null);
  const [val, setVal] = _useState(computeLivePainCount);

  _useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let active = false;
    const reduceMotion = !!(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches);

    // (c) bounce the whole number
    const bounce = () => {
      const n = numRef.current;
      if (!n) return;
      n.classList.remove('is-bump');
      void n.offsetWidth; // reflow to restart
      n.classList.add('is-bump');
    };
    // (b) damage-number "+N" that floats up and fades
    const spawnFloat = (inc) => {
      const wrap = wrapRef.current;
      if (!wrap) return;
      const f = document.createElement('span');
      f.className = 'mm-counter__float';
      f.textContent = '+' + inc;
      f.style.setProperty('--fx', (Math.random() * 26 - 9).toFixed(0) + 'px');
      wrap.appendChild(f);
      setTimeout(() => { if (f.parentNode) f.parentNode.removeChild(f); }, 1000);
    };
    // (d) red glow vignette pulse
    const glowPulse = () => {
      const g = glowRef.current;
      if (!g) return;
      g.classList.remove('is-pulse');
      void g.offsetWidth;
      g.classList.add('is-pulse');
    };

    const schedule = () => {
      timerRef.current = setTimeout(tick, 2000 + Math.random() * 3000); // 2–5s
    };
    function tick() {
      const inc = 1 + Math.floor(Math.random() * 3); // 1–3
      setVal((v) => v + inc);
      if (!reduceMotion) { bounce(); spawnFloat(inc); glowPulse(); }
      schedule();
    }
    const start = () => {
      if (active) return;
      active = true;
      el.classList.add('is-live'); // (a) enables the heartbeat loop
      schedule();
    };
    const stop = () => {
      active = false;
      el.classList.remove('is-live');
      if (timerRef.current) { clearTimeout(timerRef.current); timerRef.current = null; }
    };
    const inView = () => {
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      return r.top < vh && r.bottom > 0;
    };

    // Start WITHOUT depending on IntersectionObserver (silent in some iframes):
    // start if in view, scroll fallback, plus a safety timer.
    if (inView()) start();
    const onScroll = () => { if (inView()) start(); else stop(); };
    window.addEventListener('scroll', onScroll, { passive: true });
    const safety = setTimeout(() => { if (!active) start(); }, 1500);

    // IntersectionObserver ONLY pauses off-screen / resumes on-screen.
    let io;
    try {
      io = new IntersectionObserver((entries) => {
        entries.forEach((e) => { if (e.isIntersecting) start(); else stop(); });
      }, { threshold: 0 });
      io.observe(el);
    } catch (_) {}

    return () => {
      stop();
      window.removeEventListener('scroll', onScroll);
      clearTimeout(safety);
      if (io) io.disconnect();
    };
  }, []);

  return (
    <article ref={ref} className="mm-bento__cell mm-bento__cell--counter" data-screen-label="04 PAIN counter">
      <div className="mm-counter__noise" aria-hidden="true"></div>
      <div ref={glowRef} className="mm-counter__redglow" aria-hidden="true"></div>
      <div className="mm-counter__head">
        <p className="mm-counter__eyebrow">MONSTERS HAVE EATEN</p>
        <p className="mm-counter__eyebrow-jp">モンスター達が食べた、PAIN の数</p>
      </div>
      <div className="mm-counter__body">
        <div ref={wrapRef} className="mm-counter__numwrap">
          <div
            ref={numRef}
            className="mm-counter__num"
            aria-live="polite"
            aria-label={`${val.toLocaleString()} PAINS、今も増え続けています`}
          >
            {val.toLocaleString()}<span className="mm-counter__plus">+</span>
          </div>
        </div>
        <p className="mm-counter__unit">PAINS</p>
      </div>
    </article>
  );
}

function BentoGrid() {
  const live = MONSTERS.filter(m => m.live);
  const soon = MONSTERS.filter(m => !m.live);
  return (
    <section className="mm-bento" data-screen-label="03 Bento Grid" id="monsters">
      {/* Section title — added so the bento reads unambiguously as the
          product index. Keeps the small chapter line (03 / MONSTERS) and
          the right-side eyebrow (モンスターたち · CHOOSE YOUR HUNGER)
          intact below, as a sub-header. */}
      <div className="mm-bento__title-block">
        <h2 className="mm-bento__title">PRODUCTS</h2>
        <p className="mm-bento__lead">あなたのPAINに合う一体を、選ぼう。</p>
      </div>
      <div className="mm-bento__row mm-bento__row--live">
        {live.map((m) => <MonsterCard m={m} key={m.id} />)}
      </div>
      <div className="mm-bento__row mm-bento__row--soon">
        {soon.map((m) => <MonsterCard m={m} key={m.id} />)}
      </div>
    </section>
  );
}

// ============= PAIN counter banner — full-width capstone =============
function PainCounterBanner() {
  return (
    <section className="mm-pain" data-screen-label="04 PAIN counter" id="pain-counter">
      <PainCounterCard />
    </section>
  );
}

Object.assign(window, { AwardsRow, BentoGrid, PainCounterBanner, CharMark });
