:root{
  --bg:#f3f4f6; --surface:#fff; --raised:#fafafa; --fg:#15181d; --muted:#5d6572; --line:#dde1e6;
  --accent:#0b5fc4; --on-accent:#fff; --accent-soft:#e3eefc; --heat:#f59e0b;
  --c-shelf:#1f7a3a; --c-out:#2f63c9; --c-over:#c2410c; --c-held:#8b3fbf; --c-move:#b7791f; --c-unav:#7a828c;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --sans:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  color-scheme:light;
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --bg:#0f1115; --surface:#181b21; --raised:#1e2229; --fg:#e7eaee; --muted:#9aa3ae; --line:#2b3039;
  --accent:#5ea1ff; --on-accent:#0f1115; --accent-soft:#17283f; --heat:#ffd166;
  --c-shelf:#4fbf73; --c-out:#6c9cff; --c-over:#ff8a4c; --c-held:#c58af0; --c-move:#e5b14a; --c-unav:#8f98a3;
  color-scheme:dark}}
:root[data-theme="dark"]{
  --bg:#0f1115; --surface:#181b21; --raised:#1e2229; --fg:#e7eaee; --muted:#9aa3ae; --line:#2b3039;
  --accent:#5ea1ff; --on-accent:#0f1115; --accent-soft:#17283f; --heat:#ffd166;
  --c-shelf:#4fbf73; --c-out:#6c9cff; --c-over:#ff8a4c; --c-held:#c58af0; --c-move:#e5b14a; --c-unav:#8f98a3;
  color-scheme:dark}
/* console family palette (shared with the map-emit chips): newest generation most saturated, older ones greyer.
   Light shades take white text, dark/marquee shades near-black. --pf-other = anything outside the three families. */
