/* sema ikutoke Collections — single-file React prototype */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ─── tweak defaults ─── */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "cream",
  "pair": "editorial",
  "hero": "split",
  "pricing": "trio",
  "checkout": "drawer",
  "canvas": "dots"
}/*EDITMODE-END*/;

/* ─── data ─── */
const COVER_STYLES = [
  // 8 distinct cover gradients for templates / tiles
  { bg: "linear-gradient(135deg, #E14118 0%, #1B1410 70%)", tag: "Vinyl Co." },
  { bg: "linear-gradient(160deg, #1B8B53 0%, #F1E8D1 100%)", tag: "Pasture" },
  { bg: "radial-gradient(60% 60% at 30% 30%, #F1582E, #14110D 70%)", tag: "Embers" },
  { bg: "linear-gradient(135deg, #2D261F 0%, #C2421A 100%)", tag: "Atelier 03" },
  { bg: "linear-gradient(45deg, #5D2BD0 0%, #F4DCD2 90%)", tag: "Stayed" },
  { bg: "radial-gradient(circle at 30% 30%, #FFC83D, #C2421A 60%, #14110D 100%)", tag: "Sun&Co" },
  { bg: "linear-gradient(135deg, #0E2740 0%, #E14118 95%)", tag: "Nightline" },
  { bg: "linear-gradient(180deg, #F8F1DD 0%, #1B8B53 100%)", tag: "Greenroom" },
];

const TEMPLATES = [
  { id: "t1", name: "Quiet Pages", cat: "Writers", price: "KSh 0", note: "Free template" },
  { id: "t2", name: "Pasture & Light", cat: "Photographers", price: "KSh 2,400" },
  { id: "t3", name: "Atelier 03", cat: "Designers", price: "KSh 1,800" },
  { id: "t4", name: "Field Notes", cat: "Writers", price: "KSh 1,200" },
  { id: "t5", name: "Embers", cat: "Musicians", price: "KSh 2,000" },
  { id: "t6", name: "Stayed", cat: "Course creators", price: "KSh 3,200" },
  { id: "t7", name: "Sun & Co.", cat: "Illustrators", price: "KSh 1,500" },
  { id: "t8", name: "Nightline", cat: "Podcasters", price: "KSh 2,000" },
  { id: "t9", name: "Greenroom", cat: "Filmmakers", price: "KSh 2,800" },
];

const TICKER = [
  "M-PESA Live · 12,847 collections sold today",
  "Nairobi · Mombasa · Kisumu · Eldoret · Lagos · Kigali · Cape Town · Accra",
  "Avg. payout 11s after STK approval",
  "Built in Nairobi, made for makers everywhere",
  "Bridging KSh, USD, GHS, NGN, ZAR — settled in your wallet",
];

const HOW_STEPS = [
  { n: "01", title: "Compose.", body: "Pick a shell, drag in your work. sema ikutoke becomes the single source of truth for your collection.", line: "▸ builder · blocks · drag & drop" },
  { n: "02", title: "Distribute.", body: "One click syncs your catalog to WhatsApp, Instagram, Facebook, TikTok — and your own site.", line: "▸ WA · IG · FB · TT · Jumia" },
  { n: "03", title: "Get paid.", body: "Buyer tap. M-PESA STK pushes to their phone. Money in your wallet in seconds, every channel.", line: "▸ M-PESA · settle in 11s" },
];

/* ─── view router stage names ─── */
const VIEWS = [
  ["landing", "Landing"],
  ["signup", "Sign up"],
  ["templates", "Templates"],
  ["builder", "Builder"],
  ["channels", "Channels"],
  ["store", "Storefront"],
  ["checkout", "Checkout"],
  ["dashboard", "Dashboard"],
];

/* ═══════════════════════════════════════════════════════════════════════
   Reusable bits
   ═══════════════════════════════════════════════════════════════════════ */
