/* 光叢 canvas 定位——同 demo v0.4 的 #dots，但這支 app 是可捲動的多日訊息清單、不是
   demo 那種單一定格畫面（advisor 覆核：不重寫資料流，只換視覺外殼），所以固定滿版鋪在
   #app 之下，而不是嵌在某個會捲動的容器裡——用 z-index（不是 DOM 順序）決定疊層，
   #app 本身要設 position:relative;z-index:1（見 styles.css）才會蓋在這層之上。
   pointer-events:none——這支 app 這批不接「點光叢＝排出表情」的手勢（demo 的
   cv.addEventListener('pointerdown', ...)，屬動畫細節，非本 sprint 範圍），
   canvas 不該擋住下面內容的點擊。
   已決事項1（2026-09-12 bugbatch，積累 #10）：z-index 從 -1 拉到 4——高於 .sky-glass（2）、
   #app（1）、#interaction-bar（3，見 styles.css）。原本的 -1 讓光叢粒子飄到 .sky-glass
   覆蓋的螢幕區段時被那層的 backdrop-filter 糊掉（report #10 根因），跟
   light-core.css 自己對 #face-emoticon 早就套用的「即時反應指示不該被毛玻璃蓋過」
   （見下方 #face-emoticon 註解）是同一個理由，這裡只是把同一個理由回頭套用在光叢本身。
   pointer-events:none 不受影響——拉高 z-index 不影響任何點擊，光叢在最上層純視覺穿透。
   已知取捨（report #12a 相關）：`startReturn()` 的粒子會短暫散布到全螢幕隨機位置
   （見該函式），z-index 4 意味著這 ~2 秒內粒子可能飄過 #interaction-bar 上方——這是
   已決事項1「光叢提到玻璃之上」的直接結果，不是新引入的 bug，這裡不額外處理。 */
#light-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 4;
  pointer-events: none;
}

/* 已決事項8：face: 顏文字短暫顯示層——固定在跟光叢同一個垂直錨點附近（2026-09-07 UI 節奏批
   已決事項3改上 1/3、2026-09-09 再上移 10vh 成 23.33%、2026-09-11 版面上移已決事項7再上移
   15vh 成 8.33%、2026-09-11 20:50 追加裁定「光叢調太高了，下降 10vh」再下移成 18.33%，
   見 ui-tunables.js 的 LIGHT_ANCHOR_Y_RATIO——兩邊有同步測試，不可只改一邊），
   z-index 蓋過 #app（transient 提示，不能被捲動內容擋住），pointer-events:none 同 canvas
   的理由（不擋點擊）。淡出用 opacity transition，JS 只切 class（見 app.js 的
   showFaceEmoticon），不用 JS 算透明度。
   z-index 3（2026-09-11 已決事項8從 2 上調）：新增的 .sky-glass 毛玻璃層蓋在 #app（1）之上
   用的是 2，顏文字是即時反應指示，不該被那層毛玻璃的模糊／染色蓋過去，所以要再高一層。 */
/* 2026-09-15 交辦書已決3：光叢中心往下移到安全區之下——瀏海機（12 mini 等）的
   safe-area-inset-top 蓋住畫面最上緣一段，18.33% 這個純比例錨點沒有把它算進去，粒子雲的
   上緣可能飄進被鏡頭區/系統狀態列遮住的範圍。跟 light-core.js 的 cy()（H*LIGHT_ANCHOR_Y_RATIO
   + safeAreaTopPx）用同一個加法：比例錨點不變，額外加上安全區高度往下推。用 calc() 疊
   :root 的 --safe-area-top（env(safe-area-inset-top,0px)），不寫死像素——沒有瀏海的裝置
   這裡加 0，行為不變。#light-hitzone 共用同一個垂直錨點，兩邊都要加、都有同步測試
   （test/ui-tunables.test.ts）鎖住。 */
#face-emoticon {
  position: fixed;
  left: 50%;
  top: calc(18.33% + var(--safe-area-top));
  transform: translate(-50%, -50%);
  z-index: 3;
  pointer-events: none;
  font-size: 1.4rem;
  color: var(--ink, #fff);
  opacity: 0;
  transition: opacity 0.6s ease;
}
#face-emoticon.face-emoticon-visible {
  opacity: 1;
}

/* 打招呼手勢入口（2026-09-14 swarm 交辦，8/24 拍板移家）：原本掛在已拆除的 presence 橫幅
   「牠不在」變體上，橫幅拿掉後改掛光叢本身。#light-canvas 自己固定 pointer-events:none
   是刻意設計（見上方開頭兩批已決事項：canvas 不該擋住下面訊息清單／互動列的點擊）——這顆
   熱區維持同一個既有慣例，**不**開 pointer-events:auto。top 跟 #face-emoticon 共用同一個
   LIGHT_ANCHOR_Y_RATIO 垂直錨點（見 ui-tunables.js，兩邊有同步測試，不可只改一邊），純粹
   只提供幾何座標（app.js 用 getBoundingClientRect() 讀圓心/半徑）給 document 層級的 click
   判斷用，這顆元素本身完全不攔截任何事件。
   ⚠️ /review 修正紀錄：這裡原本開 pointer-events:auto，靠 app.js 的 pointerdown 探測
   （elementFromPoint 借位偵測底下是否有真內容）決定要不要放行——advisor 覆核抓到那個設計
   會卡死：一旦放行過一次，之後除非又有一次 pointerdown 直接落在熱區本身，永遠沒有機會
   重新判斷切回 auto，熱區會從那次之後永久失效。同時原本這裡也錯誤假設「這個錨點在 #app
   邊界之上，熱區不會蓋到訊息清單」——body.app-narrative（真正在讀訊息的敘事畫面）把 #app
   的 top 換成遠小於 max(1.5em,25vh) 的 --narrative-top，#app 的可捲動內容其實可以捲到
   跟這顆熱區同一段視覺區域。兩個問題一起改成現在這版：熱區完全不攔截，判斷邏輯搬到
   app.js 的 document click（見該處註解與 greet-gesture.js 的 shouldGreetHitzonePassThrough
   ／isWithinHitzoneCircle）。 */
#light-hitzone {
  position: fixed;
  left: 50%;
  top: calc(18.33% + var(--safe-area-top));
  transform: translate(-50%, -50%);
  width: min(45vmin, 200px);
  height: min(45vmin, 200px);
  border-radius: 50%;
  z-index: 4;
  pointer-events: none;
}
