// Xedap.vn product detail — full storefront layout: gallery, buy box,
// features + specs, story block, reviews, and two related product rows.
const { Button, IconButton, Badge, PriceTag, Rating, ProductCard, ColorSwatches,
  SizeGuideModal, InstallmentModal, WarrantyModal, CompareTray, CompareModal } = window.XedapVnDesignSystem_03b1c0;
const { useCompareState } = window; // hook đi kèm CompareTray (bundle gán ra window)

const RAPTOR_SHOTS = [
  "https://cdn.hstatic.net/files/200001086651/file/tinh_nang_1.png",
  "https://cdn.hstatic.net/files/200001086651/file/tinh_nang_2.png",
  "https://cdn.hstatic.net/files/200001086651/file/xe_dia_h_nh_cate.png",
  "https://cdn.hstatic.net/files/200001086651/file/xe_dap_do_thi_cate.png",
  "https://cdn.hstatic.net/files/200001086651/file/xe_dap_do_thi_cate.png",
];
const vnd = (n) => new Intl.NumberFormat("vi-VN").format(n) + "đ";
const wrap = { maxWidth: 1440, margin: "0 auto", padding: "0 24px" };

/* ---------- Reveal on scroll ---------- */
function Reveal({ children, delay = 0, y = 24, style }) {
  const ref = React.useRef(null);
  const [shown, setShown] = React.useState(false);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(([e]) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return <div ref={ref} style={{ ...style, opacity: shown ? 1 : 0, transform: shown ? "none" : `translateY(${y}px)`, transition: `opacity .6s ease ${delay}ms, transform .7s cubic-bezier(.22,.61,.36,1) ${delay}ms`, willChange: "opacity, transform" }}>{children}</div>;
}

/* ---------- Live countdown ---------- */
function Countdown({ seconds = 8 * 3600 + 14 * 60 + 5 }) {
  const [left, setLeft] = React.useState(seconds);
  React.useEffect(() => {
    const id = setInterval(() => setLeft((s) => (s > 0 ? s - 1 : 0)), 1000);
    return () => clearInterval(id);
  }, []);
  const p = (n) => String(n).padStart(2, "0");
  const box = { fontFamily: "var(--font-mono)", fontWeight: 700, color: "var(--foreground)", minWidth: 24, textAlign: "center", display: "inline-block" };
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
      <span style={box}>{p(Math.floor(left / 3600))}</span>:
      <span style={box}>{p(Math.floor((left % 3600) / 60))}</span>:
      <span style={box}>{p(left % 60)}</span>
    </span>
  );
}

/* ---------- Breadcrumb ---------- */
function brandOf(product) {
  return product.brand || (product.code || "").replace("Thương hiệu: ", "") || "RAPTOR";
}

function Breadcrumb({ product }) {
  const parts = ["Xe đạp", product.category || "Xe đạp địa hình", brandOf(product), product.name || "Sản phẩm"];
  return (
    <nav style={{ display: "flex", flexWrap: "wrap", gap: 6, fontSize: 12, color: "var(--muted-foreground)" }}>
      {parts.map((p, i) => (
        <span key={i} style={{ display: "flex", gap: 6, alignItems: "center" }}>
          {i > 0 && <i className="ph ph-caret-right" style={{ fontSize: 10 }} />}
          <span style={{ color: i === parts.length - 1 ? "var(--foreground)" : "var(--muted-foreground)", fontWeight: i === parts.length - 1 ? 500 : 400 }}>{p}</span>
        </span>
      ))}
    </nav>
  );
}

/* ---------- Lightbox (coverflow slide viewer) ---------- */
function Lightbox({ images, index, product, onClose, onIndex }) {
  const count = images.length;
  const go = React.useCallback((d) => onIndex(((index + d) % count + count) % count), [index, count, onIndex]);
  const [dim, setDim] = React.useState({ w: 1280, h: 800 });
  React.useEffect(() => {
    const measure = () => setDim({ w: window.innerWidth, h: window.innerHeight });
    measure();
    const onKey = (e) => {
      if (e.key === "Escape") onClose();
      else if (e.key === "ArrowRight") go(1);
      else if (e.key === "ArrowLeft") go(-1);
    };
    window.addEventListener("resize", measure);
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("resize", measure); window.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, [go, onClose]);

  // Coverflow geometry — active card big & centered, others thin slats.
  const stageH = Math.max(280, dim.h - 210);
  const activeW = Math.min(dim.w * 0.56, 940, (stageH - 30) * 1.5);
  const activeH = Math.min(stageH - 20, activeW / 1.5);
  const restW = Math.max(70, Math.round(activeW * 0.16));
  const restH = Math.round(activeH * 0.78);
  const gap = 26;
  const R = Math.max(1, Math.min(6, Math.floor(count / 2)));
  const relOf = (i) => { let r = ((i - index) % count + count) % count; if (r > count / 2) r -= count; return r; };
  const xForRel = (rel) => {
    const ar = Math.abs(rel), c1 = activeW / 2 + gap + restW / 2, pitch = restW + gap;
    const mag = ar <= 1 ? ar * c1 : c1 + (ar - 1) * pitch;
    return (rel < 0 ? -1 : 1) * mag;
  };
  const ease = "transform .55s cubic-bezier(.32,.72,0,1), width .55s cubic-bezier(.32,.72,0,1), height .55s cubic-bezier(.32,.72,0,1), opacity .4s ease";
  const nav = (dir, aria) => (
    <button onClick={() => go(dir)} aria-label={aria} style={{ position: "absolute", [dir < 0 ? "left" : "right"]: 24, top: "50%", transform: "translateY(-50%)", width: 52, height: 52, borderRadius: 5, border: "1px solid rgba(255,255,255,.25)", background: "rgba(255,255,255,.1)", backdropFilter: "blur(8px)", color: "#fff", cursor: "pointer", display: "grid", placeItems: "center", fontSize: "calc(13px + 9px*var(--ts))", zIndex: 2000 }}><i className={`ph ph-caret-${dir < 0 ? "left" : "right"}`} /></button>
  );

  return ReactDOM.createPortal(
    <div style={{ position: "fixed", inset: 0, zIndex: 3000, background: "rgba(12,14,16,.97)", backdropFilter: "blur(4px)", display: "flex", flexDirection: "column" }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "18px 24px", color: "#fff", flexShrink: 0, zIndex: 10 }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
          <span style={{ fontFamily: "var(--font-heading)", fontWeight: 700, fontSize: "calc(13px + 3px*var(--ts))" }}>{product.name}</span>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, opacity: .7 }}>{String(index + 1).padStart(2, "0")} / {String(count).padStart(2, "0")}</span>
        </div>
        <button onClick={onClose} aria-label="Đóng" style={{ width: 44, height: 44, borderRadius: 5, border: "1px solid rgba(255,255,255,.25)", background: "rgba(255,255,255,.1)", color: "#fff", cursor: "pointer", display: "grid", placeItems: "center", fontSize: "calc(13px + 7px*var(--ts))" }}><i className="ph ph-x" /></button>
      </div>
      <div style={{ position: "relative", flex: 1, minHeight: 0 }}>
        <div style={{ position: "absolute", inset: 0, isolation: "isolate", overflow: "hidden" }}>
          {images.map((s, i) => {
            const rel = relOf(i), ar = Math.abs(rel), a = Math.min(ar, 1);
            const w = activeW + (restW - activeW) * a, h = activeH + (restH - activeH) * a;
            const op = ar >= R + 1 ? 0 : ar > R ? 1 - (ar - R) : 1;
            return (
              <div key={i} onClick={() => onIndex(i)} style={{ position: "absolute", left: "50%", top: "50%", transform: `translate(-50%,-50%) translateX(${xForRel(rel)}px)`, width: w, height: h, zIndex: Math.round(1000 - ar * 100), opacity: op, transition: ease, cursor: ar < .5 ? "default" : "pointer", borderRadius: 5, overflow: "hidden", background: "#1a1c1e", boxShadow: ar < .5 ? "0 30px 80px rgba(0,0,0,.6), inset 0 0 0 1px rgba(255,255,255,.06)" : "0 16px 44px rgba(0,0,0,.5)", pointerEvents: op < .05 ? "none" : "auto" }}>
                <img src={s} alt="" draggable={false} style={{ width: "100%", height: "100%", objectFit: "cover", display: "block", userSelect: "none", pointerEvents: "none" }} />
              </div>
            );
          })}
        </div>
        {count > 1 && nav(-1, "Ảnh trước")}
        {count > 1 && nav(1, "Ảnh tiếp theo")}
      </div>
    </div>,
    document.body
  );
}

/* ---------- Gallery ---------- */
// Khớp sản phẩm đang xem với dữ liệu thật api.xedap.vn (theo slug, rồi theo tên).
const productDetailNorm = (s) => (s || "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, " ").trim();
function productDetailApiMatch(product) {
  const api = window.XedapApiData;
  if (!api || !product) return null;
  const P = api.PRODUCTS;
  const n = productDetailNorm(product.name);
  return (
    P.find((p) => p.slug === product.slug) ||
    P.find((p) => productDetailNorm(p.name) === n) ||
    P.find((p) => { const a = productDetailNorm(p.name).split(" ").filter((w) => w.length > 2); const b = n.split(" "); const hit = a.filter((w) => b.includes(w)).length; return a.length && hit >= Math.max(4, Math.ceil(a.length * 0.7)); }) ||
    null
  );
}
function Gallery({ product }) {
  // Ảnh ưu tiên từ api.xedap.vn; demo thêm ảnh cùng hãng/danh mục cho đủ số slide.
  const apiP = productDetailApiMatch(product);
  const own = [...new Set([].concat(apiP ? [apiP.img, apiP.img2] : [], product.images || [], product.img || [], product.img2 || []).filter(Boolean))];
  const api = window.XedapApiData;
  const filler = api && own.length ? [...new Set(api.PRODUCTS.filter((p) => p.slug !== product.slug && (p.brand === brandOf(product) || p.category === product.category)).flatMap((p) => [p.img, p.img2]).filter(Boolean))] : [];
  const apiShots = own.length ? [...own, ...filler.filter((s) => !own.includes(s))].slice(0, 6) : [];
  const main = apiShots[0] || RAPTOR_SHOTS[0];
  const shots = apiShots.length ? apiShots : [main, ...RAPTOR_SHOTS.filter((s) => s !== main)].slice(0, 4);
  const life = "https://cdn.hstatic.net/files/200001086651/file/tinh_nang_3.png";
  const all = apiShots.length ? shots : [...shots, life];
  // Ảnh giữ nguyên thứ tự; video sản phẩm gắn thêm ở cuối dải thumbnail.
  const videoId = product.videoId || "_Nqo5EEb4qg";
  const videoThumb = product.videoThumb || `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`;
  const media = [...(videoId ? [{ type: "video", id: videoId, thumb: videoThumb }] : []), ...all.map((s) => ({ type: "image", src: s }))];
  const [active, setActive] = React.useState(0);
  const [playing, setPlaying] = React.useState(false);
  const frameRef = React.useRef(null);
  const [lightbox, setLightbox] = React.useState(false);
  const [zoom, setZoom] = React.useState(false);
  const [zpos, setZpos] = React.useState({ x: 50, y: 50 });
  const onMove = (e) => { const r = e.currentTarget.getBoundingClientRect(); setZpos({ x: ((e.clientX - r.left) / r.width) * 100, y: ((e.clientY - r.top) / r.height) * 100 }); };
  const pick = (i) => { setActive(i); setPlaying(false); };
  const cur = media[active];
  const imgOffset = media.length - all.length;
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
      {lightbox && <Lightbox images={all} index={Math.max(0, active - imgOffset)} product={product} onClose={() => setLightbox(false)} onIndex={(i) => setActive(i + imgOffset)} />}
      {cur.type === "video" ? (
        <div style={{ position: "relative", aspectRatio: "1/1", overflow: "hidden", background: "#000", border: "1px solid var(--border)", display: "grid", placeItems: "center" }}>
          {playing ? (
            <div style={{ position: "relative", width: "100%", aspectRatio: "16/9" }}>
              <iframe ref={frameRef} src={`https://www.youtube-nocookie.com/embed/${cur.id}?autoplay=1&rel=0&playsinline=1&modestbranding=1&controls=1&iv_load_policy=3`} title={`Video ${product.name}`} referrerPolicy="strict-origin-when-cross-origin" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowFullScreen style={{ width: "100%", height: "100%", border: 0, display: "block" }}></iframe>
              <a href={`https://www.youtube.com/watch?v=${cur.id}`} target="_blank" rel="noreferrer" style={{ position: "absolute", right: 8, bottom: -30, fontSize: 12, color: "rgba(255,255,255,.75)", textDecoration: "underline" }}>Không xem được? Mở trên YouTube</a>
            </div>
          ) : (
            <button onClick={() => setPlaying(true)} aria-label="Phát video sản phẩm" style={{ position: "absolute", inset: 0, padding: 0, border: 0, background: `#000 center/cover no-repeat url(${cur.thumb})`, cursor: "pointer", display: "grid", placeItems: "center" }}>
              <span style={{ width: 74, height: 74, borderRadius: "50%", background: "rgba(0,0,0,.55)", border: "2px solid rgba(255,255,255,.9)", color: "#fff", display: "grid", placeItems: "center", fontSize: "calc(13px + 17px*var(--ts))" }}><i className="ph-fill ph-play" /></span>
            </button>
          )}
          <span style={{ position: "absolute", left: 14, top: 14, padding: "5px 10px", borderRadius: "var(--radius-md)", background: "rgba(0,0,0,.65)", color: "#fff", fontSize: 12, fontWeight: 700, letterSpacing: ".02em", display: "flex", alignItems: "center", gap: 6, pointerEvents: "none" }}><i className="ph-fill ph-video-camera" /> Video sản phẩm</span>
        </div>
      ) : (
      <div onMouseEnter={() => setZoom(true)} onMouseLeave={() => setZoom(false)} onMouseMove={onMove} style={{ position: "relative", flex: 1, aspectRatio: "1/1", overflow: "hidden", background: "var(--secondary)", border: "1px solid var(--border)" }}>
        <img src={cur.src} alt={product.name} onClick={() => setLightbox(true)} style={{ width: "100%", height: "100%", objectFit: "contain", cursor: "zoom-in", transformOrigin: `${zpos.x}% ${zpos.y}%`, transform: zoom ? "scale(2)" : "scale(1)", transition: zoom ? "transform .12s ease-out" : "transform .3s ease" }} />
        <button onClick={() => setLightbox(true)} aria-label="Xem toàn màn hình" style={{ position: "absolute", right: 14, bottom: 14, width: 34, height: 34, borderRadius: "var(--radius-md)", border: "1px solid var(--border)", background: "rgba(255,255,255,.92)", cursor: "pointer", color: "var(--foreground)", zIndex: 2 }}><i className="ph ph-arrows-out" /></button>
      </div>
      )}
      <div style={{ display: "flex", gap: 10, alignItems: "stretch", minWidth: 0 }}>
        {media.length > 1 && (
          <button onClick={() => pick((active - 1 + media.length) % media.length)} aria-label="Ảnh trước" style={{ width: 40, flexShrink: 0, border: "1px solid var(--border)", background: "#fff", cursor: "pointer", color: "var(--foreground)", display: "grid", placeItems: "center" }}><i className="ph ph-arrow-left" /></button>
        )}
        <div style={{ display: "grid", gridTemplateColumns: `repeat(${media.length}, minmax(0,1fr))`, gap: 12, flex: 1, minWidth: 0, alignItems: "start" }}>
          {media.map((m, i) => (
            <button key={i} onClick={() => pick(i)} style={{ position: "relative", padding: 0, width: "100%", minWidth: 0, border: `2px solid ${i === active ? "var(--primary)" : "var(--border)"}`, overflow: "hidden", cursor: "pointer", aspectRatio: "1/1", background: m.type === "video" ? "#000" : "var(--secondary)", borderRadius: 0 }}>
              <img src={m.type === "video" ? m.thumb : m.src} alt="" onError={m.type === "video" ? (e) => { e.currentTarget.src = `https://img.youtube.com/vi/${m.id}/hqdefault.jpg`; } : undefined} style={{ width: "100%", height: "100%", objectFit: m.type === "video" ? "cover" : "contain" }} />
              {m.type === "video" && <span style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", background: "rgba(0,0,0,.28)", color: "#fff", fontSize: "calc(13px + 9px*var(--ts))" }}><i className="ph-fill ph-play-circle" /></span>}
            </button>
          ))}
        </div>
        {media.length > 1 && (
          <button onClick={() => pick((active + 1) % media.length)} aria-label="Ảnh tiếp theo" style={{ width: 40, flexShrink: 0, border: "1px solid var(--border)", background: "#fff", cursor: "pointer", color: "var(--foreground)", display: "grid", placeItems: "center" }}><i className="ph ph-arrow-right" /></button>
        )}
      </div>
    </div>
  );
}

/* ---------- Buy box ---------- */
function OptionTiles({ label, note, items, sel, setSel }) {
  return (
    <div>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 10 }}>
        <span style={{ fontSize: 13, fontWeight: 600 }}>{label}</span>
        {note && <span style={{ fontSize: 12, color: "var(--muted-foreground)" }}>{note}</span>}
      </div>
      <div style={{ display: "flex", gap: 10 }}>
        {items.map((it, i) => (
          <button key={i} onClick={() => setSel(i)} title={it.label} style={{ position: "relative", width: 64, height: 64, padding: 4, borderRadius: "var(--radius-md)", border: `1.5px solid ${i === sel ? "var(--primary)" : "var(--border)"}`, background: "#fff", cursor: "pointer" }}>
            <img src={it.img} alt={it.label} style={{ width: "100%", height: "100%", objectFit: "contain" }} />
            {i === sel && <span style={{ position: "absolute", right: -6, top: -6, width: 18, height: 18, borderRadius: 5, background: "var(--primary)", color: "#fff", fontSize: 10, display: "grid", placeItems: "center" }}><i className="ph-fill ph-check" /></span>}
          </button>
        ))}
      </div>
    </div>
  );
}

