/* ============================================================
   Klog · 06-mobile.css —— 手机端（≤768）样式唯一落点
   ------------------------------------------------------------
   1103「电脑端 / 手机端样式分家」的产物：五件套里所有 max-width ≤768 的
   顶层媒体块整体搬到这里，按 **片序 01→05 + 片内行序** 排列，与原全局源码
   顺序逐字一致；只搬位置，不改一个字节。每块仍自带媒体查询，加载条件没变——
   分的是「写在哪只文件里」，不是「什么时候生效」。

   层叠契约（不可调换）：01-tokens → 02-base → 03-components → 04-shell
   → 05-views → 06-mobile。06 在最后 = 「手机端天然压过桌面基线」，
   与旧版「移动块夹在视图片里靠后写赢」等价。

   规矩（css-bloat-gate 有机器闸，违反当场红）：
     · 手机端样式只许写进本文件；01-05 里禁止再出现 max-width ≤768。
     · 新增页面 = 桌面段写 05 对应视图区、手机端段写本文件对应视图区，
       两边同一套前缀（如 .xx- ），别在 05 里顺手补 @media。
     · 令牌的窄屏重映射（--control-h 那类）也写在这里的 :root 段；
       改令牌前先 grep 有没有媒体重映射（探针铁律 13）。
   ============================================================ */

/* ← 01-tokens.css:423 */
@media (max-width: 768px) {
  /* 深色主题不参与：这条只管浅色窄屏（守卫写在选择器里，不靠加载顺序） */
  html:not([data-theme="dark"]) { --bg-page: #F1F2F5; }
}

/* ← 04-shell.css:432 */
@media (max-width: 600px) {
  /* .ob-card 不再在此改 padding：引导画布内距一律吃 --content-px（手机端间距规范 v1.0） */
  .login-pop { padding: var(--sp-6) var(--sp-4) var(--sp-4); }
}

/* ← 04-shell.css:472  「移动端（窄屏或触屏）：隐藏滚动条」 */
@media (max-width: 768px), (hover: none) and (pointer: coarse) {
  ::-webkit-scrollbar { width: 0; height: 0; }
  * { scrollbar-width: none; }
}

/* ← 04-shell.css:492  「≤768px：移动端布局 —— 隐藏侧栏、底部导航、全屏弹窗」 */
@media (max-width: 768px) {
  :root { --header-h: 56px; } /* 间距/触控令牌统一在「手机端间距规范 v1.0」「可读性强化」两块重映射，此处不再重复 */
  .app { flex-direction: column; height: 100dvh; }
  .sidebar { display: none; }
  .tabbar { display: flex; }
  .main { height: auto; min-height: 0; overscroll-behavior-y: contain; }
  /* iOS 防聚焦自动放大：输入类字号必须 ≥16px（<16px 触发整页 zoom 且不可逆） */
  .form-input, .search-field-input, textarea.form-input { font-size: var(--fs-input); }
  /* 悬浮导航栏脱离文档流：内容区预留底部空间（含安全区），避免列表末项被遮挡 */
  .content { padding-bottom: calc(104px + var(--sab)); }
  /* 搜索清空按钮：隐形扩展点击区到约 46px（视觉尺寸不变） */
  .search-clear::after { content: ""; position: absolute; inset: -8px; }
  /* 触屏无 hover：补 :active 按压反馈 */
  .seg button:active, .chip:active { background: var(--bg-hover); color: var(--text-1); }

  .header-actions .btn-text { display: none; }
  .header-actions .btn { padding: 0 var(--sp-3); }
  .header-left h1 { font-size: var(--fs-h2); }

  /* 文字链接触控区扩展：position:relative 锚定伪元素，视觉零变化 */
  .btn-link { position: relative; }
  .btn-link::after { content: ""; position: absolute; inset: -8px -6px; }

  .toolbar .search-field { width: 100%; }

  /* 工具栏新增按钮收起（避免与筛选器挤在同一行折行），新增动作移至导航栏右侧 */
  .toolbar > .btn-primary { display: none; }

  /* 底部导航：悬浮毛玻璃胶囊 dock + 右侧独立圆形新增按钮。
     dock 两形态（0925）：形态 a 概览+统计两席、胶囊收窄居中；形态 b 五模块席、
     左贴并让出右侧 70px 给加号。几何与过渡见文末「显式 margin 版」块 */
  .tabbar {
    position: fixed; left: 12px; right: 12px;
    bottom: calc(24px + var(--sab));
    z-index: 60;
    display: flex; align-items: center; justify-content: center;
    background: transparent; border-top: none; padding: 0;
    /* 1018：整条 bar 都是 dock 手势热区（含左右空白），交还 JS 逐帧跟，不让浏览器接滚动/缩放手势 */
    touch-action: none;
  }
  .tabbar-dock {
    position: relative;
    flex: 0 0 auto; width: calc(100% - var(--dock-r) - var(--dock-slim));
    display: flex; align-items: center;
    background: var(--bg-card);
    border-radius: var(--radius-pill);
    box-shadow: 0 0 0 1px var(--border), 0 8px 24px rgba(17,17,17,.12);
    padding: var(--sp-1);
    touch-action: none; /* 按住上滑=模块面板手势：交还给 JS 逐帧跟，不让浏览器接滚动 */
    z-index: 2;         /* 压过右侧新增按钮：滑动换位重叠时 dock 在上 */
    transition: transform var(--d-toast) var(--ease-enter);
  }
  /* 竖向橡皮筋阻尼（0930）：transform 由 app.js 逐帧写，is-pull 关掉过渡让胶囊实时贴手、绝不掉帧。
     is-snap=松手未达提交点，用带轻微过冲的弹簧曲线弹回（与 .tabbar-add 出现曲线同族） */
  .tabbar-dock.is-pull { transition: none; will-change: transform; }
  .tabbar-dock.is-snap { transition: transform var(--d-morph) var(--ease-spring); }
  /* 方向提示 chip（0930）：拖拽时浮在胶囊上方，写明这一下会开什么（↑可序AI / ↓全部模块）。
     必须挂在 .tabbar 上、不能进 .tabbar-dock——胶囊有 contain:paint，越界的子元素会被裁掉。
     到位（is-ready）时不闪不变色，只「弹一下」：放大到 1.14 再缩回原尺寸，作为「可以松手了」的信号。 */
  .tabbar-hint {
    position: absolute; left: 50%; bottom: calc(100% + 18px);
    transform: translate(-50%, 6px) scale(.92); opacity: 0; pointer-events: none;
    display: inline-flex; align-items: center; gap: var(--sp-1); white-space: nowrap;
    padding: var(--sp-1) var(--sp-3); border-radius: var(--radius-pill); z-index: 61;
    background: var(--text-1); color: var(--bg-card);
    font-size: var(--fs-label); font-weight: var(--fw-medium); letter-spacing: .3px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .22);
    transition: opacity var(--d-fast) var(--ease-float), transform var(--d-fast) var(--ease-float);
  }
  .tabbar-hint.is-on { opacity: 1; transform: translate(-50%, 0) scale(1); }
  .tabbar-hint.is-ready { animation: hintPop var(--d-push) var(--ease-float); }
  @keyframes hintPop {
    0%   { transform: translate(-50%, 0) scale(1); }
    42%  { transform: translate(-50%, 0) scale(1.14); }
    100% { transform: translate(-50%, 0) scale(1); }
  }
  @media (prefers-reduced-motion: reduce) { .tabbar-hint.is-ready { animation: none; } }
  .tabbar-hint .th-arw { font-style: normal; font-weight: var(--fw-bold); }
  /* 概览页无新增按钮时曾经在这里写死 translateX(35px) 居中（0925 起废除）。
     dock 的两态几何已整体搬到文末「显式 margin 版」块，按 .has-add 判定；
     这里绝不能再留任何位移——与那边的 margin-left 叠加会把胶囊推贴屏幕右边
     （实测 gapLeft 66 / gapRight 4 的历史 bug）。 */
  /* 选中指示器：灰色胶囊（非黑底填充），JS 定位到选中项，切换时滑动。
     位移/宽度都不走 CSS 过渡——1003 起由 app.js 的弹簧逐帧写（见文件末「果冻指示块」） */
  .tabbar-ind {
    position: absolute; top: 5px; bottom: 5px; left: 0;
    width: 0; background: var(--bg-count); border-radius: var(--radius-pill);
  }
  [data-theme="dark"] .tabbar-dock {
    box-shadow: 0 0 0 1px var(--border), 0 8px 24px rgba(0,0,0,.5);
  }
  .tabbar .menu-item { flex: 1; margin: 0; border-radius: var(--radius-pill); position: relative; z-index: 1; }
  .tabbar .menu-item.active { color: var(--text-1); }

  /* dock 右侧独立圆形新增按钮：出现 0.5→1 弹性放大（back 曲线带过冲，明显）；
     消失 0.16s ease-in 快速缩没。
     1003：材质与 dock 完全同族——同一枚 --glass-* 令牌（同一透底、同一次模糊、
     同一圈玻璃沿、同一段托底投影），图标回落到 --text-1，与 dock 里的图标同色。
     旧的「主色 72% 实底」是一枚不透明的贴片，压在半透玻璃 dock 旁边最抢眼，
     也是「加号不像这一排里的东西」的原因。 */
  .tabbar-add {
    flex: 0 0 auto; align-self: center;
    position: relative; z-index: 1; /* 层级在 dock 之下：滑动换位重叠时不遮住 dock */
    width: 60px; height: 60px; margin-left: var(--sp-3);
    border: none; border-radius: var(--radius-pill);
    background: var(--glass-fill);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    color: var(--text-1); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    box-shadow: var(--glass-rim), var(--glass-drop);
    transition: transform var(--d-push) var(--ease-spring), opacity var(--d-modal) ease, visibility 0s;
  }
  .tabbar-add svg { width: 20px; height: 20px; }
  .tabbar-add:active { transform: scale(0.92); }
  .tabbar-add[hidden] {
    /* !important 对冲全局 [hidden]{display:none!important} 兜底——FAB 动画依赖 hidden 时保持 flex 占位 */
    display: flex !important; opacity: 0; transform: scale(0.5); pointer-events: none;
    visibility: hidden;
    transition: transform var(--d-fast) ease-in, opacity var(--d-micro) ease-in, visibility 0s var(--d-fast);
  }

  .field-row, .field-row-3 { grid-template-columns: 1fr; gap: var(--sp-4); }
  .date-card { flex-wrap: wrap; }
  .date-count { text-align: right; min-width: 78px; }
  /* 待办：表格 → 卡片列表（手机上多列表格过窄，改多行卡片布局）
     结构仍为 table，仅重排 display，JS 与事件委托（tr[data-id]）保持不变 */
  #view-todo .table-wrap { overflow-x: visible; }
  #view-todo .data-table { display: block; }
  #view-todo .data-table thead { display: none; }
  #todoBody { display: block; }
  #todoBody tr {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
      "check title priority"
      "check due   created";
    align-items: start;
    column-gap: var(--sp-3); row-gap: var(--sp-1);
    padding: var(--sp-3) var(--sp-3);
    border-bottom: 1px solid var(--border);
  }
  #todoBody tr:last-child { border-bottom: none; }
  #todoBody td { display: block; padding: 0; border-bottom: none; }
  #todoBody td.col-check { grid-area: check; width: auto; padding-top: 2px; }
  #todoBody td:nth-child(2) { grid-area: title; }          /* 内含标题 + 描述，纵向堆叠 */
  #todoBody td.col-priority { grid-area: priority; width: auto; }
  #todoBody td.col-due { grid-area: due; width: auto; font-size: var(--fs-micro); color: var(--text-4); }
  #todoBody td.code {
    grid-area: created; width: auto; text-align: right;
    font-family: var(--font-sans); font-size: var(--fs-micro); color: var(--text-4);
  }
  #todoBody .todo-title, #todoBody .todo-desc { max-width: none; }
  #todoBody .todo-desc { margin-top: 3px; }

  /* 折叠行：移动端表格已转卡片网格，这里退回普通块，不进网格（无 data-id，
     左滑手势与行点击开详情都天然不碰它）；带 :last-child 分支——5107 卡片壳的
     tr:last-child 分支与本规则特异性打平且靠后，收起态折叠行恰是末行会被它翻回 grid。
     卡片的白底/描边/投影一并重置，视觉仍全靠按钮的虚线细行 */
  #todoBody tr.todo-done-fold, #todoBody tr.todo-done-fold:last-child {
    display: block; padding: 2px 0 var(--sp-2); background: transparent;
    border: none; border-radius: 0; box-shadow: none;
  }
  #todoBody tr.todo-done-fold td { padding: 0; }

  /* 复选框：放大到 20px 并用伪元素扩展隐形点击区至约 34px */
  .todo-check { position: relative; }
  .todo-check::after { content: ""; position: absolute; inset: -7px; }
    
  /* 弹窗全屏化 + 自底升起入场（移动端原生手感）；遮罩灰层移除。
     入场动画真的接上——整屏卡自底升起（sheetUp .36s，快速档），升起过程中看得见
     背后 has-layer 缩放的壳层（景深保留，这是站主要留的那一下）；关仍 sheetDown 落回。
     1010：详情（05 的 dd-modal.dd-notitle）也回到这一档——抽屉几何与「详情↔编辑」形变已撤，
     全站只此一套升起语言，不再单开 .6s 慢档。 */
  /* 手机端遮罩不参与淡入：03 基础规则 `.modal-mask{animation:maskIn}` 淡的是**整只遮罩的 opacity**，
     而卡片是它的子节点——所以这一淡，等于整页弹窗与底下的列表交叉淡 ~150ms，
     正是站主真机看到的「详情进编辑闪一帧列表页」（录屏逐帧实测 t≈32→205ms 遮罩 opacity 0→1）。
     更要命的是它会被「换页」重新触发：详情那屏的遮罩被 05 的 :has() 规则改成了 tdDimIn（只淡 background），
     切到表单时该规则不再命中、animation 退回 maskIn，浏览器当成一只**新动画从 0 重跑**。
     整屏卡片自己有 sheetUp 升起，遮罩再淡一次毫无收益，这里直接掐掉。 */
  .modal-mask { padding: 0; background: transparent; animation: none; }
  .modal-card {
    max-width: none; max-height: none; height: 100%;
    border: none; border-radius: 0;
    will-change: transform; /* 每一屏弹窗常驻合成层：① 修「冷启动首次打开直接弹到位」（首帧未合成时 CSS 动画会直接落到终态）；② 详情↔编辑切换时层不拆不建，底色不会漏画一帧（1010b 真机「闪一帧列表页」） */
    animation: sheetUp var(--d-enter) cubic-bezier(.22,1,.36,1); /* 不许过冲：spring 会在屏底露缝。曲线＝ease-float 的尾段收紧版（.61→1），
     刻意非逐字、不并档——DESIGN_SYSTEM.md §7.2 登记豁免（与 toast 岛曲线同款处理，1025 复审注） */
  }
  /* 挂上它＝「这一页不重播升起，只走内容级联」。1010 起由 Modal.open 按页面角色判定：
     编辑/新增表单（edit-form/diary-form）恒挂——它们一律自上而下推入；
     详情从编辑返回时由调用点显式 stacked；其余弹窗仍按真链（上面压着一层/刚关完 380ms 内再开）。 */
  .modal-card.is-stacked { animation: none; }
  /* 1013 站主定：表单页（edit-form/diary-form）入场撤 1010b 的无淡入硬推，回到旧版录屏
     （VID_20261013）的手感——新页盖住旧页交叉淡入，内容由上而下逐行落定（chainPushIn 回归，见 05）。
     全新打开（列表→新增）＝整卡淡入（fade-open，JS 挂）＋正文级联；链内换页（详情→编辑）＝
     卡片不动，由 05 的 swap-fade 走内容级交叉淡（.modal-ghost 承接旧页）。
     遮罩仍恒 none：动画换名重播＝1010b「闪一帧列表页」的老路，不走。
     本条必须排在 closing 之前：关闭时 closing 要赢过 fade-open，收场仍是 sheetDown。 */
  .modal-card.fade-open { animation: cardFadeIn var(--d-modal) ease-out; }
  .modal-card.closing { animation: sheetDown var(--d-fast) ease-in forwards; }
  .modal-card .modal-body { flex: 1; } /* 顶部留白=头高48+模块间距20，见「手机端间距规范」块 */
  /* 全面屏：底栏按钮避开 home 指示条（桌面 env=0，无副作用） */
  .modal-card .modal-foot { padding-bottom: calc(var(--sp-3) + var(--sab)); }
  /* 1009b：1.9x 试点的「居中悬浮卡 / 贴屏 86% 底部抽屉」两形态均已回退——站主要的是
     「以前的效果」：整屏详情 + 自底升起（见上方 sheetUp），背景纵深（has-layer）保留。
     2.00：演示稿同款底部「编辑/完成」大按钮（.dd-acts）按站主令删除，样式一并撤。 */

  /* 返回式关闭：左箭头替代右上角 X（原生 App 导航栏手感，标题保持在左侧） */
  .modal-back { display: inline-flex; }
  .modal-x { display: none; }
  /* 返回箭头靠左，标题绝对居中（不随箭头宽度偏移）；超长省略且不挡箭头点击 */
  .modal-head {
    /* 注意：不可写 position —— 基础规则的 absolute 悬浮必须保持；
       此处曾写 relative 把悬浮打回文档流，导致 头高48+body顶距56=104px 双倍空白且毛玻璃失效 */
    justify-content: flex-start;
    /* 全屏弹窗无圆角：头部同步去圆角，避免上角露出底页 */
    border-radius: 0;
    /* 头部变薄（48px）压缩打开时的顶部空白；玻璃基底改用页面灰，与白色内容形成可感知的毛玻璃层次 */
    padding-top: calc(var(--sp-2) + var(--safe-top)); padding-bottom: var(--sp-2);
    background: color-mix(in srgb, var(--bg-page) 55%, transparent);
    /* 毛玻璃移动端参数：与顶栏同步调透，20px 模糊在透明度 55% 档仍可读 */
    -webkit-backdrop-filter: blur(20px) saturate(150%); backdrop-filter: blur(20px) saturate(150%);
  }
  .modal-head h2 {
    position: absolute; left: 50%; transform: translateX(-50%);
    max-width: calc(100% - 96px); margin: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    pointer-events: none;
  }

  /* 移动端不展示「取消/关闭」按钮：退出统一走左上返回箭头；确认/提示类弹窗（keepCancel）保留 */
  .modal-foot [data-cancel] { display: none; }
  /* 左组不再推左：单独的「退出登录」等左组按钮随 flex-end 落到右侧（桌面不受影响） */
  .modal-foot-left { margin-right: 0; }

  /* 危险操作「重置」按钮：移动端只显示简约图标（rotate-ccw），无边框无底色，点击即执行重置。
     加 .pfg-row.is-danger 前缀抬高特异性——桌面隐藏图标的基础规则在文件更后位置，等特异性会被其反杀 */
  .pfg-row.is-danger .dc-reset-btn {
    width: 40px; height: 40px; padding: 0; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    border: none; background: transparent; color: var(--tag-bad-fg);
  }
  .pfg-row.is-danger .dc-reset-btn .dc-reset-txt { display: none; }
  .pfg-row.is-danger .dc-reset-btn .dc-reset-ico { display: block; width: 20px; height: 20px; }

  /* ============ 移动端动效系统：轻量 / 原生 / 尊重 reduced-motion ============ */

  /* 视图切换：自下而上淡入，替代桌面横滑（更贴近手机手感，避免横向溢出） */
  .view { animation: pageUpIn var(--d-enter) var(--ease-enter); }

  /* 底部导航：按压反馈 + 激活态微弹跳 + 44px 触控高度（1010d 瘦身一档，仍守 WCAG 44px 底线） */
  .tabbar { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
  .tabbar .menu-item {
    min-height: 44px;
    transition: color var(--transition-fast), background-color var(--transition-fast), transform var(--transition-fast);
  }
  /* 按压不叠加圆形底（项宽仅约 57px，:active 胶囊会呈小圆圈）；反馈交给滑动指示器 */
  .tabbar .menu-item.active svg { animation: tabPop var(--d-push) var(--ease-enter); }

  /* 列表 / 卡片：触摸按下轻微回弹，提供即时物理反馈 */
  .memo-card:active, .date-card:active { transform: scale(0.985); }
  .data-table tbody tr:active { background: var(--bg-hover); }

  /* 顶栏毛玻璃：手机端参数与桌面同透明档，blur 20 兼顾玻璃感与滚动帧率 */
  .header {
    -webkit-backdrop-filter: blur(20px) saturate(150%);
    backdrop-filter: blur(20px) saturate(150%);
  }

  /* 移动端专属关键帧 */
  @keyframes pageUpIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
  @keyframes sheetDown { from { transform: translateY(0); } to { transform: translateY(100%); } }
  @keyframes sheetUp { from { transform: translateY(100%); } to { transform: none; } } /* 1009b：手机端弹窗抽屉式入场（见上方 .modal-card） */
  @keyframes cardFadeIn { from { opacity: 0; } to { opacity: 1; } } /* 1013：表单全新打开整卡原地淡入（.modal-card.fade-open），时长走 --d-modal */
  @keyframes tabPop { 0% { transform: scale(0.82); } 60% { transform: scale(1.08); } 100% { transform: scale(1); } }
}

