// Main app for The Plumage Society
// A single-page editorial site for a (fictional) bird conservation org.

const { useState, useMemo, useEffect, useRef } = React;

// ── Masthead ────────────────────────────────────────────────────────────────
function Masthead({ density }) {
  const today = new Date(2026, 4, 4); // May 4, 2026 — fixed for deterministic display
  const dateStr = today.toLocaleDateString('en-GB', { day: '2-digit', month: 'long', year: 'numeric' }).toUpperCase();
  return (
    <header className="masthead">
      <div className="masthead-rule masthead-rule-top" />
      <div className="masthead-row">
        <span className="masthead-meta">EST. MCMXCVIII · CHAPTER NO. 41</span>
        <span className="masthead-meta">{dateStr} · VOL. XXVIII</span>
      </div>
      <h1 className="masthead-title">
        <span className="masthead-flourish">⌃</span>
        The Plumage Society
        <span className="masthead-flourish flip">⌃</span>
      </h1>
      <div className="masthead-row">
        <span className="masthead-meta">A NON-PROFIT FOR THE STUDY &amp; PROTECTION OF BIRDS</span>
        <span className="masthead-meta">No. 0142 · Quarterly</span>
      </div>
      <div className="masthead-rule" />
    </header>
  );
}

// ── Hero — featured bird, big plate, lede ───────────────────────────────────
function Hero({ bird, variant, onOpen }) {
  return (
    <section className={`hero hero-${variant}`}>
      <div className="hero-plate" onClick={() => onOpen(bird)}>
        <BirdPlate bird={bird} size="lg" />
        <div className="hero-plate-tag">
          <span className="mono">FEATURED · WEEK 18</span>
        </div>
      </div>
      <div className="hero-text">
        <div className="hero-eyebrow mono">FIELD BULLETIN — {bird.region.toUpperCase()}</div>
        <h2 className="hero-headline">
          {bird.common.split(' ').slice(0, -1).join(' ')}{' '}
          <em>{bird.common.split(' ').slice(-1)}</em>
        </h2>
        <div className="hero-latin">{bird.latin}</div>
        <p className="hero-lede">{bird.note}</p>
        <dl className="hero-stats">
          <div><dt>Status</dt><dd style={{ color: STATUS_TONE[bird.statusCode] }}>{bird.status}</dd></div>
          <div><dt>Population</dt><dd>{bird.trend}</dd></div>
          <div><dt>Length</dt><dd>{bird.length}</dd></div>
          <div><dt>Weight</dt><dd>{bird.weight}</dd></div>
          <div><dt>Habitat</dt><dd>{bird.habitat}</dd></div>
          <div><dt>Diet</dt><dd>{bird.diet}</dd></div>
        </dl>
        <button className="hero-cta" onClick={() => onOpen(bird)}>
          Read the full plate <span aria-hidden="true">→</span>
        </button>
      </div>
    </section>
  );
}

// ── Mission Statement ───────────────────────────────────────────────────────
function Mission() {
  return (
    <section className="mission">
      <div className="mission-mark mono">§ I.</div>
      <h3 className="mission-title">
        Every bird is recorded, by hand,<br />
        because every bird counts.
      </h3>
      <div className="mission-cols">
        <p>
          The Plumage Society is a member-supported organisation working in twenty-eight
          countries to study, protect, and recover wild bird populations. Our field teams
          maintain long-term observation posts, our lab catalogues specimens for genetic
          reference, and our policy desk negotiates protections at four UN bodies.
        </p>
        <p>
          We do not fundraise on charisma. The cerulean warbler is funded as carefully as
          the condor; the spoon-billed sandpiper as carefully as the albatross. A continent
          of common birds in quiet decline is the emergency we exist to address.
        </p>
        <p>
          Founded in 1998 by a circle of ornithologists, illustrators, and luthiers in
          Edinburgh, we remain governed by a working membership of eight thousand —
          paid in field hours, dues, and donated optics. Sightings reported to us this year:{' '}
          <strong>184,409</strong>. Hectares under our easement: <strong>21,070</strong>.
        </p>
      </div>
    </section>
  );
}

