/* =====================================================================
   Demo测试医院 · 诊后随访系统 — 交互与转场动效层 fx.css
   ---------------------------------------------------------------------
   职责：只放“动”的部分——按钮角标/扫光/涟漪/加载、导航下划线与竖线、
        卡片与 KPI 抬升、表格行 stagger、标签页下划线、表单抖动与
        开关弹性、抽屉/弹层/toast/popover 过渡、视图方向性转场、
        路由进度条扫过、页面转场幕配合、页面入场 reveal。
        静态尺寸/颜色/状态见 components.css 与 base.css。
   规范：160–420ms，ease = cubic-bezier(.22,.8,.28,1)，
        out = cubic-bezier(.16,1,.3,1)；所有动效均尊重
        prefers-reduced-motion（文件末尾统一降级）。
   ===================================================================== */

/* =====================================================================
   0. 页面转场幕配合 / 页面入场
   ===================================================================== */
html.page-ready body {
  opacity: 0;
}

html.page-in body {
  opacity: 1;
  transition: opacity 0.42s ease 0.14s;
}

html.page-leaving body {
  opacity: 1;
}

/* 视图内容进入时标题区轻微上浮（在 .view-enter-* 内） */
@keyframes fx-head-rise {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.view-enter-forward .view-head,
.view-enter-back .view-head {
  animation: fx-head-rise 0.3s var(--fx-out) 0.05s both;
}

/* =====================================================================
   1. 视图方向性转场（router 生成 .view-page.view-enter-forward 等）
   —— 只用 opacity / transform；离开页绝对定位覆盖，避免布局跳动
   ===================================================================== */
.view-page.view-enter-forward,
.view-page.view-enter-back {
  animation-duration: 0.26s;
  animation-timing-function: var(--fx-out);
  animation-fill-mode: both;
  will-change: opacity, transform;
}

.view-page.view-enter-forward,
.view-page.view-enter {
  animation-name: fx-view-in-right;
}

.view-page.view-enter-back {
  animation-name: fx-view-in-left;
}

.view-page.view-leave-forward,
.view-page.view-leave-back {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  z-index: 1;
  pointer-events: none;
  animation-duration: 0.18s;
  animation-timing-function: var(--fx-ease);
  animation-fill-mode: both;
  will-change: opacity, transform;
}

.view-page.view-leave-forward,
.view-page.view-leave {
  animation-name: fx-view-out-left;
}

.view-page.view-leave-back {
  animation-name: fx-view-out-right;
}

@keyframes fx-view-in-right {
  from {
    opacity: 0;
    transform: translateX(18px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes fx-view-in-left {
  from {
    opacity: 0;
    transform: translateX(-18px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes fx-view-out-left {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateX(-14px);
  }
}

@keyframes fx-view-out-right {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateX(14px);
  }
}

/* =====================================================================
   2. 列表 / 内容入场：.reveal-in（≤8 项 stagger）与 [data-reveal]
   ===================================================================== */
.reveal-in {
  animation: fx-reveal-in 0.34s var(--fx-out) both;
  animation-delay: var(--d, 0ms);
}

.reveal-in:nth-child(2) {
  animation-delay: var(--d, 36ms);
}
.reveal-in:nth-child(3) {
  animation-delay: var(--d, 72ms);
}
.reveal-in:nth-child(4) {
  animation-delay: var(--d, 108ms);
}
.reveal-in:nth-child(5) {
  animation-delay: var(--d, 144ms);
}
.reveal-in:nth-child(6) {
  animation-delay: var(--d, 180ms);
}
.reveal-in:nth-child(7) {
  animation-delay: var(--d, 216ms);
}
.reveal-in:nth-child(8) {
  animation-delay: var(--d, 252ms);
}

@keyframes fx-reveal-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* 旧接口：fx.reveal() 给 [data-reveal] 加 .in */
[data-reveal] {
  opacity: 0;
  transform: translateY(8px);
}

[data-reveal].in {
  opacity: 1;
  transform: none;
  transition: opacity 0.38s var(--fx-ease) var(--d, 0ms),
    transform 0.46s var(--fx-out) var(--d, 0ms);
}

[data-reveal='scale'] {
  transform: scale(0.985);
}

/* =====================================================================
   3. 按钮：四角角标展开 + 扫光 + 上浮/回弹 + focus 环 + loading 分段
   ===================================================================== */
.btn:not(.btn-icon) {
  --btn-tick: var(--accent);
  --btn-g: linear-gradient(var(--btn-tick), var(--btn-tick));
  background-image: var(--btn-g), var(--btn-g), var(--btn-g), var(--btn-g), var(--btn-g),
    var(--btn-g), var(--btn-g), var(--btn-g);
  background-repeat: no-repeat;
  background-size: 0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0;
  background-position: left top, left top, right top, right top, left bottom, left bottom,
    right bottom, right bottom;
  transition: color var(--t) var(--fx-ease), background-color var(--t) var(--fx-ease),
    border-color var(--t) var(--fx-ease), box-shadow var(--t) var(--fx-ease),
    transform 0.24s var(--fx-out), background-size 0.3s var(--fx-out);
}

/* 扫光 */
.btn:not(.btn-icon)::before {
  content: '';
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  left: -70%;
  width: 46%;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.42), transparent);
  transform: skewX(-18deg);
  transition: left 0.55s var(--fx-ease);
}

.btn:not(.btn-icon):hover:not(:disabled) {
  transform: translateY(-1px);
  background-size: 9px 1.5px, 1.5px 9px, 9px 1.5px, 1.5px 9px, 9px 1.5px, 1.5px 9px, 9px 1.5px,
    1.5px 9px;
}

.btn:not(.btn-icon):hover:not(:disabled)::before {
  left: 122%;
}

.btn:not(.btn-icon):active:not(:disabled) {
  transform: translateY(0) scale(0.985);
  transition-duration: 0.08s;
}

.btn:not(.btn-icon):focus-visible {
  background-size: 9px 1.5px, 1.5px 9px, 9px 1.5px, 1.5px 9px, 9px 1.5px, 1.5px 9px, 9px 1.5px,
    1.5px 9px;
}

.btn-primary:not(.btn-icon) {
  --btn-tick: rgba(255, 248, 242, 0.85);
}

.btn-primary:not(.btn-icon)::before {
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.26), transparent);
}

.btn-danger:not(.btn-icon) {
  --btn-tick: var(--red);
}

.btn-ghost:not(.btn-icon) {
  --btn-tick: var(--accent);
}

.btn:not(.btn-icon):disabled {
  transform: none !important;
}

.btn .ico {
  transition: transform 0.25s var(--fx-out);
}

.btn:hover:not(:disabled) .ico {
  transform: translateX(1px);
}

/* 按钮 loading：隐藏文案与图标，叠三段分段动画 */
.btn-loading {
  color: transparent !important;
  --btn-seg: var(--accent);
}

.btn-primary.btn-loading {
  --btn-seg: var(--paper-2);
}

.btn-danger.btn-loading {
  --btn-seg: var(--red);
}

.btn-loading .ico,
.btn-loading::before {
  opacity: 0;
}

.btn-loading::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 48px;
  height: 4px;
  background-image: linear-gradient(90deg, var(--btn-seg) 0 10px, transparent 10px 16px);
  background-size: 16px 100%;
  background-repeat: repeat-x;
  transform: translate(-50%, -50%);
  animation: fx-btn-seg 0.7s linear infinite;
}

@keyframes fx-btn-seg {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 16px 0;
  }
}

/* =====================================================================
   4. 涟漪（fx.ripples 注入 <span class="ripple">）
   ===================================================================== */
.btn,
.icon-btn,
.side-item,
.tab,
.menu-item,
.chip-btn,
.pager-btn,
.dt-row,
.card-link,
.pressable,
.notif-item {
  position: relative;
  overflow: hidden;
}

.ripple {
  position: absolute;
  z-index: 0;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.16;
  transform: scale(0);
  animation: fx-ripple 0.6s var(--fx-out) forwards;
  pointer-events: none;
}

@keyframes fx-ripple {
  to {
    opacity: 0;
    transform: scale(1);
  }
}

