/* AI CRM —— 基于 aham-ui v7.0 tokens（单一取值源，禁止硬编码其它色值）
   铁律：扁平无静止阴影 / 蓝 #336EE8 只做点缀 / 选中=墨色 / 状态=6px点+文字 / 表格只横线 */

:root {
  --blue: #336EE8; --blue-hover: #5C8BED; --blue-press: #164EC3; --blue-50: #EDF0F7;
  --paper: #FFFFFF; --panel: #F3F3F3; --line: #E7E7E7; --hover: rgba(20,20,20,.04);
  --ink: #262626; --ink-2: #5F5F5F; --ink-3: #6E6E6E; --ink-4: #6E6E6E;
  --ok: #5A7A60; --ok-50: #F0F2F0; --panel-strong: #E7E7E7;
  --warn: #8A7333; --warn-50: #F4F1E9;
  --risk: #9E3D31; --risk-50: #F4ECEA;
  --r-sm: 6px; --r-md: 8px; --r-lg: 12px;
  --ease: cubic-bezier(.2,0,0,1);
  --t-fast: 120ms; --t-med: 180ms; --t-page: 280ms; --t-card: 180ms;
  --mono: "JetBrains Mono", "SF Mono", Consolas, monospace;
  --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236E6E6E' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  --leading-cjk: 1.75;
  --row-h: 36px;  --ctl-h: 32px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; }
body {
  font-family: Inter, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
  background: var(--paper); color: var(--ink);
  font-size: 14px; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }

/* 键盘用户先进入正文；平时不占布局，不增加页面色块。 */
.skip-link {
  position: fixed; z-index: 220; inset-block-start: 8px; inset-inline-start: 8px; padding: 8px 12px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--paper);
  color: var(--ink); transform: translateY(-160%);
}
.skip-link:focus { transform: none; outline: 2px solid var(--blue); outline-offset: 2px; }

