/* =========================================================================
   EMPIRIUM OS — VISION BOARDS
   A Deus Ex: Human Revolution–style inventory grid: a fixed 24-column grid
   of square cells that extends downward as needed. Every photo is an
   explicit rectangular footprint — x, y, w, h, all in whole grid cells —
   placed by dragging it anywhere on the board and resized by dragging its
   corner to any whole-cell width/height. No auto-flow, no reflow-on-resize:
   items sit exactly where you put them, like weapons in the game's cargo
   grid. Placement is validated live during drag/resize — invalid (would
   overlap another item, or run off the grid) shows a red tint and reverts
   on release; valid commits on release. The grid grows extra rows live
   while you drag near its bottom edge instead of blocking the drop.
   Namespaced .eo-vb-* throughout.
   ========================================================================= */

.eo-vb-head{ align-items:flex-end; }

.eo-vb-toolbar{
  display:flex; flex-wrap:wrap; align-items:center; gap:10px;
  margin-bottom:14px; padding:12px 14px;
  background:var(--card-subtle); border:1px solid var(--line); border-radius:var(--r-lg);
}
.eo-vb-board-select{ min-width:160px; width:auto; }
.eo-vb-board-name{ width:auto; min-width:160px; flex:1 1 180px; max-width:280px; }
.eo-vb-toolbar-spacer{ flex:1 1 auto; }
.eo-vb-toolbar-note{ font-size:var(--fs-caption); color:var(--faint); white-space:nowrap; }

.eo-vb-warning{
  margin:-4px 0 14px; padding:8px 14px;
  border:1px solid rgba(var(--danger-rgb),.4); border-radius:var(--r-md);
  background:rgba(var(--danger-rgb),.1);
  color:var(--danger-soft); font-size:var(--fs-small);
}

/* ---- the board fills the panel width and never exceeds it: 24 cells at the
   MIN_CELL floor is 576px, narrower than the panel at any realistic window
   size, so --vb-cell (clamped in JS) always divides the available width
   exactly. overflow-x stays `auto` rather than `hidden` purely as a safety
   net for an absurdly narrow window — in normal use it never triggers, and
   `hidden` there would clip tiles instead of letting them be reached. ---- */
.eo-vb-board-wrap{ overflow-x:auto; overflow-y:visible; padding-bottom:6px; }

/* ---- the grid itself: fixed COLS-wide, rows grow downward. --vb-cell and
   --vb-rows are set/updated by JS (eo-vision-boards.js: syncGridMetrics) —
   --vb-cell from the panel's measured width divided by COLS, --vb-rows from
   the lowest occupied cell plus a few empty buffer rows, and live-extended
   during an active drag/resize that reaches toward the bottom. The
   checkerboard + hairline grid is a pure CSS background, not real DOM
   cells — cheap regardless of how many rows the board grows to. ---- */
.eo-vb-grid{
  position:relative;
  width: calc(var(--vb-cols, 24) * var(--vb-cell, 48px));
  height: calc(var(--vb-rows, 12) * var(--vb-cell, 48px));
  min-width: calc(var(--vb-cols, 24) * var(--vb-cell, 48px));
  background-color: var(--card-subtle);
  background-image:
    linear-gradient(45deg, rgba(255,255,255,.035) 25%, transparent 25%, transparent 75%, rgba(255,255,255,.035) 75%),
    linear-gradient(45deg, rgba(255,255,255,.035) 25%, transparent 25%, transparent 75%, rgba(255,255,255,.035) 75%),
    linear-gradient(to right, var(--line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--line) 1px, transparent 1px);
  background-size:
    calc(var(--vb-cell, 48px) * 2) calc(var(--vb-cell, 48px) * 2),
    calc(var(--vb-cell, 48px) * 2) calc(var(--vb-cell, 48px) * 2),
    var(--vb-cell, 48px) var(--vb-cell, 48px),
    var(--vb-cell, 48px) var(--vb-cell, 48px);
  background-position:
    0 0,
    var(--vb-cell, 48px) var(--vb-cell, 48px),
    0 0,
    0 0;
  border:1px solid var(--line-strong);
  border-radius:var(--r-lg);
}

.eo-vb-tile{
  position:absolute;
  left: calc(var(--x) * var(--vb-cell, 48px));
  top: calc(var(--y) * var(--vb-cell, 48px));
  width: calc(var(--w) * var(--vb-cell, 48px));
  height: calc(var(--h) * var(--vb-cell, 48px));
  margin:0; overflow:hidden; cursor:grab;
  outline:1px solid var(--line); outline-offset:-1px;
  touch-action:none; user-select:none;
}
.eo-vb-tile img{
  display:block; width:100%; height:100%; object-fit:cover; pointer-events:none;
  user-select:none;
}

/* A tile whose image blob is missing from IndexedDB (store never written, or
   swept). It keeps its footprint so the layout is unchanged and it can still
   be moved or deleted — it just has nothing to draw. */
.eo-vb-tile-missing{
  background:repeating-linear-gradient(
    45deg, var(--card-subtle), var(--card-subtle) 8px,
    transparent 8px, transparent 16px
  );
}

/* While being dragged/resized the tile rides above every other tile and its
   left/top/width/height are driven by inline style (raw px, set every
   pointermove) instead of the --x/--y/--w/--h calc — that's what makes it
   follow the cursor smoothly instead of snapping cell-by-cell, exactly like
   the reference game. The calc-based rule resumes the instant the inline
   style is cleared (on commit or on revert), which is also why no re-render
   is needed just to snap an item back after an invalid drop. */
.eo-vb-tile.eo-vb-dragging, .eo-vb-tile.eo-vb-resizing{
  cursor:grabbing; z-index:80; box-shadow:0 10px 28px rgba(0,0,0,.5);
  transition:none;
}
.eo-vb-tile.eo-vb-invalid{ outline:2px solid var(--danger); outline-offset:-2px; }
.eo-vb-tile.eo-vb-invalid::after{
  content:''; position:absolute; inset:0; z-index:1;
  background:rgba(var(--danger-rgb), .35); pointer-events:none;
}

.eo-vb-tile-x{
  position:absolute; top:6px; right:6px; width:22px; height:22px; z-index:2;
  display:flex; align-items:center; justify-content:center;
  border:none; border-radius:50%; cursor:pointer; font-size:11px; line-height:1;
  background:rgba(0,0,0,.65); color:#fff; opacity:0;
  transition:opacity var(--t-snap) var(--ease);
}
.eo-vb-tile:hover .eo-vb-tile-x, .eo-vb-tile:focus-within .eo-vb-tile-x{ opacity:1; }

.eo-vb-resize{
  position:absolute; right:2px; bottom:2px; width:18px; height:18px; z-index:2;
  cursor:nwse-resize; opacity:0; touch-action:none;
  background:linear-gradient(135deg, transparent 50%, rgba(255,255,255,.85) 50%);
  transition:opacity var(--t-snap) var(--ease);
}
.eo-vb-tile:hover .eo-vb-resize{ opacity:1; }

.eo-vb-grid.eo-vb-dropping{ outline:2px dashed var(--accent); outline-offset:-2px; }

.eo-vb-empty{
  position:absolute; inset:0; z-index:1; display:flex; align-items:center; justify-content:center;
  color:var(--faint); font-size:var(--fs-small); text-align:center; padding:20px; pointer-events:none;
}

@media (max-width:700px){
  .eo-vb-toolbar{ flex-direction:column; align-items:stretch; }
  .eo-vb-board-name{ max-width:none; }
}
