/* ============================================================
   全站统一 mobile-only 外壳（第一阶段深化）
   ------------------------------------------------------------
   整个站点放弃 PC 适配。任意视口都渲染同一套移动端布局：
   - html/body 锁定为 720px 居中画布，外层多余空间用 #bg-pad 留白
   - 标准弹窗（.std-modal）默认仍占 720px 移动画布宽；沉浸类展示容器
     （*-immersive：deck / palette / minigames）除外——
     外部 shell 铺满浏览器视口，内部内容仍按固定比例居中/信箱
   - 底部 Tab 栏始终显示，并为各业务页正文预留底部安全区
   - auth.js 不再渲染顶部 authBar，底部 Tab 是唯一导航

   仅保留 prefers-reduced-motion 这类与设备能力相关、不绑定宽度的
   媒体查询；不再引入任何 width / orientation / pointer media query。
   ============================================================ */

/* ---------- 设计变量（全站 token） ----------
   页面/组件样式统一引用，避免魔法数字散落各处。
   --primary 系：当前主色为蓝 #4a90d9（hover 深一档 #3b7bc0）。
   部分旧组件仍是靛蓝 #667eea/#5a67d8，为保持视觉不变暂未并入，
   后续统一改色时只需调整这里的变量值。 */
:root {
    --primary: #4a90d9;
    --primary-2: #3b7bc0;
    --canvas-w: 100%;       /* 画布宽：自适应界面宽度 */
    --tab-h: 54px;          /* 底部 Tab 高（不含底部安全区） */
    --text-1: #2d3748;
    --text-2: #4a5568;
    --text-3: #718096;
    --text-muted: #a0aec0;
    --border: #e2e8f0;
    --border-soft: #edf2f7;
}

* { box-sizing: border-box; }

/* 点按高亮（tap highlight）全站收口：浏览器默认的紫/蓝色半透明块统一关掉，
   按压反馈一律由各元素自己的 :active（背景变深 / 颜色变深 / 位移缩放）承担，
   与 PlainView 顶栏 ×（.pv-close:active 浅灰底）同范式。
   注意 * 优先级最低，任何想保留高亮的元素可用类选择器显式覆盖。 */
* { -webkit-tap-highlight-color: transparent; }

/* ---------- 根容器 / 移动画布 ----------
   html/body 自身不再做 vertical padding 留白；
   body padding 强制归零避免某些子页 body 设定再次叠加。
   touch-action: manipulation 作为全站默认：禁掉双击缩放（子元素自己的
   pan-y / none 等声明照常收窄生效，不受影响）；双指捏合由 viewport meta +
   mobile-shell.js 的 gesture 事件守卫兜底。 */
html, body {
    margin: 0;
    padding: 0 !important;
    min-height: 100vh;
    min-height: 100dvh;
    background: var(--border);
    color: inherit;
    touch-action: manipulation;
}

/* 中央移动画布：固定 720px、垂直撑满；宽屏两侧留白
   .app-canvas / .app-root 都视为同一画布；
   只在画布自身保留底部 Tab 安全区（一次），body 不再加 padding。 */
.app-canvas,
.app-root {
    width: 100%;
    max-width: var(--canvas-w);
    margin: 0 auto;
    min-height: 100vh;
    min-height: 100dvh;
    background: #f7fafc;
    position: relative;
    padding-top: calc(env(safe-area-inset-top, 0px));
    padding-right: calc(env(safe-area-inset-right, 0px));
    padding-left: calc(env(safe-area-inset-left, 0px));
    padding-bottom: calc(var(--tab-h) + env(safe-area-inset-bottom, 0px));
    overflow-x: hidden;
}

/* ---------- 底部 Tab 栏（B 站移动端风格） ----------
   swipe-nav.js 会把 <nav class="bottom-tab-bar"> 注入 body 并切换 .active。
   固定五等分；多于 5 项时启用横向滚动作为兜底，避免页面横向溢出。 */