:root{--pf-text:#fff;--pf-ps5:#0047bb;--pf-ps4:#2d5ea6;--pf-pso:#5b6b86;--pf-xsx:#0b7a0b;--pf-xb1:#3a7239;--pf-xo:#5b6e5a;
  --pf-ns2:#d0021b;--pf-ns:#b8323e;--pf-no:#8a5a5e;--pf-other:#8b9099}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--pf-text:#111;--pf-ps5:#5b95ff;--pf-ps4:#86a8dd;--pf-pso:#9ca7ba;
  --pf-xsx:#3fd33a;--pf-xb1:#86c283;--pf-xo:#a2b3a1;--pf-ns2:#ff5a68;--pf-ns:#ef8a92;--pf-no:#c8a5a8;--pf-other:#7d848e}}
:root[data-theme="dark"],:root[data-scheme="marquee"]{--pf-text:#111;--pf-ps5:#5b95ff;--pf-ps4:#86a8dd;--pf-pso:#9ca7ba;
  --pf-xsx:#3fd33a;--pf-xb1:#86c283;--pf-xo:#a2b3a1;--pf-ns2:#ff5a68;--pf-ns:#ef8a92;--pf-no:#c8a5a8;--pf-other:#7d848e}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);font:14px/1.4 var(--sans)}
header{display:flex;flex-wrap:wrap;align-items:center;gap:6px 16px;padding:14px 16px 10px;border-bottom:1px solid var(--line);background:var(--surface)}
h1{font-size:20px;margin:0;letter-spacing:-.01em}
.brand{display:inline-flex;align-items:center;color:inherit;text-decoration:none;border-radius:999px}
.brand:hover .pill{border-color:var(--lg-muted)}
.meta{color:var(--muted);font-size:12px}
.warn{color:var(--c-over);font-weight:600}
.tabs{margin-left:0;display:flex;gap:4px}
/* header, every page: logo + name, then the view tabs right next to it, the stats line on the right */
header h1{order:1}header .tabs{order:2}header .meta{order:3;margin-left:auto;text-align:right}
.tab[hidden]{display:none}
.tab{text-decoration:none;display:inline-block;font:inherit;border:1px solid var(--line);background:var(--raised);color:var(--fg);padding:6px 12px;border-radius:6px;cursor:pointer}
.tab[aria-selected="true"]{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.sticky{position:sticky;top:0;z-index:5;background:var(--surface);border-bottom:1px solid var(--line)}
.filters{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:10px 16px}
.filters select,.filters input[type=search],.filters input[type=datetime-local],.clock select{font:inherit;padding:6px 8px;border:1px solid var(--line);border-radius:6px;background:var(--bg);color:var(--fg);max-width:100%}
.filters input[type=search]{width:200px}
.chip{font:inherit;font-size:12px;border:1px solid var(--line);background:var(--bg);color:var(--fg);border-radius:999px;padding:4px 10px;cursor:pointer}
.chip[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.sep{width:1px;height:22px;background:var(--line)}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
main{padding:12px 16px 40px}
.empty{color:var(--muted);padding:24px;text-align:center}
footer.site{max-width:900px;margin:8px auto 0;padding:16px 16px 28px;border-top:1px solid var(--line);font-size:12px;line-height:1.5;color:var(--muted)}
footer.site p{margin:0 0 6px}
footer.site b{color:var(--fg);font-weight:600}

/* replay clock (pattern copied from __sys/_lab state_viz/files_viz: play/speed/scrub/now + hourly churn strip) */
.clock{display:grid;grid-template-columns:auto auto minmax(0,1fr) auto auto;gap:10px;align-items:center;padding:0 16px 10px}
.clock button{font:inherit;border:1px solid var(--line);background:var(--raised);color:var(--fg);border-radius:6px;padding:5px 10px;cursor:pointer}
.clock input[type=range]{width:100%;accent-color:var(--accent)}
.clock time{font:600 13px var(--mono);color:var(--accent);white-space:nowrap}
.strip-wrap{grid-column:1/-1}
#strip{width:100%;height:22px;display:block;cursor:pointer;border-radius:4px}
.strip-lbl{font-size:10.5px;color:var(--muted);letter-spacing:.04em;text-transform:uppercase;margin-bottom:3px}
@media (max-width:600px){.clock{grid-template-columns:auto minmax(0,1fr) auto}.clock .speed{display:none}.clock time{grid-column:1/-1;order:-1}}

/* board */
.board{display:grid;grid-template-columns:repeat(6,minmax(230px,1fr));gap:10px;overflow-x:auto;padding-bottom:6px}
.col{background:var(--raised);border:1px solid var(--line);border-radius:8px;display:flex;flex-direction:column;min-height:120px;max-height:calc(100vh - 230px)}
.col h2{margin:0;padding:9px 10px;font-size:13px;display:flex;align-items:center;gap:6px;border-bottom:1px solid var(--line);background:var(--raised);border-radius:8px 8px 0 0}
.col h2 .dot{width:9px;height:9px;border-radius:50%}
.col h2 .n{margin-left:auto;font:600 12px var(--mono);color:var(--muted)}
.cards{overflow-y:auto;padding:8px;display:flex;flex-direction:column;gap:6px}
.card{display:grid;grid-template-columns:34px minmax(0,1fr) auto;gap:8px;align-items:start;background:var(--surface);border:1px solid var(--line);border-left:3px solid var(--bc);border-radius:6px;padding:7px;cursor:pointer;text-align:left;font:inherit;color:inherit;width:100%}
.card:hover{border-color:var(--accent);border-left-color:var(--bc)}
.card.hot{box-shadow:0 0 0 2px var(--heat)}
@keyframes blink{0%{box-shadow:0 0 0 0 var(--bc);background:var(--accent-soft)}35%{box-shadow:0 0 0 6px transparent;background:var(--accent-soft)}100%{box-shadow:0 0 0 0 transparent}}
.card.blink{animation:blink 1.5s ease-out 1}
@media (prefers-reduced-motion:reduce){.card.blink{animation:none;outline:2px solid var(--accent)}}
.card img{width:34px;height:44px;object-fit:cover;border-radius:3px;background:var(--line)}
.card .t{font-weight:600;font-size:13px;line-height:1.25;overflow-wrap:anywhere}
.card .sub{font-size:11.5px;color:var(--muted);margin-top:2px;overflow-wrap:anywhere}
.card .x{font:600 12px var(--mono);color:var(--muted);white-space:nowrap}
.tag{display:inline-block;font-size:10.5px;padding:0 5px;border-radius:3px;border:1px solid var(--line);margin-right:3px;color:var(--muted)}
.holds{color:var(--c-over);font-weight:600}
.tally{font-size:12px;margin-top:3px;color:var(--muted)}
.tally b{font-weight:600}.tally b.ok{color:var(--c-shelf)}.tally b.no{color:var(--c-out)}
.more{font:inherit;font-size:12px;margin:2px 8px 8px;padding:6px;border:1px dashed var(--line);border-radius:6px;background:none;color:var(--muted);cursor:pointer}

/* map */
.map-head{display:flex;flex-wrap:wrap;gap:6px 14px;align-items:center;margin-bottom:8px;font-size:12px;color:var(--muted)}
.map-head i{display:inline-block;width:10px;height:10px;border-radius:2px;margin-right:4px;vertical-align:-1px}
#view-map{position:relative}
#map-links{position:absolute;top:0;left:0;pointer-events:none}
#map-links a{position:absolute;overflow:hidden;opacity:0;color:var(--accent);font:600 11px/18px system-ui,sans-serif;padding:0 5px;
  white-space:nowrap;text-decoration:underline;background:var(--surface);border-radius:4px}
#map-links a:focus-visible{opacity:1;outline:2px solid var(--accent);outline-offset:-2px}
#tip .tip-go{color:var(--accent);font-weight:600}
.map-head .lay-note{flex-basis:100%;color:var(--fg);font-weight:600}
.map-head .pf-chip b{color:var(--fg);font-weight:600}
.map-head .pf-key{flex-basis:100%;display:flex;flex-wrap:wrap;align-items:center;gap:4px 14px}
.map-head .pf-key>span{white-space:nowrap}.map-head .pf-key i{background:var(--muted)}
.map-head i.k-out{background:none;box-shadow:inset 0 0 0 2px var(--muted)}
.map-head i.k-fade{opacity:.3}
.map-head i.k-half{background:linear-gradient(to top right,var(--muted) 50%,transparent 50%);box-shadow:inset 0 0 0 1px var(--muted)}
.map-head i.k-ring{background:none;box-shadow:0 0 0 2px var(--heat)}
.map-ctl{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center;margin-bottom:8px}
.map-ctl select{font:inherit;padding:4px 6px;border:1px solid var(--line);border-radius:6px;background:var(--surface);color:var(--fg)}
#map{width:100%;display:block;background:var(--surface);border:1px solid var(--line);border-radius:8px;cursor:crosshair}

/* finder (layout modeled on the owner's PS5 Shelf Finder page) */
.find{display:grid;grid-template-columns:290px minmax(0,1fr);gap:16px;align-items:start}
@media (max-width:860px){.find{grid-template-columns:minmax(0,1fr)}}
.rail{background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:14px;display:flex;flex-direction:column;gap:16px;position:sticky;top:120px;max-height:calc(100vh - 140px);overflow:auto}
@media (max-width:860px){.rail{position:static;max-height:none}}
.fg{display:flex;flex-direction:column;gap:7px}
.fl{font-size:11.5px;font-weight:600;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);display:flex;justify-content:space-between;gap:8px}
.fl small{text-transform:none;letter-spacing:0;font-weight:400}
.rail select,.rail button.wide{font:inherit;padding:7px 8px;border:1px solid var(--line);border-radius:6px;background:var(--bg);color:var(--fg);width:100%;text-align:left;cursor:pointer}
.chips{display:flex;flex-wrap:wrap;gap:5px}
.chip .n{font:11px var(--mono);color:var(--muted);margin-left:3px}
.chip[aria-pressed="true"] .n{color:inherit;opacity:.8}
.chip.ex{background:transparent;border-color:var(--c-over);color:var(--c-over);text-decoration:line-through}
.hint{font-size:12px;color:var(--muted);margin:0}
#x-desc{display:flex;flex-direction:column}
.dgroup{border-top:1px solid var(--line)}
.dgroup:last-child{border-bottom:1px solid var(--line)}
.dgroup summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:8px;padding:8px 2px;font-weight:600;font-size:13.5px}
.dgroup summary::-webkit-details-marker{display:none}
.dgroup summary::before{content:"";width:6px;height:6px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:rotate(-45deg);transition:transform .15s;flex:none;margin-right:2px}
.dgroup[open] summary::before{transform:rotate(45deg)}
.dgroup .gname{flex:1}
.dgroup .gn{font:500 11px var(--mono);color:var(--muted)}
.dgroup .gact{font-size:11px;font-weight:600;color:var(--on-accent);background:var(--accent);border-radius:999px;padding:1px 7px}
.dgroup .chips{padding:0 0 10px}
.dmore{all:unset;cursor:pointer;color:var(--accent);font-size:12.5px;font-weight:600;margin:-2px 0 10px;display:inline-block}
.dmore:hover{text-decoration:underline}
.dmore:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:2px}
.origin{font-size:12px;color:var(--muted)}
.res-bar{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;margin-bottom:8px}
.res-bar .count{font-size:18px;font-weight:600}
.res-bar select{font:inherit;padding:5px 8px;border:1px solid var(--line);border-radius:6px;background:var(--surface);color:var(--fg)}
.results{background:var(--surface);border:1px solid var(--line);border-radius:8px;overflow:hidden}
.fr{display:grid;grid-template-columns:44px minmax(0,1.6fr) 54px minmax(0,1.4fr) minmax(0,1.7fr);gap:12px;align-items:start;padding:11px 12px;border-top:1px solid var(--line);cursor:pointer}
.fr:first-child{border-top:0}
.fr:hover{background:var(--raised)}
.fr img{width:44px;height:58px;object-fit:cover;border-radius:3px;background:var(--line)}
.fr .t{font-weight:600;line-height:1.25;overflow-wrap:anywhere}
.fr .yr{font-weight:400;color:var(--muted);font-size:12px}
.esrb{display:inline-flex;align-items:center;justify-content:center;min-width:40px;height:26px;padding:0 5px;border:2px solid var(--fg);border-radius:2px;font-weight:700;font-size:13px}
.esrb.M{background:var(--fg);color:var(--surface)}
.esrb.none{border-style:dashed;color:var(--muted);border-color:var(--line);font-weight:400}
.dtags{display:flex;flex-wrap:wrap;gap:3px}
.dtag{font-size:11px;padding:1px 6px;border-radius:3px;background:var(--bg);border:1px solid var(--line);white-space:nowrap}
.dtag.hit{background:var(--accent-soft);border-color:var(--accent);font-weight:600}
.dtag.ie{border-style:dashed;color:var(--muted)}
.avail b{display:block;font-size:13px}
.avail .ok{color:var(--c-shelf)} .avail .wait{color:var(--c-out)} .avail .no{color:var(--muted)}
.avail .sub{font-size:12px;color:var(--muted)}
.score{display:block;font:600 13px var(--mono);margin-top:5px}
.score.g{color:var(--c-shelf)} .score.m{color:var(--c-move)} .score.b{color:var(--c-over)}
.alsoon{display:flex;flex-wrap:wrap;gap:4px;align-items:center;margin-top:5px}
.also{font:inherit;font-size:11.5px;padding:1px 8px;border:1px solid var(--accent);border-radius:999px;background:var(--accent-soft);color:var(--fg);cursor:pointer}
.also:hover{background:var(--accent);color:var(--on-accent)}
.alsoon.c .also{font-size:11px;padding:0 7px}
.links{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.links a{font-size:12px;text-decoration:none;border:1px solid var(--line);border-radius:999px;padding:2px 9px;color:var(--fg)}
.links a:hover{border-color:var(--accent)}
.fr .links{margin-top:4px}.fr .links a{font-size:11px;padding:0 7px}
.call{font:12px var(--mono);background:var(--bg);border:1px solid var(--line);border-radius:3px;padding:0 4px}
@media (max-width:700px){.fr{grid-template-columns:44px minmax(0,1fr) auto;grid-template-areas:"img t e" "img av av" "d d d"}
  .fr>img{grid-area:img}.fr>.ft{grid-area:t}.fr>.fe{grid-area:e}.fr>.fa{grid-area:av}.fr>.fd{grid-area:d}}

/* activity log */
.arun{padding:7px 12px;background:var(--raised);border-top:1px solid var(--line);font-size:12px;font-weight:600;color:var(--muted);position:sticky;top:0}
.arun:first-child{border-top:0}
.arow{display:grid;grid-template-columns:30px minmax(0,2fr) minmax(0,1.2fr) minmax(0,1.6fr);gap:10px;align-items:center;padding:7px 12px;border-top:1px solid var(--line);cursor:pointer;font-size:13px}
.arow:hover{background:var(--raised)}
.arow img{width:30px;height:39px;object-fit:cover;border-radius:2px;background:var(--line)}
.arow .t{font-weight:600;overflow-wrap:anywhere}
.arow .what b{font-weight:600}
.arow .st{font-size:11.5px;color:var(--muted)}
.kdot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px;vertical-align:1px}
.pager{display:flex;flex-wrap:wrap;gap:4px;align-items:center}
.pager button{font:inherit;font-size:12px;min-width:30px;padding:4px 8px;border:1px solid var(--line);border-radius:6px;background:var(--surface);color:var(--fg);cursor:pointer}
.pager button[aria-current="page"]{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.pager button:disabled{opacity:.4;cursor:default}
@media (max-width:700px){.arow{grid-template-columns:30px minmax(0,1fr);}.arow .lib,.arow .what{grid-column:2}}

/* timeline */
.tl-grid{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:12px}
@media (max-width:900px){.tl-grid{grid-template-columns:minmax(0,1fr)}}
.panel{background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:12px}
.panel h3{margin:0 0 8px;font-size:13px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.05em}
.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;margin-bottom:12px}
.tile{background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:10px}
.tile b{display:block;font:600 22px var(--mono)}
.tile span{font-size:12px;color:var(--muted)}
#chart{width:100%;height:260px;display:block}
.legend{display:flex;flex-wrap:wrap;gap:10px;font-size:12px;color:var(--muted);margin-top:6px}
.legend i{display:inline-block;width:10px;height:10px;border-radius:2px;margin-right:4px;vertical-align:-1px}
.feed{max-height:560px;overflow-y:auto}
.ev{display:grid;grid-template-columns:86px minmax(0,1fr);gap:8px;padding:6px 0;border-top:1px solid var(--line);font-size:13px}
.ev:first-child{border-top:0}
.ev time{font:12px var(--mono);color:var(--muted)}
.ev .what{font-size:12px}
.ev:has(> img){grid-template-columns:86px 30px minmax(0,1fr)}
.ev > img{width:30px;height:39px;object-fit:cover;border-radius:2px;background:var(--line)}
.gyr{font-size:11.5px;color:var(--muted);margin-left:4px;white-space:nowrap}
.lb-chips .gyr{margin-left:0}
.bars .row{display:grid;grid-template-columns:minmax(0,1fr) 46px;gap:6px;align-items:center;font-size:12px;margin:4px 0}
.bars .bar{height:8px;border-radius:4px;background:var(--accent);margin-top:2px}
.note{font-size:12px;color:var(--muted);margin:6px 0 0}
#tip{position:fixed;pointer-events:none;background:var(--surface);border:1px solid var(--line);border-radius:6px;padding:6px 8px;font-size:12px;box-shadow:0 4px 14px rgba(0,0,0,.15);display:none;z-index:20;max-width:280px}

