/* ============================================================
   board.css —— 登记信息展示大屏（v0.5.0）
   ------------------------------------------------------------
   场景：会场大屏（横屏，1920×1080 起，兼容 4K / 超宽屏）。

   设计取向：会场物料，不是互联网海报。
     · 底：一块压暗的中国红，不做彩虹渐变
     · 金：#e9c887 单一金色，靠克制的细线和小圆角成形
     · 结构：直角为主、圆角 ≤8px；细金线分区；不用毛玻璃、不用随机粒子
     · 动效：全部是"有方向的机械感"（转环 / 脉冲 / 扫描），
             而不是漫天的光点和呼吸光斑 —— 后者是大屏上最像模板的东西
     · 唯一的高潮留给奖池：数字最大、最亮，只在"涨钱"那一刻释放

   尺寸策略：不写死 px，全部 clamp(最小, vw 比例, 最大)，
   1080p 与 4K 版式比例一致、字号按屏幕线性放大。

   v0.5.0 变更：
     · 名单卡片整体缩小一档（更精致），去掉了「撑满整行」的拉伸；
     · 分页/自动翻页全部移除，改为「铺满即静止、超出即无缝滚动」；
     · 头部右侧状态块、底部四处统计文字按要求删除。

   v0.6.0 变更：
     · 奖池从右侧栏中间挪到**头部右上角**（金额是全场最该一眼看到的信息）；
     · 右栏只剩二维码 + 档位，因此收窄，省下的宽度全给名单；
     · 新卡片入场改为「由小放大弹到位 + 金色光晕扩散」，
       参照签到墙新头像的入场语汇（见 .rc.is-new）。

   v2.3 变更（★ 用户明确要求「按参考大屏重排」）：
     · 名单卡片由「矩形框」整体改为**圆形头像墙** ——
       大圆头像 + 白色圆环 + 名次数字 + 姓名，与参考大屏同一套语汇；
     · 名次 = 展示位次，1 号坑位是最新登记（由 board.js 的 renumber() 维护）；
     · 补上参考页的中式喜庆件：金色描边外框 + 四角回纹 + 上下两条祥云云头纹；
     · 持续氛围动效：金色反光带扫过名单区 + 每张头像的金色呼吸光环（相位错开）；
     · 新登记入场改为挂在**头像圆环**上（卡片没框了，缩放整张卡会带着文字抖）。

   v2.4 变更：
     · 背景换成**手机端同款**：明亮正红渐变（#E5251B→#C9241E→#AD2221，
       三处取样自 assets/bg/page1.webp）+ 六角密排网点底纹 + 细颗粒；
     · 累计奖池从头部右上角**搬回右侧栏**、放在二维码上方，
       并补上「对奖轮盘」刻度环，把"彩票即将开奖"的味道做足；
     · 头部右侧改放「档位分布」，右栏只剩「奖池 + 二维码」两块；
     · 二维码区优雅化：深红玻璃 + 金细边 + 四角金角花 + 白卡浮起。
   ============================================================ */

:root{
  --gold:#e9c887;
  --gold-2:#c9a25f;
  --gold-3:#fff3d0;          /* 高光位：数字顶部、描边亮边 */
  --gold-deep:#8a6a2f;       /* 暗部：渐变收口，避免"糊成一片黄" */
  /* v2.4：底色从"压暗的深红"换成手机端的**明亮正红**，
     所有金线 / 灰阶文字在亮红上对比都会掉一档，所以整体提亮。 */
  --gold-line:rgba(255,220,155,.40);
  --gold-line-2:rgba(255,220,155,.20);
  --glow:rgba(233,200,135,.42);   /* 统一的光晕色，改一处即全局生效 */

  --bg-0:#C9241E;          /* 手机端背景中段色（见 assets/bg/page1.webp） */
  --bg-1:#AD2221;          /* 手机端背景底部色 */
  --panel:rgba(58,4,4,.34);
  --panel-2:rgba(58,4,4,.48);

  --ink:#fdf3e3;
  --ink-2:rgba(255,246,232,.84);
  --ink-3:rgba(255,246,232,.62);

  --r:4px;
  --r-md:8px;

  /* 卡片高度：由 board.js 按视口算出后写入，卡片一律等高，网格才整齐 */
  --card-h:200px;

  --pad:clamp(18px, 1.6vw, 44px);
  --gap:clamp(10px, .82vw, 20px);
}

/* 「万」圆徽字体：与手机端第 4 页同一款（仅含「万」1 字，1.1KB） */
@font-face{
  font-family:"PABWan";
  src:url("../assets/font/fzyt-wan.ttf") format("truetype");
  font-display:swap;
}

*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;background:var(--bg-0);color:var(--ink);overflow:hidden;
  font-family:"PingFang SC","HarmonyOS Sans SC","Microsoft YaHei","Helvetica Neue",Arial,sans-serif;
  -webkit-font-smoothing:antialiased;user-select:none;
}
img{display:block}

/* ============================================================
   根容器
   ============================================================ */
.bd{
  position:fixed;inset:0;display:flex;flex-direction:column;
  /* ★ v2.4：改为**手机端同款背景**。
     竖向渐变的三个端点直接取样自 assets/bg/page1.webp：
       顶部 rgb(229,37,27)=#E5251B  →  中部 rgb(201,36,30)=#C9241E
       →  底部 rgb(173,34,33)=#AD2221
     再叠一层顶部中央的暖红光 —— 手机端页面顶部明显比底部亮，
     这一层是"手机端那个味道"的关键，少了就变成一块平红。
     网点与颗粒在 .bd::before / .bd__grain 两层里，见下。 */
  background:
    radial-gradient(78% 44% at 50% -8%, rgba(255,138,100,.55) 0%, rgba(255,120,88,0) 74%),
    linear-gradient(180deg, #E5251B 0%, #DE251C 20%, #C9241E 58%, #AD2221 100%);
}
/* 四周压暗：把视线收到画面中心，是大屏"显大气"的关键一步 */
.bd::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  /* v2.4：亮红底上再压 .42 的黑，屏幕会重新变暗、把刚换的亮红吃掉。
     降到 .20，只留"视线收拢"的作用。 */
  background:radial-gradient(132% 108% at 50% 44%, transparent 58%, rgba(88,0,0,.20) 100%);
}
/* ★ v2.4 手机端背景的**网点底纹**（halftone）。
   ------------------------------------------------------------
   FFT 实测原图 assets/bg/page1.webp 的网点周期 ≈ 23px（图宽 640），
   即"宽度的 3.6%" —— 大屏保持同一相对比例，1920 宽就是 ≈69px 步长。
   原图是**六角密排**：两套点位错开半个步长，所以这里也是两层。
   点本身是比底色略深的暗红，不是黑色 —— 用 rgba(146,12,10,.34) 才对。
   （v2.3 在这里放的是云头纹带，v2.4 按要求换成手机端的网点。） */
