/* The interface's symbols (arrows, shapes, check marks) from a tiny bundled
   font, so every system draws them: many lack some of these characters and
   show an empty box instead. Used only where the system fonts have no glyph.
   Noto Sans Symbols, Symbols 2 and Math subsets (vendor/LICENSE.noto-fonts.txt). */
@font-face { font-family: "BA UI Symbols"; src: url("../vendor/fonts/ui-symbols.woff2") format("woff2"); unicode-range: U+20E0,U+2190,U+2191,U+2192,U+2193,U+2302,U+266A,U+26F0,U+26F6,U+2922; font-display: swap; }
@font-face { font-family: "BA UI Symbols"; src: url("../vendor/fonts/ui-math.woff2") format("woff2"); unicode-range: U+21A9,U+21BA,U+21BB,U+21C4,U+2205,U+2229,U+222A,U+223F,U+2248,U+2260,U+2261,U+2264,U+2265,U+22EF,U+233E,U+27F3; font-display: swap; }
/* the word "Brighter" wherever the site names itself or a tool, and "Brighter Shores" in the landing page's title:
   Roboto Slab SemiBold (the face the game sets its room names in), cut to those words' letters alone
   (vendor/fonts/brighter.woff2, 1.7 KB; vendor/LICENSE.roboto-slab.txt) */
