// ---------- Posts data ----------
const POSTS = [
  {
    id: "projekty-v-claude",
    title: "Projekty v Claude: váš vlastní AI pracovní prostor",
    dek: "Jak fungují Projekty, kdy je nasadit a proč nahrazují polovinu vašich Notion stránek.",
    tool: "Claude",
    category: "Návody",
    author: "Tereza Vavřincová",
    date: "8. května 2026",
    readTime: 6,
    cover: "screenshot · Claude Projects sidebar",
    featured: true,
    body: [
      { kind: "p", text: "Když Anthropic loni v dubnu spustil Projekty v Claude, řada lidí to vzala jako další chatovací funkci navíc. Po roce práce s desítkami produktových týmů můžu říct, že je to zatím nejvýraznější způsob, jak proměnit Claude z asistenta na opravdový pracovní nástroj." },
      { kind: "p", text: "Projekt je v zásadě složka. Nahrajete do ní dokumenty — PRD, výzkum, transkripty z uživatelských rozhovorů, brand guidelines — a přidáte vlastní instrukce. Každá nová konverzace v tom projektu pak má tohle všechno automaticky v hlavě." },
      { kind: "h2", text: "Kdy projekt vůbec zakládat" },
      { kind: "p", text: "Ne pro každý úkol. Pravidlo: pokud něco budete řešit víc než třikrát a pokaždé budete vysvětlovat tentýž kontext, je čas na projekt. Klasické případy:" },
      { kind: "ul", items: [
        "Onboarding nového člena týmu — instrukce + interní wiki",
        "Příprava produktových oneagerů — PRD šablona + tone of voice",
        "Customer support — historie tiketů + reference odpovědi",
        "Příprava na 1:1 — poznámky z minulých schůzek"
      ]},
      { kind: "h2", text: "Co tam nedávat" },
      { kind: "p", text: "Projekt není Google Drive. Nahrát stovku PDFek znamená, že Claude bude mít horší výsledky, ne lepší — model si musí každou konverzaci procházet vším a začne odpovídat opatrně a obecně. Držte se pod patnácti dokumenty a vyhazujte, co nepoužíváte." },
      { kind: "callout", text: "Tip: napište si do instrukcí projektu, co Claude dělat nemá. „Nikdy nepiš v marketingových superlativech.“ funguje líp než deset příkladů dobrého stylu." },
      { kind: "h2", text: "Jak vypadá dobrá instrukce" },
      { kind: "p", text: "Krátká, konkrétní, s rolí. Místo „pomáhej mi s produktovými texty“ zkuste „Jsi senior copywriter pro B2B SaaS. Píšeš krátké věty, vyhýbáš se buzzwordům, vždycky se ptáš na cílovou personu, než začneš.“ Rozdíl ve výstupu je obrovský." },
      { kind: "p", text: "A poslední věc — projekty nejsou navždy. Když přijde nová verze brand guidelines, přepište je. Když změníte proces, smažte starý projekt a založte nový. Pracovní prostor má dýchat s vámi." }
    ]
  },
  {
    id: "deep-research-chatgpt",
    title: "Deep Research v ChatGPT: když AI udělá rešerši za vás",
    dek: "Tridvacetiminutový agent, který přečte sto zdrojů a napíše vám memo. Co umí, kde selhává a kdy se vyplatí čekat.",
    tool: "ChatGPT",
    category: "Návody",
    author: "Michal Drahokoupil",
    date: "5. května 2026",
    readTime: 8,
    cover: "screenshot · Deep Research progress view",
    featured: false,
    body: [
      { kind: "p", text: "Deep Research je funkce, která zmátla i lidi, kteří ChatGPT používají denně. Není to chat. Není to vyhledávání. Je to agent — pošlete mu zadání, on si dvacet až třicet minut sám prochází internet, čte stránky, dělá si poznámky a pak vrátí strukturovaný report s citacemi." },
      { kind: "h2", text: "Pro co to opravdu funguje" },
      { kind: "p", text: "Konkurenční analýza, market sizing, technologický landscape, regulatorní rešerše. Všechno, co byste jinak zadali juniornímu analytikovi na tři dny. Loni v lednu jsem si nechal udělat report o stavu generativní AI v evropském bankovnictví — třicet stránek, šedesát zdrojů, kompletně použitelné jako brief pro stakeholdery." },
      { kind: "h2", text: "Kde to selhává" },
      { kind: "ul", items: [
        "Hodně čerstvé zprávy (mladší než pár dní)",
        "České zdroje — anglických přečte desetkrát víc",
        "Cokoli za paywall — Bloomberg, Reuters, FT vidí jen útržky",
        "Subjektivní úsudek — „co bychom měli udělat“ neumí, jen „co se děje“"
      ]},
      { kind: "h2", text: "Jak napsat zadání" },
      { kind: "p", text: "Klíčové je dát strukturu výstupu, ne otázku. Místo „udělej mi rešerši o evropském AI Actu“ zkuste: „Připrav memo pro produktového ředitele B2B SaaS. Sekce: 1) co se mění od srpna, 2) tři konkrétní rizika pro nás, 3) co dělají konkurenti. Max 5 stran, vždy s odkazy.“" },
      { kind: "callout", text: "Než zadání odešlete, ChatGPT se vás zeptá na pár doplňujících otázek. Berte to vážně — odpovědi určí kvalitu celého reportu. Neodbývejte to." },
      { kind: "h2", text: "Vyplatí se počkat?" },
      { kind: "p", text: "Pokud potřebujete odpověď do pěti minut, ne. Pokud máte půl hodiny a chcete podklad, na kterém se dá stavět, ano — a hodně. Můj poměr je zhruba jeden Deep Research týdně, většinou v pondělí ráno místo prvního kafe." }
    ]
  },
  {
    id: "custom-gpts-vs-projects",
    title: "Custom GPTs vs Claude Projects: co si vybrat?",
    dek: "Dvě nejpopulárnější cesty, jak personalizovat AI. Srovnání, které vám konečně řekne, kdo má pravdu.",
    tool: "Srovnání",
    category: "Srovnání",
    author: "Tereza Vavřincová",
    date: "30. dubna 2026",
    readTime: 5,
    cover: "screenshot · side-by-side comparison",
    featured: false,
    body: [
      { kind: "p", text: "Otázka, která se v posledních měsících objeví na každém workshopu: máme nasadit Custom GPTs, nebo Claude Projects? Krátká odpověď: záleží na tom, kdo ten nástroj bude používat." },
      { kind: "h2", text: "Custom GPTs jsou pro distribuci" },
      { kind: "p", text: "Když chcete, aby váš asistent používal celá firma — nebo dokonce veřejnost — vyhrávají GPTs. Sdílení odkazem, GPT Store, akce přes API, vlastní logo. Klasický use case: HR helpdesk, který si může otevřít kdokoli ze zaměstnanců." },
      { kind: "h2", text: "Projects jsou pro práci" },
      { kind: "p", text: "Když pracuje jeden člověk nebo malý tým a chce mít nástroj, který se s ním vyvíjí, vyhrává Claude. Lepší práce s dlouhými dokumenty, méně halucinací u faktických rešerší, instrukce se dají měnit za běhu." },
      { kind: "h2", text: "Tabulka, kdyby vás to nutkalo" },
      { kind: "p", text: "Distribuce: GPTs. Kvalita psaní: Projects. Akce přes API: GPTs. Práce s velkým kontextem: Projects. Ekosystém pluginů: GPTs. Soukromí dat: Projects (žádný GPT Store)." },
      { kind: "callout", text: "Ve většině firem, se kterými dělám, končíme u obojího. GPTs pro veřejné/sdílené nástroje, Projects pro individuální pracovní toky." }
    ]
  },
  {
    id: "notebooklm",
    title: "NotebookLM: tichý hit od Googlu",
    dek: "AI poznámkový blok, který si přečte vaše PDF a udělá z nich podcast. Vážně.",
    tool: "Google",
    category: "Návody",
    author: "Jan Pelikán",
    date: "22. dubna 2026",
    readTime: 7,
    cover: "screenshot · NotebookLM source view",
    featured: false,
    body: [
      { kind: "p", text: "Z Googlu poslední dva roky nevychází mnoho věcí, které by stály za článek. NotebookLM je výjimka — nástroj, který v tichosti dělá lepší práci než většina hlučnějších produktů." },
      { kind: "h2", text: "Co to je" },
      { kind: "p", text: "Aplikace, do které nahrajete zdroje (PDF, Google Docs, weby, YouTube videa) a kolem nich vede konverzaci. Klíčový rozdíl od ChatGPT: NotebookLM se drží toho, co jste mu dali. Pokud něco není ve zdrojích, nevymýšlí si — řekne, že to neví." },
      { kind: "h2", text: "Audio Overview" },
      { kind: "p", text: "Funkce, která dělá ten šum. Z nahraných zdrojů NotebookLM vyrobí 10–20 minutový „podcast“ — dva moderátoři spolu diskutují o tom, co jste tam dali. Zní to nepříjemně dobře. Použitelné na briefing před schůzkou, kde nestihnete přečíst všechny materiály." },
      { kind: "callout", text: "Hranice: nebudete chtít NotebookLM podcast pouštět klientovi. Pořád to zní jako AI. Ale jako rychlý orientační poslech to funguje výborně." },
      { kind: "h2", text: "Pro produktové týmy" },
      { kind: "ul", items: [
        "Nahrajte transkripty z uživatelských rozhovorů → ptejte se na patterny",
        "Nahrajte konkurenční webové stránky → ptejte se na rozdíly v poziciování",
        "Nahrajte tři dlouhé strategické dokumenty → vygenerujte FAQ pro tým"
      ]}
    ]
  },
  {
    id: "perplexity-vs-google",
    title: "Perplexity vs Google: nová éra vyhledávání",
    dek: "Kdy přepnout, kdy zůstat. A proč většina lidí mezi nimi přepíná chybně.",
    tool: "Perplexity",
    category: "Srovnání",
    author: "Michal Drahokoupil",
    date: "15. dubna 2026",
    readTime: 6,
    cover: "screenshot · Perplexity answer with sources",
    featured: false,
    body: [
      { kind: "p", text: "Google odpovídá na otázku „kde“. Perplexity odpovídá na otázku „co a proč“. Když si tohle zafixujete, ušetříte si hodiny špatně mířených dotazů." },
      { kind: "h2", text: "Kdy Google" },
      { kind: "ul", items: [
        "Navigace — najdi mi konkrétní web, restauraci, dokument",
        "Aktuálnost v řádu hodin — co se právě stalo",
        "Lokální — kde je nejbližší X",
        "Obrázky a mapy"
      ]},
      { kind: "h2", text: "Kdy Perplexity" },
      { kind: "ul", items: [
        "Vysvětlení konceptu — co to je a jak to funguje",
        "Srovnání více možností — A vs B vs C",
        "Rešerše s citacemi — chcete vědět, odkud informace pochází",
        "Otázka, na kterou byste jinak otevřeli šest záložek"
      ]},
      { kind: "h2", text: "Pro tým" },
      { kind: "p", text: "Perplexity Spaces (jejich obdoba projektů) fungují překvapivě dobře pro sdílené firemní vyhledávání — můžete tam nahrát interní dokumenty a tým hledá zároveň v nich i na webu. Jednotná vrstva, ke které tým má důvěru, je v dnešním zaplaveném prostoru víc, než se zdá." },
      { kind: "callout", text: "Pravidlo palce: pokud jste si u Google výsledků chtěli říct „a teď to někdo prosím shrň“, měli jste jít rovnou do Perplexity." }
    ]
  }
];

