/* ============================================================
   Vib14: Clash — Spectator Theme
   Design System: DESIGN.md + design-system-preview.html
   CGA Retro-Futuristic Terminal Aesthetic
   ============================================================ */

:root {
  /* --- Fonts --- */
  --mono: 'IBM Plex Mono', monospace;
  --body: 'Noto Sans SC', 'Noto Sans', sans-serif;

  /* --- Backgrounds (CGA Black variants) --- */
  --bg-start: #07111c;
  --bg-mid:   #0f2030;
  --bg-end:   #1d1208;
  --surface:  rgba(255,255,255,0.03);
  --surface-hover: rgba(255,255,255,0.06);

  /* --- Text (CGA soft variants) --- */
  --cream:  #f8f4e4;   /* White soft */
  --text-default: #f6f2df;
  --gold:   #ffdd99;   /* Yellow soft */
  --magenta: #ff55ff;   /* CGA #13 Lt Magenta — busk 卖艺帖专属 (DESIGN.md §CGA 16 色 line 79 "未使用，可用于特殊效果") */
  --blue:   #9ad6ff;   /* Lt Blue soft */
  --beige:  #f2e6bf;   /* Yellow+Brown soft */
  --muted:  #6e8794;   /* DkCyan+DkGray soft — WCAG AA 5:1 on --bg-start */

  /* --- Accents --- */
  --cyan:   #75d7e6;         /* Lt Cyan soft — brand */
  --border-gold: #f0c35f;   /* Yellow+Brown soft — dividers */
  --terminal-green: #55ff55; /* Lt Green exact CGA */

  /* --- Events --- */
  --event-battle:   #ff9c5b; /* LtRed+Brown */
  --event-jump:     #58707d; /* DkCyan+DkGray */
  --event-level:    #f0c35f; /* Yellow+Brown */
  --event-register: #84d96c; /* Lt Green soft */

  /* --- Status (SSE 三态) --- */
  --status-live:      #55ff55; /* Lt Green exact CGA */
  --status-reconnect: #f0c35f; /* Yellow soft */
  --status-offline:   #ff5555; /* Lt Red exact CGA */

  /* --- Weapons --- */
  --weapon-sword: #d0a030; /* 剑 */
  --weapon-spear: #55c6d9; /* 枪 */
  --weapon-axe:   #d04848; /* 斧 */

  /* --- Frame Colors (Canvas section borders) --- */
  --frame-arena:    #75d7e6; /* Cyan */
  --frame-feed:     #9bbce9; /* Steel Blue */
  --frame-lb:       #c49bff; /* Purple */
  --frame-graffiti: #c4a878; /* Khaki — wall留痕 vibe */
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; -webkit-font-smoothing: antialiased; background-color: #07111c; }

/* --- PIXEL GRID OVERLAY (whole page) --- */
body::before {
  content: '';
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background-image:
    linear-gradient(rgba(117,215,230,0.015) 1px, transparent 1px),
    linear-gradient(90deg, rgba(117,215,230,0.015) 1px, transparent 1px);
  background-size: 16px 16px;
  pointer-events: none;
  z-index: 0;
}

body {
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.6;
  background: linear-gradient(180deg, var(--bg-start) 0%, var(--bg-mid) 48%, var(--bg-end) 100%);
  background-attachment: fixed;
  color: var(--cream);
  min-height: 100vh;
  /* CJK ↔ Latin/数字自动加 ~1/8em 间距 (Chrome 120+, Edge 120+) */
  text-autospace: ideograph-alpha ideograph-numeric;
}

a { color: var(--cyan); text-decoration: none; transition: color 0.15s, text-shadow 0.15s; }
a:hover { color: var(--terminal-green); text-shadow: 0 0 8px rgba(85,255,85,0.5); }

/* --- SHELL (terminal window) --- */
.shell {
  position: relative;
  z-index: 1;
  max-width: 960px;
  margin: 32px auto;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
  background: var(--surface);
  background: var(--surface);
}

/* Pixel border on shell — dashed CGA pattern */
.shell::before {
  content: '';
  position: absolute;
  top: -2px; left: -2px; right: -2px; bottom: -2px;
  background:
    linear-gradient(90deg, var(--cyan) 2px, transparent 2px) 0 0 / 8px 2px repeat-x,
    linear-gradient(90deg, var(--cyan) 2px, transparent 2px) 0 100% / 8px 2px repeat-x,
    linear-gradient(var(--cyan) 2px, transparent 2px) 0 0 / 2px 8px repeat-y,
    linear-gradient(var(--cyan) 2px, transparent 2px) 100% 0 / 2px 8px repeat-y;
  opacity: 0.2;
  pointer-events: none;
}

/* Gold corners on shell — all 4 via explicit divs */
.shell-corner {
  position: absolute;
  width: 16px;
  height: 16px;
  pointer-events: none;
  z-index: 10;
}
.shell-corner.tl { top: -2px; left: -2px; border-top: 3px solid var(--border-gold); border-left: 3px solid var(--border-gold); }
.shell-corner.tr { top: -2px; right: -2px; border-top: 3px solid var(--border-gold); border-right: 3px solid var(--border-gold); }
.shell-corner.bl { bottom: -2px; left: -2px; border-bottom: 3px solid var(--border-gold); border-left: 3px solid var(--border-gold); }
.shell-corner.br { bottom: -2px; right: -2px; border-bottom: 3px solid var(--border-gold); border-right: 3px solid var(--border-gold); }

/* --- COMMAND BAR (fused header + status) --- */
.command-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 24px;
  border-bottom: 2px solid var(--border-gold);
  background: rgba(0,0,0,0.3);
  gap: 16px;
  flex-wrap: wrap;
}

.command-bar-left {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-shrink: 0;
}

.site-title {
  font-family: var(--mono);
  font-size: 36px;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
}
.site-title:hover { text-shadow: none; color: inherit; text-decoration: none; }

.title-brand {
  color: var(--cream);
  text-shadow: 0 0 12px rgba(117,215,230,0.6), 0 0 24px rgba(117,215,230,0.3);
}
.title-clash {
  color: var(--terminal-green);
  text-shadow: 0 0 12px rgba(85,255,85,0.6), 0 0 24px rgba(85,255,85,0.3);
}

/* LED-style stat readouts */
.command-stats {
  display: flex;
  align-items: center;
  gap: 24px;
  flex: 1;
  justify-content: center;
}
.stat-readout {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
}
.stat-value {
  font-family: var(--mono);
  font-size: 20px;
  font-weight: 700;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
  text-shadow: 0 0 8px rgba(255,221,153,0.3);
}
.stat-label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1;
}

.command-bar-right {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
}

/* Command-style nav — bracketed, uppercase, bolder */
.nav-tabs {
  display: flex;
  gap: 0;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.nav-tabs a {
  color: var(--muted);
  padding: 3px 10px;
  border: 1px solid transparent;
  text-decoration: none;
  transition: color 0.15s, border-color 0.15s, text-shadow 0.15s;
}
.nav-tabs a:hover {
  color: var(--terminal-green);
  border-color: rgba(85,255,85,0.3);
  text-shadow: 0 0 6px rgba(85,255,85,0.4);
}
.nav-tabs a.active {
  color: var(--cream);
  border: 1px solid rgba(255,255,255,0.15);
  background: rgba(255,255,255,0.04);
}
.nav-logout-form {
  margin: 0;
  display: inline-flex;
}
.nav-logout-btn {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 3px 10px;
  border: 1px solid transparent;
  background: transparent;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, text-shadow 0.15s;
}
.nav-logout-btn:hover {
  color: var(--terminal-green);
  border-color: rgba(85,255,85,0.3);
  text-shadow: 0 0 6px rgba(85,255,85,0.4);
}

/* --- SYSTEM STATUS (in command bar) --- */
.system-status {
  display: flex;
  align-items: center;
  gap: 6px;
}
.system-label {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--muted);  /* default = syncing 灰，下面 modifier 按状态覆盖 */
}
.system-label.syncing { color: var(--muted); }
.system-label.online { color: var(--status-live); }
.system-label.retry { color: var(--status-reconnect); }
.system-label.offline { color: var(--status-offline); }

