// gm-hand.jsx — Infográficos hand-drawn (estilo papel quadriculado), na marca Nicolas Lima.
// Biblioteca rica + base de papel + exemplo completo + regras. Sobrescreve GMInfographics.
// Carregar DEPOIS de gm-info.jsx.

const { T, F, Section, SecHead, Lead, Note, Mono, Card } = window;
const HND = "'Caveat', 'Bricolage Grotesque', cursive";

/* ── papel ─────────────────────────────────────────────────────────────── */
const paperGrid = (dark) => ({
  background: dark ? "#16110E" : "#F1E7D2",
  backgroundImage: `linear-gradient(${dark ? "rgba(242,216,167,0.09)" : "rgba(194,104,62,0.16)"} 1px, transparent 1px), linear-gradient(90deg, ${dark ? "rgba(242,216,167,0.09)" : "rgba(194,104,62,0.16)"} 1px, transparent 1px)`,
  backgroundSize: "22px 22px",
});
const paperDot = (dark) => ({
  background: dark ? "#16110E" : "#F1E7D2",
  backgroundImage: `radial-gradient(${dark ? "rgba(242,216,167,0.16)" : "rgba(194,104,62,0.26)"} 1.4px, transparent 1.6px)`,
  backgroundSize: "20px 20px",
});

