// Sayso — Testimonial Ads: living video atoms + visual sections.
// No real video files: motion is simulated from real footage stills via a slow
// Ken Burns drift, cycling burned-in subtitles, and a looping progress bar —
// so the page reads as "there are videos here" while staying calm + on-brand.

const { useState: useStateV, useEffect: useEffectV, useRef: useRefV } = React;

// ── styles ───────────────────────────────────────────────────────────────────
const VID_CSS = `
  @keyframes pc-ken { 0% { transform: scale(1.02) translate(0,0); } 100% { transform: scale(1.12) translate(-1.5%, -1.5%); } }
  @keyframes pc-prog { 0% { transform: scaleX(0); } 100% { transform: scaleX(1); } }
  @keyframes pc-capin { 0% { opacity:0; transform: translateY(4px); } 100% { opacity:1; transform:none; } }
  @keyframes pc-pulse { 0%,100% { opacity:.55; } 50% { opacity:1; } }
  @keyframes pc-eq { 0%,100% { height:5px; } 50% { height:15px; } }

  .pc-vc { position:relative; overflow:hidden; background:#15110f; border-radius:16px;
    box-shadow:var(--shadow-strong); isolation:isolate; }
  .pc-vc img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block;
    transform:scale(1.02); transform-origin:center; }
  .pc-vc.live img { animation: pc-ken 14s ease-in-out infinite alternate; }
  .pc-vc .scrim { position:absolute; inset:0; background:linear-gradient(rgba(0,0,0,0) 46%, rgba(0,0,0,0.78)); z-index:1; }
  .pc-vc .scrim-top { position:absolute; inset:0; background:linear-gradient(rgba(0,0,0,0.28), rgba(0,0,0,0) 30%); z-index:1; }
  .pc-vc .layer { position:absolute; z-index:2; }

  /* play button */
  .pc-vplay { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); z-index:3;
    border-radius:999px; background:rgba(0,0,0,0.26); backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
    display:flex; align-items:center; justify-content:center; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); }
  .pc-vc:hover .pc-vplay { transform:translate(-50%,-50%) scale(1.06); background:rgba(0,0,0,0.36); }
  .pc-vplay:hover { background:#FF238C; transform:translate(-50%,-50%) scale(1.08); }

  /* top chips row */
  .pc-vtop { position:absolute; top:13px; left:13px; right:13px; z-index:3; display:flex; align-items:center; justify-content:space-between; gap:8px; }
  .pc-chip2 { display:inline-flex; align-items:center; gap:7px; font:600 11px/1 var(--font-sans); color:#fff;
    background:rgba(0,0,0,0.42); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px); border-radius:7px; padding:6px 9px; letter-spacing:.02em; }
  .pc-rec { display:inline-flex; align-items:center; gap:6px; }
  /* instagram-style sayso identity chip */
  .pc-acct { display:inline-flex; align-items:center; gap:6px; background:rgba(0,0,0,0.36); backdrop-filter:blur(8px);
    -webkit-backdrop-filter:blur(8px); border-radius:999px; padding:3px 11px 3px 3px; }
  .pc-acct .av { width:22px; height:22px; border-radius:999px; background:#fff; flex:none; display:flex;
    align-items:center; justify-content:center; overflow:hidden; }
  .pc-acct .av img { position:static; inset:auto; transform:none; width:100%; height:100%; object-fit:contain; padding:3px; box-sizing:border-box; }
  .pc-acct .nm { font:600 12px/1 var(--font-sans); color:#fff; letter-spacing:-0.01em; }
  .pc-acct .vf { width:12px; height:12px; flex:none; margin-left:-2px; }
  .pc-rec b { width:7px; height:7px; border-radius:999px; background:var(--brand-600); animation: pc-pulse 1.6s ease-in-out infinite; }

  /* subtitle */
  .pc-sub { position:absolute; left:0; right:0; bottom:54px; z-index:3; text-align:center; padding:0 16px; }
  .pc-sub span { display:inline; font:600 clamp(14px,1.5vw,19px)/1.35 var(--font-sans); color:#fff;
    letter-spacing:-0.01em; text-shadow:0 1px 10px rgba(0,0,0,0.55); animation: pc-capin .4s ease both; }

  /* bottom meta + progress */
  .pc-vmeta { position:absolute; left:14px; right:14px; bottom:14px; z-index:3; display:flex; align-items:flex-end; justify-content:space-between; gap:12px; }
  .pc-vmeta .who b { display:block; font:600 14px/1.2 var(--font-sans); color:#fff; letter-spacing:-0.01em; }
  .pc-vmeta .who span { display:block; font:400 12px/1.3 var(--font-sans); color:rgba(255,255,255,0.72); margin-top:2px; }
  .pc-eq { display:flex; align-items:flex-end; gap:3px; height:16px; }
  .pc-eq i { width:3px; height:5px; border-radius:2px; background:rgba(255,255,255,0.9); display:block; }
  .pc-eq i:nth-child(1){ animation: pc-eq 0.9s ease-in-out infinite; }
  .pc-eq i:nth-child(2){ animation: pc-eq 0.9s ease-in-out infinite .15s; }
  .pc-eq i:nth-child(3){ animation: pc-eq 0.9s ease-in-out infinite .3s; }
  .pc-eq i:nth-child(4){ animation: pc-eq 0.9s ease-in-out infinite .45s; }
  .pc-vbar { position:absolute; left:0; right:0; bottom:0; height:4px; z-index:3; background:rgba(255,255,255,0.22); }
  .pc-vbar i { display:block; height:100%; background:var(--brand-600); transform-origin:left; transform:scaleX(0);
    animation: pc-prog 12s linear infinite; }

  @media (prefers-reduced-motion: reduce) {
    .pc-vc.live img { animation:none; } .pc-vbar i { animation:none; transform:scaleX(.4); }
    .pc-rec b, .pc-eq i { animation:none; }
  }

  /* morph showpiece */
  .pc-morph-stage { display:flex; align-items:center; justify-content:center; min-height:545px; }
  .pc-morph { position:relative; flex:none; overflow:hidden; border-radius:16px; background:#15110f; box-shadow:var(--shadow-strong);
    transition: width .9s cubic-bezier(.5,0,0,1), height .9s cubic-bezier(.5,0,0,1); }
  .pc-fmtbtns { display:flex; gap:10px; justify-content:center; margin-top:34px; }
  .pc-fmtbtn { font:600 14px/1 var(--font-sans); padding:11px 18px; border-radius:999px; border:1px solid var(--line);
    background:#fff; color:var(--text-secondary); transition:all .25s cubic-bezier(.2,0,0,1); cursor:default; letter-spacing:-0.01em; }
  .pc-fmtbtn.on { background:var(--brand-600); border-color:var(--brand-600); color:#fff; transform:translateY(-1px); }

  /* format indicators under the play button (inside the morph clip) */
  .pc-fmtind { position:absolute; top:calc(50% + 46px); left:50%; transform:translateX(-50%); z-index:3;
    display:flex; gap:16px; align-items:center; }
  .pc-fmtind span { font:600 13px/1 var(--font-sans); letter-spacing:.02em; color:rgba(255,255,255,0.6);
    transition: color 0.25s cubic-bezier(0.4, 0, 0.2, 1); text-shadow:0 1px 6px rgba(0,0,0,0.4); }
  .pc-fmtind span.on { color:#FF238C; }

  /* proof wall */
  .pc-wall { display:grid; grid-template-columns:repeat(4,1fr); gap:20px; direction:rtl; }
  .pc-story { position:absolute; left:16px; right:16px; bottom:15px; z-index:3; text-align:left; direction:ltr; }
  .pc-story .hook { margin:0 0 9px; font:600 clamp(15px,1.65vw,20px)/1.32 var(--font-sans); color:#fff;
    letter-spacing:-0.015em; text-shadow:0 1px 12px rgba(0,0,0,0.55); text-wrap:balance; }
  .pc-story .who2 { display:flex; flex-direction:column; gap:1px; }
  .pc-story .who2 .nm { font:500 13px/1.3 var(--font-sans); color:rgba(255,255,255,0.92); letter-spacing:-0.01em; }
  .pc-story .who2 .sb { font:400 12px/1.35 var(--font-sans); color:rgba(255,255,255,0.64); }
  .pc-tile { position:relative; aspect-ratio:9/16; border-radius:16px; overflow:hidden; background:#15110f; direction:ltr;
    box-shadow:var(--shadow-card); transition:transform .3s cubic-bezier(.2,0,0,1), box-shadow .3s; cursor:pointer; }
  .pc-tile:hover { transform:scale(1.02); box-shadow:var(--shadow-strong); }
  .pc-tile .wash { position:absolute; inset:0; z-index:2; background:rgba(255,35,140,0); transition:background .3s; }
  .pc-tile:hover .wash { background:rgba(255,35,140,0.16); }
  @media (max-width:960px){ .pc-wall { grid-template-columns:repeat(2,1fr); } .pc-morph-stage { min-height:480px; } }
  @media (max-width:560px){ .pc-wall { grid-template-columns:1fr 1fr; } }
  /* base: hide carousel-only chrome on desktop (declared before the mobile query so the query wins) */
  .pc-dots, .pc-swipehint { display:none; }
  /* ═ MOBILE (≤767px): live auto-drifting video carousel — 3 cards visible, snap + focus on interaction ═ */
  @media (max-width:767px){
    .pc-wall { display:flex !important; grid-template-columns:none !important; direction:ltr !important; gap:0;
      overflow-x:auto; scroll-snap-type:none; -webkit-overflow-scrolling:touch; scrollbar-width:none;
      margin-left:calc(var(--pc-pad)*-1) !important; margin-right:calc(var(--pc-pad)*-1) !important;
      padding:10px calc((100vw - 66vw)/2) 10px !important; }
    .pc-wall.interacted { scroll-snap-type:x mandatory; }
    .pc-wall::-webkit-scrollbar { display:none; }
    .pc-tile { flex:0 0 60vw; aspect-ratio:9/16; scroll-snap-align:center; margin:0 5px;
      transform:scale(1); transition:transform .45s cubic-bezier(.2,0,0,1); }
    .pc-tile::after { content:""; position:absolute; inset:0; z-index:4; border-radius:16px; pointer-events:none;
      background:rgba(0,0,0,0); transition:background .45s cubic-bezier(.2,0,0,1); }
    /* emphasis appears only once the user starts interacting */
    .pc-wall.interacted .pc-tile { transform:scale(.93); }
    .pc-wall.interacted .pc-tile::after { background:rgba(0,0,0,0.3); }
    .pc-wall.interacted .pc-tile.is-active { transform:scale(1); box-shadow:var(--shadow-strong); }
    .pc-wall.interacted .pc-tile.is-active::after { background:rgba(0,0,0,0); }
    .pc-dots { display:flex; justify-content:center; gap:6px; margin-top:18px; }
    .pc-dots i { width:6px; height:6px; border-radius:999px; background:rgba(0,0,0,0.14);
      transition:background .3s, width .3s; }
    .pc-dots i.on { width:16px; background:var(--brand-600); }
    .pc-swipehint { display:none !important; }
  }

  /* logo grid — open hairline rules (no side frame), refined caption + center tick */
  .pc-marq-head { text-align:center; font:400 15px/1 var(--font-sans); letter-spacing:-0.01em;
    color:var(--text-tertiary); text-transform:none; margin:0 0 40px; }
  .pc-marq-head strong { font-weight:600; color:var(--text-primary); letter-spacing:-0.015em; }
  .logo-tick { display:none; width:1px; height:42px; background:linear-gradient(rgba(0,0,0,0.08), rgba(0,0,0,0)); margin:0 auto; }
  .logo-shell { position:relative; }
  .logo-frame { border-top:1px solid rgba(0,0,0,0.07); border-bottom:1px solid rgba(0,0,0,0.07);
    background:transparent; display:grid; grid-template-columns:repeat(8,1fr); position:relative; z-index:1; }
  /* editorial sparkle marks at the rule ends + centre, matching the site grid */
  .logo-plus { display:none; position:absolute; width:14px; height:14px; z-index:4; transform:translate(-50%,-50%); pointer-events:none;
    background:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M12%201%20C12.6%208%2016%2011.4%2023%2012%20C16%2012.6%2012.6%2016%2012%2023%20C11.4%2016%208%2012.6%201%2012%20C8%2011.4%2011.4%208%2012%201%20Z'%20fill='%23C9C9C9'/%3E%3C/svg%3E") center/contain no-repeat; }
  .logo-cell { background:transparent; display:flex; align-items:center; justify-content:center; padding:22px 14px; min-height:62px; }
  .client-logo {
    max-width: 122px;
    width: auto;
    object-fit: contain;
    display: block;
    opacity: 0.72;
    filter: grayscale(100%);
    transition: opacity 0.25s ease, filter 0.25s ease;
  }
  .logo-cell:hover .client-logo { opacity: 1; filter: grayscale(0%); }
  @media (max-width:860px){
    .logo-frame { grid-template-columns:repeat(4,1fr); }
    .logo-cell { padding:18px 12px; min-height:56px; }
  }
  @media (max-width:520px){
    .logo-frame { grid-template-columns:repeat(2,1fr); }
  }
`;

