/* ============================================================================
   Squad44控制面板 · 移动端 / 平板端适配层  (s44-mobile.css v12)
   ----------------------------------------------------------------------------
   为什么单独一个文件，而不是往每个页面的内联 <style> 里塞 @media
   ----------------------------------------------------------------------------
   面板有 40 多个业务页，每页自带几百行内联样式，各自的断点写法还不一样：
   有的 768、有的 900、有的 1024，有的干脆没写。逐页改的话，改完一轮，
   下次谁新加一页又是老样子。

   这一层由 _brand.php 统一注入到每个带 </head> 的响应里 —— 包括 dashboard
   外壳，也包括它 iframe 进来的每个业务页。加一页新业务页，不用做任何事，
   移动端适配自动生效。

   与 s44-theme.css 的分工
   ----------------------------------------------------------------------------
   s44-theme.css   管"长什么样"：色板、圆角、描边、字体。全尺寸生效。
   s44-mobile.css  管"在小屏上怎么排"：断点、触控尺寸、抽屉、底部标签栏。
                   桌面宽度下本文件几乎不产生任何规则，只定义几个变量。

   断点口径（全站统一，别再各写各的）
   ----------------------------------------------------------------------------
     ≤ 480px        小手机：单列，标签栏文字缩到 10px
     ≤ 768px        手机：抽屉式侧栏 + 底部标签栏，进入 app 形态
     769 – 1024px   平板：侧栏收成图标轨道，两列栅格，保留表格
     ≥ 1025px       桌面：本文件不介入

   两条硬约束（改之前先读）
   ----------------------------------------------------------------------------
   1. 模态框在移动端仍然是**居中弹出**，不是底部抽屉。
      这一条是产品明确要求过的，dashboard.php 里那段 MOBILE_IFRAME_PATCH 的
      注释也写着"覆盖可能残留的底部抽屉样式"。本文件只优化居中态的呈现
      （进场曲线、安全区、头尾固定），不要再改回抽屉。
   2. 动画只碰 transform / opacity。移动端 GPU 弱，动 width/height/top/left
      会掉帧，毛玻璃在中低端安卓上是持续开销 —— 小屏一律换实色。

   性能约定与 s44-theme.css 一致：reduced-motion 下全部降级为无动画。
   ========================================================================= */

/* ------------------------------------------------------------ 1. 令牌 */
:root{
  /* 安全区：iPhone 刘海 / 底部横条、安卓手势条。
     env() 在不支持的浏览器上整条声明失效，所以先给 0 兜底再覆盖。 */
  --s44-sat:0px; --s44-sab:0px; --s44-sal:0px; --s44-sar:0px;

  /* 底部标签栏总高（含安全区）。内容区靠它算 padding-bottom，
     AI 悬浮球、Toast 也靠它避让，改一处全站跟着走。 */
  --s44-bottomnav:0px;
  --s44-tabbar-h:54px;

  /* 触控最小命中区。44px 是 Apple HIG 的下限，安卓 Material 是 48dp，
     取 44 作为按钮高度、图标按钮用 ::after 扩展到 44 见方。 */
  --s44-touch:44px;

  /* iOS Safari 地址栏收放会让 100vh 跳变，JS 每次 resize 写入真实值。
     没有 JS 时回退到 1vh，行为等同于原来。 */
  --s44-vh:1vh;
}
@supports (padding:env(safe-area-inset-bottom)){
  :root{
    --s44-sat:env(safe-area-inset-top);
    --s44-sab:env(safe-area-inset-bottom);
    --s44-sal:env(safe-area-inset-left);
    --s44-sar:env(safe-area-inset-right);
  }
}

/* ------------------------------------------------- 2. 触控基础（全尺寸） */
/* 指针是粗指针（手指 / 触控笔）时才生效，鼠标用户不受影响 —— 
   用 pointer:coarse 而不是宽度判断，因为触屏笔记本也该拿到大命中区。 */
