// scenes.jsx — Traquify 30s explainer
// Flow: Intro → Mobile scan (homeowner) → Command center (contractor dashboard) → Quote sent

const BRAND = {
  navy:    '#0b1f3a',
  navyDeep:'#081933',
  orange:  '#e95f2a',
  orangeSoft: '#fbe6d9',
  cream:   '#f6f1ea',
  paper:   '#fbf7f0',
  mint:    '#cfe2d4',
  mintDeep:'#7fa68d',
  ink:     '#1a2a44',
  line:    '#9aa9bd',
  muted:   '#6e7a8e',
  faint:   'rgba(11,31,58,0.06)',
};

const SERIF = '"Playfair Display", "Source Serif Pro", Georgia, serif';
const SANS  = '"Inter", system-ui, sans-serif';
const MONO  = '"JetBrains Mono", ui-monospace, monospace';

const LOGO_SRC = (typeof window !== 'undefined' && window.__resources && window.__resources.logo) || 'assets/logo.png';

// ─── timing map ─────────────────────────────────────────────
const T = {
  introIn:  0.0,
  scanIn:   2.4,
  cmdIn:    9.0,
  quoteIn: 17.5,
  sentIn:  25.5,
  end:     30.0,
};

// ─── small util ────────────────────────────────────────────
function Card({ x, y, w, h, children, style }) {
  return (
    <div style={{
      position: 'absolute', left: x, top: y, width: w, height: h,
      background: '#fff', borderRadius: 18,
      boxShadow: '0 24px 60px rgba(11,31,58,0.10), 0 2px 8px rgba(11,31,58,0.06)',
      border: '1px solid rgba(11,31,58,0.06)',
      overflow: 'hidden',
      ...style,
    }}>{children}</div>
  );
}

function TraquifyLogo({ height = 32, style }) {
  return <img src={LOGO_SRC} alt="Traquify" style={{ height, display: 'block', ...style }}/>;
}

// ─── 1. Intro ──────────────────────────────────────────────
function Intro() {
  return (
    <Sprite start={0} end={T.scanIn + 0.4}>
      {({ localTime }) => {
        const t = clamp(localTime, 0, 2.5);
        const logoT = clamp(t / 0.7, 0, 1);
        const tagT  = clamp((t - 0.6) / 0.5, 0, 1);
        const subT  = clamp((t - 1.1) / 0.5, 0, 1);
        const exit  = clamp((t - 2.0) / 0.5, 0, 1);
        const op = 1 - exit;

        return (
          <>
            <div style={{
              position: 'absolute', left: '50%', top: '38%',
              transform: `translate(-50%, calc(-50% + ${(1 - logoT) * 24}px))`,
              opacity: logoT * op,
            }}>
              <TraquifyLogo height={140}/>
            </div>

            <div style={{
              position: 'absolute', left: '50%', top: '58%',
              transform: `translate(-50%, ${(1 - tagT) * 12}px)`,
              opacity: tagT * op,
              fontFamily: SERIF, fontStyle: 'italic',
              fontSize: 30, color: BRAND.ink,
              whiteSpace: 'nowrap',
            }}>
              The site visit that doesn't need <span style={{ color: BRAND.orange }}>a visit.</span>
            </div>

            <div style={{
              position: 'absolute', left: '50%', top: '67%',
              transform: `translate(-50%, ${(1 - subT) * 8}px)`,
              opacity: subT * op * 0.7,
              fontFamily: MONO, fontSize: 13, color: BRAND.muted,
              letterSpacing: '0.18em', textTransform: 'uppercase',
            }}>
              Homeowners scan · Contractors quote
            </div>
          </>
        );
      }}
    </Sprite>
  );
}

// ─── Section label (compact left-gutter) ───────────────────
function SectionLabel({ index, title, subtitle, progress, maxWidth = 260 }) {
  const op = progress;
  return (
    <div style={{
      position: 'absolute', left: 60, top: 64,
      width: maxWidth,
      opacity: op,
      transform: `translateY(${(1 - op) * 8}px)`,
    }}>
      <div style={{
        fontFamily: MONO, fontSize: 11, color: BRAND.orange,
        letterSpacing: '0.18em', marginBottom: 10,
      }}>STEP {index} / 03</div>
      <div style={{
        fontFamily: SERIF, fontSize: 36, fontWeight: 700,
        color: BRAND.navy, letterSpacing: '-0.02em', lineHeight: 1.05,
      }}>{title}</div>
      {subtitle && (
        <div style={{
          fontFamily: SANS, fontSize: 14, color: BRAND.muted,
          marginTop: 10, fontWeight: 400, lineHeight: 1.4,
        }}>{subtitle}</div>
      )}
    </div>
  );
}

