:root {
  --bg: #16171a;
  --bg-soft: #1e2024;
  --bg-card: #24262b;
  --line: #33363d;
  /* Warna scrollbar: gelap seperti latar, batangnya sedikit lebih terang dari garis
     supaya terlihat tanpa pernah jadi hal paling mencolok di layar. */
  --scroll-track: #191a1e;
  --scroll-thumb: #3a3e46;
  --scroll-thumb-hover: #4c515b;
  --text: #e8e9ec;
  --muted: #9aa0aa;
  --accent: #7fa650;
  --accent-dark: #6b8f42;
  --danger: #d15b4a;
  --warn: #e0a33e;
  --info: #5b8fd1;
  --light-sq: #ebecd0;
  --dark-sq: #779556;
  /* Sorotan langkah terakhir dan petak terpilih. Ikut tema, karena kontrasnya
     bergantung pada warna yang disorot: kuning di atas petak yang sudah kuning
     nyaris tidak terlihat. */
  --hl-last: rgba(255, 235, 59, .28);
  --hl-sel: rgba(255, 235, 59, .45);
  --radius: 12px;
  --shadow: 0 6px 24px rgba(0,0,0,.35);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; overflow-x: hidden; }
body {
  background: var(--bg);
  color: var(--text);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
  min-height: 100vh;
}
a { color: var(--accent); text-decoration: none; }
@media (hover: hover) { a:hover { text-decoration: underline; } }

/* ---------- layout ---------- */
.topbar {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 16px; background: var(--bg-soft);
  border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 40;
}
.topbar .brand { font-weight: 700; font-size: 18px; color: var(--text); display: flex; align-items: center; gap: 8px; }
/* The mark is the two pieces the site is about, cut from the same set the board uses:
   knight in front, king half-tucked behind it, so they read as one shape at 26px. */
.topbar .brand span.logo { display: flex; align-items: center; }
.topbar .brand span.logo img { width: 26px; height: 26px; display: block; }
.topbar .brand span.logo img + img { margin-left: -12px; }
.topbar nav { display: flex; gap: 4px; flex: 1; overflow-x: auto; scrollbar-width: none; }
.topbar nav::-webkit-scrollbar { display: none; }
.topbar nav a {
  padding: 6px 12px; border-radius: 8px; color: var(--muted); white-space: nowrap; font-weight: 500;
}
.topbar nav a.active { background: var(--bg-card); color: var(--text); text-decoration: none; }
@media (hover: hover) {
  .topbar nav a:hover { background: var(--bg-card); color: var(--text); text-decoration: none; }
}
.topbar nav a .ic { display: none; }
.topbar .who { display: flex; align-items: center; gap: 8px; white-space: nowrap; }

/* On a wide screen the groups are invisible scaffolding: `display: contents` drops the
   wrappers so the links lay out in one row exactly as they always did. */
.nav-group { display: contents; }
.nav-group-title, .nav-head, .nav-foot, .nav-toggle, .nav-backdrop, .tabbar { display: none; }

/* ---------- phones: a drawer instead of a sideways-scrolling row ----------------
   Ten links in a row on a 390px screen meant a menu nobody could see. Below this
   width the bar keeps only the brand and a button; the links move into a grouped
   drawer, and the five most-used ones sit in a thumb bar along the bottom.        */
@media (max-width: 900px) {
  /* The drawer is a child of the header, and a positioned ancestor with a z-index
     starts its own stacking context — so the drawer's z-index was being compared
     against its siblings inside the header, not against a backdrop appended to the
     body. The backdrop won, dimmed the menu, and swallowed every tap: touching a link
     hit the backdrop, which closes the drawer, so the menu vanished and nothing
     navigated. Both now live inside the header and are ordered against each other
     (backdrop 1, drawer 2), while the header as a whole sits above the page. */
  .topbar { padding: 10px 14px; gap: 10px; z-index: 60; }
  .topbar .brand { flex: 1; font-size: 17px; }
  .topbar .who { display: none; }

  .nav-toggle {
    display: block; background: var(--bg-card); color: var(--text); border: 1px solid var(--line);
    font-size: 19px; line-height: 1; padding: 7px 12px; border-radius: 10px;
  }

  .topbar nav.drawer {
    position: fixed; top: 0; right: 0; bottom: 0; width: min(82vw, 320px);
    flex-direction: column; gap: 0; overflow-y: auto; z-index: 2;
    background: var(--bg-soft); border-left: 1px solid var(--line);
    padding: 0 0 calc(76px + env(safe-area-inset-bottom)); transform: translateX(102%);
    transition: transform .22s ease;
    box-shadow: -12px 0 32px rgba(0,0,0,.4);
    /* Parked off-canvas is not enough on its own: an invisible panel still swallows
       taps meant for the page behind it, and on iOS it can widen the viewport. */
    visibility: hidden; pointer-events: none;
  }
  body.nav-open .topbar nav.drawer { transform: translateX(0); visibility: visible; pointer-events: auto; }

  .nav-backdrop {
    display: block; position: fixed; inset: 0; z-index: 1; background: rgba(8,9,12,.6);
    opacity: 0; pointer-events: none; transition: opacity .22s ease;
  }
  body.nav-open .nav-backdrop { opacity: 1; pointer-events: auto; }
  body.nav-open { overflow: hidden; }

  /* Everything below belongs to the drawer the script builds. Scoped to `.drawer`
     so a page rendered by an older cached script keeps the plain menu instead of a
     half-styled one. */
  .topbar nav.drawer .nav-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 16px; border-bottom: 1px solid var(--line); font-weight: 700;
    position: sticky; top: 0; background: var(--bg-soft); z-index: 1;
  }
  .nav-close { background: none; border: 0; color: var(--muted); font-size: 17px; padding: 4px 8px; }

  .topbar nav.drawer .nav-group { display: block; padding: 10px 10px 4px; }
  .topbar nav.drawer .nav-group + .nav-group { border-top: 1px solid var(--line); }
  .topbar nav.drawer .nav-group-title {
    display: block; padding: 4px 10px 8px; font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .07em; color: var(--muted);
  }
  .topbar nav.drawer a {
    display: flex; align-items: center; gap: 11px; padding: 11px 12px;
    border-radius: 10px; font-size: 15px; font-weight: 600; color: var(--text);
  }
  .topbar nav.drawer a .ic { display: inline-block; font-size: 18px; width: 24px; text-align: center; }
  .topbar nav.drawer a.active {
    background: linear-gradient(90deg, rgba(127,166,80,.22), transparent);
    color: var(--accent); box-shadow: inset 3px 0 0 var(--accent);
  }
  .topbar nav.drawer .nav-foot {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 14px 16px; margin-top: 8px; border-top: 1px solid var(--line); flex-wrap: wrap;
  }

  .tabbar {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 45;
    background: var(--bg-soft); border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .tabbar a {
    flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: 8px 2px; font-size: 10.5px; font-weight: 600; color: var(--muted);
  }
  .tabbar a .ic { font-size: 19px; line-height: 1; }
  .tabbar a.active { color: var(--accent); }
  .tabbar a { text-decoration: none; }
  /* The thumb bar floats over the page, so the page has to end above it. */
  body .container { padding-bottom: 86px; }
}

.container { max-width: 1180px; margin: 0 auto; padding: 18px 16px 60px; }