@media (pointer:coarse){
  button,.btn,a.btn,[role="button"],.filter-chip,.tab,.browser-tab,
  .admin-nav-btn,.player-tab,.pagination button,.pager a,.pager button{
    min-height:var(--s44-touch);
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;   /* 去掉 iOS 双击缩放带来的 300ms 延迟 */
  }
  /* 纯图标按钮往往只有 24×24，用伪元素把命中区撑到 44，视觉尺寸不变 */
  .btn-icon,.modal-close,.icon-btn,.menu-btn,.m-close{position:relative}
  .btn-icon::after,.modal-close::after,.icon-btn::after,.menu-btn::after,.m-close::after{
    content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
    width:max(100%,var(--s44-touch));height:max(100%,var(--s44-touch));
  }
  /* 按下反馈：桌面靠 :hover，触屏没有 hover，靠 :active 给一个 60ms 的缩放 */
  .btn:active,button:active,.filter-chip:active,.card-clickable:active{
    transform:scale(.97);transition:transform 60ms var(--s44-ease,ease-out);
  }
}

/* 触屏上 :hover 会"粘住"（点完保持悬浮态直到点别处），全部关掉 */
@media (hover:none){
  .btn:hover,.card:hover,.t-item:hover,tbody tr:hover,.match-item:hover{
    transform:none!important;box-shadow:inherit;
  }
}

/* =========================================================================
   3. 平板端  769 – 1024px
   -------------------------------------------------------------------------
   平板不是"大手机"，也不是"小桌面"。横屏 iPad 有 1024px 宽，塞得下表格，
   塞不下 236px 的侧栏 + 三列栅格。所以这一档的策略是：
     · 侧栏收成 74px 图标轨道（不是抽屉，随时可点，不遮内容）
     · 三列以上栅格一律降到两列
     · 表格保留，但给横向滚动加边缘阴影提示"右边还有"
     · 字号和行高不动，平板的阅读距离和桌面一样
   ========================================================================= */
@media (min-width:769px) and (max-width:1024px){

  .sidebar:not(.open){width:var(--sidebar-collapsed,74px)!important}
  .sidebar:not(.open) .brand-info,
  .sidebar:not(.open) .nav-text,
  .sidebar:not(.open) .nav-group-title,
  .sidebar:not(.open) .collapse-text,
  .sidebar:not(.open) .user-info{display:none!important}
  .sidebar:not(.open) .nav-item{justify-content:center!important;padding-left:0!important;padding-right:0!important}
  .main{margin-left:var(--sidebar-collapsed,74px)!important}

  /* 展开态浮在内容上，不挤压布局 —— 挤压会触发整页重排，平板上能看见闪 */
  .sidebar.open{width:var(--sidebar-width,236px)!important;box-shadow:var(--pro-shadow-lg)}

  /* 栅格降列。auto-fit 的 minmax 在 1024 下会挤出三列窄卡，读起来很难受 */
  .stats-grid,.stats,.cards-grid,.grid-3,.grid-4{
    grid-template-columns:repeat(2,minmax(0,1fr))!important;
  }
  .main-grid{grid-template-columns:1fr!important}
  .side-panel{display:grid!important;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}

  /* 详情面板从右侧固定栏改为堆叠，440px 侧栏在 1024 里占掉 43% */
  .main-layout{flex-direction:column!important}
  .detail-panel{width:100%!important;position:relative!important;max-height:none!important}

  .modal{max-width:min(720px,92vw)!important}
}

/* =========================================================================
   4. 手机端  ≤ 768px —— app 形态
   ========================================================================= */
