/* ============================================================================
   析光象限 · UI Kit v1.0  （2026-10-04）
   ----------------------------------------------------------------------------
   全端统一设计层：PC 桌面 / 直板手机（单屏）/ 折叠屏（折叠态 + 展开态）。

   设计说明见 项目根/UI设计说明.md。三条硬规则：
     ① 白底浅色（永不深色）  ② 涨红跌绿（A 股约定）  ③ 同信息架构，只换列数

   使用方式：在 assets/style.css **之后**引用本文件（同源后置覆盖）。
   本文件只做三件事：
     1) 定义设计 token（间距/字号/圆角/配色/图标/层级）—— 唯一数值来源；
     2) 定义 5 档断点与栅格/分栏/吸顶吸底规则；
     3) 提供通用组件与三态（空/加载/异常）+ 热区 + 焦点可见性。
   不重写各页既有类名的语义，避免回归。
   ========================================================================= */

/* ---------------------------------------------------------------------------
   1. 设计 token
   --------------------------------------------------------------------------- */
:root{
  /* 1.1 间距（4 的倍数，唯一来源；禁止硬编码 padding/margin） */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px;
  --sp-5:20px; --sp-6:24px; --sp-7:32px; --sp-8:48px;

  /* 1.2 字号阶梯 */
  --fs-cap:11px; --fs-xs:12px; --fs-sm:12.5px; --fs-base:13px; --fs-md:14px;
  --fs-lg:15.5px; --fs-h2:18px; --fs-h1:22px; --fs-num:24px;
  --lh-body:1.65; --lh-tight:1.35;

  /* 1.3 圆角 */
  --r-xs:5px; --r-sm:7px; --r-md:9px; --r-lg:11px; --r-xl:16px;
  --r-pill:999px; --r-full:50%;

  /* 1.4 配色 */
  --bg:#f6f7f9; --surf:#fff; --surf-2:#fafbfc; --surf-3:#f6fafd;
  --ink:#1f2328; --ink-2:#374151; --ink-3:#6b7280; --ink-4:#9aa1ab;
  --line:#e5e7eb; --line-2:#d8dde3; --line-3:#f0f2f4;

  --brand:#c0392b; --brand-2:#a93226; --brand-w:#fdf0ee; --brand-ln:#f3c9c2;
  --up:#c0392b; --dn:#0a8f4c;
  --info:#2b7fc9; --info-2:#1e5fa8; --info-w:#f6fafd; --info-ln:#dbe6f0;
  --warn:#b45309; --warn-w:#fdf3e7; --warn-ln:#f3ddc0;
  --ok:#0a8f4c; --ok-w:#f2fbf5; --ok-ln:#cdebd8;
  --focus:#2b7fc9;

  /* 1.5 图标尺寸 */
  --ico-xs:13px; --ico-sm:16px; --ico-md:20px; --ico-lg:24px; --ico-xl:32px;

  /* 1.6 层级 */
  --z-base:1; --z-sticky:30; --z-nav:50; --z-fab:60;
  --z-drawer:80; --z-modal:100; --z-toast:120;

  /* 1.7 阴影（只给浮层；卡片一律描边） */
  --sh-1:0 1px 2px rgba(16,24,40,.05);
  --sh-2:0 4px 14px rgba(16,24,40,.10);
  --sh-3:0 12px 32px rgba(16,24,40,.16);

  /* 1.8 布局标尺 */
  --nav-h:56px;
  --w-page:1120px;        /* LG 主容器 */
  --w-page-xl:1240px;     /* XL 主容器 */
  --gutter:18px;          /* 页面左右留白（断点内会收紧） */
  --tap:44px;             /* 触控最小热区 */

  /* 1.9 折叠屏（由 assets/fold-adapter.js 注入；未注入时为 0） */
  --hinge-safe:0px;
}

/* 折叠展开态：显式类（JS 可用时）作为宽度断点的补充，不是主要手段。
   宽度断点本身已能正确覆盖 600~899px 的展开内屏。 */
html.fold-open  { --w-page:var(--w-page-xl); }
html.fold-v .wrap{ padding-left:calc(var(--gutter) + var(--hinge-safe)) ;
                   padding-right:calc(var(--gutter) + var(--hinge-safe)); }

/* ---------------------------------------------------------------------------
   2. 基础与全局
   --------------------------------------------------------------------------- */
