/* ============================================================================
   progress — 进度条
   ============================================================================
   为什么需要它（通行系统的必备件）
   ---------------------------------------------------------------------------
   「已知进度」和 skeleton 的「未知进度」是两件事：
     · 进度**已知**（上传 3MB 到了 60%）⇒ 用 progress 给出**可预期**的反馈
     · 进度**未知**（不知道要多久）  ⇒ 用 skeleton（本库已有）
   ⭐ 两者混用是常见错误：不知道进度却给一个假的百分比，比不给更糟。

   参照：Carbon ProgressBar / Ant Design Progress / MUI LinearProgress

   设计要点
   ---------------------------------------------------------------------------
   ① **纯 CSS，无 JS**（用 `--progress` 自定义属性驱动）
   ② 四种形态：线形 / 环形 / 不确定（indeterminate）/ 步骤分段
   ③ 动画尊重 prefers-reduced-motion（WCAG 2.3.3，本库铁律）
   ④ 暗色用令牌，不硬编码
   ⑤ **零硬编码色**（准入清单第 ④ 条）
   ============================================================================ */

/* ============================================================================
   1 · 线形进度条（最常用）
   ============================================================================ */
.progress {
  display: block;
  width: 100%;
  height: var(--progress-h);
  background: var(--surface-sunken);
  border-radius: var(--r-full);   /* 胶囊形 */
  overflow: hidden;
  /* 🔴 强制色模式下的边界预留（0.17.0 实拍：没有它进度条整体消失）
     ---------------------------------------------------------------------
     Windows 高对比度下 `background` 被强制成 Canvas，轨道与填充条**同色**
     ⇒ 735×6 的面积全白，用户完全看不出进度。

     `outline: 1px solid transparent` 是这里的正解，不是笔误：
       · 正常态：transparent ⇒ 看不见，且 outline **不占布局**，胶囊形不变
       · 强制色下：浏览器把 transparent 替换成 CanvasText
         ⇒ 自动显出一条 1px 实线，轨道因此有了轮廓
     ⚠️ 别改成 `border: 1px solid transparent`：border 在 border-box 下会
        吃掉 2px 内容高，`--progress-h: 4px` 的细条就只剩 2px 了。
     ⚠️ 也别用 `box-shadow: 0 0 0 1px transparent` 兜底 —— 实测无效，
        box-shadow 在强制色下整个被移除，透明的也一样。
     判据见 05-audit/forced-colors-check.js A2/A3。 */
  outline: 1px solid transparent;
  outline-offset: -1px;          /* 画在内侧，不与相邻元素抢位置 */
  /* ⚠️ 不用 <progress> 原生标签的原因：它在部分浏览器里无法设成胶囊形，
     且 ::-webkit-progress-value 的圆角行为不一致。 */
}

.progress__bar {
  display: block;
  height: 100%;
  width: var(--progress, 0%);
  background: var(--accent);
  border-radius: inherit;
  /* ⭐ 用 ease-out 而不是 linear —— 进度条是"向前"的 feel，
     匀速反而像卡住了。缓出更符合心理预期。 */
  transition: width var(--progress-dur) var(--ease-out);
}

/* 语义色变体（上传失败 / 即将超时 / 已完成） */
.progress--success .progress__bar { background: var(--success); }
.progress--warning .progress__bar { background: var(--warning); }
.progress--danger  .progress__bar { background: var(--danger); }

/* 🔴 强制色：填充条必须换「系统高亮色」，不能靠作者色
   ---------------------------------------------------------------------------
   强制色模式下所有作者写的 background-color 都被替换成 Canvas（白/黑）
   ⇒ 填充条与轨道同色，进度归零。实测 735×6 全白，一个像素都不剩。

   为什么用 `Highlight` 而不是别的系统色：
     · 它是**唯一**语义为"被选中的一段/重点区域"的系统色，正好对应填充条
     · 系统色关键字**不被强制替换** —— 实测 `Highlight` 在模拟下解析为
       rgb(55,0,110)，`CanvasText` 为 rgb(0,0,0)，都保持自己的身份
     ⚠️ 但**别在判据里断言具体 RGB**：模拟色板与真实高对比度主题不是同一套
        （实测 `GrayText` 在模拟下是 rgb(96,0,0) 深红，真实系统下是灰）。
        判据只能问"是不是等于 Canvas"。

   为什么选择器是 `.progress .progress__bar` 而不是 `.progress__bar`：
     上面三个变体是 0,2,0 优先级。用 0,1,0 会被它们压掉 ⇒ 危险态仍然不可见。
     这里必须同权或更高，且写在变体之后。
   --------------------------------------------------------------------------- */
@media (forced-colors: active) {
  .progress .progress__bar { background: Highlight; }
}

/* 尺寸变体 */
.progress--lg { --progress-h: 10px; }
.progress--sm { --progress-h: 4px; }

/* ============================================================================
   2 · 环形进度（需要"占比"感时，比线形更直观）
   ============================================================================ */
