/* ============================================================
   知識庫 — 圖冊模式（帶狀欄式地圖）

   一律用 .kba 前綴。移植來源是一份獨立 HTML，它的類名極短
   （.top .col .tile .content .dots .stack .mono .sf），跟 main.css 有實際衝突 ——
   .content 是 app 外殼自己的內容容器（帶 padding 與 max-width）、
   .dots 有 ::after 的動畫刪節號、.sf 是整個檔案清單元件。
   後兩者是「加法」而不是可覆蓋的宣告，靠層疊順序救不回來，只能全部改名。

   配色：來源檔本來就備好了一整組深色 token，直接採用，
   但底色 / 文字 / 分隔線改對齊 --kbg-*，切模式時舞台底色才不會跳。
   語意色（jade 結構、cinnabar 安全與否決、gamboge 跨面引用、violet 線層）
   保留來源檔自己的值 —— 那四個顏色是有意義的，不能換成面色票。
   ============================================================ */

.kba {
  /* 底色與文字：對齊舞台 */
  --kba-bg: #12151c;
  --kba-surf: #191d26;
  --kba-surf2: #232b39;
  --kba-sink: #0e1118;
  --kba-ink: #e9ecf2;
  --kba-ink2: #9aa4b6;
  --kba-ink3: #7a8497;
  --kba-ink4: #58626f;
  --kba-rule: #2b323f;
  --kba-rule2: #222833;

  /* 語意色 */
  --kba-jade: #63b3ae;    /* 結構 / 聚焦 */
  --kba-jade2: #4c9691;   /* 體帶橫桿 */
  --kba-jadeL: rgba(99, 179, 174, .17);
  --kba-cin: #e2705a;     /* 安全維度 / 否決權 */
  --kba-cinL: rgba(226, 112, 90, .15);
  --kba-gam: #d7ae4a;     /* 跨面引用 / 孤立點 */
  --kba-gamL: rgba(215, 174, 74, .15);
  --kba-vio: #a99cd6;     /* 線層 */
  --kba-violL: rgba(169, 156, 214, .16);

  --kba-mono: var(--mono);
  /* 襯線顯示體：地圖感的來源，也讓欄名跟 app 其他地方的介面文字區隔開。
     純 OS 內建字，不需要下載。 */
  --kba-disp: "Palatino Linotype", "Book Antiqua", Palatino, "Songti TC",
              "Noto Serif CJK TC", PMingLiU, serif;

  /* 以下四個由 JS 逐次量測寫入 */
  --kba-bbh: 56px;
  --kba-colw: 180px;
  --kba-gutw: 46px;
  --kba-chdh: 56px;
  --kba-tileh: 21px;
  --kba-rowh: 44px;
  --kba-lbandh: 126px;
}

/* 舞台本身就是 atlas 的根。要蓋掉力導向那邊的放射漸層與抓取游標 ——
   圖冊不能平移，整片 grab 游標會跟磚與欄頭自己的 grab 打架。 */
.kbg__stage.kba {
  background: var(--kba-bg);
  cursor: auto;
  color: var(--kba-ink);
  font-size: 13.5px;
  line-height: 1.6;
  display: block;
  height: 100%;
}
.kbg__stage.kba:has(.is-panning) { cursor: auto; }

.kba button { background: none; border: none; cursor: pointer; color: inherit; font: inherit; }
.kba :focus-visible { outline: 2px solid var(--kba-jade); outline-offset: 1px; }
.kba.is-dragging { cursor: grabbing; user-select: none; }
.kba.is-dragging .kba-hd, .kba.is-dragging .kba-tile { cursor: grabbing; }
.kba.is-gresize { cursor: col-resize; user-select: none; }

/* 圖冊沒有相機，縮放按鈕沒有意義 */
.kbg[data-kbg-mode="atlas"] .kbg__zoom { display: none; }

/* ---------- 捲動容器 ---------- */
.kba__canvas {
  overflow: auto;
  background: var(--kba-bg);
  position: relative;
  min-width: 0;
  height: 100%;
}
.kba__content {
  position: relative;
  width: max-content;
  min-width: 100%;
  min-height: 100%;
  display: flex;
  flex-direction: column;
}

