/*! Joe 主题修复：页脚吸附底部
 * 问题：页面内容不足一屏时，页脚仅跟随内容，会在页面中"上浮"，下方留白。
 * 方案：body 改为纵向 flex 容器并撑满视口高度，#Joe 占据剩余空间，页脚自然落在最底部。
 * 内容超过一屏时不受影响（页脚仍在内容之后）。
 */
body {
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

#Joe {
    flex: 1 0 auto;
}

.joe_footer {
    flex: 0 0 auto;
    margin-top: auto;
}

.joe_action {
    flex: 0 0 auto;
}

/* 「舔狗日记 / 博主卡」独立左侧栏：置于正文左侧（order:-1），右侧栏保持不动
   —— 屏幕上宽度 ≤992px 时主题本身会隐藏 .joe_aside，本栏同样隐藏（行为与原先一致） */
.joe_aside__left {
    order: -1;
    margin-left: 0;
}

/* ==================== 布局呼吸感优化 ====================
 * 背景：加入左侧栏后变成三栏，正文被挤到只有 760px 左右，整体显得紧凑。
 * 做法：① 放宽容器上限（主题最宽 1320px）② 列间距 15px → 16/18/22px
 *       ③ 侧栏卡片间距同步加大  ④ 文章条目上下留白 15px → 18px
 * 说明：主题在 ≤992px 会隐藏侧栏，故下列规则统一限定在 ≥993px，不影响手机端。
 */
@media (min-width: 993px) {
    /* 容器放宽：窄屏直接铺满窗口（留 15px 内边距），宽屏最多 1560px */
    .joe_container {
        max-width: 1560px;
    }

    /* 正文上下留白与左右栏对齐 */
    .joe_main {
        padding: 20px 0;
    }

    /* 侧栏间距（右栏 margin-left / 左栏 margin-right 成对调整）
       左栏与正文之间的空隙再放宽一些，避免显得紧凑 */
    .joe_aside {
        padding: 20px 0;
        margin-left: 20px;
    }

    .joe_aside__left {
        margin-right: 26px;
    }

    .joe_aside__item {
        width: 200px;
        margin-bottom: 16px;
    }

    .joe_list__item {
        padding: 18px 0;
    }
}

/* 中等屏幕：侧栏卡片 225px，列间距 18px */
@media (min-width: 1200px) {
    .joe_aside {
        margin-left: 22px;
    }

    .joe_aside__left {
        margin-right: 30px;
    }

    .joe_aside__item {
        width: 225px;
        margin-bottom: 18px;
    }
}

/* 宽屏：恢复主题默认卡片宽度 250px，列间距放宽到 22px */
@media (min-width: 1440px) {
    .joe_aside {
        margin-left: 24px;
    }

    .joe_aside__left {
        margin-right: 34px;
    }

    .joe_aside__item {
        width: 250px;
        margin-bottom: 22px;
    }
}

/* ==================== 侧边栏吸顶 ====================
 * 由两个独立开关控制（边栏设置 →「固定左侧栏」/「固定右侧栏」）：
 *   都开   = 两条都吸附
 *   只开一个 = 只吸附那一条
 *   都关   = 两条都随页面滚走
 * body 上的类名 joe-aside-fix--left / joe-aside-fix--right 与之一一对应，
 * 关掉时**完全不输出该类名** → CSS 直接不加吸附属性（不是靠!important 覆盖）。
 *
 * ⚠️ 两条选择器是「并列」关系而非互斥，所以要写在一起；
 *    右栏选择器必须 :not(.joe_aside__left)（左栏 class 是 `joe_aside joe_aside__left` 两个类名）。
 */
@media (min-width: 993px) {
    /* ⚠️ align-self:flex-start 要写在 .joe_aside 通用规则上（**两条栏都要**）。
       只写进"被固定的那条"分支里的话，没被固定的会回到 flex 默认的 stretch，
       高度被拉到和正文一样高（实测 7843px），卡片全摊到整页。
       （.joe_aside 是 display:block，所以拉伸只会让"容器变高"，里面卡片仍从顶部依次排列） */
    .joe_aside {
        align-self: flex-start;
    }

    body.joe-aside-fix--left .joe_aside__left,
    body.joe-aside-fix--right .joe_aside:not(.joe_aside__left) {
        position: -webkit-sticky;
        position: sticky;
        top: 100px;
        max-height: calc(100vh - 145px);
        overflow-y: auto;
        overflow-x: hidden;
        overscroll-behavior: contain;
        scrollbar-width: thin;
    }

    body.joe-aside-fix--left .joe_aside__left::-webkit-scrollbar,
    body.joe-aside-fix--right .joe_aside:not(.joe_aside__left)::-webkit-scrollbar {
        width: 6px;
    }

    body.joe-aside-fix--left .joe_aside__left::-webkit-scrollbar-thumb,
    body.joe-aside-fix--right .joe_aside:not(.joe_aside__left)::-webkit-scrollbar-thumb {
        background: var(--classA);
        border-radius: 3px;
    }

    body.joe-aside-fix--left .joe_aside__left::-webkit-scrollbar-track,
    body.joe-aside-fix--right .joe_aside:not(.joe_aside__left)::-webkit-scrollbar-track {
        background: transparent;
    }

    /* 没开的那个开关 → 不加任何吸附属性，回到主题默认（static），随页面滚走。
       ⚠️ 也别写成 position:static 去"取消"—— 见下方 last-child 那条的注释，
       .joe_aside__item 的 relative 是内部绝对定位元素的定位父。 */

    /* ---- 「文章目录」卡片的强制跟随（2026-10-09 重写） ----
       需求：不管右栏有没有开「固定右侧栏」，滚到目录那里它都要跟住视口。

       ⚠️ 原来是用 JS 逐帧算 transform 补偿滚动，**必然慢一帧 → 抖动**：
          异步滚动下浏览器在合成线程先把整页滚走，主线程收到 scroll 事件、
          再更新 transform 要等到下一次绘制，中间那一帧目录会跟着页面上移
          （实测滚动步长 90px 时目录从 70 跳到 -20，下一帧再跳回 70）。
          用户看到的就是"边滑边抖"。

       现在改成**浏览器原生 sticky**（合成线程处理，零延迟、零抖动）：
       ① 右栏「不固定」时让它 align-self:stretch 撑到和正文一样高
          —— sticky 需要有"可移动的余量"，而它原来的高度等于内容高度，没有余量；
       ② 目录卡自己 position:sticky 吸在顶栏下方。
       右栏「固定」时不用这套（整条栏本来就已经吸住了），
       那种情况目录会落在栏内可视区之外，交给 toc_card.php 把右栏滚一下露出来。 */
    body:not(.joe-aside-fix--right) .joe_aside:not(.joe_aside__left) {
        align-self: stretch;
    }

    body:not(.joe-aside-fix--right) .joe_aside__item.toc {
        position: -webkit-sticky;
        position: sticky;
        /* 与顶部留出间隔（2026-10-09 用户反馈"要离顶部远一点"）：
           桌面顶栏固定占 0~60px，原来写 55px → 卡片顶部有 5px 被顶栏压住，看着贴在一起。
           75px = 顶栏 60 + 15px 间隔，而且正好和左栏第一张卡的位置对齐
           （左栏 .joe_aside 有 15px 上内边距，吸顶后首卡 top = 55+20 = 75）。 */
        top: 75px;
        /* 主题给 :last-child 挂了 transition: top .35s，这里禁掉：
           任何 top 变化都会被慢速缓动放大成"漂移"观感 */
        transition: none;
    }

    /* 侧栏已吸顶，内部"最后一张卡片吸顶"就不需要了（避免卡片在栏内悬浮重叠）。
       ⚠️ 但这里**不能写成 position:static** —— 主题的 .joe_aside__item 靠 position:relative
       给内部绝对定位元素当参照：博主卡 .author 顶部的封面图就是 absolute;top:0。
       左栏只有博主卡一张 → 它正好是 :last-child → relative 被抹掉 →
       封面图改为相对 .joe_aside 定位，向上偏移 20px 跑出卡片外（视觉上"博主卡比别的卡高出一截"）。
       所以只用 sticky:none 取消吸顶，保留 relative。 */
    .joe_aside .joe_aside__item:last-child {
        position: relative;
        top: auto;
        margin-bottom: 0;
    }
}

