/* ============================================================================
   FRAME & GROOVE — Application shell & views
   ========================================================================= */

#app { display: flex; flex-direction: column; background: var(--bg-base); }

/* ======================= BOOT SPLASH ====================================
   Modelled on the game's own loading screen: a mark, a wordmark, and a bar
   made of discrete blocks that fill one at a time. Nothing spins.
   ===================================================================== */
#boot {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  background: var(--bg-void);
  transition: opacity var(--d-lazy) var(--ease-out), visibility var(--d-lazy);
}
#boot[data-done="true"] { opacity: 0; visibility: hidden; pointer-events: none; }

#boot .boot-inner {
  display: flex; flex-direction: column; align-items: center; gap: var(--s-4);
  animation: fg-rise var(--d-slow) var(--ease-out) both;
}

.boot-mark {
  width: 96px; height: 96px;
  image-rendering: pixelated;
  filter: drop-shadow(0 10px 22px rgba(0,0,0,.55));
  animation: boot-drop .55s var(--ease-spring) both;
}
@keyframes boot-drop {
  from { opacity: 0; transform: translateY(-14px) scale(.86) }
  to   { opacity: 1; transform: none }
}

.boot-word {
  font-size: var(--t-18); font-weight: var(--w-bold);
  letter-spacing: var(--tr-tighter);
  color: var(--text-1);
}
.boot-word em { font-style: normal; color: var(--text-4); font-weight: var(--w-medium); }

/* A row of blocks, lit left to right — the game's progress bar, not a spinner. */
.boot-bar {
  display: flex; gap: 3px;
  padding: 3px;
  border-radius: 3px;
  background: var(--bg-sunken);
  box-shadow: inset 0 0 0 1px var(--line-soft);
}
.boot-bar i {
  width: 9px; height: 9px;
  display: block;
  background: var(--surface-3);
  box-shadow: inset 1px 1px 0 rgba(255,255,255,.05), inset -1px -1px 0 rgba(0,0,0,.35);
  transition: background var(--d-base) var(--ease-out), box-shadow var(--d-base) var(--ease-out);
}
.boot-bar i[data-on="true"] {
  background: var(--accent);
  box-shadow: inset 1px 1px 0 rgba(255,255,255,.35), inset -1px -1px 0 rgba(0,0,0,.30),
              0 0 8px color-mix(in srgb, var(--accent) 55%, transparent);
}

#boot .boot-tag {
  font-size: var(--t-11); color: var(--text-4);
  letter-spacing: var(--tr-widest); text-transform: uppercase;
  min-height: 1em;
}

/* The failure state replaces the whole splash, so it needs no animation. */
#boot .boot-error { max-width: 460px; text-align: center; padding: 32px; }

/* ======================= LOGO =========================================== */
.logo { display: flex; align-items: center; gap: 10px; }
.logo-mark {
  width: 28px; height: 28px; flex: none;
  display: grid; place-items: center;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,.4));
}
.logo-mark canvas { width: 28px; height: 28px; image-rendering: pixelated; }
.logo-mark-lg { width: 60px; height: 60px; }
.logo-mark-lg canvas { width: 60px; height: 60px; }
.logo-word { font-size: var(--t-14); font-weight: var(--w-bold); letter-spacing: var(--tr-tighter); line-height: 1; }
.logo-word em { font-style: normal; color: var(--text-3); font-weight: var(--w-medium); }

/* ======================= TOP BAR ======================================== */
.topbar {
  height: var(--topbar-h); flex: none;
  display: flex; align-items: center; gap: var(--s-3);
  padding: 0 var(--s-3) 0 var(--s-4);
  background: var(--surface-1);
  border-bottom: 1px solid var(--line-hair);
  box-shadow: var(--bevel-hi);
  z-index: var(--z-sticky);
  -webkit-app-region: drag;
}
.topbar button, .topbar input, .topbar .no-drag { -webkit-app-region: no-drag; }

.crumbs { display: flex; align-items: center; gap: var(--s-1); min-width: 0; font-size: var(--t-13); }
.crumbs .crumb { color: var(--text-3); padding: 3px var(--s-2); border-radius: var(--r-sm); transition: all var(--d-fast) var(--ease-out); }
.crumbs .crumb:hover { color: var(--text-1); background: var(--surface-2); }
.crumbs .crumb.current { color: var(--text-1); font-weight: var(--w-semi); }
.crumbs .sep { color: var(--text-4); }