.bd::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  --dot:clamp(46px,3.6vw,112px);
  background-image:
    radial-gradient(circle at 50% 50%, rgba(146,12,10,.36) 0 3.3%, transparent 4.4%),
    radial-gradient(circle at 50% 50%, rgba(146,12,10,.36) 0 3.3%, transparent 4.4%);
  background-size:var(--dot) var(--dot), var(--dot) var(--dot);
  background-position:0 0, calc(var(--dot) / 2) calc(var(--dot) / 2);
  background-repeat:repeat;
}
/* ★ v2.4 细颗粒：手机端原图在网点之上还压着一层胶片颗粒。
   用内联 SVG 的 feTurbulence 生成一张 140×140 的灰度噪声小图，
   浏览器只栅格化这一小块再平铺，不是每帧生成；
   feColorMatrix saturate=0 是为了去掉 feTurbulence 默认的彩色噪点。
   单独放一层（.bd__grain）的原因：需要独立的 opacity，
   混在 .bd::before 里会把网点一起调淡。 */
.bd__grain{
  position:absolute;inset:0;pointer-events:none;z-index:1;opacity:.06;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:140px 140px;
}

/* ============================================================
   头部
   ============================================================ */
.bd__hd{
  flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;
  gap:var(--pad);
  padding:calc(var(--pad) * .78) var(--pad) calc(var(--pad) * .5);
  position:relative;z-index:3;          /* 高于 ::before 底纹，奖池不能被盖住 */
  border-bottom:1px solid var(--gold-line-2);
}
/* 标题占满左侧余量；v2.4 起右侧放的是「档位分布」（奖池已回到右栏） */
.bd__brand{min-width:0;flex:1 1 auto}
.bd__brand h1{
  margin:0;font-size:clamp(22px,1.85vw,42px);font-weight:600;letter-spacing:.02em;
  line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.bd__brand p{
  margin:clamp(4px,.34vw,9px) 0 0;color:var(--ink-3);
  font-size:clamp(12px,.82vw,18px);letter-spacing:.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* ============================================================
   主体：左侧名单 + 右侧奖池
   ============================================================ */
.bd__main{
  flex:1 1 auto;min-height:0;display:grid;
  /* v0.6.0：奖池挪去头部后，右栏只剩二维码 + 档位，可以收窄；
     省下的横向空间全给名单 —— 一屏能多放一列卡片。 */
  /* v2.4：奖池搬回右栏后，这一列从"只放二维码+档位"变回"放奖池"，
     宽度从 232~400 加到 300~520。 */
  grid-template-columns:minmax(0,1fr) clamp(300px,23.5vw,520px);
  gap:var(--gap);padding:var(--gap) var(--pad);position:relative;z-index:2;
}

/* ★ v2.3 金色描边外框 + 四角回纹 ——
   参考大屏最外圈就是一道中式金框，四角有回纹角花。
   用 ::before 画（不是给 .bd__main 加 border），因为这块要**压在头像之上** ——
   名单滚到边上时，外框必须仍然完整，不能被头像顶掉。
   z-index:3 高于 .bd__list（position:relative，z-index auto），所以能盖住。
   四角回纹 = 每个角一条横 + 一条竖，共 8 条 background-image
   （比往 DOM 里插 4 个节点便宜，也不会被 board.js 重建名单时抹掉）。 */
.bd__main::before{
  content:"";position:absolute;z-index:3;pointer-events:none;
  inset:calc(var(--gap) * .34);
  border:1px solid rgba(233,200,135,.62);
  /* 内层再压一道细金线 —— 中式双线框，比单线更像"会场的框" */
  box-shadow:
    inset 0 0 0 2px rgba(233,200,135,.07),
    inset 0 0 0 5px rgba(233,200,135,.30);
  background-image:
    linear-gradient(var(--gold),var(--gold)), linear-gradient(var(--gold),var(--gold)),
    linear-gradient(var(--gold),var(--gold)), linear-gradient(var(--gold),var(--gold)),
    linear-gradient(var(--gold),var(--gold)), linear-gradient(var(--gold),var(--gold)),
    linear-gradient(var(--gold),var(--gold)), linear-gradient(var(--gold),var(--gold));
  background-size:
    clamp(44px,3.6vw,96px) 3px, 3px clamp(44px,3.6vw,96px),
    clamp(44px,3.6vw,96px) 3px, 3px clamp(44px,3.6vw,96px),
    clamp(44px,3.6vw,96px) 3px, 3px clamp(44px,3.6vw,96px),
    clamp(44px,3.6vw,96px) 3px, 3px clamp(44px,3.6vw,96px);
  background-position:
    left top, left top, right top, right top,
    left bottom, left bottom, right bottom, right bottom;
  background-repeat:no-repeat;
}
/* 呼吸光晕单独一层（::after）—— 只动 opacity，走合成层；
   不能像第一版那样直接给 ::before 的 box-shadow 做动画：
   那是一个 1488×870 的大元素，每帧重绘一次，4K 上会明显掉帧。 */
.bd__main::after{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  inset:calc(var(--gap) * .34);
  box-shadow:inset 0 0 clamp(30px,3vw,84px) rgba(233,200,135,.28);
  opacity:.34;
  animation:frameGlow 7.5s ease-in-out infinite;
}
@keyframes frameGlow{
  0%,100%{opacity:.30}
  50%    {opacity:.88}
}

/* ---------------- 左侧：登记名单（铺满 → 滚动循环） ----------------
   三层结构：
     .bd__pages  视口，overflow:hidden —— 滚动的内容只在这里裁切
     .bd__flow   静止时负责把网格垂直居中；进入滚动后改为顶部对齐
     .bd__track  网格本体，滚动时由 board.js 改 translate3d（GPU 合成）
   ------------------------------------------------------------ */
.bd__list{position:relative;min-height:0;display:flex;flex-direction:column}
.bd__pages{flex:1 1 auto;position:relative;min-height:0;overflow:hidden}
/* ★ v2.3 持续氛围：一条金色反光带斜着扫过名单区。
   第一版做成了 62% 宽，整块亮起来像"半屏泛白"；改成 34% 宽的窄带，
   才是"金属反光掠过"的观感。
   做法是给窄条做 translate3d —— 走 GPU 合成，
   不像 background-position 动画那样每帧重绘 130 万像素。
   .bd__pages 有 overflow:hidden，扫出去的会被裁掉，不会溢出到侧栏。 */
.bd__pages::after{
  content:"";position:absolute;top:-24%;bottom:-24%;left:-48%;width:44%;
  z-index:1;pointer-events:none;will-change:transform;transform:skewX(-13deg);
  /* 单一平滑坡道（0 → 峰值 → 0）。
     第一版是 0/.055/.115/.055/0 这种「双坡道」，中间那一段 10% 的
     突然加亮在深红底上会读成一条硬边，看着像有块半透明的板子扫过。 */
  background:linear-gradient(100deg,
    transparent 0%, rgba(255,240,200,.035) 26%,
    rgba(255,248,225,.105) 50%,
    rgba(255,240,200,.035) 74%, transparent 100%);
  animation:ambSheen 13s cubic-bezier(.42,0,.58,1) infinite;
}
@keyframes ambSheen{
  /* 前面停在原地 10% 的时间，扫过去后留一段"安静期"，
     否则 13 秒一次、次次都满速，看久了会累。 */
  0%,10%  {transform:translate3d(0,0,0) skewX(-13deg)}
  58%,100%{transform:translate3d(340%,0,0) skewX(-13deg)}
}
.bd__flow{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center}
.bd__flow.is-scroll{justify-content:flex-start}

.bd__track{
  display:grid;
  /* 卡片去框后视觉间距会显小，行距放大一档；
     board.js 的 readGap() 读的就是 rowGap，几何会自适应，不用改 JS。 */
  column-gap:var(--gap);row-gap:calc(var(--gap) * 1.25);
  grid-template-columns:repeat(var(--cols,4), minmax(0,1fr));
  align-content:start;
  /* 只动 transform：不触发布局重排，滚动才是 60fps 顺滑的 */
  will-change:transform;
  transform:translate3d(0,0,0);
  backface-visibility:hidden;
}
/* 条数还没铺满一屏时（.bd__flow 不带 is-scroll）——
   每列给一个上限宽度（优先按卡片高度的 0.92 倍，宽度不够时自动收窄），
   再整体水平居中。否则 3 条记录会缩在 6 列网格的最左边，画面很偏。
   同时 board.js 会把 --cols 收成实际条数，所以不会出现空的列位。 */
.bd__flow:not(.is-scroll) .bd__track{
  grid-template-columns:repeat(var(--cols,4),
    minmax(0, min(calc(var(--card-h) * .92),
                  calc((100% - (var(--cols,4) - 1) * var(--gap)) / var(--cols,4)))));
  justify-content:center;
}

/* ---------------- 登记卡片：★ v2.3 按参考大屏（签到墙）重排 ----------------
   参考页的语汇很明确：
     大圆形头像 + 白色圆环 + 名次数字 + 姓名，
   头像直接贴在红底上，整体是一面「头像墙」。
   所以这里把 v0.5.0 的**矩形卡片**整个拆掉 ——
     · 去掉 border / background / 顶部金线：方框一在，"墙"就散了；
     · 头像放大到卡片高度的 0.56 倍（clamp 兜住极端尺寸），成为唯一主体；
     · 头像外面套白环（参考页最醒目的那一圈），
       名次数字做成白色圆角胶囊压在圆环下缘 —— 位置与参考页一致；
     · 姓名回到高对比白字 + 轻投影，在红底上一眼可读。
   卡片没框了，所以「新登记」的高亮只能从**头像圆环**上做
   （rcPop 缩放 + rcHalo 光晕扩散），另有一层持续呼吸的金色光环。
   ------------------------------------------------------------ */
.rc{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:clamp(4px,.4vw,12px);
  height:var(--card-h);
  padding:clamp(2px,.25vw,8px) clamp(2px,.2vw,6px);
  min-width:0;position:relative;text-align:center;
  animation:rcIn .45s cubic-bezier(.2,.8,.3,1) both;
}
@keyframes rcIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* 头像圆环：白圈 + 内圈压暗 + 一层持续呼吸的金色光环（::after）。
   直径跟着 --card-h 走 —— 4K 上卡片变高，头像同步放大，
   版式比例与 1080p 完全一致。 */
.rc__ring{
  position:relative;flex:0 0 auto;border-radius:50%;
  /* 尺寸取「卡片高度 × 0.55」与「列宽 80%」的较小值：
     高卡片时由高度决定（头像够大），超宽屏列变窄时由列宽兜住，
     头像永远不会顶破所在那一列。 */
  width:min(calc(var(--card-h) * .55), 80%);
  aspect-ratio:1;
  background:radial-gradient(circle at 50% 32%, rgba(255,255,255,.20), rgba(0,0,0,.30));
  /* 白环要够粗才看得出来 —— 参考页最醒目的就是这一圈。
     2px 在大屏上会糊成一道灰边；而且 Chrome 会把 border-width 吸附到整数，
     所以这里给到 6px 上下，并直接用纯白（不是 .92 的半透明白）。 */
  border:clamp(4px,.34vw,9px) solid #fff;
  box-shadow:
    0 0 clamp(10px,.85vw,26px) rgba(255,224,168,.30),
    inset 0 0 clamp(8px,.7vw,20px) rgba(0,0,0,.34);
}
/* 呼吸光环：按 nth-child 错开相位，整面墙像在"一起呼吸"，
   而不是 40 多个头像整齐划一地闪 —— 后者在大屏上很像坏掉的灯。 */
.rc__ring::after{
  content:"";position:absolute;border-radius:50%;pointer-events:none;
  inset:calc(-1 * clamp(3px,.24vw,7px));
  border:1px solid rgba(255,222,158,.55);
  animation:rcAura 4.6s ease-in-out infinite;
}
@keyframes rcAura{
  0%,100%{opacity:.14;transform:scale(1)}
  50%    {opacity:.58;transform:scale(1.045)}
}
.rc:nth-child(4n+2) .rc__ring::after{animation-delay:1.15s}
.rc:nth-child(4n+3) .rc__ring::after{animation-delay:2.30s}
.rc:nth-child(4n+4) .rc__ring::after{animation-delay:3.45s}

.rc__av{
  position:absolute;inset:0;width:100%;height:100%;
  border-radius:50%;object-fit:cover;background:rgba(0,0,0,.22);
}
.rc__av--ph{
  display:flex;align-items:center;justify-content:center;
  color:#fff3d0;font-weight:600;font-size:clamp(16px,1.5vw,42px);
  background:linear-gradient(180deg, rgba(255,255,255,.24), rgba(0,0,0,.18));
  text-shadow:0 1px 2px rgba(60,0,0,.5);
}

/* 名次胶囊：白色圆角标签，**挂在圆环下缘之外**（参考页就是这个位置）。
   第一版只往下压了 46%，结果大半个胶囊压在头像照片上，像贴了块膏药；
   现在压到 74%，只与圆环下缘轻微相叠，读起来才是"编号 + 头像"两层。
   1 = 最新登记。插了新记录后，其余卡片的名次统一 +N，
   由 board.js 的 renumber() 维护 —— 写死在 HTML 里会错。 */
.rc__rank{
  position:absolute;left:50%;bottom:0;z-index:2;
  transform:translate(-50%,74%);
  min-width:clamp(22px,1.9vw,46px);
  padding:0 clamp(5px,.45vw,12px);
  border-radius:999px;background:#fff;color:#b4142e;
  font-weight:800;line-height:1.45;
  font-size:clamp(11px,.82vw,22px);
  font-variant-numeric:tabular-nums;
  box-shadow:0 1px clamp(3px,.26vw,8px) rgba(0,0,0,.42);
}

.rc__id{
  display:flex;align-items:baseline;justify-content:center;
  gap:clamp(4px,.36vw,9px);min-width:0;max-width:100%;
  margin-top:clamp(6px,.5vw,14px);   /* 给挂在环外的名次胶囊让位 */
}
.rc__name{
  font-size:clamp(14px,1.05vw,27px);font-weight:700;letter-spacing:.03em;
  line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  color:#fff;
  /* ★ v2.4：底色从深红换成手机端的亮红后，纯白字需要更实的暗部投影才站得住 */
  text-shadow:0 1px 3px rgba(112,0,0,.72), 0 0 clamp(10px,.7vw,18px) rgba(255,214,150,.34);
}
.rc__area{
  flex:0 0 auto;color:#ffe7bb;white-space:nowrap;
  font-size:clamp(10px,.66vw,15px);letter-spacing:.02em;
  padding:0 clamp(4px,.32vw,8px);border-radius:999px;
  border:1px solid rgba(255,235,190,.46);background:rgba(74,2,2,.42);
}
.rc__duty{
  color:#fff2c6;font-weight:800;white-space:nowrap;
  font-size:clamp(15px,1.18vw,31px);line-height:1.05;
  font-variant-numeric:tabular-nums;
  /* ★ v2.4：亮红底上「纯金光晕」会被红吃掉（实测金额几乎读不出），
     改成「先一道深红贴边、再一层暖金柔光」——顺序不能反，反了就变成糊边。 */
  text-shadow:0 1px 2px rgba(112,0,0,.60), 0 0 clamp(9px,.66vw,18px) rgba(255,214,150,.42);
}
.rc__duty i{font-style:normal;font-size:.5em;margin-left:.2em;opacity:.85;font-weight:500}

/* 新登记：★ 按参考大屏的入场语汇 —— 头像**由小放大弹到位** + 金色光晕向外扩散。
   ------------------------------------------------------------
   动效挂在**圆环**上，而不是整张卡：卡片已经没有边框，
   缩放整张卡会带着姓名/金额一起抖，看着像"错位"。
   光晕用 ::before 这个透明覆盖层来放 —— 若直接把 rcHalo 写在 .rc__ring 上，
   它的 fill-mode:both 会长期顶掉圆环自身的静态投影（动画结束后光晕全没了）。
   注意 .rc 自身的 rcIn 仍在跑，两者作用在不同元素上，互不干扰。 */
.rc__ring::before{
  content:"";position:absolute;border-radius:50%;pointer-events:none;opacity:0;
  inset:calc(-1 * clamp(1px,.1vw,3px));
}
.rc.is-new .rc__ring{
  border-color:#fff;
  animation:rcPop .62s cubic-bezier(.18,.9,.28,1.06) both;
}
.rc.is-new .rc__ring::before{
  animation:rcHalo 2.2s ease-out .10s 2 both;
}
@keyframes rcPop{
  0%  {transform:scale(.58)}
  55% {transform:scale(1.075)}
  100%{transform:scale(1)}
}
@keyframes rcHalo{
  0%  {opacity:1;  box-shadow:0 0 0 0 rgba(255,232,176,.72)}
  55% {opacity:.55;box-shadow:0 0 0 clamp(16px,1.4vw,36px) rgba(255,220,150,.20)}
  100%{opacity:0;  box-shadow:0 0 0 clamp(30px,2.6vw,66px) rgba(233,200,135,0)}
}


/* ============================================================
   右侧：奖池（「大奖即将开奖」的紧张感）
   ------------------------------------------------------------
   动效全部是机械/结构性的，且都朝一个方向：
     · 双层虚线套环反向旋转 —— 像对奖机的锁环在收紧
     · 中心脉冲波纹（1.5s 一次）—— 心跳节奏
     · 斜向高光扫过（3.2s 一次）—— 金属反光，暗示"价值"
     · 涨钱时：数字弹跳 + 一层快速扩散环 + 「+N 元」上浮 + 烟花
   ============================================================ */
/* v0.6.0：奖池搬走后，这里只剩二维码与档位两项，
   竖向居中排布比"顶到最上面"更平衡。 */
/* ★ v2.4：右栏 = 「奖池（吃掉剩余高度） + 二维码（自身高度）」上下两块。
   原来这里是 justify-content:center 把二维码居中，现在有奖池撑高，
   改成拉伸即可；两块一起把整列填满，不会上下留空。 */
.bd__side{
  /* v2.5：右栏从两块变三块（奖池 / 责任额排行 / 二维码），
     块与块的间距收一档，把省下来的高度让给奖池。 */
  display:flex;flex-direction:column;
  gap:calc(var(--gap) * .82);min-height:0;
}

.jp{
  /* v2.5：右栏多了「责任额排行」一块，奖池吃掉剩下的全部高度（flex:1 1 auto）。
     ★ 轮盘尺寸必须改成 --ring = min(88%, 26vh)，**不能**再用"宽度的 92%"：
       面板从 597px 压到 ~290px 后，按宽度算出来的环（451×.92=415）比面板还高，
       被 overflow:hidden 一裁就成了"缺一块的圆"，非常难看。
       用 vh 兜住高度：1080p 实测 --ring = 280px，而奖池面板 292px，稳落在里面，
       4K / 720p 上 --ring 与 .lb 的高度都是 vh 派生的，会同比缩放，不会打架。
       ★ 记住：.lb 的高度一旦调大，.jp 就被挤矮，--ring 必须同步回调小，
         两者是"零和"关系，改一个就要重算另一个（见 .lb 那段的算式）。
       环比：刻度环 1.0 / 虚线锁环 .85 / 内圈 .63 / 中心脉冲 .42 倍。 */
  --ring:min(88%, 26vh);
  position:relative;flex:1 1 auto;min-height:0;overflow:hidden;isolation:isolate;
  display:flex;align-items:center;justify-content:center;
  border-radius:var(--r-md);
  border:1px solid var(--gold-line);
  background:
    radial-gradient(70% 58% at 50% 42%, rgba(233,200,135,.10) 0%, transparent 72%),
    linear-gradient(180deg, #6f0e0e 0%, #4a0707 55%, #2b0303 100%);
  /* 三层阴影：外圈金色描边光 → 内圈深压 → 面板下沉。比单一 inset 立体得多 */
  box-shadow:
    0 0 clamp(18px,1.6vw,44px) rgba(233,200,135,.10),
    inset 0 0 clamp(30px,3vw,90px) rgba(0,0,0,.62),
    inset 0 1px 0 rgba(255,236,196,.10);
}

/* 数字背后的金色光晕（用 ::before，不动 DOM 结构） */
.jp::before{
  content:"";position:absolute;left:50%;top:46%;pointer-events:none;z-index:0;
  width:110%;aspect-ratio:1;transform:translate(-50%,-50%);
  background:radial-gradient(closest-side, rgba(233,200,135,.20) 0%, rgba(233,200,135,.07) 46%, transparent 76%);
}

/* -------- ① 双层套环 + 雷达光束 -------- */
.jp__ring{
  position:absolute;left:50%;top:50%;pointer-events:none;
  border-radius:50%;
}
.jp__ring--a{
  width:calc(var(--ring) * .85);aspect-ratio:1;
  margin:calc(var(--ring) * -.425) 0 0 calc(var(--ring) * -.425);
  border:1px dashed rgba(233,200,135,.22);
  animation:ringA 22s linear infinite;
}
/* 雷达光束：一条贴着环内侧缓慢扫过的金色光带。
   比"再画一个虚线圆"高级得多，成本只是一层 conic-gradient。 */
.jp__ring--a::before{
  content:"";position:absolute;inset:0;border-radius:50%;
  background:conic-gradient(from 0deg,
    rgba(255,243,208,.34) 0deg, rgba(233,200,135,.13) 24deg,
    transparent 64deg, transparent 360deg);
  -webkit-mask:radial-gradient(closest-side, transparent 0 92%, #000 93%);
  mask:radial-gradient(closest-side, transparent 0 92%, #000 93%);
  animation:ringA 9s linear infinite;
}
/* ★ v2.4 新增「对奖轮盘」刻度环：一圈细密金色刻度，40s 转一圈。
   用 repeating-conic-gradient 画刻度 + mask 挖成"只剩最外一圈"，
   成本就是一层渐变，比画几十个 DOM 刻度便宜得多。
   这张"轮盘感"是"彩票即将开奖"最直接的视觉信号。 */
.jp__ring--c{
  width:var(--ring);aspect-ratio:1;
  margin:calc(var(--ring) / -2) 0 0 calc(var(--ring) / -2);
  background:repeating-conic-gradient(from 0deg,
    rgba(255,236,190,.44) 0deg .55deg, transparent .55deg 6deg);
  -webkit-mask:radial-gradient(closest-side, transparent 0 87%, #000 88% 100%, transparent 100%);
  mask:radial-gradient(closest-side, transparent 0 87%, #000 88% 100%, transparent 100%);
  animation:ringB 40s linear infinite;
}
.jp__ring--b{
  width:calc(var(--ring) * .63);aspect-ratio:1;
  margin:calc(var(--ring) * -.315) 0 0 calc(var(--ring) * -.315);
  border:1px solid rgba(233,200,135,.13);
  /* 内圈再套两层极淡的同心细环，做"刻度盘"的层次感 */
  box-shadow:0 0 0 clamp(8px,.7vw,20px) rgba(233,200,135,.045),
             inset 0 0 0 1px rgba(255,243,208,.06);
  animation:ringB 9s linear infinite reverse;
}
@keyframes ringA{from{transform:rotate(0)}to{transform:rotate(360deg)}}
@keyframes ringB{from{transform:rotate(0)}to{transform:rotate(360deg)}}

/* -------- ② 中心脉冲：一圈由内向外推出去，1.5s 一次 -------- */
.jp__pulse{
  position:absolute;left:50%;top:50%;pointer-events:none;
  /* v2.5：跟着 --ring 走。原来写死 clamp(120px,10vw,260px)，
     在压缩后的面板里 scale(1.62) 会顶出面板外、被裁掉一条边。 */
  width:calc(var(--ring) * .42);aspect-ratio:1;border-radius:50%;
  margin:calc(var(--ring) * -.21) 0 0 calc(var(--ring) * -.21);
  border:1px solid rgba(233,200,135,.34);
  /* 由细到粗、由亮到灭，观感更"开奖倒计时"而不是"水波纹" */
  animation:jpPulse 1.9s cubic-bezier(.2,.7,.3,1) infinite;
}
@keyframes jpPulse{
  0%  {transform:scale(.30);opacity:0;border-width:2px}
  16% {opacity:.62;border-width:1.5px}
  100%{transform:scale(1.62);opacity:0;border-width:.5px}
}

/* -------- ③ 斜向高光扫过 -------- */
.jp__sweep{
  position:absolute;inset:0;pointer-events:none;opacity:.55;
  background:linear-gradient(104deg,
    transparent 36%,
    rgba(255,243,208,.10) 46%,
    rgba(255,243,208,.20) 50%,
    rgba(255,243,208,.06) 54%,
    transparent 64%);
  background-size:280% 100%;
  animation:jpSweep 4.4s ease-in-out infinite;
}
@keyframes jpSweep{
  0%  {background-position:150% 0}
  100%{background-position:-60% 0}
}

/* -------- ④ 主体数字 -------- */
.jp__inner{
  position:relative;z-index:4;width:100%;text-align:center;
  /* 左右留白收到最小：把面板宽度几乎全让给数字，这是"数字显大"的前提 */
  padding:0 clamp(2px,.3vw,8px);
  transform:translateY(clamp(-8px,-.6vw,-16px));
}
.jp__cap{
  display:inline-block;position:relative;
  color:var(--gold-2);letter-spacing:.30em;text-indent:.30em;
  font-size:clamp(11px,.86vw,21px);
}
/* 标题下一条短金线，把"累计"和数字做一个视觉分隔 */
.jp__cap::after{
  content:"";position:absolute;left:50%;bottom:clamp(-12px,-.72vw,-18px);
  width:clamp(26px,2vw,52px);height:1px;transform:translateX(-50%);
  background:linear-gradient(90deg,transparent,var(--gold),transparent);
}
.jp__num{
  margin-top:clamp(12px,1vw,26px);
  display:flex;align-items:baseline;justify-content:center;
  line-height:.9;white-space:nowrap;
  transition:transform .32s cubic-bezier(.2,1.5,.35,1);
}
.jp__num.is-bump{transform:scale(1.09)}

.jp__digits{
  font-family:"Arial Black","PingFang SC",Arial,sans-serif;
  font-weight:900;font-variant-numeric:tabular-nums;letter-spacing:-.03em;
  /* v0.4.0：再放大一档（6.6vw → 8.6vw）。
     位数变多时 fitPool() 会自动缩到不顶破面板，所以放大是安全的。 */
  /* v2.4：奖池从"头部横条"回到"右栏面板"，可用宽度从 ~600px 收到 ~470px，
     基准字号同步收一档（位数字多的场景由 fitPool() 自动缩到不顶破面板）。 */
  font-size:clamp(46px,4.6vw,124px);
  /* 加了两道暗部收口，金属质感更强，不再"一片浅黄" */
  background:linear-gradient(180deg,
    #fffdf3 0%, #fff0bd 30%, #eecb84 56%, #b8913f 80%, #ffeec2 100%);
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
  /* 近距锐光 + 远距柔光，两层叠加才有"发光"而不是"描边" */
  filter:
    drop-shadow(0 0 clamp(10px,.85vw,24px) rgba(255,236,180,.50))
    drop-shadow(0 0 clamp(30px,2.6vw,72px) rgba(233,200,135,.30));
}
.jp__wan{
  font-style:normal;font-family:"PABWan","PingFang SC","Microsoft YaHei",sans-serif;
  font-size:clamp(20px,1.9vw,52px);font-weight:400;margin-left:.06em;
  color:var(--gold);
  text-shadow:0 0 clamp(10px,.8vw,22px) rgba(233,200,135,.35);
}
.jp__raw{
  margin-top:clamp(10px,.82vw,22px);
  color:var(--ink-2);letter-spacing:.06em;
  font-size:clamp(11px,.86vw,21px);font-variant-numeric:tabular-nums;
}

/* -------- ⑤ 涨幅：扩散环 + 「+N 元」上浮 -------- */
.jp__delta{
  position:absolute;left:50%;top:72%;z-index:6;pointer-events:none;
  transform:translate(-50%,-50%);opacity:0;white-space:nowrap;
  color:#fff3cd;font-weight:700;letter-spacing:.02em;
  font-size:clamp(15px,1.2vw,30px);
  text-shadow:0 1px 0 rgba(60,0,0,.55);
}
.jp.is-gain .jp__delta{animation:jpDelta 1.5s cubic-bezier(.15,.85,.25,1) both}
@keyframes jpDelta{
  0%  {opacity:0;transform:translate(-50%,-30%) scale(.7)}
  18% {opacity:1;transform:translate(-50%,-76%) scale(1.1)}
  36% {transform:translate(-50%,-90%) scale(1)}
  100%{opacity:0;transform:translate(-50%,-168%) scale(.98)}
}
.jp::after{
  content:"";position:absolute;left:50%;top:50%;z-index:5;pointer-events:none;
  width:clamp(80px,7vw,190px);aspect-ratio:1;border-radius:50%;
  transform:translate(-50%,-50%);opacity:0;
}
.jp.is-gain::after{animation:jpBurst .95s cubic-bezier(.15,.8,.25,1) both}
@keyframes jpBurst{
  0%  {opacity:1;box-shadow:0 0 0 0 rgba(255,232,176,.7)}
  60% {opacity:.4;box-shadow:0 0 0 clamp(70px,8vw,200px) rgba(233,200,135,.22)}
  100%{opacity:0;box-shadow:0 0 0 clamp(130px,16vw,400px) rgba(233,200,135,0)}
}

/* ★ v2.5：底部的「即将开奖」胶囊（.jp__badge）已按用户要求**整块移除** ——
   HTML 节点、board.js 里的赋值、这里的样式三处一起删，不留半截。
   注意 @keyframes blink 要留着：二维码下方提示语前面那颗金色呼吸点
   （.qr__tip::before）还在用它。 */
@keyframes blink{0%,100%{opacity:1}50%{opacity:.3}}

/* ============================================================
   ★ v2.4：奖池搬回右栏，下面这一整段「头部横条版式」的覆盖规则全部删除。
   ------------------------------------------------------------
   为什么删而不是留着：v0.6.0 为了把奖池塞进头部窄条，写了
   九条 `.bd__hd` 前缀的覆盖（面板宽度、横向 flex、隐藏光晕、缩字号…），
   把双层套环 / 中心脉冲的容器也从 HTML 里摘掉了。
   现在 .jp 回到右栏竖版，这些覆盖一旦残留就会继续生效、把面板压扁 ——
   所以是**删掉**，不是改值。

   头部右侧改放「档位分布」：它不是"另一个设置"，而是**奖池的拆解**
   （12/24/72 万档各多少人），放在标题旁边做一行概览，
   右栏就只剩「奖池 + 二维码」两块，职责干净。
   ============================================================ */
.bd__hd .bd__tiers{
  flex:0 0 auto;align-self:center;
  width:clamp(280px,25vw,560px);
}

/* ============================================================
   责任额排行（v2.5 新增）
   ------------------------------------------------------------
   放在「奖池」与「二维码」之间，按责任额（duty）从大到小取前 N 名。
   和名单、奖池一样，跟着每一次长轮询实时重排。

   三条设计约束：
     ① 面板高度用 clamp(…, 23vh, …) 固定，**不参与 flex 分配** ——
        行数是要按高度反推的，高度本身必须稳定，否则"能放几行"会抖；
     ② 行必须 flex:0 0 auto + 列表 overflow:hidden：
        让放不下的行**被裁掉**，而不是把每一行压扁（压扁后文字会挤在一起，
        比少显示两名更难看）。board.js 会先量高度再决定渲染几行，
        所以正常情况根本不会真的裁到；
     ③ 名次变色只给前三名（金/银/铜），后面统一用同一种素圈 ——
        40 多个人的榜上到处是彩色圆牌，反而看不出谁是头部。
   ============================================================ */
.lb{
  flex:0 0 auto;position:relative;overflow:hidden;
  display:flex;flex-direction:column;
  height:clamp(150px, 27.5vh, 360px);
  border-radius:var(--r-md);
  border:1px solid var(--gold-line);
  background:
    radial-gradient(72% 58% at 50% 0%, rgba(233,200,135,.12) 0%, transparent 74%),
    linear-gradient(180deg, #6f0e0e 0%, #4a0707 58%, #2b0303 100%);
  box-shadow:
    0 0 clamp(14px,1.2vw,34px) rgba(233,200,135,.08),
    inset 0 0 clamp(20px,2vw,58px) rgba(0,0,0,.55),
    inset 0 1px 0 rgba(255,236,196,.10);
}
.lb__hd{
  flex:0 0 auto;display:flex;align-items:baseline;gap:.6em;
  padding:clamp(6px,.55vw,12px) clamp(9px,.8vw,17px) clamp(4px,.4vw,9px);
  border-bottom:1px solid var(--gold-line-2);
}
.lb__ttl{
  color:var(--gold-3);font-weight:700;
  font-size:clamp(11px,.78vw,17px);letter-spacing:.16em;text-indent:.16em;
}
.lb__sub{
  margin-left:auto;font-style:normal;
  color:var(--ink-3);font-size:clamp(9px,.6vw,13px);letter-spacing:.1em;
}
.lb__list{
  flex:1 1 auto;min-height:0;overflow:hidden;
  margin:0;list-style:none;
  padding:clamp(3px,.26vw,7px) clamp(5px,.44vw,10px);
  display:flex;flex-direction:column;
}
.lb__row{
  flex:0 0 auto;                       /* 不压缩：放不下就裁，见上文 ② */
  display:flex;align-items:center;gap:.55em;
  padding:clamp(2px,.19vw,5px) clamp(4px,.34vw,8px);
  border-radius:var(--r);
  font-size:clamp(11px,.76vw,17px);line-height:1.5;
}
.lb__row + .lb__row{border-top:1px solid rgba(255,220,155,.09)}
.lb__rk{
  flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  width:clamp(16px,1.18vw,27px);height:clamp(16px,1.18vw,27px);
  border-radius:50%;font-weight:800;font-variant-numeric:tabular-nums;
  font-size:clamp(9px,.62vw,14px);
  background:rgba(255,255,255,.10);color:#ffe7bb;
  border:1px solid rgba(255,220,155,.30);
}
.lb__row--1 .lb__rk{background:linear-gradient(180deg,#ffeaa8,#d8a336);color:#5a1500;border-color:#ffeaa8}
.lb__row--2 .lb__rk{background:linear-gradient(180deg,#f4f6fa,#b6bec9);color:#3a3f47;border-color:#f4f6fa}
.lb__row--3 .lb__rk{background:linear-gradient(180deg,#f0c08a,#b5762f);color:#4a2400;border-color:#f0c08a}
.lb__nm{
  flex:0 1 auto;min-width:0;color:#fff;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  text-shadow:0 1px 2px rgba(112,0,0,.60);
}
.lb__ar{
  flex:0 0 auto;color:#ffe7bb;opacity:.72;
  font-size:.78em;letter-spacing:.02em;
}
.lb__dy{
  flex:0 0 auto;margin-left:auto;color:#fff2c6;font-weight:800;
  font-variant-numeric:tabular-nums;
  text-shadow:0 1px 2px rgba(112,0,0,.60);
}
.lb__dy i{font-style:normal;font-size:.62em;font-weight:600;opacity:.82;margin-left:.1em}
/* 新冒出来的那名（或名次被挤动后第一次出现的行）闪一下，
   让"实时更新"看得见 —— 否则榜在无声地重排，现场根本察觉不到 */
.lb__row.is-up{animation:lbPop 1.7s ease-out both}
@keyframes lbPop{
  0%  {background:rgba(255,224,168,.34)}
  100%{background:transparent}
}
.lb.is-empty .lb__list::after{
  content:"等待登记数据…";
  flex:1 1 auto;display:flex;align-items:center;justify-content:center;
  color:var(--ink-3);letter-spacing:.08em;font-size:clamp(10px,.72vw,16px);
}

/* ============================================================
   扫码进入
   ============================================================ */
/* ★ v2.4 二维码区优雅化
   ------------------------------------------------------------
   原来是一个"灰底 + 细边框"的方盒子，跟旁边的奖池面板撞在一起、
   也不知道谁是主角。改法是三步：
     ① 底：深红玻璃 + 顶部一层金雾（与奖池面板同一套材质语言）；
     ② 边：细金边 + **四角金角花**（与主框的四角回纹呼应，
        用 8 条 background-image 拼，不插 DOM）；
     ③ 码：白卡 + 一道极淡的金描边 + 下方投影，让二维码"浮"起来。
   提示语前面加一颗金色呼吸点，视线自然会落到它上面。 */
.qr{
  flex:0 0 auto;position:relative;
  display:flex;flex-direction:column;align-items:center;
  gap:clamp(7px,.6vw,14px);
  padding:clamp(14px,1.1vw,26px) clamp(12px,.95vw,22px) clamp(16px,1.25vw,30px);
  border-radius:var(--r-md);
  background:
    radial-gradient(88% 62% at 50% 0%, rgba(255,214,150,.13) 0%, transparent 72%),
    linear-gradient(180deg, rgba(84,7,7,.60) 0%, rgba(52,4,4,.72) 100%);
  border:1px solid rgba(255,220,155,.30);
  box-shadow:
    0 clamp(8px,.7vw,18px) clamp(22px,2vw,52px) rgba(70,0,0,.34),
    inset 0 1px 0 rgba(255,240,208,.16);
}
/* 四角金角花（每个角 = 一条横 + 一条竖，共 8 条渐变） */
.qr::before{
  content:"";position:absolute;pointer-events:none;
  inset:clamp(4px,.34vw,8px);
  background-image:
    linear-gradient(var(--gold),var(--gold)), linear-gradient(var(--gold),var(--gold)),
    linear-gradient(var(--gold),var(--gold)), linear-gradient(var(--gold),var(--gold)),
    linear-gradient(var(--gold),var(--gold)), linear-gradient(var(--gold),var(--gold)),
    linear-gradient(var(--gold),var(--gold)), linear-gradient(var(--gold),var(--gold));
  background-size:
    clamp(14px,1.1vw,26px) 2px, 2px clamp(14px,1.1vw,26px),
    clamp(14px,1.1vw,26px) 2px, 2px clamp(14px,1.1vw,26px),
    clamp(14px,1.1vw,26px) 2px, 2px clamp(14px,1.1vw,26px),
    clamp(14px,1.1vw,26px) 2px, 2px clamp(14px,1.1vw,26px);
  background-position:
    left top, left top, right top, right top,
    left bottom, left bottom, right bottom, right bottom;
  background-repeat:no-repeat;opacity:.62;
}
.qr__img{
  /* 右栏变宽了，二维码可以再大一点，远处也扫得动 */
  width:clamp(124px,10vw,232px);height:auto;
  background:#fff;border-radius:clamp(7px,.55vw,13px);
  padding:clamp(5px,.42vw,10px);
  box-shadow:
    0 0 0 1px rgba(255,240,208,.30),
    0 clamp(6px,.5vw,14px) clamp(16px,1.4vw,34px) rgba(60,0,0,.36);
}
.qr__tip{
  display:inline-flex;align-items:center;gap:.55em;
  color:#ffe7bb;letter-spacing:.14em;text-indent:.14em;text-align:center;
  font-size:clamp(12px,.84vw,19px);
}
/* 提示语前的金色呼吸点 */
.qr__tip::before{
  content:"";flex:0 0 auto;width:6px;height:6px;border-radius:50%;
  background:var(--gold);box-shadow:0 0 8px rgba(233,200,135,.7);
  animation:blink 1.9s ease-in-out infinite;
}
.qr.is-off{display:none}

/* ============================================================
   档位分布
   ============================================================ */
/* ★ v2.4：档位分布从右栏搬到头部右侧（见 R8 说明）。
   头部是窄条，所以每格改成"上标签 / 下数字"的紧凑两行；
   数字后面缀一个「人」，否则孤零零一个数字看不出是人数。 */
.bd__tiers{
  flex:0 0 auto;display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(6px,.5vw,12px);
}
.tier{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;gap:clamp(1px,.14vw,3px);
  padding:clamp(5px,.42vw,11px) clamp(4px,.36vw,9px);border-radius:var(--r);
  border:1px solid rgba(255,220,155,.30);background:rgba(58,4,4,.42);
}
.tier span{
  display:block;white-space:nowrap;color:rgba(255,246,232,.74);
  font-size:clamp(9px,.6vw,13px);letter-spacing:.02em;
}
.tier b{
  display:block;color:var(--gold-3);line-height:1;
  font-size:clamp(16px,1.16vw,26px);font-weight:800;font-variant-numeric:tabular-nums;
}
.tier b i{font-style:normal;font-size:.52em;font-weight:600;margin-left:.18em;opacity:.78}

/* ============================================================
   底部
   v0.5.0：原本的「共 N 人已登记」「N 秒自动翻页 · 共 N 条」
   「数据时间 / 页码」四处已移除，这里只剩右下角的全屏按钮，
   所以当时不再画通栏分隔线，避免在空底栏上留一条多余的横线。
   v2.5：左下角加回「已参与 N 人」（用户明确要求，且要实时更新）——
          底栏因此改成两端对齐；分隔线依旧不画，保持干净。
   ============================================================ */
.bd__ft{
  flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;
  gap:var(--gap);
  padding:0 var(--pad) calc(var(--pad) * .6);
  position:relative;z-index:2;
}

/* 左下角实时参与人数 */
.bd__count{
  display:inline-flex;align-items:baseline;gap:.34em;
  color:var(--ink-3);letter-spacing:.06em;
  font-size:clamp(11px,.8vw,17px);
}
.bd__count b{
  color:var(--gold-3);font-weight:800;
  font-variant-numeric:tabular-nums;
  font-size:clamp(17px,1.42vw,32px);line-height:1;
  text-shadow:0 1px 2px rgba(112,0,0,.55), 0 0 clamp(8px,.6vw,16px) rgba(255,214,150,.34);
}
.bd__count i{font-style:normal}
/* 数字变化时轻轻跳一下 —— "实时"要看得出来，但不能像报错一样闪 */
.bd__count.is-up b{animation:countPop .9s cubic-bezier(.2,1.5,.35,1) both}
@keyframes countPop{
  0%  {transform:scale(1.28)}
  100%{transform:scale(1)}
}

/* 右下角全屏按钮 */
.bd__full{
  display:inline-flex;align-items:center;gap:.5em;
  height:clamp(26px,1.9vw,40px);padding:0 clamp(10px,.8vw,18px);
  border:1px solid var(--gold-line);border-radius:var(--r);
  background:transparent;color:var(--ink-2);cursor:pointer;
  font-family:inherit;font-size:clamp(11px,.74vw,16px);letter-spacing:.02em;
  transition:color .2s,border-color .2s;
}
.bd__full:hover{color:var(--gold);border-color:var(--gold)}
.bd__full svg{width:1em;height:1em;flex:0 0 auto}
.bd__full.is-off,.bd__full.is-hide{display:none}

/* ============================================================
   中心弹出（每新增一条登记，从屏幕正中弹出）
   ============================================================ */
.pop{
  position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;
  pointer-events:none;opacity:0;transition:opacity .28s ease;
  background:radial-gradient(60% 50% at 50% 50%, rgba(0,0,0,.5) 0%, rgba(0,0,0,.72) 100%);
}
.pop.on{opacity:1}

.pop__ring{
  position:absolute;width:clamp(280px,27vw,600px);aspect-ratio:1;
  border-radius:50%;border:1px solid var(--gold);opacity:0;
}
.pop.on .pop__ring{animation:popRing 1.1s cubic-bezier(.15,.8,.25,1) both}
@keyframes popRing{
  0%{transform:scale(.4);opacity:0}
  28%{opacity:.8}
  100%{transform:scale(1.6);opacity:0}
}

.pop__card{
  position:relative;display:flex;flex-direction:column;align-items:center;
  gap:clamp(4px,.45vw,12px);
  min-width:clamp(220px,17vw,380px);
  max-width:clamp(280px,26vw,540px);
  padding:clamp(20px,1.7vw,44px) clamp(24px,2.1vw,54px) clamp(20px,1.75vw,46px);
  border-radius:var(--r-md);
  border:1px solid var(--gold);
  background:linear-gradient(180deg,#8a1414 0%,#5a0a0a 100%);
  box-shadow:0 0 clamp(36px,3.4vw,96px) rgba(0,0,0,.6);
  transform:scale(.8) translateY(10px);opacity:0;
}
.pop.on .pop__card{animation:popCard .8s cubic-bezier(.18,1.2,.35,1) both}
@keyframes popCard{
  0%{transform:scale(.8) translateY(10px);opacity:0}
  45%{transform:scale(1.02);opacity:1}
  100%{transform:scale(1);opacity:1}
}

.pop__badge{
  position:absolute;top:clamp(-10px,-.72vw,-17px);left:50%;transform:translateX(-50%);
  padding:clamp(3px,.28vw,7px) clamp(10px,.85vw,20px);
  border-radius:var(--r);background:var(--gold);
  color:#7a1008;font-weight:700;letter-spacing:.12em;
  font-size:clamp(11px,.8vw,17px);white-space:nowrap;
}
.pop__av{
  width:clamp(60px,5.2vw,124px);height:clamp(60px,5.2vw,124px);border-radius:50%;
  object-fit:cover;border:clamp(2px,.16vw,4px) solid rgba(255,255,255,.94);
  background:rgba(255,255,255,.08);
  box-shadow:0 0 clamp(12px,1vw,28px) rgba(255,224,168,.30);
}
.pop__av--ph{
  display:flex;align-items:center;justify-content:center;
  color:var(--gold);font-weight:600;font-size:clamp(26px,2.2vw,52px);
}
.pop__name{
  font-size:clamp(26px,2.4vw,58px);font-weight:700;letter-spacing:.04em;line-height:1.15;
  text-align:center;
}
.pop__area{
  color:var(--ink-2);letter-spacing:.08em;font-size:clamp(12px,.95vw,22px);text-align:center;
}
.pop__duty{
  margin-top:clamp(2px,.3vw,8px);
  color:var(--gold);font-weight:700;line-height:1;
  font-size:clamp(30px,2.8vw,68px);font-variant-numeric:tabular-nums;
}
.pop__duty i{font-style:normal;font-size:.52em;margin-left:.2em;opacity:.85}

/* ============================================================
   烟花层（铺满整屏，从奖池中心向外）
   ============================================================ */
.fx{
  position:fixed;inset:0;z-index:40;pointer-events:none;
  width:100%;height:100%;
}

/* ============================================================
   空态 / 提示
   ============================================================ */
.bd__empty{
  position:absolute;inset:0;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:clamp(8px,.8vw,18px);
  color:var(--ink-3);letter-spacing:.06em;font-size:clamp(13px,1vw,22px);
}
.bd__empty b{color:var(--gold);font-size:clamp(16px,1.25vw,28px)}
/* 有数据时藏空态、无数据时藏网格 —— 用同一个开关类，避免出现两种空状态 */
.bd__pages.is-empty .bd__flow{display:none}
.bd__pages:not(.is-empty) .bd__empty{display:none}

/* 竖屏 / 窄屏兜底
   v2.4：头部现在是「标题 + 档位分布」，档位在窄屏放不下就整条挪到下面；
   右栏的「奖池 + 二维码」在窄屏改为横排，省纵向空间。
   v2.5：横排变成三块（奖池 / 责任额排行 / 二维码），排行给一个受控宽度，
         高度改为自适应但**封顶** —— 不封顶的话它会按内容一路长下去，
         board.js 量出来"能放几行"就会无穷大。 */
@media (max-aspect-ratio:1/1){
  .bd__hd{flex-direction:column;align-items:stretch;gap:calc(var(--gap) * .9)}
  .bd__hd .bd__tiers{width:auto;align-self:stretch}

  .bd__main{grid-template-columns:1fr;grid-template-rows:minmax(0,1fr) auto}
  .bd__side{flex-direction:row;align-items:stretch;justify-content:flex-start;gap:var(--gap)}
  .bd__side .jp{flex:1 1 auto;min-width:0}
  /* v2.5：竖屏时三块并排成一行。★ 这里必须给「定高」而不是 height:auto + max-height：
     height:auto 时 .lb__list 会被内容撑开，board.js 量 clientHeight 就量到"全部 42 行"，
     lbCapacity() 算出 42 → 一次渲染 42 个 li → 超出的全被裁掉、TOP 标成 TOP 42。
     给死高度后 clientHeight 恒等于"真正看得见的那块"，行数反推才准。 */
  .bd__side .lb{width:clamp(190px,25vw,330px);height:clamp(150px,26vh,300px)}
  .qr{justify-content:center}
}

/* 低性能 / 省电兜底
   v2.4：祥云漂移已随网点底纹一起去掉（.bd::before 现在是静态网点，不用停）；
   新增的「对奖轮盘刻度环」要一并停，并且停在一个"看得见"的帧上。
   v2.5：排行重排的高亮、人数跳字也一并停（信息本身照常更新，只是不动画）。 */
@media (prefers-reduced-motion:reduce){
  .jp__ring,.jp__pulse,.jp__sweep,.bd__pages::after,
  .bd__main::after,.rc__ring::after{animation:none}
  .lb__row.is-up{animation:none;background:transparent}
  .bd__count.is-up b{animation:none}
  .jp__pulse{opacity:.3}
  .bd__main::after{opacity:.55}
  .bd__pages::after{display:none}
  .rc__ring::after{opacity:.34}
  /* 入场改回「直接出现」，不做缩放与光晕扩散 */
  .rc{animation:rcIn .2s linear both}
  .rc.is-new .rc__ring{animation:none}
  .rc.is-new .rc__ring::before{animation:none;opacity:0}
  .fx{display:none}
}
