@charset "utf-8";
/* ==========================================================================
   ResDown - Part 2 / hero, home modules, post detail, widgets, user center, modal
   ========================================================================== */

/* ============================ hero ============================ */

.rd-hero {
    position: relative;
    overflow: hidden;
    border-radius: var(--rd-radius-lg);
    background: radial-gradient(120% 140% at 12% 8%, #2448d8 0%, #1b2ea8 38%, #141a5c 74%, #0d1146 100%);
    color: #fff;
    padding: 38px 36px;
    margin-bottom: 20px;
}

.rd-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: linear-gradient(rgba(255, 255, 255, .05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .05) 1px, transparent 1px);
    background-size: 46px 46px;
    mask-image: radial-gradient(90% 90% at 20% 30%, #000 20%, transparent 78%);
    -webkit-mask-image: radial-gradient(90% 90% at 20% 30%, #000 20%, transparent 78%);
    pointer-events: none;
}

.rd-hero::after {
    content: "";
    position: absolute;
    width: 420px;
    height: 420px;
    right: -120px;
    top: -160px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(123, 63, 228, .55), transparent 66%);
    filter: blur(6px);
    pointer-events: none;
}

.rd-hero-in {
    position: relative;
    z-index: 2;
    display: grid;
    grid-template-columns: 1.35fr .92fr;
    gap: 34px;
    align-items: center;
}

/* ============================ 首页通栏头图 ============================
   .rd-hero.rd-bleed 配 .rd-bleed-in（style.css 里的通栏工具类）用。
   原先头图是个 1240px 内的圆角卡片，左右各留一块灰底；通栏之后深色渐变一直
   铺到屏幕两边，观感上「整页有主视觉」，而不是「页面上摆了一张宣传图」。

   分类页的头图（.rd-hero.is-sort）刻意不跟着通栏：那里是「我现在在哪一类」的
   上下文信息、不是营销位，保持卡片形态才有层级差别。 */
.rd-hero.rd-bleed {
    /* 抵掉 .rd-main 的上内边距，让深色直接顶到导航栏下沿。
       留一条浅色缝的话，头图会被看成「页面里的一个块」而不是页头。 */
    margin-top: calc(-1 * var(--rd-main-pt));
    /* 下外边距归零，把「卖点条骑进来多少」的控制权全部交给 .rd-trust-wrap。
       不归零的话两个外边距会相邻折叠相加（+20 与 -40 → 净 -20），
       于是想骑 40px 实际只骑了 20px，改数字时怎么都算不对。 */
    margin-bottom: 0;
    border-radius: 0;
    padding: 54px 0 64px;
    /* 底色比原先亮半档、去掉右上过重的紫斑：通栏后色块面积大了好几倍，
       原来的纯度铺满整屏会压得下面的内容发闷。 */
    background: radial-gradient(125% 150% at 14% 4%, #3563ff 0%, #2039c6 36%, #171e70 74%, #101554 100%);
}

/* 头图里的内容重新套回 1240px + 18px 内边距（.rd-bleed-in 提供），
   但网格本身要占满通栏宽度，否则右栏的热销榜会离开屏幕右侧太远。 */

.rd-hero.rd-bleed .rd-hero-desc {
    max-width: 560px;
}

.rd-hero-kicker {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 27px;
    padding: 0 12px;
    margin-bottom: 14px;
    border-radius: var(--rd-radius-pill);
    background: rgba(255, 255, 255, .12);
    border: 1px solid rgba(255, 255, 255, .18);
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: .3px;
}

.rd-hero h1 {
    margin: 0 0 14px;
    color: #fff;
    font-size: 42px;
    line-height: 1.18;
    /* 中文字重在深色渐变上会「发灰」，不是颜色不对，是笔画边缘被底色吃掉了。
       字距收紧到 -.8px 让字与字靠成一块整体，再加一层几乎看不见的白色外发光
       把边缘提亮 —— 读到的是「亮而不刺」，也就是常说的通透。 */
    letter-spacing: -.8px;
    text-shadow: 0 1px 0 rgba(255, 255, 255, .07);
}

.rd-hero h1 em {
    font-style: normal;
    background: linear-gradient(100deg, #7fe0ff, #b39bff 60%, #ffd28a);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.rd-hero-desc {
    max-width: 520px;
    margin: 0 0 24px;
    /* 说明文字比标题再透一档：深色底上白字纯度太高会和标题抢，读起来也发涩。
       .72 比原来的 .78 更轻，但仍在对比度安全线以上（深蓝底 ≈ 9:1）。 */
    color: rgba(255, 255, 255, .72);
    font-size: 15px;
    line-height: 1.7;
}

/* 沉浸式搜索框：不做「白底输入框压在深色头图上」，而是把整块做成半透明毛玻璃，
   与蓝色渐变融成一体 —— border 只是一圈很淡的白，仅起轮廓作用，输入区自身没有边框。
   视觉重点是「反色按钮」：白底 + 蓝字，这一屏唯一的高亮实体就是它。 */
.rd-hero-search {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 62px;
    padding: 0 8px 0 24px;
    max-width: 620px;
    border-radius: var(--rd-radius-pill);
    background: rgba(255, 255, 255, .13);
    border: 1px solid rgba(255, 255, 255, .26);
    -webkit-backdrop-filter: blur(14px) saturate(130%);
    backdrop-filter: blur(14px) saturate(130%);
    box-shadow: 0 20px 46px -26px rgba(0, 0, 0, .85), inset 0 1px 0 rgba(255, 255, 255, .16);
    transition: background .22s ease, border-color .22s ease, box-shadow .22s ease;
}

/* 聚焦时整块「亮起来」：底色加一档、描边变实、外圈补一层白光。
   没有这一步的话，玻璃底与头图太像，用户点进去后看不出光标在哪。 */
.rd-hero-search:focus-within {
    background: rgba(255, 255, 255, .2);
    border-color: rgba(255, 255, 255, .56);
    box-shadow: 0 22px 50px -26px rgba(0, 0, 0, .9), 0 0 0 4px rgba(255, 255, 255, .13), inset 0 1px 0 rgba(255, 255, 255, .22);
}

.rd-hero-search input {
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
    border: 0;
    background: transparent;
    outline: none;
    color: #fff;
    font-size: 15.5px;
}

.rd-hero-search input::placeholder {
    color: rgba(255, 255, 255, .6);
}

/* type=search 自带的清除按钮默认是深色实心叉，落在玻璃底上等于看不见 ——
   换成自绘的白色叉。去掉 -webkit-appearance 会把可点区域一起抹掉，所以必须自绘。 */
.rd-hero-search input::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    background: center / 16px 16px no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.6' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E");
    opacity: .58;
    cursor: pointer;
}

.rd-hero-search input::-webkit-search-cancel-button:hover {
    opacity: 1;
}

.rd-hero-search-btn {
    flex: 0 0 auto;
    height: 46px;
    padding: 0 26px;
    border: 0;
    border-radius: var(--rd-radius-pill);
    background: #fff;
    color: var(--rd-primary);
    font: inherit;
    font-size: 15px;
    font-weight: 800;
    letter-spacing: .5px;
    cursor: pointer;
    box-shadow: 0 12px 24px -14px rgba(0, 0, 0, .7);
    transition: background .18s ease, transform .18s ease, box-shadow .18s ease;
}

.rd-hero-search-btn:hover {
    background: #eef2ff;
    transform: translateY(-1px);
    box-shadow: 0 16px 28px -14px rgba(0, 0, 0, .78);
}

.rd-hero-search-btn:active {
    transform: translateY(0);
}

.rd-hero-search-btn:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

.rd-hero-hot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
    font-size: 13px;
    color: rgba(255, 255, 255, .62);
}

.rd-hero-hot a {
    /* 热点分类是可点元素，纯靠 padding 时行盒只有 31px，手指按不准；
       显式给一个最小高度，顺便让文案在上边缘不贴顶 */
    display: inline-flex;
    align-items: center;
    min-height: 34px;
    padding: 0 13px;
    border-radius: var(--rd-radius-pill);
    background: rgba(255, 255, 255, .1);
    border: 1px solid rgba(255, 255, 255, .16);
    color: rgba(255, 255, 255, .88);
    font-size: 12.5px;
}

.rd-hero-hot a:hover {
    background: rgba(255, 255, 255, .22);
    color: #fff;
}

/* Hero 右栏：真实内容（热销 TOP3），而不是 4 张通用能力卡。
   把「能力卡」下沉成 hero 下方的白色卖点条后，Hero 更轻、首屏信息密度也更高。 */
.rd-rank {
    padding: 16px 16px 10px;
    border-radius: var(--rd-radius);
    background: rgba(255, 255, 255, .1);
    border: 1px solid rgba(255, 255, 255, .16);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
}

.rd-rank-hd {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 6px;
    padding-bottom: 10px;
    border-bottom: 1px solid rgba(255, 255, 255, .14);
    font-size: 13.5px;
    font-weight: 800;
}

.rd-rank-hd span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.rd-rank-hd a {
    font-size: 12px;
    font-weight: 500;
    color: rgba(255, 255, 255, .68);
}

/* 来源说明（按浏览量 / 手动指定 / 刚刚更新…）：
   和侧栏的 .rd-widget-hd small 是同一个角色，只是底色是深色头图，
   所以字色用半透明白而不是 --rd-muted。 */
.rd-rank-hd small {
    font-size: 11.5px;
    font-weight: 500;
    color: rgba(255, 255, 255, .62);
}

.rd-rank-hd a:hover {
    color: #fff;
}

.rd-rank-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 4px;
    border-radius: 10px;
    color: #fff;
}

.rd-rank-item+.rd-rank-item {
    border-top: 1px solid rgba(255, 255, 255, .1);
}

.rd-rank-item:hover {
    color: #fff;
    background: rgba(255, 255, 255, .08);
}

.rd-rank-no {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 20px;
    width: 20px;
    height: 20px;
    border-radius: 6px;
    background: rgba(255, 255, 255, .16);
    font-size: 11.5px;
    font-weight: 800;
}