.save-chip {
  display: flex; align-items: center; gap: 5px;
  font-size: var(--t-11); color: var(--text-4);
  padding: 3px var(--s-2); border-radius: var(--r-full);
  transition: color var(--d-base) var(--ease-out);
}
.save-chip[data-state="saving"] { color: var(--warn); }
.save-chip[data-state="saved"] { color: var(--text-4); }
.save-chip .dot { transition: background var(--d-base) var(--ease-out); }

/* ======================= MAIN SHELL ===================================== */
.shell { display: flex; flex: 1; min-height: 0; }

/* ---- Icon rail ---------------------------------------------------------- */
.rail {
  width: var(--rail-w); flex: none;
  display: flex; flex-direction: column; align-items: center;
  gap: var(--s-1); padding: var(--s-3) 0;
  background: var(--bg-void);
  border-right: 1px solid var(--line-hair);
  z-index: var(--z-rail);
}
.rail-btn {
  position: relative;
  width: 52px; height: 54px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; border-radius: var(--r-md);
  color: var(--text-4);
  transition: all var(--d-base) var(--ease-out);
}
/* The icons are 16×16 art shown at exactly 2×, so they must never be scaled
   by anything else — and they dim rather than recolour when inactive. */
.rail-btn .rb-icon {
  display: block; width: 32px; height: 32px;
  image-rendering: pixelated;
  opacity: .55;
  filter: saturate(.35);
  transition: opacity var(--d-base) var(--ease-out), filter var(--d-base) var(--ease-out),
              transform var(--d-base) var(--ease-spring);
}
.rail-btn:hover .rb-icon { opacity: .85; filter: saturate(.75); }
.rail-btn[aria-current="true"] .rb-icon { opacity: 1; filter: none; transform: translateY(-1px); }
.rail-btn:active .rb-icon { transform: translateY(1px) scale(.94); }
.rail-btn:disabled .rb-icon { opacity: .22; filter: saturate(0); }
.rail-btn .rb-label { font-size: 9px; font-weight: var(--w-semi); letter-spacing: var(--tr-wide); text-transform: uppercase; }
.rail-btn:hover { color: var(--text-2); background: var(--surface-1); }
.rail-btn[aria-current="true"] { color: var(--text-1); background: color-mix(in srgb, var(--accent) 14%, transparent); }
.rail-btn[aria-current="true"]::before {
  content: ""; position: absolute; left: -12px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 20px; border-radius: 0 3px 3px 0; background: var(--accent);
  animation: fg-rail-in var(--d-base) var(--ease-spring);
}
@keyframes fg-rail-in { from { height: 4px; opacity: 0 } to { height: 20px; opacity: 1 } }
.rail-btn:disabled { opacity: .28; pointer-events: none; }
.rail-sep { width: 26px; height: 1px; background: var(--line-soft); margin: var(--s-2) 0; }

/* ---- View host ---------------------------------------------------------- */
.viewhost { flex: 1 1 0; min-width: 0; display: flex; position: relative; overflow: hidden; }
.view { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
.view[hidden] { display: none !important; }

.view-header {
  padding: var(--s-6) var(--s-8) var(--s-4);
  display: flex; align-items: flex-end; gap: var(--s-4);
  flex: none;
}
.view-header .vh-text { flex: 1; min-width: 0; }
.view-header h1 { font-size: var(--t-26); font-weight: var(--w-bold); letter-spacing: var(--tr-tightest); }
.view-header p { font-size: var(--t-13); color: var(--text-3); margin-top: 4px; max-width: 620px; line-height: 1.5; }
.view-body { flex: 1; min-height: 0; overflow-y: auto; padding: 0 var(--s-8) var(--s-10); }
.view-body.pad-top { padding-top: var(--s-6); }

/* ======================= LIBRARY ======================================== */
.lib-toolbar {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 0 var(--s-8) var(--s-4);
}
.lib-search { width: 250px; }

.lib-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(238px, 1fr));
  gap: var(--s-4);
}

