/* ═══════════════════════════════════════════════════
   SHARED CONTROLS — /maker only (linked directly from
   maker/index.html, NOT imported via main.css, so /studio
   legacy pages are untouched).

   Contents:
   1. Range sliders — Firefox parity + focus ring (the webkit
      track/fill/thumb live in components.css; the accent fill is
      driven by --pct, auto-bound app-wide by SF2_UI in
      js/components/ui-controls.js).
   2. Playback row — THE shared .cv-playback-row block. Promoted
      from character-viewer.css (the visual spec); the per-tab
      copies in mob/npc/pet/skill CSS are deleted. Scoped to
      .cv-shell-section so every current and future tab (misc!)
      gets it with zero markup changes.
   3. Empty states — readable contrast panel behind the icon+line
      (the old bare text was near-invisible over the checkerboard).
   4. sf2-shimmer — the shared loading shimmer keyframes.
   5. .sf2-icon — inline-SVG icon alignment (SF2_ICONS).
   ═══════════════════════════════════════════════════ */

/* ── 1. Range sliders ── */
.maker input[type="range"]::-moz-range-track {
  height: 4px;
  background: var(--border-lo);
  border-radius: var(--r);
  border: none;
}
.maker input[type="range"]::-moz-range-progress {
  height: 4px;
  background: var(--accent);
  border-radius: var(--r);
}
.maker input[type="range"]::-moz-range-thumb {
  width: 13px;
  height: 13px;
  background: var(--chrome-hi);
  border: 1px solid var(--border-lo);
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
  cursor: pointer;
}
.maker input[type="range"]:focus-visible {
  box-shadow: 0 0 0 3px var(--accent-glow);
  border-radius: var(--r);
}
.maker input[type="range"]:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ── 2. Playback row (shared across every viewer tab's rail) ── */
.maker .cv-shell-section .cv-playback-row {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
}
.maker .cv-shell-section .cv-play-btn {
  flex: 1;
  text-align: left;
  padding: var(--sp-2) var(--sp-4);
  font: inherit;
  font-size: var(--fs-4);
  border: none;
  background: transparent;
  border-radius: var(--r);
  cursor: pointer;
  color: var(--text);
  transition: background 0.12s, color 0.12s;
}
.maker .cv-shell-section .cv-play-btn:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.05);
}
.maker .cv-shell-section .cv-play-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.maker .cv-shell-section .cv-play-btn:focus {
  outline: none;
}
/* Pressed state — matches the cat-btn active fill so the sidebar
   reads as a single visual language. Applied while the loop is
   actively playing (manual click can also use :active). */