/* ← 04-shell.css:814 */
@media (max-width: 768px) {
  .chain-bar {
    position: sticky; top: calc(var(--header-h) + var(--safe-top)); z-index: 49;
    flex-shrink: 0; touch-action: none;   /* 这条带由 JS 独占：点跳/横拖寻址；竖向滚动交给下方内容大区域 */
    padding: var(--sp-2) var(--content-px);       /* 1011：栏高降到 ~23px（段/滑块尺寸不变，只削上下留白） */
    background: color-mix(in srgb, var(--bg-card) 55%, transparent);
    -webkit-backdrop-filter: blur(20px) saturate(150%);
    backdrop-filter: blur(20px) saturate(150%);
    border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
  }
  /* 栏高降了但热区不能跟着降：::before 把命中区向下扩进内容顶部那段 24px 空 padding（够不着第一张卡），
     向上只留 3px（再高会被 z50 顶栏吃掉）——合计 ~41px，仍 ≥38。透明、不画东西。 */
  .chain-bar::before { content: ""; position: absolute; left: 0; right: 0; top: -3px; bottom: -15px; }
  .chain-bar.is-on { display: block; }
}

/* ← 05-views.css:101 */
@media (max-width: 768px) {
  .cat-swatch-custom svg { width: 15px; height: 15px; }
  .cat-custom-hex { flex: 1 1 100%; margin-left: 0; }
}

/* ← 05-views.css:201 */
@media (max-width: 768px) {
  .cat-filter { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 2px; }
}

/* ← 05-views.css:583 */
@media (max-width: 768px) {
  .habit-grid { grid-template-columns: 1fr; }
}

/* ← 05-views.css:621 */
@media (max-width: 768px) {
  .mood-band { padding: var(--sp-3) var(--card-pad); }
}

/* ← 05-views.css:648 */
@media (max-width: 768px) {
  /* min-height 而不是 height：单行时与翻页钮等高（38）＝与以前逐字等值；
     一旦尾巴那枚胶囊退到第二行，白卡自己长开，不会被固定高度裁掉（1004 大档真机） */
  .hm-modal .hm-range { min-height: 38px; }
}

/* ← 05-views.css:741 */
@media (max-width: 768px) {
  /* 退出：向下滑出的同时淡出并轻微收拢，不再生硬 */
  @keyframes sheetDown { from { opacity: 1; transform: translateY(0) scale(1); } to { opacity: 0; transform: translateY(60%) scale(.98); } }

  /* 弹窗内容级联入场：字段依次上浮淡入（≤8 档，整体 320ms 内完成） */
  .modal-card.cascade .modal-body > * { animation: cascadeIn var(--d-toast) var(--ease-enter) backwards; }
  .modal-card.cascade .modal-body > *:nth-child(2) { animation-delay: .04s; }
  .modal-card.cascade .modal-body > *:nth-child(3) { animation-delay: .08s; }
  .modal-card.cascade .modal-body > *:nth-child(4) { animation-delay: var(--d-micro); }
  .modal-card.cascade .modal-body > *:nth-child(5) { animation-delay: var(--d-fast); }
  .modal-card.cascade .modal-body > *:nth-child(6) { animation-delay: var(--d-base); }
  .modal-card.cascade .modal-body > *:nth-child(7) { animation-delay: var(--d-modal); }
  .modal-card.cascade .modal-body > *:nth-child(8) { animation-delay: var(--d-toast); }
  @keyframes cascadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

  /* 列表卡片 stagger：仅视图切换时播（staggerList 控制），筛选重渲染不重放 */
  .list-cascade > * { animation: cascadeIn var(--d-push) var(--ease-enter) backwards; }
  .list-cascade > *:nth-child(2) { animation-delay: .035s; }
  .list-cascade > *:nth-child(3) { animation-delay: .07s; }
  .list-cascade > *:nth-child(4) { animation-delay: var(--d-micro); }
  .list-cascade > *:nth-child(5) { animation-delay: var(--d-fast); }
  .list-cascade > *:nth-child(6) { animation-delay: var(--d-base); }
  .list-cascade > *:nth-child(7) { animation-delay: var(--d-modal); }
  .list-cascade > *:nth-child(8) { animation-delay: var(--d-modal); }
  /* 第 9 行起不排队登场：级联讲的是「第一眼那几行的次序」，深处的行本就在屏幕外。
     原来给 9 行以后统一挂 .25s 延时，回位到半途时屏幕上那批全是「9 行以后」，
     于是整屏先僵一下再齐弹——站主报的「中间开页动效慢很多」就是这 .25s。
     顺带省掉长列表里几十条无人可见的合成动画。 */
  .list-cascade > *:nth-child(n + 9) { animation: none; }
}

/* ← 05-views.css:794 */
@media (max-width: 768px) {
  .modal-card .modal-body, .modal-card .modal-foot { transition: opacity var(--d-micro) ease, transform var(--d-micro) ease; }
  .modal-card.leaving .modal-body, .modal-card.leaving .modal-foot { opacity: 0; transform: translateY(10px); }
}

/* ← 05-views.css:915 */
@media (max-width: 768px) {
  /* 手机端行式定稿：单行不折行——头像｜昵称+@账号｜角色胶囊｜删除，
     角色胶囊兼任徽章与改角色入口（点开底部抽屉点即存）；
     行的信息区 1011 起改开「账号信息」详情（邮箱、注册时间在那页才放得下） */
  .user-row { padding: var(--sp-3) var(--sp-3); gap: var(--sp-3); }
  .user-row-info { flex: 1; min-width: 0; }
  .user-row-sub { margin-top: 3px; }
  /* 「单行不折行」是上面这句定稿，但副行一直没有溢出保护：@账号 · 添加于 2026-10-07
     在 390 宽本来就会折成两行（实测 Kezn 那一行 sub 高 40，与有没有额度钮无关）。
     补 nowrap + 省略号，行高回到一行；这一行右边再多一颗钮也不会把它顶高。
     名字行本来就有这套保护（.user-row-name），副行是漏的那一个。 */
  .user-row-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}

/* ← 05-views.css:1011 */
@media (max-width: 768px) {
  .dd { width: 100%; }
}

/* ← 05-views.css:1038 */
@media (max-width: 768px) {
  /* 1010d/e/f（站主三轮）：dock 几何只归两个令牌 + 两条 margin 规则管——宽度 = 100% − dock-r − slim
     （296→246→224→200；1012 晚场再收一档：只动 slim 78→102，≤380 档不跟、小屏席位优先）；加号 60→54 回文档流（基座本来就是 flex 子件）；has-add 时
     [胶囊+10+加号] **成组居中**，无加号时用 --dock-r（=间隔10+加号54）作占位补偿把胶囊扶正
     ——margin 0 ↔ --dock-r 就是「让位」那一下的位移量。别再重抄第二份数；
     也别把加号改回 absolute（钉右缘就成不了组，1010e 的教训） */
  .tabbar { --dock-r: 64px; --dock-slim: 102px; }
  .tabbar-dock {
    contain: layout paint;    /* 胶囊内部的重排不外溢到页面（fixed 浮层，本就独立一层） */
    transition: margin-left var(--d-toast) var(--ease-enter);
  }
  .tabbar .tabbar-add { width: 54px; height: 54px; }
  /* 1010f 成组居中：has-add 时 [胶囊+10+加号] 整组由 flex 居中（胶囊 x=39、两侧各留 39） */
  .tabbar.has-add .tabbar-dock {
    margin-left: 0; margin-right: 0;
    transform: none;
    transition: margin-left var(--d-toast) var(--ease-enter);
  }
  /* 概览/统计等没有加号的页：胶囊单体居中。延迟 .08s——加号缩到约一半时胶囊才开始走，
     重叠 80ms 去掉「等它让位」的感觉；让位方向（回有加号那侧）即时启动，不等。
     1010f：占位补偿 = --dock-r（隐藏的加号仍在流里占位，用它的宽度把胶囊扶正，两态差 32px） */
  .tabbar:not(.has-add) .tabbar-dock {
    margin-left: calc(var(--dock-r)); margin-right: 0;
    transform: none;
    transition: margin-left var(--d-toast) var(--ease-enter) .08s;
  }
}

/* ← 05-views.css:1112 */
@media (max-width: 768px) {
  .tf-row { padding: var(--sp-3) var(--sp-3); }
}

/* ← 05-views.css:1712 */
@media (max-width: 768px) {
  .ws-grid { gap: var(--sp-3) var(--sp-3); }
  .ws-stage { height: 132px; }
  .ws-mock-21 { height: 66px; }
}

/* ← 05-views.css:1775 */
@media (max-width: 768px) {
  .dc-card.dd-modal .modal-body { padding-top: calc(var(--sp-12) + var(--module-gap) * 2 + var(--safe-top)); }
}

/* ← 05-views.css:1928  「窄屏（≤360）大字先退一档，别让「可序Ai」把状态行挤成两行；底板跟着收到品牌标准 32」 */
@media (max-width: 360px) {
  .ai-name { font-size: calc(17px * var(--fs-scale)); }
  .ai-mark { width: 32px; height: 32px; }
  .ai-mark svg { height: 24px; }
}

/* ← 05-views.css:2132 */
@media (max-width: 380px) {
  /* 超窄屏 / 系统大字体：两段各留够 44px 热区，靠缩内距而不是缩字号 */
  .nl-act-btn { padding: 0 var(--sp-3); }
}

/* ← 05-views.css:2346 */
@media (max-width: 380px) {
  .toolbar { gap: var(--sp-2); }
  .seg button { padding: 0 var(--sp-2); }
}

/* ← 05-views.css:2356 */
@media (max-width: 768px) {
  :root {
    --fs-display: 1.85rem;
    --fs-h1: 1.45rem;    /* ≈23px 页面主标题 */
    --fs-h2: 1.25rem;    /* ≈20px 弹窗/分区标题 */
    --fs-body: 0.95rem;  /* ≈15.2px 正文 */
    --fs-caption: 0.9rem;/* ≈14.4px 次级文字 */
    --fs-label: 0.82rem; /* ≈13px 表单标签 */
    /* 字段标题在手机上抬到 16px（1104 站主令：全站表单标题只此一档）。
       以前这一档散落在 .fg-row / .fg-switch 的裸 calc(16px) 里，堆叠行与主角行却吃
       --fs-label 13px，同一张「新增订阅」实拍出来标题三档并存——收进令牌后各选择器
       只认令牌，尺寸端别差异留在这里这一处。 */
    --fld-label-fs: calc(16px * var(--fs-scale));
    --fs-micro: 0.75rem; /* 12px 微标签地板 */
    --lh-body: 1.65;
    --control-h: 44px;   /* iOS HIG 触控基准 */
    --control-h-sm: 34px;
    /* 手机端「卡」只有一档 12（= 待办卡）。备忘/日程/习惯/小记/心情带/用户行/面板此前漏补档，
       一直吃桌面 8，比待办卡方一截。抬令牌让 19 处一起归位，不给单类开补丁；桌面不动。 */
    --radius-card: var(--r-3);
  }

  /* 表单/搜索/自定义下拉：高度与字号对齐 44px 触控行 */
  .form-input, .search-field-input, .select-wrap select, .sel-btn, .dp-display { height: 44px; }
  .sel-btn, .dp-display, .sel-opt { font-size: var(--fs-input); }
  .select-wrap::after { top: calc(50% + 1px); }
  textarea.form-input { min-height: 88px; font-size: var(--fs-input); }
  .md-seg button { height: 40px; }
  .chip { height: 38px; font-size: var(--fs-caption); }
  .cat-filter .chip { height: 38px; }
  .search-field-icon { width: 16px; height: 16px; }
  .search-field-input { padding-left: 38px; padding-right: var(--sp-8); }
  .search-clear { width: 26px; height: 26px; right: 6px; }
  .search-clear svg { width: 12px; height: 12px; }

  /* 待办：表格字号与行高（移动端已转卡片布局） */
  .data-table { font-size: calc(15px * var(--fs-scale)); }
  .data-table th { font-size: calc(13px * var(--fs-scale)); }
  #todoBody tr { padding: var(--sp-3) var(--sp-3); row-gap: var(--sp-1); }
  .todo-check-box { width: 22px; height: 22px; }
  .todo-check-box svg { width: 14px; height: 14px; }
  .todo-desc { margin-top: var(--sp-1); }

  /* 大数字区：等宽数字是这套设计的灵魂。手机端只抬令牌——
     summary/count 合并成同一档 KPI 读数（旧 24↔27 分叉就此消除），概览问候长句收到 22。 */
  :root { --fs-num-sm: 1.5rem; --fs-num-md: 1.375rem; }
  .count-unit { font-size: var(--fs-micro); }
  .count-since { font-size: var(--fs-12); }
  .summary-sub { font-size: var(--fs-12); }

  /* 徽章/计数：全部抬到 ≥11px 地板，计数泡加大 */
  .seg-cnt { font-size: var(--fs-12); min-width: 18px; height: 18px; }
  .chip .chip-cnt { font-size: var(--fs-12); }
  .menu-cnt { font-size: var(--fs-11); min-width: 20px; height: 20px; line-height: 20px; }
  .tabbar .menu-cnt { font-size: var(--fs-10); top: 2px; left: calc(50% + 13px); }
  .role-badge { font-size: var(--fs-11); height: 18px; padding: 0 var(--sp-2); }
  .badge { font-size: var(--fs-micro); }

  /* 底部 dock：图标与标签同步放大（1010d 瘦身：图标 22→18、内距 8/7→5/5，胶囊矮一档） */
  .tabbar .menu-item { padding: var(--sp-1) 0 var(--sp-1); }
  .tabbar .menu-item svg { width: 18px; height: 18px; }

  /* Markdown 渲染（备忘详情） */
  .md-body h1 { font-size: calc(19px * var(--fs-scale)); } .md-body h2 { font-size: calc(17px * var(--fs-scale)); }
  .md-body h3 { font-size: calc(15px * var(--fs-scale)); } .md-body h4 { font-size: calc(14px * var(--fs-scale)); }

  /* Toast 与空态 */
  .toast { font-size: calc(15px * var(--fs-scale)); padding: var(--sp-2) var(--sp-4); }
}

/* ← 05-views.css:2424 */
@media (max-width: 380px) {
  :root { --fs-num-sm: 1.375rem; } /* 超窄屏：KPI 读数统一收一档（旧 summary22/count24 分叉消除） */
}

/* ← 05-views.css:2451 */
@media (max-width: 768px) {
  .tabbar-dock { overflow: hidden; } /* 兜底裁剪：形变按余量夹过，正常碰不到这条线 */
  .tabbar-ind {
    width: 0; background: transparent;
    transition: none;
    will-change: transform;
  }
  .tabbar-ind-core {
    position: absolute; inset: 0; display: block;
    border-radius: var(--radius-pill);
    background: var(--glass-sel-fill);
    box-shadow: var(--glass-sel-rim), 0 2px 8px rgba(17, 17, 17, .06);
    will-change: transform;
  }
}

/* ← 05-views.css:2472 */
@media (max-width: 768px) {
  .tabbar-dock {
    background: var(--glass-fill);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    box-shadow: var(--glass-rim), var(--glass-drop);
  }
  /* dock 只保留「拖动橡皮筋」（transform 由 app.js 逐帧写）+ 方向 chip 到位弹一下；
     之前叠在阴影上的蓄力光晕 / 到位圆环 / inset 内透光（v2.1、v2.2）已按用户要求全部移除。 */
}

/* ← 05-views.css:2567 */
@media (max-width: 768px) {
  .dd-modal .modal-foot .btn-primary { height: var(--control-h-lg); font-size: var(--fs-ctrl-lg); border-radius: var(--radius-lg); }
  .dd-modal .modal-foot .btn-danger { height: var(--control-h-lg); border-radius: var(--radius-lg); }
  .dd-modal .modal-foot { padding-left: var(--sp-4); padding-right: var(--sp-4); }
  /* 1010 圆角 §5 裁决：详情头图是「层」不是卡，裁给 r-5；此前手机 18px 被就近归到
     r-4(16) 属误档——与裁决和详情台子的「≥18」判据都相悖，这里按裁决并档，勿再降。 */
  .dd-hero { border-radius: var(--r-5); }
}

/* ← 05-views.css:2590 */
@media (max-width: 768px) {
  .dd-modal.dd-notitle .modal-head h2 { display: none; }
  /* 圆形返回钮：v1.4（2026-09-23）起升级为「全站弹窗头部」共用语言，
     详情 / 编辑 / 个人中心二级页一律同款白圆钮，规则收在文件后段
     「手机端间距规范 · 头部返回钮」一处，此处不再重复定义 */
  /* ===== 弹窗头部「主标题」收口成一条（1016 站主：详情与编辑这两页的标题要一样、且更靠左的返回钮） =====
     编辑页主标题 h2 与详情页面包屑 .dd-crumb 是**同一个角色**——排在白圆返回钮右侧、左对齐、单行省略。
     过去两处各写一遍，已经漂了两样：
       ① 字号 16 / 15（真页量出来的，差 1px 却再没人对齐过）；
       ② 各自又补了一道 margin-left: var(--sp-3)，而 .modal-head 本身就是 gap: var(--sp-3)
          —— 同一档间距叠两次，实测返回钮右缘到标题左缘 24px。
     现在合并成一条共享声明：几何与字号只有一处可改；颜色按角色分开（主标题黑、带「类型 · 名称」
     前缀的面包屑退一档灰），这是层级不是漂移。
     ★ 别再往这两条上加 margin-left/padding：与返回钮的距离只由 .modal-head 的 gap 那一档决定。 */
  .wbf-modal .modal-head h2,
  .dd-modal.dd-notitle .dd-crumb {
    position: static; transform: none; max-width: none;
    flex: 1; min-width: 0; margin-left: 0;
    text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: calc(16px * var(--fs-scale)); font-weight: var(--fw-medium);
  }
  .wbf-modal .modal-head h2 { color: var(--text-1); }                        /* 编辑页：这一页的主标题 */
  .dd-modal.dd-notitle .dd-crumb { display: block; color: var(--text-2); }   /* 详情页：面包屑，退一档灰 */
  /* 英雄区大标题升一级（勾选框仍在其左，点卡完成的手势不变）；推广到备忘/事件/习惯的英雄名 */
  .dd-modal.dd-notitle .td-title,
  .dd-modal.dd-notitle .dd-hero-name,
  .dd-modal.dd-notitle .hb-hero-name { font-size: calc(22px * var(--fs-scale)); }
  /* 紧凑一行 meta：默认贴卡左缘内衬；待办英雄区里与标题文字对齐（复选框 22 + 间隙 12） */
  .dd-meta {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2);
    margin-top: var(--sp-3); padding-left: 0;
    font-size: calc(13px * var(--fs-scale)); color: var(--text-4); line-height: 1.5;
  }
  .td-hero .dd-meta { padding-left: 34px; }
  .dd-meta .tag { font-size: var(--fs-12); }
  .dd-meta-sep { width: 1px; height: 11px; background: var(--border); flex-shrink: 0; }
  .dd-meta .td-cat { gap: var(--sp-1); }
  .dd-meta .cat-dot { width: 8px; height: 8px; }
  /* 悬浮动作条：absolute 钉在卡片底部（卡=全屏，滚动不带走；避开 home 条）。
     容器保留 dd-foot-inline 类（探针选择器契约），故所有覆写用复合选择器
     抬高特异性——基础 .dd-foot-inline 规则在文件更后位置，等特异性会被反杀 */
  .dd-foot-inline.dd-fabbar {
    position: absolute; left: 16px; right: 16px; bottom: calc(14px + var(--sab));
    z-index: 8; margin-top: 0; padding-bottom: 0;
    display: flex; flex-direction: row; align-items: center; justify-content: center; gap: var(--sp-3);
  }
  .dd-foot-inline.dd-fabbar .fab-circle {
    width: 50px; height: 50px; flex-shrink: 0; padding: 0;
    border: none; border-radius: var(--r-circle); background: var(--bg-card); color: var(--tag-bad-fg);
    box-shadow: 0 4px 12px rgba(17, 17, 17, .08); cursor: pointer; /* 阴影与返回圆钮同档，真机反馈 .22 太重 */
    display: inline-flex; align-items: center; justify-content: center;
    transition: transform var(--d-micro) ease, background var(--transition-fast);
  }
  .dd-foot-inline.dd-fabbar .fab-circle svg { width: 21px; height: 21px; }
  .dd-foot-inline.dd-fabbar .fab-circle:active { transform: scale(.94); background: var(--bg-hover); }
  /* 末条内容要从删除钮下方滚得出来 */
  .dd-modal.dd-fab .modal-body { padding-bottom: calc(76px + var(--sab)); }
  /* 没有底栏的整屏页（2.52 人物编辑器）：内容要能一路滚过手机底部手势条。
     口径照 .mc-sheet / .ss-sheet 那两处的「16px + 安全区」，不自己另定一个数。
     先例是 .bin-sheet.bin-nofoot——同样是"没有底栏所以要自己补安全区"。 */
  .dd-modal.dd-nofoot .modal-body { padding-bottom: calc(var(--sp-4) + var(--sab)); }
}

