/* ================================================================= */
/* == FORMAS.AI PLACEHOLDER STYLES                                == */
/* == Consolidated placeholder styles for chat interface          == */
/* ================================================================= */

/* ================= CSS VARIABLES ================= */
:root {
  --text-placeholder: #6a6a6a;

  /* ─── PLASMA LOADER — ONE SOURCE OF TRUTH ────────────────────────
   * The loader tracks the SAME sizing system the finished media uses
   * (--chat-media-max, defined on .chat-messages and responsive), at
   * 75% — so the plasma is never bigger than the image it resolves
   * into, and it gently grows into the final result instead of
   * snapping down from a huge box. Change the 0.75 to retune.
   * Fallback mirrors --chat-media-max for contexts outside .chat-messages. */
  --plasma-loader-scale: 0.75;
  --plasma-loader-size: calc(var(--chat-media-max, min(720px, 70%)) * var(--plasma-loader-scale));
}

/* ================= GENERATION PLACEHOLDERS ================= */

/* 
 * Generation Placeholders - Match received image sizing system
 * 
 * To set dynamic aspect ratios, use CSS custom property:
 * style="--placeholder-aspect-ratio: 16/9" for landscape
 * style="--placeholder-aspect-ratio: 9/16" for portrait
 * style="--placeholder-aspect-ratio: 1/1" for square (default)
 * 
 * Width matches received images exactly:
 * - Desktop (1024px+): 800px max-width
 * - Default: 600px max-width  
 * - Mobile (768px-): 400px max-width
 */

/* Error message styling for failed placeholders */
.error-message {
  display: none;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #ff6b6b;
  font-size: 14px;
  font-weight: 500;
  text-align: center;
  padding: 20px;
  background: rgba(255, 107, 107, 0.1);
  border: 1px solid rgba(255, 107, 107, 0.3);
  border-radius: 8px;
  margin: 10px;
}

.error-message.visible {
  display: flex;
}
/* Generation placeholders. ONE size for every device, every aspect ratio,
 * every generation type. Tweak --plasma-loader-size at :root above to
 * change the loader size everywhere — there are no other sources of truth. */
.chat-img-wrapper.generation-placeholder {
  width: min(var(--plasma-loader-size), 100%);
  max-width: var(--plasma-loader-size);
  height: auto;
  overflow: hidden;
  border-radius: 12px;
  display: block;
  position: relative;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
}

/* Image placeholders can have dynamic aspect ratios (set per-message via
 * --placeholder-aspect-ratio inline). Falls back to square. */
.chat-img-wrapper.generation-placeholder.image-placeholder {
  aspect-ratio: var(--placeholder-aspect-ratio, 1 / 1);
}

/* PLASMA LOADER SIZE — the real fix for BOTH "HUGE" and "no plasma at all".
 *
 * The plasma placeholder has no intrinsic width (its canvas is position:absolute),
 * so inside the shrink-wrapping flex `.message-content` it collapses to ~0px —
 * that's why most generations showed NO plasma (a 1×1 box). When a sibling forced
 * the lane width instead, it ballooned to the full 640px media cap from
 *   @media (min-width:1024px){ .message.assistant .chat-img-wrapper{max-width:640px} }
 * — that's the "HUGE". A finished <img> dodges this because JS stamps it a
 * fixed pixel width (.fixed-width); the placeholder never got one.
 *
 * Step 1: give the image/video placeholder's message-content a DEFINITE width
 * (it then resolves to the same media cap a finished image would use, via its
 * own max-width:min(720px,70%)). Scoped by data-type so model/pointcloud
 * placeholders keep their existing footprints. */
.message.assistant.placeholder-message[data-type="image"] .message-content,
.message.assistant.placeholder-message[data-type="video"] .message-content {
  flex: 1 1 auto;
  min-width: 0;
}
/* Step 2: size the loader to 75% of that definite media width. 5-class selector
 * outranks the generic 640px cap. width:75% (not --plasma-loader-size) because
 * message-content is ALREADY the media size — re-applying --chat-media-max's 70%
 * here would double-shrink it. */
.message.assistant .chat-img-wrapper.generation-placeholder.image-placeholder,
.message.assistant .chat-img-wrapper.generation-placeholder.video-placeholder {
  width: calc(100% * var(--plasma-loader-scale));
  max-width: calc(100% * var(--plasma-loader-scale));
}

/* 3D model placeholders stay square. */
.message.assistant.placeholder-message[data-type="model"] .message-content {
  flex: 1 1 auto;
  width: min(var(--chat-model-card-size, 520px), 100%);
  min-width: 0;
  max-width: var(--chat-model-card-size, 520px);
}

.chat-img-wrapper.generation-placeholder.model-placeholder {
  width: min(var(--chat-model-card-size, 520px), 100%);
  max-width: var(--chat-model-card-size, 520px);
  aspect-ratio: 1 / 1;
  padding: 0;
  box-sizing: border-box;
}

/* Pointcloud placeholders keep their compact 300px footprint — they're
 * not the main generation loader, they sit alongside it. */
.chat-img-wrapper.generation-placeholder.pointcloud-placeholder {
  width: min(300px, 100%);
  max-width: 300px;
  aspect-ratio: 1 / 1;
  padding: 5px;
  box-sizing: border-box;
}

