// Karavi Studio · Checkout — 3-step flow (Bag → Shipping → Payment → Confirmation)
const { useState: useStateC0, useEffect: useEffectC0, useRef: useRefC0 } = React;

const NZ_REGIONS = [
  "Northland","Auckland","Waikato","Bay of Plenty","Gisborne",
  "Hawke's Bay","Taranaki","Manawatū-Whanganui","Wellington",
  "Tasman","Nelson","Marlborough","West Coast","Canterbury",
  "Otago","Southland",
];

const SHIP_METHODS = [
  { id: "standard", label: "Standard Delivery", note: "5–7 working days", price: 0, threshold: 150 },
  { id: "express",  label: "Express Delivery",  note: "2–3 working days", price: 15 },
  { id: "white",    label: "White Glove",        note: "Scheduled delivery + setup", price: 35 },
];

const PAY_METHODS = [
  { id: "card",  label: "Credit / Debit Card",  note: "Visa, Mastercard, Amex" },
  { id: "poli",  label: "POLi Internet Banking", note: "Direct from your bank" },
  { id: "bank",  label: "Bank Transfer",         note: "We'll email details" },
  { id: "pod",   label: "Pay on Delivery",       note: "White Glove orders only" },
];

// ── Progress bar ──────────────────────────────────────────────────────────────
const CheckoutProgress = ({ step }) => {
  const steps = ["Your Bag", "Shipping", "Payment"];
  return (
    <div style={{ padding: "24px 0 0", marginBottom: 36 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 0 }}>
        {steps.map((label, i) => {
          const num = i + 1;
          const done = step > num;
          const active = step === num;
          return (
            <React.Fragment key={label}>
              <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 6 }}>
                <motion.div
                  animate={{
                    background: done ? "var(--karavi-ebony)" : active ? "var(--karavi-clay)" : "var(--line-medium)",
                    color: done || active ? "var(--karavi-cream)" : "var(--fg-3)",
                  }}
                  transition={{ duration: 0.3 }}
                  style={{
                    width: 32, height: 32, borderRadius: 999,
                    display: "flex", alignItems: "center", justifyContent: "center",
                    fontSize: 13, fontWeight: 600,
                  }}
                >
                  {done ? "✓" : num}
                </motion.div>
                <span style={{
                  fontSize: 10, letterSpacing: ".18em", textTransform: "uppercase",
                  color: active ? "var(--fg-display)" : done ? "var(--fg-2)" : "var(--fg-3)",
                  fontWeight: active ? 600 : 400,
                }}>{label}</span>
              </div>
              {i < steps.length - 1 && (
                <div style={{ flex: 1, height: 1, background: step > num ? "var(--karavi-ebony)" : "var(--line-soft)", margin: "0 8px", marginBottom: 22 }}/>
              )}
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
};

// ── Order Summary sidebar ─────────────────────────────────────────────────────
const Summary = ({ items, shipping, step }) => {
  const subtotal = items.reduce((s, i) => s + i.p.price * i.qty, 0);
  const shipCost = shipping?.price ?? 0;
  const total = subtotal + shipCost;
  const [open, setOpen] = useStateC0(false);

  const summaryContent = (
    <div>
      <div style={{ display: "flex", flexDirection: "column", gap: 14, marginBottom: 20 }}>
        {items.map((item, i) => (
          <div key={i} style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
            <div style={{ position: "relative", flexShrink: 0 }}>
              <img
                src={item.p.image} alt={item.p.name}
                style={{ width: 52, height: 60, borderRadius: 8, objectFit: "cover", display: "block" }}
              />
              <div style={{
                position: "absolute", top: -6, right: -6,
                width: 18, height: 18, borderRadius: 999,
                background: "var(--karavi-ebony)", color: "var(--karavi-cream)",
                fontSize: 10, fontWeight: 600,
                display: "flex", alignItems: "center", justifyContent: "center",
              }}>{item.qty}</div>
            </div>
            <div style={{ flex: 1 }}>
              <div style={{ fontFamily: "var(--font-display)", fontSize: 14, color: "var(--fg-display)", lineHeight: 1.2 }}>{item.p.name}</div>
              <div style={{ fontSize: 11, color: "var(--fg-3)", marginTop: 2 }}>{item.size}</div>
            </div>
            <div style={{ fontSize: 14, color: "var(--fg-1)", flexShrink: 0 }}>NZ${(item.p.price * item.qty).toFixed(0)}</div>
          </div>
        ))}
      </div>

      <div style={{ borderTop: "1px solid var(--line-soft)", paddingTop: 16, display: "flex", flexDirection: "column", gap: 10 }}>
        <div style={{ display: "flex", justifyContent: "space-between", fontSize: 13, color: "var(--fg-2)" }}>
          <span>Subtotal</span><span>NZ${subtotal.toFixed(0)}</span>
        </div>
        <div style={{ display: "flex", justifyContent: "space-between", fontSize: 13, color: "var(--fg-2)" }}>
          <span>Shipping</span>
          <span>{shipping ? (shipCost === 0 ? "Free" : `NZ$${shipCost}`) : "—"}</span>
        </div>
        <div style={{ display: "flex", justifyContent: "space-between", fontSize: 13, color: "var(--fg-2)" }}>
          <span>GST (15%)</span>
          <span>included</span>
        </div>
        <div style={{
          display: "flex", justifyContent: "space-between",
          borderTop: "1px solid var(--line-soft)", paddingTop: 12, marginTop: 2,
        }}>
          <span style={{ fontFamily: "var(--font-display)", fontSize: 18, color: "var(--fg-display)" }}>Total</span>
          <motion.span
            key={total}
            initial={{ scale: 1.05 }} animate={{ scale: 1 }} transition={{ duration: 0.22 }}
            style={{ fontFamily: "var(--font-display)", fontSize: 18, color: "var(--fg-display)" }}
          >NZ${total.toFixed(0)}</motion.span>
        </div>
      </div>
    </div>
  );

  return (
    <>
      {/* Mobile accordion */}
      <div className="k-hide-desktop" style={{ marginBottom: 28 }}>
        <motion.button
          onClick={() => setOpen(o => !o)}
          whileTap={{ scale: 0.99 }}
          style={{
            width: "100%", display: "flex", alignItems: "center", justifyContent: "space-between",
            background: "var(--karavi-bone)", border: "1px solid var(--line-soft)",
            borderRadius: 14, padding: "14px 18px", cursor: "pointer",
          }}
        >
          <span style={{ fontSize: 13, fontWeight: 500, color: "var(--fg-1)" }}>
            {open ? "Hide" : "Show"} order summary · NZ${(subtotal + shipCost).toFixed(0)}
          </span>
          <motion.span animate={{ rotate: open ? 180 : 0 }} transition={{ duration: 0.22 }} style={{ display: "inline-block" }}>▾</motion.span>
        </motion.button>
        <AnimatePresence>
          {open && (
            <motion.div
              initial={{ height: 0, opacity: 0 }} animate={{ height: "auto", opacity: 1 }}
              exit={{ height: 0, opacity: 0 }} transition={{ duration: 0.3, ease: [0.22, 0.61, 0.36, 1] }}
              style={{ overflow: "hidden" }}
            >
              <div style={{ padding: "18px", background: "var(--karavi-bone)", borderRadius: "0 0 14px 14px", border: "1px solid var(--line-soft)", borderTop: 0 }}>
                {summaryContent}
              </div>
            </motion.div>
          )}
        </AnimatePresence>
      </div>

      {/* Desktop sidebar */}
      <div className="k-hide-mobile" style={{
        position: "sticky", top: 100, background: "var(--karavi-bone)",
        border: "1px solid var(--line-soft)", borderRadius: 20, padding: 24,
      }}>
        <div style={{ fontFamily: "var(--font-display)", fontSize: 18, marginBottom: 20, color: "var(--fg-display)" }}>
          Order summary
        </div>
        {summaryContent}
      </div>
    </>
  );
};

// ── Checkout Animations (full mode only — never rendered in lite mode) ────────
// All scenes are pure inline SVG, framer-motion only. No external assets.

const BagAnim = () => {
  const parcels = [
    { x: 28, delay: 0,    fill: "#935749", pat: "kilim",  rot: -10 },
    { x: 70, delay: 0.22, fill: "#ebbca1", pat: "plain",  rot: 6   },
    { x: 50, delay: 0.42, fill: "#54573a", pat: "stripe", rot: -4  },
    { x: 86, delay: 0.62, fill: "#b8ae9f", pat: "dot",    rot: 9   },
    { x: 38, delay: 0.86, fill: "#394119", pat: "kilim",  rot: -7  },
  ];
  return (
    <div style={{ width: 200, height: 150, position: "relative", margin: "0 auto 24px" }}>
      {/* Soft drop shadow under bag */}
      <div style={{ position: "absolute", bottom: 4, left: 28, right: 28, height: 10, borderRadius: "50%", background: "radial-gradient(ellipse at center, rgba(57,65,25,0.18) 0%, transparent 70%)", filter: "blur(2px)" }}/>

      {/* Falling parcels (rendered behind bag opening) */}
      {parcels.map((p, i) => (
        <motion.div
          key={i}
          animate={{
            y: [0, 64, 70],
            opacity: [0, 1, 1, 0],
            scale: [0.55, 1, 0.95, 0.55],
            rotate: [p.rot * 2, p.rot, 0, 0],
          }}
          transition={{
            duration: 1.05, delay: p.delay,
            repeat: Infinity, repeatDelay: 1.0,
            ease: [0.55, 0.06, 0.68, 0.19],
            times: [0, 0.5, 0.75, 1],
          }}
          style={{ position: "absolute", top: 4, left: p.x, width: 22, height: 16, zIndex: 1 }}
        >
          <svg width="22" height="16" viewBox="0 0 22 16" fill="none">
            <rect x="0.5" y="0.5" width="21" height="15" rx="2" fill={p.fill}/>
            {p.pat === "kilim" && (
              <>
                <polygon points="11,3 16,8 11,13 6,8" fill="#f9ecd9" opacity="0.6"/>
                <polygon points="11,5.5 13.5,8 11,10.5 8.5,8" fill={p.fill} opacity="0.8"/>
              </>
            )}
            {p.pat === "stripe" && (
              <>
                <rect x="0.5" y="4" width="21" height="1" fill="#f9ecd9" opacity="0.55"/>
                <rect x="0.5" y="8" width="21" height="1" fill="#f9ecd9" opacity="0.55"/>
                <rect x="0.5" y="11" width="21" height="1" fill="#f9ecd9" opacity="0.55"/>
              </>
            )}
            {p.pat === "dot" && (
              <>
                <circle cx="6" cy="8" r="1.2" fill="#f9ecd9" opacity="0.65"/>
                <circle cx="11" cy="8" r="1.2" fill="#f9ecd9" opacity="0.65"/>
                <circle cx="16" cy="8" r="1.2" fill="#f9ecd9" opacity="0.65"/>
              </>
            )}
            {p.pat === "plain" && (
              <rect x="2" y="2" width="18" height="12" rx="1" fill="none" stroke="#f9ecd9" strokeWidth="0.6" opacity="0.5"/>
            )}
            {/* Twine */}
            <line x1="0.5" y1="8" x2="21.5" y2="8" stroke="#394119" strokeWidth="0.5" opacity="0.5"/>
          </svg>
        </motion.div>
      ))}

      {/* Bag with KARAVI mark */}
      <svg width="200" height="120" viewBox="0 0 200 120" fill="none" style={{ position: "absolute", bottom: 0, left: 0, zIndex: 2 }}>
        {/* Soft body */}
        <defs>
          <linearGradient id="bagGrad" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0" stopColor="#f9ecd9"/>
            <stop offset="1" stopColor="#efe6d4"/>
          </linearGradient>
        </defs>
        {/* Handles */}
        <path d="M68 32 Q 68 6, 100 6 Q 132 6, 132 32" stroke="#394119" strokeWidth="2.2" fill="none" strokeLinecap="round"/>
        {/* Body */}
        <path d="M40 36 L 26 112 a 4 4 0 0 0 4 4 h 140 a 4 4 0 0 0 4 -4 L 160 36 Z" fill="url(#bagGrad)" stroke="#394119" strokeWidth="2.2" strokeLinejoin="round"/>
        {/* Fold highlight */}
        <line x1="42" y1="48" x2="158" y2="48" stroke="#394119" strokeWidth="0.6" opacity="0.25"/>
        {/* Karavi mark on front */}
        <text x="100" y="92" textAnchor="middle" fontFamily="serif" fontSize="14" fill="#394119" opacity="0.78" letterSpacing="3">KARAVI</text>
        {/* Cord knot */}
        <circle cx="68" cy="36" r="2.4" fill="#394119"/>
        <circle cx="132" cy="36" r="2.4" fill="#394119"/>
      </svg>
    </div>
  );
};

const PlaneAnim = () => (
  <div style={{ width: "100%", maxWidth: 460, height: 156, position: "relative", margin: "0 auto 28px", overflow: "hidden", borderRadius: 14 }}>
    {/* Sky gradient bg */}
    <div style={{ position: "absolute", inset: 0, background: "linear-gradient(180deg, rgba(235,188,161,0.22) 0%, rgba(249,236,217,0.05) 60%, rgba(54,87,73,0.04) 100%)" }}/>

    {/* Sun */}
    <div style={{ position: "absolute", top: 14, right: "28%", zIndex: 0 }}>
      <motion.svg
        width="32" height="32" viewBox="0 0 32 32" fill="none"
        animate={{ rotate: 360 }}
        transition={{ duration: 60, repeat: Infinity, ease: "linear" }}
      >
        <circle cx="16" cy="16" r="7" fill="#ebbca1" opacity="0.55"/>
        <circle cx="16" cy="16" r="4" fill="#935749" opacity="0.75"/>
        <g stroke="#935749" strokeWidth="1" opacity="0.35" strokeLinecap="round">
          <line x1="16" y1="3" x2="16" y2="6"/>
          <line x1="16" y1="26" x2="16" y2="29"/>
          <line x1="3" y1="16" x2="6" y2="16"/>
          <line x1="26" y1="16" x2="29" y2="16"/>
          <line x1="6.5" y1="6.5" x2="9" y2="9"/>
          <line x1="23" y1="23" x2="25.5" y2="25.5"/>
          <line x1="25.5" y1="6.5" x2="23" y2="9"/>
          <line x1="9" y1="23" x2="6.5" y2="25.5"/>
        </g>
      </motion.svg>
    </div>

    {/* Drifting clouds */}
    <motion.div
      animate={{ x: ["0%", "12%", "0%"] }}
      transition={{ duration: 9, repeat: Infinity, ease: "easeInOut" }}
      style={{ position: "absolute", top: 30, left: "22%", zIndex: 0 }}
    >
      <svg width="44" height="18" viewBox="0 0 44 18" fill="rgba(249,236,217,0.92)">
        <ellipse cx="10" cy="13" rx="10" ry="4.5"/>
        <ellipse cx="22" cy="9"  rx="10" ry="6"/>
        <ellipse cx="34" cy="13" rx="9"  ry="4.5"/>
      </svg>
    </motion.div>
    <motion.div
      animate={{ x: ["0%", "-14%", "0%"] }}
      transition={{ duration: 11, repeat: Infinity, ease: "easeInOut" }}
      style={{ position: "absolute", top: 60, left: "58%", zIndex: 0 }}
    >
      <svg width="34" height="14" viewBox="0 0 44 18" fill="rgba(249,236,217,0.78)">
        <ellipse cx="10" cy="13" rx="10" ry="4.5"/>
        <ellipse cx="22" cy="9"  rx="10" ry="6"/>
        <ellipse cx="34" cy="13" rx="9"  ry="4.5"/>
      </svg>
    </motion.div>
    <motion.div
      animate={{ x: ["0%", "8%", "0%"] }}
      transition={{ duration: 14, repeat: Infinity, ease: "easeInOut" }}
      style={{ position: "absolute", top: 16, left: "55%", zIndex: 0 }}
    >
      <svg width="28" height="12" viewBox="0 0 44 18" fill="rgba(249,236,217,0.6)">
        <ellipse cx="10" cy="13" rx="10" ry="4.5"/>
        <ellipse cx="22" cy="9"  rx="10" ry="6"/>
        <ellipse cx="34" cy="13" rx="9"  ry="4.5"/>
      </svg>
    </motion.div>

    {/* Distant mountains */}
    <svg viewBox="0 0 460 156" preserveAspectRatio="none" style={{ position: "absolute", bottom: 36, left: 0, width: "100%", height: 64, zIndex: 0 }}>
      <path d="M 0 60 L 60 36 L 110 50 L 170 28 L 230 46 L 290 30 L 350 48 L 410 32 L 460 50 L 460 64 L 0 64 Z" fill="rgba(57,65,25,0.18)"/>
      <path d="M 0 64 L 80 48 L 140 58 L 210 42 L 280 56 L 350 44 L 420 56 L 460 50 L 460 70 L 0 70 Z" fill="rgba(57,65,25,0.28)"/>
    </svg>

    {/* Ground line */}
    <div style={{ position: "absolute", bottom: 32, left: 0, right: 0, height: 1, background: "rgba(57,65,25,0.20)", zIndex: 0 }}/>
    {/* Ground tone */}
    <div style={{ position: "absolute", bottom: 0, left: 0, right: 0, height: 32, background: "linear-gradient(180deg, rgba(235,188,161,0.18) 0%, rgba(147,87,73,0.10) 100%)", zIndex: 0 }}/>

    {/* Curved dashed route */}
    <svg viewBox="0 0 460 156" preserveAspectRatio="none" style={{ position: "absolute", inset: 0, width: "100%", height: "100%", zIndex: 1 }} aria-hidden="true">
      <path d="M 70 120 Q 230 4, 388 120" stroke="rgba(147,87,73,0.42)" strokeWidth="1.5" strokeDasharray="3 6" fill="none" strokeLinecap="round"/>
    </svg>

    {/* Warehouse on left */}
    <div style={{ position: "absolute", bottom: 6, left: 18, zIndex: 2, textAlign: "center" }}>
      <svg width="62" height="60" viewBox="0 0 62 60" fill="none">
        <rect x="5" y="22" width="52" height="32" fill="#935749" stroke="#394119" strokeWidth="1.4"/>
        <path d="M3 22 L31 4 L59 22 Z" fill="#54573a" stroke="#394119" strokeWidth="1.4" strokeLinejoin="round"/>
        <rect x="12" y="34" width="10" height="12" fill="#f9ecd9" opacity="0.85" stroke="#394119" strokeWidth="0.8"/>
        <rect x="40" y="34" width="10" height="12" fill="#f9ecd9" opacity="0.85" stroke="#394119" strokeWidth="0.8"/>
        <rect x="25" y="34" width="12" height="20" fill="#394119"/>
        <rect x="25" y="34" width="12" height="20" fill="none" stroke="#ebbca1" strokeWidth="0.6" opacity="0.5"/>
        <line x1="31" y1="36" x2="31" y2="52" stroke="#ebbca1" strokeWidth="0.4" opacity="0.6"/>
        {/* Sign */}
        <rect x="14" y="26" width="34" height="5" fill="#f9ecd9" stroke="#394119" strokeWidth="0.5"/>
        <text x="31" y="30" textAnchor="middle" fontFamily="serif" fontSize="3.4" fill="#394119" letterSpacing="0.5">KARAVI</text>
      </svg>
      <div style={{ fontSize: 8, letterSpacing: ".22em", textTransform: "uppercase", color: "var(--fg-3)", marginTop: 2, fontWeight: 500 }}>Studio</div>
    </div>

    {/* Home on right */}
    <div style={{ position: "absolute", bottom: 6, right: 18, zIndex: 2, textAlign: "center" }}>
      <svg width="62" height="60" viewBox="0 0 62 60" fill="none">
        <rect x="9" y="24" width="44" height="30" fill="#ebbca1" stroke="#394119" strokeWidth="1.4"/>
        <path d="M3 26 L31 6 L59 26 Z" fill="#935749" stroke="#394119" strokeWidth="1.4" strokeLinejoin="round"/>
        <rect x="36" y="14" width="4" height="8" fill="#394119"/>
        <rect x="26" y="36" width="10" height="18" fill="#394119"/>
        <circle cx="33" cy="46" r="0.8" fill="#ebbca1"/>
        <rect x="14" y="32" width="8" height="8" fill="#f9ecd9" stroke="#394119" strokeWidth="0.6"/>
        <line x1="18" y1="32" x2="18" y2="40" stroke="#394119" strokeWidth="0.4"/>
        <line x1="14" y1="36" x2="22" y2="36" stroke="#394119" strokeWidth="0.4"/>
        <rect x="40" y="32" width="8" height="8" fill="#f9ecd9" stroke="#394119" strokeWidth="0.6"/>
        <line x1="44" y1="32" x2="44" y2="40" stroke="#394119" strokeWidth="0.4"/>
        <line x1="40" y1="36" x2="48" y2="36" stroke="#394119" strokeWidth="0.4"/>
        {/* Welcome mat */}
        <rect x="23" y="54" width="16" height="3" fill="#935749"/>
      </svg>
      <div style={{ fontSize: 8, letterSpacing: ".22em", textTransform: "uppercase", color: "var(--fg-3)", marginTop: 2, fontWeight: 500 }}>Your home</div>
    </div>

    {/* Plane flying along curved path */}
    <motion.div
      animate={{
        x:      ["16%", "30%", "50%", "70%", "84%"],
        y:      [110, 50, 18, 50, 110],
        rotate: [-22, -12, 0, 12, 22],
      }}
      transition={{ duration: 4.2, ease: "linear", repeat: Infinity, repeatDelay: 0.4, times: [0, 0.25, 0.5, 0.75, 1] }}
      style={{ position: "absolute", top: 0, left: 0, zIndex: 3, transform: "translate(-50%, -50%)" }}
    >
      <svg width="44" height="22" viewBox="0 0 44 22" fill="none" aria-hidden="true">
        {/* Wing shadow */}
        <ellipse cx="20" cy="20" rx="14" ry="1" fill="rgba(57,65,25,0.16)"/>
        {/* Tail */}
        <path d="M3 12 L9 7 L13 12 L13 14 L9 14 L3 14 Z" fill="#54573a"/>
        {/* Body */}
        <path d="M3 11 L34 6 L40 8 L40 14 L34 16 L3 14 Z" fill="#394119"/>
        {/* Cockpit */}
        <path d="M34 8 L40 9 L40 13 L34 14 Z" fill="#ebbca1" opacity="0.85"/>
        {/* Wing */}
        <path d="M14 14 L24 18 L28 18 L21 13 Z" fill="#54573a"/>
        {/* Windows */}
        <line x1="14" y1="10.5" x2="32" y2="9.5" stroke="#f9ecd9" strokeWidth="0.5" opacity="0.7"/>
        <line x1="14" y1="11.5" x2="32" y2="10.6" stroke="#ebbca1" strokeWidth="0.3" opacity="0.5"/>
      </svg>
    </motion.div>

    {/* Contrail */}
    <motion.div
      animate={{
        opacity: [0, 0.35, 0.35, 0],
        scaleX:  [0, 1, 1, 1],
      }}
      transition={{ duration: 4.2, ease: "linear", repeat: Infinity, repeatDelay: 0.4, times: [0, 0.3, 0.85, 1] }}
      style={{ position: "absolute", top: 40, left: "20%", width: "60%", height: 1.5, background: "rgba(249,236,217,0.95)", borderRadius: 999, transformOrigin: "left", filter: "blur(0.5px)", zIndex: 2 }}
    />
  </div>
);

const CardAnim = () => (
  <div style={{ width: 220, height: 132, margin: "0 auto 28px", perspective: 800 }}>
    <motion.div
      animate={{ rotateY: [-6, 4, -6], rotateX: [3, -2, 3] }}
      transition={{ duration: 4, ease: [0.42, 0, 0.58, 1], repeat: Infinity }}
      style={{
        width: "100%", height: "100%", borderRadius: 14, overflow: "hidden",
        background: "linear-gradient(135deg, #394119 0%, #4d5520 45%, #6d7a25 100%)",
        boxShadow: "0 14px 38px rgba(57,65,25,0.30), inset 0 1px 0 rgba(255,255,255,0.08)",
        position: "relative", transformStyle: "preserve-3d",
      }}
    >
      {/* Kilim diamond watermark */}
      <svg width="220" height="132" viewBox="0 0 220 132" style={{ position: "absolute", inset: 0, opacity: 0.10 }}>
        <polygon points="180,16 200,40 180,64 160,40" fill="#ebbca1"/>
        <polygon points="180,28 192,40 180,52 168,40" fill="#394119"/>
      </svg>

      {/* Hologram strip */}
      <motion.div
        animate={{ backgroundPosition: ["0% 0%", "200% 0%"] }}
        transition={{ duration: 3, repeat: Infinity, ease: "linear" }}
        style={{
          position: "absolute", top: 64, right: 14, width: 28, height: 38, borderRadius: 4,
          background: "linear-gradient(115deg, #ebbca1 0%, #f9ecd9 25%, #935749 50%, #f9ecd9 75%, #ebbca1 100%)",
          backgroundSize: "300% 100%", opacity: 0.85,
        }}
      />

      {/* Chip */}
      <div style={{ position: "absolute", top: 30, left: 22, width: 36, height: 28, borderRadius: 6, background: "linear-gradient(135deg, #ebbca1 0%, #b8ae9f 100%)", boxShadow: "inset 0 0 0 0.5px rgba(57,65,25,0.4)" }}>
        <div style={{ position: "absolute", inset: 4, border: "0.5px solid rgba(57,65,25,0.4)", borderRadius: 3 }}/>
        <div style={{ position: "absolute", top: "50%", left: 4, right: 4, height: 0.5, background: "rgba(57,65,25,0.3)" }}/>
        <div style={{ position: "absolute", top: 4, left: "50%", bottom: 4, width: 0.5, background: "rgba(57,65,25,0.3)" }}/>
      </div>

      {/* Contactless icon */}
      <svg width="18" height="20" viewBox="0 0 24 24" fill="none" stroke="rgba(249,236,217,0.7)" strokeWidth="1.6" strokeLinecap="round" style={{ position: "absolute", top: 36, left: 64 }}>
        <path d="M3 12a9 9 0 0 1 18 0"/>
        <path d="M6 12a6 6 0 0 1 12 0"/>
        <path d="M9 12a3 3 0 0 1 6 0"/>
      </svg>

      {/* Card number */}
      <div style={{ position: "absolute", bottom: 30, left: 22, display: "flex", gap: 9, alignItems: "center" }}>
        {[0,1,2,3].map(g => (
          <div key={g} style={{ display: "flex", gap: 2.5 }}>
            {[0,1,2,3].map(d => (
              <motion.div
                key={d}
                animate={{ opacity: g === 3 ? [0.45, 0.95, 0.45] : 0.45 }}
                transition={{ duration: 1.6, delay: d * 0.1, repeat: Infinity, ease: "easeInOut" }}
                style={{ width: 4, height: 4, borderRadius: 999, background: "rgba(249,236,217,0.92)" }}
              />
            ))}
          </div>
        ))}
      </div>

      {/* Footer */}
      <div style={{ position: "absolute", bottom: 12, left: 22, right: 50, display: "flex", justifyContent: "space-between", alignItems: "flex-end" }}>
        <div>
          <div style={{ fontSize: 7, letterSpacing: ".18em", color: "rgba(249,236,217,0.5)", fontWeight: 500 }}>VALID THRU</div>
          <div style={{ fontSize: 10, color: "rgba(249,236,217,0.85)", fontFamily: "monospace", marginTop: 1 }}>05 / 29</div>
        </div>
        <div style={{
          fontFamily: "var(--font-display)", fontSize: 15, color: "rgba(249,236,217,0.95)",
          letterSpacing: "0.22em", fontWeight: 400,
        }}>KARAVI</div>
      </div>

      {/* Lock badge fade in */}
      <motion.div
        animate={{ opacity: [0, 1, 1, 0], y: [4, 0, 0, -4], scale: [0.6, 1, 1, 0.95] }}
        transition={{ duration: 3, repeat: Infinity, ease: "easeInOut", times: [0, 0.18, 0.82, 1] }}
        style={{ position: "absolute", top: 14, right: 14, display: "flex", alignItems: "center", gap: 4, padding: "3px 7px", borderRadius: 999, background: "rgba(249,236,217,0.16)", border: "1px solid rgba(249,236,217,0.25)" }}
      >
        <svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="rgba(249,236,217,0.95)" strokeWidth="2.5" strokeLinecap="round">
          <rect x="3" y="11" width="18" height="11" rx="2"/>
          <path d="M7 11V7a5 5 0 0 1 10 0v4"/>
        </svg>
        <span style={{ fontSize: 7, letterSpacing: ".16em", color: "rgba(249,236,217,0.95)", fontWeight: 500, textTransform: "uppercase" }}>Secure</span>
      </motion.div>

      {/* Shine sweep */}
      <motion.div
        animate={{ x: [-260, 360] }}
        transition={{ duration: 2.2, repeat: Infinity, repeatDelay: 1.2, ease: [0.42, 0, 0.58, 1] }}
        style={{
          position: "absolute", inset: 0, width: 80, zIndex: 4, pointerEvents: "none",
          background: "linear-gradient(100deg, transparent 0%, rgba(255,255,255,0.22) 50%, transparent 100%)",
          transform: "skewX(-18deg)",
        }}
      />
    </motion.div>
  </div>
);

const JourneyScene = ({ id, active, done, color }) => {
  const c = color || (active ? "var(--karavi-clay)" : done ? "var(--karavi-ebony)" : "var(--line-medium)");
  const fill = (active || done) ? c : "transparent";
  const accent = "var(--karavi-cream)";
  const ink = c;
  switch (id) {
    case "placed":
      return (
        <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <circle cx="24" cy="24" r="16" fill={fill} stroke={ink} strokeWidth="1.6"/>
          <path d="M16 24 L21 29 L32 18" stroke={(active || done) ? accent : ink} strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
        </svg>
      );
    case "warehouse":
      return (
        <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect x="6" y="22" width="36" height="20" fill={fill} stroke={ink} strokeWidth="1.5" strokeLinejoin="round"/>
          <path d="M4 22 L24 8 L44 22" fill={fill} stroke={ink} strokeWidth="1.5" strokeLinejoin="round"/>
          <rect x="20" y="28" width="8" height="14" fill={accent} stroke={ink} strokeWidth="0.8"/>
          <line x1="24" y1="29" x2="24" y2="41" stroke={ink} strokeWidth="0.5"/>
          <rect x="11" y="28" width="6" height="6" fill={accent} stroke={ink} strokeWidth="0.6"/>
          <rect x="31" y="28" width="6" height="6" fill={accent} stroke={ink} strokeWidth="0.6"/>
          <rect x="15" y="14" width="18" height="3" fill={accent} stroke={ink} strokeWidth="0.4"/>
        </svg>
      );
    case "flight":
      return (
        <svg width="58" height="48" viewBox="0 0 58 48" fill="none">
          {/* Mini clouds */}
          <ellipse cx="9" cy="14" rx="7" ry="2.4" fill={ink} opacity="0.25"/>
          <ellipse cx="48" cy="20" rx="6" ry="2" fill={ink} opacity="0.25"/>
          {/* Arc trail */}
          <path d="M4 38 Q 29 4, 54 38" stroke={ink} strokeDasharray="2 3" strokeWidth="1" fill="none" opacity="0.55"/>
          {/* Plane */}
          <g transform="translate(20 18) rotate(10)">
            <path d="M-12 0 L-5 -2 L9 -3 L13 -5 L14 -4 L11 -1 L14 0 L13 1 L9 0 L0 1 L-4 5 L-5 5 L-3 1 L-11 1 Z" fill={ink}/>
            <line x1="-4" y1="-1" x2="6" y2="-1.5" stroke={accent} strokeWidth="0.4" opacity="0.7"/>
          </g>
        </svg>
      );
    case "hub":
      return (
        <svg width="58" height="48" viewBox="0 0 58 48" fill="none">
          {/* Hub building */}
          <rect x="3" y="22" width="26" height="20" fill={fill} stroke={ink} strokeWidth="1.4"/>
          <rect x="6" y="26" width="20" height="3" fill={accent} stroke={ink} strokeWidth="0.4"/>
          <rect x="9" y="32" width="14" height="10" fill={accent} stroke={ink} strokeWidth="0.6"/>
          <line x1="16" y1="32" x2="16" y2="42" stroke={ink} strokeWidth="0.4"/>
          <line x1="9" y1="37" x2="23" y2="37" stroke={ink} strokeWidth="0.4"/>
          {/* Delivery van */}
          <rect x="30" y="30" width="10" height="8" fill={fill} stroke={ink} strokeWidth="1.2"/>
          <path d="M40 32 L46 32 L50 36 L50 40 L40 40 Z" fill={fill} stroke={ink} strokeWidth="1.2"/>
          <rect x="42" y="34" width="6" height="3" fill={accent} stroke={ink} strokeWidth="0.4"/>
          <circle cx="35" cy="42" r="2.2" fill={ink}/>
          <circle cx="35" cy="42" r="0.9" fill={accent}/>
          <circle cx="46" cy="42" r="2.2" fill={ink}/>
          <circle cx="46" cy="42" r="0.9" fill={accent}/>
          {/* Small box on van */}
          <rect x="32" y="32" width="3" height="3" fill={accent} stroke={ink} strokeWidth="0.4"/>
        </svg>
      );
    case "home":
      return (
        <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect x="8" y="22" width="32" height="22" fill={fill} stroke={ink} strokeWidth="1.5" strokeLinejoin="round"/>
          <path d="M5 24 L24 8 L43 24" fill={fill} stroke={ink} strokeWidth="1.5" strokeLinejoin="round"/>
          <rect x="20" y="30" width="8" height="14" fill={accent} stroke={ink} strokeWidth="1"/>
          <circle cx="26" cy="38" r="0.8" fill={ink}/>
          <rect x="12" y="28" width="5" height="5" fill={accent} stroke={ink} strokeWidth="0.6"/>
          <rect x="31" y="28" width="5" height="5" fill={accent} stroke={ink} strokeWidth="0.6"/>
          <rect x="29" y="14" width="3" height="5" fill={ink}/>
          {/* Welcome mat */}
          <rect x="18" y="43" width="12" height="2" fill={ink} opacity="0.7"/>
          {/* Delivered package on doorstep */}
          <motion.g
            initial={{ opacity: 0 }}
            animate={{ opacity: 1, scale: [0.6, 1.1, 1] }}
            transition={{ duration: 0.7, ease: [0.22, 0.61, 0.36, 1] }}
          >
            <rect x="15" y="36" width="7" height="6" fill="#935749" stroke={ink} strokeWidth="0.6"/>
            <line x1="15" y1="39" x2="22" y2="39" stroke="#f9ecd9" strokeWidth="0.5"/>
            <line x1="18.5" y1="36" x2="18.5" y2="42" stroke="#f9ecd9" strokeWidth="0.5"/>
          </motion.g>
        </svg>
      );
    default: return null;
  }
};

const OrderJourney = () => {
  const [activeIdx, setActiveIdx] = React.useState(-1);
  React.useEffect(() => {
    const delays = [350, 1150, 2050, 3000, 3950];
    const timers = delays.map((d, i) => setTimeout(() => setActiveIdx(i), d));
    return () => timers.forEach(clearTimeout);
  }, []);

  const stages = [
    { id: "placed",    label: "Order placed", sub: "Confirmed"        },
    { id: "warehouse", label: "Warehouse",    sub: "Preparing"        },
    { id: "flight",    label: "In transit",   sub: "On its way"       },
    { id: "hub",       label: "Local hub",    sub: "Out for delivery" },
    { id: "home",      label: "Your door",    sub: "Delivered"        },
  ];

  return (
    <div style={{
      marginTop: 36, padding: "26px 18px 22px",
      background: "linear-gradient(180deg, var(--karavi-bone) 0%, var(--karavi-cream) 100%)",
      borderRadius: 20, maxWidth: 680, margin: "36px auto 0",
      border: "1px solid var(--line-soft)",
    }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 22, padding: "0 6px" }}>
        <div style={{ fontSize: 11, color: "var(--fg-3)", letterSpacing: ".22em", textTransform: "uppercase", fontWeight: 500 }}>
          Your order's journey
        </div>
        <motion.div
          animate={{ opacity: activeIdx >= 4 ? 1 : 0 }}
          transition={{ duration: 0.4 }}
          style={{ fontSize: 11, color: "var(--karavi-clay)", letterSpacing: ".16em", textTransform: "uppercase", fontWeight: 500, display: "flex", alignItems: "center", gap: 6 }}
        >
          <span style={{ display: "inline-block", width: 6, height: 6, borderRadius: 999, background: "var(--status-success)" }}/>
          Live tracking
        </motion.div>
      </div>

      <div style={{ position: "relative", display: "flex", alignItems: "flex-end", padding: "0 4px" }}>
        {/* Dotted journey path - wraps under scenes */}
        <svg viewBox="0 0 640 100" preserveAspectRatio="none"
          style={{ position: "absolute", top: 28, left: 4, right: 4, width: "calc(100% - 8px)", height: 56, zIndex: 0 }}
          aria-hidden="true">
          {/* Base dashed line */}
          <path d="M 32 86 Q 160 14, 320 78 T 608 86" stroke="rgba(57,65,25,0.18)" strokeWidth="1.4" strokeDasharray="3 5" fill="none" strokeLinecap="round"/>
          {/* Filled progress line */}
          <motion.path
            d="M 32 86 Q 160 14, 320 78 T 608 86"
            stroke="var(--karavi-clay)" strokeWidth="2" fill="none" strokeLinecap="round"
            initial={{ pathLength: 0 }}
            animate={{ pathLength: activeIdx < 0 ? 0 : Math.min(1, (activeIdx + 1) / 5) }}
            transition={{ duration: 0.7, ease: [0.22, 0.61, 0.36, 1] }}
          />
        </svg>

        {stages.map((s, i) => {
          const active = activeIdx === i;
          const done   = activeIdx > i;
          return (
            <div key={s.id} style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", position: "relative", zIndex: 1 }}>
              {/* Scene with platform halo */}
              <motion.div
                animate={{
                  y: active ? [-2, -8, -2] : 0,
                  scale: active ? [1, 1.08, 1] : 1,
                }}
                transition={{ duration: 1.2, ease: [0.22, 0.61, 0.36, 1] }}
                style={{ position: "relative", display: "flex", alignItems: "center", justifyContent: "center", marginBottom: 10 }}
              >
                {active && (
                  <motion.div
                    initial={{ scale: 0.6, opacity: 0 }}
                    animate={{ scale: [0.6, 1.6, 1.9], opacity: [0.6, 0.2, 0] }}
                    transition={{ duration: 1.4, repeat: Infinity, ease: "easeOut" }}
                    style={{
                      position: "absolute", width: 56, height: 56, borderRadius: 999,
                      background: "var(--karavi-clay)", opacity: 0.15,
                    }}
                  />
                )}
                <JourneyScene id={s.id} active={active} done={done}/>
              </motion.div>

              <div style={{ textAlign: "center", lineHeight: 1.35 }}>
                <motion.div
                  animate={{ opacity: done || active ? 1 : 0.42, color: active ? "var(--karavi-clay)" : "var(--fg-display)" }}
                  transition={{ duration: 0.32 }}
                  style={{ fontSize: 10, letterSpacing: ".12em", textTransform: "uppercase", fontWeight: 600 }}
                >{s.label}</motion.div>
                <AnimatePresence mode="wait">
                  {(active || done) && (
                    <motion.div
                      key="sub"
                      initial={{ opacity: 0, y: 4 }}
                      animate={{ opacity: 1, y: 0 }}
                      exit={{ opacity: 0, y: -4 }}
                      transition={{ duration: 0.3 }}
                      style={{ fontSize: 9, color: active ? "var(--karavi-clay)" : "var(--fg-3)", marginTop: 3, fontWeight: 500 }}
                    >{s.sub}</motion.div>
                  )}
                </AnimatePresence>
              </div>
            </div>
          );
        })}
      </div>

      {/* ETA caption */}
      <motion.div
        initial={{ opacity: 0, y: 6 }}
        animate={{ opacity: activeIdx >= 4 ? 1 : 0, y: activeIdx >= 4 ? 0 : 6 }}
        transition={{ duration: 0.4, delay: 0.2 }}
        style={{ marginTop: 14, textAlign: "center", fontSize: 12, color: "var(--fg-2)", fontStyle: "italic", fontFamily: "var(--font-display)" }}
      >
        Arrived. Open at home. ✨
      </motion.div>
    </div>
  );
};

// ── Step 1: Bag Review ────────────────────────────────────────────────────────
const StepBag = ({ items, onNext, goto }) => {
  const subtotal = items.reduce((s, i) => s + i.p.price * i.qty, 0);

  if (items.length === 0) {
    return (
      <motion.div
        initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.5 }}
        style={{ textAlign: "center", padding: "80px 0" }}
      >
        <div style={{ fontFamily: "var(--font-display)", fontStyle: "italic", fontSize: 32, color: "var(--fg-display)", marginBottom: 16 }}>
          Your bag is empty.
        </div>
        <Button onClick={() => goto("shop")}>Continue browsing →</Button>
      </motion.div>
    );
  }

  return (
    <motion.div initial={{ opacity: 0, x: 30 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: -30 }} transition={{ duration: 0.38 }}>
      <h2 style={{ fontFamily: "var(--font-display)", fontWeight: 300, fontSize: "clamp(28px, 3vw, 40px)", marginBottom: 20 }}>
        Your bag
      </h2>

      {!window.KARAVI_LITE && <BagAnim/>}

      <div style={{ display: "flex", flexDirection: "column" }}>
        {items.map((item, i) => (
          <div key={i} style={{
            display: "grid", gridTemplateColumns: "72px 1fr auto", gap: 16,
            padding: "18px 0", borderBottom: "1px solid var(--line-soft)",
          }}>
            <img src={item.p.image} alt={item.p.name}
              style={{ width: 72, height: 82, borderRadius: 10, objectFit: "cover" }}/>
            <div>
              <div style={{ fontFamily: "var(--font-display)", fontSize: 17, color: "var(--fg-display)", lineHeight: 1.2 }}>{item.p.name}</div>
              <div style={{ fontSize: 12, color: "var(--fg-3)", marginTop: 3 }}>{item.size}</div>
              <div style={{ fontSize: 12, color: "var(--fg-3)", marginTop: 1 }}>Qty: {item.qty}</div>
            </div>
            <div style={{ fontFamily: "var(--font-display)", fontSize: 17, color: "var(--fg-display)", paddingTop: 2 }}>
              NZ${(item.p.price * item.qty).toFixed(0)}
            </div>
          </div>
        ))}
      </div>

      <div style={{ marginTop: 28, display: "flex", flexDirection: "column", gap: 10 }}>
        <div style={{ display: "flex", justifyContent: "space-between", fontSize: 14, color: "var(--fg-2)" }}>
          <span>Subtotal</span><span>NZ${subtotal.toFixed(0)}</span>
        </div>
        <div style={{ fontSize: 12, color: "var(--fg-3)" }}>Shipping calculated at next step.</div>
      </div>

      <div style={{ marginTop: 28, display: "flex", gap: 12, flexWrap: "wrap" }}>
        <Button full magnetic onClick={onNext}>Continue to shipping →</Button>
        <motion.button
          onClick={() => goto("shop")}
          whileHover={{ opacity: 0.7 }}
          style={{
            background: "none", border: 0, cursor: "pointer",
            fontSize: 12, letterSpacing: ".18em", textTransform: "uppercase",
            color: "var(--fg-3)", borderBottom: "1px solid var(--line-medium)",
            padding: "2px 0", minHeight: 44, width: "100%", textAlign: "center",
          }}
        >← Continue browsing</motion.button>
      </div>
    </motion.div>
  );
};