/* ── helpers de geometria ──────────────────────────────────────────────── */
function scallop(cx, cy, r, n) {
  let d = "";
  for (let i = 0; i <= n; i++) { const a = (i / n) * 2 * Math.PI; const x = cx + r * Math.cos(a), y = cy + r * Math.sin(a); d += i === 0 ? `M${x.toFixed(1)} ${y.toFixed(1)}` : ` A ${(r * 0.2).toFixed(1)} ${(r * 0.2).toFixed(1)} 0 0 1 ${x.toFixed(1)} ${y.toFixed(1)}`; }
  return d + "Z";
}
function wedge(cx, cy, r, a0, a1) {
  const p = (a) => [cx + r * Math.cos(a), cy + r * Math.sin(a)]; const [x0, y0] = p(a0), [x1, y1] = p(a1); const large = a1 - a0 > Math.PI ? 1 : 0;
  return `M${cx} ${cy} L${x0.toFixed(1)} ${y0.toFixed(1)} A ${r} ${r} 0 ${large} 1 ${x1.toFixed(1)} ${y1.toFixed(1)} Z`;
}
const HATCHES = [["coral", "#E8553A"], ["amber", "#E8A33D"], ["cyan", "#0E9AAC"], ["dcyan", "#54C8D0"], ["olive", "#7F8B45"], ["terra", "#D9714A"], ["teal", "#16786E"], ["ink", "#211913"], ["sand", "#F2D8A7"]];
const DEFS_HAND = `<defs><filter id="rghH" x="-14%" y="-14%" width="128%" height="128%"><feTurbulence type="fractalNoise" baseFrequency="0.026" numOctaves="2" seed="4" result="t"/><feDisplacementMap in="SourceGraphic" in2="t" scale="2.2"/></filter>` + HATCHES.map(([id, c], i) => `<pattern id="hb-${id}" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(${i % 2 ? -45 : 45})"><line x1="0" y1="0" x2="0" y2="7" stroke="${c}" stroke-width="2.1"/></pattern>`).join("") + `</defs>`;
function dlSvg(btn, name) {
  const tile = btn.closest("[data-eltile]");
  if (!tile) return;
  const svgs = tile.querySelectorAll("svg");
  let out;
  if (svgs.length === 1) {
    const c = svgs[0].cloneNode(true);
    c.setAttribute("xmlns", "http://www.w3.org/2000/svg");
    c.setAttribute("width", "160"); c.setAttribute("height", "160");
    c.insertAdjacentHTML("afterbegin", DEFS_HAND);
    out = new XMLSerializer().serializeToString(c);
  } else {
    const body = tile.querySelector("[data-elbody]") || tile;
    const clone = body.cloneNode(true);
    clone.querySelectorAll("button").forEach((b) => b.remove());
    const r = body.getBoundingClientRect();
    const w = Math.max(40, Math.round(r.width)), h = Math.max(40, Math.round(r.height));
    out = `<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}" viewBox="0 0 ${w} ${h}">${DEFS_HAND}<foreignObject x="0" y="0" width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="width:${w}px;height:${h}px">${clone.innerHTML}</div></foreignObject></svg>`;
  }
  const blob = new Blob([out], { type: "image/svg+xml" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a"); a.href = url; a.download = "nl-" + (name || "elemento").replace(/[^\w-]+/g, "-") + ".svg"; a.click();
  setTimeout(() => URL.revokeObjectURL(url), 900);
}

function SharedDefs() {
  return (
    <svg width="0" height="0" style={{ position: "absolute" }} aria-hidden>
      <defs>
        <filter id="rghH" x="-14%" y="-14%" width="128%" height="128%"><feTurbulence type="fractalNoise" baseFrequency="0.026" numOctaves="2" seed="4" result="t" /><feDisplacementMap in="SourceGraphic" in2="t" scale="2.2" /></filter>
        {HATCHES.map(([id, c], i) => (
          <pattern key={id} id={`hb-${id}`} width="7" height="7" patternUnits="userSpaceOnUse" patternTransform={`rotate(${i % 2 ? -45 : 45})`}>
            <line x1="0" y1="0" x2="0" y2="7" stroke={c} strokeWidth="2.1" />
          </pattern>
        ))}
      </defs>
    </svg>
  );
}

/* ── elementos hand-drawn ──────────────────────────────────────────────── */
const ink = (d) => (d ? "#F2D8A7" : "#211913");
const sub = (d) => (d ? "#9C8674" : "#6B5D4F");
const SK = (d, w = 2.4) => ({ fill: "none", stroke: ink(d), strokeWidth: w, strokeLinecap: "round", strokeLinejoin: "round" });

function IBadge({ dark, w = 116, pct = "64%", hatch = "amber" }) {
  return (
    <svg viewBox="0 0 110 110" width={w}>
      <path d={scallop(55, 55, 45, 16)} fill={dark ? "#241B16" : "#FBF6EA"} {...SK(dark)} />
      <circle cx="55" cy="55" r="33" fill={`url(#hb-${hatch})`} />
      <path d="M24 56 C 26 36 84 34 86 54 C 88 76 24 78 24 56" {...SK(dark, 2.2)} />
      <text x="55" y="64" textAnchor="middle" fontFamily={HND} fontSize="29" fontWeight="700" fill={ink(dark)}>{pct}</text>
    </svg>
  );
}
function IFlag({ dark, w = 108, pct = "48%" }) {
  return (
    <svg viewBox="0 0 120 116" width={w}>
      <path d="M21 14 C 19 50 22 80 20 106" {...SK(dark)} />
      <path d="M21 18 H97 L83 37 L97 56 H21 Z" fill="url(#hb-coral)" {...SK(dark)} />
      <text x="57" y="44" textAnchor="middle" fontFamily={HND} fontSize="22" fontWeight="700" fill={ink(dark)}>{pct}</text>
      <text x="22" y="78" fontFamily={HND} fontSize="17" fill={sub(dark)}>Sample Text</text>
    </svg>
  );
}
function IRibbon({ dark, w = 210, text = "Infográfico" }) {
  return (
    <svg viewBox="0 0 220 50" width={w}>
      <path d="M8 25 L26 11 H210 L196 25 L210 39 H26 Z" fill="url(#hb-coral)" {...SK(dark)} />
      <text x="116" y="32" textAnchor="middle" fontFamily={HND} fontSize="22" fontWeight="700" fill={ink(dark)}>{text}</text>
    </svg>
  );
}
function IArrows({ dark }) {
  const s = SK(dark, 2.6);
  return (
    <svg viewBox="0 0 150 96" width="92%">
      <g>
        <path d="M8 22 C 40 16, 80 16, 120 22" {...s} /><path d="M108 12 L124 23 L106 30" {...s} />
        <path d="M14 56 C 40 44 60 70 96 54" {...s} /><path d="M84 46 L100 54 L86 64" {...s} />
        <path d="M16 90 C 16 70 70 70 70 84 C 70 92 50 92 50 86" {...s} /><path d="M58 80 L48 88 L58 94" {...s} />
      </g>
    </svg>
  );
}
function INum({ dark, n = 1, hatch = "cyan", w = 70 }) {
  return (
    <svg viewBox="0 0 70 70" width={w}>
      <path d="M35 6 C 60 5 66 30 64 38 C 60 64 12 66 7 40 C 4 20 16 6 35 6" fill={`url(#hb-${hatch})`} {...SK(dark)} />
      <text x="35" y="46" textAnchor="middle" fontFamily={HND} fontSize="34" fontWeight="700" fill={ink(dark)}>{n}</text>
    </svg>
  );
}
function ISpeech({ dark, text = "Detalhe!", w = 130 }) {
  return (
    <svg viewBox="0 0 140 96" width={w}>
      <path d="M14 14 C 8 12 8 64 16 66 C 40 72 110 70 124 64 C 132 60 132 16 124 12 C 96 6 36 8 14 14" fill={`url(#hb-olive)`} {...SK(dark)} />
      <path d="M30 64 L26 86 L48 66" {...SK(dark)} fill={dark ? "#16110E" : "#F1E7D2"} />
      <text x="70" y="44" textAnchor="middle" fontFamily={HND} fontSize="20" fontWeight="700" fill={ink(dark)} textLength={Math.min(104, text.length * 10)} lengthAdjust="spacingAndGlyphs">{text}</text>
    </svg>
  );
}
function IPie({ dark, w = 130 }) {
  const segs = [[0.34, "coral", "34%"], [0.26, "cyan", "26%"], [0.22, "amber", "22%"], [0.18, "olive", "18%"]];
  let a = -Math.PI / 2; const cx = 65, cy = 60, r = 46;
  return (
    <svg viewBox="0 0 150 124" width={w} style={{ filter: "url(#rghH)" }}>
      {segs.map(([f, h, lbl], i) => { const a0 = a, a1 = a + f * 2 * Math.PI; a = a1; const mid = (a0 + a1) / 2; const lx = cx + (r + 14) * Math.cos(mid), ly = cy + (r + 14) * Math.sin(mid); return (<g key={i}><path d={wedge(cx, cy, r, a0, a1)} fill={`url(#hb-${h})`} {...SK(dark, 2)} /><text x={lx} y={ly} textAnchor="middle" fontFamily={HND} fontSize="15" fill={ink(dark)}>{lbl}</text></g>); })}
      <circle cx={cx} cy={cy} r="17" fill={dark ? "#16110E" : "#F1E7D2"} {...SK(dark, 2)} />
    </svg>
  );
}
function IBars({ dark, w = 150 }) {
  const data = [["A", 64, "coral"], ["B", 42, "cyan"], ["C", 90, "amber"], ["D", 30, "olive"]];
  const max = 90, base = 96, h = 70;
  return (
    <svg viewBox="0 0 160 116" width={w}>
      <path d="M16 14 L16 98 L150 98" {...SK(dark, 2.4)} />
      {data.map(([l, v, c], i) => { const bw = 26, x = 26 + i * 32, bh = (v / max) * h, y = base - bh; return (<g key={i}><path d={`M${x} ${base} L${x - 1} ${y + 2} L${x + bw} ${y} L${x + bw} ${base} Z`} fill={`url(#hb-${c})`} {...SK(dark, 2)} /><text x={x + bw / 2} y={y - 5} textAnchor="middle" fontFamily={HND} fontSize="16" fontWeight="700" fill={ink(dark)}>{v}</text></g>); })}
    </svg>
  );
}
function IVenn({ dark, w = 140 }) {
  return (
    <svg viewBox="0 0 150 120" width={w} style={{ filter: "url(#rghH)" }}>
      <circle cx="58" cy="50" r="34" fill="url(#hb-coral)" {...SK(dark, 2.2)} />
      <circle cx="92" cy="50" r="34" fill="url(#hb-cyan)" {...SK(dark, 2.2)} />
      <circle cx="75" cy="80" r="34" fill="url(#hb-amber)" {...SK(dark, 2.2)} />
      <text x="46" y="46" textAnchor="middle" fontFamily={HND} fontSize="22" fontWeight="700" fill={ink(dark)}>A</text>
      <text x="104" y="46" textAnchor="middle" fontFamily={HND} fontSize="22" fontWeight="700" fill={ink(dark)}>B</text>
      <text x="75" y="98" textAnchor="middle" fontFamily={HND} fontSize="22" fontWeight="700" fill={ink(dark)}>C</text>
    </svg>
  );
}
function IPyramid({ dark, w = 130 }) {
  const rows = [["coral", 30, 52], ["amber", 52, 72], ["cyan", 72, 92], ["olive", 92, 112]];
  return (
    <svg viewBox="0 0 150 122" width={w} style={{ filter: "url(#rghH)" }}>
      {rows.map(([c, y0, y1], i) => { const top = 75, w0 = (y0 - 28) * 0.95, w1 = (y1 - 28) * 0.95; return <path key={i} d={`M${75 - w0 / 2} ${y0} L${75 + w0 / 2} ${y0} L${75 + w1 / 2} ${y1} L${75 - w1 / 2} ${y1} Z`} fill={`url(#hb-${c})`} {...SK(dark, 2)} />; })}
      <path d="M75 26 L121 112 L29 112 Z" {...SK(dark, 2.4)} />
    </svg>
  );
}
function IPin({ dark, w = 70 }) {
  return (
    <svg viewBox="0 0 70 96" width={w} style={{ filter: "url(#rghH)" }}>
      <path d="M35 8 C 56 8 60 30 56 42 C 52 56 38 70 35 88 C 32 70 18 56 14 42 C 10 30 14 8 35 8" fill="url(#hb-coral)" {...SK(dark)} />
      <circle cx="35" cy="34" r="11" fill={dark ? "#16110E" : "#F1E7D2"} {...SK(dark, 2.2)} />
    </svg>
  );
}
function IIcons({ dark }) {
  const s = SK(dark, 2.3);
  return (
    <svg viewBox="0 0 150 80" width="92%" style={{ filter: "url(#rghH)" }}>
      {/* gear */}
      <g transform="translate(8,16)"><circle cx="22" cy="22" r="11" fill="url(#hb-olive)" {...s} /><circle cx="22" cy="22" r="4.5" {...s} /><path d="M22 4 V11 M22 33 V40 M4 22 H11 M33 22 H40 M9 9 L14 14 M30 30 L35 35 M35 9 L30 14 M14 30 L9 35" {...s} /></g>
      {/* bulb */}
      <g transform="translate(58,8)"><path d="M22 4 C 36 4 40 22 30 32 L30 40 L14 40 L14 32 C 4 22 8 4 22 4" fill="url(#hb-amber)" {...s} /><path d="M15 46 H29 M17 52 H27" {...s} /></g>
      {/* magnifier */}
      <g transform="translate(104,10)"><circle cx="22" cy="22" r="15" fill="url(#hb-cyan)" {...s} /><path d="M33 33 L46 48" {...SK(dark, 3)} /></g>
    </svg>
  );
}
function IDivider({ dark, w = 180 }) {
  const s = SK(dark, 2.2);
  return (
    <svg viewBox="0 0 200 40" width={w}>
      <path d="M10 20 C 60 14 140 26 190 20" {...s} strokeDasharray="1 8" />
      <path d="M100 8 L104 17 L113 17 L106 23 L109 32 L100 26 L91 32 L94 23 L87 17 L96 17 Z" fill="url(#hb-coral)" {...SK(dark, 1.6)} />
      <circle cx="22" cy="20" r="3.5" fill={ink(dark)} /><circle cx="178" cy="20" r="3.5" fill={ink(dark)} />
    </svg>
  );
}

/* ── seção ─────────────────────────────────────────────────────────────── */
function GMInfographics() {
  const Tile = ({ label, dark, children, h = 124, noDl }) => (
    <div data-eltile style={{ display: "flex", flexDirection: "column", gap: 8, position: "relative" }}>
      <div data-elbody style={{ ...paperGrid(dark), borderRadius: 12, border: `1px solid ${dark ? T.dline : T.line}`, height: h, display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden", padding: 8 }}>{children}</div>
      {!noDl && <button onClick={(e) => dlSvg(e.currentTarget, label)} title="Baixar SVG" style={{ position: "absolute", top: 6, right: 6, cursor: "pointer", width: 21, height: 21, borderRadius: 6, border: `1px solid ${dark ? T.dline : T.line}`, background: dark ? T.dsurface : T.card, color: T.cyan, fontSize: 11, lineHeight: 1, padding: 0 }}>↓</button>}
      <div style={{ fontFamily: HND, fontSize: 18, color: dark ? T.dsand : T.ink, textAlign: "center", lineHeight: 1 }}>{label}</div>
    </div>
  );
  const Doc = ({ k, children }) => (
    <div style={{ display: "flex", gap: 12, padding: "12px 0", borderBottom: `1px solid ${T.line}` }}>
      <div style={{ fontFamily: F.mono, fontSize: 11, color: T.clay, width: 110, flexShrink: 0, letterSpacing: 0.5, paddingTop: 2 }}>{k}</div>
      <div style={{ fontSize: 13.5, color: T.sub, lineHeight: 1.5 }}>{children}</div>
    </div>
  );

  const Full = ({ dark }) => (
    <div style={{ ...paperGrid(dark), border: `1px solid ${dark ? T.dline : T.line}`, borderRadius: 14, padding: 24, position: "relative" }}>
      <div style={{ display: "flex", justifyContent: "center", marginBottom: 6 }}><IRibbon dark={dark} text="Pipeline de Dados" w={250} /></div>
      <div style={{ display: "grid", gridTemplateColumns: "1.1fr 1fr", gap: 16, alignItems: "center" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "center" }}><IPie dark={dark} w={180} /></div>
        <div>
          <ISpeech dark={dark} text="Cadê o tempo?" w={170} />
          <div style={{ display: "flex", gap: 6, marginTop: 6 }}>{[1, 2, 3].map((n) => <INum key={n} dark={dark} n={n} hatch={["coral", "amber", "cyan"][n - 1]} w={50} />)}</div>
        </div>
      </div>
      <div style={{ display: "flex", justifyContent: "center", margin: "6px 0" }}><IDivider dark={dark} w={260} /></div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr auto 1fr", gap: 12, alignItems: "center" }}>
        <div style={{ display: "flex", justifyContent: "center" }}><IBars dark={dark} w={180} /></div>
        <IArrows dark={dark} />
        <div style={{ display: "flex", alignItems: "center", gap: 10, justifyContent: "center" }}><IBadge dark={dark} pct="40%" hatch="coral" w={104} /><span style={{ fontFamily: HND, fontSize: 19, color: dark ? T.dsand : T.ink, maxWidth: 110, lineHeight: 1.1 }}>menos latência ↑</span></div>
      </div>
    </div>
  );

  return (
    <Section id="infografia" alt>
      <SharedDefs />
      <SecHead n="10" kicker="Infográficos" title="O caderno de campo da marca."
        lead="Aqui a marca vira página de caderno: papel quadriculado, traço de caneta, hachura à mão e rótulos manuscritos. Um sistema completo pra explicar dados de um jeito caloroso e pessoal — sobre uma base sempre igual." />

      {/* base de papel */}
      <div style={{ fontFamily: F.display, fontWeight: 800, fontSize: 20, marginBottom: 16 }}>A base: papel</div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 16, marginBottom: 18 }}>
        <Tile label="Quadriculado · claro"><div style={{ ...paperGrid(false), width: "100%", height: "100%", borderRadius: 6 }} /></Tile>
        <Tile label="Quadriculado · escuro" dark><div style={{ ...paperGrid(true), width: "100%", height: "100%", borderRadius: 6 }} /></Tile>
        <Tile label="Pontilhado · claro"><div style={{ ...paperDot(false), width: "100%", height: "100%", borderRadius: 6 }} /></Tile>
        <Tile label="Pontilhado · escuro" dark><div style={{ ...paperDot(true), width: "100%", height: "100%", borderRadius: 6 }} /></Tile>
      </div>
      <Card style={{ marginBottom: 36 }}>
        <Doc k="Cor do papel">Creme quente <strong style={{ color: T.ink }}>#F1E7D2</strong> no claro; espresso <strong style={{ color: T.ink }}>#16110E</strong> no escuro. Nunca branco puro — o papel tem que ter calor.</Doc>
        <Doc k="Grade">Linhas a cada <strong style={{ color: T.ink }}>22px</strong>, em clay translúcido (claro) ou areia translúcida (escuro). Sutil: guia o olho, não compete.</Doc>
        <Doc k="Quadriculado × pontilhado">Quadriculado para infográficos densos e técnicos; pontilhado para peças mais leves e respiradas. Escolha um por peça.</Doc>
        <Doc k="Traço">Caneta de <strong style={{ color: T.ink }}>2.4px</strong>, pontas arredondadas, levemente trêmulo. Preenchimento é sempre <strong style={{ color: T.ink }}>hachura</strong> (riscado), nunca chapado — é o que dá o ar "à mão".</Doc>
      </Card>

      {/* biblioteca */}
      <div style={{ fontFamily: F.display, fontWeight: 800, fontSize: 20, marginBottom: 16 }}>Biblioteca hand-drawn</div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 16, marginBottom: 18 }}>
        <Tile label="selo de %"><IBadge dark={false} /></Tile>
        <Tile label="bandeirola"><IFlag dark={false} /></Tile>
        <Tile label="faixa / título"><IRibbon dark={false} w={180} /></Tile>
        <Tile label="balão"><ISpeech dark={false} /></Tile>
        <Tile label="pizza hachurada"><IPie dark={false} /></Tile>
        <Tile label="barras"><IBars dark={false} /></Tile>
        <Tile label="Venn"><IVenn dark={false} /></Tile>
        <Tile label="pirâmide"><IPyramid dark={false} /></Tile>
        <Tile label="passos numerados"><div style={{ display: "flex", gap: 6 }}>{[1, 2, 3].map((n) => <INum key={n} dark={false} n={n} hatch={["coral", "amber", "cyan"][n - 1]} w={54} />)}</div></Tile>
        <Tile label="setas"><IArrows dark={false} /></Tile>
        <Tile label="ícones"><IIcons dark={false} /></Tile>
        <Tile label="pin + divisória"><div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 4 }}><IPin dark={false} w={48} /><IDivider dark={false} w={130} /></div></Tile>
      </div>

      {/* no escuro */}
      <div style={{ fontFamily: F.display, fontWeight: 700, fontSize: 16, marginBottom: 12, color: T.sub }}>Os mesmos elementos no escuro</div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 16, marginBottom: 36 }}>
        <Tile label="selo de %" dark><IBadge dark={true} pct="27%" hatch="cyan" /></Tile>
        <Tile label="pizza" dark><IPie dark={true} /></Tile>
        <Tile label="Venn" dark><IVenn dark={true} /></Tile>
        <Tile label="ícones" dark><IIcons dark={true} /></Tile>
      </div>

      {/* exemplo completo */}
      <div style={{ fontFamily: F.display, fontWeight: 800, fontSize: 20, marginBottom: 16 }}>Infográfico completo · claro ⇄ escuro</div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 22, marginBottom: 18 }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 9 }}><Full dark={false} /><Mono color={T.sub} size={9.5}>Claro</Mono></div>
        <div style={{ display: "flex", flexDirection: "column", gap: 9 }}><Full dark={true} /><Mono color={T.sub} size={9.5}>Escuro</Mono></div>
      </div>

      {/* regras */}
      <Note title="Como montar um bom infográfico">
        <strong>1. Uma pergunta por peça</strong> — o infográfico responde UMA coisa. <strong>2. Fluxo de leitura claro</strong> — guie com setas e números; o olho deve saber por onde começar. <strong>3. Hachura com função</strong> — cada cor/textura significa algo, não é enfeite. <strong>4. Respiro do papel</strong> — deixe a grade aparecer; não encha tudo. <strong>5. Manuscrito só nos rótulos</strong> — Caveat em números e legendas curtas; o corpo segue Hanken.
      </Note>
      <div style={{ marginTop: 16 }}>
        <Note title="A diferença pro diagrama">
          Diagrama é estrutura limpa e geométrica (seção 04). Infográfico é <strong>narrativa visual</strong>: combina dado, imagem, ícone e texto à mão para contar uma história — mais solto, mais humano, mais memorável.
        </Note>
      </div>

      {/* assets */}
      <div style={{ fontFamily: F.display, fontWeight: 800, fontSize: 20, margin: "36px 0 16px" }}>Assets hand-drawn</div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 16 }}>
        {[["hd-selo", "Selo %"], ["hd-bandeirola", "Bandeirola"], ["hd-faixa", "Faixa"], ["hd-pin", "Pin"], ["hd-pizza", "Pizza"], ["hd-balao", "Balão"], ["hd-arrow", "Seta"], ["hd-num", "Nº"]].map(([id, label]) => (
          <a key={id} href={`assets/${id}.svg`} download style={{ textDecoration: "none", display: "flex", alignItems: "center", justifyContent: "space-between", background: T.card, border: `1px solid ${T.line2}`, borderRadius: 8, padding: "10px 13px", fontFamily: F.mono, fontSize: 11, color: T.ink }}><span>{label}</span><span style={{ color: T.cyan }}>↓</span></a>
        ))}
      </div>
    </Section>
  );
}

