/* ============================================================
   手机端适配层 —— 最后加载，手机上它是唯一说话的人。

   为什么单独一个文件：桌面的排布（三栏、悬浮卡片、hover 才出现的动作）
   在 390px 上全部失效。与其在每个页面样式里塞 @media，
   不如集中一处「改写」，读的人一眼能看全手机上到底改了什么。

   改写原则：
   1. 手指不是光标 —— 可点的东西至少 44×44，宁可留白也不挤图标。
   2. 拇指够不到顶 —— 主导航沉到底部，「记一笔」浮动在右下角。
   3. 浏览器工具条会吃掉视口 —— 吸底的东西一律让出 safe-area-inset。
   4. 弹窗变抽屉 —— 从底部升起、顶部有把手、往上滑或点遮罩都能关。
   5. hover 才出现的动作在触屏上等于没有 —— 一律常显。
   6. 手账味保留 —— 纸纹、手绘边、轻微倾斜都留着，只把「并排」改成「上下」。

   断点：
     ≤980px          手机与窄窗口（底部导航登场）
     ≤560px          真正的手机竖屏（再压一层）
     pointer: coarse 触屏交互差异（和宽度无关）
   ============================================================ */

/* ---------- 1. 令牌：安全区、手指、吸底高度 ---------- */
:root {
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --tap: 44px;          /* 手指能稳定按中的最小边长 */
  --bar-h: 76px;        /* 底部导航实高（不含安全区） */
  --topbar-h: 56px;
  --fab-h: 52px;
  --r-xl: 26px;
  --ease-soft: cubic-bezier(.3, .66, .35, 1);
}

@media (max-width: 980px) {
  body {
    overflow-x: hidden;
    padding-left: var(--safe-left);
    padding-right: var(--safe-right);
    /* 30px 的格线在窄屏上太稀，本子显得空；收密一点 */
    background-size: 220px 220px, 22px 22px, 22px 22px;
  }
}

/* ---------- 2. 外壳：手机上没有抽屉 ----------
   底部五格 + 「更多」已经把所有页面 cover 了，左侧栏在手机上没有存在理由。
   以前它是个从左边抽出来的 fixed 抽屉，而抽屉的 z-index 被困在 .app-shell 的层叠上下文里，
   遮罩却长在 <body> 上 —— 结果遮罩把抽屉整个盖住，导航项一个都按不到。
   现在：手机上侧栏直接不渲染，遮罩这个概念也没了。 */
@media (max-width: 980px) {
  .app-shell {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(0, 1fr) auto;
  }
  .rail { display: none; }
  .main { grid-column: 1; grid-row: 1; }
}

/* ---------- 2b. 左上格：返回 / 当前空间 ---------- */
.topbar-slot { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.nav-back {
  border: 1.6px dashed color-mix(in srgb, var(--ink) 26%, transparent);
  background: transparent;
  box-shadow: none;
}
.space-chip {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 38px;
  padding: 4px 10px 4px 4px;
  border: 1.6px solid color-mix(in srgb, var(--ink) 18%, transparent);
  border-radius: 999px;
  background: var(--paper-2);
  color: var(--ink);
  font-family: var(--font-ui); font-size: var(--fs-14);
  cursor: pointer;
  max-width: 190px;
  -webkit-tap-highlight-color: transparent;
}
.space-chip .avatar { width: 28px; height: 28px; font-size: 15px; }
.space-chip-name {
  min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--font-hand);
}
.space-chip .ico { color: var(--ink-faint); flex: 0 0 auto; }
@media (min-width: 981px) { .space-chip { display: none; } }

/* ---------- 3. 顶栏：回上一级 / 当前空间 + 搜索 + 一个动作 ----------
   顶栏不 sticky、不加 backdrop-filter：它是应用框的第一行格子，
   本来就不会动；sticky + 模糊只是把每帧的合成成本白白加上去。 */
@media (max-width: 980px) {
  .topbar {
    min-height: var(--topbar-h);
    padding: calc(6px + var(--safe-top)) 12px 6px;
    gap: 8px;
    background: color-mix(in srgb, var(--paper) 96%, transparent);
  }
  .topbar .search-box { flex: 1 1 auto; min-width: 0; }
  /* 搜索图标是绝对定位在输入框里的，提示文字得给它留出位置。
     34px 的左内边距在 360px 宽上会把「搜一搜」剪成一个字。 */
  .topbar .search-box .input { min-height: var(--tap); font-size: 16px; padding-left: 28px; padding-right: 8px; }
  .topbar .search-box .search-ico { left: 7px; }
  .topbar .top-actions { flex: 0 0 auto; gap: 6px; }
  /* 顶栏按钮只留图标：文字在 390px 上会把搜索框挤成「搜一搜：笔记、」 */
  .topbar .top-actions .btn { min-width: var(--tap); min-height: var(--tap); padding: 0 10px; }
  .topbar .top-actions .btn:not(.btn--icon) .ico { margin-right: 0; }
  .topbar .top-actions #quick-add { min-width: 0; padding: 0 12px; }
  .space-chip { min-height: var(--tap); max-width: 142px; padding-right: 6px; }
  /* 空间名不能裂。看到「异地两…」的人不知道自己在哪个空间里。
     箭头缩一点、右边距缩一点，把名字要的那 8px 腾出来。 */
  .space-chip .ico { width: 12px; height: 12px; }
}

@media (max-width: 560px) {
  /* 顶栏的「记一笔」和右下角浮动笔重复，留浮动那个 */
  .topbar .top-actions #quick-add { display: none; }
}

/* ---------- 4. 底部导航：应用框的第三行格子，不是 fixed ----------
   它是格子，就永远在格子该在的地方。切页时内容长短变化、浏览器工具条伸缩，
   都推不动它 —— 底栏抖动的根除在这里。 */
.mobile-bar { display: none; }

