/**
 * 组件原语样式（工单 W1-03 产出 2）
 * 依赖 tokens.css 先加载。全部原生 CSS，无框架。
 *
 * 像素边框统一用「box-shadow 硬框架法」：四边各外扩 4px，角部自然形成
 * 4px 阶梯缺口；无图片资产依赖（精灵资产是 W7-01 的事）、可嵌套不糊、
 * blur 恒 0。布局补偿：外扩 4px 由 margin: 4px 吸收。
 *
 * 状态镜像类：:hover/:active/:focus-visible 之外提供 .is-hover/.is-active/
 * .is-focus/.is-disabled/.is-loading，供展示廊与测试静态呈现全部状态。
 * hover/active 属 PRD §9.4 L1 关键反馈：不可关。
 * 按压手感（W7-03 打磨）：按下 0ms 即时到位（脆），松手 120ms 两帧
 * 顿挫回弹（--ds-dur-tick + --ds-ease-snap）——一顿回位，不用连续缓动。
 */

/* ── 1. Button ─────────────────────────────────────────── */
.dsp-btn {
  /* W10-07：ember-2 底配反白字 3.53:1 不达 AA；主按钮面降到 ember-1（同色相 ramp 暗档，
     与 market 购买链路的既有 a11y 处理一致），品牌主色 ember-2 不动 */
  --_bg: var(--ds-ember-1);
  --_fg: var(--ds-ink-inv);
  --_frame: var(--ds-ink-1);
  appearance: none;
  border: 0;
  background: var(--_bg);
  color: var(--_fg);
  font-family: var(--ds-font-pixel);
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
  padding: 8px 16px;
  margin: 4px;
  cursor: pointer;
  user-select: none;
  box-shadow:
    0 -4px 0 var(--_frame),
    0 4px 0 var(--_frame),
    -4px 0 0 var(--_frame),
    4px 0 0 var(--_frame),
    8px 8px 0 var(--ds-ink-1);
  /* 松手回弹：120ms 两帧顿挫（L1，≤200ms 不延迟内容）；按下侧在 :active 里关过渡保持即时 */
  transition:
    transform var(--ds-dur-tick) var(--ds-ease-snap),
    box-shadow var(--ds-dur-tick) var(--ds-ease-snap);
}
.dsp-btn--secondary {
  --_bg: var(--ds-panel);
  --_fg: var(--ds-ink-1);
}
.dsp-btn--danger {
  --_bg: var(--ds-danger);
}
.dsp-btn--lg {
  font-size: var(--ds-font-size-m);
  line-height: var(--ds-line-height-m);
  padding: 12px 24px;
}
.dsp-btn:hover:not(:disabled):not(.is-disabled):not(.is-loading),
.dsp-btn.is-hover {
  --_bg: var(--ds-ember-2);
}
.dsp-btn--secondary:hover:not(:disabled):not(.is-disabled):not(.is-loading),
.dsp-btn--secondary.is-hover {
  --_bg: var(--ds-floor);
}
.dsp-btn--danger:hover:not(:disabled):not(.is-disabled):not(.is-loading),
.dsp-btn--danger.is-hover {
  --_bg: var(--ds-ember-2);
}
/* 压下去的手感：2px 位移 + 投影收起（L1，不可关）；按下 0ms 即时，不回弹 */
.dsp-btn:active:not(:disabled):not(.is-disabled),
.dsp-btn.is-active {
  transition: none;
  transform: translate(2px, 2px); /* lint-pixel-allow: 工单产出2-Button 指定按下 2px 位移 */
  box-shadow:
    0 -4px 0 var(--_frame),
    0 4px 0 var(--_frame),
    -4px 0 0 var(--_frame),
    4px 0 0 var(--_frame);
}
.dsp-btn:focus-visible,
.dsp-btn.is-focus {
  outline: 4px solid var(--ds-azure-2);
  outline-offset: -4px;
}
.dsp-btn:disabled,
.dsp-btn.is-disabled {
  --_bg: var(--ds-mute);
  --_fg: var(--ds-panel);
  --_frame: var(--ds-ink-2);
  cursor: not-allowed;
  box-shadow:
    0 -4px 0 var(--_frame),
    0 4px 0 var(--_frame),
    -4px 0 0 var(--_frame),
    4px 0 0 var(--_frame);
}
.dsp-btn__dots {
  display: none;
  margin-left: 8px;
}
.dsp-btn__dots i {
  display: inline-block;
  width: 4px;
  height: 4px;
  margin-left: 4px;
  background: currentColor;
  animation: dsp-blink var(--ds-dur-cycle) var(--ds-ease-snap) infinite;
}
.dsp-btn__dots i:nth-child(2) { animation-delay: var(--ds-dur-step); }
.dsp-btn__dots i:nth-child(3) { animation-delay: var(--ds-dur-beat); }
.dsp-btn.is-loading {
  cursor: wait;
  pointer-events: none;
}
.dsp-btn.is-loading .dsp-btn__dots { display: inline-block; }
@keyframes dsp-blink {
  0% { opacity: 1; }
  50% { opacity: 0; }
  100% { opacity: 1; }
}