// ── play mark ─────────────────────────────────────────────────────────────────
function VPlay({ d = 56 }) {
  return (
    <span className="pc-vplay" style={{ width: d, height: d }}>
      <svg width={Math.round(d * 0.3)} height={Math.round(d * 0.3)} viewBox="0 0 24 24" fill="#fff"><path d="M8 5v14l11-7z" /></svg>
    </span>
  );
}

// ── VideoCard — a still that behaves like a playing clip ──────────────────────
function VideoCard({ src, objPos = "center 26%", captions = [], who, city, logo, fmt, play = true, rec = false, dur = "0:24", style, className = "" }) {
  const [ci, setCi] = useStateV(0);
  useEffectV(() => {
    if (!captions.length || (typeof matchMedia !== "undefined" && matchMedia("(prefers-reduced-motion: reduce)").matches)) return;
    const t = setInterval(() => setCi((n) => (n + 1) % captions.length), 2600);
    return () => clearInterval(t);
  }, [captions.length]);
  return (
    <div className={"pc-vc " + (play ? "live " : "") + className} style={style}>
      <img src={src} alt="" draggable="false" style={{ objectPosition: objPos }} />
      <div className="scrim-top" />
      <div className="scrim" />
      <div className="pc-vtop">
        <span className="pc-chip2">{rec ? <span className="pc-rec"><b />REC</span> : (fmt || "16:9")}</span>
        <span className="pc-chip2">{dur}</span>
      </div>
      {play && <VPlay />}
      {captions.length > 0 && (
        <div className="pc-sub"><span key={ci}>{captions[ci]}</span></div>
      )}
      <div className="pc-vmeta">
        <div className="who">
          {logo ? <b>{logo}</b> : (who && <b>{who}</b>)}
          {city && <span>{city}</span>}
        </div>
        <div className="pc-eq" aria-hidden="true"><i /><i /><i /><i /></div>
      </div>
      <div className="pc-vbar"><i /></div>
    </div>
  );
}