/* ← 05-views.css:2675 */
@media (max-width:768px) {
  /* 纵深黑灰遮罩已整层撤除（1015 站主点名设置二级页那种「背景不压黑」的干净感）：
     详情进出只留壳层缩放的景深（has-layer），mask 恒透明——与设置/个人中心二级页同一观感，
     退场也就不存在任何遮罩闪烁。曾先后试过 background 动画（真机每帧重绘=闪）与
     ::before opacity 动画（合成器顺但视觉上仍要那层黑），最终按站主审美撤干净。 */
  /* 退出整屏详情：页面向下滑走（只滑不淡）。站内 05 的 @keyframes sheetDown 带 opacity 淡出+缩放，
     加载序盖过 04 的纯位移版——用它页面会「淡走」，所以单开一只只 translateY 的关键帧。
     选择器 (0,4,0) 压过 04 的 .modal-card.closing (0,2,0)。 */
  @keyframes tdSlideDown { from { transform: translateY(0); } to { transform: translateY(100%); } }
  .modal-card.dd-modal.dd-notitle.closing { animation: tdSlideDown var(--d-push) var(--ease-ios) forwards; }
  /* 抽屉时代的顶部抓手 / 顶角圆角 / 78% 贴底几何随抽屉一起撤；整屏页靠悬浮标题栏自带留白。
     will-change 也一并上移到 04 的 `.modal-card`——它若只挂在详情上，详情↔编辑切那一瞬
     合成层要拆一次重建一次，真机就可能出现「卡片底色没画、只有悬浮标题淡淡印在列表上」的一帧。 */
}

/* ← 05-views.css:3062 */
@media (max-width: 768px) {
  .wbf-modal { background: var(--bg-page); }
  .wbf-modal .modal-body { padding-bottom: var(--sp-6); }

  .fg-card {
    display: block; background: var(--bg-card);
    border-radius: var(--radius-card-m); box-shadow: var(--shadow-card);
    overflow: hidden; margin-bottom: var(--sp-3);
  }
  .fg-card .field { margin: 0; padding: 0 var(--sp-4); position: relative; }
  .fg-card .field + .field::before {
    content: ""; position: absolute; top: 0; left: 16px; right: 16px;
    border-top: 1px solid var(--border);
  }

  /* 行式：左标签 + 右控件（无边框、右对齐）
     标签列下限 80px = 五字标签宽度（16px 实测）。1011 标题对齐开关行升 16px/500，
     15px 时代的 76px 下限跟着长 4px——下限偏小时三/四字行与五字行各起一条输入
     起始线，同一张卡右对齐的值就错开；1003 加图标片后下限随行再长一枚图标+点距。 */
  .fg-card .fg-row { display: flex; align-items: center; gap: var(--sp-3); min-height: 54px; }
  .fg-card .fg-row > label {
    flex: 0 0 auto; min-width: calc(80px + var(--fg-i-w) + var(--fg-i-gap));
    /* 图标与标题垂直居中走 flex（inline 的 vertical-align 魔法数在 15→16px 后偏低 2px，
       且字号档位一变就漂移）；文字成为匿名 flex 项，图标盒与其中心线对齐。
       字号/字重/墨色不在这里——1104 起全站字段标题只有 03 那一档，手机端由
       --fld-label-fs 在本片 :root 重映射成 16px，本行只需给版式。 */
    display: inline-flex; align-items: center;
  }
  .fg-card .fg-row > label .req { margin-left: 2px; }
  .fg-card .fg-row .form-input,
  .fg-card .fg-row .select-wrap,
  .fg-card .fg-row .date-wrap,
  .fg-card .fg-row .pwd-field { flex: 1; min-width: 0; }
  .fg-card .fg-row .form-input {
    border: none; background: transparent; box-shadow: none;
    height: 54px; text-align: right; padding: 0; font-size: calc(16px * var(--fs-scale));
  }
  .fg-card .fg-row .form-input:focus { border: none; box-shadow: none; }
  /* 密码行：右缘必须给小眼睛预留 46px（34 钮 + 5 右距 + 余量）——
     上面 .fg-row 的 padding:0 特异性更高，会把通用的 .pwd-field .form-input
     预留清掉，右对齐的占位文字就直接压在眼睛上 */
  .fg-card .fg-row .pwd-field .form-input { padding-right: 46px; }
  .fg-card .fg-row .sel-btn,
  .fg-card .fg-row .dp-display {
    width: 100%; border: none; background: transparent; box-shadow: none;
    height: 54px; text-align: right; font-size: calc(16px * var(--fs-scale)); color: var(--fld-ink);
    padding-right: 0;
  }
  /* 行式「未选值」必须退回占位档：上面 (0,3,0) 压掉 03 层 .is-placeholder 的灰——
     修复前「请选择日期」黑得像已选值（1011 实测） */
  .fg-card .fg-row .sel-btn.is-placeholder,
  .fg-card .fg-row .dp-display.is-placeholder { color: var(--text-hint); }
  /* 行式下拉：右对齐的值必须给小三角让位，否则「纪念日」这类长字会压在箭头上 */
  .fg-card .fg-row .sel-btn { padding-right: var(--sp-4); }
  .fg-card .fg-row .select-wrap::after,
  .fg-card .fg-row .date-wrap .dp-caret { right: 6px; }
  .fg-card .fg-row .date-ico { display: none; }
  .fg-card .fg-row .form-input::placeholder { text-align: right; }

  /* 农历换算：标签在上、三个描边小下拉 */
  .fg-card .fg-stack { padding: var(--sp-3) var(--sp-4) var(--sp-4); }
  /* 堆叠行标题：字形吃 03 的字段标题唯一档，这里只定它到控件的间距。
     `.fg-stack.field-row > .field > label` 是回顾页那种「组合行里再套字段」，
     直接子选择器打不到它，一并列在同一档间距里。 */
  .fg-card .fg-stack > label,
  .fg-card .fg-stack.field-row > .field > label { margin-bottom: var(--sp-2); }
  .fg-card .fg-stack .field-row-3 { gap: var(--sp-2); }
  .fg-card .fg-stack .sel-btn {
    height: 40px; border: 1px solid var(--border); background: var(--bg-page);
    border-radius: var(--radius-btn); font-size: calc(14px * var(--fs-scale)); text-align: center; padding: 0 var(--sp-1);
  }

  /* 开关行：沿用 switch-row 结构，只给卡片节奏 */
  .fg-card .fg-switch { padding: var(--sp-1) var(--sp-4); }
  .fg-card .fg-switch .switch-row { padding: var(--sp-2) 0; }
}

/* ← 05-views.css:3135  「分组卡内开关联动拍平：switch-row 自带的小内衬与卡片叠层冲突」 */
@media (max-width: 768px) {
  .fg-card .fg-row > label { margin: 0; }
  .fg-card .fg-switch .switch-row { padding: var(--sp-3) 0; border: none; background: transparent; }
  .fg-card .fg-switch + .fg-switch .switch-row::before { content: none; }
  .fg-card .fg-switch .switch-desc { font-size: var(--fs-label); margin-top: 3px; }
  /* 编辑页开关放大为 iOS 比例（46×27），统一靠右 */
  .fg-card .status-switch { width: 46px; height: 27px; }
  .fg-card .status-switch .switch-slider::before { width: 23px; height: 23px; left: 2px; top: 2px; }
  .fg-card .status-switch input:checked + .switch-slider::before { transform: translateX(19px); }
  /* check-line 搬家后的开关行：去掉复选框时代的左边距节奏 */
  .fg-card .check-line.switch-row { gap: var(--sp-3); align-items: center; justify-content: space-between; }
}

/* ← 05-views.css:3155 */
@media (max-width: 768px) {
  /* 分组卡内组件节奏 */
  .fg-card .fg-stack { padding: var(--sp-3) var(--sp-4) var(--sp-4); }
  .fg-card .fg-stack .check-line {
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--sp-3) 0; margin: 0;
  }
  .fg-card .fg-stack .md-field-head { flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-2); }
  .fg-card .fg-stack .md-seg button { height: 32px; }
  .fg-card .fg-stack .field-hint { margin-top: var(--sp-2); }
  .fg-card .fg-stack .sub-add .form-input { height: 40px; }
  /* 回顾：日期+心情组合行在卡内转纵向 */
  .fg-card .fg-stack.field-row { display: block; }
  .fg-card .fg-stack.field-row > .field { padding: 0; }
  .fg-card .fg-stack.field-row > .field + .field { margin-top: var(--sp-3); }
  /* 这一档的标题间距已并入上面 `.fg-card .fg-stack > label` 那条选择器列表 */
}