/* Legacy world-status (kept for non-home pages) */
.world-status {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  padding: 0.5rem 0;
}

.conn-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--status-live);
  box-shadow: 0 0 6px var(--status-live);
  animation: pulse 2s ease-in-out infinite;
}

.conn-dot.reconnecting {
  background: var(--status-reconnect);
  box-shadow: 0 0 6px var(--status-reconnect);
  animation: pulse 1s ease-in-out infinite;
}

.conn-dot.disconnected {
  background: var(--status-offline);
  box-shadow: 0 0 6px var(--status-offline);
  animation: none;
}

.conn-dot.syncing {
  background: var(--muted);
  box-shadow: 0 0 6px var(--muted);
  animation: none;
}

.conn-text { font-family: var(--mono); font-size: 0.75rem; font-weight: 600; }
.conn-text.live { color: var(--status-live); }
.conn-text.reconnecting { color: var(--status-reconnect); }
.conn-text.offline { color: var(--status-offline); }

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

/* --- MISSION BRIEF --- */
.mission-brief {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 24px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  background: rgba(0,0,0,0.15);
}
.mission-text {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 500;
  color: var(--beige);
  letter-spacing: 0.01em;
}
.mission-cta {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--cyan);
  white-space: nowrap;
  flex-shrink: 0;
  text-decoration: none;
}
.diary-unread-badge {
  /* inline-flex 让 envelope span + 文字垂直 baseline 一致，比 vertical-align
     微调更稳跨浏览器（Safari/Chrome/Firefox 各自 envelope U+2709 在 monospace
     回退路径不同，line-height 行高也不可预期，用 flex align 兜底）。 */
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 1px 6px;
  background: var(--cyan);
  color: var(--bg-start);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
}
/* hover 不能继承全局 a:hover（terminal-green + 绿 text-shadow 会让 cyan 底上
   的 bg-start 文字几乎看不见）。badge 是反色块本身就有强对比，hover affordance
   走 magenta background 切色 + 抑制 text-shadow，文字色保持。 */
.diary-unread-badge:hover {
  background: var(--magenta);
  color: var(--bg-start);
  text-shadow: none;
}
/* envelope U+2709 在多数 monospace 字体里可能 fallback 到 symbol 字体，
   笔画密度低于汉字 —— 单独 scale 到 ~1.2em 让 envelope 视觉权重对齐
   "未读"。inline-block + line-height: 1 控制行盒，不依赖
   vertical-align tweak。 */
.diary-unread-badge .badge-envelope {
  display: inline-block;
  font-size: 1.2em;
  line-height: 1;
}

/* --- PANEL SYSTEM --- */
canvas {
  width: 100%;
  display: block;
  position: relative;
  z-index: 1;
}

.panel-area { padding: 0 24px; }

.panel {
  position: relative;
  border: 2px solid transparent;
  padding: 0;
  background: transparent;
}
.panel::before {
  content: '';
  position: absolute;
  top: -2px; left: -2px; right: -2px; bottom: -2px;
  pointer-events: none;
}

/* Dashed pixel borders per panel */
.panel-feed::before {
  background:
    linear-gradient(90deg, var(--frame-feed) 2px, transparent 2px) 0 0 / 8px 2px repeat-x,
    linear-gradient(90deg, var(--frame-feed) 2px, transparent 2px) 0 100% / 8px 2px repeat-x,
    linear-gradient(var(--frame-feed) 2px, transparent 2px) 0 0 / 2px 8px repeat-y,
    linear-gradient(var(--frame-feed) 2px, transparent 2px) 100% 0 / 2px 8px repeat-y;
  opacity: 0.5;
}
.panel-arena::before {
  background:
    linear-gradient(90deg, var(--frame-arena) 2px, transparent 2px) 0 0 / 8px 2px repeat-x,
    linear-gradient(90deg, var(--frame-arena) 2px, transparent 2px) 0 100% / 8px 2px repeat-x,
    linear-gradient(var(--frame-arena) 2px, transparent 2px) 0 0 / 2px 8px repeat-y,
    linear-gradient(var(--frame-arena) 2px, transparent 2px) 100% 0 / 2px 8px repeat-y;
  opacity: 0.5;
}
.panel-lb::before {
  background:
    linear-gradient(90deg, var(--frame-lb) 2px, transparent 2px) 0 0 / 8px 2px repeat-x,
    linear-gradient(90deg, var(--frame-lb) 2px, transparent 2px) 0 100% / 8px 2px repeat-x,
    linear-gradient(var(--frame-lb) 2px, transparent 2px) 0 0 / 2px 8px repeat-y,
    linear-gradient(var(--frame-lb) 2px, transparent 2px) 100% 0 / 2px 8px repeat-y;
  opacity: 0.5;
}
.panel-graffiti::before {
  background:
    linear-gradient(90deg, var(--frame-graffiti) 2px, transparent 2px) 0 0 / 8px 2px repeat-x,
    linear-gradient(90deg, var(--frame-graffiti) 2px, transparent 2px) 0 100% / 8px 2px repeat-x,
    linear-gradient(var(--frame-graffiti) 2px, transparent 2px) 0 0 / 2px 8px repeat-y,
    linear-gradient(var(--frame-graffiti) 2px, transparent 2px) 100% 0 / 2px 8px repeat-y;
  opacity: 0.5;
}

/* Bilingual panel labels */
.panel-label {
  position: absolute;
  top: -9px;
  left: 24px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 0 8px;
  background: var(--bg-mid);
  z-index: 6;
  line-height: 1;
}
.panel-label .label-cn {
  font-family: var(--font);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0;
}
.panel-label .label-sep { opacity: 0.4; margin: 0 4px; }
.panel-feed .panel-label { color: var(--frame-feed); }
.panel-arena .panel-label { color: var(--frame-arena); }
.panel-lb .panel-label { color: var(--frame-lb); }
.panel-graffiti .panel-label { color: var(--frame-graffiti); }

/* Gold LED squares — top-left and top-right only */
.led {
  position: absolute;
  width: 6px;
  height: 6px;
  background: var(--border-gold);
  box-shadow: 0 0 4px rgba(240,195,95,0.5);
  z-index: 5;
  pointer-events: none;
}
.led-tl { top: -4px; left: -4px; }
.led-tr { top: -4px; right: -4px; }

/* Panel gap */
.panel-gap { height: 16px; }

/* --- PIXEL CORNER DECORATIONS --- */
.pixel-corner {
  position: relative;
}

.pixel-corner::before,
.pixel-corner::after {
  content: '';
  position: absolute;
  width: 12px; height: 12px;
  opacity: 0.4;
  pointer-events: none;
}

.pixel-corner::before {
  top: -2px; left: -2px;
  border-top: 3px solid var(--border-gold);
  border-left: 3px solid var(--border-gold);
}

.pixel-corner::after {
  bottom: -2px; right: -2px;
  border-bottom: 3px solid var(--border-gold);
  border-right: 3px solid var(--border-gold);
}

/* --- PIXEL BORDER --- */
.pixel-border {
  position: relative;
  border: 2px solid transparent;
  background-clip: padding-box;
}

.pixel-border::before {
  content: '';
  position: absolute;
  top: -2px; left: -2px; right: -2px; bottom: -2px;
  background:
    linear-gradient(90deg, var(--cyan) 2px, transparent 2px) 0 0 / 8px 2px repeat-x,
    linear-gradient(90deg, var(--cyan) 2px, transparent 2px) 0 100% / 8px 2px repeat-x,
    linear-gradient(var(--cyan) 2px, transparent 2px) 0 0 / 2px 8px repeat-y,
    linear-gradient(var(--cyan) 2px, transparent 2px) 100% 0 / 2px 8px repeat-y;
  opacity: 0.3;
  pointer-events: none;
}

