/* pages-v3.jsx — 首页视频与创始人 / 相册滚动 / 活动 / 三级课程 / 学员证言墙 / 预约表单
   本轮改造：以课程为主轴；活动与课程分开；预约收敛为一张表单。
*/

function V3Styles() {
  return (
    <style>{`
/* ================= 创始人 · 首页 ================= */
.founder{position:relative;background:var(--ink);color:var(--on-dark);overflow:hidden}
.founder-in{position:relative;display:grid;grid-template-columns:minmax(0,.62fr) minmax(0,1.38fr);gap:clamp(30px,4.6vw,74px);align-items:center;padding:clamp(48px,6vw,92px) 0}
.port-card{position:relative;background:radial-gradient(120% 90% at 50% 0%,rgba(127,196,194,.3),rgba(127,196,194,0) 62%),#0f3b3f;border:1px solid rgba(238,244,243,.16);overflow:hidden}
.port-card img{width:100%;display:block;filter:contrast(1.03) saturate(.97)}
.port-card .tagline{position:absolute;left:0;right:0;bottom:0;padding:16px 18px;background:linear-gradient(transparent,rgba(6,22,24,.92) 55%);font-family:var(--f-mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:rgba(238,244,243,.72);display:flex;justify-content:space-between;gap:10px}
.port-play{position:absolute;top:14px;right:14px;width:40px;height:40px;border-radius:50%;border:1px solid rgba(255,255,255,.4);background:rgba(11,36,38,.45);color:#fff;display:grid;place-items:center;backdrop-filter:blur(6px);transition:all .3s}
.port-play:hover{background:#fff;color:var(--ink);border-color:#fff}

.vrail{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:26px}
.vthumb{position:relative;border:0;padding:0;background:#0a2b2e;aspect-ratio:16/9;overflow:hidden;cursor:pointer}
.vthumb img{width:100%;height:100%;object-fit:cover;opacity:.82;transition:opacity .35s,transform .7s var(--ease)}
.vthumb:hover img{opacity:1;transform:scale(1.04)}
.vthumb .pl{position:absolute;inset:0;display:grid;place-items:center;color:#fff;opacity:.92}
.vthumb .pl i{width:34px;height:34px;border-radius:50%;border:1px solid rgba(255,255,255,.55);display:grid;place-items:center;font-style:normal;font-size:11px;background:rgba(0,0,0,.22)}
.vthumb .tt{position:absolute;left:8px;right:8px;bottom:7px;font-size:10.5px;line-height:1.4;color:#fff;text-align:left;text-shadow:0 1px 6px rgba(0,0,0,.8);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.vthumb .du{position:absolute;right:6px;top:6px;font-family:var(--f-mono);font-size:9px;padding:1px 5px;background:rgba(0,0,0,.55);color:#fff}

/* 播放器 */
.vplayer{position:relative;background:#0a2b2e;border:1px solid rgba(238,244,243,.14);overflow:hidden}
.vplayer video{width:100%;display:block;background:#0a2b2e}
.vplayer .meta{padding:12px 16px;display:flex;justify-content:space-between;gap:12px;align-items:center;font-family:var(--f-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:rgba(238,244,243,.55)}

/* ================= 相册滚动 ================= */
.album{position:relative;background:var(--ink);color:var(--on-dark);padding:clamp(44px,5.4vw,80px) 0 clamp(40px,4.6vw,64px);overflow:hidden}
.album-head{display:flex;align-items:flex-end;justify-content:space-between;gap:24px;flex-wrap:wrap;margin-bottom:26px}
.album-strip{display:flex;gap:clamp(10px,1.2vw,18px);overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;padding:0 var(--pad-x) 18px;scrollbar-width:none}
.album-strip::-webkit-scrollbar{display:none}
.slide{flex:none;width:clamp(268px,42vw,660px);scroll-snap-align:center;position:relative;background:#0a2b2e}
.slide img{width:100%;aspect-ratio:3/2;object-fit:cover;display:block;filter:saturate(.95)}
.slide figcaption{display:flex;justify-content:space-between;gap:14px;padding:11px 2px 0;font-family:var(--f-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:rgba(238,244,243,.55)}
.slide .no{position:absolute;left:10px;top:10px;font-family:var(--f-mono);font-size:9.5px;letter-spacing:.1em;padding:2px 7px;background:rgba(11,36,38,.6);backdrop-filter:blur(4px);color:#fff}
.album-nav{display:flex;gap:6px;align-items:center}
.album-nav button{width:38px;height:38px;border-radius:50%;border:1px solid rgba(238,244,243,.24);background:none;color:#fff;display:grid;place-items:center;transition:all .3s}
.album-nav button:hover{background:#fff;color:var(--ink);border-color:#fff}
.album-bar{height:2px;background:rgba(238,244,243,.14);margin:0 var(--pad-x);position:relative;overflow:hidden}
.album-bar i{position:absolute;left:0;top:0;bottom:0;background:var(--gold);transition:width .3s,left .3s}
.album-hint{font-family:var(--f-mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:rgba(238,244,243,.45);margin:12px var(--pad-x) 0;display:flex;justify-content:space-between;gap:16px}

/* ================= 活动 ================= */
.act-hero{background:linear-gradient(180deg,#0b2426,#0e3134);color:var(--on-dark);padding:clamp(40px,5vw,72px) 0}
.act-now{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:clamp(24px,3.4vw,48px);align-items:center;background:rgba(238,244,243,.05);border:1px solid rgba(238,244,243,.14);padding:clamp(18px,2.2vw,28px)}
.act-now .cv{position:relative;overflow:hidden;aspect-ratio:16/10;background:#0a2b2e}
.act-now .cv img{width:100%;height:100%;object-fit:cover}
.act-now .cv .badge{position:absolute;left:12px;top:12px;background:var(--gold);color:#25190a;font-family:var(--f-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;padding:3px 9px}
.act-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,1.8vw,24px)}
.act-card{background:var(--paper);border:1px solid var(--line);display:flex;flex-direction:column;transition:transform .4s var(--ease),box-shadow .4s var(--ease),border-color .4s}
.act-card:hover{transform:translateY(-3px);box-shadow:var(--shadow-float);border-color:var(--line-strong)}
.act-card .cv{position:relative;overflow:hidden;aspect-ratio:16/9;background:var(--cloud-2)}
.act-card .cv img{width:100%;height:100%;object-fit:cover;transition:transform .8s var(--ease)}
.act-card:hover .cv img{transform:scale(1.04)}
.act-card .cv .d{position:absolute;left:0;bottom:0;background:rgba(11,36,38,.82);color:#fff;font-family:var(--f-mono);font-size:10.5px;letter-spacing:.1em;padding:4px 10px;backdrop-filter:blur(6px)}
.act-card .bd{padding:18px 20px 20px;display:flex;flex-direction:column;gap:10px;flex:1}
.act-card h3{font-size:18px;line-height:1.4}
.act-facts{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--txt-2)}
.act-facts span{display:inline-flex;align-items:center;gap:5px}
.act-facts i{font-style:normal;color:var(--gold-deep);font-family:var(--f-mono);font-size:9.5px;letter-spacing:.08em;text-transform:uppercase}
.act-pts{list-style:disc;padding-left:16px;font-size:13px;color:var(--txt-2);line-height:1.7;display:grid;gap:3px}
.act-seats{display:flex;align-items:center;gap:8px;font-family:var(--f-mono);font-size:10px;letter-spacing:.1em;color:var(--gold-deep);text-transform:uppercase}
.seats-bar{height:3px;background:var(--line);flex:1;position:relative;overflow:hidden}
.seats-bar i{position:absolute;left:0;top:0;bottom:0;background:var(--gold)}
.act-foot{margin-top:auto;display:flex;align-items:center;gap:10px;padding-top:14px}
.act-src{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--txt-3);line-height:1.5}

/* 往期列表 */
.past-row{display:grid;grid-template-columns:88px minmax(0,1fr) auto auto;gap:clamp(14px,2vw,28px);align-items:center;padding:16px 0;border-bottom:1px solid var(--line-soft);transition:background .3s;cursor:pointer}
.past-row:hover{background:rgba(1,153,154,.04)}
.past-row .yr{font-family:var(--f-serif);font-size:24px;color:var(--teal-900)}
.past-row .th{display:flex;gap:8px}
.past-row .th img{width:64px;height:44px;object-fit:cover;filter:saturate(.9)}
.past-row .t{font-size:15px}
.past-row .m{font-family:var(--f-mono);font-size:10px;letter-spacing:.1em;color:var(--txt-3);text-transform:uppercase;margin-top:4px}
.past-row .go{font-family:var(--f-mono);font-size:10px;letter-spacing:.12em;color:var(--teal-700);text-transform:uppercase;white-space:nowrap}

/* ================= 三级课程 ================= */
.lv-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,1.8vw,22px);align-items:stretch}
.lv{position:relative;background:var(--paper);border:1px solid var(--line);display:flex;flex-direction:column;overflow:hidden;transition:transform .4s var(--ease),box-shadow .4s var(--ease)}
.lv:hover{transform:translateY(-4px);box-shadow:var(--shadow-float)}
.lv.open{border-color:rgba(1,153,154,.4)}
.lv .hd{padding:clamp(20px,2.2vw,26px) clamp(20px,2.2vw,26px) 0;display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
.lv .nn{font-family:var(--f-serif);font-size:34px;line-height:1;color:var(--gold);letter-spacing:-.03em}
.lv .lv-tag{font-family:var(--f-mono);font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--txt-3)}
.lv h3{font-size:clamp(20px,1.8vw,25px);margin-top:6px}
.lv .lead{font-size:14px;color:var(--txt-2);line-height:1.7;margin-top:10px;font-weight:300}
.lv .pts{display:grid;gap:8px;margin-top:18px;padding-top:16px;border-top:1px solid var(--line-soft)}
.lv .pts li{display:flex;gap:9px;font-size:13.5px;color:var(--txt-2);line-height:1.55}
.lv .pts .bx{width:13px;height:13px;flex:none;margin-top:5px;border:1px solid var(--teal-300);position:relative}
.lv .pts .bx::after{content:"";position:absolute;left:3px;top:0;width:4px;height:7px;border-right:1.3px solid var(--teal-500);border-bottom:1.3px solid var(--teal-500);transform:rotate(38deg)}
.lv .ft{padding:16px clamp(20px,2.2vw,26px) clamp(20px,2.2vw,26px);margin-top:auto}
.lv .st{display:flex;align-items:center;gap:7px;font-family:var(--f-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;margin-bottom:12px}
.lv .st.on{color:var(--teal-500)}
.lv .st.off{color:var(--txt-3)}
.lv .st .dot{width:6px;height:6px;border-radius:50%;background:currentColor;box-shadow:0 0 0 3px rgba(1,153,154,.14)}
.lv .st.off .dot{box-shadow:none}
.lv.soon{background:linear-gradient(180deg,rgba(238,243,242,.6),var(--paper))}

/* ================= 学员证言墙 ================= */
.vwall{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(10px,1.2vw,16px)}
.vcell{background:var(--paper);border:1px solid var(--line);padding:16px 16px 14px;display:flex;flex-direction:column;gap:10px;cursor:pointer;transition:transform .35s var(--ease),border-color .35s,box-shadow .35s;text-align:left}
.vcell:hover{transform:translateY(-3px);border-color:var(--line-strong);box-shadow:0 16px 34px -22px rgba(12,63,68,.4)}
.vcell img{width:46px;height:46px;border-radius:50%;object-fit:cover;filter:saturate(.9)}
.vcell .nm{font-size:12.5px;color:var(--ink);margin-top:-2px}
.vcell .q{font-family:var(--f-serif);font-size:14.5px;line-height:1.65;color:var(--teal-900);display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.vcell .more{font-family:var(--f-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--txt-3);margin-top:auto}

/* ================= 预约表单 ================= */
.form-wrap{display:grid;grid-template-columns:minmax(0,.72fr) minmax(0,1.28fr);gap:clamp(28px,4vw,72px);align-items:start}
.field{display:flex;flex-direction:column;gap:7px}
.field label{font-family:var(--f-mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--txt-3)}
.field label .req{color:var(--gold-deep)}
.field input,.field select,.field textarea{
  border:1px solid var(--line);background:var(--paper);border-radius:2px;padding:11px 13px;
  font-size:14px;color:var(--ink);outline:none;transition:border-color .3s,box-shadow .3s;width:100%;
}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--teal-500);box-shadow:0 0 0 3px rgba(1,153,154,.1)}
.field textarea{resize:vertical;min-height:96px;line-height:1.7}
.f2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.fgrid{display:grid;gap:18px}
.chips{display:flex;flex-wrap:wrap;gap:7px}
.chip{border:1px solid var(--line);background:transparent;color:var(--txt-2);padding:7px 13px;font-size:12.5px;border-radius:999px;transition:all .28s}
.chip:hover{border-color:var(--teal-700);color:var(--teal-900)}
.chip.on{background:var(--teal-900);border-color:var(--teal-900);color:#fff}
.form-note{font-size:12px;color:var(--txt-3);line-height:1.75;font-weight:300}

/* ================= 首页：课程主推 ================= */
.promo{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.86fr);gap:clamp(24px,3.4vw,60px);align-items:center}
.promo-lv{display:flex;flex-direction:column;gap:2px;border-top:1px solid var(--line)}
.promo-lv a{display:grid;grid-template-columns:44px 1fr auto;gap:16px;align-items:center;padding:17px 0;border-bottom:1px solid var(--line-soft);transition:padding-left .3s,color .3s}
.promo-lv a:hover{padding-left:8px;color:var(--teal-700)}
.promo-lv .n{font-family:var(--f-mono);font-size:10.5px;color:var(--gold-deep);letter-spacing:.1em}
.promo-lv .t{font-size:16px}
.promo-lv .s{font-family:var(--f-mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--txt-3)}

@media(max-width:1080px){
  .founder-in{grid-template-columns:1fr}
  .port-card{max-width:330px}
  .vrail{grid-template-columns:repeat(3,1fr)}
  .act-grid{grid-template-columns:1fr 1fr}
  .lv-grid{grid-template-columns:1fr}
  .vwall{grid-template-columns:repeat(3,1fr)}
  .form-wrap{grid-template-columns:1fr}
  .promo{grid-template-columns:1fr}
  .act-now{grid-template-columns:1fr}
}
@media(max-width:820px){
  .vrail{grid-template-columns:1fr 1fr}
  .act-grid{grid-template-columns:1fr}
  .vwall{grid-template-columns:1fr 1fr}
  .slide{width:min(82vw,560px)}
  .past-row{grid-template-columns:56px minmax(0,1fr) auto;row-gap:10px}
  .past-row .th{display:none}
  .past-row .go{grid-column:2/-1}
  .f2{grid-template-columns:1fr}
}
@media(max-width:560px){
  .vwall{grid-template-columns:1fr}
  .vrail{grid-template-columns:1fr}
}
`}</style>
  );
}

