// Diagram primitives + 11 step diagrams
// Technical drawing style: dimension lines, leaders, annotations
// All SVGs use viewBox 1200x700 so they scale large

const INK = "#1A1A1A";
const ACCENT = "#E85D3C";
const NG = "#B23A1A";
const OK = "#2E7D3A";
const GRID = "rgba(26,26,26,0.06)";
const GRID_HARD = "rgba(26,26,26,0.16)";

const VB_W = 1200;
const VB_H = 700;

function GridBg({ id = "grid-default", size = 24 }) {
  return (
    <defs>
      <pattern id={id} width={size} height={size} patternUnits="userSpaceOnUse">
        <path d={`M ${size} 0 L 0 0 0 ${size}`} fill="none" stroke={GRID} strokeWidth="0.5" />
      </pattern>
      <pattern id={id + "-hard"} width={size * 5} height={size * 5} patternUnits="userSpaceOnUse">
        <rect width={size * 5} height={size * 5} fill={`url(#${id})`} />
        <path d={`M ${size * 5} 0 L 0 0 0 ${size * 5}`} fill="none" stroke={GRID_HARD} strokeWidth="0.6" />
      </pattern>
    </defs>
  );
}

function Dim({ x1, y1, x2, y2, label, offset = 0, color = INK, labelBg = "#FAFAF7", fontSize = 15 }) {
  const dx = x2 - x1, dy = y2 - y1;
  const len = Math.hypot(dx, dy) || 1;
  const nx = -dy / len, ny = dx / len;
  const ox1 = x1 + nx * offset, oy1 = y1 + ny * offset;
  const ox2 = x2 + nx * offset, oy2 = y2 + ny * offset;
  const mx = (ox1 + ox2) / 2, my = (oy1 + oy2) / 2;
  const ah = 7;
  return (
    <g>
      {offset !== 0 && (
        <>
          <line x1={x1} y1={y1} x2={ox1} y2={oy1} stroke={color} strokeWidth="0.8" strokeDasharray="3 3" />
          <line x1={x2} y1={y2} x2={ox2} y2={oy2} stroke={color} strokeWidth="0.8" strokeDasharray="3 3" />
        </>
      )}
      <line x1={ox1} y1={oy1} x2={ox2} y2={oy2} stroke={color} strokeWidth="1" />
      <polygon points={`${ox1},${oy1} ${ox1 + (dx / len) * ah + nx * ah / 2},${oy1 + (dy / len) * ah + ny * ah / 2} ${ox1 + (dx / len) * ah - nx * ah / 2},${oy1 + (dy / len) * ah - ny * ah / 2}`} fill={color} />
      <polygon points={`${ox2},${oy2} ${ox2 - (dx / len) * ah + nx * ah / 2},${oy2 - (dy / len) * ah + ny * ah / 2} ${ox2 - (dx / len) * ah - nx * ah / 2},${oy2 - (dy / len) * ah - ny * ah / 2}`} fill={color} />
      {label && (
        <g transform={`translate(${mx},${my})`}>
          <rect x={-(String(label).length * fontSize * 0.32 + 10)} y={-fontSize * 0.85} width={String(label).length * fontSize * 0.64 + 20} height={fontSize * 1.7} fill={labelBg} />
          <text x="0" y={fontSize * 0.35} textAnchor="middle" fill={color} fontSize={fontSize} fontFamily="JetBrains Mono, monospace" fontWeight="500">{label}</text>
        </g>
      )}
    </g>
  );
}

function Leader({ x, y, tx, ty, label, color = INK, anchor = "start", fontSize = 16 }) {
  return (
    <g>
      <circle cx={x} cy={y} r="3.5" fill={color} />
      <line x1={x} y1={y} x2={tx} y2={ty} stroke={color} strokeWidth="1" />
      <line x1={tx} y1={ty} x2={tx + (anchor === "start" ? 56 : -56)} y2={ty} stroke={color} strokeWidth="1" />
      <text x={tx + (anchor === "start" ? 62 : -62)} y={ty + 5} textAnchor={anchor} fill={color} fontSize={fontSize} fontFamily="var(--font-ja)">{label}</text>
    </g>
  );
}

