/* ==========================================================================
   角色档案域 · character.css
   --------------------------------------------------------------------------
   承载 /Character（名片墙）、/Character/{id}（详情）、/Character/Edit/{id?}（编辑）
   三个页面里**本站公共风格包没有提供**的那部分样式。

   ★ 与站内风格包的关系 ★
   外壳 / 页标题 / 标签贴纸 / 按钮 / 表单控件一律走 comic-stylekit.css 的公共类
   （.comic-section-xl · .comic-page-title · .comic-badge · .comic-btn · .comic-input），
   本文件不再为它们造平行实现 —— 这样改一次风格包，三个页面跟着一起变。
   配色同样只走第 0 节的 token，角色自己的主色调仅通过 --char-color 注入
   （作用域见 .char-scope）。
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. 基础：主色调作用域与分节外壳
   -------------------------------------------------------------------------- */

/* 角色的主色调只在**这个作用域内**生效，不会漏到页面其它地方。
   回退值是站点蓝 —— 角色没填主色调时整页仍然是完整的，不会出现一片灰。 */
.char-scope {
    --char-color: var(--comic-blue);
}

/* 机械感的编号 / 数字：等宽字族，字符宽度一致，序号变化时整排不会跳。
   ★ 不能写 font-mono 工具类 ★ 本站从未翻译过这个类，写上去不报错、
   控制台干净，字体只是静默回落到正文字体。 */
.char-mono {
    font-family: ui-monospace, sfmono-regular, menlo, monaco, consolas,
                 'liberation mono', 'courier new', monospace;
}

/* 分节标题之下第一块内容的统一上间距。
   多数内容块自带 `margin: 2rem 0 0`（.char-facts / .char-basic / .char-drive /
   .char-relations 都是这样），但正文型面板（.char-panel）**没有**上间距 ——
   它设计上待在 .char-panels 这个分格容器里，间距由容器的 gap 负责。
   于是"能力"那一节的卡片会紧贴标题行，而同一页其它节都隔着 2~3rem。 */
.char-sect-body {
    margin-top: 2rem;
}

@media (min-width: 768px) {
    .char-sect-body { margin-top: 3rem; }
}

/* ★ 详情页不给分节配背景层 ★
   全页底纹由 _Layout 的 <main> 统一铺（comic-halftone + opacity-paper-6），
   每一节都是透明的纸底 —— 分节里再叠网点 / 速度线 / 放射线会把它拆成一排条带。
   节与节之间也不画墨线，分段交给 .comic-section-xl 的留白 + 编号徽章。
   新增分节时别再往里加铺满层。 */

/* 分节标题行（徽章 + 标题）用风格包的 .comic-sect-head / .comic-sect-no，
   这里只补标题文字的刻度。 */
.char-sect-title {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 900;
    letter-spacing: 0.04em;
    line-height: 1.15;
}

@media (min-width: 768px) {
    .char-sect-title { font-size: 2.25rem; }
}

/* 标题行下方的墨线。
   ★ 它不是分节之间的分隔线 ★ 节与节之间仍旧只有留白（见第 0 节）；
   这条线只把「标题」与「这一节的正文」分开，与编辑页 .char-form-head 同源。 */
.char-sect-head {
    padding-bottom: 0.75rem;
    border-bottom: 4px solid var(--comic-ink);
}

/* 分节内容的居中列。.comic-section-xl 只给内边距，列宽与居中由这里负责 ——
   在 grid 里 margin-inline:auto 同样有效，故三个页面共用同一个类。 */
.char-sect-inner {
    position: relative;
    max-width: 72rem;
    margin-inline: auto;
}

/* 副题：分节标题下面那行说明文字 */
.char-sect-lead {
    max-width: 68ch;
    margin: 1rem 0 0;
    color: var(--comic-muted);
    font-size: 0.9375rem;
    font-weight: 700;
    line-height: 1.75;
}

@media (min-width: 768px) {
    .char-sect-lead { font-size: 1rem; }
}

/* --------------------------------------------------------------------------
   1. 页面扉页
   -------------------------------------------------------------------------- */

/* 名片墙的扉页是纯文案排版，居中；详情页的扉页是两栏（文案在左、立绘在右），
   窄屏塌成单列。两者共用 .comic-section-xl 的外壳与 .comic-page-title 的标题。 */
.char-cover-inner {
    position: relative;
    max-width: 72rem;
    margin: 0 auto;
    text-align: center;
}

/* 居中的扉页里，统计条作为 flex 行也要跟着居中 ——
   text-align 管不到 flex 子项的水平排布，这一步不能省。 */
.char-cover-inner .char-wall-stats {
    justify-content: center;
}

/* 扉页两栏：文案在左、立绘在右。宽屏下网格拆成两行（`1fr auto`），立绘跨两行，
   操作行因此落到第二行左下角 —— 左沿与姓名块对齐、下沿与立绘对齐。 */
.char-cover-grid {
    position: relative;
    display: grid;
    gap: 2.25rem;
    max-width: 72rem;
    margin: 0 auto;
}