/* ==================== 边栏组件：标签云 / 博客信息 ==================== */

/* 标签云：胶囊标签平铺（参考 yolos.cn 的标签云） */
.joe_tagcloud {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.joe_tagcloud__item {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 20px;
    background: var(--classD);
    color: var(--routine);
    font-size: 12px;
    line-height: 18px;
    word-break: break-all;
    transition: background 0.3s, color 0.3s, transform 0.3s;
}

.joe_tagcloud__item:hover {
    background: var(--theme);
    color: #fff;
    transform: translateY(-1px);
}

.joe_tagcloud__item .count {
    margin-left: 5px;
    font-size: 11px;
    opacity: 0.6;
}

/* 博客信息：左侧名称 + 右侧数值（参考 yolos.cn 的博客信息） */
.joe_bloginfo {
    list-style: none;
    margin: 0;
    padding: 0;
}

.joe_bloginfo__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 9px 0;
    font-size: 13px;
    line-height: 1;
    border-bottom: 1px dashed var(--classC);
}

.joe_bloginfo__item:last-child {
    padding-bottom: 0;
    border-bottom: none;
}

.joe_bloginfo__item .label {
    color: var(--minor);
}

.joe_bloginfo__item .value {
    color: var(--main);
    font-weight: 500;
}

/* 两个新组件的"暂无内容"提示 */
.joe_aside__item.tagcloud .joe_aside__item-contain > .empty,
.joe_aside__item.bloginfo .joe_aside__item-contain > .empty {
    text-align: center;
    color: var(--routine);
}

/* ==================== 边栏组件「博客信息 / 标签云」 ==================== */

/* —— 卡片底色：主题只给自家卡片类型配了背景，这两个是后加的组件，之前是「完全透明」——
   2026-10-09 改为**只跟 var(--background)**，不再写死纯白：
   写死之后「组件透明度」在它们身上失效（那两张卡永远不透明），
   和旁边走 var(--background) 的卡片差一个档（实测 .66 vs .56），看着像"底色不适配"。 —— */
.joe_aside__item.tagcloud,
.joe_aside__item.bloginfo {
    background: var(--background);
}

/* —— 博客信息：每行一个彩色圆点，数值是同色系实色胶囊，行悬停高亮 —— */
.joe_bloginfo__item {
    --jc: #2b7cd3;
    --jbg: #e8f2ff;
    padding: 8px 6px;
    margin: 0 -6px;
    border-radius: 6px;
    transition: background 0.25s;
}

.joe_bloginfo__item:hover {
    background: var(--classD);
}

.joe_bloginfo__item .label {
    display: inline-flex;
    align-items: center;
    color: var(--minor);
}

.joe_bloginfo__item .label::before {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    margin-right: 8px;
    background: var(--jc);
}

.joe_bloginfo__item .value {
    display: inline-flex;
    align-items: center;
    min-height: 22px;
    padding: 1px 9px;
    border-radius: 11px;
    font-size: 12.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    background: var(--jbg);
    color: var(--jc);
    transition: transform 0.25s;
}

.joe_bloginfo__item:hover .value {
    transform: translateX(-2px);
}