.proj-card {
  display: flex; flex-direction: column;
  border-radius: var(--r-lg);
  background: var(--surface-1);
  box-shadow: var(--bevel), 0 0 0 1px var(--line-hair), var(--sh-2);
  overflow: hidden;
  cursor: pointer;
  transition: transform var(--d-base) var(--ease-out), box-shadow var(--d-base) var(--ease-out);
  text-align: left;
  position: relative;
}
.proj-card:hover { transform: translateY(-3px); box-shadow: var(--bevel), 0 0 0 1px var(--line-soft), var(--sh-4); }
.proj-card:active { transform: translateY(-1px); }
.proj-card .pc-art {
  aspect-ratio: 16 / 10;
  position: relative; overflow: hidden;
  background: var(--bg-sunken);
  border-bottom: 1px solid var(--line-hair);
  display: grid; place-items: center;
}
.proj-card .pc-art canvas, .proj-card .pc-art img { width: 100%; height: 100%; object-fit: cover; }
.proj-card .pc-art::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(0,0,0,.35));
  opacity: 0; transition: opacity var(--d-base) var(--ease-out);
}
.proj-card:hover .pc-art::after { opacity: 1; }
.proj-card .pc-body { padding: var(--s-3) var(--s-3) var(--s-3); display: flex; flex-direction: column; gap: 5px; }
.proj-card .pc-name { font-size: var(--t-13); font-weight: var(--w-semi); letter-spacing: var(--tr-tight); }
.proj-card .pc-ns { font-family: var(--f-mono); font-size: var(--t-10); color: var(--text-4); }
.proj-card .pc-stats { display: flex; align-items: center; gap: var(--s-2); margin-top: 2px; }
.proj-card .pc-menu {
  position: absolute; top: var(--s-2); right: var(--s-2);
  opacity: 0; transform: translateY(-3px);
  transition: all var(--d-fast) var(--ease-out);
  background: var(--glass); backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.proj-card:hover .pc-menu, .proj-card:focus-within .pc-menu { opacity: 1; transform: none; }

.proj-card-new {
  border: 1.5px dashed var(--line-strong);
  background: transparent; box-shadow: none;
  align-items: center; justify-content: center;
  min-height: 210px; gap: var(--s-2); color: var(--text-3);
}
.proj-card-new:hover {
  border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  box-shadow: none; transform: translateY(-3px);
}

/* Stat count pill inside cards */
.stat-mini { display: inline-flex; align-items: center; gap: 4px; font-size: var(--t-11); color: var(--text-3); }
.stat-mini svg { color: var(--text-4); }

/* ======================= SPLIT WORKSPACE ================================ */
.workspace { display: flex; flex: 1; min-width: 0; min-height: 0; }

.wk-sidebar {
  width: var(--sidebar-w); flex: none;
  display: flex; flex-direction: column;
  background: var(--surface-1);
  border-right: 1px solid var(--line-hair);
  min-height: 0;
}
.wk-sidebar-head {
  padding: var(--s-3);
  display: flex; flex-direction: column; gap: var(--s-2);
  border-bottom: 1px solid var(--line-hair);
  flex: none;
}
.wk-sidebar-list { flex: 1; min-height: 0; overflow-y: auto; padding: var(--s-2); display: flex; flex-direction: column; gap: 1px; }
.wk-sidebar-foot { padding: var(--s-2); border-top: 1px solid var(--line-hair); flex: none; }

.wk-main { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; background: var(--bg-base); }

/* ======================= PACK SETTINGS ================================== */
.settings-wrap { max-width: 780px; display: flex; flex-direction: column; gap: var(--s-5); }
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-4); }
.form-grid .span-2 { grid-column: span 2; }
@media (max-width: 900px) { .form-grid { grid-template-columns: minmax(0, 1fr); } .form-grid .span-2 { grid-column: auto; } }

.version-card {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3);
  border-radius: var(--r-md);
  background: var(--bg-sunken);
  box-shadow: inset 0 0 0 1px var(--line-hair);
}
.version-card .vc-num {
  font-family: var(--f-mono); font-size: var(--t-16); font-weight: var(--w-bold);
  color: var(--accent); line-height: 1;
}
.version-card .vc-lbl { font-size: var(--t-10); color: var(--text-4); letter-spacing: var(--tr-wide); text-transform: uppercase; margin-top: 3px; }

.feature-list { display: flex; flex-direction: column; gap: var(--s-1); }
.feature-row {
  display: flex; align-items: center; gap: var(--s-2);
  font-size: var(--t-12); color: var(--text-2);
  padding: var(--s-1) 0;
}
.feature-row .fr-icon { flex: none; }
.feature-row[data-ok="true"] .fr-icon { color: var(--ok); }
.feature-row[data-ok="false"] .fr-icon { color: var(--text-4); }
.feature-row[data-ok="false"] { color: var(--text-4); }

