// ============================================================
// Beyond the Falls - MID sections: Worlds · Synopsis · Characters
// ============================================================
const { useEffect: useEffectM, useRef: useRefM, useState: useStateM } = React;

// ============================================================
// 4) THREE WORLDS
// ============================================================
function Worlds() {
  const [open, setOpen] = useStateM(null);
  return (
    <section id="worlds" className="bg-ink text-off px-6 md:px-8 py-32 relative overflow-hidden" data-screen-label="04 Worlds">
      <div className="absolute inset-0 grain pointer-events-none"/>
      <div className="max-w-7xl mx-auto relative">
        <div className="flex items-end justify-between mb-12 reveal">
          <div>
            <div className="font-mono text-[11px] tracking-[0.2em] uppercase text-white/60 flex items-center gap-1.5"><window.BTFEye className="w-[10px] h-[10px] text-biolum"/> The Worlds</div>
            <h2 className="mt-4 font-display font-bold tracking-tight" style={{ fontSize: 'clamp(40px, 6vw, 96px)', lineHeight: .95, letterSpacing: '-0.03em' }}>
              Three <span className="script-text text-biolum" style={{ fontSize:'1.05em', lineHeight:.6 }}>worlds</span>
            </h2>
          </div>
          <div className="hidden md:block max-w-sm text-[14px] text-white/65">
            Magic, logic, and the space between. The story lives in the tension that holds them together.
          </div>
        </div>

        <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
          {window.WORLDS.map((w, i) => (
            <WorldCard key={w.key} w={w} idx={i} onOpen={() => setOpen(w)} />
          ))}
        </div>
      </div>
      {open && <WorldModal w={open} onClose={() => setOpen(null)} />}
    </section>
  );
}

function WorldCard({ w, idx, onOpen }) {
  const ref = useRefM(null);
  // layered parallax inside the card on pointer move
  const onMove = (e) => {
    const el = ref.current; if (!el) return;
    const r = el.getBoundingClientRect();
    const px = (e.clientX - r.left) / r.width - 0.5;
    const py = (e.clientY - r.top) / r.height - 0.5;
    el.style.setProperty('--px', px); el.style.setProperty('--py', py);
  };
  return (
    <window.Tilt max={9} className={`reveal reveal-delay-${idx+1} rounded-3xl overflow-hidden`}>
      <button ref={ref} onClick={onOpen} onMouseMove={onMove}
        className="world-photo-card group relative block w-full text-left aspect-[4/5] overflow-hidden focus:outline-none"
        style={{ background: w.bg, color: w.fg }}>
        {/* world key art - centered, fitted into the fixed frame */}
        {w.img && (
          <>
            <img src={w.img} alt={w.name} className="absolute inset-0 w-full h-full object-cover object-center transition-transform duration-700 group-hover:scale-[1.04]" draggable="false"/>
            {/* darkening so the title + pills stay legible */}
            <div className="absolute inset-0" style={{ background: `linear-gradient(180deg, ${w.bg}73 0%, ${w.bg}26 34%, ${w.bg}59 66%, ${w.bg}d9 100%)` }}/>
          </>
        )}
        <div className="absolute inset-0 plate-stripes-light opacity-30"/>
        {/* parallax glow */}
        <div className="absolute inset-0 transition-transform duration-300"
             style={{ background: `radial-gradient(420px circle at calc(50% + (var(--px,0) * 120px)) calc(40% + (var(--py,0) * 120px)), ${w.accent}26, transparent 60%)` }}/>
        {/* huge index */}
        <div className="absolute -bottom-6 -right-2 font-display font-bold pointer-events-none select-none"
             style={{ fontSize: 'clamp(120px,16vw,220px)', lineHeight: .8, color: `${w.fg}0f` }}>{w.n}</div>
        <div className="relative h-full p-7 flex flex-col justify-between">
          <div className="flex items-center justify-between text-[10px] font-mono tracking-[0.22em] uppercase opacity-70">
            <span>World · {w.n}</span><span>{w.tag}</span>
          </div>
          <div className="self-center my-auto text-center px-3">
            <div className="font-display font-bold tracking-tight" style={{ fontSize: 'clamp(30px,3vw,46px)', lineHeight: .98, letterSpacing:'-0.02em' }}>{w.name}</div>
            <div className="mt-3 text-[13px] leading-snug" style={{ color: `${w.fg}c0` }}>{w.short}</div>
          </div>
          <div className="flex items-center justify-between">
            <div className="flex flex-wrap gap-1.5">
              {w.pills.slice(0,2).map(p => (
                <span key={p} className="pill" style={{ background:`${w.fg}12`, color:w.fg, border:`1px solid ${w.fg}2e` }}>{p}</span>
              ))}
            </div>
            <div className="shrink-0 w-11 h-11 rounded-full flex items-center justify-center border transition group-hover:scale-110"
                 style={{ borderColor:`${w.fg}40`, background:`${w.fg}10` }}>
              <window.Glyph.arrow className="w-5 h-5 -rotate-45 group-hover:rotate-0 transition" style={{ color: w.accent }}/>
            </div>
          </div>
        </div>
      </button>
    </window.Tilt>
  );
}