/* Video placeholders use the same single size as images. */
.chat-img-wrapper.generation-placeholder.video-placeholder {
  aspect-ratio: var(--placeholder-aspect-ratio, 1 / 1) !important;
}

.chat-img-wrapper.generation-placeholder.video-placeholder .image-generation-placeholder {
  width: 100% !important;
  height: 100% !important;
  aspect-ratio: inherit !important;
}

/* Mobile keeps the same conceptual size — the `min(var(--plasma-loader-size), 100%)`
 * above already collapses to the viewport width on narrow screens. Only the
 * corner radius is slightly tighter for mobile feel. */
@media (max-width: 768px) {
  .chat-img-wrapper.generation-placeholder {
    border-radius: 10px;
  }

  .chat-img-wrapper.generation-placeholder.pointcloud-placeholder {
    max-width: 260px;
  }
}

/* Force transparent backgrounds for GPU plasma placeholders (all types) */
.chat-img-wrapper.generation-placeholder.image-placeholder,
.chat-img-wrapper.generation-placeholder.video-placeholder,
.chat-img-wrapper.generation-placeholder.model-placeholder,
.chat-img-wrapper.generation-placeholder.pointcloud-placeholder {
  background: transparent !important;
}

.image-generation-placeholder.img-placeholder,
.image-generation-placeholder.video-placeholder,
.image-generation-placeholder.model-placeholder,
.image-generation-placeholder.pointcloud-placeholder {
  background: transparent !important;
}

/* Keep the visual surface locked to the responsive chat capsule. */
.chat-img-wrapper.generation-placeholder > .image-generation-placeholder.plasma-placeholder {
  width: 100% !important;
  height: 100% !important;
  min-width: 0 !important;
  min-height: 0 !important;
  max-width: 100% !important;
  max-height: 100% !important;
  margin: 0 !important;
  aspect-ratio: inherit;
}

.chat-img-wrapper.generation-placeholder.batch-generation-placeholder {
  width: min(640px, 100%) !important;
  height: auto !important;
  min-height: 0 !important;
  aspect-ratio: auto !important;
  padding: 0 !important;
  overflow: hidden !important;
}

.batch-generation-placeholder .batch-plasma-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px;
  width: 100%;
  height: auto;
  min-width: 0;
}

/* Always 2 columns so individual tiles stay big.
 *   2 images → row of 2.
 *   3 images → 2 + 1 (3rd centered on row 2, same column-width as the others).
 *   4 images → 2 × 2. */
.batch-generation-placeholder.batch-count-2 .batch-plasma-grid,
.batch-generation-placeholder.batch-count-3 .batch-plasma-grid,
.batch-generation-placeholder.batch-count-4 .batch-plasma-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
/* For 3 items the 3rd lands naturally at row 2 / col 1. Center it across
 * both columns while keeping it the same visual width as the cells above
 * (½ of grid minus half the gap). */
.batch-generation-placeholder.batch-count-3 .batch-plasma-cell:nth-child(3) {
  grid-column: 1 / -1;
  justify-self: center;
  width: calc((100% - 4px) / 2);
}

.batch-generation-placeholder .batch-plasma-cell {
  position: relative;
  min-width: 0;
  /* Resolution order:
   *   1. --placeholder-aspect-ratio  → explicit override set by your WIP
   *      (e.g. when the prompt-bar sizing system tells the cell what
   *      shape to be).
   *   2. --batch-cell-ar             → per-batch override.
   *   3. --media-ar                  → the source image's actual aspect.
   *   4. 4 / 3                       → non-square default so loading
   *      tiles don't waste vertical space. */
  aspect-ratio: var(--placeholder-aspect-ratio, var(--batch-cell-ar, var(--media-ar, 4 / 3)));
  overflow: hidden;
  border-radius: 12px;
  background: rgba(12, 13, 16, 0.98);
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.batch-generation-placeholder .batch-plasma-cell > .image-generation-placeholder.plasma-placeholder,
.batch-generation-placeholder .batch-plasma-cell > .batch-plasma-loading-tile {
  width: 100% !important;
  height: 100% !important;
  min-width: 0 !important;
  min-height: 0 !important;
  margin: 0 !important;
}

.batch-generation-placeholder .batch-plasma-cell.pending {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.035);
}

.batch-plasma-loading-tile {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: inherit;
  background:
    radial-gradient(120% 120% at 16% 10%, rgba(255, 255, 255, 0.16), transparent 34%),
    linear-gradient(135deg, rgba(32, 35, 42, 0.96), rgba(14, 15, 20, 0.98));
  isolation: isolate;
}

.batch-plasma-reference-bg {
  position: absolute;
  inset: -12%;
  width: 124%;
  height: 124%;
  object-fit: cover;
  filter: blur(18px) saturate(1.1) brightness(0.8);
  opacity: 0.32;
  transform: scale(1.03);
  pointer-events: none;
  z-index: 0;
}

