:root {
    --bg: #ffffff;
    --bg-elevated: #f2f2f2;
    --bg-hover: #e5e5e5;
    --text: #0f0f0f;
    --text-secondary: #606060;
    --border: #e0e0e0;
    --card-radius: 12px;

    /* ===== 全站统一按钮色 =====
       前台后台共用同一套（原来是前台 YouTube 红 + 后台 Google Blue 两套）：
       淡蓝底 + 深蓝字，悬停/按下各深一档。#174ea6 on #e8f0fe 对比度 6.9:1 */
    --btn-bg: #e8f0fe;
    --btn-bg-hover: #d2e3fc;
    --btn-bg-active: #c3d9fb;
    --btn-fg: #174ea6;

    /* ===== 后台 / Material 设计 token =====
       颜色必须走变量，不要在页面里写死色值。
       --brand 只用于链接/聚焦环/选中文字这类非按钮的蓝；
       红色只留给错误提示与危险图标（--danger），按钮一律不用红。 */
    --surface: #ffffff;                 /* 卡片 / 面板底色 */
    --admin-bg: #f7f7f8;                /* 后台页面底色（grey 50） */
    --brand: #1a73e8;                   /* Google Blue 600：链接 / 聚焦环 / 选中文字 */
    --brand-ring: rgba(26, 115, 232, .14);
    --danger: #d93025;                  /* 错误提示 / 危险图标 */
    --text-strong: #202124;             /* grey 900：标题与正文 */
    --text-muted: #5f6368;              /* grey 600：表头与次级信息 */
    --text-subtle: #757575;             /* 提示文字：原 #80868b 在白底只有 3.4:1，压到 4.6:1 才够 AA */
    --placeholder: #767676;             /* 占位符：原 #9aa0a6 仅 2.8:1，且占位符常承载填写说明 */
    --outline: rgba(0, 0, 0, .12);      /* 分割线 */
    --outline-input: #dadce0;           /* 输入框描边 */
    --outline-input-hover: #9aa0a6;
    --state-hover: rgba(0, 0, 0, .06);  /* state layer：悬停叠加 */
    --state-press: rgba(0, 0, 0, .10);  /* state layer：按下叠加 */
    --bg-active: #d5d5d5;               /* 中性按钮按下态：比 --bg-hover(#e5e5e5) 再深一档 */
    --elevation-1: 0 1px 2px rgba(0, 0, 0, .08), 0 1px 3px rgba(0, 0, 0, .06);
    --elevation-2: 0 1px 3px rgba(0, 0, 0, .12), 0 8px 24px rgba(0, 0, 0, .08);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
    font-family: 'Roboto', 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
    background: var(--bg);
    color: var(--text);
    line-height: 1.6;
}

a { color: inherit; text-decoration: none; }

/* ===== 通用 SVG 图标 ===== */
.icon {
    width: 18px;
    height: 18px;
    fill: currentColor;
    flex-shrink: 0;
}
.icon-sm { width: 16px; height: 16px; }

/* ===== 顶部导航 ===== */
/* 单行 flex：左区（汉堡 + Logo）与右区（操作按钮）按内容宽度占位、不压缩，
   搜索框吃掉剩余空间（.search-field 自身 cap 在 640px），空间不够时先缩搜索框。
   搜索框在「左右两区之间」的剩余空间里居中 —— 与 YouTube masthead 一致，
   不再强求相对整页居中（那要求左右列等宽，正是下面这个老 bug 的来源）。
   原实现是三列 grid：minmax(88px,1fr) minmax(0,680px) minmax(88px,1fr)。
   实测 w=901 轨道为 88px|645px|88px、w=1024 为 132px|680px|132px —— 中间列先吃满
   680px，剩下的才平分给左右，Logo 列因此被压到站点名只剩 19px 宽；
   而 ≤900px 的窄屏覆盖又用 flex:none 让站点名完整显示，于是同一个站点名
   在 901~1150px 被截断、701~900px 却完整 —— 表现随宽度反复横跳。
   统一成 flex 后只剩一套规则：Logo 永不压缩，站点名要么完整，
   要么由 ≤700px 的媒体查询整体隐藏，不再有"某些宽度截断某些宽度完整"。 */
.topbar {
    position: sticky;
    top: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 0 24px;
    height: 56px;
    /* YouTube 风格毛玻璃：半透明白底 + 背景模糊，滚动时内容透出磨砂感 */
    background: rgba(255, 255, 255, 0.72);
    -webkit-backdrop-filter: blur(18px) saturate(160%);
    backdrop-filter: blur(18px) saturate(160%);
    border-bottom: 1px solid rgba(224, 224, 224, 0.55);
}
/* 不支持 backdrop-filter 的老浏览器回退为纯白底 */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    .topbar { background: #ffffff; }
}
/* 前台顶栏（.topbar-main）用三栏网格 minmax(0,1fr) minmax(0,2fr) minmax(0,1fr)：
   左右两栏永远等宽、中间 2 倍宽放搜索框；两侧 minmax(0,..) 允许窄屏收缩、
   Logo 超宽时走省略号、不会把列撑宽 —— 因此「搜索框」在任意宽度、有无「后台」按钮时
   都精确水平居中（自适应）。后台顶栏（.admin-nav .topbar）不套此规则，保持原 flex 布局。 */
.topbar-main {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr);
}
.logo {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 20px;
    font-weight: 700;
    white-space: nowrap;
    color: var(--text);
    /* 永不压缩：站点名是否可见只由「放不放得下」决定 ——
       放得下就完整显示（超长名字再由 .logo-name 的 max-width 兜底省略），
       放不下就交给 ≤700px 的媒体查询整体隐藏，不再出现半截省略号 */
    flex: none;
    overflow: hidden;
}
.logo .logo-badge {
    width: 32px;
    height: 32px;
    display: block;
    flex: none;
    /* 默认 SVG 图标是正方形，32×32 正好；换成用户上传的横版图片时，
       contain 让它等比缩放，不会被 32×32 的方框压扁。 */
    object-fit: contain;
}
.logo img {
    height: 32px;
    max-width: 160px;
    object-fit: contain;
}
.logo .logo-name {
    font-size: 20px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 180px;
    min-width: 0;
}
.topbar .spacer { flex: 1; }
.topbar-actions { display: flex; align-items: center; gap: 12px; min-width: 0; justify-content: flex-end; }
/* 国家缩写角标：无胶囊、无边框的纯文本（YouTube 风格），位于标题右上角。
   采用流式排布（排在标题右侧），不与标题文字重叠；内容由 geoip.js 填充 */
