/* 全年供应链 UI —— 对齐哈他 ERP 全站规范（feedback_hata_erp_ui_rules）。
   主色 Tailwind green · 侧栏 160px · body 13px · KPI 中性色。 */

:root {
    --jg-green-50:  #f0fdf4;
    --jg-green-100: #dcfce7;   /* 侧栏 active 底 */
    --jg-green-200: #bbf7d0;   /* 边框 */
    --jg-green-500: #22c55e;   /* 主色 */
    --jg-green-600: #16a34a;   /* hover · 侧栏 active 字 */
    --jg-green-700: #15803d;   /* active · link */
    --jg-ink:       #262626;   /* KPI 数值中性深灰 */
}

/* ── 字号：全站 13px（哈他对齐 Foodmax，Unfold 默认 14 偏大）── */
body { font-size: 13px; }

/* ── 侧栏宽度 ──
   不用 CSS 压宽度：Unfold 的宽度是 Alpine 内联样式（可拖拽，下限 220px），
   外层 wrapper 与 #nav-sidebar 共用同一个值。CSS 只压得住内层压不住外层，
   两者就会错开，中间空出一条灰带（踩过）。宽度改由 theme.js 设 localStorage。

   哈他规范是 160px，但那是 iframe workspace 结构：顶部一级 tab 分流，
   侧栏只放 4 字二级条目。这里所有模块都在侧栏、最长条目 6 字（月度成本录入），
   160px 会截断，所以取框架下限 220px —— 同样紧凑，且不与框架冲突。 */
#nav-sidebar-inner { height: 100dvh; position: sticky; top: 0; }

/* 侧栏内边距收紧，把宽度让给文字（Unfold 默认按 288px 留的 px-6） */
#nav-sidebar-inner > :nth-child(3) > * { padding-left: 12px; padding-right: 12px; }
#nav-sidebar-inner a { padding-left: 10px; padding-right: 10px; }

/* 结构 header · search · app_list · user —— 中间可滚，首尾不压缩。
   注：不覆盖 navigation.html，之前那样改 DOM 把导航整片搞塌过。 */
#nav-sidebar-inner > :first-child,
#nav-sidebar-inner > :nth-child(2),
#nav-sidebar-inner > :last-child { flex: 0 0 auto; }
#nav-sidebar-inner > :nth-child(3) {
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto; overscroll-behavior: contain;
}
#nav-sidebar-inner > :nth-child(3)::-webkit-scrollbar { width: 6px; }
#nav-sidebar-inner > :nth-child(3)::-webkit-scrollbar-thumb {
    background: rgb(0 0 0 / .16); border-radius: 4px;
}
@media (prefers-color-scheme: dark) {
    #nav-sidebar-inner > :nth-child(3)::-webkit-scrollbar-thumb {
        background: rgb(255 255 255 / .18);
    }
}

/* 侧栏字号：一级 / 二级同为 14px */
#nav-sidebar-inner h2,
#nav-sidebar-inner a { font-size: 14px; }
#nav-sidebar-inner a { min-height: 45px; }

/* 侧栏 active：浅绿底 + 绿字 */
#nav-sidebar-inner a[aria-current="page"],
#nav-sidebar-inner a.bg-primary-50,
#nav-sidebar-inner a.text-primary-600 {
    background: var(--jg-green-100) !important;
    color: var(--jg-green-600) !important;
}

/* ── 面包屑隐藏：侧栏 + 页头 h1 已两处指位，面包屑冗余 ── */
#content > .px-4 nav[aria-label="Breadcrumbs"],
nav[aria-label="Breadcrumbs"] { display: none; }

/* ── 数字：等宽对齐 ── */
.field-unit_cost, .field-input_cost, .field-labor_cost,
.field-transferable_cost, .field-loss_rate, .field-total_cost,
td[class*="field-"] { font-variant-numeric: tabular-nums; }

/* ── input 去 spinner：全站数字手动输入 ── */
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none; margin: 0;
}

/* ── 侧栏品牌区 ────────────────────────────────────────────
   logo 图（含「生鲜供应链卷王」小字）+ 右侧「全年供应链」加粗。

   注意 SITE_HEADER 不能置空：Unfold 的模板是
   `{% elif branding %}{% include site_icon %}{% endif %}` ——
   站点名一空，连 logo 都不渲染。 */
[class*="h-[65px]"] .text-important {
    font-weight: 700;
    font-size: 14px;
    letter-spacing: 0;
    white-space: nowrap;
    /* 文字块本身 grow 占满 logo 右边的空间，居中就是在这块里居中 */
    text-align: center;
    /* 跟右侧顶栏标题同一个行高（那边是 leading-5 = 20px）——
       行高不一致，两边即使都「垂直居中」，看起来也差着几个像素 */
    line-height: 20px;
}

/* logo 高度要跟侧栏宽度配套：侧栏 220px 时 46px 的 logo 很合适，
   收到 160px（对齐哈他）之后，logo + 文字排不下，「全年供应链」
   被挤成「年供应」。缩到 28px，两者都完整。 */
/* ★★★ 吴凡 2026-10-09：「重新调整 logo 字体大小，使之更协调，整齐」。
   实测改之前：logo 28px、「全年供应链」14px/700 —— 字显小、字重偏死，
   28px 的方形 logo 旁边配一行 14px 粗体，重量压不住。
   改成 logo 32px + 文字 18px/600：比例 ≈1:1.8，两者视觉重量才配得上。
   ★ 18px 是规范里的 `--fs-lg`（页面标题档），不是我随手挑的数 ——
     六档字号之外一律不许出现（规范 C-04）。品牌名用标题档合理。
   ★ 字重 700→600：跟表头一致。700 在 18px 上太黑，抢内容。 */
/* ★★★ 吴凡 2026-10-11：「logo 不整齐，logo 放大，和字体整齐排列」。
   浏览器里量出来问题不在 logo 自己，在**它的两层父盒**：
       DIV.shrink-0   高 72px   ← 容器只有 65px
       A              高 69px
       IMG            高 32px（上 16，中线 32）
   图片本身是居中的（文字块中线 32.5，差 0.5px），
   可外面那两层比容器还高 4~7px，把 65px 的品牌区**撑破**了 ——
   截图里 logo 下面那条空白就是它，不是没对齐。

   ★★ 根因是 `<a>` 是行内元素：行内盒要给基线下的「降部」留空间，
      于是 32px 的图外面长出 69px 的行盒。**图片居中了，盒子没居中。**
      改成 flex + `line-height: 0`，盒子才跟图一样高。
   ★ 这类「量了子元素都对、看着就是歪」的，一律往上量父盒
     —— 前两次（10-09）也是在调图和字，没量外面那层。 */
[class*="h-[65px]"] img {
    height: 44px;              /* ★ 32 → 44：18px 的字旁边 32px 压不住 */
    width: auto;
}
/* logo 外面那两层：跟图等高，不许自己长个儿 */
[class*="h-[65px]"] .shrink-0,
[class*="h-[65px]"] .shrink-0 > a {
    display: flex;
    align-items: center;
    line-height: 0;            /* ★ 关键：行内盒的降部空间，不去掉就撑高 */
    height: auto;
}
/* ★★ 两个 `<a>`（logo 的和站名的）左右各白吃 10px。
   ★★★ 来源不是 Unfold，是**这个文件第 29 行我自己写的**：
       `#nav-sidebar-inner a { padding-left: 10px; padding-right: 10px; }`
   它带 ID，特异性 (1,0,1)，压过 `[class*="h-[65px]"] .shrink-0 > a` 的
   (0,2,1) —— 所以我第一版的 `padding-left: 0` 写了等于没写，
   页面上一点变化都没有。**「改了没生效」先比特异性，别先怀疑缓存。**
   （这个仓库在同一条上栽过：加了 !important 还不生效，也是输在特异性。）
   侧栏内容宽只有 151px：logo 46 + 间距 12 + 「全年供应链」91 = 149，
   本来**正好放得下**，而这 20px 一占就超，于是站名被 `*:truncate`
   裁成「全年供应」。
   ★ 判据不是肉眼看 —— 是量 `scrollWidth > clientWidth`
     （裁掉之后那几个字仍然像个完整的词，截图上根本看不出来，
       跟内联数字框只装 7 位是同一类坑）。 */
#nav-sidebar-inner [class*="h-[65px]"] a,
[class*="h-[65px]"] .shrink-0 > a {
    padding-left: 0;
    padding-right: 0;
}
/* ★★★ 去掉那 20px 之后还差一点：实测站名仍然**两头各被切掉半个字**
   （「全年供应链」显示成「⃒年供应⃒」）。两头都切，是因为文字块
   `text-align: center` —— 盒子装不下时，居中会把两边一起裁掉，
   而靠左至少只裁右边、人一眼能看出「这里被截断了」。
   ★ 顺手把这一行的间距从 12px 收到 8px：44px 的 logo 旁边 8px 够用，
     省下的 4px 正好补上缺口。
   ★ 这一步是**看图**才发现的 —— 前一轮所有盒子的数都对（中线差 0、
     零溢出），而字就是缺了两半。量盒子量不出「字被切了」，
     要么量 scrollWidth，要么把整屏截下来看。 */
[class*="h-[65px]"] > div {
    gap: 8px;
}
[class*="h-[65px]"] .text-important {
    text-align: left;
}
/* ★★★ 吴凡 2026-10-11 第二轮：「全年供应链 字体 向下移动 1cm」。
   盒子是对齐的（logo 中线 32、文字块中线 32，差 0），**字形不在盒子中间**：
   `#site-name a` 被父层拉满 45px 高，而行高只有 21.6px ——
   文字贴在盒子顶部，比 logo 的视觉中心高了约 11px。

   ★★ 这就是为什么上一轮「中线差 0」还被说偏：
      **我量的是 a 的外框，人看的是字形。** 外框居中 ≠ 字居中。
      判据改成用 `document.createRange()` 量文本节点自己的 rect。

   ★ 做法不是往下推 margin（那会在别的字号/缩放下又错开），
     而是让 a 自己变成 flex 容器，文本作为匿名 flex item 垂直居中 ——
     字号或容器高度再变，它都还在中间。 */
[class*="h-[65px]"] #site-name a {
    display: flex;
    align-items: center;
}
[class*="h-[65px]"] #site-name,
[class*="h-[65px]"] #site-name a {
    font-size: var(--fs-lg);
    font-weight: 600;
    line-height: 1.2;          /* ★ 1.2 行高让 18px 的字盒正好 22px，
                                     跟 logo 一起居中不会偏 */
    letter-spacing: 0;         /* Unfold 给了 tracking-tight，18px 下太挤 */
}

/* 文字块与 logo 等高，两者被同一个 items-center 一起居中 —— 位置必然一致。
   前几次都在调「让文字自己居中」，可文字块高度只有一行（20px）、
   logo 有 46px，两个高度不同的盒子各自居中，看着就是没对齐。
   等高才是对齐的前提。 */
[class*="h-[65px]"] .flex-col {
    min-height: 44px;          /* ★ 跟 logo 等高 —— 等高才是对齐的前提
                                     （2026-10-11 logo 32→44，这里跟着走；
                                       漏改的话文字块还是 32，两个盒子
                                       高度不同，各自居中就又错开了） */
    display: flex;
    justify-content: center;   /* flex-col 时这一条管垂直 */
}

