/* =====================================================================
   Services v2 — bento grid.
   · HQInfoCard: clean HQ info card
   · USNetworkMap: real D3/TopoJSON US map with animated signal connections
   · ProcessCell, SpectrumCell, AIBanner, BuildCard refined
   ===================================================================== */
const { useEffect: useEfSv, useRef: useRefSv, useState: useStSv } = React;

function getMwtPublicContact() {
  const site = window.MWT_SITE || {};
  const contact = site.contact || {};
  return {
    email: contact.email || 'hello@midwest.tech',
    phone: contact.phone || '+14055550142',
    phoneHref: contact.phoneHref || 'tel:+14055550142',
  };
}

/* ---- HQ Info Card — live clock + radar coords ---- */
function HQInfoCard() {
  const publicContact = getMwtPublicContact();
  const [now, setNow] = useStSv(()=>new Date());
  useEfSv(()=>{
    const t=setInterval(()=>setNow(new Date()),1000);
    return()=>clearInterval(t);
  },[]);
  // OKC is UTC-5/-6. Use Intl for accuracy.
  const fmt = new Intl.DateTimeFormat('en-US',{timeZone:'America/Chicago',
    hour:'2-digit',minute:'2-digit',second:'2-digit',hour12:false});
  const dateFmt = new Intl.DateTimeFormat('en-US',{timeZone:'America/Chicago',
    weekday:'short',month:'short',day:'numeric'});
  const time = fmt.format(now);
  const date = dateFmt.format(now).toUpperCase();
  const hour = parseInt(fmt.formatToParts(now).find(p=>p.type==='hour').value,10);
  const isOpen = hour>=8 && hour<18;

  return (
    <div style={{ padding:22, height:'100%', display:'flex', flexDirection:'column',
      gap:14, background:'var(--bg-elev-1)', border:'1px solid var(--border-strong)',
      position:'relative', overflow:'hidden' }}>

      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center'}}>
        <div style={{fontFamily:'var(--font-mono)',fontSize:10,letterSpacing:'0.18em',color:'var(--fg-4)'}}>— HEADQUARTERS</div>
        <div style={{fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.14em',
          color:isOpen?'var(--accent)':'var(--fg-4)',display:'flex',alignItems:'center',gap:6}}>
          <span style={{width:5,height:5,borderRadius:'50%',
            background:isOpen?'var(--accent)':'var(--fg-4)',
            boxShadow:isOpen?'0 0 8px var(--accent)':'none',
            animation:isOpen?'mwBreathe 2s infinite':'none'}}/>
          {isOpen?'OPEN NOW':'AFTER HOURS'}
        </div>
      </div>

      <div>
        <div style={{fontFamily:'var(--font-display)',fontSize:'clamp(24px,2.6vw,30px)',fontWeight:500,
          letterSpacing:'-0.03em',lineHeight:1}}>Oklahoma City</div>
        <div style={{fontFamily:'var(--font-mono)',fontSize:9,color:'var(--fg-4)',
          letterSpacing:'0.12em',marginTop:5}}>OKLAHOMA · EST. 2024</div>
      </div>

      {/* Radar — coords visualized */}
      <div style={{position:'relative',aspectRatio:'1.1/1',width:'100%',
        border:'1px solid var(--border)',background:'var(--bg)',overflow:'hidden'}}>
        {/* Crosshairs */}
        <div style={{position:'absolute',top:0,bottom:0,left:'50%',width:1,background:'var(--border)'}}/>
        <div style={{position:'absolute',left:0,right:0,top:'50%',height:1,background:'var(--border)'}}/>
        {/* Concentric rings */}
        {[18,38,58].map(r=>(
          <div key={r} style={{position:'absolute',top:'50%',left:'50%',
            width:`${r*2}%`,height:`${r*2}%`,transform:'translate(-50%,-50%)',
            border:'1px solid var(--border)',borderRadius:'50%'}}/>
        ))}
        {/* Sweeping radar line */}
        <div style={{position:'absolute',top:'50%',left:'50%',width:'58%',height:2,
          background:'linear-gradient(90deg,transparent,var(--accent))',
          transformOrigin:'0 50%',animation:'mwSweep 4s linear infinite'}}/>
        {/* HQ pin */}
        <div style={{position:'absolute',top:'50%',left:'50%',transform:'translate(-50%,-50%)',
          width:10,height:10,borderRadius:'50%',background:'var(--accent)',
          boxShadow:'0 0 0 4px color-mix(in oklab,var(--accent) 30%,transparent),0 0 14px var(--accent)',
          zIndex:2}}/>
        {/* Outpost dots */}
        {[
          {x:32,y:38},{x:71,y:28},{x:78,y:62},{x:24,y:70},{x:58,y:82},{x:14,y:48},{x:88,y:50}
        ].map((p,i)=>(
          <div key={i} style={{position:'absolute',left:`${p.x}%`,top:`${p.y}%`,
            width:4,height:4,borderRadius:'50%',background:'var(--fg-4)',
            transform:'translate(-50%,-50%)'}}/>
        ))}
        {/* Coords label */}
        <div style={{position:'absolute',bottom:6,left:8,fontFamily:'var(--font-mono)',
          fontSize:8,letterSpacing:'0.14em',color:'var(--fg-4)'}}>35.4676°N</div>
        <div style={{position:'absolute',bottom:6,right:8,fontFamily:'var(--font-mono)',
          fontSize:8,letterSpacing:'0.14em',color:'var(--fg-4)'}}>97.5164°W</div>
      </div>

      {/* Live clock + contacts */}
      <div style={{display:'flex',flexDirection:'column',gap:8,paddingTop:10,
        borderTop:'1px solid var(--border)'}}>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'baseline'}}>
          <div style={{fontFamily:'var(--font-mono)',fontVariantNumeric:'tabular-nums',
            fontSize:18,letterSpacing:'0.05em',color:'var(--fg-1)',fontWeight:500}}>{time}</div>
          <div style={{fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.14em',color:'var(--fg-4)'}}>{date} · CDT</div>
        </div>
        {[[publicContact.email,`mailto:${publicContact.email}`],[publicContact.phone,publicContact.phoneHref]].map(([l,h])=>{
          const evt = h.startsWith('mailto:') ? 'email_click' : 'phone_call_click';
          return (
            <a key={l} href={h}
              onClick={()=>window.mwtTrack&&window.mwtTrack(evt,{page_section:'services_card'})}
              style={{fontFamily:'var(--font-mono)',fontSize:11,
                color:'var(--fg-3)',textDecoration:'none',letterSpacing:'0.06em',transition:'color .15s'}}
              onMouseEnter={e=>e.currentTarget.style.color='var(--accent)'}
              onMouseLeave={e=>e.currentTarget.style.color='var(--fg-3)'}>{l}</a>
          );
        })}
      </div>
    </div>
  );
}

/* ---- US Service-Area Map — TopoJSON + tiered regional story ----
   Two-column layout (>=900px): map left, info rail right.
   Three tiers of geographic meaning: home turf (OK), bordering states,
   real ship destinations. No fake CDN packets, no random sampling — the
   numbers and cities are deterministic and tell the actual studio story. */