.rd-rank-item:nth-child(2) .rd-rank-no {
    background: linear-gradient(135deg, #ffd166, #f59e0b);
    color: #4a2c00;
}

.rd-rank-item:nth-child(3) .rd-rank-no {
    background: linear-gradient(135deg, #d7deea, #98a4bb);
    color: #2b3244;
}

.rd-rank-item:nth-child(4) .rd-rank-no {
    background: linear-gradient(135deg, #e8b891, #c07f4a);
    color: #3d2405;
}

.rd-rank-t {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 13.5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rd-rank-p {
    flex: 0 0 auto;
    font-size: 13.5px;
    color: #ffd88a;
}

.rd-rank-p.is-free {
    color: #86efc0;
}

.rd-rank-empty {
    padding: 14px 4px;
    font-size: 13px;
    color: rgba(255, 255, 255, .6);
}

.rd-rank-promo-txt {
    margin: 4px 0 12px;
    font-size: 13px;
    line-height: 1.7;
    color: rgba(255, 255, 255, .78);
}

/* ============================ 分类头图 ============================ */

/* 分类页的头图比首页 Hero 矮一档：左边分类名 + 描述，右边一个资源数徽块。
   原来是把「4 本类资源」塞进首页那套 4 列统计里 —— 一个数字占一整行，
   整个色块又高又空，用户要滚一屏才看到第一个资源。 */
.rd-hero.is-sort {
    padding: 30px 34px;
}

.rd-hero.is-sort .rd-hero-in {
    grid-template-columns: 1fr auto;
    gap: 26px;
}

.rd-hero.is-sort h1 {
    font-size: 30px;
    /* 首页那条收紧字距与白色外发光是给 42px 大标题调的，
       分类页这行 30px 字沿用会显得挤、还带一层多余的亮边。 */
    letter-spacing: -.4px;
    text-shadow: none;
}

.rd-sort-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 118px;
    padding: 14px 20px;
    border-radius: var(--rd-radius);
    background: rgba(255, 255, 255, .1);
    border: 1px solid rgba(255, 255, 255, .16);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    text-align: center;
}

.rd-sort-stat b {
    font-size: 30px;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -.5px;
}

.rd-sort-stat span {
    margin-top: 2px;
    font-size: 12.5px;
    color: rgba(255, 255, 255, .66);
}

/* ============================ 卖点条 ============================ */

/* 卖点卡片：一列一张小卡，列数由后台设定（--rd-cols）。
   分隔线不是画在卡片上的 —— 容器底色从 1px 的缝里透出来就是网格线，
   所以站长设 3 列、6 列，还是窄屏折成两行，线都自动正确。
   早先的写法是 `.rd-trust-item + .rd-trust-item { border-left }`，
   在「固定 4 条单行」时没问题；一旦列数可配、折行出现，
   每行第一张也会带上一条左边线，看上去像整排没对齐。 */
.rd-trust {
    display: grid;
    grid-template-columns: repeat(var(--rd-cols, 4), minmax(0, 1fr));
    gap: 1px;
    margin: -8px 0 24px;
    background: var(--rd-border);
    border: 1px solid var(--rd-border);
    border-radius: var(--rd-radius-lg);
    /* 内层白块要按圆角裁掉，否则四角会露出直角的容器底色 */
    overflow: hidden;
    box-shadow: var(--rd-shadow-sm);
}

/* 首页：卖点条骑在通栏头图的下沿（HTML 里由 .rd-trust-wrap 包一层）。
   深色头图与浅色页面相接会有一条生硬的横线，让白卡往上压住头图底部 34px，
   交界就被这张卡片盖住了 —— 从「两块板拼起来」变成一条连续的纵向轴。
   z-index 必须高过头图的伪元素光斑（它没有 z-index，但伪元素在卡片之前绘制），
   否则那片紫光会糊在白卡上。 */
.rd-trust-wrap {
    position: relative;
    z-index: 3;
    /* 头图的 margin-bottom 已在 .rd-hero.rd-bleed 里归零，这里的负值就是实际骑入量 */
    margin: -34px 0 26px;
}

.rd-trust-wrap .rd-trust {
    margin: 0;
}

/* 窄屏降列：取「min(设定列数, 2)」，不是写死 2 ——
   站长只放 1 张卡时，写死 2 会把它挤成半宽、左边空出一半。 */
@media (max-width: 900px) {
    .rd-trust {
        grid-template-columns: repeat(var(--rd-cols-md, 2), minmax(0, 1fr));
    }
}

.rd-trust-item {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 14px 18px;
    background: var(--rd-surface);
    color: var(--rd-text);
    min-width: 0;
}

.rd-trust-item:hover {
    color: var(--rd-primary);
}

/* 标题现在自己声明了 color，父级的 :hover 颜色传不下去，得单独写一条 ——
   否则悬停时只有图标变色、文字纹丝不动，看着像只做了一半。 */
.rd-trust-item:hover b {
    color: var(--rd-primary);
}

/* 补位空卡：只负责把最后一行填平，本身没有内容也不可交互。
   min-height 兜住「整行都是空卡」的极端情况，否则那一行会塌成 0 高。 */
.rd-trust-item.is-blank {
    min-height: 66px;
    background: var(--rd-surface);
    pointer-events: none;
}

/* 图标统一成一个色系。
   改造前四条各配一种饱和渐变（紫 / 黄 / 蓝 / 绿）+ 各自的彩色投影，
   四个 38px 的彩色方块并排，谁也压不住谁，整条看起来像四个不同来源的组件
   被硬拼在一起 —— 这正是「不协调」的来源。
   现在默认是「主色浅底 + 主色图标」，安静且四条一致；
   悬停时才换成满色渐变，把「可以点」这件事交回给交互态表达。 */
.rd-trust-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 38px;
    width: 38px;
    height: 38px;
    border-radius: 12px;
    background: var(--rd-primary-soft);
    color: var(--rd-primary);
    transition: background .18s ease, color .18s ease, box-shadow .18s ease;
}

.rd-trust-item:hover .rd-trust-ico {
    background: var(--rd-grad);
    color: #fff;
    box-shadow: 0 10px 20px -12px rgba(51, 85, 255, .95);
}

.rd-trust-ico .rd-svg {
    width: 19px;
    height: 19px;
    flex: 0 0 19px;
}

.rd-trust-txt {
    min-width: 0;
}

/* ⚠️ 这里踩过一个「选择器写太宽」的坑，改文案前先看这段：
   原来备注的样式写的是 `.rd-trust-item span { color: var(--rd-muted) }` ——
   一个**后代**选择器，而渲染出来的结构是
       <a class="rd-trust-item"><i class="rd-trust-ico"></i>
          <span class="rd-trust-txt"><b>会员权益</b><span>会员资源免费下</span></span></a>
   也就是说 `.rd-trust-txt` 这个**包装用的 span 也被命中了**，而 `<b>` 自己没声明颜色，
   于是继承了包装 span 的浅灰 —— 标题和备注双双变成 #8b93a7（白底对比度仅 2.8:1），
   `font-weight: 700` 白加了。用户反馈的「文字颜色太浅」就是这一处。
   修法：标题显式声明颜色，备注改用直接子选择器 `.rd-trust-txt > span`，
   两层各自说清楚，不再靠继承。 */
.rd-trust-item b {
    display: block;
    font-size: 15px;
    /* 800 的中文点阵在 15px 会糊成一块黑，和旁边 12.5px 的副标题拉不开层级。
       700 既清楚又留得住笔画之间的空隙。 */
    font-weight: 700;
    line-height: 1.4;
    color: var(--rd-text);
}

.rd-trust-txt>span {
    display: block;
    font-size: 12.5px;
    /* --rd-text-2（#4d5569，白底约 7.4:1）而不是 --rd-muted（#8b93a7，约 2.8:1）。
       12.5px 的小字本来就难认，再用「弱化色」就只剩下一片灰。
       弱化层级靠字号和字重表达，不靠把颜色调到看不清。 */
    color: var(--rd-text-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ============================ 首页大图广告位 ============================
   对照「一方主题」演示站（jybk.cc）：那一站的首页是**两排卡片** ——
   第一排是 4 张矮的小图标卡（就是上面的 .rd-trust），
   第二排是 4 张约 303×180、比例 5:3 的大图卡。我们原来只做了第一排，
   第二排压根没有，所以用户会说「没有做那四个大卡片的广告位」。

   两种形态共用一张卡：
     · 配了图片 → 图片铺满整张卡，底部压一层深色渐变，标题/副标题压在上面；
     · 没配图片 → 用内置渐变占位（这样后台一填文字就能看到效果，
                  不必先去准备四张图，也不会留下一排灰格子）。
   文字一律白色：占位渐变是深色，图片又压了深色渐变，两处都读得清。
   后台条目格式：图片地址 | 跳转链接 | 标题 | 副标题（后三项都可留空）。 */
.rd-adv {
    display: grid;
    grid-template-columns: repeat(var(--rd-cols, 4), minmax(0, 1fr));
    gap: 18px;
}

.rd-adv-item {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: 2px;
    aspect-ratio: 5 / 3;
    min-height: 132px;
    padding: 18px;
    border-radius: var(--rd-radius-lg);
    border: 1px solid var(--rd-border);
    /* 没配图时这层背景就是渐变的兜底底；配了图由 <img> 盖住 */
    background: var(--rd-surface-2);
    overflow: hidden;
    /* isolate 必须写：下面的 img / 遮罩用 z-index:-1 压在文字之下、
       但又要盖住卡片自己的背景色。没有这层独立层叠上下文，
       z-index:-1 会穿到整张卡（甚至页面）背后，图片直接消失。 */
    isolation: isolate;
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}

.rd-adv-item:hover {
    transform: translateY(-3px);
    border-color: rgba(51, 85, 255, .35);
    box-shadow: var(--rd-shadow-lg);
}

.rd-adv-item img {
    position: absolute;
    inset: 0;
    z-index: -1;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .4s ease;
}

.rd-adv-item:hover img {
    transform: scale(1.04);
}

/* 图片版：底部一层深色渐变，保证白字在任何配图上都够对比度 */
.rd-adv-item.has-img::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 64%;
    z-index: -1;
    background: linear-gradient(to top, rgba(6, 10, 22, .82), rgba(6, 10, 22, 0));
}

/* 占位版：四个内置渐变轮着用（跟着条目序号），再叠一道柔光避免死板 */
.rd-adv-item.is-ph {
    background-image: radial-gradient(circle at 82% 12%, rgba(255, 255, 255, .34), rgba(255, 255, 255, 0) 58%);
}

.rd-adv-item.is-ph-1 {
    background-color: #3355ff;
    background-image: linear-gradient(135deg, #3355ff, #7b3df0);
}

.rd-adv-item.is-ph-2 {
    background-color: #0d9488;
    background-image: linear-gradient(135deg, #0ea5e9, #14b8a6);
}

.rd-adv-item.is-ph-3 {
    background-color: #ea580c;
    background-image: linear-gradient(135deg, #f59e0b, #ef4444);
}

.rd-adv-item.is-ph-4 {
    background-color: #7c3aed;
    background-image: linear-gradient(135deg, #8b5cf6, #ec4899);
}

.rd-adv-cap {
    min-width: 0;
    position: relative;
}

.rd-adv-cap b {
    display: block;
    font-size: 16px;
    font-weight: 700;
    line-height: 1.4;
    color: #fff;
    text-shadow: 0 1px 10px rgba(6, 10, 22, .35);
}

.rd-adv-cap span {
    display: block;
    margin-top: 3px;
    font-size: 12.5px;
    line-height: 1.5;
    color: rgba(255, 255, 255, .84);
    text-shadow: 0 1px 10px rgba(6, 10, 22, .35);
}

@media (max-width: 900px) {
    .rd-adv {
        grid-template-columns: repeat(var(--rd-cols-md, 2), minmax(0, 1fr));
        gap: 12px;
    }

    /* 两列时按 5:3 会把高度压得很扁，正文只剩两行字的位置；
       窄屏改成更方的 4:3，卡片有地方写字。 */
    .rd-adv-item {
        aspect-ratio: 4 / 3;
        padding: 14px;
    }

    .rd-adv-cap b {
        font-size: 14px;
    }

    .rd-adv-cap span {
        font-size: 12px;
    }
}

/* ============================ notice bar ============================ */

.rd-notice {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 16px;
    margin-bottom: 22px;
    border-radius: var(--rd-radius);
    background: var(--rd-surface);
    border: 1px solid var(--rd-border);
}

.rd-notice-tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex: 0 0 auto;
    height: 24px;
    padding: 0 10px;
    border-radius: var(--rd-radius-pill);
    background: var(--rd-grad);
    color: #fff;
    font-size: 12px;
    font-weight: 700;
}

.rd-notice-txt {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 13.5px;
    color: var(--rd-text-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rd-notice time {
    flex: 0 0 auto;
    font-size: 12.5px;
    color: var(--rd-muted);
}

/* ============================ category pills / tabs ============================ */

/* .rd-pills（用户中心消费记录的分类筛选）与 .rd-tabs（首页「最新/热门」的分类切换）
   观感完全一致，共用同一套规则，避免两边各自微调后慢慢跑偏。 */

.rd-pills,
.rd-tabs {
    display: flex;
    gap: 9px;
    overflow-x: auto;
    padding: 3px 1px 9px;
    scrollbar-width: none;
}

.rd-pills::-webkit-scrollbar,
.rd-tabs::-webkit-scrollbar {
    display: none;
}

.rd-pill,
.rd-tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    height: 36px;
    padding: 0 16px;
    border-radius: var(--rd-radius-pill);
    background: var(--rd-surface);
    border: 1px solid var(--rd-border);
    font-family: inherit;
    font-size: 13.5px;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    color: var(--rd-text-2);
}

/* .rd-tab 是 <button>，浏览器默认样式得自己抹平 */
.rd-tab {
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}

.rd-pill:hover,
.rd-tab:hover {
    border-color: var(--rd-primary);
    color: var(--rd-primary);
}

.rd-pill.is-active,
.rd-tab.is-active {
    background: var(--rd-grad);
    border-color: transparent;
    color: #fff;
}

.rd-pill i,
.rd-tab i {
    font-style: normal;
    font-size: 12px;
    opacity: .7;
}

/* ============================ 首页分类 Tab 工具条 ============================ */

/* 首页「最新 / 热门」共用一条 Tab 栏，横向滚动，独占整行。
   「显示方式」切换器不在这里 —— 它是右下角浮动工具栏里一个收起态的按钮，
   由 footer.php 输出。放这里会一直占着一整条的位置，太铺张。
   注意：类名不能用 .rd-toolbar —— 那是页脚右下角浮动工具区（返回顶部/换肤），
   已经带 position:fixed，撞名会让整条工具条变成固定悬浮。 */
.rd-tabs-wrap {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 18px;
}

.rd-tabs-wrap .rd-tabs {
    flex: 1 1 auto;
    min-width: 0;
    padding-bottom: 0;
}

/* 「加载更多」按钮或原生分页条；空了就完全不留高度 */
.rd-more-wrap {
    text-align: center;
}

.rd-more-wrap > *:not([hidden]) {
    margin-top: 22px;
}

.rd-loadmore {
    gap: 7px;
}

/* ============================ breadcrumb ============================ */

.rd-crumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 7px;
    margin-bottom: 14px;
    font-size: 13px;
    color: var(--rd-muted);
}

.rd-crumb a:hover {
    color: var(--rd-primary);
}

.rd-crumb i {
    font-style: normal;
    opacity: .55;
}

/* ============================ post detail ============================ */

.rd-post-hd {
    padding: 24px 26px 20px;
    border-bottom: 1px solid var(--rd-border);
}

.rd-post-title {
    margin: 0 0 14px;
    font-size: 27px;
    line-height: 1.4;
    letter-spacing: -.4px;
}

.rd-post-cats {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    margin-bottom: 12px;
}

.rd-post-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 18px;
    font-size: 13px;
    color: var(--rd-muted);
}

.rd-post-meta span {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.rd-post-body {
    padding: 24px 26px 8px;
    font-size: 15.5px;
    line-height: 1.85;
    color: var(--rd-text-2);
    word-wrap: break-word;
}

.rd-post-body img {
    border-radius: var(--rd-radius-sm);
    margin: 8px 0;
}

.rd-post-body h2 {
    margin: 28px 0 12px;
    padding-left: 12px;
    border-left: 4px solid var(--rd-primary);
    font-size: 20px;
}

.rd-post-body h3 {
    margin: 22px 0 10px;
    font-size: 17px;
}

.rd-post-body ul,
.rd-post-body ol {
    margin: 0 0 16px;
    padding-left: 22px;
    list-style: disc;
}

.rd-post-body ol {
    list-style: decimal;
}

.rd-post-body li {
    margin-bottom: 6px;
}

.rd-post-body blockquote {
    margin: 16px 0;
    padding: 12px 18px;
    border-left: 4px solid var(--rd-primary);
    border-radius: 0 var(--rd-radius-sm) var(--rd-radius-sm) 0;
    background: var(--rd-primary-soft);
    color: var(--rd-text-2);
}

.rd-post-body table {
    width: 100%;
    border-collapse: collapse;
    margin: 16px 0;
    font-size: 14px;
}

.rd-post-body th,
.rd-post-body td {
    border: 1px solid var(--rd-border-2);
    padding: 9px 12px;
    text-align: left;
}

.rd-post-body th {
    background: var(--rd-surface-2);
    font-weight: 700;
}

.rd-post-body a {
    color: var(--rd-primary);
    border-bottom: 1px solid rgba(51, 85, 255, .35);
}

/* download buttons that already exist inside content */

.rd-post-body .em-download-btn,
.rd-post-body a[href*="resource_alias"] {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 10px 20px !important;
    margin: 5px 6px 5px 0;
    border-radius: var(--rd-radius-pill) !important;
    background: var(--rd-grad) !important;
    color: #fff !important;
    border: 0 !important;
    font-weight: 700;
    box-shadow: 0 10px 20px -12px rgba(51, 85, 255, .95);
}

.rd-post-tags {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 4px 26px 18px;
}

.rd-post-tags a {
    padding: 4px 12px;
    border-radius: var(--rd-radius-pill);
    background: var(--rd-surface-2);
    border: 1px solid var(--rd-border);
    font-size: 12.5px;
    color: var(--rd-text-2);
}

.rd-post-tags a:hover {
    border-color: var(--rd-primary);
    color: var(--rd-primary);
}

/* purchase panel inside content */

.rd-buybox {
    margin: 6px 26px 22px;
    padding: 18px 20px;
    border-radius: var(--rd-radius);
    border: 1px solid rgba(51, 85, 255, .22);
    background: linear-gradient(180deg, var(--rd-primary-soft), var(--rd-surface));
}

html[data-theme="dark"] .rd-buybox {
    background: linear-gradient(180deg, #1a2140, var(--rd-surface));
}

.rd-buybox-top {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding-bottom: 14px;
    border-bottom: 1px dashed var(--rd-border-2);
}

.rd-buybox-price {
    display: flex;
    align-items: baseline;
    gap: 10px;
}

.rd-buybox-price .rd-now {
    font-size: 30px;
    font-weight: 800;
    color: var(--rd-red);
    letter-spacing: -.6px;
}

html[data-theme="dark"] .rd-buybox-price .rd-now {
    color: #ff8181;
}

.rd-buybox-price .rd-old {
    font-size: 14px;
    color: var(--rd-muted);
    text-decoration: line-through;
}

.rd-buybox-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

/* ✓ 说明条：流式排布，不用网格。
   原来是 repeat(auto-fit, minmax(190px, 1fr))，一进网格就会有「格子数」这个概念：
   1440 视口下主列宽约 784px，四列要 4×190+3×10=790px —— 差 6px 装不下，
   于是掉成 3 列，第 4 条孤零零落在第二行左侧、右边空一整格。
   条数还会变（有在线演示时是 4 条、没有时是 3 条），网格永远在某个宽度上落单。
   换成 flex 流式之后就没有格子了：装得下就一行排开，装不下就整条换到下一行，
   左对齐续排，不会出现空洞。 */
.rd-buybox-tips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 9px 20px;
    padding-top: 14px;
}

.rd-buybox-tips div {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--rd-text-2);
    /* 一条说明要么整条留在这一行、要么整条换行。
       不允许把「短时签名链接，防盗链保护」断成「短时签名链接，防盗链」+「保护」——
       那样第二行看起来像一条独立说明，读起来是坏的。 */
    white-space: nowrap;
}

.rd-buybox-tips i {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: rgba(16, 185, 129, .14);
    color: var(--rd-green);
    font-style: normal;
    font-size: 12px;
    font-weight: 800;
}

/* download box */

.rd-dlbox {
    margin: 0 26px 22px;
    border-radius: var(--rd-radius);
    border: 1px solid var(--rd-border);
    overflow: hidden;
    background: var(--rd-surface-2);
}

.rd-dlbox-hd {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 13px 18px;
    background: var(--rd-surface);
    border-bottom: 1px solid var(--rd-border);
    font-size: 15px;
    font-weight: 700;
}

.rd-dlbox-bd {
    padding: 16px 18px;
}

.rd-dl-lines {
    display: grid;
    gap: 9px;
}

.rd-dl-line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 12px 15px;
    border-radius: var(--rd-radius-sm);
    background: var(--rd-surface);
    border: 1px solid var(--rd-border);
}

.rd-dl-line b {
    font-size: 14px;
    font-weight: 700;
}

.rd-dl-line small {
    display: block;
    font-size: 12px;
    color: var(--rd-muted);
    font-weight: 400;
}

.rd-dl-lock {
    padding: 18px;
    text-align: center;
    border-radius: var(--rd-radius-sm);
    background: var(--rd-surface);
    border: 1px dashed var(--rd-border-2);
}

.rd-dl-lock b {
    display: block;
    margin-bottom: 6px;
    font-size: 15px;
}

.rd-dl-lock p {
    margin: 0 0 14px;
    font-size: 13.5px;
    color: var(--rd-muted);
}

/* vote bar */

.rd-vote {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 22px 26px 8px;
}

.rd-vote-btn {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-width: 84px;
    padding: 11px 14px;
    border-radius: var(--rd-radius);
    border: 1px solid var(--rd-border);
    background: var(--rd-surface);
    cursor: pointer;
    transition: all .18s ease;
}

.rd-vote-btn svg {
    width: 20px;
    height: 20px;
}

.rd-vote-btn span {
    font-size: 12.5px;
    font-weight: 700;
    color: var(--rd-muted);
}

.rd-vote-btn:hover {
    transform: translateY(-2px);
    border-color: var(--rd-primary);
    color: var(--rd-primary);
}

.rd-vote-btn.is-on {
    border-color: var(--rd-primary);
    background: var(--rd-primary-soft);
    color: var(--rd-primary);
}

.rd-vote-btn.is-on span {
    color: var(--rd-primary);
}

.rd-vote-btn[data-vote="dislike"].is-on {
    border-color: #94a3b8;
    background: rgba(148, 163, 184, .14);
    color: #64748b;
}

.rd-vote-btn[data-vote="collect"].is-on {
    border-color: var(--rd-gold);
    background: var(--rd-gold-soft);
    color: #b45309;
}

.rd-vote-btn[data-vote="collect"].is-on span {
    color: #b45309;
}

/* comment */

.rd-comments {
    padding: 6px 26px 24px;
}

.rd-comment-form {
    margin-bottom: 22px;
    padding: 16px;
    border-radius: var(--rd-radius);
    background: var(--rd-surface-2);
    border: 1px solid var(--rd-border);
}

.rd-comment-form textarea {
    min-height: 92px;
}

.rd-comment-form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 10px;
}

.rd-comment-form-row input {
    flex: 1 1 150px;
}

.rd-comment-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.rd-comment {
    display: flex;
    gap: 12px;
}

.rd-comment-avatar {
    flex: 0 0 40px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    object-fit: cover;
    background: var(--rd-surface-2);
}

.rd-comment-main {
    flex: 1 1 auto;
    min-width: 0;
    padding: 12px 15px;
    border-radius: var(--rd-radius);
    background: var(--rd-surface-2);
    border: 1px solid var(--rd-border);
}

.rd-comment-hd {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 9px;
    margin-bottom: 6px;
    font-size: 13px;
    color: var(--rd-muted);
}

.rd-comment-hd b {
    color: var(--rd-text);
    font-size: 14px;
}

.rd-comment-txt {
    font-size: 14.5px;
    line-height: 1.75;
    color: var(--rd-text-2);
}

.rd-comment-txt img {
    max-width: 180px;
    border-radius: 6px;
}

.rd-comment-children {
    margin-top: 14px;
    padding-left: 14px;
    border-left: 2px solid var(--rd-border);
}

.rd-comment-children .rd-comment {
    margin-bottom: 14px;
}

/* neighbor + related */

.rd-neighbor {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    padding: 18px 26px;
}

.rd-neighbor a {
    display: block;
    padding: 13px 16px;
    border-radius: var(--rd-radius);
    background: var(--rd-surface-2);
    border: 1px solid var(--rd-border);
    font-size: 14px;
    font-weight: 600;
}

.rd-neighbor a small {
    display: block;
    margin-bottom: 4px;
    font-size: 12px;
    font-weight: 600;
    color: var(--rd-muted);
}

.rd-neighbor a:hover {
    border-color: var(--rd-primary);
    color: var(--rd-primary);
}

/* ============================ widgets / sidebar ============================ */

.rd-widget {
    margin-bottom: 18px;
    background: var(--rd-surface);
    border: 1px solid var(--rd-border);
    border-radius: var(--rd-radius);
    overflow: hidden;
}

.rd-widget-hd {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    padding: 13px 16px;
    border-bottom: 1px solid var(--rd-border);
    font-size: 15px;
    /* 800 的中文标题在 320px 侧栏里会糊成一条黑杠；700 与正文分区标题统一，
       也让分组标题不再抢正文的注意力。 */
    font-weight: 700;
}

/* 侧栏标题统一加一道品牌渐变竖条，和内容区分区标题形成同一套视觉语言。
   注意：标题是纯文本节点，加 ::before 会让 flex 项从 2 个变 3 个，
   此时 justify-content:space-between 会把标题挤到中间，所以改用 flex-start + small 自动右推。 */
.rd-widget-hd::before {
    content: "";
    flex: 0 0 auto;
    width: 4px;
    height: 15px;
    border-radius: 3px;
    background: var(--rd-grad);
}

.rd-widget-hd small {
    margin-left: auto;
    font-size: 12px;
    font-weight: 500;
    color: var(--rd-muted);
}

.rd-widget-bd {
    padding: 14px 16px;
}

.rd-widget-bd.is-flush {
    padding: 6px 16px 12px;
}

.rd-author {
    text-align: center;
}

.rd-author-avatar {
    width: 66px;
    height: 66px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid transparent;
    box-shadow: var(--rd-shadow);
    /* 渐变描边：border-box 层只在透明边框区域露出，padding-box 层负责压住内部 */
    background: linear-gradient(var(--rd-surface), var(--rd-surface)) padding-box,
        var(--rd-grad) border-box;
}

/* 侧栏排行行：只有编号 + 标题。
 *
 * 这里原来是一张「富列表行」—— 56×38 缩略图 + 两行标题 + 浏览量 + 价签。
 * 站长的判断是侧栏这块地方不值得塞这么多：一屏六个模块、每行六十多像素，
 * 而浏览量/价格在正文购买区里本来就有。于是缩略图、浏览量、价签一起下线。
 * 下面三个类随之删除（HTML 也删了，不是留着不用）：
 *   .rd-rank-row .rd-list-thumb / .rd-rank-row-ph  → 封面图与无封面时的首字方块
 *   .rd-rank-row-main / .rd-rank-row-meta          → 标题/浏览量的包裹层
 *   .rd-rank-row-price（+ 暗色 / .is-free）        → 「免费 / ¥299」价签
 * 探针 probe-side.js 里钉了「排行行里不许出现这三样」，
 * 以后想加回来先想清楚是不是要推翻上面这个决定。 */
.rd-rank-row {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 0;
    border-bottom: 1px dashed var(--rd-border);
}

.rd-rank-row:last-child {
    border-bottom: 0;
}

.rd-rank-row .rd-list-idx {
    flex: 0 0 20px;
    width: 20px;
    height: 20px;
    border-radius: 6px;
    font-size: 11.5px;
}

/* 标题直接是 .rd-rank-row 的第二个 flex 子项（原来的 .rd-rank-row-main
   包裹层已经删掉），flex / min-width 必须写在这一层上：
   少了 min-width:0，长标题既不收缩也不换行，会把整行撑出侧栏。
   font-weight: 400 是「标题不加粗」这条要求的落点，别改回 600 试手感。 */
.rd-rank-row-title {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 13.5px;
    line-height: 1.45;
    font-weight: 400;
}

/* 浏览量（.rd-rank-row-meta）与价签（.rd-rank-row-price，连同暗色覆盖与
   .is-free）两个类已删除：侧栏排行行只剩「编号 + 标题」。
   价签下线还有一层理由 —— 「免费 / ¥299」在正文购买区里已经写着，
   侧栏再标一遍是同一屏里说两遍；而且给教程类普通文章标「免费」
   会让人以为能免费下载，它根本没有下载入口。 */

/* 侧栏分类行：数量改成胶囊角标，和热门榜的行节奏区分开 */
.rd-cat-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 9px 0;
    border-bottom: 1px dashed var(--rd-border);
    font-size: 13.5px;
    font-weight: 400;
}

.rd-cat-row:last-child {
    border-bottom: 0;
}

.rd-cat-row-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rd-cat-count {
    flex: 0 0 auto;
    min-width: 22px;
    height: 20px;
    padding: 0 7px;
    border-radius: var(--rd-radius-pill);
    background: var(--rd-surface-2);
    font-size: 11.5px;
    font-weight: 600;
    line-height: 20px;
    text-align: center;
    color: var(--rd-muted);
}

.rd-cat-row:hover .rd-cat-count {
    background: var(--rd-primary-soft);
    color: var(--rd-primary);
}

.rd-author-name {
    margin: 10px 0 4px;
    font-size: 15.5px;
    font-weight: 800;
}

.rd-author-desc {
    font-size: 13px;
    color: var(--rd-muted);
    line-height: 1.7;
}

.rd-author-stat {
    display: flex;
    margin-top: 13px;
    border-top: 1px solid var(--rd-border);
    padding-top: 12px;
}

.rd-author-stat div {
    flex: 1 1 0;
    text-align: center;
}

.rd-author-stat b {
    display: block;
    font-size: 16px;
    font-weight: 800;
    color: var(--rd-primary);
}

.rd-author-stat span {
    font-size: 12px;
    color: var(--rd-muted);
}

/* spec table */

.rd-spec {
    width: 100%;
    font-size: 13.5px;
}

.rd-spec tr+tr td {
    border-top: 1px solid var(--rd-border);
}

.rd-spec td {
    padding: 9px 0;
}

.rd-spec td:first-child {
    width: 82px;
    color: var(--rd-muted);
}

.rd-spec td:last-child {
    text-align: right;
    font-weight: 400;
    color: var(--rd-text);
    word-break: break-all;
}

/* price card in sidebar */

.rd-pricecard {
    padding: 18px 16px;
    border-radius: var(--rd-radius);
    border: 1px solid rgba(51, 85, 255, .25);
    background: linear-gradient(180deg, var(--rd-primary-soft), var(--rd-surface));
    margin-bottom: 18px;
}

/* 详情页侧栏里的购买卡：**不再吸顶**。
   原来这里有一条 @media (min-width: 901px) 的 position: sticky，
   想让「立即购买」始终停在视野里。实际观感是反的：往下滚时，
   侧栏里的其它卡（相关资源等）都跟着正文滚走了，只剩这一张卡孤零零悬在半空，
   像是页面没滚干净 —— 反馈很直接（「侧边只有资源卡片是悬浮的，很奇怪」）。
   侧栏整体一起滚，和左右两栏的滚动节奏一致，比单独吊着一张卡自然得多；
   购买入口在上方主区里也有一份，不靠这一张卡兜底。
   ⚠️ 别只把 sticky 删掉就完事：`.rd-pricecard.is-side` 这个类还留着，
   是给以后想恢复吸顶时用的锚点；真恢复的话，记得同时跑 probe-side.js 的吸顶断言。 */

.rd-pricecard-hd {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
    font-size: 13px;
    font-weight: 500;
    color: var(--rd-muted);
}

/* 价格行：数字与划线原价按基线对齐。用 align-items:baseline 而不是 center ——
   32px 的大字与 13.5px 的小字按中心线对齐时，小字看起来会「浮在半空」。 */
.rd-pricecard-now {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
}

.rd-pricecard .rd-now.is-free {
    color: var(--rd-green);
}

/* 卡片底部的一句补充说明。改造前这里叫 .rd-pricecard-note，文案是
   「购买后可在用户中心 → 已购资源随时下载」—— 和主区「获取资源」的 ✓ 列表
   说的是同一件事。现在只留「去哪找回已购」，并做成可点的链接。
   （旧的 .rd-pricecard-note 规则已随之删除，它没有其他引用点。） */
.rd-pricecard-fine {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px dashed var(--rd-border);
    font-size: 12.5px;
    line-height: 1.7;
    color: var(--rd-muted);
}

.rd-pricecard-fine a {
    font-weight: 500;
}

.rd-pricecard .rd-now {
    font-size: 32px;
    font-weight: 800;
    color: var(--rd-red);
    letter-spacing: -.8px;
}

.rd-pricecard .rd-old {
    margin-left: 8px;
    font-size: 13.5px;
    color: var(--rd-muted);
    text-decoration: line-through;
}

.rd-pricecard-vip {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin: 12px 0;
    padding: 9px 12px;
    border-radius: var(--rd-radius-sm);
    background: var(--rd-gold-soft);
    font-size: 13px;
    color: #b45309;
    font-weight: 600;
}

.rd-pricecard-actions {
    display: grid;
    gap: 9px;
    margin-top: 14px;
}

/* tag cloud */

.rd-cloud {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.rd-cloud a {
    padding: 5px 11px;
    border-radius: var(--rd-radius-pill);
    background: var(--rd-surface-2);
    border: 1px solid var(--rd-border);
    font-size: 12.5px;
    color: var(--rd-text-2);
}

.rd-cloud a:hover {
    border-color: var(--rd-primary);
    color: var(--rd-primary);
}

/* 友情链接那一份胶囊样式（.rd-cloud.is-plain）已随侧栏友链模块一起删除 ——
   友链现在只在页脚上方那一整条里出现。 */

/* ============================ 侧栏新增模块 ============================
   这一批是「把侧栏做厚」补的模块（图片广告位 / 站内搜索 / 本分类最新 /
   购买与售后），视觉语言与已有模块一致。
   .rd-side-center 与 .rd-side-center .rd-author-avatar 已删除：
   它们只服务于侧栏二维码与「关于本站」作者卡，两者都不在了。 */

/* 侧栏搜索：输入框与按钮焊成一条胶囊，与头图的沉浸式搜索框同一套语言，
   只是尺寸收小 —— 侧栏宽度放不下大搜索框。 */
.rd-side-search {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 4px 4px 14px;
    border-radius: var(--rd-radius-pill);
    background: var(--rd-surface-2);
    border: 1px solid var(--rd-border);
}

.rd-side-search input {
    flex: 1 1 auto;
    min-width: 0;
    height: 32px;
    border: 0;
    background: transparent;
    outline: none;
    font-family: inherit;
    font-size: 13.5px;
    color: var(--rd-text);
}

.rd-side-search input::placeholder {
    color: var(--rd-muted);
}

.rd-side-search button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 30px;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 50%;
    background: var(--rd-grad);
    color: #fff;
    cursor: pointer;
}

.rd-side-search button .rd-svg {
    width: 15px;
    height: 15px;
}

.rd-side-search:focus-within {
    border-color: var(--rd-primary);
    box-shadow: 0 0 0 3px rgba(51, 85, 255, .14);
}

/* 站点统计：2×2 数字格 */
.rd-stat-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1px;
    background: var(--rd-border);
    border: 1px solid var(--rd-border);
    border-radius: var(--rd-radius-sm);
    overflow: hidden;
}

.rd-stat-cell {
    padding: 10px 8px;
    text-align: center;
    background: var(--rd-surface);
}

.rd-stat-cell b {
    display: block;
    font-size: 17px;
    font-weight: 700;
    line-height: 1.3;
    color: var(--rd-primary);
}

.rd-stat-cell span {
    display: block;
    margin-top: 2px;
    font-size: 11.5px;
    color: var(--rd-text-2);
}

/* 侧栏公告：一条一条的卡片，标题两行截断 + 日期 */
.rd-notice-item {
    display: block;
    padding: 9px 0;
    border-bottom: 1px dashed var(--rd-border);
}

.rd-notice-item:last-child {
    border-bottom: 0;
    padding-bottom: 2px;
}

.rd-notice-item-txt {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--rd-text-2);
}