/* =====================================================================
   5. 导航：侧栏竖线 / 激活角标 / 图标位移；面包屑下划线
   ===================================================================== */
.side-item {
  --side-tick: var(--accent);
}

/* 左侧竖线：hover 自中线展开 */
.side-item::before {
  content: '';
  position: absolute;
  top: 20%;
  bottom: 20%;
  left: 0;
  z-index: 1;
  width: 2px;
  background: var(--side-tick);
  border-radius: 0 2px 2px 0;
  transform: scaleY(0);
  transform-origin: center;
  transition: transform 0.26s var(--fx-out);
  pointer-events: none;
}

.side-item:hover::before {
  transform: scaleY(1);
}

.side-item.active::before {
  transform: scaleY(1);
  top: 16%;
  bottom: 16%;
}

.side-item .side-ico {
  transition: opacity 0.2s var(--fx-ease), transform 0.28s var(--fx-out), color 0.2s;
}

.side-item:hover .side-ico {
  transform: translateX(1px);
}

.side-item.active .side-ico {
  transform: none;
}

.side-item .side-index {
  transition: opacity 0.2s var(--fx-ease), color 0.2s var(--fx-ease);
}

.side-item:hover .side-index {
  opacity: 0.75;
}

/* 激活项的角标：右上细十字 */
.side-item.active::after {
  content: '';
  position: absolute;
  top: 7px;
  right: 8px;
  width: 6px;
  height: 6px;
  border-top: 1.5px solid var(--accent);
  border-right: 1.5px solid var(--accent);
  opacity: 0.7;
  pointer-events: none;
}

/* 面包屑 hover 下划线自左展开 */
.crumb-item {
  position: relative;
}

.crumb-item::after {
  content: '';
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.26s var(--fx-out);
  pointer-events: none;
}

a.crumb-item:hover::after {
  transform: scaleX(1);
}

.crumb-item.current::after {
  display: none;
}

/* 顶栏搜索 focus：占位扩展 + 图标着色 */
.topbar-search {
  transition: flex-basis 0.3s var(--fx-out);
}

.topbar-search:focus-within {
  flex-basis: 340px;
}

.topbar-search:focus-within > .ico {
  color: var(--accent);
}

/* =====================================================================
   6. 图标按钮 / 通知 / 账号按钮
   ===================================================================== */
.icon-btn {
  transition: color var(--t-fast) var(--fx-ease), background-color var(--t-fast) var(--fx-ease),
    border-color var(--t-fast) var(--fx-ease), transform 0.2s var(--fx-out);
}

.icon-btn:hover:not(:disabled) {
  transform: translateY(-1px);
}

.icon-btn:active:not(:disabled) {
  transform: translateY(0) scale(0.94);
}

.notif-btn.loading::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  border: 1.5px solid var(--accent-soft);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: fx-spin 0.8s linear infinite;
}

/* 未读点：呼吸（仅状态反馈，小圆点） */
.notif-dot.show {
  animation: fx-dot-breathe 2.2s var(--fx-ease) infinite;
}

@keyframes fx-dot-breathe {
  0%,
  100% {
    box-shadow: 0 0 0 2px var(--paper-2), 0 0 0 2px rgba(193, 82, 45, 0);
  }
  50% {
    box-shadow: 0 0 0 2px var(--paper-2), 0 0 0 5px rgba(193, 82, 45, 0.14);
  }
}

.account-btn {
  transition: color var(--t) var(--fx-ease), background-color var(--t) var(--fx-ease),
    border-color var(--t) var(--fx-ease), transform 0.2s var(--fx-out);
}

.account-btn:hover {
  transform: translateY(-1px);
}

.account-btn:active {
  transform: scale(0.985);
}

/* =====================================================================
   7. 浮层菜单 / popover
   ===================================================================== */
.popover {
  transition: opacity 0.15s var(--fx-ease);
  transform-origin: top right;
}

.popover.open {
  animation: fx-pop-in 0.18s var(--fx-out) both;
}