.batch-plasma-ambient {
  position: absolute;
  inset: -35%;
  background:
    radial-gradient(circle at 20% 18%, rgba(105, 229, 211, 0.3), transparent 28%),
    radial-gradient(circle at 72% 20%, rgba(190, 160, 255, 0.24), transparent 30%),
    radial-gradient(circle at 52% 82%, rgba(255, 202, 117, 0.18), transparent 34%);
  filter: blur(22px) saturate(1.18);
  opacity: 0.72;
  animation: batch-plasma-breathe 3.4s ease-in-out infinite alternate;
  pointer-events: none;
  z-index: 1;
}

.batch-plasma-sheen {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(100deg, transparent 0%, rgba(255, 255, 255, 0.08) 44%, transparent 66%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.07), transparent 42%);
  transform: translateX(-55%);
  animation: batch-plasma-sheen 2.2s ease-in-out infinite;
  pointer-events: none;
  z-index: 2;
}

.batch-plasma-progress {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 12px;
  height: 3px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  overflow: hidden;
  z-index: 3;
}

.batch-plasma-progress-fill {
  display: block;
  width: 38%;
  height: 100%;
  border-radius: inherit;
  background: rgba(255, 255, 255, 0.76);
  animation: batch-plasma-progress 2.4s ease-in-out infinite;
}

.batch-generation-placeholder .batch-plasma-cell.resolved {
  background: transparent;
  border-color: transparent;
}

.batch-generation-placeholder .batch-plasma-cell.failed {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  background: rgba(30, 18, 20, 0.92);
  border-color: rgba(255, 124, 124, 0.2);
}

.batch-plasma-error {
  color: rgba(255, 222, 222, 0.9);
  font: 650 12px/1.25 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  text-align: center;
}

.batch-generation-placeholder .batch-plasma-result-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  animation: batch-plasma-image-in 180ms ease-out both;
}

/* Result grid mirrors the placeholder grid: always 2 columns so each
 * tile reads big. For 3 results the 3rd lands centered on row 2. */
.message.assistant.batch-generation-result .message-content:not(.comparison-content) > .image-grid.batch-generation-grid {
  display: grid !important;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px;
  width: min(640px, 100%) !important;
  max-width: min(640px, 100%) !important;
}

.message.assistant.batch-generation-result .message-content:not(.comparison-content) > .image-grid.batch-generation-grid:has(> .mediabubble-container:nth-child(3):last-child) > .mediabubble-container:nth-child(3) {
  grid-column: 1 / -1;
  justify-self: center;
  width: calc((100% - 4px) / 2);
}

.message.assistant.batch-generation-result .image-grid.batch-generation-grid > .mediabubble-container {
  display: block;
  width: 100% !important;
  height: auto !important;
  min-width: 0;
}

.message.assistant.batch-generation-result .image-grid.batch-generation-grid .chat-img-wrapper {
  display: block;
  width: 100% !important;
  height: auto !important;
  /* Use the real/requested aspect ratio for each tile (set via --media-ar
   * from the media metadata, then corrected from natural dimensions on load),
   * with a 4:3 fallback only when no ratio is known yet. */
  aspect-ratio: var(--media-ar, 4 / 3);
  min-width: 0;
  border-radius: 12px;
  overflow: hidden !important;
}

.message.assistant.batch-generation-result .image-grid.batch-generation-grid .chat-img-wrapper img,
.message.assistant.batch-generation-result .image-grid.batch-generation-grid .chat-img-wrapper video {
  width: 100% !important;
  height: 100% !important;
  object-fit: cover;
  border-radius: inherit;
  cursor: zoom-in;
}

@keyframes batch-plasma-image-in {
  from { opacity: 0; transform: scale(1.015); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes batch-plasma-breathe {
  from { transform: translate3d(-3%, -2%, 0) scale(1); opacity: 0.58; }
  to { transform: translate3d(3%, 2%, 0) scale(1.08); opacity: 0.86; }
}

@keyframes batch-plasma-sheen {
  0% { transform: translateX(-65%); opacity: 0; }
  24% { opacity: 0.9; }
  72% { opacity: 0.28; }
  100% { transform: translateX(65%); opacity: 0; }
}

@keyframes batch-plasma-progress {
  0% { transform: translateX(-55%); width: 32%; }
  50% { width: 58%; }
  100% { transform: translateX(210%); width: 32%; }
}

/* Remove the old forced 300x300 system (it causes inconsistent sizing and capsule mismatch). */

/* Skeleton shimmer + tag for pointcloud/model placeholders */
.chat-img-wrapper.generation-placeholder.model-placeholder::before,
.chat-img-wrapper.generation-placeholder.pointcloud-placeholder::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.04) 0%,
    rgba(255, 255, 255, 0.08) 50%,
    rgba(255, 255, 255, 0.04) 100%
  );
  background-size: 200% 100%;
  animation: chat-skeleton-shimmer 1.1s ease-in-out infinite;
  pointer-events: none;
  z-index: 2; /* overlay above any plasma canvas */
}