.char-cover-copy {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 0;
}

/* 分类小标：抬头文字 + 主色调短横。它给左栏一个明确的上边界 ——
   没有它时左栏是"从空处开始"的，姓名块看起来是浮着的。 */
.char-cover-kicker {
    display: inline-flex;
    align-items: center;
    gap: 0.7rem;
    margin: 0 0 1.1rem;
    color: var(--comic-ink);
    font-size: 0.6875rem;
    font-weight: 900;
    letter-spacing: 0.24em;
}

.char-cover-kicker::before {
    content: '';
    width: 2.25rem;
    height: 0.5rem;
    background: var(--char-color);
}

/* 姓名块：底色取角色主色调（不再固定站内红），文字色由页面按亮度算好注入
   --char-ink —— 浅色主色调下不会出现"白字压白底"。
   角色页是"这个角色的档案"，主色调落在姓名块上，翻到谁一眼就知道。 */
.char-cover-title {
    background-color: var(--char-color);
    color: var(--char-ink, var(--comic-white));
}

.char-cover-stage {
    position: relative;
    width: 100%;
    max-width: 26rem;
    margin: 0 auto;
    /* 立绘的 3D 倾斜靠它给透视，否则 rotateX/Y 会被压成平面缩放 */
    perspective: 1000px;
}

/* ---- 立绘 3D 倾斜（鼠标跟随，见 comic-effects.js）----
   只转立绘本身：编号角标是"贴上去的"，跟着一起转会读成整块面板在晃。
   --tilt-x / --tilt-y 由脚本写入，这里只负责合成与过渡。 */
[data-comic-tilt] {
    transform: rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
    transition: transform 160ms ease-out;
    will-change: transform;
}

@media (min-width: 1024px) {
    .char-cover-grid {
        grid-template-columns: 1.12fr 0.88fr;
        grid-template-rows: 1fr auto;
        align-items: start;
        column-gap: 4rem;
        row-gap: 2.25rem;
    }

    .char-cover-copy {
        grid-column: 1;
        grid-row: 1;
    }

    .char-cover-stage {
        grid-column: 2;
        grid-row: 1 / span 2;
        max-width: none;
        margin: 0;
    }

    .char-cover-actions {
        grid-column: 1;
        grid-row: 2;
        margin: 0;
    }
}

/* 详情页扉页底部的操作行（返回档案墙 / 编辑档案）。
   放在扉页里而不是单开一节：它只有两个按钮，独立成节会被读成"这一节是空的"。
   ★ 它是 .char-cover-grid 的第三个格 ★ 窄屏单列时排在立绘之后，
   宽屏由上面的 media query 提到第二行左下角。 */
.char-cover-actions {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin: 0;
}

/* 外文名：字距拉开的副标题。刻意不做大写转换 ——
   外文名是专名（Nastia·Simon），CSS 不该改写字母形态。

   ★ 颜色走 --char-text 而不是 --char-color ★ 后者是"色块底"用的，
   浅色主色调（淡黄 / 米白）直接当纸底上的正文色会看不清；
   --char-text 由页面算好：够深就用主色调，不够深退回墨色。 */
.char-cover-alias {
    margin: 1rem 0 0;
    font-size: 0.875rem;
    font-weight: 900;
    letter-spacing: 0.28em;
    color: var(--char-text, var(--char-color));
    word-break: break-word;
}

@media (min-width: 768px) {
    .char-cover-alias { font-size: 1rem; }
}

/* 对话气泡承载「一句话简介」——留出底部空间给尾巴，否则尾巴会压到下面的标签 */
.char-cover-quote {
    max-width: 34rem;
    margin: 2.5rem 0 0;
    padding: 1.25rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius-bubble);
    background: var(--comic-white);
    box-shadow: var(--comic-shadow-4);
    color: var(--comic-ink);
    font-size: 0.875rem;
    font-weight: 700;
    line-height: 1.75;
}

@media (min-width: 768px) {
    .char-cover-quote {
        padding: 1.5rem;
        font-size: 1rem;
    }
}

/* 立绘右下角的档案编号角标。与详情页分节徽章同源同形（倾角 + 墨线 + 硬阴影），
   只是尺寸收小一档 —— 它是扉页的角标，不该与页标题争重。 */
.char-portrait-no {
    position: absolute;
    top: -0.75rem;
    left: -0.75rem;
    z-index: 20;
    padding: 0.25rem 0.75rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--char-color);
    box-shadow: var(--comic-shadow-4);
    font-size: 0.75rem;
    font-weight: 900;
    letter-spacing: 0.04em;
    line-height: 1.1;
    text-transform: uppercase;
    /* 与姓名块同一套对比度规则：浅色主色调上不能写白字 */
    color: var(--char-ink, var(--comic-white));
}

/* --------------------------------------------------------------------------
   2. 媒体框（立绘 1:1.414 / 头像 3:4 / 人设图 1.414:1 / 表情集 1:1）
   -------------------------------------------------------------------------- */

