/* ============================================================
   Klog 样式 4/5 · 外壳层
   装：登录页 / 无障碍基线 / 登录弹卡 / 首访引导 runOnboarding / 滚动条 / 响应式断点
   这些是「应用外壳」而非业务视图，改动会影响开屏与全局，慎改。
   ─── 1008 拆分头结束 ─── */
/* ===================== 登录页 ===================== *//* (1008 死规则清理) *//* (1008 死规则清理) */
.login-logo { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-6); }
.login-error {
  color: var(--status-bad); font-size: var(--fs-label);
  padding: var(--sp-2) var(--sp-3); margin-top: var(--sp-3);
  background: rgba(229, 62, 62, .06); border: 1px solid rgba(229, 62, 62, .2);
  border-radius: var(--radius-badge);
  animation: shake var(--d-push) ease-out;
}
.login-error:empty { display: none; }

/* 密码可见切换（登录页） */
.pwd-field { position: relative; }
.pwd-field .form-input { padding-right: var(--sp-8); }
.pwd-toggle {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 28px; height: 28px; border: none; border-radius: var(--radius-btn);
  background: transparent; color: var(--text-4); cursor: pointer;
  display: flex; align-items: center; justify-content: center; padding: 0;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.pwd-toggle svg { width: 15px; height: 15px; }
@media (hover: hover) { .pwd-toggle:hover { background: var(--bg-hover); color: var(--text-1); } }
.pwd-toggle.on { color: var(--text-1); }

/* 全宽按钮 */
.btn-block { width: 100%; }
.login-card .btn-block { margin-top: var(--sp-1); }

/* ===================== 无障碍基线 ===================== */
html { color-scheme: light; }
[data-theme="dark"] { color-scheme: dark; }
h1, h2, h3 { text-wrap: balance; }

/* ===================== 登录弹卡（本地模式的可选登录入口） ===================== */
.login-mask {
  position: fixed; inset: 0; z-index: 400;
  display: flex; align-items: center; justify-content: center;
  background: var(--mask); padding: var(--sp-4);
  animation: maskIn var(--d-modal) ease-out;
}
.login-pop {
  position: relative; width: 100%; max-width: 380px;
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: var(--sp-7) var(--sp-6);
  box-shadow: var(--shadow-float);
  /* 出场自下而上（桌面为浮起卡片；≤768 底部抽屉版见文件末尾同名块） */
  animation: loginRiseIn var(--d-med) var(--ease-enter);
}
/* 内容错峰：logo → 表单 → 按钮 依次微升，跟随母卡节奏 */
.login-pop .login-logo { animation: rowIn var(--d-enter) var(--ease-enter) backwards .06s; }
.login-pop .field { animation: rowIn var(--d-enter) var(--ease-enter) backwards var(--d-micro); }
.login-pop .btn-block { animation: rowIn var(--d-enter) var(--ease-enter) backwards var(--d-base); }
@keyframes loginRiseIn { from { opacity: 0; transform: translateY(32px); } to { opacity: 1; transform: none; } }
@keyframes loginPopDown { to { opacity: 0; transform: translateY(20px); } }
@keyframes maskOut { to { opacity: 0; } }
/* 退场自上而下：JS 加 .is-closing，动画结束后再置 hidden */
.login-mask.is-closing { animation: maskOut var(--d-toast) ease forwards; }
.login-pop.is-closing { animation: loginPopDown var(--d-toast) ease-in forwards; }
.login-pop .btn-block + .btn-block { margin-top: var(--sp-2); }
.login-pop-sub { font-size: var(--fs-label); color: var(--text-4); margin-top: 2px; }
.login-pop-x {
  position: absolute; right: 10px; top: 10px;
  width: 30px; height: 30px; border: none; border-radius: var(--r-circle);
  background: transparent; color: var(--text-4); font-size: calc(18px * var(--fs-scale)); line-height: 1;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: background var(--transition-fast), color var(--transition-fast);
}
@media (hover: hover) { .login-pop-x:hover { background: var(--bg-hover); color: var(--text-1); } }
/* 桌面保持居中卡片：抽屉件（把手/标题）只服务于 ≤768 底部抽屉版，手机端覆写显现 */
.login-pop .wp-grab, .login-pop .wp-title { display: none; }
/* 桌面 .wp-foot 竖排堆叠（手机端抽屉版会覆写为 flex 双胶囊） */
.login-pop .wp-foot { display: block; }

/* ===================== 首次访问引导（磨砂模块卡轮播 + 昵称设置） =====================
   第 1 步＝三屏横向轮播：磨砂「模块卡」拟物缩略（待办/热力/同步）+ 大标题 + 圆点分页，
   呼应 Notion 引导的质感，但走站内黑白灰语言；第 2 步＝昵称表单，与轮播同卡原地切换
   （不关卡重开、不键盘跳动）。桌面居中卡（max-width 420），手机端（≤768）铺满整屏，
   参数见文件末尾同名块。昵称页仍复用 .dd-hero/.dd-group/.dd-row/.form-input 语言。
   ============================================================ */
/* 首访引导预藏：命中「会走引导」时首帧前藏掉 app 壳，杜绝概览闪一两帧；startApp 里解除 */
html.ob-boot .app { visibility: hidden; }
/* 1009 背景纵深：任意覆盖层（Modal 详情抽屉 / .wp-sheet 各类抽屉面板）打开时，壳层 .app 缩后退一层，
   做 iOS 式景深。1009c 全站统一一档（scale .94 / .55s ease-ios）——之前详情抽屉用 layer-sheet 走 .94/.55s、
   别的抽屉走 .965/.22s，关闭时背景缩放不一致；现合并到 has-layer 一处，卡片升起 .6s 与背景 .55s 同起同落。 */
.app { transition: transform var(--d-slow) var(--ease-ios); transform-origin: 50% 38%; }
.app.has-layer { transform: scale(.94); }
@media (prefers-reduced-motion: reduce) { .app.has-layer { transform: none; } }
.ob-mask {
  position: fixed; inset: 0; z-index: 500;
  display: flex; align-items: center; justify-content: center;
  background: var(--mask);
  /* 引导期 .app 已预藏（空白底），backdrop-filter 只会白白吃合成层 → 去掉，改纯色遮罩 */
  padding: var(--sp-4);
  animation: obMaskIn var(--d-modal) ease-out;
}
.ob-mask[hidden] { display: none; } /* 探针/兜底会直接置 hidden，压过上面的 display:flex */
.ob-mask.is-out { animation: obMaskOut var(--d-toast) ease forwards; pointer-events: none; }
@keyframes obMaskIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes obMaskOut { to { opacity: 0; } }
.ob-card {
  --nick-shift: 44px;
  position: relative; width: 100%; max-width: 420px;
  max-height: calc(100vh - 32px); overflow-y: auto;
  display: flex; flex-direction: column;
  background: var(--bg-page); border: 1px solid var(--border);
  border-radius: var(--r-5); padding: var(--sp-4);
  box-shadow: var(--shadow-modal); text-align: left;
  animation: obCardIn var(--d-enter) var(--ease-enter);
  overscroll-behavior: contain;
}
.ob-card.is-out { animation: obCardOut var(--d-toast) ease-in forwards; }
@keyframes obCardIn { from { opacity: 0; transform: translateY(18px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes obCardOut { to { opacity: 0; transform: translateY(14px); } }

/* ---- 页眉：返回钮绝对定位 + lockup（logo 锚点 + 品牌）整体右移让位；等宽步数 ---- */
.ob-head { position: relative; display: flex; align-items: center; gap: var(--sp-3); padding: 2px 2px 0; margin-bottom: var(--sp-3); }
.ob-lockup { display: flex; align-items: center; gap: var(--sp-3); transition: transform var(--d-morph) var(--ease-move); }
.ob-card.is-nick .ob-lockup { transform: translateX(var(--nick-shift)); }
.ob-mark { flex-shrink: 0; }
.ob-mark.ob-mark-fb {
  width: 32px; height: 32px; border-radius: var(--r-1); background: var(--primary); color: var(--on-primary);
  font-family: var(--font-mono); font-size: calc(17px * var(--fs-scale)); font-weight: var(--fw-bold);
  display: flex; align-items: center; justify-content: center;
}
.ob-head-txt { flex: 1; min-width: 0; }
.ob-tag {
  display: block; margin-top: 2px; font-family: var(--font-mono);
  font-size: var(--fs-12); line-height: 1.4; color: var(--text-4); letter-spacing: .2px;
  transition: opacity var(--d-toast) ease;
}
/* 昵称页：副标淡出，避免与右移的 lockup 重叠（表单页已有自己的说明） */
.ob-card.is-nick .ob-tag { opacity: 0; }
.ob-count {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-12); letter-spacing: .5px; color: var(--text-disabled); flex-shrink: 0;
}
.ob-count b { font-weight: var(--fw-medium); color: var(--text-disabled); transition: color var(--transition-fast); }
.ob-count b.on { color: var(--text-1); }
.ob-count i { font-style: normal; margin: 0 2px; }
.ob-back {
  position: absolute; left: 0; top: 50%; z-index: 7;
  transform: translateY(-50%) translateX(-6px);
  width: 32px; height: 32px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: var(--r-circle); background: transparent; color: var(--text-3); cursor: pointer; padding: 0;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--d-push) ease, transform var(--d-push) ease, visibility var(--d-push), background var(--transition-fast), color var(--transition-fast);
}
.ob-card.is-nick .ob-back { opacity: 1; visibility: visible; pointer-events: auto; transform: translateY(-50%) translateX(0); }
.ob-back svg { width: 18px; height: 18px; }
@media (hover: hover) { .ob-back:hover { background: var(--bg-hover); color: var(--text-1); } }

/* ---- 步骤容器：昵称步沿用 dd-hero 语言；欢迎步交给轮播 ---- */
.ob-step { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.ob-step[hidden] { display: none; }
.ob-step-nick { justify-content: center; }
.ob-title { font-size: calc(20px * var(--fs-scale)); font-weight: var(--fw-bold); color: var(--text-1); line-height: 1.35; margin: 0 0 var(--sp-2); }
.ob-desc { font-size: calc(15px * var(--fs-scale)); color: var(--text-3); line-height: 1.7; margin: 0; }
.ob-desc b { color: var(--text-1); font-weight: var(--fw-semibold); }

/* ---- 轮播：横向轨道 + 磨砂模块卡 + 大标题 + 圆点 ---- */
/* 轨道/视口不锁死高度：内容定高，手机端靠 carousel flex:1 撑满并垂直居中，避免自适应卡里塌陷为 0 */
.ob-carousel { display: flex; flex-direction: column; flex: 1 1 auto; justify-content: center; }
.ob-viewport {
  position: relative; overflow: hidden;
  touch-action: pan-y; user-select: none; -webkit-user-select: none;
}
.ob-track {
  display: flex; width: 300%;
  transform: translate3d(0, 0, 0);
  transition: transform var(--d-enter) var(--ease-enter);
  will-change: transform;
}
.ob-slide {
  flex: 0 0 33.3333%; width: 33.3333%; box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-6); padding: var(--sp-2) var(--sp-1);
}
/* 磨砂卡：半透白 + 背景模糊 + 细高光边；背后一层柔光让「磨砂」看得见 */
.ob-illu { position: relative; width: 100%; max-width: 268px; display: flex; align-items: center; justify-content: center; }
.ob-illu::before {
  content: ''; position: absolute; inset: -16% -10%; z-index: 0;
  background: radial-gradient(58% 56% at 50% 42%, var(--ob-glow, rgba(120, 130, 155, .18)), transparent 72%);
  pointer-events: none; /* 径向渐变已够柔，去掉 filter:blur 省一层合成 */
}
.ob-frost, .ob-ghost {
  width: 100%; border-radius: var(--r-5); padding: var(--sp-4);
  border: 1px solid var(--ob-frost-line, rgba(255, 255, 255, .6));
}
.ob-frost {
  position: relative; z-index: 1;
  /* 去掉 backdrop-filter（移动端逐帧合成最贵，滑动掉帧主因）；背后只有柔光无细节，
     用半透白 + 顶部内高光 + 外投影即可维持"磨砂浮起"观感，性能大幅提升 */
  background: var(--ob-frost-bg, linear-gradient(180deg, rgba(255, 255, 255, .9), rgba(255, 255, 255, .78)));
  box-shadow: 0 14px 28px -16px rgba(20, 22, 30, .42), inset 0 1px 0 rgba(255, 255, 255, .7);
}
.ob-ghost {
  position: absolute; z-index: 0; left: 50%; top: 50%; width: 100%;
  transform: translate(-50%, -50%) scale(.9) rotate(-4deg);
  opacity: .12; pointer-events: none; border: none; background: var(--bg-card);
}
/* ghost 只是背景景深，别让它跟着前景卡重复跑演示动效（白白多一层合成开销） */
.ob-ghost * { animation: none !important; }
/* 骨架模拟模块内容：灰白线条 / 勾选 / 热力格 / 云 */
.mk { display: flex; flex-direction: column; gap: var(--sp-3); }
.mk-hd { font-size: var(--fs-12); font-weight: var(--fw-medium); color: var(--text-3); letter-spacing: .3px; }
.mk-chk { width: 18px; height: 18px; border-radius: var(--r-1); border: 1.5px solid var(--border-strong); flex-shrink: 0; }
.mk-chk.is-on { background: var(--text-1); border-color: var(--text-1); position: relative; }
.mk-chk.is-on::after { content: ''; position: absolute; left: 5px; top: 2px; width: 4px; height: 8px; border: solid var(--bg-card); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.ln { height: 9px; border-radius: var(--r-1); background: var(--bg-muted); display: inline-block; }
.ln.s { height: 7px; opacity: .7; }
.mk-cloud { display: flex; justify-content: center; padding: var(--sp-1) 0; }
.mk-cloud svg { width: 34px; height: 34px; color: var(--text-2); }
.mk-dev .dot { width: 9px; height: 9px; border-radius: var(--r-circle); background: var(--text-1); flex-shrink: 0; }
.mk-dev .ln { flex: 0 0 auto; }
/* 文案：大标题 + 小标签 + 说明 */
.ob-copy { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--sp-2); padding: 0 var(--sp-2); }
.ob-slide-tag { font-family: var(--font-mono); font-size: var(--fs-12); letter-spacing: .6px; color: var(--text-4); text-transform: uppercase; }/* (1008 死规则清理) */
.ob-slide-desc { font-size: calc(15px * var(--fs-scale)); color: var(--text-3); line-height: 1.6; margin: 0; }
/* 圆点分页：38×38 真实热区（盒子即触控区），当前枚拉成长胶囊；钉在按钮正上方 */
.ob-dots { display: flex; align-items: center; justify-content: center; gap: var(--sp-1); padding: 0 0 var(--sp-3); flex-shrink: 0; }
.ob-dot {
  width: 38px; height: 38px; padding: 0; border: none; background: transparent;
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
}
.ob-dot::before {
  content: ''; width: 7px; height: 7px; border-radius: var(--r-pill); background: var(--border-strong);
  transition: width var(--d-toast) var(--ease-enter), background var(--d-toast);
}
.ob-dot.on::before { width: 22px; background: var(--text-1); }

/* ---- 第 1 页 · 欢迎：形变 logo 落在中心大位 + 脉冲光晕 + 大标题 ---- */
.ob-slide-hi { gap: var(--sp-6); }
/* 中心大 logo 的占位锚点（logo 本体是卡内绝对定位的 .ob-morph，覆盖在此处） */
.ob-hero-slot { position: relative; width: 96px; height: 96px; flex-shrink: 0; }
/* 形变 logo：基准=中心大位（left/top/width/height 由 JS 写入），切页时 translate+scale 缩到左上角 */
.ob-morph {
  position: absolute; z-index: 6; pointer-events: none;
  width: 96px; height: 96px; border-radius: var(--r-6);
  transform-origin: top left;
  /* 基准给显式合成态变换（非 none），首帧就走 GPU 合成，避免 none→变换 主线程插值的首次掉帧 */
  transform: translate3d(0, 0, 0) scale(1);
  transition: transform var(--d-morph) var(--ease-move), opacity var(--d-push) ease;
  will-change: transform;
}
.ob-morph svg { height: 62%; width: auto; }
.ob-morph.is-corner { transform: translate3d(var(--mx, 0), var(--my, 0), 0) scale(var(--ms, 1)); }
/* 昵称页：logo 随 lockup 一起右移让位（与 .ob-lockup 同位移量，保持与锚点对齐） */
.ob-card.is-nick .ob-morph.is-corner { transform: translate3d(calc(var(--mx, 0px) + var(--nick-shift, 44px)), var(--my, 0), 0) scale(var(--ms, 1)); }
/* 形变 logo 落位后右侧浮现的「可序 Klog」文字：快速模糊出现，回 P1 即隐 */
.ob-brand {
  font-size: calc(15px * var(--fs-scale)); font-weight: var(--fw-medium); color: var(--text-1); white-space: nowrap; flex-shrink: 0;
  opacity: 0; filter: blur(6px); transform: translateX(-6px); pointer-events: none;
  transition: opacity var(--d-fast) ease, filter var(--d-fast) ease, transform var(--d-fast) ease;
}
.ob-brand b { font-weight: var(--fw-bold); }
.ob-brand.is-on { opacity: 1; filter: blur(0); transform: none;
  transition: opacity var(--d-enter) ease var(--d-base), filter var(--d-enter) ease var(--d-base), transform var(--d-enter) ease var(--d-base); }
/* 用 .ob-brand 取代旧词标位，避免桌面「Klog」与「可序 Klog」重复 */
.ob-head .wm { display: none; }
/* 左上角 logo 落位锚点（页眉里占住 32px，词标不位移） */
.ob-logo-slot { width: 32px; height: 32px; flex-shrink: 0; }
/* 分区暂停：P1 暂停卡组演示动效、切页过渡期间也冻结，离屏/关键帧不再逐帧合成，省电省帧 */
.ob-card.is-hero .ob-deck * { animation-play-state: paused; }
/* 切页过渡期间冻结卡组动效，把首次栅格化/动画启动挪出关键帧 */
.ob-card.is-swiping .ob-deck * { animation-play-state: paused; }
.ob-hi-hello { font-size: calc(22px * var(--fs-scale)); font-weight: var(--fw-medium); letter-spacing: 1px; color: var(--text-3); margin-right: calc(-0.4em - 1px); } /* 抵消全角「！」右半空白 + 字距尾空白，使可见字居中 */
.ob-hi-title { font-size: calc(30px * var(--fs-scale)); font-weight: var(--fw-bold); color: var(--text-1); line-height: 1.24; margin: 0; }
.ob-hi-title b { color: var(--text-1); font-weight: var(--fw-bold); }
/* P1 丝滑入场：文案错峰上浮（把"瞬间闪出"变成有节奏的浮现），logo 随卡片一起淡入 */
@keyframes obHeroIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.ob-slide-hi .ob-hi-hello { animation: obHeroIn var(--d-morph) var(--ease-enter) both var(--d-fast); }
.ob-slide-hi .ob-hi-title { animation: obHeroIn var(--d-slow) var(--ease-enter) both var(--d-modal); }
.ob-slide-hi .ob-slide-desc { animation: obHeroIn var(--d-slow) var(--ease-enter) both var(--d-push); }

/* ---- 第 2/3 页 · 自动循环卡组：grid 叠放，当前张淡入，其余隐 ---- */
.ob-slide-deck { gap: var(--sp-4); }
.ob-deck { display: flex; flex-direction: column; align-items: center; width: 100%; }
.ob-deck-stage { display: grid; width: 100%; max-width: 288px; }
.ob-deck-card {
  grid-area: 1 / 1; justify-self: center; align-self: center; width: 100%;
  opacity: 0; transform: translateY(10px) scale(.97); pointer-events: none;
  transition: opacity var(--d-morph) var(--ease-enter), transform var(--d-morph) var(--ease-enter);
}
.ob-deck-card.is-on { opacity: 1; transform: none; pointer-events: auto; }
.ob-deck-card .ob-illu { max-width: 288px; }
.ob-deck-meta { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--sp-1); margin-top: var(--sp-4); }
.ob-deck-name { font-size: calc(22px * var(--fs-scale)); font-weight: var(--fw-bold); color: var(--text-1); line-height: 1.2; }
.ob-deck-desc { font-size: calc(15px * var(--fs-scale)); color: var(--text-3); line-height: 1.5; }
.ob-deck-count { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--fs-12); letter-spacing: .5px; color: var(--text-disabled); margin-top: 2px; }
/* 「卡片可点」小提示：触点图标 + 文案，图标轻微脉冲引人点击（P1 时随卡组暂停） */
.ob-deck-hint { display: inline-flex; align-items: center; gap: var(--sp-1); margin-top: var(--sp-2); font-size: var(--fs-12); letter-spacing: .3px; color: var(--text-4); }
.ob-deck-hint svg { width: 14px; height: 14px; color: var(--text-3); animation: obTapHint 2.4s ease-out infinite; }
@keyframes obTapHint { 0%,72%,100% { transform: scale(1); opacity: .65; } 18% { transform: scale(1.28); opacity: 1; } 36% { transform: scale(1); opacity: .8; } }