.chat-img-wrapper.generation-placeholder.model-placeholder[data-placeholder-tag]::after {
  content: attr(data-placeholder-tag);
  position: absolute;
  top: 10px;
  left: 10px;
  padding: 6px 10px;
  border-radius: 999px;
  background: rgba(10, 12, 18, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: rgba(255, 255, 255, 0.92);
  font: 700 10px/1 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  pointer-events: none;
  z-index: 3;
}

/* Hide plasma canvas only when there is no reference preview */
.chat-img-wrapper.generation-placeholder.model-placeholder:not(.has-reference-preview) canvas,
.chat-img-wrapper.generation-placeholder.pointcloud-placeholder:not(.has-reference-preview) canvas {
  display: none !important;
}

/* With a reference preview, disable skeleton shimmer and reveal shader glow */
.chat-img-wrapper.generation-placeholder.model-placeholder.has-reference-preview::before,
.chat-img-wrapper.generation-placeholder.pointcloud-placeholder.has-reference-preview::before {
  display: none !important;
}

.chat-img-wrapper.generation-placeholder.model-placeholder.has-reference-preview canvas,
.chat-img-wrapper.generation-placeholder.pointcloud-placeholder.has-reference-preview canvas {
  display: block !important;
  opacity: 0.95 !important;
  mix-blend-mode: screen;
}

.chat-img-wrapper.generation-placeholder.model-placeholder.has-reference-preview .plasma-bg,
.chat-img-wrapper.generation-placeholder.pointcloud-placeholder.has-reference-preview .plasma-bg {
  opacity: 0.38;
  filter: blur(20px) saturate(1.38) brightness(1.08);
  transform: scale(1.12);
}

.chat-img-wrapper.generation-placeholder.pointcloud-placeholder.has-reference-preview .plasma-bg,
.image-generation-placeholder.pointcloud-placeholder.has-reference-preview .plasma-bg {
  opacity: 0.48;
  filter: grayscale(0.2) blur(14px) saturate(1.05) brightness(0.96);
}

/* Let chat.css / command_3dmodel.css control 3D model sizing; avoid hard-coded 300px. */

/* Model placeholders: standardized to 300x300 like other Phase 3 placeholders */

.image-generation-placeholder.img-placeholder .spinner-ring,
.image-generation-placeholder.video-placeholder .spinner-ring,
.image-generation-placeholder.pointcloud-placeholder .spinner-ring,
.plasma-placeholder .spinner-ring {
  display: none !important;
}

/* Model placeholders keep their spinner visible */

/* Placeholder message surfaces are governed by chat-contract.css. */

/* Ensure plasma containers are transparent */
.plasma-placeholder,
.plasma-placeholder.image-generation-placeholder {
  background: transparent !important;
  border-radius: 20px !important;
  overflow: hidden !important;
}

/* Phase 3: use dark blue background for placeholder container */
.message.assistant.placeholder-message[data-placeholder-system="phase3"] .plasma-placeholder,
.message.assistant.placeholder-message[data-phase3="true"] .plasma-placeholder {
  background: rgba(0, 0, 45, 0.90) !important; /* dark blue-900 with opacity */
}

/* Blurred glow background image under plasma */
.plasma-placeholder .plasma-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: blur(12px) saturate(1.12) brightness(1.04);
  transform: scale(1.08);
  pointer-events: none;
  z-index: 0;
  opacity: 0.16;
}

/* Stronger color-transfer look when placeholder is based on a reference image */
.chat-img-wrapper.generation-placeholder.has-reference-preview .plasma-bg.reference-preview-bg,
.plasma-placeholder.has-reference-preview .plasma-bg.reference-preview-bg {
  opacity: 0.55;
  filter: blur(18px) saturate(1.3) brightness(1.05);
  transform: scale(1.12);
  z-index: 2;
}

/* Subtle "breathing" of the reference base image under the plasma — a gentle
   sinusoidal (ease-in-out) scale pulse so it doesn't read as a static frame.
   transform-only → GPU-composited. Duration/delay are set per tile via CSS vars
   so sibling plasmas breathe out of sync. Peaks at 1.20 (the user-requested
   ~120%); never dips below 1.10 so the blurred overscan always covers the box. */
@keyframes formasPlasmaBreathe {
  0%, 100% { transform: scale(1.10); }
  50%      { transform: scale(1.20); }
}
.plasma-bg.reference-preview-bg.is-breathing {
  animation: formasPlasmaBreathe var(--breathe-dur, 2.8s) ease-in-out var(--breathe-delay, 0s) infinite;
  transform-origin: 50% 50%;
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .plasma-bg.reference-preview-bg.is-breathing { animation: none; }
}

/* Let the reference preview bleed through the plasma canvas */
.plasma-placeholder.has-reference-preview canvas,
.image-generation-placeholder.plasma-placeholder.has-reference-preview canvas {
  opacity: 0.55 !important;
}

/* Plasma canvas element - ensure it's visible and layered correctly */
.plasma-placeholder canvas,
.image-generation-placeholder.plasma-placeholder canvas {
  position: absolute !important;
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  z-index: 1 !important;
  pointer-events: none !important;
  display: block !important;
  opacity: 1 !important;
  visibility: visible !important;
}

/* ✅ FIX: Ensure plasma container doesn't overflow */
.chat-img-wrapper.plasma-placeholder,
.chat-img-wrapper.generation-placeholder.plasma-placeholder {
  position: relative !important;
  z-index: 0 !important; /* ✨ Keep plasma BELOW other chat elements */
  contain: paint !important; /* ✨ Prevent canvas from breaking out */
}

