/* eslint-disable */
/* cityform — Commission (Make Yours) — Brand v3
   The bespoke flow for cities outside the twelve. Same system:
   9 cm, 1:11000, one signature, one landmark. */

const STEPS = ['Search', 'Adjust', 'Label', 'Confirm'];

/* Convert the storefront's % bbox (within a 2.5 km canvas centred on `chosen`)
   into the real WGS84 lat/lng bounds that /api/generate expects. The visual
   StyledMap is stylised — the customer is choosing a bbox spatially, the
   actual EA LIDAR / OSM survey data lands at generate time. */
window.bboxToWGS84 = function bboxToWGS84(chosen, bbox, opts = {}) {
  const CANVAS_M = 2500;
  const sizeM = (bbox.w / 100) * CANVAS_M;
  const dxM   = ((bbox.x + bbox.w / 2) - 50) / 100 * CANVAS_M;
  const dyM   = ((bbox.y + bbox.h / 2) - 50) / 100 * CANVAS_M;
  const mPerDegLat = 111320;
  const mPerDegLng = 111320 * Math.cos((chosen.lat * Math.PI) / 180);
  const centreLat = chosen.lat - dyM / mPerDegLat;
  const centreLng = chosen.lng + dxM / mPerDegLng;
  const halfLat = (sizeM / 2) / mPerDegLat;
  const halfLng = (sizeM / 2) / mPerDegLng;
  const safeName = (chosen.label || 'commission')
    .split(',')[0].split('·')[0].trim().replace(/[^a-zA-Z0-9]+/g, '_').slice(0, 40) || 'commission';
  return {
    lat_min: centreLat - halfLat,
    lat_max: centreLat + halfLat,
    lng_min: centreLng - halfLng,
    lng_max: centreLng + halfLng,
    angle_deg: bbox.r || 0,
    print_mm: 90,
    z_exag: opts.exag || 1.0,
    plinth_mm: 2.0,
    location_name: safeName,
  };
};

// One canonical coordinate everywhere — search, adjust, engraved label.
// Format is fixed by the label Design System v1.1 §5: DD.DDD° {N|S} ·
// DD.DDD° {E|W} (3 decimals, middle dot). The value is always the centre
// of the 1 km square (bbox→WGS84 mid-point), so the readout the customer
// picks is exactly what gets engraved.
window.fmtCoord = function fmtCoord(lat, lng) {
  return `${Math.abs(lat).toFixed(3)}° ${lat >= 0 ? 'N' : 'S'} · ${Math.abs(lng).toFixed(3)}° ${lng >= 0 ? 'E' : 'W'}`;
};
window.cropCentre = function cropCentre(chosen, bbox) {
  const w = window.bboxToWGS84(chosen, bbox);
  return { lat: (w.lat_min + w.lat_max) / 2, lng: (w.lng_min + w.lng_max) / 2 };
};

