/* metaglass.dev — shared UI components */

const Icon = {
  Search: () =>
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <circle cx="11" cy="11" r="7" /><path d="m21 21-4.3-4.3" />
    </svg>,

  GitHub: () =>
  <svg viewBox="0 0 24 24" fill="currentColor">
      <path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.57.1.78-.25.78-.55v-2.02c-3.2.7-3.87-1.36-3.87-1.36-.52-1.33-1.28-1.69-1.28-1.69-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.76 2.7 1.25 3.36.96.1-.75.4-1.26.73-1.55-2.55-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.29 1.19-3.1-.12-.29-.52-1.46.11-3.04 0 0 .97-.31 3.18 1.18a11 11 0 0 1 5.78 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.58.23 2.75.11 3.04.74.81 1.18 1.84 1.18 3.1 0 4.42-2.7 5.39-5.27 5.68.41.36.78 1.06.78 2.13v3.16c0 .31.21.66.79.55A11.51 11.51 0 0 0 23.5 12C23.5 5.65 18.35.5 12 .5Z" />
    </svg>,

  X: () =>
  <svg viewBox="0 0 24 24" fill="currentColor">
      <path d="M18.244 2H21.5l-7.55 8.63L23 22h-6.93l-5.42-7.08L4.4 22H1.14l8.08-9.23L1 2h7.1l4.9 6.48L18.24 2Zm-1.21 18h1.91L7.06 4H5.04l12 16Z" />
    </svg>,

  Star: () =>
  <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2 14.6 8.6 22 9.3l-5.5 4.8L18 21.3 12 17.5 6 21.3l1.5-7.2L2 9.3l7.4-.7L12 2Z" /></svg>,

  Arrow: () =>
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14M13 6l6 6-6 6" /></svg>,

  Out: () =>
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M7 17 17 7M9 7h8v8" /></svg>,

  Plus: () =>
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 5v14M5 12h14" /></svg>,

  Down: () =>
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="m6 9 6 6 6-6" /></svg>,

  Sun: () =>
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8"><circle cx="12" cy="12" r="4" /><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" /></svg>,

  Moon: () =>
  <svg viewBox="0 0 24 24" fill="currentColor"><path d="M21 14.5A9 9 0 0 1 9.5 3a1 1 0 0 0-1.3-1.2A10 10 0 1 0 22.2 15.8a1 1 0 0 0-1.2-1.3Z" /></svg>,

  Back: () =>
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M19 12H5M11 6l-6 6 6 6" /></svg>,

  Video: () =>
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polygon points="23 7 16 12 23 17 23 7" /><rect x="1" y="5" width="15" height="14" rx="2" ry="2" /></svg>,

  Link: () =>
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" /></svg>

};

