/* ═══ 商品详情 `/products/{pid}` ═══
   颜色一律取令牌（vendor/tokens.css）。这一份里出现任何 #hex 都是 bug。
   带 /* GAP *​/ 的数值是令牌里没有、被迫写死的，改令牌时一并回收。 */

.pd { display: flex; flex-direction: column; gap: 14px; }        /* GAP card-gap-14 */

/* 状态未知：整屏切成「这个数现在不可信」的呈现，但值照常显示——旧数据仍然有用。
   有形无色：不用红，红是「现在就看」的语言。 */
.pd-unknown .pd-kpi-v,
.pd-unknown .pd-name { color: var(--c-neutral-600); }

.pd-topline { display: flex; align-items: center; gap: var(--space-2); }
.pd-back { color: var(--c-neutral-600); }
.pd-backicon { transform: rotate(90deg); }

/* ── 二档异常条：3px 灰左条 + 断线图标，有形无色 ── */
.pd-notices:empty { display: none; }
.pd-notices { display: flex; flex-direction: column; gap: var(--space-2); }
.pd-notice {
  display: flex; gap: var(--space-2); align-items: flex-start;
  padding: var(--space-3); border: 1px solid var(--c-neutral-100);
  border-left: 3px solid var(--c-neutral-600); border-radius: var(--radius-md);
  background: var(--c-neutral-25); font-size: var(--size-base);
}
.pd-notice b { font-weight: 500; color: var(--c-neutral-900); }
.pd-notice p { margin: 2px 0 0; color: var(--c-neutral-600); }
.pd-notice > svg { flex-shrink: 0; color: var(--c-neutral-600); }

/* ── 标题块 ── */
.pd-title { display: flex; flex-direction: column; gap: 2px; }
.pd-sevrow { display: flex; align-items: center; gap: 6px; margin-bottom: 2px; }
.pd-sevrow > svg { color: var(--c-neutral-600); }
.pd-ev { font-size: var(--size-sm); font-weight: 500; color: var(--c-neutral-900); }
.pd-ev.now { color: var(--c-severity-high); }
.pd-ev.today { color: var(--c-neutral-900); }
.pd-ev.archive { color: var(--c-neutral-500); font-weight: 400; }

.pd-name {
  font-size: var(--size-3xl); font-weight: 600; letter-spacing: -.02em;
  line-height: var(--leading-snug); color: var(--c-neutral-900); margin: 0 0 2px;
}
.pd-pid { font-family: var(--font-mono); font-size: var(--size-base); color: var(--c-neutral-500); }
.pd-cn { font-size: var(--size-md); color: var(--c-neutral-500); margin-bottom: 6px; }

.pd-status { display: flex; align-items: center; gap: var(--space-2); font-size: var(--size-base);
             color: var(--c-neutral-600); margin: 4px 0 2px; }
.pd-status b { font-weight: 500; color: var(--c-neutral-900); }
.pd-status > svg { color: var(--c-neutral-600); }
.pd-status.delisted b, .pd-status.suspect b { color: var(--c-neutral-900); }
.pd-confirm { font-size: var(--size-sm); color: var(--c-neutral-600); }
.pd-confirm.muted { color: var(--c-neutral-500); }

.pd-meta { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
           font-size: var(--size-sm); color: var(--c-neutral-600); margin-top: 6px; }
.pd-mi { display: inline-flex; align-items: center; gap: 4px; }
.pd-mi + .pd-mi::before {
  content: ''; width: 1px; height: 12px; background: var(--c-neutral-100); margin-right: 12px;
}
.pd-meta { position: relative; }

/* 术语：本页首次出现时点线下划线 + 悬停一句白话。 */
.pd-term, abbr.pd-term {
  text-decoration: underline dotted var(--c-neutral-400);
  text-underline-offset: 3px; cursor: help;
}
/* 分类型的推算（阶段 / 新品列位）只加点线术语记号，不加 ≈ —— 它不是数值。 */
.pd-derivedterm { color: var(--c-neutral-600); }

