// whiteboards.jsx — six hand-drawn marker companion sketches.
// Wobble filter on every freehand stroke; text rendered crisp (outside the filter group).
// Palette: red #FF2417, ink #1F201B, dotted 3 3. Surface handled by .whiteboard wrapper.

const RED = "#FF2417";
const INK = "#1F201B";
const GRN = "#7AF58C";

function Wobble({ id, scale = 1.1 }) {
  return (
    <filter id={id} x="-10%" y="-10%" width="120%" height="120%">
      <feTurbulence type="fractalNoise" baseFrequency="0.022" numOctaves="2" seed="3" />
      <feDisplacementMap in="SourceGraphic" scale={scale} />
    </filter>
  );
}

// hand-drawn arrow: shaft + two head strokes, all inside a wobble group by caller
function arrow(x1, y1, x2, y2, color = RED, w = 1.8) {
  const ang = Math.atan2(y2 - y1, x2 - x1);
  const hl = 9;
  const a1 = ang + Math.PI - 0.5, a2 = ang + Math.PI + 0.5;
  return (
    <g stroke={color} strokeWidth={w} strokeLinecap="round" fill="none">
      <path d={`M ${x1} ${y1} Q ${(x1 + x2) / 2} ${(y1 + y2) / 2 - 4} ${x2} ${y2}`} />
      <path d={`M ${x2} ${y2} L ${x2 + hl * Math.cos(a1)} ${y2 + hl * Math.sin(a1)}`} />
      <path d={`M ${x2} ${y2} L ${x2 + hl * Math.cos(a2)} ${y2 + hl * Math.sin(a2)}`} />
    </g>
  );
}

function pageIcon(x, y, w, h, color = INK) {
  const fold = 12;
  return (
    <g stroke={color} strokeWidth="1.7" fill="#fff" strokeLinejoin="round">
      <path d={`M ${x} ${y} L ${x + w - fold} ${y} L ${x + w} ${y + fold} L ${x + w} ${y + h} L ${x} ${y + h} Z`} />
      <path d={`M ${x + w - fold} ${y} L ${x + w - fold} ${y + fold} L ${x + w} ${y + fold}`} fill="none" />
      <g stroke={color} strokeWidth="1.4">
        <path d={`M ${x + 8} ${y + 22} L ${x + w - 10} ${y + 22}`} />
        <path d={`M ${x + 8} ${y + 33} L ${x + w - 14} ${y + 33}`} />
        <path d={`M ${x + 8} ${y + 44} L ${x + w - 8} ${y + 44}`} />
      </g>
    </g>
  );
}

/* ---------------------------------------------------------------- wb-channels */
function WBChannels() {
  const topTicks = [180, 300, 420, 540, 645];
  const botTicks = [];
  for (let x = 180; x <= 645; x += 24) botTicks.push(x);
  return (
    <svg viewBox="0 0 720 360" fontFamily="IBM Plex Mono">
      <defs><Wobble id="wob-ch" /></defs>
      <g filter="url(#wob-ch)" fill="none" strokeLinecap="round">
        {/* top timeline */}
        <path d="M 180 96 L 660 96" stroke={INK} strokeWidth="1.8" />
        {topTicks.map((x, i) => <path key={i} d={`M ${x} 88 L ${x} 104`} stroke={INK} strokeWidth="1.6" />)}
        {/* ship-date markers */}
        {[240, 430, 600].map((x, i) => (
          <g key={i} stroke={RED} strokeWidth="1.8">
            <path d={`M ${x} 96 L ${x} 72`} />
            <path d={`M ${x} 72 L ${x + 18} 76 L ${x} 82 Z`} fill={RED} />
          </g>
        ))}
        {/* bottom timeline */}
        <path d="M 180 276 L 660 276" stroke={INK} strokeWidth="1.8" />
        {botTicks.map((x, i) => <path key={i} d={`M ${x} 270 L ${x} 282`} stroke={INK} strokeWidth="1.3" />)}
        <circle cx="468" cy="276" r="6" fill={RED} stroke="none" />
        {/* page + arrows */}
        {arrow(360, 150, 300, 100, RED)}
        {arrow(360, 210, 470, 268, RED)}
      </g>
      {pageIcon(330, 150, 64, 60)}
      <text x="180" y="58" fontSize="20" fontWeight="700" fill={INK}>Training data</text>
      <text x="540" y="58" fontSize="17" fontWeight="600" fill={RED}>next train run →</text>
      <text x="180" y="312" fontSize="20" fontWeight="700" fill={INK}>Live search</text>
      <text x="486" y="262" fontSize="16" fontWeight="600" fill={RED}>recrawl</text>
      <text x="180" y="346" fontSize="13" letterSpacing="0.04em" fill={INK} opacity="0.78">AIO ROTATES EVERY ~2 DAYS · MEANING STAYS ~95%</text>
    </svg>
  );
}