function HUD() {
  const [t, setT] = React.useState(() => new Date());
  React.useEffect(() => {
    const id = setInterval(() => setT(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const fmt = t.toLocaleTimeString('en-GB', { hour12: false });
  return (
    <React.Fragment>
      <div className="hud" aria-hidden="true">
        <span className="corner tl"></span>
        <span className="corner tr"></span>
        <span className="corner bl"></span>
        <span className="corner br"></span>
      </div>
      <div className="hud-status">
        <span className="dot"></span>
        <span>SIG · STRONG</span>
        <span>·</span>
        <span>UTC {fmt}</span>
        <span>·</span>
        <span>v1.0.0 — live</span>
      </div>
    </React.Fragment>);

}

function TopBar({ search, setSearch, theme, toggleTheme, onOpenSubmit }) {
  return (
    <header className="topbar">
      <div className="topbar-inner">
        <a className="brand" href="#">
          <span className="brand-mark"></span>
          <span>metaglass.dev<span className="brand-cursor"></span></span>
        </a>
        <nav className="nav">
          <a className="nav-link active" href="#marketplace"><span className="bracket">[</span>marketplace<span className="bracket">]</span></a>
          <a className="nav-link" href="guides/web-apps.html">guides</a>
          <a className="nav-link" href="#submit" onClick={(e) => { e.preventDefault(); onOpenSubmit && onOpenSubmit(); }}>submit</a>
        </nav>
        <div className="search">
          <Icon.Search />
          <input
            placeholder="search apps…"
            value={search}
            onChange={(e) => setSearch(e.target.value)} />
          
          <span className="kbd">⌘ K</span>
        </div>
        <button className="theme-toggle" onClick={toggleTheme} aria-label="Toggle theme" title={theme === 'dark' ? 'Switch to light' : 'Switch to dark'}>
          {theme === 'dark' ? <Icon.Sun /> : <Icon.Moon />}
        </button>
      </div>
    </header>);

}

function Hero({ count, newCount }) {
  return (
    <section className="hero">
      <div className="hero-grid">
        <div>
          <div className="hero-meta">
            <span className="tag-pill">{count} apps indexed</span>
            <span className="tag-pill">community-run</span>
            <span className="tag-pill">unaffiliated · fan-built</span>
          </div>
          <h1>
            Every app worth running on <span className="accent">Meta display glasses</span>.
          </h1>
          <p className="hero-sub">
            metaglass.dev is an open registry of community apps and guides for the Meta Ray-Ban Display glasses. Browse what people are shipping, read how they built it, and put your own app on the map.
          </p>
          <div className="hero-actions">
            <a className="btn" href="guides/web-apps.html">
              start building <span className="btn-arrow">→</span>
            </a>
            <a className="btn btn-ghost" href="#marketplace">
              browse marketplace
            </a>
          </div>
        </div>
        <aside className="hero-side">
          <div className="hero-side-head">
            <span className="label">// live registry</span>
            <span>{new Date().toISOString().slice(0, 10)}</span>
          </div>
          <div className="hero-side-list">
            <div className="hero-side-row"><span className="k">apps.indexed</span><span className="v num">{count}</span></div>
            <div className="hero-side-row"><span className="k">new.this_week</span><span className="v num">{newCount}</span></div>
            <div className="hero-side-row"><span className="k">guides.published</span><span className="v num">{window.METAGLASS_GUIDES.length}</span></div>
            <div className="hero-side-row"><span className="k">categories.tracked</span><span className="v num">{window.METAGLASS_CATEGORIES.length - 1}</span></div>
            <div className="hero-side-row"><span className="k">platform</span><span className="v">Meta Ray-Ban Display</span></div>
            <div className="hero-side-row"><span className="k">sdk.opened</span><span className="v">May 15, 2026</span></div>
          </div>
        </aside>
      </div>
    </section>);

}

function Marquee({ count, newCount }) {
  const items = [
  { text: `${count} apps indexed`, accent: true },
  { text: "live on metaglass.dev" },
  { text: "fan-built · unaffiliated with Meta" },
  { text: `${newCount} new this week`, accent: true },
  { text: "submissions open" },
  { text: "v1.0.0 — live" },
  { text: "open registry" },
  { text: "tag your repo: #metaglass" },
  { text: "SDK opened May 15, 2026" },
  { text: "web apps · HTML/JS/CSS" }];

  const all = [...items, ...items];
  return (
    <div className="marquee">
      <div className="marquee-track">
        {all.map((it, i) =>
        <span className="marquee-item" key={i}>
            <span className="marquee-dot"></span>
            <span className={it.accent ? "accent" : ""}>{it.text}</span>
          </span>
        )}
      </div>
    </div>);

}

function initials(name) {
  return name.split(/[.\s_-]+/).filter(Boolean).slice(0, 2).map((p) => p[0].toUpperCase()).join('');
}

function FeaturedCard({ app, onOpen }) {
  return (
    <article className="feat-card" onClick={() => onOpen(app)}>
      <div className="feat-thumb">
        {app.image ? (
          <img className="feat-thumb-img" src={app.image} alt={app.name} loading="lazy" />
        ) : (
          <span className="feat-thumb-swatch" style={{ background: app.color }}></span>
        )}
        <span className="feat-thumb-tag">{app.category}</span>
        {!app.image && <span className="feat-thumb-label">// preview</span>}
      </div>
      <h3 className="feat-name">{app.name}{app.new && <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--accent)', letterSpacing: '0.06em', textTransform: 'uppercase', marginLeft: 6 }}>new</span>}</h3>
      <p className="feat-tagline">{app.tagline}</p>
      <div className="feat-foot">
        <div className="author">
          <span className="avatar">{initials(app.author.name)}</span>
          <span>{app.author.name}</span>
        </div>
        <span className="feat-cat">{app.category}</span>
      </div>
    </article>);

}

function Filters({ categories, active, setActive, sort, setSort, counts }) {
  const sorts = ["Featured", "Newest", "A-Z"];
  return (
    <div className="filters">
      <div className="chips">
        {categories.map((cat) =>
        <button
          key={cat}
          className={`chip ${active === cat ? 'active' : ''}`}
          onClick={() => setActive(cat)}>
          
            {cat}
            <span className="chip-count">{counts[cat] ?? 0}</span>
          </button>
        )}
      </div>
      <div className="sort">
        <span>sort:</span>
        <div className="sort-btns">
          {sorts.map((s) =>
          <button
            key={s}
            className={`sort-btn ${sort === s ? 'active' : ''}`}
            onClick={() => setSort(s)}>
            {s.toLowerCase()}</button>
          )}
        </div>
      </div>
    </div>);

}

function AppRow({ app, onOpen, index }) {
  return (
    <article className="approw" onClick={() => onOpen(app)}>
      <div className="approw-thumb">
        {app.image ? (
          <img className="approw-thumb-img" src={app.image} alt={app.name} loading="lazy" />
        ) : (
          <span className="approw-thumb-swatch" style={{ background: app.color }}></span>
        )}
        {!app.image && <span className="approw-thumb-label">// {String(index + 1).padStart(3, '0')}</span>}
      </div>
      <div className="approw-body">
        <div className="approw-head">
          <h3 className="approw-name">{app.name}</h3>
          <span className={`approw-cat ${app.new ? 'new' : ''}`}>{app.new ? 'new · ' : ''}{app.category}</span>
        </div>
        <p className="approw-tagline">{app.tagline}</p>
        <div className="approw-author">
          <span className="avatar" style={{ width: 16, height: 16, fontSize: 8 }}>{initials(app.author.name)}</span>
          <span>by {app.author.name}</span>
          <span className="sep">·</span>
          <span>updated {app.updated} ago</span>
          {app.repo && <React.Fragment><span className="sep">·</span><span>{app.repo}</span></React.Fragment>}
        </div>
      </div>
      <div className="approw-actions" onClick={(e) => e.stopPropagation()}>
        {app.repo ? (
          <a className="icon-btn" href={`https://github.com/${app.repo}`} target="_blank" rel="noreferrer" title="View on GitHub"><Icon.GitHub /></a>
        ) : (
          <span className="icon-btn disabled" title="No GitHub repo linked" aria-disabled="true"><Icon.GitHub /></span>
        )}
        {app.x ? (
          <a className="icon-btn" href={`https://x.com/${app.x}`} target="_blank" rel="noreferrer" title="X"><Icon.X /></a>
        ) : (
          <span className="icon-btn disabled" title="No X profile linked" aria-disabled="true"><Icon.X /></span>
        )}
        {app.video && (
          <a className="icon-btn" href={app.video} target="_blank" rel="noreferrer" title="Watch video"><Icon.Video /></a>
        )}
      </div>
    </article>);

}

function SubmitCTA({ onOpenSubmit }) {
  return (
    <div className="submit-cta" id="submit">
      <div className="submit-cta-body">
        <h3>Built something? Put it on the map.</h3>
        <p className="dim-2">Submissions are reviewed by hand. We accept public GitHub repos or live web apps with a working demo, even if it's rough — early experiments are welcome.</p>
      </div>
      <div className="submit-cta-actions">
        <button type="button" className="btn" onClick={onOpenSubmit}>
          submit an app <Icon.Plus />
        </button>
      </div>
    </div>);

}

function Footer({ onOpenSubmit }) {
  return (
    <footer className="foot">
      <div>
        <h4>metaglass.dev</h4>
        <p className="legal">An open, community-run registry of apps and guides for Meta display glasses. Not affiliated with, endorsed by, or operated by Meta Platforms, Inc. All trademarks belong to their owners.</p>
      </div>
      <div>
        <h4>Browse</h4>
        <a href="#marketplace">Marketplace</a>
        <a href="#featured">Featured</a>
        <a href="https://glassapps.io" target="_blank" rel="noreferrer">GlassApps.io</a>
      </div>
      <div>
        <h4>Build</h4>
        <a href="https://developers.meta.com/blog/build-for-display-glasses/" target="_blank" rel="noreferrer">Official Meta Docs</a>
        <a href="https://github.com/facebookincubator/meta-wearables-webapp" target="_blank" rel="noreferrer">Meta AI Toolkit</a>
        <a href="https://github.com/levin-riegner/lr-rbm-demos" target="_blank" rel="noreferrer">L+R Demos</a>
        <a href="https://glasskit.ai/" target="_blank" rel="noreferrer">GlassKit</a>
      </div>
      <div>
        <h4>Project</h4>
        <a href="#submit" onClick={(e) => { e.preventDefault(); onOpenSubmit && onOpenSubmit(); }}>Submit an app</a>
        <a href="https://x.com/m_j_fox" target="_blank" rel="noreferrer">X</a>
      </div>
    </footer>);

}

/* ===== Build drawer ===== */
function BuildDrawer({ open, onClose }) {
  React.useEffect(() => {
    const onKey = (e) => {if (e.key === 'Escape') onClose();};
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  return (
    <React.Fragment>
      <div className={`drawer-backdrop ${open ? 'open' : ''}`} onClick={onClose}></div>
      <aside className={`drawer ${open ? 'open' : ''}`} aria-hidden={!open}>
        <div className="drawer-head">
          <span className="drawer-eyebrow">/ build for display glasses</span>
          <button className="drawer-close" onClick={onClose} aria-label="Close">✕</button>
        </div>
        <div className="drawer-body">
          <h2>Build apps that live in the corner of your vision.</h2>
          <p className="lede">Meta opened the Web App SDK for Ray-Ban Display glasses on May 15, 2026. Ship HTML/JS/CSS apps that render directly on the in-lens display.</p>

          <section className="drawer-section">
            <header className="drawer-section-head">
              <span className="num">01 / OVERVIEW</span>
              <span className="title">What the glasses can do</span>
            </header>
            <div className="capability-grid">
              <div className="capability hud">
                <div className="icon"></div>
                <h4>HUD overlays</h4>
                <p>Render web apps on the in-lens monocular display. Designed for glanceable, peripheral content.</p>
              </div>
              <div className="capability voice">
                <div className="icon"></div>
                <h4>Voice + Neural Band</h4>
                <p>Input via EMG wristband (pinch, swipe, rotate) and voice commands. No touch screen needed.</p>
              </div>
              <div className="capability gesture">
                <div className="icon"></div>
                <h4>Head tracking</h4>
                <p>DeviceOrientation API for head gesture detection. Nod, shake, tilt — all without Neural Band.</p>
              </div>
            </div>
          </section>

          <section className="drawer-section">
            <header className="drawer-section-head">
              <span className="num">02 / QUICKSTART</span>
              <span className="title">Your first web app</span>
            </header>
            <div className="step">
              <div className="n">01</div>
              <div>
                <h5>Build a standard web app</h5>
                <p>Any HTML/CSS/JS app works. No special SDK required — just standard web technologies hosted on HTTPS.</p>
                <pre className="code"><span className="com"># Any framework works — React, Vue, vanilla, etc.</span>{'\n'}<span className="kw">npx</span> create-vite my-glasses-app --template vanilla</pre>
              </div>
            </div>
            <div className="step">
              <div className="n">02</div>
              <div>
                <h5>Design for the display</h5>
                <p>The display is monocular, in the right lens. Use dark backgrounds (black = transparent on additive display), high contrast text, and glanceable layouts.</p>
                <pre className="code"><span className="com">/* Dark theme for additive display */</span>{'\n'}body {'{'} background: <span className="str">#000</span>; color: <span className="str">#fff</span>; {'}'}</pre>
              </div>
            </div>
            <div className="step">
              <div className="n">03</div>
              <div>
                <h5>Deploy and add as Web App</h5>
                <p>Host on any HTTPS server (Vercel, Netlify, GitHub Pages). Then add the URL as a Web App in the Meta View app on your phone.</p>
                <pre className="code"><span className="com"># Deploy to Vercel</span>{'\n'}<span className="kw">vercel</span> --prod</pre>
              </div>
            </div>
          </section>

          <section className="drawer-section">
            <header className="drawer-section-head">
              <span className="num">03 / RESOURCES</span>
              <span className="title">Developer resources</span>
            </header>
            {window.METAGLASS_GUIDES.map((g) =>
            <a className="guide" href={g.url} target="_blank" rel="noreferrer" key={g.id}>
                <div className="guide-thumb"><span className="num">{g.num}</span></div>
                <div>
                  <div className="guide-tag">{g.tag}</div>
                  <div className="guide-title">{g.title}</div>
                </div>
                <div className="guide-read">{g.read} →</div>
              </a>
            )}
          </section>

          <section className="drawer-section">
            <header className="drawer-section-head">
              <span className="num">04 / SPECS</span>
              <span className="title">Hardware reference</span>
            </header>
            <div className="spec-table">
              {window.METAGLASS_SPECS.map(([k, v]) =>
              <div className="spec-row" key={k}>
                  <span className="k">{k}</span>
                  <span className="v">{v}</span>
                </div>
              )}
            </div>
          </section>

          <section className="drawer-section">
            <header className="drawer-section-head">
              <span className="num">05 / OFFICIAL</span>
              <span className="title">From Meta</span>
            </header>
            <a className="outlink" href="https://developers.meta.com/blog/build-for-display-glasses/" target="_blank" rel="noreferrer">
              <span>developers.meta.com / build-for-display-glasses</span>
              <span className="arrow"><Icon.Out /></span>
            </a>
            <a className="outlink" href="https://github.com/facebookincubator/meta-wearables-webapp" target="_blank" rel="noreferrer" style={{marginTop: 8}}>
              <span>Meta Wearables Web App AI Toolkit</span>
              <span className="arrow"><Icon.Out /></span>
            </a>
          </section>
        </div>
      </aside>
    </React.Fragment>);

}

/* ===== App detail drawer ===== */
function AppDrawer({ app, onClose, onOpenOther, allApps }) {
  React.useEffect(() => {
    const onKey = (e) => {if (e.key === 'Escape' && app) onClose();};
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose, app]);

  React.useEffect(() => {
    if (app) {
      const body = document.querySelector('.appdrawer-body');
      if (body) body.scrollTop = 0;
    }
  }, [app]);

  const related = React.useMemo(() => {
    if (!app) return [];
    return allApps.filter((a) => a.id !== app.id && a.category === app.category).slice(0, 3);
  }, [app, allApps]);

  const open = !!app;
  return (
    <React.Fragment>
      <div className={`drawer-backdrop ${open ? 'open' : ''}`} onClick={onClose}></div>
      <aside className={`appdrawer ${open ? 'open' : ''}`} aria-hidden={!open}>
        {app &&
        <React.Fragment>
            <div className="appdrawer-head">
              <button className="appdrawer-back" onClick={onClose}>
                <Icon.Back /> back to catalog
              </button>
              <button className="drawer-close" onClick={onClose} aria-label="Close">✕</button>
            </div>
            <div className="appdrawer-body">
              <header className="appdrawer-hero">
                <div className="appdrawer-icon">
                  {app.image ? (
                    <img className="appdrawer-icon-img" src={app.image} alt={app.name} />
                  ) : (
                    <React.Fragment>
                      <span className="swatch" style={{ background: app.color }}></span>
                      <span className="label">// icon</span>
                    </React.Fragment>
                  )}
                </div>
                <div>
                  <div className="appdrawer-meta-top">
                    <span className={`appdrawer-cat ${app.new ? 'new' : ''}`}>{app.new ? 'new · ' : ''}{app.category}</span>
                    {app.featured && <span className="appdrawer-cat" style={{ color: 'var(--accent)', borderColor: 'color-mix(in oklch, var(--accent) 40%, var(--line))' }}>★ featured</span>}
                  </div>
                  <h1 className="appdrawer-name">{app.name}</h1>
                  <p className="appdrawer-tagline">{app.tagline}</p>
                  <div className="appdrawer-byline">
                    <span className="avatar" style={{ width: 18, height: 18, fontSize: 9 }}>{initials(app.author.name)}</span>
                    <span>by {app.author.name}</span>
                    <span className="sep">·</span>
                    <span>updated {app.updated} ago</span>
                  </div>
                  <div className="appdrawer-actions">
                    {app.appUrl &&
                  <a className="btn accent" href={app.appUrl} target="_blank" rel="noreferrer">
                        open app <Icon.Out />
                      </a>
                  }
                    {app.repo ? (
                      <a className="btn btn-ghost" href={`https://github.com/${app.repo}`} target="_blank" rel="noreferrer">
                        <Icon.GitHub /> view repo
                      </a>
                    ) : (
                      <span className="btn btn-ghost disabled" aria-disabled="true" title="No GitHub repo linked">
                        <Icon.GitHub /> no repo
                      </span>
                    )}
                    {app.x ? (
                      <a className="btn btn-ghost" href={`https://x.com/${app.x}`} target="_blank" rel="noreferrer">
                        <Icon.X /> @{app.x}
                      </a>
                    ) : (
                      <span className="btn btn-ghost disabled" aria-disabled="true">
                        <Icon.X /> no profile
                      </span>
                    )}
                    {app.video &&
                      <a className="btn btn-ghost" href={app.video} target="_blank" rel="noreferrer">
                        <Icon.Video /> watch demo
                      </a>
                    }
                  </div>
                </div>
              </header>

              <div className="appdrawer-content">
                {app.image ? (
                  <div className="appdrawer-screenshot has-image">
                    <img src={app.image} alt={`${app.name} screenshot`} loading="lazy" />
                  </div>
                ) : (
                  <div className="appdrawer-screenshot">
                    <span className="label">// screenshot not available</span>
                    <div className="frame" style={{ borderColor: app.color }}>{app.name}</div>
                  </div>
                )}

                <header className="appdrawer-section-head">
                  <span className="num">01 / ABOUT</span>
                  <span className="title">What it does</span>
                </header>
                <div className="appdrawer-prose">
                  {(app.description || app.tagline).split('\n\n').map((para, i) =>
                <p key={i}>{para}</p>
                )}
                </div>

                <div className="appdrawer-side">
                  <div>
                    <header className="appdrawer-section-head">
                      <span className="num">02 / DETAILS</span>
                      <span className="title">At a glance</span>
                    </header>
                    <div className="appdrawer-statlist">
                      <div className="row"><span className="k">author</span><span className="v">{app.author.name}</span></div>
                      {app.x && <div className="row"><span className="k">x</span><span className="v"><a href={`https://x.com/${app.x}`} target="_blank" rel="noreferrer">@{app.x}</a></span></div>}
                      {app.repo && <div className="row"><span className="k">repo</span><span className="v"><a href={`https://github.com/${app.repo}`} target="_blank" rel="noreferrer">github.com/{app.repo}</a></span></div>}
                      <div className="row"><span className="k">category</span><span className="v">{app.category.toLowerCase()}</span></div>
                      <div className="row"><span className="k">updated</span><span className="v">{app.updated} ago</span></div>
                      {app.appUrl &&
                    <div className="row"><span className="k">live app</span><span className="v"><a href={app.appUrl} target="_blank" rel="noreferrer">↗ open</a></span></div>
                    }
                      {app.video &&
                    <div className="row"><span className="k">demo</span><span className="v"><a href={app.video} target="_blank" rel="noreferrer">↗ watch</a></span></div>
                    }
                      {app.sourceUrl &&
                    <div className="row"><span className="k">source</span><span className="v"><a href={app.sourceUrl} target="_blank" rel="noreferrer">glassapps.io</a></span></div>
                    }
                    </div>
                  </div>

                  <div>
                    <header className="appdrawer-section-head">
                      <span className="num">03 / RELATED</span>
                      <span className="title">More in {app.category.toLowerCase()}</span>
                    </header>
                    {related.length === 0 ?
                  <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--ink-3)', padding: '12px 0' }}>// nothing else here yet — be the second.</div> :
                  related.map((r) =>
                  <div className="appdrawer-relrow" key={r.id} onClick={() => onOpenOther(r)}>
                        <span className="swatch" style={{ background: r.color }}></span>
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div className="name">{r.name}</div>
                          <div className="tag">{r.tagline.slice(0, 60)}{r.tagline.length > 60 ? '…' : ''}</div>
                        </div>
                        <Icon.Arrow />
                      </div>
                  )}
                  </div>
                </div>
              </div>
            </div>
          </React.Fragment>
        }
      </aside>
    </React.Fragment>);

}

function SubmitModal({ open, onClose }) {
  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  return (
    <React.Fragment>
      <div className={`drawer-backdrop ${open ? 'open' : ''}`} onClick={onClose}></div>
      <div className={`submit-modal ${open ? 'open' : ''}`} role="dialog" aria-modal="true" aria-hidden={!open}>
        <div className="submit-modal-card">
          <div className="submit-modal-head">
            <span className="drawer-eyebrow">/ submit an app</span>
            <button className="drawer-close" onClick={onClose} aria-label="Close">✕</button>
          </div>
          <div className="submit-modal-body">
            <h2>Tag me on X so I can review and add it.</h2>
            <p className="lede">Post about your app and tag <strong>@m_j_fox</strong>. Public GitHub repos or live web apps both welcome — early experiments are fine.</p>
            <div className="submit-modal-actions">
              <a className="btn accent" href="https://x.com/m_j_fox" target="_blank" rel="noreferrer">
                <Icon.X /> open @m_j_fox <Icon.Out />
              </a>
              <button type="button" className="btn btn-ghost" onClick={onClose}>close</button>
            </div>
          </div>
        </div>
      </div>
    </React.Fragment>);

}

Object.assign(window, {
  Icon, HUD, TopBar, Hero, Marquee, FeaturedCard, Filters, AppRow,
  SubmitCTA, Footer, BuildDrawer, AppDrawer, SubmitModal, initials
});