function Brand() {
  return (
    <div className="brand">
      <span className="glyph">R</span>
      sema ikutoke <small>· Collections</small>
    </div>
  );
}

function TopNav({ goto, view }) {
  return (
    <header className="topnav">
      <Brand />
      <nav className="nav-links">
        <a onClick={() => goto("templates")} style={{cursor:"pointer"}}>Templates</a>
        <a onClick={() => goto("builder")} style={{cursor:"pointer"}}>Builder</a>
        <a onClick={() => goto("channels")} style={{cursor:"pointer"}}>Channels</a>
        <a onClick={() => goto("dashboard")} style={{cursor:"pointer"}}>Dashboard</a>
        <a style={{cursor:"pointer"}}>Pricing</a>
      </nav>
      <div className="nav-actions">
        <button className="btn btn-ghost btn-sm" onClick={() => goto("signup")}>Sign in</button>
        <button className="btn btn-primary btn-sm" onClick={() => goto("signup")}>
          Start free <span className="arrow" />
        </button>
      </div>
    </header>
  );
}

function Ticker() {
  const items = [...TICKER, ...TICKER, ...TICKER];
  return (
    <div className="ticker">
      <div className="ticker-track">
        {items.map((t, i) => (
          <span key={i}><i className="dot" /> {t}</span>
        ))}
      </div>
    </div>
  );
}