function WorldModal({ w, onClose }) {
  return (
    <window.Modal onClose={onClose} accent={w.accent} bg={w.bg} fg={w.fg}
      tag={`World · ${w.n} · ${w.tag}`} title={w.name} script="how the world works" file={`/worlds/${w.key}.md`}>
      <div className="space-y-4 max-w-2xl text-[15px] leading-relaxed" style={{ color: `${w.fg}cc` }}>
        {w.body.map((p, i) => <p key={i}>{p}</p>)}
      </div>
      <div className="mt-7 flex flex-wrap gap-2">
        {w.pills.map(p => <window.Pill key={p} fg={w.fg} accent={w.accent}>{p}</window.Pill>)}
      </div>
    </window.Modal>
  );
}

// ============================================================
// 5) SYNOPSIS
// ============================================================
function Synopsis() {
  const [open, setOpen] = useStateM(false);
  const spot = window.useSpotlight('rgba(14,156,107,.08)', 600);
  return (
    <section id="synopsis" ref={spot} className="spotlight bg-mist text-ink px-6 md:px-8 py-32 relative overflow-hidden" data-screen-label="05 Synopsis">
      <div className="absolute inset-0 pointer-events-none" style={{ background: 'radial-gradient(900px 520px at 10% -5%, rgba(14,156,107,.12), transparent 60%), radial-gradient(760px 620px at 105% 105%, rgba(124,255,203,.14), transparent 60%)' }}/>
      <div className="max-w-7xl mx-auto relative">
        {/* header row */}
        <div className="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-8 mb-12">
          <div className="reveal max-w-2xl">
            <div className="font-mono text-[11px] tracking-[0.2em] uppercase text-ink/60 flex items-center gap-1.5"><window.BTFEye className="w-[10px] h-[10px] text-leaf"/> The Story</div>
            <h2 className="mt-4 font-display font-bold tracking-tight" style={{ fontSize: 'clamp(40px, 6vw, 96px)', lineHeight: .92, letterSpacing: '-0.04em' }}>
              The <span className="script-text text-leaf" style={{ fontSize:'1.02em', lineHeight:.6 }}>story</span>
            </h2>
            <p className="mt-5 max-w-xl text-[15px] text-ink/70 leading-relaxed">
              Season one in eight beats - from a single drop of contamination to a journey only children can make.
              Power has just passed from Fire to Water, and the cycle that keeps the worlds in balance is about to break.
            </p>
          </div>
          <div className="reveal reveal-delay-2 flex items-center gap-6 shrink-0">
            <div className="font-mono text-[11px] uppercase tracking-[0.18em] text-ink/45 text-right leading-relaxed hidden sm:block">
              08 beats<br/>Season 01
            </div>
            <window.Magnetic as="button" strength={0.4} data-magnet onClick={() => setOpen(true)}
              className="group inline-flex items-center gap-2 rounded-full bg-leaf text-off px-5 py-3 text-[13px] hover:bg-leafdk transition-colors">
              Read full synopsis <window.Glyph.arrow className="w-4 h-4 -rotate-45 transition-transform group-hover:translate-x-0.5 group-hover:-translate-y-0.5"/>
            </window.Magnetic>
          </div>
        </div>

        {/* beats grid - 4 cols × 2 rows, compact */}
        <div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-3">
          {window.SYNOPSIS_BEATS.map((b, i) => (
            <window.Tilt key={b.k} max={7}
              className={`reveal reveal-delay-${(i%4)+1} group relative overflow-hidden p-5 rounded-2xl bg-[#F7FCF8] border border-leaf/15 hover:border-leaf/45 transition-all duration-300 hover:-translate-y-1.5 hover:shadow-[0_26px_50px_-28px_rgba(14,156,107,.55)]`}>
              {/* hover glow */}
              <div className="absolute -top-10 -right-10 w-28 h-28 rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none" style={{ background:'radial-gradient(circle, rgba(124,255,203,.4), transparent 70%)' }}/>
              {/* watermark number */}
              <div className="absolute right-3 bottom-1 font-display font-bold pointer-events-none select-none leading-none" style={{ fontSize: 60, color: 'rgba(14,156,107,.06)' }}>{b.k}</div>
              <div className="relative flex items-center gap-3">
                <div className="w-9 h-9 rounded-full text-off flex items-center justify-center font-mono text-[12px] shrink-0 transition-transform duration-300 group-hover:scale-110 group-hover:rotate-6" style={{ background:'linear-gradient(140deg,#0E9C6B,#0B6E4C)', boxShadow:'0 6px 16px -8px rgba(14,156,107,.8)' }}>{b.k}</div>
                <div className="h-px flex-1 bg-leaf/15 group-hover:bg-leaf/40 transition-colors"/>
              </div>
              <div className="relative mt-4 font-display font-semibold tracking-tight text-[18px] leading-tight">{b.t}</div>
              <div className="relative mt-2 text-[13px] text-ink/65 leading-snug">{b.d}</div>
            </window.Tilt>
          ))}
        </div>
      </div>
      {open && <SynopsisModal onClose={() => setOpen(false)} />}
    </section>
  );
}

