/* ============================================================
   学途 · 安静皮肤 —— 组件覆盖层

   必须【最后加载】。本文件不改任何 HTML 结构、不改类名，
   只按现有类名把「玻璃拟态 + 暖木色」重写为
   「月白底 + 天青 + 胶囊 + 极轻阴影 + 描边分界」。

   为什么单独一层而不是直接改 style.css：
   保留原文件可随时一行切回旧皮肤（把 index.html 的 <link> 指回去即可）。

   本层遵守的纪律（同 tokens.css 顶部）：
   · 大面积只用 --brand-tint / --sunk 这类极浅底，不用彩色大字
   · 卡片一律 1px 描边 + 极轻阴影，不靠阴影「浮起来」
   · 删掉所有玻璃拟态（多层渐变 + 内阴影 + 外发光 + 内高光）
   · 圆角三档统一，不再一个组件一个值
   ============================================================ */

/* ============================================================
   0. 全局
   ============================================================ */
body {
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--cjk);
  -webkit-font-smoothing: antialiased;
}

/* 全局隐藏滚动条（PMS 约定，避免侧栏/内容区出现突兀的滚动条轨道） */
* { scrollbar-width: none; }
*::-webkit-scrollbar { width: 0; height: 0; }


/* ============================================================
   1. 图标契约（纪律⑤）
   统一尺寸四档 + 颜色一律跟随文本色。
   注意：内联 style="color:..."/"font-size:..." 优先级高于本层，
   所以散落的硬编码仍需逐个清理（见阶段 6 清单）。
   ============================================================ */
[class^="fa-"], [class*=" fa-"] { line-height: 1; }

.btn i, .icon-btn i, .nav-icon i, .panel-header i,
.toolbar i, .header-search i, .modal-close i,
.badge i, .empty-state i, .chart-panel i {
  font-size: 16px;
  width: 16px;
  text-align: center;
}
.btn-sm i, .btn.sm i, .badge i { font-size: 14px; width: 14px; }
.stat-icon i { font-size: 22px; width: 22px; }
.empty-state i { font-size: 22px; width: auto; }
.logo-icon i { font-size: 20px; }

/* 让图标继承文本色 —— 不再各自染成彩色 */
i[class^="fa-"], i[class*=" fa-"] { color: currentColor; }


/* ============================================================
   2. 侧栏 —— 深咖啡渐变 → 白底 + 右描边
   ============================================================ */
.sidebar {
  background: var(--surface);
  border-right: 1px solid var(--line);
}

.sidebar-header {
  padding: var(--s5) var(--s5);
  border-bottom: 1px solid var(--line);
  gap: var(--s3);
}

/* 品牌标：渐变方块保留（它是全站唯一的视觉锚点），但收敛尺寸与圆角 */
.logo-icon {
  width: 40px;
  height: 40px;
  border-radius: var(--r-sm);
  font-size: 20px;
  background: var(--logo-gradient);
  box-shadow: var(--logo-shadow);
}

.logo-title {
  color: var(--ink);
  font-size: var(--t-base);
  font-weight: 700;
  letter-spacing: -0.01em;
}
.logo-sub {
  color: var(--faint);
  font-size: var(--t-xs);
  opacity: 1;
  letter-spacing: 0;
  text-transform: none;   /* 旧版全大写 + 字距，中文下很丑 */
}

.sidebar-nav::-webkit-scrollbar-thumb { background: var(--line-2); }

/* 分组标签 */
.nav-section-label {
  padding: var(--s5) var(--s5) var(--s2);
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--faint);
  text-transform: none;   /* 同上 */
  letter-spacing: 0;
}

.nav-menu { padding: 0 var(--s2); }

