/* ============================================================
   css/panels/panels-kudos-flower.css — 小红花（关系纪念）
   ------------------------------------------------------------
   视觉唯一事实来源（TASK-KUDOS-FLOWER-001 Window 2）：
     · KUDOS-02 = 折纸花（六色 / 双折面 / 厚度感 / 轻阴影 / 小幅倾角）
     · KUDOS-01 = 黑板（板框 + 板面 + 粉笔痕）
     · KUDOS-05 = 夸夸纸张（纸的骨架 / 留白 / 语气）
     · KUDOS-04 = 花 -> 折面 -> 纸的同一物体展开（本文件只描述它的几何与过渡）

   「我的」黑板与聊天庆祝**共用**这一份视觉：花的 HTML 由
   js/kudos-flower-core.js 的 KudosFlowerCore.renderer 唯一产出，
   本文件只提供类名与几何；任何一边都不许再画第二套花 / 第二张纸。

   硬规则：
     ① 只动 transform / opacity / filter / 几何属性，绝不出现 transition: all；
     ② 退场一律「淡出 + 几何冻结」，绝不用 instant display:none 当主退场；
     ③ 不做 bounce、不做游戏胜利音、不做 confetti；
     ④ 颜色代表情绪，不代表等级：不许出现等级 / 连续天数 / 积分口径；
     ⑤ prefers-reduced-motion 下取消大位移与 3D 翻折，但保留「花 -> 纸 -> 内容」的层级。

   聊天庆祝层自己的那份样式在 css/chat/chat-kudos.css（它复用本文件的 .kf-flower / .kf-paper）。
   ============================================================ */

/* ------------------------------------------------------------
   一、令牌：六种花色 + 纸与黑板
   ------------------------------------------------------------ */
:root {
    /* 六色（KUDOS-02 已定稿的色彩）：--c 主面 / --c-light 受光面 / --c-deep 背光面 */
    --kf-red: #b8625f;
    --kf-red-light: #d78d88;
    --kf-red-deep: #914643;
    --kf-peach: #d4937f;
    --kf-peach-light: #e7b1a1;
    --kf-peach-deep: #b76e5d;
    --kf-butter: #d7c47d;
    --kf-butter-light: #e8dcae;
    --kf-butter-deep: #ad9c5b;
    --kf-lilac: #ad9bb8;
    --kf-lilac-light: #c5b7cf;
    --kf-lilac-deep: #817091;
    --kf-blue: #829fa8;
    --kf-blue-light: #a8c0c5;
    --kf-blue-deep: #5f818a;
    --kf-green: #92a391;
    --kf-green-light: #b7c2b3;
    --kf-green-deep: #6f826f;

    /* 花色 -> 纸色（KUDOS-05 的六张纸）：纸张骨架同一份，只换色调 */
    --kf-paper-red: #ead1cc;
    --kf-paper-peach: #f0d7cd;
    --kf-paper-butter: #f1e8c8;
    --kf-paper-lilac: #e8e0eb;
    --kf-paper-blue: #dce6e8;
    --kf-paper-green: #dfe7dd;

    /* 黑板（板面固定深色：这是「黑板」这一物件的本体，不随主题变浅） */
    --kf-chalk: #ede8dc;
    --kf-board-frame: linear-gradient(145deg, #777970, #5f635e 50%, #696b64);
    --kf-board-surface:
        radial-gradient(circle at 18% 34%, rgba(245, 238, 222, 0.07), transparent 26%),
        radial-gradient(circle at 73% 68%, rgba(245, 238, 222, 0.055), transparent 29%),
        radial-gradient(circle at 54% 10%, rgba(245, 238, 222, 0.035), transparent 23%),
        linear-gradient(160deg, #29332f 0%, #303a35 48%, #2b3531 100%);

    /* 纸（KUDOS-05） */
    --kf-paper-base: #fffaf3;
    --kf-paper-deep: #f1e4d8;
    --kf-ink: #4d4038;
    --kf-ink-soft: #705e54;
    --kf-ink-meta: #a48b7f;

    --kf-ease: cubic-bezier(0.16, 1, 0.3, 1);
    --kf-serif: "Noto Serif SC", "Songti SC", serif;
    --kf-serif-en: "Cormorant Garamond", "Times New Roman", serif;

    /* 黑板花的一档整体缩放：只用于机身宽度档位（360 / 390 / 430），不参与数据 */
    --kf-board-scale: 1;
}

/* ------------------------------------------------------------
   二、黑板（挂进真实 #sub-home，位置在「我的花园」与「我的资料」之间）
   ------------------------------------------------------------ */
.kf-board-wrap {
    margin-top: 26px;
}
.kf-board-caption {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 10px;
    margin: 0 6px 11px;
}
.kf-board-caption-title {
    font-size: 19px;
    letter-spacing: 0.04em;
    color: var(--text-primary);
}
.kf-board-caption-sub {
    font-size: 11px;
    line-height: 1.45;
    text-align: right;
    color: var(--text-secondary);
}

.kf-board-frame {
    position: relative;
    width: 100%;
    padding: 7px;
    border-radius: 15px 12px 16px 11px;
    background: var(--kf-board-frame);
    box-shadow: 0 16px 34px rgba(73, 64, 59, 0.12), 0 2px 0 rgba(255, 255, 255, 0.52) inset;
}
.kf-board-frame::before {
    content: "";
    position: absolute;
    inset: 3px;
    border: 1px solid rgba(242, 235, 221, 0.17);
    border-radius: 11px 9px 13px 8px;
    pointer-events: none;
}

.kf-board {
    position: relative;
    /* ★ TASK-KUDOS-FLOWER-002 R7：高度由 JS 按花的数量在 320–392 之间给（--kf-board-h），
       14 个预设槽位全部装得下、第 14 朵不贴板底；有上下限，所以花多花少不会让「我的」页跳动。 */
    /* 高度本身不做过渡：板子周围有底板与阴影，跟着高度一起拉伸会发出「整块在抻」的怪味。
       花变多/变少时，是下面的花位各自重新落位（.kf-slot 自己那段过渡），板面一步到位更干净。 */
    height: var(--kf-board-h, 320px);
    overflow: hidden;
    border-radius: 10px 8px 11px 9px;
    perspective: 700px;
    background: var(--kf-board-surface);
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.22) inset, 0 0 0 1px rgba(0, 0, 0, 0.18) inset;
    touch-action: manipulation;
}

.kf-board-copy {
    position: absolute;
    top: 16px;
    left: 18px;
    right: 18px;
    z-index: 4;
    pointer-events: none;
}
.kf-board-copy-title {
    font-size: 17px;
    font-weight: 500;
    letter-spacing: 0.04em;
    color: var(--kf-chalk);
}
.kf-board-copy-sub {
    margin-top: 4px;
    font-size: 11px;
    color: rgba(226, 222, 210, 0.58);
}

.kf-chalk {
    position: absolute;
    z-index: 1;
    pointer-events: none;
    opacity: 0.55;
    filter: blur(0.15px);
}
.kf-chalk.kf-chalk-one {
    left: 18px;
    top: 60px;
    width: 76px;
    height: 1px;
    background: linear-gradient(90deg, rgba(238, 234, 219, 0.22), transparent);
    transform: rotate(-2deg);
}
.kf-chalk.kf-chalk-two {
    right: 20px;
    bottom: 28px;
    width: 90px;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(238, 234, 219, 0.18));
    transform: rotate(3deg);
}
.kf-smudge {
    position: absolute;
    width: 78px;
    height: 36px;
    border-radius: 50%;
    opacity: 0.11;
    filter: blur(6px);
    background: #d9d3c5;
    pointer-events: none;
}
.kf-smudge.a { left: -15px; bottom: 22px; transform: rotate(-8deg); }
.kf-smudge.b { right: -17px; top: 96px; transform: rotate(12deg); }

