/* 三库（商品 / 客户 / 工厂供应商）。前缀一律 lb-。
 *
 * 布局抄的是 app/static/feishu/feishu.css 那套三栏（左筛选 / 中列表 / 右详情）——
 * 它已经在生产上跑着，断点也验证过。抄的是布局，不是配色。
 *
 * 颜色纪律（tests/test_ui_standard.py 无条件扫这个文件）：
 *   1. 不许出现裸十六进制色值（白名单只有 #fff/#ffffff/#000/#000000）；
 *   2. 不许有 :root，唯一的家是 tokens.css；
 *   3. 每个 var(--x) 都必须在 tokens.css 里有定义；
 *   4. 只引用**语义层** token，不碰 --g-* / --n-* / --a-* / --r-* / --b-* / --d-* 原始色阶
 *      （docs/中台信息架构与UI标准.md §3.1 原则 1）。
 */

* { box-sizing: border-box; }

/* display:flex/grid 会盖掉 hidden 属性（属性只给到 display:none 的 UA 默认值，
   任何显式 display 都比它强）。本页靠 hidden 控详情栏、批量条、未上线区，所以必须钉死。 */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  -webkit-font-smoothing: antialiased;
}

.lb-app { display: flex; flex-direction: column; height: 100vh; }

/* ---------------------------------------------------------------- 顶栏 */

.lb-top {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-5);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.lb-top-left { display: flex; align-items: center; gap: var(--sp-5); min-width: 0; }
.lb-top h1 { margin: 0; font-size: var(--fs-lg); font-weight: 600; white-space: nowrap; }
.lb-top-right { display: flex; align-items: center; gap: var(--sp-3); }
.lb-stat { color: var(--text-muted); font-size: var(--fs-xs); white-space: nowrap; }

.lb-tabs { display: flex; gap: var(--sp-1); }
/* 嵌在控制台 iframe 里时，shared/common.css 有一条 `html[data-embedded] header nav { display:none }`
   （给子页面自己的导航条用的），会把这排 tab 一起藏掉——用户 2026-09-23 从侧栏进来找不到「客户库」。
   三库的 tab 是页内切库，不是站内导航，嵌入时必须留着。 */
html[data-embedded] .lb-top .lb-tabs { display: flex; }
.lb-tab {
  border: 1px solid transparent; background: none; cursor: pointer;
  padding: 0 var(--sp-3); height: var(--ctl-h-sm);
  border-radius: var(--radius-sm);
  color: var(--text-secondary); font-size: var(--fs-sm); font-family: inherit;
}
.lb-tab:hover { background: var(--surface-hover); }
.lb-tab.is-on { background: var(--accent-soft-bg); color: var(--accent-soft-fg); border-color: var(--accent-soft-border); font-weight: 600; }

/* ---------------------------------------------------------------- 三栏骨架 */

.lb-body {
  flex: 1; min-height: 0;
  display: grid;
  grid-template-columns: var(--w-nav-panel) 1fr;
  background: var(--canvas);
}
.lb-body.with-detail { grid-template-columns: var(--w-nav-panel) 1fr var(--drawer-sm); }
.lb-body.side-off { grid-template-columns: 0 1fr; }
.lb-body.side-off.with-detail { grid-template-columns: 0 1fr var(--drawer-sm); }

/* 折叠手柄贴在左栏与列表的缝上 */
.lb-handle {
  position: absolute; left: var(--w-nav-panel); top: 50%;
  width: 14px; height: 44px; margin-left: -7px; margin-top: -22px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); cursor: pointer; padding: 0;
  z-index: var(--z-base);
}
.lb-handle::before {
  content: ""; display: block; width: 2px; height: 14px; margin: 0 auto;
  background: var(--text-muted); border-radius: var(--radius-full);
}
.lb-handle:hover { background: var(--surface-hover); }
.lb-body.side-off .lb-handle { left: 0; margin-left: 0; }

/* ---------------------------------------------------------------- 左：分类树 */

.lb-side {
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
}
.lb-body.side-off .lb-side { display: none; }

.lb-side-head { padding: var(--sp-3); border-bottom: 1px solid var(--border-subtle); }

.lb-seg { display: flex; gap: 0; border: 1px solid var(--border-control); border-radius: var(--radius-sm); overflow: hidden; }
.lb-seg button {
  flex: 1; border: 0; background: var(--surface); cursor: pointer;
  height: var(--ctl-h-sm); font-size: var(--fs-xs); font-family: inherit; color: var(--text-secondary);
}
.lb-seg button + button { border-left: 1px solid var(--border-subtle); }
.lb-seg button:hover { background: var(--surface-hover); }
.lb-seg button.is-on { background: var(--accent); color: var(--text-on-accent); font-weight: 600; }

