/* Bubble Admin - Shoot Bubble Legend. Giao diện tối, menu dọc bên trái (giống admin Sweet Candy). */

:root {
  color-scheme: dark;
  --page: #0e1014;
  --surface: #171a20;
  --surface-2: #20242c;
  --sidebar: #12151a;
  --ink: #eceef1;
  --ink-2: #c3c7cf;
  --muted: #8c929c;
  --axis-ink: #8c929c;
  --grid: #272b34;
  --axis: #3a3f4a;
  --border: rgba(255, 255, 255, 0.08);
  --series: #4b8cf0;
  --series-wash: rgba(75, 140, 240, 0.16);
  --series-soft: #2a5fae;
  --series-track: #1d2738;
  --accent: #2f6fd6;      /* chữ trắng trên nút 4.8:1 */
  --accent-text: #7fb0ff; /* chữ màu nhấn trên nền tối */
  --accent-ink: #ffffff;
  --good: #22b14c;
  --good-ink: #4fd17a;
  --critical: #ef6b6b;
  --critical-bg: #3a1e20;
  --warn-bg: #3a3016;
  --warn-ink: #f3d68a;
  --shadow: none;
  /* Nút phụ (.btn không kèm biến thể): nền + viền đủ rõ để không giống nút bị tắt. */
  --btn-bg: #262b35;
  --btn-bg-hover: #303643;
  --btn-border: #485061;
  --btn-border-hover: #6b7487;
  /* Hộp thoại (<dialog>): nền phủ đủ đậm để tách khỏi trang tối, viền sáng + bóng đổ để hộp nổi lên. */
  --dialog-backdrop: rgba(4, 6, 10, 0.72);
  --dialog-border: rgba(255, 255, 255, 0.16);
  --dialog-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6), 0 24px 64px rgba(0, 0, 0, 0.7), 0 8px 20px rgba(0, 0, 0, 0.45);
  --radius: 12px;
  --sidebar-w: 240px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Mở ngăn kéo khoá cuộn (ẩn thanh cuộn): giữ chỗ để trang không xê dịch. */
  scrollbar-gutter: stable;
  /* Cuộn tới ô / thông báo: chừa chỗ thanh "Lưu nháp" dính đáy. */
  scroll-padding-bottom: 90px;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
}

h1,
h2,
p {
  margin: 0;
}

code,
.mono {
  font-family: var(--mono);
  font-size: 0.9em;
}

code {
  padding: 0.1em 0.35em;
  border-radius: 6px;
  background: var(--surface-2);
  overflow-wrap: anywhere;
}

.muted {
  color: var(--muted);
}

[hidden] {
  display: none !important;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- Buttons ---------- */

/* .btn trơn = nút phụ (Tìm, Chốt lại nhóm, Thêm máy…): nền + viền rõ, hover sáng lên. Các biến thể bên dưới
   (.btn-primary / .btn-ghost / .btn-danger-fill) ghi đè nền + viền. Hover của nút phụ dùng :where() để độ ưu tiên chỉ
   bằng một lớp — .btn-primary (khai báo sau) vẫn thắng, không bị nền xám đè khi rê chuột. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 16px;
  border: 1px solid var(--btn-border);
  border-radius: 10px;
  background: var(--btn-bg);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}

:where(.btn:not(:disabled)):hover {
  background: var(--btn-bg-hover);
  border-color: var(--btn-border-hover);
}

:where(.btn:not(:disabled)):active {
  background: var(--surface-2);
}

.btn-primary {
  background: var(--accent);
  border-color: transparent;
  color: var(--accent-ink);
}

.btn-primary:hover {
  filter: brightness(1.06);
}

.btn-ghost {
  background: transparent;
  border-color: var(--border);
  color: var(--ink-2);
  min-height: 36px;
  padding: 0 12px;
  font-weight: 500;
}

.btn-ghost:hover {
  background: var(--surface-2);
  color: var(--ink);
}

/* ---------- Alerts ---------- */

.alert {
  padding: 10px 14px;
  border-radius: 10px;
  font-size: 14px;
}

.alert-error {
  background: var(--critical-bg);
  color: var(--ink);
  border-left: 4px solid var(--critical);
}

.alert-warn {
  background: var(--warn-bg);
  color: var(--warn-ink);
}

/* ---------- Login / setup ---------- */

.auth-wrap {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 24px 16px;
}

.auth-card {
  width: 100%;
  max-width: 400px;
  padding: 28px 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: var(--shadow);
  display: grid;
  gap: 14px;
}

.auth-card h1 {
  font-size: 22px;
  line-height: 1.25;
}

.login-icon {
  display: block;
  width: 64px;
  height: 64px;
  margin: 0 0 16px;
  border-radius: 14px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
}

.eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Nút "Đăng nhập bằng Google" (iframe của gsi): giữ chỗ để thẻ không nhảy khi nút tải xong. */
.g_id_signin {
  min-height: 44px;
  margin-top: 4px;
}

.steps {
  margin: 0;
  padding-left: 1.25em;
  display: grid;
  gap: 6px;
}

.form {
  display: grid;
  gap: 14px;
  margin-top: 4px;
}

.field {
  display: grid;
  gap: 6px;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-2);
}

.field input {
  width: 100%;
  min-height: 44px;
  padding: 0 12px;
  border: 1px solid var(--axis);
  border-radius: 10px;
  background: var(--page);
  color: var(--ink);
  font: inherit;
  font-weight: 400;
}

.field input:focus {
  border-color: var(--accent);
}

/* ---------- Dashboard layout ---------- */

.updated {
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.updated.is-stale {
  color: var(--critical);
}

.dash {
  display: grid;
  gap: 16px;
  padding-top: 16px;
  padding-bottom: 8px;
}

.dash > * {
  min-width: 0;
}

.empty-state {
  padding: 20px;
  background: var(--surface);
  border: 1px dashed var(--axis);
  border-radius: var(--radius);
  display: grid;
  gap: 10px;
}

.empty-state h2 {
  font-size: 17px;
}

.endpoint {
  display: inline-block;
  max-width: 100%;
}

/* ---------- KPI tiles ---------- */

.kpis {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.tile {
  min-width: 0;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  display: grid;
  align-content: start;
  gap: 4px;
}

.tile-hero {
  grid-column: 1 / -1;
  padding: 18px 20px;
}

.tile-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
}

.tile-value {
  font-size: 28px;
  font-weight: 650;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.hero-value {
  font-size: clamp(48px, 12vw, 72px);
  font-weight: 650;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

.tile-note {
  font-size: 13px;
  color: var(--muted);
}

.delta-up {
  color: var(--good-ink);
}

.delta-down {
  color: var(--critical);
}

.live-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--good);
  box-shadow: 0 0 0 0 rgba(12, 163, 12, 0.5);
  animation: live-pulse 2.4s ease-out infinite;
}

@keyframes live-pulse {
  0% { box-shadow: 0 0 0 0 rgba(12, 163, 12, 0.45); }
  70% { box-shadow: 0 0 0 7px rgba(12, 163, 12, 0); }
  100% { box-shadow: 0 0 0 0 rgba(12, 163, 12, 0); }
}

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

@media (min-width: 760px) {
  .kpis {
    grid-template-columns: minmax(0, 1.3fr) repeat(2, minmax(0, 1fr));
  }

  .tile-hero {
    grid-column: 1;
    grid-row: 1 / span 2;
    align-content: center;
  }
}

/* ---------- Cards & charts ---------- */

.card {
  min-width: 0;
  padding: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.card h2 {
  font-size: 16px;
  line-height: 1.3;
}

.card-sub {
  margin-top: 2px;
  font-size: 13px;
  color: var(--muted);
}

.card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px 16px;
  margin-bottom: 12px;
}

.segmented {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  background: var(--surface-2);
  border-radius: 10px;
}

.segmented button {
  min-height: 32px;
  padding: 0 12px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.segmented button[aria-pressed="true"] {
  background: var(--accent);
  color: var(--accent-ink);
  box-shadow: none;
}

.chart-box {
  position: relative;
  height: 260px;
  min-width: 0;
}

.chart-box canvas {
  display: block;
  max-width: 100%;
}

.chart-empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 16px;
  text-align: center;
  color: var(--muted);
  font-size: 14px;
  background: var(--surface);
}

.table-view {
  margin-top: 10px;
  font-size: 14px;
}

.table-view summary {
  cursor: pointer;
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 600;
  padding: 4px 0;
}

.table-scroll {
  max-height: 320px;
  overflow-y: auto;
  margin-top: 6px;
  border-top: 1px solid var(--grid);
}

/* ---------- Tables ---------- */

.data-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 14px;
}

.data-table th,
.data-table td {
  padding: 8px 6px;
  text-align: left;
  border-bottom: 1px solid var(--grid);
  overflow-wrap: anywhere;
  vertical-align: middle;
}

.data-table th {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
}

.data-table thead th {
  position: sticky;
  top: 0;
  background: var(--surface);
}