.char-media-frame {
    position: relative;
    overflow: hidden;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--comic-white);
    box-shadow: var(--comic-shadow-10);
    /* 缺省 1:1：调用点忘写 --media-ratio 时得到一个方框，而不是一条 0 高度的线 */
    aspect-ratio: var(--media-ratio, 1 / 1);
}

.char-media-frame img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.char-media-frame > .char-portrait-placeholder {
    position: absolute;
    inset: 0;
    aspect-ratio: auto;
}

/* 媒体框的图注（人设图 / 表情集）。字号压到全站最小一档 ——
   它是"这张图叫什么"的标注，不该与档案标题争夺注意力。 */
.char-media-caption {
    margin-top: 0.6rem;
    color: var(--comic-muted);
    font-size: 0.7rem;
    font-weight: 900;
    letter-spacing: 0.16em;
    text-transform: uppercase;
}

/* 编辑页的图像块：预览框必须**限宽** —— 不限宽的话立绘框（1:1.414，比 3:4
   更瘦长）会占掉超过半屏高，四个块要滚好几屏才看完。 */
.char-media-cell {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.char-media-cell .char-media-frame {
    max-width: 14rem;
}

/* --------------------------------------------------------------------------
   3. 图像占位牌
   -------------------------------------------------------------------------- */

.char-portrait-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    aspect-ratio: 1 / 1.414;
    padding: 1rem;
    color: var(--comic-ink);
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.6;
    text-align: center;
}

/* --------------------------------------------------------------------------
   4. 档案条目（基本信息 / 外貌）
   -------------------------------------------------------------------------- */

.char-basic {
    display: grid;
    align-items: start;
    gap: 2rem;
    margin: 2rem 0 0;
}

@media (min-width: 768px) {
    .char-basic {
        grid-template-columns: 14rem minmax(0, 1fr);
        gap: 2.5rem;
        margin-top: 3rem;
    }
}

/* ★ align-content: start 不是可选项 ★
   .char-facts 在某些版面里是网格子项（01 节与头像同格）。网格容器默认
   `align-content: normal` 等价于 stretch —— 一旦它被拉高到与头像等高，
   两个 auto 行会**各自被撑开**，于是「性别」那格变成一个 140px 高的空盒子。
   两行都从顶部起排，格子只按内容高。 */
.char-facts {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-content: start;
    gap: 1rem;
    margin: 2rem 0 0;
}

@media (min-width: 560px) {
    .char-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 768px) {
    .char-facts {
        gap: 1.25rem;
        margin-top: 3rem;
    }
}

/* 基本信息那一组是 6 格（5 项 + 主色调），排 3 列正好两行齐平 */
.char-facts--dense {
    margin-top: 0;
}

@media (min-width: 768px) {
    .char-facts--dense {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        margin-top: 0;
    }
}

/* 外貌那一节唯一的跨列项（服饰） */
.char-facts .char-fact--wide {
    grid-column: 1 / -1;
}

.char-fact {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    min-width: 0;
}

.char-fact-label {
    color: var(--comic-muted);
    font-size: 0.75rem;
    font-weight: 900;
    letter-spacing: 0.1em;
}

.char-fact-value {
    margin: 0;
    color: var(--comic-ink);
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.6;
    overflow-wrap: break-word;
}

/* 主色调那一格：色块 + 十六进制。色块直接吃 --char-color，不额外传参。 */
.char-fact-value--swatch {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.char-swatch {
    flex: 0 0 auto;
    width: 1.25rem;
    height: 1.25rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--char-color);
}

/* ---- 档案格（01 基本信息：6 格）----
   六格同构：白纸 + 墨线 + 主题色左边 + 硬阴影，与能力 / 核心事件 / 人物关系
   共用同一套条目卡语言（左侧那道 8px 主色调是本域条目卡的共同记号）。
   min-height 让六格等高：出生地只有两个字，不设底高会矮邻格一截。 */
.char-facts--cards .char-fact {
    justify-content: flex-start;
    min-height: 4.75rem;
    padding: 0.75rem 0.9rem;
    border: var(--comic-border);
    border-left: 8px solid var(--char-color);
    border-radius: var(--comic-radius);
    background: var(--comic-white);
    box-shadow: var(--comic-shadow-3);
}

/* ---- 03 外貌：7 项描述与人设图并排 ---- */
.char-appearance {
    display: grid;
    align-content: start;
    gap: 2rem;
    margin: 2rem 0 0;
}

/* 两栏内部由容器的 gap 负责间距，故把两个子块自己的上外边距清零。
   选择器比 .char-facts / .char-sheet 各多一层，md 断点的 margin-top 也一并盖住。 */
.char-appearance .char-facts,
.char-appearance .char-sheet {
    margin: 0;
}

@media (min-width: 1024px) {
    .char-appearance {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        align-items: start;
        gap: 2.5rem;
        margin-top: 3rem;
    }
}

/* --------------------------------------------------------------------------
   5. 分镜面板（内驱力 3 格 / 能力 / 核心事件）
   -------------------------------------------------------------------------- */

