@charset "UTF-8";
/* ==========================================================================
   Cenilla Network Group — Warm Ink（暖墨）
   设计语言参考 miband.qihe0507.top 的「暖纸底 · 主色强调 · 实心表面 + 细描边」
   一套令牌走全站：暖纸底 · 品牌蓝主色 · 10/16/20px 圆角 · MiSans
   当前只服务于 index.html；其余页面沿用各自的样式，互不影响。

   维护提示：本文件必须是 UTF-8（无 BOM）。
   在 Windows PowerShell 5.1 里不要用 Get-Content -Raw / Set-Content 改这个文件 ——
   它按 ANSI 代码页读写，会把中文注释变成乱码且无法还原。
   ========================================================================== */

:root{
  /* 首屏遮罩的三段强度（左 → 中 → 右）。
     浅色主题下插画本身很亮（天空），薄纱可以薄一些，让插画多露出来；
     深色主题下同一套规则要用厚纱，否则白字压在亮插画上读不出。 */
  --hero-wash-a:58%;--hero-wash-b:40%;--hero-wash-c:10%;
  /* 手机端文字横跨整宽，用不了一左一右的横向纱，改用竖向两段 */
  --hero-wash-m1:58%;--hero-wash-m2:66%;

  color-scheme: light;

  /* ---------- 表面 ---------- */
  --bg:#faf7f4;
  --bg-2:#f4efea;
  --surface:#ffffff;
  --surface-2:#fbf9f7;
  --ink:#1a1517;
  --ink-2:#453c40;
  --muted:#7a6f74;
  --line:rgba(26,21,23,.11);
  --line-2:rgba(26,21,23,.06);

  /* ---------- 外部平台品牌色（只用在图标与悬停描边，不改站内主色） ---------- */
  --brand-bili:#0d93c4;
  --brand-qq:#12b7f5;
  --brand-github:#24292f;
  --brand-afdian:#946ce6;

  /* 改动标记：用 ?diag=1 能读到这个值。
     作用是把「浏览器拿到的到底是哪一版 CSS」变成可读的事实 ——
     否则一遇到「改了没生效」，只能在缓存 / 编码 / 嵌套之间瞎猜。
     **每次改完这个文件记得更新这里的日期。** */
  --css-rev:"2026-10-24 qianse";

  /* ---------- 主色 ----------
     站点主色沿用原有品牌蓝 #2563eb。派生令牌一律 color-mix，
     换一次 --accent 就能整页换色；前一行是同等色值的字面量，给旧浏览器兜底。 */
  --accent:#2563eb;
  --accent-fg:#fff;
  --accent-ink:#1d4ed8;
  --accent-ink:color-mix(in srgb, var(--accent) 78%, #000);
  --accent-soft:rgba(37,99,235,.10);
  --accent-soft:color-mix(in srgb, var(--accent) 10%, transparent);
  --accent-line:rgba(37,99,235,.34);
  --accent-line:color-mix(in srgb, var(--accent) 34%, transparent);

  /* 辅助色：与主色同一套暖色语言，用于图标底色与渐变标题的第二段色相 */
  --teal:#0d8f8f;
  --teal-soft:rgba(13,143,143,.10);
  --amber:#c9791f;
  --amber-soft:rgba(201,121,31,.12);
  --rose:#c4566f;
  --rose-soft:rgba(196,86,111,.12);
  /* 第四辅助色：藏青（取自《夏末白夜》标题的深蓝）*/
  --night:#3a6485;
  --night-soft:rgba(58,100,133,.12);
  --ocean:#1d7fa8;
  --ocean-soft:rgba(29,127,168,.12);
  --lilac:#9f46b8;
  --lilac-soft:rgba(159,70,184,.12);
  --madder:#a34431;
  --madder-soft:rgba(163,68,49,.12);

  --shadow-1:0 1px 2px rgba(26,21,23,.05),0 4px 14px -8px rgba(26,21,23,.14);
  --shadow-2:0 2px 6px rgba(26,21,23,.06),0 20px 44px -24px rgba(26,21,23,.30);

  /* ---------- 模糊令牌 ----------
     全站唯一的模糊出处，声明处一律写 var()，不要写死 blur()。
     首帧脚本给 html 加 .fx-noblur 时，这一组整体解析成 none。

     取值按「液态玻璃」调：单纯 blur 看起来像磨砂塑料，
     真实的玻璃除了糊还要**提饱和 + 提亮**（光线穿过玻璃会略微变艳变亮）。
     所以三档都带 saturate/brightness，不再用裸 blur。 */
  --fx-glass-8:blur(8px) saturate(1.6) brightness(1.06);
  --fx-glass-14:blur(14px) saturate(1.7) brightness(1.07);
  --fx-glass-16:blur(16px) saturate(1.8) brightness(1.08);
  --fx-glass-20:blur(20px) saturate(1.8) brightness(1.1);
  /* 顶栏专用档。取值参考 Windows Aero / iOS Liquid Glass 的思路：
     它们几乎不靠底色遮罩，而是靠**重模糊 + 高饱和**把背后糊成一块柔和光斑，
     文字清晰度由「背景被糊平」来保证，而不是由「盖得够厚」来保证。
     所以这里 blur 拉到 32px、saturate 到 2.1 —— 饱和提上去之后，
     透出来的颜色更艳，玻璃感反而更强（Aero 就是这个观感）。
     代价：32px 是全站最贵的一处合成，且顶栏常驻，滚动时逐帧采样背后内容。
     弱机由 html.fx-noblur 整体关掉。 */
  --fx-glass-28:blur(28px) saturate(2) brightness(1.14);
  /* 顶栏专用档。取值对齐 iOS 通知中心那层玻璃的观感：
     它的做法是「模糊半径**远超**栏后文字的行高，把整个字摊平成一片平均色」，
     再叠一层灰调。所以这里 blur 给到 56px ——
     中文正文行高约 24~28px，56px 的采样范围足以把一整个字连同它的上下行
     一起平均掉，不会再留下可辨认的字形轮廓（32px 时会剩轮廓，7% 遮罩时更明显）。
     saturate 提到 2.2 并配 brightness：这是 iOS 玻璃「透出来是彩色柔光斑、
     而不是灰蒙蒙一片」的关键。 */
  --fx-glass-32:blur(32px) saturate(2.1) brightness(1.16);
  --fx-glass-40:blur(40px) saturate(2.1) brightness(1.18);
  --fx-glass-56:blur(56px) saturate(2.2) brightness(1.2);

  /* ---------- 液态玻璃（Liquid Glass）令牌 ----------
     一套玻璃要成立，靠的是四层叠加，缺一层就「像塑料」：
       ① 模糊 + 提饱和      —— backdrop-filter
       ② 底色本身半透明     —— glass-tint-bar / glass-tint-strong
       ③ 顶部内高光         —— glass-hi-soft（光从上方来，上沿更亮）
       ④ 环形细描边         —— glass-rim  （玻璃的厚度感来自边缘，不是阴影）
     iOS 26 的 Liquid Glass 还带折射与镜面高光，网页端能还原到的最接近程度
     就是这四层 —— 纯 CSS 做不了真实折射（需要 SVG displacement map）。

     底色分两档，按「面板会不会一直有内容从下面滚过」来选：
       glass-tint-bar   顶栏专用，最透 —— 用户要看的就是玻璃后面在滚
       glass-tint-strong 固定面板（下拉菜单、回到顶部），透过头会看不清上面的字
     另有 glass-tint-bar-stuck：顶栏吸顶后略收一点透明度，压住底下的内容。
     顶栏这档又比其它玻璃更透，因为用户要的就是「看得见内容在玻璃后面滚」。
    配套把模糊加到 28px：透明度越低，越要靠模糊来维持可读性 ——
    底色只剩 14% 时，如果模糊也弱，白字压在彩色的插画上会直接糊掉。
    这也是真玻璃的物理：越透的玻璃越靠折射糊住背后，而不是靠自身颜色盖。
    代价说明：顶栏是常驻的，28px 模糊意味着滚动时逐帧采样背后内容，
    这是全站最贵的一处合成；弱机由 html.fx-noblur 整体关掉。 */
  --glass-tint-bar:color-mix(in srgb, var(--bg) 30%, transparent);
  --glass-tint-bar-stuck:color-mix(in srgb, var(--bg) 40%, transparent);
  --glass-tint-strong:color-mix(in srgb, var(--bg) 78%, transparent);
  /* 手机那个大的展开菜单专用：比浮层再透一档。
     78% 的面板盖住整屏时看起来就是一块实心板子 —— 面积越大越需要透，
     否则背后的插画完全看不出，玻璃感就没了。
     40px 模糊配 58% 底色：能看见背后的颜色流动，但文字仍然清楚。 */
  --glass-tint-menu:color-mix(in srgb, var(--bg) 58%, transparent);
  --glass-hi-soft:rgba(255,255,255,.14);
  --glass-rim:rgba(255,255,255,.22);
  --glass-blur:var(--fx-glass-56);

  /* ---------- 平台表面质感：桌面 = Windows Aero --------------------------
     Aero 的标志是顶部那条**镜面反光带** —— 受光玻璃的反射，
     从左上斜下来，越往下越淡。所以用一个 135° 的白色渐变层，
     在很短的行程内（0% → 42%）从 20% 白淡到 1%，形成「亮 → 透明」的反光。
     手机端在下面的 @media 里整套换成 Liquid Glass（去掉反光带、改用边缘亮线）。 */
  --glass-sheen:linear-gradient(135deg,
    rgba(255,255,255,.20) 0%,
    rgba(255,255,255,.07) 22%,
    rgba(255,255,255,.01) 42%,
    transparent 68%);

  /* ---------- 折射层（Liquid Glass 的「真折射」）-------------------------
     默认关闭。开启后会被追加到 backdrop-filter 链末尾，
     用内联的 feDisplacementMap 把玻璃边缘的背后内容推开，形成透镜感。
     三档强度对应 HTML 里三个滤镜（scale 8 / 16 / 28）。
     由 app.js 读 ?refract=s|m|l 写入（也记忆到 localStorage）。

     为什么默认关：这是**全站最贵的一层** —— SVG 滤镜作用在 backdrop 上，
     滚动时逐帧对整条顶栏做位移采样。而且 Safari 对 backdrop-filter 里的
     url() 支持不稳，不支持的浏览器会静默忽略（这是可接受的降级）。 */
  --glass-refract:none;
  --grid:rgba(26,21,23,.045);
  --grain-opacity:.28;
  --grain-blend:multiply;
  --spot:rgba(37,99,235,.10);
  --spot:color-mix(in srgb, var(--accent) 10%, transparent);
  --shimmer:rgba(255,255,255,.34);
  --row-number:rgba(26,21,23,.16);

  --cursor-ring:rgba(37,99,235,.55);
  --cursor-ring:color-mix(in srgb, var(--accent) 55%, transparent);
  --cursor-ring-bg:rgba(37,99,235,.10);
  --cursor-ring-bg:color-mix(in srgb, var(--accent) 10%, transparent);
  --cursor-dot:var(--accent);

  /* 主题切换的圆形揭示：中心与半径由 app.js 点击时写入 */
  --vt-x:50%;
  --vt-y:50%;
  --vt-r:120vmax;

  /* ---------- 形状与节奏 ---------- */
  --r-s:10px;
  --r-m:16px;
  --r-l:20px;
  --ease:cubic-bezier(.22,1,.36,1);
  --spring:cubic-bezier(.34,1.4,.64,1);
  --shell:1140px;

  /* ---------- 标题阶梯 ----------
     首屏大标题（--t-display）已随 h1 一起删除；要加回来时从下面的
     预留令牌里取一档即可，不必重新定标度。 */
  --t-h2:clamp(30px,3.8vw,46px);     --t-h2-ls:-.035em;
  --t-h3:clamp(19px,2vw,22px);       --t-h3-ls:-.012em;
  --t-lede:16px;                     --t-lede-lh:1.85;

  --ic-xs:14px; --ic-s:16px; --ic-m:18px; --ic-l:24px; --ic-xl:28px;

  /* 下面这组是「预留令牌」：与参考站共用同一套刻度，但本页目前用不到，
     保留是为了以后加区块时不用重新起名。改它们不会有任何视觉变化。
       --t-h1 / --t-h1-ls   单篇详情页的大标题
       --t-h3 / --t-h3-ls   三级标题（本页卡片标题用的是写死的 16.5 / 17.5px）
       --t-lede             首屏导语字号（本页 .hero .lede 直接写 16px）
       --elev-3             最强一档投影（本页最深只用到 --elev-2）
       --fx-glass-16 / 20   中等档毛玻璃（本页目前只用 8 / 14 / 24，这两档备用） */

  --font:"MiSans","HarmonyOS Sans SC","PingFang SC","Hiragino Sans GB","Microsoft YaHei",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;
}

/* ---------- 平台表面质感：手机 = iOS Liquid Glass ------------------------
   只在 ≤820px 生效，桌面端保持上面那套 Aero（斜向镜面反光带）。

   Liquid Glass 与 Aero 的三点区别（这是它看起来「更润」的原因）：
     · 没有硬反光带 —— 高光是**边缘**性质的，不做整面斜向渐变
     · 描边更亮更细 —— 玻璃的「厚度」由边缘一圈亮线表达
     · 更透明、更偏中性 —— Aero 带冷调（青蓝），Liquid Glass 基本是无色
   iOS 26 那层真实折射（背板扭曲）纯 CSS 做不到，需要 SVG displacement map，
   这里还原到的是「边缘高光 + 细亮边 + 高透明」这三点可表达的部分。 */
@media (max-width:820px){
  :root{
    --glass-sheen:none;
    --glass-rim:rgba(255,255,255,.42);
    --glass-hi-soft:rgba(255,255,255,.30);
    /* 手机再透一档：屏幕小、内容密度低，透一些不会影响读 */
    --glass-tint-bar:color-mix(in srgb, var(--bg) 24%, transparent);
    --glass-tint-bar-stuck:color-mix(in srgb, var(--bg) 34%, transparent);
    /* 手机上的模糊比桌面再重一档：屏幕小、顶栏相对占屏比例大，
       32px 在小尺寸下看起来还不够「糊」，栏后文字仍会透出形状。 */
    --glass-blur:var(--fx-glass-40);
  }
}

[data-theme="dark"]{
  --hero-wash-a:84%;--hero-wash-b:62%;--hero-wash-c:20%;
  --hero-wash-m1:76%;--hero-wash-m2:84%;

  color-scheme: dark;

  --bg:#141011;
  --bg-2:#191416;
  --surface:#1d1819;
  --surface-2:#231d1f;
  --ink:#f4efe9;
  --ink-2:#cfc5c7;
  --muted:#9a8f92;
  --line:rgba(255,255,255,.13);
  --line-2:rgba(255,255,255,.07);

  /* 深色下品牌色提亮，保证在暗底上的可读性 */
  --brand-bili:#4bb8e8;
  --brand-qq:#4bc8f5;
  --brand-github:#e8eaed;
  --brand-afdian:#b39aff;

  --accent:#5b8cff;
  --accent-fg:#06132c;
  --accent-ink:#9ab6ff;
  --accent-ink:color-mix(in srgb, var(--accent) 74%, #fff);
  --accent-soft:rgba(91,140,255,.14);
  --accent-soft:color-mix(in srgb, var(--accent) 14%, transparent);
  --accent-line:rgba(91,140,255,.40);
  --accent-line:color-mix(in srgb, var(--accent) 40%, transparent);

  --teal:#38c4be;
  --teal-soft:rgba(56,196,190,.14);
  --amber:#e2a561;
  --amber-soft:rgba(226,165,97,.14);
  --rose:#ff7d97;
  --rose-soft:rgba(255,125,151,.14);
  --night:#7db2d8;
  --night-soft:rgba(125,178,216,.14);
  --ocean:#5cc4e8;
  --ocean-soft:rgba(92,196,232,.14);
  --lilac:#d39ae8;
  --lilac-soft:rgba(211,154,232,.14);
  --madder:#e68673;
  --madder-soft:rgba(230,134,115,.14);

  --shadow-1:0 1px 2px rgba(0,0,0,.55),0 6px 18px -10px rgba(0,0,0,.8);
  --shadow-2:0 2px 8px rgba(0,0,0,.5),0 26px 54px -28px rgba(0,0,0,.9);

  --grid:rgba(255,255,255,.05);
  --grain-opacity:.16;
  --grain-blend:overlay;
  --spot:rgba(91,140,255,.12);
  --spot:color-mix(in srgb, var(--accent) 12%, transparent);
  --shimmer:rgba(255,255,255,.14);
  --row-number:rgba(255,255,255,.20);

  --cursor-ring:rgba(91,140,255,.7);
  --cursor-ring:color-mix(in srgb, var(--accent) 70%, transparent);
  --cursor-ring-bg:rgba(91,140,255,.12);
  --cursor-ring-bg:color-mix(in srgb, var(--accent) 12%, transparent);

  /* 暗色下的玻璃：底色压得更透一点，高光收弱 ——
     暗背景上白色高光超过 .1 会发灰发脏，玻璃看上去像塑料。 */
  /* 暗色下的顶栏比浅色略透：暗底对比高，透一些也不会看不清字 */
  --glass-tint-bar:color-mix(in srgb, var(--bg) 26%, transparent);
  --glass-tint-bar-stuck:color-mix(in srgb, var(--bg) 36%, transparent);
  --glass-tint-strong:color-mix(in srgb, var(--bg) 76%, transparent);
  --glass-hi-soft:rgba(255,255,255,.05);
  --glass-rim:rgba(255,255,255,.16);
}

/* ---------- 主色主题（accent themes）--------------------------------------
   站里所有彩色都派生自 --accent（按钮、链接、高亮、光斑、描边、图标底色……），
   所以换主色只需要覆盖这一个令牌，其余靠 color-mix 自动跟随 ——
   这也是当初坚持「派生令牌一律 color-mix」的回报。

   每个主题只需给三样：
     --accent       主色本身
     --accent-fg    压在实心主色上的文字色（按钮字）
     --accent-ink   主色的加深版，用于深色文字（链接、强调）
   soft / line 两档透明度由 color-mix 生成，不必手写。

   对比度是这条链上最容易翻车的地方：--accent-fg 必须在 --accent 上够读。
   浅色系主色（琥珀、玫红）在白字下对比不足 3:1，所以它们配**深色**文字；
   深色系（蓝、紫、青）配白字。深色模式下主色整体提亮，文字色反转成深色。
   ---------------------------------------------------------------------- */
html[data-accent="violet"]{
  --accent:#7c3aed; --accent-fg:#fff; --accent-ink:#5b21b6;
}
html[data-accent="teal"]{
  --accent:#0b7d7d; --accent-fg:#fff; --accent-ink:#075e5e;
}
html[data-accent="amber"]{
  /* 琥珀在白字下只有 2.8:1，不可读 —— 所以压深色字 */
  --accent:#c9791f; --accent-fg:#2b1600; --accent-ink:#8a4d0c;
}
html[data-accent="rose"]{
  --accent:#b04a61; --accent-fg:#fff; --accent-ink:#833048;
}
html[data-accent="emerald"]{
  --accent:#0f7a4d; --accent-fg:#fff; --accent-ink:#0b5c3a;
}
html[data-accent="magenta"]{
  --accent:#b81f8a; --accent-fg:#fff; --accent-ink:#8a1668;
}
html[data-accent="graphite"]{
  --accent:#3f4652; --accent-fg:#fff; --accent-ink:#2b303a;
}
html[data-accent="sky"]{
  --accent:#0369a1; --accent-fg:#fff; --accent-ink:#075985;
}
html[data-accent="indigo"]{
  --accent:#4f46e5; --accent-fg:#fff; --accent-ink:#3730a3;
}
html[data-accent="olive"]{
  --accent:#5f7a1f; --accent-fg:#fff; --accent-ink:#4a5f16;
}
html[data-accent="coral"]{
  --accent:#c03a2d; --accent-fg:#fff; --accent-ink:#992d23;
}

/* 深色模式：主色提亮、文字色反转为深色，保证在深底上仍然显眼 */
html[data-accent="violet"][data-theme="dark"]{
  --accent:#a78bfa; --accent-fg:#1a0b33; --accent-ink:#c9b6ff;
}
html[data-accent="teal"][data-theme="dark"]{
  --accent:#38c4be; --accent-fg:#04231f; --accent-ink:#7fe0da;
}
html[data-accent="amber"][data-theme="dark"]{
  --accent:#e0a04a; --accent-fg:#2b1600; --accent-ink:#f0c684;
}
html[data-accent="rose"][data-theme="dark"]{
  --accent:#e88aa0; --accent-fg:#33101a; --accent-ink:#f4b3c2;
}
html[data-accent="emerald"][data-theme="dark"]{
  --accent:#4ade80; --accent-fg:#04231a; --accent-ink:#8ff0b5;
}
html[data-accent="magenta"][data-theme="dark"]{
  --accent:#e879d0; --accent-fg:#2a0a24; --accent-ink:#f0a8e0;
}
html[data-accent="graphite"][data-theme="dark"]{
  --accent:#9aa6b8; --accent-fg:#0d1117; --accent-ink:#c3ccd8;
}
html[data-accent="sky"][data-theme="dark"]{
  --accent:#38bdf8; --accent-fg:#0e1116; --accent-ink:#7dd3fc;
}
html[data-accent="indigo"][data-theme="dark"]{
  --accent:#818cf8; --accent-fg:#0e1116; --accent-ink:#c7d2fe;
}
html[data-accent="olive"][data-theme="dark"]{
  --accent:#a9c94f; --accent-fg:#0e1116; --accent-ink:#cbe36a;
}
html[data-accent="coral"][data-theme="dark"]{
  --accent:#f4796b; --accent-fg:#0e1116; --accent-ink:#ffb3a7;
}
/* ---------- 主题配色（从各作品封面提取）---------------------
   不是随手挑的色：每一个都是把对应封面缩小后做色相直方图，
   按「饱和度×明度」加权取主峰，再把饱和与明度调到能当主色的水平。
   四个蓝系封面本来色相接近（GalGod 226° 与永恒 228°），所以把它们拉开到
   每隔 20° 以上，否则六个小圆点看上去像重复。每个都算过对比度，
   实心主色上的字色自动选白或深。 */
html[data-accent="tiny"]{ --accent:#568f2e; --accent-fg:#141011; --accent-ink:#3d6620; }
html[data-accent="galgod"]{ --accent:#6a44c9; --accent-fg:#ffffff; --accent-ink:#4c2f92; }
html[data-accent="eternity"]{ --accent:#2b64ab; --accent-fg:#ffffff; --accent-ink:#1e4779; }
html[data-accent="huangmeic"]{ --accent:#9c642c; --accent-fg:#ffffff; --accent-ink:#70471f; }
html[data-accent="whitenight"]{ --accent:#96825a; --accent-fg:#141011; --accent-ink:#6b5c3f; }
html[data-accent="blueplanet"]{ --accent:#1b8ab2; --accent-fg:#141011; --accent-ink:#146880; }
html[data-accent="catgirl"]{ --accent:#b247aa; --accent-fg:#ffffff; --accent-ink:#8a2f83; }
html[data-accent="qianse"]{ --accent:#a34431; --accent-fg:#ffffff; --accent-ink:#7d3324; }

html[data-accent="tiny"][data-theme="dark"]{ --accent:#8ed65a; --accent-fg:#14200a; --accent-ink:#b6e88f; }
html[data-accent="galgod"][data-theme="dark"]{ --accent:#956efa; --accent-fg:#12062e; --accent-ink:#c0aaff; }
html[data-accent="eternity"][data-theme="dark"]{ --accent:#589df2; --accent-fg:#05203f; --accent-ink:#9cc6f8; }
html[data-accent="huangmeic"][data-theme="dark"]{ --accent:#e39e58; --accent-fg:#2b1600; --accent-ink:#f0c391; }
html[data-accent="whitenight"][data-theme="dark"]{ --accent:#dec592; --accent-fg:#1d1707; --accent-ink:#efdfbe; }
html[data-accent="blueplanet"][data-theme="dark"]{ --accent:#45cafa; --accent-fg:#04222e; --accent-ink:#8de0fb; }
html[data-accent="catgirl"][data-theme="dark"]{ --accent:#e67edd; --accent-fg:#2b0728; --accent-ink:#f4b6ee; }
html[data-accent="qianse"][data-theme="dark"]{ --accent:#e68673; --accent-fg:#2b0d07; --accent-ink:#f3b9aa; }

/* 默认（未设 data-accent 或 =blue）沿用 :root 里的品牌蓝，无需重复定义 */

/* ---------- 玻璃能力分级 ------------------------------------------------
   ① 支持 backdrop-filter —— 走真玻璃；
   ② 不支持（老 Firefox 等）—— 只保留半透明底色。
      关键是**把底色加到接近不透明**，否则半透明面板叠在正文上会糊成一片，
      比不做玻璃还难读。 */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  :root{
    --glass-tint-strong:color-mix(in srgb, var(--bg) 97%, transparent);
    --glass-tint-menu:color-mix(in srgb, var(--bg) 96%, transparent);
    /* 没有模糊时，34% 的顶栏等于「整条透明天窗」，文字会直接和正文叠在一起。
       这里必须顶回接近不透明 —— 玻璃是增强，可读性是底线。 */
    --glass-tint-bar:color-mix(in srgb, var(--bg) 96%, transparent);
    --glass-tint-bar-stuck:color-mix(in srgb, var(--bg) 98%, transparent);
  }
  .site-header{background:var(--glass-tint-bar-stuck)}
  /* 顶栏里的三块按钮也要回实底，否则它们在透明条上同样会糊 */
  .theme-toggle,.menu-toggle,.pill-btn{background:var(--surface)}
}

/* ---------- 基础重置 ---------------------------------------------------- */

*,*::before,*::after{box-sizing:border-box}

html{
  scroll-behavior:smooth;
  scroll-padding-top:88px;
  -webkit-text-size-adjust:100%;
  /* 禁止双指缩放（与 viewport meta 里的 user-scalable=no 同一条策略）。
     pan-x pan-y = 只允许横向和纵向滑动，不允许「捏合缩放」，
     顺带也关掉了双击缩放（双击在手机上常常是误触，会把页面放大到奇怪的比例）。
     子元素各自需要的手势不受影响：取色器写了 touch-action:none、
     合集卡片写了 pan-x，那些更具体的值会覆盖这里。 */
  touch-action:pan-x pan-y;
  background:var(--bg);
  overflow-x:clip;
}

body{
  margin:0;
  min-width:320px;
  overflow-x:clip;
  color:var(--ink);
  font-family:var(--font);
  font-size:16px;
  line-height:1.7;
  font-weight:400;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  transition:background .35s ease,color .35s ease;

  /* 底色氛围：四层多光源渐变叠在暖纸底上，缓慢漂移。
     色相全部取自站点已有的 --accent / --teal / --amber，不引入新色。 */
  background:
    linear-gradient(
      180deg,
      color-mix(in srgb,var(--accent) 9%,transparent) 0%,
      transparent 42%,
      color-mix(in srgb,var(--teal) 7%,transparent) 100%
    ),
    radial-gradient(70% 52% at 12% 12%,color-mix(in srgb,var(--accent) 12%,transparent),transparent 74%),
    radial-gradient(62% 48% at 88% 38%,color-mix(in srgb,var(--teal) 10%,transparent),transparent 76%),
    radial-gradient(56% 46% at 42% 92%,color-mix(in srgb,var(--amber) 8%,transparent),transparent 78%),
    var(--bg);
  background-attachment:fixed;
  background-size:130% 130%,130% 130%,120% 120%,115% 115%,100% 100%;
  background-position:0 0,0 0,100% 10%,24% 100%,center;
  animation:bodyAtmosphere 22s ease-in-out infinite alternate;
}
@keyframes bodyAtmosphere{
  from{background-position:0 0,0 0,100% 10%,24% 100%,center}
  to{background-position:0 0,18% 8%,82% 28%,46% 84%,center}
}
/* 弱机：只停这条改 background-position 的循环（每帧重画整块渐变），底色渐变本身保留 */
html.fx-lite body{animation:none}

img{max-width:100%;height:auto;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;border:0;background:none;cursor:pointer}
ul,ol{margin:0;padding:0;list-style:none}
h1,h2,h3,h4{margin:0}
p{margin:0}

.sprite{position:absolute;width:0;height:0;overflow:hidden}
.sprite symbol{width:0;height:0;overflow:hidden}
/* 图标一律 1em 见方，颜色跟随 currentColor。
   注意：SVG 的 width/height 默认是 300×150，页面上每个 <svg> 都必须带 .ic，
   漏掉的话图标会按 300×150 撑开、把所在容器顶变形。下面两条是兜底。 */
.ic{width:1em;height:1em;display:block;flex:none}
svg:not(.ic):not(.sprite){width:1em;height:1em;display:block;flex:none}

::selection{background:var(--accent-soft);color:var(--accent-ink)}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:6px}

/* ---------- 禁止选中正文文字 --------------------------------------------
   整页的正文、标题、按钮文字都不允许拖选。
   原因：站上到处都是拖拽类交互（卡片倾斜、取色器、自定义光标），
   鼠标一划就把文字涂蓝，既打断交互也难看。

   但**不能一刀切**：下面这些地方必须还能选中，否则会真的伤到功能 ——
     · 输入框 / 可编辑区：取色器的十六进制框、日后的搜索框
     · pre / code：代码片段的意义就是给人复制
     · .selectable：留给「确实需要复制」的文本（诊断面板就用了它）
   用 :where() 包起来是为了让这条规则的优先级为 0，
   以后任何更具体的选择器都能轻松覆盖，不会被这里卡住。
   ---------------------------------------------------------------------- */
body{
  -webkit-user-select:none;
  -moz-user-select:none;
  user-select:none;
}
:where(input,textarea,select,[contenteditable],pre,code,kbd,samp,.selectable){
  -webkit-user-select:text;
  -moz-user-select:text;
  user-select:text;
}

.shell{width:min(var(--shell),calc(100% - 48px));margin-inline:auto}
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* ---------- 背板（网格 + 颗粒） ----------------------------------------
   这一层是「画了但基本看不见」的氛围层：body 自身有不透明渐变背景，
   按绘制顺序盖在 z-index:-2 之上，只有网格线与颗粒在镂空处透出。
   不要往这层加动画 —— 它不会出像素，只会白烧合成层。 */
.backdrop{position:fixed;inset:0;z-index:-2;overflow:hidden;pointer-events:none}
.grid-lines{
  position:absolute;inset:0;
  background-image:
    linear-gradient(var(--grid) 1px,transparent 1px),
    linear-gradient(90deg,var(--grid) 1px,transparent 1px);
  background-size:64px 64px;
  mask-image:radial-gradient(80% 60% at 50% 20%,#000 0%,transparent 82%);
  -webkit-mask-image:radial-gradient(80% 60% at 50% 20%,#000 0%,transparent 82%);
}
.grain{
  position:absolute;inset:0;
  opacity:var(--grain-opacity);
  mix-blend-mode:var(--grain-blend);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E");
}

.spotlight{
  position:fixed;z-index:-1;top:0;left:0;
  width:560px;height:560px;margin:-280px 0 0 -280px;
  border-radius:50%;pointer-events:none;opacity:0;
  transition:opacity .4s ease;
  background:radial-gradient(circle,var(--spot) 0%,transparent 66%);
  will-change:transform;
}
body.has-pointer .spotlight{opacity:1}

/* ---------- 自定义光标 ------------------------------------------------ */
/* 只有 .cursor 元素真实存在时，JS 才给 body 加 .custom-cursor。
   否则 cursor:none 会把系统指针藏掉、而替代光标又不存在 —— 指针直接消失。 */
.cursor{position:fixed;z-index:9999;inset:0;pointer-events:none;display:none}
body.custom-cursor .cursor{display:block}
body.custom-cursor *{cursor:none !important}
body.custom-cursor :is(input,textarea,select,[contenteditable]){cursor:auto !important}

.cursor-dot,.cursor-ring{position:absolute;top:0;left:0;will-change:transform}
/* 指针本体：猫猫头（完整角色，不做二次裁切）。
   cursor-cat.png 96×96：原图白底用「从边缘洪水填充」抠掉，
   并额外留了 8% 透明边距，任何部分都不碰图标边界
   （早前一版把头发和下巴裁出了直边，缩到 32px 就成了一个方块）。
   显示 36px，素材 96px ≈ 2.7 倍，视网膜下依然锐利。
   热区在正中央：margin 取一半，指针坐标落在猫脸中心。 */
.cursor-dot{
  width:36px;height:36px;margin:-18px 0 0 -18px;
  background:url("cursor-cat.png") center/contain no-repeat;
  /* 浅色页面上深色头发也需要一点投影才浮得起来 */
  filter:drop-shadow(0 1px 2px rgba(0,0,0,.32));
  transition:opacity .3s ease,width .22s var(--ease),height .22s var(--ease),margin .22s var(--ease);
}
/* 悬停可用元素时：猫头放大一点，外圈浮出一枚主色细环作为反馈。
   静止时不显示圆环，免得压住猫脸。 */
.cursor-ring{
  width:30px;height:30px;margin:-15px 0 0 -15px;
  border-radius:50%;
  border:1.5px solid transparent;
  opacity:0;
  transition:width .28s var(--ease),height .28s var(--ease),margin .28s var(--ease),
             border-color .3s ease,opacity .3s ease;
}
body.cursor-hover .cursor-dot{width:42px;height:42px;margin:-21px 0 0 -21px}
body.cursor-hover .cursor-ring{
  width:58px;height:58px;margin:-29px 0 0 -29px;
  border-color:var(--cursor-ring);
  opacity:1;
}
body.cursor-down .cursor-dot{width:32px;height:32px;margin:-16px 0 0 -16px}
body.cursor-hidden .cursor-dot,body.cursor-hidden .cursor-ring{opacity:0}

/* ---------- 顶栏（液态玻璃） -------------------------------------------- */

/*
  顶栏是站里最主要的玻璃面：它常驻、底下一直有内容滚过，最经得起看。
  四层叠加缺一不可（见文件头「液态玻璃令牌」）：
    ① backdrop-filter 糊背后内容并提饱和
    ② 自身半透明底色
    ③ 底部内高光（光从上方来，玻璃下沿会收一条亮线）
    ④ 悬停/滚动后出现环形细描边
  注意 -webkit- 前缀必须写：iOS Safari 只认前缀版本，
  漏掉的话 iPhone 上会退化成一块半透明纯色。

  顶栏宽度预算（改这里的尺寸前先算一遍）：
  一行里最多要放下 4 块 —— 品牌（头像+文字）、GitHub 胶囊、主题、菜单。
  桌面 1140px 容器绰绰有余；但 iPhone 375px 上
  32+150+118+44+44 再加 3 个 gap 与 40px 边距 = 476px，直接撑爆。
  所以窄屏必须做减法：GitHub 胶囊收成纯图标、字号与间距各降一档。
  下面 ≤820px / ≤560px 两段里的数字都是按 375 / 320px 实算过的，
  要调就一起调，别只动一个。
*/
.site-header{
  position:fixed;z-index:50;top:0;left:0;right:0;
  /* 底色与高光是两层：底色由令牌给，高光由平台的 --glass-sheen 追加。
     分两层是为了让「同一套模糊与底色，只在表面质感上分平台」成为可能。 */
  background-image:var(--glass-sheen);
  background-color:var(--glass-tint-bar);
  border-bottom:1px solid transparent;
  /* 模糊与折射**必须分在两条独立的 backdrop-filter 上**（见下面 ::before）。
     原因：Chromium 里 backdrop-filter 只要含一个无法解析的函数，
     整条声明会被丢弃。曾经写成 blur(...) var(--glass-refract)，
     而 --glass-refract 默认是 none —— 在 Chromium 里这被判为无效值，
     连模糊一起失效（顶栏直接变透明，背后文字清清楚楚）。
     现在是两层：这层只负责模糊，永远有效；折射那层独立，坏了也不牵连。 */
  backdrop-filter:var(--glass-blur);
  -webkit-backdrop-filter:var(--glass-blur);
  box-shadow:inset 0 1px 0 var(--glass-hi-soft);
  transition:background .3s ease,border-color .3s ease,box-shadow .3s ease,transform .34s var(--ease);
}
.site-header.is-stuck{
  background-color:var(--glass-tint-bar-stuck);
  border-bottom-color:var(--glass-rim);
  /* 吸顶后加一条底部内高光 + 极淡外阴影，把「玻璃板」和内容分开 */
  box-shadow:
    inset 0 1px 0 var(--glass-hi-soft),
    inset 0 -1px 0 var(--glass-hi-soft),
    0 8px 24px -20px rgba(26,21,23,.5);
}

/* 折射层：独立的一层玻璃，盖在顶栏内容之下、模糊层之上。
   为什么不和模糊写同一条：见上面 .site-header 里的说明 ——
   Chromium 会因一个无效函数丢弃整条 backdrop-filter。
   独立成层之后，url(#f-refract-*) 不被支持时只是这一层不生效，
   模糊照常。默认 --glass-refract 是 none，这一层什么都不做。 */
.site-header::before{
  content:"";position:absolute;inset:0;z-index:0;
  pointer-events:none;
  border-radius:inherit;
  backdrop-filter:var(--glass-refract);
  -webkit-backdrop-filter:var(--glass-refract);
}
.header-inner{
  position:relative;z-index:1;
  width:min(var(--shell),calc(100% - 40px));margin-inline:auto;
  display:flex;align-items:center;gap:16px;height:64px;
}

/* ---------- 顶栏文字的可读性保障 ----------------------------------------
   底色压到 7% 之后，顶栏几乎没有遮罩了 —— 文字直接坐在「模糊后的插画」上。
   插画明暗不均（首屏那张上半部很亮、下半部偏暗），同一个颜色不可能到处都够对比。
   所以给顶栏内的文字与图标加一层极淡的柔光：
   亮底上它把文字边缘压住，暗底上几乎看不见 —— 两头都不吃亏。
   这是 Windows Aero 当年的做法（文字带发光），也是这套「低遮罩高模糊」方案
   能成立的前提。改顶栏透明度时别把这几条删了。 */
.brand-text,
.nav a,
.pill-btn,
.theme-toggle,
.menu-toggle{
  text-shadow:0 1px 5px color-mix(in srgb, var(--bg) 70%, transparent);
}
.brand-text,
.nav a{position:relative;z-index:1}

.brand{display:flex;align-items:center;gap:9px;font-weight:700;letter-spacing:-.01em}
/* 站点图标：黑猫头像。做成圆形 + 细描边，
   与站内其它圆角元素（卡片/按钮）保持同一套圆角语言。
   注意这不是文字标记 —— 图加载失败时只会留一个空位，所以下面给了底色兜底。 */
.brand-avatar{
  flex:none;width:32px;height:32px;
  border-radius:50%;
  border:1px solid var(--line);
  background:var(--surface-2);
  object-fit:cover;
  box-shadow:0 4px 12px -6px rgba(26,21,23,.35);
}
.brand-text{font-size:16.5px;font-weight:700;letter-spacing:-.015em;white-space:nowrap}

.nav{position:relative;display:flex;align-items:center;gap:2px;margin-left:auto}
.nav-ind{
  position:absolute;left:0;bottom:5px;height:2px;width:0;
  border-radius:2px;background:var(--accent);opacity:0;
  transition:transform .42s var(--spring),width .42s var(--spring),opacity .3s ease;
}
.nav a{
  position:relative;padding:10px 13px;border-radius:8px;
  color:var(--muted);font-size:13.5px;font-weight:500;
  transition:color .22s ease,background .22s ease;
}
.nav a:hover{color:var(--ink);background:var(--surface-2)}
.nav a.is-active{color:var(--ink);font-weight:700}

.header-actions{display:flex;align-items:center;gap:6px}
.nav + .header-actions{margin-left:0}
.header-actions:first-of-type{margin-left:auto}

/* 主题/菜单按钮也在顶栏这块玻璃上，一起做成玻璃片，
   否则会看到「玻璃板上贴了两块实心白方块」。 */
/* 顶栏里的三块按钮：底色跟着玻璃一起降，否则「玻璃板」越来越透、
   按钮还是原来那块实心白，反而成了顶栏里最扎眼的东西。
   只降到 16% —— 按钮需要能被看见边界，不能和玻璃一样透，
   否则用户点不到。边界靠 border 与内高光维持。 */
.theme-toggle,.menu-toggle{
  border:1px solid var(--line);
  background:color-mix(in srgb, var(--surface) 16%, transparent);
  backdrop-filter:var(--fx-glass-8);
  -webkit-backdrop-filter:var(--fx-glass-8);
  box-shadow:inset 0 1px 0 var(--glass-hi-soft);
  color:var(--ink-2);
  transition:border-color .22s ease,color .22s ease,background .22s ease;
}
.theme-toggle{display:grid;place-items:center;width:34px;height:34px;border-radius:9px;overflow:hidden}
.theme-toggle:hover{border-color:var(--accent);color:var(--accent-ink)}
.theme-track{position:relative;display:block;width:17px;height:17px}
.theme-track .ic{
  position:absolute;inset:0;font-size:17px;
  opacity:0;transform:scale(.4) rotate(-50deg);
  transition:opacity .26s ease,transform .44s var(--spring);
}
[data-theme-state="light"] .theme-track .t-light,
[data-theme-state="dark"] .theme-track .t-dark{opacity:1;transform:none}

/* 「跟随系统」状态标记：图标右下角一个小点。
   没有它的话，用户没法分辨「现在是深色」和「现在是跟随系统且系统恰好是深色」——
   而这两者的行为完全不同（后者会在系统切换时跟着变）。
   用 ::after 画点，不额外加 DOM。 */
.theme-toggle{position:relative}
.theme-toggle::after{
  content:"";position:absolute;right:5px;bottom:5px;
  width:5px;height:5px;border-radius:50%;
  background:var(--accent);
  box-shadow:0 0 0 1.5px var(--surface);
  opacity:0;transform:scale(.4);
  transition:opacity .24s ease,transform .3s var(--spring);
}
[data-theme-pref="auto"] .theme-toggle::after{opacity:1;transform:none}

/* 顶栏里的 GitHub 胶囊按钮：和主题/菜单按钮同一档透明度，
   三块按钮在玻璃板上保持一致，不会有一块特别实。 */
.pill-btn{
  display:inline-flex;align-items:center;gap:5px;
  height:34px;padding:0 12px;border-radius:9px;
  border:1px solid var(--line);
  background:color-mix(in srgb, var(--surface) 16%, transparent);
  color:var(--ink-2);
  font-size:12px;font-weight:500;white-space:nowrap;
  transition:border-color .22s ease,color .22s ease,background .22s ease;
}
.pill-btn .ic{font-size:13px;transition:transform .25s var(--ease)}
.pill-btn:hover{border-color:var(--accent);color:var(--accent-ink)}
.pill-btn:hover .ic{transform:translate(2px,-2px)}

.menu-toggle{display:none;width:34px;height:34px;border-radius:9px;position:relative}
.menu-toggle span{
  position:absolute;left:10px;width:14px;height:1.6px;border-radius:2px;
  background:var(--ink);transition:transform .3s var(--ease);
}
.menu-toggle span:first-child{top:13px}
.menu-toggle span:last-child{top:19px}
.menu-toggle[aria-expanded="true"] span:first-child{transform:translateY(3px) rotate(45deg)}
.menu-toggle[aria-expanded="true"] span:last-child{transform:translateY(-3px) rotate(-45deg)}

/* 移动端菜单也是一块浮在内容上的玻璃板 —— 和顶栏同一套取值，
   否则手机上打开菜单会看到两种质感的半透明面板。 */
.mobile-menu{
  position:fixed;z-index:49;top:72px;left:16px;right:16px;
  padding:12px;border-radius:var(--r-m);
  /* 手机菜单是整个站点里面积最大的一块玻璃，所以用单独一档更透的底色
     （--glass-tint-menu 58%）。用原来 78% 的浮层底色，盖住整屏后
     看起来就是一块实心板子，背后的插画完全透不出来。 */
  background:var(--glass-tint-menu);
  border:1px solid var(--glass-rim);
  backdrop-filter:var(--fx-glass-40);
  -webkit-backdrop-filter:var(--fx-glass-40);
  box-shadow:inset 0 1px 0 var(--glass-hi-soft),var(--shadow-2);
  /* 菜单项（语言 + 13 个色珠 + 导航）叠起来比手机屏幕还高，
     不给最大高度的话底部条目会直接超出视口、怎么划都够不着。 */
  max-height:calc(100vh - 92px);
  max-height:calc(100dvh - 92px);
  overflow-y:auto;
  overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  transform-origin:top center;
  animation:menuIn .28s var(--ease) both;
}
@keyframes menuIn{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
.mobile-menu nav{display:grid;gap:1px}
.mobile-menu nav a{padding:11px 13px;border-radius:9px;font-size:15px;font-weight:500;color:var(--ink-2)}
.mobile-menu nav a:hover{background:var(--surface-2);color:var(--ink)}
/* 移动菜单顶部一行：站名 + 主题切换。
   桌面端这一行整体隐藏 —— 两样东西顶栏都有。 */
.mobile-menu-top{
  display:none;
  align-items:center;gap:10px;
  margin:0 0 10px;padding:0 13px 12px;
  border-bottom:1px solid var(--line);
}
.mobile-menu-brand{
  font-size:15px;font-weight:700;letter-spacing:-.015em;color:var(--ink);
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.mobile-menu-theme{
  position:relative;display:block;flex:none;margin-left:auto;
  width:36px;height:36px;padding:0;border-radius:9px;
  border:1px solid var(--line);background:var(--surface-2);
  color:var(--ink-2);
  transition:border-color .22s ease,color .22s ease;
}
.mobile-menu-theme:hover{border-color:var(--accent);color:var(--accent-ink)}
/* 两枚图标叠在同一格，只切透明度 —— 和顶栏那枚用同一套做法。
   不用 display:none 是因为它太脆：data-theme-state 一旦缺失或取值意外，
   两条规则同时不成立，两枚图标会并排显示，按钮被撑成一个空白方块。
   叠放 + 透明度切换则天然只有一枚可见，最坏情况是两枚都淡一点，不会变形。 */
.mobile-menu-theme .ic{
  position:absolute;top:50%;left:50%;
  translate:-50% -50%;
  font-size:16px;
  opacity:0;transition:opacity .22s ease;
}
[data-theme-state="light"] .mobile-menu-theme .ic:first-child,
[data-theme-state="dark"] .mobile-menu-theme .ic:last-child{opacity:1}

/* ---------- 按钮 -------------------------------------------------------- */

.btn{
  position:relative;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:46px;padding:0 20px;
  border-radius:var(--r-s);border:1px solid transparent;
  font-size:14px;font-weight:700;letter-spacing:.01em;white-space:nowrap;overflow:hidden;
  transition:background .22s ease,color .22s ease,border-color .22s ease,
             box-shadow .22s ease,transform .22s var(--ease);
}
.btn:hover{transform:translateY(-2px)}
.btn:active{transform:translateY(0)}
.btn .ripple{
  position:absolute;border-radius:50%;pointer-events:none;
  background:rgba(255,255,255,.4);
  transform:translate(-50%,-50%) scale(0);
  animation:ripple .62s ease-out forwards;
}
@keyframes ripple{to{transform:translate(-50%,-50%) scale(1);opacity:0}}

.btn-primary{background:var(--accent);color:var(--accent-fg)}
.btn-primary:hover{background:var(--accent-ink);box-shadow:var(--shadow-1)}
.btn-ghost{border-color:var(--line);background:var(--surface);color:var(--ink)}
.btn-ghost:hover{border-color:var(--ink)}
.btn-outline{border-color:var(--line);background:transparent;color:var(--ink)}
.btn-outline:hover{border-color:var(--ink);background:var(--ink);color:var(--bg)}

/* ---------- 首屏 -------------------------------------------------------- */

.hero{
  position:relative;display:flex;flex-direction:column;justify-content:center;
  min-height:100svh;padding:126px 0 90px;
}
.hero-inner{
  width:min(var(--shell),calc(100% - 48px));margin-inline:auto;
  position:relative;z-index:1;
  /* 右侧那块视觉已经拿掉，正文占满整宽 —— 单列时给内容一个上限，
     否则导语会横贯整屏、行长过长反而难读。 */
  display:grid;grid-template-columns:minmax(0,640px);
  gap:0;align-items:center;
}
/* 两团缓慢漂移的极光，色相取自 --accent / --teal */
.hero-inner::before,
.hero-inner::after{
  content:"";position:absolute;z-index:-1;pointer-events:none;border-radius:50%;
  will-change:transform;
}
.hero-inner::before{
  left:-14%;top:-26%;width:min(660px,76vw);aspect-ratio:1;
  background:radial-gradient(closest-side,var(--spot),transparent 70%);
  animation:auroraA 19s ease-in-out infinite alternate;
}
.hero-inner::after{
  right:-16%;bottom:-34%;width:min(580px,70vw);aspect-ratio:1;
  background:radial-gradient(closest-side,color-mix(in srgb,var(--teal) 13%,transparent),transparent 72%);
  animation:auroraB 23s ease-in-out infinite alternate;
}
@keyframes auroraA{from{transform:translate3d(0,0,0) scale(1)}to{transform:translate3d(7%,5%,0) scale(1.13)}}
@keyframes auroraB{from{transform:translate3d(0,0,0) scale(1.06)}to{transform:translate3d(-6%,-7%,0) scale(.94)}}
html.fx-lite .hero-inner::before,
html.fx-lite .hero-inner::after{animation:none}

.particles{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0}
.particle{
  position:absolute;bottom:-6%;
  width:var(--s,4px);height:var(--s,4px);border-radius:50%;
  background:var(--pc,var(--accent));
  opacity:0;
  animation:rise var(--dur,18s) linear var(--delay,0s) infinite;
  translate:var(--px,0) var(--py,0);
}
@keyframes rise{
  0%{transform:translate3d(0,0,0);opacity:0}
  14%{opacity:var(--po,.5)}
  78%{opacity:var(--po,.5)}
  100%{transform:translate3d(var(--dx,20px),-104vh,0);opacity:0}
}

/* 首屏那颗状态胶囊压在插画上，也做成玻璃片，
   和顶栏呼应；不透明白底在插画上会显得像贴上去的纸片。 */
.pill{
  display:inline-flex;align-items:center;gap:8px;
  padding:7px 14px 7px 11px;border-radius:var(--r-s);
  border:1px solid var(--glass-rim);
  background:rgba(255,255,255,.14);
  backdrop-filter:var(--fx-glass-8);
  -webkit-backdrop-filter:var(--fx-glass-8);
  box-shadow:inset 0 1px 0 var(--glass-hi-soft);
  color:#fff;font-size:12.5px;font-weight:500;letter-spacing:.01em;
}
.pulse{
  width:6px;height:6px;border-radius:50%;background:#25a06a;flex:none;
  box-shadow:0 0 0 0 rgba(37,160,106,.5);animation:pulse 2.4s ease-out infinite;
}
@keyframes pulse{
  0%{box-shadow:0 0 0 0 rgba(37,160,106,.45)}
  70%{box-shadow:0 0 0 9px rgba(37,160,106,0)}
  100%{box-shadow:0 0 0 0 rgba(37,160,106,0)}
}

/* .hero h1 的规则随大标题一起删掉了 —— 首屏现在没有 h1。
   如果以后想加回标题，字号阶梯 --t-display / --t-display-ls 还在。
   .hl 保留：.sec-title em 之外，别的区块也可能用到这个高亮色。 */
.hl{color:var(--accent);font-style:normal}

/*
  首屏文字整体反色。
  背景从暖纸底换成了压暗的插画，但文字色还沿用浅色主题的 --ink / --muted
  （深灰），压在暗底上几乎不可读 —— 所以这一段必须整体翻成亮色，
  并给一点柔和投影：插画明暗不均，单靠颜色对比在亮部仍会糊。
*/
.hero /* 首屏大标题：字号随视口爬升，窄屏收到 34px；行高压到 1.08 让两行贴紧。
   第二行用 <em> 单独成块并上主色 —— 主色是用户可换的，所以这里用
   color-mix 把它和白色混合，保证在任何主色下、压在暗插画上都足够亮。 */
.hero-title{
  margin:0;
  font-size:clamp(30px,4.6vw + 8px,62px);
  line-height:1.08;
  font-weight:800;
  letter-spacing:-.035em;
  /* 跟随主题：浅色下 --ink 是近黑，深色下是近白 */
  color:var(--ink);
  text-shadow:0 1px 0 color-mix(in srgb, var(--bg) 55%, transparent);
}
.hero-title em{
  display:block;
  overflow-wrap:break-word;
  font-style:normal;
  color:var(--accent-ink);
}
/* 深色模式给主色那行一层同色辉光（参考站的效果）：
   两层不同半径的阴影叠出「荧光」感，而不是简单的模糊。
   浅色模式下不加 —— 白底上辉光只会把字糊掉。 */
html[data-theme="dark"] .hero-title em{
  text-shadow:
    0 0 18px color-mix(in srgb, var(--accent) 70%, transparent),
    0 0 46px color-mix(in srgb, var(--accent) 38%, transparent);
}

.lede{
  max-width:520px;margin:22px 0 0;
  color:var(--ink-2);
  font-size:16px;line-height:1.85;
}
/* 大标题删掉之后，导语成了首屏第一块文字，别再多压一层上边距 */
.hero .pill + .lede{margin-top:20px}
.hero-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:30px}
/* 首屏主按钮的「荧光」：与首屏主色标题行用的是同一套做法 ——
   两圈同色阴影（近处亮、远处淡）叠出光晕，而不是单层模糊。
   悬停、键盘聚焦、按下三种状态都发光；深色主题下静止态也带一点微光，
   这样它和旁边会发光的主标题是同一套语言。
   右边那颗次级按钮（GitHub）保持原样，不加光。 */
.hero-actions .btn-primary{
  transition:background .22s ease,color .22s ease,box-shadow .28s ease,transform .22s var(--ease);
}
.hero-actions .btn-primary:hover,
.hero-actions .btn-primary:focus-visible,
.hero-actions .btn-primary:active{
  box-shadow:
    0 0 16px color-mix(in srgb, var(--accent) 62%, transparent),
    0 0 40px color-mix(in srgb, var(--accent) 32%, transparent),
    0 10px 26px -10px color-mix(in srgb, var(--accent) 70%, transparent);
  transform:translateY(-1px);
}
.hero-actions .btn-primary:focus-visible{outline:2px solid var(--accent-ink);outline-offset:3px}
html[data-theme="dark"] .hero-actions .btn-primary{
  box-shadow:
    0 0 12px color-mix(in srgb, var(--accent) 34%, transparent),
    0 0 30px color-mix(in srgb, var(--accent) 18%, transparent);
}
html[data-theme="dark"] .hero-actions .btn-primary:hover,
html[data-theme="dark"] .hero-actions .btn-primary:focus-visible,
html[data-theme="dark"] .hero-actions .btn-primary:active{
  box-shadow:
    0 0 20px color-mix(in srgb, var(--accent) 72%, transparent),
    0 0 52px color-mix(in srgb, var(--accent) 42%, transparent),
    0 12px 30px -10px color-mix(in srgb, var(--accent) 80%, transparent);
}
/* 首屏次级按钮：遮罩现在跟随主题，所以按钮也回到常规描边样式，
   不再需要之前那套「暗底反色」的补丁。 */
.hero .btn-ghost{
  border-color:var(--line);
  background:var(--surface-2);
  color:var(--ink);
  backdrop-filter:var(--fx-glass-8);-webkit-backdrop-filter:var(--fx-glass-8);
}
.hero .btn-ghost:hover{border-color:#fff;background:rgba(255,255,255,.24)}

.hero-stats{
  display:flex;flex-wrap:wrap;gap:36px;
  margin-top:42px;padding-top:24px;
  border-top:1px solid var(--line);
}
.hero-stats li{display:flex;flex-direction:column;gap:2px}
.hero-stats strong{
  font-size:26px;font-weight:700;letter-spacing:-.03em;
  color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.hero-stats strong i{font-style:normal;font-size:17px;color:var(--muted);font-weight:700;margin-left:1px}
.hero-stats span{
  color:var(--muted);font-size:12.5px;
}

/* --- 首屏背景插画 + 渐变 ------------------------------------------------ */

/*
  整块首屏铺一张插画，再压一层渐变。
  渐变承担三件事，缺一不可：
   1. 左侧压实 —— 标题、导语、按钮都落在左半边，需要一个足够平的底；
   2. 右侧留亮 —— 让插画的主体（人物）透出来，不至于被糊成一片；
   3. 四边化开 —— 顶边接顶栏、底边接下面的区块，不出现一道生硬的图片边界。
  底色的「实/亮」不写死成暗色：全部由 --bg 混合，浅色主题是纸色薄纱（黑字可读），
  深色主题自动变成暗纱（白字可读）。具体强度见 --hero-wash-* 那组变量。
*/
.hero-bg{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none}
/* 取景：人物偏右，横向取 72% 把脸留在右半边（左边要给文字让位）；
   纵向取 42%。这张图是 2000x1247（比 16:9 高），纵向留白充足，
   居中取景时头部完整落在可见区内 —— 不需要像之前那两版 16:9
   视频素材那样把纵向压到 0% 再靠 transform 下移来躲顶栏。 */
.hero-bg img{
  width:100%;height:100%;object-fit:cover;
  object-position:72% 42%;
}
.hero-bg::after{
  content:"";position:absolute;inset:0;
  /* 遮罩一律用 --bg 混合，不写死 rgba：浅色主题下 --bg 是暖纸色，
     于是左侧成了「纸色薄纱」，黑字读得清；深色主题下 --bg 近黑，
     同一套规则自动变成暗纱、白字。首屏文字因此可以真正跟随主题。
     （左起 82% → 34% 处 54% → 66% 处 14%，右边全透，插画留在右半。） */
  background:
    linear-gradient(180deg,var(--bg) 0%,transparent 11%,transparent 74%,var(--bg) 100%),
    linear-gradient(96deg,
      color-mix(in srgb, var(--bg) var(--hero-wash-a), transparent) 0%,
      color-mix(in srgb, var(--bg) var(--hero-wash-b), transparent) 34%,
      color-mix(in srgb, var(--bg) var(--hero-wash-c), transparent) 66%,
      transparent 100%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--bg) 12%, transparent),
      color-mix(in srgb, var(--bg) 24%, transparent));
}
/* 插画铺满之后，左上那团极光就多余了，隐掉省一次合成 */
.hero-inner::before{display:none}

.scroll-cue{
  position:absolute;left:50%;bottom:26px;transform:translateX(-50%);
  z-index:2;display:flex;flex-direction:column;align-items:center;gap:8px;
  color:var(--muted);font-size:11px;font-weight:500;letter-spacing:.14em;
}
.scroll-cue i{
  width:1px;height:34px;
  background:linear-gradient(180deg,var(--accent-line),transparent);
  animation:cueMove 2.1s ease-in-out infinite;
}
@keyframes cueMove{
  0%,100%{transform:scaleY(.5);opacity:.45;transform-origin:top}
  50%{transform:scaleY(1);opacity:1;transform-origin:top}
}


/* ---------- 区块 -------------------------------------------------------- */

.section{position:relative;padding:112px 0;isolation:isolate}
.section + .section{padding-top:0}

.sec-head{position:relative;z-index:1;max-width:640px;margin-bottom:52px}
.kicker{
  color:var(--accent-ink);
  font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
}
/* 短杠用 inline-block 伪元素，与文字同处一个行盒，版式完全不动 */
.kicker::before{
  content:"";display:inline-block;vertical-align:middle;
  width:18px;height:2px;border-radius:2px;
  margin-right:9px;margin-top:-2px;
  background:linear-gradient(90deg,var(--accent),transparent);
}
.sec-title{
  margin:14px 0 0;
  font-size:var(--t-h2);line-height:1.16;letter-spacing:var(--t-h2-ls);
  font-weight:700;text-wrap:balance;
}
.sec-lede{max-width:560px;margin:18px 0 0;color:var(--muted);font-size:15.5px;line-height:1.85}

/* 渐变强调字：background-clip:text 不支持时文字会整段消失，所以锁在 @supports 里，
   不支持就保留 .hl 的纯色 --accent，零回退风险。 */
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .hl,.sec-title em{
    background-image:linear-gradient(100deg,var(--accent),var(--accent-ink) 42%,var(--accent) 88%);
    background-image:linear-gradient(100deg,
      var(--accent),
      color-mix(in srgb,var(--accent) 52%,var(--teal)) 44%,
      var(--accent) 90%);
    background-size:220% 100%;
    -webkit-background-clip:text;background-clip:text;
    -webkit-text-fill-color:transparent;color:transparent;
    animation:hlPan 14s ease-in-out infinite alternate;
  }
  .sec-title em{font-style:normal}
  @keyframes hlPan{from{background-position:0% 50%}to{background-position:100% 50%}}
}

/* ---------- 悬停主色高亮 ------------------------------------------------ */

/*
   border-radius:inherit 写在 ::after 上时，取值来自**宿主元素**的计算值，
   按规范这是成立的；但它同时受 overflow 与层叠上下文影响，一旦宿主自己
   没有显式圆角（或圆角被子元素覆盖），这块 300px 的径向高光就会以**直角方块**
   铺在卡片上 —— 视觉上就是「卡片的圆角没了」。
   所以这里显式写死 --r-m，并给卡片加 isolation 建立独立层叠上下文，
   不依赖 inherited 圆角这种容易被覆盖的链路。
*/
.glow{position:relative;isolation:isolate}
.glow::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  border-radius:var(--r-m);
  background:radial-gradient(300px circle at var(--px,50%) var(--py,50%),var(--spot),transparent 62%);
  opacity:0;transition:opacity .3s ease;
}
/* 小圆角组件另给一档，免得 16px 的圆角盖过它们本来的形状 */
.pill-btn.glow::after,.contact-chip.glow::after,.rel-item.glow::after{border-radius:var(--r-s)}
.glow:hover::after{opacity:1}

/* ---------- 3D tilt（卡片共用） ---------------------------------------- */
/* 关键约束：这里绝不能出现 transform-style: preserve-3d —— 那会创建真实三维
   渲染上下文，让角标与倾斜平面真实相交、被沿交线切成两半。 */
[data-tilt]{transform-style:flat}
[data-tilt]:hover{will-change:transform}

/* ---------- 项目卡 ------------------------------------------------------ */

/* 作品卡网格：两列。
   曾经为了「第四张卡不换行」改成 auto-fit，但那是错的方向 ——
   两列本来就是这套设计（卡片比例、封面取景、行距都是按两列调的），
   四张卡排成 2×2 才和下面的区块节奏一致。
   加卡片时不用改这里：新卡会自动进入下一行。 */
.product-grid{
  position:relative;z-index:1;display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:20px;
}
/* 卡片数量为奇数时（现在是 5 张），最后一张会单独落在左列、右边空一格，
   看着像少了一块。让它跨满两列再缩回单卡宽度并居中 —— 尺寸不变、位置居中，
   视觉节奏还是「两列」，只是收尾不歪。
   限定在桌面两列布局：窄屏是单列，这条规则会把卡片挤成半宽。 */
@media (min-width:821px){
  .product-grid > .product-card:last-child:nth-child(odd){
    grid-column:1 / -1;
    justify-self:center;
    width:calc(50% - 10px);   /* 50% - 半个 gap，与单列宽一致 */
  }
}

.product-card{
  position:relative;display:flex;flex-direction:row;align-items:stretch;
  border-radius:var(--r-m);border:1px solid var(--line);
  background:var(--surface);box-shadow:inset 0 1px 0 var(--hi-soft),var(--elev-1);
  overflow:hidden;
  transition:border-color .28s ease,box-shadow .34s var(--ease),transform .34s var(--ease);
}
.product-card:hover{border-color:var(--accent-line);box-shadow:inset 0 1px 0 var(--hi),var(--elev-2)}
/* 顶部主色描边：悬停时从左展开 */
.product-card::before{
  content:"";position:absolute;z-index:2;top:0;left:0;right:0;height:2px;
  background:var(--card-accent,var(--accent));
  transform:scaleX(0);transform-origin:0 50%;
  transition:transform .4s var(--ease);
}
.product-card:hover::before{transform:scaleX(1)}

/* 左栏：项目视觉（纯 CSS 生成，不依赖图片素材） */
.product-card-media{
  position:relative;flex:0 0 42%;
  display:grid;place-items:center;
  border-right:1px solid var(--line);
  background:
    radial-gradient(120% 90% at 20% 10%,var(--card-soft,var(--accent-soft)),transparent 70%),
    var(--surface-2);
  overflow:hidden;
}
.product-card-media::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(70% 45% at 50% 0%,var(--shimmer),transparent 72%);
}
/* 角标（已上线 / 待上传）做成磨砂玻璃。
   早先是 88% 的实底 + 8px 模糊 —— 底色太实，模糊看不出来，
   贴在封面上就是一块不透明的牌子。
   现在底色只留一半多点，靠 20px 模糊把背后的插画揉开，
   再加顶部高光与发丝边，就是 iOS 那种毛玻璃质感。
   字色仍用 --ink（随主题）；为什么不用白字 —— 封面有亮有暗，
   白字在亮封面上会消失，而 --ink 配半透底没这个问题。 */
/* 角标（已上线 / 待上传）：尽量透的毛玻璃。
   之前底色 54%~72%，把封面左上角原本的作品标题盖得严实。
   现在只留 26%（浅）/ 30%（深），靠 28px 模糊把背景揉开，
   下面的插画标题仍能透出轮廓。

   字色为什么不再用 var(--ink)：徽标压在封面上，而封面不随主题变。
   实测各封面左上角均亮度：小小的身影 197 · 黄莓C 93 · 夏末白夜 92 · 海蓝星 107
   —— 这四张是亮底；GalGod 3 · 永恒 12 —— 这两张是黑底。
   所以徽标自带两套固定配色，用 data-flag-tone="dark" 指定黑底那几张。 */
.product-card-flag{
  /* 横幅放右上角。封面的作品标题多在左上（小小的身影、黄莓C都是），
     放左边会把它们遮住；七张封面的右上角基本是空的（最多是头发、星空或标题上方的留白）。
     用物理右而不用 inset-inline-end：封面是图片，不随语言镜像，
     RTL 下也应该贴着图片的右上角。 */
  position:absolute;z-index:3;top:14px;right:14px;left:auto;
  display:inline-flex;align-items:center;gap:5px;
  /* 徽标整体缩一号：内距 5/11 -> 3/9、字号 11.5 -> 11、图标 13 -> 12、圆角 10 -> 8。
     缩小后右上角的占用更少，即使封面右上印了作品标题也不容易压到。 */
  padding:3px 9px;border-radius:8px;
  /* 只留 16% 底色 —— 84% 透光，封面上原本的标题能透出来。
     这个值不是拍脑子：七张封面逐个算过（模糊后取均色再叠底色），
     最暗的那张（黄莓C）仍有 5.95:1，其余 7~14:1。 */
  background:color-mix(in srgb,#fff 16%,transparent);
  backdrop-filter:var(--fx-glass-28);
  -webkit-backdrop-filter:var(--fx-glass-28);
  border:1px solid color-mix(in srgb,#fff 52%,transparent);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.60),
    0 1px 4px -1px rgba(20,16,17,.18);
  color:#1a1517;
  text-shadow:0 1px 0 rgba(255,255,255,.55);
  font-size:11px;font-weight:700;letter-spacing:.01em;
}
.product-card-flag[data-flag-tone="dark"]{
  /* 黑底封面用深色玻璃 + 白字，22% 底色（更透）下仍有 12~18:1 */
  background:color-mix(in srgb,#141011 22%,transparent);
  border-color:color-mix(in srgb,#fff 26%,transparent);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.20),
    0 1px 4px -1px rgba(0,0,0,.50);
  color:#fff;
  text-shadow:0 1px 2px rgba(0,0,0,.55);
}
/* 没有模糊的环境（老浏览器 / 弱机）：26% 的半透片直接压在插画上，
   字会跟背后的画麻花，必须把底色提回来。 */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .product-card-flag{background:color-mix(in srgb,#fff 92%,transparent)}
  .product-card-flag[data-flag-tone="dark"]{background:color-mix(in srgb,#141011 90%,transparent)}
}
html.fx-noblur .product-card-flag{background:color-mix(in srgb,#fff 92%,transparent)}
html.fx-noblur .product-card-flag[data-flag-tone="dark"]{background:color-mix(in srgb,#141011 90%,transparent)}
.product-card-flag .ic{font-size:12px;color:var(--card-accent,var(--accent))}
/* 黑底封面上卡片主色（深青/深绣）接近背景，图标会几乎看不见 —— 跟字一起转白 */
.product-card-flag[data-flag-tone="dark"] .ic{color:#fff;opacity:.92}

.product-card-copy{display:flex;flex-direction:column;gap:14px;padding:22px 24px;flex:1;min-width:0}
.product-card-head{display:flex;align-items:center;gap:12px}
/* 卡片头部的作品 logo。
   两个 logo 的原始边角情况不一样 ——「小小的身影」是白角正方形（alpha 全不透明），
   「GalGod」自带 38px 的圆角轮廓（alpha 透明）。所以**圆角在导出时就烘进图片**了，
   两张的四角 alpha 都是 0，这里不需要再靠 CSS 遮盖，也不怕以后换背景色。
   容器保留底色与描边，作为图片加载失败时的兜底。 */
.product-icon{
  display:grid;place-items:center;flex:none;
  width:46px;height:46px;border-radius:12px;
  border:1px solid var(--line);background:var(--surface-2);
  overflow:hidden;
  color:var(--card-accent,var(--accent));
}
.product-icon img{width:100%;height:100%;object-fit:cover;display:block}
.product-card-title{display:flex;flex-direction:column;min-width:0}
.product-card-title h3{font-size:19px;font-weight:700;letter-spacing:-.02em;line-height:1.3}
.product-card-title span{color:var(--muted);font-size:12.5px;margin-top:2px}
.product-card-summary{color:var(--muted);font-size:14px;line-height:1.8}

.card-tags{display:flex;flex-wrap:wrap;gap:6px}
.card-tags i{
  font-style:normal;
  padding:4px 10px;border-radius:var(--r-s);
  border:1px solid var(--line);background:var(--surface-2);
  color:var(--ink-2);font-size:11.5px;font-weight:500;
}

.card-link{
  display:inline-flex;align-items:center;gap:6px;
  color:var(--accent-ink);font-size:13.5px;font-weight:700;
  border-bottom:1px solid var(--accent-line);padding-bottom:2px;
  transition:color .22s ease,border-color .22s ease;
}
.card-link b{font-weight:700;transition:transform .28s var(--ease)}
.product-card:hover .card-link b{transform:translate(2px,-2px)}
.card-link:hover{color:var(--accent);border-color:var(--accent)}

/* 项目卡配色：每张卡自己的主色，由 --card-accent / --card-soft 驱动 */
.product-card[data-tone="amber"]{--card-accent:var(--amber);--card-soft:var(--amber-soft)}
.product-card[data-tone="teal"]{--card-accent:var(--teal);--card-soft:var(--teal-soft)}
.product-card[data-tone="muted"]{--card-accent:var(--muted);--card-soft:var(--line-2)}
.product-card[data-tone="rose"]{--card-accent:var(--rose);--card-soft:var(--rose-soft)}
.product-card[data-tone="night"]{--card-accent:var(--night);--card-soft:var(--night-soft)}
.product-card[data-tone="ocean"]{--card-accent:var(--ocean);--card-soft:var(--ocean-soft)}
.product-card[data-tone="lilac"]{--card-accent:var(--lilac);--card-soft:var(--lilac-soft)}
.product-card[data-tone="madder"]{--card-accent:var(--madder);--card-soft:var(--madder-soft)}

/* ---------- 作品下载卡（Astrobox 安装入口） ----------------------------
   在 .product-card 骨架上加两样：底部的按钮行（安装 + 源码）、以及下面那行安装说明。
   版式由 .media-top 改成「封面在上、文字在下」（见下方封面置顶变体）。
   这两张卡的 CTA 是页面里权重最高的动作，所以用实心主色按钮而不是 .card-link 文字链。 */

.dl-hint{
  margin:10px 0 0;
  color:var(--muted);font-size:11.5px;line-height:1.7;
}

/* 作品卡的按钮行：安装（主色实心）+ 源码（描边玻璃）两颗胶囊。
   刻意不复用 .card-link 那种文字链 —— 它带 border-bottom 与 margin-left:auto，
   两颗放一起会被推歪。这里单独开一个网格，谁也不抢位。

   排列方式按**卡片宽度**决定，不是按屏宽：卡片锁死 216px、内边距 24px，
   留给按钮的总宽只有 192px。并排时每颗 92px，而「前往 Astrobox 安装」
   实测要 136px —— 必然折行。所以窄卡片上改成上下堆叠，各得 192px。
   宽屏（卡片被网格拉宽到 ~380px 以上）才并排。 */
.dl-actions{
  display:grid;grid-template-columns:1fr;
  gap:8px;margin-top:auto;padding-top:6px;
}
.dl-actions .btn{
  width:100%;min-height:46px;padding:0 12px;
  font-size:13px;gap:6px;
}
.dl-actions .btn .ic{font-size:15px;flex:none}

/* 不可点的按钮：App 包尚未上传的作品用（如《永恒与星辰与日常》）。
   做成 <span> 而不是带 disabled 的 <a>：没有 href 就没有焦点、Tab 也跳不到，
   键盘和读屏用户不会撞进一个空链接；aria-disabled 只是补充语义。
   保留主色实心的位置（和将来真正的安装按钮同格），但降透明度 + 去阴影，
   明确表达「现在点不了」。上传完成后把这个 span 换回 <a> 即可。 */
.dl-actions .btn.is-pending{
  opacity:.6;
  box-shadow:none;
  cursor:default;
}

/* 卡片够宽时（≤900px 断点之后卡片变单列满宽）并排两颗 */
@media (max-width:900px){
  .dl-actions{grid-template-columns:repeat(2,minmax(0,1fr))}
/* 现在每张卡有三个按钮（主动作 + Release 下载 + 查看源码）。
   主动作占满一行，后两个并划开；否则 2 列格子里塞 3 个会落下一个孤零零的。 */
.dl-actions .btn-primary{grid-column:1 / -1}
}

/* ---------- 合集卡片区（独立区块）-------------------------------------- */

/* 合集卡单独成区之后，这里不再是两列布局：
   卡片自带 max-width:216px，放在一行里就是左侧一小块。 */
.collage-row{
  position:relative;z-index:1;
  display:flex;flex-wrap:wrap;align-items:flex-start;
  gap:20px;
}

/* --- 合集卡（仿 Astrobox 的「Galgame 合集卡片」）------------------------
   尺寸按原图量的：卡片约 216×272，封面约 192×160，下面依次是
   序号 1/2、作品名（可点，进安装页）、类型行。

   交互是**上下拖动整张卡片**切换下一部作品 —— 翻的是整页
   （封面 + 序号 + 标题 + 类型一起滑），不是只翻图片、文字另换。
   页与页在视口里上下错位叠放：上一页在上方、下一页在下方，
   拖动时相邻那页会斜着探进来。 */
.page-card{
  width:100%;max-width:216px;
  padding:12px;
  border-radius:var(--r-m);
  border:1px solid var(--line);
  background:var(--surface);
  box-shadow:inset 0 1px 0 var(--hi-soft),var(--elev-1);
  transition:box-shadow .34s var(--ease),border-color .28s ease,translate .34s var(--ease);
}
.page-card:hover{border-color:var(--accent-line);box-shadow:inset 0 1px 0 var(--hi),var(--elev-2);translate:0 -3px}

/* 视口就是「一页的位置」，页与页在这里面错位叠放 */
.pc-viewport{
  position:relative;
  border-radius:12px;
  background:var(--surface-2);
  cursor:grab;
  /* 纵向拖动归我们，横向留给页面（避免手机上左右滑时误触翻页） */
  touch-action:pan-x;
  overflow:hidden;
}
.pc-viewport.is-dragging{cursor:grabbing}
.pc-viewport:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.pc-slot{position:relative}

/* 一页：封面 + 文字整块，绝对定位叠在视口里，由 JS 摆位 */
.pc-page{
  position:absolute;top:0;left:0;right:0;
  padding-bottom:14px;
  transition:transform .5s var(--ease),opacity .44s ease,filter .44s ease;
  will-change:transform,opacity;
}
.pc-viewport.is-dragging .pc-page{transition:none}

/*
  非当前页的透明度一律由 JS 写 inline 控制（拖动时按位移实时算）。
  这里**不要再写** .pc-page:not(.is-current){opacity:...} 这类规则 ——
  规则优先级高于 inline 之外的默认值、又和拖动中的实时值打架，
  一旦写成 0.4 这种半透明，静止态就会两页叠着显示，正是重影的来源。
  「没被 JS 接管时只显示第 1 页」这件事，交给下面的 display 兜底即可。
*/

/*
  CSS 兜底：第 2 页起默认藏起来，只有 JS 明确接管之后才显示。
  这样「JS 没跑 / 跑晚了 / 量高失败」时，视口里永远只有第 1 页，
  不会退化成两页在普通流里上下叠着、糊成一片重影。
  绝对定位的页会脱离普通流，若不隐藏，视口高度为 0 时它们全会叠在同一格。
  JS 打完 .pc-ready（表示已经摆好位）才放开后面几页。
*/
.pc-page + .pc-page{display:none}
.pc-viewport.pc-ready .pc-page + .pc-page{display:block}

.pc-cover{
  margin:0;
  /*
    封面框比例是算出来的，不是随手定的。
    三张原画的比例是 1.501 / 1.536 / 1.777，框和原画的比值决定了 cover
    要裁掉多少（比值越偏离 1 裁得越多）。实测各候选比例下三张图的最大裁剪量：

      6:5  (1.20)  21.9% / 32.5% / 20.0%   max 32.5%   ← 一开始用的，裁得最狠
      2:1  (2.00)  23.2% / 11.2% / 25.0%   max 25.0%   ← 太扁，裁剪从左右转到上下
      16:9 (1.78)  12.2% /  1.5% / 14.3%   max 14.3%
      5:3  (1.65)   6.9% /  7.1% /  9.1%   max  9.1%   ← 选它

    5:3 时三张图裁得最平均、最坏情况也只有 9.1%，
    顺带把封面区高度压到 ~116px，卡片整体更紧凑。
  */
  aspect-ratio:5 / 3;
  border-radius:16px;
  overflow:hidden;
  background:var(--surface-2);
}
/*
  封面必须**铺满整框**，R 角才看得出来 —— 这是关键。
  之前用 contain：图片上下留白、边缘缩在框内部，那圈圆角只作用在框上，
  观众看到的是图片自己的直角边，于是「R 角像是没了」。

  现在用 cover：铺满整框、四角紧贴圆角，不做非等比拉伸。
  三种取景可用 URL 参数临时对比：?fit=fill（拉伸、不裁但会变形）
  / ?fit=contain（不裁不变形、但上下留白看不到 R 角）。

  R 角写两处：框 16px + 图片 14px。contain 模式下图片不贴边，
  这时图片自己的圆角就是唯一能看见的那圈 —— 留着它兜住这种取景。 */
.pc-cover img{
  width:100%;height:100%;object-fit:cover;object-position:center;
  border-radius:14px;
  -webkit-user-drag:none;user-select:none;
}

/* 「拖动封面翻页」提示：叠在封面底部，淡入淡出，不占布局高度 */
.pc-scroll{
  position:absolute;z-index:5;left:0;right:0;bottom:0;
  margin:0;padding:22px 8px 8px;
  border-radius:0 0 12px 12px;
  background:linear-gradient(180deg,transparent,rgba(20,16,17,.55));
  color:#fff;font-size:10.5px;text-align:center;
  opacity:0;transition:opacity .35s ease;
  pointer-events:none;
}
.page-card:hover .pc-scroll,
.pc-viewport:focus-visible .pc-scroll{opacity:1}
@media (hover:none){
  .pc-scroll{opacity:.9}
}

/* 序号 / 作品名 / 类型：和参考站一样紧凑，行距贴紧 */
.pc-index{
  margin:11px 0 0;
  color:var(--muted);
  font-size:10.5px;font-weight:600;letter-spacing:.04em;
  font-variant-numeric:tabular-nums;
}
.pc-title{
  display:flex;align-items:center;gap:4px;
  margin-top:2px;
  font-size:15px;font-weight:700;letter-spacing:-.02em;line-height:1.3;
  transition:color .2s ease;
}
.pc-title .ic{font-size:13px;color:var(--muted);transition:transform .25s var(--ease),color .2s ease}
.pc-title:hover{color:var(--accent-ink)}
.pc-title:hover .ic{transform:translate(2px,-2px);color:var(--accent)}
.pc-meta{
  margin:1px 0 0;
  color:var(--muted);font-size:11.5px;line-height:1.5;
}

/* 卡脚：圆点 + 上下切换按钮 */
.pc-foot{
  display:flex;align-items:center;gap:8px;
  margin-top:12px;
}
.pc-dots{display:flex;gap:5px}
.pc-dot{
  width:6px;height:6px;padding:0;border-radius:50%;
  border:0;background:var(--line);
  transition:background .25s ease,width .25s var(--ease);
}
.pc-dot:hover{background:var(--accent-line)}
.pc-dot.is-active{width:14px;border-radius:3px;background:var(--accent)}

.pc-nav{display:flex;gap:4px;margin-left:auto}
.pc-arrow{
  display:grid;place-items:center;
  width:26px;height:26px;border-radius:8px;
  border:1px solid var(--line);background:var(--surface-2);
  color:var(--ink-2);font-size:14px;
  transition:border-color .2s ease,color .2s ease,opacity .2s ease;
}
.pc-arrow:hover{border-color:var(--accent);color:var(--accent-ink)}
/* 两个按钮都是「下」字形，前一个转 180° 变成「上」，
   省一个图标，也保证两个箭头粗细完全一致 */
#collagePrev .ic{transform:rotate(180deg)}
.pc-nav[data-end="start"] #collagePrev,
.pc-nav[data-end="end"] #collageNext{opacity:.3}

@media (max-width:900px){
  .collage-row{gap:16px}
}

/* 减少动效：翻页不做位移过渡，直接换页 */
@media (prefers-reduced-motion:reduce){
  .pc-page,.pc-scroll{transition:none}
}
/* 区块收尾：一行说明 + Astrobox 官网入口 */
.works-note{
  margin:24px 0 0;
  color:var(--muted);font-size:13px;line-height:1.85;
}
.works-note a{
  display:inline-flex;align-items:center;gap:4px;margin-left:4px;
  color:var(--accent-ink);font-weight:700;
  border-bottom:1px solid var(--accent-line);padding-bottom:1px;
  transition:color .22s ease,border-color .22s ease;
}
.works-note a .ic{font-size:13px;transition:transform .25s var(--ease)}
.works-note a:hover{color:var(--accent);border-color:var(--accent)}
.works-note a:hover .ic{transform:translate(2px,-2px)}

/* 紧凑行卡（未来项目 / 资源 / 在线工具）：一行一条，比整块卡片轻。
   .row-stack 是它们的容器 —— 之前只靠 HTML 上的内联 style 撑着，
   现在收进样式表，避免内联样式和类名两套真相。 */
.row-stack{display:grid;gap:12px;margin-top:20px}
.row-card{
  position:relative;display:flex;align-items:center;gap:16px;
  padding:20px 22px;border-radius:var(--r-m);
  border:1px solid var(--line);background:var(--surface);
  box-shadow:inset 0 1px 0 var(--hi-soft),var(--elev-1);
  transition:border-color .25s ease,box-shadow .34s var(--ease),transform .25s var(--ease);
}
.row-card:hover{border-color:var(--accent-line);box-shadow:inset 0 1px 0 var(--hi),var(--elev-2);transform:translateY(-2px)}
.row-card .row-icon{
  display:grid;place-items:center;flex:none;
  width:46px;height:46px;border-radius:12px;
  border:1px solid var(--line);background:var(--surface-2);
  font-size:23px;line-height:1;color:var(--accent-ink);
  transition:transform .3s var(--spring);
}
.row-card:hover .row-icon{transform:scale(1.06)}
.row-body{display:flex;flex-direction:column;min-width:0;flex:1}
.row-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.row-head strong{font-size:16px;font-weight:700;letter-spacing:-.015em}
.row-body small{margin-top:7px;color:var(--muted);font-size:13.5px;line-height:1.75}
/* 行卡说明里的行内代码（例如导出的文件名），别用浏览器默认的等宽大写 */
.row-body small code{
  font-family:var(--mono);font-size:.92em;
  padding:1px 5px;border-radius:5px;
  background:var(--surface-2);border:1px solid var(--line-2);
  color:var(--ink-2);white-space:nowrap;
}
.row-go{flex:none;color:var(--muted);font-size:16px;transition:transform .28s var(--ease),color .22s ease}
.row-card:hover .row-go{transform:translate(3px,-3px);color:var(--accent)}

/* ---------- 状态徽标 ---------------------------------------------------- */

.state{
  display:inline-flex;align-items:center;gap:6px;
  padding:5px 11px;border-radius:var(--r-s);
  font-size:11.5px;font-weight:700;letter-spacing:.02em;
  border:1px solid var(--line);background:var(--surface-2);color:var(--ink-2);
}
.state::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.state[data-tone="live"]{border-color:var(--accent-line);background:var(--accent-soft);color:var(--accent-ink)}
.state[data-tone="wip"]{border-color:color-mix(in srgb,var(--teal) 34%,transparent);background:var(--teal-soft);color:var(--teal)}
.state[data-tone="quiet"]{border-color:var(--line);background:var(--surface-2);color:var(--muted)}
.state[data-tone="warn"]{border-color:color-mix(in srgb,var(--amber) 34%,transparent);background:var(--amber-soft);color:var(--amber)}
.state[data-tone="plan"]{border-color:var(--accent-line);background:var(--accent-soft);color:var(--accent-ink)}

/* ---------- 卡片网格（快速链接） --------------------------------------- */

/* 快速链接：删掉爱发电后剩两张卡，用两列铺满整行；
   三列会让它们各自缩到 1/3 宽、右边空出一格。
   ≤820px 与 ≤560px 两条断点会再把它压成两列 / 单列。 */
.bento{position:relative;z-index:1;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
.bcard{
  position:relative;display:flex;flex-direction:column;
  padding:24px 22px;border-radius:var(--r-m);
  border:1px solid var(--line);background:var(--surface);
  box-shadow:inset 0 1px 0 var(--hi-soft),var(--elev-1);
  overflow:hidden;
  transition:border-color .28s ease,box-shadow .34s var(--ease),transform .28s var(--ease);
}
.bcard:hover{border-color:var(--accent-line);box-shadow:inset 0 1px 0 var(--hi),var(--elev-2);transform:translateY(-4px)}
.bcard-icon{
  display:grid;place-items:center;
  width:42px;height:42px;border-radius:12px;
  background:var(--accent-soft);color:var(--accent-ink);
  font-size:20px;
  transition:transform .34s var(--spring),box-shadow .34s var(--ease);
}
.bcard:hover .bcard-icon{transform:scale(1.06);box-shadow:0 6px 16px -8px color-mix(in srgb,var(--accent) 60%,transparent)}
.bcard h3{margin:18px 0 0;font-size:16.5px;font-weight:700;letter-spacing:-.015em}
.bcard p{margin:9px 0 0;color:var(--muted);font-size:13.5px;line-height:1.78}
.bcard .card-link{margin-top:18px;align-self:flex-start}
.bcard[data-brand="github"] .bcard-icon{background:color-mix(in srgb,var(--brand-github) 10%,transparent);color:var(--brand-github)}
.bcard[data-brand="afdian"] .bcard-icon{background:color-mix(in srgb,var(--brand-afdian) 12%,transparent);color:var(--brand-afdian)}
.bcard[data-brand="mcbbs"] .bcard-icon{background:var(--amber-soft);color:var(--amber)}

/* ---------- 更新行 ------------------------------------------------------ */

.update-list{position:relative;z-index:1;display:grid;gap:10px}
.update-row{
  display:grid;grid-template-columns:112px 1fr 1.15fr auto;gap:20px;align-items:center;
  padding:22px 24px;border-radius:var(--r-m);
  border:1px solid var(--line);background:var(--surface);
  box-shadow:inset 0 1px 0 var(--hi-soft),var(--elev-1);
  transition:border-color .25s ease,box-shadow .34s var(--ease),transform .25s var(--ease);
}
a.update-row:hover{border-color:var(--accent-line);box-shadow:inset 0 1px 0 var(--hi),var(--elev-2);transform:translateY(-2px)}
.update-state{justify-self:start}
.update-row strong{font-size:15.5px;font-weight:700;letter-spacing:-.015em}
.update-row > span:last-child{color:var(--muted);font-size:14px}
.update-arrow{color:var(--muted);font-size:16px;transition:transform .28s var(--ease),color .22s ease}
a.update-row:hover .update-arrow{transform:translate(3px,-3px);color:var(--accent)}
.update-row.plain{grid-template-columns:112px 1fr 1.15fr}

/* ---------- 问答 -------------------------------------------------------- */

.faq-list{position:relative;z-index:1;display:grid;gap:8px;max-width:820px}
.faq-item{
  position:relative;
  border-radius:var(--r-s);border:1px solid var(--line);background:var(--surface);
  overflow:hidden;
  transition:border-color .25s ease,box-shadow .25s ease;
}
.faq-item:hover{border-color:var(--accent-line);box-shadow:var(--shadow-1)}
.faq-item.open{border-color:var(--accent-line);box-shadow:var(--shadow-1)}
.faq-q{
  display:flex;align-items:center;justify-content:space-between;gap:20px;
  width:100%;padding:19px 22px;text-align:start;
  font-size:15.5px;font-weight:500;
}
.faq-q i{position:relative;flex:none;width:16px;height:16px}
.faq-q i::before,.faq-q i::after{
  content:"";position:absolute;top:50%;left:0;width:100%;height:1.6px;border-radius:2px;
  background:var(--accent);transition:transform .3s var(--ease);
}
.faq-q i::after{transform:rotate(90deg)}
.faq-item.open .faq-q i::after{transform:rotate(0)}
.faq-a{display:grid;grid-template-rows:0fr;transition:grid-template-rows .35s var(--ease)}
.faq-item.open .faq-a{grid-template-rows:1fr}
.faq-a > div{overflow:hidden}
.faq-a p{padding:0 22px 20px;color:var(--muted);font-size:14px;line-height:1.85}
.faq-a p a{
  display:inline-block;margin-left:4px;
  color:var(--accent-ink);font-weight:700;
  border-bottom:1px solid var(--accent-line);
  transition:color .22s ease,border-color .22s ease;
}
.faq-a p a:hover{color:var(--accent);border-color:var(--accent)}

/* ---------- 预告横幅（通栏长条 · 圆角）----------------------------------
   横贯视口的一条玻璃长条，贴在顶栏下方。整块不可点击（只有右侧 ✕ 可关）。

   位置：顶栏本身是 position:fixed，横幅贴到 top:0 会把它盖住，
   所以从「顶栏高度 + 一点间隙」开始。

   宽度与圆角：左右各留 20px（和站内 .shell 的侧边距一致），四角用 --r-m。
   这 20px 不是装饰 —— 圆角如果紧贴屏幕边缘，视觉上会被裁掉、看不出是圆角，
   必须留出缝隙它才成立。也因此宽度是 left:20px / right:20px 而不是 0，
   且内容层用 100% 而不是 100% - 40px（外边距已经在容器上了，别减两次）。

   文字居中而不是左对齐：长条形态下左对齐会让右侧空出一大片。

   材质：用顶栏那档最透的令牌（glass-tint-bar），不是面板档的 strong ——
   横贯整屏的玻璃面积很大，用 78% 的面板档会糊成一条实心色带。 */
.ginka-banner{
  position:fixed;z-index:45;              /* 顶栏是 50，横幅压在它之下 */
  left:20px;right:20px;
  top:calc(64px + 10px + env(safe-area-inset-top, 0px));
  border-radius:var(--r-m);
  border:1px solid var(--glass-rim);
  background-color:var(--glass-tint-bar);
  background-image:var(--glass-sheen);
  backdrop-filter:var(--fx-glass-14);
  -webkit-backdrop-filter:var(--fx-glass-14);
  box-shadow:inset 0 1px 0 var(--glass-hi-soft), 0 10px 28px -22px rgba(26,21,23,.5);
  animation:ginkaIn .42s var(--ease) both;
}
@keyframes ginkaIn{
  from{opacity:0;transform:translateY(-10px)}
  to{opacity:1;transform:translateY(0)}
}
.ginka-inner{
  width:min(var(--shell),100%);
  margin-inline:auto;
  display:flex;align-items:center;justify-content:center;gap:12px;
  min-height:46px;padding:9px 16px;
  font-size:13.5px;line-height:1.6;color:var(--ink-2);
  text-align:center;
}
.ginka-banner .ginka-tag{
  flex:none;padding:3px 10px;border-radius:999px;
  background:var(--accent);color:var(--accent-fg);
  font-size:11.5px;font-weight:700;letter-spacing:.02em;
}
.ginka-banner .ginka-text{min-width:0}
.ginka-banner strong{color:var(--ink);font-weight:700}
.ginka-close{
  flex:none;display:grid;place-items:center;
  width:30px;height:30px;border-radius:50%;
  color:var(--muted);
  transition:background .22s ease,color .22s ease;
}
.ginka-close:hover{background:var(--surface-2);color:var(--ink)}
.ginka-close .ic{font-size:15px}

/* 窄屏：压扁。
   原来的写法是 flex-wrap 折行 —— 标签独占一行、文字再占两行，整条约 92px 高，
   横跨屏幕却比顶栏还厚。现在改成**不折行**：标签缩成小胶囊贴在第一行左侧，
   文字最多三行（line-clamp 兜底，永远不会把横幅撑高），关闭按钮垂直居中。
   实测高度从约 92px 降到约 54px（两行文字时）。
   左对齐而不是居中：两行以上的文字居中会让每行右端参差，看起来更碎。 */
@media (max-width:560px){
  .ginka-banner{left:10px;right:10px;border-radius:12px}
  .ginka-inner{
    flex-wrap:nowrap;align-items:flex-start;justify-content:flex-start;
    gap:8px;padding:8px 10px;
    min-height:0;
    font-size:12px;line-height:1.45;
    text-align:start;
  }
  .ginka-banner .ginka-tag{
    padding:2px 7px;font-size:10px;line-height:1.5;
    margin-top:1px;             /* 与文字首行视觉对齐 */
  }
  .ginka-banner .ginka-text{
    /* 最多三行；超出用省略号。宁可截断也不要让横幅一层层长高 */
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;
    line-clamp:3;
    overflow:hidden;
  }
  .ginka-close{width:24px;height:24px;margin-left:auto;align-self:center}
  .ginka-close .ic{font-size:13px}
}
@media (prefers-reduced-motion:reduce){
  .ginka-banner{animation:none}
}

/* 横幅占着顶栏下面那一带，首屏文字会顶上它。
   用 :has() 让首屏在有横幅时自动多让出一块 —— 横幅关掉（被 JS 移出 DOM）后
   这条选择器自然不再匹配，间距自动收回，不需要 JS 干预。
   高度核算：横条 min-height 46px，从 64px 起 → 占到 110px；
   文字若折成两行约到 131px。所以桌面留 168px（余 37px），
   窄屏横条会折行（标签 + 文字 + 关闭按钮），留 156px。
   代价是关闭横幅时首屏高度会变一次，但首屏本来就是整屏高，察觉不到。 */
html:has(#ginkaBanner) .hero{padding-top:168px}
@media (max-width:900px){
  html:has(#ginkaBanner) .hero{padding-top:156px}
}

/* ---------- 语言切换 ----------------------------------------------------
   顶栏里一枚地球图标 + 当前语言的一个字（中 / EN / 日）。
   为什么不做成三个并排链接：顶栏宽度已经很紧 —— 手机 375px 下只剩几十像素
   余量（见顶栏那段宽度预算），三坨文字塞进去必然挤坏。
   弹层挂在顶栏容器里，绝对定位到按钮正下方。 */
.lang-toggle{
  display:flex;align-items:center;gap:5px;flex:none;
  height:34px;padding:0 9px;border-radius:9px;
  border:1px solid transparent;
  background:color-mix(in srgb, var(--surface) 16%, transparent);
  backdrop-filter:var(--fx-glass-8);
  -webkit-backdrop-filter:var(--fx-glass-8);
  box-shadow:inset 0 1px 0 var(--glass-hi-soft);
  color:var(--ink-2);
  transition:border-color .22s ease,color .22s ease,background .22s ease;
}
.lang-toggle:hover{border-color:var(--accent);color:var(--accent-ink)}
.lang-toggle .ic{font-size:15px}
.lang-code{font-size:11.5px;font-weight:700;letter-spacing:.02em;line-height:1}

/* ---------- 主色主题切换 ------------------------------------------------
   顶栏一枚调色板按钮 + 一个色板浮层。样式与语言切换器保持同一套
   （同高、同圆角、同玻璃底），因为它们是同一类「设置」控件。 */
.accent-toggle{
  display:flex;align-items:center;justify-content:center;flex:none;
  width:34px;height:34px;border-radius:9px;
  border:1px solid transparent;
  background:color-mix(in srgb, var(--surface) 16%, transparent);
  backdrop-filter:var(--fx-glass-8);
  -webkit-backdrop-filter:var(--fx-glass-8);
  box-shadow:inset 0 1px 0 var(--glass-hi-soft);
  color:var(--ink-2);
  transition:border-color .22s ease,color .22s ease,background .22s ease;
}
.accent-toggle:hover{border-color:var(--accent);color:var(--accent-ink)}
.accent-toggle .ic{font-size:16px}
/* 按钮右下角点一枚当前主色的小圆点，不打开浮层也能看出当前主题 */
.accent-toggle::after{
  content:"";position:absolute;right:5px;bottom:5px;
  width:7px;height:7px;border-radius:50%;
  background:var(--accent);
  box-shadow:0 0 0 1.5px var(--surface);
}
.accent-toggle{position:relative}

/* ---------- 主色调色盘 --------------------------------------------------
   面板 = 「标题行（当前色名）+ 4×2 色珠」。比一排纯色圆点更像调色盘：
     · 色珠带顶部高光（radial-gradient）与内描边，像一滴颜料而不是色块
     · 悬停上浮 2px，按下微缩，给触觉反馈
     · 选中态是「双层描边环 + 对勾」，不只靠颜色 —— 八个圆点里认当前项
       必须有不依赖色觉的线索
     · 打开时色珠错落入场（--i 由 nth-child 给延迟），比整块弹出轻快
   面板本身沿用玻璃令牌，和语言浮层是同一族材质。 */
.accent-menu{
  position:absolute;z-index:60;
  top:calc(100% + 8px);right:20px;
  width:238px;                    /* 固定宽度：色相条需要足够的拖动行程 */
  padding:13px 14px 15px;
  /* 展开取色器后面板会变高，矮屏幕上要能滚，别顶出视口 */
  max-height:calc(100vh - 150px);
  overflow-y:auto;
  overscroll-behavior:contain;
  border-radius:var(--r-m);
  border:1px solid var(--glass-rim);
  background-color:var(--glass-tint-strong);
  backdrop-filter:var(--fx-glass-14);
  -webkit-backdrop-filter:var(--fx-glass-14);
  box-shadow:inset 0 1px 0 var(--glass-hi-soft), var(--elev-2);
}
.accent-menu[hidden]{display:none}

.accent-menu-head{
  display:flex;align-items:center;justify-content:space-between;
  flex-wrap:wrap;row-gap:2px;
  gap:14px;margin:0 1px 12px;
  font-size:11.5px;color:var(--muted);letter-spacing:.01em;
}
.accent-menu-head strong{
  color:var(--ink);font-size:12px;font-weight:700;
  /* 主题配色的色名可能较长（White night sand、رمل الليلة البيضاء），
     宽容不下时让它整体换到下一行，而不是挤出面板。 */
  min-width:0;text-align:end;overflow-wrap:break-word;
  /* 当前色名右侧点一枚同色小圆，名字与颜色一起确认 */
  display:inline-flex;align-items:center;gap:6px;
}
.accent-menu-head strong::after{
  content:"";width:7px;height:7px;border-radius:50%;
  background:var(--accent);
  box-shadow:0 0 0 1px color-mix(in srgb, var(--ink) 22%, transparent);
}

/* 面板固定 238px 宽后，grid 的单元格会比色珠宽 —— 让色珠居中，
   于是 8 个色珠在更宽的画布上均匀铺开，比挤在 166px 里更好看也更好点 */
.accent-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;justify-items:center}
/* 「主题配色」分组：与上面的通用主色隔一道细线，
   否则 18 个圆点摆在一起分不清哪些是什么。 */
.accent-sect{margin-top:13px;padding-top:11px;border-top:1px solid var(--line)}
.accent-sect-title{
  margin:0 1px 9px;
  font-size:10.5px;font-weight:600;letter-spacing:.04em;
  color:var(--muted);text-transform:uppercase;
}
/* 主题配色列表：每行一个色，左边色点、中间色名、右边作品简称。
   用列表而不用圆点网格，是因为 238px 的面板里六个纯圆点根本看不出各自出自哪部作品。 */
.accent-proj-list{display:grid;gap:1px;margin-top:2px}
.accent-proj{
  display:flex;align-items:center;gap:8px;
  width:100%;padding:6px 7px;border-radius:8px;
  text-align:start;
  transition:background .18s ease;
}
.accent-proj:hover{background:var(--surface-2)}
.accent-proj[aria-checked="true"]{background:color-mix(in srgb, var(--accent) 12%, transparent)}
.accent-proj[aria-checked="true"] .pj-nm{color:var(--accent-ink)}
.accent-proj[aria-checked="true"] .pj-dot{box-shadow:0 0 0 1.5px var(--surface),0 0 0 3px var(--accent)}
.accent-proj:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.pj-dot{
  flex:none;width:16px;height:16px;border-radius:5px;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.12);
}
/* 色点的身份色与色块一致 */
.accent-proj[data-accent="tiny"] .pj-dot{background:#568f2e}
.accent-proj[data-accent="galgod"] .pj-dot{background:#6a44c9}
.accent-proj[data-accent="eternity"] .pj-dot{background:#2b64ab}
.accent-proj[data-accent="huangmeic"] .pj-dot{background:#9c642c}
.accent-proj[data-accent="whitenight"] .pj-dot{background:#96825a}
.accent-proj[data-accent="blueplanet"] .pj-dot{background:#1b8ab2}
.accent-proj[data-accent="catgirl"] .pj-dot{background:#b247aa}
.accent-proj[data-accent="qianse"] .pj-dot{background:#a34431}
.pj-nm{font-size:11.5px;font-weight:600;color:var(--ink);flex:none}
.pj-src{
  margin-inline-start:auto;min-width:0;
  font-size:10.5px;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* 色珠 */
.accent-swatch{
  position:relative;display:grid;place-items:center;
  width:34px;height:34px;border-radius:50%;
  border:1px solid rgba(0,0,0,.14);
  /* 顶部偏左的高光 + 底部的轻微暗边，做成球面观感 */
  background-image:
    radial-gradient(circle at 33% 26%, rgba(255,255,255,.55) 0%, rgba(255,255,255,0) 58%),
    linear-gradient(180deg, rgba(255,255,255,.16), rgba(0,0,0,.10));
  box-shadow:inset 0 1px 1px rgba(255,255,255,.42), 0 1px 2px rgba(0,0,0,.14);
  transition:transform .2s var(--ease),box-shadow .2s ease;
  animation:swIn .34s var(--ease) both;
  animation-delay:calc(var(--i,0) * 26ms);
}
@keyframes swIn{
  from{opacity:0;transform:translateY(-4px) scale(.88)}
  to{opacity:1;transform:translateY(0) scale(1)}
}
.accent-swatch:hover{transform:translateY(-2px) scale(1.06);box-shadow:inset 0 1px 1px rgba(255,255,255,.5), 0 4px 10px -3px rgba(0,0,0,.3)}
.accent-swatch:active{transform:translateY(0) scale(.96)}
/* 选中态：内圈留出面板底色、外圈用**主色**收边。
   早先用的是墨色（--ink），在浅色面板上就是一圈粗黑框，看着像把圆点框住了；
   换成主色细环后既轻，也顺便强化了「这就是当前主题色」。 */
.accent-swatch[aria-checked="true"]{
  box-shadow:
    0 0 0 2px var(--glass-tint-strong),
    0 0 0 3.5px var(--accent),
    inset 0 1px 1px rgba(255,255,255,.42);
}
/* 对勾：只给选中项显示。白色在所有八种主色上都够对比（最浅的琥珀也有 5:1） */
.sw-check{
  width:14px;height:14px;flex:none;
  color:#fff;opacity:0;
  filter:drop-shadow(0 1px 2px rgba(0,0,0,.42));
  transition:opacity .18s ease,transform .2s var(--ease);
  transform:scale(.7);
}
.accent-swatch[aria-checked="true"] .sw-check{opacity:1;transform:scale(1)}

/* 八种主色的身份色。用固定色而不是 var(--accent)：
   色板要能认出「这是哪个主题」，它本身不该随当前主题变形。 */
.accent-swatch[data-accent="blue"]{background-color:#2563eb}
.accent-swatch[data-accent="violet"]{background-color:#7c3aed}
.accent-swatch[data-accent="teal"]{background-color:#0b7d7d}
.accent-swatch[data-accent="emerald"]{background-color:#0f7a4d}
.accent-swatch[data-accent="amber"]{background-color:#c9791f}
.accent-swatch[data-accent="rose"]{background-color:#b04a61}
.accent-swatch[data-accent="magenta"]{background-color:#b81f8a}
.accent-swatch[data-accent="graphite"]{background-color:#3f4652}
.accent-swatch[data-accent="sky"]{background-color:#0369a1}
.accent-swatch[data-accent="indigo"]{background-color:#4f46e5}
.accent-swatch[data-accent="olive"]{background-color:#5f7a1f}
.accent-swatch[data-accent="coral"]{background-color:#c03a2d}
/* 主题配色的色块用各自封面提取的原色 */
.accent-swatch[data-accent="tiny"]{background-color:#568f2e}
.accent-swatch[data-accent="galgod"]{background-color:#6a44c9}
.accent-swatch[data-accent="eternity"]{background-color:#2b64ab}
.accent-swatch[data-accent="huangmeic"]{background-color:#9c642c}
.accent-swatch[data-accent="whitenight"]{background-color:#96825a}
.accent-swatch[data-accent="blueplanet"]{background-color:#1b8ab2}
.accent-swatch[data-accent="catgirl"]{background-color:#b247aa}
.accent-swatch[data-accent="qianse"]{background-color:#a34431}

/* ---------- 自由取色（网页内嵌取色器）------------------------------------
   为什么不用 <input type="color">：它弹出的是**操作系统**的取色对话框
   （Windows 上是一整块方形 HSV 面板 + RGB 数字框），方角、深灰、和本站的
   暖纸 / 玻璃语言完全冲突，观感上像另一个软件插进来。

   所以自己实现一套，只保留三件必要的东西：
     1. 饱和度 × 明度面板（二维渐变 + 圆形取色点）
     2. 色相条（白圈旋钮）
     3. 十六进制输入框（想要精确色号时直接敲）
   全部沿用本站的圆角、发丝边框、内高光与阴影层级。 */
.accent-custom{
  margin-top:13px;padding-top:12px;
  border-top:1px solid var(--line);
}

/* 色卡：整行可点，点一下展开/收起取色器 */
.accent-custom-pick{
  position:relative;display:flex;align-items:center;gap:10px;width:100%;
  padding:8px 11px 8px 9px;
  border-radius:14px;                       /* iOS 那种大圆角卡片 */
  border:1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  background:linear-gradient(180deg,
    color-mix(in srgb, var(--surface) 92%, transparent),
    color-mix(in srgb, var(--surface-2) 92%, transparent));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent),
    0 1px 2px rgba(0,0,0,.06);
  cursor:pointer;text-align:start;
  transition:border-color .2s ease,box-shadow .2s ease,transform .16s var(--ease);
}
.accent-custom-pick:hover{
  border-color:color-mix(in srgb, var(--accent) 46%, transparent);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent),
    0 3px 10px -4px rgba(0,0,0,.22);
}
.accent-custom-pick:active{transform:scale(.985)}
.accent-custom-pick[aria-expanded="true"]{
  border-color:color-mix(in srgb, var(--accent) 60%, transparent);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent),
    0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);
}

/* squircle 色块：用 border-radius 约 30% 模拟 iOS 连续圆角 */
.accent-custom-face{
  position:relative;flex:none;
  width:30px;height:30px;border-radius:9px;
  display:grid;place-items:center;
  /* 未启用自定义色时显示彩虹，一眼看出「这里能自由取色」 */
  background-image:conic-gradient(from 210deg,
    #ff5f57,#ffbd2e,#28c840,#22c1d6,#5b8cff,#a855f7,#ff5f57);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.35),
    inset 0 1px 1px rgba(255,255,255,.45),
    0 1px 2px rgba(0,0,0,.16);
  transition:transform .2s var(--ease),box-shadow .2s ease;
}
.accent-custom-pick:hover .accent-custom-face{transform:scale(1.05)}

.accent-custom-label{font-size:12px;color:var(--ink-2);flex:none;font-weight:500}
.accent-custom-hex{
  margin-left:auto;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:11px;letter-spacing:.04em;color:var(--muted);
  text-transform:uppercase;
  font-variant-numeric:tabular-nums;   /* 数字等宽，换色时文字不抖 */
}

/* 启用自定义色后：色块换成该颜色，边框染上主色，出现对勾 */
.accent-custom.is-active .accent-custom-pick{
  border-color:color-mix(in srgb, var(--accent) 52%, transparent);
}
.accent-custom.is-active .accent-custom-face,
.mobile-menu-accent.is-active .accent-custom-pick .accent-custom-face{
  background-image:none;
  background-color:var(--accent);
  background-image:radial-gradient(circle at 32% 26%, rgba(255,255,255,.5) 0%, rgba(255,255,255,0) 60%);
}
.accent-custom.is-active .accent-custom-face .sw-check,
.mobile-menu-accent.is-active .accent-custom-pick .sw-check{
  opacity:1;transform:scale(1);
}
.accent-custom-pick:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ---- 展开后的取色器 ---- */
.accent-picker{display:grid;gap:10px;margin-top:10px}
.accent-picker[hidden]{display:none}
/* 被挪进手机菜单时，与菜单其它行保持同样的左右边距 */
.accent-picker.is-in-menu{margin:0 13px 14px}

/* 饱和度（横）× 明度（纵）面板。
   两层渐变叠加：白→纯色相（横向），透明→黑（纵向）。 */
.accent-sv{
  position:relative;height:132px;
  border-radius:12px;
  background-image:
    linear-gradient(to top, #000 0%, rgba(0,0,0,0) 100%),
    linear-gradient(to right, #fff 0%, hsl(var(--h, 221) 100% 50%) 100%);
  box-shadow:
    inset 0 0 0 1px rgba(0,0,0,.14),
    inset 0 1px 2px rgba(0,0,0,.10);
  cursor:crosshair;
  touch-action:none;          /* 拖动时不要触发页面滚动 */
}
.accent-sv-knob{
  position:absolute;
  /* 内缩 8px（圆点半径）再按比例定位：否则拖到最右/最下时圆点会有一半
     溢出面板边界，压在边框上很难看。这样圆点始终完整落在面板内。 */
  left:calc(8px + var(--s, 0.83) * (100% - 16px));
  top:calc(8px + (1 - var(--v, 0.92)) * (100% - 16px));
  width:16px;height:16px;margin:-8px 0 0 -8px;
  border-radius:50%;
  border:2px solid #fff;
  background:var(--accent);
  box-shadow:0 1px 4px rgba(0,0,0,.45),0 0 0 .5px rgba(0,0,0,.22);
  pointer-events:none;
}
.accent-sv:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* ---- 色相条 ----
   轨道是七段色相渐变 + 内阴影做成凹槽感；旋钮白圈 + 阴影，
   位置由 --hue 驱动（JS 写 0~1 的比值）。 */
.accent-hue{
  position:relative;
  height:26px;
  border-radius:999px;
  cursor:pointer;
  touch-action:none;
}
.accent-hue-track{
  position:absolute;inset:0;border-radius:inherit;
  background:linear-gradient(90deg,
    #ff3b30 0%,#ffcc00 16.6%,#34c759 33.3%,
    #32ade6 50%,#5b8cff 66.6%,#af52de 83.3%,#ff3b30 100%);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.28),
    inset 0 2px 4px rgba(0,0,0,.18),
    0 1px 2px rgba(0,0,0,.10);
}
.accent-hue-knob{
  position:absolute;top:50%;
  left:calc(var(--hue,0.61) * 100%);
  width:22px;height:22px;
  margin-top:-11px;margin-left:-11px;   /* 以自身中心对齐 */
  border-radius:50%;
  border:2.5px solid #fff;
  background:var(--accent);
  box-shadow:0 1px 4px rgba(0,0,0,.34),0 0 0 .5px rgba(0,0,0,.14);
  transition:transform .15s var(--ease);
  pointer-events:none;
}
.accent-hue:hover .accent-hue-knob{transform:scale(1.12)}
.accent-hue:active .accent-hue-knob{transform:scale(1.2)}
.accent-hue:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:999px}

/* ---- 十六进制输入 ---- */
.accent-hex-field{
  display:flex;align-items:center;gap:5px;
  padding:8px 11px;border-radius:11px;
  border:1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  background:color-mix(in srgb, var(--surface-2) 80%, transparent);
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:11.5px;color:var(--muted);
  transition:border-color .2s ease;
}
.accent-hex-field:focus-within{border-color:color-mix(in srgb, var(--accent) 55%, transparent)}
.accent-hex-input{
  flex:1;min-width:0;
  border:0;background:none;outline:none;
  font:inherit;font-size:12px;letter-spacing:.08em;
  color:var(--ink);text-transform:uppercase;
}
.accent-hex-input::placeholder{color:var(--muted);text-transform:none;letter-spacing:0}

.lang-menu{
  position:absolute;z-index:60;
  top:calc(100% + 8px);right:20px;
  min-width:132px;padding:6px;
  border-radius:var(--r-s);
  border:1px solid var(--glass-rim);
  background-color:var(--glass-tint-strong);
  backdrop-filter:var(--fx-glass-14);
  -webkit-backdrop-filter:var(--fx-glass-14);
  box-shadow:inset 0 1px 0 var(--glass-hi-soft), var(--elev-2);
  display:grid;gap:2px;
}
.lang-menu[hidden]{display:none}
.lang-menu button{
  text-align:start;padding:9px 11px;border-radius:7px;
  font-size:13.5px;color:var(--ink-2);
  transition:background .18s ease,color .18s ease;
}
.lang-menu button:hover{background:var(--surface-2);color:var(--ink)}
/* 当前语言：左边一条主色竖线 + 加粗，不靠颜色单独表达（色盲可辨） */
.lang-menu button[aria-checked="true"]{
  color:var(--accent-ink);font-weight:700;
  box-shadow:inset 2px 0 0 var(--accent);
}

/* 手机：把语言与主色按钮都收进菜单（顶栏放不下），桌面隐藏菜单里那两行 */
.mobile-menu-lang,
.mobile-menu-accent{display:none}
@media (max-width:820px){
  .lang-toggle{display:none}
  .lang-menu{display:none}
  .accent-toggle{display:none}
  .accent-menu{display:none}
  /* 7 种语言排成 3 列（3+3+1）。
     为何不用 4 列：320px 屏下格宽只有约 55px，
     "English" 在 13px 下就要 66px（含内边距），会撞出格子。
     3 列每格约 93px，最长的词也放得下。 */
  .mobile-menu-lang{
    display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
    gap:6px;margin:0 13px 10px;
    padding:9px 0;border-bottom:1px solid var(--line);
  }
  /* 菜单里的主色选择：12 个预置色 + 1 个自由取色，共 13 颗。
     容器是块级，里面再套一个 7 列 grid —— 这样 grid 下面还能放「颜色名条」。
     用 grid 而不是 flex-wrap：换行位置可预测（7 + 6），
     也不会因为某一颗尺寸不一致而挤出奇怪的排布。 */
  .mobile-menu-accent{
    display:block;
    margin:0 13px 12px;
    padding:0 0 11px;border-bottom:1px solid var(--line);
  }
  .mobile-accent-grid{
    display:grid;grid-template-columns:repeat(7,minmax(0,1fr));
    gap:8px;align-items:center;justify-items:center;
  }
  /* 手机端调色盘分组：与桌面面板同一套逻辑（主色 / 主题配色）。
     桌面是 4 列圆点 + 带作品名的列表；手机横向空间有限，
     用「小标题 + 7 列圆点」两段表示，避免 19 颗珠子混在一起分不清来源。 */
  .m-accent-group + .m-accent-group{margin-top:13px}
  .m-accent-label{
    margin:0 0 8px 1px;
    font-size:10.5px;font-weight:600;letter-spacing:.04em;
    color:var(--muted);text-transform:uppercase;
  }
  /* 颜色名条：细长圆角条，横贯色珠区下方，文字居中。
     左边一枚当前主色的小圆点 —— 让「名字」和「颜色」能对上，
     不必靠记住哪个中文名对应哪种色。
     用整行宽而不是包住文字：包文字会变成小药丸，文字一长一短宽度就跳；
     定宽条在切换颜色时只换字，形不变。 */
  .mobile-accent-name{
    display:flex;align-items:center;justify-content:center;
    flex-wrap:wrap;gap:6px;
    margin:10px 0 0;
    padding:5px 10px;
    border-radius:9px;
    background:color-mix(in srgb, var(--accent) 10%, transparent);
    border:1px solid color-mix(in srgb, var(--accent) 24%, transparent);
    color:var(--accent-ink);
    font-size:11px;font-weight:600;letter-spacing:.02em;
    line-height:1.25;
    transition:background .25s ease,border-color .25s ease,color .25s ease;
  }
  .mobile-accent-name::before{
    content:"";flex:none;
    width:7px;height:7px;border-radius:50%;
    background:var(--accent);
    box-shadow:inset 0 0 0 1px rgba(255,255,255,.35);
  }
  .mobile-menu-accent .accent-swatch{width:22px;height:22px;animation:none}
  .mobile-menu-accent .sw-check{width:11px;height:11px}
  /* 第 13 颗：自由取色。
     必须把桌面「整行色卡」的样式清干净 —— 那条规则带着 width:100%、
     8/11px 内边距和浅色卡片底，套到 22px 的迷你元素上会把彩虹色块挤歪，
     还会多出一个白色方框（就是手机上看到的白圈）。 */
  .mobile-menu-accent .accent-custom-pick.is-mini{
    width:22px;height:22px;padding:0;gap:0;
    border:0;background:none;box-shadow:none;border-radius:7px;
  }
  .mobile-menu-accent .accent-custom-pick.is-mini .accent-custom-face{
    width:22px;height:22px;border-radius:7px;
  }
  /* 选中环：用主色而不是墨色。22px 的珠子上墨色环太粗太黑，
     看起来像给圆点加了黑框；换成主色细环既轻又和当前主题一致。 */
  .mobile-menu-accent .accent-swatch[aria-checked="true"]{
    box-shadow:0 0 0 1.5px var(--surface-2),0 0 0 3px var(--accent);
  }
  .mobile-menu-accent.is-active .accent-custom-pick.is-mini .accent-custom-face{
    box-shadow:0 0 0 1.5px var(--surface-2),0 0 0 3px var(--accent);
  }
  .mobile-menu-lang .lang-pick{
    flex:1;padding:8px 10px;border-radius:8px;
    border:1px solid var(--line);background:var(--surface-2);
    font-size:13px;color:var(--ink-2);
  }
  /* 7 项在 3 列里会剩 1 项孤零零落在第三行；
     让它横跨整行，比只占左上角一格看着顺眼。 */
  .mobile-menu-lang .lang-pick:last-child:nth-child(3n+1){grid-column:1 / -1}
  .mobile-menu-lang .lang-pick[aria-checked="true"]{
    border-color:var(--accent);color:var(--accent-ink);font-weight:700;
  }
}

/* ---------- 页脚 -------------------------------------------------------- */

.site-footer{
  position:relative;margin-top:32px;padding:72px 0 32px;
  border-top:1px solid var(--line);background:var(--surface-2);
}
.footer-inner{display:grid;grid-template-columns:1.1fr .9fr 1.2fr;gap:44px;align-items:start;padding-bottom:40px}
.footer-brand .brand{padding:0}
.footer-brand > p{max-width:320px;margin:18px 0 0;color:var(--muted);font-size:13.5px;line-height:1.8}
.footer-tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:18px}
.footer-tags span,.footer-tags a{
  display:inline-flex;align-items:center;gap:5px;
  padding:4px 10px;border-radius:6px;border:1px solid var(--line);
  background:var(--surface);color:var(--ink-2);font-size:11.5px;font-weight:500;
  transition:border-color .22s ease,color .22s ease;
}
.footer-tags a:hover{border-color:var(--accent-line);color:var(--accent-ink)}

.footer-contact{margin-top:22px}
.footer-contact h4,
.footer-nav h4,
.related-title{
  display:flex;align-items:center;gap:7px;
  margin:0 0 14px;
  font-size:11.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
}
.footer-contact-list{display:grid;gap:8px}
.contact-chip{
  display:inline-flex;align-items:center;justify-content:flex-start;gap:8px;
  padding:8px 12px;border-radius:10px;
  border:1px solid var(--line);background:var(--surface);
  color:var(--ink-2);font-size:12.5px;line-height:1;
  transition:border-color .22s ease,color .22s ease;
}
.contact-chip .ic{width:16px;height:16px;flex:none;color:var(--muted);transition:color .22s ease}
.contact-chip:hover{border-color:var(--accent-line);color:var(--ink)}
.contact-chip[data-brand="bili"] .ic{color:var(--brand-bili)}
.contact-chip[data-brand="bili"]:hover{border-color:color-mix(in srgb,var(--brand-bili) 42%,var(--line));color:var(--brand-bili)}
.contact-chip[data-brand="qq"] .ic{color:var(--brand-qq)}
.contact-chip[data-brand="qq"]:hover{border-color:color-mix(in srgb,var(--brand-qq) 42%,var(--line));color:var(--brand-qq)}
.contact-chip[data-brand="afdian"] .ic{color:var(--brand-afdian)}
.contact-chip[data-brand="afdian"]:hover{border-color:color-mix(in srgb,var(--brand-afdian) 42%,var(--line));color:var(--brand-afdian)}

.footer-nav{display:grid;gap:26px}
.footer-nav a{display:block;margin-bottom:9px;color:var(--ink-2);font-size:13.5px;transition:color .22s ease}
.footer-nav a:hover{color:var(--accent-ink)}

.related-list{display:grid;gap:8px}
.rel-item{
  position:relative;display:flex;align-items:center;gap:12px;
  padding:10px 12px;border-radius:12px;
  border:1px solid var(--line);background:var(--surface);
  overflow:hidden;
  transition:border-color .22s ease,transform .22s var(--ease),box-shadow .22s ease;
}
.rel-item:hover{border-color:var(--accent-line);transform:translateX(3px);box-shadow:var(--shadow-1)}
.rel-badge{
  display:grid;place-items:center;flex:none;
  width:36px;height:36px;border-radius:10px;font-size:18px;
  background:var(--accent-soft);color:var(--accent-ink);
  transition:transform .3s var(--spring);
}
.rel-item:hover .rel-badge{transform:scale(1.07)}
.rel-item[data-brand="teal"] .rel-badge{background:var(--teal-soft);color:var(--teal)}
.rel-item[data-brand="amber"] .rel-badge{background:var(--amber-soft);color:var(--amber)}
.rel-item[data-brand="rose"] .rel-badge{background:var(--rose-soft);color:var(--rose)}
.rel-text{display:flex;flex-direction:column;min-width:0}
.rel-text strong{font-size:13px;font-weight:700}
.rel-text small{color:var(--muted);font-size:11.5px;margin-top:1px}
.rel-arrow{margin-left:auto;color:var(--muted);font-size:15px;transition:transform .28s var(--ease),color .22s ease}
.rel-item:hover .rel-arrow{transform:translate(3px,-3px);color:var(--accent)}

.disclaimer{
  position:relative;margin-top:8px;padding:22px 24px;
  border-radius:var(--r-m);
  border:1px solid var(--line);background:var(--surface);
}
.disclaimer h4{margin-bottom:12px}
.disclaimer h4 .ic{font-size:14px;color:var(--amber)}
.disclaimer p{color:var(--muted);font-size:12.5px;line-height:1.9}
.disclaimer p + p{margin-top:10px}
.disclaimer strong{color:var(--ink-2);font-weight:700}

.footer-base{
  display:flex;flex-wrap:wrap;gap:12px;justify-content:space-between;align-items:center;
  margin-top:24px;padding-top:20px;border-top:1px solid var(--line);
  color:var(--muted);font-size:12.5px;
}
.footer-base a{color:var(--ink);font-weight:700;border-bottom:1px solid var(--line);transition:color .22s ease,border-color .22s ease}
.footer-base a:hover{color:var(--accent-ink);border-color:var(--accent-line)}

/* ---------- 回到顶部 ---------------------------------------------------- */

/* 回到顶部按钮浮在正文之上，也是玻璃片。 */
.to-top{
  position:fixed;z-index:45;right:22px;bottom:22px;
  display:grid;place-items:center;
  width:42px;height:42px;border-radius:11px;
  border:1px solid var(--line);
  background:var(--glass-tint-strong);
  backdrop-filter:var(--fx-glass-14);
  -webkit-backdrop-filter:var(--fx-glass-14);
  box-shadow:inset 0 1px 0 var(--glass-hi-soft),var(--shadow-1);
  color:var(--ink-2);font-size:17px;
  opacity:0;visibility:hidden;transform:translateY(10px);
  transition:opacity .3s ease,transform .34s var(--ease),visibility .3s,color .22s ease,border-color .22s ease;
}
.to-top.show{opacity:1;visibility:visible;transform:none}
.to-top:hover{border-color:var(--accent);color:var(--accent-ink)}

/* ---------- 入场动画 ---------------------------------------------------- */
/* 文字出现用「上移 + 底部遮罩擦除」：模糊在中低端设备上掉帧明显，
   clip-path 只影响合成层，更顺滑。

   两条硬约束（改这段之前先读）：
   · 隐藏类挂在 html 上，由 app.js 在观察器**就绪之后同步加上**——
     不是挂在 <head> 的 .js 上。否则 app.js 一旦没加载或加载失败，
     整页 .reveal 会永久停在 opacity:0，正文直接空白。
   · html.no-anim 是「必须显示」的强制开关，脚本走到任何兜底分支都会打上它。 */
html.js-anim .reveal{opacity:0;transform:translate3d(0,18px,0)}
html.js-anim .reveal.in{
  opacity:1;transform:none;
  transition:opacity .6s var(--ease) var(--d,0ms),transform .6s var(--ease) var(--d,0ms);
}
/* 说明：首屏原来那套 .hero-ready / [data-anim="1..6"] 的编号入场已随大标题一并删除 ——
   首屏现在只剩胶囊、导语、两个按钮和一行统计，用不着逐级编排。
   全站剩下的 .reveal（IntersectionObserver 驱动）不受影响。 */
/* 强制显示：脚本兜底、noscript、以及任何异常路径都走这里 */
html.no-anim .reveal,
html.no-anim [data-anim]{opacity:1 !important;transform:none !important}

/* 列表内错落入场：按结构位置自动错峰 */
html.js-anim .product-grid > .reveal:nth-child(1){--d:0ms}
html.js-anim .product-grid > .reveal:nth-child(2){--d:90ms}
html.js-anim .bento > .reveal:nth-child(1){--d:0ms}
html.js-anim .bento > .reveal:nth-child(2){--d:70ms}
html.js-anim .bento > .reveal:nth-child(3){--d:140ms}
html.js-anim .update-list > .reveal:nth-child(1){--d:0ms}
html.js-anim .update-list > .reveal:nth-child(2){--d:70ms}
html.js-anim .update-list > .reveal:nth-child(3){--d:140ms}
html.js-anim .update-list > .reveal:nth-child(4){--d:210ms}
html.js-anim .row-stack > .reveal:nth-child(1){--d:0ms}
html.js-anim .row-stack > .reveal:nth-child(2){--d:70ms}
html.js-anim .row-stack > .reveal:nth-child(3){--d:140ms}
html.js-anim .collage-row > .reveal:nth-child(1){--d:0ms}
html.js-anim .collage-row > .reveal:nth-child(2){--d:80ms}

/* ---------- 光感令牌 ---------------------------------------------------- */
/* 浅色下白色内高光在白底上不出像素，所以浅色靠多层投影表达厚度；
   深色下才是真正的高光。 */
:root{
  --hi:rgba(255,255,255,0);
  --hi-soft:rgba(255,255,255,0);
  --elev-1:
    0 1px 1px rgba(26,21,23,.045),
    0 2px 4px -2px rgba(26,21,23,.06),
    0 10px 22px -14px rgba(26,21,23,.20);
  --elev-2:
    0 1px 1px rgba(26,21,23,.05),
    0 5px 12px -5px rgba(26,21,23,.10),
    0 20px 44px -22px rgba(26,21,23,.30),
    0 34px 68px -46px color-mix(in srgb,var(--accent) 34%,transparent);
  --elev-3:
    0 2px 3px rgba(26,21,23,.06),
    0 10px 22px -8px rgba(26,21,23,.14),
    0 34px 64px -30px rgba(26,21,23,.38),
    0 44px 88px -52px color-mix(in srgb,var(--accent) 46%,transparent);
}
[data-theme="dark"]{
  /* 暗表面上的白高光超过 10% 就发灰变脏，克制一点 */
  --hi:rgba(255,255,255,.09);
  --hi-soft:rgba(255,255,255,.04);
  --elev-1:0 1px 2px rgba(0,0,0,.5),0 10px 24px -16px rgba(0,0,0,.75);
  --elev-2:0 2px 4px rgba(0,0,0,.45),0 22px 48px -24px rgba(0,0,0,.85),0 38px 74px -50px color-mix(in srgb,var(--accent) 40%,transparent);
  --elev-3:0 3px 6px rgba(0,0,0,.5),0 34px 70px -32px rgba(0,0,0,.9),0 50px 96px -56px color-mix(in srgb,var(--accent) 52%,transparent);
}

/* ---------- 主题切换的圆形揭示（View Transitions） --------------------- */
html[data-vt="theme"]::view-transition-old(root){animation:none}
html[data-vt="theme"]::view-transition-new(root){
  animation:vtReveal .52s var(--ease) both;
  clip-path:circle(0 at var(--vt-x) var(--vt-y));
}
@keyframes vtReveal{
  to{clip-path:circle(var(--vt-r,120vmax) at var(--vt-x) var(--vt-y))}
}

/* ---------- 触屏设备：指针类效果一律不出现 ------------------------------ */
/* 除了 JS 侧的能力检测，这里再加一道 CSS 兜底：即使源文件被回写出残留的
   body 状态类，触屏上也不会显示自定义光标与聚光斑。 */
@media (hover: none){
  .cursor,.spotlight{display:none !important}
  .glow::after{display:none}
  [data-tilt]:hover{will-change:auto}
  .bcard:hover,.product-card:hover,.row-card:hover,.update-row:hover{transform:none}
  .pill-btn:hover .ic,.rel-item:hover .rel-arrow,.row-card:hover .row-go,.update-row:hover .update-arrow{transform:none}
}

/* ---------- 响应式 ------------------------------------------------------ */

@media (max-width:1024px){
  .hero-inner{gap:0}
}

@media (max-width:900px){
  .nav{display:none}
  .menu-toggle{display:block}
  .hero{min-height:auto;padding:112px 0 72px}
  .hero-inner{grid-template-columns:1fr;gap:0}
  .footer-inner{grid-template-columns:1fr 1fr;gap:32px}
  .footer-inner > div:last-child{grid-column:1/-1}
}

@media (max-width:820px){
  /* 顶栏窄屏适配。数字按 375 / 320px 实算，务必连着一起改（见顶栏那段注释）。
     取舍：**站名保留**（手机上顶栏只有头像太空），改成把**主题按钮挪进菜单**。
     主题切换本来就不常点，放菜单里合理；腾出的 44px 正好装下站名：
       375px 需要 272px / 可用 335px，余 63px。
     若把主题按钮留在顶栏，四块加起来要 324px，只剩 11px 余量，随便改点什么就溢出了。 */
  .header-inner{gap:8px}
  .theme-toggle{display:none}      /* 窄屏由菜单里的 .mobile-menu-theme 承担 */
  .mobile-menu-top{display:flex}   /* 菜单顶部的站名 + 主题切换 */
  /* GitHub 胶囊收成纯图标方块：文字和那个「↗」都去掉。
     只留图标仍然一眼可辨，且正好凑满 44px 触控目标。
     aria-label 写在 HTML 上，读屏器依然念得出「GitHub 主页」。 */
  .pill-btn{
    width:44px;height:44px;padding:0;
    justify-content:center;
  }
  .pill-btn .ic{font-size:18px}
  .pill-btn .ic:last-child{display:none}
  .pill-btn-text{display:none}

  /* 触控目标一律 ≥44px */
  .brand{padding:6px 0;min-height:44px}
  .menu-toggle{width:44px;height:44px}
  .row-card{min-height:64px}
  .rel-item{min-height:62px}
  .update-row{min-height:64px}
  .faq-q{min-height:56px}
  .footer-nav a{padding:11px 0;margin-bottom:0}
  .footer-tags span,.footer-tags a{min-height:44px;padding:12px 14px;font-size:12px}
  .contact-chip{min-height:44px;padding:12px 14px}
  .footer-base a{padding:12px 0;min-height:44px;display:inline-flex;align-items:center}
  .card-link{min-height:44px;display:inline-flex;align-items:center}
  .faq-a p a{padding:8px 0;min-height:40px;display:inline-flex;align-items:center}

  /* 区块紧凑化 */
  .section{padding:64px 0}
  .sec-head{margin-bottom:28px}
  .sec-lede{font-size:14.5px}
  .hero .lede{font-size:15px;line-height:1.8}
  .hero-stats{gap:22px;margin-top:30px;padding-top:20px}
  .hero-stats strong{font-size:23px}
  .hero-actions{gap:10px;margin-top:24px}
  .particles,.scroll-cue{display:none}

  /* 首屏背景：窄屏改成横向取景（人物居中偏右）。
     遮罩这里必须**跟着主题走** —— 早先这里是写死的三层 rgba(20,16,17,…)，
     浅色主题下首屏文字已改成近黑，却被这层暗纱压住，字直接糊在插画里。
     现在用 --bg 混合：浅色是纸纱、深色是暗纱，与桌面端同一套机制。
     手机上文字横跨整宽，所以口径从「左深右浅」改成「上下两段」。 */
  .hero-bg img{object-position:64% 38%}
  .hero-bg::after{
    background:
      linear-gradient(180deg,var(--bg) 0%,transparent 12%,transparent 72%,var(--bg) 100%),
      linear-gradient(180deg,
        color-mix(in srgb, var(--bg) var(--hero-wash-m1), transparent) 0%,
        color-mix(in srgb, var(--bg) var(--hero-wash-m2), transparent) 100%);
  }

  /* 项目卡：改竖排，主视觉压缩成一条横幅 */
  .product-grid{grid-template-columns:1fr;gap:16px}
  .product-card{flex-direction:column}
  .product-card-media{
    flex:none;min-height:132px;
    border-right:0;border-bottom:1px solid var(--line);
  }
  .product-card-copy{padding:18px 18px 20px;gap:12px}
  .product-icon{width:40px;height:40px;border-radius:10px;font-size:20px}
  .product-card-title h3{font-size:17px}
  .product-card-summary{font-size:13.5px;line-height:1.75}

  /* 快捷链接：两列瓦片比单列省一半高度 */
  .bento{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  .bcard{padding:16px 14px}
  .bcard-icon{width:36px;height:36px;border-radius:10px;font-size:17px}
  .bcard h3{margin-top:12px;font-size:14.5px;line-height:1.35}
  .bcard p{margin-top:6px;font-size:12.5px;line-height:1.65}
  .bcard .card-link{margin-top:14px;font-size:13px}

  /* 更新行：改成上下排 */
  .update-row,.update-row.plain{
    padding:16px 18px;gap:8px;min-height:0;
    grid-template-columns:1fr;align-items:start;
  }
  .update-row strong{font-size:14.5px}
  .update-row > span:last-child{font-size:13px}
  .update-arrow{display:none}

  .faq-list{gap:10px}
  .faq-item{border-radius:var(--r-m)}
  .faq-q{padding:16px 18px;font-size:15px}
  .faq-a p{padding:0 18px 18px;font-size:13.5px}

  /* 页脚 */
  .site-footer{padding:48px 0 24px}
  .footer-inner{grid-template-columns:1fr;gap:26px;padding-bottom:28px}
  .footer-inner > div:last-child{grid-column:auto}
  .disclaimer{padding:18px}
  .disclaimer p{font-size:12.5px;line-height:1.85}
  .footer-nav{grid-template-columns:1fr;gap:20px}
  .to-top{right:14px;bottom:18px;width:46px;height:46px}
}

@media (max-width:560px){
  .bento{grid-template-columns:1fr}
  /* ≤560px 顶栏仍然是「头像 + 站名 + GitHub图标 + 菜单」四块。
     站名**不隐藏** —— 早先这里曾有一条 .brand-text 的 display:no​ne，
     导致 375~560px 的屏幕上站名是空的、顶栏显得很空，已删除。
     按 390px 手机实算：头像32 + 站名136 + GitHub44 + 菜单44 + 2×5间距 = 266px，
     可用 350px，余 84px；320px 小屏需 242px / 可用 280px，余 38px。
     间距从 8px 收到 5px 就是为了把站名装回来。 */
  .header-inner{gap:5px}
  .brand{gap:7px}
  .brand-avatar{width:28px;height:28px}
  /* 站名「小猫娘土豆的环上旮旯小屋」比原来的 mcpotato1123 长得多，
     小屏上收字号并允许省略号，保证顶栏的品牌、语言、主题、菜单四块不挤爆。 */
  .brand-text{font-size:12.5px;letter-spacing:-.03em;min-width:0;overflow:hidden;text-overflow:ellipsis}
  .header-actions{gap:4px}
  .menu-toggle{width:40px;height:40px}
  .pill-btn{width:40px;height:40px}
  .hero-stats{gap:18px}
  .hero-stats li{flex:1 1 30%}
  .product-card-media{min-height:112px}
  .row-card{padding:16px;gap:13px}
  .row-icon{width:42px;height:42px;font-size:20px}
  .row-body small{font-size:12.5px}
  .dl-hint{font-size:11px}}

/* ---------- 封面置顶变体（.product-card.media-top） --------------------
   默认的 .product-card 是「左图右文」。作品下载那两张卡用的是横版封面
   （1920×1080 / 1800×1200），塞进 42% 宽的左栏会被裁掉大半，所以改成
   封面在上、文字在下的整幅版式。

   放置位置有硬要求：这段必须排在**所有断点之后**（当前在 ≤560px 之后）。
   .product-card.media-top 与 .product-card 特异性相同，只靠书写顺序取胜；
   一旦把它挪到 ≤820px 那条之前，窄屏的 flex-direction:column 与
   .product-card-media{flex:none;min-height:132px} 就会把它盖掉。 */
.product-card.media-top{flex-direction:column;align-items:stretch}
.product-card.media-top .product-card-media{
  flex:none;width:100%;aspect-ratio:16 / 10;min-height:0;
  border-right:0;border-bottom:1px solid var(--line);
}
.product-card.media-top .product-card-copy{flex:1}

/* 封面图：等比铺满，悬停轻微推近。
   object-position 用 center top —— 封面主体一般在上半部分，
   按 16/10 裁切时优先保住顶部。 */
.product-card-image{
  width:100%;height:100%;object-fit:cover;object-position:center top;
  transition:transform .6s var(--ease);
}
.product-card:hover .product-card-image{transform:scale(1.03)}

/* 角标改用 figcaption，顺手去掉 <figure> 的默认外边距 */
figure.product-card-media{margin:0}
.product-card-flag{display:inline-flex}

/* ---------- 模糊 / 动画分级（弱设备） ---------------------------------- */
/* 这里必须把**每一档**模糊令牌都归零。漏掉一档，用它的组件在弱机上就照旧
   逐帧采样背后内容 —— 顶栏是常驻的，代价最明显。
   新增模糊档时记得回来补一行（--fx-glass-24 就是这么补上的）。 */
html.fx-noblur{
  --fx-glass-8:none;
  --fx-glass-14:none;
  --fx-glass-16:none;
  --fx-glass-20:none;
  --fx-glass-24:none;
  --fx-glass-28:none;
  --fx-glass-32:none;
  --fx-glass-40:none;
  --fx-glass-56:none;
}
/* 弱机下主题切换那条 .35s 底色淡入改成立即生效，换主题不再是一次整屏重绘 */
html.fx-lite body,
html.fx-lite .spotlight{transition:none}

/* ---------- Reduced motion ---------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  html.js-anim .reveal,
  html.js-anim [data-anim],
  html.no-anim .reveal{opacity:1 !important;transform:none !important}
  .spotlight,.cursor,.particles{display:none}
  .glow::after{display:none}
  body{animation:none}
  .hero-inner::after{animation:none}
  .hl,.sec-title em{animation:none}
}

/* ---------- Print ------------------------------------------------------- */
@media print{
  .backdrop,.spotlight,.site-header,.to-top,.cursor,.particles,.scroll-cue{display:none}
  body{background:#fff;animation:none}
  html.js-anim .reveal,
  html.js-anim [data-anim],
  html.no-anim .reveal{opacity:1 !important;transform:none !important}
}

/* ---------- 阿拉伯语（从右往左）------------------------------------------
   dir="rtl" 由 i18n.js 写在 <html> 上。浏览器会自动翻转文本对齐、
   flex / grid 顺序、以及用了 start/end 语义的内外距。
   下面只补那些“写死了物理方向”的地方。 */

/* 首屏遮罩是 96deg 的左深右浅渐变。RTL 下文字跑到右边，
   所以把整层水平镜像 —— 比重写一套 264deg 的四层渐变更保守，
   且能保证两边完全对称（手机那套渐变也一并被镜像）。 */
html[dir="rtl"] .hero-bg::after{transform:scaleX(-1)}

/* 浮层锚点：语言与调色盘面板靠着顶栏右侧的按钮，
   RTL 下这些按钮在左边，所以弹层也得改靠左。 */
html[dir="rtl"] .lang-menu,
html[dir="rtl"] .accent-menu{right:auto;left:20px}

/* 选中项的竖条标记（语言菜单）从左边移到右边 */
html[dir="rtl"] .lang-menu button[aria-checked="true"]{box-shadow:inset -2px 0 0 var(--accent)}

/* 下拉项悬停时往“内侧”推一下 —— RTL 下内侧是左边 */
html[dir="rtl"] .rel-item:hover{transform:translateX(-3px)}

/* 卡片左栏与右栏之间那根分隔线：左栏已经到右边了，装饰线也跟着换边。 */
html[dir="rtl"] .product-card-media{border-right:0;border-left:1px solid var(--line)}
@media (max-width:820px){
  html[dir="rtl"] .product-card-media{border-left:0;border-bottom:1px solid var(--line)}
}

/* 箭头图标在 RTL 下要它指向相反方向才符合阅读习惯 */
html[dir="rtl"] .card-link b,html[dir="rtl"] .rel-arrow,html[dir="rtl"] .pc-title .ic{transform:scaleX(-1)}

/* 数字与包名始终用 LTR 排列：阿拉伯语里若按 RTL 排，
   像 com.galgod.band 这种包名会被拆成前后颠倒的形状。 */
html[dir="rtl"] .card-tags i[dir],
html[dir="rtl"] .accent-custom-hex,
html[dir="rtl"] .accent-hex-input{direction:ltr;unicode-bidi:plaintext}