function SynopsisModal({ onClose }) {
  const paras = [
    'The story begins on the day of the summer solstice - an important holiday for the magical world. On this day each year, power passes from one element to another, continuing an ancient cycle established to preserve balance and harmony. This year, power passes from Fire to Water.',
    'Aquius, the young ruler of the water world, takes the world into his hands, continuing the ancient tradition of the ruling family. In his first year he must prove that he was not chosen by chance, and rightfully deserves the title of Master of the Water element.',
    'The capital celebrates, and the familiar order seems unchanged. But almost immediately a troubling event occurs: in a mountain lake - one of the main sources of fresh water - an unknown contamination is found. At first it reads as an accident; soon it is clear this is only the beginning of a far greater threat.',
    'While the government tries to understand what is happening, anxiety grows in society. The situation is complicated by a new force - a mysterious organization known as the “University of Success,” which offers simple answers, fast solutions and convenient blame, quietly but steadily eroding trust in the world’s traditional institutions.',
    'For Aquius the events become not only a political crisis but a deeply personal trial. The traces lead him to an old family story rooted in his youth. In search of the truth he travels to the World of Rebirth - a place where you cannot hide from your own memories, and where the past begins to speak with the present. There he learns the truth about his family and, for the first time, honestly faces his inner problems.',
    'While the adult world tangles in versions and political calculation, the young generation begins to act. Three students - Div, Draco and Sylpha - under the guidance of the experienced Om-club mentor Homorus, begin their own investigation, bound by friendship and a shared desire to understand what is happening to their world.',
    'A special role belongs to Div, son of Aquius and future heir to the Water element. Events force him to grow up fast. Before him stands a hard choice: remain in the comfort of childhood - and forever in his father’s shadow - or grow up and accept a responsibility he is not yet ready for.',
    'Gradually the teenagers discover that the contamination is connected to another dimension - the Ordy world - where an ancient artifact of the Water element once ended up, not without Aquius’s help. Its disappearance broke the fragile balance between worlds and opened the way for destructive processes.',
    'To stop the looming catastrophe, the young friends must do what the adults cannot: pass through the Waterfall of Impressions - the mysterious border between worlds. Adults cannot cross it: their psyche is too rigidly structured, their inner layers split and frozen in contradiction. Only a child’s plasticity and openness can bind the worlds together.',
    'A dangerous journey awaits them, full of trials, doubts and discoveries. But it is on this path that they begin to understand the main thing: the strength of the world lies not in magic or power, but in the ability to hear one another, to live not only for oneself, to take responsibility, and to keep balance where it is easiest to lose.',
  ];
  return (
    <window.Modal onClose={onClose} accent="#7CFFCB" bg="#062016" fg="#F4F3EE"
      tag="Season 01 · Synopsis" title="The full story" script="from one drop -" file="/story/synopsis.md">
      <div className="modal-body-scroll pr-3 space-y-4 max-w-2xl text-[15px] leading-relaxed" style={{ color: '#F4F3EEcc' }}>
        {paras.map((p, i) => <p key={i}>{p}</p>)}
      </div>
    </window.Modal>
  );
}