/* ✅ FIX: Show avatar for placeholder messages */
.message.assistant.placeholder-message .message-avatar {
  opacity: 1 !important;
  visibility: visible !important;
  pointer-events: auto !important;
}


/* Spinner + percent overlay for plasma placeholders */
.plasma-spinner-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 5; /* Above canvas, below other UI */
}
.plasma-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 5;
}
.plasma-spinner {
  position: relative;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  opacity: 0.9;
  background: conic-gradient(rgba(255,255,255,0.9) 0turn, rgba(255,255,255,0.9) 0.75turn, rgba(255,255,255,0) 0.75turn 1turn);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 8px), #000 calc(100% - 8px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 8px), #000 calc(100% - 8px));
  animation: spin360 1s linear infinite;
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.35));
}
.plasma-percent {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-weight: 700;
  font-size: 12px;
  color: #fff;
  letter-spacing: 0.5px;
}

.plasma-status-label {
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 30px;
  z-index: 8;
  color: rgba(255, 255, 255, 0.94);
  font: 700 11px/1.25 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  letter-spacing: 0;
  text-align: center;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55);
  pointer-events: none;
}

.image-generation-placeholder.pointcloud-placeholder .plasma-spinner-overlay {
  opacity: 0.55;
}

/* Hide percentage for video placeholders */
.video-placeholder .plasma-percent,
.image-generation-placeholder:has(.video-placeholder) .plasma-percent {
  display: none !important;
}
@keyframes spin360 { to { transform: rotate(360deg); } }

/* ================= IMAGE PLACEHOLDERS ================= */

/* Basic image placeholders */
.chat-img-placeholder {
  position: absolute;
  inset: 0;
  background: var(--secondary-bg);
  pointer-events: none;
  transition: opacity 0.3s ease;
  z-index: 0;
  border-radius: inherit;
}

.message.assistant .chat-img-placeholder { 
  background: #373737; 
}

.chat-img-wrapper.lazy-load.loaded .chat-img-placeholder { 
  opacity: 0; 
}

.chat-img-placeholder.missing { 
  opacity: 1; 
}

/* Error state placeholders - Amazing plasma when no image */
.chat-img-wrapper.error .chat-img-placeholder {
  opacity: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.8);
  font-size: 0.75rem;
  background: 
    radial-gradient(ellipse at 20% 30%, rgba(255, 0, 150, 0.6) 0%, transparent 50%),
    radial-gradient(ellipse at 80% 70%, rgba(0, 255, 200, 0.5) 0%, transparent 50%),
    radial-gradient(ellipse at 40% 80%, rgba(150, 0, 255, 0.4) 0%, transparent 45%),
    radial-gradient(ellipse at 60% 20%, rgba(255, 150, 0, 0.35) 0%, transparent 45%),
    linear-gradient(135deg, #0a0a0a 0%, #1a0a1a 50%, #0a1a1a 100%);
  position: relative;
  overflow: hidden;
  animation: no-image-plasma-base 5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

.chat-img-wrapper.error .chat-img-placeholder::before {
  content: '';
  position: absolute;
  top: -40%;
  left: -40%;
  width: 180%;
  height: 180%;
  background: 
    radial-gradient(ellipse at 30% 40%, rgba(255, 0, 150, 0.9) 0%, transparent 30%),
    radial-gradient(ellipse at 70% 60%, rgba(0, 255, 200, 0.8) 0%, transparent 30%),
    radial-gradient(ellipse at 50% 20%, rgba(150, 0, 255, 0.7) 0%, transparent 25%),
    radial-gradient(ellipse at 50% 80%, rgba(255, 150, 0, 0.6) 0%, transparent 25%);
  filter: blur(120px) brightness(2.8) saturate(600%) contrast(2.2);
  animation: no-image-intense-plasma 8s cubic-bezier(0.25, 0.46, 0.45, 0.94) infinite;
  pointer-events: none;
  z-index: 1;
  opacity: 0.3;
}

.chat-img-wrapper.error .chat-img-placeholder::after {
  content: '';
  position: absolute;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  background: 
    radial-gradient(ellipse at 25% 75%, rgba(255, 255, 255, 0.5) 0%, transparent 20%),
    radial-gradient(ellipse at 75% 25%, rgba(255, 0, 150, 0.6) 0%, transparent 25%),
    radial-gradient(ellipse at 50% 50%, rgba(0, 255, 200, 0.4) 0%, transparent 30%);
  filter: blur(180px) brightness(3.5) saturate(800%) hue-rotate(0deg);
  animation: no-image-ultra-plasma 12s cubic-bezier(0.68, -0.55, 0.265, 1.55) infinite;
  pointer-events: none;
  z-index: 0;
  opacity: 0.2;
}

/* ================= ENHANCED IMAGE GENERATION PLACEHOLDERS ================= */

/* Enhanced placeholder for image generation */
.image-generation-placeholder {
  position: relative;
  width: 100%;
  height: 100%;
  background: transparent; /* Make background transparent to show plasma */
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.08);
}

/* Model placeholders now use transparent background like video placeholders */
.image-generation-placeholder.model-placeholder {
  background: transparent !important;
}

