/* ==========================================================================
   应用外壳：侧边栏 + 顶栏 + 内容区
   ========================================================================== */

.app {
  display: flex;
  min-height: 100vh;
}

/* --------------------------------------------------------------------------
   侧边栏
   -------------------------------------------------------------------------- */
.app-sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  z-index: var(--z-sticky);
  display: flex;
  flex-direction: column;
  width: var(--sidebar-width);
  padding: var(--space-4) var(--space-3);
  /* v5.2.2：**去掉 backdrop-filter**。背景模糊会让侧边栏成为一个「每帧都要重新取景模糊」的
     合成层，而 v5.2 起侧边栏里有一个会滑动的指示块（.nav-glider）—— 它每动一帧都要重新模糊
     整块侧边栏，弱显卡上直接表现为「GPU 3D 拉满、内存飙升、页面像卡死」。
     改为不透明底色后，滑动就只是纯 transform 合成，开销几乎为零。 */
  background: var(--sidebar-solid, var(--sidebar-bg));
  border-right: 1px solid var(--sidebar-border);
  /* 折叠/展开性能：
     · 内容区的位移由 .app-main 的 transform 合成动画承担（FLIP，见 .is-nav-animating
       与 js/core/shell.js 的 setSidebarCollapsed）——这是消除卡顿的关键（原来过渡
       margin-left 会每帧重排整页）；
     · 侧边栏自身宽度仍保留过渡（保住原有的面板滑动观感）：它是 position: fixed 且
       `contain: layout paint`，宽度变化的重排被限制在侧边栏内部，不会波及内容区。 */
  transition: width var(--dur-slow) var(--ease-emphasized), transform var(--dur-slow) var(--ease-emphasized);
  /* 不再常驻 will-change：那会永久保留一个整屏高度的合成层（显存常驻）。
     需要时浏览器会自行提升（折叠动画期间由 .is-nav-animating 负责）。 */
  contain: layout paint;
}

.app-sidebar__brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3) var(--space-4);
  min-height: 56px;
  /* v5.2.0：品牌区与导航之间用一条淡分隔线收口，视觉上不再糊在一起 */
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: var(--space-2);
}

.brand-mark {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  background: var(--fill-brand);
  color: #fff;
  box-shadow: var(--shadow-brand);
  transition: transform var(--dur-normal) var(--ease-spring);
}

.brand-mark:hover {
  transform: rotate(-6deg) scale(1.06);
}

.brand-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  transition: opacity var(--dur-fast) var(--ease-out), width var(--dur-slow) var(--ease-emphasized);
}

.brand-title {
  font-size: var(--text-md);
  font-weight: 680;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.brand-subtitle {
  font-size: 11px;
  color: var(--text-tertiary);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.app-sidebar__nav {
  position: relative; /* 滑动指示块（.nav-glider）的定位上下文 */
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding-right: 2px;
  margin-right: -2px;
}

.nav-section-label {
  padding: var(--space-4) var(--space-3) var(--space-2);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  /* v5.2.0：分组标题右侧带一条淡横线，层次更清楚（纯边框，不是渐变） */
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.nav-section-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-subtle);
}

.nav-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.nav-item {
  position: relative;
}

.nav-link {
  position: relative;
  z-index: 1; /* 压在滑动指示块之上（指示块是同一个滚动容器里的绝对定位元素） */
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: 10px var(--space-3);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: var(--text-base);
  font-weight: 500;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-normal) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}

/* 悬停不再横向位移（那会和滑动指示块「打架」），只改文字颜色，位移交给指示块 */
.nav-link:hover {
  color: var(--text-primary);
}

.nav-link__icon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  transition: transform var(--dur-normal) var(--ease-spring), color var(--dur-normal) var(--ease-out);
}

.nav-link:hover .nav-link__icon {
  transform: scale(1.08);
}

.nav-link__label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: opacity var(--dur-fast) var(--ease-out);
}

.nav-link__badge {
  flex-shrink: 0;
  padding: 1px 7px;
  border-radius: var(--radius-full);
  background: var(--danger-soft);
  color: var(--danger);
  font-size: 11px;
  font-weight: 700;
}

.nav-link__chevron {
  flex-shrink: 0;
  transition: transform var(--dur-normal) var(--ease-emphasized);
}

.nav-item.is-open > .nav-link .nav-link__chevron {
  transform: rotate(180deg);
}

/* 选中态：底色由滑动指示块绘制（这里只负责文字与字重，避免双重底色） */
.nav-link.is-active {
  color: var(--brand-600);
  background: transparent;
  font-weight: 620;
}

/* --------------------------------------------------------------------------
   v5.2.0 滑动指示块：跟着「选中项」滑动，鼠标在导航里移动时跟着指针滑动，
   离开导航后回到选中项。纯 transform 动画（合成层，不触发重排）。
   -------------------------------------------------------------------------- */