// ============================================================
// 6) CHARACTERS - grouped grids, clickable
// ============================================================
function Characters() {
  const [open, setOpen] = useStateM(null); // {person, group}
  return (
    <section id="characters" className="bg-ink text-off px-6 md:px-8 py-32 relative overflow-hidden" data-screen-label="06 Characters">
      <div className="absolute inset-0 grain pointer-events-none"/>
      <div className="max-w-7xl mx-auto relative">
        <div className="mb-14 reveal">
          <div className="font-mono text-[11px] tracking-[0.2em] uppercase text-white/60 flex items-center gap-1.5"><window.BTFEye className="w-[10px] h-[10px] text-biolum"/> The Cast</div>
          <h2 className="mt-4 font-display font-bold tracking-tight" style={{ fontSize: 'clamp(40px, 6vw, 96px)', lineHeight: .95, letterSpacing: '-0.03em' }}>
            The <span className="script-text text-biolum" style={{ fontSize:'1.05em', lineHeight:.6 }}>cast</span>
          </h2>
        </div>

        <div className="space-y-16">
          {window.CHAR_GROUPS.map((g, gi) => (
            <CharGroup key={g.key} g={g} gi={gi} onOpen={(p) => setOpen({ person: p, group: g })} />
          ))}
        </div>
      </div>
      {open && <CharModal person={open.person} group={open.group} onClose={() => setOpen(null)} />}
    </section>
  );
}

function CharGroup({ g, gi, onOpen }) {
  return (
    <div className="reveal">
      <div className="flex items-baseline justify-between gap-4 border-t pt-5 mb-5" style={{ borderColor: g.danger ? 'rgba(198,255,74,.25)' : 'rgba(255,255,255,.12)' }}>
        <div className="flex items-baseline gap-4">
          <span className="font-mono text-[12px] tracking-[0.2em] uppercase" style={{ color: g.accent }}>{(gi+1).toString().padStart(2,'0')}</span>
          <h3 className="font-display font-bold tracking-tight" style={{ fontSize: 'clamp(24px,3vw,40px)', letterSpacing:'-0.02em' }}>
            {g.name}{g.danger && <span className="ml-3 align-middle pill" style={{ background:'rgba(198,255,74,.14)', color:'#C6FF4A', border:'1px solid rgba(198,255,74,.3)' }}>Antagonist</span>}
          </h3>
        </div>
        <span className="hidden md:inline font-mono text-[11px] tracking-[0.2em] uppercase text-white/45">{g.tag}</span>
      </div>
      <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3">
        {g.people.map((p) => <CharCard key={p.name} p={p} g={g} onOpen={() => onOpen(p)} />)}
      </div>
    </div>
  );
}

function CharCard({ p, g, onOpen }) {
  const elc = window.EL[p.el] || g.accent;
  // One card height for all: 4/5 frame + name plate pinned to the bottom of the frame
  // (avoids captions “floating up” when a photo card sits next to a text-below sibling)
  return (
    <window.Tilt max={11} className="rounded-2xl overflow-hidden">
      <button
        onClick={onOpen}
        className={`char-photo-card group relative block w-full aspect-[4/5] text-left focus:outline-none rounded-2xl overflow-hidden`}
        style={{ background: g.bg, border: `1px solid ${g.fg}1c` }}
      >
        <div className="absolute inset-0 overflow-hidden rounded-2xl">
          {p.img ? (
            <img src={p.img} alt={p.name} className="absolute inset-0 w-full h-full object-cover object-top transition duration-700 group-hover:scale-[1.04]" draggable="false"/>
          ) : (
            <>
              <div className="absolute inset-0" style={{ background: `linear-gradient(160deg, ${elc}1f, transparent 70%)` }}/>
              <div className="absolute inset-0 plate-stripes-light opacity-40"/>
              <div className="absolute inset-0 flex items-center justify-center font-display font-bold opacity-25 group-hover:opacity-40 transition"
                   style={{ fontSize: 'clamp(40px,5vw,72px)', color: g.fg }}>{p.name.slice(0,2)}</div>
            </>
          )}
        </div>
        <div className="absolute top-3 left-3 z-10 text-[9px] font-mono tracking-[0.2em] uppercase px-2 py-1 rounded-full"
             style={{ color: '#F4F3EE', background: 'rgba(10,10,10,.4)', backdropFilter:'blur(6px)', WebkitBackdropFilter:'blur(6px)' }}>
          {p.age}
        </div>
        <div className="absolute top-3 right-3 z-10 w-2.5 h-2.5 rounded-full" style={{ background: elc, boxShadow: `0 0 12px ${elc}` }}/>
        <div className="absolute inset-0 z-10 flex items-center justify-center opacity-0 group-hover:opacity-100 transition pointer-events-none">
          <span className="pill" style={{ background:'rgba(255,255,255,.14)', color:'#F4F3EE', border:'1px solid rgba(255,255,255,.33)' }}>
            <window.Glyph.plus className="w-3 h-3"/> Profile
          </span>
        </div>
        <div className="char-name-glass" aria-hidden="true"/>
        <div className="absolute inset-x-0 bottom-0 z-30 px-3.5 pb-3.5 pt-10 pointer-events-none">
          <div className="font-display font-bold tracking-tight" style={{ fontSize: 19, letterSpacing:'-0.01em', color:'#F7F7F4', textShadow:'0 1px 10px rgba(0,0,0,.55)' }}>{p.name}</div>
          <div className="mt-0.5 text-[11.5px] font-mono tracking-[0.08em] uppercase" style={{ color: 'rgba(244,243,238,.85)', textShadow:'0 1px 8px rgba(0,0,0,.5)' }}>{p.role}</div>
        </div>
      </button>
    </window.Tilt>
  );
}

