/* =====================================================================
   内部点餐系统 · 演示样式（移动优先）
   ---------------------------------------------------------------------
   本文件不含任何裸值：颜色 / 字号 / 间距 / 圆角 / 投影 / 动效 全部来自
   tokens.css。规则见 tokens.css 顶部说明。
   （2026-09-15 对齐 iOS HIG：字号阶梯整体上移、热区 44/40/36、
     底部栏加 env(safe-area-inset-*) 安全区。）
   ===================================================================== */

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html{-webkit-text-size-adjust:100%}
html,body{margin:0;padding:0}
body{
  background:
    radial-gradient(1100px 480px at 12% -8%, var(--c-brand-50) 0%, transparent 62%),
    radial-gradient(900px 420px at 96% 2%, var(--c-green-50) 0%, transparent 58%),
    var(--bg);
  font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
  font-size:var(--fs-16); line-height:var(--lh-body);
  color:var(--ink); min-height:100vh; -webkit-font-smoothing:antialiased;
}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit;font-size:inherit}
input,select,textarea{font-family:inherit;font-size:inherit;color:inherit}
::-webkit-scrollbar{width:7px;height:7px}
::-webkit-scrollbar-thumb{background:var(--c-ink-300);border-radius:var(--r-pill)}
::-webkit-scrollbar-track{background:transparent}

/* ---------------- 外壳 ---------------- */
.shell{max-width:1180px;margin:0 auto;padding:var(--sp-6) var(--sp-5) 50px}
.masthead{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--sp-5);flex-wrap:wrap;margin-bottom:var(--sp-4)}
/* 左侧文字列必须允许收缩（flex:1 + min-width:0），否则它按内容撑到最宽，
   把右侧的版本号 / 主色切换器挤到下一行、并靠左对齐。 */
.masthead>div:first-child{flex:1;min-width:0}
.masthead h1{margin:0 0 var(--sp-1);font-size:var(--fs-24);font-weight:var(--fw-bold);letter-spacing:.2px}
.masthead h1 span{color:var(--brand)}
.masthead p{margin:0;font-size:var(--fs-15);color:var(--muted);line-height:1.65;max-width:640px}
/* 版本变更记录：内容会一轮轮累加，但它只是「参考资料」，不该把手机框（主内容）往下挤。
   给一个高度上限 + 内部滚动 —— 否则变更越写越多，手机框会被推到屏幕之外。 */
.masthead .changelog{margin:var(--sp-2) 0 0;font-size:var(--fs-13);color:var(--brand-d);font-weight:var(--fw-bold);
  line-height:1.62;max-height:124px;overflow-y:auto;padding:0 var(--sp-2) 0 10px;border-left:3px solid var(--c-brand-200)}
.masthead .ver{font-size:var(--fs-12);font-weight:var(--fw-bold);padding:5px 10px;border-radius:var(--r-xs);
  background:var(--brand-s);color:var(--brand-d);white-space:nowrap}
/* 评审开关（主色 / 图标）：只改 tokens 与渲染开关，排版一点不动。
   放在 masthead（演示外壳）而不是手机里 —— 它们是评审工具，不是产品功能。 */
.palpick,.iconpick{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.palpick>span,.iconpick>span{font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--muted)}
.palpick button,.iconpick button{display:inline-flex;align-items:center;gap:5px;min-height:var(--hit-xs);padding:0 9px;
  border-radius:var(--r-pill);font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--ink2);
  background:var(--card);border:1px solid var(--line);transition:border-color var(--dur-fast) var(--ease-out)}
.palpick button .dot{width:9px;height:9px;border-radius:var(--r-pill);flex:none}
.palpick button.on,.iconpick button.on{border-color:var(--brand);background:var(--brand-s);color:var(--brand-d)}
.masthead .side{display:flex;flex-direction:column;align-items:flex-end;gap:var(--sp-2)}

/* ---------------- 线性图标层 ----------------
   尺寸与颜色一律 1em / currentColor：图标继承所在位置的字号与颜色，
   所以「把 emoji 换成图标」不会挪动任何一行排版 —— 这是敢整体替换的前提。
   实心部件（⋯ 的圆点、⚠ 的感叹号点）必须用类来提权：样式表里的 fill:none
   会压过 SVG 上的 fill="currentColor" 呈现属性。 */
.ico{display:inline-flex;align-items:center;justify-content:center;width:1em;height:1em;vertical-align:-.12em}
.ico svg{width:1em;height:1em;display:block;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
.ico svg .solid{fill:currentColor;stroke:none}
.stage{display:grid;grid-template-columns:236px 1fr;gap:var(--sp-6);align-items:start}
@media(max-width:900px){ .stage{grid-template-columns:1fr} .screennav{display:none} }

/* ---------------- 屏幕清单 ---------------- */
.screennav{
  background:rgba(255,255,255,.78);backdrop-filter:blur(10px);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:var(--sp-3);box-shadow:var(--el-1);position:sticky;top:var(--sp-5);
  max-height:calc(100vh - 40px);overflow-y:auto;
}
.screennav .grp{font-size:var(--fs-12);font-weight:var(--fw-heavy);color:var(--c-ink-400);letter-spacing:.7px;padding:var(--sp-3) 10px var(--sp-1)}
.screennav .grp:first-child{padding-top:var(--sp-1)}
.screennav button{
  display:flex;align-items:center;gap:var(--sp-2);width:100%;padding:var(--sp-2) 10px;border-radius:var(--r-sm);
  font-size:var(--fs-15);font-weight:var(--fw-med);color:var(--ink2);text-align:left;
  transition:background var(--dur-fast) var(--ease-out);line-height:1.35;
}
.screennav button:hover{background:var(--c-ink-100)}
.screennav button.on{background:var(--brand);color:var(--on-strong)}
.screennav button .ni{font-size:var(--fs-15);width:16px;flex:none;text-align:center}
.screennav button .nw{margin-left:auto;font-size:var(--fs-11);font-weight:var(--fw-bold);background:var(--red);color:var(--on-strong);padding:2px 5px;border-radius:var(--r-xs)}
.screennav button.on .nw{background:rgba(255,255,255,.92);color:var(--brand-d)}

/* ---------------- 手机外框 ---------------- */
.phonewrap{display:flex;justify-content:center;padding-top:var(--sp-1)}
.device{
  width:392px;height:820px;background:var(--card);border-radius:42px;position:relative;
  box-shadow:0 0 0 11px var(--c-ink-900),0 0 0 13px var(--c-ink-800),0 30px 64px rgba(24,20,17,.30);
  display:flex;flex-direction:column;overflow:hidden;
}
.notch{position:absolute;top:0;left:50%;transform:translateX(-50%);width:146px;height:27px;background:var(--c-ink-900);border-radius:0 0 17px 17px;z-index:60}
.statusbar{height:44px;flex:none;display:flex;align-items:flex-end;justify-content:space-between;padding:0 var(--sp-6) var(--sp-1);
  font-size:var(--fs-15);font-weight:var(--fw-med);z-index:50;color:var(--ink)}
.statusbar .ic{display:flex;gap:5px;align-items:center}
.viewport{flex:1;overflow-y:auto;overflow-x:hidden;position:relative;background:var(--bg)}
/* 入场动画只在**切屏**时播（render() 给包层加 .enter）。
   以前挂在 .viewport > div 上，导致同屏内任何一次重渲染（选菜、打勾、
   加减份数、15 秒轮询…）都把整屏重新淡入上移一次 —— 看起来像页面自己刷新。 */
.viewport > div.enter{animation:viewin var(--dur-base) var(--ease-out)}
@keyframes viewin{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
/* Tab 栏：底部 padding 必须叠加 safe-area，否则在微信 / 全屏模式（viewport-fit=cover）
   下文字会顶到 Home Indicator。Safari 浏览器模式下 env() 取 0，不受影响。
   ★ safe-area 只允许最底层的 tabbar 消费一次。submitbar / footbar 这类
   sticky 条都位于 tabbar 之上，若再叠 env，真机上会双重计入 34pt，
   表现为「提交条与 Tab 栏之间隔了一条大白带」（2026-09-15 修复）。 */
.tabbar{flex:none;display:flex;border-top:1px solid var(--line);background:rgba(255,255,255,.96);backdrop-filter:blur(14px);
  padding:5px 2px calc(6px + env(safe-area-inset-bottom))}
.tabbar button{flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;padding:2px 0;line-height:1.15;color:var(--muted);
  font-size:var(--fs-12);font-weight:var(--fw-med);transition:color var(--dur-fast) var(--ease-out);position:relative}
.tabbar button .ti{font-size:var(--fs-22);line-height:1.15}
.tabbar button.on{color:var(--brand)}
.tabbar button .bdg{position:absolute;top:2px;left:50%;margin-left:6px;min-width:17px;height:17px;padding:0 4px;border-radius:var(--r-pill);
  background:var(--red);color:var(--on-strong);font-size:var(--fs-11);font-weight:var(--fw-heavy);display:flex;align-items:center;justify-content:center}
.toast{position:absolute;bottom:calc(132px + env(safe-area-inset-bottom));left:50%;transform:translateX(-50%) translateY(12px);background:var(--c-ink-800);color:var(--on-strong);
  font-size:var(--fs-15);font-weight:var(--fw-med);padding:10px var(--sp-4);border-radius:var(--r-md);opacity:0;
  transition:opacity var(--dur-base) var(--ease-out),transform var(--dur-base) var(--ease-out);
  pointer-events:none;z-index:90;width:max-content;max-width:86%;text-align:center;line-height:1.5}
/* ★ width:max-content 必须保留（2026-09-16）：绝对定位元素 width:auto 时，浏览器按
   CSS2.1 §10.3.7 只把「包含块宽 − left 偏移」当可用宽度做收缩适配 —— left:50% 意味着
   只有右半屏可用，一行放得下的文案也会被硬折成两行（实测 390 屏上 13 字折 2 行）。
   max-content 让盒子先按全文撑开，再由 max-width:86% 兜长文案的底；删掉必复发。 */
.toast.on{opacity:1;transform:translateX(-50%) translateY(0)}

/* ---------------- 通用 ---------------- */
.pad{padding:0 var(--gutter) var(--sp-6)}
.hd{padding:var(--sp-3) var(--gutter) var(--sp-3)}
.hd h2{margin:0;font-size:var(--fs-24);font-weight:var(--fw-bold);letter-spacing:-.3px;display:flex;align-items:center;gap:7px}
.hd p{margin:var(--sp-1) 0 0;font-size:var(--fs-13);color:var(--muted);line-height:1.5}

/* ---------------- 页头返回入口（二级屏专用） ----------------
   设计取舍：不做顶部导航条。本应用没有「导航条」这一层，页头就是标题区，
   再插一条 bar 会凭空多出一层外壳，和「扁平实心」的语言冲突。所以返回
   就落在标题行的**最左侧**，行内一个箭头，其余一概不动。
   为什么放左侧而不是沿用「设置」页原来的右上角：① 返回在左上才是通用
   预期，也与左缘侧滑方向一致；② 右上角要留给页面级动作 —— 那里已经被
   「每日菜单」的「套用上周 / 菜品库」占满了，再塞会打架。
   尺寸一律复用既有 token（热区 --hit-xs=36、图标字号 --fs-22=Tab 图标档），
   不新造数值。

   几何（三个数互为约束，改一个必须同时改其余）：
     ① .hd 左内边距 16 → 9：把按钮拉到「箭头墨迹正好压住 16 那条栅格线」。
        .ico 是 1em 方盒，font-size 22 时盒内箭头墨迹左边约 7px，故 9+7≈16。
     ② 按钮宽 36（--hit-xs）
     ③ 副标题再让 43 = 36 + 7（h2 自带 gap）—— 让副标题与主标题左缘严格
        对齐，否则副标题会比主标题更靠左，看起来像没对齐。 */
.hd.has-back{padding-left:calc(var(--gutter) - 7px)}
.hdbk{flex:0 0 auto;width:var(--hit-xs);height:var(--hit-xs);display:inline-flex;
  align-items:center;justify-content:center;border:0;background:transparent;padding:0;
  cursor:pointer;border-radius:var(--r-pill);color:var(--ink2);font-size:var(--fs-22);
  -webkit-tap-highlight-color:transparent;transition:background var(--dur-fast) var(--ease-out)}
.hdbk:active{background:var(--line2);color:var(--ink)}
.hdbk svg{stroke-width:2.4}   /* 单笔画图标比多笔画图标要略粗，否则比旁边的字轻 */
.hd.has-back p{padding-left:calc(var(--hit-xs) + 7px)}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--el-1)}
.mt6{margin-top:6px}.mt8{margin-top:var(--sp-2)}.mt10{margin-top:10px}.mt12{margin-top:var(--sp-3)}
.mt16{margin-top:var(--sp-4)}.mt20{margin-top:var(--sp-5)}.mb10{margin-bottom:10px}
.row{display:flex;align-items:center;gap:var(--sp-2)}
.between{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2)}
.grow{flex:1;min-width:0}
.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* 标签：小字号必须配粗体，否则在浅底上糊成一团 */
.tag{display:inline-flex;align-items:center;gap:3px;font-size:var(--fs-12);font-weight:var(--fw-bold);
  padding:3px 7px;border-radius:var(--r-xs);white-space:nowrap;line-height:1.35}