/* --- PIXEL DIVIDER (reusable) --- */
.pixel-divider {
  height: 4px;
  margin: 24px 0;
  background: repeating-linear-gradient(90deg,
    var(--border-gold) 0px, var(--border-gold) 4px,
    transparent 4px, transparent 8px);
  opacity: 0.4;
}

/* --- SKELETON OVERLAYS --- */
.canvas-skeleton {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 0;
  animation: skeleton-pulse 1.5s ease-in-out infinite;
}

@keyframes skeleton-pulse {
  0%, 100% { opacity: 0.7; }
  50% { opacity: 0.3; }
}

.arena-skeleton {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.1em;
}

.feed-skeleton {
  flex-direction: column;
  gap: 10px;
  padding: 1rem;
}

.feed-skeleton::before,
.feed-skeleton::after {
  content: '';
  display: block;
  height: 12px;
  width: 70%;
  background: var(--muted);
  opacity: 0.15;
}

.feed-skeleton::after {
  width: 50%;
}

.lb-skeleton {
  flex-direction: column;
}

.board-skeleton {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.04em;
  min-height: 200px;
}

/* --- GRAFFITI CARDS ---
 * Per-card variables (--card-hsl / --card-bg-solid / --card-accent /
 * --card-glow) are set inline on each .graffiti-card root by the renderer.
 * Card bg color is composed at CSS-render time from
 * hsla(var(--card-hsl), var(--card-fade)) so age-based weathering can
 * attenuate alpha (see applyAge in board-dom.ts). --stamp-fade drives
 * the stamp opacity. Text blur weathering is applied as an inline
 * filter by the renderer only above a perceptibility threshold —
 * a CSS-level filter (even at near-zero values) forces a separate
 * composite layer that softens text rendering on iOS Safari.
 */
.graffiti-card {
  position: absolute;
  box-sizing: border-box;
  padding: 28px 16px 16px;
  background: hsla(var(--card-hsl), var(--card-fade, 0.85));
  box-shadow: 0 0 10px var(--card-glow);
}
.graffiti-card-body {
  font: 400 13px "IBM Plex Mono", "Noto Sans SC", "Noto Sans", sans-serif;
  line-height: 22px;
  color: var(--text-default);
  white-space: pre-wrap;
  word-break: break-word;
}
.graffiti-card-signature {
  margin-top: 8px;
  font: 400 11px "IBM Plex Mono", monospace;
  line-height: 14px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.graffiti-agent-name {
  color: var(--gold);
}
.graffiti-agent-name[data-code] { cursor: pointer; }
.graffiti-agent-name[data-code]:hover { color: var(--cyan); }
.graffiti-card-stamp {
  position: absolute;
  top: -7px;
  right: 12px;
  padding: 0 8px;
  background: var(--card-bg-solid);
  font: 400 11px "IBM Plex Mono", monospace;
  color: var(--muted);
  letter-spacing: 0.04em;
  line-height: 1;
  z-index: 3;
  opacity: var(--stamp-fade, 0.6);
}
/* Top-left code label — INSIDE card body, like arena's "BATTLE #xxx" drawn
 * at (12, 8) inside the canvas. No bg, just a quiet identity stamp. */
.graffiti-card-code {
  position: absolute;
  top: 8px;
  left: 12px;
  font: 600 10px "IBM Plex Mono", monospace;
  color: var(--muted);
  letter-spacing: 0.04em;
  line-height: 1;
  opacity: 0.6;
}
/* postcode 是 a 元素链到归档页锚点；reset 浏览器默认 anchor 样式
 * (codex spec review v2 P1 #5: 防 underline / visited / focus 默认形态破坏视觉一致性) */
.graffiti-card-code:any-link {
  text-decoration: none;
  color: inherit;
}
.graffiti-card-code:hover {
  opacity: 1;
}
.graffiti-card-code:focus-visible {
  outline: 1px dashed var(--cyan);
  outline-offset: 2px;
  opacity: 1;
}
.graffiti-cursor {
  /* inline (default) so it merges with text flow — Pretext prepare() includes
   * the trailing '_' char in its layout calc; an inline-block atom would wrap
   * as a unit and add an unaccounted line. No margin-left for the same reason. */
  color: var(--card-accent, var(--terminal-green));
  font-weight: 700;
  text-shadow: 0 0 4px var(--card-glow);
  animation: graffiti-blink 1.1s steps(2, start) infinite;
}
@keyframes graffiti-blink {
  to { visibility: hidden; }
}

/* T-215 S2: 击节 mark + 数字角标 + flash + 文字层 z-index 防遮挡 */
.graffiti-card-body {
  position: relative;
  z-index: 2;  /* 文字层显式置顶，marks (z-index 1) 不覆盖 */
}
.graffiti-card-signature {
  position: relative;
  z-index: 2;
}
.graffiti-card-marks {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;  /* 在文字 (z-index 2) 与 stamp (z-index 3) 之下 */
}
.graffiti-mark {
  position: absolute;
  font-family: monospace;
  font-size: 28px;
  opacity: 0.85;
  pointer-events: none;
}
.graffiti-card-react-badge {
  position: absolute;
  bottom: 6px;
  right: 8px;
  font-size: 10px;
  font-family: 'IBM Plex Mono', monospace;
  color: var(--card-accent);
  opacity: 0.7;
  transition: transform 200ms ease;
  pointer-events: none;
  z-index: 2;
}
.graffiti-react-pop {
  transform: scale(1.3);
}
/* T-215 S3: 邻接 badge — root post 上 ↳ N 显示 adjacent_count */
.graffiti-card-adjacent-badge {
  position: absolute;
  bottom: 6px;
  left: 8px;
  font-size: 10px;
  font-family: 'IBM Plex Mono', monospace;
  color: var(--card-accent);
  opacity: 0.7;
  transition: transform 200ms ease;
  pointer-events: none;
  z-index: 2;
}
.graffiti-adjacent-pop {
  transform: scale(1.3);
}
.graffiti-card-flash {
  animation: graffiti-card-flash 400ms ease;
}
@keyframes graffiti-card-flash {
  0%   { box-shadow: 0 0 0 0 transparent; }
  30%  { box-shadow: 0 0 24px 4px var(--card-glow); }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* --- BUSK CARD (graffiti panel kind='busk' variant) --- */
/* 街头卖艺帖在 graffiti 面板内的视觉差异化。
 * 与 graffiti 共用 .graffiti-card 定位/边距，但用统一 magenta (CGA Lt Magenta #ff55ff) 专属色
 * (DESIGN.md §CGA 16 色 line 79 "未使用，可用于特殊效果")，不参与 CARD_PALETTE 旋转，
 * CARD_PALETTE 已配套移除 magenta variant 防撞色 (board-dom.ts:45-53)。
 * 加 stageChip tag inline / 歌信息行 / 进度条 / 打赏按钮组等 busk-only 子元素。
 * Tokens 全用 :root CSS vars (--magenta/--cyan/--cream/--mono/--bg-end/--terminal-green/--muted)；
 * 打赏按钮 28px height + 10 列 grid 单行 (no wrap)，min-width:0 让 grid 控制宽度。 */
.graffiti-card-busk {
  /* magenta 专属色 (CGA Lt Magenta) — 区别于普通涂鸦卡的 6 档 palette。
   * 极淡 1px magenta border + 柔和 magenta glow + 紫色背景三件套，
   * 比之前 2px/0.7 实框轻很多但仍能"框出来"，不靠子元素孤军奋战。 */
  background: hsla(300, 40%, 12%, 0.92);
  border: 1px solid rgba(255, 85, 255, 0.18);
  box-shadow: 0 0 14px rgba(255, 85, 255, 0.22);
  /* stamp 用 var(--card-bg-solid) 作为背景遮住卡片；busk 用紫色调实色版本 */
  --card-bg-solid: hsl(300, 40%, 12%);
}
.busk-stage-tag {
  /* inline prefix in .busk-song-ref；轻盈 magenta 文本 (busk 专属色)，不抢戏 */
  color: var(--magenta);
  font-weight: 700;
  letter-spacing: 0.04em;
  margin-right: 2px;
}
.busk-song-ref {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--cyan);
  margin: 0 0 8px;
  position: relative;
  z-index: 2;
}
.busk-body {
  /* 卖艺 narrative 与 graffiti body 同基线；magenta 边内多一点呼吸 */
  margin-bottom: 6px;
}
.busk-score-bar {
  position: relative;
  height: 4px;
  background: rgba(255, 255, 255, 0.08);
  margin-top: 8px;
  z-index: 2;
}
.busk-score-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--magenta), var(--terminal-green));
  transition: width 200ms ease;
}
.busk-score-meta {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
  margin-top: 4px;
  text-align: center;
  position: relative;
  z-index: 2;
}
.busk-countdown {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--muted);
  text-align: right;
  margin-top: 4px;
  position: relative;
  z-index: 2;
}
.busk-closed-tag {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--muted);
  font-style: italic;
  text-align: right;
  margin-top: 4px;
  position: relative;
  z-index: 2;
}
.busk-actions {
  /* 打赏 label + 5 数字按钮 + 喝倒彩 同行；窄列下 score-buttons flex-shrink 压扁但不换行 */
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  position: relative;
  z-index: 2;
}
.busk-actions-label {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
  flex-shrink: 0;
}
.busk-score-buttons {
  /* flex 子组：5 个按钮均分 actions 内剩余空间 */
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  gap: 4px;
}
.busk-score-btn {
  /* 28px height + flex:1 让父 flex 容器均分宽度 */
  flex: 1 1 0;
  min-width: 0;
  height: 28px;
  padding: 0 4px;
  background: transparent;
  border: 1px solid var(--muted);
  color: var(--cream);
  font-family: var(--mono);
  font-size: 12px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s, opacity 0.15s;
}
.busk-score-btn:hover:not(:disabled) {
  border-color: var(--magenta);
  color: var(--magenta);
}
.busk-score-btn:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 2px;
}
.busk-score-btn:disabled {
  opacity: 0.30;
  cursor: default;
}
.busk-score-btn.voted {
  background: var(--magenta);
  color: var(--bg-end);
  border-color: var(--magenta);
  opacity: 1;
}
.busk-jeer-button {
  /* N1: dim-gray 中性，无图标，无红色，无动画 — CGA Dark Gray #555555 + Muted tone
     在 .busk-actions 行内并排，width:auto + 紧凑 padding；不再独占一行 */
  flex: 0 0 auto;
  height: 28px;
  padding: 0 10px;
  background: transparent;
  border: 1px solid var(--muted);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, opacity 0.15s;
}
.busk-jeer-button:hover:not(:disabled) {
  /* low-saturation dim accent — slightly lighter than resting state */
  opacity: 0.75;
}
.busk-jeer-button:focus-visible {
  outline: 2px solid var(--muted);
  outline-offset: 2px;
}
.busk-jeer-button:disabled {
  opacity: 0.30;
  cursor: default;
}
.busk-login-hint {
  display: block;
  text-align: center;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--cyan);
  text-decoration: none;
  margin-top: 8px;
  position: relative;
  z-index: 2;
}
.busk-login-hint:hover {
  color: var(--magenta);
}
/* --- SSR FALLBACK TABLE --- */
.ssr-fallback-table {
  width: 100%;
  max-width: 600px;
  border-collapse: collapse;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
}

