/* ============================================================================
 * festival.css —— 青志社团 · 节日彩蛋装饰 (v84)
 * ----------------------------------------------------------------------------
 * 【两条铁律（用户明确叮嘱）】
 *  1. **「落叶飘零」绝不能被替换或削弱** —— 那是用户点名喜欢的效果，
 *     属"背景 vs 前景"。国庆/春节等强节日期间，季节层**降权到 opacity:.35**，
 *     不是消失（见文末 §季节让位）。
 *  2. **彩蛋层只写 --fest* 变量，绝不碰 --bg / --card / --tx**
 *     ⇒ 关掉彩蛋后界面 100% 回到原样、零残留。
 *     全部装饰挂在 [data-festival] 属性选择器下⇒ 移除该属性即彻底还原。
 *
 * 【装饰全部纯 CSS / 内联 SVG，零新增图片】
 *   横幅插画已改成 assets/season/banner-*.jpg 位图，彩蛋**不再往横幅里塞图**，
 *   只用 CSS 角饰 + 边缘粒子。
 *
 * 【铁律】
 *  - 类名一律 fest- 前缀
 *  - 禁硬编码灰色（一律 var(--tx2)/var(--tx3)/var(--line)）
 *  - 装饰层 pointer-events:none + z-index 低（不抢内容）
 *  - 全局纳入 prefers-reduced-motion
 * ========================================================================== */

/* ============================================================================
 * 一、节日配色（--fest 变量）
 *每套节日一组「主色 + 辅色」。深色模式**成套给值**（项目历史高发：暗色露白底）。
 * ⚠️ 只定义 --fest / --fest-2 / --fest-soft 三个，**不动任何底色变量**。
 * ========================================================================== */