/* ---- 演示动效公共：mock 等高出图，动效只在卡片点亮时跑 ---- */
.mk { min-height: 138px; }
.ob-deck-card.is-on .mk-chk.is-on { background: var(--text-1); border-color: var(--text-1); }
/* 待办：勾选填充 + 勾线画出 + 删除线扫过 */
.ob-todo-chk { position: relative; }
.ob-todo-chk::after { content: ''; position: absolute; left: 5px; top: 2px; width: 4px; height: 8px; border: solid var(--bg-card); border-width: 0 2px 2px 0; transform: rotate(45deg) scale(0); opacity: 0; }
.ob-todo-ln { position: relative; }
.ob-todo-ln::after { content: ''; position: absolute; left: -2px; top: 50%; height: 2px; width: 0; background: var(--text-3); }
.ob-deck-card.is-on .ob-todo-chk { animation: obChk 2.6s var(--ease-enter) infinite; }
.ob-deck-card.is-on .ob-todo-chk::after { animation: obChkMark 2.6s var(--ease-enter) infinite; }
.ob-deck-card.is-on .ob-todo-ln::after { animation: obStrike 2.6s var(--ease-enter) infinite; }
@keyframes obChk { 0%,15% { background: transparent; border-color: var(--border-strong); } 40%,82% { background: var(--text-1); border-color: var(--text-1); } 100% { background: transparent; border-color: var(--border-strong); } }
@keyframes obChkMark { 0%,30% { transform: rotate(45deg) scale(0); opacity: 0; } 46%,82% { transform: rotate(45deg) scale(1); opacity: 1; } 100% { opacity: 0; } }
@keyframes obStrike { 0%,42% { width: 0; } 62%,86% { width: 100%; } 100% { width: 100%; opacity: 0; } }
/* 备忘：标签胶囊错峰弹入 */
.mk-memo { align-items: flex-start; }
.mk-tags { display: flex; gap: var(--sp-2); margin-top: 2px; }
.ob-tagc { font-size: var(--fs-12); line-height: 1; padding: var(--sp-1) var(--sp-2); border-radius: var(--r-pill); background: var(--bg-muted); color: var(--text-3); opacity: 0; transform: scale(.6); }
.ob-deck-card.is-on .ob-tagc { animation: obTagIn 2.6s var(--ease-enter) infinite; }
.ob-deck-card.is-on .ob-tagc:nth-child(2) { animation-delay: var(--d-base); }
.ob-deck-card.is-on .ob-tagc:nth-child(3) { animation-delay: var(--d-enter); }
@keyframes obTagIn { 0% { opacity: 0; transform: scale(.6); } 22%,70% { opacity: 1; transform: scale(1); } 90%,100% { opacity: 0; transform: scale(.9); } }
/* 纪念日：心跳 + 倒数条填充 */
.mk-heart { display: flex; justify-content: center; padding: 2px 0; }
.mk-heart svg { width: 34px; height: 34px; color: var(--text-1); }
.ob-deck-card.is-on .mk-heart svg { animation: obPulse 2.6s var(--ease-enter) infinite; }
@keyframes obPulse { 0%,100% { transform: scale(1); } 12% { transform: scale(1.18); } 24% { transform: scale(1); } 36% { transform: scale(1.1); } 50% { transform: scale(1); } }
.mk-cdown { display: flex; align-items: baseline; justify-content: center; gap: var(--sp-1); font-size: calc(14px * var(--fs-scale)); color: var(--text-3); }
.mk-cdown b { font-weight: var(--fw-regular); }
.ob-cnum { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: calc(22px * var(--fs-scale)); font-weight: var(--fw-bold); color: var(--text-1); }
.mk-bar { height: 6px; border-radius: var(--r-pill); background: var(--bg-muted); overflow: hidden; }
.ob-fill { display: block; height: 100%; width: 8%; border-radius: var(--r-pill); background: var(--text-1); }
.ob-deck-card.is-on .ob-fill { animation: obFill 2.6s var(--ease-enter) infinite; }
@keyframes obFill { 0% { width: 8%; } 70%,100% { width: 78%; } }
/* 小记：书写线生长 + 心情点 */
.mk-write { position: relative; height: 12px; }
.ob-wline { display: block; height: 9px; width: 0; border-radius: var(--r-1); background: var(--bg-muted); }
.ob-deck-card.is-on .ob-wline { animation: obWrite 2.6s var(--ease-enter) infinite; }
@keyframes obWrite { 0% { width: 0; } 55%,92% { width: 100%; } 100% { width: 100%; } }
.mk-mood { display: flex; gap: var(--sp-2); }
.ob-mood { width: 16px; height: 16px; border-radius: var(--r-circle); background: var(--bg-muted); }
.ob-mood.on { background: var(--text-1); }
/* 一句话：气泡打字 + 结果胶囊滑入 */
.mk-nl { align-items: flex-start; }
.mk-bubble { position: relative; padding: var(--sp-3); border-radius: var(--r-3); background: var(--bg-muted); align-self: flex-start; max-width: 92%; }
.ob-type { display: inline-block; height: 9px; width: 0; border-radius: var(--r-1); background: var(--text-4); vertical-align: middle; }
.ob-deck-card.is-on .ob-type { animation: obType 2.6s var(--ease-enter) infinite; }
@keyframes obType { 0% { width: 0; } 40% { width: 116px; } 100% { width: 116px; } }
.ob-nlchip { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-3); padding: var(--sp-2) var(--sp-3); border-radius: var(--r-3); border: 1px solid var(--border); background: var(--bg-card); font-size: calc(14px * var(--fs-scale)); color: var(--text-2); opacity: 0; transform: translateY(8px); }
.ob-nlchip svg { width: 16px; height: 16px; color: var(--text-1); flex-shrink: 0; }
.ob-deck-card.is-on .ob-nlchip { animation: obChipIn 2.6s var(--ease-enter) infinite; }
@keyframes obChipIn { 0%,45% { opacity: 0; transform: translateY(8px); } 60%,92% { opacity: 1; transform: none; } 100% { opacity: 0; } }
/* 数据存本机：文件行 + 锁角标脉冲 */
.mk-db { position: relative; }
.mk-file svg { width: 26px; height: 26px; color: var(--text-2); flex-shrink: 0; }
.ob-fname { font-family: var(--font-mono); font-size: calc(14px * var(--fs-scale)); color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-lock { position: absolute; right: 2px; bottom: 2px; width: 36px; height: 36px; border-radius: var(--r-3); background: var(--text-1); color: var(--bg-card); display: flex; align-items: center; justify-content: center; }
.mk-lock svg { width: 18px; height: 18px; }
.ob-deck-card.is-on .mk-lock { animation: obLock 2.6s var(--ease-enter) infinite; }
@keyframes obLock { 0%,100% { transform: scale(1); } 15% { transform: scale(1.12); } 30% { transform: scale(1); } }
/* 断网也能用：wifi 熄灭闪烁 + 本地可用勾（标题左对齐，与本机档案/云端同步一致） */
.mk-off { align-items: stretch; }
.mk-wifi { display: flex; justify-content: center; padding: var(--sp-1) 0; }
.mk-wifi svg { width: 36px; height: 36px; color: var(--text-2); }
.ob-deck-card.is-on .mk-wifi svg { animation: obWifi 2.6s steps(1, end) infinite; }
@keyframes obWifi { 0%,49% { opacity: 1; } 50%,100% { opacity: .3; } }
.ob-offchip { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-3); font-size: calc(14px * var(--fs-scale)); color: var(--text-2); }
.ob-offchip svg { width: 16px; height: 16px; color: var(--text-1); }
/* 登录后同步：旋转同步箭头 + 设备行 */
.mk-cloud { display: flex; justify-content: center; padding: var(--sp-1) 0; }
.mk-cloud svg { width: 32px; height: 32px; color: var(--text-2); }
.ob-spin { display: inline-flex; }
.ob-deck-card.is-on .ob-spin { animation: obSpin 2.2s linear infinite; }
@keyframes obSpin { to { transform: rotate(360deg); } }
/* 习惯：一周打卡格依次点亮（连续成习惯）；格为正方形 */
.mk-streak { display: flex; gap: var(--sp-1); }
.mk-streak i { flex: 1; aspect-ratio: 1 / 1; border-radius: var(--r-2); background: var(--bg-muted); }
.ob-deck-card.is-on .mk-streak i { animation: obStreak 2.6s var(--ease-enter) infinite; }
.ob-deck-card.is-on .mk-streak i:nth-child(2) { animation-delay: var(--d-micro); }
.ob-deck-card.is-on .mk-streak i:nth-child(3) { animation-delay: var(--d-modal); }
.ob-deck-card.is-on .mk-streak i:nth-child(4) { animation-delay: var(--d-enter); }
.ob-deck-card.is-on .mk-streak i:nth-child(5) { animation-delay: var(--d-morph); }
.ob-deck-card.is-on .mk-streak i:nth-child(6) { animation-delay: var(--d-slow); }
.ob-deck-card.is-on .mk-streak i:nth-child(7) { animation-delay: .72s; }
@keyframes obStreak { 0%,6% { background: var(--bg-muted); } 28%,88% { background: var(--text-1); } 100% { background: var(--bg-muted); } }
.ob-hstreak { margin-left: auto; font-size: var(--fs-12); color: var(--text-4); white-space: nowrap; }