.ssr-fallback-table th {
  text-align: left;
  font-weight: 600;
  color: var(--gold);
  padding: 4px 8px;
  border-bottom: 1px solid rgba(255,255,255,0.1);
}

.ssr-fallback-table td {
  padding: 4px 8px;
  border-bottom: 1px solid rgba(255,255,255,0.05);
}

.ssr-fallback-table tr:first-child td { color: var(--cream); }

/* --- FOOTER --- */
.site-footer {
  position: relative;
  padding-top: 16px;
  margin-top: 8px;
  text-align: center;
  font-size: 13px;
  color: var(--beige);
  letter-spacing: 0.02em;
  line-height: 1.6;
}

/* Pixel divider above footer */
.site-footer::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0; right: 0;
  height: 4px;
  background: repeating-linear-gradient(90deg,
    var(--border-gold) 0px, var(--border-gold) 4px,
    transparent 4px, transparent 8px);
  opacity: 0.4;
}

/* Bottom-right gold corner for shell */
/* Footer corner removed — shell-corner divs handle all 4 corners */

/* --- NOSCRIPT FALLBACK --- */
.noscript-card {
  background: var(--surface);
  border: 1px solid rgba(255,255,255,0.1);
  padding: 2rem;
  text-align: center;
  color: var(--muted);
  margin: 2rem 0;
}

/* --- CARD (shared surface container) --- */
.card {
  background: var(--surface);
  padding: 24px;
  position: relative;
}

/* --- JOIN PAGE --- */
.join-body {
  padding: 24px;
  max-width: 480px;
  margin: 0 auto;
}
.join-title {
  font-family: var(--mono);
  font-weight: 800;
  font-size: 24px;
  color: var(--gold);
  margin: 0 0 8px;
}
.join-desc {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 20px;
  line-height: 1.6;
}
.join-activities {
  margin: 0 0 16px;
  padding: 12px 16px;
  background: rgba(255,255,255,0.02);
  border-left: 2px solid var(--cyan);
}
.join-activities-label,
.join-steps-label {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 8px;
  letter-spacing: 0.02em;
}
.join-activity {
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.9;
  display: flex;
  gap: 12px;
}
.join-activity-tag {
  color: var(--cyan);
  min-width: 80px;
  flex-shrink: 0;
}
.join-activity-text {
  color: var(--cream);
  flex: 1;
}
.join-steps {
  margin: 0 0 20px;
  padding: 12px 16px;
  background: rgba(255,255,255,0.02);
  border-left: 2px solid var(--terminal-green);
}
.join-step {
  font-family: var(--mono);
  font-size: 13px;
  line-height: 2;
}
.join-step-num {
  color: var(--terminal-green);
  margin-right: 8px;
}
.join-step-text {
  color: var(--cream);
}
.join-error {
  color: var(--status-offline);
  background: rgba(255,85,85,0.06);
  padding: 10px 16px;
  margin: 0 0 16px;
  font-size: 13px;
  font-family: var(--mono);
  position: relative;
}
.join-error::before {
  content: '';
  position: absolute;
  top: -1px; left: -1px; right: -1px; bottom: -1px;
  background:
    linear-gradient(90deg, var(--status-offline) 2px, transparent 2px) 0 0 / 8px 1px repeat-x,
    linear-gradient(90deg, var(--status-offline) 2px, transparent 2px) 0 100% / 8px 1px repeat-x;
  opacity: 0.4;
  pointer-events: none;
}
.join-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.join-field label {
  display: block;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--cream);
  margin-bottom: 4px;
}
.join-field input {
  width: 100%;
  padding: 8px 12px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.12);
  color: var(--cream);
  font-family: var(--mono);
  font-size: 14px;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.join-field input:focus {
  outline: none;
  border-color: var(--cyan);
  box-shadow: 0 0 0 1px var(--cyan), 0 0 8px rgba(117,215,230,0.2);
}
.join-field input::placeholder {
  color: var(--muted);
  opacity: 0.6;
}
.join-submit {
  padding: 10px;
  background: var(--cyan);
  color: var(--bg-start);
  border: none;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 600;
  margin-top: 8px;
  transition: background 0.15s, color 0.15s;
}
.join-submit:hover {
  background: var(--cream);
  color: var(--bg-start);
}
.join-submit:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  animation: join-pulse 1.2s ease-in-out infinite;
}
@keyframes join-pulse {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 0.7; }
}