.bottom-tab-bar {
    position: fixed;
    bottom: 0;
    /* 画布固定 720 居中：tab 也只在居中 720 内 */
    left: 50%;
    transform: translateX(-50%);
    width: 100%;
    max-width: var(--canvas-w);
    z-index: 2900;
    height: calc(var(--tab-h) + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: rgba(255, 255, 255, 0.96);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    border-top: 1px solid rgba(0, 0, 0, 0.06);
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.04);
    display: flex;
    align-items: stretch;
    justify-content: flex-start;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
}
.bottom-tab-bar::-webkit-scrollbar { display: none; }

.bottom-tab-bar .tab {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    height: var(--tab-h);
    text-decoration: none;
    color: #888;
    font-size: 12px;
    line-height: 1.1;
    padding: 4px 2px;
    position: relative;
    transition: color 0.18s ease;
    -webkit-tap-highlight-color: transparent;
    box-sizing: border-box;
}
.bottom-tab-bar .tab:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
    border-radius: 6px;
}
.bottom-tab-bar .tab-icon {
    font-size: 21px;
    line-height: 1;
    transition: transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.bottom-tab-bar .tab-label {
    font-size: 12px;
    letter-spacing: 0.2px;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 0 2px;
    box-sizing: border-box;
}
.bottom-tab-bar .tab:active .tab-icon { transform: scale(0.95); }
.bottom-tab-bar .tab.active {
    color: var(--primary);
}
.bottom-tab-bar .tab.active .tab-icon {
    transform: translateY(-3px) scale(1.08);
}
.bottom-tab-bar .tab-dot {
    position: absolute;
    top: 4px;
    right: calc(50% - 18px);
    min-width: 16px;
    height: 16px;
    line-height: 16px;
    text-align: center;
    border-radius: 8px;
    background: #f5222d;
    color: #fff;
    font-size: 10px;
    padding: 0 4px;
    font-weight: 600;
    box-sizing: border-box;
    display: none;
}
.bottom-tab-bar .tab-dot.show { display: inline-block; }

/* 键盘或弹窗出现时，隐藏底部 Tab，避免遮挡 IME / 弹层。
   MobileShell.js 负责添加 .keyboard-open / .modal-open。 */
html.keyboard-open .bottom-tab-bar,
html.modal-open .bottom-tab-bar { display: none !important; }

/* ---------- 全局触摸控件基线 ----------
   覆盖独立 button / .btn / .icon button 与 form controls 等。
   让所有可点区域高度 ≥ 44，避免被现有页面的紧凑尺寸影响可达性。 */
button, .btn, .icon-btn, [role="button"] {
    min-height: 44px;
    padding-top: 0;
    padding-bottom: 0;
}
/* 触控元素禁止文本选择 + iOS 长按 callout：手指按在按钮/链接上时，
   iOS Safari 会把下方文本「选中」并涂上系统紫蓝色选择高亮（不是 tap
   highlight——那已在文件顶部全局关掉），视觉上像整个 DOM 被选中。
   正文内容（.giv-desc / .comment-content 等）不在此列，保持可复制；
   input / textarea / select 也不在此列，保持可编辑。 */
button, .btn, .icon-btn, [role="button"], a {
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
}
button:focus-visible, .btn:focus-visible, .icon-btn:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}
button:active:not(:disabled), .btn:active:not(:disabled) {
    transform: translateY(1px);
}
button:disabled, .btn:disabled, [aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
}
.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: none;
    background: transparent;
    border-radius: 50%;
    color: inherit;
    cursor: pointer;
}
.icon-btn:focus-visible { outline-offset: 2px; }