/* ================= 视频播放器 ================= */
function VPlayer({ v, dark }) {
  return (
    <div className="vplayer" style={dark ? null : { borderColor: 'var(--line)' }}>
      <video key={v.src} src={v.src} poster={v.poster} controls playsInline preload="metadata" />
      <div className="meta" style={dark ? null : { color: 'var(--txt-3)', borderTop: '1px solid var(--line)' }}>
        <span>{v.t}</span>
        <span>{v.dur}</span>
      </div>
    </div>
  );
}

/* 创始人区块（首页） */
function Founder() {
  const go = window.__go;
  const mine = QD.videos.filter((v) => v.kind === '朵洛莉丝');
  const [cur, setCur] = React.useState(mine[0]);
  return (
    <>
      <section className="founder">
        <div className="wrap founder-in">
          <div>
            <figure className="port-card" style={{ margin: 0 }}>
              <img src={img('doloresPhoto')} alt="朵洛莉丝·侃南" />
              <button className="port-play" onClick={() => document.getElementById('vh')?.scrollIntoView({ block: 'center' })} aria-label="播放她的访谈">
                {Ico.play()}
              </button>
              <figcaption className="tagline">
                <span>朵洛莉丝·侃南 · 1931—2014</span>
                <span>QHHT® 创立者</span>
              </figcaption>
            </figure>
          </div>
          <div>
            <div className="eyebrow on-dark" style={{ display: 'inline-flex' }}>创始人 · 原声访谈</div>
            <h2 className="d2" style={{ marginTop: 16, color: '#fff', maxWidth: '18ch' }}>
              与其听我们转述，不如听她自己讲。
            </h2>
            <p className="lede" style={{ marginTop: 18, color: 'rgba(238,244,243,.7)', maxWidth: '52ch' }}>
              这些片段来自朵奶奶生前的公开访谈，中文与英文双语字幕。她把量子催眠讲得很朴素：
              不是神秘，是把人带到能听见自己的地方。
            </p>
            <div id="vh" style={{ marginTop: 26 }}>
              <VPlayer v={cur} dark />
            </div>
            <div className="vrail">
              {mine.map((v) => (
                <button key={v.id} className="vthumb" onClick={() => setCur(v)} aria-label={v.t}>
                  <img src={v.poster} alt="" loading="lazy" />
                  <span className="pl"><i>▶</i></span>
                  <span className="du">{v.dur}</span>
                  <span className="tt">{v.t}</span>
                </button>
              ))}
            </div>
            <div style={{ marginTop: 20 }}>
              <Btn kind="quiet" onClick={() => go('library')}>全部影像与著作 →</Btn>
            </div>
          </div>
        </div>
      </section>
    </>
  );
}