function StickerShape({ kind = "star", x = 0, y = 0, size = 60, fill = "#fff", stroke = INK, strokeWidth = 1, strokeDasharray }) {
  const r = size / 2;
  let path = "";
  if (kind === "star") {
    const pts = [];
    for (let i = 0; i < 10; i++) {
      const ang = (Math.PI * 2 * i) / 10 - Math.PI / 2;
      const rr = i % 2 === 0 ? r : r * 0.45;
      pts.push([Math.cos(ang) * rr, Math.sin(ang) * rr]);
    }
    path = "M" + pts.map(p => p.map(n => n.toFixed(2)).join(",")).join(" L") + " Z";
  } else if (kind === "heart") {
    path = `M 0 ${-r*0.2} C ${r*0.55} ${-r}, ${r} ${-r*0.4}, 0 ${r*0.55} C ${-r} ${-r*0.4}, ${-r*0.55} ${-r}, 0 ${-r*0.2} Z`;
  } else if (kind === "cloud") {
    path = `M ${-r*0.7} ${r*0.2} C ${-r} ${r*0.2}, ${-r} ${-r*0.3}, ${-r*0.55} ${-r*0.3} C ${-r*0.55} ${-r*0.7}, ${-r*0.1} ${-r*0.75}, ${0} ${-r*0.4} C ${r*0.15} ${-r*0.75}, ${r*0.65} ${-r*0.65}, ${r*0.6} ${-r*0.25} C ${r} ${-r*0.25}, ${r} ${r*0.2}, ${r*0.65} ${r*0.2} Z`;
  } else if (kind === "blob") {
    path = `M ${-r*0.7} ${-r*0.3} C ${-r} ${-r*0.8}, ${-r*0.2} ${-r}, ${r*0.35} ${-r*0.75} C ${r} ${-r*0.55}, ${r*0.95} ${r*0.2}, ${r*0.5} ${r*0.8} C ${-r*0.2} ${r}, ${-r*0.9} ${r*0.6}, ${-r*0.7} ${-r*0.3} Z`;
  } else if (kind === "circle") {
    return <circle cx={x} cy={y} r={r} fill={fill} stroke={stroke} strokeWidth={strokeWidth} strokeDasharray={strokeDasharray} />;
  } else if (kind === "rect") {
    return <rect x={x - r} y={y - r} width={size} height={size} rx={size * 0.1} fill={fill} stroke={stroke} strokeWidth={strokeWidth} strokeDasharray={strokeDasharray} />;
  } else if (kind === "hex") {
    const pts = [];
    for (let i = 0; i < 6; i++) {
      const ang = (Math.PI * 2 * i) / 6 - Math.PI / 2;
      pts.push([Math.cos(ang) * r, Math.sin(ang) * r]);
    }
    path = "M" + pts.map(p => p.map(n => n.toFixed(2)).join(",")).join(" L") + " Z";
  }
  return <path d={path} transform={`translate(${x},${y})`} fill={fill} stroke={stroke} strokeWidth={strokeWidth} strokeDasharray={strokeDasharray} />;
}

function VerdictBadge({ verdict = "OK", x = 0, y = 0, w = 78, h = 30 }) {
  const isOK = verdict === "OK";
  const color = isOK ? OK : NG;
  return (
    <g transform={`translate(${x},${y})`}>
      <rect x="0" y="0" width={w} height={h} fill={color} />
      <text x={w/2} y={h*0.67} textAnchor="middle" fill="#fff" fontSize="16" fontFamily="JetBrains Mono, monospace" fontWeight="500" letterSpacing="1">
        {isOK ? "OK" : "NG"}
      </text>
    </g>
  );
}