/* 文章数目 / 评论数目 / 标签数目 / 全站字数 / 访问总量 / 响应耗时 / 运行天数 / 最后活动 */
.joe_bloginfo__item:nth-child(8n+1) { --jc: #2b7cd3; --jbg: #e8f2ff; }
.joe_bloginfo__item:nth-child(8n+2) { --jc: #4e9a2b; --jbg: #eaf6e4; }
.joe_bloginfo__item:nth-child(8n+3) { --jc: #b8791f; --jbg: #fdf2e2; }
.joe_bloginfo__item:nth-child(8n+4) { --jc: #7b5cc4; --jbg: #f1ebfb; }
.joe_bloginfo__item:nth-child(8n+5) { --jc: #128295; --jbg: #e4f5f8; }
.joe_bloginfo__item:nth-child(8n+6) { --jc: #d15050; --jbg: #fdeaea; }
.joe_bloginfo__item:nth-child(8n+7) { --jc: #a97f12; --jbg: #faf3d9; }
.joe_bloginfo__item:nth-child(8n+8) { --jc: #6b6f76; --jbg: #eef0f2; }

/* —— 标签云：五色轮换的实色胶囊，数量做成同色系小气泡 —— */
.joe_tagcloud {
    gap: 8px 7px;
}

.joe_tagcloud__item {
    --jc: #2b7cd3;
    --jbg: #e8f2ff;
    --jbg2: #cfe3ff;
    padding: 4px 11px;
    font-size: 12.5px;
    border-radius: 14px;
    background: var(--jbg);
    color: var(--jc);
    transition: background 0.25s, color 0.25s;
}

.joe_tagcloud__item .count {
    margin-left: 6px;
    padding: 0 5px;
    border-radius: 8px;
    font-size: 11px;
    line-height: 16px;
    opacity: 1;
    background: var(--jbg2);
    color: var(--jc);
}

.joe_tagcloud__item:nth-child(5n+1) { --jc: #2b7cd3; --jbg: #e8f2ff; --jbg2: #cfe3ff; }
.joe_tagcloud__item:nth-child(5n+2) { --jc: #4e9a2b; --jbg: #eaf6e4; --jbg2: #d6ecd0; }
.joe_tagcloud__item:nth-child(5n+3) { --jc: #b8791f; --jbg: #fdf2e2; --jbg2: #f7e3c5; }
.joe_tagcloud__item:nth-child(5n+4) { --jc: #7b5cc4; --jbg: #f1ebfb; --jbg2: #e2d6f5; }
.joe_tagcloud__item:nth-child(5n+5) { --jc: #128295; --jbg: #e4f5f8; --jbg2: #c9e9ef; }

.joe_tagcloud__item:hover {
    color: #fff;
}

.joe_tagcloud__item:nth-child(5n+1):hover { background: #409eff; }
.joe_tagcloud__item:nth-child(5n+2):hover { background: #67c23a; }
.joe_tagcloud__item:nth-child(5n+3):hover { background: #e6a23c; }
.joe_tagcloud__item:nth-child(5n+4):hover { background: #9a78dc; }
.joe_tagcloud__item:nth-child(5n+5):hover { background: #17a2b8; }

/* —— 夜间：深色卡片上换成更亮的实色（不能用半透明，否则透出卡片底色发暗） —— */
html[data-night='night'] .joe_bloginfo__item:nth-child(8n+1) { --jc: #8cc4ff; --jbg: #24384f; }
html[data-night='night'] .joe_bloginfo__item:nth-child(8n+2) { --jc: #a5e07a; --jbg: #2a3d24; }
html[data-night='night'] .joe_bloginfo__item:nth-child(8n+3) { --jc: #f3c47a; --jbg: #40331f; }
html[data-night='night'] .joe_bloginfo__item:nth-child(8n+4) { --jc: #c3aaf0; --jbg: #332a4a; }
html[data-night='night'] .joe_bloginfo__item:nth-child(8n+5) { --jc: #6fd6e8; --jbg: #1f3a41; }
html[data-night='night'] .joe_bloginfo__item:nth-child(8n+6) { --jc: #ff9c9c; --jbg: #40282a; }
html[data-night='night'] .joe_bloginfo__item:nth-child(8n+7) { --jc: #ecc861; --jbg: #3d3520; }
html[data-night='night'] .joe_bloginfo__item:nth-child(8n+8) { --jc: #c2c6cc; --jbg: #33363a; }

html[data-night='night'] .joe_tagcloud__item:nth-child(5n+1) { --jc: #8cc4ff; --jbg: #24384f; --jbg2: #2d4664; }
html[data-night='night'] .joe_tagcloud__item:nth-child(5n+2) { --jc: #a5e07a; --jbg: #2a3d24; --jbg2: #364f2d; }
html[data-night='night'] .joe_tagcloud__item:nth-child(5n+3) { --jc: #f3c47a; --jbg: #40331f; --jbg2: #524226; }
html[data-night='night'] .joe_tagcloud__item:nth-child(5n+4) { --jc: #c3aaf0; --jbg: #332a4a; --jbg2: #42375f; }
html[data-night='night'] .joe_tagcloud__item:nth-child(5n+5) { --jc: #6fd6e8; --jbg: #1f3a41; --jbg2: #294c55; }

/* ==================== 个人介绍（博主卡）链接按钮 ==================== */

/* 网格排布：一行 1~2 个（只有 1 个时自动占满一行，2 个以上自动两列等宽），保证按钮规整对齐 */
.joe_author__links {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
    gap: 8px;
    padding-top: 14px;
    padding-bottom: 15px;
    font-size: 12.5px;
}

.joe_author__link {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
    max-width: 100%;
    padding: 4px 8px;
    border-radius: 14px;
    background: var(--classD);
    color: var(--routine);
    line-height: 20px;
    cursor: pointer;
    transition: background 0.25s, color 0.25s, transform 0.25s;
}

.joe_author__link:hover {
    background: var(--theme);
    color: #fff;
    transform: translateY(-1px);
}

.joe_author__link .icon {
    flex: none;
    display: inline-block;
    width: 14px;
    height: 14px;
    margin-right: 5px;
    border-radius: 3px;
    object-fit: contain;
    font-size: 13px;
    line-height: 14px;
    text-align: center;
}

/* favicon 加载失败（站点没有图标）时，换成内置的链接图标，保证一排按钮图标整齐 */
.joe_author__link .icon-wrap {
    position: relative;
    flex: none;
    display: inline-block;
    width: 14px;
    height: 14px;
    margin-right: 5px;
}

.joe_author__link .icon-wrap .icon {
    display: block;
    margin-right: 0;
}

.joe_author__link .icon-wrap.is-empty::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: currentColor;
    opacity: 0.75;
    -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20fill='black'%20d='M3.9%2012c0-1.71%201.39-3.1%203.1-3.1h4V7H7a5%205%200%200%200%200%2010h4v-1.9H7c-1.71%200-3.1-1.39-3.1-3.1zM8%2013h8v-2H8v2zm9-6h-4v1.9h4c1.71%200%203.1%201.39%203.1%203.1s-1.39%203.1-3.1%203.1h-4V17h4a5%205%200%200%200%200-10z'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20fill='black'%20d='M3.9%2012c0-1.71%201.39-3.1%203.1-3.1h4V7H7a5%205%200%200%200%200%2010h4v-1.9H7c-1.71%200-3.1-1.39-3.1-3.1zM8%2013h8v-2H8v2zm9-6h-4v1.9h4c1.71%200%203.1%201.39%203.1%203.1s-1.39%203.1-3.1%203.1h-4V17h4a5%205%200%200%200%200-10z'/%3E%3C/svg%3E") center / contain no-repeat;
}

.joe_author__link .text {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* 夜间模式：底再亮一点，避免深色卡片上按钮糊在一起 */
html[data-night='night'] .joe_author__link {
    background: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.9);
}

html[data-night='night'] .joe_author__link:hover {
    background: var(--theme);
    color: #fff;
}

/* ==================== 隐藏页头第二条（分类栏） ==================== */
/* 该条高 45px，本站分类已上移到第一行，所以它几乎是空的、只在最右有个登录/退出。
   手机端主题自己就有 html .joe_header__below{display:none}（max-width:992px），这里只处理桌面端。 */
@media (min-width: 993px) {
    html .joe_header__below {
        display: none;
    }
}

/* ==================== 顶部栏的登录 / 用户入口 ==================== */
/* 原来在页头第二条（已隐藏）里，现在挪到顶部栏右侧：
   未登录 = 圆形登录图标（点击进登录页）；已登录 = 头像 + 下拉菜单（新建文章 / 评论管理 / 后台管理 / 退出） */
.joe_header__above-sign {
    display: flex;
    align-items: center;
    flex: none;
    height: 60px;
    margin-left: 8px;
}

/* —— 未登录：圆形图标按钮 —— */
.joe_header__above-sign .joe_header__above-login {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    transition: background 0.35s, transform 0.35s;
}

.joe_header__above-sign .joe_header__above-login:hover {
    background: var(--classC);
    transform: translateY(-1px);
}

.joe_header__above-sign .joe_header__above-login .icon {
    width: 24px;
    height: 24px;
}

/* —— 已登录：头像 + 小箭头，整块可点开菜单 —— */
.joe_header__above-sign .joe_dropdown__link {
    padding: 4px 6px 4px 5px;
    margin-right: -6px;
    border-radius: 19px;
    cursor: pointer;
    transition: background 0.35s;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.joe_header__above-sign .joe_dropdown__link:hover,
.joe_header__above-sign .joe_dropdown.active .joe_dropdown__link {
    background: var(--classC);
}

.joe_header__above-sign .joe_dropdown__link img.avatar {
    display: block;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    object-fit: cover;
}

.joe_header__above-sign .joe_dropdown__link-icon {
    margin-left: 5px;
}

/* —— 下拉面板：贴右侧对齐（主题默认是水平居中，会顶出屏幕右边） —— */
.joe_header__above-sign .joe_dropdown__menu.joe_user_menu {
    left: auto;
    right: 0;
    width: 236px;
    padding: 0;
    -webkit-transform-origin: top right;
    transform-origin: top right;
    opacity: 0;
    -webkit-transform: perspective(600px) rotateX(-30deg);
    transform: perspective(600px) rotateX(-30deg);
}

.joe_header__above-sign .joe_dropdown.active .joe_dropdown__menu.joe_user_menu {
    opacity: 1;
    -webkit-transform: perspective(600px) rotateX(0);
    transform: perspective(600px) rotateX(0);
}

/* 小三角从正中间挪到右侧（对着头像） */
.joe_header__above-sign .joe_user_menu::before {
    left: auto;
    right: 20px;
    -webkit-transform: none;
    transform: none;
}

.joe_user_menu__head {
    padding: 12px 14px 11px;
    background: var(--classD);
    border-bottom: 1px solid var(--classC);
}

.joe_user_menu__hello {
    margin-bottom: 9px;
    font-size: 13px;
    color: var(--main);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.joe_user_menu__bar {
    height: 6px;
    border-radius: 3px;
    background: var(--classC);
    overflow: hidden;
}

.joe_user_menu__bar span {
    display: block;
    height: 100%;
    border-radius: 3px;
    background: var(--theme);
    transition: width 0.6s;
}

.joe_user_menu__meta {
    display: flex;
    justify-content: space-between;
    margin-top: 7px;
    font-size: 11px;
    color: var(--seat);
}

.joe_user_menu__item {
    display: flex;
    align-items: center;
    height: 40px;
    padding: 0 14px;
    font-size: 13.5px;
    color: var(--routine);
    transition: background 0.25s, color 0.25s;
}

.joe_user_menu__item:hover {
    background: var(--classD);
    color: var(--theme);
}

.joe_user_menu__icon {
    flex: none;
    width: 16px;
    height: 16px;
    margin-right: 10px;
}

.joe_user_menu__badge {
    margin-left: auto;
    min-width: 20px;
    height: 18px;
    padding: 0 6px;
    border-radius: 9px;
    background: var(--classC);
    color: var(--minor);
    font-size: 11px;
    font-style: normal;
    line-height: 18px;
    text-align: center;
}

.joe_user_menu__item.is-logout {
    border-top: 1px solid var(--classC);
    border-radius: 0 0 var(--radius-inner) var(--radius-inner);
    color: var(--minor);
}

.joe_user_menu__item.is-logout:hover {
    background: rgba(245, 108, 108, 0.1);
    color: #f56c6c;
}

/* 手机端顶部栏是另一套（汉堡 + 搜索），抽屉菜单里没有登录项 —— 所以这里要保留登录入口，只把尺寸和间距收紧 */
@media (max-width: 992px) {
    .joe_header__above-sign {
        height: auto; /* 桌面端是 60px，手机端不撑高顶栏（恢复原来的 55px） */
        margin-left: 2px;
    }

    .joe_header__above-sign .joe_header__above-login {
        width: 32px;
        height: 32px;
    }

    .joe_header__above-sign .joe_header__above-login .icon {
        width: 22px;
        height: 22px;
    }

    .joe_header__above-sign .joe_dropdown__link {
        padding: 3px 4px 3px 3px;
        margin-right: -4px;
    }

    .joe_header__above-sign .joe_dropdown__link img.avatar {
        width: 28px;
        height: 28px;
    }

    .joe_header__above-sign .joe_dropdown__link-icon {
        margin-left: 3px;
    }
}

/* ==================== 文章页面包屑固定（下滑不消失，不加底色） ==================== */
/* 文章头一行：左＝面包屑（首页 / 分类 / 正文），右＝分类徽章。
   2026-10-08：面包屑原来是正文容器之外一条独立的吸顶栏（.joe_container.joe_bread，
   满宽、贴在顶栏下面），现已挪进 .joe_detail__category 里 —— 不再吸顶，也不再占整行。
   ⚠️ 因此 joe.global.js 里 setAsideSticky() 找不到 .joe_bread（extra=0），
   侧栏吸顶从 98px 变 55px，这是对的（正文卡顶部上移了）。 */
.joe_detail__category {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 10px;
    margin-bottom: 12px;
}

.joe_detail__crumb {
    display: flex;
    align-items: center;
    min-width: 0;
    order: 1;
}

/* 分类徽章整体靠右排（"往后放"） */
.joe_detail__tags {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    order: 2;
    margin-left: auto;
}

/* 面包屑：原来 .item 用的是 --minor(#909399) 灰，压在浅底上很淡 → 提到 --routine 并加字重。
   层级：当前页「正文」最深最深，分类次之，分隔线最浅。 */
.joe_detail__crumb .joe_bread__bread {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    font-size: 13px;
    line-height: 22px;
}

/* ⚠️ 必须重置：主题有一条 `.joe_detail__category .item{color:#fff;font-size:12px;padding:3px 8px;
   border-radius:2px;max-width:120px;overflow:hidden}` + `:hover{transform:translate3d(0,-3px,0)}`
   —— 那是给**分类徽章**写的，面包屑现在也在这个容器里，会被误伤（徽章的蓝底/内边距/hover 上浮）。
   下面的选择器比它多一层类，优先级更高。 */
.joe_detail__crumb .joe_bread__bread .item {
    display: flex;
    align-items: center;
    max-width: none;
    padding: 0;
    margin: 0;
    overflow: visible;
    color: var(--routine);
    font-size: 13px;
    font-weight: 500;
    text-overflow: clip;
    white-space: nowrap;
    border-radius: 0;
    transition: color 0.25s;
}

.joe_detail__crumb .joe_bread__bread .item:hover {
    opacity: 1;
    -webkit-transform: none;
    transform: none;
}

.joe_detail__crumb .joe_bread__bread .item .link {
    max-width: none;
    overflow: visible;
    color: var(--routine);
    text-overflow: clip;
    transition: color 0.25s;
}

.joe_detail__crumb .joe_bread__bread .item .link:hover {
    color: var(--theme);
}

/* ⚠️ 还有一条**全局** `.link{max-width:85%;overflow:hidden;text-overflow:ellipsis}`
   （本来是给侧栏链接截断用的）。面包屑搬进窄栏后会被它把文字截成"实用.."，
   所以上面那条已经把 max-width/overflow/text-overflow 重置掉了。 */

.joe_detail__crumb .joe_bread__bread .item .icon {
    width: 14px;
    height: 14px;
    min-width: 14px;
    min-height: 14px;
    margin-right: 3px;
    fill: var(--routine);
}

.joe_detail__crumb .joe_bread__bread .line {
    padding: 0 7px;
    color: var(--seat);
    font-weight: 400;
}

/* 当前页（正文）做成一个小胶囊，视线落点更明确 */
.joe_detail__crumb .joe_bread__bread .joe_bread__now {
    padding: 1px 9px;
    color: var(--theme);
    font-weight: 600;
    background: rgba(64, 158, 255, .1);
    border-radius: 9px;
}

html[data-night='night'] .joe_detail__crumb .joe_bread__bread .joe_bread__now {
    background: rgba(84, 181, 219, .16);
}

/* ==================== 顶栏 / 页脚底色（配背景图时的半透明 → 恢复成实色白底） ==================== */
/* 配了「网站背景」图片后主题会把 --background 变成 rgba(255,255,255,.85)（卡片跟着变半透明，
   这是我们要的）；但顶栏 / 页脚这两条"栏目"要的是干净的白底，所以只要没开「上下栏目沉浸」，
   就写实色压回去 —— 沉浸关闭 = 白底栏目，沉浸开启 = 由「沉浸栏不透明度」控制。 */
html:not([data-night='night']) body:not(.joe-immersive) .joe_header,
html:not([data-night='night']) body:not(.joe-immersive) .joe_header__above,
html:not([data-night='night']) body:not(.joe-immersive) .joe_footer {
    background: #fff;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}

html[data-night='night'] body:not(.joe-immersive) .joe_header,
html[data-night='night'] body:not(.joe-immersive) .joe_header__above,
html[data-night='night'] body:not(.joe-immersive) .joe_footer {
    background: #232323;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}

body:not(.joe-immersive) .joe_header {
    box-shadow: 0 2px 10px 0 rgba(0, 0, 0, .1);
}

/* 上面两条把顶栏变成白底后有个坑：站点 logo 是**纯白**的（本项目这张实测 254,254,254，
   本来是配深色壁纸的），白底上直接看不见 —— 反相成深色。夜间 / 沉浸状态是深色底，不反相。
   ⚠️ 以后换 logo 的话记得回来看看这条（换成深色 logo 就要删掉反相）。 */
html:not([data-night='night']) body:not(.joe-immersive) .joe_header__above-logo,
html:not([data-night='night']) body.joe-immersive-solid .joe_header__above-logo {
    -webkit-filter: invert(1);
    filter: invert(1);
}

/* ==================== 上下栏目沉浸（其他设置 →「上下栏目沉浸」） ==================== */
/* 开启后顶部栏 / 页脚不再铺自己的白底，直接用网站默认底色
   （背景色 + 纹理 + 背景动效，或背景图）铺满页面最上沿和最下沿，上下边缘与内容连成一片。
   ⚠️ 沉浸只在「页面上沿」成立：顶部栏是固定/吸顶的，一旦往下滚动，内容会从它下面穿过去、
   和导航文字叠在一起（实测确实糊成一片）→ 滚过 8px 后（<html>.joe-scrolled，由 header.php 的脚本加）
   必须把默认底色还给顶部栏。页脚在文档末尾、没有内容从它下面穿过，所以始终保持沉浸。 */
body.joe-immersive .joe_header {
    background: transparent;
    box-shadow: none;
}

body.joe-immersive .joe_header__above {
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}

body.joe-immersive .joe_header__below {
    background: transparent;
    border-top-color: transparent;
}

body.joe-immersive .joe_footer {
    background: transparent;
    border-top-color: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}

/* 滚动之后（滚过 8px，<html>.joe-scrolled 由 header.php 的脚本加）：
   **底色不透明度继续由「沉浸栏不透明度」决定，和页面上沿完全一致** ——
   底色本身是 header.php 输出的 `body.joe-immersive .joe_header__above{background:rgba(255,255,255,A)}`，
   滚动态不再另写背景色（之前写 `var(--background)` / `#fff` 都会让"后台调的不透明度"在滚动后失效）。
   滚动只补两件事：
   ① 一道分隔阴影，让吸顶的顶栏和正文有个边界；
   ② 压暗层加回来并加深（见下方 ::after 那条）—— 正在滚动的内容会从顶栏下面穿过，
      不压一下白字就糊了。不透明度 ≥45% 时是浅底深字，本来就不需要压暗。 */
html.joe-scrolled body.joe-immersive .joe_header {
    box-shadow: 0 2px 10px 0 rgba(0, 0, 0, .1);
}

html[data-night='night'].joe-scrolled body.joe-immersive .joe_header {
    box-shadow: 0 2px 10px 0 rgba(0, 0, 0, .35);
}

/* 滚动态：文字/图标/logo/搜索框一律**不再另写一套** —— 它们只跟「沉浸栏不透明度」走
   （≥45% 由 .joe-immersive-solid 切深色字 + logo 反相），这样页面上沿和滚动后是一套观感。 */

/* 夜间：让主题的深色底 / 背景图层透出来，别露出白色 */
html[data-night='night'] body.joe-immersive .joe_header__above,
html[data-night='night'] body.joe-immersive .joe_footer {
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}

/* 沉浸开启后的上下栏文字：顶栏/页脚整层透明，原来的 #909399 灰字压在壁纸上根本看不清。
   这里把上下栏的字与图标统一改成白色 + 深色投影（浅色壁纸也有光晕兜底），
   再给顶栏和页脚各加一层极淡的压暗渐变 —— 任何壁纸上都能读清，同时不影响沉浸感。 */
body.joe-immersive .joe_header__above-nav .item,
body.joe-immersive .joe_header__above-nav .item a {
    color: #fff;
    font-weight: 500;
    text-shadow: 0 1px 3px rgba(0, 0, 0, .6), 0 0 10px rgba(0, 0, 0, .35);
}

body.joe-immersive .joe_header__above-nav .item.active,
body.joe-immersive .joe_header__above-nav .item:hover {
    color: #fff;
}

body.joe-immersive .joe_header__above-nav .joe_dropdown__link {
    text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}

/* 站点 logo 是图片，用投影把它从花哨壁纸里"托"出来 */
body.joe-immersive .joe_header__above-logo {
    -webkit-filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .5));
    filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .5));
}

/* 汉堡图标 / 搜索图标 / 登录图标（主题是 SVG，fill 跟随 --routine --minor） */
body.joe-immersive .joe_header__above-slideicon,
body.joe-immersive .joe_header__above-searchicon,
body.joe-immersive .joe_header__above-login svg {
    fill: #fff;
    -webkit-filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .55));
    filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .55));
}

/* 搜索框：白底白边压在壁纸上看不出边界，改成半透明玻璃感 */
body.joe-immersive .joe_header__above-search .input {
    background: rgba(255, 255, 255, .24);
    border-color: rgba(255, 255, 255, .5);
    color: #fff;
}

body.joe-immersive .joe_header__above-search .input::placeholder {
    color: rgba(255, 255, 255, .78);
}

body.joe-immersive .joe_header__above-search .icon {
    fill: #fff;
}

body.joe-immersive .joe_header__above-sign .joe_dropdown__link .avatar {
    border-color: rgba(255, 255, 255, .75);
}

body.joe-immersive .joe_header__above-sign .joe_dropdown__link-icon {
    fill: #fff;
}

body.joe-immersive .joe_header__above-sign {
    color: #fff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}

/* 页脚文字 */
body.joe-immersive .joe_footer,
body.joe-immersive .joe_footer a,
body.joe-immersive .joe_footer .item,
body.joe-immersive .joe_footer .item .run {
    color: rgba(255, 255, 255, .94);
    text-shadow: 0 1px 3px rgba(0, 0, 0, .55);
}

/* 顶栏 / 页脚的极淡压暗（::after 挂在 z-index:-1，垫在内容之下、背景之上） */
body.joe-immersive .joe_header__above::after,
body.joe-immersive .joe_footer::after {
    position: absolute;
    left: 0;
    right: 0;
    z-index: -1;
    content: '';
    pointer-events: none;
}

body.joe-immersive .joe_header__above::after {
    top: 0;
    bottom: 0;
    background: linear-gradient(180deg, rgba(0, 0, 0, .28), rgba(0, 0, 0, .03));
}

body.joe-immersive .joe_footer {
    position: relative;
    z-index: 0;
}

body.joe-immersive .joe_footer::after {
    top: 0;
    bottom: 0;
    background: linear-gradient(0deg, rgba(0, 0, 0, .3), rgba(0, 0, 0, .04));
}

/* 「沉浸栏不透明度」> 0 时**仍然保留**这层压暗：文字是白字，半透明白底 + 壁纸/滚动内容垫在下面
   才看得清（之前这里按 .joe-immersive-tint 直接 display:none，结果 0~45% 那一段白字发飘）。
   只有 ≥45%（.joe-immersive-solid，下面那组规则）才撤掉 —— 那时已经切成浅底深字了。
   ⚠️ 这条压暗层**不能按滚动状态切换**：一改就出现"滚一下顶栏忽然变亮/变暗"的跳变，
   页面上沿和滚动后必须完全一致。 */

/* 「沉浸栏不透明度」调得比较高（≥45%）时，上下栏已经是一块浅色底了 ——
   白字会糊在上面，所以整体退回主题原来的深色字、并撤掉压暗渐变（.joe-immersive-solid 由 header.php 输出） */
body.joe-immersive-solid .joe_header__above-nav .item,
body.joe-immersive-solid .joe_header__above-nav .item a,
body.joe-immersive-solid .joe_header__above-nav .item.active,
body.joe-immersive-solid .joe_header__above-nav .item:hover {
    color: var(--routine);
    font-weight: 400;
    text-shadow: none;
}

body.joe-immersive-solid .joe_header__above-logo,
body.joe-immersive-solid .joe_header__above-slideicon,
body.joe-immersive-solid .joe_header__above-searchicon,
body.joe-immersive-solid .joe_header__above-login svg {
    -webkit-filter: none;
    filter: none;
}

body.joe-immersive-solid .joe_header__above-slideicon,
body.joe-immersive-solid .joe_header__above-searchicon,
body.joe-immersive-solid .joe_header__above-login svg {
    fill: var(--routine);
}

body.joe-immersive-solid .joe_header__above-search .input {
    background: var(--classD);
    border-color: var(--classA);
    color: var(--main);
}

body.joe-immersive-solid .joe_header__above-search .input::placeholder {
    color: var(--seat);
}

body.joe-immersive-solid .joe_header__above-search .icon {
    fill: var(--minor);
}

body.joe-immersive-solid .joe_header__above-sign {
    color: var(--routine);
    text-shadow: none;
}

body.joe-immersive-solid .joe_footer,
body.joe-immersive-solid .joe_footer a,
body.joe-immersive-solid .joe_footer .item,
body.joe-immersive-solid .joe_footer .item .run {
    color: var(--minor);
    text-shadow: none;
}

body.joe-immersive-solid .joe_header__above::after,
body.joe-immersive-solid .joe_footer::after {
    display: none;
}

/* 滚动态**只**补一道分隔阴影：底色不透明度、文字/图标/logo/搜索框、压暗层全部沿用
   「沉浸栏不透明度」那一套（header.php 输出底色，.joe-immersive-solid 切深色字），
   所以页面上沿和滚动后是同一套观感，不会出现"滚一下就换脸"。 */

/* ==================== 整体框架效果（分类列表 →「整体框架效果」） ==================== */
/* 作用对象是"装着左右侧栏 + 正文"的那个容器：结构是 body > #Joe > .joe_container
   （`:not(.joe_bread)` 是 2026-10-08 之前留下的排除项：当时正文前面还有一条同级的
   .joe_container.joe_bread 面包屑栏；现在面包屑已挪进文章卡，这里留着无副作用）。
   四周留出空隙 + 圆角/描边，看起来就是一块浮在壁纸上的面板，页头页脚在框外。
   ⚠️ 不要给这个容器加 overflow（圆角靠内边距让开就行）—— 一加 overflow 侧栏的
   position:sticky 就会失效（它会是相对这个不滚动的容器吸附）。 */
body[class*='joe-pageframe--'] #Joe > .joe_container:not(.joe_bread) {
    /* 关键：容器要比视口窄，四边才留得出壁纸 —— 否则 1440 宽时左右两条边就贴到屏幕外了 */
    width: calc(100% - 52px);
    max-width: 1560px;
    margin: 22px auto;
    padding: 18px;
    border-radius: 20px;
}

body.joe-pageframe--panel #Joe > .joe_container:not(.joe_bread) {
    background: var(--background);
    box-shadow: 0 18px 44px -24px rgba(0, 0, 0, .5);
}

/* 毛玻璃（保留）：半透明白 + 背景模糊 + 亮边，壁纸在框内继续透出来 */
body.joe-pageframe--glass #Joe > .joe_container:not(.joe_bread) {
    border: 1px solid rgba(255, 255, 255, .55);
    background: rgba(255, 255, 255, .3);
    -webkit-backdrop-filter: blur(12px) saturate(1.25);
    backdrop-filter: blur(12px) saturate(1.25);
}

/* 柔影卡片（新）：不描边，靠一大片极柔和的投影把面板"托"起来，圆角更大更软 */
body.joe-pageframe--soft #Joe > .joe_container:not(.joe_bread) {
    border-radius: 26px;
    background: rgba(255, 255, 255, .62);
    box-shadow: 0 26px 62px -30px rgba(15, 23, 42, .42), 0 2px 8px -4px rgba(15, 23, 42, .18);
}

html[data-night='night'] body.joe-pageframe--soft #Joe > .joe_container:not(.joe_bread) {
    background: rgba(38, 38, 38, .62);
    box-shadow: 0 26px 62px -30px rgba(0, 0, 0, .8);
}

/* 渐变描边（新）：用 background 双层裁切做出主题色渐变边框（内层实色 padding-box，外层渐变 border-box） */
body.joe-pageframe--gradient #Joe > .joe_container:not(.joe_bread) {
    border: 1px solid transparent;
    background-image: linear-gradient(rgba(255, 255, 255, .74), rgba(255, 255, 255, .74)), linear-gradient(135deg, var(--theme), #a855f7 58%, #38bdf8);
    background-origin: border-box;
    background-clip: padding-box, border-box;
}

html[data-night='night'] body.joe-pageframe--gradient #Joe > .joe_container:not(.joe_bread) {
    background-image: linear-gradient(rgba(35, 35, 35, .74), rgba(35, 35, 35, .74)), linear-gradient(135deg, var(--theme), #a855f7 58%, #38bdf8);
}

/* 主题光晕（新）：主题色外发光，和"卡片投影"的区别是发光有颜色 */
body.joe-pageframe--glow #Joe > .joe_container:not(.joe_bread) {
    border: 1px solid rgba(255, 255, 255, .7);
    background: rgba(255, 255, 255, .66);
    box-shadow: 0 12px 44px -14px var(--theme);
}

html[data-night='night'] body.joe-pageframe--glow #Joe > .joe_container:not(.joe_bread) {
    border-color: rgba(255, 255, 255, .12);
    background: rgba(38, 38, 38, .66);
    box-shadow: 0 12px 44px -14px var(--theme);
}

/* 四角角标（新）：科技风，只在左上 / 右下画两个 L 形角标（::before / ::after，不碰内容） */
body.joe-pageframe--corner #Joe > .joe_container:not(.joe_bread) {
    position: relative;
    background: rgba(255, 255, 255, .62);
}

body.joe-pageframe--corner #Joe > .joe_container:not(.joe_bread)::before,
body.joe-pageframe--corner #Joe > .joe_container:not(.joe_bread)::after {
    position: absolute;
    width: 18px;
    height: 18px;
    border: 2px solid var(--theme);
    content: '';
    pointer-events: none;
}

body.joe-pageframe--corner #Joe > .joe_container:not(.joe_bread)::before {
    top: 7px;
    left: 7px;
    border-right: 0;
    border-bottom: 0;
    border-top-left-radius: 7px;
}

body.joe-pageframe--corner #Joe > .joe_container:not(.joe_bread)::after {
    right: 7px;
    bottom: 7px;
    border-top: 0;
    border-left: 0;
    border-bottom-right-radius: 7px;
}

html[data-night='night'] body.joe-pageframe--corner #Joe > .joe_container:not(.joe_bread) {
    background: rgba(38, 38, 38, .62);
}

/* 顶部光条（新）：顶端一道主题色渐变亮条，其余极简（注意不能写 overflow，角标要能贴到圆角外沿） */
body.joe-pageframe--beam #Joe > .joe_container:not(.joe_bread) {
    position: relative;
    border: 1px solid rgba(255, 255, 255, .6);
    background: rgba(255, 255, 255, .62);
}

body.joe-pageframe--beam #Joe > .joe_container:not(.joe_bread)::before {
    position: absolute;
    top: 0;
    left: 22px;
    right: 22px;
    height: 3px;
    border-radius: 0 0 3px 3px;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0), var(--theme) 18%, var(--theme) 82%, rgba(255, 255, 255, 0));
    content: '';
    pointer-events: none;
}

html[data-night='night'] body.joe-pageframe--beam #Joe > .joe_container:not(.joe_bread) {
    border-color: rgba(255, 255, 255, .12);
    background: rgba(38, 38, 38, .62);
}

html[data-night='night'] body.joe-pageframe--glass #Joe > .joe_container:not(.joe_bread) {
    border-color: rgba(255, 255, 255, .14);
    background: rgba(35, 35, 35, .3);
}

/* 手机 / 窄屏：框架和间距都收窄，别把内容挤扁 */
@media (max-width: 992px) {
    body[class*='joe-pageframe--'] #Joe > .joe_container:not(.joe_bread) {
        width: calc(100% - 24px);
        margin: 12px auto;
        padding: 12px;
        border-radius: 14px;
    }

    body.joe-pageframe--soft #Joe > .joe_container:not(.joe_bread) {
        border-radius: 18px;
    }

    /* 角标 / 光条跟着收窄 */
    body.joe-pageframe--corner #Joe > .joe_container:not(.joe_bread)::before,
    body.joe-pageframe--corner #Joe > .joe_container:not(.joe_bread)::after {
        width: 14px;
        height: 14px;
        border-width: 2px;
    }

    body.joe-pageframe--corner #Joe > .joe_container:not(.joe_bread)::before {
        top: 5px;
        left: 5px;
    }

    body.joe-pageframe--corner #Joe > .joe_container:not(.joe_bread)::after {
        right: 5px;
        bottom: 5px;
    }

    body.joe-pageframe--beam #Joe > .joe_container:not(.joe_bread)::before {
        left: 16px;
        right: 16px;
    }
}

/* ==================== 整体框架效果 · 第二批（2026-10-09 新增 5 种） ====================
 * 和上面一批走同一套机制（作用在 #Joe > .joe_container，共享"收窄 + 留边"的基础规则），
 * 所以这里只写各自的观感。 */
body.joe-pageframe--neon #Joe > .joe_container:not(.joe_bread) {
    border: 1px solid var(--theme);
    background: rgba(255, 255, 255, .6);
    box-shadow: 0 0 0 1px rgba(64, 158, 255, .18), 0 0 30px -8px var(--theme), inset 0 0 26px -16px var(--theme);
}

html[data-night='night'] body.joe-pageframe--neon #Joe > .joe_container:not(.joe_bread) {
    background: rgba(35, 35, 35, .6);
    box-shadow: 0 0 0 1px rgba(84, 181, 219, .22), 0 0 30px -8px var(--theme), inset 0 0 26px -16px var(--theme);
}

/* 网格纸：淡蓝网格铺底（工程图纸感）。卡片本身是半透明的，网格会微微透出来 */
body.joe-pageframe--grid #Joe > .joe_container:not(.joe_bread) {
    border: 1px solid var(--classB);
    background-color: rgba(255, 255, 255, .66);
    background-image: linear-gradient(rgba(64, 158, 255, .09) 1px, transparent 1px),
        linear-gradient(90deg, rgba(64, 158, 255, .09) 1px, transparent 1px);
    background-size: 22px 22px;
}