/* drawer */
dialog{border:1px solid var(--line);border-radius:10px;background:var(--surface);color:var(--fg);padding:0;width:min(640px,calc(100vw - 32px));max-height:85vh}
dialog::backdrop{background:rgba(0,0,0,.4)}
.dlg-h{display:flex;gap:12px;padding:14px;border-bottom:1px solid var(--line);align-items:flex-start}
.dlg-h img{width:60px;border-radius:4px}
.dlg-h h2{margin:0;font-size:17px}
.dlg-b{padding:10px 14px 16px;overflow-y:auto;max-height:calc(85vh - 110px)}
table{width:100%;border-collapse:collapse;font-size:13px}
td,th{text-align:left;padding:5px 6px;border-top:1px solid var(--line);vertical-align:top}
th{font-size:11px;color:var(--muted);font-weight:600;text-transform:uppercase;border-top:0}
.st{font-weight:600}
.close{margin-left:auto;font:inherit;background:none;border:1px solid var(--line);color:var(--fg);border-radius:6px;padding:4px 10px;cursor:pointer}
@media (max-width:600px){.filters input[type=search]{width:100%}.sep{display:none}}

/* ---- server-rendered pages (index.php): links that look like the app's buttons, forms for no-JS use ---- */
a.chip,a.card,a.arow,a.more,a.also,.pager a,.rail a.wide{text-decoration:none;color:var(--fg)}
a.chip{display:inline-block}
a.chip[aria-pressed="true"]{color:var(--on-accent)}
a.more{display:block;text-align:center}
.rail a.wide{display:block;font:inherit;padding:7px 8px;border:1px solid var(--line);border-radius:6px;background:var(--bg)}
.pager a,.pager .off{font-size:12px;min-width:30px;padding:4px 8px;border:1px solid var(--line);border-radius:6px;background:var(--surface);text-align:center}
.pager a[aria-current="page"]{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.pager .off{opacity:.4}
a.glink{color:inherit;text-decoration:none}
a.glink:hover{text-decoration:underline}
.apply{font:inherit;font-size:12px;padding:5px 12px;border:1px solid var(--accent);background:var(--accent);color:var(--on-accent);border-radius:6px;cursor:pointer}
.rail .apply{width:100%;margin-bottom:6px}
html.js .apply{display:none}                       /* with JS, dropdowns submit on change (and the app takes over) */
html:not(.booted) .js-only{display:none!important} /* replay clock, canvas map, geolocation need the app */
html.booted .ssr-only,html.booted .ssr-table{display:none}
.notice{background:var(--accent-soft);border:1px solid var(--line);border-radius:8px;padding:10px 12px;margin:0 0 12px}
.dlg-act{margin-left:auto;display:flex;gap:10px;align-items:center}
.dlg-act .close{margin-left:0}
.gamepage{max-width:820px;margin:0 auto;background:var(--surface);border:1px solid var(--line);border-radius:10px}
.gamepage .dlg-b{max-height:none}
.gamepage .dlg-h img{width:90px}
/* map without the canvas: one square per copy, libraries sized by how many copies they hold */
.mgrid{display:flex;flex-wrap:wrap;gap:6px}
.mlib{flex:1 1 150px;background:var(--surface);border:1px solid var(--line);border-radius:6px;padding:4px 5px 6px}
.mlib .mh{font-size:11px;font-weight:600;margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mlib .mh a{color:inherit}.mlib .mh a:hover{color:var(--accent)}
.mband{flex-basis:100%;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin-top:6px}
.cells{display:flex;flex-wrap:wrap;gap:1px}
.cells i{width:7px;height:7px;border-radius:1px;background:var(--line)}
.cells .b-shelf{background:var(--c-shelf)} .cells .b-out{background:var(--c-out)} .cells .b-over{background:var(--c-over)}
.cells .b-held{background:var(--c-held)} .cells .b-move{background:var(--c-move)} .cells .b-unav{background:var(--c-unav)}
.cells .b-heat{background:var(--heat)} .cells i.hot{box-shadow:0 0 0 1.5px var(--heat)}
/* no-JS map, colour by platform: solid = on shelf, hollow = out, faded = hold / moving / unavailable */
.cells i.pf-shelf{background:var(--pc)} .cells i.pf-mid{background:var(--pc);opacity:.3}
.cells i.pf-out{background:none;box-shadow:inset 0 0 0 2px var(--pc)} .cells i.pf-out.hot{box-shadow:inset 0 0 0 2px var(--pc),0 0 0 1.5px var(--heat)}
.ssr-table{margin-top:10px;font-size:13px}
.ssr-table summary{cursor:pointer;color:var(--muted)}
.scheme{font-size:12px;color:var(--muted);text-decoration:none;white-space:nowrap}
/* game dialog / page: ESRB rating with its content descriptors and interactive elements */
.dlg-tags{display:flex;gap:8px;align-items:flex-start;margin:2px 0 10px}
.dlg-tags .esrb{flex:none}
.dlg-tags .dtags{gap:4px;padding-top:2px}

/* ==== Mobile patch (handoff Task 2): phone widths and short screens only; desktop unchanged ====
   Results move above the long finder rail, using the existing markup; jump links (.jump) bridge the two. */
@media (max-width:860px){
  .sticky{position:static}                       /* the filter bar no longer pins a quarter of the screen */
  .find>section{order:1;min-width:0}             /* results first; the finder rail follows them */
  .find>.rail{order:2}
}
@media (max-width:700px){
  /* header: title (+ look switch) / one scrolling row of tabs / data line */
  header{padding:10px 12px 8px}
  h1{font-size:18px}
  header .meta{order:3;width:100%;margin-left:0;text-align:left}
  header .scheme{order:1;margin-left:auto}
  .tabs{margin-left:0;width:100%;order:2;overflow-x:auto}
  .tab{flex:1 0 auto;min-height:44px;padding:10px 12px;display:inline-flex;align-items:center;justify-content:center}
  /* filters: larger targets; 16px stops iOS zooming into inputs */
  .filters{padding:8px 12px}
  .filters select,.filters input[type=search],.filters input[type=datetime-local]{min-height:44px;font-size:16px}
  .filters select{width:100%}
  .filters .chip{min-height:44px;display:inline-flex;align-items:center}
  /* platforms: one sideways-scrolling row instead of five wrapped rows */
  #x-plats{flex-wrap:nowrap;overflow-x:auto;margin:0 -12px 8px!important;padding:0 12px;scrollbar-width:none}
  #x-plats .chip{flex:none;min-height:44px}
  main{padding:10px 12px 28px}
  .res-bar .count{width:100%}
  .res-bar select{min-height:44px}
  /* results: availability first; every part of the row stays (owner rule: phones get every feature, compactly) */
  .fr{grid-template-columns:48px minmax(0,1fr) auto;grid-template-areas:"img t e" "img av e" "d d d";gap:2px 10px;padding:10px}
  .fr img{width:48px;height:64px}
  .fr>.fd{grid-area:d;margin-top:4px}
  .fr .links{margin-top:3px;display:flex;flex-wrap:wrap;gap:4px}
  .fr .links a{font-size:11px;padding:1px 7px}
  .fr .alsoon{font-size:11.5px}
  .fr .t{font-size:15px}
  .fr .sub{margin-top:2px!important}
  .fr .meta:empty{display:none}
  .fe{text-align:right}
  .esrb{min-width:32px;height:24px;font-size:12px}
  /* finder filters at the bottom: larger targets */
  .rail .chip,.rail select,.rail .wide{min-height:44px}
  .chip,a.chip{display:inline-flex;align-items:center}
}
/* replay speed on phones (the base CSS hides it) */
@media (max-width:600px){
  .clock{grid-template-columns:auto auto minmax(0,1fr) auto}
  .clock .speed{display:block;max-width:118px;min-height:44px}
  .clock button{min-width:44px;min-height:44px}
}
/* phone Board, portrait and landscape: cover-led columns (cards keep cover, title, holds, copy count) */
@media (max-width:700px),(max-height:500px){
  .board{grid-template-columns:repeat(6,minmax(112px,1fr));gap:6px}
  .col{max-height:none;min-width:0}
  .col h2{flex-wrap:wrap;gap:2px 6px;padding:7px 6px;font-size:12px}
  .col h2 .n{width:100%;margin-left:0;font-size:11px}
  .cards{overflow:visible;padding:5px;gap:5px}
  .card{position:relative;display:block;min-width:0;padding:0 0 5px;overflow:hidden;border-left-width:1px;border-top:3px solid var(--bc)}
  .card img{display:block;width:100%;height:auto;aspect-ratio:3/4;border-radius:0}
  .card .t{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;margin:4px 5px 0;font-size:11.5px}
  .card .sub{margin:2px 5px 0;font-size:10.5px}
  .card .sub .tag{font-size:9.5px;padding:0 3px}
  .card .sub~.sub,.card .tally{font-size:10px;line-height:1.25;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
  .card .tally{margin:2px 5px 0}
  .card .x{position:absolute;top:3px;right:3px;padding:0 4px;border-radius:3px;background:rgba(0,0,0,.72);color:#fff;font-size:11px}
  .card .x:empty{display:none}
  .more{margin:0 5px 5px;min-height:44px}
}
/* short screens (phones in landscape, including those wider than 860px) */
@media (max-height:500px){
  .sticky{position:static}
  .rail{position:static;max-height:none}
  header{align-items:center;flex-wrap:nowrap;padding:4px 12px}
  h1{font-size:16px;white-space:nowrap}
  header .meta{font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:40vw}
  header .scheme{order:0;margin-left:0}
  .tabs{margin-left:auto;order:0;width:auto}
  .tab{flex:none;min-height:36px;padding:6px 10px}
  .filters{flex-wrap:nowrap;overflow-x:auto;padding:4px 12px}
  .filters>*{flex:none}
  .filters select{width:150px;min-height:36px;font-size:14px}
  .filters input[type=search]{width:160px;min-height:36px;font-size:14px}
  .filters .chip{min-height:36px;display:inline-flex;align-items:center}
  .strip-wrap .strip-lbl{display:none}   /* the strip stays; its caption gives way to the replay controls */
  .clock{grid-template-columns:auto auto minmax(0,1fr) auto auto;padding:0 12px 4px}
  .clock .speed{display:block;width:auto;max-width:none}
  .clock button,.clock select{min-height:36px}
  .clock time{grid-column:auto;order:0}
}
/* jump links between results and the finder rail (phones only) */
.jump{display:none}
@media (max-width:860px){
  .jump{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:0 12px;border:1px solid var(--line);border-radius:6px;background:var(--raised);color:var(--fg);font-weight:600;text-decoration:none}
  .rail,#x-count{scroll-margin-top:8px}
}

/* Timeline's own date range: visible labels (an empty date field renders blank on iPhones), and nothing wider than the screen */
.dt{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}
.tl-grid>*,.panel{min-width:0}
@media (max-width:700px){
  .dt{display:flex;width:100%}
  .dt span{flex:none;width:36px}
  .dt input{flex:1;min-width:0;width:auto}
}

/* game dialog: one line that sums up the copy table */
.dlg-sum{margin:0 0 8px;font-size:13px;font-weight:600}
.dlg-sum .ok{color:var(--c-shelf)}
/* phones: each copy is a small block (library / call number + status / due) instead of a four-column table */
@media (max-width:600px){
  .dlg-b thead{display:none}
  .dlg-b tbody tr{display:grid;grid-template-columns:minmax(0,1fr) auto;border-top:1px solid var(--line);padding:5px 0}
  .dlg-b tbody td{border:0;padding:1px 2px}
  .dlg-b tbody td:first-child,.dlg-b tbody td:last-child{grid-column:1/-1}
  .dlg-b tbody td:nth-child(3){text-align:right}
}
/* covers that are missing or blank show a plain controller tile (index.php coverTile) */
img.nocover{object-fit:contain}
/* phones: the dialog's Full page / Close row sits on top so the title and links get the width */
@media (max-width:600px){
  .dlg-h{flex-wrap:wrap}
  .dlg-h>div:not(.dlg-act){flex:1 1 0;min-width:0}
  .dlg-act{order:-1;width:100%;justify-content:flex-end}
  .dlg-h img{width:56px}
}

/* collections bar (media_bar() in _app/media.php): folder tabs sitting on a line in the CURRENT section's colour;
   each tab has its section's colour on top, the current one is a little taller and opens into the page below */
/* section colours live on the root so the header below the bar can take the current section's tint too */
/* Games purple, Movies red, TV green, Music blue, Audiobooks orange (owner, 2026-11-04) */
:root{--sec-games:#6d4cd6;--sec-movies:#d2453c;--sec-tv:#0e7553;--sec-music:#1565c0;--sec-audiobooks:#c47a0c;--sec-things:#b0306e;--cur:var(--accent)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--sec-games:#a990ff;--sec-movies:#ff7b70;--sec-tv:#4fd1a1;--sec-music:#6cb4ff;--sec-audiobooks:#f5b24a;--sec-things:#ff86c0}}
:root[data-theme="dark"]{--sec-games:#a990ff;--sec-movies:#ff7b70;--sec-tv:#4fd1a1;--sec-music:#6cb4ff;--sec-audiobooks:#f5b24a;--sec-things:#ff86c0}
:root:has(.mbar[data-cur="games"]){--cur:var(--sec-games)}:root:has(.mbar[data-cur="movies"]){--cur:var(--sec-movies)}
:root:has(.mbar[data-cur="tv"]){--cur:var(--sec-tv)}:root:has(.mbar[data-cur="music"]){--cur:var(--sec-music)}:root:has(.mbar[data-cur="audiobooks"]){--cur:var(--sec-audiobooks)}
:root:has(.mbar[data-cur="things"]){--cur:var(--sec-things)}
/* the strip behind the tabs takes a wash of the current section's colour so the plain tabs stand out against it;
   the header below stays the page's surface, and the current tab opens into it in that same surface */
:root{--sec-tint:color-mix(in oklab, var(--cur) 16%, var(--surface))}
/* the coloured line is painted as part of the strip's background (a border would be clipped by the sideways scroll):
   the other tabs stop just above it and the current one runs down over it, so the current tab opens into the page */
.mbar{display:flex;align-items:flex-end;gap:6px;overflow-x:auto;scrollbar-width:none;padding:6px 12px 0;white-space:nowrap;
  background:linear-gradient(var(--cur), var(--cur)) bottom / 100% 2px no-repeat, var(--sec-tint)}
.mbar a:not([aria-current="page"]){margin-bottom:2px}
.mbar::-webkit-scrollbar{display:none}
.mbar .mb-games{--sec:var(--sec-games)}.mbar .mb-movies{--sec:var(--sec-movies)}.mbar .mb-tv{--sec:var(--sec-tv)}.mbar .mb-music{--sec:var(--sec-music)}.mbar .mb-audiobooks{--sec:var(--sec-audiobooks)}.mbar .mb-things{--sec:var(--sec-things)}
.mbar a{flex:none;display:inline-flex;align-items:center;gap:6px;padding:6px 12px 7px;color:var(--fg);text-decoration:none;font-size:13px;font-weight:600;
  background:var(--surface);border:1px solid var(--line);border-top:3px solid var(--sec);border-bottom:0;border-radius:10px 10px 0 0}
.mbar a:hover{background:color-mix(in oklab, var(--sec) 6%, var(--surface))}
.mbar-i{flex:none;color:var(--sec)}
.mbar a small{font:500 11px var(--mono);color:var(--muted)}
/* the current tab: taller (rises above the row; the row is bottom-aligned so nothing jumps), outlined in its colour
   and open at the bottom: it covers the coloured line under it and runs into the header */
.mbar a[aria-current="page"]{padding-top:11px;padding-bottom:11px;margin-bottom:0;background:var(--surface);
  border:2px solid var(--sec);border-top-width:4px;border-bottom:0;box-shadow:0 -3px 10px -6px var(--sec)}
.mbar a[aria-current="page"] small{color:var(--sec)}
@media (max-width:700px){.mbar{padding:6px 6px 0;gap:5px}.mbar a{min-height:44px;padding:5px 9px 6px;font-size:13.5px}.mbar a[aria-current="page"]{min-height:50px}.mbar a small{font-size:10.5px}}
@media (max-height:500px){.mbar a{min-height:36px}.mbar a[aria-current="page"]{min-height:40px}}
/* portrait phones: all five tabs fit across (owner: phones get every feature, compact, never hidden off-screen):
   the tabs share the row, each its name over its icon and count */
@media (max-width:560px){.mbar{gap:3px;padding:6px 4px 0}
  .mbar a{flex:1 1 auto;min-width:0;display:grid;grid-template-columns:1fr auto auto 1fr;align-content:center;align-items:center;column-gap:0;row-gap:2px;padding:4px 4px 5px;font-size:12.5px}
  .mbar a .mbar-l{grid-row:1;grid-column:1/5;line-height:1.1;text-align:center}
  .mbar a .mbar-i{grid-row:2;grid-column:2;width:14px;height:14px;margin-right:3px}.mbar a small{grid-row:2;grid-column:3;font-size:10px;line-height:1}}
@media (max-width:374px){.mbar{gap:2px;padding:6px 3px 0}.mbar a{padding:4px 3px 5px;font-size:12px}}
/* six tabs (?preview=things, media_bar() .mbar6): full names and counts on wide screens; on phones each tab takes a short
   name (Audio) and a short count (31k) so all six still share a 360-390px row; the link's aria-label keeps the full ones */
.mbar6 .mbar-ls{display:none}
@media (max-width:560px){.mbar6 .mbar-lf{display:none}.mbar6 .mbar-ls{display:inline}
  .mbar6 a{padding:4px 2px 5px;font-size:12px}.mbar6 a small{font-size:9.5px}.mbar6 a .mbar-i{width:13px;height:13px;margin-right:2px}}
@media (max-width:374px){.mbar6{gap:2px;padding:6px 2px 0}.mbar6 a{font-size:11.5px;padding:4px 1px 5px}}

/* ===== Find grouped by game (preview: ?preview=group-a|b|c, _app/grouping.php + groupRow() in app.js) =====
   one row per game; one line per platform edition: family-coloured platform chip, edition words, that edition's availability */
.fr.grp{grid-template-columns:44px minmax(0,3fr) 72px minmax(0,1.4fr)}
.fr .t .tq{font-size:1.14em;color:var(--muted);font-weight:600}          /* numeral 1.45 where the title is 1.27 (Task 9) */
.fr .t .tsub{color:var(--muted);font-weight:500}
.fr.grp .gty{margin-top:2px}
.fr.grp .gty .tag{margin-left:4px}
.plines{display:flex;flex-direction:column;gap:3px;margin-top:6px}
.pl{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:2px 8px;align-items:baseline;padding:3px 6px;border-radius:6px;
  background:var(--bg);color:var(--fg);text-decoration:none;font-size:12.5px;line-height:1.35}
a.pl:hover{background:var(--accent-soft)}
.pl .pchips{display:inline-flex;flex-wrap:wrap;gap:3px}
.pl .pav{min-width:0}
.pl .pav .ok{color:var(--c-shelf)} .pl .pav .wait{color:var(--c-out)} .pl .pav .no{color:var(--muted);font-weight:500}
.pl .ped{color:var(--muted);font-style:italic}
.pl.off{display:flex;flex-wrap:wrap;gap:3px;align-items:center;background:none;padding:1px 6px;opacity:.75}
.pl.off .pfc-l{text-decoration:none;display:inline-flex;gap:3px}
.pl.off .pfc-l:hover .pfc{outline:2px solid var(--accent)}
.pfc{display:inline-block;min-width:38px;text-align:center;font:600 10.5px/17px var(--sans);padding:0 6px;border-radius:4px;white-space:nowrap;
  background:var(--pf-c,var(--pf-other));color:var(--pf-text)}
.pf-ps5{--pf-c:var(--pf-ps5)}.pf-ps4{--pf-c:var(--pf-ps4)}.pf-pso{--pf-c:var(--pf-pso)}.pf-xsx{--pf-c:var(--pf-xsx)}.pf-xb1{--pf-c:var(--pf-xb1)}
.pf-xo{--pf-c:var(--pf-xo)}.pf-ns2{--pf-c:var(--pf-ns2)}.pf-ns{--pf-c:var(--pf-ns)}.pf-no{--pf-c:var(--pf-no)}.pf-other{--pf-c:var(--pf-other)}
.psc{font:600 12px var(--mono);white-space:nowrap}
.psc.g{color:var(--c-shelf)} .psc.m{color:var(--c-move)} .psc.b{color:var(--c-over)}
.sibs{margin-top:8px}
.sibs .fl{font-size:12px;color:var(--muted);margin-bottom:2px}
.sibs .pl.here{box-shadow:inset 0 0 0 1px var(--accent)}
[data-scheme="marquee"] .pl{background:#0d0a05;border:1px solid var(--line)}
[data-scheme="marquee"] .pl.off{border:0;background:none}
[data-scheme="marquee"] .fr .t .tq,[data-scheme="marquee"] .fr .t .tsub{color:var(--muted)}
@media (max-width:700px){
  .fr.grp{grid-template-columns:48px minmax(0,1fr) auto;grid-template-areas:"img t e" "d d d"}
  .fr.grp .plines{margin-top:4px}
  .pl{font-size:12px;padding:3px 5px;gap:2px 6px}
  .pfc{min-width:34px}
}
/* Amazon's customer rating (Keepa): labelled as Amazon's so it never reads as a Metascore */
.azr{display:block;margin-top:4px;font-size:11px;line-height:1.25;color:var(--muted);white-space:nowrap}
.meta .azr,.dlg-h .azr{display:inline;margin:0;font-size:12px}
.fe .azr{white-space:normal;font-size:10.5px}
@media (max-width:700px){.fr .fe .azr{font-size:10px;white-space:normal}}   /* phones: compact, still shown */
/* Smart sort preview: why a game ranks where it does (game dialog / page) */
.why{margin-top:4px;font-size:12px;line-height:1.35;color:var(--muted);border-left:2px solid var(--accent);padding-left:6px}
.why b{color:var(--fg);font-weight:600}
/* per platform line: that edition's Amazon rating (Amazon orange, labelled) beside its Metascore */
:root{--amz:#b35300}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--amz:#ffa41c}}
:root[data-theme="dark"],:root[data-scheme="marquee"]{--amz:#ffa41c}
.pscs{display:inline-flex;gap:8px;align-items:baseline;white-space:nowrap}
.paz{font-size:11.5px;color:var(--amz);font-weight:600}
.paz-l{font-size:10px;font-weight:500;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
.pazn{font-weight:400;color:var(--muted)}
@media (max-width:700px){
  .paz-l{font-size:9px}.pazn{font-size:10px}   /* phones: compact label + count, still shown */
  .pscs{gap:5px;flex-direction:column;align-items:flex-end;gap:0}
  .fr.grp .fe .azr{display:block;white-space:normal}
  dialog .paz-l,dialog .pazn{display:inline}
}
/* the parsed title search under the box when it has minus words: "mario" · ~~kart~~ */
.qchips{display:inline-flex;flex-wrap:wrap;gap:4px;align-items:center}
.qchips:empty{display:none}
.qc{font-size:12px;padding:1px 8px;border-radius:999px;border:1px solid var(--line);background:var(--raised);color:var(--fg)}
.qc.all{font-style:italic;color:var(--muted)}
.qc.ex{text-decoration:line-through;color:var(--muted)}
.qc.ex::before{content:"−";margin-right:2px;text-decoration:none;display:inline-block}
@media (max-width:700px){.qchips{width:100%}}


/* Find rows: content tags are filter links (row_dtags() / rowTags()): require -> exclude -> clear, like the rail */
a.dtag{color:inherit;text-decoration:none;cursor:pointer}
a.dtag:hover{border-color:var(--accent)}
.dtag.ex{text-decoration:line-through;color:var(--c-over);border-color:var(--c-over)}
.fr .dmore{display:none;font-size:11px;color:var(--muted);align-self:center}
/* phones: the first 4 content tags, then a "+N" that shows the rest; active ones are never folded (app.js rowTags(): ?preview=gametags keeps
   them in place, otherwise they sort first); without JavaScript all of them */
@media (max-width:700px){
  html.js .fr>.fd:not(.all)>.fold{display:none}
  html.js .fr>.fd:not(.all)>.dmore{display:inline-flex;cursor:pointer;border:1px dashed var(--line);border-radius:3px;padding:2px 7px;color:var(--accent)}
  .fr>.fd>.dtag,.fr>.fd>.chip.mc{font-size:12px;padding:3px 8px}
}
/* Find rail: "Your location" is a collapsed group at the bottom; caveats are ⓘ tooltips, not prose */
.locgrp>summary{cursor:pointer;list-style:none}
.locgrp>summary::-webkit-details-marker{display:none}
.locgrp>summary::after{content:" ▸";font-weight:400}
.locgrp[open]>summary::after{content:" ▾"}
.fl .info{cursor:help;display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border:1px solid currentColor;border-radius:50%;font:600 9.5px/1 var(--sans);font-style:normal;text-transform:none;letter-spacing:0;color:var(--muted);margin-left:auto}
/* the filter sheet on phones / narrow windows (assets/sheet.js; without JavaScript the rail stays below the results) */
.sheet-h{display:none}
@media (max-width:860px){
  html.sheet-ready .rail{position:fixed;inset:0;z-index:35;margin:0;border-radius:0;max-height:none;overflow:auto;padding:0 14px 90px;
    transform:translateY(102%);visibility:hidden;transition:transform .22s ease,visibility 0s .22s;background:var(--surface)}
  html.sheet-ready.sheet-open .rail{transform:none;visibility:visible;transition:transform .22s ease}
  html.sheet-open body{overflow:hidden}
  html.sheet-ready .rail>.jump{display:none}
  html.sheet-ready .sheet-h{display:flex;position:sticky;top:0;z-index:2;align-items:center;justify-content:space-between;margin:0 -14px -6px;padding:10px 14px;background:var(--surface);border-bottom:1px solid var(--line)}
  .sheet-h b{font-size:17px}
  .sheet-done{font:inherit;font-weight:600;min-height:44px;padding:0 18px;border:1px solid var(--accent);border-radius:8px;background:var(--accent);color:var(--on-accent)}
  html.sheet-ready .res-bar a.jump[href$="#rail"]{display:inline-flex}
}
@media (prefers-reduced-motion:reduce){html.sheet-ready .rail{transition:none}}
/* busier / quieter than usual (_app/library.php lib_norm_tag): library pages, the library list, the map's labels */
.lb-norm{display:inline-block;vertical-align:middle;margin-left:8px;font:600 11px/1.6 system-ui,sans-serif;padding:0 7px;border-radius:999px;border:1px solid currentColor;white-space:nowrap;letter-spacing:0}
.lb-norm.busy{color:var(--c-over)}.lb-norm.quiet{color:var(--c-shelf)}.lb-norm.usual{color:var(--muted);border-style:dashed}
.mh .lb-norm{margin-left:4px;font-size:10px;line-height:1.4;padding:0 5px}
/* "Surprise me" (_app/surprise.php) in the results bar of Find and the media lists; phones: "Surprise", full height */
.res-bar a.surprise{display:inline-flex;align-items:center;gap:6px;margin-left:auto;padding:4px 12px;border:1px solid var(--accent);border-radius:999px;color:var(--accent);background:var(--surface);font-weight:600;font-size:13px;text-decoration:none;white-space:nowrap}
.res-bar a.surprise:hover{background:var(--accent);color:var(--on-accent)}
.res-bar a.surprise svg{flex:none}
@media (max-width:700px){.res-bar a.surprise{min-height:44px;padding:0 14px}.res-bar a.surprise .sx{display:none}}
/* "Plays on my console" (Find platform pills): the switch, and the note on an older console's line */
.bcrow{margin:-4px 0 10px}
.bcrow:empty{display:none}
.chip.bc{max-width:100%;white-space:normal;text-align:left}
.chip.bc[aria-pressed="true"]{background:var(--accent-soft);color:var(--fg);border-color:var(--accent)}
.chip.bc .bcx{font-weight:700}
.bcn{display:inline-block;font-size:10.5px;line-height:1.5;padding:0 6px;margin-right:4px;border-radius:999px;background:color-mix(in srgb,var(--c-shelf) 16%,transparent);color:var(--fg);border:1px solid color-mix(in srgb,var(--c-shelf) 45%,transparent);white-space:nowrap;vertical-align:1px}
.qc.fz{font-style:italic;color:var(--muted);border-style:dashed}
@media (max-width:700px){.chip.bc{min-height:44px;display:inline-flex;align-items:center;gap:4px}}

/* view tabs (Find, Board ... / Home, Browse ...): a second row of tabs under the header, underlined in the current
   section's colour, one sideways-scrolling row on phones */
.subtabs{display:flex;gap:2px;margin:0;width:auto;overflow-x:auto;scrollbar-width:none;white-space:nowrap;padding:0 10px;
  background:var(--surface);border-bottom:1px solid var(--line)}
.subtabs::-webkit-scrollbar{display:none}
.subtabs .tab{flex:none;border:0;border-radius:0;background:none;color:var(--muted);font-weight:600;font-size:13.5px;
  padding:10px 12px 9px;min-height:0;box-shadow:inset 0 -3px 0 transparent;transition:color .12s,box-shadow .12s}
.subtabs .tab:hover{color:var(--fg);box-shadow:inset 0 -3px 0 var(--line)}
.subtabs .tab[aria-selected="true"]{background:none;color:var(--fg);box-shadow:inset 0 -3px 0 var(--cur)}
@media (max-width:700px){.subtabs{padding:0 4px}.subtabs .tab{flex:1 0 auto;min-height:44px;display:inline-flex;align-items:center;justify-content:center;font-size:14px;padding:0 12px}}
@media (max-height:500px){.subtabs .tab{min-height:36px;padding:0 12px;display:inline-flex;align-items:center}}
.subtabs .tab[hidden]{display:none}

/* staged filter changes (assets/media.js; the games finder in app.js): "2 changes · 1,234 movies  [Reset] [Apply]" pinned to the bottom of the window */
.mstage{position:fixed;left:0;right:0;bottom:0;z-index:40;display:flex;align-items:center;justify-content:flex-end;gap:8px;
        padding:10px max(16px,calc((100vw - 1240px) / 2)) calc(10px + env(safe-area-inset-bottom));
        background:var(--surface);border-top:1px solid var(--line);box-shadow:0 -6px 14px -8px rgba(0,0,0,.3)}
.mstage[hidden]{display:none}
.mstage span{flex:1 1 auto;font-weight:600;font-size:13px}
.mstage button{font:inherit;padding:7px 16px;border-radius:6px;cursor:pointer;border:1px solid var(--line);background:var(--raised);color:var(--fg)}
#mstage-apply{border-color:var(--accent);background:var(--accent);color:var(--on-accent);font-weight:600}
.chip.off{opacity:.5}
body:has(.mstage:not([hidden])) footer.site{padding-bottom:80px}
@media (max-width:700px){.mstage{padding:10px 12px calc(10px + env(safe-area-inset-bottom))}.mstage button{min-height:44px}}
.chip.mc{font-size:11.5px;padding:2px 8px;text-decoration:none}
@media (max-width:700px){.chip.mc{min-height:28px}}
/* an excluded chip says "not" (colour and strike-through are not the only signal; the strike skips the word) */
.chip.ex::before{content:"not ";display:inline-block;white-space:pre;text-decoration:none;font-weight:600}
/* ?preview=gametags (html[data-gtp]): on Find rows and in the rail the "not" sits as a small tab on the chip's top edge instead of
   inside it, so excluding never widens a chip, re-wraps its line or moves its neighbours: a chip tapped three times stays put */
[data-gtp] .rail .chip.ex,[data-gtp] .fr>.fd>.chip.ex{position:relative}
[data-gtp] .rail .chip.ex::before,[data-gtp] .fr>.fd>.chip.ex::before{content:"not";position:absolute;left:8px;top:-7px;font-size:9px;line-height:11px;padding:0 3px;
  border-radius:3px;background:var(--bg);color:var(--c-over);border:1px solid var(--c-over)}
/* active filters above the results (media.php $fpills, app.js renderPills): one pill per filter, x removes it (staged in
   the bar on pages built around Apply), "+ Add filter" opens the filter rail; wraps on phones, never scrolls sideways */
.fpills{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:0 0 10px}
.fpills .chip{display:inline-flex;align-items:center;gap:4px;max-width:100%;text-decoration:none;overflow-wrap:anywhere}
.chip.fpill.inc{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.chip.fpill .x{font-size:15px;line-height:1;margin-left:2px}
.chip.fpill.pend{background:transparent;color:var(--muted);border-style:dashed;border-color:var(--line);text-decoration:line-through}
.chip.fpill.pend .x{transform:rotate(45deg)}
/* a tag pill (.tri): the body cycles include -> exclude -> clear like the tag chips, the x removes it (both are their own
   tap target: a link without JavaScript, a button in the games finder) */
.chip.fpill.tri{padding-top:0;padding-bottom:0;padding-right:2px}
.fpill.tri .fp-b,.fpill.tri .fp-x{font:inherit;color:inherit;background:none;border:0;padding:4px 0;margin:0;cursor:pointer;text-decoration:none;align-self:stretch;display:inline-flex;align-items:center}
.fpill.tri .fp-x{font-size:15px;line-height:1;padding:4px 7px;min-width:26px;justify-content:center;border-left:1px solid color-mix(in srgb,currentColor 30%,transparent)}
.fpill.tri .fp-b:focus-visible,.fpill.tri .fp-x:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-radius:3px}
.chip.fpill.tri.pend .fp-x{transform:rotate(45deg);border-left:0}
.chip.fpill.tri.ex{text-decoration:none}.chip.fpill.tri.ex .fp-b{text-decoration:line-through}
/* a search that found nothing with the filters, shown without them (media.php media_search_fallback, app.js finder) */
.notice.mfb .fbk{font-weight:600;white-space:nowrap}
.notice.mfb .fbf{color:var(--muted)}
.chip.addf{border-style:dashed;color:var(--accent);font-weight:600}
.chip.fclear{color:var(--muted)}
@media (max-width:700px){.fpills .chip{min-height:36px}}
.fd>.chip.mc.ie{border-style:dashed}
.fr>.fd{gap:4px}
/* map view: the replay bar sits in the sticky Bookmobile, under its copies (dockClock in app.js) */
.clock.in-bus{margin:8px -42px 0 0;padding:6px 0 4px;border-top:1px solid var(--line)}
.me-bus.phone .clock.in-bus{margin-right:-40px;gap:6px}
.clock.in-bus .strip-lbl{display:none}
/* ?preview=gametags (app.js GT): the series line on a Find row is a one-tap filter */
.wser{margin-top:3px}
.wser a{color:var(--accent);text-decoration:none;font-weight:600}
.wser a[aria-pressed="true"]{text-decoration:underline}
.fd>.chip.mc.wt:not([aria-pressed="true"]):not(.ex){background:var(--accent-soft)}
.fd>.chip.mc.wt.dim:not([aria-pressed="true"]):not(.ex){background:transparent;border-style:dashed;opacity:.8}   /* a possible tag shown only because nothing is confirmed */
/* ?preview=gametags rows (.fd.gt): every unselected chip has the same neutral fill and its kind shows in the border colour
   alone (game type, platform, game tag, content descriptor, interactive element); selected = the solid blue fill,
   excluded = the "not" style. Hues stay clear of the blue (selected) and the orange (excluded); each border is 3:1+ on --bg. */
:root{--rk-ty:#1b7f79;--rk-pf:#3c434d;--rk-wt:#7c5bbf;--rk-desc:#848c96;--rk-ie:#5a7d27}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--rk-ty:#4cc2b8;--rk-pf:#c5cbd3;--rk-wt:#b39af0;--rk-desc:#7a838e;--rk-ie:#9cc26a}}
:root[data-theme="dark"]{--rk-ty:#4cc2b8;--rk-pf:#c5cbd3;--rk-wt:#b39af0;--rk-desc:#7a838e;--rk-ie:#9cc26a}
.fr>.fd.gt>.chip.mc:not([aria-pressed="true"]):not(.ex){background:var(--bg);color:var(--fg);border-color:var(--rk-desc)}
.fr>.fd.gt>.chip.mc.ty:not([aria-pressed="true"]):not(.ex){border-color:var(--rk-ty)}
.fr>.fd.gt>.chip.mc.pf:not([aria-pressed="true"]){border-color:var(--rk-pf)}
.fr>.fd.gt>.chip.mc.wt:not([aria-pressed="true"]):not(.ex){border-color:var(--rk-wt)}
.fr>.fd.gt>.chip.mc.wt.dim:not([aria-pressed="true"]):not(.ex){border-style:dashed;opacity:.8}
.fr>.fd.gt>.chip.mc.ie:not([aria-pressed="true"]):not(.ex){border-color:var(--rk-ie)}
/* platform chips carry the platform badge's family colour as a small swatch (pfChip / .pfc), include only */
.fr>.fd>.chip.mc.pf::before{content:"";display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:5px;vertical-align:0;background:var(--pf-c,var(--pf-other))}
.fr>.fd>.chip.mc.pf[aria-pressed="true"]::before{box-shadow:0 0 0 1.5px var(--on-accent)}
.chip[hidden]{display:none}   /* the "Show all" folds (tag and descriptor groups): .chip display would otherwise win */
/* colour theme switch (index.php header): light / match device / dark, kept in localStorage (mw-theme) */
.themesw{order:4;display:inline-flex;gap:2px;padding:2px;border:1px solid var(--line);border-radius:999px;background:var(--raised)}
.themesw button{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:999px;background:none;color:var(--muted);cursor:pointer;padding:0}
.themesw button[aria-pressed="true"]{background:var(--surface);color:var(--fg);box-shadow:0 0 0 1px var(--line)}
.themesw button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.themesw svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.themesw svg .fill{fill:currentColor;stroke:none}
.themesw button[data-th="dark"] svg path{fill:currentColor;stroke:none}
@media (max-width:700px){header .themesw{order:2;margin-left:auto}.themesw button{width:34px;height:34px}}
@media (max-height:500px){header .themesw{order:4;margin-left:8px;flex:none}}

/* the logo (option B, "address bar"): butterfly + milkweed.pro/ject in a pill, brand_pill() in _app/lib.php.
   JetBrains Mono (OFL-1.1, assets/fonts/JetBrainsMono-OFL.txt) is self-hosted: Latin subset, 400 + 700 only. */
@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/jetbrains-mono-latin-400-normal.woff2) format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:700;font-display:swap;src:url(/assets/fonts/jetbrains-mono-latin-700-normal.woff2) format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
:root{--lg-fill:#fff;--lg-line:#cdd3dc;--lg-fg:#171a20;--lg-muted:#5f6878;--lg-accent:#b93d2f;--lg-w1:#7a4bd1;--lg-w2:#e2604e;--lg-body:#c98a12}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--lg-fill:#232833;--lg-line:#3a4250;--lg-fg:#f4f5f7;--lg-muted:#a4acb9;--lg-accent:#f2857b;--lg-w1:#b58cf5;--lg-w2:#f2857b;--lg-body:#f6d27a}}
:root[data-theme="dark"]{--lg-fill:#232833;--lg-line:#3a4250;--lg-fg:#f4f5f7;--lg-muted:#a4acb9;--lg-accent:#f2857b;--lg-w1:#b58cf5;--lg-w2:#f2857b;--lg-body:#f6d27a}
.pill{display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 14px 0 8px;background:var(--lg-fill);border:1px solid var(--lg-line);border-radius:999px;
  color:var(--lg-fg);font:400 17px/1 "JetBrains Mono",var(--mono);letter-spacing:-.03em;white-space:nowrap}
.pill b{font-weight:700}
.pill .tld{color:var(--lg-muted)}
.pill .pj{color:var(--lg-accent)}
.bfly{width:24px;height:24px;flex:none;overflow:visible}
.bf-a{fill:var(--lg-w1)}.bf-b{fill:var(--lg-w2)}.bf-c{fill:var(--lg-body)}
.bfly .wings{transform-origin:24px 25px}
/* one flap on the first page of a browser session (index.php header script); never with reduced motion */
.brand.flap .wings{animation:mw-flap 760ms cubic-bezier(.4,0,.3,1) 250ms 1 both}
@keyframes mw-flap{0%{transform:scaleX(1)}30%{transform:scaleX(.22)}62%{transform:scaleX(1.07)}82%{transform:scaleX(.96)}100%{transform:scaleX(1)}}
@media (prefers-reduced-motion:reduce){.brand.flap .wings{animation:none}}
.pill.sm{gap:5px;height:24px;padding:0 10px 0 5px;font-size:12px}
.pill.sm .bfly{width:16px;height:16px}
.pill.lg{gap:12px;height:56px;padding:0 24px 0 14px;font-size:28px}
.pill.lg .bfly{width:36px;height:36px}
@media (max-width:700px){.pill{gap:6px;height:32px;padding:0 11px 0 6px;font-size:15px}.bfly{width:22px;height:22px}
  .pill.lg{gap:9px;height:46px;padding:0 18px 0 10px;font-size:22px}.pill.lg .bfly{width:30px;height:30px}}
@media (max-width:359px){header .pill .pj{display:none}}   /* very narrow phones: butterfly + milkweed.pro beside the theme switch */
footer.site .fbrand{display:flex;align-items:center;gap:12px;margin-bottom:10px}
footer.site .fbrand a{color:var(--fg)}
/* /ject */
.jectpage .ject{max-width:640px;margin:12px auto;font-size:15px;line-height:1.55}
.ject .pill{margin:4px 0 18px}
.ject h2{font-size:16px;margin:20px 0 8px}
.ject-list{margin:0 0 16px;padding-left:20px}
.ject-list li{margin:4px 0}
.ject a{color:var(--accent)}
body[data-view="ject"] footer.site p:not(.fbrand){display:none}   /* the page already says both */