/* ---- 步骤切换（轮播 ↔ 昵称）：淡出上移 → 淡入上移；logo 已在左上角不动 ---- */
.ob-step.ob-leave { animation: obStepLeave var(--d-base) ease forwards; }
.ob-step.ob-enter { animation: obStepEnter var(--d-morph) var(--ease-enter) both; }
@keyframes obStepLeave { to { opacity: 0; transform: translateY(-10px); } }
@keyframes obStepEnter { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

/* ---- 昵称表单：卡内「上标签 + 下井」，井与编辑表单同一衬底参数 ---- */
.ob-nfield { padding: var(--sp-3) var(--sp-4) var(--sp-4); }
/* 标题走全站唯一字段标题档（1104：从前这里 12px/--text-4，是第五档）；
   已填墨色与占位同档，靠标题的深粗拉开层级。 */
.ob-nlab { display: block; font-size: var(--fld-label-fs); font-weight: var(--fw-medium); color: var(--text-1); margin-bottom: var(--sp-2); }
.ob-form .ob-ninput {
  height: 54px; padding: 0 var(--sp-3); font-size: calc(18px * var(--fs-scale)); text-align: center;
  background: var(--bg-muted); border: 1px solid transparent; border-radius: var(--r-3);
  color: var(--fld-ink); font-family: var(--font-sans);
}
.ob-form .ob-ninput::placeholder { font-size: calc(15px * var(--fs-scale)); color: var(--text-hint); }
@media (hover: hover) { .ob-form .ob-ninput:hover { border-color: var(--border-strong); } }
.ob-form .ob-ninput:focus {
  background: var(--bg-card); border-color: var(--primary); box-shadow: 0 0 0 3px var(--focus-ring);
}
.ob-form .form-error { font-size: var(--fs-12); margin-top: var(--sp-2); text-align: center; }
.ob-form.bad { animation: shake var(--d-push) ease-out; } /* 复用登录报错抖动，不另起第二套参数 */

/* ---- 收尾：通栏黑胶囊主操作（轮播与昵称共用，钉在卡底不随滑动） ---- */
.ob-foot { margin-top: var(--sp-4); flex-shrink: 0; }
.btn.ob-go {
  width: 100%; height: 48px; font-size: calc(15px * var(--fs-scale)); font-weight: var(--fw-medium);
  border-radius: var(--r-3); letter-spacing: .5px;
}
.btn.ob-go svg { width: 16px; height: 16px; }
.ob-note { font-size: var(--fs-12); line-height: 1.6; color: var(--text-4); text-align: center; margin-top: var(--sp-3); }

/* 本地模式徽章（个人中心）：灰色系，并与昵称左对齐
   （去掉基线为「名字后内联」预留的 5px 左缩进，避免徽章相对昵称右移） */
.role-badge.role-local { background: var(--bg-muted); color: var(--text-4); }
[data-theme="dark"] .role-badge.role-local { background: var(--bg-muted); color: var(--text-3); }
.pf-sub .role-badge { margin-left: 0; }
/* 本地模式「修改昵称」弹窗说明行 */
.rn-note { margin: var(--sp-3) 2px 0; font-size: var(--fs-12); line-height: 1.6; color: var(--text-4); }

/* ≤768 手机端样式 → 06-mobile.css */
@media (prefers-reduced-motion: reduce) {
  .login-mask, .login-pop, .ob-card { animation: none; }
  .login-mask.is-closing, .login-pop.is-closing,
  .login-pop .login-logo, .login-pop .field, .login-pop .btn-block { animation: none; }
  .ob-mask, .ob-mask.is-out, .ob-card.is-out, .ob-step, .ob-form.bad { animation: none; }
  .ob-track { transition: none; }
  /* 卡组演示动效与脉冲光环一律停摆；卡片切换改为无转场直切 */
  .ob-card *, .ob-card *::before, .ob-card *::after { animation: none !important; }
  .ob-deck-card { transition: none; }
}
button, a, [role="button"], input, select, textarea { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
input:focus-visible, textarea:focus-visible, select:focus-visible { outline: none; }
.btn:focus-visible, .menu-item:focus-visible,
.seg button:focus-visible, .chip:focus-visible, .btn-link:focus-visible, .modal-x:focus-visible, .modal-back:focus-visible,
.todo-check input:focus-visible + .todo-check-box { outline-offset: -2px; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}

/* ===================== 滚动条（细 / 贴合主题） ===================== */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--r-1); }
@media (hover: hover) { ::-webkit-scrollbar-thumb:hover { background: var(--text-4); } }
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }

/* 移动端（窄屏或触屏）：隐藏滚动条 */
/* ≤768 手机端样式 → 06-mobile.css「移动端（窄屏或触屏）：隐藏滚动条」 */

/* ===================== 响应式 ===================== */
/* ≤1024px：侧边栏收窄为图标、双栏面板单列 */
@media (max-width: 1024px) {
  .sidebar { width: 64px; }
  .sidebar .logo { justify-content: center; padding: var(--sp-4) 0; }
  .logo-text { display: none; }
  .menu-section-title { visibility: hidden; height: 6px; padding: 0; }
  .sidebar .menu-item { justify-content: center; padding: 0; }
  .sidebar .menu-item > span, .sidebar .menu-cnt { display: none; }
  .menu-footer { display: none; }
  .avatar-btn { display: inline-flex; } /* 侧边栏收窄：个人中心入口移至顶栏头像 */
  .header-left p { display: none; }
  .content { padding: var(--sp-4); }
}
/* ≤768px：移动端布局 —— 隐藏侧栏、底部导航、全屏弹窗 */
/* ≤768 手机端样式 → 06-mobile.css「≤768px：移动端布局 —— 隐藏侧栏、底部导航、全屏弹窗」 */

/* ============================================================
   1011 横滑链位置导轨（分段条 + 可拖动滑块，仅手机端）——shell 结构件，非页面样式
   ------------------------------------------------------------
   钉在顶栏正下方：sticky top 直接抄 .header 那条 calc，随 --header-h / 字号档自动跟。
   链有几席就几段（段与滑块由 app.js 量段元素 offsetLeft 定位，与 dock 指示块同一套路），
   滑块停在当前席：内容区手指横滑时按同一个 pill 连续跟手，点/拖导轨穿过某席当场切页。
   - 桌面有侧栏 → 默认 display:none，只有 ≤768px 且 JS 挂 .is-on 才出现；
   - 材质与顶栏同一块毛玻璃（bg-card 55% + blur20/150）；
   - 栏高靠上下 padding（段/滑块尺寸不变），热区再由 ::before 向下扩进内容顶部空 padding 回 ≥38px；
   - touch-action: none → 整条带由本件 JS 独占（点跳/横拖寻址）；竖向滚动交给下方内容大区域；
   - 弹层遮罩 z-index 9000+ 全屏盖过本件，无需另写隐藏逻辑（链外的「用户」页由 JS 藏）。
   滑块＝外层定位（translateX）+ 内层 core 软胶（scaleX/Y 果冻），落定复用 dock 那根弹簧
   （springPath 位移 + jellyFollow 形变）；跟手/寻址期间逐帧直写 transform（即时、不弹）。 */