/* ② 能力：整段正文，单列 */
.char-panel {
    position: relative;
    padding: 1.25rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--comic-white);
    box-shadow: var(--comic-shadow-4);
}

.char-panel-label {
    display: block;
    margin-bottom: 0.6rem;
    color: var(--comic-muted);
    font-size: 0.6875rem;
    font-weight: 900;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

.char-panel-body {
    margin: 0;
    color: var(--comic-ink);
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.8;
    overflow-wrap: break-word;
    white-space: pre-wrap;
}

/* 整段正文（05 能力 / 07 核心事件）。主题色左边框是本域条目卡的共同记号，
   与 01 的档案格、09 的关系卡同形 —— 三种卡片一眼看得出是同一套档案。
   ★ 06 内驱力不吃这条 ★ 它走的是 .char-panel（无 --prose），
   白描边墨底由 .char-sect--ink-panel 单独给出。 */
.char-panel--prose {
    padding: 1.5rem;
    border-left: 8px solid var(--char-color);
}

/* ★ 行宽上限 ★ 72rem 列宽下一行中文能排到 68 字，眼睛要来回扫。
   54em（约 54 个中文字）是这一版给长正文定的舒适宽度；短句不受影响。 */
.char-panel--prose .char-panel-body {
    max-width: 54em;
}

@media (min-width: 768px) {
    .char-panel--prose { padding: 2rem; }
}

/* ---- 06 内驱力：左文右图 ---- */
.char-drive {
    display: grid;
    gap: 2rem;
    margin: 2rem 0 0;
}

.char-panels {
    display: grid;
    gap: 1rem;
    align-content: start;
}

/* ---- 深色面板组（全页只有 06 内驱力这一处）----
   ★ 墨色只落在 .char-panel 这一层，不落在分节上 ★
   分节若也吃墨底，标题就成了白字压纸底、直接看不见。
   ★ 白描边必须留 ★ 墨线画在墨底上等于没有边框，面板四边会糊成一块。 */
.char-sect--ink-panel .char-panel {
    border-color: var(--comic-white);
    background: var(--comic-ink);
    box-shadow: none;
}

.char-sect--ink-panel .char-panel-label {
    color: rgba(255, 255, 255, 0.62);
}

.char-sect--ink-panel .char-panel-body {
    color: var(--comic-white);
}

@media (min-width: 1024px) {
    .char-drive {
        grid-template-columns: 1.25fr 1fr;
        gap: 2.5rem;
        margin-top: 3rem;
    }

    .char-drive-face { margin: 0; }
}

/* ---- 07 核心事件：三条并列，每条一张白卡 + 一枚书写位编号 ---- */
.char-events {
    display: grid;
    gap: 1rem;
}

.char-event {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
}

.char-event-no {
    flex: 0 0 auto;
    color: var(--comic-ink);
    font-size: 1.25rem;
    font-weight: 900;
    /* 行盒高度对齐正文首行（正文 1rem × 1.8 = 1.8rem），编号与首行文字齐基线 */
    line-height: 1.8rem;
}

/* --------------------------------------------------------------------------
   6. 人物关系（按类型分组 —— 保持站内既有的分组语义，不改成关系图）
   -------------------------------------------------------------------------- */

.char-relations {
    display: grid;
    gap: 1rem;
    margin: 2rem 0 0;
}

@media (min-width: 768px) {
    .char-relations { margin-top: 3rem; }
}

/* ★ 宽屏两栏 ★ 关系卡常常只有"类型 + 一两个名字"，铺满 72rem 时
   一张卡里九成是空白。auto-fit 让它按内容宽度分栏：够宽就两栏，
   窄屏自然退回一栏，不必再写一遍断点。 */
@media (min-width: 1024px) {
    .char-relations {
        grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr));
        align-items: start;
        gap: 1.25rem;
    }
}

.char-rel-group {
    padding: 1rem 1.25rem;
    border: var(--comic-border);
    border-left: 6px solid var(--char-color);
    border-radius: var(--comic-radius);
    background: var(--comic-white);
    box-shadow: var(--comic-shadow-4);
}

.char-rel-type {
    display: inline-block;
    margin-bottom: 0.75rem;
    padding: 0.2rem 0.6rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--char-color);
    box-shadow: var(--comic-shadow-2);
    /* 浅色主色调上不能写白字，与姓名块 / 编号角标同一套规则 */
    color: var(--char-ink, var(--comic-white));
    font-size: 0.75rem;
    font-weight: 900;
    letter-spacing: 0.04em;
}

.char-rel-targets {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.char-rel-target {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    min-width: 0;
}

.char-rel-link,
.char-rel-name {
    color: var(--comic-ink);
    font-size: 0.9375rem;
    font-weight: 900;
}

.char-rel-link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    text-decoration: none;
    border-bottom: 3px solid var(--char-color);
}

.char-rel-link:hover {
    color: var(--char-color);
}

.char-rel-alias {
    color: var(--comic-muted);
    font-size: 0.75rem;
    font-weight: 700;
}

