/* global React, PROJECTS, STACK, TIMELINE, NOW_LIST, MARQUEE, PROFILE */
const { useEffect, useRef, useState } = React;

/* ─── visuals (per-card) ───────────────────────────── */
function VisFlow() {
  return (
    <svg viewBox="0 0 400 250" preserveAspectRatio="none">
      <defs>
        <linearGradient id="ln" x1="0" x2="1">
          <stop offset="0" stopColor="rgba(255,255,255,0)" />
          <stop offset=".5" stopColor="rgba(255,255,255,0.5)" />
          <stop offset="1" stopColor="rgba(255,255,255,0)" />
        </linearGradient>
      </defs>
      {[40, 80, 120, 160, 200].map((y, i) => (
        <path key={i} d={`M-20 ${y} Q 200 ${y - 30 + i * 10} 420 ${y + (i % 2 ? 20 : -10)}`}
          fill="none" stroke="url(#ln)" strokeWidth="1" opacity={0.4 + i * 0.1} />
      ))}
      {[
        [60, 70], [180, 110], [320, 80], [240, 170], [110, 190]
      ].map(([x, y], i) => (
        <circle key={i} cx={x} cy={y} r="3" fill="#fff" opacity=".85">
          <animate attributeName="opacity" values=".3;1;.3" dur={`${3 + i}s`} repeatCount="indefinite" />
        </circle>
      ))}
    </svg>
  );
}

function VisBars() {
  const heights = [40, 65, 35, 80, 55, 90, 45, 70, 30, 85, 50, 75];
  return (
    <div className="vis-bars">
      {heights.map((h, i) => (
        <i key={i} style={{ height: `${h}%`, opacity: 0.3 + (i / heights.length) * 0.6 }} />
      ))}
    </div>
  );
}

function CardVis({ kind }) {
  if (kind === 'flow')  return <div className="vis vis-flow"><VisFlow /></div>;
  if (kind === 'bars')  return <VisBars />;
  if (kind === 'grid')  return <div className="vis vis-grid" />;
  if (kind === 'rings') return <div className="vis vis-rings" />;
  return (
    <div className="vis vis-img">
      <img src={kind} alt="" />
    </div>
  );
}

/* ─── reveal observer ──────────────────────────────── */
function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll('.reveal');
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } });
    }, { threshold: 0.12 });
    els.forEach(el => io.observe(el));
    return () => io.disconnect();
  }, []);
}

/* ─── card with cursor spotlight ───────────────────── */
function Card({ p }) {
  const ref = useRef(null);
  const onMove = (e) => {
    const r = ref.current.getBoundingClientRect();
    ref.current.style.setProperty('--mx', (e.clientX - r.left) + 'px');
    ref.current.style.setProperty('--my', (e.clientY - r.top) + 'px');
  };
  return (
    <a href="#" className="card reveal" ref={ref} onMouseMove={onMove}>
      <div className="top">
        <span className="num"><span className="sq" />{p.num} · {p.cat}</span>
        <span>{p.year} · {p.metric.v} {p.metric.l}</span>
      </div>
      <div className="canvas"><CardVis kind={p.vis} /></div>
      <h3>{p.title}</h3>
      <p className="desc">{p.desc}</p>
      <div className="foot">
        <div className="tags">{p.tags.map(t => <span key={t} className="tag">{t}</span>)}</div>
        <span className="read">Case study <span className="arr">↗</span></span>
      </div>
    </a>
  );
}

/* ─── nav ──────────────────────────────────────────── */
function Nav() {
  return (
    <nav className="nav">
      <div className="shell row">
        <a href="#" className="brand">
          <span className="mark mono">{PROFILE.initials}</span>
          <span>{PROFILE.nameShort}</span>
        </a>
        <div className="links">
          <a href="#work">work</a>
          <a href="#stack">stack</a>
          <a href="#timeline">timeline</a>
          <a href="#about">about</a>
        </div>
        <a href="#contact" className="cta">
          Get in touch <span className="arr">↗</span>
        </a>
      </div>
    </nav>
  );
}