/* 花层：花用归一化坐标（0–100 的百分比）落在板面上，
   位置 / 旋转 / 缩放全部来自服务端的 boardPosition，前端不另算一套。 */
.kf-board-layer {
    position: absolute;
    inset: 0;
    perspective: 700px;
}

.kf-slot {
    position: absolute;
    width: 54px;
    height: 54px;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transform:
        translate(-50%, -50%)
        rotate(var(--kf-rot, 0deg))
        scale(calc(var(--kf-scale, 1) * var(--kf-board-scale)));
    transform-origin: 50% 58%;
    /* 位置只在「落位 / 回流」时过渡；拖动期间由 JS 直接写 left/top，不走过渡 */
    transition: transform 0.3s var(--kf-ease), filter 0.22s ease;
    will-change: left, top, transform;
}
.kf-slot .kf-flower {
    position: absolute;
    inset: 0;
    left: auto;
    top: auto;
    translate: 0 0;
}
.kf-slot.is-pressed .kf-flower {
    transition: transform 0.16s ease, filter 0.16s ease;
    transform: rotate(var(--rz, 0deg)) rotateX(var(--rx, 4deg)) rotateY(var(--ry, -3deg)) scale(1.035);
}
.kf-slot.is-lifted {
    transition: filter 0.22s ease;
    filter: drop-shadow(0 14px 12px rgba(0, 0, 0, 0.3));
    z-index: 6;
}
/* ★ R6：拖动与落位**都不许**给 left/top 挂过渡 —— 拖动期间 JS 是逐帧直接写这两个值的，
   再挂 0.3s 过渡就变成「每帧再追 0.3 秒」：表现为发飘、回弹、拖不动（甲方实锤的根因）。
   「跟手」＝写多少就是多少；只有 transform（抬起/落下/折回）才过渡。 */
.kf-slot.is-moving {
    transition: transform 0.22s var(--kf-ease), filter 0.22s ease;
}
.kf-slot.is-settling {
    transition: transform 0.26s var(--kf-ease), filter 0.22s ease;
}

/* 删除（KUDOS-06）：花先回到黑板原处，再在原处轻柔折回 + 淡出，随后其它花自然 Reflow */
.kf-slot.is-folding .kf-flower {
    transition: transform 0.52s var(--kf-ease), filter 0.42s ease;
    transform: rotate(var(--rz, 0deg)) rotateX(74deg) rotateY(var(--ry, -3deg)) scale(0.34, 0.2);
    filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.16));
}
.kf-slot.is-folding {
    opacity: 0;
    transition: opacity 0.46s ease 0.12s;
}
/* 撤回：放回来的那一朵在原处轻轻出现 */
.kf-slot.is-back .kf-flower {
    animation: kfBack 0.46s var(--kf-ease) both;
}
@keyframes kfBack {
    from { opacity: 0; transform: rotate(var(--rz, 0deg)) rotateX(46deg) rotateY(var(--ry, -3deg)) scale(0.62); }
    to { opacity: 1; transform: rotate(var(--rz, 0deg)) rotateX(var(--rx, 4deg)) rotateY(var(--ry, -3deg)) scale(1); }
}

