/* ==========================================================================
   微迹 Weetrack — 基础样式：重置、排版、通用控件
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
  padding: 0;
}

html,
body {
  height: 100%;
}

body {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  background: var(--app-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  cursor: pointer;
}

a {
  color: inherit;
  text-decoration: none;
}

ul,
ol {
  list-style: none;
}

img,
svg {
  display: block;
  max-width: 100%;
}

[hidden] {
  display: none !important;
}

:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

/* ---------- 滚动条 ---------- */
* {
  scrollbar-width: thin;
  scrollbar-color: #d6d1c9 transparent;
}
*::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
*::-webkit-scrollbar-track {
  background: transparent;
}
*::-webkit-scrollbar-thumb {
  background: #d9d4cc;
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover {
  background: #c6c0b6;
  background-clip: content-box;
}

/* ==========================================================================
   排版工具
   ========================================================================== */
.t-title {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.t-sub {
  font-size: 12px;
  color: var(--text-3);
}
.t-muted {
  color: var(--text-2);
}
.t-num {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
}
.ellipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.row {
  display: flex;
  align-items: center;
}
.row-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.gap-4 { gap: 4px; }
.gap-6 { gap: 6px; }
.gap-8 { gap: 8px; }
.gap-10 { gap: 10px; }
.gap-12 { gap: 12px; }
.grow { flex: 1 1 auto; min-width: 0; }

/* ==========================================================================
   按钮
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 34px;
  padding: 0 14px;
  border-radius: var(--r-sm);
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-xs);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
    transform var(--dur) var(--ease), color var(--dur) var(--ease);
  white-space: nowrap;
}
.btn:hover {
  background: var(--surface-2);
  border-color: #d5cfc6;
}
.btn:active {
  transform: translateY(1px);
}
.btn[disabled] {
  opacity: 0.55;
  pointer-events: none;
}

.btn-primary {
  background: var(--text);
  border-color: var(--text);
  color: var(--text-inverse);
}
.btn-primary:hover {
  background: #3a3733;
  border-color: #3a3733;
}

.btn-brand {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
}
.btn-brand:hover {
  background: var(--brand-deep);
  border-color: var(--brand-deep);
}

.btn-soft {
  background: var(--surface-3);
  border-color: transparent;
  box-shadow: none;
  color: var(--text-2);
}
.btn-soft:hover {
  background: var(--surface-sunken);
  color: var(--text);
}

.btn-ghost {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  color: var(--text-2);
}
.btn-ghost:hover {
  background: var(--surface-3);
  color: var(--text);
}

.btn-danger {
  background: var(--red-soft);
  border-color: transparent;
  color: var(--red);
}
.btn-danger:hover {
  background: #f4d9d6;
}

.btn-sm {
  height: 28px;
  padding: 0 10px;
  font-size: 12px;
  border-radius: var(--r-xs);
}
.btn-lg {
  height: 42px;
  padding: 0 20px;
  font-size: 14px;
  border-radius: var(--r-md);
}
.btn-icon {
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: var(--r-sm);
  font-size: 14px;
}

/* 「+ 新建」胶囊按钮（参考稿右上角） */
.btn-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 28px;
  padding: 0 12px 0 10px;
  border-radius: var(--r-pill);
  font-size: 12px;
  font-weight: 500;
  color: var(--text-2);
  background: var(--surface-3);
  transition: all var(--dur) var(--ease);
}
.btn-pill:hover {
  background: var(--brand);
  color: var(--on-brand);
}
.btn-pill .plus {
  font-size: 13px;
  line-height: 1;
}

/* ==========================================================================
   表单
   ========================================================================== */
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.field-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-2);
}
.field-hint {
  font-size: 11px;
  color: var(--text-3);
}

/* ==========================================================================
   主题选择器（用户 2026-10-03 提的"对整个网站做颜色主题"）
   --------------------------------------------------------------------------
   每个主题一张小卡片：左边一块**那个主题的底色**，右下角一个主色小点。
   为什么要色块：主题多了之后光看名字（"雾蓝""藕荷"）不知道长什么样，
   得让人一眼看出"点了会变成什么色调"。
   ========================================================================== */