function Panel({ x, y, w, h, title, children, titleRight }) {
  return (
    <g transform={`translate(${x},${y})`}>
      <rect x="0" y="0" width={w} height={h} fill="#FFFFFF" stroke={INK} strokeWidth="1" />
      {title && (
        <>
          <line x1="0" y1="34" x2={w} y2="34" stroke={INK} strokeWidth="0.6" />
          <text x="16" y="23" fill={INK} fontSize="14" fontFamily="JetBrains Mono, monospace" fontWeight="500" letterSpacing="1.5">{title}</text>
          {titleRight && <text x={w - 16} y="23" textAnchor="end" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" opacity="0.5">{titleRight}</text>}
        </>
      )}
      {children}
    </g>
  );
}

// ========== 01 File formats ==========
function DiagramFileFormat({ detail = 2 }) {
  const fmt = (ext, ok, color) => ({ ext, ok, color });
  const files = [
    fmt(".ai", true, "#E87B35"),
    fmt(".psd", true, "#31A8FF"),
    fmt(".jpg", false, "#888"),
    fmt(".png", false, "#888"),
    fmt(".docx", false, "#2B579A"),
    fmt(".pptx", false, "#D24726"),
  ];
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf1" />
      <rect width={VB_W} height={VB_H} fill="url(#gf1-hard)" />
      <g transform="translate(80,120)">
        {files.map((f, i) => {
          const col = i % 3, row = Math.floor(i / 3);
          return (
            <g key={i} transform={`translate(${col * 340},${row * 220})`}>
              <g>
                {/* file icon */}
                <path d="M 20 10 L 140 10 L 180 50 L 180 180 L 20 180 Z" fill="#fff" stroke={INK} strokeWidth="1.2" />
                <path d="M 140 10 L 140 50 L 180 50" fill="none" stroke={INK} strokeWidth="1.2" />
                <rect x="40" y="80" width="120" height="42" fill={f.color} opacity={f.ok ? 1 : 0.25} />
                <text x="100" y="110" textAnchor="middle" fill="#fff" fontSize="20" fontFamily="JetBrains Mono, monospace" fontWeight="600">{f.ext}</text>
                <VerdictBadge verdict={f.ok ? "OK" : "NG"} x={200} y={20} />
                {detail >= 2 && (
                  <text x={200} y={80} fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" opacity="0.55">
                    {f.ext === ".ai" ? "Illustrator" : f.ext === ".psd" ? "Photoshop" : f.ext === ".docx" ? "Word" : f.ext === ".pptx" ? "PowerPoint" : "raster image"}
                  </text>
                )}
              </g>
            </g>
          );
        })}
      </g>
    </svg>
  );
}

// ========== 02 CMYK vs RGB ==========
function DiagramCMYK({ detail = 2 }) {
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf2" />
      <rect width={VB_W} height={VB_H} fill="url(#gf2-hard)" />

      <Panel x={80} y={80} w={500} h={540} title="CMYK" titleRight="PRINT">
        <g transform="translate(250,220)">
          <circle cx="-60" cy="-40" r="90" fill="#00AEEF" opacity="0.8" style={{ mixBlendMode: "multiply" }} />
          <circle cx="60" cy="-40" r="90" fill="#EC008C" opacity="0.8" style={{ mixBlendMode: "multiply" }} />
          <circle cx="0" cy="60" r="90" fill="#FFF200" opacity="0.8" style={{ mixBlendMode: "multiply" }} />
        </g>
        <g transform="translate(60,400)">
          {["C", "M", "Y", "K"].map((l, i) => (
            <g key={l} transform={`translate(${i * 100},0)`}>
              <rect x="0" y="0" width="80" height="40" fill={["#00AEEF", "#EC008C", "#FFF200", "#1A1A1A"][i]} />
              <text x="40" y="26" textAnchor="middle" fill={i < 3 ? "#000" : "#fff"} fontSize="18" fontFamily="JetBrains Mono, monospace" fontWeight="600">{l}</text>
            </g>
          ))}
        </g>
        <VerdictBadge verdict="OK" x={16} y={480} />
        {detail >= 2 && <text x={250} y={500} textAnchor="middle" fill={INK} fontSize="15" fontFamily="var(--font-ja)">印刷用のカラーモード</text>}
      </Panel>

      <Panel x={620} y={80} w={500} h={540} title="RGB" titleRight="SCREEN">
        <g transform="translate(250,220)">
          <circle cx="0" cy="-60" r="90" fill="#FF0000" opacity="0.7" style={{ mixBlendMode: "screen" }} />
          <circle cx="-60" cy="40" r="90" fill="#00FF00" opacity="0.7" style={{ mixBlendMode: "screen" }} />
          <circle cx="60" cy="40" r="90" fill="#0000FF" opacity="0.7" style={{ mixBlendMode: "screen" }} />
        </g>
        <g transform="translate(110,400)">
          {["R", "G", "B"].map((l, i) => (
            <g key={l} transform={`translate(${i * 100},0)`}>
              <rect x="0" y="0" width="80" height="40" fill={["#FF0000", "#00FF00", "#0000FF"][i]} />
              <text x="40" y="26" textAnchor="middle" fill="#fff" fontSize="18" fontFamily="JetBrains Mono, monospace" fontWeight="600">{l}</text>
            </g>
          ))}
        </g>
        <VerdictBadge verdict="NG" x={16} y={480} />
        {detail >= 2 && <text x={250} y={500} textAnchor="middle" fill={INK} fontSize="15" fontFamily="var(--font-ja)">画面用 → 印刷時に色が変わる</text>}
      </Panel>
    </svg>
  );
}