/* 空状态：温柔，不做「奖励中心暂无数据」 */
.kf-board-empty {
    position: absolute;
    inset: 66px 25px 20px;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: rgba(235, 229, 215, 0.8);
    pointer-events: none;
    transition: opacity 0.42s ease;
}
.kf-board-empty[hidden] { display: none; }
.kf-board-empty.is-out { opacity: 0; }
.kf-empty-line {
    width: 34px;
    height: 1px;
    margin-bottom: 13px;
    background: rgba(235, 229, 215, 0.28);
}
.kf-empty-title {
    font-size: 15px;
    letter-spacing: 0.04em;
}
.kf-empty-sub {
    margin-top: 7px;
    font-size: 11px;
    line-height: 1.8;
    color: rgba(224, 220, 209, 0.52);
}

/* ------------------------------------------------------------
   三、折纸花（KUDOS-02 定的花型，唯一一份几何）
   ------------------------------------------------------------ */
.kf-flower {
    --c: var(--kf-red);
    --c-light: var(--kf-red-light);
    --c-deep: var(--kf-red-deep);
    --s: 1;
    position: relative;
    width: 54px;
    height: 54px;
    transform: rotate(var(--rz, 0deg)) rotateX(var(--rx, 4deg)) rotateY(var(--ry, -3deg)) scale(var(--s));
    transform-style: preserve-3d;
    transform-origin: 50% 58%;
    filter: drop-shadow(0 5px 5px rgba(0, 0, 0, 0.22));
    pointer-events: none;
}

.kf-flower-edge {
    position: absolute;
    inset: 0;
    clip-path: polygon(50% 0%, 94% 33%, 79% 100%, 50% 83%, 21% 100%, 6% 33%);
    background: rgba(62, 39, 35, 0.38);
    transform: translateY(2px);
}

.kf-petal {
    position: absolute;
    left: 50%;
    top: 58%;
    width: 27px;
    height: 36px;
    transform-origin: 50% 100%;
    transform: translate(-50%, -100%) rotate(var(--rot));
    clip-path: polygon(50% 0%, 94% 31%, 78% 100%, 50% 82%, 22% 100%, 6% 31%);
    overflow: hidden;
}
.kf-petal::before,
.kf-petal::after {
    content: "";
    position: absolute;
    inset: 0;
}
.kf-petal::before {
    background: linear-gradient(135deg, var(--c-light) 0%, var(--c) 52%, var(--c-deep) 100%);
    clip-path: polygon(50% 0%, 50% 82%, 6% 31%);
}
.kf-petal::after {
    background: linear-gradient(225deg, var(--c-light) 0%, var(--c) 52%, var(--c-deep) 100%);
    clip-path: polygon(50% 0%, 94% 31%, 78% 100%, 50% 82%);
}
.kf-crease {
    position: absolute;
    left: 50%;
    top: 0;
    width: 1px;
    height: 84%;
    background: rgba(91, 57, 52, 0.26);
    transform: translateX(-50%) rotate(0.6deg);
    transform-origin: top center;
}
.kf-flower .p1 { --rot: 0deg; }
.kf-flower .p2 { --rot: 60deg; }
.kf-flower .p3 { --rot: 120deg; }
.kf-flower .p4 { --rot: 180deg; }
.kf-flower .p5 { --rot: 240deg; }
.kf-flower .p6 { --rot: 300deg; }

