// ConfiguratorPage.jsx — Tile visualiser for the Verona oven dome
(function () {
  const { useState, useEffect, useRef, useCallback } = React;

  // ---------------------------------------------------------------------------
  // Tile swatch catalogue
  // ---------------------------------------------------------------------------
  // Each tile entry has an `image` (path to the tile photo). If the image
  // is missing, the configurator falls back to a solid `color` swatch.
  const TILES = [
    { id: 'upload', label: 'Your own tile', isUpload: true, color: null },
    { id: 'gold',    label: 'Magic Gold',    image: 'images/tiles/49-D-Magic-Gold-Hex.jpg',     color: '#C9A24A' },
    { id: 'copper',  label: 'Magic Copper',  image: 'images/tiles/48-D-Magic-Copper-Hex.jpg',   color: '#A86A3E' },
    { id: 'bronze',  label: 'Magic Bronze',  image: 'images/tiles/45-D-Magic-Bronze-Hex.jpg',   color: '#6E4A45' },
    { id: 'silver',  label: 'Magic Silver',  image: 'images/tiles/47-D-Magic-Silver-Hex.jpg',   color: '#9FA3A6' },
    { id: 'black',   label: 'Magic Black',   image: 'images/tiles/46-D-Magic-Black-Hex.jpg',    color: '#2A2A2C' },
    { id: 'classic', label: 'Classic Blend', image: 'images/tiles/Magic-Blend-Classic-Hex.jpg', color: '#7D7165' },
    { id: 'trend',   label: 'Trend Blend',   image: 'images/tiles/Magic-Blend-Trend-Hex.jpg',   color: '#8A7A6E' },
  ];

  // ---------------------------------------------------------------------------
  // Helpers: generate a tiled canvas pattern from an image or a solid colour
  // ---------------------------------------------------------------------------
  // -------- Colour helpers --------
  function hexToRgb(hex) {
    const h = hex.replace('#', '');
    const v = h.length === 3
      ? h.split('').map(c => parseInt(c + c, 16))
      : [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
    return { r: v[0], g: v[1], b: v[2] };
  }

  function clamp255(n) { return Math.max(0, Math.min(255, n | 0)); }

  function jitterColor(rgb, amount, seed) {
    // Deterministic per-tile variation
    const j = (Math.sin(seed * 9301.0 + 49297.0) * 233280.0) % 1;
    const k = (Math.sin(seed * 1731.0 + 12903.0) * 233280.0) % 1;
    const l = (Math.sin(seed * 4801.0 + 39817.0) * 233280.0) % 1;
    return {
      r: clamp255(rgb.r + (j - 0.5) * amount * 2),
      g: clamp255(rgb.g + (k - 0.5) * amount * 2),
      b: clamp255(rgb.b + (l - 0.5) * amount * 2),
    };
  }

  function rgbStr({ r, g, b }, a) {
    return a == null ? `rgb(${r},${g},${b})` : `rgba(${r},${g},${b},${a})`;
  }

  // -------- Photorealistic mosaic tile pattern --------
  // Strategy: build a LARGE pattern sheet (N×N tiles) with per-tile colour
  // jitter, gloss highlights, soft grout shadows. That sheet repeats.
  function makeSolidTilePattern(ctx, tileColor, groutColor, tileSize = 28, grout = 3) {
    const N = 7; // tiles per side in the repeating sheet
    const cell = tileSize + grout;
    const W = cell * N;
    const off = document.createElement('canvas');
    off.width = W; off.height = W;
    const ox = off.getContext('2d');

    const baseRgb = hexToRgb(tileColor);
    const groutRgb = hexToRgb(groutColor);

    // 1. Grout base
    ox.fillStyle = rgbStr(groutRgb);
    ox.fillRect(0, 0, W, W);

    // 2. Subtle grout texture (slight noise)
    const grain = ox.createImageData(W, W);
    for (let i = 0; i < grain.data.length; i += 4) {
      const n = (Math.random() - 0.5) * 14;
      grain.data[i] = clamp255(groutRgb.r + n);
      grain.data[i + 1] = clamp255(groutRgb.g + n);
      grain.data[i + 2] = clamp255(groutRgb.b + n);
      grain.data[i + 3] = 255;
    }
    ox.putImageData(grain, 0, 0);

    // 3. Each tile
    for (let row = 0; row < N; row++) {
      for (let col = 0; col < N; col++) {
        const seed = row * 100 + col + 1;
        const x = col * cell + grout / 2;
        const y = row * cell + grout / 2;
        const t = tileSize;

        // Per-tile colour jitter for realism
        const c = jitterColor(baseRgb, 18, seed);

        // Soft drop shadow into grout (makes tile look slightly raised)
        ox.save();
        ox.shadowColor = 'rgba(0,0,0,0.35)';
        ox.shadowBlur = 2;
        ox.shadowOffsetY = 0.6;
        ox.fillStyle = rgbStr(c);
        const r = Math.max(1, Math.round(t * 0.06));
        roundRect(ox, x, y, t, t, r);
        ox.fill();
        ox.restore();

        // Gloss highlight (diagonal gradient from top-left)
        const gloss = ox.createLinearGradient(x, y, x + t, y + t);
        gloss.addColorStop(0, 'rgba(255,255,255,0.32)');
        gloss.addColorStop(0.35, 'rgba(255,255,255,0.08)');
        gloss.addColorStop(0.65, 'rgba(0,0,0,0.04)');
        gloss.addColorStop(1, 'rgba(0,0,0,0.18)');
        ox.fillStyle = gloss;
        roundRect(ox, x, y, t, t, r);
        ox.fill();

        // Specular highlight blob in upper-left
        const spec = ox.createRadialGradient(
          x + t * 0.25, y + t * 0.22, 0,
          x + t * 0.25, y + t * 0.22, t * 0.55,
        );
        spec.addColorStop(0, 'rgba(255,255,255,0.28)');
        spec.addColorStop(1, 'rgba(255,255,255,0)');
        ox.fillStyle = spec;
        roundRect(ox, x, y, t, t, r);
        ox.fill();

        // Bottom-right edge shadow
        const edgeShadow = ox.createLinearGradient(x + t, y + t, x + t * 0.7, y + t * 0.7);
        edgeShadow.addColorStop(0, 'rgba(0,0,0,0.20)');
        edgeShadow.addColorStop(1, 'rgba(0,0,0,0)');
        ox.fillStyle = edgeShadow;
        roundRect(ox, x, y, t, t, r);
        ox.fill();

        // Subtle micro-texture on the tile face
        ox.save();
        roundRect(ox, x, y, t, t, r);
        ox.clip();
        for (let i = 0; i < t * t * 0.05; i++) {
          const px = x + Math.random() * t;
          const py = y + Math.random() * t;
          const a = Math.random() * 0.08;
          ox.fillStyle = Math.random() > 0.5 ? `rgba(255,255,255,${a})` : `rgba(0,0,0,${a})`;
          ox.fillRect(px, py, 1, 1);
        }
        ox.restore();
      }
    }

    return ctx.createPattern(off, 'repeat');
  }

  function roundRect(ctx, x, y, w, h, r) {
    ctx.beginPath();
    ctx.moveTo(x + r, y);
    ctx.arcTo(x + w, y, x + w, y + h, r);
    ctx.arcTo(x + w, y + h, x, y + h, r);
    ctx.arcTo(x, y + h, x, y, r);
    ctx.arcTo(x, y, x + w, y, r);
    ctx.closePath();
  }

  function makeImageTilePattern(ctx, img, tileSize = 80) {
    const off = document.createElement('canvas');
    off.width = tileSize;
    off.height = tileSize;
    const ox = off.getContext('2d');
    ox.drawImage(img, 0, 0, tileSize, tileSize);
    return ctx.createPattern(off, 'repeat');
  }

  // ---------------------------------------------------------------------------
  // The dome mask path — calibrated to Verona main.jpg (1280×960 natural size)
  // The dome is an ellipse-ish hemisphere sitting centre-top of the image.
  // Coordinates expressed as fractions of the canvas display size so they
  // scale with any rendered width.
  // ---------------------------------------------------------------------------
  // Verona main.jpg natural: ~1400 × 1050 (visible oven)
  // Dome is roughly in upper-right of frame; not perfectly centred.
  // These fractions are tuned to overlay the dome hemisphere only,
  // excluding the chimney, arch face and base.
  const DOME = {
    cx: 0.42,   // dome centre horizontally
    cy: 0.27,   // dome centre vertically
    rx: 0.28,   // half-width of dome
    ry: 0.22,   // half-height of dome
    bottomCutY: 0.42,  // hard horizontal cut — anything below this Y fraction is masked out
  };

  function applyDomeClip(ctx, w, h, dome) {
    ctx.beginPath();
    ctx.ellipse(dome.cx * w, dome.cy * h, dome.rx * w, dome.ry * h, 0, 0, Math.PI * 2);
    ctx.clip();
    ctx.beginPath();
    ctx.rect(0, 0, w, dome.bottomCutY * h);
    ctx.clip();
  }

  // ---------------------------------------------------------------------------
  // Canvas renderer — three-layer compositing, no exotic blend modes:
  //
  //  Layer A (offscreen): tile pattern fills the dome area
  //  Layer B (offscreen): original oven image with dome pixels converted to
  //                        greyscale, so only brightness info remains
  //  Final canvas:
  //    1. Draw oven photo (full colour, normal)
  //    2. Draw Layer A (tile) clipped to dome at full opacity
  //    3. Draw Layer B (greyscale shading) clipped to dome at `opacity` alpha
  //       — this re-applies the 3D light/shadow on top of the tile colour
  // ---------------------------------------------------------------------------
  function toGreyscaleCanvas(img, w, h) {
    const off = document.createElement('canvas');
    off.width = w; off.height = h;
    const ox = off.getContext('2d');
    ox.drawImage(img, 0, 0, w, h);
    const id = ox.getImageData(0, 0, w, h);
    const d = id.data;
    for (let i = 0; i < d.length; i += 4) {
      const lum = 0.299 * d[i] + 0.587 * d[i+1] + 0.114 * d[i+2];
      d[i] = d[i+1] = d[i+2] = lum;
    }
    ox.putImageData(id, 0, 0);
    return off;
  }

  function applyPolygonClip(ctx, w, h, points) {
    if (!points || points.length < 3) return false;
    ctx.beginPath();
    ctx.moveTo(points[0][0] * w, points[0][1] * h);
    for (let i = 1; i < points.length; i++) {
      ctx.lineTo(points[i][0] * w, points[i][1] * h);
    }
    ctx.closePath();
    ctx.clip();
    return true;
  }

  function renderOven(canvas, ovenImg, pattern, shadingOpacity, dome, polygon, traceMode, tracePoints) {
    if (!canvas || !ovenImg) return;
    const w = canvas.width;
    const h = canvas.height;
    const ctx = canvas.getContext('2d');

    ctx.clearRect(0, 0, w, h);
    ctx.drawImage(ovenImg, 0, 0, w, h);

    if (pattern && !traceMode) {
      // Use polygon mask if available, otherwise fall back to ellipse dome
      const usePoly = polygon && polygon.length >= 3;

      ctx.save();
      if (usePoly) applyPolygonClip(ctx, w, h, polygon);
      else applyDomeClip(ctx, w, h, dome);
      ctx.globalAlpha = 1;
      ctx.globalCompositeOperation = 'source-over';
      ctx.fillStyle = pattern;
      ctx.fillRect(0, 0, w, h);
      ctx.restore();

      const grey = toGreyscaleCanvas(ovenImg, w, h);
      ctx.save();
      if (usePoly) applyPolygonClip(ctx, w, h, polygon);
      else applyDomeClip(ctx, w, h, dome);
      ctx.globalAlpha = shadingOpacity;
      ctx.globalCompositeOperation = 'multiply';
      ctx.drawImage(grey, 0, 0, w, h);
      ctx.restore();
    }

    // Trace overlay
    if (traceMode && tracePoints) {
      ctx.save();
      // Dim the photo so trace marks stand out
      ctx.fillStyle = 'rgba(255,255,255,0.25)';
      ctx.fillRect(0, 0, w, h);

      if (tracePoints.length >= 1) {
        ctx.strokeStyle = '#C75D34';
        ctx.fillStyle = 'rgba(199, 93, 52, 0.20)';
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.moveTo(tracePoints[0][0] * w, tracePoints[0][1] * h);
        for (let i = 1; i < tracePoints.length; i++) {
          ctx.lineTo(tracePoints[i][0] * w, tracePoints[i][1] * h);
        }
        if (tracePoints.length >= 3) {
          ctx.closePath();
          ctx.fill();
        }
        ctx.stroke();

        // Draw dots at each point
        tracePoints.forEach(([px, py], i) => {
          ctx.beginPath();
          ctx.arc(px * w, py * h, 5, 0, Math.PI * 2);
          ctx.fillStyle = i === 0 ? '#1B4D8E' : '#C75D34';
          ctx.fill();
          ctx.strokeStyle = '#fff';
          ctx.lineWidth = 2;
          ctx.stroke();
        });
      }
      ctx.restore();
    }
  }

  // ---------------------------------------------------------------------------
  // Tile swatch thumbnail component
  // ---------------------------------------------------------------------------
  function TileSwatch({ tile, selected, onSelect, uploadedSrc }) {
    const isUpload = tile.isUpload;
    const inputRef = useRef(null);

    const handleClick = () => {
      if (isUpload) {
        inputRef.current && inputRef.current.click();
      } else {
        onSelect(tile.id, null);
      }
    };

    const handleFile = (e) => {
      const file = e.target.files[0];
      if (!file) return;
      const url = URL.createObjectURL(file);
      onSelect('upload', url);
    };

    const borderStyle = selected
      ? '3px solid var(--tf-flame, #C75D34)'
      : '2px solid transparent';

    return (
      <div
        onClick={handleClick}
        style={{
          cursor: 'pointer',
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          gap: 6,
        }}
      >
        <div style={{
          width: 60,
          height: 60,
          borderRadius: 8,
          border: borderStyle,
          boxShadow: selected ? '0 0 0 2px rgba(199,93,52,0.25)' : '0 1px 4px rgba(0,0,0,.12)',
          overflow: 'hidden',
          transition: 'border 0.2s, box-shadow 0.2s',
          background: isUpload
            ? 'var(--surface, #F5EFE6)'
            : (tile.image ? `url(${tile.image}) center/cover` : tile.color),
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          flexShrink: 0,
        }}>
          {isUpload && uploadedSrc
            ? <img src={uploadedSrc} style={{ width: '100%', height: '100%', objectFit: 'cover' }} alt="Your tile" />
            : isUpload
              ? <span style={{ fontSize: 22, lineHeight: 1 }}>+</span>
              : null
          }
        </div>
        <span style={{
          fontSize: 10,
          fontFamily: 'var(--font-body, Inter, sans-serif)',
          color: 'var(--fg-2, #666)',
          textAlign: 'center',
          lineHeight: 1.2,
          maxWidth: 64,
        }}>{tile.label}</span>
        {isUpload && (
          <input ref={inputRef} type="file" accept="image/*" onChange={handleFile}
            style={{ display: 'none' }} />
        )}
      </div>
    );
  }

  // ---------------------------------------------------------------------------
  // Main configurator page
  // ---------------------------------------------------------------------------
  function ConfiguratorPage({ go }) {
    const canvasRef = useRef(null);
    const [ovenImg, setOvenImg] = useState(null);
    const [selectedTile, setSelectedTile] = useState('gold');
    const [tileImages, setTileImages] = useState({}); // id -> HTMLImageElement
    const [opacity, setOpacity] = useState(0.65);
    const [uploadedSrc, setUploadedSrc] = useState(null);
    const [uploadedImg, setUploadedImg] = useState(null);
    const [canvasSize, setCanvasSize] = useState({ w: 800, h: 600 });
    const wrapRef = useRef(null);

    // Dome mask polygon — hand-traced fractions of canvas (0–1).
    // Calibrated for images/Verona main.jpg.
    const DOME_POLYGON = [[0.5464,0.5174],[0.5933,0.5158],[0.6238,0.5111],[0.6438,0.5049],[0.6696,0.497],[0.6884,0.4892],[0.6896,0.4751],[0.6896,0.4501],[0.6896,0.4282],[0.6884,0.4031],[0.6872,0.3828],[0.6837,0.3672],[0.6813,0.3484],[0.6719,0.3186],[0.6567,0.2967],[0.6426,0.2779],[0.625,0.2607],[0.6144,0.2529],[0.6027,0.2451],[0.5945,0.2404],[0.5827,0.2294],[0.564,0.2216],[0.5499,0.2232],[0.5264,0.2216],[0.5135,0.2154],[0.49,0.2122],[0.4806,0.2122],[0.4595,0.2138],[0.4548,0.2154],[0.4442,0.2154],[0.4349,0.2154],[0.4372,0.2341],[0.4372,0.2451],[0.4325,0.2701],[0.429,0.2764],[0.4055,0.2842],[0.3973,0.2858],[0.382,0.2873],[0.3809,0.2811],[0.3785,0.2623],[0.3785,0.2467],[0.3809,0.2373],[0.3773,0.2404],[0.368,0.2498],[0.3539,0.2592],[0.3445,0.267],[0.3327,0.2748],[0.3245,0.2873],[0.314,0.2983],[0.3128,0.3014],[0.3081,0.3061],[0.3269,0.303],[0.3457,0.2999],[0.3621,0.2967],[0.3856,0.2983],[0.409,0.2983],[0.4243,0.303],[0.4407,0.3061],[0.4548,0.3218],[0.4665,0.3265],[0.4806,0.3421],[0.4971,0.3562],[0.5018,0.3672],[0.5135,0.3859],[0.5205,0.4031],[0.5299,0.4204],[0.5288,0.4376],[0.5381,0.4657],[0.5393,0.4751],[0.544,0.4923],[0.544,0.5017]];

    // Load oven image
    useEffect(() => {
      const img = new Image();
      img.crossOrigin = 'anonymous';
      img.src = 'images/Verona main.jpg';
      img.onload = () => setOvenImg(img);
    }, []);

    // Preload tile photos
    useEffect(() => {
      TILES.forEach(tile => {
        if (!tile.image) return;
        const img = new Image();
        img.crossOrigin = 'anonymous';
        img.onload = () => setTileImages(prev => ({ ...prev, [tile.id]: img }));
        img.onerror = () => { /* fall back to color swatch silently */ };
        img.src = tile.image;
      });
    }, []);

    // Responsive canvas sizing
    useEffect(() => {
      const measure = () => {
        if (!wrapRef.current) return;
        const maxW = Math.min(wrapRef.current.clientWidth, 760);
        const aspect = 960 / 1280;
        setCanvasSize({ w: maxW, h: Math.round(maxW * aspect) });
      };
      measure();
      window.addEventListener('resize', measure);
      return () => window.removeEventListener('resize', measure);
    }, []);

    // Build pattern & redraw whenever inputs change
    useEffect(() => {
      const canvas = canvasRef.current;
      if (!canvas || !ovenImg) return;

      // Set dimensions first — this resets the canvas context
      canvas.width = canvasSize.w;
      canvas.height = canvasSize.h;

      // Get fresh context AFTER resizing
      const ctx = canvas.getContext('2d');

      // Build pattern on the fresh context
      let pattern = null;
      if (selectedTile === 'upload' && uploadedImg) {
        const tileSize = Math.round(canvasSize.w * 0.18);
        pattern = makeImageTilePattern(ctx, uploadedImg, tileSize);
      } else {
        const tile = TILES.find(t => t.id === selectedTile);
        const tileImg = tile && tileImages[tile.id];
        if (tileImg) {
          // Use the actual tile photo as the pattern
          const tileSize = Math.round(canvasSize.w * 0.18);
          pattern = makeImageTilePattern(ctx, tileImg, tileSize);
        } else if (tile && !tile.isUpload && tile.color) {
          // Fallback: solid colour while photo loads (or if missing)
          const tileSize = Math.round(canvasSize.w * 0.040);
          const grout = Math.max(2, Math.round(tileSize * 0.14));
          pattern = makeSolidTilePattern(ctx, tile.color, tile.color, tileSize, grout);
        }
      }

      renderOven(canvas, ovenImg, pattern, opacity, null, DOME_POLYGON, false, null);
    }, [ovenImg, selectedTile, uploadedImg, opacity, canvasSize, tileImages]);

    const handleSwatchSelect = (id, url) => {
      setSelectedTile(id);
      if (url) {
        setUploadedSrc(url);
        const img = new Image();
        img.onload = () => setUploadedImg(img);
        img.src = url;
      }
    };

    const handleDownload = () => {
      const canvas = canvasRef.current;
      if (!canvas) return;
      const link = document.createElement('a');
      link.download = 'terraforno-verona-custom.png';
      link.href = canvas.toDataURL('image/png');
      link.click();
    };

    const selectedLabel = TILES.find(t => t.id === selectedTile)?.label || 'Your tile';

    return (
      <div style={{ background: 'var(--bg, #FBF6EE)', minHeight: '100vh' }}>

        {/* Page header */}
        <div style={{
          background: 'var(--surface, #F5EFE6)',
          borderBottom: '1px solid var(--border, #E8DDD0)',
          padding: '40px 0 32px',
          textAlign: 'center',
        }}>
          <div className="tf-wrap">
            <p style={{
              fontFamily: 'var(--font-body, Inter, sans-serif)',
              fontSize: 12,
              letterSpacing: '0.12em',
              textTransform: 'uppercase',
              color: 'var(--tf-flame, #C75D34)',
              marginBottom: 10,
            }}>Build Your Oven</p>
            <h1 style={{
              fontFamily: 'var(--font-display, Playfair Display, serif)',
              fontSize: 'clamp(28px, 4vw, 44px)',
              fontWeight: 600,
              color: 'var(--fg-1, #1A1008)',
              margin: '0 0 12px',
              lineHeight: 1.15,
            }}>Tile Visualiser</h1>
            <p style={{
              fontFamily: 'var(--font-body, Inter, sans-serif)',
              fontSize: 15,
              color: 'var(--fg-2, #5C4A32)',
              maxWidth: 520,
              margin: '0 auto',
              lineHeight: 1.6,
            }}>
              Choose a tile finish below — or upload a photo of your own tile — and see it live on the Verona dome.
            </p>
          </div>
        </div>

        {/* Main layout */}
        <div className="tf-wrap" style={{ padding: '40px var(--wrap-pad, 24px)' }}>
          <div style={{
            display: 'grid',
            gridTemplateColumns: 'minmax(0,1fr) 300px',
            gap: 40,
            alignItems: 'start',
          }}
            className="configurator-grid"
          >

            {/* Canvas */}
            <div ref={wrapRef} style={{ position: 'relative' }}>
              {!ovenImg && (
                <div style={{
                  position: 'absolute', inset: 0, display: 'flex',
                  alignItems: 'center', justifyContent: 'center',
                  background: 'var(--surface, #F5EFE6)', borderRadius: 12,
                }}>
                  <span style={{ color: 'var(--fg-3, #9B8B79)', fontFamily: 'var(--font-body)' }}>Loading…</span>
                </div>
              )}
              <canvas
                ref={canvasRef}
                width={canvasSize.w}
                height={canvasSize.h}
                style={{
                  display: 'block',
                  width: '100%',
                  borderRadius: 12,
                  boxShadow: '0 4px 32px rgba(0,0,0,.10)',
                  background: '#fff',
                }}
              />
              {/* Tile label badge */}
              <div style={{
                position: 'absolute', bottom: 16, left: 16,
                background: 'rgba(26,16,8,0.72)',
                backdropFilter: 'blur(8px)',
                color: '#fff',
                padding: '6px 14px',
                borderRadius: 999,
                fontFamily: 'var(--font-body, Inter, sans-serif)',
                fontSize: 12,
                letterSpacing: '0.06em',
              }}>
                {selectedLabel}
              </div>
            </div>

            {/* Controls panel */}
            <div style={{ display: 'flex', flexDirection: 'column', gap: 28 }}>

              {/* Tile grid */}
              <div>
                <p style={{
                  fontFamily: 'var(--font-body, Inter, sans-serif)',
                  fontSize: 11,
                  letterSpacing: '0.1em',
                  textTransform: 'uppercase',
                  color: 'var(--fg-3, #9B8B79)',
                  marginBottom: 14,
                }}>Select Tile Finish</p>
                <div style={{
                  display: 'grid',
                  gridTemplateColumns: 'repeat(4, 1fr)',
                  gap: 12,
                }}>
                  {TILES.map(tile => (
                    <TileSwatch
                      key={tile.id}
                      tile={tile}
                      selected={selectedTile === tile.id}
                      onSelect={handleSwatchSelect}
                      uploadedSrc={uploadedSrc}
                    />
                  ))}
                </div>
              </div>

              {/* Opacity slider */}
              <div>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 10 }}>
                  <p style={{
                    fontFamily: 'var(--font-body, Inter, sans-serif)',
                    fontSize: 11,
                    letterSpacing: '0.1em',
                    textTransform: 'uppercase',
                    color: 'var(--fg-3, #9B8B79)',
                    margin: 0,
                  }}>Shading</p>
                  <span style={{
                    fontFamily: 'var(--font-body, Inter, sans-serif)',
                    fontSize: 12,
                    color: 'var(--fg-2, #5C4A32)',
                  }}>{Math.round(opacity * 100)}%</span>
                </div>
                <input
                  type="range"
                  min="0.2"
                  max="1"
                  step="0.01"
                  value={opacity}
                  onChange={e => setOpacity(parseFloat(e.target.value))}
                  style={{ width: '100%', accentColor: 'var(--tf-flame, #C75D34)', cursor: 'pointer' }}
                />
              </div>

              {/* Info note */}
              <div style={{
                background: 'var(--surface, #F5EFE6)',
                border: '1px solid var(--border, #E8DDD0)',
                borderRadius: 10,
                padding: '14px 16px',
              }}>
                <p style={{
                  fontFamily: 'var(--font-body, Inter, sans-serif)',
                  fontSize: 12,
                  color: 'var(--fg-2, #5C4A32)',
                  lineHeight: 1.6,
                  margin: 0,
                }}>
                  This is a visual preview only. Final tile colour and texture may vary slightly depending on lighting and firing. Upload a photo of your own tile using the <strong>+</strong> swatch.
                </p>
              </div>

              {/* Download */}
              <button
                onClick={handleDownload}
                style={{
                  background: 'transparent',
                  border: '1.5px solid var(--tf-flame, #C75D34)',
                  color: 'var(--tf-flame, #C75D34)',
                  borderRadius: 8,
                  padding: '10px 0',
                  fontFamily: 'var(--font-body, Inter, sans-serif)',
                  fontSize: 13,
                  fontWeight: 500,
                  cursor: 'pointer',
                  letterSpacing: '0.04em',
                  transition: 'background 0.2s, color 0.2s',
                }}
                onMouseEnter={e => { e.currentTarget.style.background = 'var(--tf-flame, #C75D34)'; e.currentTarget.style.color = '#fff'; }}
                onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = 'var(--tf-flame, #C75D34)'; }}
              >
                Save Preview Image
              </button>

              {/* CTA */}
              <button
                onClick={() => go('contact')}
                style={{
                  background: 'var(--tf-flame, #C75D34)',
                  border: 'none',
                  color: '#fff',
                  borderRadius: 8,
                  padding: '14px 0',
                  fontFamily: 'var(--font-body, Inter, sans-serif)',
                  fontSize: 14,
                  fontWeight: 600,
                  cursor: 'pointer',
                  letterSpacing: '0.04em',
                  transition: 'background 0.2s',
                  lineHeight: 1,
                }}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--accent-hover, #9A3B1E)'}
                onMouseLeave={e => e.currentTarget.style.background = 'var(--tf-flame, #C75D34)'}
              >
                Request a Quote →
              </button>

            </div>
          </div>
        </div>

        {/* Mobile responsive style */}
        <style>{`
          @media (max-width: 740px) {
            .configurator-grid {
              grid-template-columns: 1fr !important;
            }
          }
        `}</style>
      </div>
    );
  }

  window.ConfiguratorPage = ConfiguratorPage;
})();
