// Walkthrough manifest: blocks used as illustration in service of a narrative.
// No type labels; readers should experience the blocks as part of the prose.

const walkthrough = {
  outputName: 'composed-blocks-walkthrough.single.html',
  title: 'Why single-file HTML is a delivery format, not an authoring format',
  subtitle: 'A walkthrough of the architecture this skill recommends, told through the same blocks the skill provides.',
  eyebrow: 'Walkthrough',
  showBlockLabels: false,
  footer: 'Generated by <code>scripts/build-block-sample.mjs</code> from <code>scripts/manifests/composed-blocks-walkthrough.mjs</code>.',
  patterns: {
    toc: {
      enabled: true,
      depth: 4,
      search: true,
      shortcut: 't',
    },
    'global-search': {
      enabled: true,
      shortcut: '/',
      altShortcut: '\\',
    },
    'keyboard-help': {
      enabled: true,
      entries: [
        { keys: 'T',   label: 'Open / close contents (TOC)' },
        { keys: '↑ ↓', label: 'Navigate TOC entries (in search)' },
        { keys: '→',   label: 'Expand TOC node, or jump to first child' },
        { keys: '←',   label: 'Collapse TOC node, or jump to parent' },
        { keys: '/',   label: 'Search the page' },
        { keys: '?',   label: 'Show this help' },
        { keys: 'Esc', label: 'Close any open overlay' },
      ],
    },
  },
  sections: [
    {
      id: 'opening',
      heading: 'The temptation, and the cost',
      lead: 'Generative models are happy to emit one giant HTML file on request. The result looks impressive in isolation. But the moment you want to <em>change</em> something, the cost of that approach lands.',
      blocks: [
        {
          type: 'tldr',
          data: {
            title: 'Build the site first. Package it second.',
            bodyHtml: '<p>Treating single-file HTML as a delivery format keeps content, styling, and scripts separate during authoring. The packaging step collapses a working site into one file at the end.</p>',
            pointsHtml: [
              'Author in Markdown plus YAML.',
              'Compile to typed JSON before the renderer touches it.',
              'Inline only at packaging time.',
            ],
          },
        },
        {
          type: 'callout',
          data: {
            tone: 'warning',
            title: 'Why this matters',
            bodyHtml: "<p>If your authoring artefact is one giant HTML blob, you can't diff it, restyle it, search across it, or reuse the patterns. Every change becomes a high-stakes find-and-replace.</p>",
          },
        },
      ],
    },

    {
      id: 'shape',
      heading: 'The shape of a working pipeline',
      lead: 'The architecture this skill recommends has four moving parts: source content, a compiler, a normal website, and a packager that runs once at the end.',
      blocks: [
        {
          type: 'module-map',
          data: {
            title: 'Two stages, four boxes',
            columns: [
              { label: 'Authoring' },
              { label: 'Build' },
              { label: 'Runtime' },
            ],
            modules: [
              { id: 'content',  label: 'content/',        column: 0, kind: 'entry',
                summaryHtml: '<p>Markdown + YAML sources, version-controlled, diff-friendly.</p>' },
              { id: 'compiler', label: 'scripts/build*',  column: 1,
                summaryHtml: '<p>Validates and emits typed JSON.</p>' },
              { id: 'blocks',   label: 'scripts/blocks/', column: 1, kind: 'hot-path',
                summaryHtml: '<p>Renderers — vanilla JS, packaging-safe.</p>' },
              { id: 'site',     label: 'src/',            column: 2,
                summaryHtml: '<p>A normal website, runs on a dev server.</p>' },
              { id: 'bundle',   label: 'report.html',     column: 2, kind: 'package',
                summaryHtml: '<p>The single-file deliverable.</p>' },
            ],
            connections: [
              { from: 'content',  to: 'compiler', label: 'read' },
              { from: 'compiler', to: 'site',     label: 'emit JSON' },
              { from: 'blocks',   to: 'site',     label: 'imported' },
              { from: 'site',     to: 'bundle',   label: 'package' },
            ],
          },
        },
        {
          type: 'before-after',
          data: {
            axis: 'horizontal',
            before: {
              label: 'One giant blob',
              bodyHtml: '<p>HTML, CSS, and JS interleaved by hand. No schema. Every change is a manual scan.</p>',
            },
            after: {
              label: 'Two stages',
              bodyHtml: '<p>Author in YAML and Markdown. Compile. The packager produces the deliverable in one final step.</p>',
            },
          },
        },
      ],
    },

    {
      id: 'try',
      heading: 'How big is "single-file" really?',
      lead: 'Inline assets dominate the file size. The biggest cost is Base64 — about a third on top of the raw binary. Try the controls below to feel the relationship.',
      blocks: [
        {
          type: 'slider',
          data: {
            title: 'Base64 inflation, hands-on',
            descriptionHtml: '<p>Move the sliders to see how the packaged file grows as raw asset weight increases.</p>',
            parameters: [
              { name: 'rawMb',   label: 'Raw asset size', min: 1, max: 50, step: 1, default: 12, unit: 'MB' },
              { name: 'extraMb', label: 'Other content',  min: 0, max: 20, step: 1, default: 3,  unit: 'MB' },
            ],
            outputs: [
              { label: 'Encoded size',   compute: 'rawMb * 1.33 + extraMb', format: 'number', decimals: 1, unit: 'MB' },
              { label: 'Inflation cost', compute: 'rawMb * 0.33',            format: 'number', decimals: 1, unit: 'MB' },
              { label: 'Files in 30 MB budget', compute: 'Math.floor(30 / (rawMb * 1.33 + extraMb))', format: 'integer' },
            ],
          },
        },
        {
          type: 'callout',
          data: {
            tone: 'info',
            title: 'When inline starts to bite',
            bodyHtml: '<p>Beyond about 30 MB the file becomes uncomfortable to email. Past that, the Blob-backed payload mode keeps assets inline as data records and materialises them on demand.</p>',
          },
        },
      ],
    },

    {
      id: 'install',
      heading: 'Bootstrapping a project',
      lead: 'A new project is two dependencies plus the single-file packager. Choose the package manager that matches your team.',
      blocks: [
        {
          type: 'tabbed-code',
          data: {
            title: 'Install commands',
            default: 0,
            tabs: [
              { label: 'npm',  language: 'bash', source: 'npm install gray-matter fast-glob\nnpm install -D vite-plugin-singlefile' },
              { label: 'pnpm', language: 'bash', source: 'pnpm add gray-matter fast-glob\npnpm add -D vite-plugin-singlefile' },
              { label: 'bun',  language: 'bash', source: 'bun add gray-matter fast-glob\nbun add -d vite-plugin-singlefile' },
            ],
          },
        },
      ],
    },

    {
      id: 'incident',
      heading: 'A worked example: tracing an incident in one HTML file',
      lead: 'A small incident report fits comfortably as one of these deliverables. Timeline plus annotated diff plus follow-up actions.',
      blocks: [
        {
          type: 'timeline',
          data: {
            title: 'auth-svc validator failure · 2026-04-12',
            events: [
              {
                date: '08:42',
                title: 'First failed login spike',
                bodyHtml: '<p>Grafana fires <code>auth-svc-error-rate-warn</code>.</p>',
                status: 'warning',
                tag: 'P2',
              },
              {
                date: '08:55',
                title: 'Root cause identified',
                bodyHtml: '<p>Token validator pinned to a removed JWKS endpoint after the rotation at 08:30.</p>',
                status: 'danger',
              },
              {
                date: '09:14',
                title: 'Mitigated',
                bodyHtml: '<p>Validator v2.18 rolled forward; error rate normal within five minutes.</p>',
                status: 'success',
                followUps: [
                  'Re-check JWKS rotation runbook',
                  'Add canary on validator config drift',
                ],
              },
            ],
          },
        },
        {
          type: 'severity-tag',
          data: {
            title: 'Severity vocabulary',
            layout: 'list',
            tags: [
              { name: 'P0', tone: 'danger',
                descriptionHtml: '<p>Customer impact, no workaround. Drop everything.</p>' },
              { name: 'P1', tone: 'warning',
                descriptionHtml: '<p>Customer impact with workaround.</p>' },
              { name: 'P2', tone: 'info',
                descriptionHtml: '<p>Internal warning thresholds tripped.</p>' },
            ],
          },
        },
        {
          type: 'annotated-diff',
          data: {
            title: 'The fix',
            path: 'src/auth/validator.ts',
            language: 'typescript',
            lines: [
              { kind: 'context', oldNumber: 12, newNumber: 12, content: 'export async function validate(token: string) {' },
              { kind: 'remove',  oldNumber: 13,                 content: '  const jwks = await fetch(JWKS_URL).then((r) => r.json());' },
              { kind: 'add',                    newNumber: 13,  content: '  const jwks = await getJwks();  // cached, rotation-aware' },
              { kind: 'context', oldNumber: 14, newNumber: 14, content: '  return verify(token, jwks);' },
              { kind: 'context', oldNumber: 15, newNumber: 15, content: '}' },
            ],
            notes: [
              {
                onLines: [2, 3],
                severity: 'P1',
                bodyHtml: '<p>The previous version refetched the JWKS on every request and ignored rotation events. The new helper caches by issuer and rebuilds on rotation.</p>',
              },
            ],
            jumpLinks: [
              { label: 'Top of fix', atLine: 2 },
            ],
          },
        },
      ],
    },

    {
      id: 'closing',
      heading: 'What to take from this',
      lead: 'A finished single-file HTML deliverable should feel like a designed product. The way you get there is by treating it as the last step in a normal website pipeline, not as the authoring artefact.',
      blocks: [
        {
          type: 'faq',
          data: {
            title: 'Likely questions',
            defaultOpen: 'first',
            items: [
              {
                question: 'Can I really fit a rich report in one file?',
                answerHtml: '<p>For most narrative reports, yes. The 30 MB rule of thumb holds. For media-heavy reports, use the Blob-backed payload mode.</p>',
              },
              {
                question: 'Does this break offline use?',
                answerHtml: '<p>No, that&rsquo;s the whole point. The packager removes external fonts, CDN scripts, and root-absolute URLs. The audit script flags anything left behind.</p>',
              },
              {
                question: 'What about React components?',
                answerHtml: '<p>The site itself can use React. The block layer is intentionally vanilla so renderers work identically in static and React hosts and inline cleanly during packaging.</p>',
              },
            ],
          },
        },
        {
          type: 'glossary',
          data: {
            title: 'Two terms worth keeping',
            layout: 'two-column',
            terms: [
              {
                term: 'Single-file HTML',
                definitionHtml: '<p>One <code>.html</code> file that opens in a modern browser from disk, with everything it needs inlined.</p>',
              },
              {
                term: 'Block',
                definitionHtml: '<p>Typed structured content with a colocated renderer; the unit of reuse in this skill.</p>',
              },
            ],
          },
        },
      ],
    },
  ],
};

export default walkthrough;
