/* ==========================================================================
   app-ui.css — 业务页面的通用控件（表格 / 表单 / 抽屉 / 树）
   只允许使用 app-tokens.css 里的变量，页面与脚本里禁止出现十六进制色值。
   ========================================================================== */

/* ── 页头 ───────────────────────────────────────────────────────────── */
.page-head{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--sp-4);margin-bottom:var(--sp-5);flex-wrap:wrap}
.page-head h1{margin:0}
.page-head .sub{margin:4px 0 0;color:var(--ink-3);font-size:var(--fs-body)}

/* ── 工具条 ─────────────────────────────────────────────────────────── */
.toolbar{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;margin-bottom:var(--sp-4)}
.toolbar .spacer{flex:1}

/* ── 筛选提示条 ─────────────────────────────────────────────────────── */
/* 门店默认区域会把列表收窄，必须让用户看见「被筛了」并能一键放开。
   放在工具栏正下方而不是右上角小字：这是改变结果集的操作，不是状态说明。 */
.filter-tip{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;
  margin:-8px 0 var(--sp-4);padding:8px 14px;border-radius:var(--r-md);
  background:var(--surface-2);border:1px solid var(--line-3);
  font-size:var(--fs-meta);color:var(--ink-2)}
/* display:flex 会盖掉浏览器默认的 [hidden]{display:none}，必须显式写回来 */
.filter-tip[hidden]{display:none}
.filter-tip-link{padding:0;border:0;background:none;cursor:pointer;
  font-size:var(--fs-meta);color:var(--green-ink);text-decoration:underline;text-underline-offset:3px}
.filter-tip-link:hover{color:var(--ink)}

/* ── 搜索框（设计稿 §5.2：内容区首行 48 高、圆角 10、常态无边框）─────
   为什么不用外层 .search 套 input：
     外层套壳后 input 的实测高度会变成 46（被容器的 1px 边框吃掉），
     视觉上和 48 没区别，但"看起来对"和"量出来对"是两件事 ——
     量出来的才是别人评审时拿到的数。所以直接让 input 自己成为搜索框。 */