.tag.g{background:var(--green-s);color:var(--green)}
.tag.a{background:var(--amber-s);color:var(--amber)}
.tag.r{background:var(--brand-s);color:var(--brand-d)}
.tag.b{background:var(--blue-s);color:var(--blue)}
.tag.d{background:var(--red-s);color:var(--red)}
.tag.n{background:var(--c-ink-100);color:var(--ink2)}

/* 按钮：主 / 次 / 幽灵 / 危险 / 完成；禁用降透明度，不另造灰色 */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:var(--hit);
  padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);font-size:var(--fs-17);font-weight:var(--fw-bold);
  transition:transform var(--dur-fast) var(--ease-out),opacity var(--dur-fast) var(--ease-out);
  background:var(--c-ink-100);color:var(--ink2);line-height:1.2}
.btn:active{transform:scale(.98);opacity:.88}
.btn.primary{background:var(--brand);color:var(--on-strong)}
.btn.ghost{background:var(--card);border:1px solid var(--line);color:var(--ink2)}
.btn.danger{background:var(--red-s);color:var(--red)}
.btn.ok{background:var(--green-s);color:var(--green)}
.btn.block{width:100%}
.btn.sm{min-height:var(--hit-sm);padding:var(--sp-2) var(--sp-3);font-size:var(--fs-15);border-radius:var(--r-sm)}
.btn.xs{min-height:var(--hit-xs);padding:6px var(--sp-2);font-size:var(--fs-13);border-radius:var(--r-xs)}
/* 「随便吃」次级强调钮：白底 + 主色描边 + 主色深调文字（对比口径同 .tag.r：
   --brand-d 在浅底上过 AA）。只用于选菜标题行的「随便吃 / 换一批」，别拿去当通用按钮。 */
.btn.oline{background:var(--card);border:1.5px solid var(--brand);color:var(--brand-d)}
.btn.oline .ico{font-size:15px}   /* .ico 是 1em 方盒：13px 正文下太小，提到 15px */
.btn[disabled]{opacity:.4;pointer-events:none;box-shadow:none}
/* v0.21：截止态的主按钮要「明确置灰」，不能是 40% 透明度的橙——
   那看起来仍像主操作按钮，只是淡了一点（UX 走查第 6 项）。 */
.submitbar .btn.primary[disabled]{background:var(--c-ink-200);color:var(--c-ink-500);opacity:1}

/* 头像：圆形。方头像在暖色卡片里像「色块」，圆形才读得出是「人」 */
.av{width:38px;height:38px;border-radius:var(--r-pill);display:flex;align-items:center;justify-content:center;
  font-size:var(--fs-15);font-weight:var(--fw-heavy);color:var(--on-strong);flex:none}
.av.sm{width:30px;height:30px;font-size:var(--fs-12)}
.c1{background:var(--c-c1)}.c2{background:var(--c-c2)}.c3{background:var(--c-c3)}.c4{background:var(--c-c4)}.c5{background:var(--c-c5)}
.c6{background:var(--c-c6)}.c7{background:var(--c-c7)}.c8{background:var(--c-c8)}.c9{background:var(--c-c9)}.c10{background:var(--c-c10)}

.divider{height:1px;background:var(--line2);margin:10px 0}
.empty{padding:38px var(--sp-5);text-align:center;color:var(--muted);font-size:var(--fs-15);line-height:1.9}
.empty .em{font-size:var(--is-md);display:block;margin-bottom:var(--sp-2);opacity:.45}
.sec{font-size:var(--fs-15);font-weight:var(--fw-heavy);color:var(--ink2);display:flex;align-items:center;gap:7px;margin:0 0 var(--sp-2)}
.sec .l{width:3px;height:14px;border-radius:2px;background:var(--brand)}
.sec .cnt{margin-left:auto;font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--muted)}
.hint{font-size:var(--fs-12);color:var(--muted);line-height:1.6}

/* 四类提示：信息 / 警告 / 错误 / 成功，语义与功能色一一对应 */
.callout{border-radius:var(--r-md);padding:10px var(--sp-3);font-size:var(--fs-13);line-height:1.65;display:flex;gap:var(--sp-2)}
.callout .ci{font-size:var(--fs-16);flex:none;line-height:1.35}
.callout.info{background:var(--blue-s);border:1px solid var(--c-blue-200);color:var(--c-blue-700)}
.callout.warn{background:var(--amber-s);border:1px solid var(--c-amber-200);color:var(--c-amber-700)}
.callout.bad{background:var(--red-s);border:1px solid var(--c-red-200);color:var(--c-red-700)}
.callout.good{background:var(--green-s);border:1px solid var(--c-green-200);color:var(--c-green-700)}
/* 可点的提示条（未点餐名单 → 催单弹层）：静态提示条和可点提示条必须长得不一样 */
.callout.tap{cursor:pointer;transition:transform .12s ease}
.callout.tap:active{transform:scale(.99)}
.callout .missMore{display:inline-block;margin-top:2px;text-decoration:underline}

/* ---------------- 登录 ---------------- */
.login{padding:calc(var(--sp-5) + env(safe-area-inset-top)) var(--sp-5) var(--sp-8);min-height:100%;display:flex;flex-direction:column}
.login .hero{text-align:center;padding:var(--sp-5) 0}
.login .logo{width:64px;height:64px;border-radius:var(--r-xl);display:flex;align-items:center;justify-content:center;
  font-size:var(--is-md);margin:0 auto var(--sp-3);background:linear-gradient(145deg,var(--c-brand-400),var(--c-brand-600));box-shadow:var(--el-2)}
.login h2{margin:0;font-size:var(--fs-24)}
.login .sub{margin:6px 0 0;font-size:var(--fs-13);color:var(--muted);line-height:1.6}
.field{margin-bottom:var(--sp-3)}
.field label{display:block;font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--ink2);margin-bottom:6px}
/* 必填 / 选填标记（09-17）：必填只画一颗主色深调的 *，选填在标签里写明「（选填）」。
   两者互为对照，于是不必再补一行「带 * 的是必填」的图例 —— 那又是一句废话。 */
.field label .req{font-style:normal;color:var(--brand-d);margin-left:3px}
.field label .opt{font-style:normal;font-weight:normal;color:var(--muted);font-size:var(--fs-12)}
/* 输入框字号 ≥16px 是硬约束：iOS Safari 会对 <16px 的输入框在聚焦时强制放大页面，
   键盘收起后缩放经常不还原 —— 整页「看起来没适配」多半是它。 */