.kf-center-edge {
    position: absolute;
    left: 50%;
    top: 57.5%;
    width: 15px;
    height: 15px;
    transform: translate(-50%, -51%);
    clip-path: polygon(50% 0%, 100% 38%, 74% 100%, 30% 88%, 0 40%);
    background: rgba(69, 41, 37, 0.42);
    z-index: 7;
}
.kf-center {
    position: absolute;
    left: 50%;
    top: 56.5%;
    width: 17px;
    height: 16px;
    transform: translate(-50%, -50%);
    clip-path: polygon(50% 0%, 100% 38%, 74% 100%, 30% 88%, 0 40%);
    background: linear-gradient(145deg, #e0b5ae, #b05b57 68%, #98504b);
    z-index: 8;
}
.kf-center::after {
    content: "";
    position: absolute;
    inset: 3px 5px 3px 4px;
    background: linear-gradient(140deg, rgba(255, 247, 243, 0.5), rgba(255, 247, 243, 0));
    clip-path: polygon(50% 0%, 100% 45%, 43% 100%, 10% 40%);
}

/* 六色：挂在花这一层上，纸与庆祝层取同一组值 */
.kf-flower[data-kf-color="red"] { --c: var(--kf-red); --c-light: var(--kf-red-light); --c-deep: var(--kf-red-deep); }
.kf-flower[data-kf-color="peach"] { --c: var(--kf-peach); --c-light: var(--kf-peach-light); --c-deep: var(--kf-peach-deep); }
.kf-flower[data-kf-color="butter"] { --c: var(--kf-butter); --c-light: var(--kf-butter-light); --c-deep: var(--kf-butter-deep); }
.kf-flower[data-kf-color="lilac"] { --c: var(--kf-lilac); --c-light: var(--kf-lilac-light); --c-deep: var(--kf-lilac-deep); }
.kf-flower[data-kf-color="blue"] { --c: var(--kf-blue); --c-light: var(--kf-blue-light); --c-deep: var(--kf-blue-deep); }
.kf-flower[data-kf-color="green"] { --c: var(--kf-green); --c-light: var(--kf-green-light); --c-deep: var(--kf-green-deep); }

/* ------------------------------------------------------------
   四、夸夸纸张（KUDOS-05 的视觉；层级 = 日期是 metadata，
      「为什么给你贴了一朵」与「想对你说」才是正文）
   ------------------------------------------------------------ */
/* 展开层必须自己是「有宽度也有高度」的定位层：
   只写 flex + justify-content 的话它宽高都是 0，纸在里面会被压成几个像素（实测 2×2 / 0 高）。
   位置与尺寸全部由 core 按落点和承载层的真实尺寸算好（--kf-left/--kf-top/--kf-w/--kf-h），
   盒子按内容长，中心对在落点上；竖屏 360~430 都自适应，CSS 里不写死任何像素高度。 */
.kf-paper-host {
    position: absolute;
    left: var(--kf-left, 0px);
    top: var(--kf-top, 0px);
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
.kf-paper-host.is-live { pointer-events: auto; }
/* 关键尺寸靠 JS 测出来（core 按落点与承载层的真实尺寸算），CSS 只兜底。
   四种 inset 加百分比在这个盒子上会被算成 0（实测 390 宽的层里宽高都是 0），
   所以绝不用 top/bottom 百分比去撑这个盒子。 */
.kf-paper-host {
    width: var(--kf-w, 100%);
    height: var(--kf-h, auto);
}

/* ★ TASK-KUDOS-FLOWER-002 R2：**页面级浮层**（黑板那一套专用）。
   「我的」黑板上点开一朵花时，纸绝不再活在黑板里（黑板是固定高 + overflow:hidden，
   纸在里头长不开也关不掉）。这一层挂在 #app 内、限宽 480、盖住整屏：
     .kf-fx-root > .kf-fx[data-variant="board"] > .kf-wash（半透明暖黑）+ .kf-hero（花）+ .kf-paper-host（纸）
   它与聊天那一条链完全同构（同一套 JS、同一套花与纸），只是承载层换成了整屏。 */
.kf-fx-root {
    position: absolute;
    inset: 0;
    z-index: 620;
    pointer-events: none;
}
/* 展开层必须自己是「有宽度也有高度」的定位层：
   只写 flex + justify-content 的话它宽高都是 0，纸在里面会被压成几个像素（实测 2×2 / 0 高）。
   黑板这一版直接铺满浮层：纸在整屏里居中、由内容决定高矮，不再受落点盒子的约束。
   （.kf-fx 的基础态在 css/chat/chat-kudos.css：opacity:0 + overflow:hidden + contain:paint，
     那几项对黑板这一版全都要松掉——黑板的花要能飞到板外、也要能在整屏里展开。） */
.kf-fx-root .kf-fx[data-variant="board"] {
    position: absolute;
    inset: 0;
    opacity: 1;
    overflow: visible;
    contain: none;
    transition: none;
}
/* 这一朵花：占位与整屏中心一致（--dx/--dy 是它相对黑板落点的偏移） */
.kf-fx-root .kf-fx[data-variant="board"] .kf-hero {
    position: absolute;
    left: 50%;
    top: 50%;
    z-index: 30;
    width: 58px;
    height: 58px;
    transform: translate(-50%, -50%);
    transform-style: preserve-3d;
    pointer-events: none;
    opacity: 0;
    will-change: transform;
}
.kf-fx-root .kf-fx[data-variant="board"] .kf-hero .kf-flower {
    position: absolute;
    inset: 0;
    left: auto;
    top: auto;
    width: 100%;
    height: 100%;
    translate: 0 0;
    --s: 1;
}
.kf-fx-root .kf-fx[data-variant="board"] .kf-paper-host {
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 500;
    padding: 16px 0;
    box-sizing: border-box;
}
.kf-fx-root .kf-fx[data-variant="board"] .kf-paper {
    /* 盒子宽写死在纸自己身上：盒子（.kf-sheet）的宽由内容决定，纸里面绝不能再写百分比宽
       ——那会跟盒子互相解算，实测纸被算成半个屏幕宽的一条 */
    width: min(292px, calc(100vw - 64px));
    max-height: 74vh;
}
.kf-fx-root .kf-fx[data-variant="board"] .kf-wash {
    opacity: 0;
    transition: opacity 0.38s ease;
}
.kf-fx-root .kf-fx[data-variant="board"].is-on .kf-wash { opacity: 1; }
.kf-fx-root .kf-fx[data-variant="board"].is-paper-open .kf-wash { pointer-events: auto; }

/* ★ TASK-KUDOS-FLOWER-003：黑板这一份的展开**必须与 KUDOS-04 的链路是同一条**
   （花落到落点 → 逐瓣翻过去 → 折面折包 → 纸从这一朵花的位置长出来 → 暖黑 → 内容）。
   原来这里挂的是另写的一套关键帧（`kfBoardFly` / `kfBoardFold` / `kfBoardBack`）：
   整朵花连花瓣一起被缩到 8.5%、转 -5° 淡掉，纸再从**屏幕正中**凭空长出来——
   看起来是「花被压成一个点、纸冒出来」，不是花展开（甲方实拍确认）。
   那三个关键帧已整段删除，下面换成与聊天那一份同一件事：花的几何**原地不动**，
   花瓣逐瓣翻过去、花芯与纸同点交替，纸从落点长到屏幕中央。 */

/* 花瓣基础态：翻过去的折角（花没展开时花瓣是完整的，见下面 .is-on 那条） */
.kf-fx-root .kf-fx[data-variant="board"] .kf-hero .kf-flower .kf-petal {
    transition: transform 0.56s var(--kf-ease), opacity 0.42s ease;
    transform: translate(-50%, -101%) rotate(var(--rot)) rotateX(82deg) translateZ(-4px) translateY(7px) scale(0.76, 0.62);
    opacity: 0.16;
}
/* 展开的**第一段**：花在落点上是完整的一朵（没有这条，花瓣会在加 .is-on 的那一刻
   直接跳到折角态，等于「一出现就是折好的」） */
.kf-fx-root .kf-fx[data-variant="board"].is-on .kf-hero .kf-flower .kf-petal {
    transform: translate(-50%, -100%) rotate(var(--rot)) rotateX(0deg) translateZ(0) translateY(0) scale(1);
    opacity: 1;
}
/* 展开的**第二段**：逐瓣翻过去（KUDOS-04 的错峰，与聊天同一套：0.76s 起、每瓣 +0.035s） */
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero .kf-flower .kf-petal {
    transform: translate(-50%, -101%) rotate(var(--rot)) rotateX(82deg) translateZ(-4px) translateY(7px) scale(0.76, 0.62);
    opacity: 0.16;
}
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero .kf-flower .p1 { transition-delay: 0.11s; }
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero .kf-flower .p2 { transition-delay: 0.145s; }
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero .kf-flower .p3 { transition-delay: 0.18s; }
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero .kf-flower .p4 { transition-delay: 0.215s; }
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero .kf-flower .p5 { transition-delay: 0.25s; }
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero .kf-flower .p6 { transition-delay: 0.285s; }
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero .kf-flower .kf-flower-edge { opacity: 0.18; transition: opacity 0.44s ease 0.22s; }
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero .kf-flower .kf-center-edge { opacity: 0.12; transition: opacity 0.36s ease 0.3s; }
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero .kf-flower .kf-center {
    opacity: 0.08;
    transform: translate(-50%, -50%) scale(0.66);
    transition: opacity 0.36s ease 0.3s, transform 0.42s var(--kf-ease) 0.3s;
}

/* 第一段：花**就在她点的那一朵上**，不飞、不缩、不淡。
   （原来这里挂 kfBoardFly 把它飞到屏幕正中再折——她点了左边那朵，花却先跑到屏幕中间，
     看起来就是「打开的这朵不是她点的那一朵」。落点变量 --dx/--dy 仍然要用：
     它是「这一朵在整屏浮层里的位置」，折包与纸都从同一个点长出来。） */
.kf-fx-root .kf-fx[data-variant="board"].is-on .kf-hero,
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero,
.kf-fx-root .kf-fx[data-variant="board"].is-landed .kf-hero {
    opacity: 1;
    transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px));
}