/* ← 05-views.css:3207 */
@media (max-width: 768px) {
  .toast-container {
    --il-bottom: 124px;
    top: auto;
    bottom: calc(var(--il-bottom) + var(--sab));
    gap: var(--sp-2);
  }
  .toast {
    position: relative;
    /* toast 暗台材质（§1 豁免）：明暗两档都深底白字——通知浮层须压住任意页面且高可见；
       #FCFCFC 字 / #30D158 勾（贴系统绿）/ rgba(252,252,252,.36) 描边均刻意不翻面 */
    background: rgba(26, 26, 28, .92); color: #FCFCFC;
    border: none; border-radius: var(--radius-pill);
    /* 状态点左留白 18→13（1016 站主令）：贴住圆角侧的呼吸位；种子宽由 JS 读内衬自动跟随 */
    padding: var(--sp-3) var(--sp-4) var(--sp-3) var(--sp-3); font-size: calc(14.5px * var(--fs-scale));
    box-shadow: 0 8px 24px rgba(0, 0, 0, .25);
    /* 保险丝=整屏各让 10px（1016 站主令：能完整的话必须完整——92vw 在窄屏视口仍咬字，改物理边距） */
    max-width: calc(100vw - 20px);
    /* 岛形变：width 是主角；opacity/transform 同列表供退场同帧收尾。
       will-change 把逐帧 layout 的抖劲压住（1016 真机：文字出场断续顿挫=主线程逐帧重排+模糊层） */
    /* 1016e 站主三图定案：曲线换「早冲刺收尾」——250ms 走完 99%，尾巴几乎不动；
       字固定 260ms 亮（不等 400ms 停稳事件=出场太慢），亮时边已近静止=也不犁字。 */
    overflow: hidden; animation: none; will-change: width;
    opacity: 0; visibility: hidden;
    transition: width var(--d-morph) cubic-bezier(.12,.9,.22,1), transform var(--d-push) var(--ease-exit), opacity var(--d-toast) ease, visibility 0s linear var(--d-morph);
    -webkit-backdrop-filter: blur(12px) saturate(140%);
    backdrop-filter: blur(12px) saturate(140%);
  }
  .toast.is-in { visibility: visible; opacity: 1;
    transition: width var(--d-morph) cubic-bezier(.12,.9,.22,1), transform var(--d-push) var(--ease-exit), opacity var(--d-toast) ease, visibility 0s; }
  .toast.il-instant { transition: none !important; }   /* 种子定位/量宽时挂起，防抢跑 */
  /* 就地换短句（长换短）＝收缩：不复用出场的「早冲刺收尾」（那条是给展开挑的：
     250ms 走 99% 再慢慢爬；用在收缩上读起来是先一刀抽干、再拖着走），改从容收。
     只换 width 这一条通道，其余照 is-in 原样列出来（shorthand 只能整条重写）。 */
  .toast.is-in.il-shrink {
    transition: width var(--d-toast) var(--ease-float), transform var(--d-push) var(--ease-exit), opacity var(--d-toast) ease, visibility 0s; }
  /* 退场三拍（1105 站主：收缩那一下别扭 → 又要更快更丝滑）：
     文字先退净（.12s）→ 岛体 80ms 起化掉 → 140ms 缩回种子（1105 三轮把淡出提前了一拍，见 il-dissolve）。
     ① 旧写法只改 transition-duration，缩回跟着吃出场那条早冲刺曲线：165ms 抽掉九成宽、
        剩下一截慢慢爬；
     ② 更要命的是文字压根没淡出（见下面 il-lit.il-glyph 那条），缩回去的右缘当场把还全亮的
        字切掉一截——逐帧量到 38~136px，不是观感猜。
     ③ 修好这两条后仍嫌黏：淡出被压了 .12s 延迟（先合完再化掉＝三段式，尾巴看得见）。
        现在缩回 .22s 从容收、淡出 .15s 提前到退字拍中途起跑——岛还在合的那一瞬就已经化掉了，
        肉眼到的总长从 ~390ms 收到 ~240ms，且没有「停住了才没气」的最后一格。
     visibility 延迟仍兜在最后，杜绝凭空消失。 */
  /* 退场第一拍（il-unlit＝灭字拍，比缩回早 140ms）：整句文字与那颗状态点一起先散。
     点原先不吃这一拍，只跟着岛体最后那道淡出没——绿点在胶囊里一直亮到凭空消失，
     收尾没有先后＝站主说的突兀。现在视线里的顺序是「字没→点没→胶囊合拢化掉」。
     淡出挂在 .toast-lead 整槽（不是 .toast-dot）：加载环与完成勾同住这一槽，退场一样该先散。 */
  .toast.il-unlit .toast-lead { opacity: 0; transition: opacity var(--d-micro) ease; }
  /* 退场第二拍提前（1105 三轮，站主拍「拆开：岛体提前化掉」）：岛体在字退净之前就开始化，
     缩回那一拍只管合宽度。旧口径「淡出与缩回同帧起」把总时长顶到 300ms 闸外（实测 303ms）。
     只列 opacity，别把 width 吃进来——宽度归下面那条 il-closing；本条必须排在它前面（同特异度，晚者胜）。 */
  .toast.il-dissolve { opacity: 0; transition: opacity var(--d-fast) ease; }

  .toast.il-closing {
    transition: width var(--d-modal) var(--ease-float), opacity var(--d-fast) ease, visibility 0s linear var(--d-toast); }
  .toast.il-out { opacity: 0; transform: scale(.92); }
  /* 岛是单行生物（1016 站主令：不许两行高度）：文案锁一行、岛永不长高，
     省略号只当保险丝——治本靠削文案（2.67 逐条改短）。出字仍等宽度落定（防犁字顿挫）。 */
  .toast .toast-txt { display: block; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    opacity: 0; transition: opacity var(--d-micro) ease; }
  .toast.il-lit .toast-txt { opacity: 1; transition: opacity var(--d-base) ease-out; }
  .toast .toast-act { flex: 0 0 auto; }   /* 保险丝只削文字，不削按钮 */
  /* ===== 1016 岛文字改「逐字滚动揭示」+ 装不下就跑带（站主拍板：一个字都不丢） =====
     .il-run / .il-g 的骨架样式在 03-components（顶栏标题共用），这里只管岛自己的三件事：
     ① il-glyph：亮字交给每个字自己淡入，整句那道淡入必须关掉——两层叠在一起＝字还没滚完
        就先被容器提亮，读起来是「一片白雾」不是「逐字进」。
        ★ 1105：这一条必须绑在 il-lit 上（旧写法只写 il-glyph）。摘 il-lit 时 JS 不摘 il-glyph，
          于是「opacity:1 + transition:none」一直压着上面那条淡出——退场的文字全程全亮，
          直接被缩回的裁剪边切掉；换句时也照样闪一下新句再重来。
     ② il-marquee：跑带期间不许再描省略号——字是一个都不丢，留个「…」就是撒谎。
     ③ il-tight：连封顶都装不下时，内衬/气隔/状态点槽/撤销钮一起让位，先抠字给文案。
        撤销钮视觉缩到 26，但 ::before 外扩补回 38 热区——拇指那一下不许跟着缩。 */
  .toast.il-lit.il-glyph .toast-txt { opacity: 1; transition: none; }
  .toast.il-marquee .toast-txt { text-overflow: clip; }
  .toast.il-tight { padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-2); gap: var(--sp-1); }
  .toast.il-tight:has(.toast-act) { padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-2); gap: var(--sp-1); }
  .toast.il-tight .toast-lead { width: 14px; }
  .toast.il-tight .toast-act.is-icon { width: 26px; min-width: 26px; height: 26px; min-height: 26px; }
  .toast.il-tight .toast-act.is-icon::before { inset: -6px; }

  /* 图标位 16px 槽：状态点 / 加载环 / 完成勾 三合一，同位换脸不搬家 */
  .toast-lead { position: relative; width: 16px; height: 16px; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; }
  .toast.is-in .toast-lead { animation: ilLeadPop var(--d-enter) var(--ease-lead) both; }
  @keyframes ilLeadPop { from { transform: scale(1.15); } to { transform: scale(1); } }
  .toast-spin { position: absolute; width: 16px; height: 16px; opacity: 0; transform: rotate(-90deg); }
  .toast-spin circle { fill: none; stroke: #FCFCFC; stroke-width: 2.4; stroke-linecap: round; stroke-dasharray: 34 44; }
  .toast.is-loading .toast-dot { opacity: 0; }
  .toast.is-loading .toast-spin { opacity: 1; animation: ilSpin .9s linear infinite; }
  @keyframes ilSpin { to { transform: rotate(270deg); } }
  .toast-check { position: absolute; width: 16px; height: 16px; opacity: 0; }
  .toast-check path { fill: none; stroke: #30D158; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 20; stroke-dashoffset: 20; }
  .toast.is-checked .toast-spin { opacity: 0; animation: none; }
  .toast.is-checked .toast-dot { opacity: 0; }
  .toast.is-checked .toast-check { opacity: 1; }
  .toast.is-checked .toast-check path { animation: ilDraw var(--d-enter) var(--ease-pop) .02s forwards; }
  @keyframes ilDraw { to { stroke-dashoffset: 0; } }
  /* 状态点与岛同帧起跳（挂 is-in，不挂文字揭示——挂揭示=掉拍），只留缩放脉冲 */
  .toast.is-in .toast-dot { animation: ilDotPop var(--d-push) var(--ease-lead) .05s backwards; }
  @keyframes ilDotPop { from { transform: scale(.4); opacity: .35; } to { transform: scale(1); opacity: 1; } }
  /* 连点续命：同句不重播开合，胶囊内高光扫一道 */
  .toast-sheen { position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
    background: linear-gradient(105deg, transparent 20%, rgba(255,255,255,.22) 46%, rgba(255,255,255,.05) 58%, transparent 82%);
    transform: translateX(-130%); }
  .toast.il-sustain .toast-sheen { animation: ilSheen var(--d-slow) var(--ease-enter) both; }
  @keyframes ilSheen { 0% { opacity: 0; transform: translateX(-130%); } 16% { opacity: 1; } 100% { opacity: 0; transform: translateX(130%); } }
  [data-theme="dark"] .toast {
    background: rgba(60, 62, 68, .94);
    border: 1px solid var(--border);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
  }
  .toast .toast-dot { background: #30D158; box-shadow: 0 0 0 3px rgba(48, 209, 88, .22); }
  /* 撤销钮住在深底胶囊里：描边与文字必须跟着反相，否则桌面令牌（近黑字+浅边框）在真机上等于隐形。
     带操作的 toast 不再点文字就关，光标也收回成默认，避免整条被读成一个大按钮 */
  .toast:has(.toast-act) { cursor: default; padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-3); }
  /* 撤销是拇指要点中的钮：热区按站内地板 38px 撑满，视觉上仍是一枚描边小胶囊 */
  .toast-act {
    display: inline-flex; align-items: center; min-height: 38px;
    color: #FCFCFC; border-color: rgba(252, 252, 252, .36);
    background: rgba(252, 252, 252, .1); padding: 0 var(--sp-4); font-size: calc(14px * var(--fs-scale));
  }
  @media (hover: hover) { .toast-act:hover { background: rgba(252, 252, 252, .18); } }
  /* 撤销钮瘦身（1006，站主：带撤销的 toast 特别高，但撤销钮要留）：
     38×38 热区把胶囊最小高顶到 ~58px。改视觉 30px、::before 透明外扩把热区补回 38
     （站内紧凑钮先例），点按面积一分不缩，胶囊回到 ~46px */
  .toast-act.is-icon { width: 30px; min-width: 30px; height: 30px; min-height: 30px; padding: 0; position: relative; }
  .toast-act.is-icon::before { content: ''; position: absolute; inset: -4px; }
  .toast-act.is-icon svg { width: 15px; height: 15px; }
  .toast-warn .toast-dot { background: #FF9F0A; box-shadow: 0 0 0 3px rgba(255, 159, 10, .22); }
  .toast-error .toast-dot { background: #FF453A; box-shadow: 0 0 0 3px rgba(255, 69, 58, .22); }
  .toast-out { opacity: 0; transform: translateY(10px) scale(.98); }
  /* 手机端容器锚在底部（dock 之上）：退场那一枚贴容器下缘，才和顶上来的一枚重合在同一个位置。
     特异度与上面那条保持一致（.toast-container 前缀），否则媒体查询盖不过基础规则 */
  .toast-container .toast-ghost { top: auto; bottom: 0; }
}

/* ← 05-views.css:3389 */
@media (max-width: 768px) {
  .fg-card .pf-edit-avatar { padding: var(--sp-4) var(--sp-4) 0; margin-bottom: 0; }
  .fg-card .pf-edit-avatar .field-hint { margin-top: var(--sp-1); }
}

/* ← 05-views.css:3397 */
@media (max-width: 768px) {
  .user-avatar, .avatar-btn, .user-row-avatar { border-radius: var(--r-circle); }
}

/* ← 05-views.css:3462 */
@media (max-width: 768px) {
  :root {
    /* --sp-5: 20px 已于 1025 上提进 01 令牌层（曾只造在本媒体块内 → 桌面消费点 IACVT 丢 padding） */
    --content-px: var(--sp-4);      /* 16 页面边距 */
    --content-py: var(--sp-4);      /* 16 */
    --card-pad:   var(--sp-4);      /* 16 卡片内距（横） */
    --card-gap:   var(--sp-3);      /* 12 卡片/网格间距 */
    --module-gap: var(--sp-5);      /* 20 模块/分区间距 */
  }
  /* 消费方重映射 */
  .toolbar { margin-bottom: var(--card-gap); }
  .pfg { margin-top: var(--module-gap); }
  .modal-card .modal-body { padding: calc(var(--sp-12) + var(--module-gap) + var(--safe-top)) var(--card-pad) var(--card-pad); }
  .modal-foot { padding-left: var(--card-pad); padding-right: var(--card-pad); }
  .login-pop { padding-left: var(--card-pad); padding-right: var(--card-pad); }
  /* 节奏统一（2026-09-19 定，2026-10-14 站主点名再收一档）：
     筛选行（状态分段 / 分类·标签·类型 chips）→ 列表首卡一律 card-gap 12，
     与卡片之间的间距同档，读起来是一组；此前 module-gap 20 让筛选行像浮在列表上方。
     注意用 :has 收工具栏底距——相邻 margin 会折叠取大者，给后行加 margin-top 无效 */
  .toolbar:has(+ .cat-filter) { margin-bottom: var(--card-gap); }
  .cat-filter { margin-bottom: var(--card-gap); }
  .habit-today-panel { margin-bottom: var(--module-gap); }
  /* 只剩「新增」按钮的工具栏手机端整行隐藏（动作由 FAB 承担），
     否则按钮 display:none 后残留 20px 底距 + 16px 内容边距 = 36px 死空白 */
  .toolbar-min { display: none; }
}

/* ← 05-views.css:3496 */
@media (max-width: 768px) {
  #todoBody tr { position: relative; overflow: hidden; }
  #todoBody td:not(.swipe-acts) {
    transition: transform var(--d-enter) var(--ease-pop), opacity var(--d-push) ease;
  }
  /* 注意：动作层是 td，会被 #todoBody td{display:block}（表格转卡片）压掉，
     必须用更高特异性的 #todoBody td.swipe-acts 恢复横向 flex */
  #todoBody td.swipe-acts {
    position: absolute;
    top: 0; bottom: 0; left: 100%;
    width: 188px;
    display: flex; align-items: center; gap: var(--sp-3);
    padding-right: var(--sp-3); box-sizing: border-box; z-index: 2;
    transition: transform var(--d-enter) var(--ease-pop);
  }
  .swipe-act {
    flex-shrink: 0; width: 44px; height: 44px;
    border: none; border-radius: var(--radius-pill); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: width var(--d-toast) var(--ease-enter), filter var(--transition-fast), transform var(--d-micro) ease;
  }
  .swipe-act svg { width: 20px; height: 20px; flex-shrink: 0; }
  .swipe-act:active { filter: brightness(.88); transform: scale(.93); }
  .swipe-arch { background: var(--bg-count); color: var(--text-1); }
  .swipe-del { background: var(--status-bad); color: var(--on-primary); }
}

/* ← 05-views.css:3533  「---- 1. 触摸目标：视觉尺寸克制，热区用 ::after 隐形扩张 ----」 */
@media (max-width: 768px) {
  /* 头部「保存」是全页第一主操作：视觉 34px 胶囊，热区约 50×54 */
  .modal-head-act { position: relative; height: 34px; }
  .modal-head-act::after { content: ""; position: absolute; inset: -10px -10px; }
  /* 图标态（详情铅笔 / 编辑保存对勾·加号）：v1.3 起与白圆返回钮同款材质，
     只留图标形状区分动作，不再用黑底强调——头部一排钮统一为白圆钮语言 */
  .modal-head-act.is-icon {
    width: 36px; height: 36px; border-radius: var(--r-circle);
    background: var(--bg-card); color: var(--text-1);
    box-shadow: 0 4px 12px rgba(17, 17, 17, .08);
  }
  .modal-head-act.is-icon:active { background: var(--bg-card); transform: scale(.94); }

  .cat-swatch { position: relative; width: 30px; height: 30px; border-radius: var(--r-2); }
  .cat-swatch::after { content: ""; position: absolute; inset: -5px; } /* 40px 热区，相邻色块仅轻微重叠 */
  .cat-act { width: 40px; height: 40px; }
  .cat-act svg { width: 16px; height: 16px; }
  .sub-del { position: relative; width: 36px; height: 36px; }
  .sub-del::after { content: ""; position: absolute; inset: -4px; }
  .sub-del svg { width: 15px; height: 15px; }
  .memo-pin { width: 38px; height: 38px; }
  .wd-btn { height: 40px; font-size: calc(15px * var(--fs-scale)); }
  /* 主胶囊视觉收窄（1105 站主实拍「右边太重」）：40/15/16 → 34/13/12。
     拇指不跟着缩：::after 只上下右外扩 6px（左侧是「减一次」钮，压过去会抢点击），实测热区 55×45 */
  .habit-toggle-btn { position: relative; height: 34px; padding: 0 var(--sp-3); font-size: calc(13px * var(--fs-scale)); }
  .habit-toggle-btn::after { content: ""; position: absolute; inset: -6px -6px -6px 0; }
  .pf-seg { padding: 3px; }
  .pf-seg button { height: 38px; padding: 0 var(--sp-3); font-size: calc(13px * var(--fs-scale)); }
  .dc-reset-btn { width: 40px; height: 40px; }
  .login-pop-x { top: 4px; right: 4px; width: 40px; height: 40px; }
  /* 小眼睛：保持叠加在输入框内侧右缘（基线 absolute 不动），只放大触控目标；
     旧覆写 position: relative 会让按钮换行掉到输入框下方 */
  .pwd-toggle { width: 34px; height: 34px; right: 5px; }
  .pwd-field .form-input { padding-right: 46px; }
  .pwd-toggle::after { content: ""; position: absolute; inset: -5px; }
  .ep-avatar-cam { width: 34px; height: 34px; }
  .ep-avatar-cam svg { width: 16px; height: 16px; }
  .dp-day { height: 40px; }
  .rm-cal { width: 44px; height: 44px; }
  .rm-save-btn { width: 46px; height: 46px; }
  .dd-item { padding: var(--sp-3) var(--sp-3); font-size: calc(15px * var(--fs-scale)); }
  .cat-row, .trash-row { min-height: 48px; padding: var(--sp-2) 2px; }
  .habit-today-row { min-height: 52px; }
  .search-clear { width: 30px; height: 30px; }
}

/* ← 05-views.css:3577  「---- 2. 层级：用户管理角色菜单曾被底部 dock（z60）压住 ----」 */
@media (max-width: 768px) {
  .dd-menu { z-index: 70; max-height: 264px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
}

/* ← 05-views.css:3635  「---- 4. 视口与安全区：登录页 / 引导页贴 home 条、固定 px 高在横屏溢出 ----」 */
@media (max-width: 768px) {
  .login-wrap {
    min-height: 100dvh;
    padding:
      calc(var(--content-px) + var(--sat))
      calc(var(--content-px) + var(--sar))
      calc(var(--content-px) + var(--sab))
      calc(var(--content-px) + var(--sal));
  }
  .login-mask {
    padding:
      calc(var(--content-px) + var(--sat))
      calc(var(--content-px) + var(--sar))
      calc(var(--content-px) + var(--sab))
      calc(var(--content-px) + var(--sal));
  }
  /* 引导层（.ob-mask / .ob-card）手机端见文件末尾「首次访问引导 → 全屏轮播」块，单一权威源 */
  /* 内部滚动容器一律改用 dvh：固定 px 高在小屏会顶掉底部按钮 */
  .trash-rows { max-height: min(52dvh, 340px); }
  /* 例外（0927 真机压字）：回收站/已归档 v2 的滚动容器是 .bin-scroll（抽屉）或卡片本体（dd-modal），
     .trash-rows 只是普通列表。上面那条 dvh 上限会把它的盒子压得比可视内容矮，
     而卡片按 overflow:visible 照旧画到盒子外，紧跟其后的 .bin-tip 就顶在卡片上。 */
  .bin-scroll .trash-rows, .dd-modal .trash-rows { max-height: none; }
  .md-body { max-height: min(48dvh, 360px); }
  .rm-box-list { max-height: min(56dvh, 420px); }
  .op-list { max-height: 46dvh; }
  .modal-body, .rm-modal .modal-body { overscroll-behavior: contain; }
}

/* ← 05-views.css:3665  「---- 5. 字号地板与 4pt 网格回归 ----」 */
@media (max-width: 768px) {
  .md-body h4 { font-size: calc(15px * var(--fs-scale)); }
  .fg-card .fg-stack .sel-btn { font-size: var(--fs-input); }
  .toast { font-size: calc(15px * var(--fs-scale)); }
  .role-badge { height: 20px; padding: 0 var(--sp-2); font-size: var(--fs-12); }
  .role-badge .rb-mark { width: 13px; height: 13px; } /* 与本档 fs-12/h20 同比例放大（此块在后面，覆盖上一处 ≤768 的 fs-11 档） */
  .menu-cnt { font-size: var(--fs-12); }
  .tabbar .menu-cnt { font-size: var(--fs-11); } /* 数字气泡非正文，11px 为可读下限 */
  .todo-title { font-size: calc(16px * var(--fs-scale)); }
  .sub-title, .cat-row-name, .trash-title { font-size: calc(15px * var(--fs-scale)); }
  #todoBody tr { padding: var(--sp-3) var(--card-pad); column-gap: var(--sp-2); row-gap: var(--sp-1); }

  /* 开关行对齐参考图：左「标题 + 说明」纵向成组、右开关垂直居中靠右 */
  .fg-card .fg-switch .switch-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
  .fg-card .fg-switch .switch-row > span:first-child { min-width: 0; }
  /* 字形吃 03 的字段标题唯一档；这里只让图标片与标题在同一行垂直居中 */
  .fg-card .fg-switch .switch-label { display: inline-flex; align-items: center; }
  .fg-card .fg-switch .switch-desc { font-size: var(--fs-12); line-height: 1.5; margin-top: var(--sp-1); }
  /* 开关行的图标插在标题那一行里，下面那句说明必须跟着右移同样的距离——
     否则「标题缩进一格、说明顶到图标下沿」两行左缘不齐，整页看过去就是没对齐
     （与 .pfg-t-2 那套「图标在左、两行文字同一起线」的语言对齐） */
  .fg-card .fg-switch .switch-desc { padding-left: calc(var(--fg-i-w) + var(--fg-i-gap)); }
}

/* ← 05-views.css:3690 */
@media (max-width: 768px) {
  .modal-card.chain-in .modal-body > * { animation: chainPushIn var(--d-modal) var(--ease-enter) backwards; }
  .modal-card.chain-in .modal-body > *:nth-child(2) { animation-delay: .03s; }
  .modal-card.chain-in .modal-body > *:nth-child(3) { animation-delay: .06s; }
  .modal-card.chain-in .modal-body > *:nth-child(4) { animation-delay: .09s; }
  .modal-card.chain-in .modal-body > *:nth-child(5) { animation-delay: var(--d-micro); }
  .modal-card.chain-in .modal-body > *:nth-child(n + 6) { animation-delay: var(--d-fast); }
  @keyframes chainPushIn { from { opacity: 0; transform: translateY(-12px); } to { opacity: 1; transform: translateY(0); } }
  /* 详情页入场方向统一（2026-09-17，1010 沿用）：点卡片进详情一律自下而上浮入，
     不受「380ms 链窗口」或强制 chain 影响（复用 cascadeIn 的上浮轨迹，只改方向不改节奏）；
     自上而下推入保留给「编辑/新增表单」与「删除确认」这类链内推进（非 dd-modal 表单壳）——
     1010 起这条不再靠时序：Modal.open 见到 edit-form/diary-form 就恒定挂 chain-in。
     特异性须压过上方 .modal-card.chain-in 基础规则，故带 .dd-modal 且排在其后 */
  .modal-card.dd-modal.chain-in .modal-body > * { animation-name: cascadeIn; }
  /* 卡片不升起的那一屏（is-stacked＝表单页、以及从编辑返回的详情）：正文按「淡入＋位移」入场。
     1013 二轮起全站恢复淡入（1010b 防的闪帧已由 will-change 合成层与 ghost 解决）。
     普通链内页（设置链等）借 chainPushIn 同体（淡入＋自上而下 12px），fldSlideDown 关键帧删；
     返回的详情自下而上（与它自己的升起同向），从编辑返回时 swap-fade 的 ghost 承接旧编辑页。
     时长/缓动/backwards 与 nth-child 级联延时留给 chain-in 原规则，这里只换 animation-name。
     特异性：is-stacked (0,2,0) 靠排得晚压过 cascade/chain-in；dd-modal (0,3,0) 盖过 .dd-modal.chain-in。 */
  .modal-card.is-stacked .modal-body > * { animation-name: chainPushIn; }
  @keyframes fldSlideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
  .modal-card.is-stacked.dd-modal .modal-body > * { animation-name: fldSlideUp; }
  /* ---- 1013 表单换页过渡（录屏点名，撤 1010b 无淡入硬推）----
     编舞＝录屏原版：旧页快照（.modal-ghost＋.modal-head-ghost，JS 挂，inert 不接焦点点击）
     原地不动不淡出，新内容按 chainPushIn（淡入＋自上而下 12px＋逐行延时）盖上来，
     盖满后 JS 摘（420ms）。
     ① ghost 同步淡出＝旧褪新现漏灰底，真机闪（报「详情在弹出」）→ z-index:-1 沉底不透明
     （.modal-body 无背景、relative 不造堆叠上下文）。
     ② ghost 必须显式 animation:none——它也是 .modal-body > *，chain-in/cascade 的 shorthand
     会给它套 chainPushIn（从 0 淡入＝快照瞬消）。
     下面两条只覆写 animation-name（shorthand 会重置逐行延时）；ghost (0,4,0) 靠排后赢延时。 */
  .modal-card.fade-open .modal-body > * { animation-name: chainPushIn; }
  .modal-card.swap-fade .modal-body > *:not(.modal-ghost):not(.modal-scrim) { animation-name: chainPushIn; }
  .modal-card.swap-fade.dd-modal .modal-body > *:not(.modal-ghost):not(.modal-scrim) { animation-name: fldSlideUp; } /* 返回详情自下而上，方向与进入相反；(0,5,0) 压同权重两条 */
  /* 1016：详情入场不再逐行接力（掉帧＋落时间线停）；表单链不动 */
  .modal-card.swap-fade.dd-modal .modal-body > *:not(.modal-ghost):not(.modal-scrim) { animation-delay: 0s; }
  .modal-card.dd-modal.cascade .modal-body > * { animation-delay: 0s; }
  .modal-card.swap-fade .modal-body > .modal-ghost {
    position: absolute; inset: 0; z-index: -1; overflow: hidden; pointer-events: none;
    animation: none; /* 显式钉死：ghost 也是 .modal-body > *，chain-in/cascade 会给它套 chainPushIn＝快照瞬消 */
  }
  /* 底色纱：z:-1 排 ghost 后→盖快照之上、正文之下。**必须比正文先盖满**（--d-fast vs 240ms+逐行），
     同速＝没铺底，旧页字从半透明新卡面透出（1015 截图）。逐行两条已 :not(.modal-scrim)——
     dd 那条 (0,5,0) 会抢纱层动画名 */
  .modal-card.swap-fade .modal-body > .modal-scrim {
    position: absolute; inset: 0; z-index: -1; background: var(--bg-page);
    pointer-events: none; animation: scrimIn var(--d-fast) ease-out forwards;
  }
  @keyframes scrimIn { from { opacity: 0; } to { opacity: 1; } }
  .modal-card .modal-head-ghost { pointer-events: none; animation: swapFadeOut var(--d-modal) ease-out forwards; }
  .modal-card .modal-fadeout { pointer-events: none; animation: swapFadeOut var(--d-modal) ease-out forwards; } /* 悬浮删除钮克隆随页淡出 */
  .modal-body.is-swapping { position: relative; }
  @keyframes swapFadeOut { to { opacity: 0; } }
}

/* ← 05-views.css:3756 */
@media (max-width: 380px) {
  :root { --header-h: 52px; }
  .header-actions { gap: var(--sp-1); }
  /* FAB 与 dock 宽度的收缩必须带上 .tabbar 前缀：
     基础规则 .tabbar .tabbar-add / .tabbar.has-add .tabbar-dock 特异性更高，
     裸类名的 ≤380 规则历史上一直是死代码（实测 FAB 仍 60px） */
  .tabbar .tabbar-add { width: 48px; height: 48px; }
  .tabbar .tabbar-add svg { width: 18px; height: 18px; }
  /* 1010f：两个令牌一起换——成组居中的两侧留白与占位补偿（= --dock-r）全走 var() 现算，不重抄 */
  .tabbar { --dock-r: 58px; --dock-slim: 78px; }
  .tabbar .menu-item { font-size: var(--fs-12); }
  .pf-seg button { padding: 0 var(--sp-2); }
}

/* ← 05-views.css:3781 */
@media (max-width: 768px) {
  /* 外层 .panel 拍平：行本身已是卡片，再套一层白底描边壳会露出第二张卡
     （卡间缝隙与末行下方都会透出面板白底）——让行卡直接落在页面灰底上 */
  #view-todo .panel {
    background: transparent; border: none; border-radius: 0;
    box-shadow: none; overflow: visible;
  }
  #view-todo .table-wrap { overflow: visible; }
  #todoBody { display: flex; flex-direction: column; gap: var(--card-gap); padding-top: 2px; }
  #todoBody tr, #todoBody tr:last-child {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
      "check title  priority"
      "check due    due";
    align-items: start; column-gap: var(--sp-2); row-gap: var(--sp-1);
    padding: var(--sp-3) var(--card-pad);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-card-m); /* 手机端内容卡就该吃手机端那档（1009 定 12）：历史上这里借了桌面 --radius-card(8)，于是待办卡比概览卡方一截 */
    box-shadow: var(--shadow-card);
    transition: transform var(--d-fast) var(--ease-float), opacity var(--d-base) ease,
                border-color var(--transition-fast), box-shadow var(--transition-fast);
  }
  #todoBody td.code { display: none; } /* 创建日期：手机端让位 */
  #todoBody td.col-check, #todoBody td.col-priority { padding-top: 1px; }
  #todoBody .todo-title { font-size: calc(16px * var(--fs-scale)); line-height: 1.4; }
  #todoBody .todo-meta { margin-top: var(--sp-1); gap: var(--sp-2); }

  /* 截止时间：等宽数字，作为第二行的轻量锚点 */
  #todoBody td.col-due {
    width: auto; text-align: left; padding-top: 1px;
    font-family: var(--font-mono); font-size: var(--fs-micro);
    color: var(--text-4); letter-spacing: .01em;
  }

  /* 优先级语义色（形状已表意，颜色只做辅助强化，不单靠色觉） */
  #todoBody .prio-3 { color: var(--tag-high-fg); }
  #todoBody .prio-2 { color: var(--text-3); }
  #todoBody .prio-1 { color: var(--text-disabled); }

  /* 完成态：整卡降权重（:has 不支持时自然退回原样，不影响功能） */
  #todoBody tr:has(.todo-check input:checked) {
    background: var(--bg-soft); box-shadow: none; opacity: .72;
  }
  #todoBody tr:has(.todo-check input:checked) .prio { opacity: .5; }

  /* 按压反馈与其余卡片列表同幅度 */
  #todoBody tr:active { transform: scale(.985); }
}