.theme-grid {
  display: grid;
  /* 自动铺开：宽就多列、窄就少列，不用写断点 */
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 8px;
}
.theme-card {
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  padding: 7px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--surface);
  cursor: pointer;
  transition: border-color .12s var(--ease), background .12s var(--ease);
}
.theme-card:hover { border-color: var(--line-strong); background: var(--surface-2); }
/* 选中的那张：主色描边 + 一点点主色底 */
.theme-card.on {
  border-color: var(--brand);
  background: var(--brand-soft);
}
/* 色块：底色打底 */
.theme-swatch {
  position: relative;
  display: block;
  height: 34px;
  border-radius: 7px;
  border: 1px solid var(--line);
  /* 【色块必须无视当前主题】——
     它展示的是"那个主题的样子"，所以颜色由 inline style 给死，
     不能跟当前主题的变量走（那样八个色块会全长一样）。 */
}
/* 右下角那个小点 = 那个主题的主色 */
.theme-swatch-dot {
  position: absolute;
  right: 6px;
  bottom: 5px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: currentColor;
  /* 用主题自己的主色 —— JS 里通过 style 设了 color，见下 */
  box-shadow: 0 0 0 2px rgba(255, 255, 255, .7);
}
.theme-card-name {
  font-size: 11.5px;
  color: var(--text-2);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.theme-card.on .theme-card-name { color: var(--brand-deep); font-weight: 600; }

.field-error {
  font-size: 12px;
  color: var(--red);
  min-height: 16px;
}

.input,
.textarea,
.select {
  width: 100%;
  padding: 9px 12px;
  font-size: 13px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.input::placeholder,
.textarea::placeholder {
  color: var(--text-3);
}
.input:focus,
.textarea:focus,
.select:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
.textarea {
  resize: vertical;
  min-height: 76px;
  line-height: 1.65;
}
.select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-3) 50%),
    linear-gradient(135deg, var(--text-3) 50%, transparent 50%);
  background-position: calc(100% - 16px) 52%, calc(100% - 11px) 52%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 30px;
  cursor: pointer;
}

/* 分段选择器 */
.segment {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  background: var(--surface-3);
  border-radius: var(--r-sm);
}
.segment button {
  height: 26px;
  padding: 0 11px;
  border-radius: var(--r-xs);
  font-size: 12px;
  font-weight: 500;
  color: var(--text-3);
  transition: all var(--dur) var(--ease);
  white-space: nowrap;
}
.segment button:hover {
  color: var(--text-2);
}
.segment button.active {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-xs);
}

/* 分段控件里的三块：图标 / 文字 / 数量小标。
   由 util.js 的 segment() 统一渲染 —— 以前这几块每个模块各写各的类名，
   图标和数量小标的字号、颜色就对不齐（Agent 的图标、密匣的条数标签）。 */
.segment button .seg-ico {
  font-size: 13px;
  opacity: 0.85;
}
.segment button .seg-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.segment button .seg-count {
  font-size: 10.5px;
  font-family: var(--font-num);
  line-height: 15px;
  padding: 0 6px;
  border-radius: 20px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-3);
}
.segment button.active .seg-count {
  color: inherit;
  opacity: 0.75;
}

/* 颜色 / 图标选择网格 */
.swatch-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid transparent;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.swatch:hover {
  transform: scale(1.12);
}
.swatch.active {
  border-color: var(--text);
}

.icon-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(34px, 1fr));
  gap: 6px;
}
.icon-cell {
  height: 34px;
  border-radius: var(--r-sm);
  font-size: 17px;
  background: var(--surface-3);
  transition: all var(--dur) var(--ease);
}
.icon-cell:hover {
  background: var(--surface-sunken);
}
.icon-cell.active {
  background: var(--brand-soft);
  box-shadow: inset 0 0 0 1.5px var(--brand);
}

/* 开关 */
.switch {
  position: relative;
  width: 36px;
  height: 20px;
  border-radius: 999px;
  background: var(--line-strong);
  transition: background var(--dur) var(--ease);
  flex: none;
}
.switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-xs);
  transition: transform var(--dur) var(--ease);
}
.switch[aria-checked="true"] {
  background: var(--brand);
}
.switch[aria-checked="true"]::after {
  transform: translateX(16px);
}

/* ==========================================================================
   标签 / 徽标
   ========================================================================== */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 20px;
  padding: 0 8px;
  border-radius: var(--r-pill);
  font-size: 11px;
  font-weight: 500;
  /* 用 normal 而不是 1。
     line-height:1 让行盒高度正好等于字号，字体自身的上下伸展空间被压没了，
     文字在盒子里会偏上约 1px（量出来是上留白 2.5px、下留白 3.5px）。
     改成 normal 后上下各 3px，视觉上才是真正居中。 */
  line-height: normal;
  white-space: nowrap;
}
.pill-gray { background: var(--surface-3); color: var(--text-2); }
.pill-important { background: var(--brand-soft); color: var(--brand-deep); }
.pill-handy { background: var(--green-soft); color: var(--tone-green-fg); }
.pill-urgent { background: var(--red-soft); color: var(--red); }
.pill-violet { background: var(--violet-soft); color: var(--tone-violet-fg); }
.pill-blue { background: var(--blue-soft); color: var(--tone-blue-fg); }
.pill-amber { background: var(--amber-soft); color: var(--tone-amber-fg); }
.pill-green { background: var(--green-soft); color: var(--tone-green-fg); }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 18px;
  padding: 0 7px;
  border-radius: var(--r-xs);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.badge-soon {
  background: var(--amber-soft);
  color: var(--tone-amber-fg);
}
.badge-live {
  background: var(--green-soft);
  color: var(--tone-green-fg);
}

