/* src/assets/transitions.css
 *
 * 站点级运动设计令牌 + 可复用 .t-* 类（参考 transitions.dev 设计语汇）。
 * 所有交互按钮统一通过 .t-btn / .t-btn-icon 取得动效，
 * 不再各自手写 transition / hover lift / shadow。
 *
 * 时长 / 缓动统一用 CSS 自定义属性表达，便于全局微调。
 *
 * 入口约定：
 *   - <link rel="stylesheet" href="...assets/transitions.css"> 由 head-base.html
 *     与 template_post.html 引入，所有页面都能命中。
 *   - .t-btn        外形/填充按钮（Share / Go Back / View All / 分页器）
 *   - .t-btn-icon   圆形图标按钮（顶栏搜索 / 主题切换 / 浮动按钮 / 复制按钮）
 */

:root {
    /* ===== Button motion tokens ===== */
    --t-btn-dur: 280ms;
    --t-btn-hover-delay: 45ms;
    --t-btn-press-dur: 110ms;
    --t-btn-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --t-btn-press-ease: cubic-bezier(0.4, 0, 0.6, 1);

    --t-btn-lift: -0.75px;
    --t-btn-press-scale: 0.98;
    --t-btn-icon-press-scale: 0.92;

    /* ===== Theme switch motion tokens ===== */
    --theme-transition-dur: 360ms;
    --theme-transition-ease: cubic-bezier(0.22, 1, 0.36, 1);

    /* ===== 全站统一：固定顶栏的占位与安全间距 =====
       所有页面以此为内容起点的最小上偏移；JS 会按真实 header 高度做实时同步。
       --freecat-page-top-offset 是“header 高度 + 安全间距”的合成值，
       任何主内容容器的 margin-top / padding-top 都应优先使用它，
       避免出现"hardcode 40px / 60px 但 header 实际更高"导致的遮挡。 */
    --freecat-header-height: 61px;
    --freecat-header-safe-gap: 16px;
    --freecat-page-top-offset: calc(var(--freecat-header-height) + var(--freecat-header-safe-gap));
}

/* Shared placeholder loading spinner. */
.loader {
    border: 4px solid rgba(0, 0, 0, .1);
    border-left-color: transparent;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    animation: spin89345 1s linear infinite;
}

.lazy-image-frame {
    position: relative;
}

