/* ============================================================================
   设计系统 · 组件规范层（2026-11-07，D33 拆分）
   加载顺序：app.css（基础/原型）→ theme-ios.css（iOS 风格）→ tokens.css（令牌）
             → 本文件（组件规范）→ skins.css（皮肤）→ motion.css（动效）
   本文件在 tokens.css 之后，因此只消费令牌；语义令牌又引用 app.css 的变量，
   所以本文件对「经典 / iOS」两套风格、5 套皮肤同时生效，不需要分支。
   依据：Apple HIG 44pt / Material Design 3 48dp 触控区、WCAG 2.2 Target Size (AA 24px)、
        WCAG 2.1 文本对比度 4.5:1、Ant Design / Fluent 的桌面控件 32–40px 分级，
        以及主/次/三级按钮层级与 hover / focus-visible / active / disabled / busy 五态反馈。
   桌面鼠标场景取 32 / 36 / 40 三档，图标按钮 36×36，均带可见焦点环。
   ========================================================================== */

/* ----------------------------------------------------------------------------
   令牌定义已全部迁移到 tokens.css（2026-11-07，D33）。
   本文件只消费令牌、不定义令牌 —— 别再往这里加 :root 变量，
   否则会出现"同一个 --ds-* 两处定义、改一处不生效"的隐形 bug。
   令牌清单与用法见 docs/DESIGN.md §2，可视化见 src/v2/ds-preview.html。
   -------------------------------------------------------------------------- */

/* ---------- 图标：统一线性 SVG（stroke 1.75 / round / currentColor） ---------- */
.ic svg,
.nav a .ic svg,
.search svg,
.btn svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}
.nav a .ic svg { width: var(--ds-icon); height: var(--ds-icon); }
.search svg { width: 16px; height: 16px; }
.btn svg { width: 15px; height: 15px; }

/* ---------- 按钮：尺寸 / 层级 / 五态反馈（含 iOS 主题） ---------- */
.btn,
body.ui-ios .btn {
  height: var(--ds-control-md);
  min-height: var(--ds-control-md);
  padding: 0 var(--ds-btn-px);
  border-radius: var(--ds-btn-radius);
  font-size: var(--ds-font-base);
  font-weight: var(--ds-font-medium);
  cursor: pointer;
  transition:
    background-color var(--ds-dur-fast) var(--ds-ease),
    border-color var(--ds-dur-fast) var(--ds-ease),
    color var(--ds-dur-fast) var(--ds-ease),
    box-shadow var(--ds-dur-fast) var(--ds-ease),
    transform var(--ds-dur-fast) var(--ds-ease);
}
.btn.sm,
body.ui-ios .btn.sm {
  height: var(--ds-control-sm);
  min-height: var(--ds-control-sm);
  padding: 0 var(--ds-btn-px-sm);
  font-size: var(--ds-font-sm);
}
.btn.lg,
body.ui-ios .btn.lg {
  height: var(--ds-control-lg);
  min-height: var(--ds-control-lg);
  padding: 0 var(--ds-btn-px-lg);
  /* 与 app.css 的 14px 一致：整合时原为 calc(13px + .5px) = 13.5px，会让重点按钮字号回退半档 */
  font-size: var(--ds-font-md);
}
/* 图标按钮：视觉可小，点击区不小于 36×36 */
.btn.icon,
body.ui-ios .btn.icon {
  width: var(--ds-control-md);
  min-width: var(--ds-control-md);
  padding: 0;
}

/* 一级：实心主色；二级：描边；三级：纯文字。去掉渐变，避免两套主题各自漂移 */
.btn.pri,
.btn.pri.btn-strong,
.btn.lg.pri,
body.ui-ios .btn.pri,
body.ui-ios .btn.pri.btn-strong,
body.ui-ios .btn.lg.pri {
  background: var(--ds-primary);
  border-color: var(--ds-primary);
  color: var(--ds-on-solid);
  box-shadow: var(--ds-shadow-solid);
  filter: none;
  font-weight: 600;
}
.btn.pri:hover:not(:disabled),
.btn.pri.btn-strong:hover:not(:disabled),
.btn.lg.pri:hover:not(:disabled),
body.ui-ios .btn.pri:hover:not(:disabled),
body.ui-ios .btn.pri.btn-strong:hover:not(:disabled) {
  background: var(--ds-primary-hover);
  border-color: var(--ds-primary-hover);
  color: var(--ds-on-solid);
  filter: none;
  transform: translateY(-1px);
}
/* 危险操作：与常规操作视觉分离，统一实色 */
.btn.danger,
body.ui-ios .btn.danger {
  background: var(--ds-danger);
  border-color: var(--ds-danger);
  color: var(--ds-on-solid);
  box-shadow: var(--ds-shadow-solid);
  filter: none;
  font-weight: 600;
}
.btn.danger:hover:not(:disabled),
body.ui-ios .btn.danger:hover:not(:disabled) {
  background: var(--ds-danger-hover);
  border-color: var(--ds-danger-hover);
  color: var(--ds-on-solid);
  filter: none;
}

