// Edwards Metallurgical — site app
const { useState, useEffect, useMemo, useRef } = React;
const { IDENTITY, SERVICES, CASES, PUBLICATIONS, PUBS_PENDING, TALKS,
        TIMELINE, FOCUS_AREAS, CAPABILITIES,
        FAILURE_MODES, FAILURE_MODES_ENCOUNTERED, PAGES } = window.SITE;

// ─────────────────────────────────────────────────────────────────────
// CONTACT FORM ENDPOINT
// ---------------------------------------------------------------------
// Paste your deployed endpoint URL between the quotes to make the contact
// form send. While this is empty (''), the form validates and shows the
// success state locally without sending anything — safe for testing layout.
//
//  • Google Apps Script:  set FORM_MODE = 'no-cors'  (default below)
//  • Cloudflare Worker:   set FORM_MODE = 'cors'
//
// See CONTACT_FORM_BACKEND.md in the project root for full setup steps.
// ─────────────────────────────────────────────────────────────────────
const FORM_ENDPOINT = 'https://script.google.com/macros/s/AKfycbwemuxQeTTOdTuRtqnjj_IWZZLhAydRZbeuOx9W33YoZ-jvjrKDyS79OtIAFSb9bwM9/exec';          // e.g. 'https://script.google.com/macros/s/AKfycb.../exec'
const FORM_MODE = 'no-cors';       // 'no-cors' for Apps Script · 'cors' for Cloudflare Worker

// ───────── Topbar (V3 style: monogram + nav + badge) ─────────
function Topbar({ page, setPage, theme, setTheme }) {
  return (
    <header className="v4-topbar">
      <div className="v4-topbar-inner">
        <div className="v4-brand-left">
          <div className="v4-monogram">JE</div>
          <div className="v4-brand-name">
            Edwards Metallurgical
            <span className="sub">Independent Practice · Est. 2026</span>
          </div>
        </div>
        <nav className="v4-nav-center">
          {PAGES.map(p => (
            <button key={p.id} className={page === p.id ? 'active' : ''} onClick={() => setPage(p.id)}>
              {p.label}
            </button>
          ))}
        </nav>
        <div className="v4-topbar-right">
          <button
            className="v4-badge"
            onClick={() => setPage('contact')}
            style={{ cursor: 'pointer', background: 'transparent' }}
          >◆ Open to inquiries</button>
          <button className="theme-toggle" onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
            {theme === 'dark' ? <span dangerouslySetInnerHTML={{__html: "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"4\"/><line x1=\"12\" y1=\"2.5\" x2=\"12\" y2=\"5\"/><line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"21.5\"/><line x1=\"2.5\" y1=\"12\" x2=\"5\" y2=\"12\"/><line x1=\"19\" y1=\"12\" x2=\"21.5\" y2=\"12\"/><line x1=\"5.05\" y1=\"5.05\" x2=\"6.8\" y2=\"6.8\"/><line x1=\"17.2\" y1=\"17.2\" x2=\"18.95\" y2=\"18.95\"/><line x1=\"5.05\" y1=\"18.95\" x2=\"6.8\" y2=\"17.2\"/><line x1=\"17.2\" y1=\"6.8\" x2=\"18.95\" y2=\"5.05\"/></svg>"}} /> : <span dangerouslySetInnerHTML={{__html: "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\"/></svg>"}} />}
          </button>
        </div>
      </div>
    </header>
  );
}

// ───────── Hero variants (Tweaks-selectable) ─────────
function HeroAsymmetric({ setPage }) {
  return (
    <section className="wrap v3-hero">
      <div className="name-mark">
        <span className="ln" />
        <span>Metallurgy &amp; Materials Science · Forensic &amp; Engineering Consulting · An Independent Practice</span>
        <span className="ln" />
      </div>
      <div style={{
        display: 'grid',
        gridTemplateColumns: '7fr 4fr',
        gap: 56,
        alignItems: 'center',
        textAlign: 'left',
        marginTop: 28,
        maxWidth: 1080,
        marginLeft: 'auto',
        marginRight: 'auto'
      }}>
        <h1 style={{
          fontFamily: "'Libre Caslon Display', serif",
          fontSize: 76,
          lineHeight: 1.0,
          fontWeight: 400,
          letterSpacing: '-0.01em',
          margin: 0,
          color: 'var(--ink)',
          textAlign: 'left'
        }}>
          Joshua M. <em style={{ fontFamily: "'Libre Caslon Text', serif", fontStyle: 'italic', color: 'var(--accent)', fontWeight: 400 }}>Edwards,</em><br />
          Ph.D.
        </h1>
        <p style={{
          fontFamily: "'Libre Caslon Text', serif",
          fontStyle: 'italic',
          fontSize: 19,
          lineHeight: 1.55,
          color: 'var(--ink-soft)',
          margin: 0,
          textAlign: 'left',
          textWrap: 'pretty'
        }}>
          Forensic metallurgy at peer-review and admissibility standards. Every step performed personally — for utilities, manufacturers, counsel, and the engineers who need one expert across the whole problem.
        </p>
      </div>
      <div className="cta-row" style={{ marginTop: 40 }}>
        <button className="btn primary" onClick={() => setPage('contact')}>Contact me</button>
        <button className="btn" onClick={() => setPage('services')}>What I do</button>
      </div>
    </section>
  );
}

