/* ============================================================================
   Speero demo bundle — loaded by index.html as a separate <script type="text/babel">
   so the ~3.6k lines of demo code stay OUT of the main app file.

   These demos run in the app's runtime (React is global). Anything they need from
   the app (shared components, catalog data, helpers, icons) is read once from the
   window.DEMO_API bridge that index.html sets just before it mounts. That keeps the
   demos behaving exactly like production with zero duplicated/drifting code.

   This bundle shares the app's global scope (Babel-standalone compiles top-level
   declarations to globals), so demos reference the app's React hooks, components,
   data, and helpers (useState, ProductImage, PRODUCTS, addToCart, navigate, ...) by
   bare name, exactly as they did when inline. No bridge, no duplication, no drift.

   Each demo registers itself into window.DEMOS under its route key; the app's screen
   dispatcher renders window.DEMOS[<route>] for any "/*-demo" path.
   ============================================================================ */

/* ---------- #/wheel-spin-demo ---------- */
function WheelSpinDemo() {
  const r2 = (n) => Math.round(n * 100) / 100;
  const pt = (cx, cy, r, deg) => {
    const a = (deg * Math.PI) / 180;
    return [r2(cx + r * Math.cos(a)), r2(cy + r * Math.sin(a))];
  };
  const spokeAngles = [-90, -18, 54, 126, 198];

  // Layered candidate: original casing/tread (static base) + a circular wheel
  // face tilted in true 3D so its rotation tracks the tire's foreshortening.
  // Parametrized: tilt (matches the original ellipse), spoke count, rotating
  // tread ticks on the rim.
  const LayeredWheel = ({ tilt = "52deg", spokes = 5, tread = false }) => {
    const spokeAngs = Array.from({ length: spokes }, (_, i) => -90 + (i * 360) / spokes);
    return (
      <div className="ws-layer">
        <svg className="ws-base2" viewBox="0 0 240 270" fill="none" aria-hidden="true">
          <g stroke="#2A2C31" strokeLinejoin="round" strokeLinecap="round">
            <path d="M 108 15 A 78 120 0 0 0 108 255 L 142 255 A 78 120 0 0 0 142 15 Z" strokeWidth="4" />
            <ellipse cx="142" cy="135" rx="78" ry="120" strokeWidth="4" />
            <ellipse cx="142" cy="135" rx="65" ry="107" strokeWidth="2.6" />
            <path d="M 48.25 212.13 L 82.25 212.13" strokeWidth="2.6" />
            <path d="M 34.7 176.04 L 68.7 176.04" strokeWidth="2.6" />
            <path d="M 30 135 L 64 135" strokeWidth="2.6" />
            <path d="M 34.7 93.96 L 68.7 93.96" strokeWidth="2.6" />
            <path d="M 48.25 57.87 L 82.25 57.87" strokeWidth="2.6" />
          </g>
        </svg>
        <svg className="ws-face" style={{ "--ws-tilt": tilt }} viewBox="0 0 200 200" fill="none" aria-hidden="true">
          <g stroke="#2A2C31" strokeLinejoin="round" strokeLinecap="round">
            <circle cx="100" cy="100" r="96" strokeWidth="5" />
            <circle cx="100" cy="100" r="80" strokeWidth="4" />
            {tread && Array.from({ length: 24 }).map((_, i) => {
              const [x1, y1] = pt(100, 100, 80, i * 15);
              const [x2, y2] = pt(100, 100, 94, i * 15);
              return <line key={"t" + i} x1={x1} y1={y1} x2={x2} y2={y2} strokeWidth="2.4" />;
            })}
            {spokeAngs.map((deg, i) => {
              const [x1, y1] = pt(100, 100, 28, deg);
              const [x2, y2] = pt(100, 100, 76, deg);
              return <line key={"s" + i} x1={x1} y1={y1} x2={x2} y2={y2} strokeWidth="5" />;
            })}
            <circle cx="100" cy="100" r="20" strokeWidth="5" />
            <circle cx="100" cy="100" r="7" strokeWidth="3.5" />
            {spokeAngles.map((deg, i) => {
              const [x, y] = pt(100, 100, 12, deg);
              return <circle key={"l" + i} cx={x} cy={y} r="2.4" strokeWidth="3" />;
            })}
          </g>
        </svg>
      </div>
    );
  };

  // Current production shape — perspective-baked ellipse, inner face spins.
  const TireWheel = () => (
    <svg className="ws-art tilt" viewBox="0 0 240 270" fill="none" aria-hidden="true">
      <defs><clipPath id="wsWheelFace"><ellipse cx="142" cy="135" rx="56" ry="92" /></clipPath></defs>
      <g stroke="#2A2C31" strokeLinejoin="round" strokeLinecap="round">
        <path d="M 108 15 A 78 120 0 0 0 108 255 L 142 255 A 78 120 0 0 0 142 15 Z" strokeWidth="4" />
        <ellipse cx="142" cy="135" rx="78" ry="120" strokeWidth="4" />
        <ellipse cx="142" cy="135" rx="65" ry="107" strokeWidth="2.6" />
        <path d="M 48.25 212.13 L 82.25 212.13" strokeWidth="2.6" />
        <path d="M 34.7 176.04 L 68.7 176.04" strokeWidth="2.6" />
        <path d="M 30 135 L 64 135" strokeWidth="2.6" />
        <path d="M 34.7 93.96 L 68.7 93.96" strokeWidth="2.6" />
        <path d="M 48.25 57.87 L 82.25 57.87" strokeWidth="2.6" />
        <ellipse cx="142" cy="135" rx="56" ry="92" strokeWidth="4" />
        <ellipse cx="142" cy="135" rx="46" ry="76" strokeWidth="4" />
        <g className="ws-spin-tire" clipPath="url(#wsWheelFace)">
          <path d="M 139.14 116.35 L 136.64 61.55 A 44 74 0 0 1 147.36 61.55 L 144.86 116.35 A 15 19 0 0 0 139.14 116.35 Z" strokeWidth="2.6" />
          <path d="M 155.12 125.79 L 181.88 103.73 A 44 74 0 0 1 185.19 120.88 L 156.89 132.68 A 15 19 0 0 0 155.12 125.79 Z" strokeWidth="2.6" />
          <path d="M 152.97 147.96 L 172.01 189.12 A 44 74 0 0 1 163.33 199.72 L 148.34 152.22 A 15 19 0 0 0 152.97 147.96 Z" strokeWidth="2.6" />
          <path d="M 135.66 152.22 L 120.67 199.72 A 44 74 0 0 1 111.99 189.12 L 131.03 147.96 A 15 19 0 0 0 135.66 152.22 Z" strokeWidth="2.6" />
          <path d="M 127.11 132.68 L 98.81 120.88 A 44 74 0 0 1 102.12 103.73 L 128.88 125.79 A 15 19 0 0 0 127.11 132.68 Z" strokeWidth="2.6" />
        </g>
        <ellipse cx="142" cy="135" rx="14" ry="18" strokeWidth="4" />
        <ellipse cx="142" cy="135" rx="5" ry="6.5" strokeWidth="2.6" />
        <g className="ws-spin-tire">
          <circle cx="142" cy="124" r="1.4" strokeWidth="2.6" />
          <circle cx="150.08" cy="131.6" r="1.4" strokeWidth="2.6" />
          <circle cx="147" cy="143.9" r="1.4" strokeWidth="2.6" />
          <circle cx="137" cy="143.9" r="1.4" strokeWidth="2.6" />
          <circle cx="133.92" cy="131.6" r="1.4" strokeWidth="2.6" />
        </g>
      </g>
    </svg>
  );

  const variants = [
    { id: "current", name: "1. الحالي (مرجع، دوران مكسور)", desc: "الإطار المنظوري الحالي للمقارنة فقط.", node: <TireWheel /> },
    { id: "base", name: "2. أساسي (ميل 52°، 5 قضبان)", desc: "الشكل المعتمد: وجه دائري بخمسة قضبان وميل 52° يطابق منظور الأصل.", node: <LayeredWheel tilt="52deg" /> },
    { id: "tread", name: "3. مع مداس يدور", desc: "شقوق مداس حول الإطار تدور مع العجلة، إشارة حركة أوضح ('تشاهد المداس يتحرّك').", node: <LayeredWheel tilt="52deg" tread={true} /> },
    { id: "open", name: "4. وجه أكثر انفتاحاً (ميل 44°)", desc: "ميل أقل يُظهر وجه العجلة أكثر، أقرب للأمام.", node: <LayeredWheel tilt="44deg" /> },
    { id: "narrow", name: "5. أنحف (ميل 60°)", desc: "ميل أقوى، إطار أنحف وأقرب للجانبية.", node: <LayeredWheel tilt="60deg" /> },
    { id: "fine", name: "6. قضبان أكثر (10)", desc: "عجلة أدقّ بعشرة قضبان مع المداس الدوّار.", node: <LayeredWheel tilt="52deg" spokes={10} tread={true} /> },
  ];

  return (
    <div className="cad-demo">
      <div className="cad-body">
        <h2 className="cad-title">دوران عجلة البحث البصري</h2>
        <p className="cad-sub">دوران مستمر لاختيار الشكل الذي يتطابق دورانه مع الإطار، قبل ضبط التشغيل عند الظهور والتوقّف.</p>
        {variants.map((v) => (
          <div className="cad-card" key={v.id}>
            <div className="cad-card-head">
              <h3 className="cad-card-name">{v.name}</h3>
              <p className="cad-card-desc">{v.desc}</p>
            </div>
            <div className="ws-stage">{v.node}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---------- Home/car IA demo (#/home-car-demo) ----------
   A first-time-aware re-sequencing of AnchoredHome, for a customer arriving at
   Speero for the first time to look for a spare part. Same sticky cluster and
   visual language as /car; the change is purely ORGANIZATION:
     1. Lead with the part-finding tools — popular rail, then the category grid,
        then visual search promoted to its OWN moment (the strongest path for a
        first-timer who doesn't know the part's name; in /car it's tucked at the
        bottom of the category section).
     2. Marketing (the قد يهمك promo) is demoted below the navigation tools.
     3. History-dependent sections are dropped for a no-history visitor: the
        maintenance reminder (there's no service record) is removed, and
        "recently viewed" (nothing viewed yet) is replaced by a best-sellers
        rail that's real on a first visit.
   Compare against /car. Logic is self-contained so /car stays untouched. */
function HomeCarDemo({ onMenu, onCart, cartCount, onSearch }) {
  const [stuck, setStuck] = useState(false);
  // Brief skeleton on entry so the personalized rails read as "fetched for your car".
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    const t = setTimeout(() => setLoading(false), 360);
    return () => clearTimeout(t);
  }, []);
  const sentinelRef = useRef(null);
  const [copied, setCopied] = useState(false);
  const copyPromo = () => {
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText("SPEERO26").catch(() => {});
    }
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };
  // Pin the cluster once the header scrolls away — same sentinel + IO as AnchoredHome.
  const stuckLockedUntilRef = useRef(0);
  useEffect(() => {
    const el = sentinelRef.current;
    if (!el || !("IntersectionObserver" in window)) return;
    const io = new IntersectionObserver(([e]) => {
      if (document.body.dataset.scrollY != null) return;
      const y = window.scrollY;
      const max = document.documentElement.scrollHeight - window.innerHeight;
      if (y < 0 || y > max) return;
      const now = performance.now();
      if (now < stuckLockedUntilRef.current) return;
      const next = !e.isIntersecting;
      setStuck((prev) => {
        if (prev === next) return prev;
        stuckLockedUntilRef.current = now + 400;
        return next;
      });
    }, { threshold: 0 });
    io.observe(el);
    return () => io.disconnect();
  }, []);

  // Visual-search card wheel-roll cue (replays each time it scrolls into view).
  const peekRef = useRef(null);
  const [peekRolling, setPeekRolling] = useState(false);
  useEffect(() => {
    const el = peekRef.current;
    if (!el || !("IntersectionObserver" in window)) return;
    const io = new IntersectionObserver(([e]) => setPeekRolling(e.isIntersecting), { threshold: 0.6 });
    io.observe(el);
    return () => io.disconnect();
  }, []);

  const recommended = ["bumperR", "bumperL", "shockR", "pads"];
  // Replaces "recently viewed" — real content on a first visit (a distinct set
  // from the popular rail so the two don't read as duplicates).
  const bestsellers = ["pads", "shockR", "grille", "bracketR"];
  // Labels trimmed to a single lead noun — the icon carries the meaning, so the
  // label only confirms it. Halves the text in the grid (tester feedback: too
  // much text). Full compound names ("الصدامات والشبوك") live on the category page.
  const categories = [
    { id: "bumpers-grilles",   label: "الصدامات",  icon: <IconBumper /> },
    { id: "suspension",        label: "المساعدات", icon: <IconShock /> },
    { id: "brakes",            label: "الفرامل",   icon: <IconBrakeDisc /> },
    { id: "ac",                label: "التكييف",   icon: <IconAC /> },
    { id: "lighting",          label: "الإضاءة",   icon: <IconHeadlight /> },
    { id: "engine-trans",      label: "المحرك",    icon: <IconEngine /> },
    { id: "filters",           label: "الفلاتر",   icon: <IconOil /> },
    { id: "electrical-battery",label: "الكهرباء",  icon: <IconBolt /> },
  ];

  return (
    <>
      <div ref={sentinelRef} aria-hidden="true" style={{ height: 1 }} />
      {/* Sticky cluster — identical to /car */}
      <div className={"stick-anchor" + (stuck ? " stuck" : "")}>
        <div className="car-bar">
          <button type="button" className="car-bar-photo-btn" onClick={onMenu} aria-label="فتح القائمة">
            <img className="car-bar-photo" src={CURRENT_CAR.image} alt={CURRENT_CAR.name} />
          </button>
          <div className="car-bar-body">
            <div className="car-bar-eyebrow">سيارتك الحالية</div>
            <div className="car-bar-name">{CURRENT_CAR.name}</div>
          </div>
          <div className="car-bar-actions">
            <button className="car-edit" aria-label="تغيير السيارة" onClick={onMenu}><IconEdit /></button>
            <button className="car-cart" aria-label="السلة" onClick={onCart}><IconCart />{cartCount > 0 && <span className="cart-badge">{cartCount}</span>}</button>
          </div>
        </div>
        <div className="anchor-trust"><div className="anchor-trust-inner"><TrustBadges /></div></div>
        <div className="search-wrap">
          <button className="big-search" onClick={onSearch}>
            <span className="bs-icon"><IconSearch /></span>
            <span className="bs-text">
              ابحث في قطع {CURRENT_CAR.short}
              <span className="bs-dots" aria-hidden="true"><span></span><span></span><span></span></span>
            </span>
          </button>
        </div>
      </div>

      {/* 1 — Browse by section, LEAD slot + premium tile treatment.
          Categories are the primary part-finding navigation, so they open the
          page, presented as large centered tiles (.dsc-cat-tiles — the same
          polished treatment the Discover screen uses) rather than compact rows. */}
      <section className="a-section">
        <div className="section-head">
          <h2 className="section-title">اختر القسم</h2>
        </div>
        <div className="cd-cats">
          {categories.map((c, i) => (
            <button
              key={i}
              className="cat-card"
              onClick={() => navigate(c.id ? "/spare-parts/" + c.id : "/spare-parts/all")}
            >
              <span className="cat-icon">{c.icon}</span>
              <span className="cat-label">{c.label}</span>
            </button>
          ))}
        </div>
        <button
          className="home-browse-all cd-browse"
          onClick={() => navigate("/spare-parts/all")}
        >
          <span className="cd-browse-icon"><IconGrid /></span>
          <span className="home-browse-all-title">اكتشف القطع والحلول</span>
          <span className="home-browse-all-arrow"><IconChevron /></span>
        </button>
      </section>

      {/* 2 — Visual search, kept with the other find-your-part tools (search +
          categories) so the top of the page is one clean discovery cluster,
          before any merchandising. */}
      <section className="a-section">
        <button className={"h3d-peek cd-peek" + (peekRolling ? " is-rolling" : "")} ref={peekRef} onClick={() => navigate("/locate")}>
          <div className="h3d-peek-stage">
            <svg className="h3dp-base" viewBox="0 0 240 270" fill="none" aria-hidden="true">
              <g stroke="#2A2C31" strokeLinejoin="round" strokeLinecap="round">
                <path d="M 108 15 A 78 120 0 0 0 108 255 L 142 255 A 78 120 0 0 0 142 15 Z" strokeWidth="4" />
                <ellipse cx="142" cy="135" rx="78" ry="120" strokeWidth="4" />
                <ellipse cx="142" cy="135" rx="65" ry="107" strokeWidth="2.6" />
                <path d="M 48.25 212.13 L 82.25 212.13" strokeWidth="2.6" />
                <path d="M 34.7 176.04 L 68.7 176.04" strokeWidth="2.6" />
                <path d="M 30 135 L 64 135" strokeWidth="2.6" />
                <path d="M 34.7 93.96 L 68.7 93.96" strokeWidth="2.6" />
                <path d="M 48.25 57.87 L 82.25 57.87" strokeWidth="2.6" />
              </g>
            </svg>
            <svg className="h3dp-face" viewBox="0 0 200 200" fill="none" aria-hidden="true">
              <g stroke="#2A2C31" strokeLinejoin="round" strokeLinecap="round">
                <circle cx="100" cy="100" r="96" strokeWidth="5" />
                <circle cx="100" cy="100" r="80" strokeWidth="4" />
                <line x1="100" y1="72" x2="100" y2="24" strokeWidth="5" />
                <line x1="126.63" y1="91.35" x2="172.28" y2="76.51" strokeWidth="5" />
                <line x1="116.46" y1="122.65" x2="144.67" y2="161.49" strokeWidth="5" />
                <line x1="83.54" y1="122.65" x2="55.33" y2="161.49" strokeWidth="5" />
                <line x1="73.37" y1="91.35" x2="27.72" y2="76.51" strokeWidth="5" />
                <circle cx="100" cy="100" r="20" strokeWidth="5" />
                <circle cx="100" cy="100" r="7" strokeWidth="3.5" />
                <circle cx="100" cy="88" r="2.4" strokeWidth="3" />
                <circle cx="111.41" cy="96.29" r="2.4" strokeWidth="3" />
                <circle cx="107.05" cy="109.71" r="2.4" strokeWidth="3" />
                <circle cx="92.95" cy="109.71" r="2.4" strokeWidth="3" />
                <circle cx="88.59" cy="96.29" r="2.4" strokeWidth="3" />
              </g>
            </svg>
          </div>
          <span className="h3d-peek-eyebrow"><IconSearch />دلّنا على مكان القطعة</span>
        </button>
      </section>

      {/* 3 — Recently-viewed ("last seen") rail */}
      <section className="a-section" style={{ paddingInline: 0 }}>
        <div className="section-head" style={{ padding: "0 16px" }}>
          <h2 className="section-title">شاهدت مؤخراً</h2>
        </div>
        <div className="prod-rail">
          {loading
            ? [0, 1, 2, 3].map((i) => <SkeletonRailCard key={i} />)
            : recommended.map((k) => <ProductCard key={k} p={findProduct(k)} onClick={() => navigate("/p/" + k)} />)}
        </div>
      </section>

      {/* 4 — قد يهمك promo */}
      <section className="a-section" style={{ paddingInline: 0 }}>
        <div className="section-head" style={{ padding: "0 16px" }}>
          <h2 className="section-title">ليش سبيرو؟</h2>
        </div>
        <div className="you-rail">
          <button type="button" className="you-card promo" onClick={copyPromo} aria-label="نسخ كود الخصم">
            <div>
              <div className="you-promo-eyebrow">خصم على طلبك الأول</div>
              <div className="you-pct mono">26%</div>
            </div>
            <div className="you-promo-foot">
              <span className="you-promo-sub">استخدم الكود</span>
              {copied ? (
                <span className="code-pill just-copied">تم نسخ الكود<IconThumb /></span>
              ) : (
                <span className="code-pill mono">SPEERO26</span>
              )}
            </div>
          </button>
          <div className="you-card neutral">
            <div className="you-icon"><IconTruck /></div>
            <div>
              <div className="you-title">شحن مجاني</div>
              <div className="you-sub">اطلب بـ<span className="mono">1,000</span> <Riyal /> أو أكثر</div>
            </div>
          </div>
          <div className="you-card neutral">
            <div className="you-icon"><IconChat /></div>
            <div>
              <div className="you-title">دعم فني</div>
              <div className="you-sub">فني سيارات معك على مدار اليوم</div>
            </div>
          </div>
        </div>
      </section>

      {/* Trust */}
      <TrustStrip />
    </>
  );
}

function VisualSearchSectionDemo() {
  return (
    <>
      <div className="vsd-label first">قسم محيط (Placeholder)</div>
      <VsdPlaceholder />

      <div className="vsd-label">Variant A · عنوان مدمج في البطاقة</div>
      <section className="a-section">
        <button className="vsd-a" onClick={() => navigate("/locate")}>
          <span className="vsd-a-art"><VsdWheel /></span>
          <span className="vsd-a-body">
            <span className="vsd-a-title">خلّ سيارتك تدلّك على القطعة</span>
            <span className="vsd-a-tag"><IconSearch />بحث بصري</span>
          </span>
          <span className="vsd-a-arrow"><IconChevron /></span>
        </button>
      </section>

      <VsdPlaceholder />

      <div className="vsd-label">Variant B · سيارتك + نقاط نابضة</div>
      <section className="a-section">
        <button className="vsd-b" onClick={() => navigate("/locate")}>
          <img className="vsd-b-img" src={CURRENT_CAR.image} alt={CURRENT_CAR.name} />
          <span className="vsd-b-dot" style={{ top: "60%", insetInlineStart: "26%" }} />
          <span className="vsd-b-dot" style={{ top: "47%", insetInlineStart: "53%" }} />
          <span className="vsd-b-dot" style={{ top: "40%", insetInlineStart: "75%" }} />
          <span className="vsd-b-cap">
            <span className="vsd-b-cap-title">حدد القطعة على سيارتك</span>
            <span className="vsd-b-tag"><IconSearch />بحث بصري</span>
          </span>
        </button>
      </section>

      <VsdPlaceholder />

      <div className="vsd-label">Variant C · بانر كامل العرض</div>
      <section className="a-section" style={{ paddingInline: 0 }}>
        <button className="vsd-c" onClick={() => navigate("/locate")}>
          <span className="vsd-c-body">
            <span className="vsd-c-title">خلّ سيارتك تدلّك</span>
            <span className="vsd-c-tag"><IconSearch />بحث بصري</span>
          </span>
          <VsdWheel className="vsd-c-wheel" />
        </button>
      </section>

      <VsdPlaceholder />
    </>
  );
}

/* ---------- Wheel thickness refinement (#/wheel-thickness-demo) ----------
   Side-by-side: the VS wheel (real base+face markup) next to a category glyph
   at the locked 2.9px, so the wheel's stroke can be dialed to feel like one
   family. Variation 1 pins the wheel to a single uniform stroke (.v1 = 2.4px). */
function WheelThicknessDemo() {
  return (
    <>
      <div className="wtd-head">سماكة عجلة البحث البصري مقابل أيقونة القسم</div>
      <div className="wtd-card">
        <div className="wtd-vlabel">VARIATION 1 — WHEEL 2.1px</div>
        <div className="wtd-row">
          <div className="wtd-item">
            <div className="wtd-art wtd-cat"><IconBrakeDisc /></div>
            <div className="wtd-cap">القسم · 2.9px</div>
          </div>
          <div className="wtd-item">
            <div className="wtd-art wtd-wheel v1">
              <div className="h3d-peek-stage">
                <svg className="h3dp-base" viewBox="0 0 240 270" fill="none" aria-hidden="true">
                  <g stroke="#2A2C31" strokeLinejoin="round" strokeLinecap="round">
                    <path d="M 108 15 A 78 120 0 0 0 108 255 L 142 255 A 78 120 0 0 0 142 15 Z" strokeWidth="4" />
                    <ellipse cx="142" cy="135" rx="78" ry="120" strokeWidth="4" />
                    <ellipse cx="142" cy="135" rx="65" ry="107" strokeWidth="2.6" />
                    <path d="M 48.25 212.13 L 82.25 212.13" strokeWidth="2.6" />
                    <path d="M 34.7 176.04 L 68.7 176.04" strokeWidth="2.6" />
                    <path d="M 30 135 L 64 135" strokeWidth="2.6" />
                    <path d="M 34.7 93.96 L 68.7 93.96" strokeWidth="2.6" />
                    <path d="M 48.25 57.87 L 82.25 57.87" strokeWidth="2.6" />
                  </g>
                </svg>
                <svg className="h3dp-face" viewBox="0 0 200 200" fill="none" aria-hidden="true">
                  <g stroke="#2A2C31" strokeLinejoin="round" strokeLinecap="round">
                    <circle cx="100" cy="100" r="96" strokeWidth="5" />
                    <circle cx="100" cy="100" r="80" strokeWidth="4" />
                    <line x1="100" y1="72" x2="100" y2="24" strokeWidth="5" />
                    <line x1="126.63" y1="91.35" x2="172.28" y2="76.51" strokeWidth="5" />
                    <line x1="116.46" y1="122.65" x2="144.67" y2="161.49" strokeWidth="5" />
                    <line x1="83.54" y1="122.65" x2="55.33" y2="161.49" strokeWidth="5" />
                    <line x1="73.37" y1="91.35" x2="27.72" y2="76.51" strokeWidth="5" />
                    <circle cx="100" cy="100" r="20" strokeWidth="5" />
                    <circle cx="100" cy="100" r="7" strokeWidth="3.5" />
                  </g>
                </svg>
              </div>
            </div>
            <div className="wtd-cap">العجلة · 2.1px</div>
          </div>
        </div>
      </div>
    </>
  );
}

/* ============================================================================
   Blog Screen — #/blog/{slug}
   ============================================================================
   Symptom-shaped articles that bridge the SEO landing's symptom cards to
   a car-scoped discovery page. The blog is general (car-agnostic content);
   the bottom CTA hands off to a discovery URL where the car context engages.
   Production pattern: blog links to discovery, not products, because without
   a selected car a product link is ambiguous ("for WHICH car?"). See
   [[speero-car-is-the-location]] in memory for the framing.
   ============================================================================ */
/* Demo screen for picking the position-filter drawer shape — Zeyad-only
   surface, lives at #/pos-demo. Renders four launcher cards, each opens
   the picker with a different shape variant so the trade-offs can be
   compared by *feel*, not by description. Hardcoded available-position
   counts so every glyph shows up in every variant. */
function PositionShapesDemo() {
  const [openVariant, setOpenVariant] = useState(null);
  const demoAvailable = useMemo(() => ({
    FR: 12, FL: 11, BR: 9, BL: 8, FP: 5, BP: 4, F: 24, B: 18, L: 6, R: 7,
  }), []);

  // Clear-interaction variants — each card pre-seeds an active position and
  // exposes a different gesture for clearing it. Tap "إعادة" to re-arm
  // any card after testing. The picker variant (C) opens its own sheet.
  const [clearA, setClearA] = useState("FR"); // × in pill
  const [clearB, setClearB] = useState("FR"); // tap pill to clear
  const [clearC, setClearC] = useState("FR"); // clear row in picker
  const [clearD, setClearD] = useState("FR"); // long-press to clear
  const [clearCOpen, setClearCOpen] = useState(false);
  const [longHinted, setLongHinted] = useState(false);
  const longPressRef = useRef(null);
  const onLongStart = () => {
    longPressRef.current = setTimeout(() => {
      setClearD(null);
      longPressRef.current = null;
    }, 500);
  };
  const onLongEnd = () => {
    if (longPressRef.current) {
      clearTimeout(longPressRef.current);
      longPressRef.current = null;
      setLongHinted(true);
      setTimeout(() => setLongHinted(false), 1600);
    }
  };

  // Mirror DiscoverScreen's --dsc-carbar-h tracking so the drawer's top
  // calc lands exactly under the car-bar on this screen too.
  const carbarRef = useRef(null);
  useEffect(() => {
    const el = carbarRef.current;
    if (!el || !("ResizeObserver" in window)) return;
    const setH = () => {
      document.documentElement.style.setProperty("--dsc-carbar-h", el.offsetHeight + "px");
    };
    setH();
    const ro = new ResizeObserver(setH);
    ro.observe(el);
    return () => {
      ro.disconnect();
      document.documentElement.style.removeProperty("--dsc-carbar-h");
    };
  }, []);

  const variants = [
    { id: "float",   label: "Floating panel",     desc: "12px gap من كل الحواف، أربع زوايا مدورة" },
    { id: "sweep",   label: "Swept leading edge", desc: "زاوية علوية كبيرة 40px، سفلية صغيرة 10px" },
    { id: "capsule", label: "Capsule edge",       desc: "الحافة اليسرى منحنى واحد كبير" },
    { id: "tab",     label: "Pull-tab notch",     desc: "مقبض دائري بارز في منتصف الحافة" },
  ];

  return (
    <div className="pos-demo">
      <div ref={carbarRef} className="car-bar dsc-carbar">
        <img className="car-bar-photo" src={CURRENT_CAR.image} alt={CURRENT_CAR.name} />
        <div className="car-bar-body">
          <div className="car-bar-name">{CURRENT_CAR.name}</div>
        </div>
      </div>
      <div className="pos-demo-body">
        <h2 className="pos-demo-title">جرّب أشكال فلتر الجهة</h2>
        <p className="pos-demo-sub">اضغط على كل خيار لمعاينة شكل الدرج المنبثق ثم اختر الأنسب.</p>
        <div className="pos-demo-list">
          {variants.map((v) => (
            <div key={v.id} className="pos-demo-card">
              <div className="pos-demo-card-text">
                <div className="pos-demo-card-name">{v.label}</div>
                <div className="pos-demo-card-desc">{v.desc}</div>
              </div>
              <button className="pos-demo-card-btn" onClick={() => setOpenVariant(v.id)}>
                <span className="pos-demo-card-glyph"><PositionGlyph pos={null} /></span>
                <span>افتح</span>
              </button>
            </div>
          ))}
        </div>
      </div>

      {variants.map((v) => (
        <PositionPickerSheet
          key={v.id}
          open={openVariant === v.id}
          current={null}
          available={demoAvailable}
          onSelect={() => {}}
          onClose={() => setOpenVariant(null)}
          variant={v.id}
        />
      ))}

      {/* ---- Clear interactions ---- */}
      <div className="pos-demo-body" style={{ paddingTop: 8 }}>
        <h2 className="pos-demo-title">أساليب إلغاء التحديد</h2>
        <p className="pos-demo-sub">جرّب كل أسلوب على الـ pill النشط. اضغط "إعادة" لاسترجاع الحالة.</p>
        <div className="pos-demo-list">
          {/* A — × in pill */}
          <div className="pos-demo-card pos-demo-card-stack">
            <div className="pos-demo-card-text">
              <div className="pos-demo-card-name">× داخل الـ pill</div>
              <div className="pos-demo-card-desc">زر صغير × بجانب الأيقونة. ضغطة واحدة على × لإلغاء التحديد.</div>
            </div>
            <div className="pos-demo-row">
              <button
                className={"dsc-control dsc-pos-control dsc-pos-control--withx" + (clearA ? " is-active" : "")}
                onClick={() => setClearA(clearA)}
                aria-label="الجهة"
              >
                <span className="dsc-pos-glyph"><PositionGlyph pos={clearA} /></span>
                {!clearA && <span>الجهة</span>}
                {clearA && (
                  <span
                    className="dsc-pos-clear"
                    role="button"
                    aria-label="إلغاء التحديد"
                    onClick={(e) => { e.stopPropagation(); setClearA(null); }}
                  ><IconClose /></span>
                )}
              </button>
              <button className="pos-demo-reset" onClick={() => setClearA("FR")}>إعادة</button>
            </div>
          </div>

          {/* B — single tap clears */}
          <div className="pos-demo-card pos-demo-card-stack">
            <div className="pos-demo-card-text">
              <div className="pos-demo-card-name">ضغطة واحدة على الـ pill</div>
              <div className="pos-demo-card-desc">الضغط على الأيقونة النشطة يلغي التحديد مباشرة. لتغيير الجهة لازم تفتح الفلتر من مكان آخر.</div>
            </div>
            <div className="pos-demo-row">
              <button
                className={"dsc-control dsc-pos-control" + (clearB ? " is-active" : "")}
                onClick={() => setClearB(null)}
                aria-label="الجهة"
              >
                <span className="dsc-pos-glyph"><PositionGlyph pos={clearB} /></span>
                {!clearB && <span>الجهة</span>}
              </button>
              <button className="pos-demo-reset" onClick={() => setClearB("FR")}>إعادة</button>
            </div>
          </div>

          {/* C — clear row in picker */}
          <div className="pos-demo-card pos-demo-card-stack">
            <div className="pos-demo-card-text">
              <div className="pos-demo-card-name">صف "عرض الكل" داخل الفلتر</div>
              <div className="pos-demo-card-desc">يظل الـ pill نظيف. عند فتح الفلتر يظهر صف أول للإلغاء.</div>
            </div>
            <div className="pos-demo-row">
              <button
                className={"dsc-control dsc-pos-control" + (clearC ? " is-active" : "")}
                onClick={() => setClearCOpen(true)}
                aria-label="الجهة"
              >
                <span className="dsc-pos-glyph"><PositionGlyph pos={clearC} /></span>
                {!clearC && <span>الجهة</span>}
              </button>
              <button className="pos-demo-reset" onClick={() => setClearC("FR")}>إعادة</button>
            </div>
          </div>

          {/* D — long-press clears */}
          <div className="pos-demo-card pos-demo-card-stack">
            <div className="pos-demo-card-text">
              <div className="pos-demo-card-name">ضغطة طويلة (long-press)</div>
              <div className="pos-demo-card-desc">امسك الـ pill لنصف ثانية لإلغاء التحديد. الضغطة العادية تفتح الفلتر.</div>
            </div>
            <div className="pos-demo-row">
              <button
                className={"dsc-control dsc-pos-control dsc-pos-control--longpress" + (clearD ? " is-active" : "")}
                onPointerDown={clearD ? onLongStart : undefined}
                onPointerUp={clearD ? onLongEnd : undefined}
                onPointerLeave={clearD ? onLongEnd : undefined}
                onPointerCancel={clearD ? onLongEnd : undefined}
                aria-label="الجهة (امسك للإلغاء)"
              >
                <span className="dsc-pos-glyph"><PositionGlyph pos={clearD} /></span>
                {!clearD && <span>الجهة</span>}
              </button>
              <button className="pos-demo-reset" onClick={() => setClearD("FR")}>إعادة</button>
              {longHinted && <span className="pos-demo-hint">امسك أطول</span>}
            </div>
          </div>
        </div>
      </div>

      <PositionPickerSheet
        open={clearCOpen}
        current={clearC}
        available={demoAvailable}
        onSelect={(code) => setClearC(code)}
        onClose={() => setClearCOpen(false)}
        showClearRow={true}
      />

      {/* ---- Filter content presentation variants — sort widget ---- */}
      <div className="pos-demo-body" style={{ paddingTop: 8 }}>
        <h2 className="pos-demo-title">شكل محتوى الفلتر: الترتيب</h2>
        <p className="pos-demo-sub">عرض السهم بدلاً من تكرار كلمة "السعر" يوفّر مساحة ويستفيد من الاتجاه البصري. مقارنة الأشكال:</p>
        <div className="pos-demo-list">
          <SortContentDemoCard
            name="الحالي: تسميات كاملة"
            desc="ثلاث شرائح بتسميات نصية. واضح لكن متكرّر."
            preview="full"
          />
          <SortContentDemoCard
            name="أسهم + تسمية"
            desc="السعر يظهر مرتين لكن مع سهم صغير يوضّح الاتجاه. توازن بين الوضوح والإيجاز."
            preview="arrowLabel"
          />
          <SortContentDemoCard
            name="السعر شريحة واحدة + اتجاهان"
            desc="السعر مرة واحدة، الاتجاه يُختار من زرّين داخل نفس المجموعة. أكثر إيجازاً."
            preview="combined"
          />
          <SortContentDemoCard
            name="قائمة عمودية"
            desc="كل خيار في سطر مستقل مع دائرة اختيار. أقرب للقوائم التقليدية، يأخذ ارتفاعاً أكبر."
            preview="radio"
          />
        </div>
      </div>

      {/* ---- Filter panel shape variants ---- */}
      <div className="pos-demo-body" style={{ paddingTop: 8 }}>
        <h2 className="pos-demo-title">أساليب عرض الفلتر</h2>
        <p className="pos-demo-sub">قارن الأشكال. كل بطاقة تفتح لوحة الفلتر بأسلوب مختلف، مع بيانات تجريبية مطبّقة.</p>
        <div className="pos-demo-list">
          {[
            { id: null,        name: "الحالي: درج سفلي (88vh)",   desc: "ينزلق من الأسفل، يغطي حتى 88% من الشاشة. مساحة كبيرة، لكن النتائج خلفه مختفية." },
            { id: "compact",   name: "درج سفلي مختصر (70vh)",      desc: "نفس الشكل لكن أقل ارتفاعاً. يصلح لمجموعة فلاتر صغيرة كالحالية." },
            { id: "side",      name: "درج جانبي (من اليمين)",        desc: "ينزلق من الجانب مثل درج الجهة. متناسق بصرياً مع الفلتر الثاني." },
            { id: "anchored",  name: "نافذة منبثقة من الزر",         desc: "تظهر صغيرة بجانب زر الفلتر. النتائج خلفها تبقى ظاهرة بالكامل." },
          ].map((v) => (
            <FilterPanelDemoCard key={v.id || "default"} variant={v.id} name={v.name} desc={v.desc} />
          ))}
        </div>
      </div>

      {/* ---- Active-state treatments ---- */}
      <div className="pos-demo-body" style={{ paddingTop: 8 }}>
        <h2 className="pos-demo-title">شكل الحالة النشطة</h2>
        <p className="pos-demo-sub">كل بطاقة تعرض الـ pill في الحالة النشطة بأسلوب مختلف. اضغط على الـ pill لمشاهدة الانتقال بين النشط/غير النشط.</p>
        <div className="pos-demo-list">
          {[
            { id: "outline",   name: "حدّ غامق (الحالي)",     desc: "إطار أسود + خلفية رمادية فاتحة. هادئ، يتسق مع باقي أزرار التحكم." },
            { id: "solid",     name: "خلفية سوداء (مقلوب)",  desc: "حبة سوداء كاملة + أيقونة بيضاء. تباين عالٍ، يقرأ كحالة محددة بقوة." },
            { id: "red",       name: "لمسة سبيرو الحمراء",   desc: "إطار وخلفية بدرجات حمراء خفيفة. يربط الحالة النشطة بالهوية." },
            { id: "tab",       name: "خط سفلي أحمر",         desc: "بدون تغيير الإطار، فقط خط أحمر صغير تحت الأيقونة كمؤشر تبويب." },
          ].map((v) => (
            <ActiveStateDemoCard key={v.id} variant={v.id} name={v.name} desc={v.desc} />
          ))}
        </div>
      </div>

      {/* ---- Drawer width variants ---- */}
      <div className="pos-demo-body" style={{ paddingTop: 8 }}>
        <h2 className="pos-demo-title">عرض درج الجهة</h2>
        <p className="pos-demo-sub">قارن العروض المختلفة. كل خيار يفتح الدرج بعرض مختلف. الحالي هو الأوسع.</p>
        <div className="pos-demo-list">
          {[
            { id: null,         name: "الحالي: 48vw / حد أقصى 180px (الإنتاج)", desc: "نحيف. العدّاد بين قوسين بجانب التصنيف، يوفر العرض." },
            { id: "wwide",      name: "السابق: 62vw / حد أقصى 260px",            desc: "العرض الذي كان في الإنتاج قبل التضييق. مرجع للمقارنة." },
            { id: "wcompact",   name: "متوسط: 56vw / حد أقصى 220px",             desc: "بين الحالي والسابق. أكثر راحة للقراءة، أقل من 260px." },
            { id: "wmini",      name: "صغير: 38vw / حد أقصى 140px",              desc: "تقريباً نصف العرض السابق. نخفي العدّاد لإيواء التصنيف." },
          ].map((v) => (
            <WidthDemoCard key={v.id || "current"} variant={v.id} name={v.name} desc={v.desc} available={demoAvailable} />
          ))}
        </div>
      </div>

      {/* ---- Applied filters summary — styling variants ---- */}
      <div className="pos-demo-body" style={{ paddingTop: 8 }}>
        <h2 className="pos-demo-title">شكل ملخّص الفلاتر المطبّقة</h2>
        <p className="pos-demo-sub">المعاينة تستخدم نفس البيانات بنفس ترتيب الفلتر: بديل (صيني) + السعر من الأقل + إكسبرس.</p>
        <div className="pos-demo-list">
          {[
            { id: "default",   name: "الحالي: تسمية + نقط",   desc: "نص مفصول بنقط (·) مع تسمية \"الفلاتر:\" في البداية. هادئ، سهل المسح بصرياً." },
            { id: "underline", name: "خط تحت كل فلتر",          desc: "كل قيمة تحتها خط رفيع. شكل خفيف يلمّح للنقر دون وزن البطاقات." },
            { id: "section",   name: "مجموعات بفواصل عمودية", desc: "تجميع منطقي: النوع | الترتيب | التوصيل. يوضّح أي قطعة فلتر من أي عائلة." },
            { id: "boxed",     name: "بطاقة بخط حمراء",         desc: "ملخّص داخل بطاقة بخلفية ناعمة وخط جانبي أحمر بهوية سبيرو. القيم بخط غامق." },
            { id: "tags",      name: "علامات شفافة",            desc: "كل قيمة داخل إطار رفيع شفاف. شكل الكبسولة بدون وزن البطاقات." },
          ].map((v) => (
            <AppliedSummaryDemoCard key={v.id} variant={v.id} name={v.name} desc={v.desc} />
          ))}
        </div>
      </div>
    </div>
  );
}

/* Query-indicator demo — #/query-demo. Five variants of where to put
   the "Results for {q}" indicator on the Discover search page. Each
   card mocks a slimmed Discover header so placement + copy can be
   compared by feel. The mocks are visual only — no interactivity. */
function QueryIndicatorDemo() {
  const Q = "فحمات أمامية";
  const Mock = ({ headerExtra, beforeChips, beforeControls, breadcrumb, searchText, searchHasQ }) => (
    <div className="qid-demo-mock">
      <div className="qid-mock-carbar">تشالنجر <span style={{ flex: 1 }} /></div>
      <div className={"qid-mock-search" + (searchHasQ ? " has-q" : "")}>
        <IconSearch />
        <span>{searchText}</span>
      </div>
      {headerExtra}
      {breadcrumb}
      {beforeChips}
      <div className="qid-mock-chips">
        <div className="qid-mock-chip is-active">الكل</div>
        <div className="qid-mock-chip">فرامل</div>
        <div className="qid-mock-chip">مساعدات</div>
        <div className="qid-mock-chip">تكييف</div>
      </div>
      {beforeControls}
      <div className="qid-mock-controls">
        <div className="qid-mock-pill">الجهة</div>
        <div className="qid-mock-pill">فلتر</div>
      </div>
      <div className="qid-mock-results">
        <div className="qid-mock-row" />
        <div className="qid-mock-row" />
      </div>
    </div>
  );

  return (
    <div className="qid-demo">
      <div className="qid-demo-body">
        <h2 className="qid-demo-title">إظهار كويري البحث في صفحة النتائج</h2>
        <p className="qid-demo-sub">
          لما المستخدم يوصل النتائج عبر البحث، فين نظهر له كلمة "نتائج عن «{Q}»"؟
          خمسة مواضع/صياغات للمقارنة بالإحساس.
        </p>

        <div className="qid-demo-list">
          {/* A — Inside the search pill only */}
          <div className="qid-demo-card">
            <div className="qid-demo-card-head">
              <div className="qid-demo-card-name">A · داخل شريط البحث فقط</div>
              <div className="qid-demo-card-desc">
                الكلمة تظهر في شريط البحث مكان النص التلميحي. لا توجد عبارة "نتائج" صريحة.
                الأبسط، لكن سهل الإغفال.
              </div>
            </div>
            <Mock searchText={Q} searchHasQ={true} />
          </div>

          {/* B1 — Line below search bar, formal copy */}
          <div className="qid-demo-card">
            <div className="qid-demo-card-head">
              <div className="qid-demo-card-name">B١ · سطر أسفل شريط البحث (كامل)</div>
              <div className="qid-demo-card-desc">
                «نتائج البحث عن ...» بصياغة كاملة. داخل الـ sticky cluster، يبقى مع التمرير.
              </div>
            </div>
            <Mock
              searchText="ابحث باسم القطعة أو رقمها"
              headerExtra={<div className="qid-indicator">نتائج البحث عن «<b>{Q}</b>»</div>}
            />
          </div>

          {/* B2 — Same place, compact copy */}
          <div className="qid-demo-card">
            <div className="qid-demo-card-head">
              <div className="qid-demo-card-name">B٢ · سطر أسفل شريط البحث (مختصر)</div>
              <div className="qid-demo-card-desc">
                «نتائج لـ ...» موجز، يقلل الازدحام البصري.
              </div>
            </div>
            <Mock
              searchText="ابحث باسم القطعة أو رقمها"
              headerExtra={<div className="qid-indicator">نتائج لـ «<b>{Q}</b>»</div>}
            />
          </div>

          {/* C — Above the controls row */}
          <div className="qid-demo-card">
            <div className="qid-demo-card-head">
              <div className="qid-demo-card-name">C · فوق صف الأدوات</div>
              <div className="qid-demo-card-desc">
                أقرب بصرياً للنتائج، لكن يختفي مع التمرير لأنه خارج الـ sticky cluster.
              </div>
            </div>
            <Mock
              searchText="ابحث باسم القطعة أو رقمها"
              beforeControls={<div className="qid-indicator in-controls">نتائج لـ «<b>{Q}</b>»</div>}
            />
          </div>

          {/* D — Inside breadcrumb */}
          <div className="qid-demo-card">
            <div className="qid-demo-card-head">
              <div className="qid-demo-card-name">D · داخل مسار التنقل</div>
              <div className="qid-demo-card-desc">
                الرئيسية / بحث / «...» مدمج مع نمط breadcrumb الموجود.
                يصلح لمسار <span className="mono">/search?q=</span> فقط (المسار الحر بدون قسم).
              </div>
            </div>
            <Mock
              searchText="ابحث باسم القطعة أو رقمها"
              breadcrumb={
                <div className="qid-mock-breadcrumb">
                  الرئيسية / بحث / «<b>{Q}</b>»
                </div>
              }
            />
          </div>
        </div>
      </div>
    </div>
  );
}

/* PDP hero variants demo — #/pdp-hero-demo.
   Spare-parts photos are inconsistent in quality across suppliers, so the
   title + fitment + price ("trust trio") should anchor confidence before the
   image does. Three live mocks compare how aggressively to demote the image:

     A · Title above   — order swap, image keeps full-bleed prominence
     B · Hero card     — title+fitment+price+CTA unified as a card; image
                          becomes a smaller framed thumbnail below
     C · Text-first    — same hero card; image moves out of the hero region
                          entirely (lives further down as صور المنتج)

   Same sample part across all three so the comparison is purely about
   hierarchy, not content. */
function PdpHeroDemo() {
  const SAMPLE = {
    title: "طقم فحمات فرامل أمامية",
    oem: "04465B0280",
    make: "alt",
    origin: "صيني",
    rating: 4.7,
    reviewCount: 124,
    price: "420",
    oldPrice: "525",
    kind: "pads",
  };
  const CAR = "تشالنجر";
  const discount = Math.round((1 - 420 / 525) * 100);

  const Frame = ({ children }) => (
    <div className="pdph-frame">
      <div className="pdph-frame-carbar">
        <span className="pdph-frame-carbar-chev">‹</span>
        <span className="pdph-frame-carbar-thumb" />
        <span className="pdph-frame-carbar-name">{CAR}</span>
        <span className="pdph-frame-carbar-cart" />
      </div>
      <div className="pdph-frame-search">
        <span className="pdph-frame-search-ico" />
        <span>ابحث باسم القطعة أو رقمها</span>
      </div>
      <div className="pdph-frame-body">{children}</div>
    </div>
  );

  const TitleBlock = ({ size = "md" }) => (
    <div className={"pdph-title-block pdph-title-" + size}>
      <h3 className="pdph-title">{SAMPLE.title}</h3>
      <div className="pdph-oem mono">{SAMPLE.oem}</div>
      <div className="pdph-meta">
        <MakeTag make={SAMPLE.make} origin={SAMPLE.origin} />
        <span className="pdph-rating">
          <PdpStars value={SAMPLE.rating} size={12} />
          <span className="mono">{SAMPLE.rating.toFixed(1)}</span>
          <span className="pdph-rating-count">({SAMPLE.reviewCount})</span>
        </span>
      </div>
    </div>
  );

  const FitStrip = () => (
    <div className="pdph-fit">
      <span className="pdph-fit-ico"><IconCheck /></span>
      <span>تركب على {CAR} <span className="mono">2014–2024</span></span>
    </div>
  );

  const PriceBlock = ({ compact = false }) => (
    <div className={"pdph-price-block" + (compact ? " is-compact" : "")}>
      <div className="pdph-price-row">
        <span className="pdph-price mono">{SAMPLE.price}<Riyal /></span>
        <span className="pdph-was mono">{SAMPLE.oldPrice} <Riyal /></span>
        <span className="pdph-off">-{discount}%</span>
      </div>
    </div>
  );

  const Cta = () => <button className="pdph-cta">أضف للسلة</button>;

  const ImageHero = () => (
    <div className="pdph-img pdph-img-hero">
      <ProductImage kind={SAMPLE.kind} />
    </div>
  );
  const ImageThumb = () => (
    <div className="pdph-img pdph-img-thumb">
      <ProductImage kind={SAMPLE.kind} />
    </div>
  );
  const ImageMid = () => (
    <div className="pdph-img pdph-img-mid">
      <ProductImage kind={SAMPLE.kind} />
    </div>
  );

  /* Fitment + guarantee — combined trust block right before the CTA in
     variant C. Two rows: ✓ fits your car, 🛡 we guarantee the match. The
     image sits above this; the CTA below. Reads as "see it, trust it, buy." */
  const FitGuarantee = () => (
    <div className="pdph-fitguard">
      <div className="pdph-fitguard-row pdph-fitguard-fit">
        <span className="pdph-fitguard-ico"><IconCheck /></span>
        <span>تركب على {CAR} <span className="mono">2014–2024</span></span>
      </div>
      <div className="pdph-fitguard-row pdph-fitguard-guard">
        <span className="pdph-fitguard-ico"><IconShield /></span>
        <span>ضمان مطابقة من سبيرو</span>
      </div>
    </div>
  );

  return (
    <div className="pdph-demo">
      <div className="pdph-demo-body">
        <h2 className="pdph-demo-title">عنوان القطعة قبل الصورة (صفحة المنتج)</h2>
        <p className="pdph-demo-sub">
          صور قطع الغيار من الموردين متفاوتة الجودة، فالعنوان والتركيب والسعر هم
          مرساة الثقة الحقيقية. ثلاث صياغات لتخفيض ظهور الصورة بدرجات مختلفة.
          نفس القطعة في الثلاثة. المقارنة عن التسلسل البصري وحده.
        </p>

        {/* A · Order swap — title above image, image keeps its prominence */}
        <div className="pdph-card">
          <div className="pdph-card-head">
            <div className="pdph-card-name">A · العنوان أعلى الصورة</div>
            <div className="pdph-card-desc">
              ترتيب فقط: العنوان والتركيب فوق، الصورة كما هي بحجمها الحالي تحت.
              أقل تغيير، لكن العنوان يصبح أول ما يقرأ.
              <br />
              <b>التسلسل:</b> العنوان · التركيب · الصورة · السعر · أضف للسلة
            </div>
          </div>
          <Frame>
            <TitleBlock size="lg" />
            <FitStrip />
            <ImageHero />
            <PriceBlock />
            <Cta />
          </Frame>
        </div>

        {/* B · Hero card — title+fitment+price unified, image demoted to thumb */}
        <div className="pdph-card">
          <div className="pdph-card-head">
            <div className="pdph-card-name">B · بطاقة هيرو موحدة</div>
            <div className="pdph-card-desc">
              العنوان والتركيب والسعر وزر الإضافة في بطاقة واحدة فوق. الصورة
              تنزل لمستطيل أصغر بإطار مرئي. الصورة تظل قريبة لكن بدور مساند.
              <br />
              <b>التسلسل:</b> [العنوان · التركيب · السعر · أضف] · صورة مصغرة
            </div>
          </div>
          <Frame>
            <div className="pdph-herocard">
              <TitleBlock size="lg" />
              <FitStrip />
              <PriceBlock compact />
              <Cta />
            </div>
            <ImageThumb />
          </Frame>
        </div>

        {/* C · Narrative flow — title+price → image → fitment+guarantee → CTA.
            Image is a visual confirmation step between identification and commit,
            not a hero. The fitment+guarantee block is the final trust signal
            right before the Add button. */}
        <div className="pdph-card">
          <div className="pdph-card-head">
            <div className="pdph-card-name">C · تسلسل سردي (ثقة قبل الإضافة)</div>
            <div className="pdph-card-desc">
              العنوان والسعر فوق. الصورة دور تأكيد بصري في الوسط. ثم بلوك
              تركيب + ضمان كآخر إشارة ثقة قبل زر الإضافة. كل عنصر يأتي في
              لحظته الطبيعية في قرار الشراء.
              <br />
              <b>التسلسل:</b> العنوان · السعر · الصورة · تركيب + ضمان · أضف للسلة
            </div>
          </div>
          <Frame>
            <div className="pdph-herocard">
              <TitleBlock size="lg" />
              <PriceBlock compact />
            </div>
            <ImageMid />
            <FitGuarantee />
            <Cta />
          </Frame>
        </div>
      </div>
    </div>
  );
}

/* Meter wording demo — #/meter-demo.
   Locked variant N4 ("إيجابي مباشر"). Renders the full fitguard panel —
   meter + status text + body + optional VIN action — across all 4 states
   (low → medium → high → verified) so the complete user surface is visible
   at once. Palette: F (نعناعي → فيروزي → غابي). */
function MeterColorsDemo() {
  const PALETTE = ["#A7F3D0", "#0EA5A4", "#047857"];
  const HEADER = "هل تركب على سيارتك؟";
  // Per-position label config: each tier has an inactive text and an
  // active text. At low/medium positions, the active text is the CTA
  // (and activeIsCta = true → underlined, tappable). At high, the active
  // text is the affirmative tier name. Inactive positions always render
  // their plain tier names.
  const TIERS = [
    { inactive: "منخفض", active: "أدخل رقم الهيكل", activeIsCta: true },
    { inactive: "متوسط", active: "أدخل رقم الهيكل", activeIsCta: true },
    { inactive: "مضمون", active: "مضمون", activeIsCta: false },
  ];

  const STATES = [
    {
      key: "low",
      label: "حالة منخفضة",
      level: 1,
      body: "نؤكد التركيب لك عبر رقم الهيكل.",
    },
    {
      key: "medium",
      label: "حالة متوسطة",
      level: 2,
      body: "للتأكد التام، نراجع التركيب عبر رقم الهيكل.",
    },
    {
      key: "high",
      label: "حالة عالية (نظام)",
      level: 3,
      body: "ضمان سبيرو: إن لم تطابق سيارتك، نرجعها خلال 14 يوماً من تاريخ الاستلام.",
    },
    {
      key: "verified",
      label: "موثّق برقم الهيكل",
      level: 3,
      body: "ضمان سبيرو: تم التحقق وفقاً لرقم الهيكل، وإرجاع خلال 14 يوماً إن لم تطابق.",
      vinMask: "AB123",
    },
    /* 5th case: VIN check found that THIS part doesn't fit, but Speero
       has the correct variant in catalog. UI: honest "doesn't fit" status,
       inline alternative card with the matching SKU, primary CTA to switch.
       The vinmask stays — preserves trust that we did check. */
    {
      key: "mismatch",
      label: "غير متوافقة. البديل المطابق متوفر",
      level: 0,
      isMismatch: true,
      mismatchStatus: "هذه القطعة لا تركب على سيارتك",
      body: "تم التحقق وفقاً لرقم الهيكل. هذه القطعة لا تطابق تشالنجر 2020. وجدنا البديل المطابق:",
      vinMask: "AB123",
      alternative: {
        title: "صدام أمامي V8 SXT",
        price: "420",
        note: "موثّق برقم هيكل سيارتك",
      },
      actionLabel: "انتقل للبديل المطابق",
    },
  ];

  return (
    <div className="mcd-demo">
      <div className="mcd-demo-body">
        <h2 className="mcd-demo-title">N4 · القسم كاملاً عبر الحالات</h2>
        <p className="mcd-demo-sub">
          صياغة N4 («إيجابي مباشر») مع القسم بكامله: الميتر، نصّ الحالة، الجسم،
          وفعل الـVIN عند الحاجة. أربع حالات تعرض تجربة المستخدم من البداية إلى
          التحقق:
          <br />
          <b>منخفضة</b> ← <b>متوسطة</b> ← <b>عالية بتأكيد النظام</b> ← <b>موثّقة برقم الهيكل</b>.
          <br />
          الميتر يجاوب على السؤال في الترويسة في كل حالة، والنصّ يكمل بقية الإجابة.
        </p>

        <div className="mcd-card">
          <div className="mcd-card-head">
            <div className="mcd-card-name">N4 · إيجابي مباشر</div>
            <div className="mcd-card-desc">
              «أدخل رقم الهيكل» أمر مباشر يطلب الفعل للأسفل، «نعم، مضمون» يجاوب
              على سؤال الترويسة حرفياً للأعلى.
            </div>
          </div>

          {STATES.map((s) => (
            <div key={s.key} className="mcd-state">
              <div className="mcd-state-label">{s.label}</div>
              <div className="mcd-card-panel mcd-card-panel--full">
                <div className="mcd-label">{HEADER}</div>
                <div className="mcd-meter">
                  {PALETTE.map((c, i) => (
                    <div
                      key={i}
                      className="mcd-meter-seg"
                      style={{ background: i === s.level - 1 ? c : "#E5E7EB" }}
                    />
                  ))}
                </div>
                <div className="mcd-meter-labels">
                  {[1, 2, 3].map((n) => {
                    const isActive = n === s.level;
                    const isPassed = n < s.level;
                    const tier = TIERS[n - 1];
                    const isCta = isActive && tier.activeIsCta;
                    const text = isActive ? tier.active : tier.inactive;
                    if (isCta) {
                      return (
                        <button
                          key={n}
                          type="button"
                          className="mcd-meter-labels-item is-active is-cta"
                        >
                          {text}
                        </button>
                      );
                    }
                    return (
                      <span
                        key={n}
                        className={
                          "mcd-meter-labels-item" +
                          (isActive ? " is-active" : "") +
                          (isPassed ? " is-passed" : "")
                        }
                      >
                        {text}
                        {isActive && n === 3 && (
                          <span className="mcd-meter-labels-badge" aria-hidden="true">
                            <IconCheck />
                          </span>
                        )}
                      </span>
                    );
                  })}
                </div>
                {s.isMismatch && (
                  <div className="mcd-mismatch-status">
                    <span className="mcd-mismatch-icon" aria-hidden="true">✕</span>
                    <span>{s.mismatchStatus}</span>
                  </div>
                )}
                <p className="mcd-body">{s.body}</p>
                {s.alternative && (
                  <div className="mcd-alt-card">
                    <div className="mcd-alt-thumb" aria-hidden="true" />
                    <div className="mcd-alt-body">
                      <div className="mcd-alt-title">{s.alternative.title}</div>
                      <div className="mcd-alt-price">
                        <span className="mono">{s.alternative.price}</span><Riyal />
                      </div>
                      <div className="mcd-alt-note">
                        <span className="mcd-vinmask-ico"><IconCheck /></span>
                        <span>{s.alternative.note}</span>
                      </div>
                    </div>
                  </div>
                )}
                {s.actionLabel && (
                  <button type="button" className="mcd-action-primary">
                    {s.actionLabel}
                  </button>
                )}
                {s.vinMask && (
                  <div className="mcd-vinmask">
                    <span className="mcd-vinmask-ico"><IconCheck /></span>
                    <span>رقم هيكل <span className="mono">{s.vinMask}</span></span>
                  </div>
                )}
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* Companion-items demo — #/companion-demo.
   Four variants of how the "موصى به مع" bullet in PDP details can become a
   purchase affordance. Same data across all four (طقم فحمات' brake disc +
   brake fluid). The actual cart wires through onAddToCart so the global cart
   count updates live as Zeyad taps. */
function CompanionDemo({ onAddToCart }) {
  // Brake-system companions sourced from PRODUCTS (defined near the main
  // products map). Each is a real entry, so navigation in variant D and
  // findProduct lookups in variants A-C all work.
  const flat = [
    { key: "disc",  label: "قرص فرامل أمامي" },
    { key: "fluid", label: "سائل فرامل DOT4" },
  ];
  // Picker variant (C) — one label can map to multiple SKU options. The user
  // chooses make/origin before adding. Mirrors how a real PDP would surface
  // OEM-vs-alt for each companion via Typesense facets.
  const picker = [
    {
      label: "قرص فرامل أمامي",
      options: [
        { key: "disc",    make: "oem", origin: null },
        { key: "discAlt", make: "alt", origin: "صيني" },
      ],
    },
    {
      label: "سائل فرامل",
      options: [
        { key: "fluid",    make: "oem", origin: null },
        { key: "fluidAlt", make: "alt", origin: "صيني" },
      ],
    },
  ];

  // Track which item was just added → green pulse + checkmark + revert after
  // 1500ms so the user knows the tap landed.
  const [added, setAdded] = useState({});
  const tap = (key) => {
    if (onAddToCart && PRODUCTS[key]) onAddToCart(key);
    setAdded((a) => ({ ...a, [key]: true }));
    setTimeout(() => setAdded((a) => { const n = { ...a }; delete n[key]; return n; }), 1500);
  };

  // Variant C — which label's picker is open (one at a time).
  const [openPicker, setOpenPicker] = useState(null);

  // Render helper: the existing PDP bullet shape (red dot + label : value),
  // so each preview reads like a slice of a real PDP details panel.
  const Bullet = ({ label, children }) => (
    <li>
      <span className="pdp-spec-dot" />
      <span>
        <strong className="pdp-spec-label">{label}:</strong>{" "}
        {children}
      </span>
    </li>
  );

  return (
    <div className="cmp-demo">
      <div className="cmp-demo-body">
        <h2 className="cmp-demo-title">"موصى به مع" قابلة للشراء — أربع صياغات</h2>
        <p className="cmp-demo-sub">
          نفس قائمة القطع التكميلية (قرص + سائل فرامل) معروضة بأربع أساليب مختلفة
          لجعلها قابلة للإضافة من داخل قسم التفاصيل في صفحة المنتج. اضغط على أي
          عنصر لرؤية كيف يتصرف، وراقب عدّاد السلة في الأعلى يرتفع.
        </p>

        {/* Variant A — inline pills, one-tap add */}
        <div className="cmp-card">
          <div className="cmp-card-head">
            <div className="cmp-card-name">أ · زرّ مدمج (إضافة بنقرة)</div>
            <div className="cmp-card-desc">
              زرّ صغير لكل قطعة، يضيفها للسلة بنقرة واحدة بالنوع الافتراضي (أصلي
              عادةً). أقل احتكاك، لكن المستخدم لا يختار الصانع قبل الإضافة.
            </div>
          </div>
          <div className="cmp-card-body">
            <div className="cmp-preview-frame">
              <div className="cmp-preview-eyebrow">التفاصيل</div>
              <ul className="pdp-specs">
                <Bullet label="موصى به مع">
                  <div className="cmp-pills">
                    {flat.map((c) => {
                      const p = PRODUCTS[c.key];
                      const isAdded = added[c.key];
                      return (
                        <button
                          key={c.key}
                          className={"cmp-pill" + (isAdded ? " is-added" : "")}
                          onClick={() => tap(c.key)}
                        >
                          <span className="cmp-pill-plus">{isAdded ? "✓" : "+"}</span>
                          {c.label} · <span className="mono">{p.price}</span><Riyal />
                        </button>
                      );
                    })}
                  </div>
                </Bullet>
              </ul>
            </div>
          </div>
        </div>

        {/* Variant B — four sub-flavors of the buy-together card pattern. */}

        {/* ب١ — horizontal rail of mini cards (the baseline). */}
        <div className="cmp-card">
          <div className="cmp-card-head">
            <div className="cmp-card-name">ب١ · شريط بطاقات أفقي (الأساس)</div>
            <div className="cmp-card-desc">
              بطاقات مصغّرة بصورة وسعر وزرّ إضافة، شريط أفقي قابل للتمرير. كل
              معلومة ظاهرة قبل القرار. هذا هو شكل Amazon "Frequently Bought
              Together".
            </div>
          </div>
          <div className="cmp-card-body">
            <div className="cmp-preview-frame">
              <div className="cmp-preview-eyebrow">التفاصيل · موصى به مع</div>
              <div className="cmp-rail">
                {flat.map((c) => {
                  const p = PRODUCTS[c.key];
                  const isAdded = added["rail-" + c.key];
                  return (
                    <div className="cmp-rail-card" key={c.key} onClick={() => navigate("/p/" + c.key)}>
                      <div className="cmp-rail-img"><ProductImage kind={p.kind} /></div>
                      <div className="cmp-rail-title">{c.label}</div>
                      <div className="cmp-rail-meta">
                        <MakeTag make={p.make} origin={p.origin} />
                        <span className="cmp-rail-price">{p.price}<Riyal /></span>
                      </div>
                      <button
                        className={"cmp-rail-add" + (isAdded ? " is-added" : "")}
                        onClick={(e) => {
                          e.stopPropagation();
                          if (onAddToCart) onAddToCart(c.key);
                          setAdded((a) => ({ ...a, ["rail-" + c.key]: true }));
                          setTimeout(() => setAdded((a) => { const n = { ...a }; delete n["rail-" + c.key]; return n; }), 1500);
                        }}
                      >
                        {isAdded ? "في السلة ✓" : "أضف للسلة"}
                      </button>
                    </div>
                  );
                })}
              </div>
            </div>
          </div>
        </div>

        {/* ب٢ — vertical rows, all visible without scroll. */}
        <div className="cmp-card">
          <div className="cmp-card-head">
            <div className="cmp-card-name">ب٢ · صفوف عمودية (الكل ظاهر)</div>
            <div className="cmp-card-desc">
              نفس المعلومات لكن مكدّسة عمودياً، لا تمرير أفقي. تأخذ مساحة عمودية
              أكثر مقابل وضوح أعلى — مناسبة عندما القطع التكميلية ٢-٣ فقط.
            </div>
          </div>
          <div className="cmp-card-body">
            <div className="cmp-preview-frame">
              <div className="cmp-preview-eyebrow">التفاصيل · موصى به مع</div>
              <div className="cmp-rows">
                {flat.map((c) => {
                  const p = PRODUCTS[c.key];
                  const isAdded = added["row-" + c.key];
                  return (
                    <div className="cmp-row" key={c.key}>
                      <div className="cmp-row-img"><ProductImage kind={p.kind} /></div>
                      <div className="cmp-row-body">
                        <span className="cmp-row-title">{c.label}</span>
                        <div className="cmp-row-meta">
                          <MakeTag make={p.make} origin={p.origin} />
                          <span className="cmp-row-price">{p.price}<Riyal /></span>
                        </div>
                      </div>
                      <button
                        className={"cmp-row-add" + (isAdded ? " is-added" : "")}
                        onClick={() => {
                          if (onAddToCart) onAddToCart(c.key);
                          setAdded((a) => ({ ...a, ["row-" + c.key]: true }));
                          setTimeout(() => setAdded((a) => { const n = { ...a }; delete n["row-" + c.key]; return n; }), 1500);
                        }}
                      >
                        {isAdded ? "في السلة ✓" : "أضف"}
                      </button>
                    </div>
                  );
                })}
              </div>
            </div>
          </div>
        </div>

        {/* ب٣ — compact tiles with + icon on thumbnail. Most minimal vertical
            space. Tap-anywhere adds (silent OEM default). */}
        <div className="cmp-card">
          <div className="cmp-card-head">
            <div className="cmp-card-name">ب٣ · مربعات مدمجة برمز +</div>
            <div className="cmp-card-desc">
              أصغر بصمة عمودية. الرمز "+" يعلو الصورة، الضغط في أي مكان على
              المربع يضيف القطعة (الأصلي افتراضياً). لا يعرض النوع — مناسب
              للقطع منخفضة الحساسية.
            </div>
          </div>
          <div className="cmp-card-body">
            <div className="cmp-preview-frame">
              <div className="cmp-preview-eyebrow">التفاصيل · موصى به مع</div>
              <div className="cmp-tiles">
                {flat.map((c) => {
                  const p = PRODUCTS[c.key];
                  const isAdded = added["tile-" + c.key];
                  return (
                    <button
                      key={c.key}
                      className={"cmp-tile" + (isAdded ? " is-added" : "")}
                      onClick={() => {
                        if (onAddToCart) onAddToCart(c.key);
                        setAdded((a) => ({ ...a, ["tile-" + c.key]: true }));
                        setTimeout(() => setAdded((a) => { const n = { ...a }; delete n["tile-" + c.key]; return n; }), 1500);
                      }}
                    >
                      <div className="cmp-tile-img">
                        <ProductImage kind={p.kind} />
                        <span className="cmp-tile-plus">{isAdded ? "✓" : "+"}</span>
                      </div>
                      <span className="cmp-tile-title">{c.label}</span>
                      <span className="cmp-tile-price">{p.price}<Riyal /></span>
                    </button>
                  );
                })}
              </div>
            </div>
          </div>
        </div>

        {/* ب٤ — bundle savings framing. Banner above the rail with computed
            savings, "أضف الكل" master button below. Pushes the bundle. */}
        <div className="cmp-card">
          <div className="cmp-card-head">
            <div className="cmp-card-name">ب٤ · إطار توفير الباندل ("أضف الكل")</div>
            <div className="cmp-card-desc">
              نفس شريط ب١ + لافتة "اشترها معاً ووفّر" فوق + زرّ موحّد "أضف الكل"
              تحت. يدفع المستخدم نحو إضافة الباقة كاملة بدل اتخاذ ٢-٣ قرارات
              منفصلة.
            </div>
          </div>
          <div className="cmp-card-body">
            <div className="cmp-preview-frame">
              <div className="cmp-preview-eyebrow">التفاصيل · موصى به مع</div>
              {(() => {
                // Toy bundle savings — 7% off the combined companion total
                // for demo purposes. Production would compute against real
                // bundle pricing rules.
                const subtotal = flat.reduce((s, c) => s + priceNum(PRODUCTS[c.key].price), 0);
                const saving = Math.round(subtotal * 0.07);
                const allKey = "bundle-all";
                const isAllAdded = added[allKey];
                return (
                  <>
                    <div className="cmp-bundle-banner">
                      <span>اشترها معاً ووفّر</span>
                      <span><span className="mono">{fmtPrice(saving)}</span><Riyal /></span>
                    </div>
                    <div className="cmp-rail">
                      {flat.map((c) => {
                        const p = PRODUCTS[c.key];
                        return (
                          <div className="cmp-rail-card" key={c.key} onClick={() => navigate("/p/" + c.key)}>
                            <div className="cmp-rail-img"><ProductImage kind={p.kind} /></div>
                            <div className="cmp-rail-title">{c.label}</div>
                            <div className="cmp-rail-meta">
                              <MakeTag make={p.make} origin={p.origin} />
                              <span className="cmp-rail-price">{p.price}<Riyal /></span>
                            </div>
                          </div>
                        );
                      })}
                    </div>
                    <button
                      className={"cmp-bundle-add-all" + (isAllAdded ? " is-added" : "")}
                      onClick={() => {
                        if (onAddToCart) flat.forEach((c) => onAddToCart(c.key));
                        setAdded((a) => ({ ...a, [allKey]: true }));
                        setTimeout(() => setAdded((a) => { const n = { ...a }; delete n[allKey]; return n; }), 1500);
                      }}
                    >
                      {isAllAdded ? (
                        "تمت إضافة الباقة ✓"
                      ) : (
                        <>أضف الكل · <span className="mono">{fmtPrice(subtotal - saving)}</span><Riyal /></>
                      )}
                    </button>
                  </>
                );
              })()}
            </div>
          </div>
        </div>

        {/* Variant C — underlined names → bottom picker for variants */}
        <div className="cmp-card">
          <div className="cmp-card-head">
            <div className="cmp-card-name">ج · اسم مسطّر يفتح خيارات الصانع</div>
            <div className="cmp-card-desc">
              الاسم رابط، الضغط يكشف عن أصلي/بديل بالأسعار. المستخدم يختار قبل
              الإضافة — مفيد عندما المنشأ مهم (الصيني مقابل التايواني مثلاً).
            </div>
          </div>
          <div className="cmp-card-body">
            <div className="cmp-preview-frame">
              <div className="cmp-preview-eyebrow">التفاصيل</div>
              <ul className="pdp-specs">
                <Bullet label="موصى به مع">
                  {picker.map((c, i) => (
                    <React.Fragment key={c.label}>
                      {i > 0 && <span style={{ color: "var(--muted)", margin: "0 4px" }}>·</span>}
                      <button className="cmp-link" onClick={() => setOpenPicker(openPicker === c.label ? null : c.label)}>
                        {c.label}
                      </button>
                    </React.Fragment>
                  ))}
                </Bullet>
              </ul>
              {openPicker && (() => {
                const c = picker.find((p) => p.label === openPicker);
                return (
                  <div className="cmp-picker">
                    <div className="cmp-picker-title">{c.label} — اختر النوع</div>
                    {c.options.map((opt) => {
                      const p = PRODUCTS[opt.key];
                      const isAdded = added["pick-" + opt.key];
                      return (
                        <div className="cmp-picker-row" key={opt.key}>
                          <div className="cmp-picker-row-info">
                            <span className="cmp-picker-row-title">{p.title}</span>
                            <span className="cmp-picker-row-make"><MakeTag make={opt.make} origin={opt.origin} /></span>
                          </div>
                          <span className="cmp-picker-row-price">{p.price}<Riyal /></span>
                          <button
                            className={"cmp-picker-row-cta" + (isAdded ? " is-added" : "")}
                            onClick={() => {
                              if (onAddToCart) onAddToCart(opt.key);
                              setAdded((a) => ({ ...a, ["pick-" + opt.key]: true }));
                              setTimeout(() => setAdded((a) => { const n = { ...a }; delete n["pick-" + opt.key]; return n; }), 1500);
                            }}
                          >
                            {isAdded ? "في السلة ✓" : "أضف"}
                          </button>
                        </div>
                      );
                    })}
                  </div>
                );
              })()}
            </div>
          </div>
        </div>

        {/* Variant D — names link to PDP, no inline add */}
        <div className="cmp-card">
          <div className="cmp-card-head">
            <div className="cmp-card-name">د · اسم مسطّر ينقل لصفحة المنتج</div>
            <div className="cmp-card-desc">
              لا إضافة مباشرة. الاسم رابط فقط يفتح صفحة المنتج التكميلي، حيث
              المستخدم يقرّر ويضيف من هناك. أبسط تنفيذ، لكن يفقد لحظة "وأنا
              هنا أصلاً".
            </div>
          </div>
          <div className="cmp-card-body">
            <div className="cmp-preview-frame">
              <div className="cmp-preview-eyebrow">التفاصيل</div>
              <ul className="pdp-specs">
                <Bullet label="موصى به مع">
                  {flat.map((c, i) => (
                    <React.Fragment key={c.key}>
                      {i > 0 && <span style={{ color: "var(--muted)", margin: "0 4px" }}>·</span>}
                      <a className="cmp-pdp-link" onClick={() => navigate("/p/" + c.key)} style={{ cursor: "pointer" }}>
                        {c.label}
                      </a>
                    </React.Fragment>
                  ))}
                </Bullet>
              </ul>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* Companion-applied demo — #/companion-pdp-demo.
   Same 7 variants from #/companion-demo, but each rendered INSIDE a full
   PDP details section (heading + description prose + all 4 bullets) so you
   see how the companion treatment lands in real PDP context, not as a
   standalone widget. */
function CompanionPdpDemo({ onAddToCart }) {
  const flat = [
    { key: "disc",  label: "قرص فرامل أمامي" },
    { key: "fluid", label: "سائل فرامل DOT4" },
  ];
  const picker = [
    { label: "قرص فرامل أمامي", options: [{ key: "disc", make: "oem", origin: null }, { key: "discAlt", make: "alt", origin: "صيني" }] },
    { label: "سائل فرامل",      options: [{ key: "fluid", make: "oem", origin: null }, { key: "fluidAlt", make: "alt", origin: "صيني" }] },
  ];

  const [added, setAdded] = useState({});
  const tap = (slot, key, allKeys) => {
    if (onAddToCart) {
      if (allKeys) allKeys.forEach((k) => onAddToCart(k));
      else if (PRODUCTS[key]) onAddToCart(key);
    }
    setAdded((a) => ({ ...a, [slot]: true }));
    setTimeout(() => setAdded((a) => { const n = { ...a }; delete n[slot]; return n; }), 1500);
  };
  const [openPicker, setOpenPicker] = useState(null);

  // Shared frame: full pdp-details preview with the companion bullet
  // replaced by whatever each variant passes in via `slot`.
  const Preview = ({ slot }) => (
    <div className="cmp-preview-frame" style={{ padding: "14px 16px" }}>
      <h2 className="pdp-h2" style={{ marginTop: 0 }}>التفاصيل</h2>
      <p className="pdp-desc">
        تُبدّل عند ظهور صرير عند الفرامل أو إحساس بضعف الفرملة. الفحمات الجديدة
        تعيد قوة الفرامل لمستواها قبل التآكل.
      </p>
      <ul className="pdp-specs">
        <li>
          <span className="pdp-spec-dot" />
          <span><strong className="pdp-spec-label">رقم القطعة:</strong> <span className="mono">04465B0280</span></span>
        </li>
        <li>
          <span className="pdp-spec-dot" />
          <span><strong className="pdp-spec-label">العمر التقريبي:</strong> <span className="mono">30,000-50,000</span> كم</span>
        </li>
        <li>
          <span className="pdp-spec-dot" />
          <span style={{ flex: 1, display: "block" }}>
            <strong className="pdp-spec-label">موصى به مع:</strong>
            <div style={{ marginTop: 6 }}>{slot}</div>
          </span>
        </li>
        <li>
          <span className="pdp-spec-dot" />
          <span><strong className="pdp-spec-label">التركيب:</strong> يحتاج رفع السيارة وفك العجلة</span>
        </li>
      </ul>
    </div>
  );

  // ── Slot builders (one per variant) ──────────────────────────────────

  const SlotA = () => (
    <div className="cmp-pills">
      {flat.map((c) => {
        const p = PRODUCTS[c.key];
        const slot = "ap-" + c.key;
        const isAdded = added[slot];
        return (
          <button key={c.key} className={"cmp-pill" + (isAdded ? " is-added" : "")} onClick={() => tap(slot, c.key)}>
            <span className="cmp-pill-plus">{isAdded ? "✓" : "+"}</span>
            {c.label} · <span className="mono">{p.price}</span><Riyal />
          </button>
        );
      })}
    </div>
  );

  const SlotB1 = () => (
    <div className="cmp-rail">
      {flat.map((c) => {
        const p = PRODUCTS[c.key];
        const slot = "b1p-" + c.key;
        const isAdded = added[slot];
        return (
          <div className="cmp-rail-card" key={c.key} onClick={() => navigate("/p/" + c.key)}>
            <div className="cmp-rail-img"><ProductImage kind={p.kind} /></div>
            <div className="cmp-rail-title">{c.label}</div>
            <div className="cmp-rail-meta">
              <MakeTag make={p.make} origin={p.origin} />
              <span className="cmp-rail-price">{p.price}<Riyal /></span>
            </div>
            <button
              className={"cmp-rail-add" + (isAdded ? " is-added" : "")}
              onClick={(e) => { e.stopPropagation(); tap(slot, c.key); }}
            >
              {isAdded ? "في السلة ✓" : "أضف للسلة"}
            </button>
          </div>
        );
      })}
    </div>
  );

  const SlotB2 = () => (
    <div className="cmp-rows">
      {flat.map((c) => {
        const p = PRODUCTS[c.key];
        const slot = "b2p-" + c.key;
        const isAdded = added[slot];
        return (
          <div className="cmp-row" key={c.key}>
            <div className="cmp-row-img"><ProductImage kind={p.kind} /></div>
            <div className="cmp-row-body">
              <span className="cmp-row-title">{c.label}</span>
              <div className="cmp-row-meta">
                <MakeTag make={p.make} origin={p.origin} />
                <span className="cmp-row-price">{p.price}<Riyal /></span>
              </div>
            </div>
            <button className={"cmp-row-add" + (isAdded ? " is-added" : "")} onClick={() => tap(slot, c.key)}>
              {isAdded ? "في السلة ✓" : "أضف"}
            </button>
          </div>
        );
      })}
    </div>
  );

  const SlotB3 = () => (
    <div className="cmp-tiles">
      {flat.map((c) => {
        const p = PRODUCTS[c.key];
        const slot = "b3p-" + c.key;
        const isAdded = added[slot];
        return (
          <button key={c.key} className={"cmp-tile" + (isAdded ? " is-added" : "")} onClick={() => tap(slot, c.key)}>
            <div className="cmp-tile-img">
              <ProductImage kind={p.kind} />
              <span className="cmp-tile-plus">{isAdded ? "✓" : "+"}</span>
            </div>
            <span className="cmp-tile-title">{c.label}</span>
            <span className="cmp-tile-price">{p.price}<Riyal /></span>
          </button>
        );
      })}
    </div>
  );

  const SlotB4 = () => {
    const subtotal = flat.reduce((s, c) => s + priceNum(PRODUCTS[c.key].price), 0);
    const saving = Math.round(subtotal * 0.07);
    const slot = "b4p-all";
    const isAllAdded = added[slot];
    return (
      <>
        <div className="cmp-bundle-banner">
          <span>اشترها معاً ووفّر</span>
          <span><span className="mono">{fmtPrice(saving)}</span><Riyal /></span>
        </div>
        <div className="cmp-rail">
          {flat.map((c) => {
            const p = PRODUCTS[c.key];
            return (
              <div className="cmp-rail-card" key={c.key} onClick={() => navigate("/p/" + c.key)}>
                <div className="cmp-rail-img"><ProductImage kind={p.kind} /></div>
                <div className="cmp-rail-title">{c.label}</div>
                <div className="cmp-rail-meta">
                  <MakeTag make={p.make} origin={p.origin} />
                  <span className="cmp-rail-price">{p.price}<Riyal /></span>
                </div>
              </div>
            );
          })}
        </div>
        <button
          className={"cmp-bundle-add-all" + (isAllAdded ? " is-added" : "")}
          onClick={() => tap(slot, null, flat.map((c) => c.key))}
        >
          {isAllAdded ? (
            "تمت إضافة الباقة ✓"
          ) : (
            <>أضف الكل · <span className="mono">{fmtPrice(subtotal - saving)}</span><Riyal /></>
          )}
        </button>
      </>
    );
  };

  const SlotC = () => (
    <>
      <div>
        {picker.map((c, i) => (
          <React.Fragment key={c.label}>
            {i > 0 && <span style={{ color: "var(--muted)", margin: "0 4px" }}>·</span>}
            <button className="cmp-link" onClick={() => setOpenPicker(openPicker === c.label ? null : c.label)}>
              {c.label}
            </button>
          </React.Fragment>
        ))}
      </div>
      {openPicker && (() => {
        const c = picker.find((p) => p.label === openPicker);
        return (
          <div className="cmp-picker">
            <div className="cmp-picker-title">{c.label} — اختر النوع</div>
            {c.options.map((opt) => {
              const p = PRODUCTS[opt.key];
              const slot = "cp-" + opt.key;
              const isAdded = added[slot];
              return (
                <div className="cmp-picker-row" key={opt.key}>
                  <div className="cmp-picker-row-info">
                    <span className="cmp-picker-row-title">{p.title}</span>
                    <span className="cmp-picker-row-make"><MakeTag make={opt.make} origin={opt.origin} /></span>
                  </div>
                  <span className="cmp-picker-row-price">{p.price}<Riyal /></span>
                  <button className={"cmp-picker-row-cta" + (isAdded ? " is-added" : "")} onClick={() => tap(slot, opt.key)}>
                    {isAdded ? "في السلة ✓" : "أضف"}
                  </button>
                </div>
              );
            })}
          </div>
        );
      })()}
    </>
  );

  const SlotD = () => (
    <div>
      {flat.map((c, i) => (
        <React.Fragment key={c.key}>
          {i > 0 && <span style={{ color: "var(--muted)", margin: "0 4px" }}>·</span>}
          <a className="cmp-pdp-link" onClick={() => navigate("/p/" + c.key)} style={{ cursor: "pointer" }}>
            {c.label}
          </a>
        </React.Fragment>
      ))}
    </div>
  );

  // ── Card builder + variants list ────────────────────────────────────

  const variants = [
    { id: "A",  name: "أ · زرّ مدمج (إضافة بنقرة)",            Slot: SlotA  },
    { id: "B1", name: "ب١ · شريط بطاقات أفقي (الأساس)",        Slot: SlotB1 },
    { id: "B2", name: "ب٢ · صفوف عمودية (الكل ظاهر)",          Slot: SlotB2 },
    { id: "B3", name: "ب٣ · مربعات مدمجة برمز +",               Slot: SlotB3 },
    { id: "B4", name: "ب٤ · إطار توفير الباندل (أضف الكل)",   Slot: SlotB4 },
    { id: "C",  name: "ج · اسم مسطّر يفتح خيارات الصانع",     Slot: SlotC  },
    { id: "D",  name: "د · اسم مسطّر ينقل لصفحة المنتج",      Slot: SlotD  },
  ];

  return (
    <div className="cmp-demo">
      <div className="cmp-demo-body">
        <h2 className="cmp-demo-title">كل الصياغات مطبّقة في قسم التفاصيل</h2>
        <p className="cmp-demo-sub">
          نفس الصياغات السبع من #/companion-demo، لكن داخل قسم تفاصيل كامل
          (عنوان + وصف + كل النقاط الأربع). تشاهد التأثير الكلي على المظهر
          النهائي لكل خيار قبل اتخاذ القرار.
        </p>
        {variants.map((v) => (
          <div className="cmp-card" key={v.id}>
            <div className="cmp-card-head">
              <div className="cmp-card-name">{v.name}</div>
            </div>
            <div className="cmp-card-body">
              <Preview slot={<v.Slot />} />
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* Companion-frame demo — #/companion-frame-demo.
   Shows five visual-containment variations for the "موصى به مع" rail in the
   PDP details section. Each variant is rendered twice: once with a single
   card (the "lonely" case the user flagged) and once with three cards so
   you see how each frame holds up across content lengths. */
function CompanionFrameDemo({ onAddToCart }) {
  const oneCard = [{ key: "disc",  label: "قرص فرامل أمامي" }];
  const threeCards = [
    { key: "disc",         label: "قرص فرامل أمامي" },
    { key: "bumperR",      label: "صدّام أمامي" },
    { key: "bumperRAlt",   label: "صدّام أمامي (بديل)" },
  ];

  const [added, setAdded] = useState({});
  const tap = (key) => {
    if (onAddToCart && PRODUCTS[key]) onAddToCart(key);
    setAdded((a) => ({ ...a, [key]: true }));
    setTimeout(() => setAdded((a) => { const n = { ...a }; delete n[key]; return n; }), 1500);
  };

  // The actual rail render (reusable across all frame variants).
  const Rail = ({ items, slotKey }) => (
    <div className="cmp-rail">
      {items.map((c) => {
        const p = PRODUCTS[c.key];
        const isAdded = added[slotKey + "-" + c.key];
        return (
          <div className="cmp-rail-card" key={c.key} onClick={() => navigate("/p/" + c.key)}>
            <div className="cmp-rail-img"><ProductImage kind={p.kind} /></div>
            <div className="cmp-rail-title">{c.label}</div>
            <div className="cmp-rail-meta">
              <MakeTag make={p.make} origin={p.origin} />
              <span className="cmp-rail-price">{p.price}<Riyal /></span>
            </div>
            <button
              className={"cmp-rail-add" + (isAdded ? " is-added" : "")}
              onClick={(e) => { e.stopPropagation(); tap(slotKey + "-" + c.key); }}
            >
              {isAdded ? "في السلة ✓" : "أضف للسلة"}
            </button>
          </div>
        );
      })}
    </div>
  );

  // Bullet wrapper that mirrors the live PdpDetails structure — dot + label
  // on the start, rail underneath, so each frame variant renders inside the
  // bullet's natural position.
  const Bullet = ({ children }) => (
    <div className="cmp-preview-frame" style={{ padding: "14px 16px" }}>
      <ul className="pdp-specs">
        <li>
          <span className="pdp-spec-dot" />
          <span style={{ flex: 1, display: "block", minWidth: 0 }}>
            <strong className="pdp-spec-label">موصى به مع:</strong>
            {children}
          </span>
        </li>
      </ul>
    </div>
  );

  // One "variant card" — title + two preview frames (1-card and 3-card).
  const Variant = ({ name, desc, frameClass, eyebrowLabel, slotPrefix }) => (
    <div className="cmp-card">
      <div className="cmp-card-head">
        <div className="cmp-card-name">{name}</div>
        <div className="cmp-card-desc">{desc}</div>
      </div>
      <div className="cmp-card-body" style={{ display: "flex", flexDirection: "column", gap: 14 }}>
        <div>
          <div className="cmp-preview-eyebrow">حالة بطاقة واحدة</div>
          <Bullet>
            {frameClass ? (
              <div className={frameClass} style={{ marginTop: 6 }}>
                {eyebrowLabel && <span className="cmp-frame-eyebrow-label">{eyebrowLabel}</span>}
                <Rail items={oneCard} slotKey={slotPrefix + "-one"} />
              </div>
            ) : (
              <div style={{ marginTop: 6 }}>
                <Rail items={oneCard} slotKey={slotPrefix + "-one"} />
              </div>
            )}
          </Bullet>
        </div>
        <div>
          <div className="cmp-preview-eyebrow">حالة ثلاث بطاقات (للمقارنة)</div>
          <Bullet>
            {frameClass ? (
              <div className={frameClass} style={{ marginTop: 6 }}>
                {eyebrowLabel && <span className="cmp-frame-eyebrow-label">{eyebrowLabel}</span>}
                <Rail items={threeCards} slotKey={slotPrefix + "-three"} />
              </div>
            ) : (
              <div style={{ marginTop: 6 }}>
                <Rail items={threeCards} slotKey={slotPrefix + "-three"} />
              </div>
            )}
          </Bullet>
        </div>
      </div>
    </div>
  );

  return (
    <div className="cmp-demo">
      <div className="cmp-demo-body">
        <h2 className="cmp-demo-title">إطار قسم "موصى به مع" — خمس صياغات</h2>
        <p className="cmp-demo-sub">
          المشكلة: عندما يكون هناك بطاقة واحدة فقط، تبدو معلّقة في فراغ أبيض.
          المقارنة أدناه: كل صياغة مع بطاقة واحدة (المشكلة) ومع ثلاث بطاقات
          (للتأكد أن الحل يصلح للحالتين). الصياغة الأولى هي الوضع الحالي
          بدون إطار للمقارنة.
        </p>

        <Variant
          slotPrefix="none"
          name="٠ · بدون إطار (الوضع الحالي)"
          desc="البطاقات تظهر مباشرة بعد التسمية، بدون أي حدود أو خلفية. مع بطاقة واحدة، تشعر بالعزلة."
          frameClass={null}
        />

        <Variant
          slotPrefix="rule"
          name="أ · خط متقطّع علوي"
          desc="خط رمادي متقطّع رفيع فوق الشريط، يفصل البطاقات عن الحقول التي قبلها. الأقل بصمة بصرية."
          frameClass="cmp-frame-rule"
        />

        <Variant
          slotPrefix="tint"
          name="ب · خلفية رمادية فاتحة"
          desc="الشريط داخل صندوق رمادي خفيف بزوايا مدوّرة. الصندوق يحدّد المساحة بشكل أوضح، ويرتفع التباين عن البطاقات البيضاء."
          frameClass="cmp-frame-tint"
        />

        <Variant
          slotPrefix="outline"
          name="ج · إطار رفيع"
          desc="إطار بلون hairline حول الشريط. يحدّد المنطقة بقوة دون لون خلفية. يميل قليلاً للثقل البصري."
          frameClass="cmp-frame-outline"
        />

        <Variant
          slotPrefix="eyebrow"
          name="د · تسمية صغيرة + خط فاصل"
          desc="تسمية ثانوية صغيرة (مثلاً 'اشترها معاً') فوق الشريط، مع خط رفيع تحتها. يعطي سياقاً أوضح لما البطاقات."
          frameClass="cmp-frame-eyebrow"
          eyebrowLabel="اشترِها معاً"
        />
      </div>
    </div>
  );
}

/* Confidence info-sheet integration demo — #/confidence-info-demo.
   Shows four executions of how the meter visualization integrates into
   the bottom sheet (the explainer that opens from the meter's info icon).
   Each variant is rendered as a mock bottom sheet (full content stack)
   so the visual rhythm of the sheet is preserved. The current production
   sheet has no meter — these add it in different ways. */
/* Confidence-trigger affordance demo — #/confidence-trigger-demo.
   Compares 10 visual treatments of the "tell me more" trigger that opens
   the confidence-tier explainer sheet. Each variant renders inside a mock
   meter row so it's evaluated in real production context (label + meter
   segments + tier labels visible alongside the trigger). Tap any trigger
   to open the existing PdpConfidenceInfoSheet.

   LOCKED: variant أ (blue ⓘ icon alone with a thin blue underline below,
   pinned to the inline-end / left corner of the meter row). Wired in
   `.pdp-fitguard-info-link` — keep this demo route as the comparison
   library so the choice can be re-validated against usability data later. */
function ConfidenceTriggerDemo() {
  const [sheetOpen, setSheetOpen] = useState(false);
  const openSheet = () => setSheetOpen(true);

  // Mock meter — level 2 (medium) so we render a typical real-world case
  // where the meter is mid-tier and the VIN-suggest is relevant.
  const MockMeter = () => (
    <>
      <div className="ctd-mock-meter">
        {FITGUARD_PALETTE.map((c, i) => {
          const bg = i === 1 ? c : "#E5E7EB";
          return <div key={i} className="ctd-mock-meter-seg" style={{ background: bg }} />;
        })}
      </div>
      <div className="ctd-mock-labels">
        {[1, 2, 3].map((n) => (
          <span key={n} className={"ctd-mock-label" + (n === 2 ? " is-active" : "")}>
            {FITGUARD_TIERS[n - 1].inactive}
          </span>
        ))}
      </div>
    </>
  );

  // Mock meter-row wrapper — variant 8 (whole label is the trigger)
  // replaces the static label entirely; others insert the trigger after
  // the static label.
  const MockRow = ({ trigger, replaceLabel }) => (
    <>
      <div className="ctd-mock-row">
        {replaceLabel ? (
          trigger
        ) : (
          <>
            <span className="ctd-mock-label-text">هل تركب على سيارتك؟</span>
            {trigger}
          </>
        )}
      </div>
      <MockMeter />
    </>
  );

  const variants = [
    {
      id: 1,
      name: "أ · ⓘ أزرق وحدها مع تسطير تحت الأيقونة",
      desc: "صياغة Zeyad الأصلية. أيقونة فقط بدون نص، بلون أزرق، خط رفيع تحتها كإشارة للضغط.",
      trigger: (
        <button type="button" className="ctd-trig-1" onClick={openSheet} aria-label="اعرف المستويات">
          <IconInfo />
        </button>
      ),
    },
    {
      id: 2,
      name: "ب · نص \"اعرف أكثر\" مسطّر فقط",
      desc: "بدون أيقونة. الأبسط — يعتمد على إلفة المستخدم بنمط الروابط المسطّرة بلون.",
      trigger: (
        <button type="button" className="ctd-trig-2" onClick={openSheet}>اعرف أكثر</button>
      ),
    },
    {
      id: 3,
      name: "ج · ⓘ أزرق + نص \"اعرف أكثر\" مسطّر (الحالي)",
      desc: "الأيقونة والنص معاً، أزرقان، النص مسطّر. الوضع الحالي في الإنتاج — مرجع للمقارنة.",
      trigger: (
        <button type="button" className="ctd-trig-3" onClick={openSheet}>
          <IconInfo />
          <span>اعرف أكثر</span>
        </button>
      ),
    },
    {
      id: 4,
      name: "د · علامة \"؟\" في دائرة زرقاء ممتلئة",
      desc: "علامة استفهام بيضاء على خلفية زرقاء كاملة. أقوى إشارة \"عندي سؤال — أجبني\".",
      trigger: (
        <button type="button" className="ctd-trig-4" onClick={openSheet} aria-label="اعرف المستويات">؟</button>
      ),
    },
    {
      id: 5,
      name: "ه · رابط \"ما المعنى؟\"",
      desc: "صياغة قائمة على فضول المستخدم بدل صياغة الفعل (\"اعرف\"). تدعو للاستفسار صراحةً.",
      trigger: (
        <button type="button" className="ctd-trig-5" onClick={openSheet}>ما المعنى؟</button>
      ),
    },
    {
      id: 6,
      name: "و · زر \"اعرف أكثر\" أحمر مدمج",
      desc: "زر صغير بلون سبيرو الأحمر. الأوضح والأبرز — لكن قد يطغى بصرياً على العدّاد ويُفهم كـ CTA رئيسي.",
      trigger: (
        <button type="button" className="ctd-trig-6" onClick={openSheet}>اعرف أكثر</button>
      ),
    },
    {
      id: 7,
      name: "ز · ⓘ بخطوط رمادية فقط (بدون لون)",
      desc: "أيقونة بإطار رمادي خافت، بدون لون أو تسطير. الأقل بصمة بصرية — لكن قد لا تبدو قابلة للضغط.",
      trigger: (
        <button type="button" className="ctd-trig-7" onClick={openSheet} aria-label="اعرف المستويات">
          <IconInfo />
        </button>
      ),
    },
    {
      id: 8,
      name: "ح · السؤال نفسه يصبح رابطاً (تسطير منقّط)",
      desc: "\"هل تركب على سيارتك؟\" نفسه قابل للضغط، بتسطير منقّط. لا أيقونة منفصلة — السؤال هو الإشارة.",
      trigger: (
        <button type="button" className="ctd-trig-8" onClick={openSheet}>هل تركب على سيارتك؟</button>
      ),
      replaceLabel: true,
    },
    {
      id: 9,
      name: "ط · \"تفاصيل ›\" في طرف الصف",
      desc: "رابط ينتهي بسهم، مثبت في طرف الصف. نمط رؤوس الأقسام في القوائم — \"اعرض المزيد\".",
      trigger: (
        <button type="button" className="ctd-trig-9" onClick={openSheet}>
          <span>تفاصيل</span>
          <IconChevron />
        </button>
      ),
    },
    {
      id: 10,
      name: "ي · ⓘ أزرق فقط (نمط iOS، بدون تسطير)",
      desc: "أيقونة معلومات زرقاء بدون أي تسطير أو حدود. تعتمد على اللون الأزرق وحده — تقليد قاعدة Apple.",
      trigger: (
        <button type="button" className="ctd-trig-10" onClick={openSheet} aria-label="اعرف المستويات">
          <IconInfo />
        </button>
      ),
    },
  ];

  return (
    <div className="ctd-demo">
      <div className="ctd-body">
        <h2 className="ctd-title">"اعرف أكثر" في صف العدّاد — 10 صياغات</h2>
        <p className="ctd-sub">
          العنصر الحالي (أيقونة زرقاء + نص مسطّر) قد لا يبدو واضح القابلية للضغط
          بما يكفي. أدناه 10 صياغات لإشارة "تفاصيل" بجوار عنوان العدّاد، كل واحدة
          داخل صف عدّاد محاكٍ للوضع الفعلي. اضغط أي واحدة لتجربة فتح ورقة الشرح.
        </p>

        {variants.map((v) => (
          <div className="ctd-card" key={v.id}>
            <div className="ctd-card-head">
              <div className="ctd-card-name">{v.name}</div>
              <div className="ctd-card-desc">{v.desc}</div>
            </div>
            <div className="ctd-card-body">
              <MockRow trigger={v.trigger} replaceLabel={v.replaceLabel} />
            </div>
          </div>
        ))}
      </div>
      <PdpConfidenceInfoSheet open={sheetOpen} onClose={() => setSheetOpen(false)} />
    </div>
  );
}

function ConfidenceInfoDemo() {
  // Shared content used inside every variant's sheet so the comparison is
  // about the meter integration, not the copy.
  const sections = [
    {
      level: 3,
      title: "مضمون",
      desc: "القطعة لا تتغيّر بحسب الفئة أو حجم المحرّك. نفس القطعة تركب على كل فئات سيارتك للسنة نفسها.",
      examples: ["صدّامات وشبك", "فلتر مكيف ومساحات", "لمبات الكشاف والمرايا الجانبية"],
    },
    {
      level: 2,
      title: "متوسط",
      desc: "القطعة قد تتغيّر مع الفئة (سبورت مقابل ستاندرد مثلاً). في الغالب التركيب صحيح، لكن نتأكد عبر رقم الهيكل.",
      examples: ["المساعدات وكراسي المساعد", "أقراص الفرامل", "فلتر زيت بحسب حجم المحرّك"],
    },
    {
      level: 1,
      title: "منخفض",
      desc: "القطعة تختلف اختلافاً كبيراً بحسب المحرّك أو الفئة. نحتاج رقم الهيكل لنحدّد المطابقة بدقة.",
      examples: ["طقم البواجي (يختلف بعدد الأسطوانات)", "سير المكينة وكويل الاشتعال", "حساسات المحرّك"],
    },
  ];
  const footnote = "في جميع الحالات: ضمان سبيرو يغطّيك. إن لم تطابق سيارتك، نرجعها خلال 14 يوماً.";

  // Reusable section block (title + description + bullets).
  const Section = ({ title, desc, examples }) => (
    <div className="cid-sheet-section">
      <h3 className="cid-sheet-section-title">{title}</h3>
      <p className="cid-sheet-section-desc">{desc}</p>
      <ul className="cid-sheet-section-list">
        {examples.map((ex, i) => <li key={i}>{ex}</li>)}
      </ul>
    </div>
  );

  // Reusable section block with a small inline meter on the title row,
  // showing where THIS tier sits on the 3-segment scale.
  const SectionWithRowMeter = ({ title, desc, examples, level }) => (
    <div className="cid-sheet-section">
      <div className="cid-row-title">
        <h3 className="cid-sheet-section-title" style={{ margin: 0 }}>{title}</h3>
        <div className="cid-row-meter">
          {FITGUARD_PALETTE.map((c, i) => {
            let bg = "#E5E7EB";
            if (i === level - 1) bg = c;
            else if (level === 3 && i === 0) bg = "#F3F4F6";
            return <div key={i} className="cid-row-meter-seg" style={{ background: bg }} />;
          })}
        </div>
      </div>
      <p className="cid-sheet-section-desc">{desc}</p>
      <ul className="cid-sheet-section-list">
        {examples.map((ex, i) => <li key={i}>{ex}</li>)}
      </ul>
    </div>
  );

  // Shared sheet wrapper — fake bottom-sheet chrome so each variant reads
  // as if it just opened from the PDP meter.
  const SheetFrame = ({ children }) => (
    <div className="cid-sheet">
      <div className="cid-sheet-head">
        <div className="cid-sheet-head-title">مستويات تأكيد التركيب</div>
        <button className="cid-sheet-head-x" aria-label="إغلاق"><IconClose /></button>
      </div>
      <div className="cid-sheet-body">{children}</div>
    </div>
  );

  // ── Variant A — single meter at the top, sections below ────────────
  const VariantA = () => (
    <SheetFrame>
      <div className="cid-top-meter">
        <div className="cid-top-meter-bar">
          {FITGUARD_PALETTE.map((c, i) => (
            <div key={i} className="cid-top-meter-seg" style={{ background: c }} />
          ))}
        </div>
        <div className="cid-top-meter-labels">
          <span>منخفض</span><span>متوسط</span><span>مضمون</span>
        </div>
      </div>
      {sections.map((s) => <Section key={s.title} {...s} />)}
      <p className="cid-sheet-foot">{footnote}</p>
    </SheetFrame>
  );

  // ── Variant B — each section carries its own inline mini-meter ─────
  const VariantB = () => (
    <SheetFrame>
      {sections.map((s) => <SectionWithRowMeter key={s.title} {...s} />)}
      <p className="cid-sheet-foot">{footnote}</p>
    </SheetFrame>
  );

  // ── Variant C — meter at top as tappable segment-buttons (jump nav) ─
  const sectionRefs = useRef({});
  const VariantC = () => (
    <SheetFrame>
      <div className="cid-jump-meter">
        {[1, 2, 3].map((n) => {
          const sec = sections.find((s) => s.level === n);
          return (
            <button
              key={n}
              className="cid-jump-seg"
              onClick={() => sectionRefs.current[n] && sectionRefs.current[n].scrollIntoView({ behavior: "smooth", block: "start" })}
            >
              <div className="cid-jump-seg-bar" style={{ background: FITGUARD_PALETTE[n - 1] }} />
              <span className="cid-jump-seg-label">{sec.title}</span>
            </button>
          );
        })}
      </div>
      {sections.map((s) => (
        <div key={s.title} ref={(el) => { if (el) sectionRefs.current[s.level] = el; }}>
          <Section {...s} />
        </div>
      ))}
      <p className="cid-sheet-foot">{footnote}</p>
    </SheetFrame>
  );

  // ── Variant D — tab-style meter (filter — only the selected level's
  //    section renders below). Pretty aggressive UX but useful for fast
  //    scanning when the user wants ONE specific level. ─────────────────
  const [activeTab, setActiveTab] = useState(3);
  const VariantD = () => {
    const active = sections.find((s) => s.level === activeTab);
    return (
      <SheetFrame>
        <div className="cid-tab-meter">
          {[1, 2, 3].map((n) => (
            <button
              key={n}
              className={"cid-tab-seg" + (n === activeTab ? " is-current" : "")}
              style={{ background: n === activeTab ? FITGUARD_PALETTE[n - 1] : "#E5E7EB" }}
              onClick={() => setActiveTab(n)}
              aria-label={"مستوى " + n}
            />
          ))}
        </div>
        <div className="cid-tab-labels">
          {[1, 2, 3].map((n) => {
            const sec = sections.find((s) => s.level === n);
            return (
              <button
                key={n}
                className={"cid-tab-label" + (n === activeTab ? " is-current" : "")}
                onClick={() => setActiveTab(n)}
              >{sec.title}</button>
            );
          })}
        </div>
        <Section {...active} />
        <p className="cid-sheet-foot">{footnote}</p>
      </SheetFrame>
    );
  };

  const variants = [
    { id: "A", name: "أ · عدّاد كامل في الأعلى",            desc: "العدّاد بألوانه الثلاثة فوق محتوى الورقة، يليه التسميات. الأقسام الثلاثة تتسلسل تحته. أبسط دمج.",      Variant: VariantA },
    { id: "B", name: "ب · عدّاد صغير بجوار كل عنوان",      desc: "كل قسم يحمل عدّاداً مصغّراً يبيّن أيّ شريحة تخصّه. يربط بصرياً النص بالمستوى المرئي في PDP.",        Variant: VariantB },
    { id: "C", name: "ج · شرائح قابلة للضغط تنقل للقسم",   desc: "كل شريحة في الأعلى زرّ كبير، يضغطه المستخدم لينتقل لقسمها مباشرة. مفيد للورقة الطويلة.",          Variant: VariantC },
    { id: "D", name: "د · تبويبات (يعرض قسم واحد فقط)",   desc: "العدّاد يعمل كتبويب: يختار المستخدم مستوى، يظهر قسمه فقط. مختصر، لكن يخفي السياق المقارن.",     Variant: VariantD },
  ];

  return (
    <div className="cid-demo">
      <div className="cid-body">
        <h2 className="cid-title">دمج العدّاد في ورقة المعلومات — أربع صياغات</h2>
        <p className="cid-sub">
          الورقة الحالية تشرح المستويات الثلاثة نصياً بدون أي تمثيل بصري للعدّاد.
          هذه أربع صياغات لإدراج العدّاد داخل الورقة بطرق مختلفة، مع نفس المحتوى
          النصي للمقارنة العادلة. كل بطاقة أدناه تحاكي مظهر الورقة كاملة.
        </p>

        {variants.map((v) => (
          <div className="cid-card" key={v.id}>
            <div className="cid-card-head">
              <div className="cid-card-name">{v.name}</div>
              <div className="cid-card-desc">{v.desc}</div>
            </div>
            <div className="cid-card-body">
              <v.Variant />
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* Demo: 5 tap-reveal animations for the PDP position glyph
   (#/pos-glyph-demo). Each card mocks a PDP hero block and floats the
   position badge at its native top-inline-end inset. Tapping the badge
   plays the variant's animation; tapping again reverses (variant 3
   auto-dismisses after 2.5s, matching tooltip convention). Zeyad picks
   by feel; winner gets wired into the real .pdp-pos-badge afterward. */
function PosGlyphAnimDemo() {
  const variants = [
    { id: 1, pos: "FR", name: "توسّع جانبي", desc: "البادج يتمدّد عرضياً والاسم يظهر بانزياح من جهة inline-start." },
    { id: 2, pos: "FL", name: "تحوّل لبيل (Pill)", desc: "العرض ينمو مع تحوّل border-radius لشكل بيل أفقي." },
    { id: 3, pos: "F",  name: "تلميحة Tooltip", desc: "البادج يبقى ثابتاً، تلميحة تظهر أسفله مع مؤشر سهم. اختفاء تلقائي بعد 2.5 ثانية." },
    { id: 4, pos: "B",  name: "قلب البطاقة (3D Flip)", desc: "البادج يدور على المحور Y، الوجه الخلفي يحمل الاسم العربي." },
    { id: 5, pos: "BR", name: "تسمية أسفل البادج", desc: "البادج لا يتحرّك، شريط نصّي يظهر أسفله بانزياح خفيف." },
  ];
  return (
    <div className="pga-demo">
      <div className="pga-body">
        <h2 className="pga-title">شارة الموقع — 5 حركات كشف عند الضغط</h2>
        <p className="pga-sub">
          المختبِرون يضغطون على شارة الموقع في صفحة المنتج (top-inline-end من صورة المنتج)
          لكنّها حالياً عنصر بصري بحت. أدناه 5 معالجات تكشف اسم الموقع بالعربية عند الضغط،
          كل واحدة في سياق محاكٍ لصورة المنتج. اضغط الشارة في كل بطاقة لتجربة الحركة.
        </p>
        {variants.map((v) => (
          <PosGlyphAnimCard key={v.id} variant={v} />
        ))}
      </div>
    </div>
  );
}

/* Demo: 10 color treatments for the Add-to-Cart "Added" state
   (#/cta-added-demo). Dimensions and the unadded "أضف للسلة" color
   stay locked (matches .pdp-add); only the post-add visual changes.
   Each card holds its own toggle state — tap to switch between Add
   and Added states and preview the transition. Initial state is
   Added so the variant treatment is visible at rest. */
function CtaAddedStateDemo() {
  const variants = [
    { id: 1,  name: "أخضر صلب",          desc: "اللون الحالي في الإنتاج. أخضر تأكيد كلاسيكي على الأبيض." },
    { id: 2,  name: "فحمي صلب",          desc: "تأكيد محايد بدون لون نجاح صريح. هادئ ومتوازن." },
    { id: 3,  name: "أسود صلب",          desc: "تأكيد حاسم بنبرة أرقى. يوحي بالقرار النهائي." },
    { id: 4,  name: "أخضر داكن",         desc: "نسخة أنضج من الأخضر، أقل صراخاً وأقرب لنبرة الفخامة." },
    { id: 5,  name: "حدود خضراء",        desc: "خلفية بيضاء، نصّ وحدود بالأخضر. تأكيد هادئ مع إشارة نجاح واضحة." },
    { id: 6,  name: "حدود فحمية",        desc: "خلفية بيضاء، نصّ وحدود فحمية. أقل ظهوراً، يعطي وزن أكبر للمحتوى المحيط." },
    { id: 7,  name: "نعناعي شفّاف",      desc: "خلفية مينت فاتحة، نصّ أخضر، حدود ناعمة. أنعم درجات التأكيد." },
    { id: 8,  name: "أحمر بـ ✓ أخضر",   desc: "الخلفية الحمراء كما هي، فقط أيقونة الصح خضراء. أقل تغيير ممكن، يحافظ على لون البراند." },
    { id: 9,  name: "رمادي معطّل",        desc: "خلفية رمادية فاتحة، نصّ باهت. يوحي بأن الإجراء تمّ، لا حاجة للتفاعل مجدداً." },
    { id: 10, name: "أخضر سبيرو",        desc: "الأخضر من FITGUARD_PALETTE (#047857). لون نجاح موجود مسبقاً في نظام الألوان." },
  ];
  return (
    <div className="cad-demo">
      <div className="cad-body">
        <h2 className="cad-title">حالة "في السلة" — 10 معالجات لونية</h2>
        <p className="cad-sub">
          الأبعاد والـ padding والخط ولون حالة "أضف للسلة" مثبّتة. أدناه 10 معالجات للون
          والإطار في حالة "في السلة" فقط. اضغط أيّ زرّ للتنقّل بين الحالتين ومعاينة الانتقال.
        </p>
        {variants.map((v) => (
          <CtaAddedCard key={v.id} variant={v} />
        ))}
      </div>
    </div>
  );
}

/* Demo: 10 ways to make the post-add qty stepper read as "already in your
   cart" on PDP re-entry (#/cta-stepper-demo). The bare stepper [−][2][+]
   is ambiguous to a returning buyer — looks like a qty picker rather than
   a status indicator. Each card defaults to qty=2 (simulating a re-entry
   after a prior add). Tap +/- to play with qty; at 0 the variant reverts
   to the red Add button so the round-trip is visible. */
function CtaStepperContextDemo() {
  const variants = [
    { id: 1,  name: "ستيبر فقط (الحالي)",        desc: "بدون أي إضافات. الحالة الحالية في الإنتاج — غامضة عند العودة." },
    { id: 2,  name: "تسمية يمين الستيبر",         desc: "\"في السلة\" تظهر بجوار الستيبر من جهة inline-start." },
    { id: 3,  name: "شارة حالة فوق الستيبر",      desc: "صف صغير \"✓ في السلة\" يوضّح الحالة قبل أزرار التعديل." },
    { id: 4,  name: "الرقم + لاحقة \"في السلة\"",   desc: "الرقم نفسه يحمل السياق: \"2 في السلة\"." },
    { id: 5,  name: "بطاقة بعنوان الحالة",         desc: "يلفّ الستيبر ببطاقة ذات رأس \"✓ في السلة\" منفصل." },
    { id: 6,  name: "أيقونة صح بجانب الرقم",        desc: "✓ أخضر يظهر بجوار الرقم داخل الستيبر." },
    { id: 7,  name: "أيقونة سلّة بجانب الرقم",       desc: "أيقونة السلّة بجوار الرقم — إشارة بصرية بدلاً من نصّ." },
    { id: 8,  name: "ستيبر + رابط \"اذهب للسلة\"",  desc: "الستيبر في الأعلى ورابط متابعة للسلّة أسفله — يوضح الخطوة التالية." },
    { id: 9,  name: "أزرار بنصّ \"أقل\" / \"زِد\"",  desc: "بدل + و −، استخدام كلمات تجعل الأزرار توضّح نفسها." },
    { id: 10, name: "أيقونة سلّة مهملات عند الـ 1", desc: "عند الكمية 1، يتحوّل زر النقصان لأيقونة حذف — الإجراء الحقيقي." },
  ];
  return (
    <div className="csd-demo">
      <div className="csd-body">
        <h2 className="csd-title">سياق "في السلة" للستيبر — 10 معالجات</h2>
        <p className="csd-sub">
          الستيبر بمفرده يقول "اضبط الكمية" لا "هذه في سلتك". أدناه 10 طرق لجعل الستيبر يحمل
          سياقه عند العودة لصفحة المنتج. كل بطاقة تبدأ بـ 2 كأنّك أضفت ثم عُدت — جرّب +/- لمعاينة
          السلوك، وعند 0 يعود الزرّ الأحمر.
        </p>
        {variants.map((v) => (
          <CtaStepperCard key={v.id} variant={v} />
        ))}
      </div>
    </div>
  );
}

/* Demo: 3 treatments of the loading → success → settled animation for the
   PDP Add-to-Cart button (#/cta-add-anim-demo). Same 3-state arc across
   all variants (~300ms loading + ~900ms تمت الإضافة + settle to في السلة),
   only the visual choreography differs. The settled state matches the
   shipped variant 6 from /cta-added-demo. Tap to play; "إعادة" replays. */
function CtaAddAnimDemo() {
  const variants = [
    {
      id: "A",
      name: "انتقال داخل الزر",
      desc: "كل المراحل تحدث داخل نفس الزر. مؤشّر تحميل، ثمّ \"تمت الإضافة\" بعلامة خضراء، ثمّ يستقرّ على \"في السلة\". نقطة تركيز واحدة طوال التسلسل.",
    },
    {
      id: "B",
      name: "زرّ + شريط تأكيد",
      desc: "مؤشّر داخل الزرّ ثمّ يستقرّ مباشرةً على \"في السلة\". شريط \"تمت الإضافة ✓\" ينزلق أسفل الزرّ ثمّ يختفي. يفصل بين لحظة التأكيد وحالة السلة المستقرّة.",
    },
    {
      id: "C",
      name: "وميض ثمّ استقرار",
      desc: "نبضة لطيفة أثناء التحميل، ثمّ تعبئة كاملة بلون البراند مع \"تمت الإضافة ✓\" كلحظة احتفال، ثمّ استقرار على الحالة الهادئة. أكثر شعوراً، أكثر حركة.",
    },
  ];
  return (
    <div className="cad-demo">
      <div className="cad-body">
        <h2 className="cad-title">رحلة الإضافة للسلة: 3 معالجات</h2>
        <p className="cad-sub">
          ثلاث طرق لتمثيل تسلسل تحميل ثمّ تأكيد ثمّ استقرار عند الضغط على "أضف للسلة". التوقيتات ثابتة عبر المعالجات الثلاث: 300ms تحميل ثمّ 900ms تأكيد ثمّ استقرار على الحالة الهادئة من /cta-added-demo. اضغط الزرّ لمشاهدة التسلسل، ثمّ "إعادة" لتجربته من جديد.
        </p>
        {variants.map((v) => (
          <CtaAddAnimCard key={v.id} variant={v} />
        ))}
      </div>
    </div>
  );
}

/* Demo: 5 spinner-free loading-mask alternatives for the PDP Add-to-Cart
   button (#/cta-add-mask-demo). Each variant communicates "we're adding"
   without a generic rotating spinner. All settle to the production
   variant 5 (حدود خضراء) on /cta-added-demo. Tap to play; "إعادة" replays.
   1. Optimistic settle: no loading at all, button flashes + settles.
   2. Fly-to-cart: button settles instantly, a green dot flies to cart icon.
   3. Morph to checkmark: button shrinks to a circle with a check, expands.
   4. Gradient sweep: subtle white-translucent gradient sweeps across.
   5. Animated text: "جاري الإضافة..." with cycling dots, no icon. */
function CtaAddMaskDemo() {
  const variants = [
    {
      id: "1",
      name: "تفاؤل: استقرار فوري",
      desc: "لا حالة تحميل أصلاً. الزرّ يومض ويستقرّ مباشرة على \"تمت الإضافة\" ثمّ \"في السلة\". الطلب الفعلي يعمل بالخلفية، وإن فشل يظهر إشعار قصير لإرجاع الزرّ. أسرع شعور ممكن.",
    },
    {
      id: "2",
      name: "طيران للسلة",
      desc: "الزرّ يستقرّ فوراً، وقطعة خضراء صغيرة تطير من الزرّ إلى أيقونة السلة في الأعلى. الأيقونة تنبض والشارة تزيد عند الوصول. يوضّح \"أين ذهبت قطعتي\" بصرياً.",
    },
    {
      id: "3",
      name: "تحوّل الزرّ لعلامة الصح",
      desc: "الزرّ ينكمش إلى دائرة صغيرة بعلامة صح خضراء، ثمّ يتوسّع مجدداً إلى الحالة المستقرّة. التحميل مخفيّ داخل حركة التحوّل نفسها.",
    },
    {
      id: "4",
      name: "تدرّج لوني يعبر الزرّ",
      desc: "تدرّج أبيض خفيف يمرّ بعرض الزرّ مرّة واحدة. النص لا يتغيّر، الحركة وحدها تخبر أن شيئاً يحدث. أنيق وأقل ضوضاء من الدوّار.",
    },
    {
      id: "5",
      name: "نصّ متحرّك بدون أيقونة",
      desc: "النصّ يصبح \"جاري الإضافة...\" مع نقاط متحرّكة، ثمّ يستقرّ. أبسط بديل، يستبدل الأيقونة بكلمة واضحة بالعربية.",
    },
  ];
  return (
    <div className="cad-demo">
      <div className="cad-body">
        <h2 className="cad-title">إخفاء التحميل: 5 بدائل عن الدوّار</h2>
        <p className="cad-sub">
          خمس طرق حديثة لتمثيل لحظة "نحفظ إضافتك للسلة" دون استخدام الدوّار التقليدي. كل المعالجات تستقرّ على نفس حالة "في السلة" المعتمدة (حدود خضراء). اضغط الزرّ في كلّ بطاقة لمشاهدة المعالجة، ثمّ "إعادة" لتجربتها من جديد.
        </p>
        {variants.map((v) => (
          <CtaAddMaskCard key={v.id} variant={v} />
        ))}
      </div>
    </div>
  );
}

/* Demo: 4 cart empty-state treatments (#/cart-empty-demo). Compares a bland
   single-line state against richer re-engagement layouts before picking one
   for CartDrawer. Each frame mimics the cart-drawer body. */
function CartEmptyDemo() {
  const car = CURRENT_CAR.short;
  const peek = ["pads", "bumperR", "shockR"].map(findProduct).filter(Boolean);
  const cats = DISCOVER_CATEGORIES.slice(0, 5);
  return (
    <div className="cad-demo">
      <div className="cad-body">
        <h2 className="cad-title">السلة الفارغة — 4 معالجات</h2>
        <p className="cad-sub">
          الحالة الحالية مجرد سطر واحد ("سلتك فارغة"). أدناه 4 بدائل تحوّل الحالة الفارغة
          إلى نقطة عودة للتصفّح. اختر الأنسب لتجربة المستخدم.
        </p>

        {/* A — Clean: icon + CTA */}
        <div className="cad-card">
          <div className="cad-card-head">
            <h3 className="cad-card-name">1. نظيفة: أيقونة + زر</h3>
            <p className="cad-card-desc">الحد الأدنى المهذّب: أيقونة، عنوان دافئ، وزر أحمر واحد للعودة للتصفّح. آمنة وسريعة وبدون ترويج قطع.</p>
          </div>
          <div className="ced-frame">
            <div className="ced-icon"><IconCart /></div>
            <div className="ced-title">سلتك فارغة</div>
            <div className="ced-sub">ابدأ بإضافة قطع سيارتك</div>
            <button className="cta" onClick={() => navigate("/car")}>تصفّح قطع سيارتك</button>
          </div>
        </div>

        {/* B — Launchpad: category chips */}
        <div className="cad-card">
          <div className="cad-card-head">
            <h3 className="cad-card-name">2. منصّة انطلاق: أقسام سريعة</h3>
            <p className="cad-card-desc">النسخة النظيفة مع شرائح أقسام سريعة تنقل المستخدم لقسم يحتاجه. مساعدة في التنقّل، لا ترويج لمنتجات.</p>
          </div>
          <div className="ced-frame">
            <div className="ced-icon"><IconCart /></div>
            <div className="ced-title">سلتك فارغة</div>
            <div className="ced-sub">ابدأ من قسم تحتاجه</div>
            <div className="ced-chips">
              {cats.map((c) => (
                <button key={c.id} className="ced-chip" onClick={() => navigate("/spare-parts/" + c.id)}>{c.label}</button>
              ))}
            </div>
            <button className="ced-link" onClick={() => navigate("/spare-parts/all")}>تصفّح كل القطع <IconChevron /></button>
          </div>
        </div>

        {/* C — Visual Search nudge */}
        <div className="cad-card">
          <div className="cad-card-head">
            <h3 className="cad-card-name">3. تلميح البحث البصري</h3>
            <p className="cad-card-desc">يُبرز ميزة سبيرو المميّزة عند لحظة النية: "ما تعرف اسم القطعة؟ حددها على السيارة." يوجّه إلى البحث البصري.</p>
          </div>
          <div className="ced-frame">
            <div className="ced-icon"><IconCart /></div>
            <div className="ced-title">سلتك فارغة</div>
            <div className="ced-sub">ما تعرف اسم القطعة؟ حددها على سيارتك</div>
            <button className="cta" onClick={() => navigate("/locate")}>حددها على سيارتك <IconSearch /></button>
            <button className="ced-link" onClick={() => navigate("/spare-parts/all")}>تصفّح القطع <IconChevron /></button>
          </div>
        </div>

        {/* D — Popular-parts peek */}
        <div className="cad-card">
          <div className="cad-card-head">
            <h3 className="cad-card-name">4. لمحة قطع دارجة</h3>
            <p className="cad-card-desc">يعرض رفّاً مصغّراً من "قطع دارجة لسيارتك" للإضافة بنقرة. أقوى إعادة تفاعل، لكنه يعيد اقتراح المنتجات (نفس مأخذ الترويج).</p>
          </div>
          <div className="ced-frame">
            <div className="ced-icon"><IconCart /></div>
            <div className="ced-title">سلتك فارغة</div>
            <div className="ced-peek-eyebrow">قطع دارجة لـ {car}</div>
            <div className="ced-peek">
              {peek.map((p) => (
                <div key={p.key} className="ced-peek-tile" onClick={() => navigate("/p/" + p.key)}>
                  <div className="ced-peek-img">
                    <ProductImage kind={p.kind} />
                    <button className="ced-peek-add" aria-label="أضف" onClick={(e) => e.stopPropagation()}>+</button>
                  </div>
                  <div className="ced-peek-name">{p.title}</div>
                </div>
              ))}
            </div>
            <button className="cta" onClick={() => navigate("/car")}>تصفّح قطع سيارتك</button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ---------- registry ---------- */
window.DEMOS = Object.assign(window.DEMOS || {}, {
  "wheel-spin-demo": WheelSpinDemo,
  "home-car-demo": HomeCarDemo,
  "visual-search-demo": VisualSearchSectionDemo,
  "wheel-thickness-demo": WheelThicknessDemo,
  "pos-demo": PositionShapesDemo,
  "query-demo": QueryIndicatorDemo,
  "pdp-hero-demo": PdpHeroDemo,
  "meter-demo": MeterColorsDemo,
  "companion-demo": CompanionDemo,
  "companion-pdp-demo": CompanionPdpDemo,
  "companion-frame-demo": CompanionFrameDemo,
  "confidence-trigger-demo": ConfidenceTriggerDemo,
  "confidence-info-demo": ConfidenceInfoDemo,
  "pos-glyph-demo": PosGlyphAnimDemo,
  "cta-added-demo": CtaAddedStateDemo,
  "cta-stepper-demo": CtaStepperContextDemo,
  "cta-add-anim-demo": CtaAddAnimDemo,
  "cta-add-mask-demo": CtaAddMaskDemo,
  "cart-empty-demo": CartEmptyDemo,
});

// If the page loaded directly on a demo route, the app already mounted before this
// bundle registered. Nudge a re-render so the route resolves on first paint.
window.dispatchEvent(new Event("hashchange"));
