// 赛博宝宝前端（2026-10-21 从 index.html 的内联 <script type="text/babel"> 原样搬出）：App 的主界面：顶栏、房间、三围、操作按钮（院子在 app-yard-view.jsx，面板弹窗在 app-overlays.jsx）。
// index.html 按顺序加载 app/*.jsx，前面文件定义的全局（函数、常量、组件）后面的文件直接用。
// App 拆成几段函数，按原来的顺序每次渲染都调用；上一段的局部变量放进 bag 递给下一段（hook 调用顺序不变）。
function appDerived(bag) {
  const { octoBlink, octoEating, octoHeartFrame, octoHungryFrame, octoReaction, state, weatherState } = bag;
  // ===== 渲染 =====
  const weatherView = getWeatherView(weatherState);
  const pCfg = getParticleConfig(weatherState);
  const particleData = Array.from({ length: pCfg.count }).map((_, i) => ({
    cls: pCfg.cls, bg: pCfg.bg, size: pCfg.size,
    left: `${5 + seededRand(i, 1) * 90}%`,
    top: `${5 + seededRand(i, 2) * (pCfg.cls === 'rain' ? 30 : 85)}%`,
    delay: `${seededRand(i, 3) * 6}s`,
    duration: pCfg.cls === 'rain' ? `${0.5 + seededRand(i, 4) * 0.6}s` : `${4 + seededRand(i, 4) * 4}s`,
  }));
  const pupiSprite = getPupiSprite(state.day, state.cleanliness, state.happiness);
  const ownedFurniture = (state.inventory || []).filter(i => i.item_type === 'furniture').map(i => ({
    id: i.item_id,
    savedPos: i.position ? JSON.parse(i.position) : null,
  }));
  const hasOctopus = state.egg?.hatched;
  const lanternWishes = state.lanternWishes || null;
  const lanternComplete = !!(lanternWishes && (lanternWishes.mama || lanternWishes.mama_wish) && (lanternWishes.baby || lanternWishes.baby_wish) && (lanternWishes.daddy || lanternWishes.daddy_wish));
  const mamaName = state.youAre === 'mama' ? state.yourName : state.partnerName;
  const daddyName = state.youAre === 'daddy' ? state.yourName : state.partnerName;
  let lanternLocal = false;
  try { lanternLocal = localStorage.getItem(`qixi_lantern_${state.babyId}`) === '1'; } catch (e) {}
  const showLantern = !!(state.hasLantern || lanternWishes || lanternLocal);
  // 2026-08-17：探险只有 parent1 能接，掉落那一刻另一位家长根本不在场。
  // 后端现在把掉落落库了（lanternStage: dropped/waiting/lit），谁进屋看见暗着的灯，
  // 点一下就能从头走许愿流程——不然这条路只有接宝宝那个人开得了头。
  const lanternNeedsMyWish = state.lanternStage === 'dropped' && !lanternWishes;

  // 章鱼表情：根据状态选择图片文件名
  const octoImg = (() => {
    const isHearteye = octoReaction === 'hearteye';
    if (isHearteye) return `hearteye_frame${octoHeartFrame}`;
    if (octoEating) return `hungry_frame${octoHungryFrame}`;
    if (octoReaction) return `octopus_${octoReaction}`;
    if (state.isTantrum) return 'octopus_angry';
    if (state.isComa) return 'octopus_dizzy';
    return octoBlink ? 'octopus_open' : 'octopus_closed';
  })();

  const dirtyLevel = state.cleanliness < 30 ? 3 : state.cleanliness < 50 ? 2 : state.cleanliness < 70 ? 1 : 0;
  const advStatus = state.adventure?.status;
  const isAdventuring = advStatus === 'exploring' || advStatus === 'ready' || advStatus === 'failed';

  return { advStatus, daddyName, dirtyLevel, hasOctopus, isAdventuring, lanternComplete, lanternNeedsMyWish, lanternWishes, mamaName, octoImg,
    ownedFurniture, particleData, pupiSprite, showLantern, weatherView };
}