/* pack.png icon editor */
.packicon-slot {
  width: 96px; height: 96px; border-radius: var(--r-md);
  background: var(--bg-sunken); box-shadow: inset 0 0 0 1px var(--line);
  display: grid; place-items: center; overflow: hidden; position: relative;
  cursor: pointer; flex: none;
}
.packicon-slot canvas { width: 100%; height: 100%; }
.packicon-slot .pi-over {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(0,0,0,.55); color: #fff; opacity: 0;
  transition: opacity var(--d-fast) var(--ease-out); font-size: var(--t-11); font-weight: var(--w-semi);
}
.packicon-slot:hover .pi-over { opacity: 1; }

/* ======================= EXPORT VIEW ==================================== */
.export-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); gap: var(--s-5); align-items: start; }
@media (max-width: 1080px) { .export-grid { grid-template-columns: minmax(0, 1fr); } }

.filetree {
  font-family: var(--f-mono); font-size: var(--t-11); line-height: 1.85;
  color: var(--text-2); letter-spacing: 0;
  max-height: 460px; overflow: auto;
  padding: var(--s-3);
}
.filetree .ft-row { display: flex; align-items: center; gap: 6px; white-space: pre; border-radius: 3px; padding: 0 4px; }
.filetree .ft-row:hover { background: var(--surface-2); }
.filetree .ft-dir { color: var(--text-3); }
.filetree .ft-file { color: var(--text-1); }
.filetree .ft-json  { color: var(--emerald-300); }
.filetree .ft-png   { color: var(--amber-300); }
.filetree .ft-ogg   { color: var(--amethyst-300); }
.filetree .ft-mcmeta{ color: var(--diamond-300); }
.filetree .ft-size { margin-left: auto; color: var(--text-4); padding-left: var(--s-4); }

.export-target {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3);
  border-radius: var(--r-md);
  background: var(--bg-sunken);
  box-shadow: inset 0 0 0 1px var(--line-hair);
}
.export-target .et-icon {
  width: 36px; height: 36px; border-radius: var(--r-sm); flex: none;
  display: grid; place-items: center;
  background: var(--surface-3); box-shadow: var(--bevel);
}
.export-target .et-main { flex: 1; min-width: 0; }
.export-target .et-name { font-size: var(--t-13); font-weight: var(--w-medium); }
.export-target .et-meta { font-size: var(--t-11); color: var(--text-4); font-family: var(--f-mono); }

.install-step {
  display: flex; gap: var(--s-3);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--line-hair);
}
.install-step:last-child { border-bottom: none; }
.install-step .is-num {
  width: 22px; height: 22px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: var(--surface-3); box-shadow: var(--bevel);
  font-size: var(--t-11); font-weight: var(--w-bold); color: var(--text-2);
}
.install-step .is-body { flex: 1; min-width: 0; font-size: var(--t-12); color: var(--text-2); line-height: 1.55; }
.install-step .is-body strong { color: var(--text-1); font-weight: var(--w-semi); }
.install-step code {
  font-family: var(--f-mono); font-size: var(--t-11);
  background: var(--bg-sunken); padding: 1px 5px; border-radius: var(--r-xs);
  color: var(--text-1); box-shadow: inset 0 0 0 1px var(--line-hair);
}