.search-input{
  width:100%; height:48px; border-radius:10px; border:0;
  background:var(--surface-2); padding:0 16px;
  font-family:inherit; font-size:14px; color:var(--ink);
  transition:background 160ms, box-shadow 160ms;
}
.search-input::placeholder{ color:var(--ink-5); }
.search-input:hover{ background:#F5F5F1; }
.search-input:focus{
  background:var(--surface); outline:0;
  box-shadow:0 0 0 1px var(--green-line), 0 0 0 4px rgba(7,193,96,.08);
}

/* ── 按钮补充尺寸 ───────────────────────────────────────────────────── */
.btn-sm{padding:6px 12px;font-size:12px;border-radius:var(--r-sm);min-height:30px}
.btn-line{background:var(--surface);border:1px solid var(--line);color:var(--ink-2)}
.btn-line:hover{background:var(--surface-3);color:var(--ink)}
.btn-danger{background:var(--danger-bg);color:var(--danger-ink);border:1px solid transparent}
.btn-danger:hover{background:var(--danger);color:#fff}
.btn[disabled],.btn.is-disabled{opacity:.45;cursor:not-allowed;pointer-events:none}

/* ── 卡片 ───────────────────────────────────────────────────────────── */
.panel{background:var(--surface);border-radius:var(--r-lg);box-shadow:var(--shadow-card);padding:var(--sp-5)}
.panel + .panel{margin-top:var(--sp-4)}

/* ── 表格 ───────────────────────────────────────────────────────────── */
.table-wrap{background:var(--surface);border-radius:var(--r-lg);box-shadow:var(--shadow-card);overflow:hidden}
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
table.table{width:100%;border-collapse:collapse;font-size:var(--fs-body);min-width:640px}
table.table th{
  text-align:left;font-weight:600;color:var(--ink-3);font-size:var(--fs-meta);
  letter-spacing:.04em;text-transform:none;
  padding:10px var(--sp-4);background:var(--surface-2);
  border-bottom:1px solid var(--line);white-space:nowrap;
}
table.table td{padding:12px var(--sp-4);border-bottom:1px solid var(--line-3);color:var(--ink-2);vertical-align:middle}
table.table tbody tr:last-child td{border-bottom:none}
table.table tbody tr:hover td{background:var(--surface-2)}
table.table td.num{font-variant-numeric:tabular-nums}
table.table .cell-strong{color:var(--ink);font-weight:600}
table.table .cell-actions{white-space:nowrap;text-align:right}
table.table .cell-actions .btn{margin-left:6px}
table.table .indent{color:var(--ink-5);user-select:none}

/* ── 标签 ───────────────────────────────────────────────────────────── */
.chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:var(--r-full);
  font-size:var(--fs-meta);background:var(--surface-3);color:var(--ink-2);white-space:nowrap}
.chip + .chip{margin-left:4px}
.chip-green{background:var(--green-soft);color:var(--green-ink)}
.chip-warn{background:var(--warn-bg);color:var(--warn-ink)}
.chip-danger{background:var(--danger-bg);color:var(--danger-ink)}
.chip-mute{background:var(--surface-3);color:var(--ink-4)}

/* ── 分页 ───────────────────────────────────────────────────────────── */
.pager{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  min-height:44px; padding:var(--sp-2) var(--sp-4);
  box-shadow:inset 0 1px 0 var(--line-2);
  font-size:var(--fs-meta);color:var(--ink-3);flex-wrap:wrap}
/* 44px 怎么来的：按钮/下拉都是 28px 高，上下各 8px（--sp-2）→ 28+8+8=44。
   顶部分隔线用 inset 阴影而不是 border-top：全局 *{box-sizing:border-box} 下 border 的 1px
   仍要吃掉内容高度，28+8+8+1=45，正好把设计规范 §5.9 的 44px 撑破；阴影不占盒高。 */
.pager .pager-btns{display:flex;gap:6px}
/* 页码分页（APP.pager）：左侧「共 N 条 / 每页 N 条」，右侧「上一页 页码 下一页 跳至」 */
.pager-left,.pager-right{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}
.pager-total{font-size:13px;color:var(--ink-2)}
.pager-size{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--ink-3)}
.pager-size-sel{height:28px;padding:0 6px;font-family:inherit;font-size:12px;color:var(--ink-2);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm);cursor:pointer}
.pager-size-sel:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.pager-pages,.pager-jump{display:inline-flex;align-items:center;gap:4px}
.pager-btn{display:inline-flex;align-items:center;justify-content:center;min-width:28px;height:28px;
  padding:0 8px;font-family:inherit;font-size:12px;color:var(--ink-2);background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r-sm);cursor:pointer;
  transition:background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease)}
.pager-btn:hover:not(:disabled){background:var(--surface-3)}
.pager-btn:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.pager-btn.is-active{background:var(--brand);border-color:var(--brand);color:#fff;font-weight:600;cursor:default}
.pager-btn:disabled{color:var(--ink-5);background:var(--surface-2);cursor:not-allowed}
.pager-btn.is-active:disabled{color:#fff;background:var(--brand);opacity:1}
.pager-ellipsis{min-width:20px;text-align:center;color:var(--ink-4);-webkit-user-select:none;user-select:none}
.pager-mobile-text{display:none;font-size:12px;color:var(--ink-3)}
.pager-jump{font-size:12px;color:var(--ink-3)}
.pager-jump-input{width:44px;height:28px;padding:0 6px;font-family:inherit;font-size:12px;text-align:center;
  color:var(--ink-2);background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm)}
.pager-jump-input:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 2px var(--green-soft)}
/* 手机：中间页码塞不下，只留「上一页 / 第 3/26 页 / 下一页」 */
@media (max-width:640px){
  .pager{padding:var(--sp-2) var(--sp-3)}
  .pager-pages,.pager-jump{display:none}
  .pager-mobile-text{display:inline}
  .pager-left{width:100%;justify-content:space-between}
}

/* ── 空态 / 加载态 ──────────────────────────────────────────────────── */
.empty-state{padding:var(--sp-8) var(--sp-4);text-align:center;color:var(--ink-4);font-size:var(--fs-body)}
.is-loading{opacity:.55;pointer-events:none}