.data-table .num {
  width: 5.5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.data-table .share-col {
  width: 34%;
}

.data-table tr:last-child td {
  border-bottom: 0;
}

.data-table .row-other td {
  color: var(--muted);
}

.data-table .empty-row td {
  padding: 18px 6px;
  text-align: center;
  color: var(--muted);
}

.breakdown {
  margin-top: 10px;
}

.share {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.share-bar {
  flex: 1;
  min-width: 24px;
  height: 6px;
  border-radius: 3px;
  background: var(--series-track);
  overflow: hidden;
}

.share-bar > span {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--series);
}

.share-pct {
  flex: none;
  width: 3.2em;
  text-align: right;
}

.breakdowns {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}

/* ---------- Footer ---------- */

.foot {
  padding-top: 8px;
  padding-bottom: 28px;
  display: grid;
  gap: 4px;
  font-size: 12px;
  color: var(--muted);
}

/* ---------- Narrow screens ---------- */

@media (max-width: 480px) {
  body {
    font-size: 14px;
  }

  .chart-box {
    height: 220px;
  }

  .tile {
    padding: 12px 14px;
  }

  .tile-value {
    font-size: 24px;
  }

  .card {
    padding: 14px 12px;
  }

  .data-table .num {
    width: 4.2rem;
  }
}

/* ---------- Trang Cấu hình ---------- */

.alert-ok {
  background: var(--series-track);
  color: var(--ink);
  border-left: 4px solid var(--good);
}

.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn-danger {
  color: var(--critical);
}

.btn-sm {
  min-height: 30px;
  padding: 0 10px;
  font-size: 13px;
}

.cfg-head {
  display: grid;
  gap: 10px;
}

.cfg-head-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
}

.cfg-current {
  flex: 1;
  min-width: 200px;
  font-size: 14px;
  color: var(--ink-2);
}

.cfg-layout {
  display: grid;
  gap: 16px;
}

.cfg-block-list {
  display: none;
  list-style: none;
  margin: 0;
  padding: 0;
}

.cfg-block-select-label {
  display: block;
  margin-bottom: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
}

.cfg-block-select,
.cfg-editor input,
.cfg-editor select,
.cfg-editor textarea,
.cfg-qa-form input,
.cfg-dialog input {
  min-height: 36px;
  padding: 4px 8px;
  border: 1px solid var(--axis);
  border-radius: 8px;
  background: var(--page);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
}

.cfg-block-select {
  width: 100%;
}

.cfg-block-list button {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}

.cfg-block-list button:hover {
  background: var(--surface-2);
}

.cfg-block-list button[aria-current="true"] {
  background: var(--surface-2);
  color: var(--ink);
  font-weight: 600;
}

.cfg-badges {
  display: inline-flex;
  flex: none;
  gap: 4px;
}

.badge {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: 11px;
  font-weight: 600;
  line-height: 18px;
  white-space: nowrap;
}

.badge-draft {
  background: var(--warn-bg);
  color: var(--warn-ink);
}

.badge-override {
  background: var(--series-track);
  color: var(--accent-text);
}

.badge-dirty {
  background: var(--critical-bg);
  color: var(--critical);
}

.cfg-editor h2 {
  font-size: 18px;
}

.cfg-editor-head {
  display: grid;
  gap: 6px;
  margin-bottom: 12px;
}

.cfg-doc {
  font-size: 13px;
  color: var(--ink-2);
}

.cfg-keys {
  display: grid;
}

.cfg-key {
  display: grid;
  gap: 6px 16px;
  padding: 12px 0;
  border-top: 1px solid var(--grid);
}

.cfg-key.is-override {
  box-shadow: inset 3px 0 0 var(--accent);
  padding-left: 10px;
}

.cfg-key.has-error {
  box-shadow: inset 3px 0 0 var(--critical);
  padding-left: 10px;
}

.cfg-key-name {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.cfg-key-desc {
  font-size: 13px;
  color: var(--ink-2);
}

.cfg-key-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  align-items: center;
  font-size: 12px;
  color: var(--muted);
}

.cfg-key-control {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.cfg-key-control input[type="number"] {
  width: 9rem;
}

.cfg-key-control input[type="text"],
.cfg-key-control textarea {
  width: 100%;
  max-width: 34rem;
}

.cfg-key-control textarea {
  min-height: 6.5em;
  font-family: var(--mono);
}

.cfg-key-err {
  color: var(--critical);
  font-size: 13px;
  font-weight: 600;
}

.cfg-live {
  font-size: 12px;
  color: var(--muted);
}

.cfg-switch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  cursor: pointer;
}

.cfg-switch input {
  width: 20px;
  height: 20px;
  min-height: 0;
  accent-color: var(--accent);
}

.cfg-rows {
  width: 100%;
  overflow-x: auto;
}

.cfg-rows table {
  border-collapse: collapse;
  font-size: 13px;
}

.cfg-rows th,
.cfg-rows td {
  padding: 3px 4px;
  text-align: left;
  white-space: nowrap;
}

.cfg-rows th {
  font-weight: 600;
  color: var(--muted);
}

.cfg-rows input[type="number"] {
  width: 6.5rem;
}

.cfg-rows .err {
  border-color: var(--critical);
}

.cfg-targets {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--grid);
  font-size: 14px;
}

.cfg-targets summary {
  cursor: pointer;
  font-weight: 600;
}

.cfg-targets-body {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  align-items: center;
  margin-top: 10px;
}

.cfg-targets-body label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.cfg-targets-body input[type="number"] {
  width: 9rem;
}

.cfg-actions {
  position: sticky;
  bottom: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 14px -16px -16px;
  padding: 12px 16px;
  background: var(--surface);
  border-top: 1px solid var(--border);
  border-radius: 0 0 var(--radius) var(--radius);
}

.cfg-actions input {
  flex: 1;
  min-width: 160px;
}

.cfg-actions .spacer {
  flex: 1;
}

.cfg-qa-form {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}

.cfg-qa-form input[name="install_id"] {
  flex: 2;
  min-width: 200px;
}

.cfg-qa-form input[name="days"] {
  width: 5rem;
}

.cfg-qa-form input[name="note"] {
  flex: 1;
  min-width: 140px;
}

.cfg-dialog {
  width: min(720px, calc(100vw - 32px));
  max-height: calc(100vh - 48px);
  padding: 0;
  border: 1px solid var(--dialog-border);
  border-radius: 14px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--dialog-shadow);
}

/* Nền phủ đậm + làm mờ trang phía sau (backdrop-filter là CSS thuần, không vướng CSP). Trình duyệt không hỗ trợ blur
   vẫn có lớp phủ 72 % — đủ tách hộp khỏi trang. */
.cfg-dialog::backdrop {
  background: var(--dialog-backdrop);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

.cfg-dialog-body {
  display: grid;
  gap: 12px;
  padding: 18px;
}

.cfg-dialog h2 {
  font-size: 18px;
}

.cfg-note-label {
  display: grid;
  gap: 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
}

.cfg-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.cfg-diff {
  display: grid;
  gap: 10px;
  max-height: 55vh;
  overflow: auto;
}

.cfg-diff h3 {
  margin: 0 0 4px;
  font-size: 14px;
}

.cfg-diff label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.cfg-diff table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  table-layout: fixed;
}

.cfg-diff td {
  padding: 4px 6px;
  border-bottom: 1px solid var(--grid);
  vertical-align: top;
  overflow-wrap: anywhere;
}

.cfg-diff .old {
  color: var(--muted);
  text-decoration: line-through;
}

.cfg-diff .new {
  font-weight: 600;
}

.cfg-pre {
  max-height: 55vh;
  overflow: auto;
  margin: 0;
  padding: 10px;
  border-radius: 8px;
  background: var(--surface-2);
  font-family: var(--mono);
  font-size: 12px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.cfg-warn {
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--warn-bg);
  color: var(--warn-ink);
  font-size: 13px;
}

.cfg-history-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

@media (min-width: 1180px) {
  .cfg-layout {
    grid-template-columns: 280px minmax(0, 1fr);
    align-items: start;
  }

  .cfg-blocks {
    position: sticky;
    top: 12px;
  }

  .cfg-block-select,
  .cfg-block-select-label {
    display: none;
  }

  .cfg-block-list {
    display: grid;
    gap: 2px;
  }

  .cfg-key {
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    grid-template-rows: auto auto 1fr;
    align-items: start;
  }

  .cfg-key-control {
    grid-column: 2;
    grid-row: 1 / span 3;
    align-self: center;
  }
}

@media (max-width: 480px) {
  .cfg-rows input[type="number"] {
    width: 4.6rem;
  }

  .cfg-actions {
    margin: 14px -12px -14px;
    padding: 10px 12px;
  }
}

.btn-danger-fill {
  background: var(--critical);
  border-color: transparent;
  color: #ffffff;
}

/* ---------- Khung trang: menu dọc bên trái (AdminView::layoutStart) ---------- */

.btn {
  gap: 8px;
  white-space: nowrap;
}

.layout {
  display: flex;
  min-height: 100vh;
  min-height: 100dvh;
}