/* ── 2. Panel ──────────────────────────────────────────── */
.dsp-panel {
  background: var(--ds-panel);
  padding: 16px;
  margin: 4px;
  box-shadow:
    0 -4px 0 var(--ds-ink-1),
    0 4px 0 var(--ds-ink-1),
    -4px 0 0 var(--ds-ink-1),
    4px 0 0 var(--ds-ink-1),
    8px 8px 0 var(--ds-ink-1);
}
/* 嵌套层：地板色、无投影，里外两级读得出层次 */
.dsp-panel .dsp-panel,
.dsp-panel--inset {
  background: var(--ds-floor);
  box-shadow:
    0 -4px 0 var(--ds-ink-2),
    0 4px 0 var(--ds-ink-2),
    -4px 0 0 var(--ds-ink-2),
    4px 0 0 var(--ds-ink-2);
}

/* ── 3. ProgressBar（分段像素格，不是平滑条）────────────── */
.dsp-progress {
  --_fill: var(--ds-jade-2);
  display: flex;
  gap: 4px;
  padding: 4px;
  margin: 4px;
  background: var(--ds-wall);
  box-shadow:
    0 -4px 0 var(--ds-ink-1),
    0 4px 0 var(--ds-ink-1),
    -4px 0 0 var(--ds-ink-1),
    4px 0 0 var(--ds-ink-1);
}
.dsp-progress__cell {
  width: 12px;
  height: 12px;
  background: var(--ds-panel);
}
.dsp-progress__cell.is-on {
  background: var(--_fill);
}
.dsp-progress--violet { --_fill: var(--ds-violet-2); }
.dsp-progress--azure { --_fill: var(--ds-azure-2); }
.dsp-progress--ember { --_fill: var(--ds-ember-2); }

/* ── 4. Chip ───────────────────────────────────────────── */
.dsp-chip {
  --_bg: var(--ds-floor);
  --_fg: var(--ds-ink-1);
  display: inline-block;
  background: var(--_bg);
  color: var(--_fg);
  font-family: var(--ds-font-pixel);
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
  padding: 4px 8px;
  margin: 4px;
  box-shadow:
    0 -4px 0 var(--ds-ink-1),
    0 4px 0 var(--ds-ink-1),
    -4px 0 0 var(--ds-ink-1),
    4px 0 0 var(--ds-ink-1);
}
/* W10-07：n/ssr/warning 底已收敛到深档，统一配反白字过 AA */
.dsp-chip--n   { --_bg: var(--ds-rarity-n); --_fg: var(--ds-ink-inv); }
.dsp-chip--r   { --_bg: var(--ds-rarity-r); --_fg: var(--ds-ink-inv); }
.dsp-chip--sr  { --_bg: var(--ds-rarity-sr); --_fg: var(--ds-ink-inv); }
.dsp-chip--ssr { --_bg: var(--ds-rarity-ssr); --_fg: var(--ds-ink-inv); }
.dsp-chip--success { --_bg: var(--ds-success); --_fg: var(--ds-ink-inv); }
.dsp-chip--warning { --_bg: var(--ds-warning); --_fg: var(--ds-ink-inv); }
.dsp-chip--danger  { --_bg: var(--ds-danger); --_fg: var(--ds-ink-inv); }
.dsp-chip--info    { --_bg: var(--ds-info); --_fg: var(--ds-ink-inv); }