const TOOLS = ["Vše", "Claude", "ChatGPT", "Google", "Perplexity", "Srovnání"];
const CATEGORIES = ["Vše", "Návody", "Srovnání", "Názor"];

// ---------- Icons (minimal line, no slop) ----------
const Icon = {
  search: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" {...p}><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>,
  heart: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill={p.filled ? "currentColor" : "none"} stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"><path d="M12 21s-7-4.5-9.5-9A5 5 0 0 1 12 6a5 5 0 0 1 9.5 6c-2.5 4.5-9.5 9-9.5 9z"/></svg>,
  bookmark: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill={p.filled ? "currentColor" : "none"} stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"><path d="M6 3h12v18l-6-4-6 4z"/></svg>,
  share: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="6" cy="12" r="2.5"/><circle cx="18" cy="6" r="2.5"/><circle cx="18" cy="18" r="2.5"/><path d="M8 11l8-4"/><path d="M8 13l8 4"/></svg>,
  arrow: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12h14"/><path d="m13 5 7 7-7 7"/></svg>,
  back: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M19 12H5"/><path d="m11 5-7 7 7 7"/></svg>,
  sun: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" {...p}><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>,
  moon: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>
};

// ---------- Reusable bits ----------
function Cover({ label, ratio = "16/10", tall = false }) {
  return (
    <div className="cover" style={{ aspectRatio: tall ? "4/5" : ratio }}>
      <div className="cover-stripes" />
      <span className="cover-label">{label}</span>
    </div>
  );
}