/* ── 记录起点条 ── */
.pd-origin {
  display: flex; gap: 9px; align-items: flex-start; padding: 9px 12px;
  border: 1px solid var(--c-neutral-200); border-left: 3px solid var(--c-neutral-600);
  border-radius: var(--radius-md); background: var(--c-neutral-50);
  font-size: var(--size-sm); color: var(--c-neutral-600);
}
.pd-origin > svg { flex-shrink: 0; margin-top: 1px; }
.pd-originline { margin: 0; line-height: var(--leading-snug); }
.pd-originline + .pd-originline { margin-top: 4px; }
.pd-originline b { font-weight: 500; color: var(--c-neutral-900); }

.pd-asof { margin: 0; font-size: var(--size-sm); color: var(--c-neutral-600); }

/* ── KPI 五格 ── */
.pd-kpi {
  display: flex; gap: 1px; background: var(--c-neutral-100);
  border: 1px solid var(--c-neutral-100); border-radius: var(--radius-10); overflow: hidden;
}
.pd-kpi-cell { flex: 1; min-width: 0; background: var(--c-neutral-0); padding: 10px 13px; }
.pd-kpi-l { font-size: var(--size-11); color: var(--c-neutral-500); margin-bottom: 3px; }
.pd-kpi-v { font-size: var(--size-2xl); font-weight: 600; color: var(--c-neutral-900);
            letter-spacing: -.02em; line-height: var(--leading-tight); min-height: 24px; }  /* GAP kpi-v-min */
.pd-kpi-v .bg { font-size: var(--size-base); font-weight: 400; letter-spacing: 0; }
.pd-kpi-f { font-size: var(--size-xs); color: var(--c-neutral-500); margin-top: 2px; }
/* 窄屏：五格排不下就折行，不让整页横向滚动。
   宁可折成两行也不做横向滚动条——KPI 是要一眼扫完的，扫一半要横拖等于没给。 */
@media (max-width: 900px) {
  .pd-kpi { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pd-kpi-cell { min-width: 0; }
}

/* ── 两栏 ── */
.pd-cols { display: flex; gap: 14px; align-items: flex-start; }   /* GAP col-gap-14 */
.pd-left { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 12px; }
.pd-right { flex: 0 0 336px; display: flex; flex-direction: column; gap: 12px; }  /* GAP right-336 */
@media (max-width: 1100px) {
  .pd-cols { flex-direction: column; }
  .pd-right { flex: 1 1 auto; width: 100%; }
}

/* ── 卡片：卡与卡之间是真空隙，不画分隔线 ── */
.pd-card {
  background: var(--c-neutral-0); border: 1px solid var(--border-hairline);
  border-radius: var(--radius-10); padding: 12px 14px; min-width: 0;
}
.pd-head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: 8px; }
.pd-h { font-size: var(--size-base); font-weight: 600; letter-spacing: -.01em; }
.pd-sub { font-size: var(--size-sm); color: var(--c-neutral-500); min-width: 0; }
.pd-headtail { margin-left: auto; display: flex; align-items: center; gap: 6px; }
.pd-cardbody { min-width: 0; }

/* 换时间档时保留上一档的图，整块压到 n600，不闪骨架屏。
   ⚠️ 图表这一半原来写的是 `opacity: .55` —— **同一条规则的两半，一半对一半错**：
   文字用色值是对的，图表用半透明是违规（`05-components.md` 设计线 238bd21：
   **opacity 一律不用来弱化任何东西，绑机制不绑状态名**）。
   理由是 opacity 把它盖住的**每一个**前景色同时拖向背景，而图表里有八种前景色，
   **每一个的结果对比度都不一样也算不出来**；换成色值之后每一个都算得出来。
   落法：图表内部走 `--chart-*` 角色变量（见 `ui/chart.js`），这里只换那几个变量。 */