.rd-notice-item:hover .rd-notice-item-txt {
    color: var(--rd-primary);
}

.rd-notice-item time {
    display: block;
    margin-top: 3px;
    font-size: 11.5px;
    color: var(--rd-muted);
}

.rd-side-actions {
    display: grid;
    gap: 9px;
    margin-top: 14px;
}

/* ============================ user center ============================ */

.rd-uc {
    display: flex;
    gap: 22px;
    align-items: flex-start;
}

.rd-uc-side {
    flex: 0 0 248px;
    width: 248px;
}

/* 用户中心头像卡：改成「头像在左、姓名/邮箱/会员状态在右」的横向三行。
   原先是居中的三行 + 一个 74px 头像，占掉约 200px —— 用户进用户中心是为了看
   「我买了什么」，结果第一个屏幕被一张自己的名片占了大半。
   左对齐后同样的信息只占约 118px，而且视觉上更像「账户信息条」而不是名片。
   手机上早就改成了这个结构（见 ≤900 的媒体查询），桌面端现在是同一套语言。 */
.rd-uc-profile {
    display: grid;
    grid-template-columns: 58px minmax(0, 1fr);
    grid-template-areas:
        "av name"
        "av mail"
        "av vip";
    align-items: center;
    column-gap: 13px;
    row-gap: 2px;
    padding: 18px 16px;
    text-align: left;
    border-radius: var(--rd-radius);
    background: radial-gradient(120% 120% at 20% 0%, #2448d8, #1a2a94 60%, #131a63);
    color: #fff;
    margin-bottom: 16px;
}

.rd-uc-profile img {
    grid-area: av;
    width: 58px;
    height: 58px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid rgba(255, 255, 255, .35);
}

.rd-uc-profile h3 {
    grid-area: name;
    margin: 0;
    color: #fff;
    font-size: 15.5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rd-uc-profile p {
    grid-area: mail;
    margin: 0;
    font-size: 12.5px;
    color: rgba(255, 255, 255, .72);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rd-uc-vip {
    grid-area: vip;
    justify-self: start;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    max-width: 100%;
    margin-top: 5px;
    padding: 3px 10px;
    border-radius: var(--rd-radius-pill);
    background: rgba(255, 255, 255, .18);
    font-size: 12px;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---------------- 用户中心菜单 ----------------
   改造前：8 行等宽等高、彼此只隔一条 1px 发丝线，是一整块「设置项清单」。
   问题不在某一项不好看，而在层级全平：导航、管理入口、退出登录长得一模一样，
   而三者的后果差得很远。
   现在：分三组 + 组标题（一眼能扫到「我买的」在哪），行与行不再画线，
   改用「留白 + hover 时整行变成浅色圆角块」来区分；
   当前页是实心渐变胶囊；退出登录落到带虚线分隔的底部，hover 走危险色。 */
.rd-uc-menu {
    padding: 8px;
    border-radius: var(--rd-radius);
    border: 1px solid var(--rd-border);
    background: var(--rd-surface);
}

.rd-uc-menu-title {
    padding: 9px 10px 4px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .06em;
    color: var(--rd-muted);
}

/* 第一个组标题不占额外的上边距 —— 不然菜单顶部会多出一段没用的空白 */
.rd-uc-menu-group:first-child .rd-uc-menu-title {
    padding-top: 3px;
}

/* 组与组之间留一点空白，代替原来的发丝线 */
.rd-uc-menu-group+.rd-uc-menu-group {
    margin-top: 6px;
}

.rd-uc-menu a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px;
    border-radius: 10px;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--rd-text-2);
}

/* 图标统一压到 .78 不透明度：菜单项的文字才是主体，图标太满会抢。
   hover / 选中时才全亮，也算一个「这一项被激活了」的即时反馈。 */
.rd-uc-menu a .rd-svg {
    width: 17px;
    height: 17px;
    flex: 0 0 17px;
    opacity: .78;
}

.rd-uc-menu a:hover {
    background: var(--rd-surface-2);
    color: var(--rd-primary);
}

.rd-uc-menu a:hover .rd-svg {
    opacity: 1;
}

.rd-uc-menu a.is-active {
    background: var(--rd-grad);
    color: #fff;
    box-shadow: 0 10px 20px -12px rgba(51, 85, 255, .95);
}

.rd-uc-menu a.is-active .rd-svg {
    opacity: 1;
}

.rd-uc-menu-foot {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px dashed var(--rd-border);
}

/* 「退出登录」不额外降低文字对比度。
   一开始想用 --rd-muted（#8b93a7）来「弱化」它，但 13.5px 的字配这个灰只有约 3.1:1，
   低于小字 4.5:1 的安全线 —— 弱化不等于看不清。改用 --rd-text-2（约 7:1），
   「它和导航不一样」这件事交给上面那条虚线和 hover 的危险色来表达。 */
.rd-uc-menu a.is-danger {
    color: var(--rd-text-2);
}

.rd-uc-menu a.is-danger:hover {
    background: rgba(239, 68, 68, .09);
    color: var(--rd-red);
}

.rd-uc-body {
    flex: 1 1 auto;
    min-width: 0;
}

.rd-uc-hd {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 20px;
    border-radius: var(--rd-radius) var(--rd-radius) 0 0;
    border: 1px solid var(--rd-border);
    border-bottom: 0;
    background: var(--rd-surface);
}

.rd-uc-hd h2 {
    margin: 0;
    font-size: 18px;
}

.rd-uc-panel {
    padding: 20px;
    border: 1px solid var(--rd-border);
    border-radius: 0 0 var(--rd-radius) var(--rd-radius);
    background: var(--rd-surface);
}

.rd-stat-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 14px;
    margin-bottom: 20px;
}

/* 会员权益：一个图标配一句说明，三列排布。
   用 flex + justify-content:center，**不用 grid** —— 数量不是 3 的倍数时
   （站长在后台增删过），最后一行会居中，而不是像 grid 那样在右边留一个缺口。
   原来这里是写死 5 条 + grid，看着就像掉了一张卡。 */
.rd-bene-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    justify-content: center;
}