// ── Morph showpiece — one clip, three formats, on a loop ──────────────────────
const MORPH_STATES = [
  { fmt: "9:16", w: 300, h: 533, label: "Vertical", use: "Reels · Shorts · Stories", tagline: "Next request, ready." },
  { fmt: "1:1", w: 460, h: 460, label: "Square", use: "Feeds · LinkedIn · Meta", tagline: "Campaign proof." },
  { fmt: "16:9", w: 720, h: 405, label: "Widescreen", use: "YouTube · Site · Sales", tagline: "Main story." },
];
// ── Morphing stage (reusable) — one clip, three formats, on a loop ────────────
function MorphStage({ shown = true, autoStart = true }) {
  const [i, setI] = useStateV(0);
  const reduce = typeof matchMedia !== "undefined" && matchMedia("(prefers-reduced-motion: reduce)").matches;
  useEffectV(() => {
    if (!autoStart || reduce) return;
    const t = setInterval(() => setI((n) => (n + 1) % MORPH_STATES.length), 2400);
    return () => clearInterval(t);
  }, [reduce, autoStart]);
  const s = MORPH_STATES[i];
  return (
    <div className="pc-morph-stage" style={{ flexDirection: "column" }}>
      <div className="pc-morph" style={{ width: s.w, height: s.h }}>
        <img src="assets/footage/r-source.png" alt="" draggable="false" style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", objectPosition: "center 24%" }} />
        <div style={{ position: "absolute", inset: 0, background: "linear-gradient(rgba(0,0,0,0.2), rgba(0,0,0,0) 28%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.7))" }} />
        <span className="pc-chip2" style={{ position: "absolute", top: 14, left: 14 }}>{s.fmt}</span>
        <VPlay d={54} />
        <div className="pc-fmtind">
          {MORPH_STATES.map((m, k) => (
            <span key={m.fmt} className={k === i ? "on" : ""}>{m.fmt}</span>
          ))}
        </div>
        <div style={{ position: "absolute", left: 16, right: 16, bottom: 14 }}>
          <div style={{ font: "400 12px/1.3 var(--font-sans)", color: "rgba(255,255,255,0.72)" }}>{s.use}</div>
        </div>
      </div>
      <p key={s.tagline} style={{ textAlign: "center", font: "600 clamp(18px,1.8vw,22px)/1.3 var(--font-sans)", letterSpacing: "-0.02em", color: "var(--text-primary)", margin: "22px 0 0", animation: "pc-capin .4s cubic-bezier(.2,0,0,1) both" }}>{s.tagline}</p>
    </div>
  );
}