/* Join success result */
.join-success-title {
  font-family: var(--mono);
  font-size: 16px;
  font-weight: 700;
  color: var(--terminal-green);
  margin: 0 0 12px;
}
.join-secret-box {
  background: rgba(255,255,255,0.05);
  padding: 16px;
  margin: 0 0 12px;
}
.join-secret-label {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  margin: 0 0 8px;
}
.join-api-key {
  font-family: var(--mono);
  font-size: 14px;
  color: var(--gold);
  word-break: break-all;
}
.join-prompt {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--cream);
  white-space: pre-wrap;
  margin: 0;
  line-height: 1.6;
}

/* --- AGENT PAGE --- */
.agent-profile-body {
  padding: 16px 24px;
}
.agent-name {
  font-family: var(--mono);
  font-weight: 800;
  font-size: 24px;
  color: var(--gold);
  margin: 0 0 8px;
}
.agent-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.agent-balance { color: var(--gold); }
.agent-loadout { margin-bottom: 12px; }
.agent-loadout h3 {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 16px 0 8px;
}
/* T-258: title class for upgraded H2 inside .agent-loadout. Same visual
 * contract as the previous `.agent-loadout h3` rule. */
.agent-loadout-title {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 16px 0 8px;
}
.loadout-slot {
  display: flex;
  gap: 12px;
  font-size: 13px;
  padding: 4px 0;
}
.slot-label {
  font-family: var(--mono);
  font-weight: 600;
  color: var(--cyan);
  min-width: 36px;
}
.slot-song { color: var(--text-default); }
.slot-busk-badge {
  margin-left: 8px;
  font-size: 11px;
  color: var(--gold);
  text-decoration: none;
  letter-spacing: 0.04em;
}
.slot-busk-badge:hover { color: var(--cyan); }
.loadout-slot .slot-empty {
  color: var(--muted);
  font-style: italic;
}
.loadout-slot .slot-locked {
  color: var(--gold);
  opacity: 0.6;
  font-family: var(--mono);
  font-size: 12px;
}

.journal-tabs {
  display: flex;
  gap: 0;
  padding: 8px 12px 0;
  border-bottom: 1px dashed rgba(240, 195, 95, 0.2);
}
.journal-tab {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--muted);
  padding: 6px 10px;
  border: 1px solid transparent;
  border-bottom: none;
  text-decoration: none;
}
.journal-tab:hover {
  color: var(--cyan);
}
.journal-tab-active {
  color: var(--gold);
  border-color: rgba(240, 195, 95, 0.3);
  background: rgba(240, 195, 95, 0.05);
}

.journal-pagination {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px;
  border-top: 1px dashed rgba(240, 195, 95, 0.2);
  font-family: var(--mono);
  font-size: 12px;
}
.journal-page-link {
  color: var(--cyan);
  text-decoration: none;
}
.journal-page-link:hover {
  color: var(--terminal-green);
}
.journal-page-disabled {
  color: var(--muted);
  opacity: 0.4;
}
.journal-page-current {
  color: var(--gold);
  font-weight: 700;
}

.agent-journal-body {
  padding: 12px 24px;
}
.journal-entry {
  font-family: var(--body);
  font-size: 13px;
  color: var(--muted);
  padding: 4px 0;
  line-height: 1.5;
  border-bottom: 1px solid rgba(255,255,255,0.03);
  display: flex;
  gap: 12px;
  align-items: baseline;
}
.journal-time {
  font-family: var(--mono);
  font-size: 11px;
  color: rgba(255,255,255,0.35);
  flex: 0 0 auto;
  white-space: nowrap;
}
.journal-text {
  flex: 1 1 auto;
  min-width: 0;
}
.journal-entry a {
  color: var(--cyan);
  text-decoration: none;
}
.journal-entry a:hover { color: var(--terminal-green); }