/* ======================= COMMAND PALETTE ================================ */
.cmdk-host {
  position: fixed; inset: 0; z-index: var(--z-palette);
  background: var(--scrim);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  display: flex; justify-content: center; align-items: flex-start;
  padding-top: 14vh;
  animation: fg-fade-in var(--d-fast) var(--ease-out);
}
.cmdk {
  width: min(600px, calc(100vw - 48px));
  max-height: 62vh; display: flex; flex-direction: column;
  border-radius: var(--r-xl);
  background: var(--glass);
  backdrop-filter: blur(40px) saturate(1.7); -webkit-backdrop-filter: blur(40px) saturate(1.7);
  box-shadow: var(--sh-5), 0 0 0 1px var(--line-soft), var(--bevel-hi);
  overflow: hidden;
  animation: fg-modal-in var(--d-base) var(--ease-out);
}
.cmdk-input {
  height: 50px; padding: 0 var(--s-4);
  display: flex; align-items: center; gap: var(--s-3);
  border-bottom: 1px solid var(--line-soft);
}
.cmdk-input input { flex: 1; font-size: var(--t-16); letter-spacing: var(--tr-tight); background: none; }
.cmdk-input input::placeholder { color: var(--text-4); }
.cmdk-list { flex: 1; overflow-y: auto; padding: var(--s-2); }
.cmdk-group { padding: var(--s-2) var(--s-2) var(--s-1); font-size: var(--t-10); font-weight: var(--w-bold); letter-spacing: var(--tr-widest); text-transform: uppercase; color: var(--text-4); }
.cmdk-item {
  display: flex; align-items: center; gap: var(--s-3);
  width: 100%; height: 36px; padding: 0 var(--s-3);
  border-radius: var(--r-md); font-size: var(--t-13); color: var(--text-1);
}
.cmdk-item .ci-icon { color: var(--text-3); flex: none; }
.cmdk-item .ci-hint { margin-left: auto; font-size: var(--t-11); color: var(--text-4); }
.cmdk-item[aria-selected="true"] { background: var(--accent); color: var(--text-inv); }
.cmdk-item[aria-selected="true"] .ci-icon, .cmdk-item[aria-selected="true"] .ci-hint { color: var(--text-inv); opacity: .78; }
.cmdk-foot { padding: var(--s-2) var(--s-3); border-top: 1px solid var(--line-soft); display: flex; gap: var(--s-4); font-size: var(--t-10); color: var(--text-4); }
.cmdk-foot span { display: inline-flex; align-items: center; gap: 4px; }

/* ======================= GLOBAL DROP OVERLAY =========================== */
.global-drop {
  position: fixed; inset: 0; z-index: var(--z-overlay);
  background: color-mix(in srgb, var(--accent) 14%, var(--scrim));
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  display: grid; place-items: center;
  animation: fg-fade-in var(--d-fast) var(--ease-out);
  pointer-events: none;
}
.global-drop .gd-card {
  padding: var(--s-8) var(--s-12);
  border-radius: var(--r-2xl);
  border: 2px dashed var(--accent);
  background: var(--glass);
  display: flex; flex-direction: column; align-items: center; gap: var(--s-3);
  animation: fg-pop var(--d-base) var(--ease-spring);
}

/* ======================= RESPONSIVE ===================================== */
/* The stage is the point of the whole screen, so as the window narrows the
   chrome around it gives up room first — sidebar, then panels, then the
   tool dock — and only after that does anything collapse. */
@media (max-width: 1280px) {
  :root { --inspector-w: 296px; --sidebar-w: 236px; --edpanels-w: 228px; }
}
@media (max-width: 1120px) {
  :root { --inspector-w: 272px; --sidebar-w: 208px; --edpanels-w: 212px; --tooldock-w: 42px; }
  .stage-bar .caption { display: none; }
}
@media (max-width: 980px) {
  :root { --sidebar-w: 180px; --edpanels-w: 200px; }
  .wk-sidebar .lr-sub { display: none; }
}
@media (max-width: 860px) {
  /* Below this the list cannot show text and stay useful, so it becomes a
     strip of thumbnails. Everything is still reachable — nothing is hidden. */
  :root { --sidebar-w: 60px; }
  .wk-sidebar-head .eyebrow,
  .wk-sidebar-foot .btn span,
  .list-row .lr-main,
  .list-row .lr-actions { display: none; }
  .list-row { justify-content: center; padding: var(--s-2) 0; }
  .wk-sidebar-head { padding: var(--s-2); }
  .wk-sidebar-head .row { justify-content: center; }
}
@media (max-width: 1000px) {
  .view-header, .lib-toolbar { padding-left: var(--s-5); padding-right: var(--s-5); }
  .view-body { padding-left: var(--s-5); padding-right: var(--s-5); }
  .view-header { flex-direction: column; align-items: stretch; gap: var(--s-3); }
}

/* ============================================================================
   Material — the generated block textures, used sparingly.

   Texture is applied as a low-opacity overlay rather than a literal surface,
   so the app reads as made of stone and oak without ever competing with the
   artwork it is meant to frame.
   ========================================================================= */

[data-textures="off"] .rail::before,
[data-textures="off"] .paint-wall,
[data-textures="off"] .empty .e-art::before { background-image: none !important; }