/* ================= 相册滚动 ================= */
function AlbumStrip({ limit }) {
  const go = window.__go;
  const ref = React.useRef(null);
  const [pos, setPos] = React.useState({ i: 0, n: 1, p: 0 });

  const items = React.useMemo(() => {
    const out = [];
    QD.events.forEach((ev) => {
      const k = ev.photos >= 6 ? 4 : ev.photos >= 3 ? 3 : 2;
      for (let i = 1; i <= Math.min(k, ev.photos); i++) {
        out.push({ src: `assets/gallery/${ev.id}/${String(i).padStart(2, '0')}.jpg`, ev });
      }
    });
    return limit ? out.slice(0, limit) : out;
  }, [limit]);

  const onScroll = React.useCallback(() => {
    const el = ref.current; if (!el) return;
    const kids = Array.from(el.children);
    const mid = el.scrollLeft + el.clientWidth / 2;
    let best = 0, bd = 1e9;
    kids.forEach((k, i) => {
      const c = k.offsetLeft + k.offsetWidth / 2;
      const d = Math.abs(c - mid);
      if (d < bd) { bd = d; best = i; }
    });
    setPos({ i: best, n: kids.length, p: el.scrollLeft / Math.max(1, el.scrollWidth - el.clientWidth) });
  }, []);

  React.useEffect(() => { onScroll(); }, [onScroll]);

  /* 首次挂载：把第 1 张居中，否则计数会从 2 开始 */
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    const k = el.children[0];
    if (k) el.scrollLeft = Math.max(0, k.offsetLeft - (el.clientWidth - k.offsetWidth) / 2);
    requestAnimationFrame(() => onScroll());
  }, [onScroll]);

  const step = (d) => {
    const el = ref.current; if (!el) return;
    const kids = Array.from(el.children);
    const target = Math.max(0, Math.min(kids.length - 1, pos.i + d));
    const k = kids[target];
    if (k) el.scrollTo({ left: k.offsetLeft - (el.clientWidth - k.offsetWidth) / 2, behavior: 'smooth' });
  };

  const onKey = (e) => {
    if (e.key === 'ArrowRight') { e.preventDefault(); step(1); }
    if (e.key === 'ArrowLeft') { e.preventDefault(); step(-1); }
  };

  return (
    <section className="album" aria-label="往期活动相册">
      <div className="wrap">
        <div className="album-head">
          <div>
            <div className="eyebrow on-dark" style={{ display: 'inline-flex' }}>往期活动 · 2012—2019</div>
            <h2 className="d2" style={{ marginTop: 16, color: '#fff' }}>翻相册，比看介绍可信。</h2>
          </div>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
            <div className="album-nav">
              <button onClick={() => step(-1)} aria-label="上一张">‹</button>
              <button onClick={() => step(1)} aria-label="下一张">›</button>
            </div>
            <button className="btn btn-ghost btn-sm" style={{ borderColor: 'rgba(238,244,243,.28)', color: '#fff' }}
              onClick={() => go('events')}>全部 15 场 →</button>
          </div>
        </div>
      </div>
      <div className="album-strip" ref={ref} onScroll={onScroll} tabIndex={0} onKeyDown={onKey} aria-label="照片横向滚动">
        {items.map((it, i) => (
          <figure className="slide" key={it.src + i} style={{ margin: 0 }}>
            <img src={it.src} alt={`${it.ev.title} 现场照片`} loading={i < 3 ? 'eager' : 'lazy'} />
            <span className="no">{String(i + 1).padStart(2, '0')}</span>
            <figcaption>
              <span>{it.ev.date} · {it.ev.city}</span>
              <span>{it.ev.people} 人</span>
            </figcaption>
          </figure>
        ))}
      </div>
      <div className="album-bar"><i style={{ width: Math.max(6, 100 / items.length) + '%', left: pos.p * (100 - Math.max(6, 100 / items.length)) + '%' }} /></div>
      <div className="album-hint">
        <span>{items[pos.i]?.ev.title || ''}</span>
        <span>{pos.i + 1} / {items.length} · 拖动或 ← → 浏览</span>
      </div>
    </section>
  );
}