/* 折面折包（KUDOS-04 的折叠小包）：从花芯那一点长出来、翻一下、随后被纸接住。
   它就是「那句话原来真的藏在花里面」那层桥——没有它，纸看起来就是凭空出现的。
   位置用的是同一个落点（--dx/--dy，和花一模一样），所以纸是从这朵花的位置长出来的。 */
.kf-fx-root .kf-fx[data-variant="board"] .kf-packet {
    position: absolute;
    left: 50%;
    top: 50%;
    z-index: 310;
    width: 30px;
    height: 40px;
    margin: -20px 0 0 -15px;
    opacity: 0;
    pointer-events: none;
    background: linear-gradient(148deg, var(--kf-paper-red) 0%, #fffaf3 100%);
    clip-path: polygon(50% 0%, 100% 30%, 72% 100%, 18% 83%, 0 36%);
    box-shadow: 0 7px 13px rgba(83, 62, 50, 0.16);
    will-change: transform, opacity;
}
.kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-packet {
    animation: kfBoardPacket 0.74s var(--kf-ease) both;
}
@keyframes kfBoardPacket {
    0% { opacity: 0; transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(-9deg) scale(0.2); }
    26% { opacity: 1; transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(-3deg) scale(1); }
    56% { opacity: 1; transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(-3deg) scale(0.94); }
    100% { opacity: 0; transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(-2deg) scale(0.86); }
}
/* 花芯与包同点交替：花把那句话交出去之后自己安静淡掉（不是被压成一个点）。
   时机刻意排在**纸成形之后**（打开链在 1.49s 加 .is-paper-open，这一条 1.22s 起、
   1.82s 落定）：花瓣翻完 → 折包接住 → 纸长出来 → 花才退场。
   原来排在落点那一刻（0.86s 就淡完），结果花瓣刚开始折、花已经在化掉了。 */
.kf-fx-root .kf-fx[data-variant="board"].is-paper-open .kf-hero {
    animation: kfBoardGive 0.6s var(--kf-ease) 0.22s both;
}
@keyframes kfBoardGive {
    0% { opacity: 1; transform: translate(-50%, -50%); }
    55% { opacity: 0.9; transform: translate(-50%, -50%); }
    100% { opacity: 0; transform: translate(-50%, -50%); }
}

/* 纸的种子态：**就在这朵花的落点上**（--dx/--dy 与花同一处），折包那么大（约 33px） */
.kf-fx-root .kf-fx[data-variant="board"] .kf-sheet {
    position: absolute;
    left: 50%;
    top: 50%;
    z-index: 500;
    transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px)) scale(0.11);
    opacity: 0;
    transition: transform 0.72s var(--kf-ease), opacity 0.34s ease;
}
/* 纸成形：从落点长到屏幕中央、转正、完全显影 */
.kf-fx-root .kf-fx[data-variant="board"].is-paper-open .kf-sheet {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
}
/* 聊天那一份给纸的盒子写过 276×(378 或层的 100%-96) 的硬尺寸（css/chat/chat-kudos.css），
   那是「贴着气泡那一带展开」的尺寸；黑板这一版是整屏浮层，盒子交给纸自己（纸的宽写死了
   min(292px, 整层 - 46px)），别再套聊天那个盒子的尺寸 —— 否则纸的宽度百分比会去
   解算这个「宽由内容决定」的盒子，循环一圈后被算成半个屏幕宽的一条（真量过：
   390 屏上纸只有 149×562，取下的按钮被压到 40px 以下）。 */
