/* pages-v5.jsx — 第五轮
   · 统一弹窗：Sheet（标题区 / 主体 / 底部动作区，圆角、留白、关闭按钮一致）
   · 课程 + 活动合并一页（活动在课程下方）
   · 活动卡与详情：线下特色图位
   · 著作：列表 + 简介（无价格），按主题筛选
   · 视频：影院式主屏 + 章节式片单
   · 文章：小图 + 列表 / 卡片 两种排列可切换；新分类；征稿独立入口
   · 什么是量子催眠：页头配图
*/

function V5Styles() {
  return (
    <style>{`
/* ================= 统一弹窗 ================= */
.sheet-scrim{position:fixed;inset:0;z-index:1500;background:rgba(7,24,26,.52);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;padding:24px;animation:fade .3s var(--ease)}
.sheet{position:relative;width:100%;background:var(--paper);border-radius:16px;box-shadow:0 50px 120px -30px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.6) inset;overflow:hidden;animation:rise .42s var(--ease);max-height:calc(100vh - 48px);display:flex;flex-direction:column}
.sheet-hd{position:relative;padding:28px 30px 20px;background:linear-gradient(180deg,var(--cloud-2),var(--paper))}
.sheet-hd .k{font-family:var(--f-mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--teal-500)}
.sheet-hd h3{margin-top:10px;font-size:23px;line-height:1.3;padding-right:44px}
.sheet-hd p{margin-top:6px;font-size:13.5px;color:var(--txt-2);line-height:1.65;font-weight:300}
.sheet-x{position:absolute;top:22px;right:22px;width:36px;height:36px;border-radius:50%;border:1px solid var(--line);background:var(--paper);color:var(--txt-2);display:grid;place-items:center;transition:all .3s}
.sheet-x:hover{background:var(--teal-900);color:#fff;border-color:var(--teal-900)}
.sheet-bd{padding:6px 30px 26px;overflow:auto}
.sheet-ft{padding:16px 30px 22px;border-top:1px solid var(--line-soft);background:var(--cloud);display:flex;gap:10px;align-items:center}

.sum-card{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:16px 18px;border-radius:12px;background:var(--ink);color:#fff;margin-top:4px}
.sum-card .n{font-size:14.5px}
.sum-card .s{font-family:var(--f-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.5);margin-top:3px}
.sum-card .p{font-family:var(--f-serif);font-size:28px;color:var(--gold);white-space:nowrap}
.note-soft{margin-top:12px;padding:11px 14px;border-radius:10px;background:color-mix(in oklab,var(--gold) 12%,var(--paper));color:var(--gold-deep);font-size:12.5px;line-height:1.65}
.opt-list{display:grid;gap:10px;margin-top:16px}
.opt{display:grid;grid-template-columns:44px minmax(0,1fr) 20px;gap:14px;align-items:center;padding:14px 16px;border-radius:12px;border:1px solid var(--line);background:var(--paper);text-align:left;cursor:pointer;transition:all .3s var(--ease)}
.opt:hover{border-color:var(--teal-500);transform:translateY(-1px);box-shadow:0 12px 30px -18px rgba(12,63,68,.45)}
.opt.pri{border-color:color-mix(in oklab,var(--teal-500) 50%,transparent);background:color-mix(in oklab,var(--teal-500) 5%,var(--paper))}
.opt .ic{width:44px;height:44px;border-radius:12px;display:grid;place-items:center;background:var(--cloud-2);color:var(--teal-700);font-family:var(--f-serif);font-size:18px}
.opt.pri .ic{background:var(--teal-700);color:#fff}
.opt b{display:block;font-weight:500;font-size:15px;color:var(--ink)}
.opt span.d{display:block;font-size:12.5px;color:var(--txt-3);margin-top:2px;line-height:1.5}
.opt .ar{color:var(--txt-3);transition:transform .3s}
.opt:hover .ar{transform:translateX(3px);color:var(--teal-700)}
.qr-box{width:200px;height:200px;margin:8px auto 0;padding:14px;border-radius:14px;background:#fff;border:1px solid var(--line);box-shadow:0 18px 40px -26px rgba(12,63,68,.5)}
.steps-mini{display:flex;justify-content:center;gap:18px;margin-top:16px;font-size:12px;color:var(--txt-3)}
.steps-mini span{display:flex;align-items:center;gap:6px}
.steps-mini i{font-style:normal;width:18px;height:18px;border-radius:50%;background:var(--cloud-2);display:grid;place-items:center;font-family:var(--f-mono);font-size:9.5px;color:var(--teal-700)}

/* 旧弹窗统一外观（登录 / 其它沿用 .modal 的地方） */
.scrim{background:rgba(7,24,26,.52) !important;backdrop-filter:blur(8px) !important}
.modal{border-radius:16px !important;box-shadow:0 50px 120px -30px rgba(0,0,0,.55) !important}
.modal-hd{padding:28px 30px 18px !important;background:linear-gradient(180deg,var(--cloud-2),var(--paper))}
.modal-bd{padding:8px 30px 28px !important}
.x-btn{width:36px !important;height:36px !important;border:1px solid var(--line) !important;background:var(--paper) !important}
.x-btn:hover{background:var(--teal-900) !important;color:#fff !important}

/* ================= 页面锚点导航（课程 / 活动同页） ================= */
.subnav{position:sticky;top:76px;z-index:400;background:color-mix(in oklab,var(--cloud) 92%,transparent);backdrop-filter:blur(14px);border-bottom:1px solid var(--line)}
.subnav .wrap{display:flex;gap:4px;align-items:center;height:54px;overflow-x:auto;scrollbar-width:none}
.subnav a{flex:none;padding:7px 15px;border-radius:999px;font-size:13px;color:var(--txt-2);transition:all .3s}
.subnav a.on{background:var(--teal-900);color:#fff}
.subnav .r{margin-left:auto;font-family:var(--f-mono);font-size:10px;letter-spacing:.12em;color:var(--txt-3);text-transform:uppercase;white-space:nowrap}

/* ================= 活动图位 ================= */
.ev-gal{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-top:4px}
.ev-gal figure{margin:0;position:relative;overflow:hidden;aspect-ratio:4/3;background:var(--cloud-2);border-radius:6px}
.ev-gal img{width:100%;height:100%;object-fit:cover;transition:transform .7s var(--ease)}
.cv-ph{width:100%;height:100%;background:repeating-linear-gradient(135deg,var(--cloud-2),var(--cloud-2) 6px,transparent 6px,transparent 12px)}
.ev-gal figure:hover img{transform:scale(1.06)}
.ev-gal figcaption{position:absolute;left:0;right:0;bottom:0;padding:16px 8px 6px;background:linear-gradient(transparent,rgba(7,26,28,.82));color:#fff;font-size:10.5px}
.ev-gal .slot{display:grid;place-items:center;border:1px dashed var(--line-strong);background:repeating-linear-gradient(135deg,transparent 0 7px,color-mix(in oklab,var(--teal-500) 5%,transparent) 7px 14px);font-family:var(--f-mono);font-size:9.5px;letter-spacing:.1em;color:var(--txt-3);text-transform:uppercase;text-align:center;padding:8px}

/* ================= 著作列表 ================= */
.bk-filter{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:22px}
.bk-list{display:grid;grid-template-columns:repeat(2,1fr);gap:0 clamp(24px,3vw,52px)}
.bk-row{display:grid;grid-template-columns:86px minmax(0,1fr);gap:20px;padding:22px 0;border-top:1px solid var(--line);align-items:start}
.bk-row .cv{position:relative;aspect-ratio:262/422;overflow:hidden;box-shadow:0 14px 26px -16px rgba(12,63,68,.55);background:var(--cloud-2)}
.bk-row .cv img{width:100%;height:100%;object-fit:cover}
.bk-row .cv i{position:absolute;inset:0 auto 0 0;width:5px;background:linear-gradient(90deg,rgba(0,0,0,.28),transparent)}
.bk-row .no{font-family:var(--f-mono);font-size:10px;letter-spacing:.14em;color:var(--gold-deep)}
.bk-row h4{font-family:var(--f-serif);font-weight:500;font-size:18px;line-height:1.35;margin-top:4px}
.bk-row .en{font-family:var(--f-mono);font-size:9.5px;letter-spacing:.06em;color:var(--txt-3);text-transform:uppercase;margin-top:4px;line-height:1.5}
.bk-row p{margin-top:10px;font-size:13.5px;line-height:1.78;color:var(--txt-2);font-weight:300}
.bk-row .meta{display:flex;gap:8px;margin-top:10px;flex-wrap:wrap}
.bk-row .meta span{font-size:10.5px;padding:2px 8px;border-radius:999px;background:var(--cloud-2);color:var(--txt-2)}

/* ================= 视频 · 影院 ================= */
.cine{background:#061416;color:#fff;position:relative;overflow:hidden}
.cine-glow{position:absolute;inset:-20% 10% auto;height:70%;background:radial-gradient(50% 60% at 50% 40%,color-mix(in oklab,var(--teal-500) 35%,transparent),transparent 70%);pointer-events:none}
.cine-grid{position:relative;display:grid;grid-template-columns:minmax(0,1.65fr) minmax(0,1fr);gap:clamp(18px,2.4vw,34px);align-items:stretch}
.cine-screen{position:relative;border-radius:14px;overflow:hidden;background:#000;box-shadow:0 40px 90px -30px rgba(0,0,0,.8),0 0 0 1px rgba(255,255,255,.08)}
.cine-screen video{width:100%;display:block;aspect-ratio:16/9;background:#000}
.cine-screen .bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;background:linear-gradient(180deg,#0b1f21,#081819);border-top:1px solid rgba(255,255,255,.06)}
.cine-screen .bar b{font-weight:400;font-size:15px}
.cine-screen .bar span{font-family:var(--f-mono);font-size:10px;letter-spacing:.14em;color:rgba(255,255,255,.45);text-transform:uppercase}
.cine-list{display:flex;flex-direction:column;border-radius:14px;background:rgba(255,255,255,.035);border:1px solid rgba(255,255,255,.08);overflow:hidden}
.cine-list .h{padding:14px 18px;font-family:var(--f-mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.45);border-bottom:1px solid rgba(255,255,255,.07)}
.cine-item{display:grid;grid-template-columns:104px minmax(0,1fr);gap:12px;align-items:center;padding:10px 14px;border:0;background:none;color:inherit;text-align:left;cursor:pointer;border-bottom:1px solid rgba(255,255,255,.05);transition:background .3s}
.cine-item:hover{background:rgba(255,255,255,.05)}
.cine-item.on{background:color-mix(in oklab,var(--teal-500) 18%,transparent)}
.cine-item .th{position:relative;aspect-ratio:16/9;border-radius:6px;overflow:hidden;background:#0a2224}
.cine-item .th img{width:100%;height:100%;object-fit:cover;opacity:.85}
.cine-item .th em{position:absolute;right:4px;bottom:4px;font-style:normal;font-family:var(--f-mono);font-size:9px;padding:1px 5px;border-radius:3px;background:rgba(0,0,0,.7)}
.cine-item.on .th::after{content:"正在播放";position:absolute;inset:0;display:grid;place-items:center;background:rgba(1,153,154,.45);font-size:10.5px;letter-spacing:.1em}
.cine-item .t{font-size:13px;line-height:1.5;color:rgba(255,255,255,.85)}
.cine-item .n{font-family:var(--f-mono);font-size:9.5px;letter-spacing:.12em;color:rgba(255,255,255,.4);margin-bottom:3px}

/* ================= 文章 ================= */
.art-top{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;border-bottom:1px solid var(--line);padding-bottom:0}
.art-tabs{display:flex;gap:2px;overflow-x:auto;scrollbar-width:none}
.art-tabs button{flex:none;border:0;background:none;padding:12px 14px;font-size:14px;color:var(--txt-3);border-bottom:2px solid transparent;margin-bottom:-1px;transition:all .3s}
.art-tabs button.on{color:var(--ink);border-bottom-color:var(--teal-500)}
.art-tabs button small{font-family:var(--f-mono);font-size:9.5px;margin-left:4px;opacity:.6}
.view-sw{display:flex;gap:2px;padding:3px;border-radius:999px;background:var(--cloud-2)}
.view-sw button{border:0;background:none;padding:6px 12px;border-radius:999px;font-size:12px;color:var(--txt-2);display:flex;align-items:center;gap:6px}
.view-sw button.on{background:var(--paper);color:var(--ink);box-shadow:0 2px 8px -3px rgba(12,63,68,.3)}

.art-feat{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr);gap:clamp(20px,3vw,48px);align-items:center;padding:clamp(26px,3vw,40px) 0;border-bottom:1px solid var(--line);cursor:pointer}
.art-feat .cv{aspect-ratio:16/10;overflow:hidden;border-radius:10px;background:var(--cloud-2)}
.art-feat .cv img{width:100%;height:100%;object-fit:cover;transition:transform .8s var(--ease)}
.art-feat:hover .cv img{transform:scale(1.03)}
.art-feat h2{font-size:clamp(24px,2.6vw,36px);line-height:1.25;margin-top:12px}
.art-feat p{margin-top:12px;font-size:15px;line-height:1.8;color:var(--txt-2);font-weight:300}

.art-list{display:flex;flex-direction:column}
.art-row{display:grid;grid-template-columns:76px minmax(0,1fr) 148px;gap:clamp(16px,2.4vw,34px);align-items:center;padding:20px 0;border-bottom:1px solid var(--line-soft);cursor:pointer;transition:padding-left .35s var(--ease)}
.art-row:hover{padding-left:8px}
.art-row .dt{font-family:var(--f-mono);line-height:1.2}
.art-row .dt b{display:block;font-family:var(--f-serif);font-weight:400;font-size:26px;color:var(--ink)}
.art-row .dt span{font-size:9.5px;letter-spacing:.12em;color:var(--txt-3);text-transform:uppercase}
.art-row .cat{font-family:var(--f-mono);font-size:9.5px;letter-spacing:.14em;color:var(--gold-deep);text-transform:uppercase}
.art-row h3{font-size:clamp(17px,1.4vw,20px);line-height:1.4;margin-top:5px;font-family:var(--f-serif);font-weight:500;transition:color .3s}
.art-row:hover h3{color:var(--teal-700)}
.art-row p{margin-top:6px;font-size:13.5px;line-height:1.7;color:var(--txt-3);font-weight:300;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}
.art-row .th{aspect-ratio:4/3;border-radius:8px;overflow:hidden;background:var(--cloud-2)}
.art-row .th img{width:100%;height:100%;object-fit:cover;filter:saturate(.88);transition:transform .7s var(--ease)}
.art-row:hover .th img{transform:scale(1.05)}

.art-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(18px,2.2vw,32px);padding-top:26px}
.art-card{cursor:pointer}
.art-card .th{aspect-ratio:4/3;border-radius:10px;overflow:hidden;background:var(--cloud-2)}
.art-card .th img{width:100%;height:100%;object-fit:cover;transition:transform .8s var(--ease);filter:saturate(.88)}
.art-card:hover .th img{transform:scale(1.04)}
.art-card .cat{display:block;margin-top:14px;font-family:var(--f-mono);font-size:9.5px;letter-spacing:.14em;color:var(--gold-deep);text-transform:uppercase}
.art-card h3{font-size:18px;line-height:1.4;margin-top:6px;font-family:var(--f-serif);font-weight:500}
.art-card .m{margin-top:8px;font-family:var(--f-mono);font-size:10px;color:var(--txt-3);letter-spacing:.08em}

.cfp{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:22px;align-items:center;padding:22px 26px;border-radius:14px;background:linear-gradient(120deg,var(--ink),var(--teal-800));color:#fff}
.cfp .ic{width:52px;height:52px;border-radius:14px;background:rgba(255,255,255,.1);display:grid;place-items:center;font-family:var(--f-serif);font-size:22px;color:var(--gold)}
.cfp b{display:block;font-weight:400;font-family:var(--f-serif);font-size:20px}
.cfp p{margin-top:4px;font-size:13px;color:rgba(255,255,255,.7);line-height:1.7}

/* ================= 什么是量子催眠 · 页头 ================= */
.learn-hd{position:relative;overflow:hidden;background:var(--ink);color:#fff}
.learn-hd img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:70% 50%}
.learn-hd::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,rgba(11,36,38,.96) 0%,rgba(11,36,38,.82) 38%,rgba(11,36,38,.15) 72%,transparent)}
.learn-hd .wrap{position:relative;z-index:1;padding-top:clamp(48px,6vw,96px);padding-bottom:clamp(44px,5.6vw,88px)}

@media(max-width:1080px){
  .cine-grid{grid-template-columns:1fr}
  .bk-list{grid-template-columns:1fr}
  .art-feat{grid-template-columns:1fr}
  .art-grid{grid-template-columns:1fr 1fr}
}
@media(max-width:820px){
  .ev-gal{grid-template-columns:repeat(2,1fr)}
  .art-row{grid-template-columns:minmax(0,1fr) 96px;gap:14px}
  .art-row .dt{display:none}
  .cfp{grid-template-columns:1fr;text-align:left}
  .learn-hd::after{background:linear-gradient(180deg,rgba(11,36,38,.55),rgba(11,36,38,.95) 70%)}
  .sheet-hd,.sheet-bd,.sheet-ft{padding-left:20px;padding-right:20px}
}
@media(max-width:560px){
  .art-grid{grid-template-columns:1fr}
  .bk-row{grid-template-columns:70px minmax(0,1fr);gap:14px}
  .sheet-scrim{padding:0;align-items:flex-end}
  .sheet{border-radius:18px 18px 0 0;max-height:92vh}
}
`}</style>
  );
}

