/* ─── Shadow Lab — Global Styles ─────────────────────────────────────────────
   Loaded by index.html.  All effect-specific pseudo-element rules and keyframe
   animations live here.  The component JS reads CSS custom properties at
   runtime (e.g. --cast-tilt) which are set inline on the preview element.
   ─────────────────────────────────────────────────────────────────────────── */

/* ── Design tokens ─────────────────────────────────────────────────────────── */
:root {
  color-scheme: dark;
  --app-bg:       #0d1117;
  --app-surface:  rgba(22, 27, 34, 0.88);
  --app-border:   rgba(255, 255, 255, 0.12);
  --app-muted:    #9aa4b2;
  --app-accent:   #ffc857;
  --app-accent-2: #64d2ff;
}

/* ── Base ───────────────────────────────────────────────────────────────────── */
body {
  min-height: 100vh;
  background:
    radial-gradient(circle at 15%  5%,  rgba(100, 210, 255, 0.14), transparent 28rem),
    radial-gradient(circle at 85% 18%,  rgba(255, 200,  87, 0.12), transparent 26rem),
    linear-gradient(180deg, #090d14 0%, var(--app-bg) 100%);
}

/* Disable ligatures in code contexts so individual characters are readable */
code, pre, .font-monospace { font-variant-ligatures: none; }

.text-app-muted   { color: var(--app-muted); }
.text-app-accent  { color: var(--app-accent); }
.navbar-blur      { backdrop-filter: blur(18px); background: rgba(13, 17, 23, 0.82); }

/* ── Cards & glass surfaces ─────────────────────────────────────────────────── */
.hero-panel,
.glass-card {
  background: linear-gradient(180deg, rgba(255,255,255,0.075), rgba(255,255,255,0.035));
  border: 1px solid var(--app-border);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.34);
  border-radius: 1.5rem;
  overflow: hidden;
}

.soft-pill {
  color: #dbe6f2;
  background: rgba(255, 255, 255, 0.075);
  border: 1px solid rgba(255, 255, 255, 0.11);
  border-radius: 999px;
  padding: 0.45rem 0.75rem;
}

.metric-card {
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid rgba(255, 255, 255, 0.105);
  border-radius: 1rem;
  padding: 1rem;
}

/* ── Control layouts ────────────────────────────────────────────────────────── */
.control-grid,
.model-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

@media (max-width: 768px) {
  .control-grid,
  .model-grid { grid-template-columns: 1fr; }
}

.form-control,
.form-select,
.form-range { border-color: rgba(255,255,255,0.14); }

.form-control,
.form-select { background-color: rgba(255,255,255,0.055); }

.mini-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.82rem;
  color: var(--app-muted);
  margin-bottom: 0.35rem;
}

/* ── Preview stage ──────────────────────────────────────────────────────────── */
.preview-stage {
  min-height: 28rem;
  border-radius: 1.35rem;
  border: 1px solid rgba(255,255,255,0.14);
  display: grid;
  place-items: center;
  padding: 2rem;
  overflow: hidden;
  position: relative;
  transition: background 140ms linear;
  isolation: isolate;
}

/* Subtle grid overlay on the preview background */
.preview-stage::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  opacity: 0.42;
  background-image:
    linear-gradient(rgba(255,255,255,0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.06) 1px, transparent 1px);
  background-size: 24px 24px;
  mask-image: radial-gradient(circle at center, black, transparent 78%);
}

.preview-text {
  text-align: center;
  line-height: 0.95;
  max-width: 100%;
  overflow-wrap: anywhere;
  position: relative;
  display: inline-block;
  isolation: isolate;
  user-select: none;
  transition: color 140ms linear, text-shadow 140ms linear, font-size 140ms linear;
}

.preview-text::before,
.preview-text::after { pointer-events: none; }

/* ── Effect-specific CSS classes ────────────────────────────────────────────── */
/*
   These classes are applied to .preview-text by the model when `previewClass`
   is set.  Each class enables a pseudo-element or animation that cannot be
   expressed with inline styles alone.

   To add a new effect that needs a pseudo-element or keyframe, add its class
   rule here and reference the CSS custom properties set inline by model.js.
*/

/* perspective-cast: ground-plane shadow via a perspective-transformed ::before */
.preview-text.effect-perspective-cast::before {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  color: var(--cast-color, rgba(0,0,0,0.72));
  text-shadow: none;
  opacity: var(--cast-opacity, 0.72);
  transform-origin: 50% 100%;
  transform: perspective(var(--cast-perspective, 240px))
             rotateX(var(--cast-tilt, 42deg))
             scale(var(--cast-scale, 0.84))
             translateY(var(--cast-shift, 0.14em));
  z-index: -1;
  filter: blur(var(--cast-blur, 0.5px));
}