// ========== 03 Outline fonts ==========
function DiagramOutline({ detail = 2 }) {
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf3" />
      <rect width={VB_W} height={VB_H} fill="url(#gf3-hard)" />

      <Panel x={60} y={80} w={480} h={540} title="BEFORE" titleRight="TEXT">
        <g transform="translate(240,280)">
          <text x="0" y="0" textAnchor="middle" fill={INK} fontSize="120" fontFamily="var(--font-ja)" fontWeight="600">あア</text>
        </g>
        {detail >= 2 && (
          <>
            <Leader x={200} y={240} tx={80} ty={420} label="テキスト情報" color={INK} anchor="start" fontSize={14} />
            <text x={240} y={480} textAnchor="middle" fill={INK} fontSize="15" fontFamily="JetBrains Mono, monospace" opacity="0.6">editable / font-dependent</text>
          </>
        )}
      </Panel>

      <g transform="translate(560,330)">
        <path d="M 0 20 L 60 20" stroke={INK} strokeWidth="1.5" />
        <polygon points="60,12 78,20 60,28" fill={INK} />
        <text x="40" y="0" textAnchor="middle" fill={ACCENT} fontSize="13" fontFamily="JetBrains Mono, monospace" fontWeight="500">OUTLINE</text>
      </g>

      <Panel x={660} y={80} w={480} h={540} title="AFTER" titleRight="PATH">
        <g transform="translate(240,280)">
          <text x="0" y="0" textAnchor="middle" fill="none" stroke={INK} strokeWidth="1.5" fontSize="120" fontFamily="var(--font-ja)" fontWeight="600">あア</text>
          {/* anchor points */}
          {detail >= 2 && [[-75, -55], [-45, -90], [10, -80], [45, -50], [60, 10], [30, 50], [-20, 55], [-65, 20], [80, -55], [115, -20], [130, 40], [90, 55], [45, 30]].map(([px, py], i) => (
            <rect key={i} x={px - 3} y={py - 3} width="6" height="6" fill="#fff" stroke={ACCENT} strokeWidth="1.2" />
          ))}
        </g>
        <VerdictBadge verdict="OK" x={16} y={480} />
        {detail >= 2 && <text x={240} y={500} textAnchor="middle" fill={INK} fontSize="15" fontFamily="JetBrains Mono, monospace" opacity="0.6">shape / font-free</text>}
      </Panel>
    </svg>
  );
}

// ========== 04 Link vs Embed ==========
function DiagramEmbed({ detail = 2 }) {
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf4" />
      <rect width={VB_W} height={VB_H} fill="url(#gf4-hard)" />

      {/* NG: link */}
      <Panel x={60} y={80} w={500} h={540} title="LINKED" titleRight="NG">
        <g transform="translate(250,240)">
          <rect x="-120" y="-90" width="240" height="180" fill="#fff" stroke={INK} strokeWidth="1.2" />
          <g transform="translate(-60,-40)">
            <rect x="0" y="0" width="120" height="80" fill="none" stroke={NG} strokeWidth="1.5" strokeDasharray="5 4" />
            <text x="60" y="46" textAnchor="middle" fill={NG} fontSize="14" fontFamily="JetBrains Mono, monospace">? missing</text>
          </g>
        </g>
        <g transform="translate(60,410)">
          <rect x="0" y="0" width="50" height="36" fill="#6AA84F" />
          <text x="25" y="23" textAnchor="middle" fill="#fff" fontSize="14" fontFamily="JetBrains Mono, monospace">IMG</text>
          <path d="M 60 18 L 140 18" stroke={NG} strokeWidth="1.5" strokeDasharray="5 4" />
          <text x="100" y="10" textAnchor="middle" fill={NG} fontSize="13" fontFamily="JetBrains Mono, monospace">broken</text>
          <rect x="150" y="0" width="280" height="36" fill="#fff" stroke={INK} strokeWidth="0.8" />
          <text x="290" y="24" textAnchor="middle" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" opacity="0.7">/Users/.../hero.png</text>
        </g>
        <VerdictBadge verdict="NG" x={16} y={484} />
      </Panel>

      {/* OK: embed */}
      <Panel x={640} y={80} w={500} h={540} title="EMBEDDED" titleRight="OK">
        <g transform="translate(250,240)">
          <rect x="-120" y="-90" width="240" height="180" fill="#fff" stroke={INK} strokeWidth="1.2" />
          <g transform="translate(-60,-40)">
            <rect x="0" y="0" width="120" height="80" fill="#BBDEFB" stroke="#4A90B8" strokeWidth="0.8" />
            <path d="M 0 60 L 30 30 L 55 50 L 80 25 L 120 60 L 120 80 L 0 80 Z" fill="#4A90B8" />
            <circle cx="90" cy="20" r="8" fill="#FFD54F" />
          </g>
        </g>
        <g transform="translate(60,410)">
          <rect x="0" y="0" width="50" height="36" fill="#6AA84F" />
          <text x="25" y="23" textAnchor="middle" fill="#fff" fontSize="14" fontFamily="JetBrains Mono, monospace">IMG</text>
          <rect x="70" y="0" width="360" height="36" fill={INK} />
          <text x="250" y="24" textAnchor="middle" fill="#fff" fontSize="13" fontFamily="JetBrains Mono, monospace" letterSpacing="1">INSIDE THE FILE</text>
        </g>
        <VerdictBadge verdict="OK" x={16} y={484} />
      </Panel>
    </svg>
  );
}

