/* 组件层:按钮、表单、卡片、列表、表格、状态、浮层、骨架屏与五种数据状态。
   规则:只动 transform / opacity;色值、圆角、时长全部取自 tokens.css。 */

/* ================= 按钮 ================= */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 44px; padding: 0 var(--sp-4);
  border-radius: var(--radius-s);
  border: 1px solid var(--line-strong);
  background: var(--bg-elev-1); color: var(--text);
  font-family: inherit; font-size: 14px; font-weight: 500; line-height: 1;
  cursor: pointer; white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-io),
              border-color var(--dur-fast) var(--ease-io),
              color var(--dur-fast) var(--ease-io),
              transform var(--dur-fast) var(--ease-io);
}
/* hover 只提升一级"海拔",不引入新色值 */
.btn:hover:not(:disabled) { background: var(--bg-elev-2); }
.btn:active:not(:disabled) { transform: scale(.97); }
.btn:disabled { opacity: .45; cursor: not-allowed; }

.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 600; }
.btn-primary:hover:not(:disabled) { background: var(--accent-press); border-color: var(--accent-press); }

.btn-danger { border-color: var(--danger); color: var(--danger); background: transparent; }
.btn-danger:hover:not(:disabled) { background: color-mix(in srgb, var(--danger) 10%, transparent); }

.btn-danger-solid { background: var(--danger); border-color: var(--danger); color: var(--text); font-weight: 600; }
.btn-danger-solid:hover:not(:disabled) { filter: brightness(.92); }

.btn-ghost { background: transparent; border-color: transparent; color: var(--text-dim); }
.btn-ghost:hover:not(:disabled) { background: var(--bg-elev-2); color: var(--text); }

.btn-sm { min-height: 36px; padding: 0 var(--sp-3); font-size: 13px; }
.btn-block { width: 100%; }

/* 加载中:文字变进行时 + 内联 spinner,尺寸不变以免布局跳动 */
.btn[data-loading="true"] { pointer-events: none; }
.spinner {
  width: 16px; height: 16px; flex: none;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ================= 表单 ================= */

.field { display: flex; flex-direction: column; gap: var(--sp-2); }
.field > label { font-size: 13px; color: var(--text-dim); font-weight: 500; }
.field .req { color: var(--danger); margin-left: 2px; }
.field .hint { font-size: 12px; color: var(--text-mute); }
.field .error-text { font-size: 12px; color: var(--danger); display: flex; align-items: center; gap: var(--sp-1); }

.input, .select, .textarea {
  width: 100%; min-height: 44px;
  padding: var(--sp-3);
  border-radius: var(--radius-s);
  border: 1px solid var(--line-strong);
  background: var(--bg-elev-2); color: var(--text);
  /* ≥16px 以免 iOS 聚焦时自动放大 */
  font-family: inherit; font-size: 16px; line-height: 1.5;
  transition: border-color var(--dur-fast) var(--ease-io), background var(--dur-fast) var(--ease-io);
}
.input::placeholder, .textarea::placeholder { color: var(--text-mute); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--line-strong); }
.input:focus, .select:focus, .textarea:focus { border-color: var(--accent); outline: none; }
.input[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--danger); }
.input:disabled, .select:disabled { opacity: .5; cursor: not-allowed; }
.textarea { min-height: 96px; resize: vertical; }

@media (min-width: 768px) {
  .input, .select, .textarea { font-size: 14px; }
}

.select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-dim) 50%),
                    linear-gradient(135deg, var(--text-dim) 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: var(--sp-6);
}

.switch { display: inline-flex; align-items: center; gap: var(--sp-3); min-height: 44px; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 44px; height: 24px; border-radius: 999px; flex: none;
  background: var(--bg-elev-2); border: 1px solid var(--line-strong);
  display: flex; align-items: center; padding: 2px;
  transition: background var(--dur-fast) var(--ease-io), border-color var(--dur-fast) var(--ease-io);
}
.switch .knob {
  width: 18px; height: 18px; border-radius: 50%; background: var(--text-dim);
  transition: transform var(--dur-fast) var(--ease-io), background var(--dur-fast) var(--ease-io);
}
.switch input:checked + .track { background: color-mix(in srgb, var(--accent) 20%, transparent); border-color: var(--accent); }
.switch input:checked + .track .knob { transform: translateX(20px); background: var(--accent); }
.switch input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ================= 卡片 ================= */