.kf-fx-root .kf-fx[data-variant="board"] .kf-sheet {
    width: auto !important;
    height: auto !important;
}
/* 收起：**严格反向走一遍**（KUDOS-04 的反向原则：纸不折、不缩、不转、不形变，
   只是变透明地离场；几何全程冻结）
   ①纸先退（0.42s 淡掉，不缩回一个点）②花瓣一片片翻回来（0.4s 起，错峰）③花整朵淡掉
   收完由 JS 撤层（1080ms → 1560ms，给逐瓣长回留够时间）。 */
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-sheet {
    opacity: 0;
    transition: opacity 0.42s ease 0.18s;
}
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero {
    animation: kfBoardFade 0.62s var(--kf-ease) 0.94s both;
}
@keyframes kfBoardFade {
    0% { opacity: 1; transform: translate(-50%, -50%); }
    100% { opacity: 0; transform: translate(-50%, -50%); }
}
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero .kf-flower .kf-petal {
    transform: translate(-50%, -100%) rotate(var(--rot)) rotateX(0deg) translateZ(0) translateY(0) scale(1);
    opacity: 1;
}
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero .kf-flower .p1 { transition-delay: 0.4s; }
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero .kf-flower .p2 { transition-delay: 0.425s; }
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero .kf-flower .p3 { transition-delay: 0.45s; }
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero .kf-flower .p4 { transition-delay: 0.475s; }
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero .kf-flower .p5 { transition-delay: 0.5s; }
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero .kf-flower .p6 { transition-delay: 0.525s; }
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero .kf-flower .kf-flower-edge,
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero .kf-flower .kf-center-edge { opacity: 1; transition: opacity 0.34s ease 0.42s; }
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero .kf-flower .kf-center {
    opacity: 0.92;
    transform: translate(-50%, -50%) scale(1);
    transition: opacity 0.34s ease 0.42s, transform 0.42s var(--kf-ease) 0.42s;
}
/* 纸里那句话：打开时在 0.9s 后抵达，收起时立刻先走（内容先离场，纸再退） */
.kf-fx-root .kf-fx[data-variant="board"].is-paper-open .kf-paper-body {
    opacity: 1;
    transform: translateY(0);
    transition: opacity 0.5s ease, transform 0.38s var(--kf-ease);
    transition-delay: 0.9s;
}
.kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-paper-body {
    opacity: 0;
    transform: translateY(4px);
    transition-delay: 0s;
}
@media (prefers-reduced-motion: reduce) {
    .kf-fx-root .kf-fx[data-variant="board"].is-on .kf-hero,
    .kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-hero,
    .kf-fx-root .kf-fx[data-variant="board"].is-paper-open .kf-hero,
    .kf-fx-root .kf-fx[data-variant="board"].is-closing .kf-hero {
        animation: none;
        opacity: 1;
    }
    .kf-fx-root .kf-fx[data-variant="board"].is-landing .kf-packet { animation: none; opacity: 0; }
    .kf-fx-root .kf-fx[data-variant="board"] .kf-sheet,
    .kf-fx-root .kf-fx[data-variant="board"].is-on .kf-wash {
        transition: none;
    }
}