function MakeYoursPage({ go, t, addToCart }) {
  const [step, setStep] = React.useState(0);
  const [query, setQuery] = React.useState('');
  const [chosen, setChosen] = React.useState(null);
  const [bbox, setBbox] = React.useState({ x:34, y:34, w:32, h:32, r:0 });
  const [exag, setExag] = React.useState(1.0);
  const [config, setConfig] = React.useState({
    accent: 'vermilion',
    landmarkId: 'parkhill',
    landmarkLabel: '',
    labelTitle: '',
    labelSubline: '',
    showCoords: true,
  });
  // Real OSM geometry + coverage verdict for the chosen point. Fetched once
  // here so both StepAdjust (live map) and StepConfirm (generate guard) share it.
  const [area, setArea] = React.useState(null);
  const [areaLoading, setAreaLoading] = React.useState(false);

  React.useEffect(() => {
    if (!chosen) { setArea(null); return; }
    const ctrl = new AbortController();
    setArea(null);
    setAreaLoading(true);
    fetch('/api/storefront/area_preview', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ lat: chosen.lat, lng: chosen.lng }),
      signal: ctrl.signal,
    })
      .then(r => r.ok ? r.json() : Promise.reject(r.status))
      .then(d => setArea(d))
      .catch(() => { /* leave area null → procedural fallback */ })
      .finally(() => setAreaLoading(false));
    return () => ctrl.abort();
  }, [chosen && chosen.lat, chosen && chosen.lng]);

  const coverageOk = !area || area.in_england;

  return (
    <div style={{ background:'var(--mist)', minHeight:'calc(100vh - 72px)' }}>
      {/* Stepper */}
      <div style={{ borderBottom:'1px solid var(--line)', background:'var(--bone)' }}>
        <div className="container" style={{ height:64, display:'flex', alignItems:'center', gap:24 }}>
          <div className="label" style={{ flexShrink:0 }}>Commission</div>
          <div style={{ display:'flex', alignItems:'center', flex:1, minWidth:0 }}>
            {STEPS.map((s, i) => (
              <React.Fragment key={s}>
                <button onClick={() => setStep(i)}
                  style={{
                    display:'flex', alignItems:'center', gap:10, flexShrink:0,
                    color: i <= step ? 'var(--ink)' : 'var(--stone)',
                  }}>
                  <span style={{
                    width:22, height:22,
                    border:`1.5px solid ${i <= step ? 'var(--ink)' : 'var(--line-strong)'}`,
                    background: i < step ? 'var(--ink)' : 'transparent',
                    color: i < step ? 'var(--mist)' : 'inherit',
                    display:'flex', alignItems:'center', justifyContent:'center',
                    fontSize:10, fontWeight:600, fontVariantNumeric:'tabular-nums',
                  }}>{i < step ? '✓' : (i + 1).toString().padStart(2,'0')}</span>
                  <span style={{ fontSize:11, fontWeight: i === step ? 600 : 500, letterSpacing:'0.18em', textTransform:'uppercase' }}>{s}</span>
                </button>
                {i < STEPS.length - 1 && (
                  <span style={{ flex:1, minWidth:18, height:1, background: i < step ? 'var(--ink)' : 'var(--line)', margin:'0 14px' }}/>
                )}
              </React.Fragment>
            ))}
          </div>
          <button className="btn-link" onClick={() => go('home')} style={{ fontSize:12, whiteSpace:'nowrap', flexShrink:0 }}>Save & exit</button>
        </div>
      </div>

      {step === 0 && <StepSearch query={query} setQuery={setQuery} chosen={chosen} setChosen={setChosen} next={() => setStep(1)} />}
      {step === 1 && <StepAdjust chosen={chosen} bbox={bbox} setBbox={setBbox} exag={exag} setExag={setExag} area={area} areaLoading={areaLoading} coverageOk={coverageOk} t={t} back={() => setStep(0)} next={() => setStep(2)} />}
      {step === 2 && <StepSignature chosen={chosen} bbox={bbox} t={t} config={config} setConfig={setConfig} back={() => setStep(1)} next={() => setStep(3)} />}
      {step === 3 && <StepConfirm chosen={chosen} bbox={bbox} exag={exag} config={config} area={area} t={t} back={() => setStep(2)} addToCart={addToCart} go={go} />}
    </div>
  );
}