/* ================= 活动页 ================= */
function EventsPage() {
  const go = window.__go;
  const [tab, setTab] = React.useState('upcoming');
  const [detail, setDetail] = React.useState(null);

  const upcoming = QD.upcoming;
  const past = QD.events;

  return (
    <>
      <V3Styles />
      <RealStyles />
      <section className="act-hero">
        <div className="wrap">
          <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 24, flexWrap: 'wrap' }}>
            <div>
              <div className="eyebrow on-dark" style={{ display: 'inline-flex' }}>课程与活动 · 活动</div>
              <h1 className="d1" style={{ marginTop: 18, color: '#fff', fontSize: 'clamp(32px,4.2vw,58px)', maxWidth: '16ch' }}>
                下一场，什么时候。
              </h1>
            </div>
            <div style={{ display: 'flex', gap: 4, paddingBottom: 6 }}>
              {[['upcoming', '即将到来', upcoming.length], ['past', '往期活动', past.length]].map(([k, t, n]) => (
                <button key={k} onClick={() => setTab(k)}
                  style={{
                    border: '1px solid ' + (tab === k ? 'rgba(238,244,243,.8)' : 'rgba(238,244,243,.22)'),
                    background: tab === k ? '#fff' : 'transparent', color: tab === k ? 'var(--ink)' : 'rgba(238,244,243,.75)',
                    padding: '9px 18px', fontSize: 13, borderRadius: 999, transition: 'all .3s'
                  }}>{t}<span style={{ fontFamily: 'var(--f-mono)', fontSize: 9.5, marginLeft: 6, opacity: .6 }}>{n}</span></button>
              ))}
            </div>
          </div>

          {tab === 'upcoming' && (
            <div style={{ marginTop: 30 }}>
              <div className="act-now">
                <div className="cv">
                  <img src={upcoming[0].cover} alt="" />
                  <span className="badge">最近一场 · {upcoming[0].dateText}</span>
                </div>
                <div>
                  <h2 style={{ color: '#fff', fontSize: 'clamp(21px,2.2vw,30px)', lineHeight: 1.3 }}>{upcoming[0].title}</h2>
                  <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px 20px', marginTop: 18 }}>
                    {[['时间', upcoming[0].dateText], ['地点', upcoming[0].city], ['形式', upcoming[0].form], ['余位', `${upcoming[0].left} / ${upcoming[0].seats}`]].map(([a, b]) => (
                      <div key={a}>
                        <div style={{ fontFamily: 'var(--f-mono)', fontSize: 9.5, letterSpacing: '.14em', textTransform: 'uppercase', color: 'rgba(238,244,243,.45)' }}>{a}</div>
                        <div style={{ fontSize: 14, color: '#fff', marginTop: 2 }}>{b}</div>
                      </div>
                    ))}
                  </div>
                  <div style={{ display: 'flex', gap: 10, marginTop: 22, flexWrap: 'wrap' }}>
                    <Btn kind="gold" size="sm" onClick={() => go('book')}>预约这一场</Btn>
                    <Btn kind="ghost" size="sm" style={{ borderColor: 'rgba(238,244,243,.3)', color: '#fff' }}>读原文 →</Btn>
                  </div>
                </div>
              </div>

              <div className="act-grid" style={{ marginTop: 18 }}>
                {upcoming.slice(1).map((a) => <ActCard key={a.id} a={a} />)}
                <div className="act-card" style={{ justifyContent: 'center', alignItems: 'flex-start', padding: 24, background: 'rgba(238,244,243,.04)', borderColor: 'rgba(238,244,243,.14)' }}>
                  <div className="eyebrow on-dark" style={{ display: 'inline-flex' }}>之后的排期</div>
                  <p style={{ marginTop: 14, fontSize: 13.5, color: 'rgba(238,244,243,.66)', lineHeight: 1.8 }}>
                    新活动在公众号发布后会自动出现在这里。关注公众号，推文发出即收到。
                  </p>
                  <div style={{ marginTop: 16 }}><Btn kind="ghost" size="sm" style={{ borderColor: 'rgba(238,244,243,.3)', color: '#fff' }}>关注公众号</Btn></div>
                </div>
              </div>
            </div>
          )}
        </div>
      </section>

      {tab === 'past' && (
        <>
          <section style={{ paddingTop: 'clamp(30px,3.6vw,52px)', paddingBottom: 10 }}>
            <div className="wrap">
              <p className="lede" style={{ maxWidth: '62ch' }}>
                {QD.events.length} 场已经结束的课程与活动。点开任一场，可以按相册的方式一张张看当时的照片。
              </p>
            </div>
          </section>
          <AlbumStrip />
          <section style={{ padding: 'clamp(30px,3.6vw,54px) 0 clamp(50px,6vw,80px)' }}>
            <div className="wrap">
              <div className="eyebrow">全部往期</div>
              <div style={{ marginTop: 18 }}>
                {QD.events.map((ev) => (
                  <div className="past-row" key={ev.id} onClick={() => setDetail(ev)} role="button" tabIndex={0}
                    onKeyDown={(e) => { if (e.key === 'Enter') setDetail(ev); }}>
                    <div className="yr">{ev.year}</div>
                    <div>
                      <div className="t">{ev.title}</div>
                      <div className="m">{ev.date} · {ev.people} 人 · {ev.place || ev.city} · 原站 {ev.total} 张</div>
                    </div>
                    <div className="th">
                      {[1, 2, 3].map((i) => i <= ev.photos ? <img key={i} src={`assets/gallery/${ev.id}/${String(i).padStart(2, '0')}.jpg`} alt="" loading="lazy" /> : null)}
                    </div>
                    <span className="go">看相册 →</span>
                  </div>
                ))}
              </div>
            </div>
          </section>
        </>
      )}

      {detail && <PastDetail ev={detail} onClose={() => setDetail(null)} />}
    </>
  );
}