/* ------------------------------------------------------------- wb-checkpoint1 */
function WBCheckpoint1() {
  const gates = [
    { x: 250, label: "Firewall (WAF)" },
    { x: 380, label: "CDN bot mgmt" },
    { x: 510, label: "Robots.txt" },
  ];
  function bot(x, y, s = 1) {
    return (
      <g stroke={INK} strokeWidth="1.7" fill="#fff" transform={`translate(${x} ${y}) scale(${s})`}>
        <rect x="-16" y="-12" width="32" height="26" rx="5" />
        <circle cx="-7" cy="0" r="2.4" fill={INK} stroke="none" />
        <circle cx="7" cy="0" r="2.4" fill={INK} stroke="none" />
        <path d="M -8 8 L 8 8" />
        <path d="M 0 -12 L 0 -20" /><circle cx="0" cy="-22" r="2.5" fill={INK} stroke="none" />
      </g>
    );
  }
  return (
    <svg viewBox="0 0 720 360" fontFamily="IBM Plex Mono">
      <defs><Wobble id="wob-c1" /></defs>
      <g filter="url(#wob-c1)" fill="none" strokeLinecap="round">
        {gates.map((g, i) => (
          <path key={i} d={`M ${g.x} 70 L ${g.x} 290`} stroke={i === 2 ? INK : RED} strokeWidth="2" strokeDasharray={i === 2 ? "3 3" : "none"} />
        ))}
      </g>
      {/* three bots */}
      <g filter="url(#wob-c1)">{bot(150, 110)}</g>
      <g filter="url(#wob-c1)">{bot(150, 200)}</g>
      <g filter="url(#wob-c1)">{bot(150, 290 - 4)}</g>
      {/* paths: bot1 stopped at firewall, bot2 stopped at CDN, bot3 through */}
      <g filter="url(#wob-c1)">
        {arrow(170, 110, 232, 110, INK, 1.6)}
        {arrow(170, 200, 362, 200, INK, 1.6)}
        {arrow(170, 290, 600, 290, INK, 1.6)}
      </g>
      {/* page on right */}
      {pageIcon(600, 130, 70, 100)}
      {/* gate labels */}
      {gates.map((g, i) => (
        <text key={i} x={g.x} y="58" fontSize="15" fontWeight="600" fill={i === 2 ? INK : RED} textAnchor="middle">{g.label}</text>
      ))}
      <text x="250" y="110" fontSize="18" fontWeight="700" fill={RED} textAnchor="middle">403</text>
      <text x="380" y="200" fontSize="18" fontWeight="700" fill={RED} textAnchor="middle">403</text>
      <text x="600" y="248" fontSize="15" fontWeight="600" fill={INK}>page</text>
      <text x="200" y="344" fontSize="18" fontWeight="600" fill={INK} opacity="0.8">robots.txt says yes — the edge still says no</text>
    </svg>
  );
}

/* ------------------------------------------------------------- wb-checkpoint3 */
function WBCheckpoint3() {
  const wall = [];
  for (let i = 0; i < 16; i++) wall.push(70 + i * 13);
  const sections = [80, 142, 204, 266]; // y of each H2 (4 shown, repeated visual rhythm)
  return (
    <svg viewBox="0 0 720 380" fontFamily="IBM Plex Mono">
      <defs><Wobble id="wob-c3" /></defs>
      <g filter="url(#wob-c3)" fill="none" strokeLinecap="round">
        {/* left: wall of prose */}
        {wall.map((y, i) => <path key={i} d={`M 70 ${y} L ${260 - (i % 3) * 14} ${y}`} stroke={INK} strokeWidth="1.5" />)}
        {/* right: sectioned */}
        {sections.map((y, i) => (
          <g key={i}>
            <path d={`M 440 ${y} L 540 ${y}`} stroke={RED} strokeWidth="4" />
            <path d={`M 440 ${y + 16} L 640 ${y + 16}`} stroke={INK} strokeWidth="1.5" />
            <path d={`M 440 ${y + 28} L 612 ${y + 28}`} stroke={INK} strokeWidth="1.5" />
            {arrow(648, y + 8, 686, y + 8, RED, 1.5)}
          </g>
        ))}
      </g>
      <text x="70" y="52" fontSize="17" fontWeight="700" fill={INK}>wall of prose → 0 citations</text>
      <text x="440" y="52" fontSize="17" fontWeight="700" fill={RED}>8 sections → 8 citations</text>
      {sections.map((y, i) => (
        <text key={i} x="690" y={y + 12} fontSize="14" fontWeight="600" fill={RED}>cite</text>
      ))}
    </svg>
  );
}