// ========== 05 DPI ==========
function DiagramDPI({ detail = 2 }) {
  const cells = (size, count) => {
    const arr = [];
    for (let y = 0; y < count; y++) for (let x = 0; x < count; x++) arr.push([x, y]);
    return arr.map(([x, y], i) => (
      <rect key={i} x={x * size} y={y * size} width={size - 0.5} height={size - 0.5}
        fill={`hsl(${(x * 360 / count + y * 30) % 360}, 55%, ${55 + ((x + y) % 3) * 8}%)`} />
    ));
  };
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf5" />
      <rect width={VB_W} height={VB_H} fill="url(#gf5-hard)" />

      <Panel x={60} y={80} w={500} h={540} title="72 dpi" titleRight="WEB">
        <g transform="translate(100,100)">
          <g>{cells(40, 8)}</g>
        </g>
        <VerdictBadge verdict="NG" x={16} y={484} />
        {detail >= 2 && <text x={250} y={500} textAnchor="middle" fill={INK} fontSize="15" fontFamily="var(--font-ja)">粗い・ボケる</text>}
      </Panel>

      <Panel x={640} y={80} w={500} h={540} title="350 dpi" titleRight="PRINT">
        <g transform="translate(100,100)">
          <g>{cells(10, 32)}</g>
        </g>
        <VerdictBadge verdict="OK" x={16} y={484} />
        {detail >= 2 && <text x={250} y={500} textAnchor="middle" fill={INK} fontSize="15" fontFamily="var(--font-ja)">くっきり・細部再現</text>}
      </Panel>

      {detail >= 2 && (
        <g transform="translate(600,640)">
          <text x="0" y="0" textAnchor="middle" fill={INK} fontSize="14" fontFamily="JetBrains Mono, monospace" opacity="0.55">実寸で 350dpi 以上を推奨</text>
        </g>
      )}
    </svg>
  );
}