.card {
  background: var(--bg-elev-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  padding: var(--sp-4);
}
.card-head { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.card-head h3 { font-weight: 600; }
.card-note { font-size: 12px; color: var(--text-mute); }

.grid-2 { display: grid; gap: var(--sp-3); grid-template-columns: 1fr; }
@media (min-width: 768px) { .grid-2 { grid-template-columns: repeat(2, 1fr); } }

/* 统计卡 */
.stat-grid { display: grid; gap: var(--sp-3); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 768px) { .stat-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .stat-grid { grid-template-columns: repeat(4, 1fr); } }

.stat {
  background: var(--bg-elev-1); border: 1px solid var(--line);
  border-radius: var(--radius-m); padding: var(--sp-4);
}
.stat .stat-k { font-size: 12px; color: var(--text-dim); }
.stat .stat-v { font-size: 24px; font-weight: 600; line-height: 1.25; margin-top: var(--sp-1); }
.stat .stat-sub { font-size: 12px; color: var(--text-mute); margin-top: var(--sp-1); }

/* ================= 状态点 / 标签 ================= */

.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; display: inline-block; }
.dot-online { background: var(--accent); }
.dot-offline { background: var(--text-mute); }
.dot-warn { background: var(--warn); }
.dot-danger { background: var(--danger); }

/* nowrap:中文的 min-content 宽度就是「一个字」,不锁住的话,
   flex 一旦空间不够就会把整块文字压成一列竖排字(顶栏踩过这个坑)。 */
.status { display: inline-flex; align-items: center; gap: var(--sp-2); font-size: 13px; white-space: nowrap; }
.status.online { color: var(--accent); }
.status.offline { color: var(--text-dim); }

.tag {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  height: 24px; padding: 0 var(--sp-2);
  border-radius: var(--radius-s);
  border: 1px solid var(--line-strong);
  font-size: 12px; color: var(--text-dim);
  background: var(--bg-elev-2);
  white-space: nowrap;
}
.tag-accent { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 35%, transparent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.tag-warn   { color: var(--warn);   border-color: color-mix(in srgb, var(--warn) 35%, transparent);   background: color-mix(in srgb, var(--warn) 8%, transparent); }
.tag-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, transparent); background: color-mix(in srgb, var(--danger) 8%, transparent); }
.tag-info   { color: var(--info);   border-color: color-mix(in srgb, var(--info) 35%, transparent);   background: color-mix(in srgb, var(--info) 8%, transparent); }

/* ================= 列表 ================= */

.list { display: flex; flex-direction: column; }
.list-item {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: 56px; padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--line);
  transition: background var(--dur-fast) var(--ease-io);
}
.list-item:last-child { border-bottom: 0; }
/* 名次标:榜单里取代原来的头像方块。
   头像显示「名字前两字」的做法已全站移除 —— 两个字的昵称(如「轩昀」)
   会在头像里把名字原样重复一遍,看起来就是显示了两次用户名。 */
.list-item .rank {
  flex: none; min-width: 22px; text-align: center;
  color: var(--text-mute); font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.list-item .li-main { min-width: 0; flex: 1; }
.list-item .li-title { font-size: 14px; font-weight: 500; }
.list-item .li-sub { font-size: 12px; color: var(--text-mute); }

/* ================= 表格(窄屏转卡片,不横向滚动)================= */

.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th, .table td { text-align: left; padding: var(--sp-3) var(--sp-3); border-bottom: 1px solid var(--line); }
.table th { font-size: 12px; font-weight: 500; color: var(--text-dim); }
.table tbody tr:last-child td { border-bottom: 0; }

@media (max-width: 767px) {
  .table thead { display: none; }
  .table, .table tbody, .table tr, .table td { display: block; width: 100%; }
  .table tr {
    border: 1px solid var(--line); border-radius: var(--radius-s);
    padding: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-2);
    background: var(--bg-elev-1);
  }
  .table td {
    display: flex; align-items: baseline; gap: var(--sp-3);
    border-bottom: 0; padding: var(--sp-1) 0;
  }
  .table td::before {
    content: attr(data-label);
    flex: 0 0 88px; font-size: 12px; color: var(--text-mute);
  }
}