/* --------------------------------------------------------------- wb-freshness */
function WBFreshness() {
  const cols = [];
  for (let i = 0; i < 13; i++) cols.push(120 + i * 36);
  // decay curve points
  const curve = "M 120 110 Q 300 120 420 150 Q 520 180 560 250 Q 600 300 660 318";
  return (
    <svg viewBox="0 0 720 360" fontFamily="IBM Plex Mono">
      <defs><Wobble id="wob-fr" /></defs>
      <g filter="url(#wob-fr)" fill="none" strokeLinecap="round">
        {/* calendar grid */}
        {cols.map((x, i) => <path key={"v" + i} d={`M ${x} 90 L ${x} 300`} stroke={RED} strokeWidth="1.3" opacity="0.55" />)}
        <path d="M 120 90 L 552 90" stroke={RED} strokeWidth="1.3" opacity="0.55" />
        <path d="M 120 300 L 552 300" stroke={RED} strokeWidth="1.3" opacity="0.55" />
        {/* cliff line at column 13 */}
        <path d="M 552 70 L 552 320" stroke={INK} strokeWidth="1.8" strokeDasharray="3 3" />
        {/* decay curve */}
        <path d={curve} stroke={RED} strokeWidth="2.4" />
        {/* checkmark week2 */}
        <path d="M 150 150 l 7 8 l 13 -16" stroke={GRN} strokeWidth="3" />
        {/* question mark approx week12 via text; X at week20 */}
        <path d="M 612 280 l 16 16 M 628 280 l -16 16" stroke={INK} strokeWidth="2.4" />
      </g>
      <text x="120" y="74" fontSize="16" fontWeight="600" fill={INK}>13-week calendar</text>
      <text x="556" y="64" fontSize="17" fontWeight="700" fill={INK}>cliff</text>
      <text x="150" y="138" fontSize="14" fontWeight="600" fill="#2f7a3d">fresh</text>
      <text x="470" y="200" fontSize="14" fontWeight="600" fill={INK}>on the edge ?</text>
      <text x="600" y="270" fontSize="14" fontWeight="600" fill={INK}>dropped</text>
      <text x="120" y="346" fontSize="18" fontWeight="600" fill={INK} opacity="0.8">after wk 13 → most pipelines flag stale</text>
    </svg>
  );
}