.placeholder-loader {
    position: absolute;
    top: 0.75rem;
    left: 0.75rem;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

.lazy-image-frame>img:not([data-src])+.placeholder-loader {
    display: none;
}

.dark .loader {
    border-color: rgba(255, 255, 255, 0.6);
    border-left-color: transparent;
}

@keyframes spin89345 {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}

@media (min-width: 768px) {
    :root {
        --freecat-header-height: 73px;
        --freecat-header-safe-gap: 24px;
    }
}

/* ============================================================
 * .t-btn —— 外形/填充按钮统一动效
 * 适用：Share / Go Back / View All / 分页 Prev/Next / 分页页码
 * 行为：hover 轻微抬升并带短延迟；active 下沉 + 轻缩放，press_dur 更短给更"实"的触感
 *      （不使用 box-shadow，纯 transform + 颜色过渡）
 * ============================================================ */
.t-btn {
    transition:
        transform var(--t-btn-dur) var(--t-btn-ease),
        background-color var(--t-btn-dur) var(--t-btn-ease),
        border-color var(--t-btn-dur) var(--t-btn-ease),
        color var(--t-btn-dur) var(--t-btn-ease),
        opacity var(--t-btn-dur) var(--t-btn-ease),
        filter var(--t-btn-dur) var(--t-btn-ease);
    transition-delay: 0ms;
    will-change: transform;
}

.t-btn:not([disabled]):not([aria-disabled="true"]):hover {
    transform: translateY(var(--t-btn-lift));
    transition-delay: var(--t-btn-hover-delay);
}

.t-btn:not([disabled]):not([aria-disabled="true"]):active {
    transform: translateY(0) scale(var(--t-btn-press-scale));
    transition:
        transform var(--t-btn-press-dur) var(--t-btn-press-ease);
    transition-delay: 0ms;
}

.t-btn[disabled],
.t-btn[aria-disabled="true"] {
    opacity: 0.4;
    pointer-events: none;
    transform: none;
}

.t-btn.t-btn-outline-subtle {
    background-color: transparent;
    border-color: rgba(148, 163, 184, 0.38);
    color: #64748b;
    transition:
        border-color 460ms cubic-bezier(0.4, 0, 0.2, 1) 110ms,
        outline-color 460ms cubic-bezier(0.4, 0, 0.2, 1) 110ms;
    will-change: border-color;
}

.t-btn.t-btn-outline-subtle:not([disabled]):not([aria-disabled="true"]):hover {
    border-color: rgba(100, 116, 139, 0.42);
    background-color: transparent;
    color: #64748b;
    transform: none;
}

.t-btn.t-btn-outline-subtle:not([disabled]):not([aria-disabled="true"]):active {
    border-color: rgba(100, 116, 139, 0.46);
    transform: none;
    transition-delay: 0ms;
}

.t-btn.t-btn-outline-subtle:focus-visible {
    outline: 2px solid rgba(148, 163, 184, 0.42);
    outline-offset: 3px;
}

.dark .t-btn.t-btn-outline-subtle {
    border-color: rgba(100, 116, 139, 0.48);
    color: #cbd5e1;
}

.dark .t-btn.t-btn-outline-subtle:not([disabled]):not([aria-disabled="true"]):hover {
    border-color: rgba(148, 163, 184, 0.54);
    background-color: transparent;
    color: #cbd5e1;
}

.dark .t-btn.t-btn-outline-subtle:not([disabled]):not([aria-disabled="true"]):active {
    border-color: rgba(148, 163, 184, 0.58);
}

.dark .t-btn.t-btn-outline-subtle:focus-visible {
    outline-color: rgba(148, 163, 184, 0.46);
}

/* 内部图标的 hover 微动效（向左 / 上下），由父 .group 控制 */
.t-btn:hover .t-btn-arrow-prev,
.t-btn-icon:hover .t-btn-arrow-prev {
    transform: translateX(-2px);
}
.t-btn:hover .t-btn-arrow-up,
.t-btn-icon:hover .t-btn-arrow-up {
    transform: translateY(-2px);
}
.t-btn:hover .t-btn-arrow-down,
.t-btn-icon:hover .t-btn-arrow-down {
    transform: translateY(2px);
}

/* ============================================================
 * .t-btn-icon —— 圆形图标按钮（无抬升，仅按压缩放）
 * 适用：顶栏搜索 / 主题 / 移动端 about / 浮动导航按钮 / 折叠按钮
 * ============================================================ */
.t-btn-icon {
    transition:
        transform var(--t-btn-dur) var(--t-btn-ease),
        background-color var(--t-btn-dur) var(--t-btn-ease),
        border-color var(--t-btn-dur) var(--t-btn-ease),
        color var(--t-btn-dur) var(--t-btn-ease),
        opacity var(--t-btn-dur) var(--t-btn-ease),
        filter var(--t-btn-dur) var(--t-btn-ease);
    will-change: transform, color;
}

.t-btn-icon:not([disabled]):not([aria-disabled="true"]):active {
    transform: scale(var(--t-btn-icon-press-scale));
    transition:
        transform var(--t-btn-press-dur) var(--t-btn-press-ease);
}

/* ============================================================
 * .t-floating-nav —— 浮动导航按钮（返回顶部 / 落到底部 / 返回上一页）
 * 与普通 .t-btn-icon 的差异：
 *   - 入场/离场是滚动驱动的状态切换（opacity 0↔1），需要更长 + 更柔的过渡，
 *     不能用 220ms expo-out（到末端急刹）；这里用 360ms 标准 ease-out。
 *   - 不再使用 visibility:hidden 做硬切，改用 opacity + pointer-events，
 *     避免 opacity 还在淡出时元素已经被 visibility 一刀切。
 *   - hover 颜色 + 内嵌箭头位移也走同一条慢节奏曲线，整体反馈连贯。
 *
 * 用法：在按钮上同时挂 .t-btn-icon 和 .t-floating-nav；
 *      JS 通过切换 .is-hidden 控制显隐（不要再用 invisible / opacity-0 等）。
 * ============================================================ */
.freecat-floating-nav-panel {
    --freecat-floating-nav-base-left: calc(50% + 780px + 6rem);
    --freecat-floating-nav-safe-edge: 1rem;
    --freecat-floating-nav-width: 3rem;
    display: none;
    position: fixed;
    top: 8rem;
    left: min(
        var(--freecat-floating-nav-base-left),
        calc(100vw - var(--freecat-floating-nav-width) - var(--freecat-floating-nav-safe-edge))
    );
    right: auto;
    height: calc(100vh - 300px);
    flex-direction: column;
    align-items: center;
    /* 整组按钮垂直居中；返回上一页与上面两个按钮之间留约两个身位（96px）的间距 */
    justify-content: center;
    gap: 6rem;
    transition: opacity 180ms ease-out, visibility 180ms ease-out;
}

@media (min-width: 1024px) {
    .freecat-floating-nav-panel {
        display: flex;
    }
}

.freecat-floating-nav-panel.is-layout-hidden {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* 首页隐藏返回上一页按钮（保留占位，避免上面两个按钮的居中点偏移） */
body[data-page="home"] #floating-go-back {
    visibility: hidden;
    pointer-events: none;
}

/* 顶栏搜索激活时，隐藏浮动按钮块 */
body.search-active .freecat-floating-nav-panel {
    display: none !important;
}

.t-floating-nav {
    transition:
        opacity 360ms cubic-bezier(0.4, 0, 0.2, 1),
        transform 360ms cubic-bezier(0.4, 0, 0.2, 1),
        background-color 320ms cubic-bezier(0.4, 0, 0.2, 1),
        color 320ms cubic-bezier(0.4, 0, 0.2, 1);
    pointer-events: auto;
}

.t-floating-nav.is-hidden {
    opacity: 0;
    transform: translateY(6px);
    pointer-events: none;
}

/* hover 颜色与箭头微动效 —— 用同一条 320ms ease-out 曲线，避免与显隐节奏打架 */
.t-floating-nav .t-btn-arrow-up,
.t-floating-nav .t-btn-arrow-down,
.t-floating-nav .t-btn-arrow-prev {
    transition: transform 320ms cubic-bezier(0.4, 0, 0.2, 1);
}

.t-floating-nav:hover .t-btn-arrow-up    { transform: translateY(-1.5px); }
.t-floating-nav:hover .t-btn-arrow-down  { transform: translateY(1.5px); }
.t-floating-nav:hover .t-btn-arrow-prev  { transform: translateX(-1.5px); }

@media (prefers-reduced-motion: reduce) {
    .t-floating-nav,
    .t-floating-nav .t-btn-arrow-up,
    .t-floating-nav .t-btn-arrow-down,
    .t-floating-nav .t-btn-arrow-prev {
        transition: none !important;
    }
    .t-floating-nav.is-hidden { transform: none; }
}

/* ============================================================
 * #share-btn —— 文章页 Share 按钮的状态切换
 * 设计语言：克制 / 简洁 / 高端
 *  - 默认态：显示 share 图标 + "Share"
 *  - copied 态（data-state="copied"）：图标 crossfade 成对勾，文案替换
 *  - 全程仅用 opacity 过渡，没有 scale / translate / bounce
 * ============================================================ */
#share-btn .share-btn-icon,
#share-btn .share-btn-label {
    transition: opacity var(--t-btn-dur) var(--t-btn-ease);
}