.char-relations-empty {
    margin: 2rem 0 0;
    color: var(--comic-muted);
    font-size: 0.875rem;
    font-weight: 700;
}

/* --------------------------------------------------------------------------
   7. 名片墙
   -------------------------------------------------------------------------- */

.char-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1.5rem;
    /* 单列时给个宽度上限：3:4 的竖版名片一旦摊满整屏就成了门板 */
    max-width: 24rem;
    margin: 0 auto;
}

@media (min-width: 640px) {
    .char-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        max-width: 72rem;
    }
}

@media (min-width: 1250px) {
    .char-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* 一张名片 = 两张卡面（正面头像 / 背面档案），悬停或键盘聚焦时翻面。
   3:4 与上传侧归一化的头像画布同比例 —— 两边写歪就会出现"框是竖的、图是方的"，
   而 object-fit: cover 会静默吃掉差异。 */
.char-card {
    position: relative;
    aspect-ratio: 3 / 4;
    min-width: 0;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--comic-white);
    box-shadow: var(--comic-shadow-6);
    /* 抬升档用 --comic-duration-move：位移需要比色变更长的时长才不显得抽搐 */
    transition: box-shadow var(--comic-duration-move) ease, transform var(--comic-duration-move) ease;
}

.char-card:hover,
.char-card:focus-within {
    transform: translateY(-0.5rem);
    /* ★ 上限刻意停在 10px ★ 本站阴影 token 最大的一档，
       单页突破这个刻度会让名片墙比站内所有其它卡片都"浮"一截。 */
    box-shadow: var(--comic-shadow-10);
}

/* 键盘可达：焦点环取角色主色调 */
.char-card:focus-within {
    outline: 4px solid var(--char-color);
    outline-offset: 3px;
}

/* ---- 卡面：两面绝对定位叠在一起 ----
   inset 取 4px 是扣掉父级墨线，内沿圆角再扣掉它的厚度。
   ★ pointer-events 必须跟着翻面一起切 ★ 否则透明的那面仍然吃掉点击。
   ★ 两面都是绝对定位 → 卡片高度只由 .char-card 的 3:4 说了算 ★
   背面内容必须真的装得下，不能指望"装不下就长高"。 */
.char-card-face {
    position: absolute;
    inset: 4px;
    overflow: hidden;
    border-radius: max(calc(var(--comic-radius) - 2px), 0px);
    transition: opacity var(--comic-duration-move) ease,
                transform var(--comic-duration-move) ease;
}

/* 正面（头像 + 姓名条）：默认可见，翻面时淡出并向左轻移 —— 位移方向与背面相反，
   读起来才像"翻过去"而不是"叠上去"。 */
.char-card-face--front {
    opacity: 1;
    transform: translateX(0) scale(1);
}

.char-card:hover .char-card-face--front,
.char-card:focus-within .char-card-face--front {
    opacity: 0;
    transform: translateX(-6%) scale(0.98);
    pointer-events: none;
}

/* 背面（档案）：默认不可见且向右偏，翻面时回正 */
.char-card-face--back {
    opacity: 0;
    transform: translateX(6%);
    pointer-events: none;
}

.char-card:hover .char-card-face--back,
.char-card:focus-within .char-card-face--back {
    opacity: 1;
    transform: translateX(0);
    pointer-events: auto;
}

.char-card-link {
    display: block;
    min-width: 0;
    color: var(--comic-ink);
    text-decoration: none;
}

.char-card-link:focus-visible {
    outline: none;
}

/* 「翻转」提示贴纸：正面右上角，翻面时淡出。
   ★ pointer-events: none 不能省 ★ 它压在正面链接的右上角上，
   没有这一条，那一角就点不到；而且淡出后 opacity: 0 的元素**照样吃点击**。 */
.char-card-open {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    z-index: 10;
    pointer-events: none;
    padding: 0.15rem 0.5rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--comic-yellow);
    box-shadow: var(--comic-shadow-2);
    color: var(--comic-ink);
    font-size: 0.625rem;
    font-weight: 900;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    transition: opacity var(--comic-duration-move) ease;
}

.char-card:hover .char-card-open,
.char-card:focus-within .char-card-open {
    opacity: 0;
}

/* 头像区：铺满正面卡面 */
.char-card-portrait {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: var(--comic-white);
}

.char-card-portrait img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.char-card-portrait .char-portrait-placeholder {
    position: absolute;
    inset: 0;
    aspect-ratio: auto;
}

/* 正面底部的姓名条：不悬停时整张卡只有一张脸，认人放在正面完成。
   ★ 不要加底衬 ★ 纸条会从头像下沿切走一条，人像的下巴 / 肩线常常正好在那里；
   可读性交给墨色硬描边（见下面两个 --char-cap-shadow），它不吃掉任何画面。 */