/* 品牌区容器 65px、右侧顶栏 h-16（64px），两边都靠 items-center 居中，
   本来就该对齐。之前我给文字块加了 height:100% 一类的规则去「强行居中」，
   反而把它从父容器的居中体系里拽了出来 —— 去掉，让它回到默认行为。 */
[class*="h-[65px]"] #site-name {
    justify-content: center;
}

/* ★ 收窄输入框本身还不够 —— 撑住宽度的是**外面那层包裹 div**：
   Unfold 给它挂了 min-w-56（14rem = 224px）。输入框 width:100% 只是
   填满这个 224px 的父层，量出来还是 224，看着像 CSS 没生效。 */
/* 姓名一列容易被挤到只剩两个字，给个下限 */
body.model-employee.change-list #result_list td:nth-child(2) { min-width: 72px; }

/* ── 字段说明收进「?」 ────────────────────────────────────────
   说明文字有用，但常年占两三行、把表单撑得又高又花，而人只在第一次
   填的时候需要看一眼。收进标签后面的问号里：平时干净，要看随时有。 */
.jg-tip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 15px; height: 15px;
    margin-left: 5px;
    border: 1px solid var(--color-base-300);
    border-radius: 50%;
    font-size: 11px;
    line-height: 1;
    color: var(--color-base-500);
    background: transparent;
    cursor: help;
    vertical-align: middle;
    flex: 0 0 auto;
}
.jg-tip:hover { border-color: #22c55e; color: #22c55e; }

/* 提示气泡。用 ::after 画，不额外插 DOM —— 少一层，也不会被表单收走 */
.jg-tip::after {
    content: attr(data-tip);
    position: absolute;
    z-index: 60;
    left: 0; top: 100%;
    margin-top: 6px;
    width: max-content;
    max-width: 300px;
    padding: 7px 10px;
    border-radius: 4px;
    background: var(--color-base-800);
    color: #fff;
    font-size: 12px;
    line-height: 1.6;
    text-align: left;
    white-space: normal;
    /* 默认不占位也不挡点击 —— visibility 而不是 display，
       这样有淡入，也不会因为重排让页面抖一下 */
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .12s;
}
.jg-tip:hover::after, .jg-tip:focus-visible::after {
    opacity: 1;
    visibility: visible;
}
/* 气泡是绝对定位，得有个定位参照；标签本身来当 */
.field-line label { position: relative; }

/* ── 表单控件宽度统一（全站）────────────────────────────────
   两件事：

   ① 日期框会溢出格子 11~12px，压到右边那格的标签上。撑住它的不是
      输入框自己，是外面那层包裹 div 的 min-w-56（14rem = 224px）——
      输入框 width:100% 只是填满这个 224px 的父层。之前只在加工单
      表头治过，这次全站治。

   ② 控件宽度原来跟着一行放几个字段变：一行 3 个是 200px，
      一行 2 个变 425px，一行 1 个变 672px。于是「籍贯」的输入框
      是「性别」的两倍宽，同一张表看着忽宽忽窄。
      给个统一上限，一行放几个都一样宽，只是留白不同。 */
.field-line > .grow [class*="min-w-"] { min-width: 0 !important; }
.field-line > .grow { min-width: 0; }
.field-line > .grow input:not([type="checkbox"]):not([type="radio"]),
.field-line > .grow select,
.field-line > .grow .select2-container {
    max-width: 250px;
}

/* ★ 列表框是上面那条 250px 的**例外** —— 它不是单行输入框。

   量出来的（职位权限模板页，1700px 窗口）：filter_horizontal 的左右双框
   各 484px 宽，里面的列表却被卡在 250px —— **每边白空 234px**，
   而「Can change 采购单」这种权限名当场被截断。
   人要横着拖才认得出自己勾的是哪一条，双框这个控件就白用了。

   250px 那条上限是为「一行三个字段时输入框别忽宽忽窄」定的，
   套到一个本来就要横铺的列表框上是套错了对象。
   多选列表（额外用户组、额外权限）同理。 */
.field-line > .grow select[multiple],
.field-line > .grow .selector input[type="text"] {
    max-width: none;
    width: 100%;
}

/* ★ 标签列**固定宽度**，输入框才能对齐同一条竖线。

   上一版让标签「按文字宽度走」，结果标签字数不同、输入框起点就跟着飘：
   「工号」的框从 80px 起、「性别」从 52px 起、「公司邮箱」从 236px 起 ——
   一张表上量出 17 种起点（52 到 237），看着就是乱。

   168px 是量出来的：最长的标签「个人计时费率(元/人时)」连问号 162px，
   再留 6px 余量。3 列的格子 449px，168 + 250 还差 30px 富余。 */
.field-line > div:first-child:not(:only-child) {
    min-width: 168px !important;
    width: 168px !important;
    flex: 0 0 168px;
}
.field-line > div:first-child label { white-space: normal; }

/* 开关（在职、缴社保）这类布尔字段，Unfold 把标签和开关放在**同一个** div 里，
   没有单独的标签列 —— 上面那条按「第一个子 div」定宽的规则会连开关一起挤。
   :not(:only-child) 把它排除掉，再单独把它的标签撑到同样的 168px，
   开关才落在跟别的输入框同一条竖线上。 */
.field-line > div:only-child > div:first-child {
    min-width: 168px !important;
    width: 168px !important;
    flex: 0 0 168px;
}

/* 长文本例外 —— 地址、备注、原因这类，挤成 260px 就看不全了 */
.field-line > .grow input[name="address"],
.field-line > .grow input[name="remark"],
.field-line > .grow input[name="leave_reason"],
.field-line > .grow input[name="contract_entity"],
/* 我方结算主体：公司全名 ——「渔获农业发展（江苏）有限公司」14 个字，
   250px 只放得下 12 个，最后被截成「…有限公」。
   这一格是收付款时认法人主体用的，同集团常有几家只差省份的公司，
   截断之后两家看起来一模一样（吴凡 2026-09-04 截图）。
   采购单和销售单用的是同一个字段名。 */
.field-line > .grow input[name="settle_entity"],
.field-line > .grow input[name="position"],
.field-line > .grow input[name="name"],
.field-line > .grow textarea {
    max-width: 460px;
}

/* ── 侧栏：选中项的底色铺满整条 ──────────────────────────────
   原来绿底只占中间一段（左右各空 24px，那是 ol 的 px-6），
   看着像贴了半张纸。把左右内边距从 ol 挪到每个 a 上：底色就能铺满，
   而文字的横向位置一点不动。

   ★ 内边距必须给**所有**导航项，不能只给选中的那个 —— 只给选中项加
   padding，点一下文字就往右跳一截（哈他那边栽过这个）。
   选中态只负责改颜色，不改盒子。 */
/* 两层内边距要一起挪：ol 的 px-6（24px）和它外面那层的 12px。
   只挪一层，底色还是差 12px 到不了边。 */
nav ol.px-6,
aside ol.px-6 {
    padding-left: 0 !important;
    padding-right: 0 !important;
}
nav ol.px-6 > li > a,
aside ol.px-6 > li > a {
    margin-left: -12px !important;
    margin-right: -12px !important;
    /* 侧栏 160px 时留 24px 首行缩进就够；原来 36 是按 220px 宽算的，
       窄下来之后文字会被挤到只剩几个字 */
    padding-left: 24px !important;
    padding-right: 16px !important;
    border-radius: 0 !important;
}

/* ── 已选条件标签 ────────────────────────────────────────────
   筛选框一多，选过什么全靠一个个下拉去看 —— 把生效的条件列成一排，
   点 × 去掉一条。样式跟着搜索行走，不另起一块。 */
.jg-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    width: 100%;
    margin-top: 2px;
}
.jg-chips-title {
    font-size: 12px;
    color: var(--color-base-500);
    margin-right: 2px;
}
.jg-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border: 1px solid var(--color-base-200);
    border-radius: 999px;
    background: #fff;
    font-size: 12px;
    line-height: 20px;
    color: var(--color-base-700);
    text-decoration: none;
}
.jg-chip:hover { border-color: #22c55e; color: #16a34a; }
.jg-chip-k { color: var(--color-base-500); }
.jg-chip-v { font-weight: 600; }
.jg-chip-x { color: var(--color-base-400); font-size: 13px; }
.jg-chip:hover .jg-chip-x { color: #16a34a; }
.jg-chip-clear { border-style: dashed; color: var(--color-base-500); }
@media (prefers-color-scheme: dark) {
    .jg-chip { background: var(--color-base-900); }
}

/* ── 列表页顶部：搜索 + 筛选下拉 ────────────────────────────
   跟哈他（sslx.me）同一套布局：搜索框一行，下面是筛选下拉的网格。
   筛选块由 filter_bar.js 从右侧抽屉搬过来（见那里的说明）。 */
.jg-filter-bar {
    /* ★ 用 flex 不用 grid。
       grid 下量出来格子按 2,4,1,3,5 跳着落位、行高被撑到 222px ——
       Unfold 自己的样式里有东西在干扰网格轨道，排查成本高于收益。
       flex 换行的行为是可预测的：一格 200px，排满就换行。 */
    display: flex !important;
    /* 不写 row 的话方向会是 column（外层容器的 flex-col 传下来），
       所有筛选竖着堆成一列 —— 量出来每个都在左 249 */
    flex-direction: row !important;
    flex-wrap: wrap !important;
    align-items: flex-start;
    gap: 10px 14px;
    width: 100%;
    margin: 2px 0 0 !important;
    padding: 0 !important;
    background: transparent !important;
}
.jg-filter-bar > * { flex: 0 0 200px; min-width: 0; }
/* 抽屉的空壳和遮罩搬完就没用了 */
#changelist-filter-close { display: none !important; }

.jg-filter-item { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.jg-filter-item > label {
    font-size: 12px;
    color: var(--color-base-500);
    font-weight: 500;
}
/* ★ 必须排除 #searchbar：搜索框外面已经有 Unfold 自带的边框壳
   （bg-white border rounded-default 那个 div），这条规则再给里面的
   input 加一圈边框和圆角，两层套在一起就成了「搜索框里还有一个
   搜索框」。搜索框的样式全部交给外面那层壳。
   ★★★ 2026-10-26 凡哥带截图：「期间」筛选器点开之后，里面那个
   「打字筛选…」搜索框被拉成了跟容器一样宽，盖住了右边「业务单元」
   那一栏、也压住了「搜索/导出」按钮。查下来是这条规则本身 ——
   `:not(#searchbar)` 里带了个 ID 选择器, **`:not()` 的特异性算的是
   它参数本身的特异性**, 所以这条选择器的特异性里混进了一个 ID,
   比 `.jg-ss.jg-ss-open .jg-ss-search`（三个类）那条还高, `width:100%`
   赢了 `select_search.js` 自己定的 `width:320px`。而 `.jg-ss-search`
   是 `position:fixed`, `width:100%` 算的是**整个视口**, 于是从筛选器
   那一格一路铺到视口右边缘。
   ★ 这条规则本来就不该管 `select_search.js` 的搜索浮层 —— 那层浮层
   自己有一套完整的尺寸（见下面 `.jg-ss` 那一段), 这里排除掉就好,
   不用再加 `!important` 比大小。 */
.jg-filter-select,
.jg-filter-item input:not(#searchbar):not(.jg-ss-search) {
    width: 100%;
    height: 34px;
    padding: 0 8px;
    border: 1px solid var(--color-base-200);
    border-radius: 4px;
    background: #fff;
    font-size: 13px;
    color: var(--color-base-700);
}
.jg-filter-select:focus,
.jg-filter-item input:not(#searchbar):not(.jg-ss-search):focus {
    outline: 2px solid #22c55e;
    outline-offset: -2px;
}
/* ★ `.jg-filter-search`（王欣怡 #251 那个独立文本框）2026-10-23 撤掉了——
   它和 `.jg-ss`（select_search.js）认同一个 `data-jg-search` 标记，
   两层一起挂上去就是吴凡在「利润表」截图里看到的「文本框 + 下拉 并排」。
   现在选项多的下拉统一交给 `.jg-ss` 那一套，类名和规则不再需要。 */

.jg-daterange { display: flex; gap: 6px; }
.jg-daterange-cell { flex: 1 1 0; min-width: 0; }
@media (prefers-color-scheme: dark) {
    .jg-filter-select, .jg-filter-item input:not(#searchbar) {
        background: var(--color-base-900);
        border-color: var(--color-base-700);
    }
}
/* 「显示数量 / 清空全部筛选」跟筛选排在一起，别浮到列表右上角 */
.jg-filter-actions {
    display: flex;
    flex-direction: row;
    gap: 8px;
    width: 100%;
    margin-top: 2px;
    background: transparent !important;
    border: 0 !important;
    padding: 0 !important;
}
.jg-filter-actions a, .jg-filter-actions button {
    font-size: 12px;
    padding: 4px 10px;
    border-radius: 4px;
}
/* 日期钻取搬进筛选块之后，排成一排小链接 */
.jg-date-item { flex: 0 0 auto !important; }
.jg-date-hierarchy {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 0 !important;
    min-height: 34px;
}
.jg-date-hierarchy a {
    padding: 4px 10px;
    border: 1px solid var(--color-base-200);
    border-radius: 4px;
    font-size: 13px;
    color: var(--color-base-700);
    text-decoration: none;
    white-space: nowrap;
}
.jg-date-hierarchy a:hover { border-color: #22c55e; color: #16a34a; }

/* ══════════════════════════════════════════════════════════
   跟哈他（sslx.me）对齐的骨架：160px 侧栏 + 52px 顶部条
   两个站以后可能合并，顶栏、侧栏、表格这些骨架保持一致 ——
   下面的数值都是从哈他线上量出来的，不是拍的。
   ══════════════════════════════════════════════════════════ */

/* ── 顶部条：52px 白底，tab + 右侧用户区 ───────────────────── */
.jg-top-nav {
    display: flex;
    align-items: stretch;
    height: 52px;
    /* 左 8px 跟内容区的左内边距同一个值 —— 第一个 tab 的左沿
       和下面表格卡片的左沿对齐，顶栏和内容区看着是一竖条。
       右 24px 跟哈他一致，「退出」的右外沿两边才对得齐。 */
    padding: 0 24px 0 8px;
    background: #fff;
    border-bottom: 1px solid var(--color-base-200);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
    position: sticky;
    top: 0;
    z-index: 50;
}
.jg-top-nav a.tab {
    display: flex;
    align-items: center;
    height: 100%;
    padding: 0 16px;
    font-size: 14px;
    color: var(--color-base-500);
    text-decoration: none;
    border-bottom: 3px solid transparent;
    transition: color .15s;
    white-space: nowrap;
}
.jg-top-nav a.tab:hover { color: #22c55e; }
.jg-top-nav a.tab.active {
    /* 跟侧栏选中项同一套配色：#dcfce7 底 + #15803d 字 */
    color: #15803d;
    background: #dcfce7;
    border-radius: 4px;
    font-weight: 600;
}
.jg-top-nav .right {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 13px;
}
.jg-top-nav .user-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--color-base-700);
    white-space: nowrap;
}
.jg-top-nav .avatar {
    width: 26px; height: 26px;
    background: #22c55e;
    color: #fff;
    border-radius: 50%;
    text-align: center;
    line-height: 26px;
    font-weight: 600;
    font-size: 12px;
}
.jg-top-nav .jg-top-link {
    color: var(--color-base-500);
    text-decoration: none;
    padding: 4px 10px;
    border: 1px solid var(--color-base-200);
    border-radius: 4px;
    white-space: nowrap;
}
.jg-top-nav .jg-top-link:hover {
    color: #16a34a;
    border-color: #22c55e;
    background: #f0fdf4;
}
@media (prefers-color-scheme: dark) {
    .jg-top-nav { background: var(--color-base-900); }
}

/* ── 列表表格：跟哈他一样紧凑 ─────────────────────────────── */
#result_list thead th {
    background: rgb(250, 250, 250);
    padding: 6px 8px !important;
}
#result_list tbody td,
#result_list tbody th { padding: 6px 8px !important; }
@media (prefers-color-scheme: dark) {
    #result_list thead th { background: var(--color-base-800); }
}

/* 侧栏 160px：菜单项与分组标题一律不换行。
   ★ 选择器必须落在 #nav-sidebar 上 —— 写 `aside a, nav a` 匹配不到，
     「供应商管理」被拆成「供应商管 / 理」两行。 */
#nav-sidebar a,
#nav-sidebar span,
#nav-sidebar h2,
#nav-sidebar h3 { white-space: nowrap; }
/* 收窄后左右内边距也要跟着收，否则文字还是顶到边 */
#nav-sidebar ul > li > a,
#nav-sidebar ol > li > a { padding-left: 12px; padding-right: 8px; }

/* ── 新建按钮（对齐哈他 .foodmax-addbtn）────────────────────
   绿底白字、90x36、圆角 6px，落在筛选卡右下角。
   .jg-addslot 是 header 里的隐藏槽，按钮被 filter_bar.js 搬走之后
   槽就空了；万一搬不走（页面没有筛选块），槽里那颗仍要能看见，
   所以这里不给槽设 display:none。 */
.jg-addslot { display: inline-flex; align-items: center; }

.jg-addbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 90px;
    height: 36px;
    padding: 0 16px;
    border-radius: 4px;
    background: #22c55e;
    color: #fff !important;
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}
.jg-addbtn:hover { background: #16a34a; }

/* 筛选卡最后一行：左边「清空筛选」等，右边新建 */
.jg-filter-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}
.jg-filter-actions .jg-addbtn { margin-left: auto; }

/* ── 列表行高对齐哈他（42px）────────────────────────────────
   量出来我们是 45、哈他 42。不是内边距的事（两边都是 6px/8px）——
   Unfold 直接在每个单元格上挂了字面类 h-[45px]。行里最高的一格
   内容才 36，所以 42 装得下，不会挤到任何东西。
   （查的办法：CDP 的 CSS.getMatchedStylesForNode，比对着猜快得多。） */
/* ★ 必须连 tbody th 一起 —— Django 把「可点进去的那一列」渲染成 <th>，
   只压 td 的话那一格仍然是 45，整行就跟着它 45。 */
#result_list tbody td,
#result_list tbody th { height: 42px !important; }

/* ── 剩下两处跟哈他的差值 ─────────────────────────────────── */

/* 侧栏底色：哈他 rgb(249,250,251)，我们默认是 rgb(250,250,250)。
   差一格灰阶，单看都正常，两个站并排开着就看得出来。 */
#nav-sidebar { background: rgb(249, 250, 251); }
@media (prefers-color-scheme: dark) {
    #nav-sidebar { background: var(--color-base-900); }
}

/* 搜索框：哈他 382x32，我们 320x35。
   宽度撑在外层包裹 div 上，只改 input 不动 —— 跟表单那边同一个坑。 */
#toolbar #searchbar {
    height: 32px !important;
    width: 382px !important;
    /* ★ 别写 max-width:100% —— 外层包裹是 w-80（320px），
       100% 就等于把宽度又压回 320，白设。 */
    max-width: none !important;
}
/* 包裹层跟着放开，否则输入框只是溢出，不是真的变宽 */
#toolbar div:has(> #searchbar),
#toolbar div:has(#searchbar) { width: auto !important; max-width: none !important; }