/* ── 表单 ───────────────────────────────────────────────────────────── */
.form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-4)}
.form-grid .span-2{grid-column:1/-1}
@media (max-width:720px){.form-grid{grid-template-columns:1fr}}
.form-item{display:flex;flex-direction:column;gap:6px}
.form-label{font-size:var(--fs-meta);color:var(--ink-3);font-weight:600}
.form-label .req{color:var(--danger);margin-left:2px}
.form-input,.form-select,.form-textarea{
  width:100%;min-height:38px;padding:8px 12px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--surface);color:var(--ink);
  font-size:var(--fs-body);font-family:inherit;transition:border-color var(--dur-fast) var(--ease);
}
.form-textarea{min-height:76px;resize:vertical;line-height:1.6}
.form-input:focus,.form-select:focus,.form-textarea:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(7,193,96,.12)}
.form-input:disabled,.form-select:disabled{background:var(--surface-3);color:var(--ink-4);cursor:not-allowed}
.form-hint{font-size:var(--fs-meta);color:var(--ink-4)}
.form-error{font-size:var(--fs-meta);color:var(--danger-ink);min-height:14px}

/* 多选组（角色 / 业务类型） */
.check-group{display:flex;flex-wrap:wrap;gap:8px}
.check-item{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:var(--r-full);
  border:1px solid var(--line);background:var(--surface);font-size:var(--fs-body);cursor:pointer;user-select:none}
.check-item input{accent-color:var(--brand);margin:0}
.check-item.is-on{border-color:var(--green-line);background:var(--green-soft);color:var(--green-ink)}

/* ── 抽屉（右侧滑出）───────────────────────────────────────────────── */
.drawer-mask{position:fixed;inset:0;background:rgba(20,24,27,.34);opacity:0;pointer-events:none;
  transition:opacity var(--dur-mid) var(--ease);z-index:40}
.drawer-mask.is-open{opacity:1;pointer-events:auto}
.drawer{position:fixed;top:0;right:0;bottom:0;width:min(560px,100%);background:var(--surface);
  transform:translateX(100%);
  transition:transform var(--dur-mid) var(--ease),box-shadow var(--dur-mid) var(--ease);
  z-index:41;display:flex;flex-direction:column}
/* 阴影只在打开时给。关闭态靠 translateX(100%) 把面板挪出视口，但 box-shadow
   不受视口裁剪：-24px 偏移 + 48px 模糊仍会漏回页面右边缘约 72px。一个页面里
   有多少个抽屉就叠多少层（房源详情 14 个），右边缘会被压出一条最深 #535656 的
   灰带，还盖住顶栏「退出」。见 2026-11-12 右边缘灰带排查。 */
.drawer.is-open{transform:translateX(0);box-shadow:var(--shadow-drawer)}
.drawer-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  padding:var(--sp-4) var(--sp-5);border-bottom:1px solid var(--line)}
.drawer-head h2{margin:0;font-size:var(--fs-title)}
.drawer-body{flex:1;overflow-y:auto;padding:var(--sp-5)}
.drawer-foot{display:flex;justify-content:flex-end;gap:var(--sp-3);padding:var(--sp-4) var(--sp-5);
  border-top:1px solid var(--line);background:var(--surface-2)}
.icon-btn{background:none;border:none;font-size:20px;line-height:1;color:var(--ink-4);cursor:pointer;padding:4px 8px;border-radius:var(--r-sm)}
.icon-btn:hover{background:var(--surface-3);color:var(--ink)}

/* ── 权限树 ─────────────────────────────────────────────────────────── */
.tree{display:flex;flex-direction:column;gap:2px}
.tree-group{border:1px solid var(--line-2);border-radius:var(--r-md);overflow:hidden;margin-bottom:var(--sp-3)}
.tree-group-head{display:flex;align-items:center;gap:8px;padding:10px var(--sp-4);
  background:var(--surface-2);font-weight:600;color:var(--ink);cursor:pointer}
.tree-group-head .count{margin-left:auto;font-size:var(--fs-meta);color:var(--ink-4);font-weight:400}
.tree-children{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:2px 12px;padding:var(--sp-3) var(--sp-4);
  background:var(--surface)}
