// Our Skills — Apple-style vertical panels with rich, smooth WOW animations.

const RED = '#ff2e4d';
const RED_GLOW = '#ff4d6a';
const CYAN = '#5cf0ff';
const GREEN = '#38e29a';
const AMBER = '#ffb547';

function useTick(ms = 1000) {
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => setT((x) => x + 1), ms);
    return () => clearInterval(id);
  }, [ms]);
  return t;
}
function useRaf() {
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    let raf, start;
    const loop = (ts) => { if (!start) start = ts; setT((ts - start) / 1000); raf = requestAnimationFrame(loop); };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, []);
  return t;
}
const easeInOut = (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
const lerp = (a, b, t) => a + (b - a) * t;

// Smooth Catmull-Rom -> Bezier path through points
function smoothPath(pts) {
  if (pts.length < 2) return '';
  let d = `M${pts[0][0].toFixed(1)},${pts[0][1].toFixed(1)}`;
  for (let i = 0; i < pts.length - 1; i++) {
    const p0 = pts[i - 1] || pts[i];
    const p1 = pts[i];
    const p2 = pts[i + 1];
    const p3 = pts[i + 2] || p2;
    const cp1x = p1[0] + (p2[0] - p0[0]) / 6;
    const cp1y = p1[1] + (p2[1] - p0[1]) / 6;
    const cp2x = p2[0] - (p3[0] - p1[0]) / 6;
    const cp2y = p2[1] - (p3[1] - p1[1]) / 6;
    d += ` C${cp1x.toFixed(1)},${cp1y.toFixed(1)} ${cp2x.toFixed(1)},${cp2y.toFixed(1)} ${p2[0].toFixed(1)},${p2[1].toFixed(1)}`;
  }
  return d;
}

/* ============================================================
   1. ANALYTICS — multi-series, sweeping cursor, ticker, axis labels
   ============================================================ */
function DemoAnalytics() {
  const t = useRaf();
  const N = 32;

  // Three "datasets" — we lerp between them on a slow loop for live feel
  const datasets = React.useMemo(() => [
    Array.from({ length: N }, (_, i) => 0.35 + Math.sin(i * 0.4 + 0.5) * 0.18 + i * 0.012),
    Array.from({ length: N }, (_, i) => 0.5 + Math.sin(i * 0.32 + 1.6) * 0.22 + Math.sin(i * 0.6) * 0.08 + i * 0.014),
    Array.from({ length: N }, (_, i) => 0.42 + Math.sin(i * 0.5 + 2.4) * 0.2 + i * 0.018),
  ], []);
  const cost = React.useMemo(() => [
    Array.from({ length: N }, (_, i) => 0.25 + Math.sin(i * 0.35) * 0.1 + i * 0.006),
    Array.from({ length: N }, (_, i) => 0.32 + Math.sin(i * 0.28 + 1.0) * 0.12 + i * 0.008),
    Array.from({ length: N }, (_, i) => 0.28 + Math.sin(i * 0.42 + 2.0) * 0.11 + i * 0.007),
  ], []);

  const cycleLen = 4.5;
  const phase = (t / cycleLen) % datasets.length;
  const a = Math.floor(phase);
  const b = (a + 1) % datasets.length;
  const lp = easeInOut(phase - a);
  const cur = datasets[a].map((v, i) => lerp(v, datasets[b][i], lp));
  const curCost = cost[a].map((v, i) => lerp(v, cost[b][i], lp));

  // Sweeping cursor
  const sweep = (Math.sin(t * 0.55) + 1) / 2;
  const ixF = easeInOut(sweep) * (N - 1);
  const ix = Math.round(ixF);

  const W = 900, H = 480, padX = 50, padY = 110, padB = 100;
  const innerW = W - padX * 2, innerH = H - padY - padB;
  const yFor = (v) => padY + innerH - v * innerH * 0.95;
  const xFor = (i) => padX + (i / (N - 1)) * innerW;
  const ptsR = cur.map((v, i) => [xFor(i), yFor(v)]);
  const ptsC = curCost.map((v, i) => [xFor(i), yFor(v)]);
  const pathR = smoothPath(ptsR);
  const pathC = smoothPath(ptsC);
  const areaR = pathR + ` L ${xFor(N-1)},${H-padB} L ${xFor(0)},${H-padB} Z`;
  const areaC = pathC + ` L ${xFor(N-1)},${H-padB} L ${xFor(0)},${H-padB} Z`;

  // Interp cursor on the curve
  const cx = lerp(ptsR[Math.floor(ixF)][0], ptsR[Math.ceil(ixF)][0], ixF % 1);
  const cy = lerp(ptsR[Math.floor(ixF)][1], ptsR[Math.ceil(ixF)][1], ixF % 1);
  const cyC = lerp(ptsC[Math.floor(ixF)][1], ptsC[Math.ceil(ixF)][1], ixF % 1);

  // Big number — smoothly count
  const sumR = cur.reduce((s, v) => s + v, 0) / N;
  const value = sumR * 2.6; // in millions
  const delta = (8.4 + (sumR - 0.5) * 18 + Math.sin(t * 0.4) * 0.3);

  // Bars at bottom (7 days)
  const bars = Array.from({ length: 7 }, (_, i) => {
    const ph = (t * 0.6 + i * 0.7);
    return 0.45 + Math.sin(ph) * 0.22 + Math.sin(ph * 0.5) * 0.1;
  });
  const peakBar = bars.indexOf(Math.max(...bars));

  // Period highlight
  const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
  const visMonths = months.slice(0, 12);
  const tooltipVal = (sumR * (0.7 + cur[ix]) * 220).toFixed(0);

  return (
    <div className="vis-analytics">
      <div className="va-top">
        <div className="va-label">Revenue · this quarter</div>
        <div className="va-value">${value.toFixed(2)}<i>M</i></div>
        <div className="va-delta">↗ {delta.toFixed(1)}% vs last quarter</div>
      </div>

      <div className="va-side">
        <div className="va-mini">
          <div className="va-mini-l">Active</div>
          <div className="va-mini-v">{(12400 + Math.floor(sumR * 800)).toLocaleString()}</div>
          <svg viewBox="0 0 80 24" className="va-spark">
            <path d={smoothPath(Array.from({length:8},(_,i)=>[i*11, 20 - (Math.sin(i*0.7 + t*0.4)+1)*8 - i*0.6]))} fill="none" stroke={CYAN} strokeWidth="1.6" strokeLinecap="round"/>
          </svg>
        </div>
        <div className="va-mini">
          <div className="va-mini-l">Conv.</div>
          <div className="va-mini-v">{(3.4 + Math.sin(t*0.5)*0.2).toFixed(2)}<i>%</i></div>
          <svg viewBox="0 0 80 24" className="va-spark">
            <path d={smoothPath(Array.from({length:8},(_,i)=>[i*11, 16 - (Math.sin(i*0.5 + t*0.3 + 1)+1)*6 - i*0.4]))} fill="none" stroke={GREEN} strokeWidth="1.6" strokeLinecap="round"/>
          </svg>
        </div>
      </div>

      <svg className="va-chart" viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none">
        <defs>
          <linearGradient id="vaRed" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0" stopColor={RED} stopOpacity="0.45"/>
            <stop offset="1" stopColor={RED} stopOpacity="0"/>
          </linearGradient>
          <linearGradient id="vaCyan" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0" stopColor={CYAN} stopOpacity="0.22"/>
            <stop offset="1" stopColor={CYAN} stopOpacity="0"/>
          </linearGradient>
          <filter id="vaGlow">
            <feGaussianBlur stdDeviation="3"/>
          </filter>
        </defs>
        {/* gridlines */}
        {[0.25, 0.5, 0.75, 1].map((p, i) => (
          <g key={i}>
            <line x1={padX} x2={W - padX} y1={padY + innerH * p} y2={padY + innerH * p} stroke="rgba(255,255,255,0.04)" />
            <text x={padX - 8} y={padY + innerH * p + 4} fill="#6a6b76" fontSize="11" fontFamily="JetBrains Mono" textAnchor="end">
              {(value * (1 - p)).toFixed(1)}M
            </text>
          </g>
        ))}
        {/* x-axis labels */}
        {[0, 0.25, 0.5, 0.75, 1].map((p, i) => (
          <text key={'x'+i} x={padX + innerW * p} y={H - padB + 22} fill="#6a6b76" fontSize="11" fontFamily="JetBrains Mono" textAnchor="middle">
            {visMonths[Math.floor(p * 11)]}
          </text>
        ))}

        {/* Areas */}
        <path d={areaC} fill="url(#vaCyan)" style={{ transition: 'd 0.4s' }}/>
        <path d={areaR} fill="url(#vaRed)" />
        {/* Costs line */}
        <path d={pathC} fill="none" stroke={CYAN} strokeWidth="1.8" strokeOpacity="0.55" strokeLinecap="round" strokeLinejoin="round"/>
        {/* Glow under main line */}
        <path d={pathR} fill="none" stroke={RED} strokeWidth="8" strokeOpacity="0.25" filter="url(#vaGlow)" strokeLinecap="round" strokeLinejoin="round"/>
        {/* Main line */}
        <path d={pathR} fill="none" stroke={RED} strokeWidth="3" strokeLinejoin="round" strokeLinecap="round" />

        {/* Cursor */}
        <line x1={cx} x2={cx} y1={padY} y2={H - padB} stroke="rgba(255,255,255,0.15)" strokeDasharray="3 4" />
        <circle cx={cx} cy={cyC} r="4" fill={CYAN} stroke="#0a0b10" strokeWidth="2"/>
        <circle cx={cx} cy={cy} r="7" fill="#fff" stroke={RED} strokeWidth="3"/>
        <circle cx={cx} cy={cy} r="22" fill={RED} opacity="0.12">
          <animate attributeName="r" values="14;32;14" dur="2.4s" repeatCount="indefinite"/>
          <animate attributeName="opacity" values="0.32;0;0.32" dur="2.4s" repeatCount="indefinite"/>
        </circle>

        {/* Tooltip floating */}
        <g transform={`translate(${Math.min(W - padX - 150, Math.max(padX, cx + 18))}, ${Math.max(padY + 8, cy - 64)})`}>
          <rect width="142" height="56" rx="10" fill="rgba(15,17,25,0.94)" stroke="rgba(255,255,255,0.1)"/>
          <text x="12" y="20" fill="#a7a8b2" fontSize="10" fontFamily="JetBrains Mono" letterSpacing="0.08em">{visMonths[Math.floor(ix / N * 11)].toUpperCase()} · WK {ix + 1}</text>
          <text x="12" y="40" fill="#fff" fontSize="18" fontFamily="Space Grotesk" fontWeight="600">${tooltipVal}k</text>
          <circle cx="128" cy="36" r="3" fill={RED}/>
        </g>

        {/* Bars at bottom */}
        {bars.map((v, i) => {
          const bx = padX + innerW * 0.05 + i * (innerW * 0.9 / 7);
          const bw = innerW * 0.9 / 7 - 6;
          const bh = v * 50;
          return (
            <rect key={i} x={bx} y={H - padB + 38 - bh} width={bw} height={bh} rx="3"
              fill={i === peakBar ? RED : 'rgba(255,46,77,0.3)'}
              style={{ transition: 'all 0.3s ease' }}/>
          );
        })}
      </svg>
    </div>
  );
}

/* ============================================================
   2. MOBILE — phone with floating UI cards + screen morphing
   ============================================================ */
function DemoMobile() {
  const t = useRaf();
  const dishes = [
    { name: 'Nasi Lemak',             cn: '椰浆饭',   tag: 'Chef pick',       price: '18.00', rating: '4.9', cook: '12 min', cat: 'Rice',   img: 'https://images.unsplash.com/photo-1626804475297-41608ea09aeb?w=400&q=80&auto=format&fit=crop' },
    { name: 'Char Kway Teow',         cn: '炒粿条',   tag: 'Spicy',            price: '16.00', rating: '4.8', cook: '9 min',  cat: 'Noodle', img: 'https://images.unsplash.com/photo-1645177628172-a94c1f96e6db?w=400&q=80&auto=format&fit=crop' },
    { name: 'Hainanese Chicken Rice', cn: '海南鸡饭', tag: 'Top pick',         price: '15.00', rating: '4.9', cook: '8 min',  cat: 'Rice',   img: 'https://images.unsplash.com/photo-1569058242253-92a9c755a0ec?w=400&q=80&auto=format&fit=crop' },
    { name: 'Satay Ayam',             cn: '沙嗲鸡',   tag: '10 sticks',        price: '14.00', rating: '4.7', cook: '15 min', cat: 'Grill',  img: 'https://images.unsplash.com/photo-1529193591184-b1d58069ecdd?w=400&q=80&auto=format&fit=crop' },
    { name: 'Roti Canai',             cn: '印度煎饼', tag: 'Best seller',      price: '4.50',  rating: '4.8', cook: '6 min',  cat: 'Snack',  img: 'https://images.unsplash.com/photo-1631292784640-2b24be784d5d?w=400&q=80&auto=format&fit=crop' },
    { name: 'Teh Tarik',              cn: '拉茶',     tag: 'Classic',          price: '3.50',  rating: '4.9', cook: '3 min',  cat: 'Drink',  img: 'https://images.unsplash.com/photo-1572490122747-3968b75cc699?w=400&q=80&auto=format&fit=crop' },
  ];

  // Featured rotates through first three dishes; "Add" pulse comes at end of each beat.
  const cycle = 4.0;
  const idx   = Math.floor((t / cycle) % 3);
  const phase = (t / cycle) % 1;
  const added = phase > 0.74;
  const featured = dishes[idx];
  const tick = Math.floor(t / cycle);

  // Menu list = the other 3 dishes (Satay, Roti, Teh Tarik)
  const menu = dishes.slice(3);

  // Cart line items grow with the cycle
  const cartCount = 2 + (added ? 1 : 0);
  const cartTotal = (42 + (added ? Number(featured.price) : 0)).toFixed(2);

  // Animated floating-card numbers
  const orders = 247 + Math.floor(t * 0.3);
  const rating = (4.8 + Math.sin(t * 0.6) * 0.05).toFixed(1);

  const cats = [
    { k: 'All',    n: 24 },
    { k: 'Rice',   n: 6  },
    { k: 'Noodle', n: 5  },
    { k: 'Grill',  n: 4  },
    { k: 'Drink',  n: 9  },
  ];
  const catActive = featured.cat === 'Rice' ? 1 : featured.cat === 'Noodle' ? 2 : 0;

  return (
    <div className="vis-mobile">
      {/* Floating cards */}
      <div className="vm-float vm-float-1">
        <div className="vm-f-icon" style={{background: RED}}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.5" strokeLinecap="round"><path d="M5 12l5 5L20 7"/></svg>
        </div>
        <div className="vm-f-meta">
          <div className="vm-f-t">Order paid</div>
          <div className="vm-f-s">Table 14 · RM 42.00</div>
        </div>
      </div>

      <div className="vm-float vm-float-2">
        <div className="vm-f-num">{orders}</div>
        <div className="vm-f-l">Orders<br/>today</div>
        <svg viewBox="0 0 60 20" className="vm-f-spark">
          <path d={smoothPath(Array.from({length:7},(_,i)=>[i*10, 16 - (Math.sin(i*0.8 + t*0.5)+1)*5]))} fill="none" stroke={GREEN} strokeWidth="1.5"/>
        </svg>
      </div>

      <div className="vm-float vm-float-3">
        <div className="vm-stars">
          {[0,1,2,3,4].map(i => <span key={i}>★</span>)}
        </div>
        <div className="vm-f-rate">{rating}</div>
        <div className="vm-f-l">1,284 reviews</div>
      </div>

      <div className="vm-phone">
        <div className="vm-glow"/>
        <div className="vm-notch"/>
        <div className="vm-screen">
          {/* Status bar */}
          <div className="vm-bar">
            <span>9:41</span>
            <span className="vm-bar-r">
              <svg width="14" height="9" viewBox="0 0 14 9" fill="none"><path d="M1 5.5L4 8L13 1" stroke="#fff" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/></svg>
              <svg width="14" height="9" viewBox="0 0 14 9" fill="none"><path d="M0 5C2 3 5 1 7 1C9 1 12 3 14 5" stroke="#fff" strokeWidth="1.2" strokeLinecap="round"/></svg>
              <span className="vm-batt"><i/></span>
            </span>
          </div>

          {/* Header */}
          <div className="vm-header">
            <div>
              <div className="vm-hi">
                <svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
                Table 14 · 666 Bistro
              </div>
              <div className="vm-name">Hello, Adam</div>
            </div>
            <div className="vm-avatar">AL</div>
          </div>

          {/* Search */}
          <div className="vm-search">
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
            <span>Search the menu…</span>
            <span className="vm-search-kbd">⌘K</span>
          </div>

          {/* Category chips */}
          <div className="vm-cats">
            {cats.map((c, i) => (
              <span key={c.k} className={'vm-cat' + (i === catActive ? ' on' : '')}>
                {c.k}<i>{c.n}</i>
              </span>
            ))}
          </div>

          {/* Featured card */}
          <div className="vm-feat-label">
            <span>Featured today</span>
            <span className="vm-feat-dots">
              {dishes.slice(0,3).map((_, i) => <i key={i} className={i === idx ? 'on' : ''}/>)}
            </span>
          </div>
          <div className={'vm-feat' + (added ? ' added' : '')} key={'f'+idx}>
            <div className="vm-feat-img">
              <img src={featured.img} alt={featured.name} loading="lazy"/>
              <div className="vm-feat-tag">
                <span/>{featured.tag}
              </div>
            </div>
            <div className="vm-feat-body">
              <div className="vm-feat-top">
                <div className="vm-feat-name">{featured.name}</div>
                <div className="vm-feat-cn">{featured.cn} · {featured.cook}</div>
              </div>
              <div className="vm-feat-foot">
                <div className="vm-price">
                  <span className="vm-price-cur">RM</span>
                  <span className="vm-price-v">{featured.price}</span>
                </div>
                <button className={'vm-btn ' + (added ? 'added' : '')}>
                  {added ? (
                    <>
                      <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M5 13l4 4L19 7"/></svg>
                      Added
                    </>
                  ) : (
                    <>
                      <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3" strokeLinecap="round"><path d="M12 5v14M5 12h14"/></svg>
                      Add
                    </>
                  )}
                </button>
              </div>
            </div>
          </div>

          {/* Section header */}
          <div className="vm-sec">
            <span>Popular nearby</span>
            <span className="vm-sec-l">See all →</span>
          </div>

          {/* Menu list */}
          <div className="vm-list">
            {menu.map((d, i) => (
              <div className="vm-item" key={d.name}>
                <div className="vm-item-img">
                  <img src={d.img} alt={d.name} loading="lazy"/>
                </div>
                <div className="vm-item-body">
                  <div className="vm-item-name">{d.name}</div>
                  <div className="vm-item-meta">
                    <span className="vm-item-rate"><b>★</b> {d.rating}</span>
                    <span className="vm-item-dot">·</span>
                    <span>{d.cook}</span>
                  </div>
                </div>
                <div className="vm-item-right">
                  <div className="vm-item-price">RM {d.price}</div>
                  <button className="vm-item-add" aria-label="Add">
                    <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round"><path d="M12 5v14M5 12h14"/></svg>
                  </button>
                </div>
              </div>
            ))}
          </div>

          {/* Floating cart bar */}
          <div className={'vm-cartbar' + (added ? ' pulse' : '')}>
            <div className="vm-cartbar-l">
              <div className="vm-cartbar-icon">
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.7 13.4a2 2 0 0 0 2 1.6h9.7a2 2 0 0 0 2-1.6L23 6H6"/></svg>
                <span className="vm-cartbar-c">{cartCount}</span>
              </div>
              <div>
                <div className="vm-cartbar-t">View cart</div>
                <div className="vm-cartbar-s">{cartCount} items · est. 12 min</div>
              </div>
            </div>
            <div className="vm-cartbar-total">RM {cartTotal}</div>
          </div>

          {/* Tab bar */}
          <div className="vm-tabbar">
            <div className="vm-tb on" aria-label="Menu">
              <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>
            </div>
            <div className="vm-tb" aria-label="Orders">
              <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 10h18"/></svg>
            </div>
            <div className="vm-tb vm-tb-cart" aria-label="Cart">
              <span className="vm-tb-badge">{cartCount}</span>
              <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.7 13.4a2 2 0 0 0 2 1.6h9.7a2 2 0 0 0 2-1.6L23 6H6"/></svg>
            </div>
            <div className="vm-tb" aria-label="Me">
              <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></svg>
            </div>
          </div>

          <div className="vm-homebar"/>
        </div>
      </div>

      {/* fly-to-cart particle */}
      {added && (
        <div className="vm-fly" key={tick}>
          <div/>
        </div>
      )}
    </div>
  );
}

/* ============================================================
   3. COMMERCE — real product detail page (browser chrome, thumbs,
   breadcrumb, rating, sale price, size, trust row)
   ============================================================ */
function shadeHex(hex, p) {
  const n = parseInt(hex.slice(1), 16);
  const r = Math.max(0, Math.min(255, ((n >> 16) & 255) + Math.round(p * 255)));
  const g = Math.max(0, Math.min(255, ((n >> 8)  & 255) + Math.round(p * 255)));
  const b = Math.max(0, Math.min(255, (n & 255)         + Math.round(p * 255)));
  return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}

function DemoCommerce() {
  const t = useRaf();
  const tick = Math.floor(t / 2.8);
  const variants = [
    { name: 'Sand',     color: '#c9b896', price: 459, img: 'https://images.unsplash.com/photo-1539533018447-63fcce2678e3?w=600&h=760&fit=crop&q=80&auto=format' },
    { name: 'Charcoal', color: '#2a2c33', price: 459, img: 'https://images.unsplash.com/photo-1544022613-e87ca75a784a?w=600&h=760&fit=crop&q=80&auto=format' },
    { name: 'Rust',     color: '#a8472c', price: 489, img: 'https://images.unsplash.com/photo-1591047139829-d91aecb6caea?w=600&h=760&fit=crop&q=80&auto=format' },
    { name: 'Bone',     color: '#e8e2d2', price: 459, img: 'https://images.unsplash.com/photo-1539109136881-3be0616acf4b?w=600&h=760&fit=crop&q=80&auto=format' },
  ];
  const sizes = ['XS', 'S', 'M', 'L', 'XL'];
  const soldOut = new Set(['XS']); // shows realistic stock state
  const sel = tick % variants.length;
  const sizeIdx = 2; // M selected (realistic — stays still)
  const v = variants[sel];
  const oldPrice = 689;
  const discount = Math.round((1 - v.price / oldPrice) * 100);

  // live viewer count (drifts slowly)
  const viewers = 12 + Math.floor((Math.sin(t * 0.4) + 1) * 6);

  return (
    <div className="vis-commerce">
      <div className="vc-stage">
        {/* Browser chrome */}
        <div className="vc-chrome">
          <div className="vc-traffic"><i/><i/><i/></div>
          <div className="vc-url">
            <svg className="vc-lock" width="9" height="11" viewBox="0 0 9 11" fill="none">
              <path d="M2 5V3a2.5 2.5 0 0 1 5 0v2" stroke="currentColor" strokeWidth="0.9" strokeLinecap="round"/>
              <rect x="1" y="5" width="7" height="5.4" rx="1" fill="currentColor" fillOpacity="0.55"/>
            </svg>
            <span className="vc-host">maison.shop</span><i>/coats/wool-overcoat</i>
          </div>
          <div className="vc-bag">
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
              <path d="M3 4.5h8l-.7 7.5H3.7L3 4.5zM5 4.5V3a2 2 0 0 1 4 0v1.5" stroke="currentColor" strokeWidth="1.1" strokeLinejoin="round"/>
            </svg>
            <span className="vc-bag-n">2</span>
          </div>
        </div>

        {/* Product viewer: vertical thumbnail rail + hero image */}
        <div className="vc-viewer">
          <div className="vc-thumbs">
            {variants.map((vr, i) => (
              <button key={vr.name} className={'vc-thumb' + (i === sel ? ' on' : '')} aria-label={vr.name}>
                <div className="vc-thumb-fill" style={{ background: `linear-gradient(145deg, ${vr.color}, ${shadeHex(vr.color, -0.25)})` }}>
                  <img
                    src={vr.img}
                    alt=""
                    loading="lazy"
                    onError={(e) => { e.currentTarget.style.display = 'none'; }}
                  />
                </div>
              </button>
            ))}
            <div className="vc-thumb-more">+4</div>
          </div>

          <div className="vc-hero" key={sel}>
            <div className="vc-hero-tl">
              <span className="vc-sale">−{discount}%</span>
              <span className="vc-new">NEW IN</span>
            </div>
            <button className="vc-fav" aria-label="Save">
              <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
                <path d="M7 12s-4.5-2.6-4.5-6A2.4 2.4 0 0 1 7 4.3 2.4 2.4 0 0 1 11.5 6c0 3.4-4.5 6-4.5 6z" stroke="currentColor" strokeWidth="1.1" strokeLinejoin="round"/>
              </svg>
            </button>

            <div
              className="vc-product"
              style={{
                background: `linear-gradient(155deg, ${shadeHex(v.color, 0.06)} 0%, ${v.color} 45%, ${shadeHex(v.color, -0.28)} 100%)`,
              }}>
              <img
                key={'img'+sel}
                className="vc-photo"
                src={v.img}
                alt={`${v.name} wool overcoat`}
                onError={(e) => { e.currentTarget.style.display = 'none'; }}
              />
              <div className="vc-weave"/>
              <div className="vc-vignette"/>
              <div className="vc-tag-corner">
                <i>22 SS</i>
                <b>{v.name.toUpperCase()}</b>
              </div>
              <div className="vc-photog">MAISON</div>
            </div>

            <div className="vc-hero-foot">
              <span className="vc-viewers"><i/> {viewers} viewing now</span>
              <span className="vc-imgcount">1 / 5</span>
            </div>
          </div>
        </div>

        {/* price tag fly-in */}
        <div className="vc-price-tag" key={'p' + sel}>
          <span>RM</span>
          <b>{v.price}</b>
        </div>
      </div>

      <div className="vc-info">
        <div className="vc-crumb">Coats <i>›</i> Wool overcoats <i>›</i> 22 SS</div>
        <div className="vc-brand">MAISON</div>
        <div className="vc-name">Wool overcoat</div>

        <div className="vc-rating">
          <span className="vc-stars" aria-hidden="true">
            {[0,1,2,3,4].map(i => <svg key={i} width="11" height="11" viewBox="0 0 11 11"><path d="M5.5 0.5l1.6 3.2 3.5.5-2.5 2.5.6 3.5L5.5 8.6 2.3 10.2l.6-3.5L.4 4.2l3.5-.5z" fill="currentColor"/></svg>)}
          </span>
          <span className="vc-rate-n">4.8</span>
          <span className="vc-rev">· 124 reviews</span>
        </div>

        <div className="vc-price-row">
          <span className="vc-now">RM {v.price}</span>
          <s className="vc-old">RM {oldPrice}</s>
          <span className="vc-installments">or 3× RM {Math.round(v.price/3)} interest-free</span>
        </div>

        <div className="vc-divider"/>

        <div className="vc-section-l">Color · <b>{v.name}</b></div>
        <div className="vc-swatches">
          {variants.map((vr, i) => (
            <button key={vr.name} className={'vc-sw' + (i === sel ? ' on' : '')} aria-label={vr.name}>
              <span style={{ background: vr.color }}/>
            </button>
          ))}
        </div>

        <div className="vc-section-l vc-size-l">
          <span>Size · <b>{sizes[sizeIdx]}</b></span>
          <a className="vc-size-guide">Size guide ↗</a>
        </div>
        <div className="vc-sizes">
          {sizes.map((s, i) => (
            <button
              key={s}
              className={'vc-sz' + (i === sizeIdx ? ' on' : '') + (soldOut.has(s) ? ' out' : '')}
              disabled={soldOut.has(s)}>
              {s}
            </button>
          ))}
        </div>

        <div className="vc-cta-row">
          <button className="vc-add">
            <span className="vc-add-l">Add to bag</span>
            <span className="vc-add-p">RM {v.price}</span>
          </button>
          <button className="vc-fav-btn" aria-label="Save">
            <svg width="15" height="15" viewBox="0 0 14 14" fill="none">
              <path d="M7 12s-4.5-2.6-4.5-6A2.4 2.4 0 0 1 7 4.3 2.4 2.4 0 0 1 11.5 6c0 3.4-4.5 6-4.5 6z" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round"/>
            </svg>
          </button>
        </div>

        <div className="vc-trust">
          <span className="vc-tr">
            <svg width="11" height="11" viewBox="0 0 14 14" fill="none"><path d="M1 4h7v6H1zM8 6h3l2 2v2H8z M3 12a1.2 1.2 0 100-2.4 1.2 1.2 0 000 2.4zM10.5 12a1.2 1.2 0 100-2.4 1.2 1.2 0 000 2.4z" stroke="currentColor" strokeWidth="0.9"/></svg>
            Free shipping
          </span>
          <span className="vc-tr">
            <svg width="11" height="11" viewBox="0 0 14 14" fill="none"><path d="M2 5a5 5 0 119 3M2 5V2M2 5h3" stroke="currentColor" strokeWidth="0.9" strokeLinecap="round" fill="none"/></svg>
            30-day returns
          </span>
          <span className="vc-tr">
            <svg width="11" height="11" viewBox="0 0 14 14" fill="none"><path d="M7 1l5 3v4c0 3-2.2 4.7-5 5.5C4.2 12.7 2 11 2 8V4z" stroke="currentColor" strokeWidth="0.9" fill="none"/></svg>
            Authentic
          </span>
        </div>

        <div className="vc-stock">
          <span className="vc-pip"/>
          <span>In stock · ships in 24h from KL</span>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   4. SCHEDULING — wave-fill calendar + animated booking detail
   ============================================================ */
function DemoCalendar() {
  const t = useRaf();
  const tick = Math.floor(t / 1.2);
  const cols = 7, rows = 4;
  const total = cols * rows;

  // Wave-fill from upper-left
  const waveProg = ((t * 0.6) % 6) / 6;
  const filled = new Set();
  const filledPattern = [3, 9, 15, 8, 11, 18, 6, 17, 20, 13, 5, 10, 22, 25, 1, 19];
  const cutoff = Math.floor(waveProg * (filledPattern.length + 3));
  filledPattern.slice(0, cutoff).forEach(i => filled.add(i));

  const selected = filledPattern[tick % filledPattern.length];
  const slots = [
    { t: '09:00', n: 'Dr. Tan', s: 'Consult' },
    { t: '10:30', n: 'Dr. Lim', s: 'Follow-up' },
    { t: '11:15', n: 'Dr. Wong', s: 'Scan' },
    { t: '14:00', n: 'Dr. Tan', s: 'Consult' },
    { t: '15:45', n: 'Dr. Lim', s: 'Follow-up' },
  ];
  const slotIdx = tick % slots.length;
  const utilization = Math.min(100, Math.floor((filled.size / total) * 100));

  return (
    <div className="vis-calendar">
      <div className="vk-head">
        <div>
          <div className="vk-month">May 2026</div>
          <div className="vk-sub">Week 20 · Showroom KL</div>
        </div>
        <div className="vk-util">
          <div className="vk-util-r">
            <svg viewBox="0 0 44 44">
              <circle cx="22" cy="22" r="18" stroke="rgba(255,255,255,0.08)" strokeWidth="3" fill="none"/>
              <circle cx="22" cy="22" r="18" stroke={RED} strokeWidth="3" fill="none"
                strokeDasharray={`${utilization * 1.13} 200`}
                strokeLinecap="round"
                transform="rotate(-90 22 22)"
                style={{ transition: 'stroke-dasharray 0.6s ease' }}/>
            </svg>
            <span>{utilization}<i>%</i></span>
          </div>
          <div className="vk-util-l">Booked</div>
        </div>
      </div>
      <div className="vk-dow">{['M','T','W','T','F','S','S'].map((d,i) => <span key={i}>{d}</span>)}</div>
      <div className="vk-grid">
        {Array.from({ length: total }).map((_, i) => {
          const isFilled = filled.has(i);
          const isSel = i === selected;
          return (
            <div key={i} className={'vk-cell' + (isFilled ? ' f' : '') + (isSel ? ' s' : '')}>
              <span>{i + 1}</span>
              {isFilled && <i/>}
            </div>
          );
        })}
      </div>
      <div className="vk-slots">
        {slots.map((sl, i) => (
          <div key={i} className={'vk-slot' + (i === slotIdx ? ' on' : '')}>
            <span className="vk-t">{sl.t}</span>
            <span className="vk-l">{i === slotIdx ? 'Selecting…' : sl.n}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ============================================================
   5. DEVOPS — full production deploy dashboard
   ============================================================ */
function DemoCode() {
  const t = useRaf();
  const CYCLE_LEN = 18; // seconds
  const cycle = (t % CYCLE_LEN) / CYCLE_LEN;

  // Pipeline stages — realistic CI/CD with elapsed times
  const stages = [
    { id: 'install', l: 'Install dependencies',  from: 0.00, to: 0.07, dur: 12.4 },
    { id: 'lint',    l: 'Lint & typecheck',      from: 0.07, to: 0.16, dur: 9.1  },
    { id: 'test',    l: 'Unit + integration',    from: 0.16, to: 0.34, dur: 24.7 },
    { id: 'build',   l: 'Build & containerize',  from: 0.34, to: 0.62, dur: 38.2 },
    { id: 'deploy',  l: 'Rolling deploy · 6 regions', from: 0.62, to: 0.95, dur: 47.3 },
  ];

  let activeIdx = stages.findIndex((s) => cycle >= s.from && cycle < s.to);
  const done = cycle >= 0.95;
  if (done) activeIdx = stages.length;
  if (activeIdx === -1 && !done) activeIdx = 0;

  const stageProgress = (i) => {
    const s = stages[i];
    if (cycle < s.from) return 0;
    if (cycle >= s.to) return 1;
    return (cycle - s.from) / (s.to - s.from);
  };

  const overall = Math.min(1, cycle / 0.95);

  // Regions roll out in sequence
  const regions = [
    { loc: 'SIN', city: 'Singapore'  },
    { loc: 'TYO', city: 'Tokyo'      },
    { loc: 'HKG', city: 'Hong Kong'  },
    { loc: 'SYD', city: 'Sydney'     },
    { loc: 'FRA', city: 'Frankfurt'  },
    { loc: 'IAD', city: 'N. Virginia'},
  ];
  const dStart = 0.62, dEnd = 0.95;
  const dSpan  = dEnd - dStart;
  const regionStatus = (i) => {
    const w     = dSpan / regions.length;
    const start = dStart + w * i;
    const end   = start + w * 0.85;
    if (cycle < start) return { s: 'queued',  p: 0 };
    if (cycle >= end)  return { s: 'live',    p: 1 };
    return { s: 'rolling', p: (cycle - start) / (end - start) };
  };

  // Live log stream — appears as cycle progresses
  const allLogs = React.useMemo(() => [
    { c: 0.005, l: '$ pnpm install --frozen-lockfile',                       k: 'cmd' },
    { c: 0.030, l: 'Lockfile is up to date · 1,834 packages · cached',        k: 'mute' },
    { c: 0.060, l: 'done in 11.8s',                                           k: 'ok'  },
    { c: 0.080, l: '$ pnpm lint && tsc --noEmit',                            k: 'cmd' },
    { c: 0.110, l: 'eslint  src/**  · 0 errors  0 warnings',                  k: 'mute' },
    { c: 0.145, l: 'tsc · checked 4,212 files · 0 errors',                    k: 'ok'  },
    { c: 0.170, l: '$ vitest run --coverage --reporter=dot',                 k: 'cmd' },
    { c: 0.230, l: '· · · · · · · · · · · · · · · · · ·',                    k: 'mute' },
    { c: 0.295, l: '✓ 412 tests passed · branch cov 96.2%',                  k: 'ok'  },
    { c: 0.340, l: '$ next build && docker buildx build --platform linux/arm64,linux/amd64 .', k: 'cmd' },
    { c: 0.420, l: '○ Compiled successfully · 247 routes · 1.18 MB gzip',     k: 'mute' },
    { c: 0.495, l: 'Pushed → gcr.io/six6/web@sha256:a3f9b4c2…d7e1',           k: 'mute' },
    { c: 0.580, l: 'Image scan · 0 critical · 2 low · ok',                    k: 'ok'  },
    { c: 0.625, l: '$ kubectl rollout · canary 5% → 100% surge',             k: 'cmd' },
    { c: 0.665, l: '→ sin1  pulling image · 4/4 ready · healthy',             k: 'deploy' },
    { c: 0.720, l: '→ tyo1  pulling image · 4/4 ready · healthy',             k: 'deploy' },
    { c: 0.775, l: '→ hkg1  pulling image · 4/4 ready · healthy',             k: 'deploy' },
    { c: 0.830, l: '→ syd1  pulling image · 4/4 ready · healthy',             k: 'deploy' },
    { c: 0.875, l: '→ fra1  pulling image · 4/4 ready · healthy',             k: 'deploy' },
    { c: 0.920, l: '→ iad1  pulling image · 4/4 ready · healthy',             k: 'deploy' },
    { c: 0.955, l: '✓ shipped v2026.5.17 · 2m 31s · 0 downtime · 24/24 pods', k: 'ok'  },
  ], []);
  const shownLogs = allLogs.filter((L) => cycle >= L.c);
  const tailRef = React.useRef(null);
  React.useEffect(() => {
    if (tailRef.current) tailRef.current.scrollTop = tailRef.current.scrollHeight;
  }, [shownLogs.length]);

  return (
    <div className="vis-code">
      {/* Header — branch, commit, status */}
      <div className="vd-head">
        <div className="vd-status">
          <span className={'vd-dot ' + (done ? 'green' : 'red')}/>
          <span className="vd-state">{done ? 'Deployed' : 'Deploying'}</span>
          <span className="vd-pill">
            <span className="vd-pill-icon">
              <svg viewBox="0 0 16 16" width="9" height="9" fill="currentColor"><path d="M11.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122V6A2.5 2.5 0 0110 8.5H6a1 1 0 00-1 1v1.128a2.251 2.251 0 11-1.5 0V5.372a2.25 2.25 0 111.5 0v1.836A2.492 2.492 0 016 7h4a1 1 0 001-1v-.628A2.25 2.25 0 019.5 3.25zM4.25 12a.75.75 0 100 1.5.75.75 0 000-1.5zM3.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0z"/></svg>
            </span>
            <span>main</span>
            <span className="vd-pill-sep">←</span>
            <span className="vd-pill-from">fix/checkout-poll</span>
          </span>
        </div>
        <div className="vd-rel">
          <span className="vd-rel-hash">8f3a2c1d</span>
          <span className="vd-rel-sep">·</span>
          <span>v2026.5.17</span>
        </div>
      </div>

      {/* Commit message */}
      <div className="vd-commit">
        <span className="vd-commit-msg">fix(checkout): debounce inventory polling on quantity step</span>
        <span className="vd-commit-by">@nadia · 2 files · +47 −12</span>
      </div>

      {/* Body — pipeline + terminal */}
      <div className="vd-body">
        <div className="vd-pipe">
          {stages.map((s, i) => {
            const isAct  = i === activeIdx && !done;
            const isDone = (i < activeIdx) || done;
            const p = stageProgress(i);
            const elapsed = isDone ? s.dur : isAct ? p * s.dur : 0;
            return (
              <div key={s.id} className={'vd-pipe-row' + (isAct ? ' act' : '') + (isDone ? ' done' : '')}>
                <span className="vd-pipe-i">
                  {isDone ? (
                    <svg viewBox="0 0 10 10" width="10" height="10"><path d="M2 5l2 2 4-4" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/></svg>
                  ) : isAct ? (
                    <span className="vd-spin"/>
                  ) : (
                    <span className="vd-pipe-o"/>
                  )}
                </span>
                <span className="vd-pipe-l">{s.l}</span>
                <span className="vd-pipe-d">
                  {isDone ? `${s.dur.toFixed(1)}s` :
                   isAct  ? `${elapsed.toFixed(1)}s` :
                   '—'}
                </span>
                {isAct && (
                  <span className="vd-pipe-bar"><span style={{ width: `${p * 100}%` }}/></span>
                )}
              </div>
            );
          })}
        </div>

        <div className="vd-term">
          <div className="vd-term-head">
            <span className="vd-term-dots"><i/><i/><i/></span>
            <span className="vd-term-title">runner · ubuntu-22.04 · 8 cpu</span>
          </div>
          <div className="vd-term-body" ref={tailRef}>
            {shownLogs.slice(-14).map((L, i) => (
              <div key={shownLogs.length - 14 + i} className={'vd-log ' + L.k}>
                {L.l}
              </div>
            ))}
            {!done && <div className="vd-log cursor">▍</div>}
          </div>
        </div>
      </div>

      {/* Overall progress */}
      <div className="vd-prog">
        <div className="vd-prog-bar"><div style={{ width: `${overall * 100}%` }}/></div>
        <div className="vd-prog-n">{Math.round(overall * 100)}<i>%</i></div>
      </div>

      {/* Region rollout */}
      <div className="vd-regions">
        {regions.map((r, i) => {
          const rs = regionStatus(i);
          return (
            <div key={r.loc} className={'vd-region ' + rs.s}>
              <div className="vd-region-top">
                <span className="vd-region-loc">{r.loc}</span>
                <span className={'vd-region-dot ' + rs.s}/>
              </div>
              <div className="vd-region-city">{r.city}</div>
              <div className="vd-region-meta">
                {rs.s === 'queued'  && <span className="vd-region-state">queued</span>}
                {rs.s === 'rolling' && (
                  <span className="vd-region-roll">
                    <span className="vd-region-rollbar"><span style={{ width: `${rs.p*100}%` }}/></span>
                    <span className="vd-region-pct">{Math.round(rs.p * 100)}%</span>
                  </span>
                )}
                {rs.s === 'live' && <span className="vd-region-state live">v2026.5.17</span>}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ============================================================
   SECTION
   ============================================================ */
function SkillPanel({ n, label, titleKey, desc, flip, Comp }) {
  return (
    <div className={'skill-panel reveal' + (flip ? ' flip' : '')}>
      <div className="sp-text">
        <div className="sp-n">{n}</div>
        <div className="sp-kicker">{label}</div>
        <h3 className="sp-title" dangerouslySetInnerHTML={tHtml(titleKey)}/>
        <p className="sp-desc">{desc}</p>
      </div>
      <div className="sp-vis">
        <div className="sp-vis-inner">
          <Comp/>
        </div>
      </div>
    </div>
  );
}

function Work() {
  const { t } = useLang();
  const skills = [
    { n: '01', label: t('work.1.label'), titleKey: 'work.1.title.html', desc: t('work.1.desc'), Comp: DemoAnalytics, flip: false },
    { n: '02', label: t('work.2.label'), titleKey: 'work.2.title.html', desc: t('work.2.desc'), Comp: DemoMobile,    flip: true  },
    { n: '03', label: t('work.3.label'), titleKey: 'work.3.title.html', desc: t('work.3.desc'), Comp: DemoCommerce, flip: false },
    { n: '04', label: t('work.4.label'), titleKey: 'work.4.title.html', desc: t('work.4.desc'), Comp: DemoCalendar, flip: true  },
    { n: '05', label: t('work.5.label'), titleKey: 'work.5.title.html', desc: t('work.5.desc'), Comp: DemoCode,     flip: false },
  ];

  return (
    <section className="section section-skills" id="work">
      <div className="wrap">
        <div className="section-head">
          <div className="reveal">
            <div className="kicker"><span className="dot"></span><span>{t('work.kicker')}</span><span className="bar"></span><span>{t('work.kicker.right')}</span></div>
            <h2 className="section-title" style={{marginTop:20}} dangerouslySetInnerHTML={tHtml('work.title.html')}/>
          </div>
          <div className="reveal d1">
            <p className="lead">{t('work.lead')}</p>
          </div>
        </div>

        <div className="skill-stack">
          {skills.map((s) => (<SkillPanel key={s.n} {...s}/>))}
        </div>
      </div>
    </section>
  );
}
window.Work = Work;