@keyframes fx-pop-in {
  from {
    opacity: 0;
    transform: translateY(-4px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.menu-item {
  transition: background-color var(--t-fast) var(--fx-ease), color var(--t-fast) var(--fx-ease),
    transform 0.16s var(--fx-out);
}

.menu-item:active:not(:disabled) {
  transform: scale(0.99);
}

/* =====================================================================
   8. 卡片 / KPI：hover 抬升 2px + 顶边描线；KPI 趋势条从左展开
   ===================================================================== */
.card {
  transition: transform 0.24s var(--fx-out), box-shadow 0.28s var(--fx-ease),
    border-color 0.22s var(--fx-ease);
}

.card::before {
  content: '';
  position: absolute;
  top: -1px;
  right: 0;
  left: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent), rgba(193, 82, 45, 0));
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.34s var(--fx-out);
  pointer-events: none;
}

.card:hover {
  transform: translateY(-2px);
  border-color: var(--line-2);
  box-shadow: var(--shadow);
}

.card:hover::before {
  transform: scaleX(1);
}

.kpi {
  transition: transform 0.24s var(--fx-out), box-shadow 0.28s var(--fx-ease),
    border-color 0.22s var(--fx-ease);
}

.kpi:hover {
  transform: translateY(-2px);
  border-color: var(--line-2);
  box-shadow: var(--shadow);
}

.kpi-bar i {
  animation: fx-kpi-grow 0.7s var(--fx-out) both;
}

@keyframes fx-kpi-grow {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

/* =====================================================================
   9. 表格 / 列表行：stagger 入场 + 行操作 hover 显现
   ===================================================================== */
.dt-table.in tbody tr,
table.dt-table.in tbody tr,
.dt.in .dt-row {
  animation: fx-row-in 0.32s var(--fx-out) both;
}

.dt-table.in tbody tr:nth-child(2),
.dt.in .dt-row:nth-child(2) {
  animation-delay: 30ms;
}
.dt-table.in tbody tr:nth-child(3),
.dt.in .dt-row:nth-child(3) {
  animation-delay: 60ms;
}
.dt-table.in tbody tr:nth-child(4),
.dt.in .dt-row:nth-child(4) {
  animation-delay: 90ms;
}
.dt-table.in tbody tr:nth-child(5),
.dt.in .dt-row:nth-child(5) {
  animation-delay: 120ms;
}
.dt-table.in tbody tr:nth-child(6),
.dt.in .dt-row:nth-child(6) {
  animation-delay: 150ms;
}
.dt-table.in tbody tr:nth-child(7),
.dt.in .dt-row:nth-child(7) {
  animation-delay: 180ms;
}
.dt-table.in tbody tr:nth-child(8),
.dt.in .dt-row:nth-child(8) {
  animation-delay: 210ms;
}

@keyframes fx-row-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.row-actions {
  opacity: 0;
  transform: translateX(4px);
  transition: opacity 0.22s var(--fx-ease), transform 0.24s var(--fx-out);
}

tr:hover .row-actions,
.dt-row:hover .row-actions,
.row-actions:focus-within {
  opacity: 1;
  transform: none;
}

/* =====================================================================
   10. 标签页：下划线自中间展开 + 内容淡入
   ===================================================================== */
.tab::after {
  transition: left 0.3s var(--fx-out), right 0.3s var(--fx-out),
    background-color 0.2s var(--fx-ease);
}

.tab:hover::after {
  right: 42%;
  left: 42%;
}

.tab.active:hover::after {
  right: 14%;
  left: 14%;
}

.tab-pane.active {
  animation: fx-pane-in 0.24s var(--fx-out) both;
}

@keyframes fx-pane-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* =====================================================================
   11. 表单：开关弹性 / 复选弹入 / 校验错误抖动
   ===================================================================== */
.switch > span,
.switch .switch-track {
  transition: background-color var(--t) var(--fx-ease), border-color var(--t) var(--fx-ease);
}

.switch > span::after,
.switch .switch-track::after {
  transition: transform 0.3s var(--fx-spring);
}

.switch input:checked + span::after,
.switch input:checked + .switch-track::after {
  transform: translateX(16px);
}

.switch:active > span::after,
.switch:active .switch-track::after {
  transform: scale(0.92);
}

.switch:active input:checked + span::after,
.switch:active input:checked + .switch-track::after {
  transform: translateX(16px) scale(0.92);
}

.check input:checked::after {
  animation: fx-check-in 0.2s var(--fx-spring) both;
}

@keyframes fx-check-in {
  from {
    opacity: 0;
    transform: rotate(45deg) scale(0.4);
  }
  to {
    opacity: 1;
    transform: rotate(45deg) scale(1);
  }
}

/* ui.setFieldError：.has-error + .shake + .field-error */
.shake {
  animation: fx-shake 0.28s var(--fx-ease) both;
}

.field-error {
  animation: fx-error-in 0.2s var(--fx-out) both;
}

@keyframes fx-shake {
  0%,
  100% {
    transform: translateX(0);
  }
  20% {
    transform: translateX(-4px);
  }
  40% {
    transform: translateX(4px);
  }
  60% {
    transform: translateX(-3px);
  }
  80% {
    transform: translateX(2px);
  }
}

@keyframes fx-error-in {
  from {
    opacity: 0;
    transform: translateY(-2px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* =====================================================================
   12. 遮罩 / 抽屉 / 弹层 / toast 过渡（可反向播放，非硬切换）
   ===================================================================== */
.scrim {
  transition: opacity 0.26s var(--fx-ease);
}

.drawer {
  transition: transform 0.28s var(--fx-ease), visibility 0s linear 0.28s;
}

.drawer.open {
  transition: transform 0.38s var(--fx-out), visibility 0s linear 0s;
}

.modal {
  transition: opacity 0.22s var(--fx-ease);
}

.modal-card {
  transition: transform 0.18s var(--fx-ease);
}

.modal.open .modal-card {
  transition: transform 0.28s var(--fx-out);
}

.toast {
  transition: opacity 0.26s var(--fx-ease), transform 0.34s var(--fx-out);
}

/* =====================================================================
   13. 通知列表 / 时间轴 / 徽标微反馈
   ===================================================================== */
.notif-item {
  transition: background-color var(--t-fast) var(--fx-ease),
    border-color var(--t-fast) var(--fx-ease), transform 0.2s var(--fx-out);
}

.notif-item:hover {
  transform: translateX(1px);
}

.notif-item:active {
  transform: scale(0.995);
}

.notif-unread-dot {
  animation: fx-dot-breathe 2.2s var(--fx-ease) infinite;
}

/* 时间轴：进入时节点淡入（克制） */
.timeline.in .tl-item {
  animation: fx-row-in 0.3s var(--fx-out) both;
}

.timeline.in .tl-item:nth-child(2) {
  animation-delay: 40ms;
}
.timeline.in .tl-item:nth-child(3) {
  animation-delay: 80ms;
}
.timeline.in .tl-item:nth-child(4) {
  animation-delay: 120ms;
}
.timeline.in .tl-item:nth-child(5) {
  animation-delay: 160ms;
}

/* =====================================================================
   14. 图表：柱状生长 / 迷你趋势条 / 环形图淡入（仅图表，数据可视化）
   ===================================================================== */
.chart-bars .chart-bar > i {
  transform-origin: bottom center;
  animation: fx-bar-grow 0.6s var(--fx-out) both;
}

.chart-bars .chart-bar:nth-child(2) > i {
  animation-delay: 50ms;
}
.chart-bars .chart-bar:nth-child(3) > i {
  animation-delay: 100ms;
}
.chart-bars .chart-bar:nth-child(4) > i {
  animation-delay: 150ms;
}
.chart-bars .chart-bar:nth-child(5) > i {
  animation-delay: 200ms;
}
.chart-bars .chart-bar:nth-child(6) > i {
  animation-delay: 250ms;
}
.chart-bars .chart-bar:nth-child(7) > i {
  animation-delay: 300ms;
}
.chart-bars .chart-bar:nth-child(8) > i {
  animation-delay: 350ms;
}

@keyframes fx-bar-grow {
  from {
    transform: scaleY(0);
    opacity: 0.4;
  }
  to {
    transform: scaleY(1);
    opacity: 0.9;
  }
}

.sparkline i {
  animation: fx-bar-grow 0.5s var(--fx-out) both;
}

.sparkline i:nth-child(2) {
  animation-delay: 20ms;
}
.sparkline i:nth-child(3) {
  animation-delay: 40ms;
}
.sparkline i:nth-child(4) {
  animation-delay: 60ms;
}
.sparkline i:nth-child(5) {
  animation-delay: 80ms;
}
.sparkline i:nth-child(6) {
  animation-delay: 100ms;
}
.sparkline i:nth-child(7) {
  animation-delay: 120ms;
}
.sparkline i:nth-child(8) {
  animation-delay: 140ms;
}

.chart-donut {
  animation: fx-donut-in 0.8s var(--fx-out) both;
}

@keyframes fx-donut-in {
  from {
    opacity: 0;
    transform: rotate(-16deg) scale(0.94);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.chart-donut-center {
  animation: fx-fade-in 0.5s var(--fx-ease) 0.2s both;
}

@keyframes fx-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* =====================================================================
   15. 路由进度条扫过（结构在 base.css，router 驱动 --progress）
   ===================================================================== */
.route-progress.on::before {
  background-image: linear-gradient(
    90deg,
    var(--accent-2),
    var(--accent) 55%,
    #e2a482,
    var(--accent) 78%,
    var(--accent-2)
  );
  background-size: 220% 100%;
  animation: fx-route-sheen 0.9s linear infinite;
}

@keyframes fx-route-sheen {
  from {
    background-position: 0 0;
  }
  to {
    background-position: -220% 0;
  }
}

/* =====================================================================
   16. 按下反馈工具类（router/ui 可添加）
   ===================================================================== */
.press {
  animation: fx-press 0.2s var(--fx-ease) both;
}

@keyframes fx-press {
  0% {
    transform: scale(1);
  }
  40% {
    transform: scale(0.985);
  }
  100% {
    transform: scale(1);
  }
}

/* 通用旋转（loading 指示） */
@keyframes fx-spin {
  to {
    transform: rotate(360deg);
  }
}

/* =====================================================================
   17. 无障碍：prefers-reduced-motion 全量降级（关闭动效时功能完整）
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  html.page-ready body {
    opacity: 1;
  }

  .page-veil,
  .route-progress {
    display: none !important;
  }

  [data-reveal],
  [data-reveal='scale'] {
    opacity: 1;
    transform: none;
  }

  .reveal-in {
    opacity: 1;
  }

  .view-page.view-leave-forward,
  .view-page.view-leave-back {
    display: none;
  }

  .topbar-search:focus-within {
    flex-basis: auto;
  }

  .btn-loading::after {
    animation: fx-btn-seg 1.4s steps(3) infinite;
  }
}

/* =====================================================================
   8. SPA 路由转场增强：几何航线 + 内容分层入场
   —— 页面切换时在视口上叠加一次快速几何航线，配合 router 触发
   ===================================================================== */
.route-veil {
  position: fixed;
  inset: 0;
  z-index: 820;
  pointer-events: none;
  opacity: 0;
  overflow: hidden;
}
.route-veil.on {
  opacity: 1;
}

.route-veil .rv-line {
  position: absolute;
  right: 0;
  left: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent 2%, rgba(193, 82, 45, 0.55) 20%, rgba(193, 82, 45, 0.55) 80%, transparent 98%);
  transform: scaleX(0);
  transform-origin: center;
}
.route-veil .rv-line-a {
  top: 31%;
}
.route-veil .rv-line-b {
  top: 69%;
  height: 1px;
  background: linear-gradient(90deg, transparent 8%, rgba(35, 30, 25, 0.28) 30%, rgba(35, 30, 25, 0.28) 70%, transparent 92%);
}
.route-veil.on .rv-line-a {
  animation: rv-line 0.56s var(--fx-out) both;
}
.route-veil.on .rv-line-b {
  animation: rv-line 0.56s var(--fx-out) 0.05s both;
}
@keyframes rv-line {
  0% { transform: scaleX(0); opacity: 0; }
  30% { transform: scaleX(1); opacity: 0.9; }
  100% { transform: scaleX(1); opacity: 0; }
}

.route-veil .rv-code {
  position: absolute;
  top: calc(31% - 22px);
  left: 50%;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.3em;
  white-space: nowrap;
  color: rgba(193, 82, 45, 0.8);
  opacity: 0;
  transform: translateX(-50%);
}
.route-veil.on .rv-code {
  animation: rv-code 0.6s var(--fx-ease) 0.02s both;
}
@keyframes rv-code {
  0% { opacity: 0; letter-spacing: 0.16em; }
  32% { opacity: 1; letter-spacing: 0.3em; }
  100% { opacity: 0; letter-spacing: 0.36em; }
}

.route-veil .rv-bar {
  position: absolute;
  top: 50%;
  left: 50%;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 3px;
  width: 150px;
  height: 2px;
  transform: translate(-50%, -50%);
  opacity: 0;
}
.route-veil.on .rv-bar {
  opacity: 1;
}
.route-veil .rv-bar i {
  background: rgba(193, 82, 45, 0.18);
}
.route-veil.on .rv-bar i {
  animation: rv-seg 0.55s var(--fx-ease) infinite;
}
.route-veil.on .rv-bar i:nth-child(2) { animation-delay: 0.04s; }
.route-veil.on .rv-bar i:nth-child(3) { animation-delay: 0.08s; }
.route-veil.on .rv-bar i:nth-child(4) { animation-delay: 0.12s; }
.route-veil.on .rv-bar i:nth-child(5) { animation-delay: 0.16s; }
.route-veil.on .rv-bar i:nth-child(6) { animation-delay: 0.2s; }
.route-veil.on .rv-bar i:nth-child(7) { animation-delay: 0.24s; }
.route-veil.on .rv-bar i:nth-child(8) { animation-delay: 0.28s; }
.route-veil.on .rv-bar i:nth-child(9) { animation-delay: 0.32s; }
.route-veil.on .rv-bar i:nth-child(10) { animation-delay: 0.36s; }
.route-veil.on .rv-bar i:nth-child(11) { animation-delay: 0.4s; }
.route-veil.on .rv-bar i:nth-child(12) { animation-delay: 0.44s; }
@keyframes rv-seg {
  0%, 100% { background: rgba(193, 82, 45, 0.15); }
  45% { background: rgba(193, 82, 45, 0.85); }
}

.route-veil::before,
.route-veil::after {
  content: '';
  position: absolute;
  width: 20px;
  height: 20px;
  border: 1.5px solid rgba(193, 82, 45, 0.5);
  opacity: 0;
}
.route-veil::before {
  top: 22px;
  left: 22px;
  border-right: 0;
  border-bottom: 0;
}
.route-veil::after {
  right: 22px;
  bottom: 22px;
  border-top: 0;
  border-left: 0;
}
.route-veil.on::before,
.route-veil.on::after {
  animation: rv-corner 0.55s var(--fx-ease) both;
}
@keyframes rv-corner {
  0% { opacity: 0; transform: scale(1.3); }
  40% { opacity: 0.85; transform: scale(1); }
  100% { opacity: 0; transform: scale(0.92); }
}

/* 视图内容分层入场：只对首层 ≤6 个区块做轻微位移，避免喧宾夺主 */
.view-page.view-enter-forward .view > :nth-child(-n + 6),
.view-page.view-enter-back .view > :nth-child(-n + 6) {
  animation: fx-content-rise 0.36s var(--fx-out) both;
}
.view-page.view-enter-forward .view > :nth-child(1), .view-page.view-enter-back .view > :nth-child(1) { animation-delay: 0.01s; }
.view-page.view-enter-forward .view > :nth-child(2), .view-page.view-enter-back .view > :nth-child(2) { animation-delay: 0.04s; }
.view-page.view-enter-forward .view > :nth-child(3), .view-page.view-enter-back .view > :nth-child(3) { animation-delay: 0.07s; }
.view-page.view-enter-forward .view > :nth-child(4), .view-page.view-enter-back .view > :nth-child(4) { animation-delay: 0.1s; }
.view-page.view-enter-forward .view > :nth-child(5), .view-page.view-enter-back .view > :nth-child(5) { animation-delay: 0.13s; }
.view-page.view-enter-forward .view > :nth-child(6), .view-page.view-enter-back .view > :nth-child(6) { animation-delay: 0.16s; }
@keyframes fx-content-rise {
  from { opacity: 0; transform: translateY(9px); }
  to { opacity: 1; transform: none; }
}

/* 路由进度条：加头部光点与分段刻度 */
.route-progress::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 60px;
  background: linear-gradient(90deg, transparent, rgba(255, 248, 242, 0.9));
  opacity: 0.9;
  pointer-events: none;
}
.route-progress.on::after {
  animation: fx-progress-glow 0.9s var(--fx-ease) infinite;
}
@keyframes fx-progress-glow {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 0.95; }
}

/* =====================================================================
   9. 交互补全：所有可点击 / 可聚焦元素的状态过渡
   ===================================================================== */

/* 通用可点击元素：按下回弹 */
.pager-btn,
.chip-btn,
.menu-item,
.notif-item,
.filter,
.crumb-item,
.tab,
.account-btn,
.icon-btn,
.side-item {
  -webkit-tap-highlight-color: transparent;
}
.pager-btn:active,
.chip-btn:active,
.menu-item:active,
.notif-item:active,
.filter:active,
.tab:active,
.account-btn:active,
.icon-btn:active,
.side-item:active {
  transform: scale(0.975);
}
.pager-btn,
.chip-btn,
.filter {
  transition: transform 0.16s var(--fx-out), color 0.2s var(--fx-ease), background-color 0.2s var(--fx-ease),
    border-color 0.2s var(--fx-ease), box-shadow 0.24s var(--fx-ease);
}
.pager-btn:hover:not(:disabled),
.chip-btn:hover:not(:disabled),
.filter:hover:not(.active) {
  transform: translateY(-1px);
}

/* 图标按钮 / 关闭按钮：悬停旋转 */
.icon-btn {
  transition: color 0.2s var(--fx-ease), background-color 0.2s var(--fx-ease), transform 0.22s var(--fx-out),
    border-color 0.2s var(--fx-ease);
}
.icon-btn:hover:not(:disabled) {
  transform: translateY(-1px);
}
.icon-btn:active:not(:disabled) {
  transform: scale(0.92);
}
.drawer-close,
.modal-close {
  transition: transform 0.28s var(--fx-out), color 0.2s, background-color 0.2s;
}
.drawer-close:hover,
.modal-close:hover {
  transform: rotate(90deg);
}
.drawer-close:active,
.modal-close:active {
  transform: rotate(90deg) scale(0.9);
}

/* 顶栏账号：展开时箭头旋转 */
.account-btn .account-caret {
  transition: transform 0.3s var(--fx-out), color 0.2s;
}
.account-btn.is-open .account-caret,
.account-btn:hover .account-caret {
  color: var(--accent-2);
}
.account-btn.is-open .account-caret {
  transform: rotate(180deg);
}

/* 品牌标记：hover 轻微旋转 */
.brand .brand-mark {
  transition: transform 0.35s var(--fx-spring), box-shadow 0.3s var(--fx-ease);
}
.brand:hover .brand-mark {
  transform: rotate(-5deg) scale(1.03);
}

/* 通知铃铛：hover 摇摆 */
.notif-btn:hover .ico {
  animation: fx-bell 0.6s var(--fx-ease);
}
@keyframes fx-bell {
  0%, 100% { transform: rotate(0); }
  20% { transform: rotate(-9deg); }
  45% { transform: rotate(7deg); }
  70% { transform: rotate(-4deg); }
}

/* 菜单项：悬停右移 + 图标着色 */
.menu-item {
  transition: background-color 0.18s var(--fx-ease), color 0.18s var(--fx-ease), transform 0.2s var(--fx-out);
}
.menu-item:hover:not(:disabled) {
  transform: translateX(2px);
}
.menu-item:hover .menu-ico {
  color: var(--accent-2);
}

/* 通知条目：悬停右移 + 未读点抬升 */
.notif-item {
  transition: background-color 0.2s var(--fx-ease), border-color 0.2s var(--fx-ease), transform 0.22s var(--fx-out);
}
.notif-item:hover {
  transform: translateX(2px);
}

/* 面包屑 */
.crumb-item {
  transition: color 0.2s var(--fx-ease);
}

/* 表格行：悬停强调线 + 操作按钮浮现（已定义类补充过渡） */
.dt-row,
.dt-table tbody tr {
  transition: background-color 0.2s var(--fx-ease), box-shadow 0.24s var(--fx-ease), transform 0.22s var(--fx-out);
}
.dt-row:active,
.dt-table tbody tr:active {
  transform: scale(0.998);
}

/* 表单：聚焦过渡与校验抖动（已有 .field-error 的基础上补细节） */
.input,
.select,
.textarea,
.field-select {
  transition: border-color 0.2s var(--fx-ease), box-shadow 0.24s var(--fx-ease), background-color 0.2s var(--fx-ease);
}
.field:focus-within .field-label {
  color: var(--accent-2);
}
.field-label {
  transition: color 0.2s var(--fx-ease);
}
.select:hover,
.field-select:hover {
  border-color: var(--line-2);
}
.check span,
.switch .switch-track,
.switch span {
  transition: background-color 0.24s var(--fx-ease), border-color 0.24s var(--fx-ease), box-shadow 0.24s var(--fx-ease);
}

/* 分页按钮 */
.pager-btn {
  position: relative;
  overflow: hidden;
  transition: color 0.2s, background-color 0.2s, border-color 0.2s, transform 0.16s var(--fx-out), box-shadow 0.24s;
}

/* 状态 chip / 标签：可点的才动，静态标签只做颜色渐入 */
.tag,
.status,
.risk {
  transition: color 0.2s, background-color 0.2s, border-color 0.2s;
}

/* Toast：底部倒计时细条 + 进入位移 */
.toast {
  position: fixed;
  overflow: hidden;
}
.toast::after {
  content: '';
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 2px;
  background: currentColor;
  opacity: 0.28;
  transform-origin: left center;
  transform: scaleX(0);
}
.toast.show::after {
  animation: fx-toast-life 3.2s linear forwards;
}
@keyframes fx-toast-life {
  from { transform: scaleX(1); }
  to { transform: scaleX(0); }
}

/* 弹层 / 抽屉内容：打开时逐项上浮 */
.modal.open .modal-body > :nth-child(-n + 6),
.drawer.open .drawer-body > :nth-child(-n + 6) {
  animation: fx-content-rise 0.32s var(--fx-out) both;
}
.modal.open .modal-body > :nth-child(2),
.drawer.open .drawer-body > :nth-child(2) { animation-delay: 0.03s; }
.modal.open .modal-body > :nth-child(3),
.drawer.open .drawer-body > :nth-child(3) { animation-delay: 0.06s; }
.modal.open .modal-body > :nth-child(4),
.drawer.open .drawer-body > :nth-child(4) { animation-delay: 0.09s; }
.modal.open .modal-body > :nth-child(5),
.drawer.open .drawer-body > :nth-child(5) { animation-delay: 0.12s; }
.modal.open .modal-body > :nth-child(6),
.drawer.open .drawer-body > :nth-child(6) { animation-delay: 0.15s; }

/* 常用按钮组内的次按钮：hover 时轻微描边强化 */
.btn-ghost:hover:not(:disabled) {
  border-color: var(--line-2);
  background-color: rgba(251, 248, 241, 0.9);
}

/* 链接类 */
a {
  transition: color 0.2s var(--fx-ease);
}

@media (prefers-reduced-motion: reduce) {
  .route-veil {
    display: none !important;
  }
  .view-page.view-enter-forward .view > *,
  .view-page.view-enter-back .view > *,
  .modal.open .modal-body > *,
  .drawer.open .drawer-body > * {
    animation: none !important;
  }
  .toast.show::after {
    animation: none !important;
  }
}

/* =====================================================================
   11. 交互兜底：任何按钮 / 可交互链接 / 可聚焦元素都有过渡与按压反馈
   ===================================================================== */
button,
a,
[role='button'],
[tabindex]:not([tabindex='-1']) {
  transition: color 0.2s var(--fx-ease), background-color 0.2s var(--fx-ease), border-color 0.2s var(--fx-ease),
    box-shadow 0.24s var(--fx-ease), transform 0.18s var(--fx-out), opacity 0.2s var(--fx-ease);
}

button:not(:disabled):active,
a.btn:active,
a.icon-btn:active,
a.brand:active,
a.side-item:active,
a.crumb-item:active,
[role='button']:active {
  transform: scale(0.98);
}

button:disabled,
a[aria-disabled='true'] {
  cursor: not-allowed;
  opacity: 0.55;
}

:focus-visible {
  outline: none;
}

button:focus-visible,
a:focus-visible,
[role='button']:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--paper-2), 0 0 0 4px rgba(193, 82, 45, 0.42);
}

/* 表格内文字链接 */
.dt-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.2s, border-color 0.2s;
}
.dt-link:hover {
  color: var(--accent-2);
  border-bottom-color: rgba(193, 82, 45, 0.45);
}
.dt-link:active {
  opacity: 0.75;
}

/* 紧凑列表项（工作台/详情） */
.dr-compact-item,
.dr-alert-item,
.dr-row-remove {
  transition: background-color 0.2s var(--fx-ease), border-color 0.2s var(--fx-ease), transform 0.2s var(--fx-out),
    box-shadow 0.24s var(--fx-ease), opacity 0.2s;
}
.dr-compact-item:hover {
  transform: translateX(2px);
}
.dr-compact-item:active,
.dr-alert-item:active {
  transform: scale(0.995);
}

/* 移动端导航抽屉按钮 / 遮罩 */
.dr-nav-toggle {
  transition: color 0.2s, background-color 0.2s, border-color 0.2s, transform 0.2s var(--fx-out);
}
.dr-nav-toggle:hover {
  color: var(--accent-2);
}
.dr-nav-toggle:active {
  transform: scale(0.94);
}

/* 平滑滚动（尊重 reduced-motion） */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* 滚动条：细墨线，悬停加深（WebKit / Firefox） */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
}
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--line-2);
  border: 2px solid transparent;
  border-radius: 8px;
  background-clip: content-box;
  transition: background-color 0.2s;
}
::-webkit-scrollbar-thumb:hover {
  background-color: var(--ink-4);
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  button,
  a,
  [role='button'],
  [tabindex]:not([tabindex='-1']) {
    transition-duration: 0.01ms !important;
  }
}