html[data-night='night'] body.joe-pageframe--grid #Joe > .joe_container:not(.joe_bread) {
    border-color: rgba(255, 255, 255, .12);
    background-color: rgba(35, 35, 35, .66);
    background-image: linear-gradient(rgba(84, 181, 219, .15) 1px, transparent 1px),
        linear-gradient(90deg, rgba(84, 181, 219, .15) 1px, transparent 1px);
}

/* 左右彩边：只有左右两条主题色渐变竖边，其余极简 */
body.joe-pageframe--stripe #Joe > .joe_container:not(.joe_bread) {
    background-color: rgba(255, 255, 255, .62);
    background-image: linear-gradient(180deg, var(--theme), #a855f7 55%, #38bdf8),
        linear-gradient(180deg, #38bdf8 45%, #a855f7, var(--theme));
    background-size: 4px 100%;
    background-position: left top, right top;
    background-repeat: no-repeat;
}

html[data-night='night'] body.joe-pageframe--stripe #Joe > .joe_container:not(.joe_bread) {
    background-color: rgba(35, 35, 35, .62);
}

/* 四角框线：四个角都画 L 形线（8 层背景一次画完，不占伪元素）。
   比「四角角标」多出右上 / 左下两个角，更硬朗 */
body.joe-pageframe--corner4 #Joe > .joe_container:not(.joe_bread) {
    position: relative;
    border: 1px solid rgba(255, 255, 255, .5);
    background: rgba(255, 255, 255, .6);
    box-shadow: 0 12px 34px -22px rgba(15, 23, 42, .5);
}

