// PDF Preview — static 1-page audit layout
// Shown in IntakeForm when sent===true
// PdfFloorPlan: static SVG with 3 dim tiers (appliances inner, openings middle, base cabs outer)
// PAD=80 (vs RoomCanvas PAD=56) — extra margin for stacked dim layers

function PdfFloorPlan({ f, unit }) {
  const lengthIn = parseFloat(f.length) || 0;
  const widthIn  = parseFloat(f.width)  || 0;
  if (!lengthIn || !widthIn) return (
    <div style={{ border: '1px solid var(--border-default)', background: 'var(--surface-raised)', display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '220px', fontFamily: 'var(--font-mono)', fontSize: '10px', color: 'var(--text-muted)', letterSpacing: '0.08em' }}>
      NO DIMENSIONS
    </div>
  );

  // ── Geometry constants ──────────────────────────────────────────────────────
  // RC_* = original RoomCanvas coordinate space (stored pts live here)
  const RC_PAD = 56, RC_W = 500;
  const PAD = 96, SVG_W = 600;
  const BASE_CAB_IN = 24, UPPER_CAB_IN = 12;

  const ASPECT   = Math.min(Math.max(widthIn / lengthIn, 0.4), 1.1);
  const RC_H     = Math.round(RC_W * ASPECT);
  const SVG_H    = Math.round(SVG_W * ASPECT);
  const rc_rW    = RC_W - RC_PAD * 2;
  const rc_rH    = RC_H - RC_PAD * 2;
  const rc_sX    = rc_rW / lengthIn;
  const rc_sY    = rc_rH / widthIn;
  const roomPxW  = SVG_W - PAD * 2;
  const roomPxH  = SVG_H - PAD * 2;
  const scaleX   = roomPxW / lengthIn;
  const scaleY   = roomPxH / widthIn;

  // Linear re-projection from RoomCanvas pixel space to PDF pixel space
  const rp = (pt) => ({
    x: (pt.x - RC_PAD) / rc_sX * scaleX + PAD,
    y: (pt.y - RC_PAD) / rc_sY * scaleY + PAD,
  });

  const baseCabPxX  = BASE_CAB_IN  * scaleX;
  const baseCabPxY  = BASE_CAB_IN  * scaleY;
  const upperCabPxX = UPPER_CAB_IN * scaleX;
  const upperCabPxY = UPPER_CAB_IN * scaleY;

  const ORDER = ['north', 'east', 'south', 'west'];
  const WALL = {
    north: { outerLine: [PAD, PAD, PAD + roomPxW, PAD],                              perp: { x: 0, y: -1 } },
    east:  { outerLine: [PAD + roomPxW, PAD, PAD + roomPxW, PAD + roomPxH],          perp: { x: 1,  y: 0 } },
    south: { outerLine: [PAD, PAD + roomPxH, PAD + roomPxW, PAD + roomPxH],          perp: { x: 0,  y: 1 } },
    west:  { outerLine: [PAD, PAD, PAD, PAD + roomPxH],                              perp: { x: -1, y: 0 } },
  };
  const wallIsHorz = (w) => w === 'north' || w === 'south';
  const wallScale  = (w) => wallIsHorz(w) ? scaleX : scaleY;
  const wallLenIn  = (w) => wallIsHorz(w) ? lengthIn : widthIn;

  const APP_CFG = {
    fridge:     { label: 'Fridge',     color: '#5c82b0' },
    sink:       { label: 'Sink',       color: '#4a8b6f' },
    stove:      { label: 'Stove',      color: '#b56b3a' },
    dishwasher: { label: 'Dishwasher', color: '#8c7ab0' },
  };

  // ── Reprojected data ────────────────────────────────────────────────────────
  const baseData   = (f.baseBoundary  || []).map(s => ({ ...s, pts: s.pts.map(rp) }));
  const upperData  = (f.upperBoundary || []).map(s => ({ ...s, pts: s.pts.map(rp) }));
  const openings   = f.openings   || [];
  const appliances = f.appliances || [];

  // ── Helpers ─────────────────────────────────────────────────────────────────
  const dist   = (a, b) => Math.hypot(b.x - a.x, b.y - a.y);
  const ptStr  = (pts) => pts.map(p => `${p.x.toFixed(1)},${p.y.toFixed(1)}`).join(' ');
  const fmtDim = (inches) => {
    if (unit === 'mm') return `${Math.round(inches * 25.4)}mm`;
    if (inches <= 0.5) return '0"';
    const ft = Math.floor(inches / 12), i = Math.round(inches % 12);
    return ft > 0 ? `${ft}'-${i}"` : `${i}"`;
  };
  const segWall = (p1, p2) => {
    if (Math.abs(p2.y - p1.y) < 2) return (p1.y + p2.y) / 2 < PAD + roomPxH / 2 ? 'north' : 'south';
    return (p1.x + p2.x) / 2 < PAD + roomPxW / 2 ? 'west' : 'east';
  };
  const cabRects = (pts, cpxX, cpxY) => {
    const rects = [];
    for (let i = 1; i < pts.length; i++) {
      const p1 = pts[i-1], p2 = pts[i];
      if (dist(p1, p2) < 0.5) continue;
      const { perp } = WALL[segWall(p1, p2)];
      const dep = perp.x === 0 ? cpxY : cpxX;
      rects.push([p1, p2, { x: p2.x + perp.x * dep, y: p2.y + perp.y * dep }, { x: p1.x + perp.x * dep, y: p1.y + perp.y * dep }]);
    }
    return rects;
  };
  const cornerFills = (pts, cpxX, cpxY) => {
    const fills = [];
    const corners = [
      { pt: { x: PAD + cpxX,             y: PAD + cpxY             }, x: PAD,                  y: PAD,                  w: cpxX, h: cpxY },
      { pt: { x: PAD + roomPxW - cpxX,   y: PAD + cpxY             }, x: PAD + roomPxW - cpxX, y: PAD,                  w: cpxX, h: cpxY },
      { pt: { x: PAD + roomPxW - cpxX,   y: PAD + roomPxH - cpxY   }, x: PAD + roomPxW - cpxX, y: PAD + roomPxH - cpxY, w: cpxX, h: cpxY },
      { pt: { x: PAD + cpxX,             y: PAD + roomPxH - cpxY   }, x: PAD,                  y: PAD + roomPxH - cpxY, w: cpxX, h: cpxY },
    ];
    for (let i = 1; i < pts.length - 1; i++) {
      const p = pts[i];
      for (const c of corners) {
        if (Math.abs(p.x - c.pt.x) < 3 && Math.abs(p.y - c.pt.y) < 3) fills.push(c);
      }
    }
    return fills;
  };

  // ── Dim segment (no faded — PDF always full opacity) ────────────────────────
  const renderSegDim = (p1, p2, accent, key, dimOffset, cpxX, cpxY, p1Jn, p2Jn) => {
    const w = segWall(p1, p2);
    const tk = (x, y) => <line x1={x-3.5} y1={y-3.5} x2={x+3.5} y2={y+3.5} stroke={accent} strokeWidth="1.7" />;
    if (w === 'north' || w === 'south') {
      const snap = (x) => {
        if (Math.abs(x - (PAD + cpxX))           < 4) return PAD;
        if (Math.abs(x - (PAD + roomPxW - cpxX)) < 4) return PAD + roomPxW;
        return x;
      };
      const x1 = p1Jn ? snap(p1.x) : p1.x, x2 = p2Jn ? snap(p2.x) : p2.x;
      if (Math.abs(x2 - x1) / scaleX < 2) return null;
      const wallY = w === 'north' ? PAD : PAD + roomPxH;
      const dimY  = w === 'north' ? PAD - dimOffset : PAD + roomPxH + dimOffset;
      const textY = w === 'north' ? dimY - 8 : dimY + 12;
      return (
        <g key={key}>
          <line x1={x1} y1={wallY} x2={x1} y2={dimY} stroke={accent} strokeWidth="1.0" />
          <line x1={x2} y1={wallY} x2={x2} y2={dimY} stroke={accent} strokeWidth="1.0" />
          <line x1={x1} y1={dimY}  x2={x2} y2={dimY} stroke={accent} strokeWidth="1.2" />
          {tk(x1, dimY)}{tk(x2, dimY)}
          <text x={(x1+x2)/2} y={textY} textAnchor="middle" fontFamily="'IBM Plex Mono', monospace" fontSize="11" fill={accent}>{fmtDim(Math.abs(x2-x1)/scaleX)}</text>
        </g>
      );
    } else {
      const snap = (y) => {
        if (Math.abs(y - (PAD + cpxY))           < 4) return PAD;
        if (Math.abs(y - (PAD + roomPxH - cpxY)) < 4) return PAD + roomPxH;
        return y;
      };
      const y1 = p1Jn ? snap(p1.y) : p1.y, y2 = p2Jn ? snap(p2.y) : p2.y;
      if (Math.abs(y2 - y1) / scaleY < 2) return null;
      const wallX = w === 'east' ? PAD + roomPxW : PAD;
      const dimX  = w === 'east' ? PAD + roomPxW + dimOffset : PAD - dimOffset;
      const midY  = (y1 + y2) / 2, txtX = w === 'east' ? dimX + 10 : dimX - 10;
      return (
        <g key={key}>
          <line x1={wallX} y1={y1} x2={dimX} y2={y1} stroke={accent} strokeWidth="1.0" />
          <line x1={wallX} y1={y2} x2={dimX} y2={y2} stroke={accent} strokeWidth="1.0" />
          <line x1={dimX}  y1={y1} x2={dimX} y2={y2} stroke={accent} strokeWidth="1.2" />
          {tk(dimX, y1)}{tk(dimX, y2)}
          <text x={txtX} y={midY} textAnchor="middle" dominantBaseline="middle" fontFamily="'IBM Plex Mono', monospace" fontSize="11" fill={accent} transform={`rotate(-90 ${txtX} ${midY})`}>{fmtDim(Math.abs(y2-y1)/scaleY)}</text>
        </g>
      );
    }
  };

  // ── Boundary (base or upper) ────────────────────────────────────────────────
  const renderBoundary = (data, cpxX, cpxY, accent, hatch, showDims, dimOffset) => {
    if (!data?.length) return null;
    return data.map((seg, si) => {
      if (!seg.pts?.length) return null;
      const rects = cabRects(seg.pts, cpxX, cpxY);
      const fills = cornerFills(seg.pts, cpxX, cpxY);
      return (
        <g key={si}>
          {rects.map((r, ri) => <polygon key={ri} points={ptStr(r)} fill={`url(#${hatch})`} stroke={accent} strokeWidth="1" />)}
          {fills.map((c, ci) => <rect key={ci} x={c.x} y={c.y} width={c.w} height={c.h} fill={`url(#${hatch})`} stroke={accent} strokeWidth="1" />)}
          <polyline points={ptStr(seg.pts)} fill="none" stroke={accent} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
          {showDims && seg.pts.length >= 2 && seg.pts.slice(1).map((p2, ii) =>
            renderSegDim(seg.pts[ii], p2, accent, `${si}_${ii}`, dimOffset, cpxX, cpxY, ii > 0, ii < seg.pts.length - 2)
          )}
        </g>
      );
    });
  };

  // ── Wall lines (with opening gaps) ─────────────────────────────────────────
  const renderWallLines = () => ORDER.map(wallId => {
    const [x1, y1, x2, y2] = WALL[wallId].outerLine;
    const wOps = openings.filter(o => o.wall === wallId);
    if (!wOps.length) return <line key={wallId} x1={x1} y1={y1} x2={x2} y2={y2} stroke="#2c3e50" strokeWidth="1.5" />;
    const horiz = wallIsHorz(wallId), sc = wallScale(wallId);
    const axS = horiz ? x1 : y1, axE = horiz ? x2 : y2;
    const gaps = wOps.map(o => ({ s: axS + o.positionIn * sc, e: axS + (o.positionIn + o.widthIn) * sc })).sort((a, b) => a.s - b.s);
    const segs = []; let cur = axS;
    for (const g of gaps) { if (cur < g.s - 0.5) segs.push([cur, g.s]); cur = Math.max(cur, g.e); }
    if (cur < axE - 0.5) segs.push([cur, axE]);
    return segs.map(([a, b], i) =>
      horiz ? <line key={`${wallId}_${i}`} x1={a} y1={y1} x2={b} y2={y2} stroke="#2c3e50" strokeWidth="1.5" />
            : <line key={`${wallId}_${i}`} x1={x1} y1={a} x2={x2} y2={b} stroke="#2c3e50" strokeWidth="1.5" />
    );
  });

  // ── Opening cuts ────────────────────────────────────────────────────────────
  const renderOpeningCuts = (cabType) => {
    const rel = cabType === 'base' ? openings.filter(o => o.type === 'door') : openings;
    if (!rel.length) return null;
    const dX = cabType === 'base' ? baseCabPxX : upperCabPxX;
    const dY = cabType === 'base' ? baseCabPxY : upperCabPxY;
    return rel.map(o => {
      const sc = wallScale(o.wall), gA = PAD + o.positionIn * sc, gW = o.widthIn * sc, cP = o.clearanceIn * sc;
      let rx, ry, rw, rh;
      if (o.wall === 'north')      { rx = gA - cP; ry = PAD;                     rw = gW + 2*cP; rh = dY + 2; }
      else if (o.wall === 'south') { rx = gA - cP; ry = PAD + roomPxH - dY - 2;  rw = gW + 2*cP; rh = dY + 2; }
      else if (o.wall === 'east')  { rx = PAD + roomPxW - dX - 2; ry = gA - cP;  rw = dX + 2; rh = gW + 2*cP; }
      else                         { rx = PAD;                      ry = gA - cP;  rw = dX + 2; rh = gW + 2*cP; }
      return <rect key={o.id + cabType} x={rx} y={ry} width={Math.max(0,rw)} height={Math.max(0,rh)} fill="var(--as-paper)" />;
    });
  };

  const renderApplianceCuts = (cabType) => {
    const rel = cabType === 'base' ? appliances : appliances.filter(a => a.type === 'fridge');
    if (!rel.length) return null;
    const dX = cabType === 'base' ? baseCabPxX : upperCabPxX;
    const dY = cabType === 'base' ? baseCabPxY : upperCabPxY;
    return rel.map(a => {
      const sc = wallScale(a.wall), gA = PAD + a.positionIn * sc, gW = a.widthIn * sc;
      let rx, ry, rw, rh;
      if (a.wall === 'north')      { rx = gA; ry = PAD;                    rw = gW; rh = dY + 2; }
      else if (a.wall === 'south') { rx = gA; ry = PAD + roomPxH - dY - 2; rw = gW; rh = dY + 2; }
      else if (a.wall === 'east')  { rx = PAD + roomPxW - dX - 2; ry = gA; rw = dX + 2; rh = gW; }
      else                         { rx = PAD;                     ry = gA; rw = dX + 2; rh = gW; }
      return <rect key={a.id + cabType} x={rx} y={ry} width={Math.max(0,rw)} height={Math.max(0,rh)} fill="var(--as-paper)" />;
    });
  };

  // ── Opening symbols ─────────────────────────────────────────────────────────
  const renderOpeningSymbols = () => openings.map(o => {
    const horiz = wallIsHorz(o.wall), sc = wallScale(o.wall);
    const gA = PAD + o.positionIn * sc, gW = o.widthIn * sc, gB = gA + gW;
    const color = o.type === 'door' ? '#c0703a' : '#5c82b0';
    const sweep = (o.wall === 'north' || o.wall === 'east') ? 1 : 0;
    const idx = openings.filter(x => x.type === o.type).indexOf(o) + 1;
    const lbl = (o.type === 'door' ? 'D' : 'W') + idx;
    let wC, inw;
    if      (o.wall === 'north') { wC = PAD;           inw =  1; }
    else if (o.wall === 'south') { wC = PAD + roomPxH; inw = -1; }
    else if (o.wall === 'east')  { wC = PAD + roomPxW; inw = -1; }
    else                         { wC = PAD;           inw =  1; }
    let sym, lx, ly;
    if (horiz) {
      sym = o.type === 'door'
        ? <><line x1={gA} y1={wC} x2={gA} y2={wC+inw*gW} stroke={color} strokeWidth="1.4" /><path d={`M ${gB},${wC} A ${gW},${gW} 0 0 ${sweep} ${gA},${wC+inw*gW}`} fill="none" stroke={color} strokeWidth="0.75" strokeDasharray="3 2" /></>
        : <><line x1={gA} y1={wC-1.5} x2={gB} y2={wC-1.5} stroke={color} strokeWidth="1.2" /><line x1={gA} y1={wC+1.5} x2={gB} y2={wC+1.5} stroke={color} strokeWidth="1.2" /></>;
      lx = (gA + gB) / 2; ly = wC + inw * 11;
    } else {
      sym = o.type === 'door'
        ? <><line x1={wC} y1={gA} x2={wC+inw*gW} y2={gA} stroke={color} strokeWidth="1.4" /><path d={`M ${wC},${gB} A ${gW},${gW} 0 0 ${sweep} ${wC+inw*gW},${gA}`} fill="none" stroke={color} strokeWidth="0.75" strokeDasharray="3 2" /></>
        : <><line x1={wC-1.5} y1={gA} x2={wC-1.5} y2={gB} stroke={color} strokeWidth="1.2" /><line x1={wC+1.5} y1={gA} x2={wC+1.5} y2={gB} stroke={color} strokeWidth="1.2" /></>;
      lx = wC + inw * 11; ly = (gA + gB) / 2;
    }
    return (
      <g key={o.id} opacity="0.88">
        {sym}
        <text x={lx} y={ly} textAnchor="middle" dominantBaseline="middle" fontFamily="'IBM Plex Mono', monospace" fontSize="8.5" fill={color} fontWeight="600">{lbl}</text>
      </g>
    );
  });

  // ── Appliance symbols ────────────────────────────────────────────────────
  const renderApplianceSymbols = () => {
    if (!appliances.length) return null;
    return appliances.map(a => {
      const cfg   = APP_CFG[a.type];
      const horiz = wallIsHorz(a.wall);
      const sc    = wallScale(a.wall);
      const gapA  = PAD + a.positionIn * sc;
      const gapW  = a.widthIn * sc;
      const depthPx  = horiz ? baseCabPxY  : baseCabPxX;
      const uDepthPx = horiz ? upperCabPxY : upperCabPxX;
      let rx, ry, rw, rh;
      if (a.wall === 'north')      { rx = gapA; ry = PAD;                      rw = gapW; rh = depthPx; }
      else if (a.wall === 'south') { rx = gapA; ry = PAD + roomPxH - depthPx;  rw = gapW; rh = depthPx; }
      else if (a.wall === 'east')  { rx = PAD + roomPxW - depthPx; ry = gapA;  rw = depthPx; rh = gapW; }
      else                         { rx = PAD;                      ry = gapA;  rw = depthPx; rh = gapW; }
      const mx = rx + rw / 2, my = ry + rh / 2;

      let symbol;
      if (a.type === 'fridge') {
        symbol = (
          <>
            <rect x={rx} y={ry} width={rw} height={rh} fill="rgba(92,130,176,0.10)" stroke={cfg.color} strokeWidth="1.2" />
            {horiz
              ? <line x1={gapA+3} y1={ry} x2={gapA+3} y2={ry+rh*0.88} stroke={cfg.color} strokeWidth="0.8" />
              : <line x1={rx} y1={gapA+3} x2={rx+rw*0.88} y2={gapA+3} stroke={cfg.color} strokeWidth="0.8" />}
            <text x={mx} y={my} textAnchor="middle" dominantBaseline="middle" fontFamily="'IBM Plex Mono', monospace" fontSize="8" fill={cfg.color} fontWeight="600">REF</text>
          </>
        );
      } else if (a.type === 'sink') {
        const fLen = Math.min(rw, rh) * 0.2;
        let faucet;
        if (a.wall === 'north') {
          faucet = <><line x1={mx} y1={ry} x2={mx} y2={ry+fLen} stroke={cfg.color} strokeWidth="1.3" /><line x1={mx-fLen*0.45} y1={ry+fLen*0.5} x2={mx+fLen*0.45} y2={ry+fLen*0.5} stroke={cfg.color} strokeWidth="1.3" /></>;
        } else if (a.wall === 'south') {
          faucet = <><line x1={mx} y1={ry+rh} x2={mx} y2={ry+rh-fLen} stroke={cfg.color} strokeWidth="1.3" /><line x1={mx-fLen*0.45} y1={ry+rh-fLen*0.5} x2={mx+fLen*0.45} y2={ry+rh-fLen*0.5} stroke={cfg.color} strokeWidth="1.3" /></>;
        } else if (a.wall === 'east') {
          faucet = <><line x1={rx+rw} y1={my} x2={rx+rw-fLen} y2={my} stroke={cfg.color} strokeWidth="1.3" /><line x1={rx+rw-fLen*0.5} y1={my-fLen*0.45} x2={rx+rw-fLen*0.5} y2={my+fLen*0.45} stroke={cfg.color} strokeWidth="1.3" /></>;
        } else {
          faucet = <><line x1={rx} y1={my} x2={rx+fLen} y2={my} stroke={cfg.color} strokeWidth="1.3" /><line x1={rx+fLen*0.5} y1={my-fLen*0.45} x2={rx+fLen*0.5} y2={my+fLen*0.45} stroke={cfg.color} strokeWidth="1.3" /></>;
        }
        symbol = (
          <>
            <rect x={rx} y={ry} width={rw} height={rh} fill="rgba(74,139,111,0.06)" stroke={cfg.color} strokeWidth="1.2" />
            <rect x={rx+rw*0.08} y={ry+rh*0.08} width={rw*0.84} height={rh*0.84} rx="3" ry="3" fill="rgba(74,139,111,0.14)" stroke={cfg.color} strokeWidth="0.9" />
            <circle cx={mx} cy={my} r={1.8} fill={cfg.color} />
            {faucet}
          </>
        );
      } else if (a.type === 'stove') {
        const br = Math.min(rw, rh) * 0.11;
        const bp = [[rx+rw*0.3, ry+rh*0.3],[rx+rw*0.7, ry+rh*0.3],[rx+rw*0.3, ry+rh*0.7],[rx+rw*0.7, ry+rh*0.7]];
        const hoodY = a.wall === 'south' ? PAD + roomPxH - uDepthPx : ry;
        const hoodX = a.wall === 'east'  ? PAD + roomPxW - uDepthPx : rx;
        let aboveEl = null;
        if (a.aboveStove === 'hood') {
          const shrink = gapW * 0.08;
          const wallEdge_y = a.wall === 'north' ? hoodY : hoodY + uDepthPx;
          const innerEdge_y = a.wall === 'north' ? hoodY + uDepthPx : hoodY;
          const wallEdge_x = a.wall === 'west' ? hoodX : hoodX + uDepthPx;
          const innerEdge_x = a.wall === 'west' ? hoodX + uDepthPx : hoodX;
          aboveEl = horiz
            ? <polygon points={`${gapA},${wallEdge_y} ${gapA+gapW},${wallEdge_y} ${gapA+gapW-shrink},${innerEdge_y} ${gapA+shrink},${innerEdge_y}`} fill="rgba(181,107,58,0.10)" stroke={cfg.color} strokeWidth="0.8" strokeDasharray="2 2" />
            : <polygon points={`${wallEdge_x},${gapA} ${wallEdge_x},${gapA+gapW} ${innerEdge_x},${gapA+gapW-shrink} ${innerEdge_x},${gapA+shrink}`} fill="rgba(181,107,58,0.10)" stroke={cfg.color} strokeWidth="0.8" strokeDasharray="2 2" />;
        } else if (a.aboveStove === 'microwave') {
          aboveEl = horiz
            ? <rect x={gapA+gapW*0.05} y={hoodY} width={gapW*0.9} height={uDepthPx} fill="rgba(181,107,58,0.10)" stroke={cfg.color} strokeWidth="0.8" />
            : <rect x={hoodX} y={gapA+gapW*0.05} width={uDepthPx} height={gapW*0.9} fill="rgba(181,107,58,0.10)" stroke={cfg.color} strokeWidth="0.8" />;
        }
        symbol = (
          <>
            {aboveEl}
            <rect x={rx} y={ry} width={rw} height={rh} fill="rgba(181,107,58,0.08)" stroke={cfg.color} strokeWidth="1.2" />
            {bp.map(([bx, by], i) => <circle key={i} cx={bx} cy={by} r={Math.max(br, 2.5)} fill="none" stroke={cfg.color} strokeWidth="0.9" />)}
          </>
        );
      } else {
        symbol = (
          <>
            <rect x={rx} y={ry} width={rw} height={rh} fill="rgba(140,122,176,0.08)" stroke={cfg.color} strokeWidth="1.2" />
            <text x={mx} y={my} textAnchor="middle" dominantBaseline="middle" fontFamily="'IBM Plex Mono', monospace" fontSize="8" fill={cfg.color} fontWeight="600">DW</text>
          </>
        );
      }
      return <g key={a.id} opacity="0.9">{symbol}</g>;
    });
  };

  // ── Wall dimension chain ────────────────────────────────────────────────
  const renderWallChain = (wallId, comps, getColor, DL, DT) => {
    const horiz   = wallIsHorz(wallId);
    const sc      = wallScale(wallId);
    const wLen    = wallLenIn(wallId);
    const axS     = PAD;
    const axE     = PAD + (horiz ? roomPxW : roomPxH);
    const MIN_LBL = 20;
    const GAP_CLR = '#4e606f';

    const wallPx  = horiz
      ? (wallId === 'north' ? PAD : PAD + roomPxH)
      : (wallId === 'east'  ? PAD + roomPxW : PAD);
    const dir     = (wallId === 'north' || wallId === 'west') ? -1 : 1;
    const chainPx = wallPx + dir * DL;
    // South/east (dir=+1): text ascenders reach back toward the chain — enforce minimum clearance.
    // North/west (dir=-1): text extends away from wall, any DT is safe.
    const effectiveDT = dir > 0 ? Math.max(DT, DL + 13) : DT;
    const textPx  = wallPx + dir * effectiveDT;

    const sorted = [...comps].sort((a, b) => a.positionIn - b.positionIn);
    const segs = [];
    let cursor = 0;
    for (const c of sorted) {
      if (c.positionIn > cursor + 0.5)
        segs.push({ startIn: cursor, endIn: c.positionIn, isComp: false, comp: null });
      segs.push({ startIn: c.positionIn, endIn: c.positionIn + c.widthIn, isComp: true, comp: c });
      cursor = c.positionIn + c.widthIn;
    }
    if (cursor < wLen - 0.5)
      segs.push({ startIn: cursor, endIn: wLen, isComp: false, comp: null });

    const bpts = [axS, ...segs.map(s => axS + s.endIn * sc)];
    const tk   = (bp) => horiz
      ? <line x1={bp} y1={chainPx - 3.5} x2={bp} y2={chainPx + 3.5} stroke="rgba(44,62,80,0.80)" strokeWidth="1.4" />
      : <line x1={chainPx - 3.5} y1={bp} x2={chainPx + 3.5} y2={bp} stroke="rgba(44,62,80,0.80)" strokeWidth="1.4" />;

    return (
      <g key={wallId}>
        {horiz
          ? <line x1={axS} y1={chainPx} x2={axE} y2={chainPx} stroke="rgba(44,62,80,0.45)" strokeWidth="1.0" />
          : <line x1={chainPx} y1={axS} x2={chainPx} y2={axE} stroke="rgba(44,62,80,0.45)" strokeWidth="1.0" />
        }
        {bpts.map((bp, i) => <React.Fragment key={i}>{tk(bp)}</React.Fragment>)}
        {segs.map((seg, i) => {
          const a   = axS + seg.startIn * sc;
          const b   = axS + seg.endIn   * sc;
          const mid = (a + b) / 2;
          if (b - a < MIN_LBL) return null;
          const lIn   = seg.endIn - seg.startIn;
          const color = seg.isComp ? getColor(seg.comp) : GAP_CLR;
          const fs    = seg.isComp ? '10.5' : '9.5';
          const op    = seg.isComp ? 1 : 0.88;
          return horiz
            ? <text key={i} x={mid} y={textPx} textAnchor="middle"
                fontFamily="'IBM Plex Mono', monospace" fontSize={fs} fill={color} opacity={op}>
                {fmtDim(lIn)}
              </text>
            : <text key={i} x={textPx} y={mid} textAnchor="middle" dominantBaseline="middle"
                fontFamily="'IBM Plex Mono', monospace" fontSize={fs} fill={color} opacity={op}
                transform={`rotate(-90,${textPx},${mid})`}>
                {fmtDim(lIn)}
              </text>;
        })}
      </g>
    );
  };

  // ── Opening dimension chains (middle tier, DL=28) ───────────────────────
  const renderOpeningDims = (DL=28, DT=33) => {
    if (!openings.length) return null;
    return ORDER.map(wallId => {
      const wallComps = openings.filter(o => o.wall === wallId);
      if (!wallComps.length) return null;
      return renderWallChain(wallId, wallComps, (o) => o.type === 'door' ? '#c0703a' : '#5c82b0', DL, DT);
    });
  };

  // ── Appliance dimension chains (inner tier, DL=12) ──────────────────────
  const renderApplianceDims = (DL=12, DT=17) => {
    if (!appliances.length) return null;
    return ORDER.map(wallId => {
      const wallComps = appliances.filter(a => a.wall === wallId);
      if (!wallComps.length) return null;
      return renderWallChain(wallId, wallComps, (a) => APP_CFG[a.type].color, DL, DT);
    });
  };

  // ── SVG ─────────────────────────────────────────────────────────────────────
  return (
    <svg viewBox={`0 0 ${SVG_W} ${SVG_H}`} style={{ display: 'block', width: '100%' }}>
      <defs>
        <pattern id="pdf-hatch-base"  patternUnits="userSpaceOnUse" width="7" height="7" patternTransform="rotate(45)">
          <line x1="0" y1="0" x2="0" y2="7" stroke="#c0703a" strokeWidth="0.8" opacity="0.55" />
        </pattern>
        <pattern id="pdf-hatch-upper" patternUnits="userSpaceOnUse" width="7" height="7" patternTransform="rotate(45)">
          <line x1="0" y1="0" x2="0" y2="7" stroke="#8c9a86" strokeWidth="0.8" opacity="0.55" />
        </pattern>
      </defs>

      {/* Room fill */}
      <rect x={PAD} y={PAD} width={roomPxW} height={roomPxH} fill="var(--as-paper)" />

      {/* Base boundary — dim chain at dimOffset=56 */}
      {renderBoundary(baseData, baseCabPxX, baseCabPxY, '#c0703a', 'pdf-hatch-base', true, 56)}
      {renderOpeningCuts('base')}
      {renderApplianceCuts('base')}

      {/* Upper boundary — dim chain at dimOffset=76, outside base to avoid collision */}
      {renderBoundary(upperData, upperCabPxX, upperCabPxY, '#8c9a86', 'pdf-hatch-upper', true, 76)}
      {renderOpeningCuts('upper')}
      {renderApplianceCuts('upper')}

      {/* Wall lines */}
      {renderWallLines()}

      {/* Openings — middle dim tier (DL=28, DT=33) */}
      {renderOpeningSymbols()}
      {renderOpeningDims(28, 33)}

      {/* Appliances — inner dim tier (DL=12, DT=17) */}
      {renderApplianceSymbols()}
      {renderApplianceDims(12, 17)}

      {/* Room label */}
      <text x={PAD+roomPxW/2} y={PAD+roomPxH/2-7}  textAnchor="middle" fontFamily="'IBM Plex Mono', monospace" fontSize="10" fill="#b8bfc5">{fmtDim(lengthIn)}</text>
      <text x={PAD+roomPxW/2} y={PAD+roomPxH/2+8}  textAnchor="middle" fontFamily="'IBM Plex Mono', monospace" fontSize="10" fill="#b8bfc5">{fmtDim(widthIn)}</text>
    </svg>
  );
}