/* =====================================================================
   12. 转场动画增强（覆盖：整页落定 / 视图裁切进入 / 路由航线）
   ===================================================================== */
/* 整页落定：幕布收起后，外壳轻微上浮淡入 */
@keyframes page-settle {
  from { opacity: 0.55; transform: translateY(9px); }
  to { opacity: 1; transform: none; }
}
html.page-in .shell,
html.page-in .login-shell {
  animation: page-settle 0.55s var(--fx-out) 0.04s both;
}

/* 视图进入：位移 + 遮挡裁切，层次更明确 */
@keyframes fx-view-in-right-2 {
  0% { opacity: 0; transform: translateX(26px); clip-path: inset(0 0 0 10%); }
  60% { opacity: 1; }
  100% { opacity: 1; transform: none; clip-path: inset(0 0 0 0); }
}
@keyframes fx-view-in-left-2 {
  0% { opacity: 0; transform: translateX(-26px); clip-path: inset(0 10% 0 0); }
  60% { opacity: 1; }
  100% { opacity: 1; transform: none; clip-path: inset(0 0 0 0); }
}
.view-page.view-enter-forward {
  animation: fx-view-in-right-2 0.34s var(--fx-out) both;
}
.view-page.view-enter-back {
  animation: fx-view-in-left-2 0.34s var(--fx-out) both;
}