/* ================= 统一弹窗组件 ================= */
function Sheet({ onClose, kicker, title, sub, children, footer, max = 480 }) {
  React.useEffect(() => {
    const h = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', h);
    document.body.style.overflow = 'hidden';
    return () => { window.removeEventListener('keydown', h); document.body.style.overflow = ''; };
  }, [onClose]);
  return (
    <div className="sheet-scrim" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="sheet" style={{ maxWidth: max }} role="dialog" aria-modal="true">
        <V3Styles /><V5Styles />
        <div className="sheet-hd">
          {kicker && <div className="k">{kicker}</div>}
          {title && <h3>{title}</h3>}
          {sub && <p>{sub}</p>}
          <button className="sheet-x" onClick={onClose} aria-label="关闭">{Ico.close()}</button>
        </div>
        <div className="sheet-bd">{children}</div>
        {footer && <div className="sheet-ft">{footer}</div>}
      </div>
    </div>
  );
}

/* 课程报名弹窗（重做） */
function EnrollSheet5({ c, bundle, onClose }) {
  const [mode, setMode] = React.useState(null);
  const name = bundle ? '职业催眠师套餐' : c.t;
  const sub = bundle ? '一阶段 + 二阶段 · 同时报名' : c.en;
  const price = bundle ? c.bundle.priceText : c.priceText;
  const locked = c.status === 'locked' && !bundle;
  const titles = { pay: '微信扫码付款', service: '添加课程顾问', mp: '关注公众号报名' };

  if (mode) {
    return (
      <Sheet onClose={onClose} kicker={name + ' · ' + price} title={titles[mode]}
        sub={mode === 'pay' ? '付款完成后，课程会在公众号自动开通。' : mode === 'service' ? `${QD.enroll.serviceName} · 工作日 10:00–21:00` : '关注后，在公众号菜单「课程报名」中完成。'}
        footer={<>
          <button className="btn btn-quiet" style={{ fontSize: 13 }} onClick={() => setMode(null)}>← 换一种方式</button>
          <span style={{ flex: 1 }} />
          {mode === 'pay' && <a className="btn btn-primary btn-sm" href={QD.enroll.payUrl}>打开付款页面</a>}
          {mode === 'service' && <button className="btn btn-primary btn-sm" onClick={() => navigator.clipboard && navigator.clipboard.writeText(QD.enroll.serviceWx)}>复制微信号</button>}
          {mode === 'mp' && <button className="btn btn-primary btn-sm" onClick={onClose}>我已关注</button>}
        </>}>
        <div style={{ textAlign: 'center', paddingTop: 10 }}>
          <div className="qr-box"><QrCanvas ticket={mode + c.id + (bundle ? 'b' : '')} /></div>
          {mode === 'service' && <div style={{ marginTop: 14, fontSize: 13.5 }}>微信号 <b style={{ fontFamily: 'var(--f-mono)', fontWeight: 500 }}>{QD.enroll.serviceWx}</b></div>}
          <div className="steps-mini">
            <span><i>1</i>微信扫码</span>
            <span><i>2</i>{mode === 'pay' ? '确认付款' : mode === 'service' ? '发送「报名」' : '点菜单'}</span>
            <span><i>3</i>{mode === 'pay' ? '自动开通' : '顾问跟进'}</span>
          </div>
        </div>
      </Sheet>
    );
  }

  return (
    <Sheet onClose={onClose} kicker="课程报名" title="选择报名方式" sub="三种方式结果相同，按你习惯的来。">
      <div className="sum-card">
        <div><div className="n">{name}</div><div className="s">{sub}</div></div>
        <div className="p">{price}</div>
      </div>
      {locked && <div className="note-soft">二阶段需先完成一阶段并取得证书。还没学过一阶段？选「职业套餐」一次报名两阶段更省。</div>}
      <div className="opt-list">
        <button className="opt pri" onClick={() => setMode('pay')}>
          <span className="ic">¥</span>
          <span><b>直接付款</b><span className="d">跳转微信课程平台，付款后自动开通</span></span>
          <span className="ar">→</span>
        </button>
        <button className="opt" onClick={() => setMode('service')}>
          <span className="ic">{Ico.wechat({ width: 18, height: 18 })}</span>
          <span><b>先咨询课程顾问</b><span className="d">问清楚适不适合、档期与分期</span></span>
          <span className="ar">→</span>
        </button>
        <button className="opt" onClick={() => setMode('mp')}>
          <span className="ic">◎</span>
          <span><b>关注公众号报名</b><span className="d">在公众号菜单中完成报名</span></span>
          <span className="ar">→</span>
        </button>
      </div>
    </Sheet>
  );
}