/* 输入控件：字号统一 16px（避免 iOS Safari 聚焦时放大页面） */
input, select, textarea, [contenteditable="true"] {
    font-size: 16px;
    line-height: 1.4;
}
input[type="checkbox"], input[type="radio"] {
    min-width: 22px;
    min-height: 22px;
}
input:not([type="checkbox"]):not([type="radio"]),
select,
textarea {
    min-height: 44px;
}
input:focus-visible, select:focus-visible, textarea:focus-visible,
[contenteditable="true"]:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 1px;
}

/* 滚动容器工具类：横向 / 纵向滚动 + iOS 动量 */
.scroll-x {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
}
.scroll-y {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* 全局动效偏好：尊重系统减弱动画设置 */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* ---------- 跨页 View Transitions（底部 Tab 切换：容器打开/关闭感） ----------
   底部 Tab 之间的「消息 / 社区 / 我的」是真实的跨页
   跳转，每次都白屏闪一下很扎眼。这里用浏览器原生 View Transitions 把同源
   nav 串成「一个全屏容器关闭 + 另一个全屏容器打开」的复合动效。

   关键：纯淡入淡出（root 整体 opacity 切两次）会有「先暗一下再亮一下」
   的违和感。本项目既有的 .std-modal / PlainView 用的是 translateY + opacity
   复合（见下文 .shell-enter / .shell-closing），过渡像容器被推上去 / 推上
   来。这里复用同款「14px 位移 + opacity」的物理感，让 Tab 切换和站内弹
   层保持视觉一致。底部 Tab 栏跨页稳定存在（不参与过渡），符合 iOS Tab
   栏「始终可见」的原则。

   @view-transition { navigation: auto } 启用跨文档快照；没配 view-transition-
   name 时浏览器用 ::view-transition-*(root) 默认配对。只动透明度与位移，
   不动几何与视口，遵循本文件 .std-modal / MobileShell 同款「只动 opacity/
   transform」安全策略。不支持的浏览器（Safari < 18 / Chrome < 111 / 老内核）
   自动降级为硬切，零错误。prefers-reduced-motion 由下方媒体查询 + 全局通配
   同时压平。 */
@view-transition {
    navigation: auto;
}
::view-transition-old(root) { animation: vtContainerOut 360ms cubic-bezier(0.4, 0, 0.2, 1) forwards; }
::view-transition-new(root) { animation: vtContainerIn 360ms cubic-bezier(0.4, 0, 0.2, 1) forwards; }
@keyframes vtContainerOut {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(-14px); }
}
@keyframes vtContainerIn {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    ::view-transition-old(root),
    ::view-transition-new(root),
    ::view-transition-group(root) {
        animation-duration: 0.001ms !important;
    }
}

/* ---------- 弹层开合淡入淡出（框架标准：stdModal 与 PlainView 两种容器共享） ----------
   open 时挂 .shell-enter 淡入；close 时挂 .shell-closing 淡出，动画结束才真正移除。
   只动 opacity——不碰几何与视口，真机 Safari 安全；
   「减弱动态效果」由上方全局媒体查询统一压平，JS 侧另有 matchMedia 直关兜底。 */
@keyframes shellFadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}
@keyframes shellFadeOut {
    from { opacity: 1; }
    to { opacity: 0; }
}
.shell-enter { animation: shellFadeIn .28s ease-out; }
.shell-closing {
    pointer-events: none;   /* 淡出过程中禁止误触内容 */
    animation: shellFadeOut .24s ease-in forwards;
}

/* ---------- 标准弹窗 std-modal（全屏 modal） ----------
   基础几何是纯 CSS：fixed inset:0 + height:100%，不读任何 JS 变量——
   Safari 视口值异常（刷新恢复滚动、事件缺失/滞留）都不可能把弹窗顶出屏幕。
   仅键盘确认打开期间，MobileShell.applyKeyboardGeometry 才以钳制后的内联
   top/height 做补偿，键盘收起即摘除。
   MobileShell.openOverlay / closeOverlay 会负责 aria/inert/焦点管理。 */