@media (max-width:720px){.tree-children{grid-template-columns:1fr}}
.tree-leaf{display:flex;align-items:flex-start;gap:8px;padding:5px 6px;border-radius:var(--r-sm);
  font-size:var(--fs-body);color:var(--ink-2);cursor:pointer;line-height:1.5}
.tree-leaf:hover{background:var(--surface-2)}
.tree-leaf input{accent-color:var(--brand);margin-top:3px}
.tree-leaf .code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--fs-meta);color:var(--ink-4);margin-left:4px}

/* ── 提示条 ─────────────────────────────────────────────────────────── */
.notice{display:flex;gap:var(--sp-3);padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);
  font-size:var(--fs-body);line-height:1.6;margin-bottom:var(--sp-4)}
.notice-info{background:var(--type-resale-bg);color:var(--type-resale)}
.notice-warn{background:var(--warn-bg);color:var(--warn-ink)}
.notice-danger{background:var(--danger-bg);color:var(--danger-ink)}
.notice-ok{background:var(--green-soft);color:var(--green-ink)}

/* ── 轻提示 ─────────────────────────────────────────────────────────── */
.toast{position:fixed;left:50%;bottom:32px;transform:translate(-50%,16px);z-index:60;
  background:var(--ink);color:#fff;padding:10px 18px;border-radius:var(--r-full);
  font-size:var(--fs-body);box-shadow:var(--shadow-float);opacity:0;pointer-events:none;
  transition:opacity var(--dur-fast) var(--ease),transform var(--dur-fast) var(--ease);max-width:80vw}
.toast.is-show{opacity:1;transform:translate(-50%,0)}
.toast.is-error{background:var(--danger)}

/* 宽抽屉：权限树要横向铺两列，560px 会把权限名挤成两行 */
.drawer.drawer-wide{width:min(880px,100%)}

/* 角色页：左侧角色列表 + 右侧说明，窄屏自动堆叠 */
.split{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:var(--sp-4);align-items:start}
@media (max-width:1080px){.split{grid-template-columns:1fr}}

/* 权限树里的分组折叠三角 */
.tree-group-head .caret{color:var(--ink-4);transition:transform var(--dur-fast) var(--ease);display:inline-block;font-size:10px}
.tree-group.is-collapsed .tree-children{display:none}
.tree-group.is-collapsed .caret{transform:rotate(-90deg)}

/* ==========================================================================
   窄屏（≤900px）适配
   问题现场：侧栏是 flex-direction:column 的固定 208px 竖条，窄屏下把品牌挤成竖排
   「弈/天/房/产」，导航项缩成一列压在内容上面；表格单元格还会被压成「门/店」两行。
   处理原则：侧栏在窄屏改成顶部横向滚动条（不折叠成汉堡——后台系统的导航项不多，
   多一次点击不值得），表格改成内部横向滚动 + 单元格不换行。
   ========================================================================== */
@media (max-width:900px){
  .app{flex-direction:column}

  .sidebar{
    flex:0 0 auto; width:100%;
    flex-direction:row; align-items:center;
    gap:6px; padding:10px 14px;
    overflow-x:auto; overflow-y:hidden;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
  }
  .sidebar::-webkit-scrollbar{display:none}

  .sidebar .brand{
    flex:0 0 auto; white-space:nowrap;
    padding:0 12px 0 0; margin:0;
  }

  .nav-item{flex:0 0 auto; white-space:nowrap; padding:7px 10px; font-size:12px}
  .nav-item.is-active{background:rgba(255,255,255,.13)}
  .nav-item.is-active::before{display:none}

  .main{width:100%}

  .topbar{
    height:auto; flex:0 0 auto; flex-wrap:wrap;
    gap:8px; padding:10px 14px;
  }
  .topbar .who{font-size:12px; line-height:1.6}
  .topbar > div:last-child{gap:12px !important; flex-wrap:wrap}
  .topbar a{white-space:nowrap}

  .content{padding:14px}

  .page-head{gap:12px}
  .page-head .sub{font-size:12px}

  /* 单元格一律不换行，靠 .table-scroll 横向滚动；需要折行的列单独加 .cell-wrap */
  table.table{min-width:720px}
  table.table th,table.table td{white-space:nowrap}
  table.table td.cell-strong{white-space:normal}

  .form-grid{grid-template-columns:1fr}
  .split{grid-template-columns:1fr}
}