/* ================= 提示条 ================= */

.banner {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-s);
  border: 1px solid var(--line-strong);
  background: var(--bg-elev-1);
  font-size: 13px;
}
.banner-warn { border-color: color-mix(in srgb, var(--warn) 35%, transparent); background: color-mix(in srgb, var(--warn) 8%, transparent); color: var(--warn); }
.banner-info { border-color: color-mix(in srgb, var(--info) 35%, transparent); background: color-mix(in srgb, var(--info) 8%, transparent); color: var(--info); }

/* ================= 模态框 ================= */

.modal-overlay {
  position: fixed; inset: 0; z-index: 50;
  display: grid; place-items: center;
  padding: var(--sp-4);
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.modal-overlay[hidden] { display: none; }
.modal-overlay.is-open { opacity: 1; }

.modal {
  width: 100%; max-width: 440px;
  max-height: calc(100dvh - var(--sp-6));
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--bg-elev-1);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-l);
  padding: var(--sp-5);
  box-shadow: var(--shadow-2);
  transform: scale(.97);
  transition: transform var(--dur-base) var(--ease-out);
}
.modal-overlay.is-open .modal { transform: scale(1); }
.modal-overlay.is-closing { opacity: 0; transition-duration: var(--dur-fast); transition-timing-function: var(--ease-in); }
.modal-overlay.is-closing .modal { transform: scale(.97); transition-duration: var(--dur-fast); transition-timing-function: var(--ease-in); }

.modal h2 { font-size: 20px; margin-bottom: var(--sp-3); }
.modal .modal-body { color: var(--text-dim); font-size: 14px; display: flex; flex-direction: column; gap: var(--sp-3); }
.modal .modal-actions { display: flex; gap: var(--sp-3); margin-top: var(--sp-5); }
.modal .modal-actions .btn { flex: 1; }
.modal .impact {
  border: 1px solid var(--line); border-radius: var(--radius-s);
  padding: var(--sp-3); font-size: 13px; color: var(--text-dim);
  background: var(--bg-elev-2);
  display: flex; flex-direction: column; gap: var(--sp-1);
}

/* 横屏矮屏:弹窗必须能滚,确认按钮不能被裁 */
@media (max-height: 450px) {
  .modal-overlay { place-items: start center; }
  .modal { max-height: calc(100dvh - var(--sp-4)); margin: var(--sp-2) 0; }
}

/* 弹窗打开时锁滚动,body 加 .modal-open 由 JS 处理 */
body.modal-open { overflow: hidden; }

/* ================= Toast ================= */

.toast-region {
  position: fixed; left: var(--sp-4); right: var(--sp-4); z-index: 60;
  bottom: calc(56px + var(--sp-4) + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: var(--sp-2);
  pointer-events: none;
}
@media (min-width: 1024px) {
  .toast-region { left: auto; right: var(--sp-5); bottom: var(--sp-5); width: 340px; }
}
.toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-s);
  border: 1px solid var(--line-strong);
  background: var(--bg-elev-1);
  box-shadow: var(--shadow-2);
  font-size: 14px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.toast.is-in { opacity: 1; transform: translateY(0); }
.toast.is-out { opacity: 0; transform: translateY(8px); transition-duration: var(--dur-fast); transition-timing-function: var(--ease-in); }
.toast .t-icon { flex: none; margin-top: 1px; }
.toast.ok    .t-icon { color: var(--accent); }
.toast.err   .t-icon { color: var(--danger); }
.toast.warn  .t-icon { color: var(--warn); }
.toast .t-main { flex: 1; min-width: 0; }
.toast .t-title { font-weight: 500; }
.toast .t-desc { font-size: 12px; color: var(--text-dim); margin-top: 2px; }
.toast .t-close {
  background: none; border: 0; color: var(--text-mute); cursor: pointer;
  padding: var(--sp-1); min-width: 24px; min-height: 24px;
  display: grid; place-items: center; border-radius: var(--radius-s);
}

