/* ==========================================================================
   活动报名 · 公共样式（移动优先，微信内置浏览器为主要环境）
   --------------------------------------------------------------------------
   为什么手写而不是引框架：微信里最要紧的是**首屏体积**。这个文件 gzip 后
   不到 4KB，换 bootstrap/tailwind 的任意一个都是 10 倍起。
   另一条硬约束是 CSP `script-src 'self'`（server.js）—— 不引任何 CDN 资源，
   连字体都用系统栈，少一个外部依赖就少一个"哪天被墙了页面就丑了"的故障域。

   设计令牌集中在 :root，admin.css 复用同一套，两边风格不会漂移。
   ========================================================================== */

:root {
  --ink: #15171c;
  --ink2: #4a5160;
  /* ★ 三级灰的取值不是审美问题 ★
     #8b93a3 在浅底上只有 2.8:1，远低于 WCAG AA 的 4.5:1 —— 而它承载的
     恰恰是页脚、提示语、次要说明这些**字号最小**的文字。读者是手机上
     的中年客户，不是设计评审。压到 #5f6878（5.15:1）后仍明显轻于 --ink2，
     层级还在，但看得清了。 */
  --ink3: #5f6878;
  --line: #e6e9ef;
  --line2: #f0f2f6;
  --bg: #f4f5f7;
  --card: #fff;

  --brand: #15497a;
  --brand-d: #0f3557;
  --brand-l: #eaf1f9;
  /* 金色同理：原 #b98a3c 无论当文字（浅底 2.8:1）还是当按钮底（白字 3.1:1）
     都不达标。压深后的赭金在两种用法下分别是 4.9:1 / 5.4:1。 */
  --gold: #8a6420;
  --gold-l: #fbf3e4;

  --ok: #0f7a4d;
  --ok-l: #e8f5ee;
  --warn: #a35a00;
  --warn-l: #fdf3e3;
  --danger: #c0392b;
  --danger-l: #fdecea;

  --r: 14px;
  --r-s: 10px;
  --shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 8px 24px -14px rgba(16, 24, 40, .18);
  --maxw: 720px;

  /* 底部吸底栏 + iPhone 安全区。少了 env() 在全面屏上会被小黑条压住按钮，
     而"按钮按不到"是那种用户不会反馈、直接退出的问题。 */
  --safe-b: env(safe-area-inset-bottom, 0px);
}

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

html {
  /* iOS 横屏时不许自动放大字号 —— 默认行为会让排版看起来"突然变大" */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.65 -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB",
        "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  /* 微信里点任何东西都会闪一块灰底，看着像"加载中" */
  -webkit-tap-highlight-color: transparent;
}

img { max-width: 100%; display: block; }

a { color: var(--brand); text-decoration: none; }
a:active { opacity: .7; }

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.35; }
p { margin: 0 0 .8em; }
hr { border: 0; border-top: 1px solid var(--line); margin: 20px 0; }

/* ---------------- 骨架 ---------------- */

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 16px; }