// ── Index — searchable / filterable ─────────────────────────────────────────
function Index({ birds, onOpen, cardStyle }) {
  const [q, setQ] = useState('');
  const [region, setRegion] = useState('All');
  const [status, setStatus] = useState('All');

  const filtered = useMemo(() => {
    const ql = q.trim().toLowerCase();
    return birds.filter((b) => {
      if (region !== 'All' && b.region !== region) return false;
      if (status !== 'All' && b.statusCode !== status) return false;
      if (!ql) return true;
      return (
        b.common.toLowerCase().includes(ql) ||
        b.latin.toLowerCase().includes(ql) ||
        b.family.toLowerCase().includes(ql) ||
        b.habitat.toLowerCase().includes(ql)
      );
    });
  }, [birds, q, region, status]);

  return (
    <section className="index">
      <div className="section-head">
        <span className="mono section-mark">§ II.</span>
        <h3 className="section-title">The Index</h3>
        <p className="section-sub">
          Twelve plates from this season's fieldwork. Use the index to filter by
          range, status, or by name.
        </p>
      </div>

      <div className="index-controls">
        <div className="index-search">
          <span className="mono index-search-icon">⌕</span>
          <input
            type="text"
            value={q}
            onChange={(e) => setQ(e.target.value)}
            placeholder="Search by common, scientific, or family name…"
            aria-label="Search birds"
          />
          {q && (
            <button className="index-search-clear" onClick={() => setQ('')} aria-label="Clear">
              ✕
            </button>
          )}
        </div>
        <div className="index-filter">
          <span className="index-filter-lbl mono">Region</span>
          <div className="index-chips">
            <Chip active={region === 'All'} onClick={() => setRegion('All')}>All</Chip>
            {REGIONS.map((r) => (
              <Chip key={r} active={region === r} onClick={() => setRegion(r)}>{r}</Chip>
            ))}
          </div>
        </div>
        <div className="index-filter">
          <span className="index-filter-lbl mono">Status</span>
          <div className="index-chips">
            <Chip active={status === 'All'} onClick={() => setStatus('All')}>All</Chip>
            {STATUS_ORDER.map((s) => (
              <Chip key={s} active={status === s} onClick={() => setStatus(s)}
                    tone={STATUS_TONE[s]}>{s}</Chip>
            ))}
          </div>
        </div>
      </div>

      <div className="index-meta mono">
        Showing {filtered.length} of {birds.length} plates
        {region !== 'All' && ` · ${region}`}
        {status !== 'All' && ` · ${STATUS_LABEL[status]}`}
      </div>

      <div className={`index-grid index-grid-${cardStyle}`}>
        {filtered.map((b, i) => (
          <BirdCard key={b.id} bird={b} onOpen={onOpen} cardStyle={cardStyle} index={i} />
        ))}
        {filtered.length === 0 && (
          <div className="index-empty">
            <div className="mono">— No matching plates —</div>
            <button className="link-btn" onClick={() => { setQ(''); setRegion('All'); setStatus('All'); }}>
              Reset filters
            </button>
          </div>
        )}
      </div>
    </section>
  );
}

function Chip({ active, onClick, tone, children }) {
  return (
    <button
      type="button"
      className={`chip${active ? ' chip-active' : ''}`}
      onClick={onClick}
      style={active && tone ? { borderColor: tone, color: tone } : undefined}
    >
      {children}
    </button>
  );
}

function BirdCard({ bird, onOpen, cardStyle, index }) {
  const num = String(index + 1).padStart(2, '0');
  return (
    <article className={`bird-card bird-card-${cardStyle}`} onClick={() => onOpen(bird)}>
      <div className="bird-card-plate">
        <BirdPlateCompact bird={bird} />
      </div>
      <div className="bird-card-body">
        <div className="bird-card-meta mono">
          <span>№ {num}</span>
          <span className="bird-card-status" style={{ color: STATUS_TONE[bird.statusCode] }}>
            {bird.statusCode}
          </span>
        </div>
        <h4 className="bird-card-name">{bird.common}</h4>
        <div className="bird-card-latin">{bird.latin}</div>
        <div className="bird-card-rule" />
        <div className="bird-card-foot mono">
          <span>{bird.region}</span>
          <span>{bird.length}</span>
        </div>
      </div>
    </article>
  );
}

