/* ============================================================================
   sparkline — 迷你趋势图的样式
   ============================================================================
   🔴 为什么要单独一个 CSS 文件（它只有一个类）
   ----------------------------------------------------------------------------
   因为**动画**。SVG 的 path 动画属于"视觉层"，放 JS 里就变成内联 style，
   换主题与 reduced-motion 都难管。放 CSS 里才能被 motion 门禁盯住。

   🔴 动画为什么用 stroke-dasharray 而不是 JS 逐帧
   ----------------------------------------------------------------------------
   ① **零 JS 帧循环** —— 动画完全交给合成器，JS 只画一次路径。
   ② **可被 prefers-reduced-motion 关掉** —— 一行 CSS 的事，
      写在 JS 里要自己写 if 判断（而且容易漏）。
   ③ **不阻塞主线程** —— 几十个 sparkline 同时动画也不会掉帧。
 */

/* 🔴 **修 真机实测反馈的"趋势图和文字重叠"**

   根因（实测，不是猜的）：
     ① 这里 `height: 32px` 是**写死的**，但 JS 按 `data-spark-height`
        可以画成 48 / 52 / 56px ⇒ **容器装不下**
     ② `overflow: visible` ⇒ 溢出的部分**直接画到容器外面**，
        压在下面一行的文字上

   ⭐ 这个判断是对的，而且这是**通用设计规范**：
        **任何图都不能与文字重叠。** 图要么在自己的框里，
        要么明确留出间距 —— 不能靠"溢出"去侵占别的元素的空间。

   ⇒ 修法：
     ① 容器高度**由 JS 同步写入**（消除"容器与图不一致"这个根）
     ② overflow 改 hidden（溢出即被裁，不会压到别处）
        ⚠️ 这里**不能用 visible**：末尾那个"标出最后一点"的圆点
           是画在 path 上的，不会出框；改成 hidden 是安全的。 */
.sparkline {
  display: block;
  /* 🔴 iOS 实机报的「出边框」修复：
     `width: 100%` 在**两层**都会被算：
       外层 `.spark-wrap` 是 flex 项（要收缩）
       内层 `.sparkline` 又是 100%
     ⇒ **同一个宽度算两遍**，收缩量被吃掉，组件被压成 5px 竖线。
     修法：**`min-width: 0` 允许 flex 收缩**（这是 flex 收缩的前提），
     宽度仍交给 `width:100%`—— 但父层必须允许它被压。 */
  min-width: 0;
  width: 100%;
  height: var(--spark-h, 32px);
  overflow: hidden;
  /* 🔴 图与文字之间的间距：组件自己给，不靠调用方记得留 */
  margin: var(--sp-1) 0;
}

.sparkline svg {
  display: block;
  width: 100%;
  overflow: hidden;
}

/* 🔴 颜色**一律走 CSS**，不用 stroke="var(--x)" 属性。
   presentation attribute 上的 var() 各浏览器支持不一致（规范没保证，
   Safari 尤其不可靠）。JS 只写 --spark-c，具体取值由这里决定 ——
   顺带得到一个好处：**调用方可以用 CSS 覆盖颜色，不必改 data 属性**。 */
/* 🔴 **修「趋势图变成扁平色带」**（真机实测截图指出的）

   ⚠️ 我原来写成「path / rect / circle 一律 fill: var(--spark-c)」——
      **这会把折线也填成面**！因为
      **CSS 的优先级高于 SVG presentation attribute**，
      JS 里写的 `fill="none"` **被完全无视**。
      实测：fill 属性 = none，但计算值 = rgb(27,77,143) ⇒
      折线被填成了实心多边形 ⇒ 看起来是「扁平的色带」而不是趋势线。

   ⇒ 修法：**按类型分开**，不靠属性覆盖（属性打不过 CSS）：

       .spark-line  → 只描边，不填充（折线）
       .spark-area  → 填充（面积图）
       .spark-bar   → 填充（柱状图）
       .spark-dot   → 填充（端点/单点） */