@media (max-width:768px){

  :root{--s44-bottomnav:calc(var(--s44-tabbar-h) + var(--s44-sab))}

  html{-webkit-text-size-adjust:100%}          /* 转屏后不放大字号 */
  body{overscroll-behavior-y:contain}          /* 到顶再拉不触发整页橡皮筋 */

  /* 横向溢出是移动端最常见的破相来源：某个 min-width 的表格把 body 撑宽，
     整页能左右晃。统一在这里收口，真正需要横滚的容器自己开。 */
  html,body{max-width:100%;overflow-x:hidden}

  /* ---------------------------------------------------- 4.1 外壳布局 */
  .app{padding-left:var(--s44-sal);padding-right:var(--s44-sar)}
  .main{margin-left:0!important;width:100%!important}

  /* 内容区底部让出标签栏的位置。用 padding 不用 margin —— 
     margin 会让容器背景在标签栏后面断掉，滚动时能看见一条缝。 */
  .content,.main-content,.page-body,.page{
    padding-bottom:calc(var(--s44-bottomnav) + 16px)!important;
  }
  /* iframe 模式：iframe 自己撑满，底部留白交给 iframe 内页的 body */
  .content.iframe-mode{padding-bottom:0!important}
  .content.iframe-mode iframe{
    min-height:calc(var(--s44-vh) * 100 - var(--topbar-height,56px) - var(--s44-bottomnav))!important;
  }
  /* 被 iframe 进来的业务页自己留底部余量（AI 球 + 标签栏） */
  body.icfk-embedded-page{padding-bottom:calc(var(--s44-bottomnav) + 72px)}

  /* ---------------------------------------------------- 4.2 顶栏 */
  .topbar,.top-bar,.pro-topbar{
    position:sticky;top:0;z-index:900;
    height:auto!important;min-height:var(--topbar-height,56px);
    padding-top:calc(var(--s44-sat) + 8px)!important;
    padding-left:12px!important;padding-right:12px!important;
    /* 毛玻璃换实色：中低端安卓上 backdrop-filter 是每帧的持续开销 */
    backdrop-filter:none!important;-webkit-backdrop-filter:none!important;
    background:var(--pro-card)!important;
    gap:10px!important;
  }
  /* 滚动后顶栏落一条分隔线（s44-motion.js 给 body 加 .s44-scrolled） */
  body.s44-scrolled .topbar,body.s44-scrolled .pro-topbar{
    box-shadow:0 1px 0 var(--pro-line),0 6px 16px -12px rgba(0,0,0,.4);
  }
  .topbar .page-context,.page-heading .page-context{display:none!important}
  .topbar .page-title,.page-heading .page-title{
    font-size:17px!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  .topbar-right{gap:8px!important}
  .topbar-right .uiver-seg,.topbar-right .live-indicator{display:none!important}
  .server-btn .name{max-width:88px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  /* ---------------------------------------------------- 4.3 侧栏抽屉 */
  .sidebar{
    position:fixed!important;top:0;bottom:0;left:0;z-index:1200;
    width:min(300px,86vw)!important;
    padding-top:var(--s44-sat);padding-bottom:var(--s44-sab);
    transform:translate3d(-102%,0,0);
    transition:transform 280ms var(--s44-ease,cubic-bezier(.2,.7,.2,1));
    box-shadow:none;overscroll-behavior:contain;
  }
  .sidebar.open,.sidebar.show,.sidebar.active{
    transform:translate3d(0,0,0);
    box-shadow:0 0 40px -8px rgba(0,0,0,.5);
  }
  /* 折叠态在手机上没有意义：抽屉本来就不占位，收起按钮一并藏掉 */
  .sidebar.collapsed{width:min(300px,86vw)!important}
  .sidebar.collapsed .brand-info,.sidebar.collapsed .nav-text,
  .sidebar.collapsed .nav-group-title,.sidebar.collapsed .user-info{display:block!important}
  .sidebar .collapse-btn{display:none!important}
  .sidebar .nav-item{min-height:var(--s44-touch);font-size:14.5px}

  .overlay,.sidebar-overlay{
    position:fixed;inset:0;z-index:1100;background:rgba(4,10,12,.55);
    opacity:0;visibility:hidden;
    transition:opacity 260ms var(--s44-ease,ease),visibility 260ms;
  }
  .overlay.show,.overlay.active,.sidebar-overlay.show{opacity:1;visibility:visible}
  /* 抽屉打开时锁住背景滚动，由 JS 加 body.s44-locked */
  body.s44-locked{overflow:hidden!important;position:relative}

  /* ---------------------------------------------------- 4.4 卡片与栅格 */
  .card,.stat-card,.panel,.s-card{border-radius:12px!important}
  .card-header{padding:13px 15px!important}
  .card-body{padding:15px!important}
  .card-body.np{padding:0!important}

  .stats-grid,.stats,.stats-row,.cards-grid{
    grid-template-columns:repeat(2,minmax(0,1fr))!important;gap:10px!important;
  }
  .stat-card,.s-card{padding:14px 12px!important}
  .stat-value,.stat .v,.s-card-info .num{font-size:21px!important}
  .stat-label,.stat .k{font-size:11px!important}

  .main-grid,.edit-form-grid,.fg-row,.pub-grid,.form-row,.main-layout{
    grid-template-columns:1fr!important;flex-direction:column!important;
  }
  .side-panel{grid-template-columns:1fr!important}
  .detail-panel{width:100%!important;position:relative!important;max-height:none!important}

  /* ---------------------------------------------------- 4.5 表格 */
  /* 页面自带移动端卡片视图（.cards）的，交给页面自己处理，本层不插手。
     没自带的，给横向滚动加惯性和边缘提示，至少能用。 */
  .tbl-scroll,.table-wrap,.table-responsive,.data-table-wrap{
    overflow-x:auto;-webkit-overflow-scrolling:touch;
    scroll-snap-type:x proximity;
  }
  table{font-size:13px}
  table thead th{
    font-size:10px!important;letter-spacing:.06em!important;
    padding:9px 10px!important;white-space:nowrap;
  }
  table tbody td{padding:10px!important}
  /* 首列钉住，横滚时还知道这行是谁。
     这是**可选样式**：目前没有任何页面在用 .table-sticky-first，
     需要哪张表钉首列，就给它的容器手动加上这个类。
     没有自动加是有意的 —— 首列很窄（比如只有一个复选框）时钉住反而更难看，
     该不该钉要看具体这张表长什么样。 */
  .table-sticky-first tbody td:first-child,
  .table-sticky-first thead th:first-child{
    position:sticky;left:0;z-index:2;background:var(--pro-card);
    box-shadow:1px 0 0 var(--pro-line);
  }
  /* 右侧还有内容时的渐隐提示。
     .s44-scroll-x 和 .s44-scroll-x-more 两个类都由 s44-mobile.js 自动加：
     它扫 .tbl-scroll / .table-wrap / .table-responsive / .data-table-wrap，
     绑 scroll 事件后按 scrollWidth 判断右边还有没有内容。
     页面不需要写任何东西。 */
  .s44-scroll-x{position:relative}
  .s44-scroll-x::after{
    content:"";position:absolute;top:0;right:0;bottom:0;width:26px;pointer-events:none;
    background:linear-gradient(90deg,transparent,var(--pro-card));
    opacity:0;transition:opacity 200ms var(--s44-ease,ease);
  }
  .s44-scroll-x.s44-scroll-x-more::after{opacity:1}

  /* ---------------------------------------------------- 4.6 表单 */
  /* 16px 是 iOS Safari 不触发自动缩放的下限，低于它聚焦输入框整页会放大 */
  input,select,textarea,.form-input,.form-select,.fi{
    font-size:16px!important;min-height:var(--s44-touch);
    border-radius:10px!important;
  }
  textarea,textarea.form-input,textarea.fi{min-height:110px}
  .form-group,.fg{margin-bottom:14px!important}
  .search-box,.filter-row,.players-search-bar,.bar-row{flex-direction:column!important;align-items:stretch!important}
  .search-box .form-input,.search-wrap,.search{max-width:100%!important;width:100%!important}
  /* 表单里的按钮排成整行，两个并排时各占一半 */
  .form-actions,.modal-footer,.m-ft,.pub-actions{
    display:flex!important;gap:10px!important;
  }
  .form-actions .btn,.modal-footer .btn,.m-ft .btn{flex:1;justify-content:center}

  /* ---------------------------------------------------- 4.7 筛选条 */
  /* 一排 filter-chip 在手机上会换行成三四行，占掉半屏。改成单行横滑。 */
  .matches-toolbar-left,.filter-bar,.tabs,.browser-tabs,.admin-nav,.player-tabs,.season-pick{
    display:flex!important;flex-wrap:nowrap!important;
    overflow-x:auto;-webkit-overflow-scrolling:touch;
    scroll-snap-type:x proximity;scrollbar-width:none;
    padding-bottom:2px;
  }
  .matches-toolbar-left::-webkit-scrollbar,.filter-bar::-webkit-scrollbar,
  .tabs::-webkit-scrollbar,.browser-tabs::-webkit-scrollbar,
  .admin-nav::-webkit-scrollbar,.player-tabs::-webkit-scrollbar,
  .season-pick::-webkit-scrollbar{display:none}
  .filter-chip,.browser-tab,.admin-nav-btn,.player-tab,.tabs a{
    flex:0 0 auto!important;scroll-snap-align:start;white-space:nowrap;
  }
  .admin-nav-btn{padding:10px 14px!important;font-size:12.5px!important}
  .browser-tab{padding:11px 16px!important;font-size:13px!important}

  /* ---------------------------------------------------- 4.8 模态框 */
  /* 注意：移动端仍然是居中弹出，不是底部抽屉。这是产品明确要求。
     这里只做四件事：居中、留安全区、头尾固定、进场用弹簧曲线。 */
  .modal-overlay,.modal-mask,.ux-modal-mask{
    padding:16px!important;align-items:center!important;
    padding-top:calc(16px + var(--s44-sat))!important;
    padding-bottom:calc(16px + var(--s44-sab))!important;
  }
  .modal-overlay .modal,.modal-overlay .modal-box,
  .modal-mask .modal,.modal-mask .modal-box,
  .modal-mask .modal-content,.modal-mask .modal-dialog,
  .ux-modal-mask .ux-modal-box{
    width:calc(100% - 16px)!important;max-width:460px!important;margin:0 auto!important;
    border-radius:16px!important;
    max-height:calc(var(--s44-vh) * 100 - 32px - var(--s44-sat) - var(--s44-sab))!important;
    display:flex!important;flex-direction:column!important;
    padding-bottom:0!important;
  }
  /* 底部抽屉时代留下的那道拖拽小横条，清掉 */
  .modal-overlay .modal::before,.modal-overlay .modal-box::before,
  .modal-mask .modal::before,.modal-mask .modal-box::before,
  .ux-modal-mask .ux-modal-box::before{content:none!important;display:none!important}

  .modal-overlay .modal.modal-lg,.modal-overlay .modal-box.wide,
  .modal-mask .modal.modal-lg{max-width:640px!important}

  /* 头尾不跟着滚，长表单滚到一半还能看见标题和"保存" */
  .modal-header,.m-hd{flex:0 0 auto;position:sticky;top:0;z-index:2;background:var(--pro-card)}
  .modal-body,.m-bd{flex:1 1 auto;overflow-y:auto;-webkit-overflow-scrolling:touch;
    max-height:none!important;overscroll-behavior:contain}
  .modal-footer,.m-ft,.ux-modal-foot{
    flex:0 0 auto;position:static!important;padding-bottom:16px!important;
  }

  /* ---------------------------------------------------- 4.9 浮层避让 */
  /* AI 悬浮球和 Toast 都要抬到标签栏上面，否则被挡住点不到 */
  .ai-btn,#aiBtn,.ai-float{
    bottom:calc(var(--s44-bottomnav) + 16px)!important;
    right:calc(14px + var(--s44-sar))!important;
    width:52px!important;height:52px!important;
  }
  .ai-win,#aiWin{
    left:8px!important;right:8px!important;width:auto!important;
    bottom:calc(var(--s44-bottomnav) + 76px)!important;
    max-height:calc(var(--s44-vh) * 100 - var(--s44-bottomnav) - 140px)!important;
    border-radius:16px!important;
  }
  #toastContainer{
    top:auto!important;bottom:calc(var(--s44-bottomnav) + 74px)!important;
    left:12px!important;right:12px!important;align-items:stretch!important;
  }
  #toast{bottom:calc(var(--s44-bottomnav) + 20px)!important}

  /* ---------------------------------------------------- 4.10 杂项收口 */
  .pagination,.pager{gap:6px!important;flex-wrap:wrap}
  .pagination button,.pager a,.pager span{min-width:var(--s44-touch);height:var(--s44-touch)}
  .empty,.empty-state,.admin-empty{padding:36px 16px!important}
  .hero-banner{padding:20px 16px!important;border-radius:14px!important}
  code,pre{word-break:break-all}
}