/* ---------- 體帶 ---------- */
.kba__bband {
  position: sticky; top: 0; z-index: 14;
  background: var(--kba-sink);
  border-bottom: 1px solid var(--kba-rule);
  display: flex; min-width: 100%;
}
.kba__gut {
  position: sticky; left: 0; z-index: 3; flex: none;
  width: var(--kba-gutw); background: var(--kba-sink);
  border-right: 1px solid var(--kba-rule);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1px; padding: 2px 0;
}
.kba__gutg { font-family: var(--kba-disp); font-size: 17px; color: var(--kba-ink3); line-height: 1; }
.kba__gutg--wide { font-size: 14px; }
.kba__gutn { font-family: var(--kba-mono); font-size: 8.5px; color: var(--kba-ink4); letter-spacing: .06em; }
.kba__bandw { flex: 1; position: relative; min-width: 0; }

/* 帶內的 SVG 必須脫離文件流。它的 width 屬性是「量」出來的，一旦留在流內就會
   回頭把 .kba__content{width:max-content} 撐大，下一次 repaint 又量到更大 —— 無限膨脹。 */
.kba__bband svg, .kba__lband svg { position: absolute; left: 0; top: 0; display: block; }

/* ---------- 欄區 ---------- */
/* flex:1 0 auto —— 一定要能「長到內容高度」，不能 shrink，
   否則欄內的磚會被 sticky 的線帶蓋住。 */
.kba__colswrap { position: relative; display: flex; flex: 1 0 auto; }
.kba__cgut {
  position: sticky; left: 0; z-index: 13; flex: none;
  width: var(--kba-gutw); background: var(--kba-sink);
  border-right: 1px solid var(--kba-rule);
  display: flex; flex-direction: column;
}
.kba__ghandle { position: absolute; right: -4px; top: 0; bottom: 0; width: 9px; cursor: col-resize; z-index: 22; }
.kba__ghandle::after {
  content: ""; position: absolute; left: 3px; top: 0; bottom: 0; width: 3px;
  background: transparent; transition: background .14s;
}
.kba__ghandle:hover::after, .kba__ghandle.is-on::after { background: var(--kba-jade); }
.kba__gwtip {
  position: absolute; left: calc(100% + 10px); top: 8px;
  font-family: var(--kba-mono); font-size: 10px; color: var(--kba-jade);
  background: var(--kba-surf); border: 1px solid var(--kba-jade);
  padding: 1px 6px; border-radius: 2px; display: none; white-space: nowrap;
}
.kba__ghandle.is-on .kba__gwtip { display: block; }

.kba__seghd {
  height: var(--kba-chdh); border-bottom: 1px solid var(--kba-rule);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  position: sticky; top: var(--kba-bbh); background: var(--kba-sink); z-index: 2; flex: none;
}
.kba__segpt { flex: 1; display: flex; flex-direction: column; align-items: center; padding-top: 14px; gap: 1px; }
.kba__segpt--rows, .kba__segpt--y { padding-top: 0; }
.kba__segpt--y { position: relative; padding-top: 6px; }

/* 寬度由 sizeCols() 明確寫入。min-width:max-content 搭配 flex-grow 子項會被
   flex 的 max-content 演算法放大到遠超實際需要，且結果不可預測。

   z-index:5 是把整個欄區抬到連線圖層（.kba__ovp，z-index:4）之上 —— 線是關係的
   提示，磚上的字才是內容，線壓在字上整欄就讀不了。欄區在這裡變成堆疊脈絡，
   裡面 sticky 欄頭的 z-index:10 於是只在欄區內部比較，對外仍然低於標尺欄(13)
   與上下兩條帶(14/15)，跟原本的層序一致。 */
.kba__cols { position: relative; z-index: 5; display: flex; flex: 0 0 auto; align-items: stretch; }

.kba-col {
  flex: 1 1 0; min-width: var(--kba-colw);
  border-right: 1px solid var(--kba-rule2);
  display: flex; flex-direction: column;
}
.kba-col:last-child { border-right: none; }
.kba-col.is-veto { background: linear-gradient(var(--kba-cinL), transparent 120px); }

.kba-hd {
  position: sticky; top: var(--kba-bbh); z-index: 10; min-height: 56px;
  background: var(--kba-surf); border-bottom: 1px solid var(--kba-rule);
  padding: 8px 9px; text-align: left; width: 100%;
  display: flex; flex-direction: column; gap: 2px;
  cursor: grab; touch-action: none;
  box-shadow: 0 3px 7px -5px rgba(0, 0, 0, .75);
  transition: background .14s, box-shadow .14s;
}
/* 子項不准被壓 —— .kba-hd__n 為了水平省略號有 overflow:hidden，
   一旦高度被 flex-shrink 壓縮，字就會被上下切掉。 */