.lb-tree { flex: 1; overflow-y: auto; padding: var(--sp-2); }

.lb-node {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; border: 0; background: none; cursor: pointer; font-family: inherit;
  padding: 0 var(--sp-2); height: var(--row-h);
  border-radius: var(--radius-sm);
  color: var(--text-primary); font-size: var(--fs-sm); text-align: left;
}
.lb-node:hover { background: var(--surface-hover); }
.lb-node.is-on { background: var(--surface-selected); color: var(--accent-soft-fg); font-weight: 600; }
.lb-node[data-depth="1"] { padding-left: var(--sp-5); }
.lb-node-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-node-n { color: var(--text-muted); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.lb-node.is-on .lb-node-n { color: var(--accent-soft-fg); }

/* 待确认（自动归类置信度不够）的角标 —— 截图里那种「建议分类」要能一眼看见 */
.lb-node-pending {
  background: var(--warning-bg); color: var(--warning-fg); border: 1px solid var(--warning-border);
  border-radius: var(--radius-full); padding: 0 var(--sp-2);
  font-size: var(--fs-xs); font-variant-numeric: tabular-nums;
}

.lb-side-foot { border-top: 1px solid var(--border-subtle); padding: var(--sp-3); }
.lb-side-title { margin: 0 0 var(--sp-2); font-size: var(--fs-xs); color: var(--text-muted); }
.lb-missing { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.lb-chip {
  border: 1px solid var(--border-control); background: var(--surface); cursor: pointer;
  border-radius: var(--radius-full); padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-xs); font-family: inherit; color: var(--text-secondary);
}
.lb-chip:hover { background: var(--surface-hover); }
.lb-chip.is-on { background: var(--accent-soft-bg); color: var(--accent-soft-fg); border-color: var(--accent-soft-border); }

/* ---------------------------------------------------------------- 中：列表 */

.lb-main { display: flex; flex-direction: column; min-width: 0; min-height: 0; padding: var(--sp-4); gap: var(--sp-3); }

.lb-toolbar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.lb-scope { font-weight: 600; }
.lb-tools { display: flex; gap: var(--sp-2); }

.lb-search, .lb-select, .lb-jump input {
  height: var(--ctl-h); border: 1px solid var(--border-control); border-radius: var(--control-radius);
  background: var(--surface); color: var(--text-primary);
  font-family: inherit; font-size: var(--fs-sm); padding: 0 var(--sp-3);
}
.lb-search { width: 260px; }
.lb-search::placeholder { color: var(--text-placeholder); }
.lb-search:focus, .lb-select:focus, .lb-jump input:focus { outline: 2px solid var(--focus-ring); outline-offset: 1px; }

.lb-btn {
  height: var(--ctl-h); padding: 0 var(--sp-3);
  border: 1px solid var(--border-control); border-radius: var(--control-radius);
  background: var(--surface); color: var(--text-primary);
  font-family: inherit; font-size: var(--fs-sm); cursor: pointer;
}
.lb-btn:hover { background: var(--surface-hover); }
.lb-btn-primary { background: var(--accent); color: var(--text-on-accent); border-color: var(--accent); }
.lb-btn-primary:hover { background: var(--accent-hover); }
.lb-btn-ghost { border-color: transparent; background: none; color: var(--text-secondary); }

.lb-bulk {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  background: var(--accent-soft-bg); border: 1px solid var(--accent-soft-border);
  border-radius: var(--radius-md); color: var(--accent-soft-fg);
}

.lb-table-wrap {
  flex: 1; min-height: 0; overflow: auto;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
}

/* 表格按简道云的网格来（用户 2026-09-22 指定）：整行 30px、13px 字号、**每个单元格都有竖线**。
   和只有横线的「文档式表格」是两种东西——密集网格靠竖线把列切开，一屏能可信地读十几列。 */
/* table-layout 必须是 fixed：auto 时列宽由内容撑，th 上的 width 只是建议值，
   拖动改了也不生效，而且列宽会随翻页跳动。fixed 之后每列宽度说了算。 */
.lb-table {
  border-collapse: separate; border-spacing: 0;
  font-size: var(--fs-xs); table-layout: fixed; width: max-content; min-width: 100%;
}

.lb-table thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface-sunken); color: var(--text-secondary);
  text-align: left; font-weight: 600; white-space: nowrap;
  padding: 0 var(--sp-2); height: 34px;
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border-subtle);
}
.lb-table thead th:last-child { border-right: 0; }