html{ -webkit-text-size-adjust:100%; }

/* 焦点可见性：统一 2px 焦点环。用 :focus-visible 而非 :focus，
   鼠标点击不弹环、键盘 Tab 才弹；这是可访问性的硬要求，不许 outline:none。 */
:where(a,button,[role=button],input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--focus);
  outline-offset:2px;
  border-radius:var(--r-xs);
}
/* 输入类：额外的边框高亮（焦点环可能被内联 overflow 裁掉） */
:where(input,textarea,select):focus{ border-color:var(--info) !important; }

/* 触摸设备：把热区与间距抬到可点标准 */
@media (pointer:coarse){
  :where(button,.btn,.btn2,.mini,.tab,.chip,a.cta){
    min-height:var(--tap);
  }
  /* nav 的 CTA 视觉 36px：用伪元素撑到 44（导航栏只有 50~52px 高，
     直接拉高会把品牌名挤走；热区越界到栏外不影响观感与点击） */
  .nav :where(.cta){
    position:relative; min-height:0;
  }
  .nav :where(.cta)::after{
    content:''; position:absolute; left:50%; top:50%;
    width:100%; height:100%; min-width:var(--tap); min-height:var(--tap);
    transform:translate(-50%,-50%);
  }
  input[type=checkbox]{ width:20px; height:20px; }
  input[type=range]{ height:34px; }
}