const GIFT_ITEMS = [
  { name: "Nón bảo hiểm", img: "https://cdn.hstatic.net/files/200001086651/file/20_3c147254ff2e4d5bac50549308c5267f.png", colors: ["Trắng", "Đen"], sizes: ["XS", "S", "M"], price: 0, original: 259000 },
  { name: "Nón bảo hiểm", img: "https://cdn.hstatic.net/files/200001086651/file/21_cccd6ae164a5443789a487cdb0c0da9a.png", colors: ["Trắng", "Đen"], sizes: ["XS", "S", "M"], price: 0, original: 259000 },
  { name: "Găng tay", img: "https://cdn.hstatic.net/files/200001086651/file/106.png", colors: ["Đen", "Xám"], sizes: ["M", "L"], price: 0, original: 149000 },
];
const COMBO_ITEMS = [
  { name: "Găng tay xe đạp SKMT", img: "https://cdn.hstatic.net/files/200001086651/file/106.png", colors: ["Trắng", "Đen"], sizes: ["M", "L", "XL"], price: 400000, original: 530000 },
  { name: "Giày đạp xe Shimano MX-101", img: "https://cdn.hstatic.net/files/200001086651/file/27_2f8b64b9dc5241b0b8664af2c39c7d12.png", colors: ["Đen"], sizes: ["39", "40", "41", "42"], price: 1500000, original: 1790000 },
  { name: "Nón bảo hiểm ACTIVE XQ-36", img: "https://cdn.hstatic.net/files/200001086651/file/21_cccd6ae164a5443789a487cdb0c0da9a.png", colors: ["Đen xanh dương", "Đen"], sizes: ["Tiêu chuẩn"], price: 299000, original: 359000 },
  { name: "Kính đi đường", img: "https://cdn.hstatic.net/files/200001086651/file/20_3c147254ff2e4d5bac50549308c5267f.png", colors: ["Trắng", "Đen"], sizes: ["S", "M", "L"], price: 899000, original: 1190000 },
];
const dong = (n) => n === 0 ? "0đ" : new Intl.NumberFormat("vi-VN").format(n) + "đ";

const STORES = [
  { qty: 6, name: "Nguyễn Cơ Thạch", city: "TP. Hồ Chí Minh", district: "TP. Thủ Đức", stock: "in", address: "Shop B1-00.05, Sarimi, 72 Nguyễn Cơ Thạch, P. An Khánh, TP. Thủ Đức", phone: "1800 9473", hours: "08:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/72.png" },
  { qty: 4, name: "Nguyễn Duy Trinh", city: "TP. Hồ Chí Minh", district: "TP. Thủ Đức", stock: "in", address: "585 Nguyễn Duy Trinh, P. Bình Trưng, TP. Thủ Đức", phone: "1800 9473", hours: "09:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/73.png" },
  { qty: 2, name: "Võ Thị Sáu", city: "TP. Hồ Chí Minh", district: "Quận 3", stock: "low", address: "63C Võ Thị Sáu, P. Võ Thị Sáu", phone: "1800 9473", hours: "09:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/76.png" },
  { qty: 5, name: "Đặng Văn Bi", city: "TP. Hồ Chí Minh", district: "TP. Thủ Đức", stock: "in", address: "200-202 Đặng Văn Bi, P. Thủ Đức, TP. Thủ Đức", phone: "1800 9473", hours: "09:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/50.png" },
  { qty: 8, name: "Nguyễn Thị Thập", city: "TP. Hồ Chí Minh", district: "Quận 7", stock: "in", address: "458 Nguyễn Thị Thập, P. Tân Hưng", phone: "1800 9473", hours: "09:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/75.png" },
  { qty: 0, name: "Hải Thượng Lãn Ông", city: "TP. Hồ Chí Minh", district: "Quận 5", stock: "out", address: "100 Hải Thượng Lãn Ông, P. Chợ Lớn", phone: "1800 9473", hours: "09:00 - 19:00", img: "https://cdn.hstatic.net/files/200001086651/file/72.png" },
  { qty: 3, name: "Bờ Bao Tân Thắng", city: "TP. Hồ Chí Minh", district: "Tân Phú", stock: "in", address: "93C Bờ Bao Tân Thắng, P. Tân Thành", phone: "1800 9473", hours: "09:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/73.png" },
  { qty: 1, name: "Tên Lửa - Bình Tân", city: "TP. Hồ Chí Minh", district: "Bình Tân", stock: "low", address: "122 Tên Lửa, P. An Lạc", phone: "1800 9473", hours: "09:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/76.png" },
  { qty: 7, name: "Tô Ký - Hóc Môn", city: "TP. Hồ Chí Minh", district: "Hóc Môn", stock: "in", address: "14/1A Tô Ký, Xã Đông Thạnh", phone: "1800 9473", hours: "09:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/50.png" },
  { qty: 4, name: "Emart Gò Vấp", city: "TP. Hồ Chí Minh", district: "Gò Vấp", stock: "in", address: "366 Phan Văn Trị, P. An Nhơn", phone: "1800 9473", hours: "09:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/76.png" },
  { qty: 0, name: "Emart Phan Huy Ích", city: "TP. Hồ Chí Minh", district: "Gò Vấp", stock: "out", address: "385 Phan Huy Ích, P. An Hội Tây", phone: "1800 9473", hours: "07:30 - 22:30", img: "https://cdn.hstatic.net/files/200001086651/file/50.png" },
  { qty: 9, name: "Nguyễn Oanh - Gò Vấp", city: "TP. Hồ Chí Minh", district: "Gò Vấp", stock: "in", address: "144 Nguyễn Oanh, Gò Vấp", phone: "090 551 1144", hours: "09:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/75.png" },
  { qty: 2, name: "Phạm Văn Đồng - Hà Nội", city: "Hà Nội", district: "Bắc Từ Liêm", stock: "low", address: "427 Phạm Văn Đồng, P. Xuân Đỉnh", phone: "1800 9473", hours: "09:00 - 21:00", img: "https://cdn.hstatic.net/files/200001086651/file/75.png" },
];
const STOCK = {
  in: { label: "Còn hàng", color: "#07873c", bg: "color-mix(in srgb, #07c73c 14%, #fff)" },
  low: { label: "Sắp hết", color: "#b45309", bg: "color-mix(in srgb, #f59e0b 20%, #fff)" },
  out: { label: "Hết hàng", color: "var(--muted-foreground)", bg: "var(--secondary)" },
};
const STORE_GEO = {
  "Nguyễn Cơ Thạch": [10.767, 106.722], "Nguyễn Duy Trinh": [10.780, 106.775], "Võ Thị Sáu": [10.786, 106.687],
  "Đặng Văn Bi": [10.848, 106.762], "Nguyễn Thị Thập": [10.740, 106.703], "Hải Thượng Lãn Ông": [10.752, 106.658],
  "Bờ Bao Tân Thắng": [10.801, 106.618], "Tên Lửa - Bình Tân": [10.740, 106.611], "Tô Ký - Hóc Môn": [10.867, 106.606],
  "Emart Gò Vấp": [10.830, 106.687], "Emart Phan Huy Ích": [10.847, 106.638], "Nguyễn Oanh - Gò Vấp": [10.843, 106.678],
  "Phạm Văn Đồng - Hà Nội": [21.077, 105.783],
};
function haversine(a, b, c, d) {
  const R = 6371, r = Math.PI / 180;
  const dLat = (c - a) * r, dLon = (d - b) * r;
  const x = Math.sin(dLat / 2) ** 2 + Math.cos(a * r) * Math.cos(c * r) * Math.sin(dLon / 2) ** 2;
  return R * 2 * Math.atan2(Math.sqrt(x), Math.sqrt(1 - x));
}