.geo-badge {
    display: inline-block;
    align-self: flex-start;
    margin-top: 5px;
    margin-left: -4px;
    font-size: 10px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: .5px;
    color: var(--text-secondary);
    text-transform: uppercase;
    user-select: none;
}
.geo-badge[hidden] { display: none; }

/* ===== 顶部搜索框（YouTube 风格，水平居中，一体式胶囊） ===== */
.search-box {
    min-width: 0;               /* 允许在窄屏收缩，避免溢出 */
    display: flex;
    align-items: center;
    justify-content: center;    /* 搜索框在中间栏内水平居中 */
    padding: 0 20px;
}
.search-field {
    width: 100%;
    max-width: 640px;
    height: 40px;
    display: flex;
    align-items: center;
    padding: 0 6px 0 16px;
    background: #f1f1f1;
    border-radius: 20px;
    overflow: hidden;
    transition: background .15s;
}
.search-box:focus-within .search-field {
    background: #fff;
    box-shadow: inset 0 0 0 1px #0f0f0f;
}
.search-field input[type=text] {
    flex: 1;
    min-width: 0;
    height: 100%;
    width: auto;
    padding: 0;
    margin: 0;
    border: 0;
    border-radius: 0;
    outline: 0;
    background: transparent;
    box-shadow: none;
    -webkit-appearance: none;
    appearance: none;
    font-size: 15px;
    color: var(--text);
}
.search-field input[type=text]::placeholder { color: var(--text-secondary); }
.search-field input[type=text]:focus {
    border-color: transparent;
    box-shadow: none;
}
.search-field .search-btn {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border: 0;
    outline: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .15s;
}
.search-field .search-btn:hover { background: rgba(0, 0, 0, .08); }
.search-field .search-btn .icon { width: 20px; height: 20px; }

/* 居中由 .topbar-main 的三栏网格统一处理，所有宽度自适应，无需按断点切换 */

/* ===== 按钮（YouTube 设计规范） =====
 * 标准按钮：高 36px / 全圆角 18px / Roboto 14px Medium / 水平内边距 16px
 * 紧凑按钮：高 32px / 圆角 16px
 * 大按钮：高 40px / 圆角 20px
 */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 36px;
    padding: 0 16px;
    border-radius: 18px;
    font-size: 14px;
    font-weight: 500;
    line-height: 1;
    border: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background .15s;
    background: var(--bg-elevated);
    color: var(--text);
}
.btn:hover { background: var(--bg-hover); }
/* 按压要比悬停再深一档，否则点下去没有任何"已按下"的反馈 */
.btn:active { background: var(--bg-active); }
/* 焦点圈统一走 --brand：全站其它可点元素（.chip-act/.nav-toggle/.sn-item/.bb-item）
   都是这个色，前台红/后台蓝的按钮混用两套焦点色看着像两个系统 */
.btn:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}
/* 主操作按钮：全站唯一一种「有颜色」的按钮 —— 淡蓝底 + 深蓝字。
   前台后台共用同一套（原来前台是 YouTube 红、后台是 Google Blue，两套色互不相干）。
   .btn-primary 与 .btn-brand 保留为两个类名，只是历史命名，配色已统一。 */
.btn-primary,
.btn-brand { background: var(--btn-bg); color: var(--btn-fg); }
.btn-primary:hover,
.btn-brand:hover { background: var(--btn-bg-hover); }
.btn-primary:active,
.btn-brand:active { background: var(--btn-bg-active); }
/* 紧凑按钮：表格行内操作、次要操作 */
.btn-sm {
    height: 32px;
    padding: 0 12px;
    border-radius: 16px;
    font-size: 13px;
}
/* 大按钮：登录、主要 CTA */
.btn-lg {
    height: 40px;
    padding: 0 20px;
    border-radius: 20px;
    font-size: 15px;
}

/* ===== 内容区 ===== */
.container {
    /* 参考 YouTube 主页：内容区随视口放宽到 1680，宽屏不再被 1280 卡住 */
    max-width: 1680px;
    margin: 0 auto;
    padding: 24px;
}
/* 静态站首页 h1：仅供搜索引擎识别页面主题，视觉上不占版面（无障碍/SEO 通用做法） */
.static-hero {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.section-title {
    font-size: 18px;
    font-weight: 700;
    margin-bottom: 16px;
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--text);
}
.video-grid {
    display: grid;
    /* YouTube 风格：一行最多 3 个；窗口较窄时由下方媒体查询自动降为 2/1 列，
       避免卡片被多列挤小 */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    /* 卡片自带 8px 内边距，这里收窄 gap，保证最终视觉间距不变（纵向 8+16=24，横向 0+16=16） */
    gap: 8px 0;
}

/* ===== 视频卡片 ===== */
/* YouTube 风格完整卡片：hover 不做位移悬浮，也不画描边线，
   用"整卡圆角淡底 + 极轻浮影"柔和亮起标注状态（对齐 YouTube 主页 hover 观感）。
   过渡拉长到 .4s 并配 Material 缓动：淡入与移出都像呼吸般渐显渐隐，避免 0.15s
   的生硬闪现；淡底半透明，hover 层次通透、不"啪"地糊一整块 */