// ========== 06 Layer structure ==========
function DiagramLayers({ detail = 2 }) {
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf6" />
      <rect width={VB_W} height={VB_H} fill="url(#gf6-hard)" />

      <Panel x={60} y={80} w={440} h={540} title="LAYERS" titleRight="AI">
        {/* Cut layer */}
        <g transform="translate(0,60)">
          <rect x="0" y="0" width="440" height="78" fill={ACCENT} opacity="0.08" />
          <rect x="14" y="22" width="22" height="18" fill="none" stroke={INK} strokeWidth="1" />
          <circle cx="25" cy="31" r="3.5" fill={INK} />
          <rect x="50" y="18" width="28" height="26" fill="#fff" stroke={INK} strokeWidth="0.8" />
          <path d="M 54 28 L 74 28 M 54 34 L 74 34 M 54 40 L 74 40" stroke={ACCENT} strokeWidth="1.5" />
          <rect x="94" y="20" width="20" height="20" fill={ACCENT} />
          <text x="130" y="34" fill={INK} fontSize="18" fontFamily="var(--font-ja)" fontWeight="500">カットレイヤー</text>
          <text x="130" y="54" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" opacity="0.55">cut / K100%</text>
          <line x1="0" y1="78" x2="440" y2="78" stroke={INK} strokeWidth="0.4" opacity="0.3" />
        </g>

        {/* Design layer */}
        <g transform="translate(0,140)">
          <rect x="14" y="22" width="22" height="18" fill="none" stroke={INK} strokeWidth="1" />
          <circle cx="25" cy="31" r="3.5" fill={INK} />
          <rect x="50" y="18" width="28" height="26" fill="#fff" stroke={INK} strokeWidth="0.8" />
          <circle cx="58" cy="27" r="3" fill="#6AA84F" />
          <circle cx="68" cy="34" r="3" fill="#E0B84F" />
          <rect x="94" y="20" width="20" height="20" fill="#3F7CAC" />
          <text x="130" y="34" fill={INK} fontSize="18" fontFamily="var(--font-ja)" fontWeight="500">デザインレイヤー</text>
          <text x="130" y="54" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" opacity="0.55">design / artwork</text>
        </g>

        {detail >= 2 && (
          <text x={220} y={350} textAnchor="middle" fill={INK} fontSize="14" fontFamily="JetBrains Mono, monospace" opacity="0.5">必須：別レイヤーで作成</text>
        )}
      </Panel>

      {/* Arrow */}
      <g transform="translate(540,340)">
        <path d="M 0 10 L 40 10" stroke={INK} strokeWidth="1.5" />
        <polygon points="40,4 54,10 40,16" fill={INK} />
      </g>

      {/* Stack view */}
      <g transform="translate(640,120)">
        <text x="0" y="-10" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" opacity="0.55" letterSpacing="1.5">STACK VIEW</text>
        <g transform="translate(60,0)">
          <rect x="0" y="0" width="400" height="160" fill="#fff" stroke={INK} strokeWidth="1" />
          <StickerShape kind="star" x={120} y={80} size={100} fill={INK} stroke={INK} />
          <StickerShape kind="heart" x={280} y={80} size={95} fill={INK} stroke={INK} />
          <text x={400} y={20} textAnchor="end" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" dx="-10">CUT / K100%</text>
        </g>
        <g transform="translate(0,220)">
          <rect x="0" y="0" width="400" height="160" fill="#fff" stroke={INK} strokeWidth="1" />
          <StickerShape kind="star" x={120} y={80} size={100} fill="#FFD54F" stroke="#C89A2C" strokeWidth="1" />
          <StickerShape kind="heart" x={280} y={80} size={95} fill="#F06292" stroke="#B84673" strokeWidth="1" />
          <text x={400} y={20} textAnchor="end" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" dx="-10">DESIGN</text>
        </g>
        {detail >= 2 && (
          <>
            <path d="M 430 80 L 470 80 L 470 300 L 430 300" fill="none" stroke={INK} strokeWidth="0.8" />
            <text x={482} y={194} fill={INK} fontSize="14" fontFamily="var(--font-ja)">2レイヤー</text>
          </>
        )}
      </g>
    </svg>
  );
}

// ========== 07 K100 cut line ==========
function DiagramK100({ detail = 2 }) {
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf7" />
      <rect width={VB_W} height={VB_H} fill="url(#gf7-hard)" />

      {[
        { x: 80, label: "塗りつぶしのみ", sub: "FILL", mode: "fill" },
        { x: 440, label: "輪郭線のみ", sub: "STROKE", mode: "stroke" },
        { x: 800, label: "両方", sub: "FILL + STROKE", mode: "both" },
      ].map((v, i) => (
        <Panel key={i} x={v.x} y={80} w={320} h={380} title={v.sub}>
          <g transform="translate(160,200)">
            {v.mode === "fill" && <StickerShape kind="star" x={0} y={0} size={180} fill={INK} stroke="none" />}
            {v.mode === "stroke" && <StickerShape kind="star" x={0} y={0} size={180} fill="none" stroke={INK} strokeWidth="3" />}
            {v.mode === "both" && <StickerShape kind="star" x={0} y={0} size={180} fill={INK} stroke={INK} strokeWidth="3" />}
          </g>
          <text x={160} y={80} textAnchor="middle" fill={INK} fontSize="18" fontFamily="var(--font-ja)" fontWeight="500">{v.label}</text>
          <VerdictBadge verdict="OK" x={16} y={332} />
        </Panel>
      ))}

      <g transform="translate(80,500)">
        <rect x="0" y="0" width="1040" height="100" fill="#fff" stroke={INK} strokeWidth="1" />
        <rect x="20" y="20" width="60" height="60" fill={INK} />
        <text x="100" y="40" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" opacity="0.55" letterSpacing="1.5">COLOR SPEC</text>
        <text x="100" y="70" fill={INK} fontSize="22" fontFamily="var(--font-ja)" fontWeight="500">C 0 / M 0 / Y 0 / K 100</text>
        {detail >= 2 && (
          <>
            <line x1="540" y1="24" x2="540" y2="76" stroke={INK} strokeWidth="0.4" opacity="0.3" />
            <text x={560} y={40} fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" opacity="0.55" letterSpacing="1.5">NOTE</text>
            <text x={560} y={70} fill={INK} fontSize="17" fontFamily="var(--font-ja)">RGB / スポットカラーは不可</text>
          </>
        )}
      </g>
    </svg>
  );
}