/* 撤回条（KUDOS-06）：取下之后短暂出现，点一下就放回原处。不弹系统确认框。 */
.kf-undo {
    position: absolute;
    left: 50%;
    bottom: 12px;
    z-index: 8;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 10px 7px 13px;
    border: 1px solid rgba(119, 93, 78, 0.1);
    border-radius: 999px;
    background: rgba(255, 250, 246, 0.94);
    box-shadow: 0 10px 24px rgba(90, 68, 55, 0.12);
    color: #806e64;
    font-size: 11px;
    white-space: nowrap;
    transform: translate(-50%, 10px);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease, transform 0.4s var(--kf-ease);
}
.kf-undo.is-on {
    opacity: 1;
    transform: translate(-50%, 0);
    pointer-events: auto;
}
.kf-undo-text { letter-spacing: 0.02em; }
.kf-undo-btn {
    height: 24px;
    padding: 0 8px;
    border: 0;
    border-left: 1px solid rgba(119, 93, 78, 0.12);
    background: transparent;
    color: #8f5d59;
    font: inherit;
    font-size: 11px;
    cursor: pointer;
    transition: transform 0.18s ease, color 0.18s ease;
}
.kf-undo-btn:active { transform: scale(0.97); color: #7c4a45; }

.kf-paper {
    --paper: var(--kf-paper-base);
    --paper-deep: var(--kf-paper-deep);
    --accent: var(--kf-red);
    --accent-soft: var(--kf-paper-red);
    --accent-deep: var(--kf-red-deep);
    position: relative;
    width: min(292px, calc(100% - 44px));
    /* 它是展开层里的 flex 子项：不写这句，flex 会把它压到定位层高度以下
       （实测纸被压成 53px 高、正文溢出看不见）——纸的高由它自己的内容决定 */
    flex: 0 0 auto;
    max-height: 74vh;
    padding: 29px 27px 26px;
    transform: rotate(-0.7deg);
    isolation: isolate;
    overflow: hidden;
    color: var(--kf-ink);
    background:
        radial-gradient(ellipse at 18% 8%, rgba(255, 255, 255, 0.93), transparent 22%),
        radial-gradient(ellipse at 86% 92%, rgba(160, 116, 92, 0.065), transparent 25%),
        linear-gradient(141deg, var(--paper) 0%, var(--paper) 63%, var(--paper-deep) 100%);
    border: 1px solid rgba(127, 94, 76, 0.1);
    box-shadow:
        0 22px 38px rgba(83, 62, 50, 0.16),
        0 7px 13px rgba(83, 62, 50, 0.08),
        5px 8px 0 rgba(174, 135, 111, 0.06),
        0 1px 0 rgba(255, 255, 255, 0.9) inset;
    clip-path: polygon(
        1.2% 0.8%, 99.1% 1.2%, 98.8% 18%,
        100% 38%, 98.9% 61%, 99.2% 98.7%,
        76% 99.4%, 51% 98.8%, 27% 99.6%,
        2% 98.4%, 0.7% 73%, 1.4% 47%, 0.4% 22%
    );
}
.kf-paper::before {
    content: "";
    position: absolute;
    inset: 0;
    opacity: 0.42;
    background:
        repeating-linear-gradient(8deg, rgba(95, 70, 54, 0.032) 0 1px, transparent 1px 5px),
        repeating-linear-gradient(94deg, rgba(255, 255, 255, 0.18) 0 1px, transparent 1px 8px),
        radial-gradient(circle at 42% 46%, rgba(255, 255, 255, 0.42), transparent 34%);
    mix-blend-mode: multiply;
    pointer-events: none;
}
.kf-paper::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    width: 41px;
    height: 41px;
    background: linear-gradient(225deg, rgba(255, 255, 255, 0.85), rgba(242, 225, 211, 0.42) 56%, transparent 57%);
    clip-path: polygon(100% 0, 100% 100%, 0 0);
    opacity: 0.65;
    pointer-events: none;
}
.kf-paper-foldv {
    position: absolute;
    top: 52px;
    bottom: 32px;
    left: 76%;
    width: 1px;
    background: linear-gradient(180deg, transparent, rgba(111, 81, 64, 0.065) 18%, rgba(255, 255, 255, 0.33) 49%, rgba(111, 81, 64, 0.05) 82%, transparent);
    transform: rotate(1.1deg);
    pointer-events: none;
}
.kf-paper-foldh {
    position: absolute;
    left: 12%;
    right: 12%;
    top: 64%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(111, 81, 64, 0.05) 14%, rgba(255, 255, 255, 0.32) 51%, rgba(111, 81, 64, 0.045) 87%, transparent);
    transform: rotate(-1deg);
    pointer-events: none;
}

.kf-paper-body {
    position: relative;
    z-index: 1;
    /* 黑板这张纸走正常文档流：纸的高由内容撑出来。
       （聊天那一份是「一张固定尺寸的纸 + 内部绝对定位的正文」，样式在 chat-kudos.css 里
        按 .kf-sheet 作用域写；两边共用同一套外观，但版式约束不能互相串。）
       没有这句，纸会被压成几十像素、正文全被裁掉——真机与真浏览器都量过。 */
    display: block;
    overflow: visible;
}
.kf-paper-meta {
    text-align: right;
    font-family: var(--kf-serif-en);
    font-size: 12px;
    letter-spacing: 0.16em;
    color: var(--kf-ink-meta);
}
.kf-paper-mark {
    margin-top: 24px;
}
.kf-paper-line {
    display: block;
    width: 38px;
    height: 1px;
    margin-bottom: 13px;
    background: linear-gradient(90deg, var(--accent-deep), var(--accent-soft));
    opacity: 0.78;
}
.kf-paper-heading {
    margin: 0;
    font-size: 24px;
    font-weight: 400;
    line-height: 1.48;
    letter-spacing: 0.015em;
    color: #4b3d36;
}
.kf-paper-reason {
    margin: 15px 0 0;
    font-size: 14px;
    line-height: 2;
    letter-spacing: 0.01em;
    color: var(--kf-ink-soft);
    overflow-wrap: anywhere;
}
.kf-paper-note {
    margin-top: 26px;
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--accent-deep);
    font-size: 14px;
}
.kf-paper-note::before {
    content: "";
    width: 18px;
    height: 1px;
    background: var(--accent);
    opacity: 0.72;
}
.kf-paper-message {
    margin: 15px 0 0;
    font-size: 14px;
    line-height: 2;
    color: var(--kf-ink-soft);
    overflow-wrap: anywhere;
}
.kf-paper-seal {
    position: relative;
    width: 26px;
    height: 26px;
    margin: 24px 0 0 auto;
    border-radius: 50%;
    border: 1px solid rgba(138, 112, 98, 0.55);
    opacity: 0.72;
}
.kf-paper-seal::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 12px;
    height: 12px;
    transform: translate(-50%, -50%) rotate(30deg);
    background: var(--accent);
    clip-path: polygon(50% 0%, 94% 31%, 78% 100%, 50% 82%, 22% 100%, 6% 31%);
}
/* 纸的页脚：左边一枚花印，右边「从黑板取下」（只出现在「我的」黑板上） */
.kf-paper-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    /* 页脚自身就是那个 44px 触摸条：写在页脚上，按钮与花印自然都在里面，
       不会被行高或外边距压回 23px。
       flex: 0 0 auto 是必须的：纸的盒子比它的内容矮时，flex 会把页脚一起压扁
       （实测按钮从 44 掉到 40，触摸目标不达标），页脚不许被压。 */
    flex: 0 0 auto;
    min-height: 44px;
    margin-top: 20px;
}
.kf-paper-seal-inline { margin: 0; flex: none; }
.kf-paper-dismiss {
    /* 触摸目标只按高度撑（44px），不靠加宽 —— 纸上的字距才不会被撑开 */
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    flex: 0 0 auto;
    padding: 0 2px;
    border: 0;
    background: none;
    font-family: inherit;
    font-size: 12.5px;
    letter-spacing: 0.05em;
    color: rgba(112, 94, 84, 0.78);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: color 0.2s ease, opacity 0.2s ease;
}
.kf-paper-dismiss:active { color: var(--accent-deep); opacity: 0.9; }