/* 键盘焦点：所有可交互元素统一可见焦点环（WCAG 2.4.7） */
.btn:focus-visible,
body.ui-ios .btn:focus-visible,
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--ds-primary);
  outline-offset: 2px;
  box-shadow: 0 0 0 3px var(--ds-focus-ring);
}

/* 按压 / 禁用 / 加载中 */
.btn:active:not(:disabled),
body.ui-ios .btn:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: none;
}
.btn:disabled,
.btn[aria-disabled="true"],
body.ui-ios .btn:disabled,
body.ui-ios .btn[aria-disabled="true"] {
  opacity: .45;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
  filter: none;
}
.btn[aria-busy="true"],
.btn.is-loading {
  pointer-events: none;
  opacity: .72;
}
.btn[aria-busy="true"]::before,
.btn.is-loading::before {
  content: "";
  width: 12px;
  height: 12px;
  margin-right: 2px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: ds-spin .7s linear infinite;
}
@keyframes ds-spin { to { transform: rotate(360deg); } }

/* ---------- 按钮位置：行内操作右对齐、主操作在右、危险操作分离 ---------- */
.row-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--ds-space-2);
}
.toolbar-line { gap: var(--ds-space-2); }
.ds-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--ds-space-2);
  padding-top: var(--ds-space-3);
}
/* 危险操作靠左、与右侧主操作拉开，减少误点（Ant Design / Fluent 常见排布） */
.ds-actions > .btn.danger,
.row-actions > .btn.danger { margin-right: auto; }

/* ---------- 减少动态（跟随系统辅助功能） ---------- */
@media (prefers-reduced-motion: reduce) {
  .btn,
  body.ui-ios .btn,
  .btn[aria-busy="true"]::before,
  .btn.is-loading::before {
    animation: none !important;
    transition: none !important;
    transform: none !important;
  }
}

/* ============================================================================
   以下为 2026-11-07 补充的「组件规范层」（D33）
   原则：只新增 .ds-* 命名空间的类 + 补全既有组件缺失的状态，不改任何既有布局与尺寸。
   每个值都来自 tokens.css，出现裸值即视为规范违规。
   ========================================================================== */

/* ---------- 表单控件：补全既有 .inp 缺失的焦点 / 错误 / 禁用三态 ----------
   现状：.inp 有 hover 与 transition，但键盘聚焦时没有任何视觉反馈（WCAG 2.4.7 不达标）。
   这里只加状态，不改尺寸与配色。 */
.inp:focus-within,
.inp:focus-visible {
  border-color: var(--ds-color-accent);
  box-shadow: var(--ds-shadow-focus);
  outline: none;
}
.inp.is-error,
.inp[aria-invalid="true"] {
  border-color: var(--ds-color-danger);
}
.inp.is-error:focus-within,
.inp[aria-invalid="true"]:focus-within {
  box-shadow: 0 0 0 3px var(--ds-color-danger-border);
}
.inp:disabled,
.inp[aria-disabled="true"] {
  background: var(--ds-color-bg-subtle);
  color: var(--ds-color-text-disabled);
  cursor: not-allowed;
}
/* 必填标记：只做视觉提示，语义仍靠 required / aria-required */
.fld.is-required > label::after {
  content: "*";
  color: var(--ds-color-danger);
  margin-left: 2px;
}
/* 字段级错误提示：紧贴控件下方，字号取最小档，避免撑高表单 */
.ds-fld-error {
  display: flex;
  align-items: center;
  gap: var(--ds-space-1);
  margin-top: 2px;
  font-size: var(--ds-font-2xs);
  line-height: var(--ds-leading-snug);
  color: var(--ds-color-danger);
}

/* ---------- 提示条：四种语义，统一结构与间距 ----------
   variant 用 class 表达，不复用颜色 class，避免"红字=警告"这种语义漂移。 */
