:root {
  --bg: #14171c; --panel: #1d222b; --panel2: #232a35; --line: #333c49;
  --text: #e6e9ee; --muted: #9aa6b3; --accent: #5aa9ff; --danger: #ff6b6b; --ok: #5fd38a;
}
* { box-sizing: border-box; }
body { margin: 0; font: 14px/1.45 system-ui, "Segoe UI", Roboto, sans-serif; background: var(--bg); color: var(--text); }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
h1 { font-size: 20px; margin: 16px 0 12px; }
h2 { font-size: 16px; margin: 14px 0 8px; }
h3 { font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); margin: 14px 0 6px; }
hr { border: 0; border-top: 1px solid var(--line); margin: 16px 0; }
.muted { color: var(--muted); }
.right { margin-left: auto; }

.topbar { display: flex; align-items: center; gap: 20px; padding: 8px 16px; background: var(--panel); border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.topbar .brand a { color: var(--text); font-weight: 600; }
.topbar .tabs { display: flex; gap: 4px; }
.topbar .tabs a { padding: 6px 12px; border-radius: 6px; color: var(--muted); }
.topbar .tabs a.active { background: var(--panel2); color: var(--text); }
/* Hover dropdown under a top tab (used by Match History) */
.topbar .tabs .tab-group { position: relative; display: inline-flex; }
.topbar .tabs .tab-group > a::after { content: ' ▾'; color: var(--muted); font-size: 10px; }
.topbar .tabs .tab-submenu { display: none; position: absolute; top: 100%; left: 0; min-width: 180px; background: var(--panel); border: 1px solid var(--line); border-radius: 6px; padding: 4px; z-index: 50; box-shadow: 0 6px 22px rgba(0,0,0,.4); }
.topbar .tabs .tab-group:hover .tab-submenu, .topbar .tabs .tab-group:focus-within .tab-submenu { display: block; }
.topbar .tabs .tab-submenu a { display: block; padding: 6px 10px; border-radius: 4px; color: var(--muted); white-space: nowrap; }
.topbar .tabs .tab-submenu a:hover, .topbar .tabs .tab-submenu a.active { background: var(--panel2); color: var(--text); text-decoration: none; }

/* Inline sub-tab strip used on Match History sub-pages */
nav.subtabs { display: flex; gap: 4px; margin: -4px 0 14px; border-bottom: 1px solid var(--line); }
nav.subtabs a { padding: 6px 12px; border-radius: 6px 6px 0 0; color: var(--muted); font-weight: 500; border: 1px solid transparent; border-bottom: 0; margin-bottom: -1px; }
nav.subtabs a:hover { color: var(--text); text-decoration: none; }
nav.subtabs a.active { background: var(--panel); color: var(--text); border-color: var(--line); }
.topbar .userbox { margin-left: auto; display: flex; align-items: center; gap: 10px; color: var(--muted); }
.topbar .role { background: var(--panel2); border: 1px solid var(--line); border-radius: 4px; padding: 0 5px; font-size: 11px; text-transform: uppercase; }
button.link { -webkit-appearance: none; appearance: none; background: transparent; border: 0; border-radius: 0; padding: 0; margin: 0; font: inherit; font-weight: normal; color: var(--accent); cursor: pointer; text-align: left; }
button.link:hover { text-decoration: underline; }
button.link.danger { color: var(--danger); background: transparent; border: 0; padding: 0; }
form.clearline { display: block; margin: 6px 0 2px; }
form.inline { display: inline; }

.page { max-width: 1200px; margin: 16px auto; padding: 0 16px 40px; }

/* Site footer (every page) */
.site-footer { border-top: 1px solid var(--line); margin-top: 40px; padding: 18px 16px 26px; text-align: center; color: var(--muted); font-size: 13px; }
.site-footer a { color: var(--muted); }
.site-footer a:hover { color: var(--text); }
.site-footer .sep { margin: 0 8px; opacity: .5; }
.site-footer .discord-btn { display: inline-block; margin-left: 4px; padding: 4px 12px; border-radius: 6px; background: #5865F2; color: #fff; font-weight: 600; }
.site-footer .discord-btn:hover { background: #4853d8; color: #fff; text-decoration: none; }
.site-footer .footer-copy { margin-top: 10px; font-size: 12px; opacity: .7; }
.site-footer .footer-ext { margin-top: 8px; font-size: 12px; display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: center; justify-content: center; }
.site-footer .footer-ext a { display: inline-flex; align-items: center; gap: 5px; }
.site-footer .footer-ext svg { flex: 0 0 auto; vertical-align: middle; }

/* Collapsible finalized sessions (Session Tracker) */
.session-details { margin-top: 4px; }
.session-details > summary { cursor: pointer; display: inline-flex; align-items: center; gap: 7px; color: var(--accent); font-size: 13px; font-weight: 600; list-style: none; user-select: none; padding: 5px 0; }
.session-details > summary::-webkit-details-marker { display: none; }
.session-details > summary::marker { content: ''; }
.session-details > summary:hover { text-decoration: underline; }
.session-details > summary .disclosure { display: inline-block; width: 0; height: 0; border-left: 5px solid currentColor; border-top: 4px solid transparent; border-bottom: 4px solid transparent; transition: transform .15s; }
.session-details[open] > summary .disclosure { transform: rotate(90deg); }
.session-details .tablewrap { margin-top: 8px; }

/* Player Metrics — selectable session list */
.checklist.sess-pick { max-height: 280px; }
.checklist.sess-pick li { padding: 3px 0; }
.checklist.sess-pick .check { align-items: flex-start; }
.checklist.sess-pick .sess-label { line-height: 1.35; }

/* Editable static pages (privacy / user agreement) */
.legal-body { white-space: pre-wrap; line-height: 1.55; color: var(--text); margin-top: 10px; }
.card { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 16px; margin-bottom: 16px; }
.card.narrow { max-width: 420px; margin: 40px auto; }
.danger-zone { border-color: #5a2b2b; }

label { display: block; margin: 8px 0; }
label.check { display: inline-flex; align-items: center; gap: 6px; margin: 4px 14px 4px 0; }
input[type=text], input[type=email], input[type=password], input[type=date], select {
  background: var(--panel2); border: 1px solid var(--line); color: var(--text); border-radius: 6px; padding: 6px 8px; font: inherit;
}
input[type=text], input[type=email], input[type=password] { min-width: 220px; }
textarea { background: var(--panel2); border: 1px solid var(--line); color: var(--text); border-radius: 6px; padding: 6px 8px; font: inherit; width: 100%; max-width: 560px; resize: vertical; }
fieldset { border: 1px solid var(--line); border-radius: 8px; margin: 12px 0; padding: 8px 12px 12px; }
legend { color: var(--muted); padding: 0 6px; }
.rolerow { display: flex; align-items: center; gap: 8px; margin: 4px 0; }

button, .btn { background: var(--accent); color: #06203b; border: 0; border-radius: 6px; padding: 7px 14px; font: inherit; font-weight: 600; cursor: pointer; }
button:disabled, .btn:disabled { opacity: .5; cursor: default; }
.btn.ghost, .btn.small { background: var(--panel2); color: var(--text); border: 1px solid var(--line); }
.btn.small { padding: 3px 8px; font-weight: 400; }
.btn.danger, button.danger { background: var(--danger); color: #2a0808; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.row.spread { justify-content: space-between; }

/* Two-column form grid with labels stacked above inputs. Scoped class so it
   only applies to forms that opt in. Styles every input type uniformly so
   number/file pickers stop rendering as default-white browser controls. */
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 18px; max-width: 720px; }
.form-grid .field { display: flex; flex-direction: column; gap: 4px; margin: 0; }
.form-grid .field.full { grid-column: 1 / -1; }
/* Override .field's display:flex so [hidden] actually hides the field (and
   the grid skips it). Required for the Brawl-only enemy fields. */
.form-grid .field[hidden] { display: none; }
.form-grid .field > label { margin: 0; font-size: 12px; color: var(--muted); letter-spacing: .02em; }
.form-grid .field > input,
.form-grid .field > select,
.form-grid .field > textarea {
  width: 100%; min-width: 0; max-width: none; box-sizing: border-box;
  background: var(--panel2); border: 1px solid var(--line); color: var(--text);
  border-radius: 6px; padding: 7px 10px; font: inherit;
}
.form-grid .field > input[type=file] { padding: 5px 8px; cursor: pointer; }
.form-grid .field > input[type=file]::file-selector-button {
  background: var(--panel); color: var(--text); border: 1px solid var(--line);
  border-radius: 4px; padding: 4px 10px; font: inherit; cursor: pointer; margin-right: 10px;
}
.form-grid .field > input[type=file]::file-selector-button:hover { border-color: var(--accent); color: var(--accent); }
.form-grid .field > textarea { min-height: 92px; resize: vertical; }
.form-grid .hint { grid-column: 1 / -1; margin: -4px 0 0; color: var(--muted); font-size: 12px; }
.form-grid .field-hint { color: var(--muted); font-size: 12px; margin-top: 2px; }

/* Click-to-sort table headers (opt-in via data-sort="..."). Inactive columns
   show a dim ▼ hint; the active column flips to accent colour + solid ▲/▼. */
th[data-sort] { cursor: pointer; user-select: none; transition: color .12s; }
th[data-sort]:hover { color: var(--accent); }
th[data-sort] .arr { opacity: .35; margin-left: 4px; font-size: 9px; font-weight: 700; }
th[data-sort].is-sorted { color: var(--accent); }
th[data-sort].is-sorted .arr { opacity: 1; }

/* /admin/stats: 30-day sparkline-style bar chart, one bar per day. Bar height
   scales to the day's unique-visitor count vs the 30-day max. Zero days show
   as a thin dim sliver so the timeline is still readable. */
.stats-chart {
  display: flex; align-items: flex-end; gap: 2px;
  height: 96px; padding: 12px 0 4px; border-bottom: 1px solid var(--line);
}
.stats-bar { flex: 1; background: var(--accent); min-height: 2px; transition: opacity .12s; cursor: help; }
.stats-bar:hover { opacity: .75; }
.stats-bar.zero { background: var(--line); min-height: 2px; }
.stats-chart-labels {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 11px; color: var(--muted); padding-top: 4px;
}
.stats-chart-labels .muted { font-size: 10px; letter-spacing: .04em; text-transform: uppercase; }
.form-grid .actions { grid-column: 1 / -1; display: flex; gap: 10px; align-items: center; margin-top: 4px; }
.form-grid .preview { grid-column: 1 / -1; display: flex; gap: 12px; align-items: flex-start; }
.form-grid .preview img { max-height: 140px; border: 1px solid var(--line); border-radius: 6px; }
@media (max-width: 600px) { .form-grid { grid-template-columns: minmax(0, 1fr); } }
.toolbar { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
.toolbar .sortform { margin-left: 8px; }

.flash { max-width: 1200px; margin: 10px auto 0; padding: 8px 14px; border-radius: 6px; }
.flash-notice { background: #163021; border: 1px solid #2c5b3d; color: var(--ok); }
.flash-error { background: #3a1b1b; border: 1px solid #5a2b2b; color: var(--danger); }

.tablewrap { overflow-x: auto; }
/* Site Admin: cap long lists at ~10 rows tall and scroll the rest. Header
   stays visible because table.grid th already uses position: sticky. */
.tablewrap.admin-scroll-10 { max-height: 420px; overflow-y: auto; }
table.grid { border-collapse: collapse; width: 100%; }
table.grid th, table.grid td { border: 1px solid var(--line); padding: 5px 8px; text-align: left; vertical-align: middle; }
table.grid th { background: var(--panel2); position: sticky; top: 0; font-size: 12px; }
table.grid th a.sortlink { display: block; color: inherit; text-decoration: none; cursor: pointer; }
table.grid th a.sortlink:hover { color: var(--accent); text-decoration: none; }
table.grid td.center, table.grid th.center { text-align: center; }
table.grid .rolecol { position: relative; white-space: normal; overflow-wrap: break-word; font-size: 11px; line-height: 1.2; width: 86px; min-width: 60px; max-width: 240px; text-align: center; vertical-align: bottom; padding-right: 12px; }
table.grid .rolecol .sortlink { padding: 0 2px; }
table.grid .rolecol .col-resizer { position: absolute; top: 0; right: 0; bottom: 0; width: 6px; cursor: col-resize; user-select: none; background: transparent; transition: background-color .12s; }
table.grid .rolecol .col-resizer:hover,
table.grid .rolecol .col-resizer.col-resizer-dragging { background: var(--accent); opacity: .55; }
body.col-resizing { cursor: col-resize; user-select: none; }
table.grid .col-playtime, table.grid td.col-playtime { white-space: nowrap; }
table.grid td.actions { white-space: nowrap; }
table.grid td.actions a, table.grid td.actions button.link { margin-right: 12px; }
table.grid td.actions button.link { -webkit-appearance: none; appearance: none; background: transparent; border: 0; border-radius: 0; padding: 0; font: inherit; font-weight: normal; cursor: pointer; vertical-align: baseline; color: var(--accent); }
table.grid td.actions button.link.danger { color: var(--danger); }
table.grid td.actions a:hover, table.grid td.actions button.link:hover { text-decoration: underline; }
table.grid tr.inactive td { color: var(--muted); background: rgba(255,255,255,.015); }
table.grid tr.inactive td strong { color: var(--muted); font-weight: 500; }

/* Members roster: row-number gutter + zebra striping for readability */
table.grid.roster th.rownum, table.grid.roster td.rownum { width: 36px; text-align: center; color: var(--muted); font-variant-numeric: tabular-nums; }
table.grid.roster tbody tr:nth-child(even) td { background: rgba(255,255,255,.025); }
table.grid.roster tbody tr:hover td { background: rgba(90,169,255,.06); }
.badge-inactive { display: inline-block; font-size: 10px; text-transform: uppercase; letter-spacing: .05em; padding: 1px 5px; border: 1px solid var(--line); border-radius: 3px; color: var(--muted); margin-left: 6px; vertical-align: middle; }

.layout-split { display: flex; gap: 16px; align-items: flex-start; }
.layout-split .sidecol { width: 300px; flex: 0 0 300px; }
.layout-split .grow, .grow { flex: 1; min-width: 0; }
.datelist { list-style: none; padding: 0; margin: 0; max-height: 220px; overflow: auto; }
/* Brand "X" — gold accent, matching the coming-soon page */
.brand-x { color: #f5c842; }

/* Clan settings → Profile: tidy the Description textarea under its label */
.profile-desc { display: block; margin-top: 6px; width: 100%; max-width: 520px; box-sizing: border-box; }

.datelist li { display: flex; align-items: center; }
.datelist li a { display: block; flex: 1; padding: 3px 6px; border-radius: 4px; color: var(--muted); }
.datelist li form.inline { display: flex; margin: 0; }
.datelist li .remove-x { margin: 0 4px 0 0; }
.datelist li a.active, .datelist li a:hover { background: var(--panel2); color: var(--text); text-decoration: none; }
.checklist { list-style: none; padding: 0; margin: 0; max-height: 360px; overflow: auto; }
.checklist li { padding: 1px 0; }

.gallery { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 10px; }
.gallery figure { margin: 0; width: 150px; }
.gallery img { width: 150px; height: 110px; object-fit: cover; border: 1px solid var(--line); border-radius: 6px; background: #000; }
.gallery figcaption { font-size: 12px; color: var(--muted); display: flex; justify-content: space-between; align-items: center; gap: 6px; }

/* Squad board — 2-column grid so up to 7 squads + bench fit in 4 rows × 2 cols. */
.squad-board { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-top: 6px; }
#squad-status { margin-top: 0; margin-bottom: 8px; }
.squad { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; display: flex; flex-direction: column; }
.squad-head { display: flex; align-items: baseline; gap: 8px 14px; padding: 8px 12px; border-bottom: 1px solid var(--line); background: var(--panel2); border-radius: 8px 8px 0 0; flex-wrap: wrap; }
.squad-name { font-weight: 600; }
.squad-no { font-weight: 700; color: var(--accent); flex: 0 0 auto; }
span.squad-name { flex: 0 0 auto; }
input.squad-name { background: transparent; border: 1px dashed transparent; color: var(--text); font-weight: 600; padding: 2px 6px; flex: 0 1 240px; min-width: 120px; }
input.squad-name:hover, input.squad-name:focus { border-color: var(--line); background: var(--bg); }
.squad-meta { color: var(--muted); font-size: 12px; flex: 1 1 auto; white-space: normal; line-height: 1.3; }
.squad-list { list-style: none; margin: 0; padding: 8px; min-height: 40px; display: flex; flex-direction: column; gap: 6px; flex: 1 1 auto; }
.squad.bench .squad-list { flex-flow: row wrap; }
.squad-list.drop-hover { background: #1b2735; outline: 1px dashed var(--accent); }
.squad-list li.member { display: flex; align-items: baseline; gap: 8px; background: var(--panel2); border: 1px solid var(--line); border-radius: 6px; padding: 5px 10px; cursor: grab; }
.squad.bench .squad-list li.member { gap: 6px; }
.squad-list li.member.dragging { opacity: .4; }
.squad-list li.member.unavail { color: var(--muted); cursor: default; opacity: .7; }
li.member .m-name { font-weight: 600; flex: 0 0 auto; }
li.member .m-name-link { -webkit-appearance: none; appearance: none; background: transparent; border: 0; padding: 0; font: inherit; font-weight: 600; color: var(--text); cursor: pointer; border-bottom: 1px dashed transparent; flex: 0 0 auto; }
li.member .m-name-link:hover { color: var(--accent); border-bottom-color: var(--accent); }
li.member .m-roles { color: var(--muted); font-size: 12px; flex: 1 1 auto; }
li.member .m-tag { font-size: 11px; color: var(--muted); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; flex: 0 0 auto; }
li.member .lock { color: #d8b25a; }

/* Rename role-label dialog (shared by Members, Edit Member, Squad Builder) */
dialog.role-labels-dlg { min-width: 460px; max-width: 560px; }
dialog.role-labels-dlg .rlbl-fields { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
dialog.role-labels-dlg .rlbl-row { display: grid; grid-template-columns: 140px 1fr; align-items: center; gap: 10px; }
dialog.role-labels-dlg .rlbl-default { color: var(--muted); font-size: 12px; text-align: right; }
dialog.role-labels-dlg .rlbl-input-wrap { position: relative; display: flex; align-items: center; }
dialog.role-labels-dlg .rlbl-input-wrap input { flex: 1 1 auto; padding-right: 52px; }
dialog.role-labels-dlg input { background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 4px; padding: 5px 8px; font: inherit; }
dialog.role-labels-dlg input:focus { outline: none; border-color: var(--accent); }
dialog.role-labels-dlg .rlbl-count { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; pointer-events: none; }
dialog.role-labels-dlg .rlbl-count.rlbl-count-over { color: var(--danger); font-weight: 600; }

/* Squad Builder per-member role editor */
dialog.member-edit-dlg { min-width: 380px; max-width: 480px; }
dialog.member-edit-dlg .med-fieldset { border: 1px solid var(--line); border-radius: 6px; padding: 10px 14px; margin: 0 0 12px; }
dialog.member-edit-dlg .med-fieldset legend { color: var(--muted); padding: 0 6px; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
dialog.member-edit-dlg .med-roles { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 14px; align-items: center; }
dialog.member-edit-dlg .med-roles .rolerow { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; }
dialog.member-edit-dlg .rolerow { display: flex; align-items: center; gap: 8px; }
dialog.member-edit-dlg select { background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 4px; padding: 3px 6px; }
dialog.member-edit-dlg select:disabled { opacity: .45; }

/* Home / dashboard */
.hero { position: relative; border: 1px solid var(--line); border-radius: 10px; min-height: 170px; margin: 16px 0 18px; display: flex; align-items: flex-end; overflow: hidden;
  background: linear-gradient(135deg, var(--panel2), var(--panel)); background-size: cover; background-position: center; }
.hero.has-img { min-height: 260px; }
.hero-overlay { width: 100%; padding: 16px 22px; background: linear-gradient(0deg, rgba(0,0,0,.7), rgba(0,0,0,.05)); }
.hero-overlay h1 { margin: 0; font-size: 30px; }
.hero-overlay p, .hero-overlay .hero-desc { margin: 4px 0 0; font-size: 14px; color: rgba(255,255,255,.85); }
.hero .faction-icon { position: absolute; top: 10px; right: 12px; width: 56px; height: 56px; object-fit: contain; filter: drop-shadow(0 1px 3px rgba(0,0,0,.6)); z-index: 2; }
.hero .region-badge { position: absolute; top: 12px; left: 12px; padding: 3px 10px; font: 600 13px/1 system-ui, sans-serif; letter-spacing: .05em; color: #fff; background: rgba(0,0,0,.55); border: 1px solid rgba(255,255,255,.25); border-radius: 4px; z-index: 2; }
.stats { display: flex; flex-wrap: wrap; gap: 14px; }
.stat { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 14px 18px; min-width: 130px; flex: 1; text-align: center; }
.stat-num { font-size: 26px; font-weight: 700; line-height: 1.1; }
.stat-lbl { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .05em; margin-top: 5px; }

.directory-filter { margin-bottom: 12px; align-items: center; }
.directory-filter label { display: inline-flex; align-items: center; gap: 6px; margin: 0; }

/* Public-clan directory cards */
.clan-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
/* Public-clan directory: cap the visible area at ~16 cards (4x4 on a typical
   desktop) and scroll the rest. The wrapper sits between the filter form
   and the card grid so the filter row stays sticky at the top of the card. */
.clan-grid-scroll { max-height: min(900px, 80vh); overflow-y: auto; padding-right: 6px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding-top: 8px; padding-bottom: 8px; }
.clan-grid-scroll::-webkit-scrollbar { width: 10px; }
.clan-grid-scroll::-webkit-scrollbar-track { background: transparent; }
.clan-grid-scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 5px; }
.clan-grid-scroll::-webkit-scrollbar-thumb:hover { background: var(--panel2); }
.clan-grid-meta { color: var(--muted); font-size: .85em; margin-top: 8px; text-align: right; }
.clan-card { display: flex; flex-direction: column; background: var(--panel2); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.clan-thumb { position: relative; height: 100px; background: linear-gradient(135deg, var(--panel), var(--panel2)); background-size: cover; background-position: center; border-bottom: 1px solid var(--line); }
.clan-thumb.has-img { height: 120px; }
.clan-thumb .faction-icon { position: absolute; top: 6px; right: 8px; width: 32px; height: 32px; object-fit: contain; filter: drop-shadow(0 1px 2px rgba(0,0,0,.6)); }
.clan-thumb .region-badge { position: absolute; top: 6px; left: 8px; padding: 2px 7px; font: 600 11px/1 system-ui, sans-serif; letter-spacing: .05em; color: #fff; background: rgba(0,0,0,.6); border: 1px solid rgba(255,255,255,.25); border-radius: 3px; }
.clan-desc { font-size: 13px; color: var(--text); margin: 4px 0 6px; line-height: 1.35; }
.clan-body { padding: 10px 12px; }
.clan-name { font-weight: 600; font-size: 15px; margin-bottom: 4px; }
.clan-stats { font-size: 12px; line-height: 1.5; }
.clan-cta { margin-top: 10px; }
.btn.small.apply-open { background: var(--ok); color: #06231a; border: 0; }
.btn.small.apply-open:hover { filter: brightness(1.08); text-decoration: none; }
.btn.small.apply-closed { background: var(--danger); color: #2a0808; border: 0; cursor: not-allowed; opacity: .85; }

/* Status pills (integration card) */
.pill-ok, .pill-warn, .pill-err { display: inline-block; padding: 1px 8px; border-radius: 10px; font-weight: 600; font-size: 12px; }
.pill-ok   { background: #163021; color: var(--ok);     border: 1px solid #2c5b3d; }
.pill-warn { background: #3a2f1b; color: #e0b352;       border: 1px solid #6b572c; }
.pill-err  { background: #3a1b1b; color: var(--danger); border: 1px solid #5a2b2b; }

/* Username in the topbar links to the profile page */
.topbar .who .profile-link { color: var(--text); border-bottom: 1px dashed transparent; }
.topbar .who .profile-link:hover { border-bottom-color: var(--muted); text-decoration: none; }

/* Help link in the userbox — sits between the username block and Sign out. */
.topbar .help-link { padding: 4px 10px; border-radius: 6px; color: var(--muted); background: transparent; border: 1px solid var(--line); font-size: .9em; }
.topbar .help-link:hover { background: var(--panel2); color: var(--text); text-decoration: none; }
.topbar .help-link.active { background: var(--panel2); color: var(--text); }

/* Members tab — clickable name -> Stalcraft profile modal */
button.member-name-link { -webkit-appearance: none; appearance: none; background: transparent; border: 0; padding: 0; font: inherit; font-weight: 600; color: var(--text); cursor: pointer; border-bottom: 1px dashed var(--line); }
button.member-name-link:hover { color: var(--accent); border-bottom-color: var(--accent); }

dialog.stats-dialog { background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: 10px; padding: 18px 22px 20px; min-width: 460px; max-width: 720px; box-shadow: 0 10px 40px rgba(0,0,0,.5); }
dialog.stats-dialog::backdrop { background: rgba(0,0,0,.55); }
dialog.stats-dialog .stats-close-form { float: right; margin: -6px -10px 0 8px; }
dialog.stats-dialog .stats-close { background: transparent; color: var(--muted); border: 0; font-size: 22px; line-height: 1; padding: 4px 8px; cursor: pointer; }
dialog.stats-dialog .stats-close:hover { color: var(--text); }
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; margin-top: 10px; }
.stats-grid .stat-cell { background: var(--panel2); border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; }
.stats-grid .stat-num { font-size: 18px; font-weight: 700; line-height: 1.1; }
.stats-grid .stat-lbl { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .04em; margin-top: 2px; }
.stats-grid .stat-num.kd-good, td.kd-good { color: var(--ok); font-weight: 600; }
.stats-grid .stat-num.kd-low,  td.kd-low  { color: var(--danger); font-weight: 600; }
.stats-grid .stat-num.kd-gold, td.kd-gold { color: #f5c842; font-weight: 700; text-shadow: 0 0 6px rgba(245,200,66,.25); }

/* Performance session note */
.session-note { background: var(--panel2); border-left: 3px solid var(--accent); border-radius: 0 6px 6px 0; padding: 6px 10px; margin: 8px 0 12px; font-size: 13px; }
.session-note-inline { color: var(--accent); font-weight: 500; }
/* Performance session unique ID (e.g. CR0001) — for cross-tool reference. */
.session-code-badge { display: inline-block; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.85em; font-weight: 700; letter-spacing: .02em; color: #f5c842; background: rgba(245,200,66,.12); border: 1px solid rgba(245,200,66,.4); border-radius: 4px; padding: 1px 7px; vertical-align: 2px; user-select: all; cursor: text; }

/* Site administrator UI */
.topbar .tabs a.admin-tab { color: #f5c842; }
.topbar .tabs a.admin-tab.active { background: rgba(245,200,66,.15); color: #f5c842; }
.role.role-site { background: #4a3a12; border-color: #6b572c; color: #f5c842; }
.manage-banner { max-width: 1200px; margin: 10px auto 0; padding: 8px 14px; border-radius: 6px; background: #2f2710; border: 1px solid #6b572c; color: #f5c842; display: flex; align-items: center; gap: 14px; justify-content: space-between; flex-wrap: wrap; }
.manage-banner button.link { color: #f5c842; text-decoration: underline; }

/* Top-3 trophy indicators in Performance closed-session tables */
.medal { display: inline-block; font-size: 13px; margin-left: 3px; vertical-align: -1px; line-height: 1; }

/* Victory podium on /performance/recognition */
.podium { display: flex; justify-content: center; align-items: flex-end; gap: 18px; padding: 32px 12px 4px; flex-wrap: wrap; }
.podium-place { display: flex; flex-direction: column; align-items: stretch; width: 220px; max-width: 100%; }
.podium-pos-1 { order: 2; }
.podium-pos-2 { order: 1; }
.podium-pos-3 { order: 3; }
.podium-info { text-align: center; padding: 0 6px 12px; }
.podium-cat { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-bottom: 6px; }
.podium-name { font-weight: 700; font-size: 16px; color: var(--text); margin-bottom: 4px; word-break: break-word; }
.podium-stat { font-size: 26px; font-weight: 800; line-height: 1.1; margin-bottom: 4px; }
.podium-sub { font-size: 11px; }
.podium-pos-1 .podium-stat { color: #ffd24a; }
.podium-pos-2 .podium-stat { color: #d3dae3; }
.podium-pos-3 .podium-stat { color: #d28b5a; }
.platform { width: 100%; border-radius: 8px 8px 0 0; display: flex; align-items: flex-start; justify-content: center; padding-top: 14px; box-shadow: inset 0 -10px 22px rgba(0,0,0,.28); }
.platform .num { font-size: 44px; font-weight: 900; color: rgba(0,0,0,.42); line-height: 1; }
.platform-1 { height: 170px; background: linear-gradient(180deg, #ffd24a 0%, #c4881a 100%); }
.platform-2 { height: 130px; background: linear-gradient(180deg, #e2e7ec 0%, #8b96a3 100%); }
.platform-3 { height: 95px;  background: linear-gradient(180deg, #d99a6a 0%, #8c5827 100%); }
@media (max-width: 720px) {
  .podium { flex-direction: column; align-items: stretch; gap: 14px; }
  .podium-place { order: 0 !important; width: 100%; }
  .platform { height: 56px !important; padding-top: 12px; }
  .platform .num { font-size: 30px; }
}

/* Community tools strip at the bottom of the public landing page. */
.community-tools { margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--line); text-align: center; }
.community-tools h2 { margin: 0 0 4px; font-size: 16px; }
.community-tools-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 12px; justify-content: center; }
a.community-tool { display: inline-flex; align-items: center; gap: 10px; padding: 10px 16px; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; color: var(--text); text-decoration: none; transition: border-color .15s, background .15s, transform .12s; }
a.community-tool:hover { border-color: var(--accent); background: var(--panel2); transform: translateY(-1px); text-decoration: none; }
.community-tool-icon { width: 22px; height: 22px; display: inline-flex; color: var(--accent); }
.community-tool-icon svg { width: 100%; height: 100%; display: block; }
.community-tool-label { font-weight: 600; font-size: 14px; }

/* Admin editor for the community-tools list. */
.ct-edit-form { border: 1px solid var(--line); border-radius: 8px; padding: 12px; margin-top: 10px; background: var(--panel2); }
.ct-edit-row { display: flex; gap: 14px; align-items: flex-start; }
.ct-edit-preview { flex: 0 0 56px; width: 56px; height: 56px; display: flex; align-items: center; justify-content: center; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; color: var(--accent); }
.ct-edit-preview svg { width: 32px; height: 32px; }
.ct-edit-preview-empty { color: var(--muted); font-size: 11px; letter-spacing: .08em; }
.ct-edit-fields { flex: 1; display: grid; gap: 8px; min-width: 0; }
.ct-edit-fields label { display: block; font-size: 12px; color: var(--muted); }
.ct-edit-fields input, .ct-edit-fields textarea { display: block; width: 100%; margin-top: 3px; font: inherit; background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 6px 8px; }
.ct-edit-fields textarea { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 12px; line-height: 1.4; }

/* First-sign-in welcome popup (also used by the Site Admin "Preview popup" button). */
body.welcome-locked { overflow: hidden; }
.welcome-overlay { position: fixed; inset: 0; background: rgba(8,11,15,.78); display: flex; align-items: center; justify-content: center; padding: 24px; z-index: 9000; }
.welcome-modal { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; max-width: 580px; width: 100%; max-height: 85vh; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 18px 50px rgba(0,0,0,.55); }
.welcome-modal h2 { margin: 0; padding: 18px 22px 12px; font-size: 18px; border-bottom: 1px solid var(--line); }
.welcome-modal .welcome-body { padding: 16px 22px; overflow-y: auto; line-height: 1.55; white-space: pre-wrap; flex: 1; }
.welcome-modal .welcome-foot { padding: 12px 22px; border-top: 1px solid var(--line); display: flex; justify-content: flex-end; gap: 10px; align-items: center; margin: 0; }
.welcome-modal .welcome-preview-tag { color: #f5c842; font-size: 11px; text-transform: uppercase; letter-spacing: .08em; margin-right: auto; border: 1px solid #f5c842; padding: 3px 8px; border-radius: 999px; }
.welcome-modal .btn-accept { background: var(--ok); color: #0b1118; padding: 9px 22px; border-radius: 6px; border: 0; font: 600 14px/1 inherit; cursor: pointer; }
.welcome-modal .btn-accept:hover { filter: brightness(1.08); }

/* Medal tally table on /performance/recognition */
table.medal-tally { width: 100%; }
table.medal-tally th .medal-icon { margin-right: 4px; }
table.medal-tally td.count-gold   { color: #ffd24a; font-weight: 700; }
table.medal-tally td.count-silver { color: #d3dae3; font-weight: 700; }
table.medal-tally td.count-bronze { color: #d28b5a; font-weight: 700; }

/* Remove-member ✕ on finalized sessions */
button.remove-x { -webkit-appearance: none; appearance: none; background: transparent; border: 0; padding: 0 4px; margin-left: 6px; font: inherit; font-size: 11px; line-height: 1; color: var(--muted); cursor: pointer; vertical-align: 1px; }
button.remove-x:hover { color: var(--danger); }

/* Click-to-sort headers (Performance closed-session tables) */
table.sortable-table th.sortable { cursor: pointer; user-select: none; }
table.sortable-table th.sortable:hover { color: var(--accent); }
table.sortable-table th.sortable .sort-arrow { color: var(--accent); font-size: 11px; }

/* Tab badge for unread counts (e.g. pending applications on the Recruitment tab) */
.topbar .tabs a .tab-badge { display: inline-block; background: var(--accent); color: #06203b; font-size: 11px; font-weight: 700; padding: 0 6px; border-radius: 9px; margin-left: 4px; vertical-align: 1px; }

/* Recruitment cards */
.card.application .app-head { gap: 12px; align-items: flex-start; }
.card.application .app-note { white-space: pre-wrap; background: var(--panel2); border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; margin: 10px 0; color: var(--text); }

/* Match history */
.record { font-size: 15px; }
.result { font-weight: 600; }
.result-win { color: var(--ok); }
.result-loss { color: var(--danger); }
.result-tie { color: var(--muted); }
img.thumb { height: 36px; border: 1px solid var(--line); border-radius: 4px; vertical-align: middle; }
table.grid td.notes { white-space: pre-wrap; max-width: 360px; color: var(--muted); }

/* Private-beta invite codes (Site Admin) */
code.invite-code { font-family: ui-monospace, Consolas, monospace; font-size: 14px; font-weight: 600; letter-spacing: .5px; background: var(--bg); border: 1px solid var(--line); border-radius: 5px; padding: 3px 8px; color: var(--accent); }

/* Account search filter (Site Admin) */
.account-search { display: flex; align-items: center; gap: 10px; margin: 4px 0 12px; }
.account-search input { flex: 1; max-width: 340px; padding: 7px 10px; background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 6px; font: inherit; }
.account-search input:focus { outline: none; border-color: var(--accent); }
.att-search { flex: 1 1 220px; max-width: 320px; padding: 7px 10px; background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 6px; font: inherit; }
.att-search:focus { outline: none; border-color: var(--accent); }
.att-ll { display: block; margin-top: 2px; font-size: 11px; }
/* Force "Record Attendance" onto its own row and center it horizontally even
   when the header row above it has wrapped (search + auto-fill controls). */
.att-record-wrap { flex: 1 0 100%; display: flex; justify-content: center; margin-top: 4px; }

/* Admin-issued password reset link reveal */
.act-sep { color: var(--line); margin: 0 8px 0 -4px; }
.reset-link-box { border: 1px solid var(--accent); background: var(--panel2); border-radius: 8px; padding: 12px 14px; margin: 4px 0 16px; }
.reset-link-box .rlb-head { font-size: 14px; margin-bottom: 2px; }
.reset-link-box .rlb-row { display: flex; gap: 8px; align-items: center; margin: 8px 0 4px; }
.reset-link-box .rlb-row input { flex: 1; font-family: ui-monospace, Consolas, monospace; font-size: 12px; padding: 7px 9px; background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 6px; }

/* Auth forms (register / sign in): stacked, full-width, centered card */
.auth-card h1, .auth-card > p { text-align: center; }
.auth-card form { margin-top: 14px; }
.auth-card .field { margin: 12px 0; text-align: left; }
.auth-card .field label { display: block; margin: 0 0 4px; font-size: 13px; color: var(--muted); }
.auth-card .field input { display: block; width: 100%; min-width: 0; box-sizing: border-box; padding: 9px 10px; }
.auth-card .pw-wrap { display: flex; gap: 8px; align-items: stretch; }
.auth-card .pw-wrap input { flex: 1; }
.auth-card .pw-toggle { flex: 0 0 auto; white-space: nowrap; }
.auth-card .auth-submit { width: 100%; margin-top: 8px; padding: 10px 14px; }

/* "Continue with EXBO" button — flex row with logo + label, dark navy so the
   EXBO logo reads cleanly (the global .btn accent-blue blended with it) */
.exbo-btn { display: flex; align-items: center; justify-content: center; gap: 10px; text-decoration: none; background: #0e1a2c; color: #fff; border: 1px solid #1f2d44; }
.exbo-btn:hover { background: #1a2a44; }
.exbo-btn .exbo-logo { height: 22px; width: auto; display: block; }

/* High-resolution monitor scaling — most of the CSS uses px which doesn't
   auto-grow on 1440p / 4K monitors at 100% OS scaling, so users report tiny
   text. These breakpoints scale the whole UI (text + layout) proportionally
   via `zoom`, leaving the 1080p baseline untouched. */
@media (min-width: 2200px) { body { zoom: 1.15; } }
@media (min-width: 2800px) { body { zoom: 1.30; } }
@media (min-width: 3600px) { body { zoom: 1.50; } }

/* Hamburger toggle: hidden on desktop, used by the mobile media query below.
   CSS-only — the checkbox `:checked` state drives the nav visibility. */
.nav-toggle, .nav-toggle-cb { display: none; }

/* Clan war tactical map preview (/maps/lowlands etc.). The canvas overlay
   sits exactly on top of the base map (a div with background-image) and
   shares the same scaled size, so pointer coords translate cleanly into the
   native image coordinate space. The map itself is rendered as a CSS
   background-image — no <img> element exists for the browser to offer
   "Save image as" on. The wrap's aspect-ratio is set inline per-map. */
.map-canvas-wrap {
  position: relative;
  display: block;
  width: 100%;
  /* No max-width here — the JS sets width: (zoom × 100)% and that needs
     to be allowed to exceed the viewport so overflow scrolls properly. */
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: var(--panel);
  box-shadow: 0 4px 16px rgba(0,0,0,.3);
  margin: 0 auto; /* centers the wrap when zoom < 100% */
}
.map-canvas-wrap .map-base {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  pointer-events: none;
}
.map-canvas-wrap .map-overlay {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  touch-action: none;
}
/* Tool-driven cursor + canvas hit-testing. In Pan mode the canvas is set
   to pointer-events:none in JS so clicks pass through to the wrap, which
   runs the pan handler. In Draw mode the canvas owns the cursor. */
.map-canvas-wrap.tool-pan  { cursor: grab; }
.map-canvas-wrap.tool-pan.panning { cursor: grabbing; }
.map-canvas-wrap.tool-draw .map-overlay { cursor: crosshair; }

/* Tool selector button group at the start of the toolbar. */
.tool-group {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
  background: var(--panel2);
}
.tool-btn {
  background: transparent;
  border: 0;
  color: var(--text);
  padding: 5px 12px;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  line-height: 1.2;
}
.tool-btn + .tool-btn { border-left: 1px solid var(--line); }
.tool-btn:hover { background: var(--panel); }
.tool-btn.active {
  background: var(--accent);
  color: #06203b;
}

/* Dim the colour/width controls when not in Draw mode so it's obvious they
   only apply to drawing. */
.draw-only.disabled { opacity: 0.45; pointer-events: none; }
.map-toolbar label { display: inline-flex; align-items: center; gap: 6px; margin: 0; }
.map-toolbar input[type=color] { width: 36px; height: 28px; padding: 0; border: 1px solid var(--line); border-radius: 4px; background: transparent; cursor: pointer; }
.map-toolbar input[type=range] { width: 140px; }

/* =========================== Marker palette ============================
   The white-silhouette icon PNGs are recolored with CSS mask-image +
   background-color so a single asset can render in any team color.
   The four corner brackets around each placed marker are pure CSS
   L-shapes (no asset needed). */
.marker-palette {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 6px 0 14px;
  padding: 10px 12px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
}
.palette-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}
.palette-row-hint { text-align: center; }
.marker-palette .palette-sep { margin-left: 4px; }
.palette-icon {
  width: 38px; height: 38px;
  padding: 4px;
  background: var(--panel2);
  border: 1px solid var(--line);
  border-radius: 6px;
  cursor: grab;
  display: inline-flex; align-items: center; justify-content: center;
  touch-action: none;
}
.palette-icon:hover { border-color: var(--accent); }
.palette-icon:active { cursor: grabbing; }
.palette-icon .palette-icon-glyph {
  display: block;
  width: 100%; height: 100%;
  background-color: var(--text);
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}
.palette-icon[data-icon="home"] .palette-icon-glyph { -webkit-mask-image: url('/static/maps/icons/home.png'); mask-image: url('/static/maps/icons/home.png'); }
.palette-icon[data-icon="camp"] .palette-icon-glyph { -webkit-mask-image: url('/static/maps/icons/camp.png'); mask-image: url('/static/maps/icons/camp.png'); }
.palette-icon[data-icon="halt"] .palette-icon-glyph { -webkit-mask-image: url('/static/maps/icons/halt.png'); mask-image: url('/static/maps/icons/halt.png'); }
.palette-icon[data-icon="barricade-hesco"]          .palette-icon-glyph { -webkit-mask-image: url('/static/maps/icons/barricade-hesco.svg?v=2');          mask-image: url('/static/maps/icons/barricade-hesco.svg?v=2'); }
.palette-icon[data-icon="barricade-metal-small"]    .palette-icon-glyph { -webkit-mask-image: url('/static/maps/icons/barricade-metal-small.svg?v=2');    mask-image: url('/static/maps/icons/barricade-metal-small.svg?v=2'); }
.palette-icon[data-icon="barricade-metal-c"]        .palette-icon-glyph { -webkit-mask-image: url('/static/maps/icons/barricade-metal-c.svg?v=2');        mask-image: url('/static/maps/icons/barricade-metal-c.svg?v=2'); }
.palette-icon[data-icon="barricade-metal-c-window"] .palette-icon-glyph { -webkit-mask-image: url('/static/maps/icons/barricade-metal-c-window.svg?v=2'); mask-image: url('/static/maps/icons/barricade-metal-c-window.svg?v=2'); }

.palette-color {
  width: 22px; height: 22px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid var(--line);
  cursor: pointer;
  transition: transform .12s, border-color .12s;
}
.palette-color:hover { transform: scale(1.1); }
.palette-color.active { border-color: var(--accent); transform: scale(1.18); }

/* Tint colors shared by palette swatches AND placed markers. */
.tint-white  { background-color: #ffffff; }
.tint-red    { background-color: #ff3b3b; }
.tint-blue   { background-color: #4aa9ff; }
.tint-green  { background-color: #5fd38a; }
.tint-orange { background-color: #ff9034; }

/* ========================= Markers on the map ==========================
   The markers container is absolutely positioned over the canvas and the
   base image. Each marker is positioned via percentage coords so it scales
   with the map at any viewport size. */
.map-markers {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  pointer-events: none; /* container is just a hit-test passthrough */
}
.marker {
  position: absolute;
  width:  calc(60px * var(--scale, 1));
  height: calc(60px * var(--scale, 1));
  /* --rotation defaults to 0deg; only barricade markers wire up a wheel handler
     that updates it (see attachWheelRotation in maps-show.ejs). The corner
     brackets and drag-to-move math stay rotation-agnostic. */
  transform: translate(-50%, -50%) rotate(var(--rotation, 0deg));
  pointer-events: auto;
  cursor: grab;
  touch-action: none;
}
.marker.dragging { cursor: grabbing; }
.marker.resizing { cursor: nwse-resize; }
/* Soft dark backing so white silhouettes stay readable on light terrain. */
.marker::before {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width:  calc(46px * var(--scale, 1));
  height: calc(46px * var(--scale, 1));
  background: rgba(0,0,0,.42);
  border-radius: 8px;
  pointer-events: none;
}
.marker .marker-icon {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width:  calc(38px * var(--scale, 1));
  height: calc(38px * var(--scale, 1));
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  /* Background-color = tint, applied via .tint-* class */
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.8));
}
.icon-home { -webkit-mask-image: url('/static/maps/icons/home.png'); mask-image: url('/static/maps/icons/home.png'); }
.icon-camp { -webkit-mask-image: url('/static/maps/icons/camp.png'); mask-image: url('/static/maps/icons/camp.png'); }
.icon-halt { -webkit-mask-image: url('/static/maps/icons/halt.png'); mask-image: url('/static/maps/icons/halt.png'); }
.icon-barricade-hesco          { -webkit-mask-image: url('/static/maps/icons/barricade-hesco.svg?v=2');          mask-image: url('/static/maps/icons/barricade-hesco.svg?v=2'); }
.icon-barricade-metal-small    { -webkit-mask-image: url('/static/maps/icons/barricade-metal-small.svg?v=2');    mask-image: url('/static/maps/icons/barricade-metal-small.svg?v=2'); }
.icon-barricade-metal-c        { -webkit-mask-image: url('/static/maps/icons/barricade-metal-c.svg?v=2');        mask-image: url('/static/maps/icons/barricade-metal-c.svg?v=2'); }
.icon-barricade-metal-c-window { -webkit-mask-image: url('/static/maps/icons/barricade-metal-c-window.svg?v=2'); mask-image: url('/static/maps/icons/barricade-metal-c-window.svg?v=2'); }

/* Barricades render as raw shapes on the map by default — no dark backdrop or
   corner brackets — so they read as map objects rather than POI markers. The
   backdrop and corners fade back in on hover, and stay visible while the user
   is actively dragging or resizing so the operation can't drop them mid-motion.
   pointer-events on the corners is also gated by visibility so the user can't
   accidentally click an invisible corner. */
.marker--barricade::before { opacity: 0; transition: opacity .12s ease-out; }
.marker--barricade .marker-corner {
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s ease-out;
}
.marker--barricade:hover::before,
.marker--barricade.dragging::before,
.marker--barricade.resizing::before { opacity: 1; }
.marker--barricade:hover .marker-corner,
.marker--barricade.dragging .marker-corner,
.marker--barricade.resizing .marker-corner {
  opacity: 1;
  pointer-events: auto;
}

/* Letter point markers (A-I). Same corner brackets + dark backing as the
   silhouette icons, but the center holds rendered text instead of a masked
   PNG. Tint classes set the text colour via specificity overrides. */
.marker .marker-letter {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width:  calc(38px * var(--scale, 1));
  height: calc(38px * var(--scale, 1));
  display: flex; align-items: center; justify-content: center;
  font-weight: 800;
  font-size: calc(24px * var(--scale, 1));
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  line-height: 1;
  background: transparent !important;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.85));
  pointer-events: none;
  user-select: none;
}
.marker .marker-letter.tint-white  { color: #ffffff; }
.marker .marker-letter.tint-red    { color: #ff3b3b; }
.marker .marker-letter.tint-blue   { color: #4aa9ff; }
.marker .marker-letter.tint-green  { color: #5fd38a; }
.marker .marker-letter.tint-orange { color: #ff9034; }

/* The four L-shaped corner brackets — each is a small box with only two
   adjacent borders drawn, creating an inward-pointing L. They're also the
   resize handles for the placed marker: grab a corner and drag to scale. */
.marker-corner {
  position: absolute;
  width:  calc(9px * var(--scale, 1));
  height: calc(9px * var(--scale, 1));
  border: 2px solid white;
  pointer-events: auto;
  touch-action: none;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,.7));
}
.marker-corner.tl { top: 0;    left: 0;    border-right: 0; border-bottom: 0; cursor: nwse-resize; }
.marker-corner.tr { top: 0;    right: 0;   border-left: 0;  border-bottom: 0; cursor: nesw-resize; }
.marker-corner.bl { bottom: 0; left: 0;    border-right: 0; border-top: 0;    cursor: nesw-resize; }
.marker-corner.br { bottom: 0; right: 0;   border-left: 0;  border-top: 0;    cursor: nwse-resize; }

/* Ghost marker (follows cursor while dragging from the palette). */
.marker-ghost {
  position: fixed;
  width: 60px; height: 60px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 9000;
  opacity: 0.85;
}
.marker-ghost.text-ghost {
  width: auto; height: auto;
  padding: 4px 10px;
  background: rgba(0,0,0,.75);
  border: 1px solid #fff;
  border-radius: 4px;
  color: #fff;
  font-weight: 600;
}

/* ============================ View controls ===========================
   .map-stage hosts the scrollable viewport + a floating right-side rail.
   The wrap inside the viewport gets width: (zoom × 100)% via JS, which
   produces real layout overflow → proper scrollbars on the viewport. */
.map-stage {
  position: relative;
}
.map-viewport {
  width: 100%;
  max-height: 85vh;
  overflow: auto;
  border-radius: 8px;
}

/* Floating zoom rail — vertical stack at the top-right of the map area. */
.map-zoom-rail {
  position: absolute;
  right: 12px; top: 12px;
  z-index: 60;
  display: flex; flex-direction: column; align-items: center;
  gap: 6px;
  padding: 8px 6px;
  background: rgba(15, 18, 25, .82);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0,0,0,.4);
}
.map-zoom-btn {
  width: 30px; height: 28px;
  background: var(--panel2);
  border: 1px solid var(--line);
  color: var(--text);
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px; font-weight: 700; line-height: 1;
  padding: 0;
}
.map-zoom-btn:hover { border-color: var(--accent); }
.map-zoom-btn:active { background: var(--panel); }
.map-zoom-slider {
  /* Vertical orientation with max value at the top. */
  writing-mode: vertical-rl;
  -webkit-appearance: slider-vertical;
  appearance: slider-vertical;
  width: 16px;
  height: 150px;
  margin: 4px 0;
  background: transparent;
  cursor: pointer;
}
.map-zoom-display {
  min-width: 44px; text-align: center;
  font-size: 11px; font-variant-numeric: tabular-nums;
  color: var(--text);
  background: var(--panel2);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 3px 4px;
}

/* Gridlines overlay — sized in CSS pixels of the wrap's layout box. At any
   `zoom` value the grid scales with the rest of the map content. */
.map-grid {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  background-image:
    linear-gradient(to right,  rgba(255,255,255,.30) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.30) 1px, transparent 1px);
  background-size: 64px 64px;
  display: none;
}
.map-grid.visible { display: block; }

/* =========================== Text marker ============================
   A draggable sticky-note with corner resize handles (same .marker-corner
   L-shapes as the icon markers). Every interior dimension uses calc with
   --scale so resizing the corners enlarges the font + paddings together. */
.text-marker {
  position: absolute;
  transform: translate(-50%, -50%);
  background: rgba(0,0,0,.78);
  border: 1px solid #ffffff;
  border-radius: 5px;
  color: #fff;
  font-size: calc(14px * var(--scale, 1));
  line-height: 1.3;
  pointer-events: auto;
  z-index: 5;
  box-shadow: 0 2px 6px rgba(0,0,0,.45);
  min-width: calc(80px * var(--scale, 1));
}
.text-marker-handle {
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(1px * var(--scale, 1)) calc(4px * var(--scale, 1));
  background: rgba(255,255,255,.18);
  border-bottom: 1px solid rgba(255,255,255,.25);
  border-radius: 4px 4px 0 0;
  cursor: grab;
  user-select: none;
  touch-action: none;
}
.text-marker-handle.dragging { cursor: grabbing; }
.text-marker-grip {
  display: inline-block;
  width:  calc(30px * var(--scale, 1));
  height: calc(4px  * var(--scale, 1));
  background: rgba(255,255,255,.55);
  border-radius: 2px;
}
.text-marker-del {
  background: none; border: 0; color: #fff; cursor: pointer;
  padding: 0 calc(5px * var(--scale, 1));
  line-height: 1;
  font-size: calc(15px * var(--scale, 1));
  font-weight: 700;
}
.text-marker-del:hover { color: var(--danger); }
.text-marker-body {
  padding: calc(4px * var(--scale, 1)) calc(8px * var(--scale, 1));
  outline: none;
  white-space: pre-wrap;
  min-width:  calc(60px * var(--scale, 1));
  min-height: calc(18px * var(--scale, 1));
  cursor: text;
}
.text-marker-body:empty::before {
  content: 'Click to edit';
  color: rgba(255,255,255,.45);
}
/* The .marker-corner brackets inside a text-marker sit at the bounding-box
   corners so drag-resize behaviour matches the icon markers. */
.text-marker .marker-corner { z-index: 2; }

/* The "T" text-palette button has no mask-image — render the glyph as
   actual text so it stays crisp at any size. */
.palette-icon--text .palette-icon-text {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  font-weight: 700; font-size: 22px;
  font-family: Georgia, "Times New Roman", serif;
  color: var(--text);
  line-height: 1;
}

/* Letter palette buttons (A-I) — solid bold letter glyph on the standard
   palette-icon dark backdrop. */
.palette-icon--letter .palette-icon-letter {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  font-weight: 800; font-size: 19px;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--text);
  line-height: 1;
}

/* /maps index — centered card grid with thumbnail + title. */
.maps-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 18px;
  margin: 24px auto 0;
  max-width: 1100px;
  justify-content: center;
}
.map-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
  color: var(--text);
  text-decoration: none;
  transition: border-color .15s, transform .12s, box-shadow .15s;
}
a.map-card:hover,
.map-card-saved:not(.map-card-locked):hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(0,0,0,.4);
  text-decoration: none;
}
/* Saved-card extras: clickable thumbnail link, sub-line under the title, action row. */
.map-card-thumb-link { display: block; width: 100%; line-height: 0; }
.map-card-saved .map-card-name { padding-bottom: 4px; }
.map-card-sub { width: 100%; text-align: center; padding: 0 10px 10px; }
.map-card-actions {
  width: 100%;
  display: flex; gap: 8px; justify-content: center;
  padding: 0 10px 12px;
}
.map-card-locked { opacity: .72; cursor: not-allowed; }
.map-card-locked .map-card-thumb { filter: grayscale(.4) brightness(.85); }
/* Index thumbnails are also rendered as background-image on the div itself
   (no <img> child), so right-click never offers "Save image as". */
.map-card-thumb {
  width: 100%;
  aspect-ratio: 4 / 3;
  background-color: var(--panel2);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.map-card-name {
  width: 100%;
  text-align: center;
  padding: 12px 10px;
  font-weight: 600;
  font-size: 15px;
  background: var(--panel);
}

/* Admin: /admin maps editor row. */
.map-admin-list { list-style: none; padding: 0; margin: 12px 0 0; display: flex; flex-direction: column; gap: 8px; }
.map-admin-row {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 10px;
  background: var(--panel2);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.map-admin-thumb {
  width: 56px; height: 42px;
  object-fit: cover;
  border-radius: 4px;
  background: var(--bg);
  flex: 0 0 auto;
}
.map-admin-edit { display: flex; gap: 6px; align-items: center; margin: 0; flex: 1 1 auto; min-width: 0; }
.map-admin-edit input[type=text] { flex: 1 1 auto; min-width: 0; }
.map-admin-row code { white-space: nowrap; }

/* === Resource drawer ===================================================
   A vertical "Resources" tab sits on the right edge of every page. Clicking
   it slides a small panel out from the right with curated outbound links.
   Pure CSS — the hidden checkbox in foot.ejs drives the open/close state. */
.resource-drawer-cb { display: none; }
.resource-drawer {
  position: fixed; right: 0; top: 50%; transform: translateY(-50%);
  z-index: 800; display: flex; align-items: stretch; pointer-events: none;
}
.resource-drawer-toggle, .resource-drawer-inner { pointer-events: auto; }
.resource-drawer-toggle {
  align-self: center; cursor: pointer; user-select: none;
  background: var(--panel2); color: var(--text);
  border: 1px solid var(--line); border-right: 0;
  border-radius: 6px 0 0 6px;
  padding: 18px 7px; font-size: 12px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  writing-mode: vertical-rl; text-orientation: mixed;
  box-shadow: -3px 0 10px rgba(0,0,0,.25);
  transition: background .15s, color .15s;
}
.resource-drawer-toggle:hover { background: var(--panel); color: var(--accent); }
.resource-drawer-cb:checked ~ .resource-drawer .resource-drawer-toggle { color: var(--accent); }
.resource-drawer-inner {
  width: 0; max-height: 70vh; overflow: hidden;
  background: var(--panel); border: 1px solid var(--line); border-right: 0;
  border-radius: 6px 0 0 6px;
  box-shadow: -6px 0 24px rgba(0,0,0,.35);
  transition: width .25s ease, padding .25s ease;
}
.resource-drawer-cb:checked ~ .resource-drawer .resource-drawer-inner {
  width: 280px; padding: 16px; overflow-y: auto;
}
.rd-section + .rd-section { margin-top: 18px; }
.rd-section a.rd-card + a.rd-card { margin-top: 8px; }
.resource-drawer-inner h3 {
  margin: 0 0 10px; font-size: 12px; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em; white-space: nowrap;
}
.rd-card-icon {
  width: 40px; height: 40px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px; background: var(--bg); color: var(--accent);
}
.rd-card-icon svg { width: 24px; height: 24px; display: block; }
a.rd-card {
  display: flex; align-items: center; gap: 10px;
  padding: 10px; background: var(--panel2);
  border: 1px solid var(--line); border-radius: 8px;
  color: var(--text); text-decoration: none;
  transition: border-color .15s, background .15s, transform .12s;
}
a.rd-card:hover { border-color: var(--accent); background: var(--bg); text-decoration: none; transform: translateY(-1px); }
.rd-card img {
  width: 40px; height: 40px; flex: 0 0 auto;
  border-radius: 6px; object-fit: cover; background: var(--bg);
}
.rd-card-text { min-width: 0; }
.rd-card-title { font-weight: 600; font-size: 14px; line-height: 1.2; }
.rd-card-sub { color: var(--muted); font-size: 12px; margin-top: 2px; }

/* === Mobile layout (≤768px) ===========================================
   Phase 1 mobile pass: collapse the topbar into a hamburger, stack the
   Attendance/Squads two-column layout, soften hero scaling, and let
   dialogs shrink to fit the viewport. Tables keep horizontal scroll —
   per-page card layouts are Phase 2. */
@media (max-width: 768px) {
  .page { padding: 0 10px 30px; }
  h1 { font-size: 18px; }

  /* Topbar */
  .topbar { padding: 8px 12px; gap: 8px; }
  .nav-toggle {
    display: inline-block; cursor: pointer; margin-left: auto;
    background: var(--panel2); color: var(--text);
    border: 1px solid var(--line); border-radius: 6px;
    padding: 6px 12px; font-size: 18px; line-height: 1;
    user-select: none;
  }
  .topbar .tabs {
    display: none; flex-basis: 100%; flex-direction: column;
    order: 10; gap: 2px; margin-top: 4px;
  }
  .nav-toggle-cb:checked ~ .tabs { display: flex; }
  .topbar .tabs a { padding: 10px 12px; border-radius: 6px; }

  /* Hover dropdowns -> always-visible nested stacks on touch */
  .topbar .tabs .tab-group { display: block; width: 100%; }
  .topbar .tabs .tab-group > a::after { display: none; }
  .topbar .tabs .tab-submenu {
    display: block; position: static; min-width: 0;
    background: transparent; border: 0; box-shadow: none;
    padding: 0 0 0 16px;
  }

  /* Userbox: full-width row below brand+hamburger */
  .topbar .userbox {
    flex-basis: 100%; margin-left: 0; order: 11;
    gap: 8px; flex-wrap: wrap; font-size: 13px;
  }

  /* Manage banner / flash */
  .manage-banner { flex-direction: column; align-items: flex-start; gap: 6px; }

  /* Two-column Attendance/Squads layout stacks vertically */
  .layout-split { flex-direction: column; }
  .layout-split .sidecol { width: 100%; flex: 0 0 auto; }
  .datelist { max-height: 180px; }

  /* Hero */
  .hero { min-height: 130px; }
  .hero.has-img { min-height: 180px; }
  .hero-overlay { padding: 12px 14px; }
  .hero-overlay h1 { font-size: 22px; }
  .hero .faction-icon { width: 36px; height: 36px; top: 8px; right: 8px; }

  /* Stat cards */
  .stat { min-width: 100px; padding: 10px 12px; }
  .stat-num { font-size: 20px; }

  /* Tighten table cells so horizontal scroll is shorter */
  table.grid th, table.grid td { padding: 4px 6px; font-size: 13px; }

  /* Form inputs: drop the 220px floor so they fit narrow screens */
  input[type=text], input[type=email], input[type=password] { min-width: 0; }

  /* Dialogs: shrink to viewport width */
  dialog.role-labels-dlg,
  dialog.member-edit-dlg,
  dialog.stats-dialog {
    min-width: 0; max-width: 95vw; margin: 12px auto;
  }

  /* Squad board collapses to a single column */
  .squad-board { grid-template-columns: minmax(0, 1fr); }

  /* Resource drawer: cap open width to viewport, slightly smaller toggle */
  .resource-drawer-toggle { padding: 14px 5px; font-size: 11px; }
  .resource-drawer-cb:checked ~ .resource-drawer .resource-drawer-inner {
    width: min(260px, calc(100vw - 60px));
  }
}