#share-btn:not([disabled]):not([aria-disabled="true"]):hover {
    transform: none;
}

#share-btn .share-btn-icon-default {
    opacity: 1;
}
#share-btn .share-btn-icon-done {
    opacity: 0;
}
#share-btn[data-state="copied"] .share-btn-icon-default {
    opacity: 0;
}
#share-btn[data-state="copied"] .share-btn-icon-done {
    opacity: 1;
}

/* ============================================================
 * Reduced motion guard
 * ============================================================ */
@media (prefers-reduced-motion: reduce) {
    .t-btn,
    .t-btn-icon {
        transition: none !important;
    }

    .t-btn:hover,
    .t-btn:active,
    .t-btn-icon:hover,
    .t-btn-icon:active,
    .t-btn:hover .t-btn-arrow-prev,
    .t-btn:hover .t-btn-arrow-up,
    .t-btn:hover .t-btn-arrow-down {
        transform: none !important;
    }
}

/* ============================================================
 * 全站共享动画 / 状态类（曾经在 main.js 运行时注入，现移到此处避免 FOUC）
 * 包含：fadeInUp / t-panel-slide / t-dropdown / page-transitioning-* /
 *      icon-breathe / body.search-active 遮罩
 * ============================================================ */

:root {
    --dropdown-open-dur: 250ms;
    --dropdown-close-dur: 150ms;
    --dropdown-pre-scale: 0.97;
    --dropdown-closing-scale: 0.99;
    --dropdown-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --panel-open-dur: 400ms;
    --panel-close-dur: 350ms;
    --panel-translate-y: 32px;
    --panel-blur: 2px;
    --panel-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --page-slide-dur: 200ms;
    --page-fade-dur: 200ms;
    --page-slide-distance: 8px;
    --page-blur: 3px;
    --page-slide-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --page-fade-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --icon-swap-dur: 200ms;
    --icon-swap-blur: 2px;
    --icon-swap-start-scale: 0.25;
    --icon-swap-ease: ease-in-out;
    --post-card-enter-dur: 680ms;
    --post-card-enter-ease: cubic-bezier(0.16, 1, 0.3, 1);
    --post-card-hover-dur: 260ms;
}