@media (max-width: 980px) {
  .mobile-bar {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    grid-row: 2;
    gap: 2px;
    padding: 6px 6px calc(6px + var(--safe-bottom));
    background: color-mix(in srgb, var(--paper) 97%, transparent);
    border-top: 1.6px dashed color-mix(in srgb, var(--ink) 24%, transparent);
  }

  .mobile-bar button {
    position: relative;
    border: 0; background: none; cursor: pointer;
    min-height: var(--tap);
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px;
    padding: 7px 2px 8px;
    border-radius: var(--r-md);
    font-family: var(--font-ui);
    font-size: var(--fs-12);
    letter-spacing: .04em;
    color: var(--ink-faint);
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    /* 只动颜色：底栏里任何 transform / 淡入都会让人觉得整条栏在抖 */
    transition: color var(--t-fast) var(--ease-soft), background var(--t-fast) var(--ease-soft);
  }
  .mobile-bar button .ico { width: 21px; height: 21px; }
  .mobile-bar button:active { background: color-mix(in srgb, var(--ink) 8%, transparent); }
  .mobile-bar button.is-on {
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 11%, transparent);
  }
  /* 选中态：手绘小横线，不是实心胶囊 —— 保持「写在纸上」的味道 */
  .mobile-bar button.is-on::after {
    content: "";
    position: absolute; left: 50%; bottom: 3px;
    width: 24px; height: 5px;
    transform: translateX(-50%);
    border-radius: 3px;
    background: var(--accent);
  }
}

.bar-badge {
  position: absolute;
  top: 4px; right: 50%;
  margin-right: -18px;
  min-width: 17px; height: 17px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--paper);
  font-family: var(--font-ui);
  font-size: 10.5px; font-weight: 700; line-height: 17px;
  text-align: center;
}
.bar-badge.is-quiet { background: color-mix(in srgb, var(--ink) 16%, transparent); color: var(--ink); }

/* ---------- 5. 浮动「记一笔」 ---------- */
.fab {
  position: fixed;
  z-index: 58;
  right: calc(14px + var(--safe-right));
  bottom: calc(var(--bar-h) + 14px + var(--safe-bottom));
  display: none;
  align-items: center; gap: 7px;
  min-height: var(--fab-h);
  padding: 0 18px 0 15px;
  border: 0; border-radius: 999px;
  background: var(--accent);
  color: var(--paper-2);
  font-family: var(--font-ui);
  font-size: var(--fs-15); font-weight: 700;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  filter: drop-shadow(0 3px 0 color-mix(in srgb, var(--ink) 18%, transparent));
  transition: transform var(--t-fast) var(--ease-hand), background var(--t-fast) var(--ease-soft);
}
.fab .ico { width: 20px; height: 20px; }
.fab:active { transform: translateY(2px) rotate(-1deg); background: var(--accent-deep); }

@media (max-width: 980px) { .fab { display: inline-flex; } }

/* 说话页的输入框自带发送键，再叠一支笔就会盖住它 */
body:has(.chat-composer--sticky) .fab { display: none; }

/* 管理台 / 搜一搜 / 设置 / 空间 / 回收站 / 消息：这些页自己有自己的主动作，
   而正文恰好长在右下角（管理台图表最高的那根柱子就在那）。
   笔固定在那一块，就是拿一个本页用不上的按钮盖住本页真正的内容。 */
body[data-page="admin"] .fab,
body[data-page="search"] .fab,
body[data-page="settings"] .fab,
body[data-page="space"] .fab,
body[data-page="trash"] .fab,
body[data-page="notifications"] .fab { display: none; }

/* 往下滚时把笔收起来，往上滚再出来：
   浮动的东西最怕盖住正文里的那个按钮，这一条比任何内边距都管用 */
.fab.is-hidden {
  transform: translateY(28px) scale(.86);
  opacity: 0;
  pointer-events: none;
}
@media (max-width: 420px) {
  /* 窄屏上浮动笔收成圆形，少盖住一行内容。
     注意只能收文字那一个 span —— 图标也是 span，写错了会把笔收成零宽。 */
  .fab { min-width: var(--fab-h); padding: 0; justify-content: center; }
  .fab > span:not(.ico) { display: none; }
}