function CharModal({ person, group, onClose }) {
  const elc = window.EL[person.el] || group.accent;
  return (
    <window.Modal onClose={onClose} accent={group.accent} bg={group.bg} fg={group.fg}
      tag={`${group.name} · ${person.role}`} title={person.name} script={`age ${person.age}`} file={`/cast/${person.name.toLowerCase()}.md`}>
      <div className="grid md:grid-cols-[220px_1fr] gap-6 items-start">
        {person.img ? (
          <div className="char-modal-frame relative hidden md:block w-full max-w-[220px] aspect-[9/16] rounded-2xl overflow-hidden isolate"
               style={{ background: group.bg, border:`1px solid ${group.fg}22` }}>
            <img src={person.img} alt={person.name} className="absolute inset-0 w-full h-full object-cover object-top" draggable="false"/>
            <div className="absolute inset-x-0 bottom-0 px-3 pt-6 pb-3 pointer-events-none"
                 style={{ background: 'linear-gradient(180deg, rgba(10,10,10,0) 0%, rgba(10,10,10,.72) 100%)' }}>
              <div className="text-[10px] font-mono tracking-[0.18em] uppercase" style={{ color:'rgba(244,243,238,.9)', textShadow:'0 1px 8px rgba(0,0,0,.5)' }}>{person.name} · key art</div>
            </div>
          </div>
        ) : (
        <div className="char-modal-frame relative aspect-[9/16] w-full max-w-[220px] hidden md:block rounded-2xl overflow-hidden"
             style={{ background: `linear-gradient(160deg, ${elc}2a, transparent 70%), ${group.fg}0e`, border:`1px solid ${group.fg}22` }}>
          <div className="absolute inset-0 plate-stripes-light opacity-40"/>
          <div className="absolute inset-0 flex items-center justify-center font-display font-bold opacity-30" style={{ fontSize: 64, color: group.fg }}>{person.name.slice(0,2)}</div>
          <div className="absolute bottom-3 left-3 text-[10px] font-mono tracking-[0.18em] uppercase" style={{ color:`${group.fg}99` }}>portrait · key art</div>
        </div>
        )}
        <div>
          <div className="flex flex-wrap gap-2 mb-4">
            <window.Pill fg={group.fg} accent={elc}>{person.role}</window.Pill>
            <window.Pill fg={group.fg} accent={group.accent}>{group.tag}</window.Pill>
          </div>
          <p className="text-[15px] leading-relaxed" style={{ color: `${group.fg}cc` }}>{person.d}</p>
          <div className="mt-6 rounded-2xl p-4 text-[13.5px] leading-snug" style={{ background:`${group.fg}0a`, border:`1px solid ${group.fg}1c`, color:`${group.fg}b0` }}>
            <span className="font-mono text-[10px] tracking-[0.2em] uppercase" style={{ color: group.accent }}>The circle</span>
            <div className="mt-1.5">{group.desc}</div>
          </div>
        </div>
      </div>
    </window.Modal>
  );
}

Object.assign(window, { Worlds, Synopsis, Characters });
