/* ════════════════════════════════════════════════
   云盘 SPA — style.css v2.0
   蓝白配色，高仿夸克网盘风格
   ════════════════════════════════════════════════ */

/* 令牌已抽离至 tokens.css（与主站 app.ynshw.com.cn 对齐）—— 本文件不再定义颜色字面量 */

/* ── Reset ─────────────────────────────────────── */
*,*::before,*::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 15px; -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--ys-font);
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
  overflow: hidden;
  height: 100dvh;
  overscroll-behavior: none;
}
a { text-decoration: none; color: inherit; }
button { border: none; background: none; cursor: pointer; font: inherit; }
input, textarea, select { font: inherit; outline: none; border: none; }
ul { list-style: none; }
img { display: block; max-width: 100%; }

/* ── App Shell ─────────────────────────────────── */
#app {
  position: relative;
  width: 100%;
  height: 100dvh;
  overflow: hidden;
  background: var(--bg-card);
}

/* ── Splash ────────────────────────────────────── */
#splash {
  position: absolute; inset: 0; z-index: 999;
  background: linear-gradient(145deg, var(--ys-brand) 0%, var(--ys-brand-dark) 100%);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 16px;
}
#splash .splash-icon { font-size: 4rem; }
#splash .splash-title { font-size: 1.5rem; font-weight: 700; color: #fff; }
#splash .splash-sub   { font-size: .85rem; color: rgba(255,255,255,.65); }

/* ── Loading overlay ───────────────────────────── */
#global-loading {
  position: fixed; inset: 0; z-index: 990;
  background: rgba(255,255,255,.5);
  display: none; align-items: center; justify-content: center;
}
.loading-spin {
  width: 36px; height: 36px;
  border: 3px solid var(--primary-light);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Toast ─────────────────────────────────────── */
.toast {
  position: fixed; top: 20px; left: 50%; transform: translateX(-50%) translateY(-10px);
  z-index: 9999; padding: 10px 20px;
  background: rgba(30,30,30,.9); color: #fff;
  border-radius: 20px; font-size: .85rem;
  white-space: nowrap; pointer-events: none;
  opacity: 0; transition: all .25s;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.toast-success { background: rgba(43, 182, 115,.9); }
.toast.toast-error   { background: rgba(255, 82, 82,.9); }
.toast.toast-warn    { background: rgba(245, 166, 35,.9); }

/* ── Auth Page ─────────────────────────────────── */
#auth-page {
  position: absolute; inset: 0; z-index: 100;
  background: #fff;
  display: flex; flex-direction: column;
  overflow-y: auto;
}
.auth-hero {
  background: var(--ys-brand-grad);
  padding: 56px 24px 52px;
  text-align: center; color: #fff;
  position: relative; overflow: hidden;
}
.auth-hero::before {
  content: ''; position: absolute; top: -40px; right: -40px;
  width: 180px; height: 180px; border-radius: 50%;
  background: rgba(255,255,255,.08);
}
.auth-hero::after {
  content: ''; position: absolute; bottom: -60px; left: -30px;
  width: 220px; height: 220px; border-radius: 50%;
  background: rgba(255,255,255,.06);
}
.auth-hero .hero-icon {
  font-size: 4rem; margin-bottom: 14px; position: relative; z-index: 1;
  filter: drop-shadow(0 4px 12px rgba(0,0,0,.2));
}
.auth-hero .hero-title {
  font-size: 1.65rem; font-weight: 800; letter-spacing: .5px;
  position: relative; z-index: 1;
}
.auth-hero .hero-sub {
  font-size: .82rem; opacity: .8; margin-top: 6px;
  position: relative; z-index: 1;
}
.auth-box {
  flex: 1; padding: 32px 24px 24px;
  background: #fff; border-radius: 24px 24px 0 0;
  margin-top: -20px;
  box-shadow: 0 -4px 24px rgba(var(--ys-brand-rgb),.08);
}
.auth-tabs {
  display: flex; border-bottom: 1px solid var(--ys-line-soft); margin-bottom: 28px;
  gap: 4px;
}
.auth-tab  {
  flex: 1; padding: 11px; text-align: center;
  font-size: .92rem; color: var(--ys-ink-5); cursor: pointer;
  border-bottom: 2.5px solid transparent; margin-bottom: -1px;
  transition: all .2s; font-weight: 500;
}
.auth-tab.active { color: var(--primary); border-bottom-color: var(--primary); font-weight: 700; }
.auth-form { display: none; }
.auth-form.active { display: block; }
.field-group { position: relative; margin-bottom: 16px; }
.field-group label {
  display: block; font-size: .78rem; color: var(--text-2);
  margin-bottom: 6px; font-weight: 500;
}
.field-group input {
  width: 100%; padding: 13px 16px;
  background: #f7f9ff; border-radius: 10px;
  font-size: .95rem; color: var(--text);
  border: 1.5px solid #e6ecff; transition: all .2s;
}
.field-group input:focus {
  border-color: var(--primary); background: #fff;
  box-shadow: 0 0 0 3px rgba(var(--ys-brand-rgb),.1);
}
.btn-submit {
  width: 100%; padding: 15px;
  background: linear-gradient(135deg, var(--ys-brand), var(--ys-brand-dark)); color: #fff;
  border-radius: 12px; font-size: .98rem; font-weight: 700;
  margin-top: 8px;
  box-shadow: 0 4px 18px rgba(var(--ys-brand-rgb),.35);
  transition: all .2s;
}
.btn-submit:active { transform: scale(.98); box-shadow: 0 2px 10px rgba(var(--ys-brand-rgb),.2); }
.auth-hint { text-align: center; font-size: .82rem; color: var(--text-3); margin-top: 18px; }
.auth-hint span { color: var(--primary); cursor: pointer; font-weight: 600; }

/* ── Main App ──────────────────────────────────── */
#main-app {
  position: absolute; inset: 0; z-index: 50;
  display: flex; flex-direction: column; overflow: hidden;
}
/* ── 页面滚动容器 ──────────────────────────────────────
   #main-app 是「定高 flex 列 + overflow:hidden」，它在流内只有一个子元素
   #page-content。因此 #page-content 自己必须也是「定高 flex 列」，
   下面 .page-body{flex:1;overflow-y:auto} 才拿得到可分配高度。
   ⛔ 缺这条规则时的表现： #page-content 退化成普通 block（height=内容高度），
   内容溢出 #main-app 后被 overflow:hidden 裁掉 —— 手势完全滚不动，
   只有程序化设置 scrollTop 才动（所以「看起来有滚动条/能滚」是假象）。
   同款写法见 .page-overlay（那边一直是完整的）。*/
#page-content {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.page-body {
  flex: 1; overflow-y: auto; overflow-x: hidden;
  padding-bottom: var(--nav-h);
  -webkit-overflow-scrolling: touch;
}
.page-body::-webkit-scrollbar { display: none; }