/* ---------- 6. 页头与主区 ---------- */
@media (max-width: 980px) {
  /* 内容滚动区自己滚；overscroll 不外溢，所以不会触发浏览器的下拉刷新/回弹 */
  .scroll { padding: 0; }
  .page { padding: var(--gap) 14px 26px; max-width: none; }

  /* ── 页头：手机上只给两行 ────────────────────────
     桌面那套 kicker / 标题 / 副标题 / 动作四行，在 393×852 上连头带尾
     吃掉 267px —— 屏幕的三分之一还没见到内容，而其里一个「都看过了」
     就独占一行。手机上：图标 + 标题 + 动作共一行，副标题单独一行。 */
  .page-head { flex-wrap: wrap; align-items: center; gap: 2px 8px; margin-bottom: var(--gap-sm); padding-bottom: 8px; }
  .page-head::after { display: none; }
  /* 包裹层拆掉，让 kicker / 标题 / 副标题直接参与页头的排布 */
  .page-head .head-titles { display: contents; }
  .page-head .head-icon { width: 26px; height: 26px; border-radius: 8px; color: var(--accent); }
  /* kicker 是装饰：有副标题时它就在重复说话，让位；没有副标题时它自己顶上 */
  .page-head .head-kicker:has(~ .page-sub) { display: none; }
  .page-head .head-kicker { font-size: var(--fs-12); letter-spacing: 0.14em; }
  .page-head h1 { font-size: var(--fs-20); padding-bottom: 4px; }
  .page-head .head-actions { order: 1; margin-left: auto; flex-wrap: nowrap; }
  .page-head .head-actions .btn { flex: 0 0 auto; padding: 0 10px; gap: 5px; }
  .page-head .head-actions .btn--icon { flex: 0 0 auto; }
  /* 三个以上动作挤不下：文字让位给图标，标题行不允许再长一行。
     文字并没有消失：aria-label / title 还在，读屏和长按都拿得到。 */
  .page-head .head-actions:has(.btn:nth-child(3)) .btn-text { display: none; }
  .page-head .head-actions:has(.btn:nth-child(3)) .btn {
    width: var(--tap); min-width: var(--tap); padding: 0; justify-content: center;
  }
  .page-head .page-sub {
    order: 2;
    flex: 1 0 100%;
    margin: 0;
    font-size: var(--fs-13);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .card, .panel, .stack > * { border-radius: var(--r-lg); }
  .panel { padding: 14px 14px 16px; }
  .panel-head { padding-bottom: 10px; }
  .panel-head h3 { font-size: var(--fs-17); }
  /* 面板头：图标 + 标题 + 右侧小字。手机上标题一长，右侧小字会被压到比
     自己的内容还窄，然后拆成一个词换两行（审计拓过「10/29 · 3」）。小字不许拆，
     标题自己折。 */
  .panel-head { flex-wrap: wrap; }
  .panel-head h3 { min-width: 0; flex: 1 1 auto; }
  .panel-head .panel-more { flex: 0 0 auto; white-space: nowrap; }
}

@media (max-width: 560px) {
  .page { padding: var(--gap-sm) 12px 22px; }
  .page-head h1 { font-size: var(--fs-18); }
  .panel { padding: 12px 12px 14px; }
}

/* ---------- 7. 双栏全部压成一列 ---------- */
@media (max-width: 980px) {
  .split, .split--even,
  .today-columns, .drive-layout, .album-view, .settings-grid,
  .space-grid, .note-editor { grid-template-columns: 1fr; }

  .drive-side, .album-side { order: -1; }   /* 侧栏信息先看到 */
  .grid--2, .grid--3 { grid-template-columns: 1fr 1fr; }
  .grid--4 { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }

  /* 网格子项默认 min-width:auto —— 内容多宽它就至少多宽，压不下去。
     手机上这一条不补，整页会横向溢出，连带把布局视口撑宽：
     底部导航和右下角的笔会被顶出屏幕外（最难查的那种手机 bug）。 */
  .today-columns > *, .habit-grid > *, .space-grid > *, .drive-layout > *,
  .album-view > *, .settings-grid > *, .album-grid > *, .album-photos > *,
  .file-grid > *, .switch-grid > *, .stat-grid > *, .pick-grid > *,
  .metric-strip > *, .more-grid > *, .tl-onthis-row > *, .milestone-list > *,
  .grid--2 > *, .grid--3 > *, .grid--4 > *, .split > *, .stack > *,
  .main > *, .page > * {
    min-width: 0;
  }
}
@media (max-width: 480px) {
  .grid--2, .grid--3 { grid-template-columns: 1fr; }
}

/* ---------- 8. 今日 ---------- */
@media (max-width: 980px) {
  .today-hello { flex-wrap: wrap; gap: 12px; padding: 14px; }
  .today-hello .hello-line { font-size: var(--fs-20); }
  .today-hello .together { display: flex; gap: 10px; flex-wrap: wrap; }
  .metric-strip { grid-template-columns: 1fr 1fr; gap: 10px; }
  .metric { padding: 12px; }
  .metric .metric-num { font-size: var(--fs-26); }
  /* 两列卡片各 ~156px 宽。原来「今天要做的 · 此中 1 件拖着了」会断成
     「今天要做 / 的 · 其中 1 件拖着 / 了」这种拆碎一个词的折行。
     文案缩过了，这里再兜一道：宁可省略也不要把一个词拆成两行。 */
  .metric .metric-label { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .countdown-card { padding: 12px 14px; }
  .countdown-card .cd-num { font-size: var(--fs-26); }
}

/* ---------- 9. 表单与控件：iOS 上 <16px 的输入聚焦会整页缩放 ---------- */
@media (max-width: 980px) {
  input, textarea, select { font-size: 16px; }
  input[type=checkbox], input[type=radio] { font-size: inherit; }
  /* 没挂 .input 的裸输入框（搜索框、日期框）也得有手指那么高的格子 */
  input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]),
  textarea, select { min-height: var(--tap); }
  .input, .textarea, .select { min-height: var(--tap); }
  .pref-row > select { width: 100%; flex: 1 1 100%; min-height: var(--tap); }
  .field--inline { flex-wrap: nowrap; min-height: var(--tap); }
  .field--inline .ico { flex: 0 0 auto; }
  .field--inline input, .field--inline select { flex: 1 1 120px; min-width: 0; min-height: 36px; }
  .form-row > * { flex: 1 1 100%; }

  /* 手机端复选框：命中区撑满 44×44，视觉上仍是 22×22 的手绘小方格 */
  .check, .checkline { min-height: var(--tap); gap: 2px; margin-left: -10px; }
  .checkbox { width: var(--tap); height: var(--tap); min-width: var(--tap); min-height: var(--tap); }
  .check input[type="checkbox"],
  .checkline input[type="checkbox"] {
    width: var(--tap);
    height: var(--tap);
    min-width: var(--tap);
    min-height: var(--tap);
    border: 0;
    background: transparent;
  }
  .check input[type="checkbox"]::before,
  .checkline input[type="checkbox"]::before {
    content: "";
    position: absolute;
    left: 11px;
    top: 11px;
    width: 22px;
    height: 22px;
    border-radius: 6px 8px 5px 7px / 7px 5px 8px 6px;
    background: var(--paper-2);
    border: 1.8px solid var(--line);
    transition: background var(--t-fast), border-color var(--t-fast);
  }
  .check input[type="checkbox"]:checked,
  .checkline input[type="checkbox"]:checked {
    background: transparent;
  }
  .check input[type="checkbox"]:checked::before,
  .checkline input[type="checkbox"]:checked::before {
    background: var(--sage-soft);
    border-color: var(--sage);
  }
  .check input[type="checkbox"]:checked::after,
  .checkline input[type="checkbox"]:checked::after {
    left: 15px;
    top: 15px;
    width: 12px;
    height: 8px;
  }
}