.field input,.field select,.field textarea{
  width:100%;min-height:var(--hit);padding:var(--sp-3);border:1px solid var(--line);border-radius:var(--r-md);
  font-size:var(--fs-16);background:var(--card);outline:none;color:var(--ink);
  transition:border-color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out);
}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-s)}
.field textarea{min-height:74px;resize:vertical;line-height:1.6}
.field .fh{font-size:var(--fs-12);color:var(--muted);margin-top:5px;line-height:1.55}

/* ---------------- 点餐 ---------------- */
.notice{display:flex;gap:var(--sp-2);align-items:flex-start;padding:var(--sp-3);border-radius:var(--r-md);
  font-size:var(--fs-13);line-height:1.6;font-weight:var(--fw-med)}
.notice.bad{background:var(--red-s);border:1px solid var(--c-red-200);color:var(--c-red-700)}
.notice.warn{background:var(--amber-s);border:1px solid var(--c-amber-200);color:var(--c-amber-700)}
.notice .ni{font-size:var(--fs-17);flex:none}

/* ---------------- 点餐页顶部：餐次分段 + 截止 chip ----------------
   设计原则：餐次与截止时间是「上下文」，不是「内容」。它们在成熟点餐产品里
   只占一行（顶部分段控件 + 时间 chip），主视觉必须让给菜品列表。
   v0.19（2026-09-15 反馈落地）：整行压到 44px（与主按钮同高）；
   chip 去掉倒计时图标与倒计时，直接一行「11:00 截止」。

   这一行是**一个整体**：左右两块等高（--h-ordtop），chip 定宽（--w-dlchip）。
   定宽的理由见 tokens.css 第 13 节 —— 宽度一旦跟着文案走，切餐次就会跳版。 */
.ordtop{display:flex;align-items:stretch;gap:var(--sp-2);height:var(--h-ordtop)}
.mseg{display:flex;flex:1;background:var(--c-ink-100);border-radius:var(--r-md);padding:3px;gap:3px}
/* 分段按钮不再设 min-height：整行高度由 --h-ordtop 统一约束，
   按钮在行内自适应拉伸（align-items:stretch），字号降到次级正文 15px。 */
.mseg button{flex:1;padding:4px 6px;border-radius:var(--r-sm);font-size:var(--fs-15);
  font-weight:var(--fw-heavy);color:var(--ink2);display:flex;align-items:center;justify-content:center;gap:5px;
  transition:background var(--dur-fast) var(--ease-out)}
/* 默认选中态 = 白药丸。这条仍然服务**没有 data-meal 的**分段控件，
   典型是管理端「账号管理」的 成员 / 商家 切换 —— 那里不出餐次色。 */
.mseg button.on{background:var(--card);color:var(--brand-d);box-shadow:var(--el-1)}
/* 餐次图标（☀ / 🌙）：与商家端设置页「承接午餐/晚餐」同一套字形，不新造符号，
   作用只有一个 —— 让「这是哪一餐」不必依赖读字。
   ☀ / 🌙 已登记在 app.js 的 ICONS 表里，会被**图标层**替换成线性 SVG
   （替换后是 .mi > .ico > svg 三层），所以这里只负责两件事：
   ① flex:none —— 图标层产出的 .ico 是 1em 方盒且没有 flex:none，
      在 flex 容器里会被压缩；外层套一个不可收缩的 .mi 才守得住。
   ② 字号即尺寸 —— .ico 是 1em，字号定在这里。 */
.mseg .mi{font-size:var(--fs-15);line-height:1;flex:none}
/* 餐次取色按 data-meal，不按 :nth-child —— 按钮顺序跟着 MEAL 对象的键序走，
   位置一旦调整就会串色，按餐次键取色不会。 */
.mseg button[data-meal="lunch"] {--meal-fill:var(--meal-lunch); --meal-fill-sh:var(--meal-lunch-sh)}
.mseg button[data-meal="dinner"]{--meal-fill:var(--meal-dinner);--meal-fill-sh:var(--meal-dinner-sh)}
/* 餐次选中态 = 实心餐次色 + 白字（v0.23，2026-09-16）。
   原先是白药丸压在暖灰轨道上，形状对比只有 1.14:1 —— 选中与否几乎只能靠一层影子区分，
   且两餐外观完全相同，切餐次时整页「看起来没变」。
   填充色直接取主色（午餐 --brand、晚餐靛），理由是**同色**：
   午餐这颗药丸与「确认」等 .btn.primary 是同一个橙，全站一套颜色语言。
   选择器带 [data-meal] 是必须的 —— 少了它，管理端那处没有该属性的分段控件
   会因为 var(--meal-fill) 解析失败而整块 `background` 声明作废、变成透明。
   取色理由与对比度取舍见 tokens.css 第 5.5 节。 */
.mseg button[data-meal].on{background:var(--meal-fill);color:var(--on-strong);
  box-shadow:0 2px 7px var(--meal-fill-sh)}
/* 餐次状态：小块标签比裸圆点更明确（已点 / 待重选 / 不吃 / 未点）。
   文字一律 700 阶：11px 胶囊按正文口径要 4.5:1，500 阶只有 3.04~4.23:1（实测），
   换 700 阶后为 5.39~6.57:1 —— 底色一个字不动，只换字色。 */
.mseg .st{font-size:var(--fs-11);font-weight:var(--fw-heavy);padding:1px 5px;border-radius:var(--r-xs);
  background:var(--c-ink-200);color:var(--ink-d);flex:none;line-height:1.5}
.mseg .st.ok{background:var(--green-s);color:var(--green-d)}
.mseg .st.rs{background:var(--red-s);color:var(--red-d)}
.mseg .st.no{background:var(--c-ink-200);color:var(--ink-d)}
.mseg .st.warn{background:var(--amber-s);color:var(--amber-d)}
.mseg .st.ed{background:var(--blue-s);color:var(--blue-d)}
/* 胶囊落在实心餐次色上时整颗翻成白底：浅色底既与填充色打架、对比也不足。 */
.mseg button[data-meal].on .st{background:var(--on-strong);color:var(--ink-d)}
.mseg button[data-meal].on .st.ok{color:var(--green-d)}
.mseg button[data-meal].on .st.warn{color:var(--amber-d)}
.mseg button[data-meal].on .st.rs{color:var(--red-d)}
.mseg button[data-meal].on .st.ed{color:var(--blue-d)}
/* 截止 chip：v0.19 起只有一行「11:00 截止」（b=时间、lb=「截止」二字）。
   倒计时图标与倒计时已按反馈删掉 —— 用户要看的是「几点截止」，
   不是「还剩几分钟」盯着的焦虑。宽度仍定宽，切餐次不跳版。
   v0.22：96 按「11:00 截止」定宽，v0.21 的三种长文案（已截止 18:10 / 18:10 前仍可点 /
   明天 11:40 截止）实测溢出 20~22px，--w-dlchip 放宽到 124（实测最长需 118，见 tokens 第 13 节）。 */
.dlchip{width:var(--w-dlchip);padding:0 var(--sp-2);border-radius:var(--r-md);background:var(--card);border:1px solid var(--line);
  color:var(--muted);white-space:nowrap;flex:none;
  display:flex;flex-direction:row;align-items:center;justify-content:center;gap:3px}
.dlchip .ic{font-size:var(--fs-13)}
.dlchip b{font-size:var(--fs-15);font-weight:var(--fw-heavy);color:var(--brand-d);font-variant-numeric:var(--num)}
.dlchip .lb{font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--muted)}
/* 「快到截止了」态：修饰符刻意不用 `urge` —— 商家催单页已有一个全局 `.urge` 块级类
   （display:flex / padding / border-bottom），用它做修饰符会被那套规则命中，
   chip 会悄悄变成横向 flex 行、尺寸全变。类名要挑命名空间内的，别蹭通用词。 */
/* v0.23（2026-09-16）：只留琥珀字，去掉琥珀底。
   选中的是午餐（橙实心）而这里又处于「快到截止」时，同一行会出现三个暖色块
   （牌子橙 + 告警琥珀 ×2），糊成一片；退回白底后暖色块只剩一个，
   而 `amber-700 on white` = 5.91:1，比原来的琥珀底（3.04:1）反而更清楚。 */
.dlchip.soon{background:var(--card);border-color:var(--c-amber-200)}
.dlchip.soon b{color:var(--amber-d)}
.dlchip.soon .lb{color:var(--amber-d)}
/* 已截止态：🔒 + 「已截止」，与常态同一行布局，只是换内容 */
.dlchip.off{gap:5px}
.dlchip.off .ic{font-size:var(--fs-13)}

/* 选菜提示：压成一行小字，不再用整块 callout 占位 */
.tiphint{font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--muted);margin:0 0 10px}
/* 固定搭配：常驻一行、两个份数步进器
   上一版折成可展开的一行，但折叠条排在菜品列表之后、被推到折叠线以下，
   用户既看不到它也不知道能调份数。现在压成一行常驻在选菜之前，不折、不跳版。
   两项等宽分栏，结构统一（图标 + 名称 + 步进器），步进器各自靠右对齐。
   注意：这一行是全页最挤的一行（两个 flex:none 的步进器 + 文字），字号上移后
   横向 padding 收到 10px、步进器降到密集档（--hit-xs），才能在 390pt 一行放下。

   ★ v0.20 修复「例菜的 + 按钮上有一根线」——根因不是分隔线本身，是两侧内边距不对称：
   两组内容各 167px（图标 21 + 间隔 + 标签 26 + 间隔 + 步进器），而 390 下每组只分到
   161.5px。子项全是 flex:none（不可收缩），多出的 5.5px 就**原样溢出组边界**，
   正好压在右组的 border-left 上 —— 那根 1px 线于是画在了「+」按钮里。
   右侧 12px 内边距 + 0 左侧，等于把线贴到了左组按钮的边上。
   修法两步：① 两侧各留 12px，线回到两组中间的空隙正中（左 12 / 右 12）；
   ② 回收 16px 让内容真的放得下：图标—标签间隔 8→6、数字列 26→20（一位数用不到）。
   改这一行必须跑 375 / 390 双视口：断言「+ 按钮右沿 ≤ 分隔线 - 4px」。
   ★ v0.22 复测：390 放得下、375 下右组内容超组宽 9px（吃进卡片右内边距、距边框 1px）。
   再回收 20px：两侧内边距 10→8、分隔线两侧 12→10、组内间隔 6→4、数字列 20→16。
   回归脚本 tmp/verify_order_overflow.js 固定双视口断言（溢出=0、chip 定宽不再被顶破）。 */