/* 始终预留垂直滚动条宽度，避免 body.overflow:hidden 切换时
   视口宽度变化导致 fixed header 内的导航按钮整体抖动 */
html {
    scrollbar-gutter: stable;
    overflow-anchor: none;
    color-scheme: light;
}

html.dark {
    color-scheme: dark;
}

::view-transition-old(root),
::view-transition-new(root) {
    animation-duration: var(--theme-transition-dur);
    animation-timing-function: var(--theme-transition-ease);
    mix-blend-mode: normal;
}

html.theme-transitioning,
html.theme-transitioning body,
html.theme-transitioning body *,
html.theme-transitioning body *::before,
html.theme-transitioning body *::after {
    transition-property:
        color,
        background-color,
        border-color,
        outline-color,
        text-decoration-color,
        fill,
        stroke,
        box-shadow,
        opacity,
        filter,
        backdrop-filter !important;
    transition-duration: var(--theme-transition-dur) !important;
    transition-timing-function: var(--theme-transition-ease) !important;
    transition-delay: 0ms !important;
}

html.theme-view-transitioning,
html.theme-view-transitioning body,
html.theme-view-transitioning body *,
html.theme-view-transitioning body *::before,
html.theme-view-transitioning body *::after {
    transition: none !important;
    animation-play-state: paused !important;
}