.grid { display: grid; gap: 16px; }
.grid.cards { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.play-layout { display: grid; gap: 18px; grid-template-columns: minmax(320px, 1fr) minmax(280px, 380px); align-items: start; }
@media (max-width: 900px) { .play-layout { grid-template-columns: 1fr; } }

.card {
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px; box-shadow: var(--shadow);
}
.card h2, .card h3 { margin: 0 0 10px; font-size: 17px; }
.card p.hint { color: var(--muted); margin: 4px 0 12px; font-size: 13px; }

h1 { font-size: 24px; margin: 0 0 4px; }
.subtitle { color: var(--muted); margin: 0 0 18px; }

/* ---------- controls ---------- */
button, .btn {
  font: inherit; font-weight: 600; cursor: pointer;
  background: var(--accent); color: #10240a; border: none;
  padding: 10px 14px; border-radius: 9px; min-height: 40px;
}
button:hover, .btn:hover { background: var(--accent-dark); text-decoration: none; }
button:disabled { opacity: .5; cursor: not-allowed; }
button.ghost, .btn.ghost { background: var(--bg-soft); color: var(--text); border: 1px solid var(--line); }
button.ghost:hover { background: #2c2f35; }
button.danger { background: var(--danger); color: #fff; }
button.small { padding: 6px 10px; min-height: 32px; font-size: 13px; }
.row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.row.tight { gap: 4px; }
.spacer { flex: 1; }

input, select, textarea {
  font: inherit; background: var(--bg-soft); color: var(--text);
  border: 1px solid var(--line); border-radius: 9px; padding: 10px 12px; width: 100%;
}
label { display: block; font-size: 13px; color: var(--muted); margin: 10px 0 4px; }
textarea { min-height: 110px; resize: vertical; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13px; }

.badge {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  font-size: 12px; font-weight: 700; background: var(--bg-soft); color: var(--muted); border: 1px solid var(--line);
}
.badge.standard { color: var(--muted); }
.badge.premium { color: #f0c674; border-color: #6b5a2a; background: #3a3016; }
.badge.admin { color: #8fd1e6; border-color: #2a5a6b; background: #16303a; }

.alert { padding: 10px 12px; border-radius: 9px; margin: 10px 0; font-size: 14px; }
.alert.error { background: #3a1e1a; color: #ffb4a6; border: 1px solid #6b2f26; }
.alert.info { background: #16303a; color: #a9d8ea; border: 1px solid #2a5a6b; }
.alert.ok { background: #1e3319; color: #b6e39a; border: 1px solid #3d6b2f; }

/* ---------- evaluation bar + opening name ---------- */
.eval-head { max-width: 620px; margin: 0 auto 8px; }
.opening {
  font-size: 13px; font-weight: 600; line-height: 1.35; min-height: 18px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.opening .eco {
  font-weight: 700; font-size: 11px; color: var(--accent);
  background: rgba(127,166,80,.14); border-radius: 4px; padding: 1px 5px; margin-right: 6px;
}
.eval-row { display: flex; align-items: center; gap: 10px; margin-top: 7px; }
/* Scoped under .eval-head: analysis and explore already own a plain `.eval-bar`
   further down this file, and an unscoped rule here would lose to it. */
.eval-head .eval-bar {
  position: relative; flex: 1; width: auto; height: 12px; border-radius: 6px; overflow: hidden;
  background: #2b2b31; box-shadow: inset 0 0 0 1px var(--line);
}
/* White's share grows from the left; the rest of the track is Black's. */
.eval-head .eval-bar .fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 50%;
  background: linear-gradient(180deg, #ffffff, #dcdcd2);
  transition: width .45s cubic-bezier(.4, 0, .2, 1);
}
.eval-head .eval-bar .mid {
  position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; height: auto;
  background: rgba(154,160,170,.5);
}
.eval-head .eval-num { font-variant-numeric: tabular-nums; font-weight: 700; min-width: 56px; text-align: right; }
.eval-head .eval-num.mate { color: var(--warn); }
.eval-head .eval-note { font-size: 12px; color: var(--muted); min-width: 104px; }

@media (max-width: 420px) {
  .eval-head .eval-note { display: none; }
}

/* ---------- board ---------- */
.board-wrap { width: 100%; max-width: 620px; margin: 0 auto; }
.board {
  position: relative; width: 100%; aspect-ratio: 1 / 1;
  display: grid; grid-template-columns: repeat(8, 1fr); grid-template-rows: repeat(8, 1fr);
  border-radius: 8px; overflow: hidden; touch-action: none; user-select: none;
  container-type: inline-size;
  box-shadow: var(--shadow);
}
.sq { position: relative; display: flex; align-items: center; justify-content: center; }
/* Tema papan kedua. Dipasang sebagai atribut pada <html> supaya seluruh papan di
   aplikasi ikut — bermain, Analysis, Explore, dan pratinjau di halaman Akun. */
:root[data-board="abu"] {
  --light-sq: #eef0f1;
  --dark-sq: #8e989f;
}
:root[data-board="coklat"] {
  --light-sq: #f0d9b5;
  --dark-sq: #b58863;
  /* Papan kayu sudah hangat dan kekuningan sejak awal, jadi kuning tipis di atasnya
     hampir tidak berubah apa-apa. Yang dipakai di sini kuning yang lebih pekat —
     bukan hijau atau biru, karena keduanya membuat papan klasik ini berhenti terlihat
     seperti kayu. */
  --hl-last: rgba(255, 225, 40, .45);
  --hl-sel: rgba(255, 215, 20, .62);
}
.sq.light { background: var(--light-sq); }
.sq.dark  { background: var(--dark-sq); }
.sq.last  { box-shadow: inset 0 0 0 100px var(--hl-last); }
.sq.sel   { box-shadow: inset 0 0 0 100px var(--hl-sel); }
.sq.check { background: radial-gradient(circle, #ff5f52 0%, #d1382a 70%); }
/* Koordinat memakai warna petak lawannya, jadi ia ikut berganti bersama temanya —
   ditulis mati sebagai hijau, angka-angka ini menjadi tidak terbaca di papan abu. */
.sq .coord { position: absolute; font-size: 10px; font-weight: 700; opacity: .6; color: var(--dark-sq); }
.sq.dark .coord { color: var(--light-sq); }
.sq .coord.file { right: 3px; bottom: 1px; }
.sq .coord.rank { left: 3px; top: 1px; }
/* SVG sprites from /img/pieces — sized to the square, never to a font. */
.piece {
  width: 100%; height: 100%; display: block; cursor: grab; z-index: 2;
  -webkit-user-drag: none;
}
.piece.dragging { opacity: .3; }
.piece.w { filter: drop-shadow(0 1px 2px rgba(0,0,0,.35)); }
.piece.b { filter: drop-shadow(0 1px 2px rgba(0,0,0,.45)); }
.dot {
  position: absolute; width: 28%; height: 28%; border-radius: 50%;
  background: rgba(20,20,20,.28); z-index: 1;
}
.dot.capture {
  width: 92%; height: 92%; background: transparent; border-radius: 50%;
  box-shadow: inset 0 0 0 6px rgba(20,20,20,.25);
}
.board-arrows { position: absolute; inset: 0; pointer-events: none; z-index: 3; }
.drag-ghost {
  position: fixed; pointer-events: none; z-index: 100; transform: translate(-50%, -50%) scale(1.08);
  filter: drop-shadow(0 4px 8px rgba(0,0,0,.45));
}

.promo {
  position: absolute; inset: 0; background: rgba(0,0,0,.6); z-index: 30;
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
.promo button { background: var(--bg-card); color: var(--text); padding: 6px 10px; line-height: 0; }
.promo button .piece { width: 46px; height: 46px; }

/* ---------- game side panel ---------- */
.player-row {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: 9px;
}
.player-row .name { font-weight: 600; }
.player-row .clock {
  margin-left: auto; font-variant-numeric: tabular-nums; font-size: 20px; font-weight: 700;
  padding: 2px 10px; border-radius: 7px; background: var(--bg-card);
}
.player-row .clock.low { background: #4a1f1a; color: #ffb4a6; }
.player-row .clock.active { background: var(--accent); color: #10240a; }
.player-row .dot-status { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
.player-row .dot-status.off { background: var(--danger); }

.moves {
  max-height: 320px; overflow-y: auto; font-variant-numeric: tabular-nums;
  display: grid; grid-template-columns: 34px 1fr 1fr; gap: 2px 6px; align-content: start; font-size: 14px;
}
.moves .num { color: var(--muted); }
.moves .mv { padding: 2px 6px; border-radius: 5px; cursor: pointer; }
@media (hover: hover) { .moves .mv:hover { background: var(--bg-soft); } }
.moves .mv.current { background: var(--accent); color: #10240a; font-weight: 700; }

/* One palette for the whole review: the greens are moves you would play again, the
   yellows and oranges are the ones you would take back, and brilliance and theory get
   colours of their own so they never read as "merely good". */
.label-brilliant { color: #26c2a3; }
.label-great { color: #6f9fe0; }
.label-best, .label-excellent { color: #7fd18a; }
.label-good { color: #a3c96b; }
.label-book { color: #c2a077; }
.label-forced { color: var(--muted); }
.label-inaccuracy { color: #e0c15b; }
.label-mistake { color: #e09a4a; }
.label-missed { color: #ef8a72; }
.label-blunder { color: #e05b4a; }

/* ---------- ulasan permainan: kedua pemain berdampingan ---------- */
.review td, .review th { padding: 5px 8px; border-bottom: 0; }
.review thead th { padding-bottom: 8px; border-bottom: 1px solid var(--line); }
.review tbody th { font-size: 12.5px; text-transform: none; letter-spacing: 0; color: var(--text); font-weight: 600; }
.review td.right, .review td.left { font-weight: 800; font-variant-numeric: tabular-nums; width: 22%; }
.review td.mark { width: 34px; text-align: center; }
.review .acc-row td { padding: 8px; }
.review .acc-row th, .review .total-row th { color: var(--muted); font-weight: 600; }
.review .total-row td { color: var(--muted); font-weight: 600; }
.review .acc {
  display: inline-block; padding: 6px 14px; border-radius: 8px;
  font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums;
}
.review .acc.w { background: #f2f2ee; color: #14160f; }
.review .acc.b { background: #2b2f36; color: #eef1e9; border: 1px solid var(--line); }
.review .ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%;
  font-size: 12px; font-weight: 800; line-height: 1; color: #12140f;
}
.review .ic.brilliant { background: #26c2a3; }
.review .ic.great { background: #6f9fe0; }
.review .ic.best { background: #7fa650; }
.review .ic.excellent { background: #95bb4a; }
.review .ic.good { background: #a3c96b; }
.review .ic.book { background: #c2a077; }
.review .ic.inaccuracy { background: #e8c65c; }
.review .ic.mistake { background: #e8913a; }
.review .ic.missed { background: #ef8a72; }
.review .ic.blunder { background: #e05b4a; }
.review .ic.forced { background: #4a4f57; color: #dfe3ea; }

.eval-bar { position: relative; width: 100%; height: 10px; background: #2b2b2b; border-radius: 6px; overflow: hidden; }
.eval-bar > div { height: 100%; background: #f0f0f0; transition: width .25s; }

table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line); }
th { color: var(--muted); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
/* The colour split hangs under the result it belongs to, so the two read as one
   entry: no rule between them, and the border of the pair sits under the split. */
tr.split td { color: var(--muted); font-size: 12px; padding: 0 10px 8px; }
tr.split + tr th, tr.split + tr td { border-top: 0; }
tr:has(+ tr.split) th, tr:has(+ tr.split) td { border-bottom: 0; padding-bottom: 2px; }
tr.clickable { cursor: pointer; }
@media (hover: hover) { tr.clickable:hover td { background: var(--bg-soft); } }

.list { display: flex; flex-direction: column; gap: 8px; max-height: 60vh; overflow-y: auto; }
.list .item {
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 9px; cursor: pointer; background: var(--bg-soft);
}
@media (hover: hover) { .list .item:hover { border-color: var(--accent); } }
.list .item.active { border-color: var(--accent); background: #232a1d; }
.list .item .meta { color: var(--muted); font-size: 12px; }

.pv { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13px; color: var(--text); }
.mono { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13px; }
.muted { color: var(--muted); }
.right { text-align: right; }
.left { text-align: left; }
.center { text-align: center; }
.hidden { display: none !important; }
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  padding: 6px 10px; border-radius: 999px; background: var(--bg-soft); border: 1px solid var(--line);
  cursor: pointer; font-size: 13px;
}
.chip.active { background: var(--accent); color: #10240a; border-color: var(--accent); font-weight: 700; }

.chat { display: flex; flex-direction: column; gap: 6px; }
.chat .log { max-height: 150px; overflow-y: auto; font-size: 13px; display: flex; flex-direction: column; gap: 4px; }
.chat .log .msg b { color: var(--accent); }

.progress { height: 8px; background: var(--bg-soft); border-radius: 5px; overflow: hidden; }
.progress > div { height: 100%; background: var(--accent); width: 0; transition: width .2s; }

footer.small { color: var(--muted); font-size: 12px; text-align: center; padding: 24px 0; }

/* ---------- statistics ---------- */
.page-title { display: flex; align-items: center; gap: 8px; margin: 18px 0 12px; }
.page-title.small { font-size: 17px; margin-top: 24px; }

.profile-card { display: flex; align-items: center; gap: 14px; }
.profile-card .avatar {
  width: 64px; height: 64px; border-radius: 10px; background: var(--bg-soft);
  display: flex; align-items: center; justify-content: center; flex: none;
}
.profile-card .avatar img { width: 48px; height: 48px; }
.who-name { font-size: 20px; font-weight: 700; display: flex; align-items: center; gap: 8px; }

.range-tabs, .filter-tabs, .adv-tabs { display: flex; gap: 4px; overflow-x: auto; margin: 12px 0; scrollbar-width: none; }
.range-tabs::-webkit-scrollbar, .filter-tabs::-webkit-scrollbar, .adv-tabs::-webkit-scrollbar { display: none; }
.range, .adv {
  flex: none; background: transparent; color: var(--muted); border: 0;
  padding: 7px 13px; border-radius: 8px; font-weight: 600; font-size: 13px; cursor: pointer;
}
.range.active, .adv.active { background: var(--bg-card); color: var(--text); }

.total-card { display: flex; align-items: baseline; gap: 10px; }
.total-num { font-size: 34px; font-weight: 800; line-height: 1; }

.mode-list { display: flex; flex-direction: column; }
.mode-row {
  display: grid; grid-template-columns: 34px 1fr auto auto 14px;
  align-items: center; gap: 12px; padding: 13px 2px; cursor: pointer;
  border-bottom: 1px solid var(--line);
}
.mode-row.static { cursor: default; }
.mode-row:last-child { border-bottom: 0; }
.mode-icon { font-size: 21px; text-align: center; }
.mode-name { font-weight: 600; }
.mode-name .small { font-size: 11px; font-weight: 400; }
.mode-rating { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; }
.mode-row .chev { color: var(--muted); transition: transform .18s; }
.mode-row.open .chev { transform: rotate(90deg); }
.mode-detail { padding: 4px 2px 16px 46px; border-bottom: 1px solid var(--line); }

.delta { font-size: 13px; font-weight: 700; min-width: 68px; text-align: right; }
.delta.up { color: var(--accent); }
.delta.down { color: var(--danger); }
.delta.none { color: var(--muted); font-weight: 500; }

/* Win / draw / loss as one bar — the proportions read faster than three numbers. */
.wdl { display: flex; height: 8px; border-radius: 4px; overflow: hidden; margin-bottom: 6px; }
.wdl .w { background: var(--accent); }
.wdl .d { background: #6b7280; }
.wdl .l { background: var(--danger); }
.wdl-legend { font-size: 12px; }

.kv { display: flex; justify-content: space-between; gap: 12px; padding: 5px 0; border-bottom: 1px solid var(--line); }
.kv:last-child { border-bottom: 0; }
table.mini { margin-top: 10px; font-size: 13px; }
.q-ok { color: var(--accent); } .q-warn { color: var(--warn); } .q-bad { color: var(--danger); }
.eco {
  font-weight: 700; font-size: 11px; color: var(--accent);
  background: rgba(127,166,80,.14); border-radius: 4px; padding: 1px 5px; margin-right: 6px;
}

/* ---------- tournaments ---------- */
.format-picker { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 8px; margin: 10px 0; }
.format {
  text-align: left; background: var(--bg-soft); border: 1px solid var(--line); border-radius: 10px;
  padding: 11px 13px; cursor: pointer; display: flex; flex-direction: column; gap: 4px; color: var(--text);
}
.format.active { border-color: var(--accent); background: rgba(127,166,80,.1); }
.format .muted { font-size: 12px; font-weight: 400; line-height: 1.35; }
.format-note {
  font-size: 13px; color: var(--muted); background: var(--bg-soft);
  border-left: 3px solid var(--accent); border-radius: 0 8px 8px 0; padding: 9px 12px; margin-bottom: 14px;
}
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 0 14px; }

.t-card { display: block; color: var(--text); }
@media (hover: hover) { .t-card:hover { text-decoration: none; border-color: var(--accent); } }
.t-head { display: flex; align-items: center; gap: 10px; justify-content: space-between; }
.pill {
  font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: 99px;
  background: var(--bg-soft); color: var(--muted); white-space: nowrap;
}
.pill.running { background: rgba(127,166,80,.18); color: var(--accent); }
.pill.upcoming { background: rgba(91,143,209,.18); color: var(--info); }
.pill.finished { background: rgba(154,160,170,.16); color: var(--muted); }
.pill.cancelled { background: rgba(209,91,74,.18); color: var(--danger); }

.pairing {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 2px; border-bottom: 1px solid var(--line); flex-wrap: wrap;
}
.pairing:last-child { border-bottom: 0; }
.pairing.mine { background: rgba(127,166,80,.07); border-radius: 6px; padding-left: 8px; padding-right: 8px; }
.small-row { gap: 5px; }
ol.plain { margin: 0; padding-left: 20px; }
tr.me td { background: rgba(127,166,80,.1); }

/* ---------- events ---------- */
.level-card { display: flex; flex-direction: column; gap: 8px; }
.level-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.level-points { font-size: 22px; font-weight: 800; }
.eval-bar.level-bar { position: relative; width: 100%; height: 10px; border-radius: 5px; overflow: hidden; background: #2b2b31; }
.eval-bar.level-bar .fill {
  position: absolute; left: 0; top: 0; bottom: 0;
  background: linear-gradient(90deg, var(--accent-dark), var(--accent)); transition: width .4s ease;
}
.pill.open { background: rgba(91,143,209,.18); color: var(--info); }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
ul.muted { padding-left: 18px; margin: 4px 0; }
ul.muted li { margin-bottom: 4px; }
input.gid { padding: 5px 8px; font-size: 12px; }

/* ---------- leaderboard ---------- */
.podium { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; align-items: end; margin-bottom: 14px; }
.podium .slot {
  background: var(--bg-card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 10px; text-align: center; display: flex; flex-direction: column; gap: 3px;
}
.podium .slot.p1 { border-color: var(--accent); background: rgba(127,166,80,.1); padding: 20px 10px; }
.podium .slot.mine { box-shadow: inset 0 0 0 1px var(--accent); }
.podium .medal { font-size: 22px; line-height: 1; }
.podium .who { font-weight: 700; overflow-wrap: anywhere; }
.podium .pts { font-size: 20px; font-weight: 800; font-variant-numeric: tabular-nums; }
.podium .slot.p1 .pts { font-size: 26px; color: var(--accent); }
@media (max-width: 560px) { .podium { grid-template-columns: 1fr; } .podium .slot.p1 { order: -1; } }

.table-wrap { overflow-x: auto; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td.rank-cell { font-variant-numeric: tabular-nums; white-space: nowrap; }
td.medals { white-space: nowrap; }

/* Where the points came from, as one bar: rank prize, showing up, opening bonus. */
.pt-bar { display: flex; height: 5px; border-radius: 3px; overflow: hidden; background: var(--bg-soft); margin-top: 5px; max-width: 180px; }
.pt-bar .s1 { background: var(--accent); }
.pt-bar .s2 { background: var(--info); }
.pt-bar .s3 { background: var(--warn); }
.pt-legend { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 10px; }
.pt-legend i.sw { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 5px; }
.pt-legend i.s1 { background: var(--accent); }
.pt-legend i.s2 { background: var(--info); }
.pt-legend i.s3 { background: var(--warn); }
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }

/* ---------- leaderboard, the bright version ---------------------------------
   The event ladder has to look like something worth entering, so this page runs
   warmer than the rest of the app: a gradient header, a colour per level, and a
   real podium. The colours carry meaning — each level keeps its hue everywhere it
   appears — so the brightness is doing work rather than just shouting.          */
.lb-hero {
  position: relative; overflow: hidden; border-radius: 16px; padding: 22px 20px; margin-bottom: 14px;
  background: linear-gradient(120deg, #7c3aed 0%, #db2777 45%, #f59e0b 100%);
  color: #fff; box-shadow: 0 10px 30px rgba(219,39,119,.25);
}
.lb-hero h2 { margin: 0 0 4px; font-size: 24px; display: flex; align-items: center; gap: 9px; }
.lb-hero p { margin: 0; opacity: .92; font-size: 14px; }
.lb-hero .sparkle { position: absolute; right: -10px; top: -14px; font-size: 108px; opacity: .17; transform: rotate(-12deg); }
.lb-hero .cta {
  display: inline-block; margin-top: 12px; background: rgba(255,255,255,.18); color: #fff;
  border: 1px solid rgba(255,255,255,.45); padding: 7px 14px; border-radius: 99px; font-weight: 700; font-size: 14px;
}
@media (hover: hover) { .lb-hero .cta:hover { background: rgba(255,255,255,.3); text-decoration: none; } }

.lvl { --c: var(--muted); }
.lvl-beginner     { --c: #34d399; }
.lvl-rookie       { --c: #38bdf8; }
.lvl-challenger   { --c: #fb923c; }
.lvl-intermediate { --c: #c084fc; }
.lvl-master       { --c: #fbbf24; }
.lvl-badge {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 700;
  padding: 3px 9px; border-radius: 99px; white-space: nowrap;
  color: var(--c); background: color-mix(in srgb, var(--c) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--c) 40%, transparent);
}

.podium .slot { position: relative; }
.podium .slot.p1 {
  background: linear-gradient(160deg, rgba(251,191,36,.22), rgba(249,115,22,.10));
  border-color: #fbbf24; box-shadow: 0 8px 24px rgba(251,191,36,.16);
}
.podium .slot.p2 { background: linear-gradient(160deg, rgba(203,213,225,.16), transparent); border-color: #cbd5e1; }
.podium .slot.p3 { background: linear-gradient(160deg, rgba(217,119,6,.16), transparent); border-color: #d97706; }
.podium .slot.p1 .pts { color: #fbbf24; }
.podium .crown { position: absolute; top: -12px; left: 50%; transform: translateX(-50%); font-size: 22px; }

tr.lb-row td { transition: background .15s; }
@media (hover: hover) { tr.lb-row:hover td { background: var(--bg-soft); } }
tr.lb-row.top td { background: rgba(251,191,36,.07); }
.rank-pill {
  display: inline-flex; align-items: center; justify-content: center; min-width: 26px; height: 26px;
  border-radius: 8px; font-weight: 800; font-size: 13px; background: var(--bg-soft); color: var(--muted);
}
.rank-pill.g1 { background: linear-gradient(140deg, #fbbf24, #f59e0b); color: #3a2a05; }
.rank-pill.g2 { background: linear-gradient(140deg, #e2e8f0, #94a3b8); color: #1f2937; }
.rank-pill.g3 { background: linear-gradient(140deg, #f0a868, #c2703a); color: #2b1608; }
.pts-cell { font-size: 16px; font-weight: 800; color: var(--accent); font-variant-numeric: tabular-nums; }
.streak-tag { font-size: 11px; font-weight: 700; color: #fb923c; }
.mine-card {
  background: linear-gradient(120deg, rgba(124,58,237,.18), rgba(56,189,248,.12));
  border: 1px solid rgba(124,58,237,.45);
}
.scope-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.scope-tabs .range { border-radius: 99px; padding: 7px 14px; font-weight: 600; }
.scope-tabs .range.active { background: linear-gradient(120deg, #7c3aed, #db2777); color: #fff; }

/* ---------- area picker ---------- */
.modal-back {
  position: fixed; inset: 0; background: rgba(8,9,12,.72); z-index: 120;
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.modal { width: min(460px, 100%); max-height: 88vh; overflow-y: auto; box-shadow: var(--shadow); }
.loc-row { display: flex; flex-direction: column; gap: 5px; margin-top: 11px; font-size: 13px; font-weight: 600; }
.loc-row select { width: 100%; }
.loc-note { font-size: 12px; color: var(--muted); }

/* ---------- master opponents ---------- */
.master-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 10px; }

/* ---------- lawan bot: pilih lawan dulu, lalu papan ----------------------------
   The opponent picker sits above the board because choosing who to play is the
   first thing anyone does here. On a phone that would be a wall of faces to scroll
   past, so there the grid becomes one swipeable row — the board stays a thumb-flick
   away, and the whole roster is still reachable. */
.opponent-pick { margin-bottom: 14px; }
.opponent-pick .pick-levels { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.opponent-pick .pick-levels .row { margin-top: 10px; }
label.inline { display: inline-block; margin: 0; }
select.narrow { width: auto; min-width: 110px; }

@media (max-width: 900px) {
  .opponent-pick .master-grid {
    display: flex; overflow-x: auto; gap: 8px; padding-bottom: 6px;
    scroll-snap-type: x proximity; scrollbar-width: none;
  }
  .opponent-pick .master-grid::-webkit-scrollbar { display: none; }
  .opponent-pick .master-card { flex: 0 0 128px; scroll-snap-align: start; }
}

/* ---------- scrollbar --------------------------------------------------------
   Scrollbar bawaan peramban di Windows berwarna putih-abu terang: di halaman
   segelap ini ia jadi garis paling mencolok di layar, padahal ia hanya penunjuk
   posisi. Diwarnai ulang mengikuti tema — batang membulat, tanpa garis tepi, dan
   sedikit lebih terang saat disentuh kursor supaya tetap terasa bisa ditarik.

   Dua sintaks yang berbeda dan keduanya perlu: `scrollbar-color` untuk Firefox,
   `::-webkit-scrollbar` untuk Chrome, Edge, dan Safari. */
* { scrollbar-width: thin; scrollbar-color: var(--scroll-thumb) var(--scroll-track); }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--scroll-track); border-radius: 8px; }
::-webkit-scrollbar-thumb {
  background: var(--scroll-thumb); border-radius: 8px;
  border: 2px solid var(--scroll-track);   /* jarak tipis, supaya batangnya tidak menempel di tepi */
}
::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); }
::-webkit-scrollbar-corner { background: var(--scroll-track); }

/* ---------- lawan bot di layar laptop (11-16 inci) -----------------------------
   Papan di kiri, pemilih lawan di kanan — susunan yang diminta ridwanyas (2026-08-23),
   dan yang sama dengan papan catur online mana pun.

   Sebelumnya pemilih lawan membentang selebar halaman di atas papan. Di layar 1366x768
   itu berarti papan mulai pada 870px: seorang pemain membuka halaman permainan dan
   tidak melihat satu petak pun sebelum menggulir. Kartunya juga tidak perlu selebar
   itu — delapan wajah dalam satu baris hanyalah delapan wajah yang jarang diganti. */
@media (min-width: 901px) {
  /* Papan mengikuti tinggi layar, bukan hanya lebar kolomnya. Angka 260px adalah
     bar keunggulan + dua baris pemain + tombol di bawah papan; di layar tinggi
     max-width 620px tetap yang menang. */
  /* Satu lebar untuk seluruh kolom kiri: papan, nama pemain, bar keunggulan, dan
     tombol-tombolnya. Sebelumnya hanya papan yang dibatasi, jadi baris nama
     membentang 751px di atas papan selebar 468px — mata langsung menangkap dua tepi
     yang tidak sejajar, dan itu yang membuat halaman terasa berantakan. */
  /* 700px, bukan 620: di layar 15-16 inci sisa ruangnya memang ada, dan papan yang
     lebih besar adalah alasan orang membuka halaman ini. Yang dikurangi dari tinggi
     layar dipangkas jadi 246px dengan merapatkan bar keunggulan, baris nama, dan
     tombol — bukan dengan membuang satu pun dari mereka. */
  .play-page { --board-w: min(700px, calc(100vh - 256px)); }

  /* Ruang mati di kolom kiri: setiap piksel di sini langsung jadi papan yang lebih besar. */
  .play-page .eval-head { margin-bottom: 6px; }
  .play-page .eval-head .eval-row { margin-top: 4px; }
  .play-page .player-row { padding: 5px 12px; }
  .play-page .board-wrap { margin: 6px auto !important; }
  .play-page .board-actions { margin-top: 8px; }
  .play-page .board-actions button { min-height: 46px; }
  .play-page .board-wrap,
  .play-page .eval-head,
  .play-page .player-row,
  .play-page .board-actions,
  .play-page #themeQuick,
  .play-page #status { max-width: var(--board-w); margin-left: auto; margin-right: auto; }

  /* Kolom kanan menggulir di dalam dirinya sendiri, bukan memanjangkan halaman.
     Tanpa ini tinggi halaman ditentukan oleh kolom yang lebih panjang — dan yang
     lebih panjang adalah daftar lawan, bukan papan; itulah sebabnya tombol di bawah
     papan tetap jatuh di luar layar meski papannya sendiri sudah muat. */
  .play-page .play-side {
    position: sticky; top: 12px;
    max-height: calc(100vh - 84px); overflow-y: auto; padding-right: 2px;
  }

  .play-page .opponent-pick { margin-bottom: 0; }
  /* Wajah dibuat lebih rapat: di kolom selebar 380px, kartu 132px hanya muat dua per
     baris dan sisanya jadi gulungan panjang. */
  .play-page .opponent-pick .master-grid {
    grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 8px;
    max-height: 30vh; overflow-y: auto; padding-right: 2px;
  }
  .play-page .opponent-pick .master-card { padding: 8px 5px 7px; border-radius: 11px; }
  .play-page .opponent-pick .master-card img { width: 42px; height: 42px; }
  .play-page .opponent-pick .master-card .m-name { font-size: 12px; margin-top: 2px; line-height: 1.15; }
  .play-page .opponent-pick .master-card .m-elo { font-size: 12px; }
  /* Tahun Elo dan puncaknya adalah keterangan untuk dibaca sekali, bukan tiap kali
     memilih lawan — di kolom sempit ia menghabiskan tiga baris per kartu. */
  .play-page .opponent-pick .master-card .m-elo-note { display: none; }
  .play-page .opponent-pick .pick-levels .row { flex-wrap: wrap; }
}

/* The three buttons a player reaches for mid-game, directly under the board rather
   than in a card below the move list — on a phone that card was a scroll away. */
.board-actions {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
  max-width: 620px; margin: 10px auto 0;
}
.board-actions button {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 8px 6px; min-height: 52px; font-size: 12.5px; font-weight: 600; line-height: 1.2;
}
.board-actions button .ic { font-size: 17px; line-height: 1; }
#status { max-width: 620px; margin: 0 auto; }
.master-card {
  display: flex; flex-direction: column; align-items: center; gap: 3px; text-align: center;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: 14px;
  padding: 12px 8px 10px; color: var(--text); cursor: pointer; transition: border-color .15s, transform .15s;
}
.master-card img { border-radius: 50%; display: block; }
.master-card .m-name { font-weight: 700; font-size: 14px; margin-top: 4px; }
.master-card .m-elo { font-size: 13px; font-weight: 800; color: var(--warn); font-variant-numeric: tabular-nums; }
.master-card .m-elo-note { font-size: 10.5px; }
.master-card.active { border-color: var(--accent); background: rgba(127,166,80,.12); transform: translateY(-2px); }
@media (hover: hover) { .master-card:hover { border-color: var(--accent); } }

.master-detail {
  margin-top: 12px; padding: 11px 12px; border-radius: 12px;
  background: var(--bg-soft); border: 1px solid var(--line);
}
.master-detail ul { padding-left: 18px; }
.move-source {
  margin-top: 8px; padding: 8px 10px; border-radius: 9px; font-size: 12.5px;
  background: rgba(91,143,209,.12); border-left: 3px solid var(--info); color: var(--text);
}

/* ---------- profile: the page one player sends to another ---------- */
.profile-head { display: flex; flex-direction: column; gap: 14px; }
.profile-head-top { display: flex; align-items: center; gap: 14px; }
.avatar.big { width: 62px; height: 62px; }
.avatar.big img { width: 62px; height: 62px; }
.profile-id { min-width: 0; }
.profile-rating { margin-left: auto; text-align: right; }
.profile-figures {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 10px;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 12px 0;
}
.profile-figures div { display: flex; flex-direction: column; gap: 2px; }
.profile-figures b { font-size: 17px; }

.trophy-strip { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; }
.trophy-strip::-webkit-scrollbar { display: none; }
.trophy-chip {
  flex: none; display: flex; align-items: center; gap: 8px;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px 6px 8px;
}
.trophy-chip span { display: flex; flex-direction: column; font-size: 13px; font-weight: 600; }
.trophy-chip-icon { font-size: 20px; }

/* ---------- badges ---------- */
.badge-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin-bottom: 18px; }
.badge-card {
  background: var(--bg-card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px; display: flex; flex-direction: column; gap: 6px; position: relative; overflow: hidden;
}
.badge-card.earned { border-color: #4a5a34; background: linear-gradient(180deg, #262a20, var(--bg-card)); }
/* Locked badges stay readable: the point of a locked badge is that the player can see
   exactly what it asks for, so only the icon is dimmed, never the text. */
.badge-card.locked .badge-icon { filter: grayscale(1); opacity: .45; }
.badge-icon { font-size: 30px; line-height: 1; }
.badge-name { font-weight: 700; font-size: 14px; }
.badge-desc { line-height: 1.35; }
.badge-foot { font-size: 12px; font-weight: 600; margin-top: auto; }
.badge-reward {
  position: absolute; top: 10px; right: 10px; font-size: 11px; font-weight: 700;
  color: var(--accent); background: rgba(127,166,80,.12); border: 1px solid #4a5a34;
  border-radius: 999px; padding: 2px 7px;
}
.badge-card.pop { animation: badge-pop .45s cubic-bezier(.2,.9,.3,1.4) both; }
@keyframes badge-pop { from { transform: scale(.86); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .badge-card.pop { animation: none; } }

.next-row { display: flex; gap: 12px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--line); }
.next-row:last-of-type { border-bottom: 0; }
.next-icon { font-size: 22px; }
.next-body { flex: 1; display: flex; flex-direction: column; gap: 6px; }

/* ---------- game history ---------- */
.hist-list { display: flex; flex-direction: column; }
.hist-row {
  display: flex; align-items: center; gap: 10px; padding: 10px 0;
  border-bottom: 1px solid var(--line); color: var(--text);
}
.hist-row:last-child { border-bottom: 0; }
a.hist-row:hover { text-decoration: none; background: var(--bg-soft); }
.hist-outcome { flex: none; width: 74px; font-weight: 700; font-size: 13px; }
.hist-vs { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 14px; }
.hist-vs .muted { font-weight: 400; }
.hist-when { flex: none; }
@media (max-width: 520px) {
  .hist-when { display: none; }
  .profile-rating { display: none; }
}

/* ---------- review summary: a count is a way into the moves it counted ---------- */
.review td.pickable { cursor: pointer; text-decoration: underline dotted; text-underline-offset: 3px; }
.review td.pickable:hover { background: var(--bg-soft); }
.review td.picked {
  background: var(--bg-soft); border-radius: 6px;
  box-shadow: inset 0 0 0 1px var(--accent); text-decoration: none;
}
.pick-bar {
  display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: 10px; padding: 6px 8px;
}
.pick-bar button { padding: 4px 10px; font-size: 13px; line-height: 1.2; }
.pick-what { flex: 1; display: flex; flex-direction: column; font-size: 13px; line-height: 1.3; }

/* --- Login: tombol Google & pemisah --------------------------------------- */
/* Warna dan bentuknya mengikuti panduan merek Google: putih, teks abu gelap,
   logo asli. Tombol yang "disesuaikan" dengan tema gelap situs justru membuat
   orang ragu apakah ini benar-benar login Google. */
.btn.google {
  background: #fff;
  color: #1f1f1f;
  border: 1px solid #dadce0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  font-weight: 600;
}
.btn.google:hover { background: #f5f6f7; }
.btn.google svg { width: 18px; height: 18px; flex: none; }

.or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 16px 0;
  color: var(--muted);
  font-size: 13px;
}
.or::before, .or::after { content: ''; flex: 1; height: 1px; background: var(--line); }

.form-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 12px; font-size: 13px; }
.form-foot a { color: var(--muted); }

/* --- Papan peringkat: dua tab + arena bergaya game ------------------------- */
/* Perbaikan kontras: `.chip` mengganti latar tombol tapi tidak warnanya, sehingga
   teksnya mewarisi #10240a milik tombol accent — hitam di atas latar gelap, dan baru
   terbaca saat hover mengembalikan latar terang. Warnanya sekarang dinyatakan. */
.chip { color: var(--text); }
@media (hover: hover) { .chip:hover { background: #2c2f35; } }
.chip.active { color: #10240a; }
@media (hover: hover) { .chip.active:hover { background: var(--accent-dark); } }

.lb-tabs { display: flex; gap: 8px; margin: 16px 0 14px; }
.lb-tab {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--bg-soft); color: var(--text); border: 1px solid var(--line);
  border-radius: 12px; padding: 12px 10px; font-weight: 700; font-size: 14px;
}
@media (hover: hover) { .lb-tab:hover { background: #2c2f35; } }
.lb-tab.active { color: #fff; border-color: transparent; box-shadow: 0 6px 18px rgba(0,0,0,.35); }
.lb-tab.active[data-t="elo"] { background: linear-gradient(120deg, #2563eb, #06b6d4); }
.lb-tab.active[data-t="point"] { background: linear-gradient(120deg, #7c3aed, #db2777); }
@media (hover: hover) {
  .lb-tab.active[data-t="elo"]:hover { background: linear-gradient(120deg, #1d4ed8, #0891b2); }
  .lb-tab.active[data-t="point"]:hover { background: linear-gradient(120deg, #6d28d9, #be185d); }
}

/* Arena: panel gelap berlapis, tempat papan point berdiri. Semua hiasan hidup di
   dalam ::before/::after dan elemen .deco yang tidak menangkap sentuhan, jadi
   ornamen tidak pernah menghalangi baris yang bisa diklik. */
.arena {
  position: relative; overflow: hidden; border-radius: 16px; padding: 16px 14px;
  background:
    radial-gradient(120% 90% at 8% -10%, rgba(124,58,237,.38), transparent 60%),
    radial-gradient(100% 80% at 100% 0%, rgba(6,182,212,.22), transparent 55%),
    linear-gradient(165deg, #1b2044, #141733 55%, #10121f);
  border: 1px solid rgba(148,163,255,.28);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06), var(--shadow);
}
/* Faset diagonal tipis — yang membuat latar terasa "panel game", bukan kotak polos. */
.arena::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(115deg, rgba(255,255,255,.035) 0 2px, transparent 2px 24px);
  mask-image: linear-gradient(180deg, #000, transparent 75%);
}
.arena > * { position: relative; z-index: 1; }
.arena .deco {
  position: absolute; pointer-events: none; user-select: none; z-index: 0;
  opacity: .07; filter: drop-shadow(0 6px 18px rgba(0,0,0,.6));
}
.arena .deco img { display: block; width: 100%; height: 100%; }
.arena-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.arena-head h3 { margin: 0; font-size: 16px; letter-spacing: .3px; }
.arena-head .count { color: #a5b4fc; font-size: 12px; font-weight: 700; }

.arena-row {
  display: grid; grid-template-columns: 44px 46px minmax(0, 1fr) auto; gap: 10px;
  align-items: center; padding: 9px 12px; margin-bottom: 8px; border-radius: 12px;
  background: rgba(255,255,255,.035); border: 1px solid rgba(255,255,255,.07);
  transition: transform .12s, background .12s;
}
@media (hover: hover) { .arena-row:hover { background: rgba(255,255,255,.08); transform: translateX(2px); } }
.arena-row.top1 {
  background: linear-gradient(90deg, rgba(251,191,36,.26), rgba(251,191,36,.05) 70%);
  border-color: rgba(251,191,36,.5);
}
.arena-row.top2 { background: linear-gradient(90deg, rgba(226,232,240,.2), rgba(226,232,240,.04) 70%); border-color: rgba(203,213,225,.45); }
.arena-row.top3 { background: linear-gradient(90deg, rgba(217,119,6,.22), rgba(217,119,6,.04) 70%); border-color: rgba(217,119,6,.45); }
.arena-row.me { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }

/* Medali segi enam, mengikuti bentuk lencana peringkat di papan game. */
.rank-medal {
  width: 38px; height: 42px; display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 15px; color: #cbd5e1;
  clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
  background: rgba(255,255,255,.07);
}
.rank-medal.g1 { background: linear-gradient(160deg, #fde68a, #f59e0b 60%, #b45309); color: #3a2a05; }
.rank-medal.g2 { background: linear-gradient(160deg, #f8fafc, #cbd5e1 55%, #94a3b8); color: #1f2937; }
.rank-medal.g3 { background: linear-gradient(160deg, #fcd9b0, #d97706 60%, #92400e); color: #2b1608; }

.arena-avatar {
  width: 44px; height: 44px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 32% 26%, #46528f, #171a33 70%);
  border: 2px solid rgba(255,255,255,.22); flex: none;
}
.arena-avatar img { width: 28px; height: 28px; }
.arena-row.top1 .arena-avatar { border-color: #fbbf24; box-shadow: 0 0 14px rgba(251,191,36,.45); }
.arena-row.top2 .arena-avatar { border-color: #e2e8f0; }
.arena-row.top3 .arena-avatar { border-color: #f0a868; }

.arena-who { min-width: 0; }
.arena-name { font-weight: 700; font-size: 15px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.arena-name a { color: #e8ecff; }
.arena-sub { color: #9aa6d8; font-size: 11.5px; margin-top: 2px; display: flex; gap: 8px; flex-wrap: wrap; }
.arena-score { text-align: right; }
.arena-pts { font-size: 20px; font-weight: 800; color: #ffd469; line-height: 1.1; font-variant-numeric: tabular-nums; }
.arena-row.top1 .arena-pts { text-shadow: 0 0 16px rgba(251,191,36,.5); }
.arena-unit { font-size: 11px; color: #9aa6d8; font-weight: 600; }

/* Papan Elo memakai kerangka yang sama dengan warna yang lebih tenang: yang dilihat
   di sini adalah kekuatan bermain, bukan perayaan juara. */
.arena.calm {
  background:
    radial-gradient(110% 80% at 10% -10%, rgba(37,99,235,.30), transparent 60%),
    linear-gradient(165deg, #16213a, #121a2c 60%, #0f1220);
  border-color: rgba(96,165,250,.26);
}
.arena.calm .arena-pts { color: #7dd3fc; }
.arena.calm .arena-row.top1 { background: linear-gradient(90deg, rgba(56,189,248,.22), rgba(56,189,248,.04) 70%); border-color: rgba(56,189,248,.5); }
.arena.calm .arena-row.top1 .arena-avatar { border-color: #38bdf8; box-shadow: 0 0 14px rgba(56,189,248,.4); }
.arena.calm .arena-row.top1 .arena-pts { text-shadow: 0 0 16px rgba(56,189,248,.45); }

.wl { display: inline-flex; gap: 6px; font-variant-numeric: tabular-nums; }
.wl .w { color: #86efac; } .wl .d { color: #cbd5e1; } .wl .l { color: #fca5a5; }

@media (max-width: 560px) {
  .arena-row { grid-template-columns: 34px 38px minmax(0, 1fr) auto; gap: 8px; padding: 8px 9px; }
  .rank-medal { width: 30px; height: 34px; font-size: 13px; }
  .arena-avatar { width: 38px; height: 38px; } .arena-avatar img { width: 24px; height: 24px; }
  .arena-pts { font-size: 17px; }
  .lb-tab { font-size: 13px; padding: 11px 8px; }
}

.arena-empty { text-align: center; padding: 26px 14px 30px; }
.arena-empty .big { font-size: 44px; opacity: .5; margin-bottom: 6px; }
.arena-empty p { color: #a8b2dc; margin: 0 0 14px; }

/* Bar rincian point ikut menjadi anak flex di dalam .arena-sub — tanpa basis penuh
   ia berdesakan di baris yang sama dan menyusut sampai tidak terbaca. */
.arena-sub .pt-bar { flex: 0 0 100%; max-width: 180px; margin-top: 4px; background: rgba(255,255,255,.08); }

/* Kepala halaman peringkat versi rating: biru, sewarna dengan arena tab itu. */
.lb-hero.elo {
  background: linear-gradient(120deg, #1d4ed8 0%, #0891b2 55%, #22d3ee 100%);
  box-shadow: 0 10px 30px rgba(8,145,178,.25);
}

/* --- Lockup merek untuk halaman tanpa topbar ------------------------------- */
/* Halaman masuk/daftar/pemulihan tidak memasang topbar, jadi merek dipasang
   sendiri di sana — bidak yang sama persis dengan topbar (raja di belakang,
   kuda di depan) supaya orang melihat logo yang sama sejak layar pertama. */
.brand-mark {
  display: flex; align-items: center; justify-content: center; gap: 9px;
  font-size: 22px; font-weight: 800; letter-spacing: .2px; color: var(--text);
  margin: 6px 0 14px;
}
.brand-mark .logo { display: flex; align-items: center; }
.brand-mark .logo img { width: 38px; height: 38px; display: block; }
.brand-mark .logo img + img { margin-left: -17px; }

/* Versi sebaris, untuk dipakai di tengah kalimat. */
.brand-inline { display: inline-flex; align-items: center; vertical-align: -6px; }
.brand-inline img { width: 28px; height: 28px; display: block; }
.brand-inline img + img { margin-left: -13px; }

/* --- Poster event: spanduk besar di kepala halaman Event ------------------- */
/* Bentuknya meniru poster event game: sinar emas menyebar dari satu titik, bidak
   sebagai "bintang" di depannya, lalu blok judul yang berdiri sendiri. Semua lapisan
   hiasan memakai pointer-events:none supaya tidak ada tombol yang tertutup. */
.event-poster {
  position: relative; overflow: hidden; border-radius: 18px; margin: 14px 0 16px;
  min-height: 330px; display: flex; align-items: flex-end; justify-content: center;
  background: linear-gradient(180deg, #2b2417 0%, #1c1a15 45%, #141414 100%);
  border: 1px solid rgba(212,175,55,.35);
  box-shadow: 0 14px 40px rgba(0,0,0,.45);
  isolation: isolate;
}
/* Sinar: repeating-conic-gradient memberi kipas yang rata tanpa satu pun poligon
   ditulis tangan. Dua lapis dengan sudut berbeda supaya tidak terlihat mekanis. */
.event-poster .rays, .event-poster .rays2 {
  position: absolute; inset: -55% -25% -10% -25%; pointer-events: none; z-index: 0;
  mask-image: radial-gradient(60% 55% at 50% 30%, #000 35%, transparent 78%);
}
.event-poster .rays {
  background: repeating-conic-gradient(from 0deg at 50% 30%,
    rgba(212,175,55,.55) 0deg 6deg, transparent 6deg 21deg);
}
.event-poster .rays2 {
  background: repeating-conic-gradient(from 9deg at 50% 30%,
    rgba(255,214,102,.28) 0deg 3deg, transparent 3deg 27deg);
}
.event-poster .glow {
  position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background: radial-gradient(46% 38% at 50% 30%, rgba(255,206,84,.35), transparent 70%);
}

/* Bidak putih dijadikan emas lewat filter, bukan berkas gambar baru: satu set bidak
   tetap satu sumber kebenaran, dan warnanya bisa disetel tanpa render ulang. */
.event-poster .pieces { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.event-poster .pieces img {
  position: absolute; filter: sepia(.9) saturate(3.6) hue-rotate(-10deg) brightness(.98)
    drop-shadow(0 14px 26px rgba(0,0,0,.6));
}
.event-poster .pc-king   { width: 148px; left: 50%; top: 26px; transform: translateX(-50%); }
.event-poster .pc-knight { width: 122px; left: 15%; top: 66px; transform: rotate(-12deg); }
.event-poster .pc-queen  { width: 122px; right: 14%; top: 62px; transform: rotate(11deg); }
.event-poster .pc-rook   { width: 84px;  left: 3%;  bottom: 8px; transform: rotate(8deg); opacity: .55; }
.event-poster .pc-pawn   { width: 74px;  right: 4%; bottom: 4px; transform: rotate(-9deg); opacity: .55; }

.event-poster .confetti { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.event-poster .confetti i {
  position: absolute; width: 7px; height: 11px; border-radius: 2px; opacity: .75;
  background: #f5d26b;
}

.event-poster .copy {
  position: relative; z-index: 2; text-align: center; padding: 0 18px 22px;
  width: 100%;
  background: linear-gradient(180deg, transparent, rgba(10,10,10,.82) 42%);
}
.poster-badge {
  display: inline-flex; align-items: center; gap: 7px; margin-bottom: 10px;
  padding: 6px 16px; border-radius: 99px; font-weight: 800; font-size: 12.5px; letter-spacing: 1.4px;
  color: #2a1e00; background: linear-gradient(120deg, #ffe08a, #d4af37 60%, #b8860b);
  box-shadow: 0 6px 18px rgba(212,175,55,.35);
}
@keyframes posterPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.045); } }
@media (prefers-reduced-motion: no-preference) { .poster-badge { animation: posterPulse 2.4s ease-in-out infinite; } }

.poster-brand {
  font-size: 12.5px; font-weight: 800; letter-spacing: 4px; color: #e7d9a8; opacity: .9;
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
.poster-brand img { width: 20px; height: 20px; }
.poster-title {
  margin: 2px 0 0; font-size: clamp(30px, 8.5vw, 52px); line-height: 1.02; font-weight: 900;
  letter-spacing: 1px; text-transform: uppercase;
  background: linear-gradient(180deg, #fff8e1 8%, #ffd86b 45%, #b8860b 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  text-shadow: 0 6px 26px rgba(212,175,55,.25);
}
.poster-year { font-size: 15px; font-weight: 700; letter-spacing: 8px; color: #d9c68c; margin-top: 2px; }
.poster-period {
  margin-top: 12px; display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: center;
  font-size: 13.5px; font-weight: 800; letter-spacing: 1.2px; color: #fff;
  border-top: 1px solid rgba(212,175,55,.45); border-bottom: 1px solid rgba(212,175,55,.45);
  padding: 7px 14px;
}
.poster-cta { margin-top: 14px; display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
.poster-note { margin: 10px 0 0; font-size: 12px; color: #b9b09a; }

@media (max-width: 560px) {
  .event-poster { min-height: 280px; border-radius: 14px; }
  .event-poster .pc-king { width: 108px; top: 22px; }
  .event-poster .pc-knight { width: 88px; left: 6%; top: 62px; }
  .event-poster .pc-queen { width: 88px; right: 5%; top: 58px; }
  .event-poster .pc-rook, .event-poster .pc-pawn { display: none; }
  .poster-year { letter-spacing: 6px; }
}

/* --- Top bar: scrollbar tipis saat menu tidak muat ------------------------- */
/* Di laptop 14 inci deretan menu lebih lebar dari barnya, dan menu terakhir
   ("Profil") terpotong tanpa tanda apa pun — barisnya memang bisa digeser, tapi
   scrollbar-nya disembunyikan sehingga tidak ada yang memberi tahu. Di layar lebar
   scrollbar-nya sekarang ditampilkan setipis mungkin; mode drawer (HP) tetap tanpa
   scrollbar karena di sana menunya sudah jadi daftar vertikal penuh. */
@media (min-width: 901px) {
  .topbar nav {
    scrollbar-width: thin;
    scrollbar-color: rgba(232,233,236,.26) transparent;
    padding-bottom: 3px;
    scroll-behavior: smooth;
    overscroll-behavior-x: contain;
  }
  .topbar nav::-webkit-scrollbar { display: block; height: 5px; }
  .topbar nav::-webkit-scrollbar-track { background: transparent; }
  .topbar nav::-webkit-scrollbar-thumb { background: rgba(232,233,236,.22); border-radius: 99px; }
  @media (hover: hover) {
    .topbar nav::-webkit-scrollbar-thumb:hover { background: rgba(232,233,236,.42); }
  }

  /* Tepi yang memudar = "masih ada menu di sebelah sana". Hanya dipasang saat
     barisnya benar-benar meluber, dan sisi yang sudah mentok tidak diburamkan —
     kalau tidak, menu pertama terlihat pudar padahal tidak ada yang tersembunyi. */
  .topbar nav.over { mask-image: linear-gradient(90deg, transparent 0, #000 20px, #000 calc(100% - 20px), transparent 100%); }
  .topbar nav.over.at-start { mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 20px), transparent 100%); }
  .topbar nav.over.at-end { mask-image: linear-gradient(90deg, transparent 0, #000 20px, #000 100%); }
  .topbar nav.over.at-start.at-end { mask-image: none; }
}

/* ---------- modal + pengumuman akhir partai ----------
   Papan yang diam tidak memberi tahu apa pun. Yang mengumumkan partai selesai adalah
   lapisan ini: menutupi layar, menahan sentuhan ke papan, dan menaruh langkah
   berikutnya sebagai tombol terbesar.

   Namanya .modal-card, bukan .modal: kelas .modal sudah dipakai pemilih wilayah
   (location.js) dengan ukuran dan animasinya sendiri, dan aturan di sini berada lebih
   bawah di berkas — menumpanginya akan mengecilkan serta menggeser kotak itu. */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 120;
  display: flex; align-items: center; justify-content: center; padding: 20px;
  background: rgba(8, 9, 11, .72); backdrop-filter: blur(2px);
  opacity: 0; transition: opacity .15s ease;
}
.modal-backdrop.show { opacity: 1; }
.modal-card {
  position: relative; width: 100%; max-width: 380px;
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: 16px; padding: 22px 20px 18px; box-shadow: 0 18px 50px rgba(0,0,0,.5);
  transform: translateY(8px) scale(.97); transition: transform .17s ease;
  max-height: calc(100vh - 40px); overflow-y: auto;
}
.modal-backdrop.show .modal-card { transform: none; }
.modal-x {
  position: absolute; top: 8px; right: 8px; width: 32px; min-height: 0; padding: 0;
  background: none; border: 0; color: var(--muted); font-size: 15px; line-height: 32px;
}
.modal-x:hover { background: var(--bg-soft); color: var(--text); }
.modal-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 16px; }
.modal-actions .btn, .modal-actions button { width: 100%; text-align: center; grid-column: span 2; }
.modal-actions .half { grid-column: span 1; }

/* Garis warna di tepi atas: menang hijau, kalah merah, remis abu — terbaca sebelum
   satu kata pun sempat dibaca. */
.modal-card.game-over { text-align: center; border-top: 4px solid var(--muted); }
.modal-card.game-over.win { border-top-color: var(--accent); }
.modal-card.game-over.loss { border-top-color: var(--danger); }
.go-icon { font-size: 40px; line-height: 1; margin: 2px 0 6px; }
.go-title { margin: 0; font-size: 25px; letter-spacing: -.01em; }
.modal-card.game-over.win .go-title { color: #b6e39a; }
.modal-card.game-over.loss .go-title { color: #ffb4a6; }
.go-reason { margin: 5px 0 0; color: var(--muted); font-size: 14px; }
.go-versus {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px;
  margin-top: 14px; padding: 10px 12px;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: 11px;
  font-size: 13px; font-weight: 600;
}
.go-side {
  text-align: left;
  /* Anak grid punya min-width auto: tanpa dinolkan, nama sepanjang
     "Bot level 4 — Klub" melebarkan kolomnya sendiri dan mendorong skor keluar
     kartu, bukan dipotong. Dan ellipsis hanya bekerja kalau teksnya dilarang
     berpindah baris. */
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.go-side.right { text-align: right; }
.go-side small {
  display: block; font-weight: 500; color: var(--muted); font-size: 11.5px;
  overflow: hidden; text-overflow: ellipsis;
}
.go-score { font-size: 16px; font-weight: 700; letter-spacing: .02em; }
.modal-card.game-over .alert { text-align: left; margin: 10px 0 0; }

/* Baris tombol di bawah papan berubah begitu partai selesai: menyerah/petunjuk tidak
   lagi berarti apa-apa, jadi tempatnya diambil satu tombol "main lagi". */
.board-actions.finished { grid-template-columns: 1fr; }

/* ---------- tawanan + keunggulan perwira ----------
   Barisnya ikut di dalam .player-row, di bawah nama: itu "area masing-masing pemain",
   dan menaruhnya di sana berarti tidak ada satu baris pun tambahan yang mendorong
   papan turun di layar ponsel. */
.player-row { flex-wrap: wrap; }
.player-row .name { flex: 0 1 auto; }
.captured {
  flex-basis: 100%; order: 10;
  display: flex; align-items: center; gap: 1px; min-height: 17px; margin-top: 1px;
}
.captured img {
  width: 17px; height: 17px; display: block;
  /* Tawanan bukan bagian dari posisi — dibuat redup supaya mata tidak salah membaca
     deretan ini sebagai bidak yang masih hidup. */
  opacity: .62;
  /* Ditumpuk sedikit seperti tawanan sungguhan yang disandarkan di tepi papan;
     yang pertama tidak digeser supaya barisnya tetap rata kiri. */
  margin-left: -4px;
}
.captured img:first-child { margin-left: 0; }
.captured .adv {
  margin-left: 6px; font-size: 12px; font-weight: 700; color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* ---------- skor pertemuan ----------
   Tiga angka berurutan, menang–remis–kalah, dengan kuncinya ditulis di bawah: tanpa
   kunci itu "3–1–2" adalah tiga angka yang bisa dibaca dengan tiga cara berbeda. */
.h2h {
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  margin-top: 12px; padding: 8px 12px;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: 11px;
}
.h2h .lbl { font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.h2h .val { font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; }
.h2h .val .sep { color: var(--muted); font-weight: 500; margin: 0 3px; }
.h2h .key { font-size: 10.5px; color: var(--muted); }

/* ---------- pemilih tampilan papan ---------- */
.theme-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-top: 10px; }
.theme-opt {
  display: flex; flex-direction: column; gap: 8px; align-items: stretch; text-align: center;
  background: var(--bg-soft); border: 2px solid var(--line); border-radius: 13px;
  padding: 10px; color: var(--text); cursor: pointer; font: inherit;
}
.theme-opt:hover { border-color: #4d525c; background: var(--bg-soft); }
.theme-opt.active { border-color: var(--accent); }
.theme-opt .nm { font-size: 13px; font-weight: 700; }
.theme-opt.active .nm::after { content: ' ✓'; color: var(--accent); }
/* Pratinjau: papan 4x4 sungguhan dengan bidak sungguhan, bukan gambar tersendiri —
   apa yang dilihat di sini persis yang akan muncul di papan. */
.mini-board {
  display: grid; grid-template-columns: repeat(4, 1fr); aspect-ratio: 1/1;
  border-radius: 7px; overflow: hidden;
}
.mini-board div { position: relative; }
.mini-board img { width: 100%; height: 100%; display: block; }

/* ---------- ganti tampilan cepat, di halaman bermain ---------- */
.theme-quick { position: relative; display: flex; justify-content: flex-end; margin: 8px auto 0; max-width: 620px; }
.theme-quick .tq-now { font-weight: 600; }
.tq-menu {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 50; min-width: 210px;
  background: var(--bg-card); border: 1px solid var(--line); border-radius: 12px;
  padding: 10px; box-shadow: var(--shadow);
}
.tq-group + .tq-group { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.tq-label {
  display: block; font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); margin-bottom: 5px;
}
.tq-opt {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: none; border: 0; border-radius: 8px; padding: 7px 9px;
  color: var(--text); font-size: 13.5px; font-weight: 600; min-height: 0;
}
.tq-opt:hover { background: var(--bg-soft); }
.tq-opt.active { background: var(--bg-soft); color: var(--accent); }
.tq-opt.active::after { content: '✓'; margin-left: auto; }
/* Dua petak kecil: warna papannya sendiri yang menamai pilihannya. */
.tq-chip { display: inline-flex; border-radius: 4px; overflow: hidden; box-shadow: 0 0 0 1px var(--line); }
.tq-chip i { width: 11px; height: 15px; display: block; }
.tq-more { display: block; margin-top: 10px; font-size: 12px; text-align: center; }

/* ---------- kartu username di halaman Akun ---------- */
.rename-state { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.rename-state .pill { font-size: 12px; }

/* ---------- pilihan masuk yang setara ----------
   Tombol daftar manual dibuat selebar tombol Google, tepat di bawahnya. Sebelumnya
   mendaftar dengan email sendiri hanya berupa tautan teks di bawah judul — pilihan
   yang ada, tapi harus dicari lebih dulu. */
.btn.block {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; margin-top: 10px; font-weight: 600;
}
.or-split {
  display: flex; align-items: center; gap: 10px;
  margin: 16px 0 4px; color: var(--muted); font-size: 12px;
}
.or-split::before, .or-split::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* Penanda persona. Warnanya sengaja bukan warna paket mana pun: ini bukan tingkatan
   akun, melainkan keterangan bahwa yang di seberang papan bukan orang. */
.badge.bot {
  background: #2a2d34; color: #9fb4d8; border-color: #3c4553; margin-left: 5px;
  text-transform: lowercase; letter-spacing: .02em;
}

/* Kotak kode OTP: enam angka, dibaca dari email dan diketik ulang. Diberi jarak antar
   huruf dan font monospace supaya angkanya tidak menyatu saat dieja. */
.otp {
  font-size: 26px; font-weight: 700; letter-spacing: .3em; text-align: center;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ---------- nama pemain premium ----------
   Emas yang bergerak pelan, dan berlian di depannya. Yang dijaga di sini adalah
   keterbacaan: nama tetap harus terbaca sebagai nama, jadi kilaunya berjalan di
   sepanjang huruf, bukan menyala di belakangnya. */
.vip {
  background: linear-gradient(100deg, #d9a441 0%, #f7e39b 22%, #ffffff 32%, #f7e39b 42%, #d9a441 64%, #f7e39b 86%, #d9a441 100%);
  background-size: 260% 100%;
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
  font-weight: 700;
  animation: vip-shine 5.5s linear infinite;
}
@keyframes vip-shine {
  from { background-position: 180% 0; }
  to   { background-position: -80% 0; }
}
/* Berlian tidak ikut dipotong oleh background-clip — kalau ikut, ia hilang bersama
   warnanya dan yang tersisa cuma ruang kosong di depan nama. */
.vip-gem {
  display: inline-block; margin-right: 4px;
  -webkit-text-fill-color: initial; color: initial;
  filter: drop-shadow(0 0 3px rgba(160, 220, 255, .75));
}
/* Sebagian orang mematikan animasi di tingkat sistem, dan permintaan itu berlaku juga
   di sini: emasnya tetap, kilaunya yang berhenti. */
@media (prefers-reduced-motion: reduce) {
  .vip { animation: none; background-position: 40% 0; }
}

/* --- panel admin: manajemen user ------------------------------------------- */
/* Daftar akun ditulis sebagai kartu, bukan tabel: yang membukanya hampir selalu
   sedang memegang ponsel, dan tabel tujuh kolom di layar 390px adalah tabel yang
   digeser ke samping untuk membaca satu barisnya. */
.switch-row { display: flex; gap: 10px; align-items: flex-start; cursor: pointer; }
.switch-row input { width: 18px; height: 18px; margin-top: 2px; flex: none; }
.switch-row > span { display: flex; flex-direction: column; gap: 3px; }

.filters { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 4px; }
.filters input[type="search"] { flex: 1 1 220px; min-width: 160px; }

.user-list { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.urow {
  border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px;
  background: var(--bg-soft); display: flex; flex-direction: column; gap: 6px;
}
.urow .uhead { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.urow .uname { font-weight: 700; }
.urow .umeta {
  display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 12.5px; color: var(--muted);
}
.urow .umeta span { white-space: nowrap; }
.urow .uact { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 2px; }
.urow .uact select { padding: 5px 8px; font-size: 12.5px; }
.ok-tick { color: var(--accent); font-weight: 700; }
.urow .uremark { display: flex; gap: 6px; align-items: center; }
.urow .uremark input { flex: 1; padding: 5px 8px; font-size: 12.5px; }

/* --- katalog paket --------------------------------------------------------- */
.plan .price { font-size: 26px; margin: 10px 0 2px; }
.plan .price b { font-size: 30px; }
.plan-hi { border-color: #6b5a2a; box-shadow: 0 0 0 1px rgba(240,198,116,.25); }
.plan-mine { border-color: var(--accent); }
.plan-list { list-style: none; padding: 0; margin: 14px 0 16px; display: flex; flex-direction: column; gap: 6px; }
.plan-list li { padding-left: 22px; position: relative; font-size: 14px; }
.plan-list li::before { content: "✓"; position: absolute; left: 0; color: var(--accent); font-weight: 700; }

/* ---------- halaman bermain di ponsel ----------------------------------------
   Satu keluhan, satu penyebab: di layar 390px, kartu pemilih lawan setinggi satu
   layar penuh berdiri di atas papan, jadi yang membuka "Lawan Bot" melihat daftar
   master dan sama sekali tidak melihat papannya sampai ia menggulir. Di sini papan
   naik ke urutan pertama dan pemilih lawan turun ke bawahnya dalam keadaan terlipat.

   Yang dipakai cuma `order` pada wadah halaman, bukan markup kedua: satu halaman
   dengan dua susunan berarti dua tempat yang harus diubah setiap kali ada tombol
   baru, dan yang di ponsel selalu jadi yang ketinggalan. */
@media (max-width: 900px) {
  .play-page { display: flex; flex-direction: column; }
  .play-page .play-layout { order: 1; }
  /* Pemilih lawan sekarang tinggal di kolom kanan bersama daftar langkah. Di ponsel
     kolom itu jatuh ke bawah papan, dan di dalamnya pemilih lawan turun lagi ke
     paling bawah — yang dicari selagi bermain adalah langkah terakhir, bukan daftar
     lawan yang sudah dipilih. */
  .play-page .opponent-pick { order: 3; }

  /* Wajib, dan bukan hiasan: anak sebuah flex/grid menolak menyusut di bawah lebar
     min-content-nya. Pita langkah berisi kata-kata yang tidak boleh dipatah, jadi
     min-content-nya selebar seluruh partai — dan tanpa baris ini lebar itu merambat
     naik sampai ke halaman, mendorong papan keluar layar ke kanan. */
  .play-page, .play-page > *, .play-page .play-layout > *,
  .play-page .play-layout > .grid > *, .play-page .moves { min-width: 0; }

  /* Ruang mati dipangkas semuanya: di sinilah satu layar dimenangkan atau kalah. */
  .play-page .container, .play-page .card { padding: 12px; }
  .play-page .play-layout { gap: 10px; }
  .play-page .eval-head { margin-bottom: 6px; }
  .play-page .board-wrap { margin: 6px auto !important; }
  .play-page .player-row { padding: 6px 10px; }
  .play-page .board-actions { margin-top: 8px; }
  .play-page .board-actions button { min-height: 46px; font-size: 12px; }

  /* Daftar langkah jadi satu pita mendatar: di ponsel yang dicari cuma langkah
     terakhir, dan kolom tegak setinggi 320px memakan tempat papan demi riwayat yang
     tidak sedang dibaca siapa pun. */
  .play-page .moves {
    display: flex; gap: 8px; max-height: none; overflow-x: auto; overflow-y: hidden;
    padding-bottom: 2px; scrollbar-width: none;
  }
  .play-page .moves::-webkit-scrollbar { display: none; }
  .play-page .moves .num { position: sticky; left: 0; }
  .play-page .moves > * { white-space: nowrap; }
  /* Judul "Langkah" tidak menerangkan apa pun yang tidak sudah jelas dari isinya,
     dan sebelum ada langkah pertama kartunya cuma kotak kosong yang mendorong
     pemilih lawan keluar layar. Keduanya hanya untuk kartu langkah — judul "Cari
     lawan" di halaman duel adalah judul yang benar-benar menerangkan sesuatu. */
  .play-page .moves-card > h3 { display: none; }
  .play-page .moves-card:has(> .moves:empty) { display: none; }

  /* Pembukaan dan bar keunggulan jadi satu baris. Dua baris terpisah di atas papan
     berarti 28px yang dibayar setiap layar hanya untuk satu keterangan yang jarang
     dibaca selagi berpikir. */
  .play-page .eval-head { display: flex; align-items: center; gap: 10px; }
  .play-page .eval-head .opening {
    flex: 1 1 auto; min-width: 0; font-size: 12.5px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .play-page .eval-head .eval-row { flex: 0 0 auto; margin-top: 0; width: 46%; }
  .play-page .eval-head .eval-num { min-width: 44px; font-size: 13px; }

}

/* Kartu "Setelah selesai" hanya berisi satu kalimat janji sampai partainya usai.
   Selama masih berisi kalimat itu ia disembunyikan — begitu diisi hasil partai,
   :has berhenti cocok dan kartunya muncul sendiri tanpa satu baris JS pun. Berlaku
   di semua lebar layar: kartu kosong setinggi 90px di kolom kanan sama tidak
   berartinya di laptop seperti di ponsel. */
.play-page .end-card:has(#endBox > p.muted) { display: none; }

/* Kepala kartu yang bisa dilipat: baris yang bisa disentuh, bukan judul mati.
   `display: flex` sekaligus membuang segitiga bawaan <summary> — segitiga itu muncul
   dari display:list-item, dan ia tidak pernah sejajar dengan apa pun yang kita taruh
   di sebelahnya. */
summary.setup-summary {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  font-weight: 700; font-size: 15px; list-style: none; padding: 2px 0;
}
summary.setup-summary::-webkit-details-marker { display: none; }
summary.setup-summary .txt { flex: 1; }
summary.setup-summary .chev { color: var(--muted); transition: transform .15s; }
details[open] > summary.setup-summary .chev { transform: rotate(180deg); }

/* Di layar lebar tidak ada yang dilipat. Dua nasib berbeda: kepala pemilih lawan
   memang tidak perlu ada (kartunya punya judul sendiri di dalam), sedangkan kepala
   obrolan adalah satu-satunya judul kartu itu — jadi ia tinggal berhenti terlihat
   seperti tombol. */
@media (min-width: 901px) {
  summary.setup-summary.hide-wide { display: none; }
  summary.setup-summary.as-title { cursor: default; font-size: 17px; margin-bottom: 10px; }
  summary.setup-summary.as-title .chev { display: none; }
}

/* ---------- duel online di ponsel: dua keadaan, dua susunan -------------------
   Menganggur dan sedang bermain menginginkan hal yang berbeda tepat di bawah papan.
   Selagi mencari lawan, yang dicari tombol "Cari lawan"; begitu jam berjalan, yang
   dicari menyerah/tawar remis dan daftar langkah — dan pemilih waktu jadi kartu yang
   tidak berguna sampai partai ini selesai. Yang berpindah cuma urutan; tidak ada satu
   elemen pun yang dipindahkan oleh JS, jadi tidak ada susunan kedua yang harus ikut
   diubah setiap kali ada tombol baru. */
@media (max-width: 900px) {
  .play-page .play-layout > .grid { display: flex; flex-direction: column; }
  .play-page #lobbyCard { order: 1; }
  .play-page .game-card { order: 2; }
  .play-page .chat { order: 3; }

  .play-page.playing #lobbyCard { display: none; }
  .play-page.playing .game-card { order: 0; }
  /* Judul "Partai" berlebihan waktu kartunya sudah berada tepat di bawah papan. */
  .play-page.playing .game-card > h3 { display: none; }

  /* Tiga tombol partai jadi satu baris selebar layar: sejauh jempol, seukuran jempol. */
  .play-page .board-actions-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .play-page .board-actions-row button { width: 100%; min-height: 44px; }
}

/* ---------- suara: mencari lawan, kartu lawan, pemutar musik ------------------
   Tiga tampilan yang lahir bersama bunyinya. Yang bergerak di sini semuanya punya
   pasangan yang terdengar — denyut radar berpasangan dengan sonar, kartu lawan yang
   masuk berpasangan dengan nada "ketemu" — jadi orang yang mematikan suara tetap
   mendapat kabar yang sama lewat mata, dan sebaliknya. */

/* Menunggu di antrean. Denyut yang melebar keluar dari bidak di tengah. */
.searching {
  display: flex; align-items: center; gap: 14px;
  margin-top: 12px; padding: 12px 14px;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: var(--radius);
}
.searching .radar {
  position: relative; width: 54px; height: 54px; flex: none;
  display: grid; place-items: center;
}
.searching .radar img { width: 30px; height: 30px; position: relative; z-index: 2; }
.searching .radar .ring {
  position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid var(--accent); opacity: 0;
}
@media (prefers-reduced-motion: no-preference) {
  .searching .radar .ring { animation: radar-pulse 2.1s ease-out infinite; }
  .searching .radar .ring:nth-child(2) { animation-delay: .7s; }
  .searching .radar .ring:nth-child(3) { animation-delay: 1.4s; }
  .searching .radar img { animation: radar-bob 2.1s ease-in-out infinite; }
}
/* Tanpa animasi, denyutnya tetap harus terlihat sebagai lingkaran — bukan hilang
   sama sekali, karena itulah satu-satunya tanda halaman masih bekerja. */
@media (prefers-reduced-motion: reduce) { .searching .radar .ring:first-child { opacity: .35; } }
@keyframes radar-pulse {
  0% { transform: scale(.45); opacity: .65; }
  80% { opacity: 0; }
  100% { transform: scale(1.15); opacity: 0; }
}
@keyframes radar-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
.searching-txt { display: flex; flex-direction: column; gap: 2px; }

/* Kartu "lawan ketemu": hitam di atas, putih di bawah, warna kartunya sendiri-sendiri. */
.versus-overlay {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  background: rgba(0, 0, 0, .55);
  opacity: 0; transition: opacity .2s ease;
  padding: 20px;
}
.versus-overlay.show { opacity: 1; }
.versus {
  width: min(420px, 100%);
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 18px 16px; text-align: center;
}
.vs-head {
  margin: 0 0 12px; text-transform: uppercase; letter-spacing: .12em;
  font-size: 12px; color: var(--muted);
}
.vs-side {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border-radius: 10px; text-align: left;
  transform: translateX(-24px); opacity: 0;
}
.vs-side.white { transform: translateX(24px); }
.versus-overlay.show .vs-side { transform: none; opacity: 1; transition: transform .32s ease-out, opacity .32s ease-out; }
.versus-overlay.show .vs-side.white { transition-delay: .1s; }
.vs-side.black { background: #2a2c31; border: 1px solid var(--line); }
.vs-side.white { background: #eceef0; border: 1px solid #d6d9dd; color: #17181b; }
.vs-side .vs-piece { width: 38px; height: 38px; flex: none; }
.vs-who { display: flex; flex-direction: column; min-width: 0; }
.vs-who b { font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vs-who span { font-size: 12px; opacity: .7; }
.vs-you {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  background: var(--accent); color: #10240a; border-radius: 999px; padding: 1px 6px; margin-left: 6px;
  vertical-align: middle;
}
.vs-mid { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 8px 0; }
.vs-word { font-weight: 800; font-size: 20px; letter-spacing: .1em; color: var(--accent); }
.vs-tc { font-size: 12px; color: var(--muted); }
@media (prefers-reduced-motion: reduce) {
  .vs-side, .versus-overlay.show .vs-side { transform: none; opacity: 1; transition: none; }
}

/* Pemutar musik di beranda. Satu baris: putar, nama trek, lompat, volume. */
.musicbar {
  display: flex; align-items: center; gap: 12px;
  margin: 14px 0 4px; padding: 10px 12px;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: var(--radius);
}
.musicbar .mb-play {
  width: 40px; height: 40px; flex: none; border-radius: 50%;
  padding: 0; font-size: 14px; line-height: 1;
}
.musicbar .mb-play.on { background: var(--accent); }
.musicbar .mb-txt { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.musicbar .mb-txt b { font-size: 14px; }
.musicbar .mb-txt span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.musicbar input[type="range"] { width: 110px; flex: none; accent-color: var(--accent); }
@media (max-width: 560px) {
  .musicbar input[type="range"] { width: 78px; }
}

/* Saklar di kartu setelan: barisnya sendiri yang jadi tombol, bukan kotak kecil di
   ujung — jempol memerlukan sasaran selebar baris. */
.toggle-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 10px 12px; text-align: left;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: 10px;
  color: var(--text); font: inherit; cursor: pointer;
}
.toggle-row span { display: flex; flex-direction: column; gap: 2px; }
.toggle-row small { color: var(--muted); font-size: 12px; }
.toggle-row .switch {
  width: 42px; height: 24px; flex: none; border-radius: 999px;
  background: var(--line); position: relative; transition: background .15s ease;
}
.toggle-row .switch::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 18px; height: 18px; border-radius: 50%; background: var(--muted);
  transition: transform .15s ease, background .15s ease;
}
.toggle-row .switch.on { background: rgba(127, 166, 80, .35); }
.toggle-row .switch.on::after { transform: translateX(18px); background: var(--accent); }

/* Kartu "Cari lawan" selagi antre: yang tersisa hanya pembatalan dan denyutnya.
   Pemilih waktu dan hitungan lobi tidak bisa diapa-apakan sampai antreannya selesai,
   dan di ponsel keduanyalah yang mendorong denyut radar ke balik bilah menu bawah. */
.card.queueing .tc-pick,
.card.queueing #lobbyStats { display: none; }
.card.queueing .searching { margin-top: 0; }
/* Denyutnya naik ke atas tombol Batal: yang sedang terjadi dibaca lebih dulu daripada
   cara membatalkannya. */
.card.queueing { display: flex; flex-direction: column; }
.card.queueing #queueMsg { order: 1; }
.card.queueing .row { order: 2; margin-top: 12px; }


/* ---------- pemilih kontrol waktu (Duel Online) ---------------------------- */
/* Tertutup: satu baris — ikon kecepatan, waktunya, nama kelompoknya, panah.
   Terbuka: kelompoknya turun ke bawah tombol dan mendorong isi kartu, bukan melayang
   di atasnya; di ponsel lapisan melayang di dalam kartu sempit lebih sering menutupi
   hal yang sedang dibaca daripada menghemat ruang. */
.tc-pick { position: relative; }
.tc-toggle {
  width: 100%; display: flex; align-items: center; gap: 10px; text-align: left;
  background: var(--bg-soft); color: var(--text); border: 1px solid var(--line);
  border-radius: 12px; padding: 11px 13px; font-size: 15px; cursor: pointer;
}
.tc-toggle .tc-ic { font-size: 17px; line-height: 1; flex: none; }
.tc-toggle .tc-txt { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 8px; }
.tc-toggle .tc-txt b { font-size: 16px; font-weight: 800; }
.tc-toggle .tc-txt small { color: var(--muted); font-size: 13px; }
.tc-toggle .chev { flex: none; color: var(--muted); font-size: 13px; transition: transform .18s ease; }
.tc-pick.open .tc-toggle { border-color: #454a53; }
.tc-pick.open .tc-toggle .chev { transform: rotate(180deg); }
@media (hover: hover) { .tc-toggle:hover { background: #2c2f35; } }

.tc-menu { margin-top: 12px; display: grid; gap: 14px; }
/* `display: grid` di atas mengalahkan `display: none` bawaan atribut [hidden] —
   tanpa baris ini daftarnya tidak pernah benar-benar tertutup. */
.tc-menu[hidden] { display: none; }
.tc-group-head {
  display: flex; align-items: center; gap: 7px;
  font-weight: 700; font-size: 14px; margin-bottom: 8px;
}
.tc-group-head .ic { font-size: 15px; }
.tc-group[data-mode="bullet"]    .tc-group-head { color: var(--warn); }
.tc-group[data-mode="blitz"]     .tc-group-head { color: #e5c04b; }
.tc-group[data-mode="rapid"]     .tc-group-head { color: var(--accent); }
.tc-group[data-mode="classical"] .tc-group-head { color: var(--info); }

.tc-opts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.tc-opt {
  position: relative; background: var(--bg-soft); color: var(--text);
  border: 1px solid var(--line); border-radius: 10px;
  padding: 12px 6px; font-size: 14px; font-weight: 700; cursor: pointer;
}
@media (hover: hover) { .tc-opt:hover { background: #2c2f35; } }
.tc-opt.active {
  border-color: var(--accent); color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
/* Tujuh menit tidak ada di tempat lain — penanda kecil ini yang membedakannya dari
   angka di sebelahnya, tanpa mengubah bentuk tombolnya. */
.tc-opt .tc-tag {
  position: absolute; top: -7px; right: -5px;
  background: var(--accent); color: #10240a;
  font-size: 9px; font-weight: 800; font-style: normal; letter-spacing: .3px;
  padding: 2px 5px; border-radius: 999px; text-transform: uppercase;
}

/* Umpan bot: ada di DOM, tidak pernah ada di layar. Dikeluarkan dari alur dengan
   posisi absolut supaya tidak menggeser apa pun, bukan dengan `display:none` — sebagian
   bot memang melewati kolom yang display-nya none, dan yang dicari justru bot yang
   mengisi semua kolom. */
.hp {
  position: absolute; left: -9999px; top: auto;
  width: 1px; height: 1px; overflow: hidden;
}
