/* ============================================================
   The Carnation — article, discovery, participation & info pages
   ============================================================ */

/* ===================== COMMENT MODERATION + FORMATTING ===================== */
const MOD_TERMS = ["fuck","shit","bitch","cunt","asshole","dick","pussy","bastard","whore","slut","nigger","nigga","faggot","fag","retard","kike","spic","chink","tranny","rape","rapist","kill yourself","kys","cock","cum","jizz","wank","twat","prick","douche","dipshit","dumbass","jackass","motherfucker","goddamn","piss","damn","hell no","screw you","suck my","blowjob","handjob","nazi","molest","pedophile","pedo"];
function modNormalize(s) {
  return (s || "").toLowerCase().normalize("NFKD").replace(/[\u0300-\u036f]/g, "")
    .replace(/[^a-z0-9\s]/g, " ").replace(/(.)\1{2,}/g, "$1$1").replace(/\s+/g, " ").trim();
}
function localFlag(text) {
  const n = modNormalize(text);
  const squished = n.replace(/\s+/g, "");
  for (const w of MOD_TERMS) {
    if (w.indexOf(" ") >= 0) { if (n.indexOf(w) >= 0) return true; continue; }
    if (new RegExp("\\b" + w + "s?\\b").test(n)) return true;
    if (w.length >= 5 && squished.indexOf(w) >= 0) return true;
  }
  return false;
}
async function aiModerate(text) {
  if (!(window.claude && window.claude.complete)) return null;
  try {
    const prompt = 'You moderate the public comment section of The Carnation, a civic local newspaper in Alliance, Ohio. Decide whether to publish this reader comment. BLOCK only if it contains hate speech or slurs, harassment or personal attacks, threats or calls for violence, sexual content, or gratuitous vulgarity with no civic substance. ALLOW strong opinions, criticism of leaders or businesses, and civic frustration. Reply with ONLY JSON: {"decision":"allow"|"block"}.\n\nComment:\n"""' + text + '"""';
    const out = await window.claude.complete(prompt);
    const m = out && out.match(/\{[\s\S]*?\}/);
    if (!m) return null;
    return JSON.parse(m[0]).decision === "block" ? "block" : "ok";
  } catch (e) { return null; }
}
async function moderateComment(text) {
  if (localFlag(text)) return { ok: false, reason: "Let\u2019s keep it civil — please rewrite without slurs, abuse, or vulgarity." };
  const ai = await aiModerate(text);
  if (ai === "block") return { ok: false, reason: "This space stays constructive and on-topic. Your answer wasn\u2019t published — try making the point without the heat." };
  return { ok: true };
}
function formatResponse(text) {
  const t = (text || "").trim();
  const parts = t.match(/[^.!?]+[.!?]*/g);
  if (parts && parts.length >= 2) {
    const sentences = parts.map((s) => s.trim()).filter(Boolean);
    const last = sentences[sentences.length - 1];
    if (sentences.length >= 2 && last.length <= 66 && last.length >= 6) {
      return { body: sentences.slice(0, -1).join(" "), kicker: last };
    }
  }
  return { body: t, kicker: null };
}

/* ===================== ARTICLE ===================== */
function ArticlePage({ slug }) {
  const D = C();
  const a = D.bySlug(slug);
  useStore();
  const [studio, setStudio] = useState(false);
  useEffect(() => { window.scrollTo(0, 0); if (a) S().views.bump(a.slug); }, [slug]);

  if (!a) {
    return (
      <main className="route"><section className="section"><div className="wrap wrap--narrow">
        <p className="note">That story could not be found. <a href="#/stories" style={{color:"var(--red)"}}>Back to all stories →</a></p>
      </div></section></main>
    );
  }
  const author = D.authorOf(a.authorKey);
  const more = D.ARTICLES.filter((x) => x.slug !== slug && x.dept === a.dept).slice(0, 3);
  const fallback = D.ARTICLES.filter((x) => x.slug !== slug).slice(0, 3);
  const related = more.length ? more : fallback;
  let firstPara = true;

  return (
    <main className="route art">
      <ReadingProgress />
      <div className="wrap wrap--mid">
        <a className="backlink" href={"#/" + a.dept}>← {a.category}</a>
        <header className="art__head">
          <div className="art__cat">{a.category}</div>
          <h1 className="art__title">{a.title}</h1>
          <p className="art__dek">{a.dek}</p>
          <div className="art__byline">
            <Avatar slot={"author:" + a.authorKey} initials={author.initials} size={34} />
            <span>By <a href={"#/author/" + a.authorKey} style={{borderBottom:"1px solid var(--line)"}}>{a.author}</a></span><span>·</span><span><TimeAgo ts={a.ts} /></span><span>·</span><span>{a.read} read</span><span>·</span><span>{D.views(a.slug).toLocaleString()} reads</span>
          </div>
          <TagRow tags={a.tags} className="tagrow--center" />
          <div className="art__actions">
            <button className="savebtn" onClick={() => setStudio(true)} aria-label="Share this story">
              <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 15V3"/><path d="m8 7 4-4 4 4"/><path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-7"/></svg>
              <span>Share</span>
            </button>
          </div>
        </header>
      </div>

      <div className="wrap wrap--mid">
        <Cover variant={a.cover} tag={a.category} slot={"cover:art:" + a.slug} className="art__cover" alt={a.title} />
      </div>

      <div className="wrap">
        <div className="art__body">
          {a.body.map((b, i) => {
            if (typeof b === "string") {
              if (firstPara) { firstPara = false; return <p key={i}><span className="art__dateline">{a.dateline} —</span> {b}</p>; }
              return <p key={i}>{b}</p>;
            }
            if (b.h) return <h3 key={i}>{b.h}</h3>;
            if (b.pull) return <p className="art__pull" key={i}>{b.pull}</p>;
            if (b.img) return (
              <figure className="art__fig" key={i}>
                <Cover variant={b.plate || a.cover} slot={b.img} className="art__fig-img" alt={b.cap || ""} />
                {b.cap && <figcaption className="art__cap">{b.cap}</figcaption>}
              </figure>
            );
            return null;
          })}

          {/* ===== END-OF-ARTICLE STAMP ===== */}
          <div className="endmark">
            <div className="endmark__dingbat" aria-hidden="true">
              <span className="endmark__rule" />
              <CarnationMark compact className="endmark__mark" />
              <span className="endmark__rule" />
            </div>

            <div className="endmark__author">
              <Avatar slot={"author:" + a.authorKey} initials={author.initials} size={58} />
              <div className="endmark__author-text">
                <div className="endmark__author-label">Written by</div>
                <div className="endmark__author-name">{a.author}<span className="endmark__author-role"> · {author.role}</span></div>
                <p className="endmark__author-bio">{author.bio}</p>
                <a className="endmark__author-more" href={"#/author/" + a.authorKey}>More from {a.author} <span className="arw">→</span></a>
                <AuthorContact a={author} />
              </div>
            </div>

            <div className="endmark__panel">
              <div className="endmark__panel-top">
                <span className="endmark__seal" aria-hidden="true"><CarnationMark sprig /></span>
                <div className="endmark__panel-kick">Community-supported · No paywall, ever</div>
              </div>
              <h3 className="endmark__panel-h">Keep the city's record free to read.</h3>
              <p className="endmark__panel-p">Members fund the reporting, the Local Index, and the questions we put to Alliance. Every word stays open to everyone.</p>
              <div className="endmark__panel-actions">
                <a className="btn btn--red" href="#/membership">Become a member <span className="arw">→</span></a>
                <a className="btn btn--line" href="#/submit">Send a tip</a>
              </div>
            </div>

            <div className="endmark__foot">
              <a className="endmark__footrow" href="#/submit"><span>Have a response, or a story this raises?</span><b>Write to The Carnation <span className="arw">→</span></b></a>
              <a className="endmark__footrow" href="#/corrections"><span>See a mistake in this piece?</span><b>Read our corrections policy <span className="arw">→</span></b></a>
            </div>
          </div>
        </div>
      </div>

      <section className="section section--tint" style={{marginTop:"clamp(40px,5vw,72px)"}}>
        <div className="wrap">
          <SecRule title="Related reading" />
          <div className="listgrid rail">
            {related.map((x) => <ArticleCard a={x} size="md" key={x.slug} />)}
          </div>
          <div className="rail-hint" aria-hidden="true">Swipe <span className="arw">→</span></div>
        </div>
      </section>
      {studio && window.CardStudio ? React.createElement(window.CardStudio, { article: a, onClose: () => setStudio(false) }) : null}
    </main>
  );
}

/* ===================== OPEN QUESTION — DETAIL (interactive) ===================== */
function QuestionPage({ id }) {
  const D = C();
  const q = D.byQ(id);
  useStore();
  useEffect(() => { window.scrollTo(0, 0); }, [id]);
  const [name, setName] = useState("");
  const [text, setText] = useState("");
  const [anon, setAnon] = useState(false);
  const [done, setDone] = useState(false);
  const [checking, setChecking] = useState(false);
  const [err, setErr] = useState("");

  if (!q) {
    return <main className="route"><section className="section"><div className="wrap wrap--narrow">
      <p className="note">That question could not be found. <a href="#/ideas" style={{color:"var(--red)"}}>Back to Open Questions →</a></p>
    </div></section></main>;
  }

  const userResponses = S().responses.get(id);
  const seedResponses = q.seedResponses || [];
  const shown = [...userResponses, ...seedResponses];
  const total = q.seed + userResponses.length + seedResponses.length;
  const others = D.OPEN_QUESTIONS.filter((x) => x.id !== id);

  const submit = async (e) => {
    e.preventDefault();
    const body = text.trim();
    if (!body) return;
    setErr(""); setChecking(true);
    const v = await moderateComment(body);
    setChecking(false);
    if (!v.ok) { setErr(v.reason); return; }
    S().responses.add(id, { name: anon || !name.trim() ? "Anonymous" : name.trim(), text: body });
    setText(""); setName(""); setErr(""); setDone(true);
    setTimeout(() => setDone(false), 4000);
  };

  return (
    <main className="route">
      <section className="phead">
        <div className="wrap wrap--mid">
          <a className="backlink" href="#/ideas">← Open Questions</a>
          <div className="phead__kick" style={{marginTop:"18px"}}>Open Question · {q.n}</div>
          <h1 className="phead__title qpage__q">{q.q}</h1>
          <p className="phead__dek">{q.prompt}</p>
          <div className="qpage__count"><CountUp to={total} /> responses · join them</div>
          <hr className="rule rule--double phead__rule" />
        </div>
      </section>

      <section className="section section--tight">
        <div className="wrap wrap--mid qpage__grid">
          {/* response form */}
          <div className="qpage__form-wrap">
            <h3 className="qpage__sub">Add your answer</h3>
            {done && <div className="qpage__ok">Thank you — your answer is published below.</div>}
            <form className="form" onSubmit={submit}>
              <div className="frow">
                <label>Your answer</label>
                <textarea className="textarea" required value={text} onChange={(e)=>setText(e.target.value)} placeholder="Speak plainly. Be specific. This is published for the whole city to read." />
              </div>
              <div className="frow">
                <label>Your name</label>
                <input className="input" value={name} onChange={(e)=>setName(e.target.value)} placeholder="First name + last initial" disabled={anon} />
              </div>
              <label className="qpage__anon">
                <input type="checkbox" checked={anon} onChange={(e)=>setAnon(e.target.checked)} /> Post anonymously
              </label>
              <button className="btn btn--red" type="submit" disabled={checking}>{checking ? "Reviewing\u2026" : "Publish my answer"} <span className="arw">→</span></button>
              {err && <p className="qpage__err">{err}</p>}
              <p className="note" style={{marginTop:"10px", fontSize:".78rem"}}>Answers are automatically reviewed for civility before they appear.</p>
            </form>
          </div>

          {/* responses */}
          <div className="qpage__responses">
            <h3 className="qpage__sub">What Alliance is saying <span className="qpage__sub-n">{shown.length} shown · {total} total</span></h3>
            <div className="resp-list">
              {shown.map((r, i) => { const f = formatResponse(r.text); return (
                <div className="resp" key={r._id || ("seed-"+i)}>
                  <div className="resp__head">
                    <span className="resp__name">{r.name}</span>
                    {r._at && <span className="resp__time"><TimeAgo ts={r._at} /></span>}
                  </div>
                  <p className="resp__text">{f.body}</p>
                  {f.kicker && <p className="resp__kicker">{f.kicker}</p>}
                </div>
              ); })}
              {shown.length === 0 && <p className="note">No public answers yet — be the first.</p>}
            </div>
            <p className="note" style={{marginTop:"18px", fontSize:".82rem"}}>{total - shown.length} more responses collected. The Carnation publishes a representative selection.</p>
          </div>
        </div>
      </section>

      <section className="section section--ink section--tight">
        <div className="wrap">
          <SecRule title="More Open Questions" />
          <div className="oq-grid rail">
            {others.map((x) => <QuestionCard q={x} key={x.id} />)}
          </div>
          <div className="rail-hint" aria-hidden="true">Swipe <span className="arw">→</span></div>
          <ProposeQuestion />
        </div>
      </section>
    </main>
  );
}