/* ────────────────────────────── STEP 0 · SEARCH */
function StepSearch({ query, setQuery, chosen, setChosen, next }) {
  const filtered = window.LOCATIONS.filter(loc =>
    !query || loc.q.toLowerCase().includes(query.toLowerCase()) ||
    loc.label.toLowerCase().includes(query.toLowerCase())
  );

  // Raw "lat, lng" entry — full freedom to drop a point anywhere on Earth.
  const cm = query.trim().match(/^\s*(-?\d{1,2}(?:\.\d+)?)\s*,\s*(-?\d{1,3}(?:\.\d+)?)\s*$/);
  const coordHit = (() => {
    if (!cm) return null;
    const lat = parseFloat(cm[1]), lng = parseFloat(cm[2]);
    if (Math.abs(lat) > 90 || Math.abs(lng) > 180) return null;
    return {
      q: `coord:${lat},${lng}`,
      label: window.fmtCoord(lat, lng),
      lat, lng,
    };
  })();

  /* Nominatim fallback — only kicks in when:
       - the typed query is ≥3 chars
       - no preset matches (so casual typing on Sheffield/Bath/etc. doesn't hit OSM)
     Debounced 400ms to respect Nominatim's 1 req/sec usage policy.
     `countrycodes=gb` restricts to the UK; the backend's EA LIDAR pipeline
     only covers England, but Nominatim returning Welsh/Scottish hits is
     fine — generate surfaces a clean error if the bbox lands outside coverage. */
  const [remoteHits, setRemoteHits] = React.useState([]);
  const [remoteLoading, setRemoteLoading] = React.useState(false);
  React.useEffect(() => {
    if (!query || query.length < 3) { setRemoteHits([]); setRemoteLoading(false); return; }
    const hasPreset = window.LOCATIONS.some(l =>
      l.q.toLowerCase().includes(query.toLowerCase()) ||
      l.label.toLowerCase().includes(query.toLowerCase())
    );
    if (hasPreset) { setRemoteHits([]); setRemoteLoading(false); return; }
    const ctrl = new AbortController();
    setRemoteLoading(true);
    const t = setTimeout(async () => {
      try {
        const url = `https://nominatim.openstreetmap.org/search?format=json&limit=8&q=${encodeURIComponent(query)}`;
        const r = await fetch(url, { signal: ctrl.signal });
        if (!r.ok) throw new Error(`HTTP ${r.status}`);
        const j = await r.json();
        setRemoteHits(j.map(x => ({
          q: x.display_name,
          label: x.display_name.split(',').slice(0, 2).join(', '),
          lat: parseFloat(x.lat),
          lng: parseFloat(x.lon),
        })));
      } catch (e) {
        if (e.name !== 'AbortError') setRemoteHits([]);
      } finally {
        setRemoteLoading(false);
      }
    }, 400);
    return () => { clearTimeout(t); ctrl.abort(); setRemoteLoading(false); };
  }, [query]);

  return (
    <div className="container" style={{ paddingTop:64, paddingBottom:96 }}>
      <div style={{ maxWidth:760, margin:'0 auto' }}>
        <div className="label" style={{ textAlign:'center', marginBottom:16 }}>Step 01 of 04</div>
        <h1 className="h1" style={{ fontSize:64, textAlign:'center' }}>Where in the world.</h1>
        <p className="body" style={{ textAlign:'center', fontSize:17, color:'var(--stone)', marginTop:16, marginBottom:48, maxWidth:520, marginInline:'auto' }}>
          A postcode, a place name, a landmark. We'll snap a 1 km square around it and scale to 9 cm.
        </p>

        <div style={{
          display:'flex', alignItems:'center', gap:14,
          padding:'18px 24px', background:'var(--bone)',
          border:'1px solid var(--ink)',
        }}>
          <span style={{ color:'var(--stone)' }}>{Icon.search}</span>
          <input value={query} onChange={e => { setQuery(e.target.value); setChosen(null); }}
            placeholder="S1 2HE, Park Hill, Royal Crescent"
            style={{
              flex:1, border:0, background:'none', outline:'none',
              fontFamily:'Inter, sans-serif', fontWeight:500, fontSize:22, color:'var(--ink)',
              letterSpacing:'-0.005em',
            }}/>
          <button className="btn btn-primary" disabled={!chosen}
            onClick={chosen ? next : undefined}>
            Continue &nbsp;{Icon.arrow}
          </button>
        </div>

        {(query || filtered.length > 0) && (
          <div style={{ marginTop:14, background:'var(--bone)', border:'1px solid var(--line)' }}>
            {coordHit && (
              <button onClick={() => { setChosen(coordHit); setQuery(coordHit.label); }}
                style={{
                  display:'flex', width:'100%', alignItems:'center', gap:18, padding:'14px 20px',
                  borderBottom: (filtered.length > 0 || remoteHits.length > 0) ? '1px solid var(--line)' : 'none',
                  background: chosen?.q === coordHit.q ? 'var(--mist)' : 'transparent', textAlign:'left',
                }}>
                {Icon.pin}
                <div style={{ flex:1 }}>
                  <div style={{ fontSize:15, fontWeight:500 }}>{coordHit.label}</div>
                  <div className="caption" style={{ fontSize:10, marginTop:4, letterSpacing:'0.22em' }}>USE THESE COORDINATES</div>
                </div>
                {chosen?.q === coordHit.q && Icon.check}
              </button>
            )}
            {filtered.slice(0, 8).map((loc, i) => (
              <button key={'p-' + i + '-' + loc.q} onClick={() => { setChosen(loc); setQuery(loc.label); }}
                style={{
                  display:'flex', width:'100%', alignItems:'center', gap:18, padding:'14px 20px',
                  borderBottom: i < Math.min(7, filtered.length - 1) ? '1px dotted var(--line-strong)' : 'none',
                  background: chosen?.q === loc.q ? 'var(--mist)' : 'transparent',
                  textAlign:'left',
                }}>
                {Icon.pin}
                <div style={{ flex:1 }}>
                  <div style={{ fontSize:15, fontWeight:500 }}>{loc.label}</div>
                  <div className="caption" style={{ fontSize:10, marginTop:4 }}>
                    {loc.q} &nbsp;·&nbsp; {window.fmtCoord(loc.lat, loc.lng)}
                  </div>
                </div>
                {chosen?.q === loc.q && Icon.check}
              </button>
            ))}
            {(remoteLoading || remoteHits.length > 0) && filtered.length === 0 && (
              <div style={{ padding:'10px 20px', borderTop: filtered.length > 0 ? '1px solid var(--line)' : 'none',
                fontSize:9, letterSpacing:'0.22em', fontWeight:500, color:'var(--stone)', background:'var(--mist)' }}>
                {remoteLoading ? 'SEARCHING OPENSTREETMAP…' : 'FROM OPENSTREETMAP'}
              </div>
            )}
            {remoteHits.slice(0, 6).map((loc, i) => (
              <button key={'r-' + i + '-' + loc.lat + ',' + loc.lng} onClick={() => { setChosen(loc); setQuery(loc.label); }}
                style={{
                  display:'flex', width:'100%', alignItems:'center', gap:18, padding:'14px 20px',
                  borderBottom: i < Math.min(5, remoteHits.length - 1) ? '1px dotted var(--line-strong)' : 'none',
                  background: chosen?.q === loc.q ? 'var(--mist)' : 'transparent',
                  textAlign:'left',
                }}>
                {Icon.pin}
                <div style={{ flex:1 }}>
                  <div style={{ fontSize:15, fontWeight:500 }}>{loc.label}</div>
                  <div className="caption" style={{ fontSize:10, marginTop:4 }}>
                    {window.fmtCoord(loc.lat, loc.lng)}
                  </div>
                </div>
                {chosen?.q === loc.q && Icon.check}
              </button>
            ))}
          </div>
        )}

        {/* Popular */}
        <div style={{ marginTop:64 }}>
          <div className="label" style={{ textAlign:'center', marginBottom:18 }}>Or one of these</div>
          <div style={{ display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap:10 }}>
            {window.LOCATIONS.slice(0, 6).map((loc, i) => (
              <button key={'pop-' + i + '-' + loc.q} onClick={() => { setChosen(loc); setQuery(loc.label); }}
                style={{
                  padding:'16px 18px', textAlign:'left',
                  border:'1px solid var(--line)', background:'var(--bone)',
                }}>
                <div className="h3" style={{ fontSize:16, fontWeight:600 }}>{loc.label}</div>
                <div className="caption" style={{ fontSize:10, marginTop:6 }}>{loc.q}</div>
              </button>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

/* ────────────────────────────── STEP 1 · ADJUST */
function StepAdjust({ chosen, bbox, setBbox, exag, setExag, area, areaLoading, coverageOk, t, back, next }) {
  const [dragging, setDragging] = React.useState(false);
  const wrapRef = React.useRef(null);

  const positionAt = (e) => {
    const rect = wrapRef.current.getBoundingClientRect();
    const cx = ((e.clientX - rect.left) / rect.width) * 100;
    const cy = ((e.clientY - rect.top) / rect.height) * 100;
    setBbox(b => ({ ...b, x: Math.max(0, Math.min(100 - b.w, cx - b.w / 2)), y: Math.max(0, Math.min(100 - b.h, cy - b.h / 2)) }));
  };
  // Click anywhere on the map to recentre the crop there; drag to fine-tune.
  const onMouseDown = (e) => { setDragging(true); positionAt(e); };
  const onMouseUp = () => setDragging(false);
  const onMouseMove = (e) => { if (dragging) positionAt(e); };

  const sizeKm = ((bbox.w / 100) * 2.5).toFixed(2);
  const c = chosen || window.LOCATIONS[0];
  // Live centre of the 1 km square — derived from the same bbox→WGS84
  // math the generator uses, so it tracks every click/drag of the square.
  const _cc = window.cropCentre(c, bbox);
  const cropCoord = window.fmtCoord(_cc.lat, _cc.lng);

  return (
    <div className="container" style={{ paddingTop:40, paddingBottom:64 }}>
      <div style={{ display:'grid', gridTemplateColumns:'1fr 360px', gap:32 }}>
        <div>
          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'baseline', marginBottom:18 }}>
            <div>
              <div className="label">Step 02 of 04 · Adjust the crop</div>
              <h2 className="h1" style={{ fontSize:40, marginTop:10 }}>Drag the square. Rotate to align.</h2>
            </div>
            <div className="caption" style={{ fontSize:11, textAlign:'right' }}>
              <div>{sizeKm} × {sizeKm} KM</div>
              <div style={{ marginTop:4 }}>{bbox.r}° ROTATION</div>
            </div>
          </div>
          <div ref={wrapRef}
            style={{
              height: 580, border:'1px solid var(--ink)', overflow:'hidden',
              cursor: dragging ? 'grabbing' : 'grab', position:'relative',
            }}
            onMouseDown={onMouseDown} onMouseUp={onMouseUp} onMouseLeave={onMouseUp} onMouseMove={onMouseMove}>
            <StyledMap seed={c.q + '-picker'} bbox={bbox} area={area && area.in_england ? area : null}/>
            {areaLoading && (
              <div style={{ position:'absolute', bottom:14, right:14,
                padding:'8px 12px', background:'var(--bone)', border:'1px solid var(--line)',
                fontSize:9, letterSpacing:'0.22em', fontWeight:500, color:'var(--stone)', pointerEvents:'none' }}>
                LOADING REAL MAP…
              </div>
            )}
            <div style={{ position:'absolute', left:'50%', top:'50%', transform:'translate(-50%, -50%)', pointerEvents:'none' }}>
              <div style={{ width:6, height:6, background:'var(--ink)' }}/>
            </div>
            <div style={{ position:'absolute', top:18, left:18, right:18, display:'flex', alignItems:'center', gap:10,
              padding:'12px 16px', background:'var(--bone)', border:'1px solid var(--ink)' }}>
              {Icon.search}
              <span style={{ fontSize:14, fontWeight:500 }}>{c.label}</span>
              <span style={{ marginLeft:'auto' }} className="caption">{cropCoord}</span>
            </div>
            <div style={{ position:'absolute', bottom:14, left:14,
              padding:'8px 12px', background:'var(--ink)', color:'var(--mist)',
              fontSize:10, letterSpacing:'0.22em', fontWeight:500, pointerEvents:'none' }}>
              {dragging ? 'DROP TO SET POSITION' : 'CLICK & DRAG THE SQUARE'}
            </div>
          </div>
        </div>

        {/* Side controls */}
        <div style={{ position:'sticky', top:128, alignSelf:'flex-start' }}>
          <div style={{ background:'var(--bone)', border:'1px solid var(--line)', padding:24 }}>
            <div className="label" style={{ marginBottom:14 }}>Crop size</div>
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:6 }}>
              {[{l:'0.5 km', v:18}, {l:'1.0 km', v:32}, {l:'1.5 km', v:48}].map(opt => (
                <button key={opt.l} onClick={() => setBbox(b => ({ ...b, w: opt.v, h: opt.v }))}
                  style={{
                    padding:'10px 6px', fontSize:11, fontWeight:500,
                    border:`1px solid ${Math.abs(bbox.w - opt.v) < 1 ? 'var(--ink)' : 'var(--line)'}`,
                    background: Math.abs(bbox.w - opt.v) < 1 ? 'var(--mist)' : 'transparent',
                    fontVariantNumeric:'tabular-nums', letterSpacing:'0.06em',
                  }}>{opt.l}</button>
              ))}
            </div>

            <div className="label" style={{ marginTop:24, marginBottom:10 }}>Rotation</div>
            <input type="range" min="-45" max="45" value={bbox.r}
              onChange={e => setBbox(b => ({ ...b, r: Number(e.target.value) }))}
              style={{ width:'100%' }}/>
            <div style={{ display:'flex', justifyContent:'space-between', marginTop:4 }}>
              <span className="caption" style={{ fontSize:9 }}>−45°</span>
              <span style={{ fontSize:11, fontVariantNumeric:'tabular-nums', fontWeight:500 }}>{bbox.r}°</span>
              <span className="caption" style={{ fontSize:9 }}>+45°</span>
            </div>
            <button className="btn btn-ghost" style={{ width:'100%', marginTop:14, height:36, fontSize:11 }} onClick={() => setBbox(b => ({ ...b, r:0 }))}>
              {Icon.rotate}&nbsp; Reset north
            </button>

            <div style={{ marginTop:24, paddingTop:18, borderTop:'1px dotted var(--line-strong)' }}>
              <div style={{ display:'flex', justifyContent:'space-between', marginBottom:10 }}>
                <span className="label">Vertical exaggeration</span>
                <span style={{ fontSize:11, fontVariantNumeric:'tabular-nums', fontWeight:500 }}>{exag.toFixed(1)}×</span>
              </div>
              <input type="range" min="1" max="2.5" step="0.1" value={exag}
                onChange={e => setExag(Number(e.target.value))}
                style={{ width:'100%' }}/>
              <div style={{ display:'flex', justifyContent:'space-between', marginTop:4 }}>
                <span className="caption" style={{ fontSize:9 }}>TRUE</span>
                <span className="caption" style={{ fontSize:9 }}>GENTLE</span>
                <span className="caption" style={{ fontSize:9 }}>DRAMATIC</span>
              </div>
              <p style={{ fontSize:11, color:'var(--stone)', marginTop:10, lineHeight:1.55 }}>
                1.0× for hilly cities (Sheffield, Edinburgh, the Peaks). 1.5–2× for flatter ground (Cambridge, Hull).
              </p>
            </div>

            <div style={{ marginTop:20, paddingTop:18, borderTop:'1px dotted var(--line-strong)' }}>
              <div className="label" style={{ marginBottom:8 }}>Centre coordinate</div>
              <div className="caption" style={{ fontSize:12, color:'var(--ink)' }}>
                {cropCoord}
              </div>
            </div>
          </div>

          {!coverageOk && (
            <div style={{ marginTop:20, padding:'14px 16px', background:'var(--bone)',
              borderLeft:'3px solid var(--vermilion)', fontSize:12, color:'var(--ink)', lineHeight:1.55 }}>
              <strong>{(area && area.region) || 'Outside England'} — not yet available.</strong><br/>
              <span style={{ color:'var(--stone)' }}>
                Commissions currently use Environment Agency LIDAR, which only covers England.
                Pick a place in England to continue. Scotland & Wales are coming.
              </span>
            </div>
          )}

          <div style={{ display:'flex', gap:10, marginTop:20 }}>
            <button className="btn btn-ghost" onClick={back}>{Icon.arrowL}&nbsp; Back</button>
            <button className="btn btn-primary" onClick={coverageOk ? next : undefined}
              disabled={!coverageOk} style={{ flex:1, opacity: coverageOk ? 1 : 0.4 }}>
              Signature &nbsp;{Icon.arrow}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ────────────────────────────── STEP 2 · SIGNATURE
   Pick one of six accents + one landmark icon. */
function StepSignature({ chosen, bbox, t, config, setConfig, back, next }) {
  const c = chosen || window.LOCATIONS[0];
  const placeName = c.label.split(',')[0].split('·')[0].trim();

  const title = (config.labelTitle || placeName).toUpperCase();
  const subline = config.labelSubline.toUpperCase();
  // Same crop-centre coordinate as the Adjust readout (and the engraving).
  const _cc = window.cropCentre(c, bbox);
  const coordStr = window.fmtCoord(_cc.lat, _cc.lng);

  return (
    <div className="container" style={{ paddingTop:40, paddingBottom:64 }}>
      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:64 }}>
        {/* Live label-plate preview */}
        <div style={{ position:'sticky', top:128, alignSelf:'flex-start' }}>
          <div className="label">Live label plate</div>
          <h2 className="h1" style={{ fontSize:40, marginTop:14, marginBottom:32 }}>How yours will read.</h2>
          <div style={{
            background:'var(--bone)', border:'1px solid var(--line)',
            padding:'56px 40px', display:'flex', alignItems:'center', justifyContent:'center',
          }}>
            {/* Exact laser-label artwork — mirrors cache/library/<city>/<city>_laser_label.svg
               (57.6 x 7.6 mm, slate plate #2C313A, etched text #C8CCD0). */}
            <div style={{ width:'100%', aspectRatio:'57.6 / 7.6' }}>
              <svg viewBox="0 0 57.6 7.6" width="100%" height="100%"
                   preserveAspectRatio="xMidYMid meet"
                   style={{ display:'block', filter:'drop-shadow(0 2px 6px rgba(0,0,0,0.18))' }}>
                <rect x="0" y="0" width="57.6" height="7.6" rx="3.8" ry="3.8" fill="#2C313A"/>
                <line x1="33.6" y1="1.9" x2="33.6" y2="5.7" stroke="#C8CCD0" strokeWidth="0.25"/>
                {subline ? (
                  /* Area plate — two-line parent/locality stack (§4, §6) */
                  <>
                    <text x="3" y="2.91" fontFamily="Inter, sans-serif" fontWeight="600"
                          fontSize="1.55" letterSpacing="0.45" fill="#C8CCD0">{title}</text>
                    <text x="3" y="5.81" fontFamily="Inter, sans-serif" fontWeight="600"
                          fontSize="2.0" letterSpacing="0.18" fill="#C8CCD0">{subline}</text>
                  </>
                ) : (
                  /* City plate — single name-1 line (§4, §6) */
                  <text x="3" y="4.70" fontFamily="Inter, sans-serif" fontWeight="600"
                        fontSize="2.4" letterSpacing="0.28" fill="#C8CCD0">{title}</text>
                )}
                {config.showCoords && (
                  <text x="54.6" y="4.46" textAnchor="end" fontFamily="Inter, sans-serif"
                        fontWeight="400" fontSize="1.8" letterSpacing="0.16" fill="#C8CCD0">{coordStr}</text>
                )}
              </svg>
            </div>
          </div>
          <p className="body" style={{ marginTop:20, fontSize:13, color:'var(--stone)', lineHeight:1.6 }}>
            This is the exact laser artwork — what you see is what gets engraved.
          </p>

          {/* SVG modification guide */}
          <div style={{ marginTop:20, border:'1px solid var(--line)', background:'var(--bone)' }}>
            <div style={{ padding:'12px 16px', borderBottom:'1px solid var(--line)' }}>
              <div className="label">Engraving file · &lt;city&gt;_laser_label.svg</div>
            </div>
            <div style={{ padding:'14px 16px', fontSize:11.5, color:'var(--stone)', lineHeight:1.7 }}>
              <div><strong style={{ color:'var(--ink)' }}>Plate</strong> · 57.6 × 7.6 mm, corner radius 3.8 mm · Design system v1.1</div>
              <div style={{ marginTop:8 }}><strong style={{ color:'var(--ink)' }}>Layers</strong></div>
              <div>· <code>#engrave</code> — slate plate <code>#2C313A</code> + etched text <code>#C8CCD0</code></div>
              <div>· <code>#cut</code> — red <code>#FF0000</code> 0.01 outline (the laser cut path)</div>
              <div style={{ marginTop:8 }}><strong style={{ color:'var(--ink)' }}>Variants (§1, §6)</strong></div>
              <div>· No locality → <strong>city plate</strong>: <code>name-1</code> 2.4px @ y=4.70</div>
              <div>· With locality → <strong>area plate</strong>: <code>parent</code> 1.55px @ y=2.91 + <code>locality</code> 2.0px @ y=5.81</div>
              <div style={{ marginTop:8 }}><strong style={{ color:'var(--ink)' }}>Field → element</strong></div>
              <div>· City line → <code>name-1</code> (single) or <code>parent</code> (with locality)</div>
              <div>· Locality → <code>locality</code> (bottom line, x=3)</div>
              <div>· Coordinates → <code>coord</code> (right-aligned, x=54.6, y=4.46)</div>
              <div style={{ marginTop:8, color:'var(--ink)' }}>
                Convert text to paths in Inkscape before importing to xTool XCS.
              </div>
            </div>
          </div>
        </div>

        {/* Right: label-plate editor */}
        <div>
          <div className="label">Step 03 of 04 · Label</div>
          <h2 className="h1" style={{ fontSize:40, marginTop:10 }}>Set the plate.</h2>
          <p className="body" style={{ marginTop:14, fontSize:14, color:'var(--stone)' }}>
            What gets engraved on the base. Defaults to the place you searched — change it to anything you like.
          </p>

          {/* Title */}
          <div style={{ marginTop:32 }}>
            <div className="label" style={{ marginBottom:10 }}>City line (uppercase, max 16)</div>
            <input value={config.labelTitle}
              onChange={e => setConfig(p => ({ ...p, labelTitle: e.target.value.toUpperCase().slice(0,16) }))}
              placeholder={placeName.toUpperCase()}
              style={{
                width:'100%', padding:'14px 16px',
                border:'1px solid var(--ink)', background:'var(--bone)',
                fontFamily:'Inter, sans-serif', fontSize:15, fontWeight:600,
                letterSpacing:'0.04em', textTransform:'uppercase',
              }}/>
          </div>

          {/* Subline */}
          <div style={{ marginTop:24 }}>
            <div className="label" style={{ marginBottom:10 }}>Locality — optional (uppercase, max 18)</div>
            <input value={config.labelSubline}
              onChange={e => setConfig(p => ({ ...p, labelSubline: e.target.value.toUpperCase().slice(0,18) }))}
              placeholder="e.g. KELHAM ISLAND — or leave blank"
              style={{
                width:'100%', padding:'12px 14px',
                border:'1px solid var(--ink)', background:'var(--bone)',
                fontFamily:'Inter, sans-serif', fontSize:13, fontWeight:500,
                letterSpacing:'0.22em', textTransform:'uppercase',
              }}/>
            <div className="caption" style={{ marginTop:8, fontSize:10 }}>
              Add a locality to make it a two-line <strong>area plate</strong> (city small on top,
              locality large below, §4). Leave blank for a single-line <strong>city plate</strong>.
            </div>
          </div>

          {/* Coordinates toggle */}
          <div style={{ marginTop:28 }}>
            <button onClick={() => setConfig(p => ({ ...p, showCoords: !p.showCoords }))}
              style={{
                display:'flex', alignItems:'center', gap:12, padding:'14px 16px', width:'100%',
                border:`1px solid ${config.showCoords ? 'var(--ink)' : 'var(--line)'}`,
                background: config.showCoords ? 'var(--bone)' : 'transparent',
                textAlign:'left',
              }}>
              <span style={{
                width:16, height:16, border:'1.5px solid var(--ink)',
                background: config.showCoords ? 'var(--ink)' : 'transparent',
                color:'var(--mist)', fontSize:10,
                display:'flex', alignItems:'center', justifyContent:'center',
              }}>{config.showCoords ? '✓' : ''}</span>
              <div>
                <div style={{ fontSize:13, fontWeight:600 }}>Engrave coordinates</div>
                <div style={{ fontSize:11, color:'var(--stone)', fontVariantNumeric:'tabular-nums' }}>{coordStr}</div>
              </div>
            </button>
          </div>

          <div style={{ marginTop:40, paddingTop:24, borderTop:'1px solid var(--line)',
            display:'flex', alignItems:'center', justifyContent:'space-between' }}>
            <div>
              <div className="label">Commission from</div>
              <div className="h1" style={{ fontSize:42, marginTop:6 }}>£240</div>
            </div>
            <div style={{ display:'flex', gap:10 }}>
              <button className="btn btn-ghost" onClick={back}>{Icon.arrowL}&nbsp; Back</button>
              <button className="btn btn-primary" onClick={next}>Confirm &nbsp;{Icon.arrow}</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { MakeYoursPage, StepSearch, StepAdjust, StepSignature });