.rd-bene-grid > .rd-stat {
    flex: 0 0 calc((100% - 24px) / 3);
    min-width: 0;
    display: flex;
    gap: 10px;
    align-items: flex-start;
    padding: 14px 16px;
}

.rd-bene-ico {
    flex: 0 0 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 21px;
    color: var(--rd-primary);
}

.rd-bene-ico .rd-svg {
    width: 15px;
    height: 15px;
    flex: 0 0 15px;
}

.rd-bene-ico i {
    font-size: 14px;
    line-height: 1;
}

.rd-bene-txt {
    font-size: 13.5px;
    line-height: 1.6;
    min-width: 0;
}

@media (max-width: 720px) {
    .rd-bene-grid > .rd-stat {
        flex-basis: calc((100% - 12px) / 2);
    }
}

@media (max-width: 460px) {
    .rd-bene-grid > .rd-stat {
        flex-basis: 100%;
    }
}

.rd-stat {
    padding: 16px;
    border-radius: var(--rd-radius);
    border: 1px solid var(--rd-border);
    background: var(--rd-surface-2);
}

.rd-stat b {
    display: block;
    font-size: 23px;
    font-weight: 800;
    color: var(--rd-primary);
    letter-spacing: -.5px;
    /* 统计卡里除了纯数字还有日期（2026-09-30）。不准换行 ——
       两列布局下它会被断成「2026-09-」+「30」，看着像坏了。
       窄屏放不下时靠下调字号解决，见下方断点。 */
    white-space: nowrap;
}

