// Direction A — ATLAS
// Museum / catalogue raisonné aesthetic.
// Cream paper, deep ink, serif display + mono labels.
// Numbered entries (Roman + Arabic), hover reveals a "plate" card
// at right showing description + URL preview.
//
// Reads: window.SUEDE_DATA
// Mounts as <SuedeAtlas dark={bool} onModeChange={fn} />

const Atlas = (() => {
  const { useState, useEffect, useRef, useMemo } = React;

  // ─── Tokens ───────────────────────────────────────────────
  const tokens = (dark) => ({
    paper:    dark ? '#161311' : '#f4efe5',
    paperDeep: dark ? '#0f0d0c' : '#ece5d6',
    ink:      dark ? '#ede5d3' : '#1a1612',
    inkSoft:  dark ? 'rgba(237,229,211,0.62)' : 'rgba(26,22,18,0.62)',
    rule:     dark ? 'rgba(237,229,211,0.18)' : 'rgba(26,22,18,0.18)',
    ruleSoft: dark ? 'rgba(237,229,211,0.08)' : 'rgba(26,22,18,0.08)',
    accent:   dark ? '#d6a86a' : '#7a3b1f',
    plate:    dark ? '#1e1a17' : '#faf6ec',
  });

  const FONTS = {
    serif: '"Cormorant Garamond", "EB Garamond", Georgia, serif',
    sans: '"Inter Tight", "Helvetica Neue", Arial, sans-serif',
    mono: '"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace',
  };

  const roman = (n) => {
    const map = [['M',1000],['CM',900],['D',500],['CD',400],['C',100],['XC',90],['L',50],['XL',40],['X',10],['IX',9],['V',5],['IV',4],['I',1]];
    let s = '', x = n;
    for (const [r, v] of map) while (x >= v) { s += r; x -= v; }
    return s;
  };

  // ─── Boot intro ───────────────────────────────────────────
  function Boot({ done, dark }) {
    const t = tokens(dark);
    const [phase, setPhase] = useState(0);
    useEffect(() => {
      const a = setTimeout(() => setPhase(1), 380);
      const b = setTimeout(() => setPhase(2), 1100);
      const c = setTimeout(() => setPhase(3), 1900);
      const d = setTimeout(() => done(), 2500);
      return () => [a,b,c,d].forEach(clearTimeout);
    }, []);
    return (
      <div style={{
        position:'absolute', inset:0, background: t.paper, color: t.ink,
        display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center',
        fontFamily: FONTS.serif, zIndex: 50,
        transition: 'opacity .55s ease', opacity: phase >= 3 ? 0 : 1, pointerEvents: phase >= 3 ? 'none' : 'auto',
      }}>
        <div style={{ fontFamily: FONTS.mono, fontSize: 10, letterSpacing: '0.24em', color: t.inkSoft, marginBottom: 28, textTransform:'uppercase' }}>
          <span style={{ opacity: phase >= 0 ? 1 : 0, transition:'opacity .4s' }}>Estab. MMXXIV  ·  Issue No. 001  ·  Bureau of Operations</span>
        </div>
        <div style={{ position:'relative', width: 84, height: 84, marginBottom: 22 }}>
          <img src="assets/suede-mark.jpeg" alt="" style={{
            width:'100%', height:'100%', objectFit:'cover', borderRadius: 4,
            filter: dark ? 'none' : 'invert(1) hue-rotate(180deg) contrast(1.1)',
            opacity: phase >= 1 ? 1 : 0, transform: `scale(${phase >= 1 ? 1 : 0.92})`,
            transition: 'opacity .5s, transform .6s cubic-bezier(.2,.7,.3,1)',
          }} />
        </div>
        <div style={{
          fontSize: 38, lineHeight: 1, letterSpacing: '-0.02em',
          opacity: phase >= 2 ? 1 : 0, transform: `translateY(${phase >= 2 ? 0 : 6}px)`,
          transition: 'opacity .5s, transform .5s',
        }}>
          <span style={{ fontStyle:'italic' }}>Suede Labs</span>
          <span style={{ color: t.inkSoft, margin: '0 12px' }}>·</span>
          <span>Bureau of Operations</span>
        </div>
        <div style={{
          fontFamily: FONTS.mono, fontSize: 10, letterSpacing: '0.18em', color: t.inkSoft, marginTop: 18,
          opacity: phase >= 2 ? 1 : 0, transition:'opacity .5s .15s',
        }}>
          OPENING THE INDEX …
        </div>
      </div>
    );
  }

  // ─── Topbar ────────────────────────────────────────────────
  function Topbar({ dark, onToggleDark, query, setQuery, totalCount, filteredCount }) {
    const t = tokens(dark);
    return (
      <div style={{
        position:'sticky', top:0, zIndex: 20, background: t.paper,
        borderBottom: `1px solid ${t.rule}`,
      }}>
        <div style={{ display:'flex', alignItems:'center', padding:'14px 44px 12px', gap: 24 }}>
          <a href="https://suedeai.ai" target="_blank" rel="noreferrer" style={{ display:'flex', alignItems:'center', gap: 10, textDecoration:'none', color:'inherit' }}>
            <img src="assets/suede-mark.jpeg" alt="Suede Labs" style={{
              width: 30, height: 30, borderRadius: 3, objectFit:'cover',
              filter: dark ? 'none' : 'invert(1) hue-rotate(180deg) contrast(1.05)',
            }} />
            <div style={{ display:'flex', alignItems:'baseline', gap: 10, fontFamily: FONTS.serif, fontSize: 19, color: t.ink, letterSpacing:'-0.01em' }}>
              <span style={{ fontStyle:'italic' }}>Suede Labs</span>
              <span style={{ color: t.inkSoft, fontSize: 12 }}>·</span>
              <span>Bureau of Operations</span>
            </div>
          </a>
          <div style={{ flex:1 }} />
          <div style={{
            display:'flex', alignItems:'center', gap: 8,
            border: `1px solid ${t.rule}`, padding: '7px 12px', borderRadius: 2, background: t.plate, minWidth: 320,
          }}>
            <span style={{ fontFamily: FONTS.mono, fontSize: 10, color: t.inkSoft, letterSpacing:'0.18em' }}>SEARCH</span>
            <input
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              placeholder="catalogue, asset, or url…"
              style={{
                flex:1, background:'transparent', border:0, outline:'none',
                fontFamily: FONTS.serif, fontSize: 15, color: t.ink, fontStyle:'italic',
              }}
            />
            <span style={{ fontFamily: FONTS.mono, fontSize: 10, color: t.inkSoft }}>
              {query ? `${filteredCount}/${totalCount}` : totalCount}
            </span>
          </div>
          <button onClick={onToggleDark} style={{
            background:'transparent', border:`1px solid ${t.rule}`, color: t.ink,
            fontFamily: FONTS.mono, fontSize: 10, letterSpacing:'0.18em', padding:'7px 12px', cursor:'pointer', borderRadius: 2,
          }}>
            {dark ? '☼ DAY' : '☾ NIGHT'}
          </button>
        </div>
      </div>
    );
  }

  // ─── Plate (hover preview) ─────────────────────────────────
  function PlatePreview({ item, sectionTitle, secIdx, itemIdx, dark }) {
    const t = tokens(dark);
    if (!item) {
      return (
        <div style={{
          position:'sticky', top: 100, background: t.plate,
          border: `1px solid ${t.rule}`, padding: '32px 28px', borderRadius: 2,
          fontFamily: FONTS.serif, color: t.inkSoft, fontSize: 14, fontStyle:'italic', lineHeight: 1.5,
        }}>
          <div style={{ fontFamily: FONTS.mono, fontSize: 9, letterSpacing:'0.22em', color: t.inkSoft, marginBottom: 14, textTransform:'uppercase' }}>
            Plate · Reader's Aid
          </div>
          Hover an entry in the index to view its plate. The plate displays a catalogue
          number, a short description, and the canonical destination.
          <div style={{ borderTop: `1px solid ${t.ruleSoft}`, marginTop: 22, paddingTop: 14, fontFamily: FONTS.mono, fontSize: 10, color: t.inkSoft, fontStyle:'normal', letterSpacing:'0.1em' }}>
            <div>Bureau of Operations</div>
            <div>Issue 001 · Suede Labs</div>
          </div>
        </div>
      );
    }
    const host = (() => { try { return new URL(item.url).host; } catch (e) { return item.url; } })();
    return (
      <div style={{
        position:'sticky', top: 100, background: t.plate,
        border: `1px solid ${t.rule}`, padding: '24px 26px 26px', borderRadius: 2,
        fontFamily: FONTS.serif, color: t.ink,
      }}>
        <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between', borderBottom: `1px solid ${t.ruleSoft}`, paddingBottom: 10, marginBottom: 14 }}>
          <div style={{ fontFamily: FONTS.mono, fontSize: 10, letterSpacing:'0.2em', color: t.inkSoft }}>
            PL. {String(secIdx + 1).padStart(2,'0')}.{String(itemIdx + 1).padStart(2,'0')}
          </div>
          <div style={{ fontFamily: FONTS.mono, fontSize: 10, letterSpacing:'0.2em', color: t.accent }}>
            ● ACTIVE
          </div>
        </div>
        <div style={{ fontFamily: FONTS.mono, fontSize: 10, letterSpacing:'0.18em', color: t.inkSoft, marginBottom: 4, textTransform:'uppercase' }}>
          {sectionTitle}
        </div>
        <div style={{ fontSize: 30, lineHeight: 1.08, letterSpacing:'-0.015em', marginBottom: 12 }}>
          {item.label}
        </div>
        <div style={{ fontSize: 15, fontStyle:'italic', lineHeight: 1.5, color: t.inkSoft, marginBottom: 22 }}>
          {item.desc}
        </div>

        {/* "Plate" — stylized site preview, never the real iframe */}
        <div style={{
          position:'relative', height: 150, borderRadius: 2, overflow:'hidden',
          background: dark ? 'linear-gradient(180deg,#1a1714 0%,#221c17 100%)' : 'linear-gradient(180deg,#f6efe0 0%,#ebe3d0 100%)',
          border: `1px solid ${t.ruleSoft}`, marginBottom: 16,
        }}>
          {/* etched grid */}
          <div style={{
            position:'absolute', inset:0,
            backgroundImage:
              `linear-gradient(${t.ruleSoft} 1px, transparent 1px),
               linear-gradient(90deg, ${t.ruleSoft} 1px, transparent 1px)`,
            backgroundSize: '22px 22px',
          }} />
          <div style={{
            position:'absolute', left: 14, top: 12, fontFamily: FONTS.mono, fontSize: 9, letterSpacing:'0.18em', color: t.inkSoft,
          }}>
            {host}
          </div>
          <div style={{
            position:'absolute', left: 14, right: 14, top: 38,
            fontFamily: FONTS.serif, fontSize: 22, fontStyle:'italic', color: t.ink, lineHeight: 1.1,
          }}>
            {item.label}
          </div>
          <div style={{
            position:'absolute', left: 14, right: 14, top: 78, height: 6, background: t.rule, opacity: 0.4,
          }} />
          <div style={{
            position:'absolute', left: 14, right: 60, top: 92, height: 6, background: t.rule, opacity: 0.3,
          }} />
          <div style={{
            position:'absolute', left: 14, right: 90, top: 106, height: 6, background: t.rule, opacity: 0.22,
          }} />
          <div style={{
            position:'absolute', right: 14, bottom: 12, fontFamily: FONTS.mono, fontSize: 8, letterSpacing:'0.2em', color: t.inkSoft,
          }}>
            PLATE
          </div>
        </div>

        <a href={item.url} target="_blank" rel="noreferrer" style={{
          display:'flex', alignItems:'center', justifyContent:'space-between',
          fontFamily: FONTS.mono, fontSize: 11, letterSpacing:'0.12em', color: t.accent,
          borderTop: `1px solid ${t.ruleSoft}`, paddingTop: 12, textDecoration:'none',
        }}>
          <span style={{ whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis', maxWidth: '78%' }}>
            {item.url.replace(/^https?:\/\//,'')}
          </span>
          <span>→</span>
        </a>
      </div>
    );
  }

  // ─── Section ──────────────────────────────────────────────
  function Section({ section, secIdx, query, onHover, hovered, dark }) {
    const t = tokens(dark);
    const visible = useMemo(() => {
      if (!query) return section.items.map((it, i) => ({ it, i }));
      const q = query.toLowerCase();
      return section.items
        .map((it, i) => ({ it, i }))
        .filter(({ it }) =>
          it.label.toLowerCase().includes(q) ||
          (it.desc || '').toLowerCase().includes(q) ||
          it.url.toLowerCase().includes(q) ||
          section.title.toLowerCase().includes(q)
        );
    }, [query, section]);
    if (visible.length === 0) return null;
    return (
      <section id={`atlas-sec-${section.id}`} style={{ padding: '40px 0 8px', borderTop: `1px solid ${t.rule}` }}>
        <div style={{ display:'grid', gridTemplateColumns:'90px 1fr', gap: 22, marginBottom: 18 }}>
          <div style={{ fontFamily: FONTS.mono, fontSize: 11, letterSpacing:'0.2em', color: t.inkSoft, paddingTop: 6 }}>
            {section.latin}
          </div>
          <div>
            <div style={{ fontFamily: FONTS.serif, fontSize: 34, color: t.ink, letterSpacing:'-0.015em', lineHeight: 1 }}>
              {section.title}
            </div>
            <div style={{ fontFamily: FONTS.serif, fontStyle:'italic', fontSize: 15, color: t.inkSoft, marginTop: 6 }}>
              {section.sub}
            </div>
          </div>
        </div>
        <ol style={{ listStyle:'none', padding:0, margin:0 }}>
          {visible.map(({ it, i }) => {
            const isHover = hovered && hovered.url === it.url;
            return (
              <li key={it.url + i} onMouseEnter={() => onHover({ ...it, secIdx, itemIdx: i, sectionTitle: section.title })}
                onMouseLeave={() => onHover(null)}>
                <a href={it.url} target="_blank" rel="noreferrer" style={{
                  display:'grid', gridTemplateColumns:'90px 1fr auto', gap: 22, alignItems:'baseline',
                  padding: '12px 0 11px', borderBottom: `1px solid ${t.ruleSoft}`,
                  textDecoration:'none', color: t.ink, transition:'background .15s, padding .15s',
                  background: isHover ? (dark ? 'rgba(237,229,211,0.04)' : 'rgba(26,22,18,0.03)') : 'transparent',
                  paddingLeft: isHover ? 6 : 0,
                }}>
                  <span style={{ fontFamily: FONTS.mono, fontSize: 11, letterSpacing:'0.16em', color: t.inkSoft }}>
                    {roman(secIdx + 1)}·{String(i + 1).padStart(2,'0')}
                  </span>
                  <span style={{ display:'flex', alignItems:'baseline', gap: 14, minWidth: 0 }}>
                    <span style={{ fontFamily: FONTS.serif, fontSize: 22, fontStyle: isHover ? 'italic' : 'normal', letterSpacing:'-0.01em' }}>
                      {it.label}
                    </span>
                    <span style={{ flex:1, borderBottom: `1px dotted ${t.rule}`, marginBottom: 6, opacity: isHover ? 0.6 : 0.3, transition:'opacity .2s' }} />
                    <span style={{ fontFamily: FONTS.serif, fontSize: 13.5, fontStyle:'italic', color: t.inkSoft, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis', maxWidth: 360 }}>
                      {it.desc}
                    </span>
                  </span>
                  <span style={{ fontFamily: FONTS.mono, fontSize: 10, letterSpacing:'0.16em', color: isHover ? t.accent : t.inkSoft }}>
                    {it.url.replace(/^https?:\/\//,'').replace(/^www\./,'').split('/')[0]} ↗
                  </span>
                </a>
              </li>
            );
          })}
        </ol>
      </section>
    );
  }

  // ─── Main ─────────────────────────────────────────────────
  function SuedeAtlas({ dark = false, onToggleDark }) {
    const [query, setQuery] = useState('');
    const [hovered, setHovered] = useState(null);
    const [booted, setBooted] = useState(false);
    const t = tokens(dark);
    const data = window.SUEDE_DATA;
    const totalCount = data.sections.reduce((a, s) => a + s.items.length, 0);
    const filteredCount = useMemo(() => {
      if (!query) return totalCount;
      const q = query.toLowerCase();
      return data.sections.reduce((a, s) =>
        a + s.items.filter(it =>
          it.label.toLowerCase().includes(q) ||
          (it.desc||'').toLowerCase().includes(q) ||
          it.url.toLowerCase().includes(q) ||
          s.title.toLowerCase().includes(q)
        ).length, 0);
    }, [query, data, totalCount]);

    return (
      <div style={{
        position:'relative', width:'100%', height:'100%', overflow:'auto',
        background: t.paper, color: t.ink, fontFamily: FONTS.serif,
      }}>
        {!booted && <Boot dark={dark} done={() => setBooted(true)} />}

        <Topbar dark={dark} onToggleDark={onToggleDark} query={query} setQuery={setQuery}
          totalCount={totalCount} filteredCount={filteredCount} />

        {/* Hero — letterpress front matter */}
        <header style={{ padding: '64px 44px 36px', borderBottom: `1px solid ${t.rule}` }}>
          <div style={{ display:'grid', gridTemplateColumns:'1fr 320px', gap: 60, alignItems:'flex-end' }}>
            <div>
              <div style={{ fontFamily: FONTS.mono, fontSize: 10, letterSpacing:'0.26em', color: t.inkSoft, marginBottom: 22, textTransform:'uppercase' }}>
                Volume I · Issue 001 · MMXXVI · Public Index
              </div>
              <h1 style={{ fontFamily: FONTS.serif, fontSize: 92, lineHeight: 0.92, margin: 0, letterSpacing:'-0.025em', color: t.ink }}>
                <span style={{ fontStyle:'italic', fontWeight: 400 }}>An Atlas</span>
                <span style={{ color: t.inkSoft }}> of </span>
                <span style={{ fontWeight: 500 }}>Operations</span>
              </h1>
              <div style={{ fontFamily: FONTS.serif, fontSize: 18, fontStyle:'italic', color: t.inkSoft, marginTop: 22, maxWidth: 640, lineHeight: 1.45 }}>
                Catalogue of every public surface, registry, protocol and console operated by
                Suede Labs — recorded, numbered, and made available for ordinary use.
              </div>
            </div>
            <div style={{ borderLeft: `1px solid ${t.rule}`, paddingLeft: 24, fontFamily: FONTS.mono, fontSize: 11, color: t.inkSoft, lineHeight: 1.7 }}>
              <div style={{ color: t.ink, letterSpacing:'0.16em', marginBottom: 10 }}>COLOPHON</div>
              <div>{data.sections.length} fascicles</div>
              <div>{totalCount} entries</div>
              <div>set in Cormorant &amp; JetBrains Mono</div>
              <div>maintained by the Bureau</div>
              <div>last revision · today</div>
            </div>
          </div>
        </header>

        {/* Table of contents */}
        <nav style={{ padding: '22px 44px', borderBottom: `1px solid ${t.rule}`, display:'flex', gap: 28, flexWrap:'wrap' }}>
          {data.sections.map((s, i) => (
            <a key={s.id} href={`#atlas-sec-${s.id}`} style={{
              fontFamily: FONTS.mono, fontSize: 10.5, letterSpacing:'0.18em', color: t.inkSoft, textDecoration:'none',
            }}
              onMouseEnter={(e) => e.currentTarget.style.color = t.accent}
              onMouseLeave={(e) => e.currentTarget.style.color = t.inkSoft}
            >
              <span style={{ color: t.ink }}>{roman(i+1)}.</span> {s.title.toUpperCase()} <span style={{ opacity:.5 }}>({s.items.length})</span>
            </a>
          ))}
        </nav>

        {/* Body — two-column: index + plate */}
        <div style={{ padding: '0 44px 80px', display:'grid', gridTemplateColumns:'1fr 320px', gap: 60, alignItems:'flex-start' }}>
          <div>
            {data.sections.map((s, i) => (
              <Section key={s.id} section={s} secIdx={i} query={query} onHover={setHovered} hovered={hovered} dark={dark} />
            ))}
          </div>
          <aside style={{ paddingTop: 40 }}>
            <PlatePreview item={hovered} sectionTitle={hovered?.sectionTitle} secIdx={hovered?.secIdx} itemIdx={hovered?.itemIdx} dark={dark} />
          </aside>
        </div>

        {/* Footer */}
        <footer style={{ padding: '24px 44px 36px', borderTop: `1px solid ${t.rule}`, display:'flex', alignItems:'center', justifyContent:'space-between' }}>
          <a href="https://suedeai.ai" target="_blank" rel="noreferrer" style={{ display:'flex', alignItems:'center', gap: 14, textDecoration:'none', color:'inherit' }}>
            <img src="assets/suede-mark.jpeg" alt="Suede Labs" style={{
              width: 22, height: 22, borderRadius: 2, objectFit:'cover',
              filter: dark ? 'none' : 'invert(1) hue-rotate(180deg) contrast(1.05)',
            }} />
            <span style={{ fontFamily: FONTS.serif, fontStyle:'italic', fontSize: 14, color: t.ink }}>
              Suede Labs — Bureau of Operations
            </span>
          </a>
          <div style={{ fontFamily: FONTS.mono, fontSize: 10, letterSpacing:'0.18em', color: t.inkSoft }}>
            FILED · {totalCount} ENTRIES · MMXXVI
          </div>
        </footer>
      </div>
    );
  }

  return SuedeAtlas;
})();

window.SuedeAtlas = Atlas;