.spark-line {
  stroke: var(--spark-c, var(--accent));
  fill: none;
}
.spark-area {
  stroke: none;
  fill: var(--spark-c, var(--accent));
}
.spark-bar {
  stroke: none;
  fill: var(--spark-c, var(--accent));
}
.spark-dot {
  stroke: none;
  fill: var(--spark-c, var(--accent));
}

/* 放在一行里（表格/列表右侧那种）时不该有上下外边距，
   否则会把那一行撑高、看起来错位 */
.row > .sparkline,
td > .sparkline,
.spark { margin: 0; }

/* 🔴 动画独立成 `.spark-anim`（原来复用 .spark-line，
   重写外观后那个判断就失效了 —— 动画会无视设置照播）。

   🔴 0.8.0 修：**基态必须是"看得见"，动画负责"从不可见到可见"**
   ----------------------------------------------------------------------------
   原来写反了：
     .spark-anim { stroke-dashoffset: var(--spark-len, 1000);   ← 基态：整条推出可见区
                   animation: spark-draw … forwards }           ← 靠它才变可见
     @keyframes spark-draw { to { stroke-dashoffset: 0 } }

   这个写法有个致命性质：**动画一旦被取消，线就整条消失**
   （取消 ⇒ 回落到基态 = 完全偏移 ⇒ 没有可见线段）。
   实测踩到两处，都不是理论推演：

     ① **视觉门禁假红**。`shot-baseline.py` 为了"冻结动画再截图"会注入
        `animation:none !important` ⇒ sparkline 的线整条不见 ⇒
        报"21 个块变化、观感不一致"，重跑又绿 —— 表现为**偶发假红**。
        （为什么偶发：`.spark-anim` 只在**首绘**时加；ResizeObserver 会紧接着
          再绘一次且**不加**这个类 ⇒ 截到"首绘态"就看不见、截到"重绘态"就正常。
          ⇒ 每次截图落在哪个态，取决于 RO 回调与截图的先后 —— 纯竞态。）
     ② **任何第三方 CSS 重置 / 用户样式**把动画关掉，线都会消失。
        这不是假设：`@media print` 与 `prefers-reduced-motion` 都得自己
        再补一行 `stroke-dashoffset: 0` 才不出错 —— 那正是"写反了"的味道。

   ⇒ 正确写法：基态 `0`（可见），动画的 `from` 才是"完全偏移"。
     取消动画最多是"少一次动效"，绝不会变成"少一张图"。

   ⚠️ `--spark-len` 兜底 1000 是**承重的**：dasharray 必须 ≥ 路径长度，
      否则"偏移 1000"落不到可见区之外，入场效果会变形。
      目前全库没有任何 JS 去写这个变量（早先的注释说 JS 会写，是错的），
      所以 1000 就是实际生效值。超过 1000px 宽的 sparkline 不在本库场景内。 */
.spark-anim {
  stroke-dasharray: var(--spark-len, 1000);
  stroke-dashoffset: 0;
  animation: spark-draw var(--dur-slow, 600ms) var(--ease-out) forwards;
}

@keyframes spark-draw {
  from { stroke-dashoffset: var(--spark-len, 1000); }
  to   { stroke-dashoffset: 0; }
}

/* 🔴 关掉动画的三种情况（缺一不可）：

   ① 用户在系统里说了"减少动态效果" —— 这是**必须尊重的**
      （前庭功能障碍者会因动画眩晕，WCAG 2.3.3）。
   ② 屏幕上的图是**纯装饰**（旁边已经有完整数字）—— 动它只是噪音。
   ③ 页面在后台（切走了还在动就是浪费电量）。
*/
@media (prefers-reduced-motion: reduce) {
  .spark-anim {
    animation: none;
    stroke-dashoffset: 0;
  }
}

/* 打印时也别动 —— 打印是静态的，动画只会拖慢 */
@media print {
  .spark-anim { animation: none; stroke-dashoffset: 0; }
}
