/* App shell — sticky nav, tweaks panel, renders all sections */

const PAGES = [
  {
    id: 'brand',
    label: 'Brand',
    sections: [
      { id: 'overview',    n: '00', label: 'Overview' },
      { id: 'logo',        n: '01', label: 'Logo' },
      { id: 'color',       n: '02', label: 'Colour' },
      { id: 'type',        n: '03', label: 'Typography' },
      { id: 'foundations', n: '04', label: 'Foundations' },
      { id: 'iconography', n: '05', label: 'Iconography' },
      { id: 'components',  n: '06', label: 'Components' },
      { id: 'patterns',    n: '07', label: 'Patterns' },
      { id: 'messaging',   n: '08', label: 'Messaging' },
      { id: 'voice',       n: '09', label: 'Voice' },
      { id: 'assets',         n: '10', label: 'Assets' },
      { id: 'hosted-assets',  n: '11', label: 'Hosted assets' },
      { id: 'motion',         n: '12', label: 'Motion' },
    ],
  },
  {
    id: 'generators',
    label: 'Generators',
    sections: [
      { id: 'gen-logo',    n: '01', label: 'Logo' },
      { id: 'gen-banner',  n: '02', label: 'Banner & Social' },
      { id: 'gen-pattern', n: '03', label: 'Pattern' },
    ],
  },
  {
    id: 'templates',
    label: 'Templates',
    sections: [
      { id: 'tpl-overview',       n: '00', label: 'Overview' },
      { id: 'tpl-letter',         n: '01', label: 'A4 letterhead' },
      { id: 'tpl-report',         n: '02', label: 'A4 report cover' },
      { id: 'tpl-email',          n: '03', label: 'Email' },
      { id: 'tpl-signature',      n: '04', label: 'Email signature' },
      { id: 'tpl-slide',          n: '05', label: 'Slide title' },
      { id: 'tpl-invoice',        n: '06', label: 'A4 invoice' },
      { id: 'tpl-content-slide',  n: '07', label: 'Slide content' },
      { id: 'tpl-readme',         n: '08', label: 'Repo README' },
      { id: 'tpl-ticket-comment', n: '09', label: 'Ticket / PR comment' },
    ],
  },
  {
    id: 'agents',
    label: 'For agents',
    sections: [
      { id: 'llms-overview', n: '00', label: 'llms.txt' },
      { id: 'llms-assets',   n: '01', label: 'Asset URLs' },
      { id: 'llms-recipes',  n: '02', label: 'Recipes' },
      { id: 'tokens',        n: '03', label: 'Design tokens' },
      { id: 'tailwind',      n: '04', label: 'Tailwind preset' },
      { id: 'shadcn',        n: '05', label: 'shadcn/ui theme' },
    ],
  },
];

const SECTION_TO_PAGE = Object.fromEntries(
  PAGES.flatMap(p => p.sections.map(s => [s.id, p.id]))
);

/* =================================================
 * Tweaks — theme + density + accent flavour
 * ================================================= */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "density": "comfortable",
  "accent": "aureolin"
}/*EDITMODE-END*/;

function applyTweaks(t) {
  const root = document.documentElement;
  root.setAttribute('data-theme', t.theme === 'dark' ? 'dark' : 'light');
  // Density modifies body font-size baseline (14 compact, 16 comfortable, 18 cozy)
  document.body.style.fontSize = t.density === 'compact' ? '14px'
    : t.density === 'cozy' ? '17px' : '16px';
  // Accent swap
  const accents = {
    aureolin: { 50: '#FEF8B8', 300: '#FDE033', 400: '#F7EC33', 500: '#E0D420', 800: '#5A5405' },
    dodger:   { 50: '#E6F2FF', 300: '#4DABFF', 400: '#1E96FC', 500: '#0E7EDB', 800: '#0D4A82' },
    signal:   { 50: '#FFE7E3', 300: '#FF8473', 400: '#FF331F', 500: '#E01E0B', 800: '#7A0F06' },
  };
  const a = accents[t.accent] || accents.aureolin;
  Object.entries(a).forEach(([k, v]) => root.style.setProperty(`--accent-${k}`, v));
}