.video-card {
    cursor: pointer;
    display: block;
    border-radius: var(--card-radius);
    padding: 8px;
    /* 1px 透明边框仅作布局占位（hover 不出现描边线），避免显示边框导致跳动 */
    border: 1px solid transparent;
    transition:
        background-color .4s cubic-bezier(.4, 0, .2, 1),
        box-shadow .4s cubic-bezier(.4, 0, .2, 1);
}
.video-card:hover {
    /* YouTube 风格：不加描边线；整卡用不透明实色灰(#f2f2f2)亮起，
       与纯白页面有明确边界对比，比半透明白灰清晰得多 */
    background-color: var(--bg-elevated);
    box-shadow: 0 1px 3px rgba(0, 0, 0, .03), 0 8px 20px rgba(0, 0, 0, .04);
}
.thumb {
    position: relative;
    aspect-ratio: 16/9;
    border-radius: var(--card-radius);
    overflow: hidden;
    background: var(--bg-elevated);
    margin-bottom: 10px;
}
.video-card .thumb img {
    /* 图片放大与卡片淡底同一节奏，避免画面"快动作"感 */
    transition: transform .4s cubic-bezier(.4, 0, .2, 1);
}
.video-card:hover .thumb img {
    transform: scale(1.06);
}
.thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.thumb .duration {
    position: absolute;
    right: 8px;
    bottom: 8px;
    padding: 2px 6px;
    border-radius: 4px;
    background: rgba(0,0,0,.8);
    color: #fff;
    font-size: 12px;
    font-weight: 500;
}
.thumb .views-badge {
    position: absolute;
    left: 8px;
    top: 8px;
    padding: 2px 8px;
    border-radius: 4px;
    background: rgba(0,0,0,.65);
    font-size: 11px;
    color: #fff;
}
.video-meta { display: flex; gap: 12px; }
.avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    flex-shrink: 0;
    object-fit: cover;
    background: var(--bg-elevated);
}
.video-info { min-width: 0; }
.video-title {
    font-size: 16px;
    font-weight: 600;
    line-height: 1.4;
    margin: 0 0 4px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    color: var(--text);
}
.video-channel {
    font-size: 13px;
    line-height: 1.4;
    color: var(--text-secondary);
}
/* 观看次数 · 发布时间（YouTube 元信息行） */
.video-stats {
    font-size: 13px;
    line-height: 1.4;
    color: var(--text-secondary);
    margin-top: 2px;
}
.empty-tip {
    text-align: center;
    padding: 80px 20px;
    color: var(--text-secondary);
}
.empty-tip .empty-icon {
    width: 56px;
    height: 56px;
    fill: #c4c4c4;
    margin-bottom: 12px;
}

/* ===== 播放页 ===== */
.watch-layout {
    display: grid;
    /* YouTube 观看页布局：主栏播放器限宽上限(1080)以免超大屏把标题挤出首屏、
       也让播放器与右侧栏比例协调；右栏固定 400（YouTube secondary≈402）。
       两列间距恒定 24px，播放器始终占满主栏列宽、不产生侧边空隙。
       总宽不足容器时靠 justify-content:center 整体居中，两侧留白对称 */
    grid-template-columns: minmax(0, 1080px) 400px;
    justify-content: center;
    gap: 24px;
    align-items: start;
}
.watch-main { min-width: 0; }
.player-box {
    aspect-ratio: 16/9;
    background: #000;
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 16px;
}
.player-frame {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    background: #000;
}
.player-empty {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 16px;
}
.watch-title {
    font-size: 20px;
    font-weight: 700;
    margin-bottom: 10px;
    color: var(--text);
}
.watch-meta-row {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 16px;
    font-size: 14px;
    color: var(--text-secondary);
}
.meta-item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}
.watch-desc {
    background: var(--bg-elevated);
    border-radius: var(--card-radius);
    padding: 16px;
    font-size: 14px;
    white-space: pre-wrap;
    margin-bottom: 20px;
    color: var(--text);
}

/* 侧边推荐 */
.side-title {
    font-size: 15px;
    font-weight: 700;
    margin-bottom: 12px;
    color: var(--text);
}
.rec-item {
    display: flex;
    /* YouTube 紧凑卡片：缩略图 168 宽、与文字间距 12，栏目整体更大更有存在感 */
    gap: 12px;
    padding: 8px;
    margin: 0 -8px;
    border-radius: 8px;
}
.rec-item:hover { background: var(--bg-elevated); }
.rec-thumb {
    width: 168px;
    aspect-ratio: 16/9;
    border-radius: 12px;
    overflow: hidden;
    flex-shrink: 0;
    background: var(--bg-elevated);
}
.rec-thumb img { width: 100%; height: 100%; object-fit: cover; }
.rec-info { min-width: 0; }
.rec-title {
    font-size: 14px;
    font-weight: 500;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    color: var(--text);
}
.rec-meta { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }

/* ===== 后台 ===== */
.admin-body { background: var(--admin-bg); color: var(--text-strong); }
.admin-nav {
    background: var(--surface);
    border-bottom: 1px solid var(--outline);
}
.admin-nav .topbar { border-bottom: none; }
/* 导航项：默认透明底 + 次级文字色；激活项用 secondary-container 蓝底 + 主色文字 */
.admin-nav .nav-btn {
    background: transparent;
    color: var(--text-muted);
    transition: background-color .15s ease, color .15s ease;
}
.admin-nav .nav-btn:hover { background: var(--state-hover); color: var(--text-strong); }
.admin-nav .nav-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.admin-nav .nav-btn.is-active {
    background: rgba(26, 115, 232, .12);
    color: var(--brand);
    font-weight: 500;
}
.admin-container {
    max-width: 1080px;
    margin: 0 auto;
    padding: 24px;
}
.admin-card {
    background: var(--surface);
    border-radius: var(--card-radius);
    padding: 24px;
    box-shadow: var(--elevation-1);
    margin-bottom: 20px;
}
.admin-card h2 {
    font-size: 18px;
    font-weight: 600;
    margin-bottom: 16px;
    color: var(--text-strong);
    letter-spacing: -0.1px;
}
/* 卡片头部：标题 + 右侧操作同行，窄屏自动换行（替代各处内联 flex 样式） */
.admin-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 16px;
}
.admin-head h2 { margin-bottom: 0; }
/* 次级说明行：统计、辅助信息统一 13px grey 600 */
.admin-sub {
    font-size: 13px;
    color: var(--text-muted);
    margin-bottom: 16px;
}
/* 空状态：列表 / 表格无数据时 */
.empty-state {
    text-align: center;
    padding: 64px 20px;
    color: var(--text-subtle);
}
.empty-state svg { width: 48px; height: 48px; fill: var(--outline-input); margin-bottom: 12px; }
.empty-state .empty-sub { margin-top: 8px; font-size: 13px; }
/* 行标签ellipsis 与第二行说明（列表元信息） */
.admin-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* 后台导航右侧的当前登录用户名 */
.nav-user { font-size: 13px; color: var(--text-muted); }
/* 部署日志面板 */
.log-panel {
    margin-top: 20px;
    background: var(--bg-elevated);
    border: 1px solid var(--outline);
    border-radius: 8px;
    padding: 14px 16px;
}
.log-panel h3 { font-size: 13px; font-weight: 600; color: var(--text-strong); margin-bottom: 8px; }
.log-line { font-size: 13px; line-height: 1.9; color: var(--text-strong); word-break: break-all; }
.admin-sub.mt { margin-top: 12px; }
/* 表单字段（Material outlined text field：40px 高 / 8px 圆角 / 主色聚焦） */
.form-group { margin-bottom: 18px; }
.form-group label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 6px;
    color: var(--text-strong);
}
.form-group .hint { font-size: 12px; line-height: 1.6; color: var(--text-subtle); margin-top: 4px; }
/* 卡片级别的说明段（不在 .form-group 里，如 <p class="hint">）。
   之前只有 .form-group .hint 这一条规则，卡片级 .hint 完全没样式，
   会以 16px 正文色渲染，看起来像漏了样式。 */
