/* PTC Insight — 唯一样式表（Stage 1.4「壳」）。
   视觉权威：~/.claude-tools/specs/ptc-report-django-DESIGN.md（frontend-council 2026-08-26 主方向=体系派）。

   宪法（违反即打回）：
   1. 深度只标容器，永不标数据——面板/按钮/输入有圆角与投影；表格/行/单元格零圆角零投影零渐变。
   2. 一色一职：navy=文字/结构/主操作，red=未达标语义与限量品牌 CTA，green/amber=达标/临界。
   3. 导航当前项用 navy 淡底 + navy 标记条；不引入第四种点缀色。
   4. 数据区绝对安静。
   5. 零魔法数字，尺寸与颜色一律走 :root token。
   6. 无运行时外链，且零字体请求——门店平板常年弱网/内网。

   ADDENDUM v2（2026-08-26）品牌重映射已生效：字体全 Arial（无 @font-face）、
   cyan 体系整体移除、navy/red/off-white 对齐 PTC Brand Guidelines v2.0。
   token 与 PTC Mobile 自此分叉；布局/断点/组件/动效纪律不变。 */

/* --- Tokens -------------------------------------------------------------- */
:root {
  /* 底 + 面（官方 Off White / White） */
  --bg: #f8f8f8;
  --surface: #ffffff;
  --hairline: rgba(26, 48, 89, 0.09);
  --divider: #d2d2d2;

  /* 中性梯度：真中性，不带蓝调 */
  --n-100: #f8f8f9;
  --n-200: #ededf0;
  --n-400: #d8d8dc;
  --n-500: #aeaeb4;
  --n-600: #8a8a91;
  --n-700: #62626a;
  --n-800: #43434a;

  /* 品牌 + 状态（官方 Navy / Red；green/amber 品牌未定义，沿用功能色原值） */
  --ink: #1a3059;
  /* --action = 应用内交互色，官方 navy 本色；-700/-800 是 hover/active 加深档 */
  --action: #1a3059;
  --action-700: #142647;
  --action-800: #0f1d36;
  --action-100: #e8edf4;
  --ok: #12855a;
  --ok-700: #0c6a47;
  --ok-100: #e8f6ef;
  --warn: #c47a0a;
  --warn-700: #8f5606;
  --warn-100: #fdf3e2;
  /* red 一色两职：达标「未达标」语义 + 无数据页面的限量品牌 CTA */
  --alert: #cc271d;
  --alert-700: #a31f17;
  --alert-100: #fae9e8;

  /* 圆角 */
  --r-panel: 16px;
  --r-key: 11px;
  --r-tag: 6px;
  --r-puck: 999px;

  /* 高度（阴影层） */
  --e1: 0 1px 2px rgba(26, 48, 89, 0.05);
  --e2: 0 1px 2px rgba(26, 48, 89, 0.05), 0 8px 20px -4px rgba(26, 48, 89, 0.14);
  --e3: 0 1px 3px rgba(26, 48, 89, 0.06), 0 14px 32px -8px rgba(26, 48, 89, 0.18),
        0 40px 72px -32px rgba(26, 48, 89, 0.3);

  /* 别名：保留 PTC Mobile 的语义映射，组件代码可直接照搬。
     muted-500/600 刻意映射到更深一档，中性梯度去蓝后浅档对白底不足 4.5:1。 */
  --line: var(--hairline);
  --fill-100: var(--n-100);
  --fill-200: var(--n-200);
  --muted-500: var(--n-600);
  --muted-600: var(--n-700);
  --muted-700: var(--n-700);
  --muted-800: var(--n-800);
  --action-tint: var(--action-100);
  --alert-tint: var(--alert-100);
  --alert-text: var(--alert-700);

  /* 间距 / 尺寸 */
  --pad: 14px;
  --gap: 12px;
  --card-pad: 16px;
  --tap: 44px;
  --btn-lg: 48px;
  --tabbar-h: 58px;
  --sidebar-w: 236px;
  --logo-h: 26px;

  /* 字号 */
  --fs-title: 18px;
  --fs-section: 20px;
  --fs-body: 14px;
  --fs-sm: 13px;
  --fs-xs: 12px;
  --fs-kicker: 11px;
  --fs-micro: 10px;

  /* 品牌标题字体即 Arial；正文暂以 Arial 代 FIELDWORK（授权未取得）。零字体请求 */
  --font: Arial, "Helvetica Neue", Helvetica, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --z-header: 20;
  --z-tabbar: 30;
  --z-toast: 50;

  /* ---- 以下为报表场景新增（PTC Mobile 无数据表体系） ---- */

  /* 表格两档行高：紧凑档扫读跨店对比，常规档等于 --tap 供手机点按下钻 */
  --row-h: 36px;
  --row-h-lg: 44px;
  --th-h: 34px;
  --cell-pad-x: 12px;
  --cell-pad-x-lg: 16px;

  /* 顶部状态条 */
  --topbar-h: 56px;
  --topbar-h-sm: 48px;

  /* 行首 4px 状态色条（council 强制的第二重编码） */
  --flag-w: 4px;

  /* 图表容器（Stage 2 用；先定死高宽比，弱网加载才不会撑开又塌陷） */
  --chart-ar: 16 / 9;
  --chart-ar-sm: 4 / 3;
  --chart-h-min: 220px;

  /* 加载态 */
  --skeleton-bg: var(--n-200);
  --spinner-size: 16px;
  --spinner-size-lg: 24px;

  /* 动效：唯一允许的时长常量，组件里禁止写裸毫秒 */
  --t-fast: 120ms;
  --t-ui: 160ms;
  --t-color: 200ms;

  /* 表头 sticky 必须低于 --z-header，否则滚动时表头会盖住状态条 */
  --z-sticky-th: 10;
}