/* 覆盖 v4 的 CourseCards 内部弹窗 */
window.EnrollSheet = EnrollSheet5;

/* ================= 活动卡（带图位） ================= */
function EventGallery({ a }) {
  const g = a.gallery || [];
  const slots = Math.max(0, 4 - g.length);
  return (
    <div className="ev-gal">
      {g.map(([src, cap]) => <figure key={src}><img src={src} alt={cap} loading="lazy" /><figcaption>{cap}</figcaption></figure>)}
      {Array.from({ length: slots }).map((_, i) => <figure key={'s' + i} className="slot">现场照片<br />活动后由后台上传</figure>)}
    </div>
  );
}

function UpcomingCard5({ a, big }) {
  const go = window.__go;
  const s = dparts(a.start), e = dparts(a.end);
  return (
    <article className="ev-top" style={big ? null : { gridTemplateColumns: '1fr' }}>
      {big && (
        <div className="cv">
          {a.cover ? <img src={a.cover} alt="" /> : <div className="cv-ph" style={{ aspectRatio: '16/9' }} />}
          <div className="cd"><b>{Math.max(0, Math.ceil((new Date(a.start) - new Date('2026-11-03')) / 864e5)) || '—'}</b>天后开始</div>
        </div>
      )}
      <div className="bd" style={big ? null : { padding: 'clamp(20px,2.2vw,28px)' }}>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}><V6Styles /><span className="ev-flag">活动 · 报名中</span><span className="tag">{a.form} · {a.level}</span></div>
        <h3 style={{ fontSize: big ? 'clamp(20px,2vw,27px)' : 19, lineHeight: 1.35 }}>{a.title}</h3>
        <div className="big-when">
          <div>
            <div className="k">时间</div>
            <div className="v">{s.mn} 月 {s.d} 日{a.days > 1 ? ` — ${e.mn !== s.mn ? e.mn + ' 月 ' : ''}${e.d} 日` : ''}</div>
            <div className="s">{s.y} · {s.w}{a.days > 1 ? ` 起 · 共 ${a.days} 天` : ''}</div>
          </div>
          <div>
            <div className="k">地点</div>
            <div className="v">{a.city}</div>
            <div className="s">{a.venue}</div>
          </div>
        </div>
        <div>
          <div style={{ fontFamily: 'var(--f-mono)', fontSize: 9.5, letterSpacing: '.16em', textTransform: 'uppercase', color: 'var(--txt-3)', marginBottom: 8 }}>现场是这样的</div>
          <EventGallery a={a} />
        </div>
        <div className="act-seats"><span>余位 {a.left} / {a.seats}</span><span className="seats-bar"><i style={{ width: Math.round((a.seats - a.left) / a.seats * 100) + '%' }} /></span><span>截止 {a.deadline.slice(5).replace('-', '.')}</span></div>
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
          <Btn kind="primary" size="sm" onClick={() => go('book')}>报名这一场</Btn>
          <a className="btn btn-ghost btn-sm" href={a.url}>读公众号原文 →</a>
        </div>
      </div>
    </article>
  );
}