/* 路由航线：竖向细线 + 中心菱形 */
.route-veil .rv-vline {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: linear-gradient(180deg, transparent 6%, rgba(193, 82, 45, 0.4) 30%, rgba(193, 82, 45, 0.4) 70%, transparent 94%);
  transform: scaleY(0);
  transform-origin: center;
}
.route-veil .rv-vline-a {
  left: 22%;
}
.route-veil .rv-vline-b {
  right: 22%;
}
.route-veil.on .rv-vline-a {
  animation: rv-vline 0.56s var(--fx-out) 0.02s both;
}
.route-veil.on .rv-vline-b {
  animation: rv-vline 0.56s var(--fx-out) 0.06s both;
}
@keyframes rv-vline {
  0% { transform: scaleY(0); opacity: 0; }
  32% { transform: scaleY(1); opacity: 0.75; }
  100% { transform: scaleY(1); opacity: 0; }
}
.route-veil .rv-diamond {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border: 1px solid rgba(193, 82, 45, 0.6);
  transform: rotate(45deg) scale(0.4);
  opacity: 0;
}
.route-veil.on .rv-diamond {
  animation: rv-diamond 0.6s var(--fx-ease) 0.02s both;
}
@keyframes rv-diamond {
  0% { transform: rotate(45deg) scale(0.3); opacity: 0; }
  38% { transform: rotate(45deg) scale(1); opacity: 0.9; }
  100% { transform: rotate(45deg) scale(1.6); opacity: 0; }
}