/* ----------------------------------------------- 5. 小屏收口 ≤ 480px */
@media (max-width:480px){
  .stats-grid,.stats,.stats-row,.cards-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important}
  .stat-value,.stat .v{font-size:19px!important}
  .card-body{padding:13px!important}
  .topbar .page-title{font-size:16px!important}
  .s44-tabbar-item span{font-size:9.5px!important}
  .modal-overlay .modal,.modal-mask .modal-box{width:calc(100% - 8px)!important}
}

/* =========================================================================
   6. 底部标签栏
   -------------------------------------------------------------------------
   由 s44-mobile.js 在 dashboard 外壳里按 NAV_MODEL 动态生成，
   只在 ≤768px 出现。业务页（iframe 内）不会生成，那里由外壳负责导航。

   为什么用底部而不是继续用汉堡菜单：手机单手握持时拇指够得到的是屏幕
   下三分之一，把最常用的五项放在那里，切页从"两次点击 + 一次滑动"
   变成"一次点击"。汉堡菜单仍然保留，放在标签栏最后一格的"更多"里，
   完整导航一项不少。
   ========================================================================= */
.s44-tabbar{
  position:fixed;left:0;right:0;bottom:0;z-index:1000;
  display:none;                       /* 默认不显示，由媒体查询打开 */
  height:calc(var(--s44-tabbar-h) + var(--s44-sab));
  padding-bottom:var(--s44-sab);
  background:var(--pro-card);
  border-top:1px solid var(--pro-line);
  box-shadow:0 -1px 0 var(--pro-line),0 -8px 24px -18px rgba(0,0,0,.5);
  transform:translate3d(0,0,0);
  transition:transform 260ms var(--s44-ease,cubic-bezier(.2,.7,.2,1));
}
/* 向下滚动时收起，向上滚动时回来 —— 长列表页能多看两行 */
.s44-tabbar.s44-tabbar-hidden{transform:translate3d(0,110%,0)}