/* ← 05-views.css:3842 */
@media (max-width: 768px) {
  .date-list { gap: var(--card-gap); }
  .memo-card, .date-card, .habit-card, .diary-card { padding: var(--sp-3) var(--card-pad); }

  /* 主标题层 */
  .memo-title, .habit-name, .diary-date b { font-size: calc(16px * var(--fs-scale)); }
  .memo-title { line-height: 1.4; }

  /* 次级层：辅助文字与数字 */
  .memo-content, .habit-meta, .diary-sec, .diary-date span { font-size: var(--fs-12); }
  .date-when { font-size: var(--fs-12); }        /* 与待办截止行同档 */
  .date-attrs { letter-spacing: 0; }
  .habit-meta b, .diary-date b, .memo-time { font-variant-numeric: tabular-nums; }

  /* 卡内首层间距与待办对齐（标题↔次级 = 6px，次级之间 8px） */
  /* 1014 站主点名「备忘卡标题与内容间距缩短一些」：卡内 gap 从 sp-2(8) 收到 sp-1(4)，
     并把 meta 行原本 -4 的上边距归零——否则负边距叠 4 gap 会让标题贴死 meta。
     结果：标题→meta→正文统一 4px 一档，正文整体上移，读起来更聚拢。 */
  .memo-card { gap: var(--sp-1); }
  .memo-meta { margin-top: 0; }
  .diary-head { margin-bottom: var(--sp-2); }

  /* 按压缩放统一 */
  .memo-card:active, .date-card:active, .habit-card:active, .diary-card:active { transform: scale(.985); }
}

/* ← 05-views.css:3908 */
@media (max-width: 768px) {
  .cf-sheet { padding-top: var(--sp-4); }
  .cf-sheet .wp-title { margin-bottom: var(--sp-4); }
  .cf-sheet:has(.cf-headline) .wp-title {
    font-size: calc(13px * var(--fs-scale)); font-weight: var(--fw-medium); color: var(--text-3);
    letter-spacing: .04em; margin-bottom: var(--sp-4);
  }
  .cf-sheet .cf-body { gap: var(--sp-3); }
  .cf-sheet .cf-mark { width: 56px; height: 56px; animation: cfMarkIn var(--d-enter) var(--ease-float) backwards var(--d-micro); }
  .cf-sheet .cf-mark svg { width: 26px; height: 26px; }
  .cf-sheet .cf-headline {
    font-size: calc(19px * var(--fs-scale)); font-weight: var(--fw-bold); line-height: 1.4;
    max-width: 16em; margin: 0 auto; text-wrap: balance;
  }
  .cf-sheet .cf-msg { font-size: calc(14px * var(--fs-scale)); line-height: 1.75; max-width: 21em; margin: 2px auto 0; text-wrap: balance; }
  .cf-sheet .wp-foot { margin-top: var(--sp-6); }
}

/* ← 05-views.css:3925 */
@media (max-width: 768px) {
  /* 遮罩：抽屉必须压暗背景（全屏弹窗的遮罩是透明的），并对齐底边 */
  .modal-mask:has(.cf-modal) {
    background: var(--mask);
    align-items: flex-end;
    padding: 0; overflow: hidden;
    animation: maskIn var(--d-modal) ease-out; /* 遮罩淡入统一 ease-out、时长走 --d-modal（消除 ease/.22 字面漂移） */
  }
  .cf-modal {
    height: auto; max-height: 86dvh;
    background: var(--bg-card);
    border-radius: var(--radius-sheet);
    box-shadow: var(--shadow-modal);
    animation: cfSheetUp var(--d-med) var(--ease-enter);
  }
  .cf-modal.closing { animation: cfSheetDown var(--d-fast) ease-in forwards; } /* 收在 Modal 170ms 清理预算内 */
  /* 抽屉只播「自下而上」一段，叠加内容级联 / 自上推入会打架 */
  .cf-modal.cascade .modal-body > *, .cf-modal.chain-in .modal-body > * { animation: none; }

  /* 头部退化为抽屉标题（不再是悬浮玻璃条） */
  .cf-modal .modal-head {
    position: static; justify-content: center;
    padding: var(--sp-4) var(--content-px) var(--sp-3);
    background: none; border-radius: 0;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .cf-modal .modal-head h2 {
    position: static; transform: none; max-width: 100%;
    font-size: calc(17px * var(--fs-scale)); font-weight: var(--fw-bold); color: var(--text-1);
    text-align: center; pointer-events: auto;
  }
  /* 与 .cf-sheet 同一处理：有对象名成行时标题降为眉标，全卡只留一个主标题 */
  .cf-modal:has(.cf-headline) .modal-head h2 {
    font-size: calc(13px * var(--fs-scale)); font-weight: var(--fw-medium); color: var(--text-3); letter-spacing: .04em;
  }
  .cf-modal .modal-back, .cf-modal .modal-x { display: none; } /* 关闭交给遮罩点击与底栏按钮，与选择器一致 */

  .cf-modal .modal-body { display: block; padding: 0 var(--content-px) var(--sp-4); }
  .cf-modal .cf-body { gap: var(--sp-3); }
  .cf-modal .cf-mark { width: 56px; height: 56px; animation: cfMarkIn var(--d-enter) var(--ease-float) backwards var(--d-micro); }
  .cf-modal .cf-mark svg { width: 26px; height: 26px; }
  .cf-modal .cf-headline {
    font-size: calc(19px * var(--fs-scale)); font-weight: var(--fw-bold); line-height: 1.4;
    max-width: 16em; margin: 0 auto; text-wrap: balance;
  }
  .cf-modal .cf-msg { font-size: calc(14px * var(--fs-scale)); line-height: 1.75; max-width: 21em; margin: 2px auto 0; text-wrap: balance; }

  /* 底栏：与 .wp-foot 同参数（取消 flex:1 灰 / 主操作 flex:1.5） */
  .cf-modal .modal-foot {
    background: transparent; border-top: none;
    padding: var(--sp-3) var(--content-px) calc(var(--sp-4) + var(--sab));
  }
  .cf-modal .modal-foot-group { display: flex; gap: var(--sp-3); width: 100%; }
  .cf-modal .modal-foot .btn {
    height: 50px; border: none; border-radius: var(--radius-pill);
    font-size: calc(16px * var(--fs-scale)); cursor: pointer;
    transition: transform var(--d-micro) ease, background var(--transition-fast), filter var(--transition-fast);
  }
  .cf-modal .modal-foot .btn-default { flex: 1; background: var(--bg-muted); color: var(--text-2); }
  .cf-modal .modal-foot .btn-default:active { background: var(--bg-count); }
  .cf-modal .modal-foot .btn-danger, .cf-modal .modal-foot .btn-primary {
    flex: 1.5; font-weight: var(--fw-medium);
  }
  .cf-modal .modal-foot .btn-danger { background: var(--status-bad); color: var(--on-primary); }
  .cf-modal .modal-foot .btn-danger:active { transform: scale(.985); filter: brightness(.9); }
  .cf-modal .modal-foot .btn-primary { background: var(--primary); color: var(--on-primary); }
  .cf-modal .modal-foot .btn-primary:active { transform: scale(.985); background: var(--primary-hover); }

  @keyframes cfSheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
  @keyframes cfSheetDown { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(100%); } }
  @keyframes cfMarkIn { from { opacity: 0; transform: scale(.82); } to { opacity: 1; transform: scale(1); } }
}

/* ← 05-views.css:4009 */
@media (max-width: 768px) {
  /* 概览页（无加号）的居中已由 ≤768 段的 margin-left:35px 负责
     （dock 宽 calc(100% - 70px)，空余 70px 的一半）。
     这里绝不能再叠 transform：本块历史上写过 translateX(31px)，
     与 margin 相加后 dock 右移 66px、贴死屏幕右边（实测 gapLeft 66 / gapRight 4）。 */
}

/* ← 05-views.css:4039 */
@media (max-width: 768px) {
  .modal-card .modal-head .modal-back {
    position: relative;
    width: 36px; height: 36px; margin-left: 0; flex-shrink: 0;
    border-radius: var(--r-circle); background: var(--bg-card); color: var(--text-1);
    box-shadow: 0 4px 12px rgba(17, 17, 17, .08);
  }
  .modal-card .modal-head .modal-back::before { content: ""; position: absolute; inset: -6px; }
  .modal-card .modal-head .modal-back:active { background: var(--bg-hover); transform: scale(.94); }
}

/* ← 05-views.css:4075  「---- 备忘编辑：分段控件、开关行、正文输入 ----」 */
@media (max-width: 768px) {
  /* 编辑/预览：白底描边贴白卡看不见 → 站内灰底胶囊（与 .wp-seg 同语言） */
  .fg-card .md-seg,
  .fg-card .fg-stack .md-seg {
    background: var(--bg-muted); border: none; border-radius: var(--radius-pill); padding: var(--sp-1);
  }
  .fg-card .md-seg button,
  .fg-card .fg-stack .md-seg button {
    border-left: none; height: 36px; padding: 0 var(--sp-4); border-radius: var(--radius-pill);
    font-size: calc(14px * var(--fs-scale)); color: var(--text-3); background: transparent;
  }
  .fg-card .md-seg button.active { background: var(--primary); color: var(--on-primary); font-weight: var(--fw-medium); }
  /* 开关行：复合选择器（同一元素两个类），拍平内衬灰底并补足 54px 表单行 */
  .fg-card .fg-switch.switch-row {
    background: transparent; border: none; border-radius: 0;
    padding: 0 var(--sp-4); min-height: 54px;
  }
  /* 开关行标题的字形不在这里另写——03 的 `.switch-row .switch-label` 已进字段标题唯一档 */
  /* 正文输入与预览：4px 直角 → 12px 内衬井，与卡片 16px 圆角成层级 */
  .fg-card textarea.form-input,
  .fg-card .md-body {
    border: none; border-radius: var(--r-3); background: var(--bg-soft);
    padding: var(--sp-3) var(--sp-3); font-size: calc(15px * var(--fs-scale)); line-height: 1.75;
  }
  .fg-card .md-body { min-height: 180px; max-height: none; }
  .fg-card .md-field-head { margin-bottom: var(--sp-3); }
}

/* ← 05-views.css:4112 */
@media (max-width: 768px) {
  .trash-row { padding: var(--sp-3) var(--sp-4); min-height: 66px; }
  .trash-row .trash-title { font-size: calc(16px * var(--fs-scale)); }
  /* 行内动作 = 40px 圆钮触控档，恢复↩ 与删除成对同尺寸：恢复透明底、删除淡红底，
     按压反馈只给缩放与填色（文字/描边不闪），文案在 title + .visually-hidden 里 */
  .trash-row .cat-act { width: 40px; height: 40px; border-radius: var(--radius-pill); }
  .trash-row .cat-act svg { width: 18px; height: 18px; }
  .trash-row .cat-act.cat-act-del { background: var(--tag-bad-bg); color: var(--tag-bad-fg); }
  .trash-row .cat-act.cat-act-del:active { transform: scale(.94); background: color-mix(in srgb, var(--status-bad) 18%, transparent); }
  .trash-row .cat-act:not(.cat-act-del):active { transform: scale(.94); background: var(--bg-hover); }
}

/* ← 05-views.css:4235  「手机端 ≤768：遵循手机端间距规范 v1.0（卡片内距/正文地板/触控目标）」 */
@media (max-width: 768px) {
  /* 同 §5 裁决：封面与 hero 同档（层 = r-5） */
  .diary-detail .dd-cover { border-radius: var(--r-5); padding: var(--sp-4) var(--card-pad) var(--sp-4); }
  .diary-detail .dd-day { font-size: 56px; letter-spacing: -.03em; }
  .diary-detail .dd-eyebrow { font-size: var(--fs-10); letter-spacing: .24em; margin-bottom: var(--sp-3); }
  .diary-detail .dd-my { font-size: calc(14px * var(--fs-scale)); gap: var(--sp-2); }
  .diary-detail .dd-week { font-size: calc(13px * var(--fs-scale)); padding-left: var(--sp-2); }
  .diary-detail .dd-entries { gap: var(--card-gap); margin-top: var(--card-gap); }
  .diary-detail .dd-entry {
    grid-template-columns: 34px 1fr; gap: var(--sp-3);
    border-radius: var(--radius-card-m); padding: var(--card-pad);
  }
  .diary-detail .dd-no { font-size: var(--fs-12); padding-top: 3px; }
  .diary-detail .dd-label { font-size: var(--fs-10); letter-spacing: .2em; margin-bottom: var(--sp-1); }
  .diary-detail .dd-text { font-size: calc(15px * var(--fs-scale)); line-height: 1.75; }
  .diary-detail .dd-colophon { margin-top: var(--sp-4); font-size: var(--fs-10); }
}

/* ← 05-views.css:4517  「---------- 手机端 ≤768（间距规范 v1.0：格内距吃 --card-gap、图标热区 ≥38） 」 */
@media (max-width: 768px) {
  .dg-grid { gap: var(--card-gap); }
  .dg-cell img, .dg-add { border-radius: var(--r-3); }
  .dg-del { opacity: 1; transform: none; }        /* 触屏没有 hover：摘除钮常驻 */
  .dd-film { margin-top: var(--module-gap); }
  .dd-film-head { padding-bottom: var(--sp-2); }
  .dg-film-track { gap: var(--card-gap); }
  .dg-film .dg-cell { flex-basis: 104px; width: 104px; }
  .iv-img { border-radius: var(--r-1); box-shadow: 0 18px 44px rgba(0, 0, 0, .55); }
  .iv-stage { padding: 2px var(--sp-2) calc(var(--sp-4) + var(--sab)); }
  .iv-title { display: none; }
}

/* ← 05-views.css:4531  「---------- 超窄屏 ≤380：只收格子与缩略尺寸，间距与热区不回退 ----------」 */
@media (max-width: 380px) {
  .dg-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .dg-film .dg-cell { flex-basis: 96px; width: 96px; }
  .dg-add { font-size: var(--fs-10); }
}

/* ← 05-views.css:4614 */
@media (max-width: 768px) {
  /* ---- ① 分组卡外壳 ---- */
  .wbf-modal .fg-card { border-radius: var(--radius-card-m); box-shadow: var(--shadow-card); margin-bottom: var(--card-gap); }

  /* ---- ② 行式：提示语与附加控件换到第二行，整行仍是左标签右值 ---- */
  .fg-card .fg-row { flex-wrap: wrap; }
  .fg-card .fg-row .field-hint,
  .fg-card .fg-row .field-extra { flex: 0 0 100%; }
  .fg-card .fg-row .field-hint { margin: -4px 0 var(--sp-3); font-size: var(--fs-micro); line-height: 1.5; }
  .fg-card .fg-row .field-extra { margin: 2px 0 var(--sp-3); }
  .fg-card .fg-row .field-extra:empty { display: none; margin: 0; }
  .fg-card .fg-row .wd-row { margin-top: 0; }
  .fg-card .fg-row .dom-row { margin-top: 0; }
  /* 开关行补足 54px 表单行（无描述项不再塌成 51px） */
  .fg-card .fg-switch .switch-row { min-height: 54px; }

  /* ---- ③ 井：卡内多行 / 复合控件的统一衬底 ----
     1004b 聚焦定稿（以「添加步骤」井试作选型）：静止预留 1px 透明描边；
     聚焦保持井底不翻白 + 1px 主描边 + 12px 柔光渐隐（--focus-glow）——
     细边不成粗、光晕渐隐不成「第二层边框」。 */
  .fg-card .fg-stack .form-input,
  .fg-card .fg-stack textarea.form-input,
  .fg-card .fg-stack .md-body,
  .fg-card .fg-stack .sel-btn,
  .fg-card .fg-stack .dp-display {
    background: var(--fld-fill); border: 1px solid transparent; border-radius: var(--fld-r);
    box-shadow: none; color: var(--fld-ink); font-size: calc(15px * var(--fs-scale));
  }
  /* 可输入的井一律 16px：iOS 聚焦小于 16px 的输入框会整页放大，且与行式输入框同字号
     （必须带上 textarea 限定：上面分组选择器里的 textarea 形式是 (0,3,1)，
       只写 .fg-stack .form-input 是 (0,3,0)，会被压回 15px —— 实测备忘/回顾正文井踩过） */
  .fg-card .fg-stack textarea.form-input,
  .fg-card .fg-stack .form-input { font-size: var(--fs-input); }
  .fg-card .fg-stack textarea.form-input { padding: var(--sp-3) var(--sp-3); min-height: 96px; line-height: 1.75; resize: none; }
  /* 输入井仍随内容长高（JS 写 inline height），但起始高度沿用上面 96px 的原版面比例 */
  .fg-card .fg-stack textarea.form-input.nl-ta { line-height: 1.75; }
  .fg-card .fg-stack .sel-btn,
  .fg-card .fg-stack .dp-display { height: 46px; line-height: 44px; padding: 0 var(--sp-3); text-align: left; }
  /* 箭头要落在 padding 之外：井里的下拉右内距 32px，否则长值会盖住小三角 */
  .fg-card .fg-stack .sel-btn { padding-right: var(--sp-8); }
  .fg-card .fg-stack .date-wrap .dp-display { padding-right: var(--sp-10); }
  .fg-card .fg-stack .select-wrap::after { right: 12px; }
  .fg-card .fg-stack .date-wrap .date-ico { right: 12px; }
  .fg-card .fg-stack .sel-btn.is-placeholder,
  .fg-card .fg-stack .dp-display.is-placeholder { color: var(--text-hint); }
  .fg-card .fg-stack .form-input:focus,
  .fg-card .fg-stack .sel-btn:focus-visible,
  .fg-card .fg-stack .dp-display:focus-visible {
    background: var(--fld-fill); border-color: var(--primary); box-shadow: var(--focus-glow);
  }
  /* 农历三列：井同色；左右对称内距让短值真居中，箭头收在 right:10px */
  .fg-card .fg-stack .field-row-3 .sel-btn { height: 46px; padding: 0 var(--sp-6); text-align: center; }
  .fg-card .fg-stack .field-row-3 .select-wrap::after { right: 10px; }

  /* ---- ④ 子任务：卡内无框行 + 发丝线；按住拖动排序，标题常可行内编辑 ---- */
  .fg-card .sub-editor { gap: 0; margin-bottom: 0; }
  .fg-card .sub-editor .sub-row {
    display: flex; align-items: center; gap: var(--sp-3); min-height: 52px;
    background: transparent; border: none; border-bottom: 1px solid var(--border);
    border-radius: 0; padding: var(--sp-2) 0; transition: transform var(--d-base) var(--ease-enter);
  }
  .fg-card .sub-editor .sub-row:last-child { border-bottom: none; }
  .fg-card .sub-editor .sub-name { font-size: calc(16px * var(--fs-scale)); }
  .fg-card .sub-editor .sub-handle { width: 24px; height: 44px; flex: 0 0 24px; }
  .fg-card .sub-editor .sub-del { flex: 0 0 38px; width: 38px; height: 38px; }
  /* 拖起的那一行：浮起来跟手（transform 由 JS 实时写，别在这里写死会被覆盖）。
     「跟手禁补间」归 05 的 .is-dragging-mode 公共条管，这里不再抄 transition:none，
     否则松手落位那段补间会被这条 (0,4,0) 压死 */
  .fg-card .sub-editor .sub-row.is-dragging {
    padding: var(--sp-2) var(--sp-3); margin: 0 -12px;
    background: var(--bg-card); border-bottom-color: transparent;
    border-radius: var(--r-3); box-shadow: var(--shadow-float);
  }
  .fg-card .sub-editor.is-dragging-mode { user-select: none; -webkit-user-select: none; }
  .fg-card .fg-stack .sub-add { margin-top: var(--sp-3); gap: var(--sp-2); }
  .fg-card .fg-stack .sub-add .form-input,
  .fg-card .fg-stack .sub-add .btn {
    height: 46px; background: var(--fld-fill); border: 1px solid transparent;
    border-radius: var(--fld-r); color: var(--fld-ink); font-size: calc(15px * var(--fs-scale));
  }
  .fg-card .fg-stack .sub-add .form-input { padding: 0 var(--sp-3); font-size: var(--fs-input); }
  .fg-card .fg-stack .sub-add .btn { flex: 0 0 46px; width: 46px; padding: 0; }
  .fg-card .fg-stack .sub-add .form-input:focus { background: var(--fld-fill); border-color: var(--primary); box-shadow: var(--focus-glow); }
  .fg-card .fg-stack .sub-add .btn:active { transform: scale(.96); background: var(--bg-count); }

  /* ---- ⑤ 带入：纯文字链接 → 幽灵胶囊（与心情 chip 同语言）。
     布局铁律：两颗胶囊永远一行左对齐、几何恒定——hint 独占整行（flex:0 0 100%），
     不参与按钮行的宽度分配；空态 display:none（同 fg-row .field-extra:empty 先例）。
     历史坑：hint 曾 flex:1 1 auto 挤同一行——空态吸 free space 把按钮顶在左边，
     带入后 hint 有了宽度，按钮被挤压/换行，再叠上概览时代残留的
     .ov-diary-cta{justify-content:center}（已删），整行跑中间＝「点一次变小还居中」。 ---- */
  .fg-card .diary-bring { margin-top: var(--sp-3); align-items: center; flex-wrap: wrap; gap: var(--sp-2); }
  .fg-card .diary-bring .btn-link {
    display: inline-flex; align-items: center; height: 38px; padding: 0 var(--sp-3);
    flex: 0 0 auto; white-space: nowrap;
    border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
    background: transparent; color: var(--text-2); font-size: calc(13px * var(--fs-scale)); text-decoration: none;
    transition: border-color var(--transition-fast), color var(--transition-fast), transform var(--d-micro) ease;
  }
  @media (hover: hover) { .fg-card .diary-bring .btn-link:hover { text-decoration: none; color: var(--text-2); border-color: var(--border-strong); } }
  .fg-card .diary-bring .btn-link:active { transform: scale(.97); border-color: var(--primary); color: var(--text-1); }
  .fg-card .diary-bring .field-hint { flex: 0 0 100%; min-width: 0; margin: 0; }
  .fg-card .diary-bring .field-hint:empty { display: none; }
}