// ========== 08 Fill area ==========
function DiagramFillArea({ detail = 2 }) {
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf8" />
      <rect width={VB_W} height={VB_H} fill="url(#gf8-hard)" />

      <Panel x={80} y={80} w={480} h={540} title="OK">
        <g transform="translate(240,280)">
          <StickerShape kind="blob" x={0} y={0} size={320} fill={INK} stroke="none" />
        </g>
        <text x={240} y={490} textAnchor="middle" fill={INK} fontSize="17" fontFamily="var(--font-ja)" fontWeight="500">全面 K100% で塗りつぶし</text>
        <VerdictBadge verdict="OK" x={16} y={484} />
      </Panel>

      <Panel x={640} y={80} w={480} h={540} title="NG">
        <g transform="translate(240,280)">
          <StickerShape kind="blob" x={0} y={0} size={320} fill="none" stroke={NG} strokeWidth="2" strokeDasharray="6 4" />
          {detail >= 2 && (
            <text x={0} y={0} textAnchor="middle" fill={NG} fontSize="15" fontFamily="JetBrains Mono, monospace">outline only / no fill</text>
          )}
        </g>
        <text x={240} y={490} textAnchor="middle" fill={INK} fontSize="17" fontFamily="var(--font-ja)" fontWeight="500">輪郭のみ・中抜きは認識不可</text>
        <VerdictBadge verdict="NG" x={16} y={484} />
      </Panel>
    </svg>
  );
}

// ========== 09 Bleed ==========
function DiagramBleed({ detail = 2 }) {
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf9" />
      <rect width={VB_W} height={VB_H} fill="url(#gf9-hard)" />

      {/* OK: bleed extended */}
      <Panel x={60} y={80} w={500} h={540} title="OK — 塗り足しあり">
        <g transform="translate(250,260)">
          {/* background extends past cut */}
          <StickerShape kind="cloud" x={0} y={0} size={340} fill="#4A90B8" stroke="none" />
          {/* cut line */}
          <StickerShape kind="cloud" x={0} y={0} size={300} fill="none" stroke={ACCENT} strokeWidth="2" strokeDasharray="6 4" />
          <text x={0} y={8} textAnchor="middle" fill="#fff" fontSize="22" fontFamily="var(--font-ja)" fontWeight="600">BG</text>
          {/* dim */}
          <Dim x1={140} y1={0} x2={162} y2={0} label="3mm" offset={-100} color={INK} />
        </g>
        <VerdictBadge verdict="OK" x={16} y={484} />
      </Panel>

      {/* NG: no bleed */}
      <Panel x={640} y={80} w={500} h={540} title="NG — 塗り足しなし">
        <g transform="translate(250,260)">
          <StickerShape kind="cloud" x={0} y={0} size={300} fill="#4A90B8" stroke="none" />
          <StickerShape kind="cloud" x={0} y={0} size={300} fill="none" stroke={NG} strokeWidth="2" strokeDasharray="6 4" />
          {/* shifted cut indicating misregistration */}
          <StickerShape kind="cloud" x={10} y={-6} size={300} fill="none" stroke={NG} strokeWidth="1" opacity="0.45" />
          {detail >= 2 && (
            <Leader x={150} y={-40} tx={200} ty={-120} label="白フチ" color={NG} detailed={true} />
          )}
        </g>
        <VerdictBadge verdict="NG" x={16} y={484} />
      </Panel>
    </svg>
  );
}