function GMComponents() {
  const Tile = ({ name, dark, children, span }) => (
    <div data-eltile style={{ gridColumn: span ? "1 / -1" : "auto", display: "flex", flexDirection: "column", gap: 8, position: "relative" }}>
      <div data-elbody style={{ ...paperGrid(dark), border: `1px solid ${dark ? T.dline : T.line}`, borderRadius: 14, padding: 22, minHeight: 188, display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden" }}>{children}</div>
      <button onClick={(e) => dlSvg(e.currentTarget, name)} title="Baixar SVG" style={{ position: "absolute", top: 8, right: 8, cursor: "pointer", width: 22, height: 22, borderRadius: 6, border: `1px solid ${dark ? T.dline : T.line}`, background: dark ? T.dsurface : T.card, color: T.cyan, fontSize: 12, lineHeight: 1, padding: 0 }}>↓</button>
      <div style={{ fontFamily: HND, fontSize: 18, color: dark ? T.dsand : T.ink, textAlign: "center", lineHeight: 1 }}>{name}</div>
    </div>
  );
  const arrow = (d) => <svg viewBox="0 0 50 24" width="44" style={{ filter: "url(#rghH)", flexShrink: 0 }}><g {...SK(d, 2.4)}><path d="M6 12 H40" /><path d="M32 5 L42 12 L32 19" /></g></svg>;
  const StatBlock = (d) => (<div style={{ display: "flex", alignItems: "center", gap: 18 }}><IBadge dark={d} pct="40%" hatch="coral" w={118} /><div><div style={{ fontFamily: HND, fontSize: 26, color: ink(d), lineHeight: 1.05, whiteSpace: "nowrap" }}>menos latência</div><div style={{ fontFamily: F.text, fontSize: 12.5, color: sub(d), marginTop: 6, maxWidth: 150, lineHeight: 1.3 }}>após reescrever o índice</div></div></div>);
  const ProcessFlow = (d) => (<div style={{ display: "flex", alignItems: "center", gap: 4 }}>{[["1", "Coletar", "coral"], ["2", "Modelar", "amber"], ["3", "Servir", "cyan"]].map(([n, l, h], i) => (<React.Fragment key={n}><div style={{ textAlign: "center" }}><INum dark={d} n={n} hatch={h} w={58} /><div style={{ fontFamily: HND, fontSize: 16, color: ink(d) }}>{l}</div></div>{i < 2 && arrow(d)}</React.Fragment>))}</div>);
  const KpiRow = (d) => (<div style={{ display: "flex", gap: 22 }}>{[["98,7%", "uptime"], ["1,2M", "eventos/dia"], ["40%", "−latência"]].map(([v, l]) => (<div key={l} style={{ textAlign: "center" }}><div style={{ fontFamily: HND, fontSize: 38, color: ink(d), lineHeight: 1 }}>{v}</div><div style={{ fontFamily: F.mono, fontSize: 9.5, letterSpacing: 1, textTransform: "uppercase", color: sub(d), marginTop: 5 }}>{l}</div></div>))}</div>);
  const VennEx = (d) => (<div style={{ display: "flex", alignItems: "center", gap: 14 }}><IVenn dark={d} w={150} /><div style={{ display: "flex", flexDirection: "column", gap: 7 }}>{[["A", "Software"], ["B", "Dados"], ["C", "IA"]].map(([k, t]) => <div key={k} style={{ fontFamily: HND, fontSize: 18, color: ink(d) }}><b>{k}</b> · {t}</div>)}</div></div>);
  const PyrLevels = (d) => (<div style={{ display: "flex", alignItems: "center", gap: 14 }}><IPyramid dark={d} w={126} /><div style={{ display: "flex", flexDirection: "column", gap: 9 }}>{["Produto", "Modelo", "Dados", "Infra"].map(t => <div key={t} style={{ fontFamily: HND, fontSize: 16, color: ink(d) }}>— {t}</div>)}</div></div>);
  const BarsBlock = (d) => (<div style={{ textAlign: "center" }}><div style={{ fontFamily: F.display, fontWeight: 800, fontSize: 15, color: ink(d), marginBottom: 4 }}>Eventos por etapa</div><IBars dark={d} w={196} /></div>);
  const PieCallout = (d) => {
    const segs = [[0.34, "coral", "Software 34%"], [0.26, "cyan", "Dados 26%"], [0.22, "amber", "IA 22%"], [0.18, "olive", "Outros 18%"]];
    let a = -Math.PI / 2; const cx = 86, cy = 90, r = 56;
    return (<svg viewBox="0 0 300 184" width="100%" style={{ filter: "url(#rghH)" }}>{segs.map(([f, h, lbl], i) => { const a0 = a, a1 = a + f * 2 * Math.PI; a = a1; const mid = (a0 + a1) / 2; const ex = cx + r * Math.cos(mid), ey = cy + r * Math.sin(mid); const ly = 44 + i * 34; return (<g key={i}><path d={wedge(cx, cy, r, a0, a1)} fill={`url(#hb-${h})`} {...SK(d, 2)} /><path d={`M${ex.toFixed(1)} ${ey.toFixed(1)} L 182 ${ly}`} {...SK(d, 1.5)} /><text x="188" y={ly + 4} fontFamily={HND} fontSize="17" fill={ink(d)}>{lbl}</text></g>); })}<circle cx={cx} cy={cy} r="20" fill={d ? "#16110E" : "#F1E7D2"} {...SK(d, 2)} /></svg>);
  };
  const OrgChart = (d) => (<svg viewBox="0 0 300 166" width="100%" style={{ filter: "url(#rghH)" }}><g {...SK(d, 2.2)}><path d="M150 46 V78 M70 78 H230 M70 78 V108 M150 78 V108 M230 78 V108" /><rect x="118" y="16" width="64" height="30" rx="3" fill="url(#hb-amber)" /><rect x="40" y="108" width="60" height="30" rx="3" /><rect x="120" y="108" width="60" height="30" rx="3" /><rect x="200" y="108" width="60" height="30" rx="3" /></g><text x="150" y="35" textAnchor="middle" fontFamily={HND} fontSize="16" fill={ink(d)}>Plano</text>{["Dados", "Modelo", "App"].map((t, i) => <text key={t} x={70 + i * 80} y="127" textAnchor="middle" fontFamily={HND} fontSize="15" fill={ink(d)}>{t}</text>)}</svg>);
  const Timeline = (d) => (<svg viewBox="0 0 300 116" width="100%" style={{ filter: "url(#rghH)" }}><path d="M16 60 H284" {...SK(d, 2.4)} />{[["2023", "v1", "coral"], ["2024", "v2", "amber"], ["2025", "RAG", "cyan"]].map(([y, l, h], i) => { const x = 52 + i * 98; return (<g key={y}><circle cx={x} cy="60" r="8" fill={`url(#hb-${h})`} {...SK(d, 2)} /><text x={x} y="38" textAnchor="middle" fontFamily={F.mono} fontSize="11" fill={sub(d)}>{y}</text><text x={x} y="88" textAnchor="middle" fontFamily={HND} fontSize="18" fill={ink(d)}>{l}</text></g>); })}</svg>);
  const Comparison = (d) => (<svg viewBox="0 0 280 116" width="100%" style={{ filter: "url(#rghH)" }}>{[["Batch", 55, "olive"], ["Streaming", 90, "coral"]].map(([l, w, h], i) => { const y = 30 + i * 50; return (<g key={l}><text x="10" y={y - 6} fontFamily={HND} fontSize="17" fill={ink(d)}>{l}</text><rect x="10" y={y} width="258" height="18" rx="3" fill="none" {...SK(d, 1.5)} /><rect x="10" y={y} width={2.55 * w} height="18" rx="3" fill={`url(#hb-${h})`} {...SK(d, 1.5)} /><text x={2.55 * w + 18} y={y + 14} fontFamily={HND} fontSize="16" fill={ink(d)}>{w}%</text></g>); })}</svg>);

  // ── mais elementos avulsos (JSX literal + filtro hand-drawn) ──
  const Ic = (d, kids) => (<svg viewBox="0 0 48 48" width="56" style={{ filter: "url(#rghH)", display: "block" }}><g fill="none" stroke={ink(d)} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">{kids}</g></svg>);
  const EL = {
    rocket: (d) => <><path d="M24 5 C33 12 33 26 28 34 H20 C15 26 15 12 24 5" /><circle cx="24" cy="18" r="4" fill="url(#hb-cyan)" /><path d="M20 31 L13 38 L18 31 M28 31 L35 38 L30 31" /><path d="M22 35 C23 41 25 41 26 35" fill="url(#hb-coral)" /></>,
    bulb: (d) => <><path d="M24 6 C35 6 39 19 31 27 L31 33 L17 33 L17 27 C9 19 13 6 24 6" fill="url(#hb-amber)" /><path d="M18 37 H30 M20 41 H28" /></>,
    magnifier: (d) => <><circle cx="20" cy="20" r="12" fill="url(#hb-cyan)" /><path d="M29 29 L41 41" /></>,
    megaphone: (d) => <><path d="M10 22 L30 13 L30 35 L10 27 Z" fill="url(#hb-coral)" /><path d="M10 22 V27 L16 29 V24 Z" /><path d="M34 18 C38 21 38 27 34 30" /></>,
    gears: (d) => <><circle cx="19" cy="20" r="8" fill="url(#hb-olive)" /><circle cx="19" cy="20" r="3.5" /><path d="M19 8 V12 M19 28 V32 M7 20 H11 M27 20 H31 M11 12 L14 15 M24 25 L27 28 M27 12 L24 15 M14 25 L11 28" /><circle cx="34" cy="34" r="6" /><path d="M34 25 V28 M34 40 V43 M25 34 H28 M40 34 H43" /></>,
    target: (d) => <><circle cx="24" cy="24" r="17" /><circle cx="24" cy="24" r="10" fill="url(#hb-coral)" /><circle cx="24" cy="24" r="3.4" fill={ink(d)} /></>,
    trophy: (d) => <><path d="M16 9 H32 V20 C32 27 16 27 16 20 Z" fill="url(#hb-amber)" /><path d="M16 12 C9 12 9 21 17 22 M32 12 C39 12 39 21 31 22 M24 27 V34 M17 41 H31 M20 41 L21 34 H27 L28 41" /></>,
    briefcase: (d) => <><rect x="8" y="16" width="32" height="24" rx="2" fill="url(#hb-ink)" /><path d="M18 16 V11 H30 V16 M8 27 H40" /></>,
    coins: (d) => <><ellipse cx="24" cy="14" rx="13" ry="5" fill="url(#hb-amber)" /><path d="M11 14 V24 C11 29 37 29 37 24 V14 M11 24 V33 C11 38 37 38 37 33 V24" /></>,
    dollar: (d) => <><circle cx="24" cy="24" r="17" fill="url(#hb-olive)" /><path d="M28 17 C26 14 18 14 18 19 C18 24 30 23 30 29 C30 34 21 34 19 30 M24 11 V14 M24 34 V37" /></>,
    star: (d) => <><path d="M24 6 L30 19 L44 20 L33 30 L37 44 L24 36 L11 44 L15 30 L4 20 L18 19 Z" fill="url(#hb-amber)" /></>,
    rating: (d) => <>{[0, 1, 2].map((i) => <path key={i} d={`M${10 + i * 14} 19 l3 6 6 .6 -4.5 4.2 1.3 6.2 -5.8 -3.4 -5.8 3.4 1.3 -6.2 -4.5 -4.2 6 -.6 z`} fill={i < 2 ? "url(#hb-amber)" : "none"} />)}</>,
    check: (d) => <><path d="M9 25 L20 37 L40 11" strokeWidth="3" /></>,
    checklist: (d) => <><rect x="10" y="8" width="28" height="33" rx="2" /><path d="M15 16 l3 3 5 -6 M15 27 l3 3 5 -6 M27 16 H33 M27 28 H33" /></>,
    question: (d) => <><path d="M16 17 C16 7 33 7 32 17 C31 24 24 23 24 31 M24 38 V40" /></>,
    exclamation: (d) => <><path d="M24 8 V30 M24 38 V40" strokeWidth="3" /></>,
    plane: (d) => <><path d="M6 26 L42 8 L30 42 L23 29 Z" fill="url(#hb-cyan)" /><path d="M23 29 L42 8" /></>,
    clipboard: (d) => <><rect x="11" y="9" width="26" height="33" rx="2" /><path d="M19 9 V6 H29 V9 M16 19 H32 M16 26 H32 M16 33 H27" /></>,
    folder: (d) => <><path d="M7 13 H20 L24 18 H41 V38 H7 Z" fill="url(#hb-amber)" /></>,
    calendar: (d) => <><rect x="8" y="11" width="32" height="29" rx="2" /><path d="M8 19 H40 M16 7 V14 M32 7 V14 M15 26 H21 M27 26 H33" /></>,
    clock: (d) => <><circle cx="24" cy="24" r="17" /><path d="M24 13 V24 L32 29" /></>,
    hourglass: (d) => <><path d="M13 7 H35 M13 41 H35 M15 7 C15 18 33 18 33 7 M15 41 C15 30 33 30 33 41" /><path d="M19 38 C21 33 27 33 29 38 Z" fill="url(#hb-amber)" /></>,
    person: (d) => <><circle cx="24" cy="16" r="8" /><path d="M9 41 C9 28 39 28 39 41" /></>,
    team: (d) => <><circle cx="16" cy="17" r="6" /><circle cx="32" cy="17" r="6" /><path d="M5 38 C5 28 27 28 27 38 M21 38 C21 29 43 29 43 38" /></>,
    growth: (d) => <><path d="M7 41 V7 M7 41 H42" /><path d="M11 34 L20 26 L27 30 L39 14" /><path d="M32 13 L40 12 L39 20" /></>,
    gauge: (d) => <><path d="M9 34 A16 16 0 0 1 39 34" /><path d="M24 33 L33 20" /><circle cx="24" cy="34" r="2.6" fill={ink(d)} /></>,
    lightning: (d) => <><path d="M27 5 L13 27 L23 27 L20 43 L35 21 L25 21 Z" fill="url(#hb-amber)" /></>,
    globe: (d) => <><circle cx="24" cy="24" r="17" fill="url(#hb-cyan)" /><path d="M24 7 C14 16 14 32 24 41 C34 32 34 16 24 7 M8 19 H40 M8 29 H40" /></>,
    medal: (d) => <><circle cx="24" cy="30" r="11" fill="url(#hb-amber)" /><path d="M18 21 L13 7 H20 L24 17 M30 21 L35 7 H28 L24 17" /><path d="M24 27 L26 31 L30 31 L27 34 L28 38 L24 36 L20 38 L21 34 L18 31 L22 31 Z" fill={ink(d)} /></>,
    money: (d) => <><rect x="7" y="16" width="34" height="18" rx="1.5" fill="url(#hb-olive)" /><circle cx="24" cy="25" r="5" /><path d="M13 16 V34 M35 16 V34" /></>,
  };
  const MORE = ["rocket", "bulb", "magnifier", "megaphone", "gears", "target", "trophy", "briefcase", "coins", "dollar", "money", "star", "rating", "check", "checklist", "question", "exclamation", "plane", "clipboard", "folder", "calendar", "clock", "hourglass", "person", "team", "growth", "gauge", "lightning", "globe", "medal"];
  const BLOCKS = [["Bloco de estatística", StatBlock], ["Fluxo de processo", ProcessFlow], ["Pizza com chamadas", PieCallout], ["Organograma", OrgChart], ["Linha do tempo", Timeline], ["Comparação", Comparison], ["KPIs em linha", KpiRow], ["Venn explicado", VennEx], ["Pirâmide com níveis", PyrLevels], ["Barras tituladas", BarsBlock]];
  return (
    <Section id="componentes">
      <SharedDefs />
      <SecHead n="11" kicker="Componentes" title="Blocos de infográfico prontos."
        lead="Não são ícones soltos — são componentes inteiros, compostos: estatística, fluxo de processo, pizza com chamadas, organograma, linha do tempo, comparação… Cada um já monta um pedaço do infográfico no traço hand-drawn da marca. Encaixe na peça e troque os dados." />
      <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 20, marginBottom: 30 }}>
        {BLOCKS.map(([n, R]) => <Tile key={n} name={n}>{R(false)}</Tile>)}
      </div>
      <div style={{ fontFamily: F.display, fontWeight: 700, fontSize: 16, marginBottom: 12, color: T.sub }}>Os mesmos no escuro</div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 20 }}>
        <Tile name="estatística" dark>{StatBlock(true)}</Tile>
        <Tile name="fluxo" dark>{ProcessFlow(true)}</Tile>
        <Tile name="linha do tempo" dark>{Timeline(true)}</Tile>
      </div>
      <div style={{ fontFamily: F.display, fontWeight: 800, fontSize: 20, margin: "38px 0 6px" }}>Mais elementos <span style={{ fontFamily: F.mono, fontSize: 12, color: T.taupe, fontWeight: 400 }}>{MORE.length}</span></div>
      <Lead style={{ marginBottom: 18 }}>Objetos e marcadores hand-drawn da marca, pra compor infográficos, vídeos e slides. Recolore trocando o stroke.</Lead>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(92px, 1fr))", gap: 12, marginBottom: 18 }}>
        {MORE.map((n) => (
          <div key={n} data-eltile style={{ ...paperGrid(false), border: `1px solid ${T.line}`, borderRadius: 12, padding: "16px 6px 9px", display: "flex", flexDirection: "column", alignItems: "center", gap: 7, position: "relative" }}>
            {Ic(false, EL[n](false))}
            <span style={{ fontFamily: HND, fontSize: 15, color: T.ink, lineHeight: 1 }}>{n}</span>
            <button onClick={(e) => dlSvg(e.currentTarget, n)} title="Baixar SVG" style={{ position: "absolute", top: 6, right: 6, cursor: "pointer", width: 20, height: 20, borderRadius: 6, border: `1px solid ${T.line}`, background: T.card, color: T.cyan, fontSize: 11, lineHeight: 1, padding: 0 }}>↓</button>
          </div>
        ))}
      </div>
      <div style={{ background: T.dbg, borderRadius: 14, padding: 22, display: "flex", flexWrap: "wrap", gap: 20, justifyContent: "center", marginBottom: 8 }}>
        {["rocket", "bulb", "megaphone", "trophy", "target", "gears", "star", "globe", "medal", "plane"].map((n) => <span key={n} style={{ display: "inline-flex" }}>{Ic(true, EL[n](true))}</span>)}
      </div>

      <div style={{ marginTop: 22 }}>
        <Note title="Como usar">Escolha o bloco que responde sua pergunta, encaixe sobre o papel quadriculado e troque os dados. Combine 2–3 por peça (ex.: faixa de título + pizza com chamadas + bloco de estatística) — um só assunto por infográfico.</Note>
      </div>
    </Section>
  );
}

Object.assign(window, { GMInfographics, GMComponents });