.sidebar {
  position: sticky;
  top: 0;
  flex: none;
  width: var(--sidebar-w);
  height: 100vh;
  height: 100dvh;
  background: var(--sidebar);
  border-right: 1px solid var(--border);
}

.sidebar-top,
.nav-close,
.nav-backdrop {
  display: none;
}

.nav-body {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 16px 12px;
  overflow-y: auto;
}

.drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: 0 4px 18px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  color: var(--ink);
  text-decoration: none;
}

.brand-mark {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  object-fit: cover;
}

.brand-text {
  display: grid;
  min-width: 0;
  line-height: 1.2;
}

.brand-text strong {
  font-size: 15px;
}

.brand-text small {
  font-size: 12px;
  color: var(--muted);
}

.menu {
  display: grid;
  gap: 2px;
}

.menu a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 8px;
  color: var(--ink-2);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}

.menu a:hover {
  background: var(--surface-2);
  color: var(--ink);
}

.menu a.active {
  background: var(--series-track);
  color: var(--ink);
  box-shadow: inset 3px 0 0 var(--accent);
}

.menu a.active .ico {
  color: var(--series);
}

.ico {
  flex: none;
}

.logout {
  display: grid;
  gap: 8px;
  margin-top: auto;
  padding: 14px 4px 0;
  border-top: 1px solid var(--border);
}

.who {
  overflow: hidden;
  font-size: 12px;
  color: var(--muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.logout .btn {
  justify-content: flex-start;
}

.page {
  flex: 1;
  min-width: 0;
  padding: 20px 24px 28px;
}

.page-head,
.page .dash,
.page .foot {
  max-width: 1200px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 0;
  padding-right: 0;
}

.page .dash {
  padding-top: 0;
}

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
  margin-bottom: 16px;
}

.page-title {
  font-size: 22px;
  line-height: 1.25;
}

.page-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

@media (max-width: 900px) {
  .layout {
    display: block;
  }

  .sidebar {
    z-index: 30;
    width: auto;
    height: auto;
    border-right: 0;
    border-bottom: 1px solid var(--border);
  }

  .sidebar-top {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
  }

  .nav-btn,
  .nav-close {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--ink);
  }

  .nav-body {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 50;
    width: min(280px, 85vw);
    height: auto;
    background: var(--sidebar);
    border-right: 1px solid var(--border);
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform 0.2s ease, visibility 0.2s;
  }

  /* Mở: hiện ngay (để focus được mục menu); đóng: giữ visibility tới khi trượt xong.
     :target chỉ dùng khi không có JS (html.js do admin.js gắn): có JS thì class nav-open quyết định, hash không còn tác dụng. */
  .nav-open .nav-body,
  html:not(.js) .nav-body:target {
    transform: none;
    visibility: visible;
    transition: transform 0.2s ease, visibility 0s;
  }

  .nav-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(0, 0, 0, 0.55);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s;
  }

  .nav-open .nav-backdrop,
  html:not(.js) .nav-body:target ~ .nav-backdrop {
    opacity: 1;
    pointer-events: auto;
  }

  body.nav-open {
    overflow: hidden;
  }

  /* Thanh trên cùng dính (☰ + logo) và thanh nút dính đáy cao hơn trên điện thoại. */
  html {
    scroll-padding-top: 72px;
    scroll-padding-bottom: 130px;
  }

  .page {
    padding: 16px;
  }

  .page-title {
    font-size: 19px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav-body,
  .nav-backdrop {
    transition: none;
  }
}

/* ---------- Trang Cấu hình: phần thêm sau vòng tester ---------- */

.cfg-key-status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  min-width: 0;
}

.cfg-block-list button {
  flex-wrap: wrap;
}

.cfg-block-name {
  min-width: 0;
}

.cfg-badges {
  flex-wrap: wrap;
}

.cfg-errlist {
  margin: 6px 0 0;
  padding-left: 18px;
}

.cfg-errlist li + li {
  margin-top: 2px;
}

.alert-error .btn {
  margin-top: 8px;
}

.cfg-history {
  display: grid;
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
}

.cfg-history li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px 12px;
  padding: 10px 0;
  border-top: 1px solid var(--grid);
  font-size: 14px;
}

.cfg-history li.muted {
  justify-content: center;
}

.cfg-item-main {
  display: grid;
  gap: 2px;
  min-width: 0;
  flex: 1 1 260px;
}

.cfg-item-main p {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  overflow-wrap: anywhere;
}

.cfg-item-main .muted {
  font-size: 13px;
}

.cfg-id {
  overflow-wrap: anywhere;
}

.cfg-item-actions {
  display: flex;
  gap: 6px;
}

.cfg-diff thead th {
  padding: 4px 6px;
  font-size: 12px;
  font-weight: 600;
  text-align: left;
  color: var(--muted);
}

.cfg-diff td:first-child {
  width: 34%;
}

@media (min-width: 1180px) {
  .cfg-key.is-wide {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
  }

  .cfg-key.is-wide .cfg-key-control {
    grid-column: 1;
    grid-row: auto;
  }
}

/* ---------- Icon lấy từ game (assets/game/, tools/export_game_icons.py) ---------- */

.gi {
  display: inline-block;
  flex: none;
  object-fit: contain;
  vertical-align: middle;
}

.menu a .gi {
  margin: -3px 0;
}

.page-title {
  display: flex;
  align-items: center;
  gap: 10px;
}

.cfg-block-list button {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  align-items: center;
  gap: 2px 10px;
}

/* Badge xuống hàng dưới tên: tên khối dài không bị ép còn vài chữ một dòng. */
.cfg-block-list button .cfg-badges {
  grid-column: 2;
  justify-content: flex-start;
}

.cfg-block-list button .cfg-badges:empty {
  display: none;
}

.cfg-block-list button .gi {
  grid-row: 1 / span 2;
  align-self: center;
}

.badge-wrap {
  white-space: normal;
  overflow-wrap: anywhere;
}

.cfg-note {
  overflow-wrap: anywhere;
}

.cfg-rows th {
  height: 26px;
  vertical-align: middle;
}

.cfg-editor-title {
  display: flex;
  align-items: center;
  gap: 10px;
}

.cfg-editor-title:focus {
  outline: none;
}

.cfg-key-name {
  display: flex;
  align-items: center;
  gap: 8px;
}

.cfg-th {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  line-height: 18px;
  vertical-align: middle;
}

.cfg-enum {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.cfg-diff h3 .gi {
  margin-right: 2px;
}

.cfg-diff h3,
.cfg-diff label {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Nút Google là iframe nền sáng: trang tối (color-scheme: dark) khác iframe thì trình duyệt tô nền trắng đục sau
   iframe. Cho riêng vùng nút color-scheme sáng để nền iframe trong suốt (nút filled_black tự tối). */
.g_id_signin {
  color-scheme: light;
}

/* ---------- Trang BXH / Nghi gian lận (leaderboard.php, suspect.php) ---------- */

/* Bảng rộng cuộn ngang TRONG khung thẻ (điện thoại không vỡ trang); không giới hạn chiều cao như .table-scroll.
   Bóng mờ ở mép còn nội dung bị khuất (lớp nền "local" che bóng khi đã cuộn tới mép) — báo bảng cuộn ngang được. */
.lb-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-top: 6px;
  border-top: 1px solid var(--grid);
  background:
    linear-gradient(to right, var(--surface) 30%, rgba(0, 0, 0, 0)) left center / 40px 100% no-repeat local,
    linear-gradient(to left, var(--surface) 30%, rgba(0, 0, 0, 0)) right center / 40px 100% no-repeat local,
    linear-gradient(to right, var(--lb-edge), rgba(0, 0, 0, 0)) left center / 18px 100% no-repeat scroll,
    linear-gradient(to left, var(--lb-edge), rgba(0, 0, 0, 0)) right center / 18px 100% no-repeat scroll;
  background-color: var(--surface);
  --lb-edge: rgba(127, 176, 255, 0.3);   /* nền tối: bóng đen không thấy — dùng ánh màu nhấn */
}

/* Gợi ý vuốt ngang: chỉ hiện ở màn hẹp (bảng rộng hơn khung). */
.lb-swipe {
  display: none;
  margin: 6px 0 0;
  font-size: 12px;
  color: var(--muted);
}

@media (max-width: 760px) {
  .lb-swipe {
    display: block;
  }

  .lb-table .lb-name {
    min-width: 6.5rem;
  }
}

/* Hạng cũ của người bị cờ (L13 / chờ chốt lại): không phải số hạng trên bảng của game. */
.lb-old-rank {
  color: var(--muted);
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  cursor: help;
}

.lb-table {
  table-layout: auto;
  min-width: 560px;
}

.lb-table th,
.lb-table td {
  overflow-wrap: normal;
  white-space: nowrap;
}

.lb-table .lb-name {
  min-width: 9rem;
  max-width: 16rem;
  white-space: normal;
  overflow-wrap: anywhere;
}

.lb-table .num {
  width: auto;
}

/* Bảng nhóm: Hạng | Người chơi (mã 8 ký tự chữ nhỏ dưới tên) | Điểm | Thao tác | Trạng thái (cờ + đã nhận) | Nghi.
   Màn hẹp (≤ 720px) chuyển thành thẻ — xem khối @media cuối phần BXH. */
.lb-board {
  min-width: 560px;
}

.lb-board .lb-code {
  display: block;
  font-size: 12px;
  line-height: 1.3;
  color: var(--muted);
  letter-spacing: 0.02em;
}

.lb-board .lb-score {
  font-weight: 600;
}

.lb-board .lb-act {
  width: 1%;
}

.lb-board .lb-state {
  min-width: 9rem;
  white-space: normal;
}

.lb-badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}