.rd-stat span {
    font-size: 12.5px;
    color: var(--rd-muted);
}

/* ---- 购买流程四步 ----
   原来是直接复用 .rd-stat（统计数字卡）塞进 .rd-grid-3：
   ① 三列网格装四个步骤 → 第四个单独掉到第二行左边，右边空一格；
   ② .rd-stat 的字号是给「23px 的大数字」定的，这里被行内样式压成 15px，
      卡片高度、留白、层级全和页面其他地方对不上，看着就是「借来的样式」。
   现在给流程单独一套：序号方块 + 标题 + 说明，桌面四列、平板两列、手机一列。 */
.rd-steps {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 14px;
    margin: 0 0 26px;
    padding: 0;
    list-style: none;
}

.rd-step {
    padding: 16px;
    border: 1px solid var(--rd-border);
    border-radius: var(--rd-radius);
    background: var(--rd-surface-2);
}

.rd-step-no {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 9px;
    background: var(--rd-grad);
    color: #fff;
    font-size: 13px;
    font-weight: 800;
    line-height: 1;
}

.rd-step-t {
    display: block;
    margin: 10px 0 6px;
    font-size: 14.5px;
    font-weight: 700;
    color: var(--rd-text);
}

.rd-step-d {
    margin: 0;
    font-size: 13px;
    line-height: 1.65;
    color: var(--rd-muted);
}