/* ── 5. Slot（装备槽/工位格：空/已占/锁定）──────────────── */
.dsp-slot {
  width: 48px;
  height: 48px;
  margin: 4px;
  display: grid;
  place-items: center;
  background: var(--ds-floor);
  /* W10-07：空槽符号用 ink-2（mute 在 floor 上 3.79:1 不达 AA） */
  color: var(--ds-ink-2);
  font-family: var(--ds-font-pixel);
  font-size: var(--ds-font-size-s);
  box-shadow:
    0 -4px 0 var(--ds-mute),
    0 4px 0 var(--ds-mute),
    -4px 0 0 var(--ds-mute),
    4px 0 0 var(--ds-mute);
}
.dsp-slot--filled {
  background: var(--ds-panel);
  color: var(--ds-ink-1);
  box-shadow:
    0 -4px 0 var(--ds-ink-1),
    0 4px 0 var(--ds-ink-1),
    -4px 0 0 var(--ds-ink-1),
    4px 0 0 var(--ds-ink-1),
    8px 8px 0 var(--ds-ink-1);
}
.dsp-slot--locked {
  background: var(--ds-wall);
  /* W10-07：ink-2 在 wall 上 <4.5，锁定槽文字用 ink-1 */
  color: var(--ds-ink-1);
}
.dsp-slot:focus-visible,
.dsp-slot.is-focus {
  outline: 4px solid var(--ds-azure-2);
  outline-offset: -4px;
}

/* ── 6. AvatarFrame（边框色随稀有度）────────────────────── */
.dsp-avatar {
  --_rarity: var(--ds-rarity-n);
  width: 64px;
  height: 64px;
  margin: 4px;
  padding: 4px;
  background: var(--ds-panel);
  box-shadow:
    0 -4px 0 var(--_rarity),
    0 4px 0 var(--_rarity),
    -4px 0 0 var(--_rarity),
    4px 0 0 var(--_rarity),
    8px 8px 0 var(--ds-ink-1);
}
.dsp-avatar--r   { --_rarity: var(--ds-rarity-r); }
.dsp-avatar--sr  { --_rarity: var(--ds-rarity-sr); }
.dsp-avatar--ssr { --_rarity: var(--ds-rarity-ssr); }
.dsp-avatar img,
.dsp-avatar canvas {
  display: block;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
}

/* ── 7. Dialog（模态：遮罩 + 焦点陷阱 + Esc）────────────── */
/* 无半透明叠色可用（调色板纪律），遮罩用纯色墙面色压场 */
.dsp-dialog-overlay {
  position: fixed;
  inset: 0;
  z-index: 64;
  display: grid;
  place-items: center;
  padding: 16px;
  background: var(--ds-wall);
}
.dsp-dialog {
  width: 100%;
  max-width: 448px;
  margin: 4px;
  padding: 24px;
  background: var(--ds-panel);
  color: var(--ds-ink-1);
  font-family: var(--ds-font-pixel);
  box-shadow:
    0 -4px 0 var(--ds-ink-1),
    0 4px 0 var(--ds-ink-1),
    -4px 0 0 var(--ds-ink-1),
    4px 0 0 var(--ds-ink-1),
    8px 8px 0 var(--ds-ink-1);
}
.dsp-dialog__title {
  font-size: var(--ds-font-size-m);
  line-height: var(--ds-line-height-m);
  margin: 0 0 16px;
}
.dsp-dialog__body {
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
}
.dsp-dialog__actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  margin-top: 24px;
}