.lb-unclaimed {
  font-size: 12px;
}

.lb-blocked .badge + .badge,
.lb-final .badge + .badge {
  margin-left: 4px;
}

.lb-suspect {
  min-width: 820px;
}

.lb-suspect td {
  vertical-align: top;
}

.lb-rank {
  width: 3.5rem;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.lb-table tr.lb-active td {
  background: var(--series-track);
}

.lb-table tr.lb-bot td {
  color: var(--muted);
}

.lb-table tr.lb-flagged .lb-pname {
  text-decoration: line-through;
  text-decoration-color: var(--critical);
}

.lb-table a {
  color: var(--accent-text);
}

.lb-reward,
.lb-at {
  display: block;
  font-size: 12px;
}

.lb-detail {
  font-size: 12px;
  white-space: normal;
}

.lb-reasons {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.lb-suspect .lb-reasons {
  flex-direction: column;
  flex-wrap: nowrap;
}

.lb-events {
  flex-wrap: wrap;
}

.lb-events .btn {
  gap: 6px;
}

.segmented a.btn {
  text-decoration: none;
}

.lb-find {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin-top: 12px;
  font-size: 14px;
}

.lb-find input {
  width: 10rem;
  min-height: 32px;
  padding: 0 10px;
  border: 1px solid var(--axis);
  border-radius: 8px;
  background: var(--page);
  color: var(--ink);
  font: inherit;
  text-transform: uppercase;
}

.lb-dist {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 0 0 8px;
  font-size: 13px;
}

.lb-group-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.lb-pager {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 10px;
  font-size: 13px;
}

.lb .card .alert {
  margin: 0 0 12px;
}

@media (max-width: 480px) {
  .lb-events {
    display: flex;
    width: 100%;
  }

  .lb-events .btn {
    flex: 1 1 auto;
  }
}

.lb a.btn {
  text-decoration: none;
}

/* Danh sách nhóm: "Chốt" (căn trái) đứng ngay sau "Điểm cao nhất" (căn phải) — chừa khoảng để hai số / chữ không dính. */
.lb-groups .lb-final {
  padding-left: 22px;
}

/* Nhãn Bị chặn / Chốt được xuống dòng: màn 721–900px bảng vừa khung, không phải vuốt. */
.lb-groups td.lb-blocked,
.lb-groups td.lb-final {
  white-space: normal;
}

.lb-groups td.lb-blocked .badge,
.lb-groups td.lb-final .badge {
  white-space: nowrap;
}

/* ---------- Màn hẹp (≤ 720px): mọi bảng BXH / Nghi gian lận (.lb-cards) thành thẻ, không cần vuốt ngang ----------
   Mỗi dòng một thẻ dựng bằng grid-template-areas riêng từng bảng (bên dưới). Ô có data-label hiện nhãn cột ngay trong
   thẻ (::before). Tiêu đề cột vẫn còn cho trình đọc màn hình (ẩn bằng clip, không display:none). */
@media (max-width: 720px) {
  .lb-swipe-wide {
    display: none !important;
  }

  .lb-scroll {
    background: none;
  }

  .lb-table.lb-cards {
    min-width: 0;
  }

  .lb-table.lb-cards,
  .lb-cards tbody {
    display: block;
  }

  .lb-cards thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .lb-cards tbody tr {
    display: grid;
    column-gap: 10px;
    align-items: center;
    padding: 9px 4px;
    border-bottom: 1px solid var(--grid);
  }

  .lb-cards tbody tr:last-child {
    border-bottom: 0;
  }

  .lb-cards tbody tr.empty-row {
    display: block;
  }

  /* (0,2,1): thắng .lb-table .lb-name / .data-table .num / .lb-board .lb-act… (0,2,0) của bố cục bảng. */
  .lb-table.lb-cards td {
    display: block;
    width: auto;
    min-width: 0;
    max-width: none;
    padding: 0;
    border: 0;
    background: none;
    text-align: left;
    white-space: normal;
  }

  .lb-table.lb-cards tr.empty-row td {
    padding: 14px 4px;
    text-align: center;
  }

  .lb-cards tr.lb-active {
    background: var(--series-track);
  }

  .lb-cards td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 11px;
    font-weight: 400;
    line-height: 1.3;
    color: var(--muted);
  }

  .lb-cards .lb-c-id {
    font-weight: 600;
  }

  .lb-cards .lb-c-zero {
    display: none !important;
  }

  /* Danh sách mùa: | #mùa | trạng thái           |
                    |      | bắt đầu | kết thúc   |
                    |      | nhóm    | người thật | */
  .lb-seasons tbody tr {
    grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "id status status"
      "id start end"
      "id groups players";
    row-gap: 6px;
  }

  .lb-seasons .lb-c-id { grid-area: id; align-self: start; }
  .lb-seasons .lb-c-status { grid-area: status; font-weight: 600; }
  .lb-seasons .lb-c-start { grid-area: start; }
  .lb-seasons .lb-c-end { grid-area: end; }
  .lb-seasons .lb-c-groups { grid-area: groups; }
  .lb-seasons .lb-c-players { grid-area: players; }

  /* Danh sách nhóm: | #nhóm | Đã chốt / Chưa + "N cần chốt lại"          |
                     |       | Bị chặn: nhãn cờ mùa / tài khoản (khi > 0)  |
                     |       | người thật | đã nhận | điểm cao nhất        |
                     |       | cỡ         | league (Tournament)          | */
  .lb-groups tbody tr {
    grid-template-columns: auto repeat(3, minmax(0, 1fr));
    grid-template-areas:
      "id final final final"
      "id blocked blocked blocked"
      "id players claimed top"
      "id size league league";
  }

  .lb-groups .lb-c-id { grid-area: id; align-self: start; }
  .lb-groups td.lb-final { grid-area: final; }
  .lb-groups td.lb-blocked { grid-area: blocked; margin-top: 6px; }
  .lb-groups .lb-c-players { grid-area: players; margin-top: 6px; }
  .lb-groups .lb-c-claimed { grid-area: claimed; margin-top: 6px; }
  .lb-groups .lb-c-top { grid-area: top; margin-top: 6px; }
  .lb-groups .lb-c-size { grid-area: size; margin-top: 6px; }
  .lb-groups .lb-c-league { grid-area: league; margin-top: 6px; }

  .lb-groups td.lb-blocked::before {
    display: inline;
    margin-right: 6px;
  }

  .lb-groups .lb-final .badge + .badge {
    margin-left: 6px;
  }

  /* Nghi gian lận: | tên (+ nhãn tài khoản) | N lần |
                    | mã                     |       |
                    | lý do (nhãn nối hàng ngang)    |
                    | Lần cuối: giờ + chi tiết       |
                    | Mùa: link sang BXH             | */
  .lb-suspect tbody tr {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "name total"
      "code total"
      "reasons reasons"
      "last last"
      "seasons seasons";
    align-items: start;
  }

  .lb-suspect td.lb-name { grid-area: name; font-weight: 600; }
  .lb-suspect .lb-c-code { grid-area: code; font-size: 12px; color: var(--muted); }
  .lb-suspect .lb-c-total { grid-area: total; font-weight: 600; white-space: nowrap; }
  .lb-suspect .lb-c-reasons { grid-area: reasons; margin-top: 8px; }
  .lb-suspect .lb-c-last { grid-area: last; margin-top: 8px; }
  .lb-suspect .lb-c-seasons { grid-area: seasons; margin-top: 8px; }

  .lb-suspect .lb-c-total::after {
    content: " lần";
    font-weight: 400;
    color: var(--muted);
  }

  .lb-suspect .lb-c-reasons .lb-reasons {
    flex-direction: row;
    flex-wrap: wrap;
  }

  /* Bảng nhóm: mỗi người một thẻ —
       hàng 1: hạng | tên (+ mã) | điểm;  hàng 2: | trạng thái (cờ, đã nhận) | nút Gắn / Bỏ cờ;  hàng 3: | số lần Nghi (nếu có). */
  .lb-board tbody tr {
    grid-template-columns: 2.25rem minmax(0, 1fr) auto;
    grid-template-areas:
      "rank name score"
      "rank state act"
      "rank sus sus";
  }

  .lb-board td.lb-rank {
    grid-area: rank;
    align-self: start;
  }

  .lb-board td.lb-name {
    grid-area: name;
  }

  .lb-board td.lb-score {
    grid-area: score;
    align-self: start;
    text-align: right;
  }

  .lb-board td.lb-state {
    grid-area: state;
    margin-top: 6px;
  }

  .lb-board td.lb-act {
    grid-area: act;
    justify-self: end;
    align-self: end;
    margin-top: 6px;
  }

  .lb-board td.lb-sus {
    grid-area: sus;
    margin-top: 4px;
    font-size: 12px;
  }

  .lb-board .lb-sus a::before {
    content: "Nghi gian lận mùa này: ";
  }

  .lb-board td.lb-sus-0,
  .lb-board tr.lb-bot td.lb-act,
  .lb-board tr.lb-bot td.lb-state,
  .lb-board tr.lb-bot td.lb-sus {
    display: none;
  }

  .lb-board tr.lb-bot {
    grid-template-areas: "rank name score";
    padding: 6px 4px;
  }

  .lb-board .lb-code {
    display: inline;
    margin-left: 6px;
  }
}

/* ---------- Trang Lịch mùa: thẻ "Vòng xoay" (schedule.php, M4b) ---------- */

/* Thứ tự vòng hiện hành: chip theo hàng, xuống dòng khi hẹp; lượt tắt / lễ tắt mờ + gạch. */
.rot-slots {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 8px;
  margin: 0 0 10px;
  padding: 0;
  list-style: none;
}

.rot-slot {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 6px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: 13px;
}

.rot-slot + .rot-slot::before {
  content: "→";
  margin-right: 4px;
  color: var(--muted);
}

.rot-slot.rot-fest {
  background: var(--warn-bg);
  color: var(--warn-ink);
}

.rot-slot.is-off {
  opacity: 0.55;
  text-decoration: line-through;
}

/* Bảng 24 lượt: cuộn ngang trong .lb-scroll khi hẹp (như bảng BXH). */
.rot-table {
  table-layout: auto;
  min-width: 600px;
}

.rot-table th,
.rot-table td {
  white-space: nowrap;
  overflow-wrap: normal;
}

.rot-table td:last-child {
  white-space: normal;
  min-width: 10rem;
}

.rot-table .num {
  width: auto;
}

.rot-table .rot-event .gi {
  vertical-align: middle;
}

.rot-table tr.rot-now td {
  background: var(--series-wash);
}

.cfg-key-hint {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
}

.cfg-key-hint.is-warn {
  color: var(--warn-ink);
}

.cfg-key-hint.is-critical {
  color: var(--critical);
  font-weight: 600;
}

/* Mức cảnh báo dùng chung (trang Lễ hội, thẻ Vòng xoay, đầu khối Cấu hình): đỏ = critical, xám = info; mặc định vàng. */
.cfg-warn.is-critical {
  background: var(--critical-bg);
  color: var(--critical);
}

.cfg-warn.is-info {
  background: var(--surface-2);
  color: var(--ink-2);
}

/* Bảng festival.windows (config.js): dòng sinh ra cửa sổ đang mở tô nhạt; ghi chú "Dòng i: …" dưới bảng (đỏ khi theme còn art
   tạm trên prod) — không để ở cột cuối vì bảng rộng cuộn ngang. */
.cfg-rows tr.cfg-row-open td {
  background: var(--series-wash);
}

.cfg-row-notes {
  display: grid;
  gap: 2px;
  margin: 6px 0 0;
  padding: 0;
  list-style: none;
  font-size: 12px;
  color: var(--muted);
}

.cfg-row-notes .cfg-row-open {
  color: var(--accent-text);
}

.cfg-row-notes .cfg-row-critical {
  color: var(--critical);
  font-weight: 600;
}

/* ---------- Trang Lễ hội (festival.php, M4c — chỉ xem) ---------- */

.fest-warns {
  display: grid;
  gap: 6px;
  margin-top: 10px;
}

.fest-grid {
  display: grid;
  /* Một thẻ / hàng tới màn rất rộng: bảng Cửa sổ / Mùa dự kiến có 6 cột — 2 thẻ / hàng ở 1366 px làm bảng bị cắt, phải cuộn. */
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 860px), 1fr));
  gap: 16px;
}