// bare morph block — the hero's live visual (no section heading/text)
function MorphClip() {
  return (
    <section className="pc-sec" style={{ background: "#fff" }}>
      <div className="pc-wrap" style={{ padding: "8px var(--pc-pad) 0", textAlign: "center" }}>
        <div className="pc-rise" style={{ animationDelay: "120ms" }}><MorphStage /></div>
      </div>
    </section>
  );
}

// ── Proof wall — portrait testimonial tiles (DS "same standard, everywhere") ──
function ProofWall() {
  const [ref, shown] = usePcReveal();
  const wallRef = React.useRef(null);
  const [active, setActive] = React.useState(0);
  // All four cards come from the central Film store (edited via Film Manager).
  // Ordered for RTL: store index 0 renders rightmost.
  const proof = (window.SaysoFilms ? window.SaysoFilms.get().proof : []);
  const tiles = proof.map((p) => ({
    src: p.img, objPos: p.pos || "center 18%", brand: p.brand, hook: p.hook,
    dur: p.dur, city: p.city, person: p.person, company: p.company,
    vid: window.SaysoFilms.embed(p.id, p.h),
  }));
  // Mobile: a live auto-drifting carousel that pauses + enables snap/focus on interaction.
  const interactRef = React.useRef(null);
  React.useEffect(() => {
    const wall = wallRef.current;
    if (!wall) return;
    const mq = window.matchMedia("(max-width:767px)");
    let raf = 0, autoRaf = 0, interacted = false, dir = 1;
    const computeActive = () => {
      const mid = wall.scrollLeft + wall.clientWidth / 2;
      const kids = wall.children;
      let best = 0, bestD = Infinity;
      for (let i = 0; i < kids.length; i++) {
        const c = kids[i];
        const cc = c.offsetLeft + c.offsetWidth / 2;
        const dd = Math.abs(cc - mid);
        if (dd < bestD) { bestD = dd; best = i; }
      }
      setActive(best);
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(() => { raf = 0; computeActive(); }); };
    const stopAuto = () => { if (autoRaf) { cancelAnimationFrame(autoRaf); autoRaf = 0; } };
    const startAuto = () => {
      if (!mq.matches || interacted) return;
      const step = () => {
        if (interacted) return;
        const max = wall.scrollWidth - wall.clientWidth;
        if (max <= 1) { autoRaf = requestAnimationFrame(step); return; }
        let next = wall.scrollLeft + dir * 0.42;
        if (next >= max) { next = max; dir = -1; }
        else if (next <= 0) { next = 0; dir = 1; }
        wall.scrollLeft = next;
        autoRaf = requestAnimationFrame(step);
      };
      autoRaf = requestAnimationFrame(step);
    };
    const onInteract = () => {
      if (interacted) return;
      interacted = true;
      wall.classList.add("interacted");
      stopAuto();
      computeActive();
    };
    interactRef.current = onInteract;
    const evs = ["pointerdown", "touchstart", "wheel"];
    computeActive();
    wall.addEventListener("scroll", onScroll, { passive: true });
    evs.forEach((ev) => wall.addEventListener(ev, onInteract, { passive: true }));
    const startT = setTimeout(startAuto, 900);
    const onVis = () => { if (document.hidden) stopAuto(); else startAuto(); };
    document.addEventListener("visibilitychange", onVis);
    return () => {
      clearTimeout(startT); stopAuto();
      if (raf) cancelAnimationFrame(raf);
      wall.removeEventListener("scroll", onScroll);
      evs.forEach((ev) => wall.removeEventListener(ev, onInteract));
      document.removeEventListener("visibilitychange", onVis);
    };
  }, [tiles.length]);
  const goTo = (i) => {
    const wall = wallRef.current; if (!wall) return;
    if (interactRef.current) interactRef.current();
    const c = wall.children[i]; if (!c) return;
    wall.scrollTo({ left: c.offsetLeft - (wall.clientWidth - c.offsetWidth) / 2, behavior: "smooth" });
  };
  return (
    <section className="pc-sec" id="portfolio" style={{ background: "#fff" }}>
      <div ref={ref} className="pc-wrap" style={{ padding: "120px var(--pc-pad) 60px", textAlign: "center" }}>
        <div style={rise(shown, 0)}><Cap>Real Customer Examples</Cap></div>
        <h2 className="pc-h2 center" style={rise(shown, 70)}>Real customers. <span className="pc-pink">Real material.</span></h2>
        <p className="pc-lead center" style={rise(shown, 130)}>Testimonial Ads are built from actual Sayso testimonial shoots, not staged ad scripts.</p>
        <div ref={wallRef} className="pc-wall" style={{ marginTop: 52, textAlign: "left", ...rise(shown, 200) }}>
          {tiles.map((t, i) => (
            <div key={i} className={"pc-tile" + (i === active ? " is-active" : "")} role="button" tabIndex={0} style={{ cursor: "pointer", ...vReveal(shown, 220 + i * 80) }}>
              <div className="wash" />
              <VideoCardBare {...t} />
            </div>
          ))}
        </div>
        <div className="pc-dots">
          {tiles.map((_, i) => (
            <i key={i} className={i === active ? "on" : ""} onClick={() => goTo(i)} role="button" aria-label={"Go to example " + (i + 1)} />
          ))}
        </div>
      </div>
    </section>
  );
}