.maker .cv-shell-section .cv-play-btn.playing,
.maker .cv-shell-section .cv-play-btn:active:not(:disabled) {
  background: rgba(74, 158, 192, 0.18);
  color: var(--accent-text, var(--accent));
  font-weight: 600;
}
.maker .cv-shell-section .cv-frame-nav {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 0 0 auto;
}
.maker .cv-shell-section .cv-frame-nav .zoom-btn {
  width: 22px;
  height: 22px;
  border: none;
  border-radius: var(--r);
  background: transparent;
  color: var(--text-dim);
  font-size: var(--fs-2);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.maker .cv-shell-section .cv-frame-nav .zoom-btn:hover {
  background: rgba(0, 0, 0, 0.05);
  color: var(--text);
}
.maker .cv-shell-section .cv-frame-nav .zoom-btn.is-disabled {
  opacity: 0.35;
  cursor: not-allowed;
  pointer-events: none;
}
.maker .cv-shell-section .cv-frame-counter {
  flex: 1;
  font-size: var(--fs-3);
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  text-align: center;
  padding: 0 var(--sp-1);
}

/* ── 3. Empty states — contrast chip ──
   Bare dim text over the checkerboard canvas was near-invisible
   (Character's "Select a character to preview"). The chip is scoped
   to .canvas-frame states only: the parent flexbox already centers
   the child there, so a compact panel just works. Pane-level
   .tab-pane .empty-state elements are themselves full-pane
   centerers on a flat background — those only get a color bump. */
.maker .canvas-frame .empty-state {
  /* ARP6W4 redesign — quiet dashed card + the snail mascot, replacing
     the plain contrast chip. */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-5);
  background: color-mix(in srgb, var(--chrome-hi, #fff) 80%, transparent);
  border: 1px dashed color-mix(in srgb, var(--text-dim, #636370) 34%, transparent);
  border-radius: var(--r);
  padding: 24px 40px 26px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);
  color: var(--text-mid);
  font-size: 13px;
  text-align: center;
  text-shadow: none;
  /* Size to the message, not the pane. The chip is a block-level flex column,
     so as a flex ITEM of .canvas-frame it inherited `flex: 1 1 0%` and grew to
     ~95% of the frame — a full-width slab behind one line of text, which read
     as a layout bug rather than a hint. `flex: 0 0 auto` + fit-content restores
     the "compact panel" this rule was written to be; margin:auto keeps it
     centred if a frame ever isn't a centering flex container. */
  flex: 0 0 auto;
  width: fit-content;
  max-width: min(90%, 360px);
  margin: auto;
}
.maker .canvas-frame .empty-state .icon {
  /* SF2_SNAIL_SPRITE.swapEmptyIcons() injects the faded Blue Snail
     <img> here. `zoom` (NOT transform: scale) so the scaled size IS
     the layout box — a transform left the visual overflowing its box
     and the snail sat off-center in the card (Derek 2026-08-07). */
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 0;
  opacity: 0.85;
}
.maker .canvas-frame .empty-state .icon .sf2-snail-empty {
  zoom: 2;
}
.maker .tab-pane .empty-state {
  color: var(--text-mid);
}
.maker .empty-state .empty-state-cta {
  margin-top: var(--sp-1);
}

/* ── 4. Shared loading shimmer ── */
@keyframes sf2-shimmer {
  0%   { opacity: 0.35; }
  50%  { opacity: 0.75; }
  100% { opacity: 0.35; }
}

/* ── 5. Inline SVG icons ── */
.sf2-icon {
  display: inline-block;
  vertical-align: -2px;
  flex: 0 0 auto;
}

/* Faded static Blue Snail — the empty-state placeholder (no-emoji rule).
   SF2_SNAIL_SPRITE.emptyIcon()/frame0DataUrl() produce these. */
.sf2-snail-empty {
  image-rendering: pixelated;
  opacity: 0.55;
  filter: saturate(0.75);
}

/* ── 6. Micro-interactions (UX-polish P7) ──
   All motion honors prefers-reduced-motion. The squash-and-stretch
   is the character viewer's cv-preview-bounce generalized (same
   0.42s curve); SF2_UI.bounce(el) triggers it from JS. */
@media (prefers-reduced-motion: no-preference) {
  @keyframes sf2-bounce {
    0%   { scale: 1 1; }
    18%  { scale: 1.06 0.92; }
    38%  { scale: 0.94 1.07; }
    58%  { scale: 1.02 0.97; }
    78%  { scale: 0.99 1.01; }
    100% { scale: 1 1; }
  }
  .maker .sf2-bounce {
    animation: sf2-bounce 0.42s cubic-bezier(0.22, 1, 0.36, 1);
  }

  /* Press feedback — the audit found near-zero :active states app-wide. */
  .maker .npc-btn:active {
    transform: translateY(-1px) scale(0.97);
    transition-duration: 0.06s;
  }
  .maker .char-card:active { transform: translateY(0) scale(0.985); }
  .maker .zoom-btn:active { transform: scale(0.9); }
  .maker .bd-rail-row:active { transform: scale(0.98); }
  .maker .btn:active:not(:disabled) { transform: translateY(1px); }
  .maker .cv-picker-item:active { transform: scale(0.97); }
  .maker .home-create-btn:active { transform: translateY(0) scale(0.985); }

  /* Menus pop in instead of blinking on. */
  @keyframes sf2-pop-in {
    from { opacity: 0; transform: translateY(5px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  .maker .scene-menu-panel:not([hidden]),
  .maker .maker-add-menu:not([hidden]),
  .maker .cust-add-menu:not([hidden]) {
    animation: sf2-pop-in 0.14s ease-out;
  }
}

/* Keyboard focus — visible ring on cards/cells that lacked one. */
.maker .char-card:focus-visible,
.maker .home-create-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── Frame Picker cards (R4-U5/U6) — one card language for every tab's
   frame picker (mob/NPC/pet/skill docks + the character picker chips get
   their own scoped copy). Matches the bottom thumbnail-grid cells: the
   card owns ONE light gradient background (no differently-colored inner
   thumb box), icon area, fN label, accent border when active. Loaded
   after main.css so these equal-specificity rules win the per-tab ones. */
.maker .tab-mob .mob-pose-picker-card,
.maker .tab-npc .npc-pose-picker-card,
.maker .tab-pet .pet-pose-picker-card,
.maker .tab-skill .skill-kind-picker-card {
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  gap: 3px; padding: var(--sp-2) 3px var(--sp-1); min-height: 64px;
  background: var(--cell-grad, linear-gradient(#fff, #f2f4f6));
  border: 1px solid var(--border-lo);
  border-radius: var(--r);
  cursor: pointer; font: inherit;
  transition: background 0.12s, border-color 0.12s;
}
.maker .tab-mob .mob-pose-picker-card:hover,
.maker .tab-npc .npc-pose-picker-card:hover,
.maker .tab-pet .pet-pose-picker-card:hover,
.maker .tab-skill .skill-kind-picker-card:hover {
  background: var(--cell-grad-hover, #fff);
  border-color: var(--accent);
}
.maker .tab-mob .mob-pose-picker-card.active,
.maker .tab-npc .npc-pose-picker-card.active,
.maker .tab-pet .pet-pose-picker-card.active,
.maker .tab-skill .skill-kind-picker-card.active {
  background: var(--cell-grad, linear-gradient(#fff, #f2f4f6));
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.maker .tab-mob .mob-pose-picker-card canvas,
.maker .tab-npc .npc-pose-picker-card canvas,
.maker .tab-pet .pet-pose-picker-card canvas,
.maker .tab-skill .skill-kind-picker-card canvas {
  background: transparent;          /* the card is the backdrop — no inner box */
  image-rendering: pixelated;
  max-width: 48px; max-height: 48px; display: block;
}
.maker .tab-mob .mob-pose-picker-card-label,
.maker .tab-npc .npc-pose-picker-card-label,
.maker .tab-pet .pet-pose-picker-card-label,
.maker .tab-skill .skill-kind-picker-card-label {
  font-size: var(--fs-1); color: var(--text-dim); font-variant-numeric: tabular-nums;
}
.maker .tab-mob .mob-pose-picker-card.active .mob-pose-picker-card-label,
.maker .tab-npc .npc-pose-picker-card.active .npc-pose-picker-card-label,
.maker .tab-pet .pet-pose-picker-card.active .pet-pose-picker-card-label,
.maker .tab-skill .skill-kind-picker-card.active .skill-kind-picker-card-label {
  color: var(--accent-text, var(--accent));
  font-weight: 600;
}

/* ── Uniform Export sections (R4-U7): always expanded, pinned to the
   sidebar bottom. The sidebar is a flex column; margin-top:auto pushes
   the Export section (plus anything after it) to the bottom edge. ── */
.maker .cv-shell-section.cv-shell-export { margin-top: auto; }
.maker .cv-shell-section.cv-shell-export .cv-shell-section-header { cursor: default; }

/* ── PERF-1 — picker-grid cell containment (docs/maker-performance-epic.md) ──
   Every picker grid (Maps / NPCs / Mobs / Pets / Items / Import-Map) builds one
   `.npc-btn` per catalog entry. Modern GMS Maps is 21,428 of them (24,104 cells
   with group headers, 121,752 DOM nodes), and a VISIBLE grid that large made
   every animation frame recalculate style across ~21k elements at 85-138 ms a
   pass — pinning the main thread at 97 % and the app at 6.3 fps, which in turn
   starved the map loader's own request chain (60.3 s cold load).

   `content-visibility: auto` lets the engine skip style/layout/paint for the
   off-screen cells. Measured on modern Maps: 6.3 -> 25.4 fps, setTimeout(0)
   160 ms -> 20 ms, with no JS change.

   The cards carry an explicit `height: 72px`, so their box geometry is already
   definite and the grid tracks size from the container — `contain-intrinsic-size`
   only backstops the skipped subtree, it does not drive column width.

   SF2_VGRID (PERF-2) caps the live node count outright; this rule stays as the
   floor for any grid it does not cover, and for filtered views under the cap. */
.maker .npc-btn {
  content-visibility: auto;
  contain-intrinsic-size: auto 72px;
}

/* ── Animation-rail parity (promoted from the character tab 2026-08-11) ──
   Icon-only play button · scrubbable frame counter ("0 / 3", whole area
   drags via SF2_UI.wireFrameScrub) · inline anim dropdown · the
   Frame Picker "panel row" (bordered, chevron rotates when its dock is
   open). Shared by character/npc/mob/pet/skill rails. */
.maker .cv-playback-row .cv-play-btn.cv-play-ico {
  flex: 0 0 auto;
  width: 26px;
  padding: 3px 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.maker .cv-playback-row .cv-anim-select {
  flex: 1;
  width: auto;
  min-width: 0;
}

.maker .cv-frame-scrub {
  width: 30px;
  padding: 3px 2px;
  font-size: var(--fs-3);
  border: 1px solid transparent;
  border-radius: var(--r);
  background: transparent;
  transition: border-color 0.12s, background 0.12s;
}

.maker .cv-frame-scrub:hover:not(:disabled) {
  border-color: var(--border-lo);
  background: var(--chrome-hi, #fff);
}

.maker .cv-frame-scrub:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--chrome-hi, #fff);
}

.maker .cv-frame-scrub:disabled {
  color: var(--text-dim);
  font-weight: 400;
  cursor: default;
}

.maker .cv-frame-total {
  font-size: var(--fs-3);
  color: var(--text-dim);
  white-space: nowrap;
  min-width: 16px;
}

.maker .cv-panel-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  background: var(--chrome-lo);
  border: 1px solid var(--border-lo);
  border-radius: var(--r);
  font-size: var(--fs-3);
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}

.maker .cv-panel-row:hover {
  background: #fff;
  border-color: var(--accent);
  color: var(--accent-text);
}

.maker .cv-panel-row .cv-panel-row-chev {
  font-size: 13px;
  line-height: 1;
  color: var(--text-dim);
  transition: transform 0.15s;
}

.maker .cv-panel-row:hover .cv-panel-row-chev {
  color: var(--accent-text);
}

.maker .cv-panel-row.is-active .cv-panel-row-chev {
  transform: rotate(90deg);
}

.maker .cv-playback-row .cv-frame-nav {
  cursor: ew-resize;
  user-select: none;
}