.fest-card {
  display: grid;
  gap: 10px;
  align-content: start;
}

.fest-card.is-off {
  border-style: dashed;
}

.fest-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
}

.fest-head h2 {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-right: auto;
}

.fest-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.badge-good {
  background: rgba(34, 177, 76, 0.16);
  color: var(--good-ink);
}

.fest-card h3 {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
}

.fest-table {
  table-layout: auto;
  min-width: 440px;
}

.fest-table th,
.fest-table td {
  white-space: nowrap;
}

.fest-table td:last-child,
.fest-table td.fest-wrap {
  white-space: normal;
  min-width: 8rem;
}

/* Cột trạng thái ("đang mở — chỉ kéo dài được ngày đóng · mã …") đủ rộng để không ngắt 3–4 dòng khi bảng cuộn ở màn hẹp. */
.fest-table td:last-child {
  min-width: 15rem;
}

.fest-table tr.is-open td {
  background: var(--series-wash);
}

.fest-table tr.is-past td {
  color: var(--muted);
}

.fest-gifts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fest-gifts li {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px 3px 5px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: 12px;
}

.fest-special {
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--series-track);
  color: var(--accent-text);
  font-size: 13px;
}

.fest-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.rot-windows {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 10px;
  padding: 0;
  list-style: none;
}

.rot-windows li {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px 3px 5px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: 12px;
}

.rot-windows li.is-off {
  opacity: 0.6;
}

.rot-windows li.is-art {
  background: var(--critical-bg);
  color: var(--critical);
}

/* ---------- Tracking (M9a) ---------- */
/* Trang Quảng cáo / Crash / Máy test + khối tracking của Tổng quan (Docs/WebServer/M9A_ADMIN_TRACKING.md §10). Không style=""
   nội tuyến (CSP style-src 'self'): mọi bố cục ở đây. Màu chuỗi biểu đồ đọc qua biến (assets/track.js). */

:root {
  --trk-c1: #4b8cf0;   /* Precise / crash-free / báo cáo */
  --trk-c2: #f0b44b;   /* Estimated / không-marker / số máy */
  --trk-c3: #8c6cf0;   /* Khác / ANR */
  --trk-c4: #ef6b6b;   /* Crash */
  --trk-gray: #5d6370; /* chưa tách / mẫu nhỏ / OOM */
}

.trk .card .alert,
.trk-overview .alert {
  margin-top: 8px;
}

.trk-filter {
  display: grid;
  grid-template-columns: minmax(0, 1fr);   /* cột = bề rộng thẻ: hàng nút nhanh cuộn ngang thay vì nới thẻ ra (tester r2 T-3, 320 px) */
  gap: 10px;
}

.trk-filter > * {
  min-width: 0;
}

.trk-filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: center;
}

/* Nút nhanh ngày / env / tab: một hàng, cuộn ngang trên màn hẹp thay vì xuống dòng lộn xộn. */
.trk-seg {
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  flex-wrap: nowrap;
}

.trk-seg .btn {
  flex: none;
  white-space: nowrap;
}

.trk-off {
  opacity: 0.45;
  cursor: not-allowed;
}

.trk-form {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  align-items: flex-end;
}

.trk-field {
  display: grid;
  gap: 3px;
  min-width: 0;
  font-size: 12px;
  color: var(--muted);
}

.trk-field input,
.trk-field select {
  box-sizing: border-box;
  max-width: 100%;   /* không lòi khỏi thẻ trên điện thoại hẹp (tester r2 T-3) */
  min-width: 0;
  min-height: 36px;
  padding: 0 8px;
  border: 1px solid var(--btn-border);
  border-radius: 8px;
  background: var(--surface-2);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
}

.trk-field input[type="text"] {
  width: 7.5rem;
}

.trk-source {
  font-size: 13px;
  color: var(--ink-2);
}

.trk-note {
  margin: 0;
}

.trk-alerts {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.trk-sev {
  font-weight: 700;
  margin-right: 4px;
}

.trk-kpis {
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
}

.trk-kpis-2 {
  margin-bottom: 12px;
}

.trk-tile .tile-value {
  font-size: 24px;
}

/* Số + đơn vị trong thẻ không ngắt dòng giữa chừng ("92,3 %"); giữa các số ghép (" / ") vẫn xuống dòng được. */
.trk-nw {
  white-space: nowrap;
}

.trk-tile-wide {
  grid-column: span 2;
}

.trk-tile-text .tile-value {
  font-size: 15px;
  line-height: 1.4;
}

.trk-tile.trk-untrusted .tile-value {
  color: var(--warn-ink);
  text-decoration: underline dotted;
}

.trk-dim,
.trk-tile.trk-dim .tile-value {
  color: var(--muted);
}

.trk-chart {
  height: 260px;
}

.trk-table th,
.trk-table td {
  vertical-align: top;
}

.trk-key {
  font-weight: 600;
}

.trk-title-cell {
  min-width: 14rem;
  max-width: 34rem;
  white-space: normal !important;
  overflow-wrap: anywhere !important;
}

.trk-title-cell a {
  color: var(--accent-text);
  font-family: var(--mono);
  font-size: 13px;
}

.trk-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}