function ProtoNav({ view, goto }) {
  return (
    <div className="proto-nav" role="navigation" aria-label="Prototype steps">
      {VIEWS.map(([v, label], i) => (
        <button
          key={v}
          className={view === v ? "active" : ""}
          onClick={() => goto(v)}
        >
          {String(i+1).padStart(2,"0")} {label}
        </button>
      ))}
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════════
   LANDING
   ═══════════════════════════════════════════════════════════════════════ */
function HeroSplit({ goto }) {
  return (
    <section className="hero">
      <div className="hero-grid">
        <div>

          <h1 className="h-display">
            Make a <em>place</em><br />
            for what <span className="underline-mark">you make</span>.
          </h1>
          <p className="h-sub">
            sema ikutoke is a small, opinionated builder for selling digital things —
            ebooks, presets, courses, lookbooks, beats — directly to anyone with
            a phone. Built around M-PESA. Loved by clean designers everywhere.
          </p>
          <div className="hero-actions">
            <button className="btn btn-primary btn-lg" onClick={() => goto("signup")}>
              Start a collection <span className="arrow" />
            </button>
            <button className="btn btn-outline btn-lg" onClick={() => goto("templates")}>
              Browse templates
            </button>
            <span className="meta">No card. KSh 0 / mo while you build.</span>
          </div>
        </div>
        <HeroCardStack />
      </div>
    </section>
  );
}

function HeroCentered({ goto }) {
  return (
    <section className="hero" style={{textAlign:"center", paddingBottom:60}}>
      <div className="eyebrow" style={{margin:"0 auto 32px"}}>
        <span className="chip mint" style={{padding:"2px 6px"}}>LIVE</span>
        Now in 14 markets across East &amp; West Africa
      </div>
      <h1 className="h-display" style={{maxWidth:"16ch", margin:"0 auto 28px"}}>
        A <em>quieter</em> way to sell what you <span className="underline-mark">make.</span>
      </h1>
      <p className="h-sub" style={{margin:"0 auto 32px"}}>
        sema ikutoke Collections is a small builder for digital makers. Compose a page.
        Take payment via M-PESA. Get on with making things.
      </p>
      <div className="hero-actions" style={{justifyContent:"center"}}>
        <button className="btn btn-primary btn-lg" onClick={() => goto("signup")}>
          Start free <span className="arrow" />
        </button>
        <button className="btn btn-outline btn-lg" onClick={() => goto("templates")}>
          Templates
        </button>
      </div>
      <div style={{marginTop:56, maxWidth:880, margin:"56px auto 0"}}>
        <HeroCardStack />
      </div>
    </section>
  );
}

function HeroEditorial({ goto }) {
  return (
    <section className="hero" style={{paddingBottom:60}}>
      <div style={{display:"grid", gridTemplateColumns:"180px 1fr", gap:32, marginBottom:32, alignItems:"end", borderBottom:"1px solid var(--line)", paddingBottom:24}}>
        <div className="mono">Issue 14 · 2026<br/>Nairobi</div>
        <div className="mono" style={{textAlign:"right"}}>sema ikutoke Collections · A builder for digital makers</div>
      </div>
      <h1 className="h-display" style={{fontSize:"clamp(72px, 11vw, 180px)", textAlign:"center", marginBottom:40}}>
        Sell what you <em>made</em>.
      </h1>
      <div style={{display:"grid", gridTemplateColumns:"1fr 1.4fr 1fr", gap:48, alignItems:"start"}}>
        <p className="mono" style={{lineHeight:1.6, fontSize:11}}>
          ESTABLISHED in Nairobi · Settles in 11 seconds · For writers, photographers,
          designers, course creators, musicians, illustrators, podcasters &amp; filmmakers.
        </p>
        <div style={{textAlign:"center"}}>
          <p className="h-sub" style={{margin:"0 auto 24px"}}>
            A small, opinionated tool for putting your digital work online &amp; getting
            paid for it via M-PESA. No theme store. No upsells. No 30-step funnel.
          </p>
          <div className="hero-actions" style={{justifyContent:"center"}}>
            <button className="btn btn-primary btn-lg" onClick={() => goto("signup")}>
              Begin <span className="arrow" />
            </button>
            <button className="btn btn-outline btn-lg" onClick={() => goto("templates")}>
              See templates
            </button>
          </div>
        </div>
        <p className="mono" style={{lineHeight:1.6, fontSize:11, textAlign:"right"}}>
          M-PESA Daraja · STK push · Card support · USD payouts · No-code editor ·
          Drag-and-drop · Cmd-K everywhere · Open transparently.
        </p>
      </div>
    </section>
  );
}

function HeroCardStack() {
  return (
    <div className="hero-card-stack">
      <div className="hcard hcard-back-2">
        <div className="hcard-hd"><span className="lights"><i/><i/><i/></span><code>collection-22</code></div>
      </div>
      <div className="hcard hcard-back">
        <div className="hcard-hd"><span className="lights"><i/><i/><i/></span><code>collection-19</code></div>
      </div>
      <div className="hcard hcard-main">
        <div className="hcard-hd">
          <span className="lights"><i/><i/><i/></span>
          <code>kamau.sema-ikutoke.so</code>
        </div>
        <div className="hcard-body">
          <div className="hc-cover" />
          <div className="hc-meta">
            <b>Field Notes Vol. 03</b>
            <span className="price">KSh 1,200</span>
          </div>
          <div className="hc-meta" style={{fontSize:12, color:"var(--ink-soft)"}}>
            <span>23 photographs · 14 essays · 42 MB</span>
            <span>★ 4.9 / 312</span>
          </div>
          <div className="hc-mpesa">
            <span className="mint-tag">M-PESA</span>
            STK push sent to <b style={{margin:"0 4px"}}>+254 7•• ••• 421</b>
          </div>
        </div>
      </div>
    </div>
  );
}

function HowItWorks() {
  return (
    <section>
      <div className="section-hd">
        <div>
          <div className="no">§ 01 / Method</div>
          <h2>Three steps. <em>No fuss.</em></h2>
        </div>
        <div className="right">Average creator ships in 38 min</div>
      </div>
      <div className="steps">
        {HOW_STEPS.map((s) => (
          <div className="step" key={s.n}>
            <div className="num">{s.n}</div>
            <h3>{s.title}</h3>
            <p>{s.body}</p>
            <div className="icon-line">{s.line}</div>
          </div>
        ))}
      </div>
    </section>
  );
}

function ChannelsStrip({ goto }) {
  const items = [
    { mark: "WA", name: "WhatsApp", color: "#1B8B53", note: "STK push from chat" },
    { mark: "IG", name: "Instagram", color: "#E14118", note: "Shoppable posts" },
    { mark: "FB", name: "Facebook", color: "#0E2740", note: "FB Shop sync" },
    { mark: "TT", name: "TikTok", color: "#161210", note: "Live shopping" },
    { mark: "JU", name: "Jumia", color: "#F1582E", note: "Digital catalog" },
    { mark: "RI", name: "Your site", color: "#5D2BD0", note: ".sema-ikutoke.so" },
  ];
  return (
    <section>
      <div className="section-hd">
        <div>
          <div className="no">§ 02 / Distribution</div>
          <h2>Built once. <em>Sold everywhere.</em></h2>
        </div>
        <div className="right" onClick={() => goto("channels")} style={{cursor:"pointer", textDecoration:"underline"}}>
          See all channels →
        </div>
      </div>
      <div style={{display:"grid", gridTemplateColumns:"repeat(6, 1fr)", gap:12}}>
        {items.map((c) => (
          <div key={c.mark} onClick={() => goto("channels")} className="ch-strip-card">
            <div className="chan-mark" style={{background: c.color}}>{c.mark}</div>
            <div>
              <div style={{fontFamily:"var(--serif)", fontSize:20, lineHeight:1.1}}>{c.name}</div>
              <div className="mono" style={{color:"var(--ink-faint)", fontSize:10, marginTop:3}}>{c.note}</div>
            </div>
          </div>
        ))}
      </div>
      <div className="ch-promise">
        <span className="mono" style={{color:"color-mix(in srgb, var(--paper) 60%, transparent)"}}>
          § THE PROMISE
        </span>
        <span style={{fontFamily:"var(--serif)", fontStyle:"italic", fontSize:22, lineHeight:1.2}}>
          One catalog. One inbox. One M-PESA wallet. <span style={{color:"var(--accent)"}}>No spreadsheet.</span>
        </span>
        <span style={{flex:1}} />
        <button className="btn btn-primary btn-sm" onClick={() => goto("channels")}>
          See how it works <span className="arrow"/>
        </button>
      </div>
    </section>
  );
}

function TemplatesStrip({ goto }) {
  const featured = TEMPLATES.slice(0, 5);
  return (
    <section>
      <div className="section-hd">
        <div>
          <div className="no">§ 03 / Collection</div>
          <h2>Pick a <em>shell</em>.</h2>
        </div>
        <div className="right" onClick={() => goto("templates")} style={{cursor:"pointer", textDecoration:"underline"}}>
          See all 64 templates →
        </div>
      </div>
      <div className="tiles">
        <div className="tile tile-span-6" onClick={() => goto("builder")}>
          <div className="thumb" style={{background: COVER_STYLES[0].bg}}>
            <div style={{position:"absolute", bottom:18, left:22, color:"#F1E8D1", fontFamily:"var(--serif)", fontStyle:"italic", fontSize:38, letterSpacing:"-.02em"}}>
              Quiet Pages
            </div>
            <span className="chip accent" style={{position:"absolute", top:14, left:14}}>Editor's pick</span>
          </div>
          <div className="info">
            <span className="cat">Writers · Essays · Free</span>
            <span className="name">Quiet Pages</span>
            <div className="row"><span>By sema ikutoke Studio</span><span className="price">Free</span></div>
          </div>
        </div>
        {featured.slice(1, 5).map((t, i) => (
          <div key={t.id} className="tile tile-span-3" onClick={() => goto("builder")}>
            <div className="thumb" style={{background: COVER_STYLES[i+1].bg, position:"relative"}}>
              <div style={{position:"absolute", bottom:14, left:16, color:"#F1E8D1", fontFamily:"var(--serif)", fontStyle:"italic", fontSize:22}}>
                {t.name}
              </div>
            </div>
            <div className="info">
              <span className="cat">{t.cat}</span>
              <span className="name" style={{fontSize:18}}>{t.name}</span>
              <div className="row"><span>23 blocks</span><span className="price">{t.price}</span></div>
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}

/* Pricing — varies by tweak */
const PLANS_TRIO = [
  { name: "Quiet", price: "0", suffix: "KSh / mo", tag: "Build at your own pace.",
    features: ["1 collection", "Unlimited blocks", "M-PESA checkout (5% per sale)", "sema-ikutoke.so subdomain"], cta: "Start free" },
  { name: "Studio", price: "990", suffix: "KSh / mo", tag: "For makers who ship.", featured: true,
    features: ["10 collections", "Custom domain", "M-PESA + Card (2.5% per sale)", "Email capture & list", "Analytics that's actually useful"], cta: "Start free trial" },
  { name: "Atelier", price: "2,490", suffix: "KSh / mo", tag: "For teams & agencies.",
    features: ["Unlimited collections", "Team members (5)", "All payment rails (1.9%)", "API & webhooks", "Priority support"], cta: "Talk to us" },
];
const PLANS_DUO = [
  { name: "Solo", price: "0", suffix: "KSh / mo", tag: "Free forever.",
    features: ["3 collections", "M-PESA checkout", "5% per sale", "sema ikutoke sub-domain", "Community support"], cta: "Start free" },
  { name: "Pro", price: "1,490", suffix: "KSh / mo", tag: "Everything, simply.", featured: true,
    features: ["Unlimited collections", "Custom domain", "M-PESA + Card (1.9%)", "Team seats", "API access"], cta: "Begin trial" },
];
const PLANS_QUAD = [
  { name: "Free", price: "0", suffix: "KSh / mo", tag: "Try it.",
    features: ["1 collection", "sema ikutoke sub-domain", "5% per sale"], cta: "Start free" },
  { name: "Maker", price: "490", suffix: "KSh / mo", tag: "Hobby projects.",
    features: ["3 collections", "Custom subdomain", "M-PESA (3.5% per sale)"], cta: "Start" },
  { name: "Studio", price: "990", suffix: "KSh / mo", tag: "For makers.", featured: true,
    features: ["10 collections", "Custom domain", "M-PESA + Card (2.5%)", "Analytics"], cta: "Begin trial" },
  { name: "Atelier", price: "2,490", suffix: "KSh / mo", tag: "Teams.",
    features: ["Unlimited", "All rails (1.9%)", "API · 5 seats", "Priority"], cta: "Talk to us" },
];

function Pricing({ variant, goto }) {
  const plans = variant === "duo" ? PLANS_DUO : variant === "quad" ? PLANS_QUAD : PLANS_TRIO;
  return (
    <section>
      <div className="section-hd">
        <div>
          <div className="no">§ 04 / Pricing</div>
          <h2><em>Honest</em> pricing.</h2>
        </div>
        <div className="right">All plans · 14-day trial · Cancel anytime</div>
      </div>
      <div className="pricing" style={{gridTemplateColumns: `repeat(${plans.length}, 1fr)`}}>
        {plans.map((p) => (
          <div key={p.name} className={"plan " + (p.featured ? "featured" : "")}>
            <div className="plan-name">{p.name}</div>
            <div className="plan-price">{p.price}<small>{p.suffix}</small></div>
            <div className="plan-tag" style={p.featured ? {color:"var(--paper)"} : null}>{p.tag}</div>
            <ul>{p.features.map((f, i) => <li key={i}>{f}</li>)}</ul>
            <button className="plan-cta" onClick={() => goto("signup")}>{p.cta}</button>
          </div>
        ))}
      </div>
    </section>
  );
}

function Footer({ goto }) {
  return (
    <footer className="footer">
      <div>
        <div className="big">sema ikutoke — <span style={{fontStyle:"italic", color:"var(--accent)"}}>see you soon.</span></div>
        <div className="muted" style={{fontSize:14, maxWidth:"32ch"}}>
          Made in Nairobi, for makers everywhere. Built with care since 2024.
        </div>
        <div style={{marginTop:24, display:"flex", gap:12, alignItems:"center"}}>
          <button className="btn btn-ink btn-sm" onClick={() => goto("signup")}>
            Start free <span className="arrow"/>
          </button>
          <span className="mono">no card needed</span>
        </div>
      </div>
      <div>
        <h4>Product</h4>
        <ul>
          <li><a onClick={() => goto("templates")} style={{cursor:"pointer"}}>Templates</a></li>
          <li><a onClick={() => goto("builder")} style={{cursor:"pointer"}}>Builder</a></li>
          <li>Pricing</li>
          <li>Changelog</li>
        </ul>
      </div>
      <div>
        <h4>Payments</h4>
        <ul>
          <li>M-PESA Daraja</li>
          <li>Cards (Visa / Mastercard)</li>
          <li>Mobile Money (Airtel)</li>
          <li>Payouts</li>
        </ul>
      </div>
      <div>
        <h4>Company</h4>
        <ul>
          <li>About</li>
          <li>Manifesto</li>
          <li>Journal</li>
          <li>Contact</li>
        </ul>
      </div>
    </footer>
  );
}

function Landing({ tweaks, goto }) {
  const Hero = tweaks.hero === "centered" ? HeroCentered : tweaks.hero === "editorial" ? HeroEditorial : HeroSplit;
  return (
    <div className="view-anim">
      <TopNav goto={goto} view="landing" />
      <Ticker />
      <Hero goto={goto} />
      <HowItWorks />
      <ChannelsStrip goto={goto} />
      <TemplatesStrip goto={goto} />
      <Pricing variant={tweaks.pricing} goto={goto} />
      <Footer goto={goto} />
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════════
   SIGNUP
   ═══════════════════════════════════════════════════════════════════════ */
function Signup({ goto }) {
  const [form, setForm] = useState({ name: "", email: "", phone: "", code: "+254", role: "writer" });
  const [stage, setStage] = useState("form");

  const submit = (e) => {
    e.preventDefault();
    setStage("verifying");
    setTimeout(() => goto("templates"), 1400);
  };

  return (
    <div className="view-anim">
      <TopNav goto={goto} view="signup" />
      <div className="signup">
        <div className="signup-art">
          <div className="blob" />
          <div style={{position:"relative", zIndex:1}}>
            <div className="mono" style={{color:"color-mix(in srgb, var(--paper) 60%, transparent)", marginBottom:48}}>
              § FROM THE MANIFESTO
            </div>
            <p className="big">
              A small, <em>quieter</em> way to sell what you make — on your terms.
            </p>
          </div>
          <div className="testimonial" style={{position:"relative", zIndex:1}}>
            "I switched from three other platforms. sema ikutoke lets me focus on the work,
            not the funnel. STK push, sale done, 4 seconds."
            <div style={{marginTop:12}}>— <b>Wambui K.</b>, photographer · Nairobi</div>
          </div>
        </div>
        <form className="signup-form" onSubmit={submit}>
          <div className="mono" style={{color:"var(--ink-soft)"}}>§ 01 / Begin</div>
          <h2>Make a place for what you make.</h2>
          <p>It takes about 90 seconds. We'll set up your sub-domain and a starter collection.</p>

          <div className="field">
            <label>Your name</label>
            <input
              required
              placeholder="e.g. Wambui Kamau"
              value={form.name}
              onChange={(e) => setForm({...form, name: e.target.value})}
            />
          </div>
          <div className="field">
            <label>Email</label>
            <input
              required type="email"
              placeholder="you@studio.so"
              value={form.email}
              onChange={(e) => setForm({...form, email: e.target.value})}
            />
          </div>
          <div className="field">
            <label>Phone (for M-PESA payouts)</label>
            <div className="phone-wrap">
              <select value={form.code} onChange={(e) => setForm({...form, code: e.target.value})}>
                <option>+254</option><option>+255</option><option>+256</option>
                <option>+250</option><option>+234</option>
              </select>
              <input
                required
                placeholder="712 345 678"
                value={form.phone}
                onChange={(e) => setForm({...form, phone: e.target.value})}
              />
            </div>
          </div>
          <div className="field">
            <label>What do you make?</label>
            <select value={form.role} onChange={(e) => setForm({...form, role: e.target.value})}>
              <option value="writer">Writing &amp; essays</option>
              <option value="photo">Photography</option>
              <option value="design">Design &amp; templates</option>
              <option value="music">Music &amp; sound</option>
              <option value="course">Courses &amp; teaching</option>
              <option value="other">Something else</option>
            </select>
          </div>
          <label className="consent">
            <input type="checkbox" defaultChecked />
            <span>I agree to sema ikutoke's terms &amp; the M-PESA Daraja merchant terms. Send me the occasional letter; no spam.</span>
          </label>
          <div style={{display:"flex", gap:10, alignItems:"center", marginTop:8}}>
            <button type="submit" className="btn btn-primary btn-lg" disabled={stage === "verifying"}>
              {stage === "verifying" ? "Setting up…" : "Begin →"}
            </button>
            <button type="button" className="btn btn-ghost btn-sm" onClick={() => goto("landing")}>
              ← back to home
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════════
   TEMPLATES
   ═══════════════════════════════════════════════════════════════════════ */
const CATEGORIES = ["All", "Writers", "Photographers", "Designers", "Musicians", "Course creators", "Illustrators", "Podcasters", "Filmmakers"];

function Templates({ goto }) {
  const [cat, setCat] = useState("All");
  const list = useMemo(() =>
    cat === "All" ? TEMPLATES : TEMPLATES.filter(t => t.cat === cat),
    [cat]
  );

  return (
    <div className="view-anim">
      <TopNav goto={goto} view="templates" />
      <div className="gallery">
        <div className="gallery-hd">
          <div>
            <div className="mono" style={{color:"var(--ink-soft)", marginBottom:14}}>§ 01 / Collection</div>
            <h1>Sixty-four <em>shells</em>.<br/>One that's yours.</h1>
          </div>
          <p className="h-sub" style={{maxWidth:"36ch", margin:0}}>
            Every template is a starting point — designed to be made yours. Strip
            it back, add what's missing, push it somewhere unexpected.
          </p>
        </div>
        <div className="filters">
          {CATEGORIES.map((c) => (
            <button
              key={c}
              className={"filter " + (c === cat ? "active" : "")}
              onClick={() => setCat(c)}
            >{c}</button>
          ))}
        </div>
        <div className="tiles">
          {list.map((t, i) => {
            const sp = i === 0 ? "tile-span-6" : (i % 5 === 2 ? "tile-span-3" : "tile-span-3");
            const cover = COVER_STYLES[i % COVER_STYLES.length];
            return (
              <div key={t.id} className={"tile " + sp} onClick={() => goto("builder")}>
                <div className="thumb" style={{background: cover.bg, position:"relative"}}>
                  <div style={{position:"absolute", bottom:18, left:22, color:"#F1E8D1", fontFamily:"var(--serif)", fontStyle:"italic", fontSize: i === 0 ? 38 : 24, letterSpacing:"-.02em"}}>
                    {t.name}
                  </div>
                  {t.note && <span className="chip mint" style={{position:"absolute", top:14, left:14}}>{t.note}</span>}
                </div>
                <div className="info">
                  <span className="cat">{t.cat}</span>
                  <span className="name">{t.name}</span>
                  <div className="row">
                    <span>{18 + i*2} blocks</span>
                    <span className="price">{t.price}</span>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  Brand, TopNav, Ticker, ProtoNav,
  Landing, Signup, Templates,
  COVER_STYLES, TEMPLATES,
});
