/*! 寓居租房 H5 · 统一动效层 (motion.css)
 *  设计目标：统一全部页面的动效语言，达到一线大厂 H5 交互动效标准。
 *
 *  设计原则：
 *   1) 只用 transform 类属性与 opacity —— 全部走合成层，避免触发布局/重绘；
 *   2) 优先使用独立变换属性 translate / scale，可与页面已有的 transform 叠加，不互相覆盖；
 *   3) 入场动画一律 animation-fill-mode: backwards —— 结束后不残留变换，
 *      避免「祖先带 transform 导致 position:fixed 后代改为相对祖先定位」这一经典坑；
 *   4) 出场不做 CSS 动画（否则跳转后到新页渲染之间会出现白屏），
 *      跨文档出场交给 View Transitions，浏览器会用快照平滑过渡、顺便盖住网络延迟；
 *   5) 全量支持 prefers-reduced-motion。
 *
 *  令牌（供各页复用，不要再写死时长/缓动）：
 *   时长  --mo-dur-1..4        缓动 --mo-ease-*
 *   位移  --mo-dist-*          列表 --mo-stagger-step / --mo-stagger-max
 */

:root {
  /* ---- 时长 ---- */
  --mo-dur-1: 120ms;   /* 即时反馈：按下 */
  --mo-dur-2: 200ms;   /* 小元素进出：遮罩、微调 */
  --mo-dur-3: 280ms;   /* 标准：页面入场、弹层升起 */
  --mo-dur-4: 420ms;   /* 大范围：抽屉、整屏切换 */

  /* ---- 缓动 ---- */
  --mo-ease-decelerate: cubic-bezier(0.05, 0.7, 0.1, 1);   /* 进场：快起慢停 */
  --mo-ease-accelerate: cubic-bezier(0.3, 0, 0.8, 0.15);   /* 出场：慢起快走 */
  --mo-ease-standard: cubic-bezier(0.2, 0, 0, 1);          /* 通用 */
  --mo-ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);      /* 回弹：tab、图标 */

  /* ---- 位移 ---- */
  --mo-dist-1: 4px;
  --mo-dist-2: 10px;
  --mo-dist-3: 18px;
  --mo-dist-page: 22px;   /* 页面横向位移：克制，不做整屏滑动 */

  /* ---- 列表依次入场 ---- */
  --mo-stagger-step: 26ms;
  --mo-stagger-max: 8;    /* 最多叠加到第 8 项，之后不再累加 */

  /* ---- 主题色（与各页视觉语言一致）---- */
  --mo-accent: #42A5F5;
  --mo-ink: rgba(66, 165, 245, 0.12);
}

/* ============================================================
   1. 统一接管页面入场
   ============================================================ */

/* 历史遗留清理：
   多个页面用 body{opacity:0; transform:scale(.98)} + JS 加 .loaded 来入场。
   这类写法有两个硬伤：JS 失败则永久白屏；body 上残留 transform 会让所有
   position:fixed 后代改为相对 body 定位。这里统一接管，改由下面的动画负责入场。 */
body,
body.loaded,
body.leaving {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

@keyframes mo-enter-default {
  from { opacity: 0; translate: 0 var(--mo-dist-3); }
  to   { opacity: 1; translate: 0 0; }
}
@keyframes mo-enter-forward {         /* 进入下级页：从右侧进入 */
  from { opacity: 0; translate: var(--mo-dist-page) 0; }
  to   { opacity: 1; translate: 0 0; }
}
@keyframes mo-enter-back {            /* 返回上级页：从左侧进入 */
  from { opacity: 0; translate: calc(var(--mo-dist-page) * -0.8) 0; }
  to   { opacity: 1; translate: 0 0; }
}
@keyframes mo-enter-tab-left {        /* 切到右侧 tab：内容自右向左进入 */
  from { opacity: 0; translate: var(--mo-dist-3) 0; }
  to   { opacity: 1; translate: 0 0; }
}
@keyframes mo-enter-tab-right {       /* 切到左侧 tab：内容自左向右进入 */
  from { opacity: 0; translate: calc(var(--mo-dist-3) * -1) 0; }
  to   { opacity: 1; translate: 0 0; }
}

/* 页面根容器：覆盖两种布局家族 .phone / .page，以及 app.html 的 #shell */
body > .phone,
body > .page,
body > #shell {
  animation: mo-enter-default var(--mo-dur-3) var(--mo-ease-decelerate) backwards;
}