/* 导航项：删掉整套玻璃拟态，改为扁平 + 胶囊 */
.nav-item {
  /* 10px 上下 + 28px 图标盒 = 48px 一项。
     图标盒比文字行盒(24px)大，所以高度由图标那一侧决定，
     内边距就从 12 收到 10 把空间让给图标，盒子尺寸不变。
     折叠态那份 padding 必须【同值】—— 两态高度一旦不一致，
     又会回到「收起/展开图标对不上」那个 bug。 */
  padding: 10px var(--s3);
  margin: 2px 0;
  border-radius: var(--r-pill);
  /* 文字 14 → 15px（字号略大一圈），但【盒子不能变】：
     行盒 = 15 × 1.6 = 24px，与图标盒 24px 等高，
     所以导航项仍是 24 + 上下 12×2 = 48px。
     再往上到 16px 就是 25.6px 行盒 → 会把盒子撑到 50px，那就变了。 */
  font-size: 15px;
  font-weight: 500;
  color: var(--muted);
  background: transparent;
  /* 这四条是【盖住 shell.css 那套玻璃拟态】的，删不得：
     shell.css 的 .nav-item 带 1px 边框 + 渐变底 + 发光阴影，
     少一条就会漏出来 —— 盒子多 2px（48 → 50）、图标右移 1px。 */
  border: none;
  box-shadow: none;
}

.nav-item:hover {
  background: var(--sunk);
  color: var(--ink);
  border: none;
  box-shadow: none;
  transform: none;        /* 旧版位移 4px，安静皮肤不要这种躁动 */
}

.nav-item.active {
  background: var(--brand-tint);
  color: var(--brand-deep);
  font-weight: 600;
  border: none;
  box-shadow: none;
}

.nav-icon {
  /* 图标要再大，就得从【内边距里让地方】—— 导航项高度由两者加起来决定：
       导航项高 = max(图标盒, 文字行盒 24px) + 上下内边距 × 2
     所以图标盒 24 → 28px 的同时把内边距 12 → 10px：
       28 + 10×2 = 48px，盒子依然没变。 */
  width: 28px;
  height: 28px;
  border-radius: 0;
  font-size: 26px;
  background: transparent;
  border: none;
  box-shadow: none;
}

.nav-item.active .nav-icon {
  background: transparent;
  color: var(--brand);    /* active 时图标用品牌色，而非白底方块 */
  box-shadow: none;
}

/* 旧版右侧那道 3px 指示条在胶囊风格下是多余的 */
.nav-indicator,
.nav-item.active .nav-indicator { display: none; }

/* 侧栏底部 */
.sidebar-footer { border-top: 1px solid var(--line); }

.sidebar-footer-info {
  padding: var(--s3) var(--s5) 0;
  color: var(--faint);
  font-size: var(--t-xs);
}

.sidebar-footer-user {
  padding: var(--s3) var(--s5) var(--s4);
  border-top: none;
  margin-top: 0;
}

.user-avatar {
  width: 32px;
  height: 32px;
  font-size: var(--t-sm);
  background: var(--brand-tint);
  color: var(--brand-deep);
  border: 1px solid var(--line);
}

.user-name { color: var(--ink); font-size: var(--t-sm); font-weight: 600; }
.user-role { color: var(--faint); font-size: var(--t-xs); }

.btn-logout {
  width: 32px;
  height: 32px;
  border-radius: var(--r-sm);
  background: transparent;
  border: 1px solid var(--line);
  color: var(--muted);
}
.btn-logout:hover {
  background: var(--red-soft);
  border-color: var(--red);
  color: var(--red);
  transform: none;
}

.sidebar-overlay { background: rgba(47, 52, 55, 0.32); backdrop-filter: none; }


/* ============================================================
   3. 顶栏
   ============================================================ */
.top-bar {
  background: var(--surface);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom: 1px solid var(--line);
  padding: var(--s4) var(--s6);
}

.page-title { font-size: var(--t-lg); font-weight: 700; color: var(--ink); }
.page-subtitle { font-size: var(--t-xs); color: var(--faint); }

.header-search {
  background: var(--sunk);
  border: 1px solid transparent;
  padding: var(--s2) var(--s4);
}
.header-search:focus-within {
  background: var(--surface);
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-tint);
}
.header-search i { color: var(--faint); }
.header-search input { color: var(--ink); }