.std-modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    /* 4100 > .pv-overlay (PlainView = 4000)：PlainView 是栈式内容视图，会在已
       打开的 PlainView（用户主页 / 详情等）之上再点 stdModal 触发的功能，
       此时 stdModal 必须盖在 PlainView 上。同级 4000 时 PlainView 因
       DOM 后插入反而在上层，导致 stdModal 被 PlainView 盖在后面。 */
    z-index: 4100;
    display: none;
    justify-content: center;
    align-items: stretch;
    padding: 0;
}
.std-modal-overlay.active { display: flex; }
.std-modal {
    background: #fff;
    width: 100%;
    max-width: var(--canvas-w);
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
    border-radius: 0;
    /* 高度 = 弹窗外壳（= 布局视口，fixed inset:0 天然跟随 Safari 地址栏伸缩）。
       键盘打开时由 MobileShell 内联覆盖为 visualViewport.height（已收缩，
       绝不能再减 --keyboard-inset，否则键盘被扣两遍，弹窗只剩一条缝） */
    height: 100%;
    min-height: 0;
    padding-top: env(safe-area-inset-top, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    overflow: hidden;
    position: relative;
}
/* 沉浸类展示容器（deck / palette / minigames 各自的 boxClass
   均为 <name>-immersive）：外部 shell 统一铺满整个浏览器视口（PC/移动端一致），
   突破 .std-modal 的 max-width: var(--canvas-w)（720px 移动画布）。
   内部内容仍由各容器按固定比例居中 / 信箱，绝不拉伸变形——这里只改外壳几何。 */
.std-modal.deck-immersive,
.std-modal.plt-immersive,
.std-modal.mg-immersive,
.std-modal.htmlpage-immersive {
    max-width: none;
    width: 100%;
    box-shadow: none;
}
.std-modal-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 14px 16px 10px;
    flex: none;
}
.std-modal-header h3 {
    margin: 0;
    font-size: 1rem;
    color: #5a67d8;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.std-modal-close {
    flex: none;
    width: 44px;
    height: 44px;
    background: none;
    border: none;
    font-size: 1.4rem;
    line-height: 1;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.std-modal-close:hover { color: var(--text-2); background: var(--border-soft); }
.std-modal-close:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 1px;
}
.std-modal-body {
    padding: 0 16px 16px;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
    -webkit-overflow-scrolling: touch;
}
/* 标准窗口底部按钮条：框架按 def.actions 统一渲染（观感与各页 .modal-actions 一致） */
.std-modal-actions {
    flex: none;
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border-soft);
    background: #fff;
}
.std-modal-actions button {
    background: #667eea;
    color: #fff;
    border: none;
    padding: 8px 16px;
    border-radius: 6px;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    min-height: 44px;
    transition: background 0.2s;
}
.std-modal-actions button:hover {
    background: #5a67d8;
}
.std-modal-actions button:disabled {
    opacity: 0.6;
    cursor: default;
}
.std-modal-actions button[data-kind="secondary"] {
    background: var(--border);
    color: var(--text-1);
}
.std-modal-actions button[data-kind="secondary"]:hover {
    background: #cbd5e0;
}
.std-modal-actions button[data-kind="danger"] {
    background: #fc8181;
    color: #fff;
}
.std-modal-actions button[data-kind="danger"]:hover {
    background: #f56565;
}