.nav-glider {
  position: absolute;
  left: var(--space-1);
  right: var(--space-1);
  top: 0;
  z-index: 0;
  height: 38px;
  border-radius: var(--radius-md);
  background: var(--tint-brand);
  box-shadow: var(--shadow-xs);
  pointer-events: none;
  opacity: 0;
  transform: translate3d(0, 0, 0);
  transition: transform var(--dur-normal) var(--ease-emphasized), height var(--dur-normal) var(--ease-emphasized),
    opacity var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}

.nav-glider.is-visible {
  opacity: 1;
}

/* 首次定位（或窗口尺寸变化后重新对齐）不做动画，避免「从顶部滑下来」 */
.nav-glider.is-instant {
  transition: none;
}

/* 鼠标在导航里移动时，指示块底色略深一点，表示「跟着你走」 */
.app-sidebar__nav.is-hovering > .nav-glider {
  background: var(--tint-brand-strong);
}

/* 左侧那道小竖条：跟着指示块一起滑（用伪元素，不额外加节点） */
.nav-glider::after {
  content: '';
  position: absolute;
  left: -3px;
  top: 50%;
  width: 3px;
  height: 55%;
  border-radius: var(--radius-full);
  background: var(--fill-brand);
  transform: translateY(-50%);
}

/* 子菜单：高度动画 + 逐项延迟 */
.nav-submenu {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-emphasized);
}

.nav-item.is-open > .nav-submenu {
  grid-template-rows: 1fr;
}

.nav-submenu__inner {
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-left: var(--space-4);
  border-left: 1px solid var(--border-subtle);
  margin-left: var(--space-5);
}

.nav-submenu .nav-link {
  padding: 8px var(--space-3);
  font-size: var(--text-sm);
  opacity: 0;
  transform: translateX(-8px);
}

.nav-item.is-open .nav-submenu .nav-link {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur-normal) var(--ease-out), transform var(--dur-normal) var(--ease-out),
    background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 26ms);
}

.app-sidebar__footer {
  padding-top: var(--space-3);
  /* v5.2.0：分隔改用「凹陷槽」而不是一条硬边框，和整体拟物语言一致 */
  border-top: none;
  box-shadow: inset 0 1px 0 var(--border-subtle);
  margin-top: var(--space-3);
}

.sidebar-user {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  /* v5.2.0：底部用户区做成一张「小卡片」，与导航项区分开 */
  border: 1px solid var(--border-subtle);
  background: var(--bg-surface);
  cursor: pointer;
  width: 100%;
  text-align: left;
  transition: box-shadow var(--dur-normal) var(--ease-out), transform var(--dur-normal) var(--ease-emphasized),
    border-color var(--dur-normal) var(--ease-out);
}

.sidebar-user:hover {
  transform: translateY(-1px);
  border-color: var(--border-default);
  box-shadow: var(--shadow-sm);
}

.sidebar-user__meta {
  min-width: 0;
  flex: 1;
  overflow: hidden;
}

/* 折叠态（桌面端）：图标居中，文字/徽标/子菜单整体收起 */
.app.is-collapsed .app-sidebar {
  width: var(--sidebar-width-collapsed);
}

.app.is-collapsed .brand-text,
.app.is-collapsed .nav-link__label,
.app.is-collapsed .nav-link__badge,
.app.is-collapsed .nav-link__chevron,
.app.is-collapsed .nav-section-label,
.app.is-collapsed .sidebar-user__meta,
.app.is-collapsed .nav-submenu {
  display: none;
}

/* 折叠时指示块贴近图标：左右各留一点，左侧竖条藏起来（否则会贴到边缘外） */
.app.is-collapsed .nav-glider {
  left: 6px;
  right: 6px;
}

.app.is-collapsed .nav-glider::after {
  display: none;
}

.app.is-collapsed .nav-link {
  justify-content: center;
  padding-inline: 0;
}

.app.is-collapsed .app-sidebar__brand {
  justify-content: center;
  padding-inline: 0;
}

.app.is-collapsed .sidebar-user {
  justify-content: center;
}

/* --------------------------------------------------------------------------
   主区域
   -------------------------------------------------------------------------- */
.app-main {
  flex: 1;
  min-width: 0;
  margin-left: var(--sidebar-width);
  display: flex;
  flex-direction: column;
  /* 注意：这里刻意不再有 margin-left 过渡。
     折叠时 margin-left 瞬时切到目标值，视觉位移由 JS 的 FLIP transform（translateX）补上，
     内容区每帧只做合成层位移，不再整体重排（成绩矩阵/数据表页面掉帧、卡住的主因）。 */
}

.app.is-collapsed .app-main {
  margin-left: var(--sidebar-width-collapsed);
}

/* 折叠/展开动画进行中（shell.js 加类，动画结束后移除）：
   ① 临时关闭昂贵的背景模糊——动画期间 backdrop-filter 每帧都要重算模糊；
   ② transform 的时长与缓动和原来的 margin-left 过渡完全一致，观感不变。 */
.app.is-nav-animating .app-main {
  transition: transform var(--dur-slow) var(--ease-emphasized);
  will-change: transform;
}