.header-time { color: var(--faint); font-size: var(--t-xs); }

.menu-toggle { color: var(--muted); }
.menu-toggle:hover { background: var(--sunk); }


/* ============================================================
   4. 卡片 / 面板
   ============================================================ */
.panel,
.chart-panel,
.card-glass,
.panel-glass {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--sh);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.panel-header {
  border-bottom: 1px solid var(--line);
  padding: var(--s4) var(--s5);
  font-weight: 600;
  color: var(--ink);
}

.panel-body { padding: var(--s5); }


/* ============================================================
   5. 统计卡
   ============================================================ */
.stat-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--sh);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  transition: border-color 0.2s, transform 0.2s;
}
.stat-card:hover {
  border-color: var(--brand-2);
  transform: translateY(-2px);
}

/* 旧版每个统计卡一个有彩底色图标 —— 收敛成极浅品牌底 + 品牌色图标 */
.stat-icon {
  background: var(--brand-tint) !important;
  color: var(--brand) !important;
  border-radius: var(--r-sm);
}

.stat-label { color: var(--faint); font-size: var(--t-xs); font-weight: 500; }
.stat-value { color: var(--ink); font-weight: 700; }
.stat-info { color: var(--ink); }


/* ============================================================
   6. 按钮 —— 统一为描边胶囊
   ============================================================ */
.btn {
  border-radius: var(--r-pill);
  font-weight: 600;
  font-size: var(--t-sm);
  padding: var(--s2) var(--s4);
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--ink);
  transition: background 0.18s, border-color 0.18s, color 0.18s;
  box-shadow: none;
}
.btn:hover { border-color: var(--brand-2); color: var(--brand-deep); }

.btn-primary,
.btn-accent {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
}
.btn-primary:hover,
.btn-accent:hover {
  background: var(--brand-hover);
  border-color: var(--brand-hover);
  color: var(--on-brand);
}

.btn-success {
  background: var(--green);
  border-color: var(--green);
  color: #fff;
}
.btn-danger {
  background: transparent;
  border-color: var(--red);
  color: var(--red);
}
.btn-danger:hover { background: var(--red-soft); color: var(--red); border-color: var(--red); }

.btn-outline,
.btn-glass {
  background: var(--surface);
  border: 1px solid var(--line-2);
  color: var(--ink);
}
.btn-outline:hover,
.btn-glass:hover { border-color: var(--brand-2); color: var(--brand-deep); }

.btn-sm { padding: var(--s1) var(--s3); font-size: var(--t-xs); }


/* ============================================================
   7. 标签（旧名 .badge-*，成对的语义色）
   ============================================================ */
.badge {
  border-radius: var(--r-pill);
  padding: 2px 10px;
  font-size: var(--t-xs);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  line-height: 1.7;
  border: none;
}
.badge-green  { background: var(--s-done-t);    color: var(--s-done); }
.badge-blue   { background: var(--s-idle-t);    color: var(--s-idle); }
.badge-orange { background: var(--s-doing-t);   color: var(--s-doing); }
.badge-yellow { background: var(--s-doing-t);   color: var(--s-doing); }
.badge-red    { background: var(--s-overdue-t); color: var(--s-overdue); }
.badge-purple { background: var(--s-paused-t);  color: var(--s-paused); }
.badge-gray   { background: var(--s-todo-t);    color: var(--s-todo); }
.badge-pink   { background: var(--s-paused-t);  color: var(--s-paused); }


/* ============================================================
   8. 表格
   ============================================================ */
.data-table { border-collapse: separate; border-spacing: 0; width: 100%; }

.data-table th {
  background: var(--sunk);
  color: var(--muted);
  font-size: var(--t-xs);
  font-weight: 600;
  text-align: left;
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line);
}
.data-table td {
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  font-size: var(--t-sm);
}
.data-table tr:hover td { background: var(--sunk); }
.data-table tr:last-child td { border-bottom: none; }

/* Markdown 渲染出的表格（renderMD 在所有页面都会产出）。
   旧版只定义在「课程资料」页的内嵌 <style> 里 ——
   没进过课程页就直接用智能辅导/资源工坊时，表格是无样式的。 */