/* 壳的断点必须与 token 换档点同一个值，否则会出现「桌面布局 + 手机间距」的中间态 */
@media (min-width: 900px) {
  :root {
    --pad: 28px;
    --gap: 20px;
    --card-pad: 18px;
    --fs-title: 24px;
  }
}

/* --- 基础重置 / 排版 ------------------------------------------------------ */
* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  background-image: radial-gradient(120% 90% at 50% -10%, #ffffff 0%, #fafafa 45%, #f2f2f2 100%);
  background-attachment: fixed;
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  /* 金额、日期、店号全站等宽对齐；表格扫读靠的就是这个 */
  font-variant-numeric: tabular-nums;
}

a { color: var(--action-800); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Arial 无 800：字重上限 700，靠收紧字距补回原本由重字重承担的密度 */
h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -0.02em; }

.kicker {
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-600);
}
.muted { color: var(--muted-700); font-size: var(--fs-sm); }
.note { font-size: var(--fs-kicker); color: var(--muted-700); }
.mono { font-family: var(--font-mono); font-size: var(--fs-sm); }
.stack { display: flex; flex-direction: column; gap: var(--gap); }

/* --- a11y 工具类 --------------------------------------------------------- */
:focus-visible {
  outline: 2px solid var(--action);
  outline-offset: 2px;
}

/* 键盘用户不必 tab 过整条侧栏才能进正文 */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: var(--z-toast);
  padding: 10px 14px;
  background: var(--ink);
  color: #fff;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.skip-link:focus { left: 0; text-decoration: none; }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* 壳的两套形态共用同一份 DOM，靠这两个类切换，避免重复渲染两遍导航。
   刻意只写「隐藏」不写「显示」：显示态留给元素自己的 display，
   否则会把 .topbar-pagetitle 从 block 改成 flex，text-overflow 省略号就失效了。 */
@media (max-width: 899px) { .desk-only { display: none !important; } }
@media (min-width: 900px) { .mob-only { display: none !important; } }

/* --- 应用壳 -------------------------------------------------------------- */
.shell { display: flex; min-height: 100vh; }

.shell-col {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}

.sidebar { display: none; }

.app-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  width: 100%;
  padding: var(--pad);
  /* Tab Bar 是 sticky 不是 fixed，这里只补一点呼吸位 */
  padding-bottom: calc(var(--pad) + 8px);
}

/* --- 顶部状态条 ---------------------------------------------------------- */
/* 实底不用 backdrop-filter：council 弃用 blur，且它在门店旧安卓 WebView 上掉帧 */
.topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: var(--topbar-h-sm);
  padding: 0 var(--pad);
  padding-top: max(0px, env(safe-area-inset-top));
  background: var(--surface);
  border-bottom: 1px solid var(--hairline);
}

.topbar-scope { display: flex; align-items: center; gap: 10px; }
.topbar-scope select { width: auto; min-width: 168px; }

