/* ============================================================
   Saint Denis 100% — Red Dead Redemption 2 completion checklist
   Dark game-HUD aesthetic. No gradients, hairline borders.

   Red Dead Redemption 2 has no regions on the source site, so there is no
   region filter, no region column and no borough palette here — the same
   shape L.A. Noire and GTA V ship. Category chips take their dot hue inline
   from the map data's group colour (app.js), so no group ids are hard-coded
   in this file.
   ============================================================ */

:root {
  --bg:        #111214;
  --panel:     #1A1C20;
  --panel-2:   #1F2126;
  --text:      #EDEAE2;
  --muted:     #868D98;
  /* Red Dead Redemption 2 accent — sage chartreuse, the hunter/wilderness
     read. A hue family no other game owns: San Andreas' green is a saturated
     grass and this sits well to the yellow of it, so the two are told apart in
     the game switcher at a glance. Matched to map.css. */
  --accent:    #A6BF4B;
  --accent-hi: #C4DA6A;
  --accent-rgb: 166,191,75;
  --line:      #2A2D33;

  --sans: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --display: "Anton", "Arial Narrow", Impact, var(--sans);

  --radius: 6px;
  --wrap: 1280px;
}

*, *::before, *::after { box-sizing: border-box; }
/* The `hidden` attribute must win over any `display` this file sets. The UA's
   `[hidden] { display: none }` is a user-agent rule, so any author rule setting
   `display` on the same element beats it regardless of specificity; that is how
   an undismissable modal shipped on the hub. `.results[hidden]` and
   `.mbar-n[hidden]` below are the narrow patches this replaces. */
[hidden] { display: none !important; }


html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

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

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 60;
  background: var(--accent); color: #111214; font-weight: 600;
  padding: 10px 14px; border-radius: var(--radius); transition: top .15s;
}
.skip-link:focus { top: 12px; }

a { color: var(--accent); text-underline-offset: 2px; }
a:hover { color: var(--accent-hi); }

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

/* ---------------- HUD ---------------- */

.hud {
  position: sticky; top: 0; z-index: 40;
  background: rgba(17,18,20,.94);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.hud-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 28px; padding-top: 14px; padding-bottom: 14px;
  flex-wrap: wrap;
}

.hud-main { display: flex; align-items: center; gap: 18px; min-width: 0; }

.hud-pct {
  font-family: var(--display);
  font-size: clamp(44px, 6vw, 68px);
  line-height: .9;
  color: var(--accent);
  transform: skewX(-6deg);
  letter-spacing: .01em;
  font-variant-numeric: tabular-nums;
  min-width: 2.6ch;
  text-align: left;
}

.hud-meta { min-width: 0; }

.hud-title {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(18px, 2.2vw, 26px);
  letter-spacing: .085em;
  text-transform: uppercase;
  margin: 0 0 2px;
  transform: skewX(-6deg);
}

.hud-title-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