.char-card-caption {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    padding: 0.5rem 0.75rem 0.6rem;

    /* 八向硬描边。text-shadow 不继承（它是逐元素的），所以把两条完整值
       存成自定义属性，两个元素各取一条 —— 免得同一条阴影写两遍、改一处漏一处。
       ★ 为什么分粗细分档 ★ 外文名只有 0.6875rem，套 2px 轮廓会被描边糊死，
       字腔里剩不下多少填充色；名字 1.125rem 才撑得住 2px。 */
    --char-cap-shadow-lg:
        2px 0 0 var(--comic-ink), -2px 0 0 var(--comic-ink),
        0 2px 0 var(--comic-ink), 0 -2px 0 var(--comic-ink),
        2px 2px 0 var(--comic-ink), -2px -2px 0 var(--comic-ink),
        2px -2px 0 var(--comic-ink), -2px 2px 0 var(--comic-ink);
    --char-cap-shadow-sm:
        1px 0 0 var(--comic-ink), -1px 0 0 var(--comic-ink),
        0 1px 0 var(--comic-ink), 0 -1px 0 var(--comic-ink),
        1px 1px 0 var(--comic-ink), -1px -1px 0 var(--comic-ink),
        1px -1px 0 var(--comic-ink), -1px 1px 0 var(--comic-ink);
}

.char-card-no {
    position: absolute;
    top: 0.75rem;
    left: 0.75rem;
    z-index: 10;
    padding: 0.15rem 0.5rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--char-color);
    box-shadow: var(--comic-shadow-2);
    color: var(--comic-white);
    font-size: 0.6875rem;
    font-weight: 900;
    letter-spacing: 0.04em;
}

/* 背面正文区：撑满整张卡面，卡底的操作行靠 margin-top:auto 压到底。
   ★ padding-top 比其它三边大一截 ★ 编号贴纸（.char-card-no）钉在卡片左上角，
   占到卡面内沿往下约 41px；正文从常规间距开始会被它盖住，故留 2.75rem。
   ★ 左右与底部的内边距不在这里 ★ 交给 .char-card-info / .char-card-foot 各自带：
   链接因此能一直铺到卡面边缘，卡片底部与两侧不会留下点不动的空白。 */
.char-card-body {
    display: flex;
    height: 100%;
    flex-direction: column;
    padding: 0;
    padding-top: 2.75rem;
}

/* 背面唯一的链接。
   ★ flex: 1 修的是"卡片底部点不动" ★ 卡片高度由 .char-card 的 3:4 定死，
   正文常常没有卡面高；链接不铺满的话，下方留白属于 .char-card-body，
   点上去没有任何反应（1440px 下实测有 163px 的死区）。 */
.char-card-info {
    display: block;
    flex: 1;
    min-width: 0;
    padding: 0 1.25rem 1.25rem;
    color: var(--comic-ink);
    text-decoration: none;
}

.char-card-info:focus-visible {
    outline: none;
}

/* 姓名 / 外文名：压在头像上，取纸白 + 墨色描边。
   外文名用主题色的反色（--char-color-inv，由页面现算）——
   主题色多半偏深，直接压在照片上会糊成一片。 */
.char-card-name {
    margin: 0;
    color: var(--comic-white);
    font-size: 1.125rem;
    font-weight: 900;
    letter-spacing: 0.02em;
    line-height: 1.25;
    overflow-wrap: break-word;
    text-shadow: var(--char-cap-shadow-lg);
}

.char-card-alias {
    margin-top: 0.2rem;
    /* 回退取纸白：万一 --char-color-inv 没注入（新增角色缺 ColorTheme 之类），
       宁可和外文名一样读得清，也不要变成透明字。 */
    color: var(--char-color-inv, var(--comic-white));
    font-size: 0.6875rem;
    font-weight: 900;
    letter-spacing: 0.16em;
    word-break: break-word;
    text-shadow: var(--char-cap-shadow-sm);
}

.char-card-rule {
    margin: 0.6rem 0;
    border-top: 3px solid var(--comic-ink);
}

.char-card-tagline {
    margin: 0 0 0.6rem;
    color: var(--comic-muted);
    font-size: 0.875rem;
    font-weight: 700;
    line-height: 1.65;
}

.char-card-facts {
    display: grid;
    gap: 0.375rem;
    margin: 0;
    font-size: 0.8125rem;
    line-height: 1.65;
}

.char-card-facts > div {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    min-width: 0;
}

.char-card-facts dt {
    flex: 0 0 auto;
    color: var(--comic-muted);
    font-weight: 700;
}

.char-card-facts dd {
    min-width: 0;
    margin: 0;
    color: var(--comic-ink);
    font-weight: 900;
    overflow-wrap: break-word;
}

/* 标签贴纸：底色取角色主色调，字号比通用徽章大一档。
   不复用 .comic-badge-<色> —— 那几个是固定四色变体，这里要的是角色自己的颜色；
   文字色交给现算的 --char-ink，浅色主色调上不会白字压白底。 */
.char-tag {
    padding: 0.25rem 0.75rem;
    background-color: var(--char-color);
    color: var(--char-ink, var(--comic-white));
    font-size: 0.875rem;
    letter-spacing: 0.04em;
}

/* 卡内标签：最多 4 个，再多会把卡片挤爆 */
.char-tags {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: 1.25rem;
}