/* ==========================================================================
   完成勾选框
   --------------------------------------------------------------------------
   早期是「圆点 + 圆环」的样子，容易和单选钮混淆。
   现在改成**方形勾选框**：未完成是空心方框，完成后填色并出现勾号。

   它和右边的「编辑 / 删除」按钮是同一家族：
     · 同样的圆角、同样的描边色、同样跟随 currentColor
     · 图标本身是同一套线条 SVG（对勾 / 铅笔 / 垃圾桶）
   所以这里不再写死颜色，交给 .check 的 color 统一控制。
   ========================================================================== */
.check {
  flex: none;
  /* 尺寸和「编辑 / 删除」按钮保持一致（都在 .task-row 里定义）。
     三个控件同宽同高，再配上相同的间距，一排看过去才是齐的。
     不在 .task-row 里时（比如首页快捷勾选）回退到 24px。 */
  width: var(--acts-size, 24px);
  height: var(--acts-size, 24px);
  /* 方形勾选框：不用 50% 圆的造型；和操作按钮同一套圆角语言 */
  border-radius: 7px;
  /* 【默认不画边框，只留一个勾】
     原来是常驻 1.6px 灰框，摆在两个纯图标按钮旁边显得特别「重」：
     编辑/删除都是没有外框的线条图标，只有完成外面套了个方框，
     三个凑一排就不是一个家族。

     现在默认用**透明**边框 —— 注意是透明而不是 none：
     保留占位，悬停时边框出现就不会让整个布局跳一下。
     鼠标移上来才显示边框和淡底，既干净又清楚地暗示「这里能点」。 */
  border: 1.6px solid transparent;
  background: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
    color var(--dur) var(--ease), transform var(--dur) var(--ease);
  position: relative;
  cursor: pointer;
  padding: 0;
  /* 未完成时和「编辑 / 删除」用同一个颜色（--text-2），视觉重量一致。
     之前用 --text-3 只有 2.72:1，细线条看不清。 */
  color: var(--text-2);
  /* 【不再额外加 margin-left】
     这里原来写着 margin-left: 4px，但包着它的 .right 已经有 gap: 10px，
     两者叠加后「删除 → 完成」变成 14px，而「编辑 → 删除」只有 2px
     （那是 .acts 自己的 gap）—— 差出 12px，三个控件看着就是不等距的。

     现在一律交给父容器的 gap 统一管，三者的间距完全相同。
     实测从「2px vs 14px」变成「三个都是 10px」。 */
  margin-left: 0;
}
/* 勾号：同一套线条图标，尺寸和铅笔/垃圾桶**完全一致** */
.check svg {
  width: var(--acts-icon, 15px);
  height: var(--acts-icon, 15px);
  display: block;
  stroke-width: 2.2;
  /* 勾的形状天然偏上（左边那笔在 12.5，右边收在更低处），
     在方框里会显得比几何中心高一点点。往下挪半像素补回来。 */
  transform: translateY(0.5px);
  /* 未完成时的勾要**真的看得见**，但又要明显比已完成淡。

     这里踩过一个坑：一开始用 opacity: 0.4，像素级一量发现
     勾渲染成了 rgb(196,194,191)，压在白底上只有 1.6:1 ——
     肉眼基本看不出来，整个按钮还是个空方框，问题没解决。

     改成用「颜色」而不是「整体透明度」：勾取 --brand（品牌色），
     和方框的灰描边形成颜色区分，一眼能看出「这里是待勾选的」。
     悬停时勾加深成和方框一样的深灰，已完成时则是实心底上的白勾。 */
  color: var(--brand);
}
.check:hover svg {
  /* 鼠标移上来时勾加深，暗示「点一下就是完成」 */
  color: currentColor;
}
/* 已完成的勾：跟按钮文字色走（按钮本身是实心品牌色，勾是白的） */
.check.checked svg {
  color: inherit;
}
/* 老式的字符勾号：仍保留兜底样式（个别地方还在用 span.tick） */
.check .tick {
  font-size: 13px;
  line-height: 1;
  font-weight: 700;
  color: #fff;
  /* 让勾号在中文字体里也居中对齐 */
  transform: translateY(-0.5px);
}
.check:hover {
  /* 鼠标移上来才出现边框和淡底（默认是透明的，见上面的说明） */
  border-color: var(--brand);
  background: var(--brand-soft);
  color: var(--brand);
}
.check:active {
  transform: scale(0.92);
}
/* 已完成：实心色块 + 白勾。
   边框也一起给成品牌色，否则实心块外面会留一圈透明边，看着比旁边的按钮小一号。 */