@media (max-width: 1080px) {
    .rd-steps {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 640px) {
    .rd-steps {
        grid-template-columns: minmax(0, 1fr);
        gap: 10px;
    }
}

/* table */

.rd-table-wrap {
    overflow-x: auto;
    border: 1px solid var(--rd-border);
    border-radius: var(--rd-radius);
}

.rd-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13.5px;
    min-width: 620px;
}

.rd-table th,
.rd-table td {
    padding: 12px 14px;
    text-align: left;
    border-bottom: 1px solid var(--rd-border);
    vertical-align: middle;
}

.rd-table th {
    background: var(--rd-surface-2);
    font-weight: 700;
    font-size: 13px;
    color: var(--rd-text-2);
    white-space: nowrap;
}

.rd-table tbody tr:last-child td {
    border-bottom: 0;
}

.rd-table tbody tr:hover td {
    background: var(--rd-surface-2);
}

.rd-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 22px;
    padding: 0 9px;
    border-radius: var(--rd-radius-pill);
    font-size: 12px;
    font-weight: 700;
}

.rd-chip-ok {
    background: rgba(16, 185, 129, .13);
    color: var(--rd-green);
}

.rd-chip-wait {
    background: rgba(245, 158, 11, .15);
    color: #b45309;
}

.rd-chip-no {
    background: rgba(148, 163, 184, .18);
    color: #64748b;
}

.rd-chip-err {
    background: rgba(239, 68, 68, .13);
    color: var(--rd-red);
}

.rd-chip-info {
    background: var(--rd-primary-soft);
    color: var(--rd-primary);
}

/* avatar uploader */

.rd-avatar-row {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 20px;
}

.rd-avatar-row img {
    width: 76px;
    height: 76px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--rd-border);
}

/* ============================ modal ============================ */

.rd-mask {
    position: fixed;
    inset: 0;
    z-index: 2000;
    background: rgba(12, 16, 28, .55);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s ease, visibility .2s ease;
}

.rd-mask.is-open {
    opacity: 1;
    visibility: visible;
}

.rd-modal {
    width: 100%;
    max-width: 430px;
    max-height: 92vh;
    overflow-y: auto;
    border-radius: var(--rd-radius-lg);
    background: var(--rd-surface);
    box-shadow: var(--rd-shadow-lg);
    transform: translateY(12px) scale(.98);
    transition: transform .22s ease;
}

.rd-mask.is-open .rd-modal {
    transform: translateY(0) scale(1);
}

/* 弹窗头部：图标与标题同一行。
   原来是「图标独占一行 + 标题在下一行」，图标右侧留出一整块空白 ——
   在只有 430px 宽的弹窗里看上去就像没对齐。改成两栏网格：
   图标跨两行，标题与副标题各占一行，头部整体矮下来近 20px。 */
.rd-modal-hd {
    position: relative;
    display: grid;
    grid-template-columns: 42px minmax(0, 1fr);
    column-gap: 13px;
    align-items: center;
    /* 右侧额外留出关闭按钮的位置（它绝对定位在 right:16px、宽 32px），
       否则标题在窄屏下会伸到按钮底下被压住 */
    padding: 22px 58px 6px 26px;
}

.rd-modal-logo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    grid-area: 1 / 1 / 3 / 2;
    border-radius: 13px;
    background: var(--rd-grad);
    color: #fff;
    font-size: 20px;
    font-weight: 800;
}

.rd-modal-hd h3 {
    grid-area: 1 / 2;
    margin: 0;
    font-size: 19px;
    line-height: 1.3;
}

.rd-modal-hd p {
    grid-area: 2 / 2;
    margin: 3px 0 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--rd-muted);
}

.rd-modal-close {
    position: absolute;
    top: 16px;
    right: 16px;
    /* 必须显式抬层：关闭按钮是绝对定位、但排在 .rd-modal-hd 之前，
       而 .rd-modal-hd 也是定位元素且铺满弹窗上半部（内边距里是透明的，照样吃掉点击）。
       两个都是 z-index:auto 时按 DOM 顺序绘制，后画的 .rd-modal-hd 会盖住按钮 ——
       结果就是「看得见、点不动」，而它后面的 .rd-modal-hd 又没有任何可点的东西。 */
    z-index: 3;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: 50%;
    background: var(--rd-surface-2);
    color: var(--rd-muted);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}

.rd-modal-close:hover {
    background: var(--rd-border);
    color: var(--rd-text);
}

.rd-modal-tabs {
    display: flex;
    gap: 4px;
    margin: 16px 26px 0;
    padding: 4px;
    border-radius: var(--rd-radius-pill);
    background: var(--rd-surface-2);
}

.rd-modal-tabs button {
    flex: 1 1 0;
    height: 34px;
    border: 0;
    border-radius: var(--rd-radius-pill);
    background: transparent;
    font-size: 14px;
    font-weight: 700;
    color: var(--rd-muted);
    cursor: pointer;
}

.rd-modal-tabs button.is-active {
    background: var(--rd-surface);
    color: var(--rd-primary);
    box-shadow: var(--rd-shadow-sm);
}

.rd-modal-bd {
    padding: 18px 26px 26px;
}

.rd-modal-panel {
    display: none;
}

.rd-modal-panel.is-active {
    display: block;
}

.rd-code-row {
    display: flex;
    gap: 8px;
}

.rd-code-row .rd-input {
    flex: 1 1 auto;
}

.rd-modal-foot {
    margin-top: 14px;
    font-size: 13px;
    color: var(--rd-muted);
    text-align: center;
}

.rd-modal-foot a {
    color: var(--rd-primary);
    font-weight: 500;
}

.rd-alert {
    display: none;
    margin-bottom: 14px;
    padding: 10px 14px;
    border-radius: var(--rd-radius-sm);
    font-size: 13.5px;
    line-height: 1.6;
}

.rd-alert.is-open {
    display: block;
}

.rd-alert-err {
    background: rgba(239, 68, 68, .1);
    color: #c53030;
    border: 1px solid rgba(239, 68, 68, .24);
}

.rd-alert-ok {
    background: rgba(16, 185, 129, .1);
    color: #047857;
    border: 1px solid rgba(16, 185, 129, .24);
}

.rd-alert-info {
    background: var(--rd-primary-soft);
    color: var(--rd-primary);
    border: 1px solid rgba(51, 85, 255, .22);
}

.rd-captcha {
    display: flex;
    gap: 8px;
    align-items: center;
}

.rd-captcha img {
    height: 42px;
    border-radius: var(--rd-radius-sm);
    border: 1px solid var(--rd-border);
    cursor: pointer;
}

/* pay modal */

.rd-pay-amount {
    margin: 0 0 16px;
    text-align: center;
}

.rd-pay-amount b {
    font-size: 34px;
    font-weight: 800;
    color: var(--rd-red);
    letter-spacing: -1px;
}

.rd-pay-methods {
    display: grid;
    gap: 10px;
    margin-bottom: 16px;
}

.rd-pay-way {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 13px 15px;
    border-radius: var(--rd-radius-sm);
    border: 1px solid var(--rd-border);
    background: var(--rd-surface-2);
    cursor: pointer;
    transition: all .16s ease;
}

.rd-pay-way:hover {
    border-color: rgba(51, 85, 255, .5);
}

.rd-pay-way.is-on {
    border-color: var(--rd-primary);
    background: var(--rd-primary-soft);
    box-shadow: 0 0 0 3px rgba(51, 85, 255, .1);
}

.rd-pay-way i {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 10px;
    font-style: normal;
    font-size: 17px;
    color: #fff;
}