/* ===================== SEARCH ===================== */
function SearchPage() {
  const D = C();
  const [q, setQ] = useState(() => decodeURIComponent((location.hash.split("?q=")[1] || "")));
  const inputRef = useRef(null);
  useEffect(() => { if (inputRef.current) inputRef.current.focus(); }, []);
  const results = D.search(q);
  const popular = D.allTags().slice(0, 10);

  return (
    <main className="route">
      <section className="phead">
        <div className="wrap wrap--mid">
          <div className="phead__kick">Search</div>
          <h1 className="phead__title">Find a story</h1>
          <div className="searchbox">
            <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></svg>
            <input ref={inputRef} className="searchbox__input" value={q} onChange={(e)=>setQ(e.target.value)} placeholder="Search stories, topics, authors…" aria-label="Search" />
            {q && <button className="searchbox__clear" onClick={()=>setQ("")} aria-label="Clear">×</button>}
          </div>
          <hr className="rule rule--double phead__rule" />
        </div>
      </section>

      <section className="section section--tight">
        <div className="wrap wrap--mid">
          {!q.trim() ? (
            <div>
              <span className="meta">Popular topics</span>
              <div className="topiccloud" style={{marginTop:"14px"}}>
                {popular.map((t) => <a className="topicchip" href={"#/tag/" + t.tag} key={t.tag}>{t.label}<span className="topicchip__n">{t.n}</span></a>)}
              </div>
            </div>
          ) : results.length ? (
            <>
              <span className="meta">{results.length} {results.length===1?"result":"results"} for “{q}”</span>
              <div className="searchlist">
                {results.map((a) => (
                  <a className="searchrow" href={"#/article/" + a.slug} key={a.slug}>
                    <Cover variant={a.cover} tag={a.category} slot={"cover:art:" + a.slug} className="searchrow__cover" />
                    <div className="searchrow__body">
                      <span className="card__cat">{a.category}</span>
                      <span className="searchrow__t">{a.title}</span>
                      <span className="searchrow__d">{a.dek}</span>
                      <span className="searchrow__meta">{a.author} · <TimeAgo ts={a.ts} /></span>
                    </div>
                  </a>
                ))}
              </div>
            </>
          ) : (
            <p className="note">No stories match “{q}”. Try a broader term, or <a href="#/stories" style={{color:"var(--red)"}}>browse all stories →</a></p>
          )}
        </div>
      </section>
    </main>
  );
}

/* ===================== TAG ===================== */
function TagPage({ tag }) {
  const D = C();
  const list = D.byTag(tag);
  const label = D.tagLabel(tag);
  const otherTags = D.allTags().filter((t) => t.tag !== tag).slice(0, 8);
  return (
    <main className="route">
      <section className="phead">
        <div className="wrap">
          <div className="phead__kick">Topic</div>
          <h1 className="phead__title">{label}</h1>
          <p className="phead__dek">{list.length} {list.length===1?"story":"stories"} tagged {label}.</p>
          <hr className="rule rule--double phead__rule" />
        </div>
      </section>
      <section className="section section--tight">
        <div className="wrap">
          <Reveal>
            {list.length ? (
              <div className="listgrid rise">{list.map((a) => <ArticleCard a={a} size="md" key={a.slug} />)}</div>
            ) : <p className="note">No stories tagged {label} yet.</p>}
          </Reveal>
        </div>
      </section>
      <section className="section section--tint section--tight">
        <div className="wrap">
          <SecRule title="Other topics" />
          <div className="topiccloud">
            {otherTags.map((t) => <a className="topicchip" href={"#/tag/" + t.tag} key={t.tag}>{t.label}<span className="topicchip__n">{t.n}</span></a>)}
          </div>
        </div>
      </section>
    </main>
  );
}

/* ===================== MEMBERSHIP ===================== */

/* one-time gift amount picker — chips + a checkout button */
function DonateBlock() {
  const opts = (window.coffeeOptions && window.coffeeOptions()) || [];
  const custom = window.coffeeCustomUrl && window.coffeeCustomUrl();
  const ready = window.coffeeReady && window.coffeeReady();
  const presets = opts.length ? opts : [{ amount: 5 }, { amount: 10 }, { amount: 25 }];
  const [sel, setSel] = useState(presets[1] ? presets[1].amount : presets[0].amount);
  const [other, setOther] = useState(false);

  const urlFor = () => {
    if (other) return custom;
    const m = opts.find((o) => o.amount === sel);
    return m ? m.url : custom; // fall back to name-your-price if no exact link
  };
  const target = urlFor();

  return (
    <div style={{flex:"none", minWidth:"260px"}}>
      <div className="chips" style={{marginBottom:"14px"}}>
        {presets.map((p) => (
          <button type="button" key={p.amount}
            className={"chip" + (!other && sel === p.amount ? " on" : "")}
            onClick={() => { setOther(false); setSel(p.amount); }}>${p.amount}</button>
        ))}
        <button type="button"
          className={"chip" + (other ? " on" : "")}
          onClick={() => setOther(true)}>Other</button>
      </div>
      {ready && target ? (
        <a className="btn btn--navy btn--lg" href={target} target="_blank" rel="noopener">
          {other ? "Continue to checkout" : "Give $" + sel}<span className="arw">→</span>
        </a>
      ) : (
        <span className="btn btn--navy btn--lg" style={{cursor:"default"}}>
          {other ? "Continue to checkout" : "Give $" + sel}<span className="arw">→</span>
        </span>
      )}
    </div>
  );
}

function MembershipPage() {
  const D = C();
  useStore();
  const [tier, setTier] = useState("member");
  const [email, setEmail] = useState("");
  const [name, setName] = useState("");
  const [done, setDone] = useState(false);
  const submit = async (e) => {
    e.preventDefault();
    if (!email.trim()) return;
    const memberOk = await window.captureOrAlert("members", { tier, email: email.trim(), name: name.trim() });
    if (!memberOk) return;
    if (!(window.CLOUD && window.CLOUD.enabled) && window.STORE && S().newsletter && !S().newsletter.has(email.trim())) await window.capture("newsletter", { email: email.trim() });
    else if (window.CLOUD && window.CLOUD.enabled) await window.capture("newsletter", { email: email.trim() });
    const chosen = D.MEMBER_TIERS.find((t) => t.id === tier);
    const link = chosen.price !== "Free" && window.payLink ? window.payLink(tier, email.trim()) : null;
    if (link) { window.location.href = link; return; }   // off to Stripe checkout
    setDone(true); window.scrollTo(0, 0);
  };
  return (
    <main className="route">
      <section className="phead">
        <div className="wrap">
          <div className="phead__kick">Membership</div>
          <h1 className="phead__title">Keep the city's story free to read.</h1>
          <p className="phead__dek">The Carnation has no paywall and never will. Members make that possible — and keep coverage independent, local, and ambitious.</p>
          <hr className="rule rule--double phead__rule" />
        </div>
      </section>

      {done ? (
        <section className="section section--tight"><div className="wrap wrap--narrow">
          <div className="sent">Welcome in — you're now a <b>{D.MEMBER_TIERS.find(t=>t.id===tier).label}</b>. We'll be in touch at <b>{email}</b> with the Dispatch and your member briefings.</div>
        </div></section>
      ) : (
        <>
          <section className="section section--tight">
            <div className="wrap">
              <Reveal>
                <div className="tiers rise">
                  {D.MEMBER_TIERS.map((t) => (
                    <button type="button" className={"mtier" + (t.feat ? " mtier--feat" : "") + (tier===t.id ? " on" : "")} key={t.id} onClick={()=>setTier(t.id)}>
                      {t.feat && <span className="mtier__flag">Most chosen</span>}
                      <span className="mtier__label">{t.label}</span>
                      <span className="mtier__price">{t.price}<span className="mtier__cadence">{t.cadence}</span></span>
                      <span className="mtier__desc">{t.desc}</span>
                      <span className="mtier__perks">
                        {t.perks.map((p) => <span className="mtier__perk" key={p}><span className="mtier__check">✓</span>{p}</span>)}
                      </span>
                      <span className="mtier__pick">{tier===t.id ? "Selected" : "Choose"}</span>
                    </button>
                  ))}
                </div>
              </Reveal>
            </div>
          </section>

          <section className="section section--tint section--tight">
            <div className="wrap wrap--narrow">
              <SecRule title="Join" meta={D.MEMBER_TIERS.find(t=>t.id===tier).label} />
              <form className="form" onSubmit={submit}>
                <div className="frow"><label>Your name</label><input className="input" value={name} onChange={(e)=>setName(e.target.value)} placeholder="So we can thank you properly" /></div>
                <div className="frow"><label>Email</label><input className="input" type="email" required value={email} onChange={(e)=>setEmail(e.target.value)} placeholder="Where we send the dispatch" /></div>
                <div style={{display:"flex", gap:"14px", alignItems:"center", flexWrap:"wrap"}}>
                  {(() => {
                    const chosen = D.MEMBER_TIERS.find(t=>t.id===tier);
                    const paid = chosen.price !== "Free";
                    const ready = paid && window.payReady && window.payReady(tier);
                    return (<>
                      <button className="btn btn--red btn--lg" type="submit">{!paid ? "Join free" : (ready ? "Continue to secure checkout" : "Become a member")} <span className="arw">→</span></button>
                      <span className="note">{!paid ? "Free forever — just the dispatch." : (ready ? "Secure payment via Stripe. Cancel anytime." : "Checkout isn’t connected yet — we’ll record your interest.")}</span>
                    </>);
                  })()}
                </div>
              </form>
            </div>
          </section>

          <section className="section section--tint section--tight">
            <div className="wrap wrap--narrow">
              <SecRule title="One-time gift" meta="No commitment" />
              <div style={{display:"flex", gap:"28px", alignItems:"center", justifyContent:"space-between", flexWrap:"wrap"}}>
                <div style={{flex:"1 1 320px"}}>
                  <h3 style={{fontFamily:"var(--serif)", fontWeight:600, fontSize:"clamp(1.4rem,2.6vw,1.9rem)", letterSpacing:"-.01em", marginBottom:"8px"}}>Buy us a coffee. Or lunch.</h3>
                  <p className="note" style={{fontSize:"1rem", maxWidth:"46ch"}}>Not ready for a monthly membership? A single gift of any size — the price of a coffee, a drink, lunch — keeps a story reported and the city's record free to read.</p>
                </div>
                {window.coffeeReady && window.coffeeReady() ? (
                  <DonateBlock />
                ) : (
                  <div style={{flex:"none"}}>
                    <DonateBlock />
                    <p className="note" style={{marginTop:"12px", fontSize:".78rem", maxWidth:"34ch"}}>Checkout isn't connected yet — add a Stripe link in <code style={{fontFamily:"var(--mono)"}}>payments-config.js</code> and these go live.</p>
                  </div>
                )}
              </div>
            </div>
          </section>
        </>
      )}
    </main>
  );
}