.check.checked {
  background: var(--brand);
  border-color: var(--brand);
  /* 【勾号的颜色跟着主题走 —— 用 --on-brand】
     白天主色偏暗，白勾 3.24:1；
     夜间主色为了在深底上够亮提到了 #4fb79c，**白勾只有 2.45:1**（检查抓到的），
     所以夜间换成深勾（7.7:1）。一根 --brand 兼顾不了"当文字"和"当底"两件事，
     压在上面的内容色必须单独一个令牌。 */
  color: var(--on-brand);
}
.check.checked:hover {
  /* 已经完成时，悬停给出「点了会取消」的暗示 */
  background: var(--brand-deep);
  border-color: var(--brand-deep);
  color: var(--on-brand);
}
/* 完成态：给按钮一个明确的焦点样式，方便键盘操作 */
.check:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.check-sm {
  width: 17px;
  height: 17px;
  border-radius: 5px;
  margin-left: 0;
}
.check-sm svg {
  width: 11px;
  height: 11px;
}
.check-sm .tick {
  font-size: 10px;
}

/* ==========================================================================
   卡片 / 面板
   ========================================================================== */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
}
.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 16px 12px;
}
.card-head .h-left {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.card-title {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.01em;
  display: flex;
  align-items: center;
  gap: 6px;
}
.card-title .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--brand);
}
.card-body {
  padding: 0 16px 16px;
}
.card-sub {
  font-size: 12px;
  color: var(--text-3);
}
.card-count {
  font-family: var(--font-num);
  font-size: 12px;
  color: var(--text-3);
  padding: 1px 6px;
  background: var(--surface-3);
  border-radius: var(--r-xs);
}

.group-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 2px 10px;
}
.group-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
}
.group-count {
  font-family: var(--font-num);
  font-size: 12px;
  color: var(--text-3);
}

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 26px 16px;
  text-align: center;
  color: var(--text-3);
}
.empty .ico {
  font-size: 22px;
  opacity: 0.6;
}
.empty .txt {
  font-size: 12.5px;
}

/* ==========================================================================
   模态框 / 抽屉
   ========================================================================== */
.overlay {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: var(--overlay);
  backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  animation: fade-in 0.18s var(--ease) forwards;
}
@keyframes fade-in {
  to { opacity: 1; }
}

.modal {
  width: min(660px, 100%);
  max-height: min(86vh, 880px);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  transform: translateY(10px) scale(0.99);
  animation: pop-in 0.2s var(--ease) forwards;
}
.modal-sm { width: min(440px, 100%); }
.modal-lg { width: min(820px, 100%); }
@keyframes pop-in {
  to { transform: translateY(0) scale(1); }
}

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 18px 22px 12px;
  flex: none;
}
.modal-head h3 {
  font-size: 16px;
  font-weight: 600;
}
.modal-body {
  padding: 4px 22px 8px;
  overflow-y: auto;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.modal-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 22px 18px;
  flex: none;
  border-top: 1px solid var(--line-soft);
  margin-top: 10px;
}
.modal-foot .left {
  margin-right: auto;
  display: flex;
  gap: 8px;
}

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

/* 抽屉（右侧滑出） */
.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 85;
  width: min(430px, 100%);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  animation: slide-in 0.26s var(--ease) forwards;
}
@keyframes slide-in {
  to { transform: translateX(0); }
}

/* ==========================================================================
   Toast
   ========================================================================== */
.toast-host {
  position: fixed;
  left: 50%;
  bottom: 30px;
  z-index: 200;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  font-size: 13px;
  color: #fff;
  background: rgba(32, 30, 28, 0.93);
  border-radius: var(--r-pill);
  box-shadow: var(--shadow-md);
  animation: toast-in 0.24s var(--ease);
}
.toast .ico { font-size: 13px; }
.toast-error { background: #a8403a; }
.toast-ok { background: #2f6b4a; }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(10px); }
}

/* ==========================================================================
   加载与骨架
   ========================================================================== */
.spinner {
  width: 15px;
  height: 15px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
.spinner-dark {
  border-color: rgba(0, 0, 0, 0.12);
  border-top-color: var(--text-2);
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

.skeleton {
  background: linear-gradient(90deg, #f0f1f3 25%, #e5e7eb 37%, #f0f1f3 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease infinite;
  border-radius: var(--r-sm);
}
@keyframes shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* 页面切换动画 */
.view-enter {
  animation: view-in 0.28s var(--ease);
}
@keyframes view-in {
  from { opacity: 0; transform: translateY(6px); }
}