// ── Conservation Ledger ─────────────────────────────────────────────────────
function Ledger({ birds }) {
  // Group by status, ordered most → least at risk
  const grouped = useMemo(() => {
    const order = ['CR', 'EN', 'VU', 'NT', 'LC'];
    return order.map((s) => ({
      code: s,
      label: STATUS_LABEL[s],
      tone: STATUS_TONE[s],
      birds: birds.filter((b) => b.statusCode === s),
    })).filter((g) => g.birds.length > 0);
  }, [birds]);

  return (
    <section className="ledger">
      <div className="section-head">
        <span className="mono section-mark">§ III.</span>
        <h3 className="section-title">The Conservation Ledger</h3>
        <p className="section-sub">
          A standing record of the species under our active care, ranked by IUCN assessment.
        </p>
      </div>

      <div className="ledger-table">
        <div className="ledger-row ledger-head mono">
          <div>Status</div>
          <div>Species</div>
          <div>Family</div>
          <div>Trend</div>
          <div>Range</div>
        </div>
        {grouped.map((g) => (
          <React.Fragment key={g.code}>
            <div className="ledger-group mono" style={{ color: g.tone, borderColor: g.tone }}>
              <span className="ledger-group-code">{g.code}</span>
              <span className="ledger-group-label">{g.label}</span>
              <span className="ledger-group-count">{g.birds.length} listed</span>
            </div>
            {g.birds.map((b) => (
              <div key={b.id} className="ledger-row">
                <div className="ledger-status" style={{ color: g.tone }}>
                  <span className="ledger-dot" style={{ background: g.tone }} />
                  {g.code}
                </div>
                <div className="ledger-species">
                  <div className="ledger-common">{b.common}</div>
                  <div className="ledger-latin">{b.latin}</div>
                </div>
                <div className="ledger-cell mono">{b.family}</div>
                <div className="ledger-cell mono">{b.trend}</div>
                <div className="ledger-cell mono">{b.range}</div>
              </div>
            ))}
          </React.Fragment>
        ))}
      </div>
    </section>
  );
}

// ── Field Notes (journal) ───────────────────────────────────────────────────
const NOTES = [
  {
    date: '02 MAY',
    place: 'Big Sur, California',
    author: 'L. Marwick',
    title: 'Condor #842 returns to the Pinnacles',
    body: 'Tagged in 2019 as a fledgling on the Bitter Creek nest cliff, #842 had been absent from our quarterly counts since the autumn of 2023. She returned this morning, alone, riding a thermal off the Salinas valley wall. The team confirmed the wing tag at 11:07. Two volunteers wept.',
  },
  {
    date: '24 APR',
    place: 'Codfish Island, Aotearoa',
    author: 'T. Whaitiri',
    title: 'Boom season opens, quietly',
    body: 'Three males in track bowls by the second week. The booming has been thinner than last cycle but the rimu is heavy with fruit, and we expect a productive year. Every chick will be weighed, tagged, and named — as it has been since the species\' lowest point of fifty-one birds.',
  },
  {
    date: '11 APR',
    place: 'Andalusian steppe, Spain',
    author: 'M. Vázquez',
    title: 'Rollers back to the orchards',
    body: 'Pesticide rollback in the abandoned almond groves outside Antequera has produced a measurable rebound. Eleven nest boxes occupied, against last season\'s six. The display tumbles return as if remembered between generations.',
  },
];

function Journal() {
  return (
    <section className="journal">
      <div className="section-head">
        <span className="mono section-mark">§ IV.</span>
        <h3 className="section-title">Field Notes</h3>
        <p className="section-sub">
          Observations posted from our regional teams. Updated weekly during fieldwork seasons.
        </p>
      </div>
      <div className="journal-grid">
        {NOTES.map((n, i) => (
          <article key={i} className="journal-entry">
            <div className="journal-entry-meta mono">
              <span>{n.date} · 2026</span>
              <span>{n.place}</span>
            </div>
            <h4 className="journal-entry-title">{n.title}</h4>
            <p className="journal-entry-body">{n.body}</p>
            <div className="journal-entry-sign mono">— {n.author}</div>
          </article>
        ))}
      </div>
    </section>
  );
}