/* ---------- 10. 按钮与标签：可点面积放大，视觉不变 ---------- */
@media (max-width: 980px) {
  .btn, .btn--sm { min-height: var(--tap); }
  .btn--sm { padding-inline: 12px; }
  .btn--icon { min-width: var(--tap); min-height: var(--tap); }
  /* 只有图标的按钮（编辑、小工具）手机上不能被按出 34px */
  .btn--ghost.btn--sm, .btn--danger.btn--sm { min-width: var(--tap); }
  .chip { min-height: 40px; display: inline-flex; align-items: center; }
  button.chip, .chip--sm { min-width: var(--tap); min-height: var(--tap); justify-content: center; padding-inline: 12px; }
  .chip .ico { width: 15px; height: 15px; }
  .emoji-pick { min-width: var(--tap); min-height: var(--tap); width: var(--tap); height: var(--tap); font-size: 22px; flex: 0 0 auto; }
  .candidate-pill { min-width: var(--tap); min-height: var(--tap); padding: 6px 13px; font-size: var(--fs-14); justify-content: center; flex: 0 0 auto; }
  .note-toolbar .chips {
    flex: 1 1 100%;
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .note-toolbar .chips::-webkit-scrollbar { display: none; }
  .note-toolbar .select { flex: 1 1 calc(50% - 6px); max-width: none !important; }
  .linklike { min-height: var(--tap); display: inline-flex; align-items: center; }
  select { min-height: var(--tap); }
  /* 拉条在手机上 16px 高根本推不动，把可点区域抬到 44 */
  input[type=range] { min-height: var(--tap); }
  .segmented { width: 100%; }
  .segmented button { flex: 1 1 0; min-height: 40px; }
  .tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs button, .tab { min-height: var(--tap); white-space: nowrap; }
  .link-btn { min-height: 34px; }
  /* 筛选条改成横滑，不然手机上会被折成三四行；普通标签组还是换行，不藏内容 */
  .kind-chips, .tl-filters, .trash-tabs, .emoji-row {
    display: flex; flex-wrap: nowrap;
    max-width: 100%;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 6px;
    scroll-snap-type: x proximity;
    overscroll-behavior-x: contain;
  }
  .kind-chips::-webkit-scrollbar,
  .tl-filters::-webkit-scrollbar, .trash-tabs::-webkit-scrollbar { display: none; }
  .kind-chips > *, .tl-filters > *, .trash-tabs > * { flex: 0 0 auto; scroll-snap-align: start; }
  /* 弹性容器里的子项也一样不能比内容更窄 —— 不补就会把容器推宽、整页横向溢出 */
  .tl-toolbar > *, .drive-toolbar > *, .notif-top > *, .pref-row > *,
  .account-row > *, .choice-row > *, .member-row > *, .invite-row > *,
  .chat-meta > *, .file-preview-info > *, .fp-actions > *, .quota-top > *,
  .hero-top > *, .notif-foot > *, .trash-actions > *, .account-actions > *,
  .hour-pick > *, .accent-row > * { min-width: 0; }
}

/* ---------- 11. 列表行 ---------- */
@media (max-width: 980px) {
  .row, .task-row, .notif-row, .trash-row, .member-row, .invite-row { padding: 12px; gap: 10px; }
  .row .row-title, .task-title { font-size: var(--fs-16); }
  .row .row-sub, .task-meta, .notif-snip { font-size: var(--fs-13); }
  /* 提醒里那句话只是个预览。手机上留一行、截不完就加省略号，
     比两行但最后一行只剩「明」一个字干净。 */
  .notif-snip {
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* 复选框是手机上最容易点错的地方，直接放大 */
  .task-check, .tick { width: var(--tap); height: var(--tap); min-width: var(--tap); min-height: var(--tap); }
  .task-check .tick { width: var(--tap); height: var(--tap); }

  /* 只有 hover 才出现的行内动作，触屏上必须常显 */
  .file-tools, .photo-tools, .folder-tools, .member-actions, .album-del {
    opacity: 1 !important;
    display: flex !important;
  }
  .file-tools button, .photo-tools button, .folder-tools button, .member-actions button {
    min-width: var(--tap); min-height: var(--tap);
  }
  /* 相册卡角上的删除按钮：拿 padding 把命中区撑到 44，图标本身不变大 */
  .album-del { padding: 10px; min-width: var(--tap); min-height: var(--tap); }
  .album-del .ico, .album-del svg { width: 15px; height: 15px; }
}

/* ---------- 12. 弹窗 → 底部抽屉 ---------- */
@media (max-width: 980px) {
  .modal-veil {
    align-items: flex-end;
    /* 抽屏始终整张落到底、盖住底栏。之前这里留了一个 bar-h + 6px 的空位想让底栏露出来，
       但遮罩本来就盖住了整个屏幕（底栏在遮罩下面既发暗又按不动），
       结果就是：底栏看不见、摸不到，抽屏又浮在它上方 16px —— 两边最坏的部分都拿到了。 */
    padding: 0 var(--safe-left) var(--safe-bottom) var(--safe-right);
    overflow: hidden;
  }
  .modal-card {
    display: flex;
    flex-direction: column;
    width: 100%; max-width: none;
    /* 不能贴满一整屏：底下已经被底栏占了，再长到顶的话
       全屏只剩顶上 55px 可以点外面关掉 —— 那个「关掉」区域小到按不到。
       留出一截实在的遮罩，点空白处退出才是个可用的动作。 */
    max-height: min(74dvh, 620px);
    /* 卡片自己不滚，只让 .modal-body 滚：标题、把手、按钮全都常驻 */
    overflow: hidden;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    padding: 6px 16px calc(18px + var(--safe-bottom));
    transform-origin: var(--origin-x, 50%) var(--origin-y, 100%);
    animation: sheet-up 320ms var(--ease-spring);
  }
  .modal-card > *, .modal-card .modal-body { min-width: 0; }
  /* 抽屉把手：一眼看出能往上拖。::after 本来排在最后，
     用 order:-1 把它挑到最上面，否则把手会长在抽屉底下。 */
  .modal-card::after {
    content: "";
    order: -1;
    flex: 0 0 auto;
    width: 46px; height: 5px;
    margin: 0 auto 10px;
    border-radius: 3px;
    background: color-mix(in srgb, var(--ink) 24%, transparent);
  }
  .modal-head { padding: 4px 0 10px; }
  .modal-head h2 { font-size: var(--fs-20); }
  /* 主操作常驻在抽屉底部：正文再长，「存好」也不会跌到折叠线下 */
  .modal-body {
    /* 抽屉里只让正文滚，标题和按钮不跟着跑 */
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 0 0 12px;
  }
  .modal-foot {
    position: sticky;
    bottom: 0;
    display: flex;
    gap: 10px;
    padding: 12px 0 calc(2px + var(--safe-bottom));
    background: linear-gradient(to bottom, transparent, var(--paper-2) 38%);
  }
  .modal-foot .btn { flex: 1 1 auto; }
  .confirm-dialog { max-width: none; }
}
/* 从触发图标坐标（如底部更多按钮、右下角记一笔或任意按钮）非线性弹簧展开抽屉 */
@keyframes sheet-up {
  0%   { opacity: 0; transform: scale3d(.28, .28, 1) translate3d(0, 24px, 0); }
  70%  { opacity: 1; transform: scale3d(1.01, 1.01, 1) translate3d(0, -2px, 0); }
  100% { opacity: 1; transform: scale3d(1, 1, 1) translate3d(0, 0, 0); }
}

/* ---------- 13. 日历 ---------- */
@media (max-width: 980px) {
  .cal-head { flex-wrap: wrap; gap: 8px; }
  .cal-head .cal-title { font-size: var(--fs-20); }
  .cal-dow { font-size: 11px; }
  .cal-cell { min-height: 62px; padding: 5px; }
  .cal-cell .cal-num { font-size: var(--fs-14); }
  /* 格子窄了以后事件名读不清，改成小色块 + 缩字，整格仍可点 */
  .cal-events { gap: 3px; }
  .cal-event { font-size: 10.5px; padding: 2px 4px; min-height: 20px; border-radius: 5px; }
  .cal-more { font-size: 10.5px; }
  .cal-pip { width: 8px; height: 8px; }
  .countdown-mini { padding: 5px 9px; }
}

/* ---------- 14. 网盘 / 相册 ---------- */
@media (max-width: 980px) {
  /* 文件夹列表改成横向滑动的「抽屉标签」 */
  .folder-list {
    display: flex; flex-wrap: nowrap;
    gap: 8px;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    padding-bottom: 8px;
    scrollbar-width: none;
  }
  .folder-list::-webkit-scrollbar { display: none; }
  .folder-item {
    flex: 0 0 auto; scroll-snap-align: start;
    min-height: var(--tap);
    display: inline-flex; align-items: center; gap: 7px;
    padding: 9px 13px;
  }

  /* 文件夹列表：手机上保持竖排整行（扫读比横滑快），但行高要够按 */
  .folder-list > .folder-item { min-height: var(--tap); }

  /* 工具条：筛选条一行，搜索框整行 */
  .drive-toolbar { gap: 10px; }
  .drive-toolbar .kind-chips { flex: 1 1 100%; }
  .drive-toolbar .field--inline { display: flex; width: 100%; }

  /* 文件从网格改成整行：窄屏上扫读比看缩略图重要 */
  .file-grid { grid-template-columns: 1fr; gap: 10px; }
  .file-card {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 12px;
  }
  .file-card:hover { transform: none; }
  .file-thumb { width: 54px; height: 54px; flex: 0 0 auto; }
  .file-card .file-meta { font-size: var(--fs-12); }

  .album-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
  .album-photos { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; }
  .photo-tile { min-height: 120px; }
  .pick-grid { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }

  .file-preview-stage { padding: 8px; }
  .file-preview-stage iframe, .file-preview-stage video { min-height: 240px; }
  .fp-share { flex-wrap: wrap; }
  .fp-actions { flex-wrap: wrap; gap: 8px; }
}

/* 照片放大看：手机上占满，翻页靠左右滑 */
@media (max-width: 980px) {
  .photo-view { padding: 0 8px; }
  .photo-frame { padding: 8px; }
  .photo-frame img { max-height: 58dvh; }
  .photo-hugs { gap: 8px; }
}

/* ---------- 15. 说话 ---------- */
@media (max-width: 980px) {
  .chat-wrap { height: auto; max-width: none; padding: 0; gap: 0; }
  body[data-page="chat"] .page-head {
    position: sticky; top: 0; z-index: 18;
    max-width: none;
    margin: 0 -14px 2px;
    padding: 8px 14px 7px;
    background: color-mix(in srgb, var(--paper) 97%, transparent);
    backdrop-filter: blur(7px);
    border-bottom: 1.4px dashed var(--line-soft);
    box-shadow: 0 8px 20px -20px rgba(51, 41, 31, .45);
  }

  /* 手机上不再套第二层纸框：消息直接长在页面纸上，滚的是 #scroll。
     overflow 必须是 visible —— 之前 max-height 改成 none 了，但 overflow:auto
     还在，配合 overscroll-behavior:contain 就把手指的滚动链断在这里：
     聊天区自己滚不动，页面也收不到，看起来就是「说话页无法滚动」。 */
  .chat-frame { flex: none; border-radius: 0; background: transparent; box-shadow: none; overflow: visible; }
  .chat-frame::before, .chat-frame::after { display: none; }
  .chat-scroll {
    height: auto; max-height: none;
    overflow: visible;
    overscroll-behavior: auto;
    -webkit-overflow-scrolling: auto;
    padding: 10px 12px 8px;
    border-radius: 0;
    background: transparent;
  }

  .chat-day { position: static; margin: 11px 0 5px; padding: 0; background: none; }
  .chat-row { max-width: 92%; margin-top: 7px; }
  .chat-row.is-grouped { margin-top: 2px; }
  .chat-row .avatar { --size: 28px; }
  .chat-avatar-spacer { width: 28px; flex: 0 0 28px; }
  .chat-bubble, .bubble { max-width: none; font-size: var(--fs-15); }
  .chat-meta { font-size: var(--fs-11); gap: 4px; }
  .chat-more { opacity: .75; }
  .chat-pill { font-size: var(--fs-11); padding: 2px 6px; gap: 3px; }

  .chat-composer--sticky {
    position: sticky;
    /* 贴 0：这个输入框长在 #scroll 里，而 #scroll 自己已经止于底栏上沿。
       再往上顶一个 bar-h 就是顶了两个底栏：之前这里留了一整块 76px 的空白，
       聊天框看上去浮在半空。 */
    bottom: 0;
    z-index: 24;
    padding: 8px 12px 10px;
    background: var(--paper);
    border-top: 1.6px dashed color-mix(in srgb, var(--ink) 20%, transparent);
  }
  .chat-composer { gap: 3px; }
  .chat-composer-box { padding: 6px 6px 6px 13px; border-radius: 21px; }
  .chat-composer .textarea {
    font-size: 16px; min-height: 40px; max-height: 120px;
    padding: 8px 0 6px;
  }
  .chat-send { min-height: 40px; padding: 0 14px; }
  .chat-send > span:not(.ico) { display: none; }
  .chat-composer-foot { padding: 0 6px; }
  .chat-kbd { display: none; }
  .chat-jump { top: -38px; }
  /* 输入框就是这一页的底。它下面再留一段页底内边距，贴到底时就会在
     输入框和导航条之间留一条 22px 的缝，看上去像没贴住。 */
  body[data-page="chat"] .page { padding-bottom: 0; }
}

/* 键盘弹起时（mobile.js 写 --vvh / body.is-keyboard-open）：
   底部导航让位，输入框与底部弹窗抽屉都贴到真实可见视口（键盘上沿），防止被 iPhone 键盘埋掉 */
body.is-keyboard-open .mobile-bar {
  transform: translateY(140%);
  transition: transform var(--t-base) var(--ease-hand);
}
body.is-keyboard-open .fab { display: none; }
body.is-keyboard-open .chat-composer--sticky { bottom: 0; padding-bottom: 8px; }
@media (max-width: 980px) {
  body.is-keyboard-open .modal-veil,
  body.is-keyboard-open .candidate-veil {
    top: var(--vtop, 0px);
    height: var(--vvh, 100dvh);
    bottom: auto;
    padding-bottom: 0;
  }
  body.is-keyboard-open .modal-card {
    max-height: calc(var(--vvh, 100dvh) - var(--safe-top) - 10px);
    padding-bottom: 10px;
  }
}

/* ---------- 16. 心情 / 习惯 / 问答 ---------- */
@media (max-width: 980px) {
  .habit-grid { grid-template-columns: 1fr; }
  .habit-card { padding: 12px; }
  .habit-heat { gap: 4px; grid-template-columns: repeat(auto-fill, minmax(22px, 1fr)); }
  .habit-heat--mini { grid-template-columns: repeat(14, 1fr); }
  /* 打卡格子必须够按，否则「补一次卡」变成一场误点 */
  .heat-cell { width: 100%; min-width: 22px; height: 26px; min-height: 26px; }
  .mood-picker { gap: 6px; }
  .mood-face { width: 46px; height: 46px; min-width: 46px; min-height: 46px; font-size: 22px; }
  .mood-bars { gap: 6px; }
  .mood-bar { min-height: 38px; }
  .mood-bar-num { font-size: var(--fs-13); }
  .chart-wrap { min-height: 150px; overflow-x: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
  .mood-chart { min-width: 0; }
  .mood-chart svg, .chart-wrap svg { max-width: 100%; height: auto; }
  .prompt-card { padding: 14px; }
  .prompt-q { font-size: var(--fs-17); }
}

/* ---------- 17. 时光轴 ---------- */
@media (max-width: 980px) {
  .tl-toolbar { flex-wrap: wrap; gap: 8px; }
  .tl-day { padding-left: 18px; }
  .tl-day::before { left: 5px; }
  .tl-day-dot { width: 10px; height: 10px; }
  .tl-item { padding: 10px; }
  .tl-snippet { font-size: var(--fs-13); }
  .tl-otd { padding: 10px 12px; }
  .tl-onthis-row { grid-template-columns: 1fr; }
}

/* ---------- 18. 提醒 / 回收站 ---------- */
@media (max-width: 980px) {
  .notif-row { padding: 12px; }
  /* 「标为已读」原来 27×30，手指按不准 */
  .notif-mark { min-width: var(--tap); min-height: var(--tap); }
  .notif-ico { width: 34px; height: 34px; }
  .notif-jump { min-height: var(--tap); }
  .notif-foot { flex-wrap: wrap; gap: 8px; }
  .trash-row { padding: 12px; }
  .trash-actions { flex-wrap: wrap; gap: 8px; }
  .trash-actions .btn { flex: 1 1 auto; }
  .trash-tab { min-height: var(--tap); }
}

/* ---------- 19. 空间与成员 / 设置 ---------- */
@media (max-width: 980px) {
  .space-hero-card { padding: 16px; }
  .hero-top { flex-wrap: wrap; gap: 10px; }
  .hero-stats { grid-template-columns: 1fr 1fr; gap: 8px; }
  .switch-grid { grid-template-columns: 1fr 1fr; }
  .switch-tile { min-height: 74px; }
  .member-row { flex-wrap: wrap; }
  .member-actions { flex-wrap: wrap; }
  .invite-row { flex-wrap: wrap; gap: 8px; }
  .milestone-list { grid-template-columns: 1fr; }
  .digest-row { flex-wrap: wrap; gap: 6px; }

  .pref-row { flex-wrap: wrap; gap: 10px; }
  .pref-row .btn { flex: 1 1 auto; }
  .choice-row { flex-wrap: wrap; gap: 8px; }
  .accent-row, .color-row { gap: 6px; padding: 4px 0; }
  /* 强调色圆点 30×30、调色输入 30×30，手机上都不够按。
     圆点本身不变大：把按钮撑到 44，颜色改用 ::before 画。 */
  .accent-dot,
  .color-dot {
    width: var(--tap); height: var(--tap);
    min-width: var(--tap); min-height: var(--tap);
    background: transparent;
    box-shadow: none;
    position: relative;
  }
  .accent-dot .ico,
  .color-dot .ico {
    position: relative;
    z-index: 1;
  }
  .accent-dot::before,
  .color-dot::before {
    content: "";
    position: absolute;
    inset: 7px;
    width: 30px; height: 30px;
    border-radius: 50%;
    background: var(--dot, var(--accent));
    box-shadow: inset 0 0 0 1.4px rgba(51, 41, 31, .18);
  }
  .accent-dot.is-active,
  .color-dot.is-active { box-shadow: none; }
  .accent-dot.is-active::before,
  .color-dot.is-active::before { box-shadow: 0 0 0 2px var(--paper-2), 0 0 0 4px var(--dot, var(--accent)); }
  .accent-custom {
    width: var(--tap);
    height: var(--tap);
    min-width: var(--tap);
    min-height: var(--tap);
    border: 0;
    background: transparent;
    display: grid;
    place-items: center;
  }
  .accent-custom::before {
    content: "";
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 1.6px dashed var(--line);
    background: conic-gradient(#e8927c, #f0c987, #88b88a, #7fb3d5, #b497bd, #e8927c);
  }
  .accent-custom input { width: var(--tap); height: var(--tap); }
  .stat-grid { grid-template-columns: 1fr 1fr; }
  .account-row { flex-wrap: wrap; gap: 10px; }
  .account-actions { flex-wrap: wrap; gap: 8px; }
  .hour-pick { flex-wrap: wrap; }
  .swatch-row { flex-wrap: wrap; }
}

/* ---------- 20. 登录 / 分享页 ---------- */
@media (max-width: 980px) {
  .auth-wrap { grid-template-columns: 1fr; gap: 18px; padding: 18px 16px calc(28px + var(--safe-bottom)); min-height: 100%; }
  /* 手机上先看到表单，故事挪到下面 */
  .auth-hero { order: 2; }
  .auth-card { order: 1; }
  .auth-title { font-size: 28px; }
  .auth-card { padding: 18px; }
  .auth-card .btn { width: 100%; }
  .auth-points { display: none; }     /* 窄屏上这段宣传文字只会把表单推到折叠线下 */
  .shared-wrap { padding: 14px 12px calc(24px + var(--safe-bottom)); }
  .shared-stage { padding: 8px; }
  .shared-img, .shared-frame img { max-height: 58dvh; }
  .shared-actions { flex-wrap: wrap; gap: 8px; }
}

/* ---------- 21. 提示与空状态 ---------- */
@media (max-width: 980px) {
  .toast-root { left: 12px; right: 12px; bottom: calc(var(--bar-h) + 12px + var(--safe-bottom)); max-width: none; }
  .toast { max-width: none; }
  .empty { padding: 22px 14px; }
  .pager { flex-wrap: wrap; gap: 8px; }
  .pager .btn { flex: 1 1 auto; }
}

/* ---------- 22. 触屏专属（与宽度无关） ---------- */
@media (pointer: coarse) {
  /* hover 抬起在触屏没有意义，改成按下才动 */
  .card:hover, .sticky:hover, .panel:hover, .photo-tile:hover,
  .file-card:hover, .album-card:hover, .habit-card:hover,
  .cal-cell:hover, .tl-item:hover, .tl-otd:hover, .heat-cell:hover, .metric:hover {
    transform: none !important;
  }
  .card:active, .sticky:active, .photo-tile:active, .album-card:active,
  .file-card:active, .habit-card:active, .switch-tile:active { transform: scale(.985); }

  /* 拖拽把手在触屏上没用 */
  .drag-handle, .grip { display: none; }

  /* 快捷键提示在触屏上是废话 */
  kbd, .kbd, .search-kbd, .hint-kbd, .candidate-kbd { display: none; }

  ::-webkit-scrollbar { width: 0; height: 0; }

  /* 划开一行：往右甩 = 完成，往左甩 = 看详情。
     行自己变色就是反馈，不用加额外 DOM（加一层反而会被行的背景盖住） */
  .swipeable { touch-action: pan-y; }
  /* 正在划：微抬，手感上「拿起来了」 */
  .swipeable.is-swiping { box-shadow: var(--shadow-lift); }
  .swipeable.is-armed {
    background: color-mix(in srgb, var(--sage) 26%, var(--paper-2)) !important;
  }
  .swipeable.is-armed .task-title, .swipeable.is-armed .row-title {
    color: var(--sage-deep);
  }
}

/* 可滚动区一律contain：不然滑到尽头会把整页带着一起滚 */
@media (max-width: 980px) {
  .rail, .modal-card, .modal-body, .candidate-list, .candidate-strip, .note-toolbar .chips,
  .kind-chips, .tl-filters, .tabs, .file-preview-stage, .textarea, .editor-area {
    overscroll-behavior: contain;
  }
}

/* ---------- 23. 下拉刷新提示 ---------- */
.pull-hint {
  position: fixed;
  top: calc(var(--safe-top) - 48px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 62;
  display: flex; align-items: center; gap: 7px;
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--paper-2);
  border: 1.6px dashed color-mix(in srgb, var(--ink) 26%, transparent);
  font-family: var(--font-hand); font-size: var(--fs-13);
  color: var(--ink-soft);
  transition: transform var(--t-base) var(--ease-hand);
  pointer-events: none;
}
.pull-hint .pull-text { font-variant-numeric: tabular-nums; }
.pull-hint .pull-ico { display: inline-block; transition: transform var(--t-base) var(--ease-hand); }
.pull-hint.is-ready .pull-ico { transform: rotate(180deg); }

/* ---------- 23b. 屏幕左缘跟手侧滑返回提示 ---------- */
.edge-back-pill {
  position: fixed;
  left: 10px;
  top: 50%;
  z-index: 64;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 7px 12px;
  border-radius: 999px;
  background: var(--paper-2);
  border: 1.5px solid var(--accent);
  box-shadow: var(--shadow-lift);
  font-family: var(--font-hand);
  font-size: var(--fs-13);
  color: var(--accent);
  pointer-events: none;
  opacity: 0;
  transform: translate3d(-24px, -50%, 0) scale(.82);
  transition: opacity var(--t-fast), transform var(--t-fast) var(--ease-spring);
}
.edge-back-pill.is-ready {
  background: var(--accent);
  color: var(--paper-2);
}

/* ---------- 24. 「更多」页（底部导航放不下的都在这儿） ---------- */
.more-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; margin-bottom: 12px; }
.more-group { display: block; }
.more-group-label {
  font-family: var(--font-hand); font-size: var(--fs-13);
  opacity: .68; margin: 2px 0 7px;
}
.more-item {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  min-height: 76px;
  padding: 10px 6px;
  border: 1.5px dashed color-mix(in srgb, var(--ink) 24%, transparent);
  border-radius: 13px 15px 12px 14px;
  background: var(--paper-2);
  color: var(--ink);
  font-family: var(--font-ui); font-size: var(--fs-13);
  text-align: center; text-decoration: none;
  cursor: pointer;
  box-shadow: 1px 2px 0 rgba(51, 41, 31, .04);
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--t-fast) var(--ease-spring), background var(--t-fast);
}
.more-item .ico { width: 22px; height: 22px; color: var(--accent); }
.more-item:hover { transform: translateY(-2px); }
.more-item:active { transform: scale(.94); background: color-mix(in srgb, var(--accent) 12%, var(--paper-2)); }
@media (max-width: 360px) { .more-grid { grid-template-columns: 1fr 1fr; } }

/* ---------- 25. 搜一搜 ---------- */
@media (max-width: 980px) {
  .search-field { padding: 6px 8px 6px 12px; }
  /* iOS 对 <16px 的输入框会自动放大页面 —— 搜索框是用的最多的输入框，不能香犯 */
  .search-field .input { font-size: 16px; }
  .search-field-go { min-height: var(--tap); padding: 0 14px; }
  .search-field-clear { min-width: var(--tap); min-height: var(--tap); }

  .search-scope { gap: 6px; }
  .search-scope .seg { flex: 1 1 auto; justify-content: center; min-height: var(--tap); }

  .search-chip { min-height: var(--tap); }
  /* 空页上那排「之前搜过 / 也可以试试」是这一页最常被点的东西，
     34px 高的胶囊手指按不准 */
  .search-recent-item { min-height: var(--tap); }
  .search-idle-link { min-height: var(--tap); }

  /* 顶栏那个搜索框在手机上本来就不宽，进页后页内那个才是主角 */
  .search-row { padding: 12px 13px; gap: 10px; }
  .search-row-go { display: none; }
  .search-row-snippet { -webkit-line-clamp: 3; }
  .search-group-more { margin-left: 0; width: 100%; justify-content: center; min-height: var(--tap); }
}

/* ---------- 26. 管理台 ---------- */
@media (max-width: 980px) {
  .admin-tabs { gap: 6px; }
  .admin-tab { min-height: var(--tap); flex: 1 1 auto; justify-content: center; }

  /* 四列的账在 414px 里会被挤成一堆残句：改成一张竖卡，
     名字在上、数字居中、时间在下、动作贴底（拇指能够到的位置） */
  .admin-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
    padding: 13px;
  }
  .admin-row-nums { justify-content: flex-start; gap: 12px; }
  .admin-row-when { flex-direction: row; flex-wrap: wrap; gap: 12px; }
  .admin-row-acts { padding-top: 2px; }
  .admin-row-acts .btn { flex: 1 1 auto; min-height: var(--tap); justify-content: center; }

  .admin-stats { grid-template-columns: 1fr 1fr; gap: 10px; }
  .admin-stat { padding: 13px 13px 12px; }
  .admin-stat-value { font-size: var(--fs-20); }
  .admin-stat-lines li { font-size: var(--fs-12); }

  .admin-split { grid-template-columns: minmax(0, 1fr); }

  /* 14 根柱子在窄屏里每根不到 20px，日期标签会挤到重叠 ——
     只留隔一天一个，柱子本身不受影响 */
  .admin-chart { grid-template-columns: repeat(14, minmax(0, 1fr)); gap: 4px; height: 128px; }
  .admin-bar-day { display: none; }
  .admin-bar:nth-child(2n + 1) .admin-bar-day { display: block; font-size: 9.5px; }
  .admin-bar-stack { max-width: none; }

  .admin-barrow { grid-template-columns: minmax(0, 1fr) auto; gap: 6px 10px; }
  .admin-barrow-track { grid-column: 1 / -1; }

  .admin-mini-row { grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
  .admin-mini-meta { grid-column: 1 / -1; order: 3; }

  .admin-toolbar { flex-direction: column; align-items: stretch; }
  .admin-search { flex: 1 1 auto; }
  .admin-search .input { font-size: 16px; min-height: var(--tap); }
  .admin-toolbar .field { width: 100%; }
  .admin-toolbar .select { min-height: var(--tap); width: 100%; }
  .admin-seg { width: 100%; }
  .admin-seg .seg { flex: 1 1 auto; min-height: var(--tap); justify-content: center; }
}

@media (max-width: 420px) {
  /* 三四个状态标签在一行里必定换行错位，索性强制成两行三格 */
  .admin-seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* 手指设备上动作按钮要能按得动；鼠标设备上保留紧凑尺寸 */
@media (pointer: coarse) {
  .admin-row-acts .btn--sm,
  .search-group-more,
  .admin-usage-foot .btn,
  .admin-pager .btn { min-height: var(--tap); }
}

/* ---------- 27. 横屏矮屏（手机横过来） ---------- */
@media (max-width: 980px) and (orientation: landscape) and (max-height: 540px) {
  :root { --bar-h: 58px; --fab-h: 44px; }
  .mobile-bar button { padding: 4px 2px; font-size: 10.5px; }
  .mobile-bar button .ico { width: 18px; height: 18px; }
  .fab { bottom: calc(var(--bar-h) + 8px + var(--safe-bottom)); min-height: 42px; padding: 0 14px; }
  .topbar { min-height: 48px; }
  .chat-composer--sticky { bottom: 0; }
}

/* ---------- 28. 减少动态 ---------- */
@media (prefers-reduced-motion: reduce) {
  .modal-card { animation: none; }
  .mobile-bar, .fab, .rail, .pull-hint, .mobile-bar button { transition: none; }
  * { scroll-behavior: auto; }
}