@keyframes fadeInUp {
    from { opacity: 0; transform: translate3d(0, 14px, 0) scale(0.992); }
    to   { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}

.animate-fade-in-up {
    animation: fadeInUp var(--post-card-enter-dur) var(--post-card-enter-ease) both;
    opacity: 0;
    transform-origin: center top;
    will-change: opacity, transform;
}

.delay-150 {
    animation-delay: 150ms;
}

.delay-300 {
    animation-delay: 300ms;
}

.freecat-about-social > a {
    animation: fadeInUp var(--post-card-enter-dur) var(--post-card-enter-ease) both;
    animation-delay: calc(450ms + (var(--freecat-social-index, 0) * 70ms));
    opacity: 0;
    transform-origin: center top;
    will-change: opacity, transform;
}

.post-card > div {
    transition:
        box-shadow var(--post-card-hover-dur) var(--post-card-enter-ease),
        border-color var(--post-card-hover-dur) var(--post-card-enter-ease);
}

.t-panel-slide {
    transform: translateY(var(--panel-translate-y));
    opacity: 0;
    filter: blur(var(--panel-blur));
    pointer-events: none;
    transition:
        transform var(--panel-close-dur) var(--panel-ease),
        opacity var(--panel-close-dur) var(--panel-ease),
        filter var(--panel-close-dur) var(--panel-ease);
    will-change: transform, opacity, filter;
}

.t-panel-slide[data-open="true"] {
    transform: translateY(0);
    opacity: 1;
    filter: blur(0);
    pointer-events: auto;
    transition:
        transform var(--panel-open-dur) var(--panel-ease),
        opacity var(--panel-open-dur) var(--panel-ease),
        filter var(--panel-open-dur) var(--panel-ease);
}

.t-dropdown {
    transform-origin: top right;
    transform: scale(var(--dropdown-pre-scale));
    opacity: 0;
    pointer-events: none;
    transition:
        transform var(--dropdown-open-dur) var(--dropdown-ease),
        opacity var(--dropdown-open-dur) var(--dropdown-ease);
    will-change: transform, opacity;
}

.t-dropdown[data-origin="top-left"] { transform-origin: top left; }
.t-dropdown[data-origin="top-center"] { transform-origin: top center; }
.t-dropdown[data-origin="top-right"] { transform-origin: top right; }
.t-dropdown[data-origin="bottom-left"] { transform-origin: bottom left; }
.t-dropdown[data-origin="bottom-center"] { transform-origin: bottom center; }
.t-dropdown[data-origin="bottom-right"] { transform-origin: bottom right; }

.t-dropdown.is-open {
    transform: scale(1);
    opacity: 1;
    pointer-events: auto;
}

.t-dropdown.is-closing {
    transform: scale(var(--dropdown-closing-scale));
    opacity: 0;
    pointer-events: none;
    transition:
        transform var(--dropdown-close-dur) var(--dropdown-ease),
        opacity var(--dropdown-close-dur) var(--dropdown-ease);
}

.tag-menu-panel {
    backdrop-filter: blur(18px);
    translate: -50% 0;
    width: max-content;
    min-width: 14rem;
    max-width: calc(100vw - 2rem);
}

.tag-menu-items {
    scrollbar-width: thin;
}

.tag-menu-item {
    opacity: 0;
    transform: translateY(-4px);
}

.tag-menu-panel.is-open .tag-menu-item {
    opacity: 1;
    transform: translateY(0);
    transition:
        opacity 180ms var(--dropdown-ease),
        transform 180ms var(--dropdown-ease),
        background-color 150ms ease,
        color 150ms ease;
    transition-delay: calc(var(--tag-menu-index) * 18ms);
}

@media (max-width: 767px) {
    .tag-menu-panel {
        position: fixed !important;
        left: 1rem !important;
        right: 1rem !important;
        top: calc(var(--freecat-header-height, 64px) + 0.75rem) !important;
        width: auto !important;
        translate: 0 0;
        transform-origin: top center;
    }
}

.page-transitioning-out {
    opacity: 0;
    transform: translateX(calc(var(--page-slide-distance) * -1));
    filter: blur(var(--page-blur));
    transition:
        opacity var(--page-fade-dur) var(--page-fade-ease),
        transform var(--page-slide-dur) var(--page-slide-ease),
        filter var(--page-slide-dur) var(--page-slide-ease);
}

.page-transitioning-in {
    animation: pageSlideIn var(--page-slide-dur) var(--page-slide-ease) both;
}

@keyframes pageSlideIn {
    from {
        opacity: 0;
        transform: translateX(var(--page-slide-distance));
        filter: blur(var(--page-blur));
    }
    to {
        opacity: 1;
        transform: translateX(0);
        filter: blur(0);
    }
}

.icon-breathe {
    transition:
        transform var(--icon-swap-dur) var(--icon-swap-ease),
        opacity var(--icon-swap-dur) var(--icon-swap-ease),
        filter var(--icon-swap-dur) var(--icon-swap-ease);
    will-change: transform, opacity, filter;
}

body.search-active {
    overflow: hidden !important;
}

body.search-active .page-blur-target {
    filter: blur(4px);
    opacity: 0.22;
    pointer-events: none;
    transition:
        filter var(--page-slide-dur) var(--page-slide-ease),
        opacity var(--page-fade-dur) var(--page-fade-ease);
    position: relative;
}

body.search-active .page-blur-target::before {
    content: '';
    position: fixed;
    inset: 0;
    background: radial-gradient(ellipse at center, rgba(255, 255, 255, 0.62) 0%, rgba(255, 255, 255, 0.94) 100%);
    pointer-events: none;
    z-index: 1;
}

.dark body.search-active .page-blur-target::before,
.dark.search-active .page-blur-target::before {
    background: radial-gradient(ellipse at center, rgba(8, 12, 20, 0.5) 0%, rgba(8, 12, 20, 0.82) 100%);
}

#search-results-overlay {
    backdrop-filter: blur(10px);
    overflow-y: auto;
    pointer-events: auto;
    transition:
        opacity var(--panel-open-dur) var(--panel-ease),
        transform var(--panel-open-dur) var(--panel-ease),
        filter var(--panel-open-dur) var(--panel-ease);
}