/* ── Bottom Nav ────────────────────────────────── */
.bottom-nav {
  position: fixed; bottom: 0; left: 0; right: 0;
  height: var(--nav-h);
  background: #fff;
  border-top: 1px solid var(--border);
  display: flex; z-index: 80;
  padding-bottom: env(safe-area-inset-bottom, 0);
}
/* 浮层内嵌版底栏（搜索页）：不吃 fixed，作为 flex 列的最后一项贴在浮层底部 */
.bottom-nav.nav-embed {
  position: static; left: auto; right: auto; bottom: auto;
  flex-shrink: 0; z-index: auto;
}
.nav-item {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 3px;
  cursor: pointer; position: relative;
  color: var(--text-3); transition: color .2s;
}
.nav-item.active { color: var(--primary); }
.nav-item svg { width: 22px; height: 22px; stroke: currentColor; fill: none;
                stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.nav-item span { font-size: .68rem; }
.nav-badge {
  position: absolute; top: 6px; right: calc(50% - 16px);
  background: var(--ys-danger); color: #fff;
  font-size: .6rem; min-width: 16px; height: 16px;
  border-radius: 8px; display: flex; align-items: center; justify-content: center;
  padding: 0 4px; line-height: 1;
}

/* ── Page Header ───────────────────────────────── */
.page-header {
  height: var(--header-h);
  background: #fff;
  display: flex; align-items: center;
  padding: 0 16px; gap: 10px;
  position: sticky; top: 0; z-index: 60;
  border-bottom: 1px solid var(--border);
}
.page-header h1 { flex: 1; font-size: 1.05rem; font-weight: 700; color: var(--text); }
.hdr-btn {
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; color: var(--text-2); cursor: pointer;
  transition: background .2s;
  position: relative;                 /* 供顶栏铃铛未读角标定位 */
}
.hdr-btn:active { background: var(--bg); }
/* 顶栏铃铛未读角标。
   ⚠️ 必须与底栏 .nav-badge 分开：setNavBadge() 是「把页面上所有 .nav-badge
      统一改成会话未读数」，铃铛若复用该类会被 30s 轮询改写成串号数字。 */
.hdr-badge {
  position: absolute; top: 0; right: 0;
  background: var(--ys-danger); color: #fff;
  font-size: .58rem; font-weight: 600; line-height: 1;
  min-width: 15px; height: 15px; padding: 0 3px;
  border-radius: 8px; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid #fff;
  pointer-events: none;               /* 角标不吃点击，点击仍落在铃铛上 */
}
.hdr-btn svg { width: 20px; height: 20px; stroke: currentColor; fill: none;
               stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

/* ══════════════════════════════════════════════════
   HOME PAGE
   ══════════════════════════════════════════════════ */
.home-search {
  margin: 14px 16px 0;
  background: var(--bg);
  border-radius: 20px;
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px;
}
.home-search svg { width: 18px; height: 18px; stroke: var(--text-3); fill: none;
                   stroke-width: 1.8; flex-shrink: 0; }
.home-search input {
  flex: 1; font-size: .88rem; color: var(--text);
  background: transparent;
}
.home-search input::placeholder { color: var(--text-4); }

.home-categories {
  display: grid; grid-template-columns: repeat(5, 1fr);
  gap: 12px; padding: 16px 16px 8px;
}
.cat-item {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  cursor: pointer;
}
.cat-icon {
  width: 48px; height: 48px;
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.4rem;
}
.cat-icon.c-photo  { background: #fff3e0; }
.cat-icon.c-video  { background: #e8f0fe; }
.cat-icon.c-music  { background: #fce4ec; }
.cat-icon.c-doc    { background: #e8f5e9; }
.cat-icon.c-zip    { background: #fce8e4; }
.cat-icon.c-app     { background: #e0f7fa; }
.cat-icon.c-ebook   { background: #e9e5ff; }
.cat-icon.c-font    { background: #fdf2f8; }
.cat-icon.c-torrent { background: #ccfbf1; }
.cat-icon.c-other   { background: #f1f5f9; }
.cat-item span { font-size: .7rem; color: var(--text-2); }

.section-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px 8px;
}
.section-header .sh-title { font-size: .9rem; font-weight: 600; color: var(--text); }
.section-header .sh-more  { font-size: .8rem; color: var(--primary); cursor: pointer; }

.recent-grid {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 2px; padding: 0 16px 16px;
}
.recent-item {
  aspect-ratio: 1; background: var(--bg);
  border-radius: var(--radius-sm); overflow: hidden;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 4px;
  cursor: pointer; font-size: 2rem;
  position: relative;
}
.recent-item span.ri-name {
  position: absolute; bottom: 0; left: 0; right: 0;
  font-size: .6rem; color: var(--text-2);
  background: rgba(255,255,255,.85);
  text-align: center; padding: 2px 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.empty-tip {
  display: flex; flex-direction: column; align-items: center;
  padding: 60px 24px; gap: 12px; color: var(--text-3);
}
.empty-tip .empty-icon {
  width: 80px; height: 80px;
  background: var(--primary-light);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 2rem;
}
.empty-tip p { font-size: .88rem; }

/* ══════════════════════════════════════════════════
   FILE PAGE
   ══════════════════════════════════════════════════ */
.breadcrumb {
  padding: 10px 16px;
  display: flex; align-items: center; gap: 4px;
  overflow-x: auto; white-space: nowrap;
  font-size: .8rem; color: var(--text-3);
  scrollbar-width: none;
}
.breadcrumb::-webkit-scrollbar { display: none; }
.bc-item { cursor: pointer; color: var(--text-3); flex-shrink: 0; }
.bc-item:last-child { color: var(--text); font-weight: 500; }
.bc-sep { flex-shrink: 0; }
.bc-cur { color: var(--text); font-weight: 500; flex-shrink: 0; }

/* ── 分类筛选 chips（全部 / 图片 / 视频 / 音乐 / 文档 / 压缩 / 应用 / 电子书 / 字体 / 种子 / 其他） ── */
/* 11 类采用「折行」排布：窄屏无需横向滑动即可一屏看全（桌面端宽裕时仍呈现为单行） */
.filter-chips {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 0 16px 10px;
}
/* 折行后适度收紧水平内边距与字号：桌面端回到单行、窄屏压在 2 行，避免出现「孤行尾项」；
   垂直内边距保持 5px，确保触摸目标 29px 不缩水。
   限定作用域，避免影响订单页 .ord-chips（同为 .fchip 胶囊语言，需保持原尺寸） */
.filter-chips .fchip { padding: 5px 9px; font-size: .74rem; }
.fchip {
  flex: 0 0 auto;
  padding: 5px 14px;
  border-radius: 999px;
  background: var(--bg);
  border: 1px solid var(--border-2);
  color: var(--text-2);
  font-size: .78rem;
  cursor: pointer;
}
.fchip:active { opacity: .8; }
.fchip.active {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--ys-ink-on-brand);
  font-weight: 500;
}

.file-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 16px; gap: 8px;
}
.file-sort { display: flex; align-items: center; gap: 6px; font-size: .78rem; color: var(--text-3); cursor: pointer; }
.file-views { display: flex; gap: 6px; }
.view-btn { width: 28px; height: 28px; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: var(--text-3); }
.view-btn.active { color: var(--primary); background: var(--primary-light); }
.view-btn svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.8; }

.file-list  { padding: 0 16px; }
.file-grid  { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; padding: 8px 16px; }

.file-item {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--border);
  cursor: pointer; position: relative; -webkit-tap-highlight-color: transparent;
}
.file-item:last-child { border-bottom: none; }
.file-item:active { background: var(--bg); margin: 0 -16px; padding: 10px 16px; border-radius: var(--radius-sm); }

.file-item.selected .file-icon-wrap::before {
  content: '✓';
  position: absolute; inset: 0;
  background: var(--primary); color: #fff;
  display: flex; align-items: center; justify-content: center;
  border-radius: 10px; font-size: .9rem; font-weight: 700;
  z-index: 1;
}
.file-icon-wrap { position: relative; width: 44px; height: 44px; flex-shrink: 0; }
.file-icon {
  width: 44px; height: 44px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.5rem;
}
/* file type colors */
.fi-folder { background: #fff8e1; }
.fi-image  { background: #fce4ec; }
.fi-video  { background: #e8eaf6; }
.fi-audio  { background: #f3e5f5; }
.fi-doc    { background: #e8f5e9; }
.fi-pdf    { background: #fff3e0; }
.fi-zip    { background: #fce8e4; }
.fi-other  { background: var(--bg); }
/* 2026-09-13 新增类型（应用 / 电子书 / 字体 / 种子 / 代码） */
.fi-app     { background: #e0f7fa; }
.fi-ebook   { background: #e9e5ff; }
.fi-font    { background: #fdf2f8; }
.fi-torrent { background: #ccfbf1; }
.fi-code    { background: #f1f5f9; }

.file-info { flex: 1; min-width: 0; }
.file-name { font-size: .9rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-meta { font-size: .72rem; color: var(--text-3); margin-top: 2px; }
.file-more { padding: 6px; color: var(--text-4); flex-shrink: 0; }
.file-more svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.8; }

/* Grid mode */
/* 网格项固定为正方形：尺寸只由列宽决定，绝不随文件名长短变化。
   ⚠️ aspect-ratio + min-width:0 + overflow:hidden 三者缺一不可，
   否则 nowrap 的文件名会成为 grid item 的 min-content，把 1fr 列撑开
   （表现为列宽不等、卡片变形、右侧内容溢出被裁）。 */
.file-grid-item {
  aspect-ratio: 1 / 1;
  min-width: 0;
  overflow: hidden;
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 10px 8px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.file-grid-item:active { opacity: .85; }
.file-grid-item.selected { background: var(--primary-lighter); box-shadow: inset 0 0 0 2px var(--primary); }
.file-grid-item .file-icon { width: 40px; height: 40px; flex-shrink: 0; }
.file-grid-item .file-name { font-size: .72rem; line-height: 1.4; text-align: center; color: var(--text);
                              width: 100%; min-width: 0; max-width: 100%;
                              overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 网格卡片同样需要「只有三点才弹菜单」的入口。
   绝对定位到右上角：卡片尺寸/布局不变，且触摸端无 hover，故常驻显示（弱化成 --text-4）。 */
.file-grid-item { position: relative; }
.file-grid-item .file-more { position: absolute; top: 2px; right: 2px; padding: 5px; line-height: 0; border-radius: 6px; }
.file-grid-item .file-more svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 1.8; }
.file-grid-item .file-more:active { background: rgba(0, 0, 0, .06); }

/* FAB upload */
.fab {
  position: fixed; bottom: calc(var(--nav-h) + 16px); right: 20px;
  width: 52px; height: 52px;
  background: var(--primary); color: #fff;
  border-radius: 50%; box-shadow: var(--shadow-deep);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.5rem; z-index: 65; cursor: pointer;
  transition: transform .2s; -webkit-tap-highlight-color: transparent;
}
.fab:active { transform: scale(.92); }
.fab svg { width: 24px; height: 24px; stroke: #fff; fill: none; stroke-width: 2; }

/* 上传按钮首次引导气泡。
   只在首次进入「文件」页显示（localStorage 记忆），6 秒后或用户任意点击即收起。
   定位：右侧 80px = 20(边距) + 52(按钮) + 8(间隙)；bottom 取 FAB 垂直中心
   （nav-h + 16 + 26），再用 translateY(50%) 把气泡自身高度的一半下压 ⇒ 与 FAB 垂直居中，
   不必知道气泡实际高度。小三角在右，指向 FAB。
   ⚠️ 宽屏下 #app 有 transform，会成为 position:fixed 后代的包含块 ⇒ 气泡与 FAB 一起
      自动落进居中框内，无需另加媒体查询。 */
.fab-tip {
  position: fixed;
  right: 80px;
  bottom: calc(var(--nav-h) + 42px);
  transform: translateY(50%) scale(.88);
  transform-origin: 100% 50%;
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--primary);
  color: #fff;
  font-size: .78rem;
  line-height: 1.35;
  white-space: nowrap;
  box-shadow: var(--shadow-deep);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .22s ease, transform .22s ease, visibility .22s;
  z-index: 66;                       /* 高于 .fab(65)，避免被按钮盖住 */
}
.fab-tip.in { opacity: 1; visibility: visible; transform: translateY(50%) scale(1); }
.fab-tip::after {
  content: ''; position: absolute; right: -5px; top: 50%; margin-top: -5px;
  border: 5px solid transparent; border-right: 0; border-left-color: var(--primary);
}

/* Batch bar */
.batch-bar {
  position: fixed; top: 0; left: 0; right: 0;
  height: var(--header-h); background: var(--primary);
  display: flex; align-items: center; padding: 0 16px; gap: 12px;
  z-index: 70; transform: translateY(-100%); transition: transform .25s;
}
.batch-bar.active { transform: translateY(0); }
.batch-bar .bb-cancel { color: #fff; font-size: .88rem; cursor: pointer; }
.batch-bar .bb-info   { flex: 1; color: #fff; font-size: .88rem; text-align: center; }
.batch-bar .bb-actions { display: flex; gap: 10px; }
.batch-bar .bb-btn {
  color: #fff; font-size: .82rem; cursor: pointer;
  padding: 5px 10px; border-radius: 6px; border: 1px solid rgba(255,255,255,.4);
}

/* Upload drop zone */
.upload-drop-zone {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(var(--ys-brand-rgb), .12);
  border: 3px dashed var(--primary);
  display: none; align-items: center; justify-content: center;
  flex-direction: column; gap: 12px;
  font-size: 1.1rem; color: var(--primary);
  pointer-events: none;
}
.upload-drop-zone.active { display: flex; }

/* Upload progress item */
.upload-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px; background: #fff;
  border-bottom: 1px solid var(--border);
}
.up-icon { font-size: 1.4rem; flex-shrink: 0; }
.up-info { flex: 1; min-width: 0; }
.up-name { font-size: .85rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.up-bar  { height: 4px; background: var(--bg); border-radius: 2px; margin-top: 5px; overflow: hidden; }
.up-fill { height: 100%; background: var(--primary); border-radius: 2px; transition: width .2s; }
.up-pct  { font-size: .72rem; color: var(--text-3); flex-shrink: 0; }

/* ══════════════════════════════════════════════════
   TRANSFER PAGE (Screenshot 2)
   ══════════════════════════════════════════════════ */
.transfer-tabs {
  display: flex; background: #fff;
  padding: 0 4px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto; scrollbar-width: none;
}
.transfer-tabs::-webkit-scrollbar { display: none; }
.tt-item {
  flex-shrink: 0; padding: 13px 18px;
  font-size: .88rem; color: var(--text-3); cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: all .2s; white-space: nowrap;
}
.tt-item.active { color: var(--primary); border-bottom-color: var(--primary); font-weight: 600; }

.transfer-banner {
  margin: 12px 16px;
  background: var(--primary-lighter);
  border-radius: var(--radius); padding: 14px;
  display: flex; align-items: center; gap: 12px;
  cursor: pointer;
}
.tb-icon {
  width: 40px; height: 40px; flex-shrink: 0;
  background: var(--primary-light); border-radius: 10px;
  display: flex; align-items: center; justify-content: center; font-size: 1.2rem;
}
.tb-text .tb-title { font-size: .9rem; font-weight: 600; color: var(--primary); }
.tb-text .tb-sub   { font-size: .75rem; color: var(--text-3); margin-top: 2px; }

/* 传输设置行：左 label + 右分段控件。
   为什么不用原生 <select>：① 只有 4 个离散值，平铺后一眼看全、一次点选到位；
   ② 原生下拉在移动端弹出系统级列表，风格与 App 胶囊/圆角语言割裂。
   与下方 .status-tabs 的层次区分：筛选器 = 描边胶囊 + 选中蓝底白字（大）；
   设置项 = 凹槽容器 + 选中白底蓝字（小）。 */
.concurrent-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 10px 16px; font-size: .82rem;
}
.concurrent-row .cr-label { color: var(--text-2); flex-shrink: 0; }

.seg-ctrl {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 3px; border-radius: 9px;
  /* 凹槽底要比白卡片深一档，否则白色选中块"浮"不出来（--ys-bg-sunken #f4f4f4 太浅） */
  background: var(--ys-line-strong);
}
.seg-ctrl .seg-item {
  min-width: 34px; height: 28px; padding: 0 8px;
  display: flex; align-items: center; justify-content: center;
  font-size: .8rem; color: var(--text-2); border-radius: 7px;
  cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
  transition: background .18s ease, color .18s ease, box-shadow .18s ease, transform .12s ease;
}
.seg-ctrl .seg-item.active {
  background: var(--bg-card); color: var(--primary); font-weight: 600;
  box-shadow: 0 1px 3px rgba(0,0,0,.16);
}
.seg-ctrl .seg-item:active { transform: scale(.94); }

.status-tabs {
  display: flex; gap: 8px; padding: 8px 16px 4px;
}
.st-item {
  padding: 5px 14px; border-radius: 16px;
  font-size: .8rem; cursor: pointer;
  border: 1px solid var(--border-2); color: var(--text-2);
  transition: all .2s;
}
.st-item.active {
  background: var(--primary); color: #fff; border-color: var(--primary);
}

.transfer-list { padding: 8px 16px; }
.transfer-task {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 0; border-bottom: 1px solid var(--border);
}
.transfer-task:last-child { border-bottom: none; }
.tt-file-icon { font-size: 1.8rem; flex-shrink: 0; }
.tt-file-info { flex: 1; min-width: 0; }
.tt-file-name { font-size: .88rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tt-file-meta { font-size: .72rem; color: var(--text-3); margin-top: 2px; }
.tt-prog { height: 3px; background: var(--bg); border-radius: 2px; margin-top: 5px; }
.tt-prog-fill { height: 100%; border-radius: 2px; }
.tt-prog-fill.done { background: var(--ys-success); }
.tt-prog-fill.running { background: var(--primary); }
.tt-prog-fill.failed { background: var(--ys-danger); }
.tt-status { flex-shrink: 0; display: flex; align-items: center; gap: 8px; }
.tt-status-badge { font-size: .72rem; padding: 2px 8px; border-radius: 10px; font-weight: 500; }
.tt-status-badge.done    { background: var(--ys-success-bg); color: var(--ys-success); }
.tt-status-badge.running { background: var(--primary-light); color: var(--primary); }
.tt-status-badge.failed  { background: var(--ys-danger-bg); color: var(--ys-danger); }

/* 进行中任务行的操作按钮（暂停/继续、取消）。
   只有「内存态」任务行 .transfer-task[data-live] 会渲染，已落库的历史记录没有这些按钮。
   触摸目标 30px 满足移动端可点；暂停/继续用中性描边，取消 likewise 中性（按下才转红）。 */
.tt-acts { display: flex; align-items: center; gap: 6px; }
.tt-act {
  width: 30px; height: 30px; padding: 0; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--ys-line-soft); background: transparent;
  color: var(--ys-ink-4); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.tt-act:active { background: var(--bg); color: var(--ys-ink-1); }
.tt-act[data-live-act="cancel"]:active { color: var(--ys-danger); border-color: var(--ys-danger); }
/* 已暂停：进度条与徽标同时转灰，与「进行中」一眼可分 */
.tt-prog-fill.paused { background: var(--ys-ink-4); opacity: .55; }
.tt-status-badge.paused { background: var(--bg); color: var(--ys-ink-4); }

.transfer-empty {
  display: flex; flex-direction: column; align-items: center;
  padding: 60px 24px; gap: 16px;
}
.te-circle {
  width: 100px; height: 100px; background: var(--primary-light);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.te-circle svg { width: 48px; height: 48px; stroke: var(--primary); fill: none; stroke-width: 1.5; }
.transfer-empty p { font-size: .88rem; color: var(--text-3); }
/* 空态下的「用途 / 使用说明」补充行（特异性要压过 .transfer-empty p）*/
.transfer-empty .te-hint {
  font-size: .75rem; line-height: 1.7; max-width: 16rem;
  text-align: center; margin-top: -6px;
}

/* ══════════════════════════════════════════════════
   INFO / CHAT PAGE (Screenshot 1)
   ══════════════════════════════════════════════════ */
.info-section-label {
  padding: 14px 16px 6px;
  font-size: .78rem; color: var(--text-3); font-weight: 500;
}
.conv-item {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; cursor: pointer;
  transition: background .15s; position: relative;
}
.conv-item:active { background: var(--bg); }
.conv-item::after {
  content: ''; position: absolute; left: 72px; right: 0; bottom: 0;
  height: 1px; background: var(--border);
}
.conv-avatar {
  width: 46px; height: 46px; border-radius: 50%; flex-shrink: 0;
  background: linear-gradient(135deg, #a8c4f5 0%, var(--ys-brand-mid) 100%);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.2rem; color: #fff; font-weight: 600;
  position: relative; overflow: hidden;
}
.conv-avatar img { width: 100%; height: 100%; object-fit: cover; }
.conv-avatar.deleted {
  background: var(--primary-light); color: var(--primary);
  font-size: .9rem; font-weight: 700;
}
.conv-body { flex: 1; min-width: 0; }
.conv-row1 { display: flex; align-items: center; justify-content: space-between; }
.conv-name { font-size: .9rem; font-weight: 500; color: var(--text); }
.conv-time { font-size: .72rem; color: var(--text-3); }
.conv-preview {
  font-size: .78rem; color: var(--text-3); margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.unread-dot {
  width: 8px; height: 8px; background: var(--primary); border-radius: 50%; flex-shrink: 0;
}
.unread-count {
  background: var(--ys-danger); color: #fff;
  font-size: .65rem; min-width: 16px; height: 16px;
  border-radius: 8px; padding: 0 4px;
  display: flex; align-items: center; justify-content: center;
}

.info-add-btn {
  position: fixed; bottom: calc(var(--nav-h) + 16px); right: 20px;
  width: 48px; height: 48px;
  background: var(--primary); color: #fff; border-radius: 50%;
  box-shadow: var(--shadow-deep);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.4rem; z-index: 65; cursor: pointer;
}

/* 好友请求：待接受行（右侧「接受」按钮） */
.req-item { cursor: default; }
.req-item:active { background: transparent; }
.req-item .conv-preview { color: var(--text-2); }
.req-accept {
  flex-shrink: 0; padding: 6px 14px;
  background: var(--primary); color: #fff;
  font-size: .78rem; font-weight: 500; line-height: 1.2;
  border-radius: 999px; cursor: pointer;
  transition: opacity .15s;
}
.req-accept:active { opacity: .75; }
.req-accept[data-busy] { opacity: .55; cursor: default; }

/* ══════════════════════════════════════════════════
   MINE PAGE (Screenshot 3)
   ══════════════════════════════════════════════════ */
.mine-page { background: var(--bg); }
.mine-profile {
  background: #fff; padding: 20px 16px 16px;
  display: flex; align-items: center; gap: 14px;
  margin-bottom: 8px;
}
.mine-avatar {
  width: 64px; height: 64px; border-radius: 50%; flex-shrink: 0;
  background: linear-gradient(135deg, #cfe0fc 0%, #a8c4f5 100%);
  display: flex; align-items: center; justify-content: center;
  font-size: 2rem; overflow: hidden; cursor: pointer;
}
.mine-avatar img { width: 100%; height: 100%; object-fit: cover; }
.mine-info-block { flex: 1; min-width: 0; }
.mine-nickname { font-size: 1.05rem; font-weight: 700; color: var(--text); margin-bottom: 2px; }
.mine-vip-link {
  font-size: .78rem; color: var(--primary); display: flex; align-items: center; gap: 2px; cursor: pointer; margin-bottom: 3px;
}
.mine-email    { font-size: .75rem; color: var(--text-3); }
.mine-actions  { display: flex; align-items: flex-start; gap: 8px; flex-shrink: 0; }
.mine-checkin-btn {
  display: flex; align-items: center; gap: 4px;
  padding: 6px 12px; border: 1px solid var(--primary);
  border-radius: 16px; font-size: .78rem; color: var(--primary); cursor: pointer;
}
.mine-checkin-btn.done {
  border-color: var(--border-2); color: var(--text-3);
  cursor: not-allowed;
}
.mine-qr-btn {
  width: 34px; height: 34px;
  border: 1px solid var(--border-2); border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-2); cursor: pointer; font-size: 1rem;
}
.mine-qr-btn svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.6; }

/* ── SVIP 金色标识 ────────────────────────────────────────────────
   金色要同时满足「亮得像金」和「读得清」：
   亮金 #f5a623 直接当白底文字只有 2.2:1（远低于 AA 4.5:1）⇒ 不可用。
   所以徽章 = 亮金渐变底 + 深棕字（5.5:1）；昵称当文字时用深金 #946200（4.96:1）。 */
.svip-tag {
  display: inline-flex; align-items: center; gap: 2px;
  height: 16px; padding: 0 5px 0 3px; margin-left: 5px;
  border-radius: 8px; background: var(--ys-gold-grad); color: var(--ys-gold-ink);
  font-size: .58rem; font-weight: 700; line-height: 1;
  letter-spacing: .2px; vertical-align: -1px; flex-shrink: 0; white-space: nowrap;
}
.svip-tag svg { width: 9px; height: 9px; fill: currentColor; stroke: none; }
.svip-tag.lg { height: 19px; padding: 0 7px 0 4px; border-radius: 10px;
               font-size: .66rem; letter-spacing: .3px; }
.svip-tag.lg svg { width: 11px; height: 11px; }

/* 昵称金色化：只改颜色，不动字号/字重/布局 */
.mine-nickname.is-svip,
.conv-name.is-svip,
.chat-name.is-svip { color: var(--ys-gold-name); }

/* 「我的」页 SVIP 状态行（替换非会员看到的「开通SVIP」入口）
   flex-wrap 是必需的：.mine-info-block 在 360/320 档只剩约 110px 宽，
   「有效期至 …」本身就快占满，续费胶囊放同行会顶破卡片 ⇒ 允许折行。 */
.mine-vip-state {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap; row-gap: 3px;
  font-size: .74rem; font-weight: 600; color: var(--ys-gold-name); margin-bottom: 3px;
}
.mine-vip-state .svip-tag { margin-left: 0; }

/* 日期必须整块换行、不可断字：320 档 .mine-info-block 仅约 92px 宽，
   曾把「2027-09-13」硬拆成「2027-」「09-13」两行（日期被拆断 = 可读性/语义错误）。 */
.mine-vip-state .mvr-date { white-space: nowrap; }

/* SVIP 续费入口：老会员唯一的续费路径
   （「开通SVIP」链接与 .vip-banner 横幅只对非会员渲染 ⇒ 会员续费无门）
   刻意做成轻量胶囊而不是横幅：已付费用户不该再被开通广告打扰。 */
.mine-vip-renew {
  flex-shrink: 0; padding: 1px 8px; border-radius: 9px;
  border: 1px solid rgba(148, 98, 0, .42); color: var(--ys-gold-name);
  font-size: .68rem; font-weight: 600; line-height: 1.55;
  cursor: pointer; white-space: nowrap;
}
.mine-vip-renew:active { background: rgba(148, 98, 0, .12); }

/* VIP Banner */
.vip-banner {
  margin: 0 5px 12px;
  background: linear-gradient(110deg, #2d1b00 0%, #5c3d00 40%, #8b5e00 70%, #c4820a 100%);
  border-radius: var(--radius); padding: 14px 16px;
  display: flex; align-items: center; gap: 12px; cursor: pointer;
  overflow: hidden;   /* 兜底：任何极端宽度下子元素都不会跑出圆角外 */
}
.vb-icon {
  width: 40px; height: 40px; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #ffdd82, #f5a623);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.1rem; flex-shrink: 0;
}
/* ⛔ min-width:0 是 flex 收缩的必要条件：.vb-sub 为 nowrap，其 min-content = 整行
   不换行宽度；默认 min-width:auto 会让文本区拒绝收缩，从而把 flex-shrink:0 的
   「立即开通」按钮顶出卡片外（360px 档实测溢出 13.7px） */
.vb-text { flex: 1; min-width: 0; }
.vb-title { font-size: .9rem; font-weight: 700; color: #ffd96a;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vb-sub   { font-size: .72rem; color: rgba(255,210,100,.65); margin-top: 2px;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vb-btn   {
  flex-shrink: 0; padding: 7px 14px;
  background: linear-gradient(135deg, #ffd96a, #f5a623);
  color: #5c3000; font-size: .8rem; font-weight: 700;
  border-radius: 16px; white-space: nowrap;
}
/* 窄屏（≤400px）：收紧内边距与图标，给文案留出展示宽度，避免按钮贴边/截断 */
@media (max-width: 400px) {
  .vip-banner { padding: 12px 13px; gap: 10px; }
  .vb-icon    { width: 36px; height: 36px; }
  .vb-btn     { padding: 6px 11px; font-size: .76rem; }
}

/* Storage section */
.mine-storage {
  background: #fff; margin: 0 0 8px;
  padding: 14px 16px;
}
.ms-header {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;
}
.ms-title {
  display: flex; align-items: center; gap: 6px;
  font-size: .88rem; font-weight: 600; color: var(--text);
}
.ms-title svg { width: 16px; height: 16px; stroke: var(--primary); fill: none; stroke-width: 1.8; }
.ms-total  { font-size: .78rem; color: var(--text-3); }
.ms-bar    { height: 6px; background: var(--bg); border-radius: 4px; overflow: hidden; margin-bottom: 8px; display: flex; }
.ms-seg    { height: 100%; border-radius: 0; transition: width .5s; }
.ms-seg:first-child { border-radius: 4px 0 0 4px; }
.ms-seg:last-child  { border-radius: 0 4px 4px 0; }
.ms-legend { display: flex; gap: 14px; flex-wrap: wrap; }
.ms-leg-item { display: flex; align-items: center; gap: 5px; font-size: .72rem; color: var(--text-3); }
.ms-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }

/* Quick action grid */
.mine-quick {
  background: #fff; padding: 14px 0 12px;
  margin-bottom: 8px;
}
.quick-grid { display: grid; grid-template-columns: repeat(5, 1fr); }
.quick-item {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 4px 4px 4px; cursor: pointer;
}
.quick-icon {
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--primary-light);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.2rem; transition: transform .15s;
}
.quick-icon svg { width: 22px; height: 22px; stroke: var(--primary); fill: none; stroke-width: 1.6; }
.quick-item:active .quick-icon { transform: scale(.9); }
.quick-label { font-size: .7rem; color: var(--text-2); }

/* Settings menu list */
.mine-settings { background: #fff; }
.setting-item {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 16px; cursor: pointer; position: relative;
}
.setting-item:not(:last-child)::after {
  content: ''; position: absolute; left: 58px; right: 0; bottom: 0;
  height: 1px; background: var(--border);
}
.setting-item:active { background: var(--bg); }
.si-icon {
  width: 36px; height: 36px; border-radius: 10px;
  background: var(--primary-light);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: .95rem;
}
.si-icon svg { width: 18px; height: 18px; stroke: var(--primary); fill: none; stroke-width: 1.8; }
.si-text { flex: 1; }
.si-title { font-size: .88rem; color: var(--text); font-weight: 500; }
.si-sub   { font-size: .72rem; color: var(--text-3); margin-top: 1px; }
.si-arrow { color: var(--text-4); flex-shrink: 0; font-size: .8rem; }
.si-arrow svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2; }

/* ══════════════════════════════════════════════════
   OVERLAY / SUB-PAGES
   ══════════════════════════════════════════════════ */
.page-overlay {
  position: fixed; inset: 0; z-index: 150;
  background: var(--bg-card);
  transform: translateX(100%);
  transition: transform .28s cubic-bezier(.4, 0, .2, 1);
  display: flex; flex-direction: column;
  overflow: hidden;
}
.page-overlay.open { transform: translateX(0); }
.ov-header {
  height: var(--header-h); background: #fff;
  display: flex; align-items: center; gap: 10px;
  padding: 0 16px; flex-shrink: 0;
  border-bottom: 1px solid var(--border);
}
.ov-back {
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; flex-shrink: 0; color: var(--text-2);
}
.ov-back svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 2; }
.ov-title { flex: 1; font-size: 1rem; font-weight: 700; color: var(--text); }
.ov-body  { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding-bottom: 20px; }
.ov-body::-webkit-scrollbar { display: none; }

/* ── Recycle bin ── */
.trash-item {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid var(--border); cursor: pointer;
}
.trash-item .ti-del { font-size: .72rem; color: var(--ys-danger); }

/* ── My shares ── */
.share-item {
  background: #fff; margin: 8px 16px;
  border-radius: var(--radius); padding: 14px;
  box-shadow: 0 1px 6px rgba(0,0,0,.05);
}
.share-item .share-name { font-size: .9rem; font-weight: 500; color: var(--text); margin-bottom: 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-item .share-meta { font-size: .75rem; color: var(--text-3); display: flex; gap: 12px; flex-wrap: wrap; }
.share-item .share-url  { font-size: .78rem; color: var(--primary); word-break: break-all; margin: 6px 0; }
.share-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.sh-btn {
  padding: 5px 12px; border-radius: 6px; font-size: .78rem; cursor: pointer; border: 1px solid var(--border-2);
  white-space: nowrap;
}
.sh-btn.visit  { color: var(--ys-success); border-color: var(--ys-success-line); background: var(--ys-success-bg); }
.sh-btn.copy   { color: var(--primary); border-color: var(--primary-light); background: var(--primary-light); }
.sh-btn.cancel { color: var(--ys-danger); border-color: var(--ys-danger-line); background: var(--ys-danger-bg); }
.sh-pw { display: inline-flex; align-items: center; gap: 4px; font-size: .75rem; color: var(--ys-warn-text);
         background: var(--ys-warn-bg); padding: 2px 8px; border-radius: 10px; }

/* ── Settings overlay ── */
.settings-group { background: #fff; margin-bottom: 8px; }
.settings-item {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 16px; border-bottom: 1px solid var(--border); cursor: pointer;
}
.settings-item:last-child { border-bottom: none; }
.settings-item label { font-size: .88rem; color: var(--text); cursor: pointer; }
.settings-item .sv { font-size: .82rem; color: var(--text-3); }
.settings-item input[type=text], .settings-item input[type=email], .settings-item input[type=password] {
  background: transparent; font-size: .88rem; color: var(--text); text-align: right;
  flex: 1; min-width: 0; margin-left: 10px;
}
.settings-item input::placeholder { color: var(--text-4); }
.toggle-switch {
  width: 42px; height: 24px; background: var(--border-2); border-radius: 12px;
  position: relative; cursor: pointer; transition: background .2s; flex-shrink: 0;
}
.toggle-switch.on { background: var(--primary); }
.toggle-switch::after {
  content: ''; position: absolute;
  width: 18px; height: 18px; top: 3px; left: 3px;
  background: #fff; border-radius: 50%; transition: left .2s;
  box-shadow: 0 1px 4px rgba(0,0,0,.2);
}
.toggle-switch.on::after { left: 21px; }

/* ── Notification item ── */
.notice-item {
  display: flex; gap: 12px; padding: 14px 16px;
  border-bottom: 1px solid var(--border); cursor: pointer;
}
.notice-item.unread { background: var(--primary-lighter); }
.ni-dot { width: 8px; height: 8px; background: var(--primary); border-radius: 50%; flex-shrink: 0; margin-top: 6px; }
.ni-body { flex: 1; min-width: 0; }
.ni-title { font-size: .88rem; font-weight: 500; color: var(--text); }
.ni-content { font-size: .78rem; color: var(--text-3); margin-top: 3px; }
.ni-time { font-size: .72rem; color: var(--text-4); margin-top: 4px; }

/* ── Order/VIP ── */
.vip-plans { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; padding: 16px; }
.vip-plan {
  border: 1.5px solid var(--border-2); border-radius: var(--radius);
  padding: 16px 10px; text-align: center; cursor: pointer; transition: all .2s;
}
.vip-plan.recommend { border-color: var(--primary); background: var(--primary-lighter); }
.vip-plan .vp-name  { font-size: .78rem; color: var(--text-3); margin-bottom: 8px; }
.vip-plan .vp-price { font-size: 1.4rem; font-weight: 700; color: var(--text); }
.vip-plan .vp-price span { font-size: .72rem; font-weight: 400; color: var(--text-3); }
.vip-plan .vp-tag   { font-size: .68rem; color: var(--ys-danger); margin-top: 4px; }
.vip-plan.recommend .vp-price { color: var(--primary); }
.vip-benefits { padding: 0 16px; }
.vip-benefit-item { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.vb-check { width: 18px; height: 18px; background: var(--primary-light); border-radius: 50%;
            display: flex; align-items: center; justify-content: center; color: var(--primary); font-size: .7rem; }
.vb-name { font-size: .85rem; color: var(--text); }

/* ── Privacy space ── */
.privacy-lock {
  display: flex; flex-direction: column; align-items: center;
  padding: 60px 24px; gap: 16px; text-align: center;
}
.privacy-lock .lock-icon { font-size: 3.5rem; }
.privacy-lock h3 { font-size: 1rem; font-weight: 600; color: var(--text); }
.privacy-lock p  { font-size: .82rem; color: var(--text-3); }
.pin-row { display: flex; gap: 12px; justify-content: center; margin-top: 8px; }
.pin-dot {
  width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid var(--border-2); background: transparent;
  transition: background .2s;
}
.pin-dot.filled { background: var(--primary); border-color: var(--primary); }
.pin-pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; max-width: 260px; margin: 8px auto 0; }
.pin-key {
  padding: 15px; text-align: center; font-size: 1.1rem; font-weight: 500;
  background: var(--bg); border-radius: var(--radius-sm); cursor: pointer;
  transition: background .15s; -webkit-tap-highlight-color: transparent;
}
.pin-key:active { background: var(--primary-light); }

/* ── File cleanup ── */
.cleanup-item {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; background: #fff; margin-bottom: 1px;
}
.cu-icon  { font-size: 1.8rem; flex-shrink: 0; }
.cu-info  { flex: 1; }
.cu-title { font-size: .9rem; font-weight: 500; color: var(--text); }
.cu-sub   { font-size: .75rem; color: var(--text-3); margin-top: 2px; }
.cu-size  { font-size: .82rem; color: var(--primary); font-weight: 600; margin-top: 2px; }
.cu-btn   { padding: 7px 14px; border: 1px solid var(--border-2); border-radius: 16px; font-size: .8rem; color: var(--text-2); cursor: pointer; }
.cu-btn.active { border-color: var(--primary); color: var(--primary); background: var(--primary-light); }

/* ── FTP Settings ── */
.ftp-form  { padding: 16px; }
.ftp-field { margin-bottom: 14px; }
.ftp-field label { display: block; font-size: .78rem; color: var(--text-3); margin-bottom: 5px; }
.ftp-field input {
  width: 100%; padding: 10px 12px;
  background: var(--bg); border-radius: var(--radius-sm); border: 1.5px solid transparent;
  font-size: .88rem; color: var(--text); transition: border-color .2s;
}
.ftp-field input:focus { border-color: var(--primary); background: #fff; }
.ftp-save-btn {
  width: 100%; padding: 13px;
  background: var(--primary); color: #fff; border-radius: var(--radius);
  font-size: .9rem; font-weight: 600; cursor: pointer; transition: background .2s;
}
.ftp-save-btn:active { background: var(--primary-dark); }

/* ── Chat Overlay ── */
.chat-overlay {
  position: fixed; inset: 0; z-index: 200;
  background: var(--ys-bg);
  display: flex; flex-direction: column;
  transform: translateY(100%); transition: transform .3s cubic-bezier(.4,0,.2,1);
}
.chat-overlay.open { transform: translateY(0); }
.chat-header {
  height: var(--header-h); background: #fff;
  display: flex; align-items: center; gap: 10px;
  padding: 0 16px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.chat-header .chat-name { flex: 1; font-size: .95rem; font-weight: 600; color: var(--text); }
.chat-messages {
  flex: 1; overflow-y: auto; padding: 12px 16px;
  display: flex; flex-direction: column; gap: 12px;
  -webkit-overflow-scrolling: touch;
}
.chat-messages::-webkit-scrollbar { display: none; }
.msg-row { display: flex; gap: 8px; align-items: flex-end; }
.msg-row.mine  { flex-direction: row-reverse; }
.msg-avatar { width: 32px; height: 32px; border-radius: 50%; background: var(--primary-light);
              display: flex; align-items: center; justify-content: center; font-size: .85rem;
              color: var(--primary); font-weight: 600; flex-shrink: 0; }
.msg-bubble {
  max-width: 70%; padding: 10px 13px;
  border-radius: 16px 16px 16px 4px;
  background: #fff; font-size: .88rem; line-height: 1.5; color: var(--text);
  box-shadow: 0 1px 4px rgba(0,0,0,.06); word-break: break-word;
}
.msg-row.mine .msg-bubble {
  background: var(--primary); color: #fff;
  border-radius: 16px 16px 4px 16px;
}
.msg-file-bubble {
  display: flex; align-items: center; gap: 10px;
  background: #fff; padding: 10px 12px;
  border-radius: 12px; max-width: 220px;
  box-shadow: 0 1px 4px rgba(0,0,0,.06); cursor: pointer;
}
.msg-file-icon { font-size: 1.5rem; flex-shrink: 0; }
.msg-file-info { flex: 1; min-width: 0; }
.msg-file-name { font-size: .82rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-file-size { font-size: .72rem; color: var(--text-3); }
.msg-time { font-size: .68rem; color: var(--text-4); flex-shrink: 0; align-self: flex-end; margin-bottom: 4px; }
.chat-input-bar {
  background: #fff; border-top: 1px solid var(--border);
  padding: 10px 16px; display: flex; align-items: flex-end; gap: 10px;
  flex-shrink: 0; padding-bottom: calc(10px + env(safe-area-inset-bottom, 0));
}
.chat-input {
  flex: 1; background: var(--bg); border-radius: 20px; padding: 9px 14px;
  font-size: .88rem; color: var(--text); min-height: 38px; max-height: 100px;
  overflow-y: auto; resize: none; line-height: 1.4;
}
.chat-send-btn {
  width: 36px; height: 36px; background: var(--primary); border-radius: 50%;
  display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0;
}
.chat-send-btn svg { width: 18px; height: 18px; stroke: #fff; fill: none; stroke-width: 2; }
.chat-attach-btn {
  width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0;
  color: var(--text-3);
}
.chat-attach-btn svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.8; }

/* ══════════════════════════════════════════════════
   在线预览浮层（图片 / 视频 / 音频 / PDF / 文本）
   —— 刻意恒为深色（与图库、播放器一致），不随主题令牌变化，
      故此处允许出现黑色系字面色值，做法同 .mask 的遮罩。
   ══════════════════════════════════════════════════ */
.pv-page {
  position: fixed; inset: 0; z-index: 400;
  /* 用 98.5% 而不是 96%：实测 96% 时底下的页面文字会透出来，
     文本阅读器里「影子字」压在正文下，很影响可读性 */
  background: rgba(18, 18, 20, .985);
  display: flex; flex-direction: column;
  opacity: 0; transition: opacity .2s ease;
  padding-top: env(safe-area-inset-top, 0);
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.pv-page.open { opacity: 1; }

.pv-top { display: flex; align-items: center; gap: 10px; padding: 12px 14px; flex-shrink: 0; }
.pv-name { flex: 1; min-width: 0; font-size: .86rem; color: rgba(255,255,255,.92);
           overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pv-close {
  width: 30px; height: 30px; flex-shrink: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: rgba(255,255,255,.85); background: rgba(255,255,255,.12);
  font-size: .95rem; cursor: pointer;
}
.pv-close:active { background: rgba(255,255,255,.22); }

.pv-stage { flex: 1 1 auto; min-height: 0; position: relative;
            display: flex; align-items: center; justify-content: center; overflow: hidden; }
.pv-img { max-width: 100%; max-height: 100%; object-fit: contain;
          opacity: 0; transition: opacity .18s, transform .2s; }
.pv-img.loaded { opacity: 1; }
.pv-img.zoomed { transform: scale(2); cursor: zoom-out; }
.pv-spin { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
           color: rgba(255,255,255,.7); font-size: .82rem; text-align: center; padding: 0 24px; }
.pv-frame { width: 100%; height: 100%; border: 0; background: #fff; }
.pv-media { max-width: 100%; max-height: 100%; background: #000; }
.pv-err { display: none; }
.pv-err.show { display: block; color: #ffb4b4; font-size: .8rem; line-height: 1.6;
               padding: 14px 18px; text-align: center; }

/* 音频卡片 */
.pv-stage-audio { padding: 0 20px; }
.pv-audio-card { width: 100%; max-width: 340px; background: rgba(255,255,255,.06);
                 border-radius: 18px; padding: 22px 18px; text-align: center;
                 display: flex; flex-direction: column; align-items: center; gap: 10px; }
.pv-audio-icon { font-size: 2.6rem; }
.pv-audio-name { color: rgba(255,255,255,.92); font-size: .88rem; word-break: break-all; }
.pv-audio-meta { color: rgba(255,255,255,.5); font-size: .74rem; }
.pv-audio { width: 100%; margin-top: 6px; }

/* 文本阅读器 */
.pv-stage-text { align-items: stretch; }
.pv-doc { position: relative; flex: 1; min-height: 0; overflow: auto; -webkit-overflow-scrolling: touch; }
.pv-pre { margin: 0; padding: 14px 16px 20px; color: rgba(255,255,255,.88);
          font-size: .78rem; line-height: 1.75; white-space: pre-wrap; word-break: break-word;
          font-family: ui-monospace, Menlo, Consolas, monospace; }
.pv-meta { flex-shrink: 0; padding: 6px 16px; color: rgba(255,255,255,.5);
           font-size: .72rem; text-align: center; }

/* ══════════════════════════════════════════════════
   Office / 电子书阅读器
   —— 深色浮层里放一张「白纸」（与 .pv-frame 的 #fff 同口径）。
      正文排版全部由 op-* 类承担；标签与转义由后端 office_preview.php 负责，
      前端只做「装进容器 + 把 img[data-opart] 的 src 补上」。
   ══════════════════════════════════════════════════ */
.pv-stage-doc { align-items: stretch; }
.pv-reader { flex: 1; min-height: 0; overflow: auto; -webkit-overflow-scrolling: touch;
             padding: 0 10px 16px; }
.op-paper { background: #fff; color: #23303f; border-radius: 12px; padding: 18px 16px;
            font-size: .86rem; line-height: 1.85; word-break: break-word;
            box-shadow: 0 2px 14px rgba(0,0,0,.35); }
.op-paper > :first-child { margin-top: 0; }
.op-paper > :last-child  { margin-bottom: 0; }
.op-paper h1, .op-paper h2, .op-paper h3,
.op-paper h4, .op-paper h5, .op-paper h6 {
  margin: 1.1em 0 .5em; line-height: 1.45; font-weight: 700; color: #16202b; }
.op-paper h1 { font-size: 1.32rem; }
.op-paper h2 { font-size: 1.16rem; }
.op-paper h3, .op-paper h4, .op-paper h5, .op-paper h6 { font-size: 1.02rem; }
.op-paper p { margin: .55em 0; }
.op-paper p.op-empty { margin: .3em 0; }
.op-paper ul, .op-paper ol { margin: .5em 0; padding-left: 1.5em; }
.op-paper li { margin: .22em 0; }
.op-paper blockquote { margin: .7em 0; padding: .2em 0 .2em .85em;
                       border-left: 3px solid #d7dce6; color: #4a5766; }
.op-paper pre { margin: .7em 0; padding: 10px 12px; background: #f4f6fa;
                border-radius: 8px; overflow: auto; font-size: .78rem; }
.op-paper code, .op-mono { font-family: ui-monospace, Menlo, Consolas, monospace; }
.op-paper code { font-size: .84em; }
.op-li { display: inline-block; width: 1.1em; text-align: center; }
.op-li::before { content: '\2022'; }
/* 正文里的制表符占位（勿与下面的 .op-tab 工作表标签混淆） */
.op-wtab { display: inline-block; width: 1.6em; }
.op-pgbrk { display: block; height: 1px; margin: 1.2em 0; border-top: 1px dashed #c9d0dc; }
.op-hr { margin: 1em 0; border: 0; border-top: 1px solid #e3e6ed; }
.op-a { color: #2b6cf0; text-decoration: underline; text-decoration-style: dotted; }
.op-obj { color: #6b7688; font-size: .82em; }
.op-img { display: block; max-width: 100%; height: auto; margin: .7em auto; border-radius: 6px; }
.op-img-bad { min-height: 40px; background: #f4f6fa; border: 1px dashed #d7dce6;
              color: #8b93a5; font-size: .78rem; text-align: center; padding: 12px 0; }
.op-note { color: #8b93a5; font-size: .8rem; }
/* 表格比屏幕宽时给个「可以左右滑」的提示：local 层的白色渐变**随内容滚动**、
   scroll 层的阴影**钉在容器边缘**，两者叠加的结果就是「只在确实溢出时才露出阴影」——
   纯 CSS，不需要用 JS 去测 scrollWidth。浏览器不支持 local 时只是没有阴影，不会坏版式。 */
.op-tblwrap {
  margin: .7em 0; overflow-x: auto; -webkit-overflow-scrolling: touch;
  background:
    linear-gradient(to right, #fff 30%, rgba(255,255,255,0)) left  center / 40px 100% no-repeat local,
    linear-gradient(to left,  #fff 30%, rgba(255,255,255,0)) right center / 40px 100% no-repeat local,
    radial-gradient(farthest-side at 0%   50%, rgba(35,48,63,.16), rgba(35,48,63,0)) left  center / 12px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(35,48,63,.16), rgba(35,48,63,0)) right center / 12px 100% no-repeat scroll;
}
.op-tbl { border-collapse: collapse; width: 100%; font-size: .82rem; }
.op-tbl td { border: 1px solid #dfe3eb; padding: 5px 8px; vertical-align: top; }
.op-tbl td p, .op-tbl td div { margin: 0; }
.op-tbl td p.op-empty { margin: 0; }
.op-vm { background: #f8f9fc; }
/* 还原源文件列宽（docx / pptx 表格）：<colgroup> 给各列比例 + fixed 布局让浏览器照办，
   否则手机屏宽会把多列表格挤到每列只剩 ~24px（中文被压成一列一个字）。
   ⛔ 表上的 min-width 由后端按源文件长度单位算好（office_preview.php :: op_tbl_grid），
     不要在这里写死表格宽度；超宽时由 .op-tblwrap 的 overflow-x:auto 横向滚动。
   只作用于 .op-tbl--grid —— xlsx 工作表（.op-sheettbl）靠 white-space:nowrap 撑开，不受影响。 */
.op-tbl--grid { table-layout: fixed; }
.op-tbl--grid td { overflow-wrap: break-word; }
.op-sheettbl td { white-space: nowrap; }
/* 表格条 / 章节条 / 幻灯片编号都在「纸上」，用深色字 */
.op-tabs { display: flex; gap: 6px; overflow-x: auto; padding: 0 2px 8px; }
.op-tabs::-webkit-scrollbar { display: none; }
.op-tab { flex: 0 0 auto; padding: 5px 12px; border-radius: 999px; font-size: .78rem;
          background: rgba(255,255,255,.12); color: rgba(255,255,255,.82);
          white-space: nowrap; cursor: pointer; }
.op-tab.on { background: #fff; color: #16202b; font-weight: 600; }
.op-slidewrap { margin-bottom: 14px; }
.op-slide-no { color: rgba(255,255,255,.55); font-size: .72rem; padding: 2px 4px 6px; }
.op-slide-t { margin: 0 0 .5em !important; font-size: 1.1rem; font-weight: 700; color: #16202b; }
.op-sp { margin: .3em 0; }
.op-paper-slide { min-height: 110px; }
.op-ebookbar { display: flex; align-items: center; gap: 8px; padding: 0 2px 8px; }
.op-chap { flex: 1; min-width: 0; height: 34px; border-radius: 8px; padding: 0 8px;
           border: 1px solid rgba(255,255,255,.18); background: rgba(255,255,255,.1);
           color: rgba(255,255,255,.92); font-size: .8rem; }
.op-chap option { color: #23303f; }
.op-chapn { flex-shrink: 0; color: rgba(255,255,255,.5); font-size: .74rem; }
.op-comic { display: flex; flex-direction: column; gap: 8px; }
.op-comic-p { width: 100%; height: auto; border-radius: 8px; background: rgba(255,255,255,.06); }
.op-unsup { display: flex; flex-direction: column; align-items: center; gap: 8px;
            padding: 46px 24px; text-align: center; }
.op-unsup-i { color: rgba(255,255,255,.45); }
.op-unsup-i svg { width: 40px; height: 40px; stroke: currentColor; fill: none; stroke-width: 1.5; }
.op-unsup-t { color: rgba(255,255,255,.9); font-size: .95rem; font-weight: 600; }
.op-unsup-m { color: rgba(255,255,255,.55); font-size: .8rem; line-height: 1.7; max-width: 320px; }
.op-unsup-b { margin-top: 6px; padding: 9px 22px; border-radius: 999px;
              background: var(--ys-brand); color: #fff; font-size: .84rem; cursor: pointer; }
.op-unsup-b:active { opacity: .8; }

/* 图片翻页条 */
.pv-bar { display: flex; align-items: center; justify-content: space-between; padding: 10px 24px; flex-shrink: 0; }
.pv-bar.single .pv-nav { visibility: hidden; }   /* 只有一张图就别摆左右箭头 */
.pv-nav { width: 40px; height: 40px; border-radius: 50%; background: rgba(255,255,255,.12);
          color: #fff; font-size: 1.3rem; line-height: 1;
          display: flex; align-items: center; justify-content: center; cursor: pointer; }
.pv-nav:active { background: rgba(255,255,255,.24); }
.pv-count { color: rgba(255,255,255,.75); font-size: .78rem; }

/* 底部说明与操作 */
.pv-foot { flex-shrink: 0; padding: 4px 16px 14px; text-align: center; }
.pv-hint { color: rgba(255,255,255,.45); font-size: .7rem; line-height: 1.6; padding: 0 8px 8px; }
.pv-acts { display: flex; gap: 10px; justify-content: center; }
.pv-act { padding: 8px 18px; border-radius: 18px; font-size: .8rem;
          color: rgba(255,255,255,.9); background: rgba(255,255,255,.12); cursor: pointer; }
.pv-act:active { background: rgba(255,255,255,.22); }

/* ══════════════════════════════════════════════════
   ACTION SHEET / MODAL
   ══════════════════════════════════════════════════ */
.mask {
  position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 300;
  display: flex; flex-direction: column; justify-content: flex-end;
}
.mask.center-modal { justify-content: center; align-items: center; }
.mask.hidden { display: none; }
.action-sheet {
  background: #fff; border-radius: 16px 16px 0 0;
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.as-title {
  text-align: center; padding: 14px 16px 10px;
  font-size: .82rem; color: var(--text-3);
  border-bottom: 1px solid var(--border);
}
.as-item {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 20px; cursor: pointer; border-bottom: 1px solid var(--border);
  font-size: .9rem; color: var(--text); transition: background .15s;
}
.as-item:active { background: var(--bg); }
.as-item svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.6; }
.as-item.danger { color: var(--ys-danger); }
.as-cancel {
  padding: 14px; text-align: center; font-size: .9rem; color: var(--text-2);
  cursor: pointer; background: #fff; border-top: 6px solid var(--bg);
}

/* Center modal (dialog) */
.center-dialog {
  background: #fff; border-radius: 16px;
  width: calc(100% - 64px); max-width: 320px;
  overflow: hidden;
}
.cd-head { padding: 18px 20px 8px; text-align: center; }
.cd-head h3 { font-size: 1rem; font-weight: 700; color: var(--text); }
.cd-body { padding: 8px 20px 16px; font-size: .88rem; color: var(--text-2); text-align: center; line-height: 1.6; }
.cd-input {
  width: 100%; margin: 4px 0 8px; padding: 10px 12px;
  background: var(--bg); border-radius: var(--radius-sm);
  font-size: .88rem; color: var(--text); border: 1.5px solid transparent; transition: border-color .2s;
}
.cd-input:focus { border-color: var(--primary); }
.cd-btns { display: flex; border-top: 1px solid var(--border); }
.cd-btn {
  flex: 1; padding: 13px; text-align: center;
  font-size: .9rem; cursor: pointer; transition: background .15s;
}
.cd-btn:not(:last-child) { border-right: 1px solid var(--border); }
.cd-btn:active { background: var(--bg); }
.cd-btn.primary { color: var(--primary); font-weight: 600; }
.cd-btn.danger  { color: var(--ys-danger); }

/* ══════════════════════════════════════════════════
   SEARCH RESULTS / Misc
   ══════════════════════════════════════════════════ */
.search-results-page {
  position: fixed; inset: 0; z-index: 160; background: #fff;
  display: flex; flex-direction: column;
  transform: translateY(-100%); transition: transform .25s;
}
.search-results-page.open { transform: translateY(0); }
/* 搜索页自带底栏：整页撑满浮层（.page-overlay 是定高 flex 列），
   这样 .sr-body 才会成为真正的滚动区，底栏才会被顶到屏幕底部 */
.page-overlay > .search-results-page { flex: 1 1 auto; min-height: 0; overflow: hidden; }
.sr-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px; border-bottom: 1px solid var(--border); background: #fff;
}
.sr-input {
  flex: 1; min-width: 0;                    /* 不写 min-width:0，input 的固有最小宽度（实测 180px）会顶出「取消」 */
  background: var(--bg); border-radius: 20px;
  padding: 9px 14px; font-size: .88rem; color: var(--text);
}
.sr-cancel { font-size: .88rem; color: var(--primary); cursor: pointer; flex-shrink: 0; }
.sr-body   { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; }

/* ── User search ── */
.user-search-item {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid var(--border); cursor: pointer;
}
.user-search-item:active { background: var(--bg); }
.usa-avatar { width: 40px; height: 40px; border-radius: 50%;
              background: var(--primary-light); display: flex; align-items: center; justify-content: center;
              color: var(--primary); font-weight: 600; font-size: .95rem; }
.usa-name { flex: 1; font-size: .9rem; color: var(--text); }
.usa-btn  { padding: 5px 14px; background: var(--primary-light); color: var(--primary);
            border-radius: 14px; font-size: .78rem; cursor: pointer; }
.usa-btn.added { background: var(--bg); color: var(--text-3); }

/* ── Section separator ── */
.section-sep { height: 8px; background: var(--bg); }

/* ── Pull to refresh (visual) ── */
.ptr-text {
  text-align: center; padding: 10px;
  font-size: .78rem; color: var(--text-4); display: none;
}

/* ══════════════════════════════════════════════════
   ANIMATIONS
   ══════════════════════════════════════════════════ */
@keyframes fadeIn  { from { opacity: 0; } to { opacity: 1; } }
@keyframes slideUp { from { transform: translateY(30px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }

.fade-in  { animation: fadeIn  .3s ease; }
.slide-up { animation: slideUp .3s ease; }

/* ── Safe area on iPhones ── */
@supports (padding-bottom: env(safe-area-inset-bottom)) {
  .page-body { padding-bottom: calc(var(--nav-h) + env(safe-area-inset-bottom)); }
}

/* ══════════════════════════════════════════════════
   SVG 图标系统（替代原彩色 emoji）
   .gi = 通用规格：尺寸随 font-size、描边随 currentColor。
   下列配色与各容器浅色底板配套（同色系描边图标）。
   ══════════════════════════════════════════════════ */
.gi {
  width: 1.15em; height: 1.15em;
  display: inline-block; vertical-align: -.18em;
  stroke: currentColor; fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}

/* 文件类型底板配色 */
.fi-folder { color: #e09b2d; }
.fi-image  { color: #e0568b; }
.fi-video  { color: #5b6ad0; }
.fi-audio  { color: #9256c9; }
.fi-doc    { color: #2fa14e; }
.fi-pdf    { color: #e07347; }
.fi-zip    { color: #d9534f; }
.fi-other  { color: var(--text-3); }
.fi-app     { color: #0e9aa7; }
.fi-ebook   { color: #6d28d9; }
.fi-font    { color: #c026d3; }
.fi-torrent { color: #0f766e; }
.fi-code    { color: #475569; }

/* 首页分类 */
.cat-icon.c-photo { color: #f97316; }
.cat-icon.c-video { color: #3b82f6; }
.cat-icon.c-music { color: #ec4899; }
.cat-icon.c-doc   { color: #22c55e; }
.cat-icon.c-zip   { color: #ef4444; }
.cat-icon.c-app     { color: #0e9aa7; }
.cat-icon.c-ebook   { color: #6d28d9; }
.cat-icon.c-font    { color: #c026d3; }
.cat-icon.c-torrent { color: #0f766e; }
.cat-icon.c-other   { color: #64748b; }

/* 各图标容器 */
.empty-icon        { color: var(--primary); }
.tb-icon           { color: var(--primary); }
.tt-file-icon      { color: var(--primary); }
.cu-icon           { color: var(--primary); }
.lock-icon         { color: var(--primary); }
.mine-avatar       { color: var(--primary); }
.vb-icon           { color: #fff; }
.vb-icon svg       { width: 22px; height: 22px; }
.hero-icon         { color: #fff; }
#splash .splash-icon { color: #fff; }
.pv-audio-icon     { color: rgba(255, 255, 255, .9); }
.recent-item > svg { width: 22px; height: 22px; color: var(--primary); }

/* ══════════════════════════════════════════════════
   首页顶栏：主站入口 + 实时天气胶囊
   ══════════════════════════════════════════════════ */
.hdr-site {
  flex: none; display: inline-flex; align-items: center; gap: 3px;
  padding: 4px 9px; border-radius: 999px;
  font-size: .78rem; font-weight: 600; color: var(--primary);
  background: var(--primary-light); white-space: nowrap;
  transition: background .2s;
}
.hdr-site:active { background: rgba(var(--ys-brand-rgb), .18); }
.hdr-site .gi { width: 14px; height: 14px; stroke-width: 2; }

.hdr-weather {
  flex: none; display: inline-flex; align-items: center; gap: 3px;
  padding: 4px 10px; border-radius: 999px;
  background: var(--ys-brand-grad); color: var(--ys-ink-on-brand);
  font-size: .78rem; font-weight: 600; line-height: 1;
  white-space: nowrap; cursor: pointer;
  box-shadow: 0 2px 6px rgba(var(--ys-brand-rgb), .28);
}
.hdr-weather:active { opacity: .88; }
.hdr-weather .gi { width: 14px; height: 14px; stroke-width: 2; }
.hdr-weather .wx-city { font-weight: 500; opacity: .9; }
.hdr-weather .wx-temp { font-weight: 700; }

/* 顶栏标题单行省略：主站/天气胶囊占位后，长昵称不再换行撑高 header */
.page-header h1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 首页顶栏：天气胶囊绝对水平居中（左主站 / 中天气 / 右通知），
   与 flex 流解耦，故不受左右两侧元素宽度变化影响 */
.page-header .hdr-weather { position: absolute; left: 50%; transform: translateX(-50%); }
.page-header .hdr-weather:active { opacity: .88; transform: translateX(-50%) scale(.97); }
.page-header .hdr-spacer  { flex: 1; min-width: 0; }
/* 窄屏兜底：天气胶囊与左右元素保持最小 8px 间距 */
@media (max-width: 340px) {
  .page-header { padding: 0 12px; gap: 6px; }
  .page-header .hdr-weather { font-size: .72rem; padding: 4px 8px; }
}

/* ══════════════════════════════════════════════════
   我的分享主页（#btn-qr 弹层）
   ══════════════════════════════════════════════════ */
.sh-intro {
  display: flex; gap: 11px; align-items: flex-start;
  margin: 12px 16px 0; padding: 13px 14px;
  background: var(--primary-lighter); border-radius: var(--radius, 10px);
}
.sh-intro-ico {
  width: 34px; height: 34px; flex: 0 0 auto; border-radius: 10px;
  background: var(--primary-light); color: var(--primary);
  display: flex; align-items: center; justify-content: center; font-size: 1rem;
}
.sh-intro-t { font-size: .86rem; font-weight: 700; color: var(--text); }
.sh-intro-s { font-size: .74rem; color: var(--text-3); line-height: 1.65; margin-top: 3px; }
.sh-intro-s b { color: var(--primary); }

.sh-row {
  display: flex; align-items: center; gap: 12px;
  margin: 10px 16px 0; padding: 14px;
  background: #fff; border-radius: var(--radius, 10px);
  box-shadow: 0 1px 6px rgba(0,0,0,.05);
}
.sh-row-txt { flex: 1; min-width: 0; }
.sh-row-t { font-size: .86rem; font-weight: 600; color: var(--text); }
.sh-row-s { font-size: .72rem; color: var(--text-3); margin-top: 3px; }

.sh-qr-box {
  margin: 12px 16px 0; padding: 18px 16px 14px;
  background: #fff; border-radius: var(--radius, 10px);
  box-shadow: 0 1px 6px rgba(0,0,0,.05);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.sh-qr {
  width: 200px; height: 200px; display: block;
  border-radius: 8px; background: #fff;
  image-rendering: pixelated;   /* SVG 兜底：万一被当位图渲染也别糊 */
}
.sh-qr-tip { font-size: .74rem; color: var(--text-3); }

.sh-link {
  margin: 10px 16px 0; padding: 13px 14px;
  background: #fff; border-radius: var(--radius, 10px);
  box-shadow: 0 1px 6px rgba(0,0,0,.05);
}
.sh-link-url {
  font-size: .74rem; color: var(--primary); word-break: break-all; line-height: 1.6;
  background: var(--primary-lighter); border-radius: 6px; padding: 8px 10px;
}
.sh-link-btns { display: flex; gap: 8px; margin-top: 10px; }
.sh-lbtn {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 5px;
  padding: 8px 10px; border-radius: 8px; font-size: .78rem; font-weight: 600;
  cursor: pointer; border: 1px solid var(--primary-light);
  color: var(--primary); background: var(--primary-light);
}
.sh-lbtn.primary { background: var(--primary); border-color: var(--primary); color: #fff; }

.sh-off {
  display: flex; gap: 10px; align-items: flex-start;
  margin: 12px 16px 0; padding: 14px;
  background: var(--ys-warn-bg, #fff8e6); border-radius: var(--radius, 10px);
  font-size: .76rem; color: var(--text-2); line-height: 1.7;
}
.sh-off svg { flex: 0 0 auto; margin-top: 2px; color: var(--ys-warn, #f59e0b); }
.sh-off b { color: var(--text); }

/* ══════════════════════════════════════════════════
   我的分享：逐条公开范围管理
   ══════════════════════════════════════════════════ */
.share-item .share-head { display: flex; align-items: center; gap: 10px; }
.share-item .share-head .share-name { flex: 1; min-width: 0; margin-bottom: 0; }

/* 真实可见性提示：on=已公开显示 / warn=标了公开但没露出去 / off=私密 */
.share-hint {
  font-size: .74rem; margin-top: 7px; padding: 6px 9px;
  border-radius: 6px; line-height: 1.55;
}
.share-hint.on   { color: var(--ys-success);    background: var(--ys-success-bg); }
.share-hint.warn { color: var(--ys-warn-text);  background: var(--ys-warn-bg); }
.share-hint.off  { color: var(--text-3);        background: var(--bg); }

/* 顶部汇总条 */
.sh-sum {
  background: #fff; margin: 8px 16px;
  border-radius: var(--radius); padding: 12px 14px;
  box-shadow: 0 1px 6px rgba(0,0,0,.05);
}
.sh-sum-line { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.sh-tag { font-size: .75rem; padding: 3px 10px; border-radius: 10px; white-space: nowrap; }
.sh-tag.pub  { color: var(--ys-success);   background: var(--ys-success-bg); }
.sh-tag.priv { color: var(--text-3);       background: var(--bg); }
.sh-tag.warn { color: var(--ys-warn-text); background: var(--ys-warn-bg); }
.sh-sum-btns { display: flex; gap: 8px; margin-top: 10px; }
.sh-sum-warn {
  display: flex; gap: 6px; align-items: center; margin-top: 10px;
  font-size: .74rem; line-height: 1.5; color: var(--ys-warn-text);
  background: var(--ys-warn-bg); padding: 7px 10px; border-radius: 6px;
}
.sh-sum-tip { font-size: .72rem; color: var(--text-3); line-height: 1.65; margin-top: 9px; }

/* 对话框里的复选框（分享时选「公开到我的分享主页」） */
.cd-check { display: flex; gap: 9px; align-items: flex-start; margin-top: 13px; cursor: pointer;
  text-align: left; }
.cd-check-box {
  width: 18px; height: 18px; flex: 0 0 auto; margin-top: 1px;
  border: 1.5px solid var(--border-2); border-radius: 5px;
  display: flex; align-items: center; justify-content: center;
  color: transparent; transition: background .15s, border-color .15s, color .15s;
}
.cd-check-box.on { background: var(--primary); border-color: var(--primary); color: #fff; }
.cd-check-box .gi { width: 11px; height: 11px; stroke-width: 2.6; }
.cd-check-txt { font-size: .82rem; color: var(--text); line-height: 1.5; }
.cd-check-txt i {
  display: block; font-style: normal; font-size: .72rem;
  color: var(--text-3); margin-top: 3px; line-height: 1.55;
}

/* ══════════════════════════════════════════════════
   布局修复 2026-09-13
   起因：「我的」页与隐私空间在宽屏下横向拉伸、PIN 键盘宽度失效、
         空白键伪装成真键、矮屏/横屏竖向溢出。
   ① 宽屏外壳约束  ② PIN 键盘宽度  ③ PIN 空白键  ④ 矮屏/横屏
   注意：本块为纯追加，不修改上方任何既有规则。
   ══════════════════════════════════════════════════ */

/* ② PIN 键盘宽度
   .privacy-lock 是 align-items:center 的 flex 列，其子项宽度会先收缩为
   fit-content 再受 max-width 约束 —— max-width 只是「上限」而非「目标宽度」，
   所以原 max-width:260px 永远吃不到，实测恒停在 169.4px（= 3×51.1 + 2×8），
   按键被压成窄长条。补 width:100% 把上限真正变成宽度。 */
.pin-pad {
  width: 100%; max-width: 300px;
  gap: 10px; margin: 10px auto 0;
}
.pin-key {
  padding: 0; height: 54px;   /* 原 padding:15px 参与宽度计算且撑高，改用定高 */
  display: flex; align-items: center; justify-content: center;
}

/* ③ PIN 空白键
   app.js 用 '' 占位（键盘左下角空格），它同样带 .pin-key 类，
   底色/圆角和数字键一模一样、点了又没反应 —— 看起来像个坏掉的按钮。
   属性选择器精确命中，因此不需要改 app.js。 */
.pin-key[data-key=""] {
  background: transparent;
  cursor: default;
  pointer-events: none;
}

/* ④ 矮屏 / 横屏
   .privacy-lock 固定 60px 上内边距 + 243px 键盘，在 360×640 上已溢出 7px，
   740×360 横屏上溢出 287px（必须滚动才能按到数字 0）。按可视高度分档压缩。 */
@media (max-height: 720px) {
  .privacy-lock                { padding: 28px 20px 24px; gap: 13px; }
  .privacy-lock .lock-icon .gi { width: 46px; height: 46px; }
  .pin-key                     { height: 48px; }
}
@media (max-height: 500px) {
  .privacy-lock            { padding: 12px 20px 12px; gap: 10px; }
  .privacy-lock .lock-icon { display: none; }   /* 横屏优先保证键盘完整可见 */
  .privacy-lock h3         { font-size: .92rem; }
  .privacy-lock p          { font-size: .76rem; }
  .pin-pad                 { max-width: 260px; gap: 8px; }
  .pin-key                 { height: 36px; font-size: 1rem; }
}

/* ① 宽屏外壳约束
   SPA 是纯移动版式，全文件只有一条 @media(max-width:340px)，没有任何宽屏适配，
   768px+ 会把内容整块横向摊开：快捷宫格单格 256px 而图标只占 46px、
   设置项标题与右侧箭头相距 1170px、.fab 贴到视口最右边缘。
   这里把 #app 收成一个居中的应用框：
     · transform 使 #app 成为其内部所有 position:fixed 后代
       （.page-overlay / .bottom-nav / .chat-overlay / .batch-bar /
         .upload-drop-zone / .fab / .info-add-btn / #global-loading）
       的包含块，它们随之自动落进框内，无需逐个改定位；
     · .mask（对话框、动作面板）与 .toast 挂的是 document.body，
       仍是全视口，而框本身居中 ⇒ 视觉位置不变，无需改动。 */
@media (min-width: 768px) {
  body { background: #e6eaf2; }
  #app {
    max-width: 600px; margin: 0 auto;
    transform: translateZ(0);
    box-shadow: 0 0 0 1px rgba(15, 35, 75, .06), 0 10px 44px rgba(15, 35, 75, .14);
  }
}

/* ══════════════════════════════════════════════════
   隐私空间 2026-09-13（真实实现）
   新增：PIN 错误提示、底部链接行、空间内文件列表的计数条。
   键盘主体沿用上方 .privacy-lock / .pin-* 既有规则，这里只补缺口。
   ══════════════════════════════════════════════════ */

/* PIN 错误 / 锁定提示。默认不占位（避免提示出现时键盘整体上跳），
   用 min-height 预留一行，文案换行时还能再撑高。 */
.pin-err {
  display: none;
  min-height: 18px;
  font-size: .8rem; line-height: 1.5;
  color: var(--ys-danger);
  max-width: 300px; text-align: center;
}
.pin-err.show { display: block; }

/* 底部链接行：忘记密码 / 重新输入 / 锁定 */
.priv-foot { display: flex; gap: 18px; justify-content: center; flex-wrap: wrap; margin-top: 2px; }
.priv-link {
  font-size: .8rem; color: var(--text-3); cursor: pointer;
  padding: 4px 2px; -webkit-tap-highlight-color: transparent;
}
.priv-link:active { color: var(--primary); }

/* 空间内文件列表顶部：计数 + 锁定 */
.priv-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 16px 8px;
  border-bottom: 1px solid var(--border);
}
.priv-count { font-size: .78rem; color: var(--text-3); }

/* 空态里的补充说明（.te-hint 原本只在 .transfer-empty 下有样式） */
.empty-tip .te-hint {
  font-size: .75rem; color: var(--text-4);
  line-height: 1.65; margin: 6px 0 0; padding: 0 8px; max-width: 300px;
}

/* 批量操作条：从 3 个按钮增到 4 个（新增「隐私」），
   360px 及以下的窄屏把内边距与字号收一档，避免「已选 N 项」被挤成两行。 */
@media (max-width: 380px) {
  .batch-bar           { padding: 0 10px; gap: 8px; }
  .batch-bar .bb-actions { gap: 6px; }
  .batch-bar .bb-btn   { font-size: .76rem; padding: 4px 7px; }
  .batch-bar .bb-info  { font-size: .8rem; }
}

/* ══════════════════════════════════════════════════
   订单信息（「我的」→ 订单信息）

   数据边界：只展示云盘自有的两类订单 —— 存储扩容包 / SVIP 会员
   （表 cim_cloud_orders，见 api/orders.php）。集市订单、商家入驻、
   置顶、红包等其它来源的订单**不在本模块的样式与数据范围内**。

   两个视图共用一套卡片语言：
     list —— 我的订单（筛选胶囊 + 汇总条 + 订单卡 + 加载更多）
     buy  —— 购买增值服务（模块标题 + 三列套餐卡 + 权益/提示 + 底部购买栏）
   状态色：已完成=绿 · 已关闭=灰 · 处理中=橙 · 异常=红
   ══════════════════════════════════════════════════ */

/* 筛选条：两行（订单类型 / 订单状态），复用文件页的 .fchip 胶囊语言。
   ⚠️ 用折行而非横向滚动：与文件页 .filter-chips 同一规范 ——
      横向滚动条在移动端不可发现，用户会以为「只有这几个选项」。
   两行胶囊各自独立（类型 / 状态），互不影响。 */
.ord-chips {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 10px 16px 0;
}
.ord-chips + .ord-chips { padding-top: 8px; }

/* 汇总条：共 N 单 · 扩容包 x · 会员 y · 累计消费 ¥z
   口径 = 我的全部订单，不随筛选变化（否则一筛选数字就变，用户会以为单丢了） */
.ord-stat {
  margin: 12px 16px 0; padding: 9px 12px;
  background: var(--primary-lighter); border-radius: var(--radius);
  font-size: .74rem; color: var(--text-3); line-height: 1.7;
}
.ord-stat b { color: var(--primary); font-weight: 700; }

.ord-list { padding: 10px 16px 4px; }

.ord-card {
  background: #fff; border-radius: var(--radius);
  padding: 12px 14px; margin-bottom: 10px; cursor: pointer;
}
.ord-card:active { background: var(--bg); }
.ord-card-top { display: flex; align-items: center; gap: 6px; margin-bottom: 9px; }
.ord-no {
  margin-left: auto; font-size: .68rem; color: var(--text-4);
  font-family: ui-monospace, Menlo, Consolas, monospace;
}
/* 类型徽标：扩容包=蓝（存储属性）· SVIP会员=金（付费权益属性） */
.ord-kind, .ord-badge {
  font-size: .66rem; padding: 2px 7px; border-radius: 4px;
  font-weight: 600; flex-shrink: 0; white-space: nowrap;
}
.ord-kind.quota { color: var(--primary);     background: var(--primary-lighter); }
.ord-kind.vip   { color: var(--ys-gold-deep); background: var(--ys-warn-bg); }
.ord-badge.s1 { color: var(--ys-success); background: var(--ys-success-bg); }
.ord-badge.s2 { color: var(--text-3);     background: var(--bg); }
.ord-badge.s0 { color: var(--ys-warn-text); background: var(--ys-warn-bg); }

.ord-plan { font-size: .92rem; font-weight: 700; color: var(--text); }
.ord-sum  {
  font-size: .76rem; color: var(--text-3); margin-top: 5px; line-height: 1.5;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ord-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-top: 9px;
}
.ord-time   { font-size: .72rem; color: var(--text-4); }
.ord-amount { font-size: .98rem; font-weight: 800; color: var(--ys-danger); }

.ord-more { text-align: center; font-size: .78rem; color: var(--primary); padding: 12px; cursor: pointer; }
.ord-more.done { color: var(--text-4); cursor: default; }

.ord-empty-btn {
  display: inline-block; margin-top: 12px; padding: 8px 22px;
  background: var(--primary); color: #fff; border-radius: 18px;
  font-size: .8rem; font-weight: 600; cursor: pointer;
}
.ord-empty-btn:active { opacity: .85; }

/* 骨架屏（加载中三态之一：加载中 / 空数据 / 异常） */
.sk {
  background: linear-gradient(90deg, #f0f2f5 25%, #e6e9ee 37%, #f0f2f5 63%);
  background-size: 400% 100%;
  border-radius: 6px;
  animation: sk-shine 1.2s ease-in-out infinite;
}
@keyframes sk-shine { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.sk-card { cursor: default; }
.sk-row { display: flex; align-items: center; gap: 10px; }
.sk-row + .sk-row { margin-top: 10px; }
.sk-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.sk-thumb { width: 46px; height: 46px; border-radius: 10px; flex-shrink: 0; }
.sk-w20 { width: 20%; } .sk-w30 { width: 30%; } .sk-w40 { width: 40%; }
.sk-w50 { width: 50%; } .sk-w70 { width: 70%; }

/* ══════════════════════════════════════════════════
   购买增值服务（buy 视图）

   结构照搬参考页 yunpan-vip：顶部标题 + 免费额度徽章 → 存储扩容包模块
   → SVIP 会员模块（含「不赠送空间」醒目提示）→ 权益列表 → 常见组合参考
   → 底部购买栏。配色改用本项目设计令牌（--ys-gold 即主站「集市金」），
   与云盘其余页面保持同一套视觉语言，不另起一套色板。
   ══════════════════════════════════════════════════ */
.buy-hero { text-align: center; padding: 16px 16px 4px; }
.buy-hero h1 { font-size: 1.15rem; font-weight: 700; color: var(--ys-ink); }
.buy-hero p  { font-size: .78rem; color: var(--ys-ink-4); line-height: 1.6; margin-top: 6px; }
.buy-free-badge {
  display: inline-block; margin-top: 10px; padding: 5px 14px;
  background: #fff; border: 1px solid var(--ys-line-strong);
  border-radius: 20px; font-size: .72rem; color: var(--ys-ink-3);
}
.buy-free-badge b { color: var(--ys-gold-deep); }

.buy-sec { display: flex; align-items: center; gap: 8px; padding: 4px 16px; margin: 22px 0 12px; }
.buy-sec-ico {
  width: 28px; height: 28px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.buy-sec-ico .gi { width: 16px; height: 16px; }
.buy-sec-ico.quota { background: var(--primary-lighter); color: var(--primary); }
.buy-sec-ico.vip   { background: var(--ys-warn-bg);       color: var(--ys-gold-deep); }
.buy-sec-bd { min-width: 0; }
.buy-sec-title { font-size: .95rem; font-weight: 700; color: var(--ys-ink); }
.buy-sec-sub   { font-size: .7rem; color: var(--ys-ink-4); margin-top: 3px; line-height: 1.45; }

/* 三列套餐卡：窄屏也不换行（参考页在 390px 下就是三列） */
.buy-cards {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 8px; padding: 0 16px;
}
.buy-card {
  position: relative; background: #fff; cursor: pointer;
  border: 2px solid var(--ys-line-strong); border-radius: var(--ys-r-lg);
  padding: 18px 6px 14px; text-align: center;
  transition: border-color var(--ys-dur) var(--ys-ease), transform var(--ys-dur) var(--ys-ease);
}
.buy-card:active { transform: scale(.97); }
.buy-card.active {
  border-color: var(--ys-gold);
  background: linear-gradient(180deg, #fffaf0 0%, #fff 100%);
  box-shadow: 0 4px 14px rgba(245, 166, 35, .18);
}
/* 选中角标：右上角对勾（参考页同款） */
.buy-card.active::after {
  content: "✓"; position: absolute; top: -1px; right: -1px;
  width: 20px; height: 20px; display: flex; align-items: center; justify-content: center;
  background: var(--ys-gold); color: #fff;
  border-radius: 0 10px 0 10px; font-size: 12px;
}
/* 卡片顶部角标：最划算 / 推荐 */
.buy-card-tag {
  position: absolute; top: -10px; left: 50%; transform: translateX(-50%);
  background: linear-gradient(90deg, var(--ys-danger), var(--ys-gold));
  color: #fff; font-size: .62rem; padding: 2px 9px; border-radius: 10px;
  white-space: nowrap; font-weight: 600;
}
.buy-card-name  { font-size: .8rem; font-weight: 600; color: var(--ys-ink-2); margin-bottom: 7px; }
.buy-card-price {
  font-size: 1.32rem; font-weight: 800; color: var(--ys-hot); line-height: 1;
}
.buy-card-price .unit { font-size: .66rem; font-weight: 400; color: var(--ys-ink-4); margin-left: 1px; }
.buy-card-save  { font-size: .64rem; color: var(--ys-danger); margin-top: 5px; }
.buy-card-desc  { font-size: .62rem; color: var(--ys-ink-4); margin-top: 7px; line-height: 1.35; }

.buy-tips { padding: 12px 18px 0; }
.buy-tip  { font-size: .7rem; color: var(--ys-ink-4); line-height: 1.75; }

/* 「会员不赠送空间」的醒目提示（参考页用红色警示块，这里用令牌同色系） */
.buy-warn {
  display: flex; gap: 8px; align-items: flex-start;
  margin: 0 16px 12px; padding: 11px 13px;
  background: var(--ys-danger-bg); border: 1px solid var(--ys-danger-line);
  border-radius: var(--ys-r-md);
  font-size: .74rem; color: var(--ys-danger); line-height: 1.65;
}
.buy-warn-ico { flex-shrink: 0; }
.buy-warn-ico .gi { width: 15px; height: 15px; }

.buy-benefits { background: #fff; border-radius: var(--ys-r-lg); padding: 14px 16px; margin: 14px 16px 0; }
.buy-benefits-title { font-size: .82rem; font-weight: 600; color: var(--ys-ink-2); margin-bottom: 8px; }
.buy-benefit { display: flex; align-items: center; gap: 8px; font-size: .76rem; color: var(--ys-ink-3); padding: 4px 0; }
.buy-benefit .check { color: var(--ys-gold); font-weight: 700; }

.buy-example { background: #fff; border-radius: var(--ys-r-lg); padding: 14px 16px; margin: 20px 16px 0; }
.buy-example-title {
  display: flex; align-items: center; gap: 6px;
  font-size: .82rem; font-weight: 600; color: var(--ys-ink-2); margin-bottom: 10px;
}
.buy-example-title .gi { width: 16px; height: 16px; color: var(--ys-gold); }
.buy-ex {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 0; border-bottom: 1px dashed var(--ys-line-soft); font-size: .74rem;
}
.buy-ex:last-child { border-bottom: none; }
.buy-ex .desc  { color: var(--ys-ink-3); flex: 1; }
.buy-ex .price { color: var(--ys-hot); font-weight: 700; white-space: nowrap; }

/* 底部购买栏：已选明细 + 实时合计 + 立即购买（未选时按钮置灰） */
.buy-bar {
  position: sticky; bottom: 0; z-index: 2;
  display: flex; align-items: center; gap: 10px;
  margin: 22px 16px 0; padding: 12px 14px;
  background: #fff; border: 1px solid var(--ys-line);
  border-radius: var(--ys-r-lg); box-shadow: var(--ys-shadow-md);
}
.buy-bar-info { flex: 1; min-width: 0; font-size: .74rem; color: var(--ys-ink-3); line-height: 1.5; }
.buy-bar-picked { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buy-bar-total  { display: block; margin-top: 3px; }
.buy-bar-total b { color: var(--ys-hot); font-size: 1.05rem; font-weight: 800; }
.buy-bar-money  { display: block; font-size: .68rem; color: var(--ys-ink-4); margin-top: 2px; }
.buy-bar-hint i { font-style: normal; color: var(--ys-ink-5); font-size: .68rem; }
.buy-bar-btn {
  flex-shrink: 0; min-height: 42px; padding: 0 26px;
  background: linear-gradient(90deg, #ffc145, var(--ys-gold));
  border: none; border-radius: 22px; color: #fff;
  font-size: .88rem; font-weight: 700; cursor: pointer;
  box-shadow: 0 4px 12px rgba(245, 166, 35, .35);
  transition: transform var(--ys-dur) var(--ys-ease);
}
.buy-bar-btn:active { transform: translateY(1px); }
.buy-bar-btn.dis { opacity: .45; box-shadow: none; cursor: not-allowed; }

/* ══════════════════════════════════════════════════
   订单详情（二级浮层）
   ══════════════════════════════════════════════════ */
.odx-status {
  margin: 12px 16px 0; padding: 16px; border-radius: var(--radius);
  background: var(--ys-success-bg); color: var(--ys-success);
}
.odx-status.s2 { background: var(--bg);             color: var(--text-2); }
.odx-status.s0 { background: var(--ys-warn-bg);     color: var(--ys-warn-text); }
.odx-status.s9 { background: var(--ys-danger-bg);   color: var(--ys-danger); }
.odx-st-name { font-size: 1.02rem; font-weight: 700; }
.odx-st-hint { font-size: .74rem; opacity: .9; margin-top: 5px; line-height: 1.6; }

.odx-goods { background: #fff; margin: 12px 16px 0; border-radius: var(--radius); padding: 4px 14px; }
.odx-g { display: flex; align-items: center; gap: 10px; padding: 12px 0; }
.odx-g-img {
  width: 40px; height: 40px; border-radius: var(--ys-r-md); flex-shrink: 0;
  background: var(--primary-lighter); color: var(--primary);
  display: flex; align-items: center; justify-content: center;
}
.odx-g-img .gi { width: 20px; height: 20px; }
.odx-g-bd { flex: 1; min-width: 0; }
.odx-g-n { font-size: .86rem; color: var(--text); font-weight: 600; }
.odx-g-s { font-size: .72rem; color: var(--text-3); margin-top: 3px; }
.odx-g-a { font-size: .86rem; font-weight: 700; color: var(--text); flex-shrink: 0; }
.odx-total {
  display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  padding: 12px 0; border-top: 1px solid var(--border);
  font-size: .78rem; color: var(--text-3);
}
.odx-total b { font-size: 1.12rem; font-weight: 800; color: var(--ys-danger); }

.odx-meta { background: #fff; margin: 12px 16px 0; border-radius: var(--radius); padding: 4px 14px; }
.odx-row {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 10px 0; border-bottom: 1px solid var(--border);
}
.odx-row:last-child { border-bottom: none; }
.odx-k { font-size: .76rem; color: var(--text-3); flex-shrink: 0; }
.odx-v { font-size: .78rem; color: var(--text); text-align: right; word-break: break-all; }
.odx-v.copy { color: var(--primary); cursor: pointer; }
.odx-v.copy:active { opacity: .7; }

.odx-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; padding: 18px 16px 8px; }
.odx-actions .ord-btn { padding: 9px 24px; font-size: .82rem; }

.ord-btn {
  padding: 6px 14px; border-radius: 16px; font-size: .76rem; cursor: pointer;
  background: var(--bg); color: var(--text-2); border: 1px solid var(--border);
  white-space: nowrap;
}
.ord-btn:active { opacity: .8; }

/* 窄屏收一档：套餐卡三列在 360px 下仍要放得下，价格不能换行 */
@media (max-width: 400px) {
  .buy-cards { gap: 6px; padding: 0 12px; }
  .buy-card { padding: 16px 4px 12px; }
  .buy-card-name  { font-size: .74rem; }
  .buy-card-price { font-size: 1.14rem; }
  .buy-card-desc  { font-size: .58rem; }
  .buy-bar { margin: 18px 12px 0; padding: 10px 12px; gap: 8px; }
  .buy-bar-btn { padding: 0 20px; font-size: .82rem; }
}

/* ══════════════════════════════════════════════════════════════
   用户自有存储（FTP / 存储桶）—— 设置页
   ══════════════════════════════════════════════════════════════ */
.store-now {
  margin: 0 16px 8px; padding: 9px 12px; border-radius: var(--radius-sm);
  background: var(--ys-bg-sunken); font-size: .78rem; color: var(--text-2);
}
.store-now.is-custom { background: var(--ys-success-bg); color: var(--ys-success); font-weight: 500; }
.store-now b { font-weight: 600; }

.settings-item.store-row { display: flex; align-items: center; gap: 8px; }
.store-row-main { flex: 1; min-width: 0; }
.store-row-main label { display: block; }
.store-row-sub { font-size: .72rem; color: var(--text-3); margin-top: 2px; }
.store-state { font-size: .72rem; color: var(--text-3); white-space: nowrap; }
.store-vip-tag {
  font-style: normal; font-size: .6rem; font-weight: 700; color: #fff;
  background: linear-gradient(135deg, #f5a623, #e08b12);
  border-radius: 8px; padding: 1px 6px; margin-left: 5px; vertical-align: 1px;
}

.store-note {
  margin: 12px 16px 0; padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--ys-brand-lighter); color: var(--text-2);
  font-size: .76rem; line-height: 1.65;
}
.store-note b { color: var(--primary); }

.store-form  { padding: 14px 16px 28px; }
.store-field { margin-bottom: 13px; }
.store-field > label { display: block; font-size: .76rem; color: var(--text-3); margin-bottom: 5px; }
.store-field input, .store-field select {
  width: 100%; padding: 10px 12px; box-sizing: border-box;
  background: var(--bg); border-radius: var(--radius-sm); border: 1.5px solid transparent;
  font-size: .86rem; color: var(--text); transition: border-color .2s;
  font-family: inherit;
}
.store-field input:focus, .store-field select:focus { border-color: var(--primary); background: #fff; }
.store-field-row { display: flex; gap: 10px; }
.store-field-row .store-field { flex: 1; min-width: 0; }
.store-field.store-switch { font-size: .8rem; color: var(--text-2); }
.store-field.store-switch label { display: flex; align-items: flex-start; gap: 7px; cursor: pointer; line-height: 1.5; }
.store-field.store-switch input { width: auto; margin-top: 2px; flex-shrink: 0; }

.store-help {
  margin-top: 14px; padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--ys-bg-sunken); color: var(--text-3);
  font-size: .72rem; line-height: 1.7; word-break: break-word;
}
.store-help b { color: var(--text-2); }
.store-help code { background: #fff; border-radius: 3px; padding: 0 3px; font-size: .7rem; }
.store-hint { font-size: .72rem; color: var(--text-3); line-height: 1.65; margin: -4px 0 12px; }

.store-actions { display: flex; gap: 10px; margin-top: 6px; }
.store-btn {
  flex: 1; padding: 12px; border: none; border-radius: var(--radius);
  background: var(--primary); color: #fff; font-size: .88rem; font-weight: 600;
  cursor: pointer; transition: background .2s;
}
.store-btn:active { background: var(--primary-dark); }
.store-btn:disabled { opacity: .6; }
.store-btn.ghost { background: var(--bg); color: var(--text-2); border: 1px solid var(--border-2); }
.store-btn.ghost:active { background: var(--ys-bg-sunken); }
.store-btn.text-danger {
  flex: none; width: 100%; margin-top: 10px; background: transparent;
  color: var(--ys-danger); font-size: .8rem; font-weight: 500; border: none; padding: 8px;
}
.store-btn.text-danger:active { opacity: .7; }

.store-lock {
  padding: 18px 16px; margin-bottom: 14px; border-radius: var(--radius);
  background: linear-gradient(135deg, #fff9ef, #fff3dd);
  border: 1px solid #f6dfae; text-align: center;
}
.store-lock-ico { font-size: 1.9rem; line-height: 1.2; }
.store-lock-t { font-size: .88rem; font-weight: 600; color: var(--ys-gold-deep); margin: 6px 0; }
.store-lock-d { font-size: .74rem; color: #8a6520; line-height: 1.65; margin-bottom: 12px; }
.store-lock .store-btn { background: linear-gradient(135deg, #f5a623, #e08b12); }
#bucket-fields.is-locked { display: none; }

.store-test-box {
  margin: 12px 0; padding: 10px 12px; border-radius: var(--radius-sm);
  font-size: .76rem; line-height: 1.6;
}
.store-test-box.ok  { background: var(--ys-success-bg); color: var(--ys-success); border: 1px solid var(--ys-success-line); }
.store-test-box.bad { background: var(--ys-danger-bg);  color: var(--ys-danger);  border: 1px solid var(--ys-danger-line); }
.store-test-title { font-weight: 600; margin-bottom: 6px; }
.store-steps { margin-top: 6px; }
.store-step { display: flex; gap: 6px; align-items: flex-start; padding: 3px 0; color: var(--text-2); }
.store-step .ss-ico { flex-shrink: 0; font-weight: 700; }
.store-step.ok  .ss-ico { color: var(--ys-success); }
.store-step.bad .ss-ico { color: var(--ys-danger); }
.store-step .ss-name { flex-shrink: 0; }
.store-step .ss-detail { color: var(--text-3); font-size: .72rem; word-break: break-all; }

/* ── 平台存储 → 自有桶 同步卡片（2026-09-14，见 includes/store_sync.php） ── */
.sync-card {
  margin-top: 14px; padding: 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--ys-bg-sunken);
}
.sync-head {
  display: flex; align-items: center; gap: 6px;
  font-size: .82rem; font-weight: 700; color: var(--text); margin-bottom: 7px;
}
.sync-head .gi { width: 15px; height: 15px; flex-shrink: 0; color: var(--primary); }
.sync-desc { font-size: .76rem; line-height: 1.65; color: var(--text-2); word-break: break-word; }
.sync-desc b { color: var(--primary); }
.sync-prog { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.sync-bar { flex: 1; min-width: 0; height: 6px; border-radius: 3px; background: var(--border); overflow: hidden; }
.sync-bar > i {
  display: block; height: 100%; width: 0; border-radius: 3px;
  background: var(--ys-gold-grad); transition: width .35s ease;
}
.sync-pct { font-size: .68rem; color: var(--text-3); white-space: nowrap; }
.sync-fails { margin-top: 10px; }
.sync-fails-t { font-size: .7rem; font-weight: 600; color: var(--ys-danger); margin-bottom: 4px; }
.sync-fail-row { display: flex; gap: 6px; font-size: .7rem; line-height: 1.55; padding: 2px 0; }
.sync-fail-row .sfr-name {
  flex: 0 1 46%; min-width: 0; color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sync-fail-row .sfr-msg { flex: 1 1 0; min-width: 0; color: var(--text-3); word-break: break-word; }
.sync-actions { display: flex; gap: 8px; margin-top: 11px; flex-wrap: wrap; }
/* 覆盖 .store-btn 的 flex:1 / padding:12px：窄屏要能两列并排且不溢出 */
.sync-actions .store-btn { flex: 1 1 40%; min-width: 0; padding: 10px 8px; font-size: .8rem; }
/* 只剩一个按钮时撑满整行：40% 基线会让单按钮右侧留一大片空白，看着像没做完 */
.sync-actions.is-single .store-btn { flex: 1 1 100%; }

/* 「我的」页容量卡下方的存储方式标签 */
.ms-mode {
  display: flex; align-items: center; gap: 6px;
  margin-top: 10px; padding: 7px 10px; border-radius: var(--radius-sm);
  font-size: .72rem; line-height: 1.5;
}
.ms-mode.is-bucket { background: var(--ys-success-bg); color: var(--ys-success); }
.ms-mode.is-ftp    { background: var(--ys-brand-lighter); color: var(--primary); }
.ms-mode .msm-dot {
  width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
  background: currentColor;
}

/* 下载限速说明（「我的」页容量卡下方） */
.ms-limit {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin: 8px 0; padding: 7px 10px; border-radius: var(--radius-sm);
  font-size: .72rem; line-height: 1.5;
  background: var(--ys-warn-bg, #fff7e6); color: var(--ys-warn, #b45309);
}
/* 自有存储（桶 / 直链 FTP）不限速 —— 这不是「套餐限制」，换成中性色，别用告警黄 */
.ms-limit.is-direct {
  background: var(--ys-success-bg, #f6fffb); color: var(--ys-success, #00a870);
}
.ms-limit .msm-dot {
  width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
  background: currentColor;
}
.ms-limit b { font-weight: 600; }

/* 「我的」页容量卡下方的扩容包有效期（与会员有效期是两个独立时间） */
.ms-expand {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 8px; padding: 7px 10px; border-radius: var(--radius-sm);
  font-size: .72rem; line-height: 1.5;
  background: var(--ys-brand-lighter); color: var(--primary);
}
.ms-expand .msm-dot {
  width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
  background: currentColor;
}
.ms-expand b { font-weight: 600; }

/* 并发数分段控件：超出当前套餐上限的档位置灰 */
.seg-item.is-over { opacity: .38; cursor: not-allowed; }
.concurrent-tip {
  margin-top: 6px; font-size: .7rem; line-height: 1.45;
  color: var(--text-3, #8a94a3);
  text-align: center;
}

/* 窄屏：两列字段在 360px 下仍要放得下 */
@media (max-width: 400px) {
  .store-field-row { gap: 8px; }
  .store-field input, .store-field select { padding: 9px 10px; font-size: .82rem; }
  .store-btn { padding: 11px 8px; font-size: .84rem; }
}


/* ══════════════════════════════════════════════════
   两步验证 + 「隐私与安全」模块（2026-09-13）
   —— 变量取自 tokens.css，全部为已存在令牌（避免静默失效）
   ══════════════════════════════════════════════════ */

/* 只读条目：不给点击反馈，避免让人误以为能点（原「位置信息」死开关的教训） */
.settings-item.ps-ro { cursor: default; }
.settings-item.ps-ro:active { background: transparent; }

/* 密码「未设置」用警示色，与「已设置」一眼区分 */
.settings-item .sv.warn { color: var(--ys-warn-text); }

/* 模块底部说明 */
.ps-foot { padding: 14px 16px 22px; font-size: .72rem; line-height: 1.7; color: var(--text-3); }

/* ── 两步验证：开启流程 ── */
.otp-steps { padding: 6px 16px 24px; }
.otp-step { display: flex; align-items: center; gap: 8px; margin: 16px 0 10px; font-size: .84rem; font-weight: 600; color: var(--text); }
.otp-step b { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; background: var(--primary); color: #fff; font-size: .72rem; font-weight: 700; flex-shrink: 0; }
.otp-qr { display: flex; align-items: center; justify-content: center; padding: 14px; background: #fff; border: 1px solid var(--ys-line); border-radius: var(--radius); min-height: 180px; }
.otp-qr svg { width: 190px; height: 190px; }
.otp-qr-fail { font-size: .78rem; color: var(--text-3); text-align: center; line-height: 1.6; }
.otp-manual { margin-top: 12px; font-size: .78rem; }
.otp-manual summary { cursor: pointer; color: var(--primary); padding: 4px 0; }
.otp-secret { margin-top: 8px; padding: 11px 13px; background: var(--ys-bg-sunken); border-radius: var(--radius-sm); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .84rem; letter-spacing: .08em; word-break: break-all; color: var(--text); user-select: all; }
.otp-manual-hint { margin-top: 6px; font-size: .72rem; color: var(--text-3); line-height: 1.6; }
.otp-note { margin-top: 14px; font-size: .72rem; line-height: 1.7; color: var(--text-3); }

/* 动态码输入：等宽 + 居中 + 字距加大，减少抄错 */
#otp-code, #og-code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; letter-spacing: .18em; text-align: center; font-size: 1.05rem; }

/* ── 两步验证：恢复码 ── */
.otp-warn { display: flex; gap: 9px; align-items: flex-start; padding: 12px 13px; background: var(--ys-warn-bg); border-radius: var(--radius); font-size: .78rem; line-height: 1.65; color: var(--ys-warn-text); }
.otp-warn svg { width: 16px; height: 16px; flex-shrink: 0; margin-top: 2px; }
.otp-codes { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 16px 0 20px; }
.otp-codes span { padding: 11px 6px; background: var(--ys-bg-sunken); border-radius: var(--radius-sm); text-align: center; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .95rem; letter-spacing: .1em; color: var(--text); user-select: all; }

/* ── 登录时的两步验证层 ── */
#otp-gate { position: fixed; inset: 0; z-index: 1200; display: flex; align-items: center; justify-content: center; padding: 24px; background: var(--bg); }
.otp-gate-box { width: 100%; max-width: 340px; display: flex; flex-direction: column; align-items: center; }
.og-icon { display: flex; align-items: center; justify-content: center; width: 64px; height: 64px; border-radius: 50%; background: var(--ys-brand-lighter); color: var(--primary); margin-bottom: 18px; }
.og-icon svg { width: 30px; height: 30px; }
.og-title { font-size: 1.15rem; font-weight: 700; color: var(--text); }
.og-sub { margin: 8px 0 22px; font-size: .82rem; color: var(--text-3); text-align: center; }
.otp-gate-box .cd-input { width: 100%; margin-bottom: 16px; }
.otp-gate-box .btn-submit { width: 100%; }
.og-hint { margin-top: 16px; font-size: .74rem; line-height: 1.6; color: var(--text-3); text-align: center; }
.og-out { margin-top: 20px; font-size: .82rem; color: var(--primary); cursor: pointer; }


/* ── 两步验证：验证器 App 选择指引 ──
   用户根本不知道「认证器」是什么 App ⇒ 直接在二维码下方给三条可执行的路径。
   令牌全部取自 tokens.css，不新造变量（避免静默失效）。 */
.otp-apps { margin-top: 12px; padding: 12px 13px; background: var(--ys-bg-sunken); border-radius: var(--radius); }
.otp-apps-t { margin-bottom: 8px; font-size: .74rem; font-weight: 600; color: var(--text-2); }
.otp-app { display: flex; gap: 8px; margin-top: 6px; font-size: .74rem; line-height: 1.6; color: var(--text-2); }
.otp-app b { flex-shrink: 0; min-width: 58px; color: var(--primary); font-weight: 600; }
.otp-app span { color: var(--text-3); }
.otp-apps-note { margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--ys-line); font-size: .7rem; line-height: 1.6; color: var(--text-3); }


/* ── 隐私与安全：只读「验证器」+「一次性恢复码」状态 ──
   两者均在两步验证已开启时渲染（未开启时与上方开关重复，纯噪音）。
   - 验证器：绑定的那一刻是「怎么绑」，之后的高频困惑是「下次登录去哪儿看这个码」
     ⇒ 直接给出可执行路径，而不是把用户再送回开启流程。
   - 恢复码：用掉几个之后用户无从知晓（库里只存 md5，明文只在开启那一次显示过）
     ⇒ 剩 1-2 个转琥珀、用尽转红，副标题始终给出「关闭后重新开启」这条出路。
   ⚠️ .psv-main 必须 flex:1 + min-width:0 —— 否则窄屏下副标题撑破容器不换行。 */
.ps-verif, .ps-backup { cursor: default; }
.ps-verif .psv-main, .ps-backup .psv-main { flex: 1; min-width: 0; }
.ps-verif .psv-main label, .ps-backup .psv-main label { display: block; cursor: default; }
.ps-verif .psv-sub, .ps-backup .psv-sub { display: block; margin-top: 3px; font-size: .74rem; line-height: 1.5; color: var(--text-3); }
.ps-verif .sv, .ps-backup .sv { flex-shrink: 0; margin-left: 10px; }
/* 恢复码低量警示：warn=琥珀（还剩 1-2 个）／danger=红（已用尽，验证器丢失即无法登录） */
.settings-item .sv.danger { color: var(--ys-danger); }


/* ── 「移动到文件夹」目录选择器（2026-09-14）──
   浮层结构与 .page-overlay(flex column) 配合：.mv-crumb / .ov-body 撑开中间，
   .mv-foot 用 flex-shrink:0 常驻贴底（长目录列表滚动时按钮不会跟着跑）。 */
.mv-crumb {
  padding: 10px 16px; display: flex; align-items: center; gap: 4px;
  overflow-x: auto; white-space: nowrap;
  font-size: .8rem; color: var(--text-3);
  scrollbar-width: none; flex-shrink: 0;
  border-bottom: 1px solid var(--border);
}
.mv-crumb::-webkit-scrollbar { display: none; }
.mv-foot {
  padding: 12px 16px; background: #fff; flex-shrink: 0;
  border-top: 1px solid var(--border);
  padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
}
.mv-btn {
  width: 100%; height: 44px; border: none; cursor: pointer;
  border-radius: var(--radius-sm);
  background: var(--primary); color: #fff;
  font-size: .95rem; font-weight: 600; font-family: inherit;
}
.mv-btn:disabled { opacity: .6; cursor: default; }
.mv-enter { display: flex; align-items: center; flex-shrink: 0; color: var(--text-4); }
.mv-enter svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2; }
.mv-row.mv-self { opacity: .55; }
.mv-self .file-meta { color: var(--ys-danger); }


/* ── 批量操作条：4 → 5 个按钮（2026-09-14 新增常驻「移动」）──
   「下载 / 移动」是批量场景最高频的两个动作，此前「移动」只在二级「更多」菜单里，
   用户点开只看到三项就判定功能没做 ⇒ 提到顶栏与「下载」并列。

   挤压对策（320px 最紧，实测驱动）：
     · 按钮组 flex:0 0 auto —— 永不被压缩，保证每个按钮都点得到；
     · 「已选 N 项」min-width:0 + overflow:hidden —— 空间不足时它先让位（走省略号），
       ⚠️ 反面教材：flex:1 不写 min-width:0 时其 min-content = 整行宽度，
          文本区拒绝收缩，会把定宽的按钮组顶出屏幕（与 .vb-text 那次同因）。
     · ≤440px 把字号/内边距收一档：原紧凑档断点是 380px（4 按钮时代调的），
       5 个按钮在 390px 就会挤到文案截断，所以整档上移到 440px。 */
.batch-bar .bb-actions { flex: 0 0 auto; }
.batch-bar .bb-info {
  flex: 1 1 0; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 440px) {
  .batch-bar             { padding: 0 10px; gap: 8px; }
  .batch-bar .bb-cancel  { font-size: .8rem; }
  .batch-bar .bb-info    { font-size: .78rem; }
  .batch-bar .bb-actions { gap: 4px; }
  .batch-bar .bb-btn     { font-size: .72rem; padding: 4px 6px; }
}

/* ══════════════════════════════════════════════════
   PARSE PAGE（传输页 → 云解析）
   ──────────────────────────────────────────────────
   全部使用设计令牌（tokens.css），此处禁止出现颜色字面量。
   三段结构：标题区 → 使用须知 → 解析引擎表单（+ 结果区）。
   ══════════════════════════════════════════════════ */

/* ── 标题区 ── */
.parse-hero { padding: 22px 16px 6px; text-align: center; }
.parse-hero-ico {
  width: 54px; height: 54px; margin: 0 auto 10px;
  border-radius: var(--ys-r-md);
  background: var(--ys-brand-light); color: var(--ys-brand);
  display: flex; align-items: center; justify-content: center;
}
.parse-hero-ico svg { width: 28px; height: 28px; stroke: currentColor; fill: none; stroke-width: 1.8; }
.parse-hero h2 { font-size: var(--ys-fs-lg); font-weight: 700; color: var(--ys-ink); }
.parse-hero p  { font-size: var(--ys-fs-sm); color: var(--ys-ink-4); margin-top: 4px; }

/* ── 通用卡片壳 ── */
.parse-card {
  margin: 12px 12px 0; padding: 14px;
  background: var(--ys-bg-card); border-radius: var(--ys-r-lg);
}

/* ── 使用须知（琥珀语义色，与「警示」语义一致）── */
.pn-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.pn-head svg { width: 18px; height: 18px; stroke: var(--ys-warn); fill: none; stroke-width: 2; flex-shrink: 0; }
.pn-head span { font-size: var(--ys-fs-md); font-weight: 700; color: var(--ys-ink); }
.pn-grid { display: grid; grid-template-columns: 1fr; gap: 10px; }
.pn-item { display: flex; gap: 8px; align-items: flex-start; }
/* 窄屏靠上分隔线、宽屏靠左分隔线：同一组三栏，两种排布下都有分隔感 */
.pn-item + .pn-item { border-top: 1px dashed var(--ys-line); padding-top: 10px; }
.pn-ico { flex-shrink: 0; margin-top: 2px; }
.pn-ico svg { width: 15px; height: 15px; stroke: var(--ys-warn); fill: none; stroke-width: 1.8; }
.pn-item p { font-size: var(--ys-fs-sm); line-height: 1.7; color: var(--ys-ink-3); }
@media (min-width: 520px) {
  .pn-grid { grid-template-columns: repeat(3, 1fr); gap: 12px; }
  .pn-item + .pn-item {
    border-top: none; padding-top: 0;
    border-left: 1px dashed var(--ys-line); padding-left: 12px;
  }
}

/* ── 解析引擎表单 ── */
.pf-head { margin-bottom: 14px; }
.pf-head h3 { font-size: var(--ys-fs-md); font-weight: 700; color: var(--ys-ink); }
.pf-head p  { font-size: var(--ys-fs-sm); color: var(--ys-ink-4); margin-top: 3px; }

.pf-field { margin-bottom: 14px; }
.pf-label {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--ys-fs-sm); color: var(--ys-ink-3); margin-bottom: 6px;
}
.pf-label svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.8; flex-shrink: 0; }
.pf-label .pf-opt { color: var(--ys-ink-5); }

/* 链接用 textarea：用户复制的是**整段分享文案**（带「链接：/提取码：」），
   单行 input 装不下一段多行文本，也看不到自己粘了什么。 */
.pf-input, .pf-textarea {
  width: 100%; padding: 11px 12px;
  background: var(--ys-bg-sunken);
  border: 1px solid var(--ys-line);
  border-radius: var(--ys-r);
  font-size: var(--ys-fs-base); color: var(--ys-ink);
  line-height: 1.6; resize: vertical;
  transition: border-color var(--ys-dur) var(--ys-ease), background var(--ys-dur) var(--ys-ease);
}
.pf-textarea { min-height: 62px; max-height: 160px; }
.pf-input:focus, .pf-textarea:focus {
  border-color: var(--ys-brand); background: var(--ys-bg-card);
}
.pf-input::placeholder, .pf-textarea::placeholder { color: var(--ys-ink-5); }

/* 返回格式：复用 .seg-ctrl 的令牌与选中态，只覆盖布局（撑满宽度） */
.pf-seg { display: flex; width: 100%; }
.pf-seg .seg-item { flex: 1; height: 34px; gap: 6px; font-weight: 500; }
.pf-seg .seg-item svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.8; }

/* ── 按钮 ── */
.pf-actions { display: flex; gap: 10px; margin-top: 18px; }
.pf-btn {
  height: 44px; padding: 0 18px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: 0; background: transparent;            /* <button> 默认有边框底，必须先清掉 */
  border-radius: var(--ys-r-md);
  font-size: var(--ys-fs-md); font-weight: 600;
  cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
  transition: transform .12s var(--ys-ease), opacity var(--ys-dur) var(--ys-ease);
}
.pf-btn svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2; }
.pf-btn:active { transform: scale(.97); }
.pf-btn:disabled { opacity: .5; cursor: not-allowed; }
.pf-btn:disabled:active { transform: none; }
.pf-btn.primary {
  flex: 1;
  background: var(--ys-brand-grad); color: var(--ys-ink-on-brand);
  box-shadow: var(--ys-shadow-brand);
}
.pf-btn.ghost {
  background: var(--ys-bg-card); border: 1px solid var(--ys-line-strong);
  color: var(--ys-ink-3); flex-shrink: 0;
}
/* 提交中：只降不透明度，不禁用点击 —— 禁用态由 JS 的同一把锁控制，
   样式不参与状态机（否则会出现「按钮看着能点、点了没反应」）。 */
.pf-btn.is-busy { opacity: .55; }

/* ── 功能未开放提示条 ── */
.parse-off {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 12px 12px 0; padding: 12px 14px;
  background: var(--ys-warn-bg); color: var(--ys-warn-text);
  border-radius: var(--ys-r-lg);
  font-size: var(--ys-fs-sm); line-height: 1.7;
}
.parse-off svg { width: 16px; height: 16px; flex-shrink: 0; margin-top: 2px;
                 stroke: currentColor; fill: none; stroke-width: 1.8; }

/* ── 结果区 ── */
/* ⚠️ 窄屏实测（390px，2026-09-15）：meta 串较长时会把「解析成功」压成两行「解析成/功」
   ⇒ 标题 nowrap + flex-shrink:0，meta 可收缩并省略号收尾（flex 三件套，同 §16.9）。 */
.pr-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.pr-head svg { width: 18px; height: 18px; stroke: var(--ys-success); fill: none; stroke-width: 2; flex-shrink: 0; }
.pr-title { font-size: var(--ys-fs-md); font-weight: 700; color: var(--ys-ink);
            flex-shrink: 0; white-space: nowrap; }
.pr-meta  { margin-left: auto; font-size: var(--ys-fs-sm); color: var(--ys-ink-4); text-align: right;
            min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pr-box {
  padding: 10px 12px;
  background: var(--ys-bg-sunken); border-radius: var(--ys-r);
  font-family: var(--ys-font-mono, ui-monospace), Menlo, Consolas, monospace;
  font-size: .76rem; line-height: 1.75; color: var(--ys-ink-2);
  word-break: break-all; white-space: pre-wrap;
  max-height: 224px; overflow-y: auto;
}
.pr-acts { display: flex; gap: 8px; margin-top: 10px; }
.pr-acts .pf-btn { height: 38px; font-size: var(--ys-fs-sm); flex: 1; padding: 0 12px; }
.pr-tip { margin-top: 10px; font-size: var(--ys-fs-sm); color: var(--ys-ink-4); line-height: 1.7; }