body.joe-pageframe--corner4 #Joe > .joe_container:not(.joe_bread)::before {
    position: absolute;
    top: 9px;
    right: 9px;
    bottom: 9px;
    left: 9px;
    background-image:
        linear-gradient(var(--theme), var(--theme)), linear-gradient(var(--theme), var(--theme)),
        linear-gradient(var(--theme), var(--theme)), linear-gradient(var(--theme), var(--theme)),
        linear-gradient(var(--theme), var(--theme)), linear-gradient(var(--theme), var(--theme)),
        linear-gradient(var(--theme), var(--theme)), linear-gradient(var(--theme), var(--theme));
    background-size: 22px 3px, 3px 22px, 22px 3px, 3px 22px, 22px 3px, 3px 22px, 22px 3px, 3px 22px;
    background-position: left top, left top, right top, right top, left bottom, left bottom, right bottom, right bottom;
    background-repeat: no-repeat;
    content: '';
    pointer-events: none;
}

html[data-night='night'] body.joe-pageframe--corner4 #Joe > .joe_container:not(.joe_bread) {
    border-color: rgba(255, 255, 255, .12);
    background: rgba(35, 35, 35, .6);
}

/* 内凹相框：四边内阴影往里压暗，像嵌进墙里的相框（和"外投影"的柔影卡片观感相反） */
body.joe-pageframe--inset #Joe > .joe_container:not(.joe_bread) {
    border: 1px solid rgba(255, 255, 255, .5);
    background: rgba(255, 255, 255, .5);
    box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .07),
        inset 0 16px 30px -20px rgba(15, 23, 42, .55), inset 0 -16px 30px -20px rgba(15, 23, 42, .55),
        inset 16px 0 30px -20px rgba(15, 23, 42, .55), inset -16px 0 30px -20px rgba(15, 23, 42, .55);
}