/* 一次操作结束后的轻声反馈（不是弹窗、不是 toast，自己会走） */
.kf-say {
    position: absolute;
    left: 50%;
    bottom: 18px;
    z-index: 9;
    max-width: 80%;
    padding: 8px 15px;
    border-radius: 999px;
    background: rgba(30, 36, 33, 0.72);
    color: rgba(240, 236, 226, 0.94);
    font-size: 12px;
    letter-spacing: 0.04em;
    text-align: center;
    opacity: 0;
    transform: translate(-50%, 8px);
    pointer-events: none;
    transition: opacity 0.28s ease, transform 0.32s var(--kf-ease);
}
.kf-say.is-on { opacity: 1; transform: translate(-50%, 0); }

.kf-paper-close {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 3;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: #766258;
    opacity: 0.66;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: opacity 0.22s ease, transform 0.16s ease;
}
.kf-paper-close::before,
.kf-paper-close::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 14px;
    height: 1px;
    border-radius: 99px;
    background: currentColor;
}
.kf-paper-close::before { transform: translate(-50%, -50%) rotate(45deg); }
.kf-paper-close::after { transform: translate(-50%, -50%) rotate(-45deg); }
.kf-paper-close:active { transform: scale(0.9); opacity: 1; }

/* 纸张的六种纸色（与花色一一对应） */
.kf-paper[data-kf-color="red"] { --accent: var(--kf-red); --accent-soft: var(--kf-paper-red); --accent-deep: var(--kf-red-deep); }
.kf-paper[data-kf-color="peach"] { --accent: var(--kf-peach); --accent-soft: var(--kf-paper-peach); --accent-deep: var(--kf-peach-deep); }
.kf-paper[data-kf-color="butter"] { --accent: var(--kf-butter); --accent-soft: var(--kf-paper-butter); --accent-deep: var(--kf-butter-deep); }
.kf-paper[data-kf-color="lilac"] { --accent: var(--kf-lilac); --accent-soft: var(--kf-paper-lilac); --accent-deep: var(--kf-lilac-deep); }
.kf-paper[data-kf-color="blue"] { --accent: var(--kf-blue); --accent-soft: var(--kf-paper-blue); --accent-deep: var(--kf-blue-deep); }
.kf-paper[data-kf-color="green"] { --accent: var(--kf-green); --accent-soft: var(--kf-paper-green); --accent-deep: var(--kf-green-deep); }

/* ------------------------------------------------------------
   五、机身宽度档位（360 / 390 / 430，含 <370 窄屏与 400+ 大屏）
   ------------------------------------------------------------ */
@media (max-width: 374px) {
    .kf-board-wrap { --kf-board-scale: 0.9; }
    /* 窄屏：只把高度的下限/上限压一点（具体值仍由 JS 按花的数量给，不许写死） */
    .kf-board { min-height: 296px; }
    .kf-board-caption-title { font-size: 18px; }
    .kf-board-copy-sub { font-size: 10.5px; }
    .kf-paper { padding: 25px 22px 22px; }
    .kf-paper-heading { font-size: 22px; }
    .kf-paper-reason,
    .kf-paper-message,
    .kf-paper-note { font-size: 13px; }
}
@media (min-width: 400px) {
    .kf-board-wrap { --kf-board-scale: 1.06; }
}
@media (min-width: 480px) {
    .kf-board-wrap { --kf-board-scale: 1.12; }
}

/* ------------------------------------------------------------
   六、减少动效：取消大位移与 3D 翻折，保留「花 -> 纸 -> 内容」的层级
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
    .kf-slot,
    .kf-slot.is-pressed .kf-flower,
    .kf-slot.is-moving,
    .kf-slot.is-settling,
    .kf-slot.is-folding .kf-flower,
    .kf-board-empty,
    .kf-paper-close {
        transition: none;
    }
    .kf-slot.is-lifted { filter: none; }
    .kf-slot.is-folding .kf-flower {
        transform: rotate(var(--rz, 0deg)) rotateX(0deg) rotateY(var(--ry, -3deg)) scale(0.55);
    }
}