/* ===================== LIST A SPACE ===================== */
const SPACE_TYPES = ["Storefront", "Restaurant / Café space", "Office", "Studio / Creative", "Warehouse / Light industrial", "Event venue", "Land / Lot", "Other"];
const SPACE_INTENTS = ["For lease", "For sale", "Pop-up / Short-term", "Shared / Co-use"];
const SPACE_FEATURES = ["Street frontage", "Display windows", "High ceilings", "Natural light", "Parking", "Loading dock", "Basement storage", "Updated HVAC", "ADA accessible", "Commercial kitchen", "Restrooms", "Outdoor space", "Corner location", "Move-in ready"];
const SPACE_PLANS = [
  { id: "listed", label: "Listed Space", price: "Free", short: "A clean entry in Available Spaces.", desc: "A clean entry in the Local Index's Available Spaces.", perks: ["Photo, size & asking price", "Map location & contact", "Basic condition or use notes", "Reviewed before publishing"] },
  { id: "featured", label: "Featured Space", price: "$35", cadence: "/mo", feat: true, short: "Top placement, full gallery, highlighted card.", desc: "Top placement in Available Spaces with a full gallery and a highlighted card.", perks: ["Everything in Listed", "Top placement & visual highlight", "Full photo gallery", "Newsletter mention when relevant"] },
  { id: "spotlight", label: "Space Spotlight", price: "$400", cadence: " once", short: "A photographed, written feature of the space.", desc: "A photographed, written feature telling the story of the building, storefront, studio, or opportunity.", perks: ["Everything in Featured", "Editorial photo & written feature", "Placement in Spaces", "Permanent home in the Index"] },
  { id: "activation", label: "Property Activation", price: "from $750", short: "Hands-on help getting a space tenant-ready.", desc: "For owners who want help making a vacant or underused space legible, attractive, and ready for the right tenant or partner.", perks: ["Positioning for the space", "Listing copy & visual direction", "Photography guidance or a simple shoot", "Featured placement + a Space Spotlight", "Suggested uses or tenant concepts", "Light circulation through our channels"] },
];

function ListSpacePage() {
  const [sent, setSent] = useState(false);
  const [f, setF] = useState({ title: "", type: SPACE_TYPES[0], intent: SPACE_INTENTS[0], address: "", size: "", price: "", available: "", desc: "", name: "", email: "", phone: "", plan: "featured" });
  const [feats, setFeats] = useState([]);
  const [photos, setPhotos] = useState([]);
  const builderRef = useRef(null);
  const goBuild = () => { const el = builderRef.current; if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 70, behavior: "smooth" }); };
  const set = (k) => (e) => setF((s) => ({ ...s, [k]: e.target.value }));
  const toggleFeat = (t) => setFeats((a) => a.includes(t) ? a.filter((x) => x !== t) : [...a, t]);
  const onPhotos = (e) => {
    const files = [...(e.target.files || [])]; e.target.value = "";
    files.slice(0, 4 - photos.length).forEach((file) => {
      if (!/^image\//.test(file.type)) return;
      const fr = new FileReader(); fr.onload = () => setPhotos((p) => [...p, fr.result].slice(0, 4)); fr.readAsDataURL(file);
    });
  };
  const submit = async (e) => {
    e.preventDefault();
    const plan = SPACE_PLANS.find((p) => p.id === f.plan);
    const ok = await window.captureOrAlert("submissions", { type: "Space Listing", title: f.title, body: f.desc, name: f.name, email: f.email,
      space: { type: f.type, intent: f.intent, address: f.address, size: f.size, price: f.price, available: f.available, features: feats, photos: photos.length, plan: f.plan } });
    if (!ok) return;
    const link = plan && plan.price !== "Free" && window.payLink ? window.payLink("listing_" + f.plan, f.email) : null;
    if (link) { window.location.href = link; return; }
    setSent(true); window.scrollTo(0, 0);
  };

  if (sent) {
    return (
      <main className="route">
        <section className="phead"><div className="wrap">
          <div className="phead__kick">List a Space</div>
          <h1 className="phead__title">Your space is in front of the right people.</h1>
        </div></section>
        <section className="section section--tight"><div className="wrap wrap--narrow">
          <div className="sent">Thank you. <b>{f.title || "Your listing"}</b> is submitted. We review every space before it goes into the Local Index{SPACE_PLANS.find((p)=>p.id===f.plan).price!=="Free" ? ", and will confirm your Featured placement" : ""}. Expect a note at <b>{f.email || "your email"}</b> within two business days.</div>
          <div style={{marginTop:"22px", display:"flex", gap:"12px", flexWrap:"wrap"}}>
            <a className="btn btn--line" href="#/local-index">See the Local Index <span className="arw">→</span></a>
            <a className="btn btn--line" href="#/">Back to the front page</a>
          </div>
        </div></section>
      </main>
    );
  }

  const priceUnit = f.intent === "For sale" ? "" : "/mo";
  const coverPlate = { "Restaurant / Café space": "bench", "Event venue": "marquee", "Office": "press", "Studio / Creative": "ledger", "Warehouse / Light industrial": "press" }[f.type] || "window";
  return (
    <main className="route">
      <section className="phead"><div className="wrap">
        <div className="lsp-hero">
          <div className="lsp-hero__copy">
            <div className="phead__kick">For property owners</div>
            <h1 className="phead__title" style={{marginBottom:"18px"}}>List your space where Alliance's next chapter gets written.</h1>
            <p className="phead__dek" style={{margin:0}}>A storefront, a studio, a corner waiting for its next use. Put it in front of the founders, operators, and builders who actually read this publication and are looking for room to grow.</p>
            <div className="lsp-cta-row">
              <button type="button" className="btn btn--red btn--lg" onClick={goBuild}>Start your listing <span className="arw">→</span></button>
              <a className="btn btn--line btn--lg" href="#/local-index">Browse the Local Index</a>
            </div>
          </div>
          <div className="lsp-hero__card">
            <div className="lsp-aside__label">A listing in the Local Index</div>
            <div className="profile lsp-listing" style={{cursor:"default"}}>
              <div className="lsp-coverwrap">
                <Cover variant="window" tag="For lease" slot="__lsp_sample" className="profile__cover" />
                <span className="lsp-price-badge"><b>$1,800</b>/mo</span>
              </div>
              <div className="profile__body">
                <div className="profile__cat">Available Spaces</div>
                <h3 className="profile__name">The Glass Block</h3>
                <div className="lsp-priceline"><span><b>4,200</b> sq ft</span><span>Main &amp; Arch</span><span>Available now</span></div>
                <p className="profile__blurb">A prominent corner storefront, dark for now. Ground-floor glass, good bones, and 4,200 square feet waiting for a lease, a pop-up, or its next chapter.</p>
                <div className="profile__tags"><span className="profile__tag">Corner location</span><span className="profile__tag">Display windows</span><span className="profile__tag">High ceilings</span></div>
              </div>
            </div>
          </div>
        </div>
        <hr className="rule rule--double phead__rule" style={{marginTop:"clamp(34px,5vw,60px)"}} />
      </div></section>

      <section className="section section--tight"><div className="wrap">
        <div className="lsp-trust">
          <span><b>Free</b>&nbsp;to list</span><span className="sepdot" />
          <span><b>Reviewed</b>&nbsp;by our editors</span><span className="sepdot" />
          <span>Placed beside the city's&nbsp;<b>most-read</b>&nbsp;coverage</span>
        </div>
      </div></section>

      <section className="section section--tight"><div className="wrap">
        <div className="lsp-cols">
          <div className="lsp-col">
            <SecRule title="Why list here" meta="Three reasons" />
            <div className="lsp-why">
              <div className="lsp-whyc"><span className="lsp-whyc__n">01</span><h4>The right audience</h4><p>Not a cold listings database. Your space sits beside coverage the people building Alliance read on purpose.</p></div>
              <div className="lsp-whyc"><span className="lsp-whyc__n">02</span><h4>Made to be seen</h4><p>Photos, size, price, and the story of the room, presented like a feature rather than a classified ad.</p></div>
              <div className="lsp-whyc"><span className="lsp-whyc__n">03</span><h4>Free to start</h4><p>List for nothing. Upgrade for top placement, a full gallery, or a written Spotlight when you are ready.</p></div>
            </div>
          </div>
          <div className="lsp-col">
            <SecRule title="How it works" meta="Three steps" />
            <div className="lsp-flow">
              <div className="lsp-flowrow"><span className="lsp-flowrow__n">1</span><div><h4>Build your listing</h4><p>Add the space, the details, and a few photos. Watch it come together in a live preview as you type.</p></div></div>
              <div className="lsp-flowrow"><span className="lsp-flowrow__n">2</span><div><h4>We review and publish</h4><p>Our editors check every listing for quality and fit, then place it in the Local Index, usually within two business days.</p></div></div>
              <div className="lsp-flowrow"><span className="lsp-flowrow__n">3</span><div><h4>Inquiries reach you</h4><p>Interested operators and founders contact you directly. You keep every lead.</p></div></div>
            </div>
          </div>
        </div>
      </div></section>

      <section className="section section--tint" ref={builderRef}><div className="wrap">
        <SecRule title="Build your listing" meta="Live preview as you type" />
        <form className="form lsp-build" onSubmit={submit}>
          <div className="lsp-form">
            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">01</span> Choose your plan</div>
              <div className="planpick">
                {SPACE_PLANS.map((p) => (
                  <button type="button" key={p.id} className={"planopt" + (p.feat ? " planopt--feat" : "") + (f.plan === p.id ? " on" : "")} onClick={() => setF((s)=>({...s, plan:p.id}))}>
                    <span className="planopt__radio" aria-hidden="true"></span>
                    <span className="planopt__main">
                      <span className="planopt__label">{p.label}{p.feat && <span className="planopt__flag">Most chosen</span>}</span>
                      <span className="planopt__desc">{p.short || p.desc}</span>
                    </span>
                    <span className="planopt__price">{p.price}<span className="planopt__cadence">{p.cadence||""}</span></span>
                  </button>
                ))}
              </div>
            </fieldset>

            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">02</span> The space</div>
              <div className="frow"><label>What is it?</label>
                <div className="lsp-seg">{SPACE_TYPES.map((t)=><button type="button" key={t} className={"chip"+(f.type===t?" on":"")} onClick={()=>setF((s)=>({...s,type:t}))}>{t}</button>)}</div>
              </div>
              <div className="frow"><label>Listing type</label>
                <div className="lsp-seg">{SPACE_INTENTS.map((t)=><button type="button" key={t} className={"chip"+(f.intent===t?" on":"")} onClick={()=>setF((s)=>({...s,intent:t}))}>{t}</button>)}</div>
              </div>
              <div className="frow"><label>Headline</label><input className="input" required value={f.title} onChange={set("title")} placeholder="e.g. Prominent corner storefront on Main" /></div>
              <div className="frow"><label>Address or location</label><input className="input" value={f.address} onChange={set("address")} placeholder="Main & Arch, Alliance" /></div>
            </fieldset>

            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">03</span> Details</div>
              <div className="lsp-grid2">
                <div className="frow"><label>Size (sq ft)</label><input className="input" value={f.size} onChange={set("size")} placeholder="4,200" /></div>
                <div className="frow"><label>{f.intent==="For sale"?"Asking price":"Asking rent"}</label><input className="input" value={f.price} onChange={set("price")} placeholder={f.intent==="For sale"?"185,000":"1,800"} /></div>
              </div>
              <div className="frow"><label>Available</label><input className="input" value={f.available} onChange={set("available")} placeholder="Now, or a date" /></div>
              <div className="frow"><label>Features</label>
                <div className="lsp-seg">{SPACE_FEATURES.map((t)=><button type="button" key={t} className={"chip"+(feats.includes(t)?" on":"")} onClick={()=>toggleFeat(t)}>{t}</button>)}</div>
              </div>
            </fieldset>

            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">04</span> Description &amp; photos</div>
              <div className="frow"><label>Describe the space</label><textarea className="textarea" required value={f.desc} onChange={set("desc")} placeholder="What it is, where it sits, the bones, and what it's waiting to become." /></div>
              <div className="frow"><label>Photos <span className="note" style={{textTransform:"none",letterSpacing:0}}>· up to 4</span></label>
                <div className="lsp-photos">
                  {photos.map((src,i)=>(<div className="lsp-photo" key={i}><img src={src} alt="" /><button type="button" className="lsp-photo__x" onClick={()=>setPhotos((p)=>p.filter((_,j)=>j!==i))}>×</button></div>))}
                  {photos.length<4 && (<label className="lsp-add">+ Add photo<input type="file" accept="image/*" multiple onChange={onPhotos} style={{display:"none"}} /></label>)}
                </div>
              </div>
            </fieldset>

            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">05</span> Contact</div>
              <div className="lsp-grid2">
                <div className="frow"><label>Your name</label><input className="input" value={f.name} onChange={set("name")} placeholder="Owner or agent" /></div>
                <div className="frow"><label>Phone</label><input className="input" value={f.phone} onChange={set("phone")} placeholder="(330) 555-0100" /></div>
              </div>
              <div className="frow"><label>Email</label><input className="input" type="email" required value={f.email} onChange={set("email")} placeholder="Where inquiries should go" /></div>
            </fieldset>

            <div style={{display:"flex",gap:"14px",alignItems:"center",flexWrap:"wrap"}}>
              <button className="btn btn--red btn--lg" type="submit">{SPACE_PLANS.find((p)=>p.id===f.plan).price==="Free" ? "Submit listing" : "Submit & continue to checkout"} <span className="arw">→</span></button>
              <span className="note">Reviewed before it goes live.</span>
            </div>
          </div>

          <aside className="lsp-aside">
            <div className="lsp-aside__label">Live preview · Local Index</div>
            <div className="profile lsp-listing" style={{cursor:"default"}}>
              <div className="lsp-coverwrap">
                {photos[0]
                  ? <div className="profile__cover" style={{position:"relative",overflow:"hidden"}}><img className="cover__img" src={photos[0]} alt="" /></div>
                  : <Cover variant={coverPlate} tag={f.intent} slot="__lsp_preview" className="profile__cover" />}
                <span className="lsp-price-badge">{f.price ? <><b>${f.price}</b>{priceUnit}</> : "Inquire"}</span>
              </div>
              <div className="profile__body">
                <div className="profile__cat">{f.type}</div>
                <h3 className="profile__name">{f.title || "Your headline appears here"}</h3>
                <div className="lsp-priceline">
                  {f.size && <span><b>{f.size}</b> sq ft</span>}
                  {f.available && <span>Available {f.available}</span>}
                  {f.address && <span>{f.address}</span>}
                </div>
                <p className="profile__blurb">{f.desc || "Your description appears here as you type, what the space is and what it's waiting to become."}</p>
                {feats.length>0 && <div className="profile__tags">{feats.slice(0,6).map((t)=><span className="profile__tag" key={t}>{t}</span>)}</div>}
              </div>
            </div>

            <div className="lsp-after">
              <div className="lsp-after__h">What happens after you submit</div>
              <ol className="lsp-after__steps">
                <li>Our editors review every listing for quality and fit.</li>
                <li>We publish it to Available Spaces, usually within a few days.</li>
                <li>Interested operators and founders contact you directly —<br />you keep every lead.</li>
              </ol>
              <p className="lsp-after__note">This is exactly how your space appears to readers.<br />Reviewed before it goes live.</p>
            </div>
          </aside>
        </form>
      </div></section>
    </main>
  );
}