// ─── 2. Mobile scan ────────────────────────────────────────
function ScanScene() {
  return (
    <Sprite start={T.scanIn} end={T.cmdIn + 0.4}>
      {({ localTime }) => {
        const t = localTime;
        const sceneDur = T.cmdIn - T.scanIn;
        const phoneIn  = clamp(t / 0.6, 0, 1);
        const labelIn  = clamp((t - 0.3) / 0.6, 0, 1);
        const exitFade = 1 - clamp((t - (sceneDur - 0.4)) / 0.4, 0, 1);

        const phoneX = 130, phoneY = 220, phoneW = 220, phoneH = 420;
        const roomX = 480, roomY = 130, roomW = 660, roomH = 440;

        return (
          <div style={{ position: 'absolute', inset: 0, opacity: exitFade }}>
            <SectionLabel index="01" title="Homeowner scans"
              subtitle="Mobile app · LiDAR + photos in 60 seconds" progress={labelIn} />

            <PhoneFrame x={phoneX} y={phoneY} w={phoneW} h={phoneH}
              entryProgress={phoneIn}
              scanT={clamp((t - 0.7) / (sceneDur - 1.5), 0, 1)} />

            <ScanBeam
              fromX={phoneX + phoneW - 8}
              fromY={phoneY + phoneH * 0.4}
              toX={roomX + 40} toY={roomY + 60}
              t={clamp((t - 0.6) / (sceneDur - 1.0), 0, 1)}
              localTime={t} />

            <RoomWireframe
              x={roomX} y={roomY} w={roomW} h={roomH}
              drawT={clamp((t - 0.8) / 3.5, 0, 1)}
              dotsT={clamp((t - 1.5) / 4.0, 0, 1)}
              localTime={t} />

            <StatusChip
              x={roomX} y={roomY + roomH + 20}
              w={roomW}
              text="Room scan · 3D capture in progress"
              progress={clamp((t - 1.2) / (sceneDur - 1.8), 0, 1)}
              opacity={labelIn} />
          </div>
        );
      }}
    </Sprite>
  );
}

function PhoneFrame({ x, y, w, h, entryProgress, scanT }) {
  const op = entryProgress;
  const ty = (1 - op) * 30;
  const tilt = Math.sin(scanT * Math.PI * 1.5) * 4;
  return (
    <div style={{
      position: 'absolute', left: x, top: y, width: w, height: h,
      opacity: op,
      transform: `translateY(${ty}px) rotate(${-6 + tilt * 0.3}deg)`,
      transformOrigin: 'center',
    }}>
      <div style={{
        width: '100%', height: '100%',
        background: BRAND.navy,
        borderRadius: 32, padding: 8,
        boxShadow: '0 30px 60px rgba(11,31,58,0.28)',
      }}>
        <div style={{
          width: '100%', height: '100%',
          background: '#0d2547', borderRadius: 24,
          position: 'relative', overflow: 'hidden',
        }}>
          <div style={{
            position: 'absolute', inset: 0,
            background: 'linear-gradient(180deg, #1a3358 0%, #0d2547 60%, #081a36 100%)',
          }}/>
          <svg width="100%" height="100%" viewBox="0 0 200 380" preserveAspectRatio="none"
            style={{ position: 'absolute', inset: 0 }}>
            <g stroke={BRAND.orange} strokeWidth="1" fill="none" opacity={0.7}>
              <path d={`M 30 ${120 + Math.sin(scanT*4)*4} L 170 ${120 + Math.sin(scanT*4)*4}`} opacity="0.4"/>
              <path d={`M 30 200 L 170 200`} opacity="0.6"/>
              <path d={`M 30 280 L 170 280`} opacity="0.4"/>
              <path d="M 30 80 L 30 320" opacity="0.3"/>
              <path d="M 100 60 L 100 340" opacity="0.3"/>
              <path d="M 170 80 L 170 320" opacity="0.3"/>
            </g>
            <g stroke={BRAND.orange} strokeWidth="2.5" fill="none">
              <path d="M 40 100 L 40 80 L 60 80"/>
              <path d="M 160 80 L 180 80 L 180 100"/>
              <path d="M 40 280 L 40 300 L 60 300"/>
              <path d="M 160 300 L 180 300 L 180 280"/>
            </g>
            <line x1="40" x2="180" y1={80 + scanT * 220} y2={80 + scanT * 220}
              stroke={BRAND.orange} strokeWidth="2" opacity="0.9"/>
            <line x1="40" x2="180" y1={80 + scanT * 220} y2={80 + scanT * 220}
              stroke={BRAND.orange} strokeWidth="14" opacity="0.15"/>
            {[...Array(28)].map((_, i) => {
              const seed = (i * 37 + 13) % 200;
              const dx = 50 + (seed % 130);
              const dy = 90 + ((i * 17) % 200);
              const appear = clamp(scanT * 1.4 - i / 28, 0, 1);
              return <circle key={i} cx={dx} cy={dy} r={1.6} fill={BRAND.orange} opacity={appear * 0.85}/>;
            })}
          </svg>

          {/* status bar */}
          <div style={{
            position: 'absolute', top: 10, left: 14, right: 14,
            display: 'flex', justifyContent: 'space-between',
            fontFamily: MONO, fontSize: 9, color: '#fff', opacity: 0.7,
          }}>
            <span>9:41</span>
            <span style={{ display: 'flex', gap: 4 }}>
              <span>●</span><span>●</span><span>●</span>
            </span>
          </div>

          {/* recording badge */}
          <div style={{
            position: 'absolute', top: 36, left: '50%', transform: 'translateX(-50%)',
            display: 'flex', alignItems: 'center', gap: 6,
            padding: '4px 10px',
            background: 'rgba(233,95,42,0.15)',
            border: '1px solid rgba(233,95,42,0.4)',
            borderRadius: 100,
            fontFamily: MONO, fontSize: 9, color: BRAND.orange, letterSpacing: '0.1em',
          }}>
            <span style={{
              width: 6, height: 6, borderRadius: 3, background: BRAND.orange,
              opacity: 0.5 + Math.sin(scanT * 30) * 0.5,
            }}/>
            SCANNING
          </div>

          {/* bottom HUD */}
          <div style={{
            position: 'absolute', bottom: 14, left: 0, right: 0,
            display: 'flex', justifyContent: 'center', gap: 14,
            fontFamily: MONO, fontSize: 9, color: '#fff', opacity: 0.85,
          }}>
            <span>{Math.round(scanT * 28)}/28 pts</span>
            <span style={{ color: BRAND.orange }}>{Math.round(scanT * 100)}%</span>
          </div>
          <div style={{
            position: 'absolute', bottom: 32, left: '50%', transform: 'translateX(-50%)',
            width: 38, height: 38, borderRadius: 19,
            border: '2px solid #fff', opacity: 0.85,
          }}>
            <div style={{
              position: 'absolute', inset: 4, borderRadius: 16,
              background: BRAND.orange,
            }}/>
          </div>
        </div>
      </div>
    </div>
  );
}