.hint { font-size: 13px; line-height: 1.7; color: var(--text-subtle); }
input[type=text], input[type=password], input[type=url], input[type=number], textarea, select {
    width: 100%;
    height: 40px;
    padding: 0 12px;
    border: 1px solid var(--outline-input);
    border-radius: 8px;
    font-size: 14px;
    line-height: 1.5;
    background: var(--surface);
    color: var(--text-strong);
    font-family: inherit;
    transition: border-color .15s ease, box-shadow .15s ease;
}
/* 多行文本域：高度随内容，不套用单行输入框的高度与行高 */
textarea {
    height: auto;
    min-height: 120px;
    padding: 10px 12px;
    line-height: 1.6;
    resize: vertical;
}
input::placeholder, textarea::placeholder { color: var(--placeholder); }
/* 悬停：只轻微加深边框（等价 state layer，不产生位移） */
input[type=text]:hover, input[type=password]:hover, input[type=url]:hover,
input[type=number]:hover, textarea:hover, select:hover {
    border-color: var(--outline-input-hover);
}
/* 聚焦：主色边框 + 2px 柔和光圈（后台用 Google Blue，不用前台的红色强调） */
input:focus, textarea:focus, select:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 2px var(--brand-ring);
}
input[type=file] {
    font-size: 13px;
    color: var(--text-muted);
}
/* 上传按钮也做成胶囊次按钮，避免浏览器默认样式破坏整体节奏 */
input[type=file]::file-selector-button {
    height: 32px;
    margin-right: 12px;
    padding: 0 14px;
    border: 0;
    border-radius: 16px;
    background: var(--state-hover);
    color: var(--text-strong);
    font-family: inherit;
    font-size: 13px;
    cursor: pointer;
    transition: background-color .15s ease;
}
input[type=file]::file-selector-button:hover { background: var(--state-press); }
/* 表单中的图片预览 */
.form-preview {
    display: block;
    margin-bottom: 10px;
    max-width: 280px;
    border-radius: 8px;
    background: var(--bg-elevated);
}
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 720px) { .form-row { grid-template-columns: 1fr; } }
/* 表单底部的操作行：主操作 + 次要操作（取消/返回） */
.form-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
/* 勾选项整体的标签行（label 直接包住 checkbox 的写法）
   注意：必须写成 `.form-group label.form-checkbox`。
   上方 `.form-group label` 的选择器优先级是 (0,1,1)，而单写 `.form-checkbox` 只有 (0,1,0)，
   会输掉 display 的争夺 —— 结果是 label 被压成 block，align-items:center 失效，
   16px 的方框落在文字基线上，视觉上比右侧文字偏高约 2px。
   因此这里提高优先级，并把 line-height 归一到 1，让方框与文字严格垂直居中。 */
.form-group label.form-checkbox {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    color: var(--text-strong);
    margin-bottom: 6px;
    cursor: pointer;
}
.form-group label.form-checkbox input[type=checkbox] {
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: var(--brand);
    flex: none;
}
/* 站点 Logo 预览：固定高度的小图，区别于普通封面预览。
   object-fit:contain 不可省 —— 用户上传的 Logo 多为横版（如 300×80），
   默认的 object-fit:fill 会把它按 44px 高的方框强行拉伸，看起来就是「图片显示错了」。 */
.form-preview--logo {
    max-width: none;
    width: auto;
    height: 44px;
    object-fit: contain;
    border-radius: 6px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
}

/* 后台表格（Material data table：表头 48 / 数据行 52，1px 分割线，悬停 state layer） */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.data-table {
    width: 100%;
    min-width: 760px;   /* 窄屏交由外层横向滚动承接，不撑破布局 */
    border-collapse: collapse;
}
.data-table th {
    text-align: left;
    height: 48px;
    padding: 0 16px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--text-muted);
    border-bottom: 1px solid var(--outline);
    white-space: nowrap;
}
.data-table td {
    height: 52px;
    padding: 0 16px;
    font-size: 14px;
    vertical-align: middle;
    color: var(--text-strong);
    border-bottom: 1px solid rgba(0, 0, 0, .06);
}
/* 行不做悬停变色：整行本身不可点，加灰底反而让人以为整行能点，
   鼠标扫过列表时整条灰带也很晃眼。可点击的反馈交给行内 .chip-act 按钮
   （悬停/按压各有一层），作用范围小、指向更准。 */
.data-table tbody tr:last-child td { border-bottom: 0; }
.table-thumb {
    width: 100px;
    aspect-ratio: 16/9;
    border-radius: 6px;
    object-fit: cover;
    display: block;
}
/* 单元格宽度：表格是 auto 布局，列宽必须用 width 约束，
   只写 max-width 会被长内容顶开，进而挤窄"操作"列导致按钮换行 */