/* ===================== ADD / NOMINATE A BUSINESS ===================== */
const BIZ_CATS = ["Downtown Business", "Café & Third Place", "Retail", "Restaurant", "Local Service", "Maker / Creative", "Creative Space", "Community Resource", "Other"];
const BIZ_OFFERS = ["Dine-in", "Takeout", "Delivery", "Online ordering", "Gift cards", "By appointment", "Walk-ins welcome", "Wheelchair accessible", "Free wifi", "Locally made", "Family-owned", "Open late", "Parking", "Pet-friendly"];

function AddBusinessPage() {
  const D = C();
  const [sent, setSent] = useState(false);
  const [rel, setRel] = useState("own"); // own | recommend
  const [f, setF] = useState({ title: "", cat: BIZ_CATS[0], tagline: "", desc: "", address: "", hours: "", phone: "", email: "", web: "", ig: "", fb: "", plan: "basic" });
  const [offers, setOffers] = useState([]);
  const [photos, setPhotos] = useState([]);
  const set = (k) => (e) => setF((s) => ({ ...s, [k]: e.target.value }));
  const toggle = (t) => setOffers((a) => a.includes(t) ? a.filter((x) => x !== t) : [...a, t]);
  const onPhotos = (e) => {
    const files = [...(e.target.files || [])]; e.target.value = "";
    files.slice(0, 4 - photos.length).forEach((file) => {
      if (!/^image\//.test(file.type)) return;
      const fr = new FileReader(); fr.onload = () => setPhotos((p) => [...p, fr.result].slice(0, 4)); fr.readAsDataURL(file);
    });
  };
  const submit = async (e) => {
    e.preventDefault();
    const plan = D.LISTING_LEVELS.find((p) => p.id === f.plan);
    const ok = await window.captureOrAlert("submissions", { type: rel === "own" ? "Business Claim" : "Business Nomination", title: f.title, body: f.desc, name: f.name, email: f.email,
      business: { cat: f.cat, tagline: f.tagline, address: f.address, hours: f.hours, phone: f.phone, web: f.web, ig: f.ig, fb: f.fb, offerings: offers, photos: photos.length, plan: f.plan, relationship: rel } });
    if (!ok) return;
    const link = plan && f.plan !== "basic" && window.payLink ? window.payLink("listing_" + f.plan, f.email) : null;
    if (link) { window.location.href = link; return; }
    setSent(true); window.scrollTo(0, 0);
  };

  if (sent) {
    return (
      <main className="route">
        <section className="phead"><div className="wrap">
          <div className="phead__kick">The Local Index</div>
          <h1 className="phead__title">{rel === "own" ? "Your business is on its way in." : "Thank you for the nomination."}</h1>
        </div></section>
        <section className="section section--tight"><div className="wrap wrap--narrow">
          <div className="sent">{rel === "own" ? <>We've received <b>{f.title || "your business"}</b> and will review it before it joins the Local Index. </> : <>We'll take a look at <b>{f.title || "your nomination"}</b> and reach out to them. </>}A note will land at <b>{f.email || "your email"}</b> within two business days.</div>
          <div style={{marginTop:"22px", display:"flex", gap:"12px", flexWrap:"wrap"}}>
            <a className="btn btn--line" href="#/local-index">See the Local Index <span className="arw">→</span></a>
            <a className="btn btn--line" href="#/">Back to the front page</a>
          </div>
        </div></section>
      </main>
    );
  }

  return (
    <main className="route">
      <section className="phead"><div className="wrap">
        <div className="phead__kick">For local businesses</div>
        <h1 className="phead__title">Put your business on Alliance's map.</h1>
        <p className="phead__dek">The Local Index is a curated, written guide to the people and places holding the city together — not a scraped database. Add your shop, kitchen, studio, or service, or nominate one worth knowing.</p>
        <hr className="rule rule--double phead__rule" />
      </div></section>

      <section className="section section--tint section--tight"><div className="wrap">
        <SecRule title="Your listing" meta="Live preview as you type" />
        <form className="form lsp-build" onSubmit={submit}>
          <div className="lsp-form">
            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">01</span> Your presence</div>
              <div className="frow"><label>Is this your business?</label>
                <div className="lsp-seg">
                  <button type="button" className={"chip"+(rel==="own"?" on":"")} onClick={()=>setRel("own")}>I own or run it</button>
                  <button type="button" className={"chip"+(rel==="recommend"?" on":"")} onClick={()=>setRel("recommend")}>I'm nominating it</button>
                </div>
              </div>
              <div className="planpick">
                {D.LISTING_LEVELS.map((p) => (
                  <button type="button" key={p.id} className={"planopt" + (p.feat ? " planopt--feat" : "") + (f.plan === p.id ? " on" : "")} onClick={() => setF((s)=>({...s, plan:p.id}))}>
                    <span className="planopt__radio" aria-hidden="true"></span>
                    <span className="planopt__main">
                      <span className="planopt__label">{p.label}{p.feat && <span className="planopt__flag">Editorial</span>}</span>
                      <span className="planopt__desc">{p.short || p.desc}</span>
                    </span>
                    <span className="planopt__price">{p.price}<span className="planopt__cadence">{p.cadence||""}</span></span>
                  </button>
                ))}
              </div>
            </fieldset>

            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">02</span> The business</div>
              <div className="lsp-grid2">
                <div className="frow"><label>Business name</label><input className="input" required value={f.title} onChange={set("title")} placeholder="The Press Room Coffee" /></div>
                <div className="frow"><label>One-line tagline</label><input className="input" value={f.tagline} onChange={set("tagline")} placeholder="Downtown's living room" /></div>
              </div>
              <div className="frow"><label>Category</label>
                <div className="lsp-seg">{BIZ_CATS.map((t)=><button type="button" key={t} className={"chip"+(f.cat===t?" on":"")} onClick={()=>setF((s)=>({...s,cat:t}))}>{t}</button>)}</div>
              </div>
              <div className="frow"><label>About</label><textarea className="textarea" required value={f.desc} onChange={set("desc")} placeholder="What you do, what's worth knowing, and what makes it matter to Alliance." /></div>
              <div className="frow"><label>What you offer</label>
                <div className="lsp-seg">{BIZ_OFFERS.map((t)=><button type="button" key={t} className={"chip"+(offers.includes(t)?" on":"")} onClick={()=>toggle(t)}>{t}</button>)}</div>
              </div>
            </fieldset>

            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">03</span> Find &amp; reach you</div>
              <div className="lsp-grid2">
                <div className="frow"><label>Address</label><input className="input" value={f.address} onChange={set("address")} placeholder="118 Main Street, Alliance" /></div>
                <div className="frow"><label>Hours</label><input className="input" value={f.hours} onChange={set("hours")} placeholder="Mon–Sat · 7am–8pm" /></div>
              </div>
              <div className="lsp-grid2">
                <div className="frow"><label>Phone</label><input className="input" value={f.phone} onChange={set("phone")} placeholder="(330) 555-0142" /></div>
                <div className="frow"><label>Website</label><input className="input" value={f.web} onChange={set("web")} placeholder="pressroom.coffee" /></div>
              </div>
              <div className="lsp-grid2">
                <div className="frow"><label>Instagram</label><input className="input" value={f.ig} onChange={set("ig")} placeholder="@thepressroomcoffee" /></div>
                <div className="frow"><label>Facebook</label><input className="input" value={f.fb} onChange={set("fb")} placeholder="thepressroomcoffee" /></div>
              </div>
              <div className="frow"><label>Photos or logo <span className="note" style={{textTransform:"none",letterSpacing:0}}>· up to 4</span></label>
                <div className="lsp-photos">
                  {photos.map((src,i)=>(<div className="lsp-photo" key={i}><img src={src} alt="" /><button type="button" className="lsp-photo__x" onClick={()=>setPhotos((p)=>p.filter((_,j)=>j!==i))}>×</button></div>))}
                  {photos.length<4 && (<label className="lsp-add">+ Add photo<input type="file" accept="image/*" multiple onChange={onPhotos} style={{display:"none"}} /></label>)}
                </div>
              </div>
              <div className="frow"><label>Your email <span className="note" style={{textTransform:"none",letterSpacing:0}}>· so we can follow up</span></label><input className="input" type="email" required value={f.email} onChange={set("email")} placeholder="you@email.com" /></div>
            </fieldset>

            <div style={{display:"flex",gap:"14px",alignItems:"center",flexWrap:"wrap"}}>
              <button className="btn btn--red btn--lg" type="submit">{f.plan==="basic" ? (rel==="own"?"Add my business":"Send nomination") : "Submit & continue"} <span className="arw">→</span></button>
              <span className="note">Reviewed before it goes live.</span>
            </div>
          </div>

          {/* live preview */}
          <aside className="lsp-aside">
            <div className="lsp-aside__label">Live preview · Local Index</div>
            <div className="profile lsp-listing" style={{cursor:"default"}}>
              <div className="lsp-cover">
                {photos[0]
                  ? <img src={photos[0]} alt="" />
                  : <span className="lsp-cover__hint">Add a photo to bring your listing to life</span>}
                <span className="lsp-cover__tag">{f.cat || "Downtown Business"}</span>
              </div>
              <div className="profile__body">
                <div className="profile__cat">{f.cat || "Downtown Business"}</div>
                <h3 className="profile__name">{f.title || "Your business name"}</h3>
                {(f.tagline || !f.title) && <div className="lsp-tagline">{f.tagline || "Your tagline appears here"}</div>}
                <p className="profile__blurb">{f.desc || "Your description appears here as you type — what you do and why it matters to Alliance."}</p>
                {offers.length>0 && <div className="profile__tags">{offers.slice(0,6).map((t)=><span className="profile__tag" key={t}>{t}</span>)}</div>}
                {(f.address || f.hours || f.phone || f.web) && <div className="lsp-priceline">{f.address && <span>{f.address}</span>}{f.hours && <span>{f.hours}</span>}{f.phone && <span>{f.phone}</span>}{f.web && <span><b>{f.web}</b></span>}</div>}
              </div>
            </div>

            <div className="lsp-after">
              <div className="lsp-after__h">What happens after you submit</div>
              <ol className="lsp-after__steps">
                <li>Our editors review every listing for quality and fit.</li>
                <li>We publish it to the Local Index, usually within a few days.</li>
                <li>Readers find you and inquiries reach you directly —<br />you keep every lead.</li>
              </ol>
              <p className="lsp-after__note">This is exactly how your listing appears to readers.<br />Reviewed before it goes live.</p>
            </div>
          </aside>
        </form>
      </div></section>
    </main>
  );
}

/* ===================== SUBMIT ===================== */
function SubmitPage() {
  const D = C();
  const [type, setType] = useState(D.SUBMIT_TYPES[0]);
  const [form, setForm] = useState({ title: "", body: "", name: "", email: "" });
  const [sent, setSent] = useState(false);
  const set = (k) => (e) => setForm((f) => ({ ...f, [k]: e.target.value }));
  const submit = async (e) => {
    e.preventDefault();
    const ok = await window.captureOrAlert("submissions", { type, ...form });
    if (!ok) return;
    setSent(true); window.scrollTo(0,0);
  };
  return (
    <main className="route">
      <section className="phead">
        <div className="wrap">
          <div className="phead__kick">Contribute</div>
          <h1 className="phead__title">Submit to The Carnation</h1>
          <p className="phead__dek">Nominate a business, flag a space, pitch a story, answer an open question, or send a correction. Good leads become coverage.</p>
          <hr className="rule rule--double phead__rule" />
        </div>
      </section>

      <section className="section section--tight">
        <div className="wrap wrap--narrow">
          {sent ? (
            <div className="sent">Thank you. Your submission is in — <b>The Carnation</b> reviews every lead, and you'll hear back if we follow it.</div>
          ) : (
            <form className="form" onSubmit={submit}>
              <div className="frow">
                <label>What are you sending?</label>
                <div className="chips">
                  {D.SUBMIT_TYPES.map((t) => (
                    <button type="button" key={t} className={"chip" + (type === t ? " on" : "")} onClick={() => setType(t)}>{t}</button>
                  ))}
                </div>
              </div>
              <div className="frow"><label>Title / Subject</label><input className="input" required value={form.title} onChange={set("title")} placeholder={type === "Business Nomination" ? "Name of the business" : "A short, clear headline"} /></div>
              <div className="frow"><label>Tell us about it</label><textarea className="textarea" required value={form.body} onChange={set("body")} placeholder="What's the story, and why does it matter to Alliance right now?"></textarea></div>
              <div className="frow"><label>Your name</label><input className="input" value={form.name} onChange={set("name")} placeholder="Optional, but helpful" /></div>
              <div className="frow"><label>Email</label><input className="input" type="email" value={form.email} onChange={set("email")} placeholder="So we can follow up" /></div>
              <div style={{display:"flex", gap:"14px", alignItems:"center", flexWrap:"wrap"}}>
                <button className="btn btn--red btn--lg" type="submit">Send to The Carnation <span className="arw">→</span></button>
                <span className="note">We read everything. Not everything runs.</span>
              </div>
            </form>
          )}
        </div>
      </section>
    </main>
  );
}

/* ===================== SPOTLIGHT ===================== */
function SpotlightPage({ slug }) {
  const D = C();
  useEffect(() => { window.scrollTo(0, 0); }, [slug]);

  if (slug) {
    const s = D.bySpot(slug);
    if (!s) {
      return <main className="route"><section className="section"><div className="wrap wrap--narrow">
        <p className="note">That spotlight could not be found. <a href="#/spotlight" style={{color:"var(--red)"}}>Back to Spotlight →</a></p>
      </div></section></main>;
    }
    return (
      <main className="route art">
        <div className="wrap wrap--mid">
          <a className="backlink" href="#/spotlight">← Spotlight</a>
          <header className="art__head">
            <div className="art__cat">{s.sponsored ? "Sponsored Spotlight" : "Spotlight"} · {s.kind}</div>
            <h1 className="art__title">{s.name}</h1>
            <p className="art__dek">{s.blurb}</p>
            <div className="art__byline"><span>{s.meta}</span></div>
          </header>
        </div>
        <div className="wrap wrap--mid"><Cover variant={s.cover} tag={s.kind} slot={"cover:spot:" + s.slug} className="art__cover" alt={s.name} /></div>
        <div className="wrap"><div className="art__body">
          {s.sponsored && <p className="note" style={{borderLeft:"3px solid var(--red)", paddingLeft:"16px", marginBottom:"1.4em"}}>This is a sponsored Spotlight, produced in partnership with {s.name}. The Carnation labels every paid feature.</p>}
          {s.facts && (
            <div className="facts">
              {s.facts.map((f) => (
                <div className="fact" key={f[0]}><span className="fact__k">{f[0]}</span><span className="fact__v">{f[1]}</span></div>
              ))}
            </div>
          )}
          {(s.body || []).map((b, i) => {
            if (typeof b === "string") return <p key={i}>{b}</p>;
            if (b.h) return <h3 key={i}>{b.h}</h3>;
            if (b.pull) return <p className="art__pull" key={i}>{b.pull}</p>;
            if (b.img) return (
              <figure className="art__fig" key={i}>
                <Cover variant={b.plate || s.cover} slot={b.img} className="art__fig-img" alt={b.cap || ""} />
                {b.cap && <figcaption className="art__cap">{b.cap}</figcaption>}
              </figure>
            );
            return null;
          })}
          <div className="art__actions" style={{justifyContent:"center", borderTop:"1px solid var(--line)", borderBottom:"1px solid var(--line)", padding:"16px 0", margin:"8px 0 0"}}>
            <ShareRow title={s.name} url={postUrl("spotlight", s.slug)} />
          </div>
          {D.articlesFor(s.slug).length > 0 && (
            <div className="spot-featured">
              <SecRule title="Featured in The Carnation" meta={D.articlesFor(s.slug).length + (D.articlesFor(s.slug).length === 1 ? " story" : " stories")} />
              <div className="feat-list">
                {D.articlesFor(s.slug).map((x) => (
                  <a className="featrow" href={"#/article/" + x.slug} key={x.slug}>
                    <span className="featrow__date">{x.date}</span>
                    <div className="featrow__body">
                      <span className="featrow__cat">{x.category}</span>
                      <span className="featrow__t">{x.title}</span>
                      <span className="featrow__d">{x.dek}</span>
                    </div>
                    <span className="featrow__go arw">→</span>
                  </a>
                ))}
              </div>
            </div>
          )}
          <div className="art__foot">
            <p className="note">Want a Spotlight like this for your business or organization? <a href="#/advertise" style={{color:"var(--red)"}}>See how it works →</a></p>
          </div>
        </div></div>
      </main>
    );
  }

  return (
    <main className="route">
      <section className="phead"><div className="wrap">
        <div className="phead__kick">Featured</div>
        <h1 className="phead__title">Spotlights</h1>
        <p className="phead__dek">Profiles of the people, businesses, builders, artists, workers, owners, and neighbors shaping Alliance in visible and invisible ways. Some are editorial selections; sponsored spotlights are clearly labeled.</p>
        <hr className="rule rule--double phead__rule" />
      </div></section>
      <section className="section section--tight"><div className="wrap">
        <Reveal>
          <div className="listgrid rail rise">
            {D.SPOTLIGHTS.map((s) => <SpotlightCard s={s} key={s.slug} />)}
          </div>
          <div className="rail-hint" aria-hidden="true">Swipe <span className="arw">→</span></div>
        </Reveal>
      </div></section>
    </main>
  );
}

/* ===================== MEDIA KIT — partnership intake ===================== */
const MK_INTEREST = ["Annual Business Presence", "Spotlight Feature", "Dispatch Sponsorship", "Founding Sponsor", "Section Partnership", "Regional Partnership", "Civic / Economic Partnership", "Strategic Civic Partnership", "Guide Sponsorship", "Property / Space Activation", "Not sure yet"];
const MK_BUDGET = ["Under $1,000", "$1,000 to $2,500", "$2,500 to $10,000", "$10,000 to $25,000", "$25,000 to $100,000", "$100,000+", "Not sure yet"];
const MK_GOALS = ["Visibility", "Local credibility", "Business growth", "Downtown development", "Talent attraction", "Resident attraction", "Visitor attraction", "Event promotion", "Property / space activation", "Institutional support", "Economic development", "Other"];

function downloadMediaKit() {
  const lines = [
    "THE CARNATION — PARTNER & MEDIA KIT", "A civic journal for Alliance, Ohio, and the future of American places.", "carnationpost.com  ·  partners@carnationpost.com", "",
    "WHO READS IT", "Founders, operators, property owners, civic leaders, and residents building the next Alliance.", "",
    "SPOTLIGHTS & DISPATCH", "  Editorial Spotlight ....... $150 once (remote / submitted materials)", "  In-House Spotlight ....... $400 once (our visit, interview & photo shoot)", "  Dispatch Sponsor ......... $75 per issue", "  Monthly Dispatch Sponsor . $250 / month", "",
    "THE LOCAL INDEX (BUSINESS)", "  Basic Record ............. Free", "  Annual Presence .......... $35 / mo (billed annually, $420)", "  Founding Business ........ $55 / mo (billed annually, $660)", "",
    "AVAILABLE SPACES (PROPERTY)", "  Listed Space ............. Free", "  Featured Space ........... $35 / month", "  Space Spotlight .......... $400 once", "  Property Activation ...... from $750", "",
    "SUPPORT THE LAUNCH", "  Founding Supporter ....... $100+", "  Founding Sponsor ......... $500+", "  Founding Patron .......... $1,000+", "  Founding Benefactor ...... $5,000+", "",
    "CIVIC & INSTITUTIONAL PARTNERSHIPS", "  Section Partner .......... from $1,500 / year", "  Regional Partner ......... by inquiry", "  Economic Development ..... custom", "",
    "INDEPENDENCE", "Paid partnerships do not buy editorial control. Sponsored work is clearly labeled.", "Partner-supported guides and campaigns are identified. Funding is disclosed.",
  ];
  const blob = new Blob([lines.join("\n")], { type: "text/plain" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url; a.download = "The-Carnation-Media-Kit.txt";
  document.body.appendChild(a); a.click(); document.body.removeChild(a);
  setTimeout(() => URL.revokeObjectURL(url), 1000);
}

function MediaKitPage() {
  const [sent, setSent] = useState(false);
  const [f, setF] = useState({ name: "", email: "", org: "", role: "", link: "", phone: "", interest: MK_INTEREST[0], budget: MK_BUDGET[0], note: "" });
  const [goals, setGoals] = useState([]);
  const [consent, setConsent] = useState(false);
  const set = (k) => (e) => setF((s) => ({ ...s, [k]: e.target.value }));
  const toggleGoal = (g) => setGoals((a) => a.includes(g) ? a.filter((x) => x !== g) : [...a, g]);
  const submit = async (e) => {
    e.preventDefault();
    if (!consent) return;
    const ok = await window.captureOrAlert("submissions", { type: "Media Kit Request", title: f.org || f.name, body: f.note, name: f.name, email: f.email,
      mediakit: { org: f.org, role: f.role, link: f.link, phone: f.phone, interest: f.interest, budget: f.budget, goals } });
    if (!ok) return;
    setSent(true); window.scrollTo(0, 0);
  };

  if (sent) {
    return (
      <main className="route">
        <section className="phead"><div className="wrap">
          <div className="phead__kick">Partner With The Carnation</div>
          <h1 className="phead__title">Thank you. Here's the kit.</h1>
          <p className="phead__dek">View or print the current media kit below. We'll review your request and follow up if there's a strong fit for a sponsor, partner, or custom civic package.</p>
          <hr className="rule rule--double phead__rule" />
        </div></section>
        <section className="section section--tight"><div className="wrap wrap--narrow">
          <div style={{display:"flex", gap:"14px", flexWrap:"wrap"}}>
            <a className="btn btn--red btn--lg" href="#/press">Open the Media Kit <span className="arw">→</span></a>
            <a className="btn btn--line btn--lg" href="#/contact">Schedule a Partner Call</a>
          </div>
          <p className="note" style={{marginTop:"22px"}}>Questions in the meantime? Email <a href="mailto:partners@carnationpost.com" style={{color:"var(--red)"}}>partners@carnationpost.com</a>.</p>
        </div></section>
      </main>
    );
  }

  return (
    <main className="route">
      <section className="phead"><div className="wrap">
        <div className="phead__kick">Partner With The Carnation</div>
        <h1 className="phead__title">Request the Media Kit.</h1>
        <p className="phead__dek">Tell us what you are trying to build, fund, or bring into view. We'll send the current partner kit and recommend the right path, whether that's a sponsored feature, an annual presence, or a custom civic partnership.</p>
        <hr className="rule rule--double phead__rule" />
      </div></section>

      <section className="section section--tint"><div className="wrap">
        <form className="form lsp-build" onSubmit={submit} style={{gridTemplateColumns:"1fr"}}>
          <div className="lsp-form" style={{maxWidth:"760px"}}>
            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">01</span> About you</div>
              <div className="lsp-grid2">
                <div className="frow"><label>Name</label><input className="input" required value={f.name} onChange={set("name")} placeholder="Your name" /></div>
                <div className="frow"><label>Email</label><input className="input" type="email" required value={f.email} onChange={set("email")} placeholder="you@email.com" /></div>
              </div>
              <div className="lsp-grid2">
                <div className="frow"><label>Business / organization</label><input className="input" value={f.org} onChange={set("org")} placeholder="Company, institution, or group" /></div>
                <div className="frow"><label>Role / title</label><input className="input" value={f.role} onChange={set("role")} placeholder="Owner, director, partner…" /></div>
              </div>
              <div className="lsp-grid2">
                <div className="frow"><label>Website or social link</label><input className="input" value={f.link} onChange={set("link")} placeholder="carnationpost.com or @handle" /></div>
                <div className="frow"><label>Phone <span className="note" style={{textTransform:"none",letterSpacing:0}}>· optional</span></label><input className="input" value={f.phone} onChange={set("phone")} placeholder="(330) 555-0100" /></div>
              </div>
            </fieldset>

            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">02</span> What you're interested in</div>
              <div className="lsp-grid2">
                <div className="frow"><label>Interest area</label><select className="select" value={f.interest} onChange={set("interest")}>{MK_INTEREST.map((x) => <option key={x}>{x}</option>)}</select></div>
                <div className="frow"><label>Estimated budget</label><select className="select" value={f.budget} onChange={set("budget")}>{MK_BUDGET.map((x) => <option key={x}>{x}</option>)}</select></div>
              </div>
              <div className="frow"><label>What are you trying to accomplish?</label>
                <div className="lsp-seg">{MK_GOALS.map((g) => <button type="button" key={g} className={"chip" + (goals.includes(g) ? " on" : "")} onClick={() => toggleGoal(g)}>{g}</button>)}</div>
              </div>
            </fieldset>

            <fieldset className="lsp-fieldset">
              <div className="lsp-fieldset__label"><span className="num">03</span> Brief note</div>
              <div className="frow"><label>Tell us what you are trying to support, promote, fund, or build</label><textarea className="textarea" value={f.note} onChange={set("note")} placeholder="A sentence or two is plenty. The more specific, the better we can route it." /></div>
            </fieldset>

            <label className="mk-consent">
              <input type="checkbox" checked={consent} onChange={(e) => setConsent(e.target.checked)} required />
              <span>I understand that sponsored placements and partner-supported work are clearly labeled and do not buy editorial control.</span>
            </label>

            <div style={{display:"flex", gap:"14px", alignItems:"center", flexWrap:"wrap", marginTop:"18px"}}>
              <button className="btn btn--red btn--lg" type="submit" disabled={!consent}>Request Media Kit <span className="arw">→</span></button>
              <span className="note">We'll send the kit and recommend the right path.</span>
            </div>
          </div>
        </form>
      </div></section>
    </main>
  );
}

/* ===================== PRESS / MEDIA KIT (viewable, printable) ===================== */
function PressKitPage() {
  const D = C();
  const Row = ({ label, price }) => (
    <div className="kit-rate"><span className="kit-rate__l">{label}</span><span className="kit-rate__dots" /><span className="kit-rate__p">{price}</span></div>
  );
  const year = new Date().getFullYear();
  return (
    <main className="route kit">
      <section className="kit-cover">
        <span className="kit-cover__wm" aria-hidden="true"><CarnationMark sprig /></span>
        <div className="wrap wrap--mid kit-cover__in">
          <div className="kit-cover__kick">Media &amp; Partner Kit · {year}</div>
          <span className="kit-cover__seal" aria-hidden="true"><CarnationMark sprig /></span>
          <h1 className="kit-cover__title">The Carnation</h1>
          <p className="kit-cover__tag">A civic journal for Alliance, Ohio,<br />and the future of American places.</p>
          <p className="kit-cover__thesis">What happens when overlooked American towns stop waiting for the future, and start building it.</p>
          <div className="kit-cover__meta">Vol. I — No. 1 · Alliance, Ohio · Est. 1854</div>
          <div className="kit-cover__actions">
            <button type="button" className="btn btn--red btn--lg kit-print" onClick={() => window.print()}>Save as PDF <span className="arw">↓</span></button>
            <a className="btn btn--line btn--lg kit-cover__btn" href="#/media-kit">Request a partnership</a>
          </div>
        </div>
      </section>

      <section className="section section--tight"><div className="wrap wrap--mid">
        <SecRule title="The brand" meta="Identity" />
        <div className="kit-brand">
          <div className="kit-logo">
            <span className="kit-logo__mark" aria-hidden="true"><CarnationMark sprig /></span>
            <div><div className="kit-logo__name">The Carnation</div><div className="kit-logo__sub">The Carnation City<br />Est. 1854</div></div>
          </div>
          <div className="kit-swatches">
            <div className="kit-sw" style={{background:"#c32219"}}><span>Scarlet</span><b>#C32219</b></div>
            <div className="kit-sw" style={{background:"#152364"}}><span>Navy</span><b>#152364</b></div>
            <div className="kit-sw" style={{background:"#15110c"}}><span>Ink</span><b>#15110C</b></div>
            <div className="kit-sw kit-sw--light" style={{background:"#ffffff"}}><span>Paper</span><b>#FFFFFF</b></div>
          </div>
        </div>
        <div className="kit-type">
          <div className="kit-type__row"><span className="kit-type__spec" style={{fontFamily:"var(--serif)"}}>Aa</span><div><div className="kit-type__name">Serif · Headlines &amp; body</div><div className="kit-type__demo" style={{fontFamily:"var(--serif)"}}>The record of a city becoming.</div></div></div>
          <div className="kit-type__row"><span className="kit-type__spec" style={{fontFamily:"var(--mono)"}}>Aa</span><div><div className="kit-type__name">Mono · Labels &amp; meta</div><div className="kit-type__demo kit-type__demo--mono" style={{fontFamily:"var(--mono)"}}>COMMUNITY-SUPPORTED · NO PAYWALL</div></div></div>
        </div>
      </div></section>

      <section className="section section--tight"><div className="wrap wrap--mid">
        <SecRule title="Why the carnation" meta="The name" />
        <div className="kit-flower">
          <div className="kit-flower__seal" aria-hidden="true"><CarnationMark sprig /></div>
          <div>
            <p className="kit-lede" style={{marginBottom:"12px"}}>The scarlet carnation is the official state flower of Ohio, and Alliance is its birthplace. In the 1800s a local doctor, Levi Lamborn, grew the celebrated red carnation here; Ohio later adopted it as the state flower and named Alliance the Carnation City.</p>
            <p className="note" style={{fontSize:"1rem"}}>We took the name because it already carries the mission: something rooted in one place that grows to mean more than one place. The scarlet carnation is the city's emblem, Ohio's flower, and our masthead.</p>
          </div>
        </div>
      </div></section>

      <section className="section section--tint section--tight"><div className="wrap wrap--mid">
        <SecRule title="About The Carnation" meta="Press boilerplate" />
        <p className="kit-lede" style={{maxWidth:"74ch"}}>The Carnation is an independent civic journal rooted in Alliance, Ohio, publishing stories, ideas, business coverage, local intelligence, and future-facing essays for the people, places, and possibilities shaping the next chapter of overlooked American places. Free to read, it is supported by readers, sponsors, and civic partners. The Carnation is a publication of Alliance Renaissance.</p>
        <p className="note" style={{marginTop:"10px"}}>For interviews, partnerships, or press: <a href="mailto:partners@carnationpost.com" style={{color:"var(--red)"}}>partners@carnationpost.com</a></p>
      </div></section>

      <section className="section--ink kit-quoteband"><div className="wrap wrap--mid">
        <p className="kit-quote"><span className="kit-quote__mark">“</span>The next chapter of American places won't be written in the biggest cities. It will be built in the ones everyone wrote off.</p>
        <div className="kit-glance">
          <div className="kit-g"><b>2026</b><span>Founded</span></div>
          <div className="kit-g"><b>Free</b><span>To read, always</span></div>
          <div className="kit-g"><b>6</b><span>Editorial beats</span></div>
          <div className="kit-g"><b>100%</b><span>Independent</span></div>
        </div>
      </div></section>

      <section className="section section--tight"><div className="wrap wrap--mid">
        <div className="kit-facts">
          <div className="kit-fact"><span className="kit-fact__k">Published by</span><span className="kit-fact__v">Alliance Renaissance</span></div>
          <div className="kit-fact"><span className="kit-fact__k">Home base</span><span className="kit-fact__v">Alliance, Ohio</span></div>
          <div className="kit-fact"><span className="kit-fact__k">Founded</span><span className="kit-fact__v">2026</span></div>
          <div className="kit-fact"><span className="kit-fact__k">Rhythm</span><span className="kit-fact__v">Biweekly features, periodic notes &amp; The Dispatch</span></div>
          <div className="kit-fact"><span className="kit-fact__k">Scope</span><span className="kit-fact__v">The Carnation City region, Ohio's new economy, and the future of overlooked American places</span></div>
          <div className="kit-fact"><span className="kit-fact__k">Web</span><span className="kit-fact__v">carnationpost.com</span></div>
        </div>
      </div></section>

      <section className="section section--tint section--tight"><div className="wrap wrap--mid">
        <SecRule title="Who reads it" meta="The audience" />
        <p className="kit-lede">The Carnation is read on purpose by the people deciding the city's next chapter: founders and operators, property owners and developers, civic leaders and institutions, returning residents, and the neighbors who actually show up. It is not a feed people scroll past. It is a publication they trust, share, and act on.</p>
        <div className="kit-aud">
          <div className="kit-aud__c"><span className="kit-aud__n">01</span><h4>Builders &amp; operators</h4><p>The people opening, growing, and reinvesting in Alliance.</p></div>
          <div className="kit-aud__c"><span className="kit-aud__n">02</span><h4>Owners &amp; investors</h4><p>Those holding property and weighing what to do with it.</p></div>
          <div className="kit-aud__c"><span className="kit-aud__n">03</span><h4>Civic &amp; institutional</h4><p>The City, the EDC, Mount Union, and regional partners.</p></div>
          <div className="kit-aud__c"><span className="kit-aud__n">04</span><h4>Residents &amp; returners</h4><p>People choosing whether to stay, return, or build here.</p></div>
        </div>
      </div></section>

      <section className="section section--tight"><div className="wrap wrap--mid">
        <SecRule title="Ways to partner" meta="Rate card" />
        <div className="kit-cols">
          <div>
            <h4 className="kit-grp">Spotlights &amp; Dispatch</h4>
            {D.COVERAGE_PRODUCTS.map((p) => <Row key={p.id} label={p.name} price={p.price + (p.cadence ? " " + p.cadence : "")} />)}
            <h4 className="kit-grp">The Local Index — business</h4>
            {D.LISTING_LEVELS.map((l) => <Row key={l.id} label={l.label} price={l.price + (l.cadence || "")} />)}
            <h4 className="kit-grp">Available spaces — property</h4>
            {SPACE_PLANS.map((p) => <Row key={p.id} label={p.label} price={p.price + (p.cadence || "")} />)}
          </div>
          <div>
            <h4 className="kit-grp">Support the Launch</h4>
            {D.FOUNDING_LADDER.map((t) => <Row key={t.label} label={t.label} price={t.price} />)}
            <h4 className="kit-grp">Civic &amp; Institutional Partnerships</h4>
            {D.PARTNER_PACKAGES.map((p) => <Row key={p.id} label={p.name} price={p.price + (p.cadence || "")} />)}
          </div>
        </div>
      </div></section>

      <section className="section section--ink section--tight"><div className="wrap wrap--mid">
        <SecRule title="Independence" meta="How we work" />
        <p className="indep-lead">Support the work.<br />Never the verdict.</p>
        <div className="indep-grid">
          <div className="indep"><span className="indep__n">01</span><h4>No bought coverage</h4><p>Paid partnerships never buy editorial control or a guaranteed story.</p></div>
          <div className="indep"><span className="indep__n">02</span><h4>Always labeled</h4><p>Sponsored work and partner-supported guides are clearly identified, on the page and in every share.</p></div>
          <div className="indep"><span className="indep__n">03</span><h4>Funding disclosed</h4><p>How we're funded is public, because reader trust is the publication's most valuable asset.</p></div>
          <div className="indep"><span className="indep__n">04</span><h4>Editors decide</h4><p>Editorial judgment stays with the newsroom.<br />Full stop.</p></div>
        </div>
        <div className="kit-cta" style={{marginTop:"clamp(26px,3.5vw,38px)"}}>
          <a className="btn btn--red btn--lg" href="#/media-kit">Request a partnership <span className="arw">→</span></a>
          <a className="btn btn--line btn--lg" href="#/contact">partners@carnationpost.com</a>
        </div>
      </div></section>
    </main>
  );
}

/* ===================== ADVERTISE ===================== */
function AdvertisePage() {
  const D = C();
  const coverageCheckout = {
    "spotlight-ed": "sponsor_spotlight_ed",
    "spotlight-inhouse": "sponsor_spotlight_inhouse",
    "dispatch": "sponsor_dispatch",
    "dispatch-month": "sponsor_dispatch_month",
  };
  const goSec = (id) => { const el = document.getElementById(id); if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 70, behavior: "smooth" }); };
  useEffect(() => {
    const m = (location.hash.split("?")[1] || "").match(/at=([\w-]+)/);
    if (!m) return;
    const id = m[1];
    const t = setTimeout(() => {
      const el = document.getElementById(id);
      if (el) window.scrollTo(0, el.getBoundingClientRect().top + window.scrollY - 80);
    }, 90);
    return () => clearTimeout(t);
  }, []);
  return (
    <main className="route">
      <section className="phead"><div className="wrap">
        <div className="phead__kick">Partner With The Carnation</div>
        <h1 className="phead__title">Support the work.<br />Reach the people building Alliance.</h1>
        <p className="phead__dek">Section sponsorships, Spotlight features, premium profiles in The Local Index, and Dispatch placements for businesses, institutions, and civic partners who want to back independent local media and stand beside the stories the city reads on purpose.</p>
        <div className="phead__cta">
          <a className="btn btn--red btn--lg" href="#/press">{D.MEDIA_KIT.primary} <span className="arw">→</span></a>
          <a className="btn btn--line btn--lg" href="#/contact">{D.MEDIA_KIT.secondary}</a>
        </div>
        <hr className="rule rule--double phead__rule" />
      </div></section>

      {/* THREE PATHWAYS */}
      <section className="section section--tight"><div className="wrap">
        <Reveal>
          <SecRule title="Three ways to take part" meta="Find your lane" />
          <div className="lanes rise d1" style={{display:"grid", gridTemplateColumns:"repeat(3, 1fr)", gap:"clamp(16px,1.6vw,22px)", marginTop:"clamp(20px,2.4vw,30px)"}}>

            <div style={{display:"flex", flexDirection:"column", background:"var(--paper)", border:"1px solid var(--line)", borderTop:"3px solid var(--red)", padding:"clamp(22px,2.2vw,30px)"}}>
              <span style={{fontFamily:"var(--mono)", fontSize:".62rem", letterSpacing:".2em", textTransform:"uppercase", color:"var(--red)"}}>For individuals</span>
              <h3 style={{fontFamily:"var(--serif)", fontWeight:600, fontSize:"clamp(1.3rem,1.9vw,1.6rem)", lineHeight:1.08, letterSpacing:"-.01em", margin:"10px 0 0"}}>Founding Supporters</h3>
              <p style={{fontFamily:"var(--serif)", fontSize:".98rem", lineHeight:1.55, color:"var(--ink-2)", margin:"12px 0 0", flex:"1 0 auto"}}>For individuals, families, alumni, and community members who want to help keep The Carnation free, useful, and independent.</p>
              <button className="btn btn--red" onClick={() => goSec("founding")} style={{marginTop:"clamp(18px,2vw,24px)", alignSelf:"flex-start", cursor:"pointer"}}>Become a Founding Supporter <span className="arw">→</span></button>
            </div>

            <div style={{display:"flex", flexDirection:"column", background:"var(--paper)", border:"1px solid var(--line)", borderTop:"3px solid var(--ink)", padding:"clamp(22px,2.2vw,30px)"}}>
              <span style={{fontFamily:"var(--mono)", fontSize:".62rem", letterSpacing:".2em", textTransform:"uppercase", color:"var(--ink)"}}>For local business</span>
              <h3 style={{fontFamily:"var(--serif)", fontWeight:600, fontSize:"clamp(1.3rem,1.9vw,1.6rem)", lineHeight:1.08, letterSpacing:"-.01em", margin:"10px 0 0"}}>Business Partners</h3>
              <p style={{fontFamily:"var(--serif)", fontSize:".98rem", lineHeight:1.55, color:"var(--ink-2)", margin:"12px 0 0", flex:"1 0 auto"}}>For local businesses that want to be discoverable, accurately represented, and considered for profiles, spotlights, and Local Index placement.</p>
              <button className="btn btn--line" onClick={() => goSec("business")} style={{marginTop:"clamp(18px,2vw,24px)", alignSelf:"flex-start", cursor:"pointer"}}>Request Business Options <span className="arw">→</span></button>
            </div>

            <div style={{display:"flex", flexDirection:"column", background:"var(--paper)", border:"1px solid var(--line)", borderTop:"3px solid var(--blue)", padding:"clamp(22px,2.2vw,30px)"}}>
              <span style={{fontFamily:"var(--mono)", fontSize:".62rem", letterSpacing:".2em", textTransform:"uppercase", color:"var(--blue)"}}>For institutions</span>
              <h3 style={{fontFamily:"var(--serif)", fontWeight:600, fontSize:"clamp(1.3rem,1.9vw,1.6rem)", lineHeight:1.08, letterSpacing:"-.01em", margin:"10px 0 0"}}>Civic Partners</h3>
              <p style={{fontFamily:"var(--serif)", fontSize:".98rem", lineHeight:1.55, color:"var(--ink-2)", margin:"12px 0 0", flex:"1 0 auto"}}>For larger supporters, institutions, developers, banks, foundations, and aligned sponsors helping establish The Carnation as part of Alliance&rsquo;s next chapter.</p>
              <a className="btn btn--line" href="#/press" style={{marginTop:"clamp(18px,2vw,24px)", alignSelf:"flex-start"}}>Request Partner Kit <span className="arw">→</span></a>
            </div>

          </div>
        </Reveal>
      </div></section>
      <section className="section section--tight"><div className="wrap">
        <Reveal>
          <SecRule title="Why partner" meta="The case" />
          <div className="why-grid rise d1">
            {D.WHY_ADVERTISE.map((w) => (
              <div className="why" key={w.n}>
                <span className="why__n">{w.n}</span>
                <span className="why__h">{w.h}</span>
                <span className="why__p">{w.p}</span>
              </div>
            ))}
          </div>
        </Reveal>
      </div></section>

      {/* FEATURED & SPONSORED COVERAGE — rate card */}
      <section id="coverage" className="section section--tight"><div className="wrap">
        <Reveal>
          <SecRule title="Spotlights &amp; Dispatch" meta="Rate card" />
          <div className="rategrid rise d1" style={{gridTemplateColumns:"repeat(2, 1fr)"}}>
            {D.COVERAGE_PRODUCTS.map((p) => (
              <div className={"ratecard" + (p.feat ? " ratecard--feat" : "")} key={p.id}>
                {p.feat && <span className="ratecard__tag">Most requested</span>}
                <span className="ratecard__name">{p.name}</span>
                <span className="ratecard__price">{p.mo ? (<React.Fragment>{p.mo}<span className="ratecard__cadence">/mo · billed annually ({p.price}{p.cadence})</span></React.Fragment>) : (<React.Fragment>{p.price}{p.cadence && <span className="ratecard__cadence">{p.cadence}</span>}</React.Fragment>)}</span>
                <p className="ratecard__desc">{p.desc}</p>
                <ul className="ratecard__inc">{p.includes.map((x) => <li key={x}>{x}</li>)}</ul>
                <a className={"btn ratecard__cta " + (p.feat ? "btn--red" : "btn--line")}
                  href={window.payLink ? (window.payLink(coverageCheckout[p.id]) || p.ctaPath) : p.ctaPath}>
                  {window.payReady && window.payReady(coverageCheckout[p.id]) ? "Reserve now" : p.cta} <span className="arw">→</span>
                </a>
              </div>
            ))}
          </div>
        </Reveal>
      </div></section>

      {/* LOCAL INDEX LISTINGS */}
      <section id="business" className="section section--tint"><div className="wrap">
        <Reveal>
          <SecRule title="Local Index Visibility" meta="Publication visibility" />
          <p className="note rise" style={{maxWidth:"62ch", fontSize:"1rem", marginBottom:"clamp(22px,2.6vw,34px)"}}>The Local Index is a living record of Alliance businesses, places, builders, and organizations, built to make the local economy easier to see, support, and understand. Every business can start with a free Basic Record, and some choose to do more.</p>
          <div className="levels rise d1">
            {D.LISTING_LEVELS.map((lv) => (
              <div className={"level" + (lv.feat ? " level--feat" : "")} key={lv.id}>
                <span className="level__label">{lv.label}</span>
                <span className="level__price">{lv.mo ? (<React.Fragment>{lv.mo}<span className="level__cadence">/mo</span><span className="level__alt">billed annually · {lv.price}{lv.cadence}</span></React.Fragment>) : (<React.Fragment>{lv.price}{lv.cadence && <span className="level__cadence">{lv.cadence}</span>}{lv.alt && <span className="level__alt">{lv.alt}</span>}</React.Fragment>)}</span>
                <span className="level__desc">{lv.desc}</span>
                <span className="level__perks">
                  {lv.perks.map((p) => <span className="level__perk" key={p}><span className="level__check">✓</span>{p}</span>)}
                </span>
                <a className={"btn " + (lv.feat ? "btn--red" : "btn--line")} href={lv.ctaPath} style={{marginTop:"auto", alignSelf:"flex-start"}}>{lv.cta} <span className="arw">→</span></a>
                {lv.note && <span className="level__note">{lv.note}</span>}
              </div>
            ))}
          </div>
          <p className="note rise" style={{marginTop:"clamp(20px,2.4vw,30px)", fontSize:".95rem"}}>Prices are shown as a monthly equivalent for clarity. The Carnation works in annual partnerships, billed once a year — not month-to-month.<br />Founding listing options are available for Alliance businesses, organizations, and property owners.</p>
        </Reveal>
      </div></section>

      {/* FOUNDING THE PUBLICATION — supporter ladder */}
      <section id="founding" className="section"><div className="wrap wrap--mid">
        <Reveal>
          <SecRule title="Support the Launch" meta="Launch-year support" />
          <p className="note rise" style={{maxWidth:"54ch", fontSize:"1rem", marginBottom:"clamp(22px,2.6vw,32px)", textWrap:"balance"}}>For individuals, families, businesses, and civic supporters who want The Carnation to remain free, useful, and independent.</p>
          <div className="pladder rise d1">
            {D.FOUNDING_LADDER.map((t) => (
              <div className={"pl-row" + (t.feat ? " pl-row--feat" : "")} key={t.label}>
                <div>
                  <div className="pl-row__label">{t.label}</div>
                  <div className="pl-row__desc">{t.desc}</div>
                </div>
                <div className="pl-row__price">{t.price}</div>
              </div>
            ))}
          </div>
          <div style={{marginTop:"clamp(20px,2.4vw,28px)"}}><a className="btn btn--red" href="#/media-kit">Become a Founding Supporter <span className="arw">→</span></a></div>
        </Reveal>
      </div></section>

      {/* INSTITUTIONAL PARTNERSHIPS — rate card */}
      <section id="civic" className="section section--tint"><div className="wrap">
        <Reveal>
          <SecRule title="Civic &amp; Institutional Partnerships" meta="For the long view" />
          <div className="rategrid rise d1">
            {D.PARTNER_PACKAGES.map((p) => (
              <div className={"ratecard" + (p.feat ? " ratecard--feat" : "")} key={p.id}>
                {p.feat && <span className="ratecard__tag">Presenting partner</span>}
                <span className="ratecard__name">{p.name}</span>
                <span className="ratecard__price">{p.mo ? (<React.Fragment>{p.mo}<span className="ratecard__cadence">/mo · billed annually ({p.price}{p.cadence})</span></React.Fragment>) : (<React.Fragment>{p.price}{p.cadence && <span className="ratecard__cadence">{p.cadence}</span>}</React.Fragment>)}</span>
                <p className="ratecard__desc">{p.desc}</p>
                <ul className="ratecard__inc">{p.includes.map((x) => <li key={x}>{x}</li>)}</ul>
                <a className={"btn ratecard__cta " + (p.feat ? "btn--red" : "btn--line")} href={p.ctaPath}>{p.cta} <span className="arw">→</span></a>
                {p.note && <span className="level__note" style={{marginTop:"12px"}}>{p.note}</span>}
              </div>
            ))}
          </div>
          <p className="note rise" style={{marginTop:"clamp(20px,2.4vw,30px)", fontSize:".95rem"}}>Civic and institutional partnerships are annual agreements, billed once a year. Monthly figures are shown only to make the value easy to read — we don&rsquo;t do month-to-month.</p>
        </Reveal>
      </div></section>

      {/* REQUEST MEDIA KIT */}
      <section className="section"><div className="wrap">
        <Reveal>
          <div className="dual rise">
            <div className="dual__cell">
              <span className="dual__stamp" aria-hidden="true"><CarnationMark compact /></span>
              <span className="dual__kick">Get the details</span>
              <h3 className="dual__h">See the media kit.</h3>
              <p className="dual__p">Our full partner kit, rates, and brand are public. See the kit, then tell us what you're building and we'll recommend the right placement. Founding rates and launch-year pricing are available.</p>
              <div style={{display:"flex", gap:"12px", flexWrap:"wrap", marginTop:"auto"}}>
                <a className="btn btn--red" href="#/press">{D.MEDIA_KIT.primary} <span className="arw">→</span></a>
                <a className="btn btn--line" href="#/contact">{D.MEDIA_KIT.secondary}</a>
              </div>
            </div>
            <div className="dual__cell dual__cell--ink">
              <span className="dual__kick">No strings on the newsroom</span>
              <h3 className="dual__h">Independent, and labeled.</h3>
              <p className="dual__p">Sponsorships, listings, and partner-supported guides never guarantee or block editorial coverage. Paid placements are labeled. Funding is public because reader trust is the publication's most valuable asset.</p>
              <div style={{display:"flex", gap:"12px", flexWrap:"wrap", marginTop:"auto"}}>
                <a className="btn btn--line" href="#/ethics">Ethics & standards</a>
                <a className="btn btn--line" href="#/funding">How we're funded</a>
              </div>
            </div>
          </div>
        </Reveal>
        <p className="note" style={{marginTop:"22px"}}>Prefer to back the work directly?<br />The Carnation also takes <a href="#/membership" style={{color:"var(--red)"}}>memberships and founding-supporter recognition</a>, no sponsorship required.</p>
      </div></section>
    </main>
  );
}

/* ===================== ABOUT ===================== */
function AboutPage() {
  return (
    <main className="route">
      <section className="phead">
        <div className="wrap">
          <div className="phead__kick">About · The Carnation</div>
          <h1 className="phead__title">The record of a city becoming.</h1>
          <p className="phead__dek">The Carnation is an independent civic journal rooted in Alliance, Ohio. We publish stories, ideas, profiles, guides, and local intelligence for the people, places, and possibilities shaping the next chapter of overlooked American cities. Free to read, built by the sponsors, partners, and readers who believe local culture deserves a serious record.</p>
          <hr className="rule rule--double phead__rule" />
        </div>
      </section>

      <section className="section pullband">
        <div className="wrap wrap--mid"><Reveal>
          <p className="pullband__q rise"><span className="lead">“</span>Alliance is not a place things happened to. It is a place things get built.<span className="lead lead--close">”</span></p>
          <p className="pullband__by rise d1">The premise of this publication</p>
        </Reveal></div>
      </section>

      <section className="section">
        <div className="wrap"><Reveal>
          <SecRule title="Why this, why now" meta="The premise" />
          <div className="art__body rise" style={{maxWidth:"720px", margin:"0 0 8px"}}>
            <p>Across the country, towns like Alliance get written off in a sentence: past their peak, defined by what left. That sentence is lazy, and increasingly wrong.</p>
            <p>The things that once made these places hard to leave are quietly making them worth returning to. Real main streets. Room to build. Neighbors who know your name. A cost of living that leaves space for a life. Cheap rent, remote work, local ownership, and new technology are putting small cities back in the conversation.</p>
            <p>Alliance has the bones most cities tore down: a downtown worth walking, a college that fills the streets every fall, institutions that never moved, and people who stayed on purpose. What has been missing is not potential. It is a clear, honest account of what is happening, and a public argument about what could.</p>
            <p>The Carnation keeps that account. We cover culture, business, spaces, memory, public life, technology, the local economy, and civic futures: what opens, what waits, who bets on the city, and what Alliance could become next. None of it is nostalgia. It is a wager that a city which narrates itself clearly and ambitiously gets to author its own next chapter. If it works here, it can work in a hundred places like it.</p>
          </div>
          <div className="pillars rise d1">
            <div className="pillar"><span className="pillar__n">01</span><span className="pillar__h">Attract</span><span className="pillar__p">Talent, business, and the people deciding whether to stay, return, or build.</span></div>
            <div className="pillar"><span className="pillar__n">02</span><span className="pillar__h">Document</span><span className="pillar__p">The change as it happens: what opens, what waits, who bets on the city.</span></div>
            <div className="pillar"><span className="pillar__n">03</span><span className="pillar__h">Decide</span><span className="pillar__p">The questions a city should be asking in public, before the future arrives without it.</span></div>
          </div>
        </Reveal></div>
      </section>

      <section className="section">
        <div className="wrap"><Reveal>
          <SecRule title="Why we're called The Carnation" meta="The Carnation City" />
          <div className="art__body rise" style={{maxWidth:"720px", margin:"0 0 clamp(28px,3.6vw,46px)"}}>
            <p>The name is not ours. It is the city's. In 1854, three small towns chose to become one and called the result Alliance. A generation later, a local doctor named Levi Lamborn grew a scarlet carnation so admired that Ohio made it the state flower, and named Alliance, officially, the Carnation City.</p>
            <p>We took the name because it already says what we are here to do. The carnation is a symbol of local identity and Ohio history, and of the belief that something rooted in one place can still carry meaning well beyond it.</p>
          </div>
          <div className="miles rise d1">
            <div className="mile"><span className="mile__y">1854</span><span className="mile__t">Three towns, Williamsport, Freedom, and Liberty, merge into one. The name itself is the argument: Alliance.</span></div>
            <div className="mile"><span className="mile__y">1904</span><span className="mile__t">A scarlet carnation grown in Alliance becomes Ohio's state flower, in memory of President McKinley.</span></div>
            <div className="mile"><span className="mile__y">1959</span><span className="mile__t">Ohio officially names Alliance "The Carnation City."</span></div>
            <div className="mile"><span className="mile__y">2026</span><span className="mile__t">The Carnation begins as a civic journal for Alliance's next chapter.</span></div>
          </div>
        </Reveal></div>
      </section>

      <section className="section section--tint">
        <div className="wrap"><Reveal>
          <SecRule title="What we believe" meta="Our standards" href="#/ethics" />
          <div className="dept-grid rise d1">
            <div className="dept"><span className="dept__n">01</span><span className="dept__label">Independent, and free to read</span><span className="dept__desc">No paywall on the city's own story. Backed by local sponsors and readers, not gatekept from them.</span></div>
            <div className="dept"><span className="dept__n">02</span><span className="dept__label">Reported in public</span><span className="dept__desc">We put real questions to the city and publish what Alliance says back. The work happens out in the open.</span></div>
            <div className="dept"><span className="dept__n">03</span><span className="dept__label">Ambitious, not nostalgic</span><span className="dept__desc">We honor the history and refuse to live in it. The Main Street worth building points forward.</span></div>
            <div className="dept"><span className="dept__n">04</span><span className="dept__label">Useful, not just admiring</span><span className="dept__desc">A Local Index you'd actually use, spotlights that drive real visits, coverage you can act on.</span></div>
          </div>
          <div className="rise d2" style={{marginTop:"26px", display:"flex", gap:"12px", flexWrap:"wrap"}}>
            <a className="btn btn--line" href="#/staff">Meet the staff <span className="arw">→</span></a>
            <a className="btn btn--line" href="#/ethics">Ethics & standards</a>
            <a className="btn btn--line" href="#/funding">How we're funded</a>
          </div>
        </Reveal></div>
      </section>

      <section className="section">
        <div className="wrap"><Reveal>
          <div className="dual rise">
            <div className="dual__cell">
              <span className="dual__kick">Part of something larger</span>
              <h3 className="dual__h">The platform, and the journal.</h3>
              <p className="dual__p">Alliance Renaissance is the civic platform. The Carnation is the journal. The Renaissance builds the thesis and the projects. The Carnation publishes the stories, ideas, and local record around it. The Renaissance does the building. The Carnation tells the story, asks the questions, and keeps the city in the room.</p>
              <a className="btn btn--line" href={AR_URL} target="_blank" rel="noopener">Visit Alliance Renaissance <span className="arw">→</span></a>
            </div>
            <div className="dual__cell dual__cell--ink">
              <span className="dual__kick">Take part</span>
              <h3 className="dual__h">Written with the city, not at it.</h3>
              <p className="dual__p">Pitch a story, nominate a business, flag a space, or weigh in on an open question. The good ones become coverage. Sponsorship and memberships keep it free to read.</p>
              <div style={{display:"flex", gap:"12px", flexWrap:"wrap", marginTop:"auto"}}>
                <a className="btn btn--red" href="#/submit">Submit to The Carnation</a>
                <a className="btn btn--line" href="#/membership">Become a member</a>
              </div>
            </div>
          </div>
        </Reveal></div>
      </section>
    </main>
  );
}

window.ArticlePage = ArticlePage;
window.QuestionPage = QuestionPage;
window.SearchPage = SearchPage;
window.TagPage = TagPage;
window.MembershipPage = MembershipPage;
window.SubmitPage = SubmitPage;
window.SpotlightPage = SpotlightPage;
window.AdvertisePage = AdvertisePage;
window.AboutPage = AboutPage;