.topbar-pagetitle {
  min-width: 0;
  margin-right: auto;
  font-size: var(--fs-title);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar-spacer { flex: 1; }

.topbar-stamp {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
  margin: 0;
  font-size: var(--fs-kicker);
  color: var(--muted-700);
  white-space: nowrap;
}
/* 圆点只是加速识别；新鲜度本身由后面的时间文字承载，颜色不是唯一编码 */
.stamp-dot {
  width: 9px;
  height: 9px;
  flex: none;
  background: var(--n-400);
  border-radius: var(--r-puck);
}
.stamp-dot--fresh { background: var(--ok); }
.stamp-dot--stale { background: var(--warn); }

.topbar-user { flex: none; text-align: right; line-height: 1.25; }
.topbar-user-name { font-size: var(--fs-sm); font-weight: 700; }
.topbar-user-role { font-size: var(--fs-kicker); color: var(--muted-700); }

.topbar-logout { display: flex; flex: none; margin: 0; }

/* 手机端图标登出：整块 44×44 才点得中，图标本身 20px */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tap);
  min-height: var(--tap);
  padding: 0;
  color: var(--ink);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: background-color var(--t-color) ease, transform var(--t-ui) ease;
}
.icon-btn:hover { background: var(--fill-100); text-decoration: none; }
.icon-btn:active { transform: scale(0.97); }
.icon-btn svg { width: 20px; height: 20px; }

/* --- 手机底部 Tab Bar ---------------------------------------------------- */
.tabbar {
  position: sticky;
  bottom: 0;
  z-index: var(--z-tabbar);
  display: flex;
  background: var(--surface);
  border-top: 1px solid var(--hairline);
  padding-bottom: env(safe-area-inset-bottom);
}
.tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: var(--tabbar-h);
  padding: 6px 2px;
  background: var(--surface);
  color: var(--ink);
  border: 0;
  border-top: 3px solid transparent;
  font: inherit;
  transition: transform var(--t-ui) ease, background-color var(--t-color) ease;
}
.tab:hover { text-decoration: none; }
.tab:active { transform: scale(0.97); }
.tab:focus-visible { outline: 2px solid var(--action); outline-offset: -2px; }
.tab-label {
  font-size: var(--fs-kicker);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
/* 当前项三重编码：3px 顶条（形状）+ 浅青底（颜色）+ aria-current（语义） */
.tab.is-active {
  background: var(--action-100);
  color: var(--action-800);
  border-top-color: var(--action);
}

/* --- 桌面壳 -------------------------------------------------------------- */
@media (min-width: 900px) {
  .tabbar { display: none; }

  .sidebar {
    display: flex;
    flex-direction: column;
    flex: 0 0 var(--sidebar-w);
    width: var(--sidebar-w);
    position: sticky;
    top: 0;
    height: 100vh;
    background: var(--surface);
    /* 方角无影：侧栏是结构不是卡片，只用一条 hairline 与正文分开 */
    box-shadow: 1px 0 0 var(--hairline);
  }

  .sidebar-brand { flex: none; padding: 18px 20px; border-bottom: 1px solid var(--hairline); }
  .sidebar-wordmark {
    display: block;
    font-size: var(--fs-section);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: var(--logo-h);
    color: var(--ink);
  }
  .sidebar-brand .kicker { margin-top: 3px; }

  /* 导航能长到 ~19 项 + 6 个分组标签，必须自己滚，品牌位与页脚不跟着走 */
  .sidebar-nav { flex: 1; min-height: 0; overflow-y: auto; padding: 8px 0; }

  .nav-group-label {
    padding: 14px 20px 4px;
    font-size: var(--fs-micro);
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--muted-600);
  }

  .nav-item {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: var(--tap);
    padding: 0 20px;
    border-left: 3px solid transparent;
    color: var(--ink);
    font-size: var(--fs-body);
    font-weight: 400;
    transition: background-color var(--t-color) ease, color var(--t-color) ease;
  }
  /* 导航项不做 scale：整行缩放会让侧栏「抖」，council 的 .97 是给按钮的 */
  .nav-item:hover { background: var(--fill-100); text-decoration: none; }
  .nav-item:active { background: var(--fill-200); }
  /* 内缩描边，否则焦点框会被侧栏边界裁掉 */
  .nav-item:focus-visible { outline: 2px solid var(--action); outline-offset: -2px; }
  .nav-item.is-active {
    background: var(--action-100);
    color: var(--action-800);
    font-weight: 700;
    border-left-color: var(--action);
  }

  .sidebar-foot {
    flex: none;
    margin-top: auto;
    padding: 16px 20px;
    border-top: 1px solid var(--hairline);
  }
  .sidebar-name { font-size: var(--fs-body); font-weight: 700; }
  .sidebar-role { font-size: var(--fs-xs); color: var(--muted-700); }

  .topbar { min-height: var(--topbar-h); }

  /* 跨店对比表列多，不设 1200 硬顶；行长由列宽控制，不去限制表格宽度 */
  .app-main { max-width: 1440px; padding: 28px var(--pad) 40px; }
}