@font-face { font-family: "BA Brighter"; src: url("../vendor/fonts/brighter.woff2") format("woff2"); font-weight: 600; unicode-range: U+20,U+42,U+53,U+65,U+67-69,U+6F,U+72-74; font-display: block; }
@font-face { font-family: "BA UI Symbols"; src: url("../vendor/fonts/ui-symbols2.woff2") format("woff2"); unicode-range: U+21E9,U+2212,U+2316,U+2318,U+2443,U+25A3,U+25A4,U+25A6,U+25B6,U+25B8,U+25BE,U+25C6,U+25C9,U+25CB,U+25CF,U+25EE,U+26A0,U+270E,U+2713,U+2715,U+2726,U+2733,U+2756,U+275A,U+2B71,U+2B73; font-display: swap; }
/* Brighter Shores asset viewer: dark theme */
:root {
  --bg0: #0d0f13;        /* page */
  --bg1: #14171d;        /* panels */
  --bg2: #1a1e26;        /* raised */
  --bg3: #232833;        /* hover / inputs */
  --line: #2a303c;
  --line-soft: #21262f;
  --fg0: #e8ecf2;
  --fg1: #aeb6c4;
  --fg2: #79818f;
  --accent: #78b7ff;
  --accent-dim: #3d6ea8;
  --good: #6fd08c;
  --warn: #e8b45a;
  --bad: #e87070;
  --sel: #223349;
  --mono: "SF Mono", ui-monospace, Menlo, Consolas, "BA UI Symbols", monospace;
  --sans: -apple-system, "Segoe UI", system-ui, Roboto, "BA UI Symbols", sans-serif;
  --radius: 8px;
  --topbar-h: 40px;      /* every page's top bar (phones: 44, the same on every page, below) */
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; background: var(--bg0); color: var(--fg0);
  font: 13px/1.45 var(--sans);
  overflow: hidden;
}
.mono { font-family: var(--mono); font-size: 12px; }
.dim { color: var(--fg2); }
.small { font-size: 11px; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
button { font: inherit; color: inherit; }
::selection { background: var(--accent-dim); }
/* the one page (src/app/Shell.tsx): the top bar, then the page the address names, each tool's page kept
   (hidden) once opened */
#root { height: 100%; }
.shell { display: flex; flex-direction: column; height: 100%; }
.pages { flex: 1; min-height: 0; position: relative; }
.page { position: absolute; inset: 0; display: flex; flex-direction: column; }
.page[hidden] { display: none; }
.page > :first-child { flex: 1; min-height: 0; }
.page > .page-load { top: 42%; }
/* until its own stylesheet is in, a page shows only its layout placeholders (.ph) and its load card: never
   its markup unstyled */
.page.unstyled { visibility: hidden; }
.page.unstyled .ph, .page.unstyled > .page-load { visibility: visible; }
/* (Fashion's toast is unseen from the start: its own sheet would otherwise fade it out in view) */
#toast { opacity: 0; }
/* each page's layout drawn before its code arrives (pages.tsx placeholders), and the one load card over
   where its content will be: Fashion's view (beside its panel; above it on phones) */
.ph { min-width: 0; min-height: 0; }
#fashion > main { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) 420px; }
.ph-view { background: radial-gradient(ellipse at 50% 40%, #1f2531 0%, #14171d 55%, #0d0f13 100%); }
.ph-panel { background: var(--bg1); border-left: 1px solid var(--line); }
.page[data-page=fashion] > .page-load { left: calc((100% - 420px) / 2); }
@media (max-width: 1280px) {
  #fashion > main { grid-template-columns: minmax(0, 1fr) 380px; }
  .page[data-page=fashion] > .page-load { left: calc((100% - 380px) / 2); }
}
@media (max-width: 860px) {
  #fashion > main { display: flex; flex-direction: column; }
  .ph-view { flex: 0 0 37dvh; }
  .ph-panel { flex: 1; border-left: 0; border-top: 1px solid var(--line); }
  .page[data-page=fashion] > .page-load { left: 50%; top: 18.5dvh; }
}
/* each tool's own parts of the top bar, in place, shown with its page */
/* the bar is controls, never text to select (a long press on a phone opens the switch, not a selection) */
#topbar { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
#topbar input { -webkit-user-select: text; user-select: text; }
.topbar-slot { display: contents; }
.topbar-slot[hidden] { display: none; }
/* Brighter Data's own buttons in the top bar: a desktop tool's, left out where a phone's bar has no room */
@media (max-width: 700px) { #export-btn, #overrides-btn, #data-source { display: none !important; } }
/* Brighter Data */
#app { display: flex; flex-direction: column; height: 100%; }
/* ---------- top bar ---------- */
#topbar {
  display: flex; align-items: center; gap: 16px;
  height: var(--topbar-h); padding: 0 14px;
  background: linear-gradient(180deg, #171b22, #12151b);
  border-bottom: 1px solid var(--line);
  flex: none; z-index: 30;
  /* (a pinned header: iOS home-screen apps blur and darken the top edge of the page unless a sticky or fixed
     header is there; the bar is at the top of a page that does not scroll, so its place is unchanged) */
  position: sticky; top: 0;
}
/* phones: every page's bar the same (taller, for Fashion's buttons; under the iPhone's own bar in a home-screen app),
   whichever tools have been opened: a tool's stylesheet stays once loaded, so the bar is set here, never in one */
@media (max-width: 860px) {
  :root { --topbar-h: 44px; }
  #topbar { gap: 6px; padding: env(safe-area-inset-top, 0px) 8px 0 14px; height: calc(var(--topbar-h) + env(safe-area-inset-top, 0px)); }
}
.brand { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.brand-link { display: flex; align-items: baseline; gap: 8px; color: inherit; text-decoration: none; }
.brand-link:hover .brand-name { color: var(--accent); }
.brand-mark { width: 18px; height: 18px; flex: none; align-self: center; }
/* brand/mark.svg: the Obelisk and its A */
.brand-name { font-family: "BA Brighter", var(--sans); font-weight: 600; letter-spacing: .2px; }
.brand-sub { color: var(--accent);   /* (the tool, blue as in the switcher) */ font-size: 11px; text-transform: uppercase; letter-spacing: 1.2px; }
/* the tool switch (src/tool-switch.ts): the brand itself, mark to chevron, in one faint pill that opens the tools */
.tool-switch { position: relative; align-self: center; display: inline-flex; }
.tool-switch-btn { display: inline-flex; align-items: center; gap: 6px; margin-left: -8px; padding: 2px 7px 2px 8px; border: 1px solid var(--line-soft); border-radius: 999px;
  background: rgba(255, 255, 255, .025); color: inherit; font: inherit; cursor: pointer; }
.tool-switch-btn .brand-link { align-items: baseline; }   /* (Brighter and the tool on one line of text, as in the switcher; the mark centred) */
.tool-switch-btn:hover, .tool-switch-btn[aria-expanded="true"] { background: var(--bg3); border-color: var(--line); }
.tool-switch-btn:hover .brand-name { color: var(--fg0); }
.tool-switch-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tool-switch-chevron { display: inline-grid; place-items: center; color: var(--fg2); }
.tool-switch-btn:hover .tool-switch-chevron, .tool-switch-btn[aria-expanded="true"] .tool-switch-chevron { color: var(--fg0); }
.tool-switch-chevron svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.tool-switch-menu { position: absolute; top: calc(100% + 6px); left: -8px; z-index: 90; min-width: 250px; display: flex; flex-direction: column; gap: 2px; padding: 6px;
  border-radius: 10px; background: var(--bg2); border: 1px solid var(--line); box-shadow: 0 16px 40px rgba(0, 0, 0, .55); white-space: normal; }
.tool-switch-menu[hidden] { display: none; }
.tool-switch-item { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: 7px; color: var(--fg0); text-decoration: none; }
.tool-switch-item:hover, .tool-switch-item:focus-visible, .tool-switch-home:hover, .tool-switch-home:focus-visible { background: var(--bg3); outline: none; }
.tool-switch-item.on { background: var(--sel); }
/* an entry is one button, as the landing page's cards: pressed in on a click or tap, its text never underlined */
.tool-switch-item, .tool-switch-item:hover, .tool-switch-item:active, .tool-switch-home, .tool-switch-home:hover, .tool-switch-home:active { text-decoration: none; -webkit-tap-highlight-color: transparent; }
.tool-switch-item:active, .tool-switch-home:active, .tool-switch-news:active { transform: scale(.98); background: var(--sel); transition: transform .06s; }
.tool-switch-name .brand-name { font-weight: 600; }
.tool-switch-name .brand-sub { margin-left: 3px; color: var(--accent); }
.tool-switch-line { font-size: 12px; color: var(--fg2); }
.tool-switch-rule { height: 1px; margin: 4px 6px; background: var(--line); }
/* Home and the page's own entries: plain rows, as clear as the tools */
.tool-switch-home { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border: 0; border-radius: 7px; background: none; color: var(--fg0); font: inherit; font-size: 13px; font-weight: 600; text-align: left; text-decoration: none; cursor: pointer; }
.tool-switch-home.on { background: var(--sel); }
.tool-switch-home svg { width: 15px; height: 15px; flex: none; fill: none; stroke: var(--fg1); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.tool-switch-extra { font-weight: 500; color: var(--fg1); }
.tool-switch-news { margin-top: 2px; padding: 7px 10px 6px; border: 0; border-top: 1px solid var(--line-soft); border-radius: 0 0 7px 7px; background: none; text-align: left; font: 11.5px var(--mono); color: var(--fg2); cursor: pointer; }
.tool-switch-news:hover, .tool-switch-news:focus-visible { background: var(--bg3); color: var(--accent); outline: none; }
/* "What's new" modal (reuses .modal-overlay / .modal.card / .modal-actions) */
.wn-modal { max-width: 640px; }
.wn-body { max-height: 60vh; overflow-y: auto; display: flex; flex-direction: column; gap: 18px; padding-right: 4px; }
.wn-entry { border-bottom: 1px solid var(--line); padding-bottom: 14px; }
.wn-entry:last-child { border-bottom: none; padding-bottom: 0; }
.wn-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.wn-ver { font-weight: 650; font-size: 15px; }
.wn-meta { white-space: nowrap; }
.wn-summary { margin: 6px 0 4px; color: var(--fg1); }
.wn-heading { color: var(--fg0); font-weight: 600; margin-bottom: 2px; }
.wn-list { margin: 2px 0 8px; padding-left: 20px; color: var(--fg1); }
.wn-list li { margin: 2px 0; }
/* latest release in full + prominent; older ones collapsed behind a toggle so
   the modal stays short even with a long history */
.wn-latest .wn-ver { font-size: 16px; }
.wn-earlier > summary,
.wn-old > summary { cursor: pointer; user-select: none; padding: 3px 0; }
.wn-earlier > summary { font-weight: 600; color: var(--fg1); }
.wn-earlier > summary::marker,
.wn-old > summary::marker { color: var(--accent); }
.wn-earlier[open] > summary,
.wn-old[open] > summary { margin-bottom: 8px; }
.wn-old-summary .wn-ver { font-weight: 600; font-size: 14px; }
.wn-old-summary .wn-meta { margin-left: 8px; }
.searchwrap { position: relative; flex: 1; max-width: 520px; }
#global-search {
  width: 100%; padding: 6px 10px; border-radius: 6px;
  background: var(--bg3); border: 1px solid var(--line); color: var(--fg0);
  outline: none;
  font: inherit;
}
#global-search:focus { border-color: var(--accent-dim); }
#global-search::placeholder, #list-filter::placeholder { color: var(--fg2); }
.search-results {
  position: absolute; top: 34px; left: 0; right: 0; max-height: 60vh; overflow: auto;
  background: var(--bg2); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 12px 30px rgba(0,0,0,.5); z-index: 40; padding: 4px;
}
.search-item:hover, .search-item.active { background: var(--sel); }
.top-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
/* community/source links (Discord, GitHub): neutral .btn-mini that lines its
   icon up with the label and lights up on hover, no loud solid fill */
.top-social { display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 9px; box-sizing: border-box; text-decoration: none; }
/* (the brand pill's height, on every page) */
/* the world map page (no game files needed) */
.top-social svg { display: block; }
.top-social:hover { background: var(--bg3); border-color: var(--accent); }
.top-social.discord:hover { color: #5865f2; border-color: #5865f2; }
.top-social.github:hover { color: var(--accent); border-color: var(--accent); }
/* ---------- layout ---------- */
#body { display: flex; flex: 1; min-height: 0; }
#sidebar {
  width: 320px; flex: none; display: flex; flex-direction: column;
  background: var(--bg1); border-right: 1px solid var(--line); min-height: 0;
  position: relative;   /* anchors the collapse toggle + resize handle */
}
/* (the viewer keeps room for the onboarding on a phone, where the page is wider than the screen) */
#main { flex: 1; min-width: 320px; display: flex; flex-direction: column; position: relative; background: var(--bg0); }
#viewer { flex: 1; min-height: 0; overflow: auto; position: relative; }
#details {
  width: 300px; flex: none; display: flex; flex-direction: column;
  background: var(--bg1); border-left: 1px solid var(--line); min-height: 0;
  position: relative;   /* texture picker docks over this panel */
}
.details-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 12px; border-bottom: 1px solid var(--line-soft);
  font-weight: 600; flex: none;
}
#details-body { overflow: auto; padding: 10px 12px; flex: 1; }
#sidebar > .panel-toggle { right: -15px; border-left: none; border-radius: 0 6px 6px 0; }
#details > .panel-toggle { left: -15px; border-right: none; border-radius: 6px 0 0 6px; }
#sidebar.collapsed, #details.collapsed { width: 32px; }
/* content + resize handle. The panel-ID prefix is load-bearing: children
   like #cat-tabs set display via ID selectors, which would outrank a bare
   class rule and leave icons peeking out of the collapsed rail. */
#sidebar.collapsed > :not(.panel-toggle),
#details.collapsed > :not(.panel-toggle) { display: none !important; }
#sidebar.collapsed > .panel-toggle, #details.collapsed > .panel-toggle {
  inset: 0; transform: none; width: auto; height: auto;
  background: none; border: none; border-radius: 0;
}
#sidebar.collapsed > .panel-toggle:hover, #details.collapsed > .panel-toggle:hover {
  background: var(--bg2); color: var(--fg0);
}
/* ---------- category tabs ---------- */
#cat-tabs { padding: 8px; display: flex; flex-direction: column; gap: 2px; flex: none; }
.cat-tab-row:has(.cat-tab.active) { background: var(--sel); }
.cat-tab-row:hover .cat-tab, .cat-tab.active { color: var(--fg0); }
/* ---------- list ---------- */
#list-tools { padding: 4px 8px 8px; border-bottom: 1px solid var(--line-soft); flex: none; }
#list-filter {
  width: 100%; padding: 5px 9px; border-radius: 6px;
  background: var(--bg3); border: 1px solid var(--line); color: var(--fg0); outline: none;
}
#list-filter:focus { border-color: var(--accent-dim); }
.sort-row { display: flex; gap: 4px; margin-top: 6px; }
.sort-row:has(#list-sort[hidden]) { display: none; }
#list-sort {
  flex: 1; min-width: 0; padding: 4px 6px; border-radius: 6px; font-size: 12px;
  background: var(--bg3); border: 1px solid var(--line); color: var(--fg1); outline: none;
}
#list-sort[hidden] { display: none; }
#list-sort-dir {
  flex: none; width: 28px; border-radius: 6px; font-size: 13px; line-height: 1; cursor: pointer;
  background: var(--bg3); border: 1px solid var(--line); color: var(--fg1);
}
#list-sort-dir[hidden] { display: none; }
#list-sort-dir:hover { border-color: var(--accent-dim); color: #fff; }
#list-chips { margin-top: 6px; }
#list-chips:empty { margin-top: 0; }
#list-host { flex: 1; min-height: 0; position: relative; }
.vrow.selected { background: var(--sel); box-shadow: inset 2px 0 0 var(--accent); }
.vrow.vrow-all.selected { background: var(--sel); box-shadow: inset 2px 0 0 var(--accent); }
/* ---------- badges ---------- */
.badge {
  display: inline-block; padding: 1px 7px; border-radius: 4px; font-size: 10px;
  font-weight: 600; letter-spacing: .4px; text-transform: uppercase;
  background: var(--bg3); color: var(--fg1); border: 1px solid var(--line);
  vertical-align: 1px;
}
.badge.b-accent { color: var(--accent); border-color: var(--accent-dim); }
.badge.b-good { color: var(--good); border-color: #2f5c3d; }
.badge.b-warn { color: var(--warn); border-color: #6b5426; }
.badge.b-bad  { color: var(--bad);  border-color: #6b2e2e; }
.badge.b-ghost { opacity: .65; }
/* ---------- banners ---------- */
#banners { flex: none; }
/* ---------- status bar ---------- */
#statusbar {
  display: flex; align-items: center; gap: 18px;
  height: 26px; padding: 0 12px; flex: none;
  background: var(--bg1); border-top: 1px solid var(--line);
  color: var(--fg2); font-size: 11px;
}
#status-right { margin-left: auto; }
#statusbar .err { color: var(--bad); }
.viewer-toolbar .spacer { flex: 1; }
.tv-chip.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.tv-chip.tv-none.active { color: #fff; border-color: var(--accent); }
.dye-swatch.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.btn {
  padding: 4px 11px; border-radius: 6px; border: 1px solid var(--line);
  background: var(--bg2); color: var(--fg1); cursor: pointer;
}
.btn:hover { background: var(--bg3); color: var(--fg0); }
.btn.active { background: var(--accent-dim); border-color: var(--accent-dim); color: #fff; }
.btn:disabled { opacity: .4; cursor: default; }
.btn-mini { padding: 1px 8px; font-size: 11px; border-radius: 5px; border: 1px solid var(--line); background: var(--bg2); cursor: pointer; color: var(--fg1); }
.btn-mini:hover { color: var(--fg0); background: var(--bg3); }
.btn-mini.active { background: var(--accent-dim); color: #fff; border-color: var(--accent-dim); box-shadow: inset 0 1px 3px rgba(0,0,0,0.45); }
select.btn { padding: 3px 6px; }
input[type="range"] { accent-color: var(--accent); }
/* The playback-bar variant (.pb) stacks the clip listbox above a pinned control
   row: the listbox FILLS the remaining height (no manual resizer), so shrinking
   the bar shrinks the list and never pushes the transport controls off screen. */
/* Default tall enough to show the clip header + several clip rows before the
   user drags it (the drag height, when set, is inline and overrides this).
   Without it the listbox (flex:1 1 0; min-height:0) collapses to nothing. */
.anim-bar.pb { flex-direction: column; align-items: stretch; flex-wrap: nowrap; overflow: hidden; height: 200px; }
.anim-bar.pb .clip-select {
  flex: 1 1 0; min-height: 0; width: 100%; max-width: 100%;
  font-family: var(--mono); font-size: 12px; padding: 2px; resize: none; overflow: auto;
}
.anim-bar.pb .pb-controls { flex: none; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
/* ---------- placeholder / onboarding ---------- */
.placeholder { display: flex; align-items: center; justify-content: center; height: 100%; padding: 30px; }
.card {
  max-width: 620px; background: var(--bg1); border: 1px solid var(--line);
  border-radius: 12px; padding: 26px 30px; box-shadow: 0 20px 50px rgba(0,0,0,.35);
}
.card h2 { margin: 0 0 10px; font-size: 17px; }
.card p { color: var(--fg1); }
.card pre { background: var(--bg0); border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; overflow: auto; font-family: var(--mono); font-size: 12px; color: var(--fg0); }
.notexported {
  display: flex; flex-direction: column; gap: 8px; align-items: center; justify-content: center;
  color: var(--fg2); height: 100%; min-height: 160px;
}
/* ---------- key/value details ---------- */
.kv { width: 100%; border-collapse: collapse; font-size: 12px; }
.kv td { padding: 3px 4px; vertical-align: top; border-bottom: 1px solid var(--line-soft); }
.kv td:first-child { color: var(--fg2); white-space: nowrap; padding-right: 10px; }
.kv td:last-child { font-family: var(--mono); word-break: break-word; color: var(--fg0); }
.rawjson {
  font-family: var(--mono); font-size: 11px; white-space: pre-wrap; word-break: break-all;
  background: var(--bg0); border: 1px solid var(--line-soft); border-radius: 6px; padding: 8px; color: #9fd0a2;
}
.img-stage.dragging { cursor: grabbing; }
.subthumb.active { border-color: var(--accent-dim); background: var(--bg2); }
.pad { padding: 14px; }
/* scrollbars */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: #2c323e; border-radius: 6px; border: 2px solid var(--bg1); }
::-webkit-scrollbar-thumb:hover { background: #3a4150; }
::-webkit-scrollbar-corner { background: transparent; }
@supports not selector(::-webkit-scrollbar) { * { scrollbar-color: #2c323e transparent; } }
/* (Firefox: the same colours) */
/* the persistent themed scrollbar where the platform's own floats and hides (src/scrollbar.ts): a gutter at the
   scroller's right edge, a track in it */
.vbar-host { scrollbar-width: none; }
.vbar-host.vbar-on { padding-right: 16px !important; }
.vbar-host::-webkit-scrollbar { display: none; }
.vbar { position: absolute; width: 6px; border-radius: 3px; background: rgba(255, 255, 255, .05); z-index: 3; touch-action: none; }
.vbar::before { content: ''; position: absolute; inset: 0 -10px; }
/* a finger-sized hit area */
.vbar[hidden] { display: none; }
.vbar-thumb { width: 100%; border-radius: 3px; background: #3a4150; }
.vbar:active .vbar-thumb { background: #4f5a6e; }
kbd {
  font-family: var(--mono); font-size: 10px; background: var(--bg3); padding: 1px 5px;
  border-radius: 4px; border: 1px solid var(--line); border-bottom-width: 2px;
}
.texpicker .tp-actions .btn { padding: 2px 8px; font-size: 11px; }
.texpicker .tp-fitbtn.active { background: var(--accent-dim); border-color: var(--accent); color: #fff; }
.texpicker .tp-cell.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-dim); }
.texpicker .tp-foot .btn { padding: 2px 8px; font-size: 11px; }
.texpicker .tp-foot .spacer { flex: 1; }
.skel-meshes .sm-row .badge { flex: none; padding: 0 4px; }
.skel-meshes .sm-row .dim { flex: none; white-space: nowrap; }
.skel-meshes .sm-row .dim { margin-left: auto; }
.texpicker .tp-cell.chosen { border-color: var(--good); box-shadow: 0 0 0 2px #2f5c3d; }
.texpicker .tp-cell.chosen::after {
  content: '✓'; position: absolute; top: 3px; left: 3px; z-index: 1; pointer-events: none;
  font: 10px/1 monospace; color: #06210f; background: var(--good); border-radius: 3px; padding: 1px 3px;
}
/* ---------- overrides manager modal ---------- */
/* every dialog stands over every tool's own layers (Fashion's designer drawer, 50; its looks, 65; its picture
   sheet, 80; the tool switch, 90), so its close button is never covered */
.modal-overlay {
  position: fixed; inset: 0; z-index: 150; background: rgba(6,8,11,.62);
  display: flex; align-items: center; justify-content: center;
}
/* capture modals (screenshot / video): solid backdrop so the live 3D view isn't
   visible (and animating) behind the modal while you set up a capture */
.modal.card {
  width: min(720px, 92vw); max-height: 84vh; display: flex; flex-direction: column;
  background: var(--bg1); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 18px; gap: 10px;
}
.modal.card h2 { margin: 0; font-size: 15px; }
.modal-actions { display: flex; gap: 8px; align-items: center; flex: none; }
.modal-actions .spacer { flex: 1; }
.ob-drop.over { border-color: var(--accent); background: var(--bg2); }
.ob-bundle.ok { opacity: 1; border-color: var(--accent-dim); }
.ob-cat.missing { opacity: .5; }
.btn.primary { background: var(--accent-dim); border-color: var(--accent); }
/* primary call-to-action inside viewer toolbars (e.g. Texture…) */
.btn.btn-cta { background: var(--accent-dim); border-color: var(--accent); color: #fff; font-weight: 600; }
.btn.btn-cta:hover { background: var(--accent); color: #0d0f13; }
.err { color: #e07777; }
.ob-cat.done { opacity: .75; border-color: var(--accent-dim); }
.ver-row.active { border-color: var(--accent-dim); }
/* macOS / Windows build logo, in the topbar chip + version rows */
/* The topbar chip mixes text + the icon: flex-center them so the icon doesn't
   ride the font baseline (inline vertical-align sat it ~1px off the text's
   visual middle). The version rows (.ver-head) are already flex-centered. */
#data-source { display: inline-flex; align-items: center; }
.plat-icon { display: inline-flex; align-items: center; vertical-align: middle; margin-left: 5px; color: var(--fg1); }
.plat-icon.plat-guess { opacity: .5; }
.plat-icon svg { display: block; }
.breadcrumb a { color: var(--fg1); }
.breadcrumb a:hover { color: var(--accent); text-decoration: none; }
/* panel resize handles */
.rz-handle { position: absolute; z-index: 26; }
/* inset (not overhanging): panels with overflow:auto clip negative offsets */
.rz-handle.rz-right { top: 0; bottom: 0; right: 0; width: 8px; cursor: col-resize; }
.rz-handle.rz-left { top: 0; bottom: 0; left: 0; width: 8px; cursor: col-resize; }
.rz-handle.rz-top { left: 0; right: 0; top: 0; height: 8px; cursor: row-resize; }
.rz-handle.rz-bottom { left: 0; right: 0; bottom: 0; height: 8px; cursor: row-resize; }
/* faint always-visible divider so handles are discoverable; brightens on hover */
.rz-handle::after { content: ''; position: absolute; inset: 0; background: var(--line); opacity: 0.6; transition: opacity 0.12s, background 0.12s; }
.rz-handle.rz-left::after, .rz-handle.rz-right::after { width: 2px; }
.rz-handle.rz-right::after { right: 0; left: auto; }
.rz-handle.rz-top::after, .rz-handle.rz-bottom::after { height: 2px; }
.rz-handle.rz-bottom::after { bottom: 0; top: auto; }
.rz-handle:hover::after, .rz-handle:active::after { background: var(--accent); opacity: 1; }
/* diff cards span the full viewer width (override the centered .card cap) */
.diff-body .card { max-width: none; box-shadow: none; }
.diff-room-asset.add { color: var(--good, #7ac47a); }
.world-panel .wp-inspect.active {
  background: #3d3413; border-color: #e4c45b; color: #ffe9a0;
}
/* Pinned effect instance: hide/pause read as "on" once toggled, same accent
   the rest of the app uses for an active toggle (.btn-mini.active, .wp-inspect.active) */
.world-panel .wp-edit-actions .wp-fx-hide.active,
.world-panel .wp-edit-actions .wp-fx-pause.active {
  background: var(--accent-dim); color: #fff; border-color: var(--accent-dim);
}
/* The clip listbox asks for up to 7 rows; 172px left it barely one after the
   transport controls took their share. Taller by default, and draggable so a
   long clip list can be opened up without leaving the panel. */
.world-panel .wp-anim .anim-bar.pb {
  height: 240px; min-height: 140px; max-height: 60vh; resize: vertical;
}
/* all-rooms loading overlay (js/viewers/world.js): one weighted progress bar
   over the dimmed canvas; fades out when the pipeline reaches ready */
.world-loading {
  position: absolute; inset: 0; z-index: 8;
  display: flex; align-items: center; justify-content: center;
  background: rgba(16, 19, 26, 0.94);
  transition: opacity .4s ease;
}
.world-loading.done { opacity: 0; pointer-events: none; }
.world-loading .wlo-card { width: min(340px, 72%); text-align: center; }
.world-loading .wlo-title { color: var(--fg0); font-size: 14px; margin-bottom: 12px; letter-spacing: .02em; }
.world-loading .wlo-bar {
  height: 6px; border-radius: 3px; overflow: hidden;
  background: var(--bg3); border: 1px solid var(--line);
}
.world-loading .wlo-fill {
  height: 100%; width: 0; background: var(--accent); border-radius: 3px;
  transition: width .25s ease;
}
.world-loading .wlo-pct {
  margin-top: 8px; color: var(--fg2); font-size: 11px; font-variant-numeric: tabular-nums;
}
/* confirm state (shown before any loading starts): memory warning + actions */
.world-loading .wlo-note {
  margin: 0 0 14px; color: var(--fg2); font-size: 12px; line-height: 1.55; text-align: left;
}
.world-loading .wlo-actions {
  display: flex; gap: 8px; justify-content: center; margin-bottom: 14px;
}
.world-loading .world-load-confirm {
  background: var(--accent); border-color: var(--accent); color: #10131a; font-weight: 600;
}
/* GPU-tier warning inside the confirm overlay (integrated / software adapters) */
.world-loading .wlo-warn {
  margin: 0 0 14px; padding: 8px 10px; text-align: left;
  border: 1px solid #6b5a34; border-radius: var(--radius);
  background: rgba(84, 66, 24, 0.22);
  font-size: 12px; line-height: 1.5;
}
.world-loading .wlo-warn b { display: block; margin-bottom: 4px; color: #e8c268; }
.world-loading .wlo-warn p { margin: 0; color: var(--fg2); }
.world-loading .wlo-warn-software { border-color: #6b3a34; background: rgba(84, 30, 24, 0.22); }
.world-loading .wlo-warn-software b { color: #e79a8e; }
.world-hud.collapsed { padding: 3px 7px; }
.world-hud.collapsed .wh-head { float: none; }
.modal.card.mgate { position: relative; width: min(440px, 100%); max-height: 88dvh; overflow-y: auto; gap: 12px; padding: 22px 18px 18px;
  font-size: 15px; line-height: 1.5; }
.modal.card .mgate-title { margin: 0 28px 0 0; font-size: 19px; font-weight: 650; line-height: 1.3; text-wrap: balance; }
.map-inspection .btn { white-space: normal; }
.map-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 10px; flex: none; }
.map-toolbar label { display: inline-flex; gap: 5px; align-items: center; }
.map-toolbar select { max-width: 190px; min-height: 32px; }
.map-toolbar select, .map-toolbar input[type=number] { background: var(--bg3); color: var(--fg0); border: 1px solid var(--line); border-radius: 5px; padding: 5px; }
.map-toolbar input[type=number] { width: 80px; }
.map-canvas-host { position: relative; flex: 1; min-height: 160px; overflow: hidden; background: #2a2a2a;
  /* a map, not text: taps never select, long presses never call up the text menu */
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
.map-canvas-host canvas { position: absolute; width: 100%; height: 100%; touch-action: none; cursor: grab; }
.map-canvas-host canvas:active { cursor: grabbing; }
@media (max-width: 820px) {
  body.map-active #sidebar, body.map-active #details { display: none; }
  body.map-active #topbar .top-social, body.map-active #topbar .searchwrap { display: none; }
  body.map-active #overrides-btn, body.map-active #data-source, body.map-active #export-btn { display: none; }
  .map-toolbar { gap: 6px; padding: 6px; }
  .map-toolbar button, .map-toolbar select { min-height: 40px; }
  .map-toolbar select { max-width: 44vw; flex: 1; }
  .map-inspection-toolbar { width: 100%; }
  .map-inspection { position: absolute; inset: 0 0 0 auto; width: min(340px,100%); box-sizing: border-box; z-index: 2; }
  .map-options label { min-height: 40px; }
  .map-status { font-size: 11px; }
}
/* a load in progress, the same on every page (a page opening, Fashion's places, a map update): a ring alone,
   no words and nothing behind it, that fills, or spins while the load cannot say how far it is (what it
   loads is its aria-label). It never takes a tap. */
.load-card { position: absolute; left: 50%; top: 42%; transform: translate(-50%, -50%); z-index: 4; display: flex; pointer-events: none; }
.load-card[hidden] { display: none; }
.load-card svg { width: 40px; height: 40px; transform: rotate(-90deg); filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .45)); }
.load-card circle { fill: none; stroke-width: 3.5; }
.load-card .pl-track { stroke: var(--line); }
.load-card .pl-fill { stroke: var(--accent); stroke-linecap: round; stroke-dasharray: 119.4; stroke-dashoffset: 119.4; transition: stroke-dashoffset .25s; }
.load-card.spin svg { animation: load-card-spin 1s linear infinite; }
.load-card.spin .pl-fill { stroke-dashoffset: 84; transition: none; }
@keyframes load-card-spin { to { transform: rotate(270deg); } }
/* a page that could not be loaded: its one line, where the ring was */
.page-failed { position: absolute; left: 50%; top: 42%; transform: translate(-50%, -50%); z-index: 4; max-width: calc(100% - 32px); text-align: center; color: var(--fg1); font-size: 13px; }
@media (prefers-reduced-motion: reduce) { .load-card.spin svg { animation-duration: 3s; } }