.kba-hd > * { flex: none; }
.kba-col.is-veto .kba-hd {
  background: var(--kba-cinL);
  box-shadow: inset 0 -2px 0 var(--kba-cin), 0 3px 7px -5px rgba(0, 0, 0, .75);
}
.kba-hd:hover { background: var(--kba-jadeL); }
.kba-hd__r1 { display: flex; align-items: center; gap: 6px; }
.kba-hd__id { font-family: var(--kba-mono); font-size: 9.5px; color: var(--kba-jade); letter-spacing: .06em; flex: none; }
.kba-col.is-veto .kba-hd__id { color: var(--kba-cin); }
.kba-hd__cnt { margin-left: auto; font-family: var(--kba-mono); font-size: 9px; color: var(--kba-ink3); flex: none; }
.kba-hd__n {
  font-family: var(--kba-disp); font-size: 13.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 1.45;
}
.kba-hd__rl {
  font-family: var(--kba-mono); font-size: 9px; color: var(--kba-ink3); letter-spacing: .06em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 1.5;
}

/* ---------- 磚 ---------- */
.kba__stack { display: flex; flex-direction: column; gap: 2px; padding: 7px 5px 20px; flex: 1; }
.kba-tile {
  border: 1px solid var(--kba-rule); background: var(--kba-surf); border-radius: 2px;
  padding: 2px 6px; display: flex; align-items: center; gap: 5px;
  font-size: 11px; text-align: left; height: var(--kba-tileh); flex: none;
  cursor: grab; touch-action: none;
  transition: border-color .12s, background .12s, color .12s, opacity .18s;
}
.kba-tile:hover { border-color: var(--kba-jade); background: var(--kba-jadeL); }
.kba-tile__id { font-family: var(--kba-mono); font-size: 9.5px; color: var(--kba-ink3); flex: none; }
.kba-tile__n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
.kba-tile__dg { font-family: var(--kba-mono); font-size: 9px; color: var(--kba-ink4); flex: none; }
.kba-tile.is-safety { border-left: 3px solid var(--kba-cin); }
.kba-tile.is-safety .kba-tile__id { color: var(--kba-cin); }
.kba-tile.is-wip { border-style: dashed; }
.kba-tile.is-orphan { background: var(--kba-gamL); }
.kba-tile.is-lit { border-color: var(--kba-jade); background: var(--kba-jade); color: #10201f; }
.kba-tile.is-lit .kba-tile__id, .kba-tile.is-lit .kba-tile__dg { color: #10201f; opacity: .75; }
.kba-tile.is-lit.is-safety { border-color: var(--kba-cin); background: var(--kba-cin); color: #24100c; }
.kba-tile.is-lit.is-safety .kba-tile__id, .kba-tile.is-lit.is-safety .kba-tile__dg { color: #24100c; }

.kba__cols.is-focusing .kba-tile:not(.is-lit) { opacity: .2; }
/* 欄頭是 sticky 的浮動層 —— 淡化只能作用在文字上。對整個元素下 opacity
   會連背景一起變透明，底下捲過去的磚就會透出來。 */
.kba__cols.is-focusing .kba-col:not(.is-lit) .kba-hd > * { opacity: .3; }

.kba-col.is-lit { box-shadow: inset 0 0 0 1px var(--kba-jade); }
.kba-col.is-lit .kba-hd {
  background: var(--kba-jadeL);
  box-shadow: inset 0 -2px 0 var(--kba-jade), 0 3px 7px -5px rgba(0, 0, 0, .75);
}
.kba-col.is-lit .kba-hd__id, .kba-col.is-lit .kba-hd__n { color: var(--kba-jade); }
.kba-col.is-lit.is-veto { box-shadow: inset 0 0 0 1px var(--kba-cin); }
.kba-col.is-lit.is-veto .kba-hd {
  background: var(--kba-cinL);
  box-shadow: inset 0 -2px 0 var(--kba-cin), 0 3px 7px -5px rgba(0, 0, 0, .75);
}
.kba-col.is-lit.is-veto .kba-hd__id, .kba-col.is-lit.is-veto .kba-hd__n { color: var(--kba-cin); }

.kba__none { font-size: 10.5px; color: var(--kba-ink4); font-style: italic; padding: 3px 4px; }
.kba__none--plot { position: absolute; top: 8px; left: 6px; }

/* 搜尋連動：淡化不符合者，絕不移除 —— 移除會改變版面，
   把使用者剛剛記住的位置整個打散。 */
.kba__cols.is-matching .kba-tile.is-nomatch { opacity: .18; }
.kba__cols.is-matching .kba-col.is-nomatch .kba-hd > * { opacity: .35; }

/* 連線畫在所有磚與欄頭「之下」，從磚背後穿過 —— 見 .kba__cols 的 z-index 註解 */
.kba__ovp { position: absolute; left: var(--kba-gutw); top: 0; pointer-events: none; z-index: 4; }

/* ---------- 矩陣排法：面(歸屬) × 面(引用) ---------- */
.kba__mrows { display: flex; flex-direction: column; flex: 1; align-items: stretch; }
.kba-rowlb {
  height: var(--kba-rowh); display: flex; align-items: center; justify-content: flex-end; gap: 5px;
  padding: 0 8px 0 4px; border-bottom: 1px solid var(--kba-rule2);
  font-family: var(--kba-mono); font-size: 9.5px; color: var(--kba-ink3);
  cursor: pointer; transition: .13s; flex: none; overflow: hidden; min-width: 0; width: 100%;
}
.kba-rowlb:hover, .kba-rowlb.is-lit { background: var(--kba-jadeL); color: var(--kba-jade); }
.kba-rowlb__n {
  font-size: 9px; color: var(--kba-ink4);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kba-cell {
  height: var(--kba-rowh);
  border-bottom: 1px solid var(--kba-rule2); border-right: 1px solid var(--kba-rule2);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  cursor: grab; touch-action: none; transition: background .13s, box-shadow .13s;
  position: relative; width: 100%; padding: 2px;
}
.kba-cell:last-child { border-right: none; }
.kba-cell.is-diag { background: var(--kba-surf); }
.kba-cell.is-empty { cursor: default; }
.kba-cell:not(.is-empty):hover { box-shadow: inset 0 0 0 1.5px var(--kba-jade); }
.kba-cell.is-lit { box-shadow: inset 0 0 0 1.5px var(--kba-jade); background: var(--kba-jadeL); }
.kba-cell__dots {
  display: flex; flex-wrap: wrap; gap: 2px;
  justify-content: center; align-items: center; max-width: 100%; line-height: 0;
}
.kba-cell__d { width: 6px; height: 6px; border-radius: 50%; background: var(--kba-jade2); display: block; }
.kba-cell__d.is-safety { background: var(--kba-cin); }
.kba-cell__d.is-wip { background: none; box-shadow: inset 0 0 0 1.5px var(--kba-gam); }
.kba-cell__c { font-family: var(--kba-mono); font-size: 8.5px; color: var(--kba-ink3); }
.kba__cols.is-focusing .kba-cell:not(.is-lit) .kba-cell__dots,
.kba__cols.is-focusing .kba-cell:not(.is-lit) .kba-cell__c { opacity: .25; }

/* ---------- 座標排法：y 綁真實欄位 ---------- */
/* 高度由 JS 逐次算好寫在 style.height —— 不能用 flex:1，
   那會讓 flex-basis:0 蓋掉 height。 */
.kba__plot { position: relative; flex: 0 0 auto; padding: 0; }
.kba__gl { position: absolute; left: 0; right: 0; height: 0; border-top: 1px dashed var(--kba-rule2); }
.kba-tile--plot { position: absolute; transform-origin: center; width: calc(100% - 12px); left: 6px; }
/* 被碰撞推離真值的磚，左緣加一道細記號 —— 位置是近似的，不假裝精確 */
.kba-tile--plot.is-drift::before {
  content: ""; position: absolute; left: -5px; top: 50%;
  width: 3px; height: 1px; background: var(--kba-ink4); transform: translateY(-50%);
}
.kba__ygl {
  position: absolute; right: 5px; font-family: var(--kba-mono); font-size: 8.5px;
  color: var(--kba-ink4); transform: translateY(-50%); white-space: nowrap;
}
/* 直排標題：中文用 vertical-rl 就是正的，不能再 rotate(180)
   —— 那是拉丁字軸標的做法 */
.kba__ytitle {
  position: absolute; left: 4px; top: 50%; transform: translateY(-50%);
  writing-mode: vertical-rl; text-orientation: mixed;
  font-size: 9.5px; letter-spacing: .14em; color: var(--kba-ink3);
}

/* ---------- 點層連線 ---------- */
.kba__ovp path { fill: none; }
.kba-ed { stroke: var(--kba-jade); stroke-width: 1.7; }
.kba-ed--line { stroke: var(--kba-vio); stroke-dasharray: 5 3; stroke-width: 2; }
/* 跨面引用：點被別的面借去用 —— 欄式版面唯一表達不了的關係，所以給它最亮的樣式 */
.kba-ed--xref { stroke: var(--kba-gam); stroke-dasharray: 5 3; stroke-width: 2.2; }
.kba-eddot { fill: var(--kba-gam); stroke: var(--kba-bg); stroke-width: 1.6; }

/* ---------- 線帶 ---------- */
.kba__lband {
  position: sticky; bottom: 0; z-index: 15;
  background: var(--kba-sink); border-top: 1px solid var(--kba-rule);
  display: flex; min-width: 100%;
}
.kba-arc {
  stroke: var(--kba-vio); fill: none; opacity: .5; pointer-events: none;
  transition: opacity .14s, stroke-width .14s;
}
.kba-arc.is-lit { opacity: 1; stroke-width: 3.4; }
.kba__lmsg {
  position: absolute; right: 10px; top: 6px;
  font-family: var(--kba-mono); font-size: 9.5px; color: var(--kba-ink3); pointer-events: none;
}

/* 命中區與視覺線分開 —— 同一條路徑既當 hit 又吃 :hover 改 stroke-width，
   會在游標下自己縮小 → 反覆 enter/leave 閃爍，點不到。 */
.kba-hit { fill: none; stroke: transparent; stroke-width: 15; pointer-events: stroke; cursor: pointer; }

/* ---------- 體帶的橫桿 ---------- */
.kba-bar {
  stroke: var(--kba-jade2); fill: none; stroke-width: 2; pointer-events: none;
  transition: stroke-width .14s, stroke .14s;
}
.kba-bar.is-lit { stroke: var(--kba-jade); stroke-width: 3.6; }
.kba-bar--pres { stroke-dasharray: 6 4; }
.kba-tick { fill: var(--kba-jade2); pointer-events: none; transition: fill .14s; }
.kba-tick.is-lit { fill: var(--kba-jade); }
/* 文字光暈用背景色描邊，讓標籤壓在橫桿上仍讀得出來 */
.kba-lab {
  font-size: 9.5px; fill: var(--kba-ink2); pointer-events: none;
  paint-order: stroke; stroke: var(--kba-sink); stroke-width: 3px; stroke-linejoin: round;
}
.kba-lab.is-lit { fill: var(--kba-jade); }

/* ---------- 側欄裡的圖冊控制項 ---------- */
.kbg-atlas-y { display: block; width: 100%; margin-top: 6px; }
.kbg-atlas-y.is-hidden { display: none; }
.kbg-atlas-y select,
select.kbg-atlas-y {
  width: 100%; padding: 5px 6px;
  background: var(--kbg-bg); color: var(--kbg-ink);
  border: 1px solid var(--kbg-line); border-radius: var(--radius-sm);
  font-size: var(--fs-xs); font-family: inherit;
}
.kbg-sub {
  display: flex; gap: 0; margin-bottom: 10px;
  border: 1px solid var(--kbg-line); border-radius: var(--radius-sm); overflow: hidden;
}
.kbg-sub__btn {
  flex: 1; padding: 5px 0; border: 0; background: transparent; cursor: pointer;
  color: var(--kbg-ink-2); font-size: var(--fs-xs); font-family: inherit;
  transition: background .14s, color .14s;
}
.kbg-sub__btn:hover { color: var(--kbg-ink); background: #232b38; }
.kbg-sub__btn.on { background: var(--kbg-brand-soft); color: #ffb283; }

/* 圖例的三個語意色（跟舞台上的筆觸一致） */
.kbg-leg__sw--kba-body { background: #4c9691; }
.kbg-leg__sw--kba-line { background: #a99cd6; }
.kbg-leg__sw--kba-xref { background: #d7ae4a; }
.kbg-leg__sw--kba-veto { background: #e2705a; }

/* ---------- 緊湊版（#/kb 的嵌入，容器高度有限）---------- */
/* 標準版的上下兩條帶加欄頭就要 238px，矮容器裡磚區會只剩一點點。
   常數那一側由 metricsFor() 換掉，這裡處理純樣式的部分。 */
.kbg:not(.kbg--fill) .kba { --kba-rowh: 36px; }
.kbg:not(.kbg--fill) .kba .kba-hd { min-height: 46px; padding: 6px 8px; }
.kbg:not(.kbg--fill) .kba .kba-hd__n { font-size: 12.5px; }
.kbg:not(.kbg--fill) .kba .kba-hd__rl { display: none; }
.kbg:not(.kbg--fill) .kba .kba__stack { padding: 5px 5px 14px; }

@media (prefers-reduced-motion: reduce) {
  .kba * { transition-duration: .01ms !important; }
}