.lb-sortable { cursor: pointer; user-select: none; }
.lb-sortable:hover { color: var(--text-primary); }
.lb-sortable[data-dir]::after { content: " ↓"; color: var(--accent); }
.lb-sortable[data-dir="asc"]::after { content: " ↑"; color: var(--accent); }

.lb-table tbody td {
  height: 30px; padding: 0 var(--sp-2);
  border-bottom: 1px solid var(--border-subtle);
  border-right: 1px solid var(--border-subtle);
  vertical-align: middle; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.lb-table tbody td:last-child { border-right: 0; }
.lb-table tbody tr:hover td { background: var(--surface-hover); cursor: pointer; }
.lb-table tbody tr.is-on td { background: var(--surface-selected); }

/* 行号列：简道云那套网格左边固定有一列序号，扫行时靠它定位 */
.lb-col-idx {
  width: 1%; text-align: right; color: var(--text-disabled);
  font-variant-numeric: tabular-nums; background: var(--surface-sunken);
}
.lb-table tbody tr:hover td.lb-col-idx { color: var(--text-secondary); }

.lb-col-check, .lb-col-img { width: 1%; }
.lb-col-check { text-align: center; }

.lb-thumb {
  width: 24px; height: 24px; object-fit: cover;
  border-radius: 3px; border: 1px solid var(--border-subtle);
  background: var(--surface-sunken); display: block;
}
/* 图片覆盖率只有 34%，且简道云直链约 15 天过期 —— 缺图是常态，占位要和有图的一样大，行高才不跳 */
.lb-thumb-none {
  width: 24px; height: 24px;
  border-radius: 3px; border: 1px dashed var(--border);
  background: var(--surface-sunken);
}

.lb-code { font-family: var(--font-mono); color: var(--text-secondary); }
.lb-name { max-width: 26ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }
.lb-en { max-width: 22ch; color: var(--text-muted); }
.lb-dim { color: var(--text-disabled); }
.lb-num { text-align: right; font-variant-numeric: tabular-nums; }

/* 分类胶囊：形态承担语义，颜色不重复承担（§3.1 原则 4）——
   浅底 + 1px 同族边 + 深色字永远只表示「状态」，实心填充留给主操作 */
.lb-pill {
  display: inline-block; border-radius: var(--radius-sm);
  padding: 0 5px; font-size: var(--fs-xs); line-height: 18px;
  border: 1px solid var(--border); background: var(--surface-sunken); color: var(--text-secondary);
  max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle;
}
.lb-pill[data-state="manual"]   { background: var(--info-bg);    color: var(--info-fg);    border-color: var(--info-border); }
.lb-pill[data-state="auto"]     { background: var(--success-bg); color: var(--success-fg); border-color: var(--success-border); }
.lb-pill[data-state="pending"]  { background: var(--warning-bg); color: var(--warning-fg); border-color: var(--warning-border); }
.lb-pill[data-state="excluded"] { background: var(--danger-bg);  color: var(--danger-fg);  border-color: var(--danger-border); text-decoration: line-through; }

/* 资料完整度：5 格小条，缺什么 hover 能看见 */
.lb-meter { display: inline-flex; gap: 2px; vertical-align: middle; }
.lb-meter i { width: 5px; height: 12px; border-radius: 1px; background: var(--border); display: block; }
.lb-meter i.on { background: var(--success-fg); }

/* ---------------------------------------------------------------- 分页 */

.lb-pager { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; color: var(--text-secondary); }
.lb-total { font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.lb-pages { display: flex; gap: var(--sp-1); }
.lb-pages button {
  min-width: var(--ctl-h-sm); height: var(--ctl-h-sm); padding: 0 var(--sp-2);
  border: 1px solid var(--border-control); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text-primary);
  font-family: inherit; font-size: var(--fs-xs); cursor: pointer;
}
.lb-pages button:hover:not(:disabled) { background: var(--surface-hover); }
.lb-pages button.is-on { background: var(--accent); color: var(--text-on-accent); border-color: var(--accent); font-weight: 600; }
.lb-pages button:disabled { color: var(--text-disabled); cursor: default; }
.lb-pages .lb-gap { border: 0; background: none; cursor: default; color: var(--text-muted); }
.lb-per, .lb-jump { font-size: var(--fs-xs); display: flex; align-items: center; gap: var(--sp-1); }
.lb-jump input { width: 64px; }

/* ---------------------------------------------------------------- 右：详情 */

.lb-detail {
  background: var(--surface); border-left: 1px solid var(--border);
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
}
.lb-detail-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border-subtle);
}
.lb-detail-body { flex: 1; overflow-y: auto; padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-4); }