/* --- 面板 ---------------------------------------------------------------- */
.panel {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-panel);
  box-shadow: var(--e2);
  /* 里面的表格是方角，四角由面板自己裁 */
  overflow: hidden;
}
.panel-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 12px var(--card-pad);
  border-bottom: 1px solid var(--hairline);
}
.panel-head .kicker { letter-spacing: 0.1em; color: var(--ink); }
.panel-head-note { font-size: var(--fs-kicker); color: var(--muted-700); }
.panel-head-end { margin-left: auto; }
.panel-body { padding: var(--card-pad); }
/* 表格直贴面板边，不再套一层内距 */
.panel-body--flush { padding: 0; }
.panel-title { font-size: var(--fs-section); font-weight: 700; letter-spacing: -0.02em; }
.panel-sub { margin: 2px 0 0; font-size: var(--fs-xs); color: var(--muted-700); }

/* --- 按钮 ---------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--tap);
  padding: 0 16px;
  font-family: inherit;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
  text-align: center;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: var(--r-key);
  box-shadow: var(--e2);
  cursor: pointer;
  /* 逐属性列出，禁止 transition:all——否则 disabled 的 opacity 也会跟着动 */
  transition: transform var(--t-ui) ease, box-shadow var(--t-ui) ease,
              background-color var(--t-color) ease, color var(--t-color) ease;
}
.btn:hover { text-decoration: none; box-shadow: var(--e3); }
/* 按下是「落下去」，不是盖章；.97 与 160ms 是 council 强制值 */
.btn:active { transform: scale(0.97); box-shadow: var(--e1); }
.btn:focus-visible { outline: 2px solid var(--action); outline-offset: 2px; }

/* 应用内唯一主操作：navy 实底白字。平涂无描边无渐变；
   深度只走中性阴影层，不再有有色环境光（navy 已是最深的一档，不需要再发光） */