[data-festival] {
  --fest: #c0392b;
  --fest-2: #f5c542;
  --fest-soft: rgba(192, 57, 43, .12);
}
/* 公历 */
[data-festival="newyear"]      { --fest:#c0392b; --fest-2:#e8d9a0; --fest-soft:rgba(192,57,43,.12) }
[data-festival="valentine"]    { --fest:#e0557b; --fest-2:#f7a8c0; --fest-soft:rgba(224,85,123,.14) }
[data-festival="womens"]       { --fest:#d6679a; --fest-2:#f0c0d8; --fest-soft:rgba(214,103,154,.14) }
[data-festival="fools"]        { --fest:#7b68c4; --fest-2:#b9aee0; --fest-soft:rgba(123,104,196,.14) }
[data-festival="labour"]       { --fest:#2e9e6b; --fest-2:#8fd4b0; --fest-soft:rgba(46,158,107,.14) }
[data-festival="youth"]        { --fest:#3f6fb0; --fest-2:#a8c6e4; --fest-soft:rgba(63,111,176,.14) }
[data-festival="children"]     { --fest:#f0a83c; --fest-2:#f8d79a; --fest-soft:rgba(240,168,60,.16) }
[data-festival="teachers"]     { --fest:#b07a3c; --fest-2:#ddc49a; --fest-soft:rgba(176,122,60,.14) }
[data-festival="national"]     { --fest:#d0342c; --fest-2:#f5c542; --fest-soft:rgba(208,52,44,.12) }
[data-festival="halloween"]    { --fest:#e07b39; --fest-2:#5a4a6a; --fest-soft:rgba(224,123,57,.14) }
[data-festival="christmas-eve"]{ --fest:#1f7a5c; --fest-2:#c0392b; --fest-soft:rgba(31,122,92,.14) }
[data-festival="christmas"]    { --fest:#c0392b; --fest-2:#f5c542; --fest-soft:rgba(192,57,43,.12) }
/* 农历 */
[data-festival="chunjie"]      { --fest:#d0342c; --fest-2:#f5c542; --fest-soft:rgba(208,52,44,.12) }
[data-festival="chuxi"]        { --fest:#d0342c; --fest-2:#f5c542; --fest-soft:rgba(208,52,44,.12) }
[data-festival="yuanxiao"]     { --fest:#e0557b; --fest-2:#f5c542; --fest-soft:rgba(224,85,123,.14) }
[data-festival="longtaitou"]   { --fest:#2e9e6b; --fest-2:#c9a227; --fest-soft:rgba(46,158,107,.14) }
[data-festival="duanwu"]       { --fest:#3e8f5e; --fest-2:#e0b040; --fest-soft:rgba(62,143,94,.14) }
[data-festival="qixi"]         { --fest:#8b5fa8; --fest-2:#d4a0c8; --fest-soft:rgba(139,95,168,.14) }
[data-festival="zhongyuan"]    { --fest:#4a5a7a; --fest-2:#8a9ab0; --fest-soft:rgba(74,90,122,.12) }
[data-festival="zhongqiu"]     { --fest:#c07a3c; --fest-2:#f0c860; --fest-soft:rgba(192,122,60,.14) }
[data-festival="chongyang"]    { --fest:#c9873c; --fest-2:#8a9a5b; --fest-soft:rgba(201,135,60,.14) }
[data-festival="laba"]         { --fest:#8a6b4a; --fest-2:#c4a888; --fest-soft:rgba(138,107,74,.12) }
/* 校园 */
[data-festival="graduation"]   { --fest:#3f6fb0; --fest-2:#f0c860; --fest-soft:rgba(63,111,176,.14) }
[data-festival="termstart"]    { --fest:#2e9e6b; --fest-2:#f5c542; --fest-soft:rgba(46,158,107,.14) }
/* 节气（P3，统一用一组低调的青绿，不喧宾夺主）*/
[data-festival^="term-"]       { --fest:#5b8f7d; --fest-2:#a8c4b8; --fest-soft:rgba(91,143,125,.10) }

/* ============================================================================
 * 二、边缘装饰层（.fest-edge）
 *纯 CSS 生成的飘落物 + 角饰，pointer-events:none，不抢内容。
 * ========================================================================== */
.fest-edge {
  position: fixed;
  inset: 0;
  z-index: 1;                /* 在 #seasonFx(30) 之下、内容之下 */
  pointer-events: none;
  overflow: hidden;
}
/* 12 个飘落物，数量与季节粒子(16)相当，不叠加太多 */
.fest-edge > i {
  position: absolute;
  top: -12px;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--fest);
  opacity: .42;
  animation: festFall 7s linear infinite;
}
.fest-edge > i:nth-child(3n)   { background: var(--fest-2); border-radius: 50%; }
.fest-edge > i:nth-child(4n)   { width: 6px; height: 6px; transform: rotate(45deg); }
@keyframes festFall {
  0%   { transform: translateY(-4vh) rotate(0deg); opacity: 0; }
  8%   { opacity: .42; }
  90%  { opacity: .32; }
  100% { transform: translateY(106vh) rotate(360deg); opacity: 0; }
}
/* 旋转类（灯笼/雪花感）*/
.fest-edge > i.spin { animation: festSpin 9s linear infinite; border-radius: 50%; }
@keyframes festSpin {
  0%   { transform: translateY(-4vh) rotate(0deg); opacity: 0; }
  10%  { opacity: .42; }
  100% { transform: translateY(106vh) rotate(720deg); opacity: 0; }
}

/* ============================================================================
 * 三、角饰（面板右上角小图标，纯 CSS content）
 * ⚠️ 只做「角饰」不做大面积色块 —— 保证任何节日下文字都可读。
 * ========================================================================== */
[data-festival] .panel-head::after {
  content: attr(data-fest-ico);
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 14px;
  opacity: .55;
  pointer-events: none;
  line-height: 1;
}
[data-festival] .panel-head { position: relative; }

/* 各节日的角饰（复用四季 emoji 的调性，不用图片）*/
[data-festival="chunjie"] .panel-head::after,
[data-festival="chuxi"] .panel-head::after   { content: "🏮" }
[data-festival="yuanxiao"] .panel-head::after { content: "🏮" }
[data-festival="zhongqiu"] .panel-head::after { content: "🌕" }
[data-festival="duanwu"] .panel-head::after   { content: "🎏" }
[data-festival="qixi"] .panel-head::after     { content: "💫" }
[data-festival="chongyang"] .panel-head::after{ content: "🌼" }
[data-festival="national"] .panel-head::after { content: "🚩" }
[data-festival="labour"] .panel-head::after   { content: "🛠" }
[data-festival="newyear"] .panel-head::after  { content: "🎊" }
[data-festival="teachers"] .panel-head::after { content: "🍎" }
[data-festival="children"] .panel-head::after { content: "🎈" }
[data-festival="youth"] .panel-head::after    { content: "🎓" }
[data-festival="valentine"] .panel-head::after{ content: "💝" }
[data-festival="womens"] .panel-head::after   { content: "🌷" }
[data-festival="fools"] .panel-head::after    { content: "🃏" }
[data-festival="halloween"] .panel-head::after{ content: "🎃" }
[data-festival="christmas"] .panel-head::after,
[data-festival="christmas-eve"] .panel-head::after { content: "🎄" }
[data-festival="laba"] .panel-head::after     { content: "🥣" }
[data-festival="zhongyuan"] .panel-head::after{ content: "🕯" }
[data-festival="longtaitou"] .panel-head::after { content: "✂" }
[data-festival="graduation"] .panel-head::after{ content: "🎓" }
[data-festival="termstart"] .panel-head::after { content: "📚" }

/* ============================================================================
 * 四、顶栏节日渐变（接管季节渐变槽位，但**季节渐变仍作底**）
 * ⚠️ 只改 background-image 的 color stop，用 --fest/--fest-2，
 *    不写死 background-color，避免和皮肤打架。
 * ========================================================================== */
[data-festival][data-cal-theme] .topbar {
  background-image: linear-gradient(120deg, var(--fest-soft) 0%, transparent 62%);
}
/* 无季节主题时（经典主题）也给一点节日氛围 */
[data-festival] .topbar {
  background-image: linear-gradient(120deg, var(--fest-soft) 0%, transparent 58%);
}

/* ============================================================================
 * 五、季节让位（用户铁律①）
 *强节日当天：#seasonFx 降权到 opacity .35，**不是消失**。
 * ⚠️ 只在 data-festival 上加 .fest-strong 时生效（app.js 按 strong 标记挂）。
 * ========================================================================== */
[data-festival].fest-strong #seasonFx {
  opacity: .35;
  transition: opacity .4s ease;
}
/* 弱节日（P2/P3）季节层完全保留，不降权 */

/* ============================================================================
 * 六、深色模式成套值
 * ⚠️ 深色下 --fest 要**提亮**，否则在深底上发闷（与三套皮肤同一原则）。
 * ========================================================================== */
:root[data-theme="dark"][data-festival] { --fest-soft: rgba(255, 255, 255, .06); }
:root[data-theme="dark"][data-festival="chunjie"],
:root[data-theme="dark"][data-festival="chuxi"],
:root[data-theme="dark"][data-festival="national"],
:root[data-theme="dark"][data-festival="christmas"],
:root[data-theme="dark"][data-festival="newyear"] { --fest:#e05a4e; --fest-2:#e8c46a }
:root[data-theme="dark"][data-festival="zhongqiu"],
:root[data-theme="dark"][data-festival="duanwu"],
:root[data-theme="dark"][data-festival="chongyang"] { --fest:#d4955a; --fest-2:#e8d08a }
:root[data-theme="dark"][data-festival="qixi"],
:root[data-theme="dark"][data-festival="zhongyuan"],
:root[data-theme="dark"][data-festival="valentine"],
:root[data-theme="dark"][data-festival="womens"] { --fest:#a884c4; --fest-2:#c8a8d8 }
:root[data-theme="dark"][data-festival="halloween"] { --fest:#e89a5f; --fest-2:#8a7aa0 }
:root[data-theme="dark"][data-festival="christmas-eve"],
:root[data-theme="dark"][data-festival="termstart"],
:root[data-theme="dark"][data-festival="graduation"] { --fest:#52b98d; --fest-2:#e8d08a }
/* 深色下季节让位不要降太狠，否则季节层几乎看不见 */
:root[data-theme="dark"][data-festival].fest-strong #seasonFx { opacity: .45; }
/* 深色下角饰稍微亮一点 */
:root[data-theme="dark"][data-festival] .panel-head::after { opacity: .7; }

/* ============================================================================
 * 七、减弱动效（用户铁律：全部动效可关）
 * ⚠️ 关动效后**装饰仍在**（静态可见），只是不飘。
 * ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .fest-edge > i,
  .fest-edge > i.spin { animation: none !important; opacity: .2; top: 8px; }
  [data-festival].fest-strong #seasonFx { transition: none !important; }
}

/* ============================================================================
 * 八、开关关闭时：装饰层不渲染
 * app.js 在festivalFxOn() 为 false 时**不创建** .fest-edge 节点，
 * 这里再兜一层：万一节点残留也不显示。
 * ========================================================================== */
html.no-festival .fest-edge { display: none !important; }
html.no-festival .panel-head::after { content: none !important; }
html.no-festival .topbar { background-image: none !important; }

/* ============================================================================
 * 九、打印：彩蛋装饰全部去掉
 * ========================================================================== */
@media print {
  .fest-edge { display: none !important; }
  [data-festival] .panel-head::after { content: none !important; }
}
/* ============================================================================
 * 十、节日彩蛋装饰层（v88 新增）
 * ---------------------------------------------------------------------------
 * 为什么补这一段：节日**判定**早就完整了（22 个节日 + 节前节后窗口 + 优先级），
 *   但渲染层此前只有 .fest-edge / .fest-strong 两个边框效果 ——
 *   「今天过节」判出来了，用户却看不到任何节日样子。
 *   装饰层由 Festival.decorHtml(id, level) 生成（见 festival.js）。
 *
 * ⚠ 三条纪律：
 * ① 纯 CSS 动画，不用图片 ⇒ APK 不再涨体积。
 * ② 必须 pointer-events:none —— 装饰层盖在内容上，吃点击会导致「按钮点不动」，
 *   这是装饰层最常见的翻车方式。
 * ③ 尊重 prefers-reduced-motion —— 前庭敏感用户不该被强制动画。
 * ========================================================================== */

.fest-decor {
  position: fixed;
  inset: 0;
  pointer-events: none;      /* ⚠ 纪律②：绝不吃点击 */
  z-index: 30;
  overflow: hidden;
  contain: strict;            /* 动画只在自己范围内跑，不触发整页重排 */
}

/* 飘落层：每个 <i> 是一个 emoji 粒子 */
.fest-decor-fall > i {
  position: absolute;
  top: -8vh;
  font-size: 18px;
  line-height: 1;
  opacity: .85;
  animation-name: festFall;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  will-change: transform, opacity;
}

@keyframes festFall {
  0%   { transform: translate3d(0, 0, 0) rotate(0deg);       opacity: 0; }
  8%   {                                                       opacity: .9; }
  50%  { transform: translate3d(28px, 52vh, 0) rotate(180deg); }
  92%  {                                                       opacity: .7; }
  100% { transform: translate3d(-18px, 108vh, 0) rotate(360deg); opacity: 0; }
}

/* 强节日顶部彩带：只在 STRONG 名单里出现（春节/中秋/国庆等） */
.fest-ribbon {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  display: flex;
  justify-content: space-around;
  overflow: hidden;
}
.fest-ribbon > span {
  font-size: 13px;
  line-height: 1;
  animation: festRibbonSlide 3.2s linear infinite;
}
@keyframes festRibbonSlide {
  0%   { transform: translateX(-40px) scale(.8); opacity: .5; }
  50%  { transform: translateX(0) scale(1.15);   opacity: 1; }
  100% { transform: translateX(40px) scale(.8);  opacity: .5; }
}

/* 春季：花瓣偏粉、飘落更慢（春风⇒ 视觉上「温和」一些）*/
.fest-decor-chunjie > .fest-decor-fall > i,
.fest-decor-yuanxiao > .fest-decor-fall > i,
.fest-decor-qixi > .fest-decor-fall > i { animation-duration: 5.2s; }

/* 冬季：雪花应当更小更慢（放大 + 拉长时长 ⇒ 看起来更轻）*/
.fest-decor-chuxi > .fest-decor-fall > i,
.fest-decor-dongzhi > .fest-decor-fall > i { animation-duration: 7.5s; font-size: 14px; }
.fest-decor-chuxi > .fest-decor-fall > i,
.fest-decor-dongzhi > .fest-decor-fall > i { animation-timing-function: ease-in; }

/* 毕业/开学季：粒子更密（校园节点用整月判定，视觉上要能看出「在过」）*/
.fest-decor-graduation > .fest-decor-fall > i,
.fest-decor-termstart > .fest-decor-fall > i { font-size: 20px; }

/* ⚠ 纪律③：前庭敏感 —— 关掉全部装饰动画，只保留静态存在感 */
@media (prefers-reduced-motion: reduce) {
  .fest-decor { display: none !important; }
}

/* 打印时同样去掉（与上文第九节的打印规则保持一致） */
@media print {
  .fest-decor { display: none !important; }
}

/* ============================================================================
 * 十一、生日全屏祝福（v88）
 * ---------------------------------------------------------------------------
 * 生日原本只有列表里一个🎂 徽标 + 一句祝福语，没有「今天是谁生日」的氛围。
 * 由 renderBirthdayDecor() 生成，复用节日装饰层的纪律：
 *   pointer-events:none（不吃点击）+ 尊重 prefers-reduced-motion。
 * ========================================================================== */

.bday-decor {
  position: fixed;
  inset: 0;
  pointer-events: none;      /* ⚠ 装饰不吃点击，否则按钮会点不动 */
  z-index: 31;
  overflow: hidden;
  contain: strict;
}

.bday-confetti > i {
  position: absolute;
  top: -10vh;
  font-size: 20px;
  line-height: 1;
  opacity: .9;
  animation-name: festFall;   /* 复用节日飘落关键帧，不重复造一套 */
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  will-change: transform, opacity;
}
/* 用 nth-child 给不同粒子不同延迟与时长，避免「齐刷刷一起落」的机械感 */
.bday-confetti > i:nth-child(3n)   { animation-duration: 4.2s; animation-delay: -1.1s; }
.bday-confetti > i:nth-child(3n+1) { animation-duration: 5.6s; animation-delay: -2.7s; }
.bday-confetti > i:nth-child(3n+2) { animation-duration: 6.8s; animation-delay: -0.4s; font-size: 15px; }

.bday-banner {
  position: absolute;
  top: 14vh; left: 50%;
  transform: translateX(-50%);
  max-width: 86vw;
  padding: 10px 18px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .92);
  box-shadow: 0 6px 24px rgba(0, 0, 0, .16);
  font-size: 15px;
  text-align: center;
  animation: bdayPop 2.8s ease-in-out infinite;
}
@keyframes bdayPop {
  0%, 100% { transform: translateX(-50%) scale(1); }
  50%      { transform: translateX(-50%) scale(1.05); }
}

/* 夜间模式下横幅要跟着变深，否则白底在深色页面上刺眼 */
:root[data-theme="dark"] .bday-banner { background: rgba(30, 38, 54, .92); color: #eef2fb; }

@media (prefers-reduced-motion: reduce) {
  .bday-decor { display: none !important; }
}
@media print {
  .bday-decor { display: none !important; }
}