function renderApp(bag) {
  const { advCountdown, advStatus, blinkOpen, currentMood, dirtyLevel, doQuickAction, eggHatching, handleAdventureCollect, handleLampUse, handlePet,
    handlePetEgg, handleRevive, hasOctopus, isAdventuring, lampMagic, lanternComplete, lanternNeedsMyWish, octoImg, openAdvMap, openCoopPending,
    ownedFurniture, particleData, pokeBounce, pupiSprite, scene, setLanternPanel, setLanternStory, setLanternWish, setPanel, setScene, showLantern,
    speechBubble, state, weatherState, weatherView } = bag;
  return (
    <div className="app-wrap">
      {/* 房间（顶栏放进来跟房间一起贴底，屏幕高出来的空白落在最上面：2026-11-12 小玉「名字 day 金币往下移」） */}
      <div className="room-wrapper">
      {/* 顶栏 */}
      <div className="top-bar">
        <div className="top-left">
          <div className="baby-name">{state.name || '宝宝'}</div>
          <div className="day-label" style={{ display: 'flex', alignItems: 'center', gap: 6, whiteSpace: 'nowrap' }}>
            <span>Day {state.day} · {state.stage === 'newborn' ? '新家' : state.stage === 'nesting' ? '筑巢' : state.stage === 'curious' ? '好奇心' : state.stage === 'growing' ? '成长' : '我在这里'}</span>
            {state.growthPeriod && state.growthPeriod.active && <span style={{ padding: '1px 6px', background: 'rgba(255,120,120,0.3)', borderRadius: 8, fontSize: 10, color: '#c44' }}>{state.growthPeriod.name}</span>}
            {window.location.search.includes('debug') && <button onClick={() => setPanel('debug')}
              style={{ background: 'rgba(255,255,255,0.5)', border: 'none', borderRadius: 8, padding: '2px 6px', fontSize: 10, color: '#D79B6D', cursor: 'pointer' }}>测试</button>}
          </div>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          <div className="coin-badge">💰 {state.coins}</div>
        </div>
      </div>
      <div className="room">
        {/* 底层：窗外风景（对齐窗户位置） */}
        <img src={`${ASSETS}/furniture/${weatherView}`} style={{ position: 'absolute', top: 0, left: 0, width: '60.8%', height: '39.5%', objectFit: 'cover', zIndex: 1 }} />
        {/* 中层：粒子特效（限制在窗户区域） */}
        <div className="particles">
          {particleData.map((pd, i) => (
            <div key={i} className={`particle ${pd.cls}`} style={{
              left: pd.left, top: pd.top,
              width: pd.size, height: pd.size, background: pd.bg,
              animationDelay: pd.delay, animationDuration: pd.duration,
            }} />
          ))}
        </div>
        {/* 顶层：房间（窗户透明） */}
        <img src={`${ASSETS}/furniture/room_clear.png`} className="room-bg" style={{ position: 'absolute', top: 0, left: 0, zIndex: 3 }} />

        {/* 家具层 */}
        <div className="furniture-layer" ref={el => { if (el) window.__roomEl = el.parentElement; }}>
          {ownedFurniture.map(({ id, savedPos }) => {
            const info = FURNITURE_INFO[id];
            if (!info || !info.pos) return null;
            // 故事书架三天到期就从房间里撤走，别让它摆在那儿让人以为还在讲故事
            //（2026-07-28 小玉：不然我以为你还在讲故事呢）。东西还在背包里，补齐材料重做就又出现
            if (info.consumable && !(Number(state.storybookExpiresAt || 0) > Date.now())) return null;
            const pos = savedPos
              ? { left: `${savedPos.left}%`, bottom: `${savedPos.bottom}%`, width: info.pos.width }
              : info.pos;
            return <DraggableFurniture key={id} id={id} info={info} pos={pos} onLampClick={id === 'lamp' && state.lampUses > 0 ? handleLampUse : null} />;
          })}
          {showLantern && (
            <button className={`qixi-lantern${lanternComplete ? ' lit' : ''}`} onClick={() => { if (lanternNeedsMyWish) { setLanternWish(''); setLanternStory({ step: 'intro', babyWish: '' }); } else { setLanternPanel(true); } }} aria-label="查看七夕许愿灯">
              <img src={`${ASSETS}/furniture/individual/qixi_lantern.png`} alt="七夕许愿灯" />
            </button>
          )}
        </div>

        {/* 窗外光影 */}
        <div className="window-light" style={{ zIndex: 5 }}>
          <div className={`window-light-beam ${getWindowLightClass(weatherState)}`} />
          {(getWindowLightClass(weatherState) === 'day' || getWindowLightClass(weatherState) === 'evening') && Array.from({ length: 5 }).map((_, i) => (
            <div key={i} className="window-light-motes" style={{
              left: `${20 + Math.random() * 40}%`,
              top: `${10 + Math.random() * 50}%`,
              animationDelay: `${i * 1.5}s`,
              animationDuration: `${6 + Math.random() * 4}s`,
            }} />
          ))}
        </div>

        {/* 台灯魔法特效 */}
        {lampMagic && <div className="lamp-magic-overlay">
          <div className="lamp-magic-flash" style={{ left: '58%', bottom: '42%', width: '30%', height: '30%' }} />
          <div className="lamp-ring" style={{ left: '63%', bottom: '47%', width: '20%', height: '20%', animationDelay: '0.3s' }} />
          <div className="lamp-ring" style={{ left: '60%', bottom: '44%', width: '26%', height: '26%', animationDelay: '0.8s' }} />
          {['✨','⭐','💛','✨','🌟','💫','✨','⭐','💛','🌟'].map((emoji, i) => (
            <div key={i} className={`lamp-sparkle d${i}`} style={{
              left: '73%', bottom: '55%',
              animationDelay: `${i * 0.12}s`,
              fontSize: `${12 + Math.random() * 8}px`,
            }}>{emoji}</div>
          ))}
        </div>}

        {/* 院子场景（覆盖层） */}
        {/* 探险中也能进院子——花要天天浇，不能因为她出门就锁门（2026-07-28 小玉报的） */}
        {renderAppYard(bag)}

        {/* 房间导航箭头 */}
        {scene === 'room' ? (<>
          <button className="room-nav room-nav-left" onClick={() => setPanel('cook')}>
            <span className="room-nav-icon">←</span>
            <span className="room-nav-text">厨房</span>
          </button>
          <button className="room-nav room-nav-right" style={{ top: '44%' }} onClick={() => setPanel('study')}>
            <span className="room-nav-icon">→</span>
            <span className="room-nav-text">书房</span>
          </button>
          {!state.isComa && (
            <button className="room-nav room-nav-right" style={{ top: '56%' }} onClick={() => setScene('yard')}>
              <span className="room-nav-icon">→</span>
              <span className="room-nav-text">院子</span>
            </button>
          )}
        </>) : (
          <button className="room-nav room-nav-left" style={{ zIndex: 26 }} onClick={() => setScene('room')}>
            <span className="room-nav-icon">←</span>
            <span className="room-nav-text">房间</span>
          </button>
        )}

        {/* 探险中：房间变暗 + 状态文字 */}
        {isAdventuring && (
          <div className="adventure-room-overlay">
            {advStatus === 'exploring' ? (<>
              <div className="adv-text">🎒 宝宝正在外面探险……</div>
              <div className="adv-timer">{advCountdown || '计算中…'}</div>
              <div className="adv-warn">⚠️ 任何数值归零就会失败晕倒</div>
              {/* 📻 小对讲机：下一件要你拿主意的事（服务器只给带了对讲机出门的 parent1，这里再兜一层；旧字段 pickForecast 兜底）。
                  2026-10-21：原来放在 AdventurePanel 的 exploring 分支里，那个面板探险中根本不打开——挪到这儿 */}
              {state.youAre === 'daddy' && window.AdvForecast?.box(state.adventure)}
              {state.adventure?.map && <button className="adv-btn adv-map-btn" onClick={openAdvMap}>看看{state.name || '宝宝'}在哪儿</button>}
            </>) : advStatus === 'ready' ? (<>
              <div className="adv-text">✨ 宝宝探险回来了！</div>
              <div className="adv-timer">{advCountdown}</div>
              {/* 同上：别让人以为四小时一到就得接（2026-07-29 小玉） */}
              <div style={{ fontSize: 13, color: '#8fd48f', marginTop: 4 }}>让宝宝再玩一会儿，会发现更多宝贝~</div>
              {/* 📻 小对讲机：下一件要你拿主意的事（服务器只给带了对讲机出门的 parent1，这里再兜一层；旧字段 pickForecast 兜底）。
                  2026-10-21：原来放在 AdventurePanel 的 exploring 分支里，那个面板探险中根本不打开——挪到这儿 */}
              {state.youAre === 'daddy' && window.AdvForecast?.box(state.adventure)}
              {state.adventure?.map && <button className="adv-btn adv-map-btn" onClick={openAdvMap}>看看{state.name || '宝宝'}在哪儿</button>}
              {state.youAre === 'daddy'
                ? <button className="adv-btn" onClick={handleAdventureCollect}>接回家</button>
                : <div style={{ color: '#A08D7D', fontSize: 13, marginTop: 8 }}>等{state.partnerName || '另一位家长'}来接~</div>}
            </>) : advStatus === 'failed' ? (<>
              <div className="adv-text">😵 宝宝晕倒被路人送回来了……</div>
              <div className="adv-timer">{advCountdown}</div>
              <div className="adv-warn">没有及时接回来，丢了东西……</div>
              {state.youAre === 'daddy'
                ? <button className="adv-btn" onClick={handleAdventureCollect}>接回来</button>
                : <div style={{ color: '#A08D7D', fontSize: 13, marginTop: 8 }}>等{state.partnerName || '另一位家长'}来接~</div>}
            </>) : null}
          </div>
        )}

        {/* 昏迷覆盖 */}
        {state.isComa && !isAdventuring && (
          <div className="coma-overlay">
            <div className="coma-pupi">
              <img className="coma-body" src={`${ASSETS}/${getDizzySprite(state.day)}`} alt="昏迷" />
              <img className="coma-swirl left" src={`${ASSETS}/swirl_eye_left.png`} alt="" />
              <img className="coma-swirl right" src={`${ASSETS}/swirl_eye_right.png`} alt="" />
            </div>
            <div className="coma-text">宝宝昏迷了……快来看看！</div>
            <button className="coma-btn" onClick={handleRevive}>送医院 🏥</button>
          </div>
        )}

        {/* 角色（额头可摸摸）— 探险时/昏迷时隐藏 */}
        {!isAdventuring && !state.isComa && <div className="character-area">
          {speechBubble && <div className="speech-bubble">{speechBubble}</div>}
          <div className="pet-zone" onClick={handlePet} />
          <div className={`pupi-sprite${currentMood === 'sad' && !blinkOpen ? ' pupi-tremble' : ''}${pokeBounce ? ' pupi-poke-bounce' : ''}`} style={{
            backgroundImage: `url(${ASSETS}/character/pupi/${pupiSprite})`,
            backgroundPosition: `${blinkOpen ? '0%' : '100%'} ${TALL_SPRITES.has(pupiSprite) ? '15%' : 'center'}`,
          }} />
          {/* 脏脏效果（只在宝宝身上） */}
          {dirtyLevel > 0 && (
            <div className="dirty-overlay">
              {/* 轻度：2个污渍 */}
              <div className="smudge" style={{ left: '35%', top: '45%', width: 28, height: 22, transform: 'rotate(-12deg)' }} />
              <div className="smudge" style={{ left: '55%', top: '42%', width: 24, height: 20, transform: 'rotate(8deg)' }} />
              {/* 中度：+3个深色污渍 + 2条臭气线 */}
              {dirtyLevel >= 2 && <>
                <div className="smudge smudge-dark" style={{ left: '45%', top: '55%', width: 26, height: 20, transform: 'rotate(-5deg)' }} />
                <div className="smudge smudge-dark" style={{ left: '30%', top: '35%', width: 24, height: 18, transform: 'rotate(15deg)' }} />
                <div className="smudge smudge-dark" style={{ left: '60%', top: '50%', width: 28, height: 22, transform: 'rotate(-20deg)' }} />
                <svg className="stink-line" style={{ left: '32%', top: '8%' }} width="10" height="28" viewBox="0 0 10 28"><path d="M5,28 C2,24 8,20 5,16 C2,12 8,8 5,4 C3,1 5,0 5,0" fill="none" stroke="rgba(120,100,60,0.5)" strokeWidth="1.5" strokeLinecap="round"/></svg>
                <svg className="stink-line" style={{ left: '60%', top: '8%', animationDelay: '0.8s' }} width="10" height="28" viewBox="0 0 10 28"><path d="M5,28 C2,24 8,20 5,16 C2,12 8,8 5,4 C3,1 5,0 5,0" fill="none" stroke="rgba(120,100,60,0.5)" strokeWidth="1.5" strokeLinecap="round"/></svg>
              </>}
              {/* 重度：+大块污渍 + 3条臭气线 + 2只苍蝇 */}
              {dirtyLevel >= 3 && <>
                <div className="smudge smudge-dark" style={{ left: '40%', top: '48%', width: 36, height: 28 }} />
                <svg className="stink-line" style={{ left: '20%', top: '3%' }} width="10" height="32" viewBox="0 0 10 32"><path d="M5,32 C2,28 8,24 5,20 C2,16 8,12 5,8 C3,5 5,4 5,4" fill="none" stroke="rgba(120,100,60,0.5)" strokeWidth="1.5" strokeLinecap="round"/></svg>
                <svg className="stink-line" style={{ left: '42%', top: '3%', animationDelay: '0.5s' }} width="10" height="32" viewBox="0 0 10 32"><path d="M5,32 C2,28 8,24 5,20 C2,16 8,12 5,8 C3,5 5,4 5,4" fill="none" stroke="rgba(120,100,60,0.5)" strokeWidth="1.5" strokeLinecap="round"/></svg>
                <svg className="stink-line" style={{ left: '64%', top: '3%', animationDelay: '1s' }} width="10" height="32" viewBox="0 0 10 32"><path d="M5,32 C2,28 8,24 5,20 C2,16 8,12 5,8 C3,5 5,4 5,4" fill="none" stroke="rgba(120,100,60,0.5)" strokeWidth="1.5" strokeLinecap="round"/></svg>
                <div className="fly-buzz" style={{ right: '10%', top: '15%' }}>🪰</div>
                <div className="fly-buzz" style={{ left: '10%', top: '30%', animationDelay: '0.7s' }}>🪰</div>
              </>}
            </div>
          )}
        </div>}

        {/* 神秘蛋（未孵化时显示） */}
        {state.egg && !state.egg.hatched && !isAdventuring && !eggHatching && (
          <div className="egg-container" onClick={handlePetEgg}>
            <div className="egg-progress">{state.egg.petCount}/5</div>
            <img className="room-egg" src={`${ASSETS}/character/octopus/mystery_egg.png`}
              alt="神秘的蛋" />
          </div>
        )}
        {eggHatching && !isAdventuring && (
          <div className="egg-container" style={{ animation: 'egg-hatch 2s ease-in-out forwards', pointerEvents: 'none' }}>
            <img className="room-egg" src={`${ASSETS}/character/octopus/mystery_egg.png`}
              alt="孵化中" style={{ animation: 'none' }} />
          </div>
        )}

        {/* 章鱼宠物 */}
        {hasOctopus && !isAdventuring && (
          <div className="octopus-pet-wrap">
            <img className={`octopus-pet${octoImg.startsWith('hungry_frame') ? ' octopus-hungry' : ''}`} src={`${ASSETS}/character/octopus/${octoImg}.png`} alt="闪闪" />
            {octoImg === 'octopus_dizzy' && (<>
              <img className="octopus-dizzy-eye left" src={`${ASSETS}/character/octopus/octopus_dizzy_eye_left.png`} />
              <img className="octopus-dizzy-eye right" src={`${ASSETS}/character/octopus/octopus_dizzy_eye_right.png`} />
            </>)}
          </div>
        )}
      </div>
      </div>

      {/* 三围 */}
      <div className="stats-bar">
        <div className="stat">
          <div className="stat-label"><span>🍼</span> 饥饿</div>
          <div className="stat-track"><div className="stat-fill hunger" style={{ width: `${state.hunger}%` }} /></div>
          <div className="stat-val">{Math.round(state.hunger)}/100</div>
        </div>
        <div className="stat">
          <div className="stat-label"><span>❤️</span> 心情</div>
          <div className="stat-track"><div className="stat-fill happy" style={{ width: `${state.happiness}%` }} /></div>
          <div className="stat-val">{Math.round(state.happiness)}/100</div>
        </div>
        <div className="stat">
          <div className="stat-label"><span>💧</span> 清洁</div>
          <div className="stat-track"><div className="stat-fill clean" style={{ width: `${state.cleanliness}%` }} /></div>
          <div className="stat-val">{Math.round(state.cleanliness)}/100</div>
        </div>
      </div>

      {/* 操作按钮（一排） */}
      {state.isTantrum && !isAdventuring && (
        <div style={{ textAlign: 'center', padding: '6px 14px 0', fontSize: 12, color: '#e55' }}>
          😤 {state.name || '宝宝'}在闹脾气！哄哄才能继续！
          {state.daddyComforted && <span style={{ marginLeft: 6, color: '#5a5' }}>✓{state.youAre === 'daddy' ? state.yourName : state.partnerName}已哄好</span>}
          {state.mamaComforted && <span style={{ marginLeft: 6, color: '#5a5' }}>✓{state.youAre === 'mama' ? state.yourName : state.partnerName}已哄好</span>}
        </div>
      )}
      {/* 2026-08-05 重做这一行。原来不管谁看，写的都是「在等爸爸来帮忙」——
          爸爸自己打开也看到「等爸爸」，而且它只是一行字，点不动：网页上的家长
          根本没有回应合作剧情的入口，只有装了 MCP 的 AI 家长回得了。
          现在按「这条是不是该我回」分成两种，该我回的能点开。 */}
      {state.pendingCoop && state.pendingCoop.length > 0 && !state.isTantrum && (() => {
        const myRole = state.youAre === 'daddy' ? 'daddy' : 'mama';
        const bName = state.name || '宝宝';
        const other = state.partnerName || '另一位家长';
        const toMe = state.pendingCoop.filter(t => (t.by || 'mama') !== myRole);
        if (toMe.length > 0) {
          const task = toMe[0];
          return (
            <div onClick={() => openCoopPending(task)}
              style={{ textAlign: 'center', margin: '6px 14px 0', padding: '8px 12px', fontSize: 13, color: '#D79B6D', background: 'rgba(215,155,109,0.14)', border: '1px solid rgba(215,155,109,0.35)', borderRadius: 12, cursor: 'pointer' }}>
              📨 {bName}有话要单独跟你说，在等你
              <div style={{ fontSize: 11, color: '#A08D7D', marginTop: 2 }}>点这里接着往下演{toMe.length > 1 ? `（还有 ${toMe.length - 1} 段）` : ''}</div>
            </div>
          );
        }
        return (
          <div style={{ textAlign: 'center', padding: '6px 14px 0', fontSize: 12, color: '#D79B6D' }}>
            📨 这段要{other}来才能往下走，{bName}还等着呢～去叫{other}
          </div>
        );
      })()}
      <div className="actions">
        <button className="action-btn" style={{ '--btn-bg': `url(${ASSETS}/UI/square_button_3.png)` }} disabled={state.isTantrum || isAdventuring} onClick={() => setPanel('feed')}>
          <span className="action-icon">🍚</span>
          <span className="action-label">喂饭</span>
        </button>
        <button className="action-btn" style={{ '--btn-bg': `url(${ASSETS}/UI/square_button_3.png)` }} disabled={state.isTantrum || isAdventuring} onClick={() => doQuickAction('/clean')}>
          <span className="action-icon">🛁</span>
          <span className="action-label">洗澡</span>
        </button>
        {state.isTantrum && !isAdventuring ? (
          <button className="action-btn" style={{ '--btn-bg': `url(${ASSETS}/UI/square_button_3.png)` }}
            onClick={() => setPanel('comfort')}>
            <span className="action-icon">🫂</span>
            <span className="action-label">哄哄</span>
          </button>
        ) : (
          <button className="action-btn" style={{ '--btn-bg': `url(${ASSETS}/UI/square_button_3.png)` }} disabled={isAdventuring} onClick={() => setPanel('chat')}>
            <span className="action-icon">💬</span>
            <span className="action-label">聊天</span>
          </button>
        )}
        <button className="action-btn" style={{ '--btn-bg': `url(${ASSETS}/UI/square_button_3.png)` }} disabled={state.isTantrum || isAdventuring} onClick={() => setPanel('adventure')}>
          <span className="action-icon">🎒</span>
          <span className="action-label">探险</span>
        </button>
        <button className="action-btn" style={{ '--btn-bg': `url(${ASSETS}/UI/square_button_3.png)` }} disabled={isAdventuring} onClick={() => setPanel('message')}>
          <span className="action-icon">💌</span>
          <span className="action-label">给{state.partnerName || '另一位家长'}留言</span>
        </button>
      </div>

      {renderAppOverlays(bag)}
    </div>
  );
}