function StorePicker({ product }) {
  const [open, setOpen] = React.useState(false);
  const cities = ["Tất cả", ...Array.from(new Set(STORES.map((s) => s.city)))];
  const [city, setCity] = React.useState("Tất cả");
  const [district, setDistrict] = React.useState("Tất cả");
  const [sel, setSel] = React.useState(0);
  const [pos, setPos] = React.useState(null);
  const [locating, setLocating] = React.useState(false);
  const [geoErr, setGeoErr] = React.useState("");
  const locate = () => {
    if (!navigator.geolocation) { setGeoErr("Trình duyệt không hỗ trợ định vị."); return; }
    setLocating(true); setGeoErr("");
    navigator.geolocation.getCurrentPosition(
      (p) => { setPos([p.coords.latitude, p.coords.longitude]); setLocating(false); },
      () => { setGeoErr("Không lấy được vị trí. Vui lòng cho phép truy cập vị trí."); setLocating(false); },
      { enableHighAccuracy: true, timeout: 8000 }
    );
  };
  const districts = city === "Tất cả" ? [] : ["Tất cả", ...Array.from(new Set(STORES.filter((s) => s.city === city).map((s) => s.district)))];
  const chooseCity = (c) => { setCity(c); setDistrict("Tất cả"); };
  let list = STORES.map((s, i) => ({ s, i, dist: pos && STORE_GEO[s.name] ? haversine(pos[0], pos[1], STORE_GEO[s.name][0], STORE_GEO[s.name][1]) : null })).filter(({ s }) => (city === "Tất cả" || s.city === city) && (district === "Tất cả" || s.district === district));
  if (pos) list = list.slice().sort((a, b) => (a.dist ?? 1e9) - (b.dist ?? 1e9));
  const selStore = STORES[sel];
  const selectStyle = { flex: 1, minWidth: 0, appearance: "none", WebkitAppearance: "none", padding: "10px 34px 10px 12px", borderRadius: "var(--radius-md)", border: "1px solid var(--border)", background: "#fff url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23666'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E\") no-repeat right 12px center/12px", fontFamily: "var(--font-sans)", fontSize: 13, color: "var(--foreground)", cursor: "pointer" };
  return (
    <div style={{ paddingTop: 8, marginTop: 4, borderTop: "1px solid var(--border)" }}>
      <span style={{ display: "block", fontSize: 12, fontWeight: 600, color: "var(--muted-foreground)", marginBottom: 8 }}>Chọn cửa hàng nhận xe</span>
      <button onClick={() => setOpen(true)} style={{ width: "100%", display: "flex", alignItems: "center", gap: 10, padding: "11px 14px", borderRadius: "var(--radius-md)", border: "1.5px solid var(--border)", background: "#fff", cursor: "pointer", textAlign: "left" }}>
        <i className="ph ph-storefront" style={{ fontSize: "calc(13px + 5px*var(--ts))", color: "var(--primary)", flexShrink: 0 }} />
        <span style={{ flex: 1, minWidth: 0, fontSize: "calc(13px + 1px*var(--ts))", fontWeight: 600, color: "var(--foreground)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{selStore ? selStore.name : "Chọn cửa hàng"}</span>
        <i className="ph ph-caret-down" style={{ fontSize: "calc(13px + 2px*var(--ts))", color: "var(--muted-foreground)", flexShrink: 0 }} />
      </button>
      {selStore && <span style={{ display: "block", fontSize: 12, color: "var(--muted-foreground)", marginTop: 6, lineHeight: 1.4 }}><i className="ph ph-map-pin" style={{ marginRight: 4 }} />{selStore.address}</span>}
      {open && (
        <div onClick={() => setOpen(false)} style={{ position: "fixed", inset: 0, zIndex: 100, background: "rgba(11,13,18,.5)", display: "flex", alignItems: "center", justifyContent: "center", padding: 20, backdropFilter: "blur(2px)" }}>
          <div onClick={(e) => e.stopPropagation()} style={{ width: "100%", maxWidth: 520, maxHeight: "85vh", display: "flex", flexDirection: "column", background: "#fff", borderRadius: "var(--radius-lg)", overflow: "hidden", boxShadow: "0 24px 60px rgba(0,0,0,.28)" }}>
            <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12, padding: "18px 20px", borderBottom: "1px solid var(--border)" }}>
              <span style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 5px*var(--ts))" }}>Danh sách cửa hàng</span>
              <button onClick={() => setOpen(false)} aria-label="Đóng" style={{ width: 34, height: 34, borderRadius: 5, border: "1px solid var(--border)", background: "#fff", cursor: "pointer", display: "grid", placeItems: "center", color: "var(--foreground)" }}><i className="ph ph-x" /></button>
            </div>
            <div style={{ padding: "16px 20px", display: "flex", flexDirection: "column", gap: 12, borderBottom: "1px solid var(--border)" }}>
              {product && (
                <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
                  {product.image && <img src={product.image} alt="" style={{ width: 44, height: 44, objectFit: "cover", borderRadius: 5, background: "var(--secondary)", flexShrink: 0 }} />}
                  <span style={{ fontSize: "calc(13px + 1px*var(--ts))", fontWeight: 600, color: "var(--foreground)", lineHeight: 1.35 }}>{product.name}</span>
                </div>
              )}
              <div style={{ display: "flex", gap: 10 }}>
                <select value={city} onChange={(e) => chooseCity(e.target.value)} style={selectStyle}>
                  {cities.map((c) => <option key={c} value={c}>{c === "Tất cả" ? "Tỉnh/Thành phố" : c}</option>)}
                </select>
                <select value={district} onChange={(e) => setDistrict(e.target.value)} disabled={!districts.length} style={{ ...selectStyle, opacity: districts.length ? 1 : 0.5, cursor: districts.length ? "pointer" : "not-allowed" }}>
                  {(districts.length ? districts : ["Tất cả"]).map((d) => <option key={d} value={d}>{d === "Tất cả" ? "Quận/Huyện" : d}</option>)}
                </select>
              </div>
              <button onClick={locate} disabled={locating} style={{ alignSelf: "flex-start", display: "inline-flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 5, border: `1px solid ${pos ? "var(--primary)" : "var(--border)"}`, background: pos ? "color-mix(in srgb, var(--primary) 8%, #fff)" : "#fff", color: pos ? "var(--primary)" : "var(--foreground)", fontFamily: "var(--font-sans)", fontSize: 12, fontWeight: 600, cursor: locating ? "default" : "pointer" }}><i className={locating ? "ph ph-circle-notch" : "ph ph-crosshair"} style={{ animation: locating ? "spin 1s linear infinite" : "none" }} />{locating ? "Đang định vị…" : pos ? "Cửa hàng gần bạn" : "Tìm gần tôi"}</button>
              {geoErr && <span style={{ fontSize: 11.5, color: "var(--danger)" }}>{geoErr}</span>}
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 8, overflowY: "auto", padding: "14px 20px 20px" }}>
              {list.map(({ s, i, dist }) => {
                const on = sel === i, out = s.stock === "out", st = STOCK[s.stock];
                return (
                  <button key={i} onClick={() => { if (!out) { setSel(i); setOpen(false); } }} disabled={out} style={{ display: "flex", gap: 12, textAlign: "left", padding: 10, borderRadius: "var(--radius-md)", border: `1.5px solid ${on ? "var(--primary)" : "var(--border)"}`, background: on ? "color-mix(in srgb, var(--primary) 6%, #fff)" : "#fff", cursor: out ? "not-allowed" : "pointer", alignItems: "flex-start", opacity: out ? 0.6 : 1 }}>
                    <img src={s.img} alt="" style={{ width: 56, height: 56, objectFit: "cover", borderRadius: 5, flexShrink: 0, background: "var(--secondary)", filter: out ? "grayscale(1)" : "none" }} />
                    <div style={{ display: "flex", flexDirection: "column", gap: 3, minWidth: 0, flex: 1 }}>
                      <span style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
                        <span style={{ fontSize: 13, fontWeight: 700 }}>{s.name}</span>
                        <span style={{ fontSize: 10.5, fontWeight: 600, padding: "2px 7px", borderRadius: 5, color: st.color, background: st.bg, whiteSpace: "nowrap" }}><i className={out ? "ph ph-x-circle" : "ph-fill ph-circle"} style={{ fontSize: 8, marginRight: 4, verticalAlign: "middle" }} />{out ? st.label : st.label + " · còn " + s.qty + " xe"}</span>
                      </span>
                      <span style={{ fontSize: 12, color: "var(--muted-foreground)", lineHeight: 1.4, textWrap: "pretty" }}>{s.address}</span>
                      <span style={{ fontSize: 11, color: "var(--muted-foreground)", display: "flex", gap: 12, flexWrap: "wrap" }}><span><i className="ph ph-clock" style={{ marginRight: 3 }} />{s.hours}</span><span><i className="ph ph-phone" style={{ marginRight: 3 }} />{s.phone}</span>{dist != null && <span style={{ color: "var(--primary)", fontWeight: 600 }}><i className="ph-fill ph-map-pin" style={{ marginRight: 3 }} />{dist < 10 ? dist.toFixed(1) : Math.round(dist)} km</span>}</span>
                    </div>
                    <span style={{ flexShrink: 0, width: 18, height: 18, borderRadius: 5, border: `1.5px solid ${on ? "var(--primary)" : "var(--border)"}`, display: "grid", placeItems: "center", marginTop: 2 }}>{on && <span style={{ width: 9, height: 9, borderRadius: 5, background: "var(--primary)" }} />}</span>
                  </button>
                );
              })}
              {list.length === 0 && <span style={{ fontSize: 13, color: "var(--muted-foreground)", padding: "8px 2px" }}>Không có cửa hàng phù hợp.</span>}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function AddonSelect({ options }) {
  return (
    <div style={{ position: "relative", display: "flex", flex: 1, minWidth: 0 }} onClick={(e) => e.stopPropagation()}>
      <select onClick={(e) => e.stopPropagation()} style={{ appearance: "none", WebkitAppearance: "none", padding: "5px 20px 5px 9px", border: "1px solid var(--border)", borderRadius: 5, background: "#fff", fontFamily: "var(--font-sans)", fontSize: 11, color: "var(--foreground)", cursor: "pointer", minWidth: 52, width: "100%" }}>
        {options.map((o) => <option key={o}>{o}</option>)}
      </select>
      <i className="ph ph-caret-down" style={{ position: "absolute", right: 8, top: "50%", transform: "translateY(-50%)", fontSize: 9, pointerEvents: "none", color: "var(--muted-foreground)" }} />
    </div>
  );
}

function AddonOption({ item, selected, onSelect, priceLabel, basis = "calc(50% - 6px)", bordered, multi }) {
  return (
    <div onClick={onSelect} style={{ display: "flex", alignItems: "center", gap: 8, cursor: "pointer", flex: `0 0 ${basis}`, minWidth: 0, boxSizing: "border-box", ...(bordered ? { padding: 12, borderRadius: "var(--radius-md)", border: `1.5px solid ${selected ? "var(--primary)" : "var(--border)"}`, background: selected ? "color-mix(in srgb, var(--primary) 5%, #fff)" : "#fff" } : {}) }}>
      <span style={{ flexShrink: 0, width: 18, height: 18, borderRadius: 5, border: `2px solid ${selected ? (multi ? "#16a34a" : "var(--primary)") : "var(--border)"}`, display: "grid", placeItems: "center", background: "#fff", overflow: "visible", position: "relative" }}>
        {selected && (multi ? <i className="ph-fill ph-check" style={{ fontSize: "calc(13px + 3px*var(--ts))", color: "#16a34a", position: "absolute", left: "50%", top: "45%", transform: "translate(-50%,-50%)", lineHeight: 1 }} /> : <span style={{ width: 9, height: 9, borderRadius: 5, background: "var(--primary)" }} />)}
      </span>
      <img src={item.img} alt={item.name} style={{ flexShrink: 0, width: 56, height: 56, objectFit: "contain", mixBlendMode: "multiply" }} />
      <div style={{ display: "flex", flexDirection: "column", gap: 5, minWidth: 0, flex: 1 }}>
        <span style={{ fontSize: 12, fontWeight: 500 }}>{item.name}</span>
        <div style={{ display: "flex", gap: 6 }}>
          <AddonSelect options={item.colors} />
          <AddonSelect options={item.sizes} />
        </div>
        <div style={{ display: "flex", alignItems: "baseline", gap: 5, marginTop: 1, flexWrap: "wrap" }}>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, fontWeight: 700, color: multi ? "#dc2626" : "inherit" }}>{priceLabel(item.price)}</span>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--muted-foreground)", textDecoration: "line-through" }}>{dong(item.original)}</span>
        </div>
      </div>
    </div>
  );
}

function AddonCard({ title, items, priceLabel, required, per = 2, basis, bordered, multi }) {
  const [sel, setSel] = React.useState(required ? 0 : -1);
  const [picked, setPicked] = React.useState(() => new Set());
  const [page, setPage] = React.useState(0);
  const pages = Math.ceil(items.length / per);
  const shown = items.map((it, i) => ({ it, i })).slice(page * per, page * per + per);
  const toggle = (i) => setPicked((s) => { const n = new Set(s); n.has(i) ? n.delete(i) : n.add(i); return n; });
  const allPicked = multi && items.length > 0 && picked.size === items.length;
  const toggleAll = () => setPicked(allPicked ? new Set() : new Set(items.map((_, i) => i)));
  return (
    <div style={{ border: "1px solid var(--border)", borderRadius: "var(--radius-md)", overflow: "hidden" }}>
      <div style={{ padding: "10px 16px", background: "var(--muted, #c7ccd0)", color: "var(--foreground)", fontSize: "calc(13px + 2px*var(--ts))", fontWeight: 700, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 }}>
        <span>{title}</span>
        {multi && (
          <button onClick={toggleAll} style={{ flexShrink: 0, display: "inline-flex", alignItems: "center", gap: 6, height: 28, padding: "0 12px", borderRadius: "var(--radius-pill)", border: "1px solid var(--border)", background: allPicked ? "var(--primary)" : "#fff", color: allPicked ? "var(--primary-foreground)" : "var(--foreground)", fontSize: 12.5, fontWeight: 600, cursor: "pointer" }}>
            <i className={allPicked ? "ph-fill ph-check-square" : "ph ph-check-square"} style={{ fontSize: "calc(13px + 2px*var(--ts))" }} />
            {allPicked ? "Bỏ chọn tất cả" : "Chọn tất cả"}
          </button>
        )}
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "16px 10px" }}>
        {pages > 1 && page > 0 && (
          <button onClick={() => setPage((p) => Math.max(0, p - 1))} aria-label="Trước" style={{ flexShrink: 0, width: 26, height: 26, borderRadius: 5, border: "1px solid var(--border)", background: "#fff", cursor: "pointer", display: "grid", placeItems: "center", color: "var(--foreground)" }}><i className="ph ph-caret-left" style={{ fontSize: 13 }} /></button>
        )}
        <div style={{ display: "flex", gap: 12, flex: 1, minWidth: 0 }}>
          {shown.map(({ it, i }) => (
            <AddonOption key={i} item={it} selected={multi ? picked.has(i) : sel === i} onSelect={() => multi ? toggle(i) : setSel(required && sel === i ? i : (sel === i ? -1 : i))} priceLabel={priceLabel} basis={basis} bordered={bordered} multi={multi} />
          ))}
        </div>
        {pages > 1 && (
          <button onClick={() => setPage((p) => Math.min(pages - 1, p + 1))} disabled={page === pages - 1} aria-label="Tiếp" style={{ flexShrink: 0, width: 26, height: 26, borderRadius: 5, border: "1px solid var(--border)", background: "#fff", cursor: page === pages - 1 ? "default" : "pointer", opacity: page === pages - 1 ? 0.3 : 1, display: "grid", placeItems: "center", color: "var(--foreground)" }}><i className="ph ph-caret-right" style={{ fontSize: 13 }} /></button>
        )}
      </div>
    </div>
  );
}