/* ── 侧栏与内容区之间的空隙 ───────────────────────────────
   Unfold 给内容区外层挂了 px-4（左右各 16px），侧栏右沿和表格左沿
   之间就空出一条。侧栏加宽到 200 之后这条更显眼 —— 收到 8px，
   两块连成一片。右侧不动，表格右边留白本来就该有。 */
.\@container.px-4 { padding-left: 8px !important; }

/* ── 右上角：通知铃铛 + 个人中心下拉 ───────────────────────
   把原来散在左上角（「我的通知」）和左下角（头像）的个人相关入口
   收到一处。侧栏留给业务菜单，个人的东西全在右上角。 */

.jg-top-nav .right { display: flex; align-items: center; gap: 6px; margin-left: auto; }

.jg-bell {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 4px;
    color: var(--color-font-default);
}
.jg-bell:hover { background: var(--color-base-100); }
.jg-bell .material-symbols-outlined { font-size: 18px; }
.jg-bell-dot {
    position: absolute;
    top: 1px;
    right: 0;
    min-width: 15px;
    height: 15px;
    padding: 0 3px;
    border-radius: 999px;
    background: #ef4444;
    color: #fff;
    font-size: 11px;
    line-height: 15px;
    text-align: center;
    font-weight: 600;
}

/* details/summary 做的下拉：不依赖 JS，键盘也能开 */
.jg-user { position: relative; }
.jg-user > summary {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 8px;
    border-radius: 4px;
    cursor: pointer;
    list-style: none;              /* 去掉浏览器默认的小三角 */
    font-size: 13px;
}
.jg-user > summary::-webkit-details-marker { display: none; }
.jg-user > summary:hover { background: var(--color-base-100); }
.jg-user .avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 999px;
    background: #22c55e;
    color: #fff;
    font-size: 12px;
    font-weight: 600;
}
.jg-user-caret { font-size: 18px; opacity: .55; }
.jg-user[open] .jg-user-caret { transform: rotate(180deg); }

.jg-user-menu {
    position: absolute;
    top: 38px;
    right: 0;
    min-width: 190px;
    padding: 4px;
    border: 1px solid var(--color-base-200);
    border-radius: 8px;
    background: #fff;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .10);
    z-index: 60;
}
.jg-user-head { padding: 8px 10px 10px; border-bottom: 1px solid var(--color-base-200); }
.jg-user-full { font-size: 13px; font-weight: 600; }
.jg-user-mail { font-size: 11px; color: var(--color-font-subtle); margin-top: 2px; }
.jg-user-menu a {
    display: block;
    padding: 8px 10px;
    border-radius: 4px;
    font-size: 13px;
    color: var(--color-font-default);
    text-decoration: none;
}
.jg-user-menu a:hover { background: var(--color-base-100); }
/* 退出是个 <button>（POST 表单），不是链接 —— 样式要跟上面两项一致，
   否则最后一项看着像另一个东西 */
.jg-user-menu form { margin: 0; }
.jg-user-menu .jg-user-out {
    display: block;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: 4px;
    background: none;
    font-size: 13px;
    text-align: left;
    color: #dc2626;
    cursor: pointer;
}
.jg-user-menu .jg-user-out:hover { background: var(--color-base-100); }

@media (prefers-color-scheme: dark) {
    .jg-user-menu { background: var(--color-base-900); }
}

/* 侧栏左下角那块用户信息 —— 内容已经搬到右上角，这里收掉。
   ★ 它是侧栏 nav 的最后一个直接子元素，没有稳定的类名可用；
     按「包含用户菜单按钮」来认，比按位置认稳。 */