/* ================= 骨架屏 ================= */

.sk {
  background: linear-gradient(90deg, var(--bg-elev-2) 25%, var(--line) 37%, var(--bg-elev-2) 63%);
  background-size: 400% 100%;
  animation: sk-shine 1.4s ease-in-out infinite;
  border-radius: var(--radius-s);
}
@keyframes sk-shine { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.sk-line { height: 12px; }
.sk-title { height: 20px; width: 40%; }
.sk-num { height: 28px; width: 56px; }
.sk-row { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) 0; }

/* ================= 五种数据状态 ================= */

.state {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--sp-3); padding: var(--sp-6) var(--sp-4);
}
.state .s-icon {
  width: 48px; height: 48px; display: grid; place-items: center;
  border-radius: var(--radius-m); border: 1px solid var(--line);
  background: var(--bg-elev-2); color: var(--text-dim);
}
.state .s-title { font-size: 16px; font-weight: 500; }
.state .s-desc { font-size: 13px; color: var(--text-dim); max-width: 32em; }

/* ================= 动效 ================= */

/* 入场:opacity + translateY,220ms ease-out */
@keyframes enter-up {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.enter { animation: enter-up var(--dur-base) var(--ease-out) both; }

/* 列表 stagger:每项 40ms,最多前 8 项 */
.stagger > * { animation: enter-up var(--dur-base) var(--ease-out) both; }
.stagger > *:nth-child(1) { animation-delay: 0ms; }
.stagger > *:nth-child(2) { animation-delay: 40ms; }
.stagger > *:nth-child(3) { animation-delay: 80ms; }
.stagger > *:nth-child(4) { animation-delay: 120ms; }
.stagger > *:nth-child(5) { animation-delay: 160ms; }
.stagger > *:nth-child(6) { animation-delay: 200ms; }
.stagger > *:nth-child(7) { animation-delay: 240ms; }
.stagger > *:nth-child(8) { animation-delay: 280ms; }
.stagger > *:nth-child(n+9) { animation-delay: 280ms; }

/* 数字/状态局部更新:300ms 内平滑过渡,不整页重渲染 */
.flash { transition: color var(--dur-slow) var(--ease-io); }
.flash.is-updated { color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .enter, .stagger > * { animation: none !important; opacity: 1; transform: none; }
}

/* ================= 页面级组件 ================= */

/* 服务器信息卡:地址可点击复制 */
.hero-card { display: flex; align-items: flex-start; gap: var(--sp-4); flex-wrap: wrap; }
.hero-right { display: flex; flex-direction: column; align-items: flex-end; gap: var(--sp-2); text-align: right; }

.addr-btn {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: 44px; margin-top: 2px; padding: 0; max-width: 100%;
  background: none; border: 0; color: var(--text);
  font-family: inherit; font-size: 20px; font-weight: 600;
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
  cursor: pointer; border-radius: var(--radius-s);
  transition: color var(--dur-fast) var(--ease-io);
}
.addr-btn:hover { color: var(--accent); }
.addr-btn .icon-slot { display: inline-flex; color: var(--text-mute); }
.addr-btn:hover .icon-slot { color: var(--accent); }

/* 尚未开放的入口:明确不可点,不假装可点 */
.is-soon {
  display: flex; align-items: center; gap: var(--sp-2);
  color: var(--text-mute); opacity: .5; cursor: default;
}
.sidebar .is-soon { padding: var(--sp-3); min-height: 44px; border-radius: var(--radius-s); font-size: 14px; }
.tabbar .is-soon {
  flex-direction: column; justify-content: center; align-items: center;
  gap: 2px; min-height: 44px; font-size: 12px;
}
@media (min-width: 768px) {
  .tabbar .is-soon { flex-direction: row; gap: var(--sp-2); font-size: 14px; padding: var(--sp-3) 0; }
}

/* 数值变化时的短暂着色(300ms 内恢复) */
.is-updated { color: var(--accent); }

/* ================= 表单页 / 用户区 ================= */

/* 窄栏居中:登录、注册这类单表单页面 */
.auth-wrap { max-width: 420px; margin: 0 auto; }
.auth-wrap .lead { color: var(--text-dim); margin: var(--sp-2) 0 var(--sp-5); }

/* 顶部用户区:管理后台按钮 / 用户名 / 退出 三件套统一高度与字号。
   原来按钮 36px 挨着名片 44px、字号又散着 13/14/12,基线错开、大小不一。
   头像已移除:昵称前两字作头像时,两字昵称会与旁边的用户名完全重复。 */
.user-area { display: flex; align-items: center; gap: var(--sp-2); flex: none; margin-left: auto; font-size: 13px; line-height: 1; }
.user-area .btn-sm { min-height: 34px; }
.user-chip {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: 34px; padding: 0 var(--sp-2); max-width: 220px;
  border-radius: var(--radius-s); color: var(--text); text-decoration: none;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-io);
}
.user-chip:hover { background: var(--bg-elev-2); text-decoration: none; }
.user-chip .ellipsis { font-size: 13px; font-weight: 500; }
/* 「管理员」角标与按钮同字号,不再一小一大 */
.user-area .tag { height: 22px; padding: 0 var(--sp-2); font-size: 13px; }