function ScanBeam({ fromX, fromY, toX, toY, t, localTime }) {
  if (t <= 0) return null;
  const dots = 20;
  return (
    <svg style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }} width="1280" height="720">
      {[...Array(dots)].map((_, i) => {
        const phase = ((localTime * 1.2 + i / dots) % 1);
        const spread = (i / dots - 0.5) * 60;
        const sx = fromX, sy = fromY + spread * 0.3;
        const ex = toX, ey = toY + spread * 2;
        const px = sx + (ex - sx) * phase;
        const py = sy + (ey - sy) * phase;
        const op = (1 - Math.abs(phase - 0.5) * 2) * 0.7 * clamp(t * 2, 0, 1);
        return <circle key={i} cx={px} cy={py} r="2" fill={BRAND.orange} opacity={op}/>;
      })}
      <path d={`M ${fromX} ${fromY - 20} L ${toX} ${toY - 30} L ${toX} ${toY + 30} L ${fromX} ${fromY + 20} Z`}
        fill={BRAND.orange} opacity={0.04 * clamp(t * 2, 0, 1)}/>
    </svg>
  );
}

// ─── Realistic room ─────────────────────────────────────────
function RoomWireframe({ x, y, w, h, drawT, dotsT, localTime, showMeasurements = false, measT = 0 }) {
  const cx = x, cy = y, cw = w, ch = h;
  const inset = 110;
  const fTL = [cx, cy];
  const fTR = [cx + cw, cy];
  const fBR = [cx + cw, cy + ch];
  const fBL = [cx, cy + ch];
  const bTL = [cx + inset, cy + inset * 0.6];
  const bTR = [cx + cw - inset, cy + inset * 0.6];
  const bBR = [cx + cw - inset, cy + ch - inset * 0.6];
  const bBL = [cx + inset, cy + ch - inset * 0.6];

  const pts = (arr) => arr.map(p => p.join(',')).join(' ');
  const backWall  = pts([bTL, bTR, bBR, bBL]);
  const leftWall  = pts([fTL, bTL, bBL, fBL]);
  const rightWall = pts([fTR, bTR, bBR, fBR]);
  const ceiling   = pts([fTL, bTL, bTR, fTR]);
  const floor     = pts([fBL, bBL, bBR, fBR]);

  const fade = drawT;
  const gradId = `rm${Math.round(x)}-${Math.round(y)}`;

  const winW = (bTR[0] - bTL[0]) * 0.35;
  const winH = (bBL[1] - bTL[1]) * 0.45;
  const winX = bTL[0] + (bTR[0] - bTL[0]) * 0.58;
  const winY = bTL[1] + (bBL[1] - bTL[1]) * 0.18;

  const dots = [];
  for (let i = 0; i < 60; i++) {
    const seed = (i * 53 + 7) % 1000;
    const u = (seed % 100) / 100;
    const v = ((seed * 3) % 100) / 100;
    const surface = i % 4;
    let dx, dy;
    if (surface === 0) {
      dx = bTL[0] + (bTR[0] - bTL[0]) * u;
      dy = bTL[1] + (bBL[1] - bTL[1]) * v;
    } else if (surface === 1) {
      const topY = bBL[1] + (fBL[1] - bBL[1]) * v;
      const leftX = bBL[0] + (fBL[0] - bBL[0]) * v;
      const rightX = bBR[0] + (fBR[0] - bBR[0]) * v;
      dx = leftX + (rightX - leftX) * u;
      dy = topY;
    } else if (surface === 2) {
      dx = fTL[0] + (bTL[0] - fTL[0]) * v;
      dy = fTL[1] + (bTL[1] - fTL[1]) * v + ((fBL[1] - fTL[1]) - ((bBL[1] - bTL[1]))) * v * u + (bBL[1] - bTL[1]) * u;
    } else {
      dx = fTR[0] + (bTR[0] - fTR[0]) * v;
      dy = fTR[1] + (bTR[1] - fTR[1]) * v + ((fBR[1] - fTR[1]) - ((bBR[1] - bTR[1]))) * v * u + (bBR[1] - bTR[1]) * u;
    }
    const appear = clamp(dotsT * 1.4 - i / 60, 0, 1);
    dots.push({ x: dx, y: dy, op: appear });
  }

  const measurements = showMeasurements ? [
    { x: (bTL[0] + bTR[0]) / 2, y: bTL[1] - 8, label: '14.5 ft', delay: 0.0 },
    { x: (fBR[0] + bBR[0]) / 2 + 28, y: (bBR[1] + fBR[1]) / 2, label: '8.2 ft', delay: 0.25 },
    { x: cx + cw / 2, y: (bTL[1] + bBL[1]) / 2, label: '18.3 ft', delay: 0.5 },
    { x: (fBL[0] + bBL[0]) / 2 - 28, y: (fBL[1] + bBL[1]) / 2, label: '9.1 ft', delay: 0.75 },
  ] : [];

  return (
    <>
      <svg style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }} width="1280" height="720">
        <defs>
          <linearGradient id={gradId + '-bw'} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="#efe6d2"/>
            <stop offset="100%" stopColor="#e1d4b9"/>
          </linearGradient>
          <linearGradient id={gradId + '-lw'} x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%" stopColor="#c3b59a"/>
            <stop offset="100%" stopColor="#e2d6bc"/>
          </linearGradient>
          <linearGradient id={gradId + '-rw'} x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%" stopColor="#e2d6bc"/>
            <stop offset="100%" stopColor="#c3b59a"/>
          </linearGradient>
          <linearGradient id={gradId + '-cl'} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="#f4eedf"/>
            <stop offset="100%" stopColor="#e8e0cb"/>
          </linearGradient>
          <linearGradient id={gradId + '-fl'} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="#8c6f4f"/>
            <stop offset="100%" stopColor="#b89673"/>
          </linearGradient>
        </defs>

        <polygon points={ceiling}   fill={`url(#${gradId}-cl)`} opacity={fade}/>
        <polygon points={floor}     fill={`url(#${gradId}-fl)`} opacity={fade}/>
        <polygon points={leftWall}  fill={`url(#${gradId}-lw)`} opacity={fade}/>
        <polygon points={rightWall} fill={`url(#${gradId}-rw)`} opacity={fade}/>
        <polygon points={backWall}  fill={`url(#${gradId}-bw)`} opacity={fade}/>

        {[0.2, 0.4, 0.6, 0.8].map((u, i) => {
          const lx = fBL[0] + (fBR[0] - fBL[0]) * u;
          const rx = bBL[0] + (bBR[0] - bBL[0]) * u;
          const ly = fBL[1] + (fBR[1] - fBL[1]) * u;
          const ry = bBL[1] + (bBR[1] - bBL[1]) * u;
          return <line key={'pl'+i} x1={lx} y1={ly} x2={rx} y2={ry}
            stroke="#7a5e42" strokeWidth="1" opacity={0.35 * fade}/>;
        })}

        <polyline points={`${fBL[0]},${fBL[1]} ${bBL[0]},${bBL[1]} ${bBR[0]},${bBR[1]} ${fBR[0]},${fBR[1]}`}
          fill="none" stroke="#f6efe0" strokeWidth="4" opacity={0.7 * fade}/>
        <polyline points={`${fBL[0]},${fBL[1]} ${bBL[0]},${bBL[1]} ${bBR[0]},${bBR[1]} ${fBR[0]},${fBR[1]}`}
          fill="none" stroke="#a89070" strokeWidth="1" opacity={0.5 * fade}/>

        <g opacity={fade}>
          <rect x={winX} y={winY} width={winW} height={winH}
            fill="#cfd9d6" stroke="#8a7e62" strokeWidth="2"/>
          <line x1={winX + winW/2} y1={winY} x2={winX + winW/2} y2={winY + winH}
            stroke="#8a7e62" strokeWidth="1.5"/>
          <line x1={winX} y1={winY + winH/2} x2={winX + winW} y2={winY + winH/2}
            stroke="#8a7e62" strokeWidth="1.5"/>
          <rect x={winX+2} y={winY+2} width={winW-4} height={winH-4} fill="#eef4f3" opacity="0.55"/>
        </g>

        <g stroke="#6e5a3e" strokeWidth="1.25" opacity={0.55 * fade} fill="none">
          <line x1={fTL[0]} y1={fTL[1]} x2={bTL[0]} y2={bTL[1]}/>
          <line x1={fTR[0]} y1={fTR[1]} x2={bTR[0]} y2={bTR[1]}/>
          <line x1={fBR[0]} y1={fBR[1]} x2={bBR[0]} y2={bBR[1]}/>
          <line x1={fBL[0]} y1={fBL[1]} x2={bBL[0]} y2={bBL[1]}/>
          <line x1={bTL[0]} y1={bTL[1]} x2={bTR[0]} y2={bTR[1]}/>
          <line x1={bBL[0]} y1={bBL[1]} x2={bBR[0]} y2={bBR[1]}/>
          <line x1={bTL[0]} y1={bTL[1]} x2={bBL[0]} y2={bBL[1]}/>
          <line x1={bTR[0]} y1={bTR[1]} x2={bBR[0]} y2={bBR[1]}/>
        </g>

        {drawT < 1 && dots.map((d, i) => (
          <circle key={i} cx={d.x} cy={d.y} r="2"
            fill={BRAND.orange} opacity={d.op * 0.7 * (1 - drawT * 0.4)}/>
        ))}

        {showMeasurements && [bTL, bTR, bBR, bBL].map((p, i) => (
          <g key={'a' + i}>
            <circle cx={p[0]} cy={p[1]} r="5" fill="#fff" stroke={BRAND.mintDeep} strokeWidth="2"/>
          </g>
        ))}

        {drawT > 0.2 && drawT < 1 && (
          <circle cx={cx + cw/2} cy={cy + ch/2}
            r={20 + (localTime * 80) % 200} fill="none"
            stroke={BRAND.orange} strokeWidth="1.5"
            opacity={Math.max(0, 0.4 - ((localTime * 80) % 200) / 500)}/>
        )}

        {showMeasurements && (
          <g stroke={BRAND.mintDeep} strokeWidth="1.5" opacity={measT * 0.7} strokeDasharray="4 4">
            <line x1={bTL[0]} y1={bTL[1]} x2={bTR[0]} y2={bTR[1]}/>
            <line x1={bBL[0]} y1={bBL[1]} x2={bBR[0]} y2={bBR[1]}/>
            <line x1={bBR[0]} y1={bBR[1]} x2={fBR[0]} y2={fBR[1]}/>
            <line x1={bBL[0]} y1={bBL[1]} x2={fBL[0]} y2={fBL[1]}/>
          </g>
        )}
      </svg>

      {measurements.map((m, i) => {
        const p = clamp((measT - m.delay) / 0.5, 0, 1);
        const eased = Easing.easeOutBack(p);
        return (
          <div key={i} style={{
            position: 'absolute', left: m.x, top: m.y,
            transform: `translate(-50%, -50%) scale(${eased})`,
            opacity: p,
            background: BRAND.mint, color: BRAND.navy,
            fontFamily: MONO, fontSize: 14, fontWeight: 600,
            padding: '5px 12px', borderRadius: 6,
            boxShadow: '0 6px 16px rgba(11,31,58,0.12)',
            whiteSpace: 'nowrap',
          }}>{m.label}</div>
        );
      })}
    </>
  );
}