/* 允许折行的单元格（地址、多角色标签这类长文本） */
table.table td.cell-wrap{white-space:normal !important; min-width:140px}

/* ==========================================================================
   房源列表 / 详情
   ========================================================================== */

.tag-blue{ background:var(--brand-soft,#EAF1FF); color:var(--brand-ink,#1D4ED8); }

.house-list{ display:flex; flex-direction:column; gap:10px }

.house-row{
  display:grid; grid-template-columns:minmax(0,1fr) 168px; gap:16px;
  padding:14px 16px; background:var(--surface);
  border:1px solid var(--line); border-radius:var(--r-lg,10px);
  cursor:pointer; transition:border-color var(--dur-fast,.15s) var(--ease,ease);
}
.house-row:hover{ border-color:var(--ink-5) }
.house-row:focus-visible{ outline:2px solid var(--brand); outline-offset:2px }

.house-title{ font-size:15px; font-weight:600; color:var(--ink); line-height:1.45; margin-bottom:4px }
.house-meta{ font-size:13px; color:var(--ink-3); margin-bottom:3px }
.house-sub{ font-size:12px; color:var(--ink-4); margin-bottom:8px }
.house-foot{ display:flex; align-items:center; gap:6px; flex-wrap:wrap }

.house-price{ text-align:right; border-left:1px solid var(--line); padding-left:16px }
.price-main{ font-size:19px; font-weight:600; color:var(--ink); line-height:1.3 }
.price-sub{ font-size:12px; color:var(--ink-4); margin-top:2px }
.price-time{ font-size:11px; color:var(--ink-5); margin-top:6px }

@media (max-width:640px){
  .house-row{ grid-template-columns:1fr }
  .house-price{ text-align:left; border-left:0; border-top:1px solid var(--line);
    padding-left:0; padding-top:10px; display:flex; align-items:baseline; gap:10px; flex-wrap:wrap }
  .price-time{ margin-top:0 }
}

/* 详情页 KV 列表：两列自适应，长文本自动占满一行 */
.kv{ display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:12px 24px; margin:0 }
.kv-item{ min-width:0 }
.kv-item dt{ font-size:12px; color:var(--ink-4); margin-bottom:2px }
.kv-item dd{ margin:0; font-size:13px; color:var(--ink); line-height:1.6; word-break:break-all }

.card-title{ font-size:13px; font-weight:600; color:var(--ink-2); margin:0; letter-spacing:.01em }
.card-body{ margin-top:12px }
.card-head{ display:flex; align-items:center; justify-content:space-between; gap:12px }

.list-row{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:9px 0; border-bottom:1px dashed var(--line); font-size:13px;
}
.list-row:last-child{ border-bottom:0 }

/* 图片墙：固定 4 列，缩略图裁成正方形，避免竖图把行高顶开 */
.photo-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(120px,1fr)); gap:8px }
.photo-item{ position:relative; margin:0; aspect-ratio:1/1; border-radius:8px; overflow:hidden; background:var(--surface-3) }
.photo-item img{ width:100%; height:100%; object-fit:cover; display:block }
.photo-cover{
  position:absolute; left:6px; bottom:6px; padding:1px 6px; border-radius:4px;
  background:rgba(0,0,0,.62); color:#fff; font-size:11px;
}
.photo-del{
  position:absolute; top:4px; right:4px; width:22px; height:22px; border:0; border-radius:50%;
  background:rgba(0,0,0,.55); color:#fff; font-size:14px; line-height:1; cursor:pointer;
}
.photo-del:hover{ background:var(--danger) }

/* 缩略图可点开大图：光标给出提示，键盘聚焦时补一个内描边
   （用 -2px 内描边而不是外描边，否则圆角容器 overflow:hidden 会把描边裁掉一半） */