/* ── 8. Toast（非阻塞，四语义色）────────────────────────── */
.dsp-toast-stack {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 96;
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 320px;
}
.dsp-toast {
  --_kind: var(--ds-info);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  margin: 4px;
  background: var(--ds-panel);
  color: var(--ds-ink-1);
  font-family: var(--ds-font-pixel);
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
  box-shadow:
    0 -4px 0 var(--_kind),
    0 4px 0 var(--_kind),
    -4px 0 0 var(--_kind),
    4px 0 0 var(--_kind),
    8px 8px 0 var(--ds-ink-1);
}
.dsp-toast--success { --_kind: var(--ds-success); }
.dsp-toast--warning { --_kind: var(--ds-warning); }
.dsp-toast--danger  { --_kind: var(--ds-danger); }
.dsp-toast__mark {
  flex: none;
  width: 12px;
  height: 12px;
  background: var(--_kind);
}
.dsp-toast__close {
  flex: none;
  border: 0;
  background: transparent;
  color: var(--ds-ink-2);
  font-family: var(--ds-font-pixel);
  font-size: var(--ds-font-size-s);
  cursor: pointer;
  padding: 4px;
}
.dsp-toast__close:focus-visible {
  outline: 4px solid var(--ds-azure-2);
  outline-offset: -4px;
}

/* ── 9. Tabs ───────────────────────────────────────────── */
.dsp-tabs {
  display: flex;
  gap: 4px;
  padding: 4px 4px 0;
  border-bottom: 4px solid var(--ds-ink-1);
}
.dsp-tab {
  appearance: none;
  border: 0;
  padding: 8px 16px;
  background: var(--ds-floor);
  color: var(--ds-ink-2);
  font-family: var(--ds-font-pixel);
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
  cursor: pointer;
}
.dsp-tab:hover,
.dsp-tab.is-hover {
  background: var(--ds-wall);
  color: var(--ds-ink-1);
}
/* 选中页签与下方面板咬合：上左右框架，底部开放 */
.dsp-tab[aria-selected='true'],
.dsp-tab.is-active {
  background: var(--ds-panel);
  color: var(--ds-ink-1);
  box-shadow:
    0 -4px 0 var(--ds-ink-1),
    -4px 0 0 var(--ds-ink-1),
    4px 0 0 var(--ds-ink-1);
}
.dsp-tab:focus-visible,
.dsp-tab.is-focus {
  outline: 4px solid var(--ds-azure-2);
  outline-offset: -4px;
}
.dsp-tab:disabled,
.dsp-tab.is-disabled {
  background: var(--ds-wall);
  color: var(--ds-mute);
  cursor: not-allowed;
}

/* ── 10. ListRow ───────────────────────────────────────── */
.dsp-listrow {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 12px 16px;
  background: var(--ds-panel);
  border-bottom: 4px solid var(--ds-floor);
  font-family: var(--ds-font-pixel);
}
.dsp-listrow:hover,
.dsp-listrow.is-hover {
  background: var(--ds-floor);
}
.dsp-listrow:active,
.dsp-listrow.is-active {
  background: var(--ds-wall);
}
.dsp-listrow:focus-visible,
.dsp-listrow.is-focus {
  outline: 4px solid var(--ds-azure-2);
  outline-offset: -4px;
}
.dsp-listrow.is-disabled {
  color: var(--ds-mute);
  background: var(--ds-paper);
}
.dsp-listrow__icon {
  width: 32px;
  height: 32px;
  image-rendering: pixelated;
  background: var(--ds-wall);
}
.dsp-listrow__text {
  min-width: 0;
}
.dsp-listrow__main {
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
  color: var(--ds-ink-1);
}
.dsp-listrow__sub {
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
  color: var(--ds-ink-2);
}
.dsp-listrow.is-disabled .dsp-listrow__main,
.dsp-listrow.is-disabled .dsp-listrow__sub {
  color: var(--ds-mute);
}
.dsp-listrow__actions {
  display: flex;
  gap: 8px;
  align-items: center;
}

/* ── W10-02 按钮体系：幽灵档、同行同高、移动端点击区 44px ──
 * T1 重评：主行动按钮（dsp-btn）min-height 44px（11×4 栅格），
 * 不改配色/硬阴影/像素框；chip / tab 仍走紧凑档（筛选密度优先）。
 * 同一行按钮强制同高、同字号、基线对齐（用户真机「重试」比「回到办公室」大一倍）。
 */