.char-card-body .char-tags {
    margin-top: 0.75rem;
    gap: 0.4rem;
}

.char-card-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: auto;
    padding: 0.75rem 1.25rem 1.25rem;
}

.char-card-admin {
    display: flex;
    flex: 0 0 auto;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
}

.char-card-admin .comic-btn-sm {
    padding: 0.375rem;
    gap: 0.25rem;
}

@media (min-width: 768px) {
    /* 顶边仍是那条给编号贴纸让位的 2.75rem；左右与底部的 1.5rem 落在两个子块上 */
    .char-card-body {
        padding: 0;
        padding-top: 2.75rem;
    }

    .char-card-info { padding: 0 1.5rem 1.5rem; }

    .char-card-foot { padding: 0.75rem 1.5rem 1.5rem; }

    .char-card-name { font-size: 1.375rem; }

    .char-card-alias { font-size: 0.75rem; }

    .char-card-rule { margin: 0.75rem 0; }

    .char-card-tagline {
        margin-bottom: 0.75rem;
        font-size: 1rem;
        line-height: 1.7;
    }

    .char-card-facts {
        gap: 0.4rem;
        font-size: 0.875rem;
    }

    .char-card-admin .comic-btn-sm { font-size: 0.75rem; }
}

/* 统计条：名片墙扉页上的"N 位角色"计数 */
.char-wall-stats {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-top: 1.75rem;
}

.char-wall-stat {
    display: inline-flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.4rem 0.9rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--comic-white);
    box-shadow: var(--comic-shadow-3);
    color: var(--comic-ink);
    font-size: 0.75rem;
    font-weight: 900;
    letter-spacing: 0.06em;
}

.char-wall-stat b {
    font-size: 1.125rem;
    letter-spacing: 0;
}

/* 提示条（成功 / 错误）：墨线 + 硬阴影 + 图标，状态不单靠颜色传达 */
.char-flash {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    margin-bottom: 1.5rem;
    padding: 0.75rem 1rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    box-shadow: var(--comic-shadow-3);
    font-size: 0.75rem;
    font-weight: 900;
    letter-spacing: 0.04em;
    color: var(--comic-white);
}

.char-flash--ok { background: var(--comic-green); }
.char-flash--bad { background: var(--comic-red); }

.char-flash p { margin: 0; }

/* --------------------------------------------------------------------------
   8. 继续浏览（上一个 / 下一个角色）
   -------------------------------------------------------------------------- */

.char-browse {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    margin: 2rem 0 0;
}

@media (min-width: 768px) {
    .char-browse {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 1.5rem;
        margin-top: 3rem;
    }
}

.char-browse-link {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--comic-white);
    box-shadow: var(--comic-shadow-4);
    color: var(--comic-ink);
    text-decoration: none;
    transition: transform var(--comic-duration-move) ease,
                box-shadow var(--comic-duration-move) ease;
}

.char-browse-link:hover {
    transform: translate(2px, 2px);
    box-shadow: var(--comic-shadow-2);
}

.char-browse-link--next {
    text-align: right;
    justify-content: flex-end;
}

.char-browse-label {
    flex: 0 0 auto;
    color: var(--comic-muted);
    font-size: 0.6875rem;
    font-weight: 900;
    letter-spacing: 0.08em;
}

.char-browse-name {
    min-width: 0;
    font-size: 0.9375rem;
    font-weight: 900;
    overflow-wrap: break-word;
}

/* 空态与「有下一位」的链接格同尺寸，但不投影、底色压回纸面：
   读起来是"这一格没有内容"，而不是"这里有个能点的东西没画完"。 */
.char-browse-empty {
    display: flex;
    align-items: center;
    padding: 1rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--comic-paper);
    color: var(--comic-muted);
    font-size: 0.8125rem;
    font-weight: 700;
}

/* --------------------------------------------------------------------------
   9. 编辑页
   -------------------------------------------------------------------------- */

/* 顶栏：返回 / 标题 / 保存。粘住顶部，长表单滚到哪都能就地保存。 */
.char-edit-topbar {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.75rem 1rem;
    border-bottom: var(--comic-border);
    background: var(--comic-paper);
}

.char-edit-topbar-title {
    flex: 1;
    margin: 0;
    min-width: 0;
    font-size: 1rem;
    font-weight: 900;
    letter-spacing: 0.04em;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.char-edit-back {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 0.4rem;
    color: var(--comic-ink);
    font-size: 0.8125rem;
    font-weight: 900;
    text-decoration: none;
    transition: transform var(--comic-duration) ease-out;
}

.char-edit-back:hover {
    transform: translateX(-0.25rem);
}

/* 表单主体：单列居中。★ 行宽上限 ★ 编辑页字段是长文本，
   不限宽的话 1440px 屏上单行能到 200 多字符，眼睛要来回扫。 */
.char-edit-layout {
    max-width: 56rem;
    margin: 0 auto;
    padding: 1.5rem 1rem 3rem;
}

@media (min-width: 768px) {
    .char-edit-layout { padding: 2rem 2rem 4rem; }
}

/* 表单分节：白卡 + 墨线 + 硬阴影，与站内其它表单页同构 */
.char-form-sect {
    position: relative;
    overflow: hidden;
    margin-bottom: 1.25rem;
    padding: 1.25rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--comic-white);
    box-shadow: var(--comic-shadow-4);
}

