/**
 * Build a showcase HTML page from a DESIGN.md so the user can see what each
 * design system looks like *before* generating anything. We don't try to
 * render a unique product mockup — we extract the palette, typography, and
 * a couple of component conventions, then drop them into one fixed
 * template. The full DESIGN.md is rendered below as prose for reference.
 *
 * Parsing is deliberately permissive: imported systems vary in section
 * naming and bullet style, so we use loose regexes and fall back to sane
 * defaults when a token isn't found.
 */
export function renderDesignSystemPreview(id, raw) {
    const titleMatch = /^#\s+(.+?)\s*$/m.exec(raw);
    const title = cleanTitle(titleMatch?.[1] ?? id);
    const subtitle = extractSubtitle(raw);
    const colors = extractColors(raw);
    const fonts = extractFonts(raw);
    const bg = pickColor(colors, ['page background', 'background', 'canvas', 'paper', 'bg ', 'page bg'])
        ?? pickColor(colors, ['white'])
        ?? '#ffffff';
    const fg = pickColor(colors, ['heading', 'foreground', 'ink', 'fg', 'text', 'navy', 'graphite'])
        ?? '#111111';
    // Accent: brand/primary names first, then fall back to the first color
    // that doesn't look like a neutral white/black/grey so we always show
    // something punchy in the showcase header.
    const accent = pickColor(colors, ['primary brand', 'brand primary', 'primary', 'brand', 'accent'])
        ?? firstNonNeutral(colors)
        ?? '#2f6feb';
    const muted = pickColor(colors, ['muted', 'secondary', 'neutral', 'subtle', 'caption']) ?? '#777777';
    const border = pickColor(colors, ['border', 'divider', 'rule', 'stroke']) ?? '#e5e5e5';
    const surface = pickColor(colors, ['surface', 'card', 'background-secondary', 'panel', 'elevated'])
        ?? '#ffffff';
    const display = fonts.display
        ?? fonts.heading
        ?? "system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif";
    const body = fonts.body ?? display;
    const mono = fonts.mono ?? "ui-monospace, 'JetBrains Mono', monospace";
    const renderedMarkdown = renderMarkdownLite(raw);
    return `<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>${escapeHtml(title)} — design system preview</title>
  <style>
    :root {
      --bg: ${bg};
      --fg: ${fg};
      --accent: ${accent};
      --muted: ${muted};
      --border: ${border};
      --surface: ${surface};
      --display: ${display};
      --body: ${body};
      --mono: ${mono};
    }
    * { box-sizing: border-box; }
    body {
      margin: 0;
      background: var(--bg);
      color: var(--fg);
      font-family: var(--body);
      line-height: 1.55;
      font-size: 16px;
    }
    .wrap { max-width: 960px; margin: 0 auto; padding: 56px 32px 96px; }
    .badge {
      display: inline-block;
      font-family: var(--mono);
      font-size: 11px;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      padding: 4px 10px;
      border-radius: 999px;
      background: var(--surface);
      border: 1px solid var(--border);
      color: var(--muted);
      margin-bottom: 24px;
    }
    h1 {
      font-family: var(--display);
      font-size: clamp(40px, 6vw, 72px);
      line-height: 1.05;
      letter-spacing: -0.02em;
      margin: 0 0 16px;
    }
    .lede {
      max-width: 60ch;
      font-size: 18px;
      color: var(--muted);
      margin: 0 0 56px;
    }
    section { margin-bottom: 72px; }
    .section-title {
      font-family: var(--display);
      font-size: 22px;
      font-weight: 600;
      margin: 0 0 16px;
      letter-spacing: -0.01em;
    }
    .palette {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
      gap: 16px;
    }
    .swatch {
      border: 1px solid var(--border);
      border-radius: 12px;
      overflow: hidden;
      background: var(--surface);
    }
    .swatch .chip {
      height: 96px;
    }
    .swatch .meta {
      padding: 10px 12px 12px;
      display: flex;
      flex-direction: column;
      gap: 2px;
    }
    .swatch .name { font-size: 13px; font-weight: 500; }
    .swatch .hex { font-family: var(--mono); font-size: 11px; color: var(--muted); }
    .typo-row {
      display: grid;
      grid-template-columns: 88px 1fr;
      gap: 24px;
      padding: 18px 0;
      border-top: 1px solid var(--border);
    }
    .typo-row:first-child { border-top: none; padding-top: 0; }
    .typo-row .label {
      font-family: var(--mono);
      font-size: 11px;
      text-transform: uppercase;
      letter-spacing: 0.06em;
      color: var(--muted);
      padding-top: 4px;
    }
    .typo-display { font-family: var(--display); font-size: 40px; line-height: 1.1; letter-spacing: -0.02em; }
    .typo-body { font-family: var(--body); font-size: 16px; }
    .typo-mono { font-family: var(--mono); font-size: 14px; color: var(--muted); }
    .components {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 24px;
    }
    @media (max-width: 640px) { .components { grid-template-columns: 1fr; } }
    .card {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 12px;
      padding: 24px;
    }
    .card .eyebrow {
      font-family: var(--mono);
      font-size: 11px;
      text-transform: uppercase;
      letter-spacing: 0.06em;
      color: var(--accent);
      margin-bottom: 8px;
    }
    .card h3 {
      font-family: var(--display);
      font-size: 20px;
      margin: 0 0 8px;
      letter-spacing: -0.01em;
    }
    .card p { margin: 0; color: var(--muted); }
    .btn-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
    button {
      font: inherit;
      cursor: pointer;
      border-radius: 8px;
      padding: 10px 18px;
    }
    .btn-primary {
      background: var(--accent);
      color: ${pickReadableForeground(accent)};
      border: 1px solid var(--accent);
    }
    .btn-secondary {
      background: transparent;
      color: var(--fg);
      border: 1px solid var(--border);
    }
    .btn-link {
      background: transparent;
      border: none;
      color: var(--accent);
      padding: 10px 0;
      font-weight: 500;
    }
    .prose {
      border-top: 1px solid var(--border);
      padding-top: 32px;
      color: var(--fg);
    }
    .prose h1, .prose h2, .prose h3 { font-family: var(--display); letter-spacing: -0.01em; }
    .prose h1 { font-size: 28px; margin-top: 0; }
    .prose h2 { font-size: 20px; margin-top: 32px; }
    .prose h3 { font-size: 16px; margin-top: 24px; }
    .prose p, .prose ul, .prose ol { margin: 12px 0; }
    .prose code { font-family: var(--mono); background: var(--surface); border: 1px solid var(--border); padding: 1px 5px; border-radius: 4px; font-size: 0.92em; }
    .prose blockquote { margin: 16px 0; padding: 8px 16px; border-left: 3px solid var(--accent); color: var(--muted); }
    .prose ul, .prose ol { padding-left: 22px; }
    .prose pre { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 12px 14px; overflow: auto; font-family: var(--mono); font-size: 12.5px; line-height: 1.55; }
    .prose pre code { background: transparent; border: none; padding: 0; font-size: inherit; }
    .prose hr { border: none; border-top: 1px solid var(--border); margin: 28px 0; }
    .prose a { color: var(--accent); text-decoration: none; border-bottom: 1px solid transparent; }
    .prose a:hover { border-bottom-color: var(--accent); }
    .prose img { max-width: 100%; height: auto; border-radius: 6px; }
    .prose .table-wrap { overflow-x: auto; margin: 18px 0; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); }
    .prose table { width: 100%; border-collapse: collapse; font-size: 13.5px; line-height: 1.5; }
    .prose th, .prose td { padding: 9px 14px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--border); }
    .prose th { background: var(--bg); font-weight: 600; font-size: 12px; letter-spacing: 0.02em; text-transform: uppercase; color: var(--muted); }
    .prose tr:last-child td { border-bottom: none; }
    .prose td code, .prose th code { white-space: nowrap; }
    .prose td[align="right"], .prose th[align="right"] { text-align: right; }
    .prose td[align="center"], .prose th[align="center"] { text-align: center; }
  </style>
</head>
<body>
  <main class="wrap">
    <span class="badge">Design system preview · ${escapeHtml(id)}</span>
    <h1>${escapeHtml(title)}</h1>
    ${subtitle ? `<p class="lede">${escapeHtml(subtitle)}</p>` : ''}

    <section>
      <h2 class="section-title">Palette</h2>
      <div class="palette">
        ${colors
        .slice(0, 12)
        .map((c) => `<div class="swatch">
              <div class="chip" style="background:${c.value};"></div>
              <div class="meta">
                <span class="name">${escapeHtml(c.name)}</span>
                <span class="hex">${escapeHtml(c.value)}</span>
              </div>
            </div>`)
        .join('')}
      </div>
    </section>

    <section>
      <h2 class="section-title">Typography</h2>
      <div class="typo-row">
        <span class="label">Display</span>
        <div class="typo-display">The grid carries weight; the line carries pace.</div>
      </div>
      <div class="typo-row">
        <span class="label">Body</span>
        <div class="typo-body">Body copy reads at sixteen pixels with a 1.55 leading. Restraint and rhythm matter more than novelty — pick a stack that earns the page.</div>
      </div>
      <div class="typo-row">
        <span class="label">Mono</span>
        <div class="typo-mono">/* monospace · ${escapeHtml(mono.split(',')[0]?.replace(/['"]/g, '').trim() ?? 'mono')} */</div>
      </div>
    </section>

    <section>
      <h2 class="section-title">Components</h2>
      <div class="components">
        <div class="card">
          <div class="eyebrow">Card</div>
          <h3>Production-quality artifact</h3>
          <p>Sample card showing how surfaces, borders, and accent text behave in this system.</p>
        </div>
        <div class="card">
          <div class="eyebrow">Buttons</div>
          <h3>Three weights, one accent</h3>
          <div class="btn-row" style="margin-top: 12px;">
            <button class="btn-primary">Primary</button>
            <button class="btn-secondary">Secondary</button>
            <button class="btn-link">Link →</button>
          </div>
        </div>
      </div>
    </section>

    <section class="prose">
      ${renderedMarkdown}
    </section>
  </main>
</body>
</html>`;
}
function extractSubtitle(raw) {
    const lines = raw.split(/\r?\n/);
    const h1 = lines.findIndex((l) => /^#\s+/.test(l));
    if (h1 === -1)
        return '';
    const after = lines.slice(h1 + 1);
    const nextHeading = after.findIndex((l) => /^#{1,6}\s+/.test(l));
    const window = (nextHeading === -1 ? after : after.slice(0, nextHeading))
        .join('\n')
        .replace(/^>\s*Category:.*$/gim, '')
        .replace(/^>\s*/gm, '')
        .trim();
    return window.split(/\n\n/)[0]?.slice(0, 240) ?? '';
}
function extractColors(raw) {
    const colors = [];
    const seen = new Set();
    function push(name, value) {
        const cleanName = name.replace(/[*_`]+/g, '').replace(/\s+/g, ' ').trim();
        if (!cleanName || cleanName.length > 60)
            return;
        const v = normalizeHex(value);
        const key = `${cleanName.toLowerCase()}|${v}`;
        if (seen.has(key))
            return;
        seen.add(key);
        colors.push({ name: cleanName, value: v });
    }
    // Form A: "- **Background:** `#FAFAFA`" / "- Background: #FAFAFA"
    const reA = /^[\s>*-]*\**\s*([A-Za-z][A-Za-z0-9 /&()+_-]{1,40}?)\s*\**\s*[:：]\s*`?(#[0-9a-fA-F]{3,8})/gm;
    let m;
    while ((m = reA.exec(raw)) !== null)
        push(m[1] ?? '', m[2] ?? '');
    // Form B: "**Stripe Purple** (`#533afd`)" — common in awesome-design-md.
    // Token name is whatever's bolded; the hex follows in parens/backticks.
    const reB = /\*\*([A-Za-z][A-Za-z0-9 /&()+_-]{1,40}?)\*\*\s*\(?\s*`?(#[0-9a-fA-F]{3,8})/g;
    while ((m = reB.exec(raw)) !== null)
        push(m[1] ?? '', m[2] ?? '');
    return colors;
}
function extractFonts(raw) {
    const out = {};
    // "- **Display / headings:** `'GT Sectra', ...`"
    // We want the backticked stack OR the rest of the line.
    const re = /^[\s>*-]*\**\s*([A-Za-z][A-Za-z /]{1,30}?)\s*\**\s*[:：]\s*`?([^`\n]+?)`?$/gm;
    let m;
    while ((m = re.exec(raw)) !== null) {
        const label = (m[1] ?? '').toLowerCase();
        const value = (m[2] ?? '').trim().replace(/[*_`]+$/g, '').trim();
        if (!/[a-zA-Z]/.test(value))
            continue;
        if (value.startsWith('#'))
            continue;
        if (/display|heading|h1|title/.test(label) && !out.display)
            out.display = value;
        else if (/body|text|paragraph|copy/.test(label) && !out.body)
            out.body = value;
        else if (/mono|code/.test(label) && !out.mono)
            out.mono = value;
    }
    return out;
}
function pickColor(colors, hints) {
    for (const hint of hints) {
        const needle = hint.toLowerCase();
        const found = colors.find((c) => c.name.toLowerCase().includes(needle));
        if (found)
            return found.value;
    }
    return null;
}
function firstNonNeutral(colors) {
    for (const c of colors) {
        const v = c.value.replace('#', '').toLowerCase();
        if (v.length !== 6)
            continue;
        const r = parseInt(v.slice(0, 2), 16);
        const g = parseInt(v.slice(2, 4), 16);
        const b = parseInt(v.slice(4, 6), 16);
        const max = Math.max(r, g, b);
        const min = Math.min(r, g, b);
        const sat = max === 0 ? 0 : (max - min) / max;
        if (sat > 0.25)
            return c.value;
    }
    return null;
}
function pickReadableForeground(hex) {
    const n = normalizeHex(hex);
    if (n.length !== 7)
        return '#ffffff';
    const r = parseInt(n.slice(1, 3), 16);
    const g = parseInt(n.slice(3, 5), 16);
    const b = parseInt(n.slice(5, 7), 16);
    // Standard luminance check.
    const lum = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
    return lum > 0.6 ? '#0a0a0a' : '#ffffff';
}
function normalizeHex(hex) {
    let h = hex.toLowerCase();
    if (h.length === 4) {
        h = '#' + h.slice(1).split('').map((c) => c + c).join('');
    }
    return h;
}
function cleanTitle(raw) {
    return String(raw).replace(/^Design System (Inspired by|for)\s+/i, '').trim();
}
function escapeHtml(s) {
    return String(s).replace(/[&<>"']/g, (c) => c === '&' ? '&amp;' : c === '<' ? '&lt;' : c === '>' ? '&gt;' : c === '"' ? '&quot;' : '&#39;');
}
// Tiny markdown renderer — enough for our DESIGN.md prose: H1–H4, paragraphs,
// bullet/ordered lists, blockquotes, fenced code, GFM pipe tables, horizontal
// rules, inline `code` / **bold** / *italic* / [link](url). Not a full markdown
// implementation but covers everything the DESIGN.md files actually use.
function renderMarkdownLite(src) {
    const lines = src.split(/\r?\n/);
    const out = [];
    let inList = null;
    let inBlockquote = false;
    let inCode = false;
    let i = 0;
    function closeList() {
        if (inList) {
            out.push(`</${inList}>`);
            inList = null;
        }
    }
    function closeBlockquote() {
        if (inBlockquote) {
            out.push('</blockquote>');
            inBlockquote = false;
        }
    }
    while (i < lines.length) {
        const raw = lines[i] ?? '';
        const line = raw.trimEnd();
        if (line.startsWith('```')) {
            closeList();
            closeBlockquote();
            if (!inCode) {
                out.push('<pre><code>');
                inCode = true;
            }
            else {
                out.push('</code></pre>');
                inCode = false;
            }
            i++;
            continue;
        }
        if (inCode) {
            out.push(escapeHtml(raw));
            i++;
            continue;
        }
        if (!line.trim()) {
            closeList();
            closeBlockquote();
            i++;
            continue;
        }
        // GFM pipe table — at least a header row, a separator row of dashes,
        // and one body row. Look ahead from `i` so we can consume the whole
        // block in one step.
        if (looksLikeTableHeader(line) && i + 1 < lines.length && isTableSeparator(lines[i + 1] ?? '')) {
            closeList();
            closeBlockquote();
            const headerCells = splitTableRow(line);
            const aligns = parseAlignments(lines[i + 1] ?? '', headerCells.length);
            const bodyRows = [];
            let j = i + 2;
            while (j < lines.length) {
                const next = (lines[j] ?? '').trimEnd();
                if (!next.trim() || !next.includes('|'))
                    break;
                bodyRows.push(splitTableRow(next));
                j++;
            }
            out.push(renderTable(headerCells, bodyRows, aligns));
            i = j;
            continue;
        }
        // ATX headings #..####
        const h = /^(#{1,4})\s+(.+)$/.exec(line);
        if (h) {
            closeList();
            closeBlockquote();
            const level = h[1]?.length ?? 1;
            out.push(`<h${level}>${inline(h[2] ?? '')}</h${level}>`);
            i++;
            continue;
        }
        // Horizontal rule.
        if (/^([-*_])\1{2,}\s*$/.test(line)) {
            closeList();
            closeBlockquote();
            out.push('<hr />');
            i++;
            continue;
        }
        const bq = /^>\s?(.*)$/.exec(line);
        if (bq) {
            closeList();
            if (!inBlockquote) {
                out.push('<blockquote>');
                inBlockquote = true;
            }
            out.push(`<p>${inline(bq[1] || '')}</p>`);
            i++;
            continue;
        }
        closeBlockquote();
        const li = /^([-*])\s+(.+)$/.exec(line);
        if (li) {
            if (inList !== 'ul') {
                closeList();
                out.push('<ul>');
                inList = 'ul';
            }
            out.push(`<li>${inline(li[2] ?? '')}</li>`);
            i++;
            continue;
        }
        const oli = /^\d+\.\s+(.+)$/.exec(line);
        if (oli) {
            if (inList !== 'ol') {
                closeList();
                out.push('<ol>');
                inList = 'ol';
            }
            out.push(`<li>${inline(oli[1] ?? '')}</li>`);
            i++;
            continue;
        }
        closeList();
        out.push(`<p>${inline(line)}</p>`);
        i++;
    }
    closeList();
    closeBlockquote();
    if (inCode)
        out.push('</code></pre>');
    return out.join('\n');
}
function looksLikeTableHeader(line) {
    const trimmed = line.trim();
    if (!trimmed.includes('|'))
        return false;
    // At least one pipe between non-pipe content.
    return /\|/.test(trimmed.replace(/^\||\|$/g, ''));
}
function isTableSeparator(line) {
    const trimmed = line.trim();
    if (!trimmed.includes('|'))
        return false;
    // Each cell must be only dashes / colons / whitespace.
    return splitTableRow(trimmed).every((cell) => /^:?-{1,}:?$/.test(cell.trim()));
}
function splitTableRow(line) {
    let s = line.trim();
    if (s.startsWith('|'))
        s = s.slice(1);
    if (s.endsWith('|'))
        s = s.slice(0, -1);
    return s.split('|').map((c) => c.trim());
}
function parseAlignments(separatorLine, count) {
    const cells = splitTableRow(separatorLine);
    const aligns = [];
    for (let k = 0; k < count; k++) {
        const cell = (cells[k] ?? '').trim();
        const left = cell.startsWith(':');
        const right = cell.endsWith(':');
        if (left && right)
            aligns.push('center');
        else if (right)
            aligns.push('right');
        else
            aligns.push(null);
    }
    return aligns;
}
function renderTable(header, rows, aligns) {
    const th = header
        .map((cell, k) => {
        const align = aligns[k];
        const attr = align ? ` align="${align}"` : '';
        return `<th${attr}>${inline(cell)}</th>`;
    })
        .join('');
    const body = rows
        .map((row) => {
        const tds = row
            .map((cell, k) => {
            const align = aligns[k];
            const attr = align ? ` align="${align}"` : '';
            return `<td${attr}>${inline(cell)}</td>`;
        })
            .join('');
        return `<tr>${tds}</tr>`;
    })
        .join('');
    return `<div class="table-wrap"><table><thead><tr>${th}</tr></thead><tbody>${body}</tbody></table></div>`;
}
function inline(s) {
    // Process inline tokens. Order matters: code spans first so their content
    // isn't further parsed; then bold/italic; then links; finally bare URLs.
    const escaped = escapeHtml(s);
    return escaped
        .replace(/`([^`]+)`/g, '<code>$1</code>')
        .replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
        .replace(/(^|[^*])\*([^*\n]+)\*(?!\*)/g, '$1<em>$2</em>')
        .replace(/(^|[\s(])_([^_\n]+)_(?=[\s).,;:!?]|$)/g, '$1<em>$2</em>')
        .replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g, '<a href="$2" target="_blank" rel="noreferrer noopener">$1</a>');
}
//# sourceMappingURL=design-system-preview.js.map