function Meta({ tool, readTime, date }) {
  return (
    <div className="meta">
      <span className="meta-tool">{tool}</span>
      <span className="meta-dot">·</span>
      <span>{readTime} min čtení</span>
      {date && <><span className="meta-dot">·</span><span>{date}</span></>}
    </div>
  );
}

// ---------- Hero (featured + 2 side) ----------
function Hero({ posts, onOpen, saved, liked, toggleLike, toggleSave }) {
  const featured = posts.find(p => p.featured) || posts[0];
  const side = posts.filter(p => p.id !== featured.id).slice(0, 2);
  return (
    <section className="hero">
      <article className="hero-main" onClick={() => onOpen(featured.id)}>
        <Cover label={featured.cover} ratio="16/9" />
        <div className="hero-body">
          <Meta tool={featured.tool} readTime={featured.readTime} date={featured.date} />
          <h2 className="hero-title">{featured.title}</h2>
          <p className="hero-dek">{featured.dek}</p>
          <div className="hero-foot">
            <span className="author">{featured.author}</span>
            <span className="read-link">Číst <Icon.arrow /></span>
          </div>
        </div>
      </article>
      <div className="hero-side">
        {side.map(p => (
          <article key={p.id} className="side-card" onClick={() => onOpen(p.id)}>
            <Cover label={p.cover} ratio="16/10" />
            <div className="side-body">
              <Meta tool={p.tool} readTime={p.readTime} />
              <h3 className="side-title">{p.title}</h3>
              <p className="side-dek">{p.dek}</p>
            </div>
          </article>
        ))}
      </div>
    </section>
  );
}