/* ---- Icon rail: deepslate ------------------------------------------------ */
.rail { position: relative; isolation: isolate; }
.rail::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background-image: var(--tex-deepslate);
  background-size: 48px 48px;
  image-rendering: pixelated;
  opacity: .16;
  mix-blend-mode: overlay;
  pointer-events: none;
}
:root[data-theme="bone"] .rail::before { opacity: .10; }

/* ---- Top bar: a whisper of stone ---------------------------------------- */
.topbar { position: relative; isolation: isolate; }
.topbar::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background-image: var(--tex-stone);
  background-size: 64px 64px;
  image-rendering: pixelated;
  opacity: .05; mix-blend-mode: overlay; pointer-events: none;
}

/* ---- Painting wall preview ----------------------------------------------
   Oak planks, because that is what a painting is nearly always hung on and
   the whole point of this panel is to look like the game.                  */
.paint-wall {
  background-color: #9C7F4E;
  background-image:
    linear-gradient(rgba(0,0,0,.14) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,0,0,.14) 1px, transparent 1px),
    var(--tex-oak);
  background-size: 48px 48px, 48px 48px, 48px 48px;
  image-rendering: pixelated;
}
.paint-wall::before {
  /* Ambient occlusion in the corners, the way the game shades a wall. */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse 90% 80% at 50% 42%, transparent 40%, rgba(0,0,0,.34) 100%);
}

/* ---- Empty-state plinth -------------------------------------------------- */
.empty .e-art { position: relative; overflow: hidden; isolation: isolate; }
.empty .e-art::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background-image: var(--tex-cobble);
  background-size: 48px 48px;
  image-rendering: pixelated;
  opacity: .18; mix-blend-mode: overlay;
}

/* ---- Boot splash --------------------------------------------------------- */
#boot { position: fixed; isolation: isolate; }
#boot::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background-image: var(--tex-deepslate);
  background-size: 72px 72px;
  image-rendering: pixelated;
  opacity: .10; mix-blend-mode: overlay;
}

/* ---- Card art plinth ----------------------------------------------------- */
.proj-card .pc-art { position: relative; }

/* ---- Section dividers get a hairline chisel ------------------------------ */
.panel-head, .section-head { position: relative; }

/* ---- Rail badge: something needs attention -------------------------------- */
.rail-btn .rb-flag {
  position: absolute; top: 5px; right: 8px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--warn);
  box-shadow: 0 0 0 2px var(--bg-void), 0 0 7px var(--warn);
  animation: fg-pop var(--d-base) var(--ease-spring);
}
.rail-btn .rb-flag[data-kind="error"] { background: var(--danger); box-shadow: 0 0 0 2px var(--bg-void), 0 0 7px var(--danger); }

/* ---- View transition ------------------------------------------------------ */
.view:not([hidden]) { animation: fg-view-in var(--d-base) var(--ease-out); }
@keyframes fg-view-in {
  from { opacity: 0; transform: translateY(6px) }
  to   { opacity: 1; transform: none }
}
@media (prefers-reduced-motion: reduce) { .view:not([hidden]) { animation: none } }

/* ---- Sortable list rows --------------------------------------------------
   The insertion line is an accent bar between rows, and the row being carried
   fades so it is obvious which one is in flight. */
.list-row[data-dragging="true"] { opacity: .35; }
.list-row[data-dropbefore="true"]::before,
.list-row[data-dropafter="true"]::after {
  content: ""; position: absolute; left: 6px; right: 6px; height: 2px;
  background: var(--accent); border-radius: 2px;
  box-shadow: 0 0 6px color-mix(in srgb, var(--accent) 70%, transparent);
  animation: fg-fade-in 90ms var(--ease-out);
}
.list-row[data-dropbefore="true"]::before { top: -1px; }
.list-row[data-dropafter="true"]::after { bottom: -1px; }
/* The selection bar and the drop line both use ::before; the drop line wins. */
.list-row[aria-selected="true"][data-dropbefore="true"]::before {
  left: 6px; right: 6px; top: -1px; bottom: auto; width: auto; height: 2px;
}

/* ============================================================================
   Mob variants
   The stage splits into the model and the flat sheet; both drive the same
   document, so they sit side by side rather than behind a tab.
   ========================================================================= */