html.mo-nav-forward body > .phone,
html.mo-nav-forward body > .page,
html.mo-nav-forward body > #shell { animation-name: mo-enter-forward; }

html.mo-nav-back body > .phone,
html.mo-nav-back body > .page,
html.mo-nav-back body > #shell { animation-name: mo-enter-back; }

html.mo-nav-tab-left body > .phone,
html.mo-nav-tab-left body > .page,
html.mo-nav-tab-left body > #shell { animation-name: mo-enter-tab-left; }

html.mo-nav-tab-right body > .phone,
html.mo-nav-tab-right body > .page,
html.mo-nav-tab-right body > #shell { animation-name: mo-enter-tab-right; }

/* 跨文档 View Transition 生效时，入场完全交给浏览器，避免双重动画 */
html.mo-vt body > .phone,
html.mo-vt body > .page,
html.mo-vt body > #shell { animation: none; }

/* ============================================================
   2. 跨文档 View Transitions（渐进增强）
   浏览器支持时由快照完成出场+入场，天然盖住新页面的网络加载时间；
   不支持时自动降级为「只做入场动画」，同样没有白屏。
   ============================================================ */
@view-transition { navigation: auto; }

@keyframes mo-vt-old {
  to { opacity: 0; translate: calc(var(--mo-dist-2) * -1) 0; }
}
@keyframes mo-vt-new {
  from { opacity: 0; translate: var(--mo-dist-page) 0; }
  to   { opacity: 1; translate: 0 0; }
}
@keyframes mo-vt-new-tab-left {
  from { opacity: 0; translate: var(--mo-dist-3) 0; }
  to   { opacity: 1; translate: 0 0; }
}
@keyframes mo-vt-new-tab-right {
  from { opacity: 0; translate: calc(var(--mo-dist-3) * -1) 0; }
  to   { opacity: 1; translate: 0 0; }
}
@keyframes mo-vt-new-back {
  from { opacity: 0; translate: calc(var(--mo-dist-page) * -0.8) 0; }
  to   { opacity: 1; translate: 0 0; }
}

::view-transition-old(root) {
  animation: mo-vt-old var(--mo-dur-2) var(--mo-ease-accelerate) both;
}
::view-transition-new(root) {
  animation: mo-vt-new var(--mo-dur-3) var(--mo-ease-decelerate) both;
}
html.mo-nav-tab-left::view-transition-new(root) { animation-name: mo-vt-new-tab-left; }
html.mo-nav-tab-right::view-transition-new(root) { animation-name: mo-vt-new-tab-right; }
html.mo-nav-back::view-transition-new(root) { animation-name: mo-vt-new-back; }

/* ============================================================
   3. 底部 tab：滑动指示器 + 图标/文字状态
   注意：不要给 .tabbar 设 position —— 各页原本是 position:absolute 吸底，
   覆盖它会直接破坏底部导航布局。它本身已是定位上下文，指示器挂进去即可。
   ============================================================ */

/* 底部 tab 导航在全项目唯一：定义在 app.html 的 #shellTabbar。
   各页面不再自带 tabbar，所以这里不需要任何"嵌入时隐藏"的兜底规则。 */

/* 底部导航整体质感：去掉各页的硬分隔线，改用与卡片一致的柔和阴影 + 半透明磨砂底，
   与 App 内的卡片/气泡语言（白色半透明 + 轻投影 + 大圆角）保持协调。 */
.tabbar {
  border-top: 0;
  background: rgba(255, 255, 255, 0.94);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  backdrop-filter: saturate(180%) blur(12px);
  box-shadow: 0 -1px 0 rgba(15, 23, 42, 0.05), 0 -8px 20px rgba(15, 23, 42, 0.05);
}

/* 选中指示器：尺寸由 JS 按 tab 实际盒子内缩计算，
   保证「图标 + 文字」整体落在背景之内 —— 之前固定 32px 高会把文字下沿切掉。 */
.tabbar .mo-tab-ink {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  box-sizing: border-box;
  border-radius: 12px;
  background: rgba(0, 179, 254, 0.10);
  border: 1px solid rgba(0, 179, 254, 0.16);
  box-shadow: 0 1px 4px rgba(0, 179, 254, 0.10);
  opacity: 0;
  pointer-events: none;
  z-index: 0;
  translate: 0 0;
  transition: translate var(--mo-dur-3) var(--mo-ease-spring),
              width var(--mo-dur-3) var(--mo-ease-spring),
              height var(--mo-dur-3) var(--mo-ease-spring),
              opacity var(--mo-dur-2) var(--mo-ease-standard);
}
.tabbar.mo-ink-ready .mo-tab-ink { opacity: 1; }