.cell-title {
    width: 260px;
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* 次级文字（时间等短文本） */
.cell-muted { font-size: 12px; color: var(--text-subtle); }
/* 视频链接：固定列宽 + 允许断行，避免把操作列挤掉 */
.cell-link {
    width: 220px;
    font-size: 12px;
    color: var(--text-subtle);
    word-break: break-all;
}
/* 行内操作按钮（Material filled button 小型：<a> 与 <button> 共用一套，
   保证列表行里两种写法视觉完全一致）。
   底色/字色走全站统一的淡蓝按钮 token —— 顺带修掉一个老 bug：
   基础样式原来只写了 color:#fff 却不给背景色，「查看」就成了白字白底、在白色卡片上完全看不见。 */
/* 行内操作：始终单行排布（表格布局下被挤压时也不允许换行） */
.row-actions { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
/* 删除按钮外层是 POST 表单，去掉它自带的块级表现与外边距 */
.row-actions form { margin: 0; display: inline-flex; }
.chip-act {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    padding: 0 14px;
    border: 0;
    border-radius: 16px;
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    background: var(--btn-bg);
    color: var(--btn-fg);
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color .15s ease, box-shadow .15s ease;
}
.chip-act:hover { background: var(--btn-bg-hover); }
.chip-act:active { background: var(--btn-bg-active); }
.chip-act:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* .chip-act--edit / --del 仍留在 HTML 里做语义钩子，但配色已统一：
   全站按钮只用一种淡蓝，破坏性操作靠按钮文字（"删除"）与二次确认弹窗表达。
   原来的修饰符（--edit 蓝底白字、--del 红底白字）已删除。 */

/* 登录页（Google 账号登录卡原型：居中卡片 + elevation-2 + 主按钮全宽，
   按钮沿用 .btn 的全圆角与间距，不另做方角，避免与全站按钮语言冲突） */
.login-body {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: var(--admin-bg);
}
.login-box {
    width: 100%;
    max-width: 400px;
    background: var(--surface);
    border-radius: var(--card-radius);
    padding: 40px 32px;
    box-shadow: var(--elevation-2);
    text-align: center;
}
/* 表单内容左对齐：输入框文字居中不符合表单规范 */
.login-box .form-group,
.login-box .form-group label,
.login-box input {
    text-align: left;
}
.login-box .login-logo {
    width: 56px;
    height: 56px;
    /* 图标类 Logo 是方形，用 56×56 正好；但用户也可能传横版图片，
       object-fit:contain 让非方形图等比缩放居中，不会被压扁。 */
    object-fit: contain;
    margin: 0 auto 16px;
    display: block;
}
.login-box h1 {
    font-size: 24px;
    font-weight: 500;
    letter-spacing: -0.2px;
    margin-bottom: 6px;
    color: var(--text-strong);
}
.login-box .sub {
    color: var(--text-muted);
    font-size: 14px;
    margin-bottom: 28px;
}
.login-box .btn-brand { width: 100%; margin-top: 8px; }
/* 提示条（Material banner：12px 圆角、语义色背景 + 同色系文字，不用重描边）
 *
 * 注意这里的 display:block，不是 flex。
 * 早期写成 display:flex 时，条内的每一个 <code>/<b> 甚至纯文本节点都会被当成独立
 * 的 flex item，于是「一句话里夹着几个 <code>」的提示条会被竖向切成好几列，
 * 文字错乱到读不成句（见 IndexNow 卡的本地地址告警）。
 * 提示条本来也不需要多列布局（要放图标的话，图标用 float / position 即可），故用 block。 */
.alert {
    display: block;
    padding: 12px 14px;
    border-radius: var(--card-radius);
    font-size: 13px;
    line-height: 1.6;
    margin-bottom: 16px;
    text-align: left;
}
/* 条内代码片段：略微加深底色，避免和正文糊在一起 */
.alert code {
    padding: 1px 5px;
    border-radius: 4px;
    background: rgba(0, 0, 0, .06);
    font-size: .92em;
}
.alert-error { background: #fce8e6; color: #c5221f; }
.alert-success { background: #e6f4ea; color: #137333; }
.alert-info { background: #e8f0fe; color: #1967d2; }
.alert a { color: inherit; text-decoration: underline; }
/* 兼容旧写法：条内首个 strong 仍当小标题渲染（原来是 flex item 自然成了块） */
.alert > strong:first-child { display: block; margin-bottom: 2px; }

/* 响应式 */
@media (max-width: 900px) {
    .watch-layout { grid-template-columns: 1fr; }
    .video-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 540px) {
    .video-grid { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
    .topbar { padding: 0 12px; gap: 10px; }
    .search-field { padding-left: 12px; }
    .logo .logo-name { display: none; }
    /* 窄屏顶部空间紧张，隐藏位置徽标，保持与 YouTube 移动端一致 */
    .geo-badge { display: none; }
    /* 后台窄屏：留白收窄，避免卡片贴边 */
    .admin-container { padding: 16px; }
    .admin-card { padding: 16px; }
}

/* ============================================================
 * 网页版确认弹框（Material basic dialog）
 * 结构由 admin/_footer.php 输出（cbConfirm / cbAsk / cbAskSubmit），
 * 样式统一收在这里，页面内不再写内联 <style>
 * ============================================================ */
@keyframes cbPop {
    from { opacity: 0; transform: scale(.96) translateY(6px); }
    to   { opacity: 1; transform: none; }
}
.cb-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .4);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    padding: 16px;
}
.cb-overlay[hidden] { display: none; }
.cb-dialog {
    background: var(--surface);
    border-radius: var(--card-radius);
    max-width: 400px;
    width: 100%;
    box-shadow: var(--elevation-2);
    padding: 24px;
    animation: cbPop .16s ease;
}
.cb-dialog-icon {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: #fce8e6;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 16px;
}
.cb-dialog-icon svg { width: 24px; height: 24px; fill: var(--danger); }
.cb-dialog-msg {
    text-align: center;
    font-size: 14px;
    line-height: 1.7;
    color: var(--text-strong);
    margin: 0;
    word-break: break-all;
}
.cb-dialog-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 24px; }
/* 确认弹窗的「确定」按钮同样走统一的淡蓝按钮色：红色已从按钮体系移除，
   危险语义由弹窗里的警告图标 + 提示文字承担（JS 仍会加 cb-ok-danger 类，作为语义钩子保留） */

/* ============================================================
 * 应用外壳：顶栏左侧（汉堡 + Logo） + 全局侧边栏
 * ============================================================ */
/* 顶栏左区（汉堡 + Logo）：不压缩，按内容宽度占位，是搜索框的固定邻居。
   对齐基准与 YouTube 一致 —— 汉堡「中心」和侧栏图标列「中心」同轴，Logo 左缘正好压在侧栏右边缘：
     · 侧栏 72px 宽、左右内边距 4px、条目 64px → 图标列中心 = 4 + 64/2 = 36px
     · 汉堡 40px，整组左移 8px → 中心 = 24(顶栏内边距) - 8 + 20 = 36px  ✔ 与图标列同轴
     · 汉堡与 Logo 间距 16px → Logo 左缘 = 16 + 40 + 16 = 72px  ✔ 与侧栏右边缘齐平
   用负外边距而不是把顶栏左内边距改成 16px：右内边距保持 24px，左右留白仍对称。 */
.topbar-left {
    display: flex;
    align-items: center;
    gap: 16px;
    flex: none;
    margin-left: -8px;
    min-width: 0;              /* 网格左列可收缩，Logo 超宽走省略号而非撑宽列 */
}
/* 只在 ≥901px 左移 8px：此时侧栏是 72px 常驻窄栏，汉堡必须与图标列同轴（见上）。
   ≤900px 侧栏变抽屉、不再有"图标列"，左区就正常吃顶栏内边距，
   免得窄屏（内边距收到 12px）时左边只剩 4px 而右边还有 12px，左右不对称 */
@media (max-width: 900px) {
    .topbar-left { margin-left: 0; }
    .topbar-actions { margin-right: 0; }
}
.nav-toggle {
    width: 40px;
    height: 40px;
    flex: none;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color .15s ease;
}
.nav-toggle:hover { background: var(--state-hover); }
.nav-toggle:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.nav-toggle svg { width: 24px; height: 24px; fill: currentColor; }

.app {
    display: grid;
    /* 侧边栏只有一种形态：72px 窄栏（图标 + 10px 小字）；收起 = 整栏隐藏 */
    grid-template-columns: var(--sn-w, 72px) minmax(0, 1fr);
}
.app.is-collapsed { --sn-w: 0px; }

/* 宽屏：主区钉在第 2 列 —— 侧栏隐藏（display:none）时主区仍自动占满余下宽度 */
@media (min-width: 901px) {
    .sidenav { grid-column: 1; }
    .app-main { grid-column: 2; }
    .app.is-collapsed .sidenav { display: none; }
}

.sidenav {
    position: sticky;
    top: 56px;
    align-self: start;
    height: calc(100vh - 56px);
    overflow-y: auto;
    /* 左右 4px / 上 12px：与 YouTube mini 侧栏一致 —— 条目 64px 居中在 72px 栏里 */
    padding: 12px 4px;
    background: var(--bg);
    /* 刻意不画右边框：与内容区连成一体，避免竖向分割线 */
}
/* 条目尺寸照 YouTube mini 侧栏：74px 高（24 图标 + 4 间距 + 10px 小字，其余是上下留白），
   条目之间不留额外 margin —— 间距由条目自身高度给足，整列密度才和 YouTube 一致。
   之前是 56px 高 + 4px margin（60px 节距），比 YouTube 紧 14px，顶栏下面两项看着挤成一团。
   注意：4px 栏内边距 + 64px 条目宽 → 图标列中心仍是 36px，与顶栏汉堡的对齐基准不变 */
.sn-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 100%;
    height: 74px;
    padding: 0 4px;
    margin: 0;
    border-radius: 10px;
    color: var(--text-strong);
    font-size: 14px;
    transition: background-color .15s ease;
}
.sn-item:hover { background: var(--state-hover); }
.sn-item:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.sn-item svg { width: 24px; height: 24px; flex: none; fill: currentColor; }
/* 选中态只用颜色 + 字重，不再给整条目套一层胶囊底色 */
.sn-item.is-active { color: var(--brand); font-weight: 500; }
/* 图标下方的 10px 小字标签（YouTube mini 侧栏） */
.sn-label {
    max-width: 100%;
    font-size: 10px;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* ============================================================
 * 窄屏底部导航栏（≤900px 才显示）
 * 手机比例 / 窄比例下不保留「侧边栏」这一层：导航目的地（首页/博客）
 * 直接平铺到固定底栏，再加一个「后台」入口 —— 与 YouTube 手机版的底部导航同构，
 * 顶栏只留 Logo + 搜索框（窄屏的汉堡、抽屉、遮罩都已去掉）。
 * 宽屏 display:none，彻底不参与布局；高度与顶栏一致（56px）。
 * ============================================================ */
.bottom-bar { display: none; }
.bb-item {
    flex: 1 1 0;                    /* 等分整条底栏：往 nav_items() 追加目的地也不用改布局 */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    height: 56px;                   /* 与底栏内容区（57px - 1px 上边框）严格相等 */
    min-width: 0;
    border: 0;                      /* 兜底：将来若换成 <button> 也不带 UA 默认边框/底色 */
    background: transparent;
    font: inherit;
    cursor: pointer;
    color: var(--text-secondary);
    -webkit-tap-highlight-color: transparent;   /* 去掉安卓/iOS 点击时那层系统灰蓝高亮 */
    transition: background-color .15s ease, color .15s ease;
}
.bb-item svg { width: 24px; height: 24px; fill: currentColor; }
.bb-label { font-size: 10px; line-height: 1; }
/* 悬停只在真能悬停的设备上生效，避免触屏点完后留下"粘住"的灰底 */
@media (hover: hover) {
    .bb-item:hover { background: var(--state-hover); }
}
/* 按压/悬停都是整格一层 state layer —— 这就是 YouTube 手机版的反馈方式，
   不加胶囊、不加圆角块，条目里只有「图标 + 文字」两层。
   这样做的前提是几何已经对齐：底栏 57px（1px 上边框 + 56px 内容）与条目 56px 严格相等，
   底色不会再盖到上边框上（之前"按下时底栏像动了一下"正是那 1px 差造成的）。 */
.bb-item:active { background: var(--state-press); }
/* 当前页：只用颜色 + 字重表示选中，不加任何底色；与宽屏窄栏 .sn-item.is-active 同色，
   桌面/手机来回切不跳色（红色已从按钮与选中体系里移除） */
.bb-item.is-active { color: var(--brand); }
.bb-item.is-active .bb-label { font-weight: 500; }
.bb-item:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

/* ============================================================
 * 博客：列表卡片 + 文章排版
 * ============================================================ */
.blog-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 20px;
}
.blog-head h1 { font-size: 24px; font-weight: 600; letter-spacing: -0.2px; color: var(--text-strong); }
.post-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 24px; }
.post-card {
    display: block;
    border-radius: var(--card-radius);
    overflow: hidden;
    background: var(--surface);
    box-shadow: var(--elevation-1);
    transition: box-shadow .2s ease;
}
.post-card:hover { box-shadow: var(--elevation-2); }
.post-cover { aspect-ratio: 16/9; background: var(--bg-elevated); overflow: hidden; }
.post-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.post-body { padding: 16px; }
.post-card-title {
    font-size: 16px;
    font-weight: 600;
    line-height: 1.4;
    color: var(--text-strong);
    margin-bottom: 6px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.post-card-excerpt {
    font-size: 13px;
    line-height: 1.7;
    color: var(--text-muted);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.post-card-meta { margin-top: 12px; display: flex; gap: 8px; flex-wrap: wrap; font-size: 12px; color: var(--text-subtle); }
.tag-chip {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    background: var(--state-hover);
    color: var(--text-muted);
    font-size: 12px;
}
/* 选中态除了颜色再加一档字重：只靠颜色区分，色觉障碍用户分不出筛选是否生效 */
.tag-chip.is-active { background: rgba(26, 115, 232, .12); color: var(--brand); font-weight: 500; }
/* 同一个类在前台是筛选链接、在后台是静态状态胶囊：交互态只作用在链接上，
   否则后台那些不可点的"已发布/草稿"胶囊也会有"能点"的暗示 */
a.tag-chip { transition: background-color .15s ease, color .15s ease; }
a.tag-chip:hover { background: var(--bg-hover); color: var(--text-strong); }
a.tag-chip.is-active:hover { background: rgba(26, 115, 232, .20); }
a.tag-chip:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.pager { display: flex; justify-content: center; align-items: center; gap: 8px; margin-top: 32px; }

/* Markdown 编辑区：等宽字体，便于对齐与阅读 */
.md-editor {
    min-height: 320px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace;
    font-size: 14px;
    line-height: 1.7;
}

/* 文章详情 */
.article { max-width: 760px; margin: 0 auto; }
.article-title { font-size: 28px; font-weight: 600; line-height: 1.35; letter-spacing: -0.3px; color: var(--text-strong); margin-bottom: 12px; }
.article-meta { display: flex; gap: 12px; flex-wrap: wrap; font-size: 13px; color: var(--text-subtle); margin-bottom: 20px; }
.article-cover { margin-bottom: 20px; border-radius: var(--card-radius); overflow: hidden; }
.article-cover img { width: 100%; display: block; }
.article-body { font-size: 16px; line-height: 1.85; color: var(--text-strong); }
.article-body h1, .article-body h2, .article-body h3, .article-body h4 { margin: 28px 0 12px; font-weight: 600; line-height: 1.4; }
.article-body h1 { font-size: 24px; }
.article-body h2 { font-size: 20px; }
.article-body h3 { font-size: 17px; }
.article-body h4 { font-size: 15px; }
.article-body p { margin-bottom: 16px; }
.article-body a { color: var(--brand); text-decoration: underline; }
.article-body img { max-width: 100%; height: auto; border-radius: 8px; margin: 8px 0; }
.article-body code { padding: 2px 6px; border-radius: 4px; background: var(--bg-elevated); font-size: 14px; }
.article-body pre { position: relative; margin: 0 0 16px; padding: 16px; overflow-x: auto; background: #1f2430; color: #e6e6e6; border-radius: 8px; font-size: 13px; line-height: 1.7; }
.article-body pre code { padding: 0; background: transparent; color: inherit; font-size: inherit; }
.article-body blockquote { margin: 0 0 16px; padding: 8px 16px; border-left: 3px solid var(--brand); background: var(--bg-elevated); color: var(--text-muted); }
.article-body ul, .article-body ol { margin: 0 0 16px; padding-left: 24px; }
.article-body li { margin-bottom: 6px; }
.article-body hr { margin: 28px 0; border: 0; border-top: 1px solid var(--outline); }
.article-foot { margin-top: 32px; padding-top: 20px; border-top: 1px solid var(--outline); font-size: 13px; color: var(--text-muted); }

/* 响应式：窄屏不保留侧栏，导航全部移到固定底部栏（见 .bottom-bar） */
@media (max-width: 900px) {
    /* 窄屏前台顶栏切回 flex：只剩 Logo + 搜索框（菜单/后台已下移到底栏），
       搜索框弹性填充、在剩余空间内居中 —— 避免三栏网格空出第 3 列导致搜索框偏左 */
    .topbar-main { display: flex; }
    .topbar-main .search-box { flex: 1 1 auto; padding: 0; }

    /* 后台顶栏塞了 7 个按钮且都不可压缩（.topbar-actions 是 flex:none），
       窄屏下整排会溢出顶栏、产生页面级横向滚动 → 允许换行，按钮排到第二行 */
    .admin-nav .topbar { flex-wrap: wrap; height: auto; min-height: 56px; padding: 8px 12px; }
    .admin-nav .spacer { display: none; }
    .admin-nav .topbar-actions { flex-wrap: wrap; row-gap: 4px; }

    /* 前台顶栏的「菜单」「后台」两个按钮下移到 .bottom-bar，顶栏只剩 Logo + 搜索框。
       位置只在断点上切换一次，不会出现"某些宽度在顶栏、某些宽度在底栏"。
       必须限定 .topbar-main：后台顶栏（.admin-nav .topbar）的 .topbar-actions 里
       是「查看前台/视频管理/博客管理/站点设置/退出」这排导航，隐藏掉后台就没法用了 */
    .topbar-main .nav-toggle,
    .topbar-main .topbar-actions { display: none; }
    .bottom-bar {
        display: flex;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        /* 窄屏已无抽屉/遮罩，这里只需盖住页面内容 */
        z-index: 210;
        /* 57px = 1px 上边框 + 56px 触控区：条目固定 56px，任何状态下都不会溢出底栏边界；
           safe-area 单独叠在底部，不参与触控高度 */
        height: calc(57px + env(safe-area-inset-bottom, 0px));
        padding-bottom: env(safe-area-inset-bottom, 0px);
        overflow: hidden;
        background: var(--bg);
        border-top: 1px solid var(--outline);
        box-shadow: 0 -1px 3px rgba(0, 0, 0, .06);
    }
    .app { grid-template-columns: minmax(0, 1fr); }
    /* 窄屏彻底不要侧栏：导航全在底部栏，抽屉/遮罩/汉堡一并去掉。
       display:none 的元素不是 grid 项，主区因此直接落在唯一的那一列上 */
    .sidenav { display: none; }
    /* 主区底部让出底栏总高，最后一行内容不会被底栏盖住（.container 自身还有 24px 内边距） */
    .app-main { padding-bottom: calc(57px + env(safe-area-inset-bottom, 0px)); }
    .article-title { font-size: 22px; }
}
@media (max-width: 540px) {
    .post-grid { grid-template-columns: 1fr; }
}

/* ============================================================
 * 旧博客正文里的视频播放器与图注（复刻主页 .player-box 风格）
 * ============================================================ */
/* 正文里的 player-box 受文章容器宽度约束，绝对不溢出 */
.article-body .player-box {
    max-width: 100%;
    margin: 16px 0;
}
/* 原 <figcaption> 在视频下方的居中说明 */
.article-body .video-caption {
    margin: 8px 0 4px;
    text-align: center;
    font-size: 13px;
    color: var(--text-secondary);
}
/* 普通图 <figcaption> 改成段落 */
.article-body .figure-caption {
    margin: -8px 0 16px;
    text-align: center;
    font-size: 13px;
    color: var(--text-secondary);
}

/* ============================================================
 * 旧博客正文里的 iframe 嵌入（B站视频 / YouTube / 地图 / 天气 / 小游戏）
 * 这些嵌入原先被 sanitize() 整段剥掉，现已按 host 白名单保留。
 * ============================================================ */
.article-body .embed-frame {
    margin: 16px 0;
    max-width: 100%;
    /* 默认 4:3，够用；视频类下面的 .embed-frame--video 覆盖成 16:9 */
    aspect-ratio: 4 / 3;
    border-radius: 10px;
    overflow: hidden;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
}
.article-body .embed-frame iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
}
/* B站/YouTube 视频：16:9 */
.article-body .embed-frame--video {
    aspect-ratio: 16 / 9;
    background: #000;
}

/* 代码块右上角的一键复制按钮（GitHub 风格：始终可见，hover 增强；点击后短暂显示"已复制"） */
.article-body pre > .code-copy-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    height: 26px;
    border: 0;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.08);
    color: #c9d1d9;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity .15s ease, background-color .15s ease, color .15s ease;
    -webkit-user-select: none;
    user-select: none;
}
.article-body pre > .code-copy-btn:hover {
    opacity: 1;
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
}
.article-body pre > .code-copy-btn:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.55);
    outline-offset: 2px;
    opacity: 1;
}
.article-body pre > .code-copy-btn svg {
    width: 14px;
    height: 14px;
    fill: currentColor;
    flex: none;
}
.article-body pre > .code-copy-btn.is-done {
    background: rgba(46, 160, 67, 0.85);  /* GitHub 绿 */
    color: #fff;
    opacity: 1;
}
/* 窄屏（手机）：保持始终可见，避免误以为"没有按钮" */
@media (max-width: 600px) {
    .article-body pre > .code-copy-btn { opacity: 0.85; }
}