function ActCard({ a }) {
  const go = window.__go;
  const pct = Math.round(((a.seats - a.left) / a.seats) * 100);
  return (
    <article className="act-card">
      <div className="cv">
        <img src={a.cover} alt="" loading="lazy" />
        <span className="d">{a.dateText}</span>
      </div>
      <div className="bd">
        <span className="tag" style={{ alignSelf: 'flex-start' }}>{a.form} · {a.level}</span>
        <h3>{a.title}</h3>
        <div className="act-facts">
          <span><i>地点</i>{a.city}</span>
          <span><i>主讲</i>{a.teacher}</span>
        </div>
        <ul className="act-pts">{a.points.map((p) => <li key={p}>{p}</li>)}</ul>
        <div className="act-seats">
          <span>余 {a.left} / {a.seats}</span>
          <span className="seats-bar"><i style={{ width: pct + '%' }} /></span>
        </div>
        <div className="act-foot">
          <Btn kind="primary" size="sm" onClick={() => go('book')}>预约</Btn>
          <button className="btn btn-quiet" style={{ fontSize: 12.5 }}>原文 →</button>
        </div>
        <div className="act-src">{Ico.wechat()} {a.source.name} · {a.source.at} 抓取</div>
      </div>
    </article>
  );
}

/* 往期活动详情：相册翻页 */
function PastDetail({ ev, onClose }) {
  const [i, setI] = React.useState(0);
  const ref = React.useRef(null);
  const list = Array.from({ length: ev.photos }, (_, k) => `assets/gallery/${ev.id}/${String(k + 1).padStart(2, '0')}.jpg`);

  const step = (d) => {
    const n = list.length;
    const t = (i + d + n) % n;
    setI(t);
    const el = ref.current;
    if (el) { const kid = el.children[t]; if (kid) el.scrollTo({ left: kid.offsetLeft - 8, behavior: 'smooth' }); }
  };

  React.useEffect(() => {
    const h = (e) => {
      if (e.key === 'Escape') onClose();
      if (e.key === 'ArrowRight') step(1);
      if (e.key === 'ArrowLeft') step(-1);
    };
    window.addEventListener('keydown', h);
    document.body.style.overflow = 'hidden';
    return () => { window.removeEventListener('keydown', h); document.body.style.overflow = ''; };
  }, [i, onClose]);

  return (
    <div className="rl-lb" role="dialog" aria-modal="true">
      <div className="rl-lb-top">
        <div>
          <div className="t">{ev.date} · {ev.people} 人 · {ev.place || ev.city}</div>
          <div className="c">{ev.title}</div>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          <span style={{ fontFamily: 'var(--f-mono)', fontSize: 11, letterSpacing: '.1em', color: 'rgba(255,255,255,.6)' }}>{i + 1} / {list.length}</span>
          <button className="rl-close" onClick={onClose} aria-label="关闭">{Ico.close()}</button>
        </div>
      </div>
      <div className="rl-lb-body">
        <button className="rl-lb-nav l" onClick={() => step(-1)} aria-label="上一张">‹</button>
        <img src={list[i]} alt={`${ev.title} 第 ${i + 1} 张`} />
        <button className="rl-lb-nav r" onClick={() => step(1)} aria-label="下一张">›</button>
      </div>
      <div className="rl-lb-bot" ref={ref}>
        {list.map((s, k) => (
          <button key={s} className={k === i ? 'on' : ''} onClick={() => setI(k)}><img src={s} alt="" loading="lazy" /></button>
        ))}
      </div>
    </div>
  );
}