// ── Step 2: Shipping ──────────────────────────────────────────────────────────
const StepShipping = ({ onNext, onBack, subtotal, onShipSelect, selectedShip }) => {
  const [form, setFormShip] = useStateC0({
    first: "", last: "", email: "", phone: "",
    street: "", suburb: "", city: "", region: "", postcode: "",
  });
  const [errors, setErrors] = useStateC0({});

  const set = (k, v) => setFormShip(f => ({ ...f, [k]: v }));

  const validate = () => {
    const e = {};
    if (!form.first.trim()) e.first = "Required";
    if (!form.last.trim()) e.last = "Required";
    if (!form.email.trim() || !form.email.includes("@")) e.email = "Valid email required";
    if (!form.phone.trim()) e.phone = "Required";
    if (!form.street.trim()) e.street = "Required";
    if (!form.city.trim()) e.city = "Required";
    if (!form.region) e.region = "Select a region";
    if (!form.postcode.trim()) e.postcode = "Required";
    if (!selectedShip) e.ship = "Select a shipping method";
    setErrors(e);
    return Object.keys(e).length === 0;
  };

  const fld = (id, label, opts = {}) => (
    <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      <label style={{ fontSize: 11, letterSpacing: ".18em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500 }}>{label}</label>
      <input
        type={opts.type || "text"}
        value={form[id]}
        onChange={e => set(id, e.target.value)}
        placeholder={opts.placeholder || ""}
        style={{
          fontFamily: "var(--font-body)", fontSize: 14, padding: "12px 14px",
          border: `1px solid ${errors[id] ? "var(--karavi-clay)" : "var(--line-medium)"}`,
          borderRadius: 12, background: "transparent", color: "var(--fg-1)",
          outline: "none", minHeight: 48,
        }}
        aria-invalid={!!errors[id]}
      />
      {errors[id] && <span style={{ fontSize: 11, color: "var(--karavi-clay)" }}>{errors[id]}</span>}
    </div>
  );

  return (
    <motion.div initial={{ opacity: 0, x: 30 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: -30 }} transition={{ duration: 0.38 }}>
      <h2 style={{ fontFamily: "var(--font-display)", fontWeight: 300, fontSize: "clamp(28px, 3vw, 40px)", marginBottom: 20 }}>
        Shipping
      </h2>

      {!window.KARAVI_LITE && <PlaneAnim/>}

      {/* Contact */}
      <div style={{ marginBottom: 28 }}>
        <div style={{ fontSize: 11, letterSpacing: ".22em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500, marginBottom: 16, paddingBottom: 10, borderBottom: "1px solid var(--line-soft)" }}>
          Contact details
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
          {fld("first", "First name")}
          {fld("last", "Last name")}
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14, marginTop: 14 }}>
          {fld("email", "Email", { type: "email", placeholder: "you@example.com" })}
          {fld("phone", "Phone", { type: "tel", placeholder: "+64 21 ..." })}
        </div>
      </div>

      {/* Address */}
      <div style={{ marginBottom: 28 }}>
        <div style={{ fontSize: 11, letterSpacing: ".22em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500, marginBottom: 16, paddingBottom: 10, borderBottom: "1px solid var(--line-soft)" }}>
          Delivery address
        </div>
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          {fld("street", "Street address", { placeholder: "12 Aroha Street" })}
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
            {fld("suburb", "Suburb", { placeholder: "Grey Lynn" })}
            {fld("city", "City / Town", { placeholder: "Auckland" })}
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
            <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
              <label style={{ fontSize: 11, letterSpacing: ".18em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500 }}>Region</label>
              <select
                value={form.region}
                onChange={e => set("region", e.target.value)}
                style={{
                  fontFamily: "var(--font-body)", fontSize: 14, padding: "12px 14px",
                  border: `1px solid ${errors.region ? "var(--karavi-clay)" : "var(--line-medium)"}`,
                  borderRadius: 12, background: "var(--karavi-cream)", color: form.region ? "var(--fg-1)" : "var(--fg-3)",
                  outline: "none", minHeight: 48, cursor: "pointer",
                }}
              >
                <option value="">Select region</option>
                {NZ_REGIONS.map(r => <option key={r} value={r}>{r}</option>)}
              </select>
              {errors.region && <span style={{ fontSize: 11, color: "var(--karavi-clay)" }}>{errors.region}</span>}
            </div>
            {fld("postcode", "Postcode", { placeholder: "1010" })}
          </div>
        </div>
      </div>

      {/* Shipping methods */}
      <div style={{ marginBottom: 32 }}>
        <div style={{ fontSize: 11, letterSpacing: ".22em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500, marginBottom: 16, paddingBottom: 10, borderBottom: "1px solid var(--line-soft)" }}>
          Shipping method
        </div>
        {errors.ship && <div style={{ fontSize: 12, color: "var(--karavi-clay)", marginBottom: 12 }}>{errors.ship}</div>}
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {SHIP_METHODS.map(method => {
            const isDisabled = method.id === "pod";
            const isFree = method.price === 0 && subtotal >= (method.threshold || 0);
            const cost = method.price === 0
              ? (subtotal >= (method.threshold || 0) ? "Free" : `NZ$${method.threshold} min.`)
              : `NZ$${method.price}`;
            const active = selectedShip?.id === method.id;
            return (
              <motion.button
                key={method.id}
                onClick={() => !isDisabled && onShipSelect(method)}
                whileTap={{ scale: 0.99 }}
                animate={{ borderColor: active ? "var(--karavi-ebony)" : "var(--line-medium)", background: active ? "var(--karavi-bone)" : "transparent" }}
                transition={{ duration: 0.18 }}
                style={{
                  width: "100%", textAlign: "left", cursor: isDisabled ? "not-allowed" : "pointer",
                  border: "1px solid var(--line-medium)", borderRadius: 14, padding: "16px 18px",
                  display: "flex", alignItems: "center", justifyContent: "space-between",
                  opacity: isDisabled ? 0.45 : 1,
                }}
                disabled={isDisabled}
              >
                <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
                  <motion.div
                    animate={{ borderColor: active ? "var(--karavi-ebony)" : "var(--line-medium)", background: active ? "var(--karavi-ebony)" : "transparent" }}
                    transition={{ duration: 0.18 }}
                    style={{ width: 18, height: 18, borderRadius: 999, border: "1.5px solid var(--line-medium)", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}
                  >
                    {active && <div style={{ width: 8, height: 8, borderRadius: 999, background: "var(--karavi-cream)" }}/>}
                  </motion.div>
                  <div>
                    <div style={{ fontWeight: 500, fontSize: 14, color: "var(--fg-display)" }}>{method.label}</div>
                    <div style={{ fontSize: 12, color: "var(--fg-3)", marginTop: 2 }}>{method.note}</div>
                  </div>
                </div>
                <div style={{ fontWeight: 500, fontSize: 14, color: "var(--fg-1)" }}>{cost}</div>
              </motion.button>
            );
          })}
        </div>
      </div>

      <div style={{ display: "flex", gap: 12, flexWrap: "wrap" }}>
        <motion.button onClick={onBack} whileHover={{ opacity: 0.7 }}
          style={{ background: "none", border: 0, cursor: "pointer", fontSize: 12, letterSpacing: ".18em", textTransform: "uppercase", color: "var(--fg-3)", borderBottom: "1px solid var(--line-medium)", padding: "2px 0", minHeight: 44 }}>
          ← Back to bag
        </motion.button>
        <div style={{ flex: 1 }}>
          <Button full magnetic onClick={() => { if (validate()) onNext(form); }}>Continue to payment →</Button>
        </div>
      </div>
    </motion.div>
  );
};

// ── Step 3: Payment ───────────────────────────────────────────────────────────
const StepPayment = ({ onBack, onConfirm, selectedShip, subtotal }) => {
  const [method, setMethod] = useStateC0("card");
  const [card, setCard] = useStateC0({ num: "", expiry: "", cvv: "", name: "" });
  const [processing, setProcessing] = useStateC0(false);

  const total = subtotal + (selectedShip?.price ?? 0);

  const handleConfirm = () => {
    setProcessing(true);
    setTimeout(() => { setProcessing(false); onConfirm(); }, 1800);
  };

  const setC = (k, v) => setCard(c => ({ ...c, [k]: v }));

  const formatCard = (v) => v.replace(/\D/g, "").slice(0, 16).replace(/(.{4})/g, "$1 ").trim();
  const formatExpiry = (v) => {
    const d = v.replace(/\D/g, "").slice(0, 4);
    return d.length > 2 ? d.slice(0, 2) + " / " + d.slice(2) : d;
  };

  return (
    <motion.div initial={{ opacity: 0, x: 30 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: -30 }} transition={{ duration: 0.38 }}>
      <h2 style={{ fontFamily: "var(--font-display)", fontWeight: 300, fontSize: "clamp(28px, 3vw, 40px)", marginBottom: 20 }}>
        Payment
      </h2>

      {!window.KARAVI_LITE && <CardAnim/>}

      {/* Method selector */}
      <div style={{ marginBottom: 24 }}>
        <div style={{ fontSize: 11, letterSpacing: ".22em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500, marginBottom: 16, paddingBottom: 10, borderBottom: "1px solid var(--line-soft)" }}>
          Payment method
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
          {PAY_METHODS.map(m => {
            const active = method === m.id;
            return (
              <motion.button
                key={m.id}
                onClick={() => setMethod(m.id)}
                animate={{ borderColor: active ? "var(--karavi-ebony)" : "var(--line-medium)", background: active ? "var(--karavi-bone)" : "transparent" }}
                transition={{ duration: 0.18 }}
                whileTap={{ scale: 0.98 }}
                style={{ textAlign: "left", cursor: "pointer", border: "1px solid var(--line-medium)", borderRadius: 14, padding: "14px 16px" }}
              >
                <div style={{ fontWeight: 500, fontSize: 13, color: "var(--fg-display)", marginBottom: 2 }}>{m.label}</div>
                <div style={{ fontSize: 11, color: "var(--fg-3)" }}>{m.note}</div>
              </motion.button>
            );
          })}
        </div>
      </div>

      {/* Card form */}
      <AnimatePresence mode="wait">
        {method === "card" && (
          <motion.div
            key="card-form"
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: "auto", opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            transition={{ duration: 0.3 }}
            style={{ overflow: "hidden", marginBottom: 24 }}
          >
            <div style={{ display: "flex", flexDirection: "column", gap: 14, paddingTop: 4 }}>
              <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
                <label style={{ fontSize: 11, letterSpacing: ".18em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500 }}>Card number</label>
                <input
                  type="text" inputMode="numeric" value={card.num} placeholder="1234 5678 9012 3456"
                  onChange={e => setC("num", formatCard(e.target.value))}
                  style={{ fontFamily: "var(--font-body)", fontSize: 14, padding: "12px 14px", border: "1px solid var(--line-medium)", borderRadius: 12, background: "transparent", color: "var(--fg-1)", outline: "none", minHeight: 48, letterSpacing: "0.05em" }}
                />
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 14 }}>
                <div style={{ gridColumn: "1 / 3", display: "flex", flexDirection: "column", gap: 6 }}>
                  <label style={{ fontSize: 11, letterSpacing: ".18em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500 }}>Name on card</label>
                  <input type="text" value={card.name} placeholder="A. Patel" onChange={e => setC("name", e.target.value)}
                    style={{ fontFamily: "var(--font-body)", fontSize: 14, padding: "12px 14px", border: "1px solid var(--line-medium)", borderRadius: 12, background: "transparent", color: "var(--fg-1)", outline: "none", minHeight: 48 }}/>
                </div>
                <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
                  <label style={{ fontSize: 11, letterSpacing: ".18em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500 }}>Expiry</label>
                  <input type="text" inputMode="numeric" value={card.expiry} placeholder="MM / YY"
                    onChange={e => setC("expiry", formatExpiry(e.target.value))}
                    style={{ fontFamily: "var(--font-body)", fontSize: 14, padding: "12px 14px", border: "1px solid var(--line-medium)", borderRadius: 12, background: "transparent", color: "var(--fg-1)", outline: "none", minHeight: 48 }}/>
                </div>
              </div>
              <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
                <label style={{ fontSize: 11, letterSpacing: ".18em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500 }}>CVV</label>
                <input type="text" inputMode="numeric" value={card.cvv} placeholder="123" maxLength={4}
                  onChange={e => setC("cvv", e.target.value.replace(/\D/g, "").slice(0, 4))}
                  style={{ fontFamily: "var(--font-body)", fontSize: 14, padding: "12px 14px", border: "1px solid var(--line-medium)", borderRadius: 12, background: "transparent", color: "var(--fg-1)", outline: "none", minHeight: 48, maxWidth: 120 }}/>
              </div>
            </div>
          </motion.div>
        )}

        {method === "poli" && (
          <motion.div key="poli" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.22 }}
            style={{ background: "var(--karavi-bone)", borderRadius: 14, padding: "16px 18px", marginBottom: 24 }}>
            <p style={{ fontSize: 14, color: "var(--fg-2)", lineHeight: 1.6 }}>
              You'll be redirected to your bank's secure website to authorise the payment. No card or account details are shared with Karavi.
            </p>
          </motion.div>
        )}

        {method === "bank" && (
          <motion.div key="bank" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.22 }}
            style={{ background: "var(--karavi-bone)", borderRadius: 14, padding: "16px 18px", marginBottom: 24 }}>
            <p style={{ fontSize: 14, color: "var(--fg-2)", lineHeight: 1.6 }}>
              We'll email you our bank details immediately after you place the order. Your order will be held for 3 working days pending payment.
            </p>
          </motion.div>
        )}

        {method === "pod" && (
          <motion.div key="pod" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.22 }}
            style={{ background: "var(--karavi-bone)", borderRadius: 14, padding: "16px 18px", marginBottom: 24 }}>
            <p style={{ fontSize: 14, color: "var(--fg-2)", lineHeight: 1.6 }}>
              Pay by card or cash on the day of your White Glove delivery. Our team will confirm a delivery window by phone.
            </p>
          </motion.div>
        )}
      </AnimatePresence>

      {/* Security note */}
      <div style={{ display: "flex", gap: 8, alignItems: "center", marginBottom: 28, padding: "10px 0" }}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--fg-3)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
          <rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>
        </svg>
        <span style={{ fontSize: 12, color: "var(--fg-3)" }}>All transactions are encrypted and secure.</span>
      </div>

      <div style={{ display: "flex", gap: 12, flexWrap: "wrap" }}>
        <motion.button onClick={onBack} whileHover={{ opacity: 0.7 }}
          style={{ background: "none", border: 0, cursor: "pointer", fontSize: 12, letterSpacing: ".18em", textTransform: "uppercase", color: "var(--fg-3)", borderBottom: "1px solid var(--line-medium)", padding: "2px 0", minHeight: 44 }}>
          ← Back
        </motion.button>
        <div style={{ flex: 1 }}>
          <Button full magnetic onClick={handleConfirm} disabled={processing}
            style={processing ? { opacity: 0.7 } : {}}>
            <AnimatePresence mode="wait">
              <motion.span key={processing ? "proc" : "pay"}
                initial={{ opacity: 0, y: 6 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -6 }}
                transition={{ duration: 0.18 }}>
                {processing ? "Processing…" : `Place order · NZ$${total.toFixed(0)}`}
              </motion.span>
            </AnimatePresence>
          </Button>
        </div>
      </div>
    </motion.div>
  );
};

// ── Confirmation ──────────────────────────────────────────────────────────────
const StepConfirm = ({ onComplete, goto }) => {
  const orderNum = `KAR-${Math.floor(100000 + Math.random() * 900000)}`;
  const today = new Date();
  const eta = new Date(today);
  eta.setDate(today.getDate() + 7);
  const etaStr = eta.toLocaleDateString("en-NZ", { weekday: "long", day: "numeric", month: "long" });

  return (
    <motion.div
      initial={{ opacity: 0, scale: 0.97 }} animate={{ opacity: 1, scale: 1 }}
      transition={{ duration: 0.6, ease: [0.22, 0.61, 0.36, 1] }}
      style={{ textAlign: "center", padding: "48px 0 24px" }}
    >
      {/* Checkmark */}
      <motion.div
        initial={{ scale: 0 }} animate={{ scale: 1 }}
        transition={{ type: "spring", stiffness: 280, damping: 20, delay: 0.15 }}
        style={{
          width: 72, height: 72, borderRadius: 999, margin: "0 auto 28px",
          background: "var(--status-success)", display: "flex", alignItems: "center", justifyContent: "center",
        }}
      >
        <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="var(--karavi-cream)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <path d="M20 6 9 17l-5-5"/>
        </svg>
      </motion.div>

      <Eyebrow style={{ justifyContent: "center", display: "flex", marginBottom: 14 }}>Order confirmed</Eyebrow>
      <h2 style={{ fontFamily: "var(--font-display)", fontWeight: 300, fontSize: "clamp(32px, 4vw, 52px)", lineHeight: 1.05, marginBottom: 16 }}>
        Thank you.
      </h2>
      <p style={{ fontSize: 15, color: "var(--fg-2)", lineHeight: 1.7, maxWidth: 440, margin: "0 auto 32px" }}>
        Your order <strong style={{ color: "var(--fg-display)" }}>{orderNum}</strong> has been placed. A confirmation has been sent to your email. Estimated arrival by <strong style={{ color: "var(--fg-display)" }}>{etaStr}</strong>.
      </p>

      <div style={{ display: "flex", gap: 12, justifyContent: "center", flexWrap: "wrap" }}>
        <Button onClick={() => goto("home")}>Continue shopping →</Button>
        <Button variant="secondary" onClick={onComplete}>Track my order</Button>
      </div>

      {!window.KARAVI_LITE ? (
        <OrderJourney/>
      ) : (
        <div style={{ marginTop: 48, padding: "24px", background: "var(--karavi-bone)", borderRadius: 16, maxWidth: 400, margin: "48px auto 0" }}>
          <div style={{ fontSize: 12, color: "var(--fg-3)", letterSpacing: ".12em", textTransform: "uppercase", marginBottom: 8 }}>What happens next</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 12, textAlign: "left" }}>
            {[
              "We begin preparing your order today.",
              "You'll receive a shipping notification with tracking in 1–2 days.",
              "Your pieces arrive in 5–7 working days.",
            ].map((text, i) => (
              <div key={i} style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
                <div style={{ width: 22, height: 22, borderRadius: 999, flexShrink: 0, background: "var(--karavi-ebony)", color: "var(--karavi-cream)", fontSize: 11, fontWeight: 600, display: "flex", alignItems: "center", justifyContent: "center" }}>{i + 1}</div>
                <span style={{ fontSize: 13, color: "var(--fg-2)", lineHeight: 1.5, paddingTop: 2 }}>{text}</span>
              </div>
            ))}
          </div>
        </div>
      )}
    </motion.div>
  );
};

// ── Main Checkout page ────────────────────────────────────────────────────────
const Checkout = ({ items, onComplete, goto }) => {
  const [step, setStep] = useStateC0(1);
  const [shippingForm, setShippingForm] = useStateC0(null);
  const [selectedShip, setSelectedShip] = useStateC0(null);

  const subtotal = items.reduce((s, i) => s + i.p.price * i.qty, 0);

  return (
    <main>
      <Section style={{ maxWidth: 1100, margin: "0 auto", paddingTop: 0 }}>
        <CheckoutProgress step={step}/>

        <div style={{
          display: "grid",
          gridTemplateColumns: step === 4 ? "1fr" : "1fr 380px",
          gap: 48, alignItems: "start",
        }} className="k-checkout-grid">
          <div>
            <AnimatePresence mode="wait">
              {step === 1 && (
                <StepBag key="bag" items={items} goto={goto}
                  onNext={() => setStep(2)}/>
              )}
              {step === 2 && (
                <StepShipping key="ship" subtotal={subtotal}
                  selectedShip={selectedShip}
                  onShipSelect={setSelectedShip}
                  onBack={() => setStep(1)}
                  onNext={(form) => { setShippingForm(form); setStep(3); }}/>
              )}
              {step === 3 && (
                <StepPayment key="pay" subtotal={subtotal}
                  selectedShip={selectedShip}
                  onBack={() => setStep(2)}
                  onConfirm={() => setStep(4)}/>
              )}
              {step === 4 && (
                <StepConfirm key="confirm" onComplete={onComplete} goto={goto}/>
              )}
            </AnimatePresence>
          </div>

          {step < 4 && (
            <Summary items={items} shipping={selectedShip} step={step}/>
          )}
        </div>
      </Section>

      <style>{`
        @media (max-width: 860px) {
          .k-checkout-grid { grid-template-columns: 1fr !important; }
          .k-hide-desktop { display: block !important; }
          .k-hide-mobile { display: none !important; }
        }
        @media (min-width: 861px) {
          .k-hide-desktop { display: none !important; }
          .k-hide-mobile { display: block !important; }
        }
      `}</style>
    </main>
  );
};
window.Checkout = Checkout;