.btn--primary {
  background: var(--action);
  color: #fff;
  border: 0;
}
.btn--primary:hover { background: var(--action-700); color: #fff; }
.btn--primary:active { background: var(--action-800); color: #fff; transform: scale(0.97); box-shadow: var(--e1); }
/* navy 底上的 navy 描边看不见，改用白色 */
.btn--primary:focus-visible { outline-color: #fff; outline-offset: -4px; }

/* 品牌红 CTA：只允许出现在无数据语义的页面（登录页 Sign in 等），每屏一次。
   数据页面禁止使用——那里的红专属「未达标」 */
.btn--brand {
  background: var(--alert);
  color: #fff;
  border: 0;
}
.btn--brand:hover { background: var(--alert-700); color: #fff; }
.btn--brand:active { background: var(--alert-700); color: #fff; transform: scale(0.97); box-shadow: var(--e1); }
.btn--brand:focus-visible { outline-color: #fff; outline-offset: -4px; }

.btn--secondary { background: var(--surface); color: var(--ink); border-color: var(--hairline); }
.btn--secondary:hover { background: var(--n-100); color: var(--ink); }

/* 红底按钮只给不可逆操作；与 .btn--brand 同色不同语境，不得与达标红表格同屏相邻 */
.btn--danger { background: var(--alert); color: #fff; border-color: transparent; }
.btn--danger:hover { background: var(--alert-700); color: #fff; }

.btn--ghost {
  min-height: 32px;
  padding: 0 8px;
  background: transparent;
  color: var(--action-800);
  border-color: transparent;
  box-shadow: none;
}
.btn--ghost:hover { background: var(--action-100); box-shadow: none; }
.btn--ghost:active { transform: scale(0.97); box-shadow: none; }

.btn--lg { min-height: var(--btn-lg); padding: 0 20px; }
.btn--sm { min-height: 36px; }
.btn--block { display: flex; width: 100%; }
/* 全宽按钮上 .97 的位移观感偏大，降一档 */
.btn--block:active { transform: scale(0.99); }

.btn[disabled], .btn.is-disabled {
  opacity: 0.5;
  cursor: default;
  box-shadow: var(--e1);
  transform: none;
}
.btn[disabled]:hover, .btn.is-disabled:hover { box-shadow: var(--e1); }
.btn[disabled]:active, .btn.is-disabled:active { transform: none; box-shadow: var(--e1); }
.btn--primary[disabled], .btn--primary.is-disabled { box-shadow: var(--e1); }

.btn-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }

/* 提交中不 disabled：保留可聚焦，读屏才读得到 aria-busy；pointer-events 挡重复提交 */
.btn.is-loading { pointer-events: none; }

/* --- 表单 ---------------------------------------------------------------- */
.field { display: block; margin-bottom: 14px; }
.field:last-child { margin-bottom: 0; }
.field-label {
  display: block;
  margin-bottom: 5px;
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-600);
}
.field-note { margin: 5px 0 0; font-size: var(--fs-kicker); color: var(--muted-700); }
.field-error { margin: 5px 0 0; font-size: var(--fs-kicker); font-weight: 700; color: var(--alert-700); }

input[type="text"],
input[type="password"],
input[type="tel"],
input[type="email"],
input[type="date"],
input[type="search"],
select {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: 10px 12px;
  font-family: inherit;
  font-size: 16px; /* iOS 下 <16px 聚焦会强制放大页面 */
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-key);
  box-shadow: inset 0 1px 2px rgba(26, 48, 89, 0.04);
  appearance: none;
  -webkit-appearance: none;
  transition: border-color var(--t-color) ease, box-shadow var(--t-ui) ease;
}
select {
  /* appearance:none 去掉了原生箭头，用内联 SVG 补回来（不外链图标） */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8a91' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 18px 18px;
  padding-right: 40px;
}
input:hover, select:hover { border-color: var(--n-400); }

/* 全站唯一允许 outline:none 的地方——4px navy 光晕是等效替代，可见性不降 */
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--action);
  box-shadow: 0 0 0 4px rgba(26, 48, 89, 0.35);
}
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: none; }

input:disabled, select:disabled, textarea:disabled {
  background: var(--fill-100);
  color: var(--muted-700);
  cursor: not-allowed;
  box-shadow: none;
}
::placeholder { color: var(--muted-500); }

/* 红边不是唯一编码：必须同时有 .field-error 文字并 aria-describedby 关联 */
.is-invalid { border-color: var(--alert); }

/* --- 数据表 -------------------------------------------------------------- */
/* 横向溢出交给包裹层，表格本身不设 max-width */
.table-scroll { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

.dtable {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
/* 零圆角零投影零渐变——宪法第 1 条，任何装饰蔓延到这里即打回 */
.dtable th,
.dtable td {
  height: var(--row-h);
  padding: 0 var(--cell-pad-x);
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: middle;
}
.dtable thead th {
  position: sticky;
  top: 0;
  /* 必须低于 --z-header，否则滚动时表头会盖住顶部状态条 */
  z-index: var(--z-sticky-th);
  height: var(--th-h);
  background: var(--n-100);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-600);
  border-bottom: 1px solid var(--hairline);
}
.dtable tbody tr:last-child td { border-bottom: 0; }
/* 唯一允许的行反馈：底色。无位移、无投影、无边框变化 */
.dtable tbody tr:hover { background: var(--fill-100); }

.dtable--lg th,
.dtable--lg td { height: var(--row-h-lg); padding: 0 var(--cell-pad-x-lg); }

.dtable .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1; /* 老 WebKit 兜底 */
  white-space: nowrap;
}

/* 手机端横滑时店名列冻结在左侧 */
.dtable .col-sticky {
  position: sticky;
  left: 0;
  background: var(--surface);
}
.dtable thead .col-sticky { background: var(--n-100); z-index: var(--z-sticky-th); }

/* 行首 4px 状态色条：颜色之外还有位置编码，语义仍由同行文字承担 */
.dtable td.flag,
.dtable th.flag {
  width: var(--flag-w);
  padding: 0;
  background: var(--n-400);
}
.dtable thead th.flag { background: var(--n-400); }
.dtable tr.is-ontrack td.flag { background: var(--ok); }
.dtable tr.is-atrisk td.flag { background: var(--warn); }
.dtable tr.is-behind td.flag { background: var(--alert); }
/* 文字色一律 -700 档，白底 ≥4.5:1 */
.dtable tr.is-ontrack .num--status { color: var(--ok-700); }
.dtable tr.is-atrisk .num--status { color: var(--warn-700); font-weight: 700; }
.dtable tr.is-behind .num--status { color: var(--alert-700); font-weight: 700; }

/* --- 状态标签 ------------------------------------------------------------ */
/* 文案本身就是第二编码，黑白打印/色弱下仍可读 */
.tag {
  display: inline-block;
  padding: 2px 7px;
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--n-200);
  color: var(--n-700);
  border: 1px solid var(--n-400);
  border-radius: var(--r-tag);
  box-shadow: none;
}
.tag--ok,
.tag--ontrack { background: var(--ok); color: #fff; border-color: var(--ok); }
.tag--pending,
.tag--atrisk { background: var(--warn-100); color: var(--warn-700); border-color: var(--warn); }
.tag--failed,
.tag--behind { background: var(--alert); color: #fff; border-color: var(--alert); }
.tag--na { background: var(--n-200); color: var(--n-700); border-color: var(--n-400); }

/* --- 加载态 -------------------------------------------------------------- */
/* 只做透明度脉冲：不做位移、不做扫光渐变（扫光是装饰，会侵入数据区） */
.skeleton {
  background: var(--skeleton-bg);
  animation: pulse 1.6s ease-in-out infinite;
}
.skeleton-row { height: var(--row-h); margin-bottom: 1px; }
/* 骨架尺寸与真图一致，加载完才不会跳动 */
.skeleton-chart { aspect-ratio: var(--chart-ar); min-height: var(--chart-h-min); }

.spinner {
  width: var(--spinner-size);
  height: var(--spinner-size);
  flex: none;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: var(--r-puck);
  animation: spin 700ms linear infinite;
}
.spinner--lg { width: var(--spinner-size-lg); height: var(--spinner-size-lg); }

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }

/* --- 空态 / 错误态 ------------------------------------------------------- */
/* 无插画、无 emoji；容器高度尽量贴近成功态，避免布局跳动 */
.empty { padding: 32px var(--card-pad); text-align: center; }
.empty-title { font-size: var(--fs-body); font-weight: 700; }
.empty-note { margin: 6px 0 0; font-size: var(--fs-sm); color: var(--muted-700); }

.alert-note,
.errorbox {
  margin: 14px 0 0;
  padding: 10px 12px;
  background: var(--alert-100);
  color: var(--alert-700);
  border: 1px solid rgba(204, 39, 29, 0.22);
  /* 左侧 4px 实心条 = 颜色之外的第二编码 */
  border-left: 4px solid var(--alert);
  border-radius: var(--r-key);
  font-size: var(--fs-sm);
  font-weight: 700;
}
/* 「去 Portal 改密再来」不是「你错了」，用琥珀不用红 */
.alert-note--warn {
  background: var(--warn-100);
  color: var(--warn-700);
  border-color: rgba(196, 122, 10, 0.25);
  border-left-color: var(--warn);
}

/* --- 登录页 -------------------------------------------------------------- */
.auth {
  min-height: 100dvh; /* dvh 防 iOS 地址栏收起时卡片跳动 */
  display: grid;
  place-items: center;
  padding: var(--pad);
}
.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-panel);
  box-shadow: var(--e2);
  padding: 28px 24px;
}
/* 戏在字重对比上，不在装饰上：品牌 800 / 说明 400 */
.auth-brand {
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: var(--ink);
}
.auth-sub {
  margin: 6px 0 0;
  font-size: var(--fs-sm);
  font-weight: 400;
  color: var(--muted-700);
}
.auth-form { margin-top: 20px; }
.auth-submit { margin-top: 18px; }
.auth-foot {
  margin: 18px 0 0;
  font-size: var(--fs-kicker);
  color: var(--muted-700);
  text-align: center;
}

@media (max-width: 419px) {
  .auth-card { max-width: 100%; padding: 24px 18px; }
}

/* --- reduced-motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* 加载反馈是功能性的，不能停——只放慢 */
  .spinner { animation: spin 1.4s linear infinite !important; }
  .skeleton { animation: none; opacity: 0.8; }
}

/* --- 打印 ---------------------------------------------------------------- */
/* 状态好坏在打印件上靠 .tag 文字读出，不依赖颜色 */
@media print {
  .sidebar, .topbar, .tabbar, .btn, .skip-link { display: none !important; }
  .panel { box-shadow: none; border: 1px solid #999; }
  .app-main { max-width: none; padding: 0; }
}
