/* ============================================================
   state.css —— 空 / 加载 / 出错
   ------------------------------------------------------------
   这三样以前一个都没做。不是忘了，是「先做有数据的样子」更容易——
   数据一多，截图就好看，评审就容易过。但真上线第一天，
   运营面对的全是空的：新客户没项目、新账号没库存、筛选没结果。

   这套组件的第一原则：**空态第一句必须回答「这是不是出事了」**。
   用户看到空白，第一个念头是「我弄坏了吗」，不是「我该建一条」。
   所以你看到的每一种空，都先定性、再给路。

   第二条：**四种空长得像，用户下一步动作完全不同**。
   把「加载失败」画成「暂无数据」是这个项目里最贵的一种错 ——
   运营会以为客户没下单，其实接口 500 了，等到周五才有人发现。

   第三条：不用插画。后台一天看十次空态，插画是噪音。
   一个 24px 的线图标 + 一句话，够了。
   ============================================================ */

/* ---------------- 容器 ---------------- */
.st{
  display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:2.6em 1.3em;max-width:34em;margin:0 auto;
}
.st .gl{
  width:2.7em;height:2.7em;border-radius:.72em;flex:none;
  display:flex;align-items:center;justify-content:center;
  background:var(--line2);color:var(--t3);margin-bottom:.85em;
}
.st .gl svg{width:1.4em;height:1.4em;display:block}

/* 四种空用四种底色：灰=正常情况，蓝=条件问题，橙=要找人，红=真出事。
   颜色不是装饰，是让运营两米外扫一眼就知道要不要紧张。 */