.trk-tabs {
  margin-bottom: 10px;
}

.trk-more {
  margin-top: 10px;
}

.trk-more > summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--accent-text);
}

.trk-count {
  margin-left: 4px;
  font-variant-numeric: tabular-nums;
  opacity: 0.8;
}

.trk-h2 {
  margin-bottom: 6px;
}

.trk-h3 {
  margin: 14px 0 4px;
  font-size: 13px;
  color: var(--ink-2);
}

.trk-builds {
  max-width: 420px;
}

.trk-foot {
  margin: 10px 0 0;
  padding-left: 18px;
  display: grid;
  gap: 3px;
}

.trk-links {
  display: flex;
  gap: 8px;
}

.trk-collapsed p {
  font-size: 14px;
}

.trk-dl {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 8px 16px;
  margin: 10px 0 0;
}

.trk-dl dt {
  font-size: 12px;
  color: var(--muted);
}

.trk-dl dd {
  margin: 0;
  overflow-wrap: anywhere;
}

.trk-dl-sm {
  font-size: 13px;
}

.trk-g-title {
  font-family: var(--mono);
  font-size: 15px !important;
  overflow-wrap: anywhere;
}

.trk-sig {
  user-select: all;
  white-space: nowrap;   /* chữ ký 32 hex không ngắt giữa (tester r2 M-3); ô cha xuống dòng nút "Chép" */
  overflow-wrap: normal;
}

.trk-dl-wide {
  grid-column: 1 / -1;
}

.trk-dist {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: 12px 16px;
}

.trk-dist-table {
  min-width: 0;
}

.trk-dist-table caption {
  text-align: left;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-2);
  padding-bottom: 4px;
}

.trk-dist-table td:first-child {
  overflow-wrap: break-word;   /* chỉ cắt từ dài hơn cả cột, không cắt "GameScene" thành "GameScen/e" (tester r2 M-3) */
  word-break: normal;
}

.trk-sample {
  border-top: 1px solid var(--grid);
  padding: 8px 0;
}

.trk-sample summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--ink-2);
}

.trk-pre-label {
  margin-top: 8px;
  font-size: 12px;
  color: var(--muted);
}

.trk-pre {
  margin: 4px 0 0;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--page);
  border: 1px solid var(--grid);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 60vh;
  overflow: auto;
}

.trk-code-form {
  margin-bottom: 6px;
}

.trk-mark-form {
  margin-top: 12px;
}

@media (max-width: 720px) {
  /* Bảng tracking thành thẻ (.lb-cards): ô đầu (khoá) chiếm cả hàng, các ô số hai cột. */
  .trk-table.lb-cards tbody tr {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 6px;
  }

  .trk-table.lb-cards td.trk-key,
  .trk-table.lb-cards td.trk-title-cell {
    grid-column: 1 / -1;
    max-width: none;
    min-width: 0;
  }

  .trk-table.lb-cards td:empty {
    display: none;
  }

  /* Chuỗi máy dài không khoảng trắng (thiết bị / OS / scene ≤ 64 ký tự) không tràn sang ô bên (tester r1 T-4). */
  .trk-table.lb-cards td {
    overflow-wrap: anywhere;
  }

  /* Hai tab nhóm crash: xuống dòng thay vì cuộn ngang khuất tab thứ hai + số đếm (tester r1 M-9). */
  .trk-seg.trk-tabs {
    flex-wrap: wrap;
    overflow-x: visible;
  }

  .trk-seg.trk-tabs .btn {
    flex: 1 1 auto;
    white-space: normal;
    text-align: center;
  }

  .trk-tile-wide {
    grid-column: 1 / -1;
  }
}

@media (max-width: 480px) {
  .trk-chart {
    height: 220px;
  }

  /* Nút khoảng nhanh: màn rất hẹp (320 px) xuống dòng thay vì cắt "90 ngày" + lộ thanh cuộn (tester r3 M-6); vừa một hàng thì như cũ. */
  .trk-seg.trk-quick {
    flex-wrap: wrap;
    overflow-x: visible;
  }

  .trk-kpis {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .trk-form {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .trk-field input,
  .trk-field select {
    width: 100%;
  }

  .trk-apply {
    grid-column: 1 / -1;
  }
}

/* ---------- Admin M9b ---------- */
/* Trang Người chơi (players.php), Nhật ký (audit.php), trang 403 (AdminView::forbidden) — Docs/WebServer/M9B_ADMIN.md §11.
   Tiền tố .adm-; dùng lại .card / .kpis / .tile / .data-table .lb-cards (≤ 720 px thành thẻ) / .cfg-dialog. */

.adm-forbidden {
  display: grid;
  gap: 10px;
  max-width: 640px;
}

.adm-wrap {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Gói client báo ở bảng sự kiện của đơn (tester M9b-2 r3 T-2): không ngắt giữa chữ (ô .adm-wrap cho ngắt mọi chỗ) — chỉ ngắt
   trước đoạn cuối (<wbr> sau dấu chấm cuối) khi bảng chật: "com.cgs.bubblepop1." / "pack3". */
.iap-pkg {
  overflow-wrap: normal;
  word-break: normal;
}

/* Bảng sự kiện của đơn có 11 cột: cột Lý do / Chi tiết (thường rỗng) hẹp hơn mặc định 8rem để vừa khung 1440 không cuộn. */
#iap-events td.adm-wrap[data-label="Lý do"],
#iap-events td.adm-wrap[data-label="Chi tiết"] {
  min-width: 6rem;
}

.adm-nw {
  white-space: nowrap;
}

.adm-sub {
  margin: 14px 0 6px;
  font-size: 14px;
  color: var(--ink-2);
}

.adm-code {
  font-size: 11px;
  color: var(--muted);
}

.adm-src {
  font-weight: 500;
}

.adm-target a {
  color: var(--accent-text);
}

.adm-link-quiet {
  color: var(--muted);
  font-size: 12px;
}

.adm-hint {
  margin: 10px 0 0;
  padding-left: 18px;
}

.adm-hint li + li {
  margin-top: 2px;
}

.adm-hint-sm {
  font-size: 12px;
  font-weight: 400;
  color: var(--muted);
}

.adm-list {
  margin: 6px 0 0;
  padding-left: 18px;
}

.adm-list li + li {
  margin-top: 4px;
}

.adm-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}

/* Ô tìm + bộ lọc: một hàng trên máy tính, một cột trên điện thoại. */
.adm-search,
.adm-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  align-items: flex-end;
}

.adm-search .trk-field input,
.adm-filter .trk-field input,
.adm-filter .trk-field select {
  width: 100%;
}

.adm-grow {
  flex: 1 1 280px;
}

.adm-filter .trk-field {
  flex: 1 1 150px;
}

.adm-check {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  min-height: 36px;
  font-size: 13px;
  color: var(--ink-2);
}

.adm-filter-actions {
  display: flex;
  gap: 8px;
}

.adm-quick {
  display: flex;
  gap: 6px;
  margin-top: 10px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.adm-quick .btn {
  flex: none;
}

/* Thanh khoảng nhanh của trang IAP (5 nút): xuống dòng ở màn hẹp — không giấu nút "12 tháng" sau thanh cuộn ngang không có dấu hiệu
   (tester M9b-2 r1 TM-2). */
.adm-quick.segmented {
  flex-wrap: wrap;
  overflow-x: visible;
  width: fit-content;
  max-width: 100%;
}

.adm-more {
  margin-top: 8px;
}

/* Hồ sơ người chơi: khối gập <details> — tiêu đề là nút bấm cả hàng. */
.adm-head h2 {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: center;
  font-size: 20px;
}

.adm-block > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  list-style: none;
  min-height: 32px;
}

.adm-block > summary::-webkit-details-marker {
  display: none;
}

.adm-block > summary::before {
  content: "▸";
  color: var(--muted);
  transition: transform 0.15s;
}

.adm-block[open] > summary::before {
  transform: rotate(90deg);
}

.adm-block > summary h2 {
  font-size: 16px;
}

.adm-block[open] > summary {
  margin-bottom: 10px;
}

.adm-dl {
  margin-top: 0;
}

.adm-kpis {
  margin-bottom: 12px;
}

.adm-help {
  margin: 10px 0;
}

.adm-save {
  margin-top: 10px;
}

.adm-save > summary {
  cursor: pointer;
  color: var(--accent-text);
  font-size: 13px;
}

.adm-json {
  max-height: 50vh;
}

.adm-small td,
.adm-small th {
  font-size: 13px;
}

/* Thao tác: nút thường trước, nút nguy hiểm sau vạch ngăn; Xoá ở khung đỏ cuối khối. */
.adm-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.adm-sep {
  width: 1px;
  height: 24px;
  margin: 0 4px;
  background: var(--axis);
}

.adm-actions .card-sub {
  margin-top: 10px;
}