function HeroMasthead({ setPage }) {
  return (
    <section className="wrap v3-hero">
      <div className="name-mark">
        <span className="ln" />
        <span>Metallurgy &amp; Materials Science · Forensic &amp; Engineering Consulting · An Independent Practice</span>
        <span className="ln" />
      </div>
      <h1 style={{
        fontFamily: "'Libre Caslon Display', serif",
        fontSize: 88,
        lineHeight: 1.0,
        fontWeight: 400,
        letterSpacing: '-0.015em',
        margin: '24px 0 0',
        color: 'var(--ink)',
        textAlign: 'center',
        whiteSpace: 'nowrap'
      }}>
        Joshua M. <em style={{ fontFamily: "'Libre Caslon Text', serif", fontStyle: 'italic', color: 'var(--accent)', fontWeight: 400 }}>Edwards,</em> Ph.D.
      </h1>
      <div style={{
        marginTop: 48,
        display: 'grid',
        gridTemplateColumns: '1fr 1fr',
        gap: 56,
        alignItems: 'start',
        textAlign: 'left',
        maxWidth: 1000,
        marginLeft: 'auto',
        marginRight: 'auto'
      }}>
        <p style={{
          fontFamily: "'Libre Caslon Text', serif",
          fontStyle: 'italic',
          fontSize: 19,
          lineHeight: 1.55,
          color: 'var(--ink-soft)',
          margin: 0,
          textAlign: 'center',
          hyphens: 'none',
          textWrap: 'pretty'
        }}>
          Metallurgical and materials engineering across the lab, the shop, and expert testimony — servicing utilities, manufacturers, counsel, and engineers needing cross-domain expertise end-to-end.
        </p>
        <div>
          <div style={{
            fontFamily: 'Manrope, sans-serif', fontSize: 10,
            letterSpacing: '0.24em', textTransform: 'uppercase',
            color: 'var(--accent)', fontWeight: 600,
            paddingBottom: 14, borderBottom: '1px solid var(--rule-soft)'
          }}>
            ◆ Actively seeking → Roles · Consultations · Contracts
          </div>
          <div style={{ display: 'flex', gap: 10, marginTop: 18 }}>
            <button className="btn primary" style={{ flex: 1, justifyContent: 'center' }} onClick={() => setPage('contact')}>Contact me</button>
            <button className="btn" style={{ flex: 1, justifyContent: 'center' }} onClick={() => setPage('services')}>What I do</button>
          </div>
        </div>
      </div>
    </section>
  );
}

function HeroMagazine({ setPage }) {
  return (
    <section className="wrap v3-hero">
      <div className="name-mark">
        <span className="ln" />
        <span>Metallurgy &amp; Materials Science · Forensic &amp; Engineering Consulting · An Independent Practice</span>
        <span className="ln" />
      </div>
      <h1 style={{
        fontFamily: "'Libre Caslon Display', serif",
        fontSize: 132,
        lineHeight: 0.96,
        fontWeight: 400,
        letterSpacing: '-0.02em',
        margin: '24px 0 0',
        color: 'var(--ink)',
        textAlign: 'center'
      }}>
        Joshua M. <em style={{ fontFamily: "'Libre Caslon Text', serif", fontStyle: 'italic', color: 'var(--accent)', fontWeight: 400 }}>Edwards,</em><br />
        Ph.D.
      </h1>
      <p style={{
        fontFamily: "'Libre Caslon Text', serif",
        fontStyle: 'italic',
        fontSize: 22,
        lineHeight: 1.4,
        color: 'var(--ink-soft)',
        margin: '40px auto 0',
        maxWidth: 760,
        textAlign: 'center'
      }}>
        Forensic metallurgy at peer-review and admissibility standards.
      </p>
      <div className="cta-row" style={{ marginTop: 36 }}>
        <button className="btn primary" onClick={() => setPage('contact')}>Contact me</button>
        <button className="btn" onClick={() => setPage('services')}>What I do</button>
      </div>
    </section>
  );
}