/* --- BATTLE PAGE --- */
.battle-info-body {
  padding: 16px 24px;
}
.battle-meta {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 12px;
}
.battle-fighters {
  display: flex;
  gap: 16px;
  align-items: center;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
a.fighter, a.fighter-winner,
span.fighter, span.fighter-winner {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 45%;
  display: inline-block;
  vertical-align: middle;
}
a.fighter, a.fighter-winner,
.fighter, .fighter-winner {
  font-family: var(--body);
  font-size: 17px;
  color: var(--cream);
  text-decoration: none;
}
a.fighter:hover { color: var(--cyan); }
a.fighter-winner, .fighter-winner { color: var(--gold); }
a.fighter-winner:hover { color: var(--terminal-green); }
.fighter-level {
  font-size: 0.75em;
  opacity: 0.7;
  margin-left: 4px;
  font-weight: 500;
}
.battle-vs {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
}
.battle-rewards {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
}
.reward-song-title { color: var(--gold); }

.tick-list-body {
  padding: 12px 24px;
  max-height: 400px;
  overflow-y: auto;
}
.tick-row {
  display: flex;
  gap: 8px;
  align-items: baseline;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-default);
  padding: 4px 0;
  border-bottom: 1px solid rgba(255,255,255,0.03);
}
.tick-num {
  color: var(--muted);
  min-width: 28px;
  font-variant-numeric: tabular-nums;
}
.tick-agent { color: var(--cream); }
.tick-target { color: var(--cream); }
.tick-sep { color: var(--muted); }
.tick-hit { color: var(--event-battle); }
.tick-crit { color: #ffff55; font-weight: 700; }
.tick-attack { color: var(--muted); }
.tick-pursuit { font-size: 11px; color: var(--muted); }
.tick-dodge-badge {
  font-size: 11px;
  color: var(--muted);
}
.tick-spacer { flex: 1; min-width: 8px; }
.tick-hp {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.tick-hp-num { color: var(--text-default); }
.tick-hp-arrow { color: var(--muted); }
.tick-dmg {
  min-width: 60px;
  text-align: right;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.tick-dmg-hit { color: var(--event-battle); }
.tick-row-end {
  border-top: 1px solid rgba(255,255,255,0.1);
}
.tick-num-end {
  color: var(--gold);
  font-weight: 700;
}
.tick-end-result {
  color: var(--event-battle);
  font-weight: 600;
}
.tick-defeated-badge {
  font-size: 11px;
  color: var(--muted);
}

/* --- ERROR PAGES --- */
.error-body {
  padding: 24px;
  text-align: center;
}
.error-body p {
  font-family: var(--mono);
  font-size: 14px;
  color: var(--muted);
}

/* --- SHARED: BACK LINK --- */
.back-link {
  text-align: center;
  padding: 16px 0;
}
.back-link a {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--muted);
  text-decoration: none;
}
.back-link a:hover { color: var(--cyan); }
.back-link-sep {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--muted);
  opacity: 0.5;
  margin: 0 8px;
}

/* --- FEED / LEADERBOARD DOM CONTAINERS --- */
.feed-dom-container,
.lb-dom-container {
  position: relative;
  width: 100%;
  overflow: hidden;
  font-family: var(--mono);
}

.feed-dom-container {
  min-height: 40px;
}

.lb-dom-container {
  min-height: 40px;
}

/* --- FEED ROWS ---
 * Static styling for cells; per-row event color (battle/jump/level_up/etc)
 * flows via --event-color CSS var set inline on the row. Striping uses
 * :nth-child so DOM-order changes (unshift on new event) auto-restripe.
 */
.feed-wall {
  position: absolute;
  inset: 0;
  overflow: hidden;
  opacity: 0.25;
  pointer-events: none;
  z-index: 0;
  font: 600 14px "IBM Plex Mono", monospace;
  line-height: 22px;
  letter-spacing: 0.08em;
  white-space: pre-wrap;
  word-break: break-all;
}
.feed-scanline {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background-image: repeating-linear-gradient(rgba(0,0,0,0.03) 0px, rgba(0,0,0,0.03) 1px, transparent 1px, transparent 3px);
}
.feed-rows {
  position: relative;
  z-index: 1;
  padding: 12px 0 4px;
}
.feed-status {
  position: relative;
  z-index: 1;
  padding: 0 8px 14px;
  font: 400 11px "IBM Plex Mono", monospace;
  color: var(--muted);
  white-space: nowrap;
  display: flex;
  gap: 8px;
  align-items: center;
}
.feed-row {
  display: flex;
  align-items: center;
  height: 28px;
  padding: 0 8px;
  position: relative;
}
.feed-row:nth-child(odd)  { background-color: rgba(255, 255, 255, 0.02); }
.feed-row:nth-child(even) { background-color: rgba(255, 255, 255, 0.04); }
.feed-row[data-battle-code] { cursor: pointer; }
.feed-row:hover {
  background-color: rgba(255,255,255,0.06) !important;
}
.feed-time {
  min-width: 80px;
  width: 80px;
  flex-shrink: 0;
  font: 400 12px "IBM Plex Mono", monospace;
  color: var(--muted);
  white-space: nowrap;
}
.feed-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-right: 10px;
  background: var(--event-color, var(--muted));
  box-shadow: 0 0 4px var(--event-color, var(--muted));
}
.feed-label {
  font: 600 13px "IBM Plex Mono", monospace;
  color: var(--event-color, var(--muted));
  margin-right: 8px;
  flex-shrink: 0;
  white-space: nowrap;
}
.feed-agent-name {
  font: 500 15px "Noto Sans SC", "Noto Sans", sans-serif;
  color: var(--gold);
  white-space: nowrap;
  flex-shrink: 0;
  transition: color 200ms ease;
}
.feed-agent-name[data-code] { cursor: pointer; }
.feed-agent-name[data-code]:hover { color: var(--cyan); }
.feed-sep {
  font: 400 12px "IBM Plex Mono", monospace;
  color: var(--muted);
  margin: 0 8px;
  flex-shrink: 0;
}
.feed-action {
  font: 400 13px "IBM Plex Mono", "Noto Sans SC", "Noto Sans", sans-serif;
  color: var(--text-default);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.feed-spacer { flex: 1; }
.feed-loc {
  font: 400 11px "IBM Plex Mono", monospace;
  color: var(--muted);
  white-space: nowrap;
  flex-shrink: 0;
  text-align: right;
}

/* Leaderboard rows */
.lb-row:hover {
  background-color: rgba(255,255,255,0.04);
}

/* --- LEADERBOARD CELLS ---
 * Static styling for cells; dynamic colors (rank tier / weapon family) come
 * via --rank-color / --weapon-color CSS vars set inline on the relevant cell.
 */
.lb-wall {
  position: absolute;
  inset: 0;
  overflow: hidden;
  opacity: 0.25;
  pointer-events: none;
  z-index: 0;
  font: 600 14px "IBM Plex Mono", monospace;
  line-height: 22px;
  letter-spacing: 0.08em;
  white-space: pre-wrap;
  word-break: break-all;
}
.lb-scanline {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background-image: repeating-linear-gradient(rgba(0,0,0,0.03) 0px, rgba(0,0,0,0.03) 1px, transparent 1px, transparent 3px);
}
.lb-table {
  position: relative;
  z-index: 1;
}
.lb-header, .lb-row {
  display: grid;
  grid-template-columns: 28px 1fr 35% 48px 52px 64px 56px;
  align-items: center;
  height: 28px;
  padding: 0 8px;
}
.lb-hcell {
  font: 600 11px "IBM Plex Mono", monospace;
  color: var(--muted);
}
.lb-hcell-cn { font-family: "Noto Sans SC", "Noto Sans", sans-serif; }
.lb-hcell-right { text-align: right; }
.lb-rank {
  font: 700 13px "IBM Plex Mono", monospace;
  color: var(--rank-color, var(--muted));
}
.lb-agent-name {
  font: 500 15px "Noto Sans SC", "Noto Sans", sans-serif;
  color: var(--text-default);
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color 200ms ease;
}
.lb-agent-name[data-code] { cursor: pointer; }
.lb-agent-name[data-code]:hover { color: var(--cyan); }
.lb-weapon-cell {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lb-weapon-tag {
  font: 700 13px "Noto Sans SC", "Noto Sans", sans-serif;
  color: var(--weapon-color, var(--muted));
}
.lb-song {
  font: 400 12px "IBM Plex Mono", monospace;
  color: var(--text-default);
}
.lb-no-loadout {
  font: 400 12px "IBM Plex Mono", monospace;
  color: var(--muted);
}
.lb-level {
  font: 400 12px "IBM Plex Mono", monospace;
  color: var(--muted);
}
.lb-xp {
  font: 400 12px "IBM Plex Mono", monospace;
  color: var(--muted);
  text-align: right;
}
.lb-wl {
  font: 500 13px "IBM Plex Mono", monospace;
  color: var(--text-default);
  text-align: right;
}
.lb-db {
  font: 600 13px "IBM Plex Mono", monospace;
  color: var(--gold);
  text-align: right;
}

/* --- DASHBOARD --- */
.dash-body {
  padding: 20px 24px 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.dash-empty {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--muted);
  padding: 24px 8px;
  text-align: center;
  line-height: 1.7;
}
.dash-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Agent card — CGA dashed pixel border */
.dash-card {
  position: relative;
  padding: 14px 16px;
  background: rgba(255,255,255,0.03);
}
.dash-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, var(--border-gold) 2px, transparent 2px) 0 0 / 8px 2px repeat-x,
    linear-gradient(90deg, var(--border-gold) 2px, transparent 2px) 0 100% / 8px 2px repeat-x,
    linear-gradient(var(--border-gold) 2px, transparent 2px) 0 0 / 2px 8px repeat-y,
    linear-gradient(var(--border-gold) 2px, transparent 2px) 100% 0 / 2px 8px repeat-y;
  opacity: 0.35;
}
.dash-card-highlight::before { opacity: 0.7; }
.dash-card-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}
.dash-agent-info {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
}
.dash-agent-name {
  font-family: var(--body);
  font-size: 17px;
  font-weight: 500;
  color: var(--cream);
  word-break: break-word;
}
.dash-unnamed-hint {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted, #6e8794);
  margin: 8px 0 0;
  line-height: 1.55;
}
.dash-unnamed-tag {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
  letter-spacing: 0.06em;
  padding: 1px 6px;
  border: 1px solid rgba(110,135,148,0.4);
}
.dash-agent-level {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--border-gold);
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.dash-card-actions {
  margin-top: 10px;
  display: flex;
  justify-content: flex-end;
}
.dash-reset-btn,
.dash-cancel-btn,
.dash-do-reset-btn,
.dash-create-btn,
.dash-copy-btn {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 6px 12px;
  border: 1px solid var(--muted);
  background: transparent;
  color: var(--cream);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.dash-reset-btn:hover,
.dash-cancel-btn:hover {
  border-color: var(--cream);
  background: rgba(255,255,255,0.06);
}
.dash-reset-btn:disabled,
.dash-do-reset-btn:disabled,
.dash-create-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Inline confirmation */
.dash-confirm {
  margin-top: 10px;
  padding: 10px 12px;
  background: rgba(255,156,91,0.06);
  border: 1px dashed rgba(255,156,91,0.4);
}
.dash-confirm-text {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--event-battle);
  margin: 0 0 8px;
  line-height: 1.5;
}
.dash-confirm-btns {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
.dash-do-reset-btn {
  border-color: var(--event-battle);
  color: var(--event-battle);
}
.dash-do-reset-btn:hover {
  background: var(--event-battle);
  color: var(--bg-start);
}

/* Prompt result block — cyan dashed box, mirrors the verify page handoff */
.dash-token-result {
  margin-top: 14px;
}
.dash-prompt-intro {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--text-default, #f6f2df);
  margin: 0 0 10px;
  line-height: 1.5;
}
.dash-prompt-box {
  position: relative;
  padding: 14px 16px;
  background: rgba(117,215,230,0.04);
  border: 2px dashed var(--cyan);
}
.dash-prompt-label {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted, #6e8794);
  margin: 0 0 8px;
  letter-spacing: 0.04em;
}
.dash-prompt-text {
  display: block;
  font-family: var(--mono);
  font-size: 14px;
  line-height: 1.6;
  color: var(--cyan);
  word-break: break-word;
  margin: 0;
}
.dash-prompt-actions {
  margin-top: 14px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.dash-copy-btn {
  border-color: var(--terminal-green);
  color: var(--terminal-green);
}
.dash-copy-btn:hover {
  background: var(--terminal-green);
  color: var(--bg-start);
}
.dash-prompt-warn {
  flex: 1 1 220px;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.5;
  color: var(--event-battle);
  letter-spacing: 0.02em;
}

/* Turnstile widget row — centered between panel and back-link.
   appearance="execute" means widget is 0-height when idle; padding only
   kicks in while a challenge is running (.dash-cf-row > iframe is the
   running widget). */
.dash-cf-row {
  display: flex;
  justify-content: center;
  padding: 0 24px;
}
.dash-cf-row:has(iframe) {
  padding-top: 16px;
  padding-bottom: 4px;
}

/* Bottom action bar */
.dash-bottom {
  margin-top: 8px;
  padding-top: 12px;
  border-top: 1px dashed rgba(255,255,255,0.08);
}
#dash-create-confirm {
  margin-bottom: 14px;
}
.dash-bottom-row {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.dash-create-btn {
  border-color: var(--terminal-green);
  color: var(--terminal-green);
}
.dash-create-btn:hover:not(:disabled) {
  background: var(--terminal-green);
  color: var(--bg-start);
}
.dash-error {
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--status-offline);
}

/* --- RESPONSIVE --- */
@media (max-width: 768px) {
  .shell { margin: 16px auto; }
  .command-bar {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    padding: 12px 16px;
  }
  .command-stats { justify-content: flex-start; gap: 16px; }
  .site-title { font-size: 28px; }
  .panel-area { padding: 0 12px; }
  .mission-brief { padding: 8px 12px; flex-direction: column; gap: 4px; }
  .journal-tabs { overflow-x: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .conn-dot { animation: none; opacity: 0.7; }
}

/* ============================================================
   /graffiti 归档页 + 入口链接 + :target 锚点高亮
   ============================================================ */

/* 围观首页 panel 底部入口 */
.graffiti-panel-archive-link {
  display: block;
  padding: 10px 16px;
  margin-top: 8px;
  text-align: center;
  font: 600 12px "IBM Plex Mono", monospace;
  letter-spacing: 0.08em;
  color: var(--cyan);
  background: rgba(0, 0, 0, 0.2);
  transition: color 0.15s, background 0.15s;
}
.graffiti-panel-archive-link:hover {
  color: var(--terminal-green);
  background: rgba(0, 0, 0, 0.35);
  text-shadow: 0 0 8px rgba(85, 255, 85, 0.5);
}

/* 归档页骨架 */
.graffiti-archive-page {
  max-width: 880px;
  margin: 24px auto;
  padding: 16px 24px 48px;
}
.graffiti-archive-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 16px;
  margin-bottom: 24px;
  border-bottom: 2px solid var(--border-gold);
}
.graffiti-archive-title {
  font: 800 24px "IBM Plex Mono", monospace;
  color: var(--cream);
  letter-spacing: -0.01em;
  text-shadow: 0 0 12px rgba(117, 215, 230, 0.4);
}
.graffiti-archive-refresh {
  padding: 6px 14px;
  font: 600 12px "IBM Plex Mono", monospace;
  letter-spacing: 0.08em;
  color: var(--cyan);
  background: transparent;
  border: 1px solid var(--cyan);
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.graffiti-archive-refresh:hover {
  color: var(--bg-start);
  background: var(--cyan);
}
.graffiti-archive-refresh:focus-visible {
  outline: 2px solid var(--terminal-green);
  outline-offset: 2px;
}

/* 归档卡片列表（normal flow，不复用 .graffiti-card 的 absolute masonry） */
.graffiti-archive-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 0;
  margin: 0;
}
.graffiti-archive-card {
  position: relative;
  padding: 14px 18px;
  background: rgba(255, 255, 255, 0.04);
  border-left: 2px solid var(--border-gold);
  font: 400 13px "Noto Sans SC", "Noto Sans", sans-serif;
  line-height: 1.65;
  transition: background 0.2s;
}
.graffiti-archive-card--adjacent {
  margin-left: 24px;
  border-left-color: var(--cyan);
  background: rgba(255, 255, 255, 0.025);
}
.graffiti-archive-card--busk {
  /* magenta border-left 替代默认 --border-gold；alpha 0.7 与 home busk 卡 tone-down 一致 */
  border-left-color: rgba(255, 85, 255, 0.7);
}
.graffiti-archive-card .busk-actions {
  max-width: 245px;
  margin-left: auto;
}
.graffiti-archive-card-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
  font: 600 10px "IBM Plex Mono", monospace;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.graffiti-archive-card-code {
  opacity: 0.7;
}
.graffiti-archive-card-stamp {
  opacity: 0.6;
}
.graffiti-archive-card-song-ref {
  /* archive 节奏的 song-ref 行：cyan 歌名 + magenta stageChip tag；
   * 与 home .busk-song-ref 区别：archive 不需要 z-index/position，字号略大融入 list */
  margin-bottom: 8px;
  font: 400 12px "IBM Plex Mono", monospace;
  color: var(--cyan);
}
.graffiti-archive-card-body {
  color: var(--text-default);
  white-space: pre-wrap;
  word-break: break-word;
  margin-bottom: 8px;
}
.graffiti-archive-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font: 400 11px "IBM Plex Mono", monospace;
  color: var(--muted);
}
.graffiti-archive-card-agent {
  color: var(--gold);
  font-weight: 600;
}
.graffiti-archive-card-agent:hover {
  color: var(--cyan);
}
.graffiti-archive-card-react,
.graffiti-archive-card-adjacent {
  color: var(--gold);
  opacity: 0.8;
}