/* 悬停时表格行/卡片内部小图标轻微位移，强化“可点”感知 */
.dt-row:hover .row-actions .btn .ico,
.dt-table tbody tr:hover .row-actions .btn .ico {
  transform: translateX(1px);
}
.dt-row .row-actions .btn .ico,
.dt-table tbody tr .row-actions .btn .ico {
  transition: transform 0.22s var(--fx-out);
}

/* 页签内容淡入（全局兜底，避免个别页面切换生硬） */
.tab-pane.active {
  animation: fx-pane-in 0.28s var(--fx-out) both;
}
@keyframes fx-pane-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

/* 筛选项切换时列表轻微淡入（仅交互触发的重渲染，不做循环动画） */
.dt-table.in tbody tr {
  animation: fx-row-in 0.3s var(--fx-out) both;
}
@keyframes fx-row-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  html.page-in .shell,
  html.page-in .login-shell,
  .view-page.view-enter-forward,
  .view-page.view-enter-back,
  .tab-pane.active,
  .dt-table.in tbody tr {
    animation: none !important;
  }
  .route-veil .rv-vline,
  .route-veil .rv-diamond {
    display: none !important;
  }
}

/* 离开视图：更快淡出，减少与进入视图的重叠感 */
@keyframes fx-view-out-left-2 {
  0% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateX(-34px); }
}
@keyframes fx-view-out-right-2 {
  0% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateX(34px); }
}
.view-page.view-leave-forward {
  position: absolute;
  inset: 0;
  pointer-events: none;
  animation: fx-view-out-left-2 0.18s var(--fx-ease) both;
}
.view-page.view-leave-back {
  position: absolute;
  inset: 0;
  pointer-events: none;
  animation: fx-view-out-right-2 0.18s var(--fx-ease) both;
}

@media (prefers-reduced-motion: reduce) {
  .view-page.view-leave-forward,
  .view-page.view-leave-back {
    animation-duration: 0.01ms !important;
  }
}

/* =====================================================================
   13. 审计补全：侧栏品牌、面包屑、顶部品牌、身份页签、移动端视图切换
   ===================================================================== */
.side-brand {
  border-radius: 10px;
  transition: background-color 0.22s var(--fx-ease), color 0.22s var(--fx-ease), transform 0.18s var(--fx-out);
}
.side-brand:hover {
  background-color: rgba(243, 234, 217, 0.06);
}
.side-brand:hover .brand-title {
  color: #fff4e2;
}
.side-brand:hover .brand-mark {
  transform: rotate(-4deg) scale(1.03);
}
.side-brand:active {
  transform: scale(0.995);
}

.crumb-item {
  border-radius: 4px;
  transition: color 0.2s var(--fx-ease), background-color 0.2s var(--fx-ease), transform 0.18s var(--fx-out);
}
.crumb-item:not(.current):hover {
  color: var(--accent-2);
  background-color: var(--accent-tint);
}
.crumb-item:not(.current):active {
  transform: scale(0.98);
}

.brand {
  transition: opacity 0.22s var(--fx-ease), transform 0.2s var(--fx-out);
  border-radius: 8px;
}
.brand:hover {
  opacity: 0.92;
}
.brand:active {
  transform: scale(0.995);
}

.role-tab {
  transition: color 0.22s var(--fx-ease), background-color 0.22s var(--fx-ease), transform 0.18s var(--fx-out);
}
.role-tab:hover {
  background-color: rgba(251, 248, 241, 0.65);
}
.role-tab.active:hover {
  background-color: rgba(255, 255, 255, 0.75);
}
.role-tab:active {
  transform: scale(0.985);
}

.session-mobile-nav button {
  transition: color 0.22s var(--fx-ease), background-color 0.22s var(--fx-ease), transform 0.18s var(--fx-out);
}
.session-mobile-nav button:hover {
  color: var(--ink);
  background-color: rgba(251, 248, 241, 0.75);
}
.session-mobile-nav button:active {
  transform: scale(0.97);
}

/* 侧栏品牌标记衔接 */
.side-brand .brand-mark {
  transition: transform 0.32s var(--fx-spring), box-shadow 0.3s var(--fx-ease);
}

/* 审计补全：开关 / 复选标签（可点击 label） */
.switch,
.check {
  cursor: pointer;
  transition: color 0.2s var(--fx-ease), opacity 0.2s var(--fx-ease);
}
.switch:hover,
.check:hover {
  color: var(--ink);
}
.switch:active,
.check:active {
  opacity: 0.85;
}
.switch .switch-track,
.switch span,
.check span {
  transition: background-color 0.24s var(--fx-ease), border-color 0.24s var(--fx-ease),
    box-shadow 0.24s var(--fx-ease), transform 0.26s var(--fx-spring);
}
.switch:hover .switch-track,
.switch:hover span:not(:has(input)),
.check:hover span {
  border-color: var(--line-2);
}
.switch:active .switch-track,
.switch:active span {
  transform: scale(0.96);
}

/* 审计补全 2：激活态导航/页签 hover、滑块、原生 select */
.client-nav-item.active {
  transition: color 0.22s var(--fx-ease), background-color 0.22s var(--fx-ease), box-shadow 0.24s var(--fx-ease);
}
.client-nav-item.active:hover {
  background-color: rgba(251, 248, 241, 0.72);
  box-shadow: inset 0 -2px 0 rgba(193, 82, 45, 0.25);
}
.tab.active {
  transition: color 0.2s var(--fx-ease), background-color 0.2s var(--fx-ease);
}
.tab.active:hover {
  color: var(--accent-2);
  background-color: rgba(249, 238, 230, 0.55);
}
input[type="range"] {
  transition: filter 0.22s var(--fx-ease), opacity 0.22s;
  cursor: pointer;
}
input[type="range"]:hover {
  filter: brightness(1.06) saturate(1.05);
}
input[type="range"]:active {
  filter: brightness(0.98);
}
select,
select.select,
select.field-select,
select.session-voice-select {
  transition: border-color 0.2s var(--fx-ease), background-color 0.2s var(--fx-ease), color 0.2s, box-shadow 0.24s;
  cursor: pointer;
}
select:hover {
  border-color: var(--line-2);
}
select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
select:active {
  transform: scale(0.998);
}

/* 审计补全 3：激活态侧栏、原生 select 悬停、表格行按压 */
.side-item.active:hover {
  background: #33291f;
  border-color: rgba(243, 234, 217, 0.16);
  color: #fff6e8;
}
.side-item.active:hover .side-index {
  color: var(--accent-soft);
  opacity: 1;
}
.side-item.active:hover .side-ico {
  color: #ffe6d6;
}

select:hover,
select.select:hover,
select.field-select:hover,
select.session-voice-select:hover {
  border-color: var(--accent);
  background-color: var(--paper-2);
  box-shadow: 0 0 0 2px var(--accent-tint);
}
select.dr-filter-select:hover {
  border-color: var(--accent);
  background-color: var(--accent-tint);
}