// ── Donate / Membership ─────────────────────────────────────────────────────
function Donate() {
  const [tier, setTier] = useState(60);
  const tiers = [30, 60, 120, 250];
  return (
    <section className="donate">
      <div className="donate-inner">
        <div className="donate-text">
          <span className="mono donate-mark">§ V.</span>
          <h3 className="donate-title">Become a Working Member.</h3>
          <p>
            Annual dues fund field stations, nest wardens, and the volunteer hours that
            put fledgling condors back on the cliff. Members receive the quarterly bulletin,
            site-access codes for fourteen reserves, and the year's full plate folio.
          </p>
        </div>
        <div className="donate-form">
          <div className="donate-tiers mono">
            {tiers.map((t) => (
              <button
                key={t}
                type="button"
                className={`donate-tier${tier === t ? ' donate-tier-active' : ''}`}
                onClick={() => setTier(t)}
              >
                <span className="donate-tier-amt">£{t}</span>
                <span className="donate-tier-per">/ year</span>
              </button>
            ))}
          </div>
          <button className="donate-cta">
            Pledge £{tier} <span aria-hidden="true">→</span>
          </button>
          <div className="donate-note mono">
            Registered charity SC-014892 · 100% of dues to programme work
          </div>
        </div>
      </div>
    </section>
  );
}

// ── Detail modal ────────────────────────────────────────────────────────────
function BirdDetail({ bird, onClose }) {
  useEffect(() => {
    if (!bird) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.style.overflow = '';
    };
  }, [bird, onClose]);

  if (!bird) return null;
  const plateNum = String(bird.plate).padStart(2, '0');

  return (
    <div className="detail-scrim" onClick={onClose}>
      <article className="detail" onClick={(e) => e.stopPropagation()}>
        <button className="detail-close" onClick={onClose} aria-label="Close">✕</button>
        <div className="detail-plate">
          <BirdPlate bird={bird} size="xl" />
        </div>
        <div className="detail-body">
          <div className="detail-meta mono">
            PLATE {plateNum} · {bird.family.toUpperCase()} · {bird.region.toUpperCase()}
          </div>
          <h2 className="detail-name">{bird.common}</h2>
          <div className="detail-latin">{bird.latin}</div>
          <div className="detail-status-bar" style={{ borderColor: STATUS_TONE[bird.statusCode] }}>
            <span className="detail-status-code mono" style={{ color: STATUS_TONE[bird.statusCode] }}>
              {bird.statusCode}
            </span>
            <span className="detail-status-label">{bird.status}</span>
            <span className="detail-status-trend mono">{bird.trend}</span>
          </div>
          <p className="detail-prose">{bird.note}</p>
          <dl className="detail-grid">
            <div><dt>Length</dt><dd>{bird.length}</dd></div>
            <div><dt>Weight</dt><dd>{bird.weight}</dd></div>
            <div><dt>Habitat</dt><dd>{bird.habitat}</dd></div>
            <div><dt>Diet</dt><dd>{bird.diet}</dd></div>
            <div><dt>Range</dt><dd>{bird.range}</dd></div>
            <div><dt>Family</dt><dd>{bird.family}</dd></div>
          </dl>
          <div className="detail-foot mono">
            Filed by The Plumage Society · Catalogue ref. PS-{bird.id.toUpperCase()}
          </div>
        </div>
      </article>
    </div>
  );
}

// ── Footer ──────────────────────────────────────────────────────────────────
function Footer() {
  return (
    <footer className="footer">
      <div className="footer-rule" />
      <div className="footer-cols">
        <div>
          <div className="footer-h mono">The Plumage Society</div>
          <p>14 Candlemaker Row, Edinburgh EH1 2QB · Founded 1998</p>
        </div>
        <div>
          <div className="footer-h mono">Programme</div>
          <ul>
            <li>Field stations</li>
            <li>Nest wardens</li>
            <li>Genetic reference lab</li>
            <li>Policy desk</li>
          </ul>
        </div>
        <div>
          <div className="footer-h mono">Engage</div>
          <ul>
            <li>Submit a sighting</li>
            <li>Quarterly bulletin</li>
            <li>Membership</li>
            <li>Volunteer</li>
          </ul>
        </div>
        <div>
          <div className="footer-h mono">Colophon</div>
          <p>
            Set in Cormorant Garamond, Source Serif 4, and JetBrains Mono.
            All plates rendered in the press room.
          </p>
        </div>
      </div>
      <div className="footer-base mono">
        © MMXXVI · A non-profit registered in Scotland · No bird is too small to count
      </div>
    </footer>
  );
}