@media (min-width: 768px) {
    .char-form-sect { padding: 1.5rem; }
}

/* 表单分节的标题行：小号编号徽章 + 图标 + 标题 + 墨色下划线 */
.char-form-head {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0 0 1.25rem;
    padding-bottom: 0.625rem;
    border-bottom: var(--comic-border);
    font-size: 1rem;
    font-weight: 900;
    letter-spacing: 0.04em;
    color: var(--comic-ink);
}

/* 表单里的编号徽章比详情页小一号：表单是干活的界面，
   3.5rem 的徽章在密集字段里会把注意力从输入框上拽走 */
.char-form-no {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    transform: rotate(-6deg);
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--char-color);
    box-shadow: var(--comic-shadow-2);
    font-size: 0.8rem;
    font-weight: 900;
    line-height: 1;
    color: var(--comic-white);
}

/* 字段网格：12 栏在宽屏铺开，窄屏一律单列 */
.char-field-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
}

@media (min-width: 768px) {
    .char-field-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
}

.char-col-4, .char-col-6, .char-col-8, .char-col-12 { grid-column: 1 / -1; }

@media (min-width: 768px) {
    .char-col-4 { grid-column: span 4; }
    .char-col-6 { grid-column: span 6; }
    .char-col-8 { grid-column: span 8; }
    .char-col-12 { grid-column: 1 / -1; }
}

/* 字段下方的说明文字 */
.char-field-hint {
    margin: 0.5rem 0 0;
    color: var(--comic-muted);
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1.6;
}

/* 原生取色器：尺寸必须由 CSS 定（工具类表达不了原生控件的内衬） */
.char-color-input {
    display: flex;
    align-items: stretch;
    gap: 0.5rem;
}

.char-color-input input[type="color"] {
    flex: 0 0 3rem;
    width: 3rem;
    padding: 0;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--comic-white);
    cursor: pointer;
}

.char-color-input input[type="color"]::-webkit-color-swatch-wrapper { padding: 2px; }
.char-color-input input[type="color"]::-webkit-color-swatch { border: none; border-radius: 0; }

.char-color-input .char-color-hex {
    flex: 1;
    min-width: 0;
}

/* ---- 人物关系行 ---- */

.char-rel-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

/* 一条关系 = 一行五格：类型 / 名字 / 外文名 / 关联档案 / 删除。
   ★ 列宽写死比例而不是 auto ★ 删掉一行后若列宽随内容重算，
   剩下的行会横向跳一下 —— 那是"输入框在动"的观感。 */
.char-rel-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.5rem;
    align-items: start;
    padding: 0.75rem;
    border: var(--comic-border);
    border-radius: var(--comic-radius);
    background: var(--comic-paper);
}

@media (min-width: 900px) {
    .char-rel-row {
        grid-template-columns: 1fr 1.2fr 1.2fr 1.2fr auto;
        align-items: center;
    }
}

.char-rel-empty {
    margin: 0.75rem 0 0;
    color: var(--comic-muted);
    font-size: 0.8125rem;
    font-weight: 700;
}

/* 初始态与脚本态共用：脚本给它切 .is-off */
.char-rel-empty.is-off {
    display: none;
}

/* --------------------------------------------------------------------------
   10. 动效兜底
   -------------------------------------------------------------------------- */

/* 减动效偏好下去掉位移，保留全部信息的可见性。
   ★ 翻面只去掉位移、保留透明度交叉渐变 ★ 两面都写成静态的话，
   背面会停在 opacity:0 且再没有 :hover 点亮它 —— 那是"内容彻底看不见"。 */
@media (prefers-reduced-motion: reduce) {
    .char-card,
    .char-card-face,
    .char-card-open,
    .char-browse-link,
    .char-edit-back,
    [data-comic-tilt],
    .comic-badge {
        transition: none;
    }

    /* 立绘倾斜整条关掉：脚本在减动效下压根不挂监听，这里再兜一次底 */
    [data-comic-tilt] {
        transform: none;
    }

    .char-card:hover,
    .char-card:focus-within {
        transform: none;
        box-shadow: var(--comic-shadow-6);
    }

    /* 去掉横向位移，只留可见性切换 */
    .char-card:hover .char-card-face--front,
    .char-card:focus-within .char-card-face--front,
    .char-card:hover .char-card-face--back,
    .char-card:focus-within .char-card-face--back {
        transform: none;
    }

    .char-browse-link:hover {
        transform: none;
        box-shadow: var(--comic-shadow-4);
    }

    .char-edit-back:hover {
        transform: none;
    }

    /* 粘性顶栏在减动效下也留着 —— 它不是动效，是导航可达性 */
}