/* ---------- 布局骨架：Aham Rail 60px / Expanded Sidebar 264px ---------- */
.shell { display: flex; min-height: 100vh; }
.rail {
  width: 60px; flex: none; background: var(--paper); border-inline-end: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 0;
  padding: 16px 12px; position: sticky; top: 0; height: 100vh;
  transition: width var(--t-med) var(--ease);
  overflow: hidden;
}
.nav-open .rail { width: 264px; }
.rail .brand { display: flex; align-items: center; gap: 8px; padding: 0 4px; margin-bottom: 12px; flex: none; }
.rail .logo {
  width: 34px; height: 34px; border-radius: 9px; background: var(--blue);
  display: grid; place-items: center; flex: none;
}
.rail .logo span { display: block; width: 16px; height: 3px; background: #fff; border-radius: 2px; }
.rail .logo span + span { width: 12px; margin-top: 4px; }
.rail .brand-name { font-weight: 680; font-size: 15px; letter-spacing: -0.01em; }
.rail .nav {
  display: flex; align-items: center; gap: 12px;
  height: 36px; padding: 0 8px; border-radius: var(--r-md);
  color: var(--ink-2); position: relative; white-space: nowrap;
  border: none; background: none; width: 100%; text-align: start; font-size: 13.5px;
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
@media (hover: hover) { .rail .nav:hover { background: var(--panel); color: var(--ink-2); } }
.rail .nav.on { color: var(--ink); background: var(--panel); font-weight: 600; }
.rail .lab {
  opacity: 0; transform: translateX(var(--nav-label-offset, -4px)); pointer-events: none;
  transition: opacity var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.nav-open .rail .lab { opacity: 1; transform: none; pointer-events: auto; }
.rail svg { width: 20px; height: 20px; stroke-width: 1.8; flex: none; }
.rail .nav-toggle { cursor: pointer; color: var(--ink-4); }
.rail .nav-toggle .chev { transition: transform var(--t-med) var(--ease); }
.nav-open .rail .nav-toggle .chev { transform: rotate(180deg); }

/* PRD V3 九组核心目录：中段独立滚动，品牌和底部控制不被矮视口裁掉。 */
.rail-scroll {
  flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden;
  overscroll-behavior: contain; scrollbar-width: none;
  display: flex; flex-direction: column; gap: 4px; position: relative;
}
.rail-scroll::before,.rail-scroll::after {
  content: ""; position: sticky; z-index: 4; display: block; width: 100%; height: 0;
  flex: none; pointer-events: none;
}
.nav-open .rail-scroll[data-scroll-start="false"]::before {
  top: 0; height: 10px; margin-bottom: -10px;
  background: linear-gradient(to bottom, var(--paper), rgba(255,255,255,0));
}
.nav-open .rail-scroll[data-scroll-end="false"]::after {
  bottom: 0; height: 10px; margin-top: -10px;
  background: linear-gradient(to top, var(--paper), rgba(255,255,255,0));
}
.rail-scroll::-webkit-scrollbar { width: 0; height: 0; }
.nav-open .rail-scroll { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
.nav-open .rail-scroll::-webkit-scrollbar { width: 6px; }
.nav-open .rail-scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: var(--r-sm); }
.nav-core { display: flex; flex-direction: column; gap: 4px; }
.nav-divider { height: 1px; background: var(--line); margin: 4px 8px; flex: none; }
.nav-group { min-width: 0; }
.nav-primary-row { display: flex; align-items: center; min-width: 0; }
.nav-primary-row > .nav { flex: 1; min-width: 0; }
.nav-primary .lab { min-width: 0; align-items: center; gap: 8px; overflow: hidden; }
.nav-open .nav-primary .lab { display: flex; }
.nav-primary .lab > span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.rail .nav-primary.is-active { color: var(--ink); background: transparent; font-weight: 600; }
.rail .nav-group-single .nav-primary.is-active { background: var(--aham-selected); }
.nav-order { width: 20px; flex: none; color: var(--ink-2); font: 500 12px/1 var(--mono); }
.nav-group-toggle {
  display: none; width: 32px; height: 32px; flex: none; place-items: center;
  border: 0; border-radius: var(--r-sm); background: transparent; color: var(--ink-4);
}
.nav-open .nav-group-toggle { display: grid; }
@media (hover:hover) { .nav-group-toggle:hover { background: var(--hover); color: var(--ink); } }
.nav-group-toggle span { display: block; font: 18px/1 var(--mono); transition: transform var(--t-fast) var(--ease); }
.nav-group.is-open .nav-group-toggle span { transform: rotate(90deg); }
.rail .nav-children { padding: 2px 0 4px; }
.rail .nav-children .nav { color: var(--ink-2); }
.rail .nav-children .nav.on { color: var(--ink); background: var(--panel); }
.rail-footer {
  flex: none; display: flex; flex-direction: column; gap: 4px;
  margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line);
  background: var(--paper);
}
.rail :where(.nav, .nav-group-toggle):focus-visible {
  outline: 0; box-shadow: 0 0 0 3px rgba(51,110,232,.20); z-index: 1;
}
.rail-scroll:focus-visible { outline: 0; box-shadow: inset 0 0 0 2px rgba(51,110,232,.20); }

.main { flex: 1; min-width: 0; }
/* 页面壳收口（aham-ui v7.0.2 §8.2）：网页轨默认 1280 居中收口，数据密集页用 ultra 1536 扩列。
   width:100% 兜底窄屏；max-width 管超宽屏不失控；margin-inline:auto 居中。 */
.page { width: 100%; max-width: 1280px; margin-inline: auto;
        padding: 24px 32px 64px; animation: pageIn var(--t-page) var(--ease); }
.page.dense { max-width: 1536px; }
@media (min-width: 1800px) { .page { padding: 24px 48px 64px; } }
@keyframes pageIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ---------- 页面骨架三层结构（aham-ui §8.3） ----------
   page-header：页眉区（标题+副标题+主操作）
   page-toolbar：工具区（视图切换+筛选+搜索）
   page-content：内容区（卡片/表格/详情） */
.page-header { margin: 0 0 20px; display: flex; align-items: flex-start; gap: 16px; background: transparent; }
.page-header .title-group { display: flex; flex-direction: column; gap: 4px; }
.page-header-actions {
  margin-inline-start: auto; display: flex; align-items: center; justify-content: flex-end;
  gap: 8px; flex: none; min-height: var(--layout-btn-height);
}
.page-header h1 {
  font-family: "Inter Display", Inter, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
  font-size: 24px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.25;
}
.page-header .sub { color: var(--ink-2); font-size: 13px; line-height: 1.4; }
/* 详情页返回：标题【上方】一行，当面包屑用。
   不做成带边框的按钮——来处是层级信息，画成按钮就在跟标题抢视觉重量（第一版就是这么丑的）。 */
.backlink {
  display: inline-flex; align-items: center; gap: 2px; align-self: flex-start;
  margin-bottom: 2px; font-size: 13px; color: var(--ink-2);   /* 与标题下方那行短码同号，两行次要文字尺寸一致 */
  transition: color var(--t-fast) var(--ease);
}
.backlink:hover { color: var(--blue); }
.backlink svg { width: 14px; height: 14px; flex: none; stroke-width: 2.2; }

/* 全局搜索（aham-ui §8.5）：固定在工具区 trailing；静止态只显示 32px 图标，
   用户主动展开后才出现输入框，避免与页标题争夺视觉层级。 */
.search-box {
  display: flex; flex: 0 0 32px; align-items: center; width: 32px; height: 32px; min-width: 32px;
  padding: 0; overflow: hidden; background: transparent; border: 1px solid transparent;
  border-radius: var(--r-md); color: var(--ink-3);
  transition: width var(--t-med) var(--ease), flex-basis var(--t-med) var(--ease), background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.search-box.is-expanded {
  flex-basis: auto; width: clamp(240px, 24vw, 320px); min-width: 240px; padding-inline-end: 10px;
  background: var(--paper); border-color: var(--line);
}
.search-box:focus-within { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51,110,232,.15); }
.search-toggle {
  width: 32px; height: 32px; min-width: 32px; display: inline-grid; place-items: center;
  padding: 0; border: 0; border-radius: calc(var(--r-md) - 1px); background: transparent; color: var(--ink-3);
}
.search-toggle:hover { background: var(--hover); color: var(--ink); }
.search-toggle:focus-visible { outline: 0; box-shadow: 0 0 0 3px rgba(51,110,232,.2); }
.search-toggle svg { width: 16px; height: 16px; flex: none; stroke-width: 1.8; }
.search-box input[type="search"] {
  width: 0; min-width: 0; height: 30px; min-height: 30px; padding: 0; opacity: 0;
  visibility: hidden; border: 0; background: transparent; box-shadow: none; outline: 0;
  color: var(--ink); font-size: 13px; line-height: 30px;
}
.search-box.is-expanded input[type="search"] { width: 100%; opacity: 1; visibility: visible; }
.search-box input::placeholder { color: var(--ink-4); }

.page-toolbar {
  display: flex; align-items: center; gap: 16px;
  padding: 12px 0; border-bottom: 1px solid var(--line);
  /* 状态筛选 + 负责人筛选（十来个人名）同排，窄屏放不下就换行——宁可多占一行也不截断人名 */
  flex-wrap: wrap;
}
.page-toolbar:not(:has(.lead > *, .center > *, .trail > *)) { display: none; }
/* 详情页没有任何筛选，工具行里就剩一个搜索图标，却照样占满一整行（实测页头到正文
   之间 101px 死白，其中 57px 是这一行）。只剩搜索时把它收成贴边的一小格，
   搜索本身仍在——详情页上它是全站搜索的唯一入口，不能为了省空间删掉。 */
.page-toolbar:not(:has(.lead > *, .center > *)) {
  padding: 0; border-bottom: 0; margin-top: -8px;
}
.page-toolbar:not(:has(.lead > *, .center > *)) .trail { padding-block: 2px; }
.ownerseg { flex-wrap: wrap; }
.page-toolbar .lead { display: flex; flex: 1 1 auto; gap: 8px; align-items: center; flex-wrap: wrap; }
.page-toolbar .center { flex: 1; display: flex; gap: 8px; justify-content: center; align-items: center; }
.page-toolbar .trail { display: flex; margin-inline-start: auto; gap: 8px; align-items: center; justify-content: flex-end; }

/* 桌面工具栏固定为“筛选主列 + 折叠搜索列”。筛选很多时只在主列内部换行，
   搜索始终贴住最后一行快捷筛选，不再被 flex 挤成一整行空白。 */
@media (min-width: 769px) {
  .page-toolbar {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    align-items: end; column-gap: 8px; row-gap: 8px;
  }
  .page-toolbar .lead { grid-column: 1; grid-row: 1; min-width: 0; }
  .page-toolbar .center {
    grid-column: 1; grid-row: 2; min-width: 0;
    justify-content: flex-start;
  }
  .page-toolbar .center:empty { display: none; }
  .page-toolbar .trail {
    grid-column: 2; grid-row: 1; align-self: end;
    margin-inline-start: 0;
  }
  .page-toolbar:has(> .center:not(:empty)) > .trail { grid-row: 2; }
}

.page-content { margin-top: 24px; }

/* ---------- 长串兜底：URL / 邮箱 / 内网编号，任何文本块都必须能断行 ----------
   浏览器只在连字符处断 URL，【不在 "/" 处断】。政务公示、OA、网盘那类没有连字符的链接
   （雷达写进 source_metadata 的正是这种）在浏览器眼里是一个不可断 token：它撑破卡片、
   压住相邻 kv 项，一路把整页撑出横向滚动条（2026-08-22 实测线索详情横滚 306px、商机详情 423px）。
   两层防线：
   ① 内容区整体 break-word —— 有确定宽度的容器不再被单个长串撑破；
   ② 下面点名的「自由文本」块用 anywhere —— 连 min-content 也参与收缩，
      这些块常是 flex/grid 子项，只有 anywhere 拦得住。
   台账单元格是 white-space:nowrap + 省略号，本身不换行，这两条对它无效也无害。 */
.page-content, .drawer, .panel, dialog.modal, .aham-dialog { overflow-wrap: break-word; }
.kv .item .v,
.longtext .v-view,
.addr-list > div,
.src-box, .src-line,
.tl-item .body, .tl-item .signals, .tl-item .next, .tl-item .tl-side > *,
.na-one, .na-list li,
.next-strip,
.search-meta { overflow-wrap: anywhere; }

/* ---------- 卡片与网格 ---------- */
/* 内边距：大屏放开，让内容不贴边。
   注意这里【不能】用 @container —— .card 自己就是容器（container-type:inline-size 在下面），
   而容器查询只能选中容器的【后代】、选不中容器本身；写成 @container 只会命中嵌套卡，等于没写。 */
.card { background: var(--paper); border-radius: var(--r-lg); padding: 24px;
  animation: cardIn var(--t-card) var(--ease); }
/* 大屏不放大卡片 padding（aham-ui §3.4 卡片 padding 上限 24）；靠 grid 列数铺宽，不靠撑大内边距 */
.grid { display: grid; gap: 16px; }
.grid.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid.cols-2 { grid-template-columns: 1.4fr 1fr; align-items: start; }
/* 详情双栏（aham-ui §8.3 supporting-pane）：主栏 fill + 辅栏 340 固定。 */
.grid.detail { grid-template-columns: minmax(0, 1fr) clamp(320px, 24ic, 360px); align-items: start; }
/* 详情页两栏各自是一摞卡。 */
.grid.detail > .stack { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
/* 卡片内部所有容器元素必须占满宽度，避免内容偏左导致右侧留白 */
.grid.detail .card > * { width: 100%; }
.grid.detail .detail-head { width: 100%; }
.grid.detail .kv { width: 100%; }
.grid.detail .kv .item { width: calc(50% - 12px); }
.grid.detail .longtext { width: 100%; }
.grid.detail .longtext .v-view { max-width: 100% !important; }
.grid.detail .block-head { width: 100%; }
.grid.detail .chain { width: 100%; }
.grid.detail .chain-row { width: 100%; }
.grid.detail .att-list { width: 100%; }
.grid.detail .att-row { width: 100%; }
.grid.detail .timeline { width: 100%; }
.grid.detail .tl-item { width: 100%; }
.grid.detail .tl-item .body { max-width: 100% !important; }
/* 超宽屏封顶已由 .page 层级处理（max-width:1280px），此处不再重复封顶 */
@media (max-width: 1100px) { .grid.detail { grid-template-columns: 1fr; } }
@media (max-width: 900px) { .grid.cols-4 { grid-template-columns: repeat(2, 1fr); } .grid.cols-2 { grid-template-columns: 1fr; } }
@media (max-width: 600px) {
  .grid.cols-3 { gap: 8px; }
  .grid.cols-3 > .metric { padding: 14px 12px; }
  .grid.cols-3 > .metric .v { font-size: 24px; }
}

.metric .k { font-size: 12px; color: var(--ink-2); letter-spacing: 0.02em; display: flex; align-items: center; }
.metric .v { font-size: 30px; font-weight: 680; font-family: var(--mono); letter-spacing: -0.02em; margin-top: 4px; }
.metric .v small { font-size: 14px; color: var(--ink-2); font-weight: 500; margin-left: 2px; }
.metric .d { font-size: 12px; color: var(--ink-2); margin-top: 4px; }
.metric .d b { color: var(--ink-2); font-weight: 600; }
.dashboard-metric-link { display: flex; width: 100%; align-items: center; color: inherit; }
.dashboard-metric-link .go { margin-left: auto; opacity: .55; }
.dashboard-metric-link:focus-visible { outline: 0; box-shadow: 0 0 0 3px rgba(51,110,232,.20); border-radius: var(--r-sm); }
.dashboard-customer-links { display: flex; align-items: center; gap: 6px; }
.dashboard-customer-links a { text-underline-offset: 3px; }
.dashboard-customer-links a:hover { color: var(--ink); text-decoration: underline; }
.readonly-fields { border: 0; padding: 0; margin: 0; min-inline-size: 0; }
.readonly-fields:disabled input,
.readonly-fields:disabled textarea,
.readonly-fields:disabled select {
  color: var(--ink-2); background: var(--panel); cursor: default; opacity: 1;
  -webkit-text-fill-color: var(--ink-2);
}
/* 可点击穿透的指标卡 */
.linkcard { display: block; transition: background var(--t-fast) var(--ease); }
.linkcard .go { margin-left: auto; color: var(--ink-4); opacity: 1; transition: opacity var(--t-fast) var(--ease), color var(--t-fast) var(--ease); }
.linkcard:focus-visible { outline: 0; box-shadow: 0 0 0 3px rgba(51,110,232,.20); }
.linkcard:focus-visible .go { opacity: 1; color: var(--ink); }
@media (hover: hover) {
.linkcard:hover { background: var(--hover); }
.linkcard:hover .go { opacity: 1; color: var(--ink); }
}
.dashboard-team-link {
  min-height: 44px; margin-top: 12px; padding: 8px 12px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  border-bottom: 1px solid var(--line); color: var(--ink-2);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.dashboard-team-link > span:first-child { display: flex; min-width: 0; align-items: baseline; gap: 10px; }
.dashboard-team-link b { color: var(--ink); font-size: 13px; font-weight: 600; white-space: nowrap; }
.dashboard-team-link small { overflow: hidden; color: var(--ink-2); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.dashboard-team-link .go { flex: none; color: var(--ink-2); font-size: 12px; }
.dashboard-team-link:hover { background: var(--hover); color: var(--ink); }
.dashboard-team-link:focus-visible { outline: 0; box-shadow: 0 0 0 3px rgba(51,110,232,.20); }

.section-title { font-size: 13px; font-weight: 650; color: var(--ink-2); margin: 24px 0 8px; letter-spacing: 0.02em; }
.card .section-title:first-child { margin-top: 0; }

/* ---------- 表格：只横线，表头加粗不铺色，数字右对齐等宽；固定单行行高 ----------
   列宽三原则：①确定性内容列（短码/日期/状态/人名/数字）用 min-width，不写死 width；
   ②弹性列（名称/行业/下一步/内容）自适应填充；③窄屏兜底：表格横向滚动。 */
table.ledger { width: 100%; border-collapse: collapse; table-layout: fixed; min-width: 920px; }
/* 1280px + 264px 展开侧栏时卡内约 908px；线索 8 列合计 900px，避免隐形横滚。 */
table.ledger.lead-ledger { min-width: 900px; }
table.lead-ledger col.lead-col-code { width: 104px; min-width: 104px; }
table.lead-ledger col.lead-col-company { width: 140px; min-width: 140px; }
table.lead-ledger col.lead-col-status { width: 88px; min-width: 88px; }
table.lead-ledger col.lead-col-source { width: 84px; min-width: 84px; }
table.lead-ledger col.lead-col-industry { width: 116px; min-width: 116px; }
table.lead-ledger col.lead-col-owner { width: 120px; min-width: 120px; }
table.lead-ledger col.lead-col-next { width: 152px; min-width: 152px; }
table.lead-ledger col.lead-col-contacted { width: 96px; min-width: 96px; }
/* 线索分配是台账内操作，但会比普通台账多一列。专用合同压缩的是可省略的
   公司/来源/行业/下一步，短码、状态、负责人、最近联系和操作仍保留安全宽度。 */
table.ledger.lead-ledger-assignment { min-width: 900px; }
table.lead-ledger-assignment col.lead-col-code { width: 104px; min-width: 104px; }
table.lead-ledger-assignment col.lead-col-company { width: 104px; min-width: 104px; }
table.lead-ledger-assignment col.lead-col-status { width: 88px; min-width: 88px; }
table.lead-ledger-assignment col.lead-col-source { width: 72px; min-width: 72px; }
table.lead-ledger-assignment col.lead-col-industry { width: 96px; min-width: 96px; }
table.lead-ledger-assignment col.lead-col-owner { width: 120px; min-width: 120px; }
table.lead-ledger-assignment col.lead-col-next { width: 84px; min-width: 84px; }
table.lead-ledger-assignment col.lead-col-contacted { width: 96px; min-width: 96px; }
table.lead-ledger-assignment col.lead-col-assignment { width: 136px; min-width: 136px; }
/* 同一 908px 标准视口合同：只压缩弹性文本列，关键属性、数值、负责人和末列保留。 */
table.ledger.customer-ledger { min-width: 900px; }
table.customer-ledger col.customer-col-code { width: 100px; min-width: 100px; }
table.customer-ledger col.customer-col-name { width: 104px; min-width: 104px; }
table.customer-ledger col.customer-col-attribute { width: 104px; min-width: 104px; }
table.customer-ledger col.customer-col-industry { width: 112px; min-width: 112px; }
table.customer-ledger col.customer-col-scale { width: 72px; min-width: 72px; }
table.customer-ledger col.customer-col-open { width: 88px; min-width: 88px; }
table.customer-ledger col.customer-col-won { width: 88px; min-width: 88px; }
table.customer-ledger col.customer-col-owner { width: 120px; min-width: 120px; }
table.customer-ledger col.customer-col-contacted { width: 112px; min-width: 112px; }
table.ledger.partner-ledger { min-width: 900px; }
table.partner-ledger col.partner-col-code { width: 100px; min-width: 100px; }
table.partner-ledger col.partner-col-name { width: 160px; min-width: 160px; }
table.partner-ledger col.partner-col-kind { width: 96px; min-width: 96px; }
table.partner-ledger col.partner-col-group { width: 132px; min-width: 132px; }
table.partner-ledger col.partner-col-owner { width: 120px; min-width: 120px; }
table.partner-ledger col.partner-col-contacts { width: 80px; min-width: 80px; }
table.partner-ledger col.partner-col-open { width: 80px; min-width: 80px; }
table.partner-ledger col.partner-col-maintained { width: 132px; min-width: 132px; }
table.ledger.opportunity-ledger { min-width: 900px; }
table.opportunity-ledger col.opportunity-col-code { width: 100px; min-width: 100px; }
table.opportunity-ledger col.opportunity-col-name { width: 144px; min-width: 144px; }
table.opportunity-ledger col.opportunity-col-customer { width: 112px; min-width: 112px; }
table.opportunity-ledger col.opportunity-col-stage { width: 100px; min-width: 100px; }
table.opportunity-ledger col.opportunity-col-amount { width: 120px; min-width: 120px; }
table.opportunity-ledger col.opportunity-col-next { width: 132px; min-width: 132px; }
table.opportunity-ledger col.opportunity-col-followups { width: 72px; min-width: 72px; }
table.opportunity-ledger col.opportunity-col-owner { width: 120px; min-width: 120px; }
.card:has(> table.ledger) { overflow-x: auto; }
.ledger-scroll {
  position: relative; max-width: 100%; overflow-x: auto; overscroll-behavior-inline: contain;
  scrollbar-gutter: stable; scrollbar-color: var(--line) transparent;
}
.ledger-scroll:focus-visible { outline: 0; box-shadow: 0 0 0 3px rgba(51,110,232,.20); border-radius: var(--r-sm); }
.ledger col.object-col { min-width: 210px; }
.ledger td[data-primary] .rowlink { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
table.ledger th {
  text-align: left; font-size: 13px; font-weight: 500; color: var(--ink-2);
  padding: 0 16px; height: var(--row-h); border-bottom: 1px solid var(--line);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 单行固定行高：每格不换行、超长省略号，点进详情看全。
   表头行高 = 数据行高（aham-ui §8.13：不混用，靠加粗+底边线区分，不靠加高） */
table.ledger td {
  padding: 0 16px; height: var(--row-h); border-bottom: 1px solid var(--line); vertical-align: middle;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
table.ledger td > div, table.ledger td > span:not(.avatar-i):not(.dot):not(.chip):not(.code) {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
table.ledger tr:last-child td { border-bottom: none; }
table.ledger tbody tr { transition: background var(--t-fast) var(--ease); }
.interactive-row { cursor: pointer; }
.interactive-row:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
@media (hover: hover) {
table.ledger tbody tr:hover { background: var(--hover); }
table.ledger tbody tr:hover td:first-child,
table.ledger tbody tr:hover th:first-child { background: var(--hover); }
}
table.ledger td.num, table.ledger th.num { text-align: right; font-family: var(--mono); }
/* 首列冻结（aham-ui §8.13：列数 ≥9 时建议冻结首列） */
table.ledger th:first-child, table.ledger td:first-child {
  position: sticky; left: 0; background: var(--paper); z-index: 1;
}
table.ledger td.code, table.ledger .code { font-family: var(--mono); font-size: 12px; color: var(--ink-2); }
table.ledger a.rowlink { font-weight: 600; }
table.ledger a.rowlink:hover { color: var(--blue); }
/* 头像+名称同格：用 flex 保持单行不撑高 */
table.ledger td.cell-flex { display: flex; align-items: center; gap: 8px; }
table.ledger td.cell-flex > * { flex: none; }
table.ledger td.cell-flex > .nm { flex: 1; overflow: hidden; text-overflow: ellipsis; }

/* ---------- 内容密度三档（aham-ui §8.8） ----------
   comfortable 触控/窄屏：行 44 / 控件 40 / ×1.25
   standard 默认：        行 40 / 控件 32 / ×1
   compact 数据密集台账：  行 40 / 控件 32 / ×1 （台账不是纯表格，需要可点击区域）
   同页不混；触控/窄屏强制 comfortable。 */
[data-density="comfortable"] { --row-h: 44px; --ctl-h: 40px; }
[data-density="compact"]     { --row-h: 40px; --ctl-h: 32px; }
@media (pointer: coarse) { [data-density] { --row-h: 44px; --ctl-h: 40px; } }

/* ---------- 状态点：6px 点 + 文字 ---------- */
.dot { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-2); white-space: nowrap; }
.dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--ink-4); flex: none; }
.dot.blue::before { background: var(--blue); }
.dot.ink::before { background: var(--ink); }
.dot.ok::before { background: var(--ok); }
.dot.warn::before { background: var(--warn); }
.dot.risk::before { background: var(--risk); }

/* ---------- chips / segmented：灰轨上的白色选中项，不做一排黑色按钮 ---------- */
.seg { display: inline-flex; background: var(--panel); border-radius: var(--r-md); padding: 2px; gap: 2px; align-items: center; }
/* 既认 <a>（换视图，导航）也认 <button>（页面内开关，如新建商机的模式切换）。
   只写 .seg a 的后果：放个 button 进来，一条规则都不命中，两个态长得一模一样。 */
.seg :where(a, button) {
  padding: 6px 12px; border-radius: var(--r-sm); font-size: 13px; color: var(--ink-2); line-height: 1.4;
  transition: all var(--t-fast) var(--ease); white-space: nowrap;
}
.seg :where(a, button) { appearance: none; border: 0; background: transparent;
  font: inherit; cursor: pointer; }
.seg :where(a, button):hover { color: var(--ink-2); }
.seg :where(a, button).on { background: var(--paper); color: var(--ink); font-weight: 600; }
.seg :where(a, button):focus-visible { outline: 0; box-shadow: var(--aham-shadow-focus,
  0 0 0 3px rgba(51,110,232,.2)); }
.seg a .n { font-family: var(--mono); font-size: 12px; margin-left: 4px; opacity: 0.7; }

.oppfilter { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.oppfilter select {
  appearance: none; -webkit-appearance: none;
  padding: 6px 28px 6px 12px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background-color: var(--paper); color: var(--ink); font-size: 13px; cursor: pointer;
  background-image: var(--select-chevron);
  background-repeat: no-repeat; background-position: right 8px center;
  transition: border-color var(--t-fast) var(--ease);
}
.oppfilter select:hover { border-color: var(--ink-3); }
.oppfilter select:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51,110,232,0.15); }
.filter-clear { font-size: 12px; color: var(--ink-2); padding: 6px 8px; white-space: nowrap; }
.filter-clear:hover { color: var(--blue); }

.chip { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 12px;
        background: var(--panel); color: var(--ink-2); }
.chip.old { background: var(--ink); color: #fff; }
.chip.ftype { background: var(--blue-50); color: var(--blue); }

/* ---------- 按钮 ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; border: none; border-radius: var(--r-md);
  padding: 8px 16px; font-size: 13px; font-weight: 600; line-height: 1.4;
  background: var(--blue); color: #fff;
  transition: background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
@media (hover: hover) { .btn:hover { background: var(--blue-hover); } }
.btn:active { background: var(--blue-press); transform: translateY(1px); }
.btn.ghost { background: transparent; color: var(--ink-2); }
@media (hover: hover) { .btn.ghost:hover { background: var(--panel); color: var(--ink); } }
.btn.ghost:active { background: var(--line); transform: translateY(1px); }

/* ---------- 漏斗 ---------- */
.funnel-row { display: grid; grid-template-columns: 84px 1fr 132px; align-items: center; gap: 12px;
  padding: 8px; margin: 0 -8px; border-radius: var(--r-md); transition: background var(--t-fast) var(--ease); }
.funnel-row:hover { background: var(--hover); }
.funnel-row .lab { font-size: 13px; color: var(--ink-2); }
.funnel-row:hover .lab { color: var(--ink); }
.funnel-row .bar { height: 24px; border-radius: var(--r-md); background: var(--panel); overflow: hidden; }
.funnel-row .bar i {
  display: block; height: 100%; border-radius: var(--r-md); background: var(--ink-4); width: 0;
  transition: width var(--t-med) var(--ease);
}
.funnel-row.hot .bar i { background: var(--blue); }
.funnel-row .val { font-family: var(--mono); font-size: 12.5px; color: var(--ink-2); text-align: right; }

/* ---------- 工作台沉淀流 / 待办：可点击行 ---------- */
.feed-row { display: block; padding: 8px; margin: 0 -8px; border-radius: var(--r-md);
  transition: background var(--t-fast) var(--ease); }
.feed-row:hover { background: var(--hover); }
.feed { display: flex; flex-direction: column; }
.feed-line { display: flex; align-items: center; gap: 8px; padding: 8px; margin: 0 -8px;
  border-radius: var(--r-md); font-size: 13px; transition: background var(--t-fast) var(--ease); }
.feed-line:hover { background: var(--hover); }
.feed-line .ftime { color: var(--ink-2); font-family: var(--mono); font-size: 12px; flex: none; width: 72px; }
.feed-line .favatar { width: 18px; height: 18px; font-size: 12px; flex: none; }
.feed-line .fby { color: var(--ink); font-weight: 600; flex: none; }
.feed-line .fact { color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.feed-line .fref { color: var(--ink-2); font-size: 12px; margin-left: auto; flex: none;
  max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.feed-line:hover .fref { color: var(--blue); }

/* ---------- 时间线 ---------- */
.timeline { position: relative; padding-inline-start: 24px; }
.timeline::before { content: ""; position: absolute; inset-inline-start: 6px; inset-block: 8px; width: 1px; background: var(--line); }
.tl-item { position: relative; padding: 0 0 24px 0; }
.tl-item::before {
  content: ""; position: absolute; inset-inline-start: -24px; inset-block-start: 8px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--ink-4); outline: 4px solid var(--paper);
}
.tl-item.hot::before { background: var(--blue); }
.tl-item .meta { font-size: 12px; color: var(--ink-2); display: flex; gap: 8px; flex-wrap: wrap; }
.tl-item .meta b { color: var(--ink-2); font-weight: 600; }
.tl-item .meta .ftype { background: var(--blue-50); color: var(--blue); border-radius: 999px; padding: 1px 8px; font-size: 12px; }
/* 【结构复原】agent 写的正文本来就是分段的（段落用空行、列表项用单换行），
   但 HTML 默认 white-space:normal 会把换行折叠成空格，把结构渲染成一堵墙——
   不是 agent 写成一坨，是这里没接住。pre-line：保换行、折叠缩进空格（对 Jinja 模板缩进免疫）。
   ⚠ pre-line 只给换行、不给段距。WCAG 1.4.8 第 4 条原文（2026-07 核对过 w3.org 原文，条款确实存在，
   别再有人说它不存在而删掉这条）：「Line spacing (leading) is at least space-and-a-half within
   paragraphs, and paragraph spacing is at least 1.5 times larger than the line spacing.」
   1.6×14px → 段距 ≥33.6px，靠 agent 输出「段间空一行」拿到（空行=2.0 倍行距=44.8px，达标）。
   口径要准：1.4.8 是 AAA 级，且原文是「a mechanism is available to achieve the following」——
   它要求的是【有机制可达成】，不是【内容必须如此】。拿它当目标值可以，别拿它说谁「违规」。 */
.tl-item .body, .tl-item .signals, .tl-item .next { white-space: pre-line; }
/* 行长兜底：ic = 「水」字宽（U+6C34），40ic = 40 个汉字，对齐 WCAG 1.4.8 的 CJK 上限。
   别用 ch —— ch 是字形「0」的宽度（半角），实测本项目 14px 下 80ch ≈ 49.5 个汉字而非 80，差 1.6 倍；
   且 ch 随首个可用字体漂移。此处在右栏（≤39 字/行）本不 binding，
   真正生效的是 ≤1100px 断点栅格塌成单栏、卡片撑到 ~1050px（~75 字/行）的时候。 */
.tl-item .body { margin-top: 4px; font-size: 14px; line-height: var(--leading-cjk); max-width: min(40ic, 100%); }
/* 【老 bug 补漏】关键信号/下一步 以前没有行长上限，只有 .body 有。
   单列模式下（容器 <920px，或右栏、抽屉里）它们直接铺满卡片——实测 892px = 62.5 汉字/行，
   而旁边的 .body 老老实实 39.2 字。同一条跟进里两块文字行长差 1.6 倍，看着就是没对齐。
   两列模式下轨本身已 ≤44 字，这条不 binding（见 @container 里的 max-width:none）。 */
.tl-item .tl-side > * { max-width: min(40ic, 100%); }
.tl-item .signals {
  margin-top: 8px; padding: 8px 12px; border-inline-start: 2px solid var(--blue);
  background: var(--blue-50); border-radius: 0 var(--r-md) var(--r-md) 0; font-size: 13px; color: var(--ink-2);
}
.tl-item .next { margin-top: 8px; font-size: 13px; color: var(--ink-2); }
.tl-item .next b { color: var(--ink); }

/* ---------- 看板 ---------- */
/* 列数由模板 --cols 注入（STAGES 数量 + 可能的兜底列），不再写死 7 */
.board { display: grid; grid-template-columns: repeat(var(--cols, 7), minmax(124px, 1fr)); gap: 12px; overflow-x: auto; }
.board-shell { min-width: 0; }
.board-tools { min-height: 32px; margin-bottom: 8px; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.board-overflow-hint { color: var(--ink-2); font-size: 12px; }
.board { scrollbar-gutter: stable; scrollbar-color: var(--line) transparent; overscroll-behavior-inline: contain; }
.board:focus-visible { outline: 0; box-shadow: 0 0 0 3px rgba(51,110,232,.20); border-radius: var(--r-sm); }
.board[data-hide-empty="true"] .col[data-board-empty="true"] { display: none; }
.board .col-orphan h3 { color: var(--risk); }
.board .col h3 { font-size: 12px; font-weight: 650; color: var(--ink-2); padding: 4px 4px 8px; display: flex; justify-content: space-between; }
.board .col h3 .n { font-family: var(--mono); color: var(--ink-2); font-weight: 500; }
.board .col + .col { border-inline-start: 1px solid var(--line); padding-inline-start: 12px; }
.opp-card {
  background: var(--paper); border-radius: var(--r-md); padding: 12px; margin-bottom: 8px;
  display: block; transition: background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.opp-card:hover { background: var(--hover); }
.opp-card .cust { font-size: 12px; color: var(--ink-2); display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.opp-card .nm { font-weight: 600; font-size: 14px; margin: 4px 0 8px; line-height: 1.4; }
.opp-card .amt { font-family: var(--mono); font-size: 13px; color: var(--ink-2); }
.opp-card .na { font-size: 12px; margin-top: 8px; min-width: 0; overflow: hidden; }
/* 下一步可能是没有空格的中文长句，不能依赖 Jinja 按单词截断。
   点与文字拆成两个 flex 子项，文字占剩余宽度并由 CSS 响应式省略。 */
.opp-card .na .dot { display: flex; width: 100%; min-width: 0; max-width: 100%; }
.opp-card .na .na-text {
  display: block; flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------- 登录 ---------- */
.auth-wrap { min-height: 100vh; display: grid; place-items: center; background: var(--panel); }
.auth {
  width: 360px; background: var(--paper); border-radius: 16px; padding: 40px 36px 36px;
  animation: pageIn var(--t-page) var(--ease);
}
.auth .logo { width: 44px; height: 44px; border-radius: var(--r-lg); background: var(--blue);
  display: grid; place-items: center; margin-bottom: 16px; }
.auth .logo span { display: block; width: 20px; height: 4px; background: #fff; border-radius: 2px; }
.auth .logo span + span { width: 12px; margin-top: 4px; }
.auth h1 { font-size: 20px; font-weight: 680; letter-spacing: -0.01em; }
.auth .sub { color: var(--ink-2); font-size: 13px; margin: 4px 0 24px; }
.auth label { display: block; font-size: 12px; color: var(--ink-2); margin: 16px 0 8px; font-weight: 600; }
.auth input {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 10px 12px; font: inherit; background: var(--paper);
  transition: border-color var(--t-fast) var(--ease);
}
.auth input:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51,110,232,0.15); }
.auth .btn { width: 100%; justify-content: center; margin-top: 24px; padding: 12px; }
.auth .err { color: var(--risk); font-size: 13px; margin-top: 12px; }
.auth .foot { margin-top: 24px; font-size: 12px; color: var(--ink-2); text-align: center; }

/* ---------- 空态 ---------- */
.empty { padding: 56px 0; text-align: center; color: var(--ink-2); }
.empty svg { width: 36px; height: 36px; stroke-width: 1.4; color: var(--ink-4); margin-bottom: 8px; }
.empty p { font-size: 14px; }
.empty-overview { max-width: 720px; margin-inline: auto; padding: 56px 32px; }
.empty-overview h2 { color: var(--ink); font-size: 17px; font-weight: 600; }
.empty-overview p { max-width: 54ch; margin: 8px auto 0; line-height: 1.65; }
.empty-actions { display: flex; justify-content: center; gap: 8px; margin-top: 20px; }
.empty-help-link { display: inline-block; margin-top: 12px; color: var(--ink-2); font-size: 12px; text-decoration: underline; text-underline-offset: 3px; }
.empty-help-link:hover { color: var(--ink); }

/* ---------- 交错入场 ---------- */
.stagger > * { opacity: 0; transform: translateY(8px);
  animation: itemIn var(--t-med) var(--ease) forwards; }
.stagger > *:nth-child(1) { animation-delay: 0ms; }
.stagger > *:nth-child(2) { animation-delay: 30ms; }
.stagger > *:nth-child(3) { animation-delay: 60ms; }
.stagger > *:nth-child(4) { animation-delay: 90ms; }
.stagger > *:nth-child(5) { animation-delay: 120ms; }
.stagger > *:nth-child(6) { animation-delay: 150ms; }
.stagger > *:nth-child(7) { animation-delay: 180ms; }
.stagger > *:nth-child(8) { animation-delay: 210ms; }
.stagger > *:nth-child(9) { animation-delay: 240ms; }
.stagger > *:nth-child(n+10) { animation-delay: 270ms; }
@keyframes itemIn { to { opacity: 1; transform: none; } }

/* ---------- 详情头部 ---------- */
.detail-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.detail-head h1 { font-size: 21px; font-weight: 680; }
.detail-head .code { font-family: var(--mono); color: var(--ink-2); font-size: 13px; }
.kv { display: flex; gap: 24px; flex-wrap: wrap; margin-top: 16px; }
.kv .item { min-width: 120px; }
.kv .item .k { font-size: 12px; color: var(--ink-2); }
.kv .item .v { font-size: 14px; font-weight: 600; margin-top: 1px; }
.kv .item .v.mono { font-family: var(--mono); }

/* ---------- 对话框（浮层是全系统唯一允许阴影的地方） ---------- */
dialog.modal {
  border: none; border-radius: var(--r-lg); padding: 0; width: 520px; max-width: calc(100vw - 48px);
  max-height: calc(100vh - 72px); overflow-y: auto; margin: auto;
  box-shadow: 0 12px 40px rgba(38, 38, 38, 0.14);
  animation: dlgIn var(--t-med) var(--ease);
}
dialog.modal::backdrop { background: rgba(38, 38, 38, 0.32); animation: fadeIn var(--t-med) var(--ease); }
@keyframes dlgIn { from { opacity: 0; transform: translateY(10px) scale(0.98); } to { opacity: 1; transform: none; } }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.modal form { padding: 24px; }
.modal h2 { font-size: 16px; font-weight: 680; margin-bottom: 16px; }
.modal .frow { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; }
.modal .frow .full { grid-column: 1 / -1; }
.modal .field { margin-bottom: 16px; }
.modal .field label { display: block; font-size: 12px; color: var(--ink-2); font-weight: 600; margin-bottom: 4px; }
.modal .field label::after, .panel .field label::after, .composer label::after {
  content: ''; margin-left: 4px; color: var(--risk); }
.modal .field label:has(+ input[required])::after,
.modal .field label:has(+ select[required])::after,
.modal .field label:has(+ textarea[required])::after,
.panel .field label:has(+ input[required])::after,
.panel .field label:has(+ select[required])::after,
.panel .field label:has(+ textarea[required])::after,
.composer label:has(+ input[required])::after,
.composer label:has(+ select[required])::after,
.composer label:has(+ textarea[required])::after {
  content: '*'; }
.modal .field input, .modal .field select, .modal .field textarea {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 8px 10px; font: inherit; font-size: 13.5px; line-height: 1.4; background: var(--paper); color: var(--ink);
  transition: border-color var(--t-fast) var(--ease);
}
.modal .field textarea { min-height: 64px; resize: vertical; }
.modal .field input:focus, .modal .field select:focus, .modal .field textarea:focus {
  outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51,110,232,0.15);
}
.modal .foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.modal .hint { font-size: 12px; color: var(--ink-2); margin-top: -6px; margin-bottom: 10px; }
/* 前景色必须一起写：aham-components.css 里 .btn.danger 是「浅红底 + 红字」，
   这里只改 background 的话 color 仍继承那份的 var(--aham-danger)，而 --risk 与
   --aham-danger 是同一个 #9E3D31 —— 深红底配同色红字，按钮上的字整个消失。 */
.btn.danger { background: var(--risk); color: #fff; }
.btn.danger:hover { background: #B04A3E; color: #fff; }
.btn.danger:active { background: #9E3D31; color: #fff; transform: translateY(1px); }

/* ---------- 右侧抽屉（预览附件/记录详情的通用件） ---------- */
.drawer-scrim {
  position: fixed; inset: 0; background: rgba(38, 38, 38, 0.24); z-index: 40;
  opacity: 0; pointer-events: none; transition: opacity var(--t-med) var(--ease);
}
.drawer {
  position: fixed; inset-block: 0; inset-inline-end: 0; width: 520px; max-width: 92vw; z-index: 41;
  background: var(--paper); box-shadow: -8px 0 32px rgba(38, 38, 38, 0.10);
  transform: translateX(var(--overlay-offscreen, 100%)); transition: transform 280ms var(--ease);
  display: flex; flex-direction: column;
}
.drawer[hidden] { display: none; }
/* 文档预览抽屉：按 A4 正常尺寸给宽（A4@96dpi=794px 正文 + 内边距），
   520px 的窄抽屉装 A4 会把表格切掉。行记录类抽屉仍走默认 520px。 */
.drawer.wide { width: min(96vw, 1000px); }
.drawer.wide .dbody { padding: 0; background: var(--panel); }
.drawer-open .drawer { transform: none; }
.drawer-open .drawer-scrim { opacity: 1; pointer-events: auto; }
.drawer .dhead {
  display: flex; align-items: center; gap: 8px; padding: 16px;
  border-bottom: 1px solid var(--line); flex: none;
}
.drawer .dhead h3 { font-size: 15px; font-weight: 680; flex: 1; }
.drawer .dbody { flex: 1; overflow-y: auto; padding: 16px; }
.drawer .dclose { border: none; background: none; cursor: pointer; color: var(--ink-3);
  width: 32px; height: 32px; border-radius: var(--r-md); display: grid; place-items: center; }
.drawer .dclose:hover { background: var(--panel); color: var(--ink); }
.drawer .dclose:active { background: var(--line); }

/* ---------- 表单抽屉（新增线索/客户/商机——右侧滑入，替代弹窗） ---------- */
.panel {
  position: fixed; inset-block: 0; inset-inline-end: 0; width: 480px; max-width: 94vw; z-index: 42;
  background: var(--paper); box-shadow: -8px 0 32px rgba(38, 38, 38, 0.10);
  transform: translateX(var(--overlay-offscreen, 100%)); transition: transform 280ms var(--ease);
  display: flex; flex-direction: column;
}
.panel[hidden] { display: none; }
.panel.open { transform: none; }
.panel .phead {
  display: flex; align-items: center; gap: 8px; padding: 16px;
  border-bottom: 1px solid var(--line); flex: none;
}
.panel .phead h3 { font-size: 15px; font-weight: 680; flex: 1; }
.panel form { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; }
/* `hidden` 只是 UA 的 display:none，上面那条 display:flex 会盖掉它——
   两张表单就会同时露在抽屉里。凡是靠 hidden 切换的表单必须显式压住。 */
.panel form[hidden] { display: none; }
/* 字段区按内容取高：不拉满，也不许被压扁。
   · flex:1（原来那条）把它拉满剩余空间，页脚被顶到抽屉最底——760×1900 下正文与
     页脚之间空出 760px（已有客户那张 958px），就是那一大片白；
   · min-height:0 是反过来的坑：它让这个 flex 项收缩到比内容还矮，字段溢出到盒子外，
     页脚跟着停在半空，下面又空一截。
   要的是 flex:none —— 不长不缩，内容超高时由外层 form 滚动、下面那条 sticky 吸住页脚。 */
.panel .pfields { flex: none; }
.panel .pfoot {
  /* margin-top:auto 会把页脚顶到抽屉最底：表单短的时候正文与按钮之间空出一大片
     （1440×900 下 164px，760×1900 下 760px）。要的是「跟在内容后面」，
     内容超高时才由下面那条 sticky 把它吸在底部。 */
  display: flex; justify-content: flex-end; gap: 8px; padding-top: 16px; margin-top: 16px;
  border-top: 1px solid var(--line); position: sticky; bottom: -16px; background: var(--paper);
  padding-bottom: 4px;
}
.panel .frow { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; }
.panel .frow .full { grid-column: 1 / -1; }

/* 台账行操作：格里只放单行按钮，表单一律走 dialog（浮层才逃得出列宽与 .ledger-scroll 的裁切）。 */
.row-actions { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; }
.row-actions .btn.sm { padding: 4px 10px; flex: none; }
/* 按钮永不被挤掉：格子不够时收缩的是它旁边那段说明文字（自带省略号）。 */
.row-actions > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.panel .field { margin-bottom: 16px; }
.panel .field label { display: block; font-size: 12px; color: var(--ink-2); font-weight: 600; margin-bottom: 4px; }
.panel .field input, .panel .field select, .panel .field textarea {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 8px 10px; font: inherit; font-size: 13.5px; line-height: 1.4; background: var(--paper); color: var(--ink);
  transition: border-color var(--t-fast) var(--ease);
}
.panel .field textarea { min-height: 64px; resize: vertical; }
/* P7 金额不会有人按箭头一万一万地加，箭头只占地方还容易误触；
   校验仍靠 type=number，配合模板上的 inputmode="numeric" 让手机弹数字键盘。 */
.panel .field input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
.panel .field input[type="number"]::-webkit-outer-spin-button,
.panel .field input[type="number"]::-webkit-inner-spin-button { appearance: none; margin: 0; }
/* P8 空的 date 由浏览器画出「年/月/日」，与真值同色，扫一眼像已填。
   空值态调浅，和填过的区分开。 */
.panel .field input[type="date"]:not(:valid),
.panel .field input[type="date"]:placeholder-shown { color: var(--ink-3); }
.panel .field input:focus, .panel .field select:focus, .panel .field textarea:focus {
  outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51,110,232,0.15);
}
.panel .dclose { border: none; background: none; cursor: pointer; color: var(--ink-3);
  width: 32px; height: 32px; border-radius: var(--r-md); display: grid; place-items: center; }
.panel .dclose:hover { background: var(--panel); color: var(--ink); }
.panel .dclose:active { background: var(--line); }

/* ---------- 单一中性首字头像：身份靠文字，不引入额外色相 ---------- */
.avatar-i {
  display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 50%;
  background: var(--ink-2); color: #fff; font-size: 12px; font-weight: 600; flex: none; user-select: none;
}
.avatar-i.lg { width: 32px; height: 32px; font-size: 13.5px; }
/* 台账里联合跟进人的头像堆叠：负相邻边距 + 白描边，叠成一小串（0–3 人 + 溢出计数） */
.avatar-i.stack { margin-left: -8px; box-shadow: 0 0 0 2px var(--paper); }
/* 我方跟进团队一行：头像 + 姓名 + 角色/原因 + 移除按钮 */
/* 跟进团队一行：头像 | 姓名+角色（原因换行） | 移除。
   姓名与「移除」都 flex:none —— 原因写长了就该它自己换行，不该去挤姓名（实测「李成豹」被挤成竖排三行）。 */
.fw-row { display: flex; align-items: flex-start; gap: 8px; padding: 5px 0; }
.fw-row .avatar-i { flex: none; margin-top: 1px; }
.fw-row .fw-main { flex: 1; min-width: 0; }   /* min-width:0 才允许里面的长句正常换行而不撑破容器 */
.fw-row .fw-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.fw-row .nm { font-weight: 600; flex: none; }
.fw-row .sub { color: var(--ink-2); font-size: 12px; line-height: 1.5; margin-top: 2px; }
.fw-row form { flex: none; }

/* ---------- 内联编辑（原地编辑，不弹窗） ---------- */
.inline-form .v-edit { display: none; }
.inline-form.editing .v-view { display: none; }
.inline-form.editing .v-edit { display: block; }
.inline-form .v-edit input, .inline-form .v-edit select, .inline-form .v-edit textarea {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-md); padding: 8px 10px;
  font: inherit; font-size: 13.5px; line-height: 1.4; background: var(--paper); color: var(--ink);
  transition: border-color var(--t-fast) var(--ease);
}
.inline-form .v-edit input:focus, .inline-form .v-edit select:focus, .inline-form .v-edit textarea:focus {
  outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51,110,232,0.15);
}
.inline-form .edit-foot { display: none; margin-top: 16px; gap: 8px; }
.inline-form.editing .edit-foot { display: flex; }
.card .card-tools { float: right; display: flex; gap: 4px; }

/* ---------- 区块加号 + 内联 composer ---------- */
.block-head { display: flex; align-items: center; justify-content: space-between; margin: 24px 0 8px; }
/* 标题和它的操作是一组，读的人视线不该在两端来回跑：商机页与 C01 工作区内改成紧随 + gap，
   只把真正该靠右的 ＋ 按钮用 margin auto 推开。实测原样式在 1920 下把「维护」
   推到离标题 421px 的地方。只在这两个作用域内收紧，不动其它台账页既有观感。 */
.grid.detail .block-head,
.workspace-aside-card .block-head,
.structured-block .block-head,
.comparison-block .block-head,
.competition-contacts .block-head {
  justify-content: flex-start; gap: 10px; flex-wrap: wrap;
}
.card .block-head:first-child, .card .block-head.first { margin-top: 0; }
.block-head .section-title { margin: 0; }
.plus-btn {
  width: 32px; height: 32px; border: none; border-radius: 8px; cursor: pointer;
  background: var(--panel); color: var(--ink-2); display: grid; place-items: center;
  transition: all var(--t-fast) var(--ease); font-size: 16px; line-height: 1;
}
.plus-btn:hover { background: var(--blue); color: #fff; }
/* 放在基础 .plus-btn 规则之后：热区合同按「第一条 .plus-btn{}」取宽高，
   排在它前面会把 32px 那条挡掉。 */
.grid.detail .block-head > .plus-btn,
.workspace-aside-card .block-head > .plus-btn { margin-inline-start: auto; }
.plus-btn:active { background: var(--blue-press); transform: scale(0.95); }
.composer {
  display: none; background: var(--panel); border-radius: var(--r-lg); padding: 16px; margin-bottom: 16px;
}
.composer.open { display: block; animation: itemIn var(--t-med) var(--ease); }
.composer .frow { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; }
.composer .frow .full { grid-column: 1 / -1; }
.composer label { display: block; font-size: 12px; color: var(--ink-2); font-weight: 600; margin-bottom: 4px; }
/* 勾选项：composer 里的 label 默认是「字段名」样式（block+粗体），复选框要跟框排一行、字重回正常 */
.composer label.chk { display: inline-flex; align-items: center; gap: 6px; font-size: 13px;
  font-weight: 500; color: var(--ink); cursor: pointer; margin-bottom: 2px; }
.composer label.chk input { width: auto; margin: 0; }
.composer input, .composer select, .composer textarea {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-md); padding: 8px 10px;
  font: inherit; font-size: 13.5px; line-height: 1.4; background: var(--paper); color: var(--ink);
  transition: border-color var(--t-fast) var(--ease);
}
.composer textarea { min-height: 64px; resize: vertical; }
.composer input:focus, .composer select:focus, .composer textarea:focus {
  outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51,110,232,0.15);
}
.composer .cfoot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.btn.sm { padding: 4px 12px; font-size: 13px; }

/* ---------- 溢出菜单（顶栏只留主操作） ---------- */
.menu-wrap { position: relative; }
.menu-pop {
  position: absolute; right: 0; top: calc(100% + 8px); min-width: 152px; z-index: 30;
  background: var(--paper); border-radius: var(--r-md); padding: 8px;
  box-shadow: 0 8px 28px rgba(38, 38, 38, 0.14); display: none;
}
.menu-pop.open { display: block; animation: dlgIn var(--t-fast) var(--ease); }
.menu-pop button, .menu-pop a {
  display: block; width: 100%; text-align: left; border: none; background: none; cursor: pointer;
  padding: 8px 12px; border-radius: var(--r-sm); font-size: 13px; color: var(--ink-2);
}
.menu-pop button:hover, .menu-pop a:hover { background: var(--panel); color: var(--ink); }
.menu-pop button.danger { color: var(--risk); }
.menu-pop .sep { height: 1px; background: var(--line); margin: 6px 8px; }

/* ---------- 附件区块 ---------- */
.att-list { display: flex; flex-direction: column; gap: 2px; }
.att-row {
  display: flex; align-items: center; gap: 12px; padding: 8px 12px; border-radius: var(--r-md); cursor: pointer;
  transition: background var(--t-fast) var(--ease);
}
.att-row:hover { background: var(--hover); }
/* flex 而非 grid+place-items（老 webview 如企业微信内置浏览器兼容更稳）；overflow 裁剪：
   万一 svg 尺寸没被 CSS 约束住（webview 没应用到 .att-ico svg），也不会撑破容器成一个大色块。 */
.att-ico { width: 34px; height: 34px; flex: none; border-radius: 8px;
  display: flex; align-items: center; justify-content: center; overflow: hidden; }
.att-ico svg { width: 18px; height: 18px; stroke-width: 1.6; flex: none; }
.att-ico.att-md { background: var(--blue-50); color: var(--blue); }
.att-ico.att-pdf { background: var(--risk-50); color: var(--risk); }
.att-ico.att-image { background: var(--ok-50); color: var(--ok); }
.att-ico.att-doc { background: var(--blue-50); color: #2B5FC7; }
.att-ico.att-sheet { background: var(--ok-50); color: #1F8A54; }
.att-ico.att-slide { background: var(--warn-50); color: #C9721B; }
.att-ico.att-text { background: #F0F1F3; color: var(--ink-2); }
.att-main { flex: 1; min-width: 0; }
.att-title { font-size: 13.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-meta { font-size: 12px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-code { font-family: var(--mono); font-size: 12px; color: var(--ink-2); flex: none; }

/* 独立文件资料工作区：左侧选目录，右侧读文件；不把文件名继续塞进树缩进。 */
.file-workspace.card { padding: 0; overflow: hidden; min-height: 560px; }
.file-workspace-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 20px 24px 16px; }
.file-workspace-sub { margin-top: 4px; color: var(--ink-2); font-size: 12px; }
.file-workspace > .composer { margin: 0 24px 16px; }
.file-workspace-tools { min-height: 52px; display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 8px 24px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.file-breadcrumb { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-2); font-size: 12.5px; }
.file-search { width: min(360px, 45%); flex: none; }
.file-search input { width: 100%; height: 32px; border: 1px solid var(--line); border-radius: 8px; background: var(--paper);
  padding: 0 11px; outline: none; color: var(--ink); font-size: 12.5px; }
.file-search input:focus { border-color: var(--blue); box-shadow: 0 0 0 2px var(--blue-50); }
.file-workspace-body { display: grid; grid-template-columns: 260px minmax(0, 1fr); min-height: 470px; }
.file-nav { padding: 12px 10px 20px; background: var(--panel); border-right: 1px solid var(--line); overflow: auto; }
.file-folder-row { width: 100%; min-height: 34px; display: flex; align-items: center; gap: 8px; padding: 5px 9px;
  border: 0; border-radius: 7px; background: transparent; color: var(--ink-2); cursor: pointer; text-align: left; font: inherit; }
.file-folder-row:hover { background: var(--hover); color: var(--ink); }
.file-folder-row.active { background: var(--line); color: var(--ink); font-weight: 600; }
.file-folder-row::before { content: "•"; width: 10px; flex: none; color: var(--ink-4); font-weight: 400; }
.file-nav-group > summary { list-style: none; }
.file-nav-group > summary::-webkit-details-marker { display: none; }
.file-nav-group > summary::before { content: "›"; font-size: 16px; line-height: 1; transform: rotate(0);
  transition: transform var(--t-fast) var(--ease); }
.file-nav-group[open] > summary::before { transform: rotate(90deg); }
.file-folder-label { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.file-folder-count { flex: none; color: var(--ink-2); font: 12px var(--mono); }
.file-nav-children { margin-left: 12px; padding-left: 7px; border-left: 1px solid var(--line); }
.file-list-pane { min-width: 0; background: var(--paper); }
.file-list-head { min-height: 44px; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 0 18px; border-bottom: 1px solid var(--line); color: var(--ink-2); font-size: 12px; }
.file-list-head > span:first-child { color: var(--ink-2); font-weight: 600; }
.file-table-wrap { overflow: auto; }
.file-table { width: 100%; min-width: 850px; border-collapse: collapse; table-layout: fixed; }
.file-table th { padding: 10px 12px; border-bottom: 1px solid var(--line); color: var(--ink-2); font-size: 12px; font-weight: 600; text-align: left; }
.file-table th:nth-child(1) { width: 28%; }
.file-table th:nth-child(2) { width: 30%; }
.file-table th:nth-child(3) { width: 9%; }
.file-table th:nth-child(4) { width: 16%; }
.file-table th:nth-child(5) { width: 8%; }
.file-table th:nth-child(6) { width: 9%; }
.file-list-row { cursor: pointer; }
.file-list-row[hidden] { display: none; }
.file-list-row:hover { background: var(--hover); }
.file-list-row td { padding: 11px 12px; border-bottom: 1px solid var(--line); color: var(--ink-2); font-size: 12.5px; vertical-align: middle; }
.file-name-cell { min-width: 0; display: flex; align-items: center; gap: 10px; }
.file-name-cell > span:last-child { min-width: 0; }
.file-name-cell b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); font-size: 13px; font-weight: 600; }
.file-name-cell small, .file-source-cell small { display: block; margin-top: 3px; color: var(--ink-2); font-size: 12px; }
.file-type-label { min-width: 42px; height: 24px; flex: none; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 6px; color: var(--ink-2); font: 12px var(--mono); }
.file-source-cell { min-width: 0; }
.file-source-cell > span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-actions { white-space: nowrap; text-align: right; }
.file-actions a, .file-actions button { border: 0; background: transparent; padding: 3px 5px; color: var(--blue); font: inherit; font-size: 12px; cursor: pointer; }
.file-actions form { display: inline; }
.file-actions button { color: var(--ink-2); }
.file-list-empty { padding: 56px 20px; text-align: center; color: var(--ink-2); font-size: 13px; }
.file-workspace-empty { padding: 72px 24px; }

@media (max-width: 860px) {
  .file-workspace.card { min-height: 0; }
  .file-workspace-tools { align-items: stretch; flex-direction: column; gap: 8px; padding-block: 12px; }
  .file-search { width: 100%; }
  .file-workspace-body { grid-template-columns: 1fr; min-height: 0; }
  .file-nav { max-height: 260px; border-right: 0; border-bottom: 1px solid var(--line); }
  .file-list-pane { min-height: 320px; }
}

@media (max-width: 768px) {
  .file-table-wrap { overflow: visible; padding: 10px 12px 14px; }
  .file-table { display: block; width: 100%; min-width: 0; table-layout: auto; }
  .file-table thead { display: none; }
  .file-table tbody { display: grid; gap: 8px; }
  .file-table .file-list-row {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px 14px;
    width: 100%; padding: 13px 14px; border: 1px solid var(--line);
    border-radius: var(--r-md); background: var(--paper);
  }
  .file-table .file-list-row td {
    display: flex; align-items: flex-start; justify-content: flex-end; gap: 8px;
    min-width: 0; width: auto; padding: 0; border: 0; text-align: right;
    white-space: normal; overflow: visible;
  }
  .file-table .file-list-row td::before {
    content: attr(data-label); flex: 0 0 auto; color: var(--ink-2); font-size: 12px;
  }
  .file-table .file-list-row td[data-primary],
  .file-table .file-list-row td[data-wide] {
    grid-column: 1 / -1; justify-content: flex-start; text-align: left;
  }
  .file-table .file-list-row td[data-primary]::before { display: none; }
  .file-table .file-list-row td[data-wide]::before { min-width: 66px; }
  .file-name-cell, .file-source-cell { width: 100%; }
  .file-source-cell > span { white-space: normal; overflow-wrap: anywhere; }
  .file-actions { justify-content: flex-start !important; }
  .file-actions a, .file-actions button { min-height: 44px; display: inline-flex; align-items: center; }
}

/* 跟进内联附件 chips（附件归位于产生它的动作） */
.att-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.att-chip {
  display: inline-flex; align-items: center; gap: 5px; border: 1px solid var(--line);
  background: var(--paper); border-radius: 999px; padding: 3px 10px 3px 7px;
  font-size: 12px; color: var(--ink-2); cursor: pointer;
  transition: all var(--t-fast) var(--ease);
}
.att-chip:hover { border-color: var(--ink-3); color: var(--ink); }
.att-chip svg { width: 13px; height: 13px; stroke-width: 1.8; color: var(--ink-3); }
.att-chip.att-doc svg { color: #2B5FC7; }
.att-chip.att-sheet svg { color: #1F8A54; }
.att-chip.att-slide svg { color: #C9721B; }
.att-chip.att-pdf svg { color: var(--risk); }
.att-chip.att-image svg { color: var(--ok); }

/* 无法网页预览（老 Office 等）：抽屉内仅下载卡片 */
.att-nopreview { padding: 28px 20px; text-align: center; color: var(--ink-2); }
.att-nopreview p { margin-bottom: 14px; font-size: 13px; }

/* 调研来源（人话化，不裸 JSON） */
/* 调研来源：逐项一行，标签共用一条左轨（display:contents 让所有项落进同一个网格对齐），
   值可以是长证据也可以是链接。 */
.src-box { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 3px 8px;
  font-size: 12.5px; color: var(--ink-2); }
.src-box > .src-line, .src-box > .src-pills { grid-column: 1 / -1; }
.src-line { padding: 3px 0; }
.src-item { display: contents; }
.src-item .src-k { color: var(--ink-3); white-space: nowrap; }
.src-item .src-v { min-width: 0; overflow-wrap: anywhere; }
.src-item .src-v a { color: var(--blue); }
.src-pills { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
.src-pill {
  display: inline-flex; align-items: center; gap: 5px; background: var(--panel);
  border-radius: 999px; padding: 3px 10px; font-size: 12px; color: var(--ink-2);
  transition: all var(--t-fast) var(--ease);
}
.src-pill:hover { color: var(--blue); }
.src-pill svg { width: 12px; height: 12px; stroke-width: 2; }

/* 抽屉内的附件预览 */
/* 预览元信息条：宽抽屉里 dbody 无内边距，这条自己带 padding，钉在顶部 */
.att-drawer-meta {
  font-size: 12.5px; color: var(--ink-2); padding: 11px 20px; background: var(--paper);
  border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
/* PDF / 转换后的 Office：交给浏览器原生 PDF 阅读器，满高铺满抽屉——真·保真 */
/* PDF 预览 iframe（满屏铺满抽屉）。⚠️class 名不能叫 .att-pdf——会和列表里的 PDF 图标
   <span class="att-ico att-pdf"> 撞名（同优先级、此规则在后），把 34px 图标撑成满屏大粉框。 */
.att-pdfframe { width: 100%; height: calc(100vh - 106px); border: none; display: block; background: var(--panel); }
/* 抽正文降级预览：裱成一张 A4 纸(794px@96dpi)，而不是贴边的文本流 */
.att-paper {
  width: 794px; max-width: calc(100% - 40px); margin: 22px auto; background: var(--paper);
  border: 1px solid var(--line); border-radius: 2px; padding: 54px 62px 64px;
}
.att-loading { padding: 60px 20px; text-align: center; color: var(--ink-2); font-size: 13px; }

/* 日报/周报预览抽屉：草稿 | 最终稿 两张纸卡并排，markdown 渲染 */
/* 日报「当天聚焦」：从推送卡片点进来（?date=），每人日报直接展开、不用点开看 */
.focus-day { padding: 18px 22px; }
.focus-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.focus-head .focus-stat { font-size: 13px; color: var(--ink-2); white-space: nowrap; }
.focus-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 14px; }
.focus-item { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-md); padding: 12px 14px; }
.focus-name { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 14px; margin-bottom: 8px; }
.focus-name .avatar-i { flex: none; }
.focus-name .dot { margin-left: auto; font-size: 12px; }
/* 日报正文自带换行分段，pre-wrap 保住结构，否则会折成一堵墙（feed 那边踩过） */
.focus-body { font-size: 13px; line-height: 1.65; color: var(--ink-2); white-space: pre-wrap; word-break: break-word; }
.focus-unsub { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); font-size: 13px; color: var(--ink-2); }
.focus-unsub .unsub-chip { display: inline-block; margin: 0 6px 4px 0; padding: 2px 10px; border-radius: 999px;
  background: color-mix(in srgb, var(--warn) 12%, transparent); color: var(--warn); font-size: 12.5px; }


/* MD 渲染排版（层级靠字号字重，链接用蓝） */
.md-body { font-size: 14px; line-height: var(--leading-cjk); color: var(--ink); }
.md-body h1 { font-size: 20px; font-weight: 680; margin: 18px 0 10px; }
.md-body h2 { font-size: 17px; font-weight: 680; margin: 16px 0 8px; }
.md-body h3 { font-size: 15px; font-weight: 650; margin: 14px 0 6px; }
.md-body h4, .md-body h5, .md-body h6 { font-size: 14px; font-weight: 650; margin: 12px 0 6px; }
/* 段间距 = 1×font-size（aham-ui §1.3.1）；最后一段去 margin */
.md-body p { margin: 1em 0; }
.md-body p:last-child { margin-block-end: 0; }
.md-body ul, .md-body ol { margin: 8px 0 8px 22px; }
.md-body li { margin: 3px 0; }
.md-body a { color: var(--blue); }
.md-body code { font-family: var(--mono); font-size: 12.5px; background: var(--panel); padding: 1px 5px; border-radius: 4px; }
.md-body pre { background: var(--panel); border-radius: 8px; padding: 12px 14px; overflow-x: auto; margin: 10px 0; }
.md-body pre code { background: none; padding: 0; }
.md-body blockquote { border-left: 3px solid var(--ink-3); padding-left: 16px; background: var(--panel); color: var(--ink-2); margin: 1em 0; }
.md-body hr { border: none; border-top: 1px solid var(--line); margin: 16px 0; }
.md-body strong { font-weight: 650; }
/* GFM 表格（docx/xlsx/csv 抽出的表）：横线为主、可横向滚动，沿用台账风格 */
.md-body .md-table { border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 13px; display: block; overflow-x: auto; }
.md-body .md-table th, .md-body .md-table td {
  border-bottom: 1px solid var(--line); padding: 6px 10px; text-align: left; white-space: nowrap;
}
/* docx（mammoth）预览：输出的是无 .md- 类名的原生 table/img，单独兜住——
   报价/规格表要看得清列边界，用细全框；图片按容器缩放不溢出。 */
.doc-body table { border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 13px; display: block; overflow-x: auto; }
.doc-body th, .doc-body td { border: 1px solid var(--line); padding: 6px 10px; text-align: left; vertical-align: top; }
.doc-body th { background: var(--paper); font-weight: 650; }
.doc-body img { max-width: 100%; height: auto; margin: 8px 0; border: 1px solid var(--line); }
/* 页图加载失败占位（webview 兜底）：不留空白色块，给一句可操作提示 */
.att-pagefail { padding: 22px; text-align: center; font-size: 12.5px; color: var(--warn);
  border: 1px dashed var(--line); border-radius: 8px; background: var(--paper); }
.md-body .md-table thead th { background: var(--panel); font-weight: 650; color: var(--ink-2); position: sticky; top: 0; }
@media (hover: hover) { .md-body .md-table tbody tr:hover { background: var(--panel); } }

/* 地理位置 pin */
.geo { display: inline-flex; align-items: center; gap: 4px; color: var(--ink-2); font-size: 12.5px; }
.geo:hover { color: var(--blue); }
.geo svg { width: 13px; height: 13px; stroke-width: 2; }

/* ---------- 顶部反馈条 ---------- */
.flash {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 16px; border-radius: 10px; margin-bottom: 16px; font-size: 13.5px;
  background: var(--paper); color: var(--ink-2);
  border-left: 3px solid var(--blue);
  animation: itemIn var(--t-med) var(--ease);
}
.flash.err { border-left-color: var(--risk); color: var(--risk); }

/* 商机阶段由列名表达，状态复用 Aham 的 6px 点 + 文字组件。 */

/* 行内小操作按钮 */
.mini { border: none; background: none; color: var(--ink-2); font-size: 12px; cursor: pointer;
        padding: 2px 6px; border-radius: 6px; transition: all var(--t-fast) var(--ease); }
.mini:hover { background: var(--panel); color: var(--ink-2); }
.mini:active { background: var(--line); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; transition-duration: 1ms !important; }
}

/* ---------- 联系人子模块 ---------- */
/* 待补全标记：图标+文字双编码，不只靠颜色（色觉障碍与黑白打印下也要读得出） */
.flag-todo {
  display: inline-flex; align-items: center; gap: 4px; margin-left: 8px;
  padding: 0 8px 0 4px; border-radius: 999px; font-size: 12px; font-weight: 600;
  background: var(--warn-50); color: #C9721B; vertical-align: middle;
}
.flag-todo svg { width: 11px; height: 11px; stroke-width: 2.2; }

/* 详情页头部人物条 */
.head-line { display: flex; align-items: center; gap: 16px; }
.hl-name { font-size: 19px; font-weight: 700; color: var(--ink); }
.hl-sub { margin-top: 4px; font-size: 12px; color: var(--ink-2); }
.hint-inline { font-size: 12px; color: var(--ink-2); margin-left: 12px; font-weight: 400; }

/* 决策圈层 chip：核心圈是墨色（选中/最重不用蓝，守 aham-ui 铁律） */
.chip.circle { background: var(--ink); color: #fff; }
.chip.role { background: var(--blue-50); color: var(--blue); }

/* 支持度：有序枚举 → 有序视觉。红=反对（全系统唯一红的语义沿用），灰=未接触 */
.sup { font-size: 12px; padding: 2px 8px; border-radius: 999px; font-weight: 600; }
.sup-0 { background: var(--panel); color: var(--ink-2); }          /* 未接触 */
.sup-1 { background: var(--risk-50); color: var(--risk); }         /* 反对 */
.sup-2 { background: var(--warn-50); color: #C9721B; }             /* 不支持 */
.sup-3 { background: var(--panel); color: var(--ink-2); }          /* 中立 */
.sup-4 { background: var(--ok-50); color: #1F8A54; }               /* 支持 */
.sup-5 { background: #1F8A54; color: #fff; }                       /* 铁杆支持 */

/* 相关商机卡（人 × 单） */
.stake-card {
  display: block; padding: 12px 14px; border-radius: 10px; background: var(--panel);
  margin-bottom: 8px; transition: background var(--t-fast) var(--ease);
}
.stake-card:hover { background: var(--line); }
.stake-card .cust { font-size: 13.5px; font-weight: 650; color: var(--ink); }
.stake-line { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; align-items: center; }
.stake-card .na { margin-top: 8px; }

/* ---------- 决策链（政治地图的数据面） ---------- */
/* 红旗：全部由 service 派生算出，不是手填字段。朱色短横沿用旁注语义 */
.flags { margin: 4px 0 16px; }
.flag-line {
  display: flex; align-items: flex-start; gap: 8px; padding: 8px 0;
  font-size: 12px; line-height: var(--leading-cjk); color: var(--ink-2);
}
.flag-line .fbar { width: 4px; height: 16px; border-radius: 2px; background: var(--risk); flex: none; margin-top: 4px; }

.chain-row {
  display: block; padding: 8px 8px; border-bottom: 1px solid var(--line);
  transition: background var(--t-fast) var(--ease);
}
.chain-row:last-child { border-bottom: none; }
.chain-row:hover { background: var(--hover); }
/* 两行结构：窄的右栏里 7 个元素排一行必然折行糊成一团，拆两行才读得出 */
.ch-l1 { display: flex; align-items: center; gap: 6px; min-width: 0; }
.ch-l2 { display: flex; align-items: center; gap: 5px; margin-top: 5px; padding-left: 30px; }
.ch-name { font-size: 13.5px; font-weight: 650; color: var(--ink); white-space: nowrap; }
.ch-title { font-size: 12px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-inf { font-size: 12px; color: var(--ink-2); white-space: nowrap; }
.ch-fu { font-size: 12px; color: var(--ink-2); margin-left: auto; white-space: nowrap; flex: none; }

/* 「见了谁」多选：勾了才会写进 followup_contacts，联系人页时间线全靠它 */
.pick-row { display: flex; flex-wrap: wrap; gap: 6px; }
.pick {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px;
  border: 1px solid var(--line); border-radius: 999px; font-size: 12.5px;
  color: var(--ink-2); cursor: pointer; background: var(--paper);
  transition: all var(--t-fast) var(--ease);
}
.pick:hover { border-color: var(--ink-3); }
.pick input { accent-color: var(--blue); }
.pick:has(input:checked) { border-color: var(--blue); color: var(--ink); background: var(--blue-50); }
/* 勾选组不要挂 .field —— .panel .field input{width:100%} 会把复选框拉成 46px 宽，
   把标签文字挤成一列一个字；.panel .field label{display:block} 又把胶囊拆成上下两行。
   这里给勾选组补上 .field 唯一真正需要的那点间距，其余一概不继承。 */
.panel .aham-check-group { margin-bottom: 16px; }
.panel .aham-check-group legend {
  font-size: 12px; color: var(--ink-2); font-weight: 600; margin-bottom: 4px;
}
/* .aham-check-group label 自带 16px 右边距，会叠在 .pick-row 的 gap 上，胶囊间距忽宽忽窄。 */
.aham-check-group label.pick { margin: 0; font-size: 12.5px; }

/* ---------- 长文本呈现（P0/P1） ---------- */
/* 小标题：把已有的色带补成完整 layer-cake（只扫标题形成横向条纹的扫读模式）——
   这是【我们自己的判断】，不是引文。原注释把它归给「NN/g 眼动归纳」，但查证下来
   NN/g 没有这条可核实的出处（定向搜索两轮无果），归因是编的，已删。做法本身照旧。
   用 --ink-2 不用蓝：aham-ui 铁律「蓝只做点缀、正文无彩色文字」，左边框那 2px 蓝已用掉配额。 */
.sig-h {
  font-size: 12px; font-weight: 600; color: var(--ink-2);
  margin-bottom: 4px; letter-spacing: 0.02em;
}
/* 下一步列表：待办本就该是有序列表（可 Ctrl-F / 将来可做 checkbox / agent 可回读） */
.na-list { margin: 0; padding-left: 18px; }
.na-list li { margin: 3px 0; font-size: 13px; line-height: 1.7; color: var(--ink-2); }
.na-list li::marker { color: var(--ink-2); font-size: 12px; }
.na-one { font-size: 13px; color: var(--ink-2); }

/* 时间线里残留的「下一步」= 已被后续跟进顶掉的历史，不是待办。
   降权 + 明写「已更新」，免得看着像还要做的事（活的那条在右栏卡上）。 */
.next-was { color: var(--ink-2); }
.next-was .sig-h::after {
  content: "（已更新）"; font-weight: 400; color: var(--ink-2); margin-left: 4px;
}

/* ---------- 下一步卡（右栏第一张）：全页最该被一眼看到的东西 ----------
   强调靠三样：左侧 3px 竖条 + 墨色升到 --ink + 字号升到 14.5px/行高 1.75。
   不铺底色、不上彩色正文 —— aham-ui 铁律「蓝只做点缀」，那 3px 竖条就是全部配额。 */
.nextcard { border-left: 3px solid var(--blue); }
.nextcard.overdue { border-left-color: var(--risk); }
.nextcard .block-head.first { display: flex; align-items: center; gap: 10px; }
.na-list.big li, .na-one.big {
  font-size: 14.5px; line-height: 1.75; color: var(--ink); font-weight: 500;
}
.na-list.big { padding-left: 20px; }
.na-list.big li { margin: 7px 0; }
.na-list.big li::marker { color: var(--blue); font-weight: 600; font-size: 12px; }
/* .next 已在上面吃到 pre-line；列表化后由 <ol> 接管，pre-line 对它无害 */

/* 长文本字段（主营产品/需求描述/备注）：同样保住 agent 写的换行结构 */
.longtext .v-view { white-space: pre-line; display: block; max-width: min(40ic, 100%); }
/* .kv 里长文本字段的值不该加粗：600 是给短字段（金额/日期）做锚点的，长段落加粗等于没加粗 */
.kv .item .v.longv { font-weight: 400; }
/* 地址多行：一个地址一行，吃 aham-ui「只横线」的现成规矩做行间追踪 */
.addr-list { font-weight: 400; }
.addr-list > div { padding: 3px 0; font-size: 13.5px; }
.addr-list > div + div { border-top: 1px solid var(--line); }

/* 长文本分块：窄容器里就是普通块流——组名在上、内容在下（stacked）。
   左标签轨是【宽容器增强】，窄屏一律回退 stacked（Salesforce/GOV.UK/Polaris 的断点
   分别是 768/641/490px，都是这个路子）。窄屏照样有重点，只是没有轨。
   white-space:normal 是必需的护栏不是随手写的：父级 .v-view 吃了 pre-line，
   模板里只要吐出换行就会渲成真空行。 */
/* 不给整块设行长上限：它铺满卡片，跟旁边的「地址」一个待遇。
   为什么放弃 40ic：同一张卡上「地址」是铺满的（addr_lines 只拆 ｜丨| 和换行，不拆分号，
   所以它常是一整行），而这里缩成 40 字的半截柱子，右边死一片 —— 一张卡上两种宽度就是很奇怪。
   代价说清楚：无组名的整段会按卡宽走（实测 1240px 卡 ≈ 90 汉字/行）。
   现有数据 70~231 字 = 1~3 行，可接受；WCAG 1.4.8 的 40 字是 AAA 级、且原文是「有机制可调」，
   不是硬线。真正的长文本靠组名走双轨（每轨 ≤40 字），那条路径才是给大段文字准备的。 */
.tblocks { white-space: normal; max-width: 100%; }
.tblocks > .tb-k { font-weight: 600; color: var(--ink); margin-bottom: 2px; }
.tblocks > .tb-v, .tblocks > .tb-p { margin-bottom: 10px; }
.tblocks > *:last-child { margin-bottom: 0; }
/* 一条不可断的长 URL 会把块撑破容器（右侧栏窄到 380px，这是活场景不是理论）。
   anywhere 而不是 break-word：break-word 不参与 min-content 计算，堵不住 grid 轨（见下）。 */
.tblocks > .tb-v, .tblocks > .tb-p { overflow-wrap: anywhere; }

/* ---------- 宽容器里把空出来的地方用起来（容器查询，不是媒体查询） ----------
   问题：行长上限 40ic(560px) 不能动（动了宽屏就是 86 字/行不可读），
   但商机页主栏有 1228px —— 正文只用 560，旁边白空 624px，内容像被锁在左边。
   解法：不放宽行长，而是把「关键信号 / 下一步 / 附件」从正文【下面】挪到【右边】做边栏。
   既填满宽度，又正好把销售最想扫的东西从 19 行正文底下捞上来。
   用 @container 而不是 @media：同一个 .tl-item 在商机页主栏(1228)分两栏、
   在客户页右栏(518)自动回单栏——按【容器实际宽度】决定，不用猜它被放在哪。 */
.card { container-type: inline-size; }

@container (min-width: 920px) {
  /* 跟进条目：正文 | 关键信号·下一步·附件 —— 【两列等宽】。
     原来是 40ic + 1fr，实测 2560px 下排出 560px vs 1168px（右边是左边的 2.1 倍），
     并排两栏一宽一窄看着就是没对齐。等宽由 .grid.detail 的 max-width 兜住行长上限。 */
  .tl-item {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 40px;
  }
  .tl-item .meta { grid-column: 1 / -1; }
  .tl-item .body { grid-column: 1; grid-row: 2; max-width: none; }
  .tl-item .tl-side { grid-column: 2; grid-row: 2; }
  /* 两列模式下轨宽本身就 ≤44 字（由 .grid.detail 的 max-width 兜住），
     再叠一层 40ic 会让右列内容比左列窄一截、破坏「等宽」的观感。 */
  .tl-item .tl-side > * { max-width: none; }
  /* 边栏里的块首个不要再顶一段外边距（它已经和正文并排、不是接在下面） */
  .tl-item .tl-side > *:first-child { margin-top: 0; }
  .tl-item .tl-side .signals { margin-top: 0; }

  /* 长文本字段（需求描述/主营产品）：宽容器里排成「组名 | 内容」两栏轨。
     ——为什么不再用 columns（曾经用过，是错的，别改回去）：
     ① 它锁不住行长。规范 §3.4 伪算法 (11) 式 W := (U+gap)/N - gap —— 栏宽【永远】是容器均分值，
        column-width 规范原文只是「optimal」、「actual column width may be wider」，
        40ic 只参与算栏数、之后就被丢弃。实测：容器 1108px 时排 1 栏、栏宽 1064px = 77 汉字/行。
     ② 它给不了行对齐。multicol 是分片(fragmentation)容器，规范里根本没有「行」这个概念，
        且是列优先流。实测同一份数据 4 栏的各栏行位是 y[0] | y[0] | y[0,31] | y[0,52] —— 对不齐
        不是参数没调对，是它结构上就不提供。
     ③ 对 6/9 的单块数据它纯空转：break-inside:avoid 让不可拆的单块独占第 1 栏，
        实测 2388px 容器下右边死 1824px(76%) —— 正是上面那段注释声称要解决的问题。
     ④ 「限成两栏」会更糟：columns:40ic 2 实测 91 汉字/行（先定栏数再均分，栏反而更宽）。
     grid 三样都给：行长封顶、行位对齐、栏数可控。 */
  .longtext .v-view { max-width: none; }
  /* 类名叫 tb-rail 不叫 rail：仓库里 .rail 已经是【左侧导航栏】（width:64px; height:100vh;
     position:sticky）。叫 rail 会让 .tblocks.tb-rail 同时吃到导航栏那条规则，实测被压成 64px 宽、
     文字挤成一列竖排。新类名一律带 tb- 前缀，跟 tb-k/tb-v/tb-p 一致。 */
  .tblocks.tb-rail {
    max-width: none;
    display: grid;
    /* minmax(0, 40ic) 的行为正是要的：轨从 0 起，吃掉容器剩余空间【一直长到 40ic 为止】。
       所以它自己就是「先铺满、到 40 字封顶」，不需要再给容器加 max-width
       —— 加了反而会把内容轨顶到 68 字（踩过一次）。 */
    grid-template-columns: fit-content(12ic) minmax(0, 40ic);
    column-gap: 24px;
    row-gap: 12px;
    align-items: start;
  }
  /* 钉死列号：auto-placement 只按行填格、不认「组」，
     将来若一个组名跟两段内容，裸排会从那里开始永久错位。 */
  .tblocks.tb-rail > .tb-k { grid-column: 1; margin: 0; }
  .tblocks.tb-rail > .tb-v { grid-column: 2; margin: 0; }

  /* 【双轨】容器够宽时，两组「组名|内容」并排 —— 吃满宽度，同时每条内容轨仍 ≤40ic。
     这是「铺满」和「行长可读」唯一不打架的解法：不是把一行字拉到 86 字，是并排放两组。
     阈值 76ic(≈1047px)：一组实占 ≈「组名轨 66px + 24 + 40ic(551px)」≈ 641px，
     两组需要 ≈1310px 才能都满宽；不到就由 minmax 自动缩窄（1236px 容器实测每条内容轨 516px=37.5字），
     再窄到 1047px 以下就退回单轨，免得两列各剩二十来字、比单列更难读。
     依据：Salesforce Lightning「Record Form」官方规矩就是每行最多 2 个字段。 */
  @container (min-width: 76ic) {
    .tblocks.tb-rail {
      grid-template-columns: repeat(2, fit-content(12ic) minmax(0, 40ic));
    }
    /* 解开钉死的列号，交给 auto-placement 按 k,v,k,v 逐行流 ——
       第 1 组落 1/2 轨、第 2 组落 3/4 轨，第 3 组换行回到 1/2 轨。组不会被拆开。 */
    .tblocks.tb-rail > .tb-k,
    .tblocks.tb-rail > .tb-v { grid-column: auto; }
    /* 右边那组的组名往右挪一点：跟左组内容之间要有明确的沟，否则两组糊成一片认不出边界。
       nth-of-type 数的是 .tb-k 自己的序号（2n = 每行右边那个）。 */
    .tblocks.tb-rail > .tb-k:nth-of-type(2n) { padding-left: 28px; }
  }
  /* 没组名的块横跨两栏、自己锁 40ic：它没有标签，缩进到内容栏等于假装它有。
     min-width:0 不能省 —— minmax(0,40ic) 两端都是定值=非 intrinsic，fit-content(12ic)
     是这个 span 里唯一的 intrinsic 轨，而 fit-content 只钳 growth limit、不钳 auto-minimum。
     所以跨栏块里一条不可断的 URL 会把自己的 min-content 全灌进第 1 栏：
     实测 1184px 容器，纯中文轨宽 27.55px → 含一条 URL 时炸到 352.14px，组名离内容 376px。
     今天就潜伏着：OPP-0003 的 6 个 ①式块已经在当 .tb-p 跨栏，只是内容恰好是纯中文。 */
  /* 跨栏 + 铺满（跟 .tb-p 在卡片里的待遇一致，见上面「不给整块设行长上限」那段）。
     min-width:0 【不能删】：没它的话，跨栏块里一条不可断 URL 的 min-content 会全灌进第 1 栏
     —— 实测标签轨从 55px 炸到 442px，组名离自己的内容 466px。 */
  .tblocks.tb-rail > .tb-p { grid-column: 1 / -1; min-width: 0; margin: 0; }
}

/* ---------- 逐页预览：一页一页竖排，宽度我们说了算 ---------- */
.pdf-pages { padding: 22px; display: flex; flex-direction: column; align-items: center; gap: 20px; }
.pdf-page { width: 100%; max-width: 900px; }
.pdf-page img {
  width: 100%; height: auto; display: block; background: var(--paper);
  border: 1px solid var(--line);   /* 无阴影，靠 1px 线与灰底分开——aham-ui 铁律 */
}
.pdf-page figcaption {
  margin-top: 6px; text-align: center; font-size: 12px;
  color: var(--ink-2); font-family: var(--mono);
}

/* ---------- 「我的接入」接入向导：工具选择 + 配置生成 ---------- */
.tool-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 12px; }
.tool-tab {
  border: 1px solid var(--line); background: var(--paper); color: var(--ink-2);
  border-radius: 8px; padding: 7px 14px; font-size: 13px; cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.tool-tab:hover { color: var(--ink); }
.tool-tab.on { border-color: var(--blue); color: var(--ink); font-weight: 600; }
.cfg-box {
  display: block; background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  padding: 12px 14px; font-size: 12.5px; line-height: 1.6; white-space: pre-wrap;
  word-break: break-all; overflow-x: auto; margin: 8px 0; max-height: 340px; overflow-y: auto;
}
.cfg-howto { color: var(--ink-2); font-size: 13px; line-height: 1.7; white-space: pre-line; margin: 4px 0 2px; }
.cfg-caveat { color: var(--ink-2); font-size: 12.5px; line-height: 1.6; margin-top: 8px; }

/* ================================================================
   手机端适配（≤768px）
   主力：CSS 媒体查询（视口宽度是物理事实，不会错）
   兜底：html[data-device="mobile"] 选择器（处理极端情况）
   ================================================================ */

/* ---- 断点变量 ---- */
@media (max-width: 768px) {
  :root {
    --page-px: 16px;
    --page-py: 16px;
    --page-pb: 56px;  /* 底部留高给 mobile-tabs */
  }
}

/* ---- 外壳：隐藏侧栏，页面全宽 ---- */
@media (max-width: 768px) {
  .rail { display: none; }
  html.nav-open .rail { display: none; }
  .main { margin-left: 0; }
  .page { padding: var(--page-py) var(--page-px) var(--page-pb); max-width: none; }
  .shell { flex-direction: column; }
}

/* ---- 页眉：只保留页面身份，不再混放搜索与账号工具 ---- */
@media (max-width: 768px) {
  .page-header {
    margin-bottom: 16px; flex-direction: column; align-items: stretch; gap: 8px;
  }
  .page-header-actions {
    width: 100%; margin-left: 0; justify-content: flex-start; flex-wrap: wrap;
  }
  .page-header h1 { font-size: 22px; }
}

/* ---- 工具栏：移动端筛选与折叠搜索同排 ---- */
@media (max-width: 768px) {
  .page-toolbar {
    display: grid; grid-template-columns: minmax(0, 1fr) 44px;
    align-items: start; gap: 6px;
    padding: 8px 0;
  }
  .page-toolbar .lead {
    grid-column: 1; grid-row: 1; width: auto;
    min-width: 0; justify-content: flex-start; flex-wrap: wrap; gap: 6px;
  }
  .page-toolbar .center {
    grid-column: 1 / -1; grid-row: 2; width: 100%; min-width: 0;
    justify-content: flex-start; flex-wrap: wrap; gap: 6px;
  }
  .page-toolbar .center:empty { display: none; }
  .page-toolbar .trail {
    grid-column: 2; grid-row: 1; width: 44px;
    margin-left: 0; justify-content: flex-end; align-items: flex-start;
  }
  .page-toolbar:has(.search-box.is-expanded) .trail {
    grid-column: 1 / -1; grid-row: 3; width: 100%;
  }
  .search-box { width: 44px; height: 44px; min-width: 44px; }
  .search-box.is-expanded { width: 100%; min-width: min(240px, 100%); flex: 1 1 240px; }
  .search-toggle { width: 44px; height: 44px; min-width: 44px; }
  .search-box input[type="search"], .search-box.is-expanded input[type="search"] {
    height: 42px; min-height: 42px; line-height: 42px; font-size: 16px;
  }
  /* seg 筛选按钮组：撑满宽度，按钮均分 */
  .seg {
    display: flex; width: 100%; flex-wrap: wrap; gap: 2px;
    background: var(--panel); padding: 2px;
  }
  .seg :where(a, button) {
    flex: 0 0 auto; padding: 8px 10px; font-size: 12.5px; min-height: 44px;
    border-radius: var(--r-sm); border: 0; background: transparent;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .seg :where(a, button).on { background: var(--paper); color: var(--ink); font-weight: 600; }
  /* 筛选保持一条紧凑轨：常见的三个下拉可在 390px 内均分，更多项再横向滚动。
     旧版每个下拉独占一行，商机页首屏有一半都被筛选器吃掉。 */
  .page-toolbar .center { flex-wrap: nowrap; overflow: hidden; }
  .oppfilter {
    width: 100%; flex-direction: row; align-items: center; flex-wrap: nowrap; gap: 6px;
    overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
    padding: 1px 0 3px;
  }
  .oppfilter::-webkit-scrollbar { display: none; }
  .oppfilter select {
    width: auto; min-width: 108px; min-height: 44px; flex: 1 0 108px; font-size: 13px;
  }
  .filter-clear {
    flex: 0 0 auto; align-self: center; min-height: 44px; white-space: nowrap;
    display: inline-flex; align-items: center;
  }
  /* 卡片内联 padding 覆盖 */
  .card[style*="padding:6px 22px"] {
    padding: 12px 14px !important;
  }
}

/* ---- 底部导航栏 ---- */
.mobile-tabs {
  display: none;
  position: fixed; inset-block-end: 0; inset-inline: 0; z-index: 100;
  height: 52px; background: var(--paper); border-top: 1px solid var(--line);
  justify-content: flex-start; align-items: center; overflow-x: auto; overflow-y: hidden;
  overscroll-behavior-inline: contain; scroll-snap-type: x proximity; scrollbar-width: none;
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.mobile-tabs::-webkit-scrollbar { display: none; }
/* 11 个入口共 808px，375px 视口只露得出 5 个，而滚动条是隐藏的——不给边缘渐变，
   后面 6 个（渠道/竞品库/待办/统计/账号/更新）用户根本不知道存在。渐变只在该侧
   还有内容时出现，滚到头就收掉，避免长期挂一条假边框。 */
.mobile-tabs[data-overflow-end="true"] {
  mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent 100%);
}
.mobile-tabs[data-overflow-start="true"][data-overflow-end="true"] {
  mask-image: linear-gradient(to right, transparent 0, #000 32px,
                              #000 calc(100% - 32px), transparent 100%);
}
.mobile-tabs[data-overflow-start="true"][data-overflow-end="false"] {
  mask-image: linear-gradient(to right, transparent 0, #000 32px);
}
[dir="rtl"] .mobile-tabs[data-overflow-end="true"] {
  mask-image: linear-gradient(to left, #000 calc(100% - 32px), transparent 100%);
}
@media (max-width: 768px) {
  .mobile-tabs { display: flex; }
}
.mobile-tabs .tab {
  display: flex; flex: 0 0 72px; flex-direction: column; align-items: center; gap: 2px;
  padding: 4px 6px; min-width: 44px; min-height: 44px; justify-content: center;
  color: var(--ink-2); text-decoration: none; font-size: 12px; line-height: 1.2;
  border-radius: var(--r-sm); transition: color var(--t-fast) var(--ease);
  scroll-snap-align: center;
}
.mobile-tabs .tab svg { width: 20px; height: 20px; }
.mobile-tabs .tab.on { color: var(--blue); font-weight: 600; }

/* ---- 卡片通用：手机端收紧内边距 ---- */
@media (max-width: 768px) {
  .card { padding: 16px; border-radius: var(--r-md); }
  .card + .card { margin-top: 8px; }
  /* 客户卡因为内含多个链接只能是 <article>，但它和同排三张 .linkcard 是同一种
     指标卡，内边距必须同源，否则同一个 grid 里第四张单独缩进。 */
  .linkcard, .dashboard-customer-card { padding: 12px 14px; }
}

/* ---- 详情页：双栏 → 单栏 ---- */
@media (max-width: 768px) {
  .grid.detail { grid-template-columns: 1fr; }
  .grid.cols-2 { grid-template-columns: 1fr; }
  .grid.cols-4 { grid-template-columns: 1fr; }
  .grid.detail > .stack { gap: 4px; }
}

/* ---- 表单容器：全屏化 ---- */
@media (max-width: 768px) {
  .panel {
    inset-block: 0; inset-inline-end: 0; width: 100vw; max-width: none;
    border-radius: 0; transform: translateX(var(--overlay-offscreen, 100%));
  }
  dialog.modal {
    inset-block-start: auto; inset-block-end: 0; inset-inline: 0; width: 100vw; max-width: none;
    margin: 0; border-radius: var(--r-lg) var(--r-lg) 0 0;
    max-height: 90vh; transform: translateY(0);
  }
  .drawer {
    inset-block: 0; inset-inline-end: 0; width: 100vw; max-width: none;
    border-radius: 0;
  }
  .composer { padding: 12px; border-radius: 0; }
  .frow { grid-template-columns: 1fr; }
}

/* ---- 表单控件：适配手机触控 ---- */
@media (max-width: 768px) {
  input, select, textarea { font-size: 16px; }  /* 防 iOS 自动缩放 */
  .field label { font-size: 13px; }
  .btn { min-height: 44px; padding: 10px 16px; font-size: 14px; }
  .btn.sm { min-height: 44px; padding: 6px 12px; font-size: 13px; }
  .seg { flex-wrap: wrap; }
  .seg button { padding: 8px 12px; font-size: 13px; min-height: 44px; }
}

/* ---- 响应式 DataList：同一份语义 DOM，桌面是表格、移动端原地重排为卡片 ---- */
@media (max-width: 768px) {
  /* search 等尚未迁移的非核心页保留旧卡片兜底；responsive-list 绝不被隐藏。 */
  table.ledger:not(.responsive-list) { display: none; }
  .ledger-cards { display: flex; flex-direction: column; gap: 8px; }

  .card:has(> table.ledger.responsive-list) { overflow: visible; padding: 0 !important; background: transparent; border: 0; box-shadow: none; }
  table.ledger.responsive-list { display: block; min-width: 0 !important; width: 100%; table-layout: auto; }
  table.ledger.responsive-list colgroup,
  table.ledger.responsive-list thead { display: none; }
  table.ledger.responsive-list tbody { display: grid; gap: 0; }
  table.ledger.responsive-list tbody tr {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 16px;
    padding: 12px 0; background: var(--paper); border: 0;
    border-bottom: 1px solid var(--line); border-radius: 0; box-shadow: none;
  }
  table.ledger.responsive-list tbody tr:hover { background: var(--hover); border-color: var(--line); }
  table.ledger.responsive-list tbody td,
  table.ledger.responsive-list tbody td:first-child {
    position: static; display: flex; align-items: flex-start; justify-content: flex-start; gap: 8px;
    width: auto; min-width: 0; height: auto; padding: 0; border: 0; background: transparent;
    color: var(--ink-2); font-size: 12.5px; line-height: 1.5; text-align: left;
    white-space: normal; overflow: visible; text-overflow: clip;
    /* 卡片态解除了 nowrap，长 URL / 编号就必须能断行，否则卡片被顶宽、整页横滚。 */
    min-width: 0; overflow-wrap: anywhere;
  }
  table.ledger.responsive-list tbody td::before {
    content: attr(data-label); flex: 0 0 auto; color: var(--ink-2); font-size: 12px; font-family: var(--sans);
  }
  table.ledger.responsive-list tbody td[data-primary] {
    order: -1; grid-column: 1 / -1; justify-content: flex-start; color: var(--ink);
    font-size: 14px; font-weight: 600; text-align: left;
  }
  table.ledger.responsive-list tbody td[data-primary]::before { display: none; }
  table.ledger.responsive-list tbody td[data-wide] {
    grid-column: 1 / -1; justify-content: flex-start; text-align: left;
  }
  table.ledger.responsive-list tbody td[data-wide]::before { min-width: 52px; }
  table.ledger.responsive-list tbody td.cell-flex { display: flex; justify-content: flex-start; }
  table.ledger.responsive-list tbody td.cell-flex > .nm { flex: 0 1 auto; }
}
@media (min-width: 640px) and (max-width: 768px) {
  table.ledger.responsive-list tbody tr {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
@media (min-width: 769px) {
  .ledger-cards { display: none; }
}
/* 卡片列表单条样式 */
.ledger-cards .lc {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 12px 14px; display: flex; flex-direction: column; gap: 6px;
  text-decoration: none; color: var(--ink); transition: border-color var(--t-fast) var(--ease);
}
.ledger-cards .lc:active { border-color: var(--blue); }
.ledger-cards .lc .lc-title {
  font-size: 14px; font-weight: 600; line-height: 1.4;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ledger-cards .lc .lc-meta {
  font-size: 12px; color: var(--ink-2); line-height: 1.5;
  display: flex; flex-wrap: wrap; gap: 4px 12px;
}
.ledger-cards .lc .lc-body { font-size: 13px; line-height: 1.6; color: var(--ink-2); }
.ledger-cards .lc .lc-foot { display: flex; justify-content: space-between; gap: 12px; color: var(--ink-2); font-size: 12px; }
.ledger-cards .lc .lc-code {
  font-family: var(--mono); font-size: 12px; color: var(--ink-2);
}

.interactive-row { cursor: pointer; }
.interactive-row:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* ---- 独立页面：登录 ---- */
@media (max-width: 768px) {
  .auth {
    width: 100%; max-width: 100%; border-radius: 0; padding: 32px 24px;
    min-height: 100vh; justify-content: flex-start; padding-top: 60px;
  }
  .auth .logo { width: 48px; height: 48px; }
  .auth .logo > div > span { width: 6px; height: 12px; }
  .auth h1 { font-size: 20px; }
}

/* ---- 独立页面：日报聚焦 ---- */
@media (max-width: 768px) {
  .focus-grid { grid-template-columns: 1fr; }
}

/* ---- 商机看板：单列 ---- */
@media (max-width: 768px) {
  /* 1fr 的隐含最小值是 auto，中文长句会按 min-content 撑宽整列；显式归零并命中真实的 .col。 */
  .board { grid-template-columns: minmax(0, 1fr); }
  .board .col { min-width: 0; }
}

/* ---- 触控优化：hover 只在有 hover 能力的设备上生效 ---- */
@media (hover: hover) {
  .btn.danger:hover { background: #C0392B; color: #fff; }
  .nav:hover .lab { color: var(--ink); }
  .seg button:hover { background: var(--hover); }
  .lc:hover { border-color: var(--blue); }
  .tool-tab:hover { color: var(--ink); }
}

/* ---- 触控目标：最小 44px ---- */
@media (pointer: coarse) {
  .nav { min-height: 44px; }
  .dclose { min-width: 44px; min-height: 44px; }
  .plus-btn { min-width: 44px; min-height: 44px; }
  .btn { min-height: 44px; }
  .btn.sm { min-height: 44px; }
  .tab { min-height: 44px; }
  /* 只给正文里的裸链接加触控留白。写成无差别的 `a[href]` 时，它的特异性(0,1,1)
     压过所有组件类(0,1,0)，把 .linkcard 这类「整块可点」的卡片内边距压成 4px 0
     ——工作台四张指标卡里三张是 <a>、一张是 <article>，于是只有那一张缩进 16px，
     手机端肉眼可见错位。上面的 .btn/.nav/.tab 已各自有 44px 最小高度，不靠这条。 */
  a[href]:not([class]) { padding: 4px 0; }
}

/* ---------- 商机 C01 / C02 工作区（Aham UI v7.0.2 · 网页轨） ---------- */
.opp-workspace-tabs {
  display: flex; gap: 24px; align-items: center; margin-bottom: 24px;
  border-bottom: 1px solid var(--line); overflow-x: auto;
}
.opp-workspace-tabs a {
  display: inline-flex; align-items: center; gap: 8px; min-height: 40px;
  color: var(--ink-2); font-size: 13px; white-space: nowrap; position: relative;
}
.opp-workspace-tabs a:hover { color: var(--ink); }
.opp-workspace-tabs a.on { color: var(--ink); font-weight: 600; }
.opp-workspace-tabs a.on::after {
  content: ""; position: absolute; inset-inline: 0; bottom: -1px; height: 2px; background: var(--blue);
}
.tab-count { color: var(--ink-2); font-size: 12px; font-weight: 400; }

.workspace-metrics {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; margin-bottom: 24px;
}
/* 分层靠底色，不靠描边：--paper 与页面同为 #fff，块就是隐形的；换 --panel 才看得见边界。
   （Aham v7 契约：卡片无 border 无 shadow，所以不能用描边解决。）
   三项纵向左对齐——原来 grid 1fr auto + text-align:end 把数值和它的说明顶到块两端，
   1920 下隔了大半个块宽，读的人得来回扫。 */
.workspace-metric {
  min-width: 0; background: var(--panel); border-radius: var(--r-lg); padding: 14px 16px;
  display: flex; flex-direction: column; gap: 2px;
}
.workspace-metric .metric-label { color: var(--ink-2); font-size: 12px; }
.workspace-metric strong { font-size: 26px; line-height: 1.2; font-weight: 600; font-variant-numeric: tabular-nums; }
.workspace-metric > span:last-child { color: var(--ink-3); font-size: 12px; }

.strategy-layout { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 16px; align-items: start; }
.strategy-form { padding: 0; overflow: hidden; }
.strategy-section { padding: 24px; }
.strategy-section + .strategy-section { border-top: 1px solid var(--line); }
.strategy-section-head { display: flex; justify-content: space-between; gap: 24px; margin-bottom: 24px; }
.strategy-section-head > div { display: flex; gap: 12px; align-items: baseline; }
.strategy-section-head h2 { font-size: 17px; line-height: 1.5; font-weight: 600; }
.strategy-section-head p { max-width: 38ch; color: var(--ink-2); font-size: 12px; text-align: end; }
.section-index { color: var(--ink-2); font-size: 12px; }
.strategy-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.strategy-fields label { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.strategy-fields label > span { color: var(--ink-2); font-size: 12px; font-weight: 500; }
.strategy-fields .wide { grid-column: 1 / -1; }
.strategy-fields textarea, .strategy-fields input, .strategy-fields select,
.response-filters input, .response-filters select {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--paper);
  color: var(--ink); font: inherit; font-size: 14px; padding: 8px 12px; outline: none;
}
.strategy-fields textarea { min-height: 104px; line-height: var(--leading-cjk); resize: vertical; }
.strategy-fields input, .strategy-fields select { min-height: 36px; }
.strategy-fields textarea:focus, .strategy-fields input:focus, .strategy-fields select:focus,
.response-filters input:focus, .response-filters select:focus {
  border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51,110,232,.20);
}
/* 早就写好、直到这次才被模板接上的底部操作条。表单卡自带 24px padding，
   操作条要贴到卡的左右边缘，所以用负 margin 把 padding 顶回去。 */
.strategy-actions {
  display: flex; align-items: center; justify-content: flex-end; gap: 16px;
  margin: 20px -24px -24px; padding: 14px 24px;
  border-top: 1px solid var(--line); background: var(--panel);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}
.strategy-actions .save-note { margin-inline-end: auto; color: var(--ink-2); font-size: 12px; }
.strategy-aside { display: flex; flex-direction: column; gap: 16px; position: sticky; top: 16px; }
.workspace-aside-card { padding: 16px; }
.plain-list, .rule-list { list-style: none; display: grid; gap: 12px; }
.plain-list li, .rule-list li { font-size: 13px; line-height: 1.55; color: var(--ink-2); }
.rule-list li { padding-inline-start: 16px; position: relative; }
.rule-list li::before { content: "•"; position: absolute; inset-inline-start: 0; color: var(--ink-3); }
.quiet-state { padding-block: 8px; }

.strategy-subnav {
  display: flex; gap: 20px; align-items: center; margin: -8px 0 24px;
  border-bottom: 1px solid var(--line); overflow-x: auto;
}
.strategy-subnav a { min-height: 40px; display: inline-flex; align-items: center; color: var(--ink-2); font-size: 13px; white-space: nowrap; position: relative; }
.strategy-subnav a.on { color: var(--ink); font-weight: 600; }
.strategy-subnav a.on::after { content: ""; position: absolute; inset-inline: 0; bottom: -1px; height: 2px; background: var(--blue); }
.strategy-overview-grid { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: 16px; margin-bottom: 16px; }
.strategy-module-card { display: block; min-width: 0; padding: 15px 16px; background: var(--panel); border-radius: var(--r-lg); color: var(--ink); }
.strategy-module-card:hover { background: var(--panel-strong); }
/* 状态是「靠右的徽标」，标题不是「靠左的孤儿」：用 margin auto 只把徽标推开，
   标题与它的圆点仍紧挨。原来整行 space-between，1920 下标题到状态隔了 152px。 */
.module-card-head { display: flex; align-items: center; gap: 8px; }
.module-card-head .module-state {
  margin-inline-start: auto; font-size: 12px; white-space: nowrap;
  padding: 1px 7px; border-radius: 3px; color: var(--ink-2); background: var(--paper);
}
.module-card-head .module-state.is-ready { color: var(--ok); }
.module-card-head .module-state.is-todo { color: var(--warn); }
/* 摘要是这张卡唯一的信息量，2 行截断经常把结论切掉；放到 3 行。 */
.strategy-module-card p { margin-top: 9px; color: var(--ink-2); font-size: 13px; line-height: 1.6; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.strategy-summary-columns { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }

/* 新建商机抽屉里的方式切换。用页面既有的 .seg 分段控件，不另造一套外观。 */
/* 模式开关并进标题行：抽屉只有 480px，再单起一行正文就被挤下去一截。
   标题占弹性宽、开关贴右、关闭按钮在最右。 */
.panel .phead .seg.opp-mode { margin: 0; flex: none; }
.panel .phead .seg.opp-mode button { padding: 5px 11px; font-size: 12.5px; }
.pick .task-due { display: block; color: var(--ink-3); font-size: 12px; margin-top: 2px; }

/* 决策链与策略条目走台账同一套 .aham-table：列宽用 colgroup 定，窄屏自动降级 DataList。
   确定性内容列给 min-width，弹性列（姓名/标准）自适应——与线索、客户台账同三原则。 */
/* table.ledger 的 min-width:920px 是给整页台账定的；这两张表长在详情卡里（主栏约 760px），
   照搬 920 会为 4 列内容凭空造出横滚。列宽仍由下面的 colgroup 兜底，真放不下才滚。 */
table.ledger.chain-table { min-width: 620px; }
table.ledger.item-table { min-width: 560px; }
.chain-table .chain-who { display: flex; align-items: center; gap: 9px; min-width: 0; }
.chain-who-text { min-width: 0; }
.chain-who-text b { display: block; font-weight: 500; }
.chain-who-text small { display: block; color: var(--ink-3); font-size: 12px; line-height: 1.4; }
.chain-col-who { min-width: 180px; }
.chain-col-role, .chain-col-support, .chain-col-influence { min-width: 76px; }
.chain-col-tel, .chain-col-wechat { min-width: 116px; }
.chain-col-fu { min-width: 104px; }
.chain-col-source { min-width: 84px; }
.chain-col-state { min-width: 88px; }
.chain-col-reason { min-width: 180px; }
.chain-table tr.chain-need td { padding-top: 0; border-top: 0; }
.chain-need span { display: block; color: var(--ink-2); font-size: 12px; line-height: 1.55; }
.chain-need i { color: var(--ink-3); font-style: normal; margin-inline-end: 6px; }
.item-col-code { min-width: 84px; }
.item-col-title { min-width: 240px; }
.item-col-weight { min-width: 64px; }
.item-col-state { min-width: 92px; }
.item-col-act { min-width: 56px; }
.item-table .item-detail { display: block; color: var(--ink-3); font-size: 12px; line-height: 1.5; margin-top: 2px; }
.item-table .item-act form { margin: 0; }
.summary-primary { margin-bottom: 12px; font-size: 15px; line-height: 1.6; }
.strategy-page-form { padding: 24px; }
.strategy-page-head, .competition-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; margin-bottom: 24px; }
.strategy-page-head h2, .competition-head h2 { margin-top: 2px; font-size: 20px; font-weight: 600; }
.strategy-page-head p, .competition-head p { margin-top: 4px; color: var(--ink-2); font-size: 13px; }
.head-actions, .searchbar { display: flex; align-items: center; gap: 8px; }
.searchbar input { width: min(320px,55vw); min-height: 36px; padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--paper); }
.cell-sub { margin-top: 3px; color: var(--ink-2); font-size: 12px; }
.competitor-library-card { padding: 6px 22px; overflow-x: auto; }
.competitor-detail-page .detail-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.competitor-detail-page .competitor-kv .item { min-width: calc(50% - 12px); }
.competitor-summary { color: var(--ink-2); font-size: 14px; line-height: var(--leading-cjk); }
.competitor-profile-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.competitor-profile-block { min-width: 0; padding: 16px; border-radius: var(--r-md); background: var(--panel); }
.competitor-profile-block .k, .reference-group .k { margin-bottom: 8px; color: var(--ink-2); font-size: 12px; font-weight: 500; }
.competitor-profile-block .v-view { color: var(--ink-2); font-size: 13px; line-height: 1.7; }
.competitor-profile-block textarea { min-height: 112px; resize: vertical; }
.reference-group + .reference-group { margin-top: 20px; padding-top: 20px; border-top: 1px solid var(--line); }
.reference-group > div:not(.k), .reference-group li { color: var(--ink-2); font-size: 13px; line-height: 1.6; }
.competitor-usage-list { border-top: 1px solid var(--line); }
.competitor-usage-row { display: flex; justify-content: space-between; align-items: center; gap: 16px; min-height: 64px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.competitor-usage-row:last-child { border-bottom: 0; }
.competitor-usage-row:hover { background: var(--hover); }
.competitor-usage-row > div { min-width: 0; display: grid; gap: 2px; }
.competitor-usage-row b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.competitor-usage-row div span { color: var(--ink-2); font-size: 12px; }
.compact-empty { padding: 20px 0; }
.competitor-boundary-note p { margin-top: 10px; color: var(--ink-2); font-size: 13px; line-height: 1.7; }
.text-link { color: var(--blue); }
.strategy-fields.one-col { grid-template-columns: 1fr; }
.causal-flow { display: flex; align-items: center; gap: 8px; margin-bottom: 24px; color: var(--ink-2); font-size: 12px; }
.causal-flow span { padding: 6px 10px; background: var(--panel); border-radius: var(--r-sm); }
.causal-flow i { color: var(--ink-2); font-style: normal; }
.buying-layout { display: grid; grid-template-columns: 1fr; gap: 16px; align-items: start; }
.decision-table { border-top: 1px solid var(--line); }
.decision-row { display: grid; grid-template-columns: minmax(160px,1.4fr) repeat(3,minmax(82px,.65fr)) minmax(76px,.6fr); gap: 12px; align-items: center; min-height: 52px; padding: 8px 0; border-bottom: 1px solid var(--line); color: var(--ink); font-size: 12px; }
.decision-row > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.decision-row > div span, .decision-row .span-2 { color: var(--ink-2); }
.decision-row .span-2 { grid-column: span 2; }
.flags.compact { margin-top: 16px; }
.competition-add { margin-bottom: 16px; }
.migration-note { margin-bottom: 16px; padding: 12px 16px; background: var(--panel); border-radius: var(--r-md); }
.migration-note p { margin-top: 6px; color: var(--ink-2); font-size: 13px; }
.competition-layout { display: grid; grid-template-columns: 280px minmax(0,1fr); gap: 16px; align-items: start; }
.competition-list {
  min-width: 0; background: var(--paper); border-radius: var(--r-lg); padding: 8px;
  position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow-y: auto;
}
.competition-item { display: grid; grid-template-columns: minmax(0,1fr) auto; gap: 4px 8px; min-height: 64px; padding: 10px 12px; border-radius: var(--r-md); color: var(--ink); }
.competition-item + .competition-item { margin-top: 2px; }
.competition-item:hover, .competition-item.on { background: var(--line); }
.competition-item > div { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.competition-item b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.competition-item div span, .competition-item small { color: var(--ink-2); font-size: 12px; }
.competition-item small { grid-column: 2; text-align: end; }
.competition-detail { display: grid; gap: 16px; min-width: 0; }
.competition-contacts { padding: 16px; }
.inline-relationship-form { display: flex; gap: 8px; align-items: end; flex-wrap: wrap; margin-top: 16px; }
.inline-relationship-form label { display: grid; gap: 5px; color: var(--ink-2); font-size: 12px; }
.inline-relationship-form label.grow { flex: 1 1 220px; }
.inline-relationship-form input, .inline-relationship-form select { min-width: 128px; min-height: 36px; padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--paper); color: var(--ink); }
.inline-relationship-form .grow input { width: 100%; }
.archive-inline { display: flex; justify-content: flex-end; }
.quiet { color: var(--ink-2); font-size: 12px; }
.structured-block, .comparison-block { padding: 16px; min-width: 0; }
.structured-block .block-head p, .comparison-block .block-head p { margin-top: 3px; color: var(--ink-2); font-size: 12px; }
.structured-list, .process-list, .comparison-list { border-top: 1px solid var(--line); }
.structured-row { display: grid; grid-template-columns: 78px minmax(180px,1fr) 72px 110px auto; gap: 12px; align-items: center; min-height: 52px; border-bottom: 1px solid var(--line); font-size: 12px; }
.structured-row > div, .process-row > div { min-width: 0; display: grid; gap: 2px; }
.structured-row small, .process-row small { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.text-action { border: 0; background: none; color: var(--ink-2); font: inherit; font-size: 12px; }
.text-action:hover { color: var(--ink); }
.inline-item-form { display: flex; gap: 8px; align-items: end; flex-wrap: wrap; padding-top: 16px; }
.inline-item-form label { display: grid; gap: 5px; min-width: 96px; color: var(--ink-2); font-size: 12px; }
.inline-item-form label.grow { flex: 1 1 220px; }
.inline-item-form input, .inline-item-form select { width: 100%; min-height: 36px; padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--paper); color: var(--ink); }
.compact-note { margin: 12px 0 0; }
.process-grid { display: grid; grid-template-columns: 1fr; gap: 16px; margin-top: 16px; }
.process-row { display: grid; grid-template-columns: 32px minmax(0,1fr) 84px; gap: 12px; align-items: center; min-height: 52px; border-bottom: 1px solid var(--line); font-size: 12px; }
.sequence { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; background: var(--panel); color: var(--ink-2); font: 12px var(--mono); }
.comparison-row { display: grid; grid-template-columns: minmax(170px,1.2fr) 112px 112px minmax(180px,1fr) auto; gap: 8px; align-items: center; min-height: 56px; border-bottom: 1px solid var(--line); }
.comparison-row > div { display: grid; gap: 2px; }
.comparison-row small { color: var(--ink-2); font-size: 12px; }
.comparison-row input, .comparison-row select { width: 100%; min-height: 36px; padding: 7px 9px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--paper); color: var(--ink); font-size: 12px; }
.plan-grid { display: grid; gap: 16px; }
.page-anchor-nav {
  display: flex; align-items: center; gap: 4px; margin-bottom: 16px; padding: 4px;
  border-radius: var(--r-md); background: var(--paper); overflow-x: auto;
  position: sticky; top: 8px; z-index: 2;
}
.page-anchor-nav a { padding: 6px 12px; border-radius: var(--r-sm); color: var(--ink-2); font-size: 12px; white-space: nowrap; }
.page-anchor-nav a:hover, .page-anchor-nav a:focus-visible { background: var(--panel); color: var(--ink); }
.plan-grid > [id] { scroll-margin-top: 64px; }
.plan-row { grid-template-columns: 78px minmax(220px,1fr) 110px; }
.action-row, .risk-row { grid-template-columns: 90px minmax(220px,1fr) 92px; }
.qualification-card { margin-top: 0; }

.response-toolbar {
  display: flex; justify-content: space-between; align-items: center; gap: 16px; margin-bottom: 16px;
}
.response-filters { display: flex; flex: 1; gap: 8px; align-items: center; flex-wrap: wrap; }
.response-filters input { width: min(320px, 100%); min-height: 36px; }
.response-filters select { width: auto; min-width: 144px; min-height: 36px; }
.response-table-card { padding: 0; overflow: hidden; }
.table-scroll { overflow-x: auto; }
.response-table { width: 100%; min-width: 1080px; border-collapse: collapse; table-layout: auto; }
.response-table th, .response-table td {
  height: 44px; padding: 8px 16px; border-bottom: 1px solid var(--line); text-align: start; vertical-align: top;
}
.response-table th { color: var(--ink-2); font-size: 13px; font-weight: 500; white-space: nowrap; }
.response-table td { color: var(--ink); font-size: 13px; }
.response-table tr:last-child td { border-bottom: none; }
.response-table tbody tr:hover { background: var(--hover); }
.response-table .wrap-cell { min-width: 240px; max-width: 360px; white-space: normal; line-height: 1.55; }
.response-table .response-statement { font-weight: 500; }
.response-table .cell-meta { display: block; margin-top: 4px; color: var(--ink-2); font-size: 12px; }
.table-link { border: none; background: none; color: var(--ink); font-family: var(--mono); font-size: 12px; }
.table-link:hover { color: var(--blue); }
.response-empty { padding: 64px 24px; text-align: center; }
.response-empty h2 { font-size: 17px; font-weight: 600; }
.response-empty p { margin: 8px auto 16px; max-width: 52ch; color: var(--ink-2); }
.response-panel { width: 640px; max-width: 94vw; }
.response-panel .form-section { padding-block: 8px 24px; }
.response-panel .form-section + .form-section { padding-top: 24px; border-top: 1px solid var(--line); }
.response-panel .form-section h4 { margin-bottom: 16px; font-size: 14px; font-weight: 600; }
.response-panel textarea { min-height: 80px; line-height: var(--leading-cjk); }
.response-panel select[multiple] { min-height: 112px; }
.response-panel .pfoot .spacer { flex: 1; }

/* 版本更新中心：入口留在全局头部，正文使用完整内容区，不挤进侧栏或抽屉。 */
.updates-link {
  position: relative; display: inline-flex; align-items: center; gap: 7px; min-height: 34px;
  padding: 0 10px; border-radius: var(--r-md); color: var(--ink-2); font-size: 12px; white-space: nowrap;
}
.updates-link:hover, .updates-link.on { background: var(--panel); color: var(--ink); }
.updates-link svg { width: 17px; height: 17px; stroke-width: 1.7; }
.updates-badge {
  min-width: 17px; height: 17px; padding: 0 5px; display: inline-grid; place-items: center;
  border-radius: 9px; background: var(--blue); color: #fff; font: 12px/1 var(--mono);
}
.updates-page, .update-detail { width: min(960px, 100%); margin: 0 auto; }
.updates-intro {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 24px;
  margin-bottom: 18px; padding: 28px 30px; border-radius: var(--r-lg); background: var(--paper);
}
.updates-kicker, .release-admin-box .eyebrow { color: var(--blue); font: 12px var(--mono); letter-spacing: .08em; }
.updates-intro h2 { margin-top: 8px; font-size: 22px; font-weight: 600; }
.updates-intro p { margin-top: 8px; color: var(--ink-2); font-size: 13px; line-height: 1.65; }
.updates-unread-summary { padding: 7px 10px; border-radius: 999px; background: var(--blue-50); color: var(--blue); font-size: 12px; white-space: nowrap; }
.release-list { display: grid; gap: 10px; }
.release-card {
  position: relative; display: grid; grid-template-columns: 18px minmax(0,1fr) 24px; gap: 14px;
  padding: 22px 24px; border-radius: var(--r-lg); background: var(--paper); color: var(--ink);
}
.release-card:hover { background: var(--hover); }
.release-card.unread { box-shadow: inset 3px 0 0 var(--blue); }
.release-marker { display: flex; justify-content: center; padding-top: 7px; }
.release-marker span { width: 8px; height: 8px; border: 2px solid var(--ink-4); border-radius: 50%; background: var(--paper); }
.release-card.unread .release-marker span { border-color: var(--blue); background: var(--blue); }
.release-card-body { min-width: 0; }
.release-meta { display: flex; align-items: center; gap: 9px; color: var(--ink-2); font-size: 12px; }
.release-version { color: var(--blue); font: 12px var(--mono); }
.release-new { padding: 2px 6px; border-radius: 8px; background: var(--blue); color: #fff; font-size: 12px; }
.release-card h3 { margin-top: 8px; font-size: 16px; font-weight: 600; }
.release-card p { margin-top: 7px; color: var(--ink-2); font-size: 13px; line-height: 1.65; }
.release-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 14px; }
.release-tags span { padding: 4px 8px; border-radius: var(--r-sm); background: var(--panel); color: var(--ink-2); font-size: 12px; }
.release-tags span[data-release-type="added"] { background: var(--blue-50); color: var(--blue); }
.release-delivery-line { margin-top: 12px; color: var(--ink-2); font-size: 12px; }
.release-arrow { align-self: center; width: 18px; height: 18px; color: var(--ink-3); stroke-width: 1.7; }
.update-detail { display: grid; gap: 16px; }
.update-detail-hero { padding: 34px 38px; border-radius: var(--r-lg); background: var(--paper); }
.update-detail-hero h2 { margin-top: 14px; font-size: 26px; font-weight: 600; }
.update-detail-hero > p { margin-top: 12px; max-width: 720px; color: var(--ink-2); font-size: 14px; line-height: 1.8; }
.release-read-state { padding: 2px 7px; border-radius: 8px; background: var(--panel); }
.update-sections { display: grid; gap: 12px; }
.update-section { padding: 24px 30px; border-radius: var(--r-lg); background: var(--paper); }
.update-section-title { display: flex; align-items: center; gap: 10px; }
.update-section-title h3 { font-size: 15px; font-weight: 600; }
.update-section-title > span:last-child { color: var(--ink-2); font-size: 12px; }
.update-section-icon { width: 9px; height: 9px; border-radius: 50%; background: var(--ink-3); }
.update-section[data-release-type="added"] .update-section-icon { background: var(--blue); }
.update-section[data-release-type="fixed"] .update-section-icon { background: #3a9b72; }
.update-section[data-release-type="security"] .update-section-icon { background: #d08a2c; }
.update-section ul { display: grid; gap: 11px; margin: 18px 0 0; padding: 0; list-style: none; }
.update-section li { position: relative; padding-left: 18px; color: var(--ink-2); font-size: 13px; line-height: 1.7; }
.update-section li::before { content: ""; position: absolute; left: 1px; top: .72em; width: 5px; height: 1px; background: var(--ink-3); }
.release-admin-box {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 22px 26px; border-radius: var(--r-lg); background: var(--paper);
}
.release-admin-box strong { display: block; margin-top: 6px; font-size: 14px; }
.release-admin-box p { margin-top: 5px; color: var(--ink-2); font-size: 12px; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

@media (max-width: 1024px) {
  .workspace-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .strategy-layout { grid-template-columns: 1fr; }
  .strategy-aside { position: static; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .strategy-overview-grid { grid-template-columns: repeat(2,minmax(0,1fr)); }
  .comparison-row { grid-template-columns: 1fr 1fr; padding: 10px 0; }
  .comparison-row > div, .comparison-row input { grid-column: 1 / -1; }
}
@media (max-width: 768px) {
  .opp-workspace-tabs { gap: 16px; margin-bottom: 16px; }
  .workspace-metrics { grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 16px; }
  .workspace-metric { padding: 12px; grid-template-columns: 1fr; }
  .workspace-metric strong { font-size: 20px; }
  .workspace-metric > span:last-child { text-align: start; }
  .strategy-section { padding: 16px; }
  .strategy-section-head { display: block; margin-bottom: 16px; }
  .strategy-section-head p { margin-top: 4px; text-align: start; }
  .strategy-fields { grid-template-columns: 1fr; }
  .strategy-fields .wide { grid-column: auto; }
  .strategy-actions { position: sticky; bottom: 52px; padding: 12px 16px; }
  .strategy-actions .save-note { display: none; }
  .strategy-aside { grid-template-columns: 1fr; }
  .strategy-summary-columns, .strategy-overview-grid, .competition-layout { grid-template-columns: 1fr; }
  .strategy-page-form { padding: 16px; }
  .strategy-page-head, .competition-head { align-items: stretch; flex-direction: column; }
  .strategy-page-head .btn, .competition-head .btn { width: 100%; }
  .competition-list { display: flex; overflow-x: auto; overflow-y: hidden; position: static; max-height: none; }
  .competition-item { min-width: 220px; }
  .decision-row { grid-template-columns: 1fr 1fr; }
  .structured-row, .plan-row, .action-row, .risk-row { grid-template-columns: 1fr; gap: 4px; padding: 10px 0; }
  .inline-item-form { display: grid; grid-template-columns: 1fr; }
  .inline-item-form label.grow { flex: initial; }
  .causal-flow { overflow-x: auto; }
  .response-toolbar { align-items: stretch; flex-direction: column; }
  .response-filters { display: grid; grid-template-columns: 1fr; }
  .response-filters input, .response-filters select { width: 100%; min-height: 44px; }
  .response-toolbar > .btn { width: 100%; }
  .response-panel { width: 100vw; max-width: none; }
  .response-panel .frow { grid-template-columns: 1fr; }
  .competitor-profile-grid { grid-template-columns: 1fr; }
  .competitor-detail-page .competitor-kv .item { width: 100%; min-width: 100%; }
  .updates-link { width: 36px; padding: 0; justify-content: center; }
  .updates-link-label { display: none; }
  .updates-badge { position: absolute; top: -3px; right: -5px; }
  .updates-intro { align-items: flex-start; flex-direction: column; padding: 22px 20px; }
  .updates-intro h2 { font-size: 19px; }
  .release-card { grid-template-columns: 14px minmax(0,1fr); padding: 18px 16px; }
  .release-arrow { display: none; }
  .update-detail-hero { padding: 24px 20px; }
  .update-detail-hero h2 { font-size: 22px; }
  .update-section { padding: 20px; }
  .release-admin-box { align-items: stretch; flex-direction: column; }
  .release-admin-box .btn { width: 100%; }
}

/* ================================================================
   2026-08 真机审计修复
   只在既有 Aham token 上收口交互密度；不引入新颜色、渐变或静态阴影。
   ================================================================ */

/* 原生 select 在 Chromium / 企业微信中的箭头和内边距不一致，统一为同一套扁平控件。 */
.modal .field select, .panel .field select, .composer select,
.inline-form .v-edit select, .strategy-fields select,
.inline-item-form select, .inline-relationship-form select,
.comparison-row select, .response-filters select {
  appearance: none; -webkit-appearance: none;
  padding-inline-end: 34px;
  background-image: var(--select-chevron);
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 12px 12px;
}
:where(input, select, textarea)::placeholder { color: var(--ink-3); opacity: 1; }
:where(input, select, textarea):focus-visible,
.menu-pop :where(a, button):focus-visible,
.mobile-filter-trigger:focus-visible {
  outline: none; border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(51,110,232,.15);
}

/* 顶部“⋯”菜单与表单下拉使用一致的圆角、边界和触控节奏。 */
.menu-pop { min-width: 180px; padding: 6px; border: 1px solid var(--line); }
.menu-pop button, .menu-pop a {
  min-height: 40px; display: flex; align-items: center;
  padding: 8px 12px; color: var(--ink-2); font-size: 13px;
}
.mini { color: var(--ink-2); }

/* 负责人很多时，桌面保持原布局；移动端由 JS 折叠为一条摘要。 */
.mobile-filter-shell { display: flex; align-items: center; min-width: 0; }
.mobile-filter-trigger { display: none; }
.mobile-filter-panel { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.mobile-filter-panel[hidden] { display: none !important; }
.response-toolbar .mobile-filter-shell,
.response-toolbar .mobile-filter-panel,
.response-toolbar .response-filters { flex: 1; }

/* 红旗属于正文而不是状态 chip：允许任意长客户原话换行，不能把 C01 撑出视口。 */
.flag-line { min-width: 0; max-width: 100%; }
.flag-line .flag-copy { min-width: 0; max-width: 100%; overflow-wrap: anywhere; word-break: break-word; }
.plain-list .dot { max-width: 100%; white-space: normal; align-items: flex-start; overflow-wrap: anywhere; }
.plain-list .dot::before { margin-top: .65em; }

/* 9 列跟进台账在常用 1280 视口内完整出现，长内容仍按台账规则省略。 */
@media (min-width: 769px) {
}

/* 769–1024px 是明确的平板档，避免刚跨过手机断点就突然恢复宽页边距。 */
@media (min-width: 769px) and (max-width: 1024px) {
  .rail { width: 52px; padding-inline: 8px; }
  .nav-open .rail { width: 220px; }
  .page { padding: 20px 20px 64px; }
  .page-header { margin-bottom: 18px; flex-wrap: wrap; }
  .page-toolbar { gap: 10px; }
  table.ledger { min-width: 760px; }
  table.ledger th, table.ledger td { padding-inline: 10px; }
  .file-workspace-head, .file-workspace-tools { padding-inline: 18px; }
  .file-table { min-width: 720px; }
}

@media (min-width: 861px) and (max-width: 1024px) {
  .file-workspace-body { grid-template-columns: 220px minmax(0, 1fr); }
}

@media (max-width: 768px) {
  :root {
    --mobile-tabs-h: calc(56px + env(safe-area-inset-bottom, 0px));
    --page-pb: calc(var(--mobile-tabs-h) + 24px);
  }

  /* 刘海屏 / 圆角屏安全区；浮层打开时层级必须高于底部导航。 */
  .page {
    padding-inline-start: max(var(--page-px), env(safe-area-inset-left, 0px));
    padding-inline-end: max(var(--page-px), env(safe-area-inset-right, 0px));
    padding-block-end: var(--page-pb);
  }
  .mobile-tabs {
    height: var(--mobile-tabs-h); min-height: var(--mobile-tabs-h);
    padding: 4px max(8px, env(safe-area-inset-right, 0px))
      max(4px, env(safe-area-inset-bottom, 0px))
      max(8px, env(safe-area-inset-left, 0px));
  }
  .drawer-scrim { z-index: 140; }
  .drawer { z-index: 141; }
  .panel { z-index: 142; }
  .panel form, .drawer .dbody {
    padding-bottom: max(16px, env(safe-area-inset-bottom, 0px));
  }
  .panel .pfoot {
    bottom: -16px;
    padding-bottom: max(12px, env(safe-area-inset-bottom, 0px));
  }
  dialog.modal form { padding-bottom: max(24px, calc(16px + env(safe-area-inset-bottom, 0px))); }

  /* 列表筛选默认只占一行；展开后状态/负责人各是一条可横滑轨，不再把首屏铺满。 */
  .mobile-filter-shell { width: 100%; display: block; }
  .mobile-filter-trigger {
    width: 100%; min-height: 44px; display: grid;
    grid-template-columns: auto minmax(0, 1fr) 18px; align-items: center; gap: 10px;
    padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--r-md);
    background: var(--paper); color: var(--ink); text-align: left;
  }
  .mobile-filter-title { font-size: 13px; font-weight: 600; }
  .mobile-filter-summary {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    color: var(--ink-2); font-size: 12px;
  }
  .mobile-filter-trigger svg { width: 16px; height: 16px; color: var(--ink-3); transition: transform var(--t-fast) var(--ease); }
  .mobile-filter-trigger[aria-expanded="true"] svg { transform: rotate(180deg); }
  .mobile-filter-panel:not([hidden]) {
    display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px;
    margin-top: 8px; padding: 10px; border: 1px solid var(--line);
    border-radius: var(--r-md); background: var(--paper);
  }
  .mobile-filter-panel .seg {
    width: 100%; flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
    scrollbar-width: none; padding-bottom: 2px;
  }
  .mobile-filter-panel .seg::-webkit-scrollbar { display: none; }
  .mobile-filter-panel .seg :where(a, button) { flex: 0 0 auto; }

  /* 所有可编辑控件遵循 44px 触控目标与 16px 字号，避免企业微信/iOS 聚焦放大。 */
  .search-box { min-height: 44px; }
  :where(.dclose, .aham-icon-button, .icon-btn, .plus-btn, .nav-group-toggle) {
    inline-size: 44px; block-size: 44px; min-inline-size: 44px; min-height: 44px;
  }
  .search-box.is-expanded input,
  .oppfilter select,
  .modal .field :where(input, select, textarea),
  .panel .field :where(input, select, textarea),
  .composer :where(input, select, textarea),
  .inline-form .v-edit :where(input, select, textarea),
  .strategy-fields :where(input, select, textarea),
  .inline-item-form :where(input, select),
  .inline-relationship-form :where(input, select),
  .comparison-row :where(input, select),
  .response-filters :where(input, select),
  .file-search input {
    min-height: 44px; font-size: 16px; line-height: 1.4;
  }
  .modal .field textarea, .panel .field textarea, .composer textarea,
  .strategy-fields textarea { min-height: 96px; }
  .modal .field input, .modal .field select, .modal .field textarea,
  .panel .field input, .panel .field select, .panel .field textarea,
  .composer input, .composer select, .composer textarea,
  .inline-form .v-edit input, .inline-form .v-edit select, .inline-form .v-edit textarea {
    font-size: 16px;
  }
  .panel .frow, .modal .frow, .composer .frow { grid-template-columns: minmax(0, 1fr); }
  .panel .frow .full, .modal .frow .full, .composer .frow .full { grid-column: auto; }
  .btn, .btn.sm, .mini, .plus-btn, .dclose, .tool-tab,
  .menu-pop button, .menu-pop a, .file-folder-row,
  .page-anchor-nav a, .strategy-subnav a, .opp-workspace-tabs a,
  .backlink, .table-link {
    min-height: 44px;
  }
  .mini, .table-link { display: inline-flex; align-items: center; justify-content: center; padding: 8px 10px; }
  .menu-pop { min-width: min(220px, calc(100vw - 32px)); }
  .updates-link { width: 44px; min-width: 44px; min-height: 44px; }

  /* 销售活动指标：1+2 布局替代三个 110px 窄卡片。 */
  table.ledger.responsive-list td[data-primary] .rowlink {
    min-height: 44px; display: inline-flex; align-items: center;
  }

  /* C01 的关键文字在手机上完整换行；列表摘要不再强制单行省略。 */
  .workspace-metric {
    min-height: 56px; padding: 10px 12px;
    grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px;
  }
  .workspace-metric .metric-label { grid-column: auto; color: var(--ink-2); }
  .workspace-metric strong { font-size: 19px; }
  .workspace-metric > span:last-child { display: none; }
  .flags, .flag-line, .flag-copy { width: 100%; }
  .flag-line { align-items: flex-start; }
  .structured-row small, .process-row small {
    white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere;
  }
  .strategy-subnav { gap: 16px; overscroll-behavior-x: contain; }
  .strategy-page-head { gap: 14px; margin-bottom: 18px; }
  .page-anchor-nav { top: 0; }

  /* C02 在移动端使用同一份语义表格 DOM 原地卡片化，编辑入口置于卡片首行。 */
  .response-table-card { padding: 0; overflow: visible; background: transparent; }
  .response-table-card .table-scroll { overflow: visible; }
  .response-table { display: block; width: 100%; min-width: 0; }
  .response-table thead {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .response-table tbody { display: grid; gap: 8px; }
  .response-table tr {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px 14px;
    width: 100%; padding: 13px 14px; border: 1px solid var(--line);
    border-radius: var(--r-md); background: var(--paper);
  }
  .response-table td {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
    min-width: 0; width: auto; height: auto; padding: 0; border: 0;
    font-size: 13px; line-height: 1.5; text-align: right;
  }
  .response-table td::before {
    content: attr(data-label); flex: 0 0 auto; color: var(--ink-2); font-size: 12px;
  }
  .response-table .response-code { order: -3; justify-content: flex-start; }
  .response-table .response-code::before,
  .response-table .response-action::before { display: none; }
  .response-table .response-action { order: -3; justify-self: end; }
  .response-table .response-primary {
    order: -2; grid-column: 1 / -1; display: block; text-align: left;
    padding-block: 10px; border-block: 1px solid var(--line);
  }
  .response-table .response-primary::before {
    display: block; margin-bottom: 4px; color: var(--ink-2); font-size: 12px;
  }
  .response-table .response-impact { grid-column: 1 / -1; text-align: left; }
  .response-table .response-impact::before { min-width: 64px; }
  .response-table .wrap-cell { min-width: 0; max-width: none; white-space: normal; }
  .response-table .dot { white-space: normal; text-align: left; }

  /* 文件目录保留树语义，但限制目录高度，让第一份文件更快进入首屏。 */
  .file-workspace-head { padding: 16px; }
  .file-workspace > .composer { margin-inline: 16px; }
  .file-workspace-tools { padding: 10px 16px; }
  .file-search input { height: 44px; }
  .file-nav { max-height: 176px; padding: 8px 10px; }
  .file-folder-row { padding-block: 7px; }
  .file-list-pane { min-height: 0; }
  .file-list-head { min-height: 44px; }
  .file-table .file-list-row { min-height: 44px; }
  .file-name-cell b { white-space: normal; overflow-wrap: anywhere; }
  .file-workspace-sub, .file-name-cell small, .file-source-cell small,
  .att-meta, .att-code { color: var(--ink-2); }

  /* 手机预览采用阅读流，不保留桌面 A4 的 62px 内边距。 */
  .drawer.wide { width: 100vw; max-width: none; }
  .drawer .dhead { min-height: 56px; padding-inline: 16px; }
  .att-drawer-meta { position: sticky; top: 0; z-index: 1; padding: 10px 16px; }
  .att-drawer-meta a { min-height: 44px; display: inline-flex; align-items: center; }
  .att-paper {
    width: auto; max-width: none; min-height: 0; margin: 0; border: 0;
    padding: 20px 16px max(28px, env(safe-area-inset-bottom, 0px));
  }
  .att-pdfframe { height: calc(100dvh - 112px); }
  .pdf-pages, .att-img-wrap { padding: 12px; }
}

/* 双向布局：浮层从行尾进入，箭头和安全区随书写方向镜像。 */
[dir="rtl"] { --overlay-offscreen: -100%; --nav-label-offset: 4px; }
[dir="rtl"] .drawer, [dir="rtl"] .panel { box-shadow: 8px 0 32px rgba(38, 38, 38, 0.10); }
[dir="rtl"] .nav-group-toggle span { transform: scaleX(-1); }
[dir="rtl"] .nav-group.is-open .nav-group-toggle span { transform: scaleX(-1) rotate(90deg); }
[dir="rtl"] .page {
  padding-inline-start: max(var(--page-px), env(safe-area-inset-right, 0px));
  padding-inline-end: max(var(--page-px), env(safe-area-inset-left, 0px));
}

@media (max-width: 640px) {
  /* 标题行放不下三样东西：标题 + 模式开关 + 关闭。nowrap 下开关按 flex:none 占满宽度，
     把标题挤成一列一个字（实测 375px 下 h3 只剩 15px 宽），开关自己还溢出抽屉 7px。
     窄屏改成两行：标题与关闭同行，开关整行铺开、两个态各占一半。 */
  .panel .phead { flex-wrap: wrap; }
  .panel .phead .dclose { order: 1; }
  .panel .phead .seg.opp-mode { order: 2; flex: 0 0 100%; }
  .panel .phead .seg.opp-mode button { flex: 1; }
  /* 抽屉表单的提交区参与正常文档流，避免地址栏、底部安全区和滚动容器叠压。 */
  .panel .pfoot {
    position: static;
    bottom: auto;
    margin-top: 16px;
    padding-bottom: max(4px, env(safe-area-inset-bottom, 0px));
  }
  .plus-btn { min-width: 44px; min-height: 44px; }
  .detail-summary .kv {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px 16px;
  }
  .detail-summary .kv .item,
  .grid.detail .detail-summary .kv .item { width: auto; min-width: 0; }
  .detail-summary .kv .item.u-flex-1,
  .detail-summary .longtext { grid-column: 1 / -1; }
  .detail-summary.editing .kv { grid-template-columns: 1fr; }
  .record-actions-head { align-items: flex-start; flex-wrap: wrap; }
  .record-actions-head .section-title { width: 100%; }
}

@media (max-width: 430px) {
  /* 390/430px 的详情字段必须真正单列；覆盖桌面 detail 的 calc(50% - 12px)。 */
  .kv { gap: 14px; }
  .kv .item, .grid.detail .kv .item { width: 100%; min-width: 100%; }
  .detail-head { gap: 10px; }
  .detail-head h1 { font-size: 19px; overflow-wrap: anywhere; }
  .response-table tr { grid-template-columns: minmax(0, 1fr) auto; }
}

@media (max-width: 360px) {
}
.date-filter{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.date-custom-toggle{
  height:32px;padding:0 12px;border:0;border-radius:var(--r-sm);background:var(--panel);
  color:var(--ink-2);font-size:13px;font-weight:500;
}
.date-custom-toggle:hover,.date-custom-toggle.on{background:var(--paper);color:var(--ink)}
.date-custom-toggle:focus-visible{outline:0;box-shadow:0 0 0 3px rgba(51,110,232,.2)}
.date-custom{display:flex;align-items:center;gap:6px;color:var(--ink-2);font-size:12px}
.date-custom[hidden]{display:none}
.date-custom input[type="date"]{width:142px;min-width:0;height:32px;padding:5px 8px}
.statistics-kpis{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;margin-bottom:16px}
.statistic-metric{padding:18px 20px;border-top:2px solid var(--blue)}
.statistic-metric .k{font-size:12px;color:var(--ink-2)}
.statistic-metric .v{font-size:28px;font-weight:700;line-height:1.25;margin-top:6px;color:var(--ink)}
.statistic-metric .d{font-size:12px;color:var(--ink-2);margin-top:4px}
.statistics-grid{display:grid;grid-template-columns:1.15fr .85fr;gap:16px}
.statistics-section{padding:18px 20px;min-width:0}
.statistics-section .table-scroll{overflow:auto;margin-top:12px}
.stat-granularity select{height:30px;padding:4px 28px 4px 8px;font-size:12px}
.statistics-note{padding:16px 20px;font-size:12.5px;color:var(--ink-2);line-height:1.65}
.statistics-note p{margin:7px 0 0}
@media(max-width:1100px){.statistics-kpis{grid-template-columns:repeat(3,minmax(0,1fr))}.statistics-grid{grid-template-columns:1fr}}
@media(max-width:720px){.statistics-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}.date-filter,.date-custom{align-items:stretch}.date-custom-toggle{min-height:44px}.date-custom{width:100%;flex-wrap:wrap}.date-custom input[type="date"]{flex:1;min-width:125px}.statistics-section{padding:14px}.statistic-metric{padding:14px}.statistic-metric .v{font-size:24px}}

/* 最终窄屏级联护栏：位于全部组件与页面特例之后，防固定 28/32/36px 回压触控热区。 */
@media (max-width: 768px) {
  :where(.btn, .btn.sm, button, select,
    input[type="text"], input[type="search"], input[type="date"],
    input[type="datetime-local"], input[type="tel"], input[type="url"],
    input[type="email"], input[type="number"], input:not([type]),
    .icon-btn, .aham-icon-button, .search-toggle, .nav-group-toggle,
    .plus-btn, .dclose, .mini, .tool-tab, .date-custom-toggle) {
    min-height: 44px !important;
  }
  :where(button, .btn, .btn.sm, .icon-btn, .aham-icon-button,
    .search-toggle, .nav-group-toggle, .plus-btn, .dclose, .mini) {
    min-inline-size: 44px !important;
  }
  :where(select, input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"])) {
    min-height: 44px !important;
  }
  :where(.pick, .aham-checkbox-list label, .menu-pop a, .menu-pop button,
    .mobile-tabs .tab, .seg :where(a, button), .page-anchor-nav a, .strategy-subnav a,
    .opp-workspace-tabs a, .rowlink) {
    min-height: 44px !important;
  }
  textarea { min-height: 96px !important; }
}

/* ---------- 日报/周报落地页 ---------- */
.report-sheet { display: flex; flex-direction: column; gap: 16px; }
.report-person-id { display: flex; align-items: center; gap: 12px; min-width: 0; }
.report-person-id h2 { font-size: 15px; font-weight: 600; line-height: 1.4; }
.report-person-id .code { margin-top: 1px; }
.report-person-nums { display: flex; gap: 12px; flex: none; }
/* 今日/明日两栏。窄屏与打印时都塌成一栏——纸面 A4 宽度放两栏正文会挤到不可读。 */
.report-body { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 14px; }
.report-col { min-width: 0; background: var(--panel); border-radius: var(--r-lg); padding: 14px 16px; }
.report-col .section-title { margin: 0 0 8px; }
.report-lines { margin: 0; padding-inline-start: 18px; display: grid; gap: 5px; }
.report-lines li { color: var(--ink); font-size: 14px; line-height: var(--leading-cjk); }
.report-empty { color: var(--ink-3); font-size: 13px; }
.report-missing p { color: var(--ink-2); font-size: 14px; line-height: 1.7; }
@media (max-width: 860px) { .report-body { grid-template-columns: 1fr; gap: 14px; } }
@media print {
  .report-body { grid-template-columns: 1fr; gap: 3mm; }
  /* 纸上不铺灰底（省墨、扫描也干净），改用一条细线分隔今日/明日 */
  .report-col { background: #fff; padding: 0 0 0 3mm; border-inline-start: 1px solid #bbb;
                border-radius: 0; }
}

/* ---------- 确认页上的查重候选（P1） ---------- */
.dedup-hint .dedup-list { list-style: none; display: grid; gap: 8px; margin: 12px 0 0; padding: 0; }
.dedup-hint .dedup-list a { display: block; padding: 10px 12px; border-radius: var(--r-md);
  background: var(--paper); color: var(--ink); }
.dedup-hint .dedup-list a:hover { background: var(--hover); }
.dedup-hint .dedup-list b { display: block; font-weight: 600; font-size: 14px; }
.dedup-hint .dedup-list small { display: block; color: var(--ink-3); font-size: 12px; margin-top: 2px; }
/* 「就是这家」是推荐动作，摆在最前；「确实是另一家」次要但不藏起来——
   藏了就等于又把人挡回去了。 */
.dedup-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 16px; }
.dedup-actions form { margin: 0; }

/* ============ 成交预测看板（/opportunities?view=forecast）============
   行＝分组、列＝预计成交月，圈的【面积】＝金额、深浅＝阶段。
   汇总条与矩阵共用同一套网格列，两者才可能对齐——分成两个容器各画各的，
   列宽迟早会飘，那时候「10月这一列的合计」压根不在 10 月那一列上方。 */
.forecast-shell .seg.sm :where(a, button) { padding: 4px 10px; font-size: 12.5px; }

.forecast-grid {
  display: grid;
  grid-template-columns: 112px repeat(var(--fc-cols), minmax(150px, 1fr)) 108px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-lg); overflow: hidden; min-width: 1040px;
}
.fc-corner, .fc-sum { border-bottom: 1px solid var(--line); border-right: 1px solid var(--line);
  background: #FCFCFD; padding: 9px 11px 11px; }
.fc-sum:last-of-type { border-right: 0; }
.fc-corner { font-size: 12px; color: var(--ink-3); display: flex; align-items: flex-end; }
.fc-sum.focus { background: var(--blue-50); }
.fc-sum.side  { background: #F5F5F6; }
.fc-sum.alert { background: var(--risk-50); }
.fc-k  { font-size: 13px; font-weight: 600; white-space: nowrap; }
.fc-k2 { font-size: 12px; color: var(--ink-3); white-space: nowrap; margin-top: 1px; }
.fc-k2 i { font-style: normal; opacity: .5; margin: 0 4px; }
.fc-v  { font-family: var(--mono); font-size: 19px; font-weight: 600;
  letter-spacing: -.3px; margin-top: 6px; line-height: 1.15; }
.fc-v.dim { color: var(--ink-3); font-size: 16px; }
.fc-w  { font-size: 12px; color: var(--ink-3); margin-top: 1px; }
.fc-w em { font-style: normal; font-family: var(--mono); color: var(--ink-2); }

.fc-rowlab { padding: 12px 11px; background: #FCFCFD;
  border-right: 1px solid var(--line); border-bottom: 1px solid var(--line);
  display: flex; flex-direction: column; justify-content: center; gap: 2px; }
.fc-rowlab .nm { font-size: 13px; font-weight: 600; }
.fc-rowlab .mt { font-size: 12px; color: var(--ink-3); font-family: var(--mono); }
.fc-cell { border-right: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding: 10px 6px 11px; display: flex; flex-wrap: wrap;
  align-content: flex-start; justify-content: center; gap: 10px 5px; }
.fc-cell.focus { background: #FCFDFF; }
.fc-cell.side  { background: #FAFAFB; }
.fc-cell.alert { background: #FDF9F8; }
.fc-rowtot { border-bottom: 1px solid var(--line); background: #FCFCFD;
  display: flex; flex-direction: column; align-items: flex-end;
  justify-content: center; padding: 10px 11px; gap: 1px; }
.fc-rowtot .v { font-family: var(--mono); font-size: 14px; font-weight: 600; }
.fc-rowtot .w { font-family: var(--mono); font-size: 12px; color: var(--ink-3); }
.forecast-grid > .last { border-bottom: 0; }

/* 一个商机 = 圈 + 圈下三行字。宽度自适应：格子够宽就两个并排，不够退单列。
   ⚠️ 名称金额【不能】写进圈里：小圈根本放不下，长客户名还会被截成「中广核高…」。 */
.fc-chip { width: calc(50% - 3px); min-width: 74px; max-width: 100px;
  display: flex; flex-direction: column; align-items: center;
  border-radius: var(--r-sm); padding: 2px 1px 3px; color: inherit;
  transition: background var(--t-fast) var(--ease); }
.fc-chip:hover { background: rgba(51, 110, 232, .07); }
.fc-lane { height: 66px; display: flex; align-items: flex-end; justify-content: center; }
.fc-bub { border-radius: 50%; border: 1.5px solid transparent;
  transition: transform var(--t-fast) var(--ease); }
.fc-chip:hover .fc-bub { transform: scale(1.08); }
.fc-cap { width: 100%; text-align: center; margin-top: 6px; line-height: 1.28; }
.fc-cap > span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fc-cap .cu { font-size: 12px; font-weight: 650; }
.fc-cap .nm { font-size: 12px; color: var(--ink-3); margin-top: -1px; }
.fc-cap .am { font-family: var(--mono); font-size: 12px; font-weight: 600;
  margin-top: 2px; letter-spacing: -.2px; }
.fc-cap .am.none { color: #A9ADB5; font-weight: 500; font-size: 12px; font-family: inherit; }
.fc-cap .am.odm { color: var(--risk); }
.fc-empty { color: #CDCFD4; font-size: 12px; margin: auto; padding: 24px 0; }

/* 阶段色阶：越深越接近成交。st-6/st-7 是赢单/输单——筛选切到「含赢单」时会出现，
   少了这两条它们就是透明圈。 */
.st-1 { background: #CBD9F8; border-color: #A3BCF1; }
.st-2 { background: #AAC2F4; border-color: #86A6ED; }
.st-3 { background: #7FA3EC; border-color: #5B85E3; }
.st-4 { background: #5081E7; border-color: #3465CE; }
.st-5 { background: #2B58C4; border-color: #1F42A0; }
.st-6 { background: var(--ok);   border-color: #45604A; }
.st-7 { background: #C9BDBB;     border-color: var(--risk); }
.st-0 { background: var(--panel); border-color: var(--line); }
.fc-bub.noamt, .lgdot.noamt {
  background: repeating-linear-gradient(45deg, #F5F6F8, #F5F6F8 3px, #E9EBEF 3px, #E9EBEF 6px);
  border-style: dashed; border-color: #B9BDC6; }
.fc-bub.od, .lgdot.od { box-shadow: 0 0 0 2.5px var(--paper), 0 0 0 4px var(--risk); }

.forecast-legend { display: flex; gap: 30px; flex-wrap: wrap; align-items: flex-end;
  padding: 14px 2px 4px; }
.forecast-legend .lg h4 { margin: 0 0 9px; font-size: 12px; color: var(--ink-3); font-weight: 600; }
.forecast-legend .lgrow { display: flex; align-items: center; gap: 13px; flex-wrap: wrap; }
.forecast-legend .lgi { display: flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--ink-2); }
.forecast-legend .lgdot { width: 13px; height: 13px; border-radius: 50%;
  border: 1.5px solid; flex: 0 0 auto; }
.forecast-legend .sizeref { display: flex; align-items: flex-end; gap: 14px; }
.forecast-legend .sizeref > div { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.forecast-legend .sizeref i { border-radius: 50%; background: #DCE5F8; border: 1.5px solid #A3BCF1; }
.forecast-legend .sizeref span { font-size: 12px; color: var(--ink-3); font-family: var(--mono); }

/* 气泡尺寸档位。模板不许写内联 style（smoke_aham_layout_contract 卡全仓库），
   尺寸只能走这组有限档位——20~66px、2px 一档，与 web._bubble_diameter 严格对应，
   改那边的上下限/步长就必须同步改这里，smoke_opportunity_forecast 会盯着。 */
.fc-d20, .fc-d22, .fc-d24, .fc-d26, .fc-d28,
.fc-d30, .fc-d32, .fc-d34, .fc-d36, .fc-d38, .fc-d40, .fc-d42, .fc-d44, .fc-d46,
.fc-d48, .fc-d50, .fc-d52, .fc-d54, .fc-d56, .fc-d58, .fc-d60, .fc-d62, .fc-d64, .fc-d66 { flex: 0 0 auto; }
.fc-d20 { width: 20px; height: 20px; }
.fc-d22 { width: 22px; height: 22px; }
.fc-d24 { width: 24px; height: 24px; }
.fc-d26 { width: 26px; height: 26px; }
.fc-d28 { width: 28px; height: 28px; }
.fc-d30 { width: 30px; height: 30px; }
.fc-d32 { width: 32px; height: 32px; }
.fc-d34 { width: 34px; height: 34px; }
.fc-d36 { width: 36px; height: 36px; }
.fc-d38 { width: 38px; height: 38px; }
.fc-d40 { width: 40px; height: 40px; }
.fc-d42 { width: 42px; height: 42px; }
.fc-d44 { width: 44px; height: 44px; }
.fc-d46 { width: 46px; height: 46px; }
.fc-d48 { width: 48px; height: 48px; }
.fc-d50 { width: 50px; height: 50px; }
.fc-d52 { width: 52px; height: 52px; }
.fc-d54 { width: 54px; height: 54px; }
.fc-d56 { width: 56px; height: 56px; }
.fc-d58 { width: 58px; height: 58px; }
.fc-d60 { width: 60px; height: 60px; }
.fc-d62 { width: 62px; height: 62px; }
.fc-d64 { width: 64px; height: 64px; }
.fc-d66 { width: 66px; height: 66px; }

/* 列数由 web.FORECAST_MONTHS 决定（逾期 + N 个月 + 更远期 + 未排期）。
   写成类而不是内联变量：改了月数却忘了加这里的档位，布局会立刻塌给人看，
   而不是悄悄错位。 */
.forecast-grid.fc-cols-6 { --fc-cols: 6; }
.forecast-grid.fc-cols-7 { --fc-cols: 7; }
.forecast-grid.fc-cols-8 { --fc-cols: 8; }
.forecast-grid.fc-cols-9 { --fc-cols: 9; }
.forecast-grid.fc-cols-10 { --fc-cols: 10; }
