/* 图表样式与令牌（SPEC-v2 §7.1 R7 / R9、§7.4、§7.10）：流 F。
   - 颜色只经 CSS 变量；--ch-* 令牌在 :root 与 prefers-color-scheme: dark 里各定义一次（集合相等，对比度由 tests/test_frontend_v2_static.py 计算）。
   - 类名只用 .chart / .chart-* / .gantt / .gantt-* / .gt-* / .ch-*；:root 之外不写十六进制色与 rgb 函数。
   - R9：不引用任何 SVG 图案（没有 url 引用）——图案填充由 charts.js / gantt.js 按图实例设置到 fill 属性上。
   - 颜色之外必有形状 / 纹理 / 文字（§7.4 编码规则）；本版不做任何动画（prefers-reduced-motion 无需处理）。 */

:root { /* 浅色 */
  --ch-ok: #25834a; --ch-warn: #b07a00; --ch-bad: #c93a3a; --ch-info: #3b6fd4; --ch-muted: #9aa3b2;
  --ch-on-ok: #ffffff; --ch-on-warn: #1d1600; --ch-on-bad: #ffffff;
  --ch-bar: #3f6bd0; --ch-bar-soft: #b9caf2; --ch-bar-fill: #2c4fa8; --ch-on-bar: #ffffff; --ch-done: #7d8a9e; --ch-on-done: #10151f; --ch-base: #6d7788;
  --ch-grid: #e3e7ee; --ch-weekend: rgba(110, 120, 140, .09); --ch-today: #c93a3a;
  --ch-text: #1d2330; --ch-sub: #5f6b7e; --ch-bg: #ffffff; --ch-track: #e9edf3;
}
@media (prefers-color-scheme: dark) {
  :root { /* 深色 */
    --ch-ok: #55d48a; --ch-warn: #f0b94d; --ch-bad: #ff8a85; --ch-info: #7aa5ff; --ch-muted: #6d778a;
    --ch-on-ok: #06210f; --ch-on-warn: #261a00; --ch-on-bad: #2b0a09;
    --ch-bar: #5d86ea; --ch-bar-soft: #34456b; --ch-bar-fill: #8fb0ff; --ch-on-bar: #0b1220; --ch-done: #7c889c; --ch-on-done: #0b1220; --ch-base: #a3acba;
    --ch-grid: #2d3440; --ch-weekend: rgba(255, 255, 255, .045); --ch-today: #ff8a85;
    --ch-text: #e7eaf0; --ch-sub: #a0a9b8; --ch-bg: #1b2028; --ch-track: #2a313c;
  }
}