.topbar {
  position: sticky; top: 0; z-index: 30;
  background: rgba(255, 255, 255, .92);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.topbar__in {
  max-width: var(--maxw); margin: 0 auto; padding: 10px 16px;
  display: flex; align-items: center; gap: 10px; min-height: 50px;
}
.topbar__brand { display: flex; align-items: center; gap: 8px; font-weight: 600; letter-spacing: .2px; }
.topbar__logo {
  width: 26px; height: 26px; border-radius: 8px; flex: 0 0 auto;
  background: linear-gradient(145deg, var(--brand), #2f6ea8);
  color: #fff; font-size: 14px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.topbar__sp { flex: 1; }

.page { padding-bottom: calc(28px + var(--safe-b)); }
.page--bar { padding-bottom: calc(84px + var(--safe-b)); }   /* 给吸底栏留位 */

.section-title {
  margin: 22px 0 10px; font-size: 15px; color: var(--ink2);
  display: flex; align-items: center; gap: 8px;
}
.section-title::after { content: ""; flex: 1; height: 1px; background: var(--line); }

.card {
  background: var(--card); border-radius: var(--r);
  box-shadow: var(--shadow); overflow: hidden;
}
.card + .card { margin-top: 14px; }
.card__body { padding: 16px; }

.footer {
  margin: 28px 0 0; padding: 18px 0 0; border-top: 1px solid var(--line);
  color: var(--ink3); font-size: 12px; text-align: center; line-height: 1.9;
}

/* ---------------- 活动列表卡 ---------------- */

.evlist { display: flex; flex-direction: column; gap: 14px; }

.evcard { display: block; color: inherit; background: var(--card); border-radius: var(--r);
          box-shadow: var(--shadow); overflow: hidden; }
.evcard__cover { position: relative; aspect-ratio: 16 / 9; background: var(--brand-l); }
.evcard__cover img { width: 100%; height: 100%; object-fit: cover; }
.evcard__cover--none {
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(145deg, #1c5488, #0f3557);
  color: rgba(255, 255, 255, .9); font-size: 15px; letter-spacing: 2px; padding: 0 20px;
  text-align: center;
}
.evcard__body { padding: 13px 15px 15px; }
.evcard__title { font-size: 17px; line-height: 1.45; margin-bottom: 8px; }
.evcard__sum {
  color: var(--ink2); font-size: 13.5px; margin: 6px 0 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.evcard__foot {
  margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--line2);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}

/* 角标：名额状态。放在封面右上，是列表里最先被看到的信息 */
.corner {
  position: absolute; top: 10px; right: 10px;
  padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 600;
  background: rgba(0, 0, 0, .55); color: #fff; backdrop-filter: blur(4px);
}
.corner--hot { background: rgba(185, 138, 60, .95); }
.corner--full { background: rgba(70, 74, 84, .9); }

/* ---------------- 元信息行 ---------------- */

.meta { display: flex; gap: 8px; color: var(--ink2); font-size: 14px; margin-top: 6px; }
.meta__ic { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 3px; color: var(--ink3); }
.meta__ic svg { width: 16px; height: 16px; display: block; }
.meta__tx { flex: 1; min-width: 0; }
.meta--strong .meta__tx { color: var(--ink); font-weight: 600; }

/* ---------------- 徽标 ---------------- */

.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 999px; font-size: 12px; font-weight: 600;
  background: var(--line2); color: var(--ink2); white-space: nowrap;
}
.badge--ok { background: var(--ok-l); color: var(--ok); }
.badge--warn { background: var(--warn-l); color: var(--warn); }
.badge--danger { background: var(--danger-l); color: var(--danger); }
.badge--gold { background: var(--gold-l); color: var(--gold); }
.badge--brand { background: var(--brand-l); color: var(--brand); }

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

.btn {
  appearance: none; border: 1px solid transparent; border-radius: var(--r-s);
  padding: 11px 18px; font-size: 16px; font-weight: 600; font-family: inherit;
  background: var(--line2); color: var(--ink); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition: transform .06s ease, opacity .15s ease;
}
.btn:active { transform: scale(.985); }
.btn[disabled] { opacity: .45; cursor: not-allowed; }
.btn--primary { background: var(--brand); color: #fff; }
.btn--gold { background: var(--gold); color: #fff; }
.btn--ghost { background: #fff; border-color: var(--line); color: var(--ink); }
.btn--danger { background: #fff; border-color: #f0c4bf; color: var(--danger); }
.btn--block { display: flex; width: 100%; }
.btn--lg { padding: 14px 20px; font-size: 17px; border-radius: 12px; }
.btn--sm { padding: 6px 12px; font-size: 13px; border-radius: 8px; font-weight: 500; }
.btn--bare { background: none; padding: 6px 4px; color: var(--brand); font-weight: 500; }

/* ---------------- 表单 ---------------- */

.field { margin-bottom: 15px; }
.label { display: block; font-size: 13.5px; color: var(--ink2); margin-bottom: 6px; font-weight: 500; }
.label .req { color: var(--danger); margin-left: 3px; }

.input, .select, .textarea {
  width: 100%; padding: 11px 13px; border: 1px solid var(--line);
  border-radius: var(--r-s); background: #fff; color: var(--ink);
  /* ★ 16px 不是排版选择 ★ iOS Safari 对 <16px 的输入框会在聚焦时自动放大
     整个页面，而放大后用户要手动缩回去才能看到提交按钮 —— 很多人就此放弃。 */
  font-size: 16px; font-family: inherit; line-height: 1.4;
  appearance: none; outline: none;
}
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-l);
}
.input::placeholder, .textarea::placeholder { color: #b6bcc8; }
.textarea { resize: vertical; min-height: 68px; }
.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5 6 8l3-3.5' fill='none' stroke='%238b93a3' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 12px;
  padding-right: 34px;
}
.input.is-bad, .textarea.is-bad { border-color: var(--danger); }

.hint { font-size: 12.5px; color: var(--ink3); margin-top: 5px; }
.hint--bad { color: var(--danger); }
.row2 { display: flex; gap: 10px; }
.row2 > * { flex: 1; min-width: 0; }

/* 蜜罐字段：真人看不到，脚本会填。
   用 position:absolute + 负偏移，而不是 display:none —— 部分自动化框架会跳过
   不可见元素，而对"移出视口"的元素照填不误。 */
.hp {
  position: absolute !important; left: -9999px !important; top: auto;
  width: 1px; height: 1px; overflow: hidden; opacity: 0;
}

/* ---------------- 吸底操作栏 ---------------- */

.bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  background: rgba(255, 255, 255, .96);
  backdrop-filter: saturate(180%) blur(12px);
  border-top: 1px solid var(--line);
  padding: 10px 16px calc(10px + var(--safe-b));
}
.bar__in { max-width: var(--maxw); margin: 0 auto; display: flex; align-items: center; gap: 12px; }
.bar__info { flex: 1; min-width: 0; font-size: 13px; color: var(--ink2); line-height: 1.4; }
.bar__info b { color: var(--ink); font-size: 15px; }
.bar__btn { flex: 0 0 auto; }

/* ---------------- 底部弹出表单 ---------------- */

.sheet {
  position: fixed; inset: 0; z-index: 60; display: none;
}
.sheet.is-open { display: block; }
.sheet__mask { position: absolute; inset: 0; background: rgba(12, 16, 24, .45); }
.sheet__panel {
  position: absolute; left: 0; right: 0; bottom: 0;
  max-height: 92vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: #fff; border-radius: 18px 18px 0 0;
  padding: 8px 18px calc(20px + var(--safe-b));
  animation: sheetUp .22s cubic-bezier(.2, .8, .3, 1);
}
@keyframes sheetUp { from { transform: translateY(14px); opacity: .6; } to { transform: none; opacity: 1; } }
.sheet__grab { width: 36px; height: 4px; border-radius: 2px; background: var(--line); margin: 6px auto 14px; }
.sheet__title { font-size: 17px; margin-bottom: 3px; }
.sheet__sub { font-size: 13px; color: var(--ink3); margin-bottom: 14px; }

/* ---------------- 正文排版（bodydoc 渲染出来的片段） ---------------- */

.body-doc { font-size: 16.5px; line-height: 1.85; color: #23262d; word-wrap: break-word; }
.body-doc h2 { font-size: 19px; margin: 26px 0 10px; padding-left: 10px; border-left: 3px solid var(--brand); }
.body-doc h3 { font-size: 17px; margin: 20px 0 8px; color: var(--ink); }
.body-doc p { margin: 0 0 14px; }
.body-doc ul, .body-doc ol { margin: 0 0 14px; padding-left: 22px; }
.body-doc li { margin-bottom: 6px; }
.body-doc blockquote {
  margin: 0 0 14px; padding: 12px 14px; background: var(--line2);
  border-left: 3px solid #cfd6e2; border-radius: 0 var(--r-s) var(--r-s) 0;
  color: var(--ink2); font-size: 15.5px;
}
.body-doc .bd-note {
  margin: 0 0 14px; padding: 12px 14px; background: var(--gold-l);
  border-radius: var(--r-s); color: #6b4f1c; font-size: 15px;
}
.body-doc img { border-radius: var(--r-s); margin: 6px 0 16px; height: auto; }
.body-doc a { border-bottom: 1px solid currentColor; }
.body-doc strong { color: #000; }

/* ---------------- 加载 / 空态 ---------------- */

.skeleton {
  background: linear-gradient(90deg, #eceef2 25%, #f5f6f8 37%, #eceef2 63%);
  background-size: 400% 100%; animation: sk 1.3s ease-in-out infinite;
  border-radius: var(--r); height: 190px;
}
@keyframes sk { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

.empty { text-align: center; padding: 54px 20px; color: var(--ink3); }
.empty__big { font-size: 34px; margin-bottom: 10px; opacity: .5; }

.loading { display: flex; align-items: center; justify-content: center; gap: 8px;
           padding: 40px 0; color: var(--ink3); font-size: 14px; }
.spin {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--brand);
  animation: rot .7s linear infinite;
}
@keyframes rot { to { transform: rotate(360deg); } }

/* ---------------- 提示条 ---------------- */

.toast {
  position: fixed; left: 50%; bottom: calc(96px + var(--safe-b)); transform: translateX(-50%) translateY(8px);
  z-index: 90; max-width: 86vw;
  padding: 11px 18px; border-radius: 999px; font-size: 14.5px; font-weight: 500;
  background: rgba(21, 23, 28, .92); color: #fff; box-shadow: var(--shadow);
  opacity: 0; pointer-events: none; transition: opacity .18s ease, transform .18s ease;
  text-align: center;
}
.toast.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast--bad { background: rgba(192, 57, 43, .95); }
.toast--ok { background: rgba(15, 122, 77, .95); }

/* 页面级提示块（不是浮层）：报名失败这类需要用户读两遍的信息 */
.alert { padding: 12px 14px; border-radius: var(--r-s); font-size: 14.5px; margin-bottom: 14px; }
.alert--bad { background: var(--danger-l); color: var(--danger); }
.alert--warn { background: var(--warn-l); color: var(--warn); }
.alert--ok { background: var(--ok-l); color: var(--ok); }
.alert--info { background: var(--brand-l); color: var(--brand); }

/* ---------------- 票面 ---------------- */

.ticket { background: var(--card); border-radius: var(--r); box-shadow: var(--shadow); overflow: hidden; }
.ticket__top {
  background: linear-gradient(150deg, #1c5488, #0f3557);
  color: #fff; padding: 22px 20px 20px; text-align: center;
}
.ticket__label { font-size: 12.5px; opacity: .78; letter-spacing: 3px; }
.ticket__no {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 34px; font-weight: 700; letter-spacing: 5px; margin: 8px 0 4px;
  word-break: break-all;
}
.ticket__hint { font-size: 12.5px; opacity: .72; }
.ticket__qr { padding: 20px 20px 6px; display: flex; justify-content: center; }
.ticket__qr canvas, .ticket__qr img { border-radius: 8px; }
.ticket__rows { padding: 6px 20px 20px; }
.trow { display: flex; gap: 12px; padding: 9px 0; border-bottom: 1px dashed var(--line); font-size: 15px; }
.trow:last-child { border-bottom: 0; }
.trow__k { flex: 0 0 72px; color: var(--ink3); font-size: 14px; }
.trow__v { flex: 1; min-width: 0; word-break: break-word; }
.trow__v--mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 1px; }

/* 已取消的票：票根去色 + 二维码位置换成一枚字样。
   目的不是好看 —— 是让客户和志愿者当场都能看出"这张票已经不能用了"，
   而不是扫完才被核销页拒掉。 */
.ticket--void .ticket__top { background: linear-gradient(150deg, #6b7280, #4b5563); }
.ticket__void {
  width: 100%; padding: 34px 0; text-align: center;
  font-size: 22px; font-weight: 700; letter-spacing: 6px;
  color: var(--danger); background: var(--danger-l); border-radius: var(--r-s);
}

.stamp {
  display: inline-block; padding: 3px 10px; border-radius: 6px;
  border: 1.5px solid currentColor; font-size: 12.5px; font-weight: 700; letter-spacing: 1px;
}
.stamp--ok { color: var(--ok); }
.stamp--warn { color: var(--warn); }
.stamp--danger { color: var(--danger); }

/* ---------------- 成功页 ---------------- */

.done { text-align: center; padding: 30px 16px 10px; }
.done__ic {
  width: 62px; height: 62px; margin: 0 auto 14px; border-radius: 50%;
  background: var(--ok-l); color: var(--ok);
  display: flex; align-items: center; justify-content: center;
}
.done__ic svg { width: 32px; height: 32px; }
.done__t { font-size: 20px; margin-bottom: 6px; }
.done__s { color: var(--ink2); font-size: 14.5px; }

/* ---------------- 小工具 ---------------- */

.mt0 { margin-top: 0; }
.mt8 { margin-top: 8px; }
.mt12 { margin-top: 12px; }
.mt16 { margin-top: 16px; }
.mt24 { margin-top: 24px; }
.tc { text-align: center; }
.muted { color: var(--ink3); }
.small { font-size: 13px; }
.nowrap { white-space: nowrap; }
.gap { display: flex; gap: 10px; }
.gap > * { flex: 1; }
.hide { display: none !important; }

/* ===== 海报页（/p/<slug>） ===== */

.psizes { display: flex; gap: 8px; justify-content: center; margin-bottom: 14px; }
.psizes .btn { flex: 0 1 auto; }
/* 必须能一眼看出当前是哪个尺寸 —— 否则用户不知道自己拿到的是哪一版，
   存下来发现被裁掉了才回头找原因。 */
.psizes .btn.is-on {
  background: var(--brand-l); border-color: var(--brand);
  color: var(--brand); font-weight: 600;
}

.pbox {
  border-radius: var(--r);
  overflow: hidden;
  background: var(--line2);
  box-shadow: var(--shadow);
}
/* display:block 是必须的：img 默认是行内元素，会在底部留出几像素的
   基线空隙，衬在圆角容器里就是一条灰线。 */
.pbox img { display: block; width: 100%; height: auto; }

.phint {
  margin: 12px 0 0;
  text-align: center;
  font-size: 13px;
  line-height: 1.65;
  color: var(--ink3);
}

.pops { display: flex; gap: 10px; margin-top: 16px; }
.pops .btn { flex: 1; }

/* ===== 现场核销页（/checkin） ===== */

/* 核销结果浮层。三种颜色就是三种结论，不留中间态：
   绿 = 这次核销成功，黄 = 已经核销过 / 已撤销（正常，但要留意），
   红 = 不能核销（已取消）。做成整块而不是 toast，理由见 checkin.html。 */
.ckflash {
  position: fixed; left: 50%; top: 20%; z-index: 95;
  transform: translateX(-50%) translateY(6px) scale(.96);
  min-width: 60vw; max-width: 88vw;
  padding: 22px 26px; border-radius: 18px; text-align: center;
  color: #fff; box-shadow: 0 18px 48px -12px rgba(12, 16, 24, .55);
  opacity: 0; pointer-events: none;
  transition: opacity .16s ease, transform .16s ease;
}
.ckflash.is-on { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
.ckflash--ok { background: rgba(15, 122, 77, .97); }
.ckflash--warn { background: rgba(163, 90, 0, .97); }
.ckflash--bad { background: rgba(192, 57, 43, .97); }
.ckflash__ic { display: flex; justify-content: center; margin-bottom: 8px; }
.ckflash__t { font-size: 21px; font-weight: 700; letter-spacing: .5px; }
.ckflash__s { font-size: 14px; opacity: .92; margin-top: 6px; }

.cklist { display: flex; flex-direction: column; gap: 10px; }

.ckrow {
  display: flex; align-items: center; gap: 12px;
  background: var(--card); border-radius: var(--r);
  box-shadow: var(--shadow); padding: 13px 14px;
}
/* 已取消的行整体去色：志愿者扫到它时，第一眼就该知道"这张票废了"，
   而不是读完状态徽标才反应过来 */
.ckrow--dead { opacity: .62; }
.ckrow__main { flex: 1; min-width: 0; }
.ckrow__name { font-size: 17px; font-weight: 600; }
.ckrow__ps {
  margin-left: 8px; font-size: 12.5px; font-weight: 600;
  color: var(--brand); background: var(--brand-l);
  padding: 1px 7px; border-radius: 999px;
}
.ckrow__sub { color: var(--ink2); font-size: 13.5px; margin-top: 2px; }
.ckrow__tno {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 14px; letter-spacing: 1.5px; color: var(--ink3); margin-top: 3px;
}
.ckrow__st { margin-top: 7px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ckrow__act { flex: 0 0 auto; }
.ckrow__no { font-size: 12.5px; color: var(--ink3); white-space: nowrap; }

.cklogs { padding: 4px 16px; }
.cklog {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 0; border-bottom: 1px solid var(--line2); font-size: 13.5px;
}
.cklog:last-child { border-bottom: 0; }
.cklog__op { flex: 0 0 auto; color: var(--ink); font-weight: 600; }
.cklog__nm { flex: 1; min-width: 0; color: var(--ink2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cklog__by { flex: 0 0 auto; color: var(--ink3); }
.cklog__at { flex: 0 0 auto; color: var(--ink3); font-variant-numeric: tabular-nums; }

/* ===== 活动日历页（/calendar） ===== */

/* 月份导航条。两侧是纯图标按钮、标题居中撑开 —— 标题宽度在"2026年11月"
   和"11月2日 – 11月8日"之间变化，按钮若跟着标题走，翻月时会左右跳。 */
.calbar { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
.calbar__title { flex: 1; text-align: center; font-size: 17px; font-weight: 600; }

.calnav {
  flex: 0 0 auto; width: 36px; height: 36px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: #fff; border: 1px solid var(--line); border-radius: 50%;
  color: var(--brand); cursor: pointer; font-family: inherit;
}
.calnav:active { background: var(--brand-l); }

/* 月 / 周切换 */
.caltabs { display: flex; gap: 8px; margin-bottom: 12px; }
.caltabs__b {
  flex: 1; padding: 8px 0; font-size: 14px; font-weight: 600; font-family: inherit;
  background: #fff; border: 1px solid var(--line); border-radius: var(--r-s);
  color: var(--ink2); cursor: pointer;
}
.caltabs__b.is-on { background: var(--brand); border-color: var(--brand); color: #fff; }

/* 月历网格。table-layout:fixed 保证 7 列等宽 —— 否则某个格子内容长一点
   就会把那一列撑宽，整张表跟着歪。 */
.cal__grid { width: 100%; table-layout: fixed; border-collapse: collapse; }
.cal__grid th {
  padding: 0 0 6px; font-size: 12px; font-weight: 500;
  color: var(--ink3); text-align: center;
}
.cal__cell { padding: 0; vertical-align: top; }

.cal__day {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; width: 100%; min-height: 44px; padding: 5px 0 6px;
  background: none; border: 0; border-radius: var(--r-s);
  font: inherit; font-size: 14px; color: var(--ink); cursor: default;
}
/* 只有"当天有活动"的格子才做成按钮（点了能滚到议程）。
   没活动的格子用 <span>：看起来能点、点了却没反应，比看起来就不能点更气人。 */
button.cal__day { cursor: pointer; }
button.cal__day:active { background: var(--line2); }

.cal__num { line-height: 1.1; }
/* ★「今天」不能只靠颜色 ★ 色弱用户分不出品牌蓝和深灰，
   所以再加一条下划线 —— 形状是第二重信号。 */
.cal__day.is-today .cal__num {
  color: var(--brand); font-weight: 700;
  border-bottom: 2px solid var(--brand); padding-bottom: 1px;
}

.cal__dots { display: flex; gap: 3px; height: 5px; }
.cal__dot { width: 5px; height: 5px; border-radius: 50%; background: var(--brand); }
.cal__dot--soon { background: var(--gold); }
.cal__dot--dead { background: #b6bcc8; }

/* 议程区 */
.calagenda { margin-top: 16px; }
.calgroup { padding: 0 0 4px; border-radius: var(--r); transition: background .35s ease; }
.calgroup__d { padding: 12px 6px 6px; font-size: 13px; font-weight: 600; color: var(--ink3); }
.calgroup.is-today .calgroup__d { color: var(--brand); }
.calgroup__tag {
  margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  background: var(--brand-l); color: var(--brand); font-size: 11.5px;
}
.calgroup__none { padding: 2px 6px 8px; font-size: 13px; color: var(--ink3); }
/* 点了月历格子后，短暂高亮它对应的那段议程。用底色不用描边 ——
   描边会改变行高，页面会当场跳一下。 */
.calgroup.is-hit { background: var(--brand-l); }

.calitem {
  display: block; margin-bottom: 8px; padding: 12px 14px;
  background: var(--card); border-radius: var(--r); box-shadow: var(--shadow);
  color: inherit;
}
/* 已结束的整行去色。沿用核销页 .ckrow--dead 的手法：用 opacity 一次压掉
   标题/时间/角标，而不是逐个改字色（漏掉一个就看着不协调）。 */
.calitem.is-dead { opacity: .55; }
.calitem__t { font-size: 16px; font-weight: 600; line-height: 1.4; }
.calitem__m {
  display: flex; align-items: flex-start; gap: 6px;
  margin-top: 5px; font-size: 13px; color: var(--ink2);
}
.calitem__m svg { flex: 0 0 auto; width: 14px; height: 14px; margin-top: 2px; color: var(--ink3); }
.calitem__foot { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 9px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