/* ← 05-views.css:4724 */
@media (max-width: 768px) {
  .fg-card .fg-row .field-extra .dom-row { gap: var(--sp-2); font-size: calc(15px * var(--fs-scale)); color: var(--text-2); }
  .fg-card .fg-row .field-extra .dom-row .form-input {
    flex: 0 0 auto; width: 56px; min-width: 0; height: 40px; padding: 0 var(--sp-1);
    border: 1px solid transparent; border-radius: var(--fld-r); background: var(--fld-fill);
    box-shadow: none; text-align: center; font-size: calc(16px * var(--fs-scale)); color: var(--fld-ink);
  }
  .fg-card .fg-row .field-extra .dom-row .form-input:focus {
    background: var(--fld-fill); border-color: var(--primary); box-shadow: var(--focus-glow);
  }
  .fg-card .fg-row .field-extra .dom-row .wd-btn { min-width: 40px; height: 40px; padding: 0 var(--sp-3); }
  .fg-card .fg-row > .dp-display { flex: 1 1 auto; width: auto; min-width: 0; }
}

/* ← 05-views.css:4739  「描述收起态（手机端）：整行按行式呈现，右侧「＋ 填写描述」是无框幽灵入口」 */
@media (max-width: 768px) {
  .fg-card .desc-field.is-collapsed { min-height: 54px; }
  .fg-card .desc-field.is-collapsed .desc-toggle {
    border: none; background: transparent; border-radius: 0; padding: var(--sp-2) 0;
    margin-left: auto; font-size: calc(15px * var(--fs-scale)); color: var(--text-4);
  }
  .fg-card .desc-field.is-collapsed .desc-toggle:active { color: var(--text-1); }
}

/* ← 05-views.css:4755 */
@media (max-width: 768px) {
  /* 1) 下拉替身：把 .select-wrap 的小三角改画成右向 chevron。
     只改 border/尺寸/变换，right 仍由各行的 .fg-row/.fg-stack/field-row-3
     规则决定（那些规则特异性更高、且没被本条覆盖的 right 继续生效）。 */
  .fg-card .select-wrap::after {
    border: none; width: 7px; height: 7px;
    top: 50%; transform: translateY(-50%) rotate(45deg);
    border-top: 1.6px solid var(--text-4);
    border-right: 1.6px solid var(--text-4);
  }
  /* 2) 日期 / 独立「具体时间」替身：桌面靠日历小图标，手机端 fg-row 里图标已被隐藏，
     这两枚又没有 .select-wrap 载体 → 直接给按钮补一枚同规格 chevron，并留右内距。 */
  .fg-card .fg-row .date-wrap .dp-display,
  .fg-card .fg-row > .dp-display {
    position: relative; padding-right: var(--sp-6);
  }
  .fg-card .fg-row .date-wrap .dp-display::after,
  .fg-card .fg-row > .dp-display::after {
    content: ""; position: absolute; right: 8px; top: 50%;
    width: 7px; height: 7px; pointer-events: none;
    transform: translateY(-50%) rotate(45deg);
    border-top: 1.6px solid var(--text-4);
    border-right: 1.6px solid var(--text-4);
  }
  /* 3) 例外：重复规则里的「每月 X 号」迷你日历钮（.rm-cal）是 36px 图形按钮、
     点开日历浮层而非抽屉，绝不能挂箭头，也不能被撑出内距。选择器带满 4 个类
     （.rm-cal .date-wrap .dp-display）才压得住上面那条 .fg-row .date-wrap .dp-display。 */
  .fg-card .rm-cal .date-wrap .dp-display { position: absolute; padding-right: 0; }
  .fg-card .rm-cal .date-wrap .dp-display::after { content: none; }
}

/* ← 05-views.css:4815  「超窄屏（≤380）：只收缩字号与井内距，分组与行高不回退（间距规范 v1.0）」 */
@media (max-width: 380px) {
  .fg-card .fg-stack .sub-add .btn { flex: 0 0 44px; width: 44px; }
  .fg-card .diary-bring .btn-link { padding: 0 var(--sp-3); font-size: calc(12.5px * var(--fs-scale)); }
  .fg-card .fg-stack .field-row-3 .sel-btn { padding: 0 var(--sp-4); }
}

/* ← 05-views.css:4878 */
@media (max-width: 768px) {
  /* 卡片内本周格：铺满 7 等分，格间走 8pt 节奏 */
  .hb-heat { margin-top: var(--sp-3); }
  .hb-heat-head { margin-bottom: var(--sp-2); }
  .hb-heat-title, .hb-heat-sum { font-size: var(--fs-12); }
  .hm-week { gap: var(--sp-2); }
  .hm-col em { font-size: var(--fs-micro); }
  .hm-cell { font-size: calc(13px * var(--fs-scale)); }
  .hm-sq { max-width: none; }
  .hm-sq-lg { max-width: 44px; font-size: calc(15px * var(--fs-scale)); }

  /* 详情弹窗内的热力面板：整块按卡片内距收进「井」（圆角吃基线 --radius-lg，不再重写一遍） */
  .hm-panel { margin-top: var(--module-gap); padding: var(--card-pad); }
  .hm-nav { gap: var(--sp-1); margin-top: var(--sp-3); }
  .hm-nav .dp-nav { width: 38px; height: 38px; font-size: calc(18px * var(--fs-scale)); }
  .hm-range { font-size: calc(15px * var(--fs-scale)); }
  /* 返回徽章手机端不再单独放大：与当期徽章同尺寸档（基础 .hm-back 小胶囊），
     ≥38px 热区由 .hm-back::after 外扩统一提供（见基础规则），不再靠撑高 */
  .hm-summ { margin: var(--sp-2) 0; font-size: calc(13px * var(--fs-scale)); }
  .hm-wkrow { gap: var(--sp-2); margin-bottom: var(--sp-2); max-width: 420px; }
  .hm-wkrow span { font-size: var(--fs-micro); }
  .hm-grid7 { gap: var(--sp-2); max-width: 420px; }
  .hm-day { font-size: calc(13px * var(--fs-scale)); border-radius: var(--r-1); }

  /* 年视图：连续日期网格横向滚动，格子给到可点尺寸 */
  .hm-ygrid { grid-template-rows: repeat(7, 14px); grid-auto-columns: 14px; gap: var(--sp-1); }
  .hm-dot-c { width: 14px; height: 14px; }
  .hm-mlab { gap: var(--sp-1); }
  .hm-mlab i { width: 14px; font-size: var(--fs-10); }
  .hm-ylab { grid-template-rows: repeat(7, 14px); gap: var(--sp-1); padding-top: var(--sp-4); }
  .hm-ylab span { font-size: var(--fs-10); line-height: 14px; }

  /* 四档图例：与正文同地板，色块给到 14px */
  .hm-legend { margin-top: var(--sp-3); padding-top: var(--sp-3); gap: var(--sp-2) var(--sp-3); font-size: var(--fs-12); }
  .hm-legend .hm-cell { width: 14px; height: 14px; }

  /* 多次打卡控件：减一次为 icon 类目标 38，主钮沿用 40 高 */
  .hb-ctl { gap: var(--sp-2); }
  .hb-minus { width: 38px; height: 38px; }
  .hb-minus svg { width: 14px; height: 14px; }
  .hb-times { font-size: var(--fs-body); }
}

/* ← 05-views.css:4930  「超窄屏（≤380）：只收缩年视图格宽，间距与字号地板不回退」 */
@media (max-width: 380px) {
  .hm-ygrid { grid-template-rows: repeat(7, 13px); grid-auto-columns: 13px; }
  .hm-dot-c { width: 13px; height: 13px; }
  .hm-mlab i { width: 13px; }
}

/* ← 05-views.css:4946 */
@media (max-width: 768px) {
  .login-mask {
    align-items: flex-end;
    padding: 0;
  }
  .login-pop {
    width: 100%; max-width: none;
    border: none;
    border-radius: var(--radius-sheet);
    padding: var(--sp-4) var(--card-pad) calc(var(--sp-4) + var(--sab));
    box-shadow: var(--shadow-modal);
    animation: loginSheetUp var(--d-med) var(--ease-enter);
  }
  .login-pop.is-closing { animation: loginSheetDown var(--d-toast) ease-in forwards; }
  /* 把手下拉关闭：JS 已用内联 transform 滑出屏底，退场动画让位，避免瞬跳回原位再滑一遍 */
  .login-pop.is-dragged.is-closing { animation: none; }
  /* 抽屉语言：把手 + 标题出现，右上 × 收起（关闭交给下拉 / 返回 / Esc / 取消） */
  .login-pop .wp-grab { display: flex; }
  .login-pop .wp-title { display: block; margin-bottom: var(--sp-1); }
  .login-pop .login-pop-x { display: none; }
  /* 表单语言对齐编辑抽屉：灰底画布 + 白色分组卡 + 左标签右无边框输入行（.fg-card/.fg-row 全局手机规则直接复用） */
  .login-pop { background: var(--bg-page); }
  /* 品牌 lockup 手机退场（顶栏已有 K 标，不同屏双标），只留居中灰字副题行 */
  .login-pop .login-logo { display: contents; }
  .login-pop .login-logo > div { display: contents; }
  .login-pop .login-logo .logo-icon, .login-pop .login-logo .wm-line { display: none; }
  .login-pop .login-pop-sub { text-align: center; margin: 0 2px var(--sp-3); }
  .login-pop .login-fields { margin-bottom: 0; }
  /* 两行输入统一 34px 右缩进：提示/文字右缘对齐同一条线，小眼睛就坐在密码行预留出的宽度里
     （.pwd-field 的 flex 伸展已由「.fg-card .fg-row .pwd-field」统一负责，此处不再重复；
     选择器要多列一条 .pwd-field .form-input，才能压过通用的 46px 预留） */
  .login-pop .login-fields .fg-row .form-input,
  .login-pop .login-fields .fg-row .pwd-field .form-input {
    border: none; background: transparent; box-shadow: none;
    height: 54px; text-align: right; padding: 0 34px 0 0; font-size: calc(16px * var(--fs-scale));
  }
  .login-pop .login-fields .fg-row .form-input::placeholder { text-align: right; }
  /* 登录失败提示：卡片外红字说明行（灰画布上不带徽章底） */
  .login-pop .login-error { margin: var(--sp-2) var(--sp-1) 0; padding: 0; background: none; border: none; border-radius: 0; }
  /* 底栏两枚胶囊：登录=黑底主操作 flex1.5，继续本地=灰底 flex1（与 cf-sheet .wp-foot / .wp-btn 同参）。
     DOM 提交在前（桌面竖排黑钮在上），手机端 row-reverse 镜像成灰左黑右，与其它抽屉一致 */
  .login-pop .wp-foot { display: flex; flex-direction: row-reverse; gap: var(--sp-3); margin-top: var(--module-gap); }
  .login-pop .wp-foot .btn-block { flex: 1; width: auto; margin-top: 0; }
  .login-pop .wp-foot .btn { height: 50px; border: none; border-radius: var(--radius-pill); font-size: calc(16px * var(--fs-scale)); }
  .login-pop .wp-foot .btn-default { background: var(--bg-muted); color: var(--text-2); }
  .login-pop .wp-foot .btn-default:active { background: var(--bg-count); }
  .login-pop .wp-foot .btn-primary { flex: 1.5; font-weight: var(--fw-medium); }
  .login-pop .wp-foot .btn-primary:active { transform: scale(.985); }
}

/* ← 05-views.css:5000 */
@media (max-width: 768px) and (prefers-reduced-motion: reduce) {
  .login-mask, .login-pop, .login-mask.is-closing, .login-pop.is-closing,
  .login-pop.is-dragged.is-closing { animation: none; }
  /* 把手下拉关的滑出是 JS 内联 transition，减动效下清零直接到位 */
  .login-pop { transition: none !important; }
}

/* ← 05-views.css:5010 */
@media (max-width: 768px) {
  .cp-sheet { padding-top: var(--sp-4); }
  .cp-stage { margin-bottom: var(--sp-4); }
  .cp-sv { height: 172px; }
  .cp-hue { height: 30px; margin-top: var(--sp-3); }
  .cp-thumb { width: 24px; height: 24px; }
  .cp-hex-well { gap: var(--sp-2); height: 46px; }   /* 井高抬到手机档（与 --control-h-lg 同数） */
  .cp-hex-dot { width: 26px; height: 26px; }
  .cp-hex { font-size: calc(16px * var(--fs-scale)); } /* 小于 16px 会触发 iOS 聚焦整页放大 */
  .cp-sheet .wp-foot { margin-top: var(--module-gap); }
  .cat-swatch-custom.is-filled .habit-check { width: 16px; height: 16px; }
}

/* ← 05-views.css:5023  「排在末尾的手机端规则必须在同位置归零，否则会反压前部 prefers-reduced-motion 块」 */
@media (max-width: 768px) and (prefers-reduced-motion: reduce) {
  .cp-chip, .cp-ramp i, .cp-thumb { transition: none; }
}

/* ← 05-views.css:5036 */
@media (max-width: 768px) {
  .ob-mask { align-items: stretch; padding: 0; overflow-y: auto; }
  .ob-card {
    --nick-shift: 50px;
    width: 100%; max-width: none; border: none; border-radius: 0;
    min-height: 100dvh; max-height: none; overflow: visible;
    padding: calc(var(--sp-4) + var(--sat)) var(--content-px) calc(var(--sp-4) + var(--sab));
    animation: obFadeUp var(--d-med) var(--ease-enter);
  }
  .ob-card.is-out { animation: obCardOut var(--d-toast) ease-in forwards; }
  /* 手机端只留 logo：品牌名/副标/步数交给磨砂卡与圆点承担 */
  .ob-head { padding: 0; margin-bottom: var(--sp-3); }
  .ob-head-txt, .ob-tag, .ob-count { display: none; }
  .ob-back { width: 38px; height: 38px; } /* icon 类触控 ≥38；绝对定位，left:0 对齐 logo 落位 */
  .ob-slide { gap: var(--sp-6); }
  .ob-illu { max-width: 300px; }
  .ob-frost { padding: var(--sp-4); }
  .ob-slide-title { font-size: calc(28px * var(--fs-scale)); }
  .ob-slide-desc { font-size: calc(15px * var(--fs-scale)); }
  .ob-hero-slot { width: 104px; height: 104px; }
  .ob-hi-hello { font-size: calc(24px * var(--fs-scale)); }
  .ob-brand { font-size: calc(16px * var(--fs-scale)); }
  .ob-hi-title { font-size: calc(34px * var(--fs-scale)); }
  .ob-deck-stage, .ob-deck-card .ob-illu { max-width: 300px; }
  .ob-deck-name { font-size: calc(24px * var(--fs-scale)); }
  .mk { min-height: 150px; }
  .ob-dots { padding: 0 0 var(--sp-3); }
  .ob-title { font-size: calc(20px * var(--fs-scale)); }
  .ob-foot { margin-top: var(--module-gap); }
  .btn.ob-go { height: 50px; }
  .ob-form .ob-ninput { height: 54px; font-size: calc(18px * var(--fs-scale)); }
  @keyframes obFadeUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
}

/* ← 05-views.css:5079  「暗色：磨砂卡换深色玻璃，柔光与高光边同步」 */
@media (max-width: 768px) {
  [data-theme="dark"] .ob-frost { --ob-frost-bg: rgba(30, 32, 37, .72); --ob-frost-line: rgba(255, 255, 255, .08); }
  [data-theme="dark"] .ob-illu::before { --ob-glow: rgba(90, 100, 130, .22); }
  [data-theme="dark"] .ob-ghost { background: var(--bg-card); }
}

/* ← 05-views.css:5085  「超窄屏（≤380）：只收字号，画布内距不回退」 */
@media (max-width: 380px) {
  .ob-slide-title { font-size: calc(25px * var(--fs-scale)); }
  .ob-illu { max-width: 260px; }
  .ob-hi-title { font-size: calc(29px * var(--fs-scale)); }
  .ob-deck-name { font-size: calc(22px * var(--fs-scale)); }
  .ob-title { font-size: calc(19px * var(--fs-scale)); }
  .ob-desc { font-size: calc(15px * var(--fs-scale)); }
}

/* ← 05-views.css:5094  「排在末尾的手机端规则必须在同位置归零，否则会反压前部 prefers-reduced-motion 块」 */
@media (max-width: 768px) and (prefers-reduced-motion: reduce) {
  .ob-mask, .ob-card, .ob-card.is-out, .ob-mask.is-out,
  .ob-step, .ob-form.bad { animation: none; }
  .ob-track { transition: none; }
}

/* ← 05-views.css:5141 */
@media (max-width: 768px) {
  .memo-tagbar .chip-more svg, .todo-catbar .chip-more svg, .date-typebar .chip-more svg, .mem-groupbar .chip-more svg { width: 15px; height: 15px; }
  .memo-tagbar .chip-scroll, .todo-catbar .chip-scroll, .date-typebar .chip-scroll, .mem-groupbar .chip-scroll { scroll-padding: 0 var(--content-px); }
}

/* ← 05-views.css:5220  「—— 手机端体检补丁：触控地板 ≥38（热区扩展走 .modal-head-act ::after 先例，视觉尺」 */
@media (max-width: 768px) {
  .cat-swatch::after { content: ""; position: absolute; inset: -4px; } /* 30px 色块 → 38px 热区，正好吃掉 8px 间隙、互不重叠 */
  /* 色板「一行铺满」档（1006：习惯表单 8 预设 + 1 自定义共 9 枚，定宽 30px 在 390 宽下要
     334px、卡内只有 326px，差 8px 就掉行——「+」被孤零零甩到第二行，看着像控件坏了）。
     等分而不是缩间隙：间隙仍 8px，于是「一枚宽度 + 间隙」恰好等于上面那条热区口径，
     相邻热区首尾相接、永远互不重叠；max-width 30 让宽屏不放大（与定宽档同值），
     min-width 24 是保底——窄到 9 枚都塞不下（≤320 一类老机器）就老实换行，不把色块碾成渣。
     色值小字在这一档收起：色块本身填的就是那个颜色，取色抽屉里也答得出 hex，
     留着它反而要多占 ~58px 把第 9 枚挤下去。JS 只往它身上写字、从不读它，收的是纯视觉。
     align-items 必须一起收到 flex-start：flex 默认 stretch 会把整行拉到最高那枚的高度上，
     aspect-ratio 让位给它，色块就成了 29×30 的竖蛋（390 实测）。 */
  .cat-palette.is-fit { align-items: flex-start; }
  .cat-palette.is-fit > .cat-swatch { flex: 1 1 0; box-sizing: border-box; width: auto; min-width: 24px; max-width: 30px; height: auto; aspect-ratio: 1 / 1; }
  .cat-palette.is-fit > .cat-custom-hex { display: none; }
  .tag-pick-head #tpClear { position: relative; }
  .tag-pick-head #tpClear::after { content: ""; position: absolute; inset: -11px; }
  .pf-login-act { min-height: 38px; }
}

/* ← 05-views.css:5259 */
@media (max-width: 768px) {
  .modal-card.cascade .modal-body > .dd-foot-inline,
  .modal-card.chain-in .modal-body > .dd-foot-inline {
    animation: ddFootIn var(--d-modal) var(--ease-enter);
  }
}