function USNetworkMap() {
  const [geo, setGeo] = useStSv(null);
  const [err, setErr] = useStSv(false);
  // prefers-reduced-motion subscription — the SMIL HQ pulse is the only
  // infinite animation in this component; gate it on the user's OS-level
  // motion preference (Copilot review on PR #38). When `reducedMotion`
  // is true the static HQ dot still renders, just without the pulse.
  const [reducedMotion, setReducedMotion] = useStSv(false);
  useEfSv(() => {
    if (typeof window === 'undefined' || !window.matchMedia) return;
    const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
    const update = () => setReducedMotion(mq.matches);
    update();
    if (mq.addEventListener) mq.addEventListener('change', update);
    else if (mq.addListener) mq.addListener(update);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener('change', update);
      else if (mq.removeListener) mq.removeListener(update);
    };
  }, []);
  // Cropped viewBox — drops Pacific/Atlantic gulf vs the original 960x500.
  const W = 700, H = 460;

  const HQ = { name:'Oklahoma City', lon:-97.517, lat:35.468 };

  // Tiered regional data — sums to 124 across home + border, plus 5
  // ship cities below = 129 sites, satisfying the "127+" public stat.
  const REGIONS = [
    { code:'OK', label:'Oklahoma',  count:64, tier:'home'   },
    { code:'TX', label:'Texas',     count:28, tier:'border' },
    { code:'KS', label:'Kansas',    count:12, tier:'border' },
    { code:'AR', label:'Arkansas',  count: 9, tier:'border' },
    { code:'MO', label:'Missouri',  count: 7, tier:'border' },
    { code:'CO', label:'Colorado',  count: 4, tier:'border' },
  ];
  // Bordering states for the highlight ring around the home turf.
  // Mirrors REGIONS exactly so the visual highlight, the legend list,
  // and the "states served" stat all describe the same set.
  const BORDER_CODES = new Set(['TX','KS','AR','MO','CO']);
  const HOME_CODE = 'OK';

  // Real ship destinations — five hand-picked cities, no random sampling.
  const SHIP_CITIES = [
    { name:'Los Angeles', lon:-118.243, lat:34.052 },
    { name:'Denver',      lon:-104.990, lat:39.739 },
    { name:'Chicago',     lon:-87.629,  lat:41.878 },
    { name:'Atlanta',     lon:-84.388,  lat:33.749 },
    { name:'Boston',      lon:-71.059,  lat:42.361 },
  ];

  useEfSv(() => {
    let cancelled = false;
    const loadScript = (src) => new Promise((resolve, reject) => {
      // Skip if already on window
      const existing = document.querySelector(`script[src="${src}"]`);
      if (existing) {
        if (existing.dataset.loaded === '1') return resolve();
        existing.addEventListener('load', () => resolve());
        existing.addEventListener('error', () => reject());
        return;
      }
      const s = document.createElement('script');
      s.src = src;
      s.onload = () => { s.dataset.loaded = '1'; resolve(); };
      s.onerror = () => reject();
      document.head.appendChild(s);
    });

    (async () => {
      try {
        // Self-hosted under /lib so the map can't be broken by adblockers,
        // privacy extensions, corporate firewalls, or stricter CSPs that
        // would block third-party CDNs.
        if (!window.d3) await loadScript('/lib/d3.min.js');
        if (!window.topojson) await loadScript('/lib/topojson-client.min.js');
        if (cancelled) return;
        const d3l = window.d3, tp = window.topojson;
        if (!d3l || !tp) { setErr(true); return; }
        const r = await fetch('/lib/us-atlas-states-10m.json');
        const us = await r.json();
        if (cancelled) return;
        const nation = tp.feature(us, us.objects.nation);
        const states = tp.feature(us, us.objects.states);
        // Slight inset so HQ + service ring don't crowd the cropped viewBox.
        const proj   = d3l.geoAlbersUsa().fitExtent(
          [[16, 24], [W - 16, H - 28]], nation
        );
        const path   = d3l.geoPath().projection(proj);
        setGeo({ nation, states, proj, path });
      } catch (e) { if (!cancelled) setErr(true); }
    })();

    return () => { cancelled = true; };
  }, []);

  const hqPos = geo ? geo.proj([HQ.lon, HQ.lat]) : null;
  // Project ship cities. filter() drops anything geoAlbersUsa rejects.
  const shipPts = geo
    ? SHIP_CITIES.map(c => ({ ...c, pos: geo.proj([c.lon, c.lat]) }))
        .filter(c => c.pos)
    : [];

  // 250-mile service radius in projected pixels. geoAlbersUsa is composite,
  // so we measure by projecting a point ~250 mi due east of HQ and taking
  // the resulting screen-space distance. ~250 mi ≈ 3.62° lon at 35.5° N.
  let serviceR = 0;
  if (geo && hqPos) {
    const eastPt = geo.proj([HQ.lon + 3.62, HQ.lat]);
    if (eastPt) serviceR = Math.abs(eastPt[0] - hqPos[0]);
  }

  // Reduced 4-stat strip (was 6). "States served" counts every state
  // visualized on the map: 1 home (OK) + 5 bordering (TX/KS/AR/MO/CO)
  // + 4 unique ship-destination states (CA/IL/GA/MA; Denver/CO already
  // counted in the bordering set) = 10. Sites total reconciles with
  // REGIONS counts plus the 5 ship cities.
  const STATS = [
    { v:'127+', l:'Sites shipped' },
    { v:'10',   l:'States served' },
    { v:window.MWT_PRICING.startingPriceShort, l:'Starting price' },
    { v:'100%', l:'Hand-built'    },
  ];

  // Helper: state-code lookup from a TopoJSON feature.
  const codeOf = (f) =>
    (f.properties && (f.properties.code || f.properties.iso || f.properties.STUSPS))
    || null;
  // us-atlas 10m only ships state name + id; map id to USPS code.
  const ID_TO_CODE = {
    '01':'AL','02':'AK','04':'AZ','05':'AR','06':'CA','08':'CO','09':'CT','10':'DE',
    '11':'DC','12':'FL','13':'GA','15':'HI','16':'ID','17':'IL','18':'IN','19':'IA',
    '20':'KS','21':'KY','22':'LA','23':'ME','24':'MD','25':'MA','26':'MI','27':'MN',
    '28':'MS','29':'MO','30':'MT','31':'NE','32':'NV','33':'NH','34':'NJ','35':'NM',
    '36':'NY','37':'NC','38':'ND','39':'OH','40':'OK','41':'OR','42':'PA','44':'RI',
    '45':'SC','46':'SD','47':'TN','48':'TX','49':'UT','50':'VT','51':'VA','53':'WA',
    '54':'WV','55':'WI','56':'WY',
  };
  const stateCode = (f) => {
    const c = codeOf(f);
    if (c) return c;
    const id = String(f.id || '').padStart(2,'0');
    return ID_TO_CODE[id] || null;
  };

  return (
    <div className="mw-bento-usmap" style={{ position:'relative',
      background:'var(--bg)', border:'1px solid var(--border-strong)', overflow:'hidden' }}>

      {/* HUD top bar — service-area framing, not "active network" theater */}
      <div style={{ position:'absolute', top:0, left:0, right:0, zIndex:3,
        padding:'9px 18px', borderBottom:'1px solid var(--border)',
        background:'color-mix(in oklab,var(--bg) 85%,transparent)',
        backdropFilter:'blur(12px)',
        display:'flex', justifyContent:'space-between', alignItems:'center',
        fontFamily:'var(--font-mono)', fontSize:9, letterSpacing:'0.18em' }}>
        <span style={{color:'var(--fg-4)'}}>— SERVICE AREA · OKC + REGIONAL</span>
        <div style={{display:'flex',gap:20,alignItems:'center',color:'var(--fg-4)'}}>
          <span>35.47°N 97.52°W · OKC HQ</span>
          <span style={{color:'var(--accent)',display:'flex',alignItems:'center',gap:7}}>
            <span style={{width:5,height:5,borderRadius:'50%',background:'var(--accent)',
              boxShadow:'0 0 8px var(--accent)',animation:'mwBreathe 2s infinite'}}/>
            LIVE · {REGIONS.length} STATES PRIMARY
          </span>
        </div>
      </div>

      {/* Two-column body: map left, info rail right (>=900px). The grid
          fills the cell horizontally so it doesn't grow tall. */}
      <div className="mw-bento-usmap-grid"
        style={{ paddingTop:36, paddingBottom:62 }}>

        {/* LEFT — SVG map. The right border is applied by a globals.css
            rule on .mw-bento-usmap-grid > :first-child only at >=900px so
            it doesn't leave a stray hairline at the right edge of the
            full-width single-column layout below 900px. */}
        <div style={{ position:'relative', minHeight:0 }}>
          <svg viewBox={`0 0 ${W} ${H}`}
               className="mw-usmap-svg"
               style={{width:'100%',height:'100%',display:'block'}}
               preserveAspectRatio="xMidYMid meet">
            <defs>
              <filter id="hqGlow" x="-300%" y="-300%" width="700%" height="700%">
                <feGaussianBlur in="SourceGraphic" stdDeviation="7" result="b"/>
                <feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
              </filter>
              {/* Soft glow used for bordering-state subtle shimmer + ship dots */}
              <filter id="softGlow" x="-100%" y="-100%" width="300%" height="300%">
                <feGaussianBlur in="SourceGraphic" stdDeviation="2.4" result="b"/>
                <feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
              </filter>
              {/* Home state — radial accent fill from HQ outward gives the
                  Oklahoma plate a warm-light direction instead of a flat
                  swatch. */}
              <radialGradient id="homeFill" cx="50%" cy="50%" r="60%">
                <stop offset="0%"  stopColor="color-mix(in oklab,var(--accent) 22%,transparent)"/>
                <stop offset="60%" stopColor="color-mix(in oklab,var(--accent) 12%,transparent)"/>
                <stop offset="100%" stopColor="color-mix(in oklab,var(--accent) 6%,transparent)"/>
              </radialGradient>
              {/* Bordering-state fill — slightly cooler, slightly denser than
                  the previous flat `accent 5.5%`, reads as a treated zone
                  next to the home state. */}
              <linearGradient id="borderFill" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%"  stopColor="color-mix(in oklab,var(--accent) 9%,transparent)"/>
                <stop offset="100%" stopColor="color-mix(in oklab,var(--accent) 4%,transparent)"/>
              </linearGradient>
            </defs>

            {/* Loading / error */}
            {!geo && !err && (
              <text x={W/2} y={H/2} textAnchor="middle" dominantBaseline="middle"
                fill="var(--fg-4)" fontFamily="'JetBrains Mono',monospace" fontSize="12"
                letterSpacing="5">LOADING SERVICE AREA…</text>
            )}
            {err && (
              <text x={W/2} y={H/2} textAnchor="middle" dominantBaseline="middle"
                fill="var(--fg-4)" fontFamily="'JetBrains Mono',monospace" fontSize="11"
                letterSpacing="3">MAP OFFLINE — CHECK CONNECTION</text>
            )}

            {geo && <>
              {/* State fills, tiered by tier. Home + border states use
                  gradient defs (homeFill / borderFill) for a less flat
                  read; rest of the country is a muted plate. Bordering
                  states get a soft glow filter so the accent ring
                  around Oklahoma reads as a treated service zone. */}
              {geo.states.features.map((f,i) => {
                const code = stateCode(f);
                const isHome   = code === HOME_CODE;
                const isBorder = code && BORDER_CODES.has(code);
                let fill = 'color-mix(in oklab,var(--accent) 3%,transparent)';
                let stroke = 'color-mix(in oklab,var(--accent) 18%,transparent)';
                let sw = 0.55;
                let filter;
                if (isHome) {
                  fill = 'url(#homeFill)';
                  stroke = 'var(--accent)';
                  sw = 1.2;
                } else if (isBorder) {
                  fill = 'url(#borderFill)';
                  stroke = 'color-mix(in oklab,var(--accent) 42%,transparent)';
                  sw = 0.9;
                  filter = 'url(#softGlow)';
                }
                return (
                  <path key={i} d={geo.path(f)}
                    fill={fill} stroke={stroke} strokeWidth={sw}
                    filter={filter}/>
                );
              })}
              {/* Nation outline */}
              <path d={geo.path(geo.nation)} fill="none"
                stroke="color-mix(in oklab,var(--accent) 38%,transparent)"
                strokeWidth="1.1"/>

              {/* Home + border state count labels — small mono, only on
                  states that have a meaningful client count. */}
              {geo.states.features.map((f,i) => {
                const code = stateCode(f);
                const region = REGIONS.find(r => r.code === code);
                if (!region) return null;
                const c = geo.path.centroid(f);
                if (!c || isNaN(c[0])) return null;
                const isHome = code === HOME_CODE;
                return (
                  <g key={`lbl-${code}`} pointerEvents="none">
                    <text x={c[0]} y={c[1]-2} textAnchor="middle"
                      fontFamily="'JetBrains Mono',monospace"
                      fontSize={isHome ? 11 : 9}
                      fontWeight={isHome ? 700 : 600}
                      letterSpacing="0.08em"
                      fill={isHome ? 'var(--accent)' : 'var(--fg-2)'}>
                      {code}
                    </text>
                    <text x={c[0]} y={c[1]+10} textAnchor="middle"
                      fontFamily="'JetBrains Mono',monospace"
                      fontSize={isHome ? 9 : 8}
                      letterSpacing="0.06em"
                      fill={isHome ? 'var(--accent)' : 'var(--fg-3)'}>
                      {region.count}
                    </text>
                  </g>
                );
              })}

              {/* 250-mile in-person service ring around HQ. Inner solid
                  hairline anchors the radius; outer dashed ring rotates
                  slowly via the .mw-usmap-svg-rotate CSS animation
                  (gated by prefers-reduced-motion). The rotation gives
                  the consult zone a sense of "live coverage" without the
                  dishonest CDN-packet theater the previous version had. */}
              {hqPos && serviceR > 0 && (
                <g pointerEvents="none">
                  <circle cx={hqPos[0]} cy={hqPos[1]} r={serviceR}
                    fill="color-mix(in oklab,var(--accent) 4%,transparent)"
                    stroke="color-mix(in oklab,var(--accent) 22%,transparent)"
                    strokeWidth="0.6"/>
                  <g style={{
                      transformBox:'fill-box', transformOrigin:'center',
                      // Apply the rotation around the HQ center, in SVG
                      // coordinates. We translate so the rotation origin
                      // lands on hqPos rather than the bbox center of
                      // the dashed circle (which is the same here, but
                      // explicit translate is robust).
                    }}
                    transform={`rotate(0 ${hqPos[0]} ${hqPos[1]})`}>
                    <circle className="mw-usmap-radius-ring"
                      cx={hqPos[0]} cy={hqPos[1]} r={serviceR}
                      fill="none"
                      stroke="color-mix(in oklab,var(--accent) 55%,transparent)"
                      strokeWidth="1"
                      strokeDasharray="3 5"
                      style={{
                        transformOrigin: `${hqPos[0]}px ${hqPos[1]}px`,
                      }}/>
                  </g>
                  <text x={hqPos[0]} y={hqPos[1] - serviceR - 6}
                    textAnchor="middle"
                    fontFamily="'JetBrains Mono',monospace"
                    fontSize="8" letterSpacing="0.18em"
                    fill="color-mix(in oklab,var(--accent) 70%,var(--fg-3))">
                    250 MI · IN-PERSON CONSULTS
                  </text>
                </g>
              )}

              {/* Real ship destinations — small dim dots, staggered fade-in
                  on first paint via per-dot animation-delay, then static.
                  This is the only "intersection" cue: the dots reveal in
                  hand-picked order (LA → DEN → CHI → ATL → BOS) when the
                  user first scrolls the map into view. After the reveal
                  they sit quietly. The CSS rule is gated by reduced-motion
                  so reduced-motion users see the final static state. */}
              {shipPts.map((c, i) => (
                <g key={`ship-${c.name}`} pointerEvents="none"
                  className="mw-usmap-ship"
                  style={{
                    // Stagger each city by 140 ms; reveal completes in
                    // ~700 ms. Tied to the .mw-usmap-ship-reveal animation
                    // in globals.css.
                    animationDelay: `${0.5 + i * 0.14}s`,
                  }}>
                  <circle cx={c.pos[0]} cy={c.pos[1]} r="3.4"
                    fill="none"
                    stroke="color-mix(in oklab,var(--accent) 36%,transparent)"
                    strokeWidth="0.7"/>
                  <circle cx={c.pos[0]} cy={c.pos[1]} r="2.2"
                    fill="var(--accent)" fillOpacity="0.85"
                    filter="url(#softGlow)"/>
                  <text x={c.pos[0]+6} y={c.pos[1]+3}
                    fontFamily="'JetBrains Mono',monospace"
                    fontSize="8" letterSpacing="0.1em" fontWeight="600"
                    fill="var(--fg-2)">{c.name}</text>
                </g>
              ))}

              {/* OKC HQ — single subtle radar pulse (the only infinite
                  SVG animation in the new map). The pulse <animate>
                  elements are skipped when prefers-reduced-motion is
                  set, leaving a static outline ring. */}
              {hqPos && (
                <g filter="url(#hqGlow)">
                  <circle cx={hqPos[0]} cy={hqPos[1]} r="4" fill="none"
                    stroke="var(--accent)" strokeWidth="0.9" opacity="0.6">
                    {!reducedMotion && (
                      <>
                        <animate attributeName="r"
                          values={`4;${Math.max(serviceR, 30)};4`}
                          dur="4.5s" repeatCount="indefinite"/>
                        <animate attributeName="opacity"
                          values="0.55;0;0.55" dur="4.5s" repeatCount="indefinite"/>
                      </>
                    )}
                  </circle>
                  <circle cx={hqPos[0]} cy={hqPos[1]} r="6.5"
                    fill="var(--accent)" opacity="0.95"/>
                  <circle cx={hqPos[0]} cy={hqPos[1]} r="3"
                    fill="var(--accent-ink)"/>
                  <text x={hqPos[0]+11} y={hqPos[1]-7} fontSize="10" fontWeight="700"
                    fill="var(--accent)" fontFamily="'JetBrains Mono',monospace"
                    letterSpacing="0.1em">HQ</text>
                </g>
              )}
            </>}

            {/* HUD corner marks */}
            {[[18,16,'l','t'],[W-18,16,'r','t'],[18,H-12,'l','b'],[W-18,H-12,'r','b']].map(([x,y,h,v])=>(
              <g key={`${h}${v}`} opacity="0.5">
                <line x1={x} y1={y} x2={x+(h==='l'?8:-8)} y2={y} stroke="var(--border-strong)" strokeWidth="0.8"/>
                <line x1={x} y1={y} x2={x} y2={y+(v==='t'?8:-8)} stroke="var(--border-strong)" strokeWidth="0.8"/>
              </g>
            ))}
          </svg>
        </div>

        {/* RIGHT — info rail */}
        <div style={{ display:'flex', flexDirection:'column',
          padding:'14px 16px', gap:10, minWidth:0 }}>
          <div style={{fontFamily:'var(--font-mono)',fontSize:9,
            letterSpacing:'0.18em',color:'var(--fg-4)'}}>
            — SERVICE AREA · OKC HQ
          </div>
          <div>
            <div style={{fontFamily:'var(--font-display)',
              fontSize:'clamp(22px,2.4vw,28px)', fontWeight:500,
              letterSpacing:'-0.03em', lineHeight:1, color:'var(--fg-1)'}}>
              Oklahoma City
            </div>
            <div style={{fontFamily:'var(--font-mono)', fontSize:9,
              color:'var(--fg-4)', letterSpacing:'0.12em', marginTop:5}}>
              35.47°N 97.52°W · EST. 2024
            </div>
          </div>

          <div style={{height:1, background:'var(--border)', margin:'2px 0'}}/>

          {/* Regional breakdown — code | name | count */}
          <div style={{display:'flex', flexDirection:'column', gap:6}}>
            {REGIONS.map(r => {
              const isHome = r.tier === 'home';
              return (
                <div key={r.code} style={{
                  display:'grid',
                  gridTemplateColumns:'28px 1fr auto',
                  alignItems:'baseline', gap:8,
                  fontSize:11, lineHeight:1.2 }}>
                  <span style={{
                    fontFamily:'var(--font-mono)',
                    fontWeight: isHome ? 700 : 500,
                    letterSpacing:'0.1em',
                    color: isHome ? 'var(--accent)' : 'var(--fg-3)' }}>
                    {r.code}
                  </span>
                  <span style={{
                    color: isHome ? 'var(--fg-1)' : 'var(--fg-2)',
                    fontWeight: isHome ? 500 : 400 }}>
                    {r.label}
                  </span>
                  <span style={{
                    fontFamily:'var(--font-mono)',
                    fontVariantNumeric:'tabular-nums',
                    color: isHome ? 'var(--accent)' : 'var(--fg-3)' }}>
                    {r.count}
                  </span>
                </div>
              );
            })}
          </div>

          <div style={{height:1, background:'var(--border)', margin:'2px 0'}}/>

          {/* Recent shipments — pairs the map's accent-colored ship dots
              with their cities and the kind of build delivered. Replaces
              the previous one-line italic ("Remote-built…") which the
              operator flagged as "useless" — same five cities the map
              labels, now with concrete project context so the right rail
              reads as a small live-feed instead of filler copy. */}
          <div style={{display:'flex',flexDirection:'column',gap:5}}>
            <div style={{fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.18em',
              color:'var(--fg-4)',display:'flex',justifyContent:'space-between',alignItems:'baseline'}}>
              <span>— RECENT SHIPMENTS</span>
              <span style={{color:'var(--accent)'}}>5 / 5</span>
            </div>
            {[
              { c:'Los Angeles', t:'Boutique store',     k:'CA' },
              { c:'Denver',      t:'Real-estate listings', k:'CO' },
              { c:'Chicago',     t:'Service-business site', k:'IL' },
              { c:'Atlanta',     t:'Custom SaaS portal',  k:'GA' },
              { c:'Boston',      t:'Multi-page brand',    k:'MA' },
            ].map((s, i) => (
              <div key={s.c} style={{
                display:'grid',
                gridTemplateColumns:'10px 1fr auto',
                alignItems:'center', gap:8,
                fontSize:11, lineHeight:1.25 }}>
                <span aria-hidden="true" style={{
                  width:6,height:6,borderRadius:'50%',
                  background:'var(--accent)',
                  boxShadow:'0 0 6px color-mix(in oklab,var(--accent) 60%,transparent)',
                  opacity: 0.55 + i * 0.09,
                  marginLeft:1 }}/>
                <span style={{color:'var(--fg-2)',minWidth:0,
                  overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>
                  <span style={{color:'var(--fg-1)',fontWeight:500}}>{s.c}</span>
                  <span style={{color:'var(--fg-4)',marginLeft:6,fontSize:10}}>{s.t}</span>
                </span>
                <span style={{fontFamily:'var(--font-mono)',fontSize:9,
                  letterSpacing:'0.12em',color:'var(--fg-4)'}}>{s.k}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Stats strip — 4 stats, full width across both columns,
          smaller padding than the original 6-stat strip. */}
      <div style={{ position:'absolute', bottom:0, left:0, right:0, zIndex:3,
        borderTop:'1px solid var(--border)',
        background:'color-mix(in oklab,var(--bg) 90%,transparent)',
        backdropFilter:'blur(14px)',
        display:'grid', gridTemplateColumns:'repeat(4,1fr)' }}>
        {STATS.map((s,i) => (
          <div key={s.l} style={{ padding:'10px 12px',
            borderLeft:i>0?'1px solid var(--border)':'none',
            display:'flex', flexDirection:'column', alignItems:'center',
            justifyContent:'center', textAlign:'center' }}>
            <div style={{fontFamily:'var(--font-display)',fontSize:22,fontWeight:500,
              letterSpacing:'-0.04em',lineHeight:1,color:'var(--fg-1)'}}>{s.v}</div>
            <div style={{fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.14em',
              textTransform:'uppercase',color:'var(--fg-4)',marginTop:5}}>{s.l}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---- Process Cell — animated horizontal timeline w/ visual candy ---- */
function ProcessCell() {
  const steps = [
    { n:'01', t:'Consult', d:'30 min · free call', note:'Tell us what you need',
      glyph:'phone',  metric:'30 MIN',
      deliverables:['Discovery call','Goals + audience','Rough budget'] },
    { n:'02', t:'Scope',   d:'1–3 day write-up',   note:'Fixed price, no surprises',
      glyph:'doc',    metric:'1-3 DAYS',
      deliverables:['Sitemap + features','Fixed quote','Timeline locked'] },
    { n:'03', t:'Build',   d:'2–12 weeks',         note:'Real people, real craft',
      glyph:'hammer', metric:'2-12 WKS',
      deliverables:['Design previews','Hand-coded site','Weekly check-ins'] },
    { n:'04', t:'Ship',    d:'Deploy + handoff',   note:'Yours forever, no lock-in',
      glyph:'rocket', metric:'GO LIVE',
      deliverables:['Domain + hosting','Owner training','30-day support'] },
  ];
  const [active, setActive] = useStSv(0);
  const [auto, setAuto] = useStSv(true);
  useEfSv(()=>{
    if(!auto) return;
    const t=setInterval(()=>setActive(a=>(a+1)%steps.length),2400);
    return()=>clearInterval(t);
  },[auto]);

  // Glyphs as inline SVG — small, on-brand, monochrome
  const Glyph = ({k, color}) => {
    const s = { fill:'none', stroke:color, strokeWidth:1.4, strokeLinecap:'round', strokeLinejoin:'round' };
    if (k==='phone')  return <svg viewBox="0 0 24 24" width="22" height="22"><path {...s} d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2A15 15 0 0 1 3 6a2 2 0 0 1 2-2z"/></svg>;
    if (k==='doc')    return <svg viewBox="0 0 24 24" width="22" height="22"><path {...s} d="M6 3h8l4 4v14H6z"/><path {...s} d="M14 3v4h4M9 12h6M9 16h6"/></svg>;
    if (k==='hammer') return <svg viewBox="0 0 24 24" width="22" height="22"><path {...s} d="M14 4l6 6-3 3-6-6zM11 7l-7 7 3 3 7-7"/><path {...s} d="M5 17l-2 2 2 2 2-2"/></svg>;
    if (k==='rocket') return <svg viewBox="0 0 24 24" width="22" height="22"><path {...s} d="M14 4c4 0 6 2 6 6 0 5-7 10-7 10s-7-5-7-10c0-4 2-6 6-6"/><circle {...s} cx="13" cy="10" r="2"/><path {...s} d="M9 16l-3 4M16 16l3 4"/></svg>;
    return null;
  };

  return (
    <div style={{ padding:16, display:'flex', flexDirection:'column',
      background:'var(--bg-elev-1)', border:'1px solid var(--border-strong)',
      gap:12, position:'relative', overflow:'hidden' }}
      onMouseEnter={()=>setAuto(false)} onMouseLeave={()=>setAuto(true)}>

      {/* Subtle grid background — opacity reduced for the smaller cell */}
      <div style={{position:'absolute',inset:0,opacity:0.25,pointerEvents:'none',
        backgroundImage:'linear-gradient(var(--border) 1px, transparent 1px),linear-gradient(90deg,var(--border) 1px,transparent 1px)',
        backgroundSize:'32px 32px',
        maskImage:'radial-gradient(ellipse at center,black 30%,transparent 75%)'}}/>

      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',position:'relative'}}>
        <div style={{fontFamily:'var(--font-mono)',fontSize:10,letterSpacing:'0.18em',color:'var(--fg-4)'}}>— HOW IT WORKS</div>
        <div style={{fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.14em',color:'var(--accent)',
          display:'flex',alignItems:'center',gap:7}}>
          <span style={{width:5,height:5,borderRadius:'50%',background:'var(--accent)',
            boxShadow:'0 0 8px var(--accent)',animation:'mwBreathe 2s infinite'}}/>
          STEP {steps[active].n} / 04
        </div>
      </div>

      {/* Two-column body: headline+pills (left), vertical rail (right) */}
      <div className="mw-bento-process-grid" style={{position:'relative'}}>

        {/* LEFT — active step content */}
        <div style={{display:'flex',flexDirection:'column',gap:10,minWidth:0}}>
          <div style={{display:'flex',alignItems:'center',gap:12,flexWrap:'wrap'}}>
            <span style={{color:'var(--accent)',fontFamily:'var(--font-mono)',
              fontSize:'clamp(13px,1.4vw,16px)', fontWeight:500,
              letterSpacing:'0.08em'}}>{steps[active].n}</span>
            <span key={`t-${active}`} style={{
              fontFamily:'var(--font-display)',
              fontSize:'clamp(24px,3.2vw,34px)', fontWeight:500,
              letterSpacing:'-0.035em', lineHeight:0.95, color:'var(--fg-1)',
              animation:'mwFadeIn .4s'}}>{steps[active].t}</span>
            <span style={{color:'var(--accent)',display:'inline-flex'}}>
              <Glyph k={steps[active].glyph} color="var(--accent)"/>
            </span>
          </div>
          <div key={`n-${active}`} style={{
            fontFamily:'var(--font-editorial)', fontStyle:'italic',
            fontSize:'clamp(13px,1.4vw,16px)', color:'var(--fg-3)',
            lineHeight:1.35, animation:'mwFadeIn .4s .05s backwards'}}>
            {steps[active].note}
          </div>

          {/* Deliverables strip — tighter padding */}
          <div key={`del-${active}`} style={{
            display:'flex', gap:6, flexWrap:'wrap',
            animation:'mwFadeIn .4s .1s backwards'}}>
            {steps[active].deliverables.map((d)=>(
              <div key={d} style={{display:'flex',alignItems:'center',gap:6,
                padding:'4px 8px',
                background:'color-mix(in oklab,var(--accent) 8%,transparent)',
                border:'1px solid color-mix(in oklab,var(--accent) 25%,transparent)',
                fontFamily:'var(--font-mono)',fontSize:10,letterSpacing:'0.08em',
                color:'var(--fg-2)'}}>
                <span style={{color:'var(--accent)',fontSize:9}}>◆</span>
                <span>{d}</span>
              </div>
            ))}
          </div>
        </div>

        {/* RIGHT — vertical progress rail. The rail sits 14px from the
            right edge of this column so the dots can sit on the rail
            with their metric labels flowing LEFT into the available
            space (toward the headline column). The active dot is 24px
            and inactive 12px; both center on the rail. */}
        <div style={{position:'relative', minHeight:170,
          padding:'4px 0 4px 0'}}>
          {/* Base vertical rail — anchored to right edge */}
          <div style={{position:'absolute', right:14, top:8, bottom:8,
            width:2, background:'var(--border-strong)'}}/>
          {/* Active progress fill grows top-to-bottom */}
          <div style={{position:'absolute', right:14, top:8,
            width:2,
            height:`calc((100% - 16px) * ${active/(steps.length-1)})`,
            background:'var(--accent)',
            boxShadow:'0 0 8px var(--accent)',
            transition:'height .6s var(--ease-out)'}}/>

          {steps.map((s,i)=>{
            const isActive = i === active;
            const isDone   = i < active;
            const dotSize  = isActive ? 24 : 12;
            // Position each dot at 0%, 33%, 66%, 100% along the rail.
            const yPct = (i / (steps.length - 1)) * 100;
            // Activate jumps the active step without locally calling
            // setAuto(false). Desktop hover pause/resume is handled by
            // the outer ProcessCell wrapper's onMouseEnter/onMouseLeave;
            // calling setAuto(false) here would persist on touch
            // devices, where no matching mouseLeave fires to re-arm
            // auto-advance — Codex P2 review on PR #38.
            const activate = ()=>setActive(i);
            return (
              <div key={s.n}
                role="button"
                tabIndex={0}
                aria-label={`Show step ${s.n}: ${s.t}`}
                aria-current={isActive ? 'step' : undefined}
                onMouseEnter={activate}
                onClick={activate}
                onKeyDown={(e)=>{
                  if (e.key === 'Enter' || e.key === ' ') {
                    e.preventDefault();
                    activate();
                  }
                }}
                style={{
                  position:'absolute',
                  left:0, right:0,
                  top:`calc(${yPct}% - ${dotSize/2}px)`,
                  height:dotSize,
                  cursor:'pointer'}}>
                {/* Metric label — anchored to the LEFT of the dot,
                    right edge stops 8px before the dot's left edge.
                    Rail center sits at right:15 (right:14 + width:2/2),
                    so dot left edge is at right:(15 + dotSize/2). */}
                <div style={{
                  position:'absolute',
                  left:0,
                  right: 15 + dotSize/2 + 8,
                  top:'50%', transform:'translateY(-50%)',
                  fontFamily:'var(--font-mono)', fontSize:9,
                  letterSpacing:'0.14em',
                  color: isActive ? 'var(--accent)'
                       : (isDone ? 'var(--fg-3)' : 'var(--fg-4)'),
                  transition:'color .25s, right .35s var(--ease-out)',
                  textAlign:'right',
                  whiteSpace:'nowrap',
                  overflow:'hidden', textOverflow:'ellipsis' }}>
                  {s.metric} · {s.d.toUpperCase()}
                </div>
                {/* Dot — centered on the rail (rail center at right:15) */}
                <div style={{
                  position:'absolute',
                  right: 15 - dotSize/2,
                  top:0,
                  width:dotSize, height:dotSize,
                  borderRadius:'50%',
                  background:isActive ? 'var(--accent)'
                            : (isDone ? 'var(--accent)' : 'var(--bg-elev-1)'),
                  border:`2px solid ${isActive||isDone?'var(--accent)':'var(--border-strong)'}`,
                  boxShadow:isActive
                    ? '0 0 0 4px color-mix(in oklab,var(--accent) 18%,transparent),0 0 12px var(--accent)'
                    : 'none',
                  display:'flex', alignItems:'center', justifyContent:'center',
                  transition:'all .35s var(--ease-out)',
                  zIndex:2 }}>
                  {isActive && <div style={{width:6,height:6,borderRadius:'50%',background:'var(--accent-ink)'}}/>}
                  {isDone && !isActive && <div style={{fontSize:9,color:'var(--accent-ink)',fontWeight:700}}>✓</div>}
                </div>
              </div>
            );
          })}
        </div>
      </div>

      <div style={{paddingTop:10,borderTop:'1px solid var(--border)',display:'flex',
        justifyContent:'space-between',alignItems:'center',position:'relative',gap:10,flexWrap:'wrap'}}>
        <div style={{fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.12em',color:'var(--fg-4)'}}>
          {auto ? 'AUTO-ADVANCING · HOVER TO PAUSE' : 'PAUSED · HOVER A STEP'}
        </div>
        <MagButton
          size="sm"
          variant="ghost"
          href="#contact"
          iconAfter="→"
          onClick={() => window['mwtTrack'] && window['mwtTrack']('select_content', {
            content_type: 'cta',
            content_id: 'services_free_consult',
            cta_label: 'Start with a free consult',
            page_section: 'services_process',
            page_path: typeof window !== 'undefined' ? window.location.pathname : '',
          })}
        >Start with a free consult</MagButton>
      </div>
    </div>
  );
}

/* ---- Spectrum Cell ---- */
/* Wireframe primitives drawn for the morphing website preview.
   Each receives a `weight` 0–1 indicating how "present" the layout this primitive
   belongs to currently is — all visual props (opacity, transform, stroke) ramp
   smoothly off that single number so the box feels like one continuous mockup
   reorganizing itself, not five layouts crossfading. */
function WirePrim({ weight, children, translate=[0,0], origin='50% 50%' }) {
  const w = Math.max(0, Math.min(1, weight));
  // Ease the weight so primitives "pop" near full presence and fade slow when leaving
  const eased = w * w * (3 - 2 * w);
  const tx = translate[0] * (1 - eased);
  const ty = translate[1] * (1 - eased);
  const scale = 0.92 + 0.08 * eased;
  return (
    <g style={{
      opacity: eased,
      transform: `translate(${tx}px, ${ty}px) scale(${scale})`,
      transformOrigin: origin,
      transformBox: 'fill-box',
      transition: 'opacity .35s var(--ease-out), transform .45s var(--ease-out)',
      pointerEvents: 'none',
    }}>{children}</g>
  );
}

/* ---- Realistic site previews — one full layout per spectrum stage. ----
   Each renders inside a 4:3 viewport. Designed to look like an actual site
   you'd recognize at a glance: a barber landing page, a car listings grid,
   an editorial multi-page brand, a shop, and a SaaS dashboard. */

/* Subtle striped placeholder for imagery — feels intentional, not lazy. */
function PreviewImg({ style, label, dark=false, hue='var(--accent)' }) {
  return (
    <div style={{
      background:dark
        ? `repeating-linear-gradient(135deg, #2a2a2a 0 6px, #232323 6px 12px)`
        : `repeating-linear-gradient(135deg, color-mix(in oklab,${hue} 18%,#e8e4d8) 0 6px, color-mix(in oklab,${hue} 10%,#ddd9cc) 6px 12px)`,
      color:dark?'#9a978d':'#6b6a64',
      fontFamily:'var(--font-mono)',fontSize:6,letterSpacing:'0.18em',
      display:'flex',alignItems:'center',justifyContent:'center',
      ...style
    }}>{label}</div>
  );
}

/* SIMPLE — barber landing page */
function PreviewSimple() {
  return (
    <div style={{position:'absolute',inset:0,background:'#f7f4ec',color:'#1a1a1a',
      fontFamily:'var(--font-display)',display:'flex',flexDirection:'column'}}>
      {/* Top nav */}
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',
        padding:'10px 16px',borderBottom:'1px solid #d8d4ca'}}>
        <div style={{display:'flex',alignItems:'center',gap:8}}>
          <div style={{width:12,height:12,background:'#1a1a1a',transform:'rotate(45deg)'}}/>
          <div style={{fontSize:11,fontWeight:600,letterSpacing:'0.08em'}}>MAIN ST. BARBER</div>
        </div>
        <div style={{display:'flex',gap:14,fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.14em',color:'#5b5a55'}}>
          <span>SERVICES</span><span>HOURS</span><span style={{color:'#1a1a1a',fontWeight:600}}>BOOK ↗</span>
        </div>
      </div>
      {/* Hero — fills the pane */}
      <div style={{display:'grid',gridTemplateColumns:'1.15fr 1fr',gap:12,padding:'18px 16px 14px',flex:1,minHeight:0}}>
        <div style={{display:'flex',flexDirection:'column',justifyContent:'space-between',minWidth:0}}>
          <div>
            <div style={{fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.22em',color:'#a64a2a'}}>EST. 1998 · DOWNTOWN OKC</div>
            <div style={{fontSize:'clamp(28px,4.6vw,44px)',lineHeight:0.92,fontWeight:500,letterSpacing:'-0.04em',marginTop:8}}>
              A clean cut,<br/>
              <span style={{fontFamily:'var(--font-editorial)',fontStyle:'italic',fontWeight:400}}>done right.</span>
            </div>
            <div style={{fontSize:10,lineHeight:1.45,color:'#5b5a55',marginTop:10,maxWidth:'92%'}}>
              Walk-ins welcome. Appointments preferred. Hot towel finish on every cut. Three barbers, six chairs, no fuss.
            </div>
          </div>
          <div style={{display:'flex',gap:6,alignItems:'center',marginTop:10,flexWrap:'wrap'}}>
            <div style={{padding:'7px 12px',background:'#1a1a1a',color:'#f7f4ec',
              fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.14em',fontWeight:600}}>BOOK NOW →</div>
            <div style={{padding:'7px 12px',border:'1px solid #1a1a1a',
              fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.14em'}}>(405) 555-0142</div>
          </div>
        </div>
        <PreviewImg style={{flex:1,minHeight:0}} label="BARBERSHOP / INTERIOR" hue="#a64a2a"/>
      </div>
      {/* Footer strip */}
      <div style={{display:'flex',justifyContent:'space-between',padding:'8px 16px',
        borderTop:'1px solid #d8d4ca',fontFamily:'var(--font-mono)',fontSize:8,
        letterSpacing:'0.14em',color:'#5b5a55'}}>
        <span>MON–SAT · 9–7</span><span>124 N MAIN ST</span><span>@MAINSTBARBER</span>
      </div>
    </div>
  );
}

/* LISTINGS — car inventory page */
function PreviewListings() {
  const cars = [
    {y:'2020',m:'Silverado 1500',mi:'48k',p:'$32,900',c:'#1f3b5a'},
    {y:'2018',m:'F-150 XLT',mi:'67k',p:'$28,400',c:'#7a2727'},
    {y:'2021',m:'Tacoma TRD',mi:'31k',p:'$36,200',c:'#2d4a2d'},
    {y:'2019',m:'RAM 1500',mi:'54k',p:'$29,750',c:'#3a3a3a'},
    {y:'2017',m:'Tundra SR5',mi:'82k',p:'$24,600',c:'#5c4a2d'},
    {y:'2022',m:'Ranger Lariat',mi:'19k',p:'$34,100',c:'#1a1a1a'},
  ];
  return (
    <div style={{position:'absolute',inset:0,background:'#f7f4ec',color:'#1a1a1a',
      display:'flex',flexDirection:'column'}}>
      {/* Header */}
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',
        padding:'10px 16px',background:'#1a1a1a',color:'#f7f4ec'}}>
        <div style={{fontFamily:'var(--font-display)',fontSize:14,fontWeight:600,letterSpacing:'-0.02em'}}>RED DIRT AUTO</div>
        <div style={{fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.14em',opacity:0.8}}>
          INVENTORY · FINANCING · TRADE-IN
        </div>
      </div>
      {/* Filter bar */}
      <div style={{display:'flex',gap:6,padding:'8px 16px',borderBottom:'1px solid #d8d4ca',
        fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.1em',alignItems:'center'}}>
        <span style={{color:'#5b5a55'}}>FILTER ▾</span>
        {['TRUCKS','SUVS','SEDANS','UNDER $25K'].map((f,i)=>(
          <span key={f} style={{padding:'3px 7px',
            background:i===0?'#1a1a1a':'transparent',color:i===0?'#f7f4ec':'#5b5a55',
            border:i===0?'none':'1px solid #d8d4ca',fontWeight:i===0?600:400}}>{f}</span>
        ))}
        <span style={{marginLeft:'auto',color:'#5b5a55'}}>247 RESULTS · SORT: NEWEST ▾</span>
      </div>
      {/* Grid — bigger cards, fewer columns to use the space */}
      <div style={{flex:1,padding:10,display:'grid',gridTemplateColumns:'repeat(3,1fr)',
        gridTemplateRows:'repeat(2,1fr)',gap:8,minHeight:0}}>
        {cars.map((car,i)=>(
          <div key={i} style={{background:'#fff',border:'1px solid #d8d4ca',
            display:'flex',flexDirection:'column',minHeight:0,overflow:'hidden'}}>
            <div style={{flex:1,background:`linear-gradient(135deg, ${car.c} 0%, color-mix(in oklab, ${car.c} 70%, #000) 100%)`,
              position:'relative',minHeight:0}}>
              <div style={{position:'absolute',left:5,top:5,padding:'2px 6px',
                background:'#fff',fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.1em',fontWeight:600}}>{car.y}</div>
            </div>
            <div style={{padding:'6px 8px',display:'flex',justifyContent:'space-between',alignItems:'center',gap:4}}>
              <div style={{minWidth:0}}>
                <div style={{fontFamily:'var(--font-display)',fontSize:9,fontWeight:600,lineHeight:1.05,whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{car.m}</div>
                <div style={{fontFamily:'var(--font-mono)',fontSize:7,color:'#5b5a55',letterSpacing:'0.08em',marginTop:2}}>{car.mi} MI</div>
              </div>
              <div style={{fontFamily:'var(--font-display)',fontSize:11,fontWeight:600,color:'#a64a2a',whiteSpace:'nowrap'}}>{car.p}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* FULL — editorial multi-page brand */
function PreviewFull() {
  return (
    <div style={{position:'absolute',inset:0,background:'#f7f4ec',color:'#1a1a1a',
      display:'flex',flexDirection:'column'}}>
      {/* Top nav */}
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',
        padding:'10px 16px',borderBottom:'1px solid #d8d4ca'}}>
        <div style={{fontFamily:'var(--font-editorial)',fontStyle:'italic',fontSize:15,fontWeight:500}}>Foundry Press</div>
        <div style={{display:'flex',gap:14,fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.14em',color:'#5b5a55'}}>
          <span style={{color:'#1a1a1a',borderBottom:'1px solid #1a1a1a',paddingBottom:1,fontWeight:600}}>WORK</span>
          <span>JOURNAL</span><span>STUDIO</span><span>CONTACT</span>
        </div>
      </div>
      {/* Editorial hero */}
      <div style={{padding:'14px 16px 10px',display:'flex',alignItems:'baseline',justifyContent:'space-between',gap:12,
        borderBottom:'1px solid #d8d4ca'}}>
        <div style={{fontFamily:'var(--font-display)',fontSize:'clamp(22px,3.6vw,32px)',fontWeight:500,letterSpacing:'-0.03em',lineHeight:0.95,minWidth:0}}>
          Letterpress, made <span style={{fontFamily:'var(--font-editorial)',fontStyle:'italic'}}>in the heartland.</span>
        </div>
        <div style={{fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.14em',color:'#5b5a55',whiteSpace:'nowrap'}}>VOL. 14 · 2026</div>
      </div>
      {/* Tile row — bigger imagery, fuller meta */}
      <div style={{flex:1,padding:10,display:'grid',gridTemplateColumns:'1.5fr 1fr 1fr',gap:8,minHeight:0}}>
        <div style={{display:'flex',flexDirection:'column',gap:6,minHeight:0}}>
          <PreviewImg style={{flex:1,minHeight:0}} label="HERO / PRESS FLOOR" hue="#a64a2a"/>
          <div style={{padding:'2px 2px',display:'flex',justifyContent:'space-between',alignItems:'baseline',gap:6}}>
            <div style={{minWidth:0}}>
              <div style={{fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.14em',color:'#a64a2a',marginBottom:2}}>FEATURED · 001</div>
              <div style={{fontFamily:'var(--font-display)',fontSize:11,fontWeight:600,lineHeight:1.05}}>The Larkspur Wedding Suite</div>
              <div style={{fontFamily:'var(--font-mono)',fontSize:7,color:'#5b5a55',letterSpacing:'0.08em',marginTop:3}}>WEDDING · COTTON 220 · 2026</div>
            </div>
            <div style={{fontFamily:'var(--font-mono)',fontSize:7,color:'#5b5a55',whiteSpace:'nowrap'}}>READ →</div>
          </div>
        </div>
        <div style={{display:'flex',flexDirection:'column',gap:6,minHeight:0}}>
          <PreviewImg style={{flex:1,minHeight:0}} label="DETAIL / TYPE TRAY"/>
          <div style={{padding:'2px 2px'}}>
            <div style={{fontFamily:'var(--font-display)',fontSize:9.5,fontWeight:600,lineHeight:1.1}}>Cedar &amp; Bone Menus</div>
            <div style={{fontFamily:'var(--font-mono)',fontSize:7,color:'#5b5a55',letterSpacing:'0.08em',marginTop:2}}>HOSPITALITY · 2025</div>
          </div>
        </div>
        <div style={{display:'flex',flexDirection:'column',gap:6,minHeight:0}}>
          <PreviewImg style={{flex:1,minHeight:0}} label="BUSINESS CARDS"/>
          <div style={{padding:'2px 2px'}}>
            <div style={{fontFamily:'var(--font-display)',fontSize:9.5,fontWeight:600,lineHeight:1.1}}>Plainsong Calling Cards</div>
            <div style={{fontFamily:'var(--font-mono)',fontSize:7,color:'#5b5a55',letterSpacing:'0.08em',marginTop:2}}>STATIONERY · 2024</div>
          </div>
        </div>
      </div>
      {/* Footer rule */}
      <div style={{padding:'8px 16px',borderTop:'1px solid #d8d4ca',display:'flex',
        justifyContent:'space-between',fontFamily:'var(--font-mono)',fontSize:8,
        letterSpacing:'0.14em',color:'#5b5a55'}}>
        <span>EST. 2011 · OKLAHOMA CITY</span><span style={{color:'#1a1a1a',fontWeight:600}}>BOOK A STUDIO VISIT →</span>
      </div>
    </div>
  );
}

/* STORE — eCommerce shop */
function PreviewStore() {
  const items = [
    {n:'Cast Iron Skillet',d:'12-inch · pre-seasoned',p:'$48',c:'#3a3a3a',badge:'NEW'},
    {n:'Walnut Cutting Board',d:'End-grain · oiled',p:'$72',c:'#5c3a1f'},
    {n:'Stoneware Mug Set',d:'Set of 4 · matte',p:'$36',c:'#7a6b4a'},
    {n:'Linen Apron',d:'Heavyweight · clay',p:'$54',c:'#a64a2a'},
  ];
  return (
    <div style={{position:'absolute',inset:0,background:'#f7f4ec',color:'#1a1a1a',
      display:'flex',flexDirection:'column'}}>
      {/* Header */}
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',
        padding:'10px 16px',borderBottom:'1px solid #d8d4ca'}}>
        <div style={{fontFamily:'var(--font-display)',fontSize:14,fontWeight:600,letterSpacing:'-0.02em'}}>PRAIRIE GOODS</div>
        <div style={{display:'flex',gap:12,alignItems:'center',fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.14em',color:'#5b5a55'}}>
          <span>SHOP</span><span>JOURNAL</span><span>SEARCH</span>
          <span style={{display:'inline-flex',alignItems:'center',gap:5,padding:'4px 9px',background:'#1a1a1a',color:'#f7f4ec',fontWeight:600}}>
            BAG <span style={{display:'inline-flex',alignItems:'center',justifyContent:'center',
              minWidth:14,height:14,padding:'0 4px',borderRadius:7,background:'#a64a2a',color:'#fff',fontSize:7,fontWeight:700}}>3</span>
          </span>
        </div>
      </div>
      {/* Section header */}
      <div style={{padding:'10px 16px',display:'flex',justifyContent:'space-between',alignItems:'baseline',gap:12,
        borderBottom:'1px solid #d8d4ca'}}>
        <div style={{fontFamily:'var(--font-display)',fontSize:'clamp(20px,3vw,28px)',fontWeight:500,letterSpacing:'-0.02em',lineHeight:1}}>
          Kitchen <span style={{fontFamily:'var(--font-editorial)',fontStyle:'italic'}}>essentials</span>
        </div>
        <div style={{fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.12em',color:'#5b5a55',whiteSpace:'nowrap'}}>FREE SHIP OVER $75</div>
      </div>
      {/* Product grid — 4 cards filling height with images + meta */}
      <div style={{flex:1,padding:10,display:'grid',gridTemplateColumns:'repeat(4,1fr)',gap:8,minHeight:0}}>
        {items.map((it,i)=>(
          <div key={i} style={{display:'flex',flexDirection:'column',minHeight:0}}>
            <div style={{flex:1,background:`linear-gradient(160deg, color-mix(in oklab,${it.c} 30%,#e8e4d8) 0%, color-mix(in oklab,${it.c} 55%,#c8c3b6) 100%)`,
              border:'1px solid #d8d4ca',position:'relative',minHeight:0}}>
                {it.badge && <div style={{position:'absolute',left:5,top:5,padding:'2px 5px',
                  background:'#a64a2a',color:'#fff',fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.1em',fontWeight:700}}>{it.badge}</div>}
                <div style={{position:'absolute',right:5,bottom:5,width:18,height:18,
                  background:'#fff',border:'1px solid #1a1a1a',display:'flex',alignItems:'center',justifyContent:'center',
                  fontSize:11,fontWeight:600}}>+</div>
            </div>
            <div style={{padding:'6px 2px',display:'flex',flexDirection:'column',gap:1}}>
              <div style={{display:'flex',justifyContent:'space-between',alignItems:'baseline',gap:4}}>
                <div style={{fontFamily:'var(--font-display)',fontSize:9,fontWeight:600,lineHeight:1.05,minWidth:0,whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{it.n}</div>
                <div style={{fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.04em',fontWeight:600}}>{it.p}</div>
              </div>
              <div style={{fontFamily:'var(--font-mono)',fontSize:7,color:'#5b5a55',letterSpacing:'0.06em',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{it.d}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* CUSTOM — SaaS dashboard */
function PreviewCustom() {
  return (
    <div style={{position:'absolute',inset:0,background:'#1a1a1a',color:'#f7f4ec',
      display:'flex',flexDirection:'column',fontFamily:'var(--font-display)'}}>
      {/* Top bar */}
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',
        padding:'8px 12px',borderBottom:'1px solid #2e2e2e',background:'#0e0e0e'}}>
        <div style={{display:'flex',alignItems:'center',gap:10}}>
          <div style={{width:11,height:11,background:'#a64a2a',transform:'rotate(45deg)'}}/>
          <div style={{fontSize:11,fontWeight:600,letterSpacing:'0.04em'}}>SILO ANALYTICS</div>
          <div style={{fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.14em',color:'#7a7a7a',marginLeft:6}}>/ DASHBOARD / OVERVIEW</div>
        </div>
        <div style={{display:'flex',gap:10,alignItems:'center',fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.12em',color:'#7a7a7a'}}>
          <span style={{padding:'3px 7px',border:'1px solid #2e2e2e',color:'#f7f4ec'}}>LAST 30D ▾</span>
          <span style={{display:'inline-flex',alignItems:'center',justifyContent:'center',width:14,height:14,borderRadius:'50%',background:'#a64a2a',color:'#fff',fontSize:7,fontWeight:700}}>JT</span>
        </div>
      </div>
      {/* Body: sidebar + content */}
      <div style={{flex:1,display:'grid',gridTemplateColumns:'68px 1fr',minHeight:0}}>
        {/* Sidebar */}
        <div style={{borderRight:'1px solid #2e2e2e',padding:'10px 6px',
          display:'flex',flexDirection:'column',gap:9,fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.1em',color:'#7a7a7a'}}>
          {[{l:'OVERVIEW',a:true},{l:'YIELD'},{l:'MOISTURE'},{l:'TEMP'},{l:'ALERTS'},{l:'REPORTS'},{l:'SETTINGS'}].map((s)=>(
            <div key={s.l} style={{padding:'3px 6px',color:s.a?'#f7f4ec':'#7a7a7a',
              borderLeft:s.a?'2px solid #a64a2a':'2px solid transparent',
              fontWeight:s.a?600:400}}>{s.l}</div>
          ))}
        </div>
        {/* Main */}
        <div style={{padding:8,display:'grid',gridTemplateColumns:'1.7fr 1fr',gridTemplateRows:'auto 1fr auto',gap:6,minHeight:0}}>
          {/* KPI row spans full */}
          <div style={{gridColumn:'1 / -1',display:'grid',gridTemplateColumns:'repeat(4,1fr)',gap:6}}>
            {[{l:'TOTAL YIELD',v:'14,820',d:'BU',c:'#a64a2a',t:'+8.2%'},
              {l:'AVG MOISTURE',v:'13.4',d:'%',c:'#7a9a7a',t:'+0.3%'},
              {l:'BIN TEMP',v:'52',d:'°F',c:'#7a8aa6',t:'STABLE'},
              {l:'ACTIVE BINS',v:'18 / 24',d:'',c:'#f7f4ec',t:'6 IDLE'}].map((k,i)=>(
              <div key={i} style={{padding:'6px 8px',background:'#232323',border:'1px solid #2e2e2e'}}>
                <div style={{fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.14em',color:'#7a7a7a'}}>{k.l}</div>
                <div style={{display:'flex',alignItems:'baseline',gap:3,marginTop:3}}>
                  <span style={{fontSize:18,fontWeight:600,color:k.c,letterSpacing:'-0.02em',lineHeight:1}}>{k.v}</span>
                  <span style={{fontFamily:'var(--font-mono)',fontSize:7,color:'#7a7a7a'}}>{k.d}</span>
                </div>
                <div style={{fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.1em',color:'#7a9a7a',marginTop:2}}>{k.t}</div>
              </div>
            ))}
          </div>
          {/* Chart */}
          <div style={{background:'#232323',border:'1px solid #2e2e2e',padding:8,position:'relative',minHeight:0,
            display:'flex',flexDirection:'column'}}>
            <div style={{display:'flex',justifyContent:'space-between',alignItems:'baseline'}}>
              <div style={{fontSize:10,fontWeight:600}}>Yield by week</div>
              <div style={{fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.1em',color:'#7a7a7a'}}>BU × 1000</div>
            </div>
            <svg viewBox="0 0 200 70" preserveAspectRatio="none" style={{flex:1,width:'100%',marginTop:4}}>
              {[14,28,42,56].map(y=><line key={y} x1="0" x2="200" y1={y} y2={y} stroke="#2e2e2e" strokeWidth="0.5"/>)}
              <polyline points="10,52 26,46 42,48 58,38 74,32 90,40 106,28 122,22 138,30 154,18 170,14 186,20"
                fill="none" stroke="#a64a2a" strokeWidth="1.5"/>
              <polyline points="10,52 26,46 42,48 58,38 74,32 90,40 106,28 122,22 138,30 154,18 170,14 186,20 186,68 10,68"
                fill="#a64a2a" opacity="0.15" stroke="none"/>
              <polyline points="10,58 26,54 42,55 58,50 74,47 90,49 106,42 122,40 138,42 154,36 170,34 186,38"
                fill="none" stroke="#7a9a7a" strokeWidth="0.9" strokeDasharray="2 2"/>
            </svg>
          </div>
          {/* Activity feed */}
          <div style={{background:'#232323',border:'1px solid #2e2e2e',padding:8,minHeight:0,overflow:'hidden',
            display:'flex',flexDirection:'column',gap:4}}>
            <div style={{fontSize:10,fontWeight:600,marginBottom:1}}>Activity</div>
            {[
              {t:'Bin 14',e:'Moisture +0.4%',c:'#a64a2a',time:'2m'},
              {t:'Bin 07',e:'Aeration on',c:'#7a9a7a',time:'14m'},
              {t:'Bin 21',e:'Temp alert',c:'#a64a2a',time:'1h'},
              {t:'Bin 03',e:'Loaded 412 bu',c:'#7a8aa6',time:'3h'},
              {t:'Bin 19',e:'Sensor sync',c:'#7a9a7a',time:'5h'},
            ].map((a,i)=>(
              <div key={i} style={{display:'flex',gap:5,alignItems:'center',
                fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.06em'}}>
                <span style={{width:5,height:5,background:a.c,borderRadius:'50%',flexShrink:0}}/>
                <span style={{color:'#f7f4ec',fontWeight:600,minWidth:32}}>{a.t}</span>
                <span style={{color:'#7a7a7a',flex:1,whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{a.e}</span>
                <span style={{color:'#5b5a55'}}>{a.time}</span>
              </div>
            ))}
          </div>
          {/* Bottom table — header + rows */}
          <div style={{gridColumn:'1 / -1',background:'#232323',border:'1px solid #2e2e2e',
            display:'flex',flexDirection:'column',fontFamily:'var(--font-mono)',fontSize:7,letterSpacing:'0.06em',minHeight:0,overflow:'hidden'}}>
            <div style={{display:'grid',gridTemplateColumns:'1fr 1.4fr 1fr 1fr 1fr',padding:'4px 8px',
              background:'#1a1a1a',borderBottom:'1px solid #2e2e2e',color:'#7a7a7a',letterSpacing:'0.12em'}}>
              <span>BIN</span><span>CROP</span><span>LEVEL</span><span>TEMP</span><span>STATUS</span>
            </div>
            {[
              ['#14','Hard Red Wheat','94%','51°F',{t:'OK',c:'#7a9a7a'}],
              ['#07','Yellow Corn','71%','54°F',{t:'AERATING',c:'#7a8aa6'}],
              ['#21','Soybean','38%','62°F',{t:'ALERT',c:'#a64a2a'}],
            ].map((r,i)=>(
              <div key={i} style={{display:'grid',gridTemplateColumns:'1fr 1.4fr 1fr 1fr 1fr',padding:'3px 8px',
                borderBottom:i<2?'1px solid #2e2e2e':'none',color:'#f7f4ec'}}>
                <span style={{color:'#a64a2a',fontWeight:600}}>{r[0]}</span>
                <span>{r[1]}</span><span>{r[2]}</span><span>{r[3]}</span>
                <span style={{color:r[4].c,fontWeight:600,letterSpacing:'0.1em'}}>{r[4].t}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function SpectrumCell() {
  const [pos, setPos] = useStSv(35);
  const [isDragging, setIsDragging] = useStSv(false);
  // Layout-shift-free pin: once we decide to engage the tall scroll-pin
  // shell, we keep it tall for the rest of the page-load even after the
  // user breaks out of the auto-advance. Toggling shell height mid-scroll
  // would jerk the document. `pinShellTall` is set true once and never
  // reset. `pinArmedRef` (ref-only, not state — render never reads it)
  // controls whether scroll deltas drive `pos` and whether the
  // auto-sweep is allowed to fire. `stickyEngaged` controls whether
  // the inner is `position: sticky` — released once the user has
  // fully scrubbed through the shell (ride-the-bike pattern: after
  // the first complete pass, subsequent scroll-throughs do NOT re-pin).
  const [pinShellTall, setPinShellTall] = useStSv(false);
  const [stickyEngaged, setStickyEngaged] = useStSv(true);

  const trackRef = useRefSv(null);
  const shellRef = useRefSv(null);          // tall outer container
  const interactedRef = useRefSv(false);    // user has dragged/tapped/keyed
  const pinArmedRef = useRefSv(true);       // listener guard
  const pinShellTallRef = useRefSv(false);  // mirrors pinShellTall
  const reducedMotionRef = useRefSv(false);
  const stickyEngagedRef = useRefSv(true);  // mirrors stickyEngaged
  const autoSweepRafRef = useRefSv(0);
  const autoSweepStartRef = useRefSv(0);
  const idleTimerRef = useRefSv(0);
  const sweepFiredRef = useRefSv(false);    // cap auto-sweep at one per page-load

  // Price & timeline pulled from window.MWT_PRICING (mwt-v2/pricing.js).
  // The "custom" tier shows "quote" instead of its short budget here.
  const P = window.MWT_PRICING.byKind;
  const stages = [
    { x:8,  kind:'simple',   label:'SIMPLE',    note:P.simple.weeks,   price:P.simple.budget,   url:'mainstreetbarber.com',  bizType:'Local service',
      includes:['1–3 page site','Mobile-perfect','Contact form','Hosting + SSL'] },
    { x:28, kind:'listings', label:'LISTINGS',  note:P.listings.weeks, price:P.listings.budget, url:'reddirtauto.com/inventory', bizType:'Inventory site',
      includes:['Search + filter','Up to 500 listings','Image galleries','Owner CMS'] },
    { x:50, kind:'full',     label:'FULL SITE', note:P.full.weeks,     price:P.full.budget,     url:'foundrypress.com',      bizType:'Multi-page brand',
      includes:['Multi-page site','Blog + gallery','Forms + bookings','SEO baseline'] },
    { x:72, kind:'store',    label:'STORE',     note:P.store.weeks,    price:P.store.budget,    url:'prairiegoods.com/shop', bizType:'eCommerce',
      includes:['Cart + checkout','Stripe payments','Inventory CMS','Order emails'] },
    { x:92, kind:'custom',   label:'CUSTOM',    note:P.custom.weeks,   price:'quote',           url:'app.siloanalytics.com', bizType:'Custom platform',
      includes:['Bespoke build','Logins + portals','Integrations + APIs','AI workflows'] },
  ];
  const hovered = stages.reduce((b,s)=>Math.abs(s.x-pos)<Math.abs(b.x-pos)?s:b, stages[0]);
  const currentIdx = stages.indexOf(hovered);

  // ── Disarm pin on any manual interaction ─────────────────────
  // Drag, tap-stop, keyboard arrow, and thumb focus all qualify as
  // "user took control of the slider, stop scroll-hijacking them."
  const disarmPin = () => {
    if (interactedRef.current) return;
    interactedRef.current = true;
    pinArmedRef.current = false;
    if (autoSweepRafRef.current) { window.cancelAnimationFrame(autoSweepRafRef.current); autoSweepRafRef.current = 0; }
    if (idleTimerRef.current) { window.clearTimeout(idleTimerRef.current); idleTimerRef.current = 0; }
  };

  // Pointer-driven position update. Reads pointer x relative to the track bounds.
  const positionFromPointer = (clientX) => {
    const el = trackRef.current; if (!el) return;
    const r = el.getBoundingClientRect();
    setPos(Math.max(4, Math.min(96, ((clientX - r.left) / r.width) * 100)));
  };
  const onPointerDown = (e) => {
    disarmPin();
    setIsDragging(true);
    try { e.currentTarget.setPointerCapture(e.pointerId); } catch (_) {}
    positionFromPointer(e.clientX);
  };
  const onPointerMove = (e) => {
    if (!isDragging) return;
    positionFromPointer(e.clientX);
  };
  const endDrag = (e) => {
    if (!isDragging) return;
    setIsDragging(false);
    try { e.currentTarget.releasePointerCapture(e.pointerId); } catch (_) {}
    // Compute the snap target from the pointer-up event itself rather than
    // reading `pos` from React state — the most recent `setPos` from
    // `onPointerMove` may not have committed yet, which would land the snap
    // on the wrong stop. Mirrors `positionFromPointer` math against the
    // current track bounds.
    const el = trackRef.current;
    if (!el) { return; }
    const r = el.getBoundingClientRect();
    const live = Math.max(4, Math.min(96, ((e.clientX - r.left) / r.width) * 100));
    const nearest = stages.reduce((b,s)=>Math.abs(s.x-live)<Math.abs(b.x-live)?s:b, stages[0]);
    setPos(nearest.x);
  };
  const snapTo = (idx) => {
    const clamped = Math.max(0, Math.min(stages.length - 1, idx));
    setPos(stages[clamped].x);
  };
  const onKeyDown = (e) => {
    if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') { e.preventDefault(); disarmPin(); snapTo(currentIdx - 1); }
    else if (e.key === 'ArrowRight' || e.key === 'ArrowUp') { e.preventDefault(); disarmPin(); snapTo(currentIdx + 1); }
    else if (e.key === 'Home') { e.preventDefault(); disarmPin(); snapTo(0); }
    else if (e.key === 'End')  { e.preventDefault(); disarmPin(); snapTo(stages.length - 1); }
  };
  const onStopClick = (xVal) => { disarmPin(); setPos(xVal); };
  const onThumbFocus = () => { disarmPin(); };

  // ── Reduced-motion detection ─────────────────────────────────
  // Reduced-motion users never get pin scrubbing or auto-sweep —
  // they keep the existing manual interaction with no scroll-jacking.
  useEfSv(() => {
    if (typeof window === 'undefined' || !window.matchMedia) return;
    const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
    const apply = () => {
      reducedMotionRef.current = mq.matches;
      if (mq.matches) {
        pinArmedRef.current = false;
      }
    };
    apply();
    if (mq.addEventListener) mq.addEventListener('change', apply);
    else if (mq.addListener) mq.addListener(apply);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener('change', apply);
      else if (mq.removeListener) mq.removeListener(apply);
    };
  }, []);

  // ── First-entry detection: arm the tall shell + start idle clock ─
  // IntersectionObserver fires once, the first time the section enters
  // the viewport. After that the tall shell stays tall (no layout-shift
  // mid-scroll), and the idle clock can fire the belt-and-suspenders
  // auto-sweep if no scroll deltas accumulate.
  //
  // Desktop kill switch — responsive, follows resize transitions.
  // Three reviewers (Gemini / Codex / Copilot) flagged that a
  // mount-only `matchMedia` snapshot leaks: a session that loads on
  // mobile then resizes wider keeps the scroll-pin listeners active
  // on desktop, and a session that loads on desktop then resizes
  // narrower never installs them. Subscribe to the breakpoint and
  // engage / disengage on transition. `(max-width: 767px)` (not 768)
  // because 768 is inclusive — a 768 px tablet would otherwise hit
  // the mobile path, contradicting the documented 768–1100 px
  // desktop range.
  useEfSv(() => {
    if (typeof window === 'undefined' || !window.matchMedia) return;
    if (reducedMotionRef.current) return;
    if (interactedRef.current) return;

    const mql = window.matchMedia('(max-width: 767px)');
    let io = null;

    const engage = () => {
      if (io) return;
      if (reducedMotionRef.current) return;
      if (interactedRef.current) return;
      if (pinShellTallRef.current) return;
      const el = shellRef.current; if (!el) return;
      let firedEnter = false;
      io = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
          if (!entry.isIntersecting || firedEnter) return;
          firedEnter = true;
          if (io) { io.disconnect(); io = null; }
          // Engage the tall shell only when the section has actually been
          // reached. The visual stays sticky-pinned for one extra viewport
          // height of scroll, which the wheel/touch listener maps to `pos`.
          pinShellTallRef.current = true;
          setPinShellTall(true);
          // The bento cell's row stretches to the tallest cell in that
          // row, which would balloon the side-by-side AIBanner cell into
          // a 200vh empty box. Toggle a body-scoped class so the bento
          // grid pushes the spectrum cell to its own row while pinned.
          // CSS rule lives in app/globals.css next to the other
          // .mw-spectrum-* rules. Class is prefixed with the spectrum
          // namespace so it is unambiguously owned by this component.
          if (typeof document !== 'undefined' && document.body && document.body.classList) {
            document.body.classList.add('mw-spectrum-pin-engaged');
          }
          // Belt-and-suspenders: if the user scrolls in but produces no
          // scroll delta against the shell for ~600ms (e.g., mouse stuck,
          // user reading), fire a one-shot auto-sweep. Cancelled on any
          // scroll/pointer/key activity (see disarmPin and the scroll
          // listener below).
          idleTimerRef.current = window.setTimeout(() => {
            if (!pinArmedRef.current || sweepFiredRef.current) return;
            sweepFiredRef.current = true;
            autoSweepStartRef.current = 0;
            const SWEEP_MS = 3200;
            const FROM = 4, TO = 96, SETTLE = 50;
            const tick = (ts) => {
              if (!pinArmedRef.current || interactedRef.current) {
                autoSweepRafRef.current = 0;
                return;
              }
              if (!autoSweepStartRef.current) autoSweepStartRef.current = ts;
              const t = Math.min(1, (ts - autoSweepStartRef.current) / SWEEP_MS);
              // Ease-in-out for a graceful sweep across the spectrum.
              const eased = t < 0.5 ? 2*t*t : 1 - Math.pow(-2*t + 2, 2)/2;
              const live = FROM + (TO - FROM) * eased;
              setPos(live);
              if (t < 1) {
                autoSweepRafRef.current = window.requestAnimationFrame(tick);
              } else {
                autoSweepRafRef.current = 0;
                setPos(SETTLE);
              }
            };
            autoSweepRafRef.current = window.requestAnimationFrame(tick);
          }, 600);
        });
      }, { threshold: 0.35 });
      io.observe(el);
    };

    const disengage = () => {
      // Tear down everything the engaged path can leave hanging:
      // the IntersectionObserver, the idle-timeout, any in-flight
      // auto-sweep RAF, the body class, and reset the tall-shell /
      // armed refs so a subsequent transition back to mobile re-
      // engages cleanly. The layout-shift-free invariant is broken
      // here on purpose — the alternative is the 200 vh shell
      // staying ballooned on a now-desktop viewport, which is the
      // exact bug we are fixing.
      if (io) { io.disconnect(); io = null; }
      if (idleTimerRef.current) { window.clearTimeout(idleTimerRef.current); idleTimerRef.current = 0; }
      if (autoSweepRafRef.current) { window.cancelAnimationFrame(autoSweepRafRef.current); autoSweepRafRef.current = 0; }
      pinShellTallRef.current = false;
      pinArmedRef.current = true;
      sweepFiredRef.current = false;
      setPinShellTall(false);
      stickyEngagedRef.current = true;
      setStickyEngaged(true);
      if (typeof document !== 'undefined' && document.body && document.body.classList) {
        document.body.classList.remove('mw-spectrum-pin-engaged');
      }
    };

    const apply = () => {
      if (mql.matches) engage();
      else disengage();
    };

    apply();
    if (mql.addEventListener) mql.addEventListener('change', apply);
    else if (mql.addListener) mql.addListener(apply);

    return () => {
      if (mql.removeEventListener) mql.removeEventListener('change', apply);
      else if (mql.removeListener) mql.removeListener(apply);
      disengage();
    };
  }, []);

  // ── Scroll-driven scrub ──────────────────────────────────────
  // While armed and the shell is tall, map the user's scroll progress
  // through the shell to slider `pos`. The shell is `100vh + 100vh`
  // tall and the inner is `position: sticky; height: 100vh`, so as the
  // viewport descends through the second viewport-height of the shell,
  // we have a full viewport of scroll-distance to scrub `pos` from
  // 4 → 96. Once `pos` crosses the high end the user just keeps
  // scrolling and the section unpins naturally as the sticky inner
  // releases at the bottom of the shell.
  //
  // Implementation note (post-review): we listen ONLY to `scroll` —
  // `wheel` and `touchmove` always cause `scroll` to fire too, so
  // three listeners doing the same DOM read was wasted main-thread
  // work. Then we rAF-throttle so `getBoundingClientRect()` + `setPos`
  // run at most once per frame regardless of how many scroll events
  // fire between paints. Auto-sweep / idle-timer cancellation runs
  // BEFORE any early-return so a user mid-scroll while the section
  // is just intersecting (rect.top > 0) still cancels the pending
  // 600ms sweep — that race was the Codex P1 / Copilot duplicate on
  // round 1 of PR #33.
  //
  // Desktop kill switch — responsive, mirrors the IntersectionObserver
  // effect above. Subscribes to `(max-width: 767px)` and attaches /
  // detaches the scroll listener on each transition so a session that
  // resizes from mobile to desktop tears the listener down (no scroll-
  // jacking on a now-desktop viewport) and a session that resizes
  // from desktop to mobile installs it (so the storytelling still
  // works after the resize).
  useEfSv(() => {
    if (typeof window === 'undefined' || !window.matchMedia) return;

    const mql = window.matchMedia('(max-width: 767px)');
    let scheduled = 0;
    let attached = false;

    const tick = () => {
      scheduled = 0;
      const el = shellRef.current; if (!el) return;
      const rect = el.getBoundingClientRect();
      const vh = window.innerHeight || 1;
      // Cancel any pending auto-sweep / idle timer on ANY scroll delta —
      // even before the section is fully into the scrub band — so a
      // user actively scrolling never gets the slider yanked from
      // under them by a 600ms-late timer.
      if (autoSweepRafRef.current) { window.cancelAnimationFrame(autoSweepRafRef.current); autoSweepRafRef.current = 0; }
      if (idleTimerRef.current) { window.clearTimeout(idleTimerRef.current); idleTimerRef.current = 0; }
      // Ride-the-bike: once the user has scrolled past the bottom of
      // the shell (i.e., they completed one full pass through the
      // pin), unstick the inner permanently. Subsequent scroll-throughs
      // from above will see the visual scroll naturally with the page,
      // not get pinned again. We keep the shell's `is-tall` class
      // intact to avoid layout-shift; only the sticky inner releases.
      if (stickyEngagedRef.current && rect.bottom <= 0) {
        stickyEngagedRef.current = false;
        setStickyEngaged(false);
      }
      if (!pinArmedRef.current || interactedRef.current) return;
      // Scrub window: starts when the shell's top crosses the viewport
      // top (rect.top === 0) and ends one viewport later (rect.top === -vh).
      // Outside this band we leave `pos` alone so the user can scroll past
      // the section without us yanking them back.
      if (rect.top > 0) return;
      const scrubbed = Math.min(1, Math.max(0, -rect.top / vh));
      setPos(4 + (96 - 4) * scrubbed);
    };
    const onScroll = () => {
      if (scheduled) return;
      scheduled = window.requestAnimationFrame(tick);
    };

    const attach = () => {
      if (attached) return;
      window.addEventListener('scroll', onScroll, { passive: true });
      attached = true;
    };
    const detach = () => {
      if (!attached) return;
      window.removeEventListener('scroll', onScroll);
      attached = false;
      if (scheduled) { window.cancelAnimationFrame(scheduled); scheduled = 0; }
    };

    const apply = () => {
      if (mql.matches) attach();
      else detach();
    };

    apply();
    if (mql.addEventListener) mql.addEventListener('change', apply);
    else if (mql.addListener) mql.addListener(apply);

    return () => {
      if (mql.removeEventListener) mql.removeEventListener('change', apply);
      else if (mql.removeListener) mql.removeListener(apply);
      detach();
    };
  }, []);

  // ── Cleanup any pending RAF/timeouts + body class on unmount ──
  useEfSv(() => () => {
    if (autoSweepRafRef.current) window.cancelAnimationFrame(autoSweepRafRef.current);
    if (idleTimerRef.current) window.clearTimeout(idleTimerRef.current);
    if (typeof document !== 'undefined' && document.body && document.body.classList) {
      document.body.classList.remove('mw-spectrum-pin-engaged');
    }
  }, []);

  return (
    <div
      ref={shellRef}
      className={`mw-spectrum-pin-shell${pinShellTall ? ' is-tall' : ''}`}>
      <div
        className={`mw-spectrum-pin-sticky${pinShellTall && stickyEngaged ? ' is-tall' : ''}`}>
    <div
      style={{ flex:'1 1 auto', height:'100%', padding:'24px clamp(20px,2.4vw,32px) 22px', display:'flex', flexDirection:'column', gap:18,
        position:'relative', background:'var(--accent)',
        color:'var(--accent-ink)' }}>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',gap:16,flexWrap:'wrap'}}>
        <div style={{fontFamily:'var(--font-mono)',fontSize:10,letterSpacing:'0.18em'}}>— COMPLEXITY SPECTRUM</div>
        <div style={{fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.1em',opacity:.7,whiteSpace:'nowrap'}}>↔ DRAG OR TAP A STOP</div>
      </div>

      <div style={{display:'grid',gridTemplateColumns:'minmax(0,1fr) minmax(0,46%)',gap:'clamp(20px,2.6vw,32px)',alignItems:'start',flex:1,minWidth:0}} className="mw-spectrum-grid">
        {/* LEFT: title + slider + included list */}
        <div style={{display:'flex',flexDirection:'column',gap:22,minWidth:0}}>
          <div>
            <div style={{fontFamily:'var(--font-display)',fontSize:'clamp(32px,4.6vw,56px)',fontWeight:500,lineHeight:0.93,letterSpacing:'-0.04em',display:'flex',flexWrap:'wrap',alignItems:'baseline',columnGap:14,rowGap:4}}>
              <span>{hovered.label}</span>
              <span style={{fontFamily:'var(--font-editorial)',fontStyle:'italic',fontWeight:400,fontSize:'clamp(18px,2.4vw,28px)',opacity:0.75}}>— {hovered.note}</span>
            </div>
            <div style={{fontFamily:'var(--font-mono)',fontSize:13,letterSpacing:'0.08em',opacity:0.7,marginTop:10}}>{hovered.price} · {hovered.bizType}</div>
          </div>
          {/* Slider — inset 4% on each side so end labels (SIMPLE / CUSTOM) don't clip the column edges.
              Pointer Events + setPointerCapture enable native drag on mouse, touch, and pen. Each stop
              label is a tap-target button so phone users can pick a stage without dragging. Keyboard:
              ArrowLeft/Right (or Down/Up) step stops; Home/End jump to first/last. */}
          <div
            ref={trackRef}
            className="mw-spectrum-track"
            onPointerDown={onPointerDown}
            onPointerMove={onPointerMove}
            onPointerUp={endDrag}
            onPointerCancel={endDrag}
            style={{position:'relative',height:48,padding:'0 4%',touchAction:'none',cursor:isDragging?'grabbing':'ew-resize',userSelect:'none'}}>
            <div style={{position:'absolute',top:18,left:'4%',right:'4%',height:2,background:'color-mix(in oklab,var(--accent-ink) 20%,transparent)',pointerEvents:'none'}}/>
            <div style={{position:'absolute',top:18,left:'4%',height:2,background:'var(--accent-ink)',width:`calc(${pos}% - 4%)`,maxWidth:'92%',transition:isDragging?'none':'width .25s var(--ease-out)',pointerEvents:'none'}}/>
            {stages.map(s=>{
              const active = Math.abs(s.x - pos) < 10;
              return (
                <button
                  key={s.label}
                  type="button"
                  className="mw-spectrum-stop"
                  onClick={(e)=>{e.stopPropagation(); onStopClick(s.x);}}
                  onPointerDown={(e)=>e.stopPropagation()}
                  aria-label={`Jump to ${s.label} tier`}
                  aria-pressed={active}
                  style={{position:'absolute',left:`${s.x}%`,top:0,transform:'translateX(-50%)',textAlign:'center',
                    background:'transparent',border:'none',color:'inherit',padding:'4px 6px',cursor:'pointer',
                    display:'flex',flexDirection:'column',alignItems:'center',gap:6}}>
                  <div style={{width:2,height:18,background:'var(--accent-ink)',marginTop:10,pointerEvents:'none'}}/>
                  <div style={{fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.12em',whiteSpace:'nowrap',opacity:active?1:.55,fontWeight:active?700:400,transition:'opacity .15s, font-weight .15s',pointerEvents:'none'}}>{s.label}</div>
                </button>
              );
            })}
            <div
              role="slider"
              tabIndex={0}
              aria-label="Project complexity"
              aria-valuemin={1}
              aria-valuemax={stages.length}
              aria-valuenow={currentIdx + 1}
              aria-valuetext={`${hovered.label} — ${hovered.bizType}`}
              onKeyDown={onKeyDown}
              onFocus={onThumbFocus}
              className="mw-spectrum-thumb"
              style={{position:'absolute',left:`${pos}%`,top:8,transform:'translateX(-50%)',
                width:18,height:18,background:'var(--accent-ink)',boxShadow:'0 0 0 5px var(--accent), 0 0 0 6px color-mix(in oklab,var(--accent-ink) 30%,transparent)',
                transition:isDragging?'none':'left .25s var(--ease-out)',
                touchAction:'none',cursor:isDragging?'grabbing':'grab'}}/>
          </div>

          {/* What's included */}
          <div key={`inc-${hovered.label}`} style={{display:'flex',flexWrap:'wrap',gap:6,
            animation:'mwFadeIn .35s'}}>
            {hovered.includes.map((item)=>(
              <div key={item} style={{display:'inline-flex',alignItems:'center',gap:6,
                padding:'6px 11px',
                background:'color-mix(in oklab,var(--accent-ink) 10%,transparent)',
                border:'1px solid color-mix(in oklab,var(--accent-ink) 25%,transparent)',
                fontFamily:'var(--font-mono)',fontSize:10,letterSpacing:'0.06em',whiteSpace:'nowrap'}}>
                <span style={{fontSize:8,opacity:0.7}}>✓</span>
                <span>{item}</span>
              </div>
            ))}
          </div>

          <div style={{fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.14em',opacity:0.62,display:'flex',gap:14,flexWrap:'wrap',paddingTop:10,borderTop:'1px solid color-mix(in oklab,var(--accent-ink) 18%,transparent)'}}>
            <span>◆ ALL PLANS INCLUDE HOSTING</span>
            <span style={{opacity:.4}}>·</span>
            <span>FROM $79/MO</span>
            <span style={{opacity:.4}}>·</span>
            <span>NO CONTRACT</span>
          </div>
        </div>

        {/* RIGHT: Realistic website preview — swaps cleanly between stages */}
        <div style={{position:'relative',aspectRatio:'4/3',background:'#fafaf7',
          width:'100%',maxWidth:'100%',
          border:'1px solid color-mix(in oklab,var(--accent-ink) 40%,transparent)',
          boxShadow:'0 24px 48px -22px color-mix(in oklab,var(--accent-ink) 70%,transparent), 0 2px 0 color-mix(in oklab,var(--accent-ink) 14%,transparent)',
          overflow:'hidden',display:'flex',flexDirection:'column',minWidth:0,
          color:'#1a1a1a'}}>
          {/* Browser chrome */}
          <div style={{flex:'0 0 auto',padding:'9px 11px',display:'flex',alignItems:'center',gap:10,
            borderBottom:'1px solid #d8d4ca',background:'#ecebe4'}}>
            <div style={{display:'flex',gap:5,flex:'0 0 auto'}}>
              {[0,1,2].map(i=><div key={i} style={{width:9,height:9,borderRadius:'50%',background:'#c8c3b6'}}/>)}
            </div>
            <div style={{flex:1,minWidth:0,padding:'5px 10px',background:'#fff',
              border:'1px solid #d8d4ca',fontFamily:'var(--font-mono)',fontSize:10,letterSpacing:'0.04em',
              color:'#5b5a55',overflow:'hidden',whiteSpace:'nowrap',textOverflow:'ellipsis',
              display:'flex',alignItems:'center',gap:6,
              transition:'all .35s var(--ease-out)'}}>
              <span style={{display:'inline-block',width:7,height:7,borderRadius:'50%',
                border:'1.2px solid #6b8b6b',position:'relative',flex:'0 0 auto'}}>
                <span style={{position:'absolute',left:'50%',top:'100%',width:1.2,height:3,
                  background:'#6b8b6b',transform:'translateX(-50%)'}}/>
              </span>
              <span style={{opacity:0.55,flex:'0 0 auto'}}>https://</span>
              <span key={hovered.url} style={{animation:'mwFadeIn .4s',color:'#1a1a1a',overflow:'hidden',textOverflow:'ellipsis'}}>{hovered.url}</span>
            </div>
            <div style={{fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.12em',
              color:'#a64a2a',whiteSpace:'nowrap',display:'inline-flex',alignItems:'center',gap:5,flex:'0 0 auto'}}>
              <span style={{width:6,height:6,borderRadius:'50%',background:'#a64a2a',
                animation:'mwPulse 1.6s infinite',boxShadow:'0 0 0 2px color-mix(in oklab,#a64a2a 22%,transparent)'}}/>LIVE
            </div>
          </div>

          {/* Stage indicator strip */}
          <div style={{flex:'0 0 auto',padding:'5px 11px',
            background:'#1a1a1a',
            display:'flex',justifyContent:'space-between',alignItems:'center',gap:10,
            fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.16em',
            color:'#fafaf7'}}>
            <span key={`st-${hovered.kind}`} style={{animation:'mwFadeIn .35s',minWidth:0,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>
              ◆ {hovered.label} · {hovered.bizType.toUpperCase()}
            </span>
            <span style={{opacity:0.5,flex:'0 0 auto'}}>{Math.round(pos)}% COMPLEXITY</span>
          </div>

          {/* Realistic website preview — one full mockup per stage, clean swap */}
          <div style={{flex:1,position:'relative',minHeight:0,overflow:'hidden',background:'#fafaf7'}}>
            <div key={hovered.kind} style={{position:'absolute',inset:0,
              animation:'mwFadeIn .4s var(--ease-out)'}}>
              {hovered.kind==='simple' && <PreviewSimple/>}
              {hovered.kind==='listings' && <PreviewListings/>}
              {hovered.kind==='full' && <PreviewFull/>}
              {hovered.kind==='store' && <PreviewStore/>}
              {hovered.kind==='custom' && <PreviewCustom/>}
            </div>
          </div>
        </div>
      </div>
    </div>
      </div>
    </div>
  );
}

/* ---- AI Banner ---- */
function AIBanner() {
  const convos = [
    [{r:'user',t:'is someone available saturday?'},{r:'bot',t:'yes — 10am or 2pm open.'},{r:'user',t:'book 10am, john smith.'},{r:'bot',t:'done. confirmation text sent.'}],
    [{r:'user',t:'how much for a full detail?'},{r:'bot',t:'interior + exterior starts at $180.'},{r:'user',t:'do you come to me?'},{r:'bot',t:'yes — mobile service in OKC metro.'}],
    [{r:'user',t:'do you accept walk-ins?'},{r:'bot',t:'yes, but appointments get priority.'},{r:'user',t:'what are your hours?'},{r:'bot',t:'mon–sat 8am–6pm, closed sunday.'}],
    [{r:'user',t:'is the 2018 f-150 still available?'},{r:'bot',t:'yes — 47k miles, asking $28,900.'},{r:'user',t:'can I test drive tomorrow?'},{r:'bot',t:'10am works. name and number?'}],
  ];
  const [ci, setCi] = useStSv(0); const [step, setStep] = useStSv(0);
  useEfSv(()=>{
    const conv=convos[ci];
    if(step<conv.length){const t=setTimeout(()=>setStep(s=>s+1),1400);return()=>clearTimeout(t);}
    else{const t=setTimeout(()=>{setCi(i=>(i+1)%convos.length);setStep(0);},2200);return()=>clearTimeout(t);}
  },[step,ci]);
  const msgs=convos[ci].slice(0,step);
  return (
    <div style={{padding:22,height:'100%',display:'flex',flexDirection:'column',
      gap:14,background:'var(--bg-elev-2)',border:'1px solid var(--border-strong)',
      position:'relative',overflow:'hidden'}}>
      <div style={{fontFamily:'var(--font-mono)',fontSize:10,letterSpacing:'0.18em',color:'var(--fg-4)',
        display:'flex',justifyContent:'space-between'}}>
        <span>— AI FOR YOUR CUSTOMERS</span>
        <span style={{color:'var(--accent)',display:'inline-flex',alignItems:'center',gap:6}}><DotTrace size={3}/>LIVE</span>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'minmax(0,1fr) minmax(0,260px)',gap:18,
        alignItems:'stretch',flex:1,minWidth:0}} className="mw-ai-banner-grid">
        <div style={{minWidth:0,display:'flex',flexDirection:'column',gap:14}}>
          <div style={{fontFamily:'var(--font-display)',fontSize:'clamp(22px,3vw,36px)',fontWeight:500,
            lineHeight:1.05,letterSpacing:'-0.03em'}}>
            We build by hand.<br/>
            <span style={{fontFamily:'var(--font-editorial)',fontStyle:'italic',fontWeight:400,color:'var(--accent)'}}>AI works for you.</span>
          </div>
          <div style={{fontSize:12,color:'var(--fg-3)',lineHeight:1.5}}>
            Real people design and code your site. Then we plug in a smart helper that answers questions, books jobs, and fills forms 24/7. Optional add-on from $400/mo.
          </div>
          {/* Concise inline capabilities. Replaces the prior 2x2 matrix
              that broke at the actual column width — "SMS reply when you
              can't talk" was getting squeezed into a single-character
              column and rendering vertical character fragments. The
              live chat panel on the right is the demonstration; this
              line is just the named capability list, accent-marked. */}
          <ul style={{listStyle:'none',padding:0,margin:'auto 0 0 0',display:'flex',
            flexWrap:'wrap',gap:'6px 14px',fontFamily:'var(--font-mono)',fontSize:10,
            letterSpacing:'0.12em',color:'var(--fg-3)',textTransform:'uppercase'}}>
            {['24/7 ANSWERS','APPOINTMENTS','INSTANT QUOTES','SMS REPLIES'].map((c) => (
              <li key={c} style={{display:'inline-flex',alignItems:'center',gap:6}}>
                <span aria-hidden="true" style={{width:4,height:4,
                  background:'var(--accent)',borderRadius:'50%',
                  boxShadow:'0 0 6px color-mix(in oklab,var(--accent) 60%,transparent)'}}/>
                {c}
              </li>
            ))}
          </ul>
        </div>
        <div style={{background:'var(--bg)',border:'1px solid var(--border-strong)',
          display:'flex',flexDirection:'column',minWidth:0,minHeight:0,overflow:'hidden'}}>
          <div style={{padding:'7px 10px',borderBottom:'1px solid var(--border)',
            display:'flex',alignItems:'center',gap:7,background:'var(--bg-elev-1)',flex:'0 0 auto'}}>
            <span aria-hidden="true" style={{width:6,height:6,borderRadius:'50%',background:'var(--accent)',boxShadow:'0 0 6px var(--accent)'}}/>
            <span style={{fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.16em',color:'var(--fg-4)'}}>SMART ASSISTANT · ONLINE</span>
          </div>
          {/* Messages area now flex:1 + minHeight:0 so it fills the
              right column when the bento row stretches tall, instead
              of leaving the bottom 60–70% of the panel as black void.
              justifyContent:flex-end keeps messages stacked at the
              bottom of the available space, so partial conversations
              read as "more chat above". */}
          <div style={{padding:'10px',display:'flex',flexDirection:'column',gap:7,
            flex:'1 1 auto',minHeight:0,justifyContent:'flex-end'}}>
            {msgs.map((m,i)=>(
              <div key={`${ci}-${i}`} style={{padding:'6px 9px',fontFamily:'var(--font-mono)',
                fontSize:11,lineHeight:1.4,
                color:m.r==='user'?'var(--fg-2)':'var(--accent)',
                borderLeft:`2px solid ${m.r==='user'?'var(--border-strong)':'var(--accent)'}`,
                background:m.r==='bot'?'color-mix(in oklab,var(--accent) 5%,transparent)':'transparent',
                animation:'mwFadeIn .3s',overflowWrap:'anywhere'}}>{m.t}</div>
            ))}
            {step<convos[ci].length&&convos[ci][step]?.r==='bot'&&(
              <div style={{padding:'6px 9px',borderLeft:'2px solid var(--accent)'}}><DotTrace color="var(--accent)" size={4}/></div>
            )}
          </div>
          <div style={{display:'flex',gap:4,justifyContent:'center',padding:'6px 10px',borderTop:'1px solid var(--border)',flex:'0 0 auto'}}>
            {convos.map((_,i)=>(
              <div key={i} style={{width:i===ci?12:4,height:3,
                background:i===ci?'var(--accent)':'var(--border-strong)',transition:'width .4s var(--ease-out)'}}/>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

/* ---- Build Card ---- */
/* Unique wireframe-style preview per card kind. Drawn as inline SVG, lives as a
   backdrop in the lower portion of the card and gets a subtle scale on hover. */
function BuildPreview({ kind, hover, idx = 0, count = 5 }) {
  const stroke = 'color-mix(in oklab, var(--fg-1) 18%, transparent)';
  const strokeHover = 'color-mix(in oklab, var(--accent) 50%, transparent)';
  const fill = 'color-mix(in oklab, var(--accent) 6%, transparent)';
  const accent = 'var(--accent)';
  const ink = 'var(--fg-1)';
  const muted = 'var(--fg-4)';
  const s = { stroke: hover ? strokeHover : stroke, strokeWidth: 1, fill: 'none' };
  const sf = { ...s, fill };
  const v = ((idx % count) + count) % count;
  const clipId = React.useMemo(() => 'bp-clip-' + Math.random().toString(36).slice(2, 8), []);

  // Browser frame helper — chrome bar, viewport rect, and a clip path to scope contents
  const Frame = ({ url, children, padViewport = 10 }) => (
    <g>
      {/* Outer body */}
      <rect x="2" y="2" width="196" height="126" fill="var(--bg-elev-2)"
        stroke={hover ? strokeHover : stroke} strokeWidth="1"/>
      {/* Chrome bar */}
      <rect x="2" y="2" width="196" height="14" fill="color-mix(in oklab, var(--bg-elev-2) 60%, var(--bg-elev-1))"
        stroke={hover ? strokeHover : stroke} strokeWidth="1"/>
      {/* Traffic lights */}
      <circle cx="8"  cy="9" r="1.6" fill={accent} opacity="0.55"/>
      <circle cx="13" cy="9" r="1.6" fill={muted} opacity="0.5"/>
      <circle cx="18" cy="9" r="1.6" fill={muted} opacity="0.4"/>
      {/* URL pill */}
      <rect x="26" y="5.5" width="160" height="7" rx="1.5"
        fill="color-mix(in oklab, var(--bg-elev-1) 70%, transparent)"
        stroke={stroke} strokeWidth="0.5"/>
      <text x="30" y="10.5" fontSize="4.5" fill={muted}
        fontFamily="var(--font-mono)" letterSpacing="0.04em">{url}</text>
      {/* Live dot */}
      <circle cx="190" cy="9" r="1.2" fill={accent}>
        <animate attributeName="opacity" values="0.4;1;0.4" dur="2.4s" repeatCount="indefinite"/>
      </circle>
      <defs>
        <clipPath id={clipId}>
          <rect x={2 + padViewport - 8} y="17" width={196 - 2*(padViewport - 8)} height="111"/>
        </clipPath>
      </defs>
      <g clipPath={`url(#${clipId})`}>{children}</g>
    </g>
  );

  // Scroll-shift wrapper — each variant rendered at its own y-band, viewport translates so
  // the active band is centered. Smooth vertical travel = real scroll motion.
  // Each variant is drawn in its own coordinate space starting near y=22 (TopBar).
  // We stack variants vertically (i * bandH apart) and translate the whole stack
  // by -v*bandH so the active variant aligns with the viewport top (y=17).
  // No extra +17 — that was pushing every TopBar 17px below the chrome bar.
  const Scroller = ({ bandH = 111, children }) => {
    return (
      <g style={{ transform: `translateY(${-v * bandH}px)`, transition: 'transform .7s var(--ease-out)' }}>
        {React.Children.map(children, (child, i) => (
          <g style={{ transform: `translateY(${i * bandH}px)` }}>
            {child}
          </g>
        ))}
      </g>
    );
  };

  return (
    <svg viewBox="0 0 200 130" preserveAspectRatio="xMidYMid meet"
      style={{ width:'100%', height:'100%', minHeight:130, display:'block', overflow:'hidden',
        transform: hover ? 'scale(1.01)' : 'none', transformOrigin: 'center', transition: 'transform .3s var(--ease-out)' }}>

      {/* LISTINGS — browser frame; alternates grid view / single listing detail */}
      {kind === 'listings' && (() => {
        const TopBar = () => (
          <g>
            <rect x="14" y="22" width="172" height="8" fill="color-mix(in oklab, var(--bg-elev-1) 70%, transparent)"/>
            <circle cx="20" cy="26" r="1.6" fill={accent}/>
            <line {...s} x1="28" y1="26" x2="58" y2="26" strokeWidth="1" stroke={ink}/>
            <rect x="62" y="23" width="60" height="6" fill="var(--bg-elev-1)" stroke={stroke} strokeWidth="0.5"/>
            <text x="66" y="27" fontSize="3" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.08em">SEARCH ALL</text>
            <line {...s} x1="128" y1="26" x2="148" y2="26"/>
            <text x="178" y="27" fontSize="4" textAnchor="end" fill={accent} fontFamily="var(--font-mono)" fontWeight="700" letterSpacing="0.1em">FILTER ▾</text>
          </g>
        );
        const Mountain = (props) => (
          <path d={`M${props.x} ${props.y+18} L${props.x+8} ${props.y+8} L${props.x+15} ${props.y+12} L${props.x+24} ${props.y+5} L${props.x+30} ${props.y+18} Z`}
            fill="color-mix(in oklab, var(--accent) 24%, var(--bg-elev-2))" stroke={stroke} strokeWidth="0.5"/>
        );
        const variants = [
          // Variant A: 6-card grid, one new highlight
          (
            <g key="0">
              <TopBar/>
              <text x="14" y="40" fontSize="3.6" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.12em">247 RESULTS · NEAR YOU</text>
              <text x="186" y="40" fontSize="3.6" textAnchor="end" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.1em">SORT: NEW ▾</text>
              {[0,1,2,3,4,5].map(i => {
                const x = 14 + (i%3) * 60, y = 44 + Math.floor(i/3) * 38;
                const isNew = i === (v % 6);
                return (
                  <g key={i} style={{ transition: 'opacity .55s' }} opacity={isNew ? 1 : 0.72}>
                    <rect x={x} y={y} width="56" height="34"
                      fill={isNew ? 'color-mix(in oklab, var(--accent) 8%, var(--bg-elev-2))' : 'var(--bg-elev-2)'}
                      stroke={isNew ? accent : (hover ? strokeHover : stroke)}
                      strokeWidth={isNew ? 1.4 : 1}/>
                    <rect x={x+2} y={y+2} width="52" height="18" fill={fill} stroke={stroke} strokeWidth="0.4"/>
                    <Mountain x={x+13} y={y+2}/>
                    <circle cx={x+44} cy={y+7} r="1.6" fill={isNew ? accent : muted}/>
                    <line {...s} x1={x+3} y1={y+24} x2={x+34} y2={y+24} strokeWidth="1.2"
                      stroke={isNew ? accent : ink}/>
                    <line {...s} x1={x+3} y1={y+28} x2={x+24} y2={y+28} strokeWidth="0.6"/>
                    <text x={x+53} y={y+28.5} fontSize="3.4" textAnchor="end"
                      fill={isNew ? accent : muted} fontFamily="var(--font-mono)" fontWeight="700">${(120 + i*30) + (isNew ? 9 : 0)}</text>
                    {isNew && (
                      <g>
                        <rect x={x+2} y={y+2} width="14" height="4" fill={accent}/>
                        <text x={x+9} y={y+5.4} fontSize="2.6" textAnchor="middle" fill="var(--bg-elev-1)"
                          fontFamily="var(--font-mono)" fontWeight="700" letterSpacing="0.08em">NEW</text>
                      </g>
                    )}
                  </g>
                );
              })}
            </g>
          ),
          // Variant B: single listing detail page (clicked-in)
          (
            <g key="1">
              <TopBar/>
              {/* Breadcrumb */}
              <text x="14" y="40" fontSize="3.4" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.1em">← BACK · LISTINGS / DETAIL</text>
              {/* Big photo */}
              <rect {...sf} x="14" y="46" width="100" height="62"/>
              <Mountain x={42} y={62}/>
              <circle cx="98" cy="58" r="3.5" fill={accent} opacity="0.8"/>
              {/* Thumbnail strip */}
              <rect x="14" y="112" width="22" height="10" fill={fill} stroke={accent}/>
              <rect x="40" y="112" width="22" height="10" fill={fill} stroke={stroke}/>
              <rect x="66" y="112" width="22" height="10" fill={fill} stroke={stroke}/>
              <rect x="92" y="112" width="22" height="10" fill={fill} stroke={stroke}/>
              {/* Right: details */}
              <line {...s} x1="120" y1="50" x2="180" y2="50" strokeWidth="2.2" stroke={ink}/>
              <line {...s} x1="120" y1="56" x2="170" y2="56" strokeWidth="2.2" stroke={ink}/>
              <text x="120" y="68" fontSize="6" fill={accent} fontFamily="var(--font-display)" fontWeight="700">$1,420</text>
              <text x="180" y="68" fontSize="3" textAnchor="end" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.08em">/ MO</text>
              <line {...s} x1="120" y1="76" x2="180" y2="76" strokeWidth="0.6"/>
              {[0,1,2].map(i=>(
                <g key={i}>
                  <text x="120" y={86+i*7} fontSize="3" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.08em">{['BEDS · 3','BATHS · 2','SQ FT · 1,840'][i]}</text>
                </g>
              ))}
              <rect x="120" y="110" width="60" height="10" fill={accent}/>
              <text x="150" y="117" fontSize="4.4" textAnchor="middle" fill="var(--bg-elev-1)" fontFamily="var(--font-mono)" fontWeight="700" letterSpacing="0.08em">REQUEST TOUR →</text>
            </g>
          ),
          // Variant C: list view with sidebar filter
          (
            <g key="2">
              <TopBar/>
              {/* Filter sidebar */}
              <rect {...sf} x="14" y="36" width="40" height="86"/>
              <text x="18" y="44" fontSize="3.4" fill={accent} fontFamily="var(--font-mono)" fontWeight="700" letterSpacing="0.14em">FILTERS</text>
              <line {...s} x1="18" y1="48" x2="50" y2="48" strokeWidth="0.4"/>
              {/* Filter labels — short text instead of weird stacked lines */}
              {['BEDS','BATHS','PRICE','SQ FT','TYPE'].map((label, i) => (
                <g key={label}>
                  <rect x="18" y={52+i*10} width="3" height="3"
                    fill={i===(v%5) ? accent : 'transparent'}
                    stroke={i===(v%5) ? accent : muted} strokeWidth="0.6"/>
                  <text x="24" y={55+i*10} fontSize="3" fill={i===(v%5) ? accent : muted}
                    fontFamily="var(--font-mono)" letterSpacing="0.1em" fontWeight={i===(v%5)?700:400}>{label}</text>
                </g>
              ))}
              <rect x="18" y="106" width="32" height="8" fill={accent}/>
              <text x="34" y="111.5" fontSize="3.6" textAnchor="middle" fill="var(--bg-elev-1)"
                fontFamily="var(--font-mono)" fontWeight="700" letterSpacing="0.1em">APPLY →</text>

              {/* List rows — cleaner, no weird shapes */}
              {[
                {bd:3, ba:2, sf:1240, p:280},
                {bd:4, ba:2, sf:1820, p:320},
                {bd:3, ba:3, sf:2100, p:360},
                {bd:5, ba:3, sf:2480, p:420},
              ].map((d, i) => {
                const y = 38 + i * 22;
                const isHot = i === (v % 4);
                return (
                  <g key={i} style={{ transition: 'opacity .5s' }} opacity={isHot ? 1 : 0.78}>
                    <rect x="58" y={y} width="128" height="20"
                      fill={isHot ? 'color-mix(in oklab, var(--accent) 8%, var(--bg-elev-2))' : 'var(--bg-elev-2)'}
                      stroke={isHot ? accent : stroke}/>
                    {/* Photo thumbnail */}
                    <rect x="60" y={y+2} width="22" height="16" fill={fill} stroke={stroke} strokeWidth="0.4"/>
                    <path d={`M60 ${y+18} L66 ${y+10} L71 ${y+13} L76 ${y+8} L82 ${y+18} Z`}
                      fill="color-mix(in oklab, var(--accent) 30%, var(--bg-elev-2))" opacity="0.7"/>
                    <circle cx="78" cy={y+6} r="1.2" fill={muted} opacity="0.6"/>
                    {/* Address line */}
                    <text x="86" y={y+8} fontSize="4.2" fill={isHot?accent:ink}
                      fontFamily="var(--font-display)" fontWeight="600" letterSpacing="-0.01em">
                      {`${1240 + i * 80} N ${['Maple','Cedar','Walnut','Oak'][i]} St`}
                    </text>
                    {/* Specs line */}
                    <text x="86" y={y+14} fontSize="3.2" fill={muted}
                      fontFamily="var(--font-mono)" letterSpacing="0.1em">
                      {`${d.bd} BD · ${d.ba} BA · ${d.sf.toLocaleString()} SF`}
                    </text>
                    {/* Status pill */}
                    <rect x="86" y={y+15.5} width="14" height="3.5" fill="none"
                      stroke={isHot ? accent : muted} strokeWidth="0.4" opacity={isHot?0:0.7}/>
                    {isHot && (
                      <g>
                        <rect x="86" y={y+15.5} width="14" height="3.5" fill={accent}/>
                        <text x="93" y={y+18.4} fontSize="2.4" textAnchor="middle"
                          fill="var(--bg-elev-1)" fontFamily="var(--font-mono)" fontWeight="700" letterSpacing="0.1em">NEW</text>
                      </g>
                    )}
                    {/* Price */}
                    <text x="184" y={y+9} fontSize="5" textAnchor="end"
                      fill={isHot?accent:ink} fontFamily="var(--font-display)" fontWeight="700" letterSpacing="-0.02em">${d.p}k</text>
                    <text x="184" y={y+15} fontSize="2.6" textAnchor="end"
                      fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.1em">EST. ${Math.round(d.p*4.6)}/MO</text>
                  </g>
                );
              })}
            </g>
          ),
          // Variant D: map + pinned results (real-feeling search map)
          (
            <g key="3">
              <TopBar/>
              <rect {...sf} x="14" y="36" width="172" height="86"/>
              {/* Faux road grid */}
              <g opacity="0.45">
                {[46,60,74,88,102,116].map(y => (
                  <line key={y} x1="16" y1={y} x2="184" y2={y} stroke={stroke} strokeWidth="0.4"/>
                ))}
                {[28,52,76,100,124,148,172].map(x => (
                  <line key={x} x1={x} y1="38" x2={x} y2="120" stroke={stroke} strokeWidth="0.4"/>
                ))}
              </g>
              {/* River curve */}
              <path d="M16 60 Q 60 80 100 70 T 184 90" stroke={accent} strokeWidth="0.8" fill="none" opacity="0.4"/>
              {/* Pins */}
              {[
                {x:42, y:58, hot:true},
                {x:78, y:88, hot:false},
                {x:118, y:62, hot:false},
                {x:152, y:96, hot:false},
                {x:96, y:54, hot:false},
                {x:64, y:104, hot:false},
              ].map((p, i) => {
                const isHot = i === (v % 6);
                return (
                  <g key={i} style={{ transition: 'transform .5s var(--ease-out)' }}>
                    {isHot && <circle cx={p.x} cy={p.y} r="6" fill={accent} opacity="0.18">
                      <animate attributeName="r" values="3;8;6" dur="0.6s" fill="freeze"/>
                    </circle>}
                    <path d={`M${p.x} ${p.y-5} a 3 3 0 1 1 0.01 0 z M${p.x-2.5} ${p.y-1} L${p.x} ${p.y+3} L${p.x+2.5} ${p.y-1}`}
                      fill={isHot ? accent : 'var(--bg-elev-1)'}
                      stroke={isHot ? accent : muted} strokeWidth="0.8"/>
                    <circle cx={p.x} cy={p.y-5} r="1.4" fill="var(--bg-elev-1)"/>
                    {isHot && (
                      <g>
                        <rect x={p.x+5} y={p.y-10} width="34" height="10" fill="var(--bg-elev-1)" stroke={accent}/>
                        <text x={p.x+7} y={p.y-6} fontSize="3" fill={accent} fontFamily="var(--font-mono)" fontWeight="700" letterSpacing="0.06em">${280+i*30}k</text>
                        <text x={p.x+7} y={p.y-2} fontSize="2.4" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.06em">3 BD · 2 BA</text>
                      </g>
                    )}
                  </g>
                );
              })}
              {/* Map controls */}
              <rect x="172" y="40" width="10" height="10" fill="var(--bg-elev-1)" stroke={stroke}/>
              <text x="177" y="47" fontSize="6" textAnchor="middle" fill={muted} fontFamily="var(--font-mono)" fontWeight="700">+</text>
              <rect x="172" y="52" width="10" height="10" fill="var(--bg-elev-1)" stroke={stroke}/>
              <text x="177" y="59" fontSize="6" textAnchor="middle" fill={muted} fontFamily="var(--font-mono)" fontWeight="700">−</text>
              {/* Result count */}
              <rect x="18" y="38" width="42" height="9" fill="var(--bg-elev-1)" stroke={stroke}/>
              <text x="22" y="44" fontSize="3" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.08em">6 ON THIS MAP</text>
            </g>
          ),
        ];
        return (
          <Frame url={`midwesttech.dev/listings`} padViewport={8}>
            <Scroller>{variants}</Scroller>
          </Frame>
        );
      })()}

      {/* SIMPLE — browser frame; content scrolls vertically through 5 page variants */}
      {kind === 'simple' && (() => {
        const variants = [
          // Hero + CTA + image
          (
            <g key="0">
              {/* Header strip */}
              <rect x="14" y="22" width="172" height="6" fill="color-mix(in oklab, var(--bg-elev-1) 60%, transparent)"/>
              <circle cx="20" cy="25" r="1.5" fill={accent}/>
              <line {...s} x1="160" y1="25" x2="180" y2="25" strokeWidth="0.8"/>
              {/* Hero headline */}
              <line {...s} x1="22" y1="40" x2="100" y2="40" strokeWidth="2.5" stroke={ink}/>
              <line {...s} x1="22" y1="46" x2="80" y2="46" strokeWidth="2.5" stroke={ink}/>
              {/* Subhead */}
              <line {...s} x1="22" y1="56" x2="92" y2="56"/>
              <line {...s} x1="22" y1="61" x2="78" y2="61"/>
              {/* CTA */}
              <rect x="22" y="70" width="42" height="9" fill={accent} opacity="0.9"/>
              <rect x="68" y="70" width="32" height="9" fill="none" stroke={accent} strokeWidth="0.8"/>
              {/* Hero image */}
              <rect {...sf} x="118" y="36" width="60" height="58"/>
              <circle cx="148" cy="58" r="8" stroke={accent} strokeWidth="1" fill="none"/>
              <path {...s} d="M118 90 L138 70 L158 80 L178 60 L178 94 L118 94 Z" fill="color-mix(in oklab, var(--accent) 12%, transparent)"/>
            </g>
          ),
          // About / mission section
          (
            <g key="1">
              <line {...s} x1="22" y1="32" x2="60" y2="32" strokeWidth="2" stroke={accent}/>
              <line {...s} x1="22" y1="42" x2="170" y2="42" strokeWidth="1.5" stroke={ink}/>
              <line {...s} x1="22" y1="48" x2="160" y2="48"/>
              <line {...s} x1="22" y1="53" x2="155" y2="53"/>
              <line {...s} x1="22" y1="58" x2="140" y2="58"/>
              <rect {...sf} x="22" y="68" width="156" height="36"/>
              <line {...s} x1="30" y1="78" x2="170" y2="78"/>
              <line {...s} x1="30" y1="84" x2="160" y2="84"/>
              <line {...s} x1="30" y1="90" x2="100" y2="90" stroke={accent}/>
            </g>
          ),
          // Services 3-up — proper page header + 3 service tiles
          (
            <g key="2">
              {/* Mini header bar to anchor the page (matches other variants) */}
              <rect x="14" y="22" width="172" height="6" fill="color-mix(in oklab, var(--bg-elev-1) 60%, transparent)"/>
              <circle cx="20" cy="25" r="1.5" fill={accent}/>
              <line {...s} x1="160" y1="25" x2="180" y2="25" strokeWidth="0.8"/>
              {/* Section title + kicker (real text, no floating dashes) */}
              <text x="22" y="40" fontSize="6" fill={ink} fontFamily="var(--font-display)" fontWeight="600" letterSpacing="-0.02em">What we do</text>
              <text x="22" y="48" fontSize="3.4" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.1em">THREE WAYS WE HELP</text>
              <line {...s} x1="22" y1="52" x2="178" y2="52" strokeWidth="0.4"/>
              {[0,1,2].map(i => {
                const x = 22 + i * 54;
                return (
                  <g key={i}>
                    <rect {...sf} x={x} y="58" width="48" height="56"/>
                    <circle cx={x+24} cy={72} r="5" stroke={accent} fill="none" strokeWidth="1"/>
                    <line {...s} x1={x+8} y1={86} x2={x+40} y2={86} strokeWidth="1.5" stroke={ink}/>
                    <line {...s} x1={x+8} y1={92} x2={x+36} y2={92}/>
                    <line {...s} x1={x+8} y1={98} x2={x+32} y2={98}/>
                    <rect x={x+8} y={104} width="14" height="3" fill={accent} opacity="0.85"/>
                  </g>
                );
              })}
            </g>
          ),
          // Testimonials / reviews — clean 5-point stars, tightly inside the card
          (
            <g key="3">
              {[0,1].map(i => {
                const y = 32 + i * 38;
                // Build a 5-point star path of size r centered at (cx, cy)
                const star = (cx, cy, r=2) => {
                  const pts = [];
                  for (let k = 0; k < 10; k++) {
                    const ang = -Math.PI/2 + k * Math.PI/5;
                    const rad = k % 2 === 0 ? r : r * 0.42;
                    pts.push(`${(cx + Math.cos(ang)*rad).toFixed(2)},${(cy + Math.sin(ang)*rad).toFixed(2)}`);
                  }
                  return pts.join(' ');
                };
                return (
                  <g key={i}>
                    <rect {...sf} x="22" y={y} width="156" height="32"/>
                    <text x="30" y={y+12} fontSize="11" fill={accent} fontFamily="var(--font-display)" fontWeight="600">"</text>
                    <line {...s} x1="40" y1={y+8}  x2="168" y2={y+8} strokeWidth="1.4" stroke={ink}/>
                    <line {...s} x1="40" y1={y+14} x2="160" y2={y+14}/>
                    <line {...s} x1="40" y1={y+19} x2="130" y2={y+19}/>
                    {/* 5 stars in a row, center vertically inside the bottom strip */}
                    {[0,1,2,3,4].map(k => (
                      <polygon key={k} points={star(42 + k*5.5, y+27, 2.1)}
                        fill={accent} opacity="0.92"/>
                    ))}
                    <text x={42 + 5*5.5 + 4} y={y+28.4} fontSize="3.4" fill={muted}
                      fontFamily="var(--font-mono)" letterSpacing="0.1em">5.0 · {i===0?'JAMIE R.':'CASEY P.'}</text>
                  </g>
                );
              })}
            </g>
          ),
          // Contact / footer
          (
            <g key="4">
              <line {...s} x1="22" y1="32" x2="70" y2="32" strokeWidth="2" stroke={ink}/>
              <rect {...sf} x="22" y="42" width="100" height="56"/>
              <line {...s} x1="28" y1="50" x2="50" y2="50"/>
              <rect x="28" y="54" width="88" height="6" fill="var(--bg-elev-1)" stroke={stroke}/>
              <line {...s} x1="28" y1="66" x2="50" y2="66"/>
              <rect x="28" y="70" width="88" height="6" fill="var(--bg-elev-1)" stroke={stroke}/>
              <line {...s} x1="28" y1="82" x2="50" y2="82"/>
              <rect x="28" y="86" width="88" height="8" fill={accent} opacity="0.9"/>
              {/* Map / contact info */}
              <rect {...sf} x="128" y="42" width="50" height="56"/>
              <circle cx="153" cy="65" r="3" fill={accent}/>
              <circle cx="153" cy="65" r="6" stroke={accent} fill="none" strokeWidth="0.6" opacity="0.5"/>
              <line {...s} x1="135" y1="80" x2="172" y2="80"/>
              <line {...s} x1="135" y1="86" x2="165" y2="86"/>
            </g>
          ),
        ];
        return (
          <Frame url={`midwesttech.dev/simple`} padViewport={8}>
            <Scroller>{variants}</Scroller>
          </Frame>
        );
      })()}

      {/* FULL — browser frame; scrolls through 5 multi-page variants */}
      {kind === 'full' && (() => {
        const navTab = v % 4;
        const TopNav = ({active}) => (
          <g>
            <rect x="14" y="22" width="172" height="8" fill="color-mix(in oklab, var(--bg-elev-1) 70%, transparent)"/>
            <circle cx="20" cy="26" r="1.6" fill={accent}/>
            {[0,1,2,3].map(i => (
              <g key={i}>
                <line {...s} x1={70+i*22} y1="26" x2={86+i*22} y2="26"
                  stroke={i===active?accent:(hover?strokeHover:stroke)}
                  strokeWidth={i===active?1.6:1}/>
                {i===active && <rect x={70+i*22} y="29" width="16" height="1" fill={accent}/>}
              </g>
            ))}
          </g>
        );
        const variants = [
          // Hero + sidebar + 2 tiles
          (
            <g key="0">
              <TopNav active={navTab}/>
              <rect {...sf} x="22" y="34" width="40" height="60"/>
              {[0,1,2,3].map(i => <line key={i} {...s} x1="26" y1={42+i*7} x2={56-i*4} y2={42+i*7}/>)}
              <rect {...sf} x="68" y="34" width="110" height="28"/>
              <line {...s} x1="74" y1="44" x2="160" y2="44" strokeWidth="2" stroke={ink}/>
              <line {...s} x1="74" y1="51" x2="150" y2="51"/>
              <rect x="74" y="56" width="20" height="3" fill={accent}/>
              <rect {...sf} x="68" y="66" width="52" height="28"/>
              <rect {...sf} x="126" y="66" width="52" height="28"/>
            </g>
          ),
          // Tabbed content + 3 tiles
          (
            <g key="1">
              <TopNav active={navTab}/>
              {[0,1,2,3].map(i => (
                <rect key={i} x={22+i*22} y="34" width="20" height="6"
                  fill={i===0?accent:'transparent'} stroke={i===0?accent:stroke} opacity={i===0?0.85:1}/>
              ))}
              <rect {...sf} x="22" y="44" width="156" height="20"/>
              <line {...s} x1="28" y1="52" x2="160" y2="52"/>
              <line {...s} x1="28" y1="58" x2="140" y2="58"/>
              {[0,1,2].map(i => {
                const x = 22 + i * 54;
                return (
                  <g key={i}>
                    <rect {...sf} x={x} y="68" width="48" height="26"/>
                    <line {...s} x1={x+4} y1="76" x2={x+38} y2="76"/>
                    <line {...s} x1={x+4} y1="82" x2={x+30} y2="82"/>
                  </g>
                );
              })}
            </g>
          ),
          // Article / blog
          (
            <g key="2">
              <TopNav active={navTab}/>
              <rect {...sf} x="22" y="34" width="156" height="22"/>
              <line {...s} x1="28" y1="44" x2="120" y2="44" strokeWidth="2.5" stroke={ink}/>
              <line {...s} x1="28" y1="50" x2="100" y2="50"/>
              {[0,1,2,3,4,5].map(i => (
                <line key={i} {...s} x1="22" y1={62+i*5} x2={22 + (i%2===0?156:140)} y2={62+i*5}/>
              ))}
              <rect x="22" y="92" width="20" height="2" fill={accent}/>
            </g>
          ),
          // Gallery 4-up
          (
            <g key="3">
              <TopNav active={navTab}/>
              {[0,1,2,3].map(i => {
                const x = 22 + (i%4) * 40;
                return (
                  <g key={i}>
                    <rect {...sf} x={x} y="34" width="34" height="34"/>
                    <circle cx={x+17} cy="48" r="5" stroke={accent} fill="none" strokeWidth="0.8" opacity="0.7"/>
                    <path {...s} d={`M${x} 60 L${x+10} 50 L${x+20} 56 L${x+34} 46 L${x+34} 68 L${x} 68 Z`}
                      fill="color-mix(in oklab, var(--accent) 10%, transparent)"/>
                  </g>
                );
              })}
              <rect {...sf} x="22" y="72" width="156" height="22"/>
              <line {...s} x1="28" y1="80" x2="160" y2="80"/>
              <line {...s} x1="28" y1="86" x2="140" y2="86"/>
            </g>
          ),
          // Team / about grid
          (
            <g key="4">
              <TopNav active={navTab}/>
              <line {...s} x1="22" y1="40" x2="68" y2="40" strokeWidth="2" stroke={ink}/>
              {[0,1,2,3].map(i => {
                const x = 22 + (i%4) * 40;
                return (
                  <g key={i}>
                    <rect {...sf} x={x} y="48" width="34" height="46"/>
                    <circle cx={x+17} cy={62} r="6" stroke={accent} fill="none" strokeWidth="0.8"/>
                    <line {...s} x1={x+4} y1={76} x2={x+30} y2={76} strokeWidth="1.4" stroke={ink}/>
                    <line {...s} x1={x+4} y1={82} x2={x+24} y2={82}/>
                    <rect x={x+4} y={86} width="12" height="2" fill={accent}/>
                  </g>
                );
              })}
            </g>
          ),
        ];
        return (
          <Frame url={`midwesttech.dev/full-website`} padViewport={8}>
            <Scroller>{variants}</Scroller>
          </Frame>
        );
      })()}

      {/* STORE — browser frame; product grid scrolls; cart bumps when count changes */}
      {kind === 'store' && (() => {
        const cartCount = (v % 5) + 1;
        const TopBar = () => (
          <g>
            <rect x="14" y="22" width="172" height="8" fill="color-mix(in oklab, var(--bg-elev-1) 70%, transparent)"/>
            <circle cx="20" cy="26" r="1.6" fill={accent}/>
            <line {...s} x1="28" y1="26" x2="60" y2="26" strokeWidth="1" stroke={ink}/>
            {/* Search pill */}
            <rect x="80" y="23" width="58" height="6" fill="var(--bg-elev-1)" stroke={stroke} strokeWidth="0.5"/>
            <circle cx="84" cy="26" r="1.2" stroke={muted} strokeWidth="0.6" fill="none"/>
            <text x="90" y="27" fontSize="3" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.08em">SEARCH</text>
            {/* Cart icon, right-aligned in the chrome bar — bumps when count changes */}
            <g transform="translate(170, 22)" key={`cart-${v}`}>
              <g style={{ animation: 'mwCartBump 0.5s var(--ease-out)', transformOrigin: '6px 4px' }}>
                {/* Cart body — clean trapezoidal basket + handle */}
                <path d="M0 1.2 L2.2 1.2 L3.4 6.6 L10.4 6.6 L11.6 2.6 L3.0 2.6"
                  stroke={accent} strokeWidth="0.9" fill="none"
                  strokeLinejoin="round" strokeLinecap="round"/>
                {/* Wheels */}
                <circle cx="4.6" cy="8.4" r="0.9" fill={accent}/>
                <circle cx="9.4" cy="8.4" r="0.9" fill={accent}/>
                {/* Count badge — tucked into top-right of cart */}
                <circle cx="12" cy="0.6" r="2.2" fill={accent}/>
                <text x="12" y="1.7" fontSize="2.8" textAnchor="middle"
                  fill="var(--bg-elev-1)" fontFamily="var(--font-mono)" fontWeight="700">{cartCount}</text>
              </g>
            </g>
          </g>
        );
        // Product slot
        const Product = ({ x, y, fresh, label }) => (
          <g style={{ transition: 'opacity .55s', transform: fresh ? 'scale(1.03)' : 'scale(1)', transformOrigin: `${x+24}px ${y+24}px` }}
             opacity={fresh ? 1 : 0.78}>
            <rect x={x} y={y} width="48" height="48"
              fill={fresh ? 'color-mix(in oklab, var(--accent) 8%, var(--bg-elev-2))' : 'var(--bg-elev-2)'}
              stroke={fresh ? accent : (hover ? strokeHover : stroke)}
              strokeWidth={fresh ? 1.4 : 1}/>
            {/* Product image area */}
            <rect x={x+2} y={y+2} width="44" height="26"
              fill={fresh ? 'color-mix(in oklab, var(--accent) 22%, transparent)' : fill}/>
            <circle cx={x+24} cy={y+15} r="6" stroke={fresh ? accent : stroke} strokeWidth="0.8" fill="none"/>
            <line {...s} x1={x+4} y1={y+32} x2={x+34} y2={y+32} strokeWidth="1.4"
              stroke={fresh ? accent : (hover ? strokeHover : stroke)}/>
            <line {...s} x1={x+4} y1={y+37} x2={x+26} y2={y+37}/>
            <rect x={x+4} y={y+41} width="14" height="4" fill={fresh ? accent : muted}/>
            <text x={x+44} y={y+44} fontSize="3.5" textAnchor="end"
              fill={fresh ? accent : muted} fontFamily="var(--font-mono)" fontWeight="600">{label}</text>
            {fresh && (
              <rect x={x} y={y - 2} width="14" height="2" fill={accent}>
                <animate attributeName="width" values="0;14" dur="0.45s" fill="freeze"/>
              </rect>
            )}
          </g>
        );
        const variants = [
          // Page 1: featured + 4 products
          (
            <g key="0">
              <TopBar/>
              <rect {...sf} x="14" y="34" width="172" height="22"/>
              <line {...s} x1="22" y1="42" x2="100" y2="42" strokeWidth="2" stroke={ink}/>
              <line {...s} x1="22" y1="48" x2="80" y2="48"/>
              <rect x="22" y="50" width="24" height="3" fill={accent}/>
              {[0,1,2,3].map(i => {
                const x = 14 + (i%4) * 47, y = 60;
                return <Product key={i} x={x+1} y={y} fresh={i === (v%4)} label={['NEW','HOT','SALE','$•'][i]}/>;
              })}
            </g>
          ),
          // Page 2: 6 product grid
          (
            <g key="1">
              <TopBar/>
              {[0,1,2,3,4,5].map(i => {
                const x = 14 + (i%3) * 62, y = 34 + Math.floor(i/3) * 56;
                return (
                  <g key={i} opacity={i === (v%6) ? 1 : 0.78}>
                    <rect x={x} y={y} width="58" height="50"
                      fill={i === (v%6) ? 'color-mix(in oklab, var(--accent) 8%, var(--bg-elev-2))' : 'var(--bg-elev-2)'}
                      stroke={i === (v%6) ? accent : stroke}/>
                    <rect x={x+2} y={y+2} width="54" height="28" fill={fill}/>
                    <line {...s} x1={x+4} y1={y+34} x2={x+38} y2={y+34}/>
                    <rect x={x+4} y={y+40} width="14" height="3" fill={accent}/>
                    <rect x={x+42} y={y+40} width="12" height="6" fill={accent} opacity="0.85"/>
                  </g>
                );
              })}
            </g>
          ),
          // Page 3: PDP — single product detail
          (
            <g key="2">
              <TopBar/>
              <rect {...sf} x="14" y="34" width="86" height="86"/>
              <circle cx="57" cy="68" r="14" stroke={accent} strokeWidth="1" fill="none"/>
              <rect x="20" y="106" width="14" height="10" fill={fill} stroke={stroke}/>
              <rect x="38" y="106" width="14" height="10" fill={fill} stroke={stroke}/>
              <rect x="56" y="106" width="14" height="10" fill={fill} stroke={stroke}/>
              <line {...s} x1="106" y1="40" x2="180" y2="40" strokeWidth="2" stroke={ink}/>
              <line {...s} x1="106" y1="48" x2="170" y2="48"/>
              <rect x="106" y="56" width="22" height="5" fill={accent}/>
              <line {...s} x1="106" y1="68" x2="180" y2="68"/>
              <line {...s} x1="106" y1="74" x2="172" y2="74"/>
              <line {...s} x1="106" y1="80" x2="160" y2="80"/>
              <rect x="106" y="92" width="60" height="10" fill={accent} opacity="0.9"/>
              <text x="136" y="99" fontSize="5" textAnchor="middle" fill="var(--bg-elev-1)" fontFamily="var(--font-mono)" fontWeight="700">ADD TO CART</text>
            </g>
          ),
          // Page 4: cart
          (
            <g key="3">
              <TopBar/>
              <line {...s} x1="22" y1="40" x2="60" y2="40" strokeWidth="2" stroke={ink}/>
              {[0,1,2].map(i => {
                const y = 50 + i * 22;
                return (
                  <g key={i}>
                    <rect {...sf} x="22" y={y} width="156" height="18"/>
                    <rect x={24} y={y+2} width="14" height="14" fill={fill} stroke={stroke}/>
                    <line {...s} x1="42" y1={y+6}  x2="120" y2={y+6}/>
                    <line {...s} x1="42" y1={y+11} x2="100" y2={y+11}/>
                    <rect x="158" y={y+6} width="16" height="6" fill={accent} opacity="0.85"/>
                  </g>
                );
              })}
              <rect {...sf} x="22" y="116" width="156" height="6"/>
              <rect x="120" y="116" width="58" height="6" fill={accent}/>
            </g>
          ),
          // Page 5: checkout / success
          (
            <g key="4">
              <TopBar/>
              <rect {...sf} x="22" y="38" width="156" height="80"/>
              <circle cx="100" cy="66" r="10" stroke={accent} strokeWidth="1.5" fill="color-mix(in oklab, var(--accent) 12%, transparent)"/>
              <path d="M94 66 L98 70 L106 62" stroke={accent} strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
              <line {...s} x1="50" y1="86" x2="150" y2="86" strokeWidth="2" stroke={ink}/>
              <line {...s} x1="60" y1="94" x2="140" y2="94"/>
              <rect x="78" y="102" width="44" height="8" fill={accent} opacity="0.9"/>
            </g>
          ),
        ];
        return (
          <Frame url={`midwesttech.dev/store`} padViewport={8}>
            <Scroller>{variants}</Scroller>
          </Frame>
        );
      })()}

      {/* SEO — browser frame; SERP scrolls, your result climbs */}
      {kind === 'seo' && (() => {
        const yourRank = Math.max(0, 3 - (v % 4));   // climbs from row 3 → row 0
        const TopBar = () => (
          <g>
            <rect x="14" y="22" width="172" height="8" fill="color-mix(in oklab, var(--bg-elev-1) 70%, transparent)"/>
            {/* Google-ish "G" */}
            <text x="20" y="28" fontSize="6.5" fill={accent} fontFamily="var(--font-display)" fontWeight="700">G</text>
            <rect x="32" y="23" width="120" height="6" fill="var(--bg-elev-1)" stroke={stroke} strokeWidth="0.5"/>
            <circle cx="36" cy="26" r="1.4" stroke={muted} strokeWidth="0.6" fill="none"/>
            <line {...s} x1="42" y1="26" x2="100" y2="26" stroke={ink}/>
            <text x="178" y="27" fontSize="4" textAnchor="end" fill={accent} fontFamily="var(--font-mono)">SEARCH</text>
          </g>
        );
        // Single SERP page that mutates: yourRank moves up; results below stay
        return (
          <Frame url={`google.com/search?q=lawn+care+okc`} padViewport={6}>
            <g>
              <TopBar/>
              <text x="14" y="40" fontSize="4" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.1em">ABOUT 142,000 RESULTS · 0.34s</text>
              {[0,1,2,3].map(i => {
                const y = 46 + i * 18;
                const isYou = i === yourRank;
                return (
                  <g key={i} style={{ transition: 'opacity .55s var(--ease-out)' }} opacity={isYou ? 1 : 0.62}>
                    {isYou && <rect x="12" y={y-2} width="176" height="18" fill="color-mix(in oklab, var(--accent) 12%, transparent)"
                      stroke={accent} strokeWidth="0.6"/>}
                    <text x="16" y={y+4} fontSize="4" fill={isYou ? accent : muted}
                      fontFamily="var(--font-mono)" fontWeight={isYou ? '700' : '400'} letterSpacing="0.1em">
                      #{i+1}
                    </text>
                    <line {...s} x1="28" y1={y+3} x2={28 + (isYou ? 130 : 100 - i*10)} y2={y+3}
                      strokeWidth={isYou ? 1.6 : 1}
                      stroke={isYou ? accent : (hover ? strokeHover : stroke)}/>
                    <text x="28" y={y+9.2} fontSize={isYou ? 4.4 : 3.4} fill={isYou ? accent : muted}
                      fontFamily="var(--font-mono)" fontWeight={isYou ? '700' : '400'}
                      letterSpacing={isYou ? '0.04em' : '0.06em'} opacity={isYou ? 1 : 0.7}>
                      {isYou ? 'YOURBUSINESS.COM' : ['statewidepro.com','redbudworks.com','sooner-std.com','prairie-rd.com'][i]}
                    </text>
                    <line {...s} x1="28" y1={y+13} x2={28 + (isYou ? 110 : 80 - i*8)} y2={y+13} strokeWidth="0.6"/>
                    {isYou && (
                      <g>
                        {/* Clean upward arrow — single chevron */}
                        <g transform={`translate(168 ${y+6})`}>
                          <line x1="0" y1="6" x2="0" y2="-3" stroke={accent} strokeWidth="1.6" strokeLinecap="round"/>
                          <polyline points="-3,0 0,-3 3,0" fill="none" stroke={accent} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
                          <animate attributeName="opacity" values="0;1" dur="0.4s" fill="freeze"/>
                        </g>
                        <text x="180" y={y+9.5} fontSize="3.6" textAnchor="end" fill={accent}
                          fontFamily="var(--font-mono)" fontWeight="700" letterSpacing="0.06em">#{yourRank+1}</text>
                      </g>
                    )}
                  </g>
                );
              })}
            </g>
          </Frame>
        );
      })()}

      {/* CUSTOM — browser frame; dashboard scrolls through 5 dashboard variants */}
      {kind === 'custom' && (() => {
        const TopBar = () => (
          <g>
            <rect x="14" y="22" width="172" height="8" fill="color-mix(in oklab, var(--bg-elev-1) 70%, transparent)"/>
            <circle cx="20" cy="26" r="1.6" fill={accent}/>
            <line {...s} x1="28" y1="26" x2="56" y2="26" strokeWidth="1.4" stroke={ink}/>
            <line {...s} x1="62" y1="26" x2="78" y2="26"/>
            <line {...s} x1="84" y1="26" x2="100" y2="26"/>
            <text x="178" y="27" fontSize="4" textAnchor="end" fill={accent} fontFamily="var(--font-mono)" letterSpacing="0.1em">● LIVE</text>
          </g>
        );
        // Chart rect spans x=14..130, y=34..90 — keep ALL points inside x:[20,124] y:[44,86]
        const lines = [
          '20,80 32,72 44,76 56,62 68,68 80,54 92,58 104,46 116,52 124,42',
          '20,76 32,64 44,70 56,60 68,52 80,56 92,62 104,50 116,46 124,40',
          '20,72 32,74 44,62 56,66 68,54 80,46 92,52 104,44 116,48 124,38',
          '20,80 32,72 44,76 56,60 68,56 80,50 92,54 104,46 116,42 124,36',
          '20,74 32,60 44,68 56,52 68,58 80,48 92,52 104,42 116,46 124,34',
        ];
        const pts = lines[v % lines.length];
        const liveTile = v % 4;
        const variants = [
          // Variant A: line chart + KPIs + sparkline strip
          (
            <g key="0">
              <TopBar/>
              <rect {...sf} x="14" y="34" width="116" height="56"/>
              <text x="20" y="42" fontSize="4" fill={muted} fontFamily="var(--font-mono)" letterSpacing="0.12em">REVENUE · 30D</text>
              <polyline key={`pl-${v}`} points={pts} stroke={accent} strokeWidth="1.4" fill="none">
                <animate attributeName="stroke-dasharray" from="0,400" to="400,0" dur="0.9s" fill="freeze"/>
              </polyline>
              {pts.split(' ').map((pt, i) => {
                const [cx, cy] = pt.split(',').map(Number);
                return <circle key={`pt-${v}-${i}`} cx={cx} cy={cy} r="1.4" fill={accent}/>;
              })}
              {[0,1,2,3].map(i => {
                const x = 134, y = 34 + i * 14;
                const isLive = i === liveTile;
                return (
                  <g key={i}>
                    <rect x={x} y={y} width="50" height="12"
                      fill={isLive ? 'color-mix(in oklab, var(--accent) 14%, transparent)' : fill}
                      stroke={isLive ? accent : stroke}/>
                    <text x={x+3} y={y+4.5} fontSize="3" fill={isLive ? accent : muted} fontFamily="var(--font-mono)" letterSpacing="0.1em">
                      {['REV','USERS','ORDERS','CHURN'][i]}
                    </text>
                    <rect x={x+3} y={y+6.5} width={isLive ? 32 : 18} height="3" fill={isLive ? accent : muted}
                      style={{ transition: 'width .5s' }}/>
                  </g>
                );
              })}
              {/* Mini sparkline strip */}
              <rect {...sf} x="14" y="96" width="170" height="22"/>
              {[0,1,2,3,4].map(i => (
                <polyline key={i} {...s} stroke={i === (v%5) ? accent : stroke}
                  points={`${22+i*32},112 ${28+i*32},104 ${36+i*32},108 ${44+i*32},100`}
                  strokeWidth={i === (v%5) ? 1.4 : 0.8}/>
              ))}
            </g>
          ),
          // Variant B: data table
          (
            <g key="1">
              <TopBar/>
              <rect {...sf} x="14" y="34" width="172" height="84"/>
              {/* Header */}
              <rect x="14" y="34" width="172" height="9" fill="color-mix(in oklab, var(--accent) 8%, transparent)"/>
              {[0,1,2,3].map(i => (
                <text key={i} x={22 + i*42} y="40" fontSize="3.5" fill={accent}
                  fontFamily="var(--font-mono)" letterSpacing="0.1em">{['NAME','REV','STATUS','Δ'][i]}</text>
              ))}
              {[0,1,2,3,4,5].map(i => {
                const y = 47 + i * 11;
                const isHot = i === (v % 6);
                return (
                  <g key={i} opacity={isHot ? 1 : 0.7}>
                    {isHot && <rect x="14" y={y-2} width="172" height="11" fill="color-mix(in oklab, var(--accent) 10%, transparent)"/>}
                    <line {...s} x1="22" y1={y+3} x2="48" y2={y+3} strokeWidth={isHot ? 1.4 : 1} stroke={isHot ? accent : ink}/>
                    <line {...s} x1="64" y1={y+3} x2="92" y2={y+3}/>
                    <rect x="106" y={y} width="20" height="6" fill={isHot ? accent : muted} opacity={isHot ? 0.85 : 0.5}/>
                    <text x="156" y={y+4} fontSize="3.5" fill={isHot ? accent : muted} fontFamily="var(--font-mono)">↑ {isHot ? '+24%' : '+'+(2+i)+'%'}</text>
                  </g>
                );
              })}
            </g>
          ),
          // Variant C: node graph / pipeline
          (
            <g key="2">
              <TopBar/>
              <rect {...sf} x="14" y="34" width="172" height="84"/>
              {[
                {x:30,y:50,label:'INPUT'},{x:75,y:50,label:'PARSE'},{x:120,y:50,label:'AI'},{x:165,y:50,label:'OUT'},
                {x:75,y:90,label:'CACHE'},{x:120,y:90,label:'LOG'},
              ].map((n, i, arr) => {
                const isHot = i === (v % 6);
                return (
                  <g key={i}>
                    {i < 3 && <line x1={n.x+8} y1={n.y} x2={arr[i+1].x-8} y2={arr[i+1].y}
                      stroke={isHot ? accent : stroke} strokeWidth={isHot ? 1.4 : 1}>
                      {isHot && <animate attributeName="stroke-dasharray" values="0,40;40,0" dur="0.9s" fill="freeze"/>}
                    </line>}
                    {i === 1 && <line x1={n.x} y1={n.y+6} x2={n.x} y2={86} stroke={stroke}/>}
                    {i === 2 && <line x1={n.x} y1={n.y+6} x2={n.x} y2={86} stroke={stroke}/>}
                    <circle cx={n.x} cy={n.y} r="6" fill={isHot ? accent : 'var(--bg-elev-2)'} stroke={isHot ? accent : stroke} strokeWidth="1"/>
                    <text x={n.x} y={n.y+1.5} fontSize="3" textAnchor="middle"
                      fill={isHot ? 'var(--bg-elev-1)' : muted} fontFamily="var(--font-mono)" fontWeight="600">{n.label}</text>
                  </g>
                );
              })}
            </g>
          ),
          // Variant D: form / settings
          (
            <g key="3">
              <TopBar/>
              <line {...s} x1="22" y1="40" x2="80" y2="40" strokeWidth="2" stroke={ink}/>
              {[0,1,2,3].map(i => {
                const y = 50 + i * 14;
                return (
                  <g key={i}>
                    <line {...s} x1="22" y1={y} x2="60" y2={y}/>
                    <rect x="22" y={y+3} width="140" height="6" fill="var(--bg-elev-1)" stroke={stroke}/>
                    {/* Toggle */}
                    <rect x="166" y={y+2} width="14" height="8" fill={i === (v%4) ? accent : 'var(--bg-elev-1)'} stroke={i === (v%4) ? accent : stroke}
                      style={{ transition: 'fill .4s' }}/>
                    <circle cx={i === (v%4) ? 176 : 170} cy={y+6} r="2.5" fill={i === (v%4) ? 'var(--bg-elev-1)' : muted}
                      style={{ transition: 'cx .4s var(--ease-out)' }}/>
                  </g>
                );
              })}
              <rect x="22" y="108" width="40" height="8" fill={accent}/>
              <text x="42" y="113.5" fontSize="4" textAnchor="middle" fill="var(--bg-elev-1)" fontFamily="var(--font-mono)" fontWeight="700">SAVE</text>
            </g>
          ),
          // Variant E: map + stats
          (
            <g key="4">
              <TopBar/>
              <rect {...sf} x="14" y="34" width="116" height="84"/>
              {/* Faux US shape — dots */}
              {Array.from({length: 24}).map((_, i) => {
                const x = 22 + (i*7) % 100;
                const y = 44 + Math.floor(i/14) * 30 + ((i*11) % 14);
                const isHot = (i + v) % 24 < 4;
                return <circle key={i} cx={x} cy={y} r={isHot ? 1.8 : 0.9}
                  fill={isHot ? accent : muted} opacity={isHot ? 0.9 : 0.4}>
                  {isHot && <animate attributeName="r" values="0;2.4;1.8" dur="0.6s" fill="freeze"/>}
                </circle>;
              })}
              <rect {...sf} x="134" y="34" width="50" height="84"/>
              {[0,1,2,3,4].map(i => {
                const y = 40 + i * 16;
                const isLive = i === (v % 5);
                return (
                  <g key={i}>
                    <text x="138" y={y+4} fontSize="3" fill={isLive ? accent : muted} fontFamily="var(--font-mono)" letterSpacing="0.08em">{['ACTIVE','TODAY','7D','30D','LTM'][i]}</text>
                    <rect x="138" y={y+6} width={isLive ? 38 : 22} height="3" fill={isLive ? accent : muted} opacity={isLive ? 1 : 0.5}
                      style={{ transition: 'width .5s' }}/>
                  </g>
                );
              })}
            </g>
          ),
        ];
        return (
          <Frame url={`midwesttech.dev/dashboard`} padViewport={8}>
            <Scroller>{variants}</Scroller>
          </Frame>
        );
      })()}

    </svg>
  );
}


function BuildCard({ kind, icon, name, ex, budget, weeks, ai, href, seed=0 }) {
  const [hover, setHover] = useStSv(false);
  const examples = Array.isArray(ex)?ex:[ex];
  const [idx, setIdx] = useStSv(0);
  useEfSv(()=>{
    if(examples.length<=1) return;
    const delay=setTimeout(()=>{
      const t=setInterval(()=>setIdx(i=>(i+1)%examples.length),2200);
      return()=>clearInterval(t);
    }, seed*380);
    return()=>clearTimeout(delay);
  },[]);
  return (
    <a href={href||'#contact'}
      onClick={() => window['mwtTrack'] && window['mwtTrack']('select_content', {
        content_type: 'card',
        content_id: name ? 'service_card_' + String(name).toLowerCase().replace(/[^a-z0-9]+/g, '_') : 'service_card',
        cta_label: typeof name === 'string' ? name : undefined,
        page_section: 'services_grid',
        page_path: typeof window !== 'undefined' ? window.location.pathname : '',
      })}
      onMouseEnter={()=>setHover(true)} onMouseLeave={()=>setHover(false)}
      style={{padding:18,height:'100%',display:'flex',flexDirection:'column',
        gap:10, textDecoration:'none', color:'inherit',
        background:'var(--bg-elev-1)',
        border:`1px solid ${hover?'var(--accent)':'var(--border-strong)'}`,
        transform:hover?'translateY(-2px)':'none',
        transition:'transform .25s var(--ease-out),border-color .25s',
        cursor:'pointer',position:'relative',overflow:'hidden'}}>
      {hover&&<div style={{position:'absolute',inset:0,pointerEvents:'none',
        background:'radial-gradient(circle at 30% 0%,color-mix(in oklab,var(--accent) 10%,transparent),transparent 60%)'}}/>}

      {/* COMPACT HEADER — icon + name inline, then rotating examples + dots, then meta strip */}
      <div style={{position:'relative',display:'flex',alignItems:'center',gap:10}}>
        <div style={{fontFamily:'var(--font-mono)',fontSize:22,color:'var(--accent)',lineHeight:1,flex:'0 0 auto'}}>{icon}</div>
        <div style={{fontFamily:'var(--font-display)',fontSize:20,fontWeight:500,
          letterSpacing:'-0.025em',color:'var(--fg-1)',lineHeight:1.1}}>{name}</div>
      </div>

      <div style={{position:'relative'}}>
        <div style={{fontSize:11.5,color:'var(--fg-3)',lineHeight:1.4,
          position:'relative',height:16,overflow:'hidden'}}>
          {examples.map((e,i)=>(
            <div key={i} style={{position:'absolute',inset:0,
              transform:i===idx?'translateY(0)':(i<idx?'translateY(-100%)':'translateY(100%)'),
              opacity:i===idx?1:0,
              transition:'transform .5s var(--ease-out),opacity .5s var(--ease-out)'}}>{e}</div>
          ))}
        </div>
        {examples.length>1&&(
          <div style={{display:'flex',gap:3,marginTop:6}}>
            {examples.map((_,i)=>(
              <div key={i} style={{width:i===idx?14:4,height:2,
                background:i===idx?'var(--accent)':'var(--border-strong)',
                transition:'width .4s var(--ease-out)'}}/>
            ))}
          </div>
        )}
      </div>

      {/* META STRIP — collapsed onto one row to free vertical for the preview */}
      <div style={{position:'relative',display:'flex',alignItems:'center',gap:10,
        fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.14em',
        paddingBottom:8,borderBottom:'1px solid var(--border)'}}>
        <span style={{color:'var(--fg-4)'}}>{budget}</span>
        <span style={{color:'var(--border-strong)'}}>·</span>
        <span style={{color:'var(--accent)'}}>{ai}</span>
        <span style={{flex:1}}/>
        <span style={{color:'var(--fg-4)',whiteSpace:'nowrap'}}>SHIPS {weeks.toUpperCase()}</span>
      </div>

      {/* PREVIEW — gets the lion's share of vertical space now */}
      <div style={{position:'relative',flex:1,minHeight:0,display:'flex'}}>
        <BuildPreview kind={kind} hover={hover} idx={idx} count={examples.length}/>
      </div>

      {/* FOOTER — compact CTA + url breadcrumb on one line */}
      <div style={{position:'relative',display:'flex',justifyContent:'space-between',alignItems:'center',gap:10,
        paddingTop:8,borderTop:'1px solid var(--border)'}}>
        <div style={{display:'flex',alignItems:'center',gap:6,
          fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.08em',
          color:hover?'var(--accent)':'var(--fg-4)',
          transition:'color .25s var(--ease-out)',
          opacity:0.85,whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis',minWidth:0}}>
          <span style={{opacity:0.5}}>↳</span>
          <span style={{textDecoration:hover?'underline':'none',textUnderlineOffset:2}}>midwesttech.dev/{href||''}</span>
        </div>
        <div style={{display:'flex',alignItems:'center',gap:6,padding:'6px 10px',
          border:`1px solid ${hover?'var(--accent)':'var(--border-strong)'}`,
          background:hover?'color-mix(in oklab, var(--accent) 14%, transparent)':'color-mix(in oklab, var(--bg-elev-2) 70%, transparent)',
          color:hover?'var(--accent)':'var(--fg-2)',
          transition:'all .25s var(--ease-out)',transform:hover?'translateX(2px)':'none',
          flex:'0 0 auto'}}>
          <span style={{fontFamily:'var(--font-mono)',fontSize:9.5,fontWeight:600,letterSpacing:'0.14em',textTransform:'uppercase'}}>See page</span>
          <span style={{fontFamily:'var(--font-mono)',fontSize:13,transform:hover?'translateX(2px)':'none',transition:'transform .25s var(--ease-out)'}}>→</span>
        </div>
      </div>
    </a>
  );
}

/* ---- Main Services section ---- */
function Services() {
  const ref = useRefSv(null); useReveal(ref);
  // Budgets & timelines come from window.MWT_PRICING (mwt-v2/pricing.js).
  // Update prices/timelines there, not here.
  const P = window.MWT_PRICING.byKind;
  const builds = [
    { kind:'simple',   icon:'▭', name:'Simple website',  href:'/builds/simple-website',  ex:['Website for lawn care & landscaping','Website for plumbers & HVAC','Website for salons, barbers & spas','Website for food trucks & restaurants','Website for contractors & tradespeople'], budget:P.simple.budget,   weeks:P.simple.weeks,   ai:'+chat' },
    { kind:'listings', icon:'▦', name:'Listings site',   href:'/builds/listings-site',   ex:['Real estate agent & broker websites','Used car dealer inventory sites','Vacation rental & Airbnb listing sites','Farm equipment & machinery listings','Commercial property listing sites'],     budget:P.listings.budget, weeks:P.listings.weeks, ai:'+search' },
    { kind:'full',     icon:'▣', name:'Full website',    href:'/builds/full-website',    ex:['Law firm websites OKC','Medical & dental practice websites','Church & nonprofit websites','HVAC, roofing & construction websites','Marketing agency & consulting firm websites'],             budget:P.full.budget,     weeks:P.full.weeks,     ai:'+helper' },
    { kind:'store',    icon:'▰', name:'Online store',    href:'/builds/online-store',    ex:['Boutique apparel & local brand stores','Local food, farm-to-door & specialty makers','Custom merch & print-on-demand stores','Digital download & subscription products','Multi-vendor marketplaces'],            budget:P.store.budget,    weeks:P.store.weeks,    ai:'+support' },
    { kind:'seo',      icon:'★', name:'Google presence', href:'/builds/google-presence', ex:['Local SEO for Oklahoma businesses','Google Business Profile management','Map pack ranking & citation cleanup','Monthly blog content for service businesses','Local competitor SEO monitoring'],              budget:P.seo.budget,      weeks:P.seo.weeks,      ai:'add-on' },
    { kind:'custom',   icon:'◫', name:'Custom builds',   href:'/builds/custom-builds',   ex:['Internal tools, dashboards & reporting','Client portals with role-based access','Data pipelines & API integrations','Two-sided platforms & marketplaces','AI agents that handle real workflows'],             budget:P.custom.budget,   weeks:P.custom.weeks,   ai:'any AI' },
  ];
  return (
    <section id="services" ref={ref} className="mw-reveal"
      style={{padding:'clamp(64px,10vh,100px) clamp(20px,4vw,32px) 40px',maxWidth:1440,margin:'0 auto'}}>
      <SectionHead
        eyebrow="001 / What we build"
        title={<>From a <em style={{fontFamily:'var(--font-editorial)',fontStyle:'italic',fontWeight:400,color:'var(--accent)'}}>simple website</em><br/>to <em style={{fontFamily:'var(--font-editorial)',fontStyle:'italic',fontWeight:400}}>everything you need</em>.</>}
        kicker="Every site is built by hand — no AI slop, no templates. Lawn care, hydraulics, a food truck, a salon, whatever you do, we build the site that brings in business."
      />
      <div className="mw-bento" style={{display:'grid',gridTemplateColumns:'repeat(12,1fr)',gap:8}}>
        <div className="mw-bento-wide mw-bento-spectrum"><SpectrumCell/></div>
        <div className="mw-bento-ai"><AIBanner/></div>
        {builds.map((b,i)=>(
          <div key={b.name} className="mw-bento-build"><BuildCard {...b} seed={i}/></div>
        ))}
        <div className="mw-bento-process"><ProcessCell/></div>
        <USNetworkMap/>
      </div>
    </section>
  );
}

Object.assign(window, { Services });