.stapbar{display:flex;align-items:center;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-md);padding:7px 8px}
.stapbar .grp{display:flex;align-items:center;gap:4px;flex:1;min-width:0}
/* 分隔线两侧等距：左边那组补 padding-right，右边那组用 padding-left + border-left。
   只给一侧留间距（上一版的写法）会把线推到左组按钮上。 */
.stapbar .grp:not(:last-child){padding-right:10px}
.stapbar .grp+.grp{border-left:1px solid var(--line2);padding-left:10px}
.stapbar .tb{font-size:var(--fs-17);flex:none;line-height:1}
.stapbar .grp b{font-size:var(--fs-13);font-weight:var(--fw-heavy);color:var(--ink);flex:none}
/* 内边距由 .stepper.sm 提供（2px）；这里写 3px 会被后面的 .stepper.sm 覆盖，别再重复声明 */
.stapbar .stepper{margin-left:auto}
.stapbar .stepper button{width:var(--hit-xs);height:var(--hit-xs)}
/* 数字列 26→20：一位数（1~3）用不到 26px，这里回收的 12px 就是分隔线的呼吸位。
   选择器带 .sm 是为了压过文件后面的 `.stepper.sm .v`（同权重时后者赢）。 */
.stapbar .stepper.sm .v{min-width:16px}

/* 份数步进器：热区按规范提升（次级控件 40px / 密集档 36px）。
   最初 28px 与 25px、上一版 36px 与 32px 都在规范下限之下 —— 逐轮修正。 */
.stepper{display:flex;align-items:center;gap:2px;background:var(--c-ink-100);border-radius:var(--r-md);padding:3px;flex:none}
.stepper button{width:var(--hit-sm);height:var(--hit-sm);border-radius:var(--r-sm);background:var(--card);
  font-size:var(--fs-17);font-weight:var(--fw-heavy);color:var(--ink2);display:flex;align-items:center;justify-content:center;
  transition:background var(--dur-fast) var(--ease-out)}
.stepper button:active{background:var(--brand-s)}
.stepper button[disabled]{opacity:.35}
.stepper .v{min-width:30px;text-align:center;font-size:var(--fs-16);font-weight:var(--fw-heavy);font-variant-numeric:var(--num)}
.stepper.sm{padding:2px;gap:1px;border-radius:var(--r-sm)}
.stepper.sm button{width:var(--hit-xs);height:var(--hit-xs);border-radius:var(--r-xs);font-size:var(--fs-16)}
.stepper.sm .v{min-width:26px;font-size:var(--fs-15)}

/* 成员端点餐页顶部的身份行（.hd.slim / .who / .nowday）已于 v0.19 删除：
   「张伟 · 日期 · 退出」整体移入「我的」页头部，点餐页首屏让给菜品。
   safe-area-inset-top 改由点餐页首个 .pad 的内联 padding 消费。 */

/* 分类条吸附在顶部：滚动浏览菜品时分类始终可切换（美团 / 饿了么同款做法） */
.cats{display:flex;gap:6px;margin:0 -16px var(--sp-3);padding:var(--sp-2) var(--gutter) var(--sp-2);
  position:sticky;top:0;z-index:9;background:var(--bg)}
.cats button{flex:1;min-height:var(--hit-sm);padding:var(--sp-2) 5px;border-radius:var(--r-sm);border:1px solid var(--line);
  background:var(--card);font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--ink2);transition:all var(--dur-fast) var(--ease-out);
  display:flex;align-items:center;justify-content:center;gap:5px}
.cats button.on{border-color:var(--brand);background:var(--brand-s);color:var(--brand-d)}
.cats button .n{font-size:var(--fs-11);font-weight:var(--fw-heavy);color:var(--ink2);background:var(--c-ink-100);
  border-radius:var(--r-xs);padding:1px 5px;font-variant-numeric:var(--num)}
.cats button.on .n{background:var(--card);color:var(--brand-d)}

.subcard{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}
.subcard .shd{display:flex;gap:10px;align-items:center;padding:var(--sp-3) var(--pad-card);
  background:var(--green-s);border-bottom:1px solid var(--c-green-200)}
.subcard .shd .ok{font-size:var(--fs-22);flex:none}
.subcard .shd .h1{font-size:var(--fs-16);font-weight:var(--fw-heavy);color:var(--c-green-700)}
.subcard .shd .h2{font-size:var(--fs-12);color:var(--c-green-700);margin-top:2px;font-weight:var(--fw-bold)}
.subcard .slist{padding:2px 0}
.srow{display:flex;align-items:center;gap:10px;padding:var(--sp-2) var(--pad-card);border-bottom:1px solid var(--line2)}
.srow:last-child{border-bottom:none}
.srow .thumb{width:38px;height:38px;border-radius:var(--r-sm);display:flex;align-items:center;justify-content:center;
  font-size:var(--fs-20);flex:none;background-size:cover;background-position:center}
.srow .nm{font-size:var(--fs-15);font-weight:var(--fw-bold)}
.srow .ds{font-size:var(--fs-11);color:var(--muted);margin-top:1px}
.subcard .sacts{display:flex;gap:var(--sp-2);padding:var(--sp-3) var(--pad-card);border-top:1px solid var(--line);background:var(--c-ink-50)}
.linkbtn{display:block;width:100%;text-align:center;font-size:var(--fs-13);font-weight:var(--fw-bold);
  color:var(--muted);padding:0 var(--pad-card) var(--sp-3);background:var(--c-ink-50)}
.linkbtn:active{color:var(--brand)}

.mealtabs{display:flex;gap:var(--sp-2)}
.mealtabs button{flex:1;min-height:var(--hit);padding:var(--sp-3) 10px;border-radius:var(--r-md);border:1px solid var(--line);
  background:var(--card);text-align:left;transition:all var(--dur-base) var(--ease-out);position:relative;color:var(--ink)}
.mealtabs button.on{border-color:var(--brand);background:var(--brand-s)}
/* 餐次取色按 data-meal（与成员端点餐页 .mseg 共用同一套 token），不按 :nth-child ——
   按钮顺序跟着 MEAL 的键序走，按位置取色迟早串。 */
.mealtabs button[data-meal="lunch"] {--meal-fill:var(--meal-lunch); --meal-fill-sh:var(--meal-lunch-sh)}
.mealtabs button[data-meal="dinner"]{--meal-fill:var(--meal-dinner);--meal-fill-sh:var(--meal-dinner-sh)}
/* 餐次选中态 = 实心餐次色 + 白字（v0.24，2026-09-17）——
   统一到成员端点餐页 .mseg 的颜色语言：午餐=主色橙、晚餐=靛（见 tokens.css 5.5 节）。
   改前这里是「浅橙底 --brand-s + 橙描边」，午餐与晚餐长得一模一样：
   切餐次时只有「已点 N 人」那行字变，整块看起来没换过，而且浅橙底与晚餐的靛毫无关系。
   .ms 那行在实心色上从 500 阶提到 700 阶：12px 小字压在饱和橙上本来就吃力，
   字号不能加（会撑高整块），提字重是唯一不动布局的补偿。 */
.mealtabs button[data-meal].on{border-color:var(--meal-fill);background:var(--meal-fill);color:var(--on-strong);
  box-shadow:0 2px 7px var(--meal-fill-sh)}
.mealtabs button[data-meal].on .ms{color:var(--on-strong);opacity:1;font-weight:var(--fw-bold)}
/* 选择器带 [data-meal] 是必须的：没有该属性时 var(--meal-fill) 解析失败，
   整条 background 声明会静默作废（无报错、元素变透明）。上面那条不带属性的
   .mealtabs button.on 就是这类分段控件的兜底。 */
.mealtabs .mt{font-size:var(--fs-16);font-weight:var(--fw-heavy);display:flex;align-items:center;gap:5px}
.mealtabs .ms{font-size:var(--fs-12);color:var(--muted);margin-top:3px;font-weight:var(--fw-med)}
.mealtabs button.on .ms{color:var(--brand-d);opacity:.85}
.mealtabs .bd{position:absolute;top:var(--sp-2);right:9px;font-size:var(--fs-11);font-weight:var(--fw-heavy);
  padding:2px 6px;border-radius:var(--r-xs);background:var(--green-s);color:var(--green)}
.mealtabs .bd.no{background:var(--c-ink-100);color:var(--muted)}
.mealtabs .bd.rs{background:var(--red-s);color:var(--red)}

.panel{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--el-1)}
/* 带 id 的面板是页内滚动锚点（如「已点餐」KPI → 按人明细），留一点上边距免得标题贴边 */
.panel[id]{scroll-margin-top:10px}
.panel .ph{padding:var(--sp-3) var(--pad-card);display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);
  border-bottom:1px solid var(--line2)}
.panel .ph h3{margin:0;font-size:var(--fs-15);font-weight:var(--fw-bold);display:flex;align-items:center;gap:6px}
.panel .ph .sub{font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--muted)}
.panel .pb{padding:var(--sp-3) var(--pad-card)}

/* 例菜 / 白饭 行 */
.staple{display:flex;align-items:center;gap:10px;padding:10px var(--sp-3);border-bottom:1px solid var(--line2)}
.staple:last-child{border-bottom:none}
.staple .thumb{width:42px;height:42px;border-radius:var(--r-md);display:flex;align-items:center;justify-content:center;font-size:var(--is-sm);flex:none}
.staple .nm{font-size:var(--fs-16);font-weight:var(--fw-bold)}
.staple .ds{font-size:var(--fs-12);color:var(--muted);margin-top:2px}