/* 首屏：以无过渡方式落到持久化的折叠状态（shell.js 在首帧后移除该类），
   避免刷新瞬间看到侧边栏或内容区滑动。 */
.app.is-nav-static .app-sidebar,
.app.is-nav-static .app-main {
  transition: none;
}

.app-topbar {
  position: sticky;
  top: 0;
  z-index: calc(var(--z-sticky) - 1);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  height: var(--topbar-height);
  padding: 0 var(--space-6);
  /* v5.2.2：顶栏同样去掉 backdrop-filter（常驻的全宽模糊是 GPU/显存大头），
     用不透明的顶栏底色 + 一条描边与投影保证层次；.is-nav-animating 的临时措施也就不需要了 */
  background: var(--topbar-solid, var(--topbar-bg));
  border-bottom: 1px solid var(--border-subtle);
}

.topbar-title {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.topbar-title__icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-sm);
  background: var(--bg-active);
  color: var(--brand-500);
  flex-shrink: 0;
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

.breadcrumbs {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-tertiary);
}

.breadcrumbs__sep {
  opacity: 0.5;
}

.icon-button {
  position: relative;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  border: 1px solid transparent;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-spring);
}

.icon-button:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
  border-color: var(--border-subtle);
}

.icon-button:active {
  transform: scale(0.94);
}

.icon-button__dot {
  position: absolute;
  top: 7px;
  right: 7px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--danger);
  box-shadow: 0 0 0 2px var(--bg-surface);
}

.app-content {
  flex: 1;
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-8) var(--space-6) var(--space-12);
}

.app-footer {
  padding: var(--space-6);
  border-top: 1px solid var(--border-subtle);
  color: var(--text-tertiary);
  font-size: var(--text-sm);
  text-align: center;
}

.app-footer a { color: var(--text-secondary); }

/* 移动端遮罩（v5.2.2：不再做背景模糊，纯色遮罩更便宜且观感一致） */
.sidebar-scrim {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-sticky) - 2);
  background: rgba(2, 6, 23, 0.55);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-normal) var(--ease-out);
}

/* --------------------------------------------------------------------------
   页面头部
   -------------------------------------------------------------------------- */
.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.page-header__text { min-width: 0; }

.page-header__title {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.02em;
}

.page-header__desc {
  margin-top: var(--space-1);
  color: var(--text-secondary);
  font-size: var(--text-base);
}

.page-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

/* --------------------------------------------------------------------------
   无壳布局（登录页、全屏结果页）
   -------------------------------------------------------------------------- */
.app.is-bare > .app-sidebar,
.app.is-bare > .app-main > .app-topbar,
.app.is-bare > .app-main > .app-footer,
.app.is-bare > .sidebar-scrim {
  display: none !important;
}

.app.is-bare > .app-main {
  margin-left: 0;
}

.app.is-bare > .app-main > .app-content {
  max-width: none;
  padding: 0;
  min-height: 100vh;
}

/* --------------------------------------------------------------------------
   响应式
   -------------------------------------------------------------------------- */
@media (max-width: 1180px) {
  .app-content { padding: var(--space-6) var(--space-5) var(--space-10); }
}

@media (max-width: 1024px) {
  .app-sidebar {
    transform: translateX(-100%);
    box-shadow: var(--shadow-xl);
    z-index: var(--z-drawer);
    /* v5.2.0：抽屉式滑入更「丝滑」——用弹性缓动 + 只动 transform（合成层） */
    transition: transform var(--dur-slow) var(--ease-emphasized);
    will-change: transform;
  }

  .app.is-mobile-nav-open .app-sidebar {
    transform: translateX(0);
  }

  /* 抽屉打开时，内容区轻微后退（只在移动端、且是纯 transform） */
  .app.is-mobile-nav-open .app-main {
    transform: translateX(var(--space-2)) scale(0.995);
    transition: transform var(--dur-slow) var(--ease-emphasized);
  }

  .app.is-mobile-nav-open .sidebar-scrim {
    opacity: 1;
    pointer-events: auto;
  }

  .app-main,
  .app.is-collapsed .app-main {
    margin-left: 0;
  }

  .app-topbar { padding: 0 var(--space-4); }
}

/* 减少动效偏好：滑动指示块与抽屉都直接落位，不做过渡 */
@media (prefers-reduced-motion: reduce) {
  .nav-glider,
  .app-sidebar,
  .app.is-mobile-nav-open .app-main,
  .nav-link,
  .nav-link__icon,
  .nav-link__chevron,
  .nav-submenu,
  .nav-submenu .nav-link {
    transition: none !important;
    animation: none !important;
  }
}

@media (max-width: 720px) {
  .app-topbar {
    height: 58px;
    gap: var(--space-2);
  }

  .app-content { padding: var(--space-5) var(--space-4) var(--space-10); }

  .page-header__title { font-size: var(--text-xl); }

  .topbar-title .breadcrumbs { display: none; }
}

@media (min-width: 1025px) {
  .mobile-only { display: none !important; }
}

@media (max-width: 1024px) {
  .desktop-only { display: none !important; }
}