/* ─── status bar ───────────────────────────────────── */
function StatusBar() {
  const [t, setT] = useState(() => fmt());
  useEffect(() => { const id = setInterval(() => setT(fmt()), 60_000); return () => clearInterval(id); }, []);
  function fmt() {
    const d = new Date();
    const opts = { timeZone: PROFILE.status.timezone, hour: '2-digit', minute: '2-digit', hour12: false };
    return new Intl.DateTimeFormat('en-GB', opts).format(d) + ' ' + PROFILE.status.tzLabel;
  }
  return (
    <div className="statusbar">
      <div className="shell row">
        <div className="left">
          <span className="dot" />
          <span>{PROFILE.status.availability}</span>
        </div>
        <div className="right">
          <span>{PROFILE.status.version}</span>
          <span className="sep">/</span>
          <span>{PROFILE.status.city} · {t}</span>
          <span className="sep">/</span>
          <span>{PROFILE.status.build}</span>
        </div>
      </div>
    </div>
  );
}

/* ─── hero ─────────────────────────────────────────── */
function Hero() {
  return (
    <header className="hero">
      <div className="glow-stage" />
      <div className="shell" style={{ position: 'relative', zIndex: 2 }}>
        <div className="meta-row">
          <span className="badge">
            <span className="ring" />
            <span className="mono">{PROFILE.hero.badge}</span>
          </span>
        </div>

        <div className="hero-grid">
          <div>
            <h1>
              {PROFILE.hero.h1[0]}<br />
              {PROFILE.hero.h1[1]} <span className="it">{PROFILE.hero.h1[2]}</span><br />
              {PROFILE.hero.h1[3]}
            </h1>
            <p className="lede">{PROFILE.hero.lede}</p>
            <div className="actions">
              <a href="#work" className="btn primary">View selected work <span className="arr">→</span></a>
              <a href={`mailto:${PROFILE.contact.email}`} className="btn">Email me <span className="arr">↗</span></a>
            </div>
          </div>

          <aside className="hero-meta">
            <div className="hero-portrait">
              <img src={PROFILE.photo} alt={PROFILE.name} />
            </div>
            {PROFILE.hero.meta.map(item => (
              <div className="item" key={item.k}>
                <span className="k">{item.k}</span>
                <span className="v"><b>{item.bold}</b>{item.rest}</span>
              </div>
            ))}
          </aside>
        </div>
      </div>
    </header>
  );
}

/* ─── marquee ──────────────────────────────────────── */
function Marquee() {
  const items = [...MARQUEE, ...MARQUEE];
  return (
    <div className="marquee">
      <div className="track">
        {items.map((m, i) => (
          <span key={i}>
            {m}
            <span className="dotmk" />
          </span>
        ))}
      </div>
    </div>
  );
}

/* ─── work ─────────────────────────────────────────── */
function Work() {
  return (
    <section className="block" id="work" data-screen-label="Selected Work">
      <div className="shell">
        <div className="section-head reveal">
          <div><div className="label">/ 001 · selected work</div></div>
          <h2>{PROFILE.sections.work[0]}<span className="it">{PROFILE.sections.work[1]}</span>{PROFILE.sections.work[2]}</h2>
        </div>
        <div className="work-grid">
          {PROJECTS.map(p => <Card key={p.num} p={p} />)}
        </div>
      </div>
    </section>
  );
}