.md-table {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
  margin: var(--s3) 0;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.md-table th {
  background: var(--sunk);
  color: var(--muted);
  font-size: var(--t-xs);
  font-weight: 600;
  text-align: left;
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--line);
}
.md-table td {
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  font-size: var(--t-sm);
}
.md-table tr:last-child td { border-bottom: none; }
.md-table-wrap { overflow-x: auto; margin: var(--s3) 0; }


/* ============================================================
   9. 表单
   ============================================================ */
.form-group label,
.form-label {
  color: var(--muted);
  font-size: var(--t-xs);
  font-weight: 600;
  margin-bottom: var(--s1);
  display: block;
}

.form-control,
.textarea,
.select {
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--ink);
  font-family: var(--cjk);
  font-size: var(--t-sm);
  padding: var(--s2) var(--s3);
  outline: none;
  transition: border-color 0.18s, box-shadow 0.18s;
}
.form-control:focus,
.textarea:focus,
.select:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-tint);
}
.form-control::placeholder { color: var(--faint); }


/* ============================================================
   10. 弹窗 / 抽屉 / Toast
   ============================================================ */
.modal-overlay {
  background: rgba(47, 52, 55, 0.38);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.modal-box {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--sh);
}

.modal-close {
  color: var(--faint);
  background: transparent;
  border: none;
}
.modal-close:hover { color: var(--ink); background: var(--sunk); }

.modal-actions {
  border-top: 1px solid var(--line);
  padding-top: var(--s4);
  gap: var(--s2);
}