// ========== 10 The 3mm rule (three distances) ==========
function DiagramThreeRules({ detail = 2 }) {
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf10" />
      <rect width={VB_W} height={VB_H} fill="url(#gf10-hard)" />

      {/* One big sheet showing all three distances */}
      <g transform="translate(150,80)">
        <text x="0" y="-12" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" opacity="0.55" letterSpacing="1.5">SHEET</text>
        <rect x="0" y="0" width="580" height="500" fill="#F3F1EA" stroke={INK} strokeWidth="1.2" />

        {/* Sticker A */}
        <StickerShape kind="star" x={150} y={150} size={130} fill="#FFD54F" stroke="#C89A2C" strokeWidth="1" />
        <StickerShape kind="star" x={150} y={150} size={150} fill="none" stroke={ACCENT} strokeWidth="1.5" strokeDasharray="5 4" />

        {/* Sticker B */}
        <StickerShape kind="heart" x={380} y={150} size={120} fill="#F06292" stroke="#B84673" strokeWidth="1" />
        <StickerShape kind="heart" x={380} y={150} size={140} fill="none" stroke={ACCENT} strokeWidth="1.5" strokeDasharray="5 4" />

        {/* Sticker C (artwork smaller inside cut) */}
        <StickerShape kind="blob" x={280} y={360} size={250} fill="none" stroke={ACCENT} strokeWidth="1.5" strokeDasharray="5 4" />
        <StickerShape kind="blob" x={280} y={360} size={200} fill="#A5D6A7" stroke="#4E8E52" strokeWidth="1" />

        {/* ① cut ↔ cut */}
        <Dim x1={225} y1={150} x2={310} y2={150} label="①3mm" offset={-60} color={INK} />

        {/* ② art ↔ cut */}
        <Dim x1={280} y1={260} x2={280} y2={280} label="②3mm" offset={130} color={INK} />

        {/* ③ edge ↔ cut */}
        <Dim x1={0} y1={150} x2={75} y2={150} label="③3mm" offset={-50} color={INK} />
        <Dim x1={280} y1={500} x2={280} y2={485} label="③3mm" offset={40} color={INK} />
      </g>

      {/* Legend on right */}
      {detail >= 1 && (
        <g transform="translate(820,100)">
          <text x="0" y="0" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" letterSpacing="1.5" opacity="0.55">LEGEND</text>
          {[
            ["①", "カット ↔ カット"],
            ["②", "図柄 ↔ カット"],
            ["③", "用紙端 ↔ カット"],
          ].map(([n, label], i) => (
            <g key={i} transform={`translate(0,${40 + i * 56})`}>
              <circle cx="14" cy="14" r="14" fill={ACCENT} />
              <text x="14" y="19" textAnchor="middle" fill="#fff" fontSize="15" fontFamily="JetBrains Mono, monospace" fontWeight="500">{n}</text>
              <text x="40" y="19" fill={INK} fontSize="16" fontFamily="var(--font-ja)">{label}</text>
              <text x="40" y="38" fill={INK} fontSize="13" fontFamily="JetBrains Mono, monospace" opacity="0.55">≥ 3.0mm</text>
            </g>
          ))}
        </g>
      )}
    </svg>
  );
}

// ========== 11 Angles ==========
function DiagramAngles({ detail = 2 }) {
  return (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} width="100%" preserveAspectRatio="xMidYMid meet">
      <GridBg id="gf11" />
      <rect width={VB_W} height={VB_H} fill="url(#gf11-hard)" />

      <Panel x={60} y={80} w={500} h={540} title="NG — 鋭角">
        <g transform="translate(250,290)">
          {(() => {
            const pts = [];
            const r = 160, ri = 36;
            for (let i = 0; i < 16; i++) {
              const ang = (Math.PI * 2 * i) / 16 - Math.PI / 2;
              const rr = i % 2 === 0 ? r : ri;
              pts.push(`${(Math.cos(ang) * rr).toFixed(1)},${(Math.sin(ang) * rr).toFixed(1)}`);
            }
            return <polygon points={pts.join(" ")} fill="#FFE082" stroke={NG} strokeWidth="2" strokeDasharray="5 4" />;
          })()}
          {detail >= 2 && (
            <>
              <Leader x={0} y={-160} tx={100} ty={-200} label="鋭角" color={NG} detailed={true} />
              <Leader x={36 * Math.cos(Math.PI/8)} y={-36 * Math.sin(Math.PI/8)} tx={180} ty={10} label="狭い谷" color={NG} detailed={true} />
            </>
          )}
        </g>
        <VerdictBadge verdict="NG" x={16} y={484} />
      </Panel>

      <Panel x={640} y={80} w={500} h={540} title="OK — R2mm 以上">
        <g transform="translate(250,290)">
          <StickerShape kind="blob" x={0} y={0} size={340} fill="#A5D6A7" stroke={OK} strokeWidth="2" strokeDasharray="5 4" />
          {detail >= 2 && (
            <>
              <Leader x={-140} y={-40} tx={-200} ty={-130} label="R 2mm 以上" color={OK} anchor="end" detailed={true} />
              <Leader x={130} y={70} tx={190} ty={170} label="曲線でゆとり" color={OK} detailed={true} />
            </>
          )}
        </g>
        <VerdictBadge verdict="OK" x={16} y={484} />
      </Panel>
    </svg>
  );
}

window.Diagrams = {
  DiagramFileFormat,
  DiagramCMYK,
  DiagramOutline,
  DiagramEmbed,
  DiagramDPI,
  DiagramLayers,
  DiagramK100,
  DiagramFillArea,
  DiagramBleed,
  DiagramThreeRules,
  DiagramAngles,
};