// ───────── HOME ─────────
function Home({ setPage, layout }) {
  return (
    <div className="page-fade">
      {layout === 'masthead' ? <HeroMasthead setPage={setPage} /> :
       layout === 'magazine' ? <HeroMagazine setPage={setPage} /> :
       <HeroAsymmetric setPage={setPage} />}


      <section className="wrap" style={{ paddingTop: 8 }}>
        <h2 style={{
          textAlign: 'center',
          fontFamily: "'Libre Caslon Display', serif",
          fontSize: 30,
          fontWeight: 400,
          margin: '0 0 8px',
          letterSpacing: '0.02em',
          color: 'var(--ink)'
        }}>
          At a glance
        </h2>
        <div style={{
          display: 'grid',
          gridTemplateColumns: 'repeat(5, 1fr)',
          gap: 28,
          padding: '28px 0',
          borderTop: '1px solid var(--rule)',
          borderBottom: '1px solid var(--rule)',
          marginTop: 12
        }}>
          {[
            ['Doctorate', 'Mines, 2026', 'Met. & Materials Eng.'],
            ['Master\u2019s', 'UCR, 2021', 'Materials Science & Eng.'],
            ['Peer-reviewed', '6 + dissertation', 'MSEA · MMTA · others'],
            ['Conference', '4 talks', 'TMS · GRC'],
            ['Case Studies', '3+', '2021–2025']
          ].map(([lbl, val, sub]) => (
            <div key={lbl} style={{ textAlign: 'center' }}>
              <div className="meta">{lbl}</div>
              <div style={{ fontFamily: "'Libre Caslon Display', serif", fontSize: 22, color: 'var(--accent)', marginTop: 10, lineHeight: 1.1 }}>{val}</div>
              <div style={{ fontFamily: "'Libre Caslon Text', serif", fontStyle: 'italic', fontSize: 12.5, color: 'var(--ink-soft)', marginTop: 4 }}>{sub}</div>
            </div>
          ))}
        </div>

        <div className="scroll-hint" style={{
          textAlign: 'center',
          marginTop: 32,
          fontFamily: 'Manrope, sans-serif',
          fontSize: 10,
          letterSpacing: '0.32em',
          textTransform: 'uppercase',
          color: 'var(--ink-mute)',
          fontWeight: 500,
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          gap: 6
        }}>
          <span>Scroll</span>
          <span style={{ fontSize: 16, color: 'var(--accent)' }}>↓</span>
        </div>

        <article className="lead-body" style={{ maxWidth: 760, margin: '64px auto 0' }}>
          <p>
            Steel fails for a small number of reasons, and almost always tells the story of why it failed if you know how to read it. My practice exists to read those stories — for engineers asked to fix what broke, for counsel preparing a case, and for owners considering whether to repair or replace.
          </p>
          <p>
            I hold a doctorate in metallurgical and materials engineering from the Colorado School of Mines, under Prof. Suveen Mathaudhu. The dissertation, <span className="serif-display" style={{ fontStyle: 'italic' }}>Property Enhancement of Ferrium® M54® Through Novel Processing</span>, examined gradient microstructures in ultra-high-strength steel via accumulative skin-pass rolling — aerospace-class strength and toughness through processing alone. That work, and the multi-modal characterisation stack it demanded, sit underneath every engagement I take on now.
          </p>
          <p>
            Engagements typically begin with a phone call and a few photographs, and end with a written report suitable for engineering review or litigation — built from sectioning, fractography, SEM/EDS, hardness mapping, XRD, and chemistry, presented in plain language.
          </p>
        </article>
      </section>

      <section className="wrap statement">
        <div className="quote-wrap">
          <blockquote>
            I read the <em>record</em> the metal kept,<br />
            design what comes <em>next,</em><br />
            and explain both <em>plainly.</em>
          </blockquote>
        </div>
        <div className="attr">— The working principle of the practice</div>
      </section>

      <section className="wrap">
        <div className="sectionhead">
          <div className="line" />
          <h2><span className="num">I.</span>Services</h2>
          <div className="line" />
        </div>
        <div className="services">
          {SERVICES.filter(s => !s.secondary).map(s => (
            <div key={s.num} className="service">
              <div className="num">{s.num}</div>
              <h4>{s.title}</h4>
              {s.deliverable && <span className="deliv">Deliverable · {s.deliverable}</span>}
              <p>{s.blurb}</p>
            </div>
          ))}
        </div>
        <div style={{ marginTop: 18, textAlign: 'center' }}>
          <a className="link" href="#" onClick={(e) => { e.preventDefault(); setPage('services'); }}>See my full portfolio of services →</a>
        </div>
      </section>

      <section className="wrap" style={{ paddingTop: 56 }}>
        <div className="sectionhead">
          <div className="line" />
          <h2><span className="num">II.</span>Selected Case Studies</h2>
          <div className="line" />
        </div>
        <div className="cases-preview">
          {CASES.slice(0, 3).map(c => (
            <article key={c.n} className="case-mini" onClick={() => setPage('services')}>
              <div className="mini-num">No. {c.n}</div>
              <h4>{c.title}</h4>
              <div className="industry">{c.mode} · {c.industry}</div>
              <p>{c.summary.slice(0, 120)}…</p>
            </article>
          ))}
        </div>
        <div style={{ textAlign: 'center', paddingTop: 28 }}>
          <a className="link" href="#" onClick={(e) => { e.preventDefault(); setPage('services'); }}>
            See all engagements →
          </a>
        </div>
      </section>

      <Colophon setPage={setPage} />
    </div>
  );
}

