<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Advanced Grid Generator</title>
  <style>
    * {
      box-sizing: border-box;
    }
    body {
      margin: 0;
      padding: 0;
      font-family: sans-serif;
      background-color: #f3f3f3;
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    header {
      text-align: center;
      margin-top: 20px;
    }
    h1 {
      margin-bottom: 5px;
    }
    .controls {
      background: #fff;
      padding: 15px;
      margin: 15px;
      border-radius: 8px;
      box-shadow: 0 2px 5px rgba(0,0,0,0.2);
      display: flex;
      flex-wrap: wrap;
      gap: 20px;
      max-width: 1200px;
      justify-content: space-between;
    }
    .controls label {
      font-size: 14px;
      display: flex;
      flex-direction: column;
      gap: 4px;
    }
    .controls input[type="number"] {
      width: 80px;
      padding: 4px;
    }
    .controls input[type="checkbox"] {
      transform: scale(1.2);
      margin-right: 6px;
    }
    .controls button {
      padding: 8px 16px;
      font-size: 14px;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      background: #0077cc;
      color: #fff;
      align-self: end;
      margin-top: auto;
    }
    .controls button:hover {
      background: #005b9e;
    }

    .preview-container {
      background: #ffffff;
      border: 2px solid #cccccc;
      border-radius: 4px;
      padding: 10px;
      margin-bottom: 20px;
    }
    #gridCanvas {
      display: block;
      background: #ffffff;
    }

    /* Simple responsive arrangement */
    @media (max-width: 768px) {
      .controls {
        flex-direction: column;
        align-items: flex-start;
      }
    }
  </style>