function StatusChip({ x, y, w = 660, text, progress, opacity = 1 }) {
  return (
    <div style={{
      position: 'absolute', left: x, top: y, width: w, height: 50,
      background: BRAND.navy, borderRadius: 12,
      display: 'flex', alignItems: 'center', padding: '0 20px', gap: 12,
      opacity: opacity * 0.95, overflow: 'hidden',
    }}>
      <span style={{
        width: 9, height: 9, borderRadius: 5, background: BRAND.orange,
        boxShadow: '0 0 0 4px rgba(233,95,42,0.25)',
      }}/>
      <span style={{ fontFamily: SANS, color: '#fff', fontSize: 15, fontWeight: 500 }}>{text}</span>
      <span style={{ flex: 1 }}/>
      <span style={{ fontFamily: MONO, color: 'rgba(255,255,255,0.6)', fontSize: 12 }}>
        {Math.round(progress * 100)}%
      </span>
      <div style={{
        position: 'absolute', bottom: 0, left: 0,
        width: `${progress * 100}%`, height: 3, background: BRAND.orange,
      }}/>
    </div>
  );
}

// ─── 3. Measure & detect (room view) ───────────────────────
function MeasureScene() {
  return (
    <Sprite start={T.cmdIn} end={T.quoteIn + 0.4}>
      {({ localTime }) => {
        const t = localTime;
        const sceneDur = T.quoteIn - T.cmdIn;
        const labelIn = clamp(t / 0.6, 0, 1);
        const exitFade = 1 - clamp((t - (sceneDur - 0.4)) / 0.4, 0, 1);

        const roomX = 360, roomY = 140, roomW = 800, roomH = 440;

        const drawT = 1;
        const measT = clamp((t - 0.3) / 3.0, 0, 1);
        const damageT = clamp((t - 3.5) / 2.0, 0, 1);
        const aiT = clamp((t - 3.2) / 0.6, 0, 1);
        const statsT = clamp((t - 4.2) / 1.5, 0, 1);

        // damage findings — using labels from the AI report screenshots
        const damages = [
          { x: roomX + roomW * 0.30, y: roomY + roomH * 0.45,
            label: 'Water stain · 91%', sev: 'high',   delay: 0.0 },
          { x: roomX + roomW * 0.74, y: roomY + roomH * 0.30,
            label: 'Wall surface bowing · 84%', sev: 'medium', delay: 0.4 },
          { x: roomX + roomW * 0.50, y: roomY + roomH * 0.72,
            label: 'Hairline crack · 76%', sev: 'low',    delay: 0.8 },
        ];

        return (
          <div style={{ position: 'absolute', inset: 0, opacity: exitFade }}>
            <SectionLabel index="02" title="AI inspection"
              subtitle="Contractor's dashboard: measurements + damage findings" progress={labelIn} />

            <RoomWireframe
              x={roomX} y={roomY} w={roomW} h={roomH}
              drawT={drawT} dotsT={1} localTime={t}
              showMeasurements={true} measT={measT} />

            {/* AI badge top-right of room */}
            <div style={{
              position: 'absolute',
              left: roomX + roomW - 200, top: roomY + 14,
              opacity: aiT,
              transform: `translateY(${(1 - aiT) * -8}px)`,
              display: 'flex', alignItems: 'center', gap: 8,
              padding: '8px 14px',
              background: '#fff', borderRadius: 100,
              boxShadow: '0 8px 20px rgba(11,31,58,0.12)',
              fontFamily: SANS, fontSize: 13, color: BRAND.navy, fontWeight: 600,
            }}>
              <svg width="14" height="14" viewBox="0 0 16 16">
                <path d="M8 1 L10 6 L15 8 L10 10 L8 15 L6 10 L1 8 L6 6 Z" fill={BRAND.orange}/>
              </svg>
              AI vision · live
            </div>

            {/* damage callouts on the room */}
            {damages.map((d, i) => {
              const p = clamp((damageT - d.delay / 1.5) / 0.5, 0, 1);
              const pulse = 0.7 + Math.sin((t + i) * 4) * 0.3;
              const sevColor = { high: '#d33a2c', medium: '#e89c2a', low: '#3a78d9' }[d.sev];
              return (
                <div key={i} style={{
                  position: 'absolute',
                  left: d.x, top: d.y,
                  transform: 'translate(-50%, -50%)',
                  opacity: p,
                  pointerEvents: 'none',
                }}>
                  <div style={{
                    width: 30, height: 30, borderRadius: 15,
                    border: `2px solid ${sevColor}`,
                    background: 'rgba(255,255,255,0.4)',
                    transform: `scale(${0.7 + pulse * 0.5})`,
                  }}/>
                  <div style={{
                    position: 'absolute',
                    left: 24, top: -12,
                    background: sevColor, color: '#fff',
                    fontFamily: SANS, fontSize: 11, fontWeight: 600,
                    padding: '4px 9px',
                    borderRadius: 6,
                    whiteSpace: 'nowrap',
                  }}>{d.label}</div>
                </div>
              );
            })}

            {/* Stats panel bottom */}
            <StatsPanel x={roomX} y={roomY + roomH + 18} progress={statsT} />
          </div>
        );
      }}
    </Sprite>
  );
}