html[data-night='night'] body.joe-pageframe--inset #Joe > .joe_container:not(.joe_bread) {
    border-color: rgba(255, 255, 255, .1);
    background: rgba(35, 35, 35, .5);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .45),
        inset 0 16px 30px -20px rgba(0, 0, 0, .9), inset 0 -16px 30px -20px rgba(0, 0, 0, .9),
        inset 16px 0 30px -20px rgba(0, 0, 0, .9), inset -16px 0 30px -20px rgba(0, 0, 0, .9);
}

/* 手机 / 窄屏：第二批框架的角标往里收，别占掉太多可视区 */
@media (max-width: 992px) {
    body.joe-pageframe--corner4 #Joe > .joe_container:not(.joe_bread)::before {
        top: 6px;
        right: 6px;
        bottom: 6px;
        left: 6px;
    }
}

/* ==================== 列表文字可读性（首页 / 标签 / 搜索列表） ==================== */
/* 痛点：卡片底色是半透明白（组件透明度 + 背景图透上来），而摘要和元信息用的是
   --minor #909399 —— 压在花花绿绿的壁纸上几乎看不清（用户 2026-10-08 反馈）。
   层级重排：标题 > 摘要 > 元信息，三层都要拉开对比度。
   作用对象是 li.joe_list__item，首页（.joe_index__list）与标签/搜索（.joe_archive__list）共用。 */