/* ------------------------------------------------------------- wb-specificity */
function WBSpecificity() {
  return (
    <svg viewBox="0 0 720 380" fontFamily="IBM Plex Mono">
      <defs><Wobble id="wob-sp" /></defs>
      {/* left generic passage box */}
      <rect x="40" y="70" width="290" height="170" rx="6" fill="#fff" stroke="rgba(31,32,27,0.2)" strokeWidth="1" />
      {/* right specific passage box */}
      <rect x="390" y="70" width="290" height="170" rx="6" fill="#fff" stroke="rgba(31,32,27,0.2)" strokeWidth="1" />
      <text x="56" y="104" fontFamily="Inter" fontSize="12.5" fill={INK}>A good chef's knife stays</text>
      <text x="56" y="124" fontFamily="Inter" fontSize="12.5" fill={INK}>balanced and holds an edge</text>
      <text x="56" y="144" fontFamily="Inter" fontSize="12.5" fill={INK}>for a long time. It is</text>
      <text x="56" y="164" fontFamily="Inter" fontSize="12.5" fill={INK}>recommended by an expert</text>
      <text x="56" y="184" fontFamily="Inter" fontSize="12.5" fill={INK}>after lots of testing.</text>

      <text x="406" y="104" fontFamily="Inter" fontSize="12.5" fill={INK}>The <tspan fill={RED} fontWeight="600">Misono UX10</tspan> held an</text>
      <text x="406" y="124" fontFamily="Inter" fontSize="12.5" fill={INK}>edge for 600 cuts at <tspan fill={RED} fontWeight="600">$160</tspan>.</text>
      <text x="406" y="144" fontFamily="Inter" fontSize="12.5" fill={INK}><tspan fill={RED} fontWeight="600">Tested 6 weeks</tspan> by</text>
      <text x="406" y="164" fontFamily="Inter" fontSize="12.5" fill={INK}><tspan fill={RED} fontWeight="600">Sarah Chen, chef</tspan>, across</text>
      <text x="406" y="184" fontFamily="Inter" fontSize="12.5" fill={INK}>14 competing knives.</text>

      <g filter="url(#wob-sp)" fill="none" strokeLinecap="round">
        {/* red X over generic */}
        <path d="M 48 78 L 322 232" stroke={RED} strokeWidth="2.4" />
        <path d="M 322 78 L 48 232" stroke={RED} strokeWidth="2.4" />
        {/* circles on specifics */}
        <ellipse cx="470" cy="99" rx="46" ry="13" stroke={RED} strokeWidth="1.8" transform="rotate(-3 470 99)" />
        <ellipse cx="556" cy="119" rx="22" ry="12" stroke={RED} strokeWidth="1.8" transform="rotate(4 556 119)" />
        <ellipse cx="470" cy="139" rx="50" ry="13" stroke={RED} strokeWidth="1.8" transform="rotate(-2 470 139)" />
        <ellipse cx="486" cy="159" rx="58" ry="13" stroke={RED} strokeWidth="1.8" transform="rotate(3 486 159)" />
        {/* checkmark right */}
        <path d="M 636 250 l 9 11 l 18 -22" stroke={GRN} strokeWidth="3.4" />
      </g>
      <text x="40" y="58" fontSize="17" fontWeight="700" fill={INK}>generic version</text>
      <text x="390" y="58" fontSize="17" fontWeight="700" fill={RED}>specific version</text>
      <text x="40" y="300" fontSize="15" fontWeight="600" fill={INK} opacity="0.82">generic gets cut.</text>
      <text x="390" y="300" fontSize="15" fontWeight="600" fill={INK} opacity="0.82">specific gets kept.</text>
      <text x="390" y="350" fontSize="13" letterSpacing="0.04em" fill={RED}>AI MODE 3.3 ENTITIES · AIO 1.3</text>
    </svg>
  );
}

/* ---------------------------------------------------------------------- wb-sbc */
function WBSBC() {
  return (
    <svg viewBox="0 0 720 360" fontFamily="IBM Plex Mono">
      <defs><Wobble id="wob-sbc" /></defs>
      <g filter="url(#wob-sbc)" fill="none" strokeLinecap="round">
        {/* three concentric arcs (rink from above), net at right */}
        <path d="M 560 60 A 320 300 0 0 0 560 320" stroke={INK} strokeWidth="2" />
        <path d="M 590 110 A 230 200 0 0 0 590 290" stroke={INK} strokeWidth="2" />
        <path d="M 612 150 A 150 120 0 0 0 612 270" stroke={INK} strokeWidth="2" />
        {/* net */}
        <rect x="650" y="170" width="34" height="60" rx="3" stroke={INK} strokeWidth="1.8" />
        {/* puck path */}
        <path d="M 70 240 Q 260 150 430 200 Q 560 240 648 200" stroke={RED} strokeWidth="2.2" strokeDasharray="2 6" />
        {arrow(610, 205, 648, 200, RED, 2)}
        <circle cx="70" cy="240" r="7" fill={RED} stroke="none" />
      </g>
      <text x="470" y="50" fontSize="18" fontWeight="700" fill={INK}>Seen</text>
      <text x="548" y="100" fontSize="17" fontWeight="700" fill={INK}>Believed</text>
      <text x="588" y="146" fontSize="16" fontWeight="700" fill={INK}>Chosen</text>
      <text x="90" y="224" fontSize="15" fontWeight="600" fill={RED}>citations</text>
      <text x="300" y="150" fontSize="15" fontWeight="600" fill={RED}>branded search ↑</text>
      <text x="470" y="240" fontSize="15" fontWeight="600" fill={RED}>pipeline</text>
      <text x="70" y="332" fontSize="18" fontWeight="600" fill={INK} opacity="0.8">visibility = shot on goal, not goal scored</text>
    </svg>
  );
}

Object.assign(window, {
  WBChannels, WBCheckpoint1, WBCheckpoint3, WBFreshness, WBSpecificity, WBSBC,
});