.banner-danger {
  border-color: color-mix(in srgb, var(--danger) 35%, transparent);
  background: color-mix(in srgb, var(--danger) 8%, transparent);
  color: var(--danger);
}
.banner-ok {
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  color: var(--accent);
}

/* 申请状态卡 */
.status-head { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.status-head .s-icon {
  width: 44px; height: 44px; flex: none; display: grid; place-items: center;
  border-radius: var(--radius-m); border: 1px solid var(--line); background: var(--bg-elev-2);
}
.status-head .s-icon.ok { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.status-head .s-icon.wait { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.status-head .s-icon.bad { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
.status-head .s-text { min-width: 0; }
.status-head .s-text h2 { font-size: 20px; }
.status-head .s-text p { color: var(--text-dim); font-size: 13px; margin-top: var(--sp-1); }

.kv { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-2) var(--sp-4); font-size: 14px; }
.kv dt { color: var(--text-dim); }
.kv dd { margin: 0; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }

/* 可折叠的文件清单 */
.filelist > summary {
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: 44px; cursor: pointer; list-style: none;
  color: var(--text-dim); font-size: 14px;
  transition: color var(--dur-fast) var(--ease-io);
}
.filelist > summary::-webkit-details-marker { display: none; }
.filelist > summary::before {
  content: ''; flex: none; width: 0; height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform var(--dur-fast) var(--ease-io);
}
.filelist[open] > summary::before { transform: rotate(90deg); }
.filelist > summary:hover { color: var(--text); }

/* 进度条(成就进度) */
.progress {
  height: 8px; border-radius: 999px; overflow: hidden;
  background: var(--bg-elev-2); border: 1px solid var(--line);
}
.progress-bar {
  height: 100%; background: var(--accent);
  transition: width var(--dur-slow) var(--ease-out);
}

/* ================= 帮助中心:知识库 + AI 小助手 ================= */

/* 分段切换:两个并列标签 */
.seg {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-1);
  padding: var(--sp-1); max-width: 100%;
  background: var(--bg-elev-1); border: 1px solid var(--line);
  border-radius: var(--radius-s);
}
@media (min-width: 768px) { .seg { width: min(100%, 380px); } }

.seg-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-width: 0; min-height: 44px; padding: 0 var(--sp-3);
  background: transparent; border: 1px solid transparent; border-radius: var(--radius-s);
  color: var(--text-dim); font-family: inherit; font-size: 14px; font-weight: 500;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-io), color var(--dur-fast) var(--ease-io),
              border-color var(--dur-fast) var(--ease-io);
}
.seg-btn:hover { background: var(--bg-elev-2); color: var(--text); }
.seg-btn[aria-selected="true"] {
  background: var(--bg-elev-2); border-color: var(--line-strong); color: var(--text);
}
.seg-btn[aria-selected="true"] svg { color: var(--accent); }

