/* texturePackPicker.css - styles for shared/texturePackPicker.js and the
   texture modal it opens (client/game/ui/textureBrowser.js). Reads the
   game's --surface-* variables when present (in-game settings) and falls
   back to the same literal values so the profile page renders identically.

   One deliberate visual device: every sprite preview sits on a checkerboard
   (the standard transparency backing of texture editors), so translucent
   art reads correctly and previews are recognizable as game assets at a
   glance. Selection state is the game's gold accent, nothing else.

   Layout model: a fixed toolbar (search + bulk actions) and a fixed
   Apply-All footer bracket a single scrolling list in the middle, so
   neither ever scrolls out of reach while browsing 40+ tile slots. */

.hidden { display: none; }
.texturePackPicker {
  font-size: 13px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  /* Bounded so the toolbar and Apply-All footer below stay fixed in place
     while only the list/grid between them scrolls. A dedicated host
     context (the Textures tab, ui/settingsPanel.js) can raise this via its
     own rule; this is the sane default everywhere else, including the
     profile page's standalone picker. */
  max-height: 460px;
}

/* Checkerboard transparency backing shared by every sprite preview. */
.tppThumb, .tppOption img {
  --tpp-check-a: var(--surface-1, #363b44);
  --tpp-check-b: var(--surface-2, #40464f);
  background: repeating-conic-gradient(var(--tpp-check-b) 0% 25%, var(--tpp-check-a) 0% 50%) 0 0 / 12px 12px;
  border: 1px solid var(--border, #4e555f);
  border-radius: 3px;
  image-rendering: pixelated;
}

/* ---- toolbar: search + "change all to one theme" ------------------------ */
.tppToolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  flex: none;
}
/* Inside the horizontal toolbar (search + "change all"), the search box
   grows to fill the row instead of the modal's full-width column default. */
.tppToolbar .tppSearch { flex: 1; width: auto; }

.tppSearch {
  flex: none;
  width: 100%;
  min-width: 120px;
  padding: 7px 10px 7px 28px;
  box-sizing: border-box;
  background: var(--surface-2, #40464f) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13' fill='none' stroke='%23a4aab3' stroke-width='1.6'%3E%3Ccircle cx='8.5' cy='8.5' r='6'/%3E%3Cpath d='M13 13l5 5' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat 8px center;
  color: var(--text, #e2e4e8);
  border: 1px solid var(--border, #4e555f);
  border-radius: 4px;
  font: inherit;
}
.tppSearch::placeholder { color: var(--text-faint, #7d838c); }
.tppSearch:focus { outline: none; border-color: var(--accent, #c9a24e); }
/* Native clear-button (webkit) recolored to match the dark field instead of
   inheriting a light system default. */
.tppSearch::-webkit-search-cancel-button { filter: grayscale(1) opacity(0.6); cursor: pointer; }

.tppTileRow {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px;
  border-radius: 4px;
}
.tppTileRow:hover { background: var(--surface-1, #363b44); }

.tppThumb {
  width: 44px;
  height: 44px;
  flex: none;
  object-fit: contain;
  transition: transform 0.12s ease;
}

.tppTileName {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

/* Small status pill ("Set by host", "custom", "default") - state as a
   label, not a parenthetical. */
.tppBadge {
  flex: none;
  font-size: 10px;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  padding: 3px 6px;
  border-radius: 999px;
  color: var(--accent, #c9a24e);
  border: 1px solid var(--accent-dim, #4a4230);
  background: var(--accent-dim, #4a4230);
}

/* :not(.tppIconBtn) throughout - the Lock/Edit icon buttons (Global
   Textures, Cell Texture, Personal picker rows) keep their own fixed
   square sizing (.tppIconBtn below); .tppTileRow button would otherwise
   outrank that single-class rule (one more selector = higher specificity)
   and stretch them back into text-button proportions. */
.tppTileRow button:not(.tppIconBtn),
.tppChangeAll button {
  padding: 4px 10px;
  cursor: pointer;
  background: var(--surface-2, #40464f);
  color: var(--text, #e2e4e8);
  border: 1px solid var(--border, #4e555f);
  border-radius: 4px;
  font-size: 12px;
}
.tppTileRow button:not(.tppIconBtn):hover:not(:disabled),
.tppChangeAll button:hover:not(:disabled) {
  background: var(--surface-3, #4b525c);
}
.tppTileRow button:not(.tppIconBtn):disabled,
.tppChangeAll button:disabled {
  opacity: 0.4;
  cursor: default;
}
.tppTileRow button:not(.tppIconBtn).active {
  border-color: var(--accent, #c9a24e);
  color: var(--accent, #c9a24e);
}

.tppTileList {
  flex: 1;
  min-height: 120px;
  overflow-y: auto;
  scrollbar-width: thin;
}

/* Group section heading ("Flags", "Boosts", ...) - sticky within the
   scrolling list so it's always clear which category is currently in view,
   the same affordance a long alphabetized settings list badly needed. */
.tppGroupHeader {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 5px 6px;
  margin-top: 4px;
  background: var(--surface-0, #2c3038);
  color: var(--text-dim, #a4aab3);
  font-size: 10px;
  font-weight: bold;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-bottom: 1px solid var(--border, #4e555f);
}
.tppGroupHeader:first-child { margin-top: 0; }
.tppGroupCount {
  font-weight: normal;
  color: var(--text-faint, #7d838c);
  letter-spacing: normal;
  text-transform: none;
}

.tppEmpty {
  padding: 24px 8px;
  text-align: center;
  color: var(--text-faint, #7d838c);
  font-size: 12px;
}

.tppNotice {
  font-size: 12px;
  color: var(--text-dim, #a4aab3);
  margin: 0;
}

/* ---- the shared texture-picker modal (textureBrowser.js) ----------------
   One instance, built once, reused by all three pickers: click a slot ->
   this opens over everything -> click an option -> it applies and this
   closes. No footer, no "confirm" step - the grid IS the whole modal. */
.tppModalBackdrop {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  box-sizing: border-box;
}
.tppModalBackdrop.hidden { display: none; }

.tppModal {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(560px, 100%);
  max-height: min(600px, 100%);
  background: var(--surface-0, #2c3038);
  color: var(--text, #e2e4e8);
  border: 1px solid var(--border, #4e555f);
  border-radius: 8px;
  padding: 14px;
  box-sizing: border-box;
  box-shadow: 0 12px 48px rgba(0, 0, 0, 0.6);
}

.tppModalHeader {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex: none;
}
.tppModalTitle { font-weight: bold; font-size: 15px; }
.tppModalHeader .tppIconBtn { width: 24px; height: 24px; font-size: 16px; }

.tppGrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, max-content));
  gap: 8px;
  flex: 1;
  min-height: 80px;
  overflow-y: auto;
  scrollbar-width: thin;
  align-content: start;
}

.tppOption {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 8px 4px 6px;
  background: var(--surface-1, #363b44);
  border: 2px solid transparent;
  border-radius: 5px;
  cursor: pointer;
  color: inherit;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.tppOption:hover { background: var(--surface-2, #40464f); }
.tppOption:hover img { transform: scale(1.12); }
.tppOption.active {
  border-color: var(--accent, #c9a24e);
  background: var(--accent-dim, #4a4230);
}
.tppOption:focus-visible {
  outline: 2px solid var(--accent, #c9a24e);
  outline-offset: 1px;
}

/* Change All confirm step - a plain preview grid, not a picker, so its
   cells keep the pointer cursor (they're still clickable, to exclude) but
   drop the hover-zoom feedback .tppOption implies for an actual pick. */
.tppOption.tppOptionStatic:hover img { transform: none; }

/* Clicked to exclude from this "change all" - grayed out, stays this way
   until clicked again. Click still works while excluded (toggle, not a
   one-way disable), so no pointer-events:none. */
.tppOption.tppOptionExcluded { opacity: 0.35; }
.tppOption.tppOptionExcluded:hover { background: var(--surface-1, #363b44); }

/* A group header inside a CSS grid (the Change All confirm list) needs an
   explicit span - unlike .tppTileList's flex column, a grid item defaults
   to one cell and would sit squeezed into the thumbnail grid otherwise. */
.tppGrid .tppGroupHeader { grid-column: 1 / -1; }

.tppOption img {
  width: 56px;
  height: 56px;
  object-fit: contain;
  transition: transform 0.12s ease;
}

.tppOption span {
  font-size: 10px;
  text-align: center;
  word-break: break-word;
  color: var(--text-dim, #a4aab3);
}
.tppOption.active span { color: var(--text, #e2e4e8); }

/* "Change all to one theme" row (toolbar, logged-in only) */
.tppChangeAll {
  display: flex;
  gap: 6px;
  align-items: center;
  flex: none;
}
.tppChangeAll select {
  min-width: 0;
  padding: 4px;
  background: var(--surface-2, #40464f);
  color: var(--text, #e2e4e8);
  border: 1px solid var(--border, #4e555f);
  border-radius: 4px;
}

/* Slot currently forced by the room host ("Set by host") */

/* Icon-only Lock/Edit buttons (Global Textures list) */
.tppIconBtn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 4px;
  color: var(--text-dim, #a4aab3);
  flex: none;
}
.tppIconBtn:hover:not(:disabled) { color: var(--text, #e2e4e8); background: var(--surface-2, #40464f); }
.tppIconBtn:disabled { opacity: 0.35; cursor: default; }
.tppIconBtn.active { color: var(--accent, #c9a24e); background: var(--accent-dim, #4a4230); }

/* Clickable thumbnail = opens the picker, same as the pencil button */
.tppThumbClickable { cursor: pointer; }
.tppThumbClickable:hover { outline: 2px solid var(--accent, #c9a24e); outline-offset: 1px; transform: scale(1.06); }

/* A tile with an unapplied staged change - the row itself flags it, not
   just the badge, since the change hasn't reached the room yet. */
.tppTileRow.tppPending { background: var(--accent-dim, #4a4230); }
.tppBadge.tppBadgePending { color: #1d2025; background: var(--accent, #c9a24e); border-color: var(--accent, #c9a24e); }

/* ---- Apply All / Discard All footer -------------------------------------
   Sits below the scrolling list as a fixed footer (flex: none, the list is
   the only flex: 1 region) so it's always reachable without hunting for it
   at the bottom of a long scroll. */
.tppApplyRow {
  display: flex;
  gap: 8px;
  flex: none;
  padding-top: 8px;
  border-top: 1px solid var(--border, #4e555f);
}
.tppApplyBtn {
  flex: 1;
  font-weight: bold;
  color: var(--accent, #c9a24e) !important;
  border-color: var(--accent-dim, #4a4230) !important;
}
.tppApplyBtn:not(:disabled):hover { background: var(--accent-dim, #4a4230) !important; }

/* ---- drag-and-drop upload zone ------------------------------------------
   Replaces a bare file input with a full click/drop target, so uploading a
   custom texture doesn't require hunting for the native "Choose File"
   button. The label/file/button row inside stays for keyboard users and as
   the explicit "commit the upload" action. */
.tppDropzone {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: none;
  padding: 10px;
  border: 1px dashed var(--border, #4e555f);
  border-radius: 5px;
  background: var(--surface-1, #363b44);
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.tppDropzone:hover { border-color: var(--text-dim, #a4aab3); }
.tppDropzone.tppDropActive { border-color: var(--accent, #c9a24e); background: var(--accent-dim, #4a4230); }
.tppDropzoneHint {
  font-size: 11px;
  color: var(--text-dim, #a4aab3);
  text-align: center;
  pointer-events: none;
}
.tppDropzone input[type="text"] {
  padding: 5px 8px;
  background: var(--surface-2, #40464f);
  color: var(--text, #e2e4e8);
  border: 1px solid var(--border, #4e555f);
  border-radius: 4px;
  font: inherit;
}
.tppFileInput { font-size: 11px; color: var(--text-dim, #a4aab3); }


/* ---- pack view: the sprites themselves, nothing around them ------------ */

.tppPackView { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.tppPackActions { display: flex; gap: 8px; align-items: center; flex: none; }

/* The wall sheet on the left at full size, the 40x40 tiles packed beside
   it - the same arrangement the contact sheet uses, for the same reason:
   walls is a 480x440 auto-tile grid and only means anything whole. */
.tppPackBody {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  overflow: auto;
  min-height: 0;
  padding: 8px;
  background: repeating-conic-gradient(var(--surface-2, #40464f) 0% 25%, var(--surface-1, #363b44) 0% 50%) 0 0 / 16px 16px;
  border: 1px solid var(--border, #4e555f);
  border-radius: 6px;
}

.tppWallsColumn { flex: none; }

/* No gap: the sprites butt together the way they do in the game, instead of
   floating in a grid of cards. */
.tppTiles {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-start;
  gap: 0;
  min-width: 320px;
}

/* Nothing but the sprite. No border, background, padding or label - the
   only visible state is the hover/selection outline, drawn inside the
   sprite's own bounds so picking one never shifts the others. */
.tppTile {
  padding: 0;
  border: 0;
  background: none;
  line-height: 0;
  cursor: pointer;
  outline-offset: -2px;
}
.tppTile:hover:not(:disabled) { outline: 2px solid var(--accent, #c9a24e); }
.tppTile:disabled { cursor: default; }

/* Deliberately unsized: the image renders at its intrinsic pixel size, so a
   40x40 tile is 40x40 and marsBall is 80x80. Any width/height here would be
   a resize, which is exactly what this view must not do. */
.tppTile img {
  display: block;
  image-rendering: pixelated;
}
.tppTileEmpty { width: 40px; height: 40px; }

/* Still used by the gallery's preview pane. */
.tppPackSheet {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 10px;
  background: repeating-conic-gradient(var(--surface-2, #40464f) 0% 25%, var(--surface-1, #363b44) 0% 50%) 0 0 / 16px 16px;
  border: 1px solid var(--border, #4e555f);
  border-radius: 6px;
  min-height: 0;
  overflow: auto;
}
/* No max-width: scaling the preview down is what made it unreadable. It
   scrolls inside its pane instead. */
.tppPackSheet img { image-rendering: pixelated; display: block; }

.tppPackBtn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  background: var(--surface-2, #40464f);
  color: var(--text, #e2e4e8);
  border: 1px solid var(--border, #4e555f);
  border-radius: 4px;
  font: inherit;
  cursor: pointer;
}
.tppPackBtn:hover:not(:disabled) { background: var(--surface-3, #4b525c); }
.tppPackBtn:disabled { opacity: 0.5; cursor: not-allowed; }
.tppPackBtn.primary {
  background: var(--accent-dim, #4a4230);
  border-color: var(--accent, #c9a24e);
  color: var(--accent, #c9a24e);
}

/* ---- back row (gallery) ------------------------------------------ */

.tppBackRow { display: flex; align-items: center; gap: 8px; flex: none; }
.tppBackBtn {
  padding: 4px 10px;
  background: var(--surface-2, #40464f);
  color: var(--text, #e2e4e8);
  border: 1px solid var(--border, #4e555f);
  border-radius: 4px;
  font: inherit;
  cursor: pointer;
}
.tppBackBtn:hover { background: var(--surface-3, #4b525c); }
.tppBackTitle { font-weight: 600; }

/* ---- gallery: swatch grid beside a full-size preview -------------------- */

.tppGalleryView { display: flex; flex-direction: column; gap: 8px; min-height: 0; }

/* Two panes: a scrolling grid of swatches to scan, and a preview pane that
   stays put while you scan. Collapses to one column when there isn't room
   for both (the profile page's narrower container). */
.tppGalleryBody {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 260px);
  gap: 12px;
  min-height: 0;
}
@media (max-width: 720px) {
  .tppGalleryBody { grid-template-columns: minmax(0, 1fr); }
}

.tppGalleryGrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 8px;
  overflow-y: auto;
  min-height: 0;
  align-content: start;
}
.tppGalleryCell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 6px;
  background: var(--surface-1, #363b44);
  border: 1px solid var(--border, #4e555f);
  border-radius: 5px;
  color: var(--text-dim, #a4aab3);
  font: inherit;
  font-size: 11px;
  cursor: pointer;
}
.tppGalleryCell:hover { background: var(--surface-2, #40464f); }
.tppGalleryCell.selected {
  border-color: var(--accent, #c9a24e);
  background: var(--accent-dim, #4a4230);
  color: var(--accent, #c9a24e);
}
/* Native size, like everything else here: the swatch is generated at 92x92
   (assets/themePreviewBuilder.js) and squeezing it to 56 was a downscale
   for no reason. */
.tppGalleryCell img {
  image-rendering: pixelated;
  display: block;
}
.tppGalleryCell span {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tppGalleryPreview {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  overflow: auto;
}
.tppGalleryPreviewName { font-weight: 600; }

/* ---- source tabs (texture modal): which tile's sprites you're browsing --- */

/* One row, horizontally scrollable - there are ~48 source tiles and they
   must not wrap into a wall of buttons above the grid. */
.tppSourceTabs {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  padding-bottom: 4px;
  flex: none;
}
.tppSourceTab {
  padding: 4px 9px;
  white-space: nowrap;
  background: var(--surface-1, #363b44);
  color: var(--text-dim, #a4aab3);
  border: 1px solid var(--border, #4e555f);
  border-radius: 999px;
  font: inherit;
  font-size: 11px;
  cursor: pointer;
}
.tppSourceTab:hover { background: var(--surface-2, #40464f); }
.tppSourceTab.active {
  background: var(--accent-dim, #4a4230);
  border-color: var(--accent, #c9a24e);
  color: var(--accent, #c9a24e);
}