/* 菜品卡 */
.dishgrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-2)}
.dish{background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden;text-align:left;
  transition:border-color var(--dur-fast) var(--ease-out);position:relative;display:block;width:100%;padding:0}
.dish:active{transform:scale(.985)}
.dish.on{border-color:var(--brand);box-shadow:0 0 0 1px var(--brand)}
.dish.lock{opacity:.4}
/* v0.19（2026-09-15 反馈落地）：图片区 72 → 116px（≈3:2 横图）。
   390 视口下每卡约 175px 宽，再大首屏就只剩一排菜。此样式被成员选菜、
   商家菜品管理 / 选菜池 / 例菜弹层共用 —— 六处一起变大，正是要的统一。 */
.dish .img{height:116px;display:flex;align-items:center;justify-content:center;font-size:var(--is-md);position:relative;
  background-size:cover;background-position:center}
.dish .body{padding:var(--sp-2) 9px 9px}
.dish .nm{font-size:var(--fs-15);font-weight:var(--fw-bold);line-height:1.3;display:block}
.dish .cat{font-size:var(--fs-11);color:var(--muted);margin-top:2px;display:block}
.dish .qty{position:absolute;left:7px;bottom:7px;font-size:var(--fs-11);font-weight:var(--fw-heavy);
  background:rgba(42,36,32,.82);color:var(--on-strong);padding:2px 6px;border-radius:var(--r-xs)}
.dish .tick{position:absolute;top:7px;right:7px;width:22px;height:22px;border-radius:var(--r-pill);background:var(--brand);
  color:var(--on-strong);display:flex;align-items:center;justify-content:center;font-size:var(--fs-13);font-weight:var(--fw-heavy)}
.dish .exp{position:absolute;top:7px;left:7px;font-size:var(--fs-11);font-weight:var(--fw-heavy);
  background:rgba(255,255,255,.94);color:var(--brand-d);padding:2px 6px;border-radius:var(--r-xs)}

/* ---------------- 菜品编辑弹层 · 配图选择 ----------------
   商家自助上传（09-17）：预览 84px 方块（沿用缩略图规格）。
   容器类名 .imgpick/.ipv/.ipt/.ipbtn 全仓唯一，刻意不复用 .thumb —— 后者是列表里的
   行内缩略图、尺寸由调用方给，这里要的是固定方图，混用会让两处一起变。
   按钮也不用 .btn.xs（09-17 反馈「太小、浅底浅字看不清」）：--hit-xs 只有 36px，
   底色 --c-ink-100 落在暖白弹层上几乎看不出边界，右侧还会空出一大片。改成 44px
   满宽 + 主色描边 + 主色深调文字（--brand-d on --brand-s = 4.84:1，过 AA），
   读起来像「可以按」，但仍弱于底部实心橙的「保存」——一张弹层只留一个实心主按钮。 */
.imgpick{display:flex;gap:var(--sp-3);align-items:stretch}
.imgpick .ipv{width:84px;height:84px;flex:none;border-radius:var(--r-sm);border:1px solid var(--line);
  background-size:cover;background-position:center;display:flex;align-items:center;justify-content:center;
  font-size:var(--is-md)}
.imgpick .grow{min-width:0;display:flex;flex-direction:column;justify-content:center;gap:8px}
.imgpick .ipt{font-size:var(--fs-13);font-weight:var(--fw-bold)}
.imgpick .ipbtn{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;
  min-height:var(--hit);padding:0 var(--sp-3);border-radius:var(--r-sm);
  border:1.5px solid var(--brand);background:var(--brand-s);color:var(--brand-d);
  font-size:var(--fs-15);font-weight:var(--fw-bold);
  transition:transform var(--dur-fast) var(--ease-out),opacity var(--dur-fast) var(--ease-out)}
.imgpick .ipbtn:active{transform:scale(.98);opacity:.9}

/* 底部提交条：sticky 于视口底，紧贴 Tab 栏 —— 下方 safe-area 由 tabbar 统一消费，
   这里不再叠 env（双重计入会在真机上顶出一条大白带）。 */
.submitbar{position:sticky;bottom:0;margin:var(--sp-4) -16px 0;
  padding:var(--sp-3) var(--gutter) var(--sp-3);
  background:linear-gradient(to top,var(--bg) 58%,transparent);display:flex;gap:var(--sp-2);align-items:center;z-index:20}
.submitbar .pg{font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--ink2);line-height:1.3}
.submitbar .pg b{font-size:var(--fs-20);color:var(--brand);font-variant-numeric:var(--num)}
.submitbar .pg .money{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:var(--fs-12);color:var(--muted);font-weight:var(--fw-bold)}

/* ---------------- 我的 ---------------- */
.statgrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr);gap:var(--sp-2)}
.stat{background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);padding:var(--sp-3) 9px;text-align:center}
.stat .v{font-size:var(--fs-24);font-weight:var(--fw-heavy);letter-spacing:-.5px;color:var(--brand);
  font-variant-numeric:var(--num);line-height:1.3}
.stat .k{font-size:var(--fs-12);color:var(--muted);margin-top:3px;font-weight:var(--fw-bold)}

/* 「我的」：今天的饭 */
.qcard{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}
.qrow{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) var(--pad-card);border-bottom:1px solid var(--line2)}
.qrow:last-child{border-bottom:none}
.qrow .qi{font-size:var(--fs-22);flex:none;width:24px;text-align:center}
.qrow .qn{font-size:var(--fs-15);font-weight:var(--fw-heavy)}
.qrow .qt{margin-top:5px;display:flex;flex-wrap:wrap;gap:var(--sp-1)}
.qrow .btn{flex:none;white-space:nowrap}

/* 「我的」：本月 / 累计 统计 */
.mgrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-2)}
.mstat{background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);padding:var(--sp-3) var(--pad-card)}
.mstat .v{font-size:var(--fs-24);font-weight:var(--fw-heavy);letter-spacing:-.5px;color:var(--brand);
  font-variant-numeric:var(--num);line-height:1.2}
.mstat .k{font-size:var(--fs-12);color:var(--muted);font-weight:var(--fw-bold);margin-top:var(--sp-1)}
.mstat .h{font-size:var(--fs-11);color:var(--muted);font-weight:var(--fw-med);margin-top:3px;opacity:.9}
.mstat.warn .v{color:var(--red)}
.mstat.warn .h{color:var(--red);opacity:.85}
.ratio{background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);padding:var(--sp-3) var(--pad-card)}
.rbar{height:9px;border-radius:var(--r-pill);background:var(--c-ink-200);overflow:hidden}
.rbar i{display:block;height:100%;border-radius:var(--r-pill);background:linear-gradient(90deg,var(--c-brand-600),var(--c-brand-300))}
.rlg{display:flex;justify-content:space-between;font-size:var(--fs-12);color:var(--muted);font-weight:var(--fw-bold);margin-top:7px}

/* 「我的」：用餐习惯入口行 */
.habitline{display:flex;align-items:center;gap:var(--sp-3);width:100%;text-align:left;margin-top:9px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);padding:var(--sp-3) var(--pad-card)}
.habitline:active{background:var(--c-ink-50)}
.habitline .hi{font-size:var(--fs-20);flex:none}
.habitline .ht{font-size:var(--fs-13);font-weight:var(--fw-heavy);color:var(--ink2)}
.habitline .hs{font-size:var(--fs-12);color:var(--muted);margin-top:2px;font-weight:var(--fw-med)}

/* 用餐习惯矩阵
   列宽必须足够容纳「🍱 午餐」这种带图标的标签：标签列一旦被 nowrap 顶宽，
   整条 7 列网格就会溢出卡片（表现为「日」列被切掉）。
   另外七列必须写 minmax(0,1fr) —— 写成 1fr 时它是 minmax(auto,1fr)，
   轨道最小宽度会被内容的 min-content 顶住，给子元素加 min-width:0 也压不住。 */
.habit{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--sp-3) var(--pad-card)}
.hgrid{display:grid;grid-template-columns:56px repeat(7,minmax(0,1fr));gap:3px;align-items:center}
.hgrid+.hgrid{margin-top:6px}
.hgrid.hhead{margin-bottom:var(--sp-1)}
.hgrid .hl{font-size:var(--fs-12);font-weight:var(--fw-heavy);color:var(--ink2);white-space:nowrap}
.hgrid .hd{font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--muted);text-align:center}
/* 格子热区 36px：低于规范的 44，属密集矩阵的明确偏离（一周 7 格要在一行内放下） */
.hcell{height:var(--hit-xs);border-radius:var(--r-xs);border:1px solid var(--line);background:var(--c-ink-100);
  font-size:var(--fs-13);font-weight:var(--fw-heavy);color:var(--c-ink-400);display:flex;align-items:center;
  justify-content:center;transition:transform var(--dur-fast) var(--ease-out);padding:0;min-width:0;overflow:hidden}
.hcell:active{transform:scale(.93)}
.hcell.on{background:var(--green-s);border-color:var(--c-green-200);color:var(--green)}
/* off 态显式着色（09-17 用户指定）：不吃＝浅红底大叉，与 on 态绿勾同构
   （取色与 --green-s/--c-green-200/--green 同层级的 --red 系列），空格子看不出吃不吃 */
.hcell.off{background:var(--red-s);border-color:var(--c-red-200);color:var(--red)}
.hsum{margin-top:var(--sp-3);padding-top:10px;border-top:1px solid var(--line2);
  font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--brand-d);line-height:1.6}

/* 智能建议卡 */
.sugcard{background:var(--card);border:1px solid var(--c-blue-200);border-radius:var(--r-lg);overflow:hidden}
.sugcard .shd{display:flex;gap:10px;align-items:center;padding:var(--sp-3) var(--pad-card);background:var(--blue-s);
  border-bottom:1px solid var(--c-blue-200)}