// ---------- Grid card ----------
function Card({ post, onOpen, saved, liked, toggleSave, toggleLike }) {
  return (
    <article className="card">
      <div className="card-cover" onClick={() => onOpen(post.id)}>
        <Cover label={post.cover} ratio="16/10" />
      </div>
      <div className="card-body">
        <Meta tool={post.tool} readTime={post.readTime} date={post.date} />
        <h3 className="card-title" onClick={() => onOpen(post.id)}>{post.title}</h3>
        <p className="card-dek">{post.dek}</p>
        <div className="card-foot">
          <span className="author">{post.author}</span>
          <div className="card-actions">
            <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleLike(post.id); }} aria-label="To se mi líbí">
              <Icon.heart filled={liked[post.id]} />
            </button>
            <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleSave(post.id); }} aria-label="Uložit">
              <Icon.bookmark filled={saved[post.id]} />
            </button>
          </div>
        </div>
      </div>
    </article>
  );
}

// ---------- Article Detail ----------
function Article({ post, onBack, onOpen, allPosts, liked, saved, toggleLike, toggleSave }) {
  const [progress, setProgress] = React.useState(0);
  const [comments, setComments] = React.useState([]);
  const [draft, setDraft] = React.useState("");
  const [copied, setCopied] = React.useState(false);

  const copyLink = async () => {
    try {
      await navigator.clipboard?.writeText(window.location.href);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch {}
  };

  const shareUrl = encodeURIComponent(typeof window !== "undefined" ? window.location.href : "");
  const shareTitle = encodeURIComponent(post.title);
  const shareLinks = {
    x: `https://twitter.com/intent/tweet?text=${shareTitle}&url=${shareUrl}`,
    linkedin: `https://www.linkedin.com/sharing/share-offsite/?url=${shareUrl}`,
    email: `mailto:?subject=${shareTitle}&body=${shareUrl}`,
  };

  React.useEffect(() => {
    const el = document.querySelector(".article-scroll");
    const onScroll = () => {
      const total = document.documentElement.scrollHeight - window.innerHeight;
      setProgress(Math.min(100, Math.max(0, (window.scrollY / total) * 100)));
    };
    window.addEventListener("scroll", onScroll);
    window.scrollTo(0, 0);
    return () => window.removeEventListener("scroll", onScroll);
  }, [post.id]);

  const submitComment = (e) => {
    e.preventDefault();
    if (!draft.trim()) return;
    setComments([{ id: Date.now(), name: "Vy", time: "právě teď", text: draft.trim() }, ...comments]);
    setDraft("");
  };

  const related = allPosts.filter(p => p.id !== post.id && (p.tool === post.tool || p.category === post.category)).slice(0, 3);
  const relatedFinal = related.length ? related : allPosts.filter(p => p.id !== post.id).slice(0, 3);

  return (
    <div className="article-scroll">
      <div className="progress-bar" style={{ width: `${progress}%` }} />
      <div className="article-top">
        <button className="back-btn" onClick={onBack}><Icon.back /> Zpět na blog</button>
      </div>

      <article className="article">
        <header className="article-head">
          <div className="meta meta-lg">
            <span className="meta-tool">{post.tool}</span>
            <span className="meta-dot">·</span>
            <span>{post.category}</span>
            <span className="meta-dot">·</span>
            <span>{post.readTime} min čtení</span>
          </div>
          <h1 className="article-title">{post.title}</h1>
          <p className="article-dek">{post.dek}</p>
          <div className="article-byline">
            <div className="avatar">{post.author.split(" ").map(n => n[0]).join("")}</div>
            <div>
              <div className="byline-name">{post.author}</div>
              <div className="byline-date">{post.date}</div>
            </div>
            <div className="article-actions">
              <button className={"pill " + (liked[post.id] ? "active" : "")} onClick={() => toggleLike(post.id)}>
                <Icon.heart filled={liked[post.id]} /> {liked[post.id] ? "Líbí se mi" : "Líbí"}
              </button>
              <button className={"pill " + (saved[post.id] ? "active" : "")} onClick={() => toggleSave(post.id)}>
                <Icon.bookmark filled={saved[post.id]} /> {saved[post.id] ? "Uloženo" : "Uložit"}
              </button>
              <button className="pill" onClick={copyLink} aria-label="Zkopírovat odkaz na článek">
                <Icon.share /> {copied ? "Zkopírováno" : "Sdílet"}
              </button>
            </div>
          </div>
        </header>

        <Cover label={post.cover} ratio="16/9" />

        <div className="article-body">
          {post.body.map((b, i) => {
            if (b.kind === "p") return <p key={i}>{b.text}</p>;
            if (b.kind === "h2") return <h2 key={i}>{b.text}</h2>;
            if (b.kind === "ul") return <ul key={i}>{b.items.map((it, j) => <li key={j}>{it}</li>)}</ul>;
            if (b.kind === "callout") return <aside key={i} className="callout">{b.text}</aside>;
            return null;
          })}
        </div>

        <footer className="article-foot">
          <div className="share-row">
            <span className="share-label">Sdílet článek</span>
            <button className="pill" onClick={copyLink}><Icon.share /> {copied ? "Zkopírováno" : "Zkopírovat odkaz"}</button>
            <a className="pill" href={shareLinks.x} target="_blank" rel="noopener noreferrer">X</a>
            <a className="pill" href={shareLinks.linkedin} target="_blank" rel="noopener noreferrer">LinkedIn</a>
            <a className="pill" href={shareLinks.email}>E-mail</a>
          </div>
        </footer>
      </article>

      <section className="comments">
        <h3 className="section-title">Komentáře <span className="count">{comments.length}</span></h3>
        <form className="comment-form" onSubmit={submitComment}>
          <textarea
            value={draft}
            onChange={e => setDraft(e.target.value)}
            placeholder="Co si o tom myslíte?"
            rows={3}
          />
          <div className="comment-submit">
            <span className="hint">Buďte věcní a konkrétní. Spam mažeme.</span>
            <button type="submit" className="btn-primary">Přidat komentář</button>
          </div>
        </form>
        <ul className="comment-list">
          {comments.map(c => (
            <li key={c.id} className="comment">
              <div className="avatar small">{c.name.split(" ").map(n => n[0]).join("")}</div>
              <div className="comment-body">
                <div className="comment-head"><b>{c.name}</b> <span className="comment-time">{c.time}</span></div>
                <p>{c.text}</p>
              </div>
            </li>
          ))}
        </ul>
      </section>

      <section className="related">
        <h3 className="section-title">Související čtení</h3>
        <div className="related-grid">
          {relatedFinal.map(p => (
            <article key={p.id} className="related-card" onClick={() => onOpen(p.id)}>
              <Cover label={p.cover} ratio="16/10" />
              <Meta tool={p.tool} readTime={p.readTime} />
              <h4>{p.title}</h4>
            </article>
          ))}
        </div>
      </section>
    </div>
  );
}

// ---------- Newsletter ----------
function Newsletter() {
  return (
    <section className="newsletter">
      <div className="news-inner">
        <div>
          <h3>Newsletter, na který se těšíte</h3>
          <p>Jeden e-mail v pátek. Tři nástroje, které jsem ten týden zkoušel. Žádné AI hype, žádné affiliate odkazy.</p>
        </div>
        <div className="news-done">Brzy spouštíme — možnost přihlášení bude dostupná zde.</div>
      </div>
    </section>
  );
}

// ---------- Home View ----------
function Home({ onOpen, liked, saved, toggleLike, toggleSave }) {
  const [query, setQuery] = React.useState("");
  const [tool, setTool] = React.useState("Vše");
  const [cat, setCat] = React.useState("Vše");

  const filtered = POSTS.filter(p => {
    if (tool !== "Vše" && p.tool !== tool) return false;
    if (cat !== "Vše" && p.category !== cat) return false;
    if (query) {
      const q = query.toLowerCase();
      return (p.title + " " + p.dek + " " + p.tool).toLowerCase().includes(q);
    }
    return true;
  });

  const showHero = !query && tool === "Vše" && cat === "Vše";

  return (
    <main className="home">
      <header className="masthead">
        <div className="masthead-eyebrow">Vydání &nbsp;·&nbsp; květen 2026</div>
        <h1 className="masthead-title">Co AI <em>opravdu</em> umí.</h1>
        <p className="masthead-dek">Praktický blog o AI nástrojích — Claude, ChatGPT, NotebookLM a další. Pro produktové lidi, kteří nechtějí hype, ale použitelné návody.</p>
      </header>

      <div className="toolbar">
        <div className="search">
          <Icon.search />
          <input
            value={query}
            onChange={e => setQuery(e.target.value)}
            placeholder="Hledat článek, nástroj, téma…"
          />
        </div>
        <div className="filter-group">
          <span className="filter-label">Nástroj</span>
          <div className="chips">
            {TOOLS.map(t => (
              <button key={t} className={"chip " + (tool === t ? "active" : "")} onClick={() => setTool(t)}>{t}</button>
            ))}
          </div>
        </div>
        <div className="filter-group">
          <span className="filter-label">Kategorie</span>
          <div className="chips">
            {CATEGORIES.map(c => (
              <button key={c} className={"chip " + (cat === c ? "active" : "")} onClick={() => setCat(c)}>{c}</button>
            ))}
          </div>
        </div>
      </div>

      {showHero && <Hero posts={POSTS} onOpen={onOpen} liked={liked} saved={saved} toggleLike={toggleLike} toggleSave={toggleSave} />}

      <section className="grid-section">
        <div className="grid-head">
          <h2>{showHero ? "Další články" : `${filtered.length} ${filtered.length === 1 ? "článek" : filtered.length < 5 ? "články" : "článků"}`}</h2>
          {!showHero && <button className="link-btn" onClick={() => { setQuery(""); setTool("Vše"); setCat("Vše"); }}>Vyčistit filtry</button>}
        </div>
        {filtered.length === 0 ? (
          <div className="empty">Žádné články neodpovídají. Zkuste jiné filtry.</div>
        ) : (
          <div className="grid">
            {(showHero ? filtered.filter(p => !p.featured).slice(2) : filtered).map(p => (
              <Card key={p.id} post={p} onOpen={onOpen} liked={liked} saved={saved} toggleSave={toggleSave} toggleLike={toggleLike} />
            ))}
          </div>
        )}
      </section>

      <Newsletter />
    </main>
  );
}

// ---------- Tools page ----------
const TOOL_CATALOG = [
  { name: "Claude", vendor: "Anthropic", category: "Asistent", price: "Free / $20", desc: "Náš denní pracovní kůň. Skvělý na psaní, analýzu dlouhých dokumentů a kódování. Projekty jsou killer feature.", strengths: ["Dlouhý kontext", "Kvalita psaní", "Bezpečnější odpovědi"], weaknesses: ["Žádný image-gen", "Žádný hlasový režim"], rating: 5, postId: "projekty-v-claude" },
  { name: "ChatGPT", vendor: "OpenAI", category: "Asistent", price: "Free / $20 / $200", desc: "Nejširší ekosystém — GPT Store, hlas, obrazy, Deep Research, Canvas. Jeden účet pokryje 80% potřeb.", strengths: ["Ekosystém pluginů", "Hlasový režim", "Generování obrázků"], weaknesses: ["Občas halucinuje", "Inkonzistentní napříč modely"], rating: 5, postId: "deep-research-chatgpt" },
  { name: "NotebookLM", vendor: "Google", category: "Výzkum", price: "Free / $20", desc: "Nejlepší způsob, jak vést konverzaci nad vašimi PDF, zápisy a videi. Drží se zdrojů, nelže.", strengths: ["Audio Overview", "Drží se zdrojů", "Skvělé na rešerše"], weaknesses: ["Pomalejší UI", "Omezený export"], rating: 4, postId: "notebooklm" },
  { name: "Perplexity", vendor: "Perplexity AI", category: "Vyhledávání", price: "Free / $20", desc: "AI vyhledávač s citacemi. Když Google odpovídá na „kde“, Perplexity odpovídá na „co a proč“.", strengths: ["Citace u všeho", "Spaces pro týmy", "Rychlost"], weaknesses: ["Slabší u čerstvých zpráv", "Občas povrchní"], rating: 4, postId: "perplexity-vs-google" },
  { name: "Cursor", vendor: "Anysphere", category: "Kódování", price: "Free / $20", desc: "VS Code přepsaný kolem AI. Pro vývojáře, kteří chtějí psát kód s asistentem, ne občas se ho ptát.", strengths: ["Hluboká integrace", "Composer multi-file", "Tab completion"], weaknesses: ["Křivka učení", "Drahé pro celé týmy"], rating: 4 },
  { name: "v0", vendor: "Vercel", category: "Design", price: "Free / $20", desc: "Generování UI z popisu. Vrátí vám rovnou React + Tailwind komponentu, kterou jde dál editovat.", strengths: ["Rychlý prototyping", "Dobré výchozí komponenty"], weaknesses: ["Jen React/Tailwind stack", "Nudné variace"], rating: 3 },
  { name: "Granola", vendor: "Granola", category: "Produktivita", price: "$18", desc: "Zápisník ze schůzek, který poslouchá a píše za vás. Funguje s Meet, Zoom, Teams a fyzickými schůzkami.", strengths: ["Lokální nahrávání", "Šablony pro typy schůzek"], weaknesses: ["Jen pro Mac", "Občas ujede čeština"], rating: 4 },
  { name: "Midjourney", vendor: "Midjourney", category: "Obrazy", price: "$10–$60", desc: "Nejhezčí výstupy mezi obrazovými modely. V7 konečně poslouchá pokyny.", strengths: ["Estetická kvalita", "Široká stylová paleta"], weaknesses: ["Discord UI dědictví", "Slabší text v obrazech"], rating: 4 }
];

function Stars({ n }) {
  return (
    <span className="stars" aria-label={`Hodnocení ${n} z 5`}>
      {[1,2,3,4,5].map(i => <span key={i} className={i <= n ? "star on" : "star"}>●</span>)}
    </span>
  );
}

function ToolsPage({ onOpen, onGoHome }) {
  const [cat, setCat] = React.useState("Vše");
  const cats = ["Vše", ...Array.from(new Set(TOOL_CATALOG.map(t => t.category)))];
  const filtered = cat === "Vše" ? TOOL_CATALOG : TOOL_CATALOG.filter(t => t.category === cat);
  return (
    <main className="home page">
      <header className="page-head">
        <div className="masthead-eyebrow">Katalog · {TOOL_CATALOG.length} nástrojů</div>
        <h1 className="page-title">Nástroje, které sami <em>používáme</em>.</h1>
        <p className="page-dek">Krátké recenze AI nástrojů, které prošly naším pracovním dnem. Bez affiliate odkazů, bez „top 50“. Jen to, co se vyplatí.</p>
      </header>

      <div className="filter-group page-filter">
        <span className="filter-label">Kategorie</span>
        <div className="chips">
          {cats.map(c => <button key={c} className={"chip " + (cat === c ? "active" : "")} onClick={() => setCat(c)}>{c}</button>)}
        </div>
      </div>

      <section className="tools-list">
        {filtered.map((tool, i) => (
          <article key={tool.name} className="tool-row">
            <div className="tool-idx">{String(i + 1).padStart(2, "0")}</div>
            <div className="tool-main">
              <div className="tool-head">
                <h3>{tool.name}</h3>
                <span className="tool-vendor">{tool.vendor}</span>
                <span className="tool-cat">{tool.category}</span>
                <Stars n={tool.rating} />
              </div>
              <p className="tool-desc">{tool.desc}</p>
              <div className="tool-grid">
                <div>
                  <h6>Silné stránky</h6>
                  <ul>{tool.strengths.map(s => <li key={s}>{s}</li>)}</ul>
                </div>
                <div>
                  <h6>Slabiny</h6>
                  <ul>{tool.weaknesses.map(s => <li key={s}>{s}</li>)}</ul>
                </div>
                <div>
                  <h6>Cena</h6>
                  <p className="tool-price">{tool.price}</p>
                  {tool.postId && <button className="link-btn" onClick={() => onOpen(tool.postId)}>Přečíst hloubkový článek →</button>}
                </div>
              </div>
            </div>
          </article>
        ))}
      </section>

      <Newsletter />
    </main>
  );
}

// ---------- Newsletter page ----------
function NewsletterPage() {
  return (
    <main className="home page">
      <header className="page-head center">
        <div className="masthead-eyebrow">Newsletter · každý pátek</div>
        <h1 className="page-title">Jeden e-mail v pátek. <em>Tři nástroje.</em> Žádný hype.</h1>
        <p className="page-dek">Co jsem ten týden zkoušel, co fungovalo, co ne. Žádné AI novinky, žádné affiliate odkazy, žádné top‑10 seznamy.</p>
        <div className="news-done">Brzy spouštíme — možnost přihlášení a archiv vydání bude dostupné zde.</div>
      </header>
    </main>
  );
}

// ---------- About page ----------
function AboutPage() {
  return (
    <main className="home page">
      <header className="page-head narrow">
        <div className="masthead-eyebrow">O blogu</div>
        <h1 className="page-title">Píšeme o AI <em>tak,</em> jak ji používáme.</h1>
        <p className="page-dek">Nástrojárna vznikla v lednu 2025 jako reakce na záplavu obsahu, který slibuje „nahradit všechny vaše nástroje“. My žádný nástroj nikoho nenutíme. Zkusíme ho, použijeme ho v reálné práci a napíšeme, co fungovalo a co ne.</p>
      </header>

      <section className="about-body">
        <div className="about-section">
          <h2>Pro koho píšeme</h2>
          <p>Produktoví manažeři, designéři, marketéři a operations lidi v B2B firmách. Pro lidi, kteří AI musí používat zítra ráno na konkrétní úkol — ne pro lidi, kteří chtějí číst o budoucnosti.</p>
        </div>
        <div className="about-section">
          <h2>Jak vybíráme témata</h2>
          <p>Z naší vlastní práce. Co jsme tento týden potřebovali, co nefungovalo na první pokus, co jsme museli vyzkoušet třikrát. Když přijde čtenářská otázka, na kterou nemáme odpověď, zkusíme ji a napíšeme co jsme zjistili.</p>
        </div>
        <div className="about-section">
          <h2>Jak se živíme</h2>
          <p>Z newsletteru, ze školení v produktových týmech a z konzultací. Z žádných partnerství s AI firmami. Když píšeme „Claude je v tomhle lepší než ChatGPT“, znamená to přesně to, co je tam napsáno — nikdo nám za to nezaplatil a nikdo to nečetl před vámi.</p>
        </div>

        <div className="about-section principles">
          <h2>Naše principy</h2>
          <ol>
            <li><b>Zkoušej, než napíšeš.</b> Žádný nástroj nehodnotíme z tiskovek. Použijeme ho minimálně dva týdny v reálné práci.</li>
            <li><b>Říkej, co nefunguje.</b> Slabiny dostávají stejně prostoru jako silné stránky.</li>
            <li><b>Žádné top‑X seznamy.</b> Místo „top 10 AI nástrojů 2026“ napíšeme o jednom konkrétním problému a jednom konkrétním řešení.</li>
            <li><b>Žádné affiliate.</b> Když uvidíte odkaz, vede přímo na výrobce, nikam jinam.</li>
            <li><b>Aktualizuj.</b> Články dva roky staré stárnou rychle. Vracíme se k nim a píšeme dodatky.</li>
          </ol>
        </div>
      </section>

      <Newsletter />
    </main>
  );
}

// ---------- App shell ----------
const TWEAKS_STORAGE_KEY = "nastrojarna.tweaks";
const TWEAKS_DEFAULTS = { theme: "light", density: "comfortable" };

function useTweaks() {
  const [t, setT] = React.useState(() => {
    try {
      const stored = JSON.parse(localStorage.getItem(TWEAKS_STORAGE_KEY) || "{}");
      return { ...TWEAKS_DEFAULTS, ...stored };
    } catch {
      return TWEAKS_DEFAULTS;
    }
  });
  const setTweak = React.useCallback((key, value) => {
    setT(prev => {
      const next = { ...prev, [key]: value };
      try { localStorage.setItem(TWEAKS_STORAGE_KEY, JSON.stringify(next)); } catch {}
      return next;
    });
  }, []);
  return [t, setTweak];
}

function App() {
  const [t, setTweak] = useTweaks();

  const [view, setView] = React.useState({ name: "home", postId: null });
  const [liked, setLiked] = React.useState({});
  const [saved, setSaved] = React.useState({});

  React.useEffect(() => {
    document.documentElement.dataset.theme = t.theme;
    document.documentElement.dataset.density = t.density;
  }, [t.theme, t.density]);

  const toggleLike = (id) => setLiked(s => ({ ...s, [id]: !s[id] }));
  const toggleSave = (id) => setSaved(s => ({ ...s, [id]: !s[id] }));

  const openPost = (id) => {
    setView({ name: "article", postId: id });
    window.scrollTo(0, 0);
  };
  const go = (name) => {
    setView({ name, postId: null });
    window.scrollTo(0, 0);
  };

  const post = view.postId ? POSTS.find(p => p.id === view.postId) : null;

  const NavLink = ({ to, children }) => (
    <a
      onClick={() => go(to)}
      className={view.name === to ? "active" : ""}
    >{children}</a>
  );

  return (
    <div className="app">
      <nav className="nav">
        <div className="nav-inner">
          <button className="brand" onClick={() => go("home")}>
            <span className="brand-mark">◐</span>
            <span className="brand-name">nástrojárna</span>
            <span className="brand-sub">/ ai prakticky</span>
          </button>
          <div className="nav-links">
            <NavLink to="home">Články</NavLink>
            <NavLink to="tools">Nástroje</NavLink>
            <NavLink to="newsletter">Newsletter</NavLink>
            <NavLink to="about">O blogu</NavLink>
          </div>
          <div className="nav-right">
            <button
              className="theme-toggle"
              aria-label={t.density === "comfortable" ? "Přepnout na kompaktní hustotu" : "Přepnout na vzdušnou hustotu"}
              onClick={() => setTweak("density", t.density === "comfortable" ? "compact" : "comfortable")}
              title={t.density === "comfortable" ? "Kompaktní rozložení" : "Vzdušné rozložení"}
            >
              {t.density === "comfortable" ? "≣" : "≡"}
            </button>
            <button
              className="theme-toggle"
              aria-label="Přepnout režim"
              onClick={() => setTweak("theme", t.theme === "light" ? "dark" : "light")}
              title={t.theme === "light" ? "Přepnout na tmavý režim" : "Přepnout na světlý režim"}
            >
              {t.theme === "light" ? <Icon.moon /> : <Icon.sun />}
            </button>
          </div>
        </div>
      </nav>

      {view.name === "home" && <Home onOpen={openPost} liked={liked} saved={saved} toggleLike={toggleLike} toggleSave={toggleSave} />}
      {view.name === "tools" && <ToolsPage onOpen={openPost} onGoHome={() => go("home")} />}
      {view.name === "newsletter" && <NewsletterPage />}
      {view.name === "about" && <AboutPage />}
      {view.name === "article" && (
        <Article
          post={post}
          onBack={() => go("home")}
          onOpen={openPost}
          allPosts={POSTS}
          liked={liked}
          saved={saved}
          toggleLike={toggleLike}
          toggleSave={toggleSave}
        />
      )}

      <footer className="footer">
        <div className="footer-inner">
          <div>
            <div className="brand">
              <span className="brand-mark">◐</span>
              <span className="brand-name">nástrojárna</span>
            </div>
            <p>Praktický blog o AI nástrojích.</p>
          </div>
          <div className="footer-cols">
            <div>
              <h5>Obsah</h5>
              <a onClick={() => go("home")}>Články</a>
              <a onClick={() => go("tools")}>Nástroje</a>
              <a onClick={() => go("newsletter")}>Newsletter</a>
            </div>
            <div>
              <h5>O nás</h5>
              <a onClick={() => go("about")}>O blogu</a>
            </div>
          </div>
        </div>
        <div className="footer-bottom">© 2026 nástrojárna. Psáno lidmi, kteří AI používají, ne prodávají.</div>
      </footer>

    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