/* ============================================================
 * 旧博客卡片封面占位（无图时显示浅灰16:9 占位）
 * ============================================================ */
.post-cover .cover-placeholder {
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #9ca3af;
}
.post-cover .cover-placeholder svg {
    width: 44px;
    height: 44px;
    opacity: 0.55;
}

/* ============================================================
 * 写文章编辑器工具栏 + 网页内模态框（editor-toolbar.js）
 * 风格沿用全站：浅色 + 圆角 + 磨砂；色值复用 --border/--bg-elevated/--brand 等变量。
 * ============================================================ */
.md-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 10px;
    padding: 8px;
    background: rgba(255, 255, 255, 0.55);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    border: 1px solid var(--border);
    border-radius: 12px;
}
.md-toolbar button {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 34px;
    padding: 0 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--bg-elevated, #f2f2f2);
    color: var(--text, #0f0f0f);
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    cursor: pointer;
    transition: background .15s, border-color .15s;
}
.md-toolbar button:hover { background: var(--bg-hover, #e5e5e5); }
.md-toolbar button:active { background: var(--bg-active, #d9d9d9); }
.md-toolbar button:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.md-toolbar button b, .md-toolbar button i { font-style: normal; }
.md-toolbar button b { font-weight: 700; }

/* 模态框遮罩 + 卡片 */
.md-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: rgba(15, 15, 15, 0.38);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
}
.md-modal-overlay[hidden] { display: none; }
.md-modal {
    width: min(440px, 100%);
    max-height: 90vh;
    overflow: auto;
    background: #fff;
    border: 1px solid var(--border, #e0e0e0);
    border-radius: 16px;
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.22);
    animation: md-pop .14s ease-out;
}
@keyframes md-pop { from { transform: translateY(8px) scale(.98); opacity: 0; } to { transform: none; opacity: 1; } }
.md-modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border, #e0e0e0);
}
.md-modal-title { font-size: 15px; font-weight: 600; color: var(--text-strong, #0f0f0f); }
.md-modal-x {
    width: 30px; height: 30px; border: none; border-radius: 50%;
    background: transparent; color: var(--text-secondary, #606060);
    font-size: 20px; line-height: 1; cursor: pointer;
}
.md-modal-x:hover { background: var(--bg-hover, #e5e5e5); }
.md-modal-body { padding: 16px; display: flex; flex-direction: column; gap: 12px; }
.md-modal-foot {
    display: flex; justify-content: flex-end; gap: 8px;
    padding: 12px 16px; border-top: 1px solid var(--border, #e0e0e0);
}
.md-field { display: flex; flex-direction: column; gap: 5px; font-size: 13px; color: var(--text-secondary, #606060); }
.md-field input {
    height: 36px; padding: 0 12px; border: 1px solid var(--border, #e0e0e0);
    border-radius: 10px; font-size: 14px; color: var(--text, #0f0f0f); background: #fff;
}
.md-field input:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--brand); }
.md-tabs { display: flex; gap: 6px; }
.md-tab {
    height: 32px; padding: 0 14px; border: 1px solid var(--border, #e0e0e0);
    border-radius: 16px; background: var(--bg-elevated, #f2f2f2);
    color: var(--text-secondary, #606060); font-size: 13px; cursor: pointer;
}
.md-tab.is-active { background: var(--btn-bg, #e8f0fe); color: var(--btn-fg, #174ea6); border-color: transparent; }
.md-tab-pane { display: flex; flex-direction: column; gap: 10px; }
.md-upload-status { font-size: 13px; color: var(--text-secondary, #606060); min-height: 18px; }
.md-img-preview img { max-width: 100%; max-height: 160px; border-radius: 10px; border: 1px solid var(--border, #e0e0e0); display: block; }
.md-hint { font-size: 12px; line-height: 1.6; color: var(--text-subtle, #8a8a8a); }
/* 弹窗按钮：与全站 .btn 体系一致。取消=中性次按钮，确定=主按钮（js 里已加 btn-brand）。
   单独列出是为了让取消按钮即使不带 btn 类也有完整的圆角/高度/悬停/按下/焦点反馈。 */
.md-modal-cancel,
.md-modal-ok {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 36px;
    padding: 0 16px;
    border-radius: 18px;
    font-size: 14px;
    font-weight: 500;
    line-height: 1;
    border: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background .15s;
}
.md-modal-cancel { background: var(--bg-elevated, #f2f2f2); color: var(--text, #0f0f0f); }
.md-modal-cancel:hover { background: var(--bg-hover, #e5e5e5); }
.md-modal-cancel:active { background: var(--bg-active, #d8d8d8); }
.md-modal-cancel:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.md-modal-ok { background: var(--btn-bg, #e8f0fe); color: var(--btn-fg, #174ea6); }
.md-modal-ok:hover { background: var(--btn-bg-hover, #d2e3fc); }
.md-modal-ok:active { background: var(--btn-bg-active, #c3d9fb); }
.md-modal-ok:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