// ───────── SERVICES ─────────
function Services({ setPage }) {
  const [open, setOpen] = useState(null);
  return (
    <div className="page-fade">
      <section className="wrap work-intro">
        <div>
          <div className="meta" style={{ marginBottom: 16 }}>◆ Consulting, forensic, &amp; engineering</div>
          <h1 className="serif-display">Professional Services</h1>
        </div>
        <p className="deck">
          Five formal lines of practice plus a sixth case-by-case engineering and manufacturing capability — from receipt of evidence through final report and, where required, expert testimony. Every step performed personally.
        </p>
      </section>

      {/* Five core services — V3 row style with hover indent + brass arrow */}
      <section className="wrap">
        <div className="v3-services">
          {SERVICES.filter(s => !s.secondary).map(s => (
            <div key={s.num} className="v3-service">
              <div className="num">{s.num}</div>
              <div>
                <span className="deliv">Deliverable · {s.deliverable}</span>
                <h4>{s.title}</h4>
                <p>{s.detail}</p>
              </div>
              <div className="more">Enquire →</div>
            </div>
          ))}
        </div>
      </section>

      {/* Adjacent capability — V3 dramatic card with corner badge */}
      {SERVICES.filter(s => s.secondary).map(s => (
        <section key={s.num} className="wrap" style={{ paddingTop: 56 }}>
          <div className="sectionhead">
            <div className="line" />
            <h2><span className="num">·</span>Adjacent capability</h2>
            <div className="line" />
          </div>
          <article className="v4-adjacent-card">
            <div className="corner-badge">◆ Line {s.num}</div>
            <div className="inner">
              <div>
                <div className="big-num">{s.num}</div>
                <div className="col-lbl">Engineering &amp; mfg.</div>
              </div>
              <div>
                <h4>{s.title}</h4>
                <p className="detail">{s.detail}</p>
                <div className="tags">
                  {s.tags.map(t => <span key={t}>{t}</span>)}
                </div>
                <p className="note">
                  Offered as a secondary line of the practice — useful when forensic or consulting work calls for an exemplar specimen, a one-off fixture, or a low-volume run. Not the main focus; happy to discuss.
                </p>
              </div>
            </div>
          </article>
        </section>
      ))}

      {/* Selected investigations — V1 section head pattern */}
      <section className="wrap" style={{ paddingTop: 72 }}>
        <div className="sectionhead">
          <div className="line" />
          <h2><span className="num">II.</span>Selected investigations</h2>
          <div className="line" />
        </div>
        <p style={{ textAlign: 'center', fontFamily: "'Libre Caslon Text', serif", fontStyle: 'italic', color: 'var(--ink-soft)', fontSize: 17, margin: '0 auto 28px', maxWidth: 640, textWrap: 'pretty' }}>
          Anonymised summaries of completed engagements. Client identities and proprietary detail are withheld; mechanisms, evidence, and remediation are described as suitable for general reference.
        </p>
      </section>

      {/* Failure modes — V3 centered strip */}
      <div className="wrap" style={{ paddingTop: 8, paddingBottom: 24, textAlign: 'center' }}>
        <div style={{ fontFamily: 'Manrope, sans-serif', fontSize: 10, letterSpacing: '0.3em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 600, marginBottom: 16 }}>
          ◆ Failure modes routinely encountered
        </div>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, justifyContent: 'center', maxWidth: 920, margin: '0 auto' }}>
          {FAILURE_MODES_ENCOUNTERED.map(m => (
            <span key={m} style={{
              fontFamily: 'Manrope, sans-serif',
              fontSize: 10,
              letterSpacing: '0.22em',
              textTransform: 'uppercase',
              color: 'var(--ink-soft)',
              border: '1px solid var(--rule-soft)',
              padding: '7px 12px',
              fontWeight: 500
            }}>{m}</span>
          ))}
        </div>
        <p style={{ marginTop: 18, fontFamily: 'Libre Caslon Text, serif', fontStyle: 'italic', fontSize: 15, color: 'var(--ink-mute)', maxWidth: 720, margin: '18px auto 0', textWrap: 'pretty' }}>
          Capability indicators — each mode has been encountered in forensic-consulting practice. Selected engagement details follow.
        </p>
      </div>

      {/* Case rows — V3 style with summary visible by default */}
      <div className="wrap">
        {CASES.map(c => (
          <article key={c.n} className={'v3-case-row' + (open === c.n ? ' open' : '')} onClick={() => setOpen(open === c.n ? null : c.n)}>
            <div className="top">
              <div className="num">{c.n}<small>Case · {c.year}</small></div>
              <div>
                <h3>{c.title}</h3>
                <p className="summ">{c.summary}</p>
              </div>
              <div className="side">
                <div className="lbl">Engagement type</div>
                <div className="mode-tag">{c.mode}</div>
                <div className="ind">{c.industry}</div>
                {c.status && <div className="ind" style={{ marginTop: 6, color: 'var(--accent)' }}>{c.status}</div>}
              </div>
            </div>
            <div className="v3-detail">
              <div className="v3-detail-inner">
                <div>
                  {c.findings.map(([h, b]) => (
                    <React.Fragment key={h}>
                      <h5>{h}</h5>
                      <p>{b}</p>
                    </React.Fragment>
                  ))}
                </div>
                <div>
                  <div className="v3-meta-list">
                    <dl>
                      {Object.entries(c.meta).map(([k, v]) => (
                        <React.Fragment key={k}><dt>{k}</dt><dd>{v}</dd></React.Fragment>
                      ))}
                    </dl>
                  </div>
                  <div className="v3-micrograph">SANITISED · EXEMPLAR MICROGRAPH</div>
                </div>
              </div>
            </div>
          </article>
        ))}
      </div>
      <Colophon setPage={setPage} />
    </div>
  );
}

