* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; background: #0c0e14; color: #e7e9f0; font-family: system-ui, "Segoe UI", sans-serif; }

#viewport {
  position: fixed; inset: 0; display: grid; place-items: center; overflow: hidden;
}
/* #stage is sized to the design resolution and scaled with a CSS var (letterbox fit) */
#stage {
  position: relative; transform-origin: top left;
  background: #11131b; box-shadow: 0 0 40px rgba(0,0,0,.6);
}

/* default: keep each asset's aspect ratio (no stretching), centered */
.el { position: absolute; background-size: contain; background-position: center; background-repeat: no-repeat; }
/* containers/frames/full-bleed art are meant to fill their box */
.el.cat-background { z-index: 0; background-size: 100% 100%; }
.el.cat-panel { background-size: 100% 100%; }
.el.cat-decoration { background-size: 100% 100%; }
.el.cat-interactive { cursor: pointer; transition: filter .08s ease, transform .08s ease; }
.el.cat-interactive:hover { filter: brightness(1.15) saturate(1.1); }
.el.cat-interactive:active { filter: brightness(.9); transform: translateY(1px) scale(.99); }
/* when real per-state art exists, swap images instead of faking with filters */
.el.cat-interactive.has-states:hover { filter: none; }
.el.cat-interactive.has-states:active { filter: none; transform: none; }
.el.cat-interactive[data-disabled="1"] { filter: grayscale(1) brightness(.6); cursor: not-allowed; }