function ComboSection() {
  return (
    <div>
      <h2 style={{ margin: "0 0 20px", fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 11px*var(--ts))" }}>Giảm giá khi mua kèm</h2>
      <AddonCard title="Chọn phụ kiện mua kèm để nhận ưu đãi" items={COMBO_ITEMS} priceLabel={vnd} per={4} basis="calc(25% - 9px)" bordered multi />
    </div>
  );
}

const COLOR_NAMES = { "#142ff7": "Xanh dương", "#333333": "Đen", "#000000": "Đen", "#07c73c": "Xanh lá", "#b91c1c": "Đỏ", "#ffffff": "Trắng", "#e5e7eb": "Bạc", "#f5a623": "Cam", "#7c3aed": "Tím", "#facc15": "Vàng" };
function colorName(hex) { return COLOR_NAMES[(hex || "").toLowerCase()] || "Tùy chọn"; }
function BuyBox({ product, onAdd }) {
  const cmp = useCompareState();
  const inCmp = cmp.has(product.slug);
  const colors = product.colors || ["#142ff7", "#333333", "#07c73c", "#b91c1c"];
  const sizes = ["XS", "S", "M", "L", "XL"];
  const [ci, setCi] = React.useState(0);
  const [si, setSi] = React.useState(2);
  const [ship, setShip] = React.useState(0);
  const [added, setAdded] = React.useState(false);
  const [instOpen, setInstOpen] = React.useState(false);
  const [warOpen, setWarOpen] = React.useState(false);
  const [sizeOpen, setSizeOpen] = React.useState(false);
  const handleAdd = () => { onAdd(product); setAdded(true); clearTimeout(handleAdd._t); handleAdd._t = setTimeout(() => setAdded(false), 1700); };

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
      <div>
        <h1 style={{ margin: "0", fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 13px*var(--ts))", letterSpacing: "-0.01em", lineHeight: 1.2 }}>{product.name}</h1>
        <div style={{ display: "flex", flexWrap: "wrap", gap: "8px 24px", marginTop: 8, fontSize: 12, fontWeight: 500, textTransform: "uppercase", letterSpacing: ".05em", color: "var(--muted-foreground)" }}>
          <span>Thương hiệu: {brandOf(product)}</span>
          <span>Xuất xứ: {product.origin || "Đài Loan"}</span>
        </div>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
        <div style={{ display: "flex", alignItems: "baseline", gap: 12 }}>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: "calc(13px + 17px*var(--ts))", fontWeight: 600, color: "var(--danger)" }}>{vnd(product.price)}</span>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: "calc(13px + 3px*var(--ts))", color: "var(--muted-foreground)", textDecoration: "line-through" }}>{vnd(product.originalPrice)}</span>
        </div>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontSize: 13, fontWeight: 500, color: "var(--foreground)" }}>Flash sale · kết thúc trong <Countdown /></span>
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 16, paddingBottom: 20, borderBottom: "1px solid var(--border)" }}>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontSize: "calc(13px + 1px*var(--ts))" }}><i className="ph ph-star" style={{ color: "var(--foreground)", fontSize: "calc(13px + 3px*var(--ts))" }} /><span style={{ fontWeight: 700, color: "var(--foreground)" }}>5.0</span><span style={{ color: "var(--muted-foreground)" }}>(288 đánh giá)</span></span>
        <button style={{ display: "inline-flex", alignItems: "center", gap: 6, border: "none", background: "none", cursor: "pointer", fontSize: 13, color: "var(--muted-foreground)" }}><i className="ph ph-heart" /> Lưu lại</button>
        <button style={{ display: "inline-flex", alignItems: "center", gap: 6, border: "none", background: "none", cursor: "pointer", fontSize: 13, color: "var(--muted-foreground)" }}><i className="ph ph-share-network" /> Chia sẻ</button>
      </div>

      <div>
        <div style={{ marginBottom: 10, fontSize: 13, fontWeight: 600 }}>Màu sắc: <span style={{ fontWeight: 500, color: "var(--muted-foreground)" }}>{colorName(colors[ci])}</span></div>
        <ColorSwatches colors={colors} value={ci} onChange={setCi} size={32} />
      </div>

      <div>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 10 }}>
          <span style={{ fontSize: 13, fontWeight: 600 }}>Kích thước</span>
          <button onClick={() => setSizeOpen(true)} style={{ display: "inline-flex", alignItems: "center", gap: 5, padding: 0, border: "none", background: "none", cursor: "pointer", fontFamily: "var(--font-sans)", fontSize: 12, color: "var(--primary)", textDecoration: "underline", textUnderlineOffset: 3 }}><i className="ph ph-ruler" style={{ fontSize: "calc(13px + 1px*var(--ts))" }} />Hướng dẫn chọn size</button>
        </div>
        <div style={{ display: "flex", gap: 10 }}>
          {sizes.map((s, i) => (
            <button key={s} onClick={() => setSi(i)} style={{ minWidth: 48, height: 44, padding: "0 14px", borderRadius: "var(--radius-md)", border: `1.5px solid ${i === si ? "var(--primary)" : "var(--border)"}`, background: i === si ? "var(--primary)" : "#fff", color: i === si ? "#fff" : "var(--foreground)", fontFamily: "var(--font-sans)", fontSize: "calc(13px + 1px*var(--ts))", fontWeight: 600, cursor: "pointer" }}>{s}</button>
          ))}
        </div>
      </div>

      <AddonCard title="Quà tặng khi mua xe" items={GIFT_ITEMS} priceLabel={dong} required />

      <div style={{ display: "flex", flexDirection: "column", gap: 12, padding: 16, borderRadius: "var(--radius-md)", background: "var(--secondary)" }}>
        <span style={{ fontSize: 13, fontWeight: 600 }}>Hình thức mua hàng</span>
        {["Giao hàng tận nơi · 2-4 giờ nội thành", "Nhận tại cửa hàng · miễn phí"].map((t, i) => (
          <label key={i} style={{ display: "flex", alignItems: "center", gap: 10, fontSize: "calc(13px + 1px*var(--ts))", cursor: "pointer" }}>
            <input type="radio" name="ship" checked={ship === i} onChange={() => setShip(i)} style={{ accentColor: "var(--primary)", width: 16, height: 16 }} />
            {t}
          </label>
        ))}
        <div style={{ overflow: "hidden", maxHeight: ship === 1 ? 240 : 0, opacity: ship === 1 ? 1 : 0, transition: "max-height .45s cubic-bezier(.22,.61,.36,1), opacity .3s ease" }}>
          <StorePicker product={product} />
        </div>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "minmax(0,0.8fr) minmax(0,1.6fr) minmax(0,1fr)", gap: 12, alignItems: "stretch" }}>
        <Button size="lg" variant="outline" style={{ boxShadow: "none", height: "100%", minHeight: 62, background: "#fff", borderColor: "var(--primary)", color: "var(--primary)" }} onClick={() => setInstOpen(true)}>Trả góp 0%</Button>
        <Button size="lg" style={{ boxShadow: "none", background: "#d4150a", borderColor: "#d4150a", height: "100%", minHeight: 62, display: "flex", flexDirection: "column", gap: 2, lineHeight: 1.2 }} onClick={handleAdd}><span style={{ fontSize: "calc(13px + 4px*var(--ts))", fontWeight: 800, textTransform: "uppercase" }}>Mua ngay</span><span style={{ fontSize: 12, fontWeight: 500, opacity: .9 }}>Giao nhanh từ 2 giờ hoặc nhận tại cửa hàng</span></Button>
        <Button size="lg" style={{ boxShadow: "none", height: "100%", minHeight: 62, transition: "transform .18s cubic-bezier(.34,1.56,.64,1), background .2s", transform: added ? "scale(1.03)" : "none", ...(added ? { background: "#07c73c", borderColor: "#07c73c" } : {}) }} onClick={handleAdd}>{added ? "Đã thêm" : "Thêm vào giỏ"}</Button>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, paddingTop: 4 }}>
        <button onClick={() => setWarOpen(true)} style={{ display: "flex", alignItems: "center", gap: 8, color: "var(--muted-foreground)", background: "none", border: "none", padding: 0, font: "inherit", fontSize: 13, cursor: "pointer", textAlign: "left" }}><i className="ph ph-shield-check" style={{ color: "var(--primary)", fontSize: "calc(13px + 3px*var(--ts))" }} /><span style={{ textDecoration: "underline", textUnderlineOffset: 3, textDecorationColor: "var(--border)" }}>Bảo hành chính hãng 24 tháng</span></button>
        {[["truck", "Miễn phí giao hàng"], ["arrow-counter-clockwise", "Đổi trả trong 7 ngày"], ["wrench", "Miễn phí bảo dưỡng"]].map(([ic, t]) => (
          <span key={t} style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "var(--muted-foreground)" }}><i className={`ph ph-${ic}`} style={{ color: "var(--primary)", fontSize: "calc(13px + 3px*var(--ts))" }} /> {t}</span>
        ))}
      </div>

      <img src="https://api.xedap.vn/wp-content/uploads/2023/09/image-slider-right-1.jpg" alt="Banner khuyến mãi" style={{ display: "block", width: "100%", aspectRatio: "1/1", objectFit: "cover", borderRadius: "var(--radius-md)", marginTop: 4 }} />
      <InstallmentModal open={instOpen} onClose={() => setInstOpen(false)} product={product} />
      <WarrantyModal open={warOpen} onClose={() => setWarOpen(false)} product={product} />
      <SizeGuideModal open={sizeOpen} onClose={() => setSizeOpen(false)} current={sizes[si]} />
    </div>
  );
}