.rd-pay-way i.alipay {
    background: #1677ff;
}

.rd-pay-way i.wechat {
    background: #07c160;
}

.rd-pay-way i.epay {
    background: #7b3fe4;
}

.rd-pay-way b {
    display: block;
    font-size: 14px;
}

.rd-pay-way small {
    font-size: 12px;
    color: var(--rd-muted);
}

.rd-qr {
    padding: 18px;
    text-align: center;
    border-radius: var(--rd-radius);
    background: var(--rd-surface-2);
    border: 1px dashed var(--rd-border-2);
}

/* ★ 二维码得显式居中，光靠父级的 text-align:center 等不来。
   qrcode.min.js 生成的是 <img>（base64 PNG）且 display:block ——
   块级元素不吃 text-align，会稳稳贴在左边。实测容器 340px、二维码 190px，
   中心偏移刚好 -75px（正是 (340-190)/2）。 */
.rd-qr-box {
    display: flex;
    align-items: center;
    justify-content: center;
}

.rd-qr-box img,
.rd-qr-box canvas {
    display: block;
    margin: 0 auto;
    max-width: 100%;
    background: #fff;
    padding: 8px;
    border-radius: var(--rd-radius-sm);
}

.rd-qr-box img,
.rd-qr > img {
    width: 190px;
    height: 190px;
}

/* 扫码态：挑支付方式、「立即支付」、优惠券与底部说明全部收起。
   它们此刻都不再起作用，留着只会让人以为「还没开始付」；
   顺带把弹层内容从 707px 压到 380px 左右 —— 矮窗口下不会再冒出滚动条。 */
.rd-modal.is-qr .rd-pay-methods,
.rd-modal.is-qr [data-pay-coupon],
.rd-modal.is-qr [data-pay-mail-row],
.rd-modal.is-qr [data-pay-submit],
.rd-modal.is-qr [data-pay-tip] {
    display: none !important;
}

.rd-pay-note {
    display: none;
    margin: 10px 0 0;
    font-size: 12.5px;
    line-height: 1.7;
    color: var(--rd-muted);
}

.rd-pay-note.is-on {
    display: block;
}

.rd-pay-note.is-warn {
    color: #b45309;
}

.rd-qr-actions {
    display: flex;
    gap: 8px;
    justify-content: center;
    flex-wrap: wrap;
    margin-top: 12px;
}

.rd-coupon-row {
    display: flex;
    gap: 8px;
    margin-bottom: 16px;
}

.rd-coupon-row .rd-input {
    flex: 1 1 auto;
}

/* ============================ misc ============================ */

.rd-panel-note {
    padding: 12px 15px;
    border-radius: var(--rd-radius-sm);
    background: var(--rd-gold-soft);
    color: #92400e;
    font-size: 13px;
    line-height: 1.7;
    border: 1px solid rgba(245, 158, 11, .3);
}

.rd-ticket {
    padding: 16px 18px;
    border-radius: var(--rd-radius);
    border: 1px solid var(--rd-border);
    background: var(--rd-surface-2);
    margin-bottom: 14px;
}

.rd-ticket-hd {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
}

.rd-ticket-hd b {
    font-size: 15px;
}

.rd-reply {
    margin-top: 10px;
    padding: 11px 14px;
    border-radius: var(--rd-radius-sm);
    background: var(--rd-surface);
    border: 1px solid var(--rd-border);
    font-size: 13.5px;
}

.rd-reply.is-admin {
    border-color: rgba(51, 85, 255, .3);
    background: var(--rd-primary-soft);
}

@media (max-width: 1080px) {
    .rd-hero h1 {
        font-size: 32px;
    }

    .rd-trust {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        padding: 6px;
        gap: 6px;
    }

    .rd-trust .rd-trust-item {
        border-left: 0;
        padding: 12px 14px;
        background: var(--rd-surface-2);
        border-radius: var(--rd-radius-sm);
    }

    .rd-stat-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 900px) {
    .rd-hero {
        padding: 28px 22px;
    }

    /* 通栏头图不能沿用上面那条 28px/22px：
       横向的 22px 会和 .rd-bleed-in 自带的 18px 叠加成 40px，文字被挤成窄条；
       纵向在手机上 54/64 又太高，首屏一半都给了头图。
       通栏版本左右一律留 0，由 .rd-bleed-in 统一管。 */
    .rd-hero.rd-bleed {
        padding: 30px 0 44px;
    }

    /* 卖点条骑到手机端要「轻」一点：手机上它是 2 列、卡片本身就有 140px 高，
       45px 的骑入量会让头图看起来被吃掉一截。24px 够盖住接缝，也不抢戏。 */
    .rd-trust-wrap {
        margin-top: -24px;
    }

    /* 手机端隐藏侧栏的购买卡。
       详情页在手机上同一屏里会同时出现**三份**价格和购买按钮：
       ① 正文里「获取资源」的完整购买区；② 这一张侧栏购买卡（侧栏在 ≤900 会
       竖排到正文下方，于是它出现在评论区之后）；③ 固定在屏幕底部的吸底购买条。
       第 ③ 个已经保证了「滑到哪都能买」，第 ② 个就只剩重复：
       用户滚到最底部看到「资源价格 ¥199 / 立即购买」，第一反应是
       「我不是刚才买过一遍了吗」。设计上它属于「手机端不适合显示的模块」。
       三块里最先该砍的就是它 —— 砍掉后价格信息仍有两处，且都在该在的位置。
       （侧栏另外两块「资源信息」「相关资源」是有用的补充，保留。） */
    .rd-pricecard.is-side {
        display: none;
    }

    .rd-hero-in {
        grid-template-columns: 1fr;
        gap: 22px;
    }

    .rd-rank {
        padding: 12px 14px 6px;
    }

    .rd-hero h1 {
        font-size: 27px;
    }

    /* 分类头图在主断点里是「文字 + 数字徽块」两列，手机上改成上下排 */
    .rd-hero.is-sort {
        padding: 22px 20px;
    }

    .rd-hero.is-sort .rd-hero-in {
        grid-template-columns: 1fr;
        gap: 14px;
    }

    .rd-hero.is-sort h1 {
        font-size: 24px;
    }

    .rd-sort-stat {
        flex-direction: row;
        align-items: baseline;
        gap: 8px;
        /* 铺满的父级是单列 grid，不写 justify-self 会被拉伸成整行的一条，
           失去「胶囊徽块」的意思。 */
        justify-self: start;
        min-width: 0;
        padding: 9px 16px;
    }

    .rd-sort-stat b {
        font-size: 22px;
    }

    /* 竖排时必须改成 stretch。横排下 align-items: flex-start 是为了让侧栏不被拉高，
       可换到 column 方向后它的含义变成「按内容宽度排布」——
       正文区于是被自己的内容撑到 466px，比容器（347px）还宽，
       整页多出 105px 横向滚动条（375px 实测）。 */
    .rd-uc {
        flex-direction: column;
        align-items: stretch;
    }

    .rd-uc-side {
        width: 100%;
        flex: 0 0 auto;
    }

    .rd-post-hd,
    .rd-post-body,
    .rd-comments,
    .rd-vote,
    .rd-post-tags {
        padding-left: 16px;
        padding-right: 16px;
    }

    .rd-buybox,
    .rd-dlbox {
        margin-left: 16px;
        margin-right: 16px;
    }

    .rd-neighbor {
        grid-template-columns: 1fr;
        padding-left: 16px;
        padding-right: 16px;
    }

    .rd-post-title {
        font-size: 22px;
    }
}

@media (max-width: 640px) {
    /* 小屏首屏只留「标题 + 搜索 + 热搜词」，排行榜收掉：
       它和下方「热门资源 / 最新资源」两个分区内容重复，
       留在 Hero 里会把首屏撑到 800px 以上，用户得滑一屏才看到第一个商品。 */
    .rd-hero-side {
        display: none;
    }

    .rd-trust {
        /* 通栏头图时代，负的上外边距挪到了外层的 .rd-trust-wrap 上（见那条规则），
           这里只负责卡片自己的内边距与圆角。原先的 margin-top:0 是为了抵消
           卡片自身的 -8px，现在没必要留着了。 */
        padding: 5px;
        gap: 5px;
        border-radius: var(--rd-radius);
    }

    .rd-trust-item {
        gap: 9px;
        padding: 11px 12px;
    }

    .rd-trust-ico {
        flex: 0 0 34px;
        width: 34px;
        height: 34px;
        border-radius: 10px;
    }

    .rd-trust-ico .rd-svg {
        width: 17px;
        height: 17px;
        flex: 0 0 17px;
    }

    .rd-trust-item b {
        font-size: 13.5px;
    }

    .rd-trust-item span {
        font-size: 11.5px;
        /* 手机端 2 列时每格的文字区只剩约 95px，而「授权范围见购买说明」这类 9 字
           副标题要 104px —— nowrap + ellipsis 会把尾巴整段吃掉（375px 实测裁掉 10px）。
           窄屏改成允许折行：格子是等高 grid，多一行只把该行抬高几像素，
           总比「句子看得见却被砍一半」好。 */
        white-space: normal;
        overflow: visible;
        text-overflow: clip;
        /* 即使文案再加长，也让两行长度接近（5+4），而不是挤出「8 个字 + 1 个孤字」 */
        text-wrap: balance;
    }

    /* 横排时输入区只剩 150px 出头（375px 实测），拆成上下两块：
       输入独占一行、按钮独占一行，都吃满宽度，手指也更好按。 */
    .rd-hero-search {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
        height: auto;
        padding: 8px;
        border-radius: var(--rd-radius-lg);
    }

    .rd-hero-search input {
        height: 48px;
        padding: 0 14px;
    }

    .rd-hero-search-btn {
        width: 100%;
        height: 46px;
    }

    .rd-stat-grid {
        grid-template-columns: 1fr 1fr;
        gap: 12px;
    }

    /* 两列时每格内容区只剩约 122px（375px 实测），23px 的「2026-09-30」要 125px。
       缩到 20px + 收紧内边距后是 108px，一行放得下，不必再换行。 */
    .rd-stat {
        padding: 13px 12px;
    }

    .rd-stat b {
        font-size: 20px;
    }

    .rd-modal {
        max-width: 100%;
    }

    /* 头部右侧仍要给关闭按钮留位（52px），只有正文两侧收到 18px。
       这里必须分别写，不能写成一条 `.rd-modal-hd, .rd-modal-bd { padding-right: 18px }`——
       那样会把头部预留的那 58px 一起压掉，标题又跑回按钮底下。 */
    .rd-modal-hd {
        padding: 20px 52px 4px 18px;
        column-gap: 11px;
    }

    .rd-modal-bd {
        padding: 16px 18px 22px;
    }

    .rd-modal-tabs {
        margin-left: 18px;
        margin-right: 18px;
    }

    /* 公告在手机上单行只露得出三分之一（375px 下实测要裁掉 228px），
       放成两行让整条内容可读。日期仍在右侧，不跟正文抢宽度。 */
    .rd-notice {
        align-items: flex-start;
    }

    .rd-notice-txt {
        white-space: normal;
        overflow: hidden;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        -webkit-box-orient: vertical;
        /* 命中区 ≥32px：公告常常只有一行（实测高 22px），手机上点不准。
           **不能用 ::after 上下外扩**（项目里其它胶囊是那么做的）——
           上面那句 overflow: hidden 是 -webkit-line-clamp 生效的前提，
           而 ::after 是本元素自己的子盒，会被它自己裁掉；computed style 照样
           报着 top:-5px，只有真点一下才发现点不到（R21 实测踩到过）。
           所以把高度直接做在元素自己身上：一行时也占 32px，多出来的 10px 由
           -webkit-box-pack: center 分成上下各 5px 让文字居中；两行时内容本来
           就撑满，这一条不产生任何影响。 */
        min-height: 32px;
        -webkit-box-pack: center;
    }

    /* 首页分类 Tab 在手机上贴紧上方区块，别再多留 18px */
    .rd-tabs-wrap {
        margin-bottom: 14px;
    }

    .rd-tabs-wrap .rd-tabs {
        gap: 7px;
    }

    .rd-tab {
        height: 34px;
        padding: 0 13px;
        font-size: 13px;
    }
}