/* ================= 学员证言墙 ================= */
function VoicesWall() {
  const go = window.__go;
  const [open, setOpen] = React.useState(null);
  return (
    <>
      <V3Styles />
      <section className="sec-tight" style={{ paddingTop: 'clamp(40px,4.6vw,70px)' }}>
        <div className="wrap">
          <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 24, flexWrap: 'wrap' }}>
            <div>
              <Eyebrow>学员证言 · {QD.voices.length} 位</Eyebrow>
              <h1 className="d1" style={{ marginTop: 18, maxWidth: '16ch' }}>很多人说过话。</h1>
            </div>
            <p className="lede" style={{ maxWidth: '40ch', paddingBottom: 6, fontSize: 15 }}>
              点击任意一张看完整留言。全部为原站原文，未做删改。
            </p>
          </div>
        </div>
      </section>
      <section style={{ paddingBottom: 'clamp(44px,5vw,76px)' }}>
        <div className="wrap">
          <div className="vwall">
            {QD.voices.map((v, i) => (
              <Reveal key={v.n + i} delay={(i % 4) * 40}>
                <button className="vcell" onClick={() => setOpen(v)}>
                  <img src={v.img} alt={v.n} loading="lazy" />
                  <div className="nm">{v.n}</div>
                  <div className="q">{v.q.replace(/\n+/g, ' ')}</div>
                  <div className="more">{v.short ? '短评 · 展开' : '长文 · 展开'}</div>
                </button>
              </Reveal>
            ))}
          </div>
          <div style={{ marginTop: 28, display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center' }}>
            <Btn kind="primary" onClick={() => go('book')} arw>预约一次个案</Btn>
            <span className="form-note">证言来自学员课后留言，署名使用其微信昵称。</span>
          </div>
        </div>
      </section>
      {open && (
        <Modal onClose={() => setOpen(null)} max={620}>
          <div style={{ display: 'flex', gap: 14, alignItems: 'center', paddingBottom: 18, borderBottom: '1px solid var(--line)' }}>
            <img src={open.img} alt={open.n} style={{ width: 52, height: 52, borderRadius: '50%', objectFit: 'cover' }} />
            <div>
              <div style={{ fontSize: 15 }}>{open.n}</div>
              <div style={{ fontFamily: 'var(--f-mono)', fontSize: 10, letterSpacing: '.12em', color: 'var(--txt-3)', marginTop: 2 }}>
                {open.short ? '学员短评' : '学员长文'}
              </div>
            </div>
            <button className="btn btn-ghost btn-sm" style={{ marginLeft: 'auto' }} onClick={() => setOpen(null)}>{Ico.close()}</button>
          </div>
          <p style={{ fontFamily: 'var(--f-serif)', fontSize: 17, lineHeight: 1.82, color: 'var(--teal-900)', whiteSpace: 'pre-wrap', marginTop: 18 }}>
            {open.q}
          </p>
        </Modal>
      )}
    </>
  );
}