/* Large screen adjustments for image generation placeholders */
@media (min-width: 1024px) {
  .image-generation-placeholder {
    border-radius: 8px; /* Keep consistent with received images */
  }
}



.image-generation-placeholder .spinner-ring {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
  pointer-events: none;
  z-index: 0;
}

/* 3D model placeholders use the standard white 270-degree spinner - CONSISTENT WITH IMAGE/VIDEO */
.image-generation-placeholder.model-placeholder .spinner-ring {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  opacity: 0.9;
  background: conic-gradient(rgba(255,255,255,0.9) 0turn, rgba(255,255,255,0.9) 0.75turn, rgba(255,255,255,0) 0.75turn 1turn);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 4px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 4px));
  animation: spin360 1s linear infinite;
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.35));
}

.image-generation-placeholder .progress-text {
  position: absolute;
  bottom: 12px;
  left: 12px;
  right: 12px;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.8);
  text-align: center;
  z-index: 10;
  line-height: 1.3;
}

/* Enhanced progress text for 3D model placeholders - CONSISTENT WITH IMAGE/VIDEO */
.image-generation-placeholder.model-placeholder .progress-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, 50px); /* Position below the spinner */
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0.5px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
  text-align: center;
  z-index: 15; /* Above spinner */
}

/* ================= 3D MODEL PLACEHOLDERS ================= */

/* Special styling for 3D model placeholders - Match received image sizing */
.image-generation-placeholder.model-placeholder {
  width: 100%; /* Fill container which is sized by .chat-img-wrapper.generation-placeholder */
  height: 100%;
  min-height: 0;
  border: 1px solid rgba(255, 255, 255, 0.08);
  margin: 0; /* No margin needed, container handles sizing */
  aspect-ratio: 1 / 1; /* 3D models stay square */
}

/* Large screen adjustments for 3D model placeholders */
@media (min-width: 1024px) {
  .image-generation-placeholder.model-placeholder {
    min-height: 0;
  }
}

/* Mobile adjustments for 3D model placeholders */
@media (max-width: 768px) {
  .image-generation-placeholder.model-placeholder {
    min-height: 0;
  }
}

.image-generation-placeholder.model-placeholder .placeholder-preview {
  border-radius: 2px; /* Slightly larger radius for 32x32 image */
  /* Force image to render at 32x32 pixels for 3D models */
  width: 32px;
  height: 32px;
  /* Scale up to fill container */
  transform: translate(-50%, -50%) scale(12.5); /* 32px * 12.5 = 400px for typical container */
  /* Force pixelated rendering */
  image-rendering: pixelated;
  image-rendering: -moz-crisp-edges;
  image-rendering: crisp-edges;
  /* Apply 64px blur */
  filter: blur(64px);
  opacity: 1;
  /* Simple heartbeat */
  animation: simple-heartbeat 3s ease-in-out infinite;
}

/* Responsive scaling for 3D model placeholders */
@media (min-width: 1024px) {
  .image-generation-placeholder.model-placeholder .placeholder-preview {
    transform: translate(-50%, -50%) scale(18.75); /* 32px * 18.75 = 600px for desktop */
  }
}

@media (max-width: 768px) {
  .image-generation-placeholder.model-placeholder .placeholder-preview {
    transform: translate(-50%, -50%) scale(9.375); /* 32px * 9.375 = 300px for mobile */
  }
}



/* ================= CIRCULAR PROGRESS RING FOR 3D MODELS ================= */
/* DEPRECATED: Model placeholders now use plasma effect like video placeholders */

/* Legacy circular progress ring styles - kept for compatibility but not used */
.model-progress-ring {
  display: none !important; /* Hidden since we now use plasma for all placeholders */
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 80px;
  height: 80px;
  z-index: 10;
}

.model-progress-ring svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

.model-progress-ring .progress-bg {
  fill: none;
  stroke: rgba(255, 255, 255, 0.1);
  stroke-width: 2;
}

.model-progress-ring .progress-circle {
  fill: none;
  stroke: #ffffff;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 226.19; /* 2 * π * 36 (radius) */
  stroke-dashoffset: 226.19;
  transition: stroke-dashoffset 0.3s ease;
  filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.3));
  animation: progress-ring-glow 2s ease-in-out infinite alternate;
}

@keyframes progress-ring-glow {
  0% {
    filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.3));
  }
  100% {
    filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.5));
  }
}

/* ================= PLACEHOLDER TEXT ================= */