.sugcard .shd .ok{font-size:var(--fs-22);flex:none}
.sugcard .shd .h1{font-size:var(--fs-15);font-weight:var(--fw-heavy);color:var(--c-blue-700)}
.sugcard .shd .h2{font-size:var(--fs-12);color:var(--c-blue-700);margin-top:2px;font-weight:var(--fw-bold)}
.sugcard .slist{padding:2px 0}
.sugcard .srow .si{font-size:var(--fs-17);flex:none;width:20px;text-align:center}
.sugcard .sacts{display:flex;gap:var(--sp-2);padding:var(--sp-3) var(--pad-card);border-top:1px solid var(--line);background:var(--c-ink-50)}

.rec{padding:var(--sp-3) var(--pad-card);border-bottom:1px solid var(--line2)}
.rec:last-child{border-bottom:none}
.rec .dt{font-size:var(--fs-15);font-weight:var(--fw-heavy);color:var(--ink2);display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.rec .body{font-size:var(--fs-15);color:var(--ink);margin-top:6px;line-height:1.7}
.pill{display:inline-block;font-size:var(--fs-12);padding:2px 7px;border-radius:var(--r-xs);background:var(--c-ink-100);
  margin:2px var(--sp-1) 2px 0;color:var(--ink2);font-weight:var(--fw-med);white-space:nowrap}
.pill.hi{background:var(--brand-s);color:var(--brand-d);font-weight:var(--fw-bold)}
.pill.gr{background:var(--green-s);color:var(--green)}

.setrow{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) var(--pad-card);border-bottom:1px solid var(--line2)}
.setrow:last-child{border-bottom:none}
.setrow .si{font-size:var(--fs-20);width:24px;text-align:center;flex:none}
.setrow .st{font-size:var(--fs-15);font-weight:var(--fw-bold)}
.setrow .sd{font-size:var(--fs-12);color:var(--muted);margin-top:2px;line-height:1.5}

/* 开关 */
.sw{width:44px;height:26px;border-radius:var(--r-pill);background:var(--c-ink-300);position:relative;flex:none;
  transition:background var(--dur-base) var(--ease-out)}
.sw::after{content:'';position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:var(--r-pill);background:var(--on-strong);
  transition:left var(--dur-base) var(--ease-out)}
.sw.on{background:var(--green)}
.sw.on::after{left:21px}

/* ---------------- 商家：配餐清单 ---------------- */
.preprow{display:flex;align-items:flex-start;gap:10px;padding:var(--sp-3) var(--pad-card);border-bottom:1px solid var(--line2);
  transition:background var(--dur-fast) var(--ease-out)}
.preprow:last-child{border-bottom:none}
.preprow.done{background:var(--green-s)}
.preprow.done .pname{color:var(--muted);text-decoration:line-through}
.tick{width:var(--hit-xs);height:var(--hit-xs);border-radius:var(--r-sm);border:2px solid var(--line);flex:none;
  display:flex;align-items:center;justify-content:center;font-size:var(--fs-15);color:transparent;
  transition:all var(--dur-fast) var(--ease-out);background:var(--card);margin-top:1px}
.tick.on{background:var(--green);border-color:var(--green);color:var(--on-strong)}
.pname{font-size:var(--fs-15);font-weight:var(--fw-heavy)}
/* 配餐清单局部：姓名加大加粗（17px/900），只作用于配餐行，不影响其它屏共用的 .pname */
.preprow .pname{font-size:var(--fs-17);font-weight:var(--fw-black)}
.pcont{font-size:var(--fs-13);color:var(--ink2);line-height:1.75;margin-top:var(--sp-1)}
.bars{display:flex;flex-direction:column;gap:9px}
.bar{display:flex;align-items:center;gap:9px}
.bar .bn{width:84px;font-size:var(--fs-13);font-weight:var(--fw-bold);flex:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bar .bt{flex:1;height:var(--sp-2);background:var(--c-ink-100);border-radius:var(--r-pill);overflow:hidden}
.bar .bf{height:100%;border-radius:var(--r-pill);background:linear-gradient(90deg,var(--c-brand-400),var(--c-brand-600));transition:width .5s var(--ease-out)}
.bar .bf.g{background:linear-gradient(90deg,var(--c-green-400),var(--green))}
.bar .bv{width:42px;text-align:right;font-size:var(--fs-12);font-weight:var(--fw-heavy);color:var(--ink2);
  font-variant-numeric:var(--num);flex:none}

/* 配餐页 · 底部交付条
   交付是配完餐后的规定动作，却曾是清单末尾的一个普通按钮：十来个「按人配餐」行，
   滚到一半根本碰不到它。现在吸附在视口底部（sticky 于 .viewport），滚到哪都在。
   文案同步压到最短 —— 能不能点已由按钮的可用态表达，不必写进按钮里；
   状态说明降级成下方一行小字，既不抢位置也不丢信息。
   注意：本元素必须是 .pad 的**兄弟**而非子元素，否则 .pad 的 padding-bottom 会
   在滚动到底时把交付条往上顶，留出一条缝。 */
.footbar{position:sticky;bottom:0;z-index:20;padding:10px var(--gutter) var(--sp-3);
  background:linear-gradient(to top,var(--bg) 62%,transparent)}
.footbar .fbnote{font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--muted);text-align:center;margin-top:7px;line-height:1.5}
.footbar .fbnote.ok{color:var(--green)}

/* ---------------- 未点餐名单 ----------------
   v0.22b：手机号行类名必须是 .uph —— 之前用 .ph，而 .panel .ph 是面板头部
   样式（带 padding + space-between），名单行在 .panel 里，手机号整行被误加
   头部内边距 → 和姓名错位，这就是「电话没对齐」的根因。.uph 为通用类，
   催单名单行与管理员成员行的电话行共用。姓名 17px（强调正文档）。 */
.urge{display:flex;align-items:center;gap:10px;padding:var(--sp-3) var(--pad-card);border-bottom:1px solid var(--line2);
  min-height:56px}
.urge:last-child{border-bottom:none}
.urge .urname{font-size:var(--fs-17);font-weight:var(--fw-heavy);letter-spacing:-.2px;line-height:1.3;color:var(--ink)}
.uph{font-size:var(--fs-13);color:var(--muted);font-variant-numeric:var(--num);margin-top:3px;
  font-weight:var(--fw-med);line-height:1.4;text-align:left}
.callbtn{width:var(--hit);height:var(--hit);border-radius:var(--r-md);background:var(--green);color:var(--on-strong);
  display:flex;align-items:center;justify-content:center;font-size:var(--fs-20);flex:none;text-decoration:none;box-shadow:var(--el-1)}
/* 没登记手机号：拨不了，但按钮必须留在原位 —— 抽掉会让整列对不齐 */
.callbtn.off{background:var(--c-ink-100);color:var(--muted);box-shadow:none;cursor:pointer}

/* ---------------- 常驻看板 ---------------- */
.livebar{display:flex;align-items:center;gap:10px;padding:var(--sp-3) var(--pad-card);border-radius:var(--r-md);
  background:linear-gradient(135deg,var(--c-ink-800),var(--c-ink-700));color:var(--on-strong)}
.livebar.off{background:var(--c-ink-100);color:var(--ink2);border:1px solid var(--line)}
.livebar .dot{width:var(--sp-2);height:var(--sp-2);border-radius:var(--r-pill);background:var(--c-green-400);flex:none;
  box-shadow:0 0 0 3px rgba(18,160,92,.22)}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}
.livebar .dot.blink{animation:pulse 1.1s infinite}
.livebar .lt{font-size:var(--fs-15);font-weight:var(--fw-heavy)}
.livebar .ls{font-size:var(--fs-12);opacity:.72;margin-top:2px}
.livebar .lsm{font-size:var(--fs-12);opacity:.72;margin-top:1px}
.livefeed{font-size:var(--fs-12);color:var(--ink2);padding:var(--sp-2) 0;border-bottom:1px dashed var(--line);line-height:1.6}
.livefeed:last-child{border-bottom:none}

/* ---------------- 表格（账单 / 看板） ---------------- */
.tbw{overflow-x:auto}
table.tb{width:100%;border-collapse:collapse;font-size:var(--fs-15)}
table.tb th{text-align:left;font-size:var(--fs-12);font-weight:var(--fw-heavy);color:var(--muted);
  padding:var(--sp-2) 10px;background:var(--c-ink-50);border-bottom:1px solid var(--line);white-space:nowrap}
table.tb td{padding:9px 10px;border-bottom:1px solid var(--line2);vertical-align:middle}
table.tb tr:last-child td{border-bottom:none}
table.tb td.num{font-variant-numeric:var(--num);font-weight:var(--fw-heavy)}
table.tb .rt{text-align:right}

.kpis{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2)}
.kpi{background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);padding:var(--sp-3) var(--pad-card)}
.kpi .k{font-size:var(--fs-12);color:var(--muted);font-weight:var(--fw-bold)}
.kpi .v{font-size:var(--fs-28);font-weight:var(--fw-heavy);letter-spacing:-.6px;margin-top:5px;
  font-variant-numeric:var(--num);line-height:1.2}
.kpi .v small{font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--muted);margin-left:2px;letter-spacing:0}
.kpi .d{font-size:var(--fs-12);font-weight:var(--fw-bold);margin-top:var(--sp-1);color:var(--muted)}
.kpi .d.up{color:var(--green)}
.kpi .d.down{color:var(--brand)}
/* 可点的 KPI（如「未点餐」→ 催单名单）：必须自己声明可点信号，
   否则和旁边的纯数字卡片长得一样，用户不会去点。 */
.kpi.tap{position:relative;cursor:pointer;
  border-color:var(--brand-s);box-shadow:var(--el-1);
  transition:transform .12s ease,box-shadow .12s ease}
.kpi.tap .k::after{content:' ›';color:var(--brand);font-weight:var(--fw-heavy)}
.kpi.tap:active{transform:scale(.975);box-shadow:none}

/* ---------------- 弹层 ---------------- */
.mask{position:absolute;inset:0;background:rgba(42,36,32,.44);backdrop-filter:blur(3px);display:flex;
  align-items:flex-end;justify-content:center;z-index:70;animation:fade var(--dur-base) var(--ease-out)}
