Skip to content
Luna UI
Lost Fantasy

Fantasy RPG interface pieces from Lost Fantasy: panels, bars, item cases, particles and gradient names.

6 pieces · MIT license

Lost Fantasy

Aria Moonvale

Level 42 · Arcanist

HP 86 / 100
MP 54 / 100
XP 31%
×3
Moon shard
×12
Starlight gem

Shrine blessing

+10% XP · +5% luck · ends in 2h 14m

Quest: The Lantern Road

Light 3 of 5 lanterns before dawn

Use this kit

  1. Copy the kit CSS once. It holds the shared colours and every piece's styles.
  2. Then copy any piece's HTML from its page below.
Markdown for AI agents

Pieces 6

Kit CSS

Shared tokens, then every piece's CSS in kit order. Each piece's HTML is on its own page.

Kit CSS
/* RPG panel */
.tv-rpg-panel {
  box-sizing: border-box;
  padding: 1rem;
  color: #e7e5e4;
  font-family: ui-sans-serif, system-ui, sans-serif;
  position: relative;
  border: 1px solid var(--tv-rpg-panel-frame, #776449);
  border-radius: 2px;
  background: linear-gradient(145deg, #2a2725, #1b1c22 55%, #14161b);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--tv-rpg-panel-rim, #a28a62) 35%, transparent),
    inset 1px 0 0 color-mix(in srgb, var(--tv-rpg-panel-rim, #a28a62) 18%, transparent),
    inset 0 -2px 0 #090b0e,
    0 3px 8px #00000040,
    0 0 14px var(--tv-rpg-panel-glow, transparent);
}

.tv-rpg-panel::after {
  content: "";
  position: absolute;
  inset: 4px;
  border: 1px solid color-mix(in srgb, var(--tv-rpg-panel-rim, #a28a62) 14%, transparent);
  background:
    linear-gradient(135deg, var(--tv-rpg-panel-frame, #776449) 4px, transparent 4px) top left,
    linear-gradient(225deg, var(--tv-rpg-panel-frame, #776449) 4px, transparent 4px) top right,
    linear-gradient(45deg, var(--tv-rpg-panel-frame, #776449) 4px, transparent 4px) bottom left,
    linear-gradient(315deg, var(--tv-rpg-panel-frame, #776449) 4px, transparent 4px) bottom right;
  background-size: 8px 8px;
  background-repeat: no-repeat;
  pointer-events: none;
}

.tv-rpg-panel-title {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 600;
  color: var(--tv-rpg-panel-title, #fde68a);
}

.tv-rpg-panel-subtitle {
  margin: 0.5rem 0 0;
  font-size: 0.75rem;
  line-height: 1rem;
  color: #a8a29e;
}

/* Rarity variants: add one class next to tv-rpg-panel. */
.tv-rpg-panel--common {
  --tv-rpg-panel-frame: #6b7280;
  --tv-rpg-panel-rim: #9ca3af;
  --tv-rpg-panel-title: #e5e7eb;
}

.tv-rpg-panel--uncommon {
  --tv-rpg-panel-frame: #3f7a4a;
  --tv-rpg-panel-rim: #6fbf73;
  --tv-rpg-panel-title: #bbf7d0;
}

.tv-rpg-panel--rare {
  --tv-rpg-panel-frame: #2f5f9e;
  --tv-rpg-panel-rim: #60a5fa;
  --tv-rpg-panel-title: #bfdbfe;
}

.tv-rpg-panel--epic {
  --tv-rpg-panel-frame: #6d3fa0;
  --tv-rpg-panel-rim: #b383ff;
  --tv-rpg-panel-title: #e9d5ff;
}

.tv-rpg-panel--legendary {
  --tv-rpg-panel-frame: #a8661c;
  --tv-rpg-panel-rim: #f59e0b;
  --tv-rpg-panel-title: #fde68a;
  --tv-rpg-panel-glow: #f59e0b40;
}

/* Prismatic panel */
.tv-prismatic-panel {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  box-sizing: border-box;
  display: block;
  background: #020617;
  color: #e2e8f0;
  font-family: ui-sans-serif, system-ui, sans-serif;
  box-shadow: 0 10px 15px -3px #ddd6fe1a, 0 4px 6px -4px #ddd6fe1a;
}

.tv-prismatic-panel-light {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.tv-prismatic-panel-edge,
.tv-prismatic-panel-fill,
.tv-prismatic-panel-tint,
.tv-prismatic-panel-sweep {
  position: absolute;
  inset: 0;
}

/* Prismatic edge: a 2px rim of drifting cyan, violet and amber. */
.tv-prismatic-panel-edge {
  background: linear-gradient(to right, #a5f3fc, #c4b5fd, #fde68a);
  background-size: 300% 100%;
  opacity: 0.75;
  animation: tv-prismatic-panel-drift 12s ease-in-out infinite alternate;
}

.tv-prismatic-panel-fill {
  inset: 2px;
  background: #0f172ae6;
  box-shadow: inset 0 1px 0 #eee6ff33, inset 0 -2px 0 #070a11cc;
}

.tv-prismatic-panel-tint {
  inset: 2px;
  background: linear-gradient(to right, #a5f3fc26, #f5d0fe26, #fde68a26);
  background-size: 240% 100%;
  animation: tv-prismatic-panel-drift 12s ease-in-out infinite alternate;
}

/* A soft band of light that crosses the panel every 8 seconds. */
.tv-prismatic-panel-sweep {
  opacity: 0;
  animation: tv-prismatic-panel-sweep 8s ease-in-out infinite;
}

.tv-prismatic-panel-sweep::before {
  content: "";
  position: absolute;
  top: -1.5rem;
  bottom: -1.5rem;
  left: 25%;
  width: 50%;
  transform: skewX(-12deg);
  background: linear-gradient(to right, #f5d0fe33, #fde68a4d, #a5f3fc33);
  filter: blur(24px);
}

.tv-prismatic-panel-body {
  position: relative;
  padding: 1rem 1.25rem;
}

.tv-prismatic-panel-title {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 600;
  color: #f5f3ff;
}

.tv-prismatic-panel-text {
  margin: 0.25rem 0 0;
  font-size: 0.75rem;
  line-height: 1rem;
  color: #e2e8f0;
}

/* Inner frame with four corner pieces: cyan, violet, fuchsia and amber. */
.tv-prismatic-panel-corners {
  position: absolute;
  inset: 6px;
  border: 1px solid #ddd6fe33;
  pointer-events: none;
  background:
    linear-gradient(135deg, #a5f3fc 3.5px, transparent 3.5px) top left,
    linear-gradient(225deg, #ddd6fe 3.5px, transparent 3.5px) top right,
    linear-gradient(315deg, #f5d0fe 3.5px, transparent 3.5px) bottom right,
    linear-gradient(45deg, #fde68a 3.5px, transparent 3.5px) bottom left;
  background-origin: border-box;
  background-size: 10px 10px;
  background-repeat: no-repeat;
}

@keyframes tv-prismatic-panel-drift {
  from { background-position: 0% 50%; }
  to { background-position: 100% 50%; }
}

@keyframes tv-prismatic-panel-sweep {
  0% { transform: translateX(-100%); opacity: 0; }
  10% { transform: translateX(-100%); opacity: 1; }
  85% { transform: translateX(100%); opacity: 1; }
  100% { transform: translateX(100%); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .tv-prismatic-panel-edge,
  .tv-prismatic-panel-tint {
    animation: none;
  }

  .tv-prismatic-panel-sweep {
    display: none;
  }
}

/* RPG progress bar */
/* Bronze-framed bar. Set the fill width inline; pick a colour with a variant class. */
.tv-rpg-progress-bar {
  --tv-rpg-progress-bar-top: #fde68aa6;
  --tv-rpg-progress-bar-mid: #f59e0b;
  --tv-rpg-progress-bar-bot: #b45309;
  box-sizing: border-box;
  width: 100%;
  padding: 2px;
  border: 1px solid #8a6f3a;
  border-radius: 4px;
  background: linear-gradient(180deg, #4a3520 0%, #2a1a0e 50%, #4a3520 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 200, 130, 0.3),
    inset 0 -1px 0 rgba(0, 0, 0, 0.5),
    0 1px 2px rgba(0, 0, 0, 0.4);
  font-family: ui-sans-serif, system-ui, sans-serif;
}

.tv-rpg-progress-bar-track {
  position: relative;
  height: 18px;
  border-radius: 2px;
  overflow: hidden;
  background: linear-gradient(180deg, #0c0c10 0%, #17171d 100%);
}

.tv-rpg-progress-bar-fill {
  position: absolute;
  inset: 0;
  width: 0;
  border-right: 1px solid rgba(255, 255, 255, 0.35);
  background: linear-gradient(180deg,
    var(--tv-rpg-progress-bar-top, #fde68aa6) 0%,
    var(--tv-rpg-progress-bar-mid, #f59e0b) 30%,
    var(--tv-rpg-progress-bar-bot, #b45309) 100%);
  transition: width 500ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* A slow shimmer across the fill. */
.tv-rpg-progress-bar-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.18) 50%, transparent 100%);
  background-size: 200% 100%;
  animation: tv-rpg-progress-bar-shimmer 5s linear infinite;
  pointer-events: none;
}

.tv-rpg-progress-bar-readout {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: #ffffff;
  text-shadow: 0 0 2px #000000, 0 0 3px rgba(0, 0, 0, 0.9), 0 1px 1px rgba(0, 0, 0, 0.8);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.03em;
  pointer-events: none;
}

/* Health: the blood-red HP bar, on a darker red track. */
.tv-rpg-progress-bar--health {
  --tv-rpg-progress-bar-top: rgba(255, 130, 130, 0.55);
  --tv-rpg-progress-bar-mid: #dc2626;
  --tv-rpg-progress-bar-bot: #500a0a;
}

.tv-rpg-progress-bar--health .tv-rpg-progress-bar-track {
  background: linear-gradient(180deg, #1a0808 0%, #2a0e0e 100%);
}

.tv-rpg-progress-bar--mana {
  --tv-rpg-progress-bar-top: rgba(147, 197, 253, 0.65);
  --tv-rpg-progress-bar-mid: #3b82f6;
  --tv-rpg-progress-bar-bot: #1e3a8a;
}

.tv-rpg-progress-bar--experience {
  --tv-rpg-progress-bar-top: rgba(216, 180, 254, 0.65);
  --tv-rpg-progress-bar-mid: #a855f7;
  --tv-rpg-progress-bar-bot: #581c87;
}

.tv-rpg-progress-bar--stamina {
  --tv-rpg-progress-bar-top: rgba(110, 231, 183, 0.65);
  --tv-rpg-progress-bar-mid: #10b981;
  --tv-rpg-progress-bar-bot: #064e3b;
}

@keyframes tv-rpg-progress-bar-shimmer {
  0% { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .tv-rpg-progress-bar-fill { transition: none; }
  .tv-rpg-progress-bar-fill::after { animation: none; }
}

/* Curio display case */
/* A showcase tile whose case climbs a metal ladder. The frame, finial and
   plinth light are the same at every tier; only the metal and its effects
   change. Set the metal as an RGB triple. */
.tv-curio-case {
  --tv-curio-case-metal: 186, 118, 66;
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  max-width: 10rem;
  aspect-ratio: 1;
  margin: 0 auto;
  padding: 0.875rem 0.5rem 0.625rem;
  overflow: hidden;
  border-radius: 8px;
  background: #18181b;
  color: #e4e4e7;
  font-family: ui-sans-serif, system-ui, sans-serif;
}

.tv-curio-case-aura,
.tv-curio-case-frame,
.tv-curio-case-glass {
  position: absolute;
  pointer-events: none;
}

/* Lit plinth pool under the exhibit. */
.tv-curio-case-aura {
  inset: 0;
  z-index: 0;
}

.tv-curio-case-aura::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(72% 40% at 50% 108%, rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.16), transparent 70%);
}

/* The case rail. */
.tv-curio-case-frame {
  inset: 5px;
  z-index: 1;
  overflow: hidden;
  border: 1px solid rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.42);
  border-radius: 4px;
}

/* The diamond finial straddling the rail's top edge. */
.tv-curio-case::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 50%;
  z-index: 3;
  width: 5px;
  height: 5px;
  border-radius: 1px;
  background: rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.7);
  transform: translateX(-50%) rotate(45deg);
}

.tv-curio-case-glass {
  display: none;
}

.tv-curio-case-count {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 4;
  padding: 0.125rem 0.375rem;
  border-radius: 4px;
  background: #171717b3;
  font-size: 0.6875rem;
  font-weight: 600;
  color: #e4e4e7;
}

.tv-curio-case-exhibit {
  position: relative;
  z-index: 2;
  flex: 1;
  width: 62%;
  min-height: 0;
}

.tv-curio-case-label {
  position: relative;
  z-index: 2;
  max-width: 100%;
  overflow: hidden;
  margin: 0.25rem 0 0;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 0.75rem;
  line-height: 1rem;
  font-weight: 600;
  text-align: center;
}

/* Silvered and up: the full case, with a brighter rail, larger finial and lit plinth. */
.tv-curio-case--silvered { --tv-curio-case-metal: 214, 222, 234; }
.tv-curio-case--gilded { --tv-curio-case-metal: 232, 186, 96; }
.tv-curio-case--jadebound { --tv-curio-case-metal: 88, 204, 150; }
.tv-curio-case--enchanted { --tv-curio-case-metal: 103, 232, 249; }
.tv-curio-case--enshrined { --tv-curio-case-metal: 196, 181, 253; }

.tv-curio-case--silvered::after,
.tv-curio-case--gilded::after,
.tv-curio-case--jadebound::after,
.tv-curio-case--enchanted::after,
.tv-curio-case--enshrined::after {
  width: 7px;
  height: 7px;
  background: rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.95);
}

.tv-curio-case--silvered .tv-curio-case-aura::after,
.tv-curio-case--gilded .tv-curio-case-aura::after,
.tv-curio-case--jadebound .tv-curio-case-aura::after,
.tv-curio-case--enchanted .tv-curio-case-aura::after {
  background: radial-gradient(78% 46% at 50% 106%, rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.28), transparent 70%);
}

.tv-curio-case--silvered .tv-curio-case-frame { border-color: rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.62); }
.tv-curio-case--gilded .tv-curio-case-frame { border-color: rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.7); }

.tv-curio-case--jadebound .tv-curio-case-frame {
  border-color: rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.78);
  box-shadow: 0 0 9px -4px rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.5);
}

.tv-curio-case--enchanted .tv-curio-case-frame {
  border-color: rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.85);
  box-shadow: 0 0 12px -3px rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.6);
}

/* Jadebound and up: light sweeps across the inside of the case. */
.tv-curio-case--jadebound .tv-curio-case-frame::before,
.tv-curio-case--enchanted .tv-curio-case-frame::before,
.tv-curio-case--enshrined .tv-curio-case-frame::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(112deg, transparent 42%, rgba(255, 255, 255, 0.12) 50%, transparent 58%);
  background-size: 260% 100%;
  animation: tv-curio-case-sweep 5.5s ease-in-out infinite;
}

.tv-curio-case--enchanted .tv-curio-case-frame::before {
  background: linear-gradient(112deg, transparent 42%, rgba(255, 245, 215, 0.17) 50%, transparent 58%);
  background-size: 260% 100%;
  animation-duration: 4.6s;
}

/* Enchanted and up: the finial glints just after the sweep passes. */
.tv-curio-case--enchanted::after {
  animation: tv-curio-case-glint 4.6s ease-in-out infinite;
}

/* Enshrined: sealed in a violet void, under glass, with a prismatic sweep. */
.tv-curio-case--enshrined {
  --tv-curio-case-void: 18, 10, 32;
}

.tv-curio-case--enshrined .tv-curio-case-frame {
  border-color: rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.8);
  box-shadow:
    inset 0 0 0 2px rgba(9, 9, 11, 0.8),
    inset 0 0 0 3px rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.28),
    inset 0 0 14px rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.16),
    0 0 14px -3px rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.55);
}

.tv-curio-case--enshrined .tv-curio-case-frame::before {
  background: linear-gradient(112deg, transparent 36%, rgba(240, 171, 252, 0.16) 44%, #fde68a38 50%, rgba(165, 243, 252, 0.16) 56%, transparent 64%);
  background-size: 260% 100%;
  animation-duration: 4s;
}

.tv-curio-case--enshrined::after {
  animation:
    tv-curio-case-glint 4.6s ease-in-out infinite,
    tv-curio-case-prism 6s linear infinite;
}

.tv-curio-case--enshrined .tv-curio-case-aura::after {
  background:
    radial-gradient(84% 48% at 50% 106%, rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.3), transparent 70%),
    radial-gradient(126% 108% at 50% 46%, rgba(var(--tv-curio-case-void, 18, 10, 32), 0.34) 18%, rgba(var(--tv-curio-case-void, 18, 10, 32), 0.94) 100%);
  animation: tv-curio-case-breathe 7s ease-in-out infinite;
}

.tv-curio-case--enshrined .tv-curio-case-glass {
  display: block;
  inset: 0;
  z-index: 5;
  border-radius: 8px;
  background: linear-gradient(128deg, rgba(255, 255, 255, 0.13) 0%, rgba(255, 255, 255, 0.045) 26%, transparent 44%);
}

.tv-curio-case--enshrined .tv-curio-case-glass::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(1px 1px at 22% 30%, rgba(255, 255, 255, 0.75), transparent),
    radial-gradient(1px 1px at 68% 22%, rgba(216, 205, 255, 0.6), transparent),
    radial-gradient(1px 1px at 40% 74%, rgba(255, 255, 255, 0.5), transparent),
    radial-gradient(1px 1px at 82% 62%, rgba(216, 205, 255, 0.55), transparent),
    radial-gradient(1px 1px at 12% 58%, rgba(255, 255, 255, 0.4), transparent);
}

.tv-curio-case--enshrined .tv-curio-case-glass::after {
  content: "";
  position: absolute;
  top: -16%;
  left: -34%;
  width: 48%;
  height: 152%;
  transform: rotate(18deg);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
  animation: tv-curio-case-gleam 6.5s ease-in-out infinite;
}

@keyframes tv-curio-case-sweep {
  0% { background-position: 135% 0; }
  60%, 100% { background-position: -50% 0; }
}

@keyframes tv-curio-case-glint {
  0%, 78%, 100% { box-shadow: 0 0 0 0 rgba(var(--tv-curio-case-metal, 186, 118, 66), 0); }
  86% { box-shadow: 0 0 8px 2px rgba(var(--tv-curio-case-metal, 186, 118, 66), 0.85); }
}

@keyframes tv-curio-case-prism {
  0%, 100% { background: rgba(240, 171, 252, 0.95); }
  33% { background: #fde68af2; }
  66% { background: rgba(165, 243, 252, 0.95); }
}

@keyframes tv-curio-case-breathe {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.88; }
}

@keyframes tv-curio-case-gleam {
  0% { left: -34%; }
  55%, 100% { left: 120%; }
}

/* Keep the frame and the metal; drop every moving part. */
@media (prefers-reduced-motion: reduce) {
  .tv-curio-case::after,
  .tv-curio-case-frame::before,
  .tv-curio-case-aura::after,
  .tv-curio-case-glass::after {
    animation: none;
  }

  .tv-curio-case--enshrined .tv-curio-case-glass::after { left: 62%; }
  .tv-curio-case--enshrined::after { background: rgba(240, 171, 252, 0.95); }
}

/* Ambient particles */
/* A layer of drifting particles behind content. Each bit sets its own inline
   --x, --y, --size, --dur, --delay, --drift, --hue and --rot; variants change
   what the bits are. Longhand animation properties are used on purpose:
   the shorthand cannot take a var() for its duration or delay. */
.tv-ambient-particles {
  --tv-ambient-particles-travel: 15rem;
  position: relative;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 15rem;
  overflow: hidden;
  border-radius: 6px;
  background: radial-gradient(120% 90% at 50% 100%, #2a2140 0%, #14111f 55%, #0b0a12 100%);
  font-family: ui-sans-serif, system-ui, sans-serif;
}

/* Fades every edge so nothing looks cut off at the box. */
.tv-ambient-particles-field {
  position: absolute;
  inset: 0;
  pointer-events: none;
  -webkit-mask-image:
    linear-gradient(to right, transparent 0%, #000000 8%, #000000 92%, transparent 100%),
    linear-gradient(to bottom, transparent 0%, #000000 10%, #000000 90%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent 0%, #000000 8%, #000000 92%, transparent 100%),
    linear-gradient(to bottom, transparent 0%, #000000 10%, #000000 90%, transparent 100%);
  mask-composite: intersect;
}

.tv-ambient-particles-label {
  position: relative;
  margin: 0;
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: #f5f3ff;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.6);
}

/* Motes (default): soft violet dots rising and fading. */
.tv-ambient-particles-bit {
  position: absolute;
  bottom: -10px;
  left: var(--x, 50%);
  width: var(--size, 4px);
  height: var(--size, 4px);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(196, 181, 253, 0.9) 0%, transparent 70%);
  filter: blur(0.5px);
  opacity: 0;
  animation-name: tv-ambient-particles-rise;
  animation-duration: var(--dur, 8s);
  animation-delay: var(--delay, 0s);
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

/* Fireflies: glowing points hovering in place, each in its own hue. */
.tv-ambient-particles--fireflies .tv-ambient-particles-bit {
  top: var(--y, 50%);
  bottom: auto;
  background: hsla(var(--hue, 52), 95%, 85%, 1);
  filter: none;
  box-shadow:
    0 0 8px 3px hsla(var(--hue, 52), 95%, 75%, 0.85),
    0 0 22px 8px hsla(var(--hue, 52), 95%, 62%, 0.45),
    0 0 40px 14px hsla(var(--hue, 52), 95%, 52%, 0.2);
  mix-blend-mode: screen;
  animation-name: tv-ambient-particles-hover;
  animation-timing-function: ease-in-out;
}

/* Petals: blossoms falling with a sway and a slow spin. */
.tv-ambient-particles--petals .tv-ambient-particles-bit {
  top: -20px;
  bottom: auto;
  width: calc(var(--size, 4px) * 2);
  height: calc(var(--size, 4px) * 2.8);
  border-radius: 50% 0 50% 0;
  background: radial-gradient(circle at 30% 30%, rgba(255, 240, 245, 0.95) 0%, rgba(244, 180, 200, 0.9) 55%, rgba(220, 140, 170, 0.7) 100%);
  filter: drop-shadow(0 0 2px rgba(255, 200, 220, 0.35));
  animation-name: tv-ambient-particles-fall;
  animation-duration: calc(var(--dur, 8s) * 1.5);
}

/* Embers: bright sparks rising fast off an unseen fire glowing at the bottom. */
.tv-ambient-particles--embers .tv-ambient-particles-field::after {
  content: "";
  position: absolute;
  right: 12%;
  bottom: -18%;
  left: 12%;
  height: 45%;
  background: radial-gradient(ellipse at 50% 100%, rgba(255, 140, 50, 0.32), transparent 70%);
  filter: blur(10px);
}

.tv-ambient-particles--embers .tv-ambient-particles-bit {
  bottom: 4px;
  background: radial-gradient(circle, rgba(255, 190, 90, 1) 0%, rgba(255, 140, 50, 0.9) 45%, transparent 75%);
  box-shadow: 0 0 6px 1px rgba(255, 140, 50, 0.9);
  mix-blend-mode: screen;
  animation-duration: calc(var(--dur, 8s) * 0.55);
  animation-timing-function: ease-out;
}

/* Rain: thin slanted streaks. */
.tv-ambient-particles--rain .tv-ambient-particles-bit {
  top: -40px;
  bottom: auto;
  width: 1px;
  height: calc(var(--size, 4px) * 4);
  border-radius: 0;
  background: linear-gradient(to bottom, transparent 0%, rgba(180, 200, 230, 0.85) 60%, rgba(180, 200, 230, 0.85) 100%);
  filter: blur(0.3px);
  animation-name: tv-ambient-particles-rain;
  animation-duration: calc(var(--dur, 8s) * 0.12);
}

@keyframes tv-ambient-particles-rise {
  0% { transform: translate(0, 0) scale(0.6); opacity: 0; }
  10% { opacity: 0.9; }
  50% { transform: translate(calc(var(--drift, 10px) * 0.5), calc(var(--tv-ambient-particles-travel, 15rem) * -0.5)) scale(1); }
  85% { opacity: 0.9; }
  100% { transform: translate(var(--drift, 10px), calc(var(--tv-ambient-particles-travel, 15rem) * -1)) scale(0.4); opacity: 0; }
}

@keyframes tv-ambient-particles-hover {
  0% { transform: translate(0, 0) scale(0.7); opacity: 0; }
  10% { transform: translate(-6px, -6px) scale(1); opacity: 1; }
  30% { transform: translate(6px, -10px) scale(1.1); opacity: 0.9; }
  55% { transform: translate(8px, 4px) scale(1); opacity: 1; }
  80% { transform: translate(-4px, 6px) scale(0.95); opacity: 0.8; }
  100% { transform: translate(0, 0) scale(0.7); opacity: 0; }
}

@keyframes tv-ambient-particles-fall {
  0% { transform: translate(0, 0) rotate(var(--rot, 0deg)); opacity: 0; }
  6% { opacity: 0.95; }
  25% { transform: translate(var(--drift, 10px), calc(var(--tv-ambient-particles-travel, 15rem) * 0.27)) rotate(calc(var(--rot, 0deg) + 90deg)); }
  50% { transform: translate(calc(var(--drift, 10px) * -0.85), calc(var(--tv-ambient-particles-travel, 15rem) * 0.55)) rotate(calc(var(--rot, 0deg) + 180deg)); }
  75% { transform: translate(calc(var(--drift, 10px) * 0.9), calc(var(--tv-ambient-particles-travel, 15rem) * 0.83)) rotate(calc(var(--rot, 0deg) + 270deg)); opacity: 0.85; }
  100% { transform: translate(calc(var(--drift, 10px) * -0.4), calc(var(--tv-ambient-particles-travel, 15rem) * 1.1)) rotate(calc(var(--rot, 0deg) + 360deg)); opacity: 0; }
}

@keyframes tv-ambient-particles-rain {
  0% { transform: translate(0, 0) rotate(10deg); opacity: 0; }
  8% { opacity: 0.9; }
  90% { opacity: 0.85; }
  100% { transform: translate(-3rem, calc(var(--tv-ambient-particles-travel, 15rem) * 1.25)) rotate(10deg); opacity: 0; }
}

/* Still: hold every particle at a visible resting point instead of hiding it. */
@media (prefers-reduced-motion: reduce) {
  .tv-ambient-particles-bit {
    animation: none;
    opacity: 0.7;
    bottom: auto;
    top: var(--y, 50%);
  }
}

/* Gradient text */
.tv-gradient-text {
  font-family: ui-sans-serif, system-ui, sans-serif;
  font-size: 2.25rem;
  line-height: 2.5rem;
  background-image: linear-gradient(
    var(--tv-gradient-text-angle, 90deg),
    var(--tv-gradient-text-stops, #fdba74 0%, #f97316 50%, #dc2626 100%)
  );
  background-size: var(--tv-gradient-text-spread, 100%) 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: var(--tv-gradient-text-weight, 700);
  filter: drop-shadow(0 0 var(--tv-gradient-text-glow-blur, 0px) var(--tv-gradient-text-glow-color, transparent));
  animation: var(--tv-gradient-text-motion, none), var(--tv-gradient-text-pulse, none);
}

@keyframes tv-gradient-text-slide {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}

@keyframes tv-gradient-text-sweep {
  to { background-position: var(--tv-gradient-text-spread, 100%) 50%; }
}

@keyframes tv-gradient-text-soft {
  0%, 100% { filter: drop-shadow(0 0 var(--tv-gradient-text-glow-blur, 4px) var(--tv-gradient-text-glow-color, #ffffff66)); }
  50% { filter: drop-shadow(0 0 calc(var(--tv-gradient-text-glow-blur, 4px) * 2) var(--tv-gradient-text-glow-color, #ffffff66)); }
}

@keyframes tv-gradient-text-flicker {
  0%, 100% { filter: drop-shadow(0 0 var(--tv-gradient-text-glow-blur, 4px) var(--tv-gradient-text-glow-color, #ef44448c)); }
  45% { filter: drop-shadow(0 0 calc(var(--tv-gradient-text-glow-blur, 4px) * 1.75) var(--tv-gradient-text-glow-color, #ef44448c)); }
  70% { filter: drop-shadow(0 0 calc(var(--tv-gradient-text-glow-blur, 4px) * 0.75) var(--tv-gradient-text-glow-color, #ef44448c)); }
}

@media (prefers-reduced-motion: reduce) {
  .tv-gradient-text { animation: none; }
}
Preview scene HTML and CSS
Preview scene HTML and CSS
<div class="tv-lost-fantasy-scene">
  <div class="tv-ambient-particles tv-ambient-particles--fireflies">
    <div class="tv-ambient-particles-field" aria-hidden="true">
      <span class="tv-ambient-particles-bit" style="--x: 3.1%; --y: 24.3%; --size: 3px; --dur: 7.3s; --delay: -3.9s; --drift: 28px; --hue: 48; --rot: 259deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 8.0%; --y: 69.8%; --size: 5px; --dur: 7.3s; --delay: -0.7s; --drift: 11px; --hue: 300; --rot: 63deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 17.1%; --y: 56.9%; --size: 6px; --dur: 10.8s; --delay: -6.2s; --drift: 11px; --hue: 52; --rot: 23deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 23.7%; --y: 12.8%; --size: 4px; --dur: 8.5s; --delay: -4.7s; --drift: -28px; --hue: 48; --rot: 316deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 37.9%; --y: 81.5%; --size: 4px; --dur: 7.3s; --delay: -2.2s; --drift: 20px; --hue: 330; --rot: 229deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 45.0%; --y: 39.4%; --size: 6px; --dur: 9.3s; --delay: -8.1s; --drift: 20px; --hue: 160; --rot: 179deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 55.9%; --y: 63.7%; --size: 4px; --dur: 9.6s; --delay: -9.5s; --drift: 19px; --hue: 52; --rot: 197deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 65.5%; --y: 17.6%; --size: 5px; --dur: 8.4s; --delay: -5.1s; --drift: 11px; --hue: 48; --rot: 147deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 73.2%; --y: 83.3%; --size: 5px; --dur: 10.5s; --delay: -2.9s; --drift: 21px; --hue: 300; --rot: 194deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 84.0%; --y: 44.3%; --size: 5px; --dur: 9.1s; --delay: -5.5s; --drift: 14px; --hue: 52; --rot: 263deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 92.8%; --y: 18.5%; --size: 3px; --dur: 8.8s; --delay: -7.7s; --drift: 22px; --hue: 160; --rot: 201deg"></span>
      <span class="tv-ambient-particles-bit" style="--x: 96.0%; --y: 77.1%; --size: 3px; --dur: 7.8s; --delay: -7.7s; --drift: 15px; --hue: 48; --rot: 174deg"></span>
    </div>
  </div>
  <div class="tv-lost-fantasy-scene-title">
    <span class="tv-gradient-text" style="--tv-gradient-text-stops: #F59E0B 0%, #FDE68A 35%, #FFFBEB 50%, #FDE68A 65%, #F59E0B 100%; --tv-gradient-text-angle: 90deg; --tv-gradient-text-weight: 700; --tv-gradient-text-spread: 250%; --tv-gradient-text-glow-color: #FBBF24A6; --tv-gradient-text-glow-blur: 6px; --tv-gradient-text-motion: tv-gradient-text-slide 5s ease-in-out infinite;">Lost Fantasy</span>
  </div>
  <div class="tv-lost-fantasy-scene-grid">
    <div class="tv-lost-fantasy-scene-column">
      <div class="tv-rpg-panel tv-rpg-panel--legendary">
        <h3 class="tv-rpg-panel-title">Aria Moonvale</h3>
        <p class="tv-rpg-panel-subtitle">Level 42 · Arcanist</p>
      </div>
      <div class="tv-rpg-progress-bar tv-rpg-progress-bar--health" role="progressbar" aria-label="Health" aria-valuemin="0" aria-valuemax="100" aria-valuenow="86">
        <div class="tv-rpg-progress-bar-track">
          <div class="tv-rpg-progress-bar-fill" style="width: 86%"></div>
          <span class="tv-rpg-progress-bar-readout">HP 86 / 100</span>
        </div>
      </div>
      <div class="tv-rpg-progress-bar tv-rpg-progress-bar--mana" role="progressbar" aria-label="Mana" aria-valuemin="0" aria-valuemax="100" aria-valuenow="54">
        <div class="tv-rpg-progress-bar-track">
          <div class="tv-rpg-progress-bar-fill" style="width: 54%"></div>
          <span class="tv-rpg-progress-bar-readout">MP 54 / 100</span>
        </div>
      </div>
      <div class="tv-rpg-progress-bar tv-rpg-progress-bar--experience" role="progressbar" aria-label="Experience" aria-valuemin="0" aria-valuemax="100" aria-valuenow="31">
        <div class="tv-rpg-progress-bar-track">
          <div class="tv-rpg-progress-bar-fill" style="width: 31%"></div>
          <span class="tv-rpg-progress-bar-readout">XP 31%</span>
        </div>
      </div>
    </div>
    <div class="tv-lost-fantasy-scene-curios">
      <figure class="tv-curio-case tv-curio-case--silvered">
        <span class="tv-curio-case-aura" aria-hidden="true"></span>
        <span class="tv-curio-case-frame" aria-hidden="true"></span>
        <span class="tv-curio-case-glass" aria-hidden="true"></span>
        <span class="tv-curio-case-count">×3</span>
        <svg class="tv-curio-case-exhibit" viewBox="0 0 64 64" aria-hidden="true">
          <path d="M20 14h24l10 12-22 28-22-28z" fill="#818cf8" />
          <path d="M10 26h44L32 54z" fill="#6366f1" />
          <path d="M26 26h12L32 54z" fill="#a5b4fc" />
          <path d="M20 14l6 12h12l6-12z" fill="#c7d2fe" />
          <path d="M20 14 10 26h16zM44 14l10 12H38z" fill="#a5b4fc" />
        </svg>
        <figcaption class="tv-curio-case-label">Moon shard</figcaption>
      </figure>
      <figure class="tv-curio-case tv-curio-case--enchanted">
        <span class="tv-curio-case-aura" aria-hidden="true"></span>
        <span class="tv-curio-case-frame" aria-hidden="true"></span>
        <span class="tv-curio-case-glass" aria-hidden="true"></span>
        <span class="tv-curio-case-count">×12</span>
        <svg class="tv-curio-case-exhibit" viewBox="0 0 64 64" aria-hidden="true">
          <path d="M20 14h24l10 12-22 28-22-28z" fill="#818cf8" />
          <path d="M10 26h44L32 54z" fill="#6366f1" />
          <path d="M26 26h12L32 54z" fill="#a5b4fc" />
          <path d="M20 14l6 12h12l6-12z" fill="#c7d2fe" />
          <path d="M20 14 10 26h16zM44 14l10 12H38z" fill="#a5b4fc" />
        </svg>
        <figcaption class="tv-curio-case-label">Starlight gem</figcaption>
      </figure>
    </div>
    <div class="tv-lost-fantasy-scene-column">
      <div class="tv-prismatic-panel">
        <span class="tv-prismatic-panel-light" aria-hidden="true">
          <span class="tv-prismatic-panel-edge"></span>
          <span class="tv-prismatic-panel-fill"></span>
          <span class="tv-prismatic-panel-tint"></span>
          <span class="tv-prismatic-panel-sweep"></span>
        </span>
        <div class="tv-prismatic-panel-body">
          <h3 class="tv-prismatic-panel-title">Shrine blessing</h3>
          <p class="tv-prismatic-panel-text">+10% XP · +5% luck · ends in 2h 14m</p>
        </div>
        <span class="tv-prismatic-panel-corners" aria-hidden="true"></span>
      </div>
      <div class="tv-rpg-panel tv-rpg-panel--rare">
        <h3 class="tv-rpg-panel-title">Quest: The Lantern Road</h3>
        <p class="tv-rpg-panel-subtitle">Light 3 of 5 lanterns before dawn</p>
      </div>
    </div>
  </div>
</div>


<style>
/* A night scene: fireflies behind a gilded title, a character sheet, two curio cases and a blessing. Stacks when its container is narrow. */
.tv-lost-fantasy-scene {
  position: relative;
  isolation: isolate;
  padding: 28px 24px 30px;
  overflow: hidden;
  background: #0b0a12;
}

/* The particle layer stretches behind the whole scene. */
.tv-lost-fantasy-scene > .tv-ambient-particles {
  position: absolute;
  inset: 0;
  z-index: -1;
  height: auto;
  border-radius: 0;
}

.tv-lost-fantasy-scene-title {
  margin-bottom: 22px;
  text-align: center;
}

.tv-lost-fantasy-scene-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr) minmax(0, 1fr);
  gap: 22px;
  align-items: start;
}

.tv-lost-fantasy-scene-column {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  min-width: 0;
}

.tv-lost-fantasy-scene-curios {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

@container (max-width: 760px) {
  .tv-lost-fantasy-scene-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
</style>