.joe_list__item .title {
    font-weight: 500;
    transition: color 0.25s;
}

.joe_list__item .title:hover {
    color: var(--theme);
}

/* 摘要：主题原规则是 `.joe_list__item .information .abstract`（比下面多一层 .information，
   少写这层会被它压掉），而且带 **opacity:.85** + `max-height:44px` / `line-height:22px`（正好两行）。
   → 色值加深 + **去掉 opacity**（这才是"看不清"的主因）+ 行高放松到 1.7，max-height 同步放到 50px。 */
.joe_list__item .information .abstract {
    color: #4e525a;
    line-height: 1.7;
    max-height: 50px;
    opacity: 1;
}

html[data-night='night'] .joe_list__item .information .abstract {
    color: #9a9ea6;
}

/* 元信息（日期 / 阅读 / 评论 / 分类）：比摘要弱、但也要看得清 */
.joe_list__item .meta {
    color: #7c818a;
}

html[data-night='night'] .joe_list__item .meta {
    color: #7e828a;
}

/* 分类名是个链接，给深一档 + hover 主题色，让人看得出能点 */
.joe_list__item .meta .last .link {
    color: var(--routine);
    transition: color 0.25s;
}

html[data-night='night'] .joe_list__item .meta .last .link {
    color: #a8acb4;
}