/* ← 05-views.css:5743  「---- 4. 手机端（≤768）：间距规范 v1.0 ----」 */
@media (max-width: 768px) {
  .ov-day { padding: var(--sp-4) var(--card-pad) var(--sp-4); }
  .ov-read { margin-top: var(--module-gap); }
  .ov-chip { height: 38px; }                                                        /* 与 .tl-mini / .chip 同档，站内手机端触控地板 */

  #ovTimeline { margin-top: var(--module-gap); }
  .tl-group { margin: var(--module-gap) 0 var(--card-gap); }
  .tl-item { padding: var(--sp-3) var(--card-pad) var(--sp-3) var(--sp-3); margin-bottom: var(--card-gap); }
  .tl-item::before { left: 24.5px; top: -13px; bottom: -13px; }        /* 压在图标列中心 = 左内距12 + 图标半13 − 线半0.5（原 27 按「14」算错，实测线偏右 2.5px）；-13 桥满 12px 格隙 */
  .tl-title { font-size: calc(16px * var(--fs-scale)); }                                    /* 与列表卡片主标同档 */
  .tl-meta { font-size: var(--fs-12); }                                     /* 次级 12px 地板 */
  .tl-meta > .tl-desc { max-width: 8em; }                           /* 省略号落在摘要自身（选择器与基础规则同链，才压得住） */
  .tl-check { width: 38px; height: 38px; }
  .tl-check::after { content: ""; position: absolute; inset: -3px; } /* 热区 44 */
  .tl-check svg { width: 17px; height: 17px; }
  .tl-mini { height: 38px; padding: 0 var(--sp-4); font-size: calc(14px * var(--fs-scale)); }
  /* 打卡钮在手机端也与「去写」同档（38 / 14px）；习惯页全局那条 40/15 不受影响 */
  .tl-item .habit-toggle-btn { height: 38px; font-size: calc(14px * var(--fs-scale)); }
  .tl-tag { font-size: var(--fs-12); padding: var(--sp-1) var(--sp-2); }
  .tl-more { min-height: 44px; padding-left: 51px; margin-bottom: var(--card-gap); font-size: calc(13px * var(--fs-scale)); }
  /* 叠卡：间隙与轨道桥接跟着手机端那一档走（12 / 13），露边略厚一点才看得出现在是几张 */
  .tl-deck { --deck-gap: var(--card-gap); --deck-step: 8px; }
  /* 手机端原本另有一档 .tl-item:active{transform:scale(.985)}——比桌面更狠地把整卡缩掉，
     图标列与轨道跟着抖得最明显的就是这里。0929 撤除：手机端与桌面同一律，按下只沉表面。 */
}

/* ← 05-views.css:5790 */
@media (max-width: 768px) {
  .ab-text { font-size: var(--fs-body); padding: var(--card-pad); }
  .ab-logo { width: 48px; height: 48px; border-radius: var(--r-2); }
  .ab-logo svg { height: 36px; }
  .ab-name { gap: var(--sp-3); font-size: calc(20px * var(--fs-scale)); }
}

/* ← 05-views.css:5998  「---- 5. 超窄屏（≤380）：只收缩内距，间距与栅格不回退；高度与字号守住地板 ----」 */
@media (max-width: 380px) {
  .nt-time { min-width: 56px; padding: 0 var(--sp-1); }
  /* 这条本意是给「提前提醒」那类右靠的紧凑分段器收内距；不排掉通栏那一族的话，
     8px 会把通栏按钮撑到换行（通栏档自己只给 4px，且要留给六颗一排的「自检」） */
  .nt-seg .pf-seg:not(.pf-seg-fill) button { padding: 0 var(--sp-2); }
  .nt-sub { padding-left: calc(var(--card-pad) + var(--sp-6) + var(--sp-2)); }
}

/* ← 05-views.css:6023  「手机端筛选条撑满整行：「全部标签/分类/类型」入口钉右缘（桌面保持内容宽排布）」 */
@media (max-width: 768px) {
  .memo-tagbar, .todo-catbar, .date-typebar { flex: 1 1 100%; }
}

/* ← 05-views.css:6030 */
@media (max-width: 768px) {
  #todoSeg { flex: 1 1 100%; }
  #todoSeg button { flex: 1; justify-content: center; padding: 0 var(--sp-1); height: 38px; }
}

/* ← 05-views.css:6233  「---- 手机端（真机生效的那份）：导航行在上、粒度分段器撑满一行 ----」 */
@media (max-width: 768px) {
  .st-head { flex-direction: column; align-items: stretch; gap: var(--sp-2); }
  .st-nav { order: 1; }
  .st-tools { order: 2; width: 100%; }
  /* 统计页粒度钮通栏均分（1011b 站主以样板截图指路：「日、周、月、年」四格等分铺满一行，
     与账本 .lg-seg 同款——底子按钮自带 flex:1，这里只需把容器撑开、再把方钮宽度解掉）。
     口径修正记录：原话「平均分布整体右对齐」先按「整排贴右」落了半版，随即改回均分。 */
  #statsSeg { display: flex; width: 100%; }
  #statsSeg button { flex: 1; width: auto; }
  /* 粒度钮保持正方形（--control-h 在手机端是 44，天然够热区），不再拉平撑满一行 */
  .st-range { font-size: var(--fs-body); }
  .st-hero { padding: var(--sp-4) var(--sp-3) var(--sp-3); }
  :root { --fs-num-lg: 2.15rem; } /* hero 巨数手机端收一档（由令牌说话，不再逐元素写字面量） */
  .st-grid { gap: var(--sp-1); padding: var(--sp-2) var(--sp-3) 0; }
  .st-wkrow { gap: var(--sp-1); padding: var(--sp-2) var(--sp-3) 0; }
  .st-cell { min-height: 44px; }            /* 触控热区 ≥ 44，格内两行不挤压 */
  .st-c-l { font-size: var(--fs-11); }
  .st-c-n { font-size: var(--fs-caption); } /* 正文级最小 15px 底线之下仍可读 */
  .st-g-year { grid-template-columns: repeat(4, 1fr); }
  .st-legend { padding: var(--sp-2) var(--sp-3) 0; }
  .st-bars { padding: var(--sp-2) var(--sp-2) 0; min-height: 112px; }
  .ov-bar { max-width: 26px; }
  .st-ms { padding: var(--sp-3) var(--sp-3) var(--sp-3); }
  .st-flt { gap: var(--sp-1) var(--sp-3); padding: var(--sp-2) var(--sp-3) 0; }
}

/* ← 05-views.css:6437 */
@media (max-width: 768px) {
  .head-search { display: inline-flex; }
}

/* ← 05-views.css:6477 */
@media (max-width: 768px) {
  .header-left h1, .header-left p { white-space: nowrap; }
  .header-left { overflow: hidden; transition: opacity var(--d-base) ease var(--d-micro); }
  .header.hs-search .header-left { opacity: 0; transition: opacity var(--d-fast) ease; }
}

/* ← 05-views.css:6782 */
@media (max-width: 768px) {
  /* 灰底画布上，已绑定卡升为白卡（与分组卡同一材质） */

  /* 验证码行：嵌进 .fg-row 的「右控件」槽——label 左、输入占满、发送胶囊贴右 */
  .fg-card .fg-row .eb-code-row { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--sp-3); }
  .eb-send { min-height: 38px; padding: 0 var(--sp-3); font-size: var(--fs-caption); }
  .eb-hint { padding: 0 var(--sp-1); margin-top: var(--sp-3); }
}

/* ← 05-views.css:6890  「暗档聚焦不翻色（B 定稿：底色全程不动，随上方 [dark] 底色规则接管）」 */
@media (max-width: 768px) {
  .acct-modal .modal-body { background: var(--bg-page); }
  /* 真机回炉：.fg-card .field 在手机端 margin 被清零、分隔线又是关的 → 登录两行会挤在一起；
     这里按字段节奏补回 14px（0,3,0 压过 .fg-card .field 的 0,2,0） */
  .acct-modal .fg-card .field { margin-bottom: var(--sp-3); }
  /* 卡片上下内衬（1003 真机反馈"上下内边距太近"）：.fg-card 自身无纵向 padding，
     字段贴卡上下边；上 14 下 16（上方 label 行高自带 ~4px 留白，视觉对称）。
     末字段的下边距要归零，否则底衬=14+16=30 上下不对称 */
  .acct-modal .fg-card { padding-top: var(--sp-3); padding-bottom: var(--sp-4); }
  .acct-modal .fg-card .field:last-child { margin-bottom: 0; }
}

/* ← 05-views.css:6963 */
@media (max-width: 768px) {
  .acct-card { padding: var(--sp-3) var(--sp-4); }
  .otp { gap: var(--sp-2); }
  .otp-box { height: 50px; font-size: calc(20px * var(--fs-scale)); border-radius: var(--r-3); }
}

/* ← 05-views.css:7057 */
@media (max-width: 768px) {
  /* 手机端触控地板：--control-h 已是 44，凸块跟着长高，热区不缺 */
  .seg.seg-slide > button { padding: 0 var(--sp-1); font-size: var(--fs-caption); }
}

/* ← 05-views.css:7130 */
@media (max-width: 768px) {
  .modal-card.acct-wizard .modal-body,
  .modal-card.cloud-login .modal-body {
    display: flex; flex-direction: column;
    padding-top: calc(var(--sp-12) + var(--module-gap) + var(--safe-top));
    padding-bottom: var(--auth-btn-bottom);
  }
  /* 登录页顶部多留一档 module-gap：顶栏压着 body 上沿（body 从卡片 0 起算），
     单份间距时 logo 只离顶栏 15px——站主实拍「logo 快顶到顶部栏了」。 */
  .modal-card.cloud-login .modal-body { padding-top: calc(var(--sp-12) + var(--module-gap) * 2 + var(--safe-top)); }
  /* 向导：acct-body 撑满，卡贴标题下、按钮 margin-top:auto 推到底。
     标题起跑线 2.41 起不再抄登录页那条 --auth-title-top：那 120px 是**给登录页 logo
     预留的位置**，向导页顶部没有 logo，照抄就成了一条纯空白带（站主实拍「上面看着比较空」）。
     2.46 收到一半（60px）：全砍到一份 module-gap 又太贴标题栏，站主实拍「往上移太多了」。
     取半条登录标题线，既不再空一条带，也给大标题留出该有的一口气。 */
  .acct-wizard .acct-body { flex: 1 1 auto; display: flex; flex-direction: column; }
  .acct-wizard .acct-hero { margin-top: calc(var(--auth-title-top) / 2); margin-bottom: var(--sp-4); }
  .acct-wizard .acct-card { margin-bottom: var(--sp-4); }
  .acct-wizard .acct-foot { margin-top: auto; }
  /* 登录（1104 站主实拍「logo 快顶到栏、下面空一大片」→「logo 一起往下挪」→「整体往上一些」）：
     品牌区（logo+Klog）与大标题、输入卡、说明行并成一整组贴在一起，组与主钮之间只留弹性空隙；
     主钮仍钉在 --auth-btn-bottom 那条与改密 / 绑定 / 解绑共用的底线。
     空隙按 1:2 偏分（logo 顶上一条 auto、说明行与主钮之间两条 auto）——对半开时整组沉得太深，
     三条 auto 让整组回到上半屏，同时矮屏/键盘弹出时全部归零退回顶对齐，不裁不跳。
     logo 挪进 .pfg 是为了让这几条 auto 间距落在同一个撑满的容器里——div 拆在 body 层时，
     撑满的那层把余量吃干净，logo 的 auto 顶距恒为 0。 */
  .cloud-login .pfg { flex: 1 1 auto; display: flex; flex-direction: column; margin: 0; }
  .cloud-login .cl-hero { height: auto; margin: auto 0 0; }
  .cloud-login .cl-title { margin-top: var(--sp-3); }
  .cloud-login .pfg-card { margin-top: var(--sp-3); }
  .cloud-login .cl-alt { margin-top: var(--sp-3); margin-bottom: auto; }
  .cloud-login .acct-act-block { margin-top: auto; }
  /* 标题加大加粗：登录与向导同档，强化「同一套模板」的观感 */
  /* 1025：曾裸写 800、由 05 末尾治理层压回 700 —— 现直接落定令牌档（mono 只载到 700，800 合成发虚） */
  .acct-wizard .acct-hero h2 { font-size: calc(24px * var(--fs-scale)); font-weight: var(--fw-bold); }
  .cloud-login .cl-title { font-size: calc(24px * var(--fs-scale)); font-weight: var(--fw-bold); }
  /* 解绑卡「标签 + 值」：小标签在上，邮箱加大加粗，状态收右侧 */
  .acct-wizard .klabel { font-size: var(--fld-label-fs); font-weight: var(--fw-medium); color: var(--text-1); margin-bottom: var(--sp-2); text-align: left; }
  .acct-wizard .eb-cur { align-items: center; }
  .acct-wizard .eb-cur-mail { font-size: var(--fs-input); font-weight: var(--fw-bold); }
  .acct-wizard .eb-cur-sub { margin-left: auto; }
  /* 验证码六格与账号密码输入框同一副皮肤：软垫 / 无描边 / 同高 / 同圆角，聚焦走 --focus-glow */
  .acct-wizard .otp { gap: var(--sp-3); }
  .acct-wizard .otp-box { height: 48px; background: var(--bg-muted); border-color: transparent; border-radius: var(--r-3); }
  @media (hover: hover) { .acct-wizard .otp-box:hover { background: var(--bg-count); border-color: transparent; } }
  .acct-wizard .otp-box:focus { background: var(--bg-muted); border-color: var(--primary); box-shadow: var(--focus-glow); }
  /* 手机端「已填」不另描边（底色已是软垫，格子靠数字自证）；:not(:focus) 与桌面同口径，
     否则这条压过上一行、填过的那一格聚焦时看不出描边——站主实拍「选中态没有边框」即此 */
  .acct-wizard .otp-box:not(:placeholder-shown):not(:focus) { border-color: transparent; }
  /* 暗档不再另压底色：--bg-muted 在暗档本就是 #202228（卡片 #191B1F 亮一档），
     原先这两条把它换成 --bg-disabled（#1A1B1F，与卡片只差 1）+ 手机端无描边 = 六格全糊进卡片，
     站主实拍「深色模式看不见输入框在哪」即此；聚焦不翻色也由此基类自动成立。 */
}

/* ← 05-views.css:7175 */
@media (max-width: 768px) {
  .cloud-login .cl-mark {
    width: 72px; height: 72px; border-radius: var(--r-4);
    background: var(--text-1); color: var(--bg-card);
    display: inline-flex; align-items: center; justify-content: center;
  }
  .cloud-login .cl-mark svg { width: 28px; height: 48px; }
}

/* ← 05-views.css:7193 */
@media (max-width: 768px) {
  .wp-sheet.nl-sheet.nl-full { overflow: hidden; max-height: 100%; }
  .nl-full .mf-head { flex: none; position: relative; }
  /* 1006c 标题绝对居中：mf-head 里只有左返回钮时，flex:1 的标题会偏右——站主点名要正中 */
  .nl-full .mf-head .wp-title { position: absolute; left: 0; right: 0; text-align: center; pointer-events: none; }
  /* mgr-full 左右 padding 是 0（管理页各行自带内距）——一句话这几块自己补 16 */
  .nl-full .nl-sheet-well { flex: none; margin: 2px var(--sp-4) 0; }
  .nl-full textarea.nl-sheet-ta { transition: height var(--d-modal) var(--ease-float, ease), padding var(--d-modal) ease; }
  .nl-full .nl-hint { flex: none; margin-left: var(--sp-4); margin-right: var(--sp-4); }
  .nl-full .nl-hint[hidden] { display: none; }
  /* 列表=唯一滚动层：溢出自己滚，滚到顶再下拉交给把手手势关抽屉 */
  .nl-full .nl-pvbox {
    flex: 1 1 auto; min-height: 0; overflow-y: auto;
    overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
    margin-top: var(--sp-3); padding: 0 var(--sp-4) var(--sp-2);
  }
  .nl-full .nl-pvbox:empty { display: block; }
  /* 悬浮槽收进列尾：不再 sticky 浮在列表上（误触与遮挡一起治）；
     空态保留占位，胶囊进出不许顶动列表 */
  .nl-full .nl-ai-slot { flex: none; position: static; min-height: 56px; margin-top: var(--sp-2); align-items: center; padding: 0 var(--sp-4); }
  .nl-full .nl-ai-slot:empty { display: flex; }
  /* 收缩态：井剪成一行（inline 高度用 !important 压过 nlGrowSheet 写的行内值），提示让位 */
  .nl-full.is-tight textarea.nl-sheet-ta {
    height: 36px !important; min-height: 0; padding-top: var(--sp-1); padding-bottom: var(--sp-1); overflow: hidden;
  }
  .nl-full.is-tight .nl-hint { display: none; }
  .nl-full.is-tight .nl-pvbox { margin-top: var(--sp-2); }
  /* 胶囊定稿：单段「应用」加宽（悬浮编辑已撤，见 app.js nlActHtml） */
  .nl-sheet .nl-act-apply { min-width: 132px; }
  /* 快速记·直达区（1010b 站主定稿截图）：一句说明 + 落点提示条 + 通栏分隔线 + 五个模块直建行。
     排版语言借站内既有件：图标井 = .tl-ico（时间线同款）、分隔线 = 1px --border 通栏。
     让位三态与上面 .is-tight .nl-hint 同一套语言（该抽屉的「让位」历来是 display:none 硬收）：
     ① 有结果（pvbox 非空）/ ② 收井 / ③ 键盘起 —— 直达区收起，把屏让给结果与悬浮胶囊 */
  .nl-full .nlq-sub { flex: none; margin: 0 var(--sp-4) 2px; font-size: var(--fs-caption); color: var(--text-4); }
  .nl-full .nlq-chips { flex: none; display: flex; flex-wrap: wrap; gap: var(--sp-1); margin: var(--sp-3) var(--sp-4) 0; }
  .nl-full .nlq-chips span {
    font-size: var(--fs-11); color: var(--text-3);
    background: var(--bg-inset); border: 1px solid var(--border);
    border-radius: var(--r-pill); padding: 3px var(--sp-2);
  }
  .nl-full .nlq-quick { flex: none; padding: 0 var(--sp-4); }
  .nl-full .nlq-div { border-top: 1px solid var(--border); margin: var(--sp-3) 0 2px; }
  .nl-full .nlq-row {
    display: flex; align-items: center; gap: var(--sp-3);
    width: calc(100% + 12px);   /* button 不吃块级 width:auto 的「撑满」（shrink-to-fit）——不点破它，
                                   「表单 ›」永远缩在行中间右不齐（1010d 站主抓的） */
    margin: 0 -6px; padding: var(--sp-2) var(--sp-1);
    border: 0; border-radius: var(--r-2); background: none;
    text-align: left; font: inherit; color: var(--text-1); cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .nl-full .nlq-row:active { background: var(--bg-hover); }
  .nl-full .nlq-row .tl-ico svg { width: 16px; height: 16px; }
  .nl-full .nlq-t { flex: 1; min-width: 0; font-size: calc(15px * var(--fs-scale)); font-weight: var(--fw-medium); }
  .nl-full .nlq-k { flex: none; font-size: var(--fs-11); color: var(--text-4); }
  .nl-full .nlq-chev { flex: none; width: 14px; height: 14px; color: var(--text-disabled); }
  .nl-full:has(.nl-pvbox:not(:empty)) .nlq-quick,
  .nl-full.is-tight .nlq-quick,
  .nl-full.is-kbd .nlq-quick { display: none; }
}

/* ← 05-views.css:7524  「---- 手机端（≤768）：卡面内距收一档，日历字号抬到移动地板 ----」 */
@media (max-width: 768px) {
  .lg-hero, .lg-card { padding: var(--sp-4); }
  .lg-cal { padding: var(--sp-3) var(--sp-3) var(--sp-4); }
  .lg-row { padding: var(--sp-3) var(--sp-4); }
  .lg-day { font-size: calc(13px * var(--fs-scale)); }
  .lg-well { padding: var(--sp-3) var(--sp-4); }
}

/* ← 05-views.css:8336 */
@media (max-width: 768px) {
  .mem-seg > button { height: 38px; padding: 0 var(--sp-1); }
}

/* ← 05-views.css:8360 */
@media (max-width: 768px) {
  /* A —— 首行工具带（与 .ov-day 同：bg-card / border / radius-lg / shadow-card） */
  #view-todo > .toolbar,
  #view-memo > .toolbar,
  #view-ledger > .st-head {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: var(--sp-2) var(--sp-3);
    margin-bottom: var(--card-gap);
  }
  /* 账本首行手机是纵向堆叠（导航在上、粒度在下），内距收紧一档 */
  #view-ledger > .st-head { padding: var(--sp-2); }

  /* A' —— 拆卡套卡：账本时间标签 + 翻页钮自带的白卡底/边/影撤掉，交给外层带 */
  #view-ledger .st-range,
  #view-ledger .st-navbtn {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
  }
  #view-ledger .st-range { min-height: 34px; }
  @media (hover: hover) { #view-ledger .st-navbtn:hover { background: var(--bg-hover); } }
  #view-ledger .st-navbtn:active { transform: none; }

  /* C —— 分段器选中：白凸块 → 黑底反白（transform 滑动过渡归基础规则保留，跟手不变） */
  #view-todo .seg.seg-slide::before,
  #view-ledger .lg-seg.seg.seg-slide::before {
    background: var(--primary);
    box-shadow: none;
  }
  #view-todo .seg.seg-slide > button.active,
  #view-ledger .lg-seg.seg.seg-slide > button.active { color: var(--on-primary); }
  #view-todo .seg.seg-slide > button.active .seg-cnt,
  #view-ledger .lg-seg.seg.seg-slide > button.active .seg-cnt {
    color: var(--on-primary);
    opacity: .82;
  }
  /* C —— 备忘分类选中：描边 → 黑填充反白；未选在带内给极浅底拉开层次 */
  #view-memo .chip.active {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--on-primary);
  }
  #view-memo .chip.active .chip-cnt { color: var(--on-primary); opacity: .82; }
  #view-memo .chip:not(.active) { background: var(--bg-soft); }

  /* B —— 首页首行逐格揭示收编：四页统一只随整页入场 */
  #view-overview .ov-seg,
  #view-overview .ov-segs.is-enter .ov-seg { animation: none; }
}