/* ─── stack ────────────────────────────────────────── */
function Stack() {
  const groups = STACK.reduce((acc, s) => { (acc[s.cat] ||= []).push(s); return acc; }, {});
  return (
    <section className="block" id="stack" data-screen-label="Stack">
      <div className="shell">
        <div className="section-head reveal">
          <div><div className="label">/ 002 · stack</div></div>
          <h2>{PROFILE.sections.stack[0]}<span className="it">{PROFILE.sections.stack[1]}</span>{PROFILE.sections.stack[2]}</h2>
        </div>
        {Object.entries(groups).map(([cat, items]) => (
          <div key={cat} style={{ marginBottom: 28 }} className="reveal">
            <div className="kicker" style={{ marginBottom: 14 }}>— {cat}</div>
            <div className="stack-grid">
              {items.map(s => (
                <div className="skill" key={s.name}>
                  <div className="h">
                    <span className="name">{s.name}</span>
                    <span className="yrs">{s.yrs}</span>
                  </div>
                  <span className="cat">{s.cat}</span>
                  <div className="bar"><i style={{ width: s.lvl + '%' }} /></div>
                </div>
              ))}
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}

/* ─── timeline ─────────────────────────────────────── */
function Timeline() {
  return (
    <section className="block" id="timeline" data-screen-label="Timeline">
      <div className="shell">
        <div className="section-head reveal">
          <div><div className="label">/ 003 · trajectory</div></div>
          <h2>{PROFILE.sections.timeline[0]}<span className="it">{PROFILE.sections.timeline[1]}</span>{PROFILE.sections.timeline[2]}</h2>
        </div>
        <div className="timeline">
          {TIMELINE.map((t, i) => (
            <div key={i} className="tl reveal">
              <span className="yr">{t.yr}</span>
              <span className="badge" />
              <div className="role">
                <div className="r">{t.role}</div>
                <div className="c">{t.co}</div>
              </div>
              <div className="what">{t.what}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ─── about ────────────────────────────────────────── */
function About() {
  return (
    <section className="block" id="about" data-screen-label="About">
      <div className="shell">
        <div className="section-head reveal">
          <div><div className="label">/ 004 · about</div></div>
          <h2>{PROFILE.sections.about[0]}<span className="it">{PROFILE.sections.about[1]}</span>{PROFILE.sections.about[2]}</h2>
        </div>
        <div className="about-grid">
          <div className="copy reveal">
            {PROFILE.about.bio.map((para, i) => <p key={i}>{para}</p>)}
          </div>
          <aside className="now reveal">
            <h4><span className="dotmk" /> {PROFILE.about.nowLabel}</h4>
            <ul>
              {NOW_LIST.map(n => (
                <li key={n.k}><span className="k">{n.k}</span><span>{n.v}</span></li>
              ))}
            </ul>
          </aside>
        </div>
      </div>
    </section>
  );
}

/* ─── footer / contact ─────────────────────────────── */
function Footer() {
  return (
    <footer className="footer" id="contact" data-screen-label="Contact">
      <div className="bigsig">{PROFILE.monogram}</div>
      <div className="shell" style={{ position: 'relative', zIndex: 2 }}>
        <div className="kicker reveal" style={{ marginBottom: 18 }}>/ 005 · let's talk</div>
        <h2 className="cta reveal">
          {PROFILE.contact.cta[0]}<br />
          {PROFILE.contact.cta[1]}<span className="it">{PROFILE.contact.cta[2]}</span>{PROFILE.contact.cta[3]}<br />
          <a href={`mailto:${PROFILE.contact.email}`}>{PROFILE.contact.email} →</a>
        </h2>

        <div className="footer-grid">
          <div className="reveal">
            <div className="sig">{PROFILE.contact.sig}</div>
            <div className="since">{PROFILE.contact.since}</div>
          </div>
          <div className="reveal">
            <h5>Direct</h5>
            <ul>
              <li><a href={`mailto:${PROFILE.contact.email}`}>{PROFILE.contact.email}</a></li>
              <li><a href="#">{PROFILE.contact.phone}</a></li>
              <li><a href={PROFILE.contact.resumeUrl}>résumé.pdf ↗</a></li>
            </ul>
          </div>
          <div className="reveal">
            <h5>Elsewhere</h5>
            <ul>
              {PROFILE.contact.links.map(l => (
                <li key={l.label}><a href={l.url}>{l.label}</a></li>
              ))}
            </ul>
          </div>
          <div className="reveal">
            <h5>Reading</h5>
            <ul>
              {PROFILE.contact.posts.map(p => (
                <li key={p.label}><a href={p.url}>{p.label}</a></li>
              ))}
            </ul>
          </div>
        </div>

        <div className="legal">
          <span>{PROFILE.contact.legal[0]}</span>
          <span>{PROFILE.contact.legal[1]}</span>
        </div>
      </div>
    </footer>
  );
}

/* ─── tweaks panel ─────────────────────────────────── */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accentMode": "moonlight",
  "displayFont": "geist",
  "italicFont": "instrument",
  "grain": true,
  "marquee": true,
  "density": "comfortable"
}/*EDITMODE-END*/;

function ApplyTweaks({ tweaks }) {
  useEffect(() => {
    const root = document.documentElement;
    const map = {
      moonlight: { glow: 'rgba(255,255,255,0.55)', tint: '255,255,255' },
      arctic:    { glow: 'rgba(200,225,255,0.55)', tint: '210,225,245' },
      ember:     { glow: 'rgba(255,225,200,0.50)', tint: '245,225,205' },
    };
    const c = map[tweaks.accentMode] || map.moonlight;
    root.style.setProperty('--glow', c.glow);
    root.style.setProperty('--tint', c.tint);

    const sans = {
      geist:     "'Geist',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif",
      inter:     "'Inter',-apple-system,sans-serif",
      neue:      "'Neue Haas Grotesk Display Pro','Helvetica Neue',Helvetica,Arial,sans-serif",
    }[tweaks.displayFont] || "'Geist',sans-serif";
    root.style.setProperty('--sans', sans);
    const it = {
      instrument: "'Instrument Serif',serif",
      cormorant:  "'Cormorant Garamond',serif",
      none:       "'Geist',sans-serif",
    }[tweaks.italicFont] || "'Instrument Serif',serif";
    document.querySelectorAll('.it').forEach(el => { el.style.fontFamily = it; });

    document.querySelector('.grain').style.display = tweaks.grain ? 'block' : 'none';
    document.querySelector('.marquee').style.display = tweaks.marquee ? 'block' : 'none';

    const pad = tweaks.density === 'compact' ? '60px' : tweaks.density === 'spacious' ? '160px' : '110px';
    document.querySelectorAll('section.block').forEach(el => {
      el.style.paddingTop = pad; el.style.paddingBottom = pad;
    });
  }, [tweaks]);
  return null;
}

function Tweaks() {
  const [tweaks, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const T = window.TweaksPanel, S = window.TweakSection,
        R = window.TweakRadio, B = window.TweakToggle, Sel = window.TweakSelect;
  return (
    <>
      <ApplyTweaks tweaks={tweaks} />
      <T title="Tweaks">
        <S title="Mood">
          <R label="Glow tint" value={tweaks.accentMode} onChange={v => setTweak('accentMode', v)}
             options={[{value:'moonlight',label:'Moonlight'},{value:'arctic',label:'Arctic'},{value:'ember',label:'Ember'}]} />
        </S>
        <S title="Typography">
          <Sel label="Display sans" value={tweaks.displayFont} onChange={v => setTweak('displayFont', v)}
               options={[{value:'geist',label:'Geist (default)'},{value:'inter',label:'Inter'},{value:'neue',label:'Neue Haas / Helvetica'}]} />
          <Sel label="Italic accent" value={tweaks.italicFont} onChange={v => setTweak('italicFont', v)}
               options={[{value:'instrument',label:'Instrument Serif'},{value:'cormorant',label:'Cormorant Garamond'},{value:'none',label:'No italic accent'}]} />
        </S>
        <S title="Texture">
          <B label="Film grain" value={tweaks.grain} onChange={v => setTweak('grain', v)} />
          <B label="Stack marquee" value={tweaks.marquee} onChange={v => setTweak('marquee', v)} />
        </S>
        <S title="Density">
          <R label="Section spacing" value={tweaks.density} onChange={v => setTweak('density', v)}
             options={[{value:'compact',label:'Compact'},{value:'comfortable',label:'Default'},{value:'spacious',label:'Spacious'}]} />
        </S>
      </T>
    </>
  );
}

/* ─── app ──────────────────────────────────────────── */
function App() {
  useReveal();
  return (
    <>
      <div className="grain" />
      <StatusBar />
      <Nav />
      <Hero />
      <Marquee />
      <Work />
      <Stack />
      <Timeline />
      <About />
      <Footer />
      <Tweaks />
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