// ── PdfPreview — full 1-page layout ──────────────────────────────────────────
function PdfPreview({ f, unit }) {
  const { SectionLabel, SpecRow, Badge, Button } = window.AlignSpaceDesignSystem_d3d6d6;

  const lengthIn = parseFloat(f.length) || 0;
  const widthIn  = parseFloat(f.width)  || 0;
  const hasFloorPlan = !!(lengthIn && widthIn);
  const today = new Date().toLocaleDateString('en-CA');

  const fmtL = (v) => {
    const n = parseFloat(v) || 0;
    if (!n) return '—';
    return unit === 'mm' ? `${Math.round(n * 25.4)} mm` : `${n} in`;
  };

  const footprint = lengthIn && widthIn
    ? (unit === 'mm' ? `${Math.round(lengthIn*25.4)} × ${Math.round(widthIn*25.4)} mm` : `${lengthIn} × ${widthIn} in`)
    : '—';

  const floorArea = lengthIn && widthIn
    ? (unit === 'mm' ? `${(lengthIn*widthIn*0.000645).toFixed(2)} m²` : `${(lengthIn*widthIn/144).toFixed(1)} ft²`)
    : '—';

  const cabDepthDisplay = f.cabDepth
    ? (unit === 'mm' ? `${f.cabDepth} mm` : `${Math.round(parseFloat(f.cabDepth)/25.4)} in`)
    : '—';

  const upperClearDisplay = f.upperClear
    ? (unit === 'mm' ? `${Math.round(parseFloat(f.upperClear)*25.4)} mm` : `${f.upperClear} in`)
    : '18 in';

  const openingsList = (f.openings || []).map(o => {
    const idx = (f.openings||[]).filter(x => x.type === o.type).indexOf(o) + 1;
    const w   = unit === 'mm' ? `${Math.round(o.widthIn*25.4)} mm` : `${Math.round(o.widthIn)}"`;
    const clr = o.clearanceIn ? (unit === 'mm' ? ` clr ${Math.round(o.clearanceIn*25.4)} mm` : ` clr ${Math.round(o.clearanceIn)}"`) : '';
    return { label: `${o.type === 'door' ? 'D' : 'W'}${idx}`, value: `${o.wall}  ${w}${clr}` };
  });

  const appList = (f.appliances || []).map(a => {
    const w     = unit === 'mm' ? `${Math.round(a.widthIn*25.4)} mm` : `${Math.round(a.widthIn)}"`;
    const label = a.type === 'dishwasher' ? 'DW' : a.type.charAt(0).toUpperCase() + a.type.slice(1);
    return { label, value: `${a.wall}  ${w}` };
  });

  const subHd = { fontFamily: 'var(--font-mono)', fontSize: '8px', letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: '6px' };

  // Compact label/value row used exclusively inside the titleblock — full control over sizing
  const TBRow = ({ label, value }) => (
    <div style={{ display: 'flex', justifyContent: 'space-between', gap: '6px', padding: '1.5px 0', lineHeight: 1.4 }}>
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: '9px', color: 'var(--text-muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{label}</span>
      {value ? <span style={{ fontFamily: 'var(--font-mono)', fontSize: '9px', color: 'var(--text-secondary)', textAlign: 'right', whiteSpace: 'nowrap', flexShrink: 0 }}>{value}</span> : null}
    </div>
  );

  // Hide paper's own siblings (intro text, actions) AND all non-ancestor page siblings, then print
  const handlePrint = () => {
    const paper = document.querySelector('.as-pdf-paper');
    if (!paper) { window.print(); return; }
    const ancestors = new Set();
    let node = paper.parentElement;
    while (node && node !== document.body) { ancestors.add(node); node = node.parentElement; }
    const hidden = [];
    // Hide direct siblings of the paper (intro heading, action buttons)
    Array.from(paper.parentElement?.children || []).forEach(sib => {
      if (sib !== paper) { hidden.push([sib, sib.style.display]); sib.style.display = 'none'; }
    });
    // Hide non-ancestor siblings further up the tree (other page sections)
    ancestors.forEach(anc => {
      Array.from(anc.parentElement?.children || []).forEach(sib => {
        if (!ancestors.has(sib)) { hidden.push([sib, sib.style.display]); sib.style.display = 'none'; }
      });
    });
    window.print();
    hidden.forEach(([el, d]) => { el.style.display = d; });
  };

  const openInNewTab = () => {
    const paper = document.querySelector('.as-pdf-paper');
    if (!paper) return;
    const cs = getComputedStyle(document.documentElement);
    const varNames = [
      '--as-paper','--as-navy','--as-mist','--as-slate','--as-terracotta',
      '--border-hairline','--border-default','--surface-raised','--surface-base',
      '--text-primary','--text-secondary','--text-muted',
      '--font-mono','--font-display','--font-text',
      '--text-h2','--text-sm','--text-xs','--text-2xs','--leading-relaxed','--section-y',
    ];
    const cssVars = ':root{' + varNames.map(v => `${v}:${cs.getPropertyValue(v).trim()}`).join(';') + '}';
    const inlineStyles = Array.from(document.querySelectorAll('style')).map(s => s.textContent).join('\n');
    // Resolve relative src attributes to absolute URLs so the blob can load them
    let paperHtml = paper.outerHTML;
    paperHtml = paperHtml.replace(/src="((?!data:)[^"]+)"/g, (_, src) => {
      try { return `src="${new URL(src, window.location.href).href}"`; }
      catch { return `src="${src}"`; }
    });
    const html = `<!DOCTYPE html><html><head><meta charset="utf-8"><style>body{margin:0;padding:40px;background:#b0b0b0;min-height:100vh;box-sizing:border-box}${cssVars}\n${inlineStyles}</style></head><body>${paperHtml}</body></html>`;
    const blob = new Blob([html], {type:'text/html'});
    window.open(URL.createObjectURL(blob), '_blank');
  };

  return (
    <section id="pdf-preview" style={{ background: 'var(--surface-raised)', padding: 'var(--section-y) 0' }}>
      <div className="as-wrap">

        <div style={{ maxWidth: '56ch', marginBottom: '40px' }}>
          <SectionLabel>Layout PDF Preview</SectionLabel>
          <h2 style={{ fontFamily: 'var(--font-display)', fontSize: 'var(--text-h2)', color: 'var(--text-primary)', margin: '16px 0 12px' }}>
            Your parametric audit brief.
          </h2>
          <p style={{ fontSize: 'var(--text-sm)', lineHeight: 'var(--leading-relaxed)', color: 'var(--text-muted)' }}>
            {f.email
              ? <>This is the document we're sending to <strong style={{ color: 'var(--text-primary)', fontWeight: 'normal' }}>{f.email}</strong>.</>
              : 'This is the document we\'re generating for your audit.'
            }
          </p>
        </div>

        {/* Paper container */}
        <div className="as-pdf-paper" style={{ background: '#fff', maxWidth: '760px', boxShadow: '0 4px 32px rgba(0,0,0,0.10)', border: '1px solid var(--border-hairline)' }}>

          {/* Header strip */}
          <div style={{ background: '#2c3a47', padding: '16px 32px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: '14px' }}>
              <img src="../../assets/logos/Logo002.png" alt="AlignSpace" style={{ height: '28px', width: 'auto', boxShadow: '0 0 0 1px rgba(220,221,223,0.22)' }} />
              <span style={{ fontFamily: 'var(--font-display)', fontSize: '16px', color: 'var(--as-mist)', letterSpacing: '0.02em' }}>AlignSpace</span>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: '9px', letterSpacing: '0.12em', textTransform: 'uppercase', color: 'rgba(220,221,223,0.85)', marginBottom: '3px' }}>Parametric Layout Audit</div>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: '9px', color: 'rgba(220,221,223,0.55)' }}>{today}</div>
            </div>
          </div>

          {/* Floor plan — full width */}
          <div style={{ padding: '24px 32px 12px' }}>
            {hasFloorPlan
              ? <PdfFloorPlan f={f} unit={unit} />
              : (
                <div style={{ border: '1px solid var(--border-default)', background: 'var(--surface-raised)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', gap: '8px', minHeight: '240px' }}>
                  <span style={{ fontFamily: 'var(--font-mono)', fontSize: '10px', letterSpacing: '0.08em', color: 'var(--text-muted)' }}>NO FLOOR PLAN</span>
                  <span style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-xs)', color: 'var(--text-muted)' }}>Complete the room builder to see the plan.</span>
                </div>
              )
            }
            {hasFloorPlan && (
              <p style={{ fontFamily: 'var(--font-mono)', fontSize: '8px', color: 'var(--text-muted)', marginTop: '6px', letterSpacing: '0.06em', lineHeight: 1.6 }}>
                Approximate — confirm all dimensions on site.
              </p>
            )}
          </div>

          {/* Titleblock — fixed 4-col grid, never reflows */}
          <div className="as-pdf-titleblock" style={{ borderTop: '2px solid var(--border-default)', background: 'rgba(44,62,80,0.025)', padding: '14px 32px 16px' }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: '8px', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--text-muted)', paddingBottom: '10px', marginBottom: '10px', borderBottom: '1px solid var(--border-hairline)' }}>Layout Brief</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '0 20px', alignItems: 'stretch' }}>

              {/* Col 1: Room + Cabinets */}
              <div>
                <div style={subHd}>Room</div>
                <TBRow label="Footprint"  value={footprint} />
                <TBRow label="Ceiling"    value={fmtL(f.ceiling)} />
                <TBRow label="Floor area" value={floorArea} />
                <div style={{ height: '10px' }} />
                <div style={subHd}>Cabinets</div>
                <TBRow label="Depth"       value={cabDepthDisplay} />
                <TBRow label="Upper clr."  value={upperClearDisplay} />
                <TBRow label="Width pref." value={f.widthPref || '—'} />
                <TBRow label="Spice cab."  value={f.spiceCab ? 'yes' : '—'} />
                <TBRow label="Island"      value={f.island ? 'requested' : '—'} />
              </div>

              {/* Col 2: Openings */}
              <div>
                <div style={subHd}>Openings</div>
                {openingsList.length > 0
                  ? openingsList.map((o, i) => <TBRow key={i} label={o.label} value={o.value} />)
                  : <TBRow label="—" value="" />
                }
              </div>

              {/* Col 3: Appliances + Client pinned to bottom */}
              <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
                <div>
                  <div style={subHd}>Appliances</div>
                  {appList.length > 0
                    ? appList.map((a, i) => <TBRow key={i} label={a.label} value={a.value} />)
                    : <TBRow label="—" value="" />
                  }
                </div>
                {f.name && (
                  <div style={{ marginTop: '6px' }}>
                    <div style={subHd}>Client</div>
                    <div style={{ fontFamily: 'var(--font-mono)', fontSize: '9px', lineHeight: 1.4 }}>
                      <span style={{ color: 'var(--text-secondary)' }}>{f.name}</span>
                      {f.city  && <span style={{ color: 'var(--text-muted)' }}> · {f.city}</span>}
                      {f.email && <span style={{ color: 'var(--text-muted)' }}> · {f.email}</span>}
                    </div>
                  </div>
                )}
              </div>

            </div>

            {/* Notes + Drawings — full width, below grid */}
            {(f.notes || f.drawingsLink) && (
              <div style={{ marginTop: '12px', paddingTop: '12px', borderTop: '1px solid var(--border-hairline)', display: 'grid', gridTemplateColumns: f.notes && f.drawingsLink ? '1fr 1fr' : '1fr', gap: '0 20px' }}>
                {f.notes && (
                  <div>
                    <div style={subHd}>Notes</div>
                    <div style={{ fontFamily: 'var(--font-mono)', fontSize: '9px', color: 'var(--text-secondary)', lineHeight: 1.5, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>{f.notes}</div>
                  </div>
                )}
                {f.drawingsLink && (
                  <div>
                    <div style={subHd}>Drawings</div>
                    <div style={{ fontFamily: 'var(--font-mono)', fontSize: '9px', color: 'var(--text-muted)', lineHeight: 1.5, wordBreak: 'break-all' }}>{f.drawingsLink}</div>
                  </div>
                )}
              </div>
            )}

          </div>

          {/* Footer */}
          <div style={{ borderTop: '1px solid var(--border-hairline)', padding: '12px 32px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: '8px', color: 'var(--text-muted)', letterSpacing: '0.06em' }}>
              alignspace.ca &nbsp;·&nbsp; ali@alignspace.ca &nbsp;·&nbsp; Toronto · York Region · GTA
            </span>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: '8px', color: 'rgba(44,62,80,0.22)' }}>© 2026 AlignSpace</span>
          </div>
        </div>

        {/* Actions */}
        <div style={{ marginTop: '20px', display: 'flex', alignItems: 'center', gap: '16px' }}>
          <Button variant="secondary" size="sm" onClick={handlePrint} iconLeft={<i data-lucide="printer" style={{ width: 14, height: 14 }}></i>}>Print</Button>
          <Button variant="secondary" size="sm" onClick={openInNewTab}>Debug ↗</Button>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--text-2xs)', color: 'var(--text-muted)' }}>PDF email delivery — coming soon.</span>
        </div>

      </div>
    </section>
  );
}
window.PdfPreview = PdfPreview;
