/* ============================================================================
 * tl-nodes.css — 節點語彙 SSOT（單一真相登錄表）
 * [2026-07-17 / Claude] feat/home-quality-redo
 *
 * 為什麼有這個檔：
 *   「信任節點」視覺語彙（node / avatar / seal / thread / cluster 座標系）最早長在
 *   public/community/index.html 的 inline <style> 裡（tn-* 前綴）。首頁要沿用同一套
 *   手法時，唯一正確的做法是「抽成共用 SSOT」而不是複製第二份 inline CSS。
 *   → 依 feedback_registry_driven_modularization：單一真相登錄表，禁複製。
 *
 * 【座標耦合機制】← 這是整套語彙的核心·勿改
 *   .tl-cluster 內的 <svg class="tl-thread-layer" viewBox="0 0 100 100"
 *   preserveAspectRatio="none">  被強制拉伸貼合容器
 *   → SVG 的 x/y 座標（0–100）**就是**容器寬高的百分比
 *   → **就是** .tl-cnode 的 left% / top%
 *   .tl-cnode 用 translate(-50%,-50%) 讓卡片中心對齊該座標
 *   → 線的端點真的落在卡片中心，不是畫一張圖假裝連著。
 *   容器非正方形不影響：兩套座標被同比例拉伸。
 *
 * 【用法】
 *   <link rel="stylesheet" href="/global/tl-nodes.css">  （需先載入 tl-tokens.css）
 *   本檔只提供「原子」；頁面專屬的構圖 / 浮卡 / 敘事用頁面自己的前綴（如首頁 .wr-*）。
 *
 * 【依賴】tl-tokens.css — 本檔 0 個自創 hex，全部走 var(--tl-*)。
 * ========================================================================= */

/* ── 簽名原子：node + avatar + seal（KYC 封印） ───────────────────────── */
.tl-node { position: relative; display: inline-flex; }

.tl-avatar {
  width: 100%; height: 100%;
  border-radius: var(--tl-radius-full);
  background: rgba(var(--tl-brand-navy-rgb), 0.10);
  border: 1.5px solid var(--tl-line-nodes-border);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--tl-brand-navy);
  overflow: hidden;
}

.tl-seal {
  position: absolute; right: -3px; bottom: -3px;
  width: 40%; height: 40%; min-width: 16px; min-height: 16px;
  border-radius: var(--tl-radius-full);
  background: var(--tl-seal-ground);          /* navy 底盤（固定深藍） */
  border: 1.5px solid var(--tl-line-nodes);   /* teal 環 */
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--tl-line-nodes); font-size: 0.62em;
  box-shadow: 0 1px 3px rgba(var(--tl-brand-navy-rgb), 0.35);
}

/* seal 狀態變體 —— 對應 completenessEngine 的 state: filled | inferable | missing
 * filled    → .tl-seal（預設·teal 環 + 綠勾）
 * inferable → .tl-seal--pending（gold·「我們推得出來，等你確認」）
 * missing   → 不給 seal（見 .tl-avatar--missing）
 */
.tl-seal i { color: var(--tl-brand-green); }
.tl-seal--pending {
  border-color: var(--tl-brand-gold);
  color: var(--tl-brand-gold);
}
.tl-seal--pending i { color: var(--tl-brand-gold); }

/* ── 叢集容器 + 座標系 ──────────────────────────────────────────────── */
.tl-cluster { position: relative; width: 100%; aspect-ratio: 1 / 0.92; min-height: 320px; }

.tl-thread-layer {
  position: absolute; inset: 0; width: 100%; height: 100%;
  overflow: visible;
}

.tl-thread {
  stroke: var(--tl-line-nodes);
  stroke-width: 1; fill: none;
  opacity: 0.55; stroke-linecap: round;
}

/* draw-in：終態 stroke-dashoffset:0（＝可見）。
 * 刻意不用 opacity 做進場：reduced-motion 把 animation 關掉時，
 * 元素會停在「終態」，offset:0 → 線仍然看得見。用 opacity 會整條消失。 */
.tl-thread-anim {
  stroke-dasharray: 200; stroke-dashoffset: 0;
  animation: tl-thread-draw 1.1s var(--tl-ease-standard) both;
}
.tl-thread-anim.d2 { animation-delay: 0.12s; }
.tl-thread-anim.d3 { animation-delay: 0.24s; }
.tl-thread-anim.d4 { animation-delay: 0.36s; }
.tl-thread-anim.d5 { animation-delay: 0.48s; }
.tl-thread-anim.d6 { animation-delay: 0.60s; }
@keyframes tl-thread-draw { from { stroke-dashoffset: 200; } to { stroke-dashoffset: 0; } }

/* 缺口線：通往「尚未連結」來源的邊。線的樣式本身編碼狀態 —— 缺的來源，連線是虛的。
 * 不掛 .tl-thread-anim（dasharray 會跟 draw-in 打架）。 */
.tl-thread--gap { stroke-dasharray: 3 3; opacity: 0.28; }

/* 定位節點：left%/top% 由 inline style 給（與 <line> 的 x/y 同一組座標） */
.tl-cnode { position: absolute; transform: translate(-50%, -50%); }
.tl-cnode .tl-node { width: 100%; height: 100%; }
.tl-cnode .tl-avatar {
  font-size: 1.35rem;
  background: var(--tl-bg-elevated);
  box-shadow: var(--tl-card-shadow);
}

/* avatar 狀態變體 */
.tl-avatar--pending { border: 1.5px dashed var(--tl-brand-gold); }
.tl-avatar--missing {
  border: 1.5px dashed var(--tl-border-strong);
  color: var(--tl-text-subtle);
}
.tl-cnode--missing { opacity: 0.75; }

/* ── 掃描線（AI 檢核中）────────────────────────────────────────────── */
.tl-scan {
  position: absolute; left: -8%; top: 50%; width: 116%; height: 2px;
  background: var(--tl-line-nodes);
  opacity: 0; transform-origin: left center;
  animation: tl-scan 3.6s var(--tl-ease-standard) infinite;
}
@keyframes tl-scan {
  0%, 100% { opacity: 0; }
  12%      { opacity: 0.9; }
  40%      { opacity: 0.15; }
}

/* reduced-motion：本檔自帶關閉宣告，不依賴呼叫端記得寫。
 * tl-tokens.css 有全站 * 中和，這裡再顯式關一次＝雙保險（掃描線是 infinite，最需要）。 */
@media (prefers-reduced-motion: reduce) {
  .tl-thread-anim { animation: none; stroke-dashoffset: 0; }
  .tl-scan { animation: none; opacity: 0.35; }
}