.dt-table tbody tr[data-route],
.dt-table tbody tr[data-client-id],
.dt-table tbody tr[data-fu-id],
.dt-table tbody tr[data-report-id],
.dt-table tbody tr[data-alert-id] {
  transition: background-color 0.2s var(--fx-ease), transform 0.16s var(--fx-out), box-shadow 0.22s var(--fx-ease);
}
.dt-table tbody tr[data-route]:active,
.dt-table tbody tr[data-client-id]:active,
.dt-table tbody tr[data-fu-id]:active,
.dt-table tbody tr[data-report-id]:active,
.dt-table tbody tr[data-alert-id]:active {
  background-color: var(--accent-tint);
  transform: scale(0.998);
}

/* 审计补全 4：可点击卡片/通知条/隐私勾选的按压反馈 */
.record-card,
.notif-row {
  transition: transform 0.2s var(--fx-out), box-shadow 0.24s var(--fx-ease), border-color 0.2s var(--fx-ease),
    background-color 0.2s var(--fx-ease);
}
.record-card:active,
.notif-row:active {
  transform: scale(0.997);
}
.consent-check {
  transition: color 0.2s var(--fx-ease), opacity 0.18s;
}
.consent-check:active {
  opacity: 0.82;
}
.fu-card:active {
  transform: translateY(0) scale(0.998);
}

/* =====================================================================
   14. 页面切换与页内 Tab 切换的可感知动画（增强版）
   ===================================================================== */

/* 14.1 侧栏滑动指示条 */
.side-nav {
  position: relative;
}
.side-indicator {
  position: absolute;
  left: 7px;
  top: 0;
  width: 3px;
  border-radius: 3px;
  background: linear-gradient(180deg, rgba(193, 82, 45, 0.15), var(--accent) 30%, var(--accent) 70%, rgba(193, 82, 45, 0.15));
  box-shadow: 0 0 12px rgba(193, 82, 45, 0.55);
  opacity: 0;
  transform: translateY(0);
  transition: transform 0.36s cubic-bezier(0.16, 1, 0.3, 1), height 0.3s cubic-bezier(0.16, 1, 0.3, 1),
    opacity 0.24s ease;
  pointer-events: none;
  z-index: 3;
}
.side-item.active {
  transition: color 0.24s var(--fx-ease), background-color 0.24s var(--fx-ease), border-color 0.24s var(--fx-ease),
    box-shadow 0.3s var(--fx-ease);
}

/* 14.2 内容区航线擦除（router 在 #view 上添加） */
.view-stage {
  position: relative;
}
.view-stage.route-wipe-forward::after,
.view-stage.route-wipe-back::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  background:
    linear-gradient(103deg, transparent 0%, rgba(193, 82, 45, 0) 28%, rgba(193, 82, 45, 0.06) 43%, rgba(251, 248, 241, 0.9) 50%, rgba(193, 82, 45, 0.06) 57%, rgba(193, 82, 45, 0) 72%, transparent 100%),
    repeating-linear-gradient(90deg, rgba(193, 82, 45, 0.06) 0 1px, transparent 1px 86px);
  background-size: 240% 100%, auto;
  background-repeat: no-repeat, repeat;
  animation: fx-route-wipe-forward 0.55s var(--fx-ease) both;
}
.view-stage.route-wipe-back::after {
  animation-name: fx-route-wipe-back;
}
@keyframes fx-route-wipe-forward {
  0% { background-position: 125% 0, 0 0; opacity: 0.95; }
  100% { background-position: -45% 0, 0 0; opacity: 0; }
}
@keyframes fx-route-wipe-back {
  0% { background-position: -45% 0, 0 0; opacity: 0.95; }
  100% { background-position: 125% 0, 0 0; opacity: 0; }
}

/* 14.3 视图进入更强：位移 + 裁切 + 轻微缩放 */
@keyframes fx-view-in-right-3 {
  0% { opacity: 0; transform: translateX(38px) scale(0.994); clip-path: inset(0 0 0 16%); }
  55% { opacity: 1; }
  100% { opacity: 1; transform: none; clip-path: inset(0 0 0 0); }
}
@keyframes fx-view-in-left-3 {
  0% { opacity: 0; transform: translateX(-38px) scale(0.994); clip-path: inset(0 16% 0 0); }
  55% { opacity: 1; }
  100% { opacity: 1; transform: none; clip-path: inset(0 0 0 0); }
}
.view-page.view-enter-forward {
  animation: fx-view-in-right-3 0.4s var(--fx-out) both;
}
.view-page.view-enter-back {
  animation: fx-view-in-left-3 0.4s var(--fx-out) both;
}

/* 区块内容入场加强 */
@keyframes fx-content-rise {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: none; }
}
.view-page.view-enter-forward .view > :nth-child(-n + 6),
.view-page.view-enter-back .view > :nth-child(-n + 6) {
  animation: fx-content-rise 0.4s var(--fx-out) both;
}
.view-page.view-enter-forward .view > :nth-child(2),
.view-page.view-enter-back .view > :nth-child(2) { animation-delay: 0.05s; }
.view-page.view-enter-forward .view > :nth-child(3),
.view-page.view-enter-back .view > :nth-child(3) { animation-delay: 0.1s; }
.view-page.view-enter-forward .view > :nth-child(4),
.view-page.view-enter-back .view > :nth-child(4) { animation-delay: 0.15s; }
.view-page.view-enter-forward .view > :nth-child(5),
.view-page.view-enter-back .view > :nth-child(5) { animation-delay: 0.2s; }
.view-page.view-enter-forward .view > :nth-child(6),
.view-page.view-enter-back .view > :nth-child(6) { animation-delay: 0.25s; }

/* 14.4 页内 Tab / 筛选切换：表格行与面板内容逐项入场 */
.dt-table tbody tr {
  animation: fx-row-in 0.36s var(--fx-out) both;
}
.dt-table tbody tr:nth-child(1) { animation-delay: 0.01s; }
.dt-table tbody tr:nth-child(2) { animation-delay: 0.05s; }
.dt-table tbody tr:nth-child(3) { animation-delay: 0.09s; }
.dt-table tbody tr:nth-child(4) { animation-delay: 0.13s; }
.dt-table tbody tr:nth-child(5) { animation-delay: 0.17s; }
.dt-table tbody tr:nth-child(6) { animation-delay: 0.21s; }
.dt-table tbody tr:nth-child(7) { animation-delay: 0.25s; }
.dt-table tbody tr:nth-child(8) { animation-delay: 0.29s; }
.dt-table tbody tr:nth-child(9) { animation-delay: 0.33s; }
.dt-table tbody tr:nth-child(10) { animation-delay: 0.37s; }
.dt-table tbody tr:nth-child(n + 11) { animation-delay: 0.4s; }

[data-panel] > * {
  animation: fx-content-rise 0.34s var(--fx-out) both;
}
[data-panel] > :nth-child(2) { animation-delay: 0.04s; }
[data-panel] > :nth-child(3) { animation-delay: 0.08s; }
[data-panel] > :nth-child(4) { animation-delay: 0.12s; }
[data-panel] > :nth-child(5) { animation-delay: 0.16s; }
[data-panel] > :nth-child(n + 6) { animation-delay: 0.2s; }

/* 14.5 面包屑更新动画 */
.crumb-item {
  animation: fx-crumb-in 0.3s var(--fx-out) both;
}
@keyframes fx-crumb-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}

/* 14.6 Tab 点击时下划线扫过加强 */
.tab.active::after {
  animation: fx-tab-underline 0.34s var(--fx-out) both;
}
@keyframes fx-tab-underline {
  0% { left: 50%; right: 50%; }
  100% { left: 6%; right: 6%; }
}

@media (prefers-reduced-motion: reduce) {
  .view-stage.route-wipe-forward::after,
  .view-stage.route-wipe-back::after,
  .dt-table tbody tr,
  [data-panel] > *,
  .crumb-item,
  .tab.active::after,
  .side-indicator {
    animation: none !important;
    transition-duration: 0.01ms !important;
  }
}