/* 历史页面自带的 .modal-overlay 也走统一全屏规则（现主要由 PlainView/stdModal 承载弹层） */
.modal-overlay {
    position: fixed;
    /* 同 .std-modal-overlay：基础几何纯 CSS 贴屏，键盘补偿由 MobileShell 内联下发 */
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    /* 同 .std-modal-overlay：4100 > PlainView，避免被已开的 PlainView 盖住 */
    z-index: 4100;
    display: none;
    justify-content: center;
    align-items: stretch;
    padding: 0;
}
.modal-overlay.active { display: flex; }
.modal-overlay > .modal {
    background: #fff;
    width: 100%;
    max-width: var(--canvas-w);
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
    border-radius: 0;
    /* 同 .std-modal：高度 = 弹窗外壳；键盘打开时由 MobileShell 内联覆盖（勿再减 inset） */
    height: 100%;
    min-height: 0;
    padding-top: env(safe-area-inset-top, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    overflow: hidden;
    position: relative;
}
.modal-overlay > .modal > h3,
.modal-overlay > .modal > .modal-header {
    flex: none;
    margin: 0;
    padding: 14px 16px 10px;
    font-size: 1rem;
    color: #5a67d8;
}
.modal-overlay > .modal form,
.modal-overlay > .modal > form,
.modal-overlay > .modal > .modal-body,
.modal-overlay > .modal > div:not(h3):not(.modal-header):not(.modal-actions) {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 0 16px 16px;
}
.modal-overlay > .modal .modal-actions {
    flex: none;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border-soft);
    background: #fff;
}

/* ---------- MobileShell 注入：confirm overlay + toast/status ---------- */
.ms-confirm-overlay {
    position: fixed;
    /* 同 .std-modal-overlay：基础几何纯 CSS 贴屏，键盘补偿由 MobileShell 内联下发 */
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 4100;
    background: rgba(0, 0, 0, 0.5);
    display: none;
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.ms-confirm-overlay.active { display: flex; }
.ms-confirm {
    background: #fff;
    border-radius: 14px;
    width: 100%;
    max-width: 420px;
    max-height: 80vh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}
.ms-confirm-title {
    padding: 16px 18px 4px;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--text-1);
}
.ms-confirm-title:empty { display: none; }
.ms-confirm-message {
    padding: 6px 18px 16px;
    font-size: 0.95rem;
    color: var(--text-2);
    line-height: 1.5;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
.ms-confirm-actions {
    display: flex;
    gap: 8px;
    padding: 0 14px 14px;
    justify-content: flex-end;
    flex-wrap: wrap;
}
.ms-confirm-actions button {
    flex: 1 1 0;
    min-width: 96px;
    min-height: 44px;
    padding: 0 14px;
    border-radius: 10px;
    border: 1px solid transparent;
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    background: var(--border-soft);
    color: var(--text-1);
}
.ms-confirm-actions button.ms-confirm-cancel:focus-visible,
.ms-confirm-actions button.ms-confirm-ok:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}
.ms-confirm-actions button.ms-confirm-ok {
    background: var(--primary);
    color: #fff;
}
.ms-confirm-actions button.ms-confirm-ok.danger {
    background: #f5222d;
}

/* 底部 toast（MobileShell.notify 注入 #ms-toast-region；plan25 P0-B 恢复）：
   auth.html 有一份同步副本供独立登录页兜底，改动需保持两处一致 */
.ms-toast-region {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    z-index: 4200;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
    width: min(420px, calc(100vw - 32px));
}
html.modal-open .ms-toast-region {
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
}
.ms-toast {
    background: rgba(45, 55, 72, 0.94);
    color: #fff;
    padding: 10px 14px;
    border-radius: 10px;
    font-size: 0.9rem;
    line-height: 1.4;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
    pointer-events: auto;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.18s ease, transform 0.18s ease;
}
.ms-toast.show { opacity: 1; transform: translateY(0); }
.ms-toast.success { background: rgba(56, 161, 105, 0.95); }
.ms-toast.error { background: rgba(245, 34, 45, 0.95); }
.ms-toast.info { background: rgba(74, 144, 217, 0.95); }

/* 全站锁定滚动：MobileShell.lockScroll() 期间 body 不可滚 */
html.ms-locked, html.ms-locked body {
    overflow: hidden !important;
    touch-action: none;
}

/* 顶部导航（authBar）：移动端专用方案下永远不显示 */
html #authBar { display: none !important; }