.pd-dim { color: var(--c-neutral-600); }
.pd-dim .chart {
  --chart-ink: var(--c-neutral-500);      /* 曲线与端点 */
  --chart-label: var(--c-neutral-500);
  --chart-axis: var(--c-neutral-400);
  --chart-base: var(--c-neutral-200);     /* 基线带 */
  --chart-mile: var(--c-neutral-200);     /* 里程碑竖线 */
  --chart-hatch: var(--c-neutral-200);    /* 缺口斜纹 */
}
.pd-loading { margin: 0; padding: var(--space-2) 0; font-family: var(--font-mono);
              font-size: var(--size-11); color: var(--c-neutral-500); }

/* ── 分段控件 ── */
.pd-seg { display: inline-flex; padding: 1px; gap: 1px; border-radius: var(--radius-md);
          background: var(--c-neutral-100); }
.pd-segbtn {
  height: 24px; padding: 0 9px; border: 0; border-radius: var(--radius-sm);   /* GAP seg-h-24 */
  background: none; color: var(--c-neutral-600); font-size: var(--size-sm);
  font-family: inherit; cursor: pointer;
}
.pd-segbtn:hover { color: var(--c-neutral-900); }
.pd-segbtn.on { background: var(--c-neutral-0); color: var(--c-neutral-900); font-weight: 600; }

/* ── 基线未收敛：虚线框 + 进度条（四种空状态里唯一给进度条的一种） ── */
.pd-pending {
  margin-top: 10px; border: 1px dashed var(--border-control); border-radius: var(--radius-md);
  padding: var(--space-3);
}
.pd-pending .empty { min-height: 0; padding: var(--space-2) 0; gap: 6px; }
.pd-pendinghint { margin: 0; font-size: var(--size-base); color: var(--c-neutral-600);
                  text-align: center; }

/* ── 表格替代 ── */
.pd-table { margin-top: 10px; max-height: 260px; overflow-y: auto; }   /* GAP table-max-260 */
.pd-table table.t { min-width: 0; }