/* 转场时序微调：旧视图更快退场，新视图稍后进入，减少重叠感 */
@keyframes fx-view-out-left-3 {
  0% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateX(-30px); }
}
@keyframes fx-view-out-right-3 {
  0% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateX(30px); }
}
.view-page.view-leave-forward {
  position: absolute;
  inset: 0;
  pointer-events: none;
  animation: fx-view-out-left-3 0.16s var(--fx-ease) both;
}
.view-page.view-leave-back {
  position: absolute;
  inset: 0;
  pointer-events: none;
  animation: fx-view-out-right-3 0.16s var(--fx-ease) both;
}
.view-page.view-enter-forward {
  animation: fx-view-in-right-3 0.38s var(--fx-out) 0.06s both;
}
.view-page.view-enter-back {
  animation: fx-view-in-left-3 0.38s var(--fx-out) 0.06s both;
}

@media (prefers-reduced-motion: reduce) {
  .view-stage.route-wipe-forward::after,
  .view-stage.route-wipe-back::after {
    content: none !important;
    animation: none !important;
  }
}

/* 转场时序再调：旧视图 100ms 内退场，新视图延迟 90ms 进入，避免文字重影 */
.view-page.view-leave-forward {
  animation: fx-view-out-left-3 0.1s var(--fx-ease) both;
}
.view-page.view-leave-back {
  animation: fx-view-out-right-3 0.1s var(--fx-ease) both;
}
.view-page.view-enter-forward {
  animation: fx-view-in-right-3 0.34s var(--fx-out) 0.09s both;
}
.view-page.view-enter-back {
  animation: fx-view-in-left-3 0.34s var(--fx-out) 0.09s both;
}

/* 双重类保护：离场时旧视图若残留 enter 类，确保离场动画优先生效 */
.view-page.view-enter-forward.view-leave-forward {
  animation: fx-view-out-left-3 0.1s var(--fx-ease) both;
}
.view-page.view-enter-back.view-leave-back {
  animation: fx-view-out-right-3 0.1s var(--fx-ease) both;
}

/* 页内 Tab/筛选切换：列表卡片整体淡入，单条数据也有明显过渡 */
@keyframes fx-card-swap-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
.dr-table-card,
.dt > [data-table] > .card,
.dt > [data-list] > .card {
  animation: fx-card-swap-in 0.32s var(--fx-out) both;
}

/* 航线擦除柔化：窄光带、低对比，避免大面积白色硬边 */
.view-stage.route-wipe-forward::after,
.view-stage.route-wipe-back::after {
  background:
    linear-gradient(103deg, transparent 0%, rgba(193, 82, 45, 0) 36%, rgba(193, 82, 45, 0.05) 45%, rgba(251, 248, 241, 0.66) 50%, rgba(193, 82, 45, 0.05) 55%, rgba(193, 82, 45, 0) 64%, transparent 100%),
    repeating-linear-gradient(90deg, rgba(193, 82, 45, 0.05) 0 1px, transparent 1px 96px);
  background-size: 260% 100%, auto;
  background-repeat: no-repeat, repeat;
}
@keyframes fx-card-swap-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .dr-table-card,
  .dt > [data-table] > .card,
  .dt > [data-list] > .card {
    animation: none !important;
  }
}

/* 统计窗口 / 数据面板内容整体换入动画 */
[data-body] > * {
  animation: fx-card-swap-in 0.32s var(--fx-out) both;
}
[data-body] > :nth-child(2) { animation-delay: 0.04s; }
[data-body] > :nth-child(3) { animation-delay: 0.08s; }
[data-body] > :nth-child(4) { animation-delay: 0.12s; }
[data-body] > :nth-child(n + 5) { animation-delay: 0.16s; }

@media (prefers-reduced-motion: reduce) {
  [data-body] > * {
    animation: none !important;
  }
}

/* =====================================================================
   15. 自绘下拉选择器（cselect）：替代原生 select 的系统弹层
   ===================================================================== */
.cselect {
  position: relative;
  display: inline-block;
  vertical-align: middle;
}
/* 外壳只承担尺寸，视觉全部交给 trigger（沿用 .select 的既有样式） */
.cselect.select {
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  line-height: inherit;
}
.cselect.select:hover,
.cselect.select:focus {
  border-color: transparent;
  box-shadow: none;
  background: none;
}
.cselect .cselect-trigger {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 100%;
  padding: 0 30px 0 12px;
  text-align: left;
  overflow: hidden;
}
.cselect .cselect-trigger .cselect-value {
  display: block;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cselect.is-open .cselect-trigger {
  border-color: var(--accent);
  background-color: #fffdf8;
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.cselect .cselect-trigger:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--paper-2), 0 0 0 4px rgba(193, 82, 45, 0.42);
}
.cselect-arrow {
  position: absolute;
  right: 11px;
  top: 50%;
  display: grid;
  place-items: center;
  color: var(--ink-3);
  transform: translateY(-50%);
  transition: transform 0.3s var(--fx-spring), color 0.2s var(--fx-ease);
  pointer-events: none;
}
.cselect:hover .cselect-arrow {
  color: var(--accent-2);
}
.cselect.is-open .cselect-arrow {
  color: var(--accent-2);
  transform: translateY(-50%) rotate(180deg);
}
.cselect.is-disabled {
  opacity: 0.55;
}
.cselect.is-disabled .cselect-trigger {
  cursor: not-allowed;
}
.cselect-native {
  visibility: hidden !important;
}
.field.has-error .cselect .cselect-trigger {
  border-color: var(--red);
  box-shadow: 0 0 0 3px var(--red-soft);
}
.field.has-error .cselect .cselect-arrow {
  color: var(--red);
}

/* 浮层菜单（挂载到 body，避免被弹层/抽屉的 overflow 裁剪） */
.cselect-menu {
  position: fixed;
  z-index: 1000;
  min-width: 120px;
  padding: 6px;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--paper-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  box-shadow: 0 20px 48px -24px rgba(35, 30, 25, 0.55), var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px) scale(0.98);
  transform-origin: top center;
  transition: opacity 0.18s var(--fx-ease), transform 0.26s var(--fx-out), visibility 0.26s;
  pointer-events: none;
}
.cselect-menu[aria-hidden='false'] {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
}
.cselect-menu.drop-up {
  transform: translateY(6px) scale(0.98);
  transform-origin: bottom center;
}
.cselect-menu.drop-up[aria-hidden='false'] {
  transform: none;
}
.cselect-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-2);
  background: none;
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
  transition: background-color 0.16s var(--fx-ease), color 0.16s var(--fx-ease), transform 0.16s var(--fx-out);
}
.cselect-option-label {
  overflow: hidden;
  text-overflow: ellipsis;
}
.cselect-option:hover,
.cselect-option.is-active {
  color: var(--ink);
  background: var(--accent-tint);
  transform: translateX(2px);
}
.cselect-option.is-selected {
  color: var(--accent-2);
  font-weight: 600;
}
.cselect-option:active {
  transform: scale(0.99);
}
.cselect-option:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.cselect-check {
  display: grid;
  flex: none;
  place-items: center;
  color: var(--accent-2);
  opacity: 0;
  transform: scale(0.5);
  transition: opacity 0.16s var(--fx-ease), transform 0.24s var(--fx-spring);
}
.cselect-option.is-selected .cselect-check {
  opacity: 1;
  transform: none;
}
.cselect-menu[aria-hidden='false'] .cselect-option {
  animation: cselect-opt-in 0.26s var(--fx-out) backwards;
  animation-delay: calc(var(--i, 0) * 18ms);
}
@keyframes cselect-opt-in {
  from { opacity: 0; transform: translateY(-5px); }
  to { opacity: 1; transform: none; }
}

@media (max-width: 640px) {
  .cselect .cselect-trigger {
    padding-left: 10px;
    padding-right: 28px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cselect .cselect-arrow,
  .cselect-menu,
  .cselect-option,
  .cselect-check {
    transition-duration: 0.01ms !important;
  }
  .cselect-menu[aria-hidden='false'] .cselect-option {
    animation: none !important;
  }
}