// a video card that fills its parent tile (no own radius/shadow).
// Poster image only — the actual video plays on click, in the lightbox.
function VideoCardBare({ src, objPos, brand, hook, person, company, city, dur }) {
  const sub = [brand, city].filter(Boolean).join(" \u00b7 ");
  const ppl = [person, company].filter(Boolean).join(" \u00b7 ");
  return (
    <div className="pc-vc live" style={{ position: "absolute", inset: 0, borderRadius: 0, boxShadow: "none" }}>
      <img src={src} alt="" draggable="false" style={{ objectPosition: objPos }} />
      <div className="scrim-top" />
      <div className="scrim" />
      <div className="pc-vtop">
        <span className="pc-acct">
          <span className="av"><img src="assets/logos/sayso-icon-avatar.png" alt="" draggable="false" /></span>
          <span className="nm">sayso.video</span>
          <span className="vf"><svg width="12" height="12" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="10" fill="var(--brand-600)" /><path d="m8 12.4 2.6 2.6L16 9.6" stroke="#fff" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" /></svg></span>
        </span>
        <span className="pc-chip2">{dur}</span>
      </div>
      <VPlay d={48} />
      <div className="pc-story">
        <p className="hook">{hook}</p>
        <div className="who2">
          {ppl ? <span className="nm">{ppl}</span> : null}
          {sub ? <span className="sb">{sub}</span> : null}
        </div>
      </div>
    </div>
  );
}