/* ================= 课程（三级） ================= */
function CoursesV3() {
  const go = window.__go;
  return (
    <>
      <V3Styles />
      <section className="sec-tight" style={{ paddingTop: 'clamp(42px,5vw,74px)' }}>
        <div className="wrap">
          <Eyebrow>课程 · 三个阶段</Eyebrow>
          <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 30, flexWrap: 'wrap' }}>
            <h1 className="d1" style={{ marginTop: 18, maxWidth: '15ch' }}>成为操作者，是一段长路。</h1>
            <p className="lede" style={{ maxWidth: '38ch', paddingBottom: 6 }}>
              一阶段打底，二阶段深入，三阶段仍在整理。每一阶段都有明确的前置条件。
            </p>
          </div>
        </div>
      </section>

      <section style={{ paddingBottom: 'clamp(40px,4.6vw,68px)' }}>
        <div className="wrap">
          <div className="lv-grid">
            {QD.courses3.map((c) => (
              <article key={c.id} className={'lv' + (c.status === 'open' ? ' open' : '') + (c.status === 'soon' ? ' soon' : '')}>
                <div className="hd">
                  <div>
                    <div className="lv-tag">{c.lvl} · {c.en}</div>
                    <h3>{c.t}</h3>
                  </div>
                  <div className="nn">{c.n}</div>
                </div>
                <div style={{ padding: '0 clamp(20px,2.2vw,26px)' }}>
                  <p className="lead">{c.lead}</p>
                  <div className="pts">{c.points.map((p) => <li key={p}><span className="bx" />{p}</li>)}</div>
                </div>
                <div className="ft">
                  <div className={'st ' + (c.status === 'open' ? 'on' : 'off')}>
                    <span className="dot" />{c.statusText}
                  </div>
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 8, marginBottom: 14 }}>
                    {c.meta.map(([a, b]) => (
                      <div key={a}>
                        <div style={{ fontFamily: 'var(--f-mono)', fontSize: 9, letterSpacing: '.12em', textTransform: 'uppercase', color: 'var(--txt-3)' }}>{a}</div>
                        <div style={{ fontSize: 12.5, marginTop: 2 }}>{b}</div>
                      </div>
                    ))}
                  </div>
                  <Btn kind={c.status === 'open' ? 'primary' : 'ghost'} block size="sm"
                    disabled={c.status !== 'open'}
                    onClick={() => c.status === 'open' && go('book')}>
                    {c.status === 'open' ? '报名一阶段' : c.status === 'locked' ? '需先完成一阶段' : '尚未开放'}
                  </Btn>
                </div>
              </article>
            ))}
          </div>
          <p style={{ marginTop: 18, fontSize: 12.5, color: 'var(--txt-3)', fontWeight: 300 }}>
            价格与具体排期由运营在后台配置；三阶段的课程结构定稿后会在此页与公众号同时公布。
          </p>
        </div>
      </section>

      <section className="sec" style={{ background: 'var(--cloud-2)' }}>
        <div className="wrap">
          <div className="split" style={{ alignItems: 'start' }}>
            <div>
              <Eyebrow>课程之后</Eyebrow>
              <h2 className="d2" style={{ marginTop: 16 }}>去上课，<br />还是去参加一场活动。</h2>
              <p className="lede" style={{ marginTop: 18 }}>
                活动不属于课程体系：开放日、公开课、学员聚会、案例督导。它们更短，也更容易来。
              </p>
              <div style={{ marginTop: 24, display: 'flex', gap: 12, flexWrap: 'wrap' }}>
                <Btn kind="primary" onClick={() => go('events')} arw>看即将到来的活动</Btn>
              </div>
            </div>
            <ul className="nlist">
              {[
                ['六日线下工作坊', '一阶段的实地部分，含现场个案示范与逐组点评。'],
                ['公开课与开放日', '免费或低门槛，先来听一次再决定要不要学。'],
                ['学员聚会与督导', '已结业的学员带真实个案来讨论，讲师现场回应。'],
              ].map(([a, b], i) => (
                <li key={a}><span className="k">0{i + 1}</span><div><h4>{a}</h4><p>{b}</p></div></li>
              ))}
            </ul>
          </div>
        </div>
      </section>

      <section className="sec">
        <div className="wrap">
          <SecHead eyebrow="报名之后" title="四步走进课堂" />
          <div className="grid g4">
            {[['提交预约表', '填一次信息，我们按城市与档期回你。'], ['确认条件', '十八岁以上，具备稳定自我状态，无需心理学基础。'], ['缴费与材料', '发票、学习手册与观看权限同步到公众号。'], ['测验与证书', '结课测验通过后获得一阶段证书。']].map(([a, b], i) => (
              <Reveal key={a} delay={i * 60}>
                <div style={{ paddingTop: 18, borderTop: '1px solid var(--line)' }}>
                  <div className="num">0{i + 1}</div>
                  <h4 style={{ marginTop: 10, fontSize: 17, fontFamily: 'var(--f-sans)', fontWeight: 500 }}>{a}</h4>
                  <p style={{ marginTop: 8, fontSize: 13.5, color: 'var(--txt-2)', lineHeight: 1.7, fontWeight: 300 }}>{b}</p>
                </div>
              </Reveal>
            ))}
          </div>
        </div>
      </section>
    </>
  );
}

/* ================= 预约表 ================= */
function BookForm() {
  const { requireAuth } = useAuth();
  const [sent, setSent] = React.useState(false);
  const [kind, setKind] = React.useState('课程报名');
  const [city, setCity] = React.useState('');
  const [topics, setTopics] = React.useState([]);
  const kinds = ['课程报名', '预约个案', '活动报名', '只想咨询'];
  const topicList = ['焦虑与情绪', '反复的关系模式', '身体找不到原因的不适', '人生方向', '哀伤与失去', '与父母 / 孩子', '只是想了解'];

  const toggle = (t) => setTopics((s) => s.includes(t) ? s.filter((x) => x !== t) : [...s, t]);

  const submit = (e) => {
    e.preventDefault();
    requireAuth('book', () => setSent(true));
  };

  return (
    <>
      <V3Styles />
      <section className="sec-tight" style={{ paddingTop: 'clamp(40px,4.8vw,72px)' }}>
        <div className="wrap">
          <div className="form-wrap">
            <div>
              <Eyebrow>预约 · 唯一的入口</Eyebrow>
              <h1 className="d1" style={{ marginTop: 18, fontSize: 'clamp(30px,3.6vw,48px)', maxWidth: '14ch' }}>
                先说清楚你现在的处境。
              </h1>
              <p className="lede" style={{ marginTop: 20, fontSize: 16 }}>
                我们还没有整理出一份「可以服务的人」的名单，所以先用这张表代替。
                填完之后会有人工回复，告诉你下一步合不合适。
              </p>
              <div className="card" style={{ marginTop: 28, background: 'var(--cloud-2)', border: '1px solid var(--line)' }}>
                <div className="eyebrow" style={{ marginBottom: 14 }}>几条边界</div>
                <ul style={{ display: 'grid', gap: 12 }}>
                  {[
                    '量子催眠禁止任何形式的远程操作，必须面对面。',
                    '不做医疗诊断，不替代任何治疗。',
                    '癫痫、重度精神类疾病急性期、正在服用影响意识状态的药物，请提前说明。',
                    '十八岁以下不接收。',
                  ].map((t) => (
                    <li key={t} style={{ display: 'flex', gap: 10, fontSize: 13.5, color: 'var(--txt-2)', lineHeight: 1.7, fontWeight: 300 }}>
                      <span style={{ color: 'var(--gold-deep)', flex: 'none' }}>—</span>{t}
                    </li>
                  ))}
                </ul>
              </div>
            </div>

            <div className="card" style={{ padding: 'clamp(22px,2.6vw,36px)' }}>
              {sent ? (
                <div style={{ display: 'grid', placeItems: 'center', textAlign: 'center', gap: 14, padding: '40px 0' }}>
                  <div className="checked">{Ico.check()}</div>
                  <h3 style={{ fontSize: 22, marginTop: 6 }}>表格已提交</h3>
                  <p className="form-note" style={{ maxWidth: '34ch' }}>
                    我们会在两个工作日内通过公众号回复你。如果三天没有收到消息，请在公众号里再问一句。
                  </p>
                  <button className="btn btn-ghost btn-sm" onClick={() => setSent(false)}>再填一份</button>
                </div>
              ) : (
                <form onSubmit={submit} className="fgrid">
                  <div>
                    <div className="eyebrow" style={{ marginBottom: 12 }}>我想……</div>
                    <div className="chips">
                      {kinds.map((k) => (
                        <button key={k} type="button" className={'chip' + (kind === k ? ' on' : '')} onClick={() => setKind(k)}>{k}</button>
                      ))}
                    </div>
                  </div>
                  <div className="f2">
                    <div className="field"><label>称呼 <span className="req">*</span></label><input required placeholder="怎么称呼你" /></div>
                    <div className="field"><label>微信号 <span className="req">*</span></label><input required placeholder="用于回复与通知" /></div>
                  </div>
                  <div className="f2">
                    <div className="field"><label>手机（选填）</label><input inputMode="tel" placeholder="仅用于紧急联系" /></div>
                    <div className="field">
                      <label>所在城市 <span className="req">*</span></label>
                      <input required placeholder="如：上海" value={city} onChange={(e) => setCity(e.target.value)} />
                    </div>
                  </div>
                  <div className="field">
                    <label>希望处理的议题（可多选）</label>
                    <div className="chips">
                      {topicList.map((t) => (
                        <button key={t} type="button" className={'chip' + (topics.includes(t) ? ' on' : '')} onClick={() => toggle(t)}>{t}</button>
                      ))}
                    </div>
                  </div>
                  <div className="f2">
                    <div className="field">
                      <label>是否做过量子催眠</label>
                      <select defaultValue="没有">
                        <option>没有</option><option>做过一次</option><option>做过多次</option><option>正在学习</option>
                      </select>
                    </div>
                    <div className="field">
                      <label>方便的时间</label>
                      <select defaultValue="工作日晚间">
                        <option>工作日晚间</option><option>周末</option><option>都可以</option><option>需要请假，提前约</option>
                      </select>
                    </div>
                  </div>
                  <div className="field">
                    <label>想说的话</label>
                    <textarea placeholder="最近让你觉得卡住的是什么？不必组织语言。" />
                  </div>
                  <div className="form-note">
                    提交后会先走一次关注确认（用于接收回复）。表单内容只用于这一次沟通，不会公开。
                  </div>
                  <button className="btn btn-primary btn-lg btn-block" type="submit">提交预约</button>
                </form>
              )}
            </div>
          </div>
        </div>
      </section>
    </>
  );
}