/* ---------- Features + Specs ---------- */
const FEATURES = [
  { img: "https://cdn.hstatic.net/files/200001086651/file/tinh_nang_1.png", title: "Khung thép cứng cáp, bền bỉ", body: "Khung xe được chế tạo bằng thép Raptor STL chắc chắn, chịu lực tốt, mang lại sự ổn định tốt mỗi khi di chuyển cho dù ở bất kì địa hình nào." },
  { img: "https://cdn.hstatic.net/files/200001086651/file/tinh_nang_2.png", title: "Phuộc nhún 100mm ổn định", body: "Trang bị phuộc trước Raptor STL với hành trình 100mm giúp xe hấp thụ chấn động hiệu quả và đem lại sự thoải mái khi di chuyển cho người đạp." },
  { img: "https://cdn.hstatic.net/files/200001086651/file/tinh_nang_3.png", title: "Hệ truyền động 21 tốc độ linh hoạt", body: "Tay đề 21 tốc độ với bộ chuyển líp 7 tầng và gạt đĩa 3 tầng, Rally 1B mang đến dải số 3x7 linh hoạt. Người lái có thể dễ dàng chuyển đổi giữa nhiều địa hình từ phố xá bằng phẳng đến những con dốc nhẹ." },
  { img: "https://cdn.hstatic.net/files/200001086651/file/tinh_nang_1.png", title: "Phanh đĩa cơ – kiểm soát an toàn", body: "Hệ thống phanh đĩa cơ mang lại lực phanh ổn định, dễ dàng kiểm soát tốc độ trong cả môi trường đô thị đông đúc và những chuyến đi trên địa hình phức tạp." },
];
function FeatureGrid() {
  return (
    <div>
      <h2 style={{ margin: "0 0 24px", fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 11px*var(--ts))" }}>Các tính năng chính</h2>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 32 }}>
        {FEATURES.map((f, k) => (
          <Reveal key={f.title} delay={(k % 2) * 90}>
          <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
            <div style={{ aspectRatio: "4/3", overflow: "hidden", background: "var(--secondary)" }}>
              <img src={f.img} alt={f.title} style={{ width: "100%", height: "100%", objectFit: "cover" }} />
            </div>
            <h3 style={{ margin: 0, fontSize: "calc(13px + 4px*var(--ts))", fontWeight: 700 }}>{f.title}</h3>
            <p style={{ margin: 0, fontSize: "calc(13px + 1px*var(--ts))", lineHeight: 1.6, color: "var(--muted-foreground)", textWrap: "pretty" }}>{f.body}</p>
          </div>
          </Reveal>
        ))}
      </div>
    </div>
  );
}

const SPEC_GROUPS = [
  { group: "Khung & phuộc", rows: [["Chất liệu khung", "Hợp kim nhôm 6061"], ["Phuộc trước", "Hành trình 100mm, có khóa"], ["Cỡ bánh", "24 inch"], ["Kích cỡ khung", "S / M / L"], ["Trọng lượng", "13.8 kg"]] },
  { group: "Truyền động", rows: [["Bộ đề", "Shimano Altus"], ["Tay đề", "Shimano EF500"], ["Số tốc độ", "24 tốc độ"], ["Bộ đùi đĩa", "Prowheel 3 tầng"], ["Xích", "KMC Z7"]] },
  { group: "Bánh & phanh", rows: [["Vành", "AlexRims MD25, hợp kim nhôm"], ["Moay ơ trước", "Shimano MT400"], ["Phanh", "Đĩa thủy lực"], ["Lốp", "Kenda 24×2.10"], ["Nan hoa", "Thép mạ inox"]] },
  { group: "Tiện ích & bảo hành", rows: [["Yên xe", "Velo thể thao"], ["Phụ kiện kèm", "Chắn bùn, chân chống"], ["Bảo hành khung", "5 năm"], ["Bảo hành linh kiện", "12 tháng"], ["Xuất xứ", "Chính hãng RAPTOR"]] },
];
function SpecTable({ product }) {
  const cmp = useCompareState();
  const inCmp = product ? cmp.has(product.slug) : false;
  return (
    <div>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, margin: "0 0 24px" }}>
        <h2 style={{ margin: 0, fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 11px*var(--ts))" }}>Thông số kỹ thuật</h2>
        <button onClick={() => product && cmp.toggle(product)} title={inCmp ? "Bỏ xe này khỏi danh sách so sánh" : "Thêm xe này vào danh sách so sánh để đối chiếu thông số với xe khác"} style={{ display: "inline-flex", alignItems: "center", justifyContent: "center", height: 40, padding: "0 20px", borderRadius: 999, border: inCmp ? "1px solid var(--primary)" : "1px solid var(--primary)", background: inCmp ? "var(--primary)" : "#fff", cursor: "pointer", fontFamily: "inherit", fontSize: "calc(13px + 1px*var(--ts))", fontWeight: 700, letterSpacing: ".01em", color: inCmp ? "#fff" : "var(--primary)", whiteSpace: "nowrap" }}>{inCmp ? "Đang so sánh" : "So sánh"}</button>
      </div>
      <div style={{ border: "1px solid var(--border)", borderRadius: "var(--radius-lg)", overflow: "hidden" }}>
        {SPEC_GROUPS.map((g) => (
          <div key={g.group}>
            <div style={{ padding: "10px 16px", background: "var(--secondary)", fontSize: 13, fontWeight: 700 }}>{g.group}</div>
            {g.rows.map(([k, v], i) => (
              <div key={k} style={{ display: "flex", justifyContent: "space-between", gap: 16, padding: "12px 16px", borderTop: "1px solid var(--border)" }}>
                <span style={{ fontSize: "calc(13px + 1px*var(--ts))", color: "var(--muted-foreground)" }}>{k}</span>
                <span style={{ fontSize: "calc(13px + 1px*var(--ts))", fontWeight: 500, textAlign: "right" }}>{v}</span>
              </div>
            ))}
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---------- Story block ---------- */
function StoryBlock() {
  const [open, setOpen] = React.useState(false);
  return (
    <div style={{ marginTop: 56 }}>
      <h2 style={{ margin: "0 0 20px", maxWidth: 760, fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 17px*var(--ts))", letterSpacing: "-0.02em", lineHeight: 1.25, textWrap: "balance" }}>Những chuyến phiêu lưu đòi hỏi nhiều hơn. Chiếc Rally 1B đáp ứng được điều đó.</h2>
      <p style={{ margin: 0, maxWidth: 760, fontSize: "calc(13px + 3px*var(--ts))", lineHeight: 1.7, color: "var(--muted-foreground)", textWrap: "pretty" }}>
        Dành cho những ai nghe thấy tiếng gọi của thiên nhiên hoang dã. RAPTOR Rally 1B là người bạn đồng hành đưa bạn vượt ra khỏi những con đường trải nhựa — nơi những khu rừng thâm u, chân trời trải dài và con dốc trở thành ký ức.{open && " Đi sâu hơn vào thiên nhiên và xa hơn bao giờ hết. Hãy để sức mạnh, sự thoải mái và khả năng vượt địa hình của Rally 1B đưa những vùng đất chưa được khám phá đến gần bạn hơn — từ những buổi sáng sương mù trên đỉnh đồi đến hoàng hôn rực rỡ bên bờ suối."}
      </p>
      <Button variant="outline" style={{ marginTop: 20 }} onClick={() => setOpen((o) => !o)}>{open ? "Thu gọn" : "Xem thêm"}</Button>
    </div>
  );
}

/* ---------- Reviews ---------- */
const DIST = [["5 sao", 51], ["4 sao", 9], ["3 sao", 6], ["2 sao", 5], ["1 sao", 11]];
const REVIEWS = [
  { name: "Nguyễn Minh Tuấn", stars: 5, text: "Xe giao nhanh, đóng gói kỹ. Đạp thử quanh khu đô thị thấy sang số rất ngọt, khung nhôm nhẹ nên bê lên tầng gửi xe cũng dễ. Rất đáng tiền trong tầm giá này.", helpful: 26, used: "Đã dùng khoảng 3 ngày", photos: true, time: "2 ngày trước", replies: [{ admin: true, name: "Quản Trị Viên", time: "2 ngày trước", lines: ["Chào anh Tuấn,", "Dạ Xedap.vn cảm ơn anh đã tin tưởng đặt xe tại hệ thống ạ.", "Xe hiện đang có ưu đãi tặng kèm bộ phụ kiện (mũ bảo hiểm + khoá cáp) khi mua online.", "Anh nhắn tin cho em để em kiểm tra thêm chương trình bảo dưỡng miễn phí 3 lần đầu nhé.", "Cảm ơn anh đã quan tâm đến Xedap.vn."] }] },
  { name: "Trần Thị Thu Hà", stars: 5, text: "Mình mua cho con gái đi học, yên rất êm và phanh đĩa ăn. Nhân viên tư vấn size nhiệt tình, lắp ráp sẵn giao tận nhà. Cả nhà hài lòng.", helpful: 15, used: "Đã dùng khoảng 2 tuần", note: "Bộ phận chăm sóc khách hàng đã liên hệ cảm ơn ngày 12/02/2026" },
  { name: "Lê Hoàng Nam", stars: 4, text: "Đạp đường đèo cuối tuần rất đã, phuộc ăn sóc tốt. Trừ một ít là lốp zin hơi trơn khi qua đường ướt, còn lại ổn áp trong tầm giá.", helpful: 33, used: "Đã dùng khoảng 1 tháng" },
  { name: "Trương Thúy Dương", stars: 2, text: "Giao xe bị trễ 3 ngày so với hẹn, gọi tổng đài thì máy bận liên tục. Xe dùng ổn nhưng khâu giao hàng và chăm sóc cần cải thiện nhiều. Mong shop rút kinh nghiệm cho các đơn sau.", helpful: 44, used: "Đã dùng khoảng 1 tháng", note: "Đánh giá này đã được chuyển tới bộ phận hỗ trợ", time: "5 ngày trước", replies: [{ admin: true, name: "Quản Trị Viên", time: "4 ngày trước", lines: ["Chào chị Dương,", "Dạ Xedap.vn thành thật xin lỗi vì đơn hàng của chị bị trễ so với lịch hẹn ạ.", "Em đã chuyển phản ánh tới bộ phận vận hành kho Bình Thạnh để rà soát lại quy trình giao xe.", "Chị cho em xin mã đơn hàng qua tin nhắn để em hỗ trợ bù phiếu bảo dưỡng miễn phí 1 năm ạ.", "Cảm ơn chị đã góp ý để Xedap.vn phục vụ tốt hơn."] }] },
  { name: "Phạm Quốc Đạt", stars: 5, text: "Chiếc thứ hai mình mua ở Xedap.vn rồi. Chất lượng hoàn thiện tốt, mối hàn đẹp, bảo hành rõ ràng. Sẽ giới thiệu bạn bè ủng hộ shop.", helpful: 27, used: "Đã dùng khoảng 1 tuần", photos: true },
];
function ReviewReply({ r }) {
  return (
    <div style={{ display: "flex", gap: 12, paddingTop: 16 }}>
      {r.admin ? (
        <img src="https://cdn.hstatic.net/files/200001188264/file/channels4_profile.jpg" alt="Xedap.vn" style={{ width: 36, height: 36, flexShrink: 0, borderRadius: "50%", objectFit: "cover", display: "block" }} />
      ) : (
        <span style={{ width: 36, height: 36, flexShrink: 0, borderRadius: "50%", background: "var(--secondary)", color: "var(--foreground)", display: "grid", placeItems: "center", fontWeight: 800, fontSize: "calc(13px + 2px*var(--ts))" }}>{r.name.trim().slice(0, 1)}</span>
      )}
      <div style={{ display: "flex", flexDirection: "column", gap: 8, minWidth: 0 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
          <span style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 2px*var(--ts))" }}>{r.name}</span>
          {r.admin && <span style={{ fontSize: 10, fontWeight: 800, letterSpacing: ".04em", padding: "2px 6px", borderRadius: 4, background: "var(--primary)", color: "var(--primary-foreground)" }}>QTV</span>}
          <span style={{ display: "inline-flex", alignItems: "center", gap: 4, fontSize: 12, color: "var(--muted-foreground)" }}><i className="ph ph-clock" style={{ fontSize: 13 }} />{r.time}</span>
        </div>
        <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
          {r.lines.map((l, i) => <p key={i} style={{ margin: 0, fontSize: "calc(13px + 1px*var(--ts))", lineHeight: 1.6, textWrap: "pretty" }}>{l}</p>)}
        </div>
      </div>
    </div>
  );
}
function ReviewReplyForm({ to, onCancel, onSend }) {
  const [text, setText] = React.useState("");
  const ref = React.useRef(null);
  React.useEffect(() => { ref.current && ref.current.focus(); }, []);
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10, marginTop: 14, padding: 14, borderRadius: "var(--radius-md)", background: "color-mix(in srgb, var(--secondary) 55%, #fff)", border: "1px solid var(--border)" }}>
      <span style={{ fontSize: 13, color: "var(--muted-foreground)" }}>Đang phản hồi <strong style={{ color: "var(--foreground)" }}>{to}</strong></span>
      <textarea ref={ref} rows={3} value={text} onChange={(e) => setText(e.target.value)} placeholder="Nhập nội dung phản hồi…" style={{ width: "100%", boxSizing: "border-box", resize: "vertical", padding: "10px 12px", borderRadius: "var(--radius-sm)", border: "1px solid var(--border)", fontFamily: "var(--font-sans)", fontSize: "calc(13px + 1px*var(--ts))", lineHeight: 1.6, background: "#fff", color: "var(--foreground)" }} />
      <div style={{ display: "flex", gap: 10, justifyContent: "flex-end" }}>
        <Button variant="outline" onClick={onCancel} style={{ boxShadow: "none", padding: "8px 16px", fontSize: 13 }}>Huỷ</Button>
        <Button disabled={!text.trim()} onClick={() => onSend(text.trim())} style={{ boxShadow: "none", padding: "8px 16px", fontSize: 13, opacity: text.trim() ? 1 : 0.5 }}><i className="ph ph-paper-plane-tilt" style={{ marginRight: 6 }} />Gửi phản hồi</Button>
      </div>
    </div>
  );
}
function ReviewReplyButton({ onClick }) {
  return <button onClick={onClick} style={{ alignSelf: "flex-start", display: "inline-flex", alignItems: "center", gap: 6, border: "none", background: "none", padding: 0, cursor: "pointer", fontFamily: "var(--font-sans)", fontSize: "calc(13px + 1px*var(--ts))", fontWeight: 700, color: "var(--primary)" }}><i className="ph-fill ph-chat-teardrop-text" style={{ fontSize: "calc(13px + 3px*var(--ts))" }} />Phản hồi</button>;
}
function Stars({ n }) {
  return <span style={{ display: "inline-flex", gap: 2 }}>{Array.from({ length: 5 }).map((_, i) => <i key={i} className={i < n ? "ph-fill ph-star" : "ph ph-star"} style={{ fontSize: "calc(13px + 1px*var(--ts))", color: "var(--warning)" }} />)}</span>;
}
function ReviewFormModal({ product, onClose }) {
  const [stars, setStars] = React.useState(5);
  const [hover, setHover] = React.useState(0);
  const [form, setForm] = React.useState({ name: "", email: "", phone: "", text: "" });
  const [files, setFiles] = React.useState([]);
  const [drag, setDrag] = React.useState(false);
  const [sent, setSent] = React.useState(false);
  const [errs, setErrs] = React.useState({});
  const inputRef = React.useRef(null);
  React.useEffect(() => { const k = (e) => e.key === "Escape" && onClose(); window.addEventListener("keydown", k); return () => window.removeEventListener("keydown", k); }, [onClose]);
  React.useEffect(() => () => files.forEach((f) => URL.revokeObjectURL(f.url)), []);
  const set = (k) => (e) => { setForm((f) => ({ ...f, [k]: e.target.value })); setErrs((s) => ({ ...s, [k]: null })); };
  const addFiles = (list) => { const next = Array.from(list).filter((f) => f.type.startsWith("image/")).slice(0, 5 - files.length).map((f) => ({ file: f, url: URL.createObjectURL(f), name: f.name, size: f.size })); setFiles((p) => [...p, ...next]); };
  const removeFile = (i) => setFiles((p) => { URL.revokeObjectURL(p[i].url); return p.filter((_, j) => j !== i); });
  const submit = (e) => {
    e.preventDefault();
    const next = {};
    if (!form.name.trim()) next.name = "Vui lòng nhập họ tên";
    if (!/^\S+@\S+\.\S+$/.test(form.email.trim())) next.email = "Email chưa hợp lệ";
    if (!/^0\d{9}$/.test(form.phone.replace(/\D/g, ""))) next.phone = "Số điện thoại 10 số, bắt đầu bằng 0";
    if (form.text.trim().length < 20) next.text = "Đánh giá tối thiểu 20 ký tự";
    setErrs(next);
    if (!Object.keys(next).length) setSent(true);
  };
  const label = { fontSize: 13, fontWeight: 700, marginBottom: 6, display: "block" };
  const field = (bad) => ({ width: "100%", padding: "11px 13px", fontSize: "calc(13px + 1px*var(--ts))", fontFamily: "var(--font-sans)", color: "var(--foreground)", background: "#fff", border: `1px solid ${bad ? "var(--destructive, #d92d20)" : "var(--border)"}`, borderRadius: "var(--radius-md)", outline: "none", boxSizing: "border-box" });
  const errText = (m) => m ? <div style={{ marginTop: 5, fontSize: 12, color: "var(--destructive, #d92d20)", display: "flex", alignItems: "center", gap: 5 }}><i className="ph-fill ph-warning-circle" style={{ fontSize: "calc(13px + 1px*var(--ts))" }} />{m}</div> : null;
  return (
    <div onMouseDown={(e) => e.target === e.currentTarget && onClose()} style={{ position: "fixed", inset: 0, zIndex: 120, background: "rgba(15,18,20,.55)", display: "grid", placeItems: "center", padding: 20, overflowY: "auto" }}>
      <div role="dialog" aria-modal="true" style={{ width: "min(560px, 100%)", background: "#fff", borderRadius: "var(--radius-lg, 10px)", border: "1px solid var(--border)", boxShadow: "0 24px 60px rgba(0,0,0,.28)", overflow: "hidden", maxHeight: "92vh", display: "flex", flexDirection: "column" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 12, padding: "18px 20px", borderBottom: "1px solid var(--border)" }}>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 4px*var(--ts))" }}>Viết đánh giá</div>
            <div style={{ fontSize: 13, color: "var(--muted-foreground)", marginTop: 2, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{product && product.name}</div>
          </div>
          <button onClick={onClose} aria-label="Đóng" style={{ width: 36, height: 36, display: "grid", placeItems: "center", border: "1px solid var(--border)", borderRadius: "var(--radius-md)", background: "#fff", cursor: "pointer", color: "var(--foreground)", fontSize: "calc(13px + 5px*var(--ts))" }}><i className="ph ph-x" /></button>
        </div>
        {sent ? (
          <div style={{ padding: "40px 28px", textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }}>
            <span style={{ width: 62, height: 62, borderRadius: "50%", background: "color-mix(in srgb, var(--primary) 12%, #fff)", color: "var(--primary)", display: "grid", placeItems: "center", fontSize: "calc(13px + 19px*var(--ts))" }}><i className="ph-fill ph-check-circle" /></span>
            <div style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 5px*var(--ts))" }}>Cảm ơn bạn đã đánh giá!</div>
            <p style={{ margin: 0, fontSize: "calc(13px + 1px*var(--ts))", lineHeight: 1.6, color: "var(--muted-foreground)", maxWidth: 380, textWrap: "pretty" }}>Đánh giá {stars} sao{files.length ? ` kèm ${files.length} ảnh` : ""} đã được gửi. Xedap.vn sẽ duyệt trong 24 giờ và gửi thông báo tới {form.email}.</p>
            <Button onClick={onClose} style={{ marginTop: 8, minWidth: 160, boxShadow: "none" }}>Đóng</Button>
          </div>
        ) : (
          <form onSubmit={submit} style={{ padding: 20, display: "flex", flexDirection: "column", gap: 16, overflowY: "auto" }}>
            <div>
              <span style={label}>Mức độ hài lòng</span>
              <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                <div style={{ display: "flex", gap: 4 }} onMouseLeave={() => setHover(0)}>
                  {[1, 2, 3, 4, 5].map((n) => (
                    <button key={n} type="button" onClick={() => setStars(n)} onMouseEnter={() => setHover(n)} aria-label={`${n} sao`} style={{ border: 0, background: "none", padding: 0, cursor: "pointer", fontSize: "calc(13px + 15px*var(--ts))", lineHeight: 1, color: n <= (hover || stars) ? "var(--warning)" : "var(--border)" }}><i className={n <= (hover || stars) ? "ph-fill ph-star" : "ph ph-star"} /></button>
                  ))}
                </div>
                <span style={{ fontSize: 13, color: "var(--muted-foreground)" }}>{["Rất tệ", "Không hài lòng", "Bình thường", "Hài lòng", "Tuyệt vời"][(hover || stars) - 1]}</span>
              </div>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
              <div>
                <label style={label} htmlFor="rv-email">Email <span style={{ color: "var(--destructive, #d92d20)" }}>*</span></label>
                <input id="rv-email" type="email" value={form.email} onChange={set("email")} placeholder="ban@email.com" style={field(errs.email)} />
                {errText(errs.email)}
              </div>
              <div>
                <label style={label} htmlFor="rv-phone">Số điện thoại <span style={{ color: "var(--destructive, #d92d20)" }}>*</span></label>
                <input id="rv-phone" type="tel" inputMode="numeric" value={form.phone} onChange={set("phone")} placeholder="09xx xxx xxx" style={field(errs.phone)} />
                {errText(errs.phone)}
              </div>
            </div>
            <div>
              <label style={label} htmlFor="rv-name">Họ tên hiển thị <span style={{ color: "var(--destructive, #d92d20)" }}>*</span></label>
              <input id="rv-name" value={form.name} onChange={set("name")} placeholder="Nguyễn Văn A" style={field(errs.name)} />
              {errText(errs.name)}
            </div>
            <div>
              <label style={label} htmlFor="rv-text">Đánh giá của bạn <span style={{ color: "var(--destructive, #d92d20)" }}>*</span></label>
              <textarea id="rv-text" value={form.text} onChange={set("text")} rows={5} placeholder="Xe chạy êm, khung nhẹ, lắp ráp cẩn thận…" style={{ ...field(errs.text), resize: "vertical", lineHeight: 1.6 }} />
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10 }}>
                {errText(errs.text) || <span />}
                <span style={{ fontSize: 12, color: "var(--muted-foreground)", fontFamily: "var(--font-mono)", marginTop: 5 }}>{form.text.length}/1000</span>
              </div>
            </div>
            <div>
              <span style={label}>Hình ảnh thực tế <span style={{ fontWeight: 500, color: "var(--muted-foreground)" }}>(tuỳ chọn, tối đa 5 ảnh)</span></span>
              <div onDragOver={(e) => { e.preventDefault(); setDrag(true); }} onDragLeave={() => setDrag(false)} onDrop={(e) => { e.preventDefault(); setDrag(false); addFiles(e.dataTransfer.files); }} onClick={() => inputRef.current && inputRef.current.click()} style={{ padding: "18px 14px", border: `1.5px dashed ${drag ? "var(--primary)" : "var(--border)"}`, borderRadius: "var(--radius-md)", background: drag ? "color-mix(in srgb, var(--primary) 6%, #fff)" : "color-mix(in srgb, var(--secondary) 40%, #fff)", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", gap: 10, textAlign: "center" }}>
                <i className="ph ph-image-square" style={{ fontSize: "calc(13px + 9px*var(--ts))", color: "var(--primary)" }} />
                <span style={{ fontSize: 13, color: "var(--muted-foreground)" }}>Kéo thả ảnh vào đây hoặc <b style={{ color: "var(--primary)" }}>chọn từ máy</b> · JPG/PNG ≤ 5MB</span>
              </div>
              <input ref={inputRef} type="file" accept="image/*" multiple onChange={(e) => { addFiles(e.target.files); e.target.value = ""; }} style={{ display: "none" }} />
              {files.length > 0 && (
                <div style={{ display: "flex", flexWrap: "wrap", gap: 10, marginTop: 12 }}>
                  {files.map((f, i) => (
                    <div key={i} style={{ position: "relative", width: 72, height: 72, borderRadius: "var(--radius-sm)", overflow: "hidden", border: "1px solid var(--border)", background: "var(--secondary)" }}>
                      <img src={f.url} alt={f.name} style={{ width: "100%", height: "100%", objectFit: "cover" }} />
                      <button type="button" onClick={() => removeFile(i)} aria-label={`Xoá ${f.name}`} style={{ position: "absolute", right: 3, top: 3, width: 20, height: 20, borderRadius: "50%", border: 0, background: "rgba(0,0,0,.65)", color: "#fff", cursor: "pointer", display: "grid", placeItems: "center", fontSize: 11, padding: 0 }}><i className="ph-bold ph-x" /></button>
                    </div>
                  ))}
                </div>
              )}
            </div>
            <div style={{ display: "flex", gap: 12, paddingTop: 4, borderTop: "1px solid var(--border)", marginTop: 2, paddingTop: 16 }}>
              <Button type="button" variant="outline" onClick={onClose} style={{ flex: 1, boxShadow: "none" }}>Huỷ</Button>
              <Button type="submit" style={{ flex: 2, boxShadow: "none" }}><i className="ph ph-paper-plane-tilt" style={{ marginRight: 8 }} />Gửi đánh giá</Button>
            </div>
            <p style={{ margin: 0, fontSize: 12, color: "var(--muted-foreground)", lineHeight: 1.55 }}>Email và số điện thoại chỉ dùng để xác minh đơn hàng, không hiển thị công khai.</p>
          </form>
        )}
      </div>
    </div>
  );
}
function ReviewItem({ r, verified, noteBg }) {
  const [extra, setExtra] = React.useState([]);
  const [replyTo, setReplyTo] = React.useState(null);
  const [open, setOpen] = React.useState(true);
  const replies = [...(r.replies || []), ...extra];
  const send = (text) => { setExtra((p) => [...p, { name: "Bạn", time: "Vừa xong", lines: text.split("\n").filter(Boolean) }]); setReplyTo(null); setOpen(true); };
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10, padding: "22px 0", borderBottom: "1px solid var(--border)" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <span style={{ width: 34, height: 34, flexShrink: 0, borderRadius: "50%", background: "var(--secondary)", color: "var(--foreground)", display: "grid", placeItems: "center", fontWeight: 800, fontSize: "calc(13px + 2px*var(--ts))" }}>{r.name.trim().slice(0, 1)}</span>
        <span style={{ fontSize: "calc(13px + 1px*var(--ts))", fontWeight: 700 }}>{r.name}</span>
        {r.time && <span style={{ display: "inline-flex", alignItems: "center", gap: 4, fontSize: 12, color: "var(--muted-foreground)" }}><i className="ph ph-clock" style={{ fontSize: 13 }} />{r.time}</span>}
        <span style={{ display: "inline-flex", alignItems: "center", gap: 4, fontSize: 12, color: verified }}><i className="ph-fill ph-check-circle" style={{ fontSize: "calc(13px + 1px*var(--ts))" }} />Đã mua tại Xedap.vn</span>
      </div>
      <Stars n={r.stars} />
      <p style={{ margin: 0, fontSize: "calc(13px + 1px*var(--ts))", lineHeight: 1.65, color: "var(--foreground)", textWrap: "pretty" }}>{r.text}</p>
      {r.photos && (
        <div style={{ display: "flex", gap: 8 }}>
          {[0, 1].map((i) => <div key={i} style={{ width: 60, height: 60, overflow: "hidden", borderRadius: "var(--radius-sm)", background: "var(--secondary)" }}><img src={RAPTOR_SHOTS[i + 1]} alt="" style={{ width: "100%", height: "100%", objectFit: "cover" }} /></div>)}
        </div>
      )}
      {r.note && (
        <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 14px", borderRadius: "var(--radius-md)", background: noteBg, fontSize: 13, color: "var(--foreground)" }}>
          <i className="ph-fill ph-chats-circle" style={{ fontSize: "calc(13px + 5px*var(--ts))", color: "var(--primary)", flexShrink: 0 }} />{r.note}
        </div>
      )}
      <div style={{ display: "flex", alignItems: "center", gap: 14, fontSize: 13, color: "var(--muted-foreground)", marginTop: 2 }}>
        <button style={{ display: "inline-flex", alignItems: "center", gap: 6, border: "none", background: "none", cursor: "pointer", fontFamily: "var(--font-sans)", fontSize: 13, color: "var(--muted-foreground)", padding: 0 }}><i className="ph ph-thumbs-up" style={{ fontSize: "calc(13px + 3px*var(--ts))" }} />Hữu ích ({r.helpful})</button>
        <span style={{ width: 1, height: 12, background: "var(--border)" }} />
        <span>{r.used}</span>
      </div>
      {replyTo === r.name ? <ReviewReplyForm to={r.name} onCancel={() => setReplyTo(null)} onSend={send} /> : <ReviewReplyButton onClick={() => setReplyTo(r.name)} />}
      {!!replies.length && (
        <div style={{ marginTop: 4 }}>
          <button onClick={() => setOpen((v) => !v)} style={{ display: "inline-flex", alignItems: "center", gap: 6, border: "none", background: "none", padding: 0, cursor: "pointer", fontFamily: "var(--font-sans)", fontSize: 13, color: "var(--foreground)" }}>{open ? "Thu gọn phản hồi" : `Xem ${replies.length} phản hồi`}<i className={open ? "ph ph-caret-up" : "ph ph-caret-down"} style={{ fontSize: 13 }} /></button>
          {open && (
            <div style={{ borderLeft: "2px solid var(--border)", paddingLeft: 18, marginTop: 8, marginLeft: 6 }}>
              {replies.map((rep, i) => (
                <div key={i}>
                  <ReviewReply r={rep} />
                  <div style={{ paddingLeft: 48, paddingTop: 8 }}>
                    {replyTo === `${r.name}-${i}` ? <ReviewReplyForm to={rep.name} onCancel={() => setReplyTo(null)} onSend={send} /> : <ReviewReplyButton onClick={() => setReplyTo(`${r.name}-${i}`)} />}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      )}
    </div>
  );
}
const EXPERIENCE = [["Vận hành", 5, 12], ["Độ bền khung", 5, 9], ["Dịch vụ lắp đặt", 4, 7]];
const REVIEW_FILTERS = ["Tất cả", "Có hình ảnh", "Đã mua hàng", "5 sao", "4 sao", "3 sao", "2 sao", "1 sao"];
const QUESTIONS = [
  { name: "Trần Hoàng Long", time: "4 ngày trước", text: "Cho em hỏi xe này bảo hành khung bao nhiêu năm vậy ạ?", replies: [{ admin: true, name: "Quản Trị Viên", time: "4 ngày trước", lines: ["Chào anh Long,", "Dạ khung nhôm được bảo hành 5 năm, các chi tiết truyền động bảo hành 12 tháng ạ.", "Xe còn kèm 3 lần bảo dưỡng miễn phí tại mọi cửa hàng Xedap.vn.", "Cảm ơn anh đã quan tâm đến Xedap.vn."] }] },
  { name: "Anh Nghiêm", time: "2 tuần trước", text: "Xe này có sẵn size M ở chi nhánh Hà Nội không shop?", replies: [{ admin: true, name: "Quản Trị Viên", time: "2 tuần trước", lines: ["Chào anh Nghiêm,", "Dạ size M hiện còn hàng tại Xedap.vn 254 Nguyễn Trãi, Thanh Xuân, Hà Nội ạ.", "Giá thời điểm hiện tại: 18.900.000đ, đã gồm lắp ráp và cân chỉnh miễn phí.", "Anh cho em xin số điện thoại để em giữ xe trong 24 giờ nhé."] }] },
  { name: "Quy Ngọc", time: "5 tháng trước", text: "Mình đặt từ ngày 22/2, xác nhận xong rồi mà tới 2/3 vẫn chưa thấy giao, shop kiểm tra giúp mình với.", replies: [{ admin: true, name: "Quản Trị Viên", time: "5 tháng trước", lines: ["Chào anh Quy Ngọc,", "Dạ Xedap.vn xin lỗi về việc đơn hàng bị chậm trễ ạ.", "Em đã báo kho kiểm tra lại đơn và sẽ liên hệ anh qua số điện thoại đã đăng ký trong 60 phút.", "Mong anh thông cảm."] }] },
  { name: "Huy Nguyễn", time: "11 tháng trước", text: "Mẫu này ở showroom nào Hải Phòng có vậy ạ?", replies: [{ admin: true, name: "Quản Trị Viên", time: "11 tháng trước", lines: ["Xedap.vn xin chào anh Huy!", "Dạ mẫu này còn tại Xedap.vn 162 Lạch Tray, Phường Lạch Tray, Quận Ngô Quyền, TP. Hải Phòng.", "Em giữ xe và giá trong 24 giờ số điện thoại *****339 được không ạ?", "Mong nhận được phản hồi từ mình."] }] },
];
function QuestionThread({ q }) {
  const [extra, setExtra] = React.useState([]);
  const [replyTo, setReplyTo] = React.useState(null);
  const [open, setOpen] = React.useState(true);
  const replies = [...(q.replies || []), ...extra];
  const send = (text) => { setExtra((p) => [...p, { name: "Bạn", time: "Vừa xong", lines: text.split("\n").filter(Boolean) }]); setReplyTo(null); setOpen(true); };
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10, padding: "22px 0", borderBottom: "1px solid var(--border)" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <span style={{ width: 34, height: 34, flexShrink: 0, borderRadius: "50%", background: "var(--secondary)", color: "var(--foreground)", display: "grid", placeItems: "center", fontWeight: 800, fontSize: "calc(13px + 2px*var(--ts))" }}>{q.name.trim().slice(0, 1)}</span>
        <span style={{ fontSize: "calc(13px + 1px*var(--ts))", fontWeight: 700 }}>{q.name}</span>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 4, fontSize: 12, color: "var(--muted-foreground)" }}><i className="ph ph-clock" style={{ fontSize: 13 }} />{q.time}</span>
      </div>
      <p style={{ margin: 0, fontSize: "calc(13px + 1px*var(--ts))", lineHeight: 1.65, textWrap: "pretty" }}>{q.text}</p>
      {replyTo === q.name ? <ReviewReplyForm to={q.name} onCancel={() => setReplyTo(null)} onSend={send} /> : <ReviewReplyButton onClick={() => setReplyTo(q.name)} />}
      {!!replies.length && (
        <div style={{ marginTop: 4 }}>
          <button onClick={() => setOpen((v) => !v)} style={{ display: "inline-flex", alignItems: "center", gap: 6, border: "none", background: "none", padding: 0, cursor: "pointer", fontFamily: "var(--font-sans)", fontSize: 13, color: "var(--foreground)" }}>{open ? "Thu gọn phản hồi" : `Xem ${replies.length} phản hồi`}<i className={open ? "ph ph-caret-up" : "ph ph-caret-down"} style={{ fontSize: 13 }} /></button>
          {open && (
            <div style={{ borderLeft: "2px solid var(--border)", paddingLeft: 18, marginTop: 8, marginLeft: 6 }}>
              {replies.map((rep, i) => (
                <div key={i}>
                  <ReviewReply r={rep} />
                  <div style={{ paddingLeft: 48, paddingTop: 8 }}>
                    {replyTo === `${q.name}-${i}` ? <ReviewReplyForm to={rep.name} onCancel={() => setReplyTo(null)} onSend={send} /> : <ReviewReplyButton onClick={() => setReplyTo(`${q.name}-${i}`)} />}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      )}
    </div>
  );
}
function QuestionsSection() {
  const [text, setText] = React.useState("");
  const [sent, setSent] = React.useState(false);
  const card = { background: "#fff", border: "1px solid var(--border)", borderRadius: "var(--radius-lg, 10px)", overflow: "hidden" };
  const head = { padding: "16px 24px", borderBottom: "1px solid var(--border)", fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 5px*var(--ts))" };
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 20, marginTop: 20 }}>
      <div style={card}>
        <div style={head}>Hỏi và đáp</div>
        <div style={{ display: "flex", gap: 20, padding: 24, alignItems: "flex-start" }}>
          <span style={{ width: 64, height: 64, flexShrink: 0, borderRadius: "50%", background: "color-mix(in srgb, var(--primary) 10%, #fff)", color: "var(--primary)", display: "grid", placeItems: "center", fontSize: "calc(13px + 19px*var(--ts))" }}><i className="ph-fill ph-chats-circle" /></span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 4px*var(--ts))" }}>Hãy đặt câu hỏi cho chúng tôi</div>
            <p style={{ margin: "8px 0 0", fontSize: "calc(13px + 1px*var(--ts))", lineHeight: 1.6, color: "var(--muted-foreground)", textWrap: "pretty" }}>Xedap.vn sẽ phản hồi trong vòng 1 giờ. Nếu Quý khách gửi câu hỏi sau 22h, chúng tôi sẽ trả lời vào sáng hôm sau. Thông tin có thể thay đổi theo thời gian, vui lòng đặt câu hỏi để nhận được cập nhật mới nhất.</p>
            <form onSubmit={(e) => { e.preventDefault(); if (text.trim()) { setSent(true); setText(""); } }} style={{ display: "flex", gap: 12, marginTop: 16, flexWrap: "wrap" }}>
              <input value={text} onChange={(e) => { setText(e.target.value); setSent(false); }} placeholder="Viết câu hỏi của bạn tại đây" style={{ flex: 1, minWidth: 240, padding: "12px 14px", fontSize: "calc(13px + 1px*var(--ts))", fontFamily: "var(--font-sans)", color: "var(--foreground)", background: "#fff", border: "1px solid var(--border)", borderRadius: "var(--radius-md)", outline: "none", boxSizing: "border-box" }} />
              <Button type="submit" style={{ boxShadow: "none" }}>Gửi câu hỏi<i className="ph ph-paper-plane-tilt" style={{ marginLeft: 8 }} /></Button>
            </form>
            {sent && <div style={{ marginTop: 12, display: "inline-flex", alignItems: "center", gap: 8, fontSize: 13, color: "#0a8f3c" }}><i className="ph-fill ph-check-circle" style={{ fontSize: "calc(13px + 3px*var(--ts))" }} />Đã gửi câu hỏi, Xedap.vn sẽ phản hồi trong vòng 1 giờ.</div>}
          </div>
        </div>
      </div>
      <div style={{ ...card, padding: "4px 24px 24px" }}>
        {QUESTIONS.map((q) => <QuestionThread key={q.name} q={q} />)}
        <div style={{ display: "flex", justifyContent: "center", marginTop: 24 }}>
          <Button variant="outline" style={{ boxShadow: "none", minWidth: 240 }}>Xem thêm 35 bình luận<i className="ph ph-caret-right" style={{ marginLeft: 8 }} /></Button>
        </div>
      </div>
    </div>
  );
}
function ReviewsSection({ product }) {
  const [writing, setWriting] = React.useState(false);
  const [filter, setFilter] = React.useState("Tất cả");
  const total = DIST.reduce((s, [, n]) => s + n, 0);
  const verified = "#0a8f3c";
  const noteBg = "color-mix(in srgb, var(--primary) 7%, #fff)";
  const shown = REVIEWS.filter((r) => {
    if (filter === "Tất cả" || filter === "Đã mua hàng") return true;
    if (filter === "Có hình ảnh") return !!r.photos;
    return r.stars === parseInt(filter, 10);
  });
  const card = { background: "#fff", border: "1px solid var(--border)", borderRadius: "var(--radius-lg, 10px)", overflow: "hidden" };
  const head = { padding: "16px 24px", borderBottom: "1px solid var(--border)", fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 5px*var(--ts))", textWrap: "pretty" };
  return (
    <section style={{ background: "color-mix(in srgb, var(--secondary) 40%, #fff)", borderTop: "1px solid var(--border)" }}>
      <div style={{ maxWidth: 1180, margin: "0 auto", padding: "48px 24px" }}>
        <div style={card}>
          <div style={head}>Đánh giá {product && product.name}</div>
          <div style={{ display: "grid", gridTemplateColumns: "minmax(180px, 220px) minmax(280px, 1fr) minmax(280px, 380px)", gap: 40, padding: 28, alignItems: "start" }}>
            <div style={{ textAlign: "center" }}>
              <div style={{ display: "flex", alignItems: "flex-end", gap: 4, justifyContent: "center" }}>
                <span style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 33px*var(--ts))", lineHeight: 1 }}>4.9</span>
                <span style={{ fontSize: "calc(13px + 3px*var(--ts))", color: "var(--muted-foreground)", paddingBottom: 4 }}>/5</span>
              </div>
              <div style={{ marginTop: 10, display: "flex", justifyContent: "center" }}><Stars n={5} /></div>
              <div style={{ marginTop: 8, fontSize: 13, color: "var(--muted-foreground)" }}>{total} lượt đánh giá</div>
              <Button onClick={() => setWriting(true)} style={{ marginTop: 14, width: "100%", boxShadow: "none" }}>Viết đánh giá</Button>
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 9, borderRight: "1px solid var(--border)", paddingRight: 40 }}>
              {DIST.map(([lbl, n]) => (
                <div key={lbl} style={{ display: "flex", alignItems: "center", gap: 12, fontSize: 13 }}>
                  <span style={{ display: "flex", alignItems: "center", gap: 3, color: "var(--muted-foreground)" }}>{lbl.replace(" sao", "")} <i className="ph-fill ph-star" style={{ fontSize: 12, color: "var(--warning)" }} /></span>
                  <div style={{ flex: 1, height: 7, borderRadius: 5, background: "var(--border)", overflow: "hidden" }}>
                    <div style={{ width: `${(n / total) * 100}%`, height: "100%", background: "var(--primary)" }} />
                  </div>
                  <span style={{ width: 78, textAlign: "right", fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--muted-foreground)" }}>{n} đánh giá</span>
                </div>
              ))}
            </div>
            <div>
              <div style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 2px*var(--ts))", marginBottom: 12 }}>Đánh giá theo trải nghiệm</div>
              <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
                {EXPERIENCE.map(([lbl, score, n]) => (
                  <div key={lbl} style={{ display: "flex", alignItems: "center", gap: 12, fontSize: 13 }}>
                    <span style={{ flex: 1, minWidth: 0 }}>{lbl}</span>
                    <Stars n={score} />
                    <span style={{ fontWeight: 700 }}>{score}/5</span>
                    <span style={{ color: "var(--muted-foreground)", fontSize: 12 }}>({n} đánh giá)</span>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>
        <div style={{ ...card, marginTop: 20, padding: "0 24px 24px" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap", padding: "20px 0 4px" }}>
            <span style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 2px*var(--ts))", marginRight: 4 }}>Lọc đánh giá theo</span>
            {REVIEW_FILTERS.map((f) => {
              const on = f === filter;
              return <button key={f} onClick={() => setFilter(f)} style={{ padding: "6px 14px", borderRadius: 999, cursor: "pointer", fontFamily: "var(--font-sans)", fontSize: 13, fontWeight: on ? 700 : 500, border: `1px solid ${on ? "var(--primary)" : "var(--border)"}`, background: on ? "color-mix(in srgb, var(--primary) 8%, #fff)" : "#fff", color: on ? "var(--primary)" : "var(--foreground)" }}>{f}</button>;
            })}
          </div>
          <div style={{ display: "flex", flexDirection: "column", marginTop: 8 }}>
            {shown.length ? shown.map((r) => <ReviewItem key={r.name} r={r} verified={verified} noteBg={noteBg} />) : <div style={{ padding: "40px 0", textAlign: "center", fontSize: "calc(13px + 1px*var(--ts))", color: "var(--muted-foreground)" }}>Chưa có đánh giá nào phù hợp bộ lọc này.</div>}
          </div>
          <div style={{ display: "flex", justifyContent: "center", marginTop: 24 }}>
            <Button variant="outline" style={{ boxShadow: "none", minWidth: 240 }}>Xem tất cả đánh giá<i className="ph ph-caret-right" style={{ marginLeft: 8 }} /></Button>
          </div>
        </div>
        <QuestionsSection />
        {writing && <ReviewFormModal product={product} onClose={() => setWriting(false)} />}
      </div>
    </section>
  );
}

/* ---------- Product rows ---------- */
function ProductRow({ title, items, onAdd, onOpen, compareEnabled = true }) {
  const { IMG } = window.KitData;
  const cmp = useCompareState();
  const scrollRef = React.useRef(null);
  const [prog, setProg] = React.useState(0);
  const scrollBy = (dir) => { const el = scrollRef.current; if (el) el.scrollBy({ left: dir * (el.clientWidth * 0.8), behavior: "smooth" }); };
  const onScroll = () => { const el = scrollRef.current; if (!el) return; const max = el.scrollWidth - el.clientWidth; setProg(max > 0 ? el.scrollLeft / max : 0); };
  return (
    <section style={{ ...wrap, padding: "56px 24px" }}>
      <h2 style={{ margin: "0 0 28px", fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "calc(13px + 11px*var(--ts))" }}>{title}</h2>
      <div ref={scrollRef} onScroll={onScroll} style={{ display: "grid", gridAutoFlow: "column", gridAutoColumns: "calc((100% - 4 * 20px) / 4.3)", gap: 20, overflowX: "auto", scrollSnapType: "x mandatory", scrollbarWidth: "none", paddingBottom: 4 }}>
        {items.map((p) => { const card = { ...p, image: p.img || IMG(p.seed) }; return <div key={p.slug} style={{ scrollSnapAlign: "start" }}><ProductCard product={card} onAdd={onAdd} onCompare={compareEnabled ? cmp.toggle : undefined} comparing={compareEnabled && cmp.has(p.slug)} onClick={() => onOpen && onOpen(p)} /></div>; })}
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 24, marginTop: 28 }}>
        <div style={{ display: "flex", gap: 10, flexShrink: 0 }}>
          <button onClick={() => scrollBy(-1)} aria-label="Xem trước" style={{ width: 48, height: 48, borderRadius: "var(--radius-md)", border: "1px solid var(--border)", background: "#fff", color: "var(--foreground)", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center" }}><i className="ph ph-arrow-left" style={{ fontSize: "calc(13px + 5px*var(--ts))" }} /></button>
          <button onClick={() => scrollBy(1)} aria-label="Xem thêm" style={{ width: 48, height: 48, borderRadius: "var(--radius-md)", border: "1px solid var(--border)", background: "#fff", color: "var(--foreground)", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center" }}><i className="ph ph-arrow-right" style={{ fontSize: "calc(13px + 5px*var(--ts))" }} /></button>
        </div>
        <div style={{ flex: 1, height: 4, borderRadius: 999, background: "var(--border)", position: "relative", overflow: "hidden" }}>
          <div style={{ position: "absolute", left: 0, top: 0, bottom: 0, width: "35%", transform: `translateX(${prog * (100 / 0.35 - 100)}%)`, background: "var(--foreground)", borderRadius: 999, transition: "transform .2s" }} />
        </div>
        <Button style={{ flexShrink: 0, boxShadow: "none" }} onClick={() => onOpen && onOpen(items[0])}>Xem tất cả</Button>
      </div>
    </section>
  );
}

/* ---------- Sticky buy bar ---------- */
function StickyBuyBar({ product, onAdd, visible }) {
  const cmp = useCompareState();
  const trayUp = cmp.items.length > 0;
  const [added, setAdded] = React.useState(false);
  const add = () => { onAdd(product); setAdded(true); clearTimeout(add._t); add._t = setTimeout(() => setAdded(false), 1700); };
  return (
    <div style={{ position: "fixed", left: 0, right: 0, bottom: 0, zIndex: 900, transform: (visible && !trayUp) ? "translateY(0)" : "translateY(115%)", transition: "transform .38s cubic-bezier(.22,.61,.36,1)", background: "rgba(255,255,255,.97)", backdropFilter: "blur(8px)", borderTop: "1px solid var(--border)", boxShadow: "0 -8px 30px rgba(0,0,0,.09)" }}>
      <div style={{ ...wrap, display: "flex", alignItems: "center", gap: 16, padding: "12px 24px" }}>
        <img src={(productDetailApiMatch(product) || {}).img || product.img || product.image || RAPTOR_SHOTS[0]} alt="" style={{ width: 52, height: 52, objectFit: "cover", borderRadius: "var(--radius-md)", flexShrink: 0, background: "var(--secondary)" }} />
        <div style={{ display: "flex", flexDirection: "column", gap: 2, minWidth: 0, flex: 1 }}>
          <span style={{ fontSize: "calc(13px + 1px*var(--ts))", fontWeight: 700, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{product.name}</span>
          <span style={{ display: "flex", alignItems: "baseline", gap: 8 }}>
            <span style={{ fontFamily: "var(--font-mono)", fontSize: "calc(13px + 3px*var(--ts))", fontWeight: 600, color: "var(--danger)" }}>{vnd(product.price)}</span>
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--muted-foreground)", textDecoration: "line-through" }}>{vnd(product.originalPrice)}</span>
          </span>
        </div>
        <Button size="lg" style={{ flexShrink: 0, boxShadow: "none", background: "#d4150a", borderColor: "#d4150a", textTransform: "uppercase", fontWeight: 800, transition: "transform .18s cubic-bezier(.34,1.56,.64,1), background .2s", transform: added ? "scale(1.03)" : "none", ...(added ? { background: "#07c73c", borderColor: "#07c73c" } : {}) }} onClick={add}>{added ? <React.Fragment><i className="ph-fill ph-check-circle" style={{ marginRight: 8 }} />Đã thêm</React.Fragment> : <React.Fragment>Mua ngay</React.Fragment>}</Button>
      </div>
    </div>
  );
}

/* ---------- Page ---------- */
function ProductDetail({ product, onAdd, onOpen, onBack, cartOpen }) {
  const { PRODUCTS } = window.KitData;
  // "Các lựa chọn tương tự" lấy từ dữ liệu thật api.xedap.vn — cùng danh mục trước, rồi tới sản phẩm khác.
  const apiAll = (window.XedapApiData && window.XedapApiData.PRODUCTS) || [];
  const apiPool = apiAll.filter((p) => p.slug !== product.slug && p.name !== product.name);
  const others = apiPool.length
    ? [...apiPool.filter((p) => p.category === product.category), ...apiPool.filter((p) => p.category !== product.category)]
    : PRODUCTS.filter((p) => p.slug !== product.slug);
  const boughtTogether = [
    { slug: "acc-shimano-shoes", name: "Giày Đạp Xe Thể Thao Nam SHIMANO SH-GE700 Cycling Shoes", code: "Thương hiệu: SHIMANO", brand: "SHIMANO", category: "Phụ kiện", price: 3790000, badge: "Phụ kiện", colors: [], rating: 4.8, count: 42, img: "https://cdn.hstatic.net/files/200001086651/file/27_2f8b64b9dc5241b0b8664af2c39c7d12.png" },
    { slug: "acc-giant-bottle", name: "Bình Nước Xe Đạp 750cc GIANT Cleanspring Water Bottle", code: "Thương hiệu: GIANT", brand: "GIANT", category: "Phụ kiện", price: 319000, badge: "Phụ kiện", colors: [], rating: 4.7, count: 96, img: "https://cdn.hstatic.net/files/200001086651/file/28_fc78141de6c943fc833a36aa0e710a19.png" },
    { slug: "acc-handlebar-bag", name: "Túi Ghi Đông Xe Đạp 190x110x35mm GI59 Bicycle Handlebar Bag", code: "Phụ kiện", brand: "GI59", category: "Phụ kiện", price: 299000, badge: "Phụ kiện", colors: [], rating: 4.6, count: 58, img: "https://cdn.hstatic.net/files/200001086651/file/29_63bdd217cbe6431298a63db5848206c5.png" },
    { slug: "acc-baimei-pump", name: "Ống Bơm Xe Đạp BAIMEI Air B-4518 Bicycle Mini Floor Pump", code: "Thương hiệu: BAIMEI", brand: "BAIMEI", category: "Phụ kiện", price: 139000, badge: "Phụ kiện", colors: [], rating: 4.5, count: 73, img: "https://cdn.hstatic.net/files/200001086651/file/30_f25d9805d7f04a7fb48ed89de3f00512.png" },
    { slug: "acc-helmet-fornix", name: "Nón Bảo Hiểm Xe Đạp FORNIX M310 Bicycle Helmet", code: "Thương hiệu: FORNIX", brand: "FORNIX", category: "Phụ kiện", price: 490000, badge: "Bán chạy", colors: [], rating: 4.8, count: 120, img: "https://cdn.hstatic.net/files/200001086651/file/27_2f8b64b9dc5241b0b8664af2c39c7d12.png" },
    { slug: "acc-light-set", name: "Bộ Đèn Xe Đạp Trước Sau LED Sạc USB Bicycle Light Set", code: "Phụ kiện", brand: "GI", category: "Phụ kiện", price: 259000, badge: "Hàng mới", colors: [], rating: 4.6, count: 64, img: "https://cdn.hstatic.net/files/200001086651/file/28_fc78141de6c943fc833a36aa0e710a19.png" },
    { slug: "acc-lock", name: "Khóa Chống Trộm Xe Đạp Dây Cáp Thép Bicycle Cable Lock", code: "Phụ kiện", brand: "GI59", category: "Phụ kiện", price: 189000, badge: "Trả góp 0%", colors: [], rating: 4.4, count: 51, img: "https://cdn.hstatic.net/files/200001086651/file/29_63bdd217cbe6431298a63db5848206c5.png" },
    { slug: "acc-gloves", name: "Găng Tay Đạp Xe Thể Thao Chống Trượt Cycling Gloves", code: "Phụ kiện", brand: "SHIMANO", category: "Phụ kiện", price: 149000, badge: "Bán chạy", colors: [], rating: 4.7, count: 88, img: "https://cdn.hstatic.net/files/200001086651/file/30_f25d9805d7f04a7fb48ed89de3f00512.png" },
  ];
  const buyRef = React.useRef(null);
  const [showBar, setShowBar] = React.useState(false);
  React.useEffect(() => {
    const el = buyRef.current;
    const footer = document.querySelector("footer");
    let buyOut = false, footerIn = false;
    const upd = () => setShowBar(buyOut && !footerIn);
    const io1 = new IntersectionObserver(([e]) => { buyOut = !e.isIntersecting && e.boundingClientRect.top < 0; upd(); }, { threshold: 0 });
    if (el) io1.observe(el);
    let io2;
    if (footer) { io2 = new IntersectionObserver(([e]) => { footerIn = e.isIntersecting; upd(); }, { threshold: 0, rootMargin: "0px 0px 40px 0px" }); io2.observe(footer); }
    return () => { io1.disconnect(); io2 && io2.disconnect(); };
  }, [product.slug]);
  return (
    <main>
      <div style={{ ...wrap, padding: "20px 24px 8px" }}>
        <Breadcrumb product={product} />
      </div>
      <div style={{ ...wrap, padding: "12px 24px 56px", display: "grid", gridTemplateColumns: "minmax(0, 1fr) minmax(400px, 1fr)", gap: 48, alignItems: "start" }}>
        <div style={{ position: "sticky", top: 84, minWidth: 0 }}><Gallery product={product} /></div>
        <div ref={buyRef} style={{ minWidth: 0 }}><BuyBox product={product} onAdd={onAdd} /></div>
      </div>
      <div style={{ ...wrap, padding: "0 24px 56px" }}>
        <ComboSection />
      </div>
      <div style={{ borderTop: "1px solid var(--border)" }}>
        <div style={{ ...wrap, padding: "56px 24px", display: "grid", gridTemplateColumns: "2fr 1fr", gap: 48, alignItems: "start" }}>
          <div><FeatureGrid /><StoryBlock /></div>
          <div style={{ position: "sticky", top: 84 }}><SpecTable product={product} /></div>
        </div>
      </div>
      <ReviewsSection product={product} />
      <ProductRow title="Các lựa chọn tương tự" items={others.slice(0, 10)} onAdd={onAdd} onOpen={onOpen} />
      <ProductRow title="Trang bị thêm cho hành trình" items={boughtTogether} onAdd={onAdd} onOpen={onOpen} compareEnabled={false} />
      <StickyBuyBar product={product} onAdd={onAdd} visible={showBar && !cartOpen} />
      <CompareTray />
      <CompareModal />
    </main>
  );
}

Object.assign(window, { ProductDetail });