/* 分段内容:切换时淡入 + 8px 上移(220ms,只动 opacity / transform) */
.help-panel { min-width: 0; }
.help-panel.panel-enter { animation: panel-in var(--dur-base) var(--ease-out) both; }
@keyframes panel-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* 目录 + 正文:窄屏单列,桌面(≥1024px)左栏常驻 */
.help-split { display: grid; gap: var(--sp-4); grid-template-columns: minmax(0, 1fr); }
.help-index { min-width: 0; }
.help-index-card { padding: var(--sp-2); }
.help-index-list { display: flex; flex-direction: column; gap: 2px; }

.help-index-item {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  width: 100%; min-height: 44px; padding: var(--sp-2) var(--sp-3);
  background: transparent; border: 1px solid transparent; border-radius: var(--radius-s);
  color: var(--text-dim); font-family: inherit; font-size: 14px; text-align: left;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-io), color var(--dur-fast) var(--ease-io),
              border-color var(--dur-fast) var(--ease-io);
}
.help-index-item:hover { background: var(--bg-elev-2); color: var(--text); }
.help-index-item[aria-current="true"] {
  background: var(--bg-elev-2); border-color: var(--line-strong); color: var(--text);
}
.help-index-item .hi-icon { flex: none; display: inline-flex; margin-top: 2px; }
.help-index-item[aria-current="true"] .hi-icon { color: var(--accent); }
.help-index-item .hi-text { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.help-index-item .hi-title { font-weight: 500; overflow-wrap: anywhere; }
.help-index-item .hi-sub { font-size: 12px; color: var(--text-mute); overflow-wrap: anywhere; }

@media (min-width: 1024px) {
  .help-split { grid-template-columns: 264px minmax(0, 1fr); gap: var(--sp-5); align-items: start; }
  .help-index { position: sticky; top: 84px; }
  .help-index-card { max-height: calc(100dvh - 168px); overflow-y: auto; overscroll-behavior: contain; }
}

/* Markdown 正文(renderMarkdown 的输出) */
.md { font-size: 14px; line-height: 1.75; color: var(--text-dim); overflow-wrap: anywhere; }
.md > * + * { margin-top: var(--sp-3); }
.md > *:first-child { margin-top: 0; }
.md .md-h { margin-top: var(--sp-5); color: var(--text); }
.md .md-h1 { font-size: 20px; }
.md .md-h2 { font-size: 16px; }
.md .md-h3 { font-size: 14px; }
.md strong { font-weight: 600; color: var(--text); }
.md a { overflow-wrap: anywhere; }
.md .md-ul, .md .md-ol {
  margin: 0; padding-left: 22px;
  display: flex; flex-direction: column; gap: var(--sp-1);
}
.md li::marker { color: var(--text-mute); }
.md .md-code {
  padding: 1px 5px; border-radius: var(--radius-s);
  border: 1px solid var(--line); background: var(--bg-elev-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px; overflow-wrap: anywhere;
}
.md .md-pre {
  margin: 0; padding: var(--sp-3); border-radius: var(--radius-s);
  border: 1px solid var(--line); background: var(--bg-elev-2);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.md .md-pre .md-code {
  display: block; padding: 0; border: 0; background: none;
  white-space: pre-wrap; overflow-wrap: anywhere;
}

/* 对话区 */
.ai-shell { display: flex; flex-direction: column; gap: var(--sp-3); }
.ai-head { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.ai-log {
  display: flex; flex-direction: column; gap: var(--sp-3);
  min-height: 0; max-height: min(58dvh, 520px);
  overflow-y: auto; overscroll-behavior: contain;
  padding: var(--sp-1) 2px;
}
.ai-msg { display: flex; flex-direction: column; gap: var(--sp-1); max-width: 88%; min-width: 0; }
.ai-msg.user { align-self: flex-end; align-items: flex-end; }
.ai-msg.assistant { align-self: flex-start; align-items: flex-start; }
.ai-bubble {
  min-width: 0; max-width: 100%;
  padding: var(--sp-3);
  border: 1px solid var(--line); border-radius: var(--radius-m);
  background: var(--bg-elev-2);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.ai-msg.user .ai-bubble {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-color: color-mix(in srgb, var(--accent) 30%, transparent);
}
.ai-msg.assistant .ai-bubble:not(.is-streaming) { white-space: normal; }
.ai-bubble > * + * { margin-top: var(--sp-2); }
.ai-meta { font-size: 12px; color: var(--text-mute); }
.ai-note { font-size: 12px; color: var(--warn); overflow-wrap: anywhere; }
.ai-note.err { color: var(--danger); }

/* 打字光标:等待期只闪一个方块,不做满屏 loading */
.ai-cursor {
  display: inline-block; width: 8px; height: 15px; margin-left: 3px;
  vertical-align: -2px; border-radius: 2px; background: var(--accent);
  animation: ai-caret var(--dur-slow) var(--ease-io) infinite alternate;
}
@keyframes ai-caret { from { opacity: 1; } to { opacity: .15; } }

/* 建议问题 */
/* 预选问题(.ai-suggests / .ai-chip)已于 2026-09-22 按主人要求移除,
   连同 help.html 的容器与 help.js 的 SUGGESTS 一并删除。 */

/* 输入区:自适应高度、手机字号 ≥16px(防 iOS 聚焦放大) */
.ai-compose {
  display: flex; align-items: flex-end; gap: var(--sp-2); flex-wrap: wrap;
  padding-bottom: env(safe-area-inset-bottom);
}
.ai-compose .textarea {
  flex: 1 1 180px; min-width: 0; min-height: 44px; max-height: 168px;
  padding: var(--sp-2) var(--sp-3); line-height: 1.5; resize: none;
}
.ai-compose .btn { flex: none; }

/* ================= 预览页专用(不进生产) ================= */

.pv-section { margin-top: var(--sp-6); }
.pv-section > h2 { margin-bottom: var(--sp-1); }
.pv-note { font-size: 12px; color: var(--text-mute); margin-bottom: var(--sp-3); }
.pv-grid { display: grid; gap: var(--sp-3); grid-template-columns: 1fr; }
@media (min-width: 768px) { .pv-grid { grid-template-columns: repeat(2, 1fr); } }
.pv-swatches { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.pv-swatch { display: flex; flex-direction: column; gap: var(--sp-1); font-size: 12px; color: var(--text-dim); }
.pv-swatch i { display: block; width: 72px; height: 44px; border-radius: var(--radius-s); border: 1px solid var(--line-strong); }
.pv-toolbar {
  position: sticky; top: 56px; z-index: 20;
  display: flex; flex-wrap: wrap; gap: var(--sp-2);
  padding: var(--sp-3); margin-bottom: var(--sp-4);
  background: var(--bg-elev-1); border: 1px solid var(--line); border-radius: var(--radius-m);
}
.pv-panel { display: none; }
.pv-panel.is-active { display: block; }

/* ================= 我的外观:五套预设皮肤 ================= */

.slot-grid {
  display: grid; gap: var(--sp-3); margin-top: var(--sp-3);
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
}

.slot-card {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3);
  border: 1px solid var(--line); border-radius: var(--radius-m);
  background: var(--bg-elev-1);
  transition: border-color var(--dur-fast) var(--ease-io);
}
.slot-card.active {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, var(--bg-elev-1));
}
.slot-card .slot-head { font-size: 12px; font-weight: 600; color: var(--text-dim); }
.slot-card.active .slot-head { color: var(--accent); }

.slot-stage {
  display: grid; place-items: center;
  width: 100%; height: 200px;
  border-radius: var(--radius-s); background: var(--bg-elev-2);
}
/* 触摸旋转与页面滚动必须共存:
   竖直方向交还给页面滚动(浏览器接管后会发 pointercancel,旋转自然停下),
   水平方向才归 OrbitControls 旋转 —— 这才是手机上「能转、也能滑」的手感。
   !important 是为了压过 OrbitControls 在构造函数里写下的内联
   style.touchAction="none"(见 vendor/skinview3d.bundle.js);它只用 pointer
   事件、拖拽中不调 preventDefault,所以 touch-action 在这里说了算。 */
.slot-stage canvas { display: block; cursor: grab; touch-action: pan-y !important; }
.slot-stage canvas:active { cursor: grabbing; }

.slot-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-1); }

/* ================= 移动端细节(≤767px,桌面端不受影响) ================= */

@media (max-width: 767px) {
  /* 网格列一律 minmax(0,1fr):裸 1fr 的下限是 min-content,
     一个长数字 / UUID / 网址就能把整行撑得比屏幕宽,
     屏幕上于是多出一条能左右拖的空白。 */
  .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-2 { grid-template-columns: minmax(0, 1fr); }

  /* 皮肤槽位:一行摆两个。窄屏(≤320px)原来 148px 的下限会挤成单列,
     5 个槽位就变成五行、近千像素的拖拽区。132px 让它在小屏上也是两列。 */
  .slot-grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: var(--sp-2); }
  /* 画布在手机端缩到 108×144(见 me.js mountViewer),舞台高度跟着收 */
  .slot-stage { height: 168px; }

  /* 触控目标补到 40px(小按钮原本 36px,手指按不准) */
  .btn-sm { min-height: 40px; }

  /* 表格标签列收窄,内容多留一点宽度 */
  .table td::before { flex: 0 0 72px; }

  /* 吸顶工具条要跟着 topbar 的真实高度走(含刘海安全区) */
  .pv-toolbar { top: calc(52px + env(safe-area-inset-top)); }

  /* ---- 顶栏 ----
     2026-09-22 起顶栏只留功能项(刷新 / 后台入口 / 身份 / 退出),模块名与在线人数已移除:
     394px 屏只需约 253px、320px 屏也放得下,所以回到**单行**。
     仍保留 wrap 作为极端情况的兜底 —— 名字超长时宁可折行,也不要撑破屏幕。
     文字一律 nowrap:flex 子项默认可收缩,而中文的 min-content 就是「一个字」,
     不锁住会被压成一列竖排字。 */
  .topbar { flex-wrap: wrap; column-gap: var(--sp-2); row-gap: var(--sp-1); }
  .topbar .status, .topbar .caption, .topbar .btn, .user-area { flex: none; }
  .topbar #btn-refresh { padding: 0 var(--sp-2); }
  .topbar #btn-refresh .btn-label { display: none; }   /* 刷新收成纯图标 */
  .user-area .btn-sm, .user-chip { min-height: 40px; }
  .user-chip { max-width: 150px; }

  /* ---- 服务器信息卡:手机上改成竖排 ----
     原来是左右两栏,右侧「今日/累计运行」会把地址挤到只剩几十像素,
     `115.159.206.224:25565` 这种长串就被拆成三行(还从数字中间断开)。 */
  .hero-card { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
  .hero-card .grow { flex: none; }
  .hero-right { align-items: flex-start; text-align: left; }
  .addr-btn { font-size: 18px; }                        /* 再收一号,窄屏也放得下整串 */

  /* ---- AI 对话:手机上取消内层滚动 ----
     原来 .ai-log 是个 max-height:58dvh 的内滚动容器,还带 overscroll-behavior:contain:
     手势全被它吃掉,滚到顶/底又被 contain 卡住不让链给页面 —— 于是「想滚页面没处下手」
     (与 3D 皮肤预览同一类毛病)。手机上改成整页只有一个滚动条,历史跟着页面走。
     桌面的内滚动保持不变。新消息的自动滚动由 help.js 的 scrollLog() 分流处理。 */
  .ai-log { max-height: none; overflow-y: visible; overscroll-behavior: auto; }

  /* 输入区吸底:历史跟着页面走之后,输入框不能跟着沉到几屏之外。
     吸在底部 tab 之上;横向用负外边距铺满卡片内边距,免得对话内容从两侧缝隙透出来。
     背景与 .card 同为 --bg-elev-1,所以方角不会在卡片圆角处留下痕迹。 */
  .ai-compose {
    position: sticky;
    bottom: calc(56px + env(safe-area-inset-bottom));
    z-index: 6;
    margin: 0 calc(-1 * var(--sp-4));
    padding: var(--sp-3) var(--sp-4);
    background: var(--bg-elev-1);
  }
}