/* 指示器接管后，去掉各页原本「瞬时出现」的背景块与整块弹跳，
   让滑动指示器成为唯一选中标识；JS 未生效时保持原样，不会失去选中态。 */
.tabbar.mo-ink-ready .tab.active {
  background: transparent !important;
  animation: none !important;
}

.tabbar .tab { position: relative; z-index: 1; }
.tabbar .tab svg,
.tabbar .tab img {
  transition: scale var(--mo-dur-3) var(--mo-ease-spring);
}
.tabbar .tab span { transition: color var(--mo-dur-2) var(--mo-ease-standard); }
/* 选中态文字加粗一点点，与蓝色一起把选中项拉开层次（各页原本 400/600 不统一） */
.tabbar .tab.active span { font-weight: 600; }
.tabbar .tab.active svg,
.tabbar .tab.active img { scale: 1.05; }

/* ============================================================
   4. 列表依次入场（opt-in：给容器加 data-mo-stagger）
   支持动态渲染：motion.js 会在节点变化时重排序号。
   ============================================================ */
@keyframes mo-item-in {
  from { opacity: 0; translate: 0 var(--mo-dist-2); }
  to   { opacity: 1; translate: 0 0; }
}
[data-mo-stagger] > * {
  animation: mo-item-in var(--mo-dur-2) var(--mo-ease-decelerate) backwards;
  animation-delay: calc(min(var(--mo-i, 0), var(--mo-stagger-max)) * var(--mo-stagger-step));
}

/* 深层依次入场：容器是分栏结构（如首页瀑布流 #waterfall → 列 → 卡片），
   序号跨列连续编号，视觉上就是卡片自上而下逐个浮现。 */
[data-mo-stagger-deep] > * > * {
  animation: mo-item-in var(--mo-dur-2) var(--mo-ease-decelerate) backwards;
  animation-delay: calc(min(var(--mo-i, 0), var(--mo-stagger-max)) * var(--mo-stagger-step));
}

/* ============================================================
   5. 弹层 / 遮罩：统一时长与缓动
   仅改「时间曲线」，不动各页既有的位移/显隐机制，属于安全收敛。
   ============================================================ */
.filter-sheet,
.hlp-filter-sheet,
.cp-sheet,
.comm-picker,
.type-panel,
.fs-type-panel,
.zoom-modal-box,
.complaint-modal {
  transition: transform var(--mo-dur-3) var(--mo-ease-decelerate),
              opacity var(--mo-dur-3) var(--mo-ease-decelerate),
              translate var(--mo-dur-3) var(--mo-ease-decelerate) !important;
}

.filter-overlay,
.hlp-filter-overlay,
.cp-mask,
.complaint-mask,
.zoom-modal {
  transition: opacity var(--mo-dur-2) var(--mo-ease-standard),
              visibility var(--mo-dur-2) var(--mo-ease-standard) !important;
}

/* ============================================================
   6. 通用工具类
   ============================================================ */

/* 骨架屏（加载占位比「加载中…」文字更接近大厂体感） */
@keyframes mo-shimmer {
  0%   { background-position: -160% 0; }
  100% { background-position: 260% 0; }
}
.mo-skeleton {
  background: linear-gradient(90deg, #EEF1F4 25%, #F7F9FB 37%, #EEF1F4 63%);
  background-size: 260% 100%;
  animation: mo-shimmer 1.4s linear infinite;
  border-radius: 6px;
  color: transparent !important;
}

/* 按下反馈：motion.js 用 Web Animations API 驱动，这里只提供兜底类 */
.mo-pressed { scale: 0.96; }

/* 需要精细控制时的手动钩子 */
[data-mo-sheet] { transition-timing-function: var(--mo-ease-decelerate); }

/* ============================================================
   7. 无动画偏好
   用户开启「减弱动态效果」时，位移全部归零、时长压到 1ms。
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  :root {
    --mo-dur-1: 1ms; --mo-dur-2: 1ms; --mo-dur-3: 1ms; --mo-dur-4: 1ms;
    --mo-dist-1: 0px; --mo-dist-2: 0px; --mo-dist-3: 0px; --mo-dist-page: 0px;
    --mo-stagger-step: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
  .tabbar .tab.active svg,
  .tabbar .tab.active img { translate: 0 0; scale: 1; }
}