.progress-ring {
  display: inline-grid;
  place-items: center;
  position: relative;
  width: var(--ring-size);
  height: var(--ring-size);
  border-radius: 50%;
  /* ⭐ 用 conic-gradient 而非 SVG：零依赖、纯 CSS、可被令牌驱动 */
  /* 🔴 修 bug：环形之前用 `calc(var(--progress) * 1%)`，
     但 JS 把 --progress 设成 "72%"（**带百分号**）⇒ 72% * 1% 非法
     ⇒ 整条 background 无效（实测 background-image: none，环完全没画出来）。
     ⇒ 正解：环形用**无单位**的 --progress-num（JS 同时写两个变量）。 */
  background: conic-gradient(
    var(--accent) calc(var(--progress-num, 0) * 1%),
    var(--surface-sunken) 0
  );
}

.progress-ring__label {
  /* 内圈挖空：用 surface 色的圆盘盖住中间 */
  display: grid;
  place-items: center;
  width: calc(100% - var(--ring-thickness) * 2);
  height: calc(100% - var(--ring-thickness) * 2);
  border-radius: 50%;
  background: var(--surface);
  font-size: var(--fs-sm);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;   /* 数字等宽，不跳动 */
}

.progress-ring--success { background: conic-gradient(var(--success) calc(var(--progress-num, 0) * 1%), var(--surface-sunken) 0); }
.progress-ring--danger  { background: conic-gradient(var(--danger)  calc(var(--progress-num, 0) * 1%), var(--surface-sunken) 0); }

/* 🔴 强制色：conic-gradient 整条被移除，环会"凭空不见"只剩一个数字
   ---------------------------------------------------------------------------
   实测（0.17.0）：`.progress-ring` 在 forced-colors 下 `background-image`
   变成 none ⇒ 只截到居中的 "72%"，环一个像素都没有。
   信息本身没丢（中心 label 里就是百分比数字），丢的是"这是个环"的形状。

   ⇒ 用 outline 补一个圈。**不用 border**：label 是
      `calc(100% - var(--ring-thickness) * 2)`，border 会挤小它，
      在 --ring-size 较小时数字会被裁。
   ⚠️ 也不能指望 `background: canvas` 之类的替换 —— 环是**渐变**，
      强制色下 gradient 不区分颜色，整条 background-image 直接丢弃。 */
@media (forced-colors: active) {
  .progress-ring {
    background: none;
    outline: 2px solid CanvasText;
    outline-offset: -2px;        /* 内侧描边，外径不变 */
  }
}

/* ============================================================================
   3 · 不确定进度（不知道要多久）
   ============================================================================
   ⚠️ 关键：不确定时**绝不能**显示百分比数字（那是撒谎）。
   ============================================================================ */
.progress--indeterminate .progress__bar {
  width: 35%;
  animation: progress-slide 1.1s var(--ease-out) infinite;
}

@keyframes progress-slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(340%); }
}

/* ============================================================================
   4 · 步骤分段（"第 3 步 / 共 5 步"这类已知流程）
   ============================================================================ */
.progress-steps {
  display: flex;
  gap: var(--sp-1);
}
.progress-steps__seg {
  flex: 1;
  height: var(--progress-h, 4px);
  background: var(--surface-sunken);
  border-radius: var(--r-full);
}
.progress-steps__seg--done { background: var(--accent); }
.progress-steps__seg--current { background: var(--accent); opacity: 0.55; }

/* ============================================================================
   5 · 无障碍
   ============================================================================
   进度条必须：
     · role="progressbar" + aria-valuenow/min/max（或不确定时不设 valuenow）
     · 内部文字对读屏隐藏（避免念出无意义的百分比）
   ============================================================================ */
.progress[aria-busy='true'] { cursor: progress; }

/* ============================================================================
   减少动态效果（prefers-reduced-motion: reduce）
   ============================================================================
   ⚠️⚠️ 这里改过一次。**第一版是错的**（看截图后指出）：

   第一版做法：动画停掉，留一个 33% 宽的条子，但仍保留 `::after` 的扫光渐变
   ⇒ 结果是**一条明显的两色硬边界**（左边浅、右边深，边界很锐）
   ⇒ 看起来像"卡在某个位置"，反而比分段线形更糟。

   ⭐ 通行做法（某设计系统 Horizon 设计系统）：
     "This option displays a **static progress bar, set at 25% completion**"
     —— 固定 25% 的**单色**条，**没有任何两色边界**。

   为什么单色更好：
     · 不"卡住了"的错觉（两色边界看起来像"已经走了 33%"）
     · 边界不锐利，不刺激（前庭功能敏感者对强边界尤其敏感）
     · 语义仍然清楚：有一条短条 = 正在处理
   ============================================================================ */
@media (prefers-reduced-motion: reduce) {
  .progress__bar { transition: none; }

  .progress--indeterminate .progress__bar {
    animation: none;
    transform: none;
    /* 固定 25%（对齐 Horizon）—— 表示"在处理，但不知道到哪" */
    width: 25%;
    /* ⭐ 关键：扫光层**整个去掉**，不留两色边界 */
    background: var(--accent);
  }
  .progress--indeterminate .progress__bar::after {
    /* 不用 display:none（那会留下 ::after 参与合成的空盒），
       改成 transparent —— 盒子还在，但完全不可见，边界消失 */
    content: none;
  }

  /* 语义色变体在 reduce 下也要保持单色 */
  .progress--indeterminate.progress--success .progress__bar { background: var(--success); }
  .progress--indeterminate.progress--warning .progress__bar { background: var(--warning); }
  .progress--indeterminate.progress--danger  .progress__bar { background: var(--danger); }
}