/* ================= 首页课程主推 + 活动条 ================= */
function CoursePromo() {
  const go = window.__go;
  return (
    <section className="sec">
      <div className="wrap promo">
        <div>
          <Eyebrow>主要方向 · 课程</Eyebrow>
          <h2 className="d2" style={{ marginTop: 16 }}>三级台阶，<br />每一级都有它的边界。</h2>
          <p className="lede" style={{ marginTop: 18, maxWidth: '46ch' }}>
            一阶段让人学会陪伴；二阶段学会在深水里不慌；三阶段的课程结构还在整理。
          </p>
          <div style={{ marginTop: 26 }} className="promo-lv">
            {QD.courses3.map((c) => (
              <a key={c.id} href="#c" onClick={(e) => { e.preventDefault(); go('courses'); }}>
                <span className="n">{c.lvl.replace('LEVEL ', 'L')}</span>
                <span className="t">{c.t}</span>
                <span className="s">{c.statusText}</span>
              </a>
            ))}
          </div>
        </div>
        <div>
          <div style={{ border: '1px solid var(--line)', background: 'var(--paper)' }}>
            <img src={QD.upcoming[0].cover} alt="" style={{ width: '100%', aspectRatio: '16/9', objectFit: 'cover', display: 'block' }} />
            <div style={{ padding: '20px 22px 24px' }}>
              <div className="tag gold">即将到来 · {QD.upcoming[0].dateText}</div>
              <h3 style={{ marginTop: 12, fontSize: 19, lineHeight: 1.4 }}>{QD.upcoming[0].title}</h3>
              <p style={{ marginTop: 8, fontSize: 13, color: 'var(--txt-2)', fontWeight: 300 }}>
                {QD.upcoming[0].city} · {QD.upcoming[0].form} · 余 {QD.upcoming[0].left} / {QD.upcoming[0].seats}
              </p>
              <div style={{ marginTop: 16, display: 'flex', gap: 10 }}>
                <Btn kind="primary" size="sm" onClick={() => go('events')}>活动详情</Btn>
                <Btn kind="ghost" size="sm" onClick={() => go('book')}>预约</Btn>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* 首页证言墙预览 */
function VoicesTeaser() {
  const go = window.__go;
  return (
    <section className="sec" style={{ background: 'var(--cloud-2)' }}>
      <div className="wrap">
        <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 24, flexWrap: 'wrap', marginBottom: 26 }}>
          <div>
            <Eyebrow>学员证言 · {QD.voices.length} 位</Eyebrow>
            <h2 className="d2" style={{ marginTop: 16 }}>他们说过话。</h2>
          </div>
          <Btn kind="ghost" onClick={() => go('voices')} arw>全部留言</Btn>
        </div>
        <div className="vwall">
          {QD.voices.slice(0, 8).map((v, i) => (
            <Reveal key={v.n + i} delay={(i % 4) * 40}>
              <button className="vcell" onClick={() => go('voices')}>
                <img src={v.img} alt={v.n} loading="lazy" />
                <div className="nm">{v.n}</div>
                <div className="q">{v.q.replace(/\n+/g, ' ')}</div>
              </button>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

Object.assign(window, {
  V3Styles, VPlayer, Founder, AlbumStrip, EventsPage, ActCard, PastDetail,
  VoicesWall, CoursesV3, BookForm, CoursePromo, VoicesTeaser,
});