.chain-bar { display: none; }
.chain-track { position: relative; display: flex; gap: var(--sp-1); height: 5px; }
.chain-seg {
  flex: 1 1 0; min-width: 0; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--text-2) 16%, transparent);
}
/* 每席下面一行小标题：与 .chain-seg 同 flex/gap → 逐格对齐；字号走 --fs-micro 令牌，
   超长省略。开关关掉时整行 display:none（连高度一起收回，导轨退回只剩分段+滑块）。 */
.chain-labels { display: flex; gap: var(--sp-1); margin-top: var(--sp-1); }
.chain-lab {
  flex: 1 1 0; min-width: 0; text-align: center; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  font-size: var(--fs-9); line-height: 1.2; color: var(--text-3);
}
.chain-bar.no-labels .chain-labels { display: none; }
/* 外层只做定位（translateX），可见软胶交给内层 core —— 与 dock 指示块 .tabbar-ind / .tabbar-ind-core 同构 */
.chain-knob {
  position: absolute; top: 50%; left: 0; height: 12px; width: 22px; margin-top: -6px;
  will-change: transform; pointer-events: none;
}
.chain-knob-core {
  display: block; width: 100%; height: 100%;
  border-radius: var(--r-pill); background: var(--text-1);
  box-shadow: 0 1px 3px color-mix(in srgb, var(--text-1) 30%, transparent);
}
/* 拖动寻址中：滑块走一条「带回弹」的 CSS 过渡——back 曲线过冲一点再收回＝有「弹」，
   而 CSS 过渡被打断时从「当前显示值」续接，快速连跨不会像 WAAPI 那样 cancel 后 snap 回旧落点（＝卡帧）。
   点按/落定才用 WAAPI 果冻弹簧（app.js chainBarPlace，带 core 形变）。 */
.chain-bar.is-scrub .chain-knob { transition: transform 260ms var(--ease-spring); }

/* ≤768 手机端样式 → 06-mobile.css */