.dsp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  box-sizing: border-box;
  vertical-align: middle;
}
.dsp-btn--ghost {
  --_bg: var(--ds-paper);
  --_fg: var(--ds-ink-1);
  box-shadow:
    0 -4px 0 var(--_frame),
    0 4px 0 var(--_frame),
    -4px 0 0 var(--_frame),
    4px 0 0 var(--_frame);
}
.dsp-btn--ghost:hover:not(:disabled):not(.is-disabled):not(.is-loading),
.dsp-btn--ghost.is-hover {
  --_bg: var(--ds-floor);
}
.dsp-btn-row,
.dsp-notice__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--ds-space-2);
}
.dsp-btn-row > .dsp-btn,
.dsp-notice__actions > .dsp-btn {
  margin: 0;
  min-height: 44px;
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
  padding: 12px 16px;
}

/* ── W10-02 字号阶梯（标题 / 正文 / 辅助，全站只走 token）── */
.dsp-type-title {
  margin: 0;
  font-size: var(--ds-font-size-m);
  line-height: var(--ds-line-height-m);
  color: var(--ds-ink-1);
}
.dsp-type-body {
  margin: 0;
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
  color: var(--ds-ink-1);
}
.dsp-type-aux {
  margin: 0;
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
  color: var(--ds-ink-2);
}

/* ── W10-02 屏级容器：内容少时撑满主区，避免半屏空白 ── */
.dsp-screen {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-3);
  min-height: 0;
  width: 100%;
}
.dsp-screen--center {
  justify-content: center;
}

/* ── W10-02 ScreenNotice：加载 / 空 / 错误 / 游客引导 ── */
.dsp-notice {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  min-height: 0;
}
.dsp-notice.dsp-screen {
  flex: 1 1 auto;
}
.dsp-notice__card {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-3);
  padding: var(--ds-space-4);
}
.dsp-notice__title {
  margin: 0;
  font-size: var(--ds-font-size-m);
  line-height: var(--ds-line-height-m);
  color: var(--ds-ink-1);
}
.dsp-notice__body {
  margin: 0;
  font-size: var(--ds-font-size-s);
  line-height: var(--ds-line-height-s);
  color: var(--ds-ink-2);
}
.dsp-notice__body p {
  margin: 0 0 var(--ds-space-2);
}
.dsp-notice__body p:last-child {
  margin-bottom: 0;
}
.dsp-notice__actions {
  margin-top: var(--ds-space-1);
}
.dsp-notice--loading .dsp-notice__title,
.dsp-notice--empty .dsp-notice__title {
  color: var(--ds-ink-1);
}
.dsp-notice--error .dsp-notice__card {
  box-shadow:
    0 -4px 0 var(--ds-ink-1),
    0 4px 0 var(--ds-ink-1),
    -4px 0 0 var(--ds-ink-1),
    4px 0 0 var(--ds-ink-1),
    8px 8px 0 var(--ds-ink-1);
}
.dsp-notice--guest .dsp-notice__card {
  box-shadow:
    0 -4px 0 var(--ds-ember-2),
    0 4px 0 var(--ds-ember-2),
    -4px 0 0 var(--ds-ember-2),
    4px 0 0 var(--ds-ember-2),
    8px 8px 0 var(--ds-ink-1);
}

/* ── W10-04 空白修正：屏内已有内容卡时，状态卡跟流不撑满居中 ──
 * 只有 ScreenNotice 是父级唯一子节点时才 flex 撑满 + 垂直居中。
 * 有兄弟内容卡（说明、筛选、列表）时取消 stretch，紧跟内容流。
 * flex 1 0 auto：短屏仍撑满居中，长屏按内容长高，底部安全区才能进滚动。
 */
.dsp-screen {
  flex: 1 0 auto;
  min-height: auto;
}

.dsp-screen > .dsp-notice.dsp-screen:not(:only-child),
.dsp-screen > .dsp-notice:not(:only-child) {
  flex: 0 0 auto;
  justify-content: flex-start;
  min-height: 0;
}