/* ------------------------------------------------------------ 图框、图例、查看数据 */
.chart { margin: 0; min-width: 0; }
.chart > svg, .chart-stage > svg { display: block; max-width: 100%; height: auto; overflow: visible; }
.chart > svg.ch-ring { margin: 0 auto; }
.chart-stage { position: relative; }
/* 矩阵放不下需要横向滚动时：行标签（及行链接的热区）钉在滚动区左侧；窗格不占高度（margin-bottom 取负），盖在图形左边遮住滚到它下面的格子 */
.chart-labelpane { position: sticky; left: 0; z-index: 2; background: var(--ch-bg); }
.chart-labelpane > svg { display: block; max-width: none; overflow: visible; }
.chart-error { color: var(--muted); font-size: .85rem; margin: 0; padding: 12px 0; }
.chart-note { margin: 4px 0 0; font-size: .8rem; color: var(--muted); }
.chart-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.chart-legend { display: flex; flex-wrap: wrap; gap: 2px 14px; margin-top: 6px; font-size: .8rem; line-height: 1.4; color: var(--muted); }
.chart-legend-item { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.chart-legend .ch-swatch { flex: none; overflow: visible; }
.chart-data { margin-top: 6px; }
.chart-data > summary { cursor: pointer; font-size: .82rem; color: var(--muted); width: fit-content; }
.chart-data-scroll { overflow-x: auto; margin-top: 4px; }
.chart-data table { font-size: .82rem; border-collapse: collapse; }
.chart-data th, .chart-data td { border-bottom: 1px solid var(--border); padding: 3px 12px 3px 0; text-align: left; white-space: nowrap; }
.chart-data th { font-weight: 600; color: var(--muted); }
.chart-scroll { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }
.chart-scroll:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* 行级热区：HTML 链接 / 按钮叠在 svg 上（位于 role=img 的 svg 之外），位置用百分比 */
.ch-hits { list-style: none; margin: 0; padding: 0; position: absolute; top: 0; right: 0; bottom: 0; left: 0; pointer-events: none; }
.ch-hits > li { position: absolute; margin: 0; padding: 0; }
.ch-hit { display: block; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; border-radius: 6px; background: transparent; cursor: pointer; pointer-events: auto; font: inherit; }
.ch-hit:hover { background: var(--ch-weekend); }
.ch-hit:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

/* ------------------------------------------------------------ 文字 */
.chart text { font: 12px/1 -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: var(--ch-text); }
.chart .ch-sub { fill: var(--ch-sub); }
.chart .ch-bold { font-weight: 700; }
.chart .ch-big { font-size: 22px; font-weight: 700; }
.chart .ch-lg { font-size: 15px; }
.chart .ch-mid { font-size: 13px; }
.chart .ch-sm, .chart .ch-xs { font-size: 11px; }
.chart .ch-xxs { font-size: 10px; }
.chart .ch-strike { text-decoration: line-through; }
.chart .ch-halo { paint-order: stroke; stroke: var(--ch-bg); stroke-width: 3px; stroke-linejoin: round; }
.chart .ch-bad-text { fill: var(--ch-bad); }
.chart .ch-info-text { fill: var(--ch-info); }
.chart .ch-today-text { fill: var(--ch-today); }
.chart .ch-text-fill { fill: var(--ch-text); }

/* ------------------------------------------------------------ 色调、形状 */
.chart .ch-ok { fill: var(--ch-ok); }
.chart .ch-warn { fill: var(--ch-warn); }
.chart .ch-bad { fill: var(--ch-bad); }
.chart .ch-info { fill: var(--ch-info); }
.chart .ch-muted { fill: var(--ch-muted); }
.chart .ch-bar { fill: var(--ch-bar); }
.chart .ch-bar-soft { fill: var(--ch-bar-soft); }
.chart .ch-bar-fill { fill: var(--ch-bar-fill); }
.chart .ch-done { fill: var(--ch-done); }
.chart .ch-on-ok { fill: var(--ch-on-ok); }
.chart .ch-on-warn { fill: var(--ch-on-warn); }
.chart .ch-on-bad { fill: var(--ch-on-bad); }
.chart .ch-on-bar { fill: var(--ch-on-bar); }
.chart .ch-on-done { fill: var(--ch-on-done); }
.chart .ch-base { fill: var(--ch-base); }
.chart .ch-track { fill: var(--ch-track); }
.chart .ch-track-ring { fill: none; stroke: var(--ch-track); }
.chart .ch-weekend { fill: var(--ch-weekend); }
.chart .ch-grid { stroke: var(--ch-grid); stroke-width: 1; }
.chart .ch-faint { opacity: .6; }
.chart .ch-today { stroke: var(--ch-today); stroke-width: 1.5; stroke-dasharray: 4 3; }
.chart .ch-glyph-none { fill: none; stroke: var(--ch-muted); stroke-width: 1; stroke-dasharray: 2 2; }
.chart .ch-bar-todo { fill: none; stroke: var(--ch-bar); stroke-width: 1.5; stroke-dasharray: 3 2; }
.chart .ch-bar-cancel { fill: none; stroke: var(--ch-muted); stroke-width: 1.2; stroke-dasharray: 1.5 3; }
.chart .ch-cancel { stroke: var(--ch-muted); stroke-dasharray: 1.5 3; } /* 堆叠条里「取消」的空心段：点线描边（与待办的虚线区分，§7.4）；叠在 ch-bar-todo 上 */
.chart .ch-diamond-todo { fill: var(--ch-bg); stroke: var(--ch-bar); stroke-width: 1.8; stroke-dasharray: 3 2; }
.chart .ch-stroke-ok { stroke: var(--ch-ok); stroke-width: 1; }
.chart .ch-stroke-warn { stroke: var(--ch-warn); stroke-width: 1; }
.chart .ch-stroke-bad { stroke: var(--ch-bad); stroke-width: 1; }
.chart .ch-stroke-info { stroke: var(--ch-info); stroke-width: 1; }
.chart .ch-stroke-muted { stroke: var(--ch-muted); stroke-width: 1; }
.chart .ch-dash { fill: none; stroke-width: 1.5; stroke-dasharray: 3 2.5; }
.chart .ch-heavy { stroke-width: 1.6; }
.chart .ch-thick { stroke-width: 1.8; }
.chart .ch-empty-cell { fill: none; stroke: var(--ch-grid); stroke-width: 1; stroke-dasharray: 2 3; }
.chart .ch-empty-box { fill: none; stroke: var(--ch-muted); stroke-width: 1; stroke-dasharray: 4 3; }
.chart .ch-dot { stroke: var(--ch-bg); stroke-width: 1.5; }
.chart .ch-fc { stroke: var(--ch-bad); stroke-width: 1; stroke-dasharray: 3 2; }
.chart .ch-ghost { fill: var(--ch-weekend); stroke: var(--ch-info); stroke-width: 1.6; stroke-dasharray: 4 3; }
.chart .ch-bracket { fill: none; stroke: var(--ch-sub); stroke-width: 1.4; }
.chart .ch-link { fill: none; stroke: var(--ch-sub); stroke-width: 1.2; }
.chart .ch-link-crit { stroke: var(--ch-bad); stroke-width: 1.8; }
.chart .ch-link-bad { stroke: var(--ch-bad); stroke-dasharray: 3 2; }
.chart .ch-arrow { fill: var(--ch-sub); }
.chart .ch-arrow-crit, .chart .ch-arrow-bad { fill: var(--ch-bad); }

/* 折线：进度曲线与迷你趋势；线型区分计划 / 实际 / 预测，不只靠颜色 */
.chart .ch-ln { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .ch-ln-info, .chart .ch-curve-actual { stroke: var(--ch-info); stroke-width: 2.4; }
.chart .ch-curve-planned { stroke: var(--ch-sub); stroke-dasharray: 6 4; stroke-linecap: butt; }
.chart .ch-curve-forecast { stroke: var(--ch-bad); stroke-dasharray: 1.5 4.5; stroke-width: 2.6; }
.chart .ch-line { fill: none; stroke-width: 2; }
.chart .ch-line-sub { stroke: var(--ch-sub); }
.chart .ch-line-info { stroke: var(--ch-info); }
.chart .ch-line-bad { stroke: var(--ch-bad); }
.chart .ch-line-muted { stroke: var(--ch-muted); }
.chart .ch-ld-dash { stroke-dasharray: 5 3; }
.chart .ch-ld-dot { stroke-dasharray: 1.5 3.5; stroke-linecap: round; }

/* ------------------------------------------------------------ 甘特（§7.8） */
.gantt { display: grid; grid-template-columns: var(--gt-label-w, 184px) minmax(0, 1fr); align-items: start; }
.gt-corner, .gt-head-wrap { position: sticky; top: var(--gt-sticky-top, 0px); z-index: 3; height: 40px; background: var(--ch-bg); }
.gt-corner { display: flex; align-items: flex-end; box-sizing: border-box; padding: 0 0 6px 6px; border-bottom: 1px solid var(--ch-grid); }
.gt-head-wrap { overflow: hidden; }
.gt-head-svg, .gt-body-svg, .gt-labels-svg { display: block; max-width: none; }
.gt-labels { min-width: 0; overflow: hidden; background: var(--ch-bg); }
.chart .gt-group-bg { fill: var(--ch-track); opacity: .55; }
.chart .gt-bar, .chart .gt-ghost { cursor: pointer; }
.chart .gt-hit { fill: transparent; cursor: pointer; }
.chart .gt-row { outline: none; cursor: pointer; }
.chart .gt-row:hover .gt-hit { fill: var(--ch-weekend); }
.chart .gt-row:focus-visible .gt-hit { fill: var(--ch-weekend); stroke: var(--focus); stroke-width: 2px; }
.chart .gt-assumed { stroke: var(--ch-sub); stroke-width: 1.4; stroke-dasharray: 3 2; }
.chart .gt-crit { stroke: var(--ch-bad); stroke-width: 2; }
.chart .gt-clamped path { stroke: var(--ch-bg); stroke-width: 1; stroke-linejoin: round; } /* 首页时间线里逾期很久的行：夹在左缘的小红三角，描一圈底色让它在网格线上也分得出形状 */
.gt-compact .gt-corner, .gt-compact .gt-head-wrap { position: static; }

/* ------------------------------------------------------------ 打印（§7.10）：颜色与图案保留、数据表展开、导航与按钮隐藏、甘特不被截断 */
@page { size: A4 landscape; margin: 10mm; }
@media print {
  * { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
  .topbar, .nav, .ch-tools, .chart button, .ch-hits { display: none !important; }
  details.chart-data > summary { display: none; }
  details.chart-data { display: block; }
  details.chart-data::details-content { content-visibility: visible; display: block; } /* 关着的 <details> 即使 display:block 内容也不显示；不支持该伪元素的浏览器忽略这条规则，由 beforeprint 里的 JS 展开 */
  .chart-scroll { overflow: visible; }
  .gt-corner, .gt-head-wrap { position: static; }
  .chart { break-inside: avoid; }
}