// ───────── PUBLICATIONS ─────────
function Publications({ setPage }) {
  const [view, setView] = useState('all');
  const list = useMemo(() => {
    if (view === 'featured') return PUBLICATIONS.filter(p => p.featured);
    if (view === 'theses') return PUBLICATIONS.filter(p => p.kind === 'dissertation' || p.kind === 'thesis');
    return PUBLICATIONS.filter(p => p.kind === 'journal' || p.kind === 'conference');
  }, [view]);
  const spotlight = useMemo(() => PUBLICATIONS.find(p => p.kind === 'dissertation') || PUBLICATIONS.find(p => p.featured), []);

  return (
    <div className="page-fade">
      <section className="wrap pubs-header">
        <div>
          <div className="meta" style={{ marginBottom: 16 }}>◆ Peer-reviewed work · 2021–present</div>
          <h1 className="serif-display">Publications</h1>
        </div>
        <p className="deck" style={{ fontFamily: "'Libre Caslon Text', serif", fontStyle: 'italic', fontSize: 19, color: 'var(--ink-soft)', margin: 0, textWrap: 'pretty' }}>
          Journal articles, conference proceedings, and theses across processing, microstructure, and environmental performance of secondary-hardening steels.
        </p>
      </section>

      <div className="wrap v3-pub-tools">
        <div className="seg">
          <button className={view === 'all' ? 'on' : ''} onClick={() => setView('all')}>Journal &amp; Conf.</button>
          <button className={view === 'featured' ? 'on' : ''} onClick={() => setView('featured')}>Featured</button>
          <button className={view === 'theses' ? 'on' : ''} onClick={() => setView('theses')}>Theses</button>
        </div>
        <div style={{ display: 'flex', gap: 18, alignItems: 'center' }}>
          <a className="link" href="https://orcid.org/0000-0002-0110-7059" target="_blank" rel="noopener">ORCID 0000-0002-0110-7059</a>
          <a className="link" href="https://scholar.google.com/citations?user=XY1LE24AAAAJ&hl=en" target="_blank" rel="noopener">Google Scholar</a>
        </div>
      </div>

      {/* Spotlight — V3 dissertation card */}
      <section className="wrap">
        {spotlight && (
          <div style={{
            marginTop: 40,
            padding: '40px 44px',
            background: 'var(--bg-elev)',
            border: '1px solid var(--accent-deep)',
            position: 'relative',
            display: 'grid',
            gridTemplateColumns: '180px 1fr',
            gap: 44,
            alignItems: 'start'
          }}>
            <div style={{
              position: 'absolute',
              top: -1, left: 24,
              background: 'var(--bg)',
              color: 'var(--accent)',
              padding: '4px 14px',
              fontFamily: 'Manrope, sans-serif',
              fontSize: 10,
              letterSpacing: '0.32em',
              textTransform: 'uppercase',
              fontWeight: 600,
              border: '1px solid var(--accent-deep)',
              transform: 'translateY(-50%)'
            }}>◆ Spotlight</div>
            <div>
              <div style={{ fontFamily: 'Libre Caslon Display, serif', fontSize: 84, color: 'var(--accent)', lineHeight: 1 }}>{spotlight.year}</div>
              <div style={{ fontFamily: 'Manrope, sans-serif', fontSize: 10, letterSpacing: '0.28em', textTransform: 'uppercase', color: 'var(--ink-mute)', marginTop: 10, fontWeight: 500 }}>
                Doctoral dissertation
              </div>
            </div>
            <div>
              <div style={{ fontFamily: 'Libre Caslon Display, serif', fontSize: 30, fontWeight: 400, lineHeight: 1.2, color: 'var(--ink)', letterSpacing: '-0.005em' }}>
                {spotlight.title}
              </div>
              <div style={{ fontFamily: 'Libre Caslon Text, serif', fontStyle: 'italic', color: 'var(--ink-soft)', fontSize: 17, marginTop: 12 }}>
                {spotlight.authors}
              </div>
              <div style={{ fontFamily: 'Manrope, sans-serif', fontSize: 11, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--ink-mute)', marginTop: 10, fontWeight: 500 }}>
                <strong style={{ color: 'var(--accent)', fontWeight: 600 }}>{spotlight.venue}</strong>{spotlight.vol ? ' · ' + spotlight.vol : ''}
              </div>
              <div style={{ marginTop: 18, display: 'flex', gap: 14 }}>
                {spotlight.links.map(l => (
                  <a key={l} className="link" href="#" style={{ fontFamily: 'Manrope, sans-serif', fontSize: 10, letterSpacing: '0.26em', textTransform: 'uppercase', fontWeight: 600 }}>{l} ↗</a>
                ))}
              </div>
            </div>
          </div>
        )}
      </section>

      {/* Catalogue */}
      <section className="wrap" style={{ paddingTop: 48 }}>
        <div style={{ paddingBottom: 12, borderBottom: '1px solid var(--rule)' }}>
          <div style={{ fontFamily: 'Manrope, sans-serif', fontSize: 10, letterSpacing: '0.32em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 600 }}>◆ Catalogue</div>
        </div>
        {list.map((p, i) => (
          <article key={i} className="v3-pub">
            <div className="yr">{p.year}</div>
            <div>
              <div className="title">{p.title}</div>
              <div className="auth">{p.authors}</div>
              <div className="venue"><strong>{p.venue}</strong>{p.vol ? ' · ' + p.vol : ''}</div>
            </div>
            <div className="links">
              {p.links.map(l => <a key={l} href="#">{l} ↗</a>)}
            </div>
          </article>
        ))}
        {list.length === 0 && (
          <p style={{ padding: '60px 0', textAlign: 'center', color: 'var(--ink-mute)', fontFamily: 'Libre Caslon Text, serif', fontStyle: 'italic', fontSize: 18 }}>
            Nothing under this filter yet.
          </p>
        )}
      </section>

      {/* Complete record callout */}
      <section className="wrap">
        <div style={{
          marginTop: 48,
          padding: '32px 36px',
          background: 'var(--bg-elev)',
          borderLeft: '2px solid var(--accent)',
          display: 'grid',
          gridTemplateColumns: '1fr auto',
          gap: 28,
          alignItems: 'center'
        }}>
          <div>
            <div style={{ fontFamily: 'Manrope, sans-serif', fontSize: 10, letterSpacing: '0.32em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 600, marginBottom: 10 }}>
              ◆ For the complete record
            </div>
            <h3 style={{ fontFamily: 'Libre Caslon Display, serif', fontSize: 24, fontWeight: 400, margin: 0, lineHeight: 1.25, color: 'var(--ink)' }}>
              Citation counts and current bibliography are best taken directly from source.
            </h3>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            <a className="btn" href="https://scholar.google.com/citations?user=XY1LE24AAAAJ&hl=en" target="_blank" rel="noopener">Google Scholar ↗</a>
            <a className="btn" href="https://orcid.org/0000-0002-0110-7059" target="_blank" rel="noopener">ORCID Profile ↗</a>
          </div>
        </div>
      </section>

      {/* In preparation */}
      <section className="wrap" style={{ paddingTop: 56 }}>
        <div style={{ paddingBottom: 12, borderBottom: '1px solid var(--rule)' }}>
          <div style={{ fontFamily: 'Manrope, sans-serif', fontSize: 10, letterSpacing: '0.32em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 600 }}>◆ In preparation</div>
        </div>
        {PUBS_PENDING.map((p, i) => (
          <article key={i} className="v3-pub">
            <div className="yr" style={{ fontSize: 16, color: 'var(--ink-mute)', fontFamily: 'Manrope, sans-serif', letterSpacing: '0.22em', textTransform: 'uppercase', fontWeight: 500 }}>{p.status}</div>
            <div>
              <div className="title">{p.title}</div>
              <div className="auth">{p.authors}</div>
            </div>
            <div className="links" />
          </article>
        ))}
      </section>

      {/* Conference talks */}
      <section className="wrap" style={{ paddingTop: 56 }}>
        <div style={{ paddingBottom: 12, borderBottom: '1px solid var(--rule)' }}>
          <div style={{ fontFamily: 'Manrope, sans-serif', fontSize: 10, letterSpacing: '0.32em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 600 }}>◆ Conference talks</div>
        </div>
        {TALKS.map((t, i) => (
          <article key={i} className="v3-pub">
            <div className="yr" style={{ fontSize: 22 }}>{t.date}</div>
            <div>
              <div className="title">{t.title}</div>
              <div className="auth">{t.venue} · {t.city}</div>
            </div>
            <div className="links">
              <a href="#">Talk ↗</a>
            </div>
          </article>
        ))}
      </section>

      <Colophon setPage={setPage} />
    </div>
  );
}

// ───────── ABOUT ─────────
function About({ setPage }) {
  return (
    <div className="page-fade">
      <section className="wrap about-hero">
        <div className="v4-portrait">
          <div className="cap">Joshua M. Edwards · Ph.D.</div>
        </div>
        <div className="about-text">
          <div className="meta" style={{ marginBottom: 18 }}>◆ About the principal</div>
          <h1>A practice rooted in the laboratory.</h1>
          <p className="lede-p">
            I&rsquo;m a metallurgical and materials engineer. My doctoral work, defended at the Colorado School of Mines in May 2026 under Prof. Suveen Mathaudhu, examined property enhancement of ultra-high-strength steel through novel processing — and that lab discipline is what I bring to every engagement now.
          </p>
          <p>
            The dissertation, <span className="serif-display" style={{ fontStyle: 'italic' }}>Property Enhancement of Ferrium® M54® Through Novel Processing</span>, focused on gradient microstructures produced by accumulative skin-pass rolling of hardened M54 — improving strength and toughness for aerospace-class applications. Master&rsquo;s and bachelor&rsquo;s degrees in materials science &amp; engineering from UC Riverside (Profs. Suveen Mathaudhu &amp; David Kisailus, MS; 2018, BS) sit underneath.
          </p>
          <p>
            Edwards Metallurgical was founded in 2025, in parallel with forensic-consulting work alongside Mathaudhu Consulting LLC. The practice is deliberately independent and personally staffed — every engagement, from receipt of evidence through final report and, where required, expert testimony, is performed by the principal.
          </p>
          <div style={{ marginTop: 24, paddingTop: 18, borderTop: '1px dotted var(--rule-soft)', display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            <span className="meta" style={{ marginRight: 8, alignSelf: 'center' }}>Professional affiliations</span>
            {IDENTITY.affiliations.map(a => (
              <span key={a} style={{
                fontFamily: "'JetBrains Mono', monospace",
                fontSize: 10,
                letterSpacing: '0.16em',
                textTransform: 'uppercase',
                color: 'var(--ink-soft)',
                border: '1px solid var(--rule-soft)',
                padding: '5px 10px',
                background: 'var(--bg)'
              }}>{a}</span>
            ))}
          </div>
        </div>
      </section>

      <section className="wrap" style={{ paddingTop: 64 }}>
        <div className="sectionhead">
          <div className="line" />
          <h2><span className="num">III.</span>Three focus areas</h2>
          <div className="line" />
        </div>
        <div className="v4-focus-grid">
          {FOCUS_AREAS.map((f, i) => (
            <div key={i} className="v4-focus-card">
              <div className="kicker">◆ Focus 0{i + 1}</div>
              <h4>{f.title}</h4>
              <div className="sub">{f.sub}</div>
              <p>{f.blurb}</p>
              <ul>
                {f.bullets.map(b => <li key={b}>{b}</li>)}
              </ul>
            </div>
          ))}
        </div>
      </section>

      <section className="wrap" style={{ paddingTop: 64 }}>
        <div className="sectionhead">
          <div className="line" />
          <h2><span className="num">IV.</span>Trajectory</h2>
          <div className="line" />
        </div>
        <div className="timeline">
          {TIMELINE.map((t, i) => (
            <div key={i} className="tl-item">
              <div className="yr">{t.year}</div>
              <h4>{t.what}</h4>
              <div className="org">{t.org}</div>
              {t.note && <div className="note">{t.note}</div>}
            </div>
          ))}
        </div>
      </section>

      <section className="wrap" style={{ paddingTop: 64 }}>
        <div className="sectionhead">
          <div className="line" />
          <h2><span className="num">V.</span>Capabilities &amp; methods</h2>
          <div className="line" />
        </div>
        <div style={{ paddingTop: 8 }}>
          {CAPABILITIES.map((cap, i) => (
            <div key={cap.group} style={{
              display: 'grid',
              gridTemplateColumns: '220px 1fr',
              gap: 32,
              padding: '22px 0',
              borderTop: '1px solid var(--rule-soft)',
              borderBottom: i === CAPABILITIES.length - 1 ? '1px solid var(--rule-soft)' : 'none'
            }}>
              <div>
                <div className="meta" style={{ color: 'var(--accent)' }}>0{i + 1} · Group</div>
                <h4 className="serif-display" style={{ fontSize: 22, fontWeight: 500, margin: '6px 0 0', lineHeight: 1.15 }}>{cap.group}</h4>
              </div>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, alignContent: 'flex-start' }}>
                {cap.items.map(item => (
                  <span key={item} style={{
                    fontFamily: "'JetBrains Mono', monospace",
                    fontSize: 10,
                    letterSpacing: '0.12em',
                    textTransform: 'uppercase',
                    color: 'var(--ink-soft)',
                    border: '1px solid var(--rule-soft)',
                    padding: '5px 9px',
                    background: 'var(--bg)'
                  }}>{item}</span>
                ))}
              </div>
            </div>
          ))}
        </div>
      </section>

      <Colophon setPage={setPage} />
    </div>
  );
}

// ───────── CONTACT ─────────
function Contact({ setPage }) {
  const [v, setV] = useState({ name: '', org: '', email: '', kind: '', message: '', website: '' });
  const [err, setErr] = useState({});
  const [sent, setSent] = useState(false);
  const [sending, setSending] = useState(false);

  const set = (k) => (e) => setV({ ...v, [k]: e.target.value });

  const submit = async (e) => {
    e.preventDefault();
    const n = {};
    if (!v.name.trim()) n.name = 'Please tell me who you are.';
    if (!v.email.trim()) n.email = 'An email address is required.';
    else if (!/^\S+@\S+\.\S+$/.test(v.email)) n.email = 'That doesn\u2019t look like a valid email.';
    if (!v.kind) n.kind = 'Please pick an engagement type.';
    if (!v.message.trim() || v.message.trim().length < 20) n.message = 'A few sentences of context, please.';
    setErr(n);
    if (Object.keys(n).length > 0) return;

    // No endpoint configured yet → succeed locally so the form is testable.
    if (!FORM_ENDPOINT) { setSent(true); return; }

    setSending(true);
    try {
      await fetch(FORM_ENDPOINT, {
        method: 'POST',
        // Apps Script web apps don't return CORS headers; 'no-cors' lets the
        // POST through (we can't read the response, but the row + email still
        // get written server-side). A Cloudflare Worker endpoint can drop the
        // mode line and read the JSON response instead.
        mode: FORM_MODE,
        headers: { 'Content-Type': 'text/plain;charset=utf-8' },
        body: JSON.stringify(v)
      });
      setSent(true);
    } catch (e2) {
      setErr({ submit: 'Sending failed — please email me directly at joshua@edwardsmetallurgical.com.' });
    } finally {
      setSending(false);
    }
  };

  return (
    <div className="page-fade">
      <section className="wrap contact-grid">
        <div>
          <div className="meta" style={{ marginBottom: 16 }}>◆ Engagement enquiries</div>
          <h1>Get in touch.</h1>
          <p className="deck">
            For new inquiries, please use the form. I respond to every message personally within 1–2 business days.
          </p>
          <div className="channel"><div className="ch-lbl">Email</div><div className="ch-val"><a className="link" href="mailto:joshua@edwardsmetallurgical.com">joshua@edwardsmetallurgical.com</a></div></div>
          <div className="channel"><div className="ch-lbl">Phone</div><div className="ch-val">Provided after first contact</div></div>
          <div className="channel"><div className="ch-lbl">Location</div><div className="ch-val">Denver, Colorado · USA</div></div>
          <div className="channel"><div className="ch-lbl">Profiles</div><div className="ch-val"><a className="link" href="https://www.linkedin.com/in/jmedwards95" target="_blank" rel="noopener">LinkedIn</a> · <a className="link" href="https://scholar.google.com/citations?user=XY1LE24AAAAJ&hl=en" target="_blank" rel="noopener">Scholar</a> · <a className="link" href="https://orcid.org/0000-0002-0110-7059" target="_blank" rel="noopener">ORCID</a></div></div>
          <div className="channel"><div className="ch-lbl">Ethics</div><div className="ch-val" style={{ fontStyle: 'italic', fontSize: 15, color: 'var(--ink-soft)' }}>Independent practice. Conflict checks are run before any matter is accepted; confidentiality and chain-of-custody are respected at every step. Inquiries submitted here are used solely to respond to you, are not shared, and are not added to any mailing list.</div></div>
        </div>

        {sent ? (
          <div className="form-success">
            <h3>Thank you.</h3>
            <p>Your message has reached me. I&rsquo;ll respond within 1–2 business days.</p>
          </div>
        ) : (
          <form className="contact" onSubmit={submit} noValidate>
            <div className="hd"><span>Inquiry · Form 01</span><span>Required ·</span></div>
            {/* Honeypot — hidden from humans, bots fill it; submissions with it set are ignored server-side */}
            <input
              type="text"
              name="website"
              value={v.website}
              onChange={set('website')}
              tabIndex={-1}
              autoComplete="off"
              aria-hidden="true"
              style={{ position: 'absolute', left: '-9999px', width: 1, height: 1, opacity: 0 }}
            />
            <div className="form-row">
              <div className={'field' + (err.name ? ' err' : '')}>
                <label>Name</label>
                <input value={v.name} onChange={set('name')} placeholder="Your name" />
                <div className="err-msg">{err.name || ''}</div>
              </div>
              <div className="field">
                <label>Organisation / Firm</label>
                <input value={v.org} onChange={set('org')} placeholder="Optional" />
                <div className="err-msg" />
              </div>
            </div>
            <div className={'field' + (err.email ? ' err' : '')}>
              <label>Email</label>
              <input value={v.email} onChange={set('email')} placeholder="name@firm.com" />
              <div className="err-msg">{err.email || ''}</div>
            </div>
            <div className={'field' + (err.kind ? ' err' : '')}>
              <label>Nature of engagement</label>
              <select value={v.kind} onChange={set('kind')}>
                <option value="">— Please select —</option>
                <option>Forensic failure analysis</option>
                <option>Materials &amp; processing consulting</option>
                <option>Expert witness / litigation</option>
                <option>R&amp;D / process development</option>
                <option>Other</option>
              </select>
              <div className="err-msg">{err.kind || ''}</div>
            </div>
            <div className={'field' + (err.message ? ' err' : '')}>
              <label>Brief description</label>
              <textarea rows={5} value={v.message} onChange={set('message')} placeholder="A few sentences of context — material, service, timeline, jurisdiction if applicable." />
              <div className="err-msg">{err.message || ''}</div>
            </div>
            <button className="submit" type="submit" disabled={sending}>
              {sending ? 'Sending…' : 'Send Inquiry \u00A0→'}
            </button>
            {err.submit && (
              <div style={{ marginTop: 10, fontFamily: "'Libre Caslon Text', serif", fontStyle: 'italic', fontSize: 13, color: 'var(--accent)', textAlign: 'center' }}>
                {err.submit}
              </div>
            )}
            <div style={{ marginTop: 12, fontFamily: 'Manrope, sans-serif', fontSize: 9, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--ink-mute)', textAlign: 'center' }}>
              Conflict check applies · Confidentiality respected · Reply within 1–2 business days
            </div>
          </form>
        )}
      </section>
      <Colophon setPage={setPage} />
    </div>
  );
}

// ───────── Colophon ─────────
function Colophon({ setPage }) {
  return (
    <footer className="v3-foot">
      <div className="wrap">
        <div className="foot-row">
          <div>
            <div className="display">Edwards Metallurgical</div>
            <div className="deck">An independent metallurgical &amp; materials engineering practice. Denver, Colorado.</div>
          </div>
          <div>
            <div className="h">Practice</div>
            <div className="l">
              <div><a href="#" onClick={(e) => { e.preventDefault(); setPage?.('services'); }}>Services</a></div>
              <div><a href="#" onClick={(e) => { e.preventDefault(); setPage?.('services'); }}>Case studies</a></div>
              <div><a href="#" onClick={(e) => { e.preventDefault(); setPage?.('about'); }}>Capabilities</a></div>
            </div>
          </div>
          <div>
            <div className="h">Academic</div>
            <div className="l">
              <div><a href="#" onClick={(e) => { e.preventDefault(); setPage?.('pubs'); }}>Publications</a></div>
              <div><a href="https://scholar.google.com/citations?user=XY1LE24AAAAJ&hl=en" target="_blank" rel="noopener">Google Scholar</a></div>
              <div><a href="https://orcid.org/0000-0002-0110-7059" target="_blank" rel="noopener">ORCID</a></div>
            </div>
          </div>
          <div>
            <div className="h">Contact</div>
            <div className="l">
              <div><a href="#" onClick={(e) => { e.preventDefault(); setPage?.('contact'); }}>Get in touch</a></div>
              <div><a href="https://www.linkedin.com/in/jmedwards95" target="_blank" rel="noopener">LinkedIn</a></div>
              <div><a href="mailto:joshua@edwardsmetallurgical.com">Email</a></div>
            </div>
          </div>
        </div>
        <div className="foot-bottom">
          <div>© MMXXVI · Edwards Metallurgical</div>
          <div>Set in Libre Caslon &amp; Manrope</div>
        </div>
      </div>
    </footer>
  );
}

// ───────── App ─────────
function LayoutSwitcher({ layout, setLayout }) {
  const [open, setOpen] = useState(true);
  const options = [
    { id: 'asymmetric', label: 'Asymmetric · two-col' },
    { id: 'masthead',   label: 'Masthead · big name top' },
    { id: 'magazine',   label: 'Magazine · massive + tagline' }
  ];
  if (!open) {
    return (
      <button onClick={() => setOpen(true)} style={{
        position: 'fixed', right: 16, bottom: 16, zIndex: 1000,
        background: 'var(--accent)', color: 'var(--bg)', border: 0,
        padding: '10px 14px', cursor: 'pointer',
        fontFamily: 'Manrope, sans-serif', fontSize: 10,
        letterSpacing: '0.24em', textTransform: 'uppercase', fontWeight: 600,
        boxShadow: '0 8px 24px rgba(0,0,0,.35)'
      }}>◆ Tweak Hero</button>
    );
  }
  return (
    <div style={{
      position: 'fixed', right: 16, bottom: 16, zIndex: 1000,
      background: 'var(--bg-elev)', color: 'var(--ink)',
      border: '1px solid var(--accent-deep)', width: 280,
      boxShadow: '0 12px 40px rgba(0,0,0,.35)',
      fontFamily: 'Manrope, sans-serif'
    }}>
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        padding: '10px 14px', borderBottom: '1px solid var(--rule)',
        background: 'var(--bg-deep)'
      }}>
        <span style={{
          fontSize: 10, letterSpacing: '0.28em', textTransform: 'uppercase',
          color: 'var(--accent)', fontWeight: 600
        }}>◆ Index hero · live</span>
        <button onClick={() => setOpen(false)} style={{
          background: 'transparent', border: 0, color: 'var(--ink-mute)',
          cursor: 'pointer', fontSize: 14, padding: '0 4px'
        }}>×</button>
      </div>
      <div style={{ padding: 14, display: 'flex', flexDirection: 'column', gap: 8 }}>
        {options.map(o => (
          <button
            key={o.id}
            onClick={() => setLayout(o.id)}
            style={{
              textAlign: 'left',
              padding: '10px 12px',
              background: layout === o.id ? 'var(--accent)' : 'transparent',
              color: layout === o.id ? 'var(--bg)' : 'var(--ink)',
              border: '1px solid ' + (layout === o.id ? 'var(--accent)' : 'var(--rule-soft)'),
              cursor: 'pointer',
              fontFamily: 'Manrope, sans-serif',
              fontSize: 11,
              letterSpacing: '0.12em',
              textTransform: 'uppercase',
              fontWeight: 500,
              transition: 'all .15s'
            }}
          >
            {o.label}
          </button>
        ))}
        <div style={{
          fontFamily: "'Libre Caslon Text', serif", fontStyle: 'italic',
          fontSize: 12, color: 'var(--ink-mute)', lineHeight: 1.4,
          marginTop: 4, textWrap: 'pretty'
        }}>
          Compare three hero layouts. Selection lives in the page state — refresh to reset.
        </div>
      </div>
    </div>
  );
}

function App() {
  const [page, setPage] = useState('home');
  const [theme, setTheme] = useState('dark');
  const [layout, setLayout] = useState('asymmetric');
  useEffect(() => {
    document.documentElement.dataset.theme = theme;
  }, [theme]);
  useEffect(() => {
    window.scrollTo({ top: 0, behavior: 'smooth' });
  }, [page]);

  return (
    <div data-screen-label={'V4 · ' + page}>
      <Topbar page={page} setPage={setPage} theme={theme} setTheme={setTheme} />
      {page === 'home' && <Home setPage={setPage} layout="masthead" />}
      {page === 'services' && <Services setPage={setPage} />}
      {page === 'pubs' && <Publications setPage={setPage} />}
      {page === 'about' && <About setPage={setPage} />}
      {page === 'contact' && <Contact setPage={setPage} />}
    </div>
  );
}

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