.placeholder-text {
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.2;
  color: var(--text-secondary);
  text-align: left;
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Enhanced styling for 3D model placeholder text */
.message.assistant .placeholder-message .model-placeholder + .placeholder-text {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
}

.message.assistant.placeholder-message .placeholder-text {
  width: 100%;
  padding: 8px 10px 0;
  box-sizing: border-box;
  text-align: center;
  line-height: 1.4;
}

/* ================= PLACEHOLDER PREVIEW IMAGES ================= */

/* Low-res 32x32 pixel effect for placeholder images */
.placeholder-preview.ultra-lowres {
  /* Force image to render at 32x32 pixels */
  width: 32px !important;
  height: 32px !important;
  /* Scale up to show pixelated effect */
  transform: translate(-50%, -50%) scale(18.75) !important; /* 32px * 18.75 = 600px */
  image-rendering: pixelated;
  image-rendering: -moz-crisp-edges;
  image-rendering: crisp-edges;
  object-fit: cover;
  /* Apply 64px blur */
  filter: blur(64px) !important;
  opacity: 1;
  /* Simple heartbeat */
  animation: simple-heartbeat 3s ease-in-out infinite;
}



/* Only apply blurred preview styles to model placeholders */
.image-generation-placeholder.model-placeholder .placeholder-preview {
  position: absolute;
  top: 50%;
  left: 50%;
  /* Force image to render at 32x32 pixels */
  width: 32px;
  height: 32px;
  /* Scale up to fill container */
  transform: translate(-50%, -50%) scale(12.5); /* 32px * 12.5 = 400px for typical container */
  object-fit: cover;
  /* Force pixelated rendering */
  image-rendering: pixelated;
  image-rendering: -moz-crisp-edges;
  image-rendering: crisp-edges;
  /* Apply 64px blur */
  filter: blur(64px);
  pointer-events: none;
  opacity: 1;
  /* Simple heartbeat */
  animation: simple-heartbeat 3s ease-in-out infinite;
}

/* Responsive scaling for model placeholders only */
@media (min-width: 1024px) {
  .image-generation-placeholder.model-placeholder .placeholder-preview {
    transform: translate(-50%, -50%) scale(18.75); /* 32px * 18.75 = 600px for desktop */
  }
}

@media (max-width: 768px) {
  .image-generation-placeholder.model-placeholder .placeholder-preview {
    transform: translate(-50%, -50%) scale(9.375); /* 32px * 9.375 = 300px for mobile */
  }
}

/* ================= SKELETON PLACEHOLDERS ================= */

.skeleton-placeholder {
  background: rgba(255, 255, 255, 0.04);
  animation: skeleton-loading 2.4s ease-in-out infinite;
  border-radius: 8px;
  position: relative;
  overflow: hidden;
}

.skeleton-placeholder.fade-out {
  animation: skeleton-fade-out 0.3s ease-out forwards;
}

@keyframes skeleton-loading {
  0%, 100% {
    opacity: 0.4;
  }
  50% {
    opacity: 0.7;
  }
}

@keyframes skeleton-fade-out {
  to {
    opacity: 0;
    transform: scale(0.95);
  }
}

/* ================= INPUT PLACEHOLDERS ================= */

/* Message input placeholders */
.message-input::placeholder {
  color: rgba(255, 255, 255, 0.6);
}

.message-input-container.context-mode-active .message-input::placeholder {
  color: rgba(255, 255, 255, 0.5);
  font-style: italic;
}

/* Search input placeholders - see topbar.css for complete styling */
/* .generations-search::placeholder is styled in topbar.css with state transitions */

/* Form input placeholders */
.form-group input::placeholder {
  color: var(--text-placeholder);
  opacity: 0.7;
}

/* ================= ANIMATIONS ================= */

/* Simple, lightweight heartbeat animation */
@keyframes simple-heartbeat {
  0%, 100% {
    opacity: 0.8;
  }
  50% {
    opacity: 1;
  }
}







/* Amazing plasma animations for no-image state */
@keyframes no-image-plasma-base {
  0% {
    background: 
      radial-gradient(ellipse at 20% 30%, rgba(255, 0, 150, 0.6) 0%, transparent 50%),
      radial-gradient(ellipse at 80% 70%, rgba(0, 255, 200, 0.5) 0%, transparent 50%),
      radial-gradient(ellipse at 40% 80%, rgba(150, 0, 255, 0.4) 0%, transparent 45%),
      radial-gradient(ellipse at 60% 20%, rgba(255, 150, 0, 0.35) 0%, transparent 45%),
      linear-gradient(135deg, #0a0a0a 0%, #1a0a1a 50%, #0a1a1a 100%);
    filter: brightness(1.2) saturate(200%) contrast(1.4);
  }
  25% {
    background: 
      radial-gradient(ellipse at 80% 20%, rgba(0, 255, 200, 0.65) 0%, transparent 50%),
      radial-gradient(ellipse at 20% 80%, rgba(150, 0, 255, 0.55) 0%, transparent 50%),
      radial-gradient(ellipse at 70% 30%, rgba(255, 150, 0, 0.45) 0%, transparent 45%),
      radial-gradient(ellipse at 30% 70%, rgba(255, 0, 150, 0.4) 0%, transparent 45%),
      linear-gradient(135deg, #1a0a1a 0%, #0a1a1a 50%, #1a1a0a 100%);
    filter: brightness(1.6) saturate(300%) contrast(1.8);
  }
  50% {
    background: 
      radial-gradient(ellipse at 30% 70%, rgba(150, 0, 255, 0.7) 0%, transparent 50%),
      radial-gradient(ellipse at 70% 30%, rgba(255, 150, 0, 0.6) 0%, transparent 50%),
      radial-gradient(ellipse at 20% 20%, rgba(255, 0, 150, 0.5) 0%, transparent 45%),
      radial-gradient(ellipse at 80% 80%, rgba(0, 255, 200, 0.45) 0%, transparent 45%),
      linear-gradient(135deg, #0a1a1a 0%, #1a1a0a 50%, #1a0a1a 100%);
    filter: brightness(2) saturate(400%) contrast(2.2);
  }
  75% {
    background: 
      radial-gradient(ellipse at 70% 80%, rgba(255, 150, 0, 0.65) 0%, transparent 50%),
      radial-gradient(ellipse at 30% 20%, rgba(255, 0, 150, 0.55) 0%, transparent 50%),
      radial-gradient(ellipse at 80% 40%, rgba(0, 255, 200, 0.45) 0%, transparent 45%),
      radial-gradient(ellipse at 20% 60%, rgba(150, 0, 255, 0.4) 0%, transparent 45%),
      linear-gradient(135deg, #1a1a0a 0%, #1a0a1a 50%, #0a0a0a 100%);
    filter: brightness(1.6) saturate(300%) contrast(1.8);
  }
  100% {
    background: 
      radial-gradient(ellipse at 20% 30%, rgba(255, 0, 150, 0.6) 0%, transparent 50%),
      radial-gradient(ellipse at 80% 70%, rgba(0, 255, 200, 0.5) 0%, transparent 50%),
      radial-gradient(ellipse at 40% 80%, rgba(150, 0, 255, 0.4) 0%, transparent 45%),
      radial-gradient(ellipse at 60% 20%, rgba(255, 150, 0, 0.35) 0%, transparent 45%),
      linear-gradient(135deg, #0a0a0a 0%, #1a0a1a 50%, #0a1a1a 100%);
    filter: brightness(1.2) saturate(200%) contrast(1.4);
  }
}

@keyframes no-image-intense-plasma {
  0% {
    filter: blur(120px) brightness(2.8) saturate(600%) contrast(2.2) hue-rotate(0deg);
    transform: scale(0.8) rotate(0deg);
    opacity: 0.8;
  }
  16% {
    filter: blur(180px) brightness(3.6) saturate(800%) contrast(2.8) hue-rotate(60deg);
    transform: scale(1.3) rotate(60deg);
    opacity: 0.9;
  }
  32% {
    filter: blur(240px) brightness(4.4) saturate(1000%) contrast(3.4) hue-rotate(120deg);
    transform: scale(1.6) rotate(120deg);
    opacity: 0.85;
  }
  48% {
    filter: blur(200px) brightness(3.8) saturate(850%) contrast(3) hue-rotate(180deg);
    transform: scale(1.4) rotate(180deg);
    opacity: 0.9;
  }
  64% {
    filter: blur(260px) brightness(4.6) saturate(1100%) contrast(3.6) hue-rotate(240deg);
    transform: scale(1.7) rotate(240deg);
    opacity: 0.8;
  }
  80% {
    filter: blur(160px) brightness(3.2) saturate(700%) contrast(2.6) hue-rotate(300deg);
    transform: scale(1.2) rotate(300deg);
    opacity: 0.9;
  }
  100% {
    filter: blur(120px) brightness(2.8) saturate(600%) contrast(2.2) hue-rotate(360deg);
    transform: scale(0.8) rotate(360deg);
    opacity: 0.8;
  }
}

@keyframes no-image-ultra-plasma {
  0% {
    filter: blur(180px) brightness(3.5) saturate(800%) hue-rotate(0deg);
    transform: scale(0.6) rotate(0deg);
    opacity: 0.6;
  }
  25% {
    filter: blur(280px) brightness(5) saturate(1200%) hue-rotate(90deg);
    transform: scale(1.8) rotate(-90deg);
    opacity: 0.75;
  }
  50% {
    filter: blur(360px) brightness(6.5) saturate(1500%) hue-rotate(180deg);
    transform: scale(2.2) rotate(-180deg);
    opacity: 0.7;
  }
  75% {
    filter: blur(320px) brightness(5.8) saturate(1300%) hue-rotate(270deg);
    transform: scale(2) rotate(-270deg);
    opacity: 0.75;
  }
  100% {
    filter: blur(180px) brightness(3.5) saturate(800%) hue-rotate(360deg);
    transform: scale(0.6) rotate(-360deg);
    opacity: 0.6;
  }
}


 
 

/* ================= LEGACY COMPATIBILITY ================= */

/* Legacy placeholder styles maintained for compatibility */
.message.assistant .image-generation-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
  /* No max-width here - container handles sizing */
}

/* Large screen adjustments handled by container */

/* ================= MOBILE SIZING ADJUSTMENTS ================= */

/* Mobile placeholder sizing patches */
@media (max-width: 768px) {
  .message.assistant:has(.image-generation-placeholder),
  .message.assistant.placeholder-message {
    max-width: calc(100vw - 40px);
  }
  
  /* Ensure mobile placeholders don't exceed container */
  .message.assistant .image-generation-placeholder,
  .message.assistant .chat-img-wrapper.generation-placeholder {
    max-width: 100%;
  }
}

/* This rule uses the .placeholder-message class to align placeholder width */
.message.assistant.placeholder-message {
  width: auto;
  max-width: 600px;
}

@media (min-width: 1024px) {
  .message.assistant.placeholder-message {
    max-width: 800px;
  }
}