/* 旧版 toast 是彩色实心块 —— 改为深墨底 + 白字（PMS 的单一样式） */
.toast {
  background: var(--ink);
  color: #fff;
  border-radius: var(--r-pill);
  padding: var(--s2) var(--s5);
  box-shadow: var(--sh);
  font-size: var(--t-sm);
  font-weight: 500;
}
.toast-success, .toast-error, .toast-info { background: var(--ink); color: #fff; }


/* ============================================================
   11. 空状态 / 加载态
   ============================================================ */
.empty-state {
  color: var(--faint);
  font-size: var(--t-sm);
}
.empty-state i { color: var(--line-2); }

.loading-spinner {
  color: var(--faint);
  font-size: var(--t-sm);
}

/* 空状态里那句感性文案用楷体（纪律⑦：楷体只用于此） */
.empty-state h4,
.empty-state .empty-title {
  font-family: var(--kai);
  color: var(--muted);
  font-weight: 500;
}


/* ============================================================
   12. 工具栏 / 布局辅助
   ============================================================ */
.toolbar {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin-bottom: var(--s4);
}

.chart-wrap { background: transparent; }


/* ============================================================
   13. 侧栏折叠（桌面端）
   内容密集页自动收起成 72px 图标条，其余页展开。
   由 js/sidebar-collapse.js 在 <html> 上加 .sidebar-collapsed 驱动，
   CSS 只在桌面端（≥981px）生效 —— 窄屏（≤768px）走抽屉式，
   两者互不干扰。
   ============================================================ */

/* 品牌区的手动折叠按钮（展开/收起时都显示） */
.sidebar-collapse-btn {
  margin-left: auto;
  width: 28px;
  height: 28px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.18s, border-color 0.18s, color 0.18s;
}
.sidebar-collapse-btn:hover {
  border-color: var(--brand-2);
  color: var(--brand-deep);
}

/* 品牌区两态同高 —— 折叠时按钮要从「横排」变「竖排」，
   flex-direction 不可过渡；若不锁高度，它会从 87px 长到 113px，
   而它在最顶上，于是下面所有内容会整体【往下跳 26px】。
   必须用 height 而不是 min-height —— min-height 只是【下限】，
   折叠态内容（图标40+间距12+按钮28+上下内边距32=112）本就超过 87，
   照样把盒子撑高，等于没锁。 */
.sidebar-header { height: 87px; }

@media (min-width: 981px) {
  /* 侧栏和内容区必须同步改，否则内容被压到侧栏下或露出空隙 */
  html.sidebar-collapsed .sidebar { width: 72px; }
  html.sidebar-collapsed .main-content { margin-left: 72px; }

  /* 宽度/左边距要有过渡，别硬切（基类只过渡 transform） */
  .sidebar {
    transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1),
                transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  }
  .main-content { transition: margin-left 0.3s cubic-bezier(0.4, 0, 0.2, 1); }

  /* 品牌区：只留图标，图标 + 按钮竖排居中 */
  html.sidebar-collapsed .sidebar-header {
    flex-direction: column;
    padding: 0;            /* 收掉内边距，内容 40+4+28=72 才塞得进 87 */
    gap: var(--s1);
    justify-content: center;
  }
  html.sidebar-collapsed .logo-text { display: none; }
  html.sidebar-collapsed .sidebar-collapse-btn { margin-left: 0; }

  /* 分组标签（"主菜单"/"学习"/"智能"）
     不能 display:none —— 那样三个分组的界限会完全消失，十个图标连成一整条，
     认不出哪些属于哪组。改成一根细分隔线：结构还在，但不占文字空间。 */
  /* 分组标签：折叠时【保留展开态的高度】，只把文字隐掉。
     之前压到 1px，结果它下面每个图标都被拽着往上跑
     （第一个图标从 y=138 跑到 y=112），切一次整组都动。
     要的是「图标原地不动、只变宽度」，所以高度必须留。 */
  /* 挂到 flex 列上之后它多了一个作用：导航项高度是固定的，而它是唯一
     会长高的元素 —— 剩下的纵向空间按三等分落到三条标签上，整列就正好
     铺到侧栏底部（改前底部空着 151px）。窗口多高都能填满，不写死像素。 */
  .sidebar-nav {
    display: flex;
    flex-direction: column;
  }
  .nav-menu { flex: 0 0 auto; }   /* 导航项不参与拉伸，高度恒定 */

  .nav-section-label {
    flex: 1 1 auto;
    min-height: 49px;
    max-height: 120px;   /* 屏幕特别高时别把分组拉得彼此看不见 */
    display: flex;
    align-items: center;      /* 文字在标签内垂直居中（高度现在是弹性的） */
    padding: 0 var(--s5);
    overflow: hidden;
  }
  html.sidebar-collapsed .nav-section-label {
    font-size: 0;        /* 文字渲染成 0 号字 = 不可见 */
    line-height: 0;
  }
  /* 高度留着就是一片空白；用一根居中的短线把分组讲清楚。
     居中交给 flex 容器（align-items + 横向 auto margin），
     不再写死 margin-top —— 标签高度已经变成弹性的，写死就不居中了。 */
  html.sidebar-collapsed .nav-section-label::before {
    content: '';
    display: block;
    width: 20px;
    height: 1px;
    margin: 0 auto;
    background: var(--line);
  }

  /* 导航项：只留图标，居中 */
  html.sidebar-collapsed .nav-item {
    /* 不要 justify-content: center ——
       它不可过渡，生效那一刻侧栏还有 264px 宽，图标会【瞬间跳到 132px 处】
       （264 的中点），再随宽度收缩漂回；用户看到的就是「图标还要往中间移一下」。
       保持与展开态完全相同的左边距（nav-menu 8px + item 12px = 20px），
       图标就彻底不动了 —— 收起时只有宽度在变。 */
    padding: 10px var(--s3);   /* 与展开态同值，两态都是 48px */
    gap: 0;
  }
  /* 导航项本身高度两态一致（48px，靠 span 的 0 宽行盒实现），
     再加一层过渡兜底，防止将来有人改动 span 的写法时又出现跳动。 */
  .nav-item { transition: padding .28s cubic-bezier(.4,0,.2,1),
                          gap .28s cubic-bezier(.4,0,.2,1); }

  /* 文字【不能】display:none —— 它的行盒是这一项高度的来源
     （现在由图标 24px 撑住：24 + 上下各 12px padding = 48px）。
     一旦 display:none，折叠态就只剩图标的 24px，整项掉到 24px，
     于是「每个图标的高度在收起/展开之间对不上」。
     改成压成 0 宽但仍占据行盒：高度自动与展开态一致，无需写死像素值。 */
  html.sidebar-collapsed .nav-item span {
    display: block;
    width: 0;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    visibility: hidden;
  }

  /* 侧栏底部：只留头像，收掉"系统运行中"/用户名/退出按钮。
     同样不能用 display:none —— 那样高度是瞬变的（107px→61px 一下砍掉），
     底部会「啪」地缩一下。改成显式高度 + 过渡，让它滑下去。 */
  /* 底部同理：保留高度、只隐内容 —— 否则侧栏底部会缩一下，
     连带头像跟着往上跑。 */
  /* 这里【不能】写死高度 —— 我第一版写了 height:34px 来保持高度稳定，
     结果名字(22.4px)+角色(20.8px)=43.2px 塞不进 34px，第二行被裁掉一截，
     用户看到的就是「第二个管理员显示不全」。
     正确做法：不锁高度，改用 nowrap 防止折行 —— 只要文字不折行，
     两个状态下高度天然一致，而且不会被裁。 */
  .sidebar-footer-info,
  .user-details {
    white-space: nowrap;
    overflow: hidden;
    min-width: 0;
    transition: opacity .2s;
  }
  html.sidebar-collapsed .sidebar-footer-info,
  html.sidebar-collapsed .user-details { opacity: 0; }

  html.sidebar-collapsed .btn-logout { display: none; }
  /* 左下角头像要落在 72px 导轨的正中 —— 但【不能】用 justify-content: center：
     它不可过渡，生效那一刻侧栏还有 264px 宽，头像会先跳到中缝再漂回来
     （就是导航图标那次「往中间移一下」的同一种跳）。
     算一下：(72 - 32) / 2 = 20px，而展开态头像本来就在 padding-left: 20px 处
     —— 两个位置本来就重合。所以真正该做的是把旁边那块
     【隐了形却仍占 27px】的 .user-details 宽度收成 0：
     它把可用空间吃光，center 才没东西可分，头像被挤到了 x=0。 */
  html.sidebar-collapsed .user-details { width: 0; }
}