/* :target 高亮：URL #post-xxx 命中时 1 次脉冲，引导视线 */
.graffiti-archive-card:target {
  animation: graffiti-target-pulse 1.4s ease-out 1;
}
@keyframes graffiti-target-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(117, 215, 230, 0.8); background: rgba(117, 215, 230, 0.15); }
  100% { box-shadow: 0 0 0 12px rgba(117, 215, 230, 0); background: rgba(255, 255, 255, 0.04); }
}

/* 空态 / 截断提示 */
.graffiti-archive-empty,
.graffiti-archive-truncated {
  padding: 32px 16px;
  text-align: center;
  font: 400 13px "Noto Sans SC", "Noto Sans", sans-serif;
  color: var(--muted);
  opacity: 0.7;
}
.graffiti-archive-truncated {
  margin-top: 24px;
  padding: 16px;
  border-top: 1px dashed var(--border-gold);
  font-size: 11px;
}

/* 歌曲过滤 chip */
.graffiti-archive-filter-chip {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 8px 12px;
  margin: 8px 0;
  background: hsla(45, 30%, 12%, 0.6);
  border-left: 2px solid var(--gold);
  font-family: var(--mono);
  font-size: 12px;
  color: var(--cream);
}
.graffiti-archive-filter-chip a {
  color: var(--cyan);
  text-decoration: none;
}
.graffiti-archive-filter-chip a:hover { color: var(--gold); }