// ── Tweaks panel ────────────────────────────────────────────────────────────
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "ochre",
  "density": "regular",
  "heroVariant": "split",
  "cardStyle": "plate",
  "featuredId": "cerulean-warbler"
}/*EDITMODE-END*/;

const PALETTES = {
  ochre: { name: 'Ochre & Ink', bg: '#f4ede0', surface: '#faf6ec', ink: '#1f1b14', muted: '#6b6353', accent: '#a85a2c', rule: '#d6cdbb' },
  forest: { name: 'Forest', bg: '#ebe8df', surface: '#f4f1e8', ink: '#1a221b', muted: '#5a6457', accent: '#3e6b3e', rule: '#cfd2c1' },
  sky:    { name: 'Sky', bg: '#eef0f2', surface: '#f6f7f8', ink: '#1a2230', muted: '#5e6776', accent: '#456a98', rule: '#d4d8df' },
  bone:   { name: 'Bone & Carmine', bg: '#f1ece5', surface: '#f8f4ec', ink: '#1c1917', muted: '#6b655d', accent: '#a83232', rule: '#d8d2c5' },
};

const DENSITY = {
  compact: { padBlock: '64px', padInline: '32px', gap: '24px' },
  regular: { padBlock: '96px', padInline: '48px', gap: '36px' },
  comfy:   { padBlock: '128px', padInline: '72px', gap: '48px' },
};

function App() {
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [active, setActive] = useState(null);

  const palette = PALETTES[tweaks.palette] || PALETTES.ochre;
  const density = DENSITY[tweaks.density] || DENSITY.regular;
  const featured = BIRDS.find((b) => b.id === tweaks.featuredId) || BIRDS[0];

  // Inject palette + density vars on <html> so CSS can read them everywhere
  useEffect(() => {
    const r = document.documentElement.style;
    r.setProperty('--bg', palette.bg);
    r.setProperty('--surface', palette.surface);
    r.setProperty('--ink', palette.ink);
    r.setProperty('--muted', palette.muted);
    r.setProperty('--accent', palette.accent);
    r.setProperty('--rule', palette.rule);
    r.setProperty('--pad-block', density.padBlock);
    r.setProperty('--pad-inline', density.padInline);
    r.setProperty('--gap', density.gap);
  }, [palette, density]);

  return (
    <>
      <Masthead />
      <main className="page">
        <Hero bird={featured} variant={tweaks.heroVariant} onOpen={setActive} />
        <Mission />
        <Index birds={BIRDS} onOpen={setActive} cardStyle={tweaks.cardStyle} />
        <Ledger birds={BIRDS} />
        <Journal />
        <Donate />
      </main>
      <Footer />
      <BirdDetail bird={active} onClose={() => setActive(null)} />

      <TweaksPanel title="Tweaks">
        <TweakSection label="Theme" />
        <TweakRadio label="Palette" value={tweaks.palette}
                    options={[
                      { value: 'ochre', label: 'Ochre' },
                      { value: 'forest', label: 'Forest' },
                      { value: 'sky', label: 'Sky' },
                      { value: 'bone', label: 'Bone' },
                    ]}
                    onChange={(v) => setTweak('palette', v)} />
        <TweakRadio label="Density" value={tweaks.density}
                    options={['compact', 'regular', 'comfy']}
                    onChange={(v) => setTweak('density', v)} />

        <TweakSection label="Layout" />
        <TweakRadio label="Hero" value={tweaks.heroVariant}
                    options={[
                      { value: 'split', label: 'Split' },
                      { value: 'stacked', label: 'Stacked' },
                      { value: 'overlay', label: 'Overlay' },
                    ]}
                    onChange={(v) => setTweak('heroVariant', v)} />
        <TweakRadio label="Cards" value={tweaks.cardStyle}
                    options={[
                      { value: 'plate', label: 'Plate' },
                      { value: 'list', label: 'List' },
                      { value: 'minimal', label: 'Minimal' },
                    ]}
                    onChange={(v) => setTweak('cardStyle', v)} />

        <TweakSection label="Featured Bird" />
        <TweakSelect label="Plate of the week" value={tweaks.featuredId}
                     options={BIRDS.map((b) => ({ value: b.id, label: b.common }))}
                     onChange={(v) => setTweak('featuredId', v)} />
      </TweaksPanel>
    </>
  );
}

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