/* ── 事件流 ── */
.pd-feed-card { display: flex; flex-direction: column; height: 288px; }   /* GAP feed-h-288 */
.pd-feed { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.pd-row { display: flex; gap: 10px; align-items: flex-start; padding: 1px 0; border-radius: var(--radius-sm); }
.pd-row:hover { background: var(--c-neutral-25); }
.pd-rowt { width: 62px; flex-shrink: 0; padding-top: 1px; font-family: var(--font-mono);
           font-size: var(--size-11); color: var(--c-neutral-500); }   /* GAP rowt-62 */
.pd-bar { width: 3px; flex-shrink: 0; align-self: stretch; border-radius: 2px; background: transparent; }
.pd-row.now .pd-bar { background: var(--c-severity-high); }
.pd-row.today .pd-bar { background: var(--c-severity-mid); }
.pd-rowbody { min-width: 0; flex: 1; }
.pd-rowhead { display: flex; align-items: center; gap: 6px; }
.pd-rowhead > svg { color: var(--c-neutral-600); flex-shrink: 0; }
.pd-row.archive .pd-ev { color: var(--c-neutral-500); font-weight: 400; }
.pd-fact { display: block; margin-top: 1px; font-size: var(--size-sm); color: var(--c-neutral-600); }
.pd-dot { color: var(--c-neutral-200); }
.pd-fact .xs, .pd-fact .bg { margin-left: 4px; }
.pd-rowlinks { margin-top: 2px; display: flex; gap: var(--space-3); }

/* 「这条不准」：hover 才出现，占位一直预留，文字一个像素都不动。 */
.pd-bad { margin-left: auto; opacity: 0; transition: opacity var(--motion-duration-item-enter); }
.pd-row:hover .pd-bad, .pd-row:focus-within .pd-bad { opacity: 1; }

.pd-snap { margin-top: 6px; font-size: var(--size-sm); }
.pd-snap summary { cursor: pointer; color: var(--c-neutral-600); }
.pd-snapgrid { margin-top: 6px; padding: var(--space-2); border: 1px solid var(--c-neutral-100);
               border-radius: var(--radius-md); }
.pd-snapother { margin-top: 6px; padding: var(--space-2); border: 1px dashed var(--c-neutral-200);
                border-radius: var(--radius-md); }
.pd-snapother p { margin: 0 0 4px; }
.pd-key { word-break: break-all; font-size: var(--size-11); }
.pd-members { margin: 4px 0 0; padding-left: 18px; font-size: var(--size-sm); }  /* GAP list-indent */

/* ── 键值行 ── */
.pd-kv { display: flex; gap: var(--space-2); align-items: baseline; font-size: var(--size-sm);
         padding: 3px 0; }
.pd-kv + .pd-kv { border-top: 1px solid var(--c-neutral-25); }
.pd-k { color: var(--c-neutral-500); flex-shrink: 0; }
.pd-v { margin-left: auto; color: var(--c-neutral-600); text-align: right; min-width: 0; }
.pd-pricenote { font-size: var(--size-11); color: var(--c-neutral-500); flex-shrink: 0; }

/* ── 同款 ── */
/* 虚线框 = 时候未到。斜纹是「未抓到」专属，两种质地永远只有两种。 */
.pd-waiting {
  border: 1px dashed var(--border-control); border-radius: var(--radius-md);
  padding: var(--space-3); text-align: center; color: var(--c-neutral-600);
  font-size: var(--size-base);
}
.pd-waiting b { display: block; font-size: var(--size-md); color: var(--c-neutral-900);
                font-weight: 500; margin-bottom: 4px; }
.pd-waiting p { margin: 0; line-height: var(--leading-snug); }
.pd-sametext { margin: 0; font-size: var(--size-base); color: var(--c-neutral-600);
               line-height: var(--leading-snug); }
.pd-members { display: block; }
.pd-member { display: flex; align-items: center; gap: 9px; padding: 4px 0; text-decoration: none;
             font-size: var(--size-sm); color: var(--c-neutral-600); }
.pd-member:hover { background: var(--c-neutral-25); }
.pd-membername { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-member.mine .pd-membername { font-weight: 500; color: var(--c-neutral-900); }
.pd-spark { display: inline-flex; flex-shrink: 0; min-width: 88px; }   /* GAP spark-w-88 */
.pd-membernum { width: 34px; text-align: right; flex-shrink: 0; }      /* GAP num-w-34 */
.pd-verdict { display: flex; align-items: center; gap: var(--space-2); padding: 5px 0;
              font-size: var(--size-sm); border-top: 1px solid var(--c-neutral-25); }
.pd-verdictlabel { flex: 1; min-width: 0; color: var(--c-neutral-600); }
.pd-verdictacts { display: flex; gap: 6px; }
.pd-verdictdone { color: var(--c-neutral-900); }
.pd-samefoot { margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--border-hairline);
               font-size: var(--size-sm); color: var(--c-neutral-500); }
.pd-samefoot p { margin: 0 0 4px; line-height: var(--leading-snug); }

/* ── 三档：一行字 + 一个再试，连容器都没有 ── */
.pd-tiny { margin: 4px 0 0; font-size: var(--size-sm); color: var(--c-neutral-600);
           display: flex; align-items: center; gap: var(--space-2); }
.pd-actionerr:empty { display: none; }
.pd-actionerr { display: inline-flex; }

/* ── 弹层 ── */
.pd-radios { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-bottom: var(--space-3); }
.pd-radio { display: inline-flex; align-items: center; gap: 6px; font-size: var(--size-base);
            min-height: var(--a11y-floor-target-used); cursor: pointer; }

/* ── 反馈浮标 ── */
.pd-float { position: sticky; bottom: 0; margin-left: auto; align-self: flex-end;
            box-shadow: var(--shadow-card); }