.page-nav { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; row-gap: 6px; }
.page-nav a, .page-nav span {
  font-size: 10.5px; letter-spacing: .13em; text-transform: uppercase;
  text-decoration: none; color: var(--muted);
  padding: 4px 8px; border: 1px solid var(--line); border-radius: 4px;
  white-space: nowrap;
}
.page-nav a:hover { color: var(--text); border-color: #3A3E46; }
.page-nav .here { color: #111214; background: var(--accent); border-color: var(--accent); font-weight: 600; }

.hud-sub {
  margin: 0 0 8px;
  font-size: 12.5px;
  color: var(--muted);
  letter-spacing: .04em;
  text-transform: uppercase;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.hud-sub .dot { color: var(--line); }
.hud-sub .num { color: var(--text); font-weight: 600; }

.hud-bar {
  width: min(280px, 46vw); height: 4px;
  background: var(--line); border-radius: 2px; overflow: hidden;
}
.hud-bar > span {
  display: block; height: 100%; width: 0%;
  background: var(--accent);
  transition: width .28s ease;
}

.hud-counters { display: flex; gap: 10px; flex-wrap: wrap; }

.counter {
  display: flex; align-items: center; gap: 10px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-left: 3px solid var(--c, var(--line));
  border-radius: var(--radius);
  padding: 8px 12px 8px 11px;
  min-width: 158px;
}
.counter-label {
  display: block;
  font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); white-space: nowrap;
}
.counter-val {
  font-family: var(--display);
  font-size: 19px; line-height: 1.15;
  letter-spacing: .04em;
  transform: skewX(-6deg);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.counter-val .of { color: var(--muted); }
.counter.full .counter-val { color: var(--accent); }
.counter-pip {
  width: 10px; height: 10px; flex: none;
  background: var(--ct, var(--muted));
  box-shadow: 0 0 0 3px rgba(255,255,255,.03);
}

.counter.tick { animation: tick .5s ease; }
@keyframes tick {
  0%   { background: rgba(var(--accent-rgb),.22); border-color: var(--accent); }
  40%  { background: rgba(var(--accent-rgb),.12); border-color: var(--accent); }
  100% { background: var(--panel); border-color: var(--line); }
}
.counter.tick .counter-val { animation: tickval .5s ease; }
@keyframes tickval {
  0%   { color: var(--accent); transform: skewX(-6deg) translateY(-2px); }
  100% { color: var(--text); transform: skewX(-6deg) translateY(0); }
}

/* ---------------- Panels ---------------- */

.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin: 20px 0;
}

main.wrap { padding-bottom: 40px; }

/* ---------------- Controls ---------------- */

.controls { padding: 4px 0 0; }

.toolrow {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 16px 18px;
  border-bottom: 1px solid var(--line);
}

.field { position: relative; display: flex; align-items: center; }

.search-field { flex: 1 1 260px; min-width: 200px; }
.search-ico {
  position: absolute; left: 11px; color: var(--muted); display: flex; pointer-events: none;
}

input[type="search"], select {
  width: 100%;
  background: #141518;
  border: 1px solid var(--line);
  color: var(--text);
  font-family: var(--sans);
  font-size: 14px;
  padding: 9px 12px;
  border-radius: var(--radius);
}
input[type="search"] { padding-left: 34px; }
input[type="search"]::placeholder { color: #6C737D; }
input[type="search"]:focus, select:focus { border-color: var(--accent); }
select { padding-right: 28px; cursor: pointer; }

.sort-mobile { display: none; }

/* switch */
.switch { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; user-select: none; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-track {
  width: 38px; height: 21px; background: #26282D; border: 1px solid var(--line);
  border-radius: 4px; position: relative; transition: background .15s, border-color .15s;
}
.switch-knob {
  position: absolute; top: 2px; left: 2px; width: 15px; height: 15px;
  background: var(--muted); border-radius: 2px; transition: transform .15s, background .15s;
}
.switch input:checked + .switch-track { background: rgba(var(--accent-rgb),.2); border-color: var(--accent); }
.switch input:checked + .switch-track .switch-knob { transform: translateX(17px); background: var(--accent); }
.switch input:focus-visible + .switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.switch-label { font-size: 13.5px; color: var(--muted); white-space: nowrap; }
.switch input:checked ~ .switch-label { color: var(--text); }

.tool-actions { display: flex; gap: 8px; margin-left: auto; flex-wrap: wrap; }

.btn {
  font-family: var(--sans);
  font-size: 12.5px; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--text);
  background: #202329;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 9px 14px;
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}
.btn:hover { background: #282C33; border-color: #3A3E46; }
.btn-danger:hover { color: #FF8A75; border-color: #6E3A31; }
.btn-accent { background: var(--accent); color: #111214; border-color: var(--accent); }
.btn-accent:hover { background: var(--accent-hi); border-color: var(--accent-hi); color: #111214; }

/* chips */
.chipgroup { padding: 14px 18px; border-bottom: 1px solid var(--line); }
.chipgroup:last-child { border-bottom: 0; }

.chipgroup-head {
  display: flex; align-items: baseline; gap: 14px; margin-bottom: 10px; flex-wrap: wrap;
}
.chipgroup-title {
  margin: 0; font-size: 11px; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; color: var(--muted);
}
.chipgroup-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.linkbtn {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--muted); font-family: var(--sans); font-size: 11.5px;
  letter-spacing: .06em; text-transform: uppercase;
}
.linkbtn:hover { color: var(--accent); }
.sep { color: var(--line); font-size: 11px; }

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

.chip {
  display: inline-flex; align-items: center; gap: 8px;
  background: #17181C;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--muted);
  font-family: var(--sans); font-size: 13px;
  padding: 7px 11px;
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s, opacity .12s;
}
.chip:hover { background: var(--panel-2); color: var(--text); }
.chip[aria-pressed="true"] { color: var(--text); background: var(--panel-2); border-color: #3A3E46; }
.chip[aria-pressed="false"] { opacity: .5; }
.chip[aria-pressed="false"] .chip-count { opacity: .8; }

.chip-count {
  font-family: var(--mono); font-size: 11.5px; font-variant-numeric: tabular-nums;
  color: var(--muted); letter-spacing: -.01em;
}
.chip.done .chip-count { color: var(--accent); }
.chip-dot { width: 8px; height: 8px; flex: none; background: var(--ct, var(--muted)); }

/* Category chips carry their group's hue on the dot, so the list reads as
   blocks at a glance without needing sub-headings. The hue is set inline by
   app.js from the map data's own group colour — there is no rule here keyed on
   a group id, because those ids come from the source and this file should not
   have to know them. --ct falls back to --muted (see .chip-dot above). */

/* Nine category chips fit in two or three rows on most windows, but not on a
   narrow one. Cap the list and let it scroll rather than push the table
   off-screen — it costs nothing when they all fit, and the mobile shell's
   guard below neutralises the cap once the group is re-parented. */
.chipgroup[data-group="category"] .chips {
  max-height: 178px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: #3A3E46 transparent;
  padding-right: 2px;
}
.chipgroup[data-group="category"] .chips::-webkit-scrollbar { width: 8px; }
.chipgroup[data-group="category"] .chips::-webkit-scrollbar-thumb {
  background: #3A3E46; border-radius: 4px;
}
.chipgroup[data-group="category"] .chips::-webkit-scrollbar-track { background: transparent; }

/* ---------------- Table ---------------- */

.table-panel { padding: 0; overflow: hidden; }

.table-meta {
  display: flex; align-items: baseline; gap: 6px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line);
  font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}
.table-meta .num { color: var(--text); font-size: 13px; }

.table-scroll { overflow-x: auto; }

.checklist-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

.checklist-table th {
  text-align: left;
  font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted);
  padding: 0;
  border-bottom: 1px solid var(--line);
  background: #16181B;
}
.checklist-table th.c-found { padding: 12px 8px 12px 18px; }
.checklist-table th.c-info  { padding: 12px 18px 12px 14px; }

/* No region column: the freed width goes to the name and info cells. */
.c-found { width: 76px; }
.c-name  { width: 28%; }
.c-cat   { width: 16%; }

.sortbtn {
  display: inline-flex; align-items: center; gap: 6px;
  width: 100%;
  background: none; border: 0; cursor: pointer;
  color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit;
  padding: 12px 14px;
  text-align: left;
}
.sortbtn:hover { color: var(--text); }
.arrow { width: 8px; opacity: 0; }
.arrow::before { content: "\25B2"; font-size: 7px; }
th[aria-sort="ascending"]  .sortbtn { color: var(--accent); }
th[aria-sort="descending"] .sortbtn { color: var(--accent); }
th[aria-sort="ascending"]  .arrow { opacity: 1; }
th[aria-sort="descending"] .arrow { opacity: 1; transform: rotate(180deg); }

.checklist-table tbody tr {
  border-bottom: 1px solid var(--line);
  transition: background .12s, opacity .12s;
}
.checklist-table tbody tr:last-child { border-bottom: 0; }
.checklist-table tbody tr:hover { background: var(--panel-2); }
.checklist-table tbody tr.is-hidden { display: none; }

.checklist-table td {
  padding: 14px;
  vertical-align: top;
}
.checklist-table td.c-found { padding-left: 18px; padding-right: 8px; }
.checklist-table td.c-info  { padding-right: 18px; }

/* checkbox */
.cb-wrap { display: inline-flex; align-items: center; }
.cb {
  appearance: none; -webkit-appearance: none;
  width: 22px; height: 22px; margin: 0;
  border: 1.5px solid #3D424B;
  border-radius: 3px;
  background: #141518;
  cursor: pointer;
  position: relative;
  flex: none;
  transition: background .12s, border-color .12s, box-shadow .12s;
}
.cb:hover { border-color: var(--muted); }
.cb:checked {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.14), 0 0 10px rgba(var(--accent-rgb),.25);
}
.cb:checked::after {
  content: "";
  position: absolute; left: 6.5px; top: 2.5px;
  width: 5px; height: 10px;
  border: solid #111214;
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(43deg);
}

tr.done { opacity: .62; }
tr.done:hover { opacity: .85; }
tr.done .item-title { text-decoration: line-through; color: var(--muted); text-decoration-thickness: 1px; }

.item-title { font-weight: 500; line-height: 1.4; }

.pin {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin-left: 6px;
  vertical-align: -5px;
  border: 1px solid var(--line); border-radius: 4px;
  color: var(--muted);
  opacity: 0;
  transition: color .12s, border-color .12s, opacity .12s;
}
.pin:hover { color: var(--accent); border-color: #3A3E46; }
tr:hover .pin, .pin:focus-visible { opacity: 1; }
@media (hover: none) { .pin { opacity: 1; } }
tr.done .pin { opacity: 0; }
tr.done:hover .pin, tr.done .pin:focus-visible { opacity: 1; }

.tag {
  display: inline-block;
  font-size: 12px; line-height: 1.35;
  padding: 3px 8px;
  border-radius: 4px;
  border: 1px solid var(--line);
  color: var(--muted);
  background: #17181C;
  white-space: nowrap;
}
/* The category tag is the only tag on a row, and it stays the neutral grey the
   region games use: the chip dot already carries the group hue, and repeating
   it 634 times down a column would out-shout the names. */
.tag-cat { color: #B9BEC7; }

/* info cell */
.info-cell { display: flex; gap: 10px; align-items: flex-start; }
.info-body { flex: 1 1 auto; min-width: 0; color: #C7CBD2; font-size: 13.5px; }
.info-body.clamped {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-height: 3.2em; /* fallback clamp for engines without -webkit-line-clamp */
}
.info-body > *:first-child { margin-top: 0; }
.info-body > *:last-child  { margin-bottom: 0; }
.info-body p { margin: 0 0 .55em; }
.info-body ul, .info-body ol { margin: .35em 0 .7em; padding-left: 1.2em; }
.info-body li { margin: .18em 0; }
.info-body strong { color: var(--text); font-weight: 600; }
.info-body em { color: #D6D9DE; }
.info-body a { color: var(--accent); }
.info-body br { line-height: 1; }
.info-empty { color: #5F656E; font-family: var(--mono); font-size: 13px; }

.chev {
  flex: none;
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 1px solid var(--line); border-radius: 4px;
  color: var(--muted); cursor: pointer;
  transition: color .12s, border-color .12s, transform .15s;
}
.chev:hover { color: var(--accent); border-color: #3A3E46; }
.chev svg { transition: transform .15s ease; }
tr.expanded .chev svg { transform: rotate(90deg); }

/* empty state */
.empty { padding: 44px 18px 50px; text-align: center; }
.empty p { margin: 0 0 16px; color: var(--muted); font-size: 15px; }

/* toast */
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%) translateY(14px);
  background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--accent);
  color: var(--text); padding: 11px 16px; border-radius: var(--radius);
  font-size: 13.5px; z-index: 70;
  opacity: 0; pointer-events: none;
  transition: opacity .18s, transform .18s;
  max-width: calc(100vw - 32px);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* footer */
.foot {
  color: #666C75; font-size: 12.5px;
  padding: 8px 2px 0;
}
.foot p { margin: 0 0 4px; }
.foot code { font-family: var(--mono); font-size: 11.5px; color: var(--muted); }

/* ---------------- Responsive ---------------- */

@media (max-width: 900px) {
  .hud-inner { gap: 16px; }
  .counter { min-width: 0; flex: 1 1 auto; }
  .hud-counters { width: 100%; }
}

@media (max-width: 820px) {

  /* These chips wrapped into a stack at phone widths, which on Vice City made the
     sticky header 571px of a 667px screen. One scrollable row instead - nothing is
     lost, and the clipped next chip is the affordance. */
  .hud-counters {
    flex: 1 1 100%;
    min-width: 0;              /* without this the row overflows the page instead of scrolling */
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }
  .counter { flex: 0 0 auto; }
  .hud-counters::-webkit-scrollbar { height: 3px; }
  .hud-counters::-webkit-scrollbar-thumb { background: var(--line); border-radius: 2px; }
  body { font-size: 14.5px; }
  .wrap { padding: 0 12px; }
  .sort-mobile { display: flex; flex: 1 1 150px; }
  .tool-actions { margin-left: 0; width: 100%; }
  .tool-actions .btn { flex: 1 1 auto; }

  .table-scroll { overflow-x: visible; }
  .checklist-table, .checklist-table tbody, .checklist-table tr, .checklist-table td { display: block; width: auto; }
  .checklist-table thead { display: none; }
  .checklist-table { table-layout: auto; }

  .checklist-table tbody tr {
    position: relative;
    padding: 14px 14px 14px 52px;
    border-bottom: 1px solid var(--line);
  }
  .checklist-table td { padding: 0; }
  .checklist-table td.c-found {
    position: absolute; left: 3px; top: 4px; padding: 0;
  }
  /* 44px tap target; the offsets above are pulled back by 11px so the 22px
     box still lands where it did before the target grew around it. */
  .cb-wrap {
    justify-content: center;
    min-width: 44px; min-height: 44px;
    cursor: pointer;
  }

  /* 16px stops iOS Safari zooming the page on focus */
  input[type="search"], select { font-size: 16px; }

  .linkbtn { display: inline-flex; align-items: center; min-height: 44px; padding: 0 8px; }
  .checklist-table td.c-name { font-size: 15px; margin-bottom: 8px; }
  .checklist-table td.c-cat  { display: inline-block; margin: 0 6px 8px 0; }
  .checklist-table td.c-info { padding: 0; }
}

@media (max-width: 480px) {
  .hud-pct { font-size: 40px; }
  .counter { padding: 7px 9px; }
  .counter-label { font-size: 9.5px; letter-spacing: .08em; }
  .counter-val { font-size: 16px; }
}

/* ---------------- Mobile shell ---------------- */

/* The bar, scrim and sheets are built by mobile.js and live at the end of
   <body>. Hidden by default so desktop is byte-for-byte unaffected. */
.mobile-shell { display: none; }

/* Deliberately after the 480px block: the condensed header has to win over
   the .hud-pct font-size set there. Everything below is mobile-only. */
@media (max-width: 820px) {

  :root { --mbar-h: 68px; }

  /* --- condensed header: two rows, ~63px instead of the full-height HUD --- */
  .hud-inner {
    padding-top: 8px; padding-bottom: 8px;
    gap: 4px 10px;
    align-items: center;
    justify-content: flex-start;
  }
  /* Flatten the wrappers so title/nav/count/percent/bar become siblings that
     can be ordered into two rows. Nothing is moved in the DOM to do this. */
  .hud-main, .hud-meta, .page-nav { display: contents; }

  .hud-title-row { order: 1; flex: 1 1 100%; flex-wrap: nowrap; gap: 8px; min-width: 0; }
  .hud-title {
    order: 0; flex: 1 1 auto; min-width: 0;
    margin: 0; font-size: 15px; line-height: 1.3; letter-spacing: .07em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .page-nav > :first-child { order: -1; }  /* back link, ahead of the title */
  .page-nav .here { display: none; }       /* you are already on this page */
  .page-nav a { padding: 3px 7px; font-size: 10px; }

  .hud-sub { order: 2; flex: 0 0 auto; margin: 0; gap: 0; }
  .hud-sub > span:not(.num) { display: none; }  /* separator and game name */
  .hud-sub .num { font-size: 12.5px; }
  .hud-pct { order: 3; flex: 0 0 auto; font-size: 15px; line-height: 1.2; min-width: 0; }
  .hud-bar { order: 4; flex: 1 1 auto; width: auto; }

  /* The per-group numbers are already on the category chips, and this strip is
     what made the header tall. Desktop still uses it — hidden, never removed. */
  .hud-counters { display: none; }

  /* --- controls panel, once the sheet has taken its contents --- */
  body.mobile-ui .controls { padding: 0; }
  body.mobile-ui .controls .toolrow { border-bottom: 0; }

  /* --- bottom bar --- */
  .mobile-shell { display: block; }
  /* Scoped to the class so the page still ends sensibly if mobile.js is absent. */
  body.mobile-ui main.wrap { padding-bottom: calc(var(--mbar-h) + 18px); }

  .mbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 56;
    display: flex; align-items: center; gap: 10px;
    background: rgba(17,18,20,.96);
    -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
    border-top: 1px solid var(--line);
    padding: 10px 12px max(14px, env(safe-area-inset-bottom));
  }
  .mbar-search, .mbar-filter {
    min-height: 44px; display: flex; align-items: center;
    background: #141518; border: 1px solid var(--line); border-radius: 22px;
    padding: 0 15px; font-family: var(--sans); cursor: pointer;
  }
  .mbar-search { flex: 1 1 auto; min-width: 0; gap: 9px; color: #6C737D; font-size: 15px; text-align: left; }
  .mbar-search-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mbar-filter {
    flex: none; gap: 8px; color: var(--text);
    font-size: 12.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  }
  .mbar-search[aria-expanded="true"], .mbar-filter[aria-expanded="true"] {
    color: var(--accent); border-color: var(--accent);
  }
  .mbar-n {
    font-family: var(--mono); font-size: 10px; font-weight: 600; line-height: 1.5;
    background: var(--accent); color: #111214; border-radius: 8px; padding: 0 5px;
  }
  .mbar-n[hidden] { display: none; }

  /* --- scrim + sheets --- */
  .mscrim {
    position: fixed; inset: 0; z-index: 55; background: rgba(0,0,0,.55);
    opacity: 0; pointer-events: none; transition: opacity .22s ease;
    touch-action: none;  /* iOS will scroll the page through a plain overlay */
  }
  .mscrim.on { opacity: 1; pointer-events: auto; }

  .msheet {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    max-height: 74%;                 /* the list stays visible behind it */
    display: flex; flex-direction: column;
    background: var(--panel);
    border-top: 1px solid #3A3E46;
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -18px 44px rgba(0,0,0,.6);
    transform: translateY(101%);
    visibility: hidden;
    /* visibility flips only once the slide-out has finished, which is also
       what keeps a closed sheet's controls out of the tab order. */
    transition: transform .26s cubic-bezier(.22,.61,.36,1), visibility 0s linear .26s;
  }
  .msheet.on {
    transform: translateY(0); visibility: visible;
    transition: transform .26s cubic-bezier(.22,.61,.36,1), visibility 0s;
  }

  .msheet-grab { flex: none; width: 36px; height: 4px; border-radius: 2px; background: #3A3E46; margin: 9px auto 4px; }
  .msheet-head {
    flex: none; display: flex; align-items: center; gap: 10px;
    padding: 2px 14px 6px; border-bottom: 1px solid var(--line);
  }
  .msheet-title {
    flex: 1 1 auto; margin: 0;
    font-family: var(--display); font-weight: 400; font-size: 15px;
    letter-spacing: .11em; text-transform: uppercase; transform: skewX(-6deg);
  }
  .msheet-done {
    flex: none; min-height: 44px; padding: 0 6px;
    display: inline-flex; align-items: center;
    background: none; border: 0; cursor: pointer;
    color: var(--muted); font-family: var(--sans);
    font-size: 11px; letter-spacing: .09em; text-transform: uppercase;
  }
  .msheet-done:hover { color: var(--accent); }
  .msheet-body {
    /* min-height:0 is load-bearing: without it this flex item refuses to
       shrink below its content height and shoves .msheet-foot off screen. */
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
    padding: 12px 14px 18px;
  }
  /* Pinned actions row — never scrolls, so Reset is on screen for any pane. */
  .msheet-foot {
    flex: none; border-top: 1px solid var(--line);
    padding: 12px 14px max(14px, env(safe-area-inset-bottom));
  }
  .mnote { margin: 12px 0 0; font-size: 12px; color: var(--muted); }
  .mrule { height: 1px; background: var(--line); margin: 14px 0; }

  /* Re-parented controls: drop the panel chrome they were laid out with.
     Red Dead Redemption 2 has no regions, so there is no segmented switcher
     and the one group keeps its own visible .chipgroup-title as the pane's
     heading. */
  .msheet .search-field { width: 100%; }
  .msheet .chipgroup { padding: 0; border-bottom: 0; }
  /* Any desktop height-cap on a chip list becomes a scroller inside the sheet's
     own scroller once the group is re-parented. Neutralise every variant - the
     folders express the cap with different selectors. Kept identical in every
     game folder even where it is currently a no-op, so the guard travels with the
     pattern when one is ported from another. */
  .msheet .chipgroup[data-group="region"] .chips,
  .msheet .chipgroup[data-group="category"] .chips,
  .msheet .chips-scroll {
    max-height: none;
    overflow-y: visible;
    padding-right: 0;
  }
  .msheet .chip { min-height: 44px; padding: 0 12px; }
  .msheet .switch { min-height: 44px; }
  .msheet .switch-label { font-size: 14px; }
  .msheet .tool-actions { width: 100%; margin-left: 0; gap: 8px; }
  .msheet .tool-actions .btn { flex: 1 1 0; min-height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .counter.tick { outline: 2px solid var(--accent); }
}

/* ---------------- Account sync indicator (spec 10.1) ---------------- */

/* SITE CHROME, NOT THE GAME. Waypoint's violet, never var(--accent): colour
   alone should tell you whether you are looking at Waypoint or at a game.
   Declared on the element rather than in :root so the game's token block stays
   the game's and nothing else in the sheet can pick these up by accident. */
.wp-sync {
  --wp: #8A7CFF;
  --wp-problem: #FF8A75;          /* the tint .btn-danger:hover already uses */
  display: none;
}

/* The PRESENCE of data-state is what reveals the row, and sync.js sets it only
   when there is something to say. Under file:// there is no account to sign in
   to, so it is never set and the page keeps exactly the height it has today. */
.wp-sync[data-state] {
  display: flex;
  align-items: center;
  min-height: 22px;   /* CONSTANT in all four states. Synced, Syncing, Problem
                         and Sign in are different lengths; inline they moved
                         the head by ~20px on one extra character, which is why
                         this is its own row. Do not make the height content-led. */
  margin-top: 8px;
}

.wp-sync-face {
  position: relative;
  display: inline-flex; align-items: center; gap: 7px;
  height: 22px; padding: 0;
  background: none; border: 0;
  font-family: var(--sans);
  font-size: 10.5px; font-weight: 600;
  letter-spacing: .13em; text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
}
/* The 44px touch target is grown OUTSIDE layout so the visible box stays 22px:
   -11px on each of four sides of a 22px box is 44px. Same arithmetic CLAUDE.md
   already records for td.c-found. Do not tidy it back. */
.wp-sync-face::after { content: ""; position: absolute; inset: -11px; }

/* Interactive only when actionable: sync.js emits a <button> in Problem and a
   plain <span> in the two states that offer nothing. */
button.wp-sync-face { cursor: pointer; }
button.wp-sync-face:hover, a.wp-sync-face:hover { color: var(--text); }

.wp-sync-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--wp); }
.wp-sync[data-state="problem"] .wp-sync-dot { background: var(--wp-problem); }
/* Signed out reads as an outline: present, but nothing is being carried. */
.wp-sync[data-state="signedout"] .wp-sync-dot {
  background: none; box-shadow: inset 0 0 0 1.5px var(--wp);
}

/* THE ONLY ANIMATED PROPERTY ON A GAME PAGE, on one 7px dot. No will-change:
   map.css spends a paragraph explaining that the marker pane is the single
   element in this site allowed to take one, and a second promoted layer would
   be paid on every frame of every gesture. prefers-reduced-motion is already
   handled by the global block earlier in this file. */
@keyframes wp-sync-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .28; } }
.wp-sync[data-state="syncing"] .wp-sync-dot {
  animation: wp-sync-pulse 1.1s ease-in-out infinite;
}

/* Deliberately last in the file, after both the 480px block and the mobile
   shell's own 820px block. Those flatten .hud-meta to display:contents, which
   turns this row into an unordered flex child of .hud-inner and drops it ABOVE
   the title. An explicit
   order puts it back after the progress bar and keeps it INLINE on the second
   row, which costs the condensed 63px header about 3px instead of 30. */
@media (max-width: 820px) {
  .wp-sync[data-state] { order: 5; flex: 0 0 auto; margin-top: 0; }
}