.lb-card { border: 1px solid var(--border); border-radius: var(--radius-md); padding: var(--sp-3); }
.lb-card h3 { margin: 0 0 var(--sp-2); font-size: var(--fs-sm); color: var(--text-secondary); font-weight: 600; }
.lb-hero { width: 100%; height: 160px; object-fit: contain; background: var(--surface-sunken); border-radius: var(--radius-sm); display: block; }

.lb-facts { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-2) var(--sp-3); margin: 0; font-size: var(--fs-sm); }
.lb-facts dt { color: var(--text-muted); white-space: nowrap; }
.lb-facts dd { margin: 0; word-break: break-word; }

.lb-kw { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.lb-kw span {
  border: 1px solid var(--border-subtle); border-radius: var(--radius-full);
  padding: 0 var(--sp-2); font-size: var(--fs-xs); color: var(--text-secondary); line-height: 1.9;
}

/* ---------------------------------------------------------------- 空态 / 骨架 / 未上线 */

.lb-empty-line, .lb-empty { color: var(--text-muted); font-size: var(--fs-sm); padding: var(--sp-4); text-align: center; margin: 0; }

.lb-skel { height: 12px; border-radius: var(--radius-sm); background: var(--skeleton-base); }

.lb-soon { padding: var(--sp-12) var(--sp-5); max-width: var(--prose-max); margin: 0 auto; }
.lb-soon h2 { margin: 0 0 var(--sp-3); font-size: var(--fs-xl); }
.lb-soon p { color: var(--text-secondary); line-height: var(--lh-prose); margin: 0 0 var(--sp-4); }
.lb-soon ul { color: var(--text-secondary); line-height: var(--lh-prose); padding-left: var(--sp-5); margin: 0; }
.lb-soon li { margin-bottom: var(--sp-2); }
/* 2026-10-01 工厂供应商占位页底下的去处；两颗都没权限（或权限还没读到）就整行不出 */
.lb-soon .lb-soon-go { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin: var(--sp-5) 0 0; color: var(--text-primary); }
.lb-soon-go a { display: inline-flex; align-items: center; text-decoration: none; }
html:not([data-access-ready]) .lb-soon .lb-soon-go, .lb-soon .lb-soon-go:not(:has(a:not([data-denied]))) { display: none; }

/* ---------------------------------------------------------------- 断点
   与 feishu.css 同档：1024 收起详情栏，760 收起左栏改为抽屉式。 */

@media (max-width: 1024px) {
  .lb-body.with-detail { grid-template-columns: var(--w-nav-panel) 1fr; }
  .lb-detail { position: fixed; inset: 0 0 0 auto; width: min(var(--drawer-sm), 100%); box-shadow: var(--shadow-3); z-index: var(--z-popover); }
}

@media (max-width: 760px) {
  .lb-body, .lb-body.with-detail { grid-template-columns: 1fr; }
  .lb-side { position: fixed; inset: 0 auto 0 0; width: min(var(--w-nav-panel), 86%); box-shadow: var(--shadow-3); z-index: var(--z-popover); }
  .lb-body.side-off .lb-side { display: none; }
  .lb-handle { left: 0; margin-left: 0; }
  .lb-search { width: 100%; }
  .lb-tools { flex: 1; }
  .lb-toolbar { flex-wrap: wrap; }
}

/* ---------------------------------------------------------------- 关键词编辑
   2026-09-22 从「选品规则」页搬过来的：关键词是商品主数据，该跟着商品走。
   写操作复用 selection_api 的现成接口，界面只换了个家。 */

.lb-kwchip {
  border: 1px solid var(--border-subtle); border-radius: var(--radius-full);
  padding: 0 var(--sp-2); line-height: 1.9; cursor: pointer;
  background: var(--surface); color: var(--text-secondary);
  font-size: var(--fs-xs); font-family: inherit;
}
.lb-kwchip:hover { background: var(--surface-hover); color: var(--text-primary); }
/* 停用的词不删除，只是划掉——它还要挡住自动生成器再把它加回来 */
.lb-kwchip.is-off { color: var(--text-disabled); text-decoration: line-through; background: var(--surface-sunken); }

.lb-kwadd { display: block; margin-top: var(--sp-3); font-size: var(--fs-xs); color: var(--text-muted); }
.lb-kwrow { display: flex; gap: var(--sp-2); margin-top: var(--sp-2); }
.lb-kwrow input {
  flex: 1; min-width: 0; height: var(--ctl-h);
  border: 1px solid var(--border-control); border-radius: var(--control-radius);
  background: var(--surface); color: var(--text-primary);
  font-family: inherit; font-size: var(--fs-sm); padding: 0 var(--sp-3);
}
.lb-kwrow input:focus { outline: 2px solid var(--focus-ring); outline-offset: 1px; }

/* 分页条照简道云：左边「N 条/页 · 共 X 条」，右边页码，中间留白撑开 */
.lb-pager-gap { flex: 1; }

/* ---------------------------------------------------------------- 冻结左侧列
   简道云那套网格把前几列钉在左边，横向滚到第 15 列时仍然知道自己在看哪一行。
   宽度必须写死：sticky 的 left 偏移量要能算出来，靠内容撑宽就对不齐了。 */

.lb-table th.lb-col-idx,   .lb-table td.lb-col-idx   { position: sticky; left: 0;    width: 40px;  min-width: 40px; }
.lb-table th.lb-col-check, .lb-table td.lb-col-check { position: sticky; left: 40px; width: 32px;  min-width: 32px; }
.lb-table th.lb-col-img,   .lb-table td.lb-col-img   { position: sticky; left: 72px; width: 40px;  min-width: 40px; }
.lb-table th.lb-col-code,  .lb-table td.lb-col-code  { position: sticky; left: 112px; min-width: 150px; }

/* 冻结列要自己有不透明底色，否则滚动时下层内容会透上来 */
.lb-table tbody td.lb-col-check,
.lb-table tbody td.lb-col-img,
.lb-table tbody td.lb-col-code { background: var(--surface); z-index: 1; }
.lb-table tbody tr:hover td.lb-col-check,
.lb-table tbody tr:hover td.lb-col-img,
.lb-table tbody tr:hover td.lb-col-code { background: var(--surface-hover); }
.lb-table tbody tr.is-on td.lb-col-check,
.lb-table tbody tr.is-on td.lb-col-img,
.lb-table tbody tr.is-on td.lb-col-code { background: var(--surface-selected); }
/* 表头的冻结列要压在表体之上（表头 z-index 2，这里再抬一档） */
.lb-table thead th.lb-col-idx,
.lb-table thead th.lb-col-check,
.lb-table thead th.lb-col-img,
.lb-table thead th.lb-col-code { z-index: 3; }
/* 冻结区和滚动区之间给一条实线，滚动时边界看得见 */
.lb-table th.lb-col-code, .lb-table td.lb-col-code { border-right: 1px solid var(--border); }

/* ---------------------------------------------------------------- 列宽拖动
   手柄压在每个表头的右边界上，做法与 app/static/datatable/ 那套一致：
   按下记起点 → 移动改宽 → 松开存 localStorage；双击还原默认。
   行号 / 勾选 / 主图三列不给拖：它们的宽度是冻结列 sticky 偏移量的依据，
   一改左边四列就会错位。 */

.lb-table thead th { position: relative; }
.lb-th-label { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 手柄必须**完全落在本列内**（right:0 而不是 -3px）。
   每个 th 都带 z-index:2（粘性表头要的），各自是一个层叠上下文，
   于是后一列会整体盖住前一列溢出到边界外的部分——手柄伸出去那几像素就点不到，
   鼠标落在下一列的表头上，表现为「拖不动，只选中了文字」。

   宽度给到 12px：8px 的透明条人手很难压准，尤其是触控板。
   再配一条 hover 时显出来的竖线当可见提示——不然用户根本不知道这儿能拖。 */
.lb-resize {
  position: absolute; top: 0; right: 0; width: 12px; height: 100%;
  cursor: col-resize; z-index: 4; user-select: none;
  touch-action: none;                 /* 触屏上别让浏览器把它当成滚动手势 */
  display: flex; align-items: center; justify-content: flex-end;
}
/* 可见提示：平时是那条本来就有的列分隔线，鼠标靠上去变粗变成主色 */
.lb-resize::after {
  content: ""; width: 2px; height: 60%; border-radius: 1px; background: transparent;
  transition: background var(--dur-fast) var(--ease);
}
.lb-resize:hover::after { background: var(--accent); }
.lb-table thead th:hover .lb-resize::after { background: var(--border-strong); }

/* 拖拽中整页禁选，否则会顺手把表头文字刷成选中态 */
body.lb-resizing { user-select: none; cursor: col-resize; }
body.lb-resizing .lb-resize::after { background: var(--accent); }

/* 老板 10-04：可视化——空状态（shared/viz.css）放进表格行里时不要多余的边距 */
.lb-table td > .sqv-empty { padding: 20px 8px; }