.joe_list__item .meta .last .link:hover {
    color: var(--theme);
}

/* ==================== 文章目录（右侧边栏最底下的一张卡） ====================
 * 2026-10-09：原来做的是固定在右侧的浮动面板，现在改成边栏组件里的一张卡
 * （.joe_aside__item.toc，由 side.php 在排序最后输出），跟随侧栏一起吸顶/滚走。
 * 标题清单由 toc_card.php 末尾的 JS 从 .joe_detail__article 里提取。
 * 标题少于 3 个时 JS 会把整张卡 remove()，不会留空壳。 */
.joe_aside__item.toc {
    /* 与其它组件一致：不吃主题的 sticky，卡片级定位只是给内部绝对定位用。
       （「右栏不固定」时会在下面的媒体查询里被改成 sticky 吸顶） */
    position: relative;
    /* 吸顶时浮在正文/其它卡片之上 */
    z-index: 5;
    /* 底色一律跟其它侧栏卡片一样用 var(--background)：
       白天 #fff、夜间 #232323，配了「网站背景」图时主题会把它改成
       rgba(...,.56) 的半透明白/黑 —— 直接写死 #fff/#262626 会和旁边卡片不一致
       （2026-10-09 实测：兄弟卡片 rgba(255,255,255,.561)，本卡 rgb(255,255,255)）。 */
    background: var(--background);
}

/* 吸顶时给一圈投影，让它和下面的内容分层（位置由 CSS sticky 决定，不依赖 JS 类名） */
.joe_aside__item.toc {
    box-shadow: 0 10px 30px -20px rgba(0, 0, 0, .45);
}

html[data-night='night'] .joe_aside__item.toc {
    box-shadow: 0 10px 30px -18px rgba(0, 0, 0, .8);
}

.joe_aside__item.toc .joe-toc__title {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 0 0 6px;
    padding: 0 0 8px;
    border-bottom: 1px solid var(--classC);
    color: var(--routine);
    font-size: 13px;
    font-weight: 700;
}

.joe_aside__item.toc .joe-toc__title svg {
    width: 15px;
    height: 15px;
    fill: var(--theme);
}

.joe_aside__item.toc .joe-toc__list {
    /* 侧栏卡片宽度只有 250px，最多显示十来行，超出内部滚动 */
    max-height: 300px;
    margin: 0;
    padding: 0 2px 0 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    list-style: none;
    scrollbar-width: thin;
}

.joe_aside__item.toc .joe-toc__list::-webkit-scrollbar {
    width: 5px;
}

.joe_aside__item.toc .joe-toc__list::-webkit-scrollbar-thumb {
    background: var(--classA);
    border-radius: 3px;
}

.joe_aside__item.toc .joe-toc__item {
    display: block;
    padding: 5px 9px;
    border-radius: 7px;
    color: var(--routine);
    font-size: 12.5px;
    line-height: 1.5;
    cursor: pointer;
    transition: background .18s, color .18s;
}

.joe_aside__item.toc .joe-toc__item:hover {
    background: var(--classD);
    color: var(--theme);
}

/* 当前所在章节：主题色胶囊 + 白字（参考 yolos.cn 的高亮样式） */
.joe_aside__item.toc .joe-toc__item.is-active {
    color: #fff;
    background: var(--theme);
    font-weight: 500;
}

.joe_aside__item.toc .joe-toc__item.is-active:hover {
    color: #fff;
}

/* 层级缩进：h2→h6 逐级右移，让结构一眼看清 */
.joe_aside__item.toc .joe-toc__item[data-level="1"] {
    padding-left: 9px;
}

.joe_aside__item.toc .joe-toc__item[data-level="2"] {
    padding-left: 20px;
    font-size: 12px;
}

.joe_aside__item.toc .joe-toc__item[data-level="3"] {
    padding-left: 31px;
    font-size: 11.5px;
}

.joe_aside__item.toc .joe-toc__item[data-level="4"],
.joe_aside__item.toc .joe-toc__item[data-level="5"] {
    padding-left: 42px;
    font-size: 11.5px;
    color: var(--minor);
}

.joe_aside__item.toc .joe-toc__item.is-active[data-level="4"],
.joe_aside__item.toc .joe-toc__item.is-active[data-level="5"] {
    color: #fff;
}