.adm-danger-zone {
  display: grid;
  gap: 8px;
  justify-items: start;
  margin-top: 16px;
  padding: 12px 14px;
  border: 1px solid var(--critical);
  border-radius: 10px;
  background: var(--critical-bg);
}

.adm-danger-zone h3 {
  margin: 0;
  font-size: 15px;
  color: var(--critical);
}

.adm-dialog .adm-dlg-text {
  display: grid;
  gap: 8px;
  max-height: 40vh;
  overflow: auto;
  font-size: 14px;
  color: var(--ink-2);
}

.adm-dialog input[type="text"],
.adm-dialog input[type="number"],
.adm-dialog select {
  width: 100%;
  min-height: 36px;
  padding: 4px 8px;
  border: 1px solid var(--axis);
  border-radius: 8px;
  background: var(--page);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
}

.adm-inline {
  display: flex;
  gap: 8px;
  align-items: center;
}

.adm-inline input {
  flex: 1;
  min-width: 0;
}

.adm-radios {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin: 0;
  padding: 8px 10px;
  border: 1px solid var(--axis);
  border-radius: 8px;
  font-size: 14px;
}

.adm-radios legend {
  padding: 0 4px;
  font-size: 13px;
  color: var(--muted);
}

/* Cột chữ dài (ghi chú, tên, đối tượng) xuống dòng trong bảng .lb-table (mặc định nowrap) — cột IP / nút Xem không bị đẩy khỏi khung. */
.lb-table td.adm-wrap,
.adm-audit .adm-target {
  min-width: 8rem;
  max-width: 22rem;
  white-space: normal;
  overflow-wrap: anywhere;
}

.adm-audit .adm-target {
  display: inline-block;
}

/* Nhật ký: chi tiết một dòng — hai khối JSON cạnh nhau trên máy tính. */
.adm-cols {
  display: grid;
  gap: 16px;
}

.adm-diff-add td:nth-child(2) {
  color: var(--good-ink);
}

.adm-diff-remove td:nth-child(2) {
  color: var(--critical);
}

@media (min-width: 900px) {
  .adm-cols {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 720px) {
  .adm-sep {
    display: none;
  }

  .adm-filter .trk-field,
  .adm-grow {
    flex-basis: 100%;
  }

  .adm-head h2 {
    font-size: 18px;
  }

  /* Tester M9b-1 L-1: điện thoại không có thanh cuộn ⇒ khối cuộn 40vh giấu mất chữ cuối. Màn hẹp để cả hộp thoại cuộn. */
  .adm-dialog .adm-dlg-text {
    max-height: none;
    overflow: visible;
  }
}

/* Tester M9b-1 L-3: điện thoại xoay ngang (vd 844×390) rộng hơn 720 px nhưng thấp — khối cuộn 40vh chỉ còn ~156 px, che mục 3–4
   của hộp "Xoá tài khoản" (cuộn lồng trong hộp thoại cũng cuộn). Màn thấp: như L-1, chỉ cả hộp thoại cuộn. */
@media (max-height: 600px) {
  .adm-dialog .adm-dlg-text {
    max-height: none;
    overflow: visible;
  }
}

/* ---------- Admin M9b đợt 2 — trang IAP (iap.php) + khối IAP của Tổng quan ---------- */
/* Docs/WebServer/M9B_ADMIN.md §5.2, §7, §11. Dùng lại .kpis / .tile / .data-table .lb-cards / .adm-filter; màu biểu đồ đọc
   --trk-c1..3 (assets/iap.js). Không style="" nội tuyến. */

.iap-banner {
  margin: 0 0 12px;
}

.iap-banner ul {
  margin: 0;
  padding-left: 18px;
}

.iap-banner li + li {
  margin-top: 4px;
}

.iap-ov .iap-banner {
  margin-top: 8px;
}

.iap-ov-sub {
  font-size: 12px;
  font-weight: 400;
  color: var(--muted);
}

.iap-kpis .tile-note a {
  white-space: nowrap;
}

.iap-key {
  overflow-wrap: anywhere;
}

.iap-dim td.iap-key {
  max-width: 320px;
}

.iap-status tr.iap-bad td:first-child {
  border-left: 3px solid var(--critical);
}

.iap-status code {
  font-size: 12px;
}

.iap-diff-warn {
  color: var(--warn-ink);
  font-weight: 600;
}

.iap-diff-bad {
  color: var(--critical);
  font-weight: 700;
}

.iap-full {
  display: inline-block;
}

.iap-full > summary {
  cursor: pointer;
  color: var(--accent-text);
  font-size: 12px;
}

.iap-ref-full {
  user-select: all;
  overflow-wrap: anywhere;
}

.iap-recon-form {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.iap-recon details > summary {
  cursor: pointer;
  color: var(--accent-text);
  white-space: nowrap;
}

@media (max-width: 480px) {
  .iap .trk-chart {
    height: 220px;
  }
}

@media (max-width: 720px) {
  /* Bảng IAP thành thẻ: ô khoá + ô chữ dài chiếm cả hàng, ô số ba cột (một thẻ ≈ 3 hàng thay vì mỗi số một hàng). */
  .iap-grid.lb-cards tbody tr {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-flow: row dense;   /* ô nhỏ lấp chỗ trống trước ô cả hàng — không còn ô số đứng một mình một hàng */
    row-gap: 6px;
  }

  .iap-grid.lb-cards td.iap-span2 {
    grid-column: span 2;
  }

  .iap-grid.lb-cards td.iap-key,
  .iap-grid.lb-cards td.iap-wide {
    grid-column: 1 / -1;
  }

  .iap-grid.lb-cards td.iap-key {
    font-weight: 600;
  }

  .iap-grid.lb-cards td {
    overflow-wrap: anywhere;
  }

  .iap-grid.lb-cards td:empty {
    display: none;
  }
}

/* ---------- Thông báo bản mới M10 (admin/update.php + khối game_update ở config.php — M10_UPDATE.md §5.1–5.2) ---------- */

.cfg-warn-list {
  display: grid;
  gap: 2px;
  margin: 0;
  padding-left: 18px;
}

.cfg-warn-list .cfg-key-hint {
  margin-top: 0;
  font-size: 13px;
}

.cfg-upd-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
}

.upd {
  /* Màu của popup mô phỏng (gần bảng màu dialog trong game), chỉ dùng trong khung xem trước. */
  --upd-panel: #1f4a9c;
  --upd-panel-2: #163576;
  --upd-panel-edge: #f2c14e;
  --upd-title: #ffe27a;
  --upd-text: #ffffff;
  --upd-go: #2f9e44;
  --upd-later: #59616f;
  --upd-bezel: #05070a;
  --upd-sky: #2e5a87;
  --upd-ground: #24452f;
}

.upd-dl dd {
  overflow-wrap: anywhere;
}

.upd-url {
  user-select: all;
  overflow-wrap: anywhere;
}

.upd-warnings {
  margin-top: 12px;
}

.upd-warn-list {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.upd-warn {
  padding: 6px 10px;
  border-left: 4px solid var(--warn-ink);
  border-radius: 6px;
  background: var(--warn-bg);
  color: var(--warn-ink);
  font-size: 13px;
  overflow-wrap: anywhere;
}

.upd-warn-danger {
  border-left-color: var(--critical);
  background: var(--critical-bg);
  color: var(--critical);
}

.upd-draft {
  display: grid;
  gap: 6px;
}

.upd-draft a {
  color: inherit;
  font-weight: 600;
}

.upd-cut {
  margin-bottom: 12px;
}

.upd-modes {
  display: grid;
  gap: 20px 24px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 620px), 1fr));
}

.upd-mode {
  min-width: 0;
  margin: 0;
}

.upd-mode figcaption {
  margin-bottom: 8px;
  font-size: 13px;
  color: var(--ink-2);
}

.upd-frames {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px;
}

.upd-frame {
  position: relative;
  display: grid;
  gap: 6px;
  justify-items: center;
}

.upd-screen {
  container-type: inline-size;
  display: grid;
  place-items: center;
  overflow: hidden;
  border: 8px solid var(--upd-bezel);
  border-radius: 22px;
  background: linear-gradient(180deg, var(--upd-sky), var(--upd-ground));
}

.upd-phone .upd-screen {
  --pw: 90;
  width: 240px;
  aspect-ratio: 9 / 19.5;
}

.upd-ipad .upd-screen {
  --pw: 64;
  width: 340px;
  max-width: calc(100vw - 72px);
  aspect-ratio: 3 / 4;
  border-width: 12px;
  border-radius: 18px;
}

.upd-frame-label {
  font-size: 12px;
  color: var(--muted);
}

/* Cỡ chữ theo bề rộng khung (cqw): ~40 ký tự một dòng vừa bề rộng popup như game (§6.10) — chỉ gần đúng, không phải font game. */
.upd-pop {
  position: relative;
  display: grid;
  gap: 0.7em;
  width: calc(var(--pw) * 1cqw);
  padding: 1.4em 1em 1.1em;
  border: 0.25em solid var(--upd-panel-edge);
  border-radius: 1.2em;
  background: linear-gradient(180deg, var(--upd-panel), var(--upd-panel-2));
  color: var(--upd-text);
  font-size: calc(var(--pw) * 1cqw / 24);
  line-height: 1.3;
  text-align: center;
  box-shadow: 0 0.6em 1.6em rgba(0, 0, 0, 0.45);
}