@media (prefers-reduced-motion: reduce) {
    ::view-transition-old(root),
    ::view-transition-new(root) {
        animation-duration: 1ms !important;
    }

    html.theme-transitioning,
    html.theme-transitioning body,
    html.theme-transitioning body *,
    html.theme-transitioning body *::before,
    html.theme-transitioning body *::after {
        transition: none !important;
    }

    .animate-fade-in-up,
    .freecat-about-social > a { animation: none !important; opacity: 1 !important; transform: none !important; }
    .post-card > div {
        transition: none !important;
    }
    .t-panel-slide,
    .t-dropdown,
    .tag-menu-item,
    .page-transitioning-out,
    .page-transitioning-in,
    .icon-breathe,
    #search-results-overlay,
    body.search-active .page-blur-target {
        transition: none !important;
        animation: none !important;
    }
}


/* ============================================================
 * 顶栏搜索激活时的遮罩 / 输入框定位（曾在 main.js 运行时注入，
 * 现挪到静态 CSS：避免首次激活搜索时的样式重排 + FOUC，
 * 也让样式可走 CSS 缓存，不必每次刷新页面再走 JS 注入）。
 * 入口：body.search-active 由 #search-toggle 的 click handler 切换。
 * ============================================================ */
body.search-active {
    overflow: hidden !important;
}
header.fixed {
    box-sizing: border-box;
    min-height: var(--freecat-header-height);
    height: var(--freecat-header-height);
    overflow: visible;
}

header.fixed .header-blur-target {
    height: 100%;
}

.search-active #search-container {
    position: absolute;
    left: 50%;
    top: 50%;
    right: auto;
    transform: translate(-50%, -50%);
    width: min(760px, calc(100vw - 8rem));
    max-width: 760px;
    z-index: 80;
}
@media (max-width: 767px) {
    .search-active #search-container {
        width: calc(100vw - 5.5rem);
        min-width: 0;
    }
}

.search-active .page-blur-target {
    filter: blur(4px);
    opacity: 0.18;
    pointer-events: none;
    transition: filter 0.2s cubic-bezier(0.2, 0, 0, 1), opacity 0.2s cubic-bezier(0.2, 0, 0, 1);
    position: relative;
}

.search-active .page-blur-target::before {
    content: '';
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background: radial-gradient(
        ellipse at center,
        rgba(255, 255, 255, 0.65) 0%,
        rgba(255, 255, 255, 0.95) 100%
    );
    pointer-events: none;
    z-index: 1;
}

.dark .search-active .page-blur-target::before {
    background: radial-gradient(
        ellipse at center,
        rgba(0, 0, 0, 0.45) 0%,
        rgba(0, 0, 0, 0.8) 100%
    );
}

.search-active .header-blur-target {
    opacity: 0;
    pointer-events: none;
    /* 不加 transition：搜索打开时直接隐藏，关闭时也直接复位，
       避免取消搜索后导航栏图标延迟出现 */
}

#search-results-overlay {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    backdrop-filter: blur(10px);
    background-color: rgba(255, 255, 255, 0.8) !important;
    overflow-y: auto;
    pointer-events: auto;
}
.dark #search-results-overlay {
    background-color: rgba(11, 15, 26, 0.8) !important;
}

/* ============================================================
 * 代码块折叠（曾在 post.js 运行时注入，现挪到静态 CSS）。
 * 文章页才用到，但放这里和搜索遮罩一并加载，能让 CSS 缓存命中更稳定，
 * 减少 FOUC；体积也只有几行，不构成额外负担。
 * ============================================================ */
.collapsed-code .code-content {
    overflow-y: hidden !important;
}
.collapsed-code .code-fold-controls {
    display: flex !important;
}