.mob-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--inspector-w, 320px);
  flex: 1;
  min-width: 0;
  min-height: 0;
}
.mob-stage { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.mob-stage-head {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border-bottom: 1px solid var(--line);
  background: var(--surface-1);
}
.mob-panes { display: grid; flex: 1; min-height: 0; gap: 1px; background: var(--line); }
.mob-panes[data-mode="split"] { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.mob-panes[data-mode="model"],
.mob-panes[data-mode="sheet"] { grid-template-columns: minmax(0, 1fr); }
.mob-pane { position: relative; min-width: 0; min-height: 0; background: var(--surface-0); display: flex; }
.mob-pane.mob-sheet { display: block; overflow: hidden; }

.mob-3d {
  width: 100%; height: 100%; display: block; touch-action: none; cursor: grab;
  background:
    radial-gradient(120% 90% at 50% 12%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 62%),
    var(--surface-0);
}
.mob-3d:active { cursor: grabbing; }
.mob-3d-tools { position: absolute; top: var(--s-2); right: var(--s-2); display: flex; gap: 2px; }
.mob-hint {
  position: absolute; left: 0; right: 0; bottom: var(--s-2);
  text-align: center; font-size: 10px; color: var(--text-4);
  pointer-events: none; letter-spacing: var(--tr-wide);
}
.mob-pane-fallback { padding: var(--s-4); align-self: center; }

.mob-side {
  border-left: 1px solid var(--line);
  background: var(--surface-1);
  overflow-y: auto; overflow-x: hidden;
  min-width: 0;
}

/* Base-texture picker */
.mob-base-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: var(--s-2); max-height: 52vh; overflow-y: auto;
}
.mob-base {
  display: flex; flex-direction: column; gap: 4px; align-items: center;
  padding: var(--s-2); border-radius: var(--r-2);
  background: var(--surface-2); border: 1px solid var(--line);
  cursor: pointer; transition: background var(--d-fast), border-color var(--d-fast), transform var(--d-fast);
}
.mob-base:hover { background: var(--surface-3); border-color: var(--accent); transform: translateY(-1px); }
.mob-base img { width: 100%; height: auto; image-rendering: pixelated; border-radius: var(--r-1); }

/* Import-an-image dialog */
.mob-import { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: var(--s-4); align-items: start; }
.mob-import-stage {
  display: grid; place-items: center; min-width: 0;
  padding: var(--s-3); border-radius: var(--r-2);
  background: var(--surface-2); border: 1px solid var(--line);
}
/* A 4x sheet is 256 across; left to itself it would fill the dialog and push
   the controls off the bottom of the window. */
.mob-import-preview {
  width: auto; max-width: 100%; max-height: 42vh;
  image-rendering: pixelated;
}
@media (max-width: 720px) {
  .mob-import { grid-template-columns: minmax(0, 1fr); }
}

/* Part visibility list */
.mob-parts {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(124px, 1fr));
  gap: 2px;
}
.mob-part-row {
  display: flex; align-items: center; gap: 2px; min-width: 0;
  border-radius: var(--r-1); background: var(--surface-2);
  border: 1px solid var(--line);
}
.mob-part-row[data-off="true"] { opacity: .5; }
.mob-part-eye, .mob-part-name {
  border: 0; background: transparent; color: var(--text-3); cursor: pointer;
  font: inherit; font-size: 11px; padding: 4px;
}
.mob-part-eye { display: grid; place-items: center; width: 24px; flex: none; }
.mob-part-name { flex: 1; min-width: 0; text-align: left; text-transform: capitalize; }
.mob-part-row:hover { border-color: var(--accent); }
.mob-part-row:hover .mob-part-name, .mob-part-row:hover .mob-part-eye { color: var(--text-1); }

/* One sound field. `min-width: 0` matters: the event id is a long nowrap
   string, and without it the row's min-content width pushes the whole
   inspector wider than its column. */
.snd-row {
  display: flex; flex-direction: column; gap: 4px;
  min-width: 0; max-width: 100%; overflow: hidden;
  padding: var(--s-2); border-radius: var(--r-2);
  background: var(--surface-2); border: 1px solid var(--line);
}
.snd-row > * { min-width: 0; }
.snd-row .snd-meta { font-size: 11px; color: var(--text-4); }
.snd-row .snd-id { font-size: 10px; color: var(--accent); }