.ds-hint {
  display: flex;
  align-items: flex-start;
  gap: var(--ds-space-2);
  padding: var(--ds-space-2) var(--ds-space-3);
  border: 1px solid var(--ds-color-border);
  border-radius: var(--ds-radius-md);
  background: var(--ds-color-bg-subtle);
  color: var(--ds-color-text-secondary);
  font-size: var(--ds-font-xs);
  line-height: var(--ds-leading-relaxed);
}
.ds-hint__icon {
  flex: none;
  width: var(--ds-icon);
  height: var(--ds-icon);
  margin-top: 1px;
  color: currentColor;
}
.ds-hint--info {
  background: var(--ds-color-accent-subtle);
  border-color: var(--ds-color-accent-border);
  color: var(--ds-color-accent-ink);
}
.ds-hint--success {
  background: var(--ds-color-success-subtle);
  border-color: var(--ds-color-success-border);
  color: var(--ds-color-success);
}
.ds-hint--warning {
  background: var(--ds-color-warning-subtle);
  border-color: var(--ds-color-warning-border);
  color: var(--ds-color-warning);
}
.ds-hint--danger {
  background: var(--ds-color-danger-subtle);
  border-color: var(--ds-color-danger-border);
  color: var(--ds-color-danger);
}

/* ---------- 键帽：快捷键提示统一尺寸（顶栏 Ctrl K 已在用，这里给出通用件） ---------- */
.ds-kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border: 1px solid var(--ds-color-border);
  border-bottom-width: 2px;
  border-radius: var(--ds-radius-xs);
  background: var(--ds-color-surface);
  color: var(--ds-color-text-tertiary);
  font-family: var(--ds-font-family);
  font-size: var(--ds-font-2xs);
  font-weight: var(--ds-font-medium);
  line-height: 1;
  white-space: nowrap;
}

/* ---------- 骨架屏：加载占位，形状跟随内容 ---------- */
.ds-skel {
  display: block;
  border-radius: var(--ds-radius-sm);
  background: linear-gradient(
    90deg,
    var(--ds-color-border-soft) 25%,
    var(--ds-color-border) 37%,
    var(--ds-color-border-soft) 63%
  );
  background-size: 400% 100%;
  animation: ds-skel-shimmer 1.4s var(--ds-ease) infinite;
}
.ds-skel--text { height: 10px; }
.ds-skel--title { height: 14px; width: 40%; }
.ds-skel--row { height: var(--ds-table-row-h); border-radius: var(--ds-radius-xs); }
@keyframes ds-skel-shimmer {
  from { background-position: 100% 50%; }
  to { background-position: 0 50%; }
}

/* ---------- 空状态：图标 + 一句话 + 可选主操作 ---------- */
.ds-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--ds-space-2);
  padding: var(--ds-space-8) var(--ds-space-4);
  text-align: center;
  color: var(--ds-color-text-tertiary);
}
.ds-empty__icon {
  width: var(--ds-icon-lg);
  height: var(--ds-icon-lg);
  color: var(--ds-color-text-disabled);
}
.ds-empty__title {
  font-size: var(--ds-font-base);
  font-weight: var(--ds-font-medium);
  color: var(--ds-color-text-secondary);
}
.ds-empty__desc {
  max-width: 34em;
  font-size: var(--ds-font-xs);
  line-height: var(--ds-leading-relaxed);
}

/* ---------- 分隔线 ---------- */
.ds-divider {
  height: 1px;
  border: 0;
  margin: var(--ds-space-3) 0;
  background: var(--ds-color-border-soft);
}
.ds-divider--vertical {
  width: 1px;
  height: auto;
  align-self: stretch;
  margin: 0 var(--ds-space-2);
}

/* ---------- 状态点：列表/侧栏里的迷你状态指示（配文字，不单独承载语义） ---------- */
.ds-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  flex: none;
  border-radius: var(--ds-radius-pill);
  background: var(--ds-color-text-disabled);
}
.ds-dot--ok { background: var(--ds-color-success); }
.ds-dot--warn { background: var(--ds-color-warning); }
.ds-dot--danger { background: var(--ds-color-danger); }
.ds-dot--info { background: var(--ds-color-accent); }

/* ---------- 工具类（只做一件事，可组合） ---------- */
.ds-num {
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
.ds-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 仅供读屏：视觉隐藏但保留在无障碍树里 */
.ds-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* 跳过导航链接：键盘用户 Tab 第一下就能直达主内容（WCAG 2.4.1） */
.ds-skip-link {
  position: absolute;
  left: var(--ds-space-2);
  top: -100px;
  z-index: var(--ds-z-tooltip);
  padding: var(--ds-space-2) var(--ds-space-3);
  border-radius: var(--ds-radius-sm);
  background: var(--ds-color-surface);
  color: var(--ds-color-text);
  box-shadow: var(--ds-shadow-md);
  font-size: var(--ds-font-sm);
  text-decoration: none;
}
.ds-skip-link:focus {
  top: var(--ds-space-2);
}

/* ---------- 统一关闭动效（系统偏好 + 应用内开关都要能被关掉） ---------- */
@media (prefers-reduced-motion: reduce) {
  .ds-skel { animation: none; }
}
body.ui-no-anim .ds-skel { animation: none; }