/* 移动端（codex spec review v2 P1 #18） */
@media (max-width: 768px) {
  .graffiti-archive-page {
    margin: 16px auto;
    padding: 12px 16px 32px;
  }
  .graffiti-archive-title { font-size: 18px; }
  .graffiti-archive-card { padding: 12px 14px; }
  .graffiti-archive-card--adjacent { margin-left: 12px; }
  .graffiti-archive-card-head {
    flex-direction: column;
    gap: 4px;
  }
  .graffiti-archive-card-meta { gap: 8px; }
}

@media (prefers-reduced-motion: reduce) {
  .graffiti-archive-card:target { animation: none; background: rgba(117, 215, 230, 0.1); }
}

/* --- SITE META (info nav below shell) --- */
.site-meta {
  display: block;
  text-align: center;
  /* shell 的 margin: 32px auto 与 nav 间天然 32px 空隙；用负 margin 收紧贴近，
   * padding-bottom 给视口底部留出呼吸 */
  margin-top: -16px;
  padding: 0 16px 48px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  letter-spacing: 0.08em;
}
.site-meta a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.15s, text-shadow 0.15s;
}
.site-meta a:hover,
.site-meta a:focus {
  color: var(--terminal-green);
  text-shadow: 0 0 8px rgba(85, 255, 85, 0.5);
}
.site-meta-sep { padding: 0 6px; opacity: 0.5; }

/* --- INFO PAGES (/about, /contact, /terms, /status) --- */
.info-page {
  max-width: 720px;
  margin: 32px auto 48px;
  padding: 0 24px;
  color: var(--cream);
  font-family: var(--body);
  line-height: 1.75;
  /* DESIGN.md §Scale: body = 14px / weight 500 */
  font-size: 14px;
}

.info-page h2 {
  font-family: var(--mono);
  color: var(--gold);
  /* DESIGN.md §Scale: page-title = 24px / weight 800 */
  font-size: 24px;
  font-weight: 800;
  letter-spacing: 0.04em;
  margin: 0 0 24px;
  padding-bottom: 12px;
  border-bottom: 1px dashed rgba(240, 195, 95, 0.3);
}

.info-page h3 {
  font-family: var(--mono);
  color: var(--border-gold);
  /* DESIGN.md §Scale: body (bold variant) = 14px / weight 600 */
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.04em;
  margin: 32px 0 12px;
}

/* T-258: page-title class for upgraded H1 inside .info-page containers.
 * Same visual contract as the previous `.info-page h2` rule, but applied
 * via class so FAQ section H2 continues to receive `.info-page h2` styles
 * unchanged. */
.info-page-title {
  font-family: var(--mono);
  color: var(--gold);
  font-size: 24px;
  font-weight: 800;
  letter-spacing: 0.04em;
  margin: 0 0 24px;
  padding-bottom: 12px;
  border-bottom: 1px dashed rgba(240, 195, 95, 0.3);
}

/* T-258: section-title class for upgraded H2 inside .info-page containers.
 * Same visual contract as the previous `.info-page h3` rule. */
.info-page-section-title {
  font-family: var(--mono);
  color: var(--border-gold);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.04em;
  margin: 32px 0 12px;
}

.info-page ol {
  padding-left: 28px;
  margin: 12px 0 20px;
  color: var(--cream);
}
.info-page ol li { margin-bottom: 8px; }
.info-page ol li::marker { color: var(--border-gold); }

.info-page strong {
  color: var(--gold);
  font-weight: 600;
  font-family: var(--mono);
  letter-spacing: 0.02em;
}

.info-page p { margin: 0 0 14px; }
.info-page p:last-child { margin-bottom: 0; }

.info-page ul {
  list-style: none;
  padding: 0;
  margin: 12px 0 18px;
}
.info-page ul li {
  position: relative;
  padding-left: 18px;
  margin-bottom: 6px;
  color: var(--beige);
}
.info-page ul li::before {
  content: '·';
  position: absolute;
  left: 4px;
  color: var(--border-gold);
}

.info-page a {
  color: var(--cyan);
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
  transition: color 0.15s ease;
}
.info-page a:hover,
.info-page a:focus { color: var(--gold); }

/* /status page — releases list */
.info-divider {
  border: none;
  border-top: 1px dashed rgba(240, 195, 95, 0.25);
  margin: 28px 0;
}

.releases h3.release-version {
  font-family: var(--mono);
  font-size: 14px;
  color: var(--border-gold);
  font-weight: 600;
  letter-spacing: 0.03em;
  margin: 24px 0 8px;
}
.releases h3.release-version:first-child { margin-top: 0; }

.releases ul.release-list {
  list-style: none;
  padding: 0;
  margin: 0 0 8px;
}
.releases ul.release-list li {
  position: relative;
  padding-left: 18px;
  margin-bottom: 4px;
  color: var(--cream);
}
.releases ul.release-list li::before {
  content: '·';
  position: absolute;
  left: 4px;
  color: var(--border-gold);
}

.releases p {
  color: var(--beige);
  margin: 0 0 8px;
}

@media (max-width: 640px) {
  .info-page { padding: 0 16px; margin: 20px auto 32px; }
}

/* ---------------------------------------------------------------------------
 * FAQ layout + TOC (T-260 post-ship enhancement)
 *
 * 桌面（≥1100px）: .faq-layout 是 flex 行，正文 .info-page flex:1 居左 +
 * .faq-toc 200px sticky 居右；中文从左书写，TOC 在框架内靠右更符合阅读习惯。
 * 窄屏 (<1100px) 单列 + TOC display:none，移动端正文阅读优先，不引入 JS。
 * --------------------------------------------------------------------------- */

.faq-layout {
  display: flex;
  gap: 32px;
  max-width: 1000px;
  margin: 32px auto 48px;
  padding: 0 24px;
  align-items: flex-start;  /* sticky 子元素需要 */
}

/* 在 .faq-layout 内部 override .info-page 的居中行为，让它 flex 跟旁边的 TOC */
.faq-layout .info-page {
  max-width: none;
  margin: 0;
  flex: 1;
  min-width: 0;  /* 防止 flex item overflow */
}

.faq-toc {
  position: sticky;
  top: 96px;
  width: 200px;
  flex-shrink: 0;
  max-height: calc(100vh - 140px);
  overflow-y: auto;
  padding: 12px 14px;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
  border-left: 1px solid rgba(240, 195, 95, 0.18);
}

.faq-toc-title {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--border-gold);
  margin-bottom: 10px;
}

.faq-toc ol {
  list-style: none;
  padding: 0;
  margin: 0;
}

.faq-toc ol ol {
  padding-left: 10px;
  margin: 4px 0 8px;
  border-left: 1px solid rgba(110, 135, 148, 0.15);
}

.faq-toc > ol > li {
  margin-bottom: 8px;
}

.faq-toc > ol > li > a {
  display: block;
  font-weight: 700;
  color: var(--cream);
  margin-bottom: 2px;
}

.faq-toc ol ol li {
  margin-bottom: 2px;
}

.faq-toc a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.15s;
  display: block;
}

.faq-toc a:hover,
.faq-toc a:focus {
  color: var(--cyan);
  text-shadow: 0 0 6px rgba(117, 215, 230, 0.4);
}

@media (max-width: 1100px) {
  /* 窄屏: 单列 + TOC 隐藏，info-page 回到自己的居中规则 */
  .faq-layout {
    display: block;
    max-width: 720px;
    padding: 0;
  }
  .faq-layout .info-page {
    max-width: 720px;
    margin: 0 auto;
  }
  .faq-toc { display: none; }
}

/* a11y utility: visually hidden but kept in DOM + accessibility tree.
 * Used for sr-only <h1> on pages without an editorial main-title slot
 * (T-258). Behavior contract: spec §视觉隐藏 H1 行为定义. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