/* halftone-fill: dot-screen shadow clipped through text via ::after */
.preview-text.effect-halftone-fill::after {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  color: transparent;
  -webkit-text-fill-color: transparent;
  background-color: var(--halftone-color, #db2777);
  background-image: radial-gradient(
    circle,
    rgba(255,255,255,0.86) 0 var(--halftone-dot, 1px),
    transparent calc(var(--halftone-dot, 1px) + 0.15px)
  );
  background-size: var(--halftone-pitch, 6px) var(--halftone-pitch, 6px);
  -webkit-background-clip: text;
  background-clip: text;
  transform: translate(var(--halftone-x, 0.085em), var(--halftone-y, 0.085em));
  opacity: var(--halftone-opacity, 0.94);
  z-index: -1;
}

/* spectral-tube: animated plasma flicker via CSS animation */
.preview-text.effect-spectral-tube {
  filter: saturate(var(--plasma-saturation, 0.65));
  will-change: filter, color;
  animation: shadow-lab-plasma-flicker steps(100) var(--plasma-interval, 1s) infinite alternate;
}

/* thermal-plume: animated upward heat glow */
.preview-text.effect-thermal-plume {
  animation: shadow-lab-thermal-plume var(--thermal-interval, 0.82s) ease-in-out infinite alternate;
}

/* paper-flexion: letter compression via letter-spacing custom property */
.preview-text.effect-paper-flexion {
  letter-spacing: var(--paper-letter-spacing, -0.05em);
}

/* ── Light vector compass ────────────────────────────────────────────────────── */
.vector-compass {
  width: 8rem;
  height: 8rem;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.15);
  background:
    radial-gradient(circle, rgba(255,255,255,0.07) 0 3px, transparent 4px),
    conic-gradient(
      from -90deg,
      rgba(255,200,87,0.18),
      rgba(100,210,255,0.15),
      rgba(255,255,255,0.06),
      rgba(255,200,87,0.18)
    );
  position: relative;
  flex: 0 0 auto;
}

.vector-needle {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44%;
  height: 2px;
  transform-origin: left center;
  background: var(--app-accent);
  box-shadow: 0 0 12px rgba(255, 200, 87, 0.65);
}

.vector-needle::after {
  content: "";
  position: absolute;
  right: -4px;
  top: -4px;
  border-left: 8px solid var(--app-accent);
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
}

/* ── CSS output codebox ─────────────────────────────────────────────────────── */
.codebox {
  min-height: 20rem;
  white-space: pre-wrap;
  color: #d8e2ef;
  background: #080b10;
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 1rem;
  padding: 1rem;
}

/* ── Preset panel buttons ───────────────────────────────────────────────────── */
.preset-button.active {
  border-color: var(--app-accent) !important;
  box-shadow: 0 0 0 0.18rem rgba(255, 200, 87, 0.12);
}

/* ── Lock buttons ───────────────────────────────────────────────────────────── */
.lock-button {
  width: 2.8rem;
  border-color: rgba(255,255,255,0.18);
}

.lock-button.locked {
  color: #111827;
  background: var(--app-accent);
  border-color: var(--app-accent);
  box-shadow: 0 0 0 0.18rem rgba(255, 200, 87, 0.12);
}

/* ── Parameter chips (audit panel) ─────────────────────────────────────────── */
.parameter-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.055);
  border-radius: 999px;
  padding: 0.32rem 0.55rem;
  font-size: 0.78rem;
  color: #dbe6f2;
}

/* ── Keyframe animations ─────────────────────────────────────────────────────
   Add new keyframe blocks here when creating effects that animate.
   ─────────────────────────────────────────────────────────────────────────── */

/* Used by spectral-tube: random-step saturation and hue-rotation flicker */
@keyframes shadow-lab-plasma-flicker {
  50% {
    color: var(--plasma-flash-color, #ffffff);
    filter: saturate(var(--plasma-flash-saturation, 2.0))
            hue-rotate(var(--plasma-hue-drift, 20deg));
  }
}

/* Used by thermal-plume: oscillating upward heat bloom.
   --thermal-s      : scale factor (plumeHeight / 90) — controls column height
   --thermal-tx     : positive turbulence x offset in px
   --thermal-tx-neg : negative turbulence x offset in px
   All three are set inline by ShadowPreview so the animation responds live. */
@keyframes shadow-lab-thermal-plume {
  0% {
    text-shadow:
      0                             0                                       calc(20px * var(--thermal-s, 1))  #fefcc9,
      10px                          calc(-10px * var(--thermal-s, 1))       calc(30px * var(--thermal-s, 1))  #feec85,
      -20px                         calc(-20px * var(--thermal-s, 1))       calc(40px * var(--thermal-s, 1))  #ffae34,
      var(--thermal-tx, 22px)       calc(-40px * var(--thermal-s, 1))       calc(50px * var(--thermal-s, 1))  #ec760c,
      var(--thermal-tx-neg, -22px)  calc(-60px * var(--thermal-s, 1))       calc(60px * var(--thermal-s, 1))  #cd4606,
      0                             calc(-80px * var(--thermal-s, 1))       calc(70px * var(--thermal-s, 1))  #973716,
      10px                          calc(-90px * var(--thermal-s, 1))       calc(80px * var(--thermal-s, 1))  #451b0e;
  }
  100% {
    text-shadow:
      0                             0                                       calc(20px * var(--thermal-s, 1))  #fefcc9,
      10px                          calc(-10px * var(--thermal-s, 1))       calc(30px * var(--thermal-s, 1))  #fefcc9,
      -20px                         calc(-20px * var(--thermal-s, 1))       calc(40px * var(--thermal-s, 1))  #feec85,
      var(--thermal-tx, 22px)       calc(-42px * var(--thermal-s, 1))       calc(60px * var(--thermal-s, 1))  #ffae34,
      var(--thermal-tx-neg, -22px)  calc(-58px * var(--thermal-s, 1))       calc(50px * var(--thermal-s, 1))  #ec760c,
      0                             calc(-82px * var(--thermal-s, 1))       calc(80px * var(--thermal-s, 1))  #cd4606,
      10px                          calc(-90px * var(--thermal-s, 1))       calc(80px * var(--thermal-s, 1))  #973716;
  }
}