function TweaksPanel({ tweaks, setTweaks, onClose }) {
  const update = (patch) => {
    const next = { ...tweaks, ...patch };
    setTweaks(next);
    applyTweaks(next);
    try {
      window.parent.postMessage({ type: '__edit_mode_set_keys', edits: patch }, '*');
    } catch (e) {}
  };
  return (
    <div style={{
      position: 'fixed', right: 20, bottom: 20, zIndex: 100,
      width: 296,
      background: 'var(--bg-primary)',
      border: '1px solid var(--border-secondary)',
      borderRadius: 14,
      boxShadow: '0 24px 48px -12px rgba(16,24,40,.24)',
      overflow: 'hidden',
      fontFamily: 'var(--font-body)',
    }}>
      <div style={{
        padding: '12px 16px', borderBottom: '1px solid var(--border-tertiary)',
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        background: 'var(--bg-secondary)',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <div style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--accent-400)' }} />
          <span style={{ fontSize: 13, fontWeight: 600 }}>Tweaks</span>
        </div>
        <button onClick={onClose} style={{ border: 'none', background: 'transparent',
          cursor: 'pointer', fontSize: 16, color: 'var(--text-quaternary)' }}>×</button>
      </div>
      <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 18 }}>
        <TweakRow label="Theme" options={[
          { k: 'light', l: 'Light' }, { k: 'dark', l: 'Dark' },
        ]} value={tweaks.theme} onChange={v => update({ theme: v })} />
        <TweakRow label="Density" options={[
          { k: 'compact', l: 'Compact' }, { k: 'comfortable', l: 'Normal' }, { k: 'cozy', l: 'Cozy' },
        ]} value={tweaks.density} onChange={v => update({ density: v })} />
        <TweakRow label="Accent" options={[
          { k: 'aureolin', l: 'Aureolin', c: '#F7EC33' },
          { k: 'dodger',   l: 'Dodger',   c: '#1E96FC' },
          { k: 'signal',   l: 'Signal',   c: '#FF331F' },
        ]} value={tweaks.accent} onChange={v => update({ accent: v })} />
      </div>
    </div>
  );
}

function TweakRow({ label, options, value, onChange }) {
  return (
    <div>
      <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.08em',
        textTransform: 'uppercase', color: 'var(--text-quaternary)', marginBottom: 8 }}>{label}</div>
      <div style={{ display: 'grid', gridTemplateColumns: `repeat(${options.length}, 1fr)`, gap: 4,
        background: 'var(--bg-secondary)', padding: 3, borderRadius: 8 }}>
        {options.map(o => (
          <button key={o.k} onClick={() => onChange(o.k)} style={{
            border: 'none', padding: '6px 8px', borderRadius: 6,
            background: value === o.k ? 'var(--bg-primary)' : 'transparent',
            color: value === o.k ? 'var(--text-primary)' : 'var(--text-tertiary)',
            fontSize: 12, fontWeight: 600, cursor: 'pointer',
            boxShadow: value === o.k ? '0 1px 2px rgba(16,24,40,.08)' : 'none',
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
          }}>
            {o.c && <span style={{ width: 10, height: 10, borderRadius: 3, background: o.c, border: '1px solid rgba(0,0,0,.1)' }} />}
            {o.l}
          </button>
        ))}
      </div>
    </div>
  );
}

/* =================================================
 * Variant switcher — sticky strip above the nav that
 * lets you compare Origin / Refine / Horizon side-by-side.
 * Writes the choice to <html data-variant="…"> (drives CSS)
 * and into VariantContext (drives the mark components).
 * ================================================= */
const VARIANTS = [
  {
    id: 'origin',
    label: 'Origin',
    desc: 'Current system',
    tagline: 'Penn Blue · Aureolin · Inter',
    colors: ['#121541', '#F7EC33', '#FFFFFF'],
  },
  {
    id: 'refine',
    label: 'Refine',
    desc: 'Subtle evolution',
    tagline: 'Oxford Ink · Saffron · Fraunces + Inter',
    colors: ['#0F1336', '#D89A0C', '#F6F1E5'],
  },
  {
    id: 'horizon',
    label: 'Horizon',
    desc: 'Bold exploration',
    tagline: 'Ink Black · Electric Lime · Space Grotesk',
    colors: ['#0B0F10', '#BEF264', '#F4F4F0'],
  },
];

function VariantPreviewMark({ id, size = 20, fill }) {
  if (id === 'refine')  return <RefineArrow size={size} fill={fill} />;
  if (id === 'horizon') return <HorizonGlyph size={size} fill={fill} />;
  return <OriginArrow size={size} fill={fill} />;
}