/* 选中文字配色 */
::selection{ background:#fbe3df; color:var(--ink); }

/* 滚动条：窄条浅色，不抢视线 */
*{ scrollbar-width:thin; scrollbar-color:var(--line-2) transparent; }
*::-webkit-scrollbar{ width:8px; height:8px; }
*::-webkit-scrollbar-thumb{ background:var(--line-2); border-radius:4px; }
*::-webkit-scrollbar-track{ background:transparent; }

/* 横向滚动容器：隐藏滚动条但保留可滑（用于 nav / chips / 表格外层） */
.noscroll-x{ overflow-x:auto; scrollbar-width:none; -webkit-overflow-scrolling:touch; }
.noscroll-x::-webkit-scrollbar{ display:none; }

/* ---------------------------------------------------------------------------
   3. 容器与栅格（5 档断点）
   XS <600 | SM 600-899 | MD 900-1199 | LG 1200-1439 | XL >=1440
   --------------------------------------------------------------------------- */
.wrap{
  max-width:var(--w-page);
  margin:0 auto;
  padding:0 var(--gutter) var(--sp-8);
}

/* 自适应栅格：默认 1 列 → SM 2 列 → MD 3 列 → LG/XL 4 列。
   minmax(0,1fr) 而非 1fr —— 否则宽表格/长单词会把列顶宽导致横向溢出。 */
.grid{ display:grid; gap:var(--sp-4); grid-template-columns:minmax(0,1fr); }
.grid-2,.grid-3,.grid-4{ display:grid; gap:var(--sp-4); grid-template-columns:minmax(0,1fr); }

/* 固定 2 列（窄屏也 2 列）：KPI 密排场景用，值是数字不会溢出 */
.grid-k2{ display:grid; gap:var(--sp-3); grid-template-columns:repeat(2,minmax(0,1fr)); }

@media (min-width:600px){
  .grid-2{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .grid-3{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .grid-4{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (min-width:900px){
  .wrap{ --gutter:22px; }
  .grid-3{ grid-template-columns:repeat(3,minmax(0,1fr)); }
  .grid-4{ grid-template-columns:repeat(3,minmax(0,1fr)); }
}
@media (min-width:1200px){
  .grid-4{ grid-template-columns:repeat(4,minmax(0,1fr)); }
}
@media (min-width:1440px){
  .wrap{ max-width:var(--w-page-xl); }
}

/* 主次分栏：XS/SM 纵向堆叠，MD+ 侧栏 + 主区。
   侧栏宽度用 clamp 让它在 MD 段平滑（避免 900px 处突然跳变）。 */
.split{ display:grid; gap:var(--sp-4); grid-template-columns:minmax(0,1fr); }
@media (min-width:900px){
  .split{ grid-template-columns:clamp(280px,26%,330px) minmax(0,1fr); }
  .split-side{
    position:sticky; top:calc(var(--nav-h) + var(--sp-3));
    align-self:start;
    max-height:calc(100vh - var(--nav-h) - var(--sp-7));
    overflow:auto;
  }
}
/* 等宽双栏（列表 | 详情）：折叠屏展开态用这个 —— 额外空间给「并列分组」，
   而不是把单列内容等比拉宽。 */
.split-2{ display:grid; gap:var(--sp-4); grid-template-columns:minmax(0,1fr); }
@media (min-width:600px){
  .split-2{ grid-template-columns:minmax(260px,38%) minmax(0,1fr); align-items:start; }
}

/* ---------------------------------------------------------------------------
   4. 顶部导航
   --------------------------------------------------------------------------- */
.nav{ position:relative; z-index:var(--z-nav); }
.nav .in{ height:var(--nav-h); }
.nav .links{
  white-space:nowrap; overflow-x:auto; scrollbar-width:none;
  min-width:0; -webkit-overflow-scrolling:touch;
}
.nav .links::-webkit-scrollbar{ display:none; }
.nav .links a{ flex:0 0 auto; }
.nav .brand,.nav .cta{ flex:0 0 auto; }

@media (max-width:899px){
  :root{ --nav-h:52px; }
  .nav .in{ gap:10px; padding:0 var(--sp-3); }
  .brand{ font-size:15.5px; }
  .nav .links{ gap:13px; font-size:13px; }
  .nav .cta{ padding:6px 12px; font-size:12.5px; min-height:36px; display:inline-flex; align-items:center; }
}
@media (max-width:599px){
  :root{ --nav-h:50px; }
  .nav .in{ gap:8px; padding:0 var(--sp-2) 0 var(--sp-3); }
  .brand{ font-size:15px; letter-spacing:.3px; }
  .nav .links{ gap:12px; font-size:12.5px; }
  .nav .cta{ padding:5px 10px; font-size:12px; }
}

/* ---------------------------------------------------------------------------
   5. 卡片 / 面板 / KPI
   --------------------------------------------------------------------------- */
.card,.panel{
  background:var(--surf);
  border:1px solid var(--line);
  border-radius:var(--r-lg);
  padding:var(--sp-5) var(--sp-5);
  margin-bottom:var(--sp-4);
}
@media (max-width:599px){
  .card,.panel{ padding:var(--sp-4); border-radius:var(--r-md); }
}

.kpi{
  background:var(--surf); border:1px solid var(--line);
  border-radius:var(--r-sm); padding:var(--sp-3) var(--sp-4);
}
.kpi .v{
  font-size:var(--fs-num); font-weight:700; line-height:1.15;
  font-variant-numeric:tabular-nums;
}
.kpi .l{ font-size:var(--fs-xs); color:var(--ink-2); margin-top:3px; }
.kpi .s{ font-size:var(--fs-cap); color:var(--ink-4); }
@media (max-width:599px){
  .kpi .v{ font-size:21px; }
  .kpi{ padding:var(--sp-3); }
}

/* ---------------------------------------------------------------------------
   6. 按钮 / 标签页 / chip
   热区：所有按钮 44px 起。视觉尺寸小的按钮用透明伪元素撑热区，
   这样视觉不变但手指够得着 —— 比强行放大按钮好看且不破坏排版。
   --------------------------------------------------------------------------- */
.btn,.btn2,.mini{
  display:inline-flex; align-items:center; justify-content:center; gap:6px;
  min-height:var(--tap);
  border-radius:var(--r-sm);
  font-size:var(--fs-md); font-weight:600;
  cursor:pointer; text-decoration:none;
  transition:background .12s, border-color .12s, color .12s;
  position:relative;
}
.btn{ background:var(--brand); color:#fff; border:1px solid var(--brand); padding:0 var(--sp-5); }
.btn:hover{ background:var(--brand-2); border-color:var(--brand-2); }
.btn.sec{ background:var(--surf); color:var(--ink-2); border-color:var(--line-2); }
.btn.sec:hover{ background:var(--surf-2); border-color:var(--brand); color:var(--brand); }

.btn2{
  background:var(--surf); color:var(--ink-2); border:1px solid var(--line-2);
  padding:0 var(--sp-4); font-size:var(--fs-base);
}
.btn2:hover{ border-color:var(--brand); color:var(--brand); }
.btn2.primary{ background:var(--brand); border-color:var(--brand); color:#fff; }
.btn2.primary:hover{ background:var(--brand-2); color:#fff; }

.mini{
  background:var(--surf); color:var(--ink-2); border:1.5px solid var(--line-2);
  padding:0 var(--sp-4); font-size:var(--fs-base); font-weight:500;
}
.mini:hover{ background:var(--surf-2); border-color:var(--info); color:var(--info-2); }

/* ---- 紧凑按钮：视觉尺寸小，但热区必须够手指 ----
   为什么用伪元素而不是直接加大 padding：
   表格行内/帖子底栏的空间是稀缺的，把每个按钮都撑到 44px 高会把行高顶爆、
   一屏少看两三行。伪元素做「隐形热区」—— 视觉不变，触控面达标。
   注意：需要父级 overflow 不为 hidden，否则热区被裁（.pacts 已确认可见）。
   这一类覆盖了历史上全部 27~31px 的行内小按钮（actbtn / rowgen / copy）。 */
.btn-tiny,
:where(.actbtn,.rowgen,.copy,.mini-btn,.icon-btn){
  position:relative;
}
.btn-tiny::after,
:where(.actbtn,.rowgen,.copy,.mini-btn,.icon-btn)::after{
  content:''; position:absolute; left:50%; top:50%;
  width:100%; height:100%;
  min-width:var(--tap); min-height:var(--tap);
  transform:translate(-50%,-50%);
  /* 不遮挡视觉、不截获事件之外的任何东西 */
  pointer-events:auto;
}
/* 伪元素自身就是点击目标（它覆盖在按钮之上，事件仍冒泡到按钮） */
.btn-tiny{ min-height:0; padding:5px 12px; font-size:var(--fs-xs);
  border-radius:var(--r-sm); background:var(--surf); color:var(--brand);
  border:1px solid var(--brand); font-weight:600; cursor:pointer; }
.btn-tiny:hover{ background:var(--brand); color:#fff; }

/* XS + SM（<900px）：这一区间是直板手机与折叠屏展开态，用户几乎全用手指。
   此时行高不是瓶颈 —— 页面本来就要纵向滚动 —— 所以给真实尺寸而不是靠伪元素。 */
@media (max-width:899px){
  :where(.actbtn,.rowgen,.copy,.pager button,.mini-btn,.icon-btn){
    min-height:34px;
    display:inline-flex; align-items:center; justify-content:center;
  }
  .pacts{ gap:var(--sp-1); }
  .pacts :where(.actbtn,.rowgen,.copy){ min-height:36px; }
}

/* 页内小按钮：全宽度适用。它们散落在各页内联样式里（aibtn / pager button …），
   不是统一组件，所以在 kit 里统一兜底 —— 视觉尺寸不变，靠隐形热区达标。
   为什么不分断点：鼠标场景 31px 的按钮也偏小（触控板/老年用户/手抖），
   撑热区对鼠标零副作用（只是更容易命中）。 */
:where(.pager button,.aibtn,.actbtn,.rowgen,.copy,.mini-btn,.icon-btn,.pgbtn,.swbtn){
  position:relative;
}
:where(.pager button,.aibtn,.actbtn,.rowgen,.copy,.mini-btn,.icon-btn,.pgbtn,.swbtn)::after{
  content:''; position:absolute; left:50%; top:50%;
  width:100%; height:100%; min-width:var(--tap); min-height:var(--tap);
  transform:translate(-50%,-50%);
}

/* 禁用态统一：降透明、禁手型，但保留可读 */
:where(button,.btn,.btn2,.mini):disabled,
.is-disabled{ opacity:.45; cursor:not-allowed; pointer-events:none; }

.tabs{
  display:flex; gap:var(--sp-2); flex-wrap:wrap;
  margin:var(--sp-3) 0 var(--sp-3);
}
.tab{
  min-height:var(--tap);
  display:inline-flex; align-items:center;
  background:var(--surf); border:1px solid var(--line-2);
  border-radius:var(--r-sm); padding:0 var(--sp-5);
  font-size:var(--fs-md); color:var(--ink-2); cursor:pointer;
  transition:background .12s, border-color .12s, color .12s;
}
.tab:hover{ background:var(--info-w); border-color:var(--info-ln); color:var(--info-2); }
.tab.on{ background:var(--brand); border-color:var(--brand); color:#fff; font-weight:600; }
@media (max-width:599px){
  .tabs{ gap:var(--sp-1); flex-wrap:nowrap; overflow-x:auto;
         scrollbar-width:none; -webkit-overflow-scrolling:touch;
         margin-left:calc(-1 * var(--sp-3)); margin-right:calc(-1 * var(--sp-3));
         padding:0 var(--sp-3) 2px; }
  .tabs::-webkit-scrollbar{ display:none; }
  .tab{ padding:0 var(--sp-3); font-size:var(--fs-sm); flex:0 0 auto; }
}

/* chip 组：可点筛选/多选 */
.chips{ display:flex; gap:var(--sp-2); flex-wrap:wrap; align-items:center; }
.chip{
  display:inline-flex; align-items:center; gap:5px;
  min-height:36px; padding:4px 12px;
  border:1px solid var(--line); border-radius:var(--r-pill);
  background:var(--surf); color:var(--ink-2);
  font-size:var(--fs-xs); cursor:pointer;
  max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* 触控/窄屏下 chip 再高一点 —— 它们是主要筛选取向，手指要够得着 */
@media (max-width:899px){
  .chip{ min-height:38px; }
}
.chip:hover{ border-color:var(--info); color:var(--info-2); }
.chip.on{ background:var(--brand-w); border-color:var(--brand-ln); color:var(--brand); font-weight:600; }
.chip.on i{ color:var(--brand); }
.chip b{ font-variant-numeric:tabular-nums; }
/* 作为 chip 的 span 也要撑热区（用伪元素，不让视觉变大） */
span.chip{ position:relative; }
span.chip::after{
  content:''; position:absolute; left:50%; top:50%;
  width:100%; height:100%; min-width:var(--tap); min-height:var(--tap);
  transform:translate(-50%,-50%);
}

/* ---------------------------------------------------------------------------
   7. 徽标 / 状态
   --------------------------------------------------------------------------- */
.badge{
  display:inline-block; font-size:var(--fs-cap); font-weight:600;
  padding:2px 9px; border-radius:var(--r-pill); white-space:nowrap;
  border:1px solid transparent;
}
.badge-up  { background:var(--brand-w); color:var(--brand); border-color:var(--brand-ln); }
.badge-dn  { background:var(--ok-w);    color:var(--ok);    border-color:var(--ok-ln); }
.badge-info{ background:#eef4fb;        color:#1f5fa8;      border-color:#cfe0f2; }
.badge-warn{ background:var(--warn-w);  color:var(--warn);  border-color:var(--warn-ln); }
.badge-muted{ background:#f3f4f6;       color:var(--ink-3); border-color:#e0e3e8; }
.badge-ok  { background:var(--ok-w);    color:var(--ok);    border-color:var(--ok-ln); }

/* ---------------------------------------------------------------------------
   8. 表格
   窄屏策略二选一（见 设计说明 §3.2）：
     列 ≤5 → `.tbl-cards` 卡片化；列 ≥6 → `.tbl-scroll` 容器内横滚 + 表头吸顶。
   两者都绝不允许把整页撑宽。
   --------------------------------------------------------------------------- */
.tbl{ width:100%; border-collapse:collapse; font-size:var(--fs-sm); }
.tbl th{
  background:var(--surf-2); color:var(--ink-3); font-weight:600;
  text-align:left; padding:var(--sp-2) var(--sp-3);
  border-bottom:1px solid var(--line);
}
.tbl td{
  padding:var(--sp-2) var(--sp-3);
  border-bottom:1px solid var(--line-3);
  font-variant-numeric:tabular-nums;
}
.tbl td.up{ color:var(--up); font-weight:600; }
.tbl td.dn{ color:var(--dn); font-weight:600; }

/* 吸顶表头（MD+）：top 让过导航高度 */
@media (min-width:900px){
  .tbl-scroll.sticky-head thead th{
    position:sticky; top:var(--nav-h); z-index:var(--z-sticky);
    background:var(--surf-2);
    box-shadow:inset 0 -1px 0 var(--line);
  }
}

/* 容器内横滚：双保险 —— 外层 overflow 兜住，表格自身也有 min-width */
.tbl-scroll{ overflow-x:auto; -webkit-overflow-scrolling:touch; max-width:100%; }

/* 窄屏横滚模式：给表格一个最小宽度，让列不被挤成一行一字 */
@media (max-width:899px){
  .tbl-scroll .tbl{ min-width:720px; }
  .tbl-scroll .tbl th,.tbl-scroll .tbl td{ padding:var(--sp-2) var(--sp-2); white-space:nowrap; }
}

/* 窄屏卡片化：每行一张卡，th 变字段名（靠 data-label 或首列） */
@media (max-width:599px){
  .tbl-cards{ border:0; }
  .tbl-cards thead{ display:none; }
  .tbl-cards tr{
    display:block; background:var(--surf);
    border:1px solid var(--line); border-radius:var(--r-md);
    padding:var(--sp-3); margin-bottom:var(--sp-2);
  }
  .tbl-cards td{
    display:flex; justify-content:space-between; gap:var(--sp-3);
    padding:5px 0; border:0;
    font-size:var(--fs-sm); line-height:1.5;
  }
  .tbl-cards td::before{
    content:attr(data-label);
    color:var(--ink-4); font-size:var(--fs-xs); font-weight:500; flex:0 0 auto;
  }
  .tbl-cards td:not([data-label])::before{ content:''; }
}

/* ---------------------------------------------------------------------------
   9. 工具条（可吸顶）
   --------------------------------------------------------------------------- */
.toolbar{
  display:flex; gap:var(--sp-3); align-items:center; flex-wrap:wrap;
  margin-bottom:var(--sp-3);
}
.toolbar.sticky{
  position:sticky; top:var(--nav-h); z-index:var(--z-sticky);
  background:var(--bg);
  padding:var(--sp-2) 0;
  box-shadow:0 1px 0 var(--line);
}
/* 工具条在窄屏：搜索框独占一行，按钮横滑不换行（换行会把工具条撑很高） */
@media (max-width:599px){
  .toolbar{ gap:var(--sp-2); }
  .toolbar > :where(input,select,.inp,.sel){ flex:1 1 100%; max-width:none !important; }
}

/* ---------------------------------------------------------------------------
   10. 表单
   --------------------------------------------------------------------------- */
.inp,.sel,.ta{
  width:100%; padding:9px 12px;
  border:1px solid var(--line-2); border-radius:var(--r-md);
  font-size:var(--fs-base); font-family:inherit; color:var(--ink);
  background:var(--surf); outline:none;
  transition:border-color .12s, box-shadow .12s;
}
.inp:focus,.sel:focus,.ta:focus{
  border-color:var(--info) !important;
  box-shadow:0 0 0 3px rgba(43,127,201,.14);
}
.inp::placeholder,.ta::placeholder{ color:var(--ink-4); }
.ta{ line-height:1.75; resize:vertical; }
@media (pointer:coarse){
  .inp,.sel{ min-height:var(--tap); }
  .ta{ min-height:120px; }
}

/* ---------------------------------------------------------------------------
   11. 三态：空 / 加载 / 异常
   硬规则：每个异步区域都必须有这三态。历史「一片白」的投诉全部来自缺态。
   --------------------------------------------------------------------------- */
.st-empty,.st-fail,.st-load{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:var(--sp-2); text-align:center;
  padding:var(--sp-7) var(--sp-5);
  border-radius:var(--r-md);
  font-size:var(--fs-base); line-height:1.75;
}
.st-empty{ color:var(--ink-3); background:var(--surf-2); border:1px dashed var(--line-2); }
.st-empty .ico{ font-size:var(--ico-xl); line-height:1; color:var(--ink-4); }
.st-empty b{ color:var(--ink-2); font-size:var(--fs-md); }
.st-empty .hint{ font-size:var(--fs-xs); color:var(--ink-4); max-width:460px; }

.st-load{
  flex-direction:row; color:var(--info-2); background:var(--info-w);
  border:1px solid var(--info-ln); padding:var(--sp-3) var(--sp-4);
  font-size:var(--fs-sm); justify-content:flex-start; text-align:left;
}
.st-load .hint{ color:var(--ink-3); font-size:var(--fs-xs); }

.st-fail{
  color:var(--brand); background:var(--brand-w);
  border:1px solid var(--brand-ln); padding:var(--sp-3) var(--sp-4);
  align-items:flex-start; text-align:left; font-size:var(--fs-sm);
}
.st-fail b{ color:var(--brand); }
.st-fail .why{ color:var(--ink-2); font-size:var(--fs-xs); margin-top:2px; }
.st-fail .do{ margin-top:var(--sp-2); display:flex; gap:var(--sp-2); flex-wrap:wrap; }

/* 密度：窄屏三态留白收紧，否则半屏都是空白 */
@media (max-width:599px){
  .st-empty{ padding:var(--sp-6) var(--sp-4); }
}

/* 骨架屏：闪光占位。尊重 prefers-reduced-motion。 */
.skel{
  background:linear-gradient(90deg,#eef0f3 25%,#f6f7f9 37%,#eef0f3 63%);
  background-size:400% 100%; animation:skshine 1.4s ease infinite;
  border-radius:var(--r-xs);
}
.skel-line{ height:11px; margin:var(--sp-2) 0; }
.skel-line.w40{ width:40%; } .skel-line.w60{ width:60%; } .skel-line.w80{ width:80%; }
.skel-card{ height:74px; border-radius:var(--r-md); margin-bottom:var(--sp-2); }
@keyframes skshine{ from{ background-position:100% 0; } to{ background-position:-100% 0; } }

/* 兼容既有 .spin（style.css 已定义动画，这里补尺寸变体） */
.spin{ width:13px; height:13px; border-radius:50%; flex:0 0 auto;
  border:2px solid #c6dced; border-top-color:var(--info);
  animation:xgspin .75s linear infinite; }
.spin.lg{ width:18px; height:18px; border-width:2.5px; }

@media (prefers-reduced-motion:reduce){
  .skel{ animation:none; }
  .spin{ animation:none; opacity:.7; }
  .prog-fill.indet{ animation:none; }
  *{ scroll-behavior:auto !important; }
}

/* ---------------------------------------------------------------------------
   12. 吸底操作条（XS 主操作常驻拇指区）
   --------------------------------------------------------------------------- */
.sticky-actions{
  position:fixed; left:0; right:0; bottom:0; z-index:var(--z-sticky);
  display:flex; gap:var(--sp-2); align-items:center;
  padding:var(--sp-2) var(--sp-3) calc(var(--sp-2) + env(safe-area-inset-bottom,0px));
  background:rgba(255,255,255,.96);
  backdrop-filter:saturate(150%) blur(8px);
  border-top:1px solid var(--line);
}
.sticky-actions .btn,.sticky-actions .btn2{ flex:1; }
@media (min-width:900px){ .sticky-actions{ display:none; } }
/* 有吸底条时给 body 留出空间，避免遮住页面最后一行 */
body.has-sticky-actions{ padding-bottom:calc(var(--tap) + var(--sp-5)); }

/* ---------------------------------------------------------------------------
   13. 抽屉 / 模态 / 提示
   --------------------------------------------------------------------------- */
.veil-full{
  position:fixed; inset:0; background:rgba(31,35,40,.42);
  z-index:var(--z-drawer);
}
.modal{
  position:fixed; z-index:var(--z-modal);
  left:50%; top:50%; transform:translate(-50%,-50%);
  width:min(92vw,560px); max-height:86vh; overflow:auto;
  background:var(--surf); border-radius:var(--r-xl);
  box-shadow:var(--sh-3); padding:var(--sp-6);
}
@media (max-width:599px){
  /* 窄屏：模态改为底部弹出（拇指可达） */
  .modal{
    left:0; right:0; top:auto; bottom:0; transform:none;
    width:auto; max-height:88vh;
    border-radius:var(--r-xl) var(--r-xl) 0 0;
    padding:var(--sp-5) var(--sp-4) calc(var(--sp-5) + env(safe-area-inset-bottom,0px));
  }
}

/* ---------------------------------------------------------------------------
   14. 文字工具类
   --------------------------------------------------------------------------- */
.ellip{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ellip-2{
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden;
}
.break{ word-break:break-word; overflow-wrap:anywhere; }
.num{ font-variant-numeric:tabular-nums; }
.up{ color:var(--up); } .dn{ color:var(--dn); }
.muted{ color:var(--ink-3); } .faint{ color:var(--ink-4); }
.cap{ font-size:var(--fs-cap); }
.nowrap{ white-space:nowrap; } .wrap-any{ white-space:normal; }
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}

/* ---------------------------------------------------------------------------
   15. 打印（研报导出观感）
   --------------------------------------------------------------------------- */
@media print{
  .nav,.sticky-actions,.fab,.no-print{ display:none !important; }
  .wrap{ max-width:none; padding:0; }
  .card,.panel{ break-inside:avoid; box-shadow:none; }
}