/* ================= 课程 + 活动 合并页 ================= */
function CoursesEventsPage() {
  const go = window.__go;
  const [sec, setSec] = React.useState('c');
  const [pastOpen, setPastOpen] = React.useState(null);

  React.useEffect(() => {
    const h = () => {
      const ev = document.getElementById('sec-events');
      const past = document.getElementById('sec-past');
      const y = window.scrollY + 160;
      setSec(past && y >= past.offsetTop ? 'p' : ev && y >= ev.offsetTop ? 'e' : 'c');
    };
    window.addEventListener('scroll', h, { passive: true });
    if (!window.__scrollTo && window.__route === 'events') window.__scrollTo = 'sec-events';
    if (window.__scrollTo) { const id = window.__scrollTo; window.__scrollTo = null; setTimeout(() => jump(id), 80); }
    return () => window.removeEventListener('scroll', h);
  }, []);

  const jump = (id) => { const el = document.getElementById(id); if (el) window.scrollTo({ top: el.offsetTop - 130, behavior: 'smooth' }); };

  if (pastOpen) return <PastEventDetail ev={pastOpen} onBack={() => { setPastOpen(null); setTimeout(() => jump('sec-past'), 60); }} />;

  return (
    <>
      <V3Styles /><V4Styles /><V5Styles />
      <section className="sec-tight" style={{ paddingTop: 'clamp(42px,5vw,74px)', paddingBottom: 'clamp(24px,3vw,40px)' }}>
        <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: '40ch', paddingBottom: 6 }}>
              上方是三个阶段的课程与价格；往下是即将到来的活动——还没决定之前，可以先来一场。
            </p>
          </div>
        </div>
      </section>

      <div className="subnav">
        <div className="wrap">
          {[['c', 'sec-courses', '课程 · 三个阶段'], ['e', 'sec-events', '即将到来的活动'], ['p', 'sec-past', '往期活动']].map(([k, id, t]) => (
            <a key={k} href={'#' + id} className={sec === k ? 'on' : ''} onClick={(e) => { e.preventDefault(); jump(id); }}>{t}</a>
          ))}
          <a href="#g" onClick={(e) => { e.preventDefault(); go('gallery'); }}>活动相册 →</a>
          <span className="r">一、二阶段各 ¥12,800 · 套餐 ¥24,000</span>
        </div>
      </div>

      <section id="sec-courses" style={{ padding: 'clamp(30px,3.4vw,48px) 0 clamp(44px,5vw,72px)' }}>
        <div className="wrap">
          <CourseCards />
          <p style={{ marginTop: 18, fontSize: 12.5, color: 'var(--txt-3)', fontWeight: 300 }}>
            价格单位为人民币，含教材与证书。三阶段的课程结构与价格定稿后，会在此页与公众号同时公布。
          </p>
        </div>
      </section>

      <section id="sec-events" className="sec" style={{ background: 'var(--cloud-2)' }}>
        <div className="wrap">
          <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 20, flexWrap: 'wrap', marginBottom: 26 }}>
            <div>
              <Eyebrow>活动 · 即将到来</Eyebrow>
              <h2 className="d2" style={{ marginTop: 14 }}>下一场，什么时候。</h2>
            </div>
            <span className="act-src">{Ico.wechat()} 由公众号推文自动抓取，经人工确认</span>
          </div>
          <UpcomingCard5 a={QD.upcoming[0]} big />
          <div className="ev-list" style={{ marginTop: 18 }}>
            {QD.upcoming.slice(1).map((a) => <UpcomingCard5 key={a.id} a={a} />)}
          </div>
        </div>
      </section>

      <section id="sec-past" className="sec">
        <div className="wrap">
          <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 20, flexWrap: 'wrap', marginBottom: 26 }}>
            <div>
              <Eyebrow>往期活动 · {QD.events.length} 场</Eyebrow>
              <h2 className="d2" style={{ marginTop: 14 }}>2012 — 2019</h2>
            </div>
            <Btn kind="ghost" onClick={() => go('gallery')} arw>进入活动相册</Btn>
          </div>
          <div className="past-grid">
            {QD.events.map((ev) => (
              <button key={ev.id} className="past-card" onClick={() => { setPastOpen(ev); window.scrollTo(0, 0); }}>
                <div className="cv">{ev.cover ? <img src={ev.cover} alt="" loading="lazy" /> : <div className="cv-ph" />}<span className="ended">已结束</span></div>
                <div className="bd">
                  <span className="ev-flag past" style={{ alignSelf: 'flex-start' }}>往期活动</span>
                  <span className="yr">{ev.date}</span>
                  <h3>{ev.title}</h3>
                  <p>{ev.intro}</p>
                  <div className="m"><span>{ev.place || ev.city}</span><span>{ev.people} 人参加</span></div>
                </div>
              </button>
            ))}
          </div>
        </div>
      </section>
    </>
  );
}