function StatsPanel({ x, y, progress }) {
  // Stats sourced from the AI report + heatmap screenshots
  const items = [
    { k: 'Room area',     v: '118.7 sq ft' },
    { k: 'Max deviation', v: '22.9 mm' },
    { k: 'Avg deviation', v: '5.8 mm' },
    { k: 'Surface',       v: 'Bulge', warn: true },
  ];
  return (
    <div style={{
      position: 'absolute', left: x, top: y, width: 800,
      opacity: progress,
      transform: `translateY(${(1 - progress) * 10}px)`,
      display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)',
      gap: 10,
    }}>
      {items.map((it, i) => {
        const p = clamp(progress * 1.5 - i * 0.15, 0, 1);
        return (
          <div key={i} style={{
            opacity: p,
            background: '#fff',
            border: '1px solid rgba(11,31,58,0.08)',
            borderRadius: 12,
            padding: '12px 16px',
            boxShadow: '0 4px 12px rgba(11,31,58,0.04)',
          }}>
            <div style={{
              fontFamily: MONO, fontSize: 10, color: BRAND.muted,
              textTransform: 'uppercase', letterSpacing: '0.12em',
              marginBottom: 4,
            }}>{it.k}</div>
            <div style={{
              fontFamily: SERIF, fontSize: 24, fontWeight: 700,
              color: it.warn ? BRAND.orange : BRAND.navy,
              display: 'flex', alignItems: 'baseline', gap: 6,
            }}>
              {it.v}
              {it.warn && <span style={{ fontSize: 14, color: BRAND.orange }}>⚠</span>}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ─── 4. Quote scene (standalone card) ──────────────────────
function QuoteScene() {
  return (
    <Sprite start={T.quoteIn} end={T.sentIn + 0.4}>
      {({ localTime }) => {
        const t = localTime;
        const sceneDur = T.sentIn - T.quoteIn;
        const labelIn = clamp(t / 0.5, 0, 1);
        const exitFade = 1 - clamp((t - (sceneDur - 0.4)) / 0.4, 0, 1);

        const lines = [
          { label: 'Drywall repair · 2 sections',     qty: '14 sq ft', price: 480,  delay: 0.4 },
          { label: 'Water-damaged trim replacement',  qty: '8 ft',     price: 320,  delay: 0.8 },
          { label: 'Flooring restoration',            qty: '118 sqft', price: 1640, delay: 1.2 },
          { label: 'Priming + paint, 2 coats',        qty: '1 room',   price: 760,  delay: 1.6 },
        ];
        const sumT = clamp((t - 2.5) / 1.0, 0, 1);
        const total = lines.reduce((s, l) => s + l.price, 0);
        const displayTotal = Math.round(total * Easing.easeOutCubic(sumT));
        const ctaT = clamp((t - 3.8) / 0.6, 0, 1);

        return (
          <div style={{ position: 'absolute', inset: 0, opacity: exitFade }}>
            <SectionLabel index="03" title="Send the quote"
              subtitle="One tap — already accurate" progress={labelIn} />

            <Card x={360} y={140} w={820} h={490}>
              <div style={{
                padding: '22px 30px 16px',
                borderBottom: '1px solid rgba(11,31,58,0.08)',
                display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start',
              }}>
                <div>
                  <div style={{ fontFamily: MONO, fontSize: 11, color: BRAND.muted, letterSpacing: '0.16em' }}>
                    QUOTE · #TQ-2847
                  </div>
                  <div style={{
                    fontFamily: SERIF, fontSize: 28, fontWeight: 700, color: BRAND.navy,
                    marginTop: 6,
                  }}>
                    Kitchen restoration · 42 Oak Lane
                  </div>
                  <div style={{ fontFamily: SANS, fontSize: 13, color: BRAND.muted, marginTop: 4 }}>
                    Prepared for Sarah Richardson · valid 30 days
                  </div>
                </div>
                <div style={{
                  display: 'flex', alignItems: 'center', gap: 6,
                  padding: '6px 12px',
                  background: BRAND.mint, color: BRAND.navy,
                  fontFamily: SANS, fontSize: 12, fontWeight: 600,
                  borderRadius: 100,
                  whiteSpace: 'nowrap',
                }}>
                  <span style={{ width: 6, height: 6, borderRadius: 3, background: BRAND.mintDeep }}/>
                  Auto-drafted from scan
                </div>
              </div>

              <div style={{ padding: '12px 30px' }}>
                {lines.map((line, i) => {
                  const p = clamp((t - line.delay) / 0.5, 0, 1);
                  return (
                    <div key={i} style={{
                      display: 'flex', alignItems: 'center',
                      padding: '13px 0',
                      borderBottom: '1px solid rgba(11,31,58,0.05)',
                      opacity: p,
                      transform: `translateX(${(1 - p) * 20}px)`,
                    }}>
                      <span style={{
                        width: 8, height: 8, borderRadius: 4,
                        background: BRAND.orange, marginRight: 14,
                      }}/>
                      <span style={{ flex: 1, fontFamily: SANS, fontSize: 15, color: BRAND.navy, fontWeight: 500 }}>
                        {line.label}
                      </span>
                      <span style={{ width: 100, fontFamily: MONO, fontSize: 13, color: BRAND.muted, textAlign: 'right' }}>
                        {line.qty}
                      </span>
                      <span style={{ width: 100, fontFamily: SANS, fontSize: 16, color: BRAND.navy, fontWeight: 600, textAlign: 'right' }}>
                        ${line.price.toLocaleString()}
                      </span>
                    </div>
                  );
                })}
              </div>

              <div style={{
                position: 'absolute', bottom: 0, left: 0, right: 0,
                padding: '20px 30px',
                background: BRAND.navy,
                display: 'flex', justifyContent: 'space-between', alignItems: 'center',
              }}>
                <div>
                  <div style={{ fontFamily: MONO, fontSize: 11, color: 'rgba(255,255,255,0.6)', letterSpacing: '0.16em' }}>
                    ESTIMATED TOTAL
                  </div>
                  <div style={{
                    fontFamily: SERIF, fontSize: 36, color: '#fff', fontWeight: 700, marginTop: 2,
                    fontVariantNumeric: 'tabular-nums',
                  }}>
                    ${displayTotal.toLocaleString()}
                  </div>
                </div>
                <button style={{
                  opacity: ctaT,
                  transform: `scale(${0.9 + ctaT * 0.1})`,
                  background: BRAND.orange, color: '#fff',
                  border: 'none', padding: '14px 24px', borderRadius: 10,
                  fontFamily: SANS, fontSize: 16, fontWeight: 600,
                  display: 'flex', alignItems: 'center', gap: 10,
                  cursor: 'pointer',
                  boxShadow: ctaT > 0.5
                    ? `0 8px 20px rgba(233,95,42,0.35), 0 0 0 ${4 + Math.sin(t * 6) * 4}px rgba(233,95,42,0.15)`
                    : '0 8px 20px rgba(233,95,42,0.35)',
                }}>
                  Send to client
                  <svg width="16" height="16" viewBox="0 0 16 16">
                    <path d="M2 8 L14 8 M9 3 L14 8 L9 13" stroke="#fff" strokeWidth="2"
                      fill="none" strokeLinecap="round" strokeLinejoin="round"/>
                  </svg>
                </button>
              </div>
            </Card>

            {t > 4.4 && t < 6.2 && (
              <CursorTap targetX={1060} targetY={585} t={clamp((t - 4.4) / 1.2, 0, 1)} />
            )}
          </div>
        );
      }}
    </Sprite>
  );
}

function CursorTap({ targetX, targetY, t }) {
  const startX = 800, startY = 400;
  const x = startX + (targetX - startX) * Easing.easeOutCubic(t);
  const y = startY + (targetY - startY) * Easing.easeOutCubic(t);
  const clicked = t > 0.85;
  return (
    <>
      {clicked && (
        <div style={{
          position: 'absolute', left: targetX - 30, top: targetY - 30,
          width: 60, height: 60, borderRadius: 30,
          border: `3px solid ${BRAND.orange}`,
          opacity: 1 - (t - 0.85) / 0.15,
          transform: `scale(${1 + (t - 0.85) * 4})`,
          pointerEvents: 'none',
        }}/>
      )}
      <svg style={{ position: 'absolute', left: x, top: y, pointerEvents: 'none' }}
        width="28" height="32" viewBox="0 0 28 32">
        <path d="M2 2 L2 22 L8 18 L12 28 L16 26 L12 16 L20 16 Z"
          fill="#fff" stroke={BRAND.navy} strokeWidth="1.5" strokeLinejoin="round"/>
      </svg>
    </>
  );
}

// ─── 5. Sent confirmation ──────────────────────────────────
function SentScene() {
  return (
    <Sprite start={T.sentIn} end={T.end}>
      {({ localTime }) => {
        const t = localTime;
        const checkT = clamp(t / 0.7, 0, 1);
        const textT  = clamp((t - 0.5) / 0.6, 0, 1);
        const subT   = clamp((t - 1.0) / 0.6, 0, 1);
        const planeT = clamp(t / 1.2, 0, 1);
        const planeX = -100 + planeT * 1500;
        const planeY = 360 - Math.sin(planeT * Math.PI) * 80;

        return (
          <div style={{ position: 'absolute', inset: 0 }}>
            {planeT < 1 && (
              <svg style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }} width="1280" height="720">
                <path d={`M ${-100} ${360}
                          Q 640 280 ${planeX - 20} ${planeY + 5}`}
                  stroke={BRAND.orange} strokeWidth="2" fill="none"
                  strokeDasharray="4 6" opacity="0.5"/>
                <g transform={`translate(${planeX}, ${planeY}) rotate(${Math.cos(planeT * Math.PI) * -10})`}>
                  <path d="M -20 0 L 30 -10 L 30 10 Z" fill={BRAND.orange}/>
                  <path d="M -20 0 L 10 0 L 30 10 Z" fill={BRAND.navy} opacity="0.8"/>
                </g>
              </svg>
            )}

            <div style={{
              position: 'absolute', left: '50%', top: '34%',
              transform: `translate(-50%, -50%) scale(${Easing.easeOutBack(checkT)})`,
              opacity: checkT,
            }}>
              <div style={{
                width: 120, height: 120, borderRadius: 60, background: BRAND.orange,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                boxShadow: '0 20px 50px rgba(233,95,42,0.35)',
              }}>
                <svg width="60" height="60" viewBox="0 0 60 60">
                  <path d="M 16 30 L 26 40 L 44 20"
                    stroke="#fff" strokeWidth="6" fill="none" strokeLinecap="round" strokeLinejoin="round"
                    style={{
                      strokeDasharray: 60,
                      strokeDashoffset: 60 - 60 * clamp((t - 0.3) / 0.5, 0, 1),
                    }}/>
                </svg>
              </div>
              {[0, 1, 2].map((i) => {
                const ringT = ((t + i * 0.3) % 2) / 2;
                return (
                  <div key={i} style={{
                    position: 'absolute', left: '50%', top: '50%',
                    width: 120, height: 120,
                    marginLeft: -60, marginTop: -60,
                    borderRadius: 60,
                    border: `2px solid ${BRAND.orange}`,
                    opacity: (1 - ringT) * 0.4,
                    transform: `scale(${1 + ringT * 1.5})`,
                  }}/>
                );
              })}
            </div>

            <div style={{
              position: 'absolute', left: '50%', top: '58%',
              transform: `translate(-50%, ${(1 - textT) * 14}px)`,
              opacity: textT,
              fontFamily: SERIF, fontSize: 60, fontWeight: 700,
              color: BRAND.navy, letterSpacing: '-0.02em',
              textAlign: 'center', whiteSpace: 'nowrap',
            }}>
              Quote delivered <span style={{ fontStyle: 'italic', color: BRAND.orange }}>in minutes.</span>
            </div>

            <div style={{
              position: 'absolute', left: '50%', top: '70%',
              transform: `translate(-50%, ${(1 - subT) * 10}px)`,
              opacity: subT,
              fontFamily: SANS, fontSize: 18,
              color: BRAND.muted,
              textAlign: 'center', whiteSpace: 'nowrap',
            }}>
              No drive-out · No re-measure · No back & forth
            </div>

            <div style={{
              position: 'absolute', left: '50%', bottom: 60,
              transform: 'translateX(-50%)',
              opacity: clamp((t - 1.8) / 0.6, 0, 1),
              display: 'flex', alignItems: 'center', gap: 14,
            }}>
              <TraquifyLogo height={36}/>
              <div style={{
                fontFamily: MONO, fontSize: 12, color: BRAND.muted,
                paddingLeft: 14, borderLeft: '1px solid rgba(11,31,58,0.15)',
                letterSpacing: '0.1em',
              }}>
                traquify.com
              </div>
            </div>
          </div>
        );
      }}
    </Sprite>
  );
}

// ─── Chrome: top-right logo + bottom step pips ─────────────
function Chrome() {
  const time = useTime();
  let step = 0;
  if (time >= T.scanIn && time < T.cmdIn) step = 1;
  else if (time >= T.cmdIn && time < T.quoteIn) step = 2;
  else if (time >= T.quoteIn && time < T.sentIn) step = 3;
  else if (time >= T.sentIn) step = 4;

  const labels = ['', 'Scan', 'Process', 'Quote', 'Sent'];

  return (
    <>
      {step > 0 && step < 4 && (
        <div style={{
          position: 'absolute', right: 40, top: 36,
          opacity: 0.9,
        }}>
          <TraquifyLogo height={26}/>
        </div>
      )}

      {step > 0 && step < 4 && (
        <div style={{
          position: 'absolute', left: '50%', bottom: 28,
          transform: 'translateX(-50%)',
          display: 'flex', alignItems: 'center', gap: 18,
        }}>
          {[1, 2, 3].map((i) => {
            const active = i === step;
            const done = i < step;
            return (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <div style={{
                  width: active ? 36 : 8, height: 8,
                  borderRadius: 4,
                  background: done || active ? BRAND.orange : 'rgba(11,31,58,0.15)',
                  transition: 'all 240ms',
                }}/>
                {active && (
                  <span style={{
                    fontFamily: MONO, fontSize: 11, color: BRAND.navy,
                    letterSpacing: '0.12em', textTransform: 'uppercase',
                  }}>{labels[i]}</span>
                )}
              </div>
            );
          })}
        </div>
      )}
    </>
  );
}

// ─── Root composition ─────────────────────────────────────
function TraquifyScene() {
  return (
    <>
      <div style={{
        position: 'absolute', inset: 0,
        background: `radial-gradient(ellipse at 30% 20%, ${BRAND.orangeSoft} 0%, transparent 60%),
                     radial-gradient(ellipse at 80% 90%, ${BRAND.cream} 0%, ${BRAND.paper} 70%)`,
      }}/>
      <Intro />
      <ScanScene />
      <MeasureScene />
      <QuoteScene />
      <SentScene />
      <Chrome />
    </>
  );
}

Object.assign(window, { TraquifyScene, BRAND, T });