// small helper mirroring gridbuild's vReveal for staggered children
function vReveal(shown, delay = 0) {
  if (typeof matchMedia !== "undefined" && matchMedia("(prefers-reduced-motion: reduce)").matches) return {};
  const tr = { transition: `opacity 600ms cubic-bezier(.2,0,0,1) ${delay}ms, transform 600ms cubic-bezier(.2,0,0,1) ${delay}ms` };
  return shown ? { ...tr, opacity: 1, transform: "none" } : { ...tr, opacity: 0, transform: "translateY(18px)" };
}

// ── Static logo row — local <img> brand assets (user supplies SVGs) ──────────
function LogoMarquee() {
  const logos = [
    { src: "logos/n/aws.png", alt: "AWS", h: 28 },
    { src: "logos/n/monday.png", alt: "monday.com", h: 15 },
    { src: "logos/n/fiverr.png", alt: "Fiverr", h: 14 },
    { src: "logos/n/taboola.png", alt: "Taboola", h: 13 },
    { src: "logos/n/similarweb.png", alt: "SimilarWeb", h: 14 },
    { src: "logos/n/checkpoint.png", alt: "Check Point", h: 26 },
    { src: "logos/n/clarivate.png", alt: "Clarivate", h: 14 },
    { src: "logos/n/stratasys.png", alt: "Stratasys", h: 24 },
    { src: "logos/n/sapiens.png", alt: "Sapiens", h: 13 },
    { src: "logos/n/talonone.png", alt: "Talon.One", h: 30 },
    { src: "logos/n/nayax.png", alt: "Nayax", h: 14 },
    { src: "logos/n/panaya.png", alt: "Panaya", h: 18 },
    { src: "logos/n/payem.png", alt: "PayEm", h: 18 },
    { src: "logos/n/drivenets.png", alt: "DriveNets", h: 26 },
    { src: "logos/n/alma.png", alt: "Alma", h: 20 },
    { src: "logos/n/guesty.png", alt: "Guesty", h: 19 },
  ];
  return (
    <section className="pc-sec" style={{ background: "#fff" }}>
      <div className="pc-wrap" style={{ padding: "84px var(--pc-pad) 8px" }}>
        <div className="pc-marq-head">Trusted by <strong>leading marketing &amp; revenue teams</strong></div>
        <div className="logo-tick"></div>
        <div className="logo-shell">
          <span className="logo-plus" style={{ left: 0, top: "0.5px" }}></span>
          <span className="logo-plus" style={{ left: "50%", top: "0.5px" }}></span>
          <span className="logo-plus" style={{ left: "100%", top: "0.5px" }}></span>
          <span className="logo-plus" style={{ left: 0, top: "calc(100% - 0.5px)" }}></span>
          <span className="logo-plus" style={{ left: "50%", top: "calc(100% - 0.5px)" }}></span>
          <span className="logo-plus" style={{ left: "100%", top: "calc(100% - 0.5px)" }}></span>
          <div className="logo-frame">
            {logos.map((l, i) => (
              <div key={i} className="logo-cell">
                <img src={l.src} alt={l.alt} className="client-logo" style={{ maxHeight: l.h }} />
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { VID_CSS, VideoCard, VPlay, MorphStage, MorphClip, ProofWall, LogoMarquee });