.photo-thumb{ cursor:zoom-in }
.photo-thumb:focus-visible{ outline:2px solid var(--brand,#2563EB); outline-offset:-2px }

/* 图片灯箱：全屏黑底 + 居中大图。
   结构 .lightbox > (.lightbox-stage > img.lightbox-img) + 关闭/左右/计数。
   stage 铺满整层但 pointer-events:none，只有 <img> 自己收事件 ——
   这样点空白处落到 .lightbox 上可以关闭，点在大图上则不会误关。 */
.lightbox{
  position:fixed; inset:0; z-index:55; display:flex; align-items:center; justify-content:center;
  background:rgba(8,10,12,.88); opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity var(--dur-mid,.2s) var(--ease,ease), visibility 0s linear .2s;
}
/* 关闭态用 visibility:hidden 而不是只靠 opacity:0：
   opacity 为 0 的元素仍然在 Tab 键的遍历顺序里，键盘用户会跳进一个看不见的按钮。
   visibility 延迟 .2s 再切，淡出动画才不会被立刻掐断。
   层级 55：高于抽屉（40/41），低于 toast（60）—— 灯箱开着时弹出的提示仍要看得见。 */
.lightbox.is-open{
  opacity:1; visibility:visible; pointer-events:auto;
  transition:opacity var(--dur-mid,.2s) var(--ease,ease), visibility 0s linear 0s;
}
.lightbox-stage{
  display:flex; align-items:center; justify-content:center;
  width:100%; height:100%; padding:24px; pointer-events:none;
}
.lightbox-img{
  max-width:90vw; max-height:85vh; width:auto; height:auto; object-fit:contain;
  pointer-events:auto; cursor:default; border-radius:6px;
  background:rgba(255,255,255,.04); box-shadow:0 18px 60px rgba(0,0,0,.55);
}
.lightbox-close{
  position:absolute; top:16px; right:16px; width:38px; height:38px;
  display:flex; align-items:center; justify-content:center;
  border:0; border-radius:50%; background:rgba(255,255,255,.14); color:#fff;
  font-size:22px; line-height:1; cursor:pointer; z-index:1;
}
.lightbox-nav{
  position:absolute; top:50%; transform:translateY(-50%); width:44px; height:44px;
  display:flex; align-items:center; justify-content:center;
  border:0; border-radius:50%; background:rgba(255,255,255,.14); color:#fff;
  font-size:26px; line-height:1; cursor:pointer; z-index:1;
}
.lightbox-close:hover{ background:rgba(255,255,255,.28) }
.lightbox-nav:hover{ background:rgba(255,255,255,.28) }
.lightbox-close:focus-visible,.lightbox-nav:focus-visible{ outline:2px solid #fff; outline-offset:2px }
.lightbox-prev{ left:16px }
.lightbox-next{ right:16px }
.lightbox-count{
  position:absolute; left:50%; bottom:18px; transform:translateX(-50%);
  padding:3px 12px; border-radius:var(--r-full,999px); background:rgba(0,0,0,.6);
  color:#fff; font-size:12px; letter-spacing:.04em;
}
@media (max-width:640px){
  .lightbox-stage{ padding:12px }
  .lightbox-img{ max-width:96vw; max-height:80vh }
  .lightbox-nav{ width:38px; height:38px; font-size:22px }
  .lightbox-prev{ left:8px }
  .lightbox-next{ right:8px }
  .lightbox-close{ top:10px; right:10px }
}

/* 跟进时间线 */
.timeline-item{ padding:10px 0 10px 14px; border-left:2px solid var(--line); margin-left:4px }
.timeline-item:first-child{ border-left-color:var(--brand) }
.timeline-head{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:4px; font-size:13px }
.timeline-body{ font-size:13px; color:var(--ink-2); line-height:1.65; white-space:pre-wrap }

/* 页签栏（客源：私海 / 公海）
   用下划线而不是胶囊：后台里胶囊控件容易被当成按钮，点下去以为会提交什么 */
.tabbar{ display:flex; gap:4px; border-bottom:1px solid var(--line); margin-bottom:var(--sp-4) }
.tab{
  position:relative; padding:9px 14px 10px; border:0; background:transparent; cursor:pointer;
  font-size:13px; color:var(--ink-4); font-weight:500;
}
.tab:hover{ color:var(--ink-2) }
.tab.is-active{ color:var(--ink) }
.tab.is-active::after{
  content:''; position:absolute; left:10px; right:10px; bottom:-1px; height:2px;
  background:var(--brand); border-radius:2px 2px 0 0;
}
.tab-badge{
  display:inline-block; min-width:18px; padding:0 5px; margin-left:4px;
  border-radius:var(--r-full); background:var(--surface-3);
  font-size:11px; line-height:16px; text-align:center; color:var(--ink-3);
}
.tab-badge:empty{ display:none }

/* 选择器（成交登记里选房源 / 选客户）
   为什么不用 <select>：房源动辄几千条，一次性塞进下拉框会把页面卡死；
   这里做成"输入关键词 → 出结果 → 点一条选中"，搜索交给后端游标接口。 */
.picker-line{ display:flex; gap:8px }
.picker-line .form-input{ flex:1; min-width:0 }
.picker-box{
  margin-top:8px; max-height:220px; overflow-y:auto;
  border:1px solid var(--line); border-radius:var(--r-md); background:var(--surface-2);
}
.picker-item{
  display:block; width:100%; text-align:left; padding:9px 12px; border:0; background:transparent;
  border-bottom:1px solid var(--line-3); cursor:pointer; font-size:13px; color:var(--ink-2); line-height:1.5;
}
.picker-item:last-child{ border-bottom:0 }
.picker-item:hover{ background:var(--surface-3) }
.picker-item b{ display:block; color:var(--ink); font-weight:600; font-size:13px }
.picker-item span{ color:var(--ink-4); font-size:12px }
.picker-chosen{
  margin-top:8px; padding:8px 12px; border-radius:var(--r-md);
  background:var(--surface-2); border:1px dashed var(--line);
  font-size:13px; color:var(--ink-3);
}
.picker-chosen.is-set{ border-style:solid; border-color:var(--brand-line,var(--line)); color:var(--ink) }

/* 成交状态步骤条：只读展示，不给点——状态只能往前推，点回去是错的 */
.steps{ display:flex; gap:0; margin:0 0 var(--sp-4) }
.step{
  flex:1; position:relative; text-align:center; font-size:12px; color:var(--ink-4);
  padding-top:22px;
}
.step::before{
  content:''; position:absolute; top:6px; left:50%; transform:translateX(-50%);
  width:10px; height:10px; border-radius:50%; background:var(--surface-3); border:2px solid var(--line);
}
.step::after{
  content:''; position:absolute; top:10px; left:50%; width:100%; height:2px;
  background:var(--line); z-index:-1;
}
.step:last-child::after{ display:none }
.step.is-done{ color:var(--ink-2) }
.step.is-done::before{ background:var(--brand); border-color:var(--brand) }
.step.is-current{ color:var(--ink); font-weight:600 }
.step.is-current::before{ background:var(--surface); border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-soft,rgba(0,0,0,.06)) }
.step.is-skip{ color:var(--ink-4); text-decoration:line-through }

@media (max-width:640px){
  .picker-line{ flex-direction:column }
  .steps{ display:none }
}

/* ── 业务参数页 ──────────────────────────────────────────────────────
   一项参数 = 左边"是什么/为什么"，右边"改成多少"。
   说明文字不折叠：这些数字改错的后果都是业务级的（客户被误收走），
   让用户点开三角才看到解释，等于默认他不看。 */
.panel-title{ font-size:var(--fs-title); font-weight:600; color:var(--ink); margin:0 0 4px }
.panel-desc{ font-size:var(--fs-body); color:var(--ink-3); margin:0 0 var(--sp-4); line-height:1.65 }
/* 现场说明（如"本店已单独设置，覆盖这里的公司默认值"）：颜色比正文重一点，
   因为它讲的是"你现在到底在用什么"，而不是"这个参数是干什么的"。 */
.panel-note{
  font-size:var(--fs-body); color:var(--ink-2); line-height:1.7;
  background:var(--surface-2); border-left:3px solid var(--brand);
  border-radius:var(--r-sm); padding:var(--sp-3) var(--sp-4);
  margin:0 0 var(--sp-4);
}
.param-list{ display:flex; flex-direction:column }
.param-row{
  display:flex; gap:var(--sp-5); align-items:flex-start;
  padding:var(--sp-4) 0; border-top:1px solid var(--line-2);
}
.param-row:first-child{ border-top:none; padding-top:0 }
.param-main{ flex:1; min-width:0 }
.param-title{ display:inline-flex; align-items:center; gap:6px; font-size:var(--fs-body); font-weight:600; color:var(--ink) }
.param-desc{ font-size:12px; color:var(--ink-3); line-height:1.7; margin:6px 0 0 }
.param-ctrl{ display:flex; align-items:center; gap:8px; flex-shrink:0; flex-wrap:nowrap; justify-content:flex-end; max-width:360px }
/* 下拉项不折行：之前的 flex-wrap 会把「恢复默认」挤到第二行，
   于是同一列里有的行高 40px、有的 76px，四行看下来参差不齐 */
.param-ctrl .form-select{ width:170px; flex:0 0 170px }
/* 城市/区域选择器比枚举宽一些：地名（如"巴音郭楞蒙古自治州"）在 170px 里只剩一半 */
.param-ctrl .form-select-wide{ width:200px; flex:0 0 200px }
.param-ctrl .param-actions{ flex-shrink:0 }
.param-ctrl .form-hint{ flex-basis:100%; text-align:right }
.param-num{ width:96px; text-align:right }
.param-unit{ font-size:12px; color:var(--ink-4); min-width:14px }
.param-actions{ display:flex; gap:6px }
.tag{
  display:inline-block; padding:1px 6px; border-radius:var(--r-sm,4px);
  font-size:var(--fs-meta); font-weight:500; line-height:1.6;
}
.tag-info{ background:var(--brand-soft,#EAF1FF); color:var(--brand-ink,#1D4ED8) }

@media (max-width:760px){
  /* 窄屏改成上下堆叠：左右排时输入框只有 60px 宽，数字被截断后看不清填了几位 */
  .param-row{ flex-direction:column; gap:var(--sp-3) }
  .param-ctrl{ max-width:none; width:100%; justify-content:flex-start }
  .param-num{ width:120px; text-align:left }
  /* 手机上让城市/区域占满整行：200px 固定宽在小屏会顶着「恢复默认」按钮 */
  .param-ctrl .form-select-wide{ width:100%; flex:1 1 auto; min-width:0 }
}

/* ── 删除引导（RB-00）───────────────────────────────────────────────
   卡片式单选，而不是下拉框。原因：这里要说服用户"先别删"，
   下拉框只能给出选项名，给不出每个选项的后果；而用户之所以想删，
   多数是因为不知道改状态也能达到同样目的。
   主行动（标记无效）用浅品牌底 + 左侧色条，删掉的那个用危险色，
   但不做成实心红按钮 —— 实心红会让人以为那是主按钮。 */
.guide-list{display:flex;flex-direction:column;gap:var(--sp-2)}
.guide-item{
  display:block;width:100%;text-align:left;cursor:pointer;
  padding:var(--sp-3) var(--sp-4);border:1px solid var(--line-2,var(--ink-5));
  border-left:3px solid transparent;border-radius:var(--r-md);
  background:var(--surface);font:inherit;color:inherit;
  transition:border-color .15s,background .15s;
}
.guide-item:hover{border-color:var(--brand);background:var(--surface-2,var(--surface))}
.guide-item.is-primary{border-left-color:var(--brand);background:var(--brand-soft,#EAF7EF)}
.guide-item.is-danger{border-left-color:var(--danger,#E5484D)}
.guide-item.is-danger:hover{border-color:var(--danger,#E5484D);background:var(--danger-bg,#FDECEC)}
.guide-item.is-active{border-color:var(--brand);box-shadow:0 0 0 2px var(--brand-soft,#EAF7EF)}
.guide-title{display:flex;align-items:center;gap:var(--sp-2);font-size:var(--fs-body);font-weight:600}
.guide-desc{display:block;margin-top:4px;font-size:var(--fs-meta);line-height:1.7;color:var(--ink-3)}
.tag-rec{background:var(--brand);color:#fff}