@keyframes fade{from{opacity:0}to{opacity:1}}
.sheet{background:var(--card);border-radius:var(--r-xl) var(--r-xl) 0 0;width:100%;max-height:92%;
  display:flex;flex-direction:column;overflow:hidden;box-shadow:var(--el-2);
  animation:up var(--dur-fast) cubic-bezier(.34,1.3,.64,1)}
@keyframes up{from{transform:translateY(30px);opacity:.4}to{transform:none;opacity:1}}
.sheet .grab{width:38px;height:var(--sp-1);border-radius:var(--r-pill);background:var(--c-ink-300);margin:9px auto var(--sp-1);flex:none}
.sheet .sh{padding:9px var(--sp-4) var(--sp-3);border-bottom:1px solid var(--line2);display:flex;align-items:center;
  justify-content:space-between;gap:10px;flex:none}
.sheet .sh h3{margin:0;font-size:var(--fs-17)}
.sheet .sb{padding:var(--pad-card) var(--sp-4);overflow-y:auto;flex:1}
.sheet .sf{padding:var(--sp-3) var(--sp-4) calc(var(--sp-5) + env(safe-area-inset-bottom));border-top:1px solid var(--line2);display:flex;gap:var(--sp-2);background:var(--c-ink-50);flex:none}
.sheet .sf .btn{flex:1}

/* 菜品详情大图 */
.heroimg{height:150px;display:flex;align-items:center;justify-content:center;font-size:var(--is-lg);border-radius:var(--r-md);
  margin-bottom:var(--sp-3);background-size:cover;background-position:center}

.pre{background:var(--c-ink-50);border:1px solid var(--line);border-radius:var(--r-md);padding:var(--sp-3);
  font-size:var(--fs-13);line-height:1.9;white-space:pre-wrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  color:var(--ink2);margin:0}

/* 上传 */
.upload{border:1.5px dashed var(--c-ink-300);border-radius:var(--r-md);padding:var(--sp-5);text-align:center;
  background:var(--c-ink-50);transition:background var(--dur-fast) var(--ease-out);display:block;width:100%}
.upload:active{background:var(--c-ink-100)}
.upload .ui{font-size:var(--is-md);display:block;margin-bottom:7px;opacity:.6}
.upload .ut{font-size:var(--fs-15);font-weight:var(--fw-bold);color:var(--ink2)}
.upload .us{font-size:var(--fs-12);color:var(--muted);margin-top:var(--sp-1);line-height:1.6}

.cmprow{display:flex;align-items:center;gap:9px;font-size:var(--fs-13);padding:7px 0;border-bottom:1px dashed var(--line)}
.cmprow:last-child{border-bottom:none}
.cmprow .cv{font-variant-numeric:var(--num);font-weight:var(--fw-heavy)}

/* 菜品页 · 今日菜单入口卡
   高频日常操作（排今日菜单）放最上，低频资产维护（菜品库）排其后。 */
.menucard{display:block;width:100%;text-align:left;font:inherit;color:inherit;cursor:pointer;
  -webkit-appearance:none;appearance:none;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:var(--sp-3) var(--pad-card);box-shadow:var(--el-1)}
.menucard.todo{border-color:var(--brand-s2);background:var(--brand-s)}
.menucard .mch{display:flex;align-items:center;gap:9px}
.menucard .mch .mi{font-size:var(--fs-20)}
.menucard .mct{font-size:var(--fs-16);font-weight:var(--fw-heavy);letter-spacing:-.2px}
.menucard .mcs{font-size:var(--fs-12);color:var(--muted);margin-top:2px}
.menucard .mcgo{margin-left:auto;font-size:var(--fs-15);font-weight:var(--fw-heavy);color:var(--brand);white-space:nowrap}
.menucard .mcline{display:flex;align-items:center;gap:var(--sp-2);margin-top:9px;padding-top:9px;
  border-top:1px dashed var(--line);font-size:var(--fs-13)}
.menucard .mcline .ml{font-weight:var(--fw-heavy);color:var(--ink2);flex:0 0 34px}
.menucard .mcline .mv{font-weight:var(--fw-heavy);color:var(--green);font-variant-numeric:var(--num)}
.menucard .mcline .mv.warn{color:var(--red)}
.menucard .mcline .mex{color:var(--muted);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hdacts{display:flex;gap:6px;flex:0 0 auto}

/* =====================================================================
   视觉规范屏（demo 内置的设计规范展示）
   这一屏本身就是规范的一部分：它把 tokens.css 的值渲染出来给人看，
   值全部由内联样式引用 var()，改 tokens 即改这一屏。
   ===================================================================== */
.specsec{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--pad-card);box-shadow:var(--el-1)}
.specsec+.specsec{margin-top:var(--sp-3)}
.specsec h3{margin:0 0 var(--sp-3);font-size:var(--fs-16);font-weight:var(--fw-heavy);display:flex;align-items:center;gap:6px}
.specsec h3 .n{font-size:var(--fs-11);font-weight:var(--fw-heavy);color:var(--brand-d);background:var(--brand-s);
  border-radius:var(--r-xs);padding:2px 6px;letter-spacing:.4px}
.swatches{display:grid;grid-template-columns:repeat(5,1fr);gap:6px}
.swatch{border-radius:var(--r-sm);overflow:hidden;border:1px solid var(--line)}
.swatch .chip{height:38px}
.swatch .lb{font-size:var(--fs-11);font-weight:var(--fw-bold);color:var(--muted);text-align:center;padding:3px 0;line-height:1.3;
  font-variant-numeric:var(--num);background:var(--card)}
.typerow{display:flex;align-items:baseline;gap:10px;padding:7px 0;border-bottom:1px dashed var(--line2)}
.typerow:last-child{border-bottom:none}
.typerow .tp{color:var(--ink);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.typerow .tm{font-size:var(--fs-11);color:var(--muted);font-weight:var(--fw-bold);flex:none;font-variant-numeric:var(--num)}
.tokenlist{display:flex;flex-direction:column;gap:6px}
.tokenrow{display:flex;align-items:center;gap:var(--sp-2);font-size:var(--fs-12);color:var(--ink2)}
.tokenrow .tk{width:74px;flex:none;color:var(--muted);font-weight:var(--fw-bold)}
.tokenrow .tv{font-variant-numeric:var(--num);font-weight:var(--fw-bold)}
.radii{display:flex;gap:var(--sp-2);align-items:flex-end}
.radiobox{flex:1;text-align:center}
.radiobox .bx{height:44px;background:var(--brand-s);border:1px solid var(--c-brand-200);margin-bottom:var(--sp-1)}
.radiobox .rl{font-size:var(--fs-11);color:var(--muted);font-weight:var(--fw-bold);font-variant-numeric:var(--num)}
.elebox{height:46px;border-radius:var(--r-md);background:var(--card);border:1px solid var(--line);display:flex;
  align-items:center;justify-content:center;font-size:var(--fs-12);color:var(--muted);font-weight:var(--fw-bold)}
.hitrow{display:flex;align-items:center;gap:10px;padding:7px 0;border-bottom:1px dashed var(--line2)}
.hitrow:last-child{border-bottom:none}
.hitrow .hb{display:flex;align-items:center;justify-content:center;border-radius:var(--r-sm);background:var(--brand-s);
  border:1px solid var(--c-brand-200);color:var(--brand-d);font-size:var(--fs-11);font-weight:var(--fw-heavy);flex:none}
.hitrow .ht{font-size:var(--fs-12);color:var(--ink2);line-height:1.5}
.hitrow .ht b{font-weight:var(--fw-heavy)}
.hitrow .hv{margin-left:auto;font-size:var(--fs-11);font-weight:var(--fw-heavy);flex:none;font-variant-numeric:var(--num)}
.hitrow .hv.pass{color:var(--green)}
.hitrow .hv.warn{color:var(--amber)}
.note{font-size:var(--fs-12);color:var(--muted);line-height:1.65;margin-top:var(--sp-3);padding-top:var(--sp-3);
  border-top:1px dashed var(--line)}
.note b{color:var(--ink2)}

@media(max-width:900px){
  .shell{padding:var(--sp-4) var(--sp-3) 40px}
  .device{width:100%;max-width:392px}
}

/* =====================================================================
   成员端 · 点餐页「选菜区」（2026-09-17 按参考图重做）
   ---------------------------------------------------------------------
   只服务「点餐」这一屏。类名全部新起：.ptabs / .selrow / .dens / .pick /
   .picklist / .dgrid / .dcard / .cbtn。
   旧类 .cats / .dishgrid / .dish **一个字节不改** —— 它们还被商家菜品库
   （app.js:1996 / 1998 / 2087）与访客点餐（app.js:2783）共用，动一处会连带
   改掉另外三屏，那就不叫「只改选菜区」了。

   橙色一律取主色 --brand(#F97316)：分类药丸的橙 = 提交按钮的橙。
   不引入第二个橙、不引入渐变材质 —— 与 tokens.css §5.5「全站只有一套橙色
   语言」是同一条取舍，代价（白字 2.80:1）一并继承，不在这处单独偏离。

   两处**有意偏离参考图源码**（那双是 bug，不是设计）：
     ① .pick .ds / .dcard .ds 显式 display:block —— 参考图里描述行是 inline
        <span>，而 overflow:hidden + text-overflow:ellipsis 在 inline 元素上
        不生效，长描述会一路穿过右侧圆形按钮（放大截图可见）。
     ② .selrow .cnt 显式 white-space:nowrap —— 参考图里已选计数被右侧提示
        文字挤成了「已选」/「0/3」两行。
   ===================================================================== */

/* ── 分类药丸 ───────────────────────────────────────────────────────
   旧 .cats 用「等宽方框 + 1px 描边 + 灰胶囊计数」表达选中，方框底色是极浅的
   --brand-s，切换时几乎看不出；实心药丸把「现在在看哪一类」变成一眼可辨。
   仍保持吸顶：这是原有可用性改进（滚到菜品深处也能换类），不因换皮而丢。 */
.ptabs{display:flex;gap:var(--sp-2);margin:0 -16px var(--sp-3);
  padding:var(--sp-2) var(--gutter);position:sticky;top:0;z-index:9;background:var(--bg);
  overflow-x:auto;scrollbar-width:none}
.ptabs::-webkit-scrollbar{display:none}
.ptabs button{flex:none;min-height:var(--hit-xs);padding:0 var(--sp-4);border:0;border-radius:var(--r-pill);
  background:var(--c-ink-100);color:var(--ink2);font-size:var(--fs-13);font-weight:var(--fw-bold);
  display:inline-flex;align-items:center;gap:5px;white-space:nowrap;
  transition:background var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out)}