/* Spawn rules */
.spawn-rule {
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-2); border-radius: var(--r-2);
  background: var(--surface-2); border: 1px solid var(--line);
}
.chip-wrap { display: flex; flex-wrap: wrap; gap: 4px; }
.chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 4px 2px 7px; border-radius: var(--r-1);
  background: var(--surface-3); border: 1px solid var(--line);
  font: var(--w-med) 11px/1.4 var(--font-mono); color: var(--text-2);
}
.chip-x {
  display: grid; place-items: center; width: 14px; height: 14px;
  border: 0; border-radius: 3px; background: transparent; color: var(--text-4); cursor: pointer;
}
.chip-x:hover { background: var(--danger); color: #fff; }

.mob-pick-list { max-height: 48vh; overflow-y: auto; display: flex; flex-direction: column; gap: 1px; }
.mob-pick {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-2);
  padding: 6px var(--s-2); border: 0; border-radius: var(--r-1);
  background: transparent; color: var(--text-2); cursor: pointer; text-align: left;
}
.mob-pick:hover { background: var(--surface-3); color: var(--text-1); }

.kv-grid { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px var(--s-3); font-size: 12px; }
.kv-k { color: var(--text-4); }
.kv-v { color: var(--text-2); }
.kv-v.mono { font-family: var(--font-mono); font-size: 11px; }

@media (max-width: 1100px) {
  .mob-layout { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }
  .mob-side { border-left: 0; border-top: 1px solid var(--line); max-height: 46vh; }
  .mob-panes[data-mode="split"] { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) minmax(0, 1fr); }
}

/* The editor's own panel column is re-homed inside the mob inspector, so it
   stops being a second scrolling region and just stacks with the rest. */
.mob-side .edpanels { width: auto; flex: none; border: 0; background: transparent; }
.mob-side .edpanels-scroll { overflow: visible; max-height: none; padding: 0; }

/* ---- Renamed sprites ----------------------------------------------------
   The same two-column shape as the mob editor: canvas on the left, one
   inspector column on the right holding both the sprite's own settings and
   the editor's panels. */
.spr-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--inspector-w, 320px);
  flex: 1; min-width: 0; min-height: 0;
}
.spr-stage { display: flex; min-width: 0; min-height: 0; }

/* The item picker: a wall of sprites, because that is how anybody finds the
   one they meant. */
.spr-pick { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: var(--s-4); align-items: start; }
.spr-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
  gap: 4px; max-height: 46vh; overflow-y: auto;
  padding: var(--s-2); border-radius: var(--r-2);
  background: var(--bg-sunken); border: 1px solid var(--line);
}
.spr-cell {
  aspect-ratio: 1; display: grid; place-items: center;
  border-radius: var(--r-1); border: 1px solid transparent;
  background: var(--surface-2); cursor: pointer;
  transition: background var(--d-fast), border-color var(--d-fast);
}
.spr-cell:hover { background: var(--surface-3); border-color: var(--line-strong); }
.spr-cell[aria-pressed="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, var(--surface-2));
}
.spr-cell img { width: 28px; height: 28px; image-rendering: pixelated; }
.spr-cell-blank { width: 28px; height: 28px; border: 1px dashed var(--line-strong); border-radius: 2px; }

.spr-chosen {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2); border-radius: var(--r-2);
  background: var(--surface-2); border: 1px solid var(--line);
  min-height: 52px;
}
.spr-chosen img { width: 32px; height: 32px; image-rendering: pixelated; }

/* The in-game preview: one inventory slot and the name under it. */
.spr-preview { display: flex; flex-direction: column; align-items: center; gap: var(--s-2); }
.spr-slot {
  width: 72px; height: 72px; display: grid; place-items: center;
  background: var(--bg-sunken);
  border: 2px solid var(--line-strong);
  box-shadow: inset 2px 2px 0 rgba(0,0,0,.28);
}
.spr-preview-art { width: 64px; height: 64px; image-rendering: pixelated; }
.spr-preview-name {
  font-style: italic; color: var(--text-1);
  text-shadow: 1px 1px 0 rgba(0,0,0,.6);
  padding: 3px 8px; border-radius: var(--r-1);
  background: rgba(16, 0, 24, .82);
  border: 1px solid rgba(80, 40, 160, .6);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The unofficial-fan-tool line, sitting quietly under the pack grid. */
.lib-footer {
  flex: none;
  padding: var(--s-3) var(--s-5) var(--s-4);
  border-top: 1px solid var(--line-hair);
  text-align: center;
}