.upd-pop p {
  margin: 0;
}

.upd-pop-title {
  color: var(--upd-title);
  font-size: 1.45em;
  font-weight: 800;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.upd-pop-notes {
  display: grid;
  text-align: left;
}

.upd-line {
  display: block;
  min-height: 1.3em;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.upd-default {
  opacity: 0.85;
}

.upd-pop-gift,
.upd-pop-amount {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4em;
  font-weight: 700;
}

.upd-pop-gift .gi,
.upd-pop-amount .gi {
  width: 1.6em;
  height: 1.6em;
}

.upd-pop-amount {
  font-size: 2em;
}

.upd-pop-btns {
  display: flex;
  justify-content: center;
  gap: 0.6em;
}

.upd-btn {
  padding: 0.45em 1em;
  border-radius: 0.6em;
  background: var(--upd-later);
  font-weight: 700;
  white-space: nowrap;
}

.upd-btn-go {
  background: var(--upd-go);
}

.upd-x {
  position: absolute;
  top: -0.6em;
  right: -0.6em;
  display: grid;
  place-items: center;
  width: 1.8em;
  height: 1.8em;
  border-radius: 50%;
  background: var(--critical);
  font-weight: 800;
}

.upd-none {
  padding: 12px;
  border: 1px dashed var(--axis);
  border-radius: 8px;
  font-size: 13px;
}

.upd-note {
  margin-top: 14px;
}

.upd-kpis {
  margin-bottom: 12px;
}

@media (min-width: 760px) {
  .upd-kpis {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.upd-small {
  font-size: 18px;
}

.upd-h3 {
  margin: 16px 0 0;
  font-size: 14px;
  color: var(--ink-2);
}

.upd-table tr.upd-current td {
  background: var(--series-wash);
}

/* Màn hẹp: bảng thành thẻ (grid có column-gap) ⇒ tô cả thẻ (tr), không tô từng ô — tô ô để lại khe hở giữa ô (tester M10 r3 TM-1). */
@media (max-width: 720px) {
  .upd-table.lb-cards tr.upd-current {
    background: var(--series-wash);
  }

  .upd-table.lb-cards tr.upd-current td {
    background: none;
  }
}

.upd-online-list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.upd-online-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
}

@media (max-width: 480px) {
  .upd-phone .upd-screen {
    width: min(240px, calc(100vw - 72px));
  }
}

/* Bảng số nhỏ (theo nền tảng, 14 ngày): giữ dạng bảng cả trên điện thoại (5 cột số vừa 358 px), không thành thẻ. */
.upd-compact {
  table-layout: auto;
  font-size: 13px;
}

.upd-compact .num {
  width: auto;
  white-space: nowrap;
}

/* M11 — trang Yêu cầu xoá (delete_requests.php): mỗi thao tác là một <details> mở ra form nhỏ, xếp dọc trong ô Thao tác. */
.dlr-actions {
  min-width: 200px;
}

.dlr-actions details + details {
  margin-top: 6px;
}

.dlr-actions summary {
  list-style: none;
  cursor: pointer;
}

.dlr-actions summary::-webkit-details-marker {
  display: none;
}

.dlr-form {
  margin-top: 8px;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  min-width: 240px;
}

/* .adm-filter cho ô 150 px theo chiều chính — form dọc thì đó là chiều cao: bỏ. */
.dlr-form .trk-field {
  flex: none;
}

.dlr-table td.adm-wrap {
  min-width: 160px;
}

/* Nút "Đã trả lời" trong ô Trả lời (form một nút, không khung). */
.dlr-reply {
  margin: 0;
}

/* ---------- M12c — trang BXH level (levels.php — Docs/WebServer/M12_LEVEL_LEADERBOARD.md §5) ---------- */
/* Dùng lại .card / .kpis .trk-kpis / .tile / .data-table .lb-table .lb-cards (≤ 720 px thành thẻ) / .adm-filter / .cfg-dialog; màu biểu
   đồ đọc --trk-c1 / --trk-c2 (assets/levels.js). Không style="" nội tuyến (CSP style-src 'self'). */

.lvl-head {
  flex-wrap: wrap;
  gap: 8px;
}

.lvl-past {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
}

.lvl-sub {
  margin: 14px 0 6px;
  font-size: 14px;
}

.lvl-kpis .tile-note strong {
  color: var(--warn-ink);
}

.lvl-table .lvl-rank {
  width: 72px;
  white-space: nowrap;
}

.lvl-table .lvl-value,
.lvl-at {
  white-space: nowrap;
}

.lvl-detail,
.lvl-why,
.lvl-raw,
.lvl-frank {
  font-size: 12px;
}

.lvl-detail {
  overflow-wrap: anywhere;
}

.lvl-acts {
  display: inline-flex;
  flex-wrap: nowrap;
  gap: 4px;
}

.lvl-hidden-final .lb-pname {
  text-decoration: line-through;
}

.lvl-q td {
  font-weight: 600;
}

.lvl-dist-table,
.lvl-hist-table {
  max-width: 560px;
}

.lvl-sus-list {
  display: grid;
  gap: 4px;
  margin: 0;
  padding-left: 18px;
}

/* Tên (có thể RTL) và mã người chơi là hai đoạn bidi riêng: chữ số đầu mã (42HA9MH1) không bị kéo sang trái tên Ả Rập (W2). */
.lvl-table .lb-pname,
.lvl-table .lb-code,
.lvl-player-head .lb-pname,
.lvl-player-head .lb-code {
  unicode-bidi: isolate;
}

/* .lb-table td mặc định nowrap: ô dài (nơi vào top, nghi vấn) xuống dòng để cột Thao tác không bị đẩy khỏi khung ở desktop / iPad. */
.lvl-table td.lvl-wide,
.lvl-table td.lvl-sus {
  min-width: 10rem;
  max-width: 22rem;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Tab Soát (9–10 cột): tiêu đề cột và ô tín hiệu (heartbeat, tuổi · IAP) xuống dòng, ô nghi vấn hẹp lại — bảng vừa khung ở desktop
   1440 (tester M12c vòng 2: rộng hơn khung 153–487 px, cột "Nghi vấn gần nhất" bị che mà không có gợi ý cuộn). */
.lvl-review th {
  white-space: normal;
  vertical-align: bottom;
}

.lvl-review td.lvl-name {
  min-width: 8rem;
  white-space: normal;
}

.lvl-review td.lvl-wrap {
  min-width: 6.5rem;
  white-space: normal;
}

.lvl-review td.lvl-sus,
.lvl-review td.lvl-wide {
  min-width: 8rem;
  max-width: 13rem;
}

/* levels.js bật khi bảng rộng hơn khung ở mọi cỡ ≥ 721 px (≤ 720 px bảng thành thẻ — .lb-swipe-wide ẩn). */
.lvl-swipe.lvl-swipe-on {
  display: block;
}

/* Gợi ý vuốt ngang cả ở iPad dọc (761–1024 px) — bảng BXH level nhiều cột hơn bảng BXH sự kiện. */
@media (min-width: 721px) and (max-width: 1024px) {
  .lvl-swipe {
    display: block;
  }
}

@media (max-width: 480px) {
  .lvl .lvl-chart {
    height: 220px;
  }
}

@media (max-width: 720px) {
  /* Bảng BXH level thành thẻ: | hạng | tên (2 cột)        |
                               | nước | giá trị | đạt lúc   |
                               | trạng thái / nghi vấn / thao tác: cả hàng | */
  .lvl-table.lb-cards tbody tr {
    grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr);
    grid-auto-flow: row dense;
    row-gap: 6px;
  }

  .lvl-table.lb-cards td.lvl-rank {
    width: auto;
    font-weight: 700;
  }

  .lvl-table.lb-cards td.lvl-name {
    grid-column: 2 / -1;
    font-weight: 600;
  }

  /* Tab Soát / lịch sử kỳ của một người: không có cột hạng ⇒ hai cột đều nhau, ô dài chiếm cả hàng. */
  .lvl-review.lb-cards tbody tr,
  .lvl-pp.lb-cards tbody tr {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .lvl-review.lb-cards td.lvl-name,
  .lvl-review.lb-cards td.lvl-wide,
  .lvl-pp.lb-cards td.lvl-key,
  .lvl-table.lb-cards td.lvl-state,
  .lvl-table.lb-cards td.lvl-sus,
  .lvl-table.lb-cards td.lvl-act {
    grid-column: 1 / -1;
  }

  .lvl-table.lb-cards td {
    overflow-wrap: anywhere;
  }

  .lvl-table.lb-cards td.lvl-act:empty {
    display: none;
  }

  .lvl-acts {
    flex-wrap: wrap;
  }
}