#nav-sidebar > div:last-child:has(button[id*="user"]),
#nav-sidebar [class*="border-t"]:has(.truncate):last-child { display: none !important; }

/* ── 个人信息页 ─────────────────────────────────────────── */
.jg-me { padding: 16px 8px; }
.jg-me-card {
    max-width: 900px;
    padding: 20px 24px 24px;
    border: 1px solid var(--color-base-200);
    border-radius: 8px;
    background: #fff;
}
.jg-me-card h2 { font-size: 14px; font-weight: 600; margin: 18px 0 2px; }
.jg-me-card h2:first-child { margin-top: 0; }
.jg-me-hint { font-size: 12px; color: var(--color-font-subtle); margin-bottom: 12px; }
.jg-me-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px 16px; }
.jg-me-item { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.jg-me-wide { grid-column: 1 / -1; }
.jg-me-item label { font-size: 12px; color: var(--color-font-subtle); }
.jg-me-ro { font-size: 13px; padding: 7px 0; }
.jg-me-item input {
    height: 34px;
    padding: 0 10px;
    border: 1px solid var(--color-base-200);
    border-radius: 4px;
    font-size: 13px;
    background: #fff;
    width: 100%;
}
.jg-me-item input:focus { outline: 2px solid #86efac; outline-offset: -1px; }
.jg-me-err { font-size: 12px; color: #dc2626; }
.jg-me-actions {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-top: 22px;
    padding-top: 16px;
    border-top: 1px solid var(--color-base-200);
}
.jg-me-actions .jg-addbtn { border: 0; cursor: pointer; }
.jg-me-link { font-size: 13px; color: var(--color-font-subtle); }

@media (prefers-color-scheme: dark) {
    .jg-me-card, .jg-me-item input { background: var(--color-base-900); }
}

/* ── 二级页签 ───────────────────────────────────────────── */
.jg-sub-nav {
    display: flex;
    align-items: center;
    gap: 2px;
    height: 40px;
    padding: 0 8px;
    background: #fff;
    border-bottom: 1px solid var(--color-base-200);
}
.jg-sub-nav .sub {
    padding: 5px 12px;
    border-radius: 4px;
    font-size: 13px;
    color: var(--color-font-subtle);
    text-decoration: none;
    white-space: nowrap;
}
.jg-sub-nav .sub:hover { background: var(--color-base-100); }
.jg-sub-nav .sub.active {
    background: #f0fdf4;
    color: #15803d;
    font-weight: 500;
}
@media (prefers-color-scheme: dark) {
    .jg-sub-nav { background: var(--color-base-900); }
    .jg-sub-nav .sub.active { background: rgba(34, 197, 94, .18); color: #86efac; }
}

/* ── 搜索 + 筛选 + 操作：一张卡片（照哈他 foodmax-filter-topbar）──
   关键词是筛选网格的第一格，占两列宽；其余条件每格一列。
   底部一条分隔线，左「搜索」右「新建」。 */
.jg-filter-card {
    /* ★ 卡片被塞进一个 flex 行容器里（Unfold 的 toolbar 那层是
       sm:flex-row），作为 flex 子项它只会按内容撑开 —— 筛选少的页面
       就缩成半屏宽，右边空一大块。占满整行。 */
    width: 100%;
    flex: 1 0 100%;
    /* ★ 原来这里是 `margin: 12px -12px`，用来抵掉外层容器的 padding:12px
       （不抵的话卡片 221~1671、表格 209~1683，上下两块边不齐）。
       2026-09-05 去掉外层那圈边框时连它的 padding 一起清了，
       负 margin 就没东西可抵，卡片反而**比表格宽出 13px**（196~1696）——
       真浏览器量出来的。外层不再有 padding，这里也就不需要负 margin。 */
    margin: 12px 0;
    padding: 16px 20px;
    border: 1px solid var(--color-base-200);
    border-radius: 8px;
    background: #fff;
}
/* ★ 外面那一圈是 Unfold 自己给 toolbar 容器画的（`lg:border`），
   于是筛选区被**两圈边框**套着：我们的卡片 1px 圆角 8px，
   外面还有一圈 1px 圆角 6px，中间隔着 12px 的 padding。
   吴凡 2026-09-05 指出来的 —— 页面上看就是一个框套一个框。
   ★ 去掉外面那一圈，保留我们自己的卡片（它才是跟表格左右对齐的那个）。
   ★ 用 :has() 限定成「里面确实有我们卡片」的页面：没有筛选卡的页面
     （利润表这类没有 search_fields 的）上，Unfold 这圈边框是工具条
     唯一的边界，一刀切掉会让那些页面散架。
   ★ 选择器直接认「谁是卡片的爹」。第一版写成
     `.changelist-form-container > div:has(…)` 是错的：那层 div 中间还隔着
     一个 `.grow.min-w-0`，不是直接子元素，所以一条都没匹配上 ——
     而 CSS 匹配不上是**不报错的**，部署完页面纹丝不动，
     只有真浏览器量出来才知道。 */
div:has(> .jg-filter-card) {
    border: 0 !important;
    padding: 0 !important;
    margin-bottom: 0 !important;
    border-radius: 0 !important;
}
/* 标签在左、控件在右，一行一条 —— 原来标签压在控件上面，
   每个条件占两行高，五六个条件就把卡片撑得很厚。
   横排之后同样的条件只占一半的高度。 */
.jg-filter-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 10px 20px;
}
.jg-filter-card .jg-filter-item {
    display: flex;
    flex-direction: row;      /* 左右排 */
    align-items: center;
    gap: 8px;
    min-width: 0;
}
.jg-filter-card .jg-search-cell { grid-column: span 2; }
.jg-filter-card .jg-filter-item > label {
    flex: 0 0 auto;
    min-width: 56px;
    font-size: 13px;
    color: var(--color-font-default);
    line-height: 32px;
    white-space: nowrap;
}
/* 控件吃掉标签之外的所有宽度 */
.jg-filter-card .jg-filter-item > select,
.jg-filter-card .jg-filter-item > form,
.jg-filter-card .jg-filter-item > #toolbar { flex: 1 1 auto; min-width: 0; }
.jg-filter-card .jg-filter-item select {
    width: 100%;
    height: 32px;
    padding: 0 8px;
    border: 1px solid var(--color-base-200);
    border-radius: 4px;
    background: #fff;
    font-size: 13px;
}
/* 搜索框回到跟其他控件一样的高度和宽度 —— 它现在是网格里的一格，
   不再需要之前那条 382px 的固定宽度 */
.jg-filter-card #toolbar #searchbar { height: 30px !important; width: 100% !important; }
.jg-filter-card #toolbar > form > div { width: 100%; }

.jg-filter-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--color-base-200);
}
/* 搜索按钮 —— 09-21 吴凡拍板: 实心绿 → **描边次操作**。两站同时改。
 *
 * 机检 B-01「一屏只允许 1 个实心主按钮」报了 72 页(占全部建议 28%),
 * 根因不是谁做错了, 是规范第 5 节的按钮表只列了三类 ——
 * 主操作(保存/新建) / 次操作(取消/导出) / 危险操作, **「搜索」一类都不沾**:
 * 它既不提交也不是取消。规范没说, 两站就各自理解成了实心主按钮。
 *
 * 定成次操作的理由: 搜索是可重复、无副作用的取数动作, 不改变任何数据;
 * 而 B-01 要保护的是「这一屏你最该点的那一个」—— 列表页上那一个是「新建」。
 *
 * ★ 只改配色, 高度 36 / 圆角 4 / 字号 13 一个不动。
 *   哈他对应的是 foodmax-theme.css 的 .foodmax-search-btn, 同日同样改法。 */
.jg-searchbtn {
    height: 36px;
    min-width: 90px;
    padding: 0 16px;
    border: 1px solid #22c55e;
    border-radius: 4px;
    background: #fff;
    color: #22c55e;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
}
.jg-searchbtn:hover { background: #f0fdf4; border-color: #16a34a; color: #16a34a; }
.jg-filter-extra { display: flex; align-items: center; gap: 12px; font-size: 12px; }

@media (prefers-color-scheme: dark) {
    .jg-filter-card,
    .jg-filter-card .jg-filter-item select { background: var(--color-base-900); }
}

/* 日期区间：两个日期框 + 一个「至」，占两列（跟关键词一样宽） */
.jg-filter-card .jg-date-range { grid-column: span 2; }
.jg-filter-card .jg-date-range > .jg-range { flex: 1 1 auto; min-width: 0; }
.jg-range { display: flex; align-items: center; gap: 6px; }
.jg-range input[type="date"] {
    flex: 1;
    min-width: 0;
    height: 32px;
    padding: 0 8px;
    border: 1px solid var(--color-base-200);
    border-radius: 4px;
    background: #fff;
    font-size: 13px;
}
.jg-range-sep { font-size: 12px; color: var(--color-font-subtle); }
@media (prefers-color-scheme: dark) {
    .jg-range input[type="date"] { background: var(--color-base-900); }
}

/* 搜索框里那个「/」快捷键徽标是个带边框的小方块，套在搜索框里面，
   看着像「搜索框里还有一个搜索框」。快捷键本身留着（键盘照样能用），
   只是不再画出来。 */
.jg-filter-card #toolbar kbd { display: none !important; }

/* ── 空状态：说清为什么空 ─────────────────────────────────── */
.jg-empty-scope { font-size: 13px; color: var(--color-font-subtle); }
.jg-empty-pools {
    margin-top: 18px;
    padding: 14px 16px;
    border: 1px solid var(--color-base-200);
    border-radius: 8px;
    background: var(--color-base-50);
    max-width: 640px;
}
.jg-empty-pools-title { font-size: 13px; font-weight: 600; margin-bottom: 8px; }
.jg-empty-pools table { width: 100%; font-size: 13px; border-collapse: collapse; }
.jg-empty-pools th {
    text-align: left;
    font-weight: 500;
    color: var(--color-font-subtle);
    padding: 4px 8px;
    border-bottom: 1px solid var(--color-base-200);
}
.jg-empty-pools td { padding: 4px 8px; }
.jg-empty-pools .num { text-align: right; font-variant-numeric: tabular-nums; }
.jg-empty-pools .neg { color: #dc2626; }
.jg-empty-pools-note {
    margin-top: 10px;
    font-size: 12px;
    color: var(--color-font-subtle);
    line-height: 1.6;
}
@media (prefers-color-scheme: dark) {
    .jg-empty-pools { background: var(--color-base-900); }
}

/* ── 列表第一列是「点进去看详情」的入口，要看得出能点 ──────
   张丽博 2026-09-01 的原话是「销售单据无查看按钮，不能查看已录入单据」——
   其实点最前面的单号就能进去，但那一列渲染成和别的格子一样的黑字，
   完全看不出是个链接，所以没人会去点。
   （哈他那边也是黑字，这条不照抄它。）

   默认：加粗，和哈他的字重一致，安静但有分量。
   悬停：变绿加下划线，整行也跟着浅一层底色 —— 鼠标扫过去就知道点哪。 */
#result_list tbody th a,
#result_list tbody td a {
    font-weight: 600;
    cursor: pointer;
}
#result_list tbody th a:hover,
#result_list tbody td a:hover {
    color: #15803d;
    text-decoration: underline;
    text-underline-offset: 2px;
}
#result_list tbody tr:hover { background: #f6fdf8; }
#result_list tbody tr:hover th a { color: #15803d; }

@media (prefers-color-scheme: dark) {
    #result_list tbody tr:hover { background: rgba(34, 197, 94, .08); }
    #result_list tbody th a:hover,
    #result_list tbody td a:hover,
    #result_list tbody tr:hover th a { color: #86efac; }
}

/* 导出按钮：跟「新建」并排，但不是主操作，所以用描边不用实心 */
.jg-exportbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 78px;
    height: 36px;
    padding: 0 14px;
    border: 1px solid var(--color-base-200);
    border-radius: 4px;
    background: #fff;
    font-size: 13px;
    color: var(--color-font-default);
    text-decoration: none;
    white-space: nowrap;
}
.jg-exportbtn:hover { border-color: #22c55e; color: #15803d; }
/* 「导出」和「新建」一起推到最右并排 —— 使用者要求「位置都靠近最右侧
   的新建按钮」。左边只留「搜索」。 */
/* ★ 右侧按钮要**成组**：只有第一个吃掉左边的空白，后面的紧挨着排。
   原来每个 .jg-exportbtn 都是 margin-left:auto —— flex 里两个 auto
   会把剩余空间对半分，于是「导出」孤零零飘在正中间，
   「导入 / 新建」在最右边，看着像两组不相干的按钮。
   用户 2026-09-02：「导出按钮靠近导入摆放」。 */
.jg-filter-actions .jg-exportbtn { margin-left: 8px; }
.jg-filter-actions .jg-exportbtn:first-of-type { margin-left: auto; }
.jg-filter-actions .jg-exportbtn + .jg-addbtn { margin-left: 8px; }
.jg-filter-actions .jg-addbtn:first-child { margin-left: auto; }

/* ★★★ 「搜索」也靠右，跟在筛选条右端（吴凡 2026-09-24：「搜索和新建的按钮
   位置看看大多 ERP 网站怎么摆放的，方便用户使用」）。

   原来搜索孤零零在左下角，而人是从左上往右下把筛选填完的 ——
   填完最后一格，手在右下，按钮却在屏幕另一头（实测两者相距 800px）。
   主流中后台（Ant Design Pro 的 QueryFilter、用友、金蝶、SAP Fiori 的
   筛选条）都是**查询按钮跟在筛选区右下角、主操作在最右**。
   本仓库的规范 §3.1 其实早就这么写着：`[搜索][重置][导出][+ 新建]` ——
   这一页只是没照着做。

   ★ 顺序上「搜索」在这一组最左、「新建」在最右，中间隔开一段：
     两者一个是"查我要的"、一个是"建一张新的"，挨太近会点错，
     而「新建」在工作台里会开一个新页签，点错了还得关。 */
.jg-filter-actions .jg-searchbtn {
    margin-left: auto;      /* 它来吃掉左边的空白 */
    margin-right: 20px;     /* 跟导出/导入/新建那一组拉开距离 */
}
/* 有搜索按钮时，右侧那一组就不再各自吃空白了（两个 auto 会把空间对半分，
   09-02 就是那样让「导出」飘在正中间的）。 */
.jg-filter-actions .jg-searchbtn ~ .jg-exportbtn:first-of-type { margin-left: 0; }
.jg-filter-actions .jg-searchbtn ~ .jg-addbtn { margin-left: 0; }

/* 表单页的「取消」：安静的文字链，离「保存」最远 */
.jg-cancel {
    display: inline-flex;
    align-items: center;
    height: 38px;
    padding: 0 12px;
    font-size: 13px;
    color: var(--color-font-subtle);
    text-decoration: none;
}
.jg-cancel:hover { color: #dc2626; text-decoration: underline; }

@media (prefers-color-scheme: dark) {
    .jg-exportbtn { background: var(--color-base-900); }
}

/* 未保存行的「移除」—— 安静的小字，别做成显眼的删除按钮，
   免得跟「停用」混淆（已保存的记录只能停用，不能删） */
.jg-row-remove {
    margin-left: 8px;
    font-size: 12px;
    color: var(--color-font-subtle);
    text-decoration: none;
    white-space: nowrap;
}
.jg-row-remove:hover { color: #dc2626; text-decoration: underline; }

/* 已保存行的「删除」—— 走 Django 自己的 DELETE 复选框（见
   inline_remove.js 的 addDeleteLink）。做成跟「移除」一样的安静小字，
   但**勾上之后整行画成划掉的**：删除是保存那一刻才发生的，
   在此之前必须一眼看得出「这几行我打算删」，否则人会以为已经删了、
   直接关掉页面。 */
.jg-row-delete {
    margin-left: 8px;
    font-size: 12px;
    color: var(--color-font-subtle);
    text-decoration: none;
    white-space: nowrap;
}
.jg-row-delete:hover { color: #dc2626; text-decoration: underline; }
tr.jg-row-doomed { opacity: .45; }
tr.jg-row-doomed td { text-decoration: line-through; }
/* 划掉的是数据，不是那个「撤销删除」按钮 —— 它得留着能看清 */
/* 没有删除权限时给已保存行的提示 —— 灰字，不是按钮，
   点不了但看得见（见 inline_remove.js 的 hintDisable） */
.jg-row-hint {
    margin-left: 8px;
    font-size: 11px;
    color: var(--color-font-subtle);
    white-space: nowrap;
}

tr.jg-row-doomed .jg-row-delete {
    text-decoration: none;
    opacity: 1;
    color: #dc2626;
}

/* 登记付款的三个选项 */
.jg-pay-modes { display: flex; flex-direction: column; gap: 8px; font-size: 13px; }
.jg-pay-modes label { display: flex; align-items: center; gap: 8px; font-weight: 400; }

/* 撤销付款这类高风险确认页 */
.jg-warn { color: #d97706; }
.jg-danger { background: #dc2626 !important; }
.jg-danger:hover { background: #b91c1c !important; }
.jg-void-list { width: 100%; font-size: 13px; border-collapse: collapse; margin-top: 8px; }
.jg-void-list th {
    text-align: left; font-weight: 500; color: var(--color-font-subtle);
    padding: 4px 8px; border-bottom: 1px solid var(--color-base-200);
}
.jg-void-list td { padding: 4px 8px; }
.jg-void-list .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ── 内联表：像 Excel 一样一行就是一行 ─────────────────────
   Unfold 的表格里塞了两样东西，把每行撑成三行高：一条移动端汇总行
   （「复制 侯菊桃(W0003) ¥90.76」，它只在小屏上有意义），
   以及每行一个「复制整行」链接。加行用「添加另一个」就够了。
   标记由 inline_remove.js 打上（那两样东西都没有可用的类名）。 */
@media (min-width: 1024px) {
    tr.jg-mobile-only { display: none !important; }
}
.jg-inline-copy { display: none !important; }

/* 行高压到一行：Unfold 给每格设了 min-h-[62.5px] */
[id$="-group"] tbody tr.form-row > td,
[id$="-group"] tbody tr.form-row > th {
    min-height: 0 !important;
    padding-top: 4px !important;
    padding-bottom: 4px !important;
    vertical-align: middle;
}
[id$="-group"] tbody tr.form-row input:not([type="checkbox"]),
[id$="-group"] tbody tr.form-row select {
    height: 32px;
}
/* ★ 光把高度压到 32px 会把字的下沿切掉：unfold 给 select 的
   padding 是按更高的行设的，压扁之后基线偏下，「kg」的 g、
   「份」的撇都会被裁一截 —— 吴凡 2026-09-04 截图里那个「kα」
   就是这么来的（其实是 kg）。
   ★ 单位这一列尤其要命：kg / 斤 / 只 / 条 / 个 差一笔就是另一个单位，
     而 09-01 刚因为「元/kg 乘了份数」把 9 万行成本算错过。
     下沿被裁的字，人是靠猜在读。 */
[id$="-group"] tbody tr.form-row select {
    line-height: 30px;
    padding-top: 0;
    padding-bottom: 0;
}
/* select2 自己画的那个框也要跟着收，否则行还是被它撑高 */
[id$="-group"] tbody tr.form-row .select2-selection,
[id$="-group"] tbody tr.form-row .select2-container { height: 32px !important; }
[id$="-group"] tbody tr.form-row .select2-selection__rendered {
    line-height: 30px !important;
}
/* 「移除」跟备注框并排，不另起一行 —— 它单独占一行时每行高 60px，
   并排之后就是一行的高度。 */
[id$="-group"] tbody tr.form-row .field-remark {
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}
/* ★ min-width 不能是 0 —— 备注是最后一列、又要和「移除」并排，
   flex 会把它压到 26px 宽，看着像个不能填的小方块
   （张丽博 2026-09-01：「单据内备注栏不能编辑」，其实是挤没了）。
   给个保底宽度，宁可这一列宽一点。 */
[id$="-group"] tbody tr.form-row .field-remark input {
    flex: 1 1 auto;
    min-width: 120px;
}
[id$="-group"] tbody tr.form-row .field-remark .jg-row-remove { flex: 0 0 auto; }

/* 「操作记录」跟「取消」并排，但它不是危险操作 —— 悬停不变红 */
.jg-history:hover { color: #15803d !important; }

/* 列表里「付款状态」后面那个付款入口 */
.jg-pay-link {
    display: inline-block;
    margin-top: 2px;
    padding: 1px 8px;
    border: 1px solid #22c55e;
    border-radius: 4px;
    font-size: 11px;
    color: #15803d;
    text-decoration: none;
    white-space: nowrap;
}
.jg-pay-link:hover { background: #22c55e; color: #fff; }

/* ── 采购明细：供应商「带出来的 vs 认过的」 ──────────────────
   灰色斜体 = 从单头带下来、还没人确认；黑色 = 采购确认过。
   见 supplier_confirm.js 里的说明。 */
.field-supplier.jg-sup-auto .select2-selection__rendered,
.field-supplier.jg-sup-auto select {
    color: #9ca3af !important;
    font-style: italic;
}
/* 明细行的供应商下拉（2026-09-03 从 select2 换成按商品收窄的原生下拉，
   见 NarrowedSupplierSelect）。

   ★ 必须给一个最小宽度。原生 select 在 flex 行里会被旁边的「确认」按钮
     和「可从 N 家拿」提示挤成一格，「舟山水产档口」显示成「舟…」——
     采购根本认不出选中的是哪家，而页面上一点异常都看不出来。
     ★ 11em 不够 —— 吴凡 2026-09-04 截图上「渔获农业发展（江苏）有限公司」
       显示成「渔获农业发展…」，14 个字砍掉一半。公司全名普遍是
       「XX农业发展（省份）有限公司」这个形状，前 11 个字里省份和公司性质
       全看不到，而同一个集团下常有好几家只差省份的公司 ——
       截断之后**两家看起来一模一样**。放到 16em。
     ★ 明细表本来就横向可滚，加宽不会挤坏别的列。 */
#items-group .field-supplier .jg-sup-select {
    min-width: 16em;
    max-width: 100%;
}
.jg-sup-ok {
    margin-left: 4px;
    padding: 1px 6px;
    font-size: 11px;
    line-height: 16px;
    border: 1px solid #d1d5db;
    border-radius: 4px;
    background: #fff;
    color: #d97706;
    cursor: pointer;
    white-space: nowrap;
}
.jg-sup-ok:hover { background: #fffbeb; border-color: #f59e0b; }
.jg-sup-ok.is-ok {
    color: #16a34a;
    border-color: transparent;
    background: transparent;
    cursor: default;
}
/* 「供应商已确认」是脚本用的开关，不给人看 —— 摆出来只会让人以为要自己勾。
   th 和 td 都要藏，只藏一边表格会错位一列。 */
.jg-has-supconfirm .field-supplier_confirmed,
.jg-has-supconfirm th.column-supplier_confirmed { display: none !important; }
/* 这个品还能从哪几家拿 —— 只提示，不替采购挑。
   跟「确认」按钮一样挂在 unfold 的 flex 行里，跟供应商同一行，
   不另起一行（另起一行会把行高从 47px 顶到 114px）。全名在 title 里。 */
.jg-sup-hint {
    margin-left: 4px;
    font-size: 11px;
    line-height: 15px;
    color: #6b7280;
    white-space: nowrap;
    cursor: help;
}

/* ── 加工单「批次余量」列 ────────────────────────────────
   这列 unfold 只给了 68–79px，「剩 8300.00 kg」被折成三行；再叠一句
   0 成本的红字就断成 5 行、行高 59px→102px。而实测 10 个批次 9 个是
   0 成本 —— 常态不是边角，一铺整张表就散了。
   给够宽度 + 不折行，警告压成一个小标记（整句在 title 里）。 */
.field-stock_ro { min-width: 150px; }
.jg-batch-left { white-space: nowrap; }
.jg-nocost {
    margin-left: 4px;
    padding: 0 4px;
    font-size: 11px;
    line-height: 16px;
    color: #b91c1c;
    background: #fef2f2;
    border: 1px solid #fecaca;
    border-radius: 4px;
    white-space: nowrap;
    cursor: help;
}

/* ── 可多选的筛选器（销售渠道）────────────────────────────
   Django 自带的外键筛选天生单选。这个是勾选式的，
   每一项点一下切换「加进来 / 去掉」。渠道有 20 多个，
   要看「哈他那几家加起来」时不用来回切二十次。 */
.jg-multi-filter { font-size: 13px; }
.jg-multi-title { color: var(--color-base-500); margin-bottom: 4px; }
.jg-multi-list {
    max-height: 190px;
    overflow-y: auto;
    border: 1px solid var(--color-base-200);
    border-radius: 4px;
    padding: 2px;
    background: #fff;
}
.jg-multi-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 6px;
    border-radius: 4px;
    color: inherit;
    text-decoration: none;
    white-space: nowrap;
}
.jg-multi-item:hover { background: var(--color-base-100); }
.jg-multi-item.is-on { color: #16a34a; font-weight: 600; }
.jg-multi-box {
    width: 14px; height: 14px; flex: none;
    border: 1px solid var(--color-base-300);
    border-radius: 4px;
    font-size: 11px; line-height: 12px; text-align: center;
}
.jg-multi-item.is-on .jg-multi-box {
    border-color: #16a34a; color: #16a34a;
}
/* 搜索框 —— 刘晓缤 2026-09-03：「一个一个找渠道比较麻烦」 */
.jg-multi-search {
    width: 100%;
    box-sizing: border-box;
    margin-bottom: 4px;
    padding: 3px 8px;
    font-size: 13px;
    line-height: 20px;
    border: 1px solid var(--color-base-200);
    border-radius: 4px;
    background: #fff;
}
.jg-multi-search:focus {
    outline: none;
    border-color: #22c55e;
}
/* 加工人工「这一组还有谁」：勾选框列表，装进一个能滚的小框里。
   ★ 原来用原生 <select multiple>，要按住 ctrl/⌘ 才能点第二个，
     在表格单元格里只露两行高 —— 鲁纪念 2026-09-03：
     「还是不能多选，确认不了」。 */
.jg-people-pick {
    max-height: 132px;
    overflow-y: auto;
    min-width: 150px;
    padding: 2px 4px;
    border: 1px solid var(--color-base-200);
    border-radius: 4px;
    background: #fff;
    font-size: 12px;
    line-height: 1.7;
}
.jg-people-pick li { list-style: none; white-space: nowrap; }
.jg-people-pick label { display: flex; align-items: center; gap: 4px; }

/* 搜索状态下，「全部」这一项变成「全选搜到的 N 个」—— 标绿，
   跟它平时「清空筛选」的意思区分开 */
.jg-multi-item.is-pickall { color: #16a34a; font-weight: 600; }
.jg-multi-item.is-pickall .jg-multi-box { border-color: #16a34a; }
.jg-multi-empty {
    padding: 4px 6px;
    font-size: 12px;
    color: var(--color-base-400);
}

/* ── 登记付款：一张单一行，各自填各自的金额 ────────────────
   刘晓缤 2026-09-02：「三张采购单每个的付款金额是不一样的」。 */
.jg-pay-table {
    width: 100%;
    margin: 14px 0;
    border-collapse: collapse;
    font-size: 13px;
}
.jg-pay-table th,
.jg-pay-table td {
    padding: 7px 10px;
    border-bottom: 1px solid var(--color-base-200);
    text-align: left;
}
.jg-pay-table th {
    color: var(--color-base-500);
    font-weight: 600;
    white-space: nowrap;
}
.jg-pay-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.jg-pay-table .sub { color: var(--color-base-500); font-size: 11px; }
.jg-pay-table .owe { color: #d97706; font-weight: 600; }
.jg-pay-input {
    width: 120px;
    padding: 4px 8px;
    text-align: right;
    border: 1px solid var(--color-base-300);
    border-radius: 4px;
    font-variant-numeric: tabular-nums;
}
.jg-pay-input:focus { border-color: #22c55e; outline: none; }

/* 按品找资源：那一行搜索框 */
.jg-find-bar { display: flex; gap: 10px; margin: 12px 0 4px; }
.jg-find-input {
    flex: 1;
    max-width: 340px;
    padding: 7px 12px;
    font-size: 14px;
    border: 1px solid var(--color-base-300);
    border-radius: 4px;
}
.jg-find-input:focus { border-color: #22c55e; outline: none; }
.jg-find-bar .jg-addbtn { border: 0; cursor: pointer; }

/* 已付清的「付款」按钮：灰掉，但**留在原位**。
   拿掉的话人会以为「这单怎么没有付款入口」；灰着并带一句说明，
   才知道是已经付完了。刘晓缤 2026-09-02。 */
.jg-pay-done {
    color: var(--color-base-400) !important;
    border-color: var(--color-base-200) !important;
    background: var(--color-base-50) !important;
    cursor: not-allowed;
    pointer-events: auto;          /* 还要能显示 title 提示 */
}


/* ── 只读字段里的宽表格：冲掉 Unfold 的 max-w-2xl ─────────────
   Unfold 把只读字段包在 .readonly.max-w-2xl 里（42rem 上限）——
   一张五列的横向表格塞进去只能占半屏，右边空一大片。
   用户 2026-09-02：「拉满红色框的表单设计模式」。
   ★ 只对显式标了 .jg-wide 的那几块生效，不动其余只读字段：
     那个 42rem 上限对大段文字是对的（一行八十个字没法读）。 */
.readonly:has(> .jg-wide) { max-width: none !important; }
.jg-wide { width: 100%; }


/* ── 采购明细：几列填的是名字，别挤成三个字 ──────────────────
   用户 2026-09-03：「二级类目 选择后显示不全」「产地，代办人…显示不全」。
   截图里「宝山加工—1」只显示成「宝山加」、「福建罗田」成了「福建罗」——
   录的时候看不出自己选的是哪一个，那这一列就等于没用。

   ★ 给的是 min-width 不是固定宽：内容短的时候还是让浏览器自己收窄，
     整表不会因此横向撑爆。
   ★ 只在宽屏生效（≥1280）—— 小屏上本来就要横滚，
     再压其它列只会更难用。 */
@media (min-width: 1280px) {
    [id$="-group"] tbody tr.form-row .field-category input,
    [id$="-group"] tbody tr.form-row .field-origin input,
    [id$="-group"] tbody tr.form-row .field-agent input {
        min-width: 110px;
    }
    [id$="-group"] tbody tr.form-row .field-category,
    [id$="-group"] tbody tr.form-row .field-origin,
    [id$="-group"] tbody tr.form-row .field-agent { min-width: 118px; }
}

/* ── 明细表的数字框：别把数字裁掉 ────────────────────────────
   张国庆 2026-09-18（#268 隔壁那条 #267）：「采购金额修改全部显示，
   目前仅显示出小数点后一位」。

   ★★★ 它不是格式化出错，是**框太窄**：Unfold 给内联表里的 input 的是
     `w-full min-w-20`（80px，去掉左右各 12px 的 padding 和 1px 边框，
     真正能显示的只剩 78px）。13px 下一个数字约 7.8px，**8 位就超了**：
     `53306.02` 要 86px，于是尾巴上的 `2` 被裁在框外 ——
     而框里剩下的 `53306.0` **还是一个合法的数**，
     人不会觉得它被截断了，只会以为系统把金额改错了。
     （同一条教训 ui-tokens.css:562 已经吃过一次：金额被冻结列盖住半截，
      `¥1,674.00` 剩下 `.00` 照样像个数。数字这一类，
      **裁掉一截比整格空着危险**。）

   ★ 为什么是 116px：正式站 16.9 万行采购明细，金额 8 位的有 49,468 行
     （29%）、9 位 3,222 行、最长 10 位（¥1,197,327.58）。
     116px 去掉 padding + 边框剩 90px ≈ 11 位，把 10 位那一档整个盖住。
   ★ 为什么连单价/数量/重量一起给：它们跟金额挤在同一排、同样是
     `min-w-20`，单价 4 位小数（`97695.0000` 10 位）、数量最大 205,296，
     裁起来一模一样。只修被报的那一格，下一个人明天报的就是隔壁那格。
   ★ 只作用于 `#items-group`（采购明细 / 辅料采购明细 / 销售明细）。
     加工单的 inputs/outputs 表 2026-09-12 起冻结，改宽也算改它的样子，
     要动得吴凡本人点头（docs/UI_COLLAB.md 二之二）。
   ★ 给的是 min-width，列宽仍由表格自己算；表本来就在可横滚的容器里
     （T-04），宽出来的这一截不会压到别的列身上。
   ★ **不分宽窄屏**：隔壁那条「名字列别挤成三个字」只在 ≥1280 生效，
     窄屏上挤一挤还认得出是哪一个；数字不行 —— 窄屏上裁掉的那一位
     照样是一个看不出来的错数。 */
#items-group tbody tr.form-row .field-amount_input input,
#items-group tbody tr.form-row .field-unit_price input,
#items-group tbody tr.form-row .field-qty input,
#items-group tbody tr.form-row .field-weight_kg_override input,
#items-group tbody tr.form-row .field-settle_price input,
#items-group tbody tr.form-row .field-settle_amount input,
#items-group tbody tr.form-row .field-plan_weight input,
#items-group tbody tr.form-row .field-ship_weight input,
#items-group tbody tr.form-row .field-settle_weight input {
    min-width: 116px;
}

/* ── 日历弹层：年 / 月 两个下拉 ──────────────────────────────
   刘家乐 2026-09-03：「添加供应商合同、营业执照等资料没有年份选择选项，
   只能按月一个一个去翻」。控件逻辑在 static/jg/date_year_month.js。

   ★ 原来那行「九月 2026」的说明文字（table caption）藏起来 ——
     下拉里写的就是同一个年月，两处并排显示只是把弹层撑高一截，
     人还得分辨哪个能点。位置没变，只是把「只能看」换成了「能选」。 */
.calendarbox .jg-ym {
    display: flex;
    justify-content: center;
    gap: 8px;
    /* 左右留出 36px：翻页的 ‹ › 是绝对定位钉在两个角上的，
       不留位置会被下拉压在底下点不着 */
    padding: 10px 36px 2px;
}
.calendarbox .jg-ym select {
    height: 28px;
    padding: 0 6px;
    font-size: 12px;
    border-radius: 4px;
    border: 1px solid var(--color-base-200);
    background: var(--color-white);
    color: var(--color-base-700);
    cursor: pointer;
}
.calendarbox .jg-ym select:focus {
    outline: 2px solid #86efac;
    outline-offset: -1px;
}
/* ★★★ 只有**年月下拉真的插上了**才藏掉原生的标题。
   2026-09-09 张丽博报的那条（日期弹层标题整行空白、‹ › 压在星期上）
   就是这里：原来无条件 `display:none`，是按「下拉一定插得上」写的。
   而那天三个日历框一个都没被增强 —— 于是标题凭空消失，
   页面上看不出是 JS 没跑，只看得到一个坏掉的日历。

   ★ `:has()` 让 CSS 自己去问「下拉在不在」，而不是替 JS 打包票。
     JS 再坏一次，最坏也只是回到原生的「九月 2026」，不是一片空白。 */
.calendarbox:has(.jg-ym) .calendar caption { display: none; }

@media (prefers-color-scheme: dark) {
    .calendarbox .jg-ym select {
        border-color: var(--color-base-700);
        background: var(--color-base-800);
        color: var(--color-base-200);
    }
}

/* ── 导出字段勾选面板（柳明珠 2026-09-07）─────────────────────
   「导出时可以自行选择表内的全部字段，不选择默认为全部字段导出」。

   ★ 悬浮在导出按钮下方，不挤走筛选卡上原有的东西 ——
     那一行已经排了搜索、筛选、导出、导入、新建五样。
   ★ 字段多（员工档案 50 多个）所以列表要能滚，面板本身不长高：
     一个撑满整屏的面板会把下面的列表整个盖住。 */
.jg-fieldpick {
    position: absolute; z-index: 40; margin-top: 6px;
    min-width: 320px; max-width: 460px;
    background: var(--color-base-50, #fff);
    border: 1px solid rgba(0,0,0,.12); border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,.12); padding: 12px 14px;
    font-size: 13px;
}
.jg-fp-head { margin-bottom: 8px; position: relative; padding-right: 22px; }
.jg-fp-head span { display: block; opacity: .55; font-size: 12px; margin-top: 2px; }
/* ★ 关闭叉（#125 张国庆：「能不能设置一个关闭的功能」）。
   原来只能再点一次「导出」把面板收回去 —— 而那个按钮此时被面板盖住
   一半，人只会以为卡死了。ESC 和点面板外面也都能关，见 filter_bar.js */
.jg-fp-x { position: absolute; top: -2px; right: -4px;
           width: 22px; height: 22px; line-height: 20px; text-align: center;
           cursor: pointer; border-radius: 4px; font-size: 16px;
           opacity: .45; }
.jg-fp-x:hover { opacity: .9; background: rgba(0,0,0,.06); }
/* ★★ 这次到底导几行 —— #124 的根子不是导错了，
   是人不知道那个按钮不看勾选。现在它看了，就更要说清楚看到了几行。 */
.jg-fp-head .jg-fp-scope { opacity: .9; color: #16a34a; margin-top: 4px; }
.jg-fp-tools { display: flex; gap: 14px; margin-bottom: 8px; }
.jg-fp-tools a { cursor: pointer; color: #16a34a; font-size: 12px;
                 border-bottom: 1px dashed currentColor; }
.jg-fp-list { max-height: 300px; overflow-y: auto;
              display: grid; grid-template-columns: 1fr 1fr; gap: 2px 10px;
              border-top: 1px solid rgba(0,0,0,.06);
              border-bottom: 1px solid rgba(0,0,0,.06);
              padding: 8px 0; margin-bottom: 10px; }
.jg-fp-list label { display: flex; align-items: center; gap: 6px;
                    white-space: nowrap; overflow: hidden;
                    text-overflow: ellipsis; cursor: pointer; }
.jg-fp-list input { margin: 0; }
.jg-fp-go { padding: 6px 22px; background: #22c55e; color: #fff;
            border: 0; border-radius: 4px; cursor: pointer; font-size: 13px; }

/* ══════════════════════════════════════════════════════════
   列表页勾选框：选中了就得看得出来
   ══════════════════════════════════════════════════════════
   2026-09-11 柳明珠(#72) + 王欣怡(#77) 都报「采购单已选中，
   但方框内没有对勾」。

   真凶在 ui-tokens.css：
       #result_list tbody td input:focus { background: var(--c-surface) !important }
   真鼠标点一下勾选框，它会**获得焦点**，这条 !important 就把背景刷成白色，
   盖掉了 Tailwind 的 checked:bg-primary-600 —— 框逻辑上是选中的
   （底下计数器也在动、行也变色），视觉上却还是个空白方框。

   ★★ 我第一轮用 JS 的 cb.click() 试，那**不产生焦点**，所以测出来一切正常，
      差点把这条反馈当成「用户点错地方了」关掉。
      **验 UI 要用真鼠标事件 —— JS 触发绕过的正是出问题的那一半。**

   ★★★ 为什么改在这儿而不是去 ui-tokens.css 改：
      那个文件是**从哈他仓库生成**的（scripts/deploy_ui_tokens.sh 从
      $HATA_DIR 取源），在全年这边改下次生成就没了；而哈他不归这个窗口动。
      所以在全年自己的 theme.css 里用**更高优先级**盖回来。
      ★ theme.css 比 ui-tokens.css **先**加载，所以同优先级盖不住 ——
        这里靠选择器更具体（多一个属性选择器 + 一个伪类）取胜。
      ★ 根治要在哈他那份源文件上把 checkbox/radio 排除掉，已写进 UI_HANDOFF。
   ────────────────────────────────────────────────────────── */
#result_list tbody td input[type="checkbox"]:checked,
#result_list tbody td input[type="checkbox"]:checked:focus,
#result_list tbody td input[type="checkbox"]:checked:hover {
  background: var(--c-primary) !important;
  border-color: var(--c-primary) !important;
}

/* ── 加工人工「这一组还有谁」：收起 + 搜索（#183，吴凡 2026-09-16 定） ──
   原来几十个工人名字平铺在表格单元格里，把那一列撑得很高，还没法搜。
   ★ 收起时只露触发条；展开的列表**浮在上面**（absolute）——
     嵌在单元格里的话，展开又会把那一行撑高，等于没收。 */
/* ★★ 一律写 `div.jg-people-pick`：Django 的 CheckboxSelectMultiple 把
   widget 的 attrs 发给**每一个 <input>**，所以这个 class 同时落在
   2 个容器和 148 个勾选框上（09-16 实测）。不限定标签的话，
   `min-width:150px` 会把每个复选框撑成 150px 宽。 */
div.jg-people-pick { position: relative; font-size: 13px; min-width: 150px; }
div.jg-people-pick .jg-pp-head {
    display: flex; align-items: center; gap: 6px;
}
div.jg-people-pick .jg-pp-trigger {
    display: inline-block; padding: 6px 10px; cursor: pointer;
    border: 1px solid var(--color-base-200); border-radius: 4px;
    background: #fff; color: inherit; text-decoration: none; white-space: nowrap;
}
div.jg-people-pick .jg-pp-trigger:hover { border-color: #22c55e; color: #16a34a; }
div.jg-people-pick .jg-pp-count { color: #16a34a; font-weight: 600; }
/* 收起时：搜索框和名单都不露面 */
div.jg-people-pick .jg-pp-search,
div.jg-people-pick .jg-pp-list { display: none; }
/* ★★★ 展开的浮层用 `position: fixed`，坐标由 people_pick.js 算。
   鲁纪念 #196「下拉菜单太小了显示不出来」：这一格待在内联表格里，
   外层有 overflow-x:auto（表格要横向滚），**绝对定位的子元素会被整个裁掉**
   —— 搜索框露出来了、名单一个字都看不见。fixed 相对视口，裁不到。 */
div.jg-people-pick.jg-pp-open .jg-pp-search {
    display: block; position: fixed; z-index: 1200;
    width: 260px; box-sizing: border-box; padding: 6px 8px;
    border: 1px solid var(--color-base-200); border-radius: 4px; background: #fff;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .08);
}
div.jg-people-pick.jg-pp-open .jg-pp-list {
    display: block; position: fixed; z-index: 1200;
    width: 260px; box-sizing: border-box;
    overflow-y: auto;
    border: 1px solid var(--color-base-200); border-radius: 4px;
    background: #fff; padding: 4px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .08);
}
div.jg-people-pick.jg-pp-open .jg-pp-list label {
    display: flex; align-items: center; gap: 6px;
    padding: 3px 6px; border-radius: 4px; white-space: nowrap;
    justify-content: flex-start;
}
/* ★ Unfold 给勾选框的 label 内部留了很大的间距，名字被推到最右边，
   「刘夫华(W0006)」的工号就被截掉了（#196 第二轮实测）。
   在这个浮层里把内部元素的外边距和弹性都压平，文字紧跟着勾选框。 */
div.jg-people-pick.jg-pp-open .jg-pp-list label > * {
    margin: 0 !important; flex: none !important;
}
div.jg-people-pick.jg-pp-open .jg-pp-list label input[type="checkbox"] {
    min-width: 0 !important; width: 14px; height: 14px;
}
div.jg-people-pick.jg-pp-open .jg-pp-list label:hover {
    background: var(--color-base-100);
}

/* ── 选项多的普通下拉加搜索（#184，吴凡 09-16 批）──────────────
   ★ 浮层一律 `position: fixed`，坐标由 select_search.js 算 ——
     内联表格外层有 overflow-x:auto，绝对定位会被整个裁掉（#196 的教训）。
   ★ 原来的 <select> 留在 DOM 里（表单要提交它），只是藏起来。 */
.jg-ss { position: relative; display: inline-block; min-width: 150px; }
.jg-ss .jg-ss-native { display: none; }
.jg-ss .jg-ss-btn {
    display: block; padding: 6px 10px; cursor: pointer; min-width: 150px;
    max-width: 230px; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap;
    border: 1px solid var(--color-base-200); border-radius: 4px;
    background: #fff; color: inherit; text-decoration: none; font-size: 13px;
}
.jg-ss .jg-ss-btn:hover { border-color: #22c55e; color: #16a34a; }
.jg-ss .jg-ss-search, .jg-ss .jg-ss-list { display: none; }
.jg-ss.jg-ss-open .jg-ss-search {
    display: block; position: fixed; z-index: 1200;
    width: 320px; box-sizing: border-box; padding: 6px 8px; font-size: 13px;
    border: 1px solid var(--color-base-200); border-radius: 4px; background: #fff;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .08);
}
.jg-ss.jg-ss-open .jg-ss-list {
    display: block; position: fixed; z-index: 1200;
    width: 320px; box-sizing: border-box; overflow-y: auto;
    border: 1px solid var(--color-base-200); border-radius: 4px;
    background: #fff; padding: 4px; font-size: 13px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .08);
}
.jg-ss.jg-ss-open .jg-ss-item {
    display: block; padding: 5px 8px; border-radius: 4px;
    color: inherit; text-decoration: none; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis;
}
.jg-ss.jg-ss-open .jg-ss-item:hover { background: var(--color-base-100); }
.jg-ss.jg-ss-open .jg-ss-item.is-on { color: #16a34a; font-weight: 600; }
.jg-ss.jg-ss-open .jg-ss-empty {
    padding: 8px; color: var(--color-base-400); white-space: nowrap;
}

/* ── 确认页那几个类（.jg-me-tbl / .jg-me-go / .jg-me-now）───────
   ★★★ 2026-09-17 补：这三个类**在整个仓库里从来没有定义过**。
     `templates/admin/org/bulk_edit.html`（批量修改所选，#182 前半段）和
     `member_swap.html`（批量替换组员）两页都在用它们 ——
     于是两页都是**裸 HTML**：表格没有线、按钮长成一行普通文字、
     select 连边框都没有（Tailwind Preflight 把 border-width 归零了）。
     页面能用、控制台不报错、机检也扫不到（机检只扫列表页/新建页/编辑页，
     动作确认页不在它的页面集里）——**又是一次「做了但看不见」**。
     是正式站截图肉眼看出来的。教训还是那条：**验算之后必须真浏览器看一眼**。
   ★ 样式照抄本文件里已有的 `.jg-pay-table` 和 `.jg-addbtn`，
     不新造一套 —— 确认页跟别处长得一样，人才不用重新认。 */
.jg-me-tbl {
    width: 100%;
    margin: 14px 0;
    border-collapse: collapse;
    font-size: 13px;
}
.jg-me-tbl th,
.jg-me-tbl td {
    padding: 8px 10px;
    border-bottom: 1px solid var(--color-base-200);
    text-align: left;
    vertical-align: top;
}
.jg-me-tbl th {
    color: var(--color-base-500);
    font-weight: 600;
    white-space: nowrap;
    width: 1%;
}
/* ★ 裸的 select/input 必须自己写边框：Preflight 把 border-width 归零，
     颜色还在、宽度是 0，看着就是「没有框」。这坑一天栽过两次（#190/#192）。 */
.jg-me-tbl select,
.jg-me-tbl input[type="text"],
.jg-me-tbl input[type="number"] {
    padding: 6px 10px;
    font-size: 13px;
    border: 1px solid var(--color-base-300);
    border-radius: 4px;
    background: #fff;
}
.jg-me-tbl select:focus,
.jg-me-tbl input:focus { border-color: #22c55e; outline: none; }
.jg-me-now { margin-top: 4px; font-size: 11px; color: var(--color-base-500); }
.jg-me-go {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 90px;
    height: 36px;
    padding: 0 16px;
    border: 0;
    border-radius: 4px;
    background: #22c55e;
    color: #fff !important;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
}
.jg-me-go:hover { background: #16a34a; }
/* ★ 「还不能按」要看得出来，不然人会以为按钮坏了 */
.jg-me-go[disabled] {
    background: var(--color-base-200);
    color: var(--color-base-500) !important;
    cursor: not-allowed;
}

/* 人力成本分摊明细表（王欣怡 #203「计算过程请全部展示，以便核验」）──
   ★ 摆在「人力成本」那一格底下，所以要比正文小一号、行要矮 ——
     它是给人**核数**用的，不是页面主角。
   ★ 最后一列是算式原文（「7 月薪资：人力总成本 12,227.98 − 团队激励 …」），
     可能很长：整表能横滚，不撑破卡片。 */
.jg-labor-detail { font-size: 11px; margin: 6px 0 2px; }
.jg-labor-detail th,
.jg-labor-detail td { padding: 3px 8px; white-space: nowrap; }
.jg-labor-detail .sub { color: var(--color-base-500); }
.jg-labor-detail .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
/* ★ 外层给一层横滚：算式那一列长起来会把整个卡片顶宽，
     而这一格本来就在表单里 —— 顶宽之后整页都跟着横滚。 */
.field-labor_note .jg-labor-detail { display: block; overflow-x: auto; }

/* ── 加工单：成品换标时才露出「投入数量(份)」那一列 ──────────────
   吴凡 2026-09-17 批 A：投入那一段两种类目都渲染同一套列，按类目显隐。

   ★★ **默认是藏起来的**，`.jg-rework` 由 proc_rework.js 在类目是
      成品换标/漏气时加上。这个方向是特意选的：JS 万一没跑起来，
      页面退回的是**原料加工的老样子**（09-11 特意把这一列从原料加工撤掉过），
      而不是给原料加工凭空多一列。
      —— 默认值要选"出事时也对"的那一边。

   ★ td 上没有 field- 类（unfold 的内联单元格只有一串排版类），
     所以只能靠 `:has()` 认里面那个输入框。这个项目已经在用 `:has()`
     （哈他 bare 模式那条选择器），不是新引入的依赖。 */
#inputs-group:not(.jg-rework) th.column-qty,
#inputs-group:not(.jg-rework) td:has(input[name$="-qty"]) {
    display: none;
}

/* ── 成品换标：必填的是「份数」，不是「重量」──────────────────────
   吴凡 2026-09-17：「当类型为 成品换标、漏气成品，只需要填写份就行」。

   服务端在能判断时已经把 weight_kg 设成非必填（编辑页读得到类目），
   这里管新建页那一刻：类目一切，星号要跟着挪。
   ★ 星号是 unfold 放在列头里的一个 span（.text-red-600）。 */
#inputs-group.jg-rework th.column-weight_kg .text-red-600,
#inputs-group.jg-rework th.column-weight_kg .text-red-500 {
    display: none;
}
#inputs-group.jg-rework th.column-qty > span > span::after {
    content: "*";
    color: #dc2626;
}

/* ══════════════════════════════════════════════════════════════
   自建页面上的数据表 —— 跟标准列表页长一个样。

   ★★★ 吴凡 2026-10-09：「各个 list 列表页面都应该是这个样式的，
      以后所有 list 页面格式 UI 都要类似。你看看哪几个页面还是这样
      乱七八糟的」。指的就是：标准 changelist（收支录入那种）是一个
      白底圆角卡 + 细线表，而自建页（收入计算、月度损益表、库存看板…）
      各写各的 —— 11 个自建页**没有一个**用标准页那套。

   ★★ 所以这里只有**一份**。每个页面各写一套的下场已经看见了：
      11 个页面 11 种长相，而且下次新加的第 12 个还会再跑偏一次。
      数值是在正式站的标准列表页上**真量出来的**，不是我挑的：
        表头 13px / font-weight 600
        单元格 13px / 行高 36px
        分隔线 var(--color-base-200)（实测 rgb(228,228,231)）
        外壳   白底、圆角、1px 细边、极淡阴影

   ★ 想要「#」序号列的，给 <table> 加 id="result_list" ——
     `static/jg/row_no.js` 按**这个 id** 现插，跟标准列表页同一条路。
   ══════════════════════════════════════════════════════════════ */
/* ★★★ 外壳**不用 jg- 类**，直接用标准列表页那串 Unfold 类
   （`rounded-default border border-base-200 shadow-xs …`）。
   原因：`ui-tokens.css` 里有一条全站规则 ——
   `[class*="jg-"] { border-radius: 0 !important }`（机检窗口定的直角规范），
   而标准列表页是圆角的（它用 Unfold 自己的类）。
   在这儿新造一个 jg- 外壳，圆角会被那条 !important 抹平，
   于是「照着标准页做」反而做不出标准页的样子。
   ★ 两套规范在这一点上不一致，已记进 docs/UI_HANDOFF.md 交机检窗口定。 */

.jg-list {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}
.jg-list th {
    padding: 8px 12px;
    text-align: left;
    font-weight: 600;
    white-space: nowrap;
    color: var(--color-font-important-light, #18181b);
    border-bottom: 1px solid var(--color-base-200);
}
.jg-list td {
    padding: 0 12px;
    height: 36px;
    text-align: left;
    border-top: 1px solid var(--color-base-200);
    /* ★ 单元格禁止折行（规范 T-03）：过长截断 + title 悬浮全文。
         折行会让这一行比别人高一截，整张表看着是歪的。 */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.jg-list tbody tr:first-child td { border-top: 0; }
/* ★ 数字等宽：9 和 10 不一样宽的话，一列数字看着是歪的（规范 T-06
     说全部左对齐，所以这里只管等宽，不改对齐）。 */
.jg-list .num { font-variant-numeric: tabular-nums; }
.jg-list .sub { color: var(--color-base-500); font-size: 12px; }
/* 合计行：加粗 + 一道上实线，跟数据行分开 */
.jg-list tfoot td, .jg-list tr.jg-list-total td {
    font-weight: 600;
    border-top: 1px solid var(--color-base-300);
}
/* 底下那行条数 —— 标准列表页底部也是这么一行（「- 5981 库存批次」） */
.jg-list-foot {
    padding: 6px 2px;
    font-size: 13px;
    color: var(--color-font-subtle-light, #71717a);
}
/* 筛选区：跟表一样的卡，摆在表上面 */
.jg-list-filter {
    background: var(--color-base-white, #fff);
    border: 1px solid var(--color-base-200);
    border-radius: 8px;
    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05);
    padding: 14px 16px;
    margin: 12px 0;
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
    font-size: 13px;
}

/* ════════════════════════════════════════════════════════════
   T-02 / T-03：表格里一格就是一行，**禁止折行**
   （吴凡 2026-10-12 拿销售单截图：收货仓那一格「上海盘点美味宝山
     长虹路」**一个字一行竖着排**，整行被撑到 229px 高）

   ## 为什么会竖着排

   Unfold 给内联表加的是 Tailwind 的 `w-full`，也就是
   `width: 100%` —— 表格被钉死在容器宽度上。
   列一多（销售单补齐字段后 23 列），`table-layout: auto` 就开始
   **压缩列**去凑那个宽度：收货仓被压到 **51px**，而里面是 11 个
   汉字 ≈ 143px，于是一个字一行。

   ★★★ 外层 `.formset-wrapper` 本来就有 `overflow-x: auto` ——
      也就是说**横向滚动是允许的**（规范 T-04），
      压缩列这件事从头到尾没必要。`w-full` 把一个「可以滚动」的
      容器当成了「必须塞进去」的容器。

   ## 改法

   `min-width: max-content` —— 让表按内容的自然宽度撑开，
   超出的部分交给外层滚动。配 `white-space: nowrap` 兜住
   「某一格仍然想折」的情况。

   ★ 这不是给销售单打的补丁，是**所有内联表**（采购单、加工单、
     盘点单…）共用的一条。规范里 T-02/T-03 早就这么写了，
     只是从来没人在内联表上落实过。 */
.formset-wrapper > table { min-width: max-content; }
.formset-wrapper > table > thead > tr > th,
.formset-wrapper > table > tbody > tr > td { white-space: nowrap; }

/* ★ 纯文字格（里面没有输入控件的那种）再加一道上限：
   一条 200 字的备注会把表撑到屏幕外面去，横向滚动也救不了。
   规范 T-03 的后半句：**截断 + title 悬浮全文**。
   `title` 由 `cell_ellipsis.js` 只在**真的截断了**的格子上挂，
   不截断的不挂 —— 挂满 title 会让鼠标走到哪都弹一个气泡。

   ★★ `:not(:has(input,select,textarea))` 这一句不能省：
      带输入框的格子设 `overflow:hidden` 会把 select2 的下拉
      **裁掉**（下拉是绝对定位的子元素，父级一 hidden 就看不见了）。 */
.formset-wrapper > table > tbody > tr
  > td:not(:has(input, select, textarea, .select2-container)) {
    max-width: 240px;
    overflow: hidden;
    text-overflow: ellipsis;
}