/* ================= 著作与影像页 ================= */
function LibraryPage() {
  const go = window.__go;
  const [th, setTh] = React.useState('全部');
  const list = th === '全部' ? QD.books : QD.books.filter((b) => b.theme === th);
  return (
    <>
      <V3Styles /><V5Styles />
      <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: '16ch' }}>她写下的，和她留下的。</h1>
            <p className="lede" style={{ maxWidth: '40ch', paddingBottom: 6 }}>
              朵洛莉丝一生写了二十余本书，全部来自催眠个案的逐字记录。这里是每本书讲什么的简介。
            </p>
          </div>
        </div>
      </section>

      <CinemaSection />

      <section className="sec">
        <div className="wrap">
          <SecHead eyebrow={'著作 · ' + QD.books.length + ' 本'} title="每本书，大概在说什么" />
          <div className="bk-filter">
            {QD.bookThemes.map((t) => (
              <button key={t} className={'chip' + (th === t ? ' on' : '')} onClick={() => setTh(t)}>
                {t}<span style={{ fontFamily: 'var(--f-mono)', fontSize: 9.5, marginLeft: 5, opacity: .6 }}>{t === '全部' ? QD.books.length : QD.books.filter((b) => b.theme === t).length}</span>
              </button>
            ))}
          </div>
          <div className="bk-list">
            {list.map((b) => (
              <div className="bk-row" key={b.img} onClick={() => go('library')} role="button" tabIndex={0}
                onKeyDown={(e) => { if (e.key === 'Enter') go('library'); }} style={{ cursor: 'pointer' }}>
                <div className="cv"><img src={b.img} alt={'《' + b.t + '》'} loading="lazy" /><i /></div>
                <div>
                  <span className="no">{String(QD.books.indexOf(b) + 1).padStart(2, '0')} · {b.year || '—'}</span>
                  <h4>{b.t}</h4>
                  <div className="en">{b.en}</div>
                  <p>{b.intro}</p>
                  <div className="meta"><span>{b.lang === '英语' ? '英文版' : b.lang + '版'}</span><span>看简介 →</span></div>
                </div>
              </div>
            ))}
          </div>
          <p className="form-note" style={{ marginTop: 22 }}>本站不销售实体书籍，仅作介绍。</p>
        </div>
      </section>

      <section className="sec" style={{ background: 'var(--cloud-2)' }}>
        <div className="wrap">
          <SecHead eyebrow="更多影像" title="课程、花絮与学员" />
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(240px,1fr))', gap: 12 }}>
            {QD.videosOther.map((v, i) => {
              /* 兼容两种形态：本地三元组 ["标题","分类","时长"] 与接口对象 */
              const t = Array.isArray(v) ? v[0] : (v.t || v.title || '');
              const k = Array.isArray(v) ? v[1] : (v.kind || '');
              const d = Array.isArray(v) ? v[2] : (v.du || v.dur || '');
              return (
                <div key={t || i} style={{ display: 'grid', gridTemplateColumns: '44px 1fr', gap: 12, alignItems: 'center', padding: '12px 14px', background: 'var(--paper)', border: '1px solid var(--line)', borderRadius: 10 }}>
                  <span style={{ width: 44, height: 44, borderRadius: 10, background: 'var(--teal-900)', color: '#fff', display: 'grid', placeItems: 'center' }}>{Ico.play()}</span>
                  <div>
                    <div style={{ fontSize: 13.5, lineHeight: 1.45 }}>{t}</div>
                    <div style={{ fontFamily: 'var(--f-mono)', fontSize: 9.5, color: 'var(--txt-3)', letterSpacing: '.1em', marginTop: 3 }}>{k} · {d}</div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </section>
    </>
  );
}

/* ================= 影院式视频区 ================= */
function CinemaSection({ title = '听她自己讲', kicker = '朵洛莉丝 · 原声访谈', step }) {
  const go = window.__go;
  const list = QD.videos;
  const [cur, setCur] = React.useState(list[0]);
  const ref = React.useRef(null);
  const pick = (v) => { setCur(v); setTimeout(() => { const el = ref.current; if (el) { el.load(); el.play().catch(() => { }); } }, 30); };
  return (
    <section className="cine sec">
      <V5Styles />
      <div className="cine-glow" />
      <div className="wrap" style={{ position: 'relative' }}>
        <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 20, flexWrap: 'wrap', marginBottom: 26 }}>
          <div>
            {step ? <div className="step-tag" style={{ color: 'var(--gold)' }}><i>{step}</i>{kicker}</div>
              : <div className="eyebrow on-dark" style={{ display: 'inline-flex' }}>{kicker}</div>}
            <h2 className="d2" style={{ marginTop: 14, color: '#fff' }}>{title}</h2>
          </div>
          <p style={{ maxWidth: '40ch', fontSize: 14, lineHeight: 1.8, color: 'rgba(255,255,255,.62)' }}>中英双语字幕。从「什么是量子催眠」开始，到「为什么要成为一名操作者」。</p>
        </div>
        <div className="cine-grid">
          <div className="cine-screen">
            <video ref={ref} key={cur.src} src={cur.src} poster={cur.poster} controls playsInline preload="metadata" />
            <div className="bar"><b>{cur.t}</b><span>{cur.dur} · {cur.en}</span></div>
          </div>
          <div className="cine-list">
            <div className="h">片单 · {list.length} 支</div>
            {list.map((v, i) => (
              <button key={v.id} className={'cine-item' + (cur.id === v.id ? ' on' : '')} onClick={() => pick(v)}>
                <span className="th"><img src={v.poster} alt="" loading="lazy" /><em>{v.dur}</em></span>
                <span>
                  <span className="n" style={{ display: 'block' }}>{String(i + 1).padStart(2, '0')} · {v.kind}</span>
                  <span className="t" style={{ display: 'block' }}>{v.t.replace('朵洛莉丝·侃南', '')}</span>
                </span>
              </button>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

/* ================= 文章页 ================= */
function PostsPage() {
  const go = window.__go;
  const [cat, setCat] = React.useState('全部');
  const [view, setView] = React.useState(() => localStorage.getItem('qhht-artview') || 'list');
  const [cfp, setCfp] = React.useState(false);
  React.useEffect(() => { localStorage.setItem('qhht-artview', view); }, [view]);
  const list = cat === '全部' ? QD.posts : QD.posts.filter((p) => p.cat === cat);
  const [feat, ...rest] = list;
  const d = (s) => { const [y, m, dd] = s.split('-'); return { y, md: m + '.' + dd, dd }; };

  return (
    <>
      <V5Styles />
      <section className="sec-tight" style={{ paddingTop: 'clamp(42px,5vw,74px)', paddingBottom: 20 }}>
        <div className="wrap">
          <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 24, flexWrap: 'wrap' }}>
            <div>
              <Eyebrow>文章 · 同步自公众号</Eyebrow>
              <h1 className="d1" style={{ marginTop: 18 }}>阅读</h1>
              <div style={{ marginTop: 12, display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: 'var(--txt-3)' }}><V6Styles /><WxBadge text="量子催眠中国" />带此标记的文章同步自公众号，可一键跳转原文</div>
            </div>
            <button className="btn btn-ghost btn-sm" onClick={() => setCfp(true)}>✎ 征稿 · 投递你的故事</button>
          </div>
          <div className="art-top" style={{ marginTop: 28 }}>
            <div className="art-tabs">
              {QD.postCats.map((c) => (
                <button key={c} className={cat === c ? 'on' : ''} onClick={() => setCat(c)}>
                  {c}<small>{c === '全部' ? QD.posts.length : QD.posts.filter((p) => p.cat === c).length}</small>
                </button>
              ))}
            </div>
            <div className="view-sw" role="group" aria-label="排列方式">
              <button className={view === 'list' ? 'on' : ''} onClick={() => setView('list')}>☰ 列表</button>
              <button className={view === 'grid' ? 'on' : ''} onClick={() => setView('grid')}>▦ 卡片</button>
            </div>
          </div>
        </div>
      </section>

      <section style={{ paddingBottom: 'clamp(48px,6vw,84px)' }}>
        <div className="wrap">
          {view === 'list' && feat && (
            <>
              <div className="art-feat" onClick={() => go('post', feat.id)}>
                <div className="cv"><img src={feat.img} alt="" /></div>
                <div>
                  <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}><span className="tag gold">{feat.cat}</span>{feat.src === 'wechat' && <WxBadge text={'同步自公众号 · ' + (feat.wx || '量子催眠中国')} />}</div>
                  <h2>{feat.t}</h2>
                  <p>{feat.ex}</p>
                  <div style={{ marginTop: 16, fontFamily: 'var(--f-mono)', fontSize: 10.5, letterSpacing: '.1em', color: 'var(--txt-3)' }}>{feat.date.replace(/-/g, '.')} · {feat.read.toLocaleString()} 阅读</div>
                </div>
              </div>
              <div className="art-list">
                {rest.map((p) => {
                  const dt = d(p.date);
                  return (
                    <div key={p.id} className="art-row" onClick={() => go('post', p.id)}>
                      <div className="dt"><b>{dt.md}</b><span>{dt.y}</span></div>
                      <div>
                        <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}><span className="cat">{p.cat}</span>{p.src === 'wechat' && <WxBadge />}</div>
                        <h3>{p.t}</h3>
                        <p>{p.ex}</p>
                      </div>
                      <div className="th"><img src={p.img} alt="" loading="lazy" /></div>
                    </div>
                  );
                })}
              </div>
            </>
          )}
          {view === 'grid' && (
            <div className="art-grid">
              {list.map((p) => (
                <div key={p.id} className="art-card" onClick={() => go('post', p.id)}>
                  <div className="th"><img src={p.img} alt="" loading="lazy" /></div>
                  <div style={{ display: 'flex', gap: 10, alignItems: 'center', marginTop: 14, flexWrap: 'wrap' }}><span className="cat" style={{ marginTop: 0 }}>{p.cat}</span>{p.src === 'wechat' && <WxBadge />}</div>
                  <h3>{p.t}</h3>
                  <div className="m">{p.date.replace(/-/g, '.')} · {p.read.toLocaleString()} 阅读</div>
                </div>
              ))}
            </div>
          )}
          {!list.length && <p className="form-note" style={{ padding: '40px 0' }}>这个分类下暂时还没有文章。</p>}

          <div className="cfp" style={{ marginTop: 'clamp(36px,4vw,56px)' }}>
            <span className="ic">✎</span>
            <div><b>{QD.callForPapers.t}</b><p>{QD.callForPapers.d}</p></div>
            <button className="btn btn-gold btn-sm" onClick={() => setCfp(true)}>我要投稿</button>
          </div>
        </div>
      </section>

      {cfp && (
        <Sheet onClose={() => setCfp(false)} kicker="征稿" title="投递你的量子催眠故事" sub="个案体会、学习手记、操作者感悟均可。经编辑整理后发布，发布前会与你确认。"
          footer={<><span className="form-note">也可直接发邮件：{QD.callForPapers.mail}</span><span style={{ flex: 1 }} /><button className="btn btn-primary btn-sm" onClick={() => setCfp(false)}>提交</button></>}>
          <div className="fgrid" style={{ paddingTop: 8 }}>
            <div className="f2">
              <div className="field"><label>署名</label><input placeholder="可用昵称" /></div>
              <div className="field"><label>微信号</label><input placeholder="用于编辑联系" /></div>
            </div>
            <div className="field"><label>身份</label>
              <select defaultValue="来访者"><option>来访者</option><option>学员</option><option>持证操作者</option></select>
            </div>
            <div className="field"><label>标题</label><input placeholder="一句话说说这是个什么故事" /></div>
            <div className="field"><label>正文</label><textarea style={{ minHeight: 140 }} placeholder="不必组织得很完整，编辑会帮你整理。" /></div>
          </div>
        </Sheet>
      )}
    </>
  );
}

/* ================= 什么是量子催眠 · 页头 ================= */
function LearnHeader() {
  return (
    <section className="learn-hd">
      <V5Styles />
      <img src={img('learnHero')} alt="" />
      <div className="wrap">
        <div className="eyebrow on-dark" style={{ display: 'inline-flex' }}>理解 · 第一层</div>
        <h1 className="d1" style={{ marginTop: 20, color: '#fff', maxWidth: '12ch' }}>什么是量子催眠</h1>
        <p className="lede" style={{ marginTop: 22, maxWidth: '46ch', color: 'rgba(238,244,243,.75)' }}>
          量子催眠（Quantum Healing Hypnosis Technique，QHHT®）是回溯催眠大师朵洛莉丝·侃南
          基于近五十年实践锤炼而成的一种独特催眠技术。
        </p>
        <div style={{ marginTop: 28, display: 'flex', gap: 22, flexWrap: 'wrap', fontFamily: 'var(--f-mono)', fontSize: 10.5, letterSpacing: '.14em', color: 'rgba(238,244,243,.5)', textTransform: 'uppercase' }}>
          <span>约 8 分钟阅读</span><span>技术说明 · 非医疗建议</span>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, {
  V5Styles, Sheet, EnrollSheet5, EventGallery, UpcomingCard5, CoursesEventsPage,
  LibraryPage, CinemaSection, PostsPage, LearnHeader,
});