@media (max-width: 900px) {
    /* 面包屑在手机上只有 22px 高，手指点「首页」很容易点到旁边的分隔符 */
    .rd-crumb a {
        padding: 6px 0;
    }

    /* 筛选 / 分类胶囊条在手机上一律改成换行排布。
       横向滚动时最后一个胶囊必然被切掉半截露在边上
       （375px 实测：消费记录的「已退款」、首页的「插件工具」都被切），
       看上去就像布局坏了，而且没人会想到右边还能滑。
       换行多占一行，但每一项都完整可见、都能点。 */
    .rd-pills,
    .rd-tabs {
        flex-wrap: wrap;
        overflow-x: visible;
        padding-bottom: 3px;
    }

    /* 用户中心：原样铺开时，头像卡（约 200px）加竖排菜单（约 350px）
       会把真正的页面内容顶到一屏以外 —— 用户进来先看到的是两块导航。
       头像卡收成两行紧凑信息条，菜单改成横向滚动的胶囊条，
       整块高度从约 550px 降到约 110px。 */
    .rd-uc-profile {
        display: grid;
        grid-template-columns: 46px minmax(0, 1fr) auto;
        grid-template-areas:
            "av name vip"
            "av mail vip";
        align-items: center;
        column-gap: 12px;
        row-gap: 1px;
        padding: 13px 15px;
        margin-bottom: 12px;
        text-align: left;
    }

    .rd-uc-profile img {
        grid-area: av;
        width: 46px;
        height: 46px;
        border-width: 2px;
    }

    .rd-uc-profile h3 {
        grid-area: name;
        margin: 0;
        font-size: 15px;
    }

    .rd-uc-profile p {
        grid-area: mail;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .rd-uc-profile .rd-uc-vip {
        grid-area: vip;
        justify-self: end;
        margin: 0;
        max-width: 132px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* 菜单改成「可换行的胶囊条」而不是横向滚动条。
       菜单有 7~9 项、合计约 1000px，横向滚动时最后那枚胶囊必被切掉半截露在边上
       （375px 下实测要滚 689px），看上去就像布局坏了；
       换行多占一两行，但每一项都完整可见、都能点，也不会再有人猜「右边是不是还有」。 */
    .rd-uc-menu {
        display: flex;
        flex-wrap: wrap;
        gap: 7px;
        padding: 0;
        margin-bottom: 14px;
        border: 0;
        border-radius: 0;
        background: transparent;
    }

    /* 桌面端的分组结构在胶囊条里必须「消失」，否则每个 .rd-uc-menu-group
       会变成一个 flex 项，里面的链接竖着堆成一坨，胶囊条就散了。
       display:contents 让子元素直接参与外层 flex —— 比把 markup 拆成
       「桌面版 / 手机版两份」干净得多。组标题直接藏掉：胶囊条本就很短，
       再加三行小标题会把这一块又撑高回去，与「降低首屏导航占比」的初衷相悖。 */
    .rd-uc-menu-title {
        display: none;
    }

    .rd-uc-menu-group,
    .rd-uc-menu-foot {
        display: contents;
    }

    .rd-uc-menu a {
        flex: 0 0 auto;
        padding: 8px 12px;
        border: 1px solid var(--rd-border);
        border-radius: var(--rd-radius-pill);
        background: var(--rd-surface);
        font-size: 13px;
        white-space: nowrap;
    }

    .rd-uc-menu a.is-active {
        background: var(--rd-grad);
        color: #fff;
        box-shadow: none;
    }

    .rd-uc-menu a .rd-svg {
        width: 15px;
        height: 15px;
        flex: 0 0 15px;
    }
}

/* ============================ 超窄屏（≤360） ============================
   这是最窄的一档安卓机。信任条在此宽度下每格内容区只剩约 112px：
   图标 34 + 间距 11 占掉 45，留给「会员资源免费下载」的只有 67px，
   而 12px 的中文要 96px —— 必然被 ellipsis 切掉尾巴（实测裁掉 14px）。
   改成图标在上、文字在下，文字拿到完整的 112px，一行就放得下。 */
@media (max-width: 360px) {
    /* 320px 下统计卡每格内容区只剩约 104px，20px 的日期要 110px —— 再降一档 */
    .rd-stat b {
        font-size: 18px;
    }

    .rd-trust-item {
        flex-direction: column;
        align-items: flex-start;
        gap: 7px;
    }

    .rd-trust-item b {
        font-size: 13px;
    }

    .rd-trust-item span {
        font-size: 11.5px;
    }
}

/* ==================================================================
 * 手机端命中区补丁（≤640px）—— 只放大「手指能点到」的范围，不改外观
 *
 * 项目规矩：手机上可点元素的高度必须 ≥32px（`.workbuddy/tools/audit-mobile.js`，
 * 只在 ≤640 统计，逐个数 `<a> / <button> / .rd-btn`）。这一批胶囊与小链接的
 * **视觉高度是有意收紧的**（22~31px，各自定义处都有说明）—— 直接补 padding
 * 撑到 32px 会把底色、描边、行高一起变大，观感就不是原来那个小胶囊了
 * （`.rd-badge` 更是写死了 `height: 22px`，角标本来就该小）。
 *
 * 做法：绝对定位的 ::after 上下外扩，**底色、文字位置、卡片高度完全不变**。
 *   · 只上下扩（left/right 保持 0），避免横向抢走邻座的点击；
 *   · ::after 上不能加 pointer-events: none —— 那等于没扩；
 *   · 宿主必须 position: relative（下面第一组）。
 *
 * ⚠️⚠️ ::after 是**宿主自己的子盒** —— 宿主只要带 `overflow: hidden`，
 * 那段外扩就会被它自己裁掉。而 `getComputedStyle(el, '::after')` 照样报着
 * `top:-5px`：CSS 读起来一切正常、审计算出来的「有效命中区」也够 32px，
 * **只有真点一下才发现点不到**（R21 实测：.rd-cat 外扩后点「上边缘外 3px」，
 * elementFromPoint 拿到的是 div.rd-item-meta）。
 * 所以下面这两个元素**不在这张表里**，它们的 32px 是做在元素自己身上的，
 * 各自的定义处有完整说明 —— 别把它们再挪回来：
 *   · `.rd-item-meta .rd-cat`（style.css 的 ≤640 段）
 *     要靠 overflow:hidden 截断长分类名（flex 子项没它就没法收缩）
 *   · `.rd-notice-txt`（pages.css 的 ≤640 段）
 *     要靠 overflow:hidden 才能生效 -webkit-line-clamp
 *
 * ⚠️ 这不是「把判据糊过去」：`probe-mobile.js` 有一段**遍历式真实命中测试** ——
 * 对下面表里每一个元素，都在它外扩出来的那几像素上做一次 `elementFromPoint`，
 * 必须命中该元素本身；再往上 9px 做阴性对照，必须不再命中它。
 * 光有审计算出来的数字不算数，两条一起才算。
 * ================================================================== */
@media (max-width: 640px) {
    .rd-badge,
    .rd-more,
    .rd-buybox-tips a,
    .rd-post-tags > a,
    .rd-viewsw-btn,
    .rd-modal-foot a {
        position: relative;
    }

    /* 22~23px → 32px（实测：.rd-badge 22 / .rd-more 23） */
    .rd-badge::after,
    .rd-more::after,
    .rd-buybox-tips a::after {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        top: -5px;
        bottom: -5px;
    }

    /* 31px → 35px。原来只扩 1px，理由是「标签是一排相邻的胶囊，多扩会抢邻座」——
       那条理由站不住：同一行的标签是**水平**相邻，上下扩根本碰不到彼此；
       真正相邻的是**换行后的下一行标签**，而行距只有 8px —— 上下各 2px
       吃掉 4px、还剩 4px，不会重叠。
       而 1px 太贴边：`probe-mobile` 的扫描判据自带 ±1px 采样噪声，
       实测一度只有 32.3px，再有一点字体差异就会假红。 */
    .rd-post-tags > a::after {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        top: -2px;
        bottom: -2px;
    }

    /* 下面两个审计够不到（弹层未打开时 display:none，探针不会去开），
       但手机上确实点不准，顺手一起修：
       `.rd-viewsw-btn` 是「大图/标准/列表」切换，三个是竖排相邻项，只补 1px；
       `.rd-modal-foot a` 是登录弹层底部的「还没有账号 / 忘记密码」，只有 17px 高。 */
    .rd-viewsw-btn::after {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        top: -1px;
        bottom: -1px;
    }

    .rd-modal-foot a::after {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        top: -8px;
        bottom: -8px;
    }
}

/* 320px 这一档（最窄的旧机型）：卡片只有约 114px 可用宽度，
   「分类名 + 浏览量」挤不下，分类名会被压到 60px 宽、把「网站模板」裁掉 6px
   （audit-mobile 的「文字被裁」报的就是它）。
   让底栏换成两行 —— 只影响 ≤360 这一档，360 以上仍然是一行。 */
@media (max-width: 360px) {
    .rd-item-meta {
        flex-wrap: wrap;
        row-gap: 2px;
    }
}