/* 窄屏走抽屉式，折叠按钮没有意义，隐藏 */
@media (max-width: 768px) {
  .sidebar-collapse-btn { display: none; }
}


/* ============================================================
   品牌区文字：禁止折行（修「展开瞬间闪一下」）
   展开的瞬间侧栏宽度还只有 72px —— 宽度要过渡 0.3s 才长到 264px ——
   此时「多智能体教学辅助系统」会被挤成好几行，下个瞬间又展开回一行，
   那一闪就是它。nowrap + 裁切之后文字只会被「揭开」，不会再折行。
   放在文件末尾：与 shell.css 里的 .logo-text 同特异性，靠加载顺序取胜。
   ============================================================ */
.logo-text { white-space: nowrap; overflow: hidden; min-width: 0; }
.logo-title, .logo-sub { white-space: nowrap; overflow: hidden; text-overflow: clip; }

/* ============================================================
   侧栏所有文字禁止折行（同一类 bug 的完整收口）
   现象：展开瞬间侧栏宽度还只有 72px（宽度要 0.3s 才过渡到 264），
        任何文字在这个宽度下都会被挤成多行，下个瞬间又跳回一行 —— 就是那一闪。
   品牌区先修了，导航项与分组标签当时漏了：
        「分析看板」「AI画像构建」          → 会被挤成多行
        「主菜单」3 字约 39px，而收起态内容宽只有 32px → 也会折
   统一处理：nowrap + 裁切 + min-width:0（后两者让 flex 子项还能正常收缩）。
   ============================================================ */
.nav-item span,
.nav-section-label,
.sidebar-footer-info,
.user-name,
.user-role {
  white-space: nowrap;
  overflow: hidden;
  min-width: 0;
}