/* ← 05-views.css:8420 */
@media (max-width: 768px) {
  #view-stats > .st-head {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: var(--sp-2);
    margin-bottom: var(--card-gap);
  }
  #view-stats .st-range,
  #view-stats .st-navbtn {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
  }
  #view-stats .st-range { min-height: 34px; }
  @media (hover: hover) { #view-stats .st-navbtn:hover { background: var(--bg-hover); } }
  #view-stats .st-navbtn:active { transform: none; }
}

/* ← 05-views.css:8443 */
@media (max-width: 768px) {
  #view-stats .seg.seg-slide::before { background: var(--primary); box-shadow: none; }
  #view-stats .seg.seg-slide > button.active { color: var(--on-primary); }
  #view-ledger > .st-head .st-tools,
  #view-stats > .st-head .st-tools { order: 1; }
  #view-ledger > .st-head .st-nav,
  #view-stats > .st-head .st-nav { order: 2; }
}

/* ← 05-views.css:8463 */
@media (max-width: 768px) {
  /* ① 待办滑块回到与账本同高（覆盖上面那条 height:38 特例） */
  #todoSeg button { height: var(--control-h); }

  /* ② 年格 / 周格改矮，不再 1/1 正方。订阅的续费日历并挂同一族格子，一起收
     （1/1 正方在 390 档量出来只有 40.9px，压在 44 触达线下） */
  #view-ledger .lg-cal-my .lg-mo,
  #view-ledger .lg-cal-g .lg-day,
  #view-subs .lg-cal-g .lg-day { aspect-ratio: auto; min-height: 44px; }
  /* 汇总卡 → 支出日历 / 分类 之间的段距收到 card-gap，与统计同一节奏。
     订阅四段的组标题并挂 .lg-grp（见 05 订阅段头 ④），同一条腿一起收。 */
  #view-ledger .lg-grp,
  #view-subs .lg-grp { margin-top: var(--card-gap); }
}

/* ← 05-views.css:8483 */
@media (max-width: 768px) {
  #todoSeg { display: flex; width: 100%; }
}

/* ← 05-views.css:8496 */
@media (max-width: 768px) {
  #view-todo > .toolbar { padding-left: var(--sp-2); padding-right: var(--sp-2); }
}

/* ← 05-views.css:8509 */
@media (max-width: 768px) {
  .u-role-pill.role-badge { height: 30px; }
  /* 详情页昵称行：昵称文本与右侧「当前/已停用」tag 是 inline 混排，基线让矮个 tag 偏下、
     且此前详情页的 tag 没吃到列表行 .user-row-name .tag 的左 margin（4-6px 紧贴）。
     改成 flex 居中，靠 column-gap 拉开与昵称的间距，只认 .us-d-id 这个详情页容器，不连坐别的 .dd-hero-name。 */
  .us-d-id .dd-hero-name { display: flex; align-items: center; flex-wrap: wrap; gap: 2px var(--sp-2); }
}

/* ← 05-views.css:8522 */
@media (max-width: 768px) {
  .role-badge { height: 24px; }
}

/* ← 05-views.css:8537 */
@media (max-width: 768px) {
  /* 庆祝岛：状态点换成四角星芒，currentColor 跟随岛上白字；点其它岛态不受影响。
     星芒 url 只写一份挂进 --il-spark，mask / -webkit-mask 各引用它，避免整串字面重复（膨胀闸）。 */
  .toast.toast-celebrate .toast-dot { display: none; }
  .toast.toast-celebrate .toast-lead::after {
    --il-spark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M12 1.6C13 7.6 16.4 11 22.4 12 16.4 13 13 16.4 12 22.4 11 16.4 7.6 13 1.6 12 7.6 11 11 7.6 12 1.6Z'/%3E%3C/svg%3E");
    content: ""; position: absolute; left: 0; top: 0; width: 16px; height: 16px;
    background: currentColor;
    -webkit-mask: var(--il-spark) center / contain no-repeat;
    mask: var(--il-spark) center / contain no-repeat;
  }
}

/* ← 05-views.css:8771 */
@media (max-width: 768px) {
  .fg-card .desc-field:not(.is-collapsed) {
    padding-top: var(--sp-3); padding-bottom: var(--sp-4);
  }
  .fg-card .desc-field:not(.is-collapsed) > .form-input {
    flex: 0 0 100%; min-width: 0; width: auto;
    background: var(--fld-fill); border: 1px solid var(--border); border-radius: var(--fld-r);
    box-shadow: none; color: var(--fld-ink); text-align: left; font-size: var(--fs-input);
  }
  .fg-card .desc-field:not(.is-collapsed) > textarea.form-input {
    height: auto; min-height: 96px; padding: var(--sp-3); line-height: 1.75; resize: none;
  }
  .fg-card .desc-field:not(.is-collapsed) > input.form-input {
    height: 46px; padding: 0 var(--sp-3); line-height: 44px;
  }
  .fg-card .desc-field:not(.is-collapsed) > .form-input::placeholder { text-align: left; color: var(--text-hint); }
  .fg-card .desc-field:not(.is-collapsed) > .form-input:focus { border-color: var(--primary); box-shadow: var(--focus-glow); }
  .fg-card .desc-field:not(.is-collapsed) > .field-hint { margin-top: var(--sp-2); }
}

/* ← 05-views.css:8893 */
@media (max-width: 768px) {
  /* ⓪ 1020 续（站主实拍点名「卡套卡」）：拆掉工具带那张白卡——分段条自己就是
        一只白卡轨道，直接浮在画布上，与下方 chips 平级；桌面不受影响（该壳只活
        在 ≤768 的统一块里，这里同媒体块靠文件末尾后来者胜撤干净）。
        顺手把上下留白回补给画布节奏：白卡没了，间距由 margin 说话。 */
  #view-todo > .toolbar {
    background: transparent; border-color: transparent; box-shadow: none;
    padding: 0; margin-bottom: var(--sp-2);
  }
  /* ① 统计即分段器：只认待办这一只 seg（账本/统计/心情不动）。
         1020 续：轨道改白（--bg-card）、凸块改灰（--border-strong 一档，1020 续2 站主点名
       真机看后再深一档：由 --seg-track #E9EAEE 抬到 --border-strong #D1D5DB；续8 站主点名「还是太灰」，
       再压一档——color-mix(--border-strong 70%, --text-4)；续9 站主令「试试主题色 + 白字」：Klog 主色即
       --primary #111（无彩色强调），故凸块回到黑底、选中文字反白 --on-primary——白槽黑把手。
       ⚠ 这等于把 1020 一路撤掉的「黑底反白」请回来，且与账本 lgSeg 同貌（账本一直黑底反白），
         待站主真机看过定夺：保留（todo 与账本同语言）或回退到续8 浅中灰把手（todo 独立于账本）。）、
        选中墨回正黑——白槽灰把手。反白语言的锚点在统一块 C（8167 起），它的规则把
        待办与账本并写在一起（并写提的是整条特异性，账本那份规则同样管着待办的节点），
        单写 #view-todo 特异性打不过。这里每条选择器多叠一枚 .seg-slide 类把特异性
        抬过 C 一档——只加类不改语义、不碰账本声明，账本保持黑底反白一字不动。
        白轨浮在 #F1F2F5 画布上只差一档亮度，补一圈发丝描边把它从背景里请出来
        （暗档 --border 自动换深色值，不用另开规则）。 */
  #view-todo .seg.seg-slide.seg-slide { background: var(--bg-card); box-shadow: inset 0 0 0 1px var(--border); }
  #view-todo .seg.seg-slide.seg-slide::before { background: var(--primary); box-shadow: none; }
  #view-todo .seg.seg-slide.seg-slide > button.active { color: var(--on-primary); }
  #view-todo .seg.seg-slide.seg-slide > button.active .seg-cnt { color: var(--on-primary); opacity: 1; }
  #view-todo .seg.seg-slide > button {
    flex-direction: column; justify-content: center; gap: 1px;
    height: auto; padding: var(--sp-2) var(--sp-1);
  }
  #view-todo .seg.seg-slide .seg-lab { font-size: var(--fs-micro); line-height: 1.1; }
  #view-todo .seg.seg-slide .seg-cnt {
    font-size: calc(22px * var(--fs-scale)); font-weight: var(--fw-semibold);
    line-height: 1.15; font-variant-numeric: tabular-nums;
  }
  /* 段序 DOM 是老口径（待办/已完成/全部），数字视觉主次交给统计语义，不重排 DOM——
     bindSeg/空态复位按 data-f 找档，重排只会牵动回归。 */

  /* ② 控件行（1025 站主定稿）：左＝固定入口钮，右＝分类快切 rail。
     老规矩「三枚 chip 溢出换行兜底」必须撤——rail 自己横滑吸收溢出，再换行等于顶栏
     长高一行、吃掉列表首屏。rail 的 flex:1 1 auto + min-width:0、边缘渐隐、隐藏滚动条
     全在上方 .todo-catbar .chip-scroll 那条桌面在用的老规则里，这里不重复声明。 */
  #todoCatBar { flex-wrap: nowrap; }
  #todoCatBar .chip { flex: 0 0 auto; }
  #todoCatBar .chip-filter { flex: 0 0 auto; }
  /* 图标尺寸必须自己声明：站内 svg 宽度历来是按 .chip-sort / .chip-more 逐个 scope 的
     （见 5113-5119），没有一条通用的 `.chip svg`——新类名不在名单里就是 0×0，
     实拍过一次「分类排序」只剩文字、图标凭空消失。 */
  #todoCatBar .chip-filter svg { width: 15px; height: 15px; flex: none; }
  /* 生效指示点：排序≠智能 或 只看逾期开着时才由 JS 画出来（不留 hidden 与 display 打擂）。
     5×5 等宽高 → --r-circle 合规；色走 --primary，不新增色值。 */
  #todoCatBar .chip-filter.is-on { border-color: var(--primary); }
  #todoCatBar .chip-pip { width: 5px; height: 5px; border-radius: var(--r-circle); background: var(--primary); flex: none; }

  /* ③ 1020 那枚「已逾期」胶囊退役：开关搬进合并抽屉的 .fs-over 行（样式在 5145 段，
     刻意不放本宽度块——抽屉门禁是 wbCoarse，宽屏平板也会用到它）。
     排序钮 .chip-sort 手机端同时退役（只剩桌面在用）。登记一条历史遗留：它的翻牌动画
     规则历来就写在本 ≤768 块里，而 .chip-sort 只在桌面渲染 → 桌面其实从没吃到过这个动画。
     本轮按「桌面维持现状」不搬不改，只把这条死规则删掉并留字在此，要修另开一轮。 */

  /* 分类回显翻入（1020 续3 立、1025 搬进 rail）：合并抽屉里选完分类后，rail 中选中的那枚
     胶囊标签竖向翻入一次；数字滚动不吃 CSS——app.js 复用 KPI 的 animateCounters
     （380ms 三次缓出，自带减动降级）。 */
  #todoCatBar .chip.flip .todo-cat-lab { animation: todoSortFlip var(--d-push) var(--ease-ios); }
}

/* ← 05-views.css:8974 */
@media (max-width: 768px) {
  /* 记忆 / 订阅 · 分段器翻成待办白槽黑把手（两只同族：自带轨道浮在画布上，非账本那种坐在带里） */
  #view-date .seg.seg-slide.mem-seg, #view-subs .sb-seg { background: var(--bg-card); box-shadow: inset 0 0 0 1px var(--border); }
  #view-date .seg.seg-slide.mem-seg::before, #view-subs .sb-seg::before { background: var(--primary); box-shadow: none; }
  #view-date .seg.seg-slide.mem-seg > button.active, #view-subs .sb-seg > button.active { color: var(--on-primary); }
  #view-date .seg.seg-slide.mem-seg > button.active .seg-cnt { color: var(--on-primary); opacity: .82; }
  /* 记忆分段器→下方内容：原 sp-2(8) 比待办「分段→分类」13 明显偏小、两页不一致。抬到 card-gap(12) 对齐待办节奏。 */
  #view-date .mem-seg { margin-bottom: var(--card-gap); }
  /* 事件档 分类条→列表卡 实测 24px：工具栏被撑到 50 高、分类行只 38 且顶对齐，chip 下已悬空 12px；
     再叠 toolbar 底距 12 = 24，违反「筛选行→列表 12」既定节奏。底距归 0，那 12px 悬空正好＝目标间距。
     只作用记忆事件工具条，不碰待办/备忘/账本的白卡工具带。 */
  #view-date #memToolbar { margin-bottom: 0; }
   /* 备忘 · 拆白卡工具带（无分段器时工具带透明，裸标签行浮在画布上）+ 标签单行横滑 */
   #view-memo > .toolbar {
     background: transparent; border-color: transparent; box-shadow: none;
     padding: 0; margin-bottom: var(--sp-2);
   }
   /* 1025 站主令：网格「全部标签」入口要钉在标签行右缘、固定不随溢出掉行——改回与待办
      #todoCatBar 同款的 nowrap：溢出交给 .chip-scroll 内部横滑吸收，.chip-more(flex:0 0 auto)
      压在滚动区右侧始终可见。上一版（1020续10）设 wrap 会让标签撑满后把网格钮折到第二行行首，
      既违反标签条族本意（5104：「换行会无限占高，收成一横行滑区」），也正是站主点名的错位。 */
   #view-memo .memo-tagbar { flex-wrap: nowrap; }
   #view-memo .memo-tagbar .chip { flex: 0 0 auto; }
}

/* ← 05-views.css:9003 */
@media (max-width: 768px) {
  #view-todo > .toolbar { row-gap: 0; margin-bottom: var(--card-gap); }
}

/* ← 05-views.css:9033 */
@media (max-width: 768px) {
  .memo-pin {
    position: relative;
    width: 28px; height: 24px; border-radius: var(--radius-btn);
  }
  .memo-pin::after {
    content: ""; position: absolute; inset: -8px -6px; /* 隐形扩热区，不撑布局盒（仿 .sub-del） */
  }
}

/* ← 05-views.css:9367 */
@media (max-width: 768px) {
  /* 外层白卡工具带（1017 块 A + 统计并入块）原样留着不动，本轮只拆里面那层框：
     分段器自己的轨道抹透明（base 的 --seg-track 灰槽 + 第一轮加的 inset 发丝边一起撤），
     一层框 = 那张带，黑把手直接坐在带面上；带内两行 8px gap 也交还给块 A。 */
  #view-ledger .seg.seg-slide.lg-seg,
  #view-stats .seg.seg-slide.st-seg {
    background: transparent;
    box-shadow: none;
  }
  /* 把手收成「贴着字」的做法被站主推翻（第四轮 00:1x 实拍纠正）：「不是把黑块的宽度
     降低，还原它的宽度——要缩的是它与这张白卡的内边距」。把手已还原成 base 的铺满
     整格（transform 走位那套原样回归，上一版「贴字 + left 算位」整体撤除）；
     收的是**内衬**：带 padding 从 --sp-2(8) 降到 --sp-1(4)，黑块与卡边 12 → 8。
     第五轮（09:1x，站主令「再收到 4px 看看是否太贴边」）：黑块与卡边只吃带内衬一层——
     分段器自己的 `--seg-pad` 归 0（那只 4px 内衬撤掉），黑块与卡边 8 → 4。
     连带：块高 36 → 44（铺满格高）、圆角 8 → --seg-r(12)，与卡片圆角同档；
     桌面 >768 不在作用域，桌面分段器仍是灰槽 + 4px 内衬。
     只动这两页的带与分段器，不碰块 A / 统计并入块 / 记忆 / 待办。 */
  #view-ledger > .st-head,
  #view-stats > .st-head {
    padding: var(--sp-1);
  }
  #view-ledger .seg.seg-slide.lg-seg,
  #view-stats .seg.seg-slide.st-seg {
    /* ★ 必须写 0px 不许写 0：base 宽度是 calc((100% - 2*pad)/n)，pad 为无单位 0 时
       「百分比 − 数字」型别不合 → IACBT 整条回落 auto → 凸块 shrink-to-fit 成 0px 宽
       （高度靠 top/bottom 拉伸所以看着还在）。实拍会看到黑块凭空消失。 */
    --seg-pad: 0px;
  }
  /* 第六轮（站主令「黑块圆角改成与待办、记忆一致；白卡圆角与内部组件圆角要视觉流畅」）：
     ① 把手圆角回同心档。round-5 把 --seg-pad 归 0 后 base 的 calc(--seg-r − --seg-pad)
        算成 12，与卡片(12)同心失效——DESIGN_SYSTEM §5 绑定①「内层 = 外层 − 内衬」：
        卡 12 − 内衬 4 = 8。待办 / 记忆把手正是 calc(12 − 4) = 8（那边 --seg-pad 还是 4px），
        这里直接按「卡 − 内衬」写，值与它们一致、语义也一致。
     ② 翻页钮（‹ ›）圆角同规则：--radius-btn(4) 是裸在画布上的档，进了 12 圆角的卡、
        内衬 4px，按同心也该 8。只动这两页首行卡里的（.st-head 后代），不连带
        记一笔表单里那对 data-cd-nav 的 .st-navbtn（app.js 32435，不在卡里、不吃这条）。 */
  #view-ledger .seg.seg-slide.lg-seg::before,
  #view-stats .seg.seg-slide.st-seg::before {
    border-radius: calc(var(--seg-r) - var(--sp-1));
  }
  #view-ledger > .st-head .st-navbtn,
  #view-stats > .st-head .st-navbtn {
    border-radius: calc(var(--r-3) - var(--sp-1));
  }
}

/* ============================================================
   触达 44 地板补齐（1104，详见 DESIGN_SYSTEM.md §9）
   ------------------------------------------------------------
   旧地板 38。手机端 <44 的可点控件优先用伪元素隐形扩张。
   例外保留：chip / tl-mini 38（滚动槽会裁纵向伪元素，站主确认保留 38）、
   .lg-mgr 24×17（嵌账本组标题，扩大会压下方分类行）、
   .lg-day 41×44（紧邻日历网格、无空档）、搜索展开态输入框 34（形变锁定）。
   ============================================================ */
@media (max-width: 768px) {
  /* 头栏：搜索(34) + 头像(32)，间距仅 4px——各向外侧扩，互不侵占 */
  .avatar-btn { position: relative; }
  .avatar-btn::after { content: ""; position: absolute; inset: -6px -8px -6px -4px; } /* 32→44 宽 */
  .head-search:not(.is-open)::after { content: ""; position: absolute; inset: -5px 0 -5px -10px; } /* 34→44 宽 */
  .head-search .hs-x::after { inset: -9px; } /* 26→44 有效（原 -8 只到 42） */

  /* chip / tl-mini 维持 38：横向滚动槽 overflow-y 会算成 auto、纵向伪元素被裁，
     无法隐形扩到 44；站主 1104 确认保留 38。 */

  /* 34 档小按钮：纵向扩到 44，横向各 2px（42 宽的单钮也能到 44） */
  .btn-sm { position: relative; }
  .btn-sm::after { content: ""; position: absolute; inset: -5px -2px; }

  /* 分段器：38 档上下补到 44；紧凑档（26 高）原 ::before 6→9；小档（30 高）原 4→7 */
  .pf-seg button { position: relative; }
  .pf-seg button::after { content: ""; position: absolute; inset: -3px 0; }
  .pf-seg.pf-seg-tight button::before { top: -9px; bottom: -9px; }
  .pf-seg.pf-seg-sm button::before { top: -7px; bottom: -7px; }

  /* 38 方形图标钮：外扩到 44 */
  .st-navbtn { position: relative; }
  .st-navbtn::after { content: ""; position: absolute; inset: -3px; }

  /* 统计页筛选小字钮（37×24）：上下 11 / 左右 4 → 45×46（行内横间距 12，不互抢） */
  .st-flt button { position: relative; }
  .st-flt button::after { content: ""; position: absolute; inset: -11px -4px; }

  /* 引导：返回 38→44；圆点 38→44（间距 4→0，视觉节奏不撞） */
  .ob-back::after { content: ""; position: absolute; inset: -3px; }
  .ob-dots { gap: 0; }
  .ob-dot { width: 44px; height: 44px; }

  /* 设置开关：视觉 38×22 不动，input 热区 44×44 */
  .pf-switch { width: 44px; height: 44px; }
  .pf-track { inset: 11px 3px; }
}