function VariantSwitcher({ variant, setVariant }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === 'Escape') setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    document.addEventListener('keydown', onKey);
    return () => {
      document.removeEventListener('mousedown', onDoc);
      document.removeEventListener('keydown', onKey);
    };
  }, [open]);

  const current = VARIANTS.find(v => v.id === variant) || VARIANTS[0];
  const [curPrimary, curAccent] = current.colors;

  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button
        onClick={() => setOpen(o => !o)}
        title={current.tagline}
        style={{
          display: 'flex', alignItems: 'center', gap: 10,
          padding: '6px 10px 6px 6px',
          borderRadius: 8,
          background: 'var(--bg-secondary)',
          border: '1px solid var(--border-secondary)',
          color: 'var(--text-secondary)',
          fontFamily: 'inherit', cursor: 'pointer',
        }}
      >
        <span style={{
          width: 24, height: 24, borderRadius: 6, flexShrink: 0,
          background: curPrimary,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <VariantPreviewMark id={current.id} size={14} fill={curAccent} />
        </span>
        <span style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', lineHeight: 1.1 }}>
          <span style={{ fontSize: 9, fontWeight: 700, letterSpacing: '.12em',
            textTransform: 'uppercase', color: 'var(--text-quaternary)' }}>System</span>
          <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--text-primary)', marginTop: 2 }}>
            {current.label}
          </span>
        </span>
        <svg width="10" height="10" viewBox="0 0 10 10" style={{ marginLeft: 2, opacity: .6 }}>
          <path d="M2 4l3 3 3-3" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      </button>

      {open && (
        <div style={{
          position: 'absolute', top: 'calc(100% + 6px)', right: 0,
          width: 300, zIndex: 60,
          background: 'var(--bg-primary)',
          border: '1px solid var(--border-secondary)',
          borderRadius: 12,
          boxShadow: '0 16px 36px -12px rgba(16,24,40,.18)',
          padding: 6,
          display: 'flex', flexDirection: 'column', gap: 4,
        }}>
          {VARIANTS.map(v => {
            const active = variant === v.id;
            const [primary, accent, canvas] = v.colors;
            return (
              <button
                key={v.id}
                onClick={() => { setVariant(v.id); setOpen(false); }}
                title={v.tagline}
                style={{
                  display: 'flex', alignItems: 'center', gap: 10,
                  padding: '8px 10px',
                  borderRadius: 8,
                  cursor: 'pointer', textAlign: 'left',
                  background: active ? 'var(--brand-50)' : 'transparent',
                  border: '1px solid transparent',
                  fontFamily: 'inherit',
                }}
              >
                <span style={{
                  width: 30, height: 30, borderRadius: 6, flexShrink: 0,
                  background: primary,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                }}>
                  <VariantPreviewMark id={v.id} size={16} fill={accent} />
                </span>
                <span style={{ flex: 1, minWidth: 0 }}>
                  <span style={{ display: 'block', fontSize: 13, fontWeight: 600,
                    color: active ? 'var(--brand-600)' : 'var(--text-primary)' }}>
                    {v.label}
                  </span>
                  <span style={{ display: 'block', fontSize: 11, color: 'var(--text-quaternary)', marginTop: 1 }}>
                    {v.desc}
                  </span>
                </span>
                <span style={{ display: 'flex', gap: 3, flexShrink: 0 }}>
                  {v.colors.map((c, i) => (
                    <span key={i} style={{
                      width: 8, height: 8, borderRadius: 999, background: c,
                      border: '1px solid rgba(0,0,0,.08)',
                    }} />
                  ))}
                </span>
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
}

/* =================================================
 * Top chrome (header) — brand mark + page tabs.
 * Section nav lives in the left SideNav.
 * ================================================= */
function Nav({ page, setPage, variant, setVariant }) {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 10);
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  const goto = (pageId) => {
    const p = PAGES.find(p => p.id === pageId);
    if (!p) return;
    setPage(pageId);
    const first = p.sections[0]?.id;
    if (first) {
      window.location.hash = first;
      window.scrollTo({ top: 0, behavior: 'auto' });
    }
  };
  return (
    <header style={{
      position: 'sticky', top: 0, zIndex: 50,
      background: scrolled ? 'var(--bg-primary)' : 'var(--bg-canvas)',
      borderBottom: scrolled ? '1px solid var(--border-secondary)' : '1px solid transparent',
      transition: 'background .2s, border-color .2s',
    }}>
      <div style={{
        padding: '14px 40px',
        display: 'flex', alignItems: 'center', gap: 32,
      }}>
        <a
          href="#overview"
          onClick={(e) => { e.preventDefault(); goto('brand'); }}
          style={{ display: 'flex', alignItems: 'center', gap: 10, textDecoration: 'none', color: 'inherit' }}
        >
          <ArrowMark size={22} fill="var(--brand-600)" />
          <div>
            <div style={{ fontSize: 14, fontWeight: 700, letterSpacing: '-0.01em', color: 'var(--text-primary)' }}>Nexus ReGen</div>
            <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '.12em', color: 'var(--brand-500)', textTransform: 'uppercase', marginTop: 1 }}>Design System</div>
          </div>
        </a>
        <nav style={{ display: 'flex', gap: 4 }}>
          {PAGES.map(p => {
            const active = page === p.id;
            return (
              <button
                key={p.id}
                onClick={() => goto(p.id)}
                style={{
                  padding: '8px 14px',
                  borderRadius: 8,
                  border: 'none',
                  background: active ? 'var(--brand-600)' : 'transparent',
                  color: active ? 'var(--text-on-brand)' : 'var(--text-secondary)',
                  fontSize: 13,
                  fontWeight: 600,
                  cursor: 'pointer',
                  fontFamily: 'inherit',
                }}
              >
                {p.label}
              </button>
            );
          })}
        </nav>
        <div style={{ marginLeft: 'auto', display: 'flex', gap: 10, alignItems: 'center' }}>
          <ColorToolButton />
          <VariantSwitcher variant={variant} setVariant={setVariant} />
          <Badge color="accent" variant="subtle">v0.1</Badge>
        </div>
      </div>
    </header>
  );
}

/* =================================================
 * SideNav — sticky vertical section list
 * ================================================= */
function SideNav({ active, sections, label }) {
  return (
    <nav aria-label="Sections" style={{
      position: 'sticky',
      top: 80, /* header (~70) + breathing room */
      alignSelf: 'flex-start',
      width: 220,
      flexShrink: 0,
      maxHeight: 'calc(100vh - 160px)',
      overflowY: 'auto',
      paddingTop: 8,
      paddingBottom: 24,
    }}>
      <div style={{
        fontSize: 10, fontWeight: 700, letterSpacing: '.14em',
        textTransform: 'uppercase', color: 'var(--text-quaternary)',
        padding: '0 12px 10px',
      }}>{label || 'Contents'}</div>
      <ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: 1 }}>
        {sections.map(s => {
          const isActive = active === s.id;
          return (
            <li key={s.id}>
              <a href={`#${s.id}`} style={{
                display: 'flex', alignItems: 'center', gap: 10,
                padding: '8px 12px',
                borderRadius: 8,
                fontSize: 13, fontWeight: 500,
                textDecoration: 'none',
                color: isActive ? 'var(--brand-600)' : 'var(--text-tertiary)',
                background: isActive ? 'var(--brand-50)' : 'transparent',
                borderLeft: `2px solid ${isActive ? 'var(--brand-600)' : 'transparent'}`,
                paddingLeft: 14,
                transition: 'background .12s, color .12s',
              }}>
                <span style={{
                  fontFamily: 'var(--font-mono)',
                  fontSize: 11,
                  color: isActive ? 'var(--brand-500)' : 'var(--text-quaternary)',
                  minWidth: 18,
                }}>{s.n}</span>
                <span>{s.label}</span>
              </a>
            </li>
          );
        })}
      </ul>
    </nav>
  );
}

/* =================================================
 * Root
 * ================================================= */
const VARIANT_STORAGE_KEY = 'nexus.brand.variant';

function App() {
  // Resolve initial page from URL hash, falling back to 'brand'.
  const initialPage = (() => {
    const hashId = (typeof window !== 'undefined' ? window.location.hash.slice(1) : '');
    return SECTION_TO_PAGE[hashId] || 'brand';
  })();
  const [page, setPage] = useState(initialPage);
  const activePageDef = PAGES.find(p => p.id === page) || PAGES[0];
  const [active, setActive] = useState(activePageDef.sections[0].id);
  const [tweaks, setTweaks] = useState(TWEAK_DEFAULTS);
  const [tweaksOpen, setTweaksOpen] = useState(false);
  const [variant, setVariantState] = useState(() => {
    try {
      const stored = localStorage.getItem(VARIANT_STORAGE_KEY);
      if (stored === 'origin' || stored === 'refine' || stored === 'horizon') return stored;
    } catch (e) {}
    return 'origin';
  });

  const setVariant = (v) => {
    setVariantState(v);
    try { localStorage.setItem(VARIANT_STORAGE_KEY, v); } catch (e) {}
  };

  // Sync variant to <html data-variant="…"> so CSS token scopes activate.
  // Also clear any inline --accent-* overrides left by the tweaks panel so
  // the variant's canonical accent ramp wins.
  useEffect(() => {
    document.documentElement.setAttribute('data-variant', variant);
    ['25','50','100','200','300','400','500','600','700','800','900'].forEach(k => {
      document.documentElement.style.removeProperty(`--accent-${k}`);
    });
  }, [variant]);

  // Apply tweaks on mount — theme + density only, not accent (we let the
  // active variant define its own accent ramp; tweaking accent is opt-in
  // via the Tweaks panel).
  useEffect(() => {
    const root = document.documentElement;
    root.setAttribute('data-theme', TWEAK_DEFAULTS.theme === 'dark' ? 'dark' : 'light');
    document.body.style.fontSize = TWEAK_DEFAULTS.density === 'compact' ? '14px'
      : TWEAK_DEFAULTS.density === 'cozy' ? '17px' : '16px';
  }, []);

  // Scroll-spy — observes only the current page's sections.
  useEffect(() => {
    const io = new IntersectionObserver(entries => {
      entries.forEach(e => {
        if (e.isIntersecting) setActive(e.target.id);
      });
    }, { rootMargin: '-30% 0px -60% 0px' });
    activePageDef.sections.forEach(s => {
      const el = document.getElementById(s.id);
      if (el) io.observe(el);
    });
    return () => io.disconnect();
  }, [page]);

  // Sync page state when the user navigates via hash (incl. browser back/forward).
  useEffect(() => {
    const onHash = () => {
      const id = window.location.hash.slice(1);
      const targetPage = SECTION_TO_PAGE[id];
      if (targetPage && targetPage !== page) setPage(targetPage);
    };
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, [page]);

  // Tweaks bridge
  useEffect(() => {
    const onMsg = (e) => {
      const d = e.data;
      if (!d || typeof d !== 'object') return;
      if (d.type === '__activate_edit_mode') setTweaksOpen(true);
      if (d.type === '__deactivate_edit_mode') setTweaksOpen(false);
    };
    window.addEventListener('message', onMsg);
    // Announce availability after listener is registered
    try {
      window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    } catch (err) {}
    return () => window.removeEventListener('message', onMsg);
  }, []);

  return (
    <VariantContext.Provider value={{ variant, setVariant }}>
    <ColorToolProvider>
    <div>
      <Nav page={page} setPage={setPage} variant={variant} setVariant={setVariant} />
      <div style={{
        padding: '0 40px',
        display: 'flex', gap: 32, alignItems: 'flex-start',
      }}>
        <SideNav
          active={active}
          sections={activePageDef.sections}
          label={activePageDef.label}
        />
        <main style={{ flex: 1, minWidth: 0 }}>
          {page === 'brand' && (
            <>
              <S_Overview />
              <S_Logo />
              <S_Color />
              <S_Type />
              <S_Foundations />
              <S_Iconography />
              <S_Components />
              <S_Patterns />
              <S_Messaging />
              <S_Voice />
              <S_Assets />
              <S_HostedAssets />
              <S_Motion />
            </>
          )}
          {page === 'generators' && (
            <>
              <S_GenLogo />
              <S_GenBanner />
              <S_GenPattern />
            </>
          )}
          {page === 'templates' && (
            <>
              <S_TplOverview />
              <S_TplLetter />
              <S_TplReport />
              <S_TplEmail />
              <S_TplSignature />
              <S_TplSlide />
              <S_TplInvoice />
              <S_TplContentSlide />
              <S_TplReadme />
              <S_TplTicketComment />
            </>
          )}
          {page === 'agents' && (
            <>
              <S_LlmsOverview />
              <S_LlmsAssets />
              <S_LlmsRecipes />
              <S_Tokens />
              <S_Tailwind />
              <S_Shadcn />
            </>
          )}
        </main>
      </div>

      {/* Footer */}
      <footer style={{
        borderTop: '1px solid var(--border-secondary)',
        padding: '32px 40px',
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        fontSize: 13, color: 'var(--text-quaternary)',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <ArrowMark size={18} fill="var(--brand-600)" />
          Nexus ReGen Design System · v0.1 · April 2026
        </div>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12 }}>
          design@nexusregen.com
        </div>
      </footer>

      {tweaksOpen && (
        <TweaksPanel tweaks={tweaks} setTweaks={setTweaks} onClose={() => setTweaksOpen(false)} />
      )}
    </div>
    </ColorToolProvider>
    </VariantContext.Provider>
  );
}

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