.ptabs button.on{background:var(--brand);color:var(--on-strong)}
.ptabs button .n{font-size:var(--fs-12);opacity:.72;font-variant-numeric:var(--num)}
.ptabs button.on .n{opacity:.9}

/* ── 已选行：左计数 · 中随状态变的提示 · 右密度三图标 ──────────────── */
.selrow{display:flex;align-items:center;gap:var(--sp-2);padding:0 0 var(--sp-3)}
.selrow .cnt{font-size:var(--fs-15);font-weight:var(--fw-bold);color:var(--ink2);white-space:nowrap}
.selrow .cnt b{font-size:var(--fs-17);color:var(--brand);font-variant-numeric:var(--num)}
.selrow .left{margin-left:auto;font-size:var(--fs-12);color:var(--muted);white-space:nowrap}

/* 密度切换：36px 热区，对齐 tokens.css §11 的「密集控件」档，不另造更小的档 */
.dens{display:flex;gap:2px;flex:none;padding:2px;background:var(--c-ink-100);border-radius:var(--r-sm)}
.dens>button{width:var(--hit-xs);height:32px;border:0;border-radius:var(--r-xs);background:none;color:var(--muted);
  font-size:18px;   /* .ico 是 1em 方盒：这里定的是图标实际尺寸 */
  display:flex;align-items:center;justify-content:center;
  transition:background var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out)}
.dens>button.on{background:var(--card);color:var(--brand);box-shadow:var(--el-1)}

/* ── 列表档（默认）：缩略图在左 · 菜名+描述在右 · 圆形按钮收尾 ──────── */
.picklist{display:flex;flex-direction:column;gap:var(--sp-2)}
.pick{display:flex;align-items:center;gap:var(--sp-3);width:100%;text-align:left;
  background:var(--card);border:1.5px solid transparent;border-radius:var(--r-lg);
  padding:var(--sp-3);box-shadow:var(--el-1);position:relative;
  transition:border-color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.pick:active{transform:scale(.99)}
.pick.on{border-color:var(--brand);box-shadow:0 4px 16px rgba(249,115,22,.20)}
.pick.lock{opacity:.5}
.pick .ph{width:64px;height:64px;border-radius:var(--r-md);flex:none;display:flex;align-items:center;
  justify-content:center;font-size:var(--is-sm);background-size:cover;background-position:center}
.pick .bd{flex:1;min-width:0}
.pick .nm{display:block;font-size:var(--fs-16);font-weight:var(--fw-bold);color:var(--ink);line-height:1.25}
.pick .ds{display:block;margin-top:3px;font-size:var(--fs-13);color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ── 圆形选择按钮：未选=主色虚线环+＋；已选=主色实心+✓ ───────────────
   30px 是**视觉尺寸**不是热区：整张卡都是按钮，点哪儿都算，不违反 44pt 下限。 */
.cbtn{width:30px;height:30px;border-radius:var(--r-pill);flex:none;display:flex;align-items:center;
  justify-content:center;border:1.5px dashed var(--c-brand-300);background:var(--brand-s);
  color:var(--brand);font-size:var(--fs-15);font-weight:var(--fw-heavy);line-height:1}
.pick.on .cbtn,.dcard.on .cbtn{background:var(--brand);border:1.5px solid var(--brand);color:var(--on-strong)}

/* ── 宫格档 / 大图档：图上文下，两者只差图高与内距 ────────────────── */
.dgrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-2)}
.dgrid.one{grid-template-columns:minmax(0,1fr)}
.dcard{background:var(--card);border:1.5px solid transparent;border-radius:var(--r-lg);overflow:hidden;
  text-align:left;display:block;width:100%;padding:0;box-shadow:var(--el-1);
  transition:border-color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.dcard:active{transform:scale(.99)}
.dcard.on{border-color:var(--brand);box-shadow:0 4px 16px rgba(249,115,22,.20)}
.dcard.lock{opacity:.5}
.dcard .ph{display:flex;align-items:center;justify-content:center;width:100%;height:176px;flex:none;
  font-size:var(--is-md);background-size:cover;background-position:center}
.dcard .meta{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) var(--sp-3) var(--sp-4)}
.dcard .tx{flex:1;min-width:0}
.dcard .nm{display:block;font-size:var(--fs-16);font-weight:var(--fw-bold);color:var(--ink);line-height:1.25}
.dcard .ds{display:block;margin-top:3px;font-size:var(--fs-13);color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dcard.tiny .ph{height:104px}
.dcard.tiny .meta{padding:var(--sp-2) var(--sp-2) var(--sp-3);gap:var(--sp-2)}
.dcard.tiny .nm{font-size:var(--fs-15)}
.dcard.tiny .cbtn{width:26px;height:26px}

/* ---------------- 月度账单（商家 / 管理端）· 2026-09-17 改版 ----------------
   移植自 design/redesign/merchant-bill.html（v3 提案稿）：信息架构照搬
   （当月=预估·截至今日、午晚拆分、环比同期、供餐天数、规则与明细可折叠），
   颜色 / 圆角 / 字号全部改走本站 tokens（--brand #F97316 系），不引入 v3 资产。
   全部类名 .b* 作用域化，一个字节不动既有共享组件。 */
.bmonths{display:flex;gap:6px;overflow-x:auto;padding:2px 0;scrollbar-width:none}
.bmonths::-webkit-scrollbar{display:none}
.bmonths button{flex:none;min-height:var(--hit-xs);padding:0 var(--sp-3);border-radius:var(--r-pill);
  background:var(--c-ink-100);color:var(--ink2);font-size:var(--fs-13);font-weight:var(--fw-med);
  font-variant-numeric:var(--num);transition:background var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out)}
.bmonths button.on{background:var(--brand);color:var(--on-strong);font-weight:var(--fw-bold)}

/* 汇总卡：渐变与 .btn.primary / .mseg 选中态同一个橙系，白字对比属全站既有取舍 */
.bhero{border-radius:var(--r-lg);padding:var(--sp-4);
  background:linear-gradient(135deg,var(--c-brand-500),var(--c-brand-400));
  color:var(--on-strong);box-shadow:0 6px 16px var(--meal-lunch-sh)}
.bhero .bh-cap{font-size:var(--fs-13);font-weight:var(--fw-med);opacity:.95;
  display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.bhero .bhest{background:rgba(255,255,255,.22);border-radius:var(--r-pill);
  padding:2px 9px;font-size:var(--fs-12);font-weight:var(--fw-bold)}
.bhero .bh-amt{font-size:var(--fs-28);font-weight:var(--fw-heavy);letter-spacing:-.6px;
  margin-top:6px;font-variant-numeric:var(--num);line-height:1.15}
.bhero .bh-delta{margin-top:2px;font-size:var(--fs-13);opacity:.95;font-variant-numeric:var(--num)}
.bhero .bh-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--sp-2);
  margin-top:var(--sp-3);padding-top:var(--sp-3);border-top:1px solid rgba(255,255,255,.30)}
.bhero .bh-cell{min-width:0}
.bhero .bh-cell .k{font-size:var(--fs-12);opacity:.85}
.bhero .bh-cell .v{font-size:var(--fs-15);font-weight:var(--fw-bold);margin-top:2px;
  font-variant-numeric:var(--num);white-space:nowrap}
.bhero .bh-cell .s{font-size:var(--fs-12);opacity:.85;margin-top:2px;white-space:nowrap}

/* 可折叠面板头：.ph 的 div 形态变成 button（button 全局已 reset），只补宽度与手型 */
.panel .ph.bph{width:100%;cursor:pointer;text-align:left}
.panel .ph.bph:active{background:var(--c-ink-50)}
.bchev{display:inline-block;color:var(--muted);font-size:var(--fs-15);line-height:1;
  transition:transform var(--dur-fast) var(--ease-out)}
.bchev.open{transform:rotate(180deg)}

/* 明细表（成员 / 午 / 晚 / 金额 / 没收到）：紧凑内距，首末列对齐卡片边 */
.btb th,.btb td{padding:var(--sp-2) 8px}
.btb th:first-child,.btb td:first-child{padding-left:var(--pad-card)}
.btb th:last-child,.btb td:last-child{padding-right:var(--pad-card)}
.btb .bwho{display:flex;align-items:center;gap:7px;min-width:0}
.btb .bwho b{font-weight:var(--fw-med);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.btb .bmc{color:var(--ink2);font-weight:var(--fw-med)}
.btb tbody tr.brow{cursor:pointer;transition:background var(--dur-fast) var(--ease-out)}
.btb tbody tr.brow:active{background:var(--c-ink-100)}
.btb tbody tr.bguest td{background:var(--c-ink-100);color:var(--ink2)}
.btb tbody tr.bguest .bwho b{font-weight:var(--fw-med)}
/* 「没收到」：协商参考信息，不是告警 —— 中性胶囊，不再用 .tag.d 红色 */
.btb .bnnr{display:inline-block;font-size:var(--fs-12);font-weight:var(--fw-bold);
  color:var(--ink2);background:var(--c-ink-100);border-radius:var(--r-pill);
  padding:2px 9px;white-space:nowrap}
.btb tfoot td{font-weight:var(--fw-bold);background:var(--card);border-top:1px solid var(--line)}

/* 表尾小注：替代原来的两条 callout（异常说明 + 访客说明） */
.bnote{margin:var(--sp-3) var(--sp-1) 0;font-size:var(--fs-12);color:var(--muted);line-height:1.7}