.s44-tabbar-inner{display:flex;height:var(--s44-tabbar-h);align-items:stretch}
.s44-tabbar-item{
  flex:1 1 0;min-width:0;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  border:none;background:none;padding:0 2px;cursor:pointer;
  color:var(--pro-subtle);font-family:inherit;
  -webkit-tap-highlight-color:transparent;
  position:relative;
  transition:color 180ms var(--s44-ease,ease);
}
.s44-tabbar-item i,.s44-tabbar-item svg{font-size:18px;width:18px;height:18px;line-height:1}
.s44-tabbar-item span{
  font-size:10.5px;line-height:1;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.s44-tabbar-item:active{transform:scale(.94);transition:transform 60ms ease-out}
.s44-tabbar-item.on{color:var(--primary);font-weight:600}
/* 选中态那条短横：位置用 transform 推，切换时横向滑过去而不是闪现 */
.s44-tabbar-item.on::before{
  content:"";position:absolute;top:0;left:50%;width:22px;height:2px;
  border-radius:0 0 2px 2px;background:var(--primary);
  transform:translateX(-50%) scaleX(1);transform-origin:50% 0;
  animation:s44-tab-pop 240ms var(--s44-spring,cubic-bezier(.34,1.28,.64,1));
}
@keyframes s44-tab-pop{from{transform:translateX(-50%) scaleX(.2);opacity:.4}
                        to{transform:translateX(-50%) scaleX(1);opacity:1}}
/* 未读红点（反馈中心等） */
.s44-tabbar-item .s44-dot{
  position:absolute;top:6px;left:calc(50% + 8px);
  min-width:15px;height:15px;padding:0 4px;border-radius:99px;
  background:var(--s44-bad,#B3453B);color:#fff;
  font-size:9px;line-height:15px;font-weight:700;text-align:center;
}

@media (max-width:768px){
  .s44-tabbar{display:block}
  /* 底部标签栏出现后，外壳自带的"更多"按钮就不需要重复出现在顶栏 */
  body.s44-has-tabbar .topbar .menu-btn{display:none}
}

/* =========================================================================
   7. 过渡动画补充
   -------------------------------------------------------------------------
   原来只有 s44-motion.js 里的卡片进场和滚动揭示，切页、切标签、抽屉这些
   高频动作是硬切的。补齐之后，每一次交互都有一个 160–280ms 的过渡，
   用户能看出"从哪来、到哪去"。

   全部只动 transform / opacity。时长梯度：
     微交互（按下、勾选）  60–140ms
     局部切换（标签、抽屉） 180–280ms
     整页切换               240–320ms
   ========================================================================= */

/* 7.1 换页：内容整体上浮淡入。iframe 换 src 时由 JS 加在容器上 */
.s44-page-enter{animation:s44-page-in 260ms var(--s44-ease,cubic-bezier(.2,.7,.2,1)) both}
@keyframes s44-page-in{from{opacity:0;transform:translate3d(0,10px,0)}to{opacity:1;transform:none}}

/* 7.2 换页去程：淡出并轻微下沉，和进场形成方向感 */
.s44-page-leave{animation:s44-page-out 140ms var(--s44-ease-in,cubic-bezier(.5,0,.9,.3)) both}
@keyframes s44-page-out{from{opacity:1;transform:none}to{opacity:0;transform:translate3d(0,-6px,0)}}

/* 7.3 标签面板切换：横向微移，比纯淡入更能表达"换了一屏" */
.tab-content.active,.player-tab-content.active,.admin-panel.active,.pane.on{
  animation:s44-pane-in 220ms var(--s44-ease,cubic-bezier(.2,.7,.2,1)) both;
}
@keyframes s44-pane-in{from{opacity:0;transform:translate3d(6px,0,0)}to{opacity:1;transform:none}}

/* 7.4 模态框：进场用弹簧收尾，退场干脆利落（退场慢会显得拖沓） */
.modal-overlay.show .modal,.modal-mask.show .modal-box,.ux-modal-mask.show .ux-modal-box{
  animation:s44-modal-in 280ms var(--s44-spring,cubic-bezier(.34,1.28,.64,1)) both;
}
@keyframes s44-modal-in{
  from{opacity:0;transform:scale(.94) translate3d(0,-8px,0)}
  to{opacity:1;transform:none}
}
.modal-overlay,.modal-mask,.ux-modal-mask{
  transition:opacity 200ms var(--s44-ease,ease),visibility 200ms;
}

/* 7.5 列表项依次落位。JS 只给前 10 个加 --i，超出的直接显形，避免长列表拖尾 */
.s44-stagger{opacity:0;transform:translate3d(0,8px,0);
  animation:s44-stagger-in 300ms var(--s44-ease,cubic-bezier(.2,.7,.2,1)) both;
  animation-delay:calc(var(--i,0) * 32ms);
}
@keyframes s44-stagger-in{to{opacity:1;transform:none}}

/* 7.6 Toast：从底部推上来，退场原路返回 */
.s44-toast-in{animation:s44-toast-in 240ms var(--s44-spring,cubic-bezier(.34,1.28,.64,1)) both}
@keyframes s44-toast-in{from{opacity:0;transform:translate3d(0,16px,0)}to{opacity:1;transform:none}}

/* 7.7 下拉刷新的指示环。只在 iframe 内页顶部下拉时出现 */
.s44-pull{
  position:fixed;left:50%;top:calc(var(--s44-sat) + 8px);z-index:1500;
  width:30px;height:30px;margin-left:-15px;border-radius:50%;
  background:var(--pro-card);border:1px solid var(--pro-line);
  display:flex;align-items:center;justify-content:center;
  opacity:0;transform:translate3d(0,-24px,0) scale(.8);pointer-events:none;
  transition:opacity 160ms var(--s44-ease,ease),transform 160ms var(--s44-ease,ease);
}
.s44-pull.on{opacity:1;transform:translate3d(0,0,0) scale(1)}
.s44-pull i{font-size:13px;color:var(--primary);transition:transform 160ms var(--s44-ease,ease)}
.s44-pull.ready i{transform:rotate(180deg)}
.s44-pull.spin i{animation:s44-spin .7s linear infinite}
@keyframes s44-spin{to{transform:rotate(360deg)}}

/* 7.8 数字变化时闪一下，让"刚刚更新了"这件事可见（在线人数、待办计数） */
.s44-flash{animation:s44-flash 620ms var(--s44-ease,ease) 1}
@keyframes s44-flash{
  0%{background-color:color-mix(in srgb,var(--primary) 22%,transparent)}
  100%{background-color:transparent}
}

/* --------------------------------------------- 8. 无障碍：减弱动态 */
/* 系统开了"减少动态效果"就全部关掉。这里必须重复一遍而不是依赖
   s44-theme.css 里那段 —— 本文件在它之后加载，同权重后来者胜，
   不重复的话本文件新增的动画会漏网。 */
@media (prefers-reduced-motion:reduce){
  .s44-page-enter,.s44-page-leave,.s44-stagger,.s44-toast-in,
  .tab-content.active,.player-tab-content.active,.admin-panel.active,.pane.on,
  .modal-overlay.show .modal,.modal-mask.show .modal-box,
  .s44-tabbar-item.on::before,.s44-flash{
    animation:none!important;opacity:1!important;transform:none!important;
  }
  .sidebar,.s44-tabbar,.overlay{transition:none!important}
  .s44-pull{display:none}
}

/* --------------------------------------------- 9. 横屏矮屏 */
/* 手机横屏时高度只有 375 左右，顶栏 + 标签栏就吃掉三分之一。
   这一档把两者都压薄，并且滚动时标签栏自动收起。 */
@media (max-width:900px) and (max-height:480px) and (orientation:landscape){
  :root{--s44-tabbar-h:46px;--topbar-height:48px}
  .topbar{padding-top:calc(var(--s44-sat) + 4px)!important;min-height:48px!important}
  .s44-tabbar-item span{display:none}
  .s44-tabbar-item i{font-size:19px}
  .modal-overlay .modal,.modal-mask .modal-box{
    max-height:calc(var(--s44-vh) * 100 - 20px)!important;
  }
}

/* --------------------------------------------- 10. 打印 */
@media print{
  .s44-tabbar,.s44-pull,.overlay{display:none!important}
  body{padding-bottom:0!important}
}