</head>
<body>

  <header>
    <h1>Advanced Grid Generator</h1>
    <p>Generate precise column, row, and baseline grids for design projects.</p>
  </header>

  <!-- CONTROLS PANEL -->
  <form class="controls" onsubmit="event.preventDefault(); drawGrid();">
    <!-- Page Dimensions -->
    <div>
      <label>
        Page Width (px)
        <input type="number" id="pageWidth" value="800" min="100" />
      </label>
      <label>
        Page Height (px)
        <input type="number" id="pageHeight" value="600" min="100" />
      </label>
    </div>

    <!-- Margins -->
    <div>
      <label>
        Margin Top (px)
        <input type="number" id="marginTop" value="40" min="0" />
      </label>
      <label>
        Margin Right (px)
        <input type="number" id="marginRight" value="40" min="0" />
      </label>
      <label>
        Margin Bottom (px)
        <input type="number" id="marginBottom" value="40" min="0" />
      </label>
      <label>
        Margin Left (px)
        <input type="number" id="marginLeft" value="40" min="0" />
      </label>
    </div>

    <!-- Columns -->
    <div>
      <label>
        Number of Columns
        <input type="number" id="columns" value="6" min="1" />
      </label>
      <label>
        Column Gutter (px)
        <input type="number" id="columnGutter" value="20" min="0" />
      </label>
      <label style="display: flex; align-items: center;">
        <input type="checkbox" id="showColumns" checked />
        Show Columns
      </label>
    </div>

    <!-- Rows / Baseline -->
    <div>
      <label>
        Number of Rows (optional)
        <input type="number" id="rows" value="0" min="0" />
        <small style="font-size:11px; color:#555;">Set 0 to skip row count</small>
      </label>
      <label>
        Row Gutter (px)
        <input type="number" id="rowGutter" value="20" min="0" />
      </label>
      <label style="display: flex; align-items: center;">
        <input type="checkbox" id="showRows" checked />
        Show Rows
      </label>
    </div>

    <!-- Baseline Grid -->
    <div>
      <label>
        Baseline Spacing (px)
        <input type="number" id="baselineSpacing" value="0" min="0" />
        <small style="font-size:11px; color:#555;">Set 0 to skip baseline</small>
      </label>
      <label style="display: flex; align-items: center;">
        <input type="checkbox" id="showBaseline" />
        Show Baseline
      </label>
    </div>

    <!-- Generate / Export -->
    <div style="display: flex; flex-direction: column; gap: 8px;">
      <button type="submit" title="Generate the grid">Generate Grid</button>
      <button type="button" onclick="exportPNG()" title="Export as PNG">Export PNG</button>
      <button type="button" onclick="exportSVG()" title="Export as SVG">Export SVG</button>
    </div>
  </form>

  <!-- PREVIEW AREA -->
  <div class="preview-container">
    <canvas id="gridCanvas"></canvas>
  </div>

  <script>
    const canvas = document.getElementById('gridCanvas');
    const ctx = canvas.getContext('2d');

    function drawGrid() {
      // Gather inputs
      const pageWidth = parseFloat(document.getElementById('pageWidth').value) || 800;
      const pageHeight = parseFloat(document.getElementById('pageHeight').value) || 600;
      const marginTop = parseFloat(document.getElementById('marginTop').value) || 0;
      const marginRight = parseFloat(document.getElementById('marginRight').value) || 0;
      const marginBottom = parseFloat(document.getElementById('marginBottom').value) || 0;
      const marginLeft = parseFloat(document.getElementById('marginLeft').value) || 0;

      const columns = parseInt(document.getElementById('columns').value) || 1;
      const columnGutter = parseFloat(document.getElementById('columnGutter').value) || 0;
      const showColumns = document.getElementById('showColumns').checked;

      const rows = parseInt(document.getElementById('rows').value) || 0; 
      const rowGutter = parseFloat(document.getElementById('rowGutter').value) || 0;
      const showRows = document.getElementById('showRows').checked;

      const baselineSpacing = parseFloat(document.getElementById('baselineSpacing').value) || 0;
      const showBaseline = document.getElementById('showBaseline').checked;

      // Update canvas size
      canvas.width = pageWidth;
      canvas.height = pageHeight;

      // Clear the canvas
      ctx.clearRect(0, 0, pageWidth, pageHeight);

      // Draw page background
      ctx.fillStyle = '#ffffff';
      ctx.fillRect(0, 0, pageWidth, pageHeight);

      // Workable area
      const workableWidth = pageWidth - marginLeft - marginRight;
      const workableHeight = pageHeight - marginTop - marginBottom;

      // Outline the margin area
      ctx.strokeStyle = '#999999';
      ctx.lineWidth = 1;
      ctx.strokeRect(marginLeft, marginTop, workableWidth, workableHeight);

      // --- Draw Columns ---
      if (showColumns && columns > 0) {
        // total gutter space = (columns - 1) * columnGutter
        // single column width = (workableWidth - total gutter space) / columns
        const totalColumnGutters = (columns - 1) * columnGutter;
        const columnWidth = (workableWidth - totalColumnGutters) / columns;

        for (let i = 0; i < columns; i++) {
          const x = marginLeft + i * (columnWidth + columnGutter);
          // Fill each column with a subtle color
          ctx.fillStyle = 'rgba(255, 0, 0, 0.1)'; 
          ctx.fillRect(x, marginTop, columnWidth, workableHeight);

          // Draw the column boundary lines
          ctx.strokeStyle = 'rgba(255, 0, 0, 0.3)';
          ctx.lineWidth = 1;
          ctx.beginPath();
          ctx.moveTo(x, marginTop);
          ctx.lineTo(x, marginTop + workableHeight);
          ctx.stroke();
          ctx.beginPath();
          ctx.moveTo(x + columnWidth, marginTop);
          ctx.lineTo(x + columnWidth, marginTop + workableHeight);
          ctx.stroke();
        }
      }

      // --- Draw Rows ---
      if (showRows && rows > 0) {
        // total row gutter space = (rows - 1) * rowGutter
        // single row height = (workableHeight - total row gutter) / rows
        const totalRowGutters = (rows - 1) * rowGutter;
        const rowHeight = (workableHeight - totalRowGutters) / rows;

        for (let j = 0; j < rows; j++) {
          const y = marginTop + j * (rowHeight + rowGutter);
          // Fill each row with a subtle color
          ctx.fillStyle = 'rgba(0, 128, 255, 0.07)';
          ctx.fillRect(marginLeft, y, workableWidth, rowHeight);

          // Draw the row boundary lines
          ctx.strokeStyle = 'rgba(0, 128, 255, 0.3)';
          ctx.lineWidth = 1;
          ctx.beginPath();
          ctx.moveTo(marginLeft, y);
          ctx.lineTo(marginLeft + workableWidth, y);
          ctx.stroke();
          ctx.beginPath();
          ctx.moveTo(marginLeft, y + rowHeight);
          ctx.lineTo(marginLeft + workableWidth, y + rowHeight);
          ctx.stroke();
        }
      }

      // --- Draw Baseline ---
      if (showBaseline && baselineSpacing > 0) {
        ctx.strokeStyle = 'rgba(0, 0, 0, 0.15)';
        ctx.lineWidth = 1;
        let baselineY = marginTop;

        while (baselineY <= marginTop + workableHeight) {
          ctx.beginPath();
          ctx.moveTo(marginLeft, baselineY);
          ctx.lineTo(marginLeft + workableWidth, baselineY);
          ctx.stroke();

          baselineY += baselineSpacing;
        }
      }
    }

    // Function to export the canvas as a PNG
    function exportPNG() {
      const dataURL = canvas.toDataURL('image/png');
      const link = document.createElement('a');
      link.href = dataURL;
      link.download = 'grid.png';
      link.click();
    }

    // Function to export the grid as SVG
    function exportSVG() {
      const pageWidth = parseFloat(document.getElementById('pageWidth').value) || 800;
      const pageHeight = parseFloat(document.getElementById('pageHeight').value) || 600;
      const marginTop = parseFloat(document.getElementById('marginTop').value) || 0;
      const marginRight = parseFloat(document.getElementById('marginRight').value) || 0;
      const marginBottom = parseFloat(document.getElementById('marginBottom').value) || 0;
      const marginLeft = parseFloat(document.getElementById('marginLeft').value) || 0;

      const columns = parseInt(document.getElementById('columns').value) || 1;
      const columnGutter = parseFloat(document.getElementById('columnGutter').value) || 0;
      const showColumns = document.getElementById('showColumns').checked;

      const rows = parseInt(document.getElementById('rows').value) || 0; 
      const rowGutter = parseFloat(document.getElementById('rowGutter').value) || 0;
      const showRows = document.getElementById('showRows').checked;

      const baselineSpacing = parseFloat(document.getElementById('baselineSpacing').value) || 0;
      const showBaseline = document.getElementById('showBaseline').checked;

      // Workable area
      const workableWidth = pageWidth - marginLeft - marginRight;
      const workableHeight = pageHeight - marginTop - marginBottom;

      // Build the SVG step by step
      // Start with the root <svg> tag
      let svgContent = '';
      svgContent += `<?xml version="1.0" encoding="UTF-8"?>\n`;
      svgContent += `<svg width="${pageWidth}" height="${pageHeight}" xmlns="http://www.w3.org/2000/svg">\n`;

      // White background
      svgContent += `  <rect width="${pageWidth}" height="${pageHeight}" fill="#ffffff" />\n`;

      // Margin outline
      svgContent += `  <rect x="${marginLeft}" y="${marginTop}" width="${workableWidth}" height="${workableHeight}" fill="none" stroke="#999999" stroke-width="1" />\n`;

      // Columns
      if (showColumns && columns > 0) {
        const totalColumnGutters = (columns - 1) * columnGutter;
        const columnWidth = (workableWidth - totalColumnGutters) / columns;

        for (let i = 0; i < columns; i++) {
          const x = marginLeft + i * (columnWidth + columnGutter);
          // Column background
          svgContent += `  <rect x="${x}" y="${marginTop}" width="${columnWidth}" height="${workableHeight}" fill="rgba(255, 0, 0, 0.1)" />\n`;
          // Column boundary lines
          const colLeft = x;
          const colRight = x + columnWidth;
          svgContent += `  <line x1="${colLeft}" y1="${marginTop}" x2="${colLeft}" y2="${marginTop + workableHeight}" stroke="rgba(255, 0, 0, 0.3)" stroke-width="1"/>\n`;
          svgContent += `  <line x1="${colRight}" y1="${marginTop}" x2="${colRight}" y2="${marginTop + workableHeight}" stroke="rgba(255, 0, 0, 0.3)" stroke-width="1"/>\n`;
        }
      }

      // Rows
      if (showRows && rows > 0) {
        const totalRowGutters = (rows - 1) * rowGutter;
        const rowHeight = (workableHeight - totalRowGutters) / rows;

        for (let j = 0; j < rows; j++) {
          const y = marginTop + j * (rowHeight + rowGutter);
          // Row background
          svgContent += `  <rect x="${marginLeft}" y="${y}" width="${workableWidth}" height="${rowHeight}" fill="rgba(0,128,255,0.07)" />\n`;
          // Row boundary lines
          const rowTop = y;
          const rowBottom = y + rowHeight;
          svgContent += `  <line x1="${marginLeft}" y1="${rowTop}" x2="${marginLeft + workableWidth}" y2="${rowTop}" stroke="rgba(0,128,255,0.3)" stroke-width="1" />\n`;
          svgContent += `  <line x1="${marginLeft}" y1="${rowBottom}" x2="${marginLeft + workableWidth}" y2="${rowBottom}" stroke="rgba(0,128,255,0.3)" stroke-width="1" />\n`;
        }
      }

      // Baseline
      if (showBaseline && baselineSpacing > 0) {
        let baselineY = marginTop;
        while (baselineY <= marginTop + workableHeight) {
          svgContent += `  <line x1="${marginLeft}" y1="${baselineY}" x2="${marginLeft + workableWidth}" y2="${baselineY}" stroke="rgba(0,0,0,0.15)" stroke-width="1"/>\n`;
          baselineY += baselineSpacing;
        }
      }

      // Close the <svg> tag
      svgContent += `</svg>`;

      // Prepare for download
      const svgBlob = new Blob([svgContent], { type: 'image/svg+xml' });
      const svgUrl = URL.createObjectURL(svgBlob);

      const downloadLink = document.createElement('a');
      downloadLink.href = svgUrl;
      downloadLink.download = 'grid.svg';
      downloadLink.click();

      // Revoke the object URL for memory cleanup
      setTimeout(() => {
        URL.revokeObjectURL(svgUrl);
      }, 1000);
    }

    // Generate a default grid on page load
    window.addEventListener('DOMContentLoaded', drawGrid);
  </script>
</body>
</html>