.el.cat-value {
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; text-shadow: 0 1px 2px rgba(0,0,0,.9); pointer-events: none;
  line-height: 1.05; overflow: hidden;
}
.el.cat-value.is-bar {
  background: rgba(20,16,30,.55);
  border: 1px solid rgba(255,255,255,.28);
  border-radius: 999px; overflow: hidden; padding: 0;
  box-shadow: inset 0 2px 4px rgba(0,0,0,.45);
  display: block;
}
.el.cat-value.is-bar .bar-fill {
  position: absolute; left: 0; top: 0; height: 100%; width: 50%;
  border-radius: 999px;
  background: linear-gradient(90deg, #43b6ff, #7cf58f);
  box-shadow: 0 0 10px rgba(80,200,255,.55) inset;
  transition: width .45s cubic-bezier(.22,.61,.36,1);
}
.el.cat-value.is-bar .bar-label {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 12px; color: #fff;
  text-shadow: 0 1px 2px rgba(0,0,0,.95); pointer-events: none; white-space: nowrap;
}
.el.cat-text { display: flex; align-items: center; justify-content: center;
  pointer-events: none; font-weight: 600; text-shadow: 0 1px 3px rgba(0,0,0,.9);
  white-space: pre-line; line-height: 1.1; overflow: hidden; text-align: center; }
.el.cat-text.is-longtext { align-items: flex-start; justify-content: flex-start;
  text-align: left; padding: 4px 6px; font-weight: 500; opacity: .92; }

/* dynamic feel: engine-driven, not baked. two mechanisms:
   1) particle layer for category=dynamic areas
   2) pulsing glow (drop-shadow follows alpha) for any element with a dynamic hint */
.el.cat-dynamic { pointer-events: none; }
.fx-layer { position: absolute; inset: 0; overflow: visible; }
.fx { position: absolute; left: 0; top: 0; will-change: transform, opacity; border-radius: 50%; }
.fx.ember { background: radial-gradient(circle, #fff2c4 0%, #ffcf6e 40%, rgba(255,170,60,.5) 60%, transparent 72%);
  box-shadow: 0 0 6px rgba(255,190,90,.8); }
.fx.dot { background: radial-gradient(circle, #d8fbff 0%, rgba(110,230,255,.7) 45%, transparent 72%);
  box-shadow: 0 0 6px rgba(90,220,255,.8); }
.fx.shimmer { filter: blur(5px);
  background: radial-gradient(circle, rgba(120,255,210,.55) 0%, transparent 70%); }
#stage.fx-off .fx-layer { display: none; }

.fx-glow { animation: fxGlow 2.4s ease-in-out infinite; }
.fx-glow.fx-warm { animation-name: fxGlowWarm; }
#stage.fx-off .fx-glow { animation: none !important; }
@keyframes fxGlow {
  0%,100% { filter: drop-shadow(0 0 2px rgba(120,230,255,.35)); }
  50%     { filter: drop-shadow(0 0 12px rgba(120,230,255,.9)); }
}
@keyframes fxGlowWarm {
  0%,100% { filter: drop-shadow(0 0 3px rgba(255,200,110,.4)); }
  50%     { filter: drop-shadow(0 0 14px rgba(255,200,110,.95)); }
}

/* ---- motion: living UI (JS drives transforms; CSS provides sheen/shadow) ---- */
.el.motion { will-change: transform; }
.el.cat-portrait.motion { transform-origin: 50% 100%; }

/* soft breathing ground shadow under a character */
.char-shadow {
  position: absolute; left: 50%; bottom: -6px; width: 62%; height: 12px;
  transform: translateX(-50%); border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0,0,0,.42) 0%, rgba(0,0,0,.18) 55%, transparent 75%);
  pointer-events: none; z-index: -1; will-change: transform, opacity;
}
/* blink frame cross-fades over the idle art; inherits the character's transform */
.blink-layer {
  position: absolute; inset: 0; background-size: contain; background-position: center;
  background-repeat: no-repeat; opacity: 0; transition: opacity .09s linear; pointer-events: none;
}
/* layered 2.5D cut-out rig: base + part layers share one contained canvas */
.rig-canvas { position: absolute; will-change: transform; }
.rig-layer { position: absolute; inset: 0; will-change: transform; backface-visibility: hidden; }
#stage.fx-off .rig-layer { transform: none !important; }
.rig-video { will-change: transform; backface-visibility: hidden; user-select: none; }

/* runtime notification badge (data-driven, not baked into art) */
.el.badge {
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 35% 30%, #ff6b6b 0%, #e53935 70%, #c62828 100%);
  color: #fff; font-weight: 800; line-height: 1; border-radius: 50%;
  border: 2px solid #fff; box-shadow: 0 2px 6px rgba(0,0,0,.4);
  text-shadow: 0 1px 1px rgba(0,0,0,.35); pointer-events: none;
  font-family: system-ui, "Segoe UI", Arial, sans-serif;
}

/* active navigation tab */
.el.nav-tab { transition: transform .16s ease, filter .16s ease; transform-origin: center bottom; }
.el.nav-tab.tab-active { transform: scale(1.14); filter: drop-shadow(0 4px 10px rgba(90,150,255,.55)) brightness(1.06); z-index: 5; }

/* transient action feedback */
.toast {
  position: absolute; left: 50%; bottom: 26px; transform: translateX(-50%) translateY(12px);
  background: rgba(20,18,32,.92); color: #fff; padding: 9px 16px; border-radius: 999px;
  font-size: 14px; font-weight: 600; letter-spacing: .3px; pointer-events: none;
  border: 1px solid rgba(255,255,255,.14); box-shadow: 0 8px 24px rgba(0,0,0,.4);
  opacity: 0; transition: opacity .2s ease, transform .2s ease; z-index: 9999;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

.fx.spark {
  background: radial-gradient(circle, #fffbe6 0%, #ffe38a 45%, rgba(255,205,90,.55) 62%, transparent 74%);
  box-shadow: 0 0 8px rgba(255,225,140,.95);
}

/* moving highlight sweep for filled surfaces (bars, primary buttons).
   NB: do NOT set position:relative here — it would override .el's absolute
   positioning (same specificity, later rule) and drop elements into normal
   flow, stacking bars/buttons and pushing them off their bbox. .el is already
   a positioned containing block for the ::after sweep. */
.fx-sheen { overflow: hidden; }
.fx-sheen::after {
  content: ""; position: absolute; top: 0; left: 0; height: 100%; width: 60%;
  background: linear-gradient(105deg, transparent 0%, rgba(255,255,255,.55) 50%, transparent 100%);
  transform: skewX(-18deg); pointer-events: none; mix-blend-mode: screen;
  animation: sheenSweep 3.4s ease-in-out infinite;
}
.el.cat-value.is-bar.fx-sheen::after { mix-blend-mode: screen; opacity: .85; }
@keyframes sheenSweep {
  0%   { left: -70%; }
  55%  { left: 130%; }
  100% { left: 130%; }
}
#stage.fx-off .fx-sheen::after { animation: none; opacity: 0; }
#stage.fx-off .char-shadow { transform: translateX(-50%) !important; }

/* debug boxes */
#stage.show-boxes .el { outline: 1px solid rgba(255,255,255,.25); }
#stage.show-boxes .el.cat-interactive { outline-color: #ff5050; }
#stage.show-boxes .el.cat-value { outline-color: #ffc828; }
#stage.show-boxes .el.cat-dynamic { outline-color: #b450ff; }

#hud {
  position: fixed; left: 12px; bottom: 12px; display: flex; gap: 16px; align-items: center;
  background: rgba(0,0,0,.55); padding: 8px 14px; border-radius: 10px; font-size: 13px;
  backdrop-filter: blur(6px);
}
#hud label { display: flex; gap: 6px; align-items: center; cursor: pointer; }
#hud-name { font-weight: 700; color: #8fd0ff; }