.st.k-empty .gl{background:#F2F3F5;color:var(--t3)}
.st.k-filter .gl{background:var(--blue-l);color:var(--blue)}
.st.k-deny   .gl{background:var(--warn-l);color:var(--warn)}
.st.k-err    .gl{background:var(--dan-l);color:var(--dan)}
/* 第五种：空得对。绿色不是装饰 —— 它让运营知道「这一块不用管」，
   省下来的注意力可以放到真正红着的那几块上。 */
.st.k-clear .gl{background:var(--ok-l);color:var(--ok)}

/* 「这是正常的」这句话要单独成一行、带色、稍重。
   混在解释里就没人在意了，用户还是会去找刷新按钮。 */
.st .af{
  font-size:.9em;color:var(--ok);line-height:1.7;margin-top:.5em;font-weight:500;max-width:28em;
}

.st h4{
  font-size:1.02em;font-weight:600;letter-spacing:-.1px;line-height:1.5;
  color:var(--t1);text-wrap:balance;
}
.st p{font-size:.92em;color:var(--t2);line-height:1.78;margin-top:.45em;max-width:29em}

/* 「为什么会这样」—— 后台必须有这一块。
   只写「暂无数据」等于把排查成本推给用户；写清原因，他才知道
   是自己没建、还是条件筛没了、还是根本没权限。 */
.st .why{
  width:100%;text-align:left;margin-top:1.05em;padding:.72em .88em;border-radius:.6em;
  background:var(--bg);border-left:2.5px solid var(--line);
  font-size:.86em;color:var(--t2);line-height:1.72;
}
.st .why b{display:block;font-size:.94em;color:var(--t1);font-weight:600;margin-bottom:.15em}
.st.k-deny .why{border-left-color:#E8C07A}
.st.k-err  .why{border-left-color:#F0B3AD}

/* 筛空必须把生效的条件摆出来。
   「没有符合条件的结果」和「没有数据」是两句话，
   不说清楚，用户会去建一条重复的数据。 */
.st .conds{
  display:flex;flex-wrap:wrap;gap:.35em;justify-content:center;margin-top:.9em;
  font-size:.82em;
}
.st .conds span{
  padding:.16em .55em;border-radius:.35em;background:var(--blue-l);
  color:var(--blue);border:1px dashed #BFD3FF;white-space:nowrap;
}

/* 「找谁」这一行必须比解释更显眼 —— 挡空状态下，用户唯一能做的事就是找人。
   只写「无权限」而不写人名，等于把他扔在原地。 */
.st .who{
  width:100%;text-align:left;margin-top:.7em;padding:.6em .88em;border-radius:.55em;
  background:var(--warn-l);border:1px solid #F2DDB4;
  font-size:.86em;line-height:1.7;color:#5C3B00;display:flex;gap:.55em;align-items:flex-start;
}
.st .who b{
  flex:none;font-size:.9em;font-weight:700;color:var(--warn);
  padding:.1em .4em;background:#fff;border-radius:.3em;border:1px solid #F2DDB4;
}
.st .who span{flex:1;min-width:0}

.st .acts{display:flex;gap:.5em;margin-top:1.25em;flex-wrap:wrap;justify-content:center}

/* 状态块里的按钮要能吃两套底子：客户端是 .btn（实心蓝、11px 内padding），
   后台是 13px 密排（白底描边、29px 高）。由容器决定长相，
   state.js 不需要知道自己在哪个端 —— 少一处判断就少一处漂移。 */
.st .acts .btn{flex:none;padding:.6em 1.05em;font-size:.9em;border-radius:.55em}
.st .acts .btn.ghost{background:#fff}
.ah-main .st .acts .btn{
  height:29px;padding:0 12px;font-size:12px;font-weight:500;border-radius:6px;
}
.ah-main .st .acts .btn:not(.pri){background:#fff;color:var(--t2);border:1px solid var(--line)}
.ah-main .st .acts .btn:not(.pri):hover{background:#fff;border-color:#C9CDD4;color:var(--t1)}
.ah-main .st .acts .btn.pri:hover{background:var(--blue-d)}
.ah-main .st.k-err .acts .btn.pri:hover{background:#B42318}

/* 请求号 / 重试次数 / 数据截止时间。开发查线上问题，第一个问的就是这个。 */
.st .meta{
  margin-top:1.05em;font-size:.78em;color:var(--t3);line-height:1.6;
  font-variant-numeric:tabular-nums;letter-spacing:.01em;
}
.st .meta code{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.96em;color:var(--t2);background:var(--line2);padding:0 .3em;border-radius:.25em;
}

/* 嵌在表格/卡片里时收一收 —— 一屏里出现两个大空态，比空白更乱 */
.st.inBox{padding:2em 1em}
.st.inRow{padding:2.1em 1em;max-width:none}

/* 加载态用同一套骨架，但不要图标 —— 图标会让人以为已经有结论了 */
.st.load{padding:2.4em 1.3em}
.st.load .gl{background:transparent;color:var(--t3);animation:spin 1.1s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){
  .st.load .gl{animation:none}
}

/* ---------------- 骨架屏 ----------------
   骨架不是「加载动画」，是「提前把版式占住」。
   转圈居中会让页面高度从 0 跳到 800，用户屏幕上的按钮跑掉，
   第二次点击就点错了。所以骨架要长得像真内容。 */
.sk{
  border-radius:4px;background-color:#EDEFF2;
  background-image:linear-gradient(90deg,#EDEFF2 0%,#F7F8FA 50%,#EDEFF2 100%);
  background-size:200px 100%;background-repeat:no-repeat;
  animation:shim 1.3s linear infinite;
}
@keyframes shim{from{background-position:-200px 0}to{background-position:calc(100% + 200px) 0}}
@media (prefers-reduced-motion:reduce){.sk{animation:none;background-image:none}}

.sk.l{height:1em;border-radius:3px}
.sk.l.sm{height:.82em}
.sk.l.xs{height:.66em}
.sk.b{height:3.3em}
.sk.c{border-radius:50%}
.skg{display:grid;gap:.72em}
.skg.row{display:flex;align-items:center;gap:.7em}

/* 表格骨架行：列宽跟真表格对齐，加载完不用重排 */
.skrow td{padding:9px 12px;border-bottom:1px solid var(--line2)}
.skrow:last-child td{border-bottom:0}

/* ---------------- 局部刷新 ----------------
   筛选、翻页、重算 —— 这些都只该影响那一块。
   整页闪白再画回来，等于每次点筛选都把用户的视线清零一次。 */
.reloading{position:relative;opacity:.42;pointer-events:none;transition:opacity .16s}
.reloading::after{
  content:'';position:absolute;inset:0;background:rgba(255,255,255,.35);
  border-radius:inherit;
}

/* 顶部细进度条：不确定时长时用它，比转圈诚实 ——
   转圈转到 8 秒用户就开始怀疑卡死了，进度条一直在走就不慌。 */
.rbar{height:2px;background:var(--blue-l);overflow:hidden;border-radius:1px;position:relative;margin-bottom:10px}
.rbar i{
  position:absolute;top:0;bottom:0;width:32%;background:var(--blue);border-radius:2px;
  animation:slide 1.05s cubic-bezier(.4,0,.2,1) infinite;
}
@keyframes slide{from{left:-32%}to{left:100%}}
@media (prefers-reduced-motion:reduce){.rbar i{animation:none;left:0;width:100%}}

/* ---------------- 出错：三级 ----------------
   .retry  可重试（网络、超时、502）→ 给重试，并且显示重试了几次
   .final  不可重试（403/404/参数错）→ 不给重试按钮。给了就是骗人，
           用户点三次还在原地，从此不再相信任何「重试」
   .part   部分失败 → 不给整页错误，好数据照显，坏的那几条单独说
   第三种最常见，也最容易被懒成第一种。 */
.st.k-err .acts .bt.pri{background:var(--dan);border-color:var(--dan)}
.st.k-err .acts .bt.pri:hover{background:#B42318;border-color:#B42318}

/* 重试次数用完了要换话术，不能还挂着按钮让他一直点 */
.st .tries{font-size:.8em;color:var(--t3);margin-top:.55em;font-variant-numeric:tabular-nums}

/* 「还没有配置」这类空态里的下一步，常常不是新建而是去别处先做一件事。
   用 .st .linknext 把那个跨页动作和主按钮区分开。 */
.st .linknext{
  display:inline-flex;align-items:center;gap:.3em;margin-top:.85em;
  font-size:.86em;color:var(--blue);cursor:pointer;text-decoration:none;
  padding:.25em .1em;
}
.st .linknext:hover{text-decoration:underline}

/* ---------------- 规范缺项：给开发看的，不是给用户看的 ----------------
   原型阶段让它红着，评审时一眼看见「这个空态没给下一步」；
   正式实现换成 lint 拦截，这一块根本渲染不出来。 */
.specmiss{
  width:100%;text-align:left;margin-top:.8em;padding:.42em .7em;border-radius:.4em;
  font-size:.8em;line-height:1.6;background:#FFF1F0;border:1px dashed #E8837A;color:#A32618;
}
.specmiss::before{content:'⚠ ';font-weight:700}
